From fe50fa1d5098b7030aa372a4cc8481b0eb12907d Mon Sep 17 00:00:00 2001 From: Git User Date: Fri, 24 May 2019 11:16:06 -0700 Subject: [PATCH 001/790] Initial empty repository From 9be583aa80c56e9e4cd3ce7fef45850cfbb565df Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 24 May 2019 15:25:31 -0700 Subject: [PATCH 002/790] Camera: Add makefile support for camera drivers This change adds dummy Makefile support to compile camera driver project along with base kernel. Change-Id: I237ba87442c17869b7cc264371c5c3996f43eb95 Signed-off-by: Jigarkumar Zala --- Makefile | 4 ++++ camera_stub.c | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 Makefile create mode 100644 camera_stub.c diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..b5ddf0094c84 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y := -Wno-unused-function +obj-y := camera_stub.o diff --git a/camera_stub.c b/camera_stub.c new file mode 100644 index 000000000000..e2e808c53e5d --- /dev/null +++ b/camera_stub.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +static void _camera_techpack_stub(void) +{ +} From 05349feaa2032c614aae119891b850ef5aa1f49b Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 24 May 2019 17:56:58 -0700 Subject: [PATCH 003/790] Camera: Bring over camera driver changes Bring over camera driver changes as of msm-4.19 commit 5a5551a7 (Merge "msm: camera: reqmgr: Fix CRM shift one req issue"). Change-Id: Ic0c2b2d74d1b3470c1c51d98228e312fb13c501a Signed-off-by: Jigarkumar Zala --- Makefile | 23 +- camera_stub.c | 8 - config/konacamera.conf | 1 + config/konacameraconf.h | 8 + drivers/Makefile | 13 + drivers/cam_cdm/Makefile | 12 + drivers/cam_cdm/cam_cdm.h | 253 + drivers/cam_cdm/cam_cdm_core_common.c | 587 ++ drivers/cam_cdm/cam_cdm_core_common.h | 45 + drivers/cam_cdm/cam_cdm_hw_core.c | 1135 +++ drivers/cam_cdm/cam_cdm_intf.c | 573 ++ drivers/cam_cdm/cam_cdm_intf_api.h | 202 + drivers/cam_cdm/cam_cdm_soc.c | 199 + drivers/cam_cdm/cam_cdm_soc.h | 21 + drivers/cam_cdm/cam_cdm_util.c | 717 ++ drivers/cam_cdm/cam_cdm_util.h | 161 + drivers/cam_cdm/cam_cdm_virtual.h | 18 + drivers/cam_cdm/cam_cdm_virtual_core.c | 382 + drivers/cam_cdm/cam_hw_cdm170_reg.h | 135 + drivers/cam_core/Makefile | 10 + drivers/cam_core/cam_context.c | 586 ++ drivers/cam_core/cam_context.h | 460 ++ drivers/cam_core/cam_context_utils.c | 1018 +++ drivers/cam_core/cam_context_utils.h | 33 + drivers/cam_core/cam_hw.h | 46 + drivers/cam_core/cam_hw_intf.h | 80 + drivers/cam_core/cam_hw_mgr_intf.h | 338 + drivers/cam_core/cam_node.c | 836 +++ drivers/cam_core/cam_node.h | 104 + drivers/cam_core/cam_subdev.c | 154 + drivers/cam_cpas/Makefile | 14 + drivers/cam_cpas/cam_cpas_hw.c | 1857 +++++ drivers/cam_cpas/cam_cpas_hw.h | 212 + drivers/cam_cpas/cam_cpas_hw_intf.h | 128 + drivers/cam_cpas/cam_cpas_intf.c | 725 ++ drivers/cam_cpas/cam_cpas_soc.c | 614 ++ drivers/cam_cpas/cam_cpas_soc.h | 123 + drivers/cam_cpas/camss_top/Makefile | 9 + drivers/cam_cpas/camss_top/cam_camsstop_hw.c | 82 + drivers/cam_cpas/cpas_top/Makefile | 9 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 635 ++ drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 268 + drivers/cam_cpas/cpas_top/cpastop100.h | 531 ++ drivers/cam_cpas/cpas_top/cpastop_v150_100.h | 530 ++ drivers/cam_cpas/cpas_top/cpastop_v170_110.h | 538 ++ drivers/cam_cpas/cpas_top/cpastop_v175_100.h | 558 ++ drivers/cam_cpas/cpas_top/cpastop_v175_101.h | 558 ++ drivers/cam_cpas/cpas_top/cpastop_v175_120.h | 760 ++ drivers/cam_cpas/cpas_top/cpastop_v175_130.h | 760 ++ drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 743 ++ drivers/cam_cpas/include/cam_cpas_api.h | 543 ++ drivers/cam_fd/Makefile | 17 + drivers/cam_fd/cam_fd_context.c | 249 + drivers/cam_fd/cam_fd_context.h | 30 + drivers/cam_fd/cam_fd_dev.c | 207 + drivers/cam_fd/fd_hw_mgr/Makefile | 17 + drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 1949 +++++ drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h | 179 + drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr_intf.h | 18 + drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile | 16 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c | 1164 +++ .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h | 237 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c | 235 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h | 282 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c | 295 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.h | 46 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h | 63 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h | 63 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v600.h | 61 + drivers/cam_icp/Makefile | 17 + drivers/cam_icp/cam_icp_context.c | 271 + drivers/cam_icp/cam_icp_context.h | 42 + drivers/cam_icp/cam_icp_subdev.c | 275 + drivers/cam_icp/fw_inc/hfi_intf.h | 168 + drivers/cam_icp/fw_inc/hfi_reg.h | 336 + drivers/cam_icp/fw_inc/hfi_session_defs.h | 564 ++ drivers/cam_icp/fw_inc/hfi_sys_defs.h | 540 ++ drivers/cam_icp/hfi.c | 942 +++ drivers/cam_icp/icp_hw/Makefile | 12 + drivers/cam_icp/icp_hw/a5_hw/Makefile | 14 + drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 518 ++ drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 81 + drivers/cam_icp/icp_hw/a5_hw/a5_dev.c | 228 + drivers/cam_icp/icp_hw/a5_hw/a5_soc.c | 191 + drivers/cam_icp/icp_hw/a5_hw/a5_soc.h | 36 + drivers/cam_icp/icp_hw/bps_hw/Makefile | 14 + drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 416 ++ drivers/cam_icp/icp_hw/bps_hw/bps_core.h | 39 + drivers/cam_icp/icp_hw/bps_hw/bps_dev.c | 207 + drivers/cam_icp/icp_hw/bps_hw/bps_soc.c | 162 + drivers/cam_icp/icp_hw/bps_hw/bps_soc.h | 26 + drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile | 19 + .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 5582 +++++++++++++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 397 ++ .../icp_hw_mgr/include/cam_a5_hw_intf.h | 74 + .../icp_hw_mgr/include/cam_bps_hw_intf.h | 37 + .../icp_hw_mgr/include/cam_icp_hw_intf.h | 33 + .../icp_hw_mgr/include/cam_ipe_hw_intf.h | 37 + .../icp_hw/include/cam_icp_hw_mgr_intf.h | 47 + drivers/cam_icp/icp_hw/ipe_hw/Makefile | 14 + drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 410 ++ drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h | 39 + drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c | 199 + drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c | 165 + drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h | 26 + drivers/cam_isp/Makefile | 13 + drivers/cam_isp/cam_isp_context.c | 3937 +++++++++++ drivers/cam_isp/cam_isp_context.h | 224 + drivers/cam_isp/cam_isp_dev.c | 197 + drivers/cam_isp/cam_isp_dev.h | 31 + drivers/cam_isp/isp_hw_mgr/Makefile | 17 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 6280 +++++++++++++++++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 217 + drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c | 28 + drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h | 67 + drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile | 15 + .../hw_utils/cam_isp_packet_parser.c | 916 +++ .../isp_hw_mgr/hw_utils/cam_tasklet_util.c | 327 + .../hw_utils/include/cam_isp_packet_parser.h | 157 + .../hw_utils/include/cam_tasklet_util.h | 116 + .../hw_utils/irq_controller/Makefile | 5 + .../irq_controller/cam_irq_controller.c | 730 ++ .../irq_controller/cam_irq_controller.h | 272 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 256 + drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile | 4 + .../isp_hw_mgr/isp_hw/ife_csid_hw/Makefile | 14 + .../isp_hw/ife_csid_hw/cam_ife_csid170.h | 305 + .../isp_hw/ife_csid_hw/cam_ife_csid175.h | 346 + .../isp_hw/ife_csid_hw/cam_ife_csid175_200.h | 362 + .../isp_hw/ife_csid_hw/cam_ife_csid17x.c | 86 + .../isp_hw/ife_csid_hw/cam_ife_csid480.h | 379 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3704 ++++++++++ .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 513 ++ .../isp_hw/ife_csid_hw/cam_ife_csid_dev.c | 140 + .../isp_hw/ife_csid_hw/cam_ife_csid_dev.h | 16 + .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c | 58 + .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h | 315 + .../isp_hw/ife_csid_hw/cam_ife_csid_soc.c | 237 + .../isp_hw/ife_csid_hw/cam_ife_csid_soc.h | 119 + .../isp_hw/include/cam_ife_csid_hw_intf.h | 222 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 250 + .../isp_hw/include/cam_vfe_hw_intf.h | 370 + .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile | 16 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 748 ++ .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h | 91 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c | 197 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h | 35 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 347 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h | 117 + .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile | 17 + .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c | 74 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 843 +++ .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 1013 +++ .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1121 +++ .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1360 ++++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 329 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 400 ++ .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile | 16 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c | 79 + .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c | 1221 ++++ .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h | 128 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver1.h | 113 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 3781 ++++++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 227 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 3924 ++++++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 223 + .../vfe_hw/vfe_bus/include/cam_vfe_bus.h | 98 + .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile | 18 + .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c | 556 ++ .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.h | 58 + .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 1145 +++ .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h | 66 + .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 881 +++ .../vfe_hw/vfe_top/cam_vfe_camif_ver2.h | 87 + .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 1299 ++++ .../vfe_hw/vfe_top/cam_vfe_camif_ver3.h | 81 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c | 615 ++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h | 87 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 526 ++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h | 55 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top.c | 55 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 1059 +++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h | 64 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 1101 +++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h | 85 + .../vfe_hw/vfe_top/include/cam_vfe_top.h | 50 + drivers/cam_jpeg/Makefile | 14 + drivers/cam_jpeg/cam_jpeg_context.c | 202 + drivers/cam_jpeg/cam_jpeg_context.h | 67 + drivers/cam_jpeg/cam_jpeg_dev.c | 201 + drivers/cam_jpeg/cam_jpeg_dev.h | 32 + drivers/cam_jpeg/jpeg_hw/Makefile | 15 + drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 1602 +++++ drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 155 + .../jpeg_hw/include/cam_jpeg_hw_intf.h | 37 + .../jpeg_hw/include/cam_jpeg_hw_mgr_intf.h | 16 + drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile | 13 + .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 197 + .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 44 + .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 233 + .../jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c | 55 + .../jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h | 18 + drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile | 13 + .../cam_jpeg_enc_hw_info_ver_4_2_0.h | 72 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 428 ++ .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h | 79 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 231 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c | 55 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h | 18 + drivers/cam_lrme/Makefile | 16 + drivers/cam_lrme/cam_lrme_context.c | 251 + drivers/cam_lrme/cam_lrme_context.h | 33 + drivers/cam_lrme/cam_lrme_dev.c | 235 + drivers/cam_lrme/lrme_hw_mgr/Makefile | 16 + .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 1155 +++ .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h | 126 + .../lrme_hw_mgr/cam_lrme_hw_mgr_intf.h | 18 + drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile | 15 + .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c | 1274 ++++ .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h | 451 ++ .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c | 304 + .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h | 195 + .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h | 186 + .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c | 161 + .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h | 21 + drivers/cam_req_mgr/Makefile | 15 + drivers/cam_req_mgr/cam_mem_mgr.c | 1391 ++++ drivers/cam_req_mgr/cam_mem_mgr.h | 126 + drivers/cam_req_mgr/cam_mem_mgr_api.h | 120 + drivers/cam_req_mgr/cam_req_mgr_core.c | 3242 +++++++++ drivers/cam_req_mgr/cam_req_mgr_core.h | 470 ++ drivers/cam_req_mgr/cam_req_mgr_core_defs.h | 17 + drivers/cam_req_mgr/cam_req_mgr_debug.c | 132 + drivers/cam_req_mgr/cam_req_mgr_debug.h | 14 + drivers/cam_req_mgr/cam_req_mgr_dev.c | 752 ++ drivers/cam_req_mgr/cam_req_mgr_dev.h | 43 + drivers/cam_req_mgr/cam_req_mgr_interface.h | 332 + drivers/cam_req_mgr/cam_req_mgr_timer.c | 90 + drivers/cam_req_mgr/cam_req_mgr_timer.h | 64 + drivers/cam_req_mgr/cam_req_mgr_util.c | 333 + drivers/cam_req_mgr/cam_req_mgr_util.h | 165 + drivers/cam_req_mgr/cam_req_mgr_util_priv.h | 42 + drivers/cam_req_mgr/cam_req_mgr_workq.c | 267 + drivers/cam_req_mgr/cam_req_mgr_workq.h | 144 + drivers/cam_req_mgr/cam_subdev.h | 108 + drivers/cam_sensor_module/Makefile | 12 + .../cam_sensor_module/cam_actuator/Makefile | 12 + .../cam_actuator/cam_actuator_core.c | 981 +++ .../cam_actuator/cam_actuator_core.h | 66 + .../cam_actuator/cam_actuator_dev.c | 442 ++ .../cam_actuator/cam_actuator_dev.h | 123 + .../cam_actuator/cam_actuator_soc.c | 77 + .../cam_actuator/cam_actuator_soc.h | 19 + drivers/cam_sensor_module/cam_cci/Makefile | 11 + .../cam_sensor_module/cam_cci/cam_cci_core.c | 1727 +++++ .../cam_sensor_module/cam_cci/cam_cci_core.h | 39 + .../cam_sensor_module/cam_cci/cam_cci_dev.c | 521 ++ .../cam_sensor_module/cam_cci/cam_cci_dev.h | 313 + .../cam_sensor_module/cam_cci/cam_cci_hwreg.h | 79 + .../cam_sensor_module/cam_cci/cam_cci_soc.c | 417 ++ .../cam_sensor_module/cam_cci/cam_cci_soc.h | 45 + drivers/cam_sensor_module/cam_csiphy/Makefile | 12 + .../cam_csiphy/cam_csiphy_core.c | 971 +++ .../cam_csiphy/cam_csiphy_core.h | 52 + .../cam_csiphy/cam_csiphy_dev.c | 253 + .../cam_csiphy/cam_csiphy_dev.h | 293 + .../cam_csiphy/cam_csiphy_soc.c | 383 + .../cam_csiphy/cam_csiphy_soc.h | 73 + .../cam_csiphy/include/cam_csiphy_1_0_hwreg.h | 348 + .../cam_csiphy/include/cam_csiphy_1_1_hwreg.h | 499 ++ .../include/cam_csiphy_1_2_1_hwreg.h | 491 ++ .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 512 ++ .../cam_csiphy/include/cam_csiphy_2_0_hwreg.h | 289 + drivers/cam_sensor_module/cam_eeprom/Makefile | 11 + .../cam_eeprom/cam_eeprom_core.c | 1506 ++++ .../cam_eeprom/cam_eeprom_core.h | 21 + .../cam_eeprom/cam_eeprom_dev.c | 594 ++ .../cam_eeprom/cam_eeprom_dev.h | 196 + .../cam_eeprom/cam_eeprom_soc.c | 384 + .../cam_eeprom/cam_eeprom_soc.h | 16 + drivers/cam_sensor_module/cam_flash/Makefile | 14 + .../cam_flash/cam_flash_core.c | 1812 +++++ .../cam_flash/cam_flash_core.h | 19 + .../cam_flash/cam_flash_dev.c | 652 ++ .../cam_flash/cam_flash_dev.h | 225 + .../cam_flash/cam_flash_soc.c | 251 + .../cam_flash/cam_flash_soc.h | 14 + drivers/cam_sensor_module/cam_ois/Makefile | 12 + .../cam_sensor_module/cam_ois/cam_ois_core.c | 843 +++ .../cam_sensor_module/cam_ois/cam_ois_core.h | 34 + .../cam_sensor_module/cam_ois/cam_ois_dev.c | 422 ++ .../cam_sensor_module/cam_ois/cam_ois_dev.h | 126 + .../cam_sensor_module/cam_ois/cam_ois_soc.c | 122 + .../cam_sensor_module/cam_ois/cam_ois_soc.h | 12 + .../cam_sensor_module/cam_res_mgr/Makefile | 12 + .../cam_res_mgr/cam_res_mgr.c | 739 ++ .../cam_res_mgr/cam_res_mgr_api.h | 141 + .../cam_res_mgr/cam_res_mgr_private.h | 110 + drivers/cam_sensor_module/cam_sensor/Makefile | 13 + .../cam_sensor/cam_sensor_core.c | 1325 ++++ .../cam_sensor/cam_sensor_core.h | 86 + .../cam_sensor/cam_sensor_dev.c | 394 ++ .../cam_sensor/cam_sensor_dev.h | 118 + .../cam_sensor/cam_sensor_soc.c | 285 + .../cam_sensor/cam_sensor_soc.h | 18 + .../cam_sensor_module/cam_sensor_io/Makefile | 12 + .../cam_sensor_io/cam_sensor_cci_i2c.c | 232 + .../cam_sensor_io/cam_sensor_i2c.h | 174 + .../cam_sensor_io/cam_sensor_io.c | 217 + .../cam_sensor_io/cam_sensor_io.h | 116 + .../cam_sensor_io/cam_sensor_qup_i2c.c | 530 ++ .../cam_sensor_io/cam_sensor_spi.c | 615 ++ .../cam_sensor_io/cam_sensor_spi.h | 103 + .../cam_sensor_utils/Makefile | 13 + .../cam_sensor_utils/cam_sensor_cmn_header.h | 396 ++ .../cam_sensor_utils/cam_sensor_util.c | 2057 ++++++ .../cam_sensor_utils/cam_sensor_util.h | 61 + drivers/cam_smmu/Makefile | 7 + drivers/cam_smmu/cam_smmu_api.c | 3570 ++++++++++ drivers/cam_smmu/cam_smmu_api.h | 395 ++ drivers/cam_sync/Makefile | 7 + drivers/cam_sync/cam_sync.c | 1094 +++ drivers/cam_sync/cam_sync_api.h | 144 + drivers/cam_sync/cam_sync_private.h | 196 + drivers/cam_sync/cam_sync_util.c | 450 ++ drivers/cam_sync/cam_sync_util.h | 145 + drivers/cam_utils/Makefile | 9 + drivers/cam_utils/cam_common_util.c | 50 + drivers/cam_utils/cam_common_util.h | 48 + drivers/cam_utils/cam_cx_ipeak.c | 128 + drivers/cam_utils/cam_cx_ipeak.h | 17 + drivers/cam_utils/cam_debug_util.c | 117 + drivers/cam_utils/cam_debug_util.h | 134 + drivers/cam_utils/cam_io_util.c | 280 + drivers/cam_utils/cam_io_util.h | 232 + drivers/cam_utils/cam_packet_util.c | 326 + drivers/cam_utils/cam_packet_util.h | 126 + drivers/cam_utils/cam_soc_util.c | 1752 +++++ drivers/cam_utils/cam_soc_util.h | 638 ++ drivers/cam_utils/cam_trace.c | 8 + drivers/cam_utils/cam_trace.h | 301 + include/Kbuild | 2 + include/uapi/Kbuild | 3 + include/uapi/media/Kbuild | 14 + include/uapi/media/cam_cpas.h | 89 + include/uapi/media/cam_defs.h | 746 ++ include/uapi/media/cam_fd.h | 132 + include/uapi/media/cam_icp.h | 210 + include/uapi/media/cam_isp.h | 693 ++ include/uapi/media/cam_isp_ife.h | 52 + include/uapi/media/cam_isp_vfe.h | 49 + include/uapi/media/cam_jpeg.h | 122 + include/uapi/media/cam_lrme.h | 69 + include/uapi/media/cam_req_mgr.h | 444 ++ include/uapi/media/cam_sensor.h | 485 ++ include/uapi/media/cam_sync.h | 139 + 356 files changed, 134959 insertions(+), 10 deletions(-) delete mode 100644 camera_stub.c create mode 100644 config/konacamera.conf create mode 100644 config/konacameraconf.h create mode 100644 drivers/Makefile create mode 100644 drivers/cam_cdm/Makefile create mode 100644 drivers/cam_cdm/cam_cdm.h create mode 100644 drivers/cam_cdm/cam_cdm_core_common.c create mode 100644 drivers/cam_cdm/cam_cdm_core_common.h create mode 100644 drivers/cam_cdm/cam_cdm_hw_core.c create mode 100644 drivers/cam_cdm/cam_cdm_intf.c create mode 100644 drivers/cam_cdm/cam_cdm_intf_api.h create mode 100644 drivers/cam_cdm/cam_cdm_soc.c create mode 100644 drivers/cam_cdm/cam_cdm_soc.h create mode 100644 drivers/cam_cdm/cam_cdm_util.c create mode 100644 drivers/cam_cdm/cam_cdm_util.h create mode 100644 drivers/cam_cdm/cam_cdm_virtual.h create mode 100644 drivers/cam_cdm/cam_cdm_virtual_core.c create mode 100644 drivers/cam_cdm/cam_hw_cdm170_reg.h create mode 100644 drivers/cam_core/Makefile create mode 100644 drivers/cam_core/cam_context.c create mode 100644 drivers/cam_core/cam_context.h create mode 100644 drivers/cam_core/cam_context_utils.c create mode 100644 drivers/cam_core/cam_context_utils.h create mode 100644 drivers/cam_core/cam_hw.h create mode 100644 drivers/cam_core/cam_hw_intf.h create mode 100644 drivers/cam_core/cam_hw_mgr_intf.h create mode 100644 drivers/cam_core/cam_node.c create mode 100644 drivers/cam_core/cam_node.h create mode 100644 drivers/cam_core/cam_subdev.c create mode 100644 drivers/cam_cpas/Makefile create mode 100644 drivers/cam_cpas/cam_cpas_hw.c create mode 100644 drivers/cam_cpas/cam_cpas_hw.h create mode 100644 drivers/cam_cpas/cam_cpas_hw_intf.h create mode 100644 drivers/cam_cpas/cam_cpas_intf.c create mode 100644 drivers/cam_cpas/cam_cpas_soc.c create mode 100644 drivers/cam_cpas/cam_cpas_soc.h create mode 100644 drivers/cam_cpas/camss_top/Makefile create mode 100644 drivers/cam_cpas/camss_top/cam_camsstop_hw.c create mode 100644 drivers/cam_cpas/cpas_top/Makefile create mode 100644 drivers/cam_cpas/cpas_top/cam_cpastop_hw.c create mode 100644 drivers/cam_cpas/cpas_top/cam_cpastop_hw.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop100.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v150_100.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v170_110.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v175_100.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v175_101.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v175_120.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v175_130.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v480_100.h create mode 100644 drivers/cam_cpas/include/cam_cpas_api.h create mode 100644 drivers/cam_fd/Makefile create mode 100644 drivers/cam_fd/cam_fd_context.c create mode 100644 drivers/cam_fd/cam_fd_context.h create mode 100644 drivers/cam_fd/cam_fd_dev.c create mode 100644 drivers/cam_fd/fd_hw_mgr/Makefile create mode 100644 drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c create mode 100644 drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h create mode 100644 drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr_intf.h create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.h create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h create mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v600.h create mode 100644 drivers/cam_icp/Makefile create mode 100644 drivers/cam_icp/cam_icp_context.c create mode 100644 drivers/cam_icp/cam_icp_context.h create mode 100644 drivers/cam_icp/cam_icp_subdev.c create mode 100644 drivers/cam_icp/fw_inc/hfi_intf.h create mode 100644 drivers/cam_icp/fw_inc/hfi_reg.h create mode 100644 drivers/cam_icp/fw_inc/hfi_session_defs.h create mode 100644 drivers/cam_icp/fw_inc/hfi_sys_defs.h create mode 100644 drivers/cam_icp/hfi.c create mode 100644 drivers/cam_icp/icp_hw/Makefile create mode 100644 drivers/cam_icp/icp_hw/a5_hw/Makefile create mode 100644 drivers/cam_icp/icp_hw/a5_hw/a5_core.c create mode 100644 drivers/cam_icp/icp_hw/a5_hw/a5_core.h create mode 100644 drivers/cam_icp/icp_hw/a5_hw/a5_dev.c create mode 100644 drivers/cam_icp/icp_hw/a5_hw/a5_soc.c create mode 100644 drivers/cam_icp/icp_hw/a5_hw/a5_soc.h create mode 100644 drivers/cam_icp/icp_hw/bps_hw/Makefile create mode 100644 drivers/cam_icp/icp_hw/bps_hw/bps_core.c create mode 100644 drivers/cam_icp/icp_hw/bps_hw/bps_core.h create mode 100644 drivers/cam_icp/icp_hw/bps_hw/bps_dev.c create mode 100644 drivers/cam_icp/icp_hw/bps_hw/bps_soc.c create mode 100644 drivers/cam_icp/icp_hw/bps_hw/bps_soc.h create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h create mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h create mode 100644 drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h create mode 100644 drivers/cam_icp/icp_hw/ipe_hw/Makefile create mode 100644 drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c create mode 100644 drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h create mode 100644 drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c create mode 100644 drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c create mode 100644 drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h create mode 100644 drivers/cam_isp/Makefile create mode 100644 drivers/cam_isp/cam_isp_context.c create mode 100644 drivers/cam_isp/cam_isp_context.h create mode 100644 drivers/cam_isp/cam_isp_dev.c create mode 100644 drivers/cam_isp/cam_isp_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c create mode 100644 drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h create mode 100644 drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c create mode 100644 drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c create mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h create mode 100644 drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver1.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h create mode 100644 drivers/cam_jpeg/Makefile create mode 100644 drivers/cam_jpeg/cam_jpeg_context.c create mode 100644 drivers/cam_jpeg/cam_jpeg_context.h create mode 100644 drivers/cam_jpeg/cam_jpeg_dev.c create mode 100644 drivers/cam_jpeg/cam_jpeg_dev.h create mode 100644 drivers/cam_jpeg/jpeg_hw/Makefile create mode 100644 drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c create mode 100644 drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h create mode 100644 drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h create mode 100644 drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h create mode 100644 drivers/cam_lrme/Makefile create mode 100644 drivers/cam_lrme/cam_lrme_context.c create mode 100644 drivers/cam_lrme/cam_lrme_context.h create mode 100644 drivers/cam_lrme/cam_lrme_dev.c create mode 100644 drivers/cam_lrme/lrme_hw_mgr/Makefile create mode 100644 drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c create mode 100644 drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h create mode 100644 drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr_intf.h create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c create mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h create mode 100644 drivers/cam_req_mgr/Makefile create mode 100644 drivers/cam_req_mgr/cam_mem_mgr.c create mode 100644 drivers/cam_req_mgr/cam_mem_mgr.h create mode 100644 drivers/cam_req_mgr/cam_mem_mgr_api.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_core.c create mode 100644 drivers/cam_req_mgr/cam_req_mgr_core.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_core_defs.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_debug.c create mode 100644 drivers/cam_req_mgr/cam_req_mgr_debug.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_dev.c create mode 100644 drivers/cam_req_mgr/cam_req_mgr_dev.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_interface.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_timer.c create mode 100644 drivers/cam_req_mgr/cam_req_mgr_timer.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_util.c create mode 100644 drivers/cam_req_mgr/cam_req_mgr_util.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_util_priv.h create mode 100644 drivers/cam_req_mgr/cam_req_mgr_workq.c create mode 100644 drivers/cam_req_mgr/cam_req_mgr_workq.h create mode 100644 drivers/cam_req_mgr/cam_subdev.h create mode 100644 drivers/cam_sensor_module/Makefile create mode 100644 drivers/cam_sensor_module/cam_actuator/Makefile create mode 100644 drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c create mode 100644 drivers/cam_sensor_module/cam_actuator/cam_actuator_core.h create mode 100644 drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c create mode 100644 drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h create mode 100644 drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c create mode 100644 drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.h create mode 100644 drivers/cam_sensor_module/cam_cci/Makefile create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_core.c create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_core.h create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_dev.c create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_dev.h create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_soc.c create mode 100644 drivers/cam_sensor_module/cam_cci/cam_cci_soc.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/Makefile create mode 100644 drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c create mode 100644 drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c create mode 100644 drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c create mode 100644 drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h create mode 100644 drivers/cam_sensor_module/cam_eeprom/Makefile create mode 100644 drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c create mode 100644 drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.h create mode 100644 drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c create mode 100644 drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h create mode 100644 drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c create mode 100644 drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h create mode 100644 drivers/cam_sensor_module/cam_flash/Makefile create mode 100644 drivers/cam_sensor_module/cam_flash/cam_flash_core.c create mode 100644 drivers/cam_sensor_module/cam_flash/cam_flash_core.h create mode 100644 drivers/cam_sensor_module/cam_flash/cam_flash_dev.c create mode 100644 drivers/cam_sensor_module/cam_flash/cam_flash_dev.h create mode 100644 drivers/cam_sensor_module/cam_flash/cam_flash_soc.c create mode 100644 drivers/cam_sensor_module/cam_flash/cam_flash_soc.h create mode 100644 drivers/cam_sensor_module/cam_ois/Makefile create mode 100644 drivers/cam_sensor_module/cam_ois/cam_ois_core.c create mode 100644 drivers/cam_sensor_module/cam_ois/cam_ois_core.h create mode 100644 drivers/cam_sensor_module/cam_ois/cam_ois_dev.c create mode 100644 drivers/cam_sensor_module/cam_ois/cam_ois_dev.h create mode 100644 drivers/cam_sensor_module/cam_ois/cam_ois_soc.c create mode 100644 drivers/cam_sensor_module/cam_ois/cam_ois_soc.h create mode 100644 drivers/cam_sensor_module/cam_res_mgr/Makefile create mode 100644 drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c create mode 100644 drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h create mode 100644 drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h create mode 100644 drivers/cam_sensor_module/cam_sensor/Makefile create mode 100644 drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c create mode 100644 drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h create mode 100644 drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c create mode 100644 drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h create mode 100644 drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c create mode 100644 drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.h create mode 100644 drivers/cam_sensor_module/cam_sensor_io/Makefile create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c create mode 100644 drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h create mode 100644 drivers/cam_sensor_module/cam_sensor_utils/Makefile create mode 100644 drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h create mode 100644 drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c create mode 100644 drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h create mode 100644 drivers/cam_smmu/Makefile create mode 100644 drivers/cam_smmu/cam_smmu_api.c create mode 100644 drivers/cam_smmu/cam_smmu_api.h create mode 100644 drivers/cam_sync/Makefile create mode 100644 drivers/cam_sync/cam_sync.c create mode 100644 drivers/cam_sync/cam_sync_api.h create mode 100644 drivers/cam_sync/cam_sync_private.h create mode 100644 drivers/cam_sync/cam_sync_util.c create mode 100644 drivers/cam_sync/cam_sync_util.h create mode 100644 drivers/cam_utils/Makefile create mode 100644 drivers/cam_utils/cam_common_util.c create mode 100644 drivers/cam_utils/cam_common_util.h create mode 100644 drivers/cam_utils/cam_cx_ipeak.c create mode 100644 drivers/cam_utils/cam_cx_ipeak.h create mode 100644 drivers/cam_utils/cam_debug_util.c create mode 100644 drivers/cam_utils/cam_debug_util.h create mode 100644 drivers/cam_utils/cam_io_util.c create mode 100644 drivers/cam_utils/cam_io_util.h create mode 100644 drivers/cam_utils/cam_packet_util.c create mode 100644 drivers/cam_utils/cam_packet_util.h create mode 100644 drivers/cam_utils/cam_soc_util.c create mode 100644 drivers/cam_utils/cam_soc_util.h create mode 100644 drivers/cam_utils/cam_trace.c create mode 100644 drivers/cam_utils/cam_trace.h create mode 100644 include/Kbuild create mode 100644 include/uapi/Kbuild create mode 100644 include/uapi/media/Kbuild create mode 100644 include/uapi/media/cam_cpas.h create mode 100644 include/uapi/media/cam_defs.h create mode 100644 include/uapi/media/cam_fd.h create mode 100644 include/uapi/media/cam_icp.h create mode 100644 include/uapi/media/cam_isp.h create mode 100644 include/uapi/media/cam_isp_ife.h create mode 100644 include/uapi/media/cam_isp_vfe.h create mode 100644 include/uapi/media/cam_jpeg.h create mode 100644 include/uapi/media/cam_lrme.h create mode 100644 include/uapi/media/cam_req_mgr.h create mode 100644 include/uapi/media/cam_sensor.h create mode 100644 include/uapi/media/cam_sync.h diff --git a/Makefile b/Makefile index b5ddf0094c84..f844d98cbdc6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,23 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y := -Wno-unused-function -obj-y := camera_stub.o +# auto-detect subdirs +ifeq ($(CONFIG_ARCH_KONA), y) +include $(srctree)/techpack/camera/config/konacamera.conf +endif + +# Use USERINCLUDE when you must reference the UAPI directories only. +USERINCLUDE += \ + -I$(srctree)/techpack/camera/include/uapi + +# Use LINUXINCLUDE when you must reference the include/ directory. +# Needed to be compatible with the O= option +LINUXINCLUDE += \ + -I$(srctree)/techpack/camera/include/uapi \ + -I$(srctree)/techpack/camera/include + +ifeq ($(CONFIG_ARCH_KONA), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/konacameraconf.h +endif + +obj-y += drivers/ diff --git a/camera_stub.c b/camera_stub.c deleted file mode 100644 index e2e808c53e5d..000000000000 --- a/camera_stub.c +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. - */ - -static void _camera_techpack_stub(void) -{ -} diff --git a/config/konacamera.conf b/config/konacamera.conf new file mode 100644 index 000000000000..9b08bcb80c2b --- /dev/null +++ b/config/konacamera.conf @@ -0,0 +1 @@ +export CONFIG_SPECTRA_CAMERA=y \ No newline at end of file diff --git a/config/konacameraconf.h b/config/konacameraconf.h new file mode 100644 index 000000000000..e0cf514fe3cf --- /dev/null +++ b/config/konacameraconf.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#define CONFIG_SPECTRA_CAMERA 1 + diff --git a/drivers/Makefile b/drivers/Makefile new file mode 100644 index 000000000000..28d4762a55df --- /dev/null +++ b/drivers/Makefile @@ -0,0 +1,13 @@ +obj-y += cam_req_mgr/ +obj-y += cam_utils/ +obj-y += cam_core/ +obj-y += cam_sync/ +obj-y += cam_smmu/ +obj-y += cam_cpas/ +obj-y += cam_cdm/ +obj-y += cam_isp/ +obj-y += cam_sensor_module/ +obj-y += cam_icp/ +obj-y += cam_jpeg/ +obj-y += cam_fd/ +obj-y += cam_lrme/ diff --git a/drivers/cam_cdm/Makefile b/drivers/cam_cdm/Makefile new file mode 100644 index 000000000000..2b5b712cbbb3 --- /dev/null +++ b/drivers/cam_cdm/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm_util.o cam_cdm_intf.o cam_cdm_soc.o\ + cam_cdm_core_common.o cam_cdm_virtual_core.o \ + cam_cdm_hw_core.o diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h new file mode 100644 index 000000000000..ab12ab52f293 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CDM_H_ +#define _CAM_CDM_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_cdm_intf_api.h" +#include "cam_soc_util.h" +#include "cam_cpas_api.h" +#include "cam_hw_intf.h" +#include "cam_hw.h" +#include "cam_debug_util.h" + +#define CAM_MAX_SW_CDM_VERSION_SUPPORTED 1 +#define CAM_SW_CDM_INDEX 0 +#define CAM_CDM_INFLIGHT_WORKS 5 +#define CAM_CDM_HW_RESET_TIMEOUT 300 + +#define CAM_CDM_HW_ID_MASK 0xF +#define CAM_CDM_HW_ID_SHIFT 0x5 +#define CAM_CDM_CLIENTS_ID_MASK 0x1F + +#define CAM_CDM_GET_HW_IDX(x) (((x) >> CAM_CDM_HW_ID_SHIFT) & \ + CAM_CDM_HW_ID_MASK) +#define CAM_CDM_CREATE_CLIENT_HANDLE(hw_idx, client_idx) \ + ((((hw_idx) & CAM_CDM_HW_ID_MASK) << CAM_CDM_HW_ID_SHIFT) | \ + ((client_idx) & CAM_CDM_CLIENTS_ID_MASK)) +#define CAM_CDM_GET_CLIENT_IDX(x) ((x) & CAM_CDM_CLIENTS_ID_MASK) +#define CAM_PER_CDM_MAX_REGISTERED_CLIENTS (CAM_CDM_CLIENTS_ID_MASK + 1) +#define CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM (CAM_CDM_HW_ID_MASK + 1) + +/* enum cam_cdm_reg_attr - read, write, read and write permissions.*/ +enum cam_cdm_reg_attr { + CAM_REG_ATTR_READ, + CAM_REG_ATTR_WRITE, + CAM_REG_ATTR_READ_WRITE, +}; + +/* enum cam_cdm_hw_process_intf_cmd - interface commands.*/ +enum cam_cdm_hw_process_intf_cmd { + CAM_CDM_HW_INTF_CMD_ACQUIRE, + CAM_CDM_HW_INTF_CMD_RELEASE, + CAM_CDM_HW_INTF_CMD_SUBMIT_BL, + CAM_CDM_HW_INTF_CMD_RESET_HW, + CAM_CDM_HW_INTF_CMD_INVALID, +}; + +/* enum cam_cdm_regs - CDM driver offset enums.*/ +enum cam_cdm_regs { + /*cfg_offsets 0*/ + CDM_CFG_HW_VERSION, + CDM_CFG_TITAN_VERSION, + CDM_CFG_RST_CMD, + CDM_CFG_CGC_CFG, + CDM_CFG_CORE_CFG, + CDM_CFG_CORE_EN, + CDM_CFG_FE_CFG, + /*irq_offsets 7*/ + CDM_IRQ_MASK, + CDM_IRQ_CLEAR, + CDM_IRQ_CLEAR_CMD, + CDM_IRQ_SET, + CDM_IRQ_SET_CMD, + CDM_IRQ_STATUS, + CDM_IRQ_USR_DATA, + /*BL FIFO Registers 14*/ + CDM_BL_FIFO_BASE_REG, + CDM_BL_FIFO_LEN_REG, + CDM_BL_FIFO_STORE_REG, + CDM_BL_FIFO_CFG, + CDM_BL_FIFO_RB, + CDM_BL_FIFO_BASE_RB, + CDM_BL_FIFO_LEN_RB, + CDM_BL_FIFO_PENDING_REQ_RB, + /*CDM System Debug Registers 22*/ + CDM_DBG_WAIT_STATUS, + CDM_DBG_SCRATCH_0_REG, + CDM_DBG_SCRATCH_1_REG, + CDM_DBG_SCRATCH_2_REG, + CDM_DBG_SCRATCH_3_REG, + CDM_DBG_SCRATCH_4_REG, + CDM_DBG_SCRATCH_5_REG, + CDM_DBG_SCRATCH_6_REG, + CDM_DBG_SCRATCH_7_REG, + CDM_DBG_LAST_AHB_ADDR, + CDM_DBG_LAST_AHB_DATA, + CDM_DBG_CORE_DBUG, + CDM_DBG_LAST_AHB_ERR_ADDR, + CDM_DBG_LAST_AHB_ERR_DATA, + CDM_DBG_CURRENT_BL_BASE, + CDM_DBG_CURRENT_BL_LEN, + CDM_DBG_CURRENT_USED_AHB_BASE, + CDM_DBG_DEBUG_STATUS, + /*FE Bus Miser Registers 40*/ + CDM_BUS_MISR_CFG_0, + CDM_BUS_MISR_CFG_1, + CDM_BUS_MISR_RD_VAL, + /*Performance Counter registers 43*/ + CDM_PERF_MON_CTRL, + CDM_PERF_MON_0, + CDM_PERF_MON_1, + CDM_PERF_MON_2, + /*Spare registers 47*/ + CDM_SPARE, +}; + +/* struct cam_cdm_reg_offset - struct for offset with attribute.*/ +struct cam_cdm_reg_offset { + uint32_t offset; + enum cam_cdm_reg_attr attribute; +}; + +/* struct cam_cdm_reg_offset_table - struct for whole offset table.*/ +struct cam_cdm_reg_offset_table { + uint32_t first_offset; + uint32_t last_offset; + uint32_t reg_count; + const struct cam_cdm_reg_offset *offsets; + uint32_t offset_max_size; +}; + +/* enum cam_cdm_flags - Bit fields for CDM flags used */ +enum cam_cdm_flags { + CAM_CDM_FLAG_SHARED_CDM, + CAM_CDM_FLAG_PRIVATE_CDM, +}; + +/* enum cam_cdm_type - Enum for possible CAM CDM types */ +enum cam_cdm_type { + CAM_VIRTUAL_CDM, + CAM_HW_CDM, +}; + +/* enum cam_cdm_mem_base_index - Enum for possible CAM CDM types */ +enum cam_cdm_mem_base_index { + CAM_HW_CDM_BASE_INDEX, + CAM_HW_CDM_MAX_INDEX = CAM_SOC_MAX_BLOCK, +}; + +/* struct cam_cdm_client - struct for cdm clients data.*/ +struct cam_cdm_client { + struct cam_cdm_acquire_data data; + void __iomem *changebase_addr; + uint32_t stream_on; + uint32_t refcount; + struct mutex lock; + uint32_t handle; +}; + +/* struct cam_cdm_work_payload - struct for cdm work payload data.*/ +struct cam_cdm_work_payload { + struct cam_hw_info *hw; + uint32_t irq_status; + uint32_t irq_data; + struct work_struct work; +}; + +/* enum cam_cdm_bl_cb_type - Enum for possible CAM CDM cb request types */ +enum cam_cdm_bl_cb_type { + CAM_HW_CDM_BL_CB_CLIENT = 1, + CAM_HW_CDM_BL_CB_INTERNAL, +}; + +/* struct cam_cdm_bl_cb_request_entry - callback entry for work to process.*/ +struct cam_cdm_bl_cb_request_entry { + uint8_t bl_tag; + enum cam_cdm_bl_cb_type request_type; + uint32_t client_hdl; + void *userdata; + uint32_t cookie; + struct list_head entry; +}; + +/* struct cam_cdm_hw_intf_cmd_submit_bl - cdm interface submit command.*/ +struct cam_cdm_hw_intf_cmd_submit_bl { + uint32_t handle; + struct cam_cdm_bl_request *data; +}; + +/* struct cam_cdm_hw_mem - CDM hw memory struct */ +struct cam_cdm_hw_mem { + int32_t handle; + uint32_t vaddr; + uintptr_t kmdvaddr; + size_t size; +}; + +/* struct cam_cdm - CDM hw device struct */ +struct cam_cdm { + uint32_t index; + char name[128]; + enum cam_cdm_id id; + enum cam_cdm_flags flags; + struct completion reset_complete; + struct completion bl_complete; + struct workqueue_struct *work_queue; + struct list_head bl_request_list; + struct cam_hw_version version; + uint32_t hw_version; + uint32_t hw_family_version; + struct cam_iommu_handle iommu_hdl; + struct cam_cdm_reg_offset_table *offset_tbl; + struct cam_cdm_utils_ops *ops; + struct cam_cdm_client *clients[CAM_PER_CDM_MAX_REGISTERED_CLIENTS]; + uint8_t bl_tag; + atomic_t error; + atomic_t bl_done; + struct cam_cdm_hw_mem gen_irq; + uint32_t cpas_handle; +}; + +/* struct cam_cdm_private_dt_data - CDM hw custom dt data */ +struct cam_cdm_private_dt_data { + bool dt_cdm_shared; + uint32_t dt_num_supported_clients; + const char *dt_cdm_client_name[CAM_PER_CDM_MAX_REGISTERED_CLIENTS]; +}; + +/* struct cam_cdm_intf_devices - CDM mgr interface devices */ +struct cam_cdm_intf_devices { + struct mutex lock; + uint32_t refcount; + struct cam_hw_intf *device; + struct cam_cdm_private_dt_data *data; +}; + +/* struct cam_cdm_intf_mgr - CDM mgr interface device struct */ +struct cam_cdm_intf_mgr { + bool probe_done; + struct cam_cdm_intf_devices nodes[CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM]; + uint32_t cdm_count; + uint32_t dt_supported_hw_cdm; + int32_t refcount; +}; + +int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, + struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, + uint32_t *index); +int cam_cdm_intf_deregister_hw_cdm(struct cam_hw_intf *hw, + struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, + uint32_t index); + +#endif /* _CAM_CDM_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c new file mode 100644 index 000000000000..5401945c0e23 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -0,0 +1,587 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_soc_util.h" +#include "cam_smmu_api.h" +#include "cam_io_util.h" +#include "cam_cdm_intf_api.h" +#include "cam_cdm.h" +#include "cam_cdm_soc.h" +#include "cam_cdm_core_common.h" + +static void cam_cdm_get_client_refcount(struct cam_cdm_client *client) +{ + mutex_lock(&client->lock); + CAM_DBG(CAM_CDM, "CDM client get refcount=%d", + client->refcount); + client->refcount++; + mutex_unlock(&client->lock); +} + +static void cam_cdm_put_client_refcount(struct cam_cdm_client *client) +{ + mutex_lock(&client->lock); + CAM_DBG(CAM_CDM, "CDM client put refcount=%d", + client->refcount); + if (client->refcount > 0) { + client->refcount--; + } else { + CAM_ERR(CAM_CDM, "Refcount put when zero"); + WARN_ON(1); + } + mutex_unlock(&client->lock); +} + +bool cam_cdm_set_cam_hw_version( + uint32_t ver, struct cam_hw_version *cam_version) +{ + switch (ver) { + case CAM_CDM170_VERSION: + case CAM_CDM175_VERSION: + case CAM_CDM480_VERSION: + cam_version->major = (ver & 0xF0000000); + cam_version->minor = (ver & 0xFFF0000); + cam_version->incr = (ver & 0xFFFF); + cam_version->reserved = 0; + return true; + default: + CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", ver); + break; + } + return false; +} + +bool cam_cdm_cpas_cb(uint32_t client_handle, void *userdata, + struct cam_cpas_irq_data *irq_data) +{ + if (!irq_data) + return false; + + CAM_DBG(CAM_CDM, "CPAS error callback type=%d", irq_data->irq_type); + + return false; +} + +struct cam_cdm_utils_ops *cam_cdm_get_ops( + uint32_t ver, struct cam_hw_version *cam_version, bool by_cam_version) +{ + if (by_cam_version == false) { + switch (ver) { + case CAM_CDM170_VERSION: + case CAM_CDM175_VERSION: + case CAM_CDM480_VERSION: + return &CDM170_ops; + default: + CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", + ver); + } + } else if (cam_version) { + if (((cam_version->major == 1) && + (cam_version->minor == 0) && + (cam_version->incr == 0)) || + ((cam_version->major == 1) && + (cam_version->minor == 1) && + (cam_version->incr == 0)) || + ((cam_version->major == 1) && + (cam_version->minor == 2) && + (cam_version->incr == 0))) { + + CAM_DBG(CAM_CDM, + "cam_hw_version=%x:%x:%x supported", + cam_version->major, cam_version->minor, + cam_version->incr); + return &CDM170_ops; + } + + CAM_ERR(CAM_CDM, "cam_hw_version=%x:%x:%x not supported", + cam_version->major, cam_version->minor, + cam_version->incr); + } + + return NULL; +} + +struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( + uint32_t tag, struct list_head *bl_list) +{ + struct cam_cdm_bl_cb_request_entry *node; + + list_for_each_entry(node, bl_list, entry) { + if (node->bl_tag == tag) + return node; + } + CAM_ERR(CAM_CDM, "Could not find the bl request for tag=%x", tag); + + return NULL; +} + +int cam_cdm_get_caps(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_cdm *cdm_core; + + if ((cdm_hw) && (cdm_hw->core_info) && (get_hw_cap_args) && + (sizeof(struct cam_iommu_handle) == arg_size)) { + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + *((struct cam_iommu_handle *)get_hw_cap_args) = + cdm_core->iommu_hdl; + return 0; + } + + return -EINVAL; +} + +int cam_cdm_find_free_client_slot(struct cam_cdm *hw) +{ + int i; + + for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) { + if (hw->clients[i] == NULL) { + CAM_DBG(CAM_CDM, "Found client slot %d", i); + return i; + } + } + CAM_ERR(CAM_CDM, "No more client slots"); + + return -EBUSY; +} + + +void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, + enum cam_cdm_cb_status status, void *data) +{ + int i; + struct cam_cdm *core = NULL; + struct cam_cdm_client *client = NULL; + + if (!cdm_hw) { + CAM_ERR(CAM_CDM, "CDM Notify called with NULL hw info"); + return; + } + core = (struct cam_cdm *)cdm_hw->core_info; + + if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { + int client_idx; + struct cam_cdm_bl_cb_request_entry *node = + (struct cam_cdm_bl_cb_request_entry *)data; + + client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl); + client = core->clients[client_idx]; + if ((!client) || (client->handle != node->client_hdl)) { + CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, + node->client_hdl); + return; + } + cam_cdm_get_client_refcount(client); + if (client->data.cam_cdm_callback) { + CAM_DBG(CAM_CDM, "Calling client=%s cb cookie=%d", + client->data.identifier, node->cookie); + client->data.cam_cdm_callback(node->client_hdl, + node->userdata, CAM_CDM_CB_STATUS_BL_SUCCESS, + node->cookie); + CAM_DBG(CAM_CDM, "Exit client cb cookie=%d", + node->cookie); + } else { + CAM_ERR(CAM_CDM, "No cb registered for client hdl=%x", + node->client_hdl); + } + cam_cdm_put_client_refcount(client); + return; + } + + for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) { + if (core->clients[i] != NULL) { + client = core->clients[i]; + mutex_lock(&client->lock); + CAM_DBG(CAM_CDM, "Found client slot %d", i); + if (client->data.cam_cdm_callback) { + if (status == CAM_CDM_CB_STATUS_PAGEFAULT) { + unsigned long iova = + (unsigned long)data; + + client->data.cam_cdm_callback( + client->handle, + client->data.userdata, + CAM_CDM_CB_STATUS_PAGEFAULT, + (iova & 0xFFFFFFFF)); + } + } else { + CAM_ERR(CAM_CDM, + "No cb registered for client hdl=%x", + client->handle); + } + mutex_unlock(&client->lock); + } + } +} + +int cam_cdm_stream_ops_internal(void *hw_priv, + void *start_args, bool operation) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_cdm *core = NULL; + int rc = -EPERM; + int client_idx; + struct cam_cdm_client *client; + uint32_t *handle = start_args; + + if (!hw_priv) + return -EINVAL; + + core = (struct cam_cdm *)cdm_hw->core_info; + client_idx = CAM_CDM_GET_CLIENT_IDX(*handle); + client = core->clients[client_idx]; + if (!client) { + CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle); + return -EINVAL; + } + cam_cdm_get_client_refcount(client); + if (*handle != client->handle) { + CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle); + cam_cdm_put_client_refcount(client); + return -EINVAL; + } + if (operation == true) { + if (true == client->stream_on) { + CAM_ERR(CAM_CDM, + "Invalid CDM client is already streamed ON"); + cam_cdm_put_client_refcount(client); + return rc; + } + } else { + if (client->stream_on == false) { + CAM_ERR(CAM_CDM, + "Invalid CDM client is already streamed Off"); + cam_cdm_put_client_refcount(client); + return rc; + } + } + + mutex_lock(&cdm_hw->hw_mutex); + if (operation == true) { + if (!cdm_hw->open_count) { + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = + CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = + CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(core->cpas_handle, + &ahb_vote, &axi_vote); + if (rc != 0) { + CAM_ERR(CAM_CDM, "CPAS start failed"); + goto end; + } + CAM_DBG(CAM_CDM, "CDM init first time"); + if (core->id == CAM_CDM_VIRTUAL) { + CAM_DBG(CAM_CDM, + "Virtual CDM HW init first time"); + rc = 0; + } else { + CAM_DBG(CAM_CDM, "CDM HW init first time"); + rc = cam_hw_cdm_init(hw_priv, NULL, 0); + if (rc == 0) { + rc = cam_hw_cdm_alloc_genirq_mem( + hw_priv); + if (rc != 0) { + CAM_ERR(CAM_CDM, + "Genirqalloc failed"); + cam_hw_cdm_deinit(hw_priv, + NULL, 0); + } + } else { + CAM_ERR(CAM_CDM, "CDM HW init failed"); + } + } + if (rc == 0) { + cdm_hw->open_count++; + client->stream_on = true; + } else { + if (cam_cpas_stop(core->cpas_handle)) + CAM_ERR(CAM_CDM, "CPAS stop failed"); + } + } else { + cdm_hw->open_count++; + CAM_DBG(CAM_CDM, "CDM HW already ON count=%d", + cdm_hw->open_count); + rc = 0; + client->stream_on = true; + } + } else { + if (cdm_hw->open_count) { + cdm_hw->open_count--; + CAM_DBG(CAM_CDM, "stream OFF CDM %d", + cdm_hw->open_count); + if (!cdm_hw->open_count) { + CAM_DBG(CAM_CDM, "CDM Deinit now"); + if (core->id == CAM_CDM_VIRTUAL) { + CAM_DBG(CAM_CDM, + "Virtual CDM HW Deinit"); + rc = 0; + } else { + CAM_DBG(CAM_CDM, "CDM HW Deinit now"); + rc = cam_hw_cdm_deinit( + hw_priv, NULL, 0); + if (cam_hw_cdm_release_genirq_mem( + hw_priv)) + CAM_ERR(CAM_CDM, + "Genirq release fail"); + } + if (rc) { + CAM_ERR(CAM_CDM, + "Deinit failed in streamoff"); + } else { + client->stream_on = false; + rc = cam_cpas_stop(core->cpas_handle); + if (rc) + CAM_ERR(CAM_CDM, + "CPAS stop failed"); + } + } else { + client->stream_on = false; + rc = 0; + CAM_DBG(CAM_CDM, + "Client stream off success =%d", + cdm_hw->open_count); + } + } else { + CAM_DBG(CAM_CDM, "stream OFF CDM Invalid %d", + cdm_hw->open_count); + rc = -ENXIO; + } + } +end: + cam_cdm_put_client_refcount(client); + mutex_unlock(&cdm_hw->hw_mutex); + return rc; +} + +int cam_cdm_stream_start(void *hw_priv, + void *start_args, uint32_t size) +{ + int rc = 0; + + if (!hw_priv) + return -EINVAL; + + rc = cam_cdm_stream_ops_internal(hw_priv, start_args, true); + return rc; + +} + +int cam_cdm_stream_stop(void *hw_priv, + void *start_args, uint32_t size) +{ + int rc = 0; + + if (!hw_priv) + return -EINVAL; + + rc = cam_cdm_stream_ops_internal(hw_priv, start_args, false); + return rc; + +} + +int cam_cdm_process_cmd(void *hw_priv, + uint32_t cmd, void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_hw_soc_info *soc_data = NULL; + struct cam_cdm *core = NULL; + int rc = -EINVAL; + + if ((!hw_priv) || (!cmd_args) || + (cmd >= CAM_CDM_HW_INTF_CMD_INVALID)) + return rc; + + soc_data = &cdm_hw->soc_info; + core = (struct cam_cdm *)cdm_hw->core_info; + switch (cmd) { + case CAM_CDM_HW_INTF_CMD_SUBMIT_BL: { + struct cam_cdm_hw_intf_cmd_submit_bl *req; + int idx; + struct cam_cdm_client *client; + + if (sizeof(struct cam_cdm_hw_intf_cmd_submit_bl) != arg_size) { + CAM_ERR(CAM_CDM, "Invalid CDM cmd %d arg size=%x", cmd, + arg_size); + break; + } + req = (struct cam_cdm_hw_intf_cmd_submit_bl *)cmd_args; + if ((req->data->type < 0) || + (req->data->type > CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA)) { + CAM_ERR(CAM_CDM, "Invalid req bl cmd addr type=%d", + req->data->type); + break; + } + idx = CAM_CDM_GET_CLIENT_IDX(req->handle); + client = core->clients[idx]; + if ((!client) || (req->handle != client->handle)) { + CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, + req->handle); + break; + } + cam_cdm_get_client_refcount(client); + if ((req->data->flag == true) && + (!client->data.cam_cdm_callback)) { + CAM_ERR(CAM_CDM, + "CDM request cb without registering cb"); + cam_cdm_put_client_refcount(client); + break; + } + if (client->stream_on != true) { + CAM_ERR(CAM_CDM, + "Invalid CDM needs to be streamed ON first"); + cam_cdm_put_client_refcount(client); + break; + } + if (core->id == CAM_CDM_VIRTUAL) + rc = cam_virtual_cdm_submit_bl(cdm_hw, req, client); + else + rc = cam_hw_cdm_submit_bl(cdm_hw, req, client); + + cam_cdm_put_client_refcount(client); + break; + } + case CAM_CDM_HW_INTF_CMD_ACQUIRE: { + struct cam_cdm_acquire_data *data; + int idx; + struct cam_cdm_client *client; + + if (sizeof(struct cam_cdm_acquire_data) != arg_size) { + CAM_ERR(CAM_CDM, "Invalid CDM cmd %d arg size=%x", cmd, + arg_size); + break; + } + + mutex_lock(&cdm_hw->hw_mutex); + data = (struct cam_cdm_acquire_data *)cmd_args; + CAM_DBG(CAM_CDM, "Trying to acquire client=%s in hw idx=%d", + data->identifier, core->index); + idx = cam_cdm_find_free_client_slot(core); + if ((idx < 0) || (core->clients[idx])) { + mutex_unlock(&cdm_hw->hw_mutex); + CAM_ERR(CAM_CDM, + "Fail to client slots, client=%s in hw idx=%d", + data->identifier, core->index); + break; + } + core->clients[idx] = kzalloc(sizeof(struct cam_cdm_client), + GFP_KERNEL); + if (!core->clients[idx]) { + mutex_unlock(&cdm_hw->hw_mutex); + rc = -ENOMEM; + break; + } + + mutex_unlock(&cdm_hw->hw_mutex); + client = core->clients[idx]; + mutex_init(&client->lock); + data->ops = core->ops; + if (core->id == CAM_CDM_VIRTUAL) { + data->cdm_version.major = 1; + data->cdm_version.minor = 0; + data->cdm_version.incr = 0; + data->cdm_version.reserved = 0; + data->ops = cam_cdm_get_ops(0, + &data->cdm_version, true); + if (!data->ops) { + mutex_destroy(&client->lock); + mutex_lock(&cdm_hw->hw_mutex); + kfree(core->clients[idx]); + core->clients[idx] = NULL; + mutex_unlock( + &cdm_hw->hw_mutex); + rc = -EPERM; + CAM_ERR(CAM_CDM, "Invalid ops for virtual cdm"); + break; + } + } else { + data->cdm_version = core->version; + } + + cam_cdm_get_client_refcount(client); + mutex_lock(&client->lock); + memcpy(&client->data, data, + sizeof(struct cam_cdm_acquire_data)); + client->handle = CAM_CDM_CREATE_CLIENT_HANDLE( + core->index, + idx); + client->stream_on = false; + data->handle = client->handle; + CAM_DBG(CAM_CDM, "Acquired client=%s in hwidx=%d", + data->identifier, core->index); + mutex_unlock(&client->lock); + rc = 0; + break; + } + case CAM_CDM_HW_INTF_CMD_RELEASE: { + uint32_t *handle = cmd_args; + int idx; + struct cam_cdm_client *client; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=%x", + cmd, arg_size, *handle); + return -EINVAL; + } + idx = CAM_CDM_GET_CLIENT_IDX(*handle); + mutex_lock(&cdm_hw->hw_mutex); + client = core->clients[idx]; + if ((!client) || (*handle != client->handle)) { + CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", + client, *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + cam_cdm_put_client_refcount(client); + mutex_lock(&client->lock); + if (client->refcount != 0) { + CAM_ERR(CAM_CDM, "CDM Client refcount not zero %d", + client->refcount); + rc = -EPERM; + mutex_unlock(&client->lock); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + core->clients[idx] = NULL; + mutex_unlock(&client->lock); + mutex_destroy(&client->lock); + kfree(client); + mutex_unlock(&cdm_hw->hw_mutex); + rc = 0; + break; + } + case CAM_CDM_HW_INTF_CMD_RESET_HW: { + CAM_ERR(CAM_CDM, "CDM HW reset not supported for handle =%x", + *((uint32_t *)cmd_args)); + break; + } + default: + CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); + break; + } + return rc; +} diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h new file mode 100644 index 000000000000..8dcbe8ed1971 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CDM_CORE_COMMON_H_ +#define _CAM_CDM_CORE_COMMON_H_ + +#include "cam_mem_mgr.h" + +#define CAM_CDM170_VERSION 0x10000000 +#define CAM_CDM175_VERSION 0x10010000 +#define CAM_CDM480_VERSION 0x10020000 + +extern struct cam_cdm_utils_ops CDM170_ops; + +int cam_hw_cdm_init(void *hw_priv, void *init_hw_args, uint32_t arg_size); +int cam_hw_cdm_deinit(void *hw_priv, void *init_hw_args, uint32_t arg_size); +int cam_hw_cdm_alloc_genirq_mem(void *hw_priv); +int cam_hw_cdm_release_genirq_mem(void *hw_priv); +int cam_cdm_get_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size); +int cam_cdm_stream_ops_internal(void *hw_priv, void *start_args, + bool operation); +int cam_cdm_stream_start(void *hw_priv, void *start_args, uint32_t size); +int cam_cdm_stream_stop(void *hw_priv, void *start_args, uint32_t size); +int cam_cdm_process_cmd(void *hw_priv, uint32_t cmd, void *cmd_args, + uint32_t arg_size); +bool cam_cdm_set_cam_hw_version( + uint32_t ver, struct cam_hw_version *cam_version); +bool cam_cdm_cpas_cb(uint32_t client_handle, void *userdata, + struct cam_cpas_irq_data *irq_data); +struct cam_cdm_utils_ops *cam_cdm_get_ops( + uint32_t ver, struct cam_hw_version *cam_version, bool by_cam_version); +int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req, + struct cam_cdm_client *client); +int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req, + struct cam_cdm_client *client); +struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( + uint32_t tag, struct list_head *bl_list); +void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, + enum cam_cdm_cb_status status, void *data); + +#endif /* _CAM_CDM_CORE_COMMON_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c new file mode 100644 index 000000000000..40dba7352f32 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -0,0 +1,1135 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "cam_soc_util.h" +#include "cam_smmu_api.h" +#include "cam_cdm_intf_api.h" +#include "cam_cdm.h" +#include "cam_cdm_core_common.h" +#include "cam_cdm_soc.h" +#include "cam_io_util.h" +#include "cam_hw_cdm170_reg.h" + +#define CAM_HW_CDM_CPAS_0_NAME "qcom,cam170-cpas-cdm0" +#define CAM_HW_CDM_IPE_0_NAME "qcom,cam170-ipe0-cdm" +#define CAM_HW_CDM_IPE_1_NAME "qcom,cam170-ipe1-cdm" +#define CAM_HW_CDM_BPS_NAME "qcom,cam170-bps-cdm" + +#define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 + +static void cam_hw_cdm_work(struct work_struct *work); + +/* DT match table entry for all CDM variants*/ +static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { + { + .compatible = CAM_HW_CDM_CPAS_0_NAME, + .data = &cam170_cpas_cdm_offset_table, + }, + {} +}; + +static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) +{ + if (!strcmp(CAM_HW_CDM_CPAS_0_NAME, name)) + return CAM_CDM_CPAS_0; + + return CAM_CDM_MAX; +} + +int cam_hw_cdm_bl_fifo_pending_bl_rb(struct cam_hw_info *cdm_hw, + uint32_t *pending_bl) +{ + int rc = 0; + + if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB, + pending_bl)) { + CAM_ERR(CAM_CDM, "Failed to read CDM pending BL's"); + rc = -EIO; + } + + return rc; +} + +static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw, + bool enable) +{ + int rc = -EIO; + uint32_t irq_mask = 0; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + + if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_MASK, + &irq_mask)) { + CAM_ERR(CAM_CDM, "Failed to read CDM IRQ mask"); + return rc; + } + + if (enable == true) { + if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, + (irq_mask | 0x4))) { + CAM_ERR(CAM_CDM, "Write failed to enable BL done irq"); + } else { + atomic_inc(&core->bl_done); + rc = 0; + CAM_DBG(CAM_CDM, "BL done irq enabled =%d", + atomic_read(&core->bl_done)); + } + } else { + if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, + (irq_mask & 0x70003))) { + CAM_ERR(CAM_CDM, "Write failed to disable BL done irq"); + } else { + atomic_dec(&core->bl_done); + rc = 0; + CAM_DBG(CAM_CDM, "BL done irq disable =%d", + atomic_read(&core->bl_done)); + } + } + return rc; +} + +static int cam_hw_cdm_enable_core(struct cam_hw_info *cdm_hw, bool enable) +{ + int rc = 0; + + if (enable == true) { + if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x01)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW core enable"); + rc = -EIO; + } + } else { + if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x02)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW core disable"); + rc = -EIO; + } + } + return rc; +} + +int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) +{ + int rc = 0; + + if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0x10100)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); + rc = -EIO; + } + + return rc; +} + +int cam_hw_cdm_disable_core_dbg(struct cam_hw_info *cdm_hw) +{ + int rc = 0; + + if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); + rc = -EIO; + } + + return rc; +} + +void cam_hw_cdm_dump_scratch_registors(struct cam_hw_info *cdm_hw) +{ + uint32_t dump_reg = 0; + + cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg); + CAM_ERR(CAM_CDM, "dump core en=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_0_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch0=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_1_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch1=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_2_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch2=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_3_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch3=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_4_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch4=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_5_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch5=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_6_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch6=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_7_REG, &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch7=%x", dump_reg); + +} + +void cam_hw_cdm_dump_core_debug_registers( + struct cam_hw_info *cdm_hw) +{ + uint32_t dump_reg, core_dbg, loop_cnt; + + mutex_lock(&cdm_hw->hw_mutex); + cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW core status=%x", dump_reg); + /* First pause CDM, If it fails still proceed to dump debug info */ + cam_hw_cdm_enable_core(cdm_hw, false); + cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW current pending BL=%x", dump_reg); + loop_cnt = dump_reg; + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_DEBUG_STATUS, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, &core_dbg); + if (core_dbg & 0x100) { + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_LAST_AHB_ADDR, &dump_reg); + CAM_ERR(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_LAST_AHB_DATA, &dump_reg); + CAM_ERR(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); + } else { + CAM_ERR(CAM_CDM, "CDM HW AHB dump not enable"); + } + + if (core_dbg & 0x10000) { + int i; + + CAM_ERR(CAM_CDM, "CDM HW BL FIFO dump with loop count=%d", + loop_cnt); + for (i = 0 ; i < loop_cnt ; i++) { + cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_RB, i); + cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_BASE_RB, + &dump_reg); + CAM_ERR(CAM_CDM, "BL(%d) base addr =%x", i, dump_reg); + cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_LEN_RB, + &dump_reg); + CAM_ERR(CAM_CDM, "BL(%d) len=%d tag=%d", i, + (dump_reg & 0xFFFFF), (dump_reg & 0xFF000000)); + } + } else { + CAM_ERR(CAM_CDM, "CDM HW BL FIFO readback not enable"); + } + + CAM_ERR(CAM_CDM, "CDM HW default dump"); + cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_CFG, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW core cfg=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_STATUS, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW irq status=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_SET, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW irq set reg=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_BL_BASE, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW current BL base=%x", dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_BL_LEN, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW current BL len=%d tag=%d", + (dump_reg & 0xFFFFF), (dump_reg & 0xFF000000)); + + cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_USED_AHB_BASE, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); + + cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg); + CAM_ERR(CAM_CDM, "CDM HW current pending BL=%x", dump_reg); + + /* Enable CDM back */ + cam_hw_cdm_enable_core(cdm_hw, true); + mutex_unlock(&cdm_hw->hw_mutex); + +} + +int cam_hw_cdm_wait_for_bl_fifo(struct cam_hw_info *cdm_hw, + uint32_t bl_count) +{ + uint32_t pending_bl = 0; + int32_t available_bl_slots = 0; + int rc = -EIO; + long time_left; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + + do { + if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB, + &pending_bl)) { + CAM_ERR(CAM_CDM, "Failed to read CDM pending BL's"); + rc = -EIO; + break; + } + available_bl_slots = CAM_CDM_HWFIFO_SIZE - pending_bl; + if (available_bl_slots < 0) { + CAM_ERR(CAM_CDM, "Invalid available slots %d:%d:%d", + available_bl_slots, CAM_CDM_HWFIFO_SIZE, + pending_bl); + break; + } + if (bl_count < (available_bl_slots - 1)) { + CAM_DBG(CAM_CDM, + "BL slot available_cnt=%d requested=%d", + (available_bl_slots - 1), bl_count); + rc = bl_count; + break; + } else if (0 == (available_bl_slots - 1)) { + rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, true); + if (rc) { + CAM_ERR(CAM_CDM, "Enable BL done irq failed"); + break; + } + time_left = wait_for_completion_timeout( + &core->bl_complete, msecs_to_jiffies( + CAM_CDM_BL_FIFO_WAIT_TIMEOUT)); + if (time_left <= 0) { + CAM_ERR(CAM_CDM, + "CDM HW BL Wait timed out failed"); + if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, + false)) + CAM_ERR(CAM_CDM, + "Disable BL done irq failed"); + rc = -EIO; + break; + } + if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, false)) + CAM_ERR(CAM_CDM, "Disable BL done irq failed"); + rc = 0; + CAM_DBG(CAM_CDM, "CDM HW is ready for data"); + } else { + rc = (bl_count - (available_bl_slots - 1)); + break; + } + } while (1); + + return rc; +} + +bool cam_hw_cdm_bl_write(struct cam_hw_info *cdm_hw, uint32_t src, + uint32_t len, uint32_t tag) +{ + if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_BASE_REG, src)) { + CAM_ERR(CAM_CDM, "Failed to write CDM base to BL base"); + return true; + } + if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_LEN_REG, + ((len & 0xFFFFF) | ((tag & 0xFF) << 20)))) { + CAM_ERR(CAM_CDM, "Failed to write CDM BL len"); + return true; + } + return false; +} + +bool cam_hw_cdm_commit_bl_write(struct cam_hw_info *cdm_hw) +{ + if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_STORE_REG, 1)) { + CAM_ERR(CAM_CDM, "Failed to write CDM commit BL"); + return true; + } + return false; +} + +int cam_hw_cdm_submit_gen_irq(struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req) +{ + struct cam_cdm_bl_cb_request_entry *node; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + uint32_t len; + int rc; + + if (core->bl_tag > 63) { + CAM_ERR(CAM_CDM, "bl_tag invalid =%d", core->bl_tag); + rc = -EINVAL; + goto end; + } + CAM_DBG(CAM_CDM, "CDM write BL last cmd tag=%x total=%d cookie=%d", + core->bl_tag, req->data->cmd_arrary_count, req->data->cookie); + node = kzalloc(sizeof(struct cam_cdm_bl_cb_request_entry), + GFP_KERNEL); + if (!node) { + rc = -ENOMEM; + goto end; + } + node->request_type = CAM_HW_CDM_BL_CB_CLIENT; + node->client_hdl = req->handle; + node->cookie = req->data->cookie; + node->bl_tag = core->bl_tag; + node->userdata = req->data->userdata; + list_add_tail(&node->entry, &core->bl_request_list); + len = core->ops->cdm_required_size_genirq() * core->bl_tag; + core->ops->cdm_write_genirq(((uint32_t *)core->gen_irq.kmdvaddr + len), + core->bl_tag); + rc = cam_hw_cdm_bl_write(cdm_hw, (core->gen_irq.vaddr + (4*len)), + ((4 * core->ops->cdm_required_size_genirq()) - 1), + core->bl_tag); + if (rc) { + CAM_ERR(CAM_CDM, "CDM hw bl write failed for gen irq bltag=%d", + core->bl_tag); + list_del_init(&node->entry); + kfree(node); + rc = -EIO; + goto end; + } + + if (cam_hw_cdm_commit_bl_write(cdm_hw)) { + CAM_ERR(CAM_CDM, "Cannot commit the genirq BL with tag tag=%d", + core->bl_tag); + list_del_init(&node->entry); + kfree(node); + rc = -EIO; + } + +end: + return rc; +} + +int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req, + struct cam_cdm_client *client) +{ + int i, rc; + struct cam_cdm_bl_request *cdm_cmd = req->data; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + uint32_t pending_bl = 0; + int write_count = 0; + + if (req->data->cmd_arrary_count > CAM_CDM_HWFIFO_SIZE) { + pr_info("requested BL more than max size, cnt=%d max=%d", + req->data->cmd_arrary_count, CAM_CDM_HWFIFO_SIZE); + } + + if (atomic_read(&core->error)) + return -EIO; + + mutex_lock(&cdm_hw->hw_mutex); + mutex_lock(&client->lock); + rc = cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &pending_bl); + if (rc) { + CAM_ERR(CAM_CDM, "Cannot read the current BL depth"); + mutex_unlock(&client->lock); + mutex_unlock(&cdm_hw->hw_mutex); + return rc; + } + + for (i = 0; i < req->data->cmd_arrary_count ; i++) { + uint64_t hw_vaddr_ptr = 0; + size_t len = 0; + + if ((!cdm_cmd->cmd[i].len) && + (cdm_cmd->cmd[i].len > 0x100000)) { + CAM_ERR(CAM_CDM, + "cmd len(%d) is invalid cnt=%d total cnt=%d", + cdm_cmd->cmd[i].len, i, + req->data->cmd_arrary_count); + rc = -EINVAL; + break; + } + if (atomic_read(&core->error)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, + "In error state cnt=%d total cnt=%d\n", + i, req->data->cmd_arrary_count); + rc = -EIO; + break; + } + if (write_count == 0) { + write_count = cam_hw_cdm_wait_for_bl_fifo(cdm_hw, + (req->data->cmd_arrary_count - i)); + if (write_count < 0) { + CAM_ERR(CAM_CDM, + "wait for bl fifo failed %d:%d", + i, req->data->cmd_arrary_count); + rc = -EIO; + break; + } + } else { + write_count--; + } + + if (req->data->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE) { + rc = cam_mem_get_io_buf( + cdm_cmd->cmd[i].bl_addr.mem_handle, + core->iommu_hdl.non_secure, &hw_vaddr_ptr, + &len); + } else if (req->data->type == CAM_CDM_BL_CMD_TYPE_HW_IOVA) { + if (!cdm_cmd->cmd[i].bl_addr.hw_iova) { + CAM_ERR(CAM_CDM, + "Hw bl hw_iova is invalid %d:%d", + i, req->data->cmd_arrary_count); + rc = -EINVAL; + break; + } + rc = 0; + hw_vaddr_ptr = + (uint64_t)cdm_cmd->cmd[i].bl_addr.hw_iova; + len = cdm_cmd->cmd[i].len + cdm_cmd->cmd[i].offset; + } else { + CAM_ERR(CAM_CDM, + "Only mem hdl/hw va type is supported %d", + req->data->type); + rc = -EINVAL; + break; + } + + if ((!rc) && (hw_vaddr_ptr) && (len) && + (len >= cdm_cmd->cmd[i].offset)) { + CAM_DBG(CAM_CDM, "Got the HW VA"); + if (core->bl_tag >= + (CAM_CDM_HWFIFO_SIZE - 1)) + core->bl_tag = 0; + rc = cam_hw_cdm_bl_write(cdm_hw, + ((uint32_t)hw_vaddr_ptr + + cdm_cmd->cmd[i].offset), + (cdm_cmd->cmd[i].len - 1), core->bl_tag); + if (rc) { + CAM_ERR(CAM_CDM, "Hw bl write failed %d:%d", + i, req->data->cmd_arrary_count); + rc = -EIO; + break; + } + } else { + CAM_ERR(CAM_CDM, + "Sanity check failed for hdl=%x len=%zu:%d", + cdm_cmd->cmd[i].bl_addr.mem_handle, len, + cdm_cmd->cmd[i].offset); + CAM_ERR(CAM_CDM, "Sanity check failed for %d:%d", + i, req->data->cmd_arrary_count); + rc = -EINVAL; + break; + } + + if (!rc) { + CAM_DBG(CAM_CDM, + "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)) { + CAM_ERR(CAM_CDM, + "Cannot commit the BL %d tag=%d", + i, core->bl_tag); + rc = -EIO; + break; + } + CAM_DBG(CAM_CDM, "BL commit success BL %d tag=%d", i, + core->bl_tag); + core->bl_tag++; + if ((req->data->flag == true) && + (i == (req->data->cmd_arrary_count - + 1))) { + rc = cam_hw_cdm_submit_gen_irq( + cdm_hw, req); + if (rc == 0) + core->bl_tag++; + } + } + } + mutex_unlock(&client->lock); + mutex_unlock(&cdm_hw->hw_mutex); + return rc; + +} + +static void cam_hw_cdm_work(struct work_struct *work) +{ + struct cam_cdm_work_payload *payload; + struct cam_hw_info *cdm_hw; + struct cam_cdm *core; + + payload = container_of(work, struct cam_cdm_work_payload, work); + if (payload) { + cdm_hw = payload->hw; + core = (struct cam_cdm *)cdm_hw->core_info; + + 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, *tnode; + + CAM_DBG(CAM_CDM, "inline IRQ data=0x%x", + payload->irq_data); + mutex_lock(&cdm_hw->hw_mutex); + 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_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); + } + mutex_unlock(&cdm_hw->hw_mutex); + } + + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_INFO_RST_DONE_MASK) { + CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); + complete(&core->reset_complete); + } + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_INFO_BL_DONE_MASK) { + if (atomic_read(&core->bl_done)) { + CAM_DBG(CAM_CDM, "CDM HW BL done IRQ"); + complete(&core->bl_complete); + } + } + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { + CAM_ERR_RATE_LIMIT(CAM_CDM, + "Invalid command IRQ, Need HW reset\n"); + atomic_inc(&core->error); + cam_hw_cdm_dump_core_debug_registers(cdm_hw); + } + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) { + CAM_ERR_RATE_LIMIT(CAM_CDM, "AHB Error IRQ\n"); + atomic_inc(&core->error); + cam_hw_cdm_dump_core_debug_registers(cdm_hw); + atomic_dec(&core->error); + } + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK) { + CAM_ERR_RATE_LIMIT(CAM_CDM, "Overflow Error IRQ\n"); + atomic_inc(&core->error); + cam_hw_cdm_dump_core_debug_registers(cdm_hw); + atomic_dec(&core->error); + } + kfree(payload); + } else { + CAM_ERR(CAM_CDM, "NULL payload"); + } + +} + +static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, + struct device *dev, unsigned long iova, int flags, void *token, + uint32_t buf_info) +{ + struct cam_hw_info *cdm_hw = NULL; + struct cam_cdm *core = NULL; + + if (token) { + cdm_hw = (struct cam_hw_info *)token; + core = (struct cam_cdm *)cdm_hw->core_info; + atomic_inc(&core->error); + cam_hw_cdm_dump_core_debug_registers(cdm_hw); + CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n", + (void *)iova); + cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT, + (void *)iova); + atomic_dec(&core->error); + } else { + CAM_ERR(CAM_CDM, "Invalid token"); + } + +} + +irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) +{ + struct cam_hw_info *cdm_hw = data; + struct cam_cdm *cdm_core = cdm_hw->core_info; + struct cam_cdm_work_payload *payload; + bool work_status; + + CAM_DBG(CAM_CDM, "Got irq"); + payload = kzalloc(sizeof(struct cam_cdm_work_payload), GFP_ATOMIC); + if (payload) { + if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_STATUS, + &payload->irq_status)) { + CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status"); + } + if (!payload->irq_status) { + CAM_ERR_RATE_LIMIT(CAM_CDM, "Invalid irq received\n"); + kfree(payload); + return IRQ_HANDLED; + } + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) { + if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_USR_DATA, + &payload->irq_data)) { + CAM_ERR(CAM_CDM, + "Failed to read CDM HW IRQ data"); + } + } + CAM_DBG(CAM_CDM, "Got payload=%d", payload->irq_status); + payload->hw = cdm_hw; + INIT_WORK((struct work_struct *)&payload->work, + cam_hw_cdm_work); + if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_CLEAR, + payload->irq_status)) + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ Clear"); + if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_CLEAR_CMD, 0x01)) + 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=0x%x", + payload->irq_status); + kfree(payload); + } + } + + return IRQ_HANDLED; +} + +int cam_hw_cdm_alloc_genirq_mem(void *hw_priv) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_mem_mgr_request_desc genirq_alloc_cmd; + struct cam_mem_mgr_memory_desc genirq_alloc_out; + struct cam_cdm *cdm_core = NULL; + int rc = -EINVAL; + + if (!hw_priv) + return rc; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + genirq_alloc_cmd.align = 0; + genirq_alloc_cmd.size = (8 * CAM_CDM_HWFIFO_SIZE); + genirq_alloc_cmd.smmu_hdl = cdm_core->iommu_hdl.non_secure; + genirq_alloc_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE; + rc = cam_mem_mgr_request_mem(&genirq_alloc_cmd, + &genirq_alloc_out); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to get genirq cmd space rc=%d", rc); + goto end; + } + cdm_core->gen_irq.handle = genirq_alloc_out.mem_handle; + cdm_core->gen_irq.vaddr = (genirq_alloc_out.iova & 0xFFFFFFFF); + cdm_core->gen_irq.kmdvaddr = genirq_alloc_out.kva; + cdm_core->gen_irq.size = genirq_alloc_out.len; + +end: + return rc; +} + +int cam_hw_cdm_release_genirq_mem(void *hw_priv) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_cdm *cdm_core = NULL; + struct cam_mem_mgr_memory_desc genirq_release_cmd; + int rc = -EINVAL; + + if (!hw_priv) + return rc; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + genirq_release_cmd.mem_handle = cdm_core->gen_irq.handle; + rc = cam_mem_mgr_release_mem(&genirq_release_cmd); + if (rc) + CAM_ERR(CAM_CDM, "Failed to put genirq cmd space for hw"); + + return rc; +} + +int cam_hw_cdm_init(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_cdm *cdm_core = NULL; + int rc; + long time_left; + + if (!hw_priv) + return -EINVAL; + + soc_info = &cdm_hw->soc_info; + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, true); + if (rc) { + CAM_ERR(CAM_CDM, "Enable platform failed"); + goto end; + } + + CAM_DBG(CAM_CDM, "Enable soc done"); + +/* Before triggering the reset to HW, clear the reset complete */ + atomic_set(&cdm_core->error, 0); + atomic_set(&cdm_core->bl_done, 0); + reinit_completion(&cdm_core->reset_complete); + reinit_completion(&cdm_core->bl_complete); + + if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask"); + goto disable_return; + } + if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_RST_CMD, 0x9)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); + goto disable_return; + } + + CAM_DBG(CAM_CDM, "Waiting for CDM HW resetdone"); + time_left = wait_for_completion_timeout(&cdm_core->reset_complete, + msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); + + if (time_left <= 0) { + CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + goto disable_return; + } else { + CAM_DBG(CAM_CDM, "CDM Init success"); + cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; + cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003); + rc = 0; + goto end; + } + +disable_return: + rc = -EIO; + cam_soc_util_disable_platform_resource(soc_info, true, true); +end: + return rc; +} + +int cam_hw_cdm_deinit(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_cdm *cdm_core = NULL; + int rc = 0; + + if (!hw_priv) + return -EINVAL; + + soc_info = &cdm_hw->soc_info; + cdm_core = cdm_hw->core_info; + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_CDM, "disable platform failed"); + } else { + CAM_DBG(CAM_CDM, "CDM Deinit success"); + cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + } + + return rc; +} + +int cam_hw_cdm_probe(struct platform_device *pdev) +{ + int rc; + struct cam_hw_info *cdm_hw = NULL; + struct cam_hw_intf *cdm_hw_intf = NULL; + struct cam_cdm *cdm_core = NULL; + struct cam_cdm_private_dt_data *soc_private = NULL; + struct cam_cpas_register_params cpas_parms; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + cdm_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!cdm_hw_intf) + return -ENOMEM; + + cdm_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!cdm_hw) { + kfree(cdm_hw_intf); + return -ENOMEM; + } + + cdm_hw->core_info = kzalloc(sizeof(struct cam_cdm), GFP_KERNEL); + if (!cdm_hw->core_info) { + kfree(cdm_hw); + kfree(cdm_hw_intf); + return -ENOMEM; + } + + cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + cdm_hw->soc_info.pdev = pdev; + cdm_hw->soc_info.dev = &pdev->dev; + cdm_hw->soc_info.dev_name = pdev->name; + cdm_hw_intf->hw_type = CAM_HW_CDM; + cdm_hw->open_count = 0; + mutex_init(&cdm_hw->hw_mutex); + spin_lock_init(&cdm_hw->hw_lock); + init_completion(&cdm_hw->hw_complete); + + rc = cam_hw_cdm_soc_get_dt_properties(cdm_hw, msm_cam_hw_cdm_dt_match); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to get dt properties"); + goto release_mem; + } + cdm_hw_intf->hw_idx = cdm_hw->soc_info.index; + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + soc_private = (struct cam_cdm_private_dt_data *) + cdm_hw->soc_info.soc_private; + if (soc_private->dt_cdm_shared == true) + cdm_core->flags = CAM_CDM_FLAG_SHARED_CDM; + else + cdm_core->flags = CAM_CDM_FLAG_PRIVATE_CDM; + + cdm_core->bl_tag = 0; + cdm_core->id = cam_hw_cdm_get_id_by_name(cdm_core->name); + if (cdm_core->id >= CAM_CDM_MAX) { + CAM_ERR(CAM_CDM, "Failed to get CDM HW name for %s", + cdm_core->name); + goto release_private_mem; + } + INIT_LIST_HEAD(&cdm_core->bl_request_list); + init_completion(&cdm_core->reset_complete); + init_completion(&cdm_core->bl_complete); + cdm_hw_intf->hw_priv = cdm_hw; + cdm_hw_intf->hw_ops.get_hw_caps = cam_cdm_get_caps; + cdm_hw_intf->hw_ops.init = cam_hw_cdm_init; + cdm_hw_intf->hw_ops.deinit = cam_hw_cdm_deinit; + cdm_hw_intf->hw_ops.start = cam_cdm_stream_start; + cdm_hw_intf->hw_ops.stop = cam_cdm_stream_stop; + cdm_hw_intf->hw_ops.read = NULL; + cdm_hw_intf->hw_ops.write = NULL; + cdm_hw_intf->hw_ops.process_cmd = cam_cdm_process_cmd; + mutex_lock(&cdm_hw->hw_mutex); + + CAM_DBG(CAM_CDM, "type %d index %d", cdm_hw_intf->hw_type, + cdm_hw_intf->hw_idx); + + platform_set_drvdata(pdev, cdm_hw_intf); + + rc = cam_smmu_get_handle("cpas-cdm0", &cdm_core->iommu_hdl.non_secure); + if (rc < 0) { + CAM_ERR(CAM_CDM, "cpas-cdm get iommu handle failed"); + goto unlock_release_mem; + } + cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, + cam_hw_cdm_iommu_fault_handler, cdm_hw); + + cdm_core->iommu_hdl.secure = -1; + + cdm_core->work_queue = alloc_workqueue(cdm_core->name, + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, + CAM_CDM_INFLIGHT_WORKS); + + rc = cam_soc_util_request_platform_resource(&cdm_hw->soc_info, + cam_hw_cdm_irq, cdm_hw); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to request platform resource"); + goto destroy_non_secure_hdl; + } + + cpas_parms.cam_cpas_client_cb = cam_cdm_cpas_cb; + cpas_parms.cell_index = cdm_hw->soc_info.index; + cpas_parms.dev = &pdev->dev; + cpas_parms.userdata = cdm_hw_intf; + strlcpy(cpas_parms.identifier, "cpas-cdm", CAM_HW_IDENTIFIER_LENGTH); + rc = cam_cpas_register_client(&cpas_parms); + if (rc) { + CAM_ERR(CAM_CDM, "Virtual CDM CPAS registration failed"); + goto release_platform_resource; + } + CAM_DBG(CAM_CDM, "CPAS registration successful handle=%d", + cpas_parms.client_handle); + cdm_core->cpas_handle = cpas_parms.client_handle; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(cdm_core->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_CDM, "CPAS start failed"); + goto cpas_unregister; + } + + rc = cam_hw_cdm_init(cdm_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to Init CDM HW"); + goto cpas_stop; + } + cdm_hw->open_count++; + + if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_HW_VERSION, + &cdm_core->hw_version)) { + CAM_ERR(CAM_CDM, "Failed to read CDM HW Version"); + goto deinit; + } + + if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_TITAN_VERSION, + &cdm_core->hw_family_version)) { + CAM_ERR(CAM_CDM, "Failed to read CDM family Version"); + goto deinit; + } + + CAM_DBG(CAM_CDM, "CDM Hw version read success family =%x hw =%x", + cdm_core->hw_family_version, cdm_core->hw_version); + cdm_core->ops = cam_cdm_get_ops(cdm_core->hw_version, NULL, + false); + if (!cdm_core->ops) { + CAM_ERR(CAM_CDM, "Failed to util ops for hw"); + goto deinit; + } + + if (!cam_cdm_set_cam_hw_version(cdm_core->hw_version, + &cdm_core->version)) { + CAM_ERR(CAM_CDM, "Failed to set cam he version for hw"); + goto deinit; + } + + rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to Deinit CDM HW"); + cdm_hw->open_count--; + goto cpas_stop; + } + + rc = cam_cpas_stop(cdm_core->cpas_handle); + if (rc) { + CAM_ERR(CAM_CDM, "CPAS stop failed"); + cdm_hw->open_count--; + goto cpas_unregister; + } + + rc = cam_cdm_intf_register_hw_cdm(cdm_hw_intf, + soc_private, CAM_HW_CDM, &cdm_core->index); + if (rc) { + CAM_ERR(CAM_CDM, "HW CDM Interface registration failed"); + cdm_hw->open_count--; + goto cpas_unregister; + } + cdm_hw->open_count--; + mutex_unlock(&cdm_hw->hw_mutex); + + CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx); + + return rc; + +deinit: + if (cam_hw_cdm_deinit(cdm_hw, NULL, 0)) + CAM_ERR(CAM_CDM, "Deinit failed for hw"); + cdm_hw->open_count--; +cpas_stop: + if (cam_cpas_stop(cdm_core->cpas_handle)) + CAM_ERR(CAM_CDM, "CPAS stop failed"); +cpas_unregister: + if (cam_cpas_unregister_client(cdm_core->cpas_handle)) + CAM_ERR(CAM_CDM, "CPAS unregister failed"); +release_platform_resource: + if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info)) + CAM_ERR(CAM_CDM, "Release platform resource failed"); + + flush_workqueue(cdm_core->work_queue); + destroy_workqueue(cdm_core->work_queue); +destroy_non_secure_hdl: + cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, + NULL, cdm_hw); + if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) + CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); +unlock_release_mem: + mutex_unlock(&cdm_hw->hw_mutex); +release_private_mem: + kfree(cdm_hw->soc_info.soc_private); +release_mem: + mutex_destroy(&cdm_hw->hw_mutex); + kfree(cdm_hw_intf); + kfree(cdm_hw->core_info); + kfree(cdm_hw); + return rc; +} + +int cam_hw_cdm_remove(struct platform_device *pdev) +{ + int rc = -EBUSY; + struct cam_hw_info *cdm_hw = NULL; + struct cam_hw_intf *cdm_hw_intf = NULL; + struct cam_cdm *cdm_core = NULL; + + cdm_hw_intf = platform_get_drvdata(pdev); + if (!cdm_hw_intf) { + CAM_ERR(CAM_CDM, "Failed to get dev private data"); + return rc; + } + + cdm_hw = cdm_hw_intf->hw_priv; + if (!cdm_hw) { + CAM_ERR(CAM_CDM, + "Failed to get hw private data for type=%d idx=%d", + cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx); + return rc; + } + + cdm_core = cdm_hw->core_info; + if (!cdm_core) { + CAM_ERR(CAM_CDM, + "Failed to get hw core data for type=%d idx=%d", + cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx); + return rc; + } + + if (cdm_hw->open_count != 0) { + CAM_ERR(CAM_CDM, "Hw open count invalid type=%d idx=%d cnt=%d", + cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx, + cdm_hw->open_count); + return rc; + } + + rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "Deinit failed for hw"); + return rc; + } + + rc = cam_cpas_unregister_client(cdm_core->cpas_handle); + if (rc) { + CAM_ERR(CAM_CDM, "CPAS unregister failed"); + return rc; + } + + if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info)) + CAM_ERR(CAM_CDM, "Release platform resource failed"); + + flush_workqueue(cdm_core->work_queue); + destroy_workqueue(cdm_core->work_queue); + + if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) + CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); + cam_smmu_unset_client_page_fault_handler( + cdm_core->iommu_hdl.non_secure, cdm_hw); + + mutex_destroy(&cdm_hw->hw_mutex); + kfree(cdm_hw->soc_info.soc_private); + kfree(cdm_hw_intf); + kfree(cdm_hw->core_info); + kfree(cdm_hw); + + return 0; +} + +static struct platform_driver cam_hw_cdm_driver = { + .probe = cam_hw_cdm_probe, + .remove = cam_hw_cdm_remove, + .driver = { + .name = "msm_cam_cdm", + .owner = THIS_MODULE, + .of_match_table = msm_cam_hw_cdm_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_hw_cdm_init_module(void) +{ + return platform_driver_register(&cam_hw_cdm_driver); +} + +static void __exit cam_hw_cdm_exit_module(void) +{ + platform_driver_unregister(&cam_hw_cdm_driver); +} + +module_init(cam_hw_cdm_init_module); +module_exit(cam_hw_cdm_exit_module); +MODULE_DESCRIPTION("MSM Camera HW CDM driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c new file mode 100644 index 000000000000..94e2f36d0544 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_cdm_intf_api.h" +#include "cam_cdm.h" +#include "cam_cdm_virtual.h" +#include "cam_soc_util.h" +#include "cam_cdm_soc.h" + +static struct cam_cdm_intf_mgr cdm_mgr; +static DEFINE_MUTEX(cam_cdm_mgr_lock); + +static const struct of_device_id msm_cam_cdm_intf_dt_match[] = { + { .compatible = "qcom,cam-cdm-intf", }, + {} +}; + +static int get_cdm_mgr_refcount(void) +{ + int rc = 0; + + mutex_lock(&cam_cdm_mgr_lock); + if (cdm_mgr.probe_done == false) { + CAM_ERR(CAM_CDM, "CDM intf mgr not probed yet"); + rc = -EPERM; + } else { + CAM_DBG(CAM_CDM, "CDM intf mgr get refcount=%d", + cdm_mgr.refcount); + cdm_mgr.refcount++; + } + mutex_unlock(&cam_cdm_mgr_lock); + return rc; +} + +static void put_cdm_mgr_refcount(void) +{ + mutex_lock(&cam_cdm_mgr_lock); + if (cdm_mgr.probe_done == false) { + CAM_ERR(CAM_CDM, "CDM intf mgr not probed yet"); + } else { + CAM_DBG(CAM_CDM, "CDM intf mgr put refcount=%d", + cdm_mgr.refcount); + if (cdm_mgr.refcount > 0) { + cdm_mgr.refcount--; + } else { + CAM_ERR(CAM_CDM, "Refcount put when zero"); + WARN_ON(1); + } + } + mutex_unlock(&cam_cdm_mgr_lock); +} + +static int get_cdm_iommu_handle(struct cam_iommu_handle *cdm_handles, + uint32_t hw_idx) +{ + int rc = -EPERM; + struct cam_hw_intf *hw = cdm_mgr.nodes[hw_idx].device; + + if (hw->hw_ops.get_hw_caps) { + rc = hw->hw_ops.get_hw_caps(hw->hw_priv, cdm_handles, + sizeof(struct cam_iommu_handle)); + } + + return rc; +} + +static int get_cdm_index_by_id(char *identifier, + uint32_t cell_index, uint32_t *hw_index) +{ + int rc = -EPERM, i, j; + char client_name[128]; + + CAM_DBG(CAM_CDM, "Looking for HW id of =%s and index=%d", + identifier, cell_index); + snprintf(client_name, sizeof(client_name), "%s", identifier); + CAM_DBG(CAM_CDM, "Looking for HW id of %s count:%d", client_name, + cdm_mgr.cdm_count); + mutex_lock(&cam_cdm_mgr_lock); + for (i = 0; i < cdm_mgr.cdm_count; i++) { + mutex_lock(&cdm_mgr.nodes[i].lock); + CAM_DBG(CAM_CDM, "dt_num_supported_clients=%d", + cdm_mgr.nodes[i].data->dt_num_supported_clients); + + for (j = 0; j < + cdm_mgr.nodes[i].data->dt_num_supported_clients; j++) { + CAM_DBG(CAM_CDM, "client name:%s", + cdm_mgr.nodes[i].data->dt_cdm_client_name[j]); + if (!strcmp( + cdm_mgr.nodes[i].data->dt_cdm_client_name[j], + client_name)) { + rc = 0; + *hw_index = i; + break; + } + } + mutex_unlock(&cdm_mgr.nodes[i].lock); + if (rc == 0) + break; + } + mutex_unlock(&cam_cdm_mgr_lock); + + return rc; +} + +int cam_cdm_get_iommu_handle(char *identifier, + struct cam_iommu_handle *cdm_handles) +{ + int i, j, rc = -EPERM; + + if ((!identifier) || (!cdm_handles)) + return -EINVAL; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + return rc; + } + CAM_DBG(CAM_CDM, "Looking for Iommu handle of %s", identifier); + + for (i = 0; i < cdm_mgr.cdm_count; i++) { + mutex_lock(&cdm_mgr.nodes[i].lock); + if (!cdm_mgr.nodes[i].data) { + mutex_unlock(&cdm_mgr.nodes[i].lock); + continue; + } + for (j = 0; j < + cdm_mgr.nodes[i].data->dt_num_supported_clients; + j++) { + if (!strcmp( + cdm_mgr.nodes[i].data->dt_cdm_client_name[j], + identifier)) { + rc = get_cdm_iommu_handle(cdm_handles, i); + break; + } + } + mutex_unlock(&cdm_mgr.nodes[i].lock); + if (rc == 0) + break; + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_get_iommu_handle); + +int cam_cdm_acquire(struct cam_cdm_acquire_data *data) +{ + int rc = -EPERM; + struct cam_hw_intf *hw; + uint32_t hw_index = 0; + + if ((!data) || (!data->base_array_cnt)) + return -EINVAL; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + return rc; + } + + if (data->id > CAM_CDM_HW_ANY) { + CAM_ERR(CAM_CDM, + "only CAM_CDM_VIRTUAL/CAM_CDM_HW_ANY is supported"); + rc = -EPERM; + goto end; + } + rc = get_cdm_index_by_id(data->identifier, data->cell_index, + &hw_index); + if ((rc < 0) && (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM)) { + CAM_ERR(CAM_CDM, "Failed to identify associated hw id"); + goto end; + } else { + CAM_DBG(CAM_CDM, "hw_index:%d", hw_index); + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) { + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_ACQUIRE, data, + sizeof(struct cam_cdm_acquire_data)); + if (rc < 0) { + CAM_ERR(CAM_CDM, "CDM hw acquire failed"); + goto end; + } + } else { + CAM_ERR(CAM_CDM, "idx %d doesn't have acquire ops", + hw_index); + rc = -EPERM; + } + } +end: + if (rc < 0) { + CAM_ERR(CAM_CDM, "CDM acquire failed for id=%d name=%s, idx=%d", + data->id, data->identifier, data->cell_index); + put_cdm_mgr_refcount(); + } + return rc; +} +EXPORT_SYMBOL(cam_cdm_acquire); + +int cam_cdm_release(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EPERM; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) { + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_RELEASE, &handle, + sizeof(handle)); + if (rc < 0) + CAM_ERR(CAM_CDM, + "hw release failed for handle=%x", + handle); + } else + CAM_ERR(CAM_CDM, "hw idx %d doesn't have release ops", + hw_index); + } + put_cdm_mgr_refcount(); + if (rc == 0) + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_release); + + +int cam_cdm_submit_bls(uint32_t handle, struct cam_cdm_bl_request *data) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (!data) + return rc; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + struct cam_cdm_hw_intf_cmd_submit_bl req; + + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) { + req.data = data; + req.handle = handle; + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_SUBMIT_BL, &req, + sizeof(struct cam_cdm_hw_intf_cmd_submit_bl)); + if (rc < 0) + CAM_ERR(CAM_CDM, + "hw submit bl failed for handle=%x", + handle); + } else { + CAM_ERR(CAM_CDM, "hw idx %d doesn't have submit ops", + hw_index); + } + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_submit_bls); + +int cam_cdm_stream_on(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.start) { + rc = hw->hw_ops.start(hw->hw_priv, &handle, + sizeof(uint32_t)); + if (rc < 0) + CAM_ERR(CAM_CDM, + "hw start failed handle=%x", + handle); + } else { + CAM_ERR(CAM_CDM, + "hw idx %d doesn't have start ops", + hw_index); + } + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_stream_on); + +int cam_cdm_stream_off(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.stop) { + rc = hw->hw_ops.stop(hw->hw_priv, &handle, + sizeof(uint32_t)); + if (rc < 0) + CAM_ERR(CAM_CDM, "hw stop failed handle=%x", + handle); + } else { + CAM_ERR(CAM_CDM, "hw idx %d doesn't have stop ops", + hw_index); + } + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_stream_off); + +int cam_cdm_reset_hw(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) { + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_RESET_HW, &handle, + sizeof(handle)); + if (rc < 0) + CAM_ERR(CAM_CDM, + "CDM hw release failed for handle=%x", + handle); + } else { + CAM_ERR(CAM_CDM, "hw idx %d doesn't have release ops", + hw_index); + } + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_reset_hw); + +int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, + struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, + uint32_t *index) +{ + int rc = -EINVAL; + + if ((!hw) || (!data) || (!index)) + return rc; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + return rc; + } + + mutex_lock(&cam_cdm_mgr_lock); + if ((type == CAM_VIRTUAL_CDM) && + (!cdm_mgr.nodes[CAM_SW_CDM_INDEX].device)) { + mutex_lock(&cdm_mgr.nodes[CAM_SW_CDM_INDEX].lock); + cdm_mgr.nodes[CAM_SW_CDM_INDEX].device = hw; + cdm_mgr.nodes[CAM_SW_CDM_INDEX].data = data; + *index = cdm_mgr.cdm_count; + mutex_unlock(&cdm_mgr.nodes[CAM_SW_CDM_INDEX].lock); + cdm_mgr.cdm_count++; + rc = 0; + } else if ((type == CAM_HW_CDM) && (cdm_mgr.cdm_count > 0)) { + mutex_lock(&cdm_mgr.nodes[cdm_mgr.cdm_count].lock); + cdm_mgr.nodes[cdm_mgr.cdm_count].device = hw; + cdm_mgr.nodes[cdm_mgr.cdm_count].data = data; + *index = cdm_mgr.cdm_count; + mutex_unlock(&cdm_mgr.nodes[cdm_mgr.cdm_count].lock); + cdm_mgr.cdm_count++; + rc = 0; + } else { + CAM_ERR(CAM_CDM, "CDM registration failed type=%d count=%d", + type, cdm_mgr.cdm_count); + } + mutex_unlock(&cam_cdm_mgr_lock); + put_cdm_mgr_refcount(); + + return rc; +} + +int cam_cdm_intf_deregister_hw_cdm(struct cam_hw_intf *hw, + struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, + uint32_t index) +{ + int rc = -EINVAL; + + if ((!hw) || (!data)) + return rc; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + mutex_lock(&cam_cdm_mgr_lock); + if ((type == CAM_VIRTUAL_CDM) && + (hw == cdm_mgr.nodes[CAM_SW_CDM_INDEX].device) && + (index == CAM_SW_CDM_INDEX)) { + mutex_lock(&cdm_mgr.nodes[cdm_mgr.cdm_count].lock); + cdm_mgr.nodes[CAM_SW_CDM_INDEX].device = NULL; + cdm_mgr.nodes[CAM_SW_CDM_INDEX].data = NULL; + mutex_unlock(&cdm_mgr.nodes[cdm_mgr.cdm_count].lock); + rc = 0; + } else if ((type == CAM_HW_CDM) && + (hw == cdm_mgr.nodes[index].device)) { + mutex_lock(&cdm_mgr.nodes[index].lock); + cdm_mgr.nodes[index].device = NULL; + cdm_mgr.nodes[index].data = NULL; + mutex_unlock(&cdm_mgr.nodes[index].lock); + cdm_mgr.cdm_count--; + rc = 0; + } else { + CAM_ERR(CAM_CDM, "CDM Deregistration failed type=%d index=%d", + type, index); + } + mutex_unlock(&cam_cdm_mgr_lock); + put_cdm_mgr_refcount(); + + return rc; +} + +static int cam_cdm_intf_probe(struct platform_device *pdev) +{ + int i, rc; + + rc = cam_cdm_intf_mgr_soc_get_dt_properties(pdev, &cdm_mgr); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to get dt properties"); + return rc; + } + mutex_lock(&cam_cdm_mgr_lock); + for (i = 0 ; i < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM; i++) { + mutex_init(&cdm_mgr.nodes[i].lock); + cdm_mgr.nodes[i].device = NULL; + cdm_mgr.nodes[i].data = NULL; + cdm_mgr.nodes[i].refcount = 0; + } + cdm_mgr.probe_done = true; + cdm_mgr.refcount = 0; + mutex_unlock(&cam_cdm_mgr_lock); + rc = cam_virtual_cdm_probe(pdev); + if (rc) { + mutex_lock(&cam_cdm_mgr_lock); + cdm_mgr.probe_done = false; + for (i = 0 ; i < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM; i++) { + if (cdm_mgr.nodes[i].device || cdm_mgr.nodes[i].data || + (cdm_mgr.nodes[i].refcount != 0)) + CAM_ERR(CAM_CDM, + "Valid node present in index=%d", i); + mutex_destroy(&cdm_mgr.nodes[i].lock); + cdm_mgr.nodes[i].device = NULL; + cdm_mgr.nodes[i].data = NULL; + cdm_mgr.nodes[i].refcount = 0; + } + mutex_unlock(&cam_cdm_mgr_lock); + } + + CAM_DBG(CAM_CDM, "CDM Intf probe done"); + + return rc; +} + +static int cam_cdm_intf_remove(struct platform_device *pdev) +{ + int i, rc = -EBUSY; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + return rc; + } + + if (cam_virtual_cdm_remove(pdev)) { + CAM_ERR(CAM_CDM, "Virtual CDM remove failed"); + goto end; + } + put_cdm_mgr_refcount(); + + mutex_lock(&cam_cdm_mgr_lock); + if (cdm_mgr.refcount != 0) { + CAM_ERR(CAM_CDM, "cdm manger refcount not zero %d", + cdm_mgr.refcount); + goto end; + } + + for (i = 0 ; i < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM; i++) { + if (cdm_mgr.nodes[i].device || cdm_mgr.nodes[i].data || + (cdm_mgr.nodes[i].refcount != 0)) { + CAM_ERR(CAM_CDM, "Valid node present in index=%d", i); + mutex_unlock(&cam_cdm_mgr_lock); + goto end; + } + mutex_destroy(&cdm_mgr.nodes[i].lock); + cdm_mgr.nodes[i].device = NULL; + cdm_mgr.nodes[i].data = NULL; + cdm_mgr.nodes[i].refcount = 0; + } + cdm_mgr.probe_done = false; + rc = 0; + +end: + mutex_unlock(&cam_cdm_mgr_lock); + return rc; +} + +static struct platform_driver cam_cdm_intf_driver = { + .probe = cam_cdm_intf_probe, + .remove = cam_cdm_intf_remove, + .driver = { + .name = "msm_cam_cdm_intf", + .owner = THIS_MODULE, + .of_match_table = msm_cam_cdm_intf_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_cdm_intf_init_module(void) +{ + return platform_driver_register(&cam_cdm_intf_driver); +} + +static void __exit cam_cdm_intf_exit_module(void) +{ + platform_driver_unregister(&cam_cdm_intf_driver); +} + +module_init(cam_cdm_intf_init_module); +module_exit(cam_cdm_intf_exit_module); +MODULE_DESCRIPTION("MSM Camera CDM Intf driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h new file mode 100644 index 000000000000..3e89b22b1b18 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CDM_API_H_ +#define _CAM_CDM_API_H_ + +#include +#include "cam_cdm_util.h" +#include "cam_soc_util.h" + +/* enum cam_cdm_id - Enum for possible CAM CDM hardwares */ +enum cam_cdm_id { + CAM_CDM_VIRTUAL, + CAM_CDM_HW_ANY, + CAM_CDM_CPAS_0, + CAM_CDM_IPE0, + CAM_CDM_IPE1, + CAM_CDM_BPS, + CAM_CDM_VFE, + CAM_CDM_MAX +}; + +/* enum cam_cdm_cb_status - Enum for possible CAM CDM callback */ +enum cam_cdm_cb_status { + CAM_CDM_CB_STATUS_BL_SUCCESS, + CAM_CDM_CB_STATUS_INVALID_BL_CMD, + CAM_CDM_CB_STATUS_PAGEFAULT, + CAM_CDM_CB_STATUS_HW_RESET_ONGOING, + CAM_CDM_CB_STATUS_HW_RESET_DONE, + CAM_CDM_CB_STATUS_UNKNOWN_ERROR, +}; + +/* enum cam_cdm_bl_cmd_addr_type - Enum for possible CDM bl cmd addr types */ +enum cam_cdm_bl_cmd_addr_type { + CAM_CDM_BL_CMD_TYPE_MEM_HANDLE, + CAM_CDM_BL_CMD_TYPE_HW_IOVA, + CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA, +}; + +/** + * struct cam_cdm_acquire_data - Cam CDM acquire data structure + * + * @identifier : Input identifier string which is the device label from dt + * like vfe, ife, jpeg etc + * @cell_index : Input integer identifier pointing to the cell index from dt + * of the device. This can be used to form a unique string + * with @identifier like vfe0, ife1, jpeg0 etc + * @id : ID of a specific or any CDM HW which needs to be acquired. + * @userdata : Input private data which will be returned as part + * of callback. + * @cam_cdm_callback : Input callback pointer for triggering the + * callbacks from CDM driver + * @handle : CDM Client handle + * @userdata : Private data given at the time of acquire + * @status : Callback status + * @cookie : Cookie if the callback is gen irq status + * @base_array_cnt : Input number of ioremapped address pair pointing + * in base_array, needed only if selected cdm is a virtual. + * @base_array : Input pointer to ioremapped address pair arrary + * needed only if selected cdm is a virtual. + * @cdm_version : CDM version is output while acquiring HW cdm and + * it is Input while acquiring virtual cdm, Currently fixing it + * to one version below acquire API. + * @ops : Output pointer updated by cdm driver to the CDM + * util ops for this HW version of CDM acquired. + * @handle : Output Unique handle generated for this acquire + * + */ +struct cam_cdm_acquire_data { + char identifier[128]; + uint32_t cell_index; + enum cam_cdm_id id; + void *userdata; + void (*cam_cdm_callback)(uint32_t handle, void *userdata, + enum cam_cdm_cb_status status, uint64_t cookie); + uint32_t base_array_cnt; + struct cam_soc_reg_map *base_array[CAM_SOC_MAX_BLOCK]; + struct cam_hw_version cdm_version; + struct cam_cdm_utils_ops *ops; + uint32_t handle; +}; + +/** + * struct cam_cdm_bl_cmd - Cam CDM HW bl command + * + * @bl_addr : Union of all three type for CDM BL commands + * @mem_handle : Input mem handle of bl cmd + * @offset : Input offset of the actual bl cmd in the memory pointed + * by mem_handle + * @len : Input length of the BL command, Cannot be more than 1MB and + * this is will be validated with offset+size of the memory pointed + * by mem_handle + * + */ +struct cam_cdm_bl_cmd { + union { + int32_t mem_handle; + uint32_t *hw_iova; + uintptr_t kernel_iova; + } bl_addr; + uint32_t offset; + uint32_t len; +}; + +/** + * struct cam_cdm_bl_request - Cam CDM HW base & length (BL) request + * + * @flag : 1 for callback needed and 0 for no callback when this BL + * request is done + * @userdata :Input private data which will be returned as part + * of callback if request for this bl request in flags. + * @cookie : Cookie if the callback is gen irq status + * @type : type of the submitted bl cmd address. + * @cmd_arrary_count : Input number of BL commands to be submitted to CDM + * @bl_cmd_array : Input payload holding the BL cmd's arrary + * to be sumbitted. + * + */ +struct cam_cdm_bl_request { + int flag; + void *userdata; + uint64_t cookie; + enum cam_cdm_bl_cmd_addr_type type; + uint32_t cmd_arrary_count; + struct cam_cdm_bl_cmd cmd[1]; +}; + +/** + * @brief : API to get the CDM capabilities for a camera device type + * + * @identifier : Input pointer to a string which is the device label from dt + * like vfe, ife, jpeg etc, We do not need cell index + * assuming all devices of a single type maps to one SMMU + * client + * @cdm_handles : Input iommu handle memory pointer to update handles + * + * @return 0 on success + */ +int cam_cdm_get_iommu_handle(char *identifier, + struct cam_iommu_handle *cdm_handles); + +/** + * @brief : API to acquire a CDM + * + * @data : Input data for the CDM to be acquired + * + * @return 0 on success + */ +int cam_cdm_acquire(struct cam_cdm_acquire_data *data); + +/** + * @brief : API to release a previously acquired CDM + * + * @handle : Input handle for the CDM to be released + * + * @return 0 on success + */ +int cam_cdm_release(uint32_t handle); + +/** + * @brief : API to submit the base & length (BL's) for acquired CDM + * + * @handle : Input cdm handle to which the BL's needs to be sumbitted. + * @data : Input pointer to the BL's to be sumbitted + * + * @return 0 on success + */ +int cam_cdm_submit_bls(uint32_t handle, struct cam_cdm_bl_request *data); + +/** + * @brief : API to stream ON a previously acquired CDM, + * during this we turn on/off clocks/power based on active clients. + * + * @handle : Input handle for the CDM to be released + * + * @return 0 on success + */ +int cam_cdm_stream_on(uint32_t handle); + +/** + * @brief : API to stream OFF a previously acquired CDM, + * during this we turn on/off clocks/power based on active clients. + * + * @handle : Input handle for the CDM to be released + * + * @return 0 on success + */ +int cam_cdm_stream_off(uint32_t handle); + +/** + * @brief : API to reset previously acquired CDM, + * this can be only performed only the CDM is private. + * + * @handle : Input handle of the CDM to reset + * + * @return 0 on success + */ +int cam_cdm_reset_hw(uint32_t handle); + +#endif /* _CAM_CDM_API_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_soc.c b/drivers/cam_cdm/cam_cdm_soc.c new file mode 100644 index 000000000000..2fb5d5fe97b9 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_soc.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_soc_util.h" +#include "cam_smmu_api.h" +#include "cam_cdm.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" + +#define CAM_CDM_OFFSET_FROM_REG(x, y) ((x)->offsets[y].offset) +#define CAM_CDM_ATTR_FROM_REG(x, y) ((x)->offsets[y].attribute) + +bool cam_cdm_read_hw_reg(struct cam_hw_info *cdm_hw, + enum cam_cdm_regs reg, uint32_t *value) +{ + void __iomem *reg_addr; + struct cam_cdm *cdm = (struct cam_cdm *)cdm_hw->core_info; + void __iomem *base = + cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].mem_base; + resource_size_t mem_len = + cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size; + + CAM_DBG(CAM_CDM, "E: b=%pK blen=%d reg=%x off=%x", (void __iomem *)base, + (int)mem_len, reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, + reg))); + CAM_DBG(CAM_CDM, "E: b=%pK reg=%x off=%x", (void __iomem *)base, + reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg))); + + if ((reg > cdm->offset_tbl->offset_max_size) || + (reg > cdm->offset_tbl->last_offset)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, "Invalid reg=%d\n", reg); + goto permission_error; + } else { + reg_addr = (base + (CAM_CDM_OFFSET_FROM_REG( + cdm->offset_tbl, reg))); + if (reg_addr > (base + mem_len)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, + "Invalid mapped region %d", reg); + goto permission_error; + } + *value = cam_io_r_mb(reg_addr); + CAM_DBG(CAM_CDM, "X b=%pK reg=%x off=%x val=%x", + (void __iomem *)base, reg, + (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)), + *value); + return false; + } +permission_error: + *value = 0; + return true; + +} + +bool cam_cdm_write_hw_reg(struct cam_hw_info *cdm_hw, + enum cam_cdm_regs reg, uint32_t value) +{ + void __iomem *reg_addr; + struct cam_cdm *cdm = (struct cam_cdm *)cdm_hw->core_info; + void __iomem *base = + cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].mem_base; + resource_size_t mem_len = + cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size; + + CAM_DBG(CAM_CDM, "E: b=%pK reg=%x off=%x val=%x", (void __iomem *)base, + reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)), value); + + if ((reg > cdm->offset_tbl->offset_max_size) || + (reg > cdm->offset_tbl->last_offset)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, "CDM accessing invalid reg=%d\n", + reg); + goto permission_error; + } else { + reg_addr = (base + CAM_CDM_OFFSET_FROM_REG( + cdm->offset_tbl, reg)); + if (reg_addr > (base + mem_len)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, + "Accessing invalid region %d:%d\n", + reg, (CAM_CDM_OFFSET_FROM_REG( + cdm->offset_tbl, reg))); + goto permission_error; + } + cam_io_w_mb(value, reg_addr); + return false; + } +permission_error: + return true; + +} + +int cam_cdm_soc_load_dt_private(struct platform_device *pdev, + struct cam_cdm_private_dt_data *ptr) +{ + int i, rc = -EINVAL; + + ptr->dt_num_supported_clients = of_property_count_strings( + pdev->dev.of_node, + "cdm-client-names"); + CAM_DBG(CAM_CDM, "Num supported cdm_client = %d", + ptr->dt_num_supported_clients); + if (ptr->dt_num_supported_clients > + CAM_PER_CDM_MAX_REGISTERED_CLIENTS) { + CAM_ERR(CAM_CDM, "Invalid count of client names count=%d", + ptr->dt_num_supported_clients); + rc = -EINVAL; + return rc; + } + if (ptr->dt_num_supported_clients < 0) { + CAM_DBG(CAM_CDM, "No cdm client names found"); + ptr->dt_num_supported_clients = 0; + ptr->dt_cdm_shared = false; + } else { + ptr->dt_cdm_shared = true; + } + for (i = 0; i < ptr->dt_num_supported_clients; i++) { + rc = of_property_read_string_index(pdev->dev.of_node, + "cdm-client-names", i, &(ptr->dt_cdm_client_name[i])); + CAM_DBG(CAM_CDM, "cdm-client-names[%d] = %s", i, + ptr->dt_cdm_client_name[i]); + if (rc < 0) { + CAM_ERR(CAM_CDM, "Reading cdm-client-names failed"); + break; + } + } + + return rc; +} + +int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, + const struct of_device_id *table) +{ + int rc; + struct cam_hw_soc_info *soc_ptr; + const struct of_device_id *id; + + if (!cdm_hw || (cdm_hw->soc_info.soc_private) + || !(cdm_hw->soc_info.pdev)) + return -EINVAL; + + soc_ptr = &cdm_hw->soc_info; + + rc = cam_soc_util_get_dt_properties(soc_ptr); + if (rc != 0) { + CAM_ERR(CAM_CDM, "Failed to retrieve the CDM dt properties"); + } else { + soc_ptr->soc_private = kzalloc( + sizeof(struct cam_cdm_private_dt_data), + GFP_KERNEL); + if (!soc_ptr->soc_private) + return -ENOMEM; + + rc = cam_cdm_soc_load_dt_private(soc_ptr->pdev, + soc_ptr->soc_private); + if (rc != 0) { + CAM_ERR(CAM_CDM, "Failed to load CDM dt private data"); + goto error; + } + id = of_match_node(table, soc_ptr->pdev->dev.of_node); + if ((!id) || !(id->data)) { + CAM_ERR(CAM_CDM, "Failed to retrieve the CDM id table"); + goto error; + } + CAM_DBG(CAM_CDM, "CDM Hw Id compatible =%s", id->compatible); + ((struct cam_cdm *)cdm_hw->core_info)->offset_tbl = + (struct cam_cdm_reg_offset_table *)id->data; + strlcpy(((struct cam_cdm *)cdm_hw->core_info)->name, + id->compatible, + sizeof(((struct cam_cdm *)cdm_hw->core_info)->name)); + } + + return rc; + +error: + rc = -EINVAL; + kfree(soc_ptr->soc_private); + soc_ptr->soc_private = NULL; + return rc; +} + +int cam_cdm_intf_mgr_soc_get_dt_properties( + struct platform_device *pdev, struct cam_cdm_intf_mgr *mgr) +{ + int rc; + + rc = of_property_read_u32(pdev->dev.of_node, + "num-hw-cdm", &mgr->dt_supported_hw_cdm); + CAM_DBG(CAM_CDM, "Number of HW cdm supported =%d", + mgr->dt_supported_hw_cdm); + + return rc; +} diff --git a/drivers/cam_cdm/cam_cdm_soc.h b/drivers/cam_cdm/cam_cdm_soc.h new file mode 100644 index 000000000000..b422b34f244b --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_soc.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CDM_SOC_H_ +#define _CAM_CDM_SOC_H_ + +int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, + const struct of_device_id *table); +bool cam_cdm_read_hw_reg(struct cam_hw_info *cdm_hw, + enum cam_cdm_regs reg, uint32_t *value); +bool cam_cdm_write_hw_reg(struct cam_hw_info *cdm_hw, + enum cam_cdm_regs reg, uint32_t value); +int cam_cdm_intf_mgr_soc_get_dt_properties( + struct platform_device *pdev, + struct cam_cdm_intf_mgr *mgr); +int cam_cdm_soc_load_dt_private(struct platform_device *pdev, + struct cam_cdm_private_dt_data *ptr); + +#endif /* _CAM_CDM_SOC_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_util.c b/drivers/cam_cdm/cam_cdm_util.c new file mode 100644 index 000000000000..278dadb18db4 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_util.c @@ -0,0 +1,717 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_cdm_intf_api.h" +#include "cam_cdm_util.h" +#include "cam_cdm.h" +#include "cam_io_util.h" + +#define CAM_CDM_DWORD 4 + +#define CAM_CDM_SW_CMD_COUNT 2 +#define CAM_CMD_LENGTH_MASK 0xFFFF +#define CAM_CDM_COMMAND_OFFSET 24 +#define CAM_CDM_REG_OFFSET_MASK 0x00FFFFFF + +#define CAM_CDM_DMI_DATA_HI_OFFSET 8 +#define CAM_CDM_DMI_DATA_OFFSET 8 +#define CAM_CDM_DMI_DATA_LO_OFFSET 12 + +static unsigned int CDMCmdHeaderSizes[ + CAM_CDM_CMD_PRIVATE_BASE + CAM_CDM_SW_CMD_COUNT] = { + 0, /* UNUSED*/ + 3, /* DMI*/ + 0, /* UNUSED*/ + 2, /* RegContinuous*/ + 1, /* RegRandom*/ + 2, /* BUFFER_INDIREC*/ + 2, /* GenerateIRQ*/ + 3, /* WaitForEvent*/ + 1, /* ChangeBase*/ + 1, /* PERF_CONTROL*/ + 3, /* DMI32*/ + 3, /* DMI64*/ +}; + +/** + * struct cdm_regrandom_cmd - Definition for CDM random register command. + * @count: Number of register writes + * @reserved: reserved bits + * @cmd: Command ID (CDMCmd) + */ +struct cdm_regrandom_cmd { + unsigned int count : 16; + unsigned int reserved : 8; + unsigned int cmd : 8; +} __attribute__((__packed__)); + +/** + * struct cdm_regcontinuous_cmd - Definition for a CDM register range command. + * @count: Number of register writes + * @reserved0: reserved bits + * @cmd: Command ID (CDMCmd) + * @offset: Start address of the range of registers + * @reserved1: reserved bits + */ +struct cdm_regcontinuous_cmd { + unsigned int count : 16; + unsigned int reserved0 : 8; + unsigned int cmd : 8; + unsigned int offset : 24; + unsigned int reserved1 : 8; +} __attribute__((__packed__)); + +/** + * struct cdm_dmi_cmd - Definition for a CDM DMI command. + * @length: Number of bytes in LUT - 1 + * @reserved: reserved bits + * @cmd: Command ID (CDMCmd) + * @addr: Address of the LUT in memory + * @DMIAddr: Address of the target DMI config register + * @DMISel: DMI identifier + */ +struct cdm_dmi_cmd { + unsigned int length : 16; + unsigned int reserved : 8; + unsigned int cmd : 8; + unsigned int addr; + unsigned int DMIAddr : 24; + unsigned int DMISel : 8; +} __attribute__((__packed__)); + +/** + * struct cdm_indirect_cmd - Definition for a CDM indirect buffer command. + * @length: Number of bytes in buffer - 1 + * @reserved: reserved bits + * @cmd: Command ID (CDMCmd) + * @addr: Device address of the indirect buffer + */ +struct cdm_indirect_cmd { + unsigned int length : 16; + unsigned int reserved : 8; + unsigned int cmd : 8; + unsigned int addr; +} __attribute__((__packed__)); + +/** + * struct cdm_changebase_cmd - Definition for CDM base address change command. + * @base: Base address to be changed to + * @cmd:Command ID (CDMCmd) + */ +struct cdm_changebase_cmd { + unsigned int base : 24; + unsigned int cmd : 8; +} __attribute__((__packed__)); + +/** + * struct cdm_wait_event_cmd - Definition for a CDM Gen IRQ command. + * @mask: Mask for the events + * @id: ID to read back for debug + * @iw_reserved: reserved bits + * @iw: iw AHB write bit + * @cmd:Command ID (CDMCmd) + * @offset: Offset to where data is written + * @offset_reserved: reserved bits + * @data: data returned in IRQ_USR_DATA + */ +struct cdm_wait_event_cmd { + unsigned int mask : 8; + unsigned int id : 8; + unsigned int iw_reserved : 7; + unsigned int iw : 1; + unsigned int cmd : 8; + unsigned int offset : 24; + unsigned int offset_reserved : 8; + unsigned int data; +} __attribute__((__packed__)); + +/** + * struct cdm_genirq_cmd - Definition for a CDM Wait event command. + * @reserved: reserved bits + * @cmd:Command ID (CDMCmd) + * @userdata: userdata returned in IRQ_USR_DATA + */ +struct cdm_genirq_cmd { + unsigned int reserved : 24; + unsigned int cmd : 8; + unsigned int userdata; +} __attribute__((__packed__)); + +/** + * struct cdm_perf_ctrl_cmd_t - Definition for CDM perf control command. + * @perf: perf command + * @reserved: reserved bits + * @cmd:Command ID (CDMCmd) + */ +struct cdm_perf_ctrl_cmd { + unsigned int perf : 2; + unsigned int reserved : 22; + unsigned int cmd : 8; +} __attribute__((__packed__)); + +uint32_t cdm_get_cmd_header_size(unsigned int command) +{ + return CDMCmdHeaderSizes[command]; +} + +uint32_t cdm_required_size_reg_continuous(uint32_t numVals) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT) + numVals; +} + +uint32_t cdm_required_size_reg_random(uint32_t numRegVals) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM) + + (2 * numRegVals); +} + +uint32_t cdm_required_size_dmi(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); +} + +uint32_t cdm_required_size_genirq(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_GEN_IRQ); +} + +uint32_t cdm_required_size_indirect(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_BUFF_INDIRECT); +} + +uint32_t cdm_required_size_changebase(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_CHANGE_BASE); +} + +uint32_t cdm_offsetof_dmi_addr(void) +{ + return offsetof(struct cdm_dmi_cmd, addr); +} + +uint32_t cdm_offsetof_indirect_addr(void) +{ + return offsetof(struct cdm_indirect_cmd, addr); +} + +uint32_t *cdm_write_regcontinuous(uint32_t *pCmdBuffer, uint32_t reg, + uint32_t numVals, uint32_t *pVals) +{ + uint32_t i; + struct cdm_regcontinuous_cmd *pHeader = + (struct cdm_regcontinuous_cmd *)pCmdBuffer; + + pHeader->count = numVals; + pHeader->cmd = CAM_CDM_CMD_REG_CONT; + pHeader->reserved0 = 0; + pHeader->reserved1 = 0; + pHeader->offset = reg; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); + + for (i = 0; i < numVals; i++) + (((uint32_t *)pCmdBuffer)[i]) = (((uint32_t *)pVals)[i]); + + pCmdBuffer += numVals; + + return pCmdBuffer; +} + +uint32_t *cdm_write_regrandom(uint32_t *pCmdBuffer, uint32_t numRegVals, + uint32_t *pRegVals) +{ + uint32_t i; + uint32_t *dst, *src; + struct cdm_regrandom_cmd *pHeader = + (struct cdm_regrandom_cmd *)pCmdBuffer; + + pHeader->count = numRegVals; + pHeader->cmd = CAM_CDM_CMD_REG_RANDOM; + pHeader->reserved = 0; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); + dst = pCmdBuffer; + src = pRegVals; + for (i = 0; i < numRegVals; i++) { + *dst++ = *src++; + *dst++ = *src++; + } + + return dst; +} + +uint32_t *cdm_write_dmi(uint32_t *pCmdBuffer, uint8_t dmiCmd, + uint32_t DMIAddr, uint8_t DMISel, uint32_t dmiBufferAddr, + uint32_t length) +{ + struct cdm_dmi_cmd *pHeader = (struct cdm_dmi_cmd *)pCmdBuffer; + + pHeader->cmd = dmiCmd; + pHeader->addr = dmiBufferAddr; + pHeader->length = length - 1; + pHeader->DMIAddr = DMIAddr; + pHeader->DMISel = DMISel; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); + + return pCmdBuffer; +} + +uint32_t *cdm_write_indirect(uint32_t *pCmdBuffer, uint32_t indirectBufAddr, + uint32_t length) +{ + struct cdm_indirect_cmd *pHeader = + (struct cdm_indirect_cmd *)pCmdBuffer; + + pHeader->cmd = CAM_CDM_CMD_BUFF_INDIRECT; + pHeader->addr = indirectBufAddr; + pHeader->length = length - 1; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_BUFF_INDIRECT); + + return pCmdBuffer; +} + +uint32_t *cdm_write_changebase(uint32_t *pCmdBuffer, uint32_t base) +{ + struct cdm_changebase_cmd *pHeader = + (struct cdm_changebase_cmd *)pCmdBuffer; + + pHeader->cmd = CAM_CDM_CMD_CHANGE_BASE; + pHeader->base = base; + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_CHANGE_BASE); + + return pCmdBuffer; +} + +void cdm_write_genirq(uint32_t *pCmdBuffer, uint32_t userdata) +{ + struct cdm_genirq_cmd *pHeader = (struct cdm_genirq_cmd *)pCmdBuffer; + + pHeader->cmd = CAM_CDM_CMD_GEN_IRQ; + pHeader->userdata = userdata; +} + +struct cam_cdm_utils_ops CDM170_ops = { + cdm_get_cmd_header_size, + cdm_required_size_reg_continuous, + cdm_required_size_reg_random, + cdm_required_size_dmi, + cdm_required_size_genirq, + cdm_required_size_indirect, + cdm_required_size_changebase, + cdm_offsetof_dmi_addr, + cdm_offsetof_indirect_addr, + cdm_write_regcontinuous, + cdm_write_regrandom, + cdm_write_dmi, + cdm_write_indirect, + cdm_write_changebase, + cdm_write_genirq, +}; + +int cam_cdm_get_ioremap_from_base(uint32_t hw_base, + uint32_t base_array_size, + struct cam_soc_reg_map *base_table[CAM_SOC_MAX_BLOCK], + void __iomem **device_base) +{ + int ret = -EINVAL, i; + + for (i = 0; i < base_array_size; i++) { + if (base_table[i]) + CAM_DBG(CAM_CDM, "In loop %d ioremap for %x addr=%x", + i, (base_table[i])->mem_cam_base, hw_base); + if ((base_table[i]) && + ((base_table[i])->mem_cam_base == hw_base)) { + *device_base = (base_table[i])->mem_base; + ret = 0; + break; + } + } + + return ret; +} + +static int cam_cdm_util_reg_cont_write(void __iomem *base_addr, + uint32_t *cmd_buf, uint32_t cmd_buf_size, uint32_t *used_bytes) +{ + int ret = 0; + uint32_t *data; + struct cdm_regcontinuous_cmd *reg_cont; + + if ((cmd_buf_size < cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)) || + (!base_addr)) { + CAM_ERR(CAM_CDM, "invalid base addr and data length %d %pK", + cmd_buf_size, base_addr); + return -EINVAL; + } + + reg_cont = (struct cdm_regcontinuous_cmd *)cmd_buf; + if ((!reg_cont->count) || (reg_cont->count > 0x10000) || + (((reg_cont->count * sizeof(uint32_t)) + + cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)) > + cmd_buf_size)) { + CAM_ERR(CAM_CDM, "buffer size %d is not sufficient for count%d", + cmd_buf_size, reg_cont->count); + return -EINVAL; + } + data = cmd_buf + cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); + cam_io_memcpy(base_addr + reg_cont->offset, data, + reg_cont->count * sizeof(uint32_t)); + + *used_bytes = (reg_cont->count * sizeof(uint32_t)) + + (4 * cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)); + + return ret; +} + +static int cam_cdm_util_reg_random_write(void __iomem *base_addr, + uint32_t *cmd_buf, uint32_t cmd_buf_size, uint32_t *used_bytes) +{ + uint32_t i; + struct cdm_regrandom_cmd *reg_random; + uint32_t *data; + + if (!base_addr) { + CAM_ERR(CAM_CDM, "invalid base address"); + return -EINVAL; + } + + reg_random = (struct cdm_regrandom_cmd *) cmd_buf; + if ((!reg_random->count) || (reg_random->count > 0x10000) || + (((reg_random->count * (sizeof(uint32_t) * 2)) + + cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM)) > + cmd_buf_size)) { + CAM_ERR(CAM_CDM, "invalid reg_count %d cmd_buf_size %d", + reg_random->count, cmd_buf_size); + return -EINVAL; + } + data = cmd_buf + cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); + + for (i = 0; i < reg_random->count; i++) { + CAM_DBG(CAM_CDM, "reg random: offset %pK, value 0x%x", + ((void __iomem *)(base_addr + data[0])), + data[1]); + cam_io_w(data[1], base_addr + data[0]); + data += 2; + } + + *used_bytes = ((reg_random->count * (sizeof(uint32_t) * 2)) + + (4 * cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM))); + + return 0; +} + +static int cam_cdm_util_swd_dmi_write(uint32_t cdm_cmd_type, + void __iomem *base_addr, uint32_t *cmd_buf, uint32_t cmd_buf_size, + uint32_t *used_bytes) +{ + uint32_t i; + struct cdm_dmi_cmd *swd_dmi; + uint32_t *data; + + swd_dmi = (struct cdm_dmi_cmd *)cmd_buf; + + if (cmd_buf_size < (cdm_required_size_dmi() + swd_dmi->length + 1)) { + CAM_ERR(CAM_CDM, "invalid CDM_SWD_DMI length %d", + swd_dmi->length + 1); + return -EINVAL; + } + data = cmd_buf + cdm_required_size_dmi(); + + if (cdm_cmd_type == CAM_CDM_CMD_SWD_DMI_64) { + for (i = 0; i < (swd_dmi->length + 1)/8; i++) { + cam_io_w_mb(data[0], base_addr + + swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_LO_OFFSET); + cam_io_w_mb(data[1], base_addr + + swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_HI_OFFSET); + data += 2; + } + } else if (cdm_cmd_type == CAM_CDM_CMD_DMI) { + for (i = 0; i < (swd_dmi->length + 1)/4; i++) { + cam_io_w_mb(data[0], base_addr + + swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_OFFSET); + data += 1; + } + } else { + for (i = 0; i < (swd_dmi->length + 1)/4; i++) { + cam_io_w_mb(data[0], base_addr + + swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_LO_OFFSET); + data += 1; + } + } + *used_bytes = (4 * cdm_required_size_dmi()) + swd_dmi->length + 1; + + return 0; +} + +int cam_cdm_util_cmd_buf_write(void __iomem **current_device_base, + uint32_t *cmd_buf, uint32_t cmd_buf_size, + struct cam_soc_reg_map *base_table[CAM_SOC_MAX_BLOCK], + uint32_t base_array_size, uint8_t bl_tag) +{ + int ret = 0; + uint32_t cdm_cmd_type = 0, total_cmd_buf_size = 0; + uint32_t used_bytes = 0; + + total_cmd_buf_size = cmd_buf_size; + + while (cmd_buf_size > 0) { + CAM_DBG(CAM_CDM, "cmd data=%x", *cmd_buf); + cdm_cmd_type = (*cmd_buf >> CAM_CDM_COMMAND_OFFSET); + switch (cdm_cmd_type) { + case CAM_CDM_CMD_REG_CONT: { + ret = cam_cdm_util_reg_cont_write(*current_device_base, + cmd_buf, cmd_buf_size, &used_bytes); + if (ret) + break; + + if (used_bytes > 0) { + cmd_buf_size -= used_bytes; + cmd_buf += used_bytes/4; + } + } + break; + case CAM_CDM_CMD_REG_RANDOM: { + ret = cam_cdm_util_reg_random_write( + *current_device_base, cmd_buf, cmd_buf_size, + &used_bytes); + if (ret) + break; + + if (used_bytes > 0) { + cmd_buf_size -= used_bytes; + cmd_buf += used_bytes / 4; + } + } + break; + case CAM_CDM_CMD_DMI: + case CAM_CDM_CMD_SWD_DMI_32: + case CAM_CDM_CMD_SWD_DMI_64: { + if (*current_device_base == 0) { + CAM_ERR(CAM_CDM, + "Got SWI DMI cmd =%d for invalid hw", + cdm_cmd_type); + ret = -EINVAL; + break; + } + ret = cam_cdm_util_swd_dmi_write(cdm_cmd_type, + *current_device_base, cmd_buf, cmd_buf_size, + &used_bytes); + if (ret) + break; + + if (used_bytes > 0) { + cmd_buf_size -= used_bytes; + cmd_buf += used_bytes / 4; + } + } + break; + case CAM_CDM_CMD_CHANGE_BASE: { + struct cdm_changebase_cmd *change_base_cmd = + (struct cdm_changebase_cmd *)cmd_buf; + + ret = cam_cdm_get_ioremap_from_base( + change_base_cmd->base, base_array_size, + base_table, current_device_base); + if (ret != 0) { + CAM_ERR(CAM_CDM, + "Get ioremap change base failed %x", + change_base_cmd->base); + break; + } + CAM_DBG(CAM_CDM, "Got ioremap for %x addr=%pK", + change_base_cmd->base, + current_device_base); + cmd_buf_size -= (4 * + cdm_required_size_changebase()); + cmd_buf += cdm_required_size_changebase(); + } + break; + default: + CAM_ERR(CAM_CDM, "unsupported cdm_cmd_type type 0%x", + cdm_cmd_type); + ret = -EINVAL; + break; + } + + if (ret < 0) + break; + } + + return ret; +} + +static long cam_cdm_util_dump_dmi_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI]; + CAM_INFO(CAM_CDM, "DMI"); + return ret; +} + +static long cam_cdm_util_dump_buff_indirect(uint32_t *cmd_buf_addr) +{ + long ret = 0; + + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT]; + CAM_INFO(CAM_CDM, "Buff Indirect"); + return ret; +} + +static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + struct cdm_regcontinuous_cmd *p_regcont_cmd; + uint32_t *temp_ptr = cmd_buf_addr; + int i = 0; + + p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr; + temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT]; + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT]; + + CAM_INFO(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X", + p_regcont_cmd->count, p_regcont_cmd->offset); + + for (i = 0; i < p_regcont_cmd->count; i++) { + CAM_INFO(CAM_CDM, "DATA_%d: 0x%X", i, + *temp_ptr); + temp_ptr++; + ret++; + } + + return ret; +} + +static long cam_cdm_util_dump_reg_random_cmd(uint32_t *cmd_buf_addr) +{ + struct cdm_regrandom_cmd *p_regrand_cmd; + uint32_t *temp_ptr = cmd_buf_addr; + long ret = 0; + int i = 0; + + p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr; + temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM]; + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM]; + + CAM_INFO(CAM_CDM, "REG_RAND: COUNT: %u", + p_regrand_cmd->count); + + for (i = 0; i < p_regrand_cmd->count; i++) { + CAM_INFO(CAM_CDM, "OFFSET_%d: 0x%X DATA_%d: 0x%X", + i, *temp_ptr & CAM_CDM_REG_OFFSET_MASK, i, + *(temp_ptr + 1)); + temp_ptr += 2; + ret += 2; + } + + return ret; +} + +static long cam_cdm_util_dump_gen_irq_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ]; + + CAM_INFO(CAM_CDM, "GEN_IRQ"); + + return ret; +} + +static long cam_cdm_util_dump_wait_event_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT]; + + CAM_INFO(CAM_CDM, "WAIT_EVENT"); + + return ret; +} + +static long cam_cdm_util_dump_change_base_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + struct cdm_changebase_cmd *p_cbase_cmd; + uint32_t *temp_ptr = cmd_buf_addr; + + p_cbase_cmd = (struct cdm_changebase_cmd *)temp_ptr; + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE]; + + CAM_INFO(CAM_CDM, "CHANGE_BASE: 0x%X", + p_cbase_cmd->base); + + return ret; +} + +static long cam_cdm_util_dump_perf_ctrl_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL]; + + CAM_INFO(CAM_CDM, "PERF_CTRL"); + + return ret; +} + +void cam_cdm_util_dump_cmd_buf( + uint32_t *cmd_buf_start, uint32_t *cmd_buf_end) +{ + uint32_t *buf_now = cmd_buf_start; + uint32_t cmd = 0; + + if (!cmd_buf_start || !cmd_buf_end) { + CAM_INFO(CAM_CDM, "Invalid args"); + return; + } + + do { + cmd = *buf_now; + cmd = cmd >> CAM_CDM_COMMAND_OFFSET; + + switch (cmd) { + case CAM_CDM_CMD_DMI: + case CAM_CDM_CMD_DMI_32: + case CAM_CDM_CMD_DMI_64: + buf_now += cam_cdm_util_dump_dmi_cmd(buf_now); + break; + case CAM_CDM_CMD_REG_CONT: + buf_now += cam_cdm_util_dump_reg_cont_cmd(buf_now); + break; + case CAM_CDM_CMD_REG_RANDOM: + buf_now += cam_cdm_util_dump_reg_random_cmd(buf_now); + break; + case CAM_CDM_CMD_BUFF_INDIRECT: + buf_now += cam_cdm_util_dump_buff_indirect(buf_now); + break; + case CAM_CDM_CMD_GEN_IRQ: + buf_now += cam_cdm_util_dump_gen_irq_cmd(buf_now); + break; + case CAM_CDM_CMD_WAIT_EVENT: + buf_now += cam_cdm_util_dump_wait_event_cmd(buf_now); + break; + case CAM_CDM_CMD_CHANGE_BASE: + buf_now += cam_cdm_util_dump_change_base_cmd(buf_now); + break; + case CAM_CDM_CMD_PERF_CTRL: + buf_now += cam_cdm_util_dump_perf_ctrl_cmd(buf_now); + break; + default: + CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x", + cmd, *buf_now); + buf_now++; + break; + } + } while (buf_now <= cmd_buf_end); +} diff --git a/drivers/cam_cdm/cam_cdm_util.h b/drivers/cam_cdm/cam_cdm_util.h new file mode 100644 index 000000000000..663eca92a5fe --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_util.h @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CDM_UTIL_H_ +#define _CAM_CDM_UTIL_H_ + +enum cam_cdm_command { + CAM_CDM_CMD_UNUSED = 0x0, + CAM_CDM_CMD_DMI = 0x1, + CAM_CDM_CMD_NOT_DEFINED = 0x2, + CAM_CDM_CMD_REG_CONT = 0x3, + CAM_CDM_CMD_REG_RANDOM = 0x4, + CAM_CDM_CMD_BUFF_INDIRECT = 0x5, + CAM_CDM_CMD_GEN_IRQ = 0x6, + CAM_CDM_CMD_WAIT_EVENT = 0x7, + CAM_CDM_CMD_CHANGE_BASE = 0x8, + CAM_CDM_CMD_PERF_CTRL = 0x9, + CAM_CDM_CMD_DMI_32 = 0xa, + CAM_CDM_CMD_DMI_64 = 0xb, + CAM_CDM_CMD_PRIVATE_BASE = 0xc, + CAM_CDM_CMD_SWD_DMI_32 = (CAM_CDM_CMD_PRIVATE_BASE + 0x64), + CAM_CDM_CMD_SWD_DMI_64 = (CAM_CDM_CMD_PRIVATE_BASE + 0x65), + CAM_CDM_CMD_PRIVATE_BASE_MAX = 0x7F +}; + +/** + * struct cam_cdm_utils_ops - Camera CDM util ops + * + * @cdm_get_cmd_header_size: Returns the size of the given command header + * in DWORDs. + * @command Command ID + * @return Size of the command in DWORDs + * + * @cdm_required_size_reg_continuous: Calculates the size of a reg-continuous + * command in dwords. + * @numVals Number of continuous values + * @return Size in dwords + * + * @cdm_required_size_reg_random: Calculates the size of a reg-random command + * in dwords. + * @numRegVals Number of register/value pairs + * @return Size in dwords + * + * @cdm_required_size_dmi: Calculates the size of a DMI command in dwords. + * @return Size in dwords + * + * @cdm_required_size_genirq: Calculates size of a Genirq command in dwords. + * @return Size in dwords + * + * @cdm_required_size_indirect: Calculates the size of an indirect command + * in dwords. + * @return Size in dwords + * + * @cdm_required_size_changebase: Calculates the size of a change-base command + * in dwords. + * @return Size in dwords + * + * @cdm_offsetof_dmi_addr: Returns the offset of address field in the DMI + * command header. + * @return Offset of addr field + * + * @cdm_offsetof_indirect_addr: Returns the offset of address field in the + * indirect command header. + * @return Offset of addr field + * + * @cdm_write_regcontinuous: Writes a command into the command buffer. + * @pCmdBuffer: Pointer to command buffer + * @reg: Beginning of the register address range where + * values will be written. + * @numVals: Number of values (registers) that will be written + * @pVals : An array of values that will be written + * @return Pointer in command buffer pointing past the written commands + * + * @cdm_write_regrandom: Writes a command into the command buffer in + * register/value pairs. + * @pCmdBuffer: Pointer to command buffer + * @numRegVals: Number of register/value pairs that will be written + * @pRegVals: An array of register/value pairs that will be written + * The even indices are registers and the odd indices + * arevalues, e.g., {reg1, val1, reg2, val2, ...}. + * @return Pointer in command buffer pointing past the written commands + * + * @cdm_write_dmi: Writes a DMI command into the command bufferM. + * @pCmdBuffer: Pointer to command buffer + * @dmiCmd: DMI command + * @DMIAddr: Address of the DMI + * @DMISel: Selected bank that the DMI will write to + * @length: Size of data in bytes + * @return Pointer in command buffer pointing past the written commands + * + * @cdm_write_indirect: Writes a indirect command into the command buffer. + * @pCmdBuffer: Pointer to command buffer + * @indirectBufferAddr: Device address of the indirect cmd buffer. + * @length: Size of data in bytes + * @return Pointer in command buffer pointing past the written commands + * + * @cdm_write_changebase: Writes a changing CDM (address) base command into + * the command buffer. + * @pCmdBuffer: Pointer to command buffer + * @base: New base (device) address + * @return Pointer in command buffer pointing past the written commands + * + * @cdm_write_genirq: Writes a gen irq command into the command buffer. + * @pCmdBuffer: Pointer to command buffer + * @userdata: userdata or cookie return by hardware during irq. + */ +struct cam_cdm_utils_ops { +uint32_t (*cdm_get_cmd_header_size)(unsigned int command); +uint32_t (*cdm_required_size_reg_continuous)(uint32_t numVals); +uint32_t (*cdm_required_size_reg_random)(uint32_t numRegVals); +uint32_t (*cdm_required_size_dmi)(void); +uint32_t (*cdm_required_size_genirq)(void); +uint32_t (*cdm_required_size_indirect)(void); +uint32_t (*cdm_required_size_changebase)(void); +uint32_t (*cdm_offsetof_dmi_addr)(void); +uint32_t (*cdm_offsetof_indirect_addr)(void); +uint32_t* (*cdm_write_regcontinuous)( + uint32_t *pCmdBuffer, + uint32_t reg, + uint32_t numVals, + uint32_t *pVals); +uint32_t *(*cdm_write_regrandom)( + uint32_t *pCmdBuffer, + uint32_t numRegVals, + uint32_t *pRegVals); +uint32_t *(*cdm_write_dmi)( + uint32_t *pCmdBuffer, + uint8_t dmiCmd, + uint32_t DMIAddr, + uint8_t DMISel, + uint32_t dmiBufferAddr, + uint32_t length); +uint32_t *(*cdm_write_indirect)( + uint32_t *pCmdBuffer, + uint32_t indirectBufferAddr, + uint32_t length); +uint32_t *(*cdm_write_changebase)( + uint32_t *pCmdBuffer, + uint32_t base); +void (*cdm_write_genirq)( + uint32_t *pCmdBuffer, + uint32_t userdata); +}; + +/** + * cam_cdm_util_log_cmd_bufs() + * + * @brief: Util function to log cdm command buffers + * + * @cmd_buffer_start: Pointer to start of cmd buffer + * @cmd_buffer_end: Pointer to end of cmd buffer + * + */ +void cam_cdm_util_dump_cmd_buf( + uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end); + + + +#endif /* _CAM_CDM_UTIL_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_virtual.h b/drivers/cam_cdm/cam_cdm_virtual.h new file mode 100644 index 000000000000..193e01be4796 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_virtual.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CDM_VIRTUAL_H_ +#define _CAM_CDM_VIRTUAL_H_ + +#include "cam_cdm_intf_api.h" + +int cam_virtual_cdm_probe(struct platform_device *pdev); +int cam_virtual_cdm_remove(struct platform_device *pdev); +int cam_cdm_util_cmd_buf_write(void __iomem **current_device_base, + uint32_t *cmd_buf, uint32_t cmd_buf_size, + struct cam_soc_reg_map *base_table[CAM_SOC_MAX_BLOCK], + uint32_t base_array_size, uint8_t bl_tag); + +#endif /* _CAM_CDM_VIRTUAL_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_virtual_core.c b/drivers/cam_cdm/cam_cdm_virtual_core.c new file mode 100644 index 000000000000..5abca3939338 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_virtual_core.c @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_soc_util.h" +#include "cam_smmu_api.h" +#include "cam_cdm_intf_api.h" +#include "cam_cdm.h" +#include "cam_cdm_util.h" +#include "cam_cdm_virtual.h" +#include "cam_cdm_core_common.h" +#include "cam_cdm_soc.h" +#include "cam_io_util.h" + +#define CAM_CDM_VIRTUAL_NAME "qcom,cam_virtual_cdm" + +static void cam_virtual_cdm_work(struct work_struct *work) +{ + struct cam_cdm_work_payload *payload; + struct cam_hw_info *cdm_hw; + struct cam_cdm *core; + + payload = container_of(work, struct cam_cdm_work_payload, work); + if (payload) { + cdm_hw = payload->hw; + core = (struct cam_cdm *)cdm_hw->core_info; + if (payload->irq_status & 0x2) { + struct cam_cdm_bl_cb_request_entry *node; + + CAM_DBG(CAM_CDM, "CDM HW Gen/inline IRQ with data=%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) { + 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_ERR(CAM_CDM, "Invalid node=%pK %d", + node, node->request_type); + } + list_del_init(&node->entry); + kfree(node); + } else { + CAM_ERR(CAM_CDM, "Invalid node for inline irq"); + } + mutex_unlock(&cdm_hw->hw_mutex); + } + if (payload->irq_status & 0x1) { + CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); + complete(&core->reset_complete); + } + kfree(payload); + } + +} + +int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req, + struct cam_cdm_client *client) +{ + int i, rc = -EINVAL; + struct cam_cdm_bl_request *cdm_cmd = req->data; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + + mutex_lock(&client->lock); + for (i = 0; i < req->data->cmd_arrary_count ; i++) { + uintptr_t vaddr_ptr = 0; + size_t len = 0; + + if ((!cdm_cmd->cmd[i].len) && + (cdm_cmd->cmd[i].len > 0x100000)) { + CAM_ERR(CAM_CDM, + "len(%d) is invalid count=%d total cnt=%d", + cdm_cmd->cmd[i].len, i, + req->data->cmd_arrary_count); + rc = -EINVAL; + break; + } + if (req->data->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE) { + rc = cam_mem_get_cpu_buf( + cdm_cmd->cmd[i].bl_addr.mem_handle, &vaddr_ptr, + &len); + } else if (req->data->type == + CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA) { + rc = 0; + vaddr_ptr = cdm_cmd->cmd[i].bl_addr.kernel_iova; + len = cdm_cmd->cmd[i].offset + cdm_cmd->cmd[i].len; + } else { + CAM_ERR(CAM_CDM, + "Only mem hdl/Kernel va type is supported %d", + req->data->type); + rc = -EINVAL; + break; + } + + 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, + (void *)vaddr_ptr, cdm_cmd->cmd[i].offset, + cdm_cmd->cmd[i].len, len); + rc = cam_cdm_util_cmd_buf_write( + &client->changebase_addr, + ((uint32_t *)vaddr_ptr + + ((cdm_cmd->cmd[i].offset)/4)), + cdm_cmd->cmd[i].len, client->data.base_array, + client->data.base_array_cnt, core->bl_tag); + if (rc) { + CAM_ERR(CAM_CDM, + "write failed for cnt=%d:%d len %u", + i, req->data->cmd_arrary_count, + cdm_cmd->cmd[i].len); + break; + } + } else { + CAM_ERR(CAM_CDM, + "Sanity check failed for hdl=%x len=%zu:%d", + cdm_cmd->cmd[i].bl_addr.mem_handle, len, + cdm_cmd->cmd[i].offset); + CAM_ERR(CAM_CDM, + "Sanity check failed for cmd_count=%d cnt=%d", + i, req->data->cmd_arrary_count); + rc = -EINVAL; + break; + } + if (!rc) { + struct cam_cdm_work_payload *payload; + + CAM_DBG(CAM_CDM, + "write BL success for cnt=%d with tag=%d", + i, core->bl_tag); + if ((true == req->data->flag) && + (i == req->data->cmd_arrary_count)) { + struct cam_cdm_bl_cb_request_entry *node; + + node = kzalloc(sizeof( + struct cam_cdm_bl_cb_request_entry), + GFP_KERNEL); + if (!node) { + rc = -ENOMEM; + break; + } + node->request_type = CAM_HW_CDM_BL_CB_CLIENT; + node->client_hdl = req->handle; + node->cookie = req->data->cookie; + node->bl_tag = core->bl_tag; + node->userdata = req->data->userdata; + mutex_lock(&cdm_hw->hw_mutex); + list_add_tail(&node->entry, + &core->bl_request_list); + mutex_unlock(&cdm_hw->hw_mutex); + + payload = kzalloc(sizeof( + struct cam_cdm_work_payload), + GFP_ATOMIC); + if (payload) { + payload->irq_status = 0x2; + payload->irq_data = core->bl_tag; + payload->hw = cdm_hw; + INIT_WORK((struct work_struct *) + &payload->work, + cam_virtual_cdm_work); + queue_work(core->work_queue, + &payload->work); + } + } + core->bl_tag++; + CAM_DBG(CAM_CDM, + "Now commit the BL nothing for virtual"); + if (!rc && (core->bl_tag == 63)) + core->bl_tag = 0; + } + } + mutex_unlock(&client->lock); + return rc; +} + +int cam_virtual_cdm_probe(struct platform_device *pdev) +{ + struct cam_hw_info *cdm_hw = NULL; + struct cam_hw_intf *cdm_hw_intf = NULL; + struct cam_cdm *cdm_core = NULL; + struct cam_cdm_private_dt_data *soc_private = NULL; + int rc; + struct cam_cpas_register_params cpas_parms; + + cdm_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!cdm_hw_intf) + return -ENOMEM; + + cdm_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!cdm_hw) { + kfree(cdm_hw_intf); + return -ENOMEM; + } + + cdm_hw->core_info = kzalloc(sizeof(struct cam_cdm), GFP_KERNEL); + if (!cdm_hw->core_info) { + kfree(cdm_hw); + kfree(cdm_hw_intf); + return -ENOMEM; + } + cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + cdm_hw->soc_info.pdev = pdev; + cdm_hw_intf->hw_type = CAM_VIRTUAL_CDM; + cdm_hw->soc_info.soc_private = kzalloc( + sizeof(struct cam_cdm_private_dt_data), GFP_KERNEL); + if (!cdm_hw->soc_info.soc_private) { + rc = -ENOMEM; + goto soc_load_failed; + } + + rc = cam_cdm_soc_load_dt_private(pdev, cdm_hw->soc_info.soc_private); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to load CDM dt private data"); + kfree(cdm_hw->soc_info.soc_private); + cdm_hw->soc_info.soc_private = NULL; + goto soc_load_failed; + } + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + soc_private = (struct cam_cdm_private_dt_data *) + cdm_hw->soc_info.soc_private; + if (soc_private->dt_cdm_shared == true) + cdm_core->flags = CAM_CDM_FLAG_SHARED_CDM; + else + cdm_core->flags = CAM_CDM_FLAG_PRIVATE_CDM; + + cdm_core->bl_tag = 0; + INIT_LIST_HEAD(&cdm_core->bl_request_list); + init_completion(&cdm_core->reset_complete); + cdm_hw_intf->hw_priv = cdm_hw; + cdm_hw_intf->hw_ops.get_hw_caps = cam_cdm_get_caps; + cdm_hw_intf->hw_ops.init = NULL; + cdm_hw_intf->hw_ops.deinit = NULL; + cdm_hw_intf->hw_ops.start = cam_cdm_stream_start; + cdm_hw_intf->hw_ops.stop = cam_cdm_stream_stop; + cdm_hw_intf->hw_ops.read = NULL; + cdm_hw_intf->hw_ops.write = NULL; + cdm_hw_intf->hw_ops.process_cmd = cam_cdm_process_cmd; + + CAM_DBG(CAM_CDM, "type %d index %d", cdm_hw_intf->hw_type, + cdm_hw_intf->hw_idx); + + platform_set_drvdata(pdev, cdm_hw_intf); + + cdm_hw->open_count = 0; + cdm_core->iommu_hdl.non_secure = -1; + cdm_core->iommu_hdl.secure = -1; + mutex_init(&cdm_hw->hw_mutex); + spin_lock_init(&cdm_hw->hw_lock); + init_completion(&cdm_hw->hw_complete); + mutex_lock(&cdm_hw->hw_mutex); + cdm_core->id = CAM_CDM_VIRTUAL; + memcpy(cdm_core->name, CAM_CDM_VIRTUAL_NAME, + sizeof(CAM_CDM_VIRTUAL_NAME)); + cdm_core->work_queue = alloc_workqueue(cdm_core->name, + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, + CAM_CDM_INFLIGHT_WORKS); + cdm_core->ops = NULL; + + cpas_parms.cam_cpas_client_cb = cam_cdm_cpas_cb; + cpas_parms.cell_index = cdm_hw->soc_info.index; + cpas_parms.dev = &pdev->dev; + cpas_parms.userdata = cdm_hw_intf; + strlcpy(cpas_parms.identifier, "cam-cdm-intf", + CAM_HW_IDENTIFIER_LENGTH); + rc = cam_cpas_register_client(&cpas_parms); + if (rc) { + CAM_ERR(CAM_CDM, "Virtual CDM CPAS registration failed"); + goto cpas_registration_failed; + } + CAM_DBG(CAM_CDM, "CPAS registration successful handle=%d", + cpas_parms.client_handle); + cdm_core->cpas_handle = cpas_parms.client_handle; + + CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx); + + rc = cam_cdm_intf_register_hw_cdm(cdm_hw_intf, + soc_private, CAM_VIRTUAL_CDM, &cdm_core->index); + if (rc) { + CAM_ERR(CAM_CDM, "Virtual CDM Interface registration failed"); + goto intf_registration_failed; + } + CAM_DBG(CAM_CDM, "CDM%d registered to intf successful", + cdm_hw_intf->hw_idx); + mutex_unlock(&cdm_hw->hw_mutex); + + return 0; +intf_registration_failed: + cam_cpas_unregister_client(cdm_core->cpas_handle); +cpas_registration_failed: + kfree(cdm_hw->soc_info.soc_private); + flush_workqueue(cdm_core->work_queue); + destroy_workqueue(cdm_core->work_queue); + mutex_unlock(&cdm_hw->hw_mutex); + mutex_destroy(&cdm_hw->hw_mutex); +soc_load_failed: + kfree(cdm_hw->core_info); + kfree(cdm_hw); + kfree(cdm_hw_intf); + return rc; +} + +int cam_virtual_cdm_remove(struct platform_device *pdev) +{ + struct cam_hw_info *cdm_hw = NULL; + struct cam_hw_intf *cdm_hw_intf = NULL; + struct cam_cdm *cdm_core = NULL; + int rc = -EBUSY; + + cdm_hw_intf = platform_get_drvdata(pdev); + if (!cdm_hw_intf) { + CAM_ERR(CAM_CDM, "Failed to get dev private data"); + return rc; + } + + cdm_hw = cdm_hw_intf->hw_priv; + if (!cdm_hw) { + CAM_ERR(CAM_CDM, + "Failed to get virtual private data for type=%d idx=%d", + cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx); + return rc; + } + + cdm_core = cdm_hw->core_info; + if (!cdm_core) { + CAM_ERR(CAM_CDM, + "Failed to get virtual core data for type=%d idx=%d", + cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx); + return rc; + } + + rc = cam_cpas_unregister_client(cdm_core->cpas_handle); + if (rc) { + CAM_ERR(CAM_CDM, "CPAS unregister failed"); + return rc; + } + + rc = cam_cdm_intf_deregister_hw_cdm(cdm_hw_intf, + cdm_hw->soc_info.soc_private, CAM_VIRTUAL_CDM, + cdm_core->index); + if (rc) { + CAM_ERR(CAM_CDM, + "Virtual CDM Interface de-registration failed"); + return rc; + } + + flush_workqueue(cdm_core->work_queue); + destroy_workqueue(cdm_core->work_queue); + mutex_destroy(&cdm_hw->hw_mutex); + kfree(cdm_hw->soc_info.soc_private); + kfree(cdm_hw->core_info); + kfree(cdm_hw); + kfree(cdm_hw_intf); + rc = 0; + + return rc; +} diff --git a/drivers/cam_cdm/cam_hw_cdm170_reg.h b/drivers/cam_cdm/cam_hw_cdm170_reg.h new file mode 100644 index 000000000000..4a0fbda825c5 --- /dev/null +++ b/drivers/cam_cdm/cam_hw_cdm170_reg.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_HW_CDM170_REG_H_ +#define _CAM_HW_CDM170_REG_H_ + +#define CAM_CDM_REG_OFFSET_FIRST 0x0 +#define CAM_CDM_REG_OFFSET_LAST 0x200 +#define CAM_CDM_REGS_COUNT 0x30 +#define CAM_CDM_HWFIFO_SIZE 0x40 + +#define CAM_CDM_OFFSET_HW_VERSION 0x0 +#define CAM_CDM_OFFSET_TITAN_VERSION 0x4 +#define CAM_CDM_OFFSET_RST_CMD 0x10 +#define CAM_CDM_OFFSET_CGC_CFG 0x14 +#define CAM_CDM_OFFSET_CORE_CFG 0x18 +#define CAM_CDM_OFFSET_CORE_EN 0x1c +#define CAM_CDM_OFFSET_FE_CFG 0x20 +#define CAM_CDM_OFFSET_IRQ_MASK 0x30 +#define CAM_CDM_OFFSET_IRQ_CLEAR 0x34 +#define CAM_CDM_OFFSET_IRQ_CLEAR_CMD 0x38 +#define CAM_CDM_OFFSET_IRQ_SET 0x3c +#define CAM_CDM_OFFSET_IRQ_SET_CMD 0x40 + +#define CAM_CDM_OFFSET_IRQ_STATUS 0x44 +#define CAM_CDM_IRQ_STATUS_INFO_RST_DONE_MASK 0x1 +#define CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK 0x2 +#define CAM_CDM_IRQ_STATUS_INFO_BL_DONE_MASK 0x4 +#define CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK 0x10000 +#define CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK 0x20000 +#define CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK 0x40000 + +#define CAM_CDM_OFFSET_BL_FIFO_BASE_REG 0x50 +#define CAM_CDM_OFFSET_BL_FIFO_LEN_REG 0x54 +#define CAM_CDM_OFFSET_BL_FIFO_STORE_REG 0x58 +#define CAM_CDM_OFFSET_BL_FIFO_CFG 0x5c +#define CAM_CDM_OFFSET_BL_FIFO_RB 0x60 +#define CAM_CDM_OFFSET_BL_FIFO_BASE_RB 0x64 +#define CAM_CDM_OFFSET_BL_FIFO_LEN_RB 0x68 +#define CAM_CDM_OFFSET_BL_FIFO_PENDING_REQ_RB 0x6c +#define CAM_CDM_OFFSET_IRQ_USR_DATA 0x80 +#define CAM_CDM_OFFSET_WAIT_STATUS 0x84 +#define CAM_CDM_OFFSET_SCRATCH_0_REG 0x90 +#define CAM_CDM_OFFSET_SCRATCH_1_REG 0x94 +#define CAM_CDM_OFFSET_SCRATCH_2_REG 0x98 +#define CAM_CDM_OFFSET_SCRATCH_3_REG 0x9c +#define CAM_CDM_OFFSET_SCRATCH_4_REG 0xa0 +#define CAM_CDM_OFFSET_SCRATCH_5_REG 0xa4 +#define CAM_CDM_OFFSET_SCRATCH_6_REG 0xa8 +#define CAM_CDM_OFFSET_SCRATCH_7_REG 0xac +#define CAM_CDM_OFFSET_LAST_AHB_ADDR 0xd0 +#define CAM_CDM_OFFSET_LAST_AHB_DATA 0xd4 +#define CAM_CDM_OFFSET_CORE_DBUG 0xd8 +#define CAM_CDM_OFFSET_LAST_AHB_ERR_ADDR 0xe0 +#define CAM_CDM_OFFSET_LAST_AHB_ERR_DATA 0xe4 +#define CAM_CDM_OFFSET_CURRENT_BL_BASE 0xe8 +#define CAM_CDM_OFFSET_CURRENT_BL_LEN 0xec +#define CAM_CDM_OFFSET_CURRENT_USED_AHB_BASE 0xf0 +#define CAM_CDM_OFFSET_DEBUG_STATUS 0xf4 +#define CAM_CDM_OFFSET_BUS_MISR_CFG_0 0x100 +#define CAM_CDM_OFFSET_BUS_MISR_CFG_1 0x104 +#define CAM_CDM_OFFSET_BUS_MISR_RD_VAL 0x108 +#define CAM_CDM_OFFSET_PERF_MON_CTRL 0x110 +#define CAM_CDM_OFFSET_PERF_MON_0 0x114 +#define CAM_CDM_OFFSET_PERF_MON_1 0x118 +#define CAM_CDM_OFFSET_PERF_MON_2 0x11c +#define CAM_CDM_OFFSET_SPARE 0x200 + +/* + * Always make sure below register offsets are aligned with + * enum cam_cdm_regs offsets + */ +struct cam_cdm_reg_offset cam170_cpas_cdm_register_offsets[] = { + { CAM_CDM_OFFSET_HW_VERSION, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_TITAN_VERSION, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_RST_CMD, CAM_REG_ATTR_WRITE }, + { CAM_CDM_OFFSET_CGC_CFG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_CORE_CFG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_CORE_EN, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_FE_CFG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_IRQ_MASK, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_IRQ_CLEAR, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_IRQ_CLEAR_CMD, CAM_REG_ATTR_WRITE }, + { CAM_CDM_OFFSET_IRQ_SET, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_IRQ_SET_CMD, CAM_REG_ATTR_WRITE }, + { CAM_CDM_OFFSET_IRQ_STATUS, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_IRQ_USR_DATA, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BL_FIFO_BASE_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BL_FIFO_LEN_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BL_FIFO_STORE_REG, CAM_REG_ATTR_WRITE }, + { CAM_CDM_OFFSET_BL_FIFO_CFG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BL_FIFO_RB, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BL_FIFO_BASE_RB, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_BL_FIFO_LEN_RB, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_BL_FIFO_PENDING_REQ_RB, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_WAIT_STATUS, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_SCRATCH_0_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_1_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_2_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_3_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_4_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_5_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_6_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_SCRATCH_7_REG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_LAST_AHB_ADDR, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_LAST_AHB_DATA, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_CORE_DBUG, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_LAST_AHB_ERR_ADDR, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_LAST_AHB_ERR_DATA, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_CURRENT_BL_BASE, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_CURRENT_BL_LEN, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_CURRENT_USED_AHB_BASE, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_DEBUG_STATUS, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_BUS_MISR_CFG_0, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BUS_MISR_CFG_1, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_BUS_MISR_RD_VAL, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_PERF_MON_CTRL, CAM_REG_ATTR_READ_WRITE }, + { CAM_CDM_OFFSET_PERF_MON_0, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_PERF_MON_1, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_PERF_MON_2, CAM_REG_ATTR_READ }, + { CAM_CDM_OFFSET_SPARE, CAM_REG_ATTR_READ_WRITE } +}; + +struct cam_cdm_reg_offset_table cam170_cpas_cdm_offset_table = { + .first_offset = 0x0, + .last_offset = 0x200, + .reg_count = 0x30, + .offsets = cam170_cpas_cdm_register_offsets, + .offset_max_size = (sizeof(cam170_cpas_cdm_register_offsets)/ + sizeof(struct cam_cdm_reg_offset)), +}; + +#endif /* _CAM_HW_CDM170_REG_H_ */ diff --git a/drivers/cam_core/Makefile b/drivers/cam_core/Makefile new file mode 100644 index 000000000000..986b65f0ecd4 --- /dev/null +++ b/drivers/cam_core/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(src) + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_context.o cam_context_utils.o cam_node.o cam_subdev.o diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c new file mode 100644 index 000000000000..85908a3b6a4d --- /dev/null +++ b/drivers/cam_core/cam_context.c @@ -0,0 +1,586 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_context.h" +#include "cam_debug_util.h" +#include "cam_node.h" + +static int cam_context_handle_hw_event(void *context, uint32_t evt_id, + void *evt_data) +{ + int rc = 0; + struct cam_context *ctx = (struct cam_context *)context; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].irq_ops) + rc = ctx->state_machine[ctx->state].irq_ops(ctx, evt_id, + evt_data); + else + CAM_DBG(CAM_CORE, + "No function to handle event %d in dev %d, state %d", + evt_id, ctx->dev_hdl, ctx->state); + return rc; +} + +int cam_context_shutdown(struct cam_context *ctx) +{ + int rc = 0; + struct cam_release_dev_cmd cmd; + + if (ctx->state > CAM_CTX_AVAILABLE && ctx->state < CAM_CTX_STATE_MAX) { + cmd.session_handle = ctx->session_hdl; + cmd.dev_handle = ctx->dev_hdl; + rc = cam_context_handle_release_dev(ctx, &cmd); + if (rc) + CAM_ERR(CAM_CORE, + "context release failed for dev_name %s", + ctx->dev_name); + else + cam_context_putref(ctx); + } else { + CAM_WARN(CAM_CORE, + "dev %s context id %u state %d invalid to release hdl", + ctx->dev_name, ctx->ctx_id, ctx->state); + rc = -EINVAL; + } + + rc = cam_destroy_device_hdl(ctx->dev_hdl); + if (rc) + CAM_ERR(CAM_CORE, "destroy device hdl failed for node %s", + ctx->dev_name); + else + ctx->dev_hdl = -1; + + return rc; +} + +int cam_context_handle_crm_get_dev_info(struct cam_context *ctx, + struct cam_req_mgr_device_info *info) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!info) { + CAM_ERR(CAM_CORE, "Invalid get device info payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.get_dev_info) { + rc = ctx->state_machine[ctx->state].crm_ops.get_dev_info( + ctx, info); + } else { + CAM_ERR(CAM_CORE, "No get device info in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_crm_link(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *link) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!link) { + CAM_ERR(CAM_CORE, "Invalid link payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.link) { + rc = ctx->state_machine[ctx->state].crm_ops.link(ctx, link); + } else { + CAM_ERR(CAM_CORE, "No crm link in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_crm_unlink(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!unlink) { + CAM_ERR(CAM_CORE, "Invalid unlink payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.unlink) { + rc = ctx->state_machine[ctx->state].crm_ops.unlink( + ctx, unlink); + } else { + CAM_ERR(CAM_CORE, "No crm unlink in dev %d, name %s, state %d", + ctx->dev_hdl, ctx->dev_name, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_crm_apply_req(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!apply) { + CAM_ERR(CAM_CORE, "Invalid apply request payload"); + 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); + } else { + CAM_ERR(CAM_CORE, "No crm apply req in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_crm_flush_req(struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.flush_req) { + rc = ctx->state_machine[ctx->state].crm_ops.flush_req(ctx, + flush); + } else { + CAM_ERR(CAM_CORE, "No crm flush req in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_crm_process_evt(struct cam_context *ctx, + struct cam_req_mgr_link_evt_data *process_evt) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.process_evt) { + rc = ctx->state_machine[ctx->state].crm_ops.process_evt(ctx, + process_evt); + } else { + /* handling of this message is optional */ + CAM_DBG(CAM_CORE, "No crm process evt in dev %d, state %d", + ctx->dev_hdl, ctx->state); + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, + uint32_t buf_info) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].pagefault_ops) { + rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova, + buf_info); + } else { + CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", + ctx->dev_hdl, ctx->state); + } + + return rc; +} + +int cam_context_handle_acquire_dev(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + int i; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid acquire device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.acquire_dev) { + rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_dev( + ctx, cmd); + } else { + CAM_ERR(CAM_CORE, "No acquire device in dev %d, state %d", + cmd->dev_handle, ctx->state); + rc = -EPROTO; + } + + INIT_LIST_HEAD(&ctx->active_req_list); + INIT_LIST_HEAD(&ctx->wait_req_list); + INIT_LIST_HEAD(&ctx->pending_req_list); + INIT_LIST_HEAD(&ctx->free_req_list); + + for (i = 0; i < ctx->req_size; i++) { + INIT_LIST_HEAD(&ctx->req_list[i].list); + list_add_tail(&ctx->req_list[i].list, &ctx->free_req_list); + } + + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_acquire_hw(struct cam_context *ctx, + void *args) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!args) { + CAM_ERR(CAM_CORE, "Invalid acquire device hw command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.acquire_hw) { + rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_hw( + ctx, args); + } else { + CAM_ERR(CAM_CORE, "No acquire hw for dev %s, state %d", + ctx->dev_name, ctx->state); + rc = -EPROTO; + } + + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_release_dev(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid release device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.release_dev) { + rc = ctx->state_machine[ctx->state].ioctl_ops.release_dev( + ctx, cmd); + } else { + CAM_ERR(CAM_CORE, "No release device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_release_hw(struct cam_context *ctx, + void *args) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!args) { + CAM_ERR(CAM_CORE, "Invalid release HW command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.release_hw) { + rc = ctx->state_machine[ctx->state].ioctl_ops.release_hw( + ctx, args); + } else { + CAM_ERR(CAM_CORE, "No release hw for dev %s, state %d", + ctx->dev_name, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_flush_dev(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid flush device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.flush_dev) { + rc = ctx->state_machine[ctx->state].ioctl_ops.flush_dev( + ctx, cmd); + } else { + CAM_WARN(CAM_CORE, "No flush device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_config_dev(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid config device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.config_dev) { + rc = ctx->state_machine[ctx->state].ioctl_ops.config_dev( + ctx, cmd); + } else { + CAM_ERR(CAM_CORE, "No config device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_start_dev(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid start device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.start_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.start_dev( + ctx, cmd); + else + /* start device can be optional for some driver */ + CAM_DBG(CAM_CORE, "No start device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_handle_stop_dev(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid stop device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev( + ctx, cmd); + else + /* stop device can be optional for some driver */ + CAM_WARN(CAM_CORE, "No stop device in dev %d, name %s state %d", + ctx->dev_hdl, ctx->dev_name, ctx->state); + + ctx->last_flush_req = 0; + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + +int cam_context_init(struct cam_context *ctx, + const char *dev_name, + uint64_t dev_id, + uint32_t ctx_id, + struct cam_req_mgr_kmd_ops *crm_node_intf, + struct cam_hw_mgr_intf *hw_mgr_intf, + struct cam_ctx_request *req_list, + uint32_t req_size) +{ + int i; + + /* crm_node_intf is optinal */ + if (!ctx || !hw_mgr_intf || !req_list) { + CAM_ERR(CAM_CORE, "Invalid input parameters"); + return -EINVAL; + } + + memset(ctx, 0, sizeof(*ctx)); + ctx->dev_hdl = -1; + ctx->link_hdl = -1; + ctx->session_hdl = -1; + INIT_LIST_HEAD(&ctx->list); + mutex_init(&ctx->ctx_mutex); + mutex_init(&ctx->sync_mutex); + spin_lock_init(&ctx->lock); + + 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; + ctx->irq_cb_intf = cam_context_handle_hw_event; + + INIT_LIST_HEAD(&ctx->active_req_list); + INIT_LIST_HEAD(&ctx->wait_req_list); + INIT_LIST_HEAD(&ctx->pending_req_list); + INIT_LIST_HEAD(&ctx->free_req_list); + ctx->req_list = req_list; + ctx->req_size = req_size; + for (i = 0; i < req_size; i++) { + INIT_LIST_HEAD(&ctx->req_list[i].list); + list_add_tail(&ctx->req_list[i].list, &ctx->free_req_list); + ctx->req_list[i].ctx = ctx; + } + ctx->state = CAM_CTX_AVAILABLE; + ctx->state_machine = NULL; + ctx->ctx_priv = NULL; + + return 0; +} + +int cam_context_deinit(struct cam_context *ctx) +{ + if (!ctx) + return -EINVAL; + + /** + * This is called from platform device remove. + * Everyting should be released at this moment. + * so we just free the memory for the context + */ + if (ctx->state != CAM_CTX_AVAILABLE) + CAM_ERR(CAM_CORE, "Device did not shutdown cleanly"); + + memset(ctx, 0, sizeof(*ctx)); + + return 0; +} + +void cam_context_putref(struct cam_context *ctx) +{ + kref_put(&ctx->refcount, cam_node_put_ctxt_to_free_list); + CAM_DBG(CAM_CORE, + "ctx device hdl %ld, ref count %d, dev_name %s", + ctx->dev_hdl, refcount_read(&(ctx->refcount.refcount)), + ctx->dev_name); +} + +void cam_context_getref(struct cam_context *ctx) +{ + if (kref_get_unless_zero(&ctx->refcount) == 0) { + /* should never happen */ + WARN(1, "%s fail\n", __func__); + } + CAM_DBG(CAM_CORE, + "ctx device hdl %ld, ref count %d, dev_name %s", + ctx->dev_hdl, refcount_read(&(ctx->refcount.refcount)), + ctx->dev_name); +} diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h new file mode 100644 index 000000000000..55fd376f33d6 --- /dev/null +++ b/drivers/cam_core/cam_context.h @@ -0,0 +1,460 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CONTEXT_H_ +#define _CAM_CONTEXT_H_ + +#include +#include +#include +#include "cam_req_mgr_interface.h" +#include "cam_hw_mgr_intf.h" + +/* Forward declarations */ +struct cam_context; + +/* max request number */ +#define CAM_CTX_REQ_MAX 20 +#define CAM_CTX_CFG_MAX 20 +#define CAM_CTX_RES_MAX 20 + +/** + * enum cam_ctx_state - context top level states + * + */ +enum cam_context_state { + CAM_CTX_UNINIT = 0, + CAM_CTX_AVAILABLE = 1, + CAM_CTX_ACQUIRED = 2, + CAM_CTX_READY = 3, + CAM_CTX_ACTIVATED = 4, + CAM_CTX_STATE_MAX = 5, +}; + +/** + * struct cam_ctx_request - Common request structure for the context + * + * @list: Link list entry + * @status: Request status + * @request_id: Request id + * @req_priv: Derived request object + * @hw_update_entries: Hardware update entries + * @num_hw_update_entries: Number of hardware update entries + * @in_map_entries: Entries for in fences + * @num_in_map_entries: Number of in map entries + * @out_map_entries: Entries for out fences + * @num_out_map_entries: Number of out map entries + * @num_in_acked: Number of in fence acked + * @num_out_acked: Number of out fence acked + * @flushed: Request is flushed + * @ctx: The context to which this request belongs + * @pf_data page fault debug data + * + */ +struct cam_ctx_request { + struct list_head list; + uint32_t status; + uint64_t request_id; + void *req_priv; + struct cam_hw_update_entry hw_update_entries[CAM_CTX_CFG_MAX]; + uint32_t num_hw_update_entries; + struct cam_hw_fence_map_entry in_map_entries[CAM_CTX_CFG_MAX]; + uint32_t num_in_map_entries; + struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX]; + uint32_t num_out_map_entries; + atomic_t num_in_acked; + uint32_t num_out_acked; + int flushed; + struct cam_context *ctx; + struct cam_hw_mgr_dump_pf_data pf_data; +}; + +/** + * struct cam_ctx_ioctl_ops - Function table for handling IOCTL calls + * + * @acquire_dev: Function pointer for acquire device + * @release_dev: Function pointer for release device + * @config_dev: Function pointer for config device + * @start_dev: Function pointer for start device + * @stop_dev: Function pointer for stop device + * @flush_dev: Function pointer for flush device + * @acquire_hw: Function pointer for acquire hw + * @release_hw: Function pointer for release hw + * + */ +struct cam_ctx_ioctl_ops { + int (*acquire_dev)(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd); + int (*release_dev)(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd); + int (*config_dev)(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd); + int (*start_dev)(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd); + int (*stop_dev)(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd); + int (*flush_dev)(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd); + int (*acquire_hw)(struct cam_context *ctx, void *args); + int (*release_hw)(struct cam_context *ctx, void *args); +}; + +/** + * struct cam_ctx_crm_ops - Function table for handling CRM to context calls + * + * @get_dev_info: Get device informaiton + * @link: Link the context + * @unlink: Unlink the context + * @apply_req: Apply setting for the context + * @flush_req: Flush request to remove request ids + * @process_evt: Handle event notification from CRM.(optional) + * + */ +struct cam_ctx_crm_ops { + int (*get_dev_info)(struct cam_context *ctx, + struct cam_req_mgr_device_info *device_info); + int (*link)(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *link); + int (*unlink)(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink); + int (*apply_req)(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply); + int (*flush_req)(struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush); + int (*process_evt)(struct cam_context *ctx, + struct cam_req_mgr_link_evt_data *evt_data); +}; + + +/** + * struct cam_ctx_ops - Collection of the interface funciton tables + * + * @ioctl_ops: Ioctl funciton table + * @crm_ops: CRM to context interface function table + * @irq_ops: Hardware event handle function + * @pagefault_ops: Function to be called on page fault + * + */ +struct cam_ctx_ops { + struct cam_ctx_ioctl_ops ioctl_ops; + struct cam_ctx_crm_ops crm_ops; + cam_hw_event_cb_func irq_ops; + cam_hw_pagefault_cb_func pagefault_ops; +}; + +/** + * struct cam_context - camera context object for the subdevice node + * + * @dev_name: String giving name of device associated + * @dev_id: ID of device associated + * @ctx_id: ID for this context + * @list: Link list entry + * @sessoin_hdl: Session handle + * @dev_hdl: Device handle + * @link_hdl: Link handle + * @ctx_mutex: Mutex for ioctl calls + * @lock: Spin lock + * @active_req_list: Requests pending for done event + * @pending_req_list: Requests pending for reg upd event + * @wait_req_list: Requests waiting for apply + * @free_req_list: Requests that are free + * @req_list: Reference to the request storage + * @req_size: Size of the request storage + * @hw_mgr_intf: Context to HW interface + * @ctx_crm_intf: Context to CRM interface + * @crm_ctx_intf: CRM to context interface + * @irq_cb_intf: HW to context callback interface + * @state: Current state for top level state machine + * @state_machine: Top level state machine + * @ctx_priv: Private context pointer + * @ctxt_to_hw_map: Context to hardware mapping pointer + * @refcount: Context object refcount + * @node: The main node to which this context belongs + * @sync_mutex: mutex to sync with sync cb thread + * @last_flush_req: Last request to flush + * + */ +struct cam_context { + const char *dev_name; + uint64_t dev_id; + uint32_t ctx_id; + struct list_head list; + int32_t session_hdl; + int32_t dev_hdl; + int32_t link_hdl; + + struct mutex ctx_mutex; + spinlock_t lock; + + struct list_head active_req_list; + struct list_head pending_req_list; + struct list_head wait_req_list; + struct list_head free_req_list; + struct cam_ctx_request *req_list; + uint32_t req_size; + + struct cam_hw_mgr_intf *hw_mgr_intf; + struct cam_req_mgr_crm_cb *ctx_crm_intf; + struct cam_req_mgr_kmd_ops *crm_ctx_intf; + cam_hw_event_cb_func irq_cb_intf; + + enum cam_context_state state; + struct cam_ctx_ops *state_machine; + + void *ctx_priv; + void *ctxt_to_hw_map; + + struct kref refcount; + void *node; + struct mutex sync_mutex; + uint32_t last_flush_req; +}; + +/** + * cam_context_shutdown() + * + * @brief: Calls while device close or shutdown + * + * @ctx: Object pointer for cam_context + * + */ +int cam_context_shutdown(struct cam_context *ctx); + +/** + * cam_context_handle_crm_get_dev_info() + * + * @brief: Handle get device information command + * + * @ctx: Object pointer for cam_context + * @info: Device information returned + * + */ +int cam_context_handle_crm_get_dev_info(struct cam_context *ctx, + struct cam_req_mgr_device_info *info); + +/** + * cam_context_handle_crm_link() + * + * @brief: Handle link command + * + * @ctx: Object pointer for cam_context + * @link: Link command payload + * + */ +int cam_context_handle_crm_link(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *link); + +/** + * cam_context_handle_crm_unlink() + * + * @brief: Handle unlink command + * + * @ctx: Object pointer for cam_context + * @unlink: Unlink command payload + * + */ +int cam_context_handle_crm_unlink(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink); + +/** + * cam_context_handle_crm_apply_req() + * + * @brief: Handle apply request command + * + * @ctx: Object pointer for cam_context + * @apply: Apply request command payload + * + */ +int cam_context_handle_crm_apply_req(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply); + +/** + * cam_context_handle_crm_flush_req() + * + * @brief: Handle flush request command + * + * @ctx: Object pointer for cam_context + * @apply: Flush request command payload + * + */ +int cam_context_handle_crm_flush_req(struct cam_context *ctx, + struct cam_req_mgr_flush_request *apply); + +/** + * cam_context_handle_crm_process_evt() + * + * @brief: Handle process event command + * + * @ctx: Object pointer for cam_context + * @process_evt: process event command payload + * + */ +int cam_context_handle_crm_process_evt(struct cam_context *ctx, + struct cam_req_mgr_link_evt_data *process_evt); + +/** + * cam_context_dump_pf_info() + * + * @brief: Handle dump active request request command + * + * @ctx: Object pointer for cam_context + * @iova: Page fault address + * @buf_info: Information about closest memory handle + * + */ +int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, + uint32_t buf_info); + +/** + * cam_context_handle_acquire_dev() + * + * @brief: Handle acquire device command + * + * @ctx: Object pointer for cam_context + * @cmd: Acquire device command payload + * + */ +int cam_context_handle_acquire_dev(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd); + +/** + * cam_context_handle_acquire_hw() + * + * @brief: Handle acquire HW command + * + * @ctx: Object pointer for cam_context + * @cmd: Acquire HW command payload + * + */ +int cam_context_handle_acquire_hw(struct cam_context *ctx, + void *cmd); + +/** + * cam_context_handle_release_dev() + * + * @brief: Handle release device command + * + * @ctx: Object pointer for cam_context + * @cmd: Release device command payload + * + */ +int cam_context_handle_release_dev(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd); + +/** + * cam_context_handle_release_hw() + * + * @brief: Handle release HW command + * + * @ctx: Object pointer for cam_context + * @cmd: Release HW command payload + * + */ +int cam_context_handle_release_hw(struct cam_context *ctx, + void *cmd); + +/** + * cam_context_handle_config_dev() + * + * @brief: Handle config device command + * + * @ctx: Object pointer for cam_context + * @cmd: Config device command payload + * + */ +int cam_context_handle_config_dev(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd); + +/** + * cam_context_handle_flush_dev() + * + * @brief: Handle flush device command + * + * @ctx: Object pointer for cam_context + * @cmd: Flush device command payload + * + */ +int cam_context_handle_flush_dev(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd); + +/** + * cam_context_handle_start_dev() + * + * @brief: Handle start device command + * + * @ctx: Object pointer for cam_context + * @cmd: Start device command payload + * + */ +int cam_context_handle_start_dev(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd); + +/** + * cam_context_handle_stop_dev() + * + * @brief: Handle stop device command + * + * @ctx: Object pointer for cam_context + * @cmd: Stop device command payload + * + */ +int cam_context_handle_stop_dev(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd); + +/** + * cam_context_deinit() + * + * @brief: Camera context deinitialize function + * + * @ctx: Object pointer for cam_context + * + */ +int cam_context_deinit(struct cam_context *ctx); + +/** + * cam_context_init() + * + * @brief: Camera context initialize function + * + * @ctx: Object pointer for cam_context + * @dev_name: String giving name of device associated + * @dev_id: ID of the device associated + * @ctx_id: ID for this context + * @crm_node_intf: Function table for crm to context interface + * @hw_mgr_intf: Function table for context to hw interface + * @req_list: Requests storage + * @req_size: Size of the request storage + * + */ +int cam_context_init(struct cam_context *ctx, + const char *dev_name, + uint64_t dev_id, + uint32_t ctx_id, + struct cam_req_mgr_kmd_ops *crm_node_intf, + struct cam_hw_mgr_intf *hw_mgr_intf, + struct cam_ctx_request *req_list, + uint32_t req_size); + +/** + * cam_context_putref() + * + * @brief: Put back context reference. + * + * @ctx: Context for which ref is returned + * + */ +void cam_context_putref(struct cam_context *ctx); + +/** + * cam_context_getref() + * + * @brief: Get back context reference. + * + * @ctx: Context for which ref is taken + * + */ +void cam_context_getref(struct cam_context *ctx); + +#endif /* _CAM_CONTEXT_H_ */ diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c new file mode 100644 index 000000000000..6b6b17743d1b --- /dev/null +++ b/drivers/cam_core/cam_context_utils.c @@ -0,0 +1,1018 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_context.h" +#include "cam_context_utils.h" +#include "cam_mem_mgr.h" +#include "cam_node.h" +#include "cam_req_mgr_util.h" +#include "cam_sync_api.h" +#include "cam_trace.h" +#include "cam_debug_util.h" + +static uint cam_debug_ctx_req_list; +module_param(cam_debug_ctx_req_list, uint, 0644); + +static inline int cam_context_validate_thread(void) +{ + if (in_interrupt()) { + WARN(1, "Invalid execution context\n"); + return -EINVAL; + } + return 0; +} + +int cam_context_buf_done_from_hw(struct cam_context *ctx, + void *done_event_data, uint32_t bubble_state) +{ + int j; + int result; + struct cam_ctx_request *req; + struct cam_hw_done_event_data *done = + (struct cam_hw_done_event_data *)done_event_data; + int rc; + + if (!ctx || !done) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, done); + return -EINVAL; + } + + rc = cam_context_validate_thread(); + if (rc) + return rc; + + spin_lock(&ctx->lock); + if (list_empty(&ctx->active_req_list)) { + CAM_ERR(CAM_CTXT, "[%s][%d] no active request", + ctx->dev_name, ctx->ctx_id); + spin_unlock(&ctx->lock); + return -EIO; + } + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + + trace_cam_buf_done("UTILS", ctx, req); + + if (done->request_id != req->request_id) { + CAM_ERR(CAM_CTXT, + "[%s][%d] mismatch: done req[%lld], active req[%lld]", + ctx->dev_name, ctx->ctx_id, + done->request_id, req->request_id); + spin_unlock(&ctx->lock); + return -EIO; + } + + if (!req->num_out_map_entries) { + CAM_ERR(CAM_CTXT, "[%s][%d] no output fence to signal", + ctx->dev_name, ctx->ctx_id); + spin_unlock(&ctx->lock); + return -EIO; + } + + /* + * since another thread may be adding/removing from active + * list, so hold the lock + */ + list_del_init(&req->list); + spin_unlock(&ctx->lock); + if (!bubble_state) { + result = CAM_SYNC_STATE_SIGNALED_SUCCESS; + } else { + CAM_DBG(CAM_REQ, + "[%s][ctx_id %d] : req[%llu] is done with error", + ctx->dev_name, ctx->ctx_id, req->request_id); + + for (j = 0; j < req->num_out_map_entries; j++) + CAM_DBG(CAM_REQ, "fence %d signaled with error", + req->out_map_entries[j].sync_id); + + result = CAM_SYNC_STATE_SIGNALED_ERROR; + } + + for (j = 0; j < req->num_out_map_entries; j++) { + cam_sync_signal(req->out_map_entries[j].sync_id, result); + req->out_map_entries[j].sync_id = -1; + } + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from active_list to free_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + + /* + * another thread may be adding/removing from free list, + * so hold the lock + */ + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + req->ctx = NULL; + spin_unlock(&ctx->lock); + + return 0; +} + +static int cam_context_apply_req_to_hw(struct cam_ctx_request *req, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_context *ctx = req->ctx; + struct cam_hw_config_args cfg; + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + spin_lock(&ctx->lock); + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from pending_list to active_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + + cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + cfg.request_id = req->request_id; + cfg.hw_update_entries = req->hw_update_entries; + cfg.num_hw_update_entries = req->num_hw_update_entries; + cfg.out_map_entries = req->out_map_entries; + cfg.num_out_map_entries = req->num_out_map_entries; + cfg.priv = req->req_priv; + + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc) { + spin_lock(&ctx->lock); + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from active_list to free_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + } + +end: + return rc; +} + +static void cam_context_sync_callback(int32_t sync_obj, int status, void *data) +{ + struct cam_ctx_request *req = data; + struct cam_context *ctx = NULL; + struct cam_flush_dev_cmd flush_cmd; + struct cam_req_mgr_apply_request apply; + int rc; + + if (!req) { + CAM_ERR(CAM_CTXT, "Invalid input param"); + return; + } + rc = cam_context_validate_thread(); + if (rc) + return; + + ctx = req->ctx; + if (!ctx) { + CAM_ERR(CAM_CTXT, "Invalid ctx for req %llu", req->request_id); + return; + } + + if (atomic_inc_return(&req->num_in_acked) == req->num_in_map_entries) { + apply.request_id = req->request_id; + /* + * take mutex to ensure that another thread does + * not flush the request while this + * thread is submitting it to h/w. The submit to + * h/w and adding to the active list should happen + * in a critical section which is provided by this + * mutex. + */ + if (status == CAM_SYNC_STATE_SIGNALED_ERROR) { + CAM_DBG(CAM_CTXT, "fence error: %d", sync_obj); + flush_cmd.req_id = req->request_id; + cam_context_flush_req_to_hw(ctx, &flush_cmd); + } + + mutex_lock(&ctx->sync_mutex); + if (!req->flushed) { + cam_context_apply_req_to_hw(req, &apply); + mutex_unlock(&ctx->sync_mutex); + } else { + req->flushed = 0; + req->ctx = NULL; + mutex_unlock(&ctx->sync_mutex); + spin_lock(&ctx->lock); + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from pending_list to free_list", + ctx->dev_name, ctx->ctx_id, + req->request_id); + } + } + cam_context_putref(ctx); +} + +int32_t cam_context_release_dev_to_hw(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + struct cam_hw_release_args arg; + + if (!ctx) { + CAM_ERR(CAM_CTXT, "Invalid input param"); + return -EINVAL; + } + + if ((!ctx->hw_mgr_intf) || (!ctx->hw_mgr_intf->hw_release)) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + return -EINVAL; + } + + arg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + arg.active_req = false; + + ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &arg); + ctx->ctxt_to_hw_map = NULL; + + ctx->session_hdl = -1; + ctx->dev_hdl = -1; + ctx->link_hdl = -1; + + return 0; +} + +int32_t cam_context_config_dev_to_hw( + struct cam_context *ctx, struct cam_config_dev_cmd *cmd) +{ + int rc = 0; + size_t len; + struct cam_hw_stream_setttings cfg; + uintptr_t packet_addr; + struct cam_packet *packet; + + if (!ctx || !cmd) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + return -EINVAL; + } + + if (!ctx->hw_mgr_intf->hw_config_stream_settings) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + return rc; + } + + rc = cam_context_validate_thread(); + if (rc) { + CAM_ERR(CAM_CTXT, + "Not executing in the right context"); + return rc; + } + + rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, + &packet_addr, &len); + if (rc) { + CAM_ERR(CAM_CTXT, "[%s][%d] Can not get packet address", + ctx->dev_name, ctx->ctx_id); + rc = -EINVAL; + return rc; + } + + packet = (struct cam_packet *) ((uint8_t *)packet_addr + + (uint32_t)cmd->offset); + + memset(&cfg, 0, sizeof(cfg)); + cfg.packet = packet; + cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + cfg.priv = NULL; + + CAM_DBG(CAM_CTXT, "Processing config settings"); + rc = ctx->hw_mgr_intf->hw_config_stream_settings( + ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc) { + CAM_ERR(CAM_CTXT, + "[%s][%d] Config failed stream settings", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + } + + return rc; +} + +int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc = 0; + struct cam_ctx_request *req = NULL; + struct cam_hw_prepare_update_args cfg; + 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) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + return -EINVAL; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + return -EFAULT; + } + rc = cam_context_validate_thread(); + if (rc) + return rc; + + spin_lock(&ctx->lock); + if (!list_empty(&ctx->free_req_list)) { + req = list_first_entry(&ctx->free_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + } + spin_unlock(&ctx->lock); + + if (!req) { + CAM_ERR(CAM_CTXT, "[%s][%d] No more request obj free", + ctx->dev_name, ctx->ctx_id); + return -ENOMEM; + } + + memset(req, 0, sizeof(*req)); + INIT_LIST_HEAD(&req->list); + req->ctx = ctx; + + /* for config dev, only memory handle is supported */ + /* map packet from the memhandle */ + rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, + &packet_addr, &len); + if (rc != 0) { + CAM_ERR(CAM_CTXT, "[%s][%d] Can not get packet address", + ctx->dev_name, ctx->ctx_id); + rc = -EINVAL; + goto free_req; + } + + if ((len < sizeof(struct cam_packet)) || + (cmd->offset >= (len - sizeof(struct cam_packet)))) { + CAM_ERR(CAM_CTXT, "Not enough buf"); + return -EINVAL; + + } + 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); + rc = -EINVAL; + goto free_req; + } + + 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_ERR(CAM_CORE, + "request %lld has been flushed, reject packet", + packet->header.request_id); + rc = -EINVAL; + 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->ctxt_to_hw_map; + cfg.max_hw_update_entries = CAM_CTX_CFG_MAX; + cfg.num_hw_update_entries = req->num_hw_update_entries; + cfg.hw_update_entries = req->hw_update_entries; + cfg.max_out_map_entries = CAM_CTX_CFG_MAX; + cfg.out_map_entries = req->out_map_entries; + cfg.max_in_map_entries = CAM_CTX_CFG_MAX; + cfg.in_map_entries = req->in_map_entries; + cfg.pf_data = &(req->pf_data); + + rc = ctx->hw_mgr_intf->hw_prepare_update( + ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc != 0) { + CAM_ERR(CAM_CTXT, + "[%s][%d] Prepare config packet failed in HW layer", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto free_req; + } + req->num_hw_update_entries = cfg.num_hw_update_entries; + req->num_out_map_entries = cfg.num_out_map_entries; + req->num_in_map_entries = cfg.num_in_map_entries; + atomic_set(&req->num_in_acked, 0); + req->request_id = packet->header.request_id; + req->status = 1; + req->req_priv = cfg.priv; + + for (i = 0; i < req->num_out_map_entries; i++) { + rc = cam_sync_get_obj_ref(req->out_map_entries[i].sync_id); + if (rc) { + CAM_ERR(CAM_CTXT, "Can't get ref for sync %d", + req->out_map_entries[i].sync_id); + goto put_ref; + } + } + + if (req->num_in_map_entries > 0) { + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->pending_req_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from free_list to pending_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + + for (j = 0; j < req->num_in_map_entries; j++) { + cam_context_getref(ctx); + rc = cam_sync_register_callback( + cam_context_sync_callback, + (void *)req, + req->in_map_entries[j].sync_id); + if (rc) { + CAM_ERR(CAM_CTXT, + "[%s][%d] Failed register fence cb: %d ret = %d", + ctx->dev_name, ctx->ctx_id, + req->in_map_entries[j].sync_id, rc); + spin_lock(&ctx->lock); + list_del_init(&req->list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from pending_list to free_list", + ctx->dev_name, ctx->ctx_id, + req->request_id); + + goto put_ctx_ref; + } + CAM_DBG(CAM_CTXT, "register in fence cb: %d ret = %d", + req->in_map_entries[j].sync_id, rc); + } + } + + return rc; +put_ctx_ref: + for (j; j >= 0; j--) + cam_context_putref(ctx); +put_ref: + for (--i; i >= 0; i--) { + if (cam_sync_put_obj_ref(req->out_map_entries[i].sync_id)) + CAM_ERR(CAM_CTXT, "Failed to put ref of fence %d", + req->out_map_entries[i].sync_id); + } +free_req: + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + req->ctx = NULL; + spin_unlock(&ctx->lock); + + return rc; +} + +int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + struct cam_hw_acquire_args param; + struct cam_create_dev_hdl req_hdl_param; + struct cam_hw_release_args release; + + if (!ctx || !cmd) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + CAM_DBG(CAM_CTXT, "ses hdl: %x, num_res: %d, type: %d, res: %lld", + cmd->session_handle, cmd->num_resources, cmd->handle_type, + cmd->resource_hdl); + + if (cmd->num_resources > CAM_CTX_RES_MAX) { + CAM_ERR(CAM_CTXT, "[%s][%d] resource limit exceeded", + ctx->dev_name, ctx->ctx_id); + rc = -ENOMEM; + goto end; + } + + /* for now we only support user pointer */ + if (cmd->handle_type != 1) { + CAM_ERR(CAM_CTXT, "[%s][%d] Only user pointer is supported", + ctx->dev_name, ctx->ctx_id); + rc = -EINVAL; + goto end; + } + + /* fill in parameters */ + param.context_data = ctx; + param.event_cb = ctx->irq_cb_intf; + param.num_acq = cmd->num_resources; + param.acquire_info = cmd->resource_hdl; + + /* call HW manager to reserve the resource */ + rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, + ¶m); + if (rc != 0) { + CAM_ERR(CAM_CTXT, "[%s][%d] Acquire device failed", + ctx->dev_name, ctx->ctx_id); + goto end; + } + + ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + + /* if hw resource acquire successful, acquire dev handle */ + req_hdl_param.session_hdl = cmd->session_handle; + /* bridge is not ready for these flags. so false for now */ + req_hdl_param.v4l2_sub_dev_flag = 0; + req_hdl_param.media_entity_flag = 0; + req_hdl_param.priv = ctx; + req_hdl_param.ops = ctx->crm_ctx_intf; + + ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param); + if (ctx->dev_hdl <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_CTXT, "[%s][%d] Can not create device handle", + ctx->dev_name, ctx->ctx_id); + goto free_hw; + } + cmd->dev_handle = ctx->dev_hdl; + + /* store session information */ + ctx->session_hdl = cmd->session_handle; + + return rc; + +free_hw: + release.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); + ctx->ctxt_to_hw_map = NULL; + ctx->dev_hdl = -1; +end: + return rc; +} + +int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) +{ + struct cam_hw_flush_args flush_args; + struct list_head temp_list; + struct cam_ctx_request *req; + uint32_t i; + int rc = 0; + bool free_req; + + CAM_DBG(CAM_CTXT, "[%s] E: NRT flush ctx", ctx->dev_name); + memset(&flush_args, 0, sizeof(flush_args)); + + /* + * flush pending requests, take the sync lock to synchronize with the + * sync callback thread so that the sync cb thread does not try to + * submit request to h/w while the request is being flushed + */ + mutex_lock(&ctx->sync_mutex); + INIT_LIST_HEAD(&temp_list); + spin_lock(&ctx->lock); + list_splice_init(&ctx->pending_req_list, &temp_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving all pending requests from pending_list to temp_list", + ctx->dev_name, ctx->ctx_id); + + flush_args.num_req_pending = 0; + while (true) { + spin_lock(&ctx->lock); + if (list_empty(&temp_list)) { + spin_unlock(&ctx->lock); + break; + } + + req = list_first_entry(&temp_list, + struct cam_ctx_request, list); + + list_del_init(&req->list); + spin_unlock(&ctx->lock); + req->flushed = 1; + + flush_args.flush_req_pending[flush_args.num_req_pending++] = + req->req_priv; + + free_req = false; + for (i = 0; i < req->num_in_map_entries; i++) { + rc = cam_sync_deregister_callback( + cam_context_sync_callback, + (void *)req, + req->in_map_entries[i].sync_id); + if (!rc) { + cam_context_putref(ctx); + if (atomic_inc_return(&req->num_in_acked) == + req->num_in_map_entries) + free_req = true; + } + } + + for (i = 0; i < req->num_out_map_entries; i++) { + if (req->out_map_entries[i].sync_id != -1) { + rc = cam_sync_signal( + req->out_map_entries[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc == -EALREADY) { + CAM_ERR(CAM_CTXT, + "Req: %llu already signalled, sync_id:%d", + req->request_id, + req->out_map_entries[i].sync_id); + break; + } + } + } + + /* + * If we have deregistered the last sync callback, req will + * not be put on the free list. So put it on the free list here + */ + if (free_req) { + req->ctx = NULL; + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock(&ctx->lock); + } + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Deleting req[%llu] from temp_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + } + mutex_unlock(&ctx->sync_mutex); + + if (ctx->hw_mgr_intf->hw_flush) { + flush_args.num_req_active = 0; + spin_lock(&ctx->lock); + list_for_each_entry(req, &ctx->active_req_list, list) { + flush_args.flush_req_active[flush_args.num_req_active++] + = req->req_priv; + } + spin_unlock(&ctx->lock); + + if (flush_args.num_req_pending || flush_args.num_req_active) { + flush_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + flush_args.flush_type = CAM_FLUSH_TYPE_ALL; + ctx->hw_mgr_intf->hw_flush( + ctx->hw_mgr_intf->hw_mgr_priv, &flush_args); + } + } + + INIT_LIST_HEAD(&temp_list); + spin_lock(&ctx->lock); + list_splice_init(&ctx->active_req_list, &temp_list); + INIT_LIST_HEAD(&ctx->active_req_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving all requests from active_list to temp_list", + ctx->dev_name, ctx->ctx_id); + + while (true) { + spin_lock(&ctx->lock); + if (list_empty(&temp_list)) { + spin_unlock(&ctx->lock); + break; + } + req = list_first_entry(&temp_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + spin_unlock(&ctx->lock); + + for (i = 0; i < req->num_out_map_entries; i++) { + if (req->out_map_entries[i].sync_id != -1) { + rc = cam_sync_signal( + req->out_map_entries[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc == -EALREADY) { + CAM_ERR(CAM_CTXT, + "Req: %llu already signalled ctx: %pK dev_name: %s dev_handle: %d ctx_state: %d", + req->request_id, req->ctx, + req->ctx->dev_name, + req->ctx->dev_hdl, + req->ctx->state); + break; + } + } + } + + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock(&ctx->lock); + req->ctx = NULL; + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from temp_list to free_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + } + + CAM_DBG(CAM_CTXT, "[%s] X: NRT flush ctx", ctx->dev_name); + + return 0; +} + +int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + struct cam_ctx_request *req = NULL; + struct cam_hw_flush_args flush_args; + uint32_t i; + int32_t sync_id = 0; + int rc = 0; + bool free_req = false; + + CAM_DBG(CAM_CTXT, "[%s] E: NRT flush req", ctx->dev_name); + + memset(&flush_args, 0, sizeof(flush_args)); + flush_args.num_req_pending = 0; + flush_args.num_req_active = 0; + mutex_lock(&ctx->sync_mutex); + spin_lock(&ctx->lock); + list_for_each_entry(req, &ctx->pending_req_list, list) { + if (req->request_id != cmd->req_id) + continue; + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Deleting req[%llu] from pending_list", + ctx->dev_name, ctx->ctx_id, req->request_id); + + list_del_init(&req->list); + req->flushed = 1; + + flush_args.flush_req_pending[flush_args.num_req_pending++] = + req->req_priv; + break; + } + spin_unlock(&ctx->lock); + mutex_unlock(&ctx->sync_mutex); + + if (ctx->hw_mgr_intf->hw_flush) { + if (!flush_args.num_req_pending) { + spin_lock(&ctx->lock); + list_for_each_entry(req, &ctx->active_req_list, list) { + if (req->request_id != cmd->req_id) + continue; + + list_del_init(&req->list); + + flush_args.flush_req_active[ + flush_args.num_req_active++] = + req->req_priv; + break; + } + spin_unlock(&ctx->lock); + } + + if (flush_args.num_req_pending || flush_args.num_req_active) { + flush_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + flush_args.flush_type = CAM_FLUSH_TYPE_REQ; + ctx->hw_mgr_intf->hw_flush( + ctx->hw_mgr_intf->hw_mgr_priv, &flush_args); + } + } + + if (req) { + if (flush_args.num_req_pending) { + for (i = 0; i < req->num_in_map_entries; i++) { + rc = cam_sync_deregister_callback( + cam_context_sync_callback, + (void *)req, + req->in_map_entries[i].sync_id); + if (rc) + continue; + + cam_context_putref(ctx); + if (atomic_inc_return(&req->num_in_acked) == + req->num_in_map_entries) + free_req = true; + } + } + + if (flush_args.num_req_pending || flush_args.num_req_active) { + for (i = 0; i < req->num_out_map_entries; i++) { + sync_id = + req->out_map_entries[i].sync_id; + if (sync_id != -1) { + rc = cam_sync_signal(sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc == -EALREADY) { + CAM_ERR(CAM_CTXT, + "Req: %llu already signalled, sync_id:%d", + req->request_id, sync_id); + break; + } + } + } + if (flush_args.num_req_active || free_req) { + req->ctx = NULL; + spin_lock(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock(&ctx->lock); + + if (cam_debug_ctx_req_list & ctx->dev_id) + CAM_INFO(CAM_CTXT, + "[%s][%d] : Moving req[%llu] from %s to free_list", + ctx->dev_name, ctx->ctx_id, + req->request_id, + flush_args.num_req_active ? + "active_list" : + "pending_list"); + } + } + } + CAM_DBG(CAM_CTXT, "[%s] X: NRT flush req", ctx->dev_name); + + return 0; +} + +int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + + int rc = 0; + + if (!ctx || !cmd) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + if (cmd->flush_type == CAM_FLUSH_TYPE_ALL) { + ctx->last_flush_req = cmd->req_id; + rc = cam_context_flush_ctx_to_hw(ctx); + } else if (cmd->flush_type == CAM_FLUSH_TYPE_REQ) + rc = cam_context_flush_req_to_hw(ctx, cmd); + else { + rc = -EINVAL; + CAM_ERR(CAM_CORE, "[%s][%d] Invalid flush type %d", + ctx->dev_name, ctx->ctx_id, cmd->flush_type); + } + +end: + return rc; +} + +int32_t cam_context_start_dev_to_hw(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + struct cam_hw_start_args arg; + + if (!ctx || !cmd) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + if ((cmd->session_handle != ctx->session_hdl) || + (cmd->dev_handle != ctx->dev_hdl)) { + CAM_ERR(CAM_CTXT, + "[%s][%d] Invalid session hdl[%d], dev_handle[%d]", + ctx->dev_name, ctx->ctx_id, + cmd->session_handle, cmd->dev_handle); + rc = -EPERM; + goto end; + } + + if (ctx->hw_mgr_intf->hw_start) { + arg.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, + &arg); + if (rc) { + /* HW failure. user need to clean up the resource */ + CAM_ERR(CAM_CTXT, "[%s][%d] Start HW failed", + ctx->dev_name, ctx->ctx_id); + goto end; + } + } + +end: + return rc; +} + +int32_t cam_context_stop_dev_to_hw(struct cam_context *ctx) +{ + int rc = 0; + struct cam_hw_stop_args stop; + + if (!ctx) { + CAM_ERR(CAM_CTXT, "Invalid input param"); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + rc = cam_context_validate_thread(); + if (rc) + goto end; + + rc = cam_context_flush_ctx_to_hw(ctx); + if (rc) + goto end; + + /* stop hw first */ + if (ctx->hw_mgr_intf->hw_stop) { + stop.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop); + } + +end: + return rc; +} + +int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, + struct cam_packet *packet, unsigned long iova, uint32_t buf_info, + bool *mem_found) +{ + int rc = 0; + struct cam_hw_cmd_args cmd_args; + + if (!ctx) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK ", ctx); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + if (ctx->hw_mgr_intf->hw_cmd) { + cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO; + cmd_args.u.pf_args.pf_data.packet = packet; + cmd_args.u.pf_args.iova = iova; + cmd_args.u.pf_args.buf_info = buf_info; + cmd_args.u.pf_args.mem_found = mem_found; + ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &cmd_args); + } + +end: + return rc; +} diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h new file mode 100644 index 000000000000..c3483327ba81 --- /dev/null +++ b/drivers/cam_core/cam_context_utils.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CONTEXT_UTILS_H_ +#define _CAM_CONTEXT_UTILS_H_ + +#include + +int cam_context_buf_done_from_hw(struct cam_context *ctx, + void *done_event_data, uint32_t bubble_state); +int32_t cam_context_release_dev_to_hw(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd); +int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd); +int32_t cam_context_config_dev_to_hw( + struct cam_context *ctx, struct cam_config_dev_cmd *cmd); +int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd); +int32_t cam_context_start_dev_to_hw(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd); +int32_t cam_context_stop_dev_to_hw(struct cam_context *ctx); +int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd); +int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx); +int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd); +int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, + struct cam_packet *packet, unsigned long iova, uint32_t buf_info, + bool *mem_found); + +#endif /* _CAM_CONTEXT_UTILS_H_ */ diff --git a/drivers/cam_core/cam_hw.h b/drivers/cam_core/cam_hw.h new file mode 100644 index 000000000000..8ee889fcffb9 --- /dev/null +++ b/drivers/cam_core/cam_hw.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_HW_H_ +#define _CAM_HW_H_ + +#include "cam_soc_util.h" + +/* + * This file declares Enums, Structures and APIs to be used as template + * when writing any HW driver in the camera subsystem. + */ + +/* Hardware state enum */ +enum cam_hw_state { + CAM_HW_STATE_POWER_DOWN, + CAM_HW_STATE_POWER_UP, +}; + +/** + * struct cam_hw_info - Common hardware information + * + * @hw_mutex: Hardware mutex + * @hw_lock: Hardware spinlock + * @hw_complete: Hardware Completion + * @open_count: Count to track the HW enable from the client + * @hw_state: Hardware state + * @soc_info: Platform SOC properties for hardware + * @node_info: Private HW data related to nodes + * @core_info: Private HW data related to core logic + * + */ +struct cam_hw_info { + struct mutex hw_mutex; + spinlock_t hw_lock; + struct completion hw_complete; + uint32_t open_count; + enum cam_hw_state hw_state; + struct cam_hw_soc_info soc_info; + void *node_info; + void *core_info; +}; + +#endif /* _CAM_HW_H_ */ diff --git a/drivers/cam_core/cam_hw_intf.h b/drivers/cam_core/cam_hw_intf.h new file mode 100644 index 000000000000..63e88dd24aea --- /dev/null +++ b/drivers/cam_core/cam_hw_intf.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_HW_INTF_H_ +#define _CAM_HW_INTF_H_ + +#include + +/* + * This file declares Constants, Enums, Structures and APIs to be used as + * Interface between HW driver and HW Manager. + */ + +/** + * struct cam_hw_ops - Hardware layer interface functions + * + * @get_hw_caps: Function pointer for get hw caps + * @init: Function poniter for initialize hardware + * @deinit: Function pointer for deinitialize hardware + * @reset: Function pointer for reset hardware + * @reserve: Function pointer for reserve hardware + * @release: Function pointer for release hardware + * @start: Function pointer for start hardware + * @stop: Function pointer for stop hardware + * @read: Function pointer for read hardware registers + * @write: Function pointer for Write hardware registers + * @process_cmd: Function pointer for additional hardware controls + * @flush_cmd: Function pointer for flush requests + * + */ +struct cam_hw_ops { + int (*get_hw_caps)(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size); + int (*init)(void *hw_priv, + void *init_hw_args, uint32_t arg_size); + int (*deinit)(void *hw_priv, + void *init_hw_args, uint32_t arg_size); + int (*reset)(void *hw_priv, + void *reset_core_args, uint32_t arg_size); + int (*reserve)(void *hw_priv, + void *reserve_args, uint32_t arg_size); + int (*release)(void *hw_priv, + void *release_args, uint32_t arg_size); + int (*start)(void *hw_priv, + void *start_args, uint32_t arg_size); + int (*stop)(void *hw_priv, + void *stop_args, uint32_t arg_size); + int (*read)(void *hw_priv, + void *read_args, uint32_t arg_size); + int (*write)(void *hw_priv, + void *write_args, uint32_t arg_size); + int (*process_cmd)(void *hw_priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size); + int (*flush)(void *hw_priv, + void *flush_args, uint32_t arg_size); +}; + +/** + * struct cam_hw_intf - Common hardware node + * + * @hw_type: Hardware type + * @hw_idx: Hardware ID + * @hw_ops: Hardware interface function table + * @hw_priv: Private hardware node pointer + * + */ +struct cam_hw_intf { + uint32_t hw_type; + uint32_t hw_idx; + struct cam_hw_ops hw_ops; + void *hw_priv; +}; + +/* hardware event callback function type */ +typedef int (*cam_hw_mgr_event_cb_func)(void *priv, uint32_t evt_id, + void *evt_data); + +#endif /* _CAM_HW_INTF_H_ */ diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h new file mode 100644 index 000000000000..56138c33091d --- /dev/null +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -0,0 +1,338 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_HW_MGR_INTF_H_ +#define _CAM_HW_MGR_INTF_H_ + +#include +#include +#include +/* + * This file declares Constants, Enums, Structures and APIs to be used as + * Interface between HW Manager and Context. + */ + + +/* maximum context numbers */ +#define CAM_CTX_MAX 8 + +/* maximum buf done irqs */ +#define CAM_NUM_OUT_PER_COMP_IRQ_MAX 12 + +/* hardware event callback function type */ +typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, + void *evt_data); + +/* hardware page fault callback function type */ +typedef int (*cam_hw_pagefault_cb_func)(void *context, unsigned long iova, + uint32_t buf_info); + +/** + * struct cam_hw_update_entry - Entry for hardware config + * + * @handle: Memory handle for the configuration + * @offset: Memory offset + * @len: Size of the configuration + * @flags: Flags for the config entry(eg. DMI) + * @addr: Address of hardware update entry + * + */ +struct cam_hw_update_entry { + int handle; + uint32_t offset; + uint32_t len; + uint32_t flags; + uintptr_t addr; +}; + +/** + * struct cam_hw_fence_map_entry - Entry for the resource to sync id map + * + * @resrouce_handle: Resource port id for the buffer + * @sync_id: Sync id + * + */ +struct cam_hw_fence_map_entry { + uint32_t resource_handle; + int32_t sync_id; +}; + +/** + * struct cam_hw_done_event_data - Payload for hw done event + * + * @num_handles: number of handles in the event + * @resrouce_handle: list of the resource handle + * @timestamp: time stamp + * @request_id: request identifier + * + */ +struct cam_hw_done_event_data { + uint32_t num_handles; + uint32_t resource_handle[CAM_NUM_OUT_PER_COMP_IRQ_MAX]; + struct timeval timestamp; + uint64_t request_id; +}; + +/** + * struct cam_hw_acquire_args - Payload for acquire command + * + * @context_data: Context data pointer for the callback function + * @event_cb: Callback function array + * @num_acq: Total number of acquire in the payload + * @acquire_info: Acquired resource array pointer + * @ctxt_to_hw_map: HW context (returned) + * @acquired_hw_id: Acquired hardware mask + * @acquired_hw_path: Acquired path mask for an input + * if input splits into multiple paths, + * its updated per hardware + * valid_acquired_hw: Valid num of acquired hardware + * + */ +struct cam_hw_acquire_args { + void *context_data; + cam_hw_event_cb_func event_cb; + uint32_t num_acq; + uint32_t acquire_info_size; + uintptr_t acquire_info; + void *ctxt_to_hw_map; + + uint32_t acquired_hw_id[CAM_MAX_ACQ_RES]; + uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; + uint32_t valid_acquired_hw; +}; + +/** + * struct cam_hw_release_args - Payload for release command + * + * @ctxt_to_hw_map: HW context from the acquire + * @active_req: Active request flag + * + */ +struct cam_hw_release_args { + void *ctxt_to_hw_map; + bool active_req; +}; + +/** + * struct cam_hw_start_args - Payload for start command + * + * @ctxt_to_hw_map: HW context from the acquire + * @num_hw_update_entries: Number of Hardware configuration + * @hw_update_entries: Hardware configuration list + * + */ +struct cam_hw_start_args { + void *ctxt_to_hw_map; + uint32_t num_hw_update_entries; + struct cam_hw_update_entry *hw_update_entries; +}; + +/** + * struct cam_hw_stop_args - Payload for stop command + * + * @ctxt_to_hw_map: HW context from the acquire + * @args: Arguments to pass for stop + * + */ +struct cam_hw_stop_args { + void *ctxt_to_hw_map; + void *args; +}; + + +/** + * struct cam_hw_mgr_dump_pf_data - page fault debug data + * + * packet: pointer to packet + */ +struct cam_hw_mgr_dump_pf_data { + void *packet; +}; + +/** + * 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) + * @num_hw_update_entries: Number of actual hardware update entries (returned) + * @max_out_map_entries: Maximum output fence mapping supported + * @out_map_entries: Actual output fence mapping list (returned) + * @num_out_map_entries: Number of actual output fence mapping (returned) + * @max_in_map_entries: Maximum input fence mapping supported + * @in_map_entries: Actual input fence mapping list (returned) + * @num_in_map_entries: Number of acutal input fence mapping (returned) + * @priv: Private pointer of hw update + * @pf_data: Debug data for page fault + * + */ +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; + uint32_t num_hw_update_entries; + uint32_t max_out_map_entries; + struct cam_hw_fence_map_entry *out_map_entries; + uint32_t num_out_map_entries; + uint32_t max_in_map_entries; + struct cam_hw_fence_map_entry *in_map_entries; + uint32_t num_in_map_entries; + void *priv; + struct cam_hw_mgr_dump_pf_data *pf_data; +}; + +/** + * struct cam_hw_stream_setttings - Payload for config stream command + * + * @packet: CSL packet from user mode driver + * @ctxt_to_hw_map: HW context from the acquire + * @priv: Private pointer of hw update + * + */ +struct cam_hw_stream_setttings { + struct cam_packet *packet; + void *ctxt_to_hw_map; + void *priv; +}; + +/** + * struct cam_hw_config_args - Payload for config command + * + * @ctxt_to_hw_map: HW context from the acquire + * @num_hw_update_entries: Number of hardware update entries + * @hw_update_entries: Hardware update list + * @out_map_entries: Out map info + * @num_out_map_entries: Number of out map entries + * @priv: Private pointer + * @request_id: Request ID + * + */ +struct cam_hw_config_args { + void *ctxt_to_hw_map; + uint32_t num_hw_update_entries; + struct cam_hw_update_entry *hw_update_entries; + struct cam_hw_fence_map_entry *out_map_entries; + uint32_t num_out_map_entries; + void *priv; + uint64_t request_id; + bool init_packet; +}; + +/** + * struct cam_hw_flush_args - Flush arguments + * + * @ctxt_to_hw_map: HW context from the acquire + * @num_req_pending: Num request to flush, valid when flush type is REQ + * @flush_req_pending: Request pending pointers to flush + * @num_req_active: Num request to flush, valid when flush type is REQ + * @flush_req_active: Request active pointers to flush + * @flush_type: The flush type + * + */ +struct cam_hw_flush_args { + void *ctxt_to_hw_map; + uint32_t num_req_pending; + void *flush_req_pending[20]; + uint32_t num_req_active; + void *flush_req_active[20]; + enum flush_type_t flush_type; +}; + +/** + * struct cam_hw_dump_pf_args - Payload for dump pf info command + * + * @pf_data: Debug data for page fault + * @iova: Page fault address + * @buf_info: Info about memory buffer where page + * fault occurred + * @mem_found: If fault memory found in current + * request + * + */ +struct cam_hw_dump_pf_args { + struct cam_hw_mgr_dump_pf_data pf_data; + unsigned long iova; + uint32_t buf_info; + bool *mem_found; +}; + +/* enum cam_hw_mgr_command - Hardware manager command type */ +enum cam_hw_mgr_command { + CAM_HW_MGR_CMD_INTERNAL, + CAM_HW_MGR_CMD_DUMP_PF_INFO, +}; + +/** + * struct cam_hw_cmd_args - Payload for hw manager command + * + * @ctxt_to_hw_map: HW context from the acquire + * @cmd_type HW command type + * @internal_args Arguments for internal command + * @pf_args Arguments for Dump PF info command + * + */ +struct cam_hw_cmd_args { + void *ctxt_to_hw_map; + uint32_t cmd_type; + union { + void *internal_args; + struct cam_hw_dump_pf_args pf_args; + } u; +}; + +/** + * cam_hw_mgr_intf - HW manager interface + * + * @hw_mgr_priv: HW manager object + * @hw_get_caps: Function pointer for get hw caps + * args = cam_query_cap_cmd + * @hw_acquire: Function poniter for acquire hw resources + * args = cam_hw_acquire_args + * @hw_release: Function pointer for release hw device resource + * args = cam_hw_release_args + * @hw_start: Function pointer for start hw devices + * args = cam_hw_start_args + * @hw_stop: Function pointer for stop hw devices + * args = cam_hw_stop_args + * @hw_prepare_update: Function pointer for prepare hw update for hw + * devices args = cam_hw_prepare_update_args + * @hw_config_stream_settings: Function pointer for configure stream for hw + * devices args = cam_hw_stream_setttings + * @hw_config: Function pointer for configure hw devices + * args = cam_hw_config_args + * @hw_read: Function pointer for read hardware registers + * @hw_write: Function pointer for Write hardware registers + * @hw_cmd: Function pointer for any customized commands for + * the hardware manager + * @hw_open: Function pointer for HW init + * @hw_close: Function pointer for HW deinit + * @hw_flush: Function pointer for HW flush + * + */ +struct cam_hw_mgr_intf { + void *hw_mgr_priv; + + int (*hw_get_caps)(void *hw_priv, void *hw_caps_args); + int (*hw_acquire)(void *hw_priv, void *hw_acquire_args); + int (*hw_release)(void *hw_priv, void *hw_release_args); + int (*hw_start)(void *hw_priv, void *hw_start_args); + int (*hw_stop)(void *hw_priv, void *hw_stop_args); + int (*hw_prepare_update)(void *hw_priv, void *hw_prepare_update_args); + int (*hw_config_stream_settings)(void *hw_priv, + void *hw_stream_settings); + int (*hw_config)(void *hw_priv, void *hw_config_args); + int (*hw_read)(void *hw_priv, void *read_args); + int (*hw_write)(void *hw_priv, void *write_args); + int (*hw_cmd)(void *hw_priv, void *write_args); + int (*hw_open)(void *hw_priv, void *fw_download_args); + int (*hw_close)(void *hw_priv, void *hw_close_args); + int (*hw_flush)(void *hw_priv, void *hw_flush_args); +}; + +#endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c new file mode 100644 index 000000000000..1ef4aa59302e --- /dev/null +++ b/drivers/cam_core/cam_node.c @@ -0,0 +1,836 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_node.h" +#include "cam_trace.h" +#include "cam_debug_util.h" + +static void cam_node_print_ctx_state( + struct cam_node *node) +{ + int i; + struct cam_context *ctx; + + CAM_INFO(CAM_CORE, "[%s] state=%d, ctx_size %d", + node->name, node->state, node->ctx_size); + + mutex_lock(&node->list_mutex); + for (i = 0; i < node->ctx_size; i++) { + ctx = &node->ctx_list[i]; + + spin_lock_bh(&ctx->lock); + CAM_INFO(CAM_CORE, + "[%s][%d] : state=%d, refcount=%d, active_req_list=%d, pending_req_list=%d, wait_req_list=%d, free_req_list=%d", + ctx->dev_name ? ctx->dev_name : "null", + i, ctx->state, + atomic_read(&(ctx->refcount.refcount.refs)), + list_empty(&ctx->active_req_list), + list_empty(&ctx->pending_req_list), + list_empty(&ctx->wait_req_list), + list_empty(&ctx->free_req_list)); + spin_unlock_bh(&ctx->lock); + } + mutex_unlock(&node->list_mutex); +} + +static struct cam_context *cam_node_get_ctxt_from_free_list( + struct cam_node *node) +{ + struct cam_context *ctx = NULL; + + mutex_lock(&node->list_mutex); + if (!list_empty(&node->free_ctx_list)) { + ctx = list_first_entry(&node->free_ctx_list, + struct cam_context, list); + list_del_init(&ctx->list); + } + mutex_unlock(&node->list_mutex); + if (ctx) + kref_init(&ctx->refcount); + return ctx; +} + +void cam_node_put_ctxt_to_free_list(struct kref *ref) +{ + struct cam_context *ctx = + container_of(ref, struct cam_context, refcount); + struct cam_node *node = ctx->node; + + mutex_lock(&node->list_mutex); + list_add_tail(&ctx->list, &node->free_ctx_list); + mutex_unlock(&node->list_mutex); +} + +static int __cam_node_handle_query_cap(struct cam_node *node, + struct cam_query_cap_cmd *query) +{ + int rc = -EFAULT; + + if (!query) { + CAM_ERR(CAM_CORE, "Invalid params"); + return -EINVAL; + } + + if (node->hw_mgr_intf.hw_get_caps) { + rc = node->hw_mgr_intf.hw_get_caps( + node->hw_mgr_intf.hw_mgr_priv, query); + } + + return rc; +} + +static int __cam_node_handle_acquire_dev(struct cam_node *node, + struct cam_acquire_dev_cmd *acquire) +{ + int rc = 0; + struct cam_context *ctx = NULL; + + if (!acquire) + return -EINVAL; + + ctx = cam_node_get_ctxt_from_free_list(node); + if (!ctx) { + CAM_ERR(CAM_CORE, "No free ctx in free list node %s", + node->name); + cam_node_print_ctx_state(node); + + rc = -ENOMEM; + 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", + node->name); + goto free_ctx; + } + + CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d", + node->name, ctx->ctx_id); + + return 0; +free_ctx: + cam_context_putref(ctx); +err: + return rc; +} + +static int __cam_node_handle_acquire_hw_v1(struct cam_node *node, + struct cam_acquire_hw_cmd_v1 *acquire) +{ + int rc = 0; + struct cam_context *ctx = NULL; + + if (!acquire) + return -EINVAL; + + if (acquire->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (acquire->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(acquire->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + acquire->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_acquire_hw(ctx, acquire); + if (rc) { + CAM_ERR(CAM_CORE, "Acquire device failed for node %s", + node->name); + return rc; + } + + CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d", + node->name, ctx->ctx_id); + + return 0; +} + +static int __cam_node_handle_acquire_hw_v2(struct cam_node *node, + struct cam_acquire_hw_cmd_v2 *acquire) +{ + int rc = 0; + struct cam_context *ctx = NULL; + + if (!acquire) + return -EINVAL; + + if (acquire->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (acquire->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(acquire->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + acquire->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_acquire_hw(ctx, acquire); + if (rc) { + CAM_ERR(CAM_CORE, "Acquire device failed for node %s", + node->name); + return rc; + } + + CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d", + node->name, ctx->ctx_id); + + return 0; +} + +static int __cam_node_handle_start_dev(struct cam_node *node, + struct cam_start_stop_dev_cmd *start) +{ + struct cam_context *ctx = NULL; + int rc; + + if (!start) + return -EINVAL; + + if (start->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (start->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(start->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + start->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_start_dev(ctx, start); + if (rc) + CAM_ERR(CAM_CORE, "Start failure for node %s", node->name); + + return rc; +} + +static int __cam_node_handle_stop_dev(struct cam_node *node, + struct cam_start_stop_dev_cmd *stop) +{ + struct cam_context *ctx = NULL; + int rc; + + if (!stop) + return -EINVAL; + + if (stop->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (stop->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(stop->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + stop->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_stop_dev(ctx, stop); + if (rc) + CAM_ERR(CAM_CORE, "Stop failure for node %s", node->name); + + return rc; +} + +static int __cam_node_handle_config_dev(struct cam_node *node, + struct cam_config_dev_cmd *config) +{ + struct cam_context *ctx = NULL; + int rc; + + if (!config) + return -EINVAL; + + if (config->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (config->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(config->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + config->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_config_dev(ctx, config); + if (rc) + CAM_ERR(CAM_CORE, "Config failure for node %s", node->name); + + return rc; +} + +static int __cam_node_handle_flush_dev(struct cam_node *node, + struct cam_flush_dev_cmd *flush) +{ + struct cam_context *ctx = NULL; + int rc; + + if (!flush) + return -EINVAL; + + if (flush->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (flush->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(flush->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + flush->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_flush_dev(ctx, flush); + if (rc) + CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name); + + return rc; +} + +static int __cam_node_handle_release_dev(struct cam_node *node, + struct cam_release_dev_cmd *release) +{ + int rc = 0; + struct cam_context *ctx = NULL; + + if (!release) + return -EINVAL; + + if (release->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (release->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d node %s", + release->dev_handle, node->name); + return -EINVAL; + } + + if (ctx->state > CAM_CTX_UNINIT && ctx->state < CAM_CTX_STATE_MAX) { + rc = cam_context_handle_release_dev(ctx, release); + if (rc) + CAM_ERR(CAM_CORE, "context release failed for node %s", + node->name); + } else { + CAM_WARN(CAM_CORE, + "node %s context id %u state %d invalid to release hdl", + node->name, ctx->ctx_id, ctx->state); + goto destroy_dev_hdl; + } + + cam_context_putref(ctx); + +destroy_dev_hdl: + rc = cam_destroy_device_hdl(release->dev_handle); + if (rc) + CAM_ERR(CAM_CORE, "destroy device hdl failed for node %s", + node->name); + else + ctx->dev_hdl = -1; + + CAM_DBG(CAM_CORE, "[%s] Release ctx_id=%d, refcount=%d", + node->name, ctx->ctx_id, + atomic_read(&(ctx->refcount.refcount.refs))); + + return rc; +} + +static int __cam_node_handle_release_hw_v1(struct cam_node *node, + struct cam_release_hw_cmd_v1 *release) +{ + int rc = 0; + struct cam_context *ctx = NULL; + + if (!release) + return -EINVAL; + + if (release->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (release->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d node %s", + release->dev_handle, node->name); + return -EINVAL; + } + + rc = cam_context_handle_release_hw(ctx, release); + if (rc) + CAM_ERR(CAM_CORE, "context release failed node %s", node->name); + + CAM_DBG(CAM_CORE, "[%s] Release ctx_id=%d, refcount=%d", + node->name, ctx->ctx_id, + atomic_read(&(ctx->refcount.refcount.refs))); + + return rc; +} + +static int __cam_node_crm_get_dev_info(struct cam_req_mgr_device_info *info) +{ + struct cam_context *ctx = NULL; + + if (!info) + return -EINVAL; + + ctx = (struct cam_context *) cam_get_device_priv(info->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + info->dev_hdl); + return -EINVAL; + } + return cam_context_handle_crm_get_dev_info(ctx, info); +} + +static int __cam_node_crm_link_setup( + struct cam_req_mgr_core_dev_link_setup *setup) +{ + int rc; + struct cam_context *ctx = NULL; + + if (!setup) + return -EINVAL; + + ctx = (struct cam_context *) cam_get_device_priv(setup->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + setup->dev_hdl); + return -EINVAL; + } + + if (setup->link_enable) + rc = cam_context_handle_crm_link(ctx, setup); + else + rc = cam_context_handle_crm_unlink(ctx, setup); + + return rc; +} + +static int __cam_node_crm_apply_req(struct cam_req_mgr_apply_request *apply) +{ + struct cam_context *ctx = NULL; + + if (!apply) + return -EINVAL; + + ctx = (struct cam_context *) cam_get_device_priv(apply->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + apply->dev_hdl); + return -EINVAL; + } + + trace_cam_apply_req("Node", apply->request_id); + + return cam_context_handle_crm_apply_req(ctx, apply); +} + +static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) +{ + struct cam_context *ctx = NULL; + + if (!flush) { + CAM_ERR(CAM_CORE, "Invalid flush request payload"); + return -EINVAL; + } + + ctx = (struct cam_context *) cam_get_device_priv(flush->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + flush->dev_hdl); + return -EINVAL; + } + + return cam_context_handle_crm_flush_req(ctx, flush); +} + +static int __cam_node_crm_process_evt( + struct cam_req_mgr_link_evt_data *evt_data) +{ + struct cam_context *ctx = NULL; + + if (!evt_data) { + CAM_ERR(CAM_CORE, "Invalid process event request payload"); + return -EINVAL; + } + + ctx = (struct cam_context *) cam_get_device_priv(evt_data->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + evt_data->dev_hdl); + return -EINVAL; + } + return cam_context_handle_crm_process_evt(ctx, evt_data); +} + +int cam_node_deinit(struct cam_node *node) +{ + if (node) + memset(node, 0, sizeof(*node)); + + CAM_DBG(CAM_CORE, "deinit complete"); + + return 0; +} + +int cam_node_shutdown(struct cam_node *node) +{ + int i = 0; + int rc = 0; + + if (!node) + return -EINVAL; + + for (i = 0; i < node->ctx_size; i++) { + if (node->ctx_list[i].dev_hdl > 0) { + CAM_DBG(CAM_CORE, + "Node [%s] invoking shutdown on context [%d]", + node->name, i); + rc = cam_context_shutdown(&(node->ctx_list[i])); + } + } + + if (node->hw_mgr_intf.hw_close) + node->hw_mgr_intf.hw_close(node->hw_mgr_intf.hw_mgr_priv, + NULL); + + return 0; +} + +int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, + struct cam_context *ctx_list, uint32_t ctx_size, char *name) +{ + int rc = 0; + int i; + + if (!node || !hw_mgr_intf || + sizeof(node->hw_mgr_intf) != sizeof(*hw_mgr_intf)) { + return -EINVAL; + } + + memset(node, 0, sizeof(*node)); + + strlcpy(node->name, name, sizeof(node->name)); + + memcpy(&node->hw_mgr_intf, hw_mgr_intf, sizeof(node->hw_mgr_intf)); + node->crm_node_intf.apply_req = __cam_node_crm_apply_req; + node->crm_node_intf.get_dev_info = __cam_node_crm_get_dev_info; + node->crm_node_intf.link_setup = __cam_node_crm_link_setup; + node->crm_node_intf.flush_req = __cam_node_crm_flush_req; + node->crm_node_intf.process_evt = __cam_node_crm_process_evt; + + mutex_init(&node->list_mutex); + INIT_LIST_HEAD(&node->free_ctx_list); + node->ctx_list = ctx_list; + node->ctx_size = ctx_size; + for (i = 0; i < ctx_size; i++) { + if (!ctx_list[i].state_machine) { + CAM_ERR(CAM_CORE, + "camera context %d is not initialized", i); + rc = -1; + goto err; + } + INIT_LIST_HEAD(&ctx_list[i].list); + list_add_tail(&ctx_list[i].list, &node->free_ctx_list); + ctx_list[i].node = node; + } + + node->state = CAM_NODE_STATE_INIT; +err: + CAM_DBG(CAM_CORE, "Exit. (rc = %d)", rc); + return rc; +} + +int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) +{ + int rc = 0; + + if (!cmd) + return -EINVAL; + + CAM_DBG(CAM_CORE, "handle cmd %d", cmd->op_code); + + switch (cmd->op_code) { + case CAM_QUERY_CAP: { + struct cam_query_cap_cmd query; + + if (copy_from_user(&query, u64_to_user_ptr(cmd->handle), + sizeof(query))) { + rc = -EFAULT; + break; + } + + rc = __cam_node_handle_query_cap(node, &query); + if (rc) { + CAM_ERR(CAM_CORE, "querycap is failed(rc = %d)", + rc); + break; + } + + if (copy_to_user(u64_to_user_ptr(cmd->handle), &query, + sizeof(query))) + rc = -EFAULT; + + break; + } + case CAM_ACQUIRE_DEV: { + struct cam_acquire_dev_cmd acquire; + + if (copy_from_user(&acquire, u64_to_user_ptr(cmd->handle), + sizeof(acquire))) { + rc = -EFAULT; + break; + } + rc = __cam_node_handle_acquire_dev(node, &acquire); + if (rc) { + CAM_ERR(CAM_CORE, "acquire device failed(rc = %d)", + rc); + break; + } + if (copy_to_user(u64_to_user_ptr(cmd->handle), &acquire, + sizeof(acquire))) + rc = -EFAULT; + break; + } + case CAM_ACQUIRE_HW: { + uint32_t api_version; + void *acquire_ptr = NULL; + size_t acquire_size; + + if (copy_from_user(&api_version, (void __user *)cmd->handle, + sizeof(api_version))) { + rc = -EFAULT; + break; + } + + if (api_version == 1) { + acquire_size = sizeof(struct cam_acquire_hw_cmd_v1); + } else if (api_version == 2) { + acquire_size = sizeof(struct cam_acquire_hw_cmd_v2); + } else { + CAM_ERR(CAM_CORE, "Unsupported api version %d", + api_version); + rc = -EINVAL; + break; + } + + acquire_ptr = kzalloc(acquire_size, GFP_KERNEL); + if (!acquire_ptr) { + CAM_ERR(CAM_CORE, "No memory for acquire HW"); + rc = -ENOMEM; + break; + } + + if (copy_from_user(acquire_ptr, (void __user *)cmd->handle, + acquire_size)) { + rc = -EFAULT; + goto acquire_kfree; + } + + if (api_version == 1) { + rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr); + if (rc) { + CAM_ERR(CAM_CORE, + "acquire device failed(rc = %d)", rc); + goto acquire_kfree; + } + CAM_INFO(CAM_CORE, "Acquire HW successful"); + } else if (api_version == 2) { + rc = __cam_node_handle_acquire_hw_v2(node, acquire_ptr); + if (rc) { + CAM_ERR(CAM_CORE, + "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, + acquire_size)) + rc = -EFAULT; + +acquire_kfree: + kfree(acquire_ptr); + break; + } + case CAM_START_DEV: { + struct cam_start_stop_dev_cmd start; + + if (copy_from_user(&start, u64_to_user_ptr(cmd->handle), + sizeof(start))) + rc = -EFAULT; + else { + rc = __cam_node_handle_start_dev(node, &start); + if (rc) + CAM_ERR(CAM_CORE, + "start device failed(rc = %d)", rc); + } + break; + } + case CAM_STOP_DEV: { + struct cam_start_stop_dev_cmd stop; + + if (copy_from_user(&stop, u64_to_user_ptr(cmd->handle), + sizeof(stop))) + rc = -EFAULT; + else { + rc = __cam_node_handle_stop_dev(node, &stop); + if (rc) + CAM_ERR(CAM_CORE, + "stop device failed(rc = %d)", rc); + } + break; + } + case CAM_CONFIG_DEV: { + struct cam_config_dev_cmd config; + + if (copy_from_user(&config, u64_to_user_ptr(cmd->handle), + sizeof(config))) + rc = -EFAULT; + else { + rc = __cam_node_handle_config_dev(node, &config); + if (rc) + CAM_ERR(CAM_CORE, + "config device failed(rc = %d)", rc); + } + break; + } + case CAM_RELEASE_DEV: { + struct cam_release_dev_cmd release; + + if (copy_from_user(&release, u64_to_user_ptr(cmd->handle), + sizeof(release))) + rc = -EFAULT; + else { + rc = __cam_node_handle_release_dev(node, &release); + if (rc) + CAM_ERR(CAM_CORE, + "release device failed(rc = %d)", rc); + } + break; + } + case CAM_RELEASE_HW: { + uint32_t api_version; + size_t release_size; + void *release_ptr = NULL; + + if (copy_from_user(&api_version, (void __user *)cmd->handle, + sizeof(api_version))) { + rc = -EFAULT; + break; + } + + if (api_version == 1) { + release_size = sizeof(struct cam_release_hw_cmd_v1); + } else { + CAM_ERR(CAM_CORE, "Unsupported api version %d", + api_version); + rc = -EINVAL; + break; + } + + release_ptr = kzalloc(release_size, GFP_KERNEL); + if (!release_ptr) { + CAM_ERR(CAM_CORE, "No memory for release HW"); + rc = -ENOMEM; + break; + } + + if (copy_from_user(release_ptr, (void __user *)cmd->handle, + release_size)) { + rc = -EFAULT; + goto release_kfree; + } + + if (api_version == 1) { + rc = __cam_node_handle_release_hw_v1(node, release_ptr); + if (rc) + CAM_ERR(CAM_CORE, + "release device failed(rc = %d)", rc); + } + + CAM_INFO(CAM_CORE, "Release HW done(rc = %d)", rc); + +release_kfree: + kfree(release_ptr); + break; + } + case CAM_FLUSH_REQ: { + struct cam_flush_dev_cmd flush; + + if (copy_from_user(&flush, u64_to_user_ptr(cmd->handle), + sizeof(flush))) + rc = -EFAULT; + else { + rc = __cam_node_handle_flush_dev(node, &flush); + if (rc) + CAM_ERR(CAM_CORE, + "flush device failed(rc = %d)", rc); + } + break; + } + default: + CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code); + rc = -EINVAL; + } + + return rc; +} diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h new file mode 100644 index 000000000000..ad49c4b619a9 --- /dev/null +++ b/drivers/cam_core/cam_node.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_NODE_H_ +#define _CAM_NODE_H_ + +#include +#include "cam_context.h" +#include "cam_hw_mgr_intf.h" +#include "cam_req_mgr_interface.h" + +#define CAM_NODE_NAME_LENGTH_MAX 256 + +#define CAM_NODE_STATE_UNINIT 0 +#define CAM_NODE_STATE_INIT 1 + +/** + * struct cam_node - Singleton Node for camera HW devices + * + * @name: Name for struct cam_node + * @state: Node state: + * 0 = uninitialized, 1 = initialized + * @list_mutex: Mutex for the context pool + * @free_ctx_list: Free context pool list + * @ctx_list: Context list + * @ctx_size: Context list size + * @hw_mgr_intf: Interface for cam_node to HW + * @crm_node_intf: Interface for the CRM to cam_node + * + */ +struct cam_node { + char name[CAM_NODE_NAME_LENGTH_MAX]; + uint32_t state; + + /* context pool */ + struct mutex list_mutex; + struct list_head free_ctx_list; + struct cam_context *ctx_list; + uint32_t ctx_size; + + /* interfaces */ + struct cam_hw_mgr_intf hw_mgr_intf; + struct cam_req_mgr_kmd_ops crm_node_intf; +}; + +/** + * cam_node_handle_ioctl() + * + * @brief: Handle ioctl commands + * + * @node: Node handle + * @cmd: IOCTL command + * + */ +int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd); + +/** + * cam_node_deinit() + * + * @brief: Deinitialization function for the Node interface + * + * @node: Node handle + * + */ +int cam_node_deinit(struct cam_node *node); + +/** + * cam_node_shutdown() + * + * @brief: Shutdowns/Closes the cam node. + * + * @node: Cam_node pointer + * + */ +int cam_node_shutdown(struct cam_node *node); + +/** + * cam_node_init() + * + * @brief: Initialization function for the Node interface. + * + * @node: Cam_node pointer + * @hw_mgr_intf: HW manager interface blob + * @ctx_list: List of cam_contexts to be added + * @ctx_size: Size of the cam_context + * @name: Name for the node + * + */ +int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, + struct cam_context *ctx_list, uint32_t ctx_size, char *name); + +/** + * cam_node_put_ctxt_to_free_list() + * + * @brief: Put context in node free list. + * + * @ref: Context's kref object + * + */ +void cam_node_put_ctxt_to_free_list(struct kref *ref); + +#endif /* _CAM_NODE_H_ */ diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c new file mode 100644 index 000000000000..1a81a4d59e99 --- /dev/null +++ b/drivers/cam_core/cam_subdev.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_subdev.h" +#include "cam_node.h" +#include "cam_debug_util.h" + +/** + * cam_subdev_subscribe_event() + * + * @brief: function to subscribe to v4l2 events + * + * @sd: Pointer to struct v4l2_subdev. + * @fh: Pointer to struct v4l2_fh. + * @sub: Pointer to struct v4l2_event_subscription. + */ +static int cam_subdev_subscribe_event(struct v4l2_subdev *sd, + struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + return v4l2_event_subscribe(fh, sub, CAM_SUBDEVICE_EVENT_MAX, NULL); +} + +/** + * cam_subdev_unsubscribe_event() + * + * @brief: function to unsubscribe from v4l2 events + * + * @sd: Pointer to struct v4l2_subdev. + * @fh: Pointer to struct v4l2_fh. + * @sub: Pointer to struct v4l2_event_subscription. + */ +static int cam_subdev_unsubscribe_event(struct v4l2_subdev *sd, + struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + return v4l2_event_unsubscribe(fh, sub); +} + +static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, + void *arg) +{ + long rc; + struct cam_node *node = + (struct cam_node *) v4l2_get_subdevdata(sd); + + if (!node || node->state == CAM_NODE_STATE_UNINIT) { + rc = -EINVAL; + goto end; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_node_handle_ioctl(node, + (struct cam_control *) arg); + break; + default: + CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, + node->name); + rc = -EINVAL; + } +end: + return rc; +} + +#ifdef CONFIG_COMPAT +static long cam_subdev_compat_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int rc; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_CORE, "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + rc = cam_subdev_ioctl(sd, cmd, &cmd_data); + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_CORE, + "Failed to copy to user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + + return rc; +} +#endif + +const struct v4l2_subdev_core_ops cam_subdev_core_ops = { + .ioctl = cam_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_subdev_compat_ioctl, +#endif + .subscribe_event = cam_subdev_subscribe_event, + .unsubscribe_event = cam_subdev_unsubscribe_event, +}; + +static const struct v4l2_subdev_ops cam_subdev_ops = { + .core = &cam_subdev_core_ops, +}; + +int cam_subdev_remove(struct cam_subdev *sd) +{ + if (!sd) + return -EINVAL; + + cam_unregister_subdev(sd); + cam_node_deinit((struct cam_node *)sd->token); + kfree(sd->token); + + return 0; +} + +int cam_subdev_probe(struct cam_subdev *sd, struct platform_device *pdev, + char *name, uint32_t dev_type) +{ + int rc; + struct cam_node *node = NULL; + + if (!sd || !pdev || !name) + return -EINVAL; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + /* Setup camera v4l2 subdevice */ + sd->pdev = pdev; + sd->name = name; + sd->ops = &cam_subdev_ops; + sd->token = node; + sd->sd_flags = + V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + sd->ent_function = dev_type; + + rc = cam_register_subdev(sd); + if (rc) { + CAM_ERR(CAM_CORE, "cam_register_subdev() failed for dev: %s", + sd->name); + goto err; + } + platform_set_drvdata(sd->pdev, sd); + return rc; +err: + kfree(node); + return rc; +} diff --git a/drivers/cam_cpas/Makefile b/drivers/cam_cpas/Makefile new file mode 100644 index 000000000000..e0af486932f1 --- /dev/null +++ b/drivers/cam_cpas/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +#ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/cpas_top +#ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/camss_top +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree) + +obj-$(CONFIG_SPECTRA_CAMERA) += cpas_top/ +obj-$(CONFIG_SPECTRA_CAMERA) += camss_top/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpas_soc.o cam_cpas_intf.o cam_cpas_hw.o \ No newline at end of file diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c new file mode 100644 index 000000000000..f7bf5a22129f --- /dev/null +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -0,0 +1,1857 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_cpas_hw.h" +#include "cam_cpas_hw_intf.h" +#include "cam_cpas_soc.h" + +static uint cam_min_camnoc_ib_bw; +module_param(cam_min_camnoc_ib_bw, uint, 0644); + + +int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, + enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + uint32_t value; + int reg_base_index; + + if (reg_info->enable == false) + return 0; + + reg_base_index = cpas_core->regbase_index[reg_base]; + if (reg_base_index == -1) + return -EINVAL; + + if (reg_info->masked_value) { + value = cam_io_r_mb( + soc_info->reg_map[reg_base_index].mem_base + + reg_info->offset); + value = value & (~reg_info->mask); + value = value | (reg_info->value << reg_info->shift); + } else { + value = reg_info->value; + } + + CAM_DBG(CAM_CPAS, "Base[%d] Offset[0x%8x] Value[0x%8x]", + reg_base, reg_info->offset, value); + + cam_io_w_mb(value, soc_info->reg_map[reg_base_index].mem_base + + reg_info->offset); + + return 0; +} + +static int cam_cpas_util_vote_bus_client_level( + struct cam_cpas_bus_client *bus_client, unsigned int level) +{ + if (!bus_client->valid || (bus_client->dyn_vote == true)) { + CAM_ERR(CAM_CPAS, "Invalid params %d %d", bus_client->valid, + bus_client->dyn_vote); + return -EINVAL; + } + + if (level >= bus_client->num_usecases) { + CAM_ERR(CAM_CPAS, "Invalid vote level=%d, usecases=%d", level, + bus_client->num_usecases); + return -EINVAL; + } + + if (level == bus_client->curr_vote_level) + return 0; + + CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] index[%d]", + bus_client->client_id, bus_client->name, level); + msm_bus_scale_client_update_request(bus_client->client_id, level); + bus_client->curr_vote_level = level; + + return 0; +} + +static int cam_cpas_util_vote_bus_client_bw( + struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib, + bool camnoc_bw) +{ + struct msm_bus_paths *path; + struct msm_bus_scale_pdata *pdata; + int idx = 0; + uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; + + if (cam_min_camnoc_ib_bw > 0) + min_camnoc_ib_bw = (uint64_t)cam_min_camnoc_ib_bw * 1000000L; + + CAM_DBG(CAM_CPAS, "cam_min_camnoc_ib_bw = %d, min_camnoc_ib_bw=%llu", + cam_min_camnoc_ib_bw, min_camnoc_ib_bw); + + if (!bus_client->valid) { + CAM_ERR(CAM_CPAS, "bus client not valid"); + return -EINVAL; + } + + if ((bus_client->num_usecases != 2) || + (bus_client->num_paths != 1) || + (bus_client->dyn_vote != true)) { + CAM_ERR(CAM_CPAS, "dynamic update not allowed %d %d %d", + bus_client->num_usecases, bus_client->num_paths, + bus_client->dyn_vote); + return -EINVAL; + } + + mutex_lock(&bus_client->lock); + + if (bus_client->curr_vote_level > 1) { + CAM_ERR(CAM_CPAS, "curr_vote_level %d cannot be greater than 1", + bus_client->curr_vote_level); + mutex_unlock(&bus_client->lock); + return -EINVAL; + } + + idx = bus_client->curr_vote_level; + idx = 1 - idx; + bus_client->curr_vote_level = idx; + mutex_unlock(&bus_client->lock); + + if (camnoc_bw == true) { + if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_CAMNOC_AB_BW)) + ab = CAM_CPAS_AXI_MIN_CAMNOC_AB_BW; + + if ((ib > 0) && (ib < min_camnoc_ib_bw)) + ib = min_camnoc_ib_bw; + } else { + if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_MNOC_AB_BW)) + ab = CAM_CPAS_AXI_MIN_MNOC_AB_BW; + + if ((ib > 0) && (ib < CAM_CPAS_AXI_MIN_MNOC_IB_BW)) + ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW; + } + + pdata = bus_client->pdata; + path = &(pdata->usecase[idx]); + path->vectors[0].ab = ab; + path->vectors[0].ib = ib; + + CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", + bus_client->client_id, bus_client->name, ab, ib, idx); + msm_bus_scale_client_update_request(bus_client->client_id, idx); + + return 0; +} + +static int cam_cpas_util_register_bus_client( + struct cam_hw_soc_info *soc_info, struct device_node *dev_node, + struct cam_cpas_bus_client *bus_client) +{ + struct msm_bus_scale_pdata *pdata = NULL; + uint32_t client_id; + int rc; + + pdata = msm_bus_pdata_from_node(soc_info->pdev, + dev_node); + if (!pdata) { + CAM_ERR(CAM_CPAS, "failed get_pdata"); + return -EINVAL; + } + + if ((pdata->num_usecases == 0) || + (pdata->usecase[0].num_paths == 0)) { + CAM_ERR(CAM_CPAS, "usecase=%d", pdata->num_usecases); + rc = -EINVAL; + goto error; + } + + client_id = msm_bus_scale_register_client(pdata); + if (!client_id) { + CAM_ERR(CAM_CPAS, "failed in register ahb bus client"); + rc = -EINVAL; + goto error; + } + + bus_client->dyn_vote = of_property_read_bool(dev_node, + "qcom,msm-bus-vector-dyn-vote"); + + if (bus_client->dyn_vote && (pdata->num_usecases != 2)) { + CAM_ERR(CAM_CPAS, "Excess or less vectors %d", + pdata->num_usecases); + rc = -EINVAL; + goto fail_unregister_client; + } + + msm_bus_scale_client_update_request(client_id, 0); + + bus_client->src = pdata->usecase[0].vectors[0].src; + bus_client->dst = pdata->usecase[0].vectors[0].dst; + bus_client->pdata = pdata; + bus_client->client_id = client_id; + bus_client->num_usecases = pdata->num_usecases; + bus_client->num_paths = pdata->usecase[0].num_paths; + bus_client->curr_vote_level = 0; + bus_client->valid = true; + bus_client->name = pdata->name; + mutex_init(&bus_client->lock); + + CAM_DBG(CAM_CPAS, "Bus Client=[%d][%s] : src=%d, dst=%d", + bus_client->client_id, bus_client->name, + bus_client->src, bus_client->dst); + + return 0; +fail_unregister_client: + msm_bus_scale_unregister_client(bus_client->client_id); +error: + return rc; + +} + +static int cam_cpas_util_unregister_bus_client( + struct cam_cpas_bus_client *bus_client) +{ + if (!bus_client->valid) + return -EINVAL; + + if (bus_client->dyn_vote) + cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false); + else + cam_cpas_util_vote_bus_client_level(bus_client, 0); + + msm_bus_scale_unregister_client(bus_client->client_id); + bus_client->valid = false; + + mutex_destroy(&bus_client->lock); + + return 0; +} + +static int cam_cpas_util_axi_cleanup(struct cam_cpas *cpas_core, + struct cam_hw_soc_info *soc_info) +{ + int i = 0; + + for (i = 0; i < cpas_core->num_axi_ports; i++) { + cam_cpas_util_unregister_bus_client( + &cpas_core->axi_port[i].bus_client); + of_node_put(cpas_core->axi_port[i].axi_port_node); + cpas_core->axi_port[i].axi_port_node = NULL; + } + + return 0; +} + +static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core, + struct cam_hw_soc_info *soc_info) +{ + int i = 0, rc = 0; + struct device_node *axi_port_mnoc_node = NULL; + + for (i = 0; i < cpas_core->num_axi_ports; i++) { + axi_port_mnoc_node = cpas_core->axi_port[i].axi_port_node; + rc = cam_cpas_util_register_bus_client(soc_info, + axi_port_mnoc_node, &cpas_core->axi_port[i].bus_client); + if (rc) + goto bus_register_fail; + } + + return 0; +bus_register_fail: + of_node_put(cpas_core->axi_port[i].axi_port_node); + return rc; +} + +static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, + int enable) +{ + int rc, i = 0; + struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info; + uint64_t ab_bw, ib_bw; + + rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client, + (enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in AHB vote, enable=%d, rc=%d", + enable, rc); + return rc; + } + + if (enable) { + ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + } else { + ab_bw = 0; + ib_bw = 0; + } + + for (i = 0; i < cpas_core->num_axi_ports; i++) { + rc = cam_cpas_util_vote_bus_client_bw( + &cpas_core->axi_port[i].bus_client, + ab_bw, ib_bw, false); + if (rc) { + CAM_ERR(CAM_CPAS, + "Failed in mnoc vote, enable=%d, rc=%d", + enable, rc); + goto remove_ahb_vote; + } + } + + return 0; +remove_ahb_vote: + cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client, + CAM_SUSPEND_VOTE); + return rc; +} + +static int cam_cpas_hw_reg_write(struct cam_hw_info *cpas_hw, + uint32_t client_handle, enum cam_cpas_reg_base reg_base, + uint32_t offset, bool mb, uint32_t value) +{ + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_client *cpas_client = NULL; + int reg_base_index = cpas_core->regbase_index[reg_base]; + uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle); + int rc = 0; + + if (reg_base_index < 0 || reg_base_index >= soc_info->num_reg_map) { + CAM_ERR(CAM_CPAS, + "Invalid reg_base=%d, reg_base_index=%d, num_map=%d", + reg_base, reg_base_index, soc_info->num_reg_map); + return -EINVAL; + } + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + mutex_lock(&cpas_core->client_mutex[client_indx]); + cpas_client = cpas_core->cpas_client[client_indx]; + + if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index); + rc = -EPERM; + goto unlock_client; + } + + if (mb) + cam_io_w_mb(value, + soc_info->reg_map[reg_base_index].mem_base + offset); + else + cam_io_w(value, + soc_info->reg_map[reg_base_index].mem_base + offset); + +unlock_client: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + return rc; +} + +static int cam_cpas_hw_reg_read(struct cam_hw_info *cpas_hw, + uint32_t client_handle, enum cam_cpas_reg_base reg_base, + uint32_t offset, bool mb, uint32_t *value) +{ + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_client *cpas_client = NULL; + int reg_base_index = cpas_core->regbase_index[reg_base]; + uint32_t reg_value; + uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle); + int rc = 0; + + if (!value) + return -EINVAL; + + if (reg_base_index < 0 || reg_base_index >= soc_info->num_reg_map) { + CAM_ERR(CAM_CPAS, + "Invalid reg_base=%d, reg_base_index=%d, num_map=%d", + reg_base, reg_base_index, soc_info->num_reg_map); + return -EINVAL; + } + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + mutex_lock(&cpas_core->client_mutex[client_indx]); + cpas_client = cpas_core->cpas_client[client_indx]; + + if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index); + rc = -EPERM; + goto unlock_client; + } + + if (mb) + reg_value = cam_io_r_mb( + soc_info->reg_map[reg_base_index].mem_base + offset); + else + reg_value = cam_io_r( + soc_info->reg_map[reg_base_index].mem_base + offset); + + *value = reg_value; + +unlock_client: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + return rc; +} + +static int cam_cpas_util_set_camnoc_axi_clk_rate( + struct cam_hw_info *cpas_hw) +{ + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_tree_node *tree_node = NULL; + int rc = 0, i = 0; + + CAM_DBG(CAM_CPAS, "control_camnoc_axi_clk=%d", + soc_private->control_camnoc_axi_clk); + + if (soc_private->control_camnoc_axi_clk) { + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + uint64_t required_camnoc_bw = 0; + int32_t clk_rate = 0; + + for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) { + tree_node = soc_private->tree_node[i]; + if (!tree_node || + !tree_node->camnoc_max_needed) + continue; + + if (required_camnoc_bw < (tree_node->camnoc_bw * + tree_node->bus_width_factor)) { + required_camnoc_bw = tree_node->camnoc_bw * + tree_node->bus_width_factor; + } + } + + required_camnoc_bw += (required_camnoc_bw * + soc_private->camnoc_axi_clk_bw_margin) / 100; + + if ((required_camnoc_bw > 0) && + (required_camnoc_bw < + soc_private->camnoc_axi_min_ib_bw)) + required_camnoc_bw = soc_private->camnoc_axi_min_ib_bw; + + clk_rate = required_camnoc_bw / soc_private->camnoc_bus_width; + + CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %d", + required_camnoc_bw, clk_rate); + + /* + * CPAS hw is not powered on for the first client. + * Also, clk_rate will be overwritten with default + * value while power on. So, skipping this for first + * client. + */ + if (cpas_core->streamon_clients) { + rc = cam_soc_util_set_src_clk_rate(soc_info, clk_rate); + if (rc) + CAM_ERR(CAM_CPAS, + "Failed in setting camnoc axi clk %llu %d %d", + required_camnoc_bw, clk_rate, rc); + } + } + + return rc; +} + +static int cam_cpas_util_translate_client_paths( + struct cam_axi_vote *axi_vote) +{ + int i; + uint32_t *path_data_type = NULL; + + if (!axi_vote) + return -EINVAL; + + for (i = 0; i < axi_vote->num_paths; i++) { + path_data_type = &axi_vote->axi_path[i].path_data_type; + /* Update path_data_type from UAPI value to internal value */ + if (*path_data_type >= CAM_CPAS_PATH_DATA_CONSO_OFFSET) + *path_data_type = CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT + + (*path_data_type % + CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT); + else + *path_data_type %= CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT; + + if (*path_data_type >= CAM_CPAS_PATH_DATA_MAX) { + CAM_ERR(CAM_CPAS, "index Invalid: %d", path_data_type); + return -EINVAL; + } + } + + return 0; +} + +static int cam_cpas_axi_consolidate_path_votes( + struct cam_cpas_client *cpas_client, + struct cam_axi_vote *axi_vote) +{ + int rc = 0, i, k, l; + struct cam_axi_vote *con_axi_vote = &cpas_client->axi_vote; + bool path_found = false, cons_entry_found; + struct cam_cpas_tree_node *curr_tree_node = NULL; + struct cam_cpas_tree_node *sum_tree_node = NULL; + uint32_t transac_type; + uint32_t path_data_type; + struct cam_axi_per_path_bw_vote *axi_path; + + con_axi_vote->num_paths = 0; + + for (i = 0; i < axi_vote->num_paths; i++) { + path_found = false; + path_data_type = axi_vote->axi_path[i].path_data_type; + transac_type = axi_vote->axi_path[i].transac_type; + + if ((path_data_type >= CAM_CPAS_PATH_DATA_MAX) || + (transac_type >= CAM_CPAS_TRANSACTION_MAX)) { + CAM_ERR(CAM_CPAS, "Invalid path or transac type: %d %d", + path_data_type, transac_type); + return -EINVAL; + } + + axi_path = &con_axi_vote->axi_path[con_axi_vote->num_paths]; + + curr_tree_node = + cpas_client->tree_node[path_data_type][transac_type]; + if (curr_tree_node) { + path_found = true; + memcpy(axi_path, &axi_vote->axi_path[i], + sizeof(struct cam_axi_per_path_bw_vote)); + con_axi_vote->num_paths++; + continue; + } + + for (k = 0; k < CAM_CPAS_PATH_DATA_MAX; k++) { + sum_tree_node = cpas_client->tree_node[k][transac_type]; + + if (!sum_tree_node) + continue; + + if (sum_tree_node->constituent_paths[path_data_type]) { + path_found = true; + /* + * Check if corresponding consolidated path + * entry is already added into consolidated list + */ + cons_entry_found = false; + for (l = 0; l < con_axi_vote->num_paths; l++) { + if ((con_axi_vote->axi_path[l] + .path_data_type == k) && + (con_axi_vote->axi_path[l] + .transac_type == transac_type)) { + cons_entry_found = true; + con_axi_vote->axi_path[l] + .camnoc_bw += + axi_vote->axi_path[i] + .camnoc_bw; + + con_axi_vote->axi_path[l] + .mnoc_ab_bw += + axi_vote->axi_path[i] + .mnoc_ab_bw; + + con_axi_vote->axi_path[l] + .mnoc_ib_bw += + axi_vote->axi_path[i] + .mnoc_ib_bw; + break; + } + } + + /* If not found, add a new entry */ + if (!cons_entry_found) { + axi_path->path_data_type = k; + axi_path->transac_type = transac_type; + axi_path->camnoc_bw = + axi_vote->axi_path[i].camnoc_bw; + axi_path->mnoc_ab_bw = + axi_vote->axi_path[i].mnoc_ab_bw; + axi_path->mnoc_ib_bw = + axi_vote->axi_path[i].mnoc_ib_bw; + con_axi_vote->num_paths++; + } + break; + } + } + + if (!path_found) { + CAM_ERR(CAM_CPAS, + "Client [%s][%d] Consolidated path not found for path=%d, transac=%d", + cpas_client->data.identifier, + cpas_client->data.cell_index, + path_data_type, transac_type); + return -EINVAL; + } + } + + return rc; +} + +static int cam_cpas_util_apply_client_axi_vote( + struct cam_hw_info *cpas_hw, + struct cam_cpas_client *cpas_client, + struct cam_axi_vote *axi_vote) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_axi_vote *con_axi_vote = NULL; + struct cam_cpas_axi_port *axi_port = NULL; + struct cam_cpas_tree_node *curr_tree_node = NULL; + struct cam_cpas_tree_node *par_tree_node = NULL; + uint32_t transac_type; + uint32_t path_data_type; + bool axi_port_updated[CAM_CPAS_MAX_AXI_PORTS] = {false}; + uint64_t mnoc_ab_bw = 0, mnoc_ib_bw = 0, + curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0, + par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0; + int rc = 0, i = 0; + + mutex_lock(&cpas_core->tree_lock); + if (!cpas_client->tree_node_valid) { + /* + * This is by assuming apply_client_axi_vote is called + * for these clients from only cpas_start, cpas_stop. + * not called from hw_update_axi_vote + */ + for (i = 0; i < cpas_core->num_axi_ports; i++) { + if (axi_vote->axi_path[0].mnoc_ab_bw) { + /* start case */ + cpas_core->axi_port[i].additional_bw += + CAM_CPAS_DEFAULT_AXI_BW; + } else { + /* stop case */ + cpas_core->axi_port[i].additional_bw -= + CAM_CPAS_DEFAULT_AXI_BW; + } + axi_port_updated[i] = true; + } + goto vote_start_clients; + } + + rc = cam_cpas_axi_consolidate_path_votes(cpas_client, axi_vote); + if (rc) { + CAM_ERR(CAM_PERF, "Failed in bw consolidation, Client [%s][%d]", + cpas_client->data.identifier, + cpas_client->data.cell_index); + goto unlock_tree; + } + + con_axi_vote = &cpas_client->axi_vote; + + cam_cpas_dump_axi_vote_info(cpas_client, "Consolidated Vote", + con_axi_vote); + + /* Traverse through node tree and update bw vote values */ + for (i = 0; i < con_axi_vote->num_paths; i++) { + path_data_type = + con_axi_vote->axi_path[i].path_data_type; + transac_type = + con_axi_vote->axi_path[i].transac_type; + curr_tree_node = cpas_client->tree_node[path_data_type] + [transac_type]; + + if (con_axi_vote->axi_path[i].mnoc_ab_bw == 0) + con_axi_vote->axi_path[i].mnoc_ab_bw = + con_axi_vote->axi_path[i].camnoc_bw; + + if (con_axi_vote->axi_path[i].camnoc_bw == 0) + con_axi_vote->axi_path[i].camnoc_bw = + con_axi_vote->axi_path[i].mnoc_ab_bw; + + if ((curr_tree_node->camnoc_bw == + con_axi_vote->axi_path[i].camnoc_bw) && + (curr_tree_node->mnoc_ab_bw == + con_axi_vote->axi_path[i].mnoc_ab_bw) && + (curr_tree_node->mnoc_ib_bw == + con_axi_vote->axi_path[i].mnoc_ib_bw)) + continue; + + curr_camnoc_old = curr_tree_node->camnoc_bw; + curr_mnoc_ab_old = curr_tree_node->mnoc_ab_bw; + curr_mnoc_ib_old = curr_tree_node->mnoc_ib_bw; + curr_tree_node->camnoc_bw = + con_axi_vote->axi_path[i].camnoc_bw; + curr_tree_node->mnoc_ab_bw = + con_axi_vote->axi_path[i].mnoc_ab_bw; + curr_tree_node->mnoc_ib_bw = + con_axi_vote->axi_path[i].mnoc_ib_bw; + + while (curr_tree_node->parent_node) { + par_tree_node = curr_tree_node->parent_node; + par_camnoc_old = par_tree_node->camnoc_bw; + par_mnoc_ab_old = par_tree_node->mnoc_ab_bw; + par_mnoc_ib_old = par_tree_node->mnoc_ib_bw; + par_tree_node->mnoc_ab_bw -= curr_mnoc_ab_old; + par_tree_node->mnoc_ab_bw += curr_tree_node->mnoc_ab_bw; + par_tree_node->mnoc_ib_bw -= curr_mnoc_ib_old; + par_tree_node->mnoc_ib_bw += curr_tree_node->mnoc_ib_bw; + + if (par_tree_node->merge_type == + CAM_CPAS_TRAFFIC_MERGE_SUM) { + par_tree_node->camnoc_bw -= + curr_camnoc_old; + par_tree_node->camnoc_bw += + curr_tree_node->camnoc_bw; + } else if (par_tree_node->merge_type == + CAM_CPAS_TRAFFIC_MERGE_SUM_INTERLEAVE) { + par_tree_node->camnoc_bw -= + (curr_camnoc_old / 2); + par_tree_node->camnoc_bw += + (curr_tree_node->camnoc_bw / 2); + } else { + CAM_ERR(CAM_CPAS, "Invalid Merge type"); + rc = -EINVAL; + goto unlock_tree; + } + + if (!par_tree_node->parent_node) { + if ((par_tree_node->axi_port_idx < 0) || + (par_tree_node->axi_port_idx >= + CAM_CPAS_MAX_AXI_PORTS)) { + CAM_ERR(CAM_CPAS, + "AXI port index invalid"); + rc = -EINVAL; + goto unlock_tree; + } + + cpas_core->axi_port + [par_tree_node->axi_port_idx].ab_bw = + par_tree_node->mnoc_ab_bw; + cpas_core->axi_port + [par_tree_node->axi_port_idx].ib_bw = + par_tree_node->mnoc_ib_bw; + axi_port_updated[par_tree_node->axi_port_idx] = + true; + } + + curr_tree_node = par_tree_node; + curr_camnoc_old = par_camnoc_old; + curr_mnoc_ab_old = par_mnoc_ab_old; + curr_mnoc_ib_old = par_mnoc_ib_old; + } + } + + if (!par_tree_node) { + CAM_DBG(CAM_CPAS, "No change in BW for all paths"); + rc = 0; + goto unlock_tree; + } + +vote_start_clients: + for (i = 0; i < cpas_core->num_axi_ports; i++) { + if (axi_port_updated[i]) + axi_port = &cpas_core->axi_port[i]; + else + continue; + + CAM_DBG(CAM_PERF, "Port[%s] : ab=%lld ib=%lld additional=%lld", + axi_port->axi_port_name, axi_port->ab_bw, + axi_port->ib_bw, axi_port->additional_bw); + + if (axi_port->ab_bw) + mnoc_ab_bw = axi_port->ab_bw; + else + mnoc_ab_bw = axi_port->additional_bw; + + if (cpas_core->axi_port[i].ib_bw_voting_needed) + mnoc_ib_bw = axi_port->ib_bw; + else + mnoc_ib_bw = 0; + + rc = cam_cpas_util_vote_bus_client_bw(&axi_port->bus_client, + mnoc_ab_bw, mnoc_ib_bw, false); + if (rc) { + CAM_ERR(CAM_CPAS, + "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d", + mnoc_ab_bw, mnoc_ib_bw, rc); + goto unlock_tree; + } + } + + rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in setting axi clk rate rc=%d", rc); + +unlock_tree: + mutex_unlock(&cpas_core->tree_lock); + return rc; +} + +static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, + uint32_t client_handle, struct cam_axi_vote *client_axi_vote) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_client *cpas_client = NULL; + struct cam_axi_vote axi_vote = {0}; + uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle); + int rc = 0; + + if (!client_axi_vote) { + CAM_ERR(CAM_CPAS, "Invalid arg, client_handle=%d", + client_handle); + return -EINVAL; + } + + memcpy(&axi_vote, client_axi_vote, sizeof(struct cam_axi_vote)); + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], + "Incoming Vote", &axi_vote); + + mutex_lock(&cpas_hw->hw_mutex); + mutex_lock(&cpas_core->client_mutex[client_indx]); + cpas_client = cpas_core->cpas_client[client_indx]; + + if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index); + rc = -EPERM; + goto unlock_client; + } + + rc = cam_cpas_util_translate_client_paths(&axi_vote); + if (rc) { + CAM_ERR(CAM_CPAS, + "Unable to translate per path votes rc: %d", rc); + goto unlock_client; + } + + cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], + "Translated Vote", &axi_vote); + + rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, + cpas_core->cpas_client[client_indx], &axi_vote); + +unlock_client: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return rc; +} + +static int cam_cpas_util_get_ahb_level(struct cam_hw_info *cpas_hw, + struct device *dev, unsigned long freq, enum cam_vote_level *req_level) +{ + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + struct dev_pm_opp *opp; + unsigned int corner; + enum cam_vote_level level = CAM_SVS_VOTE; + unsigned long corner_freq = freq; + int i; + + if (!dev || !req_level) { + CAM_ERR(CAM_CPAS, "Invalid params %pK, %pK", dev, req_level); + return -EINVAL; + } + + opp = dev_pm_opp_find_freq_ceil(dev, &corner_freq); + if (IS_ERR(opp)) { + CAM_DBG(CAM_CPAS, "OPP Ceil not available for freq :%ld, %pK", + corner_freq, opp); + *req_level = CAM_TURBO_VOTE; + return 0; + } + + corner = dev_pm_opp_get_voltage(opp); + + for (i = 0; i < soc_private->num_vdd_ahb_mapping; i++) + if (corner == soc_private->vdd_ahb[i].vdd_corner) + level = soc_private->vdd_ahb[i].ahb_level; + + CAM_DBG(CAM_CPAS, + "From OPP table : freq=[%ld][%ld], corner=%d, level=%d", + freq, corner_freq, corner, level); + + *req_level = level; + + return 0; +} + +static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw, + struct cam_cpas_client *cpas_client, struct cam_ahb_vote *ahb_vote, + enum cam_vote_level *applied_level) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_bus_client *ahb_bus_client = &cpas_core->ahb_bus_client; + enum cam_vote_level required_level; + enum cam_vote_level highest_level; + int i, rc = 0; + + if (!ahb_bus_client->valid) { + CAM_ERR(CAM_CPAS, "AHB Bus client not valid"); + return -EINVAL; + } + + if (ahb_vote->type == CAM_VOTE_DYNAMIC) { + rc = cam_cpas_util_get_ahb_level(cpas_hw, cpas_client->data.dev, + ahb_vote->vote.freq, &required_level); + if (rc) + return rc; + } else { + required_level = ahb_vote->vote.level; + } + + if (cpas_client->ahb_level == required_level) + return 0; + + mutex_lock(&ahb_bus_client->lock); + cpas_client->ahb_level = required_level; + + CAM_DBG(CAM_CPAS, "Client=[%d][%s] required level[%d], curr_level[%d]", + ahb_bus_client->client_id, ahb_bus_client->name, + required_level, ahb_bus_client->curr_vote_level); + + if (required_level == ahb_bus_client->curr_vote_level) + goto unlock_bus_client; + + highest_level = required_level; + for (i = 0; i < cpas_core->num_clients; i++) { + if (cpas_core->cpas_client[i] && (highest_level < + cpas_core->cpas_client[i]->ahb_level)) + highest_level = cpas_core->cpas_client[i]->ahb_level; + } + + CAM_DBG(CAM_CPAS, "Required highest_level[%d]", highest_level); + + rc = cam_cpas_util_vote_bus_client_level(ahb_bus_client, + highest_level); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in ahb vote, level=%d, rc=%d", + highest_level, rc); + goto unlock_bus_client; + } + + rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info, highest_level); + if (rc) { + CAM_ERR(CAM_CPAS, + "Failed in scaling clock rate level %d for AHB", + highest_level); + goto unlock_bus_client; + } + + if (applied_level) + *applied_level = highest_level; + +unlock_bus_client: + mutex_unlock(&ahb_bus_client->lock); + return rc; +} + +static int cam_cpas_hw_update_ahb_vote(struct cam_hw_info *cpas_hw, + uint32_t client_handle, struct cam_ahb_vote *client_ahb_vote) +{ + struct cam_ahb_vote ahb_vote; + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_client *cpas_client = NULL; + uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle); + int rc = 0; + + if (!client_ahb_vote) { + CAM_ERR(CAM_CPAS, "Invalid input arg"); + return -EINVAL; + } + + ahb_vote = *client_ahb_vote; + + if (ahb_vote.vote.level == 0) { + CAM_DBG(CAM_CPAS, "0 ahb vote from client %d", + client_handle); + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + } + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + mutex_lock(&cpas_hw->hw_mutex); + mutex_lock(&cpas_core->client_mutex[client_indx]); + cpas_client = cpas_core->cpas_client[client_indx]; + + if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index); + rc = -EPERM; + goto unlock_client; + } + + CAM_DBG(CAM_PERF, + "client=[%d][%s][%d] : type[%d], level[%d], freq[%ld], applied[%d]", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index, ahb_vote.type, + ahb_vote.vote.level, ahb_vote.vote.freq, + cpas_core->cpas_client[client_indx]->ahb_level); + + rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, + cpas_core->cpas_client[client_indx], &ahb_vote, NULL); + +unlock_client: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return rc; +} + +static int cam_cpas_util_create_vote_all_paths( + struct cam_cpas_client *cpas_client, + struct cam_axi_vote *axi_vote) +{ + int i, j; + uint64_t camnoc_bw, mnoc_ab_bw, mnoc_ib_bw; + struct cam_axi_per_path_bw_vote *axi_path; + + if (!cpas_client || !axi_vote) + return -EINVAL; + + camnoc_bw = axi_vote->axi_path[0].camnoc_bw; + mnoc_ab_bw = axi_vote->axi_path[0].mnoc_ab_bw; + mnoc_ib_bw = axi_vote->axi_path[0].mnoc_ib_bw; + + axi_vote->num_paths = 0; + + for (i = 0; i < CAM_CPAS_TRANSACTION_MAX; i++) { + for (j = 0; j < CAM_CPAS_PATH_DATA_MAX; j++) { + if (cpas_client->tree_node[j][i]) { + axi_path = + &axi_vote->axi_path[axi_vote->num_paths]; + + axi_path->path_data_type = j; + axi_path->transac_type = i; + axi_path->camnoc_bw = camnoc_bw; + axi_path->mnoc_ab_bw = mnoc_ab_bw; + axi_path->mnoc_ib_bw = mnoc_ib_bw; + + axi_vote->num_paths++; + } + } + } + + return 0; +} + +static int cam_cpas_hw_start(void *hw_priv, void *start_args, + uint32_t arg_size) +{ + struct cam_hw_info *cpas_hw; + struct cam_cpas *cpas_core; + uint32_t client_indx; + struct cam_cpas_hw_cmd_start *cmd_hw_start; + struct cam_cpas_client *cpas_client; + struct cam_ahb_vote *ahb_vote; + struct cam_axi_vote axi_vote = {0}; + enum cam_vote_level applied_level = CAM_SVS_VOTE; + int rc, i = 0; + struct cam_cpas_private_soc *soc_private = NULL; + bool invalid_start = true; + + if (!hw_priv || !start_args) { + CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", + hw_priv, start_args); + return -EINVAL; + } + + if (sizeof(struct cam_cpas_hw_cmd_start) != arg_size) { + CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d", + sizeof(struct cam_cpas_hw_cmd_start), arg_size); + return -EINVAL; + } + + cpas_hw = (struct cam_hw_info *)hw_priv; + cpas_core = (struct cam_cpas *) cpas_hw->core_info; + soc_private = (struct cam_cpas_private_soc *) + cpas_hw->soc_info.soc_private; + cmd_hw_start = (struct cam_cpas_hw_cmd_start *)start_args; + client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_start->client_handle); + ahb_vote = cmd_hw_start->ahb_vote; + + if (!ahb_vote || !cmd_hw_start->axi_vote) + return -EINVAL; + + if (!ahb_vote->vote.level) { + CAM_ERR(CAM_CPAS, "Invalid vote ahb[%d]", + ahb_vote->vote.level); + return -EINVAL; + } + + memcpy(&axi_vote, cmd_hw_start->axi_vote, sizeof(struct cam_axi_vote)); + for (i = 0; i < axi_vote.num_paths; i++) { + if ((axi_vote.axi_path[i].camnoc_bw != 0) || + (axi_vote.axi_path[i].mnoc_ab_bw != 0) || + (axi_vote.axi_path[i].mnoc_ib_bw != 0)) { + invalid_start = false; + break; + } + } + + if (invalid_start) { + CAM_ERR(CAM_CPAS, "Zero start vote"); + return -EINVAL; + } + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + mutex_lock(&cpas_hw->hw_mutex); + mutex_lock(&cpas_core->client_mutex[client_indx]); + cpas_client = cpas_core->cpas_client[client_indx]; + + if (!CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "client=[%d] is not registered", + client_indx); + rc = -EPERM; + goto done; + } + + if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] is in start state", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index); + rc = -EPERM; + goto done; + } + + CAM_DBG(CAM_CPAS, + "AHB :client=[%d][%s][%d] type[%d], level[%d], applied[%d]", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index, + ahb_vote->type, ahb_vote->vote.level, cpas_client->ahb_level); + rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client, + ahb_vote, &applied_level); + if (rc) + goto done; + + cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start Vote", + &axi_vote); + + /* + * If client has indicated start bw to be applied on all paths + * of client, apply that otherwise apply whatever the client supplies + * for specific paths + */ + if (axi_vote.axi_path[0].path_data_type == + CAM_CPAS_API_PATH_DATA_STD_START) { + rc = cam_cpas_util_create_vote_all_paths(cpas_client, + &axi_vote); + } else { + rc = cam_cpas_util_translate_client_paths(&axi_vote); + } + + if (rc) { + CAM_ERR(CAM_CPAS, "Unable to create or translate paths rc: %d", + rc); + goto done; + } + + cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start Translated Vote", + &axi_vote); + + rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, + cpas_client, &axi_vote); + if (rc) + goto done; + + if (cpas_core->streamon_clients == 0) { + atomic_set(&cpas_core->irq_count, 1); + rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, + applied_level); + if (rc) { + atomic_set(&cpas_core->irq_count, 0); + CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc); + goto done; + } + + if (cpas_core->internal_ops.power_on) { + rc = cpas_core->internal_ops.power_on(cpas_hw); + if (rc) { + atomic_set(&cpas_core->irq_count, 0); + cam_cpas_soc_disable_resources( + &cpas_hw->soc_info, true, true); + CAM_ERR(CAM_CPAS, + "failed in power_on settings rc=%d", + rc); + goto done; + } + } + CAM_DBG(CAM_CPAS, "irq_count=%d\n", + atomic_read(&cpas_core->irq_count)); + cpas_hw->hw_state = CAM_HW_STATE_POWER_UP; + } + + cpas_client->started = true; + cpas_core->streamon_clients++; + + CAM_DBG(CAM_CPAS, "client=[%d][%s][%d] streamon_clients=%d", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index, cpas_core->streamon_clients); +done: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return rc; +} + +static int _check_irq_count(struct cam_cpas *cpas_core) +{ + return (atomic_read(&cpas_core->irq_count) > 0) ? 0 : 1; +} + +static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, + uint32_t arg_size) +{ + struct cam_hw_info *cpas_hw; + struct cam_cpas *cpas_core; + uint32_t client_indx; + struct cam_cpas_hw_cmd_stop *cmd_hw_stop; + struct cam_cpas_client *cpas_client; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + struct cam_cpas_private_soc *soc_private = NULL; + int rc = 0; + long result; + + if (!hw_priv || !stop_args) { + CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", + hw_priv, stop_args); + return -EINVAL; + } + + if (sizeof(struct cam_cpas_hw_cmd_stop) != arg_size) { + CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d", + sizeof(struct cam_cpas_hw_cmd_stop), arg_size); + return -EINVAL; + } + + cpas_hw = (struct cam_hw_info *)hw_priv; + cpas_core = (struct cam_cpas *) cpas_hw->core_info; + soc_private = (struct cam_cpas_private_soc *) + cpas_hw->soc_info.soc_private; + cmd_hw_stop = (struct cam_cpas_hw_cmd_stop *)stop_args; + client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_stop->client_handle); + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + mutex_lock(&cpas_hw->hw_mutex); + mutex_lock(&cpas_core->client_mutex[client_indx]); + cpas_client = cpas_core->cpas_client[client_indx]; + + CAM_DBG(CAM_CPAS, "Client=[%d][%s][%d] streamon_clients=%d", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index, cpas_core->streamon_clients); + + if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "Client=[%d][%s][%d] is not started", + client_indx, cpas_client->data.identifier, + cpas_client->data.cell_index); + rc = -EPERM; + goto done; + } + + cpas_client->started = false; + cpas_core->streamon_clients--; + + if (cpas_core->streamon_clients == 0) { + if (cpas_core->internal_ops.power_off) { + rc = cpas_core->internal_ops.power_off(cpas_hw); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed in power_off settings rc=%d", + rc); + /* Do not return error, passthrough */ + } + } + + rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info); + if (rc) { + CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc); + goto done; + } + + /* Wait for any IRQs still being handled */ + atomic_dec(&cpas_core->irq_count); + result = wait_event_timeout(cpas_core->irq_count_wq, + _check_irq_count(cpas_core), HZ); + if (result == 0) { + CAM_ERR(CAM_CPAS, "Wait failed: irq_count=%d", + atomic_read(&cpas_core->irq_count)); + } + + rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, + true, false); + if (rc) { + CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc); + goto done; + } + CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d\n", + atomic_read(&cpas_core->irq_count)); + cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + } + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SUSPEND_VOTE; + rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client, + &ahb_vote, NULL); + if (rc) + goto done; + + rc = cam_cpas_util_create_vote_all_paths(cpas_client, &axi_vote); + if (rc) { + CAM_ERR(CAM_CPAS, "Unable to create per path votes rc: %d", rc); + goto done; + } + + cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Stop Vote", &axi_vote); + + rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, + cpas_client, &axi_vote); +done: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return rc; +} + +static int cam_cpas_hw_init(void *hw_priv, void *init_hw_args, + uint32_t arg_size) +{ + struct cam_hw_info *cpas_hw; + struct cam_cpas *cpas_core; + int rc = 0; + + if (!hw_priv || !init_hw_args) { + CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", + hw_priv, init_hw_args); + return -EINVAL; + } + + if (sizeof(struct cam_cpas_hw_caps) != arg_size) { + CAM_ERR(CAM_CPAS, "INIT HW size mismatch %zd %d", + sizeof(struct cam_cpas_hw_caps), arg_size); + return -EINVAL; + } + + cpas_hw = (struct cam_hw_info *)hw_priv; + cpas_core = (struct cam_cpas *)cpas_hw->core_info; + + if (cpas_core->internal_ops.init_hw_version) { + rc = cpas_core->internal_ops.init_hw_version(cpas_hw, + (struct cam_cpas_hw_caps *)init_hw_args); + } + + return rc; +} + +static int cam_cpas_hw_register_client(struct cam_hw_info *cpas_hw, + struct cam_cpas_register_params *register_params) +{ + int rc; + char client_name[CAM_HW_IDENTIFIER_LENGTH + 3]; + int32_t client_indx = -1; + struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + + CAM_DBG(CAM_CPAS, "Register params : identifier=%s, cell_index=%d", + register_params->identifier, register_params->cell_index); + + if (soc_private->client_id_based) + snprintf(client_name, sizeof(client_name), "%s%d", + register_params->identifier, + register_params->cell_index); + else + snprintf(client_name, sizeof(client_name), "%s", + register_params->identifier); + + mutex_lock(&cpas_hw->hw_mutex); + + rc = cam_common_util_get_string_index(soc_private->client_name, + soc_private->num_clients, client_name, &client_indx); + + mutex_lock(&cpas_core->client_mutex[client_indx]); + + if (rc || !CAM_CPAS_CLIENT_VALID(client_indx) || + CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, + "Inval client %s %d : %d %d %pK %d", + register_params->identifier, + register_params->cell_index, + CAM_CPAS_CLIENT_VALID(client_indx), + CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx), + cpas_core->cpas_client[client_indx], rc); + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return -EPERM; + } + + register_params->client_handle = + CAM_CPAS_GET_CLIENT_HANDLE(client_indx); + memcpy(&cpas_core->cpas_client[client_indx]->data, register_params, + sizeof(struct cam_cpas_register_params)); + cpas_core->registered_clients++; + cpas_core->cpas_client[client_indx]->registered = true; + + CAM_DBG(CAM_CPAS, "client=[%d][%s][%d], registered_clients=%d", + client_indx, + cpas_core->cpas_client[client_indx]->data.identifier, + cpas_core->cpas_client[client_indx]->data.cell_index, + cpas_core->registered_clients); + + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + + return 0; +} + +static int cam_cpas_hw_unregister_client(struct cam_hw_info *cpas_hw, + uint32_t client_handle) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle); + int rc = 0; + + if (!CAM_CPAS_CLIENT_VALID(client_indx)) + return -EINVAL; + + mutex_lock(&cpas_hw->hw_mutex); + mutex_lock(&cpas_core->client_mutex[client_indx]); + + if (!CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "Client=[%d][%s][%d] not registered", + client_indx, + cpas_core->cpas_client[client_indx]->data.identifier, + cpas_core->cpas_client[client_indx]->data.cell_index); + rc = -EPERM; + goto done; + } + + if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { + CAM_ERR(CAM_CPAS, "Client=[%d][%s][%d] is not stopped", + client_indx, + cpas_core->cpas_client[client_indx]->data.identifier, + cpas_core->cpas_client[client_indx]->data.cell_index); + + rc = -EPERM; + goto done; + } + + CAM_DBG(CAM_CPAS, "client=[%d][%s][%d], registered_clients=%d", + client_indx, + cpas_core->cpas_client[client_indx]->data.identifier, + cpas_core->cpas_client[client_indx]->data.cell_index, + cpas_core->registered_clients); + + cpas_core->cpas_client[client_indx]->registered = false; + cpas_core->registered_clients--; +done: + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return rc; +} + +static int cam_cpas_hw_get_hw_info(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + struct cam_hw_info *cpas_hw; + struct cam_cpas *cpas_core; + struct cam_cpas_hw_caps *hw_caps; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", + hw_priv, get_hw_cap_args); + return -EINVAL; + } + + if (sizeof(struct cam_cpas_hw_caps) != arg_size) { + CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d", + sizeof(struct cam_cpas_hw_caps), arg_size); + return -EINVAL; + } + + cpas_hw = (struct cam_hw_info *)hw_priv; + cpas_core = (struct cam_cpas *) cpas_hw->core_info; + hw_caps = (struct cam_cpas_hw_caps *)get_hw_cap_args; + + *hw_caps = cpas_core->hw_caps; + + return 0; +} + + +static int cam_cpas_hw_process_cmd(void *hw_priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = -EINVAL; + + if (!hw_priv || !cmd_args || + (cmd_type >= CAM_CPAS_HW_CMD_INVALID)) { + CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK %d", + hw_priv, cmd_args, cmd_type); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_CPAS_HW_CMD_REGISTER_CLIENT: { + struct cam_cpas_register_params *register_params; + + if (sizeof(struct cam_cpas_register_params) != arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + register_params = (struct cam_cpas_register_params *)cmd_args; + rc = cam_cpas_hw_register_client(hw_priv, register_params); + break; + } + case CAM_CPAS_HW_CMD_UNREGISTER_CLIENT: { + uint32_t *client_handle; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + client_handle = (uint32_t *)cmd_args; + rc = cam_cpas_hw_unregister_client(hw_priv, *client_handle); + break; + } + case CAM_CPAS_HW_CMD_REG_WRITE: { + struct cam_cpas_hw_cmd_reg_read_write *reg_write; + + if (sizeof(struct cam_cpas_hw_cmd_reg_read_write) != + arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + reg_write = + (struct cam_cpas_hw_cmd_reg_read_write *)cmd_args; + rc = cam_cpas_hw_reg_write(hw_priv, reg_write->client_handle, + reg_write->reg_base, reg_write->offset, reg_write->mb, + reg_write->value); + break; + } + case CAM_CPAS_HW_CMD_REG_READ: { + struct cam_cpas_hw_cmd_reg_read_write *reg_read; + + if (sizeof(struct cam_cpas_hw_cmd_reg_read_write) != + arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + reg_read = + (struct cam_cpas_hw_cmd_reg_read_write *)cmd_args; + rc = cam_cpas_hw_reg_read(hw_priv, + reg_read->client_handle, reg_read->reg_base, + reg_read->offset, reg_read->mb, ®_read->value); + + break; + } + case CAM_CPAS_HW_CMD_AHB_VOTE: { + struct cam_cpas_hw_cmd_ahb_vote *cmd_ahb_vote; + + if (sizeof(struct cam_cpas_hw_cmd_ahb_vote) != arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + cmd_ahb_vote = (struct cam_cpas_hw_cmd_ahb_vote *)cmd_args; + rc = cam_cpas_hw_update_ahb_vote(hw_priv, + cmd_ahb_vote->client_handle, cmd_ahb_vote->ahb_vote); + break; + } + case CAM_CPAS_HW_CMD_AXI_VOTE: { + struct cam_cpas_hw_cmd_axi_vote *cmd_axi_vote; + + if (sizeof(struct cam_cpas_hw_cmd_axi_vote) != arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + cmd_axi_vote = (struct cam_cpas_hw_cmd_axi_vote *)cmd_args; + rc = cam_cpas_hw_update_axi_vote(hw_priv, + cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote); + break; + } + default: + CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type); + break; + } + + return rc; +} + +static int cam_cpas_util_client_setup(struct cam_hw_info *cpas_hw) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + int i; + + for (i = 0; i < CAM_CPAS_MAX_CLIENTS; i++) { + mutex_init(&cpas_core->client_mutex[i]); + } + + return 0; +} + +int cam_cpas_util_client_cleanup(struct cam_hw_info *cpas_hw) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + int i; + + for (i = 0; i < CAM_CPAS_MAX_CLIENTS; i++) { + if (cpas_core->cpas_client[i] && + cpas_core->cpas_client[i]->registered) { + cam_cpas_hw_unregister_client(cpas_hw, i); + } + kfree(cpas_core->cpas_client[i]); + cpas_core->cpas_client[i] = NULL; + mutex_destroy(&cpas_core->client_mutex[i]); + } + + return 0; +} + +static int cam_cpas_util_get_internal_ops(struct platform_device *pdev, + struct cam_hw_intf *hw_intf, struct cam_cpas_internal_ops *internal_ops) +{ + struct device_node *of_node = pdev->dev.of_node; + int rc; + const char *compat_str = NULL; + + rc = of_property_read_string_index(of_node, "arch-compat", 0, + (const char **)&compat_str); + if (rc) { + CAM_ERR(CAM_CPAS, "failed to get arch-compat rc=%d", rc); + return -EINVAL; + } + + if (strnstr(compat_str, "camss_top", strlen(compat_str))) { + hw_intf->hw_type = CAM_HW_CAMSSTOP; + rc = cam_camsstop_get_internal_ops(internal_ops); + } else if (strnstr(compat_str, "cpas_top", strlen(compat_str))) { + hw_intf->hw_type = CAM_HW_CPASTOP; + rc = cam_cpastop_get_internal_ops(internal_ops); + } else { + CAM_ERR(CAM_CPAS, "arch-compat %s not supported", compat_str); + rc = -EINVAL; + } + + return rc; +} + +int cam_cpas_hw_probe(struct platform_device *pdev, + struct cam_hw_intf **hw_intf) +{ + int rc = 0; + int i; + struct cam_hw_info *cpas_hw = NULL; + struct cam_hw_intf *cpas_hw_intf = NULL; + struct cam_cpas *cpas_core = NULL; + struct cam_cpas_private_soc *soc_private; + struct cam_cpas_internal_ops *internal_ops; + + cpas_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!cpas_hw_intf) + return -ENOMEM; + + cpas_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!cpas_hw) { + kfree(cpas_hw_intf); + return -ENOMEM; + } + + cpas_core = kzalloc(sizeof(struct cam_cpas), GFP_KERNEL); + if (!cpas_core) { + kfree(cpas_hw); + kfree(cpas_hw_intf); + return -ENOMEM; + } + + for (i = 0; i < CAM_CPAS_REG_MAX; i++) + cpas_core->regbase_index[i] = -1; + + cpas_hw_intf->hw_priv = cpas_hw; + cpas_hw->core_info = cpas_core; + + cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + cpas_hw->soc_info.pdev = pdev; + cpas_hw->soc_info.dev = &pdev->dev; + cpas_hw->soc_info.dev_name = pdev->name; + cpas_hw->open_count = 0; + mutex_init(&cpas_hw->hw_mutex); + spin_lock_init(&cpas_hw->hw_lock); + init_completion(&cpas_hw->hw_complete); + + cpas_hw_intf->hw_ops.get_hw_caps = cam_cpas_hw_get_hw_info; + cpas_hw_intf->hw_ops.init = cam_cpas_hw_init; + cpas_hw_intf->hw_ops.deinit = NULL; + cpas_hw_intf->hw_ops.reset = NULL; + cpas_hw_intf->hw_ops.reserve = NULL; + cpas_hw_intf->hw_ops.release = NULL; + cpas_hw_intf->hw_ops.start = cam_cpas_hw_start; + cpas_hw_intf->hw_ops.stop = cam_cpas_hw_stop; + cpas_hw_intf->hw_ops.read = NULL; + cpas_hw_intf->hw_ops.write = NULL; + cpas_hw_intf->hw_ops.process_cmd = cam_cpas_hw_process_cmd; + + cpas_core->work_queue = alloc_workqueue("cam-cpas", + WQ_UNBOUND | WQ_MEM_RECLAIM, CAM_CPAS_INFLIGHT_WORKS); + if (!cpas_core->work_queue) { + rc = -ENOMEM; + goto release_mem; + } + + internal_ops = &cpas_core->internal_ops; + rc = cam_cpas_util_get_internal_ops(pdev, cpas_hw_intf, internal_ops); + if (rc) + goto release_workq; + + rc = cam_cpas_soc_init_resources(&cpas_hw->soc_info, + internal_ops->handle_irq, cpas_hw); + if (rc) + goto release_workq; + + soc_private = (struct cam_cpas_private_soc *) + cpas_hw->soc_info.soc_private; + cpas_core->num_clients = soc_private->num_clients; + atomic_set(&cpas_core->irq_count, 0); + init_waitqueue_head(&cpas_core->irq_count_wq); + + if (internal_ops->setup_regbase) { + rc = internal_ops->setup_regbase(&cpas_hw->soc_info, + cpas_core->regbase_index, CAM_CPAS_REG_MAX); + if (rc) + goto deinit_platform_res; + } + + rc = cam_cpas_util_client_setup(cpas_hw); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in client setup, rc=%d", rc); + goto deinit_platform_res; + } + + rc = cam_cpas_util_register_bus_client(&cpas_hw->soc_info, + cpas_hw->soc_info.pdev->dev.of_node, + &cpas_core->ahb_bus_client); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in ahb setup, rc=%d", rc); + goto client_cleanup; + } + + rc = cam_cpas_util_axi_setup(cpas_core, &cpas_hw->soc_info); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in axi setup, rc=%d", rc); + goto ahb_cleanup; + } + + /* Need to vote first before enabling clocks */ + rc = cam_cpas_util_vote_default_ahb_axi(cpas_hw, true); + if (rc) + goto axi_cleanup; + + rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, CAM_SVS_VOTE); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in soc_enable_resources, rc=%d", rc); + goto remove_default_vote; + } + + if (internal_ops->get_hw_info) { + rc = internal_ops->get_hw_info(cpas_hw, &cpas_core->hw_caps); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in get_hw_info, rc=%d", rc); + goto disable_soc_res; + } + } else { + CAM_ERR(CAM_CPAS, "Invalid get_hw_info"); + goto disable_soc_res; + } + + rc = cam_cpas_hw_init(cpas_hw_intf->hw_priv, + &cpas_core->hw_caps, sizeof(struct cam_cpas_hw_caps)); + if (rc) + goto disable_soc_res; + + rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc); + goto remove_default_vote; + } + + rc = cam_cpas_util_vote_default_ahb_axi(cpas_hw, false); + if (rc) + goto axi_cleanup; + + *hw_intf = cpas_hw_intf; + return 0; + +disable_soc_res: + cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true); +remove_default_vote: + cam_cpas_util_vote_default_ahb_axi(cpas_hw, false); +axi_cleanup: + cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info); +ahb_cleanup: + cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client); +client_cleanup: + cam_cpas_util_client_cleanup(cpas_hw); +deinit_platform_res: + cam_cpas_soc_deinit_resources(&cpas_hw->soc_info); +release_workq: + cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private); + flush_workqueue(cpas_core->work_queue); + destroy_workqueue(cpas_core->work_queue); +release_mem: + mutex_destroy(&cpas_hw->hw_mutex); + kfree(cpas_core); + kfree(cpas_hw); + kfree(cpas_hw_intf); + CAM_ERR(CAM_CPAS, "failed in hw probe"); + return rc; +} + +int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf) +{ + struct cam_hw_info *cpas_hw; + struct cam_cpas *cpas_core; + + if (!cpas_hw_intf) { + CAM_ERR(CAM_CPAS, "cpas interface not initialized"); + return -EINVAL; + } + + cpas_hw = (struct cam_hw_info *)cpas_hw_intf->hw_priv; + cpas_core = (struct cam_cpas *)cpas_hw->core_info; + + if (cpas_hw->hw_state == CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_CPAS, "cpas hw is in power up state"); + return -EINVAL; + } + + cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info); + cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private); + cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client); + cam_cpas_util_client_cleanup(cpas_hw); + cam_cpas_soc_deinit_resources(&cpas_hw->soc_info); + flush_workqueue(cpas_core->work_queue); + destroy_workqueue(cpas_core->work_queue); + mutex_destroy(&cpas_hw->hw_mutex); + kfree(cpas_core); + kfree(cpas_hw); + kfree(cpas_hw_intf); + + return 0; +} diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h new file mode 100644 index 000000000000..7b1eda841488 --- /dev/null +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CPAS_HW_H_ +#define _CAM_CPAS_HW_H_ + +#include +#include "cam_cpas_api.h" +#include "cam_cpas_hw_intf.h" +#include "cam_common_util.h" + +#define CAM_CPAS_INFLIGHT_WORKS 5 +#define CAM_CPAS_MAX_CLIENTS 40 +#define CAM_CPAS_MAX_AXI_PORTS 6 +#define CAM_CPAS_MAX_TREE_LEVELS 4 +#define CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT 32 +#define CAM_CPAS_PATH_DATA_MAX 38 +#define CAM_CPAS_TRANSACTION_MAX 2 + +#define CAM_CPAS_AXI_MIN_MNOC_AB_BW (2048 * 1024) +#define CAM_CPAS_AXI_MIN_MNOC_IB_BW (2048 * 1024) +#define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024) +#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000UL) + +#define CAM_CPAS_GET_CLIENT_IDX(handle) (handle) +#define CAM_CPAS_GET_CLIENT_HANDLE(indx) (indx) + +#define CAM_CPAS_CLIENT_VALID(indx) \ + ((indx >= 0) && (indx < CAM_CPAS_MAX_CLIENTS)) +#define CAM_CPAS_CLIENT_REGISTERED(cpas_core, indx) \ + ((CAM_CPAS_CLIENT_VALID(indx)) && \ + (cpas_core->cpas_client[indx]->registered)) +#define CAM_CPAS_CLIENT_STARTED(cpas_core, indx) \ + ((CAM_CPAS_CLIENT_REGISTERED(cpas_core, indx)) && \ + (cpas_core->cpas_client[indx]->started)) + +/** + * enum cam_cpas_access_type - Enum for Register access type + */ +enum cam_cpas_access_type { + CAM_REG_TYPE_READ, + CAM_REG_TYPE_WRITE, + CAM_REG_TYPE_READ_WRITE, +}; + +/** + * struct cam_cpas_internal_ops - CPAS Hardware layer internal ops + * + * @get_hw_info: Function pointer for get hw info + * @init_hw_version: Function pointer for hw init based on version + * @handle_irq: Function poniter for irq handling + * @setup_regbase: Function pointer for setup rebase indices + * @power_on: Function pointer for hw core specific power on settings + * @power_off: Function pointer for hw core specific power off settings + * + */ +struct cam_cpas_internal_ops { + int (*get_hw_info)(struct cam_hw_info *cpas_hw, + struct cam_cpas_hw_caps *hw_caps); + int (*init_hw_version)(struct cam_hw_info *cpas_hw, + struct cam_cpas_hw_caps *hw_caps); + irqreturn_t (*handle_irq)(int irq_num, void *data); + int (*setup_regbase)(struct cam_hw_soc_info *soc_info, + int32_t regbase_index[], int32_t num_reg_map); + int (*power_on)(struct cam_hw_info *cpas_hw); + int (*power_off)(struct cam_hw_info *cpas_hw); +}; + +/** + * struct cam_cpas_reg : CPAS register info + * + * @enable: Whether this reg info need to be enabled + * @access_type: Register access type + * @masked_value: Whether this register write/read is based on mask, shift + * @mask: Mask for this register value + * @shift: Shift for this register value + * @value: Register value + * + */ +struct cam_cpas_reg { + bool enable; + enum cam_cpas_access_type access_type; + bool masked_value; + uint32_t offset; + uint32_t mask; + uint32_t shift; + uint32_t value; +}; + +/** + * struct cam_cpas_client : CPAS Client structure info + * + * @data: Client register params + * @registered: Whether client has registered with cpas + * @started: Whether client has streamed on + * @tree_node_valid: Indicates whether tree node has at least one valid node + * @ahb_level: Determined/Applied ahb level for the client + * @axi_vote: Determined/Applied axi vote for the client + * @axi_port: Client's parent axi port + * @tree_node: All granular path voting nodes for the client + * + */ +struct cam_cpas_client { + struct cam_cpas_register_params data; + bool registered; + bool started; + bool tree_node_valid; + enum cam_vote_level ahb_level; + struct cam_axi_vote axi_vote; + struct cam_cpas_axi_port *axi_port; + struct cam_cpas_tree_node *tree_node[CAM_CPAS_PATH_DATA_MAX] + [CAM_CPAS_TRANSACTION_MAX]; +}; + +/** + * struct cam_cpas_bus_client : Bus client information + * + * @src: Bus master/src id + * @dst: Bus slave/dst id + * @pdata: Bus pdata information + * @client_id: Bus client id + * @num_usecases: Number of use cases for this client + * @num_paths: Number of paths for this client + * @curr_vote_level: current voted index + * @dyn_vote: Whether dynamic voting enabled + * @lock: Mutex lock used while voting on this client + * @valid: Whether bus client is valid + * @name: Name of the bus client + * + */ +struct cam_cpas_bus_client { + int src; + int dst; + struct msm_bus_scale_pdata *pdata; + uint32_t client_id; + int num_usecases; + int num_paths; + unsigned int curr_vote_level; + bool dyn_vote; + struct mutex lock; + bool valid; + const char *name; +}; + +/** + * struct cam_cpas_axi_port : AXI port information + * + * @axi_port_name: Name of this AXI port + * @bus_client: bus client info for this port + * @ib_bw_voting_needed: if this port can update ib bw dynamically + * @axi_port_node: Node representing AXI Port info in device tree + * @ab_bw: AB bw value for this port + * @ib_bw: IB bw value for this port + * @additional_bw: Additional bandwidth to cover non-hw cpas clients + */ +struct cam_cpas_axi_port { + const char *axi_port_name; + struct cam_cpas_bus_client bus_client; + bool ib_bw_voting_needed; + struct device_node *axi_port_node; + uint64_t ab_bw; + uint64_t ib_bw; + uint64_t additional_bw; +}; + +/** + * struct cam_cpas : CPAS core data structure info + * + * @hw_caps: CPAS hw capabilities + * @cpas_client: Array of pointers to CPAS clients info + * @client_mutex: Mutex for accessing client info + * @tree_lock: Mutex lock for accessing CPAS node tree + * @num_clients: Total number of clients that CPAS supports + * @num_axi_ports: Total number of axi ports found in device tree + * @registered_clients: Number of Clients registered currently + * @streamon_clients: Number of Clients that are in start state currently + * @regbase_index: Register base indices for CPAS register base IDs + * @ahb_bus_client: AHB Bus client info + * @axi_port: AXI port info for a specific axi index + * @internal_ops: CPAS HW internal ops + * @work_queue: Work queue handle + * + */ +struct cam_cpas { + struct cam_cpas_hw_caps hw_caps; + struct cam_cpas_client *cpas_client[CAM_CPAS_MAX_CLIENTS]; + struct mutex client_mutex[CAM_CPAS_MAX_CLIENTS]; + struct mutex tree_lock; + uint32_t num_clients; + uint32_t num_axi_ports; + uint32_t registered_clients; + uint32_t streamon_clients; + int32_t regbase_index[CAM_CPAS_REG_MAX]; + struct cam_cpas_bus_client ahb_bus_client; + struct cam_cpas_axi_port axi_port[CAM_CPAS_MAX_AXI_PORTS]; + struct cam_cpas_internal_ops internal_ops; + struct workqueue_struct *work_queue; + atomic_t irq_count; + wait_queue_head_t irq_count_wq; +}; + +int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); +int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); + +int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, + enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info); + +int cam_cpas_util_client_cleanup(struct cam_hw_info *cpas_hw); + +#endif /* _CAM_CPAS_HW_H_ */ diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h new file mode 100644 index 000000000000..0926e6e3d8d1 --- /dev/null +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CPAS_HW_INTF_H_ +#define _CAM_CPAS_HW_INTF_H_ + +#include + +#include "cam_cpas_api.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_debug_util.h" + +/* Number of times to retry while polling */ +#define CAM_CPAS_POLL_RETRY_CNT 5 +/* Minimum usecs to sleep while polling */ +#define CAM_CPAS_POLL_MIN_USECS 200 +/* Maximum usecs to sleep while polling */ +#define CAM_CPAS_POLL_MAX_USECS 250 + +/** + * enum cam_cpas_hw_type - Enum for CPAS HW type + */ +enum cam_cpas_hw_type { + CAM_HW_CPASTOP, + CAM_HW_CAMSSTOP, +}; + +/** + * enum cam_cpas_hw_cmd_process - Enum for CPAS HW process command type + */ +enum cam_cpas_hw_cmd_process { + CAM_CPAS_HW_CMD_REGISTER_CLIENT, + CAM_CPAS_HW_CMD_UNREGISTER_CLIENT, + CAM_CPAS_HW_CMD_REG_WRITE, + CAM_CPAS_HW_CMD_REG_READ, + CAM_CPAS_HW_CMD_AHB_VOTE, + CAM_CPAS_HW_CMD_AXI_VOTE, + CAM_CPAS_HW_CMD_INVALID, +}; + +/** + * struct cam_cpas_hw_cmd_reg_read_write : CPAS cmd struct for reg read, write + * + * @client_handle: Client handle + * @reg_base: Register base type + * @offset: Register offset + * @value: Register value + * @mb: Whether to do operation with memory barrier + * + */ +struct cam_cpas_hw_cmd_reg_read_write { + uint32_t client_handle; + enum cam_cpas_reg_base reg_base; + uint32_t offset; + uint32_t value; + bool mb; +}; + +/** + * struct cam_cpas_hw_cmd_ahb_vote : CPAS cmd struct for AHB vote + * + * @client_handle: Client handle + * @ahb_vote: AHB voting info + * + */ +struct cam_cpas_hw_cmd_ahb_vote { + uint32_t client_handle; + struct cam_ahb_vote *ahb_vote; +}; + +/** + * struct cam_cpas_hw_cmd_axi_vote : CPAS cmd struct for AXI vote + * + * @client_handle: Client handle + * @axi_vote: axi bandwidth vote + * + */ +struct cam_cpas_hw_cmd_axi_vote { + uint32_t client_handle; + struct cam_axi_vote *axi_vote; +}; + +/** + * struct cam_cpas_hw_cmd_start : CPAS cmd struct for start + * + * @client_handle: Client handle + * + */ +struct cam_cpas_hw_cmd_start { + uint32_t client_handle; + struct cam_ahb_vote *ahb_vote; + struct cam_axi_vote *axi_vote; +}; + +/** + * struct cam_cpas_hw_cmd_stop : CPAS cmd struct for stop + * + * @client_handle: Client handle + * + */ +struct cam_cpas_hw_cmd_stop { + uint32_t client_handle; +}; + +/** + * struct cam_cpas_hw_caps : CPAS HW capabilities + * + * @camera_family: Camera family type + * @camera_version: Camera version + * @cpas_version: CPAS version + * @camera_capability: Camera hw capabilities + * + */ +struct cam_cpas_hw_caps { + uint32_t camera_family; + struct cam_hw_version camera_version; + struct cam_hw_version cpas_version; + uint32_t camera_capability; +}; + +int cam_cpas_hw_probe(struct platform_device *pdev, + struct cam_hw_intf **hw_intf); +int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf); + +#endif /* _CAM_CPAS_HW_INTF_H_ */ diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c new file mode 100644 index 000000000000..e43d9f01ec2c --- /dev/null +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cam_subdev.h" +#include "cam_cpas_hw_intf.h" + +#define CAM_CPAS_DEV_NAME "cam-cpas" +#define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done) + +/** + * struct cam_cpas_intf : CPAS interface + * + * @pdev: Platform device + * @subdev: Subdev info + * @hw_intf: CPAS HW interface + * @hw_caps: CPAS HW capabilities + * @intf_lock: CPAS interface mutex + * @open_cnt: CPAS subdev open count + * @probe_done: Whether CPAS prove completed + * + */ +struct cam_cpas_intf { + struct platform_device *pdev; + struct cam_subdev subdev; + struct cam_hw_intf *hw_intf; + struct cam_cpas_hw_caps hw_caps; + struct mutex intf_lock; + uint32_t open_cnt; + bool probe_done; +}; + +static struct cam_cpas_intf *g_cpas_intf; + +const char *cam_cpas_axi_util_path_type_to_string( + uint32_t path_data_type) +{ + switch (path_data_type) { + /* IFE Paths */ + case CAM_AXI_PATH_DATA_IFE_LINEAR: + return "IFE_LINEAR"; + case CAM_AXI_PATH_DATA_IFE_VID: + return "IFE_VID"; + case CAM_AXI_PATH_DATA_IFE_DISP: + return "IFE_DISP"; + case CAM_AXI_PATH_DATA_IFE_STATS: + return "IFE_STATS"; + case CAM_AXI_PATH_DATA_IFE_RDI0: + return "IFE_RDI0"; + case CAM_AXI_PATH_DATA_IFE_RDI1: + return "IFE_RDI1"; + case CAM_AXI_PATH_DATA_IFE_RDI2: + return "IFE_RDI2"; + case CAM_AXI_PATH_DATA_IFE_RDI3: + return "IFE_RDI3"; + case CAM_AXI_PATH_DATA_IFE_PDAF: + return "IFE_PDAF"; + case CAM_AXI_PATH_DATA_IFE_PIXEL_RAW: + return "IFE_PIXEL_RAW"; + + /* IPE Paths */ + case CAM_AXI_PATH_DATA_IPE_RD_IN: + return "IPE_RD_IN"; + case CAM_AXI_PATH_DATA_IPE_RD_REF: + return "IPE_RD_REF"; + case CAM_AXI_PATH_DATA_IPE_WR_VID: + return "IPE_WR_VID"; + case CAM_AXI_PATH_DATA_IPE_WR_DISP: + return "IPE_WR_DISP"; + case CAM_AXI_PATH_DATA_IPE_WR_REF: + return "IPE_WR_REF"; + + /* Common Paths */ + case CAM_AXI_PATH_DATA_ALL: + return "DATA_ALL"; + default: + return "IFE_PATH_INVALID"; + } +} +EXPORT_SYMBOL(cam_cpas_axi_util_path_type_to_string); + +const char *cam_cpas_axi_util_trans_type_to_string( + uint32_t transac_type) +{ + switch (transac_type) { + case CAM_AXI_TRANSACTION_READ: + return "TRANSAC_READ"; + case CAM_AXI_TRANSACTION_WRITE: + return "TRANSAC_WRITE"; + default: + return "TRANSAC_INVALID"; + } +} +EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string); + +int cam_cpas_get_cpas_hw_version(uint32_t *hw_version) +{ + struct cam_hw_info *cpas_hw = NULL; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (!hw_version) { + CAM_ERR(CAM_CPAS, "invalid input %pK", hw_version); + return -EINVAL; + } + + cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv; + + *hw_version = cpas_hw->soc_info.hw_version; + + if (*hw_version == CAM_CPAS_TITAN_NONE) { + CAM_DBG(CAM_CPAS, "Didn't find a valid HW Version %d", + *hw_version); + } + + return 0; +} + +int cam_cpas_get_hw_info(uint32_t *camera_family, + struct cam_hw_version *camera_version, + struct cam_hw_version *cpas_version, + uint32_t *cam_caps) +{ + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (!camera_family || !camera_version || !cpas_version || !cam_caps) { + CAM_ERR(CAM_CPAS, "invalid input %pK %pK %pK %pK", + camera_family, camera_version, cpas_version, cam_caps); + return -EINVAL; + } + + *camera_family = g_cpas_intf->hw_caps.camera_family; + *camera_version = g_cpas_intf->hw_caps.camera_version; + *cpas_version = g_cpas_intf->hw_caps.cpas_version; + *cam_caps = g_cpas_intf->hw_caps.camera_capability; + + return 0; +} +EXPORT_SYMBOL(cam_cpas_get_hw_info); + +int cam_cpas_reg_write(uint32_t client_handle, + enum cam_cpas_reg_base reg_base, uint32_t offset, bool mb, + uint32_t value) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + struct cam_cpas_hw_cmd_reg_read_write cmd_reg_write; + + cmd_reg_write.client_handle = client_handle; + cmd_reg_write.reg_base = reg_base; + cmd_reg_write.offset = offset; + cmd_reg_write.value = value; + cmd_reg_write.mb = mb; + + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_REG_WRITE, &cmd_reg_write, + sizeof(struct cam_cpas_hw_cmd_reg_read_write)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_reg_write); + +int cam_cpas_reg_read(uint32_t client_handle, + enum cam_cpas_reg_base reg_base, uint32_t offset, bool mb, + uint32_t *value) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (!value) { + CAM_ERR(CAM_CPAS, "Invalid arg value"); + return -EINVAL; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + struct cam_cpas_hw_cmd_reg_read_write cmd_reg_read; + + cmd_reg_read.client_handle = client_handle; + cmd_reg_read.reg_base = reg_base; + cmd_reg_read.offset = offset; + cmd_reg_read.mb = mb; + cmd_reg_read.value = 0; + + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_REG_READ, &cmd_reg_read, + sizeof(struct cam_cpas_hw_cmd_reg_read_write)); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + return rc; + } + + *value = cmd_reg_read.value; + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_reg_read); + +int cam_cpas_update_axi_vote(uint32_t client_handle, + struct cam_axi_vote *axi_vote) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (!axi_vote) { + CAM_ERR(CAM_CPAS, "NULL axi vote"); + return -EINVAL; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + struct cam_cpas_hw_cmd_axi_vote cmd_axi_vote; + + cmd_axi_vote.client_handle = client_handle; + cmd_axi_vote.axi_vote = axi_vote; + + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_AXI_VOTE, &cmd_axi_vote, + sizeof(struct cam_cpas_hw_cmd_axi_vote)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_update_axi_vote); + +int cam_cpas_update_ahb_vote(uint32_t client_handle, + struct cam_ahb_vote *ahb_vote) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + struct cam_cpas_hw_cmd_ahb_vote cmd_ahb_vote; + + cmd_ahb_vote.client_handle = client_handle; + cmd_ahb_vote.ahb_vote = ahb_vote; + + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_AHB_VOTE, &cmd_ahb_vote, + sizeof(struct cam_cpas_hw_cmd_ahb_vote)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_update_ahb_vote); + +int cam_cpas_stop(uint32_t client_handle) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (g_cpas_intf->hw_intf->hw_ops.stop) { + struct cam_cpas_hw_cmd_stop cmd_hw_stop; + + cmd_hw_stop.client_handle = client_handle; + + rc = g_cpas_intf->hw_intf->hw_ops.stop( + g_cpas_intf->hw_intf->hw_priv, &cmd_hw_stop, + sizeof(struct cam_cpas_hw_cmd_stop)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in stop, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid stop ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_stop); + +int cam_cpas_start(uint32_t client_handle, + struct cam_ahb_vote *ahb_vote, struct cam_axi_vote *axi_vote) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (!axi_vote) { + CAM_ERR(CAM_CPAS, "NULL axi vote"); + return -EINVAL; + } + + if (g_cpas_intf->hw_intf->hw_ops.start) { + struct cam_cpas_hw_cmd_start cmd_hw_start; + + cmd_hw_start.client_handle = client_handle; + cmd_hw_start.ahb_vote = ahb_vote; + cmd_hw_start.axi_vote = axi_vote; + + rc = g_cpas_intf->hw_intf->hw_ops.start( + g_cpas_intf->hw_intf->hw_priv, &cmd_hw_start, + sizeof(struct cam_cpas_hw_cmd_start)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in start, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid start ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_start); + +int cam_cpas_unregister_client(uint32_t client_handle) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_UNREGISTER_CLIENT, + &client_handle, sizeof(uint32_t)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_unregister_client); + +int cam_cpas_register_client( + struct cam_cpas_register_params *register_params) +{ + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_REGISTER_CLIENT, register_params, + sizeof(struct cam_cpas_register_params)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EINVAL; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_register_client); + +int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf, + struct cam_control *cmd) +{ + int rc = 0; + + if (!cmd) { + CAM_ERR(CAM_CPAS, "Invalid input cmd"); + return -EINVAL; + } + + switch (cmd->op_code) { + case CAM_QUERY_CAP: { + struct cam_cpas_query_cap query; + + rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle), + sizeof(query)); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d", + rc); + break; + } + + rc = cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, + &query.reserved); + if (rc) + break; + + rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query, + sizeof(query)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc); + + break; + } + case CAM_SD_SHUTDOWN: + break; + default: + CAM_ERR(CAM_CPAS, "Unknown op code %d for CPAS", cmd->op_code); + rc = -EINVAL; + break; + } + + return rc; +} + +static int cam_cpas_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); + + if (!cpas_intf || !cpas_intf->probe_done) { + CAM_ERR(CAM_CPAS, "CPAS not initialized"); + return -ENODEV; + } + + mutex_lock(&cpas_intf->intf_lock); + cpas_intf->open_cnt++; + CAM_DBG(CAM_CPAS, "CPAS Subdev open count %d", cpas_intf->open_cnt); + mutex_unlock(&cpas_intf->intf_lock); + + return 0; +} + +static int cam_cpas_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); + + if (!cpas_intf || !cpas_intf->probe_done) { + CAM_ERR(CAM_CPAS, "CPAS not initialized"); + return -ENODEV; + } + + mutex_lock(&cpas_intf->intf_lock); + cpas_intf->open_cnt--; + CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt); + mutex_unlock(&cpas_intf->intf_lock); + + return 0; +} + +static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int32_t rc; + struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); + + if (!cpas_intf || !cpas_intf->probe_done) { + CAM_ERR(CAM_CPAS, "CPAS not initialized"); + return -ENODEV; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg); + break; + default: + CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); + rc = -EINVAL; + break; + } + + return rc; +} + +#ifdef CONFIG_COMPAT +static long cam_cpas_subdev_compat_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int32_t rc; + struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); + + if (!cpas_intf || !cpas_intf->probe_done) { + CAM_ERR(CAM_CPAS, "CPAS not initialized"); + return -ENODEV; + } + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_CPAS, "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_cpas_subdev_cmd(cpas_intf, &cmd_data); + break; + default: + CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); + rc = -EINVAL; + break; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_CPAS, + "Failed to copy to user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + + return rc; +} +#endif + +static struct v4l2_subdev_core_ops cpas_subdev_core_ops = { + .ioctl = cam_cpas_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_cpas_subdev_compat_ioctl, +#endif +}; + +static const struct v4l2_subdev_ops cpas_subdev_ops = { + .core = &cpas_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops cpas_subdev_intern_ops = { + .open = cam_cpas_subdev_open, + .close = cam_cpas_subdev_close, +}; + +static int cam_cpas_subdev_register(struct platform_device *pdev) +{ + int rc; + struct cam_subdev *subdev; + + if (!g_cpas_intf) + return -EINVAL; + + subdev = &g_cpas_intf->subdev; + + subdev->name = CAM_CPAS_DEV_NAME; + subdev->pdev = pdev; + subdev->ops = &cpas_subdev_ops; + subdev->internal_ops = &cpas_subdev_intern_ops; + subdev->token = g_cpas_intf; + subdev->sd_flags = + V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + subdev->ent_function = CAM_CPAS_DEVICE_TYPE; + + rc = cam_register_subdev(subdev); + if (rc) { + CAM_ERR(CAM_CPAS, "failed register subdev: %s!", + CAM_CPAS_DEV_NAME); + return rc; + } + + platform_set_drvdata(g_cpas_intf->pdev, g_cpas_intf); + return rc; +} + +static int cam_cpas_dev_probe(struct platform_device *pdev) +{ + struct cam_cpas_hw_caps *hw_caps; + struct cam_hw_intf *hw_intf; + int rc; + + if (g_cpas_intf) { + CAM_ERR(CAM_CPAS, "cpas dev proble already done"); + return -EALREADY; + } + + g_cpas_intf = kzalloc(sizeof(*g_cpas_intf), GFP_KERNEL); + if (!g_cpas_intf) + return -ENOMEM; + + mutex_init(&g_cpas_intf->intf_lock); + g_cpas_intf->pdev = pdev; + + rc = cam_cpas_hw_probe(pdev, &g_cpas_intf->hw_intf); + if (rc || (g_cpas_intf->hw_intf == NULL)) { + CAM_ERR(CAM_CPAS, "Failed in hw probe, rc=%d", rc); + goto error_destroy_mem; + } + + hw_intf = g_cpas_intf->hw_intf; + hw_caps = &g_cpas_intf->hw_caps; + if (hw_intf->hw_ops.get_hw_caps) { + rc = hw_intf->hw_ops.get_hw_caps(hw_intf->hw_priv, + hw_caps, sizeof(struct cam_cpas_hw_caps)); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in get_hw_caps, rc=%d", rc); + goto error_hw_remove; + } + } else { + CAM_ERR(CAM_CPAS, "Invalid get_hw_caps ops"); + goto error_hw_remove; + } + + rc = cam_cpas_subdev_register(pdev); + if (rc) + goto error_hw_remove; + + g_cpas_intf->probe_done = true; + CAM_DBG(CAM_CPAS, + "CPAS INTF Probe success %d, %d.%d.%d, %d.%d.%d, 0x%x", + hw_caps->camera_family, hw_caps->camera_version.major, + hw_caps->camera_version.minor, hw_caps->camera_version.incr, + hw_caps->cpas_version.major, hw_caps->cpas_version.minor, + hw_caps->cpas_version.incr, hw_caps->camera_capability); + + return rc; + +error_hw_remove: + cam_cpas_hw_remove(g_cpas_intf->hw_intf); +error_destroy_mem: + mutex_destroy(&g_cpas_intf->intf_lock); + kfree(g_cpas_intf); + g_cpas_intf = NULL; + CAM_ERR(CAM_CPAS, "CPAS probe failed"); + return rc; +} + +static int cam_cpas_dev_remove(struct platform_device *dev) +{ + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + mutex_lock(&g_cpas_intf->intf_lock); + g_cpas_intf->probe_done = false; + cam_unregister_subdev(&g_cpas_intf->subdev); + cam_cpas_hw_remove(g_cpas_intf->hw_intf); + mutex_unlock(&g_cpas_intf->intf_lock); + mutex_destroy(&g_cpas_intf->intf_lock); + kfree(g_cpas_intf); + g_cpas_intf = NULL; + + return 0; +} + +static const struct of_device_id cam_cpas_dt_match[] = { + {.compatible = "qcom,cam-cpas"}, + {} +}; + +static struct platform_driver cam_cpas_driver = { + .probe = cam_cpas_dev_probe, + .remove = cam_cpas_dev_remove, + .driver = { + .name = CAM_CPAS_DEV_NAME, + .owner = THIS_MODULE, + .of_match_table = cam_cpas_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_cpas_dev_init_module(void) +{ + return platform_driver_register(&cam_cpas_driver); +} + +static void __exit cam_cpas_dev_exit_module(void) +{ + platform_driver_unregister(&cam_cpas_driver); +} + +module_init(cam_cpas_dev_init_module); +module_exit(cam_cpas_dev_exit_module); +MODULE_DESCRIPTION("MSM CPAS driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c new file mode 100644 index 000000000000..9dd24cdaa3d1 --- /dev/null +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -0,0 +1,614 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_cpas_api.h" +#include "cam_cpas_hw_intf.h" +#include "cam_cpas_hw.h" +#include "cam_cpas_soc.h" + +static uint cpas_dump; +module_param(cpas_dump, uint, 0644); + + +void cam_cpas_dump_axi_vote_info( + const struct cam_cpas_client *cpas_client, + const char *identifier, + struct cam_axi_vote *axi_vote) +{ + int i; + + if (!cpas_dump) + return; + + if (!axi_vote || (axi_vote->num_paths > + CAM_CPAS_MAX_PATHS_PER_CLIENT)) { + CAM_ERR(CAM_PERF, "Invalid num_paths %d", + axi_vote ? axi_vote->num_paths : -1); + return; + } + + for (i = 0; i < axi_vote->num_paths; i++) { + CAM_INFO(CAM_PERF, + "Client [%s][%d] : [%s], Path=[%d] [%d], camnoc[%llu], mnoc_ab[%llu], mnoc_ib[%llu]", + cpas_client->data.identifier, cpas_client->data.cell_index, + identifier, + axi_vote->axi_path[i].path_data_type, + axi_vote->axi_path[i].transac_type, + axi_vote->axi_path[i].camnoc_bw, + axi_vote->axi_path[i].mnoc_ab_bw, + axi_vote->axi_path[i].mnoc_ib_bw); + } + +} + +void cam_cpas_util_debug_parse_data( + struct cam_cpas_private_soc *soc_private) +{ + int i, j; + struct cam_cpas_tree_node *curr_node = NULL; + + if (!cpas_dump) + return; + + for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) { + if (!soc_private->tree_node[i]) + break; + + curr_node = soc_private->tree_node[i]; + CAM_INFO(CAM_CPAS, + "NODE cell_idx: %d, level: %d, name: %s, axi_port_idx: %d, merge_type: %d, parent_name: %s", + curr_node->cell_idx, curr_node->level_idx, + curr_node->node_name, curr_node->axi_port_idx, + curr_node->merge_type, curr_node->parent_node ? + curr_node->parent_node->node_name : "no parent"); + + if (curr_node->level_idx) + continue; + + CAM_INFO(CAM_CPAS, "path_type: %d, transac_type: %s", + curr_node->path_data_type, + cam_cpas_axi_util_trans_type_to_string( + curr_node->path_trans_type)); + + for (j = 0; j < CAM_CPAS_PATH_DATA_MAX; j++) { + CAM_INFO(CAM_CPAS, "Constituent path: %d", + curr_node->constituent_paths[j] ? j : -1); + } + } + + CAM_INFO(CAM_CPAS, "NUMBER OF NODES PARSED: %d", i); +} + +int cam_cpas_node_tree_cleanup(struct cam_cpas *cpas_core, + struct cam_cpas_private_soc *soc_private) +{ + int i = 0; + + for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) { + if (soc_private->tree_node[i]) { + of_node_put(soc_private->tree_node[i]->tree_dev_node); + kfree(soc_private->tree_node[i]); + soc_private->tree_node[i] = NULL; + } + } + + for (i = 0; i < CAM_CPAS_MAX_TREE_LEVELS; i++) { + of_node_put(soc_private->level_node[i]); + soc_private->level_node[i] = NULL; + } + + of_node_put(soc_private->camera_bus_node); + soc_private->camera_bus_node = NULL; + mutex_destroy(&cpas_core->tree_lock); + + return 0; +} + +static int cam_cpas_util_path_type_to_idx(uint32_t *path_data_type) +{ + if (*path_data_type >= CAM_CPAS_PATH_DATA_CONSO_OFFSET) + *path_data_type = CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT + + (*path_data_type % CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT); + else + *path_data_type %= CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT; + + if (*path_data_type >= CAM_CPAS_PATH_DATA_MAX) { + CAM_ERR(CAM_CPAS, "index Invalid: %d", path_data_type); + return -EINVAL; + } + + return 0; +} + +static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, + struct device_node *of_node, struct cam_cpas_private_soc *soc_private) +{ + struct device_node *camera_bus_node; + struct device_node *level_node; + struct device_node *curr_node; + struct device_node *parent_node; + struct device_node *mnoc_node; + int mnoc_idx = 0; + uint32_t path_idx; + bool camnoc_max_needed = false; + struct cam_cpas_tree_node *curr_node_ptr = NULL; + struct cam_cpas_client *curr_client = NULL; + const char *client_name = NULL; + uint32_t client_idx = 0, cell_idx = 0, level_idx = 0; + int rc = 0, count = 0, i; + + camera_bus_node = of_find_node_by_name(of_node, "camera-bus-nodes"); + if (!camera_bus_node) { + CAM_ERR(CAM_CPAS, "Camera Bus node not found in cpas DT node"); + return -EINVAL; + } + + soc_private->camera_bus_node = camera_bus_node; + + for_each_available_child_of_node(camera_bus_node, level_node) { + rc = of_property_read_u32(level_node, "level-index", + &level_idx); + if (rc) { + CAM_ERR(CAM_CPAS, "Error raeding level idx rc: %d", rc); + return rc; + } + if (level_idx >= CAM_CPAS_MAX_TREE_LEVELS) { + CAM_ERR(CAM_CPAS, "Invalid level idx: %d", level_idx); + return -EINVAL; + } + + soc_private->level_node[level_idx] = level_node; + camnoc_max_needed = of_property_read_bool(level_node, + "camnoc-max-needed"); + + for_each_available_child_of_node(level_node, curr_node) { + curr_node_ptr = + kzalloc(sizeof(struct cam_cpas_tree_node), + GFP_KERNEL); + if (!curr_node_ptr) + return -ENOMEM; + + curr_node_ptr->tree_dev_node = curr_node; + rc = of_property_read_u32(curr_node, "cell-index", + &curr_node_ptr->cell_idx); + if (rc) { + CAM_ERR(CAM_CPAS, "Node index not found"); + return rc; + } + + if (curr_node_ptr->cell_idx >= + CAM_CPAS_MAX_TREE_NODES) { + CAM_ERR(CAM_CPAS, "Invalid cell idx: %d", + cell_idx); + return -EINVAL; + } + + soc_private->tree_node[curr_node_ptr->cell_idx] = + curr_node_ptr; + curr_node_ptr->level_idx = level_idx; + + rc = of_property_read_string(curr_node, "node-name", + &curr_node_ptr->node_name); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed to read node-name rc=%d", + rc); + return rc; + } + + curr_node_ptr->camnoc_max_needed = camnoc_max_needed; + rc = of_property_read_u32(curr_node, "bus-width-factor", + &curr_node_ptr->bus_width_factor); + if (rc) + curr_node_ptr->bus_width_factor = 1; + + rc = of_property_read_u32(curr_node, + "traffic-merge-type", + &curr_node_ptr->merge_type); + + curr_node_ptr->axi_port_idx = -1; + mnoc_node = of_find_node_by_name(curr_node, + "qcom,axi-port-mnoc"); + if (mnoc_node) { + if (mnoc_idx >= CAM_CPAS_MAX_AXI_PORTS) + return -EINVAL; + + cpas_core->axi_port[mnoc_idx].axi_port_node + = mnoc_node; + rc = of_property_read_string( + curr_node, "qcom,axi-port-name", + &cpas_core->axi_port[mnoc_idx] + .axi_port_name); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed to read mnoc-port-name rc=%d", + rc); + return rc; + } + cpas_core->axi_port + [mnoc_idx].ib_bw_voting_needed + = of_property_read_bool(curr_node, + "ib-bw-voting-needed"); + curr_node_ptr->axi_port_idx = mnoc_idx; + mnoc_idx++; + cpas_core->num_axi_ports++; + } + + rc = of_property_read_string(curr_node, + "client-name", &client_name); + if (!rc) { + rc = of_property_read_u32(curr_node, + "traffic-data", &curr_node_ptr->path_data_type); + if (rc) { + CAM_ERR(CAM_CPAS, + "Path Data type not found"); + return rc; + } + + rc = cam_cpas_util_path_type_to_idx( + &curr_node_ptr->path_data_type); + if (rc) + return rc; + + rc = of_property_read_u32(curr_node, + "traffic-transaction-type", + &curr_node_ptr->path_trans_type); + if (rc) { + CAM_ERR(CAM_CPAS, + "Path Transac type not found"); + return rc; + } + + if (curr_node_ptr->path_trans_type >= + CAM_CPAS_TRANSACTION_MAX) { + CAM_ERR(CAM_CPAS, + "Invalid transac type: %d", + curr_node_ptr->path_trans_type); + return -EINVAL; + } + + count = of_property_count_u32_elems(curr_node, + "constituent-paths"); + for (i = 0; i < count; i++) { + rc = of_property_read_u32_index( + curr_node, "constituent-paths", + i, &path_idx); + if (rc) { + CAM_ERR(CAM_CPAS, + "No constituent path at %d", i); + return rc; + } + + rc = cam_cpas_util_path_type_to_idx( + &path_idx); + if (rc) + return rc; + + curr_node_ptr->constituent_paths + [path_idx] = true; + } + + rc = cam_common_util_get_string_index( + soc_private->client_name, + soc_private->num_clients, + client_name, &client_idx); + if (rc) { + CAM_ERR(CAM_CPAS, + "client name not found in list: %s", + client_name); + return rc; + } + + if (client_idx >= CAM_CPAS_MAX_CLIENTS) + return -EINVAL; + + curr_client = + cpas_core->cpas_client[client_idx]; + curr_client->tree_node_valid = true; + curr_client->tree_node + [curr_node_ptr->path_data_type] + [curr_node_ptr->path_trans_type] = + curr_node_ptr; + CAM_DBG(CAM_CPAS, + "CLIENT NODE ADDED: %d %d %s", + curr_node_ptr->path_data_type, + curr_node_ptr->path_trans_type, + client_name); + } + + parent_node = of_parse_phandle(curr_node, + "parent-node", 0); + if (parent_node) { + of_property_read_u32(parent_node, "cell-index", + &cell_idx); + curr_node_ptr->parent_node = + soc_private->tree_node[cell_idx]; + } else { + CAM_DBG(CAM_CPAS, + "no parent node at this level"); + } + } + } + mutex_init(&cpas_core->tree_lock); + cam_cpas_util_debug_parse_data(soc_private); + + return 0; +} + +int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, + struct platform_device *pdev, struct cam_cpas_private_soc *soc_private) +{ + struct device_node *of_node; + int count = 0, i = 0, rc = 0; + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + + if (!soc_private || !pdev) { + CAM_ERR(CAM_CPAS, "invalid input arg %pK %pK", + soc_private, pdev); + return -EINVAL; + } + + of_node = pdev->dev.of_node; + + rc = of_property_read_string(of_node, "arch-compat", + &soc_private->arch_compat); + if (rc) { + CAM_ERR(CAM_CPAS, "device %s failed to read arch-compat", + pdev->name); + return rc; + } + + soc_private->camnoc_axi_min_ib_bw = 0; + rc = of_property_read_u64(of_node, + "camnoc-axi-min-ib-bw", + &soc_private->camnoc_axi_min_ib_bw); + if (rc == -EOVERFLOW) { + soc_private->camnoc_axi_min_ib_bw = 0; + rc = of_property_read_u32(of_node, + "camnoc-axi-min-ib-bw", + (u32 *)&soc_private->camnoc_axi_min_ib_bw); + } + + if (rc) { + CAM_DBG(CAM_CPAS, + "failed to read camnoc-axi-min-ib-bw rc:%d", rc); + soc_private->camnoc_axi_min_ib_bw = + CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; + } + + CAM_DBG(CAM_CPAS, "camnoc-axi-min-ib-bw = %llu", + soc_private->camnoc_axi_min_ib_bw); + + soc_private->client_id_based = of_property_read_bool(of_node, + "client-id-based"); + + count = of_property_count_strings(of_node, "client-names"); + if (count <= 0) { + CAM_ERR(CAM_CPAS, "no client-names found"); + count = 0; + return -EINVAL; + } else if (count > CAM_CPAS_MAX_CLIENTS) { + CAM_ERR(CAM_CPAS, "Number of clients %d greater than max %d", + count, CAM_CPAS_MAX_CLIENTS); + count = 0; + return -EINVAL; + } + + soc_private->num_clients = count; + CAM_DBG(CAM_CPAS, + "arch-compat=%s, client_id_based = %d, num_clients=%d", + soc_private->arch_compat, soc_private->client_id_based, + soc_private->num_clients); + + for (i = 0; i < soc_private->num_clients; i++) { + rc = of_property_read_string_index(of_node, + "client-names", i, &soc_private->client_name[i]); + if (rc) { + CAM_ERR(CAM_CPAS, "no client-name at cnt=%d", i); + return -EINVAL; + } + + cpas_core->cpas_client[i] = + kzalloc(sizeof(struct cam_cpas_client), GFP_KERNEL); + if (!cpas_core->cpas_client[i]) { + rc = -ENOMEM; + goto cleanup_clients; + } + + CAM_DBG(CAM_CPAS, "Client[%d] : %s", i, + soc_private->client_name[i]); + } + + soc_private->control_camnoc_axi_clk = of_property_read_bool(of_node, + "control-camnoc-axi-clk"); + + if (soc_private->control_camnoc_axi_clk == true) { + rc = of_property_read_u32(of_node, "camnoc-bus-width", + &soc_private->camnoc_bus_width); + if (rc || (soc_private->camnoc_bus_width == 0)) { + CAM_ERR(CAM_CPAS, "Bus width not found rc=%d, %d", + rc, soc_private->camnoc_bus_width); + goto cleanup_clients; + } + + rc = of_property_read_u32(of_node, + "camnoc-axi-clk-bw-margin-perc", + &soc_private->camnoc_axi_clk_bw_margin); + + if (rc) { + /* this is not fatal, overwrite rc */ + rc = 0; + soc_private->camnoc_axi_clk_bw_margin = 0; + } + } + + CAM_DBG(CAM_CPAS, + "control_camnoc_axi_clk=%d, width=%d, margin=%d", + soc_private->control_camnoc_axi_clk, + soc_private->camnoc_bus_width, + soc_private->camnoc_axi_clk_bw_margin); + + count = of_property_count_u32_elems(of_node, "vdd-corners"); + if ((count > 0) && (count <= CAM_REGULATOR_LEVEL_MAX) && + (of_property_count_strings(of_node, "vdd-corner-ahb-mapping") == + count)) { + const char *ahb_string; + + for (i = 0; i < count; i++) { + rc = of_property_read_u32_index(of_node, "vdd-corners", + i, &soc_private->vdd_ahb[i].vdd_corner); + if (rc) { + CAM_ERR(CAM_CPAS, + "vdd-corners failed at index=%d", i); + rc = -ENODEV; + goto cleanup_clients; + } + + rc = of_property_read_string_index(of_node, + "vdd-corner-ahb-mapping", i, &ahb_string); + if (rc) { + CAM_ERR(CAM_CPAS, + "no ahb-mapping at index=%d", i); + rc = -ENODEV; + goto cleanup_clients; + } + + rc = cam_soc_util_get_level_from_string(ahb_string, + &soc_private->vdd_ahb[i].ahb_level); + if (rc) { + CAM_ERR(CAM_CPAS, + "invalid ahb-string at index=%d", i); + rc = -EINVAL; + goto cleanup_clients; + } + + CAM_DBG(CAM_CPAS, + "Vdd-AHB mapping [%d] : [%d] [%s] [%d]", i, + soc_private->vdd_ahb[i].vdd_corner, + ahb_string, soc_private->vdd_ahb[i].ahb_level); + } + + soc_private->num_vdd_ahb_mapping = count; + } + + rc = cam_cpas_parse_node_tree(cpas_core, of_node, soc_private); + if (rc) { + CAM_ERR(CAM_CPAS, "Node tree parsing failed rc: %d", rc); + goto cleanup_tree; + } + + return 0; + +cleanup_tree: + cam_cpas_node_tree_cleanup(cpas_core, soc_private); +cleanup_clients: + cam_cpas_util_client_cleanup(cpas_hw); + return rc; +} + +int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, struct cam_hw_info *cpas_hw) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in get_dt_properties, rc=%d", rc); + return rc; + } + + if (soc_info->irq_line && !irq_handler) { + CAM_ERR(CAM_CPAS, "Invalid IRQ handler"); + return -EINVAL; + } + + rc = cam_soc_util_request_platform_resource(soc_info, irq_handler, + cpas_hw); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in request_platform_resource, rc=%d", + rc); + return rc; + } + + soc_info->soc_private = kzalloc(sizeof(struct cam_cpas_private_soc), + GFP_KERNEL); + if (!soc_info->soc_private) { + rc = -ENOMEM; + goto release_res; + } + + rc = cam_cpas_get_custom_dt_info(cpas_hw, soc_info->pdev, + soc_info->soc_private); + if (rc) { + CAM_ERR(CAM_CPAS, "failed in get_custom_info, rc=%d", rc); + goto free_soc_private; + } + + return rc; + +free_soc_private: + kfree(soc_info->soc_private); +release_res: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} + +int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info) +{ + int rc; + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_ERR(CAM_CPAS, "release platform failed, rc=%d", rc); + + kfree(soc_info->soc_private); + soc_info->soc_private = NULL; + + return rc; +} + +int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info, + enum cam_vote_level default_level) +{ + int rc = 0; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + default_level, true); + if (rc) + CAM_ERR(CAM_CPAS, "enable platform resource failed, rc=%d", rc); + + return rc; +} + +int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info, + bool disable_clocks, bool disable_irq) +{ + int rc = 0; + + rc = cam_soc_util_disable_platform_resource(soc_info, + disable_clocks, disable_irq); + if (rc) + CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc); + + return rc; +} + +int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_irq_disable(soc_info); + if (rc) + CAM_ERR(CAM_CPAS, "disable irq failed, rc=%d", rc); + + return rc; +} diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h new file mode 100644 index 000000000000..7921cd4b956e --- /dev/null +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CPAS_SOC_H_ +#define _CAM_CPAS_SOC_H_ + +#include "cam_soc_util.h" +#include "cam_cpas_hw.h" + +#define CAM_REGULATOR_LEVEL_MAX 16 +#define CAM_CPAS_MAX_TREE_NODES 50 + +/** + * struct cam_cpas_vdd_ahb_mapping : Voltage to ahb level mapping + * + * @vdd_corner : Voltage corner value + * @ahb_level : AHB vote level corresponds to this vdd_corner + * + */ +struct cam_cpas_vdd_ahb_mapping { + unsigned int vdd_corner; + enum cam_vote_level ahb_level; +}; + +/** + * struct cpas_tree_node: Generic cpas tree node for BW voting + * + * @cell_idx: Index to identify node from device tree and its parent + * @level_idx: Index to identify at what level the node is present + * @axi_port_idx: Index to identify which axi port to vote the consolidated bw + * @path_data_type: Traffic type info from device tree (ife-vid, ife-disp etc) + * @path_trans_type: Transaction type info from device tree (rd, wr) + * @merge_type: Traffic merge type (calculation info) from device tree + * @bus_width_factor: Factor for accounting bus width in CAMNOC bw calculation + * @camnoc_bw: CAMNOC bw value at current node + * @mnoc_ab_bw: MNOC AB bw value at current node + * @mnoc_ib_bw: MNOC IB bw value at current node + * @ddr_ab_bw: DDR AB bw value at current node + * @ddr_ib_bw: DDR IB bw value at current node + * @camnoc_max_needed: If node is needed for CAMNOC BW calculation then true + * @constituent_paths: Constituent paths presence info from device tree + * Ex: For CAM_CPAS_PATH_DATA_IFE_UBWC_STATS, index corresponding to + * CAM_CPAS_PATH_DATA_IFE_VID, CAM_CPAS_PATH_DATA_IFE_DISP and + * CAM_CPAS_PATH_DATA_IFE_STATS + * @tree_dev_node: Device node from devicetree for current tree node + * @parent_node: Pointer to node one or more level above the current level + * (starting from end node of cpas client) + * + */ +struct cam_cpas_tree_node { + uint32_t cell_idx; + uint32_t level_idx; + int axi_port_idx; + const char *node_name; + uint32_t path_data_type; + uint32_t path_trans_type; + uint32_t merge_type; + uint32_t bus_width_factor; + uint64_t camnoc_bw; + uint64_t mnoc_ab_bw; + uint64_t mnoc_ib_bw; + uint64_t ddr_ab_bw; + uint64_t ddr_ib_bw; + bool camnoc_max_needed; + bool constituent_paths[CAM_CPAS_PATH_DATA_MAX]; + struct device_node *tree_dev_node; + struct cam_cpas_tree_node *parent_node; +}; + +/** + * struct cam_cpas_private_soc : CPAS private DT info + * + * @arch_compat: ARCH compatible string + * @client_id_based: Whether clients are id based + * @num_clients: Number of clients supported + * @client_name: Client names + * @tree_node: Array of pointers to all tree nodes required to calculate + * axi bw, arranged with help of cell index in device tree + * @camera_bus_node: Device tree node from cpas node + * @level_node: Device tree node for each level in camera_bus_node + * @num_vdd_ahb_mapping : Number of vdd to ahb level mapping supported + * @vdd_ahb : AHB level mapping info for the supported vdd levels + * @control_camnoc_axi_clk : Whether CPAS driver need to set camnoc axi clk freq + * @camnoc_bus_width : CAMNOC Bus width + * @camnoc_axi_clk_bw_margin : BW Margin in percentage to add while calculating + * camnoc axi clock + * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target + * + */ +struct cam_cpas_private_soc { + const char *arch_compat; + bool client_id_based; + uint32_t num_clients; + const char *client_name[CAM_CPAS_MAX_CLIENTS]; + struct cam_cpas_tree_node *tree_node[CAM_CPAS_MAX_TREE_NODES]; + struct device_node *camera_bus_node; + struct device_node *level_node[CAM_CPAS_MAX_TREE_LEVELS]; + uint32_t num_vdd_ahb_mapping; + struct cam_cpas_vdd_ahb_mapping vdd_ahb[CAM_REGULATOR_LEVEL_MAX]; + bool control_camnoc_axi_clk; + uint32_t camnoc_bus_width; + uint32_t camnoc_axi_clk_bw_margin; + uint64_t camnoc_axi_min_ib_bw; +}; + +void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); +void cam_cpas_dump_axi_vote_info( + const struct cam_cpas_client *cpas_client, + const char *identifier, + struct cam_axi_vote *axi_vote); +int cam_cpas_node_tree_cleanup(struct cam_cpas *cpas_core, + struct cam_cpas_private_soc *soc_private); +int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t vfe_irq_handler, struct cam_hw_info *cpas_hw); +int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info); +int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info, + enum cam_vote_level default_level); +int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info, + bool disable_clocks, bool disable_irq); +int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info); +#endif /* _CAM_CPAS_SOC_H_ */ diff --git a/drivers/cam_cpas/camss_top/Makefile b/drivers/cam_cpas/camss_top/Makefile new file mode 100644 index 000000000000..902e74e20607 --- /dev/null +++ b/drivers/cam_cpas/camss_top/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_camsstop_hw.o diff --git a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c new file mode 100644 index 000000000000..b7f3550bc632 --- /dev/null +++ b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_cpas_hw_intf.h" +#include "cam_cpas_hw.h" +#include "cam_cpas_soc.h" + +int cam_camsstop_get_hw_info(struct cam_hw_info *cpas_hw, + struct cam_cpas_hw_caps *hw_caps) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CAMSS]; + uint32_t reg_value; + + if (reg_indx == -1) + return -EINVAL; + + hw_caps->camera_family = CAM_FAMILY_CAMERA_SS; + + reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x0); + hw_caps->camera_version.major = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c); + hw_caps->camera_version.minor = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->camera_version.incr = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + CAM_DBG(CAM_FD, "Family %d, version %d.%d.%d", + hw_caps->camera_family, hw_caps->camera_version.major, + hw_caps->camera_version.minor, hw_caps->camera_version.incr); + + return 0; +} + +int cam_camsstop_setup_regbase_indices(struct cam_hw_soc_info *soc_info, + int32_t regbase_index[], int32_t num_reg_map) +{ + uint32_t index; + int rc; + + if (num_reg_map > CAM_CPAS_REG_MAX) { + CAM_ERR(CAM_CPAS, "invalid num_reg_map=%d", num_reg_map); + return -EINVAL; + } + + if (soc_info->num_mem_block > CAM_SOC_MAX_BLOCK) { + CAM_ERR(CAM_CPAS, "invalid num_mem_block=%d", + soc_info->num_mem_block); + return -EINVAL; + } + + rc = cam_common_util_get_string_index(soc_info->mem_block_name, + soc_info->num_mem_block, "cam_camss", &index); + if ((rc == 0) && (index < num_reg_map)) { + regbase_index[CAM_CPAS_REG_CAMSS] = index; + } else { + CAM_ERR(CAM_CPAS, "regbase not found for CAM_CPAS_REG_CAMSS"); + return -EINVAL; + } + + return 0; +} + +int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) +{ + if (!internal_ops) { + CAM_ERR(CAM_CPAS, "invalid NULL param"); + return -EINVAL; + } + + internal_ops->get_hw_info = cam_camsstop_get_hw_info; + internal_ops->init_hw_version = NULL; + internal_ops->handle_irq = NULL; + internal_ops->setup_regbase = cam_camsstop_setup_regbase_indices; + internal_ops->power_on = NULL; + internal_ops->power_off = NULL; + + return 0; +} diff --git a/drivers/cam_cpas/cpas_top/Makefile b/drivers/cam_cpas/cpas_top/Makefile new file mode 100644 index 000000000000..2db4c393c65d --- /dev/null +++ b/drivers/cam_cpas/cpas_top/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpastop_hw.o diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c new file mode 100644 index 000000000000..57eb9de92be4 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -0,0 +1,635 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_cpas_hw_intf.h" +#include "cam_cpas_hw.h" +#include "cam_cpastop_hw.h" +#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" +#include "cpastop_v175_130.h" +#include "cpastop_v480_100.h" + +struct cam_camnoc_info *camnoc_info; + +#define CAMNOC_SLAVE_MAX_ERR_CODE 7 +static const char * const camnoc_salve_err_code[] = { + "Target Error", /* err code 0 */ + "Address decode error", /* err code 1 */ + "Unsupported request", /* err code 2 */ + "Disconnected target", /* err code 3 */ + "Security violation", /* err code 4 */ + "Hidden security violation", /* err code 5 */ + "Timeout Error", /* err code 6 */ + "Unknown Error", /* unknown err code */ +}; + +static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, + struct cam_cpas_hw_caps *hw_caps) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CPASTOP]; + uint32_t reg_value; + + if (reg_indx == -1) + return -EINVAL; + + hw_caps->camera_family = CAM_FAMILY_CPAS_SS; + + reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x0); + hw_caps->camera_version.major = + CAM_BITS_MASK_SHIFT(reg_value, 0xff0000, 0x10); + hw_caps->camera_version.minor = + CAM_BITS_MASK_SHIFT(reg_value, 0xff00, 0x8); + hw_caps->camera_version.incr = + CAM_BITS_MASK_SHIFT(reg_value, 0xff, 0x0); + + reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x4); + hw_caps->cpas_version.major = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c); + hw_caps->cpas_version.minor = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->cpas_version.incr = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x8); + hw_caps->camera_capability = reg_value; + + CAM_DBG(CAM_FD, "Family %d, version %d.%d.%d, cpas %d.%d.%d, cap 0x%x", + hw_caps->camera_family, hw_caps->camera_version.major, + hw_caps->camera_version.minor, hw_caps->camera_version.incr, + hw_caps->cpas_version.major, hw_caps->cpas_version.minor, + hw_caps->cpas_version.incr, hw_caps->camera_capability); + + soc_info->hw_version = CAM_CPAS_TITAN_NONE; + + if ((hw_caps->camera_version.major == 1) && + (hw_caps->camera_version.minor == 7) && + (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_170_V100; + else if ((hw_caps->cpas_version.major == 1) && + (hw_caps->cpas_version.minor == 1) && + (hw_caps->cpas_version.incr == 0)) + soc_info->hw_version = CAM_CPAS_TITAN_170_V110; + 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_170_V120; + } else if ((hw_caps->camera_version.major == 1) && + (hw_caps->camera_version.minor == 7) && + (hw_caps->camera_version.incr == 5)) { + 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_175_V100; + else if ((hw_caps->cpas_version.major == 1) && + (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->cpas_version.major == 1) && + (hw_caps->cpas_version.minor == 3) && + (hw_caps->cpas_version.incr == 0)) + soc_info->hw_version = CAM_CPAS_TITAN_175_V130; + } 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; + } else if ((hw_caps->camera_version.major == 4) && + (hw_caps->camera_version.minor == 8) && + (hw_caps->camera_version.incr == 0)) { + soc_info->hw_version = CAM_CPAS_TITAN_480_V100; + } + + CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); + + return 0; +} + +static int cam_cpastop_setup_regbase_indices(struct cam_hw_soc_info *soc_info, + int32_t regbase_index[], int32_t num_reg_map) +{ + uint32_t index; + int rc; + + if (num_reg_map > CAM_CPAS_REG_MAX) { + CAM_ERR(CAM_CPAS, "invalid num_reg_map=%d", num_reg_map); + return -EINVAL; + } + + if (soc_info->num_mem_block > CAM_SOC_MAX_BLOCK) { + CAM_ERR(CAM_CPAS, "invalid num_mem_block=%d", + soc_info->num_mem_block); + return -EINVAL; + } + + rc = cam_common_util_get_string_index(soc_info->mem_block_name, + soc_info->num_mem_block, "cam_cpas_top", &index); + if ((rc == 0) && (index < num_reg_map)) { + regbase_index[CAM_CPAS_REG_CPASTOP] = index; + } else { + CAM_ERR(CAM_CPAS, "regbase not found for CPASTOP, rc=%d, %d %d", + rc, index, num_reg_map); + return -EINVAL; + } + + rc = cam_common_util_get_string_index(soc_info->mem_block_name, + soc_info->num_mem_block, "cam_camnoc", &index); + if ((rc == 0) && (index < num_reg_map)) { + regbase_index[CAM_CPAS_REG_CAMNOC] = index; + } else { + CAM_ERR(CAM_CPAS, "regbase not found for CAMNOC, rc=%d, %d %d", + rc, index, num_reg_map); + return -EINVAL; + } + + return 0; +} + +static int cam_cpastop_handle_errlogger(struct cam_cpas *cpas_core, + struct cam_hw_soc_info *soc_info, + struct cam_camnoc_irq_slave_err_data *slave_err) +{ + int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; + int err_code_index = 0; + + if (!camnoc_info->err_logger) { + CAM_ERR_RATE_LIMIT(CAM_CPAS, "Invalid err logger info"); + return -EINVAL; + } + + slave_err->mainctrl.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->mainctrl); + + slave_err->errvld.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errvld); + + slave_err->errlog0_low.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog0_low); + + slave_err->errlog0_high.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog0_high); + + slave_err->errlog1_low.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog1_low); + + slave_err->errlog1_high.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog1_high); + + slave_err->errlog2_low.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog2_low); + + slave_err->errlog2_high.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog2_high); + + slave_err->errlog3_low.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog3_low); + + slave_err->errlog3_high.value = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->err_logger->errlog3_high); + + CAM_ERR_RATE_LIMIT(CAM_CPAS, + "Possible memory configuration issue, fault at SMMU raised as CAMNOC SLAVE_IRQ"); + + CAM_ERR_RATE_LIMIT(CAM_CPAS, + "mainctrl[0x%x 0x%x] errvld[0x%x 0x%x] stall_en=%d, fault_en=%d, err_vld=%d", + camnoc_info->err_logger->mainctrl, + slave_err->mainctrl.value, + camnoc_info->err_logger->errvld, + slave_err->errvld.value, + slave_err->mainctrl.stall_en, + slave_err->mainctrl.fault_en, + slave_err->errvld.err_vld); + + err_code_index = slave_err->errlog0_low.err_code; + if (err_code_index > CAMNOC_SLAVE_MAX_ERR_CODE) + err_code_index = CAMNOC_SLAVE_MAX_ERR_CODE; + + CAM_ERR_RATE_LIMIT(CAM_CPAS, + "errlog0 low[0x%x 0x%x] high[0x%x 0x%x] loginfo_vld=%d, word_error=%d, non_secure=%d, device=%d, opc=%d, err_code=%d(%s) sizef=%d, addr_space=%d, len1=%d", + camnoc_info->err_logger->errlog0_low, + slave_err->errlog0_low.value, + camnoc_info->err_logger->errlog0_high, + slave_err->errlog0_high.value, + slave_err->errlog0_low.loginfo_vld, + slave_err->errlog0_low.word_error, + slave_err->errlog0_low.non_secure, + slave_err->errlog0_low.device, + slave_err->errlog0_low.opc, + slave_err->errlog0_low.err_code, + camnoc_salve_err_code[err_code_index], + slave_err->errlog0_low.sizef, + slave_err->errlog0_low.addr_space, + slave_err->errlog0_high.len1); + + CAM_ERR_RATE_LIMIT(CAM_CPAS, + "errlog1_low[0x%x 0x%x] errlog1_high[0x%x 0x%x] errlog2_low[0x%x 0x%x] errlog2_high[0x%x 0x%x] errlog3_low[0x%x 0x%x] errlog3_high[0x%x 0x%x]", + camnoc_info->err_logger->errlog1_low, + slave_err->errlog1_low.value, + camnoc_info->err_logger->errlog1_high, + slave_err->errlog1_high.value, + camnoc_info->err_logger->errlog2_low, + slave_err->errlog2_low.value, + camnoc_info->err_logger->errlog2_high, + slave_err->errlog2_high.value, + camnoc_info->err_logger->errlog3_low, + slave_err->errlog3_low.value, + camnoc_info->err_logger->errlog3_high, + slave_err->errlog3_high.value); + + return 0; +} + +static int cam_cpastop_handle_ubwc_enc_err(struct cam_cpas *cpas_core, + struct cam_hw_soc_info *soc_info, int i, + struct cam_camnoc_irq_ubwc_enc_data *enc_err) +{ + int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; + + enc_err->encerr_status.value = + cam_io_r_mb(soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->irq_err[i].err_status.offset); + + /* Let clients handle the UBWC errors */ + CAM_DBG(CAM_CPAS, + "ubwc enc err [%d]: offset[0x%x] value[0x%x]", + i, camnoc_info->irq_err[i].err_status.offset, + enc_err->encerr_status.value); + + return 0; +} + +static int cam_cpastop_handle_ubwc_dec_err(struct cam_cpas *cpas_core, + struct cam_hw_soc_info *soc_info, int i, + struct cam_camnoc_irq_ubwc_dec_data *dec_err) +{ + int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; + + dec_err->decerr_status.value = + cam_io_r_mb(soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->irq_err[i].err_status.offset); + + /* Let clients handle the UBWC errors */ + CAM_DBG(CAM_CPAS, + "ubwc dec err status [%d]: offset[0x%x] value[0x%x] thr_err=%d, fcl_err=%d, len_md_err=%d, format_err=%d", + i, camnoc_info->irq_err[i].err_status.offset, + dec_err->decerr_status.value, + dec_err->decerr_status.thr_err, + dec_err->decerr_status.fcl_err, + dec_err->decerr_status.len_md_err, + dec_err->decerr_status.format_err); + + return 0; +} + +static int cam_cpastop_handle_ahb_timeout_err(struct cam_hw_info *cpas_hw, + struct cam_camnoc_irq_ahb_timeout_data *ahb_err) +{ + CAM_ERR_RATE_LIMIT(CAM_CPAS, "ahb timeout error"); + + return 0; +} + +static int cam_cpastop_disable_test_irq(struct cam_hw_info *cpas_hw) +{ + camnoc_info->irq_sbm->sbm_clear.value &= ~0x4; + camnoc_info->irq_sbm->sbm_enable.value &= ~0x100; + camnoc_info->irq_err[CAM_CAMNOC_HW_IRQ_CAMNOC_TEST].enable = false; + + return 0; +} + +static int cam_cpastop_reset_irq(struct cam_hw_info *cpas_hw) +{ + int i; + + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->irq_sbm->sbm_clear); + for (i = 0; i < camnoc_info->irq_err_size; i++) { + if (camnoc_info->irq_err[i].enable) + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->irq_err[i].err_clear); + } + + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->irq_sbm->sbm_enable); + for (i = 0; i < camnoc_info->irq_err_size; i++) { + if (camnoc_info->irq_err[i].enable) + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->irq_err[i].err_enable); + } + + return 0; +} + +static void cam_cpastop_notify_clients(struct cam_cpas *cpas_core, + struct cam_cpas_irq_data *irq_data) +{ + int i; + struct cam_cpas_client *cpas_client; + bool error_handled = false; + + CAM_DBG(CAM_CPAS, + "Notify CB : num_clients=%d, registered=%d, started=%d", + cpas_core->num_clients, cpas_core->registered_clients, + cpas_core->streamon_clients); + + for (i = 0; i < cpas_core->num_clients; i++) { + if (CAM_CPAS_CLIENT_STARTED(cpas_core, i)) { + cpas_client = cpas_core->cpas_client[i]; + if (cpas_client->data.cam_cpas_client_cb) { + CAM_DBG(CAM_CPAS, + "Calling client CB %d : %d", + i, irq_data->irq_type); + error_handled = + cpas_client->data.cam_cpas_client_cb( + cpas_client->data.client_handle, + cpas_client->data.userdata, + irq_data); + if (error_handled) + break; + } + } + } +} + +static void cam_cpastop_work(struct work_struct *work) +{ + struct cam_cpas_work_payload *payload; + struct cam_hw_info *cpas_hw; + struct cam_cpas *cpas_core; + struct cam_hw_soc_info *soc_info; + int i; + enum cam_camnoc_hw_irq_type irq_type; + struct cam_cpas_irq_data irq_data; + + payload = container_of(work, struct cam_cpas_work_payload, work); + if (!payload) { + CAM_ERR(CAM_CPAS, "NULL payload"); + return; + } + + cpas_hw = payload->hw; + cpas_core = (struct cam_cpas *) cpas_hw->core_info; + soc_info = &cpas_hw->soc_info; + + if (!atomic_inc_not_zero(&cpas_core->irq_count)) { + CAM_ERR(CAM_CPAS, "CPAS off"); + return; + } + + for (i = 0; i < camnoc_info->irq_err_size; i++) { + if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) && + (camnoc_info->irq_err[i].enable)) { + irq_type = camnoc_info->irq_err[i].irq_type; + CAM_ERR_RATE_LIMIT(CAM_CPAS, + "Error occurred, type=%d", irq_type); + memset(&irq_data, 0x0, sizeof(irq_data)); + irq_data.irq_type = (enum cam_camnoc_irq_type)irq_type; + + switch (irq_type) { + case CAM_CAMNOC_HW_IRQ_SLAVE_ERROR: + cam_cpastop_handle_errlogger( + cpas_core, soc_info, + &irq_data.u.slave_err); + break; + case CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR: + case CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR: + case CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: + cam_cpastop_handle_ubwc_enc_err( + cpas_core, soc_info, i, + &irq_data.u.enc_err); + break; + case CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR: + cam_cpastop_handle_ubwc_dec_err( + cpas_core, soc_info, i, + &irq_data.u.dec_err); + break; + case CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT: + cam_cpastop_handle_ahb_timeout_err( + cpas_hw, &irq_data.u.ahb_err); + break; + case CAM_CAMNOC_HW_IRQ_CAMNOC_TEST: + CAM_DBG(CAM_CPAS, "TEST IRQ"); + break; + default: + CAM_ERR(CAM_CPAS, "Invalid IRQ type"); + break; + } + + cam_cpastop_notify_clients(cpas_core, &irq_data); + + payload->irq_status &= + ~camnoc_info->irq_err[i].sbm_port; + } + } + atomic_dec(&cpas_core->irq_count); + wake_up(&cpas_core->irq_count_wq); + CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); + + if (payload->irq_status) + CAM_ERR(CAM_CPAS, "IRQ not handled irq_status=0x%x", + payload->irq_status); + + kfree(payload); +} + +static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data) +{ + struct cam_hw_info *cpas_hw = (struct cam_hw_info *)data; + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; + struct cam_cpas_work_payload *payload; + + if (!atomic_inc_not_zero(&cpas_core->irq_count)) { + CAM_ERR(CAM_CPAS, "CPAS off"); + return IRQ_HANDLED; + } + + payload = kzalloc(sizeof(struct cam_cpas_work_payload), GFP_ATOMIC); + if (!payload) + goto done; + + payload->irq_status = cam_io_r_mb( + soc_info->reg_map[camnoc_index].mem_base + + camnoc_info->irq_sbm->sbm_status.offset); + + CAM_DBG(CAM_CPAS, "IRQ callback, irq_status=0x%x", payload->irq_status); + + payload->hw = cpas_hw; + INIT_WORK((struct work_struct *)&payload->work, cam_cpastop_work); + + if (TEST_IRQ_ENABLE) + cam_cpastop_disable_test_irq(cpas_hw); + + cam_cpastop_reset_irq(cpas_hw); + + queue_work(cpas_core->work_queue, &payload->work); +done: + atomic_dec(&cpas_core->irq_count); + wake_up(&cpas_core->irq_count_wq); + + return IRQ_HANDLED; +} + +static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) +{ + int i; + + for (i = 0; i < camnoc_info->specific_size; i++) { + if (camnoc_info->specific[i].enable) { + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].priority_lut_low); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].priority_lut_high); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].urgency); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].danger_lut); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].safe_lut); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].ubwc_ctl); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].flag_out_set0_low); + } + } + + return 0; +} + +static int cam_cpastop_poweroff(struct cam_hw_info *cpas_hw) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; + int rc = 0; + struct cam_cpas_hw_errata_wa_list *errata_wa_list = + camnoc_info->errata_wa_list; + + if (!errata_wa_list) + return 0; + + if (errata_wa_list->camnoc_flush_slave_pending_trans.enable) { + struct cam_cpas_hw_errata_wa *errata_wa = + &errata_wa_list->camnoc_flush_slave_pending_trans; + + rc = cam_io_poll_value_wmask( + soc_info->reg_map[camnoc_index].mem_base + + errata_wa->data.reg_info.offset, + errata_wa->data.reg_info.value, + errata_wa->data.reg_info.mask, + CAM_CPAS_POLL_RETRY_CNT, + CAM_CPAS_POLL_MIN_USECS, CAM_CPAS_POLL_MAX_USECS); + if (rc) { + CAM_DBG(CAM_CPAS, + "camnoc flush slave pending trans failed"); + /* Do not return error, passthrough */ + rc = 0; + } + } + + return rc; +} + +static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, + struct cam_cpas_hw_caps *hw_caps) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + + CAM_DBG(CAM_CPAS, + "hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d", + soc_info->hw_version, + hw_caps->camera_version.major, + hw_caps->camera_version.minor, + hw_caps->camera_version.incr, + hw_caps->cpas_version.major, + hw_caps->cpas_version.minor, + hw_caps->cpas_version.incr); + + switch (soc_info->hw_version) { + case CAM_CPAS_TITAN_170_V100: + camnoc_info = &cam170_cpas100_camnoc_info; + break; + case CAM_CPAS_TITAN_170_V110: + camnoc_info = &cam170_cpas110_camnoc_info; + break; + case CAM_CPAS_TITAN_175_V100: + camnoc_info = &cam175_cpas100_camnoc_info; + break; + 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_175_V130: + camnoc_info = &cam175_cpas130_camnoc_info; + break; + case CAM_CPAS_TITAN_150_V100: + camnoc_info = &cam150_cpas100_camnoc_info; + break; + case CAM_CPAS_TITAN_480_V100: + camnoc_info = &cam480_cpas100_camnoc_info; + break; + default: + CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", + hw_caps->camera_version.major, + hw_caps->camera_version.minor, + hw_caps->camera_version.incr); + rc = -EINVAL; + break; + } + + return 0; +} + +int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) +{ + if (!internal_ops) { + CAM_ERR(CAM_CPAS, "invalid NULL param"); + return -EINVAL; + } + + internal_ops->get_hw_info = cam_cpastop_get_hw_info; + internal_ops->init_hw_version = cam_cpastop_init_hw_version; + internal_ops->handle_irq = cam_cpastop_handle_irq; + internal_ops->setup_regbase = cam_cpastop_setup_regbase_indices; + internal_ops->power_on = cam_cpastop_poweron; + internal_ops->power_off = cam_cpastop_poweroff; + + return 0; +} diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h new file mode 100644 index 000000000000..8a8c61a21914 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CPASTOP_HW_H_ +#define _CAM_CPASTOP_HW_H_ + +#include "cam_cpas_api.h" +#include "cam_cpas_hw.h" + +/** + * enum cam_camnoc_hw_irq_type - Enum for camnoc error types + * + * @CAM_CAMNOC_HW_IRQ_SLAVE_ERROR: Each slave port in CAMNOC (3 QSB ports and + * 1 QHB port) has an error logger. The error + * observed at any slave port is logged into + * the error logger register and an IRQ is + * triggered + * @CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IFE0 UBWC + * encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IFE1 or IFE3 + * UBWC encoder instance + * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR: Triggered if any error + * detected in the IPE/BPS + * UBWC decoder instance + * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: Triggered if any error + * detected in the IPE/BPS UBWC + * encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE0_UBWC_ENCODE_ERROR: Triggered if any UBWC error + * is detected in IFE0 write path + * @CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR: Triggered if any UBWC error + * is detected in IFE1 write path + * @CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT : Triggered when the QHS_ICP + * slave times out after 4000 + * AHB cycles + * @CAM_CAMNOC_HW_IRQ_RESERVED1 : Reserved + * @CAM_CAMNOC_HW_IRQ_RESERVED2 : Reserved + * @CAM_CAMNOC_HW_IRQ_CAMNOC_TEST : To test the IRQ logic + */ +enum cam_camnoc_hw_irq_type { + CAM_CAMNOC_HW_IRQ_SLAVE_ERROR = + CAM_CAMNOC_IRQ_SLAVE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE0_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR = + CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR, + CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT = + CAM_CAMNOC_IRQ_AHB_TIMEOUT, + CAM_CAMNOC_HW_IRQ_RESERVED1, + CAM_CAMNOC_HW_IRQ_RESERVED2, + CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, +}; + +/** + * enum cam_camnoc_port_type - Enum for different camnoc hw ports. All CAMNOC + * settings like QoS, LUT mappings need to be configured for + * each of these ports. + * + * @CAM_CAMNOC_CDM: Indicates CDM HW connection to camnoc + * @CAM_CAMNOC_IFE02: Indicates IFE0, IFE2 HW connection to camnoc + * @CAM_CAMNOC_IFE13: Indicates IFE1, IFE3 HW connection to camnoc + * @CAM_CAMNOC_IFE_LINEAR: Indicates linear data from all IFEs to cammnoc + * @CAM_CAMNOC_IFE_UBWC_STATS: Indicates ubwc+stats from all IFEs to cammnoc + * @CAM_CAMNOC_IFE_RDI_WR: Indicates RDI write data from all IFEs to cammnoc + * @CAM_CAMNOC_IFE_RDI_RD: Indicates RDI read data from all IFEs to cammnoc + * @CAM_CAMNOC_IFE0123_RDI_WRITE: RDI write only for all IFEx + * @CAM_CAMNOC_IFE0_NRDI_WRITE: IFE0 non-RDI write + * @CAM_CAMNOC_IFE01_RDI_READ: IFE0/1 RDI READ + * @CAM_CAMNOC_IFE1_NRDI_WRITE: IFE1 non-RDI write + * @CAM_CAMNOC_IPE_BPS_LRME_READ: Indicates IPE, BPS, LRME Read HW + * connection to camnoc + * @CAM_CAMNOC_IPE_BPS_LRME_WRITE: Indicates IPE, BPS, LRME Write HW + * connection to camnoc + * @CAM_CAMNOC_IPE_VID_DISP_WRITE: Indicates IPE's VID/DISP Wrire HW + * connection to camnoc + * @CAM_CAMNOC_IPE0_RD: Indicates IPE's Read0 HW connection to camnoc + * @CAM_CAMNOC_IPE1_BPS_RD: Indicates IPE's Read1 + BPS Read HW connection + * to camnoc + * @CAM_CAMNOC_IPE_BPS_WR: Indicates IPE+BPS Write HW connection to camnoc + * @CAM_CAMNOC_JPEG: Indicates JPEG HW connection to camnoc + * @CAM_CAMNOC_FD: Indicates FD HW connection to camnoc + * @CAM_CAMNOC_ICP: Indicates ICP HW connection to camnoc + */ +enum cam_camnoc_port_type { + CAM_CAMNOC_CDM, + CAM_CAMNOC_IFE02, + CAM_CAMNOC_IFE13, + CAM_CAMNOC_IFE_LINEAR, + CAM_CAMNOC_IFE_UBWC_STATS, + CAM_CAMNOC_IFE_RDI_WR, + CAM_CAMNOC_IFE_RDI_RD, + CAM_CAMNOC_IFE0123_RDI_WRITE, + CAM_CAMNOC_IFE0_NRDI_WRITE, + CAM_CAMNOC_IFE01_RDI_READ, + CAM_CAMNOC_IFE1_NRDI_WRITE, + CAM_CAMNOC_IPE_BPS_LRME_READ, + CAM_CAMNOC_IPE_BPS_LRME_WRITE, + CAM_CAMNOC_IPE_VID_DISP_WRITE, + CAM_CAMNOC_IPE0_RD, + CAM_CAMNOC_IPE1_BPS_RD, + CAM_CAMNOC_IPE_BPS_WR, + CAM_CAMNOC_JPEG, + CAM_CAMNOC_FD, + CAM_CAMNOC_ICP, +}; + +/** + * struct cam_camnoc_specific : CPAS camnoc specific settings + * + * @port_type: Port type + * @enable: Whether to enable settings for this connection + * @priority_lut_low: Priority Low LUT mapping for this connection + * @priority_lut_high: Priority High LUT mapping for this connection + * @urgency: Urgency (QoS) settings for this connection + * @danger_lut: Danger LUT mapping for this connection + * @safe_lut: Safe LUT mapping for this connection + * @ubwc_ctl: UBWC control settings for this connection + * + */ +struct cam_camnoc_specific { + enum cam_camnoc_port_type port_type; + bool enable; + struct cam_cpas_reg priority_lut_low; + struct cam_cpas_reg priority_lut_high; + struct cam_cpas_reg urgency; + struct cam_cpas_reg danger_lut; + struct cam_cpas_reg safe_lut; + struct cam_cpas_reg ubwc_ctl; + struct cam_cpas_reg flag_out_set0_low; +}; + +/** + * struct cam_camnoc_irq_sbm : Sideband manager settings for all CAMNOC IRQs + * + * @sbm_enable: SBM settings for IRQ enable + * @sbm_status: SBM settings for IRQ status + * @sbm_clear: SBM settings for IRQ clear + * + */ +struct cam_camnoc_irq_sbm { + struct cam_cpas_reg sbm_enable; + struct cam_cpas_reg sbm_status; + struct cam_cpas_reg sbm_clear; +}; + +/** + * struct cam_camnoc_irq_err : Error settings specific to each CAMNOC IRQ + * + * @irq_type: Type of IRQ + * @enable: Whether to enable error settings for this IRQ + * @sbm_port: Corresponding SBM port for this IRQ + * @err_enable: Error enable settings for this IRQ + * @err_status: Error status settings for this IRQ + * @err_clear: Error clear settings for this IRQ + * + */ +struct cam_camnoc_irq_err { + enum cam_camnoc_hw_irq_type irq_type; + bool enable; + uint32_t sbm_port; + struct cam_cpas_reg err_enable; + struct cam_cpas_reg err_status; + struct cam_cpas_reg err_clear; +}; + +/** + * struct cam_cpas_hw_errata_wa : Struct for HW errata workaround info + * + * @enable: Whether to enable this errata workround + * @data: HW Errata workaround data + * + */ +struct cam_cpas_hw_errata_wa { + bool enable; + union { + struct cam_cpas_reg reg_info; + } data; +}; + +/** + * struct cam_cpas_hw_errata_wa_list : List of HW Errata workaround info + * + * @camnoc_flush_slave_pending_trans: Errata workaround info for flushing + * camnoc slave pending transactions before turning off CPAS_TOP gdsc + * + */ +struct cam_cpas_hw_errata_wa_list { + struct cam_cpas_hw_errata_wa camnoc_flush_slave_pending_trans; +}; + +/** + * struct cam_camnoc_err_logger_info : CAMNOC error logger register offsets + * + * @mainctrl: Register offset for mainctrl + * @errvld: Register offset for errvld + * @errlog0_low: Register offset for errlog0_low + * @errlog0_high: Register offset for errlog0_high + * @errlog1_low: Register offset for errlog1_low + * @errlog1_high: Register offset for errlog1_high + * @errlog2_low: Register offset for errlog2_low + * @errlog2_high: Register offset for errlog2_high + * @errlog3_low: Register offset for errlog3_low + * @errlog3_high: Register offset for errlog3_high + * + */ +struct cam_camnoc_err_logger_info { + uint32_t mainctrl; + uint32_t errvld; + uint32_t errlog0_low; + uint32_t errlog0_high; + uint32_t errlog1_low; + uint32_t errlog1_high; + uint32_t errlog2_low; + uint32_t errlog2_high; + uint32_t errlog3_low; + uint32_t errlog3_high; +}; + +/** + * struct cam_camnoc_info : Overall CAMNOC settings info + * + * @specific: Pointer to CAMNOC SPECIFICTONTTPTR settings + * @specific_size: Array size of SPECIFICTONTTPTR settings + * @irq_sbm: Pointer to CAMNOC IRQ SBM settings + * @irq_err: Pointer to CAMNOC IRQ Error settings + * @irq_err_size: Array size of IRQ Error settings + * @err_logger: Pointer to CAMNOC IRQ Error logger read registers + * @errata_wa_list: HW Errata workaround info + * + */ +struct cam_camnoc_info { + struct cam_camnoc_specific *specific; + int specific_size; + struct cam_camnoc_irq_sbm *irq_sbm; + struct cam_camnoc_irq_err *irq_err; + int irq_err_size; + struct cam_camnoc_err_logger_info *err_logger; + struct cam_cpas_hw_errata_wa_list *errata_wa_list; +}; + +/** + * struct cam_cpas_work_payload : Struct for cpas work payload data + * + * @hw: Pointer to HW info + * @irq_status: IRQ status value + * @irq_data: IRQ data + * @work: Work handle + * + */ +struct cam_cpas_work_payload { + struct cam_hw_info *hw; + uint32_t irq_status; + uint32_t irq_data; + struct work_struct work; +}; + +#endif /* _CAM_CPASTOP_HW_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop100.h b/drivers/cam_cpas/cpas_top/cpastop100.h new file mode 100644 index 000000000000..2f444710e9f4 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop100.h @@ -0,0 +1,531 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP100_H_ +#define _CPASTOP100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas100_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_cpas100_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_cpas100_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 = 0, + }, + .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 = 0x3, + }, + .ubwc_ctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .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 = 0x3, + }, + .ubwc_ctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x988, /* SPECIFIC_IFE13_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 = 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 = true, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1188, /* 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 = 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 = false, + } +}; + +static struct cam_camnoc_err_logger_info cam170_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 cam170_cpas100_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = true, + .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 */ + }, + }, +}; + +struct cam_camnoc_info cam170_cpas100_camnoc_info = { + .specific = &cam_cpas100_camnoc_specific[0], + .specific_size = sizeof(cam_cpas100_camnoc_specific) / + sizeof(cam_cpas100_camnoc_specific[0]), + .irq_sbm = &cam_cpas100_irq_sbm, + .irq_err = &cam_cpas100_irq_err[0], + .irq_err_size = sizeof(cam_cpas100_irq_err) / + sizeof(cam_cpas100_irq_err[0]), + .err_logger = &cam170_cpas100_err_logger_offsets, + .errata_wa_list = &cam170_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v150_100.h b/drivers/cam_cpas/cpas_top/cpastop_v150_100.h new file mode 100644 index 000000000000..df9711e74379 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v150_100.h @@ -0,0 +1,530 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#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/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/cam_cpas/cpas_top/cpastop_v170_110.h new file mode 100644 index 000000000000..788f571a3a13 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v170_110.h @@ -0,0 +1,538 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V170_110_H_ +#define _CPASTOP_V170_110_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas110_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_cpas110_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_cpas110_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 = 0x66666543, + }, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .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 = 0x66666543, + }, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x988, /* SPECIFIC_IFE13_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 = 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 = true, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1188, /* 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 = 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 cam170_cpas110_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 cam170_cpas110_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 cam170_cpas110_camnoc_info = { + .specific = &cam_cpas110_camnoc_specific[0], + .specific_size = sizeof(cam_cpas110_camnoc_specific) / + sizeof(cam_cpas110_camnoc_specific[0]), + .irq_sbm = &cam_cpas110_irq_sbm, + .irq_err = &cam_cpas110_irq_err[0], + .irq_err_size = sizeof(cam_cpas110_irq_err) / + sizeof(cam_cpas110_irq_err[0]), + .err_logger = &cam170_cpas110_err_logger_offsets, + .errata_wa_list = &cam170_cpas110_errata_wa_list, +}; + +#endif /* _CPASTOP_V170_110_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_100.h b/drivers/cam_cpas/cpas_top/cpastop_v175_100.h new file mode 100644 index 000000000000..aae26b5a9178 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_100.h @@ -0,0 +1,558 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V175_100_H_ +#define _CPASTOP_V175_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v175_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_v175_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_v175_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 = 0x66666543, + }, + .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 = { + /* + * 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 = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .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 = 0x66666543, + }, + .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 = { + /* + * 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 = 0x988, /* SPECIFIC_IFE13_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 = 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 = { + /* + * 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 = 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 = { + /* + * 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 = 0x1188, /* 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 = 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 cam175_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 cam175_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 cam175_cpas100_camnoc_info = { + .specific = &cam_cpas_v175_100_camnoc_specific[0], + .specific_size = sizeof(cam_cpas_v175_100_camnoc_specific) / + sizeof(cam_cpas_v175_100_camnoc_specific[0]), + .irq_sbm = &cam_cpas_v175_100_irq_sbm, + .irq_err = &cam_cpas_v175_100_irq_err[0], + .irq_err_size = sizeof(cam_cpas_v175_100_irq_err) / + sizeof(cam_cpas_v175_100_irq_err[0]), + .err_logger = &cam175_cpas100_err_logger_offsets, + .errata_wa_list = &cam175_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP_V175_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_101.h b/drivers/cam_cpas/cpas_top/cpastop_v175_101.h new file mode 100644 index 000000000000..7ec9bec36fd1 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_101.h @@ -0,0 +1,558 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V175_101_H_ +#define _CPASTOP_V175_101_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v175_101_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_v175_101_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_v175_101_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 = 0x66666543, + }, + .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 = { + /* + * 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 = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .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 = 0x66666543, + }, + .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 = { + /* + * 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 = 0x988, /* SPECIFIC_IFE13_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 = 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 = { + /* + * 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 = 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 = { + /* + * 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 = 0x1188, /* 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 = 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 cam175_cpas101_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 cam175_cpas101_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 cam175_cpas101_camnoc_info = { + .specific = &cam_cpas_v175_101_camnoc_specific[0], + .specific_size = sizeof(cam_cpas_v175_101_camnoc_specific) / + sizeof(cam_cpas_v175_101_camnoc_specific[0]), + .irq_sbm = &cam_cpas_v175_101_irq_sbm, + .irq_err = &cam_cpas_v175_101_irq_err[0], + .irq_err_size = sizeof(cam_cpas_v175_101_irq_err) / + sizeof(cam_cpas_v175_101_irq_err[0]), + .err_logger = &cam175_cpas101_err_logger_offsets, + .errata_wa_list = &cam175_cpas101_errata_wa_list, +}; + +#endif /* _CPASTOP_V175_101_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_120.h b/drivers/cam_cpas/cpas_top/cpastop_v175_120.h new file mode 100644 index 000000000000..5844c38ae52c --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_120.h @@ -0,0 +1,760 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#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 = ARRAY_SIZE(cam_cpas_v175_120_camnoc_specific), + .irq_sbm = &cam_cpas_v175_120_irq_sbm, + .irq_err = &cam_cpas_v175_120_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v175_120_irq_err), + .err_logger = &cam175_cpas120_err_logger_offsets, + .errata_wa_list = &cam175_cpas120_errata_wa_list, +}; + +#endif /* _CPASTOP_V175_120_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h new file mode 100644 index 000000000000..fe6e274c5668 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h @@ -0,0 +1,760 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V175_130_H_ +#define _CPASTOP_V175_130_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v175_130_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_130_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_130_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 = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3234, /* SPECIFIC_IFE1_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .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_cpas130_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_cpas130_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_cpas130_camnoc_info = { + .specific = &cam_cpas_v175_130_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v175_130_camnoc_specific), + .irq_sbm = &cam_cpas_v175_130_irq_sbm, + .irq_err = &cam_cpas_v175_130_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v175_130_irq_err), + .err_logger = &cam175_cpas130_err_logger_offsets, + .errata_wa_list = &cam175_cpas130_errata_wa_list, +}; + +#endif /* _CPASTOP_V175_130_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h new file mode 100644 index 000000000000..d4782d7df110 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -0,0 +1,743 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V480_100_H_ +#define _CPASTOP_V480_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v480_100_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = false, + .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_v480_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, /* IFE02_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x590, /* IFE02_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x598, /* 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, /* IFE13_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x990, /* IFE13_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x998, /* 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, /* IBL_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xd10, /* IBL_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xd18, /* 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, /* IBL_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1190, + /* IBL_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1198, /* 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_v480_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, /* CDM_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x38, /* CDM_URGENCY_LOW */ + .mask = 0x7, /* CDM_URGENCY_LOW_READ_MASK */ + .shift = 0x0, /* CDM_URGENCY_LOW_READ_SHIFT */ + .value = 0x2, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* CDM_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 = 0x630, /* FD_PRIORITYLUT_LOW */ + .value = 0x44444444, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x634, /* FD_PRIORITYLUT_HIGH */ + .value = 0x44444444, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x638, /* FD_URGENCY_LOW */ + .value = 0x2, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x640, /* FD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x648, /* FD_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ + /* IFE_LINEAR_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* IFE_LINEAR_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ + .value = 0x1, + }, + .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_IFE_RDI_RD, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ + /* IFE_RDI_RD_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* IFE_RDI_RD_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ + .value = 0x1, + }, + .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_IFE_RDI_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* IFE_RDI_WR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* IFE_RDI_WR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x1438, /* IFE_RDI_WR_URGENCY_LOW */ + /* IFE_RDI_WR_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* IFE_RDI_WR_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1440, /* IFE_RDI_WR_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1448, /* IFE_RDI_WR_SAFELUT_LOW */ + .value = 0x1, + }, + .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_IFE_UBWC_STATS, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A30, /* IFE_UBWC_STATS_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A34, /* IFE_UBWC_STATS_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x1A38, /* IFE_UBWC_STATS_URGENCY_LOW */ + /* IFE_UBWC_STATS_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* IFE_UBWC_STATS_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A40, /* IFE_UBWC_STATS_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A48, /* IFE_UBWC_STATS_SAFELUT_LOW */ + .value = 0x1, + }, + .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 = 0x1B88, /* IFE_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE0_RD, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ + /* IPE0_RD_URGENCY_LOW_READ_MASK */ + .mask = 0x7, + /* IPE0_RD_URGENCY_LOW_READ_SHIFT */ + .shift = 0x0, + .value = 3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E48, /* IPE0_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 = 0x1F08, /* IPE0_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE1_BPS_RD, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ + /* IPE1_BPS_RD_URGENCY_LOW_READ_MASK */ + .mask = 0x7, + /* IPE1_BPS_RD_URGENCY_LOW_READ_SHIFT */ + .shift = 0x0, + .value = 3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2448, /* IPE1_BPS_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 = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ + /* IPE_BPS_WR_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* IPE_BPS_WR_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2848, /* IPE_BPS_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 = 0x2988, /* IPE_BPS_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 = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E38, /* JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .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 cam480_cpas100_err_logger_offsets = { + .mainctrl = 0x7008, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x7010, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x7020, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x7024, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x7028, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x702c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x7030, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x7034, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x7038, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x703c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam480_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 cam480_cpas100_camnoc_info = { + .specific = &cam_cpas_v480_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v480_100_camnoc_specific), + .irq_sbm = &cam_cpas_v480_100_irq_sbm, + .irq_err = &cam_cpas_v480_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v480_100_irq_err), + .err_logger = &cam480_cpas100_err_logger_offsets, + .errata_wa_list = &cam480_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP_V480_100_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h new file mode 100644 index 000000000000..932f4b2abf88 --- /dev/null +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -0,0 +1,543 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CPAS_API_H_ +#define _CAM_CPAS_API_H_ + +#include +#include + +#include +#include "cam_soc_util.h" + +#define CAM_HW_IDENTIFIER_LENGTH 128 + +/* Default AXI Bandwidth vote */ +#define CAM_CPAS_DEFAULT_AXI_BW 1024 + +#define CAM_CPAS_MAX_PATHS_PER_CLIENT 15 +#define CAM_CPAS_API_PATH_DATA_STD_START 512 + +/** + * enum cam_cpas_reg_base - Enum for register base identifier. These + * are the identifiers used in generic register + * write/read APIs provided by cpas driver. + */ +enum cam_cpas_reg_base { + CAM_CPAS_REG_CPASTOP, + CAM_CPAS_REG_CAMNOC, + CAM_CPAS_REG_CAMSS, + CAM_CPAS_REG_MAX +}; + +/** + * enum cam_cpas_hw_version - Enum for Titan CPAS HW Versions + */ +enum cam_cpas_hw_version { + CAM_CPAS_TITAN_NONE = 0, + CAM_CPAS_TITAN_150_V100 = 0x150100, + CAM_CPAS_TITAN_170_V100 = 0x170100, + CAM_CPAS_TITAN_170_V110 = 0x170110, + CAM_CPAS_TITAN_170_V120 = 0x170120, + CAM_CPAS_TITAN_175_V100 = 0x175100, + CAM_CPAS_TITAN_175_V101 = 0x175101, + CAM_CPAS_TITAN_175_V120 = 0x175120, + CAM_CPAS_TITAN_175_V130 = 0x175130, + CAM_CPAS_TITAN_480_V100 = 0x480100, + CAM_CPAS_TITAN_MAX +}; + +/** + * enum cam_camnoc_irq_type - Enum for camnoc irq types + * + * @CAM_CAMNOC_IRQ_SLAVE_ERROR: Each slave port in CAMNOC (3 QSB ports and + * 1 QHB port) has an error logger. The error + * observed at any slave port is logged into + * the error logger register and an IRQ is + * triggered + * @CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the IFE0 UBWC encoder instance + * @CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the IFE1 or IFE3 UBWC encoder + * instance + * @CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the IFE0 UBWC encoder instance + * @CAM_CAMNOC_IRQ_IFE1_WR_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the IFE1 UBWC encoder + * instance + * @CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR: Triggered if any error detected + * in the IPE/BPS UBWC decoder + * instance + * @CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: Triggered if any error detected + * in the IPE/BPS UBWC encoder + * instance + * @CAM_CAMNOC_IRQ_AHB_TIMEOUT : Triggered when the QHS_ICP slave + * times out after 4000 AHB cycles + */ +enum cam_camnoc_irq_type { + CAM_CAMNOC_IRQ_SLAVE_ERROR, + CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR, + CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_AHB_TIMEOUT, +}; + +/** + * struct cam_camnoc_irq_slave_err_data : Data for Slave error. + * + * @mainctrl : Err logger mainctrl info + * @errvld : Err logger errvld info + * @errlog0_low : Err logger errlog0_low info + * @errlog0_high : Err logger errlog0_high info + * @errlog1_low : Err logger errlog1_low info + * @errlog1_high : Err logger errlog1_high info + * @errlog2_low : Err logger errlog2_low info + * @errlog2_high : Err logger errlog2_high info + * @errlog3_low : Err logger errlog3_low info + * @errlog3_high : Err logger errlog3_high info + * + */ +struct cam_camnoc_irq_slave_err_data { + union { + struct { + uint32_t stall_en : 1; /* bit 0 */ + uint32_t fault_en : 1; /* bit 1 */ + uint32_t rsv : 30; /* bits 2-31 */ + }; + uint32_t value; + } mainctrl; + union { + struct { + uint32_t err_vld : 1; /* bit 0 */ + uint32_t rsv : 31; /* bits 1-31 */ + }; + uint32_t value; + } errvld; + union { + struct { + uint32_t loginfo_vld : 1; /* bit 0 */ + uint32_t word_error : 1; /* bit 1 */ + uint32_t non_secure : 1; /* bit 2 */ + uint32_t device : 1; /* bit 3 */ + uint32_t opc : 3; /* bits 4 - 6 */ + uint32_t rsv0 : 1; /* bit 7 */ + uint32_t err_code : 3; /* bits 8 - 10 */ + uint32_t sizef : 3; /* bits 11 - 13 */ + uint32_t rsv1 : 2; /* bits 14 - 15 */ + uint32_t addr_space : 6; /* bits 16 - 21 */ + uint32_t rsv2 : 10; /* bits 22 - 31 */ + }; + uint32_t value; + } errlog0_low; + union { + struct { + uint32_t len1 : 10; /* bits 0 - 9 */ + uint32_t rsv : 22; /* bits 10 - 31 */ + }; + uint32_t value; + } errlog0_high; + union { + struct { + uint32_t path : 16; /* bits 0 - 15 */ + uint32_t rsv : 16; /* bits 16 - 31 */ + }; + uint32_t value; + } errlog1_low; + union { + struct { + uint32_t extid : 18; /* bits 0 - 17 */ + uint32_t rsv : 14; /* bits 18 - 31 */ + }; + uint32_t value; + } errlog1_high; + union { + struct { + uint32_t errlog2_lsb : 32; /* bits 0 - 31 */ + }; + uint32_t value; + } errlog2_low; + union { + struct { + uint32_t errlog2_msb : 16; /* bits 0 - 16 */ + uint32_t rsv : 16; /* bits 16 - 31 */ + }; + uint32_t value; + } errlog2_high; + union { + struct { + uint32_t errlog3_lsb : 32; /* bits 0 - 31 */ + }; + uint32_t value; + } errlog3_low; + union { + struct { + uint32_t errlog3_msb : 32; /* bits 0 - 31 */ + }; + uint32_t value; + } errlog3_high; +}; + +/** + * struct cam_camnoc_irq_ubwc_enc_data : Data for UBWC Encode error. + * + * @encerr_status : Encode error status + * + */ +struct cam_camnoc_irq_ubwc_enc_data { + union { + struct { + uint32_t encerrstatus : 3; /* bits 0 - 2 */ + uint32_t rsv : 29; /* bits 3 - 31 */ + }; + uint32_t value; + } encerr_status; +}; + +/** + * struct cam_camnoc_irq_ubwc_dec_data : Data for UBWC Decode error. + * + * @decerr_status : Decoder error status + * @thr_err : Set to 1 if + * At least one of the bflc_len fields in the bit steam exceeds + * its threshold value. This error is possible only for + * RGBA1010102, TP10, and RGB565 formats + * @fcl_err : Set to 1 if + * Fast clear with a legal non-RGB format + * @len_md_err : Set to 1 if + * The calculated burst length does not match burst length + * specified by the metadata value + * @format_err : Set to 1 if + * Illegal format + * 1. bad format :2,3,6 + * 2. For 32B MAL, metadata=6 + * 3. For 32B MAL RGB565, Metadata != 0,1,7 + * 4. For 64B MAL RGB565, metadata[3:1] == 1,2 + * + */ +struct cam_camnoc_irq_ubwc_dec_data { + union { + struct { + uint32_t thr_err : 1; /* bit 0 */ + uint32_t fcl_err : 1; /* bit 1 */ + uint32_t len_md_err : 1; /* bit 2 */ + uint32_t format_err : 1; /* bit 3 */ + uint32_t rsv : 28; /* bits 4 - 31 */ + }; + uint32_t value; + } decerr_status; +}; + +struct cam_camnoc_irq_ahb_timeout_data { + uint32_t data; +}; + +/** + * struct cam_cpas_irq_data : CAMNOC IRQ data + * + * @irq_type : To identify the type of IRQ + * @u : Union of irq err data information + * @slave_err : Data for Slave error. + * Valid if type is CAM_CAMNOC_IRQ_SLAVE_ERROR + * @enc_err : Data for UBWC Encode error. + * Valid if type is one of below: + * CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR + * CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR + * CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR + * @dec_err : Data for UBWC Decode error. + * Valid if type is CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR + * @ahb_err : Data for Slave error. + * Valid if type is CAM_CAMNOC_IRQ_AHB_TIMEOUT + * + */ +struct cam_cpas_irq_data { + enum cam_camnoc_irq_type irq_type; + union { + struct cam_camnoc_irq_slave_err_data slave_err; + struct cam_camnoc_irq_ubwc_enc_data enc_err; + struct cam_camnoc_irq_ubwc_dec_data dec_err; + struct cam_camnoc_irq_ahb_timeout_data ahb_err; + } u; +}; + +/** + * struct cam_cpas_register_params : Register params for cpas client + * + * @identifier : Input identifier string which is the device label + * from dt like vfe, ife, jpeg etc + * @cell_index : Input integer identifier pointing to the cell index + * from dt of the device. This can be used to form a + * unique string with @identifier like vfe0, ife1, + * jpeg0, etc + * @dev : device handle + * @userdata : Input private data which will be passed as + * an argument while callback. + * @cam_cpas_callback : Input callback pointer for triggering the + * callbacks from CPAS driver. + * @client_handle : CPAS client handle + * @userdata : User data given at the time of register + * @event_type : event type + * @event_data : event data + * @client_handle : Output Unique handle generated for this register + * + */ +struct cam_cpas_register_params { + char identifier[CAM_HW_IDENTIFIER_LENGTH]; + uint32_t cell_index; + struct device *dev; + void *userdata; + bool (*cam_cpas_client_cb)( + uint32_t client_handle, + void *userdata, + struct cam_cpas_irq_data *irq_data); + uint32_t client_handle; +}; + +/** + * enum cam_vote_type - Enum for voting type + * + * @CAM_VOTE_ABSOLUTE : Absolute vote + * @CAM_VOTE_DYNAMIC : Dynamic vote + */ +enum cam_vote_type { + CAM_VOTE_ABSOLUTE, + CAM_VOTE_DYNAMIC, +}; + +/** + * struct cam_ahb_vote : AHB vote + * + * @type : AHB voting type. + * CAM_VOTE_ABSOLUTE : vote based on the value 'level' is set + * CAM_VOTE_DYNAMIC : vote calculated dynamically using 'freq' + * and 'dev' handle is set + * @level : AHB vote level + * @freq : AHB vote dynamic frequency + * + */ +struct cam_ahb_vote { + enum cam_vote_type type; + union { + enum cam_vote_level level; + unsigned long freq; + } vote; +}; + +/** + * struct cam_axi_vote : AXI vote + * + * @num_paths: Number of paths on which BW vote is sent to CPAS + * @axi_path: Per path BW vote info + * + */ +struct cam_axi_vote { + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_CPAS_MAX_PATHS_PER_CLIENT]; +}; + +/** + * cam_cpas_register_client() + * + * @brief: API to register cpas client + * + * @register_params: Input params to register as a client to CPAS + * + * @return 0 on success. + * + */ +int cam_cpas_register_client( + struct cam_cpas_register_params *register_params); + +/** + * cam_cpas_unregister_client() + * + * @brief: API to unregister cpas client + * + * @client_handle: Client handle to be unregistered + * + * @return 0 on success. + * + */ +int cam_cpas_unregister_client(uint32_t client_handle); + +/** + * cam_cpas_start() + * + * @brief: API to start cpas client hw. Clients have to vote for minimal + * bandwidth requirements for AHB, AXI. Use cam_cpas_update_ahb_vote + * to scale bandwidth after start. + * + * @client_handle: client cpas handle + * @ahb_vote : Pointer to ahb vote info + * @axi_vote : Pointer to axi bandwidth vote info + * + * If AXI vote is not applicable to a particular client, use the value exposed + * by CAM_CPAS_DEFAULT_AXI_BW as the default vote request. + * + * @return 0 on success. + * + */ +int cam_cpas_start( + uint32_t client_handle, + struct cam_ahb_vote *ahb_vote, + struct cam_axi_vote *axi_vote); + +/** + * cam_cpas_stop() + * + * @brief: API to stop cpas client hw. Bandwidth for AHB, AXI votes + * would be removed for this client on this call. Clients should not + * use cam_cpas_update_ahb_vote or cam_cpas_update_axi_vote + * to remove their bandwidth vote. + * + * @client_handle: client cpas handle + * + * @return 0 on success. + * + */ +int cam_cpas_stop(uint32_t client_handle); + +/** + * cam_cpas_update_ahb_vote() + * + * @brief: API to update AHB vote requirement. Use this function only + * between cam_cpas_start and cam_cpas_stop in case clients wants + * to scale to different vote level. Do not use this function to de-vote, + * removing client's vote is implicit on cam_cpas_stop + * + * @client_handle : Client cpas handle + * @ahb_vote : Pointer to ahb vote info + * + * @return 0 on success. + * + */ +int cam_cpas_update_ahb_vote( + uint32_t client_handle, + struct cam_ahb_vote *ahb_vote); + +/** + * cam_cpas_update_axi_vote() + * + * @brief: API to update AXI vote requirement. Use this function only + * between cam_cpas_start and cam_cpas_stop in case clients wants + * to scale to different vote level. Do not use this function to de-vote, + * removing client's vote is implicit on cam_cpas_stop + * + * @client_handle : Client cpas handle + * @axi_vote : Pointer to axi bandwidth vote info + * + * @return 0 on success. + * + */ +int cam_cpas_update_axi_vote( + uint32_t client_handle, + struct cam_axi_vote *axi_vote); + +/** + * cam_cpas_reg_write() + * + * @brief: API to write a register value in CPAS register space + * + * @client_handle : Client cpas handle + * @reg_base : Register base identifier + * @offset : Offset from the register base address + * @mb : Whether to do reg write with memory barrier + * @value : Value to be written in register + * + * @return 0 on success. + * + */ +int cam_cpas_reg_write( + uint32_t client_handle, + enum cam_cpas_reg_base reg_base, + uint32_t offset, + bool mb, + uint32_t value); + +/** + * cam_cpas_reg_read() + * + * @brief: API to read a register value from CPAS register space + * + * @client_handle : Client cpas handle + * @reg_base : Register base identifier + * @offset : Offset from the register base address + * @mb : Whether to do reg read with memory barrier + * @value : Value to be red from register + * + * @return 0 on success. + * + */ +int cam_cpas_reg_read( + uint32_t client_handle, + enum cam_cpas_reg_base reg_base, + uint32_t offset, + bool mb, + uint32_t *value); + +/** + * cam_cpas_get_hw_info() + * + * @brief: API to get camera hw information + * + * @camera_family : Camera family type. One of + * CAM_FAMILY_CAMERA_SS + * CAM_FAMILY_CPAS_SS + * @camera_version : Camera platform version + * @cpas_version : Camera cpas version + * @cam_caps : Camera capability + * + * @return 0 on success. + * + */ +int cam_cpas_get_hw_info( + uint32_t *camera_family, + struct cam_hw_version *camera_version, + struct cam_hw_version *cpas_version, + uint32_t *cam_caps); + +/** + * cam_cpas_get_cpas_hw_version() + * + * @brief: API to get camera cpas hw version + * + * @hw_version : Camera cpas hw version + * + * @return 0 on success. + * + */ +int cam_cpas_get_cpas_hw_version( + uint32_t *hw_version); + +/** + * cam_cpas_axi_util_path_type_to_string() + * + * @brief: API to get string for given path type + * + * @path_data_type : Path type + * + * @return string. + * + */ +const char *cam_cpas_axi_util_path_type_to_string( + uint32_t path_data_type); + +/** + * cam_cpas_axi_util_trans_type_to_string() + * + * @brief: API to get string for given transaction type + * + * @path_data_type : Transaction type + * + * @return string. + * + */ +const char *cam_cpas_axi_util_trans_type_to_string( + uint32_t path_data_type); + + +#endif /* _CAM_CPAS_API_H_ */ diff --git a/drivers/cam_fd/Makefile b/drivers/cam_fd/Makefile new file mode 100644 index 000000000000..20fd941327ed --- /dev/null +++ b/drivers/cam_fd/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr/fd_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_dev.o cam_fd_context.o diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c new file mode 100644 index 000000000000..427fcf788081 --- /dev/null +++ b/drivers/cam_fd/cam_fd_context.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include + +#include "cam_debug_util.h" +#include "cam_fd_context.h" +#include "cam_trace.h" + +static const char fd_dev_name[] = "fd"; + +/* Functions in Available state */ +static int __cam_fd_ctx_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_acquire_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Acquire dev, rc=%d", rc); + return rc; + } + + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("FD", ctx); + + return rc; +} + +/* Functions in Acquired state */ +static int __cam_fd_ctx_release_dev_in_acquired(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Release dev, rc=%d", rc); + return rc; + } + + ctx->state = CAM_CTX_AVAILABLE; + trace_cam_context_state("FD", ctx); + + return rc; +} + +static int __cam_fd_ctx_config_dev_in_acquired(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_prepare_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Prepare dev, rc=%d", rc); + return rc; + } + + return rc; +} + +static int __cam_fd_ctx_start_dev_in_acquired(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_start_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Start dev, rc=%d", rc); + return rc; + } + + ctx->state = CAM_CTX_ACTIVATED; + trace_cam_context_state("FD", ctx); + + return rc; +} + +/* Functions in Activated state */ +static int __cam_fd_ctx_stop_dev_in_activated(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_stop_dev_to_hw(ctx); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Stop dev, rc=%d", rc); + return rc; + } + + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("FD", ctx); + + return rc; +} + +static int __cam_fd_ctx_release_dev_in_activated(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = __cam_fd_ctx_stop_dev_in_activated(ctx, NULL); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Stop dev, rc=%d", rc); + return rc; + } + + rc = __cam_fd_ctx_release_dev_in_acquired(ctx, cmd); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Release dev, rc=%d", rc); + return rc; + } + + return rc; +} + +static int __cam_fd_ctx_flush_dev_in_activated(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_flush_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_ICP, "Failed to flush device, rc=%d", rc); + + return rc; +} +static int __cam_fd_ctx_config_dev_in_activated( + struct cam_context *ctx, struct cam_config_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_prepare_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_FD, "Failed in Prepare dev, rc=%d", rc); + return rc; + } + + return rc; +} + +static int __cam_fd_ctx_handle_irq_in_activated(void *context, + uint32_t evt_id, void *evt_data) +{ + int rc; + + rc = cam_context_buf_done_from_hw(context, evt_data, evt_id); + if (rc) { + CAM_ERR(CAM_FD, "Failed in buf done, rc=%d", rc); + return rc; + } + + return rc; +} + +/* top state machine */ +static struct cam_ctx_ops + cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = __cam_fd_ctx_acquire_dev_in_available, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .release_dev = __cam_fd_ctx_release_dev_in_acquired, + .config_dev = __cam_fd_ctx_config_dev_in_acquired, + .start_dev = __cam_fd_ctx_start_dev_in_acquired, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Ready */ + { + .ioctl_ops = { }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Activated */ + { + .ioctl_ops = { + .stop_dev = __cam_fd_ctx_stop_dev_in_activated, + .release_dev = __cam_fd_ctx_release_dev_in_activated, + .config_dev = __cam_fd_ctx_config_dev_in_activated, + .flush_dev = __cam_fd_ctx_flush_dev_in_activated, + }, + .crm_ops = {}, + .irq_ops = __cam_fd_ctx_handle_irq_in_activated, + }, +}; + + +int cam_fd_context_init(struct cam_fd_context *fd_ctx, + struct cam_context *base_ctx, struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id) +{ + int rc; + + if (!base_ctx || !fd_ctx) { + CAM_ERR(CAM_FD, "Invalid Context %pK %pK", base_ctx, fd_ctx); + return -EINVAL; + } + + memset(fd_ctx, 0, sizeof(*fd_ctx)); + + rc = cam_context_init(base_ctx, fd_dev_name, CAM_FD, ctx_id, + NULL, hw_intf, fd_ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_FD, "Camera Context Base init failed, rc=%d", rc); + return rc; + } + + fd_ctx->base = base_ctx; + base_ctx->ctx_priv = fd_ctx; + base_ctx->state_machine = cam_fd_ctx_state_machine; + + return rc; +} + +int cam_fd_context_deinit(struct cam_fd_context *fd_ctx) +{ + int rc = 0; + + if (!fd_ctx || !fd_ctx->base) { + CAM_ERR(CAM_FD, "Invalid inputs %pK", fd_ctx); + return -EINVAL; + } + + rc = cam_context_deinit(fd_ctx->base); + if (rc) + CAM_ERR(CAM_FD, "Error in base deinit, rc=%d", rc); + + memset(fd_ctx, 0, sizeof(*fd_ctx)); + + return rc; +} diff --git a/drivers/cam_fd/cam_fd_context.h b/drivers/cam_fd/cam_fd_context.h new file mode 100644 index 000000000000..ab0fa92b43f2 --- /dev/null +++ b/drivers/cam_fd/cam_fd_context.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_CONTEXT_H_ +#define _CAM_FD_CONTEXT_H_ + +#include "cam_context.h" +#include "cam_context_utils.h" +#include "cam_hw_mgr_intf.h" +#include "cam_req_mgr_interface.h" + +/** + * struct cam_fd_context - Face Detection context information + * + * @base : Base context pointer for this FD context + * @req_base : List of base requests for this FD context + */ +struct cam_fd_context { + struct cam_context *base; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; +}; + +int cam_fd_context_init(struct cam_fd_context *fd_ctx, + struct cam_context *base_ctx, struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id); +int cam_fd_context_deinit(struct cam_fd_context *ctx); + +#endif /* _CAM_FD_CONTEXT_H_ */ diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c new file mode 100644 index 000000000000..c92cea8fc9e9 --- /dev/null +++ b/drivers/cam_fd/cam_fd_dev.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "cam_subdev.h" +#include "cam_node.h" +#include "cam_fd_context.h" +#include "cam_fd_hw_mgr.h" +#include "cam_fd_hw_mgr_intf.h" + +#define CAM_FD_DEV_NAME "cam-fd" + +/** + * struct cam_fd_dev - FD device information + * + * @sd: Subdev information + * @base_ctx: List of base contexts + * @fd_ctx: List of FD contexts + * @lock: Mutex handle + * @open_cnt: FD subdev open count + * @probe_done: Whether FD probe is completed + */ +struct cam_fd_dev { + struct cam_subdev sd; + struct cam_context base_ctx[CAM_CTX_MAX]; + struct cam_fd_context fd_ctx[CAM_CTX_MAX]; + struct mutex lock; + uint32_t open_cnt; + bool probe_done; +}; + +static struct cam_fd_dev g_fd_dev; + +static int cam_fd_dev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_fd_dev *fd_dev = &g_fd_dev; + + if (!fd_dev->probe_done) { + CAM_ERR(CAM_FD, "FD Dev not initialized, fd_dev=%pK", fd_dev); + return -ENODEV; + } + + mutex_lock(&fd_dev->lock); + fd_dev->open_cnt++; + CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); + mutex_unlock(&fd_dev->lock); + + return 0; +} + +static int cam_fd_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_fd_dev *fd_dev = &g_fd_dev; + struct cam_node *node = v4l2_get_subdevdata(sd); + + if (!fd_dev->probe_done) { + CAM_ERR(CAM_FD, "FD Dev not initialized, fd_dev=%pK", fd_dev); + return -ENODEV; + } + + mutex_lock(&fd_dev->lock); + fd_dev->open_cnt--; + CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); + mutex_unlock(&fd_dev->lock); + + if (!node) { + CAM_ERR(CAM_FD, "Node ptr is NULL"); + return -EINVAL; + } + + cam_node_shutdown(node); + + return 0; +} + +static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { + .open = cam_fd_dev_open, + .close = cam_fd_dev_close, +}; + +static int cam_fd_dev_probe(struct platform_device *pdev) +{ + int rc; + int i; + struct cam_hw_mgr_intf hw_mgr_intf; + struct cam_node *node; + + g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; + + /* Initialize the v4l2 subdevice first. (create cam_node) */ + rc = cam_subdev_probe(&g_fd_dev.sd, pdev, CAM_FD_DEV_NAME, + CAM_FD_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_FD, "FD cam_subdev_probe failed, rc=%d", rc); + return rc; + } + node = (struct cam_node *) g_fd_dev.sd.token; + + rc = cam_fd_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf); + if (rc) { + CAM_ERR(CAM_FD, "Failed in initializing FD HW manager, rc=%d", + rc); + goto unregister_subdev; + } + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_fd_context_init(&g_fd_dev.fd_ctx[i], + &g_fd_dev.base_ctx[i], &node->hw_mgr_intf, i); + if (rc) { + CAM_ERR(CAM_FD, "FD context init failed i=%d, rc=%d", + i, rc); + goto deinit_ctx; + } + } + + rc = cam_node_init(node, &hw_mgr_intf, g_fd_dev.base_ctx, CAM_CTX_MAX, + CAM_FD_DEV_NAME); + if (rc) { + CAM_ERR(CAM_FD, "FD node init failed, rc=%d", rc); + goto deinit_ctx; + } + + mutex_init(&g_fd_dev.lock); + g_fd_dev.probe_done = true; + + CAM_DBG(CAM_FD, "Camera FD probe complete"); + + return 0; + +deinit_ctx: + for (--i; i >= 0; i--) { + if (cam_fd_context_deinit(&g_fd_dev.fd_ctx[i])) + CAM_ERR(CAM_FD, "FD context %d deinit failed", i); + } +unregister_subdev: + if (cam_subdev_remove(&g_fd_dev.sd)) + CAM_ERR(CAM_FD, "Failed in subdev remove"); + + return rc; +} + +static int cam_fd_dev_remove(struct platform_device *pdev) +{ + int i, rc; + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_fd_context_deinit(&g_fd_dev.fd_ctx[i]); + if (rc) + CAM_ERR(CAM_FD, "FD context %d deinit failed, rc=%d", + i, rc); + } + + rc = cam_fd_hw_mgr_deinit(pdev->dev.of_node); + if (rc) + CAM_ERR(CAM_FD, "Failed in hw mgr deinit, rc=%d", rc); + + rc = cam_subdev_remove(&g_fd_dev.sd); + if (rc) + CAM_ERR(CAM_FD, "Unregister failed, rc=%d", rc); + + mutex_destroy(&g_fd_dev.lock); + g_fd_dev.probe_done = false; + + return rc; +} + +static const struct of_device_id cam_fd_dt_match[] = { + { + .compatible = "qcom,cam-fd" + }, + {} +}; + +static struct platform_driver cam_fd_driver = { + .probe = cam_fd_dev_probe, + .remove = cam_fd_dev_remove, + .driver = { + .name = "cam_fd", + .owner = THIS_MODULE, + .of_match_table = cam_fd_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_fd_dev_init_module(void) +{ + return platform_driver_register(&cam_fd_driver); +} + +static void __exit cam_fd_dev_exit_module(void) +{ + platform_driver_unregister(&cam_fd_driver); +} + +module_init(cam_fd_dev_init_module); +module_exit(cam_fd_dev_exit_module); +MODULE_DESCRIPTION("MSM FD driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_fd/fd_hw_mgr/Makefile b/drivers/cam_fd/fd_hw_mgr/Makefile new file mode 100644 index 000000000000..cc15876c9602 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr/fd_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_hw_mgr.o diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c new file mode 100644 index 000000000000..0d7e709ad38f --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -0,0 +1,1949 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_soc_util.h" +#include "cam_mem_mgr_api.h" +#include "cam_smmu_api.h" +#include "cam_packet_util.h" +#include "cam_fd_context.h" +#include "cam_fd_hw_intf.h" +#include "cam_fd_hw_core.h" +#include "cam_fd_hw_soc.h" +#include "cam_fd_hw_mgr_intf.h" +#include "cam_fd_hw_mgr.h" +#include "cam_trace.h" + +static struct cam_fd_hw_mgr g_fd_hw_mgr; + +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; + + if (!packet) + return -EINVAL; + + CAM_DBG(CAM_FD, "Packet request=%d, op_code=0x%x, size=%d, flags=%d", + packet->header.request_id, packet->header.op_code, + packet->header.size, packet->header.flags); + CAM_DBG(CAM_FD, + "Packet cmdbuf(offset=%d, num=%d) io(offset=%d, num=%d)", + packet->cmd_buf_offset, packet->num_cmd_buf, + packet->io_configs_offset, packet->num_io_configs); + CAM_DBG(CAM_FD, + "Packet Patch(offset=%d, num=%d) kmd(offset=%d, num=%d)", + packet->patch_offset, packet->num_patches, + packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index); + + 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, + packet->io_configs_offset, packet->header.size); + return -EINVAL; + } + + /* All buffers must come through io config, do not support patching */ + if (packet->num_patches || !packet->num_io_configs) { + CAM_ERR(CAM_FD, "wrong number of cmd/patch info: %u %u", + packet->num_cmd_buf, packet->num_patches); + return -EINVAL; + } + + /* KMD Buf index can never be greater than or equal to num cmd bufs */ + if (packet->kmd_cmd_buf_index >= packet->num_cmd_buf) { + CAM_ERR(CAM_FD, "Invalid kmd index %d (%d)", + packet->kmd_cmd_buf_index, packet->num_cmd_buf); + return -EINVAL; + } + + if ((packet->header.op_code & 0xff) != + CAM_PACKET_OPCODES_FD_FRAME_UPDATE) { + CAM_ERR(CAM_FD, "Invalid op_code %u", + packet->header.op_code & 0xff); + return -EINVAL; + } + + cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)&packet->payload + + packet->cmd_buf_offset); + + for (i = 0; i < packet->num_cmd_buf; i++) { + /* + * We can allow 0 length cmd buffer. This can happen in case + * umd gives an empty cmd buffer as kmd buffer + */ + if (!cmd_desc[i].length) + continue; + + if ((cmd_desc[i].meta_data != CAM_FD_CMD_BUFFER_ID_GENERIC) && + (cmd_desc[i].meta_data != CAM_FD_CMD_BUFFER_ID_CDM)) { + CAM_ERR(CAM_FD, "Invalid meta_data [%d] %u", i, + cmd_desc[i].meta_data); + return -EINVAL; + } + + CAM_DBG(CAM_FD, + "CmdBuf[%d] hdl=%d, offset=%d, size=%d, len=%d, type=%d, meta_data=%d", + i, + cmd_desc[i].mem_handle, cmd_desc[i].offset, + cmd_desc[i].size, cmd_desc[i].length, cmd_desc[i].type, + cmd_desc[i].meta_data); + + rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); + if (rc) { + CAM_ERR(CAM_FD, "Invalid cmd buffer %d", i); + return rc; + } + } + + return 0; +} + +static int cam_fd_mgr_util_put_ctx( + struct list_head *src_list, + struct cam_fd_hw_mgr_ctx **fd_ctx) +{ + int rc = 0; + struct cam_fd_hw_mgr_ctx *ctx_ptr = NULL; + + mutex_lock(&g_fd_hw_mgr.ctx_mutex); + ctx_ptr = *fd_ctx; + if (ctx_ptr) + list_add_tail(&ctx_ptr->list, src_list); + *fd_ctx = NULL; + mutex_unlock(&g_fd_hw_mgr.ctx_mutex); + + return rc; +} + +static int cam_fd_mgr_util_get_ctx( + struct list_head *src_list, + struct cam_fd_hw_mgr_ctx **fd_ctx) +{ + int rc = 0; + struct cam_fd_hw_mgr_ctx *ctx_ptr = NULL; + + mutex_lock(&g_fd_hw_mgr.ctx_mutex); + if (!list_empty(src_list)) { + ctx_ptr = list_first_entry(src_list, + struct cam_fd_hw_mgr_ctx, list); + list_del_init(&ctx_ptr->list); + } else { + CAM_ERR(CAM_FD, "No more free fd hw mgr ctx"); + rc = -1; + } + *fd_ctx = ctx_ptr; + mutex_unlock(&g_fd_hw_mgr.ctx_mutex); + + return rc; +} + +static int cam_fd_mgr_util_put_frame_req( + struct list_head *src_list, + struct cam_fd_mgr_frame_request **frame_req) +{ + int rc = 0; + struct cam_fd_mgr_frame_request *req_ptr = NULL; + + mutex_lock(&g_fd_hw_mgr.frame_req_mutex); + req_ptr = *frame_req; + 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); + + return rc; +} + +static int cam_fd_mgr_util_get_frame_req( + struct list_head *src_list, + struct cam_fd_mgr_frame_request **frame_req) +{ + int rc = 0; + struct cam_fd_mgr_frame_request *req_ptr = NULL; + + mutex_lock(&g_fd_hw_mgr.frame_req_mutex); + if (!list_empty(src_list)) { + req_ptr = list_first_entry(src_list, + struct cam_fd_mgr_frame_request, list); + list_del_init(&req_ptr->list); + } else { + CAM_DBG(CAM_FD, "Frame req not available"); + rc = -EPERM; + } + *frame_req = req_ptr; + mutex_unlock(&g_fd_hw_mgr.frame_req_mutex); + + return rc; +} + +static int cam_fd_mgr_util_get_device(struct cam_fd_hw_mgr *hw_mgr, + struct cam_fd_hw_mgr_ctx *hw_ctx, struct cam_fd_device **hw_device) +{ + if (!hw_mgr || !hw_ctx || !hw_device) { + CAM_ERR(CAM_FD, "Invalid input %pK %pK %pK", hw_mgr, hw_ctx, + hw_device); + return -EINVAL; + } + + if ((hw_ctx->device_index < 0) || + (hw_ctx->device_index >= CAM_FD_HW_MAX)) { + CAM_ERR(CAM_FD, "Invalid device indx %d", hw_ctx->device_index); + return -EINVAL; + } + + CAM_DBG(CAM_FD, "ctx_index=%u, hw_ctx=%d", hw_ctx->ctx_index, + hw_ctx->device_index); + + *hw_device = &hw_mgr->hw_device[hw_ctx->device_index]; + + return 0; +} + +static int cam_fd_mgr_util_release_device(struct cam_fd_hw_mgr *hw_mgr, + struct cam_fd_hw_mgr_ctx *hw_ctx) +{ + struct cam_fd_device *hw_device; + struct cam_fd_hw_release_args hw_release_args; + int rc; + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + if (hw_device->hw_intf->hw_ops.release) { + hw_release_args.hw_ctx = hw_ctx; + hw_release_args.ctx_hw_private = hw_ctx->ctx_hw_private; + rc = hw_device->hw_intf->hw_ops.release( + hw_device->hw_intf->hw_priv, &hw_release_args, + sizeof(hw_release_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HW release %d", rc); + return rc; + } + } else { + CAM_ERR(CAM_FD, "Invalid release function"); + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + hw_device->num_ctxts--; + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + hw_ctx->device_index = -1; + + return rc; +} + +static int cam_fd_mgr_util_select_device(struct cam_fd_hw_mgr *hw_mgr, + struct cam_fd_hw_mgr_ctx *hw_ctx, + struct cam_fd_acquire_dev_info *fd_acquire_args) +{ + int i, rc; + struct cam_fd_hw_reserve_args hw_reserve_args; + struct cam_fd_device *hw_device = NULL; + + if (!hw_mgr || !hw_ctx || !fd_acquire_args) { + CAM_ERR(CAM_FD, "Invalid input %pK %pK %pK", hw_mgr, hw_ctx, + fd_acquire_args); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + /* Check if a device is free which can satisfy the requirements */ + for (i = 0; i < hw_mgr->num_devices; i++) { + hw_device = &hw_mgr->hw_device[i]; + CAM_DBG(CAM_FD, + "[%d] : num_ctxts=%d, modes=%d, raw_results=%d", + i, hw_device->num_ctxts, + hw_device->hw_caps.supported_modes, + hw_device->hw_caps.raw_results_available); + if ((hw_device->num_ctxts == 0) && + (fd_acquire_args->mode & + hw_device->hw_caps.supported_modes) && + (!fd_acquire_args->get_raw_results || + hw_device->hw_caps.raw_results_available)) { + CAM_DBG(CAM_FD, "Found dedicated HW Index=%d", i); + hw_device->num_ctxts++; + break; + } + } + + /* + * We couldn't find a free HW which meets requirement, now check if + * there is a HW which meets acquire requirements + */ + if (i == hw_mgr->num_devices) { + for (i = 0; i < hw_mgr->num_devices; i++) { + hw_device = &hw_mgr->hw_device[i]; + if ((fd_acquire_args->mode & + hw_device->hw_caps.supported_modes) && + (!fd_acquire_args->get_raw_results || + hw_device->hw_caps.raw_results_available)) { + hw_device->num_ctxts++; + CAM_DBG(CAM_FD, "Found sharing HW Index=%d", i); + break; + } + } + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + if ((i == hw_mgr->num_devices) || !hw_device) { + CAM_ERR(CAM_FD, "Couldn't acquire HW %d %d", + fd_acquire_args->mode, + fd_acquire_args->get_raw_results); + return -EBUSY; + } + + CAM_DBG(CAM_FD, "Device index %d selected for this acquire", i); + + /* Check if we can reserve this HW */ + if (hw_device->hw_intf->hw_ops.reserve) { + hw_reserve_args.hw_ctx = hw_ctx; + hw_reserve_args.mode = fd_acquire_args->mode; + rc = hw_device->hw_intf->hw_ops.reserve( + hw_device->hw_intf->hw_priv, &hw_reserve_args, + sizeof(hw_reserve_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HW reserve %d", rc); + return rc; + } + hw_ctx->ctx_hw_private = hw_reserve_args.ctx_hw_private; + } else { + CAM_ERR(CAM_FD, "Invalid reserve function"); + return -EPERM; + } + + /* Update required info in hw context */ + hw_ctx->device_index = i; + + CAM_DBG(CAM_FD, "ctx index=%u, device_index=%d", hw_ctx->ctx_index, + hw_ctx->device_index); + + return 0; +} + +static int cam_fd_mgr_util_pdev_get_hw_intf(struct device_node *of_node, + int i, struct cam_hw_intf **device_hw_intf) +{ + struct device_node *device_node = NULL; + struct platform_device *child_pdev = NULL; + struct cam_hw_intf *hw_intf = NULL; + const char *name = NULL; + int rc; + + rc = of_property_read_string_index(of_node, "compat-hw-name", i, &name); + if (rc) { + CAM_ERR(CAM_FD, "Getting dev object name failed %d %d", i, rc); + goto put_node; + } + + device_node = of_find_node_by_name(NULL, name); + if (!device_node) { + CAM_ERR(CAM_FD, "Cannot find node in dtsi %s", name); + return -ENODEV; + } + + child_pdev = of_find_device_by_node(device_node); + if (!child_pdev) { + CAM_ERR(CAM_FD, "Failed to find device on bus %s", + device_node->name); + rc = -ENODEV; + goto put_node; + } + + hw_intf = (struct cam_hw_intf *)platform_get_drvdata(child_pdev); + if (!hw_intf) { + CAM_ERR(CAM_FD, "No driver data for child device"); + rc = -ENODEV; + goto put_node; + } + + CAM_DBG(CAM_FD, "child type %d index %d child_intf %pK", + hw_intf->hw_type, hw_intf->hw_idx, hw_intf); + + if (hw_intf->hw_idx >= CAM_FD_HW_MAX) { + CAM_ERR(CAM_FD, "hw_idx invalid %d", hw_intf->hw_idx); + rc = -ENODEV; + goto put_node; + } + + rc = 0; + *device_hw_intf = hw_intf; + +put_node: + of_node_put(device_node); + + return rc; +} + +static int cam_fd_packet_generic_blob_handler(void *user_data, + uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) +{ + struct cam_fd_hw_cmd_prestart_args *prestart_args = + (struct cam_fd_hw_cmd_prestart_args *)user_data; + + if (!blob_data || (blob_size == 0)) { + CAM_ERR(CAM_FD, "Invalid blob info %pK %u", blob_data, + blob_size); + return -EINVAL; + } + + if (!prestart_args) { + CAM_ERR(CAM_FD, "Invalid user data"); + return -EINVAL; + } + + switch (blob_type) { + case CAM_FD_BLOB_TYPE_RAW_RESULTS_REQUIRED: { + uint32_t *get_raw_results = (uint32_t *)blob_data; + + if (sizeof(uint32_t) != blob_size) { + CAM_ERR(CAM_FD, "Invalid blob size %zu %u", + sizeof(uint32_t), blob_size); + return -EINVAL; + } + + prestart_args->get_raw_results = *get_raw_results; + break; + } + case CAM_FD_BLOB_TYPE_SOC_CLOCK_BW_REQUEST: { + struct cam_fd_soc_clock_bw_request *clk_req = + (struct cam_fd_soc_clock_bw_request *)blob_data; + + if (sizeof(struct cam_fd_soc_clock_bw_request) != blob_size) { + CAM_ERR(CAM_FD, "Invalid blob size %zu %u", + sizeof(struct cam_fd_soc_clock_bw_request), + blob_size); + return -EINVAL; + } + + CAM_DBG(CAM_FD, "SOC Clk Request clock=%lld, bw=%lld", + clk_req->clock_rate, clk_req->bandwidth); + + break; + } + default: + CAM_WARN(CAM_FD, "Unknown blob type %d", blob_type); + break; + } + + return 0; +} + +static int cam_fd_mgr_util_parse_generic_cmd_buffer( + struct cam_fd_hw_mgr_ctx *hw_ctx, struct cam_packet *packet, + struct cam_fd_hw_cmd_prestart_args *prestart_args) +{ + struct cam_cmd_buf_desc *cmd_desc = NULL; + int i, rc = 0; + + cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)&packet->payload + + packet->cmd_buf_offset); + + for (i = 0; i < packet->num_cmd_buf; i++) { + if (!cmd_desc[i].length) + continue; + + if (cmd_desc[i].meta_data == CAM_FD_CMD_BUFFER_ID_CDM) + continue; + + rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); + if (rc) + return rc; + + rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[i], + cam_fd_packet_generic_blob_handler, prestart_args); + if (rc) + CAM_ERR(CAM_FD, "Failed in processing blobs %d", rc); + + break; + } + + return rc; +} + +static int cam_fd_mgr_util_get_buf_map_requirement(uint32_t direction, + uint32_t resource_type, bool *need_io_map, bool *need_cpu_map) +{ + if (!need_io_map || !need_cpu_map) { + CAM_ERR(CAM_FD, "Invalid input pointers %pK %pK", need_io_map, + need_cpu_map); + return -EINVAL; + } + + if (direction == CAM_BUF_INPUT) { + switch (resource_type) { + case CAM_FD_INPUT_PORT_ID_IMAGE: + *need_io_map = true; + *need_cpu_map = false; + break; + default: + CAM_WARN(CAM_FD, "Invalid port: dir %d, id %d", + direction, resource_type); + return -EINVAL; + } + } else if (direction == CAM_BUF_OUTPUT) { + switch (resource_type) { + case CAM_FD_OUTPUT_PORT_ID_RESULTS: + *need_io_map = true; + *need_cpu_map = true; + break; + case CAM_FD_OUTPUT_PORT_ID_RAW_RESULTS: + *need_io_map = true; + *need_cpu_map = true; + break; + case CAM_FD_OUTPUT_PORT_ID_WORK_BUFFER: + *need_io_map = true; + *need_cpu_map = false; + break; + default: + CAM_WARN(CAM_FD, "Invalid port: dir %d, id %d", + direction, resource_type); + return -EINVAL; + } + } else { + CAM_WARN(CAM_FD, "Invalid direction %d", direction); + return -EINVAL; + } + + return 0; +} + +static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl, + struct cam_hw_prepare_update_args *prepare, + struct cam_fd_hw_io_buffer *input_buf, + struct cam_fd_hw_io_buffer *output_buf, uint32_t io_buf_size) +{ + int rc = -EINVAL; + uint32_t plane, num_out_buf, num_in_buf; + int i, j; + struct cam_buf_io_cfg *io_cfg; + dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; + uintptr_t cpu_addr[CAM_PACKET_MAX_PLANES]; + size_t size; + bool need_io_map, need_cpu_map; + + /* Get IO Buf information */ + num_out_buf = 0; + num_in_buf = 0; + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &prepare->packet->payload + prepare->packet->io_configs_offset); + + for (i = 0; i < prepare->packet->num_io_configs; i++) { + CAM_DBG(CAM_FD, + "IOConfig[%d] : handle[%d] Dir[%d] Res[%d] Fence[%d], Format[%d]", + i, io_cfg[i].mem_handle[0], io_cfg[i].direction, + io_cfg[i].resource_type, + io_cfg[i].fence, io_cfg[i].format); + + if ((num_in_buf >= io_buf_size) || + (num_out_buf >= io_buf_size)) { + CAM_ERR(CAM_FD, "Invalid number of buffers %d %d %d", + num_in_buf, num_out_buf, io_buf_size); + return -EINVAL; + } + + rc = cam_fd_mgr_util_get_buf_map_requirement( + io_cfg[i].direction, io_cfg[i].resource_type, + &need_io_map, &need_cpu_map); + if (rc) { + CAM_WARN(CAM_FD, "Invalid io buff [%d] : %d %d %d", + i, io_cfg[i].direction, + io_cfg[i].resource_type, rc); + continue; + } + + memset(io_addr, 0x0, sizeof(io_addr)); + for (plane = 0; plane < CAM_PACKET_MAX_PLANES; plane++) { + if (!io_cfg[i].mem_handle[plane]) + break; + + io_addr[plane] = 0x0; + cpu_addr[plane] = 0x0; + + if (need_io_map) { + rc = cam_mem_get_io_buf( + io_cfg[i].mem_handle[plane], + iommu_hdl, &io_addr[plane], &size); + if (rc) { + CAM_ERR(CAM_FD, + "Invalid io buf %d %d %d %d", + io_cfg[i].direction, + io_cfg[i].resource_type, plane, + rc); + return -ENOMEM; + } + + io_addr[plane] += io_cfg[i].offsets[plane]; + } + + if (need_cpu_map) { + rc = cam_mem_get_cpu_buf( + io_cfg[i].mem_handle[plane], + &cpu_addr[plane], &size); + if (rc || ((io_addr[plane] & 0xFFFFFFFF) + != io_addr[plane])) { + CAM_ERR(CAM_FD, + "Invalid cpu buf %d %d %d %d", + io_cfg[i].direction, + io_cfg[i].resource_type, plane, + 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); + rc = -EINVAL; + return rc; + } + cpu_addr[plane] += io_cfg[i].offsets[plane]; + } + + CAM_DBG(CAM_FD, "IO Address[%d][%d] : %pK, %pK", + io_cfg[i].direction, plane, io_addr[plane], + cpu_addr[plane]); + } + + switch (io_cfg[i].direction) { + case CAM_BUF_INPUT: { + prepare->in_map_entries[num_in_buf].resource_handle = + io_cfg[i].resource_type; + prepare->in_map_entries[num_in_buf].sync_id = + io_cfg[i].fence; + + input_buf[num_in_buf].valid = true; + for (j = 0; j < plane; j++) { + input_buf[num_in_buf].io_addr[j] = io_addr[j]; + input_buf[num_in_buf].cpu_addr[j] = cpu_addr[j]; + } + input_buf[num_in_buf].num_buf = plane; + input_buf[num_in_buf].io_cfg = &io_cfg[i]; + + num_in_buf++; + break; + } + case CAM_BUF_OUTPUT: { + prepare->out_map_entries[num_out_buf].resource_handle = + io_cfg[i].resource_type; + prepare->out_map_entries[num_out_buf].sync_id = + io_cfg[i].fence; + + output_buf[num_out_buf].valid = true; + for (j = 0; j < plane; j++) { + output_buf[num_out_buf].io_addr[j] = io_addr[j]; + output_buf[num_out_buf].cpu_addr[j] = + cpu_addr[j]; + } + output_buf[num_out_buf].num_buf = plane; + output_buf[num_out_buf].io_cfg = &io_cfg[i]; + + num_out_buf++; + break; + } + default: + CAM_ERR(CAM_FD, "Unsupported io direction %d", + io_cfg[i].direction); + rc = -EINVAL; + break; + } + } + + prepare->num_in_map_entries = num_in_buf; + prepare->num_out_map_entries = num_out_buf; + return rc; +} + +static int cam_fd_mgr_util_prepare_hw_update_entries( + struct cam_fd_hw_mgr *hw_mgr, + struct cam_hw_prepare_update_args *prepare, + struct cam_fd_hw_cmd_prestart_args *prestart_args, + struct cam_kmd_buf_info *kmd_buf_info) +{ + int i, rc; + struct cam_hw_update_entry *hw_entry; + uint32_t num_ent; + struct cam_fd_hw_mgr_ctx *hw_ctx = + (struct cam_fd_hw_mgr_ctx *)prepare->ctxt_to_hw_map; + struct cam_fd_device *hw_device; + uint32_t kmd_buf_max_size, kmd_buf_used_bytes = 0; + uint32_t *kmd_buf_addr; + struct cam_cmd_buf_desc *cmd_desc = NULL; + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + kmd_buf_addr = (uint32_t *)((uint8_t *)kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes); + kmd_buf_max_size = kmd_buf_info->size - kmd_buf_info->used_bytes; + + prestart_args->cmd_buf_addr = kmd_buf_addr; + prestart_args->size = kmd_buf_max_size; + prestart_args->pre_config_buf_size = 0; + prestart_args->post_config_buf_size = 0; + + if (hw_device->hw_intf->hw_ops.process_cmd) { + rc = hw_device->hw_intf->hw_ops.process_cmd( + hw_device->hw_intf->hw_priv, CAM_FD_HW_CMD_PRESTART, + prestart_args, + sizeof(struct cam_fd_hw_cmd_prestart_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in CMD_PRESTART %d", rc); + return rc; + } + } + + kmd_buf_used_bytes += prestart_args->pre_config_buf_size; + kmd_buf_used_bytes += prestart_args->post_config_buf_size; + + /* HW layer is expected to add commands */ + if (!kmd_buf_used_bytes || (kmd_buf_used_bytes > kmd_buf_max_size)) { + CAM_ERR(CAM_FD, "Invalid kmd used bytes %d (%d)", + kmd_buf_used_bytes, kmd_buf_max_size); + return -ENOMEM; + } + + hw_entry = prepare->hw_update_entries; + num_ent = 0; + + if (prestart_args->pre_config_buf_size) { + if ((num_ent + 1) >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_FD, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); + return -EINVAL; + } + + hw_entry[num_ent].handle = kmd_buf_info->handle; + hw_entry[num_ent].len = prestart_args->pre_config_buf_size; + hw_entry[num_ent].offset = kmd_buf_info->offset; + + kmd_buf_info->used_bytes += prestart_args->pre_config_buf_size; + kmd_buf_info->offset += prestart_args->pre_config_buf_size; + num_ent++; + } + + /* + * set the cmd_desc to point the first command descriptor in the + * packet and update hw entries with CDM command buffers + */ + cmd_desc = (struct cam_cmd_buf_desc *)((uint8_t *) + &prepare->packet->payload + prepare->packet->cmd_buf_offset); + + for (i = 0; i < prepare->packet->num_cmd_buf; i++) { + if (!cmd_desc[i].length) + continue; + + if (cmd_desc[i].meta_data != CAM_FD_CMD_BUFFER_ID_CDM) + continue; + + if (num_ent + 1 >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_FD, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); + return -EINVAL; + } + + hw_entry[num_ent].handle = cmd_desc[i].mem_handle; + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].offset = cmd_desc[i].offset; + num_ent++; + } + + if (prestart_args->post_config_buf_size) { + if (num_ent + 1 >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_FD, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); + return -EINVAL; + } + + hw_entry[num_ent].handle = kmd_buf_info->handle; + hw_entry[num_ent].len = prestart_args->post_config_buf_size; + hw_entry[num_ent].offset = kmd_buf_info->offset; + + kmd_buf_info->used_bytes += prestart_args->post_config_buf_size; + kmd_buf_info->offset += prestart_args->post_config_buf_size; + + num_ent++; + } + + prepare->num_hw_update_entries = num_ent; + + CAM_DBG(CAM_FD, "FinalConfig : hw_entries=%d, Sync(in=%d, out=%d)", + prepare->num_hw_update_entries, prepare->num_in_map_entries, + prepare->num_out_map_entries); + + return rc; +} + +static int cam_fd_mgr_util_submit_frame(void *priv, void *data) +{ + struct cam_fd_device *hw_device; + struct cam_fd_hw_mgr *hw_mgr; + struct cam_fd_mgr_frame_request *frame_req; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_hw_cmd_start_args start_args; + int rc; + + if (!priv) { + CAM_ERR(CAM_FD, "Invalid data"); + return -EINVAL; + } + + hw_mgr = (struct cam_fd_hw_mgr *)priv; + mutex_lock(&hw_mgr->frame_req_mutex); + + /* Check if we have any frames pending in high priority list */ + if (!list_empty(&hw_mgr->frame_pending_list_high)) { + CAM_DBG(CAM_FD, "Pending frames in high priority list"); + frame_req = list_first_entry(&hw_mgr->frame_pending_list_high, + struct cam_fd_mgr_frame_request, list); + } else if (!list_empty(&hw_mgr->frame_pending_list_normal)) { + CAM_DBG(CAM_FD, "Pending frames in normal priority list"); + frame_req = list_first_entry(&hw_mgr->frame_pending_list_normal, + struct cam_fd_mgr_frame_request, list); + } else { + mutex_unlock(&hw_mgr->frame_req_mutex); + CAM_DBG(CAM_FD, "No pending frames"); + return 0; + } + + CAM_DBG(CAM_FD, "FrameSubmit : Frame[%lld]", frame_req->request_id); + hw_ctx = frame_req->hw_ctx; + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + mutex_unlock(&hw_mgr->frame_req_mutex); + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + mutex_lock(&hw_device->lock); + if (hw_device->ready_to_process == false) { + mutex_unlock(&hw_device->lock); + mutex_unlock(&hw_mgr->frame_req_mutex); + return -EBUSY; + } + + trace_cam_submit_to_hw("FD", frame_req->request_id); + + list_del_init(&frame_req->list); + mutex_unlock(&hw_mgr->frame_req_mutex); + + if (hw_device->hw_intf->hw_ops.start) { + start_args.hw_ctx = hw_ctx; + start_args.ctx_hw_private = hw_ctx->ctx_hw_private; + start_args.hw_req_private = &frame_req->hw_req_private; + start_args.hw_update_entries = frame_req->hw_update_entries; + start_args.num_hw_update_entries = + frame_req->num_hw_update_entries; + + rc = hw_device->hw_intf->hw_ops.start( + hw_device->hw_intf->hw_priv, &start_args, + sizeof(start_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HW Start %d", rc); + mutex_unlock(&hw_device->lock); + goto put_req_into_free_list; + } + } else { + CAM_ERR(CAM_FD, "Invalid hw_ops.start"); + mutex_unlock(&hw_device->lock); + rc = -EPERM; + goto put_req_into_free_list; + } + + hw_device->ready_to_process = false; + hw_device->cur_hw_ctx = hw_ctx; + hw_device->req_id = frame_req->request_id; + mutex_unlock(&hw_device->lock); + + rc = cam_fd_mgr_util_put_frame_req( + &hw_mgr->frame_processing_list, &frame_req); + if (rc) { + CAM_ERR(CAM_FD, + "Failed in putting frame req in processing list"); + goto stop_unlock; + } + + return rc; + +stop_unlock: + if (hw_device->hw_intf->hw_ops.stop) { + struct cam_fd_hw_stop_args stop_args; + + stop_args.hw_ctx = hw_ctx; + stop_args.ctx_hw_private = hw_ctx->ctx_hw_private; + stop_args.hw_req_private = &frame_req->hw_req_private; + if (hw_device->hw_intf->hw_ops.stop( + hw_device->hw_intf->hw_priv, &stop_args, + sizeof(stop_args))) + CAM_ERR(CAM_FD, "Failed in HW Stop %d", rc); + } +put_req_into_free_list: + cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list, &frame_req); + + return rc; +} + +static int cam_fd_mgr_util_schedule_frame_worker_task( + struct cam_fd_hw_mgr *hw_mgr) +{ + int32_t rc = 0; + struct crm_workq_task *task; + struct cam_fd_mgr_work_data *work_data; + + task = cam_req_mgr_workq_get_task(hw_mgr->work); + if (!task) { + CAM_ERR(CAM_FD, "no empty task available"); + return -ENOMEM; + } + + work_data = (struct cam_fd_mgr_work_data *)task->payload; + work_data->type = CAM_FD_WORK_FRAME; + + task->process_cb = cam_fd_mgr_util_submit_frame; + rc = cam_req_mgr_workq_enqueue_task(task, hw_mgr, CRM_TASK_PRIORITY_0); + + return rc; +} + +static int32_t cam_fd_mgr_workq_irq_cb(void *priv, void *data) +{ + struct cam_fd_device *hw_device = NULL; + struct cam_fd_hw_mgr *hw_mgr; + struct cam_fd_mgr_work_data *work_data; + struct cam_fd_mgr_frame_request *frame_req = NULL; + enum cam_fd_hw_irq_type irq_type; + bool frame_abort = true; + int rc; + + if (!data || !priv) { + CAM_ERR(CAM_FD, "Invalid data %pK %pK", data, priv); + return -EINVAL; + } + + hw_mgr = (struct cam_fd_hw_mgr *)priv; + work_data = (struct cam_fd_mgr_work_data *)data; + irq_type = work_data->irq_type; + + CAM_DBG(CAM_FD, "FD IRQ type=%d", irq_type); + + if (irq_type == CAM_FD_IRQ_HALT_DONE) { + /* HALT would be followed by a RESET, ignore this */ + CAM_DBG(CAM_FD, "HALT IRQ callback"); + return 0; + } + + /* Get the frame from processing list */ + rc = cam_fd_mgr_util_get_frame_req(&hw_mgr->frame_processing_list, + &frame_req); + if (rc || !frame_req) { + /* + * This can happen if reset is triggered while no frames + * were pending, so not an error, just continue to check if + * there are any pending frames and submit + */ + CAM_DBG(CAM_FD, "No Frame in processing list, rc=%d", rc); + goto submit_next_frame; + } + + if (!frame_req->hw_ctx) { + CAM_ERR(CAM_FD, "Invalid Frame request %lld", + frame_req->request_id); + goto put_req_in_free_list; + } + + rc = cam_fd_mgr_util_get_device(hw_mgr, frame_req->hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + goto put_req_in_free_list; + } + + /* Read frame results first */ + if (irq_type == CAM_FD_IRQ_FRAME_DONE) { + struct cam_fd_hw_frame_done_args frame_done_args; + + CAM_DBG(CAM_FD, "FrameDone : Frame[%lld]", + frame_req->request_id); + + frame_done_args.hw_ctx = frame_req->hw_ctx; + frame_done_args.ctx_hw_private = + frame_req->hw_ctx->ctx_hw_private; + frame_done_args.request_id = frame_req->request_id; + frame_done_args.hw_req_private = &frame_req->hw_req_private; + + if (hw_device->hw_intf->hw_ops.process_cmd) { + rc = hw_device->hw_intf->hw_ops.process_cmd( + hw_device->hw_intf->hw_priv, + CAM_FD_HW_CMD_FRAME_DONE, + &frame_done_args, sizeof(frame_done_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in CMD_PRESTART %d", + rc); + frame_abort = true; + goto notify_context; + } + } + + frame_abort = false; + } + + trace_cam_irq_handled("FD", irq_type); + +notify_context: + /* Do a callback to inform frame done or stop done */ + if (frame_req->hw_ctx->event_cb) { + struct cam_hw_done_event_data buf_data; + + CAM_DBG(CAM_FD, "FrameHALT : Frame[%lld]", + frame_req->request_id); + + buf_data.num_handles = frame_req->num_hw_update_entries; + buf_data.request_id = frame_req->request_id; + + rc = frame_req->hw_ctx->event_cb(frame_req->hw_ctx->cb_priv, + frame_abort, &buf_data); + if (rc) + CAM_ERR(CAM_FD, "Error in event cb handling %d", rc); + } + + /* + * Now we can set hw device is free to process further frames. + * Note - Do not change state to IDLE until we read the frame results, + * Otherwise, other thread may schedule frame processing before + * reading current frame's results. Also, we need to set to IDLE state + * in case some error happens after getting this irq callback + */ + mutex_lock(&hw_device->lock); + hw_device->ready_to_process = true; + hw_device->req_id = -1; + hw_device->cur_hw_ctx = NULL; + CAM_DBG(CAM_FD, "ready_to_process=%d", hw_device->ready_to_process); + mutex_unlock(&hw_device->lock); + +put_req_in_free_list: + rc = cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list, + &frame_req); + if (rc) { + CAM_ERR(CAM_FD, "Failed in putting frame req in free list"); + /* continue */ + } + +submit_next_frame: + /* Check if there are any frames pending for processing and submit */ + rc = cam_fd_mgr_util_submit_frame(hw_mgr, NULL); + if (rc) { + CAM_ERR(CAM_FD, "Error while submit frame, rc=%d", rc); + return rc; + } + + return rc; +} + +static int cam_fd_mgr_irq_cb(void *data, enum cam_fd_hw_irq_type irq_type) +{ + struct cam_fd_hw_mgr *hw_mgr = &g_fd_hw_mgr; + int rc = 0; + unsigned long flags; + struct crm_workq_task *task; + struct cam_fd_mgr_work_data *work_data; + + spin_lock_irqsave(&hw_mgr->hw_mgr_slock, flags); + task = cam_req_mgr_workq_get_task(hw_mgr->work); + if (!task) { + CAM_ERR(CAM_FD, "no empty task available"); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_slock, flags); + return -ENOMEM; + } + + work_data = (struct cam_fd_mgr_work_data *)task->payload; + work_data->type = CAM_FD_WORK_IRQ; + work_data->irq_type = irq_type; + + task->process_cb = cam_fd_mgr_workq_irq_cb; + rc = cam_req_mgr_workq_enqueue_task(task, hw_mgr, CRM_TASK_PRIORITY_0); + if (rc) + CAM_ERR(CAM_FD, "Failed in enqueue work task, rc=%d", rc); + + spin_unlock_irqrestore(&hw_mgr->hw_mgr_slock, flags); + + return rc; +} + +static int cam_fd_mgr_hw_get_caps(void *hw_mgr_priv, void *hw_get_caps_args) +{ + int rc = 0; + struct cam_fd_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query = hw_get_caps_args; + struct cam_fd_query_cap_cmd query_fd; + void __user *caps_handle = + u64_to_user_ptr(query->caps_handle); + + if (copy_from_user(&query_fd, caps_handle, + sizeof(struct cam_fd_query_cap_cmd))) { + CAM_ERR(CAM_FD, "Failed in copy from user, rc=%d", rc); + return -EFAULT; + } + + query_fd = hw_mgr->fd_caps; + + CAM_DBG(CAM_FD, + "IOMMU device(%d, %d), CDM(%d, %d), versions %d.%d, %d.%d", + query_fd.device_iommu.secure, query_fd.device_iommu.non_secure, + query_fd.cdm_iommu.secure, query_fd.cdm_iommu.non_secure, + query_fd.hw_caps.core_version.major, + query_fd.hw_caps.core_version.minor, + query_fd.hw_caps.wrapper_version.major, + query_fd.hw_caps.wrapper_version.minor); + + if (copy_to_user(caps_handle, &query_fd, + sizeof(struct cam_fd_query_cap_cmd))) + rc = -EFAULT; + + return rc; +} + +static int cam_fd_mgr_hw_acquire(void *hw_mgr_priv, void *hw_acquire_args) +{ + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_hw_acquire_args *acquire_args = + (struct cam_hw_acquire_args *)hw_acquire_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_acquire_dev_info fd_acquire_args; + int rc; + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_FD, "Invalid acquire args %pK", acquire_args); + return -EINVAL; + } + + if (copy_from_user(&fd_acquire_args, + (void __user *)acquire_args->acquire_info, + sizeof(struct cam_fd_acquire_dev_info))) { + CAM_ERR(CAM_FD, "Copy from user failed"); + return -EFAULT; + } + + CAM_DBG(CAM_FD, "Acquire : mode=%d, get_raw_results=%d, priority=%d", + fd_acquire_args.mode, fd_acquire_args.get_raw_results, + fd_acquire_args.priority); + + /* get a free fd hw mgr ctx */ + rc = cam_fd_mgr_util_get_ctx(&hw_mgr->free_ctx_list, &hw_ctx); + if (rc || !hw_ctx) { + CAM_ERR(CAM_FD, "Get hw context failed, rc=%d, hw_ctx=%pK", + rc, hw_ctx); + return -EINVAL; + } + + if (fd_acquire_args.get_raw_results && !hw_mgr->raw_results_available) { + CAM_ERR(CAM_FD, "HW cannot support raw results %d (%d)", + fd_acquire_args.get_raw_results, + hw_mgr->raw_results_available); + goto put_ctx; + } + + if (!(fd_acquire_args.mode & hw_mgr->supported_modes)) { + CAM_ERR(CAM_FD, "HW cannot support requested mode 0x%x (0x%x)", + fd_acquire_args.mode, hw_mgr->supported_modes); + rc = -EPERM; + goto put_ctx; + } + + rc = cam_fd_mgr_util_select_device(hw_mgr, hw_ctx, &fd_acquire_args); + if (rc) { + CAM_ERR(CAM_FD, "Failed in selecting device, rc=%d", rc); + goto put_ctx; + } + + hw_ctx->ctx_in_use = true; + hw_ctx->hw_mgr = hw_mgr; + hw_ctx->get_raw_results = fd_acquire_args.get_raw_results; + hw_ctx->mode = fd_acquire_args.mode; + + /* Save incoming cam core info into hw ctx*/ + hw_ctx->cb_priv = acquire_args->context_data; + hw_ctx->event_cb = acquire_args->event_cb; + + /* Update out args */ + acquire_args->ctxt_to_hw_map = hw_ctx; + + cam_fd_mgr_util_put_ctx(&hw_mgr->used_ctx_list, &hw_ctx); + + return 0; +put_ctx: + list_del_init(&hw_ctx->list); + cam_fd_mgr_util_put_ctx(&hw_mgr->free_ctx_list, &hw_ctx); + return rc; +} + +static int cam_fd_mgr_hw_release(void *hw_mgr_priv, void *hw_release_args) +{ + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_hw_release_args *release_args = hw_release_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + int rc; + + if (!hw_mgr_priv || !hw_release_args) { + CAM_ERR(CAM_FD, "Invalid arguments %pK, %pK", + hw_mgr_priv, hw_release_args); + return -EINVAL; + } + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)release_args->ctxt_to_hw_map; + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + + rc = cam_fd_mgr_util_release_device(hw_mgr, hw_ctx); + if (rc) + CAM_ERR(CAM_FD, "Failed in release device, rc=%d", rc); + + hw_ctx->ctx_in_use = false; + list_del_init(&hw_ctx->list); + cam_fd_mgr_util_put_ctx(&hw_mgr->free_ctx_list, &hw_ctx); + + return 0; +} + +static int cam_fd_mgr_hw_start(void *hw_mgr_priv, void *mgr_start_args) +{ + int rc = 0; + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_hw_start_args *hw_mgr_start_args = + (struct cam_hw_start_args *)mgr_start_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_device *hw_device; + struct cam_fd_hw_init_args hw_init_args; + + if (!hw_mgr_priv || !hw_mgr_start_args) { + CAM_ERR(CAM_FD, "Invalid arguments %pK %pK", + hw_mgr_priv, hw_mgr_start_args); + return -EINVAL; + } + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)hw_mgr_start_args->ctxt_to_hw_map; + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + + CAM_DBG(CAM_FD, "ctx index=%u, device_index=%d", hw_ctx->ctx_index, + hw_ctx->device_index); + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + if (hw_device->hw_intf->hw_ops.init) { + hw_init_args.hw_ctx = hw_ctx; + hw_init_args.ctx_hw_private = hw_ctx->ctx_hw_private; + rc = hw_device->hw_intf->hw_ops.init( + hw_device->hw_intf->hw_priv, &hw_init_args, + sizeof(hw_init_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HW Init %d", rc); + return rc; + } + } else { + CAM_ERR(CAM_FD, "Invalid init function"); + return -EINVAL; + } + + return rc; +} + +static int cam_fd_mgr_hw_flush_req(void *hw_mgr_priv, + struct cam_hw_flush_args *flush_args) +{ + int rc = 0; + struct cam_fd_mgr_frame_request *frame_req, *req_temp, *flush_req; + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_fd_device *hw_device; + struct cam_fd_hw_stop_args hw_stop_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + uint32_t i = 0; + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)flush_args->ctxt_to_hw_map; + + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + CAM_DBG(CAM_FD, "ctx index=%u, hw_ctx=%d", hw_ctx->ctx_index, + hw_ctx->device_index); + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + mutex_lock(&hw_mgr->frame_req_mutex); + for (i = 0; i < flush_args->num_req_active; i++) { + flush_req = (struct cam_fd_mgr_frame_request *) + flush_args->flush_req_active[i]; + + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_pending_list_high, list) { + if (frame_req->hw_ctx != hw_ctx) + continue; + + if (frame_req->request_id != flush_req->request_id) + continue; + + list_del_init(&frame_req->list); + break; + } + + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_pending_list_normal, list) { + if (frame_req->hw_ctx != hw_ctx) + continue; + + if (frame_req->request_id != flush_req->request_id) + continue; + + list_del_init(&frame_req->list); + break; + } + + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_processing_list, list) { + if (frame_req->hw_ctx != hw_ctx) + continue; + + if (frame_req->request_id != flush_req->request_id) + continue; + + list_del_init(&frame_req->list); + + mutex_lock(&hw_device->lock); + if ((hw_device->ready_to_process == true) || + (hw_device->cur_hw_ctx != hw_ctx)) + goto unlock_dev_flush_req; + + if (hw_device->hw_intf->hw_ops.stop) { + hw_stop_args.hw_ctx = hw_ctx; + rc = hw_device->hw_intf->hw_ops.stop( + hw_device->hw_intf->hw_priv, + &hw_stop_args, + sizeof(hw_stop_args)); + if (rc) { + CAM_ERR(CAM_FD, + "Failed in HW Stop %d", rc); + goto unlock_dev_flush_req; + } + hw_device->ready_to_process = true; + } + +unlock_dev_flush_req: + mutex_unlock(&hw_device->lock); + break; + } + } + mutex_unlock(&hw_mgr->frame_req_mutex); + + 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_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list, + &flush_req); + } + + return rc; +} + +static int cam_fd_mgr_hw_flush_ctx(void *hw_mgr_priv, + struct cam_hw_flush_args *flush_args) +{ + int rc = 0; + struct cam_fd_mgr_frame_request *frame_req, *req_temp, *flush_req; + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_fd_device *hw_device; + struct cam_fd_hw_stop_args hw_stop_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + uint32_t i = 0; + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)flush_args->ctxt_to_hw_map; + + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + CAM_DBG(CAM_FD, "ctx index=%u, hw_ctx=%d", hw_ctx->ctx_index, + hw_ctx->device_index); + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + mutex_lock(&hw_mgr->frame_req_mutex); + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_pending_list_high, list) { + if (frame_req->hw_ctx != hw_ctx) + continue; + + list_del_init(&frame_req->list); + } + + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_pending_list_normal, list) { + if (frame_req->hw_ctx != hw_ctx) + continue; + + list_del_init(&frame_req->list); + } + + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_processing_list, list) { + if (frame_req->hw_ctx != hw_ctx) + continue; + + list_del_init(&frame_req->list); + mutex_lock(&hw_device->lock); + if ((hw_device->ready_to_process == true) || + (hw_device->cur_hw_ctx != hw_ctx)) + goto unlock_dev_flush_ctx; + + if (hw_device->hw_intf->hw_ops.stop) { + hw_stop_args.hw_ctx = hw_ctx; + rc = hw_device->hw_intf->hw_ops.stop( + hw_device->hw_intf->hw_priv, &hw_stop_args, + sizeof(hw_stop_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HW Stop %d", rc); + goto unlock_dev_flush_ctx; + } + hw_device->ready_to_process = true; + } + +unlock_dev_flush_ctx: + mutex_unlock(&hw_device->lock); + } + mutex_unlock(&hw_mgr->frame_req_mutex); + + 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); + } + + return rc; +} + +static int cam_fd_mgr_hw_flush(void *hw_mgr_priv, + void *hw_flush_args) +{ + int rc = 0; + struct cam_hw_flush_args *flush_args = + (struct cam_hw_flush_args *)hw_flush_args; + + if (!hw_mgr_priv || !hw_flush_args) { + CAM_ERR(CAM_FD, "Invalid arguments %pK %pK", + hw_mgr_priv, hw_flush_args); + return -EINVAL; + } + + switch (flush_args->flush_type) { + case CAM_FLUSH_TYPE_REQ: + rc = cam_fd_mgr_hw_flush_req(hw_mgr_priv, flush_args); + break; + case CAM_FLUSH_TYPE_ALL: + rc = cam_fd_mgr_hw_flush_ctx(hw_mgr_priv, flush_args); + break; + default: + rc = -EINVAL; + CAM_ERR(CAM_FD, "Invalid flush type %d", + flush_args->flush_type); + break; + } + return rc; +} + +static int cam_fd_mgr_hw_stop(void *hw_mgr_priv, void *mgr_stop_args) +{ + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_hw_stop_args *hw_mgr_stop_args = + (struct cam_hw_stop_args *)mgr_stop_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_device *hw_device; + struct cam_fd_hw_deinit_args hw_deinit_args; + int rc = 0; + + if (!hw_mgr_priv || !hw_mgr_stop_args) { + CAM_ERR(CAM_FD, "Invalid arguments %pK %pK", + hw_mgr_priv, hw_mgr_stop_args); + return -EINVAL; + } + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)hw_mgr_stop_args->ctxt_to_hw_map; + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + CAM_DBG(CAM_FD, "ctx index=%u, hw_ctx=%d", hw_ctx->ctx_index, + hw_ctx->device_index); + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + CAM_DBG(CAM_FD, "FD Device ready_to_process = %d", + hw_device->ready_to_process); + + if (hw_device->hw_intf->hw_ops.deinit) { + hw_deinit_args.hw_ctx = hw_ctx; + hw_deinit_args.ctx_hw_private = hw_ctx->ctx_hw_private; + rc = hw_device->hw_intf->hw_ops.deinit( + hw_device->hw_intf->hw_priv, &hw_deinit_args, + sizeof(hw_deinit_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HW DeInit %d", rc); + return rc; + } + } + + return rc; +} + +static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv, + void *hw_prepare_update_args) +{ + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_hw_prepare_update_args *prepare = + (struct cam_hw_prepare_update_args *) hw_prepare_update_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_device *hw_device; + struct cam_kmd_buf_info kmd_buf; + int rc; + struct cam_fd_hw_cmd_prestart_args prestart_args; + struct cam_fd_mgr_frame_request *frame_req; + + if (!hw_mgr_priv || !hw_prepare_update_args) { + CAM_ERR(CAM_FD, "Invalid args %pK %pK", + hw_mgr_priv, hw_prepare_update_args); + return -EINVAL; + } + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)prepare->ctxt_to_hw_map; + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + goto error; + } + + 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; + } + + rc = cam_packet_util_get_kmd_buffer(prepare->packet, &kmd_buf); + if (rc) { + CAM_ERR(CAM_FD, "Error in get kmd buf buffer %d", rc); + goto error; + } + + CAM_DBG(CAM_FD, + "KMD Buf : hdl=%d, cpu_addr=%pK, offset=%d, size=%d, used=%d", + kmd_buf.handle, kmd_buf.cpu_addr, kmd_buf.offset, + kmd_buf.size, kmd_buf.used_bytes); + + /* We do not expect any patching, but just do it anyway */ + rc = cam_packet_util_process_patches(prepare->packet, + hw_mgr->device_iommu.non_secure, -1); + if (rc) { + CAM_ERR(CAM_FD, "Patch FD packet failed, rc=%d", rc); + return rc; + } + + memset(&prestart_args, 0x0, sizeof(prestart_args)); + prestart_args.ctx_hw_private = hw_ctx->ctx_hw_private; + prestart_args.hw_ctx = hw_ctx; + prestart_args.request_id = prepare->packet->header.request_id; + + rc = cam_fd_mgr_util_parse_generic_cmd_buffer(hw_ctx, prepare->packet, + &prestart_args); + if (rc) { + CAM_ERR(CAM_FD, "Error in parsing gerneric cmd buffer %d", rc); + goto error; + } + + rc = cam_fd_mgr_util_prepare_io_buf_info( + hw_mgr->device_iommu.non_secure, prepare, + prestart_args.input_buf, prestart_args.output_buf, + CAM_FD_MAX_IO_BUFFERS); + if (rc) { + CAM_ERR(CAM_FD, "Error in prepare IO Buf %d", rc); + goto error; + } + + rc = cam_fd_mgr_util_prepare_hw_update_entries(hw_mgr, prepare, + &prestart_args, &kmd_buf); + if (rc) { + CAM_ERR(CAM_FD, "Error in hw update entries %d", rc); + goto error; + } + + /* get a free frame req from free list */ + rc = cam_fd_mgr_util_get_frame_req(&hw_mgr->frame_free_list, + &frame_req); + if (rc || !frame_req) { + CAM_ERR(CAM_FD, "Get frame_req failed, rc=%d, hw_ctx=%pK", + rc, hw_ctx); + return -ENOMEM; + } + + /* Setup frame request info and queue to pending list */ + frame_req->hw_ctx = hw_ctx; + frame_req->request_id = prepare->packet->header.request_id; + /* This has to be passed to HW while calling hw_ops->start */ + frame_req->hw_req_private = prestart_args.hw_req_private; + + /* + * Save the current frame_req into priv, + * this will come as priv while hw_config + */ + prepare->priv = frame_req; + + CAM_DBG(CAM_FD, "FramePrepare : Frame[%lld]", frame_req->request_id); + + return 0; +error: + return rc; +} + +static int cam_fd_mgr_hw_config(void *hw_mgr_priv, void *hw_config_args) +{ + struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + struct cam_hw_config_args *config = + (struct cam_hw_config_args *) hw_config_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_mgr_frame_request *frame_req; + int rc; + int i; + + if (!hw_mgr || !config) { + CAM_ERR(CAM_FD, "Invalid arguments %pK %pK", hw_mgr, config); + return -EINVAL; + } + + if (!config->num_hw_update_entries) { + CAM_ERR(CAM_FD, "No hw update enteries are available"); + return -EINVAL; + } + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)config->ctxt_to_hw_map; + if (!hw_ctx || !hw_ctx->ctx_in_use) { + CAM_ERR(CAM_FD, "Invalid context is used, hw_ctx=%pK", hw_ctx); + return -EPERM; + } + + frame_req = config->priv; + + trace_cam_apply_req("FD", frame_req->request_id); + CAM_DBG(CAM_FD, "FrameHWConfig : Frame[%lld]", frame_req->request_id); + + frame_req->num_hw_update_entries = config->num_hw_update_entries; + for (i = 0; i < config->num_hw_update_entries; i++) { + frame_req->hw_update_entries[i] = config->hw_update_entries[i]; + CAM_DBG(CAM_FD, "PreStart HWEntry[%d] : %d %d %d %d %pK", + frame_req->hw_update_entries[i].handle, + frame_req->hw_update_entries[i].offset, + frame_req->hw_update_entries[i].len, + frame_req->hw_update_entries[i].flags, + frame_req->hw_update_entries[i].addr); + } + + if (hw_ctx->priority == CAM_FD_PRIORITY_HIGH) { + CAM_DBG(CAM_FD, "Insert frame into prio0 queue"); + rc = cam_fd_mgr_util_put_frame_req( + &hw_mgr->frame_pending_list_high, &frame_req); + } else { + CAM_DBG(CAM_FD, "Insert frame into prio1 queue"); + rc = cam_fd_mgr_util_put_frame_req( + &hw_mgr->frame_pending_list_normal, &frame_req); + } + if (rc) { + CAM_ERR(CAM_FD, "Failed in queuing frame req, rc=%d", rc); + goto put_free_list; + } + + rc = cam_fd_mgr_util_schedule_frame_worker_task(hw_mgr); + if (rc) { + CAM_ERR(CAM_FD, "Worker task scheduling failed %d", rc); + goto remove_and_put_free_list; + } + + return 0; + +remove_and_put_free_list: + + if (hw_ctx->priority == CAM_FD_PRIORITY_HIGH) { + CAM_DBG(CAM_FD, "Removing frame into prio0 queue"); + cam_fd_mgr_util_get_frame_req( + &hw_mgr->frame_pending_list_high, &frame_req); + } else { + CAM_DBG(CAM_FD, "Removing frame into prio1 queue"); + cam_fd_mgr_util_get_frame_req( + &hw_mgr->frame_pending_list_normal, &frame_req); + } +put_free_list: + cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list, + &frame_req); + + return rc; +} + +int cam_fd_hw_mgr_deinit(struct device_node *of_node) +{ + CAM_DBG(CAM_FD, "HW Mgr Deinit"); + + cam_req_mgr_workq_destroy(&g_fd_hw_mgr.work); + + cam_smmu_destroy_handle(g_fd_hw_mgr.device_iommu.non_secure); + g_fd_hw_mgr.device_iommu.non_secure = -1; + + mutex_destroy(&g_fd_hw_mgr.ctx_mutex); + mutex_destroy(&g_fd_hw_mgr.frame_req_mutex); + mutex_destroy(&g_fd_hw_mgr.hw_mgr_mutex); + + return 0; +} + +int cam_fd_hw_mgr_init(struct device_node *of_node, + struct cam_hw_mgr_intf *hw_mgr_intf) +{ + int count, i, rc = 0; + struct cam_hw_intf *hw_intf = NULL; + struct cam_fd_hw_mgr_ctx *hw_mgr_ctx; + struct cam_fd_device *hw_device; + struct cam_fd_mgr_frame_request *frame_req; + + if (!of_node || !hw_mgr_intf) { + CAM_ERR(CAM_FD, "Invalid args of_node %pK hw_mgr_intf %pK", + of_node, hw_mgr_intf); + return -EINVAL; + } + + memset(&g_fd_hw_mgr, 0x0, sizeof(g_fd_hw_mgr)); + memset(hw_mgr_intf, 0x0, sizeof(*hw_mgr_intf)); + + mutex_init(&g_fd_hw_mgr.ctx_mutex); + mutex_init(&g_fd_hw_mgr.frame_req_mutex); + mutex_init(&g_fd_hw_mgr.hw_mgr_mutex); + spin_lock_init(&g_fd_hw_mgr.hw_mgr_slock); + + count = of_property_count_strings(of_node, "compat-hw-name"); + if (!count || (count > CAM_FD_HW_MAX)) { + CAM_ERR(CAM_FD, "Invalid compat names in dev tree %d", count); + return -EINVAL; + } + g_fd_hw_mgr.num_devices = count; + + g_fd_hw_mgr.raw_results_available = false; + g_fd_hw_mgr.supported_modes = 0; + + for (i = 0; i < count; i++) { + hw_device = &g_fd_hw_mgr.hw_device[i]; + + rc = cam_fd_mgr_util_pdev_get_hw_intf(of_node, i, &hw_intf); + if (rc) { + CAM_ERR(CAM_FD, "hw intf from pdev failed, rc=%d", rc); + return rc; + } + + mutex_init(&hw_device->lock); + + hw_device->valid = true; + hw_device->hw_intf = hw_intf; + hw_device->ready_to_process = true; + + if (hw_device->hw_intf->hw_ops.process_cmd) { + struct cam_fd_hw_cmd_set_irq_cb irq_cb_args; + + irq_cb_args.cam_fd_hw_mgr_cb = cam_fd_mgr_irq_cb; + irq_cb_args.data = hw_device; + + rc = hw_device->hw_intf->hw_ops.process_cmd( + hw_device->hw_intf->hw_priv, + CAM_FD_HW_CMD_REGISTER_CALLBACK, + &irq_cb_args, sizeof(irq_cb_args)); + if (rc) { + CAM_ERR(CAM_FD, + "Failed in REGISTER_CALLBACK %d", rc); + return rc; + } + } + + if (hw_device->hw_intf->hw_ops.get_hw_caps) { + rc = hw_device->hw_intf->hw_ops.get_hw_caps( + hw_intf->hw_priv, &hw_device->hw_caps, + sizeof(hw_device->hw_caps)); + if (rc) { + CAM_ERR(CAM_FD, "Failed in get_hw_caps %d", rc); + return rc; + } + + g_fd_hw_mgr.raw_results_available |= + hw_device->hw_caps.raw_results_available; + g_fd_hw_mgr.supported_modes |= + hw_device->hw_caps.supported_modes; + + CAM_DBG(CAM_FD, + "Device[mode=%d, raw=%d], Mgr[mode=%d, raw=%d]", + hw_device->hw_caps.supported_modes, + hw_device->hw_caps.raw_results_available, + g_fd_hw_mgr.supported_modes, + g_fd_hw_mgr.raw_results_available); + } + } + + INIT_LIST_HEAD(&g_fd_hw_mgr.free_ctx_list); + INIT_LIST_HEAD(&g_fd_hw_mgr.used_ctx_list); + INIT_LIST_HEAD(&g_fd_hw_mgr.frame_free_list); + INIT_LIST_HEAD(&g_fd_hw_mgr.frame_pending_list_high); + INIT_LIST_HEAD(&g_fd_hw_mgr.frame_pending_list_normal); + INIT_LIST_HEAD(&g_fd_hw_mgr.frame_processing_list); + + g_fd_hw_mgr.device_iommu.non_secure = -1; + g_fd_hw_mgr.device_iommu.secure = -1; + g_fd_hw_mgr.cdm_iommu.non_secure = -1; + g_fd_hw_mgr.cdm_iommu.secure = -1; + + rc = cam_smmu_get_handle("fd", + &g_fd_hw_mgr.device_iommu.non_secure); + if (rc) { + CAM_ERR(CAM_FD, "Get iommu handle failed, rc=%d", rc); + goto destroy_mutex; + } + + rc = cam_cdm_get_iommu_handle("fd", &g_fd_hw_mgr.cdm_iommu); + if (rc) + CAM_DBG(CAM_FD, "Failed to acquire the CDM iommu handles"); + + CAM_DBG(CAM_FD, "iommu handles : device(%d, %d), cdm(%d, %d)", + g_fd_hw_mgr.device_iommu.non_secure, + g_fd_hw_mgr.device_iommu.secure, + g_fd_hw_mgr.cdm_iommu.non_secure, + g_fd_hw_mgr.cdm_iommu.secure); + + /* Init hw mgr contexts and add to free list */ + for (i = 0; i < CAM_CTX_MAX; i++) { + hw_mgr_ctx = &g_fd_hw_mgr.ctx_pool[i]; + + memset(hw_mgr_ctx, 0x0, sizeof(*hw_mgr_ctx)); + INIT_LIST_HEAD(&hw_mgr_ctx->list); + + hw_mgr_ctx->ctx_index = i; + hw_mgr_ctx->device_index = -1; + hw_mgr_ctx->hw_mgr = &g_fd_hw_mgr; + + list_add_tail(&hw_mgr_ctx->list, &g_fd_hw_mgr.free_ctx_list); + } + + /* Init hw mgr frame requests and add to free list */ + for (i = 0; i < CAM_CTX_REQ_MAX; i++) { + frame_req = &g_fd_hw_mgr.frame_req[i]; + + memset(frame_req, 0x0, sizeof(*frame_req)); + INIT_LIST_HEAD(&frame_req->list); + + list_add_tail(&frame_req->list, &g_fd_hw_mgr.frame_free_list); + } + + rc = cam_req_mgr_workq_create("cam_fd_worker", CAM_FD_WORKQ_NUM_TASK, + &g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_FD, "Unable to create a worker, rc=%d", rc); + goto detach_smmu; + } + + for (i = 0; i < CAM_FD_WORKQ_NUM_TASK; i++) + g_fd_hw_mgr.work->task.pool[i].payload = + &g_fd_hw_mgr.work_data[i]; + + /* Setup hw cap so that we can just return the info when requested */ + memset(&g_fd_hw_mgr.fd_caps, 0, sizeof(g_fd_hw_mgr.fd_caps)); + g_fd_hw_mgr.fd_caps.device_iommu = g_fd_hw_mgr.device_iommu; + g_fd_hw_mgr.fd_caps.cdm_iommu = g_fd_hw_mgr.cdm_iommu; + g_fd_hw_mgr.fd_caps.hw_caps = g_fd_hw_mgr.hw_device[0].hw_caps; + + CAM_DBG(CAM_FD, + "IOMMU device(%d, %d), CDM(%d, %d) versions core[%d.%d], wrapper[%d.%d]", + g_fd_hw_mgr.fd_caps.device_iommu.secure, + g_fd_hw_mgr.fd_caps.device_iommu.non_secure, + g_fd_hw_mgr.fd_caps.cdm_iommu.secure, + g_fd_hw_mgr.fd_caps.cdm_iommu.non_secure, + g_fd_hw_mgr.fd_caps.hw_caps.core_version.major, + g_fd_hw_mgr.fd_caps.hw_caps.core_version.minor, + g_fd_hw_mgr.fd_caps.hw_caps.wrapper_version.major, + g_fd_hw_mgr.fd_caps.hw_caps.wrapper_version.minor); + + hw_mgr_intf->hw_mgr_priv = &g_fd_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_fd_mgr_hw_get_caps; + hw_mgr_intf->hw_acquire = cam_fd_mgr_hw_acquire; + hw_mgr_intf->hw_release = cam_fd_mgr_hw_release; + hw_mgr_intf->hw_start = cam_fd_mgr_hw_start; + hw_mgr_intf->hw_stop = cam_fd_mgr_hw_stop; + hw_mgr_intf->hw_prepare_update = cam_fd_mgr_hw_prepare_update; + hw_mgr_intf->hw_config = cam_fd_mgr_hw_config; + hw_mgr_intf->hw_read = NULL; + hw_mgr_intf->hw_write = NULL; + hw_mgr_intf->hw_close = NULL; + hw_mgr_intf->hw_flush = cam_fd_mgr_hw_flush; + + return rc; + +detach_smmu: + cam_smmu_destroy_handle(g_fd_hw_mgr.device_iommu.non_secure); + g_fd_hw_mgr.device_iommu.non_secure = -1; +destroy_mutex: + mutex_destroy(&g_fd_hw_mgr.ctx_mutex); + mutex_destroy(&g_fd_hw_mgr.frame_req_mutex); + mutex_destroy(&g_fd_hw_mgr.hw_mgr_mutex); + + return rc; +} diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h new file mode 100644 index 000000000000..351cae971a42 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_MGR_H_ +#define _CAM_FD_HW_MGR_H_ + +#include +#include + +#include +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "cam_hw_mgr_intf.h" +#include "cam_req_mgr_workq.h" +#include "cam_fd_hw_intf.h" + +#define CAM_FD_HW_MAX 1 +#define CAM_FD_WORKQ_NUM_TASK 10 + +struct cam_fd_hw_mgr; + +/** + * enum cam_fd_mgr_work_type - Type of worker task + * + * @CAM_FD_WORK_FRAME : Work type indicating frame task + * @CAM_FD_WORK_IRQ : Work type indicating irq task + */ +enum cam_fd_mgr_work_type { + CAM_FD_WORK_FRAME, + CAM_FD_WORK_IRQ, +}; + +/** + * struct cam_fd_hw_mgr_ctx : FD HW Mgr context + * + * @list : List pointer used to maintain this context + * in free, used list + * @ctx_index : Index of this context + * @ctx_in_use : Whether this context is in use + * @event_cb : Event callback pointer to notify cam core context + * @cb_priv : Event callback private pointer + * @hw_mgr : Pointer to hw manager + * @get_raw_results : Whether this context needs raw results + * @mode : Mode in which this context runs + * @device_index : HW Device used by this context + * @ctx_hw_private : HW layer's private context pointer for this context + * @priority : Priority of this context + */ +struct cam_fd_hw_mgr_ctx { + struct list_head list; + uint32_t ctx_index; + bool ctx_in_use; + cam_hw_event_cb_func event_cb; + void *cb_priv; + struct cam_fd_hw_mgr *hw_mgr; + bool get_raw_results; + enum cam_fd_hw_mode mode; + int32_t device_index; + void *ctx_hw_private; + uint32_t priority; +}; + +/** + * struct cam_fd_device : FD HW Device + * + * @hw_caps : This FD device's capabilities + * @hw_intf : FD device's interface information + * @ready_to_process : Whether this device is ready to process next frame + * @num_ctxts : Number of context currently running on this device + * @valid : Whether this device is valid + * @lock : Lock used for protectin + * @cur_hw_ctx : current hw context running in the device + * @req_id : current processing req id + */ +struct cam_fd_device { + struct cam_fd_hw_caps hw_caps; + struct cam_hw_intf *hw_intf; + bool ready_to_process; + uint32_t num_ctxts; + bool valid; + struct mutex lock; + struct cam_fd_hw_mgr_ctx *cur_hw_ctx; + int64_t req_id; +}; + +/** + * struct cam_fd_mgr_frame_request : Frame request information maintained + * in HW Mgr layer + * + * @list : List pointer used to maintain this request in + * free, pending, processing request lists + * @request_id : Request ID corresponding to this request + * @hw_ctx : HW context from which this request is coming + * @hw_req_private : HW layer's private information specific to + * this request + * @hw_update_entries : HW update entries corresponding to this request + * which needs to be submitted to HW through CDM + * @num_hw_update_entries : Number of HW update entries + */ +struct cam_fd_mgr_frame_request { + struct list_head list; + uint64_t request_id; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_hw_req_private hw_req_private; + struct cam_hw_update_entry hw_update_entries[CAM_FD_MAX_HW_ENTRIES]; + uint32_t num_hw_update_entries; +}; + +/** + * struct cam_fd_mgr_work_data : HW Mgr work data information + * + * @type : Type of work + * @irq_type : IRQ type when this work is queued because of irq callback + */ +struct cam_fd_mgr_work_data { + enum cam_fd_mgr_work_type type; + enum cam_fd_hw_irq_type irq_type; +}; + +/** + * struct cam_fd_hw_mgr : FD HW Mgr information + * + * @free_ctx_list : List of free contexts available for acquire + * @used_ctx_list : List of contexts that are acquired + * @frame_free_list : List of free frame requests available + * @frame_pending_list_high : List of high priority frame requests pending + * for processing + * @frame_pending_list_normal : List of normal priority frame requests pending + * for processing + * @frame_processing_list : List of frame requests currently being + * processed currently. Generally maximum one + * request would be present in this list + * @hw_mgr_mutex : Mutex to protect hw mgr data when accessed + * from multiple threads + * @hw_mgr_slock : Spin lock to protect hw mgr data when accessed + * from multiple threads + * @ctx_mutex : Mutex to protect context list + * @frame_req_mutex : Mutex to protect frame request list + * @device_iommu : Device IOMMU information + * @cdm_iommu : CDM IOMMU information + * @hw_device : Underlying HW device information + * @num_devices : Number of HW devices available + * @raw_results_available : Whether raw results available in this driver + * @supported_modes : Supported modes by this driver + * @ctx_pool : List of context + * @frame_req : List of frame requests + * @work : Worker handle + * @work_data : Worker data + * @fd_caps : FD driver capabilities + */ +struct cam_fd_hw_mgr { + struct list_head free_ctx_list; + struct list_head used_ctx_list; + struct list_head frame_free_list; + struct list_head frame_pending_list_high; + struct list_head frame_pending_list_normal; + struct list_head frame_processing_list; + struct mutex hw_mgr_mutex; + spinlock_t hw_mgr_slock; + struct mutex ctx_mutex; + struct mutex frame_req_mutex; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + struct cam_fd_device hw_device[CAM_FD_HW_MAX]; + uint32_t num_devices; + bool raw_results_available; + uint32_t supported_modes; + struct cam_fd_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; + struct cam_fd_mgr_frame_request frame_req[CAM_CTX_REQ_MAX]; + struct cam_req_mgr_core_workq *work; + struct cam_fd_mgr_work_data work_data[CAM_FD_WORKQ_NUM_TASK]; + struct cam_fd_query_cap_cmd fd_caps; +}; + +#endif /* _CAM_FD_HW_MGR_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr_intf.h b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr_intf.h new file mode 100644 index 000000000000..81ed464e400a --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr_intf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_MGR_INTF_H_ +#define _CAM_FD_HW_MGR_INTF_H_ + +#include + +#include "cam_debug_util.h" +#include "cam_hw_mgr_intf.h" + +int cam_fd_hw_mgr_init(struct device_node *of_node, + struct cam_hw_mgr_intf *hw_mgr_intf); +int cam_fd_hw_mgr_deinit(struct device_node *of_node); + +#endif /* _CAM_FD_HW_MGR_INTF_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile b/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile new file mode 100644 index 000000000000..fd43ca7a4546 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr/fd_hw +ccflags-y += -I$(srctree)/techpack/camera +ccflags-y += -I$(srctree)/techpack/camera/drivers/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/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c new file mode 100644 index 000000000000..c28fcdf3efc6 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -0,0 +1,1164 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_fd_hw_core.h" +#include "cam_fd_hw_soc.h" +#include "cam_trace.h" + +#define CAM_FD_REG_VAL_PAIR_SIZE 256 + +static uint32_t cam_fd_cdm_write_reg_val_pair(uint32_t *buffer, + uint32_t index, uint32_t reg_offset, uint32_t reg_value) +{ + buffer[index++] = reg_offset; + buffer[index++] = reg_value; + + CAM_DBG(CAM_FD, "FD_CDM_CMD: Base[FD_CORE] Offset[0x%8x] Value[0x%8x]", + reg_offset, reg_value); + + return index; +} + +static void cam_fd_hw_util_cdm_callback(uint32_t handle, void *userdata, + enum cam_cdm_cb_status status, uint64_t cookie) +{ + trace_cam_cdm_cb("FD", status); + CAM_DBG(CAM_FD, "CDM hdl=%x, udata=%pK, status=%d, cookie=%llu", + handle, userdata, status, cookie); +} + +static void cam_fd_hw_util_enable_power_on_settings(struct cam_hw_info *fd_hw) +{ + struct cam_hw_soc_info *soc_info = &fd_hw->soc_info; + struct cam_fd_hw_static_info *hw_static_info = + ((struct cam_fd_core *)fd_hw->core_info)->hw_static_info; + + if (hw_static_info->enable_errata_wa.single_irq_only == false) { + /* Enable IRQs here */ + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_mask, + hw_static_info->irq_mask); + } + + /* QoS settings */ + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.vbif_req_priority, + hw_static_info->qos_priority); + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.vbif_priority_level, + hw_static_info->qos_priority_level); +} + +int cam_fd_hw_util_get_hw_caps(struct cam_hw_info *fd_hw, + struct cam_fd_hw_caps *hw_caps) +{ + struct cam_hw_soc_info *soc_info = &fd_hw->soc_info; + struct cam_fd_hw_static_info *hw_static_info = + ((struct cam_fd_core *)fd_hw->core_info)->hw_static_info; + uint32_t reg_value; + + if (!hw_static_info) { + CAM_ERR(CAM_FD, "Invalid hw info data"); + return -EINVAL; + } + + reg_value = cam_fd_soc_register_read(soc_info, CAM_FD_REG_CORE, + hw_static_info->core_regs.version); + hw_caps->core_version.major = + CAM_BITS_MASK_SHIFT(reg_value, 0xf00, 0x8); + hw_caps->core_version.minor = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0, 0x4); + hw_caps->core_version.incr = + CAM_BITS_MASK_SHIFT(reg_value, 0xf, 0x0); + + reg_value = cam_fd_soc_register_read(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.wrapper_version); + hw_caps->wrapper_version.major = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c); + hw_caps->wrapper_version.minor = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->wrapper_version.incr = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + hw_caps->raw_results_available = + hw_static_info->results.raw_results_available; + hw_caps->supported_modes = hw_static_info->supported_modes; + + CAM_DBG(CAM_FD, "core:%d.%d.%d wrapper:%d.%d.%d intermediate:%d", + hw_caps->core_version.major, hw_caps->core_version.minor, + hw_caps->core_version.incr, hw_caps->wrapper_version.major, + hw_caps->wrapper_version.minor, hw_caps->wrapper_version.incr, + hw_caps->raw_results_available); + + return 0; +} + +static int cam_fd_hw_util_fdwrapper_sync_reset(struct cam_hw_info *fd_hw) +{ + struct cam_fd_core *fd_core = (struct cam_fd_core *)fd_hw->core_info; + struct cam_fd_hw_static_info *hw_static_info = fd_core->hw_static_info; + struct cam_hw_soc_info *soc_info = &fd_hw->soc_info; + long time_left; + + /* Before triggering reset to HW, clear the reset complete */ + reinit_completion(&fd_core->reset_complete); + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_CORE, + hw_static_info->core_regs.control, 0x1); + + if (hw_static_info->enable_errata_wa.single_irq_only) { + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_mask, + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE)); + } + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.sw_reset, 0x1); + + time_left = wait_for_completion_timeout(&fd_core->reset_complete, + msecs_to_jiffies(CAM_FD_HW_HALT_RESET_TIMEOUT)); + if (time_left <= 0) + CAM_WARN(CAM_FD, "HW reset timeout time_left=%ld", time_left); + + CAM_DBG(CAM_FD, "FD Wrapper SW Sync Reset complete"); + + return 0; +} + + +static int cam_fd_hw_util_fdwrapper_halt(struct cam_hw_info *fd_hw) +{ + struct cam_fd_core *fd_core = (struct cam_fd_core *)fd_hw->core_info; + struct cam_fd_hw_static_info *hw_static_info = fd_core->hw_static_info; + struct cam_hw_soc_info *soc_info = &fd_hw->soc_info; + long time_left; + + /* Before triggering halt to HW, clear halt complete */ + reinit_completion(&fd_core->halt_complete); + + if (hw_static_info->enable_errata_wa.single_irq_only) { + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_mask, + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE)); + } + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.hw_stop, 0x1); + + time_left = wait_for_completion_timeout(&fd_core->halt_complete, + msecs_to_jiffies(CAM_FD_HW_HALT_RESET_TIMEOUT)); + if (time_left <= 0) + CAM_WARN(CAM_FD, "HW halt timeout time_left=%ld", time_left); + + CAM_DBG(CAM_FD, "FD Wrapper Halt complete"); + + return 0; +} + +static int cam_fd_hw_util_processcmd_prestart(struct cam_hw_info *fd_hw, + struct cam_fd_hw_cmd_prestart_args *prestart_args) +{ + struct cam_hw_soc_info *soc_info = &fd_hw->soc_info; + struct cam_fd_hw_static_info *hw_static_info = + ((struct cam_fd_core *)fd_hw->core_info)->hw_static_info; + struct cam_fd_ctx_hw_private *ctx_hw_private = + prestart_args->ctx_hw_private; + uint32_t size, size_required = 0; + uint32_t mem_base; + uint32_t *cmd_buf_addr = prestart_args->cmd_buf_addr; + uint32_t reg_val_pair[CAM_FD_REG_VAL_PAIR_SIZE]; + uint32_t num_cmds = 0; + int i; + struct cam_fd_hw_io_buffer *io_buf; + struct cam_fd_hw_req_private *req_private; + uint32_t available_size = prestart_args->size; + bool work_buffer_configured = false; + + if (!ctx_hw_private || !cmd_buf_addr) { + CAM_ERR(CAM_FD, "Invalid input prestart args %pK %pK", + ctx_hw_private, cmd_buf_addr); + return -EINVAL; + } + + if (prestart_args->get_raw_results && + !hw_static_info->results.raw_results_available) { + CAM_ERR(CAM_FD, "Raw results not supported %d %d", + prestart_args->get_raw_results, + hw_static_info->results.raw_results_available); + return -EINVAL; + } + + req_private = &prestart_args->hw_req_private; + req_private->ctx_hw_private = prestart_args->ctx_hw_private; + req_private->request_id = prestart_args->request_id; + req_private->get_raw_results = prestart_args->get_raw_results; + req_private->fd_results = NULL; + req_private->raw_results = NULL; + + /* Start preparing CDM register values that KMD has to insert */ + num_cmds = cam_fd_cdm_write_reg_val_pair(reg_val_pair, num_cmds, + hw_static_info->core_regs.control, 0x1); + num_cmds = cam_fd_cdm_write_reg_val_pair(reg_val_pair, num_cmds, + hw_static_info->core_regs.control, 0x0); + + for (i = 0; i < CAM_FD_MAX_IO_BUFFERS; i++) { + io_buf = &prestart_args->input_buf[i]; + + if (io_buf->valid == false) + break; + + if (io_buf->io_cfg->direction != CAM_BUF_INPUT) { + CAM_ERR(CAM_FD, "Incorrect direction %d %d", + io_buf->io_cfg->direction, CAM_BUF_INPUT); + return -EINVAL; + } + + switch (io_buf->io_cfg->resource_type) { + case CAM_FD_INPUT_PORT_ID_IMAGE: { + if ((num_cmds + 2) > CAM_FD_REG_VAL_PAIR_SIZE) { + CAM_ERR(CAM_FD, + "Invalid reg_val pair size %d, %d", + num_cmds, CAM_FD_REG_VAL_PAIR_SIZE); + return -EINVAL; + } + + num_cmds = cam_fd_cdm_write_reg_val_pair( + reg_val_pair, num_cmds, + hw_static_info->core_regs.image_addr, + io_buf->io_addr[0]); + break; + } + default: + CAM_ERR(CAM_FD, "Invalid resource type %d", + io_buf->io_cfg->resource_type); + return -EINVAL; + } + } + + for (i = 0; i < CAM_FD_MAX_IO_BUFFERS; i++) { + io_buf = &prestart_args->output_buf[i]; + + if (io_buf->valid == false) + break; + + if (io_buf->io_cfg->direction != CAM_BUF_OUTPUT) { + CAM_ERR(CAM_FD, "Incorrect direction %d %d", + io_buf->io_cfg->direction, CAM_BUF_INPUT); + return -EINVAL; + } + + switch (io_buf->io_cfg->resource_type) { + case CAM_FD_OUTPUT_PORT_ID_RESULTS: { + uint32_t face_results_offset; + + size_required = hw_static_info->results.max_faces * + hw_static_info->results.per_face_entries * 4; + + if (io_buf->io_cfg->planes[0].plane_stride < + size_required) { + CAM_ERR(CAM_FD, "Invalid results size %d %d", + io_buf->io_cfg->planes[0].plane_stride, + size_required); + return -EINVAL; + } + + req_private->fd_results = + (struct cam_fd_results *)io_buf->cpu_addr[0]; + + face_results_offset = + (uint8_t *)&req_private->fd_results->faces[0] - + (uint8_t *)req_private->fd_results; + + if (hw_static_info->ro_mode_supported) { + if ((num_cmds + 4) > CAM_FD_REG_VAL_PAIR_SIZE) { + CAM_ERR(CAM_FD, + "Invalid reg_val size %d, %d", + num_cmds, + CAM_FD_REG_VAL_PAIR_SIZE); + return -EINVAL; + } + /* + * Face data actually starts 16bytes later in + * the io buffer Check cam_fd_results. + */ + num_cmds = cam_fd_cdm_write_reg_val_pair( + reg_val_pair, num_cmds, + hw_static_info->core_regs.result_addr, + io_buf->io_addr[0] + + face_results_offset); + num_cmds = cam_fd_cdm_write_reg_val_pair( + reg_val_pair, num_cmds, + hw_static_info->core_regs.ro_mode, + 0x1); + + req_private->ro_mode_enabled = true; + } else { + req_private->ro_mode_enabled = false; + } + break; + } + case CAM_FD_OUTPUT_PORT_ID_RAW_RESULTS: { + size_required = + hw_static_info->results.raw_results_entries * + sizeof(uint32_t); + + if (io_buf->io_cfg->planes[0].plane_stride < + size_required) { + CAM_ERR(CAM_FD, "Invalid results size %d %d", + io_buf->io_cfg->planes[0].plane_stride, + size_required); + return -EINVAL; + } + + req_private->raw_results = + (uint32_t *)io_buf->cpu_addr[0]; + break; + } + case CAM_FD_OUTPUT_PORT_ID_WORK_BUFFER: { + if ((num_cmds + 2) > CAM_FD_REG_VAL_PAIR_SIZE) { + CAM_ERR(CAM_FD, + "Invalid reg_val pair size %d, %d", + num_cmds, CAM_FD_REG_VAL_PAIR_SIZE); + return -EINVAL; + } + + num_cmds = cam_fd_cdm_write_reg_val_pair( + reg_val_pair, num_cmds, + hw_static_info->core_regs.work_addr, + io_buf->io_addr[0]); + + work_buffer_configured = true; + break; + } + default: + CAM_ERR(CAM_FD, "Invalid resource type %d", + io_buf->io_cfg->resource_type); + return -EINVAL; + } + } + + if (!req_private->fd_results || !work_buffer_configured) { + CAM_ERR(CAM_FD, "Invalid IO Buffers results=%pK work=%d", + req_private->fd_results, work_buffer_configured); + return -EINVAL; + } + + /* First insert CHANGE_BASE command */ + size = ctx_hw_private->cdm_ops->cdm_required_size_changebase(); + /* since cdm returns dwords, we need to convert it into bytes */ + if ((size * 4) > available_size) { + CAM_ERR(CAM_FD, "buf size:%d is not sufficient, expected: %d", + prestart_args->size, size); + return -EINVAL; + } + + mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE(soc_info, + ((struct cam_fd_soc_private *)soc_info->soc_private)-> + regbase_index[CAM_FD_REG_CORE]); + + ctx_hw_private->cdm_ops->cdm_write_changebase(cmd_buf_addr, mem_base); + cmd_buf_addr += size; + available_size -= (size * 4); + + size = ctx_hw_private->cdm_ops->cdm_required_size_reg_random( + num_cmds/2); + /* cdm util returns dwords, need to convert to bytes */ + if ((size * 4) > available_size) { + CAM_ERR(CAM_FD, "Insufficient size:%d , expected size:%d", + available_size, size); + return -ENOMEM; + } + ctx_hw_private->cdm_ops->cdm_write_regrandom(cmd_buf_addr, num_cmds/2, + reg_val_pair); + cmd_buf_addr += size; + available_size -= (size * 4); + + /* Update pre_config_buf_size in bytes */ + prestart_args->pre_config_buf_size = + prestart_args->size - available_size; + + /* Insert start trigger command into CDM as post config commands. */ + num_cmds = cam_fd_cdm_write_reg_val_pair(reg_val_pair, 0, + hw_static_info->core_regs.control, 0x2); + size = ctx_hw_private->cdm_ops->cdm_required_size_reg_random( + num_cmds/2); + if ((size * 4) > available_size) { + CAM_ERR(CAM_FD, "Insufficient size:%d , expected size:%d", + available_size, size); + return -ENOMEM; + } + ctx_hw_private->cdm_ops->cdm_write_regrandom(cmd_buf_addr, num_cmds/2, + reg_val_pair); + cmd_buf_addr += size; + available_size -= (size * 4); + + prestart_args->post_config_buf_size = size * 4; + + CAM_DBG(CAM_FD, "PreConfig [%pK %d], PostConfig[%pK %d]", + prestart_args->cmd_buf_addr, prestart_args->pre_config_buf_size, + cmd_buf_addr, prestart_args->post_config_buf_size); + + for (i = 0; i < (prestart_args->pre_config_buf_size + + prestart_args->post_config_buf_size) / 4; i++) + CAM_DBG(CAM_FD, "CDM KMD Commands [%d] : [%pK] [0x%x]", i, + &prestart_args->cmd_buf_addr[i], + prestart_args->cmd_buf_addr[i]); + + return 0; +} + +static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw, + struct cam_fd_hw_frame_done_args *frame_done_args) +{ + struct cam_fd_core *fd_core = (struct cam_fd_core *)fd_hw->core_info; + struct cam_fd_hw_static_info *hw_static_info = fd_core->hw_static_info; + struct cam_fd_hw_req_private *req_private; + uint32_t base, face_cnt; + uint32_t *buffer; + 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) || + !fd_core->hw_req_private) { + CAM_ERR(CAM_FD, + "Invalid state for results state=%d, results=%d %pK", + 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; + req_private = fd_core->hw_req_private; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + /* + * Copy the register value as is into output buffers. + * Wehter we are copying the output data by reading registers or + * programming output buffer directly to HW must be transparent to UMD. + * In case HW supports writing face count value directly into + * DDR memory in future, these values should match. + */ + req_private->fd_results->face_count = + cam_fd_soc_register_read(&fd_hw->soc_info, CAM_FD_REG_CORE, + hw_static_info->core_regs.result_cnt); + + face_cnt = req_private->fd_results->face_count & 0x3F; + + if (face_cnt > hw_static_info->results.max_faces) { + CAM_WARN(CAM_FD, "Face count greater than max %d %d", + face_cnt, hw_static_info->results.max_faces); + face_cnt = hw_static_info->results.max_faces; + } + + CAM_DBG(CAM_FD, "ReqID[%lld] Faces Detected = %d", + req_private->request_id, face_cnt); + + /* + * We need to read the face data information from registers only + * if one of below is true + * 1. RO mode is not set. i.e FD HW doesn't write face data into + * DDR memory + * 2. On the current chipset, results written into DDR memory by FD HW + * are not gauranteed to be correct + */ + if (!req_private->ro_mode_enabled || + hw_static_info->enable_errata_wa.ro_mode_results_invalid) { + buffer = (uint32_t *)&req_private->fd_results->faces[0]; + base = hw_static_info->core_regs.results_reg_base; + + /* + * Write register values as is into face data buffer. Its UMD + * driver responsibility to interpret the data and extract face + * properties from output buffer. Think in case output buffer + * is directly programmed to HW, then KMD has no control to + * extract the face properties and UMD anyway has to extract + * face properties. So we follow the same approach and keep + * this transparent to UMD. + */ + for (i = 0; + i < (face_cnt * + hw_static_info->results.per_face_entries); i++) { + *buffer = cam_fd_soc_register_read(&fd_hw->soc_info, + CAM_FD_REG_CORE, base + (i * 0x4)); + CAM_DBG(CAM_FD, "FaceData[%d] : 0x%x", i / 4, *buffer); + buffer++; + } + } + + if (req_private->get_raw_results && + req_private->raw_results && + hw_static_info->results.raw_results_available) { + buffer = req_private->raw_results; + base = hw_static_info->core_regs.raw_results_reg_base; + + for (i = 0; + i < hw_static_info->results.raw_results_entries; + i++) { + *buffer = cam_fd_soc_register_read(&fd_hw->soc_info, + CAM_FD_REG_CORE, base + (i * 0x4)); + CAM_DBG(CAM_FD, "RawData[%d] : 0x%x", i, *buffer); + buffer++; + } + } + + spin_lock_irqsave(&fd_core->spin_lock, flags); + 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; +} + +irqreturn_t cam_fd_hw_irq(int irq_num, void *data) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)data; + struct cam_fd_core *fd_core; + struct cam_hw_soc_info *soc_info; + struct cam_fd_hw_static_info *hw_static_info; + uint32_t reg_value; + enum cam_fd_hw_irq_type irq_type = CAM_FD_IRQ_FRAME_DONE; + uint32_t num_irqs = 0; + + if (!fd_hw) { + CAM_ERR(CAM_FD, "Invalid data in IRQ callback"); + return IRQ_NONE; + } + + fd_core = (struct cam_fd_core *) fd_hw->core_info; + soc_info = &fd_hw->soc_info; + hw_static_info = fd_core->hw_static_info; + + reg_value = cam_fd_soc_register_read(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_status); + + CAM_DBG(CAM_FD, "FD IRQ status 0x%x", reg_value); + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_clear, + reg_value); + + if (reg_value & CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE)) { + complete_all(&fd_core->halt_complete); + irq_type = CAM_FD_IRQ_HALT_DONE; + num_irqs++; + } + + if (reg_value & CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE)) { + complete_all(&fd_core->reset_complete); + irq_type = CAM_FD_IRQ_RESET_DONE; + num_irqs++; + } + + if (reg_value & CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE)) { + complete_all(&fd_core->processing_complete); + irq_type = CAM_FD_IRQ_FRAME_DONE; + num_irqs++; + } + + /* + * We should never get an IRQ callback with no or more than one mask. + * Validate first to make sure nothing going wrong. + */ + if (num_irqs != 1) { + CAM_ERR(CAM_FD, + "Invalid number of IRQs, value=0x%x, num_irqs=%d", + reg_value, num_irqs); + return IRQ_NONE; + } + + trace_cam_irq_activated("FD", irq_type); + + if (irq_type == CAM_FD_IRQ_HALT_DONE) { + /* + * Do not send HALT IRQ callback to Hw Mgr, + * a reset would always follow + */ + return IRQ_HANDLED; + } + + spin_lock(&fd_core->spin_lock); + /* Do not change state to IDLE on HALT IRQ. Reset must follow halt */ + if ((irq_type == CAM_FD_IRQ_RESET_DONE) || + (irq_type == CAM_FD_IRQ_FRAME_DONE)) { + + fd_core->core_state = CAM_FD_CORE_STATE_IDLE; + if (irq_type == CAM_FD_IRQ_FRAME_DONE) + fd_core->results_valid = true; + + CAM_DBG(CAM_FD, "FD IRQ type %d, state=%d", + irq_type, fd_core->core_state); + } + spin_unlock(&fd_core->spin_lock); + + if (fd_core->irq_cb.cam_fd_hw_mgr_cb) + fd_core->irq_cb.cam_fd_hw_mgr_cb(fd_core->irq_cb.data, + irq_type); + + return IRQ_HANDLED; +} + +int cam_fd_hw_get_hw_caps(void *hw_priv, void *get_hw_cap_args, + uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + struct cam_fd_core *fd_core; + struct cam_fd_hw_caps *fd_hw_caps = + (struct cam_fd_hw_caps *)get_hw_cap_args; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_FD, "Invalid input pointers %pK %pK", + hw_priv, get_hw_cap_args); + return -EINVAL; + } + + fd_core = (struct cam_fd_core *)fd_hw->core_info; + *fd_hw_caps = fd_core->hw_caps; + + CAM_DBG(CAM_FD, "core:%d.%d wrapper:%d.%d mode:%d, raw:%d", + fd_hw_caps->core_version.major, + fd_hw_caps->core_version.minor, + fd_hw_caps->wrapper_version.major, + fd_hw_caps->wrapper_version.minor, + fd_hw_caps->supported_modes, + fd_hw_caps->raw_results_available); + + return 0; +} + +int cam_fd_hw_init(void *hw_priv, void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + struct cam_fd_core *fd_core; + struct cam_fd_hw_init_args *init_args = + (struct cam_fd_hw_init_args *)init_hw_args; + int rc = 0; + unsigned long flags; + + if (!fd_hw || !init_args) { + CAM_ERR(CAM_FD, "Invalid argument %pK %pK", fd_hw, init_args); + return -EINVAL; + } + + if (arg_size != sizeof(struct cam_fd_hw_init_args)) { + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, + sizeof(struct cam_fd_hw_init_args)); + return -EINVAL; + } + + fd_core = (struct cam_fd_core *)fd_hw->core_info; + + mutex_lock(&fd_hw->hw_mutex); + CAM_DBG(CAM_FD, "FD HW Init ref count before %d", fd_hw->open_count); + + if (fd_hw->open_count > 0) { + rc = 0; + goto cdm_streamon; + } + + rc = cam_fd_soc_enable_resources(&fd_hw->soc_info); + if (rc) { + CAM_ERR(CAM_FD, "Enable SOC failed, rc=%d", rc); + goto unlock_return; + } + + spin_lock_irqsave(&fd_core->spin_lock, flags); + fd_hw->hw_state = CAM_HW_STATE_POWER_UP; + fd_core->core_state = CAM_FD_CORE_STATE_IDLE; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + rc = cam_fd_hw_reset(hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_FD, "Reset Failed, rc=%d", rc); + goto disable_soc; + } + + cam_fd_hw_util_enable_power_on_settings(fd_hw); + +cdm_streamon: + fd_hw->open_count++; + CAM_DBG(CAM_FD, "FD HW Init ref count after %d", fd_hw->open_count); + + if (init_args->ctx_hw_private) { + struct cam_fd_ctx_hw_private *ctx_hw_private = + init_args->ctx_hw_private; + + rc = cam_cdm_stream_on(ctx_hw_private->cdm_handle); + if (rc) { + CAM_ERR(CAM_FD, "CDM StreamOn fail :handle=0x%x, rc=%d", + ctx_hw_private->cdm_handle, rc); + fd_hw->open_count--; + if (!fd_hw->open_count) + goto disable_soc; + } + } + + mutex_unlock(&fd_hw->hw_mutex); + + return rc; + +disable_soc: + if (cam_fd_soc_disable_resources(&fd_hw->soc_info)) + CAM_ERR(CAM_FD, "Error in disable soc resources"); + + spin_lock_irqsave(&fd_core->spin_lock, flags); + fd_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + fd_core->core_state = CAM_FD_CORE_STATE_POWERDOWN; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); +unlock_return: + mutex_unlock(&fd_hw->hw_mutex); + return rc; +} + +int cam_fd_hw_deinit(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = hw_priv; + struct cam_fd_core *fd_core = NULL; + struct cam_fd_hw_deinit_args *deinit_args = + (struct cam_fd_hw_deinit_args *)deinit_hw_args; + int rc = 0; + unsigned long flags; + + if (!fd_hw || !deinit_hw_args) { + CAM_ERR(CAM_FD, "Invalid argument"); + return -EINVAL; + } + + if (arg_size != sizeof(struct cam_fd_hw_deinit_args)) { + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, + sizeof(struct cam_fd_hw_deinit_args)); + return -EINVAL; + } + + mutex_lock(&fd_hw->hw_mutex); + if (fd_hw->open_count == 0) { + mutex_unlock(&fd_hw->hw_mutex); + CAM_ERR(CAM_FD, "Error Unbalanced deinit"); + return -EFAULT; + } + + fd_hw->open_count--; + CAM_DBG(CAM_FD, "FD HW ref count=%d", fd_hw->open_count); + + if (fd_hw->open_count > 0) { + rc = 0; + goto positive_ref_cnt; + } + + rc = cam_fd_soc_disable_resources(&fd_hw->soc_info); + if (rc) + CAM_ERR(CAM_FD, "Failed in Disable SOC, rc=%d", rc); + + fd_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + fd_core = (struct cam_fd_core *)fd_hw->core_info; + + /* With the ref_cnt correct, this should never happen */ + WARN_ON(!fd_core); + + spin_lock_irqsave(&fd_core->spin_lock, flags); + fd_core->core_state = CAM_FD_CORE_STATE_POWERDOWN; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); +positive_ref_cnt: + if (deinit_args->ctx_hw_private) { + struct cam_fd_ctx_hw_private *ctx_hw_private = + deinit_args->ctx_hw_private; + + rc = cam_cdm_stream_off(ctx_hw_private->cdm_handle); + if (rc) { + CAM_ERR(CAM_FD, + "Failed in CDM StreamOff, handle=0x%x, rc=%d", + ctx_hw_private->cdm_handle, rc); + } + } + + mutex_unlock(&fd_hw->hw_mutex); + return rc; +} + +int cam_fd_hw_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + struct cam_fd_core *fd_core; + struct cam_fd_hw_static_info *hw_static_info; + struct cam_hw_soc_info *soc_info; + unsigned long flags; + int rc; + + if (!fd_hw) { + CAM_ERR(CAM_FD, "Invalid input handle"); + return -EINVAL; + } + + fd_core = (struct cam_fd_core *)fd_hw->core_info; + hw_static_info = fd_core->hw_static_info; + soc_info = &fd_hw->soc_info; + + spin_lock_irqsave(&fd_core->spin_lock, flags); + if ((fd_core->core_state == CAM_FD_CORE_STATE_POWERDOWN) || + (fd_core->core_state == CAM_FD_CORE_STATE_RESET_PROGRESS)) { + CAM_ERR(CAM_FD, "Reset not allowed in %d state", + fd_core->core_state); + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + return -EINVAL; + } + + fd_core->results_valid = false; + fd_core->core_state = CAM_FD_CORE_STATE_RESET_PROGRESS; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.cgc_disable, 0x1); + + rc = cam_fd_hw_util_fdwrapper_halt(fd_hw); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HALT rc=%d", rc); + return rc; + } + + rc = cam_fd_hw_util_fdwrapper_sync_reset(fd_hw); + if (rc) { + CAM_ERR(CAM_FD, "Failed in RESET rc=%d", rc); + return rc; + } + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.cgc_disable, 0x0); + + spin_lock_irqsave(&fd_core->spin_lock, flags); + fd_core->core_state = CAM_FD_CORE_STATE_IDLE; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + return rc; +} + +int cam_fd_hw_start(void *hw_priv, void *hw_start_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + struct cam_fd_core *fd_core; + struct cam_fd_hw_static_info *hw_static_info; + struct cam_fd_hw_cmd_start_args *start_args = + (struct cam_fd_hw_cmd_start_args *)hw_start_args; + struct cam_fd_ctx_hw_private *ctx_hw_private; + unsigned long flags; + int rc; + + if (!hw_priv || !start_args) { + CAM_ERR(CAM_FD, "Invalid input args %pK %pK", hw_priv, + start_args); + return -EINVAL; + } + + if (arg_size != sizeof(struct cam_fd_hw_cmd_start_args)) { + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, + sizeof(struct cam_fd_hw_cmd_start_args)); + return -EINVAL; + } + + fd_core = (struct cam_fd_core *)fd_hw->core_info; + hw_static_info = fd_core->hw_static_info; + + spin_lock_irqsave(&fd_core->spin_lock, flags); + if (fd_core->core_state != CAM_FD_CORE_STATE_IDLE) { + CAM_ERR(CAM_FD, "Cannot start in %d state", + fd_core->core_state); + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + return -EINVAL; + } + + /* + * We are about to start FD HW processing, save the request + * private data which is being processed by HW. Once the frame + * processing is finished, process_cmd(FRAME_DONE) should be called + * with same hw_req_private as input. + */ + fd_core->hw_req_private = start_args->hw_req_private; + fd_core->core_state = CAM_FD_CORE_STATE_PROCESSING; + fd_core->results_valid = false; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + ctx_hw_private = start_args->ctx_hw_private; + + /* Before starting HW process, clear processing complete */ + reinit_completion(&fd_core->processing_complete); + + if (hw_static_info->enable_errata_wa.single_irq_only) { + cam_fd_soc_register_write(&fd_hw->soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_mask, + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE)); + } + + if (start_args->num_hw_update_entries > 0) { + struct cam_cdm_bl_request *cdm_cmd = ctx_hw_private->cdm_cmd; + struct cam_hw_update_entry *cmd; + int i; + + cdm_cmd->cmd_arrary_count = start_args->num_hw_update_entries; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = false; + cdm_cmd->userdata = NULL; + cdm_cmd->cookie = 0; + + for (i = 0 ; i <= start_args->num_hw_update_entries; i++) { + cmd = (start_args->hw_update_entries + i); + cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i].offset = cmd->offset; + cdm_cmd->cmd[i].len = cmd->len; + } + + rc = cam_cdm_submit_bls(ctx_hw_private->cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_FD, + "Failed to submit cdm commands, rc=%d", rc); + goto error; + } + } else { + CAM_ERR(CAM_FD, "Invalid number of hw update entries"); + rc = -EINVAL; + goto error; + } + + return 0; +error: + spin_lock_irqsave(&fd_core->spin_lock, flags); + fd_core->core_state = CAM_FD_CORE_STATE_IDLE; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + return rc; +} + +int cam_fd_hw_halt_reset(void *hw_priv, void *stop_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + struct cam_fd_core *fd_core; + struct cam_fd_hw_static_info *hw_static_info; + struct cam_hw_soc_info *soc_info; + unsigned long flags; + int rc; + + if (!fd_hw) { + CAM_ERR(CAM_FD, "Invalid input handle"); + return -EINVAL; + } + + fd_core = (struct cam_fd_core *)fd_hw->core_info; + hw_static_info = fd_core->hw_static_info; + soc_info = &fd_hw->soc_info; + + spin_lock_irqsave(&fd_core->spin_lock, flags); + if ((fd_core->core_state == CAM_FD_CORE_STATE_POWERDOWN) || + (fd_core->core_state == CAM_FD_CORE_STATE_RESET_PROGRESS)) { + CAM_ERR(CAM_FD, "Reset not allowed in %d state", + fd_core->core_state); + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + return -EINVAL; + } + + fd_core->results_valid = false; + fd_core->core_state = CAM_FD_CORE_STATE_RESET_PROGRESS; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.cgc_disable, 0x1); + + rc = cam_fd_hw_util_fdwrapper_halt(fd_hw); + if (rc) { + CAM_ERR(CAM_FD, "Failed in HALT rc=%d", rc); + return rc; + } + + /* HALT must be followed by RESET */ + rc = cam_fd_hw_util_fdwrapper_sync_reset(fd_hw); + if (rc) { + CAM_ERR(CAM_FD, "Failed in RESET rc=%d", rc); + return rc; + } + + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.cgc_disable, 0x0); + + spin_lock_irqsave(&fd_core->spin_lock, flags); + fd_core->core_state = CAM_FD_CORE_STATE_IDLE; + spin_unlock_irqrestore(&fd_core->spin_lock, flags); + + return rc; +} + +int cam_fd_hw_reserve(void *hw_priv, void *hw_reserve_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + int rc = -EINVAL; + struct cam_fd_ctx_hw_private *ctx_hw_private; + struct cam_fd_hw_reserve_args *reserve_args = + (struct cam_fd_hw_reserve_args *)hw_reserve_args; + struct cam_cdm_acquire_data cdm_acquire; + struct cam_cdm_bl_request *cdm_cmd; + int i; + + if (!fd_hw || !reserve_args) { + CAM_ERR(CAM_FD, "Invalid input %pK, %pK", fd_hw, reserve_args); + return -EINVAL; + } + + if (arg_size != sizeof(struct cam_fd_hw_reserve_args)) { + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, + sizeof(struct cam_fd_hw_reserve_args)); + return -EINVAL; + } + + cdm_cmd = kzalloc(((sizeof(struct cam_cdm_bl_request)) + + ((CAM_FD_MAX_HW_ENTRIES - 1) * + sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); + if (!cdm_cmd) + return -ENOMEM; + + ctx_hw_private = kzalloc(sizeof(struct cam_fd_ctx_hw_private), + GFP_KERNEL); + if (!ctx_hw_private) { + kfree(cdm_cmd); + return -ENOMEM; + } + + memset(&cdm_acquire, 0, sizeof(cdm_acquire)); + strlcpy(cdm_acquire.identifier, "fd", sizeof("fd")); + cdm_acquire.cell_index = fd_hw->soc_info.index; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ctx_hw_private; + cdm_acquire.cam_cdm_callback = cam_fd_hw_util_cdm_callback; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.base_array_cnt = fd_hw->soc_info.num_reg_map; + for (i = 0; i < fd_hw->soc_info.num_reg_map; i++) + cdm_acquire.base_array[i] = &fd_hw->soc_info.reg_map[i]; + + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_FD, "Failed to acquire the CDM HW"); + goto error; + } + + ctx_hw_private->hw_ctx = reserve_args->hw_ctx; + ctx_hw_private->fd_hw = fd_hw; + ctx_hw_private->mode = reserve_args->mode; + ctx_hw_private->cdm_handle = cdm_acquire.handle; + ctx_hw_private->cdm_ops = cdm_acquire.ops; + ctx_hw_private->cdm_cmd = cdm_cmd; + + reserve_args->ctx_hw_private = ctx_hw_private; + + CAM_DBG(CAM_FD, "private=%pK, hw_ctx=%pK, mode=%d, cdm_handle=0x%x", + ctx_hw_private, ctx_hw_private->hw_ctx, ctx_hw_private->mode, + ctx_hw_private->cdm_handle); + + return 0; +error: + kfree(ctx_hw_private); + kfree(cdm_cmd); + return rc; +} + +int cam_fd_hw_release(void *hw_priv, void *hw_release_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + int rc = -EINVAL; + struct cam_fd_ctx_hw_private *ctx_hw_private; + struct cam_fd_hw_release_args *release_args = + (struct cam_fd_hw_release_args *)hw_release_args; + + if (!fd_hw || !release_args) { + CAM_ERR(CAM_FD, "Invalid input %pK, %pK", fd_hw, release_args); + return -EINVAL; + } + + if (arg_size != sizeof(struct cam_fd_hw_release_args)) { + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, + sizeof(struct cam_fd_hw_release_args)); + return -EINVAL; + } + + ctx_hw_private = + (struct cam_fd_ctx_hw_private *)release_args->ctx_hw_private; + + rc = cam_cdm_release(ctx_hw_private->cdm_handle); + if (rc) + CAM_ERR(CAM_FD, "Release cdm handle failed, handle=0x%x, rc=%d", + ctx_hw_private->cdm_handle, rc); + + kfree(ctx_hw_private->cdm_cmd); + kfree(ctx_hw_private); + release_args->ctx_hw_private = NULL; + + return 0; +} + +int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *fd_hw = (struct cam_hw_info *)hw_priv; + int rc = -EINVAL; + + if (!hw_priv || !cmd_args || + (cmd_type >= CAM_FD_HW_CMD_MAX)) { + CAM_ERR(CAM_FD, "Invalid arguments %pK %pK %d", hw_priv, + cmd_args, cmd_type); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_FD_HW_CMD_REGISTER_CALLBACK: { + struct cam_fd_hw_cmd_set_irq_cb *irq_cb_args; + struct cam_fd_core *fd_core = + (struct cam_fd_core *)fd_hw->core_info; + + if (sizeof(struct cam_fd_hw_cmd_set_irq_cb) != arg_size) { + CAM_ERR(CAM_FD, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + irq_cb_args = (struct cam_fd_hw_cmd_set_irq_cb *)cmd_args; + fd_core->irq_cb.cam_fd_hw_mgr_cb = + irq_cb_args->cam_fd_hw_mgr_cb; + fd_core->irq_cb.data = irq_cb_args->data; + rc = 0; + break; + } + case CAM_FD_HW_CMD_PRESTART: { + struct cam_fd_hw_cmd_prestart_args *prestart_args; + + if (sizeof(struct cam_fd_hw_cmd_prestart_args) != arg_size) { + CAM_ERR(CAM_FD, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + prestart_args = (struct cam_fd_hw_cmd_prestart_args *)cmd_args; + rc = cam_fd_hw_util_processcmd_prestart(fd_hw, prestart_args); + break; + } + case CAM_FD_HW_CMD_FRAME_DONE: { + struct cam_fd_hw_frame_done_args *cmd_frame_results; + + if (sizeof(struct cam_fd_hw_frame_done_args) != + arg_size) { + CAM_ERR(CAM_FD, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + cmd_frame_results = + (struct cam_fd_hw_frame_done_args *)cmd_args; + rc = cam_fd_hw_util_processcmd_frame_done(fd_hw, + cmd_frame_results); + break; + } + default: + break; + } + + return rc; +} diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h new file mode 100644 index 000000000000..22f9130d9cd1 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_CORE_H_ +#define _CAM_FD_HW_CORE_H_ + +#include +#include +#include +#include +#include + +#include "cam_common_util.h" +#include "cam_debug_util.h" +#include "cam_io_util.h" +#include "cam_cpas_api.h" +#include "cam_cdm_intf_api.h" +#include "cam_fd_hw_intf.h" +#include "cam_fd_hw_soc.h" + +#define CAM_FD_IRQ_TO_MASK(irq) (1 << (irq)) +#define CAM_FD_MASK_TO_IRQ(mask, irq) ((mask) >> (irq)) + +#define CAM_FD_HW_HALT_RESET_TIMEOUT 750 + +/** + * enum cam_fd_core_state - FD Core internal states + * + * @CAM_FD_CORE_STATE_POWERDOWN : Indicates FD core is powered down + * @CAM_FD_CORE_STATE_IDLE : Indicates FD HW is in idle state. + * Core can be in this state when it is + * ready to process frames or when + * processing is finished and results are + * available + * @CAM_FD_CORE_STATE_PROCESSING : Indicates FD core is processing frame + * @CAM_FD_CORE_STATE_READING_RESULTS : Indicates results are being read from + * FD core + * @CAM_FD_CORE_STATE_RESET_PROGRESS : Indicates FD Core is in reset state + */ +enum cam_fd_core_state { + CAM_FD_CORE_STATE_POWERDOWN, + CAM_FD_CORE_STATE_IDLE, + CAM_FD_CORE_STATE_PROCESSING, + CAM_FD_CORE_STATE_READING_RESULTS, + CAM_FD_CORE_STATE_RESET_PROGRESS, +}; + +/** + * struct cam_fd_ctx_hw_private : HW private information for a specific hw ctx. + * This information is populated by HW layer on + * reserve() and given back to HW Mgr as private + * data for the hw context. This private_data + * has to be passed by HW Mgr layer while + * further HW layer calls + * + * @hw_ctx : Corresponding hw_ctx pointer + * @fd_hw : FD HW info pointer + * @cdm_handle : CDM Handle for this context + * @cdm_ops : CDM Ops + * @cdm_cmd : CDM command pointer + * @mode : Mode this context is running + * @curr_req_private : Current Request information + * + */ +struct cam_fd_ctx_hw_private { + void *hw_ctx; + struct cam_hw_info *fd_hw; + uint32_t cdm_handle; + struct cam_cdm_utils_ops *cdm_ops; + struct cam_cdm_bl_request *cdm_cmd; + enum cam_fd_hw_mode mode; + struct cam_fd_hw_req_private *curr_req_private; +}; + +/** + * struct cam_fd_core_regs : FD HW Core register offsets info + * + * @version : Offset of version register + * @control : Offset of control register + * @result_cnt : Offset of result count register + * @result_addr : Offset of results address register + * @image_addr : Offset of image address register + * @work_addr : Offset of work address register + * @ro_mode : Offset of ro_mode register + * @results_reg_base : Offset of results_reg_base register + * @raw_results_reg_base : Offset of raw_results_reg_base register + * + */ +struct cam_fd_core_regs { + uint32_t version; + uint32_t control; + uint32_t result_cnt; + uint32_t result_addr; + uint32_t image_addr; + uint32_t work_addr; + uint32_t ro_mode; + uint32_t results_reg_base; + uint32_t raw_results_reg_base; +}; + +/** + * struct cam_fd_core_regs : FD HW Wrapper register offsets info + * + * @wrapper_version : Offset of wrapper_version register + * @cgc_disable : Offset of cgc_disable register + * @hw_stop : Offset of hw_stop register + * @sw_reset : Offset of sw_reset register + * @vbif_req_priority : Offset of vbif_req_priority register + * @vbif_priority_level : Offset of vbif_priority_level register + * @vbif_done_status : Offset of vbif_done_status register + * @irq_mask : Offset of irq mask register + * @irq_status : Offset of irq status register + * @irq_clear : Offset of irq clear register + * + */ +struct cam_fd_wrapper_regs { + uint32_t wrapper_version; + uint32_t cgc_disable; + uint32_t hw_stop; + uint32_t sw_reset; + uint32_t vbif_req_priority; + uint32_t vbif_priority_level; + uint32_t vbif_done_status; + uint32_t irq_mask; + uint32_t irq_status; + uint32_t irq_clear; +}; + +/** + * struct cam_fd_hw_errata_wa : FD HW Errata workaround enable/dsiable info + * + * @single_irq_only : Whether to enable only one irq at any time + * @ro_mode_enable_always : Whether to enable ro mode always + * @ro_mode_results_invalid : Whether results written directly into output + * memory by HW are valid or not + */ +struct cam_fd_hw_errata_wa { + bool single_irq_only; + bool ro_mode_enable_always; + bool ro_mode_results_invalid; +}; + +/** + * struct cam_fd_hw_results_prop : FD HW Results properties + * + * @max_faces : Maximum number of faces supported + * @per_face_entries : Number of register with properties for each face + * @raw_results_entries : Number of raw results entries for the full search + * @raw_results_available : Whether raw results available on this HW + * + */ +struct cam_fd_hw_results_prop { + uint32_t max_faces; + uint32_t per_face_entries; + uint32_t raw_results_entries; + bool raw_results_available; +}; + +/** + * struct cam_fd_hw_static_info : FD HW information based on HW version + * + * @core_version : Core version of FD HW + * @wrapper_version : Wrapper version of FD HW + * @core_regs : Register offset information for core registers + * @wrapper_regs : Register offset information for wrapper registers + * @results : Information about results available on this HW + * @enable_errata_wa : Errata workaround information + * @irq_mask : IRQ mask to enable + * @qos_priority : QoS priority setting for this chipset + * @qos_priority_level : QoS priority level setting for this chipset + * @supported_modes : Supported HW modes on this HW version + * @ro_mode_supported : Whether RO mode is supported on this HW + * + */ +struct cam_fd_hw_static_info { + struct cam_hw_version core_version; + struct cam_hw_version wrapper_version; + struct cam_fd_core_regs core_regs; + struct cam_fd_wrapper_regs wrapper_regs; + struct cam_fd_hw_results_prop results; + struct cam_fd_hw_errata_wa enable_errata_wa; + uint32_t irq_mask; + uint32_t qos_priority; + uint32_t qos_priority_level; + uint32_t supported_modes; + bool ro_mode_supported; +}; + +/** + * struct cam_fd_core : FD HW core data structure + * + * @hw_static_info : HW information specific to version + * @hw_caps : HW capabilities + * @core_state : Current HW state + * @processing_complete : Whether processing is complete + * @reset_complete : Whether reset is complete + * @halt_complete : Whether halt is complete + * @hw_req_private : Request that is being currently processed by HW + * @results_valid : Whether HW frame results are available to get + * @spin_lock : Mutex to protect shared data in hw layer + * @irq_cb : HW Manager callback information + * + */ +struct cam_fd_core { + struct cam_fd_hw_static_info *hw_static_info; + struct cam_fd_hw_caps hw_caps; + enum cam_fd_core_state core_state; + struct completion processing_complete; + struct completion reset_complete; + struct completion halt_complete; + struct cam_fd_hw_req_private *hw_req_private; + bool results_valid; + spinlock_t spin_lock; + struct cam_fd_hw_cmd_set_irq_cb irq_cb; +}; + +int cam_fd_hw_util_get_hw_caps(struct cam_hw_info *fd_hw, + struct cam_fd_hw_caps *hw_caps); +irqreturn_t cam_fd_hw_irq(int irq_num, void *data); + +int cam_fd_hw_get_hw_caps(void *hw_priv, void *get_hw_cap_args, + uint32_t arg_size); +int cam_fd_hw_init(void *hw_priv, void *init_hw_args, uint32_t arg_size); +int cam_fd_hw_deinit(void *hw_priv, void *deinit_hw_args, uint32_t arg_size); +int cam_fd_hw_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size); +int cam_fd_hw_reserve(void *hw_priv, void *hw_reserve_args, uint32_t arg_size); +int cam_fd_hw_release(void *hw_priv, void *hw_release_args, uint32_t arg_size); +int cam_fd_hw_start(void *hw_priv, void *hw_start_args, uint32_t arg_size); +int cam_fd_hw_halt_reset(void *hw_priv, void *stop_args, uint32_t arg_size); +int cam_fd_hw_read(void *hw_priv, void *read_args, uint32_t arg_size); +int cam_fd_hw_write(void *hw_priv, void *write_args, uint32_t arg_size); +int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); + +#endif /* _CAM_FD_HW_CORE_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c new file mode 100644 index 000000000000..3498e6235279 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_subdev.h" +#include "cam_fd_hw_intf.h" +#include "cam_fd_hw_core.h" +#include "cam_fd_hw_soc.h" +#include "cam_fd_hw_v41.h" +#include "cam_fd_hw_v501.h" +#include "cam_fd_hw_v600.h" + +static char fd_dev_name[8]; + +static int cam_fd_hw_dev_probe(struct platform_device *pdev) +{ + struct cam_hw_info *fd_hw; + struct cam_hw_intf *fd_hw_intf; + struct cam_fd_core *fd_core; + const struct of_device_id *match_dev = NULL; + struct cam_fd_hw_static_info *hw_static_info = NULL; + int rc = 0; + uint32_t hw_idx; + struct cam_fd_hw_init_args init_args; + struct cam_fd_hw_deinit_args deinit_args; + + fd_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!fd_hw_intf) + return -ENOMEM; + + fd_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!fd_hw) { + kfree(fd_hw_intf); + return -ENOMEM; + } + + fd_core = kzalloc(sizeof(struct cam_fd_core), GFP_KERNEL); + if (!fd_core) { + kfree(fd_hw); + kfree(fd_hw_intf); + return -ENOMEM; + } + of_property_read_u32(pdev->dev.of_node, + "cell-index", &hw_idx); + + fd_hw_intf->hw_priv = fd_hw; + fd_hw->core_info = fd_core; + fd_hw_intf->hw_idx = hw_idx; + + memset(fd_dev_name, 0, sizeof(fd_dev_name)); + snprintf(fd_dev_name, sizeof(fd_dev_name), + "fd%1u", fd_hw_intf->hw_idx); + + fd_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + fd_hw->soc_info.pdev = pdev; + fd_hw->soc_info.dev = &pdev->dev; + fd_hw->soc_info.dev_name = fd_dev_name; + fd_hw->open_count = 0; + mutex_init(&fd_hw->hw_mutex); + spin_lock_init(&fd_hw->hw_lock); + init_completion(&fd_hw->hw_complete); + + spin_lock_init(&fd_core->spin_lock); + init_completion(&fd_core->processing_complete); + init_completion(&fd_core->halt_complete); + init_completion(&fd_core->reset_complete); + + fd_hw_intf->hw_ops.get_hw_caps = cam_fd_hw_get_hw_caps; + fd_hw_intf->hw_ops.init = cam_fd_hw_init; + fd_hw_intf->hw_ops.deinit = cam_fd_hw_deinit; + fd_hw_intf->hw_ops.reset = cam_fd_hw_reset; + fd_hw_intf->hw_ops.reserve = cam_fd_hw_reserve; + fd_hw_intf->hw_ops.release = cam_fd_hw_release; + fd_hw_intf->hw_ops.start = cam_fd_hw_start; + fd_hw_intf->hw_ops.stop = cam_fd_hw_halt_reset; + fd_hw_intf->hw_ops.read = NULL; + fd_hw_intf->hw_ops.write = NULL; + fd_hw_intf->hw_ops.process_cmd = cam_fd_hw_process_cmd; + fd_hw_intf->hw_type = CAM_HW_FD; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev || !match_dev->data) { + CAM_ERR(CAM_FD, "No Of_match data, %pK", match_dev); + rc = -EINVAL; + goto free_memory; + } + hw_static_info = (struct cam_fd_hw_static_info *)match_dev->data; + fd_core->hw_static_info = hw_static_info; + + CAM_DBG(CAM_FD, "HW Static Info : version core[%d.%d] wrapper[%d.%d]", + hw_static_info->core_version.major, + hw_static_info->core_version.minor, + hw_static_info->wrapper_version.major, + hw_static_info->wrapper_version.minor); + + rc = cam_fd_soc_init_resources(&fd_hw->soc_info, cam_fd_hw_irq, fd_hw); + if (rc) { + CAM_ERR(CAM_FD, "Failed to init soc, rc=%d", rc); + goto free_memory; + } + + memset(&init_args, 0x0, sizeof(init_args)); + memset(&deinit_args, 0x0, sizeof(deinit_args)); + rc = cam_fd_hw_init(fd_hw, &init_args, sizeof(init_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed to hw init, rc=%d", rc); + goto deinit_platform_res; + } + + rc = cam_fd_hw_util_get_hw_caps(fd_hw, &fd_core->hw_caps); + if (rc) { + CAM_ERR(CAM_FD, "Failed to get hw caps, rc=%d", rc); + goto deinit_hw; + } + + rc = cam_fd_hw_deinit(fd_hw, &deinit_args, sizeof(deinit_args)); + if (rc) { + CAM_ERR(CAM_FD, "Failed to deinit hw, rc=%d", rc); + goto deinit_platform_res; + } + + platform_set_drvdata(pdev, fd_hw_intf); + CAM_DBG(CAM_FD, "FD-%d probe successful", fd_hw_intf->hw_idx); + + return rc; + +deinit_hw: + if (cam_fd_hw_deinit(fd_hw, &deinit_args, sizeof(deinit_args))) + CAM_ERR(CAM_FD, "Failed in hw deinit"); +deinit_platform_res: + if (cam_fd_soc_deinit_resources(&fd_hw->soc_info)) + CAM_ERR(CAM_FD, "Failed in soc deinit"); + mutex_destroy(&fd_hw->hw_mutex); +free_memory: + kfree(fd_hw); + kfree(fd_hw_intf); + kfree(fd_core); + + return rc; +} + +static int cam_fd_hw_dev_remove(struct platform_device *pdev) +{ + int rc = 0; + struct cam_hw_intf *fd_hw_intf; + struct cam_hw_info *fd_hw; + struct cam_fd_core *fd_core; + + fd_hw_intf = platform_get_drvdata(pdev); + if (!fd_hw_intf) { + CAM_ERR(CAM_FD, "Invalid fd_hw_intf from pdev"); + return -EINVAL; + } + + fd_hw = fd_hw_intf->hw_priv; + if (!fd_hw) { + CAM_ERR(CAM_FD, "Invalid fd_hw from fd_hw_intf"); + rc = -ENODEV; + goto free_fd_hw_intf; + } + + fd_core = (struct cam_fd_core *)fd_hw->core_info; + if (!fd_core) { + CAM_ERR(CAM_FD, "Invalid fd_core from fd_hw"); + rc = -EINVAL; + goto deinit_platform_res; + } + + kfree(fd_core); + +deinit_platform_res: + rc = cam_fd_soc_deinit_resources(&fd_hw->soc_info); + if (rc) + CAM_ERR(CAM_FD, "Error in FD soc deinit, rc=%d", rc); + + mutex_destroy(&fd_hw->hw_mutex); + kfree(fd_hw); + +free_fd_hw_intf: + kfree(fd_hw_intf); + + return rc; +} + +static const struct of_device_id cam_fd_hw_dt_match[] = { + { + .compatible = "qcom,fd41", + .data = &cam_fd_wrapper120_core410_info, + }, + { + .compatible = "qcom,fd501", + .data = &cam_fd_wrapper200_core501_info, + }, + { + .compatible = "qcom,fd600", + .data = &cam_fd_wrapper200_core600_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_fd_hw_dt_match); + +static struct platform_driver cam_fd_hw_driver = { + .probe = cam_fd_hw_dev_probe, + .remove = cam_fd_hw_dev_remove, + .driver = { + .name = "cam_fd_hw", + .owner = THIS_MODULE, + .of_match_table = cam_fd_hw_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_fd_hw_init_module(void) +{ + return platform_driver_register(&cam_fd_hw_driver); +} + +static void __exit cam_fd_hw_exit_module(void) +{ + platform_driver_unregister(&cam_fd_hw_driver); +} + +module_init(cam_fd_hw_init_module); +module_exit(cam_fd_hw_exit_module); +MODULE_DESCRIPTION("CAM FD HW driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h new file mode 100644 index 000000000000..040bd161e006 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_INTF_H_ +#define _CAM_FD_HW_INTF_H_ + +#include +#include +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_soc_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_subdev.h" +#include "cam_cpas_api.h" +#include "cam_hw_mgr_intf.h" +#include "cam_debug_util.h" + +#define CAM_FD_MAX_IO_BUFFERS 5 +#define CAM_FD_MAX_HW_ENTRIES 5 + +/** + * enum cam_fd_hw_type - Enum for FD HW type + * + * @CAM_HW_FD : FaceDetection HW type + */ +enum cam_fd_hw_type { + CAM_HW_FD, +}; + +/** + * enum cam_fd_hw_mode - Mode in which HW can run + * + * @CAM_FD_MODE_FACEDETECTION : Face Detection mode in which face search + * is done on the given frame + * @CAM_FD_MODE_PYRAMID : Pyramid mode where a pyramid image is generated + * from an input image + */ +enum cam_fd_hw_mode { + CAM_FD_MODE_FACEDETECTION = 0x1, + CAM_FD_MODE_PYRAMID = 0x2, +}; + +/** + * enum cam_fd_priority - FD priority levels + * + * @CAM_FD_PRIORITY_HIGH : Indicates high priority client, driver prioritizes + * frame requests coming from contexts with HIGH + * priority compared to context with normal priority + * @CAM_FD_PRIORITY_NORMAL : Indicates normal priority client + */ +enum cam_fd_priority { + CAM_FD_PRIORITY_HIGH = 0x0, + CAM_FD_PRIORITY_NORMAL, +}; + +/** + * enum cam_fd_hw_irq_type - FD HW IRQ types + * + * @CAM_FD_IRQ_FRAME_DONE : Indicates frame processing is finished + * @CAM_FD_IRQ_HALT_DONE : Indicates HW halt is finished + * @CAM_FD_IRQ_RESET_DONE : Indicates HW reset is finished + */ +enum cam_fd_hw_irq_type { + CAM_FD_IRQ_FRAME_DONE, + CAM_FD_IRQ_HALT_DONE, + CAM_FD_IRQ_RESET_DONE, +}; + +/** + * enum cam_fd_hw_cmd_type - FD HW layer custom commands + * + * @CAM_FD_HW_CMD_PRESTART : Command to process pre-start settings + * @CAM_FD_HW_CMD_FRAME_DONE : Command to process frame done settings + * @CAM_FD_HW_CMD_UPDATE_SOC : Command to process soc update + * @CAM_FD_HW_CMD_REGISTER_CALLBACK : Command to set hw mgr callback + * @CAM_FD_HW_CMD_MAX : Indicates max cmd + */ +enum cam_fd_hw_cmd_type { + CAM_FD_HW_CMD_PRESTART, + CAM_FD_HW_CMD_FRAME_DONE, + CAM_FD_HW_CMD_UPDATE_SOC, + CAM_FD_HW_CMD_REGISTER_CALLBACK, + CAM_FD_HW_CMD_MAX, +}; + +/** + * struct cam_fd_hw_io_buffer : FD HW IO Buffer information + * + * @valid : Whether this IO Buf configuration is valid + * @io_cfg : IO Configuration information + * @num_buf : Number planes in io_addr, cpu_addr array + * @io_addr : Array of IO address information for planes + * @cpu_addr : Array of CPU address information for planes + */ +struct cam_fd_hw_io_buffer { + bool valid; + struct cam_buf_io_cfg *io_cfg; + uint32_t num_buf; + uint64_t io_addr[CAM_PACKET_MAX_PLANES]; + uintptr_t cpu_addr[CAM_PACKET_MAX_PLANES]; +}; + +/** + * struct cam_fd_hw_req_private : FD HW layer's private information + * specific to a request + * + * @ctx_hw_private : FD HW layer's ctx specific private data + * @request_id : Request ID corresponding to this private information + * @get_raw_results : Whether to get raw results for this request + * @ro_mode_enabled : Whether RO mode is enabled for this request + * @fd_results : Pointer to save face detection results + * @raw_results : Pointer to save face detection raw results + */ +struct cam_fd_hw_req_private { + void *ctx_hw_private; + uint64_t request_id; + bool get_raw_results; + bool ro_mode_enabled; + struct cam_fd_results *fd_results; + uint32_t *raw_results; +}; + +/** + * struct cam_fd_hw_reserve_args : Reserve args for this HW context + * + * @hw_ctx : HW context for which reserve is requested + * @mode : Mode for which this reserve is requested + * @ctx_hw_private : Pointer to save HW layer's private information specific + * to this hw context. This has to be passed while calling + * further HW layer calls + */ +struct cam_fd_hw_reserve_args { + void *hw_ctx; + enum cam_fd_hw_mode mode; + void *ctx_hw_private; +}; + +/** + * struct cam_fd_hw_release_args : Release args for this HW context + * + * @hw_ctx : HW context for which release is requested + * @ctx_hw_private : HW layer's private information specific to this hw context + */ +struct cam_fd_hw_release_args { + void *hw_ctx; + void *ctx_hw_private; +}; + +/** + * struct cam_fd_hw_init_args : Init args for this HW context + * + * @hw_ctx : HW context for which init is requested + * @ctx_hw_private : HW layer's private information specific to this hw context + */ +struct cam_fd_hw_init_args { + void *hw_ctx; + void *ctx_hw_private; +}; + +/** + * struct cam_fd_hw_deinit_args : Deinit args for this HW context + * + * @hw_ctx : HW context for which deinit is requested + * @ctx_hw_private : HW layer's private information specific to this hw context + */ +struct cam_fd_hw_deinit_args { + void *hw_ctx; + void *ctx_hw_private; +}; + +/** + * struct cam_fd_hw_cmd_prestart_args : Prestart command args + * + * @hw_ctx : HW context which submitted this prestart + * @ctx_hw_private : HW layer's private information specific to + * this hw context + * @request_id : Request ID corresponds to this pre-start command + * @get_raw_results : Whether to get raw results for this request + * @input_buf : Input IO Buffer information for this request + * @output_buf : Output IO Buffer information for this request + * @cmd_buf_addr : Command buffer address to fill kmd commands + * @size : Size available in command buffer + * @pre_config_buf_size : Buffer size filled with commands by KMD that has + * to be inserted before umd commands + * @post_config_buf_size : Buffer size filled with commands by KMD that has + * to be inserted after umd commands + * @hw_req_private : HW layer's private information specific to + * this request + */ +struct cam_fd_hw_cmd_prestart_args { + void *hw_ctx; + void *ctx_hw_private; + uint64_t request_id; + bool get_raw_results; + struct cam_fd_hw_io_buffer input_buf[CAM_FD_MAX_IO_BUFFERS]; + struct cam_fd_hw_io_buffer output_buf[CAM_FD_MAX_IO_BUFFERS]; + uint32_t *cmd_buf_addr; + uint32_t size; + uint32_t pre_config_buf_size; + uint32_t post_config_buf_size; + struct cam_fd_hw_req_private hw_req_private; +}; + +/** + * struct cam_fd_hw_cmd_start_args : Start command args + * + * @hw_ctx : HW context which submitting start command + * @ctx_hw_private : HW layer's private information specific to + * this hw context + * @hw_req_private : HW layer's private information specific to + * this request + * @hw_update_entries : HW update entries corresponds to this request + * @num_hw_update_entries : Number of hw update entries + */ +struct cam_fd_hw_cmd_start_args { + void *hw_ctx; + void *ctx_hw_private; + struct cam_fd_hw_req_private *hw_req_private; + struct cam_hw_update_entry *hw_update_entries; + uint32_t num_hw_update_entries; +}; + +/** + * struct cam_fd_hw_stop_args : Stop command args + * + * @hw_ctx : HW context which submitting stop command + * @ctx_hw_private : HW layer's private information specific to this hw context + * @request_id : Request ID that need to be stopped + * @hw_req_private : HW layer's private information specific to this request + */ +struct cam_fd_hw_stop_args { + void *hw_ctx; + void *ctx_hw_private; + uint64_t request_id; + struct cam_fd_hw_req_private *hw_req_private; +}; + +/** + * struct cam_fd_hw_frame_done_args : Frame done command args + * + * @hw_ctx : HW context which submitting frame done request + * @ctx_hw_private : HW layer's private information specific to this hw context + * @request_id : Request ID that need to be stopped + * @hw_req_private : HW layer's private information specific to this request + */ +struct cam_fd_hw_frame_done_args { + void *hw_ctx; + void *ctx_hw_private; + uint64_t request_id; + struct cam_fd_hw_req_private *hw_req_private; +}; + +/** + * struct cam_fd_hw_reset_args : Reset command args + * + * @hw_ctx : HW context which submitting reset command + * @ctx_hw_private : HW layer's private information specific to this hw context + */ +struct cam_fd_hw_reset_args { + void *hw_ctx; + void *ctx_hw_private; +}; + +/** + * struct cam_fd_hw_cmd_set_irq_cb : Set IRQ callback command args + * + * @cam_fd_hw_mgr_cb : HW Mgr's callback pointer + * @data : HW Mgr's private data + */ +struct cam_fd_hw_cmd_set_irq_cb { + int (*cam_fd_hw_mgr_cb)(void *data, enum cam_fd_hw_irq_type irq_type); + void *data; +}; + +#endif /* _CAM_FD_HW_INTF_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c new file mode 100644 index 000000000000..56635aa6bce4 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_fd_hw_core.h" +#include "cam_fd_hw_soc.h" + +static bool cam_fd_hw_util_cpas_callback(uint32_t handle, void *userdata, + struct cam_cpas_irq_data *irq_data) +{ + if (!irq_data) + return false; + + CAM_DBG(CAM_FD, "CPAS hdl=%d, udata=%pK, irq_type=%d", + handle, userdata, irq_data->irq_type); + + return false; +} + +static int cam_fd_hw_soc_util_setup_regbase_indices( + struct cam_hw_soc_info *soc_info) +{ + struct cam_fd_soc_private *soc_private = + (struct cam_fd_soc_private *)soc_info->soc_private; + uint32_t index; + int rc, i; + + for (i = 0; i < CAM_FD_REG_MAX; i++) + soc_private->regbase_index[i] = -1; + + if ((soc_info->num_mem_block > CAM_SOC_MAX_BLOCK) || + (soc_info->num_mem_block != CAM_FD_REG_MAX)) { + CAM_ERR(CAM_FD, "Invalid num_mem_block=%d", + soc_info->num_mem_block); + return -EINVAL; + } + + rc = cam_common_util_get_string_index(soc_info->mem_block_name, + soc_info->num_mem_block, "fd_core", &index); + if ((rc == 0) && (index < CAM_FD_REG_MAX)) { + soc_private->regbase_index[CAM_FD_REG_CORE] = index; + } else { + CAM_ERR(CAM_FD, "regbase not found for FD_CORE, rc=%d, %d %d", + rc, index, CAM_FD_REG_MAX); + return -EINVAL; + } + + rc = cam_common_util_get_string_index(soc_info->mem_block_name, + soc_info->num_mem_block, "fd_wrapper", &index); + if ((rc == 0) && (index < CAM_FD_REG_MAX)) { + soc_private->regbase_index[CAM_FD_REG_WRAPPER] = index; + } else { + CAM_ERR(CAM_FD, "regbase not found FD_WRAPPER, rc=%d, %d %d", + rc, index, CAM_FD_REG_MAX); + return -EINVAL; + } + + CAM_DBG(CAM_FD, "Reg indices : CORE=%d, WRAPPER=%d", + soc_private->regbase_index[CAM_FD_REG_CORE], + soc_private->regbase_index[CAM_FD_REG_WRAPPER]); + + return 0; +} + +static int cam_fd_soc_set_clk_flags(struct cam_hw_soc_info *soc_info) +{ + int i, rc = 0; + + if (soc_info->num_clk > CAM_SOC_MAX_CLK) { + CAM_ERR(CAM_FD, "Invalid num clk %d", soc_info->num_clk); + return -EINVAL; + } + + /* set memcore and mem periphery logic flags to 0 */ + for (i = 0; i < soc_info->num_clk; i++) { + if ((strcmp(soc_info->clk_name[i], "fd_core_clk") == 0) || + (strcmp(soc_info->clk_name[i], "fd_core_uar_clk") == + 0)) { + rc = cam_soc_util_set_clk_flags(soc_info, i, + CLKFLAG_NORETAIN_MEM); + if (rc) + CAM_ERR(CAM_FD, + "Failed in NORETAIN_MEM i=%d, rc=%d", + i, rc); + + cam_soc_util_set_clk_flags(soc_info, i, + CLKFLAG_NORETAIN_PERIPH); + if (rc) + CAM_ERR(CAM_FD, + "Failed in NORETAIN_PERIPH i=%d, rc=%d", + i, rc); + } + } + + return rc; +} + +void cam_fd_soc_register_write(struct cam_hw_soc_info *soc_info, + enum cam_fd_reg_base reg_base, uint32_t reg_offset, uint32_t reg_value) +{ + struct cam_fd_soc_private *soc_private = + (struct cam_fd_soc_private *)soc_info->soc_private; + int32_t reg_index = soc_private->regbase_index[reg_base]; + + CAM_DBG(CAM_FD, "FD_REG_WRITE: Base[%d] Offset[0x%8x] Value[0x%8x]", + reg_base, reg_offset, reg_value); + + cam_io_w_mb(reg_value, + soc_info->reg_map[reg_index].mem_base + reg_offset); +} + +uint32_t cam_fd_soc_register_read(struct cam_hw_soc_info *soc_info, + enum cam_fd_reg_base reg_base, uint32_t reg_offset) +{ + struct cam_fd_soc_private *soc_private = + (struct cam_fd_soc_private *)soc_info->soc_private; + int32_t reg_index = soc_private->regbase_index[reg_base]; + uint32_t reg_value; + + reg_value = cam_io_r_mb( + soc_info->reg_map[reg_index].mem_base + reg_offset); + + CAM_DBG(CAM_FD, "FD_REG_READ: Base[%d] Offset[0x%8x] Value[0x%8x]", + reg_base, reg_offset, reg_value); + + return reg_value; +} + +int cam_fd_soc_enable_resources(struct cam_hw_soc_info *soc_info) +{ + struct cam_fd_soc_private *soc_private = soc_info->soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + int rc; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 2; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = 7200000; + axi_vote.axi_path[0].mnoc_ab_bw = 7200000; + axi_vote.axi_path[0].mnoc_ib_bw = 7200000; + axi_vote.axi_path[1].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[1].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[1].camnoc_bw = 7200000; + axi_vote.axi_path[1].mnoc_ab_bw = 7200000; + axi_vote.axi_path[1].mnoc_ib_bw = 7200000; + + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_FD, "Error in CPAS START, rc=%d", rc); + return -EFAULT; + } + + rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_SVS_VOTE, + true); + if (rc) { + CAM_ERR(CAM_FD, "Error enable platform failed, rc=%d", rc); + goto stop_cpas; + } + + return rc; + +stop_cpas: + if (cam_cpas_stop(soc_private->cpas_handle)) + CAM_ERR(CAM_FD, "Error in CPAS STOP"); + + return rc; +} + + +int cam_fd_soc_disable_resources(struct cam_hw_soc_info *soc_info) +{ + struct cam_fd_soc_private *soc_private; + int rc = 0; + + if (!soc_info) { + CAM_ERR(CAM_FD, "Invalid soc_info param"); + return -EINVAL; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_FD, "disable platform resources failed, rc=%d", rc); + return rc; + } + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_FD, "Error in CPAS STOP, handle=0x%x, rc=%d", + soc_private->cpas_handle, rc); + return rc; + } + + return rc; +} + +int cam_fd_soc_init_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, void *private_data) +{ + struct cam_fd_soc_private *soc_private; + struct cam_cpas_register_params cpas_register_param; + int rc; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_FD, "Failed in get_dt_properties, rc=%d", rc); + return rc; + } + + rc = cam_soc_util_request_platform_resource(soc_info, irq_handler, + private_data); + if (rc) { + CAM_ERR(CAM_FD, "Failed in request_platform_resource rc=%d", + rc); + return rc; + } + + rc = cam_fd_soc_set_clk_flags(soc_info); + if (rc) { + CAM_ERR(CAM_FD, "failed in set_clk_flags rc=%d", rc); + goto release_res; + } + + soc_private = kzalloc(sizeof(struct cam_fd_soc_private), GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto release_res; + } + soc_info->soc_private = soc_private; + + rc = cam_fd_hw_soc_util_setup_regbase_indices(soc_info); + if (rc) { + CAM_ERR(CAM_FD, "Failed in setup regbase, rc=%d", rc); + goto free_soc_private; + } + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "fd", CAM_HW_IDENTIFIER_LENGTH); + cpas_register_param.cell_index = soc_info->index; + cpas_register_param.dev = &soc_info->pdev->dev; + cpas_register_param.userdata = private_data; + cpas_register_param.cam_cpas_client_cb = cam_fd_hw_util_cpas_callback; + + rc = cam_cpas_register_client(&cpas_register_param); + if (rc) { + CAM_ERR(CAM_FD, "CPAS registration failed"); + goto free_soc_private; + } + soc_private->cpas_handle = cpas_register_param.client_handle; + CAM_DBG(CAM_FD, "CPAS handle=%d", soc_private->cpas_handle); + + return rc; + +free_soc_private: + kfree(soc_info->soc_private); + soc_info->soc_private = NULL; +release_res: + cam_soc_util_release_platform_resource(soc_info); + + return rc; +} + +int cam_fd_soc_deinit_resources(struct cam_hw_soc_info *soc_info) +{ + struct cam_fd_soc_private *soc_private = + (struct cam_fd_soc_private *)soc_info->soc_private; + int rc; + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_FD, "Unregister cpas failed, handle=%d, rc=%d", + soc_private->cpas_handle, rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_ERR(CAM_FD, "release platform failed, rc=%d", rc); + + kfree(soc_info->soc_private); + soc_info->soc_private = NULL; + + return rc; +} diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.h new file mode 100644 index 000000000000..b27ce09e36e6 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_SOC_H_ +#define _CAM_FD_HW_SOC_H_ + +#include "cam_soc_util.h" + +/** + * enum cam_fd_reg_base - Enum for FD register sets + * + * @CAM_FD_REG_CORE : Indicates FD Core register space + * @CAM_FD_REG_WRAPPER : Indicates FD Wrapper register space + * @CAM_FD_REG_MAX : Max number of register sets supported + */ +enum cam_fd_reg_base { + CAM_FD_REG_CORE, + CAM_FD_REG_WRAPPER, + CAM_FD_REG_MAX +}; + +/** + * struct cam_fd_soc_private : FD private SOC information + * + * @regbase_index : Mapping between Register base enum to register index in SOC + * @cpas_handle : CPAS handle + * + */ +struct cam_fd_soc_private { + int32_t regbase_index[CAM_FD_REG_MAX]; + uint32_t cpas_handle; +}; + +int cam_fd_soc_init_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, void *private_data); +int cam_fd_soc_deinit_resources(struct cam_hw_soc_info *soc_info); +int cam_fd_soc_enable_resources(struct cam_hw_soc_info *soc_info); +int cam_fd_soc_disable_resources(struct cam_hw_soc_info *soc_info); +uint32_t cam_fd_soc_register_read(struct cam_hw_soc_info *soc_info, + enum cam_fd_reg_base reg_base, uint32_t reg_offset); +void cam_fd_soc_register_write(struct cam_hw_soc_info *soc_info, + enum cam_fd_reg_base reg_base, uint32_t reg_offset, uint32_t reg_value); + +#endif /* _CAM_FD_HW_SOC_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h new file mode 100644 index 000000000000..ad1fb0bc5737 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_V41_H_ +#define _CAM_FD_HW_V41_H_ + +static struct cam_fd_hw_static_info cam_fd_wrapper120_core410_info = { + .core_version = { + .major = 4, + .minor = 1, + .incr = 0, + }, + .wrapper_version = { + .major = 1, + .minor = 2, + .incr = 0, + }, + .core_regs = { + .version = 0x38, + .control = 0x0, + .result_cnt = 0x4, + .result_addr = 0x20, + .image_addr = 0x24, + .work_addr = 0x28, + .ro_mode = 0x34, + .results_reg_base = 0x400, + .raw_results_reg_base = 0x800, + }, + .wrapper_regs = { + .wrapper_version = 0x0, + .cgc_disable = 0x4, + .hw_stop = 0x8, + .sw_reset = 0x10, + .vbif_req_priority = 0x20, + .vbif_priority_level = 0x24, + .vbif_done_status = 0x34, + .irq_mask = 0x50, + .irq_status = 0x54, + .irq_clear = 0x58, + }, + .results = { + .max_faces = 35, + .per_face_entries = 4, + .raw_results_available = true, + .raw_results_entries = 512, + }, + .enable_errata_wa = { + .single_irq_only = true, + .ro_mode_enable_always = true, + .ro_mode_results_invalid = true, + }, + .irq_mask = CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE) | + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE) | + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE), + .qos_priority = 4, + .qos_priority_level = 4, + .supported_modes = CAM_FD_MODE_FACEDETECTION | CAM_FD_MODE_PYRAMID, + .ro_mode_supported = true, +}; + +#endif /* _CAM_FD_HW_V41_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h new file mode 100644 index 000000000000..f3eedeb3b811 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_V501_H_ +#define _CAM_FD_HW_V501_H_ + +static struct cam_fd_hw_static_info cam_fd_wrapper200_core501_info = { + .core_version = { + .major = 5, + .minor = 0, + .incr = 1, + }, + .wrapper_version = { + .major = 2, + .minor = 0, + .incr = 0, + }, + .core_regs = { + .version = 0x38, + .control = 0x0, + .result_cnt = 0x4, + .result_addr = 0x20, + .image_addr = 0x24, + .work_addr = 0x28, + .ro_mode = 0x34, + .results_reg_base = 0x400, + .raw_results_reg_base = 0x800, + }, + .wrapper_regs = { + .wrapper_version = 0x0, + .cgc_disable = 0x4, + .hw_stop = 0x8, + .sw_reset = 0x10, + .vbif_req_priority = 0x20, + .vbif_priority_level = 0x24, + .vbif_done_status = 0x34, + .irq_mask = 0x50, + .irq_status = 0x54, + .irq_clear = 0x58, + }, + .results = { + .max_faces = 35, + .per_face_entries = 4, + .raw_results_available = true, + .raw_results_entries = 512, + }, + .enable_errata_wa = { + .single_irq_only = true, + .ro_mode_enable_always = true, + .ro_mode_results_invalid = true, + }, + .irq_mask = CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE) | + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE) | + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE), + .qos_priority = 4, + .qos_priority_level = 4, + .supported_modes = CAM_FD_MODE_FACEDETECTION | CAM_FD_MODE_PYRAMID, + .ro_mode_supported = true, +}; + +#endif /* _CAM_FD_HW_V501_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v600.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v600.h new file mode 100644 index 000000000000..0c81cb642930 --- /dev/null +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v600.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_HW_V600_H_ +#define _CAM_FD_HW_V600_H_ + +static struct cam_fd_hw_static_info cam_fd_wrapper200_core600_info = { + .core_version = { + .major = 6, + .minor = 0, + .incr = 0, + }, + .wrapper_version = { + .major = 2, + .minor = 0, + .incr = 0, + }, + .core_regs = { + .version = 0x38, + .control = 0x0, + .result_cnt = 0x4, + .result_addr = 0x20, + .image_addr = 0x24, + .work_addr = 0x28, + .ro_mode = 0x34, + .results_reg_base = 0x400, + }, + .wrapper_regs = { + .wrapper_version = 0x0, + .cgc_disable = 0x4, + .hw_stop = 0x8, + .sw_reset = 0x10, + .vbif_req_priority = 0x20, + .vbif_priority_level = 0x24, + .vbif_done_status = 0x34, + .irq_mask = 0x50, + .irq_status = 0x54, + .irq_clear = 0x58, + }, + .results = { + .max_faces = 35, + .per_face_entries = 4, + .raw_results_available = false, + }, + .enable_errata_wa = { + .single_irq_only = true, + .ro_mode_enable_always = true, + .ro_mode_results_invalid = true, + }, + .irq_mask = CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE) | + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE) | + CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE), + .qos_priority = 4, + .qos_priority_level = 4, + .supported_modes = CAM_FD_MODE_FACEDETECTION | CAM_FD_MODE_PYRAMID, + .ro_mode_supported = true, +}; + +#endif /* _CAM_FD_HW_V600_H_ */ diff --git a/drivers/cam_icp/Makefile b/drivers/cam_icp/Makefile new file mode 100644 index 000000000000..b41c6cf1fb65 --- /dev/null +++ b/drivers/cam_icp/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc +ccflags-y += -I$(srctree)/techpack/camera +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ + +obj-$(CONFIG_SPECTRA_CAMERA) += icp_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp_subdev.o cam_icp_context.o hfi.o diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c new file mode 100644 index 000000000000..c7d9c63f8429 --- /dev/null +++ b/drivers/cam_icp/cam_icp_context.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cam_node.h" +#include "cam_context.h" +#include "cam_context_utils.h" +#include "cam_icp_context.h" +#include "cam_req_mgr_util.h" +#include "cam_mem_mgr.h" +#include "cam_trace.h" +#include "cam_debug_util.h" +#include "cam_packet_util.h" + +static const char icp_dev_name[] = "icp"; + +static int cam_icp_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + int rc = 0; + bool b_mem_found = false; + + if (!ctx) { + CAM_ERR(CAM_ICP, "Invalid ctx"); + return -EINVAL; + } + + CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &b_mem_found); + if (rc) + CAM_ERR(CAM_ICP, "Failed to dump pf info"); + + if (b_mem_found) + CAM_ERR(CAM_ICP, "Found page fault in req %lld %d", + req->request_id, rc); + } + + return rc; +} + +static int __cam_icp_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_acquire_dev_to_hw(ctx, cmd); + if (!rc) { + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("ICP", ctx); + } + + return rc; +} + +static int __cam_icp_release_dev_in_acquired(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_ICP, "Unable to release device"); + + ctx->state = CAM_CTX_AVAILABLE; + trace_cam_context_state("ICP", ctx); + return rc; +} + +static int __cam_icp_start_dev_in_acquired(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_start_dev_to_hw(ctx, cmd); + if (!rc) { + ctx->state = CAM_CTX_READY; + trace_cam_context_state("ICP", ctx); + } + + return rc; +} + +static int __cam_icp_flush_dev_in_ready(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_flush_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_ICP, "Failed to flush device"); + + return rc; +} + +static int __cam_icp_config_dev_in_ready(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc; + size_t len; + uintptr_t packet_addr; + struct cam_packet *packet; + + rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, + &packet_addr, &len); + if (rc) { + CAM_ERR(CAM_ICP, "[%s][%d] Can not get packet address", + ctx->dev_name, ctx->ctx_id); + rc = -EINVAL; + return rc; + } + + packet = (struct cam_packet *) ((uint8_t *)packet_addr + + (uint32_t)cmd->offset); + + if (((packet->header.op_code & 0xff) == + CAM_ICP_OPCODE_IPE_SETTINGS) || + ((packet->header.op_code & 0xff) == + CAM_ICP_OPCODE_BPS_SETTINGS)) + rc = cam_context_config_dev_to_hw(ctx, cmd); + else + rc = cam_context_prepare_dev_to_hw(ctx, cmd); + + if (rc) + CAM_ERR(CAM_ICP, "Failed to prepare device"); + + return rc; +} + +static int __cam_icp_stop_dev_in_ready(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_stop_dev_to_hw(ctx); + if (rc) + CAM_ERR(CAM_ICP, "Failed to stop device"); + + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("ICP", ctx); + return rc; +} + +static int __cam_icp_release_dev_in_ready(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = __cam_icp_stop_dev_in_ready(ctx, NULL); + if (rc) + CAM_ERR(CAM_ICP, "Failed to stop device"); + + rc = __cam_icp_release_dev_in_acquired(ctx, cmd); + if (rc) + CAM_ERR(CAM_ICP, "Failed to release device"); + + return rc; +} + +static int __cam_icp_handle_buf_done_in_ready(void *ctx, + uint32_t evt_id, void *done) +{ + return cam_context_buf_done_from_hw(ctx, done, evt_id); +} + +static struct cam_ctx_ops + cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = __cam_icp_acquire_dev_in_available, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .release_dev = __cam_icp_release_dev_in_acquired, + .start_dev = __cam_icp_start_dev_in_acquired, + .config_dev = __cam_icp_config_dev_in_ready, + .flush_dev = __cam_icp_flush_dev_in_ready, + }, + .crm_ops = {}, + .irq_ops = __cam_icp_handle_buf_done_in_ready, + .pagefault_ops = cam_icp_context_dump_active_request, + }, + /* Ready */ + { + .ioctl_ops = { + .stop_dev = __cam_icp_stop_dev_in_ready, + .release_dev = __cam_icp_release_dev_in_ready, + .config_dev = __cam_icp_config_dev_in_ready, + .flush_dev = __cam_icp_flush_dev_in_ready, + }, + .crm_ops = {}, + .irq_ops = __cam_icp_handle_buf_done_in_ready, + .pagefault_ops = cam_icp_context_dump_active_request, + }, + /* Activated */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + .pagefault_ops = cam_icp_context_dump_active_request, + }, +}; + +int cam_icp_context_init(struct cam_icp_context *ctx, + struct cam_hw_mgr_intf *hw_intf, uint32_t ctx_id) +{ + int rc; + + if ((!ctx) || (!ctx->base) || (!hw_intf)) { + CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", ctx, hw_intf); + rc = -EINVAL; + goto err; + } + + rc = cam_context_init(ctx->base, icp_dev_name, CAM_ICP, ctx_id, + NULL, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_ICP, "Camera Context Base init failed"); + goto err; + } + + ctx->base->state_machine = cam_icp_ctx_state_machine; + ctx->base->ctx_priv = ctx; + ctx->ctxt_to_hw_map = NULL; + +err: + return rc; +} + +int cam_icp_context_deinit(struct cam_icp_context *ctx) +{ + if ((!ctx) || (!ctx->base)) { + CAM_ERR(CAM_ICP, "Invalid params: %pK", ctx); + return -EINVAL; + } + + cam_context_deinit(ctx->base); + memset(ctx, 0, sizeof(*ctx)); + + return 0; +} diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h new file mode 100644 index 000000000000..edd8bd5617c9 --- /dev/null +++ b/drivers/cam_icp/cam_icp_context.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ICP_CONTEXT_H_ +#define _CAM_ICP_CONTEXT_H_ + +#include "cam_context.h" + +/** + * struct cam_icp_context - icp context + * @base: icp context object + * @state_machine: state machine for ICP context + * @req_base: common request structure + * @state: icp context state + * @ctxt_to_hw_map: context to FW handle mapping + */ +struct cam_icp_context { + struct cam_context *base; + struct cam_ctx_ops *state_machine; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + uint32_t state; + void *ctxt_to_hw_map; +}; + +/** + * cam_icp_context_init() - ICP context init + * @ctx: Pointer to context + * @hw_intf: Pointer to ICP hardware interface + * @ctx_id: ID for this context + */ +int cam_icp_context_init(struct cam_icp_context *ctx, + struct cam_hw_mgr_intf *hw_intf, uint32_t ctx_id); + +/** + * cam_icp_context_deinit() - ICP context deinit + * @ctx: Pointer to context + */ +int cam_icp_context_deinit(struct cam_icp_context *ctx); + +#endif /* _CAM_ICP_CONTEXT_H_ */ diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c new file mode 100644 index 000000000000..f6dbaec5f133 --- /dev/null +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_req_mgr_dev.h" +#include "cam_subdev.h" +#include "cam_node.h" +#include "cam_context.h" +#include "cam_icp_context.h" +#include "cam_hw_mgr_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_debug_util.h" +#include "cam_smmu_api.h" + +#define CAM_ICP_DEV_NAME "cam-icp" + +struct cam_icp_subdev { + struct cam_subdev sd; + struct cam_node *node; + struct cam_context ctx[CAM_ICP_CTX_MAX]; + struct cam_icp_context ctx_icp[CAM_ICP_CTX_MAX]; + struct mutex icp_lock; + int32_t open_cnt; + int32_t reserved; +}; + +static struct cam_icp_subdev g_icp_dev; + +static const struct of_device_id cam_icp_dt_match[] = { + {.compatible = "qcom,cam-icp"}, + {} +}; + +static void cam_icp_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_ICP, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + +static int cam_icp_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_hw_mgr_intf *hw_mgr_intf = NULL; + struct cam_node *node = v4l2_get_subdevdata(sd); + int rc = 0; + + mutex_lock(&g_icp_dev.icp_lock); + if (g_icp_dev.open_cnt >= 1) { + CAM_ERR(CAM_ICP, "ICP subdev is already opened"); + rc = -EALREADY; + goto end; + } + + if (!node) { + CAM_ERR(CAM_ICP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + hw_mgr_intf = &node->hw_mgr_intf; + rc = hw_mgr_intf->hw_open(hw_mgr_intf->hw_mgr_priv, NULL); + if (rc < 0) { + CAM_ERR(CAM_ICP, "FW download failed"); + goto end; + } + g_icp_dev.open_cnt++; +end: + mutex_unlock(&g_icp_dev.icp_lock); + return rc; +} + +static int cam_icp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = 0; + struct cam_hw_mgr_intf *hw_mgr_intf = NULL; + struct cam_node *node = v4l2_get_subdevdata(sd); + + mutex_lock(&g_icp_dev.icp_lock); + if (g_icp_dev.open_cnt <= 0) { + CAM_DBG(CAM_ICP, "ICP subdev is already closed"); + rc = -EINVAL; + goto end; + } + g_icp_dev.open_cnt--; + if (!node) { + CAM_ERR(CAM_ICP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + hw_mgr_intf = &node->hw_mgr_intf; + if (!hw_mgr_intf) { + CAM_ERR(CAM_ICP, "hw_mgr_intf is not initialized"); + rc = -EINVAL; + goto end; + } + + rc = cam_node_shutdown(node); + if (rc < 0) { + CAM_ERR(CAM_ICP, "HW close failed"); + goto end; + } + +end: + mutex_unlock(&g_icp_dev.icp_lock); + return 0; +} + +const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { + .open = cam_icp_subdev_open, + .close = cam_icp_subdev_close, +}; + +static int cam_icp_probe(struct platform_device *pdev) +{ + int rc = 0, i = 0; + struct cam_node *node; + struct cam_hw_mgr_intf *hw_mgr_intf; + int iommu_hdl = -1; + + if (!pdev) { + CAM_ERR(CAM_ICP, "pdev is NULL"); + return -EINVAL; + } + + g_icp_dev.sd.pdev = pdev; + g_icp_dev.sd.internal_ops = &cam_icp_subdev_internal_ops; + rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME, + CAM_ICP_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_ICP, "ICP cam_subdev_probe failed"); + goto probe_fail; + } + + node = (struct cam_node *) g_icp_dev.sd.token; + + hw_mgr_intf = kzalloc(sizeof(*hw_mgr_intf), GFP_KERNEL); + if (!hw_mgr_intf) { + rc = -EINVAL; + goto hw_alloc_fail; + } + + rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf, + &iommu_hdl); + if (rc) { + CAM_ERR(CAM_ICP, "ICP HW manager init failed: %d", rc); + goto hw_init_fail; + } + + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { + g_icp_dev.ctx_icp[i].base = &g_icp_dev.ctx[i]; + rc = cam_icp_context_init(&g_icp_dev.ctx_icp[i], + hw_mgr_intf, i); + if (rc) { + CAM_ERR(CAM_ICP, "ICP context init failed"); + goto ctx_fail; + } + } + + rc = cam_node_init(node, hw_mgr_intf, g_icp_dev.ctx, + CAM_ICP_CTX_MAX, CAM_ICP_DEV_NAME); + if (rc) { + CAM_ERR(CAM_ICP, "ICP node init failed"); + goto ctx_fail; + } + + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_icp_dev_iommu_fault_handler, node); + + g_icp_dev.open_cnt = 0; + mutex_init(&g_icp_dev.icp_lock); + + CAM_DBG(CAM_ICP, "ICP probe complete"); + + return rc; + +ctx_fail: + for (--i; i >= 0; i--) + cam_icp_context_deinit(&g_icp_dev.ctx_icp[i]); +hw_init_fail: + kfree(hw_mgr_intf); +hw_alloc_fail: + cam_subdev_remove(&g_icp_dev.sd); +probe_fail: + return rc; +} + +static int cam_icp_remove(struct platform_device *pdev) +{ + int i; + struct v4l2_subdev *sd; + struct cam_subdev *subdev; + + if (!pdev) { + CAM_ERR(CAM_ICP, "pdev is NULL"); + return -ENODEV; + } + + sd = platform_get_drvdata(pdev); + if (!sd) { + CAM_ERR(CAM_ICP, "V4l2 subdev is NULL"); + return -ENODEV; + } + + subdev = v4l2_get_subdevdata(sd); + if (!subdev) { + CAM_ERR(CAM_ICP, "cam subdev is NULL"); + return -ENODEV; + } + + for (i = 0; i < CAM_ICP_CTX_MAX; i++) + cam_icp_context_deinit(&g_icp_dev.ctx_icp[i]); + cam_node_deinit(g_icp_dev.node); + cam_subdev_remove(&g_icp_dev.sd); + mutex_destroy(&g_icp_dev.icp_lock); + + return 0; +} + +static struct platform_driver cam_icp_driver = { + .probe = cam_icp_probe, + .remove = cam_icp_remove, + .driver = { + .name = "cam_icp", + .owner = THIS_MODULE, + .of_match_table = cam_icp_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_icp_init_module(void) +{ + return platform_driver_register(&cam_icp_driver); +} + +static void __exit cam_icp_exit_module(void) +{ + platform_driver_unregister(&cam_icp_driver); +} +module_init(cam_icp_init_module); +module_exit(cam_icp_exit_module); +MODULE_DESCRIPTION("MSM ICP driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h new file mode 100644 index 000000000000..1dcf4ee3668a --- /dev/null +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _HFI_INTF_H_ +#define _HFI_INTF_H_ + +#include + +/** + * struct hfi_mem + * @len: length of memory + * @kva: kernel virtual address + * @iova: IO virtual address + * @reserved: reserved field + */ +struct hfi_mem { + uint64_t len; + uintptr_t kva; + uint32_t iova; + uint32_t reserved; +}; + +/** + * struct hfi_mem_info + * @qtbl: qtable hfi memory + * @cmd_q: command queue hfi memory for host to firmware communication + * @msg_q: message queue hfi memory for firmware to host communication + * @dbg_q: debug queue hfi memory for firmware debug information + * @sfr_buf: buffer for subsystem failure reason[SFR] + * @sec_heap: secondary heap hfi memory for firmware + * @qdss: qdss mapped memory for fw + * @io_mem: io memory info + * @icp_base: icp base address + */ +struct hfi_mem_info { + struct hfi_mem qtbl; + struct hfi_mem cmd_q; + struct hfi_mem msg_q; + struct hfi_mem dbg_q; + struct hfi_mem sfr_buf; + struct hfi_mem sec_heap; + struct hfi_mem shmem; + struct hfi_mem qdss; + struct hfi_mem io_mem; + void __iomem *icp_base; +}; + +/** + * hfi_write_cmd() - function for hfi write + * @cmd_ptr: pointer to command data for hfi write + * + * Returns success(zero)/failure(non zero) + */ +int hfi_write_cmd(void *cmd_ptr); + +/** + * hfi_read_message() - function for hfi read + * @pmsg: buffer to place read message for hfi queue + * @q_id: queue id + * @words_read: total number of words read from the queue + * returned as output to the caller + * + * Returns success(zero)/failure(non zero) + */ +int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); + +/** + * hfi_init() - function initialize hfi after firmware download + * @event_driven_mode: event mode + * @hfi_mem: hfi memory info + * @icp_base: icp base address + * @debug: debug flag + * + * Returns success(zero)/failure(non zero) + */ +int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, + void *__iomem icp_base, bool debug); + +/** + * hfi_get_hw_caps() - hardware capabilities from firmware + * @query_caps: holds query information from hfi + * + * Returns success(zero)/failure(non zero) + */ +int hfi_get_hw_caps(void *query_caps); + +/** + * hfi_send_system_cmd() - send hfi system command to firmware + * @type: type of system command + * @data: command data + * @size: size of command data + */ +void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); + +/** + * cam_hfi_enable_cpu() - enable A5 CPU + * @icp_base: icp base address + */ +void cam_hfi_enable_cpu(void __iomem *icp_base); + +/** + * cam_hfi_disable_cpu() - disable A5 CPU + * @icp_base: icp base address + */ +void cam_hfi_disable_cpu(void __iomem *icp_base); + +/** + * cam_hfi_deinit() - cleanup HFI + */ +void cam_hfi_deinit(void __iomem *icp_base); +/** + * hfi_set_debug_level() - set debug level + * @a5_dbg_type: 1 for debug_q & 2 for qdss + * @lvl: FW debug message level + */ +int hfi_set_debug_level(u64 a5_dbg_type, uint32_t lvl); + +/** + * hfi_set_fw_dump_level() - set firmware dump level + * @lvl: level of firmware dump level + */ +int hfi_set_fw_dump_level(uint32_t lvl); + +/** + * hfi_enable_ipe_bps_pc() - Enable interframe pc + * Host sends a command to firmware to enable interframe + * power collapse for IPE and BPS hardware. + * + * @enable: flag to enable/disable + * @core_info: Core information to firmware + */ +int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info); + +/** + * hfi_cmd_ubwc_config_ext() - UBWC configuration to firmware + * @ubwc_ipe_cfg: UBWC ipe fetch/write configuration params + * @ubwc_bps_cfg: UBWC bps fetch/write configuration params + */ +int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg, + uint32_t *ubwc_bps_cfg); + +/** + * hfi_cmd_ubwc_config() - UBWC configuration to firmware + * for older targets + * @ubwc_cfg: UBWC configuration parameters + */ +int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg); + +/** + * cam_hfi_resume() - function to resume + * @hfi_mem: hfi memory info + * @icp_base: icp base address + * @debug: debug flag + * + * Returns success(zero)/failure(non zero) + */ +int cam_hfi_resume(struct hfi_mem_info *hfi_mem, + void __iomem *icp_base, bool debug); + +/** + * cam_hfi_queue_dump() - utility function to dump hfi queues + */ +void cam_hfi_queue_dump(void); + + +#endif /* _HFI_INTF_H_ */ diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h new file mode 100644 index 000000000000..f67a7044f26b --- /dev/null +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -0,0 +1,336 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_HFI_REG_H_ +#define _CAM_HFI_REG_H_ + +#include +#include "hfi_intf.h" + + +/* start of ICP CSR registers */ +#define HFI_REG_A5_HW_VERSION 0x0 +#define HFI_REG_A5_CSR_NSEC_RESET 0x4 +#define HFI_REG_A5_CSR_A5_CONTROL 0x8 +#define HFI_REG_A5_CSR_ETM 0xC +#define HFI_REG_A5_CSR_A2HOSTINTEN 0x10 +#define HFI_REG_A5_CSR_A2HOSTINT 0x14 +#define HFI_REG_A5_CSR_A2HOSTINTCLR 0x18 +#define HFI_REG_A5_CSR_A2HOSTINTSTATUS 0x1C +#define HFI_REG_A5_CSR_A2HOSTINTSET 0x20 +#define HFI_REG_A5_CSR_HOST2ICPINT 0x30 +#define HFI_REG_A5_CSR_A5_STATUS 0x200 +#define HFI_REG_A5_QGIC2_LM_ID 0x204 +#define HFI_REG_A5_SPARE 0x400 + +/* general purpose registers from */ +#define HFI_REG_FW_VERSION 0x44 +#define HFI_REG_HOST_ICP_INIT_REQUEST 0x48 +#define HFI_REG_ICP_HOST_INIT_RESPONSE 0x4C +#define HFI_REG_SHARED_MEM_PTR 0x50 +#define HFI_REG_SHARED_MEM_SIZE 0x54 +#define HFI_REG_QTBL_PTR 0x58 +#define HFI_REG_UNCACHED_HEAP_PTR 0x5C +#define HFI_REG_UNCACHED_HEAP_SIZE 0x60 +#define HFI_REG_QDSS_IOVA 0x6C +#define HFI_REG_SFR_PTR 0x68 +#define HFI_REG_QDSS_IOVA_SIZE 0x70 +#define HFI_REG_IO_REGION_IOVA 0x74 +#define HFI_REG_IO_REGION_SIZE 0x78 + +/* end of ICP CSR registers */ + +/* flags for ICP CSR registers */ +#define ICP_FLAG_CSR_WAKE_UP_EN (1 << 4) +#define ICP_FLAG_CSR_A5_EN (1 << 9) +#define ICP_CSR_EN_CLKGATE_WFI (1 << 12) +#define ICP_CSR_EDBGRQ (1 << 14) +#define ICP_CSR_DBGSWENABLE (1 << 22) +#define ICP_CSR_A5_STATUS_WFI (1 << 7) + +#define ICP_FLAG_A5_CTRL_DBG_EN (ICP_FLAG_CSR_WAKE_UP_EN|\ + ICP_FLAG_CSR_A5_EN|\ + ICP_CSR_EDBGRQ|\ + ICP_CSR_DBGSWENABLE) + +#define ICP_FLAG_A5_CTRL_EN (ICP_FLAG_CSR_WAKE_UP_EN|\ + ICP_FLAG_CSR_A5_EN|\ + ICP_CSR_EN_CLKGATE_WFI) + +/* start of Queue table and queues */ +#define MAX_ICP_HFI_QUEUES 4 +#define ICP_QHDR_TX_TYPE_MASK 0xFF000000 +#define ICP_QHDR_RX_TYPE_MASK 0x00FF0000 +#define ICP_QHDR_PRI_TYPE_MASK 0x0000FF00 +#define ICP_QHDR_Q_ID_MASK 0x000000FF + +#define ICP_CMD_Q_SIZE_IN_BYTES 4096 +#define ICP_MSG_Q_SIZE_IN_BYTES 4096 +#define ICP_DBG_Q_SIZE_IN_BYTES 102400 +#define ICP_MSG_SFR_SIZE_IN_BYTES 4096 + +#define ICP_SHARED_MEM_IN_BYTES (1024 * 1024) +#define ICP_UNCACHED_HEAP_SIZE_IN_BYTES (2 * 1024 * 1024) +#define ICP_HFI_MAX_PKT_SIZE_IN_WORDS 25600 +#define ICP_HFI_MAX_PKT_SIZE_MSGQ_IN_WORDS 256 + +#define ICP_HFI_QTBL_HOSTID1 0x01000000 +#define ICP_HFI_QTBL_STATUS_ENABLED 0x00000001 +#define ICP_HFI_NUMBER_OF_QS 3 +#define ICP_HFI_NUMBER_OF_ACTIVE_QS 3 +#define ICP_HFI_QTBL_OFFSET 0 +#define ICP_HFI_VAR_SIZE_PKT 0 +#define ICP_HFI_MAX_MSG_SIZE_IN_WORDS 128 + + +/* Queue Header type masks. Use these to access bitfields in qhdr_type */ +#define HFI_MASK_QHDR_TX_TYPE 0xFF000000 +#define HFI_MASK_QHDR_RX_TYPE 0x00FF0000 +#define HFI_MASK_QHDR_PRI_TYPE 0x0000FF00 +#define HFI_MASK_QHDR_Q_ID_TYPE 0x000000FF + + +#define TX_EVENT_DRIVEN_MODE_1 0 +#define RX_EVENT_DRIVEN_MODE_1 0 +#define TX_EVENT_DRIVEN_MODE_2 0x01000000 +#define RX_EVENT_DRIVEN_MODE_2 0x00010000 +#define TX_EVENT_POLL_MODE_2 0x02000000 +#define RX_EVENT_POLL_MODE_2 0x00020000 +#define U32_OFFSET 0x1 +#define BYTE_WORD_SHIFT 2 + +/** + * @INVALID: Invalid state + * @HFI_DEINIT: HFI is not initialized yet + * @HFI_INIT: HFI is initialized + * @HFI_READY: HFI is ready to send/receive commands/messages + */ +enum hfi_state { + HFI_DEINIT, + HFI_INIT, + HFI_READY +}; + +/** + * @RESET: init success + * @SET: init failed + */ +enum reg_settings { + RESET, + SET, + SET_WM = 1024 +}; + +/** + * @INTR_DISABLE: Disable interrupt + * @INTR_ENABLE: Enable interrupt + * @INTR_ENABLE_WD0: Enable WD0 + * @INTR_ENABLE_WD1: Enable WD1 + */ +enum intr_status { + INTR_DISABLE, + INTR_ENABLE, + INTR_ENABLE_WD0, + INTR_ENABLE_WD1 = 0x4 +}; + +/** + * @ICP_INIT_RESP_RESET: reset init state + * @ICP_INIT_RESP_SUCCESS: init success + * @ICP_INIT_RESP_FAILED: init failed + */ +enum host_init_resp { + ICP_INIT_RESP_RESET, + ICP_INIT_RESP_SUCCESS, + ICP_INIT_RESP_FAILED +}; + +/** + * @ICP_INIT_REQUEST_RESET: reset init request + * @ICP_INIT_REQUEST_SET: set init request + */ +enum host_init_request { + ICP_INIT_REQUEST_RESET, + ICP_INIT_REQUEST_SET +}; + +/** + * @QHDR_INACTIVE: Queue is inactive + * @QHDR_ACTIVE: Queue is active + */ +enum qhdr_status { + QHDR_INACTIVE, + QHDR_ACTIVE +}; + +/** + * @INTR_MODE: event driven mode 1, each send and receive generates interrupt + * @WM_MODE: event driven mode 2, interrupts based on watermark mechanism + * @POLL_MODE: poll method + */ +enum qhdr_event_drv_type { + INTR_MODE, + WM_MODE, + POLL_MODE +}; + +/** + * @TX_INT: event driven mode 1, each send and receive generates interrupt + * @TX_INT_WM: event driven mode 2, interrupts based on watermark mechanism + * @TX_POLL: poll method + * @ICP_QHDR_TX_TYPE_MASK defines position in qhdr_type + */ +enum qhdr_tx_type { + TX_INT, + TX_INT_WM, + TX_POLL +}; + +/** + * @RX_INT: event driven mode 1, each send and receive generates interrupt + * @RX_INT_WM: event driven mode 2, interrupts based on watermark mechanism + * @RX_POLL: poll method + * @ICP_QHDR_RX_TYPE_MASK defines position in qhdr_type + */ +enum qhdr_rx_type { + RX_INT, + RX_INT_WM, + RX_POLL +}; + +/** + * @Q_CMD: Host to FW command queue + * @Q_MSG: FW to Host message queue + * @Q_DEBUG: FW to Host debug queue + * @ICP_QHDR_Q_ID_MASK defines position in qhdr_type + */ +enum qhdr_q_id { + Q_CMD, + Q_MSG, + Q_DBG +}; + +/** + * struct hfi_qtbl_hdr + * @qtbl_version: Queue table version number + * Higher 16 bits: Major version + * Lower 16 bits: Minor version + * @qtbl_size: Queue table size from version to last parametr in qhdr entry + * @qtbl_qhdr0_offset: Offset to the start of first qhdr + * @qtbl_qhdr_size: Queue header size in bytes + * @qtbl_num_q: Total number of queues in Queue table + * @qtbl_num_active_q: Total number of active queues + */ +struct hfi_qtbl_hdr { + uint32_t qtbl_version; + uint32_t qtbl_size; + uint32_t qtbl_qhdr0_offset; + uint32_t qtbl_qhdr_size; + uint32_t qtbl_num_q; + uint32_t qtbl_num_active_q; +} __packed; + +/** + * struct hfi_q_hdr + * @qhdr_status: Queue status, qhdr_state define possible status + * @qhdr_start_addr: Queue start address in non cached memory + * @qhdr_type: qhdr_tx, qhdr_rx, qhdr_q_id and priority defines qhdr type + * @qhdr_q_size: Queue size + * Number of queue packets if qhdr_pkt_size is non-zero + * Queue size in bytes if qhdr_pkt_size is zero + * @qhdr_pkt_size: Size of queue packet entries + * 0x0: variable queue packet size + * non zero: size of queue packet entry, fixed + * @qhdr_pkt_drop_cnt: Number of packets dropped by sender + * @qhdr_rx_wm: Receiver watermark, applicable in event driven mode + * @qhdr_tx_wm: Sender watermark, applicable in event driven mode + * @qhdr_rx_req: Receiver sets this bit if queue is empty + * @qhdr_tx_req: Sender sets this bit if queue is full + * @qhdr_rx_irq_status: Receiver sets this bit and triggers an interrupt to + * the sender after packets are dequeued. Sender clears this bit + * @qhdr_tx_irq_status: Sender sets this bit and triggers an interrupt to + * the receiver after packets are queued. Receiver clears this bit + * @qhdr_read_idx: Read index + * @qhdr_write_idx: Write index + */ +struct hfi_q_hdr { + uint32_t dummy[15]; + uint32_t qhdr_status; + uint32_t dummy1[15]; + uint32_t qhdr_start_addr; + uint32_t dummy2[15]; + uint32_t qhdr_type; + uint32_t dummy3[15]; + uint32_t qhdr_q_size; + uint32_t dummy4[15]; + uint32_t qhdr_pkt_size; + uint32_t dummy5[15]; + uint32_t qhdr_pkt_drop_cnt; + uint32_t dummy6[15]; + uint32_t qhdr_rx_wm; + uint32_t dummy7[15]; + uint32_t qhdr_tx_wm; + uint32_t dummy8[15]; + uint32_t qhdr_rx_req; + uint32_t dummy9[15]; + uint32_t qhdr_tx_req; + uint32_t dummy10[15]; + uint32_t qhdr_rx_irq_status; + uint32_t dummy11[15]; + uint32_t qhdr_tx_irq_status; + uint32_t dummy12[15]; + uint32_t qhdr_read_idx; + uint32_t dummy13[15]; + uint32_t qhdr_write_idx; + uint32_t dummy14[15]; +}; + +/** + * struct sfr_buf + * @size: Number of characters + * @msg : Subsystem failure reason + */ +struct sfr_buf { + uint32_t size; + char msg[ICP_MSG_SFR_SIZE_IN_BYTES]; +}; + +/** + * struct hfi_q_tbl + * @q_tbl_hdr: Queue table header + * @q_hdr: Queue header info, it holds info of cmd, msg and debug queues + */ +struct hfi_qtbl { + struct hfi_qtbl_hdr q_tbl_hdr; + struct hfi_q_hdr q_hdr[MAX_ICP_HFI_QUEUES]; +}; + +/** + * struct hfi_info + * @map: Hfi shared memory info + * @smem_size: Shared memory size + * @uncachedheap_size: uncached heap size + * @msgpacket_buf: message buffer + * @hfi_state: State machine for hfi + * @cmd_q_lock: Lock for command queue + * @cmd_q_state: State of command queue + * @mutex msg_q_lock: Lock for message queue + * @msg_q_state: State of message queue + * @csr_base: CSR base address + */ +struct hfi_info { + struct hfi_mem_info map; + uint32_t smem_size; + uint32_t uncachedheap_size; + uint32_t msgpacket_buf[ICP_HFI_MAX_MSG_SIZE_IN_WORDS]; + uint8_t hfi_state; + struct mutex cmd_q_lock; + bool cmd_q_state; + struct mutex msg_q_lock; + bool msg_q_state; + void __iomem *csr_base; +}; + +#endif /* _CAM_HFI_REG_H_ */ diff --git a/drivers/cam_icp/fw_inc/hfi_session_defs.h b/drivers/cam_icp/fw_inc/hfi_session_defs.h new file mode 100644 index 000000000000..e50b5d147a2f --- /dev/null +++ b/drivers/cam_icp/fw_inc/hfi_session_defs.h @@ -0,0 +1,564 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_HFI_SESSION_DEFS_H +#define _CAM_HFI_SESSION_DEFS_H + +#include + +#define HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO 0x1 +#define HFI_IPEBPS_CMD_OPCODE_BPS_FRAME_PROCESS 0x2 +#define HFI_IPEBPS_CMD_OPCODE_BPS_ABORT 0x3 +#define HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY 0x4 + +#define HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO 0x5 +#define HFI_IPEBPS_CMD_OPCODE_IPE_FRAME_PROCESS 0x6 +#define HFI_IPEBPS_CMD_OPCODE_IPE_ABORT 0x7 +#define HFI_IPEBPS_CMD_OPCODE_IPE_DESTROY 0x8 + +#define HFI_IPEBPS_CMD_OPCODE_BPS_WAIT_FOR_IPE 0x9 +#define HFI_IPEBPS_CMD_OPCODE_BPS_WAIT_FOR_BPS 0xa +#define HFI_IPEBPS_CMD_OPCODE_IPE_WAIT_FOR_BPS 0xb +#define HFI_IPEBPS_CMD_OPCODE_IPE_WAIT_FOR_IPE 0xc + +#define HFI_IPEBPS_CMD_OPCODE_MEM_MAP 0xe +#define HFI_IPEBPS_CMD_OPCODE_MEM_UNMAP 0xf + +#define HFI_IPEBPS_HANDLE_TYPE_BPS 0x1 +#define HFI_IPEBPS_HANDLE_TYPE_IPE_RT 0x2 +#define HFI_IPEBPS_HANDLE_TYPE_IPE_NON_RT 0x3 + +/** + * struct mem_map_region_data + * @start_addr: cmd buffer region start addr + * @len : length of the region + * + * create mem_map_region_data + */ +struct mem_map_region_data { + uint32_t start_addr; + uint32_t len; +}; + +/** + * struct hfi_cmd_ipe_bps_map + * @user_data : user arg + * @mem_map_request_num: number of mappings + * @mem_map_region_sets: array of all map/unmap info + * + * create hfi_cmd_ipe_bps_map + */ +struct hfi_cmd_ipe_bps_map { + uint64_t user_data; + uint32_t mem_map_request_num; + struct mem_map_region_data mem_map_region_sets[1]; +} __packed; + +/** + * struct hfi_cmd_ipe_bps_map_ack + * @rc : Async return code + * @user_data: user_arg + * + * create hfi_cmd_ipe_bps_map_ack + */ +struct hfi_cmd_ipe_bps_map_ack { + uint32_t rc; + uint64_t user_data; +}; + +/** + * struct abort_data + * @num_req_ids: Number of req ids + * @num_req_id: point to specific req id + * + * create abort data + */ +struct abort_data { + uint32_t num_req_ids; + uint32_t num_req_id[1]; +}; + +/** + * struct hfi_cmd_data + * @abort: abort data + * @user data: user supplied argument + * + * create session abort data + */ +struct hfi_cmd_abort { + struct abort_data abort; + uint64_t user_data; +} __packed; + +/** + * struct hfi_cmd_abort_destroy + * @user_data: user supplied data + * + * IPE/BPS destroy/abort command + * @HFI_IPEBPS_CMD_OPCODE_IPE_ABORT + * @HFI_IPEBPS_CMD_OPCODE_BPS_ABORT + * @HFI_IPEBPS_CMD_OPCODE_IPE_DESTROY + * @HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY + */ +struct hfi_cmd_abort_destroy { + uint64_t user_data; +} __packed; + +/** + * struct hfi_cmd_chaining_ops + * @wait_hdl: current session handle waits on wait_hdl to complete operation + * @user_data: user supplied argument + * + * this structure for chaining opcodes + * BPS_WAITS_FOR_IPE + * BPS_WAITS_FOR_BPS + * IPE_WAITS_FOR_BPS + * IPE_WAITS_FOR_IPE + */ +struct hfi_cmd_chaining_ops { + uint32_t wait_hdl; + uint64_t user_data; +} __packed; + +/** + * struct hfi_cmd_create_handle + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @handle_type: IPE/BPS firmware session handle type + * @user_data1: caller provided data1 + * @user_data2: caller provided data2 + * + * create firmware session handle + */ +struct hfi_cmd_create_handle { + uint32_t size; + uint32_t pkt_type; + uint32_t handle_type; + uint64_t user_data1; + uint64_t user_data2; +} __packed; + +/** + * struct hfi_cmd_ipebps_async + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @opcode: opcode for IPE/BPS async operation + * CONFIG_IO: configures I/O for IPE/BPS handle + * FRAME_PROCESS: image frame to be processed by IPE/BPS + * ABORT: abort all processing frames of IPE/BPS handle + * DESTROY: destroy earlier created IPE/BPS handle + * BPS_WAITS_FOR_IPE: sync for BPS to wait for IPE + * BPS_WAITS_FOR_BPS: sync for BPS to wait for BPS + * IPE_WAITS_FOR_IPE: sync for IPE to wait for IPE + * IPE_WAITS_FOR_BPS: sync for IPE to wait for BPS + * @num_fw_handles: number of IPE/BPS firmware handles in fw_handles array + * @fw_handles: IPE/BPS handles array + * @payload: command payload for IPE/BPS opcodes + * @direct: points to actual payload + * @indirect: points to address of payload + * + * sends async command to the earlier created IPE or BPS handle + * for asynchronous operation. + */ +struct hfi_cmd_ipebps_async { + uint32_t size; + uint32_t pkt_type; + uint32_t opcode; + uint64_t user_data1; + uint64_t user_data2; + uint32_t num_fw_handles; + uint32_t fw_handles[1]; + union { + uint32_t direct[1]; + uint32_t indirect; + } payload; +} __packed; + +/** + * struct hfi_msg_create_handle_ack + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @err_type: error code + * @fw_handle: output param for IPE/BPS handle + * @user_data1: user provided data1 + * @user_data2: user provided data2 + * + * ack for create handle command of IPE/BPS + * @HFI_MSG_IPEBPS_CREATE_HANDLE_ACK + */ +struct hfi_msg_create_handle_ack { + uint32_t size; + uint32_t pkt_type; + uint32_t err_type; + uint32_t fw_handle; + uint64_t user_data1; + uint64_t user_data2; +} __packed; + +/** + * struct hfi_msg_ipebps_async + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @opcode: opcode of IPE/BPS async operation + * @user_data1: user provided data1 + * @user_data2: user provided data2 + * @err_type: error code + * @msg_data: IPE/BPS async done message data + * + * result of IPE/BPS async command + * @HFI_MSG_IPEBPS_ASYNC_COMMAND_ACK + */ +struct hfi_msg_ipebps_async_ack { + uint32_t size; + uint32_t pkt_type; + uint32_t opcode; + uint64_t user_data1; + uint64_t user_data2; + uint32_t err_type; + uint32_t msg_data[1]; +} __packed; + +/** + * struct hfi_msg_frame_process_done + * @result: result of frame process command + * @scratch_buffer_address: address of scratch buffer + */ +struct hfi_msg_frame_process_done { + uint32_t result; + uint32_t scratch_buffer_address; +}; + +/** + * struct hfi_msg_chaining_op + * @status: return status + * @user_data: user data provided as part of chaining ops + * + * IPE/BPS wait response + */ +struct hfi_msg_chaining_op { + uint32_t status; + uint64_t user_data; +} __packed; + +/** + * struct hfi_msg_abort_destroy + * @status: return status + * @user_data: user data provided as part of abort/destroy ops + * + * IPE/BPS abort/destroy response + */ +struct hfi_msg_abort_destroy { + uint32_t status; + uint64_t user_data; +} __packed; + +#define MAX_NUM_OF_IMAGE_PLANES 2 +#define MAX_HFR_GROUP 16 + +enum hfi_ipe_io_images { + IPE_INPUT_IMAGE_FULL, + IPE_INPUT_IMAGE_DS4, + IPE_INPUT_IMAGE_DS16, + IPE_INPUT_IMAGE_DS64, + IPE_INPUT_IMAGE_FULL_REF, + IPE_INPUT_IMAGE_DS4_REF, + IPE_INPUT_IMAGE_DS16_REF, + IPE_INPUT_IMAGE_DS64_REF, + IPE_OUTPUT_IMAGE_DISPLAY, + IPE_OUTPUT_IMAGE_VIDEO, + IPE_OUTPUT_IMAGE_FULL_REF, + IPE_OUTPUT_IMAGE_DS4_REF, + IPE_OUTPUT_IMAGE_DS16_REF, + IPE_OUTPUT_IMAGE_DS64_REF, + IPE_INPUT_IMAGE_FIRST = IPE_INPUT_IMAGE_FULL, + IPE_INPUT_IMAGE_LAST = IPE_INPUT_IMAGE_DS64_REF, + IPE_OUTPUT_IMAGE_FIRST = IPE_OUTPUT_IMAGE_DISPLAY, + IPE_OUTPUT_IMAGE_LAST = IPE_OUTPUT_IMAGE_DS64_REF, + IPE_IO_IMAGES_MAX +}; + +enum bps_io_images { + BPS_INPUT_IMAGE, + BPS_OUTPUT_IMAGE_FULL, + BPS_OUTPUT_IMAGE_DS4, + BPS_OUTPUT_IMAGE_DS16, + BPS_OUTPUT_IMAGE_DS64, + BPS_OUTPUT_IMAGE_STATS_BG, + BPS_OUTPUT_IMAGE_STATS_BHIST, + BPS_OUTPUT_IMAGE_REG1, + BPS_OUTPUT_IMAGE_REG2, + BPS_OUTPUT_IMAGE_FIRST = BPS_OUTPUT_IMAGE_FULL, + BPS_OUTPUT_IMAGE_LAST = BPS_OUTPUT_IMAGE_REG2, + BPS_IO_IMAGES_MAX +}; + +struct frame_buffer { + uint32_t buf_ptr[MAX_NUM_OF_IMAGE_PLANES]; + uint32_t meta_buf_ptr[MAX_NUM_OF_IMAGE_PLANES]; +} __packed; + +struct bps_frame_process_data { + struct frame_buffer buffers[BPS_IO_IMAGES_MAX]; + uint32_t max_num_cores; + uint32_t target_time; + uint32_t ubwc_stats_buffer_addr; + uint32_t ubwc_stats_buffer_size; + uint32_t cdm_buffer_addr; + uint32_t cdm_buffer_size; + uint32_t iq_settings_addr; + uint32_t strip_lib_out_addr; + uint32_t cdm_prog_addr; + uint32_t request_id; +}; + +enum hfi_ipe_image_format { + IMAGE_FORMAT_INVALID, + IMAGE_FORMAT_MIPI_8, + IMAGE_FORMAT_MIPI_10, + IMAGE_FORMAT_MIPI_12, + IMAGE_FORMAT_MIPI_14, + IMAGE_FORMAT_BAYER_8, + IMAGE_FORMAT_BAYER_10, + IMAGE_FORMAT_BAYER_12, + IMAGE_FORMAT_BAYER_14, + IMAGE_FORMAT_PDI_10, + IMAGE_FORMAT_PD_10, + IMAGE_FORMAT_PD_8, + IMAGE_FORMAT_INDICATIONS, + IMAGE_FORMAT_REFINEMENT, + IMAGE_FORMAT_UBWC_TP_10, + IMAGE_FORMAT_UBWC_NV_12, + IMAGE_FORMAT_UBWC_NV12_4R, + IMAGE_FORMAT_UBWC_P010, + IMAGE_FORMAT_LINEAR_TP_10, + IMAGE_FORMAT_LINEAR_P010, + IMAGE_FORMAT_LINEAR_NV12, + IMAGE_FORMAT_LINEAR_PLAIN_16, + IMAGE_FORMAT_YUV422_8, + IMAGE_FORMAT_YUV422_10, + IMAGE_FORMAT_STATISTICS_BAYER_GRID, + IMAGE_FORMAT_STATISTICS_BAYER_HISTOGRAM, + IMAGE_FORMAT_MAX +}; + +enum hfi_ipe_plane_format { + PLANE_FORMAT_INVALID = 0, + PLANE_FORMAT_MIPI_8, + PLANE_FORMAT_MIPI_10, + PLANE_FORMAT_MIPI_12, + PLANE_FORMAT_MIPI_14, + PLANE_FORMAT_BAYER_8, + PLANE_FORMAT_BAYER_10, + PLANE_FORMAT_BAYER_12, + PLANE_FORMAT_BAYER_14, + PLANE_FORMAT_PDI_10, + PLANE_FORMAT_PD_10, + PLANE_FORMAT_PD_8, + PLANE_FORMAT_INDICATIONS, + PLANE_FORMAT_REFINEMENT, + PLANE_FORMAT_UBWC_TP_10_Y, + PLANE_FORMAT_UBWC_TP_10_C, + PLANE_FORMAT_UBWC_NV_12_Y, + PLANE_FORMAT_UBWC_NV_12_C, + PLANE_FORMAT_UBWC_NV_12_4R_Y, + PLANE_FORMAT_UBWC_NV_12_4R_C, + PLANE_FORMAT_UBWC_P010_Y, + PLANE_FORMAT_UBWC_P010_C, + PLANE_FORMAT_LINEAR_TP_10_Y, + PLANE_FORMAT_LINEAR_TP_10_C, + PLANE_FORMAT_LINEAR_P010_Y, + PLANE_FORMAT_LINEAR_P010_C, + PLANE_FORMAT_LINEAR_NV12_Y, + PLANE_FORMAT_LINEAR_NV12_C, + PLANE_FORMAT_LINEAR_PLAIN_16_Y, + PLANE_FORMAT_LINEAR_PLAIN_16_C, + PLANE_FORMAT_YUV422_8, + PLANE_FORMAT_YUV422_10, + PLANE_FORMAT_STATISTICS_BAYER_GRID, + PLANE_FORMAT_STATISTICS_BAYER_HISTOGRAM, + PLANE_FORMAT_MAX +}; + +enum hfi_ipe_bayer_pixel_order { + FIRST_PIXEL_R, + FIRST_PIXEL_GR, + FIRST_PIXEL_B, + FIRST_PIXEL_GB, + FIRST_PIXEL_MAX +}; + +enum hfi_ipe_pixel_pack_alignment { + PIXEL_LSB_ALIGNED, + PIXEL_MSB_ALIGNED, +}; + +enum hfi_ipe_yuv_422_order { + PIXEL_ORDER_Y_U_Y_V, + PIXEL_ORDER_Y_V_Y_U, + PIXEL_ORDER_U_Y_V_Y, + PIXEL_ORDER_V_Y_U_Y, + PIXEL_ORDER_YUV422_MAX +}; + +enum ubwc_write_client { + IPE_WR_CLIENT_0 = 0, + IPE_WR_CLIENT_1, + IPE_WR_CLIENT_5, + IPE_WR_CLIENT_6, + IPE_WR_CLIENT_7, + IPE_WR_CLIENT_8, + IPE_WR_CLIENT_MAX +}; + +/** + * struct image_info + * @format: image format + * @img_width: image width + * @img_height: image height + * @bayer_order: pixel order + * @pix_align: alignment + * @yuv422_order: YUV order + * @byte_swap: byte swap + */ +struct image_info { + enum hfi_ipe_image_format format; + uint32_t img_width; + uint32_t img_height; + enum hfi_ipe_bayer_pixel_order bayer_order; + enum hfi_ipe_pixel_pack_alignment pix_align; + enum hfi_ipe_yuv_422_order yuv422_order; + uint32_t byte_swap; +} __packed; + +/** + * struct buffer_layout + * @buf_stride: buffer stride + * @buf_height: buffer height + */ +struct buffer_layout { + uint32_t buf_stride; + uint32_t buf_height; +} __packed; + +/** + * struct image_desc + * @info: image info + * @buf_layout: buffer layout + * @meta_buf_layout: meta buffer layout + */ +struct image_desc { + struct image_info info; + struct buffer_layout buf_layout[MAX_NUM_OF_IMAGE_PLANES]; + struct buffer_layout meta_buf_layout[MAX_NUM_OF_IMAGE_PLANES]; +} __packed; + +struct ica_stab_coeff { + uint32_t coeffs[8]; +} __packed; + +struct ica_stab_params { + uint32_t mode; + struct ica_stab_coeff transforms[3]; +} __packed; + +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; + +struct ipe_frame_process_data { + uint32_t strip_lib_out_addr; + uint32_t iq_settings_addr; + uint32_t scratch_buffer_addr; + uint32_t scratch_buffer_size; + uint32_t ubwc_stats_buffer_addr; + uint32_t ubwc_stats_buffer_size; + uint32_t cdm_buffer_addr; + uint32_t cdm_buffer_size; + uint32_t max_num_cores; + uint32_t target_time; + uint32_t cdm_prog_base; + uint32_t cdm_pre_ltm; + uint32_t cdm_post_ltm; + uint32_t cdm_anr_full_pass; + uint32_t cdm_anr_ds4; + uint32_t cdm_anr_ds16; + uint32_t cdm_anr_ds64; + uint32_t cdm_tf_full_pass; + uint32_t cdm_tf_ds4; + uint32_t cdm_tf_ds16; + uint32_t cdm_tf_ds64; + uint32_t request_id; + uint32_t frames_in_batch; + struct frame_set framesets[MAX_HFR_GROUP]; +} __packed; + +/** + * struct hfi_cmd_ipe_config + * @images: images descreptions + * @user_data: user supplied data + * + * payload for IPE async command + */ +struct hfi_cmd_ipe_config { + struct image_desc images[IPE_IO_IMAGES_MAX]; + uint64_t user_data; +} __packed; + +/** + * struct frame_buffers + * @buf_ptr: buffer pointers for all planes + * @meta_buf_ptr: meta buffer pointers for all planes + */ +struct frame_buffers { + uint32_t buf_ptr[MAX_NUM_OF_IMAGE_PLANES]; + uint32_t meta_buf_ptr[MAX_NUM_OF_IMAGE_PLANES]; +} __packed; + +/** + * struct hfi_msg_ipe_config + * @rc: result of ipe config command + * @scratch_mem_size: scratch mem size for a config + * @user_data: user data + */ +struct hfi_msg_ipe_config { + uint32_t rc; + uint32_t scratch_mem_size; + uint64_t user_data; +} __packed; + +/** + * struct hfi_msg_bps_common + * @rc: result of ipe config command + * @user_data: user data + */ +struct hfi_msg_bps_common { + uint32_t rc; + uint64_t user_data; +} __packed; + +/** + * struct ipe_bps_destroy + * @user_data: user data + */ +struct ipe_bps_destroy { + uint64_t userdata; +}; + +/** + * struct hfi_msg_ipe_frame_process + * @status: result of ipe frame process command + * @scratch_buf_addr: address of scratch buffer + * @user_data: user data + */ +struct hfi_msg_ipe_frame_process { + uint32_t status; + uint32_t scratch_buf_addr; + uint64_t user_data; +} __packed; + +#endif /* _CAM_HFI_SESSION_DEFS_H */ diff --git a/drivers/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/cam_icp/fw_inc/hfi_sys_defs.h new file mode 100644 index 000000000000..ddd9bf15c6aa --- /dev/null +++ b/drivers/cam_icp/fw_inc/hfi_sys_defs.h @@ -0,0 +1,540 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _HFI_DEFS_H_ +#define _HFI_DEFS_H_ + +#include + +/* + * Following base acts as common starting points + * for all enumerations. + */ +#define HFI_COMMON_BASE 0x0 + +/* HFI Domain base offset for commands and messages */ +#define HFI_DOMAIN_SHFT (24) +#define HFI_DOMAIN_BMSK (0x7 << HFI_DOMAIN_SHFT) +#define HFI_DOMAIN_BASE_ICP (0x0 << HFI_DOMAIN_SHFT) +#define HFI_DOMAIN_BASE_IPE_BPS (0x1 << HFI_DOMAIN_SHFT) +#define HFI_DOMAIN_BASE_CDM (0x2 << HFI_DOMAIN_SHFT) +#define HFI_DOMAIN_BASE_DBG (0x3 << HFI_DOMAIN_SHFT) + +/* Command base offset for commands */ +#define HFI_CMD_START_OFFSET 0x10000 + +/* Command base offset for messages */ +#define HFI_MSG_START_OFFSET 0x20000 + +/* System Level Error types */ +#define HFI_ERR_SYS_NONE (HFI_COMMON_BASE) +#define HFI_ERR_SYS_FATAL (HFI_COMMON_BASE + 0x1) +#define HFI_ERR_SYS_VERSION_MISMATCH (HFI_COMMON_BASE + 0x2) +#define HFI_ERR_SYS_UNSUPPORTED_DOMAIN (HFI_COMMON_BASE + 0x3) +#define HFI_ERR_SYS_UNSUPPORT_CMD (HFI_COMMON_BASE + 0x4) +#define HFI_ERR_SYS_CMDFAILED (HFI_COMMON_BASE + 0x5) +#define HFI_ERR_SYS_CMDSIZE (HFI_COMMON_BASE + 0x6) + +/* System Level Event types */ +#define HFI_EVENT_SYS_ERROR (HFI_COMMON_BASE + 0x1) +#define HFI_EVENT_ICP_ERROR (HFI_COMMON_BASE + 0x2) +#define HFI_EVENT_IPE_BPS_ERROR (HFI_COMMON_BASE + 0x3) +#define HFI_EVENT_CDM_ERROR (HFI_COMMON_BASE + 0x4) +#define HFI_EVENT_DBG_ERROR (HFI_COMMON_BASE + 0x5) + +/* Core level start Ranges for errors */ +#define HFI_ERR_ICP_START (HFI_COMMON_BASE + 0x64) +#define HFI_ERR_IPE_BPS_START (HFI_ERR_ICP_START + 0x64) +#define HFI_ERR_CDM_START (HFI_ERR_IPE_BPS_START + 0x64) +#define HFI_ERR_DBG_START (HFI_ERR_CDM_START + 0x64) + +/*ICP Core level error messages */ +#define HFI_ERR_NO_RES (HFI_ERR_ICP_START + 0x1) +#define HFI_ERR_UNSUPPORTED_RES (HFI_ERR_ICP_START + 0x2) +#define HFI_ERR_UNSUPPORTED_PROP (HFI_ERR_ICP_START + 0x3) +#define HFI_ERR_INIT_EXPECTED (HFI_ERR_ICP_START + 0x4) +#define HFI_ERR_INIT_IGNORED (HFI_ERR_ICP_START + 0x5) + +/* System level commands */ +#define HFI_CMD_COMMON_START \ + (HFI_DOMAIN_BASE_ICP + HFI_CMD_START_OFFSET + 0x0) +#define HFI_CMD_SYS_INIT (HFI_CMD_COMMON_START + 0x1) +#define HFI_CMD_SYS_PC_PREP (HFI_CMD_COMMON_START + 0x2) +#define HFI_CMD_SYS_SET_PROPERTY (HFI_CMD_COMMON_START + 0x3) +#define HFI_CMD_SYS_GET_PROPERTY (HFI_CMD_COMMON_START + 0x4) +#define HFI_CMD_SYS_PING (HFI_CMD_COMMON_START + 0x5) +#define HFI_CMD_SYS_RESET (HFI_CMD_COMMON_START + 0x6) + +/* Core level commands */ +/* IPE/BPS core Commands */ +#define HFI_CMD_IPE_BPS_COMMON_START \ + (HFI_DOMAIN_BASE_IPE_BPS + HFI_CMD_START_OFFSET + 0x0) +#define HFI_CMD_IPEBPS_CREATE_HANDLE \ + (HFI_CMD_IPE_BPS_COMMON_START + 0x8) +#define HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT \ + (HFI_CMD_IPE_BPS_COMMON_START + 0xa) +#define HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT \ + (HFI_CMD_IPE_BPS_COMMON_START + 0xe) + +/* CDM core Commands */ +#define HFI_CMD_CDM_COMMON_START \ + (HFI_DOMAIN_BASE_CDM + HFI_CMD_START_OFFSET + 0x0) +#define HFI_CMD_CDM_TEST_START (HFI_CMD_CDM_COMMON_START + 0x800) +#define HFI_CMD_CDM_END (HFI_CMD_CDM_COMMON_START + 0xFFF) + +/* Debug/Test Commands */ +#define HFI_CMD_DBG_COMMON_START \ + (HFI_DOMAIN_BASE_DBG + HFI_CMD_START_OFFSET + 0x0) +#define HFI_CMD_DBG_TEST_START (HFI_CMD_DBG_COMMON_START + 0x800) +#define HFI_CMD_DBG_END (HFI_CMD_DBG_COMMON_START + 0xFFF) + +/* System level messages */ +#define HFI_MSG_ICP_COMMON_START \ + (HFI_DOMAIN_BASE_ICP + HFI_MSG_START_OFFSET + 0x0) +#define HFI_MSG_SYS_INIT_DONE (HFI_MSG_ICP_COMMON_START + 0x1) +#define HFI_MSG_SYS_PC_PREP_DONE (HFI_MSG_ICP_COMMON_START + 0x2) +#define HFI_MSG_SYS_DEBUG (HFI_MSG_ICP_COMMON_START + 0x3) +#define HFI_MSG_SYS_IDLE (HFI_MSG_ICP_COMMON_START + 0x4) +#define HFI_MSG_SYS_PROPERTY_INFO (HFI_MSG_ICP_COMMON_START + 0x5) +#define HFI_MSG_SYS_PING_ACK (HFI_MSG_ICP_COMMON_START + 0x6) +#define HFI_MSG_SYS_RESET_ACK (HFI_MSG_ICP_COMMON_START + 0x7) +#define HFI_MSG_EVENT_NOTIFY (HFI_MSG_ICP_COMMON_START + 0x8) + +/* Core level Messages */ +/* IPE/BPS core Messages */ +#define HFI_MSG_IPE_BPS_COMMON_START \ + (HFI_DOMAIN_BASE_IPE_BPS + HFI_MSG_START_OFFSET + 0x0) +#define HFI_MSG_IPEBPS_CREATE_HANDLE_ACK \ + (HFI_MSG_IPE_BPS_COMMON_START + 0x08) +#define HFI_MSG_IPEBPS_ASYNC_COMMAND_DIRECT_ACK \ + (HFI_MSG_IPE_BPS_COMMON_START + 0x0a) +#define HFI_MSG_IPEBPS_ASYNC_COMMAND_INDIRECT_ACK \ + (HFI_MSG_IPE_BPS_COMMON_START + 0x0e) +#define HFI_MSG_IPE_BPS_TEST_START \ + (HFI_MSG_IPE_BPS_COMMON_START + 0x800) +#define HFI_MSG_IPE_BPS_END \ + (HFI_MSG_IPE_BPS_COMMON_START + 0xFFF) + +/* CDM core Messages */ +#define HFI_MSG_CDM_COMMON_START \ + (HFI_DOMAIN_BASE_CDM + HFI_MSG_START_OFFSET + 0x0) +#define HFI_MSG_PRI_CDM_PAYLOAD_ACK (HFI_MSG_CDM_COMMON_START + 0xa) +#define HFI_MSG_PRI_LLD_PAYLOAD_ACK (HFI_MSG_CDM_COMMON_START + 0xb) +#define HFI_MSG_CDM_TEST_START (HFI_MSG_CDM_COMMON_START + 0x800) +#define HFI_MSG_CDM_END (HFI_MSG_CDM_COMMON_START + 0xFFF) + +/* core level test command ranges */ +/* ICP core level test command range */ +#define HFI_CMD_ICP_TEST_START (HFI_CMD_ICP_COMMON_START + 0x800) +#define HFI_CMD_ICP_END (HFI_CMD_ICP_COMMON_START + 0xFFF) + +/* IPE/BPS core level test command range */ +#define HFI_CMD_IPE_BPS_TEST_START \ + (HFI_CMD_IPE_BPS_COMMON_START + 0x800) +#define HFI_CMD_IPE_BPS_END (HFI_CMD_IPE_BPS_COMMON_START + 0xFFF) + +/* ICP core level test message range */ +#define HFI_MSG_ICP_TEST_START (HFI_MSG_ICP_COMMON_START + 0x800) +#define HFI_MSG_ICP_END (HFI_MSG_ICP_COMMON_START + 0xFFF) + +/* ICP core level Debug test message range */ +#define HFI_MSG_DBG_COMMON_START \ + (HFI_DOMAIN_BASE_DBG + 0x0) +#define HFI_MSG_DBG_TEST_START (HFI_MSG_DBG_COMMON_START + 0x800) +#define HFI_MSG_DBG_END (HFI_MSG_DBG_COMMON_START + 0xFFF) + +/* System level property base offset */ +#define HFI_PROPERTY_ICP_COMMON_START (HFI_DOMAIN_BASE_ICP + 0x0) + +#define HFI_PROP_SYS_DEBUG_CFG (HFI_PROPERTY_ICP_COMMON_START + 0x1) +#define HFI_PROP_SYS_UBWC_CFG (HFI_PROPERTY_ICP_COMMON_START + 0x2) +#define HFI_PROP_SYS_IMAGE_VER (HFI_PROPERTY_ICP_COMMON_START + 0x3) +#define HFI_PROP_SYS_SUPPORTED (HFI_PROPERTY_ICP_COMMON_START + 0x4) +#define HFI_PROP_SYS_IPEBPS_PC (HFI_PROPERTY_ICP_COMMON_START + 0x5) +#define HFI_PROP_SYS_FW_DUMP_CFG (HFI_PROPERTY_ICP_COMMON_START + 0x8) +#define HFI_PROPERTY_SYS_UBWC_CONFIG_EX (HFI_PROPERTY_ICP_COMMON_START + 0x9) + +/* Capabilities reported at sys init */ +#define HFI_CAPS_PLACEHOLDER_1 (HFI_COMMON_BASE + 0x1) +#define HFI_CAPS_PLACEHOLDER_2 (HFI_COMMON_BASE + 0x2) + +/* Section describes different debug levels (HFI_DEBUG_MSG_X) + * available for debug messages from FW + */ +#define HFI_DEBUG_MSG_LOW 0x00000001 +#define HFI_DEBUG_MSG_MEDIUM 0x00000002 +#define HFI_DEBUG_MSG_HIGH 0x00000004 +#define HFI_DEBUG_MSG_ERROR 0x00000008 +#define HFI_DEBUG_MSG_FATAL 0x00000010 +/* Messages containing performance data */ +#define HFI_DEBUG_MSG_PERF 0x00000020 +/* Disable ARM9 WFI in low power mode. */ +#define HFI_DEBUG_CFG_WFI 0x01000000 +/* Disable ARM9 watchdog. */ +#define HFI_DEBUG_CFG_ARM9WD 0x10000000 + + +/* + * HFI_FW_DUMP levels + * HFI_FW_DUMP_xx + */ +#define HFI_FW_DUMP_DISABLED 0x00000000 +#define HFI_FW_DUMP_ON_FAILURE 0x00000001 +#define HFI_FW_DUMP_ALWAYS 0x00000002 + +/* Number of available dump levels. */ +#define NUM_HFI_DUMP_LVL 0x00000003 + +/* Debug Msg Communication types: + * Section describes different modes (HFI_DEBUG_MODE_X) + * available to communicate the debug messages + */ + /* Debug message output through the interface debug queue. */ +#define HFI_DEBUG_MODE_QUEUE 0x00000001 + /* Debug message output through QDSS. */ +#define HFI_DEBUG_MODE_QDSS 0x00000002 + /* Number of debug modes available. */ +#define NUM_HFI_DEBUG_MODE 0x00000002 + +#define HFI_DEBUG_MSG_LOW 0x00000001 +#define HFI_DEBUG_MSG_MEDIUM 0x00000002 +#define HFI_DEBUG_MSG_HIGH 0x00000004 +#define HFI_DEBUG_MSG_ERROR 0x00000008 +#define HFI_DEBUG_MSG_FATAL 0x00000010 +#define HFI_DEBUG_MSG_PERF 0x00000020 +#define HFI_DEBUG_CFG_WFI 0x01000000 +#define HFI_DEBUG_CFG_ARM9WD 0x10000000 + +#define HFI_DEV_VERSION_MAX 0x5 + +/** + * start of sys command packet types + * These commands are used to get system level information + * from firmware + */ + +/** + * struct hfi_caps_support + * payload to report caps through HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED + * @type: capability type + * @min: minimum supported value for the capability + * @max: maximum supported value for the capability + * @step_size: supported steps between min-max + */ +struct hfi_caps_support { + uint32_t type; + uint32_t min; + uint32_t max; + uint32_t step_size; +} __packed; + +/** + * struct hfi_caps_support_info + * capability report through HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED + * @num_caps: number of capabilities listed + * @caps_data: capabilities info array + */ +struct hfi_caps_support_info { + uint32_t num_caps; + struct hfi_caps_support caps_data[1]; +} __packed; + +/** + * struct hfi_debug + * payload structure to configure HFI_PROPERTY_SYS_DEBUG_CONFIG + * @debug_config: it is a result of HFI_DEBUG_MSG_X values that + * are OR-ed together to specify the debug message types + * to otput + * @debug_mode: debug message output through debug queue/qdss + * @HFI_PROPERTY_SYS_DEBUG_CONFIG + */ +struct hfi_debug { + uint32_t debug_config; + uint32_t debug_mode; +} __packed; + +/** + * struct hfi_ipe_bps_pc + * payload structure to configure HFI_PROPERTY_SYS_IPEBPS_PC + * @enable: Flag to enable IPE, BPS interfrane power collapse + * @core_info: Core information to firmware + */ +struct hfi_ipe_bps_pc { + uint32_t enable; + uint32_t core_info; +} __packed; + +/** + * struct hfi_cmd_ubwc_cfg + * Payload structure to configure HFI_PROP_SYS_UBWC_CFG + * @ubwc_fetch_cfg: UBWC configuration for fecth + * @ubwc_write_cfg: UBWC configuration for write + */ +struct hfi_cmd_ubwc_cfg { + uint32_t ubwc_fetch_cfg; + uint32_t ubwc_write_cfg; +} __packed; + +/** + * struct hfi_cmd_ubwc_cfg_ext + * Payload structure to configure HFI_UBWC_CFG_TYPE_EXT + * @bps: UBWC configuration for bps + * @ipe: UBWC configuration for ipe + */ +struct hfi_cmd_ubwc_cfg_ext { + struct hfi_cmd_ubwc_cfg bps; + struct hfi_cmd_ubwc_cfg ipe; +} __packed; + +/** + * struct hfi_cmd_sys_init + * command to initialization of system session + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @HFI_CMD_SYS_INIT + */ +struct hfi_cmd_sys_init { + uint32_t size; + uint32_t pkt_type; +} __packed; + +/** + * struct hfi_cmd_pc_prep + * command to firmware to prepare for power collapse + * @eize: packet size in bytes + * @pkt_type: opcode of a packet + * @HFI_CMD_SYS_PC_PREP + */ +struct hfi_cmd_pc_prep { + uint32_t size; + uint32_t pkt_type; +} __packed; + +/** + * struct hfi_cmd_prop + * command to get/set properties of firmware + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @num_prop: number of properties queried/set + * @prop_data: array of property IDs being queried. size depends on num_prop + * array of property IDs and associated structure pairs in set + * @HFI_CMD_SYS_GET_PROPERTY + * @HFI_CMD_SYS_SET_PROPERTY + */ +struct hfi_cmd_prop { + uint32_t size; + uint32_t pkt_type; + uint32_t num_prop; + uint32_t prop_data[1]; +} __packed; + +/** + * struct hfi_cmd_ping_pkt + * ping command pings the firmware to confirm whether + * it is alive. + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @user_data: client data, firmware returns this data + * as part of HFI_MSG_SYS_PING_ACK + * @HFI_CMD_SYS_PING + */ +struct hfi_cmd_ping_pkt { + uint32_t size; + uint32_t pkt_type; + uint64_t user_data; +} __packed; + +/** + * struct hfi_cmd_sys_reset_pkt + * sends the reset command to FW. FW responds in the same type + * of packet. so can be used for reset_ack_pkt type also + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @user_data: client data, firmware returns this data + * as part of HFI_MSG_SYS_RESET_ACK + * @HFI_CMD_SYS_RESET + */ + +struct hfi_cmd_sys_reset_pkt { + uint32_t size; + uint32_t pkt_type; + uint64_t user_data; +} __packed; + +/* end of sys command packet types */ + +/* start of sys message packet types */ + +/** + * struct hfi_prop + * structure to report maximum supported features of firmware. + */ +struct hfi_sys_support { + uint32_t place_holder; +} __packed; + +/** + * struct hfi_supported_prop + * structure to report HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED + * for a session + * @num_prop: number of properties supported + * @prop_data: array of supported property IDs + */ +struct hfi_supported_prop { + uint32_t num_prop; + uint32_t prop_data[1]; +} __packed; + +/** + * struct hfi_image_version + * system image version + * @major: major version number + * @minor: minor version number + * @ver_name_size: size of version name + * @ver_name: image version name + */ +struct hfi_image_version { + uint32_t major; + uint32_t minor; + uint32_t ver_name_size; + uint8_t ver_name[1]; +} __packed; + +/** + * struct hfi_msg_init_done_data + * @api_ver: Firmware API version + * @dev_ver: Device version + * @num_icp_hw: Number of ICP hardware information + * @dev_hw_ver: Supported hardware version information + * @reserved: Reserved field + */ +struct hfi_msg_init_done_data { + uint32_t api_ver; + uint32_t dev_ver; + uint32_t num_icp_hw; + uint32_t dev_hw_ver[HFI_DEV_VERSION_MAX]; + uint32_t reserved; +}; + +/** + * struct hfi_msg_init_done + * system init done message from firmware. Many system level properties + * are returned with the packet + * @size: Packet size in bytes + * @pkt_type: Opcode of a packet + * @err_type: Error code associated with response + * @num_prop: Number of default capability info + * @prop_data: Array of property ids and corresponding structure pairs + */ +struct hfi_msg_init_done { + uint32_t size; + uint32_t pkt_type; + uint32_t err_type; + uint32_t num_prop; + uint32_t prop_data[1]; +} __packed; + +/** + * struct hfi_msg_pc_prep_done + * system power collapse preparation done message + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @err_type: error code associated with the response + */ +struct hfi_msg_pc_prep_done { + uint32_t size; + uint32_t pkt_type; + uint32_t err_type; +} __packed; + +/** + * struct hfi_msg_prop + * system property info from firmware + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @num_prop: number of property info structures + * @prop_data: array of property IDs and associated structure pairs + */ +struct hfi_msg_prop { + uint32_t size; + uint32_t pkt_type; + uint32_t num_prop; + uint32_t prop_data[1]; +} __packed; + +/** + * struct hfi_msg_idle + * system idle message from firmware + * @size: packet size in bytes + * @pkt_type: opcode of a packet + */ +struct hfi_msg_idle { + uint32_t size; + uint32_t pkt_type; +} __packed; + +/** + * struct hfi_msg_ping_ack + * system ping ack message + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @user_data: this data is sent as part of ping command from host + */ +struct hfi_msg_ping_ack { + uint32_t size; + uint32_t pkt_type; + uint64_t user_data; +} __packed; + +/** + * struct hfi_msg_debug + * system debug message defination + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @msg_type: debug message type + * @msg_size: size of debug message in bytes + * @timestamp_hi: most significant 32 bits of the 64 bit timestamp field. + * timestamp shall be interpreted as a signed 64-bit value + * representing microseconds. + * @timestamp_lo: least significant 32 bits of the 64 bit timestamp field. + * timestamp shall be interpreted as a signed 64-bit value + * representing microseconds. + * @msg_data: message data in string form + */ +struct hfi_msg_debug { + uint32_t size; + uint32_t pkt_type; + uint32_t msg_type; + uint32_t msg_size; + uint32_t timestamp_hi; + uint32_t timestamp_lo; + uint8_t msg_data[1]; +} __packed; +/** + * struct hfi_msg_event_notify + * event notify message + * @size: packet size in bytes + * @pkt_type: opcode of a packet + * @fw_handle: firmware session handle + * @event_id: session event id + * @event_data1: event data corresponding to event ID + * @event_data2: event data corresponding to event ID + * @ext_event_data: info array, interpreted based on event_data1 + * and event_data2 + */ +struct hfi_msg_event_notify { + uint32_t size; + uint32_t pkt_type; + uint32_t fw_handle; + uint32_t event_id; + uint32_t event_data1; + uint32_t event_data2; + uint32_t ext_event_data[1]; +} __packed; +/** + * end of sys message packet types + */ + +#endif /* _HFI_DEFS_H_ */ diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c new file mode 100644 index 000000000000..06ad9de00eac --- /dev/null +++ b/drivers/cam_icp/hfi.c @@ -0,0 +1,942 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "hfi_reg.h" +#include "hfi_sys_defs.h" +#include "hfi_session_defs.h" +#include "hfi_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_debug_util.h" +#include "cam_soc_util.h" + +#define HFI_VERSION_INFO_MAJOR_VAL 1 +#define HFI_VERSION_INFO_MINOR_VAL 1 +#define HFI_VERSION_INFO_STEP_VAL 0 +#define HFI_VERSION_INFO_STEP_VAL 0 +#define HFI_VERSION_INFO_MAJOR_BMSK 0xFF000000 +#define HFI_VERSION_INFO_MAJOR_SHFT 24 +#define HFI_VERSION_INFO_MINOR_BMSK 0xFFFF00 +#define HFI_VERSION_INFO_MINOR_SHFT 8 +#define HFI_VERSION_INFO_STEP_BMSK 0xFF +#define HFI_VERSION_INFO_STEP_SHFT 0 + +#define HFI_MAX_POLL_TRY 5 + +#define HFI_MAX_PC_POLL_TRY 150 +#define HFI_POLL_TRY_SLEEP 1 + +static struct hfi_info *g_hfi; +unsigned int g_icp_mmu_hdl; +static DEFINE_MUTEX(hfi_cmd_q_mutex); +static DEFINE_MUTEX(hfi_msg_q_mutex); + +void cam_hfi_queue_dump(void) +{ + struct hfi_qtbl *qtbl; + struct hfi_qtbl_hdr *qtbl_hdr; + struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr; + struct hfi_mem_info *hfi_mem = NULL; + uint32_t *read_q, *read_ptr; + int i; + + hfi_mem = &g_hfi->map; + if (!hfi_mem) { + CAM_ERR(CAM_HFI, "Unable to dump queues hfi memory is NULL"); + return; + } + + qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; + qtbl_hdr = &qtbl->q_tbl_hdr; + CAM_DBG(CAM_HFI, + "qtbl: version = %x size = %u num q = %u qhdr_size = %u", + qtbl_hdr->qtbl_version, qtbl_hdr->qtbl_size, + qtbl_hdr->qtbl_num_q, qtbl_hdr->qtbl_qhdr_size); + + cmd_q_hdr = &qtbl->q_hdr[Q_CMD]; + CAM_DBG(CAM_HFI, "cmd: size = %u r_idx = %u w_idx = %u addr = %x", + cmd_q_hdr->qhdr_q_size, cmd_q_hdr->qhdr_read_idx, + cmd_q_hdr->qhdr_write_idx, hfi_mem->cmd_q.iova); + read_q = (uint32_t *)g_hfi->map.cmd_q.kva; + read_ptr = (uint32_t *)(read_q + 0); + CAM_DBG(CAM_HFI, "CMD Q START"); + for (i = 0; i < ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++) + CAM_DBG(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]); + + msg_q_hdr = &qtbl->q_hdr[Q_MSG]; + CAM_DBG(CAM_HFI, "msg: size = %u r_idx = %u w_idx = %u addr = %x", + msg_q_hdr->qhdr_q_size, msg_q_hdr->qhdr_read_idx, + msg_q_hdr->qhdr_write_idx, hfi_mem->msg_q.iova); + read_q = (uint32_t *)g_hfi->map.msg_q.kva; + read_ptr = (uint32_t *)(read_q + 0); + CAM_DBG(CAM_HFI, "MSG Q START"); + for (i = 0; i < ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++) + CAM_DBG(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]); +} + +int hfi_write_cmd(void *cmd_ptr) +{ + uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp; + uint32_t *write_q, *write_ptr; + struct hfi_qtbl *q_tbl; + struct hfi_q_hdr *q; + int rc = 0; + + if (!cmd_ptr) { + CAM_ERR(CAM_HFI, "command is null"); + return -EINVAL; + } + + mutex_lock(&hfi_cmd_q_mutex); + if (!g_hfi) { + CAM_ERR(CAM_HFI, "HFI interface not setup"); + rc = -ENODEV; + goto err; + } + + if (g_hfi->hfi_state != HFI_READY || + !g_hfi->cmd_q_state) { + CAM_ERR(CAM_HFI, "HFI state: %u, cmd q state: %u", + g_hfi->hfi_state, g_hfi->cmd_q_state); + rc = -ENODEV; + goto err; + } + + q_tbl = (struct hfi_qtbl *)g_hfi->map.qtbl.kva; + q = &q_tbl->q_hdr[Q_CMD]; + + write_q = (uint32_t *)g_hfi->map.cmd_q.kva; + + size_in_words = (*(uint32_t *)cmd_ptr) >> BYTE_WORD_SHIFT; + if (!size_in_words) { + CAM_DBG(CAM_HFI, "failed"); + rc = -EINVAL; + goto err; + } + + read_idx = q->qhdr_read_idx; + empty_space = (q->qhdr_write_idx >= read_idx) ? + (q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) : + (read_idx - q->qhdr_write_idx); + if (empty_space <= size_in_words) { + CAM_ERR(CAM_HFI, "failed: empty space %u, size_in_words %u", + empty_space, size_in_words); + rc = -EIO; + goto err; + } + + new_write_idx = q->qhdr_write_idx + size_in_words; + write_ptr = (uint32_t *)(write_q + q->qhdr_write_idx); + + if (new_write_idx < q->qhdr_q_size) { + memcpy(write_ptr, (uint8_t *)cmd_ptr, + size_in_words << BYTE_WORD_SHIFT); + } else { + new_write_idx -= q->qhdr_q_size; + temp = (size_in_words - new_write_idx) << BYTE_WORD_SHIFT; + memcpy(write_ptr, (uint8_t *)cmd_ptr, temp); + memcpy(write_q, (uint8_t *)cmd_ptr + temp, + new_write_idx << BYTE_WORD_SHIFT); + } + + /* + * To make sure command data in a command queue before + * updating write index + */ + wmb(); + + q->qhdr_write_idx = new_write_idx; + + /* + * Before raising interrupt make sure command data is ready for + * firmware to process + */ + wmb(); + cam_io_w_mb((uint32_t)INTR_ENABLE, + g_hfi->csr_base + HFI_REG_A5_CSR_HOST2ICPINT); +err: + mutex_unlock(&hfi_cmd_q_mutex); + return rc; +} + +int hfi_read_message(uint32_t *pmsg, uint8_t q_id, + uint32_t *words_read) +{ + struct hfi_qtbl *q_tbl_ptr; + struct hfi_q_hdr *q; + uint32_t new_read_idx, size_in_words, word_diff, temp; + uint32_t *read_q, *read_ptr, *write_ptr; + uint32_t size_upper_bound = 0; + int rc = 0; + + if (!pmsg) { + CAM_ERR(CAM_HFI, "Invalid msg"); + return -EINVAL; + } + + if (q_id > Q_DBG) { + CAM_ERR(CAM_HFI, "Invalid q :%u", q_id); + return -EINVAL; + } + + mutex_lock(&hfi_msg_q_mutex); + if (!g_hfi) { + CAM_ERR(CAM_HFI, "hfi not set up yet"); + rc = -ENODEV; + goto err; + } + + if ((g_hfi->hfi_state != HFI_READY) || + !g_hfi->msg_q_state) { + CAM_ERR(CAM_HFI, "hfi state: %u, msg q state: %u", + g_hfi->hfi_state, g_hfi->msg_q_state); + rc = -ENODEV; + goto err; + } + + q_tbl_ptr = (struct hfi_qtbl *)g_hfi->map.qtbl.kva; + q = &q_tbl_ptr->q_hdr[q_id]; + + if (q->qhdr_read_idx == q->qhdr_write_idx) { + CAM_DBG(CAM_HFI, "Q not ready, state:%u, r idx:%u, w idx:%u", + g_hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx); + rc = -EIO; + goto err; + } + + if (q_id == Q_MSG) { + read_q = (uint32_t *)g_hfi->map.msg_q.kva; + size_upper_bound = ICP_HFI_MAX_PKT_SIZE_MSGQ_IN_WORDS; + } else { + read_q = (uint32_t *)g_hfi->map.dbg_q.kva; + size_upper_bound = ICP_HFI_MAX_PKT_SIZE_IN_WORDS; + } + + read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx); + write_ptr = (uint32_t *)(read_q + q->qhdr_write_idx); + + if (write_ptr > read_ptr) + size_in_words = write_ptr - read_ptr; + else { + word_diff = read_ptr - write_ptr; + if (q_id == Q_MSG) + size_in_words = (ICP_MSG_Q_SIZE_IN_BYTES >> + BYTE_WORD_SHIFT) - word_diff; + else + size_in_words = (ICP_DBG_Q_SIZE_IN_BYTES >> + BYTE_WORD_SHIFT) - word_diff; + } + + if ((size_in_words == 0) || + (size_in_words > size_upper_bound)) { + CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x", + size_in_words << BYTE_WORD_SHIFT); + q->qhdr_read_idx = q->qhdr_write_idx; + rc = -EIO; + goto err; + } + + new_read_idx = q->qhdr_read_idx + size_in_words; + + if (new_read_idx < q->qhdr_q_size) { + memcpy(pmsg, read_ptr, size_in_words << BYTE_WORD_SHIFT); + } else { + new_read_idx -= q->qhdr_q_size; + temp = (size_in_words - new_read_idx) << BYTE_WORD_SHIFT; + memcpy(pmsg, read_ptr, temp); + memcpy((uint8_t *)pmsg + temp, read_q, + new_read_idx << BYTE_WORD_SHIFT); + } + + q->qhdr_read_idx = new_read_idx; + *words_read = size_in_words; + /* Memory Barrier to make sure message + * queue parameters are updated after read + */ + wmb(); +err: + mutex_unlock(&hfi_msg_q_mutex); + return rc; +} + +int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg) +{ + uint8_t *prop; + struct hfi_cmd_prop *dbg_prop; + uint32_t size = 0; + + size = sizeof(struct hfi_cmd_prop) + + sizeof(struct hfi_cmd_ubwc_cfg); + + CAM_DBG(CAM_HFI, + "size of ubwc %u, ubwc_cfg [rd-0x%x,wr-0x%x]", + size, ubwc_cfg[0], ubwc_cfg[1]); + + prop = kzalloc(size, GFP_KERNEL); + if (!prop) + return -ENOMEM; + + dbg_prop = (struct hfi_cmd_prop *)prop; + dbg_prop->size = size; + dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; + dbg_prop->num_prop = 1; + dbg_prop->prop_data[0] = HFI_PROP_SYS_UBWC_CFG; + dbg_prop->prop_data[1] = ubwc_cfg[0]; + dbg_prop->prop_data[2] = ubwc_cfg[1]; + + hfi_write_cmd(prop); + kfree(prop); + + return 0; +} + +int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg, + uint32_t *ubwc_bps_cfg) +{ + uint8_t *prop; + struct hfi_cmd_prop *dbg_prop; + uint32_t size = 0; + + size = sizeof(struct hfi_cmd_prop) + + sizeof(struct hfi_cmd_ubwc_cfg_ext); + + CAM_DBG(CAM_HFI, + "size of ubwc %u, ubwc_ipe_cfg[rd-0x%x,wr-0x%x] ubwc_bps_cfg[rd-0x%x,wr-0x%x]", + size, ubwc_ipe_cfg[0], ubwc_ipe_cfg[1], + ubwc_bps_cfg[0], ubwc_bps_cfg[1]); + + prop = kzalloc(size, GFP_KERNEL); + if (!prop) + return -ENOMEM; + + dbg_prop = (struct hfi_cmd_prop *)prop; + dbg_prop->size = size; + dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; + dbg_prop->num_prop = 1; + dbg_prop->prop_data[0] = HFI_PROPERTY_SYS_UBWC_CONFIG_EX; + dbg_prop->prop_data[1] = ubwc_bps_cfg[0]; + dbg_prop->prop_data[2] = ubwc_bps_cfg[1]; + dbg_prop->prop_data[3] = ubwc_ipe_cfg[0]; + dbg_prop->prop_data[4] = ubwc_ipe_cfg[1]; + + hfi_write_cmd(prop); + kfree(prop); + + return 0; +} + + +int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info) +{ + uint8_t *prop; + struct hfi_cmd_prop *dbg_prop; + uint32_t size = 0; + + size = sizeof(struct hfi_cmd_prop) + + sizeof(struct hfi_ipe_bps_pc); + + prop = kzalloc(size, GFP_KERNEL); + if (!prop) + return -ENOMEM; + + dbg_prop = (struct hfi_cmd_prop *)prop; + dbg_prop->size = size; + dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; + dbg_prop->num_prop = 1; + dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC; + dbg_prop->prop_data[1] = enable; + dbg_prop->prop_data[2] = core_info; + + hfi_write_cmd(prop); + kfree(prop); + + return 0; +} + +int hfi_set_debug_level(u64 a5_dbg_type, uint32_t lvl) +{ + uint8_t *prop; + struct hfi_cmd_prop *dbg_prop; + uint32_t size = 0, val; + + val = HFI_DEBUG_MSG_LOW | + HFI_DEBUG_MSG_MEDIUM | + HFI_DEBUG_MSG_HIGH | + HFI_DEBUG_MSG_ERROR | + HFI_DEBUG_MSG_FATAL | + HFI_DEBUG_MSG_PERF | + HFI_DEBUG_CFG_WFI | + HFI_DEBUG_CFG_ARM9WD; + + if (lvl > val) + return -EINVAL; + + size = sizeof(struct hfi_cmd_prop) + + sizeof(struct hfi_debug); + + prop = kzalloc(size, GFP_KERNEL); + if (!prop) + return -ENOMEM; + + dbg_prop = (struct hfi_cmd_prop *)prop; + dbg_prop->size = size; + dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; + dbg_prop->num_prop = 1; + dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG; + dbg_prop->prop_data[1] = lvl; + dbg_prop->prop_data[2] = a5_dbg_type; + hfi_write_cmd(prop); + + kfree(prop); + + return 0; +} + +int hfi_set_fw_dump_level(uint32_t lvl) +{ + uint8_t *prop = NULL; + struct hfi_cmd_prop *fw_dump_level_switch_prop = NULL; + uint32_t size = 0; + + CAM_DBG(CAM_HFI, "fw dump ENTER"); + + size = sizeof(struct hfi_cmd_prop) + sizeof(lvl); + prop = kzalloc(size, GFP_KERNEL); + if (!prop) + return -ENOMEM; + + fw_dump_level_switch_prop = (struct hfi_cmd_prop *)prop; + fw_dump_level_switch_prop->size = size; + fw_dump_level_switch_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; + fw_dump_level_switch_prop->num_prop = 1; + fw_dump_level_switch_prop->prop_data[0] = HFI_PROP_SYS_FW_DUMP_CFG; + fw_dump_level_switch_prop->prop_data[1] = lvl; + + CAM_DBG(CAM_HFI, "prop->size = %d\n" + "prop->pkt_type = %d\n" + "prop->num_prop = %d\n" + "prop->prop_data[0] = %d\n" + "prop->prop_data[1] = %d\n", + fw_dump_level_switch_prop->size, + fw_dump_level_switch_prop->pkt_type, + fw_dump_level_switch_prop->num_prop, + fw_dump_level_switch_prop->prop_data[0], + fw_dump_level_switch_prop->prop_data[1]); + + hfi_write_cmd(prop); + kfree(prop); + return 0; +} + +void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) +{ + switch (type) { + case HFI_CMD_SYS_INIT: { + struct hfi_cmd_sys_init init; + + memset(&init, 0, sizeof(init)); + + init.size = sizeof(struct hfi_cmd_sys_init); + init.pkt_type = type; + hfi_write_cmd(&init); + } + break; + case HFI_CMD_SYS_PC_PREP: { + struct hfi_cmd_pc_prep prep; + + prep.size = sizeof(struct hfi_cmd_pc_prep); + prep.pkt_type = type; + hfi_write_cmd(&prep); + } + break; + case HFI_CMD_SYS_SET_PROPERTY: { + struct hfi_cmd_prop prop; + + if ((uint32_t)data == (uint32_t)HFI_PROP_SYS_DEBUG_CFG) { + prop.size = sizeof(struct hfi_cmd_prop); + prop.pkt_type = type; + prop.num_prop = 1; + prop.prop_data[0] = HFI_PROP_SYS_DEBUG_CFG; + hfi_write_cmd(&prop); + } + } + break; + case HFI_CMD_SYS_GET_PROPERTY: + break; + case HFI_CMD_SYS_PING: { + struct hfi_cmd_ping_pkt ping; + + ping.size = sizeof(struct hfi_cmd_ping_pkt); + ping.pkt_type = type; + ping.user_data = (uint64_t)data; + hfi_write_cmd(&ping); + } + break; + case HFI_CMD_SYS_RESET: { + struct hfi_cmd_sys_reset_pkt reset; + + reset.size = sizeof(struct hfi_cmd_sys_reset_pkt); + reset.pkt_type = type; + reset.user_data = (uint64_t)data; + hfi_write_cmd(&reset); + } + break; + case HFI_CMD_IPEBPS_CREATE_HANDLE: { + struct hfi_cmd_create_handle handle; + + handle.size = sizeof(struct hfi_cmd_create_handle); + handle.pkt_type = type; + handle.handle_type = (uint32_t)data; + handle.user_data1 = 0; + hfi_write_cmd(&handle); + } + break; + case HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT: + break; + default: + CAM_ERR(CAM_HFI, "command not supported :%d", type); + break; + } +} + + +int hfi_get_hw_caps(void *query_buf) +{ + int i = 0; + struct cam_icp_query_cap_cmd *query_cmd = NULL; + + if (!query_buf) { + CAM_ERR(CAM_HFI, "query buf is NULL"); + return -EINVAL; + } + + query_cmd = (struct cam_icp_query_cap_cmd *)query_buf; + query_cmd->fw_version.major = 0x12; + query_cmd->fw_version.minor = 0x12; + query_cmd->fw_version.revision = 0x12; + + query_cmd->api_version.major = 0x13; + query_cmd->api_version.minor = 0x13; + query_cmd->api_version.revision = 0x13; + + query_cmd->num_ipe = 2; + query_cmd->num_bps = 1; + + for (i = 0; i < CAM_ICP_DEV_TYPE_MAX; i++) { + query_cmd->dev_ver[i].dev_type = i; + query_cmd->dev_ver[i].hw_ver.major = 0x34 + i; + query_cmd->dev_ver[i].hw_ver.minor = 0x34 + i; + query_cmd->dev_ver[i].hw_ver.incr = 0x34 + i; + } + return 0; +} + +void cam_hfi_disable_cpu(void __iomem *icp_base) +{ + uint32_t data; + uint32_t val; + uint32_t try = 0; + + 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) + break; + /* Need to poll here to confirm that FW is going trigger wfi + * and Host can the proceed. No interrupt is expected from FW + * at this time. + */ + usleep_range(HFI_POLL_TRY_SLEEP * 1000, + (HFI_POLL_TRY_SLEEP * 1000) + 1000); + try++; + } + + val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL); + val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN); + cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL); + + val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET); + cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET); + + cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET, + icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); + cam_io_w_mb((uint32_t)INTR_DISABLE, + icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); +} + +void cam_hfi_enable_cpu(void __iomem *icp_base) +{ + cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN, + icp_base + HFI_REG_A5_CSR_A5_CONTROL); + cam_io_w_mb((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET); +} + +int cam_hfi_resume(struct hfi_mem_info *hfi_mem, + void __iomem *icp_base, bool debug) +{ + int rc = 0; + uint32_t data; + uint32_t fw_version, status = 0; + uint32_t retry_cnt = 0; + + cam_hfi_enable_cpu(icp_base); + g_hfi->csr_base = icp_base; + + if (debug) { + cam_io_w_mb(ICP_FLAG_A5_CTRL_DBG_EN, + (icp_base + HFI_REG_A5_CSR_A5_CONTROL)); + + /* Barrier needed as next write should be done after + * sucessful previous write. Next write enable clock + * gating + */ + wmb(); + + cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN, + icp_base + HFI_REG_A5_CSR_A5_CONTROL); + + } else { + cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN, + icp_base + HFI_REG_A5_CSR_A5_CONTROL); + } + + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), + status, (status == ICP_INIT_RESP_SUCCESS), 100, 10000); + + CAM_DBG(CAM_HFI, "1: status = %u", status); + status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); + CAM_DBG(CAM_HFI, "2: status = %u", status); + if (status == ICP_INIT_RESP_SUCCESS) + break; + + if (status == ICP_INIT_RESP_FAILED) { + CAM_ERR(CAM_HFI, "ICP Init Failed. status = %u", + status); + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); + return -EINVAL; + } + retry_cnt++; + } + + if ((retry_cnt == HFI_MAX_POLL_TRY) && + (status == ICP_INIT_RESP_RESET)) { + CAM_ERR(CAM_HFI, "Reached Max retries. status = %u", + status); + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); + return -EINVAL; + } + + cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), + icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); + + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version); + + data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS); + CAM_DBG(CAM_HFI, "wfi status = %x", (int)data); + + cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR); + cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova, + icp_base + HFI_REG_SFR_PTR); + cam_io_w_mb((uint32_t)hfi_mem->shmem.iova, + icp_base + HFI_REG_SHARED_MEM_PTR); + cam_io_w_mb((uint32_t)hfi_mem->shmem.len, + icp_base + HFI_REG_SHARED_MEM_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->sec_heap.iova, + icp_base + HFI_REG_UNCACHED_HEAP_PTR); + cam_io_w_mb((uint32_t)hfi_mem->sec_heap.len, + icp_base + HFI_REG_UNCACHED_HEAP_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->qdss.iova, + icp_base + HFI_REG_QDSS_IOVA); + cam_io_w_mb((uint32_t)hfi_mem->qdss.len, + icp_base + HFI_REG_QDSS_IOVA_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova, + icp_base + HFI_REG_IO_REGION_IOVA); + cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, + icp_base + HFI_REG_IO_REGION_SIZE); + + return rc; +} + +int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, + void __iomem *icp_base, bool debug) +{ + int rc = 0; + struct hfi_qtbl *qtbl; + struct hfi_qtbl_hdr *qtbl_hdr; + struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; + uint32_t hw_version, soc_version, fw_version, status = 0; + uint32_t retry_cnt = 0; + struct sfr_buf *sfr_buffer; + + mutex_lock(&hfi_cmd_q_mutex); + mutex_lock(&hfi_msg_q_mutex); + + if (!g_hfi) { + g_hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL); + if (!g_hfi) { + rc = -ENOMEM; + goto alloc_fail; + } + } + + if (g_hfi->hfi_state != HFI_DEINIT) { + CAM_ERR(CAM_HFI, "hfi_init: invalid state"); + return -EINVAL; + } + + memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map)); + g_hfi->hfi_state = HFI_DEINIT; + soc_version = socinfo_get_version(); + if (debug) { + cam_io_w_mb( + (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN | + ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE), + icp_base + HFI_REG_A5_CSR_A5_CONTROL); + msleep(100); + cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN | + ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI), + icp_base + HFI_REG_A5_CSR_A5_CONTROL); + } else { + /* Due to hardware bug in V1 ICP clock gating has to be + * disabled, this is supposed to be fixed in V-2. But enabling + * the clock gating is causing the firmware hang, hence + * disabling the clock gating on both V1 and V2 until the + * hardware team root causes this + */ + cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN | + ICP_FLAG_CSR_WAKE_UP_EN | + ICP_CSR_EN_CLKGATE_WFI, + icp_base + HFI_REG_A5_CSR_A5_CONTROL); + } + + qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; + qtbl_hdr = &qtbl->q_tbl_hdr; + qtbl_hdr->qtbl_version = 0xFFFFFFFF; + qtbl_hdr->qtbl_size = sizeof(struct hfi_qtbl); + qtbl_hdr->qtbl_qhdr0_offset = sizeof(struct hfi_qtbl_hdr); + qtbl_hdr->qtbl_qhdr_size = sizeof(struct hfi_q_hdr); + qtbl_hdr->qtbl_num_q = ICP_HFI_NUMBER_OF_QS; + qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS; + + /* setup host-to-firmware command queue */ + cmd_q_hdr = &qtbl->q_hdr[Q_CMD]; + cmd_q_hdr->qhdr_status = QHDR_ACTIVE; + cmd_q_hdr->qhdr_start_addr = hfi_mem->cmd_q.iova; + cmd_q_hdr->qhdr_q_size = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; + cmd_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT; + cmd_q_hdr->qhdr_pkt_drop_cnt = RESET; + cmd_q_hdr->qhdr_read_idx = RESET; + cmd_q_hdr->qhdr_write_idx = RESET; + + /* setup firmware-to-Host message queue */ + msg_q_hdr = &qtbl->q_hdr[Q_MSG]; + msg_q_hdr->qhdr_status = QHDR_ACTIVE; + msg_q_hdr->qhdr_start_addr = hfi_mem->msg_q.iova; + msg_q_hdr->qhdr_q_size = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; + msg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT; + msg_q_hdr->qhdr_pkt_drop_cnt = RESET; + msg_q_hdr->qhdr_read_idx = RESET; + msg_q_hdr->qhdr_write_idx = RESET; + + /* setup firmware-to-Host message queue */ + dbg_q_hdr = &qtbl->q_hdr[Q_DBG]; + dbg_q_hdr->qhdr_status = QHDR_ACTIVE; + dbg_q_hdr->qhdr_start_addr = hfi_mem->dbg_q.iova; + dbg_q_hdr->qhdr_q_size = ICP_DBG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; + dbg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT; + dbg_q_hdr->qhdr_pkt_drop_cnt = RESET; + dbg_q_hdr->qhdr_read_idx = RESET; + dbg_q_hdr->qhdr_write_idx = RESET; + + sfr_buffer = (struct sfr_buf *)hfi_mem->sfr_buf.kva; + sfr_buffer->size = ICP_MSG_SFR_SIZE_IN_BYTES; + + switch (event_driven_mode) { + case INTR_MODE: + cmd_q_hdr->qhdr_type = Q_CMD; + cmd_q_hdr->qhdr_rx_wm = SET; + cmd_q_hdr->qhdr_tx_wm = SET; + cmd_q_hdr->qhdr_rx_req = SET; + cmd_q_hdr->qhdr_tx_req = RESET; + cmd_q_hdr->qhdr_rx_irq_status = RESET; + cmd_q_hdr->qhdr_tx_irq_status = RESET; + + msg_q_hdr->qhdr_type = Q_MSG; + msg_q_hdr->qhdr_rx_wm = SET; + msg_q_hdr->qhdr_tx_wm = SET; + msg_q_hdr->qhdr_rx_req = SET; + msg_q_hdr->qhdr_tx_req = RESET; + msg_q_hdr->qhdr_rx_irq_status = RESET; + msg_q_hdr->qhdr_tx_irq_status = RESET; + + dbg_q_hdr->qhdr_type = Q_DBG; + dbg_q_hdr->qhdr_rx_wm = SET; + dbg_q_hdr->qhdr_tx_wm = SET_WM; + dbg_q_hdr->qhdr_rx_req = RESET; + dbg_q_hdr->qhdr_tx_req = RESET; + dbg_q_hdr->qhdr_rx_irq_status = RESET; + dbg_q_hdr->qhdr_tx_irq_status = RESET; + + break; + + case POLL_MODE: + cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_POLL_MODE_2 | + RX_EVENT_POLL_MODE_2; + msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_POLL_MODE_2 | + RX_EVENT_POLL_MODE_2; + dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_POLL_MODE_2 | + RX_EVENT_POLL_MODE_2; + break; + + case WM_MODE: + cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_DRIVEN_MODE_2 | + RX_EVENT_DRIVEN_MODE_2; + cmd_q_hdr->qhdr_rx_wm = SET; + cmd_q_hdr->qhdr_tx_wm = SET; + cmd_q_hdr->qhdr_rx_req = RESET; + cmd_q_hdr->qhdr_tx_req = SET; + cmd_q_hdr->qhdr_rx_irq_status = RESET; + cmd_q_hdr->qhdr_tx_irq_status = RESET; + + msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_DRIVEN_MODE_2 | + RX_EVENT_DRIVEN_MODE_2; + msg_q_hdr->qhdr_rx_wm = SET; + msg_q_hdr->qhdr_tx_wm = SET; + msg_q_hdr->qhdr_rx_req = SET; + msg_q_hdr->qhdr_tx_req = RESET; + msg_q_hdr->qhdr_rx_irq_status = RESET; + msg_q_hdr->qhdr_tx_irq_status = RESET; + + dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_DRIVEN_MODE_2 | + RX_EVENT_DRIVEN_MODE_2; + dbg_q_hdr->qhdr_rx_wm = SET; + dbg_q_hdr->qhdr_tx_wm = SET_WM; + dbg_q_hdr->qhdr_rx_req = RESET; + dbg_q_hdr->qhdr_tx_req = RESET; + dbg_q_hdr->qhdr_rx_irq_status = RESET; + dbg_q_hdr->qhdr_tx_irq_status = RESET; + break; + + default: + CAM_ERR(CAM_HFI, "Invalid event driven mode :%u", + event_driven_mode); + break; + } + + cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, + icp_base + HFI_REG_QTBL_PTR); + cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova, + icp_base + HFI_REG_SFR_PTR); + cam_io_w_mb((uint32_t)hfi_mem->shmem.iova, + icp_base + HFI_REG_SHARED_MEM_PTR); + cam_io_w_mb((uint32_t)hfi_mem->shmem.len, + icp_base + HFI_REG_SHARED_MEM_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->sec_heap.iova, + icp_base + HFI_REG_UNCACHED_HEAP_PTR); + cam_io_w_mb((uint32_t)hfi_mem->sec_heap.len, + icp_base + HFI_REG_UNCACHED_HEAP_SIZE); + cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_SET, + icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); + cam_io_w_mb((uint32_t)hfi_mem->qdss.iova, + icp_base + HFI_REG_QDSS_IOVA); + cam_io_w_mb((uint32_t)hfi_mem->qdss.len, + icp_base + HFI_REG_QDSS_IOVA_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova, + icp_base + HFI_REG_IO_REGION_IOVA); + cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, + icp_base + HFI_REG_IO_REGION_SIZE); + + hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); + + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), + status, (status == ICP_INIT_RESP_SUCCESS), 100, 10000); + + CAM_DBG(CAM_HFI, "1: status = %u rc = %d", status, rc); + status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); + CAM_DBG(CAM_HFI, "2: status = %u rc = %d", status, rc); + if (status == ICP_INIT_RESP_SUCCESS) + break; + + if (status == ICP_INIT_RESP_FAILED) { + CAM_ERR(CAM_HFI, "ICP Init Failed. status = %u", + status); + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); + goto regions_fail; + } + retry_cnt++; + } + + if ((retry_cnt == HFI_MAX_POLL_TRY) && + (status == ICP_INIT_RESP_RESET)) { + CAM_ERR(CAM_HFI, "Reached Max retries. status = %u", + status); + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_ERR(CAM_HFI, + "hw version : : [%x], fw version : [%x]", + hw_version, fw_version); + goto regions_fail; + } + + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]", + hw_version, fw_version); + + g_hfi->csr_base = icp_base; + g_hfi->hfi_state = HFI_READY; + g_hfi->cmd_q_state = true; + g_hfi->msg_q_state = true; + cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), + icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); + + mutex_unlock(&hfi_cmd_q_mutex); + mutex_unlock(&hfi_msg_q_mutex); + + return rc; +regions_fail: + kfree(g_hfi); + g_hfi = NULL; +alloc_fail: + mutex_unlock(&hfi_cmd_q_mutex); + mutex_unlock(&hfi_msg_q_mutex); + return rc; +} + +void cam_hfi_deinit(void __iomem *icp_base) +{ + mutex_lock(&hfi_cmd_q_mutex); + mutex_lock(&hfi_msg_q_mutex); + + if (!g_hfi) { + CAM_ERR(CAM_HFI, "hfi path not established yet"); + goto err; + } + + g_hfi->cmd_q_state = false; + g_hfi->msg_q_state = false; + + kzfree(g_hfi); + g_hfi = NULL; + +err: + mutex_unlock(&hfi_cmd_q_mutex); + mutex_unlock(&hfi_msg_q_mutex); +} diff --git a/drivers/cam_icp/icp_hw/Makefile b/drivers/cam_icp/icp_hw/Makefile new file mode 100644 index 000000000000..e07836a01f12 --- /dev/null +++ b/drivers/cam_icp/icp_hw/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += icp_hw_mgr/ a5_hw/ ipe_hw/ bps_hw/ diff --git a/drivers/cam_icp/icp_hw/a5_hw/Makefile b/drivers/cam_icp/icp_hw/a5_hw/Makefile new file mode 100644 index 000000000000..db80567488a0 --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/a5_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += a5_dev.o a5_core.o a5_soc.o diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c new file mode 100644 index 000000000000..baac5ff5976c --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -0,0 +1,518 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_a5_hw_intf.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "a5_core.h" +#include "a5_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "hfi_intf.h" +#include "hfi_sys_defs.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info, + struct cam_icp_cpas_vote *cpas_vote) +{ + int rc = 0; + + if (cpas_vote->ahb_vote_valid) + rc = cam_cpas_update_ahb_vote(core_info->cpas_handle, + &cpas_vote->ahb_vote); + + if (cpas_vote->axi_vote_valid) + rc = cam_cpas_update_axi_vote(core_info->cpas_handle, + &cpas_vote->axi_vote); + + if (rc) + CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc); + + return rc; +} + +static int32_t cam_icp_validate_fw(const uint8_t *elf) +{ + struct elf32_hdr *elf_hdr; + + if (!elf) { + CAM_ERR(CAM_ICP, "Invalid params"); + return -EINVAL; + } + + elf_hdr = (struct elf32_hdr *)elf; + + if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG)) { + CAM_ERR(CAM_ICP, "ICP elf identifier is failed"); + return -EINVAL; + } + + /* check architecture */ + if (elf_hdr->e_machine != EM_ARM) { + CAM_ERR(CAM_ICP, "unsupported arch"); + return -EINVAL; + } + + /* check elf bit format */ + if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) { + CAM_ERR(CAM_ICP, "elf doesn't support 32 bit format"); + return -EINVAL; + } + + return 0; +} + +static int32_t cam_icp_get_fw_size(const uint8_t *elf, uint32_t *fw_size) +{ + int32_t rc = 0; + int32_t i = 0; + uint32_t num_prg_hdrs; + unsigned char *icp_prg_hdr_tbl; + uint32_t seg_mem_size = 0; + struct elf32_hdr *elf_hdr; + struct elf32_phdr *prg_hdr; + + if (!elf || !fw_size) { + CAM_ERR(CAM_ICP, "invalid args"); + return -EINVAL; + } + + *fw_size = 0; + + elf_hdr = (struct elf32_hdr *)elf; + num_prg_hdrs = elf_hdr->e_phnum; + icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff; + prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0]; + + if (!prg_hdr) { + CAM_ERR(CAM_ICP, "failed to get elf program header attr"); + return -EINVAL; + } + + CAM_DBG(CAM_ICP, "num_prg_hdrs = %d", num_prg_hdrs); + for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) { + if (prg_hdr->p_flags == 0) + continue; + + seg_mem_size = (prg_hdr->p_memsz + prg_hdr->p_align - 1) & + ~(prg_hdr->p_align - 1); + seg_mem_size += prg_hdr->p_vaddr; + CAM_DBG(CAM_ICP, "memsz:%x align:%x addr:%x seg_mem_size:%x", + (int)prg_hdr->p_memsz, (int)prg_hdr->p_align, + (int)prg_hdr->p_vaddr, (int)seg_mem_size); + if (*fw_size < seg_mem_size) + *fw_size = seg_mem_size; + + } + + if (*fw_size == 0) { + CAM_ERR(CAM_ICP, "invalid elf fw file"); + return -EINVAL; + } + + return rc; +} + +static int32_t cam_icp_program_fw(const uint8_t *elf, + struct cam_a5_device_core_info *core_info) +{ + int32_t rc = 0; + uint32_t num_prg_hdrs; + unsigned char *icp_prg_hdr_tbl; + int32_t i = 0; + u8 *dest; + u8 *src; + struct elf32_hdr *elf_hdr; + struct elf32_phdr *prg_hdr; + + elf_hdr = (struct elf32_hdr *)elf; + num_prg_hdrs = elf_hdr->e_phnum; + icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff; + prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0]; + + if (!prg_hdr) { + CAM_ERR(CAM_ICP, "failed to get elf program header attr"); + return -EINVAL; + } + + for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) { + if (prg_hdr->p_flags == 0) + continue; + + CAM_DBG(CAM_ICP, "Loading FW header size: %u", + prg_hdr->p_filesz); + if (prg_hdr->p_filesz != 0) { + src = (u8 *)((u8 *)elf + prg_hdr->p_offset); + dest = (u8 *)(((u8 *)core_info->fw_kva_addr) + + prg_hdr->p_vaddr); + + memcpy_toio(dest, src, prg_hdr->p_filesz); + } + } + + return rc; +} + +static int32_t cam_a5_download_fw(void *device_priv) +{ + int32_t rc = 0; + uint32_t fw_size; + const uint8_t *fw_start = NULL; + struct cam_hw_info *a5_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_a5_device_core_info *core_info = NULL; + struct cam_a5_device_hw_info *hw_info = NULL; + struct platform_device *pdev = NULL; + struct a5_soc_info *cam_a5_soc_info = NULL; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &a5_dev->soc_info; + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + hw_info = core_info->a5_hw_info; + pdev = soc_info->pdev; + cam_a5_soc_info = soc_info->soc_private; + + rc = request_firmware(&core_info->fw_elf, "CAMERA_ICP.elf", &pdev->dev); + if (rc) { + CAM_ERR(CAM_ICP, "Failed to locate fw: %d", rc); + return rc; + } + + if (!core_info->fw_elf) { + CAM_ERR(CAM_ICP, "Invalid elf size"); + rc = -EINVAL; + goto fw_download_failed; + } + + fw_start = core_info->fw_elf->data; + rc = cam_icp_validate_fw(fw_start); + if (rc) { + CAM_ERR(CAM_ICP, "fw elf validation failed"); + goto fw_download_failed; + } + + rc = cam_icp_get_fw_size(fw_start, &fw_size); + if (rc) { + CAM_ERR(CAM_ICP, "unable to get fw size"); + goto fw_download_failed; + } + + if (core_info->fw_buf_len < fw_size) { + CAM_ERR(CAM_ICP, "mismatch in fw size: %u %llu", + fw_size, core_info->fw_buf_len); + rc = -EINVAL; + goto fw_download_failed; + } + + rc = cam_icp_program_fw(fw_start, core_info); + if (rc) { + CAM_ERR(CAM_ICP, "fw program is failed"); + goto fw_download_failed; + } + +fw_download_failed: + release_firmware(core_info->fw_elf); + return rc; +} + +int cam_a5_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *a5_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_a5_device_core_info *core_info = NULL; + struct cam_icp_cpas_vote cpas_vote; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &a5_dev->soc_info; + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_ICP, "soc_info: %pK core_info: %pK", + soc_info, core_info); + return -EINVAL; + } + + cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; + cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.axi_vote.num_paths = 1; + cpas_vote.axi_vote.axi_path[0].path_data_type = + CAM_ICP_DEFAULT_AXI_PATH; + cpas_vote.axi_vote.axi_path[0].transac_type = + CAM_ICP_DEFAULT_AXI_TRANSAC; + cpas_vote.axi_vote.axi_path[0].camnoc_bw = + CAM_ICP_A5_BW_BYTES_VOTE; + cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw = + CAM_ICP_A5_BW_BYTES_VOTE; + cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw = + CAM_ICP_A5_BW_BYTES_VOTE; + cpas_vote.axi_vote.axi_path[0].ddr_ab_bw = + CAM_ICP_A5_BW_BYTES_VOTE; + cpas_vote.axi_vote.axi_path[0].ddr_ib_bw = + CAM_ICP_A5_BW_BYTES_VOTE; + + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote.ahb_vote, &cpas_vote.axi_vote); + if (rc) { + CAM_ERR(CAM_ICP, "cpas start failed: %d", rc); + goto error; + } + core_info->cpas_start = true; + + rc = cam_a5_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_ICP, "soc enable is failed: %d", rc); + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_ICP, "cpas stop is failed"); + else + core_info->cpas_start = false; + } + +error: + return rc; +} + +int cam_a5_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *a5_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_a5_device_core_info *core_info = NULL; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &a5_dev->soc_info; + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + rc = cam_a5_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc); + + if (core_info->cpas_start) { + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_ICP, "cpas stop is failed"); + else + core_info->cpas_start = false; + } + + return rc; +} + +irqreturn_t cam_a5_irq(int irq_num, void *data) +{ + struct cam_hw_info *a5_dev = data; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_a5_device_core_info *core_info = NULL; + struct cam_a5_device_hw_info *hw_info = NULL; + uint32_t irq_status = 0; + + if (!data) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info or query_cap args"); + return IRQ_HANDLED; + } + + soc_info = &a5_dev->soc_info; + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + hw_info = core_info->a5_hw_info; + + irq_status = cam_io_r_mb(soc_info->reg_map[A5_SIERRA_BASE].mem_base + + core_info->a5_hw_info->a5_host_int_status); + + cam_io_w_mb(irq_status, + soc_info->reg_map[A5_SIERRA_BASE].mem_base + + core_info->a5_hw_info->a5_host_int_clr); + + if ((irq_status & A5_WDT_0) || + (irq_status & A5_WDT_1)) { + CAM_ERR_RATE_LIMIT(CAM_ICP, "watch dog interrupt from A5"); + } + + spin_lock(&a5_dev->hw_lock); + if (core_info->irq_cb.icp_hw_mgr_cb) + core_info->irq_cb.icp_hw_mgr_cb(irq_status, + core_info->irq_cb.data); + spin_unlock(&a5_dev->hw_lock); + + return IRQ_HANDLED; +} + +int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *a5_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_a5_device_core_info *core_info = NULL; + struct cam_a5_device_hw_info *hw_info = NULL; + struct a5_soc_info *a5_soc = NULL; + unsigned long flags; + uint32_t ubwc_ipe_cfg[ICP_UBWC_MAX] = {0}; + uint32_t ubwc_bps_cfg[ICP_UBWC_MAX] = {0}; + uint32_t index = 0; + int rc = 0, ddr_type = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid arguments"); + return -EINVAL; + } + + if (cmd_type >= CAM_ICP_A5_CMD_MAX) { + CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type); + return -EINVAL; + } + + soc_info = &a5_dev->soc_info; + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + hw_info = core_info->a5_hw_info; + + switch (cmd_type) { + case CAM_ICP_A5_CMD_FW_DOWNLOAD: + rc = cam_a5_download_fw(device_priv); + break; + case CAM_ICP_A5_CMD_SET_FW_BUF: { + struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "cmd args NULL"); + return -EINVAL; + } + + core_info->fw_buf = fw_buf_info->iova; + core_info->fw_kva_addr = fw_buf_info->kva; + core_info->fw_buf_len = fw_buf_info->len; + + CAM_DBG(CAM_ICP, "fw buf info = %x %llx %lld", + core_info->fw_buf, core_info->fw_kva_addr, + core_info->fw_buf_len); + break; + } + case CAM_ICP_A5_SET_IRQ_CB: { + struct cam_icp_a5_set_irq_cb *irq_cb = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "cmd args NULL"); + return -EINVAL; + } + + spin_lock_irqsave(&a5_dev->hw_lock, flags); + core_info->irq_cb.icp_hw_mgr_cb = irq_cb->icp_hw_mgr_cb; + core_info->irq_cb.data = irq_cb->data; + spin_unlock_irqrestore(&a5_dev->hw_lock, flags); + break; + } + + case CAM_ICP_A5_SEND_INIT: + hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0); + break; + + case CAM_ICP_A5_CMD_PC_PREP: + hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0); + break; + + case CAM_ICP_A5_CMD_VOTE_CPAS: { + struct cam_icp_cpas_vote *cpas_vote = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "cmd args NULL"); + return -EINVAL; + } + + cam_a5_cpas_vote(core_info, cpas_vote); + break; + } + + case CAM_ICP_A5_CMD_CPAS_START: { + struct cam_icp_cpas_vote *cpas_vote = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "cmd args NULL"); + return -EINVAL; + } + + if (!core_info->cpas_start) { + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote->ahb_vote, + &cpas_vote->axi_vote); + core_info->cpas_start = true; + } + break; + } + + case CAM_ICP_A5_CMD_CPAS_STOP: + if (core_info->cpas_start) { + cam_cpas_stop(core_info->cpas_handle); + core_info->cpas_start = false; + } + break; + case CAM_ICP_A5_CMD_UBWC_CFG: { + struct a5_ubwc_cfg_ext *ubwc_cfg_ext = NULL; + + a5_soc = soc_info->soc_private; + if (!a5_soc) { + CAM_ERR(CAM_ICP, "A5 private soc info is NULL"); + return -EINVAL; + } + + if (a5_soc->ubwc_config_ext) { + /* Invoke kernel API to determine DDR type */ + ddr_type = of_fdt_get_ddrtype(); + if ((ddr_type == DDR_TYPE_LPDDR5) || + (ddr_type == DDR_TYPE_LPDDR5X)) + index = 1; + + ubwc_cfg_ext = &a5_soc->uconfig.ubwc_cfg_ext; + ubwc_ipe_cfg[0] = + ubwc_cfg_ext->ubwc_ipe_fetch_cfg[index]; + ubwc_ipe_cfg[1] = + ubwc_cfg_ext->ubwc_ipe_write_cfg[index]; + ubwc_bps_cfg[0] = + ubwc_cfg_ext->ubwc_bps_fetch_cfg[index]; + ubwc_bps_cfg[1] = + ubwc_cfg_ext->ubwc_bps_write_cfg[index]; + rc = hfi_cmd_ubwc_config_ext(&ubwc_ipe_cfg[0], + &ubwc_bps_cfg[0]); + } else { + rc = hfi_cmd_ubwc_config(a5_soc->uconfig.ubwc_cfg); + } + + break; + } + default: + break; + } + + return rc; +} diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h new file mode 100644 index 000000000000..a5c0fffde1d1 --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_A5_CORE_H +#define CAM_A5_CORE_H + +#include +#include +#include +#include +#include "cam_a5_hw_intf.h" + +#define A5_QGIC_BASE 0 +#define A5_SIERRA_BASE 1 +#define A5_CSR_BASE 2 + +#define A5_HOST_INT 0x1 +#define A5_WDT_0 0x2 +#define A5_WDT_1 0x4 + +#define ELF_GUARD_PAGE (2 * 1024 * 1024) + +struct cam_a5_device_hw_info { + uint32_t hw_ver; + uint32_t nsec_reset; + uint32_t a5_control; + uint32_t a5_host_int_en; + uint32_t a5_host_int; + uint32_t a5_host_int_clr; + uint32_t a5_host_int_status; + uint32_t a5_host_int_set; + uint32_t host_a5_int; + uint32_t fw_version; + uint32_t init_req; + uint32_t init_response; + uint32_t shared_mem_ptr; + uint32_t shared_mem_size; + uint32_t qtbl_ptr; + uint32_t uncached_heap_ptr; + uint32_t uncached_heap_size; + uint32_t a5_status; +}; + +/** + * struct cam_a5_device_hw_info + * @a5_hw_info: A5 hardware info + * @fw_elf: start address of fw start with elf header + * @fw: start address of fw blob + * @fw_buf: smmu alloc/mapped fw buffer + * @fw_buf_len: fw buffer length + * @query_cap: A5 query info from firmware + * @a5_acquire: Acquire information of A5 + * @irq_cb: IRQ callback + * @cpas_handle: CPAS handle for A5 + * @cpast_start: state variable for cpas + */ +struct cam_a5_device_core_info { + struct cam_a5_device_hw_info *a5_hw_info; + const struct firmware *fw_elf; + void *fw; + uint32_t fw_buf; + uintptr_t fw_kva_addr; + uint64_t fw_buf_len; + struct cam_icp_a5_query_cap query_cap; + struct cam_icp_a5_acquire_dev a5_acquire[8]; + struct cam_icp_a5_set_irq_cb irq_cb; + uint32_t cpas_handle; + bool cpas_start; +}; + +int cam_a5_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_a5_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); + +irqreturn_t cam_a5_irq(int irq_num, void *data); +#endif /* CAM_A5_CORE_H */ diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c new file mode 100644 index 000000000000..b4f33d3e4dd3 --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "a5_core.h" +#include "a5_soc.h" +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_a5_hw_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +struct a5_soc_info cam_a5_soc_info; +EXPORT_SYMBOL(cam_a5_soc_info); + +struct cam_a5_device_hw_info cam_a5_hw_info = { + .hw_ver = 0x0, + .nsec_reset = 0x4, + .a5_control = 0x8, + .a5_host_int_en = 0x10, + .a5_host_int = 0x14, + .a5_host_int_clr = 0x18, + .a5_host_int_status = 0x1c, + .a5_host_int_set = 0x20, + .host_a5_int = 0x30, + .fw_version = 0x44, + .init_req = 0x48, + .init_response = 0x4c, + .shared_mem_ptr = 0x50, + .shared_mem_size = 0x54, + .qtbl_ptr = 0x58, + .uncached_heap_ptr = 0x5c, + .uncached_heap_size = 0x60, + .a5_status = 0x200, +}; +EXPORT_SYMBOL(cam_a5_hw_info); + +static bool cam_a5_cpas_cb(uint32_t client_handle, void *userdata, + struct cam_cpas_irq_data *irq_data) +{ + bool error_handled = false; + + if (!irq_data) + return error_handled; + + switch (irq_data->irq_type) { + case CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR: + CAM_ERR_RATE_LIMIT(CAM_ICP, + "IPE/BPS UBWC Decode error type=%d status=%x thr_err=%d, fcl_err=%d, len_md_err=%d, format_err=%d", + irq_data->irq_type, + irq_data->u.dec_err.decerr_status.value, + irq_data->u.dec_err.decerr_status.thr_err, + irq_data->u.dec_err.decerr_status.fcl_err, + irq_data->u.dec_err.decerr_status.len_md_err, + irq_data->u.dec_err.decerr_status.format_err); + error_handled = true; + break; + case CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: + CAM_ERR_RATE_LIMIT(CAM_ICP, + "IPE/BPS UBWC Encode error type=%d status=%x", + irq_data->irq_type, + irq_data->u.enc_err.encerr_status.value); + error_handled = true; + break; + default: + break; + } + + return error_handled; +} + +int cam_a5_register_cpas(struct cam_hw_soc_info *soc_info, + struct cam_a5_device_core_info *core_info, + uint32_t hw_idx) +{ + struct cam_cpas_register_params cpas_register_params; + int rc; + + cpas_register_params.dev = &soc_info->pdev->dev; + memcpy(cpas_register_params.identifier, "icp", sizeof("icp")); + cpas_register_params.cam_cpas_client_cb = cam_a5_cpas_cb; + cpas_register_params.cell_index = hw_idx; + cpas_register_params.userdata = NULL; + + rc = cam_cpas_register_client(&cpas_register_params); + if (rc < 0) { + CAM_ERR(CAM_ICP, "failed: %d", rc); + return rc; + } + + core_info->cpas_handle = cpas_register_params.client_handle; + return rc; +} + +int cam_a5_probe(struct platform_device *pdev) +{ + int rc = 0; + struct cam_hw_info *a5_dev = NULL; + struct cam_hw_intf *a5_dev_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_a5_device_core_info *core_info = NULL; + struct cam_a5_device_hw_info *hw_info = NULL; + + a5_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!a5_dev_intf) + return -ENOMEM; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &a5_dev_intf->hw_idx); + + a5_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!a5_dev) { + rc = -ENOMEM; + goto a5_dev_alloc_failure; + } + + a5_dev->soc_info.pdev = pdev; + a5_dev->soc_info.dev = &pdev->dev; + a5_dev->soc_info.dev_name = pdev->name; + a5_dev_intf->hw_priv = a5_dev; + a5_dev_intf->hw_ops.init = cam_a5_init_hw; + a5_dev_intf->hw_ops.deinit = cam_a5_deinit_hw; + a5_dev_intf->hw_ops.process_cmd = cam_a5_process_cmd; + a5_dev_intf->hw_type = CAM_ICP_DEV_A5; + + CAM_DBG(CAM_ICP, "type %d index %d", + a5_dev_intf->hw_type, + a5_dev_intf->hw_idx); + + platform_set_drvdata(pdev, a5_dev_intf); + + a5_dev->core_info = kzalloc(sizeof(struct cam_a5_device_core_info), + GFP_KERNEL); + if (!a5_dev->core_info) { + rc = -ENOMEM; + goto core_info_alloc_failure; + } + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ICP, "No a5 hardware info"); + rc = -EINVAL; + goto match_err; + } + hw_info = (struct cam_a5_device_hw_info *)match_dev->data; + core_info->a5_hw_info = hw_info; + + a5_dev->soc_info.soc_private = &cam_a5_soc_info; + + rc = cam_a5_init_soc_resources(&a5_dev->soc_info, cam_a5_irq, + a5_dev); + if (rc < 0) { + CAM_ERR(CAM_ICP, "failed to init_soc"); + goto init_soc_failure; + } + + CAM_DBG(CAM_ICP, "soc info : %pK", + (void *)&a5_dev->soc_info); + rc = cam_a5_register_cpas(&a5_dev->soc_info, + core_info, a5_dev_intf->hw_idx); + if (rc < 0) { + CAM_ERR(CAM_ICP, "a5 cpas registration failed"); + goto cpas_reg_failed; + } + a5_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&a5_dev->hw_mutex); + spin_lock_init(&a5_dev->hw_lock); + init_completion(&a5_dev->hw_complete); + + CAM_DBG(CAM_ICP, "A5%d probe successful", + a5_dev_intf->hw_idx); + return 0; + +cpas_reg_failed: +init_soc_failure: +match_err: + kfree(a5_dev->core_info); +core_info_alloc_failure: + kfree(a5_dev); +a5_dev_alloc_failure: + kfree(a5_dev_intf); + + return rc; +} + +static const struct of_device_id cam_a5_dt_match[] = { + { + .compatible = "qcom,cam-a5", + .data = &cam_a5_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_a5_dt_match); + +static struct platform_driver cam_a5_driver = { + .probe = cam_a5_probe, + .driver = { + .name = "cam-a5", + .owner = THIS_MODULE, + .of_match_table = cam_a5_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_a5_init_module(void) +{ + return platform_driver_register(&cam_a5_driver); +} + +static void __exit cam_a5_exit_module(void) +{ + platform_driver_unregister(&cam_a5_driver); +} + +module_init(cam_a5_init_module); +module_exit(cam_a5_exit_module); +MODULE_DESCRIPTION("CAM A5 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c new file mode 100644 index 000000000000..bcdc12632356 --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "a5_soc.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +static int cam_a5_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + int rc = 0, i; + const char *fw_name; + struct a5_soc_info *a5_soc_info; + struct device_node *of_node = NULL; + struct platform_device *pdev = NULL; + struct a5_ubwc_cfg_ext *ubwc_cfg_ext = NULL; + int num_ubwc_cfg; + + pdev = soc_info->pdev; + of_node = pdev->dev.of_node; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_ICP, "get a5 dt prop is failed"); + return rc; + } + + a5_soc_info = soc_info->soc_private; + fw_name = a5_soc_info->fw_name; + + rc = of_property_read_string(of_node, "fw_name", &fw_name); + if (rc < 0) { + CAM_ERR(CAM_ICP, "fw_name read failed"); + goto end; + } + + ubwc_cfg_ext = &a5_soc_info->uconfig.ubwc_cfg_ext; + num_ubwc_cfg = of_property_count_u32_elems(of_node, + "ubwc-ipe-fetch-cfg"); + if ((num_ubwc_cfg < 0) || (num_ubwc_cfg > ICP_UBWC_MAX)) { + CAM_DBG(CAM_ICP, "wrong ubwc_ipe_fetch_cfg: %d", num_ubwc_cfg); + rc = num_ubwc_cfg; + goto ubwc_ex_cfg; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, "ubwc-ipe-fetch-cfg", + i, &ubwc_cfg_ext->ubwc_ipe_fetch_cfg[i]); + if (rc < 0) { + CAM_ERR(CAM_ICP, + "unable to read ubwc_ipe_fetch_cfg values"); + goto end; + } + } + + num_ubwc_cfg = of_property_count_u32_elems(of_node, + "ubwc-ipe-write-cfg"); + if ((num_ubwc_cfg < 0) || (num_ubwc_cfg > ICP_UBWC_MAX)) { + CAM_ERR(CAM_ICP, "wrong ubwc_ipe_write_cfg: %d", num_ubwc_cfg); + rc = num_ubwc_cfg; + goto end; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, "ubwc-ipe-write-cfg", + i, &ubwc_cfg_ext->ubwc_ipe_write_cfg[i]); + if (rc < 0) { + CAM_ERR(CAM_ICP, + "unable to read ubwc_ipe_write_cfg values"); + goto end; + } + } + + num_ubwc_cfg = of_property_count_u32_elems(of_node, + "ubwc-bps-fetch-cfg"); + if ((num_ubwc_cfg < 0) || (num_ubwc_cfg > ICP_UBWC_MAX)) { + CAM_ERR(CAM_ICP, "wrong ubwc_bps_fetch_cfg: %d", num_ubwc_cfg); + rc = num_ubwc_cfg; + goto end; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, "ubwc-bps-fetch-cfg", + i, &ubwc_cfg_ext->ubwc_bps_fetch_cfg[i]); + if (rc < 0) { + CAM_ERR(CAM_ICP, + "unable to read ubwc_bps_fetch_cfg values"); + goto end; + } + } + + num_ubwc_cfg = of_property_count_u32_elems(of_node, + "ubwc-bps-write-cfg"); + if ((num_ubwc_cfg < 0) || (num_ubwc_cfg > ICP_UBWC_MAX)) { + CAM_ERR(CAM_ICP, "wrong ubwc_bps_write_cfg: %d", num_ubwc_cfg); + rc = num_ubwc_cfg; + goto end; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, "ubwc-bps-write-cfg", + i, &ubwc_cfg_ext->ubwc_bps_write_cfg[i]); + if (rc < 0) { + CAM_ERR(CAM_ICP, + "unable to read ubwc_bps_write_cfg values"); + goto end; + } + } + + a5_soc_info->ubwc_config_ext = true; + CAM_DBG(CAM_ICP, "read ubwc_cfg_ext for ipe/bps"); + return rc; + +ubwc_ex_cfg: + num_ubwc_cfg = of_property_count_u32_elems(of_node, "ubwc-cfg"); + if ((num_ubwc_cfg < 0) || (num_ubwc_cfg > ICP_UBWC_MAX)) { + CAM_ERR(CAM_ICP, "wrong ubwc_cfg: %d", num_ubwc_cfg); + rc = num_ubwc_cfg; + goto end; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, "ubwc-cfg", + i, &a5_soc_info->uconfig.ubwc_cfg[i]); + if (rc < 0) { + CAM_ERR(CAM_ICP, "unable to read ubwc_cfg values"); + break; + } + } + +end: + return rc; +} + +static int cam_a5_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t a5_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, a5_irq_handler, + irq_data); + + return rc; +} + +int cam_a5_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t a5_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_a5_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + rc = cam_a5_request_platform_resource(soc_info, a5_irq_handler, + irq_data); + if (rc < 0) + return rc; + + return rc; +} + +int cam_a5_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, true); + if (rc) + CAM_ERR(CAM_ICP, "enable platform failed"); + + return rc; +} + +int cam_a5_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) + CAM_ERR(CAM_ICP, "disable platform failed"); + + return rc; +} diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h new file mode 100644 index 000000000000..eadf9d726696 --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_A5_SOC_H +#define CAM_A5_SOC_H + +#include "cam_soc_util.h" + +#define ICP_UBWC_MAX 2 + +struct a5_ubwc_cfg_ext { + uint32_t ubwc_ipe_fetch_cfg[ICP_UBWC_MAX]; + uint32_t ubwc_ipe_write_cfg[ICP_UBWC_MAX]; + uint32_t ubwc_bps_fetch_cfg[ICP_UBWC_MAX]; + uint32_t ubwc_bps_write_cfg[ICP_UBWC_MAX]; +}; + +struct a5_soc_info { + char *fw_name; + bool ubwc_config_ext; + union { + uint32_t ubwc_cfg[ICP_UBWC_MAX]; + struct a5_ubwc_cfg_ext ubwc_cfg_ext; + } uconfig; +}; + +int cam_a5_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t a5_irq_handler, void *irq_data); + +int cam_a5_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +int cam_a5_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +#endif diff --git a/drivers/cam_icp/icp_hw/bps_hw/Makefile b/drivers/cam_icp/icp_hw/bps_hw/Makefile new file mode 100644 index 000000000000..2abf88310cbd --- /dev/null +++ b/drivers/cam_icp/icp_hw/bps_hw/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/bps_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += bps_dev.o bps_core.o bps_soc.o diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c new file mode 100644 index 000000000000..73075a4ec379 --- /dev/null +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "bps_core.h" +#include "bps_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_bps_hw_intf.h" +#include "cam_icp_hw_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "hfi_reg.h" + +#define HFI_MAX_POLL_TRY 5 + +static int cam_bps_cpas_vote(struct cam_bps_device_core_info *core_info, + struct cam_icp_cpas_vote *cpas_vote) +{ + int rc = 0; + + if (cpas_vote->ahb_vote_valid) + rc = cam_cpas_update_ahb_vote(core_info->cpas_handle, + &cpas_vote->ahb_vote); + if (cpas_vote->axi_vote_valid) + rc = cam_cpas_update_axi_vote(core_info->cpas_handle, + &cpas_vote->axi_vote); + + if (rc < 0) + CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc); + + return rc; +} + + +int cam_bps_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *bps_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_bps_device_core_info *core_info = NULL; + struct cam_icp_cpas_vote cpas_vote; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &bps_dev->soc_info; + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; + cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.axi_vote.num_paths = 1; + cpas_vote.axi_vote.axi_path[0].path_data_type = + CAM_BPS_DEFAULT_AXI_PATH; + cpas_vote.axi_vote.axi_path[0].transac_type = + CAM_BPS_DEFAULT_AXI_TRANSAC; + cpas_vote.axi_vote.axi_path[0].camnoc_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote.ahb_vote, &cpas_vote.axi_vote); + if (rc) { + CAM_ERR(CAM_ICP, "cpas start failed: %d", rc); + goto error; + } + core_info->cpas_start = true; + + rc = cam_bps_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_ICP, "soc enable is failed: %d", rc); + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_ICP, "cpas stop is failed"); + else + core_info->cpas_start = false; + } else { + core_info->clk_enable = true; + } + +error: + return rc; +} + +int cam_bps_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *bps_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_bps_device_core_info *core_info = NULL; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &bps_dev->soc_info; + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + rc = cam_bps_disable_soc_resources(soc_info, core_info->clk_enable); + if (rc) + CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc); + core_info->clk_enable = false; + + if (core_info->cpas_start) { + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_ICP, "cpas stop is failed"); + else + core_info->cpas_start = false; + } + + return rc; +} + +static int cam_bps_handle_pc(struct cam_hw_info *bps_dev) +{ + struct cam_hw_soc_info *soc_info = NULL; + struct cam_bps_device_core_info *core_info = NULL; + struct cam_bps_device_hw_info *hw_info = NULL; + int pwr_ctrl; + int pwr_status; + + soc_info = &bps_dev->soc_info; + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + hw_info = core_info->bps_hw_info; + + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (!(pwr_ctrl & BPS_COLLAPSE_MASK)) { + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0x1); + + if ((pwr_status >> BPS_PWR_ON_MASK)) + CAM_WARN(CAM_ICP, "BPS: pwr_status(%x):pwr_ctrl(%x)", + pwr_status, pwr_ctrl); + } + cam_bps_get_gdsc_control(soc_info); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, + &pwr_ctrl); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + pwr_ctrl, pwr_status); + + return 0; +} + +static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) +{ + struct cam_hw_soc_info *soc_info = NULL; + struct cam_bps_device_core_info *core_info = NULL; + struct cam_bps_device_hw_info *hw_info = NULL; + int pwr_ctrl; + int pwr_status; + int rc = 0; + + soc_info = &bps_dev->soc_info; + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + hw_info = core_info->bps_hw_info; + + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); + if (pwr_ctrl & BPS_COLLAPSE_MASK) { + CAM_DBG(CAM_ICP, "BPS: pwr_ctrl set(%x)", pwr_ctrl); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0); + } + + rc = cam_bps_transfer_gdsc_control(soc_info); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status); + CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + pwr_ctrl, pwr_status); + + return rc; +} + +static int cam_bps_cmd_reset(struct cam_hw_soc_info *soc_info, + struct cam_bps_device_core_info *core_info) +{ + uint32_t retry_cnt = 0; + uint32_t status = 0; + int pwr_ctrl, pwr_status, rc = 0; + bool reset_bps_cdm_fail = false; + 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); + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((soc_info->reg_map[0].mem_base + + BPS_CDM_IRQ_STATUS), + status, ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1), + 100, 10000); + + CAM_DBG(CAM_ICP, "bps_cdm_irq_status = %u", status); + + if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1) + break; + retry_cnt++; + } + status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + BPS_CDM_IRQ_STATUS); + if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) != 0x1) { + CAM_ERR(CAM_ICP, "BPS CDM rst failed status 0x%x", status); + reset_bps_cdm_fail = true; + } + + /* Reset BPS core*/ + status = 0; + cam_io_w_mb((uint32_t)0x3, + soc_info->reg_map[0].mem_base + BPS_TOP_RST_CMD); + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((soc_info->reg_map[0].mem_base + + BPS_TOP_IRQ_STATUS), + status, ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1), + 100, 10000); + + CAM_DBG(CAM_ICP, "bps_top_irq_status = %u", status); + + if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1) + break; + retry_cnt++; + } + status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + BPS_TOP_IRQ_STATUS); + if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) != 0x1) { + CAM_ERR(CAM_ICP, "BPS top rst failed status 0x%x", status); + reset_bps_top_fail = true; + } + + cam_bps_get_gdsc_control(soc_info); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, core_info->bps_hw_info->pwr_ctrl, + true, &pwr_ctrl); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, core_info->bps_hw_info->pwr_status, + true, &pwr_status); + CAM_DBG(CAM_ICP, "(After) pwr_ctrl = %x pwr_status = %x", + pwr_ctrl, pwr_status); + + if (reset_bps_cdm_fail || reset_bps_top_fail) + rc = -EAGAIN; + + return rc; +} + +int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *bps_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_bps_device_core_info *core_info = NULL; + struct cam_bps_device_hw_info *hw_info = NULL; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid arguments"); + return -EINVAL; + } + + if (cmd_type >= CAM_ICP_BPS_CMD_MAX) { + CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type); + return -EINVAL; + } + + soc_info = &bps_dev->soc_info; + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + hw_info = core_info->bps_hw_info; + + switch (cmd_type) { + case CAM_ICP_BPS_CMD_VOTE_CPAS: { + struct cam_icp_cpas_vote *cpas_vote = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "cmd args NULL"); + return -EINVAL; + } + + cam_bps_cpas_vote(core_info, cpas_vote); + break; + } + + case CAM_ICP_BPS_CMD_CPAS_START: { + struct cam_icp_cpas_vote *cpas_vote = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "cmd args NULL"); + return -EINVAL; + } + + if (!core_info->cpas_start) { + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote->ahb_vote, + &cpas_vote->axi_vote); + core_info->cpas_start = true; + } + break; + } + + case CAM_ICP_BPS_CMD_CPAS_STOP: + if (core_info->cpas_start) { + cam_cpas_stop(core_info->cpas_handle); + core_info->cpas_start = false; + } + break; + case CAM_ICP_BPS_CMD_POWER_COLLAPSE: + rc = cam_bps_handle_pc(bps_dev); + break; + case CAM_ICP_BPS_CMD_POWER_RESUME: + rc = cam_bps_handle_resume(bps_dev); + break; + case CAM_ICP_BPS_CMD_UPDATE_CLK: { + struct cam_a5_clk_update_cmd *clk_upd_cmd = + (struct cam_a5_clk_update_cmd *)cmd_args; + uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; + + CAM_DBG(CAM_ICP, "bps_src_clk rate = %d", (int)clk_rate); + + if (!core_info->clk_enable) { + if (clk_upd_cmd->ipe_bps_pc_enable) { + cam_bps_handle_pc(bps_dev); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0x0); + } + rc = cam_bps_toggle_clk(soc_info, true); + if (rc) + CAM_ERR(CAM_ICP, "Enable failed"); + else + core_info->clk_enable = true; + if (clk_upd_cmd->ipe_bps_pc_enable) { + rc = cam_bps_handle_resume(bps_dev); + if (rc) + CAM_ERR(CAM_ICP, "BPS resume failed"); + } + } + CAM_DBG(CAM_ICP, "clock rate %d", clk_rate); + rc = cam_bps_update_clk_rate(soc_info, clk_rate); + if (rc) + CAM_ERR(CAM_ICP, "Failed to update clk"); + } + break; + case CAM_ICP_BPS_CMD_DISABLE_CLK: + if (core_info->clk_enable == true) + cam_bps_toggle_clk(soc_info, false); + core_info->clk_enable = false; + break; + case CAM_ICP_BPS_CMD_RESET: + rc = cam_bps_cmd_reset(soc_info, core_info); + break; + default: + CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type); + rc = -EINVAL; + break; + } + return rc; +} + +irqreturn_t cam_bps_irq(int irq_num, void *data) +{ + return IRQ_HANDLED; +} diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.h b/drivers/cam_icp/icp_hw/bps_hw/bps_core.h new file mode 100644 index 000000000000..162c5e65530c --- /dev/null +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_BPS_CORE_H +#define CAM_BPS_CORE_H + +#include +#include +#include +#include + +#define BPS_COLLAPSE_MASK 0x1 +#define BPS_PWR_ON_MASK 0x2 + +struct cam_bps_device_hw_info { + uint32_t hw_idx; + uint32_t pwr_ctrl; + uint32_t pwr_status; + uint32_t reserved; +}; + +struct cam_bps_device_core_info { + struct cam_bps_device_hw_info *bps_hw_info; + uint32_t cpas_handle; + bool cpas_start; + bool clk_enable; +}; + +int cam_bps_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_bps_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); + +irqreturn_t cam_bps_irq(int irq_num, void *data); +#endif /* CAM_BPS_CORE_H */ diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c new file mode 100644 index 000000000000..a80c27325b72 --- /dev/null +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "bps_core.h" +#include "bps_soc.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_io_util.h" +#include "cam_icp_hw_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +static struct cam_bps_device_hw_info cam_bps_hw_info = { + .hw_idx = 0, + .pwr_ctrl = 0x5c, + .pwr_status = 0x58, + .reserved = 0, +}; +EXPORT_SYMBOL(cam_bps_hw_info); + +static char bps_dev_name[8]; + +static bool cam_bps_cpas_cb(uint32_t client_handle, void *userdata, + struct cam_cpas_irq_data *irq_data) +{ + bool error_handled = false; + + if (!irq_data) + return error_handled; + + switch (irq_data->irq_type) { + case CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR: + CAM_ERR_RATE_LIMIT(CAM_ICP, + "IPE/BPS UBWC Decode error type=%d status=%x thr_err=%d, fcl_err=%d, len_md_err=%d, format_err=%d", + irq_data->irq_type, + irq_data->u.dec_err.decerr_status.value, + irq_data->u.dec_err.decerr_status.thr_err, + irq_data->u.dec_err.decerr_status.fcl_err, + irq_data->u.dec_err.decerr_status.len_md_err, + irq_data->u.dec_err.decerr_status.format_err); + error_handled = true; + break; + case CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: + CAM_ERR_RATE_LIMIT(CAM_ICP, + "IPE/BPS UBWC Encode error type=%d status=%x", + irq_data->irq_type, + irq_data->u.enc_err.encerr_status.value); + error_handled = true; + break; + default: + break; + } + + return error_handled; +} + +int cam_bps_register_cpas(struct cam_hw_soc_info *soc_info, + struct cam_bps_device_core_info *core_info, + uint32_t hw_idx) +{ + struct cam_cpas_register_params cpas_register_params; + int rc; + + cpas_register_params.dev = &soc_info->pdev->dev; + memcpy(cpas_register_params.identifier, "bps", sizeof("bps")); + cpas_register_params.cam_cpas_client_cb = cam_bps_cpas_cb; + cpas_register_params.cell_index = hw_idx; + cpas_register_params.userdata = NULL; + + rc = cam_cpas_register_client(&cpas_register_params); + if (rc < 0) { + CAM_ERR(CAM_ICP, "failed: %d", rc); + return rc; + } + core_info->cpas_handle = cpas_register_params.client_handle; + + return rc; +} + +int cam_bps_probe(struct platform_device *pdev) +{ + struct cam_hw_info *bps_dev = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_bps_device_core_info *core_info = NULL; + struct cam_bps_device_hw_info *hw_info = NULL; + int rc = 0; + + bps_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!bps_dev_intf) + return -ENOMEM; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &bps_dev_intf->hw_idx); + + bps_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!bps_dev) { + kfree(bps_dev_intf); + return -ENOMEM; + } + + memset(bps_dev_name, 0, sizeof(bps_dev_name)); + snprintf(bps_dev_name, sizeof(bps_dev_name), + "bps%1u", bps_dev_intf->hw_idx); + + bps_dev->soc_info.pdev = pdev; + bps_dev->soc_info.dev = &pdev->dev; + bps_dev->soc_info.dev_name = bps_dev_name; + bps_dev_intf->hw_priv = bps_dev; + bps_dev_intf->hw_ops.init = cam_bps_init_hw; + bps_dev_intf->hw_ops.deinit = cam_bps_deinit_hw; + bps_dev_intf->hw_ops.process_cmd = cam_bps_process_cmd; + bps_dev_intf->hw_type = CAM_ICP_DEV_BPS; + platform_set_drvdata(pdev, bps_dev_intf); + bps_dev->core_info = kzalloc(sizeof(struct cam_bps_device_core_info), + GFP_KERNEL); + if (!bps_dev->core_info) { + kfree(bps_dev); + kfree(bps_dev_intf); + return -ENOMEM; + } + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ICP, "No bps hardware info"); + kfree(bps_dev->core_info); + kfree(bps_dev); + kfree(bps_dev_intf); + rc = -EINVAL; + return rc; + } + hw_info = &cam_bps_hw_info; + core_info->bps_hw_info = hw_info; + + rc = cam_bps_init_soc_resources(&bps_dev->soc_info, cam_bps_irq, + bps_dev); + if (rc < 0) { + CAM_ERR(CAM_ICP, "failed to init_soc"); + kfree(bps_dev->core_info); + kfree(bps_dev); + kfree(bps_dev_intf); + return rc; + } + CAM_DBG(CAM_ICP, "soc info : %pK", + (void *)&bps_dev->soc_info); + + rc = cam_bps_register_cpas(&bps_dev->soc_info, + core_info, bps_dev_intf->hw_idx); + if (rc < 0) { + kfree(bps_dev->core_info); + kfree(bps_dev); + kfree(bps_dev_intf); + return rc; + } + bps_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&bps_dev->hw_mutex); + spin_lock_init(&bps_dev->hw_lock); + init_completion(&bps_dev->hw_complete); + CAM_DBG(CAM_ICP, "BPS%d probe successful", + bps_dev_intf->hw_idx); + + return rc; +} + +static const struct of_device_id cam_bps_dt_match[] = { + { + .compatible = "qcom,cam-bps", + .data = &cam_bps_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_bps_dt_match); + +static struct platform_driver cam_bps_driver = { + .probe = cam_bps_probe, + .driver = { + .name = "cam-bps", + .owner = THIS_MODULE, + .of_match_table = cam_bps_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_bps_init_module(void) +{ + return platform_driver_register(&cam_bps_driver); +} + +static void __exit cam_bps_exit_module(void) +{ + platform_driver_unregister(&cam_bps_driver); +} + +module_init(cam_bps_init_module); +module_exit(cam_bps_exit_module); +MODULE_DESCRIPTION("CAM BPS driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c new file mode 100644 index 000000000000..bf152d1fc485 --- /dev/null +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "bps_soc.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +static int cam_bps_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) + CAM_ERR(CAM_ICP, "get bps dt prop is failed"); + + return rc; +} + +static int cam_bps_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t bps_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, bps_irq_handler, + irq_data); + + return rc; +} + +int cam_bps_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t bps_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_bps_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + rc = cam_bps_request_platform_resource(soc_info, bps_irq_handler, + irq_data); + if (rc < 0) + return rc; + + return rc; +} + +int cam_bps_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, false); + if (rc) + CAM_ERR(CAM_ICP, "enable platform failed"); + + return rc; +} + +int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info, + bool disable_clk) +{ + int rc = 0; + + rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk, + false); + if (rc) + CAM_ERR(CAM_ICP, "disable platform failed"); + + return rc; +} + +int cam_bps_transfer_gdsc_control(struct cam_hw_soc_info *soc_info) +{ + int i; + int rc; + + for (i = 0; i < soc_info->num_rgltr; i++) { + rc = regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_FAST); + if (rc) { + CAM_ERR(CAM_ICP, "Regulator set mode %s failed", + soc_info->rgltr_name[i]); + goto rgltr_set_mode_failed; + } + } + return 0; + +rgltr_set_mode_failed: + for (i = i - 1; i >= 0; i--) + if (soc_info->rgltr[i]) + regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_NORMAL); + + return rc; +} + +int cam_bps_get_gdsc_control(struct cam_hw_soc_info *soc_info) +{ + int i; + int rc; + + for (i = 0; i < soc_info->num_rgltr; i++) { + rc = regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_NORMAL); + if (rc) { + CAM_ERR(CAM_ICP, "Regulator set mode %s failed", + soc_info->rgltr_name[i]); + goto rgltr_set_mode_failed; + } + } + return 0; + +rgltr_set_mode_failed: + for (i = i - 1; i >= 0; i--) + if (soc_info->rgltr[i]) + regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_FAST); + + return rc; +} + +int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_rate) +{ + int32_t src_clk_idx; + + if (!soc_info) + return -EINVAL; + + src_clk_idx = soc_info->src_clk_idx; + + if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) && + (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && + (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { + CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d", + clk_rate, + soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); + clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; + } + + return cam_soc_util_set_src_clk_rate(soc_info, clk_rate); +} + +int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable) +{ + int rc = 0; + + if (clk_enable) + rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE); + else + cam_soc_util_clk_disable_default(soc_info); + + return rc; +} diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h new file mode 100644 index 000000000000..da4feac909e4 --- /dev/null +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_BPS_SOC_H_ +#define _CAM_BPS_SOC_H_ + +#include "cam_soc_util.h" + +int cam_bps_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t bps_irq_handler, void *irq_data); + +int cam_bps_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info, + bool disable_clk); + +int cam_bps_get_gdsc_control(struct cam_hw_soc_info *soc_info); + +int cam_bps_transfer_gdsc_control(struct cam_hw_soc_info *soc_info); + +int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_rate); +int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable); +#endif /* _CAM_BPS_SOC_H_*/ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile b/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile new file mode 100644 index 000000000000..2d06413e74ca --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/isp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/a5_hw/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp_hw_mgr.o diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c new file mode 100644 index 000000000000..2a77519d92cb --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -0,0 +1,5582 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cam_sync_api.h" +#include "cam_packet_util.h" +#include "cam_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_icp_hw_mgr.h" +#include "cam_a5_hw_intf.h" +#include "cam_bps_hw_intf.h" +#include "cam_ipe_hw_intf.h" +#include "cam_smmu_api.h" +#include "cam_mem_mgr.h" +#include "hfi_intf.h" +#include "hfi_reg.h" +#include "hfi_session_defs.h" +#include "hfi_sys_defs.h" +#include "cam_req_mgr_workq.h" +#include "cam_mem_mgr.h" +#include "a5_core.h" +#include "hfi_sys_defs.h" +#include "cam_debug_util.h" +#include "cam_soc_util.h" +#include "cam_trace.h" +#include "cam_cpas_api.h" +#include "cam_common_util.h" + +#define ICP_WORKQ_TASK_CMD_TYPE 1 +#define ICP_WORKQ_TASK_MSG_TYPE 2 + +#define ICP_DEV_TYPE_TO_CLK_TYPE(dev_type) \ + ((dev_type == CAM_ICP_RES_TYPE_BPS) ? ICP_CLK_HW_BPS : ICP_CLK_HW_IPE) + +#define ICP_DEVICE_IDLE_TIMEOUT 400 + +static struct cam_icp_hw_mgr icp_hw_mgr; + +static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl); + +static const char *cam_icp_dev_type_to_name( + uint32_t dev_type) +{ + switch (dev_type) { + case CAM_ICP_RES_TYPE_BPS: + return "BPS"; + case CAM_ICP_RES_TYPE_IPE_RT: + return "IPE_RT"; + case CAM_ICP_RES_TYPE_IPE: + return "IPE"; + default: + return "Invalid dev type"; + } +} + +static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *a5_dev_intf = NULL; + int rc; + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is NULL"); + return -EINVAL; + } + + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_CMD_UBWC_CFG, NULL, 0); + if (rc) + CAM_ERR(CAM_ICP, "CAM_ICP_A5_CMD_UBWC_CFG is failed"); + + return rc; +} + +static void cam_icp_hw_mgr_clk_info_update(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) +{ + struct cam_icp_clk_info *hw_mgr_clk_info; + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; + else + hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; + + if (hw_mgr_clk_info->base_clk >= ctx_data->clk_info.base_clk) + hw_mgr_clk_info->base_clk -= ctx_data->clk_info.base_clk; +} + +static void cam_icp_hw_mgr_reset_clk_info(struct cam_icp_hw_mgr *hw_mgr) +{ + int i; + + for (i = 0; i < ICP_CLK_HW_MAX; i++) { + hw_mgr->clk_info[i].base_clk = 0; + hw_mgr->clk_info[i].curr_clk = ICP_CLK_SVS_HZ; + hw_mgr->clk_info[i].threshold = ICP_OVER_CLK_THRESHOLD; + hw_mgr->clk_info[i].over_clked = 0; + hw_mgr->clk_info[i].uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW; + hw_mgr->clk_info[i].compressed_bw = CAM_CPAS_DEFAULT_AXI_BW; + } + hw_mgr->icp_default_clk = ICP_CLK_SVS_HZ; +} + +static int cam_icp_get_actual_clk_rate_idx( + struct cam_icp_hw_ctx_data *ctx_data, uint32_t base_clk) +{ + int i; + + for (i = 0; i < CAM_MAX_VOTE; i++) + if (ctx_data->clk_info.clk_rate[i] >= base_clk) + return i; + + /* + * Caller has to ensure returned index is within array + * size bounds while accessing that index. + */ + + return i; +} + +static bool cam_icp_is_over_clk(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_icp_clk_info *hw_mgr_clk_info) +{ + int base_clk_idx; + int curr_clk_idx; + + base_clk_idx = cam_icp_get_actual_clk_rate_idx(ctx_data, + hw_mgr_clk_info->base_clk); + + curr_clk_idx = cam_icp_get_actual_clk_rate_idx(ctx_data, + hw_mgr_clk_info->curr_clk); + + CAM_DBG(CAM_ICP, "bc_idx = %d cc_idx = %d %d %d", + base_clk_idx, curr_clk_idx, hw_mgr_clk_info->base_clk, + hw_mgr_clk_info->curr_clk); + + if (curr_clk_idx > base_clk_idx) + return true; + + return false; +} + +static int cam_icp_get_lower_clk_rate(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, uint32_t base_clk) +{ + int i; + + i = cam_icp_get_actual_clk_rate_idx(ctx_data, base_clk); + + if (i > 0) + return ctx_data->clk_info.clk_rate[i - 1]; + + CAM_DBG(CAM_ICP, "Already clk at lower level"); + return base_clk; +} + +static int cam_icp_get_next_clk_rate(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, uint32_t base_clk) +{ + int i; + + i = cam_icp_get_actual_clk_rate_idx(ctx_data, base_clk); + + if (i < CAM_MAX_VOTE - 1) + return ctx_data->clk_info.clk_rate[i + 1]; + + CAM_DBG(CAM_ICP, "Already clk at higher level"); + + return base_clk; +} + +static int cam_icp_get_actual_clk_rate(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, uint32_t base_clk) +{ + int i; + + for (i = 0; i < CAM_MAX_VOTE; i++) + if (ctx_data->clk_info.clk_rate[i] >= base_clk) + return ctx_data->clk_info.clk_rate[i]; + + return base_clk; +} + +static int cam_icp_supported_clk_rates(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) +{ + int i; + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *dev_intf = NULL; + struct cam_hw_info *dev = NULL; + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + dev_intf = hw_mgr->bps_dev_intf; + else + dev_intf = hw_mgr->ipe0_dev_intf; + + if (!dev_intf) { + CAM_ERR(CAM_ICP, "dev_intf is invalid"); + return -EINVAL; + } + dev = (struct cam_hw_info *)dev_intf->hw_priv; + soc_info = &dev->soc_info; + + for (i = 0; i < CAM_MAX_VOTE; i++) { + ctx_data->clk_info.clk_rate[i] = + soc_info->clk_rate[i][soc_info->src_clk_idx]; + CAM_DBG(CAM_ICP, "clk_info[%d] = %d", + i, ctx_data->clk_info.clk_rate[i]); + } + + return 0; +} + +static int cam_icp_clk_idx_from_req_id(struct cam_icp_hw_ctx_data *ctx_data, + uint64_t req_id) +{ + struct hfi_frame_process_info *frame_process; + int i; + + frame_process = &ctx_data->hfi_frame_process; + + for (i = 0; i < CAM_FRAME_CMD_MAX; i++) + if (frame_process->request_id[i] == req_id) + return i; + + return 0; +} + +static int cam_icp_ctx_clk_info_init(struct cam_icp_hw_ctx_data *ctx_data) +{ + int i; + + ctx_data->clk_info.curr_fc = 0; + ctx_data->clk_info.base_clk = 0; + ctx_data->clk_info.uncompressed_bw = 0; + ctx_data->clk_info.compressed_bw = 0; + for (i = 0; i < CAM_ICP_MAX_PER_PATH_VOTES; i++) { + ctx_data->clk_info.axi_path[i].camnoc_bw = 0; + ctx_data->clk_info.axi_path[i].mnoc_ab_bw = 0; + ctx_data->clk_info.axi_path[i].mnoc_ib_bw = 0; + } + + cam_icp_supported_clk_rates(&icp_hw_mgr, ctx_data); + + return 0; +} + +static bool cam_icp_frame_pending(struct cam_icp_hw_ctx_data *ctx_data) +{ + return !bitmap_empty(ctx_data->hfi_frame_process.bitmap, + CAM_FRAME_CMD_MAX); +} + +static int cam_icp_ctx_timer_reset(struct cam_icp_hw_ctx_data *ctx_data) +{ + if (ctx_data && ctx_data->watch_dog) { + ctx_data->watch_dog_reset_counter++; + CAM_DBG(CAM_ICP, "reset timer : ctx_id = %d, counter=%d", + ctx_data->ctx_id, ctx_data->watch_dog_reset_counter); + crm_timer_reset(ctx_data->watch_dog); + } + + return 0; +} + +static void cam_icp_device_timer_reset(struct cam_icp_hw_mgr *hw_mgr, + int device_index) +{ + if ((device_index >= ICP_CLK_HW_MAX) || (!hw_mgr)) + return; + + if (hw_mgr->clk_info[device_index].watch_dog) { + CAM_DBG(CAM_ICP, "reset timer : device_index = %d", + device_index); + crm_timer_reset(hw_mgr->clk_info[device_index].watch_dog); + hw_mgr->clk_info[device_index].watch_dog_reset_counter++; + } +} + +static int32_t cam_icp_deinit_idle_clk(void *priv, void *data) +{ + struct cam_icp_hw_mgr *hw_mgr = (struct cam_icp_hw_mgr *)priv; + struct clk_work_data *task_data = (struct clk_work_data *)data; + struct cam_icp_clk_info *clk_info = + (struct cam_icp_clk_info *)task_data->data; + uint32_t id; + uint32_t i; + struct cam_icp_hw_ctx_data *ctx_data; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + struct cam_hw_intf *dev_intf = NULL; + struct cam_a5_clk_update_cmd clk_upd_cmd; + int rc = 0; + bool busy = false; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + clk_info->base_clk = 0; + clk_info->curr_clk = 0; + clk_info->over_clked = 0; + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { + ctx_data = &hw_mgr->ctx_data[i]; + mutex_lock(&ctx_data->ctx_mutex); + if ((ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED) && + (ICP_DEV_TYPE_TO_CLK_TYPE( + ctx_data->icp_dev_acquire_info->dev_type) + == clk_info->hw_type)) { + busy = cam_icp_frame_pending(ctx_data); + if (busy) { + mutex_unlock(&ctx_data->ctx_mutex); + break; + } + cam_icp_ctx_clk_info_init(ctx_data); + } + mutex_unlock(&ctx_data->ctx_mutex); + } + + if (busy) { + cam_icp_device_timer_reset(hw_mgr, clk_info->hw_type); + rc = -EBUSY; + goto done; + } + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk"); + rc = -EINVAL; + goto done; + } + + if (clk_info->hw_type == ICP_CLK_HW_BPS) { + dev_intf = bps_dev_intf; + id = CAM_ICP_BPS_CMD_DISABLE_CLK; + } else if (clk_info->hw_type == ICP_CLK_HW_IPE) { + dev_intf = ipe0_dev_intf; + id = CAM_ICP_IPE_CMD_DISABLE_CLK; + } else { + CAM_ERR(CAM_ICP, "Error"); + goto done; + } + + CAM_DBG(CAM_ICP, "Disable %d", clk_info->hw_type); + + clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; + + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + &clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd)); + + if (clk_info->hw_type != ICP_CLK_HW_BPS) + if (ipe1_dev_intf) + ipe1_dev_intf->hw_ops.process_cmd( + ipe1_dev_intf->hw_priv, id, + &clk_upd_cmd, + sizeof(struct cam_a5_clk_update_cmd)); + +done: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int32_t cam_icp_ctx_timer(void *priv, void *data) +{ + struct clk_work_data *task_data = (struct clk_work_data *)data; + struct cam_icp_hw_ctx_data *ctx_data = + (struct cam_icp_hw_ctx_data *)task_data->data; + struct cam_icp_hw_mgr *hw_mgr = &icp_hw_mgr; + uint32_t id; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + struct cam_hw_intf *dev_intf = NULL; + struct cam_icp_clk_info *clk_info; + struct cam_icp_cpas_vote clk_update; + int i = 0; + int device_share_ratio = 1; + + if (!ctx_data) { + CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk"); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) || + (ctx_data->watch_dog_reset_counter == 0)) { + CAM_DBG(CAM_ICP, "state %d, counter=%d", + ctx_data->state, ctx_data->watch_dog_reset_counter); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + if (cam_icp_frame_pending(ctx_data)) { + cam_icp_ctx_timer_reset(ctx_data); + mutex_unlock(&ctx_data->ctx_mutex); + return -EBUSY; + } + + CAM_DBG(CAM_ICP, + "E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u", + ctx_data->ctx_id, + ctx_data->clk_info.uncompressed_bw, + ctx_data->clk_info.compressed_bw, + ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk); + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk"); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + + if (!ctx_data->icp_dev_acquire_info) { + CAM_WARN(CAM_ICP, "NULL acquire info"); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { + dev_intf = bps_dev_intf; + clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; + id = CAM_ICP_BPS_CMD_VOTE_CPAS; + } else { + dev_intf = ipe0_dev_intf; + clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; + id = CAM_ICP_IPE_CMD_VOTE_CPAS; + } + + /* + * Since there are 2 devices, we assume the load is evenly shared + * between HWs and corresponding AXI paths. So divide total bw by half + * to vote on each device + */ + if ((ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) + device_share_ratio = 2; + + clk_update.ahb_vote.type = CAM_VOTE_DYNAMIC; + clk_update.ahb_vote.vote.freq = 0; + clk_update.ahb_vote_valid = false; + + if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) { + clk_update.axi_vote.num_paths = 1; + if (ctx_data->icp_dev_acquire_info->dev_type == + CAM_ICP_RES_TYPE_BPS) { + clk_update.axi_vote.axi_path[0].path_data_type = + CAM_BPS_DEFAULT_AXI_PATH; + clk_update.axi_vote.axi_path[0].transac_type = + CAM_BPS_DEFAULT_AXI_TRANSAC; + } else { + clk_update.axi_vote.axi_path[0].path_data_type = + CAM_IPE_DEFAULT_AXI_PATH; + clk_update.axi_vote.axi_path[0].transac_type = + CAM_IPE_DEFAULT_AXI_TRANSAC; + } + + clk_info->compressed_bw -= ctx_data->clk_info.compressed_bw; + clk_info->uncompressed_bw -= ctx_data->clk_info.uncompressed_bw; + + ctx_data->clk_info.uncompressed_bw = 0; + ctx_data->clk_info.compressed_bw = 0; + ctx_data->clk_info.curr_fc = 0; + ctx_data->clk_info.base_clk = 0; + + clk_update.axi_vote.num_paths = 1; + clk_update.axi_vote.axi_path[0].camnoc_bw = + clk_info->uncompressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].mnoc_ab_bw = + clk_info->compressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].mnoc_ib_bw = + clk_info->compressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].ddr_ab_bw = + clk_info->compressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].ddr_ib_bw = + clk_info->compressed_bw / device_share_ratio; + } else { + int path_index; + + /* + * Remove previous vote of this context from hw mgr first. + * hw_mgr_clk_info has all valid paths, with each path in its + * own index. BW that we wanted to vote now is after removing + * current context's vote from hw mgr consolidated vote + */ + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + if (ctx_data->icp_dev_acquire_info->dev_type == + CAM_ICP_RES_TYPE_BPS) { + /* + * By assuming BPS has Read-All, Write-All + * votes only. + */ + path_index = + ctx_data->clk_info.axi_path[i] + .transac_type - + CAM_AXI_TRANSACTION_READ; + } else { + path_index = + ctx_data->clk_info.axi_path[i] + .path_data_type - + CAM_AXI_PATH_DATA_IPE_START_OFFSET; + } + + if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_ICP, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i] + .path_data_type, + CAM_AXI_PATH_DATA_IPE_START_OFFSET, + CAM_ICP_MAX_PER_PATH_VOTES); + continue; + } + + clk_info->axi_path[path_index].camnoc_bw -= + ctx_data->clk_info.axi_path[i].camnoc_bw; + clk_info->axi_path[path_index].mnoc_ab_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + clk_info->axi_path[path_index].mnoc_ib_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + clk_info->axi_path[path_index].ddr_ab_bw -= + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + clk_info->axi_path[path_index].ddr_ib_bw -= + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + } + + memset(&ctx_data->clk_info.axi_path[0], 0, + CAM_ICP_MAX_PER_PATH_VOTES * + sizeof(struct cam_axi_per_path_bw_vote)); + ctx_data->clk_info.curr_fc = 0; + ctx_data->clk_info.base_clk = 0; + + clk_update.axi_vote.num_paths = clk_info->num_paths; + memcpy(&clk_update.axi_vote.axi_path[0], + &clk_info->axi_path[0], + clk_update.axi_vote.num_paths * + sizeof(struct cam_axi_per_path_bw_vote)); + + if (device_share_ratio > 1) { + for (i = 0; i < clk_update.axi_vote.num_paths; i++) { + clk_update.axi_vote.axi_path[i].camnoc_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].mnoc_ab_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].mnoc_ib_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].ddr_ab_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].ddr_ib_bw /= + device_share_ratio; + } + } + } + + clk_update.axi_vote_valid = true; + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + &clk_update, sizeof(clk_update)); + + /* + * Vote half bandwidth each on both devices. + * Total bw at mnoc - CPAS will take care of adding up. + * camnoc clk calculate is more accurate this way. + */ + if ((ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) + ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id, + &clk_update, sizeof(clk_update)); + + CAM_DBG(CAM_ICP, "X :ctx_id = %d curr_fc = %u bc = %u", + ctx_data->ctx_id, ctx_data->clk_info.curr_fc, + ctx_data->clk_info.base_clk); + mutex_unlock(&ctx_data->ctx_mutex); + + return 0; +} + +static void cam_icp_ctx_timer_cb(struct timer_list *timer_data) +{ + unsigned long flags; + struct crm_workq_task *task; + struct clk_work_data *task_data; + struct cam_req_mgr_timer *timer = + container_of(timer_data, struct cam_req_mgr_timer, sys_timer); + + spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task(icp_hw_mgr.timer_work); + if (!task) { + CAM_ERR(CAM_ICP, "no empty task"); + spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags); + return; + } + + task_data = (struct clk_work_data *)task->payload; + task_data->data = timer->parent; + task_data->type = ICP_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_icp_ctx_timer; + cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags); +} + +static void cam_icp_device_timer_cb(struct timer_list *timer_data) +{ + unsigned long flags; + struct crm_workq_task *task; + struct clk_work_data *task_data; + struct cam_req_mgr_timer *timer = + container_of(timer_data, struct cam_req_mgr_timer, sys_timer); + + spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task(icp_hw_mgr.timer_work); + if (!task) { + CAM_ERR(CAM_ICP, "no empty task"); + spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags); + return; + } + + task_data = (struct clk_work_data *)task->payload; + task_data->data = timer->parent; + task_data->type = ICP_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_icp_deinit_idle_clk; + cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags); +} + +static int cam_icp_clk_info_init(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) +{ + int i, j; + + for (i = 0; i < ICP_CLK_HW_MAX; i++) { + hw_mgr->clk_info[i].base_clk = ICP_CLK_SVS_HZ; + hw_mgr->clk_info[i].curr_clk = ICP_CLK_SVS_HZ; + hw_mgr->clk_info[i].threshold = ICP_OVER_CLK_THRESHOLD; + hw_mgr->clk_info[i].over_clked = 0; + hw_mgr->clk_info[i].uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW; + hw_mgr->clk_info[i].compressed_bw = CAM_CPAS_DEFAULT_AXI_BW; + for (j = 0; j < CAM_ICP_MAX_PER_PATH_VOTES; j++) { + hw_mgr->clk_info[i].axi_path[j].path_data_type = 0; + hw_mgr->clk_info[i].axi_path[j].transac_type = 0; + hw_mgr->clk_info[i].axi_path[j].camnoc_bw = 0; + hw_mgr->clk_info[i].axi_path[j].mnoc_ab_bw = 0; + hw_mgr->clk_info[i].axi_path[j].mnoc_ib_bw = 0; + } + + hw_mgr->clk_info[i].hw_type = i; + hw_mgr->clk_info[i].watch_dog_reset_counter = 0; + } + + hw_mgr->icp_default_clk = ICP_CLK_SVS_HZ; + + return 0; +} + +static int cam_icp_ctx_timer_start(struct cam_icp_hw_ctx_data *ctx_data) +{ + int rc = 0; + + rc = crm_timer_init(&ctx_data->watch_dog, + 200, ctx_data, &cam_icp_ctx_timer_cb); + if (rc) + CAM_ERR(CAM_ICP, "Failed to start timer"); + + ctx_data->watch_dog_reset_counter = 0; + + CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + return rc; +} + +static int cam_icp_device_timer_start(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; + int i; + + for (i = 0; i < ICP_CLK_HW_MAX; i++) { + if (!hw_mgr->clk_info[i].watch_dog) { + rc = crm_timer_init(&hw_mgr->clk_info[i].watch_dog, + ICP_DEVICE_IDLE_TIMEOUT, &hw_mgr->clk_info[i], + &cam_icp_device_timer_cb); + + if (rc) + CAM_ERR(CAM_ICP, "Failed to start timer %d", i); + + hw_mgr->clk_info[i].watch_dog_reset_counter = 0; + } + } + + return rc; +} + +static int cam_icp_ctx_timer_stop(struct cam_icp_hw_ctx_data *ctx_data) +{ + if (ctx_data->watch_dog) { + CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + ctx_data->watch_dog_reset_counter = 0; + crm_timer_exit(&ctx_data->watch_dog); + ctx_data->watch_dog = NULL; + } + + return 0; +} + +static void cam_icp_device_timer_stop(struct cam_icp_hw_mgr *hw_mgr) +{ + if (!hw_mgr->bps_ctxt_cnt && + hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog) { + hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog_reset_counter = 0; + crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog); + hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog = NULL; + } + + if (!hw_mgr->ipe_ctxt_cnt && + hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog) { + hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog_reset_counter = 0; + crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog); + hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog = NULL; + } +} + +static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles, + uint64_t budget) +{ + uint64_t base_clk; + uint64_t mul = 1000000000; + + base_clk = (frame_cycles * mul) / budget; + + CAM_DBG(CAM_ICP, "budget = %lld fc = %d ib = %lld base_clk = %lld", + budget, frame_cycles, + (long long)(frame_cycles * mul), base_clk); + + return base_clk; +} + +static bool cam_icp_busy_prev_reqs(struct hfi_frame_process_info *frm_process, + uint64_t req_id) +{ + int i; + int cnt; + + for (i = 0, cnt = 0; i < CAM_FRAME_CMD_MAX; i++) { + if (frm_process->request_id[i]) { + if (frm_process->fw_process_flag[i]) { + CAM_DBG(CAM_ICP, "r id = %lld busy = %d", + frm_process->request_id[i], + frm_process->fw_process_flag[i]); + cnt++; + } + } + } + if (cnt > 1) + return true; + + return false; +} + +static int cam_icp_calc_total_clk(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_clk_info *hw_mgr_clk_info, uint32_t dev_type) +{ + int i; + struct cam_icp_hw_ctx_data *ctx_data; + + hw_mgr_clk_info->base_clk = 0; + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { + ctx_data = &hw_mgr->ctx_data[i]; + if (ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED && + ICP_DEV_TYPE_TO_CLK_TYPE( + ctx_data->icp_dev_acquire_info->dev_type) == + ICP_DEV_TYPE_TO_CLK_TYPE(dev_type)) + hw_mgr_clk_info->base_clk += + ctx_data->clk_info.base_clk; + } + + return 0; +} + +static bool cam_icp_update_clk_busy(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_icp_clk_info *hw_mgr_clk_info, + struct cam_icp_clk_bw_request *clk_info, + uint32_t base_clk) +{ + uint32_t next_clk_level; + uint32_t actual_clk; + bool rc = false; + + /* 1. if current request frame cycles(fc) are more than previous + * frame fc + * Calculate the new base clock. + * if sum of base clocks are more than next available clk level + * Update clock rate, change curr_clk_rate to sum of base clock + * rates and make over_clked to zero + * else + * Update clock rate to next level, update curr_clk_rate and make + * overclked cnt to zero + * 2. if current fc is less than or equal to previous frame fc + * Still Bump up the clock to next available level + * if it is available, then update clock, make overclk cnt to + * zero. If the clock is already at highest clock rate then + * no need to update the clock + */ + ctx_data->clk_info.base_clk = base_clk; + hw_mgr_clk_info->over_clked = 0; + if (clk_info->frame_cycles > ctx_data->clk_info.curr_fc) { + cam_icp_calc_total_clk(hw_mgr, hw_mgr_clk_info, + ctx_data->icp_dev_acquire_info->dev_type); + actual_clk = cam_icp_get_actual_clk_rate(hw_mgr, + ctx_data, base_clk); + if (hw_mgr_clk_info->base_clk > actual_clk) { + hw_mgr_clk_info->curr_clk = hw_mgr_clk_info->base_clk; + } else { + next_clk_level = cam_icp_get_next_clk_rate(hw_mgr, + ctx_data, hw_mgr_clk_info->curr_clk); + hw_mgr_clk_info->curr_clk = next_clk_level; + } + rc = true; + } else { + next_clk_level = + cam_icp_get_next_clk_rate(hw_mgr, ctx_data, + hw_mgr_clk_info->curr_clk); + if (hw_mgr_clk_info->curr_clk < next_clk_level) { + hw_mgr_clk_info->curr_clk = next_clk_level; + rc = true; + } + } + ctx_data->clk_info.curr_fc = clk_info->frame_cycles; + + return rc; +} + +static bool cam_icp_update_clk_overclk_free(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_icp_clk_info *hw_mgr_clk_info, + struct cam_icp_clk_bw_request *clk_info, + uint32_t base_clk) +{ + int rc = false; + + /* + * In caseof no pending packets case + * 1. In caseof overclk cnt is less than threshold, increase + * overclk count and no update in the clock rate + * 2. In caseof overclk cnt is greater than or equal to threshold + * then lower clock rate by one level and update hw_mgr current + * clock value. + * a. In case of new clock rate greater than sum of clock + * rates, reset overclk count value to zero if it is + * overclock + * b. if it is less than sum of base clocks then go to next + * level of clock and make overclk count to zero + * c. if it is same as sum of base clock rates update overclock + * cnt to 0 + */ + if (hw_mgr_clk_info->over_clked < hw_mgr_clk_info->threshold) { + hw_mgr_clk_info->over_clked++; + rc = false; + } else { + hw_mgr_clk_info->curr_clk = + cam_icp_get_lower_clk_rate(hw_mgr, ctx_data, + hw_mgr_clk_info->curr_clk); + if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk) { + if (cam_icp_is_over_clk(hw_mgr, ctx_data, + hw_mgr_clk_info)) + hw_mgr_clk_info->over_clked = 0; + } else if (hw_mgr_clk_info->curr_clk < + hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->curr_clk = + cam_icp_get_next_clk_rate(hw_mgr, ctx_data, + hw_mgr_clk_info->curr_clk); + hw_mgr_clk_info->over_clked = 0; + } else if (hw_mgr_clk_info->curr_clk == + hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->over_clked = 0; + } + rc = true; + } + + return rc; +} + +static bool cam_icp_update_clk_free(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_icp_clk_info *hw_mgr_clk_info, + struct cam_icp_clk_bw_request *clk_info, + uint32_t base_clk) +{ + int rc = false; + bool over_clocked = false; + + ctx_data->clk_info.curr_fc = clk_info->frame_cycles; + ctx_data->clk_info.base_clk = base_clk; + cam_icp_calc_total_clk(hw_mgr, hw_mgr_clk_info, + ctx_data->icp_dev_acquire_info->dev_type); + + /* + * Current clock is not always sum of base clocks, due to + * clock scales update to next higher or lower levels, it + * equals to one of discrete clock values supported by hardware. + * So even current clock is higher than sum of base clocks, we + * can not consider it is over clocked. if it is greater than + * discrete clock level then only it is considered as over clock. + * 1. Handle over clock case + * 2. If current clock is less than sum of base clocks + * update current clock + * 3. If current clock is same as sum of base clocks no action + */ + + over_clocked = cam_icp_is_over_clk(hw_mgr, ctx_data, + hw_mgr_clk_info); + + if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk && + over_clocked) { + rc = cam_icp_update_clk_overclk_free(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, base_clk); + } else if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->over_clked = 0; + rc = false; + } else if (hw_mgr_clk_info->curr_clk < hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->curr_clk = cam_icp_get_actual_clk_rate(hw_mgr, + ctx_data, hw_mgr_clk_info->base_clk); + rc = true; + } + + return rc; +} + +static bool cam_icp_debug_clk_update(struct cam_icp_clk_info *hw_mgr_clk_info) +{ + if (icp_hw_mgr.icp_debug_clk < ICP_CLK_TURBO_HZ && + icp_hw_mgr.icp_debug_clk && + icp_hw_mgr.icp_debug_clk != hw_mgr_clk_info->curr_clk) { + hw_mgr_clk_info->base_clk = icp_hw_mgr.icp_debug_clk; + hw_mgr_clk_info->curr_clk = icp_hw_mgr.icp_debug_clk; + hw_mgr_clk_info->uncompressed_bw = icp_hw_mgr.icp_debug_clk; + hw_mgr_clk_info->compressed_bw = icp_hw_mgr.icp_debug_clk; + CAM_DBG(CAM_ICP, "bc = %d cc = %d", + hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk); + return true; + } + + return false; +} + +static bool cam_icp_default_clk_update(struct cam_icp_clk_info *hw_mgr_clk_info) +{ + if (icp_hw_mgr.icp_default_clk != hw_mgr_clk_info->curr_clk) { + hw_mgr_clk_info->base_clk = icp_hw_mgr.icp_default_clk; + hw_mgr_clk_info->curr_clk = icp_hw_mgr.icp_default_clk; + hw_mgr_clk_info->uncompressed_bw = icp_hw_mgr.icp_default_clk; + hw_mgr_clk_info->compressed_bw = icp_hw_mgr.icp_default_clk; + CAM_DBG(CAM_ICP, "bc = %d cc = %d", + hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk); + return true; + } + + return false; +} + +static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_icp_clk_info *hw_mgr_clk_info, + struct cam_icp_clk_bw_req_internal_v2 *clk_info, + bool busy) +{ + int i, path_index; + bool update_required = true; + + /* + * If current request bandwidth is different from previous frames, then + * recalculate bandwidth of all contexts of same hardware and update + * voting of bandwidth + */ + + for (i = 0; i < clk_info->num_paths; i++) + CAM_DBG(CAM_ICP, "clk_info camnoc = %lld busy = %d", + clk_info->axi_path[i].camnoc_bw, busy); + + if (clk_info->num_paths == ctx_data->clk_info.num_paths) { + update_required = false; + for (i = 0; i < clk_info->num_paths; i++) { + if ((clk_info->axi_path[i].transac_type == + ctx_data->clk_info.axi_path[i].transac_type) && + (clk_info->axi_path[i].path_data_type == + ctx_data->clk_info.axi_path[i].path_data_type) && + (clk_info->axi_path[i].camnoc_bw == + ctx_data->clk_info.axi_path[i].camnoc_bw) && + (clk_info->axi_path[i].mnoc_ab_bw == + ctx_data->clk_info.axi_path[i].mnoc_ab_bw)) { + continue; + } else { + update_required = true; + break; + } + } + } + + if (!update_required) { + CAM_DBG(CAM_ICP, + "Incoming BW hasn't changed, no update required"); + return false; + } + + if (busy) { + for (i = 0; i < clk_info->num_paths; i++) { + if (ctx_data->clk_info.axi_path[i].camnoc_bw > + clk_info->axi_path[i].camnoc_bw) + return false; + } + } + + /* + * Remove previous vote of this context from hw mgr first. + * hw_mgr_clk_info has all valid paths, with each path in its own index + */ + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + if (ctx_data->icp_dev_acquire_info->dev_type == + CAM_ICP_RES_TYPE_BPS) { + /* By assuming BPS has Read-All, Write-All votes only */ + path_index = + ctx_data->clk_info.axi_path[i].transac_type - + CAM_AXI_TRANSACTION_READ; + } else { + path_index = + ctx_data->clk_info.axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_IPE_START_OFFSET; + } + + if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_ICP, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_IPE_START_OFFSET, + CAM_ICP_MAX_PER_PATH_VOTES); + continue; + } + + hw_mgr_clk_info->axi_path[path_index].camnoc_bw -= + ctx_data->clk_info.axi_path[i].camnoc_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ib_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ab_bw -= + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ib_bw -= + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + } + + ctx_data->clk_info.num_paths = clk_info->num_paths; + + memcpy(&ctx_data->clk_info.axi_path[0], + &clk_info->axi_path[0], + clk_info->num_paths * sizeof(struct cam_axi_per_path_bw_vote)); + + /* + * Add new vote of this context in hw mgr. + * hw_mgr_clk_info has all paths, with each path in its own index + */ + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + if (ctx_data->icp_dev_acquire_info->dev_type == + CAM_ICP_RES_TYPE_BPS) { + /* By assuming BPS has Read-All, Write-All votes only */ + path_index = + ctx_data->clk_info.axi_path[i].transac_type - + CAM_AXI_TRANSACTION_READ; + } else { + path_index = + ctx_data->clk_info.axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_IPE_START_OFFSET; + } + + if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_ICP, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_IPE_START_OFFSET, + CAM_ICP_MAX_PER_PATH_VOTES); + continue; + } + + hw_mgr_clk_info->axi_path[path_index].path_data_type = + ctx_data->clk_info.axi_path[i].path_data_type; + hw_mgr_clk_info->axi_path[path_index].transac_type = + ctx_data->clk_info.axi_path[i].transac_type; + hw_mgr_clk_info->axi_path[path_index].camnoc_bw += + ctx_data->clk_info.axi_path[i].camnoc_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw += + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ib_bw += + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ab_bw += + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ib_bw += + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + + CAM_DBG(CAM_ICP, + "Consolidate Path Vote : Dev[%s] i[%d] path_idx[%d] : [%s %s] [%lld %lld]", + cam_icp_dev_type_to_name( + ctx_data->icp_dev_acquire_info->dev_type), + i, path_index, + cam_cpas_axi_util_trans_type_to_string( + hw_mgr_clk_info->axi_path[path_index].transac_type), + cam_cpas_axi_util_path_type_to_string( + hw_mgr_clk_info->axi_path[path_index].path_data_type), + hw_mgr_clk_info->axi_path[path_index].camnoc_bw, + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw); + } + + if (hw_mgr_clk_info->num_paths < ctx_data->clk_info.num_paths) + hw_mgr_clk_info->num_paths = ctx_data->clk_info.num_paths; + + return true; +} + +static bool cam_icp_update_bw(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_icp_clk_info *hw_mgr_clk_info, + struct cam_icp_clk_bw_request *clk_info, + bool busy) +{ + int i; + struct cam_icp_hw_ctx_data *ctx; + + /* + * If current request bandwidth is different from previous frames, then + * recalculate bandwidth of all contexts of same hardware and update + * voting of bandwidth + */ + CAM_DBG(CAM_ICP, "ubw ctx = %lld clk_info ubw = %lld busy = %d", + ctx_data->clk_info.uncompressed_bw, + clk_info->uncompressed_bw, busy); + + if ((clk_info->uncompressed_bw == ctx_data->clk_info.uncompressed_bw) && + (ctx_data->clk_info.uncompressed_bw == + hw_mgr_clk_info->uncompressed_bw)) { + CAM_DBG(CAM_ICP, "Update not required bw=%lld", + ctx_data->clk_info.uncompressed_bw); + return false; + } + + if (busy && + (ctx_data->clk_info.uncompressed_bw > + clk_info->uncompressed_bw)) { + CAM_DBG(CAM_ICP, "Busy, Update not req existing=%lld, new=%lld", + ctx_data->clk_info.uncompressed_bw, + clk_info->uncompressed_bw); + return false; + } + + ctx_data->clk_info.uncompressed_bw = clk_info->uncompressed_bw; + ctx_data->clk_info.compressed_bw = clk_info->compressed_bw; + hw_mgr_clk_info->uncompressed_bw = 0; + hw_mgr_clk_info->compressed_bw = 0; + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { + ctx = &hw_mgr->ctx_data[i]; + if (ctx->state == CAM_ICP_CTX_STATE_ACQUIRED && + ICP_DEV_TYPE_TO_CLK_TYPE( + ctx->icp_dev_acquire_info->dev_type) == + ICP_DEV_TYPE_TO_CLK_TYPE( + ctx_data->icp_dev_acquire_info->dev_type)) { + hw_mgr_clk_info->uncompressed_bw += + ctx->clk_info.uncompressed_bw; + hw_mgr_clk_info->compressed_bw += + ctx->clk_info.compressed_bw; + CAM_DBG(CAM_ICP, + "Current context=[%lld %lld] Total=[%lld %lld]", + ctx->clk_info.uncompressed_bw, + ctx->clk_info.compressed_bw, + hw_mgr_clk_info->uncompressed_bw, + hw_mgr_clk_info->compressed_bw); + } + } + + return true; +} + +static bool cam_icp_check_clk_update(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, int idx) +{ + bool busy, rc = false; + uint32_t base_clk; + struct cam_icp_clk_bw_request *clk_info; + struct hfi_frame_process_info *frame_info; + uint64_t req_id; + struct cam_icp_clk_info *hw_mgr_clk_info; + + cam_icp_ctx_timer_reset(ctx_data); + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { + cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_BPS); + hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; + CAM_DBG(CAM_ICP, "Reset bps timer"); + } else { + cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_IPE); + hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; + CAM_DBG(CAM_ICP, "Reset ipe timer"); + } + + if (icp_hw_mgr.icp_debug_clk) + return cam_icp_debug_clk_update(hw_mgr_clk_info); + + /* Check is there any pending frames in this context */ + frame_info = &ctx_data->hfi_frame_process; + req_id = frame_info->request_id[idx]; + busy = cam_icp_busy_prev_reqs(frame_info, req_id); + CAM_DBG(CAM_ICP, "busy = %d req_id = %lld", busy, req_id); + + clk_info = &ctx_data->hfi_frame_process.clk_info[idx]; + if (!clk_info->frame_cycles) + return cam_icp_default_clk_update(hw_mgr_clk_info); + + /* Calculate base clk rate */ + base_clk = cam_icp_mgr_calc_base_clk( + clk_info->frame_cycles, clk_info->budget_ns); + ctx_data->clk_info.rt_flag = clk_info->rt_flag; + + if (busy) + rc = cam_icp_update_clk_busy(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, base_clk); + else + rc = cam_icp_update_clk_free(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, base_clk); + + CAM_DBG(CAM_ICP, "bc = %d cc = %d busy = %d overclk = %d uc = %d", + hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk, + busy, hw_mgr_clk_info->over_clked, rc); + + return rc; +} + +static bool cam_icp_check_bw_update(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, int idx) +{ + bool busy, bw_updated = false; + int i; + struct cam_icp_clk_bw_request *clk_info; + struct cam_icp_clk_bw_req_internal_v2 *clk_info_v2; + struct cam_icp_clk_info *hw_mgr_clk_info; + struct hfi_frame_process_info *frame_info; + uint64_t req_id; + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; + else + hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; + + frame_info = &ctx_data->hfi_frame_process; + req_id = frame_info->request_id[idx]; + busy = cam_icp_busy_prev_reqs(frame_info, req_id); + + if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) { + clk_info = &ctx_data->hfi_frame_process.clk_info[idx]; + + CAM_DBG(CAM_ICP, + "Ctx[%pK][%d] Req[%lld] Current camno=%lld, mnoc=%lld", + ctx_data, ctx_data->ctx_id, req_id, + hw_mgr_clk_info->uncompressed_bw, + hw_mgr_clk_info->compressed_bw); + + bw_updated = cam_icp_update_bw(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, busy); + } else if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V2) { + clk_info_v2 = &ctx_data->hfi_frame_process.clk_info_v2[idx]; + + bw_updated = cam_icp_update_bw_v2(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info_v2, busy); + + for (i = 0; i < hw_mgr_clk_info->num_paths; i++) { + CAM_DBG(CAM_ICP, + "Final path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s", + cam_cpas_axi_util_path_type_to_string( + hw_mgr_clk_info->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + hw_mgr_clk_info->axi_path[i].transac_type), + hw_mgr_clk_info->axi_path[i].camnoc_bw, + hw_mgr_clk_info->axi_path[i].mnoc_ab_bw, + hw_mgr_clk_info->axi_path[i].mnoc_ib_bw, + cam_icp_dev_type_to_name( + ctx_data->icp_dev_acquire_info->dev_type)); + } + } else { + CAM_ERR(CAM_ICP, "Invalid bw config version: %d", + ctx_data->bw_config_version); + return false; + } + + return bw_updated; +} + +static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) +{ + uint32_t id; + uint32_t curr_clk_rate; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + struct cam_hw_intf *dev_intf = NULL; + struct cam_a5_clk_update_cmd clk_upd_cmd; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk"); + return -EINVAL; + } + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { + dev_intf = bps_dev_intf; + curr_clk_rate = hw_mgr->clk_info[ICP_CLK_HW_BPS].curr_clk; + id = CAM_ICP_BPS_CMD_UPDATE_CLK; + } else { + dev_intf = ipe0_dev_intf; + curr_clk_rate = hw_mgr->clk_info[ICP_CLK_HW_IPE].curr_clk; + id = CAM_ICP_IPE_CMD_UPDATE_CLK; + } + + CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d", curr_clk_rate, + ctx_data->icp_dev_acquire_info->dev_type); + clk_upd_cmd.curr_clk_rate = curr_clk_rate; + clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; + + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + &clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd)); + + if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS) + if (ipe1_dev_intf) + ipe1_dev_intf->hw_ops.process_cmd( + ipe1_dev_intf->hw_priv, id, + &clk_upd_cmd, + sizeof(struct cam_a5_clk_update_cmd)); + + return 0; +} + +static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) +{ + uint32_t id; + int i = 0; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + struct cam_hw_intf *dev_intf = NULL; + struct cam_icp_clk_info *clk_info; + struct cam_icp_cpas_vote clk_update = {{0}, {0}, 0, 0}; + int device_share_ratio = 1; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk"); + return -EINVAL; + } + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { + dev_intf = bps_dev_intf; + clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; + id = CAM_ICP_BPS_CMD_VOTE_CPAS; + } else { + dev_intf = ipe0_dev_intf; + clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; + id = CAM_ICP_IPE_CMD_VOTE_CPAS; + } + + /* + * Since there are 2 devices, we assume the load is evenly shared + * between HWs and corresponding AXI paths. So divide total bw by half + * to vote on each device + */ + if ((ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) + device_share_ratio = 2; + + clk_update.ahb_vote.type = CAM_VOTE_DYNAMIC; + clk_update.ahb_vote.vote.freq = 0; + clk_update.ahb_vote_valid = false; + + if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) { + clk_update.axi_vote.num_paths = 1; + if (ctx_data->icp_dev_acquire_info->dev_type == + CAM_ICP_RES_TYPE_BPS) { + clk_update.axi_vote.axi_path[0].path_data_type = + CAM_BPS_DEFAULT_AXI_PATH; + clk_update.axi_vote.axi_path[0].transac_type = + CAM_BPS_DEFAULT_AXI_TRANSAC; + } else { + clk_update.axi_vote.axi_path[0].path_data_type = + CAM_IPE_DEFAULT_AXI_PATH; + clk_update.axi_vote.axi_path[0].transac_type = + CAM_IPE_DEFAULT_AXI_TRANSAC; + } + clk_update.axi_vote.axi_path[0].camnoc_bw = + clk_info->uncompressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].mnoc_ab_bw = + clk_info->compressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].mnoc_ib_bw = + clk_info->compressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].ddr_ab_bw = + clk_info->compressed_bw / device_share_ratio; + clk_update.axi_vote.axi_path[0].ddr_ib_bw = + clk_info->compressed_bw / device_share_ratio; + } else { + clk_update.axi_vote.num_paths = clk_info->num_paths; + memcpy(&clk_update.axi_vote.axi_path[0], + &clk_info->axi_path[0], + clk_update.axi_vote.num_paths * + sizeof(struct cam_axi_per_path_bw_vote)); + + if (device_share_ratio > 1) { + for (i = 0; i < clk_update.axi_vote.num_paths; i++) { + clk_update.axi_vote.axi_path[i].camnoc_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].mnoc_ab_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].mnoc_ib_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].ddr_ab_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].ddr_ib_bw /= + device_share_ratio; + } + } + } + + clk_update.axi_vote_valid = true; + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + &clk_update, sizeof(clk_update)); + + /* + * Vote half bandwidth each on both devices. + * Total bw at mnoc - CPAS will take care of adding up. + * camnoc clk calculate is more accurate this way. + */ + if ((ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) + ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id, + &clk_update, sizeof(clk_update)); + + return 0; +} + +static int cam_icp_mgr_ipe_bps_clk_update(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, int idx) +{ + int rc = 0; + + if (cam_icp_check_clk_update(hw_mgr, ctx_data, idx)) + rc = cam_icp_update_clk_rate(hw_mgr, ctx_data); + + if (cam_icp_check_bw_update(hw_mgr, ctx_data, idx)) + rc |= cam_icp_update_cpas_vote(hw_mgr, ctx_data); + + return rc; +} + +static int cam_icp_mgr_ipe_bps_resume(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) +{ + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + uint32_t core_info_mask = 0; + int rc = 0; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close"); + return -EINVAL; + } + + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { + if (hw_mgr->bps_ctxt_cnt++) + goto end; + if (!hw_mgr->bps_clk_state) { + bps_dev_intf->hw_ops.init( + bps_dev_intf->hw_priv, NULL, 0); + hw_mgr->bps_clk_state = true; + } + if (icp_hw_mgr.ipe_bps_pc_flag) { + bps_dev_intf->hw_ops.process_cmd( + bps_dev_intf->hw_priv, + CAM_ICP_BPS_CMD_POWER_RESUME, NULL, 0); + } + core_info_mask = ICP_PWR_CLP_BPS; + } else { + if (hw_mgr->ipe_ctxt_cnt++) + goto end; + if (!hw_mgr->ipe_clk_state) + ipe0_dev_intf->hw_ops.init( + ipe0_dev_intf->hw_priv, NULL, 0); + if (icp_hw_mgr.ipe_bps_pc_flag) { + ipe0_dev_intf->hw_ops.process_cmd( + ipe0_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_POWER_RESUME, NULL, 0); + } + + if ((icp_hw_mgr.ipe1_enable) && + (ipe1_dev_intf) && + (!hw_mgr->ipe_clk_state)) { + ipe1_dev_intf->hw_ops.init(ipe1_dev_intf->hw_priv, + NULL, 0); + + if (icp_hw_mgr.ipe_bps_pc_flag) { + ipe1_dev_intf->hw_ops.process_cmd( + ipe1_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_POWER_RESUME, + NULL, 0); + } + } + hw_mgr->ipe_clk_state = true; + + if ((icp_hw_mgr.ipe1_enable) && + (ipe1_dev_intf)) + core_info_mask = (ICP_PWR_CLP_IPE0 | + ICP_PWR_CLP_IPE1); + else + core_info_mask = ICP_PWR_CLP_IPE0; + } + + CAM_DBG(CAM_ICP, "core_info %X", core_info_mask); + if (icp_hw_mgr.ipe_bps_pc_flag) + rc = hfi_enable_ipe_bps_pc(true, core_info_mask); + else + rc = hfi_enable_ipe_bps_pc(false, core_info_mask); +end: + return rc; +} + +static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, int dev_type) +{ + int rc = 0, dev; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close"); + return -EINVAL; + } + + if (!ctx_data) + dev = dev_type; + else + dev = ctx_data->icp_dev_acquire_info->dev_type; + + if (dev == CAM_ICP_RES_TYPE_BPS) { + CAM_DBG(CAM_ICP, "bps ctx cnt %d", hw_mgr->bps_ctxt_cnt); + if (ctx_data) + --hw_mgr->bps_ctxt_cnt; + + if (hw_mgr->bps_ctxt_cnt) + goto end; + + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { + rc = bps_dev_intf->hw_ops.process_cmd( + bps_dev_intf->hw_priv, + CAM_ICP_BPS_CMD_POWER_COLLAPSE, + NULL, 0); + } + + if (hw_mgr->bps_clk_state) { + bps_dev_intf->hw_ops.deinit + (bps_dev_intf->hw_priv, NULL, 0); + hw_mgr->bps_clk_state = false; + } + } else { + CAM_DBG(CAM_ICP, "ipe ctx cnt %d", hw_mgr->ipe_ctxt_cnt); + if (ctx_data) + --hw_mgr->ipe_ctxt_cnt; + + if (hw_mgr->ipe_ctxt_cnt) + goto end; + + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { + rc = ipe0_dev_intf->hw_ops.process_cmd( + ipe0_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0); + } + + if (hw_mgr->ipe_clk_state) + ipe0_dev_intf->hw_ops.deinit( + ipe0_dev_intf->hw_priv, NULL, 0); + + if (ipe1_dev_intf) { + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { + rc = ipe1_dev_intf->hw_ops.process_cmd( + ipe1_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_POWER_COLLAPSE, + NULL, 0); + } + + if (hw_mgr->ipe_clk_state) + ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv, + NULL, 0); + } + + hw_mgr->ipe_clk_state = false; + } + +end: + return rc; +} + +static int cam_icp_mgr_ipe_bps_get_gdsc_control( + struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong"); + return -EINVAL; + } + + if (icp_hw_mgr.ipe_bps_pc_flag) { + rc = bps_dev_intf->hw_ops.process_cmd( + bps_dev_intf->hw_priv, + CAM_ICP_BPS_CMD_POWER_COLLAPSE, + NULL, 0); + + rc = ipe0_dev_intf->hw_ops.process_cmd( + ipe0_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0); + + if (ipe1_dev_intf) { + rc = ipe1_dev_intf->hw_ops.process_cmd( + ipe1_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_POWER_COLLAPSE, + NULL, 0); + } + } + + return rc; +} + +static int cam_icp_set_dbg_default_clk(void *data, u64 val) +{ + icp_hw_mgr.icp_debug_clk = val; + return 0; +} + +static int cam_icp_get_dbg_default_clk(void *data, u64 *val) +{ + *val = icp_hw_mgr.icp_debug_clk; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_default_clk, + cam_icp_get_dbg_default_clk, + cam_icp_set_dbg_default_clk, "%16llu"); + +static int cam_icp_set_a5_dbg_lvl(void *data, u64 val) +{ + icp_hw_mgr.a5_dbg_lvl = val; + return 0; +} + +static int cam_icp_get_a5_dbg_lvl(void *data, u64 *val) +{ + *val = icp_hw_mgr.a5_dbg_lvl; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fs, cam_icp_get_a5_dbg_lvl, + cam_icp_set_a5_dbg_lvl, "%08llu"); + +static int cam_icp_set_a5_dbg_type(void *data, u64 val) +{ + if (val <= NUM_HFI_DEBUG_MODE) + icp_hw_mgr.a5_debug_type = val; + return 0; +} + +static int cam_icp_get_a5_dbg_type(void *data, u64 *val) +{ + *val = icp_hw_mgr.a5_debug_type; + return 0; +} + + +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_type_fs, cam_icp_get_a5_dbg_type, + cam_icp_set_a5_dbg_type, "%08llu"); + +static int cam_icp_set_a5_fw_dump_lvl(void *data, u64 val) +{ + if (val < NUM_HFI_DUMP_LVL) + icp_hw_mgr.a5_fw_dump_lvl = val; + return 0; +} + +static int cam_icp_get_a5_fw_dump_lvl(void *data, u64 *val) +{ + *val = icp_hw_mgr.a5_fw_dump_lvl; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_a5_fw_dump_lvl, + cam_icp_set_a5_fw_dump_lvl, "%08llu"); + +static int cam_icp_hw_mgr_create_debugfs_entry(void) +{ + int rc = 0; + + icp_hw_mgr.dentry = debugfs_create_dir("camera_icp", NULL); + if (!icp_hw_mgr.dentry) + return -ENOMEM; + + if (!debugfs_create_bool("icp_pc", + 0644, + icp_hw_mgr.dentry, + &icp_hw_mgr.icp_pc_flag)) { + CAM_ERR(CAM_ICP, "failed to create icp_pc entry"); + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_bool("ipe_bps_pc", + 0644, + icp_hw_mgr.dentry, + &icp_hw_mgr.ipe_bps_pc_flag)) { + CAM_ERR(CAM_ICP, "failed to create ipe_bps_pc entry"); + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_file("icp_debug_clk", + 0644, + icp_hw_mgr.dentry, NULL, + &cam_icp_debug_default_clk)) { + CAM_ERR(CAM_ICP, "failed to create icp_debug_clk entry"); + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_bool("a5_jtag_debug", + 0644, + icp_hw_mgr.dentry, + &icp_hw_mgr.a5_jtag_debug)) { + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_file("a5_debug_type", + 0644, + icp_hw_mgr.dentry, + NULL, &cam_icp_debug_type_fs)) { + CAM_ERR(CAM_ICP, "failed to create a5_debug_type"); + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_file("a5_debug_lvl", + 0644, + icp_hw_mgr.dentry, + NULL, &cam_icp_debug_fs)) { + CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl"); + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_file("a5_fw_dump_lvl", + 0644, + icp_hw_mgr.dentry, + NULL, &cam_icp_debug_fw_dump)) { + CAM_ERR(CAM_ICP, "failed to create a5_fw_dump_lvl"); + rc = -ENOMEM; + goto err; + } + + return rc; +err: + debugfs_remove_recursive(icp_hw_mgr.dentry); + icp_hw_mgr.dentry = NULL; + return rc; +} + +static int cam_icp_mgr_process_cmd(void *priv, void *data) +{ + int rc; + struct hfi_cmd_work_data *task_data = NULL; + struct cam_icp_hw_mgr *hw_mgr; + + if (!data || !priv) { + CAM_ERR(CAM_ICP, "Invalid params%pK %pK", data, priv); + return -EINVAL; + } + + hw_mgr = priv; + task_data = (struct hfi_cmd_work_data *)data; + + rc = hfi_write_cmd(task_data->data); + + return rc; +} + +static int cam_icp_mgr_cleanup_ctx(struct cam_icp_hw_ctx_data *ctx_data) +{ + int i; + struct hfi_frame_process_info *hfi_frame_process; + struct cam_hw_done_event_data buf_data; + + hfi_frame_process = &ctx_data->hfi_frame_process; + for (i = 0; i < CAM_FRAME_CMD_MAX; i++) { + if (!hfi_frame_process->request_id[i]) + continue; + buf_data.request_id = hfi_frame_process->request_id[i]; + ctx_data->ctxt_event_cb(ctx_data->context_priv, + false, &buf_data); + hfi_frame_process->request_id[i] = 0; + if (ctx_data->hfi_frame_process.in_resource[i] > 0) { + CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", + ctx_data->hfi_frame_process.in_resource[i]); + cam_sync_destroy( + ctx_data->hfi_frame_process.in_resource[i]); + ctx_data->hfi_frame_process.in_resource[i] = 0; + } + hfi_frame_process->fw_process_flag[i] = false; + clear_bit(i, ctx_data->hfi_frame_process.bitmap); + } + + for (i = 0; i < CAM_FRAME_CMD_MAX; i++) { + if (!hfi_frame_process->in_free_resource[i]) + continue; + + CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", + ctx_data->hfi_frame_process.in_free_resource[i]); + cam_sync_destroy( + ctx_data->hfi_frame_process.in_free_resource[i]); + ctx_data->hfi_frame_process.in_free_resource[i] = 0; + } + + return 0; +} + +static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) +{ + int i; + uint32_t idx; + uint64_t request_id; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL; + struct hfi_frame_process_info *hfi_frame_process; + struct cam_hw_done_event_data buf_data; + uint32_t clk_type; + + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + request_id = ioconfig_ack->user_data2; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); + if (!ctx_data) { + CAM_ERR(CAM_ICP, "Invalid Context req %llu", request_id); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + cam_icp_ctx_timer_reset(ctx_data); + if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) { + CAM_DBG(CAM_ICP, "ctx %u is in %d state", + ctx_data->ctx_id, ctx_data->state); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + CAM_DBG(CAM_REQ, + "ctx_id : %u, request_id :%lld dev_type: %d", + ctx_data->ctx_id, request_id, + ctx_data->icp_dev_acquire_info->dev_type); + + clk_type = ICP_DEV_TYPE_TO_CLK_TYPE( + ctx_data->icp_dev_acquire_info->dev_type); + cam_icp_device_timer_reset(&icp_hw_mgr, clk_type); + + hfi_frame_process = &ctx_data->hfi_frame_process; + for (i = 0; i < CAM_FRAME_CMD_MAX; i++) + if (hfi_frame_process->request_id[i] == request_id) + break; + + if (i >= CAM_FRAME_CMD_MAX) { + CAM_ERR(CAM_ICP, "pkt not found in ctx data for req_id =%lld", + request_id); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + idx = i; + + if (flag == ICP_FRAME_PROCESS_FAILURE) + CAM_ERR(CAM_ICP, "Done with error: ctx_id %d req %llu dev %d", + ctx_data->ctx_id, request_id, + ctx_data->icp_dev_acquire_info->dev_type); + + buf_data.request_id = hfi_frame_process->request_id[idx]; + ctx_data->ctxt_event_cb(ctx_data->context_priv, flag, &buf_data); + hfi_frame_process->request_id[idx] = 0; + if (ctx_data->hfi_frame_process.in_resource[idx] > 0) { + CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", + ctx_data->hfi_frame_process.in_resource[idx]); + cam_sync_destroy(ctx_data->hfi_frame_process.in_resource[idx]); + ctx_data->hfi_frame_process.in_resource[idx] = 0; + } + clear_bit(idx, ctx_data->hfi_frame_process.bitmap); + hfi_frame_process->fw_process_flag[idx] = false; + mutex_unlock(&ctx_data->ctx_mutex); + + return 0; +} + +static int cam_icp_mgr_process_msg_frame_process(uint32_t *msg_ptr) +{ + struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL; + struct hfi_msg_frame_process_done *frame_done; + + if (!msg_ptr) { + CAM_ERR(CAM_ICP, "msg ptr is NULL"); + return -EINVAL; + } + + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + if (ioconfig_ack->err_type != HFI_ERR_SYS_NONE) { + CAM_ERR(CAM_ICP, "failed with error : %u", + ioconfig_ack->err_type); + cam_icp_mgr_handle_frame_process(msg_ptr, + ICP_FRAME_PROCESS_FAILURE); + return -EIO; + } + + frame_done = + (struct hfi_msg_frame_process_done *)ioconfig_ack->msg_data; + if (!frame_done) { + cam_icp_mgr_handle_frame_process(msg_ptr, + ICP_FRAME_PROCESS_FAILURE); + return -EINVAL; + } + + if (frame_done->result) + return cam_icp_mgr_handle_frame_process(msg_ptr, + ICP_FRAME_PROCESS_FAILURE); + else + return cam_icp_mgr_handle_frame_process(msg_ptr, + ICP_FRAME_PROCESS_SUCCESS); +} + +static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr) +{ + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL; + struct hfi_msg_ipe_config *ipe_config_ack = NULL; + struct hfi_msg_bps_common *bps_config_ack = NULL; + + if (!msg_ptr) { + CAM_ERR(CAM_ICP, "msg ptr is NULL"); + return -EINVAL; + } + + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + + if (ioconfig_ack->opcode == HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO) { + ipe_config_ack = + (struct hfi_msg_ipe_config *)(ioconfig_ack->msg_data); + if (ipe_config_ack->rc) { + CAM_ERR(CAM_ICP, "rc = %d err = %u", + ipe_config_ack->rc, ioconfig_ack->err_type); + return -EIO; + } + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); + if (!ctx_data) { + CAM_ERR(CAM_ICP, "wrong ctx data from IPE response"); + return -EINVAL; + } + ctx_data->scratch_mem_size = ipe_config_ack->scratch_mem_size; + } else { + bps_config_ack = + (struct hfi_msg_bps_common *)(ioconfig_ack->msg_data); + if (bps_config_ack->rc) { + CAM_ERR(CAM_ICP, "rc : %u, opcode :%u", + bps_config_ack->rc, ioconfig_ack->opcode); + return -EIO; + } + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); + if (!ctx_data) { + CAM_ERR(CAM_ICP, "wrong ctx data from BPS response"); + return -EINVAL; + } + } + complete(&ctx_data->wait_complete); + + return 0; +} + +static int cam_icp_mgr_process_msg_create_handle(uint32_t *msg_ptr) +{ + struct hfi_msg_create_handle_ack *create_handle_ack = NULL; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + int rc = 0; + + create_handle_ack = (struct hfi_msg_create_handle_ack *)msg_ptr; + if (!create_handle_ack) { + CAM_ERR(CAM_ICP, "Invalid create_handle_ack"); + return -EINVAL; + } + + ctx_data = + (struct cam_icp_hw_ctx_data *)(uintptr_t) + create_handle_ack->user_data1; + if (!ctx_data) { + CAM_ERR(CAM_ICP, "Invalid ctx_data"); + return -EINVAL; + } + + if (ctx_data->state == CAM_ICP_CTX_STATE_IN_USE) { + ctx_data->fw_handle = create_handle_ack->fw_handle; + CAM_DBG(CAM_ICP, "fw_handle = %x", ctx_data->fw_handle); + } else { + CAM_WARN(CAM_ICP, + "This ctx is no longer in use current state: %d", + ctx_data->state); + ctx_data->fw_handle = 0; + rc = -EPERM; + } + complete(&ctx_data->wait_complete); + return rc; +} + +static int cam_icp_mgr_process_msg_ping_ack(uint32_t *msg_ptr) +{ + struct hfi_msg_ping_ack *ping_ack = NULL; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + + ping_ack = (struct hfi_msg_ping_ack *)msg_ptr; + if (!ping_ack) { + CAM_ERR(CAM_ICP, "Empty ping ack message"); + return -EINVAL; + } + + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ping_ack->user_data); + if (!ctx_data) { + CAM_ERR(CAM_ICP, "Invalid ctx_data"); + return -EINVAL; + } + + if (ctx_data->state == CAM_ICP_CTX_STATE_IN_USE) + complete(&ctx_data->wait_complete); + + return 0; +} + +static int cam_icp_mgr_process_indirect_ack_msg(uint32_t *msg_ptr) +{ + int rc; + + if (!msg_ptr) { + CAM_ERR(CAM_ICP, "msg ptr is NULL"); + return -EINVAL; + } + + switch (msg_ptr[ICP_PACKET_OPCODE]) { + case HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO: + case HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO: + CAM_DBG(CAM_ICP, "received IPE/BPS_CONFIG_IO:"); + rc = cam_icp_mgr_process_msg_config_io(msg_ptr); + if (rc) + return rc; + break; + + case HFI_IPEBPS_CMD_OPCODE_IPE_FRAME_PROCESS: + case HFI_IPEBPS_CMD_OPCODE_BPS_FRAME_PROCESS: + rc = cam_icp_mgr_process_msg_frame_process(msg_ptr); + if (rc) + return rc; + break; + default: + CAM_ERR(CAM_ICP, "Invalid opcode : %u", + msg_ptr[ICP_PACKET_OPCODE]); + rc = -EINVAL; + break; + } + + return rc; +} + +static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr) +{ + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL; + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + int rc = 0; + + a5_dev_intf = icp_hw_mgr.a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + switch (msg_ptr[ICP_PACKET_OPCODE]) { + case HFI_IPEBPS_CMD_OPCODE_IPE_ABORT: + case HFI_IPEBPS_CMD_OPCODE_BPS_ABORT: + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); + if (ctx_data->state != CAM_ICP_CTX_STATE_FREE) + complete(&ctx_data->wait_complete); + CAM_DBG(CAM_ICP, "received IPE/BPS/ ABORT: ctx_state =%d", + ctx_data->state); + break; + case HFI_IPEBPS_CMD_OPCODE_IPE_DESTROY: + case HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY: + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); + if ((ctx_data->state == CAM_ICP_CTX_STATE_RELEASE) || + (ctx_data->state == CAM_ICP_CTX_STATE_IN_USE)) { + complete(&ctx_data->wait_complete); + } + CAM_DBG(CAM_ICP, "received IPE/BPS/ DESTROY: ctx_state =%d", + ctx_data->state); + break; + case HFI_IPEBPS_CMD_OPCODE_MEM_MAP: + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + ctx_data = + (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + if (ctx_data->state != CAM_ICP_CTX_STATE_FREE) + complete(&ctx_data->wait_complete); + CAM_DBG(CAM_ICP, + "received IPE/BPS MAP ACK:ctx_state =%d err_status =%u", + ctx_data->state, ioconfig_ack->err_type); + break; + case HFI_IPEBPS_CMD_OPCODE_MEM_UNMAP: + ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; + ctx_data = + (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + if (ctx_data->state != CAM_ICP_CTX_STATE_FREE) + complete(&ctx_data->wait_complete); + CAM_DBG(CAM_ICP, + "received IPE/BPS UNMAP ACK:ctx_state =%d err_status =%u", + ctx_data->state, ioconfig_ack->err_type); + break; + default: + CAM_ERR(CAM_ICP, "Invalid opcode : %u", + msg_ptr[ICP_PACKET_OPCODE]); + rc = -EINVAL; + break; + } + return rc; +} + +static int cam_icp_ipebps_reset(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; + struct cam_hw_intf *ipe0_dev_intf; + struct cam_hw_intf *ipe1_dev_intf; + struct cam_hw_intf *bps_dev_intf; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if (hw_mgr->bps_ctxt_cnt) { + rc = bps_dev_intf->hw_ops.process_cmd( + bps_dev_intf->hw_priv, + CAM_ICP_BPS_CMD_RESET, + NULL, 0); + if (rc) + CAM_ERR(CAM_ICP, "bps reset failed"); + } + + if (hw_mgr->ipe_ctxt_cnt) { + rc = ipe0_dev_intf->hw_ops.process_cmd( + ipe0_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_RESET, + NULL, 0); + if (rc) + CAM_ERR(CAM_ICP, "ipe0 reset failed"); + + if (ipe1_dev_intf) { + rc = ipe1_dev_intf->hw_ops.process_cmd( + ipe1_dev_intf->hw_priv, + CAM_ICP_IPE_CMD_RESET, + NULL, 0); + if (rc) + CAM_ERR(CAM_ICP, "ipe1 reset failed"); + } + } + + return 0; +} + +static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; + struct sfr_buf *sfr_buffer = NULL; + + CAM_DBG(CAM_ICP, "Enter"); + + if (atomic_read(&hw_mgr->recovery)) { + CAM_ERR(CAM_ICP, "Recovery is set"); + return rc; + } + + sfr_buffer = (struct sfr_buf *)icp_hw_mgr.hfi_mem.sfr_buf.kva; + CAM_WARN(CAM_ICP, "SFR:%s", sfr_buffer->msg); + + cam_icp_mgr_ipe_bps_get_gdsc_control(hw_mgr); + cam_icp_ipebps_reset(hw_mgr); + + atomic_set(&hw_mgr->recovery, 1); + CAM_DBG(CAM_ICP, "Done"); + return rc; +} +static int cam_icp_mgr_process_fatal_error( + struct cam_icp_hw_mgr *hw_mgr, uint32_t *msg_ptr) +{ + struct hfi_msg_event_notify *event_notify; + int rc = 0; + + CAM_DBG(CAM_ICP, "Enter"); + + event_notify = (struct hfi_msg_event_notify *)msg_ptr; + if (!event_notify) { + CAM_ERR(CAM_ICP, "Empty event message"); + return -EINVAL; + } + + CAM_DBG(CAM_ICP, "evt_id: %u evt_data1: %u evt_data2: %u", + event_notify->event_id, + event_notify->event_data1, + event_notify->event_data2); + + 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(unsigned int debug_lvl) +{ + uint32_t *msg_ptr = NULL, *pkt_ptr = NULL; + struct hfi_msg_debug *dbg_msg; + uint32_t read_len, size_processed = 0; + uint64_t timestamp = 0; + char *dbg_buf; + int rc = 0; + + rc = hfi_read_message(icp_hw_mgr.dbg_buf, Q_DBG, &read_len); + if (rc) + return; + + msg_ptr = (uint32_t *)icp_hw_mgr.dbg_buf; + while (true) { + pkt_ptr = msg_ptr; + if (pkt_ptr[ICP_PACKET_TYPE] == HFI_MSG_SYS_DEBUG) { + dbg_msg = (struct hfi_msg_debug *)pkt_ptr; + dbg_buf = (char *)&dbg_msg->msg_data; + 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); + if (size_processed >= read_len) + return; + msg_ptr += (pkt_ptr[ICP_PACKET_SIZE] >> + BYTE_WORD_SHIFT); + pkt_ptr = NULL; + dbg_msg = NULL; + dbg_buf = NULL; + } +} + +static int cam_icp_process_msg_pkt_type( + struct cam_icp_hw_mgr *hw_mgr, + uint32_t *msg_ptr, + uint32_t *msg_processed_len) +{ + int rc = 0; + int size_processed = 0; + + switch (msg_ptr[ICP_PACKET_TYPE]) { + case HFI_MSG_SYS_INIT_DONE: + CAM_DBG(CAM_ICP, "received SYS_INIT_DONE"); + complete(&hw_mgr->a5_complete); + size_processed = ( + (struct hfi_msg_init_done *)msg_ptr)->size; + break; + + case HFI_MSG_SYS_PC_PREP_DONE: + CAM_DBG(CAM_ICP, "HFI_MSG_SYS_PC_PREP_DONE is received\n"); + complete(&hw_mgr->a5_complete); + size_processed = sizeof(struct hfi_msg_pc_prep_done); + break; + + case HFI_MSG_SYS_PING_ACK: + CAM_DBG(CAM_ICP, "received SYS_PING_ACK"); + rc = cam_icp_mgr_process_msg_ping_ack(msg_ptr); + size_processed = sizeof(struct hfi_msg_ping_ack); + break; + + case HFI_MSG_IPEBPS_CREATE_HANDLE_ACK: + CAM_DBG(CAM_ICP, "received IPEBPS_CREATE_HANDLE_ACK"); + rc = cam_icp_mgr_process_msg_create_handle(msg_ptr); + size_processed = sizeof(struct hfi_msg_create_handle_ack); + break; + + case HFI_MSG_IPEBPS_ASYNC_COMMAND_INDIRECT_ACK: + CAM_DBG(CAM_ICP, "received ASYNC_INDIRECT_ACK"); + rc = cam_icp_mgr_process_indirect_ack_msg(msg_ptr); + size_processed = ( + (struct hfi_msg_ipebps_async_ack *)msg_ptr)->size; + break; + + case HFI_MSG_IPEBPS_ASYNC_COMMAND_DIRECT_ACK: + CAM_DBG(CAM_ICP, "received ASYNC_DIRECT_ACK"); + rc = cam_icp_mgr_process_direct_ack_msg(msg_ptr); + size_processed = ( + (struct hfi_msg_ipebps_async_ack *)msg_ptr)->size; + break; + + case HFI_MSG_EVENT_NOTIFY: + CAM_DBG(CAM_ICP, "received EVENT_NOTIFY"); + size_processed = ( + (struct hfi_msg_event_notify *)msg_ptr)->size; + rc = cam_icp_mgr_process_fatal_error(hw_mgr, msg_ptr); + if (rc) + CAM_ERR(CAM_ICP, "failed in processing evt notify"); + + break; + + default: + CAM_ERR(CAM_ICP, "invalid msg : %u", + msg_ptr[ICP_PACKET_TYPE]); + rc = -EINVAL; + break; + } + + *msg_processed_len = size_processed; + return rc; +} + +static int32_t cam_icp_mgr_process_msg(void *priv, void *data) +{ + uint32_t read_len, msg_processed_len; + uint32_t *msg_ptr = NULL; + struct hfi_msg_work_data *task_data; + struct cam_icp_hw_mgr *hw_mgr; + int rc = 0; + + if (!data || !priv) { + CAM_ERR(CAM_ICP, "Invalid data"); + return -EINVAL; + } + + task_data = data; + hw_mgr = priv; + + rc = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG, &read_len); + if (rc) { + CAM_DBG(CAM_ICP, "Unable to read msg q rc %d", rc); + } else { + read_len = read_len << BYTE_WORD_SHIFT; + msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf; + while (true) { + cam_icp_process_msg_pkt_type(hw_mgr, msg_ptr, + &msg_processed_len); + + if (!msg_processed_len) { + CAM_ERR(CAM_ICP, "Failed to read"); + rc = -EINVAL; + break; + } + + read_len -= msg_processed_len; + if (read_len > 0) { + msg_ptr += (msg_processed_len >> + BYTE_WORD_SHIFT); + msg_processed_len = 0; + } else { + break; + } + } + } + + 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)) { + CAM_ERR_RATE_LIMIT(CAM_ICP, "watch dog interrupt from A5"); + + rc = cam_icp_mgr_trigger_recovery(hw_mgr); + } + + return rc; +} + +int32_t cam_icp_hw_mgr_cb(uint32_t irq_status, void *data) +{ + int32_t rc = 0; + unsigned long flags; + struct cam_icp_hw_mgr *hw_mgr = data; + struct crm_workq_task *task; + struct hfi_msg_work_data *task_data; + + if (!data) { + CAM_ERR(CAM_ICP, "irq cb data is NULL"); + return rc; + } + + spin_lock_irqsave(&hw_mgr->hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work); + if (!task) { + CAM_ERR(CAM_ICP, "no empty task"); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags); + return -ENOMEM; + } + + task_data = (struct hfi_msg_work_data *)task->payload; + task_data->data = hw_mgr; + task_data->irq_status = irq_status; + task_data->type = ICP_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_icp_mgr_process_msg; + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags); + + return rc; +} + +static void cam_icp_free_hfi_mem(void) +{ + int rc; + + cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl); + rc = cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap); + if (rc) + CAM_ERR(CAM_ICP, "failed to unreserve sec heap"); + + cam_smmu_dealloc_qdss(icp_hw_mgr.iommu_hdl); + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.qtbl); + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.cmd_q); + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.msg_q); + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.dbg_q); + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf); +} + +static int cam_icp_alloc_secheap_mem(struct cam_mem_mgr_memory_desc *secheap) +{ + int rc; + struct cam_mem_mgr_request_desc alloc; + struct cam_mem_mgr_memory_desc out; + struct cam_smmu_region_info secheap_info; + + memset(&alloc, 0, sizeof(alloc)); + memset(&out, 0, sizeof(out)); + + rc = cam_smmu_get_region_info(icp_hw_mgr.iommu_hdl, + CAM_SMMU_REGION_SECHEAP, + &secheap_info); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to get secheap memory info"); + return rc; + } + + alloc.size = secheap_info.iova_len; + alloc.align = 0; + alloc.flags = 0; + alloc.smmu_hdl = icp_hw_mgr.iommu_hdl; + rc = cam_mem_mgr_reserve_memory_region(&alloc, + CAM_SMMU_REGION_SECHEAP, + &out); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to reserve secheap memory"); + return rc; + } + + *secheap = out; + CAM_DBG(CAM_ICP, "kva: %llX, iova: %x, hdl: %x, len: %lld", + out.kva, out.iova, out.mem_handle, out.len); + + return rc; +} + +static int cam_icp_alloc_sfr_mem(struct cam_mem_mgr_memory_desc *sfr) +{ + int rc; + struct cam_mem_mgr_request_desc alloc; + struct cam_mem_mgr_memory_desc out; + + memset(&alloc, 0, sizeof(alloc)); + memset(&out, 0, sizeof(out)); + alloc.size = SZ_8K; + alloc.align = 0; + alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE | + CAM_MEM_FLAG_HW_SHARED_ACCESS; + + alloc.smmu_hdl = icp_hw_mgr.iommu_hdl; + rc = cam_mem_mgr_request_mem(&alloc, &out); + if (rc) + return rc; + + *sfr = out; + CAM_DBG(CAM_ICP, "kva: %llX, iova: %x, hdl: %x, len: %lld", + out.kva, out.iova, out.mem_handle, out.len); + + return rc; +} + +static int cam_icp_alloc_shared_mem(struct cam_mem_mgr_memory_desc *qtbl) +{ + int rc; + struct cam_mem_mgr_request_desc alloc; + struct cam_mem_mgr_memory_desc out; + + memset(&alloc, 0, sizeof(alloc)); + memset(&out, 0, sizeof(out)); + alloc.size = SZ_1M; + alloc.align = 0; + alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE | + CAM_MEM_FLAG_HW_SHARED_ACCESS; + alloc.smmu_hdl = icp_hw_mgr.iommu_hdl; + rc = cam_mem_mgr_request_mem(&alloc, &out); + if (rc) + return rc; + + *qtbl = out; + CAM_DBG(CAM_ICP, "kva: %llX, iova: %x, hdl: %x, len: %lld", + out.kva, out.iova, out.mem_handle, out.len); + + return rc; +} + +static int cam_icp_allocate_fw_mem(void) +{ + int rc; + uintptr_t kvaddr; + size_t len; + dma_addr_t iova; + + rc = cam_smmu_alloc_firmware(icp_hw_mgr.iommu_hdl, + &iova, &kvaddr, &len); + if (rc) + return -ENOMEM; + + icp_hw_mgr.hfi_mem.fw_buf.len = len; + icp_hw_mgr.hfi_mem.fw_buf.kva = kvaddr; + icp_hw_mgr.hfi_mem.fw_buf.iova = iova; + icp_hw_mgr.hfi_mem.fw_buf.smmu_hdl = icp_hw_mgr.iommu_hdl; + + CAM_DBG(CAM_ICP, "kva: %zX, iova: %llx, len: %zu", + kvaddr, iova, len); + + return rc; +} + +static int cam_icp_allocate_qdss_mem(void) +{ + int rc; + size_t len; + dma_addr_t iova; + + rc = cam_smmu_alloc_qdss(icp_hw_mgr.iommu_hdl, + &iova, &len); + if (rc) + return rc; + + icp_hw_mgr.hfi_mem.qdss_buf.len = len; + icp_hw_mgr.hfi_mem.qdss_buf.iova = iova; + icp_hw_mgr.hfi_mem.qdss_buf.smmu_hdl = icp_hw_mgr.iommu_hdl; + + CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len); + + return rc; +} + +static int cam_icp_get_io_mem_info(void) +{ + int rc; + size_t len; + dma_addr_t iova; + + rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl, + &iova, &len); + if (rc) + return rc; + + icp_hw_mgr.hfi_mem.io_mem.iova_len = len; + icp_hw_mgr.hfi_mem.io_mem.iova_start = iova; + + CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len); + + return rc; +} + +static int cam_icp_allocate_hfi_mem(void) +{ + int rc; + + rc = cam_smmu_get_region_info(icp_hw_mgr.iommu_hdl, + CAM_SMMU_REGION_SHARED, + &icp_hw_mgr.hfi_mem.shmem); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to get shared memory info"); + return rc; + } + + rc = cam_icp_allocate_fw_mem(); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate FW memory"); + return rc; + } + + rc = cam_icp_allocate_qdss_mem(); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate qdss memory"); + goto fw_alloc_failed; + } + + rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.qtbl); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate qtbl memory"); + goto qtbl_alloc_failed; + } + + rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.cmd_q); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate cmd q memory"); + goto cmd_q_alloc_failed; + } + + rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.msg_q); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate msg q memory"); + goto msg_q_alloc_failed; + } + + rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.dbg_q); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate dbg q memory"); + goto dbg_q_alloc_failed; + } + + rc = cam_icp_alloc_sfr_mem(&icp_hw_mgr.hfi_mem.sfr_buf); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate sfr buffer"); + goto sfr_buf_alloc_failed; + } + + rc = cam_icp_alloc_secheap_mem(&icp_hw_mgr.hfi_mem.sec_heap); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to allocate sec heap memory"); + goto sec_heap_alloc_failed; + } + + rc = cam_icp_get_io_mem_info(); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to get I/O region info"); + goto get_io_mem_failed; + } + + return rc; +get_io_mem_failed: + cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap); +sec_heap_alloc_failed: + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf); +sfr_buf_alloc_failed: + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.dbg_q); +dbg_q_alloc_failed: + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.msg_q); +msg_q_alloc_failed: + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.cmd_q); +cmd_q_alloc_failed: + cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.qtbl); +qtbl_alloc_failed: + cam_smmu_dealloc_qdss(icp_hw_mgr.iommu_hdl); +fw_alloc_failed: + cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl); + return rc; +} + +static int cam_icp_mgr_get_free_ctx(struct cam_icp_hw_mgr *hw_mgr) +{ + int i = 0; + + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { + mutex_lock(&hw_mgr->ctx_data[i].ctx_mutex); + if (hw_mgr->ctx_data[i].state == CAM_ICP_CTX_STATE_FREE) { + hw_mgr->ctx_data[i].state = CAM_ICP_CTX_STATE_IN_USE; + mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex); + break; + } + mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex); + } + + return i; +} + +static void cam_icp_mgr_put_ctx(struct cam_icp_hw_ctx_data *ctx_data) +{ + ctx_data->state = CAM_ICP_CTX_STATE_FREE; +} + +static int cam_icp_mgr_send_pc_prep(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc; + struct cam_hw_intf *a5_dev_intf = NULL; + unsigned long rem_jiffies; + int timeout = 5000; + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); + return -EINVAL; + } + + reinit_completion(&hw_mgr->a5_complete); + CAM_DBG(CAM_ICP, "Sending HFI init command"); + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, CAM_ICP_A5_CMD_PC_PREP, NULL, 0); + if (rc) + return rc; + + CAM_DBG(CAM_ICP, "Wait for PC_PREP_DONE Message\n"); + rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.a5_complete, + msecs_to_jiffies((timeout))); + if (!rem_jiffies) { + rc = -ETIMEDOUT; + CAM_ERR(CAM_ICP, "PC_PREP response timed out %d\n", rc); + } + CAM_DBG(CAM_ICP, "Done Waiting for PC_PREP Message\n"); + + return rc; +} + +static int cam_ipe_bps_deint(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + if ((!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close"); + return 0; + } + + if (ipe1_dev_intf && hw_mgr->ipe_clk_state) { + ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv, + NULL, 0); + } + + if (hw_mgr->ipe_clk_state) + ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0); + if (hw_mgr->bps_clk_state) + bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0); + + + hw_mgr->bps_clk_state = false; + hw_mgr->ipe_clk_state = false; + + return 0; +} + +static int cam_icp_mgr_hw_close_u(void *hw_priv, void *hw_close_args) +{ + struct cam_icp_hw_mgr *hw_mgr = hw_priv; + int rc = 0; + + CAM_DBG(CAM_ICP, "UMD calls close"); + if (!hw_mgr) { + CAM_ERR(CAM_ICP, "Null hw mgr"); + return 0; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + rc = cam_icp_mgr_hw_close(hw_mgr, NULL); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +} + +static int cam_icp_mgr_hw_close_k(void *hw_priv, void *hw_close_args) +{ + struct cam_icp_hw_mgr *hw_mgr = hw_priv; + + CAM_DBG(CAM_ICP, "KMD calls close"); + if (!hw_mgr) { + CAM_ERR(CAM_ICP, "Null hw mgr"); + return 0; + } + + return cam_icp_mgr_hw_close(hw_mgr, NULL); + +} + +static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc; + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + + CAM_DBG(CAM_ICP, "ENTER"); + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + + if (!hw_mgr->icp_pc_flag || atomic_read(&hw_mgr->recovery)) { + cam_hfi_disable_cpu( + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + rc = cam_icp_mgr_hw_close_k(hw_mgr, NULL); + } else { + CAM_DBG(CAM_PERF, "Sending PC prep ICP PC enabled"); + rc = cam_icp_mgr_send_pc_prep(hw_mgr); + cam_hfi_disable_cpu( + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + } + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + CAM_DBG(CAM_ICP, "EXIT"); + + return rc; +} + +static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + struct hfi_mem_info hfi_mem; + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + + hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva; + hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova; + hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len; + CAM_DBG(CAM_ICP, "qtbl kva = %llX IOVA = %X length = %lld\n", + hfi_mem.qtbl.kva, hfi_mem.qtbl.iova, hfi_mem.qtbl.len); + + hfi_mem.cmd_q.kva = icp_hw_mgr.hfi_mem.cmd_q.kva; + hfi_mem.cmd_q.iova = icp_hw_mgr.hfi_mem.cmd_q.iova; + hfi_mem.cmd_q.len = icp_hw_mgr.hfi_mem.cmd_q.len; + CAM_DBG(CAM_ICP, "cmd_q kva = %llX IOVA = %X length = %lld\n", + hfi_mem.cmd_q.kva, hfi_mem.cmd_q.iova, hfi_mem.cmd_q.len); + + hfi_mem.msg_q.kva = icp_hw_mgr.hfi_mem.msg_q.kva; + hfi_mem.msg_q.iova = icp_hw_mgr.hfi_mem.msg_q.iova; + hfi_mem.msg_q.len = icp_hw_mgr.hfi_mem.msg_q.len; + CAM_DBG(CAM_ICP, "msg_q kva = %llX IOVA = %X length = %lld\n", + hfi_mem.msg_q.kva, hfi_mem.msg_q.iova, hfi_mem.msg_q.len); + + hfi_mem.dbg_q.kva = icp_hw_mgr.hfi_mem.dbg_q.kva; + hfi_mem.dbg_q.iova = icp_hw_mgr.hfi_mem.dbg_q.iova; + hfi_mem.dbg_q.len = icp_hw_mgr.hfi_mem.dbg_q.len; + CAM_DBG(CAM_ICP, "dbg_q kva = %llX IOVA = %X length = %lld\n", + hfi_mem.dbg_q.kva, hfi_mem.dbg_q.iova, hfi_mem.dbg_q.len); + + hfi_mem.sfr_buf.kva = icp_hw_mgr.hfi_mem.sfr_buf.kva; + hfi_mem.sfr_buf.iova = icp_hw_mgr.hfi_mem.sfr_buf.iova; + hfi_mem.sfr_buf.len = icp_hw_mgr.hfi_mem.sfr_buf.len; + CAM_DBG(CAM_ICP, "sfr kva = %llX IOVA = %X length = %lld\n", + hfi_mem.sfr_buf.kva, hfi_mem.sfr_buf.iova, + hfi_mem.sfr_buf.len); + + hfi_mem.sec_heap.kva = icp_hw_mgr.hfi_mem.sec_heap.kva; + hfi_mem.sec_heap.iova = icp_hw_mgr.hfi_mem.sec_heap.iova; + hfi_mem.sec_heap.len = icp_hw_mgr.hfi_mem.sec_heap.len; + + hfi_mem.shmem.iova = icp_hw_mgr.hfi_mem.shmem.iova_start; + hfi_mem.shmem.len = icp_hw_mgr.hfi_mem.shmem.iova_len; + + hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; + hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; + + hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; + hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; + + CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld", + hfi_mem.io_mem.iova, + hfi_mem.io_mem.len); + + return cam_hfi_resume(&hfi_mem, + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, + hw_mgr->a5_jtag_debug); +} + +static int cam_icp_mgr_abort_handle( + struct cam_icp_hw_ctx_data *ctx_data) +{ + int rc = 0; + unsigned long rem_jiffies; + size_t packet_size; + int timeout = 1000; + struct hfi_cmd_ipebps_async *abort_cmd; + + packet_size = + sizeof(struct hfi_cmd_ipebps_async) + + sizeof(struct hfi_cmd_abort) - + sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct); + abort_cmd = kzalloc(packet_size, GFP_KERNEL); + CAM_DBG(CAM_ICP, "abort pkt size = %d", (int) packet_size); + if (!abort_cmd) { + rc = -ENOMEM; + return rc; + } + + abort_cmd->size = packet_size; + abort_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT; + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_ABORT; + else + abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_ABORT; + + reinit_completion(&ctx_data->wait_complete); + abort_cmd->num_fw_handles = 1; + abort_cmd->fw_handles[0] = ctx_data->fw_handle; + abort_cmd->user_data1 = PTR_TO_U64(ctx_data); + abort_cmd->user_data2 = (uint64_t)0x0; + + rc = hfi_write_cmd(abort_cmd); + if (rc) { + kfree(abort_cmd); + return rc; + } + CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK", + ctx_data->fw_handle, ctx_data); + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + 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(); + } + + kfree(abort_cmd); + return rc; +} + +static int cam_icp_mgr_destroy_handle( + struct cam_icp_hw_ctx_data *ctx_data) +{ + int rc = 0; + int timeout = 1000; + unsigned long rem_jiffies; + size_t packet_size; + struct hfi_cmd_ipebps_async *destroy_cmd; + + packet_size = + sizeof(struct hfi_cmd_ipebps_async) + + sizeof(struct hfi_cmd_abort_destroy) - + sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct); + destroy_cmd = kzalloc(packet_size, GFP_KERNEL); + if (!destroy_cmd) { + rc = -ENOMEM; + return rc; + } + + destroy_cmd->size = packet_size; + destroy_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT; + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + destroy_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY; + else + destroy_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_DESTROY; + + reinit_completion(&ctx_data->wait_complete); + destroy_cmd->num_fw_handles = 1; + destroy_cmd->fw_handles[0] = ctx_data->fw_handle; + destroy_cmd->user_data1 = PTR_TO_U64(ctx_data); + destroy_cmd->user_data2 = (uint64_t)0x0; + memcpy(destroy_cmd->payload.direct, &ctx_data->temp_payload, + sizeof(uint64_t)); + + rc = hfi_write_cmd(destroy_cmd); + if (rc) { + kfree(destroy_cmd); + return rc; + } + CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK", + ctx_data->fw_handle, ctx_data); + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + if (!rem_jiffies) { + rc = -ETIMEDOUT; + CAM_ERR(CAM_ICP, "FW response timeout: %d for %u", + rc, ctx_data->ctx_id); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_hfi_queue_dump(); + } + kfree(destroy_cmd); + return rc; +} + +static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) +{ + int i = 0; + + if (ctx_id >= CAM_ICP_CTX_MAX) { + CAM_ERR(CAM_ICP, "ctx_id is wrong: %d", ctx_id); + return -EINVAL; + } + + mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + if (hw_mgr->ctx_data[ctx_id].state != + CAM_ICP_CTX_STATE_ACQUIRED) { + mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + CAM_DBG(CAM_ICP, + "ctx with id: %d not in right state to release: %d", + ctx_id, hw_mgr->ctx_data[ctx_id].state); + return 0; + } + cam_icp_mgr_ipe_bps_power_collapse(hw_mgr, + &hw_mgr->ctx_data[ctx_id], 0); + hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_RELEASE; + CAM_DBG(CAM_ICP, "E: ctx_id = %d recovery = %d", + ctx_id, atomic_read(&hw_mgr->recovery)); + cam_icp_mgr_abort_handle(&hw_mgr->ctx_data[ctx_id]); + cam_icp_mgr_destroy_handle(&hw_mgr->ctx_data[ctx_id]); + cam_icp_mgr_cleanup_ctx(&hw_mgr->ctx_data[ctx_id]); + + hw_mgr->ctx_data[ctx_id].fw_handle = 0; + hw_mgr->ctx_data[ctx_id].scratch_mem_size = 0; + for (i = 0; i < CAM_FRAME_CMD_MAX; i++) + clear_bit(i, hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); + kfree(hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); + hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap = NULL; + cam_icp_hw_mgr_clk_info_update(hw_mgr, &hw_mgr->ctx_data[ctx_id]); + hw_mgr->ctx_data[ctx_id].clk_info.curr_fc = 0; + hw_mgr->ctx_data[ctx_id].clk_info.base_clk = 0; + hw_mgr->ctxt_cnt--; + kfree(hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info); + hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL; + hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_FREE; + cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[ctx_id]); + mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + + CAM_DBG(CAM_ICP, "X: ctx_id = %d", ctx_id); + return 0; +} + +static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + + a5_dev_intf = hw_mgr->a5_dev_intf; + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!a5_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close"); + return; + } + + if (ipe1_dev_intf) + ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv, NULL, 0); + ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0); + bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0); + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + hw_mgr->bps_clk_state = false; + hw_mgr->ipe_clk_state = false; +} + +static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) +{ + struct cam_icp_hw_mgr *hw_mgr = hw_priv; + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + struct cam_icp_a5_set_irq_cb irq_cb; + struct cam_icp_a5_set_fw_buf_info fw_buf_info; + int rc = 0; + + CAM_DBG(CAM_ICP, "E"); + if (hw_mgr->fw_download == false) { + CAM_DBG(CAM_ICP, "hw mgr is already closed"); + return 0; + } + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_DBG(CAM_ICP, "a5_dev_intf is NULL"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + fw_buf_info.kva = 0; + fw_buf_info.iova = 0; + fw_buf_info.len = 0; + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_CMD_SET_FW_BUF, + &fw_buf_info, + sizeof(fw_buf_info)); + if (rc) + CAM_ERR(CAM_ICP, "nullify the fw buf failed"); + cam_hfi_deinit( + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + irq_cb.icp_hw_mgr_cb = NULL; + irq_cb.data = NULL; + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) + CAM_ERR(CAM_ICP, "deregister irq call back failed"); + + cam_icp_free_hfi_mem(); + hw_mgr->fw_download = false; + + CAM_DBG(CAM_ICP, "Exit"); + return rc; +} + +static int cam_icp_mgr_device_init(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *ipe0_dev_intf = NULL; + struct cam_hw_intf *ipe1_dev_intf = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + + a5_dev_intf = hw_mgr->a5_dev_intf; + ipe0_dev_intf = hw_mgr->ipe0_dev_intf; + ipe1_dev_intf = hw_mgr->ipe1_dev_intf; + bps_dev_intf = hw_mgr->bps_dev_intf; + + if ((!a5_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong"); + return -EINVAL; + } + + rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0); + if (rc) + goto a5_dev_init_failed; + + rc = bps_dev_intf->hw_ops.init(bps_dev_intf->hw_priv, NULL, 0); + if (rc) + goto bps_dev_init_failed; + + rc = ipe0_dev_intf->hw_ops.init(ipe0_dev_intf->hw_priv, NULL, 0); + if (rc) + goto ipe0_dev_init_failed; + + if (ipe1_dev_intf) { + rc = ipe1_dev_intf->hw_ops.init(ipe1_dev_intf->hw_priv, + NULL, 0); + if (rc) + goto ipe1_dev_init_failed; + } + + hw_mgr->bps_clk_state = true; + hw_mgr->ipe_clk_state = true; + + return rc; +ipe1_dev_init_failed: + ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0); + hw_mgr->ipe_clk_state = false; +ipe0_dev_init_failed: + bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0); + hw_mgr->bps_clk_state = false; +bps_dev_init_failed: + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); +a5_dev_init_failed: + return rc; +} + +static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc; + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + struct cam_icp_a5_set_irq_cb irq_cb; + struct cam_icp_a5_set_fw_buf_info fw_buf_info; + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + + irq_cb.icp_hw_mgr_cb = cam_icp_hw_mgr_cb; + irq_cb.data = hw_mgr; + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) + goto set_irq_failed; + + fw_buf_info.kva = icp_hw_mgr.hfi_mem.fw_buf.kva; + fw_buf_info.iova = icp_hw_mgr.hfi_mem.fw_buf.iova; + fw_buf_info.len = icp_hw_mgr.hfi_mem.fw_buf.len; + + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_CMD_SET_FW_BUF, + &fw_buf_info, sizeof(fw_buf_info)); + if (rc) + goto set_irq_failed; + + cam_hfi_enable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_CMD_FW_DOWNLOAD, + NULL, 0); + if (rc) + goto fw_download_failed; + + return rc; +fw_download_failed: + cam_hfi_disable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); +set_irq_failed: + return rc; +} + +static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + struct hfi_mem_info hfi_mem; + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + + hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva; + hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova; + hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len; + + hfi_mem.cmd_q.kva = icp_hw_mgr.hfi_mem.cmd_q.kva; + hfi_mem.cmd_q.iova = icp_hw_mgr.hfi_mem.cmd_q.iova; + hfi_mem.cmd_q.len = icp_hw_mgr.hfi_mem.cmd_q.len; + + hfi_mem.msg_q.kva = icp_hw_mgr.hfi_mem.msg_q.kva; + hfi_mem.msg_q.iova = icp_hw_mgr.hfi_mem.msg_q.iova; + hfi_mem.msg_q.len = icp_hw_mgr.hfi_mem.msg_q.len; + + hfi_mem.dbg_q.kva = icp_hw_mgr.hfi_mem.dbg_q.kva; + hfi_mem.dbg_q.iova = icp_hw_mgr.hfi_mem.dbg_q.iova; + hfi_mem.dbg_q.len = icp_hw_mgr.hfi_mem.dbg_q.len; + + hfi_mem.sfr_buf.kva = icp_hw_mgr.hfi_mem.sfr_buf.kva; + hfi_mem.sfr_buf.iova = icp_hw_mgr.hfi_mem.sfr_buf.iova; + hfi_mem.sfr_buf.len = icp_hw_mgr.hfi_mem.sfr_buf.len; + + hfi_mem.sec_heap.kva = icp_hw_mgr.hfi_mem.sec_heap.kva; + hfi_mem.sec_heap.iova = icp_hw_mgr.hfi_mem.sec_heap.iova; + hfi_mem.sec_heap.len = icp_hw_mgr.hfi_mem.sec_heap.len; + + hfi_mem.shmem.iova = icp_hw_mgr.hfi_mem.shmem.iova_start; + hfi_mem.shmem.len = icp_hw_mgr.hfi_mem.shmem.iova_len; + + hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; + hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; + + hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; + hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; + + return cam_hfi_init(0, &hfi_mem, + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, + hw_mgr->a5_jtag_debug); +} + +static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc; + struct cam_hw_intf *a5_dev_intf = NULL; + unsigned long rem_jiffies; + int timeout = 5000; + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + return -EINVAL; + } + + reinit_completion(&hw_mgr->a5_complete); + CAM_DBG(CAM_ICP, "Sending HFI init command"); + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_SEND_INIT, + NULL, 0); + if (rc) + return rc; + + rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.a5_complete, + msecs_to_jiffies((timeout))); + 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"); + + return rc; +} + +static int cam_icp_mgr_hw_open_u(void *hw_mgr_priv, void *download_fw_args) +{ + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + int rc = 0; + + if (!hw_mgr) { + CAM_ERR(CAM_ICP, "Null hw mgr"); + return 0; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + rc = cam_icp_mgr_hw_open(hw_mgr, download_fw_args); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +} + +static int cam_icp_mgr_hw_open_k(void *hw_mgr_priv, void *download_fw_args) +{ + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr) { + CAM_ERR(CAM_ICP, "Null hw mgr"); + return 0; + } + + return cam_icp_mgr_hw_open(hw_mgr, download_fw_args); +} + +static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; + struct cam_hw_intf *a5_dev_intf = NULL; + bool downloadFromResume = true; + + CAM_DBG(CAM_ICP, "Enter"); + a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0]; + + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5 dev intf is wrong"); + return -EINVAL; + } + + if (hw_mgr->fw_download == false) { + CAM_DBG(CAM_ICP, "Downloading FW"); + rc = cam_icp_mgr_hw_open_k(hw_mgr, &downloadFromResume); + CAM_DBG(CAM_ICP, "FW Download Done Exit"); + return rc; + } + + rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0); + if (rc) + return -EINVAL; + + rc = cam_icp_mgr_hfi_resume(hw_mgr); + if (rc) + goto hfi_resume_failed; + + CAM_DBG(CAM_ICP, "Exit"); + return rc; +hfi_resume_failed: + cam_icp_mgr_icp_power_collapse(hw_mgr); + return rc; +} + +static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) +{ + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_info *a5_dev = NULL; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + bool icp_pc = false; + int rc = 0; + + if (!hw_mgr) { + CAM_ERR(CAM_ICP, "hw_mgr is NULL"); + return -EINVAL; + } + + if (hw_mgr->fw_download) { + CAM_DBG(CAM_ICP, "FW already downloaded"); + return rc; + } + + a5_dev_intf = hw_mgr->a5_dev_intf; + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + return -EINVAL; + } + a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + rc = cam_icp_allocate_hfi_mem(); + if (rc) + goto alloc_hfi_mem_failed; + + rc = cam_icp_mgr_device_init(hw_mgr); + if (rc) + goto dev_init_fail; + + rc = cam_icp_mgr_fw_download(hw_mgr); + if (rc) + goto fw_download_failed; + + rc = cam_icp_mgr_hfi_init(hw_mgr); + if (rc) + goto hfi_init_failed; + + rc = cam_icp_mgr_send_fw_init(hw_mgr); + if (rc) + goto fw_init_failed; + + hw_mgr->ctxt_cnt = 0; + hw_mgr->fw_download = true; + atomic_set(&hw_mgr->recovery, 0); + + CAM_INFO(CAM_ICP, "FW download done successfully"); + + rc = cam_ipe_bps_deint(hw_mgr); + if (download_fw_args) + icp_pc = *((bool *)download_fw_args); + + if (download_fw_args && icp_pc == true && hw_mgr->icp_pc_flag) { + rc = cam_ipe_bps_deint(hw_mgr); + CAM_DBG(CAM_ICP, "deinit all clocks"); + } + + if (download_fw_args && icp_pc == true) + return rc; + + rc = cam_ipe_bps_deint(hw_mgr); + rc = cam_icp_mgr_icp_power_collapse(hw_mgr); + CAM_DBG(CAM_ICP, "deinit all clocks at boot up"); + + return rc; + +fw_init_failed: + cam_hfi_deinit( + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); +hfi_init_failed: + cam_hfi_disable_cpu( + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); +fw_download_failed: + cam_icp_mgr_device_deinit(hw_mgr); +dev_init_fail: + cam_icp_free_hfi_mem(); +alloc_hfi_mem_failed: + return rc; +} + +static int cam_icp_mgr_handle_config_err( + struct cam_hw_config_args *config_args, + struct cam_icp_hw_ctx_data *ctx_data, + int idx) +{ + struct cam_hw_done_event_data buf_data; + + buf_data.request_id = *(uint64_t *)config_args->priv; + ctx_data->ctxt_event_cb(ctx_data->context_priv, false, &buf_data); + + ctx_data->hfi_frame_process.request_id[idx] = 0; + ctx_data->hfi_frame_process.fw_process_flag[idx] = false; + clear_bit(idx, ctx_data->hfi_frame_process.bitmap); + + return 0; +} + +static int cam_icp_mgr_enqueue_config(struct cam_icp_hw_mgr *hw_mgr, + struct cam_hw_config_args *config_args) +{ + int rc = 0; + uint64_t request_id = 0; + struct crm_workq_task *task; + struct hfi_cmd_work_data *task_data; + struct hfi_cmd_ipebps_async *hfi_cmd; + struct cam_hw_update_entry *hw_update_entries; + struct icp_frame_info *frame_info = NULL; + + frame_info = (struct icp_frame_info *)config_args->priv; + request_id = frame_info->request_id; + hw_update_entries = config_args->hw_update_entries; + CAM_DBG(CAM_ICP, "req_id = %lld %pK", request_id, config_args->priv); + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) { + CAM_ERR(CAM_ICP, "no empty task"); + return -ENOMEM; + } + + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)hw_update_entries->addr; + hfi_cmd = (struct hfi_cmd_ipebps_async *)hw_update_entries->addr; + task_data->request_id = request_id; + task_data->type = ICP_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_icp_mgr_process_cmd; + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + + return rc; +} + +static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data, + uint32_t io_buf_addr) +{ + int rc = 0; + struct hfi_cmd_work_data *task_data; + struct hfi_cmd_ipebps_async ioconfig_cmd; + unsigned long rem_jiffies; + int timeout = 5000; + struct crm_workq_task *task; + uint32_t size_in_words; + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) + return -ENOMEM; + + ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async); + ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT; + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO; + else + ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO; + + reinit_completion(&ctx_data->wait_complete); + + ioconfig_cmd.num_fw_handles = 1; + ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle; + ioconfig_cmd.payload.indirect = io_buf_addr; + ioconfig_cmd.user_data1 = PTR_TO_U64(ctx_data); + ioconfig_cmd.user_data2 = (uint64_t)0x0; + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)&ioconfig_cmd; + task_data->request_id = 0; + task_data->type = ICP_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_icp_mgr_process_cmd; + size_in_words = (*(uint32_t *)task_data->data) >> 2; + CAM_DBG(CAM_ICP, "size_in_words %u", size_in_words); + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + if (rc) + return rc; + + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + 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(); + } + + return rc; +} + +static int cam_icp_mgr_send_recfg_io(struct cam_icp_hw_ctx_data *ctx_data, + struct hfi_cmd_ipebps_async *ioconfig_cmd, uint64_t req_id) +{ + int rc = 0; + struct hfi_cmd_work_data *task_data; + struct crm_workq_task *task; + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) + return -ENOMEM; + + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)ioconfig_cmd; + task_data->request_id = req_id; + task_data->type = ICP_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_icp_mgr_process_cmd; + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + if (rc) + return rc; + + return rc; +} + +static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) +{ + int rc = 0; + int idx; + uint64_t req_id; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_config_args *config_args = config_hw_args; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct icp_frame_info *frame_info = NULL; + + if (!hw_mgr || !config_args) { + CAM_ERR(CAM_ICP, "Invalid arguments %pK %pK", + hw_mgr, config_args); + return -EINVAL; + } + + if (!config_args->num_hw_update_entries) { + CAM_ERR(CAM_ICP, "No hw update enteries are available"); + return -EINVAL; + } + + ctx_data = config_args->ctxt_to_hw_map; + mutex_lock(&hw_mgr->hw_mgr_mutex); + mutex_lock(&ctx_data->ctx_mutex); + if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) { + mutex_unlock(&ctx_data->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_ICP, "ctx id :%u is not in use", + ctx_data->ctx_id); + return -EINVAL; + } + + frame_info = (struct icp_frame_info *)config_args->priv; + req_id = frame_info->request_id; + idx = cam_icp_clk_idx_from_req_id(ctx_data, req_id); + + cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx); + ctx_data->hfi_frame_process.fw_process_flag[idx] = true; + + CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id, + frame_info->io_config); + + if (frame_info->io_config != 0) { + CAM_INFO(CAM_ICP, "Send recfg io"); + rc = cam_icp_mgr_send_recfg_io(ctx_data, + &frame_info->hfi_cfg_io_cmd, req_id); + if (rc) + CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd"); + } + + rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args); + if (rc) + goto config_err; + CAM_DBG(CAM_REQ, + "req_id = %lld on ctx_id %u for dev %d queued to FW", + req_id, ctx_data->ctx_id, + ctx_data->icp_dev_acquire_info->dev_type); + mutex_unlock(&ctx_data->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return 0; +config_err: + cam_icp_mgr_handle_config_err(config_args, ctx_data, idx); + mutex_unlock(&ctx_data->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_icp_mgr_prepare_frame_process_cmd( + struct cam_icp_hw_ctx_data *ctx_data, + struct hfi_cmd_ipebps_async *hfi_cmd, + uint64_t request_id, + uint32_t fw_cmd_buf_iova_addr) +{ + hfi_cmd->size = sizeof(struct hfi_cmd_ipebps_async); + hfi_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT; + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + hfi_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_FRAME_PROCESS; + else + hfi_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_FRAME_PROCESS; + hfi_cmd->num_fw_handles = 1; + hfi_cmd->fw_handles[0] = ctx_data->fw_handle; + hfi_cmd->payload.indirect = fw_cmd_buf_iova_addr; + hfi_cmd->user_data1 = PTR_TO_U64(ctx_data); + hfi_cmd->user_data2 = request_id; + + CAM_DBG(CAM_ICP, "ctx_data : %pK, request_id :%lld cmd_buf %x", + (void *)ctx_data->context_priv, request_id, + fw_cmd_buf_iova_addr); + + return 0; +} + +static bool cam_icp_mgr_is_valid_inconfig(struct cam_packet *packet) +{ + int i, num_in_map_entries = 0; + bool in_config_valid = false; + struct cam_buf_io_cfg *io_cfg_ptr = NULL; + + io_cfg_ptr = (struct cam_buf_io_cfg *) ((uint32_t *) &packet->payload + + packet->io_configs_offset/4); + + for (i = 0 ; i < packet->num_io_configs; i++) + if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) + num_in_map_entries++; + + if (num_in_map_entries <= CAM_MAX_IN_RES) { + in_config_valid = true; + } else { + CAM_ERR(CAM_ICP, "In config entries(%u) more than allowed(%u)", + num_in_map_entries, CAM_MAX_IN_RES); + } + + CAM_DBG(CAM_ICP, "number of in_config info: %u %u %u %u", + packet->num_io_configs, IPE_IO_IMAGES_MAX, + num_in_map_entries, CAM_MAX_IN_RES); + + return in_config_valid; +} + +static bool cam_icp_mgr_is_valid_outconfig(struct cam_packet *packet) +{ + int i, num_out_map_entries = 0; + bool out_config_valid = false; + struct cam_buf_io_cfg *io_cfg_ptr = NULL; + + io_cfg_ptr = (struct cam_buf_io_cfg *) ((uint32_t *) &packet->payload + + packet->io_configs_offset/4); + + for (i = 0 ; i < packet->num_io_configs; i++) + if (io_cfg_ptr[i].direction == CAM_BUF_OUTPUT) + num_out_map_entries++; + + if (num_out_map_entries <= CAM_MAX_OUT_RES) { + out_config_valid = true; + } else { + CAM_ERR(CAM_ICP, "Out config entries(%u) more than allowed(%u)", + num_out_map_entries, CAM_MAX_OUT_RES); + } + + CAM_DBG(CAM_ICP, "number of out_config info: %u %u %u %u", + packet->num_io_configs, IPE_IO_IMAGES_MAX, + num_out_map_entries, CAM_MAX_OUT_RES); + + return out_config_valid; +} + +static int cam_icp_mgr_pkt_validation(struct cam_packet *packet) +{ + if (((packet->header.op_code & 0xff) != + CAM_ICP_OPCODE_IPE_UPDATE) && + ((packet->header.op_code & 0xff) != + CAM_ICP_OPCODE_BPS_UPDATE)) { + CAM_ERR(CAM_ICP, "Invalid Opcode in pkt: %d", + packet->header.op_code & 0xff); + return -EINVAL; + } + + if (packet->num_io_configs > IPE_IO_IMAGES_MAX) { + CAM_ERR(CAM_ICP, "Invalid number of io configs: %d %d", + IPE_IO_IMAGES_MAX, packet->num_io_configs); + return -EINVAL; + } + + if (packet->num_cmd_buf > CAM_ICP_CTX_MAX_CMD_BUFFERS) { + CAM_ERR(CAM_ICP, "Invalid number of cmd buffers: %d %d", + CAM_ICP_CTX_MAX_CMD_BUFFERS, packet->num_cmd_buf); + return -EINVAL; + } + + if (!cam_icp_mgr_is_valid_inconfig(packet) || + !cam_icp_mgr_is_valid_outconfig(packet)) { + return -EINVAL; + } + + CAM_DBG(CAM_ICP, "number of cmd/patch info: %u %u %u %u", + packet->num_cmd_buf, + packet->num_io_configs, IPE_IO_IMAGES_MAX, + packet->num_patches); + return 0; +} + +static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, + struct cam_packet *packet, struct cam_icp_hw_ctx_data *ctx_data, + uint32_t *fw_cmd_buf_iova_addr) +{ + int rc = 0; + int i, j, k; + int num_cmd_buf = 0; + uint64_t addr; + size_t len; + struct cam_cmd_buf_desc *cmd_desc = NULL; + uintptr_t cpu_addr = 0; + struct ipe_frame_process_data *frame_process_data = NULL; + struct bps_frame_process_data *bps_frame_process_data = NULL; + struct frame_set *ipe_set = NULL; + struct frame_buffer *bps_bufs = NULL; + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + + *fw_cmd_buf_iova_addr = 0; + for (i = 0; i < packet->num_cmd_buf; i++, num_cmd_buf++) { + if (cmd_desc[i].type == CAM_CMD_BUF_FW) { + rc = cam_mem_get_io_buf(cmd_desc[i].mem_handle, + hw_mgr->iommu_hdl, &addr, &len); + if (rc) { + CAM_ERR(CAM_ICP, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + + if (num_cmd_buf > 0) + num_cmd_buf--; + return rc; + } + *fw_cmd_buf_iova_addr = addr; + *fw_cmd_buf_iova_addr = + (*fw_cmd_buf_iova_addr + cmd_desc[i].offset); + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &cpu_addr, &len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_ICP, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + *fw_cmd_buf_iova_addr = 0; + + if (num_cmd_buf > 0) + num_cmd_buf--; + return rc; + } + if ((len <= cmd_desc[i].offset) || + (cmd_desc[i].size < cmd_desc[i].length) || + ((len - cmd_desc[i].offset) < + cmd_desc[i].length)) { + CAM_ERR(CAM_ICP, "Invalid offset or length"); + return -EINVAL; + } + cpu_addr = cpu_addr + cmd_desc[i].offset; + } + } + + if (!cpu_addr) { + CAM_ERR(CAM_ICP, "invalid number of cmd buf"); + return -EINVAL; + } + + if (ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS) { + CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr); + frame_process_data = (struct ipe_frame_process_data *)cpu_addr; + CAM_DBG(CAM_ICP, "%u %u %u", frame_process_data->max_num_cores, + frame_process_data->target_time, + frame_process_data->frames_in_batch); + frame_process_data->strip_lib_out_addr = 0; + frame_process_data->iq_settings_addr = 0; + frame_process_data->scratch_buffer_addr = 0; + frame_process_data->ubwc_stats_buffer_addr = 0; + frame_process_data->cdm_buffer_addr = 0; + frame_process_data->cdm_prog_base = 0; + for (i = 0; i < frame_process_data->frames_in_batch; i++) { + ipe_set = &frame_process_data->framesets[i]; + for (j = 0; j < IPE_IO_IMAGES_MAX; j++) { + for (k = 0; k < MAX_NUM_OF_IMAGE_PLANES; k++) { + ipe_set->buffers[j].buf_ptr[k] = 0; + ipe_set->buffers[j].meta_buf_ptr[k] = 0; + } + } + } + } else { + CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr); + bps_frame_process_data = + (struct bps_frame_process_data *)cpu_addr; + CAM_DBG(CAM_ICP, "%u %u", + bps_frame_process_data->max_num_cores, + bps_frame_process_data->target_time); + bps_frame_process_data->ubwc_stats_buffer_addr = 0; + bps_frame_process_data->cdm_buffer_addr = 0; + bps_frame_process_data->iq_settings_addr = 0; + bps_frame_process_data->strip_lib_out_addr = 0; + bps_frame_process_data->cdm_prog_addr = 0; + for (i = 0; i < BPS_IO_IMAGES_MAX; i++) { + bps_bufs = &bps_frame_process_data->buffers[i]; + for (j = 0; j < MAX_NUM_OF_IMAGE_PLANES; j++) { + bps_bufs->buf_ptr[j] = 0; + bps_bufs->meta_buf_ptr[j] = 0; + } + } + } + + return rc; +} + +static int cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_packet *packet, + struct cam_hw_prepare_update_args *prepare_args, + int32_t index) +{ + int i, j, k, rc = 0; + struct cam_buf_io_cfg *io_cfg_ptr = NULL; + int32_t sync_in_obj[CAM_MAX_IN_RES]; + int32_t merged_sync_in_obj; + + io_cfg_ptr = (struct cam_buf_io_cfg *) ((uint32_t *) &packet->payload + + packet->io_configs_offset/4); + prepare_args->num_out_map_entries = 0; + prepare_args->num_in_map_entries = 0; + + for (i = 0, j = 0, k = 0; i < packet->num_io_configs; i++) { + if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) { + sync_in_obj[j++] = io_cfg_ptr[i].fence; + prepare_args->num_in_map_entries++; + } else { + prepare_args->out_map_entries[k++].sync_id = + io_cfg_ptr[i].fence; + prepare_args->num_out_map_entries++; + } + CAM_DBG(CAM_REQ, + "ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u memh %x", + ctx_data->ctx_id, packet->header.request_id, i, + io_cfg_ptr[i].direction, io_cfg_ptr[i].fence, + io_cfg_ptr[i].resource_type, + io_cfg_ptr[i].mem_handle[0]); + } + + if (prepare_args->num_in_map_entries > 1) + prepare_args->num_in_map_entries = + cam_common_util_remove_duplicate_arr( + sync_in_obj, prepare_args->num_in_map_entries); + + if (prepare_args->num_in_map_entries > 1) { + rc = cam_sync_merge(&sync_in_obj[0], + prepare_args->num_in_map_entries, &merged_sync_in_obj); + if (rc) { + prepare_args->num_out_map_entries = 0; + prepare_args->num_in_map_entries = 0; + return rc; + } + + ctx_data->hfi_frame_process.in_resource[index] = + merged_sync_in_obj; + prepare_args->in_map_entries[0].sync_id = merged_sync_in_obj; + prepare_args->num_in_map_entries = 1; + CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d", + ctx_data->ctx_id, packet->header.request_id, + merged_sync_in_obj); + } else if (prepare_args->num_in_map_entries == 1) { + prepare_args->in_map_entries[0].sync_id = sync_in_obj[0]; + prepare_args->num_in_map_entries = 1; + ctx_data->hfi_frame_process.in_resource[index] = 0; + } else { + CAM_ERR(CAM_ICP, "No input fences"); + prepare_args->num_in_map_entries = 0; + ctx_data->hfi_frame_process.in_resource[index] = 0; + rc = -EINVAL; + } + + return rc; +} + +static int cam_icp_process_stream_settings( + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_cmd_mem_regions *cmd_mem_regions, + bool map_unmap) +{ + int rc = 0, i = 0; + size_t packet_size, map_cmd_size, len; + uint64_t iova; + unsigned long rem_jiffies; + int timeout = 5000; + struct hfi_cmd_ipe_bps_map *map_cmd; + struct hfi_cmd_ipebps_async *async_direct; + + map_cmd_size = + sizeof(struct hfi_cmd_ipe_bps_map) + + ((cmd_mem_regions->num_regions - 1) * + sizeof(struct mem_map_region_data)); + + map_cmd = kzalloc(map_cmd_size, GFP_KERNEL); + if (!map_cmd) + return -ENOMEM; + + for (i = 0; i < cmd_mem_regions->num_regions; i++) { + rc = cam_mem_get_io_buf( + cmd_mem_regions->map_info_array[i].mem_handle, + icp_hw_mgr.iommu_hdl, &iova, &len); + if (rc) { + CAM_ERR(CAM_ICP, + "Failed to get cmd region iova for handle %u", + cmd_mem_regions->map_info_array[i].mem_handle); + kfree(map_cmd); + return -EINVAL; + } + + map_cmd->mem_map_region_sets[i].start_addr = (uint32_t)iova + + (cmd_mem_regions->map_info_array[i].offset); + map_cmd->mem_map_region_sets[i].len = (uint32_t) len; + + CAM_DBG(CAM_ICP, "Region %u mem_handle %d iova %pK len %u", + (i+1), cmd_mem_regions->map_info_array[i].mem_handle, + (uint32_t)iova, (uint32_t)len); + } + + map_cmd->mem_map_request_num = cmd_mem_regions->num_regions; + map_cmd->user_data = 0; + + packet_size = + sizeof(struct hfi_cmd_ipebps_async) + + (sizeof(struct hfi_cmd_ipe_bps_map) + + ((cmd_mem_regions->num_regions - 1) * + sizeof(struct mem_map_region_data))) - + sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct); + + async_direct = kzalloc(packet_size, GFP_KERNEL); + if (!async_direct) { + kfree(map_cmd); + return -ENOMEM; + } + + async_direct->size = packet_size; + async_direct->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT; + if (map_unmap) + async_direct->opcode = HFI_IPEBPS_CMD_OPCODE_MEM_MAP; + else + async_direct->opcode = HFI_IPEBPS_CMD_OPCODE_MEM_UNMAP; + async_direct->num_fw_handles = 1; + async_direct->fw_handles[0] = ctx_data->fw_handle; + async_direct->user_data1 = (uint64_t)ctx_data; + async_direct->user_data2 = (uint64_t)0x0; + memcpy(async_direct->payload.direct, map_cmd, + map_cmd_size); + + reinit_completion(&ctx_data->wait_complete); + rc = hfi_write_cmd(async_direct); + if (rc) { + CAM_ERR(CAM_ICP, "hfi write failed rc %d", rc); + goto end; + } + + CAM_DBG(CAM_ICP, "Sent FW %s cmd", + map_unmap ? "Map" : "Unmap"); + + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + if (!rem_jiffies) { + rc = -ETIMEDOUT; + CAM_ERR(CAM_ICP, "FW response timed out %d", rc); + cam_hfi_queue_dump(); + } + +end: + kfree(map_cmd); + kfree(async_direct); + return rc; +} + +static int cam_icp_packet_generic_blob_handler(void *user_data, + uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) +{ + struct cam_icp_clk_bw_request *soc_req; + struct cam_icp_clk_bw_request *clk_info; + struct cam_icp_clk_bw_request_v2 *soc_req_v2; + struct cam_icp_clk_bw_req_internal_v2 *clk_info_v2; + struct cam_cmd_mem_regions *cmd_mem_regions; + struct icp_cmd_generic_blob *blob; + struct cam_icp_hw_ctx_data *ctx_data; + uint32_t index; + size_t io_buf_size, clk_update_size; + int rc = 0; + uintptr_t pResource; + + if (!blob_data || (blob_size == 0)) { + CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data, + blob_size); + return -EINVAL; + } + + blob = (struct icp_cmd_generic_blob *)user_data; + ctx_data = blob->ctx; + index = blob->frame_info_idx; + + switch (blob_type) { + case CAM_ICP_CMD_GENERIC_BLOB_CLK: + CAM_WARN(CAM_ICP, + "Using deprecated blob type GENERIC_BLOB_CLK"); + if (blob_size != sizeof(struct cam_icp_clk_bw_request)) { + CAM_ERR(CAM_ICP, "Mismatch blob size %d expected %lu", + blob_size, + sizeof(struct cam_icp_clk_bw_request)); + return -EINVAL; + } + + if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_UNKNOWN) { + ctx_data->bw_config_version = CAM_ICP_BW_CONFIG_V1; + } else if (ctx_data->bw_config_version != + CAM_ICP_BW_CONFIG_V1) { + CAM_ERR(CAM_ICP, + "Mismatch blob versions %d expected v1 %d, blob_type=%d", + ctx_data->bw_config_version, + CAM_ICP_BW_CONFIG_V1, blob_type); + return -EINVAL; + } + + clk_info = &ctx_data->hfi_frame_process.clk_info[index]; + + soc_req = (struct cam_icp_clk_bw_request *)blob_data; + *clk_info = *soc_req; + CAM_DBG(CAM_ICP, "budget:%llu fc: %llu %d BW %lld %lld", + clk_info->budget_ns, clk_info->frame_cycles, + clk_info->rt_flag, clk_info->uncompressed_bw, + clk_info->compressed_bw); + break; + + case CAM_ICP_CMD_GENERIC_BLOB_CLK_V2: + if (blob_size < sizeof(struct cam_icp_clk_bw_request_v2)) { + CAM_ERR(CAM_ICP, "Mismatch blob size %d expected %lu", + blob_size, + sizeof(struct cam_icp_clk_bw_request_v2)); + return -EINVAL; + } + + if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_UNKNOWN) { + ctx_data->bw_config_version = CAM_ICP_BW_CONFIG_V2; + } else if (ctx_data->bw_config_version != + CAM_ICP_BW_CONFIG_V2) { + CAM_ERR(CAM_ICP, + "Mismatch blob versions %d expected v2 %d, blob_type=%d", + ctx_data->bw_config_version, + CAM_ICP_BW_CONFIG_V2, blob_type); + return -EINVAL; + } + + soc_req_v2 = (struct cam_icp_clk_bw_request_v2 *)blob_data; + if (soc_req_v2->num_paths > CAM_ICP_MAX_PER_PATH_VOTES) { + CAM_ERR(CAM_ICP, "Invalid num paths: %d", + soc_req_v2->num_paths); + return -EINVAL; + } + + /* Check for integer overflow */ + if (soc_req_v2->num_paths != 1) { + if (sizeof(struct cam_axi_per_path_bw_vote) > + ((UINT_MAX - + sizeof(struct cam_icp_clk_bw_request_v2)) / + (soc_req_v2->num_paths - 1))) { + CAM_ERR(CAM_ICP, + "Size exceeds limit paths:%u size per path:%lu", + soc_req_v2->num_paths - 1, + sizeof( + struct cam_axi_per_path_bw_vote)); + return -EINVAL; + } + } + + clk_update_size = sizeof(struct cam_icp_clk_bw_request_v2) + + ((soc_req_v2->num_paths - 1) * + sizeof(struct cam_axi_per_path_bw_vote)); + if (blob_size < clk_update_size) { + CAM_ERR(CAM_ICP, "Invalid blob size: %u", + blob_size); + return -EINVAL; + } + + clk_info = &ctx_data->hfi_frame_process.clk_info[index]; + clk_info_v2 = &ctx_data->hfi_frame_process.clk_info_v2[index]; + + memcpy(clk_info_v2, soc_req_v2, clk_update_size); + + /* Use v1 structure for clk fields */ + clk_info->budget_ns = clk_info_v2->budget_ns; + clk_info->frame_cycles = clk_info_v2->frame_cycles; + clk_info->rt_flag = clk_info_v2->rt_flag; + + CAM_DBG(CAM_ICP, "budget=%llu, frame_cycle=%llu, rt_flag=%d", + clk_info_v2->budget_ns, clk_info_v2->frame_cycles, + clk_info_v2->rt_flag); + break; + + case CAM_ICP_CMD_GENERIC_BLOB_CFG_IO: + CAM_DBG(CAM_ICP, "CAM_ICP_CMD_GENERIC_BLOB_CFG_IO"); + pResource = *((uint32_t *)blob_data); + if (copy_from_user(&ctx_data->icp_dev_io_info, + (void __user *)pResource, + sizeof(struct cam_icp_acquire_dev_info))) { + CAM_ERR(CAM_ICP, "Failed in copy from user"); + return -EFAULT; + } + CAM_DBG(CAM_ICP, "buf handle %d", + ctx_data->icp_dev_io_info.io_config_cmd_handle); + rc = cam_mem_get_io_buf( + ctx_data->icp_dev_io_info.io_config_cmd_handle, + icp_hw_mgr.iommu_hdl, + blob->io_buf_addr, &io_buf_size); + if (rc) + CAM_ERR(CAM_ICP, "Failed in blob update"); + else + CAM_DBG(CAM_ICP, "io buf addr %llu", + *blob->io_buf_addr); + break; + + case CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_MAP: + cmd_mem_regions = + (struct cam_cmd_mem_regions *)blob_data; + if (cmd_mem_regions->num_regions <= 0) { + rc = -EINVAL; + CAM_ERR(CAM_ICP, + "Invalid number of regions for FW map %u", + cmd_mem_regions->num_regions); + } else { + CAM_DBG(CAM_ICP, + "Processing blob for mapping %u regions", + cmd_mem_regions->num_regions); + rc = cam_icp_process_stream_settings(ctx_data, + cmd_mem_regions, true); + } + break; + + case CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_UNMAP: + cmd_mem_regions = + (struct cam_cmd_mem_regions *)blob_data; + if (cmd_mem_regions->num_regions <= 0) { + rc = -EINVAL; + CAM_ERR(CAM_ICP, + "Invalid number of regions for FW unmap %u", + cmd_mem_regions->num_regions); + } else { + CAM_DBG(CAM_ICP, + "Processing blob for unmapping %u regions", + cmd_mem_regions->num_regions); + rc = cam_icp_process_stream_settings(ctx_data, + cmd_mem_regions, false); + } + break; + + default: + CAM_WARN(CAM_ICP, "Invalid blob type %d", blob_type); + break; + } + return rc; +} + +static int cam_icp_process_generic_cmd_buffer( + struct cam_packet *packet, + struct cam_icp_hw_ctx_data *ctx_data, + int32_t index, + uint64_t *io_buf_addr) +{ + int i, rc = 0; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct icp_cmd_generic_blob cmd_generic_blob; + + cmd_generic_blob.ctx = ctx_data; + cmd_generic_blob.frame_info_idx = index; + cmd_generic_blob.io_buf_addr = io_buf_addr; + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + for (i = 0; i < packet->num_cmd_buf; i++) { + if (!cmd_desc[i].length) + continue; + + if (cmd_desc[i].meta_data != CAM_ICP_CMD_META_GENERIC_BLOB) + continue; + + rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[i], + cam_icp_packet_generic_blob_handler, &cmd_generic_blob); + if (rc) + CAM_ERR(CAM_ICP, "Failed in processing blobs %d", rc); + } + + return rc; +} + +static int cam_icp_mgr_process_cfg_io_cmd( + struct cam_icp_hw_ctx_data *ctx_data, + struct hfi_cmd_ipebps_async *ioconfig_cmd, + uint64_t request_id, + uint64_t io_config) +{ + ioconfig_cmd->size = sizeof(struct hfi_cmd_ipebps_async); + ioconfig_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT; + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO; + else + ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO; + + ioconfig_cmd->num_fw_handles = 1; + ioconfig_cmd->fw_handles[0] = ctx_data->fw_handle; + ioconfig_cmd->payload.indirect = io_config; + ioconfig_cmd->user_data1 = PTR_TO_U64(ctx_data); + ioconfig_cmd->user_data2 = request_id; + + return 0; +} + +static int cam_icp_mgr_update_hfi_frame_process( + struct cam_icp_hw_ctx_data *ctx_data, + struct cam_packet *packet, + struct cam_hw_prepare_update_args *prepare_args, + int32_t *idx) +{ + int32_t index, rc; + struct hfi_cmd_ipebps_async *hfi_cmd = NULL; + + index = find_first_zero_bit(ctx_data->hfi_frame_process.bitmap, + ctx_data->hfi_frame_process.bits); + if (index < 0 || index >= CAM_FRAME_CMD_MAX) { + CAM_ERR(CAM_ICP, "request idx is wrong: %d", index); + return -EINVAL; + } + set_bit(index, ctx_data->hfi_frame_process.bitmap); + + ctx_data->hfi_frame_process.request_id[index] = + packet->header.request_id; + ctx_data->hfi_frame_process.frame_info[index].request_id = + packet->header.request_id; + ctx_data->hfi_frame_process.frame_info[index].io_config = 0; + rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index, + &ctx_data->hfi_frame_process.frame_info[index].io_config); + if (rc) { + clear_bit(index, ctx_data->hfi_frame_process.bitmap); + ctx_data->hfi_frame_process.request_id[index] = -1; + return rc; + } + + if (ctx_data->hfi_frame_process.frame_info[index].io_config) { + hfi_cmd = (struct hfi_cmd_ipebps_async *) + &ctx_data->hfi_frame_process.frame_info[index].hfi_cfg_io_cmd; + rc = cam_icp_mgr_process_cfg_io_cmd(ctx_data, hfi_cmd, + packet->header.request_id, + ctx_data->hfi_frame_process.frame_info[index].io_config); + } + *idx = index; + + return rc; +} + +static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + uint64_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_ICP, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_ICP, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get src buf address fail"); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_ICP, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_ICP, + "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], + io_cfg[i].mem_handle[j]); + + iova_addr += io_cfg[i].offsets[j]; + + } + } +} + +static int cam_icp_mgr_config_stream_settings( + void *hw_mgr_priv, void *hw_stream_settings) +{ + int rc = 0; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct cam_packet *packet = NULL; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct icp_cmd_generic_blob cmd_generic_blob; + struct cam_hw_stream_setttings *config_args = + hw_stream_settings; + + if ((!hw_stream_settings) || + (!hw_mgr) || (!config_args->packet)) { + CAM_ERR(CAM_ICP, "Invalid input arguments"); + return -EINVAL; + } + + ctx_data = config_args->ctxt_to_hw_map; + mutex_lock(&ctx_data->ctx_mutex); + packet = config_args->packet; + + cmd_generic_blob.ctx = ctx_data; + cmd_generic_blob.frame_info_idx = -1; + cmd_generic_blob.io_buf_addr = NULL; + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + + if (!cmd_desc[0].length || + cmd_desc[0].meta_data != CAM_ICP_CMD_META_GENERIC_BLOB) { + CAM_ERR(CAM_ICP, "Invalid cmd buffer length/metadata"); + rc = -EINVAL; + goto end; + } + + rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[0], + cam_icp_packet_generic_blob_handler, &cmd_generic_blob); + if (rc) + CAM_ERR(CAM_ICP, "Failed in processing cmd mem blob %d", rc); + +end: + mutex_unlock(&ctx_data->ctx_mutex); + return rc; +} + +static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv, + void *prepare_hw_update_args) +{ + int rc = 0; + int32_t idx; + uint32_t fw_cmd_buf_iova_addr; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct cam_packet *packet = NULL; + struct hfi_cmd_ipebps_async *hfi_cmd = NULL; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_prepare_update_args *prepare_args = + prepare_hw_update_args; + + if ((!prepare_args) || (!hw_mgr) || (!prepare_args->packet)) { + CAM_ERR(CAM_ICP, "Invalid args"); + return -EINVAL; + } + + ctx_data = prepare_args->ctxt_to_hw_map; + mutex_lock(&ctx_data->ctx_mutex); + if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_ICP, "ctx id: %u is not in use", + ctx_data->ctx_id); + return -EINVAL; + } + + 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); + return rc; + } + + rc = cam_icp_mgr_process_cmd_desc(hw_mgr, packet, + ctx_data, &fw_cmd_buf_iova_addr); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + return rc; + } + + prepare_args->pf_data->packet = packet; + + CAM_DBG(CAM_REQ, "req id = %lld for ctx = %u", + packet->header.request_id, ctx_data->ctx_id); + /* Update Buffer Address from handles and patch information */ + rc = cam_packet_util_process_patches(packet, hw_mgr->iommu_hdl, + hw_mgr->iommu_sec_hdl); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + return rc; + } + + rc = cam_icp_mgr_update_hfi_frame_process(ctx_data, packet, + prepare_args, &idx); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + return rc; + } + + rc = cam_icp_mgr_process_io_cfg(hw_mgr, ctx_data, + packet, prepare_args, idx); + if (rc) { + if (ctx_data->hfi_frame_process.in_resource[idx] > 0) + cam_sync_destroy( + ctx_data->hfi_frame_process.in_resource[idx]); + clear_bit(idx, ctx_data->hfi_frame_process.bitmap); + ctx_data->hfi_frame_process.request_id[idx] = -1; + mutex_unlock(&ctx_data->ctx_mutex); + return rc; + } + + hfi_cmd = (struct hfi_cmd_ipebps_async *) + &ctx_data->hfi_frame_process.hfi_frame_cmd[idx]; + cam_icp_mgr_prepare_frame_process_cmd( + ctx_data, hfi_cmd, packet->header.request_id, + fw_cmd_buf_iova_addr); + + prepare_args->num_hw_update_entries = 1; + prepare_args->hw_update_entries[0].addr = (uintptr_t)hfi_cmd; + prepare_args->priv = &ctx_data->hfi_frame_process.frame_info[idx]; + + CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u", + packet->header.request_id, ctx_data->ctx_id); + mutex_unlock(&ctx_data->ctx_mutex); + return rc; +} + +static int cam_icp_mgr_send_abort_status(struct cam_icp_hw_ctx_data *ctx_data) +{ + struct hfi_frame_process_info *hfi_frame_process; + int idx; + + mutex_lock(&ctx_data->ctx_mutex); + hfi_frame_process = &ctx_data->hfi_frame_process; + for (idx = 0; idx < CAM_FRAME_CMD_MAX; idx++) { + if (!hfi_frame_process->request_id[idx]) + continue; + + ctx_data->ctxt_event_cb(ctx_data->context_priv, true, + &hfi_frame_process->request_id[idx]); + + /* now release memory for hfi frame process command */ + hfi_frame_process->request_id[idx] = 0; + if (ctx_data->hfi_frame_process.in_resource[idx] > 0) { + CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", + ctx_data->hfi_frame_process.in_resource[idx]); + cam_sync_destroy( + ctx_data->hfi_frame_process.in_resource[idx]); + ctx_data->hfi_frame_process.in_resource[idx] = 0; + } + clear_bit(idx, ctx_data->hfi_frame_process.bitmap); + } + mutex_unlock(&ctx_data->ctx_mutex); + return 0; +} + +static int cam_icp_mgr_delete_sync(void *priv, void *data) +{ + struct hfi_cmd_work_data *task_data = NULL; + struct cam_icp_hw_ctx_data *ctx_data; + struct hfi_frame_process_info *hfi_frame_process; + int idx; + + if (!data || !priv) { + CAM_ERR(CAM_ICP, "Invalid params%pK %pK", data, priv); + return -EINVAL; + } + + task_data = (struct hfi_cmd_work_data *)data; + ctx_data = task_data->data; + + if (!ctx_data) { + CAM_ERR(CAM_ICP, "Null Context"); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + hfi_frame_process = &ctx_data->hfi_frame_process; + for (idx = 0; idx < CAM_FRAME_CMD_MAX; idx++) { + if (!hfi_frame_process->in_free_resource[idx]) + continue; + //cam_sync_destroy( + //ctx_data->hfi_frame_process.in_free_resource[idx]); + ctx_data->hfi_frame_process.in_resource[idx] = 0; + } + mutex_unlock(&ctx_data->ctx_mutex); + return 0; +} + +static int cam_icp_mgr_delete_sync_obj(struct cam_icp_hw_ctx_data *ctx_data) +{ + int rc = 0; + struct crm_workq_task *task; + struct hfi_cmd_work_data *task_data; + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) { + CAM_ERR(CAM_ICP, "no empty task"); + return -ENOMEM; + } + + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)ctx_data; + task_data->request_id = 0; + task_data->type = ICP_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_icp_mgr_delete_sync; + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + + return rc; +} + +static int cam_icp_mgr_flush_all(struct cam_icp_hw_ctx_data *ctx_data, + struct cam_hw_flush_args *flush_args) +{ + struct hfi_frame_process_info *hfi_frame_process; + int idx; + bool clear_in_resource = false; + + hfi_frame_process = &ctx_data->hfi_frame_process; + for (idx = 0; idx < CAM_FRAME_CMD_MAX; idx++) { + if (!hfi_frame_process->request_id[idx]) + continue; + + /* now release memory for hfi frame process command */ + hfi_frame_process->request_id[idx] = 0; + if (ctx_data->hfi_frame_process.in_resource[idx] > 0) { + ctx_data->hfi_frame_process.in_free_resource[idx] = + ctx_data->hfi_frame_process.in_resource[idx]; + ctx_data->hfi_frame_process.in_resource[idx] = 0; + } + clear_bit(idx, ctx_data->hfi_frame_process.bitmap); + clear_in_resource = true; + } + + if (clear_in_resource) + cam_icp_mgr_delete_sync_obj(ctx_data); + + return 0; +} + +static int cam_icp_mgr_flush_req(struct cam_icp_hw_ctx_data *ctx_data, + struct cam_hw_flush_args *flush_args) +{ + int64_t request_id; + struct hfi_frame_process_info *hfi_frame_process; + int idx; + bool clear_in_resource = false; + + hfi_frame_process = &ctx_data->hfi_frame_process; + request_id = *(int64_t *)flush_args->flush_req_pending[0]; + for (idx = 0; idx < CAM_FRAME_CMD_MAX; idx++) { + if (!hfi_frame_process->request_id[idx]) + continue; + + if (hfi_frame_process->request_id[idx] != request_id) + continue; + + /* now release memory for hfi frame process command */ + hfi_frame_process->request_id[idx] = 0; + if (ctx_data->hfi_frame_process.in_resource[idx] > 0) { + ctx_data->hfi_frame_process.in_free_resource[idx] = + ctx_data->hfi_frame_process.in_resource[idx]; + ctx_data->hfi_frame_process.in_resource[idx] = 0; + } + clear_bit(idx, ctx_data->hfi_frame_process.bitmap); + clear_in_resource = true; + } + + if (clear_in_resource) + cam_icp_mgr_delete_sync_obj(ctx_data); + + return 0; +} + +static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) +{ + struct cam_hw_flush_args *flush_args = hw_flush_args; + struct cam_icp_hw_ctx_data *ctx_data; + struct cam_icp_hw_mgr *hw_mgr = hw_priv; + + if ((!hw_priv) || (!hw_flush_args)) { + CAM_ERR(CAM_ICP, "Input params are Null:"); + return -EINVAL; + } + + ctx_data = flush_args->ctxt_to_hw_map; + if (!ctx_data) { + CAM_ERR(CAM_ICP, "Ctx data is NULL"); + return -EINVAL; + } + + if ((flush_args->flush_type >= CAM_FLUSH_TYPE_MAX) || + (flush_args->flush_type < CAM_FLUSH_TYPE_REQ)) { + CAM_ERR(CAM_ICP, "Invalid lush type: %d", + flush_args->flush_type); + return -EINVAL; + } + + CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d", + ctx_data->ctx_id, flush_args->flush_type); + + switch (flush_args->flush_type) { + case CAM_FLUSH_TYPE_ALL: + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (!atomic_read(&hw_mgr->recovery) + && flush_args->num_req_active) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + cam_icp_mgr_abort_handle(ctx_data); + } else { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + } + mutex_lock(&ctx_data->ctx_mutex); + cam_icp_mgr_flush_all(ctx_data, flush_args); + mutex_unlock(&ctx_data->ctx_mutex); + break; + case CAM_FLUSH_TYPE_REQ: + mutex_lock(&ctx_data->ctx_mutex); + if (flush_args->num_req_active) { + CAM_ERR(CAM_ICP, "Flush request is not supported"); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + if (flush_args->num_req_pending) + cam_icp_mgr_flush_req(ctx_data, flush_args); + mutex_unlock(&ctx_data->ctx_mutex); + break; + default: + CAM_ERR(CAM_ICP, "Invalid flush type: %d", + flush_args->flush_type); + return -EINVAL; + } + + return 0; +} + +static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) +{ + int rc = 0; + int ctx_id = 0; + struct cam_hw_release_args *release_hw = release_hw_args; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + + if (!release_hw || !hw_mgr) { + CAM_ERR(CAM_ICP, "Invalid args: %pK %pK", release_hw, hw_mgr); + return -EINVAL; + } + + CAM_DBG(CAM_ICP, "Enter recovery set %d", + atomic_read(&hw_mgr->recovery)); + ctx_data = release_hw->ctxt_to_hw_map; + if (!ctx_data) { + CAM_ERR(CAM_ICP, "NULL ctx data"); + return -EINVAL; + } + + ctx_id = ctx_data->ctx_id; + if (ctx_id < 0 || ctx_id >= CAM_ICP_CTX_MAX) { + CAM_ERR(CAM_ICP, "Invalid ctx id: %d", ctx_id); + return -EINVAL; + } + + mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + if (hw_mgr->ctx_data[ctx_id].state != CAM_ICP_CTX_STATE_ACQUIRED) { + CAM_DBG(CAM_ICP, "ctx is not in use: %d", ctx_id); + mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + return -EINVAL; + } + mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (!atomic_read(&hw_mgr->recovery) && release_hw->active_req) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + cam_icp_mgr_abort_handle(ctx_data); + cam_icp_mgr_send_abort_status(ctx_data); + } else { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + rc = cam_icp_mgr_release_ctx(hw_mgr, ctx_id); + if (!hw_mgr->ctxt_cnt) { + CAM_DBG(CAM_ICP, "Last Release"); + cam_icp_mgr_icp_power_collapse(hw_mgr); + cam_icp_hw_mgr_reset_clk_info(hw_mgr); + rc = cam_ipe_bps_deint(hw_mgr); + } + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + if ((!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)) + cam_icp_device_timer_stop(hw_mgr); + + CAM_DBG(CAM_ICP, "Release done for ctx_id %d", ctx_id); + return rc; +} + +static int cam_icp_mgr_create_handle(uint32_t dev_type, + struct cam_icp_hw_ctx_data *ctx_data) +{ + struct hfi_cmd_create_handle create_handle; + struct hfi_cmd_work_data *task_data; + unsigned long rem_jiffies; + int timeout = 5000; + struct crm_workq_task *task; + int rc = 0; + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) + return -ENOMEM; + + create_handle.size = sizeof(struct hfi_cmd_create_handle); + create_handle.pkt_type = HFI_CMD_IPEBPS_CREATE_HANDLE; + create_handle.handle_type = dev_type; + create_handle.user_data1 = PTR_TO_U64(ctx_data); + reinit_completion(&ctx_data->wait_complete); + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)&create_handle; + task_data->request_id = 0; + task_data->type = ICP_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_icp_mgr_process_cmd; + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + if (rc) + return rc; + + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + 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(); + } + + if (ctx_data->fw_handle == 0) { + CAM_ERR(CAM_ICP, "Invalid handle created"); + rc = -EINVAL; + } + + return rc; +} + +static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data) +{ + struct hfi_cmd_ping_pkt ping_pkt; + struct hfi_cmd_work_data *task_data; + unsigned long rem_jiffies; + int timeout = 5000; + struct crm_workq_task *task; + int rc = 0; + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) { + CAM_ERR(CAM_ICP, "No free task to send ping command"); + return -ENOMEM; + } + + ping_pkt.size = sizeof(struct hfi_cmd_ping_pkt); + ping_pkt.pkt_type = HFI_CMD_SYS_PING; + ping_pkt.user_data = PTR_TO_U64(ctx_data); + init_completion(&ctx_data->wait_complete); + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)&ping_pkt; + task_data->request_id = 0; + task_data->type = ICP_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_icp_mgr_process_cmd; + + rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + if (rc) + return rc; + + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + 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(); + } + + return rc; +} + +static int cam_icp_get_acquire_info(struct cam_icp_hw_mgr *hw_mgr, + struct cam_hw_acquire_args *args, + struct cam_icp_hw_ctx_data *ctx_data) +{ + int i; + int acquire_size; + struct cam_icp_acquire_dev_info icp_dev_acquire_info; + struct cam_icp_res_info *p_icp_out = NULL; + + if (copy_from_user(&icp_dev_acquire_info, + (void __user *)args->acquire_info, + sizeof(struct cam_icp_acquire_dev_info))) { + CAM_ERR(CAM_ICP, "Failed in acquire"); + return -EFAULT; + } + + if (icp_dev_acquire_info.secure_mode > CAM_SECURE_MODE_SECURE) { + CAM_ERR(CAM_ICP, "Invalid mode:%d", + icp_dev_acquire_info.secure_mode); + return -EINVAL; + } + + if ((icp_dev_acquire_info.num_out_res > ICP_MAX_OUTPUT_SUPPORTED) || + (icp_dev_acquire_info.num_out_res <= 0)) { + CAM_ERR(CAM_ICP, "Invalid num of out resources: %u", + icp_dev_acquire_info.num_out_res); + return -EINVAL; + } + + if (icp_dev_acquire_info.dev_type >= CAM_ICP_RES_TYPE_MAX) { + CAM_ERR(CAM_ICP, "Invalid device type: %d", + icp_dev_acquire_info.dev_type); + return -EFAULT; + } + + acquire_size = sizeof(struct cam_icp_acquire_dev_info) + + ((icp_dev_acquire_info.num_out_res - 1) * + sizeof(struct cam_icp_res_info)); + ctx_data->icp_dev_acquire_info = kzalloc(acquire_size, GFP_KERNEL); + if (!ctx_data->icp_dev_acquire_info) + return -ENOMEM; + + if (copy_from_user(ctx_data->icp_dev_acquire_info, + (void __user *)args->acquire_info, acquire_size)) { + CAM_ERR(CAM_ICP, "Failed in acquire: size = %d", acquire_size); + kfree(ctx_data->icp_dev_acquire_info); + ctx_data->icp_dev_acquire_info = NULL; + return -EFAULT; + } + + CAM_DBG(CAM_ICP, "%x %x %x %x %x %x %x", + ctx_data->icp_dev_acquire_info->dev_type, + ctx_data->icp_dev_acquire_info->in_res.format, + ctx_data->icp_dev_acquire_info->in_res.width, + ctx_data->icp_dev_acquire_info->in_res.height, + ctx_data->icp_dev_acquire_info->in_res.fps, + ctx_data->icp_dev_acquire_info->num_out_res, + ctx_data->icp_dev_acquire_info->scratch_mem_size); + + p_icp_out = ctx_data->icp_dev_acquire_info->out_res; + for (i = 0; i < icp_dev_acquire_info.num_out_res; i++) + CAM_DBG(CAM_ICP, "out[i] %x %x %x %x", + p_icp_out[i].format, + p_icp_out[i].width, + p_icp_out[i].height, + p_icp_out[i].fps); + + return 0; +} + +static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) +{ + int rc = 0, bitmap_size = 0; + uint32_t ctx_id = 0; + uint64_t io_buf_addr; + size_t io_buf_size; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_icp_hw_ctx_data *ctx_data = NULL; + struct cam_hw_acquire_args *args = acquire_hw_args; + struct cam_icp_acquire_dev_info *icp_dev_acquire_info; + struct cam_cmd_mem_regions cmd_mem_region; + + if ((!hw_mgr_priv) || (!acquire_hw_args)) { + CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", hw_mgr_priv, + acquire_hw_args); + return -EINVAL; + } + + if (args->num_acq > 1) { + CAM_ERR(CAM_ICP, "number of resources are wrong: %u", + args->num_acq); + return -EINVAL; + } + + CAM_DBG(CAM_ICP, "ENTER"); + mutex_lock(&hw_mgr->hw_mgr_mutex); + ctx_id = cam_icp_mgr_get_free_ctx(hw_mgr); + if (ctx_id >= CAM_ICP_CTX_MAX) { + CAM_ERR(CAM_ICP, "No free ctx space in hw_mgr"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -ENOSPC; + } + ctx_data = &hw_mgr->ctx_data[ctx_id]; + ctx_data->ctx_id = ctx_id; + + mutex_lock(&ctx_data->ctx_mutex); + rc = cam_icp_get_acquire_info(hw_mgr, args, ctx_data); + if (rc) + goto acquire_info_failed; + + icp_dev_acquire_info = ctx_data->icp_dev_acquire_info; + + CAM_DBG(CAM_ICP, "acquire io buf handle %d", + icp_dev_acquire_info->io_config_cmd_handle); + rc = cam_mem_get_io_buf( + icp_dev_acquire_info->io_config_cmd_handle, + hw_mgr->iommu_hdl, + &io_buf_addr, &io_buf_size); + if (rc) { + CAM_ERR(CAM_ICP, "unable to get src buf info from io desc"); + goto get_io_buf_failed; + } + + CAM_DBG(CAM_ICP, "hdl: %d, addr: %pK, size: %zu", + icp_dev_acquire_info->io_config_cmd_handle, + (void *)io_buf_addr, io_buf_size); + + if (!hw_mgr->ctxt_cnt) { + rc = cam_icp_clk_info_init(hw_mgr, ctx_data); + if (rc) + goto get_io_buf_failed; + + rc = cam_icp_mgr_icp_resume(hw_mgr); + if (rc) + goto get_io_buf_failed; + + if (icp_hw_mgr.a5_debug_type) + hfi_set_debug_level(icp_hw_mgr.a5_debug_type, + icp_hw_mgr.a5_dbg_lvl); + + hfi_set_fw_dump_level(icp_hw_mgr.a5_fw_dump_lvl); + + rc = cam_icp_send_ubwc_cfg(hw_mgr); + if (rc) + goto ubwc_cfg_failed; + } + + + rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data); + if (rc) + goto ipe_bps_resume_failed; + + rc = cam_icp_mgr_send_ping(ctx_data); + if (rc) { + CAM_ERR(CAM_ICP, "ping ack not received"); + goto send_ping_failed; + } + CAM_DBG(CAM_ICP, "ping ack received"); + + rc = cam_icp_mgr_create_handle(icp_dev_acquire_info->dev_type, + ctx_data); + if (rc) { + CAM_ERR(CAM_ICP, "create handle failed"); + goto create_handle_failed; + } + + cmd_mem_region.num_regions = 1; + cmd_mem_region.map_info_array[0].mem_handle = + icp_dev_acquire_info->io_config_cmd_handle; + cmd_mem_region.map_info_array[0].offset = 0; + cmd_mem_region.map_info_array[0].size = + icp_dev_acquire_info->io_config_cmd_size; + cmd_mem_region.map_info_array[0].flags = 0; + + rc = cam_icp_process_stream_settings(ctx_data, + &cmd_mem_region, true); + if (rc) { + CAM_ERR(CAM_ICP, + "sending config io mapping failed rc %d", rc); + goto send_map_info_failed; + } + + rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr); + if (rc) { + CAM_ERR(CAM_ICP, "IO Config command failed %d", rc); + goto ioconfig_failed; + } + + rc = cam_icp_process_stream_settings(ctx_data, + &cmd_mem_region, false); + if (rc) { + CAM_ERR(CAM_ICP, + "sending config io unmapping failed %d", rc); + goto send_map_info_failed; + } + + ctx_data->context_priv = args->context_data; + args->ctxt_to_hw_map = ctx_data; + + bitmap_size = BITS_TO_LONGS(CAM_FRAME_CMD_MAX) * sizeof(long); + ctx_data->hfi_frame_process.bitmap = + kzalloc(bitmap_size, GFP_KERNEL); + if (!ctx_data->hfi_frame_process.bitmap) + goto ioconfig_failed; + + ctx_data->hfi_frame_process.bits = bitmap_size * BITS_PER_BYTE; + hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb; + icp_dev_acquire_info->scratch_mem_size = ctx_data->scratch_mem_size; + + if (copy_to_user((void __user *)args->acquire_info, + icp_dev_acquire_info, sizeof(struct cam_icp_acquire_dev_info))) + goto copy_to_user_failed; + + cam_icp_ctx_clk_info_init(ctx_data); + ctx_data->state = CAM_ICP_CTX_STATE_ACQUIRED; + mutex_unlock(&ctx_data->ctx_mutex); + CAM_DBG(CAM_ICP, "scratch size = %x fw_handle = %x", + (unsigned int)icp_dev_acquire_info->scratch_mem_size, + (unsigned int)ctx_data->fw_handle); + /* Start device timer*/ + if (((hw_mgr->bps_ctxt_cnt == 1) || (hw_mgr->ipe_ctxt_cnt == 1))) + cam_icp_device_timer_start(hw_mgr); + /* Start context timer*/ + cam_icp_ctx_timer_start(ctx_data); + hw_mgr->ctxt_cnt++; + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_DBG(CAM_ICP, "Acquire Done for ctx_id %u dev name %s dev type %d", + ctx_data->ctx_id, cam_icp_dev_type_to_name( + icp_dev_acquire_info->dev_type), + icp_dev_acquire_info->dev_type); + + return 0; + +copy_to_user_failed: + kfree(ctx_data->hfi_frame_process.bitmap); + ctx_data->hfi_frame_process.bitmap = NULL; +ioconfig_failed: + cam_icp_process_stream_settings(ctx_data, + &cmd_mem_region, false); +send_map_info_failed: + cam_icp_mgr_destroy_handle(ctx_data); +create_handle_failed: +send_ping_failed: + cam_icp_mgr_ipe_bps_power_collapse(hw_mgr, ctx_data, 0); +ipe_bps_resume_failed: +ubwc_cfg_failed: + if (!hw_mgr->ctxt_cnt) + cam_icp_mgr_icp_power_collapse(hw_mgr); +get_io_buf_failed: + kfree(hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info); + 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; +} + +static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) +{ + int rc = 0; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query_cap = hw_caps_args; + + if ((!hw_mgr_priv) || (!hw_caps_args)) { + CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", + hw_mgr_priv, hw_caps_args); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (copy_from_user(&icp_hw_mgr.icp_caps, + u64_to_user_ptr(query_cap->caps_handle), + sizeof(struct cam_icp_query_cap_cmd))) { + CAM_ERR(CAM_ICP, "copy_from_user failed"); + rc = -EFAULT; + goto end; + } + + rc = hfi_get_hw_caps(&icp_hw_mgr.icp_caps); + if (rc) + goto end; + + icp_hw_mgr.icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl; + icp_hw_mgr.icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl; + + if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), + &icp_hw_mgr.icp_caps, sizeof(struct cam_icp_query_cap_cmd))) { + CAM_ERR(CAM_ICP, "copy_to_user failed"); + rc = -EFAULT; + } +end: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_icp_mgr_alloc_devs(struct device_node *of_node) +{ + int rc; + uint32_t num_dev; + + rc = of_property_read_u32(of_node, "num-a5", &num_dev); + if (rc) { + CAM_ERR(CAM_ICP, "getting num of a5 failed"); + goto num_a5_failed; + } + + icp_hw_mgr.devices[CAM_ICP_DEV_A5] = kzalloc( + sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + if (!icp_hw_mgr.devices[CAM_ICP_DEV_A5]) { + rc = -ENOMEM; + goto num_a5_failed; + } + + rc = of_property_read_u32(of_node, "num-ipe", &num_dev); + if (rc) { + CAM_ERR(CAM_ICP, "getting number of ipe dev nodes failed"); + goto num_ipe_failed; + } + + if (!icp_hw_mgr.ipe1_enable) + num_dev = 1; + + icp_hw_mgr.devices[CAM_ICP_DEV_IPE] = kcalloc(num_dev, + sizeof(struct cam_hw_intf *), GFP_KERNEL); + if (!icp_hw_mgr.devices[CAM_ICP_DEV_IPE]) { + rc = -ENOMEM; + goto num_ipe_failed; + } + + rc = of_property_read_u32(of_node, "num-bps", &num_dev); + if (rc) { + CAM_ERR(CAM_ICP, "read num bps devices failed"); + goto num_bps_failed; + } + icp_hw_mgr.devices[CAM_ICP_DEV_BPS] = kcalloc(num_dev, + sizeof(struct cam_hw_intf *), GFP_KERNEL); + if (!icp_hw_mgr.devices[CAM_ICP_DEV_BPS]) { + rc = -ENOMEM; + goto num_bps_failed; + } + + icp_hw_mgr.ipe_bps_pc_flag = of_property_read_bool(of_node, + "ipe_bps_pc_en"); + + icp_hw_mgr.icp_pc_flag = of_property_read_bool(of_node, + "icp_pc_en"); + + return 0; +num_bps_failed: + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_IPE]); +num_ipe_failed: + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_A5]); +num_a5_failed: + return rc; +} + +static int cam_icp_mgr_init_devs(struct device_node *of_node) +{ + int rc = 0; + int count, i; + const char *name = NULL; + struct device_node *child_node = NULL; + struct platform_device *child_pdev = NULL; + struct cam_hw_intf *child_dev_intf = NULL; + + rc = cam_icp_mgr_alloc_devs(of_node); + if (rc) + return rc; + + count = of_property_count_strings(of_node, "compat-hw-name"); + if (!count) { + CAM_ERR(CAM_ICP, "no compat hw found in dev tree, cnt = %d", + count); + rc = -EINVAL; + goto compat_hw_name_failed; + } + + for (i = 0; i < count; i++) { + rc = of_property_read_string_index(of_node, "compat-hw-name", + i, &name); + if (rc) { + CAM_ERR(CAM_ICP, "getting dev object name failed"); + goto compat_hw_name_failed; + } + + child_node = of_find_node_by_name(NULL, name); + if (!child_node) { + CAM_ERR(CAM_ICP, "Cannot find node in dtsi %s", name); + rc = -ENODEV; + goto compat_hw_name_failed; + } + + child_pdev = of_find_device_by_node(child_node); + if (!child_pdev) { + CAM_ERR(CAM_ICP, "failed to find device on bus %s", + child_node->name); + rc = -ENODEV; + of_node_put(child_node); + goto compat_hw_name_failed; + } + + child_dev_intf = (struct cam_hw_intf *)platform_get_drvdata( + child_pdev); + if (!child_dev_intf) { + CAM_ERR(CAM_ICP, "no child device"); + of_node_put(child_node); + if (!icp_hw_mgr.ipe1_enable) + continue; + goto compat_hw_name_failed; + } + icp_hw_mgr.devices[child_dev_intf->hw_type] + [child_dev_intf->hw_idx] = child_dev_intf; + + if (!child_dev_intf->hw_ops.process_cmd) + goto compat_hw_name_failed; + + of_node_put(child_node); + } + + icp_hw_mgr.a5_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_A5][0]; + icp_hw_mgr.bps_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_BPS][0]; + icp_hw_mgr.ipe0_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_IPE][0]; + if (icp_hw_mgr.ipe1_enable) + icp_hw_mgr.ipe1_dev_intf = + icp_hw_mgr.devices[CAM_ICP_DEV_IPE][1]; + + return 0; +compat_hw_name_failed: + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_BPS]); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_IPE]); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_A5]); + return rc; +} + +static int cam_icp_mgr_create_wq(void) +{ + int rc; + int i; + + rc = cam_req_mgr_workq_create("icp_command_queue", ICP_WORKQ_NUM_TASK, + &icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ, + 0); + if (rc) { + CAM_ERR(CAM_ICP, "unable to create a command worker"); + goto cmd_work_failed; + } + + rc = cam_req_mgr_workq_create("icp_message_queue", ICP_WORKQ_NUM_TASK, + &icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_ICP, "unable to create a message worker"); + goto msg_work_failed; + } + + rc = cam_req_mgr_workq_create("icp_timer_queue", ICP_WORKQ_NUM_TASK, + &icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_ICP, "unable to create a timer worker"); + goto timer_work_failed; + } + + icp_hw_mgr.cmd_work_data = + kzalloc(sizeof(struct hfi_cmd_work_data) * ICP_WORKQ_NUM_TASK, + GFP_KERNEL); + if (!icp_hw_mgr.cmd_work_data) + goto cmd_work_data_failed; + + icp_hw_mgr.msg_work_data = + kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, + GFP_KERNEL); + if (!icp_hw_mgr.msg_work_data) + goto msg_work_data_failed; + + icp_hw_mgr.timer_work_data = + kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, + GFP_KERNEL); + if (!icp_hw_mgr.timer_work_data) + goto timer_work_data_failed; + + rc = cam_icp_hw_mgr_create_debugfs_entry(); + if (rc) + goto debugfs_create_failed; + + for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) + icp_hw_mgr.msg_work->task.pool[i].payload = + &icp_hw_mgr.msg_work_data[i]; + + for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) + icp_hw_mgr.cmd_work->task.pool[i].payload = + &icp_hw_mgr.cmd_work_data[i]; + + for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) + icp_hw_mgr.timer_work->task.pool[i].payload = + &icp_hw_mgr.timer_work_data[i]; + return 0; + +debugfs_create_failed: + kfree(icp_hw_mgr.timer_work_data); +timer_work_data_failed: + kfree(icp_hw_mgr.msg_work_data); +msg_work_data_failed: + kfree(icp_hw_mgr.cmd_work_data); +cmd_work_data_failed: + cam_req_mgr_workq_destroy(&icp_hw_mgr.timer_work); +timer_work_failed: + cam_req_mgr_workq_destroy(&icp_hw_mgr.msg_work); +msg_work_failed: + cam_req_mgr_workq_destroy(&icp_hw_mgr.cmd_work); +cmd_work_failed: + return rc; +} + +static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_ICP, "Invalid arguments"); + return -EINVAL; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_icp_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->iommu_hdl, + 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"); + } + + return rc; +} + +int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, + int *iommu_hdl) +{ + int i, rc = 0; + struct cam_hw_mgr_intf *hw_mgr_intf; + struct cam_cpas_query_cap query; + uint32_t cam_caps, camera_hw_version; + + hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl; + if (!of_node || !hw_mgr_intf) { + CAM_ERR(CAM_ICP, "Invalid args of_node %pK hw_mgr %pK", + of_node, hw_mgr_intf); + return -EINVAL; + } + + hw_mgr_intf->hw_mgr_priv = &icp_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_icp_mgr_get_hw_caps; + hw_mgr_intf->hw_acquire = cam_icp_mgr_acquire_hw; + hw_mgr_intf->hw_release = cam_icp_mgr_release_hw; + hw_mgr_intf->hw_prepare_update = cam_icp_mgr_prepare_hw_update; + hw_mgr_intf->hw_config_stream_settings = + cam_icp_mgr_config_stream_settings; + hw_mgr_intf->hw_config = cam_icp_mgr_config_hw; + hw_mgr_intf->hw_open = cam_icp_mgr_hw_open_u; + hw_mgr_intf->hw_close = cam_icp_mgr_hw_close_u; + hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush; + hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd; + + icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE; + mutex_init(&icp_hw_mgr.hw_mgr_mutex); + spin_lock_init(&icp_hw_mgr.hw_mgr_lock); + + for (i = 0; i < CAM_ICP_CTX_MAX; i++) + mutex_init(&icp_hw_mgr.ctx_data[i].ctx_mutex); + + cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, &cam_caps); + cam_cpas_get_cpas_hw_version(&camera_hw_version); + + if (camera_hw_version == CAM_CPAS_TITAN_480_V100) { + if (cam_caps & CPAS_TITAN_480_IPE0_BIT) + icp_hw_mgr.ipe0_enable = true; + if (cam_caps & CPAS_BPS_BIT) + icp_hw_mgr.bps_enable = true; + } else { + if (cam_caps & CPAS_IPE0_BIT) + icp_hw_mgr.ipe0_enable = true; + if (cam_caps & CPAS_IPE1_BIT) + icp_hw_mgr.ipe1_enable = true; + if (cam_caps & CPAS_BPS_BIT) + icp_hw_mgr.bps_enable = true; + } + + rc = cam_icp_mgr_init_devs(of_node); + if (rc) + goto dev_init_failed; + + rc = cam_smmu_get_handle("icp", &icp_hw_mgr.iommu_hdl); + if (rc) { + CAM_ERR(CAM_ICP, "get mmu handle failed: %d", rc); + goto icp_get_hdl_failed; + } + + rc = cam_smmu_get_handle("cam-secure", &icp_hw_mgr.iommu_sec_hdl); + if (rc) { + CAM_ERR(CAM_ICP, "get secure mmu handle failed: %d", rc); + goto secure_hdl_failed; + } + + rc = cam_icp_mgr_create_wq(); + if (rc) + goto icp_wq_create_failed; + + if (iommu_hdl) + *iommu_hdl = icp_hw_mgr.iommu_hdl; + + init_completion(&icp_hw_mgr.a5_complete); + return rc; + +icp_wq_create_failed: + cam_smmu_destroy_handle(icp_hw_mgr.iommu_sec_hdl); + icp_hw_mgr.iommu_sec_hdl = -1; +secure_hdl_failed: + cam_smmu_destroy_handle(icp_hw_mgr.iommu_hdl); + icp_hw_mgr.iommu_hdl = -1; +icp_get_hdl_failed: + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_BPS]); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_IPE]); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_A5]); +dev_init_failed: + mutex_destroy(&icp_hw_mgr.hw_mgr_mutex); + for (i = 0; i < CAM_ICP_CTX_MAX; i++) + mutex_destroy(&icp_hw_mgr.ctx_data[i].ctx_mutex); + + return rc; +} diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h new file mode 100644 index 000000000000..3fa1ee0e0f8f --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -0,0 +1,397 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_ICP_HW_MGR_H +#define CAM_ICP_HW_MGR_H + +#include +#include +#include +#include "cam_icp_hw_intf.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" +#include "cam_a5_hw_intf.h" +#include "hfi_session_defs.h" +#include "cam_req_mgr_workq.h" +#include "cam_mem_mgr.h" +#include "cam_smmu_api.h" +#include "cam_soc_util.h" +#include "cam_req_mgr_timer.h" + +#define CAM_ICP_ROLE_PARENT 1 +#define CAM_ICP_ROLE_CHILD 2 + +#define CAM_FRAME_CMD_MAX 20 + +#define CAM_MAX_OUT_RES 6 +#define CAM_MAX_IN_RES 8 + +#define ICP_WORKQ_NUM_TASK 100 +#define ICP_WORKQ_TASK_CMD_TYPE 1 +#define ICP_WORKQ_TASK_MSG_TYPE 2 + +#define ICP_PACKET_SIZE 0 +#define ICP_PACKET_TYPE 1 +#define ICP_PACKET_OPCODE 2 +#define ICP_MAX_OUTPUT_SUPPORTED 6 + +#define ICP_FRAME_PROCESS_SUCCESS 0 +#define ICP_FRAME_PROCESS_FAILURE 1 +#define ICP_MSG_BUF_SIZE 256 +#define ICP_DBG_BUF_SIZE 102400 + +#define ICP_CLK_HW_IPE 0x0 +#define ICP_CLK_HW_BPS 0x1 +#define ICP_CLK_HW_MAX 0x2 + +#define ICP_OVER_CLK_THRESHOLD 5 + +#define CPAS_IPE0_BIT 0x1000 +#define CPAS_IPE1_BIT 0x2000 +#define CPAS_BPS_BIT 0x400 +#define CPAS_TITAN_480_IPE0_BIT 0x800 + +#define ICP_PWR_CLP_BPS 0x00000001 +#define ICP_PWR_CLP_IPE0 0x00010000 +#define ICP_PWR_CLP_IPE1 0x00020000 + +#define CAM_ICP_CTX_STATE_FREE 0x0 +#define CAM_ICP_CTX_STATE_IN_USE 0x1 +#define CAM_ICP_CTX_STATE_ACQUIRED 0x2 +#define CAM_ICP_CTX_STATE_RELEASE 0x3 + +#define CAM_ICP_CTX_MAX_CMD_BUFFERS 0x2 + +/* Current appliacble vote paths, based on number of UAPI definitions */ +#define CAM_ICP_MAX_PER_PATH_VOTES 6 + +/** + * struct icp_hfi_mem_info + * @qtbl: Memory info of queue table + * @cmd_q: Memory info of command queue + * @msg_q: Memory info of message queue + * @dbg_q: Memory info of debug queue + * @sec_heap: Memory info of secondary heap + * @fw_buf: Memory info of firmware + * @qdss_buf: Memory info of qdss + * @sfr_buf: Memory info for sfr buffer + * @shmem: Memory info for shared region + * @io_mem: Memory info for io region + */ +struct icp_hfi_mem_info { + struct cam_mem_mgr_memory_desc qtbl; + struct cam_mem_mgr_memory_desc cmd_q; + struct cam_mem_mgr_memory_desc msg_q; + struct cam_mem_mgr_memory_desc dbg_q; + struct cam_mem_mgr_memory_desc sec_heap; + struct cam_mem_mgr_memory_desc fw_buf; + struct cam_mem_mgr_memory_desc qdss_buf; + struct cam_mem_mgr_memory_desc sfr_buf; + struct cam_smmu_region_info shmem; + struct cam_smmu_region_info io_mem; +}; + +/** + * struct hfi_cmd_work_data + * @type: Task type + * @data: Pointer to command data + * @request_id: Request id + */ +struct hfi_cmd_work_data { + uint32_t type; + void *data; + int32_t request_id; +}; + +/** + * struct hfi_msg_work_data + * @type: Task type + * @data: Pointer to message data + * @irq_status: IRQ status + */ +struct hfi_msg_work_data { + uint32_t type; + void *data; + uint32_t irq_status; +}; + +/** + * struct clk_work_data + * @type: Task type + * @data: Pointer to clock info + */ +struct clk_work_data { + uint32_t type; + void *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 { + uint64_t request_id; + uint64_t io_config; + struct hfi_cmd_ipebps_async hfi_cfg_io_cmd; +}; + +/** + * struct cam_icp_clk_bw_request_v2 + * + * @budget_ns: Time required to process frame + * @frame_cycles: Frame cycles needed to process the frame + * @rt_flag: Flag to indicate real time stream + * @num_paths: Number of paths for per path bw vote + * @axi_path: Per path vote info for IPE/BPS + */ +struct cam_icp_clk_bw_req_internal_v2 { + uint64_t budget_ns; + uint32_t frame_cycles; + uint32_t rt_flag; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; +}; + +/** + * struct hfi_frame_process_info + * @hfi_frame_cmd: Frame process command info + * @bitmap: Bitmap for hfi_frame_cmd + * @bits: Used in hfi_frame_cmd bitmap + * @lock: Lock for hfi_frame_cmd + * @request_id: Request id list + * @num_out_resources: Number of out syncs + * @out_resource: Out sync info + * @fw_process_flag: Frame process flag + * @clk_info: Clock information for a request + * @clk_info_v2: Clock info for AXI bw voting v2 + * @frame_info: information needed to process request + */ +struct hfi_frame_process_info { + struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX]; + void *bitmap; + size_t bits; + struct mutex lock; + uint64_t request_id[CAM_FRAME_CMD_MAX]; + uint32_t num_out_resources[CAM_FRAME_CMD_MAX]; + uint32_t out_resource[CAM_FRAME_CMD_MAX][CAM_MAX_OUT_RES]; + uint32_t in_resource[CAM_FRAME_CMD_MAX]; + uint32_t in_free_resource[CAM_FRAME_CMD_MAX]; + uint32_t fw_process_flag[CAM_FRAME_CMD_MAX]; + struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX]; + struct cam_icp_clk_bw_req_internal_v2 clk_info_v2[CAM_FRAME_CMD_MAX]; + struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX]; +}; + +/** + * struct cam_ctx_clk_info + * @curr_fc: Context latest request frame cycles + * @rt_flag: Flag to indicate real time request + * @base_clk: Base clock to process the request + * @reserved: Reserved field + * #uncompressed_bw: Current bandwidth voting + * @compressed_bw: Current compressed bandwidth voting + * @clk_rate: Supported clock rates for the context + * @num_paths: Number of valid AXI paths + * @axi_path: ctx based per path bw vote + */ +struct cam_ctx_clk_info { + uint32_t curr_fc; + uint32_t rt_flag; + uint32_t base_clk; + uint32_t reserved; + uint64_t uncompressed_bw; + uint64_t compressed_bw; + int32_t clk_rate[CAM_MAX_VOTE]; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; +}; +/** + * struct cam_icp_hw_ctx_data + * @context_priv: Context private data + * @ctx_mutex: Mutex for context + * @fw_handle: Firmware handle + * @scratch_mem_size: Scratch memory size + * @acquire_dev_cmd: Acquire command + * @icp_dev_acquire_info: Acquire device info + * @ctxt_event_cb: Context callback function + * @state: context state + * @role: Role of a context in case of chaining + * @chain_ctx: Peer context + * @hfi_frame_process: Frame process command + * @wait_complete: Completion info + * @temp_payload: Payload for destroy handle data + * @ctx_id: Context Id + * @bw_config_version: BW config version indicator + * @clk_info: Current clock info of a context + * @watch_dog: watchdog timer handle + * @watch_dog_reset_counter: Counter for watch dog reset + * @icp_dev_io_info: io config resource + */ +struct cam_icp_hw_ctx_data { + void *context_priv; + struct mutex ctx_mutex; + uint32_t fw_handle; + uint32_t scratch_mem_size; + struct cam_acquire_dev_cmd acquire_dev_cmd; + struct cam_icp_acquire_dev_info *icp_dev_acquire_info; + cam_hw_event_cb_func ctxt_event_cb; + uint32_t state; + uint32_t role; + struct cam_icp_hw_ctx_data *chain_ctx; + struct hfi_frame_process_info hfi_frame_process; + struct completion wait_complete; + struct ipe_bps_destroy temp_payload; + uint32_t ctx_id; + uint32_t bw_config_version; + struct cam_ctx_clk_info clk_info; + struct cam_req_mgr_timer *watch_dog; + uint32_t watch_dog_reset_counter; + struct cam_icp_acquire_dev_info icp_dev_io_info; +}; + +/** + * struct icp_cmd_generic_blob + * @ctx: Current context info + * @frame_info_idx: Index used for frame process info + * @io_buf_addr: pointer to io buffer address + */ +struct icp_cmd_generic_blob { + struct cam_icp_hw_ctx_data *ctx; + uint32_t frame_info_idx; + uint64_t *io_buf_addr; +}; + +/** + * struct cam_icp_clk_info + * @base_clk: Base clock to process request + * @curr_clk: Current clock of hadrware + * @threshold: Threshold for overclk count + * @over_clked: Over clock count + * @uncompressed_bw: Current bandwidth voting + * @compressed_bw: Current compressed bandwidth voting + * @num_paths: Number of AXI vote paths + * @axi_path: Current per path bw vote info + * @hw_type: IPE/BPS device type + * @watch_dog: watchdog timer handle + * @watch_dog_reset_counter: Counter for watch dog reset + */ +struct cam_icp_clk_info { + uint32_t base_clk; + uint32_t curr_clk; + uint32_t threshold; + uint32_t over_clked; + uint64_t uncompressed_bw; + uint64_t compressed_bw; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; + uint32_t hw_type; + struct cam_req_mgr_timer *watch_dog; + uint32_t watch_dog_reset_counter; +}; + +/** + * struct cam_icp_hw_mgr + * @hw_mgr_mutex: Mutex for ICP hardware manager + * @hw_mgr_lock: Spinlock for ICP hardware manager + * @devices: Devices of ICP hardware manager + * @ctx_data: Context data + * @icp_caps: ICP capabilities + * @fw_download: Firmware download state + * @iommu_hdl: Non secure IOMMU handle + * @iommu_sec_hdl: Secure IOMMU handle + * @hfi_mem: Memory for hfi + * @cmd_work: Work queue for hfi commands + * @msg_work: Work queue for hfi messages + * @timer_work: Work queue for timer watchdog + * @msg_buf: Buffer for message data from firmware + * @dbg_buf: Buffer for debug data from firmware + * @a5_complete: Completion info + * @cmd_work_data: Pointer to command work queue task + * @msg_work_data: Pointer to message work queue task + * @timer_work_data: Pointer to timer work queue task + * @ctxt_cnt: Active context count + * @ipe_ctxt_cnt: IPE Active context count + * @bps_ctxt_cnt: BPS Active context count + * @dentry: Debugfs entry + * @a5_debug: A5 debug flag + * @icp_pc_flag: Flag to enable/disable power collapse + * @ipe_bps_pc_flag: Flag to enable/disable + * power collapse for ipe & bps + * @icp_debug_clk: Set clock based on debug value + * @icp_default_clk: Set this clok if user doesn't supply + * @clk_info: Clock info of hardware + * @secure_mode: Flag to enable/disable secure camera + * @a5_jtag_debug: entry to enable A5 JTAG debugging + * @a5_debug_type : entry to enable FW debug message/qdss + * @a5_dbg_lvl : debug level set to FW. + * @a5_fw_dump_lvl : level set for dumping the FW data + * @ipe0_enable: Flag for IPE0 + * @ipe1_enable: Flag for IPE1 + * @bps_enable: Flag for BPS + * @a5_dev_intf : Device interface for A5 + * @ipe0_dev_intf: Device interface for IPE0 + * @ipe1_dev_intf: Device interface for IPE1 + * @bps_dev_intf: Device interface for BPS + * @ipe_clk_state: IPE clock state flag + * @bps_clk_state: BPS clock state flag + * @recovery: Flag to validate if in previous session FW + * reported a fatal error or wdt. If set FW is + * re-downloaded for new camera session. + */ +struct cam_icp_hw_mgr { + struct mutex hw_mgr_mutex; + spinlock_t hw_mgr_lock; + + struct cam_hw_intf **devices[CAM_ICP_DEV_MAX]; + struct cam_icp_hw_ctx_data ctx_data[CAM_ICP_CTX_MAX]; + struct cam_icp_query_cap_cmd icp_caps; + + bool fw_download; + int32_t iommu_hdl; + int32_t iommu_sec_hdl; + struct icp_hfi_mem_info hfi_mem; + struct cam_req_mgr_core_workq *cmd_work; + struct cam_req_mgr_core_workq *msg_work; + struct cam_req_mgr_core_workq *timer_work; + uint32_t msg_buf[ICP_MSG_BUF_SIZE]; + uint32_t dbg_buf[ICP_DBG_BUF_SIZE]; + struct completion a5_complete; + struct hfi_cmd_work_data *cmd_work_data; + struct hfi_msg_work_data *msg_work_data; + struct hfi_msg_work_data *timer_work_data; + uint32_t ctxt_cnt; + uint32_t ipe_ctxt_cnt; + uint32_t bps_ctxt_cnt; + struct dentry *dentry; + bool a5_debug; + bool icp_pc_flag; + bool ipe_bps_pc_flag; + uint64_t icp_debug_clk; + uint64_t icp_default_clk; + struct cam_icp_clk_info clk_info[ICP_CLK_HW_MAX]; + bool secure_mode; + bool a5_jtag_debug; + u64 a5_debug_type; + u64 a5_dbg_lvl; + u64 a5_fw_dump_lvl; + bool ipe0_enable; + bool ipe1_enable; + bool bps_enable; + struct cam_hw_intf *a5_dev_intf; + struct cam_hw_intf *ipe0_dev_intf; + struct cam_hw_intf *ipe1_dev_intf; + struct cam_hw_intf *bps_dev_intf; + bool ipe_clk_state; + bool bps_clk_state; + atomic_t recovery; +}; + +static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args); +static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args); +static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr); +static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr); +#endif /* CAM_ICP_HW_MGR_H */ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h new file mode 100644 index 000000000000..397592a4410c --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_A5_HW_INTF_H +#define CAM_A5_HW_INTF_H + +#include +#include +#include +#include "cam_hw_mgr_intf.h" +#include "cam_icp_hw_intf.h" + +enum cam_icp_a5_cmd_type { + CAM_ICP_A5_CMD_FW_DOWNLOAD, + CAM_ICP_A5_CMD_POWER_COLLAPSE, + CAM_ICP_A5_CMD_POWER_RESUME, + CAM_ICP_A5_CMD_SET_FW_BUF, + CAM_ICP_A5_CMD_ACQUIRE, + CAM_ICP_A5_SET_IRQ_CB, + CAM_ICP_A5_TEST_IRQ, + CAM_ICP_A5_SEND_INIT, + CAM_ICP_A5_CMD_VOTE_CPAS, + CAM_ICP_A5_CMD_CPAS_START, + CAM_ICP_A5_CMD_CPAS_STOP, + CAM_ICP_A5_CMD_UBWC_CFG, + CAM_ICP_A5_CMD_PC_PREP, + CAM_ICP_A5_CMD_MAX, +}; + +struct cam_icp_a5_set_fw_buf_info { + uint32_t iova; + uint64_t kva; + uint64_t len; +}; + +/** + * struct cam_icp_a5_query_cap - ICP query device capability payload + * @fw_version: firmware version info + * @api_version: api version info + * @num_ipe: number of ipes + * @num_bps: number of bps + * @num_dev: number of device capabilities in dev_caps + * @reserved: reserved + * @dev_ver: returned device capability array + * @CAM_QUERY_CAP IOCTL + */ +struct cam_icp_a5_query_cap { + struct cam_icp_ver fw_version; + struct cam_icp_ver api_version; + uint32_t num_ipe; + uint32_t num_bps; + uint32_t num_dev; + uint32_t reserved; + struct cam_icp_dev_ver dev_ver[CAM_ICP_DEV_TYPE_MAX]; +}; + +struct cam_icp_a5_acquire_dev { + uint32_t ctx_id; + struct cam_icp_acquire_dev_info icp_acquire_info; + struct cam_icp_res_info icp_out_acquire_info[2]; + uint32_t fw_handle; +}; + +struct cam_icp_a5_set_irq_cb { + int32_t (*icp_hw_mgr_cb)(uint32_t irq_status, void *data); + void *data; +}; + +struct cam_icp_a5_test_irq { + uint32_t test_irq; +}; +#endif /* CAM_A5_HW_INTF_H */ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h new file mode 100644 index 000000000000..e02022435d8b --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_BPS_HW_INTF_H +#define CAM_BPS_HW_INTF_H + +#include +#include +#include "cam_hw_mgr_intf.h" +#include "cam_icp_hw_intf.h" + +/* BPS register */ +#define BPS_TOP_RST_CMD 0x1008 +#define BPS_CDM_RST_CMD 0x10 +#define BPS_CDM_IRQ_STATUS 0x44 +#define BPS_TOP_IRQ_STATUS 0x100C + +/* BPS CDM/TOP status register */ +#define BPS_RST_DONE_IRQ_STATUS_BIT 0x1 + +enum cam_icp_bps_cmd_type { + CAM_ICP_BPS_CMD_FW_DOWNLOAD, + CAM_ICP_BPS_CMD_POWER_COLLAPSE, + CAM_ICP_BPS_CMD_POWER_RESUME, + CAM_ICP_BPS_CMD_SET_FW_BUF, + CAM_ICP_BPS_CMD_VOTE_CPAS, + CAM_ICP_BPS_CMD_CPAS_START, + CAM_ICP_BPS_CMD_CPAS_STOP, + CAM_ICP_BPS_CMD_UPDATE_CLK, + CAM_ICP_BPS_CMD_DISABLE_CLK, + CAM_ICP_BPS_CMD_RESET, + CAM_ICP_BPS_CMD_MAX, +}; + +#endif /* CAM_BPS_HW_INTF_H */ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h new file mode 100644 index 000000000000..aadf27fef485 --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_ICP_HW_INTF_H +#define CAM_ICP_HW_INTF_H + +#define CAM_ICP_CMD_BUF_MAX_SIZE 128 +#define CAM_ICP_MSG_BUF_MAX_SIZE CAM_ICP_CMD_BUF_MAX_SIZE + +#define CAM_ICP_BW_CONFIG_UNKNOWN 0 +#define CAM_ICP_BW_CONFIG_V1 1 +#define CAM_ICP_BW_CONFIG_V2 2 + +enum cam_a5_hw_type { + CAM_ICP_DEV_A5, + CAM_ICP_DEV_IPE, + CAM_ICP_DEV_BPS, + CAM_ICP_DEV_MAX, +}; + +/** + * struct cam_a5_clk_update_cmd - Payload for hw manager command + * + * @curr_clk_rate: clk rate to HW + * @ipe_bps_pc_enable power collpase enable flag + */ +struct cam_a5_clk_update_cmd { + uint32_t curr_clk_rate; + bool ipe_bps_pc_enable; +}; +#endif diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h new file mode 100644 index 000000000000..836a56492447 --- /dev/null +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_IPE_HW_INTF_H +#define CAM_IPE_HW_INTF_H + +#include +#include +#include "cam_hw_mgr_intf.h" +#include "cam_icp_hw_intf.h" + +/* IPE registers */ +#define IPE_TOP_RST_CMD 0x1008 +#define IPE_CDM_RST_CMD 0x10 +#define IPE_CDM_IRQ_STATUS 0x44 +#define IPE_TOP_IRQ_STATUS 0x100C + +/* IPE CDM/TOP status register */ +#define IPE_RST_DONE_IRQ_STATUS_BIT 0x1 + +enum cam_icp_ipe_cmd_type { + CAM_ICP_IPE_CMD_FW_DOWNLOAD, + CAM_ICP_IPE_CMD_POWER_COLLAPSE, + CAM_ICP_IPE_CMD_POWER_RESUME, + CAM_ICP_IPE_CMD_SET_FW_BUF, + CAM_ICP_IPE_CMD_VOTE_CPAS, + CAM_ICP_IPE_CMD_CPAS_START, + CAM_ICP_IPE_CMD_CPAS_STOP, + CAM_ICP_IPE_CMD_UPDATE_CLK, + CAM_ICP_IPE_CMD_DISABLE_CLK, + CAM_ICP_IPE_CMD_RESET, + CAM_ICP_IPE_CMD_MAX, +}; + +#endif /* CAM_IPE_HW_INTF_H */ diff --git a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h new file mode 100644 index 000000000000..25fbe2b8f6c5 --- /dev/null +++ b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_ICP_HW_MGR_INTF_H +#define CAM_ICP_HW_MGR_INTF_H + +#include +#include +#include +#include "cam_cpas_api.h" + +#define ICP_CLK_TURBO_HZ 600000000 +#define ICP_CLK_SVS_HZ 400000000 + +#define CAM_ICP_A5_BW_BYTES_VOTE 40000000 + +#define CAM_ICP_CTX_MAX 54 + +#define CPAS_IPE1_BIT 0x2000 + +#define CAM_IPE_DEFAULT_AXI_PATH CAM_AXI_PATH_DATA_IPE_WR_VID +#define CAM_IPE_DEFAULT_AXI_TRANSAC CAM_AXI_TRANSACTION_WRITE +#define CAM_BPS_DEFAULT_AXI_PATH CAM_AXI_PATH_DATA_ALL +#define CAM_BPS_DEFAULT_AXI_TRANSAC CAM_AXI_TRANSACTION_WRITE +#define CAM_ICP_DEFAULT_AXI_PATH CAM_AXI_PATH_DATA_ALL +#define CAM_ICP_DEFAULT_AXI_TRANSAC CAM_AXI_TRANSACTION_READ + +int cam_icp_hw_mgr_init(struct device_node *of_node, + uint64_t *hw_mgr_hdl, int *iommu_hdl); + +/** + * struct cam_icp_cpas_vote + * @ahb_vote: AHB vote info + * @axi_vote: AXI vote info + * @ahb_vote_valid: Flag for ahb vote data + * @axi_vote_valid: flag for axi vote data + */ +struct cam_icp_cpas_vote { + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote; + uint32_t ahb_vote_valid; + uint32_t axi_vote_valid; +}; + +#endif /* CAM_ICP_HW_MGR_INTF_H */ diff --git a/drivers/cam_icp/icp_hw/ipe_hw/Makefile b/drivers/cam_icp/icp_hw/ipe_hw/Makefile new file mode 100644 index 000000000000..5055e12dff2a --- /dev/null +++ b/drivers/cam_icp/icp_hw/ipe_hw/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/ipe_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += ipe_dev.o ipe_core.o ipe_soc.o diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c new file mode 100644 index 000000000000..82d0ebe54cc4 --- /dev/null +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "ipe_core.h" +#include "ipe_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_ipe_hw_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "hfi_reg.h" + +#define HFI_MAX_POLL_TRY 5 + +static int cam_ipe_cpas_vote(struct cam_ipe_device_core_info *core_info, + struct cam_icp_cpas_vote *cpas_vote) +{ + int rc = 0; + + if (cpas_vote->ahb_vote_valid) + rc = cam_cpas_update_ahb_vote(core_info->cpas_handle, + &cpas_vote->ahb_vote); + if (cpas_vote->axi_vote_valid) + rc = cam_cpas_update_axi_vote(core_info->cpas_handle, + &cpas_vote->axi_vote); + + if (rc) + CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc); + + return rc; +} + +int cam_ipe_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *ipe_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ipe_device_core_info *core_info = NULL; + struct cam_icp_cpas_vote cpas_vote; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &ipe_dev->soc_info; + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; + cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.axi_vote.num_paths = 1; + cpas_vote.axi_vote.axi_path[0].path_data_type = + CAM_IPE_DEFAULT_AXI_PATH; + cpas_vote.axi_vote.axi_path[0].transac_type = + CAM_IPE_DEFAULT_AXI_TRANSAC; + cpas_vote.axi_vote.axi_path[0].camnoc_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote.ahb_vote, &cpas_vote.axi_vote); + if (rc) { + CAM_ERR(CAM_ICP, "cpas start failed: %d", rc); + goto error; + } + core_info->cpas_start = true; + + rc = cam_ipe_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_ICP, "soc enable is failed : %d", rc); + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_ICP, "cpas stop is failed"); + else + core_info->cpas_start = false; + } else { + core_info->clk_enable = true; + } + +error: + return rc; +} + +int cam_ipe_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *ipe_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ipe_device_core_info *core_info = NULL; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &ipe_dev->soc_info; + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + rc = cam_ipe_disable_soc_resources(soc_info, core_info->clk_enable); + if (rc) + CAM_ERR(CAM_ICP, "soc disable is failed : %d", rc); + core_info->clk_enable = false; + + if (core_info->cpas_start) { + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_ICP, "cpas stop is failed"); + else + core_info->cpas_start = false; + } + + return rc; +} + +static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev) +{ + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ipe_device_core_info *core_info = NULL; + struct cam_ipe_device_hw_info *hw_info = NULL; + int pwr_ctrl; + int pwr_status; + + soc_info = &ipe_dev->soc_info; + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + hw_info = core_info->ipe_hw_info; + + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (!(pwr_ctrl & IPE_COLLAPSE_MASK)) { + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0x1); + + if (pwr_status >> IPE_PWR_ON_MASK) + CAM_WARN(CAM_ICP, "BPS: pwr_status(%x):pwr_ctrl(%x)", + pwr_status, pwr_ctrl); + + } + cam_ipe_get_gdsc_control(soc_info); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + pwr_ctrl, pwr_status); + + return 0; +} + +static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) +{ + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ipe_device_core_info *core_info = NULL; + struct cam_ipe_device_hw_info *hw_info = NULL; + int pwr_ctrl; + int pwr_status; + int rc = 0; + + soc_info = &ipe_dev->soc_info; + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + hw_info = core_info->ipe_hw_info; + + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (pwr_ctrl & IPE_COLLAPSE_MASK) { + CAM_DBG(CAM_ICP, "IPE pwr_ctrl set(%x)", pwr_ctrl); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0); + } + + rc = cam_ipe_transfer_gdsc_control(soc_info); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + pwr_ctrl, pwr_status); + + return rc; +} + +static int cam_ipe_cmd_reset(struct cam_hw_soc_info *soc_info, + struct cam_ipe_device_core_info *core_info) +{ + int pwr_ctrl, pwr_status, rc = 0; + uint32_t status = 0, retry_cnt = 0; + bool reset_ipe_cdm_fail = false; + 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); + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((soc_info->reg_map[0].mem_base + + IPE_CDM_IRQ_STATUS), + status, ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1), + 100, 10000); + + CAM_DBG(CAM_HFI, "ipe_cdm_irq_status = %u", status); + + if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1) + break; + retry_cnt++; + } + status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + IPE_CDM_IRQ_STATUS); + if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) != 0x1) { + CAM_ERR(CAM_ICP, "IPE CDM rst failed status 0x%x", status); + reset_ipe_cdm_fail = true; + } + + /* IPE reset*/ + status = 0; + cam_io_w_mb((uint32_t)0x3, + soc_info->reg_map[0].mem_base + IPE_TOP_RST_CMD); + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((soc_info->reg_map[0].mem_base + + IPE_TOP_IRQ_STATUS), + status, ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1), + 100, 10000); + + CAM_DBG(CAM_HFI, "ipe_top_irq_status = %u", status); + + + if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1) + break; + retry_cnt++; + } + status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + IPE_TOP_IRQ_STATUS); + if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) != 0x1) { + CAM_ERR(CAM_ICP, "IPE top rst failed status 0x%x", status); + reset_ipe_top_fail = true; + } + + cam_ipe_get_gdsc_control(soc_info); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, core_info->ipe_hw_info->pwr_ctrl, + true, &pwr_ctrl); + cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, core_info->ipe_hw_info->pwr_status, + true, &pwr_status); + CAM_DBG(CAM_ICP, "(After)pwr_ctrl = %x pwr_status = %x", + pwr_ctrl, pwr_status); + + if (reset_ipe_cdm_fail || reset_ipe_top_fail) + rc = -EAGAIN; + + return rc; +} + +int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *ipe_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ipe_device_core_info *core_info = NULL; + struct cam_ipe_device_hw_info *hw_info = NULL; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_ICP, "Invalid arguments"); + return -EINVAL; + } + + if (cmd_type >= CAM_ICP_IPE_CMD_MAX) { + CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type); + return -EINVAL; + } + + soc_info = &ipe_dev->soc_info; + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + hw_info = core_info->ipe_hw_info; + + switch (cmd_type) { + case CAM_ICP_IPE_CMD_VOTE_CPAS: { + struct cam_icp_cpas_vote *cpas_vote = cmd_args; + + if (!cmd_args) + return -EINVAL; + + cam_ipe_cpas_vote(core_info, cpas_vote); + break; + } + + case CAM_ICP_IPE_CMD_CPAS_START: { + struct cam_icp_cpas_vote *cpas_vote = cmd_args; + + if (!cmd_args) + return -EINVAL; + + if (!core_info->cpas_start) { + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote->ahb_vote, &cpas_vote->axi_vote); + core_info->cpas_start = true; + } + break; + } + + case CAM_ICP_IPE_CMD_CPAS_STOP: + if (core_info->cpas_start) { + cam_cpas_stop(core_info->cpas_handle); + core_info->cpas_start = false; + } + break; + case CAM_ICP_IPE_CMD_POWER_COLLAPSE: + rc = cam_ipe_handle_pc(ipe_dev); + break; + case CAM_ICP_IPE_CMD_POWER_RESUME: + rc = cam_ipe_handle_resume(ipe_dev); + break; + case CAM_ICP_IPE_CMD_UPDATE_CLK: { + struct cam_a5_clk_update_cmd *clk_upd_cmd = + (struct cam_a5_clk_update_cmd *)cmd_args; + uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; + + CAM_DBG(CAM_ICP, "ipe_src_clk rate = %d", (int)clk_rate); + if (!core_info->clk_enable) { + if (clk_upd_cmd->ipe_bps_pc_enable) { + cam_ipe_handle_pc(ipe_dev); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0x0); + } + rc = cam_ipe_toggle_clk(soc_info, true); + if (rc) + CAM_ERR(CAM_ICP, "Enable failed"); + else + core_info->clk_enable = true; + if (clk_upd_cmd->ipe_bps_pc_enable) { + rc = cam_ipe_handle_resume(ipe_dev); + if (rc) + CAM_ERR(CAM_ICP, "bps resume failed"); + } + } + CAM_DBG(CAM_ICP, "clock rate %d", clk_rate); + + rc = cam_ipe_update_clk_rate(soc_info, clk_rate); + if (rc) + CAM_ERR(CAM_ICP, "Failed to update clk"); + } + break; + case CAM_ICP_IPE_CMD_DISABLE_CLK: + if (core_info->clk_enable == true) + cam_ipe_toggle_clk(soc_info, false); + core_info->clk_enable = false; + break; + case CAM_ICP_IPE_CMD_RESET: + rc = cam_ipe_cmd_reset(soc_info, core_info); + break; + default: + CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type); + rc = -EINVAL; + break; + } + return rc; +} + +irqreturn_t cam_ipe_irq(int irq_num, void *data) +{ + return IRQ_HANDLED; +} diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h new file mode 100644 index 000000000000..1a15e9233896 --- /dev/null +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_IPE_CORE_H +#define CAM_IPE_CORE_H + +#include +#include +#include +#include + +#define IPE_COLLAPSE_MASK 0x1 +#define IPE_PWR_ON_MASK 0x2 + +struct cam_ipe_device_hw_info { + uint32_t hw_idx; + uint32_t pwr_ctrl; + uint32_t pwr_status; + uint32_t reserved; +}; + +struct cam_ipe_device_core_info { + struct cam_ipe_device_hw_info *ipe_hw_info; + uint32_t cpas_handle; + bool cpas_start; + bool clk_enable; +}; + +int cam_ipe_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_ipe_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); +irqreturn_t cam_ipe_irq(int irq_num, void *data); + +#endif /* CAM_IPE_CORE_H */ diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c new file mode 100644 index 000000000000..0390488d92b3 --- /dev/null +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "ipe_core.h" +#include "ipe_soc.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_io_util.h" +#include "cam_icp_hw_intf.h" +#include "cam_icp_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +static struct cam_ipe_device_hw_info cam_ipe_hw_info[] = { + { + .hw_idx = 0, + .pwr_ctrl = 0x4c, + .pwr_status = 0x48, + .reserved = 0, + }, + { + .hw_idx = 1, + .pwr_ctrl = 0x54, + .pwr_status = 0x50, + .reserved = 0, + }, +}; +EXPORT_SYMBOL(cam_ipe_hw_info); + +static char ipe_dev_name[8]; + +int cam_ipe_register_cpas(struct cam_hw_soc_info *soc_info, + struct cam_ipe_device_core_info *core_info, + uint32_t hw_idx) +{ + struct cam_cpas_register_params cpas_register_params; + int rc; + + cpas_register_params.dev = &soc_info->pdev->dev; + memcpy(cpas_register_params.identifier, "ipe", sizeof("ipe")); + cpas_register_params.cam_cpas_client_cb = NULL; + cpas_register_params.cell_index = hw_idx; + cpas_register_params.userdata = NULL; + + rc = cam_cpas_register_client(&cpas_register_params); + if (rc < 0) { + CAM_ERR(CAM_ICP, "failed: %d", rc); + return rc; + } + core_info->cpas_handle = cpas_register_params.client_handle; + + return rc; +} + +int cam_ipe_probe(struct platform_device *pdev) +{ + struct cam_hw_info *ipe_dev = NULL; + struct cam_hw_intf *ipe_dev_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_ipe_device_core_info *core_info = NULL; + struct cam_ipe_device_hw_info *hw_info = NULL; + int rc = 0; + struct cam_cpas_query_cap query; + uint32_t cam_caps; + uint32_t hw_idx; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &hw_idx); + + cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, &cam_caps); + if ((!(cam_caps & CPAS_IPE1_BIT)) && (hw_idx)) { + CAM_ERR(CAM_ICP, "IPE1 hw idx = %d\n", hw_idx); + return -EINVAL; + } + + ipe_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!ipe_dev_intf) + return -ENOMEM; + + ipe_dev_intf->hw_idx = hw_idx; + ipe_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!ipe_dev) { + kfree(ipe_dev_intf); + return -ENOMEM; + } + + memset(ipe_dev_name, 0, sizeof(ipe_dev_name)); + snprintf(ipe_dev_name, sizeof(ipe_dev_name), + "ipe%1u", ipe_dev_intf->hw_idx); + + ipe_dev->soc_info.pdev = pdev; + ipe_dev->soc_info.dev = &pdev->dev; + ipe_dev->soc_info.dev_name = ipe_dev_name; + ipe_dev_intf->hw_priv = ipe_dev; + ipe_dev_intf->hw_ops.init = cam_ipe_init_hw; + ipe_dev_intf->hw_ops.deinit = cam_ipe_deinit_hw; + ipe_dev_intf->hw_ops.process_cmd = cam_ipe_process_cmd; + ipe_dev_intf->hw_type = CAM_ICP_DEV_IPE; + + CAM_DBG(CAM_ICP, "type %d index %d", + ipe_dev_intf->hw_type, + ipe_dev_intf->hw_idx); + + platform_set_drvdata(pdev, ipe_dev_intf); + + ipe_dev->core_info = kzalloc(sizeof(struct cam_ipe_device_core_info), + GFP_KERNEL); + if (!ipe_dev->core_info) { + kfree(ipe_dev); + kfree(ipe_dev_intf); + return -ENOMEM; + } + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_DBG(CAM_ICP, "No ipe hardware info"); + kfree(ipe_dev->core_info); + kfree(ipe_dev); + kfree(ipe_dev_intf); + rc = -EINVAL; + return rc; + } + hw_info = &cam_ipe_hw_info[ipe_dev_intf->hw_idx]; + core_info->ipe_hw_info = hw_info; + + rc = cam_ipe_init_soc_resources(&ipe_dev->soc_info, cam_ipe_irq, + ipe_dev); + if (rc < 0) { + CAM_ERR(CAM_ICP, "failed to init_soc"); + kfree(ipe_dev->core_info); + kfree(ipe_dev); + kfree(ipe_dev_intf); + return rc; + } + + CAM_DBG(CAM_ICP, "cam_ipe_init_soc_resources : %pK", + (void *)&ipe_dev->soc_info); + rc = cam_ipe_register_cpas(&ipe_dev->soc_info, + core_info, ipe_dev_intf->hw_idx); + if (rc < 0) { + kfree(ipe_dev->core_info); + kfree(ipe_dev); + kfree(ipe_dev_intf); + return rc; + } + ipe_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&ipe_dev->hw_mutex); + spin_lock_init(&ipe_dev->hw_lock); + init_completion(&ipe_dev->hw_complete); + + CAM_DBG(CAM_ICP, "IPE%d probe successful", + ipe_dev_intf->hw_idx); + + return rc; +} + +static const struct of_device_id cam_ipe_dt_match[] = { + { + .compatible = "qcom,cam-ipe", + .data = &cam_ipe_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_ipe_dt_match); + +static struct platform_driver cam_ipe_driver = { + .probe = cam_ipe_probe, + .driver = { + .name = "cam-ipe", + .owner = THIS_MODULE, + .of_match_table = cam_ipe_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_ipe_init_module(void) +{ + return platform_driver_register(&cam_ipe_driver); +} + +static void __exit cam_ipe_exit_module(void) +{ + platform_driver_unregister(&cam_ipe_driver); +} + +module_init(cam_ipe_init_module); +module_exit(cam_ipe_exit_module); +MODULE_DESCRIPTION("CAM IPE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c new file mode 100644 index 000000000000..a33c7b68bf97 --- /dev/null +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "ipe_soc.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + + +int cam_ipe_transfer_gdsc_control(struct cam_hw_soc_info *soc_info) +{ + int i; + int rc; + + for (i = 0; i < soc_info->num_rgltr; i++) { + rc = regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_FAST); + if (rc) { + CAM_ERR(CAM_ICP, "Regulator set mode %s failed", + soc_info->rgltr_name[i]); + goto rgltr_set_mode_failed; + } + } + return 0; + +rgltr_set_mode_failed: + for (i = i - 1; i >= 0; i--) + if (soc_info->rgltr[i]) + regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_NORMAL); + + return rc; +} + +int cam_ipe_get_gdsc_control(struct cam_hw_soc_info *soc_info) +{ + int i; + int rc; + + for (i = 0; i < soc_info->num_rgltr; i++) { + rc = regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_NORMAL); + if (rc) { + CAM_ERR(CAM_ICP, "Regulator set mode %s failed", + soc_info->rgltr_name[i]); + goto rgltr_set_mode_failed; + } + } + return 0; + +rgltr_set_mode_failed: + for (i = i - 1; i >= 0; i--) + if (soc_info->rgltr[i]) + regulator_set_mode(soc_info->rgltr[i], + REGULATOR_MODE_FAST); + + return rc; +} + +static int cam_ipe_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) + CAM_ERR(CAM_ICP, "get ipe dt prop is failed"); + + return rc; +} + +static int cam_ipe_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t ipe_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, ipe_irq_handler, + irq_data); + + return rc; +} + +int cam_ipe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ipe_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_ipe_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + rc = cam_ipe_request_platform_resource(soc_info, ipe_irq_handler, + irq_data); + if (rc < 0) + return rc; + + return rc; +} + +int cam_ipe_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, false); + if (rc) { + CAM_ERR(CAM_ICP, "enable platform failed"); + return rc; + } + + return rc; +} + +int cam_ipe_disable_soc_resources(struct cam_hw_soc_info *soc_info, + bool disable_clk) +{ + int rc = 0; + + rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk, + false); + if (rc) + CAM_ERR(CAM_ICP, "enable platform failed"); + + return rc; +} + +int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_rate) +{ + int32_t src_clk_idx; + + if (!soc_info) + return -EINVAL; + + src_clk_idx = soc_info->src_clk_idx; + + if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) && + (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && + (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { + CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d", + clk_rate, + soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); + clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; + } + + return cam_soc_util_set_src_clk_rate(soc_info, clk_rate); +} + +int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable) +{ + int rc = 0; + + if (clk_enable) + rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE); + else + cam_soc_util_clk_disable_default(soc_info); + + return rc; +} diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h new file mode 100644 index 000000000000..8981b18823ad --- /dev/null +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_IPE_SOC_H +#define CAM_IPE_SOC_H + +#include "cam_soc_util.h" + +int cam_ipe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ipe_irq_handler, void *irq_data); + +int cam_ipe_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +int cam_ipe_disable_soc_resources(struct cam_hw_soc_info *soc_info, + bool disable_clk); + +int cam_ipe_get_gdsc_control(struct cam_hw_soc_info *soc_info); + +int cam_ipe_transfer_gdsc_control(struct cam_hw_soc_info *soc_info); + +int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_rate); +int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable); +#endif /* CAM_IPE_SOC_H */ diff --git a/drivers/cam_isp/Makefile b/drivers/cam_isp/Makefile new file mode 100644 index 000000000000..069350122c7b --- /dev/null +++ b/drivers/cam_isp/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ + +obj-$(CONFIG_SPECTRA_CAMERA) += isp_hw_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_dev.o cam_isp_context.o diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c new file mode 100644 index 000000000000..7e1fa25910b2 --- /dev/null +++ b/drivers/cam_isp/cam_isp_context.c @@ -0,0 +1,3937 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "cam_mem_mgr.h" +#include "cam_sync_api.h" +#include "cam_req_mgr_dev.h" +#include "cam_trace.h" +#include "cam_debug_util.h" +#include "cam_packet_util.h" +#include "cam_context_utils.h" +#include "cam_cdm_util.h" +#include "cam_isp_context.h" +#include "cam_common_util.h" + +static const char isp_dev_name[] = "isp"; + +#define INC_STATE_MONITOR_HEAD(head) \ + (atomic64_add_return(1, head) % \ + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) + +static int cam_isp_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info); + +static void __cam_isp_ctx_update_state_monitor_array( + struct cam_isp_context *ctx_isp, + enum cam_isp_state_change_trigger trigger_type, + uint64_t req_id) +{ + int iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head); + + ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state = + ctx_isp->substate_activated; + ctx_isp->cam_isp_ctx_state_monitor[iterator].frame_id = + ctx_isp->frame_id; + ctx_isp->cam_isp_ctx_state_monitor[iterator].trigger = + trigger_type; + ctx_isp->cam_isp_ctx_state_monitor[iterator].req_id = + req_id; + ctx_isp->cam_isp_ctx_state_monitor[iterator].evt_time_stamp = + jiffies_to_msecs(jiffies) - ctx_isp->init_timestamp; +} + +static const char *__cam_isp_ctx_substate_val_to_type( + uint32_t type) +{ + switch (type) { + case CAM_ISP_CTX_ACTIVATED_SOF: + return "SOF"; + case CAM_ISP_CTX_ACTIVATED_APPLIED: + return "APPLIED"; + case CAM_ISP_CTX_ACTIVATED_EPOCH: + return "EPOCH"; + case CAM_ISP_CTX_ACTIVATED_BUBBLE: + return "BUBBLE"; + case CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED: + return "BUBBLE_APPLIED"; + case CAM_ISP_CTX_ACTIVATED_HW_ERROR: + return "HW_ERROR"; + case CAM_ISP_CTX_ACTIVATED_HALT: + return "HALT"; + default: + return "CAM_ISP_CTX_INVALID_STATE"; + } +} + +static const char *__cam_isp_hw_evt_val_to_type( + uint32_t evt_id) +{ + switch (evt_id) { + case CAM_ISP_STATE_CHANGE_TRIGGER_ERROR: + return "ERROR"; + case CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED: + return "APPLIED"; + case CAM_ISP_STATE_CHANGE_TRIGGER_SOF: + return "SOF"; + case CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE: + return "REG_UPDATE"; + case CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH: + return "EPOCH"; + case CAM_ISP_STATE_CHANGE_TRIGGER_EOF: + return "EOF"; + case CAM_ISP_STATE_CHANGE_TRIGGER_DONE: + return "DONE"; + case CAM_ISP_STATE_CHANGE_TRIGGER_FLUSH: + return "FLUSH"; + default: + return "CAM_ISP_EVENT_INVALID"; + } +} + +static void __cam_isp_ctx_dump_state_monitor_array( + struct cam_isp_context *ctx_isp) +{ + int i = 0; + int64_t state_head = 0; + uint32_t index, num_entries, oldest_entry; + + state_head = atomic64_read(&ctx_isp->state_monitor_head); + + if (state_head == -1) { + return; + } else if (state_head < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) { + num_entries = state_head; + oldest_entry = 0; + } else { + num_entries = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; + oldest_entry = (state_head + 1) % + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; + } + + CAM_ERR(CAM_ISP, + "Dumping state information for preceding requests"); + + index = oldest_entry; + + for (i = 0; i < num_entries; i++) { + CAM_ERR(CAM_ISP, + "Index[%d] time[%d] : State[%s] Frame[%lld] ReqId[%llu] evt_type[%s]", + index, + ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp, + __cam_isp_ctx_substate_val_to_type( + ctx_isp->cam_isp_ctx_state_monitor[index].curr_state), + ctx_isp->cam_isp_ctx_state_monitor[index].frame_id, + ctx_isp->cam_isp_ctx_state_monitor[index].req_id, + __cam_isp_hw_evt_val_to_type( + ctx_isp->cam_isp_ctx_state_monitor[index].trigger)); + + index = (index + 1) % CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; + } +} + +static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) +{ + int i = 0, rc = 0; + size_t len = 0; + uint32_t *buf_addr; + uint32_t *buf_start, *buf_end; + size_t remain_len = 0; + + for (i = 0; i < req_isp->num_cfg; i++) { + rc = cam_packet_util_get_cmd_mem_addr( + req_isp->cfg[i].handle, &buf_addr, &len); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Failed to get_cmd_mem_addr, rc=%d", + rc); + } else { + if (req_isp->cfg[i].offset >= ((uint32_t)len)) { + CAM_ERR(CAM_ISP, + "Invalid offset exp %u actual %u", + req_isp->cfg[i].offset, (uint32_t)len); + return; + } + remain_len = len - req_isp->cfg[i].offset; + + if (req_isp->cfg[i].len > + ((uint32_t)remain_len)) { + CAM_ERR(CAM_ISP, + "Invalid len exp %u remain_len %u", + req_isp->cfg[i].len, + (uint32_t)remain_len); + return; + } + + 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); + cam_cdm_util_dump_cmd_buf(buf_start, buf_end); + } + } +} + +static int __cam_isp_ctx_enqueue_request_in_order( + struct cam_context *ctx, struct cam_ctx_request *req) +{ + struct cam_ctx_request *req_current; + struct cam_ctx_request *req_prev; + struct list_head temp_list; + + INIT_LIST_HEAD(&temp_list); + spin_lock_bh(&ctx->lock); + if (list_empty(&ctx->pending_req_list)) { + list_add_tail(&req->list, &ctx->pending_req_list); + } else { + list_for_each_entry_safe_reverse( + req_current, req_prev, &ctx->pending_req_list, list) { + if (req->request_id < req_current->request_id) { + list_del_init(&req_current->list); + list_add(&req_current->list, &temp_list); + continue; + } else if (req->request_id == req_current->request_id) { + CAM_WARN(CAM_ISP, + "Received duplicated request %lld", + req->request_id); + } + break; + } + list_add_tail(&req->list, &ctx->pending_req_list); + + if (!list_empty(&temp_list)) { + list_for_each_entry_safe( + req_current, req_prev, &temp_list, list) { + list_del_init(&req_current->list); + list_add_tail(&req_current->list, + &ctx->pending_req_list); + } + } + } + spin_unlock_bh(&ctx->lock); + return 0; +} + +static int __cam_isp_ctx_enqueue_init_request( + struct cam_context *ctx, struct cam_ctx_request *req) +{ + int rc = 0; + struct cam_ctx_request *req_old; + struct cam_isp_ctx_req *req_isp_old; + struct cam_isp_ctx_req *req_isp_new; + + spin_lock_bh(&ctx->lock); + if (list_empty(&ctx->pending_req_list)) { + list_add_tail(&req->list, &ctx->pending_req_list); + CAM_DBG(CAM_ISP, "INIT packet added req id= %d", + req->request_id); + goto end; + } + + req_old = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + req_isp_old = (struct cam_isp_ctx_req *) req_old->req_priv; + req_isp_new = (struct cam_isp_ctx_req *) req->req_priv; + if (req_isp_old->hw_update_data.packet_opcode_type == + CAM_ISP_PACKET_INIT_DEV) { + if ((req_isp_old->num_cfg + req_isp_new->num_cfg) >= + CAM_ISP_CTX_CFG_MAX) { + CAM_WARN(CAM_ISP, "Can not merge INIT pkt"); + rc = -ENOMEM; + } + + if (req_isp_old->num_fence_map_out != 0 || + req_isp_old->num_fence_map_in != 0) { + CAM_WARN(CAM_ISP, "Invalid INIT pkt sequence"); + rc = -EINVAL; + } + + if (!rc) { + memcpy(req_isp_old->fence_map_out, + req_isp_new->fence_map_out, + sizeof(req_isp_new->fence_map_out[0])* + req_isp_new->num_fence_map_out); + req_isp_old->num_fence_map_out = + req_isp_new->num_fence_map_out; + + memcpy(req_isp_old->fence_map_in, + req_isp_new->fence_map_in, + sizeof(req_isp_new->fence_map_in[0])* + req_isp_new->num_fence_map_in); + req_isp_old->num_fence_map_in = + req_isp_new->num_fence_map_in; + + memcpy(&req_isp_old->cfg[req_isp_old->num_cfg], + req_isp_new->cfg, + sizeof(req_isp_new->cfg[0])* + req_isp_new->num_cfg); + req_isp_old->num_cfg += req_isp_new->num_cfg; + + req_old->request_id = req->request_id; + + list_add_tail(&req->list, &ctx->free_req_list); + } + } else { + CAM_WARN(CAM_ISP, + "Received Update pkt before INIT pkt. req_id= %lld", + req->request_id); + rc = -EINVAL; + } +end: + spin_unlock_bh(&ctx->lock); + return rc; +} + +static const char *__cam_isp_resource_handle_id_to_type( + uint32_t resource_handle) +{ + switch (resource_handle) { + case CAM_ISP_IFE_OUT_RES_FULL: + return "FULL"; + case CAM_ISP_IFE_OUT_RES_DS4: + return "DS4"; + case CAM_ISP_IFE_OUT_RES_DS16: + return "DS16"; + case CAM_ISP_IFE_OUT_RES_RAW_DUMP: + return "RAW_DUMP"; + case CAM_ISP_IFE_OUT_RES_FD: + return "FD"; + case CAM_ISP_IFE_OUT_RES_PDAF: + return "PDAF"; + case CAM_ISP_IFE_OUT_RES_RDI_0: + return "RDI_0"; + case CAM_ISP_IFE_OUT_RES_RDI_1: + return "RDI_1"; + case CAM_ISP_IFE_OUT_RES_RDI_2: + return "RDI_2"; + case CAM_ISP_IFE_OUT_RES_RDI_3: + return "RDI_3"; + case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE: + return "STATS_HDR_BE"; + case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST: + return "STATS_HDR_BHIST"; + case CAM_ISP_IFE_OUT_RES_STATS_TL_BG: + return "STATS_TL_BG"; + case CAM_ISP_IFE_OUT_RES_STATS_BF: + return "STATS_BF"; + case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG: + return "STATS_AWB_BG"; + case CAM_ISP_IFE_OUT_RES_STATS_BHIST: + return "STATS_BHIST"; + case CAM_ISP_IFE_OUT_RES_STATS_RS: + return "STATS_RS"; + case CAM_ISP_IFE_OUT_RES_STATS_CS: + return "STATS_CS"; + case CAM_ISP_IFE_OUT_RES_STATS_IHIST: + return "STATS_IHIST"; + case CAM_ISP_IFE_OUT_RES_FULL_DISP: + return "FULL_DISP"; + case CAM_ISP_IFE_OUT_RES_DS4_DISP: + return "DS4_DISP"; + case CAM_ISP_IFE_OUT_RES_DS16_DISP: + return "DS16_DISP"; + case CAM_ISP_IFE_OUT_RES_2PD: + return "2PD"; + case CAM_ISP_IFE_OUT_RES_RDI_RD: + return "RDI_RD"; + case CAM_ISP_IFE_OUT_RES_LCR: + return "LCR"; + default: + return "CAM_ISP_Invalid_Resource_Type"; + } +} + +static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data) +{ + uint64_t ts = 0; + + if (!evt_data) + return 0; + + switch (evt_id) { + case CAM_ISP_HW_EVENT_ERROR: + ts = ((struct cam_isp_hw_error_event_data *)evt_data)-> + timestamp; + break; + case CAM_ISP_HW_EVENT_SOF: + ts = ((struct cam_isp_hw_sof_event_data *)evt_data)-> + timestamp; + break; + case CAM_ISP_HW_EVENT_REG_UPDATE: + ts = ((struct cam_isp_hw_reg_update_event_data *)evt_data)-> + timestamp; + break; + case CAM_ISP_HW_EVENT_EPOCH: + ts = ((struct cam_isp_hw_epoch_event_data *)evt_data)-> + timestamp; + break; + case CAM_ISP_HW_EVENT_EOF: + ts = ((struct cam_isp_hw_eof_event_data *)evt_data)-> + timestamp; + break; + case CAM_ISP_HW_EVENT_DONE: + break; + default: + CAM_DBG(CAM_ISP, "Invalid Event Type %d", evt_id); + } + + return ts; +} + +static void __cam_isp_ctx_handle_buf_done_fail_log( + uint64_t request_id, struct cam_isp_ctx_req *req_isp) +{ + int i; + + if (req_isp->num_fence_map_out >= CAM_ISP_CTX_RES_MAX) { + CAM_ERR(CAM_ISP, + "Num Resources exceed mMAX %d >= %d ", + req_isp->num_fence_map_out, CAM_ISP_CTX_RES_MAX); + return; + } + + CAM_ERR(CAM_ISP, + "Prev Req[%lld] : num_out=%d, num_acked=%d, bubble : report=%d, detected=%d", + request_id, req_isp->num_fence_map_out, req_isp->num_acked, + req_isp->bubble_report, req_isp->bubble_detected); + CAM_ERR(CAM_ISP, + "Resource Handles that fail to generate buf_done in prev frame"); + for (i = 0; i < req_isp->num_fence_map_out; i++) { + if (req_isp->fence_map_out[i].sync_id != -1) + CAM_ERR(CAM_ISP, + "Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]", + __cam_isp_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle), + req_isp->fence_map_out[i].resource_handle, + req_isp->fence_map_out[i].sync_id); + } +} + +static int __cam_isp_ctx_handle_buf_done_in_activated_state( + struct cam_isp_context *ctx_isp, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state) +{ + int rc = 0; + int i, j; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + uint64_t buf_done_req_id; + + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_ISP, "Buf done with no active request!"); + goto end; + } + + CAM_DBG(CAM_ISP, "Enter with bubble_state %d", bubble_state); + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + + trace_cam_buf_done("ISP", ctx, req); + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + for (i = 0; i < done->num_handles; i++) { + for (j = 0; j < req_isp->num_fence_map_out; j++) { + if (done->resource_handle[i] == + req_isp->fence_map_out[j].resource_handle) + break; + } + + if (j == req_isp->num_fence_map_out) { + CAM_ERR(CAM_ISP, + "Can not find matching lane handle 0x%x!", + done->resource_handle[i]); + rc = -EINVAL; + continue; + } + + if (req_isp->fence_map_out[j].sync_id == -1) { + __cam_isp_ctx_handle_buf_done_fail_log( + req->request_id, req_isp); + continue; + } + + if (!req_isp->bubble_detected) { + 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, + ctx->ctx_id); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS); + if (rc) + CAM_DBG(CAM_ISP, "Sync failed with rc = %d", + rc); + } else if (!req_isp->bubble_report) { + 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, + ctx->ctx_id); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) + CAM_ERR(CAM_ISP, "Sync failed with rc = %d", + rc); + } else { + /* + * Ignore the buffer done if bubble detect is on + * Increment the ack number here, and queue the + * request back to pending list whenever all the + * buffers are done. + */ + req_isp->num_acked++; + CAM_DBG(CAM_ISP, + "buf done with bubble state %d recovery %d", + bubble_state, req_isp->bubble_report); + continue; + } + + CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x ctx %u", + req->request_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; + } + } + + 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, ctx %u", + req->request_id, req_isp->num_acked, + req_isp->num_fence_map_out, ctx->ctx_id); + WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out); + } + + if (req_isp->num_acked != req_isp->num_fence_map_out) + return rc; + + ctx_isp->active_req_cnt--; + buf_done_req_id = req->request_id; + + if (req_isp->bubble_detected && req_isp->bubble_report) { + req_isp->num_acked = 0; + 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], 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], ctx %u", + buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + } + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); +end: + return rc; +} + +static void __cam_isp_ctx_send_sof_boot_timestamp( + struct cam_isp_context *ctx_isp, uint64_t request_id, + uint32_t sof_event_status) +{ + struct cam_req_mgr_message req_msg; + + req_msg.session_hdl = ctx_isp->base->session_hdl; + req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; + req_msg.u.frame_msg.request_id = request_id; + req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp; + req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; + req_msg.u.frame_msg.sof_status = sof_event_status; + + CAM_DBG(CAM_ISP, + "request id:%lld frame number:%lld boot time stamp:0x%llx", + request_id, ctx_isp->frame_id, + ctx_isp->boot_timestamp); + + if (cam_req_mgr_notify_message(&req_msg, + V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS, + V4L_EVENT_CAM_REQ_MGR_EVENT)) + CAM_ERR(CAM_ISP, + "Error in notifying the boot time for req id:%lld", + request_id); +} + + +static void __cam_isp_ctx_send_sof_timestamp( + struct cam_isp_context *ctx_isp, uint64_t request_id, + uint32_t sof_event_status) +{ + struct cam_req_mgr_message req_msg; + + req_msg.session_hdl = ctx_isp->base->session_hdl; + req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; + req_msg.u.frame_msg.request_id = request_id; + req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val; + req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; + req_msg.u.frame_msg.sof_status = sof_event_status; + + CAM_DBG(CAM_ISP, + "request id:%lld frame number:%lld SOF time stamp:0x%llx", + request_id, ctx_isp->frame_id, + ctx_isp->sof_timestamp_val); + CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status); + + if (cam_req_mgr_notify_message(&req_msg, + V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT)) + CAM_ERR(CAM_ISP, + "Error in notifying the sof time for req id:%lld", + request_id); + + __cam_isp_ctx_send_sof_boot_timestamp(ctx_isp, + request_id, sof_event_status); + +} + +static int __cam_isp_ctx_reg_upd_in_epoch_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + if (ctx_isp->frame_id == 1) + CAM_DBG(CAM_ISP, "Reg update for early PCR"); + else + CAM_WARN(CAM_ISP, + "Unexpected reg update in activated substate:%d for frame_id:%lld", + ctx_isp->substate_activated, ctx_isp->frame_id); + return 0; +} + +static int __cam_isp_ctx_reg_upd_in_activated_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + int rc = 0; + struct cam_ctx_request *req; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_ctx_req *req_isp; + 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++; + request_id = req->request_id; + 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), ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); + } + + /* + * This function only called directly from applied and bubble applied + * state so change substate here. + */ + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; + CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE, request_id); + +end: + return rc; +} + +static int __cam_isp_ctx_notify_sof_in_activated_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + int rc = 0; + struct cam_req_mgr_trigger_notify notify; + struct cam_context *ctx = ctx_isp->base; + struct cam_ctx_request *req; + uint64_t request_id = 0; + + /* + * notify reqmgr with sof signal. Note, due to scheduling delay + * we can run into situation that two active requests has already + * be in the active queue while we try to do the notification. + * In this case, we need to skip the current notification. This + * helps the state machine to catch up the delay. + */ + 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(¬ify); + 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) { + if (req->request_id > ctx_isp->reported_req_id) { + request_id = req->request_id; + ctx_isp->reported_req_id = request_id; + break; + } + } + + if (ctx_isp->substate_activated == CAM_ISP_CTX_ACTIVATED_BUBBLE) + request_id = 0; + + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, + request_id); + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Can not notify SOF to CRM for ctx %u", + ctx->ctx_id); + rc = -EFAULT; + } + + return 0; +} + +static int __cam_isp_ctx_notify_eof_in_activated_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + int rc = 0; + struct cam_req_mgr_trigger_notify notify; + struct cam_context *ctx = ctx_isp->base; + + if (!(ctx_isp->subscribe_event & CAM_TRIGGER_POINT_EOF)) + return rc; + + /* notify reqmgr with eof signal */ + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { + notify.link_hdl = ctx->link_hdl; + notify.dev_hdl = ctx->dev_hdl; + notify.frame_id = ctx_isp->frame_id; + notify.trigger = CAM_TRIGGER_POINT_EOF; + + ctx->ctx_crm_intf->notify_trigger(¬ify); + CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld ctx %u", + ctx_isp->frame_id, ctx->ctx_id); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_EOF, 0); + } else { + CAM_ERR(CAM_ISP, "Can not notify EOF to CRM for ctx %u", + ctx->ctx_id); + rc = -EFAULT; + } + + return rc; +} + +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; + return 0; +} + +static int __cam_isp_ctx_sof_in_activated_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 = NULL; + struct cam_context *ctx = ctx_isp->base; + uint64_t request_id = 0; + + /* First check if there is a valid request in active list */ + list_for_each_entry(req, &ctx->active_req_list, list) { + if (req->request_id > ctx_isp->reported_req_id) { + request_id = req->request_id; + break; + } + } + + /* + * If nothing in active list, current request might have not moved + * from wait to active list. This could happen if REG_UPDATE to sw + * is coming immediately after SOF + */ + if (request_id == 0) { + req = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + if (req) + request_id = req->request_id; + } + + 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, request_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; +} + +static int __cam_isp_ctx_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_epoch_in_applied(struct cam_isp_context *ctx_isp, + void *evt_data) +{ + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + uint64_t request_id = 0; + + if (list_empty(&ctx->wait_req_list)) { + /* + * If no wait req in epoch, this is an error case. + * The recovery is to go back to sof state + */ + CAM_ERR(CAM_ISP, "No wait request"); + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + + /* Send SOF event as empty frame*/ + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + goto end; + } + + req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, + list); + req_isp = (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; + + CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); + if (req_isp->bubble_report && ctx->ctx_crm_intf && + ctx->ctx_crm_intf->notify_err) { + struct cam_req_mgr_error_notify notify; + + notify.link_hdl = ctx->link_hdl; + notify.dev_hdl = ctx->dev_hdl; + notify.req_id = req->request_id; + notify.error = CRM_KMD_ERR_BUBBLE; + ctx->ctx_crm_intf->notify_err(¬ify); + 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; + } + + /* + * 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), 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); + + if (req->request_id > ctx_isp->reported_req_id) { + request_id = req->request_id; + ctx_isp->reported_req_id = request_id; + } + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_ERROR); + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; + CAM_DBG(CAM_ISP, "next substate %d", + ctx_isp->substate_activated); +end: + if (request_id == 0) { + req = list_last_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id); + } else { + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, request_id); + } + return 0; +} + + +static int __cam_isp_ctx_buf_done_in_applied(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; + + rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0); + return rc; +} + + +static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, + void *evt_data) +{ + int rc = 0; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; + struct cam_ctx_request *req; + + 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; + + if (list_empty(&ctx->active_req_list)) + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + else + CAM_DBG(CAM_ISP, "Still need to wait for the buf done"); + + req = list_last_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + if (req) + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_SOF, + req->request_id); + + CAM_DBG(CAM_ISP, "next substate %d", + ctx_isp->substate_activated); + + return rc; +} + +static int __cam_isp_ctx_buf_done_in_epoch(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; + + rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0); + return rc; +} + +static int __cam_isp_ctx_buf_done_in_bubble( + 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; + + rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1); + return rc; +} + +static int __cam_isp_ctx_epoch_in_bubble_applied( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + uint64_t request_id = 0; + + /* + * This means we missed the reg upd ack. So we need to + * transition to BUBBLE state again. + */ + + if (list_empty(&ctx->wait_req_list)) { + /* + * If no pending req in epoch, this is an error case. + * Just go back to the bubble state. + */ + CAM_ERR(CAM_ISP, "No pending request."); + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; + goto end; + } + + req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, + list); + req_isp = (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; + + if (req_isp->bubble_report && ctx->ctx_crm_intf && + ctx->ctx_crm_intf->notify_err) { + struct cam_req_mgr_error_notify notify; + + notify.link_hdl = ctx->link_hdl; + notify.dev_hdl = ctx->dev_hdl; + notify.req_id = req->request_id; + notify.error = CRM_KMD_ERR_BUBBLE; + ctx->ctx_crm_intf->notify_err(¬ify); + atomic_set(&ctx_isp->process_bubble, 1); + CAM_DBG(CAM_REQ, + "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; + } + + /* + * 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) ctx %u", + req->request_id, ctx_isp->active_req_cnt); + ctx_isp->active_req_cnt++; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + + if (!req_isp->bubble_report) { + if (req->request_id > ctx_isp->reported_req_id) { + request_id = req->request_id; + ctx_isp->reported_req_id = request_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_ERROR); + } else + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } else + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; + CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); +end: + req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request, + list); + if (req) + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id); + return 0; +} + +static int __cam_isp_ctx_buf_done_in_bubble_applied( + 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; + + rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1); + + return rc; +} + +static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, + void *evt_data) +{ + int rc = 0; + uint32_t i = 0; + bool found = 0; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_to_report = NULL; + struct cam_ctx_request *req_to_dump = NULL; + struct cam_ctx_request *req_temp; + struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_ctx_req *req_isp_to_report = NULL; + struct cam_req_mgr_error_notify notify; + uint64_t error_request_id; + 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 = + (struct cam_isp_hw_error_event_data *)evt_data; + + uint32_t error_type = error_event_data->error_type; + + CAM_DBG(CAM_ISP, "Enter error_type = %d", error_type); + if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) || + (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW)) + notify.error = CRM_KMD_ERR_OVERFLOW; + + /* + * The error is likely caused by first request on the active list. + * If active list is empty check wait list (maybe error hit as soon + * as RUP and we handle error before RUP. + */ + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_ISP, + "handling error with no active request"); + if (list_empty(&ctx->wait_req_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Error with no active/wait request"); + goto end; + } else { + req_to_dump = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + } + } else { + req_to_dump = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + } + + req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv; + + if (error_event_data->enable_req_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); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if (!req_isp->bubble_report) { + 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 0x%x ctx %u", + req->request_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, + CAM_SYNC_STATE_SIGNALED_ERROR); + fence_map_out->sync_id = -1; + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } else { + found = 1; + break; + } + } + + if (found) + goto move_to_pending; + + list_for_each_entry_safe(req, req_temp, + &ctx->wait_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if (!req_isp->bubble_report) { + 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 0x%x ctx %u", + req->request_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, + CAM_SYNC_STATE_SIGNALED_ERROR); + fence_map_out->sync_id = -1; + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } else { + found = 1; + break; + } + } + +move_to_pending: + /* + * If bubble recovery is enabled on any request we need to move that + * request and all the subsequent requests to the pending list. + * Note: + * We need to traverse the active list in reverse order and add + * to head of pending list. + * e.g. pending current state: 10, 11 | active current state: 8, 9 + * intermittent for loop iteration- pending: 9, 10, 11 | active: 8 + * final state - pending: 8, 9, 10, 11 | active: NULL + */ + if (found) { + list_for_each_entry_safe_reverse(req, req_temp, + &ctx->active_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + ctx_isp->active_req_cnt--; + } + list_for_each_entry_safe_reverse(req, req_temp, + &ctx->wait_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + ctx_isp->active_req_cnt--; + } + } + +end: + do { + if (list_empty(&ctx->pending_req_list)) { + error_request_id = ctx_isp->last_applied_req_id + 1; + req_isp = NULL; + break; + } + req = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + error_request_id = ctx_isp->last_applied_req_id; + + if (req_isp->bubble_report) { + req_to_report = req; + req_isp_to_report = req_to_report->req_priv; + break; + } + + for (i = 0; i < req_isp->num_fence_map_out; i++) { + if (req_isp->fence_map_out[i].sync_id != -1) + rc = cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + req_isp->fence_map_out[i].sync_id = -1; + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + + } while (req->request_id < ctx_isp->last_applied_req_id); + + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { + notify.link_hdl = ctx->link_hdl; + notify.dev_hdl = ctx->dev_hdl; + notify.req_id = error_request_id; + + if (req_isp_to_report && req_isp_to_report->bubble_report) { + if (error_event_data->recovery_enabled) + notify.error = CRM_KMD_ERR_BUBBLE; + } else { + notify.error = CRM_KMD_ERR_FATAL; + } + + 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(¬ify); + + /* + * 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; + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Can not notify ERRROR to CRM for ctx %u", + ctx->ctx_id); + rc = -EFAULT; + } + + CAM_DBG(CAM_ISP, "Exit"); + + 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; + + 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_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(¬ify); + 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); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_SOF, request_id); + } 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(¬ify); + 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_REG_UPDATE, + 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 */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + __cam_isp_ctx_sof_in_activated_state, + __cam_isp_ctx_reg_upd_in_sof, + __cam_isp_ctx_notify_sof_in_activated_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_reg_upd_in_activated_state, + __cam_isp_ctx_epoch_in_applied, + __cam_isp_ctx_notify_eof_in_activated_state, + __cam_isp_ctx_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_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 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) +{ + int rc = 0; + struct cam_ctx_request *req; + struct cam_ctx_request *active_req = NULL; + struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *active_req_isp; + struct cam_isp_context *ctx_isp = NULL; + struct cam_hw_config_args cfg; + + if (list_empty(&ctx->pending_req_list)) { + CAM_ERR(CAM_ISP, "No available request for Apply id %lld", + apply->request_id); + rc = -EFAULT; + goto end; + } + + /* + * When the pipeline has issue, the requests can be queued up in the + * pipeline. In this case, we should reject the additional request. + * The maximum number of request allowed to be outstanding is 2. + * + */ + 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); + spin_unlock_bh(&ctx->lock); + + /* + * Check whether the request id is matching the tip, if not, this means + * we are in the middle of the error handling. Need to reject this apply + */ + if (req->request_id != apply->request_id) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Invalid Request Id asking %llu existing %llu", + apply->request_id, req->request_id); + rc = -EFAULT; + goto end; + } + + 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(CAM_ISP, + "Reject apply request (id %lld) due to congestion(cnt = %d) ctx %u", + req->request_id, + ctx_isp->active_req_cnt, + ctx->ctx_id); + + spin_lock_bh(&ctx->lock); + if (!list_empty(&ctx->active_req_list)) + active_req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + else + CAM_ERR_RATE_LIMIT(CAM_ISP, + "WARNING: should not happen (cnt = %d) but active_list empty", + ctx_isp->active_req_cnt); + spin_unlock_bh(&ctx->lock); + + if (active_req) { + active_req_isp = + (struct cam_isp_ctx_req *) active_req->req_priv; + __cam_isp_ctx_handle_buf_done_fail_log( + active_req->request_id, active_req_isp); + } + + rc = -EFAULT; + goto end; + } + req_isp->bubble_report = apply->report_if_bubble; + + cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; + cfg.request_id = req->request_id; + cfg.hw_update_entries = req_isp->cfg; + cfg.num_hw_update_entries = req_isp->num_cfg; + cfg.priv = &req_isp->hw_update_data; + cfg.init_packet = 0; + + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); + } else { + spin_lock_bh(&ctx->lock); + ctx_isp->substate_activated = next_state; + ctx_isp->last_applied_req_id = apply->request_id; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->wait_req_list); + CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld", + next_state, ctx_isp->last_applied_req_id); + spin_unlock_bh(&ctx->lock); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, + req->request_id); + } +end: + return rc; +} + +static int __cam_isp_ctx_apply_req_in_sof( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "current substate %d", + ctx_isp->substate_activated); + 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); + + return rc; +} + +static int __cam_isp_ctx_apply_req_in_epoch( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "current substate %d", + ctx_isp->substate_activated); + 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); + + return rc; +} + +static int __cam_isp_ctx_apply_req_in_bubble( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "current substate %d", + ctx_isp->substate_activated); + 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); + + return rc; +} + +static int __cam_isp_ctx_flush_req(struct cam_context *ctx, + struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req) +{ + int i, rc, tmp = 0; + uint32_t cancel_req_id_found = 0; + struct cam_ctx_request *req; + struct cam_ctx_request *req_temp; + struct cam_isp_ctx_req *req_isp; + struct list_head flush_list; + struct cam_isp_context *ctx_isp = NULL; + + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + + INIT_LIST_HEAD(&flush_list); + if (list_empty(req_list)) { + CAM_DBG(CAM_ISP, "request list is empty"); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + CAM_ERR(CAM_ISP, "no request to cancel"); + return -EINVAL; + } else + return 0; + } + + CAM_DBG(CAM_REQ, "Flush [%u] in progress for req_id %llu", + flush_req->type, flush_req->req_id); + list_for_each_entry_safe(req, req_temp, req_list, list) { + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + if (req->request_id != flush_req->req_id) { + continue; + } else { + list_del_init(&req->list); + list_add_tail(&req->list, &flush_list); + cancel_req_id_found = 1; + __cam_isp_ctx_update_state_monitor_array( + ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_FLUSH, + req->request_id); + break; + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &flush_list); + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_FLUSH, req->request_id); + } + + list_for_each_entry_safe(req, req_temp, &flush_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + for (i = 0; i < req_isp->num_fence_map_out; i++) { + if (req_isp->fence_map_out[i].sync_id != -1) { + CAM_DBG(CAM_ISP, "Flush req 0x%llx, fence %d", + req->request_id, + req_isp->fence_map_out[i].sync_id); + rc = cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) { + tmp = req_isp->fence_map_out[i].sync_id; + CAM_ERR_RATE_LIMIT(CAM_ISP, + "signal fence %d failed", tmp); + } + req_isp->fence_map_out[i].sync_id = -1; + } + } + list_add_tail(&req->list, &ctx->free_req_list); + } + + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && + !cancel_req_id_found) + CAM_DBG(CAM_ISP, + "Flush request id:%lld is not found in the list", + flush_req->req_id); + + return 0; +} + +static int __cam_isp_ctx_flush_req_in_top_state( + struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush_req) +{ + int rc = 0; + struct cam_isp_context *ctx_isp; + + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + CAM_INFO(CAM_ISP, "Last request id to flush is %lld", + flush_req->req_id); + ctx->last_flush_req = flush_req->req_id; + } + + CAM_DBG(CAM_ISP, "try to flush pending list"); + spin_lock_bh(&ctx->lock); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); + spin_unlock_bh(&ctx->lock); + + atomic_set(&ctx_isp->process_bubble, 0); + return rc; +} + +static int __cam_isp_ctx_flush_req_in_ready( + struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush_req) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "try to flush pending list"); + spin_lock_bh(&ctx->lock); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); + + /* if nothing is in pending req list, change state to acquire */ + if (list_empty(&ctx->pending_req_list)) + ctx->state = CAM_CTX_ACQUIRED; + spin_unlock_bh(&ctx->lock); + + trace_cam_context_state("ISP", ctx); + + CAM_DBG(CAM_ISP, "Flush request in ready state. next state %d", + ctx->state); + return rc; +} + +static struct cam_ctx_ops + cam_isp_ctx_activated_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 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) +{ + int rc = 0; + struct cam_context *ctx = ctx_isp->base; + struct cam_req_mgr_trigger_notify notify; + struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; + uint64_t request_id = 0; + + 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_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", + ctx_isp->frame_id, ctx_isp->sof_timestamp_val); + + /* + * notify reqmgr with sof signal. Note, due to scheduling delay + * we can run into situation that two active requests has already + * be in the active queue while we try to do the notification. + * In this case, we need to skip the current notification. This + * helps the state machine to catch up the delay. + */ + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger && + ctx_isp->active_req_cnt <= 2) { + 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(¬ify); + CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", + ctx_isp->frame_id); + + /* + * It is idle frame with out any applied request id, send + * request id as zero + */ + __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"); + } + + if (list_empty(&ctx->active_req_list)) + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + else + CAM_DBG(CAM_ISP, "Still need to wait for the buf done"); + + CAM_DBG(CAM_ISP, "next substate %d", + ctx_isp->substate_activated); + return rc; +} + +static int __cam_isp_ctx_rdi_only_sof_in_applied_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; + + 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_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", + ctx_isp->frame_id, ctx_isp->sof_timestamp_val); + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED; + CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + + return 0; +} + +static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; + uint64_t request_id = 0; + + /* + * Sof in bubble applied state means, reg update not received. + * before increment frame id and override time stamp value, send + * the previous sof time stamp that got captured in the + * sof in applied state. + */ + CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", + ctx_isp->frame_id, ctx_isp->sof_timestamp_val); + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + ctx_isp->frame_id++; + ctx_isp->sof_timestamp_val = sof_event_data->timestamp; + ctx_isp->boot_timestamp = sof_event_data->boot_time; + 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)) { + /* + * If no pending req in epoch, this is an error case. + * The recovery is to go back to sof state + */ + CAM_ERR(CAM_ISP, "No wait request"); + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + + /* Send SOF event as empty frame*/ + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + goto end; + } + + req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, + list); + req_isp = (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; + + CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); + if (req_isp->bubble_report && ctx->ctx_crm_intf && + ctx->ctx_crm_intf->notify_err) { + struct cam_req_mgr_error_notify notify; + + notify.link_hdl = ctx->link_hdl; + notify.dev_hdl = ctx->dev_hdl; + notify.req_id = req->request_id; + notify.error = CRM_KMD_ERR_BUBBLE; + ctx->ctx_crm_intf->notify_err(¬ify); + CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld", + ctx_isp->frame_id); + } else { + req_isp->bubble_report = 0; + } + + /* + * Always move the request to active list. Let buf done + * function handles the rest. + */ + ctx_isp->active_req_cnt++; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)", + req->request_id, ctx_isp->active_req_cnt); + + if (!req_isp->bubble_report) { + if (req->request_id > ctx_isp->reported_req_id) { + request_id = req->request_id; + ctx_isp->reported_req_id = request_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_ERROR); + } else + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } else + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + /* change the state to bubble, as reg update has not come */ + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; + CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); +end: + return 0; +} + +static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + uint32_t i; + struct cam_ctx_request *req; + struct cam_context *ctx = ctx_isp->base; + struct cam_req_mgr_trigger_notify notify; + struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; + struct cam_isp_ctx_req *req_isp; + uint64_t request_id = 0; + + 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_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", + ctx_isp->frame_id, ctx_isp->sof_timestamp_val); + /* + * Signal all active requests with error and move the all the active + * requests to free list + */ + while (!list_empty(&ctx->active_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + CAM_DBG(CAM_ISP, "signal fence in active list. fence num %d", + req_isp->num_fence_map_out); + for (i = 0; i < req_isp->num_fence_map_out; i++) + if (req_isp->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } + + /* notify reqmgr with sof signal */ + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { + 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(¬ify); + CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", + ctx_isp->frame_id); + + } else { + CAM_ERR(CAM_ISP, "Can not notify SOF to CRM"); + } + + /* + * It is idle frame with out any applied request id, send + * request id as zero + */ + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + + CAM_DBG(CAM_ISP, "next substate %d", + ctx_isp->substate_activated); + + return 0; +} + +static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_ctx_request *req; + 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; + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; + /* notify reqmgr with sof signal*/ + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { + if (list_empty(&ctx->wait_req_list)) { + CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request"); + goto error; + } + 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; + request_id = + (req_isp->hw_update_data.packet_opcode_type == + CAM_ISP_PACKET_INIT_DEV) ? + 0 : req->request_id; + + 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_ISP, + "move request %lld to active list(cnt = %d)", + req->request_id, ctx_isp->active_req_cnt); + /* if packet has buffers, set correct request id */ + request_id = req->request_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 req %lld to free list(cnt=%d)", + req->request_id, ctx_isp->active_req_cnt); + } + + 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(¬ify); + CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", + ctx_isp->frame_id); + } else { + CAM_ERR(CAM_ISP, "Can not notify SOF to CRM"); + } + if (request_id) + ctx_isp->reported_req_id = request_id; + + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + + return 0; +error: + /* Send SOF event as idle frame*/ + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + /* + * There is no request in the pending list, move the sub state machine + * to SOF sub state + */ + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + + return 0; +} + +static struct cam_isp_ctx_irq_ops + cam_isp_ctx_rdi_only_activated_state_machine_irq + [CAM_ISP_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .irq_ops = { + NULL, + __cam_isp_ctx_rdi_only_sof_in_top_state, + __cam_isp_ctx_reg_upd_in_sof, + NULL, + NULL, + NULL, + }, + }, + /* APPLIED */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + __cam_isp_ctx_rdi_only_sof_in_applied_state, + NULL, + NULL, + NULL, + __cam_isp_ctx_buf_done_in_applied, + }, + }, + /* EPOCH */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + __cam_isp_ctx_rdi_only_sof_in_top_state, + NULL, + NULL, + NULL, + __cam_isp_ctx_buf_done_in_epoch, + }, + }, + /* BUBBLE*/ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + __cam_isp_ctx_rdi_only_sof_in_bubble_state, + NULL, + NULL, + NULL, + __cam_isp_ctx_buf_done_in_bubble, + }, + }, + /* BUBBLE APPLIED ie PRE_BUBBLE */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + __cam_isp_ctx_rdi_only_sof_in_bubble_applied, + __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state, + NULL, + NULL, + __cam_isp_ctx_buf_done_in_bubble_applied, + }, + }, + /* HW ERROR */ + { + }, + /* HALT */ + { + }, +}; + +static int __cam_isp_ctx_rdi_only_apply_req_top_state( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "current substate %d", + ctx_isp->substate_activated); + 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); + + return rc; +} + +static struct cam_ctx_ops + cam_isp_ctx_rdi_only_activated_state_machine + [CAM_ISP_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .ioctl_ops = {}, + .crm_ops = { + .apply_req = __cam_isp_ctx_rdi_only_apply_req_top_state, + }, + .irq_ops = NULL, + }, + /* APPLIED */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* EPOCH */ + { + .ioctl_ops = {}, + .crm_ops = { + .apply_req = __cam_isp_ctx_rdi_only_apply_req_top_state, + }, + .irq_ops = NULL, + }, + /* PRE BUBBLE */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* BUBBLE */ + { + .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_release_hw_in_top_state(struct cam_context *ctx, + void *cmd) +{ + int rc = 0; + struct cam_hw_release_args rel_arg; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_req_mgr_flush_request flush_req; + + 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->last_flush_req = 0; + ctx_isp->frame_id = 0; + ctx_isp->active_req_cnt = 0; + ctx_isp->reported_req_id = 0; + ctx_isp->hw_acquired = false; + ctx_isp->init_received = false; + + atomic64_set(&ctx_isp->state_monitor_head, -1); + + /* + * Ideally, we should never have any active request here. + * 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"); + + /* Flush all the pending request list */ + flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; + flush_req.link_hdl = ctx->link_hdl; + flush_req.dev_hdl = ctx->dev_hdl; + + CAM_DBG(CAM_ISP, "try to flush pending list"); + 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; + + trace_cam_context_state("ISP", ctx); + CAM_DBG(CAM_ISP, "Release device success[%u] next state %d", + ctx->ctx_id, ctx->state); + return rc; +} + +/* 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; + struct cam_isp_context *ctx_isp = + (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; + } + + 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; + ctx_isp->hw_acquired = false; + ctx_isp->init_received = false; + + atomic64_set(&ctx_isp->state_monitor_head, -1); + + /* + * Ideally, we should never have any active request here. + * 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"); + + /* Flush all the pending request list */ + flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; + flush_req.link_hdl = ctx->link_hdl; + flush_req.dev_hdl = ctx->dev_hdl; + + CAM_DBG(CAM_ISP, "try to flush pending list"); + 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; + + trace_cam_context_state("ISP", ctx); + CAM_DBG(CAM_ISP, "Release device success[%u] next state %d", + ctx->ctx_id, ctx->state); + return rc; +} + +static int __cam_isp_ctx_config_dev_in_top_state( + struct cam_context *ctx, struct cam_config_dev_cmd *cmd) +{ + int rc = 0, i; + struct cam_ctx_request *req = NULL; + struct cam_isp_ctx_req *req_isp; + 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 = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "get free request object......"); + + /* get free request */ + spin_lock_bh(&ctx->lock); + if (!list_empty(&ctx->free_req_list)) { + req = list_first_entry(&ctx->free_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + } + spin_unlock_bh(&ctx->lock); + + if (!req) { + CAM_ERR(CAM_ISP, "No more request obj free"); + return -ENOMEM; + } + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + /* for config dev, only memory handle is supported */ + /* map packet from the memhandle */ + rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, + &packet_addr, &len); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Can not get packet address"); + rc = -EINVAL; + 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); + rc = -EINVAL; + goto free_req; + } + + 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); + CAM_DBG(CAM_ISP, "packet with length %zu, offset 0x%llx", + len, cmd->offset); + CAM_DBG(CAM_ISP, "Packet request id %lld", + packet->header.request_id); + 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.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); + rc = -EINVAL; + goto free_req; + } + + /* 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; + cfg.max_out_map_entries = CAM_ISP_CTX_RES_MAX; + cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX; + cfg.out_map_entries = req_isp->fence_map_out; + cfg.in_map_entries = req_isp->fence_map_in; + cfg.priv = &req_isp->hw_update_data; + cfg.pf_data = &(req->pf_data); + + CAM_DBG(CAM_ISP, "try to prepare config packet......"); + + rc = ctx->hw_mgr_intf->hw_prepare_update( + ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Prepare config packet failed in HW layer"); + rc = -EFAULT; + goto free_req; + } + req_isp->num_cfg = cfg.num_hw_update_entries; + req_isp->num_fence_map_out = cfg.num_out_map_entries; + req_isp->num_fence_map_in = cfg.num_in_map_entries; + req_isp->num_acked = 0; + req_isp->bubble_detected = false; + + for (i = 0; i < req_isp->num_fence_map_out; i++) { + rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id); + if (rc) { + CAM_ERR(CAM_ISP, "Can't get ref for fence %d", + req_isp->fence_map_out[i].sync_id); + goto put_ref; + } + } + + CAM_DBG(CAM_ISP, "num_entry: %d, num fence out: %d, num fence in: %d", + req_isp->num_cfg, req_isp->num_fence_map_out, + req_isp->num_fence_map_in); + + req->request_id = packet->header.request_id; + req->status = 1; + + CAM_DBG(CAM_ISP, "Packet request id %lld packet opcode:%d", + packet->header.request_id, + req_isp->hw_update_data.packet_opcode_type); + + if (req_isp->hw_update_data.packet_opcode_type == + CAM_ISP_PACKET_INIT_DEV) { + if (ctx->state < CAM_CTX_ACTIVATED) { + rc = __cam_isp_ctx_enqueue_init_request(ctx, req); + if (rc) + CAM_ERR(CAM_ISP, "Enqueue INIT pkt failed"); + ctx_isp->init_received = true; + } else { + rc = -EINVAL; + CAM_ERR(CAM_ISP, "Recevied INIT pkt in wrong state"); + } + } else { + if (ctx->state >= CAM_CTX_READY && ctx->ctx_crm_intf->add_req) { + add_req.link_hdl = ctx->link_hdl; + add_req.dev_hdl = ctx->dev_hdl; + add_req.req_id = req->request_id; + add_req.skip_before_applying = 0; + rc = ctx->ctx_crm_intf->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_ISP, "Add req failed: req id=%llu", + req->request_id); + } else { + __cam_isp_ctx_enqueue_request_in_order( + ctx, req); + } + } else { + rc = -EINVAL; + CAM_ERR(CAM_ISP, "Recevied Update in wrong state"); + } + } + if (rc) + goto put_ref; + + CAM_DBG(CAM_REQ, + "Preprocessing Config req_id %lld successful on ctx %u", + req->request_id, ctx->ctx_id); + + return rc; + +put_ref: + for (--i; i >= 0; i--) { + 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); + } +free_req: + spin_lock_bh(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock_bh(&ctx->lock); + + return rc; +} + +static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc = 0; + struct cam_hw_acquire_args param; + struct cam_isp_resource *isp_res = NULL; + struct cam_create_dev_hdl req_hdl_param; + struct cam_hw_release_args release; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_ISP, "HW interface is not ready"); + rc = -EFAULT; + goto end; + } + + CAM_DBG(CAM_ISP, + "session_hdl 0x%x, num_resources %d, hdl type %d, res %lld", + cmd->session_handle, cmd->num_resources, + cmd->handle_type, cmd->resource_hdl); + + if (cmd->num_resources == CAM_API_COMPAT_CONSTANT) { + ctx_isp->split_acquire = true; + CAM_DBG(CAM_ISP, "Acquire dev handle"); + goto get_dev_handle; + } + + if (cmd->num_resources > CAM_ISP_CTX_RES_MAX) { + CAM_ERR(CAM_ISP, "Too much resources in the acquire"); + rc = -ENOMEM; + goto end; + } + + /* for now we only support user pointer */ + if (cmd->handle_type != 1) { + CAM_ERR(CAM_ISP, "Only user pointer is supported"); + rc = -EINVAL; + goto end; + } + + isp_res = kzalloc( + sizeof(*isp_res)*cmd->num_resources, GFP_KERNEL); + if (!isp_res) { + rc = -ENOMEM; + goto end; + } + + CAM_DBG(CAM_ISP, "start copy %d resources from user", + cmd->num_resources); + + if (copy_from_user(isp_res, u64_to_user_ptr(cmd->resource_hdl), + sizeof(*isp_res)*cmd->num_resources)) { + rc = -EFAULT; + goto free_res; + } + + param.context_data = ctx; + param.event_cb = ctx->irq_cb_intf; + param.num_acq = cmd->num_resources; + param.acquire_info = (uintptr_t) isp_res; + + /* call HW manager to reserve the resource */ + rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, + ¶m); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Acquire device failed"); + goto free_res; + } + + /* 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_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); + if (rc) { + CAM_ERR(CAM_ISP, "HW command failed"); + goto free_hw; + } + + if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) { + /* + * this context has rdi only resource assign rdi only + * state machine + */ + CAM_DBG(CAM_ISP, "RDI only session Context"); + + ctx_isp->substate_machine_irq = + 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 = + cam_isp_ctx_activated_state_machine_irq; + ctx_isp->substate_machine = + cam_isp_ctx_activated_state_machine; + } + + ctx_isp->hw_ctx = param.ctxt_to_hw_map; + ctx_isp->hw_acquired = true; + ctx_isp->split_acquire = false; + ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + + atomic64_set(&ctx_isp->state_monitor_head, -1); + + kfree(isp_res); + isp_res = NULL; + +get_dev_handle: + + req_hdl_param.session_hdl = cmd->session_handle; + /* bridge is not ready for these flags. so false for now */ + req_hdl_param.v4l2_sub_dev_flag = 0; + req_hdl_param.media_entity_flag = 0; + req_hdl_param.ops = ctx->crm_ctx_intf; + req_hdl_param.priv = ctx; + + CAM_DBG(CAM_ISP, "get device handle form bridge"); + ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param); + if (ctx->dev_hdl <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_ISP, "Can not create device handle"); + goto free_hw; + } + cmd->dev_handle = ctx->dev_hdl; + + /* store session information */ + ctx->session_hdl = cmd->session_handle; + ctx->state = CAM_CTX_ACQUIRED; + + trace_cam_context_state("ISP", ctx); + CAM_DBG(CAM_ISP, + "Acquire success on session_hdl 0x%x num_rsrces %d ctx %u", + cmd->session_handle, cmd->num_resources, ctx->ctx_id); + + return rc; + +free_hw: + release.ctxt_to_hw_map = ctx_isp->hw_ctx; + if (ctx_isp->hw_acquired) + ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, + &release); + ctx_isp->hw_ctx = NULL; + ctx_isp->hw_acquired = false; +free_res: + kfree(isp_res); +end: + return rc; +} + +static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, + void *args) +{ + int rc = 0; + struct cam_acquire_hw_cmd_v1 *cmd = + (struct cam_acquire_hw_cmd_v1 *)args; + struct cam_hw_acquire_args param; + struct cam_hw_release_args release; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_ISP, "HW interface is not ready"); + rc = -EFAULT; + goto end; + } + + CAM_DBG(CAM_ISP, + "session_hdl 0x%x, hdl type %d, res %lld", + cmd->session_handle, cmd->handle_type, cmd->resource_hdl); + + /* for now we only support user pointer */ + if (cmd->handle_type != 1) { + CAM_ERR(CAM_ISP, "Only user pointer is supported"); + rc = -EINVAL; + goto end; + } + + if (cmd->data_size < sizeof(*acquire_hw_info)) { + CAM_ERR(CAM_ISP, "data_size is not a valid value"); + goto end; + } + + acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL); + if (!acquire_hw_info) { + rc = -ENOMEM; + goto end; + } + + CAM_DBG(CAM_ISP, "start copy resources from user"); + + if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl, + cmd->data_size)) { + rc = -EFAULT; + goto free_res; + } + + memset(¶m, 0, sizeof(param)); + param.context_data = ctx; + param.event_cb = ctx->irq_cb_intf; + param.num_acq = CAM_API_COMPAT_CONSTANT; + param.acquire_info_size = cmd->data_size; + param.acquire_info = (uint64_t) acquire_hw_info; + + /* call HW manager to reserve the resource */ + rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, + ¶m); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Acquire device failed"); + goto free_res; + } + + /* 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_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); + if (rc) { + CAM_ERR(CAM_ISP, "HW command failed"); + goto free_hw; + } + + if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) { + /* + * this context has rdi only resource assign rdi only + * state machine + */ + CAM_DBG(CAM_ISP, "RDI only session Context"); + + ctx_isp->substate_machine_irq = + 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 = + cam_isp_ctx_activated_state_machine_irq; + ctx_isp->substate_machine = + cam_isp_ctx_activated_state_machine; + } + + ctx_isp->hw_ctx = param.ctxt_to_hw_map; + ctx_isp->hw_acquired = true; + ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + + atomic64_set(&ctx_isp->state_monitor_head, -1); + + trace_cam_context_state("ISP", ctx); + CAM_DBG(CAM_ISP, + "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; + +free_hw: + release.ctxt_to_hw_map = ctx_isp->hw_ctx; + ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); + ctx_isp->hw_ctx = NULL; + ctx_isp->hw_acquired = false; +free_res: + kfree(acquire_hw_info); +end: + return rc; +} + +static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, + void *args) +{ + int rc = 0, i, j; + struct cam_acquire_hw_cmd_v2 *cmd = + (struct cam_acquire_hw_cmd_v2 *)args; + struct cam_hw_acquire_args param; + struct cam_hw_release_args release; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_ISP, "HW interface is not ready"); + rc = -EFAULT; + goto end; + } + + CAM_DBG(CAM_ISP, + "session_hdl 0x%x, hdl type %d, res %lld", + cmd->session_handle, cmd->handle_type, cmd->resource_hdl); + + /* for now we only support user pointer */ + if (cmd->handle_type != 1) { + CAM_ERR(CAM_ISP, "Only user pointer is supported"); + rc = -EINVAL; + goto end; + } + + if (cmd->data_size < sizeof(*acquire_hw_info)) { + CAM_ERR(CAM_ISP, "data_size is not a valid value"); + goto end; + } + + acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL); + if (!acquire_hw_info) { + rc = -ENOMEM; + goto end; + } + + CAM_DBG(CAM_ISP, "start copy resources from user"); + + if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl, + cmd->data_size)) { + rc = -EFAULT; + goto free_res; + } + + memset(¶m, 0, sizeof(param)); + param.context_data = ctx; + param.event_cb = ctx->irq_cb_intf; + param.num_acq = CAM_API_COMPAT_CONSTANT; + param.acquire_info_size = cmd->data_size; + param.acquire_info = (uint64_t) acquire_hw_info; + + /* call HW manager to reserve the resource */ + rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, + ¶m); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Acquire device failed"); + goto free_res; + } + + /* 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_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); + if (rc) { + CAM_ERR(CAM_ISP, "HW command failed"); + goto free_hw; + } + + if (param.valid_acquired_hw) { + for (i = 0; i < CAM_MAX_ACQ_RES; i++) + cmd->hw_info.acquired_hw_id[i] = + param.acquired_hw_id[i]; + + for (i = 0; i < CAM_MAX_ACQ_RES; i++) + for (j = 0; j < CAM_MAX_HW_SPLIT; j++) + cmd->hw_info.acquired_hw_path[i][j] = + param.acquired_hw_path[i][j]; + } + cmd->hw_info.valid_acquired_hw = + param.valid_acquired_hw; + + cmd->hw_info.valid_acquired_hw = param.valid_acquired_hw; + + if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) { + /* + * this context has rdi only resource assign rdi only + * state machine + */ + CAM_DBG(CAM_ISP, "RDI only session Context"); + + ctx_isp->substate_machine_irq = + 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 = + cam_isp_ctx_activated_state_machine_irq; + ctx_isp->substate_machine = + cam_isp_ctx_activated_state_machine; + } + + 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 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; + +free_hw: + release.ctxt_to_hw_map = ctx_isp->hw_ctx; + ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); + ctx_isp->hw_ctx = NULL; + ctx_isp->hw_acquired = false; +free_res: + kfree(acquire_hw_info); +end: + return rc; +} + + +static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx, + void *args) +{ + int rc = -EINVAL; + uint32_t api_version; + + if (!ctx || !args) { + CAM_ERR(CAM_ISP, "Invalid input pointer"); + return rc; + } + + api_version = *((uint32_t *)args); + if (api_version == 1) + rc = __cam_isp_ctx_acquire_hw_v1(ctx, args); + else if (api_version == 2) + rc = __cam_isp_ctx_acquire_hw_v2(ctx, args); + else + CAM_ERR(CAM_ISP, "Unsupported api version %d", api_version); + + return rc; +} + +static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + if (!ctx_isp->hw_acquired) { + CAM_ERR(CAM_ISP, "HW is not acquired, reject packet"); + return -EINVAL; + } + + rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd); + + if (!rc && (ctx->link_hdl >= 0)) { + ctx->state = CAM_CTX_READY; + trace_cam_context_state("ISP", ctx); + } + + CAM_DBG(CAM_ISP, "next state %d", ctx->state); + return rc; +} + +static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *link) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "Enter........."); + + ctx->link_hdl = link->link_hdl; + ctx->ctx_crm_intf = link->crm_cb; + ctx_isp->subscribe_event = link->subscribe_event; + + /* change state only if we had the init config */ + if (ctx_isp->init_received) { + ctx->state = CAM_CTX_READY; + trace_cam_context_state("ISP", ctx); + } + + CAM_DBG(CAM_ISP, "next state %d", ctx->state); + + return rc; +} + +static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + int rc = 0; + + ctx->link_hdl = -1; + ctx->ctx_crm_intf = NULL; + + return rc; +} + +static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_device_info *dev_info) +{ + int rc = 0; + + dev_info->dev_hdl = ctx->dev_hdl; + strlcpy(dev_info->name, CAM_ISP_DEV_NAME, sizeof(dev_info->name)); + dev_info->dev_id = CAM_REQ_MGR_DEVICE_IFE; + dev_info->p_delay = 1; + dev_info->trigger = CAM_TRIGGER_POINT_SOF; + + return rc; +} + +static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + struct cam_isp_start_args start_isp; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + if (cmd->session_handle != ctx->session_hdl || + cmd->dev_handle != ctx->dev_hdl) { + rc = -EPERM; + goto end; + } + + if (list_empty(&ctx->pending_req_list)) { + /* should never happen */ + CAM_ERR(CAM_ISP, "Start device with empty configuration"); + rc = -EFAULT; + goto end; + } else { + req = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + } + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + if (!ctx_isp->hw_ctx) { + CAM_ERR(CAM_ISP, "Wrong hw context pointer."); + rc = -EFAULT; + goto end; + } + + start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; + start_isp.hw_config.request_id = req->request_id; + start_isp.hw_config.hw_update_entries = req_isp->cfg; + start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg; + start_isp.hw_config.priv = &req_isp->hw_update_data; + start_isp.hw_config.init_packet = 1; + start_isp.start_only = false; + + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->frame_id = 0; + ctx_isp->active_req_cnt = 0; + ctx_isp->reported_req_id = 0; + ctx_isp->substate_activated = ctx_isp->rdi_only_context ? + CAM_ISP_CTX_ACTIVATED_APPLIED : + (req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH : + CAM_ISP_CTX_ACTIVATED_SOF; + + atomic64_set(&ctx_isp->state_monitor_head, -1); + + /* + * Only place to change state before calling the hw due to + * hardware tasklet has higher priority that can cause the + * irq handling comes early + */ + ctx->state = CAM_CTX_ACTIVATED; + trace_cam_context_state("ISP", ctx); + rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, + &start_isp); + if (rc) { + /* HW failure. user need to clean up the resource */ + CAM_ERR(CAM_ISP, "Start HW failed"); + ctx->state = CAM_CTX_READY; + trace_cam_context_state("ISP", ctx); + goto end; + } + CAM_DBG(CAM_ISP, "start device success ctx %u", ctx->ctx_id); + + list_del_init(&req->list); + + if (req_isp->num_fence_map_out) { + list_add_tail(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; + } else { + list_add_tail(&req->list, &ctx->wait_req_list); + } +end: + return rc; +} + +static int __cam_isp_ctx_unlink_in_ready(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + int rc = 0; + + ctx->link_hdl = -1; + ctx->ctx_crm_intf = NULL; + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("ISP", ctx); + + return rc; +} + +static int __cam_isp_ctx_stop_dev_in_activated_unlock( + struct cam_context *ctx, struct cam_start_stop_dev_cmd *stop_cmd) +{ + int rc = 0; + uint32_t i; + struct cam_hw_stop_args stop; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_stop_args stop_isp; + + /* Mask off all the incoming hardware events */ + spin_lock_bh(&ctx->lock); + 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); + + /* stop hw first */ + if (ctx_isp->hw_ctx) { + stop.ctxt_to_hw_map = ctx_isp->hw_ctx; + + if (stop_cmd) + stop_isp.hw_stop_cmd = + CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; + else + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; + + stop_isp.stop_only = false; + stop.args = (void *) &stop_isp; + ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop); + } + + while (!list_empty(&ctx->pending_req_list)) { + req = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + CAM_DBG(CAM_ISP, "signal fence in pending list. fence num %d", + req_isp->num_fence_map_out); + for (i = 0; i < req_isp->num_fence_map_out; i++) + if (req_isp->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + } + + while (!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; + CAM_DBG(CAM_ISP, "signal fence in wait list. fence num %d", + req_isp->num_fence_map_out); + for (i = 0; i < req_isp->num_fence_map_out; i++) + if (req_isp->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + } + + while (!list_empty(&ctx->active_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + CAM_DBG(CAM_ISP, "signal fence in active list. fence num %d", + req_isp->num_fence_map_out); + for (i = 0; i < req_isp->num_fence_map_out; i++) + if (req_isp->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + } + ctx_isp->frame_id = 0; + ctx_isp->active_req_cnt = 0; + ctx_isp->reported_req_id = 0; + atomic_set(&ctx_isp->process_bubble, 0); + atomic64_set(&ctx_isp->state_monitor_head, -1); + + 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; +} + +static int __cam_isp_ctx_stop_dev_in_activated(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *)ctx->ctx_priv; + + __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, cmd); + ctx_isp->init_received = false; + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("ISP", ctx); + return rc; +} + +static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc = 0; + + rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL); + if (rc) + CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc); + + rc = __cam_isp_ctx_release_dev_in_top_state(ctx, cmd); + if (rc) + CAM_ERR(CAM_ISP, "Release device failed rc=%d", rc); + + return rc; +} + +static int __cam_isp_ctx_release_hw_in_activated(struct cam_context *ctx, + void *cmd) +{ + int rc = 0; + + rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL); + if (rc) + CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc); + + rc = __cam_isp_ctx_release_hw_in_top_state(ctx, cmd); + if (rc) + CAM_ERR(CAM_ISP, "Release hw failed rc=%d", rc); + + return rc; +} + +static int __cam_isp_ctx_link_pause(struct cam_context *ctx) +{ + int rc = 0; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW; + 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); + + return rc; +} + +static int __cam_isp_ctx_link_resume(struct cam_context *ctx) +{ + int rc = 0; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW; + 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); + + return rc; +} + +static int __cam_isp_ctx_handle_sof_freeze_evt( + struct cam_context *ctx) +{ + int rc = 0; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_SOF_DEBUG; + isp_hw_cmd_args.u.sof_irq_enable = 1; + 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); + + return rc; +} + +static int __cam_isp_ctx_process_evt(struct cam_context *ctx, + struct cam_req_mgr_link_evt_data *link_evt_data) +{ + int rc = 0; + + switch (link_evt_data->evt_type) { + case CAM_REQ_MGR_LINK_EVT_ERR: + /* No need to handle this message now */ + break; + case CAM_REQ_MGR_LINK_EVT_PAUSE: + __cam_isp_ctx_link_pause(ctx); + break; + case CAM_REQ_MGR_LINK_EVT_RESUME: + __cam_isp_ctx_link_resume(ctx); + break; + case CAM_REQ_MGR_LINK_EVT_SOF_FREEZE: + __cam_isp_ctx_handle_sof_freeze_evt(ctx); + break; + default: + CAM_WARN(CAM_ISP, "Unknown event from CRM"); + break; + } + return rc; +} + +static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + int rc = 0; + + CAM_WARN(CAM_ISP, + "Received unlink in activated state. It's unexpected"); + + rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL); + if (rc) + CAM_WARN(CAM_ISP, "Stop device failed rc=%d", rc); + + rc = __cam_isp_ctx_unlink_in_ready(ctx, unlink); + if (rc) + CAM_ERR(CAM_ISP, "Unlink failed rc=%d", rc); + + return rc; +} + +static int __cam_isp_ctx_apply_req(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_ctx_ops *ctx_ops = NULL; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + trace_cam_apply_req("ISP", apply->request_id); + CAM_DBG(CAM_ISP, "Enter: apply req in Substate %d request _id:%lld", + ctx_isp->substate_activated, apply->request_id); + ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated]; + if (ctx_ops->crm_ops.apply_req) { + rc = ctx_ops->crm_ops.apply_req(ctx, apply); + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No handle function in activated substate %d", + ctx_isp->substate_activated); + rc = -EFAULT; + } + + if (rc) + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Apply failed in active substate %d", + ctx_isp->substate_activated); + return rc; +} + + + +static int __cam_isp_ctx_handle_irq_in_activated(void *context, + uint32_t evt_id, void *evt_data) +{ + int rc = 0; + struct cam_isp_ctx_irq_ops *irq_ops = NULL; + struct cam_context *ctx = (struct cam_context *)context; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *)ctx->ctx_priv; + + spin_lock(&ctx->lock); + + trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id, + __cam_isp_ctx_get_event_ts(evt_id, evt_data)); + + CAM_DBG(CAM_ISP, "Enter: State %d, Substate %d, evt id %d", + ctx->state, ctx_isp->substate_activated, evt_id); + irq_ops = &ctx_isp->substate_machine_irq[ctx_isp->substate_activated]; + if (irq_ops->irq_ops[evt_id]) { + rc = irq_ops->irq_ops[evt_id](ctx_isp, evt_data); + } else { + CAM_DBG(CAM_ISP, "No handle function for substate %d", + ctx_isp->substate_activated); + __cam_isp_ctx_dump_state_monitor_array(ctx_isp); + } + + CAM_DBG(CAM_ISP, "Exit: State %d Substate %d", + ctx->state, ctx_isp->substate_activated); + spin_unlock(&ctx->lock); + return rc; +} + +/* top state machine */ +static struct cam_ctx_ops + cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = __cam_isp_ctx_acquire_dev_in_available, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .acquire_hw = __cam_isp_ctx_acquire_hw_in_acquired, + .release_dev = __cam_isp_ctx_release_dev_in_top_state, + .config_dev = __cam_isp_ctx_config_dev_in_acquired, + .release_hw = __cam_isp_ctx_release_hw_in_top_state, + }, + .crm_ops = { + .link = __cam_isp_ctx_link_in_acquired, + .unlink = __cam_isp_ctx_unlink_in_acquired, + .get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired, + .flush_req = __cam_isp_ctx_flush_req_in_top_state, + }, + .irq_ops = NULL, + .pagefault_ops = cam_isp_context_dump_active_request, + }, + /* Ready */ + { + .ioctl_ops = { + .start_dev = __cam_isp_ctx_start_dev_in_ready, + .release_dev = __cam_isp_ctx_release_dev_in_top_state, + .config_dev = __cam_isp_ctx_config_dev_in_top_state, + .release_hw = __cam_isp_ctx_release_hw_in_top_state, + }, + .crm_ops = { + .unlink = __cam_isp_ctx_unlink_in_ready, + .flush_req = __cam_isp_ctx_flush_req_in_ready, + }, + .irq_ops = NULL, + .pagefault_ops = cam_isp_context_dump_active_request, + }, + /* Activated */ + { + .ioctl_ops = { + .stop_dev = __cam_isp_ctx_stop_dev_in_activated, + .release_dev = __cam_isp_ctx_release_dev_in_activated, + .config_dev = __cam_isp_ctx_config_dev_in_top_state, + .release_hw = __cam_isp_ctx_release_hw_in_activated, + }, + .crm_ops = { + .unlink = __cam_isp_ctx_unlink_in_activated, + .apply_req = __cam_isp_ctx_apply_req, + .flush_req = __cam_isp_ctx_flush_req_in_top_state, + .process_evt = __cam_isp_ctx_process_evt, + }, + .irq_ops = __cam_isp_ctx_handle_irq_in_activated, + .pagefault_ops = cam_isp_context_dump_active_request, + }, +}; + + +static int cam_isp_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + bool mem_found = false; + int rc = 0; + + struct cam_isp_context *isp_ctx = + (struct cam_isp_context *)ctx->ctx_priv; + + if (!isp_ctx) { + CAM_ERR(CAM_ISP, "Invalid isp ctx"); + return -EINVAL; + } + + CAM_INFO(CAM_ISP, "iommu fault handler for isp ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + hw_update_data = &req_isp->hw_update_data; + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &mem_found); + if (rc) + CAM_ERR(CAM_ISP, "Failed to dump pf info"); + + if (mem_found) + CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", + req->request_id, rc); + } + + CAM_INFO(CAM_ISP, "Iterating over wait_list of isp ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->wait_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + hw_update_data = &req_isp->hw_update_data; + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &mem_found); + if (rc) + CAM_ERR(CAM_ISP, "Failed to dump pf info"); + + if (mem_found) + CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", + req->request_id, rc); + } + + return rc; +} + +int cam_isp_context_init(struct cam_isp_context *ctx, + struct cam_context *ctx_base, + struct cam_req_mgr_kmd_ops *crm_node_intf, + struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id) + +{ + int rc = -1; + int i; + + if (!ctx || !ctx_base) { + CAM_ERR(CAM_ISP, "Invalid Context"); + goto err; + } + + /* ISP context setup */ + memset(ctx, 0, sizeof(*ctx)); + + ctx->base = ctx_base; + ctx->frame_id = 0; + ctx->active_req_cnt = 0; + ctx->reported_req_id = 0; + ctx->hw_ctx = NULL; + ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + ctx->substate_machine = cam_isp_ctx_activated_state_machine; + ctx->substate_machine_irq = cam_isp_ctx_activated_state_machine_irq; + ctx->init_timestamp = jiffies_to_msecs(jiffies); + + for (i = 0; i < CAM_CTX_REQ_MAX; i++) { + ctx->req_base[i].req_priv = &ctx->req_isp[i]; + ctx->req_isp[i].base = &ctx->req_base[i]; + } + + /* camera context setup */ + rc = cam_context_init(ctx_base, isp_dev_name, CAM_ISP, ctx_id, + crm_node_intf, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_ISP, "Camera Context Base init failed"); + goto err; + } + + /* link camera context with isp context */ + ctx_base->state_machine = cam_isp_ctx_top_state_machine; + ctx_base->ctx_priv = ctx; + + /* initializing current state for error logging */ + for (i = 0; i < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; i++) { + ctx->cam_isp_ctx_state_monitor[i].curr_state = + CAM_ISP_CTX_ACTIVATED_MAX; + } + atomic64_set(&ctx->state_monitor_head, -1); +err: + return rc; +} + +int cam_isp_context_deinit(struct cam_isp_context *ctx) +{ + int rc = 0; + + if (ctx->base) + cam_context_deinit(ctx->base); + + if (ctx->substate_activated != CAM_ISP_CTX_ACTIVATED_SOF) + CAM_ERR(CAM_ISP, "ISP context substate is invalid"); + + memset(ctx, 0, sizeof(*ctx)); + return rc; +} diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h new file mode 100644 index 000000000000..bbf39b5617cf --- /dev/null +++ b/drivers/cam_isp/cam_isp_context.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ISP_CONTEXT_H_ +#define _CAM_ISP_CONTEXT_H_ + + +#include +#include +#include + +#include "cam_context.h" +#include "cam_isp_hw_mgr_intf.h" + +/* + * Maximum hw resource - This number is based on the maximum + * output port resource. The current maximum resource number + * is 24. + */ +#define CAM_ISP_CTX_RES_MAX 24 + +/* + * Maximum configuration entry size - This is based on the + * worst case DUAL IFE use case plus some margin. + */ +#define CAM_ISP_CTX_CFG_MAX 22 + +/* + * Maximum entries in state monitoring array for error logging + */ +#define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 40 + +/* forward declaration */ +struct cam_isp_context; + +/* cam isp context irq handling function type */ +typedef int (*cam_isp_hw_event_cb_func)(struct cam_isp_context *ctx_isp, + void *evt_data); + +/** + * enum cam_isp_ctx_activated_substate - sub states for activated + * + */ +enum cam_isp_ctx_activated_substate { + 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, +}; + +/** + * enum cam_isp_state_change_trigger - Different types of ISP events + * + */ +enum cam_isp_state_change_trigger { + CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, + CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, + CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE, + CAM_ISP_STATE_CHANGE_TRIGGER_SOF, + CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, + CAM_ISP_STATE_CHANGE_TRIGGER_DONE, + CAM_ISP_STATE_CHANGE_TRIGGER_EOF, + CAM_ISP_STATE_CHANGE_TRIGGER_FLUSH, + CAM_ISP_STATE_CHANGE_TRIGGER_MAX +}; + +/** + * struct cam_isp_ctx_irq_ops - Function table for handling IRQ callbacks + * + * @irq_ops: Array of handle function pointers. + * + */ +struct cam_isp_ctx_irq_ops { + cam_isp_hw_event_cb_func irq_ops[CAM_ISP_HW_EVENT_MAX]; +}; + +/** + * struct cam_isp_ctx_req - ISP context request object + * + * @base: Common request object ponter + * @cfg: ISP hardware configuration array + * @num_cfg: Number of ISP hardware configuration entries + * @fence_map_out: Output fence mapping array + * @num_fence_map_out: Number of the output fence map + * @fence_map_in: Input fence mapping array + * @num_fence_map_in: Number of input fence map + * @num_acked: Count to track acked entried for output. + * If count equals the number of fence out, it means + * the request has been completed. + * @bubble_report: Flag to track if bubble report is active on + * current request + * @hw_update_data: HW update data for this request + * + */ +struct cam_isp_ctx_req { + struct cam_ctx_request *base; + + struct cam_hw_update_entry cfg[CAM_ISP_CTX_CFG_MAX]; + uint32_t num_cfg; + struct cam_hw_fence_map_entry fence_map_out + [CAM_ISP_CTX_RES_MAX]; + uint32_t num_fence_map_out; + struct cam_hw_fence_map_entry fence_map_in[CAM_ISP_CTX_RES_MAX]; + uint32_t num_fence_map_in; + uint32_t num_acked; + int32_t bubble_report; + struct cam_isp_prepare_hw_update_data hw_update_data; + bool bubble_detected; +}; + +/** + * struct cam_isp_context_state_monitor - ISP context state + * monitoring for + * debug purposes + * + * @curr_state: Current sub state that received req + * @trigger: Event type of incoming req + * @req_id: Request id + * @frame_id: Frame id based on SOFs + * @evt_time_stamp Current time stamp + * + */ +struct cam_isp_context_state_monitor { + enum cam_isp_ctx_activated_substate curr_state; + enum cam_isp_state_change_trigger trigger; + uint64_t req_id; + int64_t frame_id; + unsigned int evt_time_stamp; +}; + +/** + * struct cam_isp_context - ISP context object + * + * @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 + * @req_isp: ISP private request object storage + * @hw_ctx: HW object returned by the acquire device command + * @sof_timestamp_val: Captured time stamp value at sof hw event + * @boot_timestamp: Boot time stamp for a given req_id + * @active_req_cnt: Counter for the active request + * @reported_req_id: Last reported request id + * @subscribe_event: The irq event mask that CRM subscribes to, IFE + * will invoke CRM cb at those event. + * @last_applied_req_id: Last applied request id + * @state_monitor_head: Write index to the state monitoring array + * @cam_isp_ctx_state_monitor: State monitoring array + * @rdi_only_context: Get context type information. + * true, if context is rdi only context + * @hw_acquired: Indicate whether HW resources are acquired + * @init_received: Indicate whether init config packet is received + * @split_acquire: Indicate whether a separate acquire is expected + * @init_timestamp: Timestamp at which this context is initialized + * + */ +struct cam_isp_context { + struct cam_context *base; + + 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; + + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; + + void *hw_ctx; + uint64_t sof_timestamp_val; + uint64_t boot_timestamp; + int32_t active_req_cnt; + int64_t reported_req_id; + uint32_t subscribe_event; + int64_t last_applied_req_id; + atomic64_t state_monitor_head; + struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; + bool rdi_only_context; + bool hw_acquired; + bool init_received; + bool split_acquire; + unsigned int init_timestamp; +}; + +/** + * cam_isp_context_init() + * + * @brief: Initialization function for the ISP context + * + * @ctx: ISP context obj to be initialized + * @bridge_ops: Bridge call back funciton + * @hw_intf: ISP hw manager interface + * @ctx_id: ID for this context + * + */ +int cam_isp_context_init(struct cam_isp_context *ctx, + struct cam_context *ctx_base, + struct cam_req_mgr_kmd_ops *bridge_ops, + struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id); + +/** + * cam_isp_context_deinit() + * + * @brief: Deinitialize function for the ISP context + * + * @ctx: ISP context obj to be deinitialized + * + */ +int cam_isp_context_deinit(struct cam_isp_context *ctx); + + +#endif /* __CAM_ISP_CONTEXT_H__ */ diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c new file mode 100644 index 000000000000..b93ae3fd5b82 --- /dev/null +++ b/drivers/cam_isp/cam_isp_dev.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cam_isp_dev.h" +#include "cam_hw_mgr_intf.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_node.h" +#include "cam_debug_util.h" +#include "cam_smmu_api.h" + +static struct cam_isp_dev g_isp_dev; + +static void cam_isp_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + +static const struct of_device_id cam_isp_dt_match[] = { + { + .compatible = "qcom,cam-isp" + }, + {} +}; + +static int cam_isp_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + mutex_lock(&g_isp_dev.isp_mutex); + g_isp_dev.open_cnt++; + mutex_unlock(&g_isp_dev.isp_mutex); + + return 0; +} + +static int cam_isp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = 0; + struct cam_node *node = v4l2_get_subdevdata(sd); + + mutex_lock(&g_isp_dev.isp_mutex); + if (g_isp_dev.open_cnt <= 0) { + CAM_DBG(CAM_ISP, "ISP subdev is already closed"); + rc = -EINVAL; + goto end; + } + + g_isp_dev.open_cnt--; + if (!node) { + CAM_ERR(CAM_ISP, "Node ptr is NULL"); + rc = -EINVAL; + goto end; + } + + if (g_isp_dev.open_cnt == 0) + cam_node_shutdown(node); + +end: + mutex_unlock(&g_isp_dev.isp_mutex); + return rc; +} + +static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { + .close = cam_isp_subdev_close, + .open = cam_isp_subdev_open, +}; + +static int cam_isp_dev_remove(struct platform_device *pdev) +{ + int rc = 0; + int i; + + /* clean up resources */ + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_isp_context_deinit(&g_isp_dev.ctx_isp[i]); + if (rc) + CAM_ERR(CAM_ISP, "ISP context %d deinit failed", + i); + } + + rc = cam_subdev_remove(&g_isp_dev.sd); + if (rc) + CAM_ERR(CAM_ISP, "Unregister failed"); + + memset(&g_isp_dev, 0, sizeof(g_isp_dev)); + return 0; +} + +static int cam_isp_dev_probe(struct platform_device *pdev) +{ + int rc = -1; + int i; + struct cam_hw_mgr_intf hw_mgr_intf; + struct cam_node *node; + int iommu_hdl = -1; + + g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; + /* Initialize the v4l2 subdevice first. (create cam_node) */ + rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, + CAM_IFE_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_ISP, "ISP cam_subdev_probe failed!"); + goto err; + } + node = (struct cam_node *) g_isp_dev.sd.token; + + memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf)); + rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf, &iommu_hdl); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!"); + goto unregister; + } + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_isp_context_init(&g_isp_dev.ctx_isp[i], + &g_isp_dev.ctx[i], + &node->crm_node_intf, + &node->hw_mgr_intf, + i); + if (rc) { + CAM_ERR(CAM_ISP, "ISP context init failed!"); + goto unregister; + } + } + + rc = cam_node_init(node, &hw_mgr_intf, g_isp_dev.ctx, CAM_CTX_MAX, + CAM_ISP_DEV_NAME); + if (rc) { + CAM_ERR(CAM_ISP, "ISP node init failed!"); + goto unregister; + } + + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_isp_dev_iommu_fault_handler, node); + + mutex_init(&g_isp_dev.isp_mutex); + + CAM_INFO(CAM_ISP, "Camera ISP probe complete"); + + return 0; +unregister: + rc = cam_subdev_remove(&g_isp_dev.sd); +err: + return rc; +} + + +static struct platform_driver isp_driver = { + .probe = cam_isp_dev_probe, + .remove = cam_isp_dev_remove, + .driver = { + .name = "cam_isp", + .owner = THIS_MODULE, + .of_match_table = cam_isp_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_isp_dev_init_module(void) +{ + return platform_driver_register(&isp_driver); +} + +static void __exit cam_isp_dev_exit_module(void) +{ + platform_driver_unregister(&isp_driver); +} + +module_init(cam_isp_dev_init_module); +module_exit(cam_isp_dev_exit_module); +MODULE_DESCRIPTION("MSM ISP driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/cam_isp_dev.h b/drivers/cam_isp/cam_isp_dev.h new file mode 100644 index 000000000000..cf9140eb8c88 --- /dev/null +++ b/drivers/cam_isp/cam_isp_dev.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ISP_DEV_H_ +#define _CAM_ISP_DEV_H_ + +#include "cam_subdev.h" +#include "cam_hw_mgr_intf.h" +#include "cam_context.h" +#include "cam_isp_context.h" + +/** + * struct cam_isp_dev - Camera ISP V4l2 device node + * + * @sd: Commone camera subdevice node + * @ctx: Isp base context storage + * @ctx_isp: Isp private context storage + * @isp_mutex: ISP dev mutex + * @open_cnt: Open device count + */ +struct cam_isp_dev { + struct cam_subdev sd; + struct cam_context ctx[CAM_CTX_MAX]; + struct cam_isp_context ctx_isp[CAM_CTX_MAX]; + struct mutex isp_mutex; + int32_t open_cnt; +}; + +#endif /* __CAM_ISP_DEV_H__ */ diff --git a/drivers/cam_isp/isp_hw_mgr/Makefile b/drivers/cam_isp/isp_hw_mgr/Makefile new file mode 100644 index 000000000000..33b808c934e3 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(src) + +obj-$(CONFIG_SPECTRA_CAMERA) += hw_utils/ isp_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_hw_mgr.o cam_ife_hw_mgr.o diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c new file mode 100644 index 000000000000..cb0b341b981f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -0,0 +1,6280 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "cam_smmu_api.h" +#include "cam_req_mgr_workq.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_isp_hw.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_vfe_hw_intf.h" +#include "cam_isp_packet_parser.h" +#include "cam_ife_hw_mgr.h" +#include "cam_cdm_intf_api.h" +#include "cam_packet_util.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_mem_mgr_api.h" +#include "cam_common_util.h" + +#define CAM_IFE_HW_ENTRIES_MAX 20 + +#define TZ_SVC_SMMU_PROGRAM 0x15 +#define TZ_SAFE_SYSCALL_ID 0x3 +#define CAM_IFE_SAFE_DISABLE 0 +#define CAM_IFE_SAFE_ENABLE 1 +#define SMMU_SE_IFE 0 + +#define CAM_ISP_PACKET_META_MAX \ + (CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1) + +#define CAM_ISP_GENERIC_BLOB_TYPE_MAX \ + (CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 + 1) + +static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = { + CAM_ISP_HW_CMD_GET_HFR_UPDATE, + CAM_ISP_HW_CMD_CLOCK_UPDATE, + 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, + CAM_ISP_HW_CMD_UBWC_UPDATE_V2, + CAM_ISP_HW_CMD_CORE_CONFIG, + CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, + CAM_ISP_HW_CMD_BW_UPDATE_V2, +}; + +static struct cam_ife_hw_mgr g_ife_hw_mgr; + +static int cam_ife_hw_mgr_event_handler( + void *priv, + uint32_t evt_id, + void *evt_info); + +static int cam_ife_notify_safe_lut_scm(bool safe_trigger) +{ + uint32_t camera_hw_version, rc = 0; + struct scm_desc desc = {0}; + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (!rc) { + switch (camera_hw_version) { + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_175_V100: + + desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL); + desc.args[0] = SMMU_SE_IFE; + desc.args[1] = safe_trigger; + + CAM_DBG(CAM_ISP, "Safe scm call %d", safe_trigger); + if (scm_call2(SCM_SIP_FNID(TZ_SVC_SMMU_PROGRAM, + TZ_SAFE_SYSCALL_ID), &desc)) { + CAM_ERR(CAM_ISP, + "scm call to Enable Safe failed"); + rc = -EINVAL; + } + break; + default: + break; + } + } + + return rc; +} + +static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv, + void *hw_caps_args) +{ + int rc = 0; + int i; + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query = hw_caps_args; + struct cam_isp_query_cap_cmd query_isp; + + CAM_DBG(CAM_ISP, "enter"); + + if (copy_from_user(&query_isp, + u64_to_user_ptr(query->caps_handle), + sizeof(struct cam_isp_query_cap_cmd))) { + rc = -EFAULT; + return rc; + } + + query_isp.device_iommu.non_secure = hw_mgr->mgr_common.img_iommu_hdl; + query_isp.device_iommu.secure = hw_mgr->mgr_common.img_iommu_hdl_secure; + query_isp.cdm_iommu.non_secure = hw_mgr->mgr_common.cmd_iommu_hdl; + query_isp.cdm_iommu.secure = hw_mgr->mgr_common.cmd_iommu_hdl_secure; + query_isp.num_dev = 2; + for (i = 0; i < query_isp.num_dev; i++) { + query_isp.dev_caps[i].hw_type = CAM_ISP_HW_IFE; + query_isp.dev_caps[i].hw_version.major = 1; + query_isp.dev_caps[i].hw_version.minor = 7; + query_isp.dev_caps[i].hw_version.incr = 0; + query_isp.dev_caps[i].hw_version.reserved = 0; + } + + if (copy_to_user(u64_to_user_ptr(query->caps_handle), + &query_isp, sizeof(struct cam_isp_query_cap_cmd))) + rc = -EFAULT; + + CAM_DBG(CAM_ISP, "exit rc :%d", rc); + + return rc; +} + +static int cam_ife_hw_mgr_is_rdi_res(uint32_t res_id) +{ + int rc = 0; + + switch (res_id) { + case CAM_ISP_IFE_OUT_RES_RDI_0: + case CAM_ISP_IFE_OUT_RES_RDI_1: + case CAM_ISP_IFE_OUT_RES_RDI_2: + case CAM_ISP_IFE_OUT_RES_RDI_3: + rc = 1; + break; + default: + break; + } + + return rc; +} + +static int cam_ife_hw_mgr_reset_csid_res( + struct cam_ife_hw_mgr_res *isp_hw_res) +{ + int i; + int rc = 0; + struct cam_hw_intf *hw_intf; + struct cam_csid_reset_cfg_args csid_reset_args; + + csid_reset_args.reset_type = CAM_IFE_CSID_RESET_PATH; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + csid_reset_args.node_res = isp_hw_res->hw_res[i]; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "Resetting csid hardware %d", + hw_intf->hw_idx); + if (hw_intf->hw_ops.reset) { + rc = hw_intf->hw_ops.reset(hw_intf->hw_priv, + &csid_reset_args, + sizeof(struct cam_csid_reset_cfg_args)); + if (rc <= 0) + goto err; + } + } + + return 0; +err: + CAM_ERR(CAM_ISP, "RESET HW res failed: (type:%d, id:%d)", + isp_hw_res->res_type, isp_hw_res->res_id); + return rc; +} + +static int cam_ife_hw_mgr_init_hw_res( + struct cam_ife_hw_mgr_res *isp_hw_res) +{ + int i; + int rc = -1; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "enabled vfe hardware %d", + hw_intf->hw_idx); + if (hw_intf->hw_ops.init) { + rc = hw_intf->hw_ops.init(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + if (rc) + goto err; + } + } + + return 0; +err: + CAM_ERR(CAM_ISP, "INIT HW res failed: (type:%d, id:%d)", + isp_hw_res->res_type, isp_hw_res->res_id); + return rc; +} + +static int cam_ife_hw_mgr_start_hw_res( + struct cam_ife_hw_mgr_res *isp_hw_res, + struct cam_ife_hw_mgr_ctx *ctx) +{ + int i; + int rc = -1; + struct cam_hw_intf *hw_intf; + + /* Start slave (which is right split) first */ + for (i = CAM_ISP_HW_SPLIT_MAX - 1; i >= 0; i--) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.start) { + isp_hw_res->hw_res[i]->rdi_only_ctx = + ctx->is_rdi_only_context; + rc = hw_intf->hw_ops.start(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start HW resources"); + goto err; + } + CAM_DBG(CAM_ISP, "Start HW %d Res %d", hw_intf->hw_idx, + isp_hw_res->hw_res[i]->res_id); + } else { + CAM_ERR(CAM_ISP, "function null"); + goto err; + } + } + + return 0; +err: + CAM_ERR(CAM_ISP, "Start hw res failed (type:%d, id:%d)", + isp_hw_res->res_type, isp_hw_res->res_id); + return rc; +} + +static void cam_ife_hw_mgr_stop_hw_res( + struct cam_ife_hw_mgr_res *isp_hw_res) +{ + int i; + struct cam_hw_intf *hw_intf; + uint32_t dummy_args; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.stop) + hw_intf->hw_ops.stop(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + else + CAM_ERR(CAM_ISP, "stop null"); + if (hw_intf->hw_ops.process_cmd && + isp_hw_res->res_type == CAM_IFE_HW_MGR_RES_IFE_OUT) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ, + &dummy_args, sizeof(dummy_args)); + } + } +} + +static void cam_ife_hw_mgr_deinit_hw_res( + struct cam_ife_hw_mgr_res *isp_hw_res) +{ + int i; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.deinit) + hw_intf->hw_ops.deinit(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + } +} + +static void cam_ife_hw_mgr_deinit_hw( + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + int i = 0; + + if (!ctx->init_done) { + CAM_WARN(CAM_ISP, "ctx is not in init state"); + return; + } + + /* Deinit IFE CID */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { + CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); + cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); + } + + /* Deinit IFE CSID */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__); + cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); + } + + /* Deint IFE MUX(SRC) */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + 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]); + + ctx->init_done = false; +} + +static int cam_ife_hw_mgr_init_hw( + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + int rc = 0, i; + + CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", + ctx->ctx_index); + /* INIT IFE CID */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { + rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)", + hw_mgr_res->res_id); + goto deinit; + } + } + + CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d", + ctx->ctx_index); + + /* INIT IFE csid */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)", + hw_mgr_res->res_id); + goto deinit; + } + } + + /* INIT IFE SRC */ + CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d", + ctx->ctx_index); + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)", + hw_mgr_res->res_id); + goto deinit; + } + } + + /* 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); + + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)", + ctx->res_list_ife_out[i].res_id); + goto deinit; + } + } + + return rc; +deinit: + ctx->init_done = true; + cam_ife_hw_mgr_deinit_hw(ctx); + return rc; +} + +static int cam_ife_hw_mgr_put_res( + struct list_head *src_list, + struct cam_ife_hw_mgr_res **res) +{ + int rc = 0; + struct cam_ife_hw_mgr_res *res_ptr = NULL; + + res_ptr = *res; + if (res_ptr) + list_add_tail(&res_ptr->list, src_list); + + return rc; +} + +static int cam_ife_hw_mgr_get_res( + struct list_head *src_list, + struct cam_ife_hw_mgr_res **res) +{ + int rc = 0; + struct cam_ife_hw_mgr_res *res_ptr = NULL; + + if (!list_empty(src_list)) { + res_ptr = list_first_entry(src_list, + struct cam_ife_hw_mgr_res, list); + list_del_init(&res_ptr->list); + } else { + CAM_ERR(CAM_ISP, "No more free ife hw mgr ctx"); + rc = -1; + } + *res = res_ptr; + + return rc; +} + +static int cam_ife_hw_mgr_free_hw_res( + struct cam_ife_hw_mgr_res *isp_hw_res) +{ + int rc = 0; + int i; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.release) { + rc = hw_intf->hw_ops.release(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + if (rc) + CAM_ERR(CAM_ISP, + "Release hw resource id %d failed", + isp_hw_res->res_id); + isp_hw_res->hw_res[i] = NULL; + } else + CAM_ERR(CAM_ISP, "Release null"); + } + /* caller should make sure the resource is in a list */ + list_del_init(&isp_hw_res->list); + memset(isp_hw_res, 0, sizeof(*isp_hw_res)); + INIT_LIST_HEAD(&isp_hw_res->list); + + return 0; +} + +static int cam_ife_mgr_csid_stop_hw( + struct cam_ife_hw_mgr_ctx *ctx, struct list_head *stop_list, + uint32_t base_idx, uint32_t stop_cmd) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_isp_resource_node *stop_res[CAM_IFE_PIX_PATH_RES_MAX - 1]; + struct cam_csid_hw_stop_args stop; + struct cam_hw_intf *hw_intf; + uint32_t i, cnt; + + cnt = 0; + list_for_each_entry(hw_mgr_res, stop_list, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + isp_res = hw_mgr_res->hw_res[i]; + if (isp_res->hw_intf->hw_idx != base_idx) + continue; + CAM_DBG(CAM_ISP, "base_idx %d res_id %d cnt %u", + base_idx, isp_res->res_id, cnt); + stop_res[cnt] = isp_res; + cnt++; + } + } + + if (cnt) { + hw_intf = stop_res[0]->hw_intf; + stop.num_res = cnt; + stop.node_res = stop_res; + stop.stop_cmd = stop_cmd; + hw_intf->hw_ops.stop(hw_intf->hw_priv, &stop, sizeof(stop)); + } + + return 0; +} + +static int cam_ife_hw_mgr_release_hw_for_ctx( + struct cam_ife_hw_mgr_ctx *ife_ctx) +{ + uint32_t i; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_ife_hw_mgr_res *hw_mgr_res_temp; + + /* ife leaf resource */ + 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) { + 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 csid resource */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &ife_ctx->res_list_ife_csid, 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 cid resource */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &ife_ctx->res_list_ife_cid, 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 root node */ + if (ife_ctx->res_list_ife_in.res_type != CAM_IFE_HW_MGR_RES_UNINIT) + cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_in); + + /* clean up the callback function */ + ife_ctx->common.cb_priv = NULL; + memset(ife_ctx->common.event_cb, 0, sizeof(ife_ctx->common.event_cb)); + + CAM_DBG(CAM_ISP, "release context completed ctx id:%d", + ife_ctx->ctx_index); + + return 0; +} + + +static int cam_ife_hw_mgr_put_ctx( + struct list_head *src_list, + struct cam_ife_hw_mgr_ctx **ife_ctx) +{ + int rc = 0; + struct cam_ife_hw_mgr_ctx *ctx_ptr = NULL; + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + ctx_ptr = *ife_ctx; + if (ctx_ptr) + list_add_tail(&ctx_ptr->list, src_list); + *ife_ctx = NULL; + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); + return rc; +} + +static int cam_ife_hw_mgr_get_ctx( + struct list_head *src_list, + struct cam_ife_hw_mgr_ctx **ife_ctx) +{ + int rc = 0; + struct cam_ife_hw_mgr_ctx *ctx_ptr = NULL; + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + if (!list_empty(src_list)) { + ctx_ptr = list_first_entry(src_list, + struct cam_ife_hw_mgr_ctx, list); + list_del_init(&ctx_ptr->list); + } else { + CAM_ERR(CAM_ISP, "No more free ife hw mgr ctx"); + rc = -1; + } + *ife_ctx = ctx_ptr; + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); + + return rc; +} + +static void cam_ife_mgr_add_base_info( + struct cam_ife_hw_mgr_ctx *ctx, + enum cam_isp_hw_split_id split_id, + uint32_t base_idx) +{ + uint32_t i; + + if (!ctx->num_base) { + ctx->base[0].split_id = split_id; + ctx->base[0].idx = base_idx; + ctx->num_base++; + CAM_DBG(CAM_ISP, + "Add split id = %d for base idx = %d num_base=%d", + split_id, base_idx, ctx->num_base); + } else { + /*Check if base index already exists in the list */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == base_idx) { + if (split_id != CAM_ISP_HW_SPLIT_MAX && + ctx->base[i].split_id == + CAM_ISP_HW_SPLIT_MAX) + ctx->base[i].split_id = split_id; + + break; + } + } + + if (i == ctx->num_base) { + ctx->base[ctx->num_base].split_id = split_id; + ctx->base[ctx->num_base].idx = base_idx; + ctx->num_base++; + CAM_DBG(CAM_ISP, + "Add split_id=%d for base idx=%d num_base=%d", + split_id, base_idx, ctx->num_base); + } + } +} + +static int cam_ife_mgr_process_base_info( + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *res = NULL; + uint32_t i; + + if (list_empty(&ctx->res_list_ife_src)) { + CAM_ERR(CAM_ISP, "Mux List empty"); + return -ENODEV; + } + + /* IFE mux in resources */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) + continue; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + res = hw_mgr_res->hw_res[i]; + cam_ife_mgr_add_base_info(ctx, i, + res->hw_intf->hw_idx); + CAM_DBG(CAM_ISP, "add base info for hw %d", + res->hw_intf->hw_idx); + } + } + CAM_DBG(CAM_ISP, "ctx base num = %d", ctx->num_base); + + 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_generic_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.priv = 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, + struct cam_isp_in_port_generic_info *in_port) +{ + int rc = -EINVAL; + struct cam_vfe_acquire_args vfe_acquire; + struct cam_isp_out_port_generic_info *out_port = NULL; + struct cam_ife_hw_mgr_res *ife_out_res; + struct cam_hw_intf *hw_intf; + uint32_t i, vfe_out_res_id, vfe_in_res_id; + + /* take left resource */ + vfe_in_res_id = ife_src_res->hw_res[0]->res_id; + + switch (vfe_in_res_id) { + case CAM_ISP_HW_VFE_IN_RDI0: + vfe_out_res_id = CAM_ISP_IFE_OUT_RES_RDI_0; + break; + case CAM_ISP_HW_VFE_IN_RDI1: + vfe_out_res_id = CAM_ISP_IFE_OUT_RES_RDI_1; + break; + case CAM_ISP_HW_VFE_IN_RDI2: + vfe_out_res_id = CAM_ISP_IFE_OUT_RES_RDI_2; + break; + case CAM_ISP_HW_VFE_IN_RDI3: + vfe_out_res_id = CAM_ISP_IFE_OUT_RES_RDI_3; + break; + default: + CAM_ERR(CAM_ISP, "invalid resource type"); + goto err; + } + CAM_DBG(CAM_ISP, "vfe_in_res_id = %d, vfe_out_red_id = %d", + vfe_in_res_id, vfe_out_res_id); + + vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_OUT; + vfe_acquire.tasklet = ife_ctx->common.tasklet_info; + + ife_out_res = &ife_ctx->res_list_ife_out[vfe_out_res_id & 0xFF]; + for (i = 0; i < in_port->num_out_res; i++) { + out_port = &in_port->data[i]; + + CAM_DBG(CAM_ISP, "i = %d, vfe_out_res_id = %d, out_port: %d", + i, vfe_out_res_id, out_port->res_type); + + if (vfe_out_res_id != out_port->res_type) + continue; + + vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops; + vfe_acquire.priv = ife_ctx; + vfe_acquire.vfe_out.out_port_info = out_port; + vfe_acquire.vfe_out.split_id = CAM_ISP_HW_SPLIT_LEFT; + vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; + vfe_acquire.vfe_out.is_dual = 0; + vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; + hw_intf = ife_src_res->hw_res[0]->hw_intf; + 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", + out_port->res_type); + goto err; + } + break; + } + + if (i == in_port->num_out_res) { + CAM_ERR(CAM_ISP, + "Cannot acquire out resource, i=%d, num_out_res=%d", + i, in_port->num_out_res); + goto err; + } + + ife_out_res->hw_res[0] = vfe_acquire.vfe_out.rsrc_node; + ife_out_res->is_dual_vfe = 0; + ife_out_res->res_id = vfe_out_res_id; + 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: + return rc; +} + +static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_ife_hw_mgr_res *ife_src_res, + struct cam_isp_in_port_generic_info *in_port, + bool acquire_lcr) +{ + int rc = -1; + uint32_t i, j, k; + struct cam_vfe_acquire_args vfe_acquire; + struct cam_isp_out_port_generic_info *out_port; + struct cam_ife_hw_mgr_res *ife_out_res; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < in_port->num_out_res; i++) { + out_port = &in_port->data[i]; + k = out_port->res_type & 0xFF; + if (k >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "invalid output resource type 0x%x", + out_port->res_type); + continue; + } + + if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type)) + continue; + + if ((acquire_lcr && + out_port->res_type != CAM_ISP_IFE_OUT_RES_LCR) || + (!acquire_lcr && + out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR)) + continue; + + if ((out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD && + ife_src_res->res_id != CAM_ISP_HW_VFE_IN_PDLIB) || + (ife_src_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB && + out_port->res_type != CAM_ISP_IFE_OUT_RES_2PD)) + continue; + + CAM_DBG(CAM_ISP, "res_type 0x%x", out_port->res_type); + + ife_out_res = &ife_ctx->res_list_ife_out[k]; + ife_out_res->is_dual_vfe = in_port->usage_type; + + vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_OUT; + vfe_acquire.tasklet = ife_ctx->common.tasklet_info; + vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops; + vfe_acquire.priv = ife_ctx; + vfe_acquire.vfe_out.out_port_info = out_port; + vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_vfe; + vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; + vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; + + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { + if (!ife_src_res->hw_res[j]) + continue; + + hw_intf = ife_src_res->hw_res[j]->hw_intf; + + if (j == 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", + out_port->res_type); + goto err; + } + + ife_out_res->hw_res[j] = + vfe_acquire.vfe_out.rsrc_node; + CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x", + ife_out_res->hw_res[j]->res_type, + ife_out_res->hw_res[j]->res_id); + + } + ife_out_res->res_type = + (enum cam_ife_hw_mgr_res_type)CAM_ISP_RESOURCE_VFE_OUT; + 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; +err: + /* release resource at the entry function */ + return rc; +} + +static int cam_ife_hw_mgr_acquire_res_ife_out( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port) +{ + int rc = -EINVAL; + struct cam_ife_hw_mgr_res *ife_src_res; + + list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) { + if (ife_src_res->num_children) + continue; + + switch (ife_src_res->res_id) { + case CAM_ISP_HW_VFE_IN_CAMIF: + case CAM_ISP_HW_VFE_IN_PDLIB: + case CAM_ISP_HW_VFE_IN_RD: + rc = cam_ife_hw_mgr_acquire_res_ife_out_pixel(ife_ctx, + ife_src_res, in_port, false); + break; + case CAM_ISP_HW_VFE_IN_LCR: + rc = cam_ife_hw_mgr_acquire_res_ife_out_pixel(ife_ctx, + ife_src_res, in_port, true); + break; + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + rc = cam_ife_hw_mgr_acquire_res_ife_out_rdi(ife_ctx, + ife_src_res, in_port); + break; + default: + CAM_ERR(CAM_ISP, "Unknown IFE SRC resource: %d", + ife_src_res->res_id); + break; + } + if (rc) + goto err; + } + + return 0; +err: + /* release resource on entry function */ + 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_generic_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 %d", rc); + return rc; +} + +static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) +{ + if (hw_idx == 0) + return CAM_ISP_IFE0_HW; + else if (hw_idx == 1) + return CAM_ISP_IFE1_HW; + else if (hw_idx == 2) + return CAM_ISP_IFE0_LITE_HW; + else if (hw_idx == 3) + return CAM_ISP_IFE1_LITE_HW; + else if (hw_idx == 4) + return CAM_ISP_IFE2_LITE_HW; + return 0; +} + +static int cam_convert_res_id_to_hw_path(int path, bool acquire_lcr) +{ + if (path == CAM_IFE_PIX_PATH_RES_IPP && acquire_lcr) + return CAM_ISP_LCR_PATH; + else if (path == CAM_IFE_PIX_PATH_RES_PPP) + return CAM_ISP_PPP_PATH; + else if (path == CAM_IFE_PIX_PATH_RES_IPP) + return CAM_ISP_PXL_PATH; + else if (path == CAM_IFE_PIX_PATH_RES_RDI_0) + return CAM_ISP_RDI0_PATH; + else if (path == CAM_IFE_PIX_PATH_RES_RDI_1) + return CAM_ISP_RDI1_PATH; + else if (path == CAM_IFE_PIX_PATH_RES_RDI_2) + return CAM_ISP_RDI2_PATH; + else if (path == CAM_IFE_PIX_PATH_RES_RDI_3) + return CAM_ISP_RDI3_PATH; + return 0; +} + +static int cam_ife_hw_mgr_acquire_res_ife_src( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + bool acquire_lcr, uint32_t *acquired_hw_id, + uint32_t *acquired_hw_path) +{ + int rc = -1; + int i; + 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; + + ife_hw_mgr = ife_ctx->hw_mgr; + + list_for_each_entry(csid_res, &ife_ctx->res_list_ife_csid, list) { + if (csid_res->num_children && !acquire_lcr) + continue; + + if (acquire_lcr && csid_res->res_id != CAM_IFE_PIX_PATH_RES_IPP) + 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); + + 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.priv = ife_ctx; + vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; + + switch (csid_res->res_id) { + case CAM_IFE_PIX_PATH_RES_IPP: + if (!acquire_lcr) + vfe_acquire.vfe_in.res_id = + CAM_ISP_HW_VFE_IN_CAMIF; + else + vfe_acquire.vfe_in.res_id = + CAM_ISP_HW_VFE_IN_LCR; + if (csid_res->is_dual_vfe) + vfe_acquire.vfe_in.sync_mode = + CAM_ISP_HW_SYNC_MASTER; + else + vfe_acquire.vfe_in.sync_mode = + CAM_ISP_HW_SYNC_NONE; + + break; + case CAM_IFE_PIX_PATH_RES_PPP: + vfe_acquire.vfe_in.res_id = + CAM_ISP_HW_VFE_IN_PDLIB; + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + + break; + case CAM_IFE_PIX_PATH_RES_RDI_0: + vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RDI0; + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + case CAM_IFE_PIX_PATH_RES_RDI_1: + vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RDI1; + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + case CAM_IFE_PIX_PATH_RES_RDI_2: + vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RDI2; + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + case CAM_IFE_PIX_PATH_RES_RDI_3: + vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RDI3; + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + default: + CAM_ERR(CAM_ISP, "Wrong IFE CSID Resource Node"); + goto err; + } + 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; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!csid_res->hw_res[i]) + continue; + + hw_intf = ife_hw_mgr->ife_devices[ + csid_res->hw_res[i]->hw_intf->hw_idx]; + + /* fill in more acquire information as needed */ + /* slave Camif resource, */ + if (i == CAM_ISP_HW_SPLIT_RIGHT && + ife_src_res->is_dual_vfe) + 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; + + *acquired_hw_id |= + cam_convert_hw_idx_to_ife_hw_num( + hw_intf->hw_idx); + + if (i >= CAM_MAX_HW_SPLIT) { + CAM_ERR(CAM_ISP, "HW split is invalid: %d", i); + return -EINVAL; + } + + acquired_hw_path[i] |= cam_convert_res_id_to_hw_path( + ife_src_res->hw_res[i]->res_id, acquire_lcr); + + 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); + + } + + 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); + } + + return 0; +err: + /* release resource at the entry function */ + return rc; +} + +static int cam_ife_mgr_acquire_cid_res( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + struct cam_ife_hw_mgr_res **cid_res, + enum cam_ife_pix_path_res_id path_res_id) +{ + int rc = -1; + int i, j; + struct cam_ife_hw_mgr *ife_hw_mgr; + struct cam_hw_intf *hw_intf; + struct cam_ife_hw_mgr_res *cid_res_temp, *cid_res_iterator; + struct cam_csid_hw_reserve_resource_args csid_acquire; + uint32_t acquired_cnt = 0; + struct cam_isp_out_port_generic_info *out_port = NULL; + + ife_hw_mgr = ife_ctx->hw_mgr; + *cid_res = NULL; + + rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, cid_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto end; + } + + cid_res_temp = *cid_res; + + csid_acquire.res_type = CAM_ISP_RESOURCE_CID; + csid_acquire.in_port = in_port; + 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]); + + /* Try acquiring CID resource from previously acquired HW */ + list_for_each_entry(cid_res_iterator, &ife_ctx->res_list_ife_cid, + list) { + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!cid_res_iterator->hw_res[i]) + continue; + + if (in_port->num_out_res && + ((cid_res_iterator->is_secure == 1 && + out_port->secure_mode == 0) || + (cid_res_iterator->is_secure == 0 && + out_port->secure_mode == 1))) + continue; + + if (!in_port->num_out_res && + cid_res_iterator->is_secure == 1) + continue; + + hw_intf = cid_res_iterator->hw_res[i]->hw_intf; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_DBG(CAM_ISP, + "No ife cid resource from hw %d", + hw_intf->hw_idx); + continue; + } + + cid_res_temp->hw_res[acquired_cnt++] = + csid_acquire.node_res; + + CAM_DBG(CAM_ISP, + "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 && + path_res_id == CAM_IFE_PIX_PATH_RES_IPP) + /* + * Continue to acquire Right for IPP. + * Dual IFE for RDI and PPP is not currently + * supported. + */ + + continue; + + if (acquired_cnt) + /* + * If successfully acquired CID from + * previously acquired HW, skip the next + * part + */ + goto acquire_successful; + } + } + + /* Acquire Left if not already acquired */ + 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; + } + } + 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; + + 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); + + cid_res_temp->res_type = CAM_IFE_HW_MGR_RES_CID; + /* CID(DT_ID) value of acquire device, require for path */ + cid_res_temp->res_id = csid_acquire.node_res->res_id; + cid_res_temp->is_dual_vfe = in_port->usage_type; + ife_ctx->is_dual = (bool)in_port->usage_type; + + if (in_port->num_out_res) + cid_res_temp->is_secure = out_port->secure_mode; + + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, cid_res); + + /* + * Acquire Right if not already acquired. + * Dual IFE for RDI and PPP is not currently supported. + */ + 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; + csid_acquire.in_port = in_port; + for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) { + if (!ife_hw_mgr->csid_devices[j]) + continue; + + if (j == cid_res_temp->hw_res[0]->hw_intf->hw_idx) + continue; + + hw_intf = ife_hw_mgr->csid_devices[j]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) + continue; + else + break; + } + + if (j == CAM_IFE_CSID_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, + "Can not acquire ife csid rdi resource"); + goto end; + } + cid_res_temp->hw_res[1] = csid_acquire.node_res; + CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d", + in_port->usage_type); + } + 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: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, cid_res); +end: + return rc; + +} + +static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + bool is_ipp, + bool crop_enable) +{ + int rc = -1; + int i; + int master_idx = -1; + + struct cam_ife_hw_mgr *ife_hw_mgr; + struct cam_ife_hw_mgr_res *csid_res; + struct cam_ife_hw_mgr_res *cid_res; + struct cam_hw_intf *hw_intf; + struct cam_csid_hw_reserve_resource_args csid_acquire; + enum cam_ife_pix_path_res_id path_res_id; + + ife_hw_mgr = ife_ctx->hw_mgr; + /* get cid resource */ + if (is_ipp) + path_res_id = CAM_IFE_PIX_PATH_RES_IPP; + else + path_res_id = CAM_IFE_PIX_PATH_RES_PPP; + + rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res, + path_res_id); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed"); + goto end; + } + + rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto end; + } + + csid_res->res_type = + (enum cam_ife_hw_mgr_res_type)CAM_ISP_RESOURCE_PIX_PATH; + + csid_res->res_id = path_res_id; + + if (in_port->usage_type && is_ipp) + csid_res->is_dual_vfe = 1; + else { + csid_res->is_dual_vfe = 0; + 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); + + csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_acquire.res_id = path_res_id; + csid_acquire.cid = cid_res->hw_res[i]->res_id; + csid_acquire.in_port = in_port; + csid_acquire.out_port = in_port->data; + csid_acquire.node_res = NULL; + csid_acquire.crop_enable = crop_enable; + + hw_intf = cid_res->hw_res[i]->hw_intf; + + if (csid_res->is_dual_vfe) { + if (i == CAM_ISP_HW_SPLIT_LEFT) { + master_idx = hw_intf->hw_idx; + csid_acquire.sync_mode = + CAM_ISP_HW_SYNC_MASTER; + } else { + if (master_idx == -1) { + CAM_ERR(CAM_ISP, + "No Master found"); + goto put_res; + } + csid_acquire.sync_mode = + CAM_ISP_HW_SYNC_SLAVE; + csid_acquire.master_idx = master_idx; + } + } + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_ERR(CAM_ISP, + "Cannot acquire ife csid pxl path rsrc %s", + (is_ipp) ? "IPP" : "PPP"); + goto put_res; + } + + csid_res->hw_res[i] = csid_acquire.node_res; + CAM_DBG(CAM_ISP, + "acquired csid(%s)=%d pxl path rsrc %s successfully", + (i == 0) ? "left" : "right", hw_intf->hw_idx, + (is_ipp) ? "IPP" : "PPP"); + } + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); + + 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); + return 0; +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res); +end: + return rc; +} + +static enum cam_ife_pix_path_res_id + cam_ife_hw_mgr_get_ife_csid_rdi_res_type( + 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: + path_id = CAM_IFE_PIX_PATH_RES_RDI_0; + break; + case CAM_ISP_IFE_OUT_RES_RDI_1: + path_id = CAM_IFE_PIX_PATH_RES_RDI_1; + break; + case CAM_ISP_IFE_OUT_RES_RDI_2: + path_id = CAM_IFE_PIX_PATH_RES_RDI_2; + break; + case CAM_ISP_IFE_OUT_RES_RDI_3: + path_id = CAM_IFE_PIX_PATH_RES_RDI_3; + break; + default: + path_id = CAM_IFE_PIX_PATH_RES_MAX; + CAM_DBG(CAM_ISP, "maximum rdi output type exceeded"); + break; + } + + CAM_DBG(CAM_ISP, "out_port %x path_id %d", out_port_type, path_id); + + return path_id; +} + +static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port) +{ + int rc = -EINVAL; + int i; + + struct cam_ife_hw_mgr *ife_hw_mgr; + struct cam_ife_hw_mgr_res *csid_res; + struct cam_ife_hw_mgr_res *cid_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_out_port_generic_info *out_port; + struct cam_csid_hw_reserve_resource_args csid_acquire; + 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_res_id = cam_ife_hw_mgr_get_ife_csid_rdi_res_type( + out_port->res_type); + 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_res_id); + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed"); + goto end; + } + + /* For each RDI we need CID + PATH resource */ + rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, + &csid_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto end; + } + + memset(&csid_acquire, 0, sizeof(csid_acquire)); + 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; + csid_acquire.out_port = out_port; + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; + csid_acquire.node_res = NULL; + + /* Enable RDI crop for single ife use case only */ + if (in_port->usage_type) + csid_acquire.crop_enable = false; + else + csid_acquire.crop_enable = true; + + hw_intf = cid_res->hw_res[0]->hw_intf; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_ERR(CAM_ISP, + "CSID Path reserve failed hw=%d rc=%d cid=%d", + hw_intf->hw_idx, rc, + cid_res->hw_res[0]->res_id); + + goto put_res; + } + + if (csid_acquire.node_res == NULL) { + CAM_ERR(CAM_ISP, "Acquire CSID RDI rsrc failed"); + + goto put_res; + } + + csid_res->res_type = (enum cam_ife_hw_mgr_res_type) + CAM_ISP_RESOURCE_PIX_PATH; + csid_res->res_id = csid_acquire.res_id; + csid_res->is_dual_vfe = 0; + csid_res->hw_res[0] = csid_acquire.node_res; + csid_res->hw_res[1] = NULL; + 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); + + } + + return 0; +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res); +end: + return rc; +} + +static int cam_ife_hw_mgr_acquire_res_root( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port) +{ + int rc = -1; + + if (ife_ctx->res_list_ife_in.res_type == CAM_IFE_HW_MGR_RES_UNINIT) { + /* first acquire */ + 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) && (!ife_ctx->is_fe_enable)) { + CAM_ERR(CAM_ISP, "No Free resource for this context"); + goto err; + } else { + /* else do nothing */ + } + return 0; +err: + /* release resource in entry function */ + return rc; +} + +static int cam_ife_mgr_check_and_update_fe_v0( + 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++) { + + if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || + (in_port->num_out_res <= 0)) { + CAM_ERR(CAM_ISP, "Invalid num output res %u", + in_port->num_out_res); + return -EINVAL; + } + + 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_mgr_check_and_update_fe_v2( + 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_v2 *in_port = NULL; + uint32_t in_port_length = 0; + uint32_t total_in_port_length = 0; + + in_port = (struct cam_isp_in_port_info_v2 *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset); + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + + if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || + (in_port->num_out_res <= 0)) { + CAM_ERR(CAM_ISP, "Invalid num output res %u", + in_port->num_out_res); + return -EINVAL; + } + + in_port_length = sizeof(struct cam_isp_in_port_info_v2) + + (in_port->num_out_res - 1) * + sizeof(struct cam_isp_out_port_info_v2); + 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_v2 *) + ((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_mgr_check_and_update_fe( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_acquire_hw_info *acquire_hw_info) +{ + uint32_t major_ver = 0, minor_ver = 0; + + if (acquire_hw_info == NULL || ife_ctx == NULL) + return -EINVAL; + + major_ver = (acquire_hw_info->common_info_version >> 12) & 0xF; + minor_ver = (acquire_hw_info->common_info_version) & 0xFFF; + + switch (major_ver) { + case 1: + return cam_ife_mgr_check_and_update_fe_v0( + ife_ctx, acquire_hw_info); + case 2: + return cam_ife_mgr_check_and_update_fe_v2( + ife_ctx, acquire_hw_info); + break; + default: + CAM_ERR(CAM_ISP, "Invalid ver of common info from user"); + return -EINVAL; + } + + return 0; +} + +static int cam_ife_hw_mgr_preprocess_port( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + int *ipp_count, + int *rdi_count, + int *ppp_count, + int *ife_rd_count, + int *lcr_count) +{ + int ipp_num = 0; + int rdi_num = 0; + int ppp_num = 0; + int ife_rd_num = 0; + int lcr_num = 0; + uint32_t i; + struct cam_isp_out_port_generic_info *out_port; + struct cam_ife_hw_mgr *ife_hw_mgr; + + ife_hw_mgr = ife_ctx->hw_mgr; + + 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 if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR) + lcr_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; + *lcr_count = lcr_num; + + CAM_DBG(CAM_ISP, "rdi: %d ipp: %d ppp: %d ife_rd: %d lcr: %d", + rdi_num, ipp_num, ppp_num, ife_rd_num, lcr_num); + + return 0; +} + +static int cam_ife_mgr_acquire_hw_for_ctx( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + uint32_t *num_pix_port, uint32_t *num_rdi_port, + uint32_t *acquired_hw_id, uint32_t *acquired_hw_path) +{ + int rc = -1; + int is_dual_vfe = 0; + int ipp_count = 0; + int rdi_count = 0; + int ppp_count = 0; + int ife_rd_count = 0; + int lcr_count = 0; + bool crop_enable = true; + + is_dual_vfe = in_port->usage_type; + + /* get root node resource */ + rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port); + if (rc) { + CAM_ERR(CAM_ISP, "Can not acquire csid rx resource"); + goto err; + } + + cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, + &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); + + if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count + && !lcr_count) { + CAM_ERR(CAM_ISP, + "No PIX or RDI or PPP or IFE RD or LCR resource"); + return -EINVAL; + } + + if (ipp_count || lcr_count) { + /* get ife csid IPP resource */ + rc = cam_ife_hw_mgr_acquire_res_ife_csid_pxl(ife_ctx, + in_port, true, crop_enable); + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire IFE CSID IPP/LCR resource Failed"); + goto err; + } + } + + if (rdi_count) { + /* get ife csid RDI resource */ + rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port); + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire IFE CSID RDI resource Failed"); + goto err; + } + } + + if (ppp_count) { + /* get ife csid PPP resource */ + + /* If both IPP and PPP paths are requested with the same vc dt + * it is implied that the sensor is a type 3 PD sensor. Crop + * must be enabled for this sensor on PPP path as well. + */ + if (!ipp_count) + crop_enable = false; + + rc = cam_ife_hw_mgr_acquire_res_ife_csid_pxl(ife_ctx, + in_port, false, crop_enable); + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire IFE CSID PPP resource Failed"); + goto err; + } + } + + /* get ife src resource */ + 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); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE RD SRC resource Failed"); + goto err; + } + } else if (ipp_count || ppp_count || rdi_count) { + rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, + in_port, false, + acquired_hw_id, acquired_hw_path); + + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire IFE IPP/PPP SRC resource Failed"); + goto err; + } + } + + if (lcr_count) { + rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port, true, + acquired_hw_id, acquired_hw_path); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE LCR 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 + ife_rd_count + lcr_count; + *num_rdi_port += rdi_count; + + return 0; +err: + /* release resource at the acquire entry funciton */ + return rc; +} + +void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, + enum cam_cdm_cb_status status, uint64_t cookie) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + + if (!userdata) { + CAM_ERR(CAM_ISP, "Invalid args"); + return; + } + + ctx = 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 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", + handle, userdata, status, cookie); + } +} + +static int cam_ife_mgr_acquire_get_unified_structure_v0( + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t offset, uint32_t *input_size, + struct cam_isp_in_port_generic_info **in_port) +{ + struct cam_isp_in_port_info *in = NULL; + uint32_t in_port_length = 0; + struct cam_isp_in_port_generic_info *port_info = NULL; + int32_t rc = 0, i; + + in = (struct cam_isp_in_port_info *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset + *input_size); + + in_port_length = sizeof(struct cam_isp_in_port_info) + + (in->num_out_res - 1) * + sizeof(struct cam_isp_out_port_info); + + *input_size += in_port_length; + + if ((*input_size) > acquire_hw_info->input_info_size) { + CAM_ERR(CAM_ISP, "Input is not proper"); + rc = -EINVAL; + } + + port_info = kzalloc( + sizeof(struct cam_isp_in_port_generic_info), GFP_KERNEL); + + if (!port_info) + return -ENOMEM; + + port_info->major_ver = + (acquire_hw_info->input_info_version >> 16) & 0xFFFF; + port_info->minor_ver = + acquire_hw_info->input_info_version & 0xFFFF; + port_info->res_type = in->res_type; + port_info->lane_type = in->lane_type; + port_info->lane_num = in->lane_num; + port_info->lane_cfg = in->lane_cfg; + port_info->vc[0] = in->vc; + port_info->dt[0] = in->dt; + port_info->num_valid_vc_dt = 1; + port_info->format = in->format; + port_info->test_pattern = in->test_pattern; + port_info->usage_type = in->usage_type; + port_info->left_start = in->left_start; + port_info->left_stop = in->left_stop; + port_info->left_width = in->left_width; + port_info->right_start = in->right_start; + port_info->right_stop = in->right_stop; + port_info->right_width = in->right_width; + port_info->line_start = in->line_start; + port_info->line_stop = in->line_stop; + port_info->height = in->height; + port_info->pixel_clk = in->pixel_clk; + port_info->batch_size = in->batch_size; + port_info->dsp_mode = in->dsp_mode; + port_info->hbi_cnt = in->hbi_cnt; + port_info->cust_node = 0; + port_info->num_out_res = in->num_out_res; + + port_info->data = kcalloc(in->num_out_res, + sizeof(struct cam_isp_out_port_generic_info), + GFP_KERNEL); + if (port_info->data == NULL) { + rc = -ENOMEM; + goto release_port_mem; + } + + for (i = 0; i < in->num_out_res; i++) { + port_info->data[i].res_type = in->data[i].res_type; + port_info->data[i].format = in->data[i].format; + port_info->data[i].width = in->data[i].width; + port_info->data[i].height = in->data[i].height; + port_info->data[i].comp_grp_id = in->data[i].comp_grp_id; + port_info->data[i].split_point = in->data[i].split_point; + port_info->data[i].secure_mode = in->data[i].secure_mode; + port_info->data[i].reserved = in->data[i].reserved; + } + *in_port = port_info; + + return 0; +release_port_mem: + kfree(port_info); + return rc; +} + +static int cam_ife_mgr_acquire_get_unified_structure_v2( + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t offset, uint32_t *input_size, + struct cam_isp_in_port_generic_info **in_port) +{ + struct cam_isp_in_port_info_v2 *in = NULL; + uint32_t in_port_length = 0; + struct cam_isp_in_port_generic_info *port_info = NULL; + int32_t rc = 0, i; + + in = (struct cam_isp_in_port_info_v2 *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset + *input_size); + + in_port_length = sizeof(struct cam_isp_in_port_info_v2) + + (in->num_out_res - 1) * + sizeof(struct cam_isp_out_port_info_v2); + + *input_size += in_port_length; + + if ((*input_size) > acquire_hw_info->input_info_size) { + CAM_ERR(CAM_ISP, "Input is not proper"); + rc = -EINVAL; + } + + port_info = kzalloc( + sizeof(struct cam_isp_in_port_generic_info), GFP_KERNEL); + + if (!port_info) + return -ENOMEM; + + port_info->major_ver = + (acquire_hw_info->input_info_version >> 16) & 0xFFFF; + port_info->minor_ver = + acquire_hw_info->input_info_version & 0xFFFF; + port_info->res_type = in->res_type; + port_info->lane_type = in->lane_type; + port_info->lane_num = in->lane_num; + port_info->lane_cfg = in->lane_cfg; + port_info->num_valid_vc_dt = in->num_valid_vc_dt; + + if (port_info->num_valid_vc_dt == 0 || + port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) { + CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d", + in->num_valid_vc_dt); + rc = -EINVAL; + goto release_mem; + } + + for (i = 0; i < port_info->num_valid_vc_dt; i++) { + port_info->vc[i] = in->vc[i]; + port_info->dt[i] = in->dt[i]; + } + + port_info->format = in->format; + port_info->test_pattern = in->test_pattern; + port_info->usage_type = in->usage_type; + port_info->left_start = in->left_start; + port_info->left_stop = in->left_stop; + port_info->left_width = in->left_width; + port_info->right_start = in->right_start; + port_info->right_stop = in->right_stop; + port_info->right_width = in->right_width; + port_info->line_start = in->line_start; + port_info->line_stop = in->line_stop; + port_info->height = in->height; + port_info->pixel_clk = in->pixel_clk; + port_info->batch_size = in->batch_size; + port_info->dsp_mode = in->dsp_mode; + port_info->hbi_cnt = in->hbi_cnt; + port_info->cust_node = in->cust_node; + port_info->num_out_res = in->num_out_res; + + port_info->data = kcalloc(in->num_out_res, + sizeof(struct cam_isp_out_port_generic_info), + GFP_KERNEL); + if (port_info->data == NULL) { + rc = -ENOMEM; + goto release_mem; + } + + for (i = 0; i < port_info->num_out_res; i++) { + port_info->data[i].res_type = in->data[i].res_type; + port_info->data[i].format = in->data[i].format; + port_info->data[i].width = in->data[i].width; + port_info->data[i].height = in->data[i].height; + port_info->data[i].comp_grp_id = in->data[i].comp_grp_id; + port_info->data[i].split_point = in->data[i].split_point; + port_info->data[i].secure_mode = in->data[i].secure_mode; + } + + *in_port = port_info; + + return 0; + +release_mem: + kfree(port_info); + return rc; +} + +static int cam_ife_mgr_acquire_get_unified_structure( + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t offset, uint32_t *input_size, + struct cam_isp_in_port_generic_info **in_port) +{ + uint32_t major_ver = 0, minor_ver = 0; + + if (acquire_hw_info == NULL || input_size == NULL) + return -EINVAL; + + major_ver = (acquire_hw_info->common_info_version >> 12) & 0xF; + minor_ver = (acquire_hw_info->common_info_version) & 0xFFF; + + switch (major_ver) { + case 1: + return cam_ife_mgr_acquire_get_unified_structure_v0( + acquire_hw_info, offset, input_size, in_port); + case 2: + return cam_ife_mgr_acquire_get_unified_structure_v2( + acquire_hw_info, offset, input_size, in_port); + break; + default: + CAM_ERR(CAM_ISP, "Invalid ver of i/p port info from user"); + return -EINVAL; + } + + return 0; +} + +/* entry function: acquire_hw */ +static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) +{ + struct cam_ife_hw_mgr *ife_hw_mgr = hw_mgr_priv; + struct cam_hw_acquire_args *acquire_args = acquire_hw_args; + int rc = -1; + int i, j; + struct cam_ife_hw_mgr_ctx *ife_ctx; + struct cam_isp_in_port_generic_info *in_port = NULL; + struct cam_cdm_acquire_data cdm_acquire; + uint32_t num_pix_port_per_in = 0; + uint32_t num_rdi_port_per_in = 0; + uint32_t total_pix_port = 0; + uint32_t total_rdi_port = 0; + struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; + uint32_t input_size = 0; + + CAM_DBG(CAM_ISP, "Enter..."); + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error"); + return -EINVAL; + } + + /* get the ife ctx */ + rc = cam_ife_hw_mgr_get_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); + if (rc || !ife_ctx) { + CAM_ERR(CAM_ISP, "Get ife hw context failed"); + goto err; + } + + ife_ctx->common.cb_priv = acquire_args->context_data; + for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) + ife_ctx->common.event_cb[i] = acquire_args->event_cb; + + ife_ctx->hw_mgr = ife_hw_mgr; + + + memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); + cdm_acquire.cell_index = 0; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ife_ctx; + cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; + for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (ife_hw_mgr->cdm_reg_map[i]) + cdm_acquire.base_array[j++] = + ife_hw_mgr->cdm_reg_map[i]; + } + cdm_acquire.base_array_cnt = j; + + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_ctx; + } + + CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x", + cdm_acquire.handle); + ife_ctx->cdm_handle = cdm_acquire.handle; + ife_ctx->cdm_ops = cdm_acquire.ops; + + acquire_hw_info = + (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; + + 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_cdm; + } + + /* acquire HW resources */ + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + rc = cam_ife_mgr_acquire_get_unified_structure(acquire_hw_info, + i, &input_size, &in_port); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Failed in parsing: %d", rc); + 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, + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + + total_pix_port += num_pix_port_per_in; + total_rdi_port += num_rdi_port_per_in; + + if (rc) { + CAM_ERR(CAM_ISP, "can not acquire resource"); + goto free_mem; + } + kfree(in_port->data); + kfree(in_port); + in_port = NULL; + } + + /* Check whether context has only RDI resource */ + if (!total_pix_port) { + ife_ctx->is_rdi_only_context = 1; + CAM_DBG(CAM_ISP, "RDI only context"); + } + + /* Process base info */ + rc = cam_ife_mgr_process_base_info(ife_ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Process base info failed"); + goto free_res; + } + + acquire_args->ctxt_to_hw_map = ife_ctx; + ife_ctx->ctx_in_use = 1; + + acquire_args->valid_acquired_hw = + acquire_hw_info->num_inputs; + + cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); + + CAM_DBG(CAM_ISP, "Exit...(success)"); + + return 0; +free_mem: + kfree(in_port->data); + kfree(in_port); +free_res: + cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); +free_cdm: + cam_cdm_release(ife_ctx->cdm_handle); +free_ctx: + cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); +err: + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +void cam_ife_mgr_acquire_get_unified_dev_str(struct cam_isp_in_port_info *in, + struct cam_isp_in_port_generic_info *gen_port_info) +{ + int i; + + gen_port_info->res_type = in->res_type; + gen_port_info->lane_type = in->lane_type; + gen_port_info->lane_num = in->lane_num; + gen_port_info->lane_cfg = in->lane_cfg; + gen_port_info->vc[0] = in->vc; + gen_port_info->dt[0] = in->dt; + gen_port_info->num_valid_vc_dt = 1; + gen_port_info->format = in->format; + gen_port_info->test_pattern = in->test_pattern; + gen_port_info->usage_type = in->usage_type; + gen_port_info->left_start = in->left_start; + gen_port_info->left_stop = in->left_stop; + gen_port_info->left_width = in->left_width; + gen_port_info->right_start = in->right_start; + gen_port_info->right_stop = in->right_stop; + gen_port_info->right_width = in->right_width; + gen_port_info->line_start = in->line_start; + gen_port_info->line_stop = in->line_stop; + gen_port_info->height = in->height; + gen_port_info->pixel_clk = in->pixel_clk; + gen_port_info->batch_size = in->batch_size; + gen_port_info->dsp_mode = in->dsp_mode; + gen_port_info->hbi_cnt = in->hbi_cnt; + gen_port_info->cust_node = 0; + gen_port_info->num_out_res = in->num_out_res; + + for (i = 0; i < in->num_out_res; i++) { + gen_port_info->data[i].res_type = in->data[i].res_type; + gen_port_info->data[i].format = in->data[i].format; + gen_port_info->data[i].width = in->data[i].width; + gen_port_info->data[i].height = in->data[i].height; + gen_port_info->data[i].comp_grp_id = in->data[i].comp_grp_id; + gen_port_info->data[i].split_point = in->data[i].split_point; + gen_port_info->data[i].secure_mode = in->data[i].secure_mode; + } +} + +/* entry function: acquire_hw */ +static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) +{ + struct cam_ife_hw_mgr *ife_hw_mgr = hw_mgr_priv; + struct cam_hw_acquire_args *acquire_args = acquire_hw_args; + int rc = -1; + int i, j; + struct cam_ife_hw_mgr_ctx *ife_ctx; + struct cam_isp_in_port_info *in_port = NULL; + struct cam_isp_resource *isp_resource = NULL; + struct cam_cdm_acquire_data cdm_acquire; + struct cam_isp_in_port_generic_info *gen_port_info = NULL; + uint32_t num_pix_port_per_in = 0; + uint32_t num_rdi_port_per_in = 0; + uint32_t total_pix_port = 0; + uint32_t total_rdi_port = 0; + uint32_t in_port_length = 0; + + CAM_DBG(CAM_ISP, "Enter..."); + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error"); + return -EINVAL; + } + + /* get the ife ctx */ + rc = cam_ife_hw_mgr_get_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); + if (rc || !ife_ctx) { + CAM_ERR(CAM_ISP, "Get ife hw context failed"); + goto err; + } + + ife_ctx->common.cb_priv = acquire_args->context_data; + for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) + ife_ctx->common.event_cb[i] = acquire_args->event_cb; + + ife_ctx->hw_mgr = ife_hw_mgr; + + + memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); + cdm_acquire.cell_index = 0; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ife_ctx; + cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; + for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (ife_hw_mgr->cdm_reg_map[i]) + cdm_acquire.base_array[j++] = + ife_hw_mgr->cdm_reg_map[i]; + } + cdm_acquire.base_array_cnt = j; + + + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_ctx; + } + + CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x", + cdm_acquire.handle); + ife_ctx->cdm_handle = cdm_acquire.handle; + ife_ctx->cdm_ops = cdm_acquire.ops; + + isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; + + /* acquire HW resources */ + for (i = 0; i < acquire_args->num_acq; i++) { + 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, + isp_resource[i].length); + + in_port_length = sizeof(struct cam_isp_in_port_info); + + if (in_port_length > isp_resource[i].length) { + CAM_ERR(CAM_ISP, "buffer size is not enough"); + rc = -EINVAL; + goto free_res; + } + + in_port = memdup_user( + u64_to_user_ptr(isp_resource[i].res_hdl), + isp_resource[i].length); + if (!IS_ERR(in_port)) { + 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; + kfree(in_port); + 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); + if (in_port_length > isp_resource[i].length) { + CAM_ERR(CAM_ISP, "buffer size is not enough"); + rc = -EINVAL; + kfree(in_port); + goto free_res; + } + + gen_port_info = kzalloc( + sizeof(struct cam_isp_in_port_generic_info), + GFP_KERNEL); + if (gen_port_info == NULL) { + rc = -ENOMEM; + goto free_res; + } + + gen_port_info->data = kcalloc( + sizeof(struct cam_isp_out_port_generic_info), + in_port->num_out_res, GFP_KERNEL); + if (gen_port_info->data == NULL) { + kfree(gen_port_info); + gen_port_info = NULL; + rc = -ENOMEM; + goto free_res; + } + + cam_ife_mgr_acquire_get_unified_dev_str(in_port, + gen_port_info); + + rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, + gen_port_info, &num_pix_port_per_in, + &num_rdi_port_per_in, + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + + total_pix_port += num_pix_port_per_in; + total_rdi_port += num_rdi_port_per_in; + + kfree(in_port); + if (gen_port_info != NULL) { + kfree(gen_port_info->data); + kfree(gen_port_info); + gen_port_info = NULL; + } + if (rc) { + CAM_ERR(CAM_ISP, "can not acquire resource"); + goto free_res; + } + } else { + CAM_ERR(CAM_ISP, + "Copy from user failed with in_port = %pK", + in_port); + rc = -EFAULT; + goto free_res; + } + } + + /* Check whether context has only RDI resource */ + if (!total_pix_port) { + ife_ctx->is_rdi_only_context = 1; + CAM_DBG(CAM_ISP, "RDI only context"); + } + + /* Process base info */ + rc = cam_ife_mgr_process_base_info(ife_ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Process base info failed"); + goto free_res; + } + + acquire_args->ctxt_to_hw_map = ife_ctx; + ife_ctx->ctx_in_use = 1; + + cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); + + CAM_DBG(CAM_ISP, "Exit...(success)"); + + return 0; +free_res: + cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); + cam_cdm_release(ife_ctx->cdm_handle); +free_ctx: + cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); +err: + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +/* entry function: acquire_hw */ +static int cam_ife_mgr_acquire(void *hw_mgr_priv, + void *acquire_hw_args) +{ + struct cam_hw_acquire_args *acquire_args = acquire_hw_args; + int rc = -1; + + CAM_DBG(CAM_ISP, "Enter..."); + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error"); + return -EINVAL; + } + + if (acquire_args->num_acq == CAM_API_COMPAT_CONSTANT) + rc = cam_ife_mgr_acquire_hw(hw_mgr_priv, acquire_hw_args); + else + rc = cam_ife_mgr_acquire_dev(hw_mgr_priv, acquire_hw_args); + + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +static const char *cam_isp_util_usage_data_to_string( + uint32_t usage_data) +{ + switch (usage_data) { + case CAM_ISP_USAGE_LEFT_PX: + return "LEFT_PX"; + case CAM_ISP_USAGE_RIGHT_PX: + return "RIGHT_PX"; + case CAM_ISP_USAGE_RDI: + return "RDI"; + default: + return "USAGE_INVALID"; + } +} + +static int cam_isp_classify_vote_info( + struct cam_ife_hw_mgr_res *hw_mgr_res, + struct cam_isp_bw_config_v2 *bw_config, + struct cam_axi_vote *isp_vote, + uint32_t split_idx, + bool *camif_l_bw_updated, + bool *camif_r_bw_updated) +{ + int rc = 0, i, j = 0; + + if ((hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) + || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_RD) || + (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB)) { + if (split_idx == CAM_ISP_HW_SPLIT_LEFT) { + if (*camif_l_bw_updated) + return rc; + + for (i = 0; i < bw_config->num_paths; i++) { + if (bw_config->axi_path[i].usage_data == + CAM_ISP_USAGE_LEFT_PX) { + memcpy(&isp_vote->axi_path[j], + &bw_config->axi_path[i], + sizeof(struct + cam_axi_per_path_bw_vote)); + j++; + } + } + isp_vote->num_paths = j; + + *camif_l_bw_updated = true; + } else { + if (*camif_r_bw_updated) + return rc; + + for (i = 0; i < bw_config->num_paths; i++) { + if (bw_config->axi_path[i].usage_data == + CAM_ISP_USAGE_RIGHT_PX) { + memcpy(&isp_vote->axi_path[j], + &bw_config->axi_path[i], + sizeof(struct + cam_axi_per_path_bw_vote)); + j++; + } + } + isp_vote->num_paths = j; + + *camif_r_bw_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_RDI3)) { + for (i = 0; i < bw_config->num_paths; i++) { + if ((bw_config->axi_path[i].usage_data == + CAM_ISP_USAGE_RDI) && + ((bw_config->axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_IFE_RDI0) == + (hw_mgr_res->res_id - + CAM_ISP_HW_VFE_IN_RDI0))) { + memcpy(&isp_vote->axi_path[j], + &bw_config->axi_path[i], + sizeof(struct + cam_axi_per_path_bw_vote)); + j++; + } + } + isp_vote->num_paths = j; + + } else { + if (hw_mgr_res->hw_res[split_idx]) { + CAM_ERR(CAM_ISP, "Invalid res_id %u, split_idx: %u", + hw_mgr_res->res_id, split_idx); + rc = -EINVAL; + return rc; + } + } + + for (i = 0; i < isp_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "CLASSIFY_VOTE [%s] [%s] [%s] [%llu] [%llu] [%llu]", + cam_isp_util_usage_data_to_string( + isp_vote->axi_path[i].usage_data), + cam_cpas_axi_util_path_type_to_string( + isp_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + isp_vote->axi_path[i].transac_type), + isp_vote->axi_path[i].camnoc_bw, + isp_vote->axi_path[i].mnoc_ab_bw, + isp_vote->axi_path[i].mnoc_ib_bw); + } + + return rc; +} + +static int cam_isp_blob_bw_update_v2( + struct cam_isp_bw_config_v2 *bw_config, + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_vfe_bw_update_args_v2 bw_upd_args; + int rc = -EINVAL; + uint32_t i, split_idx; + bool camif_l_bw_updated = false; + bool camif_r_bw_updated = false; + + for (i = 0; i < bw_config->num_paths; i++) { + CAM_DBG(CAM_PERF, + "ISP_BLOB usage_type=%u [%s] [%s] [%s] [%llu] [%llu] [%llu]", + bw_config->usage_type, + cam_isp_util_usage_data_to_string( + bw_config->axi_path[i].usage_data), + cam_cpas_axi_util_path_type_to_string( + bw_config->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + bw_config->axi_path[i].transac_type), + bw_config->axi_path[i].camnoc_bw, + bw_config->axi_path[i].mnoc_ab_bw, + bw_config->axi_path[i].mnoc_ib_bw); + } + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + for (split_idx = 0; split_idx < CAM_ISP_HW_SPLIT_MAX; + split_idx++) { + if (!hw_mgr_res->hw_res[split_idx]) + continue; + + memset(&bw_upd_args.isp_vote, 0, + sizeof(struct cam_axi_vote)); + rc = cam_isp_classify_vote_info(hw_mgr_res, bw_config, + &bw_upd_args.isp_vote, split_idx, + &camif_l_bw_updated, &camif_r_bw_updated); + if (rc) + return rc; + + if (!bw_upd_args.isp_vote.num_paths) + continue; + + hw_intf = hw_mgr_res->hw_res[split_idx]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + bw_upd_args.node_res = + hw_mgr_res->hw_res[split_idx]; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_BW_UPDATE_V2, + &bw_upd_args, + sizeof( + struct cam_vfe_bw_update_args_v2)); + if (rc) + CAM_ERR(CAM_ISP, + "BW Update failed rc: %d", rc); + } else { + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + } + + return rc; +} + +static int cam_isp_blob_bw_update( + struct cam_isp_bw_config *bw_config, + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_vfe_bw_update_args bw_upd_args; + uint64_t cam_bw_bps = 0; + uint64_t ext_bw_bps = 0; + int rc = -EINVAL; + uint32_t i; + bool camif_l_bw_updated = false; + bool camif_r_bw_updated = false; + + CAM_DBG(CAM_PERF, + "ISP_BLOB usage=%u left cam_bw_bps=%llu ext_bw_bps=%llu, right cam_bw_bps=%llu ext_bw_bps=%llu", + bw_config->usage_type, + bw_config->left_pix_vote.cam_bw_bps, + bw_config->left_pix_vote.ext_bw_bps, + bw_config->right_pix_vote.cam_bw_bps, + bw_config->right_pix_vote.ext_bw_bps); + + 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_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; + + cam_bw_bps = + bw_config->left_pix_vote.cam_bw_bps; + ext_bw_bps = + bw_config->left_pix_vote.ext_bw_bps; + + camif_l_bw_updated = true; + } else { + if (camif_r_bw_updated) + continue; + + cam_bw_bps = + bw_config->right_pix_vote.cam_bw_bps; + ext_bw_bps = + bw_config->right_pix_vote.ext_bw_bps; + + camif_r_bw_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_RDI3)) { + uint32_t idx = hw_mgr_res->res_id - + CAM_ISP_HW_VFE_IN_RDI0; + if (idx >= bw_config->num_rdi) + continue; + + cam_bw_bps = + bw_config->rdi_vote[idx].cam_bw_bps; + ext_bw_bps = + bw_config->rdi_vote[idx].ext_bw_bps; + } else if (hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_PDLIB) { + if (i == CAM_ISP_HW_SPLIT_LEFT) { + if (camif_l_bw_updated) + continue; + + cam_bw_bps = + bw_config->left_pix_vote.cam_bw_bps; + ext_bw_bps = + bw_config->left_pix_vote.ext_bw_bps; + + camif_l_bw_updated = true; + } else { + if (camif_r_bw_updated) + continue; + + cam_bw_bps = + bw_config->right_pix_vote.cam_bw_bps; + ext_bw_bps = + bw_config->right_pix_vote.ext_bw_bps; + + camif_r_bw_updated = true; + } + } else { + if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_LCR + && hw_mgr_res->hw_res[i]) { + CAM_ERR(CAM_ISP, "Invalid res_id %u", + hw_mgr_res->res_id); + rc = -EINVAL; + return rc; + } + } + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + bw_upd_args.node_res = + hw_mgr_res->hw_res[i]; + + bw_upd_args.camnoc_bw_bytes = cam_bw_bps; + bw_upd_args.external_bw_bytes = ext_bw_bps; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_BW_UPDATE, + &bw_upd_args, + sizeof(struct cam_vfe_bw_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "BW Update failed"); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + +/* entry function: config_hw */ +static int cam_ife_mgr_config_hw(void *hw_mgr_priv, + void *config_hw_args) +{ + int rc = -1, i; + struct cam_hw_config_args *cfg; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_isp_prepare_hw_update_data *hw_update_data; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_mgr_priv || !config_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + cfg = config_hw_args; + ctx = (struct cam_ife_hw_mgr_ctx *)cfg->ctxt_to_hw_map; + if (!ctx) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + if (!ctx->ctx_in_use || !ctx->cdm_cmd) { + CAM_ERR(CAM_ISP, "Invalid context parameters"); + return -EPERM; + } + if (atomic_read(&ctx->overflow_pending)) + return -EINVAL; + + hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; + + CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld", + ctx, ctx->ctx_index, cfg->request_id); + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (hw_update_data->bw_config_valid[i] == true) { + + CAM_DBG(CAM_ISP, "idx=%d, bw_config_version=%d", + ctx, ctx->ctx_index, i, + hw_update_data->bw_config_version); + + if (hw_update_data->bw_config_version == + CAM_ISP_BW_CONFIG_V1) { + rc = cam_isp_blob_bw_update( + (struct cam_isp_bw_config *) + &hw_update_data->bw_config[i], ctx); + if (rc) + CAM_ERR(CAM_ISP, + "Bandwidth Update Failed rc: %d", rc); + } else if (hw_update_data->bw_config_version == + CAM_ISP_BW_CONFIG_V2) { + rc = cam_isp_blob_bw_update_v2( + (struct cam_isp_bw_config_v2 *) + &hw_update_data->bw_config_v2[i], ctx); + if (rc) + CAM_ERR(CAM_ISP, + "Bandwidth Update Failed rc: %d", rc); + + } else { + CAM_ERR(CAM_ISP, + "Invalid bw config version: %d", + hw_update_data->bw_config_version); + } + } + } + + 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; + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = ctx; + cdm_cmd->cookie = cfg->request_id; + + for (i = 0 ; i <= cfg->num_hw_update_entries; i++) { + cmd = (cfg->hw_update_entries + i); + cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i].offset = cmd->offset; + cdm_cmd->cmd[i].len = cmd->len; + } + + if (cfg->init_packet) + init_completion(&ctx->config_done_complete); + + CAM_DBG(CAM_ISP, "Submit to CDM"); + rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to apply the configs"); + return rc; + } + + if (cfg->init_packet) { + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(30)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, + "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 ctx_index %d", + cfg->request_id, ctx->ctx_index); + } + } + } else { + CAM_ERR(CAM_ISP, "No commands to config"); + } + CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); + + return rc; +} + +static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args) +{ + int rc = 0; + struct cam_hw_stop_args *stop_args = stop_hw_args; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_ife_hw_mgr_ctx *ctx; + uint32_t i, master_base_idx = 0; + + if (!stop_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "Enter...ctx id:%d", + ctx->ctx_index); + + if (!ctx->num_base) { + CAM_ERR(CAM_ISP, "Number of bases are zero"); + return -EINVAL; + } + + /* get master base index first */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT) { + master_base_idx = ctx->base[i].idx; + break; + } + } + + if (i == ctx->num_base) + master_base_idx = ctx->base[0].idx; + + + /* stop the master CIDs first */ + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, + master_base_idx, CAM_CSID_HALT_IMMEDIATELY); + + /* stop rest of the CIDs */ + for (i = 0; i < ctx->num_base; i++) { + if (i == master_base_idx) + continue; + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, + ctx->base[i].idx, CAM_CSID_HALT_IMMEDIATELY); + } + + /* stop the master CSID path first */ + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + master_base_idx, CAM_CSID_HALT_IMMEDIATELY); + + /* Stop rest of the CSID paths */ + for (i = 0; i < ctx->num_base; i++) { + if (i == master_base_idx) + continue; + + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + ctx->base[i].idx, CAM_CSID_HALT_IMMEDIATELY); + } + + /* 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); + } + + /* 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]); + + + /* Stop tasklet for context */ + cam_tasklet_stop(ctx->common.tasklet_info); + CAM_DBG(CAM_ISP, "Exit...ctx id:%d rc :%d", + ctx->ctx_index, rc); + + return rc; +} + +static int cam_ife_mgr_bw_control(struct cam_ife_hw_mgr_ctx *ctx, + enum cam_vfe_bw_control_action action) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_vfe_bw_control_args bw_ctrl_args; + int rc = -EINVAL; + uint32_t i; + + CAM_DBG(CAM_ISP, "Enter...ctx id:%d", ctx->ctx_index); + + 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; + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + bw_ctrl_args.node_res = + hw_mgr_res->hw_res[i]; + bw_ctrl_args.action = action; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_BW_CONTROL, + &bw_ctrl_args, + sizeof(struct cam_vfe_bw_control_args)); + if (rc) + CAM_ERR(CAM_ISP, "BW Update failed"); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + +static int cam_ife_mgr_pause_hw(struct cam_ife_hw_mgr_ctx *ctx) +{ + return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_EXCLUDE); +} + +/* entry function: stop_hw */ +static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) +{ + int rc = 0; + struct cam_hw_stop_args *stop_args = stop_hw_args; + struct cam_isp_stop_args *stop_isp; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_ife_hw_mgr_ctx *ctx; + enum cam_ife_csid_halt_cmd csid_halt_type; + uint32_t i, master_base_idx = 0; + + if (!hw_mgr_priv || !stop_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index); + stop_isp = (struct cam_isp_stop_args *)stop_args->args; + + if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_IMMEDIATELY) && + (stop_isp->stop_only)) { + CAM_ERR(CAM_ISP, "Invalid params hw_stop_cmd:%d stop_only:%d", + stop_isp->hw_stop_cmd, stop_isp->stop_only); + return -EPERM; + } + + /* Set the csid halt command */ + if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) + csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY; + else + csid_halt_type = CAM_CSID_HALT_IMMEDIATELY; + + /* Note:stop resource will remove the irq mask from the hardware */ + + if (!ctx->num_base) { + CAM_ERR(CAM_ISP, "number of bases are zero"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Halting CSIDs"); + + /* get master base index first */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT) { + master_base_idx = ctx->base[i].idx; + break; + } + } + + /* + * If Context does not have PIX resources and has only RDI resource + * then take the first base index. + */ + if (i == ctx->num_base) + master_base_idx = ctx->base[0].idx; + CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); + + /* Stop the master CSID path first */ + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY); + + /* stop rest of the CSID paths */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == master_base_idx) + continue; + CAM_DBG(CAM_ISP, "Stopping CSID idx %d i %d master %d", + ctx->base[i].idx, i, master_base_idx); + + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY); + } + + CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx); + + /* Stop the master CIDs first */ + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, + master_base_idx, csid_halt_type); + + /* stop rest of the CIDs */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == master_base_idx) + continue; + CAM_DBG(CAM_ISP, "Stopping CID idx %d i %d master %d", + ctx->base[i].idx, i, master_base_idx); + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, + 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_ife_mgr_pause_hw(ctx); + + if (stop_isp->stop_only) { + cam_tasklet_stop(ctx->common.tasklet_info); + goto end; + } + + if (cam_cdm_stream_off(ctx->cdm_handle)) + CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); + + cam_ife_hw_mgr_deinit_hw(ctx); + cam_tasklet_stop(ctx->common.tasklet_info); + + CAM_DBG(CAM_ISP, + "Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc); + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + if (!atomic_dec_return(&g_ife_hw_mgr.active_ctx_cnt)) { + rc = cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE); + if (rc) { + CAM_ERR(CAM_ISP, + "SAFE SCM call failed:Check TZ/HYP dependency"); + rc = 0; + } + } + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); + +end: + return rc; +} + +static int cam_ife_mgr_reset_vfe_hw(struct cam_ife_hw_mgr *hw_mgr, + uint32_t hw_idx) +{ + uint32_t i = 0; + struct cam_hw_intf *vfe_hw_intf; + uint32_t vfe_reset_type; + + if (!hw_mgr) { + CAM_DBG(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + /* Reset VFE HW*/ + vfe_reset_type = CAM_VFE_HW_RESET_HW; + + for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) { + if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + continue; + CAM_DBG(CAM_ISP, "VFE (id = %d) reset", hw_idx); + vfe_hw_intf = hw_mgr->ife_devices[i]; + vfe_hw_intf->hw_ops.reset(vfe_hw_intf->hw_priv, + &vfe_reset_type, sizeof(vfe_reset_type)); + break; + } + + CAM_DBG(CAM_ISP, "Exit Successfully"); + return 0; +} + +static int cam_ife_mgr_restart_hw(void *start_hw_args) +{ + int rc = -1; + struct cam_hw_start_args *start_args = start_hw_args; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t i; + + if (!start_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); + + cam_tasklet_start(ctx->common.tasklet_info); + + /* start the IFE out devices */ + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + rc = cam_ife_hw_mgr_start_hw_res( + &ctx->res_list_ife_out[i], ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE OUT (%d)", i); + goto err; + } + } + + 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); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", ctx->ctx_index); + /* Start the IFE CSID HW devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START CID SRC ... in ctx id:%d", ctx->ctx_index); + /* Start IFE root node: do nothing */ + CAM_DBG(CAM_ISP, "Exit...(success)"); + return 0; + +err: + cam_ife_mgr_stop_hw_in_overflow(start_hw_args); + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) +{ + int rc = -1; + struct cam_isp_start_args *start_isp = start_hw_args; + struct cam_hw_stop_args stop_args; + struct cam_isp_stop_args stop_isp; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *rsrc_node = NULL; + uint32_t i, camif_debug; + + if (!hw_mgr_priv || !start_isp) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *) + start_isp->hw_config.ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + if ((!ctx->init_done) && start_isp->start_only) { + CAM_ERR(CAM_ISP, "Invalid args init_done %d start_only %d", + ctx->init_done, start_isp->start_only); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Enter... ctx id:%d", + ctx->ctx_index); + + /* update Bandwidth should be done at the hw layer */ + + cam_tasklet_start(ctx->common.tasklet_info); + + if (ctx->init_done && start_isp->start_only) + goto start_only; + + /* set current csid debug information to CSID HW */ + for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { + if (g_ife_hw_mgr.csid_devices[i]) + rc = g_ife_hw_mgr.csid_devices[i]->hw_ops.process_cmd( + g_ife_hw_mgr.csid_devices[i]->hw_priv, + CAM_IFE_CSID_SET_CSID_DEBUG, + &g_ife_hw_mgr.debug_cfg.csid_debug, + sizeof(g_ife_hw_mgr.debug_cfg.csid_debug)); + } + + camif_debug = g_ife_hw_mgr.debug_cfg.camif_debug; + 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; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->process_cmd && (rsrc_node->res_id == + CAM_ISP_HW_VFE_IN_CAMIF)) { + rc = hw_mgr_res->hw_res[i]->process_cmd( + hw_mgr_res->hw_res[i], + CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + &camif_debug, + sizeof(camif_debug)); + } + } + } + + rc = cam_ife_hw_mgr_init_hw(ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Init failed"); + goto tasklet_stop; + } + + ctx->init_done = true; + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + if (!atomic_fetch_inc(&g_ife_hw_mgr.active_ctx_cnt)) { + rc = cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_ENABLE); + if (rc) { + CAM_ERR(CAM_ISP, + "SAFE SCM call failed:Check TZ/HYP dependency"); + rc = -EFAULT; + goto deinit_hw; + } + } + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); + + CAM_DBG(CAM_ISP, "start cdm interface"); + rc = cam_cdm_stream_on(ctx->cdm_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start cdm (%d)", + ctx->cdm_handle); + goto safe_disable; + } + + /* Apply initial configuration */ + CAM_DBG(CAM_ISP, "Config HW"); + rc = cam_ife_mgr_config_hw(hw_mgr_priv, &start_isp->hw_config); + if (rc) { + CAM_ERR(CAM_ISP, "Config HW failed"); + goto cdm_streamoff; + } + +start_only: + + CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", + ctx->ctx_index); + /* start the IFE out devices */ + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + rc = cam_ife_hw_mgr_start_hw_res( + &ctx->res_list_ife_out[i], ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE OUT (%d)", + i); + goto err; + } + } + + 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 */ + 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); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", + ctx->ctx_index); + /* Start the IFE CSID HW devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START CID SRC ... in ctx id:%d", + ctx->ctx_index); + /* Start the IFE CID HW devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { + rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + /* Start IFE root node: do nothing */ + CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index); + + return 0; + +err: + stop_isp.stop_only = false; + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; + stop_args.ctxt_to_hw_map = start_isp->hw_config.ctxt_to_hw_map; + stop_args.args = (void *)(&stop_isp); + + cam_ife_mgr_stop_hw(hw_mgr_priv, &stop_args); + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; + +cdm_streamoff: + cam_cdm_stream_off(ctx->cdm_handle); + +safe_disable: + cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE); + +deinit_hw: + cam_ife_hw_mgr_deinit_hw(ctx); + +tasklet_stop: + cam_tasklet_stop(ctx->common.tasklet_info); + + return rc; +} + +static int cam_ife_mgr_read(void *hw_mgr_priv, void *read_args) +{ + return -EPERM; +} + +static int cam_ife_mgr_write(void *hw_mgr_priv, void *write_args) +{ + return -EPERM; +} + +static int cam_ife_mgr_release_hw(void *hw_mgr_priv, + void *release_hw_args) +{ + int rc = 0; + struct cam_hw_release_args *release_args = release_hw_args; + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_ife_hw_mgr_ctx *ctx; + uint32_t i; + + if (!hw_mgr_priv || !release_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)release_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "Enter...ctx id:%d", + ctx->ctx_index); + + if (ctx->init_done) + cam_ife_hw_mgr_deinit_hw(ctx); + + /* we should called the stop hw before this already */ + cam_ife_hw_mgr_release_hw_for_ctx(ctx); + + /* reset base info */ + ctx->num_base = 0; + memset(ctx->base, 0, sizeof(ctx->base)); + + /* release cdm handle */ + cam_cdm_release(ctx->cdm_handle); + + /* clean context */ + list_del_init(&ctx->list); + ctx->ctx_in_use = 0; + ctx->is_rdi_only_context = 0; + ctx->cdm_handle = 0; + ctx->cdm_ops = NULL; + atomic_set(&ctx->overflow_pending, 0); + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + ctx->sof_cnt[i] = 0; + ctx->eof_cnt[i] = 0; + ctx->epoch_cnt[i] = 0; + } + CAM_DBG(CAM_ISP, "Exit...ctx id:%d", + ctx->ctx_index); + cam_ife_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx); + 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, + struct cam_ubwc_config *ubwc_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ubwc_plane_cfg_v1 *ubwc_plane_cfg; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t res_id_out, i; + uint32_t total_used_bytes = 0; + uint32_t kmd_buf_remain_size; + uint32_t *cmd_buf_addr; + uint32_t bytes_used = 0; + int num_ent, rc = 0; + + ctx = prepare->ctxt_to_hw_map; + if (!ctx) { + CAM_ERR(CAM_ISP, "Invalid ctx"); + rc = -EINVAL; + goto end; + } + + if ((prepare->num_hw_update_entries + 1) >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + rc = -EINVAL; + goto end; + } + + switch (ubwc_config->api_version) { + case CAM_UBWC_CFG_VERSION_1: + CAM_DBG(CAM_ISP, "num_ports= %d", ubwc_config->num_ports); + + kmd_buf_info = blob_info->kmd_buf_info; + for (i = 0; i < ubwc_config->num_ports; i++) { + ubwc_plane_cfg = &ubwc_config->ubwc_plane_cfg[i][0]; + res_id_out = ubwc_plane_cfg->port_type & 0xFF; + + CAM_DBG(CAM_ISP, "UBWC config idx %d, port_type=%d", i, + ubwc_plane_cfg->port_type); + + if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid port type:%x", + ubwc_plane_cfg->port_type); + rc = -EINVAL; + goto end; + } + + if ((kmd_buf_info->used_bytes + + total_used_bytes) < kmd_buf_info->size) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + total_used_bytes); + } else { + CAM_ERR(CAM_ISP, + "no free kmd memory for base=%d bytes_used=%u buf_size=%u", + blob_info->base_info->idx, bytes_used, + kmd_buf_info->size); + rc = -ENOMEM; + goto end; + } + + cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + total_used_bytes/4; + hw_mgr_res = &ctx->res_list_ife_out[res_id_out]; + + if (!hw_mgr_res) { + CAM_ERR(CAM_ISP, "Invalid hw_mgr_res"); + rc = -EINVAL; + goto end; + } + + rc = cam_isp_add_cmd_buf_update( + hw_mgr_res, blob_type, + blob_type_hw_cmd_map[blob_type], + blob_info->base_info->idx, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)ubwc_plane_cfg, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%x", + blob_info->base_info->idx, + bytes_used, + res_id_out); + goto end; + } + + total_used_bytes += bytes_used; + } + + if (total_used_bytes) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = + total_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + num_ent++; + + kmd_buf_info->used_bytes += total_used_bytes; + kmd_buf_info->offset += total_used_bytes; + prepare->num_hw_update_entries = num_ent; + } + break; + default: + CAM_ERR(CAM_ISP, "Invalid UBWC API Version %d", + ubwc_config->api_version); + rc = -EINVAL; + break; + } +end: + return rc; +} + +static int cam_isp_get_generic_ubwc_data_v2( + struct cam_ubwc_plane_cfg_v2 *ubwc_cfg, + uint32_t version, + struct cam_vfe_generic_ubwc_config *generic_ubwc_cfg) +{ + int i = 0; + + generic_ubwc_cfg->api_version = version; + for (i = 0; i < CAM_PACKET_MAX_PLANES - 1; i++) { + generic_ubwc_cfg->ubwc_plane_cfg[i].port_type = + ubwc_cfg[i].port_type; + generic_ubwc_cfg->ubwc_plane_cfg[i].meta_stride = + ubwc_cfg[i].meta_stride; + generic_ubwc_cfg->ubwc_plane_cfg[i].meta_size = + ubwc_cfg[i].meta_size; + generic_ubwc_cfg->ubwc_plane_cfg[i].meta_offset = + ubwc_cfg[i].meta_offset; + generic_ubwc_cfg->ubwc_plane_cfg[i].packer_config = + ubwc_cfg[i].packer_config; + generic_ubwc_cfg->ubwc_plane_cfg[i].mode_config_0 = + ubwc_cfg[i].mode_config_0; + generic_ubwc_cfg->ubwc_plane_cfg[i].mode_config_1 = + ubwc_cfg[i].mode_config_1; + generic_ubwc_cfg->ubwc_plane_cfg[i].tile_config = + ubwc_cfg[i].tile_config; + generic_ubwc_cfg->ubwc_plane_cfg[i].h_init = + ubwc_cfg[i].h_init; + generic_ubwc_cfg->ubwc_plane_cfg[i].v_init = + ubwc_cfg[i].v_init; + generic_ubwc_cfg->ubwc_plane_cfg[i].static_ctrl = + ubwc_cfg[i].static_ctrl; + generic_ubwc_cfg->ubwc_plane_cfg[i].ctrl_2 = + ubwc_cfg[i].ctrl_2; + generic_ubwc_cfg->ubwc_plane_cfg[i].stats_ctrl_2 = + ubwc_cfg[i].stats_ctrl_2; + generic_ubwc_cfg->ubwc_plane_cfg[i].lossy_threshold_0 = + ubwc_cfg[i].lossy_threshold_0; + generic_ubwc_cfg->ubwc_plane_cfg[i].lossy_threshold_1 = + ubwc_cfg[i].lossy_threshold_1; + generic_ubwc_cfg->ubwc_plane_cfg[i].lossy_var_offset = + ubwc_cfg[i].lossy_var_offset; + generic_ubwc_cfg->ubwc_plane_cfg[i].bandwidth_limit = + ubwc_cfg[i].bandwidth_limit; + } + + return 0; +} + +static int cam_isp_blob_ubwc_update_v2( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_ubwc_config_v2 *ubwc_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ubwc_plane_cfg_v2 *ubwc_plane_cfg; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t res_id_out, i; + uint32_t total_used_bytes = 0; + uint32_t kmd_buf_remain_size; + uint32_t *cmd_buf_addr; + uint32_t bytes_used = 0; + int num_ent, rc = 0; + struct cam_vfe_generic_ubwc_config generic_ubwc_cfg; + + ctx = prepare->ctxt_to_hw_map; + if (!ctx) { + CAM_ERR(CAM_ISP, "Invalid ctx"); + rc = -EINVAL; + goto end; + } + + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "num_ports= %d", ubwc_config->num_ports); + + kmd_buf_info = blob_info->kmd_buf_info; + for (i = 0; i < ubwc_config->num_ports; i++) { + ubwc_plane_cfg = &ubwc_config->ubwc_plane_cfg[i][0]; + res_id_out = ubwc_plane_cfg->port_type & 0xFF; + + CAM_DBG(CAM_ISP, "UBWC config idx %d, port_type=%d", i, + ubwc_plane_cfg->port_type); + + if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid port type:%x", + ubwc_plane_cfg->port_type); + rc = -EINVAL; + goto end; + } + + if ((kmd_buf_info->used_bytes + + total_used_bytes) < kmd_buf_info->size) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + total_used_bytes); + } else { + CAM_ERR(CAM_ISP, + "no free kmd memory for base=%d bytes_used=%u buf_size=%u", + blob_info->base_info->idx, bytes_used, + kmd_buf_info->size); + rc = -ENOMEM; + goto end; + } + + cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + total_used_bytes/4; + hw_mgr_res = &ctx->res_list_ife_out[res_id_out]; + + if (!hw_mgr_res) { + CAM_ERR(CAM_ISP, "Invalid hw_mgr_res"); + rc = -EINVAL; + goto end; + } + + rc = cam_isp_get_generic_ubwc_data_v2(ubwc_plane_cfg, + ubwc_config->api_version, &generic_ubwc_cfg); + + rc = cam_isp_add_cmd_buf_update( + hw_mgr_res, blob_type, + blob_type_hw_cmd_map[blob_type], + blob_info->base_info->idx, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)&generic_ubwc_cfg, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%x", + blob_info->base_info->idx, + bytes_used, + res_id_out); + goto end; + } + + total_used_bytes += bytes_used; + } + + if (total_used_bytes) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = + total_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + num_ent++; + + kmd_buf_info->used_bytes += total_used_bytes; + kmd_buf_info->offset += total_used_bytes; + prepare->num_hw_update_entries = num_ent; + } +end: + return rc; +} + +static int cam_isp_blob_hfr_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_resource_hfr_config *hfr_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_isp_port_hfr_config *port_hfr_config; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t res_id_out, i; + uint32_t total_used_bytes = 0; + uint32_t kmd_buf_remain_size; + uint32_t *cmd_buf_addr; + uint32_t bytes_used = 0; + int num_ent, rc = 0; + + ctx = prepare->ctxt_to_hw_map; + CAM_DBG(CAM_ISP, "num_ports= %d", + hfr_config->num_ports); + + /* Max one hw entries required for hfr config update */ + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + kmd_buf_info = blob_info->kmd_buf_info; + for (i = 0; i < hfr_config->num_ports; i++) { + port_hfr_config = &hfr_config->port_hfr_config[i]; + res_id_out = port_hfr_config->resource_type & 0xFF; + + CAM_DBG(CAM_ISP, "hfr config idx %d, type=%d", i, + res_id_out); + + if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "invalid out restype:%x", + port_hfr_config->resource_type); + return -EINVAL; + } + + if ((kmd_buf_info->used_bytes + + total_used_bytes) < kmd_buf_info->size) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + total_used_bytes); + } else { + CAM_ERR(CAM_ISP, + "no free kmd memory for base %d", + blob_info->base_info->idx); + rc = -ENOMEM; + return rc; + } + + cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + total_used_bytes/4; + hw_mgr_res = &ctx->res_list_ife_out[res_id_out]; + + rc = cam_isp_add_cmd_buf_update( + hw_mgr_res, blob_type, + blob_type_hw_cmd_map[blob_type], + blob_info->base_info->idx, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)port_hfr_config, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed cmd_update, base_idx=%d, rc=%d", + blob_info->base_info->idx, bytes_used); + return rc; + } + + total_used_bytes += bytes_used; + } + + if (total_used_bytes) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + num_ent++; + + kmd_buf_info->used_bytes += total_used_bytes; + kmd_buf_info->offset += total_used_bytes; + prepare->num_hw_update_entries = num_ent; + } + + return rc; +} + +static int cam_isp_blob_csid_clock_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_csid_clock_config *clock_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; + struct cam_ife_csid_clock_update_args csid_clock_upd_args; + uint64_t clk_rate = 0; + int rc = -EINVAL; + uint32_t i; + + ctx = prepare->ctxt_to_hw_map; + + CAM_DBG(CAM_ISP, + "csid clk=%llu", clock_config->csid_clock); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + clk_rate = 0; + if (!hw_mgr_res->hw_res[i]) + continue; + clk_rate = clock_config->csid_clock; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + csid_clock_upd_args.clk_rate = clk_rate; + CAM_DBG(CAM_ISP, "i= %d clk=%llu\n", + i, csid_clock_upd_args.clk_rate); + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + blob_type_hw_cmd_map[blob_type], + &csid_clock_upd_args, + sizeof( + struct cam_ife_csid_clock_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + +static int cam_isp_blob_core_cfg_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_core_config *core_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; + uint64_t clk_rate = 0; + int rc = 0, i; + struct cam_vfe_core_config_args vfe_core_config; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + clk_rate = 0; + if (!hw_mgr_res->hw_res[i] || + hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF) + continue; + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + vfe_core_config.node_res = + hw_mgr_res->hw_res[i]; + + memcpy(&vfe_core_config.core_config, + core_config, + sizeof(struct cam_isp_core_config)); + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CORE_CONFIG, + &vfe_core_config, + sizeof( + struct cam_vfe_core_config_args)); + if (rc) + CAM_ERR(CAM_ISP, "Core cfg parse fail"); + } else { + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + } + + return rc; +} + +static int cam_isp_blob_clock_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_clock_config *clock_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; + struct cam_vfe_clock_update_args clock_upd_args; + uint64_t clk_rate = 0; + int rc = -EINVAL; + uint32_t i; + uint32_t j; + bool camif_l_clk_updated = false; + bool camif_r_clk_updated = false; + + ctx = prepare->ctxt_to_hw_map; + + CAM_DBG(CAM_PERF, + "usage=%u left_clk= %lu right_clk=%lu", + clock_config->usage_type, + clock_config->left_pix_hz, + clock_config->right_pix_hz); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + clk_rate = 0; + if (!hw_mgr_res->hw_res[i]) + continue; + + if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { + if (i == CAM_ISP_HW_SPLIT_LEFT) { + if (camif_l_clk_updated) + continue; + + clk_rate = + clock_config->left_pix_hz; + + camif_l_clk_updated = true; + } else { + if (camif_r_clk_updated) + continue; + + clk_rate = + clock_config->right_pix_hz; + + camif_r_clk_updated = true; + } + } else if (hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_PDLIB) { + if (i == CAM_ISP_HW_SPLIT_LEFT) { + if (camif_l_clk_updated) + continue; + + clk_rate = + clock_config->left_pix_hz; + + camif_l_clk_updated = true; + } else { + if (camif_r_clk_updated) + continue; + + clk_rate = + clock_config->right_pix_hz; + + camif_r_clk_updated = true; + } + } else if ((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], + clk_rate); + else + if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_LCR + && hw_mgr_res->hw_res[i]) { + CAM_ERR(CAM_ISP, "Invalid res_id %u", + hw_mgr_res->res_id); + rc = -EINVAL; + return rc; + } + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + clock_upd_args.node_res = + hw_mgr_res->hw_res[i]; + CAM_DBG(CAM_ISP, + "res_id=%u i= %d clk=%llu\n", + hw_mgr_res->res_id, i, clk_rate); + + clock_upd_args.clk_rate = clk_rate; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CLOCK_UPDATE, + &clock_upd_args, + sizeof( + struct cam_vfe_clock_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update failed"); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + +static int cam_isp_blob_vfe_out_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_vfe_out_config *vfe_out_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_isp_vfe_wm_config *wm_config; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *ife_out_res; + uint32_t res_id_out, i; + uint32_t total_used_bytes = 0; + uint32_t kmd_buf_remain_size; + uint32_t *cmd_buf_addr; + uint32_t bytes_used = 0; + int num_ent, rc = 0; + + ctx = prepare->ctxt_to_hw_map; + + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + kmd_buf_info = blob_info->kmd_buf_info; + for (i = 0; i < vfe_out_config->num_ports; i++) { + wm_config = &vfe_out_config->wm_config[i]; + res_id_out = wm_config->port_type & 0xFF; + + CAM_DBG(CAM_ISP, "VFE out config idx: %d port: 0x%x", + i, wm_config->port_type); + + if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid out port:0x%x", + wm_config->port_type); + return -EINVAL; + } + + if ((kmd_buf_info->used_bytes + + total_used_bytes) < kmd_buf_info->size) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + total_used_bytes); + } else { + CAM_ERR(CAM_ISP, + "No free kmd memory for base idx: %d", + blob_info->base_info->idx); + rc = -ENOMEM; + return rc; + } + + cmd_buf_addr = kmd_buf_info->cpu_addr + + (kmd_buf_info->used_bytes / 4) + + (total_used_bytes / 4); + ife_out_res = &ctx->res_list_ife_out[res_id_out]; + + rc = cam_isp_add_cmd_buf_update( + ife_out_res, blob_type, + blob_type_hw_cmd_map[blob_type], + blob_info->base_info->idx, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)wm_config, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed to update VFE Out out_type:0x%X base_idx:%d bytes_used:%u rc:%d", + wm_config->port_type, blob_info->base_info->idx, + bytes_used, rc); + return rc; + } + + total_used_bytes += bytes_used; + } + + if (total_used_bytes) { + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + num_ent++; + + kmd_buf_info->used_bytes += total_used_bytes; + kmd_buf_info->offset += total_used_bytes; + prepare->num_hw_update_entries = num_ent; + } + + return rc; +} + +static int cam_isp_packet_generic_blob_handler(void *user_data, + uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) +{ + int rc = 0; + struct cam_isp_generic_blob_info *blob_info = user_data; + struct cam_hw_prepare_update_args *prepare = NULL; + struct cam_ife_hw_mgr_ctx *ife_mgr_ctx = NULL; + + if (!blob_data || (blob_size == 0) || !blob_info) { + CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK", + blob_data, blob_size, blob_info); + return -EINVAL; + } + + if (blob_type >= CAM_ISP_GENERIC_BLOB_TYPE_MAX) { + CAM_ERR(CAM_ISP, "Invalid Blob Type %d Max %d", blob_type, + CAM_ISP_GENERIC_BLOB_TYPE_MAX); + return -EINVAL; + } + + prepare = blob_info->prepare; + if (!prepare || !prepare->ctxt_to_hw_map) { + CAM_ERR(CAM_ISP, "Failed. prepare is NULL, blob_type %d", + blob_type); + return -EINVAL; + } + + ife_mgr_ctx = prepare->ctxt_to_hw_map; + CAM_DBG(CAM_ISP, "Context[%pK][%d] blob_type=%d, blob_size=%d", + ife_mgr_ctx, ife_mgr_ctx->ctx_index, blob_type, blob_size); + + switch (blob_type) { + case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: { + struct cam_isp_resource_hfr_config *hfr_config; + + if (blob_size < sizeof(struct cam_isp_resource_hfr_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + hfr_config = (struct cam_isp_resource_hfr_config *)blob_data; + + if (hfr_config->num_ports > CAM_ISP_IFE_OUT_RES_MAX || + hfr_config->num_ports == 0) { + CAM_ERR(CAM_ISP, "Invalid num_ports %u in HFR config", + hfr_config->num_ports); + return -EINVAL; + } + + /* Check for integer overflow */ + if (hfr_config->num_ports != 1) { + if (sizeof(struct cam_isp_port_hfr_config) > + ((UINT_MAX - + sizeof(struct cam_isp_resource_hfr_config)) / + (hfr_config->num_ports - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in hfr config num_ports:%u size per port:%lu", + hfr_config->num_ports, + sizeof(struct cam_isp_port_hfr_config)); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_isp_resource_hfr_config) + + (hfr_config->num_ports - 1) * + sizeof(struct cam_isp_port_hfr_config))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(struct cam_isp_resource_hfr_config) + + (hfr_config->num_ports - 1) * + sizeof(struct cam_isp_port_hfr_config)); + return -EINVAL; + } + + rc = cam_isp_blob_hfr_update(blob_type, blob_info, + hfr_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "HFR Update Failed"); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: { + struct cam_isp_clock_config *clock_config; + + if (blob_size < sizeof(struct cam_isp_clock_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + clock_config = (struct cam_isp_clock_config *)blob_data; + + if (clock_config->num_rdi > CAM_IFE_RDI_NUM_MAX) { + CAM_ERR(CAM_ISP, "Invalid num_rdi %u in clock config", + clock_config->num_rdi); + return -EINVAL; + } + + /* Check for integer overflow */ + if (clock_config->num_rdi != 1) { + if (sizeof(uint64_t) > ((UINT_MAX - + sizeof(struct cam_isp_clock_config)) / + (clock_config->num_rdi - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in clock config num_rdi:%u size per port:%lu", + clock_config->num_rdi, + sizeof(uint64_t)); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_isp_clock_config) + + sizeof(uint64_t) * (clock_config->num_rdi - 1))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(uint32_t) * 2 + sizeof(uint64_t) * + (clock_config->num_rdi + 2)); + return -EINVAL; + } + + rc = cam_isp_blob_clock_update(blob_type, blob_info, + clock_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update Failed"); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: { + struct cam_isp_bw_config *bw_config; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + CAM_WARN(CAM_ISP, "Deprecated Blob TYPE_BW_CONFIG"); + if (blob_size < sizeof(struct cam_isp_bw_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + bw_config = (struct cam_isp_bw_config *)blob_data; + + if (bw_config->num_rdi > CAM_IFE_RDI_NUM_MAX) { + CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config", + bw_config->num_rdi); + return -EINVAL; + } + + /* Check for integer overflow */ + if (bw_config->num_rdi != 1) { + if (sizeof(struct cam_isp_bw_vote) > ((UINT_MAX - + sizeof(struct cam_isp_bw_config)) / + (bw_config->num_rdi - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in bw config num_rdi:%u size per port:%lu", + bw_config->num_rdi, + sizeof(struct cam_isp_bw_vote)); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_isp_bw_config) + + (bw_config->num_rdi - 1) * + sizeof(struct cam_isp_bw_vote))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, sizeof(struct cam_isp_bw_config) + + (bw_config->num_rdi - 1) * + sizeof(struct cam_isp_bw_vote)); + return -EINVAL; + } + + if (!prepare || !prepare->priv || + (bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) { + CAM_ERR(CAM_ISP, "Invalid inputs"); + return -EINVAL; + } + + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + memcpy(&prepare_hw_data->bw_config[bw_config->usage_type], + bw_config, sizeof(prepare_hw_data->bw_config[0])); + prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V1; + prepare_hw_data->bw_config_valid[bw_config->usage_type] = true; + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2: { + size_t bw_config_size = 0; + struct cam_isp_bw_config_v2 *bw_config; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + if (blob_size < sizeof(struct cam_isp_bw_config_v2)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + bw_config = (struct cam_isp_bw_config_v2 *)blob_data; + + if (bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) { + CAM_ERR(CAM_ISP, "Invalid num paths %d", + bw_config->num_paths); + return -EINVAL; + } + + /* Check for integer overflow */ + if (bw_config->num_paths != 1) { + if (sizeof(struct cam_axi_per_path_bw_vote) > + ((UINT_MAX - + sizeof(struct cam_isp_bw_config_v2)) / + (bw_config->num_paths - 1))) { + CAM_ERR(CAM_ISP, + "Size exceeds limit paths:%u size per path:%lu", + bw_config->num_paths - 1, + sizeof( + struct cam_axi_per_path_bw_vote)); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_isp_bw_config_v2) + + ((bw_config->num_paths - 1) * + sizeof(struct cam_axi_per_path_bw_vote)))) { + CAM_ERR(CAM_ISP, + "Invalid blob size: %u, num_paths: %u, bw_config size: %lu, per_path_vote size: %lu", + blob_size, bw_config->num_paths, + sizeof(struct cam_isp_bw_config_v2), + sizeof(struct cam_axi_per_path_bw_vote)); + return -EINVAL; + } + + if (!prepare || !prepare->priv || + (bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) { + CAM_ERR(CAM_ISP, "Invalid inputs"); + return -EINVAL; + } + + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + memset(&prepare_hw_data->bw_config_v2[bw_config->usage_type], + 0, sizeof( + prepare_hw_data->bw_config_v2[bw_config->usage_type])); + bw_config_size = sizeof(struct cam_isp_bw_config_internal_v2) + + ((bw_config->num_paths - 1) * + sizeof(struct cam_axi_per_path_bw_vote)); + memcpy(&prepare_hw_data->bw_config_v2[bw_config->usage_type], + bw_config, bw_config_size); + + prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V2; + prepare_hw_data->bw_config_valid[bw_config->usage_type] = true; + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG: { + struct cam_ubwc_config *ubwc_config; + + if (blob_size < sizeof(struct cam_ubwc_config)) { + CAM_ERR(CAM_ISP, "Invalid blob_size %u", blob_size); + return -EINVAL; + } + + ubwc_config = (struct cam_ubwc_config *)blob_data; + + if (ubwc_config->num_ports > CAM_VFE_MAX_UBWC_PORTS || + ubwc_config->num_ports == 0) { + CAM_ERR(CAM_ISP, "Invalid num_ports %u in ubwc config", + ubwc_config->num_ports); + return -EINVAL; + } + + /* Check for integer overflow */ + if (ubwc_config->num_ports != 1) { + if (sizeof(struct cam_ubwc_plane_cfg_v1) > + ((UINT_MAX - sizeof(struct cam_ubwc_config)) / + ((ubwc_config->num_ports - 1) * 2))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in ubwc config num_ports:%u size per port:%lu", + ubwc_config->num_ports, + sizeof(struct cam_ubwc_plane_cfg_v1) * + 2); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_ubwc_config) + + (ubwc_config->num_ports - 1) * + sizeof(struct cam_ubwc_plane_cfg_v1) * 2)) { + CAM_ERR(CAM_ISP, "Invalid blob_size %u expected %lu", + blob_size, + sizeof(struct cam_ubwc_config) + + (ubwc_config->num_ports - 1) * + sizeof(struct cam_ubwc_plane_cfg_v1) * 2); + return -EINVAL; + } + + rc = cam_isp_blob_ubwc_update(blob_type, blob_info, + ubwc_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "UBWC Update Failed rc: %d", rc); + } + break; + + case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2: { + struct cam_ubwc_config_v2 *ubwc_config; + + if (blob_size < sizeof(struct cam_ubwc_config_v2)) { + CAM_ERR(CAM_ISP, "Invalid blob_size %u", blob_size); + return -EINVAL; + } + + ubwc_config = (struct cam_ubwc_config_v2 *)blob_data; + + if (ubwc_config->num_ports > CAM_VFE_MAX_UBWC_PORTS || + ubwc_config->num_ports == 0) { + CAM_ERR(CAM_ISP, "Invalid num_ports %u in ubwc config", + ubwc_config->num_ports); + return -EINVAL; + } + + /* Check for integer overflow */ + if (ubwc_config->num_ports != 1) { + if (sizeof(struct cam_ubwc_plane_cfg_v2) > + ((UINT_MAX - sizeof(struct cam_ubwc_config_v2)) + / ((ubwc_config->num_ports - 1) * 2))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in ubwc config num_ports:%u size per port:%lu", + ubwc_config->num_ports, + sizeof(struct cam_ubwc_plane_cfg_v2) * + 2); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_ubwc_config_v2) + + (ubwc_config->num_ports - 1) * + sizeof(struct cam_ubwc_plane_cfg_v2) * 2)) { + CAM_ERR(CAM_ISP, "Invalid blob_size %u expected %lu", + blob_size, + sizeof(struct cam_ubwc_config_v2) + + (ubwc_config->num_ports - 1) * + sizeof(struct cam_ubwc_plane_cfg_v2) * 2); + return -EINVAL; + } + + rc = cam_isp_blob_ubwc_update_v2(blob_type, blob_info, + ubwc_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "UBWC Update Failed rc: %d", rc); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG: { + struct cam_isp_csid_clock_config *clock_config; + + if (blob_size < sizeof(struct cam_isp_csid_clock_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(struct cam_isp_csid_clock_config)); + return -EINVAL; + } + + clock_config = (struct cam_isp_csid_clock_config *)blob_data; + + rc = cam_isp_blob_csid_clock_update(blob_type, blob_info, + clock_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update Failed"); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: { + struct cam_fe_config *fe_config; + + if (blob_size < sizeof(struct cam_fe_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, sizeof(struct cam_fe_config)); + return -EINVAL; + } + + 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; + case CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG: { + struct cam_isp_core_config *core_config; + + if (blob_size < sizeof(struct cam_isp_core_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, sizeof(struct cam_isp_core_config)); + return -EINVAL; + } + + core_config = (struct cam_isp_core_config *)blob_data; + + rc = cam_isp_blob_core_cfg_update(blob_type, blob_info, + core_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Core cfg update fail: %d", rc); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG: { + struct cam_isp_vfe_out_config *vfe_out_config; + + if (blob_size < sizeof(struct cam_isp_vfe_out_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", + blob_size, + sizeof(struct cam_isp_vfe_out_config)); + return -EINVAL; + } + + vfe_out_config = (struct cam_isp_vfe_out_config *)blob_data; + + if (vfe_out_config->num_ports > CAM_IFE_HW_OUT_RES_MAX || + vfe_out_config->num_ports == 0) { + CAM_ERR(CAM_ISP, + "Invalid num_ports:%u in vfe out config", + vfe_out_config->num_ports, + CAM_IFE_HW_OUT_RES_MAX); + return -EINVAL; + } + + /* Check for integer overflow */ + if (vfe_out_config->num_ports != 1) { + if (sizeof(struct cam_isp_vfe_wm_config) > ((UINT_MAX - + sizeof(struct cam_isp_vfe_out_config)) / + (vfe_out_config->num_ports - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in vfe out config num_ports:%u size per port:%lu", + vfe_out_config->num_ports, + sizeof(struct cam_isp_vfe_wm_config)); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_isp_vfe_out_config) + + (vfe_out_config->num_ports - 1) * + sizeof(struct cam_isp_vfe_wm_config))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, sizeof(struct cam_isp_vfe_out_config) + + (vfe_out_config->num_ports - 1) * + sizeof(struct cam_isp_vfe_wm_config)); + return -EINVAL; + } + + rc = cam_isp_blob_vfe_out_update(blob_type, blob_info, + vfe_out_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "VFE out update failed rc: %d", rc); + } + break; + + default: + CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); + break; + } + + return rc; +} + +static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, + void *prepare_hw_update_args) +{ + int rc = 0; + struct cam_hw_prepare_update_args *prepare = + (struct cam_hw_prepare_update_args *) prepare_hw_update_args; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr *hw_mgr; + struct cam_kmd_buf_info kmd_buf; + uint32_t i; + bool fill_fence = true; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + if (!hw_mgr_priv || !prepare_hw_update_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map; + hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv; + + + CAM_DBG(CAM_REQ, "ctx[%pK][%d] Enter for req_id %lld", + ctx, ctx->ctx_index, prepare->packet->header.request_id); + + rc = cam_packet_util_validate_packet(prepare->packet, + prepare->remain_len); + if (rc) + return rc; + + /* Pre parse the packet*/ + rc = cam_packet_util_get_kmd_buffer(prepare->packet, &kmd_buf); + if (rc) + return rc; + + rc = cam_packet_util_process_patches(prepare->packet, + hw_mgr->mgr_common.cmd_iommu_hdl, + hw_mgr->mgr_common.cmd_iommu_hdl_secure); + if (rc) { + CAM_ERR(CAM_ISP, "Patch ISP packet failed."); + return rc; + } + + prepare->num_hw_update_entries = 0; + prepare->num_in_map_entries = 0; + prepare->num_out_map_entries = 0; + + memset(&prepare_hw_data->bw_config[0], 0x0, + sizeof(prepare_hw_data->bw_config[0]) * + CAM_IFE_HW_NUM_MAX); + memset(&prepare_hw_data->bw_config_valid[0], 0x0, + sizeof(prepare_hw_data->bw_config_valid[0]) * + CAM_IFE_HW_NUM_MAX); + + for (i = 0; i < ctx->num_base; i++) { + CAM_DBG(CAM_ISP, "process cmd buffer for device %d", i); + + /* Add change base */ + rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in change base i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + + + /* get command buffers */ + if (ctx->base[i].split_id != CAM_ISP_HW_SPLIT_MAX) { + rc = cam_isp_add_command_buffers(prepare, &kmd_buf, + &ctx->base[i], + cam_isp_packet_generic_blob_handler, + ctx->res_list_ife_out, CAM_IFE_HW_OUT_RES_MAX); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in add cmdbuf, i=%d, split_id=%d, rc=%d", + i, ctx->base[i].split_id, rc); + goto end; + } + } + + /* get IO buffers */ + rc = cam_isp_add_io_buffers(hw_mgr->mgr_common.img_iommu_hdl, + hw_mgr->mgr_common.img_iommu_hdl_secure, + prepare, ctx->base[i].idx, + &kmd_buf, ctx->res_list_ife_out, + &ctx->res_list_ife_in_rd, + CAM_IFE_HW_OUT_RES_MAX, fill_fence); + + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in io buffers, i=%d, rc=%d", + i, rc); + goto end; + } + + /* fence map table entries need to fill only once in the loop */ + if (fill_fence) + fill_fence = false; + } + + /* + * reg update will be done later for the initial configure. + * need to plus one to the op_code and only take the lower + * bits to get the type of operation since UMD definition + * of op_code has some difference from KMD. + */ + if (((prepare->packet->header.op_code + 1) & 0xF) == + CAM_ISP_PACKET_INIT_DEV) { + prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV; + goto end; + } else + prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV; + + /* add reg update commands */ + for (i = 0; i < ctx->num_base; i++) { + /* Add change base */ + rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in change base adding reg_update cmd i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + + /*Add reg update */ + rc = cam_isp_add_reg_update(prepare, &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Add Reg_update cmd Failed i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + } + +end: + return rc; +} + +static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) +{ + return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); +} + +static int cam_ife_mgr_sof_irq_debug( + struct cam_ife_hw_mgr_ctx *ctx, + uint32_t sof_irq_enable) +{ + int rc = 0; + uint32_t i = 0; + struct cam_ife_hw_mgr_res *hw_mgr_res = NULL; + struct cam_hw_intf *hw_intf = NULL; + struct cam_isp_resource_node *rsrc_node = NULL; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, 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_ops.process_cmd) { + rc |= hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_SOF_IRQ_DEBUG, + &sof_irq_enable, + sizeof(sof_irq_enable)); + } + } + } + + 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; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->process_cmd && (rsrc_node->res_id == + CAM_ISP_HW_VFE_IN_CAMIF)) { + rc |= hw_mgr_res->hw_res[i]->process_cmd( + hw_mgr_res->hw_res[i], + CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, + &sof_irq_enable, + sizeof(sof_irq_enable)); + } + } + } + + return rc; +} + +static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + uint64_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + 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", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "get src buf address fail mem_handle 0x%x", + io_cfg[i].mem_handle[j]); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_ISP, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_ISP, + "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 + + (unsigned int)src_buf_size, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + } + } +} + +static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *) + hw_cmd_args->ctxt_to_hw_map; + struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Fatal: Invalid context is used"); + return -EPERM; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_INTERNAL: + if (!hw_cmd_args->u.internal_args) { + CAM_ERR(CAM_ISP, "Invalid cmd arguments"); + return -EINVAL; + } + + isp_hw_cmd_args = (struct cam_isp_hw_cmd_args *) + hw_cmd_args->u.internal_args; + + switch (isp_hw_cmd_args->cmd_type) { + case CAM_ISP_HW_MGR_CMD_PAUSE_HW: + cam_ife_mgr_pause_hw(ctx); + break; + case CAM_ISP_HW_MGR_CMD_RESUME_HW: + cam_ife_mgr_resume_hw(ctx); + break; + case CAM_ISP_HW_MGR_CMD_SOF_DEBUG: + 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); + rc = -EINVAL; + break; + } + break; + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_ife_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->mgr_common.img_iommu_hdl, + hw_mgr->mgr_common.img_iommu_hdl_secure, + hw_cmd_args->u.pf_args.buf_info, + hw_cmd_args->u.pf_args.mem_found); + break; + default: + CAM_ERR(CAM_ISP, "Invalid cmd"); + } + + return rc; +} + +static int cam_ife_mgr_cmd_get_sof_timestamp( + struct cam_ife_hw_mgr_ctx *ife_ctx, + uint64_t *time_stamp, + uint64_t *boot_time_stamp) +{ + int rc = -EINVAL; + uint32_t i; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_csid_get_time_stamp_args csid_get_time; + + 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]) + 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( + hw_intf->hw_priv, + CAM_IFE_CSID_CMD_GET_TIME_STAMP, + &csid_get_time, + sizeof( + struct cam_csid_get_time_stamp_args)); + if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { + *time_stamp = + csid_get_time.time_stamp_val; + *boot_time_stamp = + csid_get_time.boot_timestamp; + } + } + } + } + + if (rc) + CAM_ERR_RATE_LIMIT(CAM_ISP, "Getting sof time stamp failed"); + + return rc; +} + +static int cam_ife_mgr_process_recovery_cb(void *priv, void *data) +{ + int32_t rc = 0; + struct cam_hw_event_recovery_data *recovery_data = data; + struct cam_hw_start_args start_args; + struct cam_hw_stop_args stop_args; + struct cam_ife_hw_mgr *ife_hw_mgr = priv; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t i = 0; + + uint32_t error_type = recovery_data->error_type; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + + /* Here recovery is performed */ + CAM_DBG(CAM_ISP, "ErrorType = %d", error_type); + + switch (error_type) { + case CAM_ISP_HW_ERROR_OVERFLOW: + case CAM_ISP_HW_ERROR_BUSIF_OVERFLOW: + if (!recovery_data->affected_ctx[0]) { + CAM_ERR(CAM_ISP, + "No context is affected but recovery called"); + kfree(recovery_data); + return 0; + } + /* stop resources here */ + CAM_DBG(CAM_ISP, "STOP: Number of affected context: %d", + recovery_data->no_of_context); + for (i = 0; i < recovery_data->no_of_context; i++) { + stop_args.ctxt_to_hw_map = + recovery_data->affected_ctx[i]; + rc = cam_ife_mgr_stop_hw_in_overflow(&stop_args); + if (rc) { + CAM_ERR(CAM_ISP, "CTX stop failed(%d)", rc); + return rc; + } + } + + CAM_DBG(CAM_ISP, "RESET: CSID PATH"); + for (i = 0; i < recovery_data->no_of_context; i++) { + ctx = recovery_data->affected_ctx[i]; + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, + list) { + rc = cam_ife_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed RESET (%d)", + hw_mgr_res->res_id); + return rc; + } + } + } + + CAM_DBG(CAM_ISP, "RESET: Calling VFE reset"); + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (recovery_data->affected_core[i]) + cam_ife_mgr_reset_vfe_hw(ife_hw_mgr, i); + } + + CAM_DBG(CAM_ISP, "START: Number of affected context: %d", + recovery_data->no_of_context); + + for (i = 0; i < recovery_data->no_of_context; i++) { + ctx = recovery_data->affected_ctx[i]; + start_args.ctxt_to_hw_map = ctx; + + atomic_set(&ctx->overflow_pending, 0); + + rc = cam_ife_mgr_restart_hw(&start_args); + if (rc) { + CAM_ERR(CAM_ISP, "CTX start failed(%d)", rc); + return rc; + } + CAM_DBG(CAM_ISP, "Started resources rc (%d)", rc); + } + CAM_DBG(CAM_ISP, "Recovery Done rc (%d)", rc); + + break; + + case CAM_ISP_HW_ERROR_P2I_ERROR: + break; + + case CAM_ISP_HW_ERROR_VIOLATION: + break; + + default: + CAM_ERR(CAM_ISP, "Invalid Error"); + } + CAM_DBG(CAM_ISP, "Exit: ErrorType = %d", error_type); + + kfree(recovery_data); + return rc; +} + +static int cam_ife_hw_mgr_do_error_recovery( + struct cam_hw_event_recovery_data *ife_mgr_recovery_data) +{ + int32_t rc = 0; + struct crm_workq_task *task = NULL; + struct cam_hw_event_recovery_data *recovery_data = NULL; + + recovery_data = kzalloc(sizeof(struct cam_hw_event_recovery_data), + GFP_ATOMIC); + if (!recovery_data) + return -ENOMEM; + + memcpy(recovery_data, ife_mgr_recovery_data, + sizeof(struct cam_hw_event_recovery_data)); + + CAM_DBG(CAM_ISP, "Enter: error_type (%d)", recovery_data->error_type); + + task = cam_req_mgr_workq_get_task(g_ife_hw_mgr.workq); + if (!task) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No empty task frame"); + kfree(recovery_data); + return -ENOMEM; + } + + task->process_cb = &cam_ife_mgr_process_recovery_cb; + task->payload = recovery_data; + rc = cam_req_mgr_workq_enqueue_task(task, + recovery_data->affected_ctx[0]->hw_mgr, + CRM_TASK_PRIORITY_0); + + return rc; +} + +/* + * This function checks if any of the valid entry in affected_core[] + * is associated with this context. if YES + * a. It fills the other cores associated with this context.in + * affected_core[] + * b. Return true + */ +static bool cam_ife_hw_mgr_is_ctx_affected( + struct cam_ife_hw_mgr_ctx *ife_hwr_mgr_ctx, + uint32_t *affected_core, + uint32_t size) +{ + + bool rc = false; + uint32_t i = 0, j = 0; + uint32_t max_idx = ife_hwr_mgr_ctx->num_base; + uint32_t ctx_affected_core_idx[CAM_IFE_HW_NUM_MAX] = {0}; + + CAM_DBG(CAM_ISP, "Enter:max_idx = %d", max_idx); + + if ((max_idx >= CAM_IFE_HW_NUM_MAX) || (size > CAM_IFE_HW_NUM_MAX)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "invalid parameter = %d", max_idx); + return rc; + } + + for (i = 0; i < max_idx; i++) { + if (affected_core[ife_hwr_mgr_ctx->base[i].idx]) + rc = true; + else { + ctx_affected_core_idx[j] = ife_hwr_mgr_ctx->base[i].idx; + j = j + 1; + } + } + + if (rc) { + while (j) { + if (affected_core[ctx_affected_core_idx[j-1]] != 1) + affected_core[ctx_affected_core_idx[j-1]] = 1; + j = j - 1; + } + } + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +/* + * For any dual VFE context, if non-affected VFE is also serving + * another context, then that context should also be notified with fatal error + * So Loop through each context and - + * a. match core_idx + * b. Notify CTX with fatal error + */ +static int cam_ife_hw_mgr_find_affected_ctx( + struct cam_isp_hw_error_event_data *error_event_data, + uint32_t curr_core_idx, + struct cam_hw_event_recovery_data *recovery_data) +{ + uint32_t affected_core[CAM_IFE_HW_NUM_MAX] = {0}; + struct cam_ife_hw_mgr_ctx *ife_hwr_mgr_ctx = NULL; + cam_hw_event_cb_func notify_err_cb; + struct cam_ife_hw_mgr *ife_hwr_mgr = NULL; + enum cam_isp_hw_event_type event_type = CAM_ISP_HW_EVENT_ERROR; + uint32_t i = 0; + + if (!recovery_data) { + CAM_ERR(CAM_ISP, "recovery_data parameter is NULL"); + return -EINVAL; + } + + recovery_data->no_of_context = 0; + affected_core[curr_core_idx] = 1; + ife_hwr_mgr = &g_ife_hw_mgr; + + list_for_each_entry(ife_hwr_mgr_ctx, + &ife_hwr_mgr->used_ctx_list, list) { + /* + * Check if current core_idx matches the HW associated + * with this context + */ + if (!cam_ife_hw_mgr_is_ctx_affected(ife_hwr_mgr_ctx, + affected_core, CAM_IFE_HW_NUM_MAX)) + continue; + + atomic_set(&ife_hwr_mgr_ctx->overflow_pending, 1); + notify_err_cb = ife_hwr_mgr_ctx->common.event_cb[event_type]; + + /* Add affected_context in list of recovery data */ + CAM_DBG(CAM_ISP, "Add affected ctx %d to list", + ife_hwr_mgr_ctx->ctx_index); + if (recovery_data->no_of_context < CAM_CTX_MAX) + recovery_data->affected_ctx[ + recovery_data->no_of_context++] = + ife_hwr_mgr_ctx; + + /* + * In the call back function corresponding ISP context + * will update CRM about fatal Error + */ + notify_err_cb(ife_hwr_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_ERROR, error_event_data); + } + + /* fill the affected_core in recovery data */ + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + recovery_data->affected_core[i] = affected_core[i]; + CAM_DBG(CAM_ISP, "Vfe core %d is affected (%d)", + i, recovery_data->affected_core[i]); + } + + return 0; +} + +static int cam_ife_hw_mgr_handle_hw_err( + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + uint32_t core_idx; + struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_hw_event_recovery_data recovery_data = {0}; + int rc = -EINVAL; + + if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) + error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; + else if (event_info->res_type == CAM_ISP_RESOURCE_VFE_IN) + error_event_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; + else if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) + error_event_data.error_type = CAM_ISP_HW_ERROR_BUSIF_OVERFLOW; + + core_idx = event_info->hw_idx; + + if (g_ife_hw_mgr.debug_cfg.enable_recovery) + error_event_data.recovery_enabled = true; + else + error_event_data.recovery_enabled = false; + + rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, + core_idx, &recovery_data); + + if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) + return rc; + + if (g_ife_hw_mgr.debug_cfg.enable_recovery) { + CAM_DBG(CAM_ISP, "IFE Mgr recovery is enabled"); + + /* Trigger for recovery */ + if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) + recovery_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; + else + recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; + cam_ife_hw_mgr_do_error_recovery(&recovery_data); + } else { + CAM_DBG(CAM_ISP, "recovery is not enabled"); + rc = 0; + } + + return rc; +} + +static int cam_ife_hw_mgr_handle_hw_rup( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; + cam_hw_event_cb_func ife_hwr_irq_rup_cb; + struct cam_isp_hw_reg_update_event_data rup_event_data; + + ife_hwr_irq_rup_cb = + ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_REG_UPDATE]; + + switch (event_info->res_id) { + case CAM_ISP_HW_VFE_IN_CAMIF: + if (ife_hw_mgr_ctx->is_dual) + if (event_info->hw_idx != 1) + break; + + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + ife_hwr_irq_rup_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + break; + + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + if (!ife_hw_mgr_ctx->is_rdi_only_context) + break; + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + ife_hwr_irq_rup_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + break; + + case CAM_ISP_HW_VFE_IN_PDLIB: + case CAM_ISP_HW_VFE_IN_LCR: + break; + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "RUP done for VFE:%d source %d", event_info->hw_idx, + event_info->res_id); + + return 0; +} + +static int cam_ife_hw_mgr_check_irq_for_dual_vfe( + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx, + uint32_t hw_event_type) +{ + int32_t rc = -1; + uint32_t *event_cnt = NULL; + uint32_t core_idx0 = 0; + uint32_t core_idx1 = 1; + + if (!ife_hw_mgr_ctx->is_dual) + return 0; + + switch (hw_event_type) { + case CAM_ISP_HW_EVENT_SOF: + event_cnt = ife_hw_mgr_ctx->sof_cnt; + break; + case CAM_ISP_HW_EVENT_EPOCH: + event_cnt = ife_hw_mgr_ctx->epoch_cnt; + break; + case CAM_ISP_HW_EVENT_EOF: + event_cnt = ife_hw_mgr_ctx->eof_cnt; + break; + default: + return 0; + } + + if (event_cnt[core_idx0] == event_cnt[core_idx1]) { + + event_cnt[core_idx0] = 0; + event_cnt[core_idx1] = 0; + + rc = 0; + return rc; + } + + if ((event_cnt[core_idx0] && + (event_cnt[core_idx0] - event_cnt[core_idx1] > 1)) || + (event_cnt[core_idx1] && + (event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) { + + CAM_ERR_RATE_LIMIT(CAM_ISP, + "One of the VFE could not generate hw event %d", + hw_event_type); + rc = -1; + return rc; + } + + CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d", + hw_event_type); + + return rc; +} + +static int cam_ife_hw_mgr_handle_hw_epoch( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; + cam_hw_event_cb_func ife_hw_irq_epoch_cb; + struct cam_isp_hw_epoch_event_data epoch_done_event_data; + int rc = 0; + + ife_hw_irq_epoch_cb = + ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EPOCH]; + + switch (event_info->res_id) { + case CAM_ISP_HW_VFE_IN_CAMIF: + ife_hw_mgr_ctx->epoch_cnt[event_info->hw_idx]++; + rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, + CAM_ISP_HW_EVENT_EPOCH); + if (!rc) { + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); + } + break; + + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + case CAM_ISP_HW_VFE_IN_PDLIB: + case CAM_ISP_HW_VFE_IN_LCR: + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "Epoch for VFE:%d source %d", event_info->hw_idx, + event_info->res_id); + + return 0; +} + +static int cam_ife_hw_mgr_handle_hw_sof( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; + cam_hw_event_cb_func ife_hw_irq_sof_cb; + struct cam_isp_hw_sof_event_data sof_done_event_data; + int rc = 0; + + ife_hw_irq_sof_cb = + ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF]; + + switch (event_info->res_id) { + case CAM_ISP_HW_VFE_IN_CAMIF: + case CAM_ISP_HW_VFE_IN_RD: + ife_hw_mgr_ctx->sof_cnt[event_info->hw_idx]++; + rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, + CAM_ISP_HW_EVENT_SOF); + if (!rc) { + cam_ife_mgr_cmd_get_sof_timestamp(ife_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); + + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + + ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + } + break; + + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + if (!ife_hw_mgr_ctx->is_rdi_only_context) + break; + cam_ife_mgr_cmd_get_sof_timestamp(ife_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + break; + + case CAM_ISP_HW_VFE_IN_PDLIB: + case CAM_ISP_HW_VFE_IN_LCR: + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "SOF for VFE:%d source %d", event_info->hw_idx, + event_info->res_id); + + return 0; +} + +static int cam_ife_hw_mgr_handle_hw_eof( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; + cam_hw_event_cb_func ife_hw_irq_eof_cb; + struct cam_isp_hw_eof_event_data eof_done_event_data; + int rc = 0; + + ife_hw_irq_eof_cb = + ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EOF]; + + switch (event_info->res_id) { + case CAM_ISP_HW_VFE_IN_CAMIF: + ife_hw_mgr_ctx->eof_cnt[event_info->hw_idx]++; + rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, + CAM_ISP_HW_EVENT_EOF); + if (!rc) { + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + ife_hw_irq_eof_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + } + break; + + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + case CAM_ISP_HW_VFE_IN_PDLIB: + case CAM_ISP_HW_VFE_IN_LCR: + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "EOF for VFE:%d source %d", event_info->hw_idx, + event_info->res_id); + + return 0; +} + +static int cam_ife_hw_mgr_handle_hw_buf_done( + void *ctx, + void *evt_info) +{ + cam_hw_event_cb_func ife_hwr_irq_wm_done_cb; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; + struct cam_isp_hw_done_event_data buf_done_event_data = {0}; + struct cam_isp_hw_event_info *event_info = evt_info; + + ife_hwr_irq_wm_done_cb = + ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_DONE]; + + buf_done_event_data.num_handles = 1; + buf_done_event_data.resource_handle[0] = event_info->res_id; + + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + return 0; + + if (buf_done_event_data.num_handles > 0 && ife_hwr_irq_wm_done_cb) { + CAM_DBG(CAM_ISP, "Notify ISP context"); + ife_hwr_irq_wm_done_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); + } + + CAM_DBG(CAM_ISP, "Buf done for VFE:%d out_res->res_id: 0x%x", + event_info->hw_idx, event_info->res_id); + + return 0; +} + +static int cam_ife_hw_mgr_event_handler( + void *priv, + uint32_t evt_id, + void *evt_info) +{ + int rc = 0; + + if (!evt_info) + return -EINVAL; + + if (!priv) + if (evt_id != CAM_ISP_HW_EVENT_ERROR) + return -EINVAL; + + CAM_DBG(CAM_ISP, "Event ID 0x%x", evt_id); + + switch (evt_id) { + case CAM_ISP_HW_EVENT_SOF: + rc = cam_ife_hw_mgr_handle_hw_sof(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_REG_UPDATE: + rc = cam_ife_hw_mgr_handle_hw_rup(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_EPOCH: + rc = cam_ife_hw_mgr_handle_hw_epoch(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_EOF: + rc = cam_ife_hw_mgr_handle_hw_eof(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_DONE: + rc = cam_ife_hw_mgr_handle_hw_buf_done(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_ERROR: + rc = cam_ife_hw_mgr_handle_hw_err(evt_info); + break; + + default: + CAM_ERR(CAM_ISP, "Invalid event ID %d", evt_id); + break; + } + + return rc; +} + +static int cam_ife_hw_mgr_sort_dev_with_caps( + struct cam_ife_hw_mgr *ife_hw_mgr) +{ + int i; + + /* get caps for csid devices */ + for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { + if (!ife_hw_mgr->csid_devices[i]) + continue; + if (ife_hw_mgr->csid_devices[i]->hw_ops.get_hw_caps) { + ife_hw_mgr->csid_devices[i]->hw_ops.get_hw_caps( + ife_hw_mgr->csid_devices[i]->hw_priv, + &ife_hw_mgr->ife_csid_dev_caps[i], + sizeof(ife_hw_mgr->ife_csid_dev_caps[i])); + } + } + + /* get caps for ife devices */ + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (!ife_hw_mgr->ife_devices[i]) + continue; + if (ife_hw_mgr->ife_devices[i]->hw_ops.get_hw_caps) { + ife_hw_mgr->ife_devices[i]->hw_ops.get_hw_caps( + ife_hw_mgr->ife_devices[i]->hw_priv, + &ife_hw_mgr->ife_dev_caps[i], + sizeof(ife_hw_mgr->ife_dev_caps[i])); + } + } + + return 0; +} + +static int cam_ife_set_csid_debug(void *data, u64 val) +{ + g_ife_hw_mgr.debug_cfg.csid_debug = val; + CAM_DBG(CAM_ISP, "Set CSID Debug value :%lld", val); + return 0; +} + +static int cam_ife_get_csid_debug(void *data, u64 *val) +{ + *val = g_ife_hw_mgr.debug_cfg.csid_debug; + CAM_DBG(CAM_ISP, "Get CSID Debug value :%lld", + g_ife_hw_mgr.debug_cfg.csid_debug); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_ife_csid_debug, + cam_ife_get_csid_debug, + cam_ife_set_csid_debug, "%16llu"); + +static int cam_ife_set_camif_debug(void *data, u64 val) +{ + g_ife_hw_mgr.debug_cfg.camif_debug = val; + CAM_DBG(CAM_ISP, + "Set camif enable_diag_sensor_status value :%lld", val); + return 0; +} + +static int cam_ife_get_camif_debug(void *data, u64 *val) +{ + *val = g_ife_hw_mgr.debug_cfg.camif_debug; + CAM_DBG(CAM_ISP, + "Set camif enable_diag_sensor_status value :%lld", + g_ife_hw_mgr.debug_cfg.csid_debug); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug, + cam_ife_get_camif_debug, + cam_ife_set_camif_debug, "%16llu"); + +static int cam_ife_hw_mgr_debug_register(void) +{ + g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", + NULL); + + if (!g_ife_hw_mgr.debug_cfg.dentry) { + CAM_ERR(CAM_ISP, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_file("ife_csid_debug", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, + &cam_ife_csid_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_ife_csid_debug"); + goto err; + } + + if (!debugfs_create_u32("enable_recovery", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, + &g_ife_hw_mgr.debug_cfg.enable_recovery)) { + CAM_ERR(CAM_ISP, "failed to create enable_recovery"); + goto err; + } + + if (!debugfs_create_file("ife_camif_debug", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, + &cam_ife_camif_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug"); + goto err; + } + g_ife_hw_mgr.debug_cfg.enable_recovery = 0; + + return 0; + +err: + debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); + return -ENOMEM; +} + +int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) +{ + int rc = -EFAULT; + int i, j; + struct cam_iommu_handle cdm_handles; + struct cam_ife_hw_mgr_ctx *ctx_pool; + struct cam_ife_hw_mgr_res *res_list_ife_out; + + CAM_DBG(CAM_ISP, "Enter"); + + memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr)); + + mutex_init(&g_ife_hw_mgr.ctx_mutex); + + if (CAM_IFE_HW_NUM_MAX != CAM_IFE_CSID_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, "CSID num is different then IFE num"); + return -EINVAL; + } + + /* fill ife hw intf information */ + for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + rc = cam_vfe_hw_init(&g_ife_hw_mgr.ife_devices[i], i); + if (!rc) { + struct cam_hw_info *vfe_hw = + (struct cam_hw_info *) + g_ife_hw_mgr.ife_devices[i]->hw_priv; + struct cam_hw_soc_info *soc_info = &vfe_hw->soc_info; + + j++; + + g_ife_hw_mgr.cdm_reg_map[i] = &soc_info->reg_map[0]; + CAM_DBG(CAM_ISP, + "reg_map: mem base = %pK cam_base = 0x%llx", + (void __iomem *)soc_info->reg_map[0].mem_base, + (uint64_t) soc_info->reg_map[0].mem_cam_base); + } else { + g_ife_hw_mgr.cdm_reg_map[i] = NULL; + } + } + if (j == 0) { + CAM_ERR(CAM_ISP, "no valid IFE HW"); + return -EINVAL; + } + + /* fill csid hw intf information */ + for (i = 0, j = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { + rc = cam_ife_csid_hw_init(&g_ife_hw_mgr.csid_devices[i], i); + if (!rc) + j++; + } + if (!j) { + CAM_ERR(CAM_ISP, "no valid IFE CSID HW"); + return -EINVAL; + } + + cam_ife_hw_mgr_sort_dev_with_caps(&g_ife_hw_mgr); + + /* setup ife context list */ + INIT_LIST_HEAD(&g_ife_hw_mgr.free_ctx_list); + INIT_LIST_HEAD(&g_ife_hw_mgr.used_ctx_list); + + /* + * for now, we only support one iommu handle. later + * we will need to setup more iommu handle for other + * use cases. + * Also, we have to release them once we have the + * deinit support + */ + if (cam_smmu_get_handle("ife", + &g_ife_hw_mgr.mgr_common.img_iommu_hdl)) { + CAM_ERR(CAM_ISP, "Can not get iommu handle"); + return -EINVAL; + } + + if (cam_smmu_get_handle("cam-secure", + &g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure)) { + CAM_ERR(CAM_ISP, "Failed to get secure iommu handle"); + goto secure_fail; + } + + CAM_DBG(CAM_ISP, "iommu_handles: non-secure[0x%x], secure[0x%x]", + g_ife_hw_mgr.mgr_common.img_iommu_hdl, + g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure); + + if (!cam_cdm_get_iommu_handle("ife", &cdm_handles)) { + CAM_DBG(CAM_ISP, "Successfully acquired the CDM iommu handles"); + g_ife_hw_mgr.mgr_common.cmd_iommu_hdl = cdm_handles.non_secure; + g_ife_hw_mgr.mgr_common.cmd_iommu_hdl_secure = + cdm_handles.secure; + } else { + CAM_DBG(CAM_ISP, "Failed to acquire the CDM iommu handles"); + g_ife_hw_mgr.mgr_common.cmd_iommu_hdl = -1; + g_ife_hw_mgr.mgr_common.cmd_iommu_hdl_secure = -1; + } + + atomic_set(&g_ife_hw_mgr.active_ctx_cnt, 0); + for (i = 0; i < CAM_CTX_MAX; i++) { + memset(&g_ife_hw_mgr.ctx_pool[i], 0, + sizeof(g_ife_hw_mgr.ctx_pool[i])); + INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].list); + + INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_in.list); + 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]; + INIT_LIST_HEAD(&res_list_ife_out->list); + } + + /* init context pool */ + INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].free_res_list); + for (j = 0; j < CAM_IFE_HW_RES_POOL_MAX; j++) { + INIT_LIST_HEAD( + &g_ife_hw_mgr.ctx_pool[i].res_pool[j].list); + list_add_tail( + &g_ife_hw_mgr.ctx_pool[i].res_pool[j].list, + &g_ife_hw_mgr.ctx_pool[i].free_res_list); + } + + g_ife_hw_mgr.ctx_pool[i].cdm_cmd = + kzalloc(((sizeof(struct cam_cdm_bl_request)) + + ((CAM_IFE_HW_ENTRIES_MAX - 1) * + sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); + if (!g_ife_hw_mgr.ctx_pool[i].cdm_cmd) { + rc = -ENOMEM; + CAM_ERR(CAM_ISP, "Allocation Failed for cdm command"); + goto end; + } + + g_ife_hw_mgr.ctx_pool[i].ctx_index = i; + g_ife_hw_mgr.ctx_pool[i].hw_mgr = &g_ife_hw_mgr; + + cam_tasklet_init(&g_ife_hw_mgr.mgr_common.tasklet_pool[i], + &g_ife_hw_mgr.ctx_pool[i], i); + g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = + g_ife_hw_mgr.mgr_common.tasklet_pool[i]; + + + init_completion(&g_ife_hw_mgr.ctx_pool[i].config_done_complete); + list_add_tail(&g_ife_hw_mgr.ctx_pool[i].list, + &g_ife_hw_mgr.free_ctx_list); + } + + /* Create Worker for ife_hw_mgr with 10 tasks */ + rc = cam_req_mgr_workq_create("cam_ife_worker", 10, + &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Unable to create worker"); + goto end; + } + + /* fill return structure */ + hw_mgr_intf->hw_mgr_priv = &g_ife_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_ife_mgr_get_hw_caps; + hw_mgr_intf->hw_acquire = cam_ife_mgr_acquire; + hw_mgr_intf->hw_start = cam_ife_mgr_start_hw; + hw_mgr_intf->hw_stop = cam_ife_mgr_stop_hw; + hw_mgr_intf->hw_read = cam_ife_mgr_read; + hw_mgr_intf->hw_write = cam_ife_mgr_write; + hw_mgr_intf->hw_release = cam_ife_mgr_release_hw; + hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update; + hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; + hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; + + if (iommu_hdl) + *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; + + cam_ife_hw_mgr_debug_register(); + CAM_DBG(CAM_ISP, "Exit"); + + return 0; +end: + if (rc) { + for (i = 0; i < CAM_CTX_MAX; i++) { + cam_tasklet_deinit( + &g_ife_hw_mgr.mgr_common.tasklet_pool[i]); + kfree(g_ife_hw_mgr.ctx_pool[i].cdm_cmd); + g_ife_hw_mgr.ctx_pool[i].cdm_cmd = NULL; + g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = NULL; + } + } + cam_smmu_destroy_handle( + g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure); + g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure = -1; +secure_fail: + cam_smmu_destroy_handle(g_ife_hw_mgr.mgr_common.img_iommu_hdl); + g_ife_hw_mgr.mgr_common.img_iommu_hdl = -1; + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h new file mode 100644 index 000000000000..16143b014ebf --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_HW_MGR_H_ +#define _CAM_IFE_HW_MGR_H_ + +#include +#include "cam_isp_hw_mgr.h" +#include "cam_vfe_hw_intf.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_tasklet_util.h" + +/* enum cam_ife_hw_mgr_res_type - manager resource node type */ +enum cam_ife_hw_mgr_res_type { + CAM_IFE_HW_MGR_RES_UNINIT, + CAM_IFE_HW_MGR_RES_ROOT, + 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, +}; + +/* IFE resource constants */ +#define CAM_IFE_HW_IN_RES_MAX (CAM_ISP_IFE_IN_RES_MAX & 0xFF) +#define CAM_IFE_HW_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_MAX & 0xFF) +#define CAM_IFE_HW_RES_POOL_MAX 64 + +/** + * struct cam_vfe_hw_mgr_res- HW resources for the VFE manager + * + * @list: used by the resource list + * @res_type: IFE manager resource type + * @res_id: resource id based on the resource type for root or + * leaf resource, it matches the KMD interface port id. + * For branch resrouce, it is defined by the ISP HW + * layer + * @hw_res: hw layer resource array. For single VFE, only one VFE + * hw resrouce will be acquired. For dual VFE, two hw + * resources from different VFE HW device will be + * acquired + * @parent: point to the parent resource node. + * @children: point to the children resource nodes + * @child_num: numbe of the child resource node. + * @is_secure informs whether the resource is in secure mode or not + * + */ +struct cam_ife_hw_mgr_res { + struct list_head list; + enum cam_ife_hw_mgr_res_type res_type; + uint32_t res_id; + uint32_t is_dual_vfe; + struct cam_isp_resource_node *hw_res[CAM_ISP_HW_SPLIT_MAX]; + + /* graph */ + struct cam_ife_hw_mgr_res *parent; + struct cam_ife_hw_mgr_res *child[CAM_IFE_HW_OUT_RES_MAX]; + uint32_t num_children; + uint32_t is_secure; +}; + + +/** + * struct ctx_base_info - Base hardware information for the context + * + * @idx: Base resource index + * @split_id: Split info for the base resource + * + */ +struct ctx_base_info { + uint32_t idx; + enum cam_isp_hw_split_id split_id; +}; + +/** + * struct cam_ife_hw_mgr_debug - contain the debug information + * + * @dentry: Debugfs entry + * @csid_debug: csid debug information + * @enable_recovery: enable recovery + * @enable_diag_sensor_status: enable sensor diagnosis status + * @enable_req_dump: Enable request dump on HW errors + * + */ +struct cam_ife_hw_mgr_debug { + struct dentry *dentry; + uint64_t csid_debug; + uint32_t enable_recovery; + uint32_t camif_debug; + uint32_t enable_req_dump; +}; + +/** + * struct cam_vfe_hw_mgr_ctx - IFE HW manager Context object + * + * @list: used by the ctx list. + * @common: common acquired context data + * @ctx_index: acquired context id. + * @hw_mgr: IFE hw mgr which owns this context + * @ctx_in_use: flag to tell whether context is active + * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be + * 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 + * @irq_status0_mask: irq_status0_mask for the context + * @irq_status1_mask: irq_status1_mask for the context + * @base device base index array contain the all IFE HW + * instance associated with this context. + * @num_base number of valid base data in the base array + * @cdm_handle cdm hw acquire handle + * @cdm_ops cdm util operation pointer for building + * cdm commands + * @cdm_cmd cdm base and length request pointer + * @sof_cnt sof count value per core, used for dual VFE + * @epoch_cnt epoch count value per core, used for dual VFE + * @eof_cnt eof count value per core, used for dual VFE + * @overflow_pending flat to specify the overflow is pending for the + * context + * @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 + * @is_dual indicate whether context is in dual VFE mode + */ +struct cam_ife_hw_mgr_ctx { + struct list_head list; + struct cam_isp_hw_mgr_ctx common; + + uint32_t ctx_index; + struct cam_ife_hw_mgr *hw_mgr; + uint32_t ctx_in_use; + + struct cam_ife_hw_mgr_res res_list_ife_in; + 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]; + + struct list_head free_res_list; + struct cam_ife_hw_mgr_res res_pool[CAM_IFE_HW_RES_POOL_MAX]; + + uint32_t irq_status0_mask[CAM_IFE_HW_NUM_MAX]; + uint32_t irq_status1_mask[CAM_IFE_HW_NUM_MAX]; + struct ctx_base_info base[CAM_IFE_HW_NUM_MAX]; + uint32_t num_base; + uint32_t cdm_handle; + struct cam_cdm_utils_ops *cdm_ops; + struct cam_cdm_bl_request *cdm_cmd; + + uint32_t sof_cnt[CAM_IFE_HW_NUM_MAX]; + uint32_t epoch_cnt[CAM_IFE_HW_NUM_MAX]; + uint32_t eof_cnt[CAM_IFE_HW_NUM_MAX]; + atomic_t overflow_pending; + uint32_t is_rdi_only_context; + struct completion config_done_complete; + bool init_done; + bool is_fe_enable; + bool is_dual; +}; + +/** + * struct cam_ife_hw_mgr - IFE HW Manager + * + * @mgr_common: common data for all HW managers + * @csid_devices; csid device instances array. This will be filled by + * HW manager during the initialization. + * @ife_devices: IFE device instances array. This will be filled by + * HW layer during initialization + * @ctx_mutex: mutex for the hw context pool + * @free_ctx_list: free hw context list + * @used_ctx_list: used hw context list + * @ctx_pool: context storage + * @ife_csid_dev_caps csid device capability stored per core + * @ife_dev_caps ife device capability per core + * @work q work queue for IFE hw manager + * @debug_cfg debug configuration + */ +struct cam_ife_hw_mgr { + struct cam_isp_hw_mgr mgr_common; + struct cam_hw_intf *csid_devices[CAM_IFE_CSID_HW_NUM_MAX]; + struct cam_hw_intf *ife_devices[CAM_IFE_HW_NUM_MAX]; + struct cam_soc_reg_map *cdm_reg_map[CAM_IFE_HW_NUM_MAX]; + + struct mutex ctx_mutex; + atomic_t active_ctx_cnt; + struct list_head free_ctx_list; + struct list_head used_ctx_list; + struct cam_ife_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; + + struct cam_ife_csid_hw_caps ife_csid_dev_caps[ + CAM_IFE_CSID_HW_NUM_MAX]; + struct cam_vfe_hw_get_hw_cap ife_dev_caps[CAM_IFE_HW_NUM_MAX]; + struct cam_req_mgr_core_workq *workq; + struct cam_ife_hw_mgr_debug debug_cfg; +}; + +/** + * cam_ife_hw_mgr_init() + * + * @brief: Initialize the IFE hardware manger. This is the + * etnry functinon for the IFE HW manager. + * + * @hw_mgr_intf: IFE hardware manager object returned + * @iommu_hdl: Iommu handle to be returned + * + */ +int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); + +#endif /* _CAM_IFE_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c new file mode 100644 index 000000000000..b1567d6b9cd8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_isp_hw_mgr_intf.h" +#include "cam_ife_hw_mgr.h" +#include "cam_debug_util.h" + + +int cam_isp_hw_mgr_init(struct device_node *of_node, + struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl) +{ + int rc = 0; + const char *compat_str = NULL; + + rc = of_property_read_string_index(of_node, "arch-compat", 0, + (const char **)&compat_str); + + if (strnstr(compat_str, "ife", strlen(compat_str))) + rc = cam_ife_hw_mgr_init(hw_mgr, iommu_hdl); + else { + CAM_ERR(CAM_ISP, "Invalid ISP hw type"); + rc = -EINVAL; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h new file mode 100644 index 000000000000..69e24bcc8625 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ISP_HW_MGR_H_ +#define _CAM_ISP_HW_MGR_H_ + +#include "cam_isp_hw_mgr_intf.h" +#include "cam_tasklet_util.h" + +#define CAM_ISP_HW_NUM_MAX 7 + +/** + * struct cam_isp_hw_mgr_ctx - common acquired context for managers + * + * @takslet_info: assciated tasklet + * @event_cb: call back interface to ISP context. Set during + * acquire device + * @cb_priv: first argument for the call back function + * set during acquire device + * + */ +struct cam_isp_hw_mgr_ctx { + void *tasklet_info; + cam_hw_event_cb_func event_cb[CAM_ISP_HW_EVENT_MAX]; + void *cb_priv; +}; + +/** + * struct cam_isp_hw_mgr - ISP HW Manager common object + * + * @tasklet_pool: Tasklet pool + * @img_iommu_hdl: iommu memory handle for regular image buffer + * @img_iommu_hdl_secure: iommu memory handle for secure image buffer + * @cmd_iommu_hdl: iommu memory handle for regular command buffer + * @cmd_iommu_hdl: iommu memory handle for secure command buffer + * @scratch_buf_range: scratch buffer range (not for IFE) + * @scratch_buf_addr: scratch buffer address (not for IFE) + * + */ +struct cam_isp_hw_mgr { + void *tasklet_pool[CAM_CTX_MAX]; + int img_iommu_hdl; + int img_iommu_hdl_secure; + int cmd_iommu_hdl; + int cmd_iommu_hdl_secure; + uint32_t scratch_buf_range; + dma_addr_t scratch_buf_addr; +}; + +/** + * struct cam_hw_event_recovery_data - Payload for the recovery procedure + * + * @error_type: Error type that causes the recovery + * @affected_core: Array of the hardware cores that are affected + * @affected_ctx: Array of the hardware contexts that are affected + * @no_of_context: Actual number of the affected context + * + */ +struct cam_hw_event_recovery_data { + uint32_t error_type; + uint32_t affected_core[CAM_ISP_HW_NUM_MAX]; + struct cam_ife_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX]; + uint32_t no_of_context; +}; +#endif /* _CAM_ISP_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile b/drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile new file mode 100644 index 000000000000..ccdfc05f103d --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_tasklet_util.o cam_isp_packet_parser.o +obj-$(CONFIG_SPECTRA_CAMERA) += irq_controller/ diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c new file mode 100644 index 000000000000..be098a619aaf --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -0,0 +1,916 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "cam_mem_mgr.h" +#include "cam_isp_hw.h" +#include "cam_vfe_hw_intf.h" +#include "cam_isp_packet_parser.h" +#include "cam_debug_util.h" + +int cam_isp_add_change_base( + 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) +{ + int rc = -EINVAL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *res; + struct cam_isp_hw_get_cmd_update get_base; + struct cam_hw_update_entry *hw_entry; + uint32_t num_ent, i; + + hw_entry = prepare->hw_update_entries; + num_ent = prepare->num_hw_update_entries; + + /* Max one hw entries required for each base */ + if (num_ent + 1 >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); + return -EINVAL; + } + + list_for_each_entry(hw_mgr_res, res_list_isp_src, list) { + if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) + continue; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + res = hw_mgr_res->hw_res[i]; + if (res->hw_intf->hw_idx != base_idx) + continue; + + get_base.res = res; + get_base.cmd_type = CAM_ISP_HW_CMD_GET_CHANGE_BASE; + get_base.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4; + get_base.cmd.size = kmd_buf_info->size - + kmd_buf_info->used_bytes; + + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_CHANGE_BASE, &get_base, + sizeof(struct cam_isp_hw_get_cmd_update)); + if (rc) + return rc; + + hw_entry[num_ent].handle = kmd_buf_info->handle; + hw_entry[num_ent].len = get_base.cmd.used_bytes; + hw_entry[num_ent].offset = kmd_buf_info->offset; + CAM_DBG(CAM_ISP, + "num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + + kmd_buf_info->used_bytes += get_base.cmd.used_bytes; + kmd_buf_info->offset += get_base.cmd.used_bytes; + num_ent++; + prepare->num_hw_update_entries = num_ent; + + /* return success */ + return 0; + } + } + + return rc; +} + +static int cam_isp_update_dual_config( + struct cam_hw_prepare_update_args *prepare, + struct cam_cmd_buf_desc *cmd_desc, + uint32_t split_id, + uint32_t base_idx, + struct cam_ife_hw_mgr_res *res_list_isp_out, + uint32_t size_isp_out) +{ + int rc = -EINVAL; + struct cam_isp_dual_config *dual_config; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *res; + 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, remain_len = 0; + uint32_t *cpu_addr; + uint32_t i, j; + + CAM_DBG(CAM_ISP, "cmd des size %d, length: %d", + cmd_desc->size, cmd_desc->length); + + rc = cam_packet_util_get_cmd_mem_addr( + cmd_desc->mem_handle, &cpu_addr, &len); + 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_ISP, "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_ISP, "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) { + CAM_ERR(CAM_ISP, + "failed update for i:%d > size_isp_out:%d", + i, size_isp_out); + rc = -EINVAL; + goto end; + } + + hw_mgr_res = &res_list_isp_out[i]; + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; 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]; + + if (res->res_id < CAM_ISP_IFE_OUT_RES_BASE || + res->res_id >= CAM_ISP_IFE_OUT_RES_MAX) + continue; + + outport_id = res->res_id & 0xFF; + + ports_plane_idx = (j * (dual_config->num_ports * + CAM_PACKET_MAX_PLANES)) + + (outport_id * CAM_PACKET_MAX_PLANES); + + if (dual_config->stripes[ports_plane_idx].port_id == 0) + continue; + + dual_isp_update_args.split_id = j; + dual_isp_update_args.res = res; + dual_isp_update_args.dual_cfg = dual_config; + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_STRIPE_UPDATE, + &dual_isp_update_args, + sizeof(struct cam_isp_hw_dual_isp_update_args)); + if (rc) + goto end; + } + } + +end: + return rc; +} + +int cam_isp_add_cmd_buf_update( + struct cam_ife_hw_mgr_res *hw_mgr_res, + uint32_t cmd_type, + uint32_t hw_cmd_type, + uint32_t base_idx, + uint32_t *cmd_buf_addr, + uint32_t kmd_buf_remain_size, + void *cmd_update_data, + uint32_t *bytes_used) +{ + int rc = 0; + struct cam_isp_resource_node *res; + struct cam_isp_hw_get_cmd_update cmd_update; + uint32_t i; + uint32_t total_used_bytes = 0; + + if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) { + CAM_ERR(CAM_ISP, "io res id:%d not valid", + hw_mgr_res->res_type); + return -EINVAL; + } + + cmd_update.cmd_type = hw_cmd_type; + cmd_update.cmd.cmd_buf_addr = cmd_buf_addr; + cmd_update.cmd.size = kmd_buf_remain_size; + cmd_update.cmd.used_bytes = 0; + cmd_update.data = cmd_update_data; + CAM_DBG(CAM_ISP, "cmd_type %u cmd buffer 0x%pK, size %d", + cmd_update.cmd_type, + cmd_update.cmd.cmd_buf_addr, + cmd_update.cmd.size); + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + if (hw_mgr_res->hw_res[i]->hw_intf->hw_idx != base_idx) + continue; + + res = hw_mgr_res->hw_res[i]; + cmd_update.res = res; + + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + cmd_update.cmd_type, &cmd_update, + 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; + } + + total_used_bytes += cmd_update.cmd.used_bytes; + } + *bytes_used = total_used_bytes; + CAM_DBG(CAM_ISP, "total_used_bytes %u", total_used_bytes); + return rc; +} + +int cam_isp_add_command_buffers( + struct cam_hw_prepare_update_args *prepare, + struct cam_kmd_buf_info *kmd_buf_info, + struct ctx_base_info *base_info, + cam_packet_generic_blob_handler blob_handler_cb, + struct cam_ife_hw_mgr_res *res_list_isp_out, + uint32_t size_isp_out) +{ + int rc = 0; + uint32_t cmd_meta_data, num_ent, i; + uint32_t base_idx; + enum cam_isp_hw_split_id split_id; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_hw_update_entry *hw_entry; + + hw_entry = prepare->hw_update_entries; + split_id = base_info->split_id; + base_idx = base_info->idx; + + /* + * set the cmd_desc to point the first command descriptor in the + * packet + */ + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint8_t *)&prepare->packet->payload + + prepare->packet->cmd_buf_offset); + + CAM_DBG(CAM_ISP, "split id = %d, number of command buffers:%d", + split_id, prepare->packet->num_cmd_buf); + + for (i = 0; i < prepare->packet->num_cmd_buf; i++) { + num_ent = prepare->num_hw_update_entries; + if (!cmd_desc[i].length) + continue; + + /* One hw entry space required for left or right or common */ + if (num_ent + 1 >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); + return -EINVAL; + } + + rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); + if (rc) + return rc; + + cmd_meta_data = cmd_desc[i].meta_data; + + CAM_DBG(CAM_ISP, "meta type: %d, split_id: %d", + cmd_meta_data, split_id); + + switch (cmd_meta_data) { + case CAM_ISP_PACKET_META_BASE: + case CAM_ISP_PACKET_META_LEFT: + case CAM_ISP_PACKET_META_DMI_LEFT: + if (split_id == CAM_ISP_HW_SPLIT_LEFT) { + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].handle = + cmd_desc[i].mem_handle; + hw_entry[num_ent].offset = cmd_desc[i].offset; + CAM_DBG(CAM_ISP, + "Meta_Left num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + + if (cmd_meta_data == + CAM_ISP_PACKET_META_DMI_LEFT) + hw_entry[num_ent].flags = 0x1; + + num_ent++; + } + break; + case CAM_ISP_PACKET_META_RIGHT: + case CAM_ISP_PACKET_META_DMI_RIGHT: + if (split_id == CAM_ISP_HW_SPLIT_RIGHT) { + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].handle = + cmd_desc[i].mem_handle; + hw_entry[num_ent].offset = cmd_desc[i].offset; + CAM_DBG(CAM_ISP, + "Meta_Right num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + + if (cmd_meta_data == + CAM_ISP_PACKET_META_DMI_RIGHT) + hw_entry[num_ent].flags = 0x1; + num_ent++; + } + break; + case CAM_ISP_PACKET_META_COMMON: + case CAM_ISP_PACKET_META_DMI_COMMON: + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].handle = + cmd_desc[i].mem_handle; + hw_entry[num_ent].offset = cmd_desc[i].offset; + CAM_DBG(CAM_ISP, + "Meta_Common num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + if (cmd_meta_data == CAM_ISP_PACKET_META_DMI_COMMON) + hw_entry[num_ent].flags = 0x1; + + num_ent++; + break; + case CAM_ISP_PACKET_META_DUAL_CONFIG: + rc = cam_isp_update_dual_config(prepare, + &cmd_desc[i], split_id, base_idx, + res_list_isp_out, size_isp_out); + + if (rc) + return rc; + break; + case CAM_ISP_PACKET_META_GENERIC_BLOB_LEFT: + if (split_id == CAM_ISP_HW_SPLIT_LEFT) { + struct cam_isp_generic_blob_info blob_info; + + prepare->num_hw_update_entries = num_ent; + blob_info.prepare = prepare; + blob_info.base_info = base_info; + blob_info.kmd_buf_info = kmd_buf_info; + + rc = cam_packet_util_process_generic_cmd_buffer( + &cmd_desc[i], + blob_handler_cb, + &blob_info); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in processing blobs %d", + rc); + return rc; + } + num_ent = prepare->num_hw_update_entries; + } + break; + case CAM_ISP_PACKET_META_GENERIC_BLOB_RIGHT: + if (split_id == CAM_ISP_HW_SPLIT_RIGHT) { + struct cam_isp_generic_blob_info blob_info; + + prepare->num_hw_update_entries = num_ent; + blob_info.prepare = prepare; + blob_info.base_info = base_info; + blob_info.kmd_buf_info = kmd_buf_info; + + rc = cam_packet_util_process_generic_cmd_buffer( + &cmd_desc[i], + blob_handler_cb, + &blob_info); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in processing blobs %d", + rc); + return rc; + } + num_ent = prepare->num_hw_update_entries; + } + break; + case CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON: { + struct cam_isp_generic_blob_info blob_info; + + prepare->num_hw_update_entries = num_ent; + blob_info.prepare = prepare; + blob_info.base_info = base_info; + blob_info.kmd_buf_info = kmd_buf_info; + + rc = cam_packet_util_process_generic_cmd_buffer( + &cmd_desc[i], + blob_handler_cb, + &blob_info); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in processing blobs %d", rc); + return rc; + } + num_ent = prepare->num_hw_update_entries; + } + break; + default: + CAM_ERR(CAM_ISP, "invalid cdm command meta data %d", + cmd_meta_data); + return -EINVAL; + } + prepare->num_hw_update_entries = num_ent; + } + + return rc; +} + +int cam_isp_add_io_buffers( + int iommu_hdl, + int sec_iommu_hdl, + struct cam_hw_prepare_update_args *prepare, + 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) +{ + int rc = 0; + uint64_t io_addr[CAM_PACKET_MAX_PLANES]; + struct cam_buf_io_cfg *io_cfg; + struct cam_isp_resource_node *res; + 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; + uint32_t i, j, num_out_buf, num_in_buf; + uint32_t res_id_out, res_id_in, plane_id; + uint32_t io_cfg_used_bytes, num_ent; + size_t size; + int32_t hdl; + int mmu_hdl; + bool mode, is_buf_secure; + + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &prepare->packet->payload + + prepare->packet->io_configs_offset); + num_out_buf = 0; + num_in_buf = 0; + io_cfg_used_bytes = 0; + prepare->pf_data->packet = prepare->packet; + + /* Max one hw entries required for each base */ + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + for (i = 0; i < prepare->packet->num_io_configs; i++) { + CAM_DBG(CAM_ISP, "======= io config idx %d ============", i); + CAM_DBG(CAM_REQ, + "i %d req_id %llu resource_type:%d fence:%d direction %d", + i, prepare->packet->header.request_id, + io_cfg[i].resource_type, io_cfg[i].fence, + io_cfg[i].direction); + CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format); + + if (io_cfg[i].direction == CAM_BUF_OUTPUT) { + res_id_out = io_cfg[i].resource_type & 0xFF; + if (res_id_out >= size_isp_out) { + CAM_ERR(CAM_ISP, "invalid out restype:%x", + io_cfg[i].resource_type); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, + "configure output io with fill fence %d", + fill_fence); + out_map_entries = + &prepare->out_map_entries[num_out_buf]; + if (fill_fence) { + if (num_out_buf < + prepare->max_out_map_entries) { + out_map_entries->resource_handle = + io_cfg[i].resource_type; + out_map_entries->sync_id = + io_cfg[i].fence; + num_out_buf++; + } else { + CAM_ERR(CAM_ISP, "ln_out:%d max_ln:%d", + num_out_buf, + prepare->max_out_map_entries); + return -EINVAL; + } + } + + hw_mgr_res = &res_list_isp_out[res_id_out]; + if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) { + CAM_ERR(CAM_ISP, "io res id:%d not valid", + io_cfg[i].resource_type); + return -EINVAL; + } + } else if (io_cfg[i].direction == CAM_BUF_INPUT) { + res_id_in = io_cfg[i].resource_type & 0xFF; + 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) { + if (num_in_buf < prepare->max_in_map_entries) { + in_map_entries->resource_handle = + io_cfg[i].resource_type; + in_map_entries->sync_id = + io_cfg[i].fence; + num_in_buf++; + } else { + CAM_ERR(CAM_ISP, "ln_in:%d imax_ln:%d", + num_in_buf, + prepare->max_in_map_entries); + return -EINVAL; + } + } + } else { + CAM_ERR(CAM_ISP, "Invalid io config direction :%d", + io_cfg[i].direction); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "setup mem io"); + 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; + + if (hw_mgr_res->hw_res[j]->hw_intf->hw_idx != base_idx) + continue; + + res = hw_mgr_res->hw_res[j]; + if (res->res_id != io_cfg[i].resource_type) { + CAM_ERR(CAM_ISP, + "wm err res id:%d io res id:%d", + res->res_id, io_cfg[i].resource_type); + return -EINVAL; + } + + 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; + update_buf.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + io_cfg_used_bytes/4; + wm_update.image_buf = io_addr; + wm_update.num_buf = plane_id; + wm_update.io_cfg = &io_cfg[i]; + update_buf.cmd.size = kmd_buf_remain_size; + update_buf.wm_update = &wm_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, &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; + } + 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; + } + } + + CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d", + io_cfg_used_bytes, fill_fence); + if (io_cfg_used_bytes) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = io_cfg_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + CAM_DBG(CAM_ISP, + "num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); + num_ent++; + + kmd_buf_info->used_bytes += io_cfg_used_bytes; + kmd_buf_info->offset += io_cfg_used_bytes; + prepare->num_hw_update_entries = num_ent; + } + + if (fill_fence) { + prepare->num_out_map_entries = num_out_buf; + prepare->num_in_map_entries = num_in_buf; + } + + return rc; +} + + +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) +{ + 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; + uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; + + hw_entry = prepare->hw_update_entries; + /* Max one hw entries required for each base */ + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + reg_update_size = 0; + list_for_each_entry(hw_mgr_res, res_list_isp_src, list) { + if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) + continue; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + res = hw_mgr_res->hw_res[i]; + if (res->hw_intf->hw_idx != base_idx) + continue; + + if (kmd_buf_info->size > (kmd_buf_info->used_bytes + + reg_update_size)) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + reg_update_size); + } else { + CAM_ERR(CAM_ISP, "no free mem %d %d %d", + base_idx, kmd_buf_info->size, + kmd_buf_info->used_bytes + + reg_update_size); + rc = -EINVAL; + return rc; + } + + get_regup.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + reg_update_size/4; + get_regup.cmd.size = kmd_buf_remain_size; + get_regup.cmd_type = CAM_ISP_HW_CMD_GET_REG_UPDATE; + get_regup.res = res; + + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_REG_UPDATE, &get_regup, + sizeof(struct cam_isp_hw_get_cmd_update)); + if (rc) + return rc; + + CAM_DBG(CAM_ISP, "Reg update added for res %d hw_id %d", + res->res_id, res->hw_intf->hw_idx); + reg_update_size += get_regup.cmd.used_bytes; + } + } + + if (reg_update_size) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = reg_update_size; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + CAM_DBG(CAM_ISP, + "num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); + num_ent++; + + kmd_buf_info->used_bytes += reg_update_size; + kmd_buf_info->offset += reg_update_size; + prepare->num_hw_update_entries = num_ent; + /* reg update is success return status 0 */ + rc = 0; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c new file mode 100644 index 000000000000..5145dadded28 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "cam_tasklet_util.h" +#include "cam_irq_controller.h" +#include "cam_debug_util.h" + +#define CAM_TASKLETQ_SIZE 256 + +static void cam_tasklet_action(unsigned long data); + +/** + * struct cam_tasklet_queue_cmd: + * @Brief: Structure associated with each slot in the + * tasklet queue + * + * @list: list_head member for each entry in queue + * @payload: Payload structure for the event. This will be + * passed to the handler function + * @handler_priv: Private data passed at event subscribe + * @bottom_half_handler: Function pointer for event handler in bottom + * half context + * + */ +struct cam_tasklet_queue_cmd { + struct list_head list; + void *payload; + void *handler_priv; + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; +}; + +/** + * struct cam_tasklet_info: + * @Brief: Tasklet private structure + * + * @list: list_head member for each tasklet + * @index: Instance id for the tasklet + * @tasklet_lock: Spin lock + * @tasklet_active: Atomic variable to control tasklet state + * @tasklet: Tasklet structure used to schedule bottom half + * @free_cmd_list: List of free tasklet queue cmd for use + * @used_cmd_list: List of used tasklet queue cmd + * @cmd_queue: Array of tasklet cmd for storage + * @ctx_priv: Private data passed to the handling function + * + */ +struct cam_tasklet_info { + struct list_head list; + uint32_t index; + spinlock_t tasklet_lock; + atomic_t tasklet_active; + struct tasklet_struct tasklet; + + struct list_head free_cmd_list; + struct list_head used_cmd_list; + struct cam_tasklet_queue_cmd cmd_queue[CAM_TASKLETQ_SIZE]; + + void *ctx_priv; +}; + +struct cam_irq_bh_api tasklet_bh_api = { + .bottom_half_enqueue_func = cam_tasklet_enqueue_cmd, + .get_bh_payload_func = cam_tasklet_get_cmd, + .put_bh_payload_func = cam_tasklet_put_cmd, +}; + +int cam_tasklet_get_cmd( + void *bottom_half, + void **bh_cmd) +{ + int rc = 0; + unsigned long flags; + struct cam_tasklet_info *tasklet = bottom_half; + struct cam_tasklet_queue_cmd *tasklet_cmd = NULL; + + *bh_cmd = NULL; + + if (tasklet == NULL) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "tasklet is NULL"); + return -EINVAL; + } + + if (!atomic_read(&tasklet->tasklet_active)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active"); + rc = -EPIPE; + return rc; + } + + spin_lock_irqsave(&tasklet->tasklet_lock, flags); + if (list_empty(&tasklet->free_cmd_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No more free tasklet cmd"); + rc = -ENODEV; + goto spin_unlock; + } else { + tasklet_cmd = list_first_entry(&tasklet->free_cmd_list, + struct cam_tasklet_queue_cmd, list); + list_del_init(&(tasklet_cmd)->list); + *bh_cmd = tasklet_cmd; + } + +spin_unlock: + spin_unlock_irqrestore(&tasklet->tasklet_lock, flags); + return rc; +} + +void cam_tasklet_put_cmd( + void *bottom_half, + void **bh_cmd) +{ + unsigned long flags; + struct cam_tasklet_info *tasklet = bottom_half; + struct cam_tasklet_queue_cmd *tasklet_cmd = *bh_cmd; + + if (tasklet == NULL) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "tasklet is NULL"); + return; + } + + if (tasklet_cmd == NULL) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid tasklet_cmd"); + return; + } + + spin_lock_irqsave(&tasklet->tasklet_lock, flags); + list_del_init(&tasklet_cmd->list); + list_add_tail(&tasklet_cmd->list, &tasklet->free_cmd_list); + *bh_cmd = NULL; + spin_unlock_irqrestore(&tasklet->tasklet_lock, flags); +} + +/** + * cam_tasklet_dequeue_cmd() + * + * @brief: Initialize the tasklet info structure + * + * @hw_mgr_ctx: Private Ctx data that will be passed to the handler + * function + * @idx: Index of tasklet used as identity + * @tasklet_action: Tasklet callback function that will be called + * when tasklet runs on CPU + * + * @return: 0: Success + * Negative: Failure + */ +static int cam_tasklet_dequeue_cmd( + struct cam_tasklet_info *tasklet, + struct cam_tasklet_queue_cmd **tasklet_cmd) +{ + int rc = 0; + unsigned long flags; + + *tasklet_cmd = NULL; + + CAM_DBG(CAM_ISP, "Dequeue before lock."); + spin_lock_irqsave(&tasklet->tasklet_lock, flags); + if (list_empty(&tasklet->used_cmd_list)) { + CAM_DBG(CAM_ISP, "End of list reached. Exit"); + rc = -ENODEV; + goto spin_unlock; + } else { + *tasklet_cmd = list_first_entry(&tasklet->used_cmd_list, + struct cam_tasklet_queue_cmd, list); + list_del_init(&(*tasklet_cmd)->list); + CAM_DBG(CAM_ISP, "Dequeue Successful"); + } + +spin_unlock: + spin_unlock_irqrestore(&tasklet->tasklet_lock, flags); + return rc; +} + +void cam_tasklet_enqueue_cmd( + void *bottom_half, + void *bh_cmd, + void *handler_priv, + void *evt_payload_priv, + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler) +{ + unsigned long flags; + struct cam_tasklet_queue_cmd *tasklet_cmd = bh_cmd; + struct cam_tasklet_info *tasklet = bottom_half; + + if (!bottom_half) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "NULL bottom half"); + return; + } + + if (!bh_cmd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "NULL bh cmd"); + return; + } + + if (!atomic_read(&tasklet->tasklet_active)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active\n"); + return; + } + + CAM_DBG(CAM_ISP, "Enqueue tasklet cmd"); + tasklet_cmd->bottom_half_handler = bottom_half_handler; + tasklet_cmd->payload = evt_payload_priv; + tasklet_cmd->handler_priv = handler_priv; + spin_lock_irqsave(&tasklet->tasklet_lock, flags); + list_add_tail(&tasklet_cmd->list, + &tasklet->used_cmd_list); + spin_unlock_irqrestore(&tasklet->tasklet_lock, flags); + tasklet_schedule(&tasklet->tasklet); +} + +int cam_tasklet_init( + void **tasklet_info, + void *hw_mgr_ctx, + uint32_t idx) +{ + int i; + struct cam_tasklet_info *tasklet = NULL; + + tasklet = kzalloc(sizeof(struct cam_tasklet_info), GFP_KERNEL); + if (!tasklet) { + CAM_DBG(CAM_ISP, + "Error! Unable to allocate memory for tasklet"); + *tasklet_info = NULL; + return -ENOMEM; + } + + tasklet->ctx_priv = hw_mgr_ctx; + tasklet->index = idx; + spin_lock_init(&tasklet->tasklet_lock); + memset(tasklet->cmd_queue, 0, sizeof(tasklet->cmd_queue)); + INIT_LIST_HEAD(&tasklet->free_cmd_list); + INIT_LIST_HEAD(&tasklet->used_cmd_list); + for (i = 0; i < CAM_TASKLETQ_SIZE; i++) { + INIT_LIST_HEAD(&tasklet->cmd_queue[i].list); + list_add_tail(&tasklet->cmd_queue[i].list, + &tasklet->free_cmd_list); + } + tasklet_init(&tasklet->tasklet, cam_tasklet_action, + (unsigned long)tasklet); + tasklet_disable(&tasklet->tasklet); + + *tasklet_info = tasklet; + + return 0; +} + +void cam_tasklet_deinit(void **tasklet_info) +{ + struct cam_tasklet_info *tasklet = *tasklet_info; + + if (atomic_read(&tasklet->tasklet_active)) { + atomic_set(&tasklet->tasklet_active, 0); + tasklet_kill(&tasklet->tasklet); + tasklet_disable(&tasklet->tasklet); + } + kfree(tasklet); + *tasklet_info = NULL; +} + +static inline void cam_tasklet_flush(struct cam_tasklet_info *tasklet_info) +{ + cam_tasklet_action((unsigned long) tasklet_info); +} + +int cam_tasklet_start(void *tasklet_info) +{ + struct cam_tasklet_info *tasklet = tasklet_info; + int i = 0; + + if (atomic_read(&tasklet->tasklet_active)) { + CAM_ERR(CAM_ISP, "Tasklet already active. idx = %d", + tasklet->index); + return -EBUSY; + } + + /* clean up the command queue first */ + for (i = 0; i < CAM_TASKLETQ_SIZE; i++) { + list_del_init(&tasklet->cmd_queue[i].list); + list_add_tail(&tasklet->cmd_queue[i].list, + &tasklet->free_cmd_list); + } + + atomic_set(&tasklet->tasklet_active, 1); + + tasklet_enable(&tasklet->tasklet); + + return 0; +} + +void cam_tasklet_stop(void *tasklet_info) +{ + struct cam_tasklet_info *tasklet = tasklet_info; + + atomic_set(&tasklet->tasklet_active, 0); + tasklet_kill(&tasklet->tasklet); + tasklet_disable(&tasklet->tasklet); + cam_tasklet_flush(tasklet); +} + +/* + * cam_tasklet_action() + * + * @brief: Process function that will be called when tasklet runs + * on CPU + * + * @data: Tasklet Info structure that is passed in tasklet_init + * + * @return: Void + */ +static void cam_tasklet_action(unsigned long data) +{ + struct cam_tasklet_info *tasklet_info = NULL; + struct cam_tasklet_queue_cmd *tasklet_cmd = NULL; + + tasklet_info = (struct cam_tasklet_info *)data; + + while (!cam_tasklet_dequeue_cmd(tasklet_info, &tasklet_cmd)) { + tasklet_cmd->bottom_half_handler(tasklet_cmd->handler_priv, + tasklet_cmd->payload); + cam_tasklet_put_cmd(tasklet_info, (void **)(&tasklet_cmd)); + } +} diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h new file mode 100644 index 000000000000..50161ea001f5 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ISP_HW_PARSER_H_ +#define _CAM_ISP_HW_PARSER_H_ + +#include +#include +#include "cam_isp_hw_mgr_intf.h" +#include "cam_ife_hw_mgr.h" +#include "cam_hw_intf.h" +#include "cam_packet_util.h" + +/* + * struct cam_isp_generic_blob_info + * + * @prepare: Payload for prepare command + * @ctx_base_info: Base hardware information for the context + * @kmd_buf_info: Kmd buffer to store the custom cmd data + */ +struct cam_isp_generic_blob_info { + struct cam_hw_prepare_update_args *prepare; + struct ctx_base_info *base_info; + struct cam_kmd_buf_info *kmd_buf_info; +}; + +/* + * cam_isp_add_change_base() + * + * @brief Add change base in the hw entries list + * processe the isp source list get the change base from + * ISP HW instance + * + * @prepare: Contain the packet and HW update variables + * @res_list_isp_src: Resource list for IFE/VFE source + * @base_idx: Base or dev index of the IFE/VFE HW instance for + * which change change base need to be added + * @kmd_buf_info: Kmd buffer to store the change base command + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_isp_add_change_base( + 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); + +/* + * cam_isp_add_cmd_buf_update() + * + * @brief Add command buffer in the HW entries list for given + * Blob Data. + * + * @hw_mgr_res: HW resource to get the update from + * @cmd_type: Cmd type to get update for + * @hw_cmd_type: HW Cmd type corresponding to cmd_type + * @base_idx: Base hardware index + * @cmd_buf_addr: Cpu buf addr of kmd scratch buffer + * @kmd_buf_remain_size: Remaining size left for cmd buffer update + * @cmd_update_data: Data needed by HW to process the cmd and provide + * cmd buffer + * @bytes_used: Address of the field to be populated with + * total bytes used as output to caller + * + * @return: Negative for Failure + * otherwise returns bytes used + */ +int cam_isp_add_cmd_buf_update( + struct cam_ife_hw_mgr_res *hw_mgr_res, + uint32_t cmd_type, + uint32_t hw_cmd_type, + uint32_t base_idx, + uint32_t *cmd_buf_addr, + uint32_t kmd_buf_remain_size, + void *cmd_update_data, + uint32_t *bytes_used); + +/* + * cam_isp_add_command_buffers() + * + * @brief Add command buffer in the HW entries list for given + * left or right VFE/IFE instance. + * + * @prepare: Contain the packet and HW update variables + * @kmd_buf_info: KMD buffer to store the custom cmd data + * @base_info: base hardware information + * @blob_handler_cb: Call_back_function for Meta handling + * @res_list_isp_out: IFE /VFE out resource list + * @size_isp_out: Size of the res_list_isp_out array + * + * @return: 0 for success + * Negative for Failure + */ +int cam_isp_add_command_buffers( + struct cam_hw_prepare_update_args *prepare, + struct cam_kmd_buf_info *kmd_buf_info, + struct ctx_base_info *base_info, + cam_packet_generic_blob_handler blob_handler_cb, + struct cam_ife_hw_mgr_res *res_list_isp_out, + uint32_t size_isp_out); + +/* + * cam_isp_add_io_buffers() + * + * @brief Add io buffer configurations in the HW entries list + * processe the io configurations based on the base + * index and update the HW entries list + * + * @iommu_hdl: Iommu handle to get the IO buf from memory manager + * @sec_iommu_hdl: Secure iommu handle to get the IO buf from + * memory manager + * @prepare: Contain the packet and HW update variables + * @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 + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_isp_add_io_buffers( + int iommu_hdl, + int sec_iommu_hdl, + struct cam_hw_prepare_update_args *prepare, + 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); + +/* + * cam_isp_add_reg_update() + * + * @brief Add reg update in the hw entries list + * processe the isp source list get the reg update from + * ISP HW instance + * + * @prepare: Contain the packet and HW update variables + * @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 + * @return: 0 for success + * -EINVAL for Fail + */ +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); + +#endif /*_CAM_ISP_HW_PARSER_H */ diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h new file mode 100644 index 000000000000..22beb49ef6fc --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TASKLET_UTIL_H_ +#define _CAM_TASKLET_UTIL_H_ + +#include "cam_irq_controller.h" + +/* + * cam_tasklet_init() + * + * @brief: Initialize the tasklet info structure + * + * @tasklet: Tasklet to initialize + * @hw_mgr_ctx: Private Ctx data that will be passed to the handler + * function + * @idx: Index of tasklet used as identity + * + * @return: 0: Success + * Negative: Failure + */ +int cam_tasklet_init( + void **tasklet, + void *hw_mgr_ctx, + uint32_t idx); + +/* + * cam_tasklet_deinit() + * + * @brief: Deinitialize the tasklet info structure + * + * @tasklet: Tasklet to deinitialize + * + * @return: Void + */ +void cam_tasklet_deinit(void **tasklet); + +/* + * cam_tasklet_start() + * + * @brief: Enable the tasklet to be scheduled and run. + * Caller should make sure this function is called + * before trying to enqueue. + * + * @tasklet: Tasklet to start + * + * @return: 0: Success + * Negative: Failure + */ +int cam_tasklet_start(void *tasklet); + +/* + * cam_tasklet_stop() + * + * @brief: Disable the tasklet so it can no longer be scheduled. + * Need to enable again to run. + * + * @tasklet: Tasklet to stop + * + * @return: Void + */ +void cam_tasklet_stop(void *tasklet); + +/* + * cam_tasklet_enqueue_cmd() + * + * @brief: Enqueue the tasklet_cmd to used list + * + * @bottom_half: Tasklet info to enqueue onto + * @bh_cmd: Tasklet cmd used to enqueue task + * @handler_priv: Private Handler data that will be passed to the + * handler function + * @evt_payload_priv: Event payload that will be passed to the handler + * function + * @bottom_half_handler: Callback function that will be called by tasklet + * for handling event + * + * @return: Void + */ +void cam_tasklet_enqueue_cmd( + void *bottom_half, + void *bh_cmd, + void *handler_priv, + void *evt_payload_priv, + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler); + +/** + * cam_tasklet_get_cmd() + * + * @brief: Get free cmd from tasklet + * + * @bottom_half: Tasklet Info structure to get cmd from + * @bh_cmd: Return tasklet_cmd pointer if successful + * + * @return: 0: Success + * Negative: Failure + */ +int cam_tasklet_get_cmd(void *bottom_half, void **bh_cmd); + +/** + * cam_tasklet_put_cmd() + * + * @brief: Put back cmd to free list + * + * @bottom_half: Tasklet Info structure to put cmd into + * @bh_cmd: tasklet_cmd pointer that needs to be put back + * + * @return: Void + */ +void cam_tasklet_put_cmd(void *bottom_half, void **bh_cmd); + +extern struct cam_irq_bh_api tasklet_bh_api; + +#endif /* _CAM_TASKLET_UTIL_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile new file mode 100644 index 000000000000..fb595fe8f02a --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_irq_controller.o \ No newline at end of file diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c new file mode 100644 index 000000000000..8ed8b9f8b1a8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -0,0 +1,730 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_irq_controller.h" +#include "cam_debug_util.h" + +/** + * struct cam_irq_evt_handler: + * @Brief: Event handler information + * + * @priority: Priority level of this event + * @evt_bit_mask_arr: evt_bit_mask that has the bits set for IRQs to + * subscribe for + * @handler_priv: Private data that will be passed to the Top/Bottom + * Half handler function + * @top_half_handler: Top half Handler callback function + * @bottom_half_handler: Bottom half Handler callback function + * @bottom_half: Pointer to bottom_half implementation on which to + * enqueue the event for further handling + * @bottom_half_enqueue_func: + * Function used to enqueue the bottom_half event + * @list_node: list_head struct used for overall handler List + * @th_list_node: list_head struct used for top half handler List + */ +struct cam_irq_evt_handler { + enum cam_irq_priority_level priority; + uint32_t *evt_bit_mask_arr; + void *handler_priv; + CAM_IRQ_HANDLER_TOP_HALF top_half_handler; + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; + void *bottom_half; + struct cam_irq_bh_api irq_bh_api; + struct list_head list_node; + struct list_head th_list_node; + int index; +}; + +/** + * struct cam_irq_register_obj: + * @Brief: Structure containing information related to + * a particular register Set + * + * @index: Index of set in Array + * @mask_reg_offset: Offset of IRQ MASK register + * @clear_reg_offset: Offset of IRQ CLEAR register + * @status_reg_offset: Offset of IRQ STATUS register + * @top_half_enable_mask: Array of enabled bit_mask sorted by priority + */ +struct cam_irq_register_obj { + uint32_t index; + uint32_t mask_reg_offset; + uint32_t clear_reg_offset; + uint32_t status_reg_offset; + uint32_t top_half_enable_mask[CAM_IRQ_PRIORITY_MAX]; +}; + +/** + * struct cam_irq_controller: + * + * @brief: IRQ Controller structure. + * + * @name: Name of IRQ Controller block + * @mem_base: Mapped base address of register space to which + * register offsets are added to access registers + * @num_registers: Number of sets(mask/clear/status) of IRQ registers + * @irq_register_arr: Array of Register object associated with this + * Controller + * @irq_status_arr: Array of IRQ Status values + * @global_clear_offset: Offset of Global IRQ Clear register. This register + * contains the BIT that needs to be set for the CLEAR + * to take effect + * @global_clear_bitmask: Bitmask needed to be used in Global Clear register + * for Clear IRQ cmd to take effect + * @evt_handler_list_head: List of all event handlers + * @th_list_head: List of handlers sorted by priority + * @hdl_idx: Unique identity of handler assigned on Subscribe. + * Used to Unsubscribe. + * @lock: Lock for use by controller + */ +struct cam_irq_controller { + const char *name; + void __iomem *mem_base; + uint32_t num_registers; + struct cam_irq_register_obj *irq_register_arr; + uint32_t *irq_status_arr; + uint32_t global_clear_offset; + uint32_t global_clear_bitmask; + struct list_head evt_handler_list_head; + struct list_head th_list_head[CAM_IRQ_PRIORITY_MAX]; + uint32_t hdl_idx; + spinlock_t lock; + struct cam_irq_th_payload th_payload; +}; + +int cam_irq_controller_deinit(void **irq_controller) +{ + struct cam_irq_controller *controller = *irq_controller; + struct cam_irq_evt_handler *evt_handler = NULL; + + while (!list_empty(&controller->evt_handler_list_head)) { + evt_handler = list_first_entry( + &controller->evt_handler_list_head, + struct cam_irq_evt_handler, list_node); + list_del_init(&evt_handler->list_node); + kfree(evt_handler->evt_bit_mask_arr); + kfree(evt_handler); + } + + kfree(controller->th_payload.evt_status_arr); + kfree(controller->irq_status_arr); + kfree(controller->irq_register_arr); + kfree(controller); + *irq_controller = NULL; + return 0; +} + +int cam_irq_controller_init(const char *name, + void __iomem *mem_base, + struct cam_irq_controller_reg_info *register_info, + void **irq_controller) +{ + struct cam_irq_controller *controller = NULL; + int i, rc = 0; + + *irq_controller = NULL; + + if (!register_info->num_registers || !register_info->irq_reg_set || + !name || !mem_base) { + CAM_ERR(CAM_IRQ_CTRL, "Invalid parameters"); + rc = -EINVAL; + return rc; + } + + controller = kzalloc(sizeof(struct cam_irq_controller), GFP_KERNEL); + if (!controller) { + CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ Controller"); + return -ENOMEM; + } + + controller->irq_register_arr = kzalloc(register_info->num_registers * + sizeof(struct cam_irq_register_obj), GFP_KERNEL); + if (!controller->irq_register_arr) { + CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ register Arr"); + rc = -ENOMEM; + goto reg_alloc_error; + } + + controller->irq_status_arr = kzalloc(register_info->num_registers * + sizeof(uint32_t), GFP_KERNEL); + if (!controller->irq_status_arr) { + CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ status Arr"); + rc = -ENOMEM; + goto status_alloc_error; + } + + controller->th_payload.evt_status_arr = + kzalloc(register_info->num_registers * sizeof(uint32_t), + GFP_KERNEL); + if (!controller->th_payload.evt_status_arr) { + CAM_DBG(CAM_IRQ_CTRL, + "Failed to allocate BH payload bit mask Arr"); + rc = -ENOMEM; + goto evt_mask_alloc_error; + } + + controller->name = name; + + CAM_DBG(CAM_IRQ_CTRL, "num_registers: %d", + register_info->num_registers); + for (i = 0; i < register_info->num_registers; i++) { + controller->irq_register_arr[i].index = i; + controller->irq_register_arr[i].mask_reg_offset = + register_info->irq_reg_set[i].mask_reg_offset; + controller->irq_register_arr[i].clear_reg_offset = + register_info->irq_reg_set[i].clear_reg_offset; + controller->irq_register_arr[i].status_reg_offset = + register_info->irq_reg_set[i].status_reg_offset; + CAM_DBG(CAM_IRQ_CTRL, "i %d mask_reg_offset: 0x%x", i, + controller->irq_register_arr[i].mask_reg_offset); + CAM_DBG(CAM_IRQ_CTRL, "i %d clear_reg_offset: 0x%x", i, + controller->irq_register_arr[i].clear_reg_offset); + CAM_DBG(CAM_IRQ_CTRL, "i %d status_reg_offset: 0x%x", i, + controller->irq_register_arr[i].status_reg_offset); + } + controller->num_registers = register_info->num_registers; + controller->global_clear_bitmask = register_info->global_clear_bitmask; + controller->global_clear_offset = register_info->global_clear_offset; + controller->mem_base = mem_base; + + CAM_DBG(CAM_IRQ_CTRL, "global_clear_bitmask: 0x%x", + controller->global_clear_bitmask); + CAM_DBG(CAM_IRQ_CTRL, "global_clear_offset: 0x%x", + controller->global_clear_offset); + CAM_DBG(CAM_IRQ_CTRL, "mem_base: %pK", + (void __iomem *)controller->mem_base); + + INIT_LIST_HEAD(&controller->evt_handler_list_head); + for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++) + INIT_LIST_HEAD(&controller->th_list_head[i]); + + spin_lock_init(&controller->lock); + + controller->hdl_idx = 1; + *irq_controller = controller; + + return rc; + +evt_mask_alloc_error: + kfree(controller->irq_status_arr); +status_alloc_error: + kfree(controller->irq_register_arr); +reg_alloc_error: + kfree(controller); + + return rc; +} + +int cam_irq_controller_subscribe_irq(void *irq_controller, + enum cam_irq_priority_level priority, + uint32_t *evt_bit_mask_arr, + void *handler_priv, + CAM_IRQ_HANDLER_TOP_HALF top_half_handler, + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler, + void *bottom_half, + struct cam_irq_bh_api *irq_bh_api) +{ + struct cam_irq_controller *controller = irq_controller; + struct cam_irq_evt_handler *evt_handler = NULL; + int i; + int rc = 0; + uint32_t irq_mask; + unsigned long flags = 0; + bool need_lock; + + if (!controller || !handler_priv || !evt_bit_mask_arr) { + CAM_ERR(CAM_IRQ_CTRL, + "Inval params: ctlr=%pK hdl_priv=%pK bit_mask_arr=%pK", + controller, handler_priv, evt_bit_mask_arr); + return -EINVAL; + } + + if (!top_half_handler) { + CAM_ERR(CAM_IRQ_CTRL, "Missing top half handler"); + return -EINVAL; + } + + if (bottom_half_handler && + (!bottom_half || !irq_bh_api)) { + CAM_ERR(CAM_IRQ_CTRL, + "Invalid params: bh_handler=%pK bh=%pK bh_enq_f=%pK", + bottom_half_handler, + bottom_half, + irq_bh_api); + return -EINVAL; + } + + if (irq_bh_api && + (!irq_bh_api->bottom_half_enqueue_func || + !irq_bh_api->get_bh_payload_func || + !irq_bh_api->put_bh_payload_func)) { + CAM_ERR(CAM_IRQ_CTRL, + "Invalid: enqueue_func=%pK get_bh=%pK put_bh=%pK", + irq_bh_api->bottom_half_enqueue_func, + irq_bh_api->get_bh_payload_func, + irq_bh_api->put_bh_payload_func); + return -EINVAL; + } + + if (priority >= CAM_IRQ_PRIORITY_MAX) { + CAM_ERR(CAM_IRQ_CTRL, "Invalid priority=%u, max=%u", priority, + CAM_IRQ_PRIORITY_MAX); + return -EINVAL; + } + + evt_handler = kzalloc(sizeof(struct cam_irq_evt_handler), GFP_KERNEL); + if (!evt_handler) { + CAM_DBG(CAM_IRQ_CTRL, "Error allocating hlist_node"); + return -ENOMEM; + } + + evt_handler->evt_bit_mask_arr = kzalloc(sizeof(uint32_t) * + controller->num_registers, GFP_KERNEL); + if (!evt_handler->evt_bit_mask_arr) { + CAM_DBG(CAM_IRQ_CTRL, "Error allocating hlist_node"); + rc = -ENOMEM; + goto free_evt_handler; + } + + INIT_LIST_HEAD(&evt_handler->list_node); + INIT_LIST_HEAD(&evt_handler->th_list_node); + + for (i = 0; i < controller->num_registers; i++) + evt_handler->evt_bit_mask_arr[i] = evt_bit_mask_arr[i]; + + evt_handler->priority = priority; + evt_handler->handler_priv = handler_priv; + evt_handler->top_half_handler = top_half_handler; + evt_handler->bottom_half_handler = bottom_half_handler; + evt_handler->bottom_half = bottom_half; + evt_handler->index = controller->hdl_idx++; + + if (irq_bh_api) + evt_handler->irq_bh_api = *irq_bh_api; + + /* Avoid rollover to negative values */ + if (controller->hdl_idx > 0x3FFFFFFF) + controller->hdl_idx = 1; + + need_lock = !in_irq(); + if (need_lock) + spin_lock_irqsave(&controller->lock, flags); + for (i = 0; i < controller->num_registers; i++) { + controller->irq_register_arr[i].top_half_enable_mask[priority] + |= evt_bit_mask_arr[i]; + + irq_mask = cam_io_r_mb(controller->mem_base + + controller->irq_register_arr[i].mask_reg_offset); + irq_mask |= evt_bit_mask_arr[i]; + + cam_io_w_mb(irq_mask, controller->mem_base + + controller->irq_register_arr[i].mask_reg_offset); + } + + list_add_tail(&evt_handler->list_node, + &controller->evt_handler_list_head); + list_add_tail(&evt_handler->th_list_node, + &controller->th_list_head[priority]); + + if (need_lock) + spin_unlock_irqrestore(&controller->lock, flags); + + return evt_handler->index; + +free_evt_handler: + kfree(evt_handler); + evt_handler = NULL; + + return rc; +} + +int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle) +{ + struct cam_irq_controller *controller = irq_controller; + struct cam_irq_evt_handler *evt_handler = NULL; + struct cam_irq_evt_handler *evt_handler_temp; + struct cam_irq_register_obj *irq_register = NULL; + enum cam_irq_priority_level priority; + unsigned long flags = 0; + unsigned int i; + uint32_t irq_mask; + uint32_t found = 0; + int rc = -EINVAL; + bool need_lock; + + if (!controller) + return rc; + + need_lock = !in_irq(); + if (need_lock) + spin_lock_irqsave(&controller->lock, flags); + + list_for_each_entry_safe(evt_handler, evt_handler_temp, + &controller->evt_handler_list_head, list_node) { + if (evt_handler->index == handle) { + CAM_DBG(CAM_IRQ_CTRL, "enable item %d", handle); + found = 1; + rc = 0; + break; + } + } + + if (!found) { + if (need_lock) + spin_unlock_irqrestore(&controller->lock, flags); + return rc; + } + + priority = evt_handler->priority; + for (i = 0; i < controller->num_registers; i++) { + irq_register = &controller->irq_register_arr[i]; + irq_register->top_half_enable_mask[priority] |= + evt_handler->evt_bit_mask_arr[i]; + + irq_mask = cam_io_r_mb(controller->mem_base + + irq_register->mask_reg_offset); + irq_mask |= evt_handler->evt_bit_mask_arr[i]; + + cam_io_w_mb(irq_mask, controller->mem_base + + controller->irq_register_arr[i].mask_reg_offset); + } + if (need_lock) + spin_unlock_irqrestore(&controller->lock, flags); + + return rc; +} + +int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle) +{ + struct cam_irq_controller *controller = irq_controller; + struct cam_irq_evt_handler *evt_handler = NULL; + struct cam_irq_evt_handler *evt_handler_temp; + struct cam_irq_register_obj *irq_register; + enum cam_irq_priority_level priority; + unsigned long flags = 0; + unsigned int i; + uint32_t irq_mask; + uint32_t found = 0; + int rc = -EINVAL; + bool need_lock; + + if (!controller) + return rc; + + need_lock = !in_irq(); + if (need_lock) + spin_lock_irqsave(&controller->lock, flags); + + list_for_each_entry_safe(evt_handler, evt_handler_temp, + &controller->evt_handler_list_head, list_node) { + if (evt_handler->index == handle) { + CAM_DBG(CAM_IRQ_CTRL, "disable item %d", handle); + found = 1; + rc = 0; + break; + } + } + + if (!found) { + if (need_lock) + spin_unlock_irqrestore(&controller->lock, flags); + return rc; + } + + priority = evt_handler->priority; + for (i = 0; i < controller->num_registers; i++) { + irq_register = &controller->irq_register_arr[i]; + irq_register->top_half_enable_mask[priority] &= + ~(evt_handler->evt_bit_mask_arr[i]); + + irq_mask = cam_io_r_mb(controller->mem_base + + irq_register->mask_reg_offset); + CAM_DBG(CAM_IRQ_CTRL, "irq_mask 0x%x before disable 0x%x", + irq_register->mask_reg_offset, irq_mask); + irq_mask &= ~(evt_handler->evt_bit_mask_arr[i]); + + cam_io_w_mb(irq_mask, controller->mem_base + + irq_register->mask_reg_offset); + CAM_DBG(CAM_IRQ_CTRL, "irq_mask 0x%x after disable 0x%x", + irq_register->mask_reg_offset, irq_mask); + + /* Clear the IRQ bits of this handler */ + cam_io_w_mb(evt_handler->evt_bit_mask_arr[i], + controller->mem_base + + irq_register->clear_reg_offset); + + if (controller->global_clear_offset) + cam_io_w_mb( + controller->global_clear_bitmask, + controller->mem_base + + controller->global_clear_offset); + } + if (need_lock) + spin_unlock_irqrestore(&controller->lock, flags); + + return rc; +} + +int cam_irq_controller_unsubscribe_irq(void *irq_controller, + uint32_t handle) +{ + struct cam_irq_controller *controller = irq_controller; + struct cam_irq_evt_handler *evt_handler = NULL; + struct cam_irq_evt_handler *evt_handler_temp; + struct cam_irq_register_obj *irq_register; + enum cam_irq_priority_level priority; + uint32_t i; + uint32_t found = 0; + uint32_t irq_mask; + unsigned long flags = 0; + int rc = -EINVAL; + bool need_lock; + + need_lock = !in_irq(); + if (need_lock) + spin_lock_irqsave(&controller->lock, flags); + + list_for_each_entry_safe(evt_handler, evt_handler_temp, + &controller->evt_handler_list_head, list_node) { + if (evt_handler->index == handle) { + CAM_DBG(CAM_IRQ_CTRL, "unsubscribe item %d", handle); + list_del_init(&evt_handler->list_node); + list_del_init(&evt_handler->th_list_node); + found = 1; + rc = 0; + break; + } + } + + priority = evt_handler->priority; + if (found) { + for (i = 0; i < controller->num_registers; i++) { + irq_register = &controller->irq_register_arr[i]; + irq_register->top_half_enable_mask[priority] &= + ~(evt_handler->evt_bit_mask_arr[i]); + + irq_mask = cam_io_r_mb(controller->mem_base + + irq_register->mask_reg_offset); + irq_mask &= ~(evt_handler->evt_bit_mask_arr[i]); + + cam_io_w_mb(irq_mask, controller->mem_base + + irq_register->mask_reg_offset); + + /* Clear the IRQ bits of this handler */ + cam_io_w_mb(evt_handler->evt_bit_mask_arr[i], + controller->mem_base + + irq_register->clear_reg_offset); + if (controller->global_clear_offset) + cam_io_w_mb( + controller->global_clear_bitmask, + controller->mem_base + + controller->global_clear_offset); + } + + kfree(evt_handler->evt_bit_mask_arr); + kfree(evt_handler); + } + + if (need_lock) + spin_unlock_irqrestore(&controller->lock, flags); + + return rc; +} + +/** + * cam_irq_controller_match_bit_mask() + * + * @Brief: This function checks if any of the enabled IRQ bits + * for a certain handler is Set in the Status values + * of the controller. + * + * @controller: IRQ Controller structure + * @evt_handler: Event handler structure + * + * @Return: True: If any interested IRQ Bit is Set + * False: Otherwise + */ +static bool cam_irq_controller_match_bit_mask( + struct cam_irq_controller *controller, + struct cam_irq_evt_handler *evt_handler) +{ + int i; + + for (i = 0; i < controller->num_registers; i++) { + if (evt_handler->evt_bit_mask_arr[i] & + controller->irq_status_arr[i]) + return true; + } + + return false; +} + +static void cam_irq_controller_th_processing( + struct cam_irq_controller *controller, + struct list_head *th_list_head) +{ + struct cam_irq_evt_handler *evt_handler = NULL; + struct cam_irq_th_payload *th_payload = &controller->th_payload; + bool is_irq_match; + int rc = -EINVAL; + int i; + void *bh_cmd = NULL; + struct cam_irq_bh_api *irq_bh_api = NULL; + + CAM_DBG(CAM_IRQ_CTRL, "Enter"); + + if (list_empty(th_list_head)) + return; + + list_for_each_entry(evt_handler, th_list_head, th_list_node) { + is_irq_match = cam_irq_controller_match_bit_mask(controller, + evt_handler); + + if (!is_irq_match) + continue; + + CAM_DBG(CAM_IRQ_CTRL, "match found"); + + cam_irq_th_payload_init(th_payload); + th_payload->handler_priv = evt_handler->handler_priv; + th_payload->num_registers = controller->num_registers; + for (i = 0; i < controller->num_registers; i++) { + th_payload->evt_status_arr[i] = + controller->irq_status_arr[i] & + evt_handler->evt_bit_mask_arr[i]; + } + + irq_bh_api = &evt_handler->irq_bh_api; + bh_cmd = NULL; + + if (evt_handler->bottom_half_handler) { + rc = irq_bh_api->get_bh_payload_func( + evt_handler->bottom_half, &bh_cmd); + if (rc || !bh_cmd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No payload, IRQ handling frozen"); + continue; + } + } + + /* + * irq_status_arr[0] is dummy argument passed. the entire + * status array is passed in th_payload. + */ + if (evt_handler->top_half_handler) + rc = evt_handler->top_half_handler( + controller->irq_status_arr[0], + (void *)th_payload); + + if (rc && bh_cmd) { + irq_bh_api->put_bh_payload_func( + evt_handler->bottom_half, &bh_cmd); + continue; + } + + if (evt_handler->bottom_half_handler) { + CAM_DBG(CAM_IRQ_CTRL, "Enqueuing bottom half for %s", + controller->name); + irq_bh_api->bottom_half_enqueue_func( + evt_handler->bottom_half, + bh_cmd, + evt_handler->handler_priv, + th_payload->evt_payload_priv, + evt_handler->bottom_half_handler); + } + } + + CAM_DBG(CAM_IRQ_CTRL, "Exit"); +} + +irqreturn_t cam_irq_controller_clear_and_mask(int irq_num, void *priv) +{ + struct cam_irq_controller *controller = priv; + uint32_t i = 0; + + if (!controller) + return IRQ_NONE; + + for (i = 0; i < controller->num_registers; i++) { + + cam_io_w_mb(0x0, controller->mem_base + + controller->irq_register_arr[i].clear_reg_offset); + } + + if (controller->global_clear_offset) + cam_io_w_mb(controller->global_clear_bitmask, + controller->mem_base + + controller->global_clear_offset); + + for (i = 0; i < controller->num_registers; i++) { + cam_io_w_mb(0x0, controller->mem_base + + controller->irq_register_arr[i].mask_reg_offset); + } + + return IRQ_HANDLED; +} + +irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv) +{ + struct cam_irq_controller *controller = priv; + struct cam_irq_register_obj *irq_register; + bool need_th_processing[CAM_IRQ_PRIORITY_MAX] = {false}; + int i; + int j; + + if (!controller) + return IRQ_NONE; + + CAM_DBG(CAM_IRQ_CTRL, "locking controller %pK name %s lock %pK", + controller, controller->name, &controller->lock); + spin_lock(&controller->lock); + for (i = 0; i < controller->num_registers; i++) { + irq_register = &controller->irq_register_arr[i]; + controller->irq_status_arr[i] = cam_io_r_mb( + controller->mem_base + + controller->irq_register_arr[i].status_reg_offset); + cam_io_w_mb(controller->irq_status_arr[i], + controller->mem_base + + controller->irq_register_arr[i].clear_reg_offset); + CAM_DBG(CAM_IRQ_CTRL, "Read irq status%d (0x%x) = 0x%x", i, + controller->irq_register_arr[i].status_reg_offset, + controller->irq_status_arr[i]); + for (j = 0; j < CAM_IRQ_PRIORITY_MAX; j++) { + if (irq_register->top_half_enable_mask[j] & + controller->irq_status_arr[i]) + need_th_processing[j] = true; + CAM_DBG(CAM_IRQ_CTRL, + "i %d j %d need_th_processing = %d", + i, j, need_th_processing[j]); + } + } + + CAM_DBG(CAM_IRQ_CTRL, "Status Registers read Successful"); + + if (controller->global_clear_offset) + cam_io_w_mb(controller->global_clear_bitmask, + controller->mem_base + controller->global_clear_offset); + + CAM_DBG(CAM_IRQ_CTRL, "Status Clear done"); + + for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++) { + if (need_th_processing[i]) { + CAM_DBG(CAM_IRQ_CTRL, "Invoke TH processing"); + cam_irq_controller_th_processing(controller, + &controller->th_list_head[i]); + } + } + spin_unlock(&controller->lock); + CAM_DBG(CAM_IRQ_CTRL, "unlocked controller %pK name %s lock %pK", + controller, controller->name, &controller->lock); + + return IRQ_HANDLED; +} diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h new file mode 100644 index 000000000000..caf21c5caf12 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IRQ_CONTROLLER_H_ +#define _CAM_IRQ_CONTROLLER_H_ + +#include + +#define CAM_IRQ_BITS_PER_REGISTER 32 + +/* + * enum cam_irq_priority_level: + * @Brief: Priority levels for IRQ events. + * Priority_0 events will be serviced before + * Priority_1 if they these bits are set in the same + * Status Read. And so on upto Priority_4. + * + * Default Priority is Priority_4. + */ +enum cam_irq_priority_level { + CAM_IRQ_PRIORITY_0, + CAM_IRQ_PRIORITY_1, + CAM_IRQ_PRIORITY_2, + CAM_IRQ_PRIORITY_3, + CAM_IRQ_PRIORITY_4, + CAM_IRQ_PRIORITY_MAX, +}; + +/* + * struct cam_irq_register_set: + * @Brief: Structure containing offsets of IRQ related + * registers belonging to a Set + * + * @mask_reg_offset: Offset of IRQ MASK register + * @clear_reg_offset: Offset of IRQ CLEAR register + * @status_reg_offset: Offset of IRQ STATUS register + */ +struct cam_irq_register_set { + uint32_t mask_reg_offset; + uint32_t clear_reg_offset; + uint32_t status_reg_offset; +}; + +/* + * struct cam_irq_controller_reg_info: + * @Brief: Structure describing the IRQ registers + * + * @num_registers: Number of sets(mask/clear/status) of IRQ registers + * @irq_reg_set: Array of Register Set Offsets. + * Length of array = num_registers + * @global_clear_offset: Offset of Global IRQ Clear register. This register + * contains the BIT that needs to be set for the CLEAR + * to take effect + * @global_clear_bitmask: Bitmask needed to be used in Global Clear register + * for Clear IRQ cmd to take effect + */ +struct cam_irq_controller_reg_info { + uint32_t num_registers; + struct cam_irq_register_set *irq_reg_set; + uint32_t global_clear_offset; + uint32_t global_clear_bitmask; +}; + +/* + * struct cam_irq_th_payload: + * @Brief: Event payload structure. This structure will be + * passed to the Top Half handler functions. + * + * @handler_priv: Private Data of handling object set when + * subscribing to IRQ event. + * @num_registers: Length of evt_bit_mask Array below + * @evt_status_arr: Array of Status bitmask read from registers. + * Length of array = num_registers + * @evt_payload_priv: Private payload pointer which can be set by Top + * Half handler for use in Bottom Half. + */ +struct cam_irq_th_payload { + void *handler_priv; + uint32_t num_registers; + uint32_t *evt_status_arr; + void *evt_payload_priv; +}; + +/* + * cam_irq_th_payload_init() + * + * @brief: Initialize the top half payload structure + * + * @th_payload: Top Half payload structure to Initialize + * + * @return: Void + */ +static inline void cam_irq_th_payload_init( + struct cam_irq_th_payload *th_payload) { + th_payload->handler_priv = NULL; + th_payload->evt_payload_priv = NULL; +} + +typedef int (*CAM_IRQ_HANDLER_TOP_HALF)(uint32_t evt_id, + struct cam_irq_th_payload *th_payload); + +typedef int (*CAM_IRQ_HANDLER_BOTTOM_HALF)(void *handler_priv, + void *evt_payload_priv); + +typedef void (*CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC)(void *bottom_half, + void *bh_cmd, void *handler_priv, void *evt_payload_priv, + CAM_IRQ_HANDLER_BOTTOM_HALF); + +typedef int (*CAM_IRQ_GET_TASKLET_PAYLOAD_FUNC)(void *bottom_half, + void **bh_cmd); + +typedef void (*CAM_IRQ_PUT_TASKLET_PAYLOAD_FUNC)(void *bottom_half, + void **bh_cmd); + +struct cam_irq_bh_api { + CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC bottom_half_enqueue_func; + CAM_IRQ_GET_TASKLET_PAYLOAD_FUNC get_bh_payload_func; + CAM_IRQ_PUT_TASKLET_PAYLOAD_FUNC put_bh_payload_func; +}; + +/* + * cam_irq_controller_init() + * + * @brief: Create and Initialize IRQ Controller. + * + * @name: Name of IRQ Controller block + * @mem_base: Mapped base address of register space to which + * register offsets are added to access registers + * @register_info: Register Info structure associated with this Controller + * @irq_controller: Pointer to IRQ Controller that will be filled if + * initialization is successful + * + * @return: 0: Success + * Negative: Failure + */ +int cam_irq_controller_init(const char *name, + void __iomem *mem_base, + struct cam_irq_controller_reg_info *register_info, + void **irq_controller); + +/* + * cam_irq_controller_subscribe_irq() + * + * @brief: Subscribe to certain IRQ events. + * + * @irq_controller: Pointer to IRQ Controller that controls this event IRQ + * @priority: Priority level of these events used if multiple events + * are SET in the Status Register + * @evt_bit_mask_arr: evt_bit_mask that has the bits set for IRQs to + * subscribe for + * @handler_priv: Private data that will be passed to the Top/Bottom Half + * handler function + * @top_half_handler: Top half Handler callback function + * @bottom_half_handler: Bottom half Handler callback function + * @bottom_half: Pointer to bottom_half implementation on which to + * enqueue the event for further handling + * @bottom_half_enqueue_func: + * Function used to enqueue the bottom_half event + * + * @return: Positive: Success. Value represents handle which is + * to be used to unsubscribe + * Negative: Failure + */ +int cam_irq_controller_subscribe_irq(void *irq_controller, + enum cam_irq_priority_level priority, + uint32_t *evt_bit_mask_arr, + void *handler_priv, + CAM_IRQ_HANDLER_TOP_HALF top_half_handler, + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler, + void *bottom_half, + struct cam_irq_bh_api *irq_bh_api); + +/* + * cam_irq_controller_unsubscribe_irq() + * + * @brief: Unsubscribe to IRQ events previously subscribed to. + * + * @irq_controller: Pointer to IRQ Controller that controls this event IRQ + * @handle: Handle returned on successful subscribe used to + * identify the handler object + * + * @return: 0: Success + * Negative: Failure + */ +int cam_irq_controller_unsubscribe_irq(void *irq_controller, + uint32_t handle); + +/* + * cam_irq_controller_deinit() + * + * @brief: Deinitialize IRQ Controller. + * + * @irq_controller: Pointer to IRQ Controller that needs to be + * deinitialized + * + * @return: 0: Success + * Negative: Failure + */ +int cam_irq_controller_deinit(void **irq_controller); + +/* + * cam_irq_controller_handle_irq() + * + * @brief: Function that should be registered with the IRQ line. + * This is the first function to be called when the IRQ + * is fired. It will read the Status register and Clear + * the IRQ bits. It will then call the top_half handlers + * and enqueue the result to bottom_half. + * + * @irq_num: Number of IRQ line that was set that lead to this + * function being called + * @priv: Private data registered with request_irq is passed back + * here. This private data should be the irq_controller + * structure. + * + * @return: IRQ_HANDLED/IRQ_NONE + */ +irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv); + +/* + * cam_irq_controller_disable_irq() + * + * @brief: Disable the interrupts on given controller. + * Unsubscribe will disable the IRQ by default, so this is + * only needed if between subscribe/unsubscribe there is + * need to disable IRQ again + * + * @irq_controller: Pointer to IRQ Controller that controls the registered + * events to it. + * @handle: Handle returned on successful subscribe, used to + * identify the handler object + * + * @return: 0: events found and disabled + * Negative: events not registered on this controller + */ +int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle); + +/* + * cam_irq_controller_enable_irq() + * + * @brief: Enable the interrupts on given controller. + * Subscribe will enable the IRQ by default, so this is + * only needed if between subscribe/unsubscribe there is + * need to enable IRQ again + * + * @irq_controller: Pointer to IRQ Controller that controls the registered + * events to it. + * @handle: Handle returned on successful subscribe, used to + * identify the handler object + * + * @return: 0: events found and enabled + * Negative: events not registered on this controller + */ +int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle); + +/* + * cam_irq_controller_clear_and_mask() + * + * @brief: This function clears and masks all the irq bits + * + * @irq_num: Number of IRQ line that was set that lead to this + * function being called + * @priv: Private data registered with request_irq is passed back + * here. This private data should be the irq_controller + * structure. + * + * @return: IRQ_HANDLED/IRQ_NONE + */ +irqreturn_t cam_irq_controller_clear_and_mask(int irq_num, void *priv); +#endif /* _CAM_IRQ_CONTROLLER_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h new file mode 100644 index 000000000000..fb39c02e25c8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ISP_HW_MGR_INTF_H_ +#define _CAM_ISP_HW_MGR_INTF_H_ + +#include +#include +#include +#include +#include "cam_hw_mgr_intf.h" + +/* MAX IFE instance */ +#define CAM_IFE_HW_NUM_MAX 7 +#define CAM_IFE_RDI_NUM_MAX 4 +#define CAM_ISP_BW_CONFIG_V1 1 +#define CAM_ISP_BW_CONFIG_V2 2 + +/* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ +#define CAM_ISP_MAX_PER_PATH_VOTES 30 +/** + * enum cam_isp_hw_event_type - Collection of the ISP hardware events + */ +enum cam_isp_hw_event_type { + CAM_ISP_HW_EVENT_ERROR, + CAM_ISP_HW_EVENT_SOF, + CAM_ISP_HW_EVENT_REG_UPDATE, + CAM_ISP_HW_EVENT_EPOCH, + CAM_ISP_HW_EVENT_EOF, + CAM_ISP_HW_EVENT_DONE, + CAM_ISP_HW_EVENT_MAX +}; + + +/** + * enum cam_isp_hw_err_type - Collection of the ISP error types for + * ISP hardware event CAM_ISP_HW_EVENT_ERROR + */ +enum cam_isp_hw_err_type { + CAM_ISP_HW_ERROR_NONE, + CAM_ISP_HW_ERROR_OVERFLOW, + CAM_ISP_HW_ERROR_P2I_ERROR, + CAM_ISP_HW_ERROR_VIOLATION, + CAM_ISP_HW_ERROR_BUSIF_OVERFLOW, + CAM_ISP_HW_ERROR_MAX, +}; + +/** + * enum cam_isp_hw_stop_cmd - Specify the stop command type + */ +enum cam_isp_hw_stop_cmd { + CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY, + CAM_ISP_HW_STOP_IMMEDIATELY, + CAM_ISP_HW_STOP_MAX, +}; + +/** + * struct cam_isp_stop_args - hardware stop arguments + * + * @hw_stop_cmd: Hardware stop command type information + * @stop_only Send stop only to hw drivers. No Deinit to be + * done. + * + */ +struct cam_isp_stop_args { + enum cam_isp_hw_stop_cmd hw_stop_cmd; + bool stop_only; +}; + +/** + * struct cam_isp_start_args - isp hardware start arguments + * + * @config_args: Hardware configuration commands. + * @start_only Send start only to hw drivers. No init to + * be done. + * + */ +struct cam_isp_start_args { + struct cam_hw_config_args hw_config; + bool start_only; +}; + +/** + * struct cam_isp_bw_config_internal_v2 - Bandwidth configuration + * + * @usage_type: ife hw index + * @num_paths: Number of data paths + * @axi_path per path vote info + */ +struct cam_isp_bw_config_internal_v2 { + uint32_t usage_type; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_ISP_MAX_PER_PATH_VOTES]; +}; + +/** + * struct cam_isp_bw_config_internal - Internal Bandwidth configuration + * + * @usage_type: Usage type (Single/Dual) + * @num_rdi: Number of RDI votes + * @left_pix_vote: Bandwidth vote for left ISP + * @right_pix_vote: Bandwidth vote for right ISP + * @rdi_vote: RDI bandwidth requirements + */ +struct cam_isp_bw_config_internal { + uint32_t usage_type; + uint32_t num_rdi; + struct cam_isp_bw_vote left_pix_vote; + struct cam_isp_bw_vote right_pix_vote; + struct cam_isp_bw_vote rdi_vote[CAM_IFE_RDI_NUM_MAX]; +}; + +/** + * struct cam_isp_prepare_hw_update_data - hw prepare data + * + * @packet_opcode_type: Packet header opcode in the packet header + * this opcode defines, packet is init packet or + * update packet + * @bw_config_version: BW config version indicator + * @bw_config: BW config information + * @bw_config_v2: BW config info for AXI bw voting v2 + * @bw_config_valid: Flag indicating whether the bw_config at the index + * is valid or not + * + */ +struct cam_isp_prepare_hw_update_data { + uint32_t packet_opcode_type; + uint32_t bw_config_version; + struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; + struct cam_isp_bw_config_internal_v2 bw_config_v2[CAM_IFE_HW_NUM_MAX]; + bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; +}; + + +/** + * struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF + * + * @timestamp: Time stamp for the sof event + * @boot_time: Boot time stamp for the sof event + * + */ +struct cam_isp_hw_sof_event_data { + uint64_t timestamp; + uint64_t boot_time; +}; + +/** + * struct cam_isp_hw_reg_update_event_data - Event payload for + * CAM_HW_EVENT_REG_UPDATE + * + * @timestamp: Time stamp for the reg update event + * + */ +struct cam_isp_hw_reg_update_event_data { + uint64_t timestamp; +}; + +/** + * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH + * + * @timestamp: Time stamp for the epoch event + * + */ +struct cam_isp_hw_epoch_event_data { + uint64_t timestamp; +}; + +/** + * struct cam_isp_hw_done_event_data - Event payload for CAM_HW_EVENT_DONE + * + * @num_handles: Number of resource handeles + * @resource_handle: Resource handle array + * @timestamp: Timestamp for the buf done event + * + */ +struct cam_isp_hw_done_event_data { + uint32_t num_handles; + uint32_t resource_handle[ + CAM_NUM_OUT_PER_COMP_IRQ_MAX]; + uint64_t timestamp; +}; + +/** + * struct cam_isp_hw_eof_event_data - Event payload for CAM_HW_EVENT_EOF + * + * @timestamp: Timestamp for the eof event + * + */ +struct cam_isp_hw_eof_event_data { + uint64_t timestamp; +}; + +/** + * struct cam_isp_hw_error_event_data - Event payload for CAM_HW_EVENT_ERROR + * + * @error_type: Error type for the error event + * @timestamp: Timestamp for the error event + * @recovery_enabled: Identifies if the context needs to recover & reapply + * this request + * @enable_req_dump: Enable request dump on HW errors + */ +struct cam_isp_hw_error_event_data { + uint32_t error_type; + uint64_t timestamp; + bool recovery_enabled; + bool enable_req_dump; +}; + +/* enum cam_isp_hw_mgr_command - Hardware manager command type */ +enum cam_isp_hw_mgr_command { + CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT, + 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 + * @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; + union { + uint32_t sof_irq_enable; + uint32_t ctx_type; + } u; +}; + + +/** + * cam_isp_hw_mgr_init() + * + * @brief: Initialization function for the ISP hardware manager + * + * @of_node: Device node input + * @hw_mgr: Input/output structure for the ISP hardware manager + * initialization + * @iommu_hdl: Iommu handle to be returned + */ +int cam_isp_hw_mgr_init(struct device_node *of_node, + struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl); + +#endif /* __CAM_ISP_HW_MGR_INTF_H__ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile new file mode 100644 index 000000000000..41c244c96572 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_SPECTRA_CAMERA) += ife_csid_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += vfe_hw/ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile new file mode 100644 index 000000000000..8ccd9f0b3f62 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_ife_csid_dev.o cam_ife_csid_soc.o cam_ife_csid_core.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_ife_csid17x.o cam_ife_csid_lite17x.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h new file mode 100644 index 000000000000..714fa8ef2b31 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_170_H_ +#define _CAM_IFE_CSID_170_H_ + +#include "cam_ife_csid_core.h" + +static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_170_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_rdi_reg_offset cam_ife_csid_170_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, +}; + +static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_170_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, +}; + +static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_170_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, +}; + +static struct cam_ife_csid_csi2_rx_reg_offset + cam_ife_csid_170_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_de_scramble_cfg0_addr = 0x114, + .csid_csi2_rx_de_scramble_cfg1_addr = 0x118, + .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, + + .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 = 0x3, +}; + +static struct cam_ife_csid_csi2_tpg_reg_offset + cam_ife_csid_170_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_170_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 = 0, + .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, + .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 = 0x7FFF, + .rdi_irq_mask_all = 0x7FFF, + .ppp_irq_mask_all = 0x0, + .measure_en_hbi_vbi_cnt_mask = 0xC, + .format_measure_en_val = 1, +}; + +static struct cam_ife_csid_reg_offset cam_ife_csid_170_reg_offset = { + .cmn_reg = &cam_ife_csid_170_cmn_reg_offset, + .csi2_reg = &cam_ife_csid_170_csi2_reg_offset, + .ipp_reg = &cam_ife_csid_170_ipp_reg_offset, + .ppp_reg = NULL, + .rdi_reg = { + &cam_ife_csid_170_rdi_0_reg_offset, + &cam_ife_csid_170_rdi_1_reg_offset, + &cam_ife_csid_170_rdi_2_reg_offset, + NULL, + }, + .tpg_reg = &cam_ife_csid_170_tpg_reg_offset, +}; + +#endif /*_CAM_IFE_CSID_170_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h new file mode 100644 index 000000000000..70f96ea416d8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h @@ -0,0 +1,346 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_175_H_ +#define _CAM_IFE_CSID_175_H_ + +#include "cam_ife_csid_core.h" + +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_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_175_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, +}; + +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, + .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, +}; + +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, + .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, +}; + +static struct cam_ife_csid_csi2_rx_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, + .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_de_scramble_cfg0_addr = 0x114, + .csid_csi2_rx_de_scramble_cfg1_addr = 0x118, + .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, + + .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 = 0x3, +}; + +static struct cam_ife_csid_csi2_tpg_reg_offset + cam_ife_csid_175_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_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 = 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, + .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 = 0x7FFF, + .rdi_irq_mask_all = 0x7FFF, + .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_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_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_175_tpg_reg_offset, +}; + +#endif /*_CAM_IFE_CSID_175_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h new file mode 100644 index 000000000000..7d47da31e4a8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -0,0 +1,362 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#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/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c new file mode 100644 index 000000000000..d88347caa388 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + + +#include +#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_csid480.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 +#define CAM_CSID_VERSION_V480 0x40080000 + +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 struct cam_ife_csid_hw_info cam_ife_csid480_hw_info = { + .csid_reg = &cam_ife_csid_480_reg_offset, + .hw_dts_version = CAM_CSID_VERSION_V480, +}; + +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, + }, + { + .compatible = "qcom,csid480", + .data = &cam_ife_csid480_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_ife_csid17x_dt_match); + +static struct platform_driver cam_ife_csid17x_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_csid17x_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_ife_csid17x_init_module(void) +{ + return platform_driver_register(&cam_ife_csid17x_driver); +} + +static void __exit cam_ife_csid17x_exit_module(void) +{ + platform_driver_unregister(&cam_ife_csid17x_driver); +} + +module_init(cam_ife_csid17x_init_module); +module_exit(cam_ife_csid17x_exit_module); +MODULE_DESCRIPTION("CAM IFE_CSID17X driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h new file mode 100644 index 000000000000..c18a21ff7c32 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_480_H_ +#define _CAM_IFE_CSID_480_H_ + +#include "cam_ife_csid_core.h" + +static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_480_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, + .csid_pxl_err_recovery_cfg0_addr = 0x2d0, + .csid_pxl_err_recovery_cfg1_addr = 0x2d4, + .csid_pxl_err_recovery_cfg2_addr = 0x2d8, + .csid_pxl_multi_vcdt_cfg0_addr = 0x2dc, + /* configurations */ + .pix_store_en_shift_val = 7, + .early_eof_en_shift_val = 29, + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_480_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, + .csid_pxl_err_recovery_cfg0_addr = 0x7d0, + .csid_pxl_err_recovery_cfg1_addr = 0x7d4, + .csid_pxl_err_recovery_cfg2_addr = 0x7d8, + .csid_pxl_multi_vcdt_cfg0_addr = 0x7dc, + /* configurations */ + .pix_store_en_shift_val = 7, + .early_eof_en_shift_val = 29, + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + + +static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_480_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_err_recovery_cfg0_addr = 0x3b0, + .csid_rdi_err_recovery_cfg1_addr = 0x3b4, + .csid_rdi_err_recovery_cfg2_addr = 0x3b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x3bc, + .csid_rdi_byte_cntr_ping_addr = 0x3e0, + .csid_rdi_byte_cntr_pong_addr = 0x3e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_480_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_err_recovery_cfg0_addr = 0x4b0, + .csid_rdi_err_recovery_cfg1_addr = 0x4b4, + .csid_rdi_err_recovery_cfg2_addr = 0x4b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x4bc, + .csid_rdi_byte_cntr_ping_addr = 0x4e0, + .csid_rdi_byte_cntr_pong_addr = 0x4e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_480_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_err_recovery_cfg0_addr = 0x5b0, + .csid_rdi_err_recovery_cfg1_addr = 0x5b4, + .csid_rdi_err_recovery_cfg2_addr = 0x5b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x5bc, + .csid_rdi_byte_cntr_ping_addr = 0x5e0, + .csid_rdi_byte_cntr_pong_addr = 0x5e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_csi2_rx_reg_offset + cam_ife_csid_480_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_de_scramble_cfg0_addr = 0x114, + .csid_csi2_rx_de_scramble_cfg1_addr = 0x118, + .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, + + .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 = 0x3, +}; + +static struct cam_ife_csid_csi2_tpg_reg_offset + cam_ife_csid_480_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_480_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 = 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, + .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 = 0x7FFF, + .rdi_irq_mask_all = 0x7FFF, + .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_480_reg_offset = { + .cmn_reg = &cam_ife_csid_480_cmn_reg_offset, + .csi2_reg = &cam_ife_csid_480_csi2_reg_offset, + .ipp_reg = &cam_ife_csid_480_ipp_reg_offset, + .ppp_reg = &cam_ife_csid_480_ppp_reg_offset, + .rdi_reg = { + &cam_ife_csid_480_rdi_0_reg_offset, + &cam_ife_csid_480_rdi_1_reg_offset, + &cam_ife_csid_480_rdi_2_reg_offset, + NULL, + }, + .tpg_reg = &cam_ife_csid_480_tpg_reg_offset, +}; + +#endif /*_CAM_IFE_CSID_480_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c new file mode 100644 index 000000000000..cce05296f04a --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -0,0 +1,3704 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_ife_csid_core.h" +#include "cam_isp_hw.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + +/* Timeout value in msec */ +#define IFE_CSID_TIMEOUT 1000 + +/* TPG VC/DT values */ +#define CAM_IFE_CSID_TPG_VC_VAL 0xA +#define CAM_IFE_CSID_TPG_DT_VAL 0x2B + +/* Timeout values in usec */ +#define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000 +#define CAM_IFE_CSID_TIMEOUT_ALL_US 100000 + +/* + * Constant Factors needed to change QTimer ticks to nanoseconds + * QTimer Freq = 19.2 MHz + * Time(us) = ticks/19.2 + * Time(ns) = ticks/19.2 * 1000 + */ +#define CAM_IFE_CSID_QTIMER_MUL_FACTOR 10000 +#define CAM_IFE_CSID_QTIMER_DIV_FACTOR 192 + +/* Max number of sof irq's triggered in case of SOF freeze */ +#define CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX 12 + +/* Max CSI Rx irq error count threshold value */ +#define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 100 + +static int cam_ife_csid_is_ipp_ppp_format_supported( + uint32_t in_format) +{ + int rc = -EINVAL; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_DPCM_10_6_10: + case CAM_FORMAT_DPCM_10_8_10: + case CAM_FORMAT_DPCM_12_6_12: + 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: + break; + } + return rc; +} + +static int cam_ife_csid_get_format_rdi( + uint32_t in_format, uint32_t out_format, + uint32_t *decode_fmt, uint32_t *plain_fmt) +{ + int rc = 0; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_6: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN8: + *decode_fmt = 0x0; + *plain_fmt = 0x0; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_8: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_PLAIN128: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN8: + *decode_fmt = 0x1; + *plain_fmt = 0x0; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_10: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_PLAIN128: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_10: + *decode_fmt = 0x2; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_12: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_12: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_12: + *decode_fmt = 0x3; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_14: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_14: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_14: + *decode_fmt = 0x4; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_16: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_16: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_16: + *decode_fmt = 0x5; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_20: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_20: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN32_20: + *decode_fmt = 0x6; + *plain_fmt = 0x2; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_DPCM_10_6_10: + *decode_fmt = 0x7; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_10_8_10: + *decode_fmt = 0x8; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_12_6_12: + *decode_fmt = 0x9; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_12_8_12: + *decode_fmt = 0xA; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_14_8_14: + *decode_fmt = 0xB; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_14_10_14: + *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; + } + + if (rc) + CAM_ERR(CAM_ISP, "Unsupported format pair in %d out %d", + in_format, out_format); + + return rc; +} + +static int cam_ife_csid_get_format_ipp_ppp( + uint32_t in_format, + uint32_t *decode_fmt, uint32_t *plain_fmt) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "input format:%d", + in_format); + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + *decode_fmt = 0; + *plain_fmt = 0; + break; + case CAM_FORMAT_MIPI_RAW_8: + *decode_fmt = 0x1; + *plain_fmt = 0; + break; + case CAM_FORMAT_MIPI_RAW_10: + *decode_fmt = 0x2; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_MIPI_RAW_12: + *decode_fmt = 0x3; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_MIPI_RAW_14: + *decode_fmt = 0x4; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_MIPI_RAW_16: + *decode_fmt = 0x5; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_MIPI_RAW_20: + *decode_fmt = 0x6; + *plain_fmt = 0x2; + break; + case CAM_FORMAT_DPCM_10_6_10: + *decode_fmt = 0x7; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_10_8_10: + *decode_fmt = 0x8; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_12_6_12: + *decode_fmt = 0x9; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_12_8_12: + *decode_fmt = 0xA; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_14_8_14: + *decode_fmt = 0xB; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_DPCM_14_10_14: + *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); + rc = -EINVAL; + } + + CAM_DBG(CAM_ISP, "decode_fmt:%d plain_fmt:%d", + *decode_fmt, *plain_fmt); + + return rc; +} + +static int cam_ife_match_vc_dt_pair(int32_t *vc, uint32_t *dt, + uint32_t num_valid_vc_dt, struct cam_ife_csid_cid_data *cid_data) +{ + uint32_t camera_hw_version; + int rc = 0; + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + return -EINVAL; + } + + if (camera_hw_version != CAM_CPAS_TITAN_480_V100) + num_valid_vc_dt = 1; + + switch (num_valid_vc_dt) { + case 2: + if (vc[1] != cid_data->vc1 || + dt[1] != cid_data->dt1) + return -EINVAL; + case 1: + if (vc[0] != cid_data->vc || + dt[0] != cid_data->dt) + return -EINVAL; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node **res, int32_t *vc, uint32_t *dt, + uint32_t num_valid_vc_dt) +{ + struct cam_ife_csid_cid_data *cid_data; + uint32_t i = 0; + + *res = NULL; + + /* Return already reserved CID if the VC/DT matches */ + for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++) { + if (csid_hw->cid_res[i].res_state >= + CAM_ISP_RESOURCE_STATE_RESERVED) { + cid_data = (struct cam_ife_csid_cid_data *) + csid_hw->cid_res[i].res_priv; + if (!cam_ife_match_vc_dt_pair(vc, dt, + num_valid_vc_dt, cid_data)) { + cid_data->cnt++; + *res = &csid_hw->cid_res[i]; + CAM_DBG(CAM_ISP, "CSID:%d CID %d", + csid_hw->hw_intf->hw_idx, + csid_hw->cid_res[i].res_id); + return 0; + } + } + } + + for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++) { + if (csid_hw->cid_res[i].res_state == + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + cid_data = (struct cam_ife_csid_cid_data *) + csid_hw->cid_res[i].res_priv; + cid_data->vc = vc[0]; + cid_data->dt = dt[0]; + if (num_valid_vc_dt > 1) { + cid_data->vc1 = vc[1]; + cid_data->dt1 = dt[1]; + cid_data->is_valid_vc1_dt1 = 1; + } + cid_data->cnt = 1; + csid_hw->cid_res[i].res_state = + CAM_ISP_RESOURCE_STATE_RESERVED; + *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; + } + } + + CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available", + csid_hw->hw_intf->hw_idx); + + return -EINVAL; +} + + +static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) +{ + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg; + int rc = 0; + uint32_t val = 0, i; + uint32_t status; + + soc_info = &csid_hw->hw_info->soc_info; + csid_reg = csid_hw->csid_info->csid_reg; + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid HW State:%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d Csid reset", + csid_hw->hw_intf->hw_idx); + + /* Mask all interrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + if (csid_reg->cmn_reg->num_pix) + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + + if (csid_reg->cmn_reg->num_ppp) + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_mask_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr); + + /* clear all interrupts */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + + cam_io_w_mb(csid_reg->csi2_reg->csi2_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); + + if (csid_reg->cmn_reg->num_pix) + cam_io_w_mb(csid_reg->cmn_reg->ipp_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); + + if (csid_reg->cmn_reg->num_ppp) + cam_io_w_mb(csid_reg->cmn_reg->ppp_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_clear_addr); + + for (i = 0 ; i < csid_reg->cmn_reg->num_rdis; i++) + cam_io_w_mb(csid_reg->cmn_reg->rdi_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + cam_io_w_mb(0x80, soc_info->reg_map[0].mem_base + + csid_hw->csid_info->csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + + /* enable the IPP and RDI format measure */ + if (csid_reg->cmn_reg->num_pix) + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_cfg0_addr); + + if (csid_reg->cmn_reg->num_ppp) + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_cfg0_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + 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 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); + + 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; + } + + 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) + CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d", + csid_hw->hw_intf->hw_idx, val); + csid_hw->error_irq_count = 0; + + return rc; +} + +static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, + struct cam_csid_reset_cfg_args *reset) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *res; + const struct cam_ife_csid_reg_offset *csid_reg; + uint32_t reset_strb_addr, reset_strb_val, val, id; + struct completion *complete; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + res = reset->node_res; + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid hw state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "CSID:%d resource:%d", + csid_hw->hw_intf->hw_idx, res->res_id); + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + if (!csid_reg->ipp_reg) { + CAM_ERR(CAM_ISP, "CSID:%d IPP not supported :%d", + csid_hw->hw_intf->hw_idx, + res->res_id); + return -EINVAL; + } + + reset_strb_addr = csid_reg->ipp_reg->csid_pxl_rst_strobes_addr; + complete = &csid_hw->csid_ipp_complete; + + /* Enable path reset done interrupt */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + val |= CSID_PATH_INFO_RST_DONE; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { + if (!csid_reg->ppp_reg) { + CAM_ERR(CAM_ISP, "CSID:%d PPP not supported :%d", + csid_hw->hw_intf->hw_idx, + res->res_id); + return -EINVAL; + } + + reset_strb_addr = csid_reg->ppp_reg->csid_pxl_rst_strobes_addr; + complete = &csid_hw->csid_ppp_complete; + + /* Enable path reset done interrupt */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_mask_addr); + val |= CSID_PATH_INFO_RST_DONE; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_mask_addr); + } else { + id = res->res_id; + if (!csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d RDI res not supported :%d", + csid_hw->hw_intf->hw_idx, + res->res_id); + return -EINVAL; + } + + reset_strb_addr = + csid_reg->rdi_reg[id]->csid_rdi_rst_strobes_addr; + complete = + &csid_hw->csid_rdin_complete[id]; + + /* Enable path reset done interrupt */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + val |= CSID_PATH_INFO_RST_DONE; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + } + + init_completion(complete); + reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all; + + /* Enable the Test gen before reset */ + cam_io_w_mb(1, csid_hw->hw_info->soc_info.reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_ctrl_addr); + + /* Reset the corresponding ife csid path */ + cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + + reset_strb_addr); + + rc = wait_for_completion_timeout(complete, + msecs_to_jiffies(IFE_CSID_TIMEOUT)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, "CSID:%d Res id %d fail rc = %d", + csid_hw->hw_intf->hw_idx, + res->res_id, rc); + if (rc == 0) + rc = -ETIMEDOUT; + } + + /* Disable Test Gen after reset*/ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_ctrl_addr); + +end: + return rc; + +} + +static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, + struct cam_csid_hw_reserve_resource_args *cid_reserv) +{ + int rc = 0, i; + struct cam_ife_csid_cid_data *cid_data; + uint32_t camera_hw_version; + uint32_t valid_vc_dt; + + CAM_DBG(CAM_ISP, + "CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->res_type, + cid_reserv->in_port->lane_type, + cid_reserv->in_port->lane_num, + cid_reserv->in_port->dt[0], + cid_reserv->in_port->vc[0]); + + if (cid_reserv->in_port->res_type >= CAM_ISP_IFE_IN_RES_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid phy sel %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->res_type); + rc = -EINVAL; + goto end; + } + + if (cid_reserv->in_port->lane_type >= CAM_ISP_LANE_TYPE_MAX && + cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid lane type %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->lane_type); + rc = -EINVAL; + goto end; + } + + if ((cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_DPHY && + cid_reserv->in_port->lane_num > 4) && + cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid lane num %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->lane_num); + rc = -EINVAL; + goto end; + } + if ((cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_CPHY && + cid_reserv->in_port->lane_num > 3) && + cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { + CAM_ERR(CAM_ISP, " CSID:%d Invalid lane type %d & num %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->lane_type, + cid_reserv->in_port->lane_num); + rc = -EINVAL; + goto end; + } + + valid_vc_dt = cid_reserv->in_port->num_valid_vc_dt; + + /* CSID CSI2 v2.0 supports 31 vc */ + for (i = 0; i < valid_vc_dt; i++) { + if (cid_reserv->in_port->vc[i] > 0x1f || + cid_reserv->in_port->dt[i] > 0x3f) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d or dt: %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->vc[i], + cid_reserv->in_port->dt[i]); + rc = -EINVAL; + goto end; + } + } + + if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG && ( + (cid_reserv->in_port->format < CAM_FORMAT_MIPI_RAW_8 && + cid_reserv->in_port->format > CAM_FORMAT_MIPI_RAW_16))) { + CAM_ERR(CAM_ISP, " CSID:%d Invalid tpg decode fmt %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->format); + rc = -EINVAL; + goto end; + } + + if (csid_hw->csi2_reserve_cnt == UINT_MAX) { + CAM_ERR(CAM_ISP, + "CSID%d reserve cnt reached max", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + goto end; + } + 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: %x", camera_hw_version); + break; + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_170_V120: + if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_PHY_3 && + csid_hw->hw_intf->hw_idx != 2) { + rc = -EINVAL; + goto end; + } + break; + case CAM_CPAS_TITAN_480_V100: + if (cid_reserv->in_port->cust_node == 1) { + if (cid_reserv->in_port->usage_type == 1) { + CAM_ERR(CAM_ISP, "Dual IFE is not supported"); + rc = -EINVAL; + goto end; + } + if (csid_hw->hw_intf->hw_idx != 0) { + CAM_DBG(CAM_ISP, "CSID%d not eligible", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } + } + break; + default: + break; + } + CAM_DBG(CAM_ISP, "Reserve_cnt %u", csid_hw->csi2_reserve_cnt); + + if (csid_hw->csi2_reserve_cnt) { + /* current configure res type should match requested res type */ + if (csid_hw->res_type != cid_reserv->in_port->res_type) { + rc = -EINVAL; + goto end; + } + + if (cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { + if (csid_hw->csi2_rx_cfg.lane_cfg != + cid_reserv->in_port->lane_cfg || + csid_hw->csi2_rx_cfg.lane_type != + cid_reserv->in_port->lane_type || + csid_hw->csi2_rx_cfg.lane_num != + cid_reserv->in_port->lane_num) { + rc = -EINVAL; + goto end; + } + } else { + if (csid_hw->tpg_cfg.in_format != + cid_reserv->in_port->format || + csid_hw->tpg_cfg.width != + cid_reserv->in_port->left_width || + csid_hw->tpg_cfg.height != + cid_reserv->in_port->height || + csid_hw->tpg_cfg.test_pattern != + cid_reserv->in_port->test_pattern) { + rc = -EINVAL; + goto end; + } + } + } + + switch (cid_reserv->res_id) { + case CAM_IFE_PIX_PATH_RES_IPP: + if (csid_hw->ipp_res.res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_DBG(CAM_ISP, + "CSID:%d IPP resource not available", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } + break; + case CAM_IFE_PIX_PATH_RES_PPP: + if (csid_hw->ppp_res.res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d PPP resource not available state %d", + csid_hw->hw_intf->hw_idx, + csid_hw->ppp_res.res_state); + rc = -EINVAL; + goto end; + } + break; + case CAM_IFE_PIX_PATH_RES_RDI_0: + case CAM_IFE_PIX_PATH_RES_RDI_1: + case CAM_IFE_PIX_PATH_RES_RDI_2: + case CAM_IFE_PIX_PATH_RES_RDI_3: + if (csid_hw->rdi_res[cid_reserv->res_id].res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d RDI:%d resource not available", + csid_hw->hw_intf->hw_idx, + cid_reserv->res_id); + rc = -EINVAL; + goto end; + } + break; + default: + CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } + + rc = cam_ife_csid_cid_get(csid_hw, + &cid_reserv->node_res, + cid_reserv->in_port->vc, + cid_reserv->in_port->dt, + cid_reserv->in_port->num_valid_vc_dt); + if (rc) { + CAM_ERR(CAM_ISP, "CSID:%d CID Reserve failed res_type %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->res_type); + goto end; + } + cid_data = (struct cam_ife_csid_cid_data *) + cid_reserv->node_res->res_priv; + + if (!csid_hw->csi2_reserve_cnt) { + csid_hw->res_type = cid_reserv->in_port->res_type; + + csid_hw->csi2_rx_cfg.lane_cfg = + cid_reserv->in_port->lane_cfg; + csid_hw->csi2_rx_cfg.lane_type = + cid_reserv->in_port->lane_type; + csid_hw->csi2_rx_cfg.lane_num = + cid_reserv->in_port->lane_num; + + if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { + csid_hw->csi2_rx_cfg.phy_sel = 0; + if (cid_reserv->in_port->format > + CAM_FORMAT_MIPI_RAW_16) { + CAM_ERR(CAM_ISP, " Wrong TPG format"); + rc = -EINVAL; + goto end; + } + csid_hw->tpg_cfg.in_format = + cid_reserv->in_port->format; + csid_hw->tpg_cfg.usage_type = + cid_reserv->in_port->usage_type; + if (cid_reserv->in_port->usage_type) + csid_hw->tpg_cfg.width = + (cid_reserv->in_port->right_stop + 1); + else + csid_hw->tpg_cfg.width = + cid_reserv->in_port->left_width; + + csid_hw->tpg_cfg.height = cid_reserv->in_port->height; + csid_hw->tpg_cfg.test_pattern = + cid_reserv->in_port->test_pattern; + + CAM_DBG(CAM_ISP, "CSID:%d TPG width:%d height:%d", + csid_hw->hw_intf->hw_idx, + csid_hw->tpg_cfg.width, + csid_hw->tpg_cfg.height); + + cid_data->tpg_set = 1; + } else { + csid_hw->csi2_rx_cfg.phy_sel = + (cid_reserv->in_port->res_type & 0xFF) - 1; + } + } + + csid_hw->csi2_reserve_cnt++; + CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired", + csid_hw->hw_intf->hw_idx, + cid_reserv->node_res->res_id); + +end: + return rc; +} + + +static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, + struct cam_csid_hw_reserve_resource_args *reserve) +{ + int rc = 0, i; + struct cam_ife_csid_path_cfg *path_data; + struct cam_isp_resource_node *res; + + /* CSID CSI2 v2.0 supports 31 vc */ + if (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX) { + CAM_ERR(CAM_ISP, "CSID: %d Sync Mode: %d", + reserve->sync_mode); + return -EINVAL; + } + + for (i = 0; i < reserve->in_port->num_valid_vc_dt; i++) { + if (reserve->in_port->dt[i] > 0x3f || + reserve->in_port->vc[i] > 0x1f) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d", + csid_hw->hw_intf->hw_idx, + reserve->in_port->vc, reserve->in_port->dt); + rc = -EINVAL; + goto end; + } + } + + switch (reserve->res_id) { + case CAM_IFE_PIX_PATH_RES_IPP: + if (csid_hw->ipp_res.res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d IPP resource not available %d", + csid_hw->hw_intf->hw_idx, + csid_hw->ipp_res.res_state); + rc = -EINVAL; + goto end; + } + + if (cam_ife_csid_is_ipp_ppp_format_supported( + reserve->in_port->format)) { + CAM_ERR(CAM_ISP, + "CSID:%d res id:%d un support format %d", + csid_hw->hw_intf->hw_idx, reserve->res_id, + reserve->in_port->format); + rc = -EINVAL; + goto end; + } + + /* assign the IPP resource */ + res = &csid_hw->ipp_res; + CAM_DBG(CAM_ISP, + "CSID:%d IPP resource:%d acquired successfully", + csid_hw->hw_intf->hw_idx, res->res_id); + + break; + case CAM_IFE_PIX_PATH_RES_PPP: + if (csid_hw->ppp_res.res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d PPP resource not available %d", + csid_hw->hw_intf->hw_idx, + csid_hw->ppp_res.res_state); + rc = -EINVAL; + goto end; + } + + if (cam_ife_csid_is_ipp_ppp_format_supported( + reserve->in_port->format)) { + CAM_ERR(CAM_ISP, + "CSID:%d res id:%d unsupported format %d", + csid_hw->hw_intf->hw_idx, reserve->res_id, + reserve->in_port->format); + rc = -EINVAL; + goto end; + } + + /* assign the PPP resource */ + res = &csid_hw->ppp_res; + CAM_DBG(CAM_ISP, + "CSID:%d PPP resource:%d acquired successfully", + csid_hw->hw_intf->hw_idx, res->res_id); + + break; + case CAM_IFE_PIX_PATH_RES_RDI_0: + case CAM_IFE_PIX_PATH_RES_RDI_1: + case CAM_IFE_PIX_PATH_RES_RDI_2: + case CAM_IFE_PIX_PATH_RES_RDI_3: + if (csid_hw->rdi_res[reserve->res_id].res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d RDI:%d resource not available %d", + csid_hw->hw_intf->hw_idx, + reserve->res_id, + csid_hw->rdi_res[reserve->res_id].res_state); + rc = -EINVAL; + goto end; + } else { + res = &csid_hw->rdi_res[reserve->res_id]; + CAM_DBG(CAM_ISP, + "CSID:%d RDI resource:%d acquire success", + csid_hw->hw_intf->hw_idx, + res->res_id); + } + + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id:%d", + csid_hw->hw_intf->hw_idx, reserve->res_id); + rc = -EINVAL; + goto end; + } + + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + path_data = (struct cam_ife_csid_path_cfg *)res->res_priv; + + path_data->cid = reserve->cid; + path_data->in_format = reserve->in_port->format; + path_data->out_format = reserve->out_port->format; + path_data->sync_mode = reserve->sync_mode; + path_data->height = reserve->in_port->height; + path_data->start_line = reserve->in_port->line_start; + path_data->end_line = reserve->in_port->line_stop; + path_data->crop_enable = reserve->crop_enable; + + CAM_DBG(CAM_ISP, + "Res id: %d height:%d line_start %d line_stop %d crop_en %d", + reserve->res_id, reserve->in_port->height, + reserve->in_port->line_start, reserve->in_port->line_stop, + path_data->crop_enable); + + if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { + path_data->dt = CAM_IFE_CSID_TPG_DT_VAL; + path_data->vc = CAM_IFE_CSID_TPG_VC_VAL; + } else { + path_data->dt = reserve->in_port->dt[0]; + path_data->vc = reserve->in_port->vc[0]; + if (reserve->in_port->num_valid_vc_dt) { + path_data->dt1 = reserve->in_port->dt[1]; + path_data->vc1 = reserve->in_port->vc[1]; + path_data->is_valid_vc1_dt1 = 1; + } + } + + if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { + path_data->start_pixel = reserve->in_port->left_start; + path_data->end_pixel = reserve->in_port->left_stop; + path_data->width = reserve->in_port->left_width; + CAM_DBG(CAM_ISP, "CSID:%d master:startpixel 0x%x endpixel:0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_pixel, + path_data->end_pixel); + CAM_DBG(CAM_ISP, "CSID:%d master:line start:0x%x line end:0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_line, + path_data->end_line); + } else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { + path_data->master_idx = reserve->master_idx; + CAM_DBG(CAM_ISP, "CSID:%d master_idx=%d", + csid_hw->hw_intf->hw_idx, path_data->master_idx); + path_data->start_pixel = reserve->in_port->right_start; + path_data->end_pixel = reserve->in_port->right_stop; + path_data->width = reserve->in_port->right_width; + CAM_DBG(CAM_ISP, "CSID:%d slave:start:0x%x end:0x%x width 0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_pixel, + path_data->end_pixel, path_data->width); + CAM_DBG(CAM_ISP, "CSID:%d slave:line start:0x%x line end:0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_line, + path_data->end_line); + } else { + path_data->width = reserve->in_port->left_width; + path_data->start_pixel = reserve->in_port->left_start; + path_data->end_pixel = reserve->in_port->left_stop; + CAM_DBG(CAM_ISP, "Res id: %d left width %d start: %d stop:%d", + reserve->res_id, reserve->in_port->left_width, + reserve->in_port->left_start, + reserve->in_port->left_stop); + } + + CAM_DBG(CAM_ISP, "Res %d width %d height %d", reserve->res_id, + path_data->width, path_data->height); + reserve->node_res = res; + +end: + return rc; +} + +static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) +{ + int rc = 0; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t i, val, clk_lvl; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + /* overflow check before increment */ + if (csid_hw->hw_info->open_count == UINT_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Open count reached max", + csid_hw->hw_intf->hw_idx); + return -EINVAL; + } + + /* Increment ref Count */ + csid_hw->hw_info->open_count++; + if (csid_hw->hw_info->open_count > 1) { + CAM_DBG(CAM_ISP, "CSID hw has already been enabled"); + return rc; + } + + CAM_DBG(CAM_ISP, "CSID:%d init CSID HW", + csid_hw->hw_intf->hw_idx); + + clk_lvl = cam_soc_util_get_vote_level(soc_info, csid_hw->clk_rate); + CAM_DBG(CAM_ISP, "CSID clock lvl %u", clk_lvl); + + rc = cam_ife_csid_enable_soc_resources(soc_info, clk_lvl); + if (rc) { + CAM_ERR(CAM_ISP, "CSID:%d Enable SOC failed", + csid_hw->hw_intf->hw_idx); + goto err; + } + + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP; + /* Reset CSID top */ + rc = cam_ife_csid_global_reset(csid_hw); + if (rc) + goto disable_soc; + + /* clear all interrupts */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + + cam_io_w_mb(csid_reg->csi2_reg->csi2_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); + + if (csid_reg->cmn_reg->num_pix) + cam_io_w_mb(csid_reg->cmn_reg->ipp_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); + + if (csid_reg->cmn_reg->num_ppp) + cam_io_w_mb(csid_reg->cmn_reg->ppp_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_clear_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + cam_io_w_mb(csid_reg->cmn_reg->rdi_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_hw_version_addr); + CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + return 0; + +disable_soc: + cam_ife_csid_disable_soc_resources(soc_info); + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; +err: + csid_hw->hw_info->open_count--; + return rc; +} + +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) { + CAM_WARN(CAM_ISP, "Unbalanced disable_hw"); + return rc; + } + + /* Decrement ref Count */ + csid_hw->hw_info->open_count--; + + if (csid_hw->hw_info->open_count) { + rc = 0; + return rc; + } + + soc_info = &csid_hw->hw_info->soc_info; + csid_reg = csid_hw->csid_info->csid_reg; + + CAM_DBG(CAM_ISP, "%s:Calling Global Reset\n", __func__); + cam_ife_csid_global_reset(csid_hw); + CAM_DBG(CAM_ISP, "%s:Global Reset Done\n", __func__); + + CAM_DBG(CAM_ISP, "CSID:%d De-init CSID HW", + csid_hw->hw_intf->hw_idx); + + /*disable the top IRQ interrupt */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); + + rc = cam_ife_csid_disable_soc_resources(soc_info); + if (rc) + 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; + + return rc; +} + + +static int cam_ife_csid_tpg_start(struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + uint32_t val = 0; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg = NULL; + + csid_hw->tpg_start_cnt++; + if (csid_hw->tpg_start_cnt == 1) { + /*Enable the TPG */ + CAM_DBG(CAM_ISP, "CSID:%d start CSID TPG", + csid_hw->hw_intf->hw_idx); + + soc_info = &csid_hw->hw_info->soc_info; + { + uint32_t val; + uint32_t i; + uint32_t base = 0x600; + + CAM_DBG(CAM_ISP, "================ TPG ============"); + for (i = 0; i < 16; i++) { + val = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + base + i * 4); + CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", + (base + i*4), val); + } + + CAM_DBG(CAM_ISP, "================ IPP ============="); + base = 0x200; + for (i = 0; i < 10; i++) { + val = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + base + i * 4); + CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", + (base + i*4), val); + } + + CAM_DBG(CAM_ISP, "================ RX ============="); + base = 0x100; + for (i = 0; i < 5; i++) { + val = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + base + i * 4); + CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", + (base + i*4), val); + } + } + + /* Enable the IFE force clock on for dual isp case */ + csid_reg = csid_hw->csid_info->csid_reg; + if (csid_hw->tpg_cfg.usage_type) { + rc = cam_ife_csid_enable_ife_force_clock_on(soc_info, + csid_reg->tpg_reg->tpg_cpas_ife_reg_offset); + if (rc) + return rc; + } + + CAM_DBG(CAM_ISP, "============ TPG control ============"); + val = (4 << 20); + val |= (0x80 << 8); + val |= (((csid_hw->csi2_rx_cfg.lane_num - 1) & 0x3) << 4); + val |= 7; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_ctrl_addr); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + 0x600); + CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", 0x600, val); + } + + return 0; +} + +static int cam_ife_csid_tpg_stop(struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg = NULL; + + if (csid_hw->tpg_start_cnt) + csid_hw->tpg_start_cnt--; + + if (csid_hw->tpg_start_cnt) + return 0; + + soc_info = &csid_hw->hw_info->soc_info; + csid_reg = csid_hw->csid_info->csid_reg; + + /* disable the TPG */ + if (!csid_hw->tpg_start_cnt) { + CAM_DBG(CAM_ISP, "CSID:%d stop CSID TPG", + csid_hw->hw_intf->hw_idx); + + /* Disable the IFE force clock on for dual isp case */ + if (csid_hw->tpg_cfg.usage_type) + rc = cam_ife_csid_disable_ife_force_clock_on(soc_info, + csid_reg->tpg_reg->tpg_cpas_ife_reg_offset); + + /*stop the TPG */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_hw->csid_info->csid_reg->tpg_reg->csid_tpg_ctrl_addr); + } + + return 0; +} + + +static int cam_ife_csid_config_tpg(struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t val = 0; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + CAM_DBG(CAM_ISP, "CSID:%d TPG config", + csid_hw->hw_intf->hw_idx); + + /* configure one DT, infinite frames */ + val = (0 << 16) | (1 << 10) | CAM_IFE_CSID_TPG_VC_VAL; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_vc_cfg0_addr); + + /* vertical blanking count = 0x3FF, horzontal blanking count = 0x740*/ + val = (0x3FF << 12) | 0x740; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_vc_cfg1_addr); + + cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base + + csid_hw->csid_info->csid_reg->tpg_reg->csid_tpg_lfsr_seed_addr); + + val = csid_hw->tpg_cfg.width << 16 | + csid_hw->tpg_cfg.height; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_dt_n_cfg_0_addr); + + cam_io_w_mb(CAM_IFE_CSID_TPG_DT_VAL, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_dt_n_cfg_1_addr); + + /* + * in_format is the same as the input resource format. + * it is one larger than the register spec format. + */ + val = ((csid_hw->tpg_cfg.in_format - 1) << 16) | 0x8; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_dt_n_cfg_2_addr); + + /* static frame with split color bar */ + val = 1 << 5; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_color_bars_cfg_addr); + /* config pix pattern */ + cam_io_w_mb(csid_hw->tpg_cfg.test_pattern, + soc_info->reg_map[0].mem_base + + csid_reg->tpg_reg->csid_tpg_common_gen_cfg_addr); + + return 0; +} + +static int cam_ife_csid_enable_csi2( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_ife_csid_cid_data *cid_data; + uint32_t val = 0; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + CAM_DBG(CAM_ISP, "CSID:%d count:%d config csi2 rx", + csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt); + + /* overflow check before increment */ + if (csid_hw->csi2_cfg_cnt == UINT_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Open count reached max", + csid_hw->hw_intf->hw_idx); + return -EINVAL; + } + + cid_data = (struct cam_ife_csid_cid_data *)res->res_priv; + + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + csid_hw->csi2_cfg_cnt++; + if (csid_hw->csi2_cfg_cnt > 1) + 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 & + 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); + + /* rx cfg1*/ + val = (1 << csid_reg->csi2_reg->csi2_misr_enable_shift_val); + /* if VC value is more than 3 than set full width of VC */ + if (cid_data->vc > 3 || (cid_data->is_valid_vc1_dt1 && + cid_data->vc1 > 3)) + val |= (1 << csid_reg->csi2_reg->csi2_vc_mode_shift_val); + + /* enable packet ecc correction */ + val |= 1; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + + if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG) { + /* Config the TPG */ + rc = cam_ife_csid_config_tpg(csid_hw, res); + if (rc) { + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; + } + } + + /*Enable the CSI2 rx inerrupts */ + val = CSID_CSI2_RX_INFO_RST_DONE | + CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION | + CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION | + CSID_CSI2_RX_ERROR_CRC | + CSID_CSI2_RX_ERROR_ECC | + CSID_CSI2_RX_ERROR_MMAPPED_VC_DT | + CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW | + CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME | + CSID_CSI2_RX_ERROR_CPHY_PH_CRC; + + /* Enable the interrupt based on csid debug info set */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOT_IRQ) + val |= CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) + val |= CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val |= CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED; + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + return 0; +} + +static int cam_ife_csid_disable_csi2( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + + if (res->res_id >= CAM_IFE_CSID_CID_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id :%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + CAM_DBG(CAM_ISP, "CSID:%d cnt : %d Disable csi2 rx", + csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt); + + if (csid_hw->csi2_cfg_cnt) + csid_hw->csi2_cfg_cnt--; + + if (csid_hw->csi2_cfg_cnt) + return 0; + + /* Disable the CSI2 rx inerrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + /* Reset the Rx CFG registers */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + return 0; +} + +static void cam_ife_csid_halt_csi2( + struct cam_ife_csid_hw *csid_hw) +{ + 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; + CAM_INFO(CAM_ISP, "CSID: %d cnt: %d Halt csi2 rx", + csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt); + + /* Disable the CSI2 rx inerrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + /* Reset the Rx CFG registers */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); +} + +static int cam_ife_csid_init_config_pxl_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + struct cam_ife_csid_path_cfg *path_data; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; + bool is_ipp; + uint32_t decode_format = 0, plain_format = 0, val = 0; + uint32_t camera_hw_version; + + path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + is_ipp = true; + pxl_reg = csid_reg->ipp_reg; + } else { + is_ipp = false; + pxl_reg = csid_reg->ppp_reg; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d %s:%d is not supported on HW", + csid_hw->hw_intf->hw_idx, + (is_ipp) ? "IPP" : "PPP", res->res_id); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Config %s Path", (is_ipp) ? "IPP" : "PPP"); + rc = cam_ife_csid_get_format_ipp_ppp(path_data->in_format, + &decode_format, &plain_format); + if (rc) + return rc; + + /* + * configure Pxl path and enable the time stamp capture. + * enable the HW measrurement blocks + */ + val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | + (decode_format << csid_reg->cmn_reg->fmt_shift_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_h_en_shift_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_v_en_shift_val) | + (1 << 1) | 1; + + val |= (1 << pxl_reg->pix_store_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + camera_hw_version = 0; + } + CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); + + if (path_data->is_valid_vc1_dt1 && + camera_hw_version == CAM_CPAS_TITAN_480_V100) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_multi_vcdt_cfg0_addr); + val |= ((path_data->vc1 << 2) | + (path_data->dt1 << 7) | 1); + } + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg1_addr); + + /* select the post irq sub sample strobe for time stamp capture */ + val |= CSID_TIMESTAMP_STB_POST_IRQ; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg1_addr); + + if (path_data->crop_enable) { + val = (((path_data->end_pixel & 0xFFFF) << + csid_reg->cmn_reg->crop_shift) | + (path_data->start_pixel & 0xFFFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_hcrop_addr); + CAM_DBG(CAM_ISP, "CSID:%d Horizontal crop config val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + val = (((path_data->end_line & 0xFFFF) << + csid_reg->cmn_reg->crop_shift) | + (path_data->start_line & 0xFFFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_vcrop_addr); + CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + /* Enable generating early eof strobe based on crop config */ + if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + val |= (1 << pxl_reg->early_eof_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + } + } + + /* set frame drop pattern to 0 and period to 1 */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_frm_drop_period_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_frm_drop_pattern_addr); + /* set irq sub sample pattern to 0 and period to 1 */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_subsample_period_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_subsample_pattern_addr); + /* set pxl drop pattern to 0 and period to 1 */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_pix_drop_pattern_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_pix_drop_period_addr); + /* set line drop pattern to 0 and period to 1 */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_line_drop_pattern_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_line_drop_period_addr); + + + /* Enable the Pxl path */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) + val |= csid_reg->cmn_reg->format_measure_en_val; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + + /* Enable Error Detection */ + if (pxl_reg->overflow_ctrl_en) { + val = pxl_reg->overflow_ctrl_en; + /* Overflow ctrl mode: 2 -> Detect overflow */ + val |= 0x8; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_err_recovery_cfg0_addr); + } + + /* Enable the HBI/VBI counter */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + } + + /* configure the rx packet capture based on csid debug set */ + val = 0; + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val = ((1 << + csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr); + CAM_DBG(CAM_ISP, "rx capture control value 0x%x", val); + + res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; + + return rc; +} + +static int cam_ife_csid_deinit_pxl_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + uint32_t val; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; + bool is_ipp; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + is_ipp = true; + pxl_reg = csid_reg->ipp_reg; + } else { + is_ipp = false; + pxl_reg = csid_reg->ppp_reg; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { + CAM_ERR(CAM_ISP, + "CSID:%d %s Res type %d res_id:%d in wrong state %d", + csid_hw->hw_intf->hw_idx, + (is_ipp) ? "IPP" : "PPP", + res->res_type, res->res_id, res->res_state); + rc = -EINVAL; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d %s %d is not supported on HW", + csid_hw->hw_intf->hw_idx, (is_ipp) ? "IPP" : "PPP", + res->res_id); + rc = -EINVAL; + goto end; + } + + /* Disable Error Recovery */ + if (pxl_reg->overflow_ctrl_en) + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_err_recovery_cfg0_addr); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + if (val & csid_reg->cmn_reg->format_measure_en_val) { + val &= ~csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + + /* Disable the HBI/VBI counter */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + } + +end: + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_ife_csid_enable_pxl_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_ife_csid_path_cfg *path_data; + const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; + bool is_ipp; + uint32_t val = 0; + + path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + is_ipp = true; + pxl_reg = csid_reg->ipp_reg; + } else { + is_ipp = false; + pxl_reg = csid_reg->ppp_reg; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { + CAM_ERR(CAM_ISP, + "CSID:%d %s path res type:%d res_id:%d Invalid state%d", + csid_hw->hw_intf->hw_idx, + (is_ipp) ? "IPP" : "PPP", + res->res_type, res->res_id, res->res_state); + return -EINVAL; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d %s %d not supported on HW", + csid_hw->hw_intf->hw_idx, (is_ipp) ? "IPP" : "PPP", + res->res_id); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Enable %s path", (is_ipp) ? "IPP" : "PPP"); + + /* Set master or slave path */ + if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) + /*Set halt mode as master */ + val = CSID_HALT_MODE_MASTER << 2; + else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + /*Set halt mode as slave and set master idx */ + val = path_data->master_idx << 4 | CSID_HALT_MODE_SLAVE << 2; + else + /* Default is internal halt mode */ + val = 0; + + /* + * Resume at frame boundary if Master or No Sync. + * Slave will get resume command from Master. + */ + if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || + path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) + val |= CAM_CSID_RESUME_AT_FRAME_BOUNDARY; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + + CAM_DBG(CAM_ISP, "CSID:%d %s Ctrl val: 0x%x", + csid_hw->hw_intf->hw_idx, + (is_ipp) ? "IPP" : "PPP", val); + + /* 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 (pxl_reg->overflow_ctrl_en) + val |= CSID_PATH_OVERFLOW_RECOVERY; + + 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) + val |= CSID_PATH_INFO_INPUT_EOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + + CAM_DBG(CAM_ISP, "Enable %s IRQ mask 0x%x", + (is_ipp) ? "IPP" : "PPP", val); + + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + +static int cam_ife_csid_disable_pxl_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res, + 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; + const struct cam_ife_csid_pxl_reg_offset *pxl_reg; + bool is_ipp; + + path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return rc; + } + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + is_ipp = true; + pxl_reg = csid_reg->ipp_reg; + } else { + is_ipp = false; + pxl_reg = csid_reg->ppp_reg; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_DBG(CAM_ISP, "CSID:%d %s path Res:%d Invalid state%d", + csid_hw->hw_intf->hw_idx, (is_ipp) ? "IPP" : "PPP", + res->res_id, res->res_state); + return -EINVAL; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d %s %d is not supported on HW", + csid_hw->hw_intf->hw_idx, (is_ipp) ? "IPP" : "PPP", + res->res_id); + return -EINVAL; + } + + if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY && + stop_cmd != CAM_CSID_HALT_IMMEDIATELY) { + CAM_ERR(CAM_ISP, "CSID:%d %s path un supported stop command:%d", + csid_hw->hw_intf->hw_idx, (is_ipp) ? "IPP" : "PPP", + stop_cmd); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id:%d %s path", + csid_hw->hw_intf->hw_idx, res->res_id, + (is_ipp) ? "IPP" : "PPP"); + + 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; +} + +static int cam_ife_csid_init_config_rdi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + struct cam_ife_csid_path_cfg *path_data; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t path_format = 0, plain_fmt = 0, val = 0, id; + uint32_t format_measure_addr; + uint32_t camera_hw_version; + + path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + id = res->res_id; + if (!csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d RDI:%d is not supported on HW", + csid_hw->hw_intf->hw_idx, id); + return -EINVAL; + } + + rc = cam_ife_csid_get_format_rdi(path_data->in_format, + path_data->out_format, &path_format, &plain_fmt); + if (rc) + return rc; + + /* if path decode format is payload only then RDI crop is not applied */ + if (path_format == 0xF) + path_data->crop_enable = 0; + + /* + * RDI path config and enable the time stamp capture + * Enable the measurement blocks + */ + val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | + (path_format << csid_reg->cmn_reg->fmt_shift_val) | + (plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_h_en_shift_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_v_en_shift_val) | + (1 << 2) | 3; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + camera_hw_version = 0; + } + CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); + + if (path_data->is_valid_vc1_dt1 && + camera_hw_version == CAM_CPAS_TITAN_480_V100) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_multi_vcdt_cfg0_addr); + val |= ((path_data->vc1 << 2) | + (path_data->dt1 << 7) | 1); + } + + /* select the post irq sub sample strobe for time stamp capture */ + cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr); + + if (path_data->crop_enable) { + val = (((path_data->end_pixel & 0xFFFF) << + csid_reg->cmn_reg->crop_shift) | + (path_data->start_pixel & 0xFFFF)); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_hcrop_addr); + CAM_DBG(CAM_ISP, "CSID:%d Horizontal crop config val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + val = (((path_data->end_line & 0xFFFF) << + csid_reg->cmn_reg->crop_shift) | + (path_data->start_line & 0xFFFF)); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_vcrop_addr); + CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + } + + /* Enable Error Detection */ + if (csid_reg->rdi_reg[id]->overflow_ctrl_en) { + val = csid_reg->rdi_reg[id]->overflow_ctrl_en; + /* Overflow ctrl mode: 2 -> Detect overflow */ + val |= 0x8; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_err_recovery_cfg0_addr); + } + + /* set frame drop pattern to 0 and period to 1 */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_frm_drop_period_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_frm_drop_pattern_addr); + /* set IRQ sum sabmple */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_subsample_period_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_subsample_pattern_addr); + + /* set pixel drop pattern to 0 and period to 1 */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_pattern_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_period_addr); + /* set line drop pattern to 0 and period to 1 */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_line_drop_pattern_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_line_drop_period_addr); + + /* Configure the halt mode */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + + /* Enable the RPP path */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) + val |= csid_reg->cmn_reg->format_measure_en_val; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + + format_measure_addr = + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr; + + /* Enable the HBI/VBI counter */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + format_measure_addr); + val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + format_measure_addr); + } + + /* configure the rx packet capture based on csid debug set */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val = ((1 << + csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; + + return rc; +} + +static int cam_ife_csid_deinit_rdi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + uint32_t id, val, format_measure_addr; + 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; + id = res->res_id; + + if (res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3 || + res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW || + !csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, + res->res_state); + return -EINVAL; + } + + /* Disable Error Recovery */ + if (csid_reg->rdi_reg[id]->overflow_ctrl_en) { + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_err_recovery_cfg0_addr); + } + + format_measure_addr = + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + val &= ~csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + + /* Disable the HBI/VBI counter */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + format_measure_addr); + val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + format_measure_addr); + } + + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_ife_csid_enable_rdi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t id, val; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + id = res->res_id; + + if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3 || + !csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, + "CSID:%d invalid res type:%d res_id:%d state%d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + return -EINVAL; + } + + /*resume at frame boundary */ + cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + + /* 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_reg->rdi_reg[id]->overflow_ctrl_en) + val |= CSID_PATH_OVERFLOW_RECOVERY; + + 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) + val |= CSID_PATH_INFO_INPUT_EOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + + +static int cam_ife_csid_disable_rdi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res, + enum cam_ife_csid_halt_cmd stop_cmd) +{ + int rc = 0; + uint32_t id, val = 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; + id = res->res_id; + + if ((res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3) || + (!csid_reg->rdi_reg[res->res_id])) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d Res:%d already in stopped state:%d", + csid_hw->hw_intf->hw_idx, + res->res_id, res->res_state); + return rc; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d Res:%d Invalid res_state%d", + csid_hw->hw_intf->hw_idx, res->res_id, + res->res_state); + return -EINVAL; + } + + if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY && + stop_cmd != CAM_CSID_HALT_IMMEDIATELY) { + CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d", + csid_hw->hw_intf->hw_idx, stop_cmd); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_id); + + 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; +} + +static int cam_ife_csid_get_hbi_vbi( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + uint32_t hbi, vbi; + const struct cam_ife_csid_reg_offset *csid_reg; + const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + struct cam_hw_soc_info *soc_info; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH || + res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_format_measure1_addr); + vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_format_measure2_addr); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { + hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_format_measure1_addr); + vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_format_measure2_addr); + } else { + rdi_reg = csid_reg->rdi_reg[res->res_id]; + hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure1_addr); + vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure2_addr); + } + + 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; +} + + +static int cam_ife_csid_get_time_stamp( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_csid_get_time_stamp_args *time_stamp; + struct cam_isp_resource_node *res; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + struct timespec64 ts; + uint32_t time_32, id; + + time_stamp = (struct cam_csid_get_time_stamp_args *)cmd_args; + res = time_stamp->node_res; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH || + res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_timestamp_curr1_sof_addr); + time_stamp->time_stamp_val = (uint64_t) time_32; + time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_timestamp_curr0_sof_addr); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_timestamp_curr1_sof_addr); + time_stamp->time_stamp_val = (uint64_t) time_32; + time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_timestamp_curr0_sof_addr); + } else { + id = res->res_id; + rdi_reg = csid_reg->rdi_reg[id]; + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_timestamp_curr1_sof_addr); + time_stamp->time_stamp_val = (uint64_t) time_32; + time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; + + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_timestamp_curr0_sof_addr); + } + + time_stamp->time_stamp_val |= (uint64_t) time_32; + time_stamp->time_stamp_val = mul_u64_u32_div( + time_stamp->time_stamp_val, + CAM_IFE_CSID_QTIMER_MUL_FACTOR, + CAM_IFE_CSID_QTIMER_DIV_FACTOR); + + get_monotonic_boottime64(&ts); + time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + + return 0; +} + +static int cam_ife_csid_set_csid_debug(struct cam_ife_csid_hw *csid_hw, + void *cmd_args) +{ + uint32_t *csid_debug; + + csid_debug = (uint32_t *) cmd_args; + csid_hw->csid_debug = *csid_debug; + CAM_DBG(CAM_ISP, "CSID:%d set csid debug value:%d", + csid_hw->hw_intf->hw_idx, csid_hw->csid_debug); + + return 0; +} + +static int cam_ife_csid_get_hw_caps(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw_caps *hw_caps; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + const struct cam_ife_csid_reg_offset *csid_reg; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + csid_reg = csid_hw->csid_info->csid_reg; + hw_caps = (struct cam_ife_csid_hw_caps *) get_hw_cap_args; + + hw_caps->num_rdis = csid_reg->cmn_reg->num_rdis; + hw_caps->num_pix = csid_reg->cmn_reg->num_pix; + hw_caps->num_ppp = csid_reg->cmn_reg->num_ppp; + hw_caps->major_version = csid_reg->cmn_reg->major_version; + hw_caps->minor_version = csid_reg->cmn_reg->minor_version; + hw_caps->version_incr = csid_reg->cmn_reg->version_incr; + + CAM_DBG(CAM_ISP, + "CSID:%d No rdis:%d, no pix:%d, major:%d minor:%d ver :%d", + csid_hw->hw_intf->hw_idx, hw_caps->num_rdis, + hw_caps->num_pix, hw_caps->major_version, + hw_caps->minor_version, hw_caps->version_incr); + + return rc; +} + +static int cam_ife_csid_reset(void *hw_priv, + void *reset_args, uint32_t arg_size) +{ + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_csid_reset_cfg_args *reset; + int rc = 0; + + if (!hw_priv || !reset_args || (arg_size != + sizeof(struct cam_csid_reset_cfg_args))) { + CAM_ERR(CAM_ISP, "CSID:Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + reset = (struct cam_csid_reset_cfg_args *)reset_args; + + switch (reset->reset_type) { + case CAM_IFE_CSID_RESET_GLOBAL: + rc = cam_ife_csid_global_reset(csid_hw); + break; + case CAM_IFE_CSID_RESET_PATH: + rc = cam_ife_csid_path_reset(csid_hw, reset); + break; + default: + CAM_ERR(CAM_ISP, "CSID:Invalid reset type :%d", + reset->reset_type); + rc = -EINVAL; + break; + } + + return rc; +} + +static int cam_ife_csid_reserve(void *hw_priv, + void *reserve_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_csid_hw_reserve_resource_args *reserv; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_csid_hw_reserve_resource_args))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + reserv = (struct cam_csid_hw_reserve_resource_args *)reserve_args; + + CAM_DBG(CAM_ISP, "res_type %d, CSID: %u", + reserv->res_type, csid_hw->hw_intf->hw_idx); + + mutex_lock(&csid_hw->hw_info->hw_mutex); + switch (reserv->res_type) { + case CAM_ISP_RESOURCE_CID: + rc = cam_ife_csid_cid_reserve(csid_hw, reserv); + break; + case CAM_ISP_RESOURCE_PIX_PATH: + rc = cam_ife_csid_path_reserve(csid_hw, reserv); + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type :%d", + csid_hw->hw_intf->hw_idx, reserv->res_type); + rc = -EINVAL; + break; + } + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_ife_csid_release(void *hw_priv, + void *release_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + struct cam_ife_csid_cid_data *cid_data; + + if (!hw_priv || !release_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + res = (struct cam_isp_resource_node *)release_args; + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if ((res->res_type == CAM_ISP_RESOURCE_CID && + res->res_id >= CAM_IFE_CSID_CID_MAX) || + (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && + res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + goto end; + } + + if ((res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE) || + (res->res_state >= CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_WARN(CAM_ISP, + "CSID:%d res type:%d Res %d in state %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, + res->res_state); + goto end; + } + + CAM_DBG(CAM_ISP, "CSID:%d res type :%d Resource id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); + + switch (res->res_type) { + case CAM_ISP_RESOURCE_CID: + cid_data = (struct cam_ife_csid_cid_data *) res->res_priv; + if (cid_data->cnt) + cid_data->cnt--; + + if (!cid_data->cnt) + res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + if (csid_hw->csi2_reserve_cnt) + csid_hw->csi2_reserve_cnt--; + + if (!csid_hw->csi2_reserve_cnt) + memset(&csid_hw->csi2_rx_cfg, 0, + sizeof(struct cam_ife_csid_csi2_rx_cfg)); + + CAM_DBG(CAM_ISP, "CSID:%d res id :%d cnt:%d reserv cnt:%d", + csid_hw->hw_intf->hw_idx, + res->res_id, cid_data->cnt, csid_hw->csi2_reserve_cnt); + + break; + case CAM_ISP_RESOURCE_PIX_PATH: + res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + break; + } + +end: + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_ife_csid_reset_retain_sw_reg( + struct cam_ife_csid_hw *csid_hw) +{ + int rc = 0; + uint32_t status; + const struct cam_ife_csid_reg_offset *csid_reg = + csid_hw->csid_info->csid_reg; + struct cam_hw_soc_info *soc_info; + + soc_info = &csid_hw->hw_info->soc_info; + /* clear the top interrupt first */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + 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; + } else { + CAM_DBG(CAM_ISP, "CSID:%d hw reset completed %d", + csid_hw->hw_intf->hw_idx, rc); + rc = 0; + } + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + return rc; +} + +static int cam_ife_csid_init_hw(void *hw_priv, + void *init_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + 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))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + res = (struct cam_isp_resource_node *)init_args; + csid_reg = csid_hw->csid_info->csid_reg; + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if ((res->res_type == CAM_ISP_RESOURCE_CID && + res->res_id >= CAM_IFE_CSID_CID_MAX) || + (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && + res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res tpe:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + goto end; + } + + if ((res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && + (res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { + CAM_ERR(CAM_ISP, + "CSID:%d res type:%d res_id:%dInvalid state %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "CSID:%d res type :%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); + + /* Initialize the csid hardware */ + rc = cam_ife_csid_enable_hw(csid_hw); + if (rc) + goto end; + + switch (res->res_type) { + case CAM_ISP_RESOURCE_CID: + rc = cam_ife_csid_enable_csi2(csid_hw, res); + break; + case CAM_ISP_RESOURCE_PIX_PATH: + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP || + res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + rc = cam_ife_csid_init_config_pxl_path(csid_hw, res); + else + rc = cam_ife_csid_init_config_rdi_path(csid_hw, res); + + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type state %d", + csid_hw->hw_intf->hw_idx, + res->res_type); + break; + } + + rc = cam_ife_csid_reset_retain_sw_reg(csid_hw); + if (rc < 0) + CAM_ERR(CAM_ISP, "CSID: Failed in SW reset"); + + 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; +} + +static int cam_ife_csid_deinit_hw(void *hw_priv, + void *deinit_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + + if (!hw_priv || !deinit_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID:Invalid arguments"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Enter"); + res = (struct cam_isp_resource_node *)deinit_args; + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if (res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in De-init state", + csid_hw->hw_intf->hw_idx, + res->res_id); + goto end; + } + + switch (res->res_type) { + case CAM_ISP_RESOURCE_CID: + CAM_DBG(CAM_ISP, "De-Init ife_csid"); + rc = cam_ife_csid_disable_csi2(csid_hw, res); + break; + case CAM_ISP_RESOURCE_PIX_PATH: + CAM_DBG(CAM_ISP, "De-Init Pix Path: %d\n", 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_deinit_pxl_path(csid_hw, res); + else + rc = cam_ife_csid_deinit_rdi_path(csid_hw, res); + + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid Res type %d", + csid_hw->hw_intf->hw_idx, + res->res_type); + goto end; + } + + /* Disable CSID HW */ + CAM_DBG(CAM_ISP, "Disabling CSID Hw\n"); + cam_ife_csid_disable_hw(csid_hw); + CAM_DBG(CAM_ISP, "%s: Exit\n", __func__); + +end: + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_ife_csid_start(void *hw_priv, void *start_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + const struct cam_ife_csid_reg_offset *csid_reg; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + res = (struct cam_isp_resource_node *)start_args; + csid_reg = csid_hw->csid_info->csid_reg; + + if ((res->res_type == CAM_ISP_RESOURCE_CID && + res->res_id >= CAM_IFE_CSID_CID_MAX) || + (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && + res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res tpe:%d res id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + goto end; + } + + /* Reset sof irq debug fields */ + csid_hw->sof_irq_triggered = false; + csid_hw->irq_debug_cnt = 0; + + CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); + + switch (res->res_type) { + case CAM_ISP_RESOURCE_CID: + if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG) + rc = cam_ife_csid_tpg_start(csid_hw, res); + break; + case CAM_ISP_RESOURCE_PIX_PATH: + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP || + res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + rc = cam_ife_csid_enable_pxl_path(csid_hw, res); + else + rc = cam_ife_csid_enable_rdi_path(csid_hw, res); + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + csid_hw->hw_intf->hw_idx, + res->res_type); + break; + } +end: + return rc; +} + +static int cam_ife_csid_stop(void *hw_priv, + void *stop_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + 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))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + csid_stop = (struct cam_csid_hw_stop_args *) stop_args; + + if (!csid_stop->num_res) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + CAM_DBG(CAM_ISP, "CSID:%d num_res %d", + csid_hw->hw_intf->hw_idx, + csid_stop->num_res); + + /* Stop the resource first */ + for (i = 0; i < csid_stop->num_res; i++) { + res = csid_stop->node_res[i]; + CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id); + switch (res->res_type) { + case CAM_ISP_RESOURCE_CID: + if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG) + 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, + res, csid_stop->stop_cmd); + else + rc = cam_ife_csid_disable_rdi_path(csid_hw, + res, csid_stop->stop_cmd); + + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + csid_hw->hw_intf->hw_idx, + res->res_type); + break; + } + } + + 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; + } + + CAM_DBG(CAM_ISP, "%s: Exit\n", __func__); + + return rc; + +} + +static int cam_ife_csid_read(void *hw_priv, + void *read_args, uint32_t arg_size) +{ + CAM_ERR(CAM_ISP, "CSID: un supported"); + + return -EINVAL; +} + +static int cam_ife_csid_write(void *hw_priv, + void *write_args, uint32_t arg_size) +{ + CAM_ERR(CAM_ISP, "CSID: un supported"); + return -EINVAL; +} + +static int cam_ife_csid_sof_irq_debug( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + int i = 0; + uint32_t val = 0; + bool sof_irq_enable = false; + 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; + + if (*((uint32_t *)cmd_args) == 1) + sof_irq_enable = true; + + if (csid_hw->hw_info->hw_state == + CAM_HW_STATE_POWER_DOWN) { + CAM_WARN(CAM_ISP, + "CSID powered down unable to %s sof irq", + (sof_irq_enable == true) ? "enable" : "disable"); + return 0; + } + + if (csid_reg->ipp_reg) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + + if (val) { + if (sof_irq_enable) + val |= CSID_PATH_INFO_INPUT_SOF; + else + val &= ~CSID_PATH_INFO_INPUT_SOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + val = 0; + } + } + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr); + if (val) { + if (sof_irq_enable) + val |= CSID_PATH_INFO_INPUT_SOF; + else + val &= ~CSID_PATH_INFO_INPUT_SOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr); + val = 0; + } + } + + if (sof_irq_enable) { + csid_hw->csid_debug |= CSID_DEBUG_ENABLE_SOF_IRQ; + csid_hw->sof_irq_triggered = true; + } else { + csid_hw->csid_debug &= ~CSID_DEBUG_ENABLE_SOF_IRQ; + csid_hw->sof_irq_triggered = false; + } + + CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s", + (sof_irq_enable == true) ? "enabled" : "disabled"); + + return 0; +} + +static int cam_ife_csid_set_csid_clock( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_csid_clock_update_args *clk_update = NULL; + + if (!csid_hw) + return -EINVAL; + + clk_update = + (struct cam_ife_csid_clock_update_args *)cmd_args; + + csid_hw->clk_rate = clk_update->clk_rate; + CAM_INFO(CAM_ISP, "CSID clock rate %llu", csid_hw->clk_rate); + + return 0; +} + +static int cam_ife_csid_process_cmd(void *hw_priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res = NULL; + + if (!hw_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + + switch (cmd_type) { + case CAM_IFE_CSID_CMD_GET_TIME_STAMP: + rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args); + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + res = ((struct cam_csid_get_time_stamp_args *) + cmd_args)->node_res; + cam_ife_csid_get_hbi_vbi(csid_hw, res); + } + break; + case CAM_IFE_CSID_SET_CSID_DEBUG: + rc = cam_ife_csid_set_csid_debug(csid_hw, cmd_args); + break; + case CAM_IFE_CSID_SOF_IRQ_DEBUG: + rc = cam_ife_csid_sof_irq_debug(csid_hw, cmd_args); + break; + case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE: + rc = cam_ife_csid_set_csid_clock(csid_hw, cmd_args); + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", + csid_hw->hw_intf->hw_idx, cmd_type); + rc = -EINVAL; + break; + } + + return rc; + +} + +irqreturn_t cam_ife_csid_irq(int irq_num, void *data) +{ + struct cam_ife_csid_hw *csid_hw; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg; + const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg; + uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0; + uint32_t irq_status_rdi[4] = {0, 0, 0, 0}; + 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; + + CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); + + if (!data) { + CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); + return IRQ_HANDLED; + } + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + csi2_reg = csid_reg->csi2_reg; + + /* read */ + irq_status_top = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_status_addr); + + irq_status_rx = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_status_addr); + + if (csid_reg->cmn_reg->num_pix) + irq_status_ipp = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_status_addr); + + if (csid_reg->cmn_reg->num_ppp) + irq_status_ppp = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_status_addr); + + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + irq_status_rdi[i] = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr); + + /* clear */ + cam_io_w_mb(irq_status_rx, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); + if (csid_reg->cmn_reg->num_pix) + cam_io_w_mb(irq_status_ipp, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); + + if (csid_reg->cmn_reg->num_ppp) + cam_io_w_mb(irq_status_ppp, soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_irq_clear_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + cam_io_w_mb(irq_status_rdi[i], soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + } + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", irq_status_top); + CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx); + CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp); + CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", irq_status_ppp); + CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x", irq_status_rdi[0]); + CAM_DBG(CAM_ISP, "irq_status_rdi1= 0x%x", irq_status_rdi[1]); + CAM_DBG(CAM_ISP, "irq_status_rdi2= 0x%x", irq_status_rdi[2]); + + if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "csi rx reset complete"); + complete(&csid_hw->csid_csi2_complete); + } + + 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) { + fatal_err_detected = true; + csid_hw->error_irq_count = 0; + } + + if (fatal_err_detected) + cam_ife_csid_halt_csi2(csid_hw); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) { + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL0_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL1_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL2_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL3_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + } + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOT_IRQ) { + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL0_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL1_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL2_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL3_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + } + + if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) && + (irq_status_rx & CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d LONG_PKT_CAPTURED", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d long packet VC :%d DT:%d WC:%d", + csid_hw->hw_intf->hw_idx, + (val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF)); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_1_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d long packet ECC :%d", + csid_hw->hw_intf->hw_idx, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_ftr_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d long pkt cal CRC:%d expected CRC:%d", + csid_hw->hw_intf->hw_idx, (val >> 16), (val & 0xFFFF)); + } + if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) && + (irq_status_rx & CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d SHORT_PKT_CAPTURED", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_short_pkt_0_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d short pkt VC :%d DT:%d LC:%d", + csid_hw->hw_intf->hw_idx, + (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_short_pkt_1_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d short packet ECC :%d", + csid_hw->hw_intf->hw_idx, val); + } + + if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) && + (irq_status_rx & CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PKT_HDR_CAPTURED", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_cphy_pkt_hdr_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d cphy packet VC :%d DT:%d WC:%d", + csid_hw->hw_intf->hw_idx, + (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + } + + /*read the IPP errors */ + if (csid_reg->cmn_reg->num_pix) { + /* IPP reset done bit */ + if (irq_status_ipp & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "CSID IPP reset complete"); + complete(&csid_hw->csid_ipp_complete); + } + + if ((irq_status_ipp & CSID_PATH_INFO_INPUT_SOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + if (csid_hw->sof_irq_triggered) + csid_hw->irq_debug_cnt++; + } + + if ((irq_status_ipp & CSID_PATH_INFO_INPUT_EOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) + 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_OVERFLOW_RECOVERY)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP Overflow due to back pressure", + 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", + csid_hw->hw_intf->hw_idx); + /* Stop IPP path immediately */ + cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_ctrl_addr); + } + } + + /*read PPP errors */ + if (csid_reg->cmn_reg->num_ppp) { + /* PPP reset done bit */ + if (irq_status_ppp & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "CSID PPP reset complete"); + complete(&csid_hw->csid_ppp_complete); + } + + if ((irq_status_ppp & CSID_PATH_INFO_INPUT_SOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP SOF received", + csid_hw->hw_intf->hw_idx); + if (csid_hw->sof_irq_triggered) + csid_hw->irq_debug_cnt++; + } + + if ((irq_status_ppp & CSID_PATH_INFO_INPUT_EOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received", + csid_hw->hw_intf->hw_idx); + + if ((irq_status_ppp & 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_OVERFLOW_RECOVERY)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP Overflow due to back pressure", + 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", + csid_hw->hw_intf->hw_idx); + /* Stop PPP path immediately */ + cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, + soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_ctrl_addr); + } + } + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + if (irq_status_rdi[i] & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i); + complete(&csid_hw->csid_rdin_complete[i]); + } + + if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_SOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID RDI:%d SOF received", i); + if (csid_hw->sof_irq_triggered) + csid_hw->irq_debug_cnt++; + } + + if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) + 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, + "CSID RDI :%d CCIF violation", i); + + if ((irq_status_rdi[i] & CSID_PATH_OVERFLOW_RECOVERY)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID RDI :%d Overflow due to back pressure", + i); + + if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RDI fifo over flow", + csid_hw->hw_intf->hw_idx); + /* Stop RDI path immediately */ + cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); + } + } + + if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { + cam_ife_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); + csid_hw->irq_debug_cnt = 0; + } + + CAM_DBG(CAM_ISP, "IRQ Handling exit"); + return IRQ_HANDLED; +} + +int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, + uint32_t csid_idx) +{ + int rc = -EINVAL; + uint32_t i; + uint32_t num_paths; + struct cam_ife_csid_path_cfg *path_data; + struct cam_ife_csid_cid_data *cid_data; + struct cam_hw_info *csid_hw_info; + struct cam_ife_csid_hw *ife_csid_hw = NULL; + + if (csid_idx >= CAM_IFE_CSID_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, "Invalid csid index:%d", csid_idx); + return rc; + } + + csid_hw_info = (struct cam_hw_info *) csid_hw_intf->hw_priv; + ife_csid_hw = (struct cam_ife_csid_hw *) csid_hw_info->core_info; + + ife_csid_hw->hw_intf = csid_hw_intf; + ife_csid_hw->hw_info = csid_hw_info; + + CAM_DBG(CAM_ISP, "type %d index %d", + 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); + init_completion(&ife_csid_hw->csid_csi2_complete); + init_completion(&ife_csid_hw->csid_ipp_complete); + init_completion(&ife_csid_hw->csid_ppp_complete); + for (i = 0; i < CAM_IFE_CSID_RDI_MAX; i++) + init_completion(&ife_csid_hw->csid_rdin_complete[i]); + + + rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info, + cam_ife_csid_irq, ife_csid_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc", csid_idx); + goto err; + } + + ife_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_ife_csid_get_hw_caps; + ife_csid_hw->hw_intf->hw_ops.init = cam_ife_csid_init_hw; + ife_csid_hw->hw_intf->hw_ops.deinit = cam_ife_csid_deinit_hw; + ife_csid_hw->hw_intf->hw_ops.reset = cam_ife_csid_reset; + ife_csid_hw->hw_intf->hw_ops.reserve = cam_ife_csid_reserve; + ife_csid_hw->hw_intf->hw_ops.release = cam_ife_csid_release; + ife_csid_hw->hw_intf->hw_ops.start = cam_ife_csid_start; + ife_csid_hw->hw_intf->hw_ops.stop = cam_ife_csid_stop; + ife_csid_hw->hw_intf->hw_ops.read = cam_ife_csid_read; + ife_csid_hw->hw_intf->hw_ops.write = cam_ife_csid_write; + ife_csid_hw->hw_intf->hw_ops.process_cmd = cam_ife_csid_process_cmd; + + num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->num_pix + + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + /* Initialize the CID resource */ + for (i = 0; i < num_paths; i++) { + ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID; + ife_csid_hw->cid_res[i].res_id = i; + ife_csid_hw->cid_res[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + ife_csid_hw->cid_res[i].hw_intf = ife_csid_hw->hw_intf; + + cid_data = kzalloc(sizeof(struct cam_ife_csid_cid_data), + GFP_KERNEL); + if (!cid_data) { + rc = -ENOMEM; + goto err; + } + ife_csid_hw->cid_res[i].res_priv = cid_data; + } + + /* Initialize the IPP resources */ + if (ife_csid_hw->csid_info->csid_reg->cmn_reg->num_pix) { + ife_csid_hw->ipp_res.res_type = CAM_ISP_RESOURCE_PIX_PATH; + ife_csid_hw->ipp_res.res_id = CAM_IFE_PIX_PATH_RES_IPP; + ife_csid_hw->ipp_res.res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + ife_csid_hw->ipp_res.hw_intf = ife_csid_hw->hw_intf; + path_data = kzalloc(sizeof(*path_data), + GFP_KERNEL); + if (!path_data) { + rc = -ENOMEM; + goto err; + } + ife_csid_hw->ipp_res.res_priv = path_data; + } + + /* Initialize PPP resource */ + if (ife_csid_hw->csid_info->csid_reg->cmn_reg->num_ppp) { + ife_csid_hw->ppp_res.res_type = CAM_ISP_RESOURCE_PIX_PATH; + ife_csid_hw->ppp_res.res_id = CAM_IFE_PIX_PATH_RES_PPP; + ife_csid_hw->ppp_res.res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + ife_csid_hw->ppp_res.hw_intf = ife_csid_hw->hw_intf; + path_data = kzalloc(sizeof(*path_data), + GFP_KERNEL); + if (!path_data) { + rc = -ENOMEM; + goto err; + } + ife_csid_hw->ppp_res.res_priv = path_data; + } + + /* Initialize the RDI resource */ + for (i = 0; i < ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + i++) { + /* res type is from RDI 0 to RDI3 */ + ife_csid_hw->rdi_res[i].res_type = + CAM_ISP_RESOURCE_PIX_PATH; + ife_csid_hw->rdi_res[i].res_id = i; + ife_csid_hw->rdi_res[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + ife_csid_hw->rdi_res[i].hw_intf = ife_csid_hw->hw_intf; + + path_data = kzalloc(sizeof(*path_data), + GFP_KERNEL); + if (!path_data) { + rc = -ENOMEM; + goto err; + } + ife_csid_hw->rdi_res[i].res_priv = path_data; + } + + ife_csid_hw->csid_debug = 0; + ife_csid_hw->error_irq_count = 0; + + return 0; +err: + if (rc) { + kfree(ife_csid_hw->ipp_res.res_priv); + kfree(ife_csid_hw->ppp_res.res_priv); + for (i = 0; i < + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + i++) + kfree(ife_csid_hw->rdi_res[i].res_priv); + + for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++) + kfree(ife_csid_hw->cid_res[i].res_priv); + + } + + return rc; +} + + +int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw) +{ + int rc = -EINVAL; + uint32_t i; + + if (!ife_csid_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return rc; + } + + /* release the privdate data memory from resources */ + kfree(ife_csid_hw->ipp_res.res_priv); + kfree(ife_csid_hw->ppp_res.res_priv); + for (i = 0; i < + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + i++) { + kfree(ife_csid_hw->rdi_res[i].res_priv); + } + for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++) + kfree(ife_csid_hw->cid_res[i].res_priv); + + cam_ife_csid_deinit_soc_resources(&ife_csid_hw->hw_info->soc_info); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h new file mode 100644 index 000000000000..a3c54fed7c03 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -0,0 +1,513 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_HW_H_ +#define _CAM_IFE_CSID_HW_H_ + +#include "cam_hw.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_ife_csid_soc.h" + +#define CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED BIT(0) +#define CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED BIT(1) +#define CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED BIT(2) +#define CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED BIT(3) +#define CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED BIT(4) +#define CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED BIT(5) +#define CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED BIT(6) +#define CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED BIT(7) +#define CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED BIT(8) +#define CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED BIT(9) +#define CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED BIT(10) +#define CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION BIT(11) +#define CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION BIT(12) +#define CSID_CSI2_RX_ERROR_CPHY_PH_CRC BIT(13) +#define CSID_CSI2_RX_WARNING_ECC BIT(14) +#define CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW BIT(15) +#define CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW BIT(16) +#define CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW BIT(17) +#define CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW BIT(18) +#define CSID_CSI2_RX_ERROR_CRC BIT(19) +#define CSID_CSI2_RX_ERROR_ECC BIT(20) +#define CSID_CSI2_RX_ERROR_MMAPPED_VC_DT BIT(21) +#define CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT BIT(22) +#define CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW BIT(23) +#define CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME BIT(24) +#define CSID_CSI2_RX_INFO_TG_DONE BIT(25) +#define CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW BIT(26) +#define CSID_CSI2_RX_INFO_RST_DONE BIT(27) + +#define CSID_PATH_INFO_RST_DONE BIT(1) +#define CSID_PATH_ERROR_FIFO_OVERFLOW BIT(2) +#define CSID_PATH_INFO_SUBSAMPLED_EOF BIT(3) +#define CSID_PATH_INFO_SUBSAMPLED_SOF BIT(4) +#define CSID_PATH_INFO_FRAME_DROP_EOF BIT(5) +#define CSID_PATH_INFO_FRAME_DROP_EOL BIT(6) +#define CSID_PATH_INFO_FRAME_DROP_SOL BIT(7) +#define CSID_PATH_INFO_FRAME_DROP_SOF BIT(8) +#define CSID_PATH_INFO_INPUT_EOF BIT(9) +#define CSID_PATH_INFO_INPUT_EOL BIT(10) +#define CSID_PATH_INFO_INPUT_SOL BIT(11) +#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) +#define CSID_PATH_OVERFLOW_RECOVERY BIT(17) + +/* + * Debug values enable the corresponding interrupts and debug logs provide + * necessary information + */ +#define CSID_DEBUG_ENABLE_SOF_IRQ BIT(0) +#define CSID_DEBUG_ENABLE_EOF_IRQ BIT(1) +#define CSID_DEBUG_ENABLE_SOT_IRQ BIT(2) +#define CSID_DEBUG_ENABLE_EOT_IRQ BIT(3) +#define CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE BIT(4) +#define CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE BIT(5) +#define CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6) +#define CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7) +#define CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) + +/* enum cam_csid_path_halt_mode select the path halt mode control */ +enum cam_csid_path_halt_mode { + CSID_HALT_MODE_INTERNAL, + CSID_HALT_MODE_GLOBAL, + CSID_HALT_MODE_MASTER, + CSID_HALT_MODE_SLAVE, +}; + +/** + *enum cam_csid_path_timestamp_stb_sel - select the sof/eof strobes used to + * capture the timestamp + */ +enum cam_csid_path_timestamp_stb_sel { + CSID_TIMESTAMP_STB_PRE_HALT, + CSID_TIMESTAMP_STB_POST_HALT, + CSID_TIMESTAMP_STB_POST_IRQ, + CSID_TIMESTAMP_STB_MAX, +}; + +struct cam_ife_csid_pxl_reg_offset { + /* Pxl path register offsets*/ + uint32_t csid_pxl_irq_status_addr; + uint32_t csid_pxl_irq_mask_addr; + uint32_t csid_pxl_irq_clear_addr; + uint32_t csid_pxl_irq_set_addr; + + uint32_t csid_pxl_cfg0_addr; + uint32_t csid_pxl_cfg1_addr; + uint32_t csid_pxl_ctrl_addr; + uint32_t csid_pxl_frm_drop_pattern_addr; + uint32_t csid_pxl_frm_drop_period_addr; + uint32_t csid_pxl_irq_subsample_pattern_addr; + uint32_t csid_pxl_irq_subsample_period_addr; + uint32_t csid_pxl_hcrop_addr; + uint32_t csid_pxl_vcrop_addr; + uint32_t csid_pxl_pix_drop_pattern_addr; + uint32_t csid_pxl_pix_drop_period_addr; + uint32_t csid_pxl_line_drop_pattern_addr; + uint32_t csid_pxl_line_drop_period_addr; + uint32_t csid_pxl_rst_strobes_addr; + uint32_t csid_pxl_status_addr; + uint32_t csid_pxl_misr_val_addr; + uint32_t csid_pxl_format_measure_cfg0_addr; + uint32_t csid_pxl_format_measure_cfg1_addr; + uint32_t csid_pxl_format_measure0_addr; + uint32_t csid_pxl_format_measure1_addr; + uint32_t csid_pxl_format_measure2_addr; + uint32_t csid_pxl_timestamp_curr0_sof_addr; + uint32_t csid_pxl_timestamp_curr1_sof_addr; + uint32_t csid_pxl_timestamp_perv0_sof_addr; + uint32_t csid_pxl_timestamp_perv1_sof_addr; + uint32_t csid_pxl_timestamp_curr0_eof_addr; + uint32_t csid_pxl_timestamp_curr1_eof_addr; + uint32_t csid_pxl_timestamp_perv0_eof_addr; + uint32_t csid_pxl_timestamp_perv1_eof_addr; + uint32_t csid_pxl_err_recovery_cfg0_addr; + uint32_t csid_pxl_err_recovery_cfg1_addr; + uint32_t csid_pxl_err_recovery_cfg2_addr; + uint32_t csid_pxl_multi_vcdt_cfg0_addr; + + /* 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; + uint32_t overflow_ctrl_en; +}; + +struct cam_ife_csid_rdi_reg_offset { + uint32_t csid_rdi_irq_status_addr; + uint32_t csid_rdi_irq_mask_addr; + uint32_t csid_rdi_irq_clear_addr; + uint32_t csid_rdi_irq_set_addr; + + /*RDI N register address */ + uint32_t csid_rdi_cfg0_addr; + uint32_t csid_rdi_cfg1_addr; + uint32_t csid_rdi_ctrl_addr; + uint32_t csid_rdi_frm_drop_pattern_addr; + uint32_t csid_rdi_frm_drop_period_addr; + uint32_t csid_rdi_irq_subsample_pattern_addr; + uint32_t csid_rdi_irq_subsample_period_addr; + uint32_t csid_rdi_rpp_hcrop_addr; + uint32_t csid_rdi_rpp_vcrop_addr; + uint32_t csid_rdi_rpp_pix_drop_pattern_addr; + uint32_t csid_rdi_rpp_pix_drop_period_addr; + uint32_t csid_rdi_rpp_line_drop_pattern_addr; + uint32_t csid_rdi_rpp_line_drop_period_addr; + uint32_t csid_rdi_yuv_chroma_conversion_addr; + uint32_t csid_rdi_rst_strobes_addr; + uint32_t csid_rdi_status_addr; + uint32_t csid_rdi_misr_val0_addr; + uint32_t csid_rdi_misr_val1_addr; + uint32_t csid_rdi_misr_val2_addr; + uint32_t csid_rdi_misr_val3_addr; + uint32_t csid_rdi_format_measure_cfg0_addr; + uint32_t csid_rdi_format_measure_cfg1_addr; + uint32_t csid_rdi_format_measure0_addr; + uint32_t csid_rdi_format_measure1_addr; + uint32_t csid_rdi_format_measure2_addr; + uint32_t csid_rdi_timestamp_curr0_sof_addr; + uint32_t csid_rdi_timestamp_curr1_sof_addr; + uint32_t csid_rdi_timestamp_prev0_sof_addr; + uint32_t csid_rdi_timestamp_prev1_sof_addr; + uint32_t csid_rdi_timestamp_curr0_eof_addr; + uint32_t csid_rdi_timestamp_curr1_eof_addr; + uint32_t csid_rdi_timestamp_prev0_eof_addr; + uint32_t csid_rdi_timestamp_prev1_eof_addr; + uint32_t csid_rdi_err_recovery_cfg0_addr; + uint32_t csid_rdi_err_recovery_cfg1_addr; + uint32_t csid_rdi_err_recovery_cfg2_addr; + uint32_t csid_rdi_multi_vcdt_cfg0_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; + uint32_t overflow_ctrl_en; +}; + +struct cam_ife_csid_csi2_rx_reg_offset { + uint32_t csid_csi2_rx_irq_status_addr; + uint32_t csid_csi2_rx_irq_mask_addr; + uint32_t csid_csi2_rx_irq_clear_addr; + uint32_t csid_csi2_rx_irq_set_addr; + uint32_t csid_csi2_rx_cfg0_addr; + uint32_t csid_csi2_rx_cfg1_addr; + 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_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; + uint32_t csid_csi2_rx_captured_short_pkt_1_addr; + uint32_t csid_csi2_rx_captured_long_pkt_0_addr; + uint32_t csid_csi2_rx_captured_long_pkt_1_addr; + uint32_t csid_csi2_rx_captured_long_pkt_ftr_addr; + uint32_t csid_csi2_rx_captured_cphy_pkt_hdr_addr; + uint32_t csid_csi2_rx_lane0_misr_addr; + uint32_t csid_csi2_rx_lane1_misr_addr; + uint32_t csid_csi2_rx_lane2_misr_addr; + uint32_t csid_csi2_rx_lane3_misr_addr; + 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; + uint32_t csi2_rst_done_shift_val; + uint32_t csi2_irq_mask_all; + uint32_t csi2_misr_enable_shift_val; + uint32_t csi2_vc_mode_shift_val; + uint32_t csi2_capture_long_pkt_en_shift; + uint32_t csi2_capture_short_pkt_en_shift; + uint32_t csi2_capture_cphy_pkt_en_shift; + uint32_t csi2_capture_long_pkt_dt_shift; + uint32_t csi2_capture_long_pkt_vc_shift; + 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 { + uint32_t csid_tpg_ctrl_addr; + uint32_t csid_tpg_vc_cfg0_addr; + uint32_t csid_tpg_vc_cfg1_addr; + uint32_t csid_tpg_lfsr_seed_addr; + uint32_t csid_tpg_dt_n_cfg_0_addr; + uint32_t csid_tpg_dt_n_cfg_1_addr; + uint32_t csid_tpg_dt_n_cfg_2_addr; + uint32_t csid_tpg_color_bars_cfg_addr; + uint32_t csid_tpg_color_box_cfg_addr; + uint32_t csid_tpg_common_gen_cfg_addr; + uint32_t csid_tpg_cgen_n_cfg_addr; + uint32_t csid_tpg_cgen_n_x0_addr; + uint32_t csid_tpg_cgen_n_x1_addr; + uint32_t csid_tpg_cgen_n_x2_addr; + uint32_t csid_tpg_cgen_n_xy_addr; + uint32_t csid_tpg_cgen_n_y1_addr; + uint32_t csid_tpg_cgen_n_y2_addr; + + /*configurations */ + uint32_t tpg_dtn_cfg_offset; + uint32_t tpg_cgen_cfg_offset; + uint32_t tpg_cpas_ife_reg_offset; + +}; +struct cam_ife_csid_common_reg_offset { + /* MIPI CSID registers */ + uint32_t csid_hw_version_addr; + uint32_t csid_cfg0_addr; + uint32_t csid_ctrl_addr; + uint32_t csid_reset_addr; + uint32_t csid_rst_strobes_addr; + + uint32_t csid_test_bus_ctrl_addr; + uint32_t csid_top_irq_status_addr; + uint32_t csid_top_irq_mask_addr; + uint32_t csid_top_irq_clear_addr; + uint32_t csid_top_irq_set_addr; + uint32_t csid_irq_cmd_addr; + + /*configurations */ + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; + 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; + uint32_t path_rst_done_shift_val; + uint32_t path_en_shift_val; + uint32_t dt_id_shift_val; + uint32_t vc_shift_val; + uint32_t dt_shift_val; + uint32_t fmt_shift_val; + uint32_t plain_fmt_shit_val; + uint32_t crop_v_en_shift_val; + uint32_t crop_h_en_shift_val; + uint32_t crop_shift; + uint32_t ipp_irq_mask_all; + uint32_t rdi_irq_mask_all; + uint32_t ppp_irq_mask_all; + uint32_t measure_en_hbi_vbi_cnt_mask; + uint32_t format_measure_en_val; +}; + +/** + * struct cam_ife_csid_reg_offset- CSID instance register info + * + * @cmn_reg: csid common registers info + * @ipp_reg: ipp register offset information + * @ppp_reg: ppp register offset information + * @rdi_reg: rdi register offser information + * + */ +struct cam_ife_csid_reg_offset { + const struct cam_ife_csid_common_reg_offset *cmn_reg; + const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg; + const struct cam_ife_csid_pxl_reg_offset *ipp_reg; + const struct cam_ife_csid_pxl_reg_offset *ppp_reg; + const struct cam_ife_csid_rdi_reg_offset *rdi_reg[CAM_IFE_CSID_RDI_MAX]; + const struct cam_ife_csid_csi2_tpg_reg_offset *tpg_reg; +}; + + +/** + * struct cam_ife_csid_hw_info- CSID HW info + * + * @csid_reg: csid register offsets + * @hw_dts_version: HW DTS version + * @csid_max_clk: maximim csid clock + * + */ +struct cam_ife_csid_hw_info { + const struct cam_ife_csid_reg_offset *csid_reg; + uint32_t hw_dts_version; + uint32_t csid_max_clk; + +}; + + + +/** + * struct cam_ife_csid_csi2_rx_cfg- csid csi2 rx configuration data + * @phy_sel: input resource type for sensor only + * @lane_type: lane type: c-phy or d-phy + * @lane_num : active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * + */ +struct cam_ife_csid_csi2_rx_cfg { + uint32_t phy_sel; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; +}; + +/** + * struct cam_ife_csid_tpg_cfg- csid tpg configuration data + * @width: width + * @height: height + * @test_pattern : pattern + * @in_format: decode format + * @usage_type: whether dual isp is required + * + */ +struct cam_ife_csid_tpg_cfg { + uint32_t width; + uint32_t height; + uint32_t test_pattern; + uint32_t in_format; + uint32_t usage_type; +}; + +/** + * struct cam_ife_csid_cid_data- cid configuration private data + * + * @vc: Virtual channel + * @dt: Data type + * @cnt: Cid resource reference count. + * @tpg_set: Tpg used for this cid resource + * @is_valid_vc1_dt1: Valid vc1 and dt1 + * + */ +struct cam_ife_csid_cid_data { + uint32_t vc; + uint32_t dt; + uint32_t vc1; + uint32_t dt1; + uint32_t cnt; + uint32_t tpg_set; + uint32_t is_valid_vc1_dt1; +}; + + +/** + * struct cam_ife_csid_path_cfg- csid path configuration details. It is stored + * as private data for IPP/ RDI paths + * @vc : Virtual channel number + * @dt : Data type number + * @cid cid number, it is same as DT_ID number in HW + * @in_format: input decode format + * @out_format: output format + * @crop_enable: crop is enable or disabled, if enabled + * then remaining parameters are valid. + * @start_pixel: start pixel + * @end_pixel: end_pixel + * @width: width + * @start_line: start line + * @end_line: end_line + * @height: heigth + * @sync_mode: Applicable for IPP/RDI path reservation + * Reserving the path for master IPP or slave IPP + * master (set value 1), Slave ( set value 2) + * for RDI, set mode to none + * @master_idx: For Slave reservation, Give master IFE instance Index. + * Slave will synchronize with master Start and stop operations + * @clk_rate Clock rate + * + */ +struct cam_ife_csid_path_cfg { + uint32_t vc; + uint32_t dt; + uint32_t vc1; + uint32_t dt1; + uint32_t is_valid_vc1_dt1; + uint32_t cid; + uint32_t in_format; + uint32_t out_format; + bool crop_enable; + uint32_t start_pixel; + uint32_t end_pixel; + uint32_t width; + uint32_t start_line; + uint32_t end_line; + uint32_t height; + enum cam_isp_hw_sync_mode sync_mode; + uint32_t master_idx; + uint64_t clk_rate; +}; + +/** + * struct cam_ife_csid_hw- csid hw device resources data + * + * @hw_intf: contain the csid hw interface information + * @hw_info: csid hw device information + * @csid_info: csid hw specific information + * @res_type: CSID in resource type + * @csi2_rx_cfg: Csi2 rx decoder configuration for csid + * @tpg_cfg: TPG configuration + * @csi2_rx_reserve_cnt: CSI2 reservations count value + * @csi2_cfg_cnt: csi2 configuration count + * @tpg_start_cnt: tpg start count + * @ipp_res: image pixel path resource + * @ppp_res: phase pxl path resource + * @rdi_res: raw dump image path resources + * @cid_res: cid resources state + * @csid_top_reset_complete: csid top reset completion + * @csid_csi2_reset_complete: csi2 reset completion + * @csid_ipp_reset_complete: ipp reset completion + * @csid_ppp_complete: ppp reset completion + * @csid_rdin_reset_complete: rdi n completion + * @csid_debug: csid debug information to enable the SOT, EOT, + * SOF, EOF, measure etc in the csid hw + * @clk_rate Clock rate + * @sof_irq_triggered: Flag is set on receiving event to enable sof irq + * incase of SOF freeze. + * @irq_debug_cnt: Counter to track sof irq's when above flag is set. + * @error_irq_count Error IRQ count, if continuous error irq comes + * need to stop the CSID and mask interrupts. + * + */ +struct cam_ife_csid_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_ife_csid_hw_info *csid_info; + uint32_t res_type; + struct cam_ife_csid_csi2_rx_cfg csi2_rx_cfg; + struct cam_ife_csid_tpg_cfg tpg_cfg; + uint32_t csi2_reserve_cnt; + uint32_t csi2_cfg_cnt; + uint32_t tpg_start_cnt; + struct cam_isp_resource_node ipp_res; + struct cam_isp_resource_node ppp_res; + struct cam_isp_resource_node rdi_res[CAM_IFE_CSID_RDI_MAX]; + struct cam_isp_resource_node cid_res[CAM_IFE_CSID_CID_MAX]; + struct completion csid_top_complete; + struct completion csid_csi2_complete; + struct completion csid_ipp_complete; + struct completion csid_ppp_complete; + struct completion csid_rdin_complete[CAM_IFE_CSID_RDI_MAX]; + uint64_t csid_debug; + uint64_t clk_rate; + 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, + uint32_t csid_idx); + +int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw); + +#endif /* _CAM_IFE_CSID_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c new file mode 100644 index 000000000000..05bf36899392 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include "cam_ife_csid_core.h" +#include "cam_ife_csid_dev.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_ife_csid_hw_list[CAM_IFE_CSID_HW_NUM_MAX] = { + 0, 0, 0, 0}; + +static char csid_dev_name[8]; + +int cam_ife_csid_probe(struct platform_device *pdev) +{ + + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + struct cam_ife_csid_hw *csid_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_ife_csid_hw_info *csid_hw_data = NULL; + uint32_t csid_dev_idx; + int rc = 0; + + CAM_DBG(CAM_ISP, "probe called"); + + csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL); + if (!csid_hw_intf) { + rc = -ENOMEM; + goto err; + } + + csid_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!csid_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + csid_dev = kzalloc(sizeof(struct cam_ife_csid_hw), GFP_KERNEL); + if (!csid_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + /* get ife csid hw index */ + of_property_read_u32(pdev->dev.of_node, "cell-index", &csid_dev_idx); + /* get ife csid hw information */ + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the IFE CSID HW!"); + rc = -EINVAL; + goto free_dev; + } + + memset(csid_dev_name, 0, sizeof(csid_dev_name)); + snprintf(csid_dev_name, sizeof(csid_dev_name), + "csid%1u", csid_dev_idx); + + csid_hw_intf->hw_idx = csid_dev_idx; + csid_hw_intf->hw_type = CAM_ISP_HW_TYPE_IFE_CSID; + csid_hw_intf->hw_priv = csid_hw_info; + + csid_hw_info->core_info = csid_dev; + csid_hw_info->soc_info.pdev = pdev; + csid_hw_info->soc_info.dev = &pdev->dev; + csid_hw_info->soc_info.dev_name = csid_dev_name; + csid_hw_info->soc_info.index = csid_dev_idx; + + csid_hw_data = (struct cam_ife_csid_hw_info *)match_dev->data; + /* need to setup the pdev before call the ife hw probe init */ + csid_dev->csid_info = csid_hw_data; + + rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx); + if (rc) + goto free_dev; + + platform_set_drvdata(pdev, csid_dev); + CAM_DBG(CAM_ISP, "CSID:%d probe successful", + csid_hw_intf->hw_idx); + + + if (csid_hw_intf->hw_idx < CAM_IFE_CSID_HW_NUM_MAX) + cam_ife_csid_hw_list[csid_hw_intf->hw_idx] = csid_hw_intf; + else + goto free_dev; + + return 0; + +free_dev: + kfree(csid_dev); +free_hw_info: + kfree(csid_hw_info); +free_hw_intf: + kfree(csid_hw_intf); +err: + return rc; +} + +int cam_ife_csid_remove(struct platform_device *pdev) +{ + struct cam_ife_csid_hw *csid_dev = NULL; + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + + csid_dev = (struct cam_ife_csid_hw *)platform_get_drvdata(pdev); + csid_hw_intf = csid_dev->hw_intf; + csid_hw_info = csid_dev->hw_info; + + CAM_DBG(CAM_ISP, "CSID:%d remove", + csid_dev->hw_intf->hw_idx); + + cam_ife_csid_hw_deinit(csid_dev); + + /*release the csid device memory */ + kfree(csid_dev); + kfree(csid_hw_info); + kfree(csid_hw_intf); + return 0; +} + +int cam_ife_csid_hw_init(struct cam_hw_intf **ife_csid_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_ife_csid_hw_list[hw_idx]) { + *ife_csid_hw = cam_ife_csid_hw_list[hw_idx]; + } else { + *ife_csid_hw = NULL; + rc = -1; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h new file mode 100644 index 000000000000..1f8e4d05b74b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_DEV_H_ +#define _CAM_IFE_CSID_DEV_H_ + +#include "cam_isp_hw.h" + +irqreturn_t cam_ife_csid_irq(int irq_num, void *data); + +int cam_ife_csid_probe(struct platform_device *pdev); +int cam_ife_csid_remove(struct platform_device *pdev); + +#endif /*_CAM_IFE_CSID_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c new file mode 100644 index 000000000000..0a80f1a51cf5 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_ife_csid_lite17x.h" +#include "cam_ife_csid_core.h" +#include "cam_ife_csid_dev.h" + +#define CAM_CSID_LITE_DRV_NAME "csid_lite" + +static struct cam_ife_csid_hw_info cam_ife_csid_lite_hw_info = { + .csid_reg = &cam_ife_csid_lite_17x_reg_offset, +}; + +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, + }, + { + .compatible = "qcom,csid-lite480", + .data = &cam_ife_csid_lite_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_ife_csid_lite_dt_match); + +static struct platform_driver cam_ife_csid_lite_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_lite_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_ife_csid_lite_init_module(void) +{ + return platform_driver_register(&cam_ife_csid_lite_driver); +} + +static void __exit cam_ife_csid_lite_exit_module(void) +{ + platform_driver_unregister(&cam_ife_csid_lite_driver); +} + +module_init(cam_ife_csid_lite_init_module); +module_exit(cam_ife_csid_lite_exit_module); +MODULE_DESCRIPTION("CAM IFE_CSID_LITE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h new file mode 100644 index 000000000000..0573e30d151e --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_LITE17X_H_ +#define _CAM_IFE_CSID_LITE17X_H_ +#include "cam_ife_csid_core.h" + +static const struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_17x_rdi_0_reg_offset = { + + .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, +}; + +static const struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_17x_rdi_1_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, +}; + +static const struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_17x_rdi_2_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_yuv_chroma_conversion_addr = 0x434, + .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, +}; + +static const struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_17x_rdi_3_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, +}; + +static const struct cam_ife_csid_csi2_rx_reg_offset + cam_ife_csid_lite_17x_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_de_scramble_cfg0_addr = 0x114, + .csid_csi2_rx_de_scramble_cfg1_addr = 0x118, + .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, + + .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 = 0x3, +}; + + +static const struct cam_ife_csid_csi2_tpg_reg_offset + cam_ife_csid_lite_17x_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 const struct cam_ife_csid_common_reg_offset + cam_csid_lite_17x_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 = 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, + .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 = 0x7FFF, + .rdi_irq_mask_all = 0x7FFF, + .ppp_irq_mask_all = 0xFFFF, +}; + +static const struct cam_ife_csid_reg_offset cam_ife_csid_lite_17x_reg_offset = { + .cmn_reg = &cam_csid_lite_17x_cmn_reg_offset, + .csi2_reg = &cam_ife_csid_lite_17x_csi2_reg_offset, + .ipp_reg = NULL, + .rdi_reg = { + &cam_ife_csid_lite_17x_rdi_0_reg_offset, + &cam_ife_csid_lite_17x_rdi_1_reg_offset, + &cam_ife_csid_lite_17x_rdi_2_reg_offset, + &cam_ife_csid_lite_17x_rdi_3_reg_offset, + }, + .tpg_reg = &cam_ife_csid_lite_17x_tpg_reg_offset, +}; + +#endif /*_CAM_IFE_CSID_LITE17X_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c new file mode 100644 index 000000000000..3a6d3e8abf98 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ +#include +#include "cam_ife_csid_soc.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +static int cam_ife_csid_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + struct device_node *of_node = NULL; + struct csid_device_soc_info *csid_soc_info = NULL; + int rc = 0; + + of_node = soc_info->pdev->dev.of_node; + csid_soc_info = (struct csid_device_soc_info *)soc_info->soc_private; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) + return rc; + + return rc; +} + +static int cam_ife_csid_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t csid_irq_handler, + void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, csid_irq_handler, + irq_data); + if (rc) + return rc; + + return rc; +} + +int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t csid_irq_handler, void *irq_data) +{ + int rc = 0; + struct cam_cpas_register_params cpas_register_param; + struct cam_csid_soc_private *soc_private; + + soc_private = kzalloc(sizeof(struct cam_csid_soc_private), GFP_KERNEL); + if (!soc_private) + return -ENOMEM; + + soc_info->soc_private = soc_private; + + rc = cam_ife_csid_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + /* Need to see if we want post process the clock list */ + + rc = cam_ife_csid_request_platform_resource(soc_info, csid_irq_handler, + irq_data); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Error Request platform resources failed rc=%d", rc); + goto free_soc_private; + } + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "csid", + CAM_HW_IDENTIFIER_LENGTH); + cpas_register_param.cell_index = soc_info->index; + cpas_register_param.dev = soc_info->dev; + 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 = cpas_register_param.client_handle; + } + + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); +free_soc_private: + kfree(soc_private); + + return rc; +} + +int cam_ife_csid_deinit_soc_resources( + struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_csid_soc_private *soc_private; + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -ENODEV; + } + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + + return rc; +} + +int cam_ife_csid_enable_soc_resources( + struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level) +{ + int rc = 0; + struct cam_csid_soc_private *soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + soc_private = soc_info->soc_private; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + CAM_DBG(CAM_ISP, "csid camnoc_bw:%lld mnoc_ab_bw:%lld mnoc_ib_bw:%lld ", + axi_vote.axi_path[0].camnoc_bw, + axi_vote.axi_path[0].mnoc_ab_bw, + axi_vote.axi_path[0].mnoc_ib_bw); + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_ISP, "Error CPAS start failed"); + rc = -EFAULT; + goto end; + } + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + clk_level, true); + if (rc) { + CAM_ERR(CAM_ISP, "enable platform failed"); + goto stop_cpas; + } + + return rc; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); +end: + return rc; +} + +int cam_ife_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_csid_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) + CAM_ERR(CAM_ISP, "Disable platform failed"); + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Error CPAS stop failed rc=%d", rc); + return rc; + } + + return rc; +} + +int cam_ife_csid_enable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_ife_base_offset) +{ + int rc = 0; + struct cam_csid_soc_private *soc_private; + uint32_t cpass_ife_force_clk_offset; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + + soc_private = soc_info->soc_private; + cpass_ife_force_clk_offset = + cpas_ife_base_offset + (0x4 * soc_info->index); + rc = cam_cpas_reg_write(soc_private->cpas_handle, CAM_CPAS_REG_CPASTOP, + cpass_ife_force_clk_offset, 1, 1); + + if (rc) + CAM_ERR(CAM_ISP, "CPASS set IFE:%d Force clock On failed", + soc_info->index); + else + CAM_DBG(CAM_ISP, "CPASS set IFE:%d Force clock On", + soc_info->index); + + return rc; +} + +int cam_ife_csid_disable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_ife_base_offset) +{ + int rc = 0; + struct cam_csid_soc_private *soc_private; + uint32_t cpass_ife_force_clk_offset; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + + soc_private = soc_info->soc_private; + cpass_ife_force_clk_offset = + cpas_ife_base_offset + (0x4 * soc_info->index); + rc = cam_cpas_reg_write(soc_private->cpas_handle, CAM_CPAS_REG_CPASTOP, + cpass_ife_force_clk_offset, 1, 0); + + if (rc) + CAM_ERR(CAM_ISP, "CPASS set IFE:%d Force clock Off failed", + soc_info->index); + else + CAM_DBG(CAM_ISP, "CPASS set IFE:%d Force clock off", + soc_info->index); + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h new file mode 100644 index 000000000000..317dcb39a59b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_SOC_H_ +#define _CAM_IFE_CSID_SOC_H_ + +#include "cam_isp_hw.h" + +/* + * struct cam_csid_soc_private: + * + * @Brief: Private SOC data specific to CSID HW Driver + * + * @cpas_handle: Handle returned on registering with CPAS driver. + * This handle is used for all further interface + * with CPAS. + */ +struct cam_csid_soc_private { + uint32_t cpas_handle; +}; + +/** + * struct csid_device_soc_info - CSID SOC info object + * + * @csi_vdd_voltage: csi vdd voltage value + * + */ +struct csid_device_soc_info { + int csi_vdd_voltage; +}; + +/** + * cam_ife_csid_init_soc_resources() + * + * @brief: csid initialization function for the soc info + * + * @soc_info: soc info structure pointer + * @csid_irq_handler: irq handler function to be registered + * @irq_data: irq data for the callback function + * + */ +int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t csid_irq_handler, void *irq_data); + + +/** + * cam_ife_csid_deinit_soc_resources() + * + * @brief: csid de initialization function for the soc info + * + * @soc_info: soc info structure pointer + * + */ +int cam_ife_csid_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + +/** + * cam_ife_csid_enable_soc_resources() + * + * @brief: csid soc resource enable function + * + * @soc_info: soc info structure pointer + * @clk_lvl: vote level to start with + * + */ +int cam_ife_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info, + uint32_t clk_lvl); + +/** + * cam_ife_csid_disable_soc_resources() + * + * @brief: csid soc resource disable function + * + * @soc_info: soc info structure pointer + * + */ +int cam_ife_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +/** + * cam_ife_csid_enable_ife_force_clock() + * + * @brief: if csid testgen used for dual isp case, before + * starting csid test gen, enable ife force clock on + * through cpas + * + * @soc_info: soc info structure pointer + * @cpas_ife_base_offset: cpas ife force clock base reg offset value + * + */ +int cam_ife_csid_enable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_ife_base_offset); + +/** + * cam_ife_csid_disable_ife_force_clock_on() + * + * @brief: disable the IFE force clock on after dual ISP + * CSID test gen stop + * + * @soc_info: soc info structure pointer + * @cpas_ife_base_offset: cpas ife force clock base reg offset value + * + */ +int cam_ife_csid_disable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_ife_base_offset); + +/** + * cam_ife_csid_get_vote_level() + * + * @brief: get the vote level from clock rate + * + * @soc_info: soc info structure pointer + * @clock_rate clock rate + * + */ +uint32_t cam_ife_csid_get_vote_level(struct cam_hw_soc_info *soc_info, + uint64_t clock_rate); + +#endif diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h new file mode 100644 index 000000000000..247dfc5960fb --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_HW_INTF_H_ +#define _CAM_CSID_HW_INTF_H_ + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" + +/* MAX IFE CSID instance */ +#define CAM_IFE_CSID_HW_NUM_MAX 7 +#define CAM_IFE_CSID_RDI_MAX 4 + +/** + * enum cam_ife_pix_path_res_id - Specify the csid patch + */ +enum cam_ife_pix_path_res_id { + CAM_IFE_PIX_PATH_RES_RDI_0, + CAM_IFE_PIX_PATH_RES_RDI_1, + CAM_IFE_PIX_PATH_RES_RDI_2, + CAM_IFE_PIX_PATH_RES_RDI_3, + CAM_IFE_PIX_PATH_RES_IPP, + CAM_IFE_PIX_PATH_RES_PPP, + CAM_IFE_PIX_PATH_RES_MAX, +}; + +/** + * enum cam_ife_cid_res_id - Specify the csid cid + */ +enum cam_ife_cid_res_id { + CAM_IFE_CSID_CID_0, + CAM_IFE_CSID_CID_1, + CAM_IFE_CSID_CID_2, + CAM_IFE_CSID_CID_3, + CAM_IFE_CSID_CID_MAX, +}; + +/** + * struct cam_ife_csid_hw_caps- get the CSID hw capability + * @num_rdis: number of rdis supported by CSID HW device + * @num_pix: number of pxl paths supported by CSID HW device + * @num_ppp: number of ppp paths supported by CSID HW device + * @major_version : major version + * @minor_version: minor version + * @version_incr: version increment + * + */ +struct cam_ife_csid_hw_caps { + uint32_t num_rdis; + uint32_t num_pix; + uint32_t num_ppp; + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; +}; + +struct cam_isp_out_port_generic_info { + uint32_t res_type; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t comp_grp_id; + uint32_t split_point; + uint32_t secure_mode; + uint32_t reserved; +}; + +struct cam_isp_in_port_generic_info { + uint32_t major_ver; + uint32_t minor_ver; + uint32_t res_type; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; + uint32_t vc[CAM_ISP_VC_DT_CFG]; + uint32_t dt[CAM_ISP_VC_DT_CFG]; + uint32_t num_valid_vc_dt; + uint32_t format; + uint32_t test_pattern; + uint32_t usage_type; + uint32_t left_start; + uint32_t left_stop; + uint32_t left_width; + uint32_t right_start; + uint32_t right_stop; + uint32_t right_width; + uint32_t line_start; + uint32_t line_stop; + uint32_t height; + uint32_t pixel_clk; + uint32_t batch_size; + uint32_t dsp_mode; + uint32_t hbi_cnt; + uint32_t cust_node; + uint32_t num_out_res; + struct cam_isp_out_port_generic_info *data; +}; + +/** + * struct cam_csid_hw_reserve_resource- hw reserve + * @res_type : Reource type CID or PATH + * if type is CID, then res_id is not required, + * if type is path then res id need to be filled + * @res_id : Resource id to be reserved + * @in_port : Input port resource info + * @out_port: Output port resource info, used for RDI path only + * @sync_mode: Sync mode + * Sync mode could be master, slave or none + * @master_idx: Master device index to be configured in the slave path + * for master path, this value is not required. + * only slave need to configure the master index value + * @cid: cid (DT_ID) value for path, this is applicable for CSID path + * reserve + * @node_res : Reserved resource structure pointer + * @crop_enable : Flag to indicate CSID crop enable + * + */ +struct cam_csid_hw_reserve_resource_args { + enum cam_isp_resource_type res_type; + uint32_t res_id; + struct cam_isp_in_port_generic_info *in_port; + struct cam_isp_out_port_generic_info *out_port; + enum cam_isp_hw_sync_mode sync_mode; + uint32_t master_idx; + uint32_t cid; + struct cam_isp_resource_node *node_res; + bool crop_enable; +}; + +/** + * enum cam_ife_csid_halt_cmd - Specify the halt command type + */ +enum cam_ife_csid_halt_cmd { + CAM_CSID_HALT_AT_FRAME_BOUNDARY, + CAM_CSID_RESUME_AT_FRAME_BOUNDARY, + CAM_CSID_HALT_IMMEDIATELY, + CAM_CSID_HALT_MAX, +}; + +/** + * struct cam_csid_hw_stop- stop all resources + * @stop_cmd : Applicable only for PATH resources + * if stop command set to Halt immediately,driver will stop + * path immediately, manager need to reset the path after HI + * if stop command set to halt at frame boundary, driver will set + * halt at frame boundary and wait for frame boundary + * @node_res : reource pointer array( ie cid or CSID) + * @num_res : number of resources to be stopped + * + */ +struct cam_csid_hw_stop_args { + enum cam_ife_csid_halt_cmd stop_cmd; + struct cam_isp_resource_node **node_res; + uint32_t num_res; +}; + +/** + * enum cam_ife_csid_reset_type - Specify the reset type + */ +enum cam_ife_csid_reset_type { + CAM_IFE_CSID_RESET_GLOBAL, + CAM_IFE_CSID_RESET_PATH, + CAM_IFE_CSID_RESET_MAX, +}; + +/** + * struct cam_ife_csid_reset_cfg- csid reset configuration + * @ reset_type : Global reset or path reset + * @res_node : resource need to be reset + * + */ +struct cam_csid_reset_cfg_args { + enum cam_ife_csid_reset_type reset_type; + struct cam_isp_resource_node *node_res; +}; + +/** + * struct cam_csid_get_time_stamp_args- time stamp capture arguments + * @res_node : resource to get the time stamp + * @time_stamp_val : captured time stamp + * @boot_timestamp : boot time stamp + */ +struct cam_csid_get_time_stamp_args { + struct cam_isp_resource_node *node_res; + uint64_t time_stamp_val; + uint64_t boot_timestamp; +}; + +/** + * enum cam_ife_csid_cmd_type - Specify the csid command + */ +enum cam_ife_csid_cmd_type { + CAM_IFE_CSID_CMD_GET_TIME_STAMP, + CAM_IFE_CSID_SET_CSID_DEBUG, + CAM_IFE_CSID_SOF_IRQ_DEBUG, + CAM_IFE_CSID_CMD_MAX, +}; + +/** + * cam_ife_csid_hw_init() + * + * @brief: Initialize function for the CSID hardware + * + * @ife_csid_hw: CSID hardware instance returned + * @hw_idex: CSID hardware instance id + */ +int cam_ife_csid_hw_init(struct cam_hw_intf **ife_csid_hw, + uint32_t hw_idx); + +/* + * struct cam_ife_csid_clock_update_args: + * + * @clk_rate: Clock rate requested + */ +struct cam_ife_csid_clock_update_args { + uint64_t clk_rate; +}; + + +#endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h new file mode 100644 index 000000000000..33254c1610ae --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ISP_HW_H_ +#define _CAM_ISP_HW_H_ + +#include +#include +#include "cam_hw.h" +#include "cam_soc_util.h" +#include "cam_irq_controller.h" +#include "cam_hw_intf.h" + +/* + * struct cam_isp_timestamp: + * + * @mono_time: Monotonic boot time + * @vt_time: AV Timer time + * @ticks: Qtimer ticks + */ +struct cam_isp_timestamp { + struct timeval mono_time; + struct timeval vt_time; + uint64_t ticks; +}; + +/* + * cam_isp_hw_get_timestamp() + * + * @Brief: Get timestamp values + * + * @time_stamp: Structure that holds different time values + * + * @Return: Void + */ +void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp); + +enum cam_isp_hw_type { + CAM_ISP_HW_TYPE_CSID = 0, + CAM_ISP_HW_TYPE_ISPIF = 1, + CAM_ISP_HW_TYPE_VFE = 2, + CAM_ISP_HW_TYPE_IFE_CSID = 3, + CAM_ISP_HW_TYPE_MAX = 4, +}; + +enum cam_isp_hw_split_id { + CAM_ISP_HW_SPLIT_LEFT = 0, + CAM_ISP_HW_SPLIT_RIGHT, + CAM_ISP_HW_SPLIT_MAX, +}; + +enum cam_isp_hw_sync_mode { + CAM_ISP_HW_SYNC_NONE, + CAM_ISP_HW_SYNC_MASTER, + CAM_ISP_HW_SYNC_SLAVE, + CAM_ISP_HW_SYNC_MAX, +}; + +enum cam_isp_resource_state { + CAM_ISP_RESOURCE_STATE_UNAVAILABLE = 0, + CAM_ISP_RESOURCE_STATE_AVAILABLE = 1, + CAM_ISP_RESOURCE_STATE_RESERVED = 2, + CAM_ISP_RESOURCE_STATE_INIT_HW = 3, + CAM_ISP_RESOURCE_STATE_STREAMING = 4, +}; + +enum cam_isp_resource_type { + CAM_ISP_RESOURCE_UNINT, + CAM_ISP_RESOURCE_SRC, + CAM_ISP_RESOURCE_CID, + 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, + CAM_ISP_HW_CMD_BW_UPDATE, + CAM_ISP_HW_CMD_BW_UPDATE_V2, + CAM_ISP_HW_CMD_BW_CONTROL, + CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ, + CAM_ISP_HW_CMD_UBWC_UPDATE, + CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, + CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + 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_UBWC_UPDATE_V2, + CAM_ISP_HW_CMD_CORE_CONFIG, + CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, + CAM_ISP_HW_CMD_MAX, +}; + +/* + * struct cam_isp_resource_node: + * + * @Brief: Structure representing HW resource object + * + * @res_type: Resource Type + * @res_id: Unique resource ID within res_type objects + * for a particular HW + * @res_state: State of the resource + * @hw_intf: HW Interface of HW to which this resource + * belongs + * @res_priv: Private data of the resource + * @list: list_head node for this resource + * @cdm_ops: CDM operation functions + * @tasklet_info: Tasklet structure that will be used to + * schedule IRQ events related to this resource + * @irq_handle: handle returned on subscribing for IRQ event + * @rdi_only_ctx: resource belong to rdi only context or not + * @init: function pointer to init the HW resource + * @deinit: function pointer to deinit the HW resource + * @start: function pointer to start the HW resource + * @stop: function pointer to stop the HW resource + * @process_cmd: function pointer for processing commands + * specific to the resource + * @top_half_handler: Top Half handler function + * @bottom_half_handler: Bottom Half handler function + */ +struct cam_isp_resource_node { + enum cam_isp_resource_type res_type; + uint32_t res_id; + enum cam_isp_resource_state res_state; + struct cam_hw_intf *hw_intf; + void *res_priv; + struct list_head list; + void *cdm_ops; + void *tasklet_info; + int irq_handle; + int rdi_only_ctx; + + int (*init)(struct cam_isp_resource_node *rsrc_node, + void *init_args, uint32_t arg_size); + int (*deinit)(struct cam_isp_resource_node *rsrc_node, + void *deinit_args, uint32_t arg_size); + int (*start)(struct cam_isp_resource_node *rsrc_node); + int (*stop)(struct cam_isp_resource_node *rsrc_node); + int (*process_cmd)(struct cam_isp_resource_node *rsrc_node, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size); + CAM_IRQ_HANDLER_TOP_HALF top_half_handler; + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; +}; + +/* + * struct cam_isp_hw_event_info: + * + * @Brief: Structure to pass event details to hw mgr + * + * @res_type: Type of IFE resource + * @res_id: Unique resource ID + * @hw_idx: IFE hw index + * @err_type: Error type if any + * + */ +struct cam_isp_hw_event_info { + enum cam_isp_resource_type res_type; + uint32_t res_id; + uint32_t hw_idx; + uint32_t err_type; +}; + +/* + * struct cam_isp_hw_cmd_buf_update: + * + * @Brief: Contain the new created command buffer information + * + * @cmd_buf_addr: Command buffer to store the change base command + * @size: Size of the buffer in bytes + * @used_bytes: Consumed bytes in the command buffer + * + */ +struct cam_isp_hw_cmd_buf_update { + uint32_t *cmd_buf_addr; + uint32_t size; + uint32_t used_bytes; +}; + +/* + * struct cam_isp_hw_get_wm_update: + * + * @Brief: Get cmd buffer for WM updates. + * + * @ image_buf: image buffer address array + * @ num_buf: Number of buffers in the image_buf array + * @ io_cfg: IO buffer config information sent from UMD + * + */ +struct cam_isp_hw_get_wm_update { + uint64_t *image_buf; + uint32_t num_buf; + struct cam_buf_io_cfg *io_cfg; +}; + +/* + * struct cam_isp_hw_get_cmd_update: + * + * @Brief: Get cmd buffer update for different CMD types + * + * @res: Resource node + * @cmd_type: Command type for which to get update + * @cmd: Command buffer information + * + */ +struct cam_isp_hw_get_cmd_update { + struct cam_isp_resource_node *res; + enum cam_isp_hw_cmd_type cmd_type; + struct cam_isp_hw_cmd_buf_update cmd; + 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_vfe_generic_ubwc_config *ubwc_config; + struct cam_isp_vfe_wm_config *wm_config; + }; +}; + +/* + * struct cam_isp_hw_dual_isp_update_args: + * + * @Brief: update the dual isp striping configuration. + * + * @ split_id: spilt id to inform left or rifht + * @ res: resource node + * @ dual_cfg: dual isp configuration + * + */ +struct cam_isp_hw_dual_isp_update_args { + enum cam_isp_hw_split_id split_id; + struct cam_isp_resource_node *res; + struct cam_isp_dual_config *dual_cfg; +}; +#endif /* _CAM_ISP_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h new file mode 100644 index 000000000000..7944cbc8933f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -0,0 +1,370 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_HW_INTF_H_ +#define _CAM_VFE_HW_INTF_H_ + +#include "cam_isp_hw.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_cpas_api.h" + +#define CAM_VFE_HW_NUM_MAX 7 + +#define VFE_CORE_BASE_IDX 0 +/* + * VBIF and BUS do not exist on same HW. + * Hence both can be 1 below. + */ +#define VFE_VBIF_BASE_IDX 1 +#define VFE_BUS_BASE_IDX 1 + +#define CAM_VFE_MAX_UBWC_PORTS 4 + +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_RD = 2, + CAM_ISP_HW_VFE_IN_RDI0 = 3, + CAM_ISP_HW_VFE_IN_RDI1 = 4, + CAM_ISP_HW_VFE_IN_RDI2 = 5, + CAM_ISP_HW_VFE_IN_RDI3 = 6, + CAM_ISP_HW_VFE_IN_PDLIB = 7, + CAM_ISP_HW_VFE_IN_LCR = 8, + CAM_ISP_HW_VFE_IN_MAX, +}; + +enum cam_isp_hw_vfe_core { + CAM_ISP_HW_VFE_CORE_0, + CAM_ISP_HW_VFE_CORE_1, + CAM_ISP_HW_VFE_CORE_2, + CAM_ISP_HW_VFE_CORE_3, + CAM_ISP_HW_VFE_CORE_MAX, +}; + +enum cam_vfe_hw_irq_status { + CAM_VFE_IRQ_STATUS_ERR_COMP = -3, + CAM_VFE_IRQ_STATUS_COMP_OWRT = -2, + CAM_VFE_IRQ_STATUS_ERR = -1, + CAM_VFE_IRQ_STATUS_SUCCESS = 0, + CAM_VFE_IRQ_STATUS_OVERFLOW = 1, + CAM_VFE_IRQ_STATUS_P2I_ERROR = 2, + CAM_VFE_IRQ_STATUS_VIOLATION = 3, + CAM_VFE_IRQ_STATUS_MAX, +}; + +enum cam_vfe_hw_irq_regs { + CAM_IFE_IRQ_CAMIF_REG_STATUS0 = 0, + CAM_IFE_IRQ_CAMIF_REG_STATUS1 = 1, + CAM_IFE_IRQ_CAMIF_REG_STATUS2 = 2, + CAM_IFE_IRQ_VIOLATION_STATUS = 3, + CAM_IFE_IRQ_REGISTERS_MAX, +}; + +enum cam_vfe_bus_irq_regs { + CAM_IFE_IRQ_BUS_REG_STATUS0 = 0, + CAM_IFE_IRQ_BUS_REG_STATUS1 = 1, + CAM_IFE_IRQ_BUS_REG_STATUS2 = 2, + CAM_IFE_IRQ_BUS_REG_COMP_ERR = 3, + CAM_IFE_IRQ_BUS_REG_COMP_OWRT = 4, + CAM_IFE_IRQ_BUS_DUAL_COMP_ERR = 5, + CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT = 6, + CAM_IFE_BUS_IRQ_REGISTERS_MAX, +}; + +enum cam_vfe_bus_ver3_irq_regs { + CAM_IFE_IRQ_BUS_VER3_REG_STATUS0 = 0, + CAM_IFE_IRQ_BUS_VER3_REG_STATUS1 = 1, + CAM_IFE_IRQ_BUS_VER3_REG_MAX, +}; + +enum cam_vfe_reset_type { + CAM_VFE_HW_RESET_HW_AND_REG, + CAM_VFE_HW_RESET_HW, + CAM_VFE_HW_RESET_MAX, +}; + +/* + * struct cam_vfe_hw_get_hw_cap: + * + * @max_width: Max width supported by HW + * @max_height: Max height supported by HW + * @max_pixel_num: Max Pixel channels available + * @max_rdi_num: Max Raw channels available + */ +struct cam_vfe_hw_get_hw_cap { + uint32_t max_width; + uint32_t max_height; + uint32_t max_pixel_num; + uint32_t max_rdi_num; +}; + +/* + * struct cam_vfe_hw_vfe_out_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @out_port_info: Output Port details to acquire + * @unique_id: Unique Identity of Context to associate with this + * resource. Used for composite grouping of multiple + * resources in the same context + * @is_dual: Dual VFE or not + * @split_id: In case of Dual VFE, this is Left or Right. + * (Default is Left if Single VFE) + * @is_master: In case of Dual VFE, this is Master or Slave. + * (Default is Master in case of Single VFE) + * @dual_slave_core: If Master and Slave exists, HW Index of Slave + * @cdm_ops: CDM operations + */ +struct cam_vfe_hw_vfe_out_acquire_args { + struct cam_isp_resource_node *rsrc_node; + struct cam_isp_out_port_generic_info *out_port_info; + uint32_t unique_id; + uint32_t is_dual; + enum cam_isp_hw_split_id split_id; + uint32_t is_master; + uint32_t dual_slave_core; + struct cam_cdm_utils_ops *cdm_ops; +}; + +/* + * struct cam_vfe_hw_vfe_in_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @res_id: Resource ID of resource to acquire if specific, + * else CAM_ISP_HW_VFE_IN_MAX + * @cdm_ops: CDM operations + * @sync_mode: In case of Dual VFE, this is Master or Slave. + * (Default is Master in case of Single VFE) + * @in_port: Input port details to acquire + */ +struct cam_vfe_hw_vfe_in_acquire_args { + struct cam_isp_resource_node *rsrc_node; + uint32_t res_id; + void *cdm_ops; + enum cam_isp_hw_sync_mode sync_mode; + struct cam_isp_in_port_generic_info *in_port; +}; + +/* + * struct cam_vfe_acquire_args: + * + * @rsrc_type: Type of Resource (OUT/IN) to acquire + * @tasklet: Tasklet to associate with this resource. This is + * used to schedule bottom of IRQ events associated + * with this resource. + * @priv: Context data + * @event_cb: Callback function to hw mgr in case of hw events + * @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 { + enum cam_isp_resource_type rsrc_type; + void *tasklet; + void *priv; + cam_hw_mgr_event_cb_func event_cb; + 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; + }; +}; + +/* + * struct cam_vfe_clock_update_args: + * + * @node_res: Resource to get the time stamp + * @clk_rate: Clock rate requested + */ +struct cam_vfe_clock_update_args { + struct cam_isp_resource_node *node_res; + uint64_t clk_rate; +}; + +/* + * struct cam_vfe_core_config_args: + * + * @node_res: Resource to get the time stamp + * @core_config: Core config for IFE + */ +struct cam_vfe_core_config_args { + struct cam_isp_resource_node *node_res; + struct cam_isp_core_config core_config; +}; + +/* + * struct cam_vfe_bw_update_args_v2: + * + * @node_res: Resource to get the BW + * @isp_vote: Vote info according to usage data (left/right/rdi) + */ +struct cam_vfe_bw_update_args_v2 { + struct cam_isp_resource_node *node_res; + struct cam_axi_vote isp_vote; +}; + +/* + * struct cam_vfe_bw_update_args: + * + * @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 + */ +struct cam_vfe_bw_update_args { + struct cam_isp_resource_node *node_res; + uint64_t camnoc_bw_bytes; + 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 +}; + +/* + * struct cam_vfe_bw_control_args: + * + * @node_res: Resource to get the time stamp + * @action: Bandwidth control action + */ +struct cam_vfe_bw_control_args { + struct cam_isp_resource_node *node_res; + enum cam_vfe_bw_control_action action; +}; + +/* + * struct cam_vfe_top_irq_evt_payload: + * + * @Brief: This structure is used to save payload for IRQ + * related to VFE_TOP resources + * + * @list: list_head node for the payload + * @irq_reg_val: IRQ and Error register values, read when IRQ was + * handled + * @ts: Timestamp + */ +struct cam_vfe_top_irq_evt_payload { + struct list_head list; + uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX]; + struct cam_isp_timestamp ts; +}; + +/* + * struct cam_vfe_bus_irq_evt_payload: + * + * @Brief: This structure is used to save payload for IRQ + * related to VFE_BUS resources + * + * @list: list_head node for the payload + * @core_index: Index of VFE HW that generated this IRQ event + * @debug_status_0: Value of debug status_0 register at time of IRQ + * @evt_id: IRQ event + * @irq_reg_val: IRQ and Error register values, read when IRQ was + * handled + * @error_type: Identify different errors + * @ts: Timestamp + */ +struct cam_vfe_bus_irq_evt_payload { + struct list_head list; + uint32_t core_index; + uint32_t debug_status_0; + uint32_t ccif_violation_status; + uint32_t overflow_status; + uint32_t image_size_violation_status; + uint32_t evt_id; + uint32_t irq_reg_val[CAM_IFE_BUS_IRQ_REGISTERS_MAX]; + struct cam_isp_timestamp ts; +}; + +/** + * struct cam_ubwc_generic_plane_config - UBWC Plane configuration info + * + * @port_type: Port Type + * @meta_stride: UBWC metadata stride + * @meta_size: UBWC metadata plane size + * @meta_offset: UBWC metadata offset + * @packer_config: UBWC packer config + * @mode_config: UBWC mode config + * @static ctrl: UBWC static ctrl + * @ctrl_2: UBWC ctrl 2 + * @tile_config: UBWC tile config + * @h_init: UBWC horizontal initial coordinate in pixels + * @v_init: UBWC vertical initial coordinate in lines + * @stats_ctrl_2: UBWC stats control + * @lossy_threshold0 UBWC lossy threshold 0 + * @lossy_threshold1 UBWC lossy threshold 1 + * @lossy_var_offset UBWC offset variance threshold + * @bandwidth limit UBWC bandwidth limit + */ +struct cam_vfe_generic_ubwc_plane_config { + uint32_t port_type; + uint32_t meta_stride; + uint32_t meta_size; + uint32_t meta_offset; + uint32_t packer_config; + uint32_t mode_config_0; + uint32_t mode_config_1; + uint32_t tile_config; + uint32_t h_init; + uint32_t v_init; + uint32_t static_ctrl; + uint32_t ctrl_2; + uint32_t stats_ctrl_2; + uint32_t lossy_threshold_0; + uint32_t lossy_threshold_1; + uint32_t lossy_var_offset; + uint32_t bandwidth_limit; +}; + +/** + * struct cam_ubwc_generic_config - UBWC Configuration Payload + * + * @api_version: UBWC config api version + * @ubwc_plane_config: Array of UBWC configurations per plane + */ +struct cam_vfe_generic_ubwc_config { + uint32_t api_version; + struct cam_vfe_generic_ubwc_plane_config + ubwc_plane_cfg[CAM_PACKET_MAX_PLANES - 1]; +}; + +/* + * cam_vfe_hw_init() + * + * @Brief: Initialize VFE HW device + * + * @vfe_hw: vfe_hw interface to fill in and return on + * successful initialization + * @hw_idx: Index of VFE HW + */ +int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx); + +/* + * cam_vfe_put_evt_payload() + * + * @Brief: Put the evt payload back to free list + * + * @core_info: VFE HW core_info + * @evt_payload: Event payload data + */ +int cam_vfe_put_evt_payload(void *core_info, + struct cam_vfe_top_irq_evt_payload **evt_payload); + +#endif /* _CAM_VFE_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile new file mode 100644 index 000000000000..1609a7a04808 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_soc.o cam_vfe_dev.o cam_vfe_core.o +obj-$(CONFIG_SPECTRA_CAMERA) += vfe_bus/ vfe_top/ vfe17x/ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c new file mode 100644 index 000000000000..0fe3e9c79f35 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -0,0 +1,748 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "cam_tasklet_util.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_vfe_soc.h" +#include "cam_vfe_core.h" +#include "cam_vfe_bus.h" +#include "cam_vfe_top.h" +#include "cam_ife_hw_mgr.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + +static const char drv_name[] = "vfe"; + +#define CAM_VFE_17X_CLEAR_0_REG_OFFSET 0x00000064 +#define CAM_VFE_17X_CLEAR_1_REG_OFFSET 0x00000068 +#define CAM_VFE_17X_IRQ_CMD_REG_OFFSET 0x00000058 +#define CAM_VFE_17X_TOP_RESET_MASK 0x80000000 + +#define CAM_VFE_48X_CLEAR_0_REG_OFFSET 0x00000048 +#define CAM_VFE_48X_CLEAR_1_REG_OFFSET 0x0000004C +#define CAM_VFE_48X_CLEAR_2_REG_OFFSET 0x00000050 +#define CAM_VFE_48X_IRQ_CMD_REG_OFFSET 0x00000038 +#define CAM_VFE_48X_TOP_RESET_MASK 0x00000001 + +#define CAM_VFE_LITE_48X_CLEAR_0_REG_OFFSET 0x00000034 +#define CAM_VFE_LITE_48X_CLEAR_1_REG_OFFSET 0x00000038 +#define CAM_VFE_LITE_48X_CLEAR_2_REG_OFFSET 0x0000003C +#define CAM_VFE_LITE_48X_IRQ_CMD_REG_OFFSET 0x00000024 +#define CAM_VFE_LITE_48X_TOP_RESET_MASK 0x00020000 + +int cam_vfe_get_hw_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size) +{ + struct cam_hw_info *vfe_dev = hw_priv; + struct cam_vfe_hw_core_info *core_info = NULL; + int rc = 0; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + core_info = (struct cam_vfe_hw_core_info *)vfe_dev->core_info; + + if (core_info->vfe_top->hw_ops.get_hw_caps) + core_info->vfe_top->hw_ops.get_hw_caps( + core_info->vfe_top->top_priv, + get_hw_cap_args, arg_size); + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +int cam_vfe_reset_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc = -EINVAL; + struct cam_hw_info *vfe_hw; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + void __iomem *mem_base; + + vfe_hw = th_payload->handler_priv; + soc_info = &vfe_hw->soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + CAM_DBG(CAM_ISP, "Enter"); + + /* + * Clear All IRQs to avoid spurious IRQs immediately + * after Reset Done. + */ + CAM_DBG(CAM_ISP, "TOP_IRQ_STATUS_0 = 0x%x", + th_payload->evt_status_arr[0]); + + mem_base = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base; + + switch (soc_info->hw_version) { + case CAM_CPAS_TITAN_480_V100: + if (!soc_private->is_ife_lite) { + if (th_payload->evt_status_arr[0] & 0x1) { + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_48X_CLEAR_0_REG_OFFSET); + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_48X_CLEAR_1_REG_OFFSET); + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_48X_CLEAR_2_REG_OFFSET); + cam_io_w(0x00000001, mem_base + + CAM_VFE_48X_IRQ_CMD_REG_OFFSET); + CAM_DBG(CAM_ISP, + "Calling Complete for RESET CMD"); + complete(&vfe_hw->hw_complete); + rc = 0; + } + } else { + if (th_payload->evt_status_arr[0] & (1<<17)) { + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_LITE_48X_CLEAR_0_REG_OFFSET); + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_LITE_48X_CLEAR_1_REG_OFFSET); + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_LITE_48X_CLEAR_2_REG_OFFSET); + cam_io_w(0x00000001, mem_base + + CAM_VFE_LITE_48X_IRQ_CMD_REG_OFFSET); + CAM_DBG(CAM_ISP, + "Calling Complete for RESET CMD"); + complete(&vfe_hw->hw_complete); + rc = 0; + } + } + break; + default: + if (th_payload->evt_status_arr[0] & (1<<31)) { + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_17X_CLEAR_0_REG_OFFSET); + cam_io_w(0xFFFFFFFF, mem_base + + CAM_VFE_17X_CLEAR_1_REG_OFFSET); + cam_io_w(0x00000001, mem_base + + CAM_VFE_17X_IRQ_CMD_REG_OFFSET); + CAM_DBG(CAM_ISP, "Calling Complete for RESET CMD"); + complete(&vfe_hw->hw_complete); + rc = 0; + } + break; + } + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +int cam_vfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_isp_resource_node *isp_res = NULL; + int rc = 0; + uint32_t reset_core_args = + CAM_VFE_HW_RESET_HW_AND_REG; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + mutex_lock(&vfe_hw->hw_mutex); + vfe_hw->open_count++; + if (vfe_hw->open_count > 1) { + mutex_unlock(&vfe_hw->hw_mutex); + CAM_DBG(CAM_ISP, "VFE has already been initialized cnt %d", + vfe_hw->open_count); + return 0; + } + mutex_unlock(&vfe_hw->hw_mutex); + + soc_info = &vfe_hw->soc_info; + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + + /* Turn ON Regulators, Clocks and other SOC resources */ + rc = cam_vfe_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "Enable SOC failed"); + rc = -EFAULT; + goto decrement_open_cnt; + } + + isp_res = (struct cam_isp_resource_node *)init_hw_args; + if (isp_res && isp_res->init) { + rc = isp_res->init(isp_res, NULL, 0); + if (rc) { + CAM_ERR(CAM_ISP, "init Failed rc=%d", rc); + goto disable_soc; + } + } + + CAM_DBG(CAM_ISP, "Enable soc done"); + + /* Do HW Reset */ + rc = cam_vfe_reset(hw_priv, &reset_core_args, sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Reset Failed rc=%d", rc); + goto deinint_vfe_res; + } + + rc = core_info->vfe_bus->hw_ops.init(core_info->vfe_bus->bus_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_ISP, "Bus HW init Failed rc=%d", rc); + goto deinint_vfe_res; + } + + rc = core_info->vfe_top->hw_ops.init(core_info->vfe_top->top_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_ISP, "Top HW init Failed rc=%d", rc); + 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; + +deinint_vfe_res: + if (isp_res && isp_res->deinit) + isp_res->deinit(isp_res, NULL, 0); +disable_soc: + cam_vfe_disable_soc_resources(soc_info); +decrement_open_cnt: + mutex_lock(&vfe_hw->hw_mutex); + vfe_hw->open_count--; + mutex_unlock(&vfe_hw->hw_mutex); + return rc; +} + +int cam_vfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_isp_resource_node *isp_res = NULL; + int rc = 0; + uint32_t reset_core_args = + CAM_VFE_HW_RESET_HW_AND_REG; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + mutex_lock(&vfe_hw->hw_mutex); + if (!vfe_hw->open_count) { + mutex_unlock(&vfe_hw->hw_mutex); + CAM_ERR(CAM_ISP, "Error. Unbalanced deinit"); + return -EFAULT; + } + vfe_hw->open_count--; + if (vfe_hw->open_count) { + mutex_unlock(&vfe_hw->hw_mutex); + CAM_DBG(CAM_ISP, "open_cnt non-zero =%d", vfe_hw->open_count); + return 0; + } + mutex_unlock(&vfe_hw->hw_mutex); + + soc_info = &vfe_hw->soc_info; + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + + rc = core_info->vfe_bus->hw_ops.deinit(core_info->vfe_bus->bus_priv, + NULL, 0); + 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); + if (rc) + CAM_ERR(CAM_ISP, "deinit failed"); + } + + rc = cam_vfe_reset(hw_priv, &reset_core_args, sizeof(uint32_t)); + + /* Turn OFF Regulators, Clocks and other SOC resources */ + CAM_DBG(CAM_ISP, "Disable SOC resource"); + rc = cam_vfe_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_ISP, "Disable SOC failed"); + + vfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +int cam_vfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) +{ + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + uint32_t top_reset_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + int rc; + + CAM_DBG(CAM_ISP, "Enter"); + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + soc_info = &vfe_hw->soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + + memset(top_reset_irq_reg_mask, 0, sizeof(top_reset_irq_reg_mask)); + + switch (soc_info->hw_version) { + case CAM_CPAS_TITAN_480_V100: + if (!soc_private->is_ife_lite) + top_reset_irq_reg_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + = CAM_VFE_48X_TOP_RESET_MASK; + else + top_reset_irq_reg_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + = CAM_VFE_LITE_48X_TOP_RESET_MASK; + break; + default: + top_reset_irq_reg_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + = CAM_VFE_17X_TOP_RESET_MASK; + break; + } + + core_info->reset_irq_handle = cam_irq_controller_subscribe_irq( + core_info->vfe_irq_controller, CAM_IRQ_PRIORITY_0, + top_reset_irq_reg_mask, vfe_hw, + cam_vfe_reset_irq_top_half, NULL, NULL, NULL); + if (core_info->reset_irq_handle < 1) { + CAM_ERR(CAM_ISP, "subscribe irq controller failed"); + core_info->reset_irq_handle = 0; + return -EFAULT; + } + + reinit_completion(&vfe_hw->hw_complete); + + CAM_DBG(CAM_ISP, "calling RESET on VFE:%d", soc_info->index); + + core_info->vfe_top->hw_ops.reset(core_info->vfe_top->top_priv, + reset_core_args, arg_size); + + /* Wait for Completion or Timeout of 500ms */ + rc = wait_for_completion_timeout(&vfe_hw->hw_complete, 500); + + if (!rc) + CAM_ERR(CAM_ISP, "Reset Timeout"); + else + CAM_DBG(CAM_ISP, "reset complete done (%d)", rc); + + rc = cam_irq_controller_unsubscribe_irq( + core_info->vfe_irq_controller, core_info->reset_irq_handle); + if (rc) + CAM_ERR(CAM_ISP, "Error. Unsubscribe failed"); + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp) +{ + struct timespec ts; + + get_monotonic_boottime(&ts); + time_stamp->mono_time.tv_sec = ts.tv_sec; + time_stamp->mono_time.tv_usec = ts.tv_nsec/1000; +} + +int cam_vfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) +{ + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_vfe_acquire_args *acquire; + int rc = -ENODEV; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_vfe_acquire_args))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + 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) { + 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) { + rc = core_info->vfe_bus->hw_ops.reserve( + core_info->vfe_bus->bus_priv, acquire, + sizeof(*acquire)); + } 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); + + return rc; +} + +int cam_vfe_release(void *hw_priv, void *release_args, uint32_t arg_size) +{ + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_isp_resource_node *isp_res; + int rc = -ENODEV; + + if (!hw_priv || !release_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + isp_res = (struct cam_isp_resource_node *) release_args; + + mutex_lock(&vfe_hw->hw_mutex); + if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_IN) + rc = core_info->vfe_top->hw_ops.release( + core_info->vfe_top->top_priv, isp_res, + sizeof(*isp_res)); + else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) + rc = core_info->vfe_bus->hw_ops.release( + core_info->vfe_bus->bus_priv, isp_res, + sizeof(*isp_res)); + 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); + + return rc; +} + + +int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size) +{ + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_isp_resource_node *isp_res; + struct cam_hw_soc_info *soc_info = NULL; + int rc = 0; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + soc_info = &vfe_hw->soc_info; + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + isp_res = (struct cam_isp_resource_node *)start_args; + core_info->tasklet_info = isp_res->tasklet_info; + + mutex_lock(&vfe_hw->hw_mutex); + if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_IN) { + rc = core_info->vfe_top->hw_ops.start( + core_info->vfe_top->top_priv, isp_res, + sizeof(struct cam_isp_resource_node)); + + if (rc) + CAM_ERR(CAM_ISP, "Failed to start VFE IN"); + } else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) { + rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0); + + if (rc) + CAM_ERR(CAM_ISP, "Failed to start VFE OUT"); + } 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); + + if (rc) + CAM_ERR(CAM_ISP, "Failed to start BUS RD"); + } + } else { + CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type); + rc = -EFAULT; + } + + mutex_unlock(&vfe_hw->hw_mutex); + + return rc; +} + +int cam_vfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size) +{ + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_isp_resource_node *isp_res; + int rc = -EINVAL; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + isp_res = (struct cam_isp_resource_node *)stop_args; + + mutex_lock(&vfe_hw->hw_mutex); + if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_IN) { + rc = core_info->vfe_top->hw_ops.stop( + core_info->vfe_top->top_priv, isp_res, + 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); + } + + if (core_info->reset_irq_handle > 0) { + cam_irq_controller_unsubscribe_irq( + core_info->vfe_irq_controller, + core_info->reset_irq_handle); + core_info->reset_irq_handle = 0; + } + + mutex_unlock(&vfe_hw->hw_mutex); + + return rc; +} + +int cam_vfe_read(void *hw_priv, void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_write(void *hw_priv, void *write_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *vfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_vfe_hw_info *hw_info = NULL; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + soc_info = &vfe_hw->soc_info; + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + hw_info = core_info->vfe_hw_info; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_CHANGE_BASE: + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + case CAM_ISP_HW_CMD_CLOCK_UPDATE: + case CAM_ISP_HW_CMD_BW_UPDATE: + case CAM_ISP_HW_CMD_BW_CONTROL: + case CAM_ISP_HW_CMD_CORE_CONFIG: + case CAM_ISP_HW_CMD_BW_UPDATE_V2: + 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_GET_BUF_UPDATE: + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: + case CAM_ISP_HW_CMD_UBWC_UPDATE: + case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: + case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: + rc = core_info->vfe_bus->hw_ops.process_cmd( + 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; + break; + } + return rc; +} + +irqreturn_t cam_vfe_irq(int irq_num, void *data) +{ + struct cam_hw_info *vfe_hw; + struct cam_vfe_hw_core_info *core_info; + + if (!data) + return IRQ_NONE; + + vfe_hw = (struct cam_hw_info *)data; + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + + return cam_irq_controller_handle_irq(irq_num, + core_info->vfe_irq_controller); +} + +int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_vfe_hw_info *vfe_hw_info) +{ + int rc = -EINVAL; + struct cam_vfe_soc_private *soc_private = NULL; + + CAM_DBG(CAM_ISP, "Enter"); + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + rc = cam_irq_controller_init(drv_name, + CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX), + vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller); + if (rc) { + CAM_ERR(CAM_ISP, + "Error, cam_irq_controller_init failed rc = %d", rc); + return rc; + } + + rc = cam_vfe_top_init(vfe_hw_info->top_version, soc_info, hw_intf, + vfe_hw_info->top_hw_info, core_info->vfe_irq_controller, + &core_info->vfe_top); + if (rc) { + CAM_ERR(CAM_ISP, "Error, cam_vfe_top_init failed rc = %d", rc); + goto deinit_controller; + } + + 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) { + CAM_ERR(CAM_ISP, "Error, cam_vfe_bus_init failed rc = %d", rc); + goto deinit_top; + } + + /* Read Bus is not valid for vfe-lite */ + if (!soc_private->is_ife_lite) { + 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_WARN(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); + } + + spin_lock_init(&core_info->spin_lock); + + return rc; + +deinit_top: + cam_vfe_top_deinit(vfe_hw_info->top_version, + &core_info->vfe_top); + +deinit_controller: + cam_irq_controller_deinit(&core_info->vfe_irq_controller); + + return rc; +} + +int cam_vfe_core_deinit(struct cam_vfe_hw_core_info *core_info, + struct cam_vfe_hw_info *vfe_hw_info) +{ + int rc = -EINVAL; + unsigned long flags; + + spin_lock_irqsave(&core_info->spin_lock, flags); + + rc = cam_vfe_bus_deinit(vfe_hw_info->bus_version, + &core_info->vfe_bus); + if (rc) + CAM_ERR(CAM_ISP, "Error cam_vfe_bus_deinit failed rc=%d", rc); + + rc = cam_vfe_top_deinit(vfe_hw_info->top_version, + &core_info->vfe_top); + if (rc) + CAM_ERR(CAM_ISP, "Error cam_vfe_top_deinit failed rc=%d", rc); + + rc = cam_irq_controller_deinit(&core_info->vfe_irq_controller); + if (rc) + CAM_ERR(CAM_ISP, + "Error cam_irq_controller_deinit failed rc=%d", rc); + + spin_unlock_irqrestore(&core_info->spin_lock, flags); + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h new file mode 100644 index 000000000000..43afd0377057 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_CORE_H_ +#define _CAM_VFE_CORE_H_ + +#include +#include "cam_hw_intf.h" +#include "cam_vfe_top.h" +#include "cam_vfe_bus.h" +#include "cam_vfe_hw_intf.h" + +struct cam_vfe_hw_info { + struct cam_irq_controller_reg_info *irq_reg_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; + void *camif_reg; + + uint32_t camif_lite_version; + void *camif_lite_reg; + + uint32_t testgen_version; + void *testgen_reg; + + uint32_t num_qos_settings; + struct cam_isp_reg_val_pair *qos_settings; + + uint32_t num_ds_settings; + struct cam_isp_reg_val_pair *ds_settings; + + uint32_t num_vbif_settings; + struct cam_isp_reg_val_pair *vbif_settings; +}; + +#define CAM_VFE_EVT_MAX 256 + +struct cam_vfe_hw_core_info { + struct cam_vfe_hw_info *vfe_hw_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; + spinlock_t spin_lock; + int reset_irq_handle; +}; + +int cam_vfe_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size); +int cam_vfe_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_vfe_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size); +int cam_vfe_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size); +int cam_vfe_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size); +int cam_vfe_release(void *device_priv, + void *reserve_args, uint32_t arg_size); +int cam_vfe_start(void *device_priv, + void *start_args, uint32_t arg_size); +int cam_vfe_stop(void *device_priv, + void *stop_args, uint32_t arg_size); +int cam_vfe_read(void *device_priv, + void *read_args, uint32_t arg_size); +int cam_vfe_write(void *device_priv, + void *write_args, uint32_t arg_size); +int cam_vfe_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); + +irqreturn_t cam_vfe_irq(int irq_num, void *data); + +int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_vfe_hw_info *vfe_hw_info); + +int cam_vfe_core_deinit(struct cam_vfe_hw_core_info *core_info, + struct cam_vfe_hw_info *vfe_hw_info); + +#endif /* _CAM_VFE_CORE_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c new file mode 100644 index 000000000000..362d513c6a8f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + + +#include +#include +#include +#include "cam_vfe_dev.h" +#include "cam_vfe_core.h" +#include "cam_vfe_soc.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX] = {0, 0, 0, 0}; + +static char vfe_dev_name[8]; + +int cam_vfe_probe(struct platform_device *pdev) +{ + struct cam_hw_info *vfe_hw = NULL; + struct cam_hw_intf *vfe_hw_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + struct cam_vfe_hw_info *hw_info = NULL; + int rc = 0; + + vfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!vfe_hw_intf) { + rc = -ENOMEM; + goto end; + } + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &vfe_hw_intf->hw_idx); + + vfe_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!vfe_hw) { + rc = -ENOMEM; + goto free_vfe_hw_intf; + } + + memset(vfe_dev_name, 0, sizeof(vfe_dev_name)); + snprintf(vfe_dev_name, sizeof(vfe_dev_name), + "vfe%1u", vfe_hw_intf->hw_idx); + + vfe_hw->soc_info.pdev = pdev; + vfe_hw->soc_info.dev = &pdev->dev; + vfe_hw->soc_info.dev_name = vfe_dev_name; + vfe_hw_intf->hw_priv = vfe_hw; + vfe_hw_intf->hw_ops.get_hw_caps = cam_vfe_get_hw_caps; + vfe_hw_intf->hw_ops.init = cam_vfe_init_hw; + vfe_hw_intf->hw_ops.deinit = cam_vfe_deinit_hw; + vfe_hw_intf->hw_ops.reset = cam_vfe_reset; + vfe_hw_intf->hw_ops.reserve = cam_vfe_reserve; + vfe_hw_intf->hw_ops.release = cam_vfe_release; + vfe_hw_intf->hw_ops.start = cam_vfe_start; + vfe_hw_intf->hw_ops.stop = cam_vfe_stop; + vfe_hw_intf->hw_ops.read = cam_vfe_read; + vfe_hw_intf->hw_ops.write = cam_vfe_write; + vfe_hw_intf->hw_ops.process_cmd = cam_vfe_process_cmd; + vfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_VFE; + + CAM_DBG(CAM_ISP, "type %d index %d", + vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx); + + platform_set_drvdata(pdev, vfe_hw_intf); + + vfe_hw->core_info = kzalloc(sizeof(struct cam_vfe_hw_core_info), + GFP_KERNEL); + if (!vfe_hw->core_info) { + CAM_DBG(CAM_ISP, "Failed to alloc for core"); + rc = -ENOMEM; + goto free_vfe_hw; + } + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "Of_match Failed"); + rc = -EINVAL; + goto free_core_info; + } + hw_info = (struct cam_vfe_hw_info *)match_dev->data; + core_info->vfe_hw_info = hw_info; + + rc = cam_vfe_init_soc_resources(&vfe_hw->soc_info, cam_vfe_irq, + vfe_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Failed to init soc rc=%d", rc); + goto free_core_info; + } + + rc = cam_vfe_core_init(core_info, &vfe_hw->soc_info, + vfe_hw_intf, hw_info); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Failed to init core rc=%d", rc); + goto deinit_soc; + } + + vfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&vfe_hw->hw_mutex); + spin_lock_init(&vfe_hw->hw_lock); + init_completion(&vfe_hw->hw_complete); + + if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) + cam_vfe_hw_list[vfe_hw_intf->hw_idx] = vfe_hw_intf; + + cam_vfe_init_hw(vfe_hw, NULL, 0); + cam_vfe_deinit_hw(vfe_hw, NULL, 0); + + CAM_DBG(CAM_ISP, "VFE%d probe successful", vfe_hw_intf->hw_idx); + + return rc; + +deinit_soc: + if (cam_vfe_deinit_soc_resources(&vfe_hw->soc_info)) + CAM_ERR(CAM_ISP, "Failed to deinit soc"); +free_core_info: + kfree(vfe_hw->core_info); +free_vfe_hw: + kfree(vfe_hw); +free_vfe_hw_intf: + kfree(vfe_hw_intf); +end: + return rc; +} + +int cam_vfe_remove(struct platform_device *pdev) +{ + struct cam_hw_info *vfe_hw = NULL; + struct cam_hw_intf *vfe_hw_intf = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + int rc = 0; + + vfe_hw_intf = platform_get_drvdata(pdev); + if (!vfe_hw_intf) { + CAM_ERR(CAM_ISP, "Error! No data in pdev"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "type %d index %d", + vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx); + + if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) + cam_vfe_hw_list[vfe_hw_intf->hw_idx] = NULL; + + vfe_hw = vfe_hw_intf->hw_priv; + if (!vfe_hw) { + CAM_ERR(CAM_ISP, "Error! HW data is NULL"); + rc = -ENODEV; + goto free_vfe_hw_intf; + } + + core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; + if (!core_info) { + CAM_ERR(CAM_ISP, "Error! core data NULL"); + rc = -EINVAL; + goto deinit_soc; + } + + rc = cam_vfe_core_deinit(core_info, core_info->vfe_hw_info); + if (rc < 0) + CAM_ERR(CAM_ISP, "Failed to deinit core rc=%d", rc); + + kfree(vfe_hw->core_info); + +deinit_soc: + rc = cam_vfe_deinit_soc_resources(&vfe_hw->soc_info); + if (rc < 0) + CAM_ERR(CAM_ISP, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&vfe_hw->hw_mutex); + kfree(vfe_hw); + + CAM_DBG(CAM_ISP, "VFE%d remove successful", vfe_hw_intf->hw_idx); + +free_vfe_hw_intf: + kfree(vfe_hw_intf); + + return rc; +} + +int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx) +{ + int rc = 0; + + if (cam_vfe_hw_list[hw_idx]) { + *vfe_hw = cam_vfe_hw_list[hw_idx]; + rc = 0; + } else { + *vfe_hw = NULL; + rc = -ENODEV; + } + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h new file mode 100644 index 000000000000..c2d78b69c684 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_DEV_H_ +#define _CAM_VFE_DEV_H_ + +#include + +/* + * cam_vfe_probe() + * + * @brief: Driver probe function called on Boot + * + * @pdev: Platform Device pointer + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_probe(struct platform_device *pdev); + +/* + * cam_vfe_remove() + * + * @brief: Driver remove function + * + * @pdev: Platform Device pointer + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_remove(struct platform_device *pdev); + +#endif /* _CAM_VFE_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c new file mode 100644 index 000000000000..cf899e97f326 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_cpas_api.h" +#include "cam_vfe_soc.h" +#include "cam_debug_util.h" + +static bool cam_vfe_cpas_cb(uint32_t client_handle, void *userdata, + struct cam_cpas_irq_data *irq_data) +{ + bool error_handled = false; + + if (!irq_data) + return error_handled; + + 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, + irq_data->u.enc_err.encerr_status.value); + error_handled = true; + break; + default: + break; + } + + return error_handled; +} + +static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + int rc = 0, num_ubwc_cfg = 0, i = 0; + struct device_node *of_node = NULL; + struct platform_device *pdev = NULL; + struct cam_vfe_soc_private *vfe_soc_private; + + pdev = soc_info->pdev; + of_node = pdev->dev.of_node; + vfe_soc_private = soc_info->soc_private; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "Error! get DT properties failed rc=%d", rc); + return rc; + } + + vfe_soc_private->is_ife_lite = false; + if (strnstr(soc_info->compatible, "lite", + strlen(soc_info->compatible)) != NULL) { + vfe_soc_private->is_ife_lite = true; + goto end; + } + + switch (soc_info->hw_version) { + case CAM_CPAS_TITAN_480_V100: + num_ubwc_cfg = of_property_count_u32_elems(of_node, + "ubwc-static-cfg"); + + if (num_ubwc_cfg < 0 || num_ubwc_cfg > UBWC_STATIC_CONFIG_MAX) { + CAM_ERR(CAM_ISP, "wrong num_ubwc_cfg: %d", + num_ubwc_cfg); + rc = num_ubwc_cfg; + goto end; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, + "ubwc-static-cfg", i, + &vfe_soc_private->ubwc_static_ctrl[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "unable to read ubwc static config"); + break; + } + } + break; + default: + break; + } + +end: + return rc; +} + +static int cam_vfe_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t vfe_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, vfe_irq_handler, + irq_data); + if (rc) + CAM_ERR(CAM_ISP, + "Error! Request platform resource failed rc=%d", rc); + + return rc; +} + +static int cam_vfe_release_platform_resource(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_ERR(CAM_ISP, + "Error! Release platform resource failed rc=%d", rc); + + return rc; +} + +int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t vfe_irq_handler, void *irq_data) +{ + int rc = 0; + struct cam_vfe_soc_private *soc_private; + struct cam_cpas_register_params cpas_register_param; + + soc_private = kzalloc(sizeof(struct cam_vfe_soc_private), + GFP_KERNEL); + if (!soc_private) { + CAM_DBG(CAM_ISP, "Error! soc_private Alloc Failed"); + return -ENOMEM; + } + soc_info->soc_private = soc_private; + + rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version); + if (rc) { + CAM_ERR(CAM_ISP, "Error! Invalid cpas version rc=%d", rc); + goto free_soc_private; + } + soc_info->hw_version = soc_private->cpas_version; + + rc = cam_vfe_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Error! Get DT properties failed rc=%d", rc); + goto free_soc_private; + } + + rc = cam_soc_util_get_option_clk_by_name(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 with rc %d", rc); + + rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler, + irq_data); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Error! Request platform resources failed rc=%d", rc); + goto free_soc_private; + } + + 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); + 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; + } + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); +free_soc_private: + kfree(soc_private); + + return rc; +} + +int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_vfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error! soc_info NULL"); + return -ENODEV; + } + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error! soc_private NULL"); + return -ENODEV; + } + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc); + + rc = cam_vfe_release_platform_resource(soc_info); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Error! Release platform resources failed rc=%d", rc); + + rc = cam_soc_util_clk_put(&soc_private->dsp_clk); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Error Put dsp clk failed rc=%d", rc); + + kfree(soc_private); + + return rc; +} + +int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_vfe_soc_private *soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error! Invalid params"); + rc = -EINVAL; + goto end; + } + soc_private = soc_info->soc_private; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + if (strnstr(soc_info->compatible, "lite", + strlen(soc_info->compatible))) { + axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_RDI1; + } else { + axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_VID; + } + + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = 10640000000L; + axi_vote.axi_path[0].mnoc_ab_bw = 10640000000L; + axi_vote.axi_path[0].mnoc_ib_bw = 10640000000L; + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_ISP, "Error! CPAS 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) { + CAM_ERR(CAM_ISP, "Error! enable platform failed rc=%d", rc); + goto stop_cpas; + } + + return rc; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); +end: + return rc; +} + +int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name) +{ + int rc = 0; + struct cam_vfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + if (strcmp(clk_name, CAM_VFE_DSP_CLK_NAME) == 0) { + rc = cam_soc_util_clk_enable(soc_private->dsp_clk, + CAM_VFE_DSP_CLK_NAME, soc_private->dsp_clk_rate); + if (rc) + CAM_ERR(CAM_ISP, + "Error enable dsp clk failed rc=%d", rc); + } + + return rc; +} + +int cam_vfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name) +{ + int rc = 0; + struct cam_vfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + if (strcmp(clk_name, CAM_VFE_DSP_CLK_NAME) == 0) { + rc = cam_soc_util_clk_disable(soc_private->dsp_clk, + CAM_VFE_DSP_CLK_NAME); + if (rc) + CAM_ERR(CAM_ISP, + "Error enable dsp clk failed rc=%d", rc); + } + + return rc; +} + + +int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_vfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error! Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_ISP, "Disable platform failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc); + return rc; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h new file mode 100644 index 000000000000..64d9de084ec1 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_SOC_H_ +#define _CAM_VFE_SOC_H_ + +#include "cam_soc_util.h" +#include "cam_isp_hw.h" + +#define CAM_VFE_DSP_CLK_NAME "ife_dsp_clk" + +#define UBWC_STATIC_CONFIG_MAX 2 + +/* + * struct cam_vfe_soc_private: + * + * @Brief: Private SOC data specific to VFE HW Driver + * + * @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 + * @ubwc_static_ctrl: UBWC static control configuration + * @is_ife_lite: Flag to indicate full vs lite IFE + */ +struct cam_vfe_soc_private { + uint32_t cpas_handle; + uint32_t cpas_version; + struct clk *dsp_clk; + int32_t dsp_clk_index; + int32_t dsp_clk_rate; + uint32_t ubwc_static_ctrl[UBWC_STATIC_CONFIG_MAX]; + bool is_ife_lite; +}; + +/* + * cam_vfe_init_soc_resources() + * + * @Brief: Initialize SOC resources including private data + * + * @soc_info: Device soc information + * @handler: Irq handler function pointer + * @irq_data: Irq handler function Callback data + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t vfe_irq_handler, void *irq_data); + +/* + * cam_vfe_deinit_soc_resources() + * + * @Brief: Deinitialize SOC resources including private data + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_vfe_enable_soc_resources() + * + * @brief: Enable regulator, irq resources, start CPAS + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_vfe_disable_soc_resources() + * + * @brief: Disable regulator, irq resources, stop CPAS + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_vfe_soc_enable_clk() + * + * @brief: Enable clock with given name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to enable + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name); + +/* + * cam_vfe_soc_disable_dsp_clk() + * + * @brief: Disable clock with given name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to enable + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name); + +#endif /* _CAM_VFE_SOC_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile new file mode 100644 index 000000000000..e129ea6999b0 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c new file mode 100644 index 000000000000..5336352a4797 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_vfe170.h" +#include "cam_vfe175.h" +#include "cam_vfe175_130.h" +#include "cam_vfe480.h" +#include "cam_vfe_lite17x.h" +#include "cam_vfe_lite48x.h" +#include "cam_vfe_hw_intf.h" +#include "cam_vfe_core.h" +#include "cam_vfe_dev.h" + +static const struct of_device_id cam_vfe_dt_match[] = { + { + .compatible = "qcom,vfe170", + .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,vfe480", + .data = &cam_vfe480_hw_info, + }, + { + .compatible = "qcom,vfe-lite170", + .data = &cam_vfe_lite17x_hw_info, + }, + { + .compatible = "qcom,vfe-lite175", + .data = &cam_vfe_lite17x_hw_info, + }, + { + .compatible = "qcom,vfe-lite480", + .data = &cam_vfe_lite48x_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_vfe_dt_match); + +static struct platform_driver cam_vfe_driver = { + .probe = cam_vfe_probe, + .remove = cam_vfe_remove, + .driver = { + .name = "cam_vfe", + .owner = THIS_MODULE, + .of_match_table = cam_vfe_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_vfe_init_module(void) +{ + return platform_driver_register(&cam_vfe_driver); +} + +static void __exit cam_vfe_exit_module(void) +{ + platform_driver_unregister(&cam_vfe_driver); +} + +module_init(cam_vfe_init_module); +module_exit(cam_vfe_exit_module); +MODULE_DESCRIPTION("CAM VFE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h new file mode 100644 index 000000000000..748c324f5496 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -0,0 +1,843 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE170_H_ +#define _CAM_VFE170_H_ + +#include "cam_vfe_camif_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] = { + { + .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_camif_ver2_reg vfe170_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_170_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 = 0x0FFF7E80, + .enable_diagnostic_hw = 0x1, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = { + .reset = 0x0000001C, + .cgc_ovd = 0x0000002C, + .enable = 0x00000040, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_reg = { + .reset = 0x00000020, + .cgc_ovd = 0x00000030, + .enable = 0x00000044, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_reg = { + .reset = 0x00000024, + .cgc_ovd = 0x00000034, + .enable = 0x00000048, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_reg = { + .reset = 0x00000028, + .cgc_ovd = 0x00000038, + .enable = 0x0000004C, +}; + +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 = { + &lens_170_reg, + &stats_170_reg, + &color_170_reg, + &zoom_170_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 vfe170_rdi_reg = { + .reg_update_cmd = 0x000004AC, +}; + +static struct cam_vfe_rdi_reg_data vfe_170_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 = { + .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 = { + .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, + .camif_hw_info = { + .common_reg = &vfe170_top_common_reg, + .camif_reg = &vfe170_camif_reg, + .reg_data = &vfe_170_camif_reg_data, + }, + .camif_lite_hw_info = { + .common_reg = NULL, + .camif_lite_reg = NULL, + .reg_data = NULL, + }, + .rdi_hw_info = { + .common_reg = &vfe170_top_common_reg, + .rdi_reg = &vfe170_rdi_reg, + .reg_data = { + &vfe_170_rdi_0_data, + &vfe_170_rdi_1_data, + &vfe_170_rdi_2_data, + NULL, + }, + }, + .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, + }, +}; + +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_reg_offset_ubwc_client 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, + .bw_limit = 0x000025A0, +}; + +static struct cam_vfe_bus_ver2_reg_offset_ubwc_client 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, + .bw_limit = 0x000026A0, +}; + +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, + .debug_status_cfg = 0x0000226C, + .debug_status_0 = 0x00002270, + }, + .num_client = 20, + .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 = &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 = &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, + }, + }, + .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 = 18, + .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, + }, + }, +}; + +struct cam_vfe_hw_info cam_vfe170_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, + + .camif_version = CAM_VFE_CAMIF_VER_2_0, + .camif_reg = &vfe170_camif_reg, + + .camif_lite_version = 0, + .camif_reg = NULL, + +}; + +#endif /* _CAM_VFE170_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h new file mode 100644 index 000000000000..db61bfbdc84b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -0,0 +1,1013 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#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 vfe175_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_top_irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe175_top_irq_reg_set, + .global_clear_offset = 0x00000058, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_camif_ver2_reg vfe175_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_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, + .subscribe_irq_mask0 = 0x00000017, + .subscribe_irq_mask1 = 0x00000000, + .enable_diagnostic_hw = 0x1, +}; + +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_err_irq_mask0 = 0x00400000, + .lite_err_irq_mask1 = 0x00004100, + .lite_subscribe_irq_mask0 = 0x001C0000, + .lite_subscribe_irq_mask1 = 0x0, + .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_175_reg = { + .reset = 0x00000020, + .cgc_ovd = 0x00000030, + .enable = 0x00000044, +}; + +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_175_reg = { + .reset = 0x00000028, + .cgc_ovd = 0x00000038, + .enable = 0x0000004C, +}; + +static struct cam_vfe_top_ver2_reg_offset_common vfe175_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_reg, + &stats_175_reg, + &color_175_reg, + &zoom_175_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_rdi_reg = { + .reg_update_cmd = 0x000004AC, +}; + +static struct cam_vfe_rdi_common_reg_data vfe175_rdi_reg_data = { + .subscribe_irq_mask0 = 0x780001E0, + .subscribe_irq_mask1 = 0x0, + .error_irq_mask0 = 0x0, + .error_irq_mask1 = 0x3C, +}; + +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_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_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 vfe175_top_hw_info = { + .common_reg = &vfe175_top_common_reg, + .camif_hw_info = { + .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 = &vfe175_top_common_reg, + .rdi_reg = &vfe175_rdi_reg, + .common_reg_data = &vfe175_rdi_reg_data, + .reg_data = { + &vfe_175_rdi_0_data, + &vfe_175_rdi_1_data, + &vfe_175_rdi_2_data, + NULL, + }, + }, + .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, + }, +}; + +static struct cam_irq_register_set vfe175_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_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_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_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, + .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_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, + .debug_status_cfg = 0x0000226C, + .debug_status_0 = 0x00002270, + }, + .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_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_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_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 */ + { + .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_hw_info = { + .irq_reg_info = &vfe175_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_2_0, + .bus_hw_info = &vfe175_bus_hw_info, + + .top_version = CAM_VFE_TOP_VER_2_0, + .top_hw_info = &vfe175_top_hw_info, + + .camif_version = CAM_VFE_CAMIF_VER_2_0, + .camif_reg = &vfe175_camif_reg, + + .camif_lite_version = CAM_VFE_CAMIF_LITE_VER_2_0, + .camif_lite_reg = &vfe175_camif_lite_reg, + +}; + +#endif /* _CAM_VFE175_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h new file mode 100644 index 000000000000..03a6409324d8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -0,0 +1,1121 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#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, + .subscribe_irq_mask0 = 0x00000017, + .subscribe_irq_mask1 = 0x00000000, + .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_err_irq_mask0 = 0x00400000, + .lite_err_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_common_reg_data vfe175_130_rdi_reg_data = { + .subscribe_irq_mask0 = 0x780001E0, + .subscribe_irq_mask1 = 0x0, + .error_irq_mask0 = 0x0, + .error_irq_mask1 = 0x3C, +}; + +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, + .common_reg_data = &vfe175_130_rdi_reg_data, + .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, + .buf_size = 0x0000505C, + .stride = 0x00005060, + .unpacker_cfg = 0x00005064, + .latency_buf_allocation = 0x00005078, + .burst_limit = 0x00005080, + }, + }, + .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, + .debug_status_cfg = 0x0000226C, + .debug_status_0 = 0x00002270, + }, + .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_RD_VER_1_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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h new file mode 100644 index 000000000000..e855a54dc723 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -0,0 +1,1360 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_VFE480_H_ +#define _CAM_VFE480_H_ +#include "cam_vfe_camif_ver3.h" +#include "cam_vfe_top_ver3.h" +#include "cam_vfe_core.h" +#include "cam_vfe_bus_ver3.h" +#include "cam_irq_controller.h" + +static struct cam_irq_register_set vfe480_top_irq_reg_set[3] = { + { + .mask_reg_offset = 0x0000003C, + .clear_reg_offset = 0x00000048, + .status_reg_offset = 0x00000054, + }, + { + .mask_reg_offset = 0x00000040, + .clear_reg_offset = 0x0000004C, + .status_reg_offset = 0x00000058, + }, + { + .mask_reg_offset = 0x00000044, + .clear_reg_offset = 0x00000050, + .status_reg_offset = 0x0000005C, + }, +}; + +static struct cam_irq_controller_reg_info vfe480_top_irq_reg_info = { + .num_registers = 3, + .irq_reg_set = vfe480_top_irq_reg_set, + .global_clear_offset = 0x00000038, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_camif_ver3_pp_clc_reg vfe480_camif_reg = { + .hw_version = 0x00002600, + .hw_status = 0x00002604, + .module_cfg = 0x00002660, + .pdaf_raw_crop_width_cfg = 0x00002668, + .pdaf_raw_crop_height_cfg = 0x0000266C, + .line_skip_pattern = 0x00002670, + .pixel_skip_pattern = 0x00002674, + .period_cfg = 0x00002678, + .irq_subsample_pattern = 0x0000267C, + .epoch_irq_cfg = 0x00002680, + .debug_1 = 0x000027F0, + .debug_0 = 0x000027F4, + .test_bus_ctrl = 0x000027F8, + .spare = 0x000027FC, + .reg_update_cmd = 0x00000034, +}; + +static struct cam_vfe_camif_ver3_reg_data vfe_480_camif_reg_data = { + .pp_extern_reg_update_shift = 4, + .dual_pd_extern_reg_update_shift = 17, + .extern_reg_update_mask = 1, + .dual_ife_pix_en_shift = 3, + .operating_mode_shift = 11, + .input_mux_sel_shift = 5, + .pixel_pattern_shift = 24, + .pixel_pattern_mask = 0x7, + .dsp_mode_shift = 24, + .dsp_mode_mask = 0x1, + .dsp_en_shift = 23, + .dsp_en_mask = 0x1, + .reg_update_cmd_data = 0x41, + .epoch_line_cfg = 0x00000014, + .sof_irq_mask = 0x00000001, + .epoch0_irq_mask = 0x00000004, + .epoch1_irq_mask = 0x00000008, + .eof_irq_mask = 0x00000002, + .error_irq_mask0 = 0x82000200, + .error_irq_mask2 = 0x30301F80, + .subscribe_irq_mask1 = 0x00000007, + .enable_diagnostic_hw = 0x1, + .pp_camif_cfg_en_shift = 0, + .pp_camif_cfg_ife_out_en_shift = 8, +}; + +static struct cam_vfe_top_ver3_reg_offset_common vfe480_top_common_reg = { + .hw_version = 0x00000000, + .titan_version = 0x00000004, + .hw_capability = 0x00000008, + .lens_feature = 0x0000000C, + .stats_feature = 0x00000010, + .color_feature = 0x00000014, + .zoom_feature = 0x00000018, + .global_reset_cmd = 0x0000001C, + .core_cfg_0 = 0x0000002C, + .core_cfg_1 = 0x00000030, + .reg_update_cmd = 0x00000034, + .violation_status = 0x00000074, + .core_cgc_ovd_0 = 0x00000020, + .core_cgc_ovd_1 = 0x00000094, + .ahb_cgc_ovd = 0x00000024, + .noc_cgc_ovd = 0x00000028, + .trigger_cdm_events = 0x00000090, + .sbi_frame_idx = 0x00000110, + .dsp_status = 0x0000007C, + .diag_config = 0x00000064, + .diag_sensor_status_0 = 0x00000068, + .diag_sensor_status_1 = 0x00000098, + .bus_overflow_status = 0x0000AA68, +}; + +static struct cam_vfe_camif_lite_ver3_reg vfe480_camif_rdi[3] = { + { + .lite_hw_version = 0x9A00, + .lite_hw_status = 0x9A04, + .lite_module_config = 0x9A60, + .lite_skip_period = 0x9A68, + .lite_irq_subsample_pattern = 0x9A6C, + .lite_epoch_irq = 0x9A70, + .lite_debug_1 = 0x9BF0, + .lite_debug_0 = 0x9BF4, + .lite_test_bus_ctrl = 0x9BF8, + .camif_lite_spare = 0x9BFC, + .reg_update_cmd = 0x34, + }, + { + .lite_hw_version = 0x9C00, + .lite_hw_status = 0x9C04, + .lite_module_config = 0x9C60, + .lite_skip_period = 0x9C68, + .lite_irq_subsample_pattern = 0x9C6C, + .lite_epoch_irq = 0x9C70, + .lite_debug_1 = 0x9DF0, + .lite_debug_0 = 0x9DF4, + .lite_test_bus_ctrl = 0x9DF8, + .camif_lite_spare = 0x9DFC, + .reg_update_cmd = 0x34, + }, + { + .lite_hw_version = 0x9E00, + .lite_hw_status = 0x9E04, + .lite_module_config = 0x9E60, + .lite_skip_period = 0x9E68, + .lite_irq_subsample_pattern = 0x9E6C, + .lite_epoch_irq = 0x9E70, + .lite_debug_1 = 0x9FF0, + .lite_debug_0 = 0x9FF4, + .lite_test_bus_ctrl = 0x9FF8, + .camif_lite_spare = 0x9FFC, + .reg_update_cmd = 0x34, + }, +}; + +static struct cam_vfe_camif_lite_ver3_reg_data vfe480_camif_rdi_reg_data[3] = { + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x2, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x10, + .epoch0_irq_mask = 0x40, + .epoch1_irq_mask = 0x80, + .eof_irq_mask = 0x20, + .error_irq_mask0 = 0x20000000, + .error_irq_mask2 = 0x20000, + .subscribe_irq_mask1 = 0x30, + .enable_diagnostic_hw = 0x1, + }, + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x4, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x100, + .epoch0_irq_mask = 0x400, + .epoch1_irq_mask = 0x800, + .eof_irq_mask = 0x200, + .error_irq_mask0 = 0x10000000, + .error_irq_mask2 = 0x40000, + .subscribe_irq_mask1 = 0x300, + .enable_diagnostic_hw = 0x1, + }, + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x8, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x1000, + .epoch0_irq_mask = 0x4000, + .epoch1_irq_mask = 0x8000, + .eof_irq_mask = 0x2000, + .error_irq_mask0 = 0x8000000, + .error_irq_mask2 = 0x80000, + .subscribe_irq_mask1 = 0x3000, + .enable_diagnostic_hw = 0x1, + }, +}; + +static struct cam_vfe_camif_lite_ver3_reg vfe480_camif_lcr = { + .lite_hw_version = 0xA000, + .lite_hw_status = 0xA004, + .lite_module_config = 0xA060, + .lite_skip_period = 0xA068, + .lite_irq_subsample_pattern = 0xA06C, + .lite_epoch_irq = 0xA070, + .lite_debug_1 = 0xA1F0, + .lite_debug_0 = 0xA1F4, + .lite_test_bus_ctrl = 0xA1F8, + .camif_lite_spare = 0xA1FC, + .reg_update_cmd = 0x0034, +}; + +static struct cam_vfe_camif_lite_ver3_reg_data vfe480_camif_lcr_reg_data = { + .extern_reg_update_shift = 16, + .reg_update_cmd_data = 0x40, + .epoch_line_cfg = 0x00140014, + .sof_irq_mask = 0x100000, + .epoch0_irq_mask = 0x400000, + .epoch1_irq_mask = 0x800000, + .eof_irq_mask = 0x200000, + .error_irq_mask0 = 0x0, + .error_irq_mask2 = 0x18000, + .subscribe_irq_mask1 = 0x300000, + .enable_diagnostic_hw = 0x1, +}; + +static struct cam_vfe_camif_lite_ver3_reg vfe480_camif_pd = { + .lite_hw_version = 0xA400, + .lite_hw_status = 0xA404, + .lite_module_config = 0xA460, + .lite_skip_period = 0xA468, + .lite_irq_subsample_pattern = 0xA46C, + .lite_epoch_irq = 0xA470, + .lite_debug_1 = 0xA5F0, + .lite_debug_0 = 0xA5F4, + .lite_test_bus_ctrl = 0xA5F8, + .camif_lite_spare = 0xA5FC, + .reg_update_cmd = 0x0034, +}; + +static struct cam_vfe_camif_lite_ver3_reg_data vfe480_camif_pd_reg_data = { + .extern_reg_update_shift = 17, + .operating_mode_shift = 13, + .input_mux_sel_shift = 31, + .reg_update_cmd_data = 0x20, + .epoch_line_cfg = 0x00140014, + .sof_irq_mask = 0x10000, + .epoch0_irq_mask = 0x40000, + .epoch1_irq_mask = 0x80000, + .eof_irq_mask = 0x20000, + .error_irq_mask0 = 0x40000000, + .error_irq_mask2 = 0x6000, + .subscribe_irq_mask1 = 0x30000, + .enable_diagnostic_hw = 0x1, +}; + +struct cam_vfe_camif_lite_ver3_hw_info rdi_hw_info_arr[CAM_VFE_RDI_VER2_MAX] = { + { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_rdi[0], + .reg_data = &vfe480_camif_rdi_reg_data[0], + }, + { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_rdi[1], + .reg_data = &vfe480_camif_rdi_reg_data[1], + }, + { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_rdi[2], + .reg_data = &vfe480_camif_rdi_reg_data[2], + }, +}; + +static struct cam_vfe_top_ver3_hw_info vfe480_top_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_reg = &vfe480_camif_reg, + .reg_data = &vfe_480_camif_reg_data, + }, + .pdlib_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_pd, + .reg_data = &vfe480_camif_pd_reg_data, + }, + .rdi_hw_info[0] = &rdi_hw_info_arr[0], + .rdi_hw_info[1] = &rdi_hw_info_arr[1], + .rdi_hw_info[2] = &rdi_hw_info_arr[2], + .lcr_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_lcr, + .reg_data = &vfe480_camif_lcr_reg_data, + }, + .mux_type = { + CAM_VFE_CAMIF_VER_3_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_PDLIB_VER_1_0, + CAM_VFE_LCR_VER_1_0, + }, +}; + +static struct cam_irq_register_set vfe480_bus_irq_reg[2] = { + { + .mask_reg_offset = 0x0000AA18, + .clear_reg_offset = 0x0000AA20, + .status_reg_offset = 0x0000AA28, + }, + { + .mask_reg_offset = 0x0000AA1C, + .clear_reg_offset = 0x0000AA24, + .status_reg_offset = 0x0000AA2C, + }, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe480_ubwc_regs_client_0 = { + .meta_addr = 0x0000AC40, + .meta_cfg = 0x0000AC44, + .mode_cfg = 0x0000AC48, + .stats_ctrl = 0x0000AC4C, + .ctrl_2 = 0x0000AC50, + .lossy_thresh0 = 0x0000AC54, + .lossy_thresh1 = 0x0000AC58, + .off_lossy_var = 0x0000AC5C, + .bw_limit = 0x0000AC1C, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe480_ubwc_regs_client_1 = { + .meta_addr = 0x0000AD40, + .meta_cfg = 0x0000AD44, + .mode_cfg = 0x0000AD48, + .stats_ctrl = 0x0000AD4C, + .ctrl_2 = 0x0000AD50, + .lossy_thresh0 = 0x0000AD54, + .lossy_thresh1 = 0x0000AD58, + .off_lossy_var = 0x0000AD5C, + .bw_limit = 0x0000AD1C, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe480_ubwc_regs_client_4 = { + .meta_addr = 0x0000B040, + .meta_cfg = 0x0000B044, + .mode_cfg = 0x0000B048, + .stats_ctrl = 0x0000B04C, + .ctrl_2 = 0x0000B050, + .lossy_thresh0 = 0x0000B054, + .lossy_thresh1 = 0x0000B058, + .off_lossy_var = 0x0000B05C, + .bw_limit = 0x0000B01C, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe480_ubwc_regs_client_5 = { + .meta_addr = 0x0000B140, + .meta_cfg = 0x0000B144, + .mode_cfg = 0x0000B148, + .stats_ctrl = 0x0000B14C, + .ctrl_2 = 0x0000B150, + .lossy_thresh0 = 0x0000B154, + .lossy_thresh1 = 0x0000B158, + .off_lossy_var = 0x0000B15C, + .bw_limit = 0x0000B11C, +}; + +static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { + .common_reg = { + .hw_version = 0x0000AA00, + .cgc_ovd = 0x0000AA08, + .comp_cfg_0 = 0x0000AA0C, + .comp_cfg_1 = 0x0000AA10, + .if_frameheader_cfg = { + 0x0000AA34, + 0x0000AA38, + 0x0000AA3C, + 0x0000AA40, + 0x0000AA44, + 0x0000AA48, + }, + .ubwc_static_ctrl = 0x0000AA58, + .pwr_iso_cfg = 0x0000AA5C, + .overflow_status_clear = 0x0000AA60, + .ccif_violation_status = 0x0000AA64, + .overflow_status = 0x0000AA68, + .image_size_violation_status = 0x0000AA70, + .debug_status_top_cfg = 0x0000AAD4, + .debug_status_top = 0x0000AAD8, + .test_bus_ctrl = 0x0000AADC, + .irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe480_bus_irq_reg, + .global_clear_offset = 0x0000AA30, + .global_clear_bitmask = 0x00000001, + }, + }, + .num_client = CAM_VFE_BUS_VER3_MAX_CLIENTS, + .bus_client_reg = { + /* BUS Client 0 FULL Y */ + { + .cfg = 0x0000AC00, + .image_addr = 0x0000AC04, + .frame_incr = 0x0000AC08, + .image_cfg_0 = 0x0000AC0C, + .image_cfg_1 = 0x0000AC10, + .image_cfg_2 = 0x0000AC14, + .packer_cfg = 0x0000AC18, + .frame_header_addr = 0x0000AC20, + .frame_header_incr = 0x0000AC24, + .frame_header_cfg = 0x0000AC28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000AC30, + .irq_subsample_pattern = 0x0000AC34, + .framedrop_period = 0x0000AC38, + .framedrop_pattern = 0x0000AC3C, + .system_cache_cfg = 0x0000AC60, + .burst_limit = 0x0000AC64, + .addr_status_0 = 0x0000AC68, + .addr_status_1 = 0x0000AC6C, + .addr_status_2 = 0x0000AC70, + .addr_status_3 = 0x0000AC74, + .debug_status_cfg = 0x0000AC78, + .debug_status_0 = 0x0000AC7C, + .debug_status_1 = 0x0000AC80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = &vfe480_ubwc_regs_client_0, + }, + /* BUS Client 1 FULL C */ + { + .cfg = 0x0000AD00, + .image_addr = 0x0000AD04, + .frame_incr = 0x0000AD08, + .image_cfg_0 = 0x0000AD0C, + .image_cfg_1 = 0x0000AD10, + .image_cfg_2 = 0x0000AD14, + .packer_cfg = 0x0000AD18, + .frame_header_addr = 0x0000AD20, + .frame_header_incr = 0x0000AD24, + .frame_header_cfg = 0x0000AD28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000AD30, + .irq_subsample_pattern = 0x0000AD34, + .framedrop_period = 0x0000AD38, + .framedrop_pattern = 0x0000AD3C, + .system_cache_cfg = 0x0000AD60, + .burst_limit = 0x0000AD64, + .addr_status_0 = 0x0000AD68, + .addr_status_1 = 0x0000AD6C, + .addr_status_2 = 0x0000AD70, + .addr_status_3 = 0x0000AD74, + .debug_status_cfg = 0x0000AD78, + .debug_status_0 = 0x0000AD7C, + .debug_status_1 = 0x0000AD80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = &vfe480_ubwc_regs_client_1, + }, + /* BUS Client 2 DS4 */ + { + .cfg = 0x0000AE00, + .image_addr = 0x0000AE04, + .frame_incr = 0x0000AE08, + .image_cfg_0 = 0x0000AE0C, + .image_cfg_1 = 0x0000AE10, + .image_cfg_2 = 0x0000AE14, + .packer_cfg = 0x0000AE18, + .frame_header_addr = 0x0000AE20, + .frame_header_incr = 0x0000AE24, + .frame_header_cfg = 0x0000AE28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000AE30, + .irq_subsample_pattern = 0x0000AE34, + .framedrop_period = 0x0000AE38, + .framedrop_pattern = 0x0000AE3C, + .system_cache_cfg = 0x0000AE60, + .burst_limit = 0x0000AE64, + .addr_status_0 = 0x0000AE68, + .addr_status_1 = 0x0000AE6C, + .addr_status_2 = 0x0000AE70, + .addr_status_3 = 0x0000AE74, + .debug_status_cfg = 0x0000AE78, + .debug_status_0 = 0x0000AE7C, + .debug_status_1 = 0x0000AE80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* BUS Client 3 DS16 */ + { + .cfg = 0x0000AF00, + .image_addr = 0x0000AF04, + .frame_incr = 0x0000AF08, + .image_cfg_0 = 0x0000AF0C, + .image_cfg_1 = 0x0000AF10, + .image_cfg_2 = 0x0000AF14, + .packer_cfg = 0x0000AF18, + .frame_header_addr = 0x0000AF20, + .frame_header_incr = 0x0000AF24, + .frame_header_cfg = 0x0000AF28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000AF30, + .irq_subsample_pattern = 0x0000AF34, + .framedrop_period = 0x0000AF38, + .framedrop_pattern = 0x0000AF3C, + .system_cache_cfg = 0x0000AF60, + .burst_limit = 0x0000AF64, + .addr_status_0 = 0x0000AF68, + .addr_status_1 = 0x0000AF6C, + .addr_status_2 = 0x0000AF70, + .addr_status_3 = 0x0000AF74, + .debug_status_cfg = 0x0000AF78, + .debug_status_0 = 0x0000AF7C, + .debug_status_1 = 0x0000AF80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* BUS Client 4 DISP Y */ + { + .cfg = 0x0000B000, + .image_addr = 0x0000B004, + .frame_incr = 0x0000B008, + .image_cfg_0 = 0x0000B00C, + .image_cfg_1 = 0x0000B010, + .image_cfg_2 = 0x0000B014, + .packer_cfg = 0x0000B018, + .frame_header_addr = 0x0000B020, + .frame_header_incr = 0x0000B024, + .frame_header_cfg = 0x0000B028, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B030, + .irq_subsample_pattern = 0x0000B034, + .framedrop_period = 0x0000B038, + .framedrop_pattern = 0x0000B03C, + .system_cache_cfg = 0x0000B060, + .burst_limit = 0x0000B064, + .addr_status_0 = 0x0000B068, + .addr_status_1 = 0x0000B06C, + .addr_status_2 = 0x0000B070, + .addr_status_3 = 0x0000B074, + .debug_status_cfg = 0x0000B078, + .debug_status_0 = 0x0000B07C, + .debug_status_1 = 0x0000B080, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = &vfe480_ubwc_regs_client_4, + }, + /* BUS Client 5 DISP C */ + { + .cfg = 0x0000B100, + .image_addr = 0x0000B104, + .frame_incr = 0x0000B108, + .image_cfg_0 = 0x0000B10C, + .image_cfg_1 = 0x0000B110, + .image_cfg_2 = 0x0000B114, + .packer_cfg = 0x0000B118, + .frame_header_addr = 0x0000B120, + .frame_header_incr = 0x0000B124, + .frame_header_cfg = 0x0000B128, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B130, + .irq_subsample_pattern = 0x0000B134, + .framedrop_period = 0x0000B138, + .framedrop_pattern = 0x0000B13C, + .system_cache_cfg = 0x0000B160, + .burst_limit = 0x0000B164, + .addr_status_0 = 0x0000B168, + .addr_status_1 = 0x0000B16C, + .addr_status_2 = 0x0000B170, + .addr_status_3 = 0x0000B174, + .debug_status_cfg = 0x0000B178, + .debug_status_0 = 0x0000B17C, + .debug_status_1 = 0x0000B180, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = &vfe480_ubwc_regs_client_5, + }, + /* BUS Client 6 DISP DS4 */ + { + .cfg = 0x0000B200, + .image_addr = 0x0000B204, + .frame_incr = 0x0000B208, + .image_cfg_0 = 0x0000B20C, + .image_cfg_1 = 0x0000B210, + .image_cfg_2 = 0x0000B214, + .packer_cfg = 0x0000B218, + .frame_header_addr = 0x0000B220, + .frame_header_incr = 0x0000B224, + .frame_header_cfg = 0x0000B228, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B230, + .irq_subsample_pattern = 0x0000B234, + .framedrop_period = 0x0000B238, + .framedrop_pattern = 0x0000B23C, + .system_cache_cfg = 0x0000B260, + .burst_limit = 0x0000B264, + .addr_status_0 = 0x0000B268, + .addr_status_1 = 0x0000B26C, + .addr_status_2 = 0x0000B270, + .addr_status_3 = 0x0000B274, + .debug_status_cfg = 0x0000B278, + .debug_status_0 = 0x0000B27C, + .debug_status_1 = 0x0000B280, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = NULL, + }, + /* BUS Client 7 DISP DS16 */ + { + .cfg = 0x0000B300, + .image_addr = 0x0000B304, + .frame_incr = 0x0000B308, + .image_cfg_0 = 0x0000B30C, + .image_cfg_1 = 0x0000B310, + .image_cfg_2 = 0x0000B314, + .packer_cfg = 0x0000B318, + .frame_header_addr = 0x0000B320, + .frame_header_incr = 0x0000B324, + .frame_header_cfg = 0x0000B328, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B330, + .irq_subsample_pattern = 0x0000B334, + .framedrop_period = 0x0000B338, + .framedrop_pattern = 0x0000B33C, + .system_cache_cfg = 0x0000B360, + .burst_limit = 0x0000B364, + .addr_status_0 = 0x0000B368, + .addr_status_1 = 0x0000B36C, + .addr_status_2 = 0x0000B370, + .addr_status_3 = 0x0000B374, + .debug_status_cfg = 0x0000B378, + .debug_status_0 = 0x0000B37C, + .debug_status_1 = 0x0000B380, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = NULL, + }, + /* BUS Client 8 FD Y */ + { + .cfg = 0x0000B400, + .image_addr = 0x0000B404, + .frame_incr = 0x0000B408, + .image_cfg_0 = 0x0000B40C, + .image_cfg_1 = 0x0000B410, + .image_cfg_2 = 0x0000B414, + .packer_cfg = 0x0000B418, + .frame_header_addr = 0x0000B420, + .frame_header_incr = 0x0000B424, + .frame_header_cfg = 0x0000B428, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B430, + .irq_subsample_pattern = 0x0000B434, + .framedrop_period = 0x0000B438, + .framedrop_pattern = 0x0000B43C, + .system_cache_cfg = 0x0000B460, + .burst_limit = 0x0000B464, + .addr_status_0 = 0x0000B468, + .addr_status_1 = 0x0000B46C, + .addr_status_2 = 0x0000B470, + .addr_status_3 = 0x0000B474, + .debug_status_cfg = 0x0000B478, + .debug_status_0 = 0x0000B47C, + .debug_status_1 = 0x0000B480, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .ubwc_regs = NULL, + }, + /* BUS Client 9 FD C */ + { + .cfg = 0x0000B500, + .image_addr = 0x0000B504, + .frame_incr = 0x0000B508, + .image_cfg_0 = 0x0000B50C, + .image_cfg_1 = 0x0000B510, + .image_cfg_2 = 0x0000B514, + .packer_cfg = 0x0000B518, + .frame_header_addr = 0x0000B520, + .frame_header_incr = 0x0000B524, + .frame_header_cfg = 0x0000B528, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B530, + .irq_subsample_pattern = 0x0000B534, + .framedrop_period = 0x0000B538, + .framedrop_pattern = 0x0000B53C, + .system_cache_cfg = 0x0000B560, + .burst_limit = 0x0000B564, + .addr_status_0 = 0x0000B568, + .addr_status_1 = 0x0000B56C, + .addr_status_2 = 0x0000B570, + .addr_status_3 = 0x0000B574, + .debug_status_cfg = 0x0000B578, + .debug_status_0 = 0x0000B57C, + .debug_status_1 = 0x0000B580, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .ubwc_regs = NULL, + }, + /* BUS Client 10 PIXEL RAW */ + { + .cfg = 0x0000B600, + .image_addr = 0x0000B604, + .frame_incr = 0x0000B608, + .image_cfg_0 = 0x0000B60C, + .image_cfg_1 = 0x0000B610, + .image_cfg_2 = 0x0000B614, + .packer_cfg = 0x0000B618, + .frame_header_addr = 0x0000B620, + .frame_header_incr = 0x0000B624, + .frame_header_cfg = 0x0000B628, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B630, + .irq_subsample_pattern = 0x0000B634, + .framedrop_period = 0x0000B638, + .framedrop_pattern = 0x0000B63C, + .system_cache_cfg = 0x0000B660, + .burst_limit = 0x0000B664, + .addr_status_0 = 0x0000B668, + .addr_status_1 = 0x0000B66C, + .addr_status_2 = 0x0000B670, + .addr_status_3 = 0x0000B674, + .debug_status_cfg = 0x0000B678, + .debug_status_0 = 0x0000B67C, + .debug_status_1 = 0x0000B680, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, + .ubwc_regs = NULL, + }, + /* BUS Client 11 CAMIF PD */ + { + .cfg = 0x0000B700, + .image_addr = 0x0000B704, + .frame_incr = 0x0000B708, + .image_cfg_0 = 0x0000B70C, + .image_cfg_1 = 0x0000B710, + .image_cfg_2 = 0x0000B714, + .packer_cfg = 0x0000B718, + .frame_header_addr = 0x0000B720, + .frame_header_incr = 0x0000B724, + .frame_header_cfg = 0x0000B728, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B730, + .irq_subsample_pattern = 0x0000B734, + .framedrop_period = 0x0000B738, + .framedrop_pattern = 0x0000B73C, + .system_cache_cfg = 0x0000B760, + .burst_limit = 0x0000B764, + .addr_status_0 = 0x0000B768, + .addr_status_1 = 0x0000B76C, + .addr_status_2 = 0x0000B770, + .addr_status_3 = 0x0000B774, + .debug_status_cfg = 0x0000B778, + .debug_status_0 = 0x0000B77C, + .debug_status_1 = 0x0000B780, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_4, + .ubwc_regs = NULL, + }, + /* BUS Client 12 STATS HDR BE */ + { + .cfg = 0x0000B800, + .image_addr = 0x0000B804, + .frame_incr = 0x0000B808, + .image_cfg_0 = 0x0000B80C, + .image_cfg_1 = 0x0000B810, + .image_cfg_2 = 0x0000B814, + .packer_cfg = 0x0000B818, + .frame_header_addr = 0x0000B820, + .frame_header_incr = 0x0000B824, + .frame_header_cfg = 0x0000B828, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B830, + .irq_subsample_pattern = 0x0000B834, + .framedrop_period = 0x0000B838, + .framedrop_pattern = 0x0000B83C, + .system_cache_cfg = 0x0000B860, + .burst_limit = 0x0000B864, + .addr_status_0 = 0x0000B868, + .addr_status_1 = 0x0000B86C, + .addr_status_2 = 0x0000B870, + .addr_status_3 = 0x0000B874, + .debug_status_cfg = 0x0000B878, + .debug_status_0 = 0x0000B87C, + .debug_status_1 = 0x0000B880, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_5, + .ubwc_regs = NULL, + }, + /* BUS Client 13 STATS HDR BHIST */ + { + .cfg = 0x0000B900, + .image_addr = 0x0000B904, + .frame_incr = 0x0000B908, + .image_cfg_0 = 0x0000B90C, + .image_cfg_1 = 0x0000B910, + .image_cfg_2 = 0x0000B914, + .packer_cfg = 0x0000B918, + .frame_header_addr = 0x0000B920, + .frame_header_incr = 0x0000B924, + .frame_header_cfg = 0x0000B928, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000B930, + .irq_subsample_pattern = 0x0000B934, + .framedrop_period = 0x0000B938, + .framedrop_pattern = 0x0000B93C, + .system_cache_cfg = 0x0000B960, + .burst_limit = 0x0000B964, + .addr_status_0 = 0x0000B968, + .addr_status_1 = 0x0000B96C, + .addr_status_2 = 0x0000B970, + .addr_status_3 = 0x0000B974, + .debug_status_cfg = 0x0000B978, + .debug_status_0 = 0x0000B97C, + .debug_status_1 = 0x0000B980, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_5, + .ubwc_regs = NULL, + }, + /* BUS Client 14 STATS TINTLESS BG */ + { + .cfg = 0x0000BA00, + .image_addr = 0x0000BA04, + .frame_incr = 0x0000BA08, + .image_cfg_0 = 0x0000BA0C, + .image_cfg_1 = 0x0000BA10, + .image_cfg_2 = 0x0000BA14, + .packer_cfg = 0x0000BA18, + .frame_header_addr = 0x0000BA20, + .frame_header_incr = 0x0000BA24, + .frame_header_cfg = 0x0000BA28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000BA30, + .irq_subsample_pattern = 0x0000BA34, + .framedrop_period = 0x0000BA38, + .framedrop_pattern = 0x0000BA3C, + .system_cache_cfg = 0x0000BA60, + .burst_limit = 0x0000BA64, + .addr_status_0 = 0x0000BA68, + .addr_status_1 = 0x0000BA6C, + .addr_status_2 = 0x0000BA70, + .addr_status_3 = 0x0000BA74, + .debug_status_cfg = 0x0000BA78, + .debug_status_0 = 0x0000BA7C, + .debug_status_1 = 0x0000BA80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_6, + .ubwc_regs = NULL, + }, + /* BUS Client 15 STATS AWB BG */ + { + .cfg = 0x0000BB00, + .image_addr = 0x0000BB04, + .frame_incr = 0x0000BB08, + .image_cfg_0 = 0x0000BB0C, + .image_cfg_1 = 0x0000BB10, + .image_cfg_2 = 0x0000BB14, + .packer_cfg = 0x0000BB18, + .frame_header_addr = 0x0000BB20, + .frame_header_incr = 0x0000BB24, + .frame_header_cfg = 0x0000BB28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000BB30, + .irq_subsample_pattern = 0x0000BB34, + .framedrop_period = 0x0000BB38, + .framedrop_pattern = 0x0000BB3C, + .system_cache_cfg = 0x0000BB60, + .burst_limit = 0x0000BB64, + .addr_status_0 = 0x0000BB68, + .addr_status_1 = 0x0000BB6C, + .addr_status_2 = 0x0000BB70, + .addr_status_3 = 0x0000BB74, + .debug_status_cfg = 0x0000BB78, + .debug_status_0 = 0x0000BB7C, + .debug_status_1 = 0x0000BB80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_6, + .ubwc_regs = NULL, + }, + /* BUS Client 16 STATS BHIST */ + { + .cfg = 0x0000BC00, + .image_addr = 0x0000BC04, + .frame_incr = 0x0000BC08, + .image_cfg_0 = 0x0000BC0C, + .image_cfg_1 = 0x0000BC10, + .image_cfg_2 = 0x0000BC14, + .packer_cfg = 0x0000BC18, + .frame_header_addr = 0x0000BC20, + .frame_header_incr = 0x0000BC24, + .frame_header_cfg = 0x0000BC28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000BC30, + .irq_subsample_pattern = 0x0000BC34, + .framedrop_period = 0x0000BC38, + .framedrop_pattern = 0x0000BC3C, + .system_cache_cfg = 0x0000BC60, + .burst_limit = 0x0000BC64, + .addr_status_0 = 0x0000BC68, + .addr_status_1 = 0x0000BC6C, + .addr_status_2 = 0x0000BC70, + .addr_status_3 = 0x0000BC74, + .debug_status_cfg = 0x0000BC78, + .debug_status_0 = 0x0000BC7C, + .debug_status_1 = 0x0000BC80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_7, + .ubwc_regs = NULL, + }, + /* BUS Client 17 STATS RS */ + { + .cfg = 0x0000BD00, + .image_addr = 0x0000BD04, + .frame_incr = 0x0000BD08, + .image_cfg_0 = 0x0000BD0C, + .image_cfg_1 = 0x0000BD10, + .image_cfg_2 = 0x0000BD14, + .packer_cfg = 0x0000BD18, + .frame_header_addr = 0x0000BD20, + .frame_header_incr = 0x0000BD24, + .frame_header_cfg = 0x0000BD28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000BD30, + .irq_subsample_pattern = 0x0000BD34, + .framedrop_period = 0x0000BD38, + .framedrop_pattern = 0x0000BD3C, + .system_cache_cfg = 0x0000BD60, + .burst_limit = 0x0000BD64, + .addr_status_0 = 0x0000BD68, + .addr_status_1 = 0x0000BD6C, + .addr_status_2 = 0x0000BD70, + .addr_status_3 = 0x0000BD74, + .debug_status_cfg = 0x0000BD78, + .debug_status_0 = 0x0000BD7C, + .debug_status_1 = 0x0000BD80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_7, + .ubwc_regs = NULL, + }, + /* BUS Client 18 STATS CS */ + { + .cfg = 0x0000BE00, + .image_addr = 0x0000BE04, + .frame_incr = 0x0000BE08, + .image_cfg_0 = 0x0000BE0C, + .image_cfg_1 = 0x0000BE10, + .image_cfg_2 = 0x0000BE14, + .packer_cfg = 0x0000BE18, + .frame_header_addr = 0x0000BE20, + .frame_header_incr = 0x0000BE24, + .frame_header_cfg = 0x0000BE28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000BE30, + .irq_subsample_pattern = 0x0000BE34, + .framedrop_period = 0x0000BE38, + .framedrop_pattern = 0x0000BE3C, + .system_cache_cfg = 0x0000BE60, + .burst_limit = 0x0000BE64, + .addr_status_0 = 0x0000BE68, + .addr_status_1 = 0x0000BE6C, + .addr_status_2 = 0x0000BE70, + .addr_status_3 = 0x0000BE74, + .debug_status_cfg = 0x0000BE78, + .debug_status_0 = 0x0000BE7C, + .debug_status_1 = 0x0000BE80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_7, + .ubwc_regs = NULL, + }, + /* BUS Client 19 STATS IHIST */ + { + .cfg = 0x0000BF00, + .image_addr = 0x0000BF04, + .frame_incr = 0x0000BF08, + .image_cfg_0 = 0x0000BF0C, + .image_cfg_1 = 0x0000BF10, + .image_cfg_2 = 0x0000BF14, + .packer_cfg = 0x0000BF18, + .frame_header_addr = 0x0000BF20, + .frame_header_incr = 0x0000BF24, + .frame_header_cfg = 0x0000BF28, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000BF30, + .irq_subsample_pattern = 0x0000BF34, + .framedrop_period = 0x0000BF38, + .framedrop_pattern = 0x0000BF3C, + .system_cache_cfg = 0x0000BF60, + .burst_limit = 0x0000BF64, + .addr_status_0 = 0x0000BF68, + .addr_status_1 = 0x0000BF6C, + .addr_status_2 = 0x0000BF70, + .addr_status_3 = 0x0000BF74, + .debug_status_cfg = 0x0000BF78, + .debug_status_0 = 0x0000BF7C, + .debug_status_1 = 0x0000BF80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_7, + .ubwc_regs = NULL, + }, + /* BUS Client 20 STATS BF */ + { + .cfg = 0x0000C000, + .image_addr = 0x0000C004, + .frame_incr = 0x0000C008, + .image_cfg_0 = 0x0000C00C, + .image_cfg_1 = 0x0000C010, + .image_cfg_2 = 0x0000C014, + .packer_cfg = 0x0000C018, + .frame_header_addr = 0x0000C020, + .frame_header_incr = 0x0000C024, + .frame_header_cfg = 0x0000C028, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000C030, + .irq_subsample_pattern = 0x0000C034, + .framedrop_period = 0x0000C038, + .framedrop_pattern = 0x0000C03C, + .system_cache_cfg = 0x0000C060, + .burst_limit = 0x0000C064, + .addr_status_0 = 0x0000C068, + .addr_status_1 = 0x0000C06C, + .addr_status_2 = 0x0000C070, + .addr_status_3 = 0x0000C074, + .debug_status_cfg = 0x0000C078, + .debug_status_0 = 0x0000C07C, + .debug_status_1 = 0x0000C080, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_8, + .ubwc_regs = NULL, + }, + /* BUS Client 21 PDAF V2.0 */ + { + .cfg = 0x0000C100, + .image_addr = 0x0000C104, + .frame_incr = 0x0000C108, + .image_cfg_0 = 0x0000C10C, + .image_cfg_1 = 0x0000C110, + .image_cfg_2 = 0x0000C114, + .packer_cfg = 0x0000C118, + .frame_header_addr = 0x0000C120, + .frame_header_incr = 0x0000C124, + .frame_header_cfg = 0x0000C128, + .line_done_cfg = 0x0000C12C, + .irq_subsample_period = 0x0000C130, + .irq_subsample_pattern = 0x0000C134, + .framedrop_period = 0x0000C138, + .framedrop_pattern = 0x0000C13C, + .system_cache_cfg = 0x0000C160, + .burst_limit = 0x0000C164, + .addr_status_0 = 0x0000C168, + .addr_status_1 = 0x0000C16C, + .addr_status_2 = 0x0000C170, + .addr_status_3 = 0x0000C174, + .debug_status_cfg = 0x0000C178, + .debug_status_0 = 0x0000C17C, + .debug_status_1 = 0x0000C180, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_9, + .ubwc_regs = NULL, + }, + /* BUS Client 22 LCR */ + { + .cfg = 0x0000C200, + .image_addr = 0x0000C204, + .frame_incr = 0x0000C208, + .image_cfg_0 = 0x0000C20C, + .image_cfg_1 = 0x0000C210, + .image_cfg_2 = 0x0000C214, + .packer_cfg = 0x0000C218, + .frame_header_addr = 0x0000C220, + .frame_header_incr = 0x0000C224, + .frame_header_cfg = 0x0000C228, + .line_done_cfg = 0, + .irq_subsample_period = 0x0000C230, + .irq_subsample_pattern = 0x0000C234, + .framedrop_period = 0x0000C238, + .framedrop_pattern = 0x0000C23C, + .system_cache_cfg = 0x0000C260, + .burst_limit = 0x0000C264, + .addr_status_0 = 0x0000C268, + .addr_status_1 = 0x0000C26C, + .addr_status_2 = 0x0000C270, + .addr_status_3 = 0x0000C274, + .debug_status_cfg = 0x0000C278, + .debug_status_0 = 0x0000C27C, + .debug_status_1 = 0x0000C280, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_10, + .ubwc_regs = NULL, + }, + /* BUS Client 23 RDI0 */ + { + .cfg = 0x0000C300, + .image_addr = 0x0000C304, + .frame_incr = 0x0000C308, + .image_cfg_0 = 0x0000C30C, + .image_cfg_1 = 0x0000C310, + .image_cfg_2 = 0x0000C314, + .packer_cfg = 0x0000C318, + .frame_header_addr = 0x0000C320, + .frame_header_incr = 0x0000C324, + .frame_header_cfg = 0x0000C328, + .line_done_cfg = 0x0000C32C, + .irq_subsample_period = 0x0000C330, + .irq_subsample_pattern = 0x0000C334, + .framedrop_period = 0x0000C338, + .framedrop_pattern = 0x0000C33C, + .system_cache_cfg = 0x0000C360, + .burst_limit = 0x0000C364, + .addr_status_0 = 0x0000C368, + .addr_status_1 = 0x0000C36C, + .addr_status_2 = 0x0000C370, + .addr_status_3 = 0x0000C374, + .debug_status_cfg = 0x0000C378, + .debug_status_0 = 0x0000C37C, + .debug_status_1 = 0x0000C380, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_11, + .ubwc_regs = NULL, + }, + /* BUS Client 24 RDI1 */ + { + .cfg = 0x0000C400, + .image_addr = 0x0000C404, + .frame_incr = 0x0000C408, + .image_cfg_0 = 0x0000C40C, + .image_cfg_1 = 0x0000C410, + .image_cfg_2 = 0x0000C414, + .packer_cfg = 0x0000C418, + .frame_header_addr = 0x0000C420, + .frame_header_incr = 0x0000C424, + .frame_header_cfg = 0x0000C428, + .line_done_cfg = 0x0000C42C, + .irq_subsample_period = 0x0000C430, + .irq_subsample_pattern = 0x0000C434, + .framedrop_period = 0x0000C438, + .framedrop_pattern = 0x0000C43C, + .system_cache_cfg = 0x0000C460, + .burst_limit = 0x0000C464, + .addr_status_0 = 0x0000C468, + .addr_status_1 = 0x0000C46C, + .addr_status_2 = 0x0000C470, + .addr_status_3 = 0x0000C474, + .debug_status_cfg = 0x0000C478, + .debug_status_0 = 0x0000C47C, + .debug_status_1 = 0x0000C480, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_12, + .ubwc_regs = NULL, + }, + /* BUS Client 25 RDI2 */ + { + .cfg = 0x0000C500, + .image_addr = 0x0000C504, + .frame_incr = 0x0000C508, + .image_cfg_0 = 0x0000C50C, + .image_cfg_1 = 0x0000C510, + .image_cfg_2 = 0x0000C514, + .packer_cfg = 0x0000C518, + .frame_header_addr = 0x0000C520, + .frame_header_incr = 0x0000C524, + .frame_header_cfg = 0x0000C528, + .line_done_cfg = 0x0000C52C, + .irq_subsample_period = 0x0000C530, + .irq_subsample_pattern = 0x0000C534, + .framedrop_period = 0x0000C538, + .framedrop_pattern = 0x0000C53C, + .system_cache_cfg = 0x0000C560, + .burst_limit = 0x0000C564, + .addr_status_0 = 0x0000C568, + .addr_status_1 = 0x0000C56C, + .addr_status_2 = 0x0000C570, + .addr_status_3 = 0x0000C574, + .debug_status_cfg = 0x0000C578, + .debug_status_0 = 0x0000C57C, + .debug_status_1 = 0x0000C580, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_13, + .ubwc_regs = NULL, + }, + }, + .num_out = 23, + .vfe_out_hw_info = { + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_4, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_5, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL, + .max_width = 4096, + .max_height = 4096, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FD, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_PDAF, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = + CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = + CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + .max_width = 4096, + .max_height = 4096, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LCR, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + }, + }, + .comp_done_shift = 6, + .top_irq_shift = 7, +}; + +static struct cam_irq_register_set vfe480_bus_rd_irq_reg[1] = { + { + .mask_reg_offset = 0x0000A810, + .clear_reg_offset = 0x0000A814, + .status_reg_offset = 0x0000A81C, + }, +}; + +static struct cam_vfe_bus_rd_ver1_hw_info vfe480_bus_rd_hw_info = { + .common_reg = { + .hw_version = 0x0000A800, + .hw_capability = 0x0000A804, + .sw_reset = 0x0000A808, + .cgc_ovd = 0x0000A80C, + .pwr_iso_cfg = 0x0000A834, + .input_if_cmd = 0x0000A820, + .test_bus_ctrl = 0x0000A848, + .irq_reg_info = { + .num_registers = 1, + .irq_reg_set = vfe480_bus_rd_irq_reg, + .global_clear_offset = 0x0000A818, + .global_clear_bitmask = 0x00000001, + }, + }, + .num_client = 1, + .bus_client_reg = { + /* BUS Client 0 */ + { + .cfg = 0x0000A850, + .image_addr = 0x0000A858, + .buf_size = 0x0000A85C, + .stride = 0x0000A860, + .unpacker_cfg = 0x0000A864, + .latency_buf_allocation = 0x0000A878, + .burst_limit = 0x0000A880, + }, + }, + .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, + }, + }, +}; + +struct cam_vfe_hw_info cam_vfe480_hw_info = { + .irq_reg_info = &vfe480_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_3_0, + .bus_hw_info = &vfe480_bus_hw_info, + + .bus_rd_version = CAM_VFE_BUS_RD_VER_1_0, + .bus_rd_hw_info = &vfe480_bus_rd_hw_info, + + .top_version = CAM_VFE_TOP_VER_3_0, + .top_hw_info = &vfe480_top_hw_info, +}; + +#endif /* _CAM_VFE480_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h new file mode 100644 index 000000000000..0c94b63be2e0 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_LITE17X_H_ +#define _CAM_VFE_LITE17X_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 vfe17x_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 vfe17x_top_irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe17x_top_irq_reg_set, + .global_clear_offset = 0x00000058, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_top_ver2_reg_offset_common vfe17x_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 vfe17x_rdi_reg = { + .reg_update_cmd = 0x000004AC, +}; + +static struct cam_vfe_rdi_reg_data vfe17x_rdi_0_data = { + .reg_update_cmd_data = 0x2, + .sof_irq_mask = 0x8000000, + .reg_update_irq_mask = 0x20, +}; + +static struct cam_vfe_rdi_reg_data vfe17x_rdi_1_data = { + .reg_update_cmd_data = 0x4, + .sof_irq_mask = 0x10000000, + .reg_update_irq_mask = 0x40, +}; + +static struct cam_vfe_rdi_reg_data vfe17x_rdi_2_data = { + .reg_update_cmd_data = 0x8, + .sof_irq_mask = 0x20000000, + .reg_update_irq_mask = 0x80, +}; + +static struct cam_vfe_rdi_reg_data vfe17x_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 vfe17x_top_hw_info = { + .common_reg = &vfe17x_top_common_reg, + .camif_hw_info = { + .common_reg = NULL, + .camif_reg = NULL, + .reg_data = NULL, + }, + .rdi_hw_info = { + .common_reg = &vfe17x_top_common_reg, + .rdi_reg = &vfe17x_rdi_reg, + .reg_data = { + &vfe17x_rdi_0_data, + &vfe17x_rdi_1_data, + &vfe17x_rdi_2_data, + &vfe17x_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 vfe17x_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 vfe17x_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 = vfe17x_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_lite17x_hw_info = { + .irq_reg_info = &vfe17x_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_2_0, + .bus_hw_info = &vfe17x_bus_hw_info, + + .top_version = CAM_VFE_TOP_VER_2_0, + .top_hw_info = &vfe17x_top_hw_info, + +}; + +#endif /* _CAM_VFE_LITE17X_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h new file mode 100644 index 000000000000..c9d66ed94e97 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -0,0 +1,400 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_LITE48x_H_ +#define _CAM_VFE_LITE48x_H_ + +#include "cam_vfe_bus_ver3.h" +#include "cam_irq_controller.h" +#include "cam_vfe_top_ver3.h" +#include "cam_vfe_core.h" + +static struct cam_irq_register_set vfe48x_top_irq_reg_set[3] = { + { + .mask_reg_offset = 0x00000028, + .clear_reg_offset = 0x00000034, + .status_reg_offset = 0x00000040, + }, + { + .mask_reg_offset = 0x0000002C, + .clear_reg_offset = 0x00000038, + .status_reg_offset = 0x00000044, + }, + { + .mask_reg_offset = 0x00000030, + .clear_reg_offset = 0x0000003C, + .status_reg_offset = 0x00000048, + }, +}; + +static struct cam_irq_controller_reg_info vfe48x_top_irq_reg_info = { + .num_registers = 3, + .irq_reg_set = vfe48x_top_irq_reg_set, + .global_clear_offset = 0x00000024, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_top_ver3_reg_offset_common vfe48x_top_common_reg = { + .hw_version = 0x00000000, + .titan_version = 0x00000004, + .hw_capability = 0x00000008, + .global_reset_cmd = 0x0000000C, + .core_cgc_ovd_0 = 0x00000010, + .ahb_cgc_ovd = 0x00000014, + .noc_cgc_ovd = 0x00000018, + .reg_update_cmd = 0x00000020, + .diag_config = 0x00000050, + .diag_sensor_status_0 = 0x00000054, + .bus_overflow_status = 0x00001A68, +}; + +static struct cam_vfe_camif_lite_ver3_reg vfe48x_camif_rdi[4] = { + { + .lite_hw_version = 0x1200, + .lite_hw_status = 0x1204, + .lite_module_config = 0x1260, + .lite_skip_period = 0x1268, + .lite_irq_subsample_pattern = 0x126C, + .lite_epoch_irq = 0x1270, + .lite_debug_1 = 0x13F0, + .lite_debug_0 = 0x13F4, + .lite_test_bus_ctrl = 0x13F8, + .camif_lite_spare = 0x13FC, + .reg_update_cmd = 0x0020, + }, + { + .lite_hw_version = 0x1400, + .lite_hw_status = 0x1404, + .lite_module_config = 0x1460, + .lite_skip_period = 0x1468, + .lite_irq_subsample_pattern = 0x146C, + .lite_epoch_irq = 0x1470, + .lite_debug_1 = 0x15F0, + .lite_debug_0 = 0x15F4, + .lite_test_bus_ctrl = 0x15F8, + .camif_lite_spare = 0x15FC, + .reg_update_cmd = 0x0020, + }, + { + .lite_hw_version = 0x1600, + .lite_hw_status = 0x1604, + .lite_module_config = 0x1660, + .lite_skip_period = 0x1668, + .lite_irq_subsample_pattern = 0x166C, + .lite_epoch_irq = 0x1670, + .lite_debug_1 = 0x17F0, + .lite_debug_0 = 0x17F4, + .lite_test_bus_ctrl = 0x17F8, + .camif_lite_spare = 0x17FC, + .reg_update_cmd = 0x0020, + }, + { + .lite_hw_version = 0x1800, + .lite_hw_status = 0x1804, + .lite_module_config = 0x1860, + .lite_skip_period = 0x1868, + .lite_irq_subsample_pattern = 0x186C, + .lite_epoch_irq = 0x1870, + .lite_debug_1 = 0x19F0, + .lite_debug_0 = 0x19F4, + .lite_test_bus_ctrl = 0x19F8, + .camif_lite_spare = 0x19FC, + .reg_update_cmd = 0x0020, + }, +}; + +static struct cam_vfe_camif_lite_ver3_reg_data vfe48x_camif_rdi_reg_data[4] = { + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x1, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x1, + .epoch0_irq_mask = 0x4, + .epoch1_irq_mask = 0x8, + .eof_irq_mask = 0x02, + .error_irq_mask0 = 0x1, + .error_irq_mask2 = 0x100, + .subscribe_irq_mask1 = 0x3, + .enable_diagnostic_hw = 0x1, + }, + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x2, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x10, + .epoch0_irq_mask = 0x40, + .epoch1_irq_mask = 0x80, + .eof_irq_mask = 0x20, + .error_irq_mask0 = 0x2, + .error_irq_mask2 = 0x200, + .subscribe_irq_mask1 = 0x30, + .enable_diagnostic_hw = 0x1, + }, + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x4, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x100, + .epoch0_irq_mask = 0x400, + .epoch1_irq_mask = 0x800, + .eof_irq_mask = 0x200, + .error_irq_mask0 = 0x4, + .error_irq_mask2 = 0x400, + .subscribe_irq_mask1 = 0x300, + .enable_diagnostic_hw = 0x1, + }, + { + .extern_reg_update_shift = 0, + .reg_update_cmd_data = 0x8, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x1000, + .epoch0_irq_mask = 0x4000, + .epoch1_irq_mask = 0x8000, + .eof_irq_mask = 0x2000, + .error_irq_mask0 = 0x8, + .error_irq_mask2 = 0x800, + .subscribe_irq_mask1 = 0x3000, + .enable_diagnostic_hw = 0x1, + }, +}; + +static struct cam_vfe_camif_lite_ver3_hw_info + vfe48x_rdi_hw_info[CAM_VFE_RDI_VER2_MAX] = { + { + .common_reg = &vfe48x_top_common_reg, + .camif_lite_reg = &vfe48x_camif_rdi[0], + .reg_data = &vfe48x_camif_rdi_reg_data[0], + }, + { + .common_reg = &vfe48x_top_common_reg, + .camif_lite_reg = &vfe48x_camif_rdi[1], + .reg_data = &vfe48x_camif_rdi_reg_data[1], + }, + { + .common_reg = &vfe48x_top_common_reg, + .camif_lite_reg = &vfe48x_camif_rdi[2], + .reg_data = &vfe48x_camif_rdi_reg_data[2], + }, + { + .common_reg = &vfe48x_top_common_reg, + .camif_lite_reg = &vfe48x_camif_rdi[3], + .reg_data = &vfe48x_camif_rdi_reg_data[3], + }, +}; + +static struct cam_vfe_top_ver3_hw_info vfe48x_top_hw_info = { + .common_reg = &vfe48x_top_common_reg, + .rdi_hw_info[0] = &vfe48x_rdi_hw_info[0], + .rdi_hw_info[1] = &vfe48x_rdi_hw_info[1], + .rdi_hw_info[2] = &vfe48x_rdi_hw_info[2], + .rdi_hw_info[3] = &vfe48x_rdi_hw_info[3], + .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 vfe48x_bus_irq_reg[2] = { + { + .mask_reg_offset = 0x00001A18, + .clear_reg_offset = 0x00001A20, + .status_reg_offset = 0x00001A28, + }, + { + .mask_reg_offset = 0x00001A1C, + .clear_reg_offset = 0x00001A24, + .status_reg_offset = 0x00001A2C, + }, +}; + +static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { + .common_reg = { + .hw_version = 0x00001A00, + .cgc_ovd = 0x00001A08, + .if_frameheader_cfg = { + 0x00001A34, + 0x00001A38, + 0x00001A3C, + 0x00001A40, + }, + .pwr_iso_cfg = 0x00001A5C, + .overflow_status_clear = 0x00001A60, + .ccif_violation_status = 0x00001A64, + .overflow_status = 0x00001A68, + .image_size_violation_status = 0x00001A70, + .debug_status_top_cfg = 0x00001AD4, + .debug_status_top = 0x00001AD8, + .test_bus_ctrl = 0x00001ADC, + .irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe48x_bus_irq_reg, + .global_clear_offset = 0x00001A30, + .global_clear_bitmask = 0x00000001, + }, + }, + .num_client = 4, + .bus_client_reg = { + /* RDI 0 */ + { + .cfg = 0x00001C00, + .image_addr = 0x00001C04, + .frame_incr = 0x00001C08, + .image_cfg_0 = 0x00001C0C, + .image_cfg_1 = 0x00001C10, + .image_cfg_2 = 0x00001C14, + .packer_cfg = 0x00001C18, + .frame_header_addr = 0x00001C20, + .frame_header_incr = 0x00001C24, + .frame_header_cfg = 0x00001C28, + .line_done_cfg = 0x00001C2C, + .irq_subsample_period = 0x00001C30, + .irq_subsample_pattern = 0x00001C34, + .framedrop_period = 0x00001C38, + .framedrop_pattern = 0x00001C3C, + .system_cache_cfg = 0x00001C60, + .burst_limit = 0x00001C64, + .addr_status_0 = 0x00001C68, + .addr_status_1 = 0x00001C6C, + .addr_status_2 = 0x00001C70, + .addr_status_3 = 0x00001C74, + .debug_status_cfg = 0x00001C78, + .debug_status_0 = 0x00001C7C, + .debug_status_1 = 0x00001C80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* RDI 1 */ + { + .cfg = 0x00001D00, + .image_addr = 0x00001D04, + .frame_incr = 0x00001D08, + .image_cfg_0 = 0x00001D0C, + .image_cfg_1 = 0x00001D10, + .image_cfg_2 = 0x00001D14, + .packer_cfg = 0x00001D18, + .frame_header_addr = 0x00001D20, + .frame_header_incr = 0x00001D24, + .frame_header_cfg = 0x00001D28, + .line_done_cfg = 0x00001D2C, + .irq_subsample_period = 0x00001D30, + .irq_subsample_pattern = 0x00001D34, + .framedrop_period = 0x00001D38, + .framedrop_pattern = 0x00001D3C, + .system_cache_cfg = 0x00001D60, + .burst_limit = 0x00001D64, + .addr_status_0 = 0x00001D68, + .addr_status_1 = 0x00001D6C, + .addr_status_2 = 0x00001D70, + .addr_status_3 = 0x00001D74, + .debug_status_cfg = 0x00001D78, + .debug_status_0 = 0x00001D7C, + .debug_status_1 = 0x00001D80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = NULL, + }, + /* RDI 2 */ + { + .cfg = 0x00001E00, + .image_addr = 0x00001E04, + .frame_incr = 0x00001E08, + .image_cfg_0 = 0x00001E0C, + .image_cfg_1 = 0x00001E10, + .image_cfg_2 = 0x00001E14, + .packer_cfg = 0x00001E18, + .frame_header_addr = 0x00001E20, + .frame_header_incr = 0x00001E24, + .frame_header_cfg = 0x00001E28, + .line_done_cfg = 0x00001E2C, + .irq_subsample_period = 0x00001E30, + .irq_subsample_pattern = 0x00001E34, + .framedrop_period = 0x00001E38, + .framedrop_pattern = 0x00001E3C, + .system_cache_cfg = 0x00001E60, + .burst_limit = 0x00001E64, + .addr_status_0 = 0x00001E68, + .addr_status_1 = 0x00001E6C, + .addr_status_2 = 0x00001E70, + .addr_status_3 = 0x00001E74, + .debug_status_cfg = 0x00001E78, + .debug_status_0 = 0x00001E7C, + .debug_status_1 = 0x00001E80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .ubwc_regs = NULL, + }, + /* RDI 3 */ + { + .cfg = 0x00001F00, + .image_addr = 0x00001F04, + .frame_incr = 0x00001F08, + .image_cfg_0 = 0x00001F0C, + .image_cfg_1 = 0x00001F10, + .image_cfg_2 = 0x00001F14, + .packer_cfg = 0x00001F18, + .frame_header_addr = 0x00001F20, + .frame_header_incr = 0x00001F24, + .frame_header_cfg = 0x00001F28, + .line_done_cfg = 0x00001F2C, + .irq_subsample_period = 0x00001F30, + .irq_subsample_pattern = 0x00001F34, + .framedrop_period = 0x00001F38, + .framedrop_pattern = 0x00001F3C, + .system_cache_cfg = 0x00001F60, + .burst_limit = 0x00001F64, + .addr_status_0 = 0x00001F68, + .addr_status_1 = 0x00001F6C, + .addr_status_2 = 0x00001F70, + .addr_status_3 = 0x00001F74, + .debug_status_cfg = 0x00001F78, + .debug_status_0 = 0x00001F7C, + .debug_status_1 = 0x00001F80, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, + .ubwc_regs = NULL, + }, + }, + .num_out = 4, + .vfe_out_hw_info = { + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + }, + }, + .comp_done_shift = 4, + .top_irq_shift = 4, +}; + +static struct cam_vfe_hw_info cam_vfe_lite48x_hw_info = { + .irq_reg_info = &vfe48x_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_3_0, + .bus_hw_info = &vfe48x_bus_hw_info, + + .top_version = CAM_VFE_TOP_VER_3_0, + .top_hw_info = &vfe48x_top_hw_info, + +}; + +#endif /* _CAM_VFE_LITE48x_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile new file mode 100644 index 000000000000..bdf6d3ee981b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/isp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_bus.o cam_vfe_bus_ver2.o cam_vfe_bus_rd_ver1.o cam_vfe_bus_ver3.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c new file mode 100644 index 000000000000..2b902d753ad2 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#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_vfe_bus_ver3.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, + void *vfe_irq_controller, + struct cam_vfe_bus **vfe_bus) +{ + int rc = -ENODEV; + + switch (bus_type) { + case BUS_TYPE_WR: + 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); + break; + case CAM_VFE_BUS_VER_3_0: + rc = cam_vfe_bus_ver3_init(soc_info, hw_intf, + bus_hw_info, vfe_irq_controller, vfe_bus); + break; + default: + CAM_ERR(CAM_ISP, "Unsupported Bus WR Version 0x%x", + bus_version); + break; + } + break; + case BUS_TYPE_RD: + switch (bus_version) { + case CAM_VFE_BUS_RD_VER_1_0: + /* 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 RD Version 0x%x", + bus_version); + break; + } + break; + default: + CAM_ERR(CAM_ISP, "Unsupported Bus type %d", bus_type); + break; + } + + return rc; +} + +int cam_vfe_bus_deinit(uint32_t bus_version, + struct cam_vfe_bus **vfe_bus) +{ + int rc = -ENODEV; + + switch (bus_version) { + case CAM_VFE_BUS_VER_2_0: + rc = cam_vfe_bus_ver2_deinit(vfe_bus); + break; + case CAM_VFE_BUS_VER_3_0: + rc = cam_vfe_bus_ver3_deinit(vfe_bus); + break; + default: + CAM_ERR(CAM_ISP, "Unsupported Bus Version %x", bus_version); + break; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c new file mode 100644 index 000000000000..ca2d443747f7 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c @@ -0,0 +1,1221 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#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; + + 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]; + + int irq_handle; + int 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_generic_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->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->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->buf_size; + 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, + acq_args->priv, + 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->buf_size, 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[3] = {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 < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ"); + bus_priv->irq_handle = 0; + 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); + 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); + 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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h new file mode 100644 index 000000000000..19cc86496371 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#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 cfg; + uint32_t image_addr; + uint32_t buf_size; + uint32_t stride; + uint32_t unpacker_cfg; + uint32_t latency_buf_allocation; + uint32_t burst_limit; +}; + +/* + * 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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver1.h new file mode 100644 index 000000000000..2783ddccf2d8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver1.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_BUS_VER1_H_ +#define _CAM_VFE_BUS_VER1_H_ + +enum cam_vfe_bus_ver1_pingpong_id { + CAM_VFE_BUS_VER1_PING, + CAM_VFE_BUS_VER1_PONG, + CAM_VFE_BUS_VER1_PINGPONG_MAX, +}; + +enum cam_vfe_bus_ver1_wm_type { + CAM_VFE_BUS_WM_TYPE_IMAGE, + CAM_VFE_BUS_WM_TYPE_STATS, + CAM_VFE_BUS_WM_TYPE_MAX, +}; + +enum cam_vfe_bus_ver1_comp_grp_type { + CAM_VFE_BUS_VER1_COMP_GRP_IMG0, + CAM_VFE_BUS_VER1_COMP_GRP_IMG1, + CAM_VFE_BUS_VER1_COMP_GRP_IMG2, + CAM_VFE_BUS_VER1_COMP_GRP_IMG3, + CAM_VFE_BUS_VER1_COMP_GRP_STATS0, + CAM_VFE_BUS_VER1_COMP_GRP_STATS1, + CAM_VFE_BUS_VER1_COMP_GRP_MAX, +}; + +struct cam_vfe_bus_ver1_common_reg { + uint32_t cmd_offset; + uint32_t cfg_offset; + uint32_t io_fmt_offset; + uint32_t argb_cfg_offset; + uint32_t xbar_cfg0_offset; + uint32_t xbar_cfg1_offset; + uint32_t xbar_cfg2_offset; + uint32_t xbar_cfg3_offset; + uint32_t ping_pong_status_reg; +}; + +struct cam_vfe_bus_ver1_wm_reg { + uint32_t wm_cfg_offset; + uint32_t ping_addr_offset; + uint32_t ping_max_addr_offset; + uint32_t pong_addr_offset; + uint32_t pong_max_addr_offset; + uint32_t addr_cfg_offset; + uint32_t ub_cfg_offset; + uint32_t image_size_offset; + uint32_t buffer_cfg_offset; + uint32_t framedrop_pattern_offset; + uint32_t irq_subsample_pattern_offset; + uint32_t ping_pong_status_bit; /* 0 - 31 */ + uint32_t composite_bit; /* 0 -31 */ +}; + +struct cam_vfe_bus_ver1_wm_resource_data { + uint32_t index; + uint32_t wm_type; + uint32_t res_type; + + uint32_t offset; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t scanline; + + uint32_t burst_len; + + uint32_t framedrop_period; + uint32_t framedrop_pattern; + + uint32_t buf_valid[CAM_VFE_BUS_VER1_PINGPONG_MAX]; + uint32_t ub_size; + uint32_t ub_offset; + + struct cam_vfe_bus_ver1_wm_reg hw_regs; +}; + +struct cam_vfe_bus_ver1_comp_grp_reg { + enum cam_vfe_bus_ver1_comp_grp_type comp_grp_type; + uint32_t comp_grp_offset; +}; + +struct cam_vfe_bus_ver1_comp_grp { + struct cam_vfe_bus_ver1_comp_grp_reg reg_info; + struct list_head wm_list; + uint32_t cur_bit_mask; +}; + +/* + * cam_vfe_bus_ver1_init() + * + * @Brief: Initialize Bus layer + * + * @mem_base: Mapped base address of register space + * @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 + */ +int cam_vfe_bus_ver1_init( + void __iomem *mem_base, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + void *vfe_irq_controller, + struct cam_vfe_bus **vfe_bus); + +#endif /* _CAM_VFE_BUS_VER1_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c new file mode 100644 index 000000000000..2a452c0d874d --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -0,0 +1,3781 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#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_ver2.h" +#include "cam_vfe_core.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + +static const char drv_name[] = "vfe_bus"; + +#define CAM_VFE_BUS_IRQ_REG0 0 +#define CAM_VFE_BUS_IRQ_REG1 1 +#define CAM_VFE_BUS_IRQ_REG2 2 +#define CAM_VFE_BUS_IRQ_MAX 3 + +#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256 + +#define CAM_VFE_BUS_SET_DEBUG_REG 0x82 + +#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFF01 +#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFF01 +#define CAM_VFE_BUS_INTRA_CLIENT_MASK 0x3 +#define CAM_VFE_BUS_ADDR_SYNC_INTRA_CLIENT_SHIFT 8 +#define CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL \ + ((1 << CAM_VFE_BUS_VER2_MAX_CLIENTS) - 1) + +#define MAX_BUF_UPDATE_REG_NUM \ + ((sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client) + \ + sizeof(struct cam_vfe_bus_ver2_reg_offset_ubwc_client))/4) +#define MAX_REG_VAL_PAIR_SIZE \ + (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) + +static uint32_t bus_error_irq_mask[3] = { + 0x7800, + 0x0000, + 0x0040, +}; + +enum cam_vfe_bus_packer_format { + PACKER_FMT_PLAIN_128 = 0x0, + PACKER_FMT_PLAIN_8 = 0x1, + PACKER_FMT_PLAIN_16_10BPP = 0x2, + PACKER_FMT_PLAIN_16_12BPP = 0x3, + PACKER_FMT_PLAIN_16_14BPP = 0x4, + PACKER_FMT_PLAIN_16_16BPP = 0x5, + PACKER_FMT_ARGB_10 = 0x6, + PACKER_FMT_ARGB_12 = 0x7, + PACKER_FMT_ARGB_14 = 0x8, + PACKER_FMT_PLAIN_32_20BPP = 0x9, + PACKER_FMT_PLAIN_64 = 0xA, + PACKER_FMT_TP_10 = 0xB, + PACKER_FMT_PLAIN_32_32BPP = 0xC, + PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD, + PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE, + PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF, + PACKER_FMT_MAX = 0xF, +}; + +enum cam_vfe_bus_comp_grp_id { + CAM_VFE_BUS_COMP_GROUP_NONE = -EINVAL, + CAM_VFE_BUS_COMP_GROUP_ID_0 = 0x0, + CAM_VFE_BUS_COMP_GROUP_ID_1 = 0x1, + CAM_VFE_BUS_COMP_GROUP_ID_2 = 0x2, + CAM_VFE_BUS_COMP_GROUP_ID_3 = 0x3, + CAM_VFE_BUS_COMP_GROUP_ID_4 = 0x4, + CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5, +}; + +struct cam_vfe_bus_ver2_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_ver2_reg_offset_common *common_reg; + uint32_t io_buf_update[ + MAX_REG_VAL_PAIR_SIZE]; + + struct cam_vfe_bus_irq_evt_payload evt_payload[ + CAM_VFE_BUS_VER2_PAYLOAD_MAX]; + 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 addr_no_sync; + cam_hw_mgr_event_cb_func event_cb; + bool hw_init; +}; + +struct cam_vfe_bus_ver2_wm_resource_data { + uint32_t index; + struct cam_vfe_bus_ver2_common_data *common_data; + struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs; + + bool init_cfg_done; + bool hfr_cfg_done; + + uint32_t offset; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; + enum cam_vfe_bus_packer_format pack_fmt; + + uint32_t burst_len; + + uint32_t en_ubwc; + bool ubwc_updated; + uint32_t packer_cfg; + uint32_t tile_cfg; + uint32_t h_init; + uint32_t v_init; + uint32_t ubwc_meta_stride; + uint32_t ubwc_mode_cfg_0; + uint32_t ubwc_mode_cfg_1; + uint32_t ubwc_meta_offset; + + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + + uint32_t en_cfg; + uint32_t is_dual; + uint32_t ubwc_lossy_threshold_0; + uint32_t ubwc_lossy_threshold_1; + uint32_t ubwc_bandwidth_limit; +}; + +struct cam_vfe_bus_ver2_comp_grp_data { + enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type; + struct cam_vfe_bus_ver2_common_data *common_data; + struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs; + + uint32_t comp_grp_local_idx; + uint32_t unique_id; + + uint32_t is_master; + uint32_t dual_slave_core; + uint32_t intra_client_mask; + uint32_t composite_mask; + uint32_t addr_sync_mode; + + uint32_t acquire_dev_cnt; +}; + +struct cam_vfe_bus_ver2_vfe_out_data { + uint32_t out_type; + struct cam_vfe_bus_ver2_common_data *common_data; + + uint32_t num_wm; + struct cam_isp_resource_node *wm_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_out_list; + + uint32_t format; + uint32_t max_width; + uint32_t max_height; + struct cam_cdm_utils_ops *cdm_util_ops; + uint32_t secure_mode; + void *priv; +}; + +struct cam_vfe_bus_ver2_priv { + struct cam_vfe_bus_ver2_common_data common_data; + uint32_t num_client; + uint32_t num_out; + + struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS]; + struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX]; + struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; + + struct list_head free_comp_grp; + struct list_head free_dual_comp_grp; + struct list_head used_comp_grp; + + int irq_handle; + int error_irq_handle; + void *tasklet_info; +}; + +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 int cam_vfe_bus_get_evt_payload( + struct cam_vfe_bus_ver2_common_data *common_data, + struct cam_vfe_bus_irq_evt_payload **evt_payload) +{ + int rc; + + spin_lock(&common_data->spin_lock); + + if (!common_data->hw_init) { + *evt_payload = NULL; + CAM_ERR_RATE_LIMIT(CAM_ISP, "VFE:%d Bus uninitialized", + common_data->core_index); + rc = -EPERM; + goto done; + } + + if (list_empty(&common_data->free_payload_list)) { + *evt_payload = NULL; + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&common_data->free_payload_list, + struct cam_vfe_bus_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + rc = 0; +done: + spin_unlock(&common_data->spin_lock); + return rc; +} + +static enum cam_vfe_bus_comp_grp_id + cam_vfe_bus_comp_grp_id_convert(uint32_t comp_grp) +{ + switch (comp_grp) { + case CAM_ISP_RES_COMP_GROUP_ID_0: + return CAM_VFE_BUS_COMP_GROUP_ID_0; + case CAM_ISP_RES_COMP_GROUP_ID_1: + return CAM_VFE_BUS_COMP_GROUP_ID_1; + case CAM_ISP_RES_COMP_GROUP_ID_2: + return CAM_VFE_BUS_COMP_GROUP_ID_2; + case CAM_ISP_RES_COMP_GROUP_ID_3: + return CAM_VFE_BUS_COMP_GROUP_ID_3; + case CAM_ISP_RES_COMP_GROUP_ID_4: + return CAM_VFE_BUS_COMP_GROUP_ID_4; + case CAM_ISP_RES_COMP_GROUP_ID_5: + return CAM_VFE_BUS_COMP_GROUP_ID_5; + case CAM_ISP_RES_COMP_GROUP_NONE: + default: + return CAM_VFE_BUS_COMP_GROUP_NONE; + } +} + +static int cam_vfe_bus_put_evt_payload( + struct cam_vfe_bus_ver2_common_data *common_data, + struct cam_vfe_bus_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!common_data) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&common_data->spin_lock, flags); + if (common_data->hw_init) + list_add_tail(&(*evt_payload)->list, + &common_data->free_payload_list); + spin_unlock_irqrestore(&common_data->spin_lock, flags); + + *evt_payload = NULL; + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_bus_ver2_get_intra_client_mask( + enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core, + enum cam_vfe_bus_ver2_vfe_core_id current_core, + uint32_t *intra_client_mask) +{ + int rc = 0; + uint32_t camera_hw_version = 0; + uint32_t version_based_intra_client_mask = 0x1; + + *intra_client_mask = 0; + + + if (dual_slave_core == current_core) { + CAM_ERR(CAM_ISP, + "Invalid params. Same core as Master and Slave"); + return -EINVAL; + } + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + + CAM_DBG(CAM_ISP, "CPAS VERSION %d", camera_hw_version); + + switch (camera_hw_version) { + case CAM_CPAS_TITAN_170_V100: + version_based_intra_client_mask = 0x3; + break; + default: + version_based_intra_client_mask = 0x1; + break; + } + + + switch (current_core) { + case CAM_VFE_BUS_VER2_VFE_CORE_0: + switch (dual_slave_core) { + case CAM_VFE_BUS_VER2_VFE_CORE_1: + *intra_client_mask = version_based_intra_client_mask; + break; + default: + CAM_ERR(CAM_ISP, "Invalid value for slave core %u", + dual_slave_core); + rc = -EINVAL; + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_CORE_1: + switch (dual_slave_core) { + case CAM_VFE_BUS_VER2_VFE_CORE_0: + *intra_client_mask = version_based_intra_client_mask; + break; + default: + CAM_ERR(CAM_ISP, "Invalid value for slave core %u", + dual_slave_core); + rc = -EINVAL; + break; + } + break; + default: + CAM_ERR(CAM_ISP, + "Invalid value for master core %u", current_core); + rc = -EINVAL; + break; + } + + return rc; +} + +static bool cam_vfe_bus_can_be_secure(uint32_t out_type) +{ + switch (out_type) { + case CAM_VFE_BUS_VER2_VFE_OUT_FULL: + case CAM_VFE_BUS_VER2_VFE_OUT_DS4: + case CAM_VFE_BUS_VER2_VFE_OUT_DS16: + case CAM_VFE_BUS_VER2_VFE_OUT_FD: + case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP: + case CAM_VFE_BUS_VER2_VFE_OUT_RDI0: + case CAM_VFE_BUS_VER2_VFE_OUT_RDI1: + case CAM_VFE_BUS_VER2_VFE_OUT_RDI2: + case CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP: + case CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP: + case CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP: + return true; + + case CAM_VFE_BUS_VER2_VFE_OUT_PDAF: + case CAM_VFE_BUS_VER2_VFE_OUT_2PD: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST: + default: + return false; + } +} + +static enum cam_vfe_bus_ver2_vfe_out_type + cam_vfe_bus_get_out_res_id(uint32_t res_type) +{ + switch (res_type) { + case CAM_ISP_IFE_OUT_RES_FULL: + return CAM_VFE_BUS_VER2_VFE_OUT_FULL; + case CAM_ISP_IFE_OUT_RES_DS4: + return CAM_VFE_BUS_VER2_VFE_OUT_DS4; + case CAM_ISP_IFE_OUT_RES_DS16: + return CAM_VFE_BUS_VER2_VFE_OUT_DS16; + case CAM_ISP_IFE_OUT_RES_FD: + return CAM_VFE_BUS_VER2_VFE_OUT_FD; + case CAM_ISP_IFE_OUT_RES_RAW_DUMP: + return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP; + case CAM_ISP_IFE_OUT_RES_PDAF: + return CAM_VFE_BUS_VER2_VFE_OUT_PDAF; + case CAM_ISP_IFE_OUT_RES_2PD: + return CAM_VFE_BUS_VER2_VFE_OUT_2PD; + case CAM_ISP_IFE_OUT_RES_RDI_0: + return CAM_VFE_BUS_VER2_VFE_OUT_RDI0; + case CAM_ISP_IFE_OUT_RES_RDI_1: + return CAM_VFE_BUS_VER2_VFE_OUT_RDI1; + case CAM_ISP_IFE_OUT_RES_RDI_2: + return CAM_VFE_BUS_VER2_VFE_OUT_RDI2; + case CAM_ISP_IFE_OUT_RES_RDI_3: + return CAM_VFE_BUS_VER2_VFE_OUT_RDI3; + case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE; + case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST; + case CAM_ISP_IFE_OUT_RES_STATS_TL_BG: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG; + case CAM_ISP_IFE_OUT_RES_STATS_BF: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF; + case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG; + case CAM_ISP_IFE_OUT_RES_STATS_BHIST: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST; + case CAM_ISP_IFE_OUT_RES_STATS_RS: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS; + case CAM_ISP_IFE_OUT_RES_STATS_CS: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS; + case CAM_ISP_IFE_OUT_RES_STATS_IHIST: + return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST; + case CAM_ISP_IFE_OUT_RES_FULL_DISP: + return CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP; + case CAM_ISP_IFE_OUT_RES_DS4_DISP: + return CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP; + case CAM_ISP_IFE_OUT_RES_DS16_DISP: + return CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP; + default: + return CAM_VFE_BUS_VER2_VFE_OUT_MAX; + } +} + +static int cam_vfe_bus_get_num_wm( + enum cam_vfe_bus_ver2_vfe_out_type res_type, + uint32_t format) +{ + switch (res_type) { + case CAM_VFE_BUS_VER2_VFE_OUT_RDI0: + case CAM_VFE_BUS_VER2_VFE_OUT_RDI1: + case CAM_VFE_BUS_VER2_VFE_OUT_RDI2: + case CAM_VFE_BUS_VER2_VFE_OUT_RDI3: + switch (format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_DPCM_10_6_10: + case CAM_FORMAT_DPCM_10_8_10: + case CAM_FORMAT_DPCM_12_6_12: + case CAM_FORMAT_DPCM_12_8_12: + case CAM_FORMAT_DPCM_14_8_14: + case CAM_FORMAT_DPCM_14_10_14: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN32_20: + case CAM_FORMAT_PLAIN128: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_FULL: + case CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP: + switch (format) { + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_TP10: + case CAM_FORMAT_UBWC_NV12: + case CAM_FORMAT_UBWC_NV12_4R: + case CAM_FORMAT_UBWC_TP10: + case CAM_FORMAT_UBWC_P010: + case CAM_FORMAT_PLAIN16_10: + return 2; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_FD: + switch (format) { + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_TP10: + case CAM_FORMAT_PLAIN16_10: + return 2; + case CAM_FORMAT_Y_ONLY: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_DS4: + case CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP: + case CAM_VFE_BUS_VER2_VFE_OUT_DS16: + case CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP: + switch (format) { + case CAM_FORMAT_PD8: + case CAM_FORMAT_PD10: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP: + switch (format) { + case CAM_FORMAT_ARGB_14: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_PDAF: + switch (format) { + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_2PD: + switch (format) { + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN64: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS: + switch (format) { + case CAM_FORMAT_PLAIN64: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS: + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST: + switch (format) { + case CAM_FORMAT_PLAIN16_16: + return 1; + default: + break; + } + break; + default: + break; + } + + CAM_ERR(CAM_ISP, "Unsupported format %u for resource_type %u", + format, res_type); + + return -EINVAL; +} + +static int cam_vfe_bus_get_wm_idx( + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id, + enum cam_vfe_bus_plane_type plane) +{ + int wm_idx = -1; + + switch (vfe_out_res_id) { + case CAM_VFE_BUS_VER2_VFE_OUT_RDI0: + switch (plane) { + case PLANE_Y: + wm_idx = 0; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_RDI1: + switch (plane) { + case PLANE_Y: + wm_idx = 1; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_RDI2: + switch (plane) { + case PLANE_Y: + wm_idx = 2; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_RDI3: + switch (plane) { + case PLANE_Y: + wm_idx = 3; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_FULL: + switch (plane) { + case PLANE_Y: + wm_idx = 3; + break; + case PLANE_C: + wm_idx = 4; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_DS4: + switch (plane) { + case PLANE_Y: + wm_idx = 5; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_DS16: + switch (plane) { + case PLANE_Y: + wm_idx = 6; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_FD: + switch (plane) { + case PLANE_Y: + wm_idx = 7; + break; + case PLANE_C: + wm_idx = 8; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP: + switch (plane) { + case PLANE_Y: + wm_idx = 9; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_PDAF: + case CAM_VFE_BUS_VER2_VFE_OUT_2PD: + switch (plane) { + case PLANE_Y: + wm_idx = 10; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE: + switch (plane) { + case PLANE_Y: + wm_idx = 11; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 12; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG: + switch (plane) { + case PLANE_Y: + wm_idx = 13; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF: + switch (plane) { + case PLANE_Y: + wm_idx = 14; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG: + switch (plane) { + case PLANE_Y: + wm_idx = 15; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 16; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS: + switch (plane) { + case PLANE_Y: + wm_idx = 17; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS: + switch (plane) { + case PLANE_Y: + wm_idx = 18; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 19; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP: + switch (plane) { + case PLANE_Y: + wm_idx = 20; + break; + case PLANE_C: + wm_idx = 21; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP: + switch (plane) { + case PLANE_Y: + wm_idx = 22; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP: + switch (plane) { + case PLANE_Y: + wm_idx = 23; + break; + default: + break; + } + break; + + default: + break; + } + + return wm_idx; +} + +static void cam_vfe_bus_get_comp_vfe_out_res_id_list( + uint32_t comp_mask, uint32_t *out_list, int *num_out) +{ + int count = 0; + + if (comp_mask & 0x1) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_0; + + if (comp_mask & 0x2) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_1; + + if (comp_mask & 0x4) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_2; + + if ((comp_mask & 0x8) && (((comp_mask >> 4) & 0x1) == 0)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_3; + + if (comp_mask & 0x18) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL; + + if (comp_mask & 0x20) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4; + + if (comp_mask & 0x40) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16; + + if (comp_mask & 0x180) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FD; + + if (comp_mask & 0x200) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RAW_DUMP; + + if (comp_mask & 0x800) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_HDR_BE; + + if (comp_mask & 0x1000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST; + + if (comp_mask & 0x2000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_TL_BG; + + if (comp_mask & 0x4000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BF; + + if (comp_mask & 0x8000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_AWB_BG; + + if (comp_mask & 0x10000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BHIST; + + if (comp_mask & 0x20000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_RS; + + if (comp_mask & 0x40000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_CS; + + if (comp_mask & 0x80000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_IHIST; + + if (comp_mask & 0x300000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL_DISP; + + if (comp_mask & 0x400000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4_DISP; + + if (comp_mask & 0x800000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16_DISP; + + *num_out = count; + +} + +static enum cam_vfe_bus_packer_format + cam_vfe_bus_get_packer_fmt(uint32_t out_fmt, int wm_index) +{ + switch (out_fmt) { + case CAM_FORMAT_NV21: + if ((wm_index == 4) || (wm_index == 6) || (wm_index == 21)) + return PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN; + case CAM_FORMAT_NV12: + case CAM_FORMAT_UBWC_NV12: + case CAM_FORMAT_UBWC_NV12_4R: + case CAM_FORMAT_Y_ONLY: + return PACKER_FMT_PLAIN_8_LSB_MSB_10; + case CAM_FORMAT_PLAIN16_16: + return PACKER_FMT_PLAIN_16_16BPP; + case CAM_FORMAT_PLAIN64: + return PACKER_FMT_PLAIN_64; + case CAM_FORMAT_PLAIN8: + return PACKER_FMT_PLAIN_8; + case CAM_FORMAT_PLAIN16_10: + return PACKER_FMT_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return PACKER_FMT_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return PACKER_FMT_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN32_20: + return PACKER_FMT_PLAIN_32_20BPP; + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PD8: + case CAM_FORMAT_PD10: + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_UBWC_TP10: + case CAM_FORMAT_TP10: + return PACKER_FMT_TP_10; + case CAM_FORMAT_ARGB_14: + return PACKER_FMT_ARGB_14; + default: + return PACKER_FMT_MAX; + } +} + +static int cam_vfe_bus_acquire_wm( + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_isp_out_port_generic_info *out_port_info, + void *tasklet, + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id, + enum cam_vfe_bus_plane_type plane, + struct cam_isp_resource_node **wm_res, + uint32_t *client_done_mask, + uint32_t is_dual) +{ + uint32_t wm_idx = 0; + struct cam_isp_resource_node *wm_res_local = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL; + + *wm_res = NULL; + *client_done_mask = 0; + + /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */ + wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane); + if (wm_idx < 0 || wm_idx >= ver2_bus_priv->num_client) { + CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d", + vfe_out_res_id, plane); + return -EINVAL; + } + + wm_res_local = &ver2_bus_priv->bus_client[wm_idx]; + if (wm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "WM res not available state:%d", + wm_res_local->res_state); + return -EALREADY; + } + wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + wm_res_local->tasklet_info = tasklet; + + rsrc_data = wm_res_local->res_priv; + rsrc_data->format = out_port_info->format; + rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format, + wm_idx); + + rsrc_data->width = out_port_info->width; + rsrc_data->height = out_port_info->height; + rsrc_data->is_dual = is_dual; + /* Set WM offset value to default */ + rsrc_data->offset = 0; + CAM_DBG(CAM_ISP, "WM %d width %d height %d", rsrc_data->index, + rsrc_data->width, rsrc_data->height); + + if (rsrc_data->index < 3) { + /* Write master 0-2 refers to RDI 0/ RDI 1/RDI 2 */ + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_PLAIN128: + rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->pack_fmt = 0x0; + rsrc_data->en_cfg = 0x3; + break; + case CAM_FORMAT_PLAIN8: + rsrc_data->en_cfg = 0x1; + rsrc_data->pack_fmt = 0x1; + rsrc_data->width = rsrc_data->width * 2; + rsrc_data->stride = rsrc_data->width; + break; + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN32_20: + rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->pack_fmt = 0x0; + rsrc_data->en_cfg = 0x3; + break; + case CAM_FORMAT_PLAIN64: + rsrc_data->en_cfg = 0x1; + rsrc_data->pack_fmt = 0xA; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported RDI format %d", + rsrc_data->format); + return -EINVAL; + } + } else if ((rsrc_data->index < 5) || + (rsrc_data->index == 7) || (rsrc_data->index == 8) || + (rsrc_data->index == 20) || (rsrc_data->index == 21)) { + /* + * Write master 3, 4 - for Full OUT , 7-8 FD OUT, + * WM 20-21 = FULL_DISP + */ + switch (rsrc_data->format) { + case CAM_FORMAT_UBWC_NV12_4R: + rsrc_data->en_ubwc = 1; + rsrc_data->width = ALIGNUP(rsrc_data->width, 64); + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_UBWC_NV12: + rsrc_data->en_ubwc = 1; + /* Fall through for NV12 */ + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + case CAM_FORMAT_Y_ONLY: + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_UBWC_TP10: + rsrc_data->en_ubwc = 1; + rsrc_data->width = + ALIGNUP(rsrc_data->width, 48) * 4 / 3; + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_TP10: + rsrc_data->width = + ALIGNUP(rsrc_data->width, 3) * 4 / 3; + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_PLAIN16_10: + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + rsrc_data->width *= 2; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d", + rsrc_data->format); + return -EINVAL; + } + rsrc_data->en_cfg = 0x1; + } else if (rsrc_data->index >= 11 && rsrc_data->index < 20) { + /* Write master 11 - 19 stats */ + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = 0x3; + } else if (rsrc_data->index == 10) { + /* Write master 10 - PDAF/2PD */ + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = 0x3; + if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_PDAF) + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x10; + } else if (rsrc_data->index == 9) { + /* Write master 9 - Raw dump */ + rsrc_data->width = rsrc_data->width * 2; + rsrc_data->stride = rsrc_data->width; + rsrc_data->en_cfg = 0x1; + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x10; + } else { + /* Write master 5-6 DS ports */ + uint32_t align_width; + + rsrc_data->width = rsrc_data->width * 4; + rsrc_data->height = rsrc_data->height / 2; + rsrc_data->en_cfg = 0x1; + CAM_DBG(CAM_ISP, "before width %d", rsrc_data->width); + align_width = ALIGNUP(rsrc_data->width, 16); + if (align_width != rsrc_data->width) { + CAM_WARN(CAM_ISP, + "Override width %u with expected %u", + rsrc_data->width, align_width); + rsrc_data->width = align_width; + } + } + + *client_done_mask = (1 << wm_idx); + *wm_res = wm_res_local; + + CAM_DBG(CAM_ISP, "WM %d: processed width %d, processed height %d", + rsrc_data->index, rsrc_data->width, rsrc_data->height); + return 0; +} + +static int cam_vfe_bus_release_wm(void *bus_priv, + struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = + wm_res->res_priv; + + rsrc_data->offset = 0; + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 0; + rsrc_data->format = 0; + rsrc_data->pack_fmt = 0; + rsrc_data->burst_len = 0; + rsrc_data->irq_subsample_period = 0; + rsrc_data->irq_subsample_pattern = 0; + rsrc_data->framedrop_period = 0; + rsrc_data->framedrop_pattern = 0; + rsrc_data->packer_cfg = 0; + rsrc_data->en_ubwc = 0; + rsrc_data->tile_cfg = 0; + rsrc_data->h_init = 0; + rsrc_data->v_init = 0; + rsrc_data->ubwc_meta_stride = 0; + rsrc_data->ubwc_mode_cfg_0 = 0; + rsrc_data->ubwc_mode_cfg_1 = 0; + rsrc_data->ubwc_meta_offset = 0; + rsrc_data->init_cfg_done = false; + rsrc_data->hfr_cfg_done = false; + rsrc_data->en_cfg = 0; + rsrc_data->is_dual = 0; + + rsrc_data->ubwc_lossy_threshold_0 = 0; + rsrc_data->ubwc_lossy_threshold_1 = 0; + rsrc_data->ubwc_bandwidth_limit = 0; + wm_res->tasklet_info = NULL; + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +static int cam_vfe_bus_start_wm( + struct cam_isp_resource_node *wm_res, + uint32_t *bus_irq_reg_mask) +{ + int rc = 0, val = 0; + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_vfe_bus_ver2_common_data *common_data = + rsrc_data->common_data; + uint32_t camera_hw_version; + + cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit); + + cam_io_w_mb(rsrc_data->width, + common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg); + cam_io_w(rsrc_data->height, + common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg); + cam_io_w(rsrc_data->pack_fmt, + common_data->mem_base + rsrc_data->hw_regs->packer_cfg); + + /* Configure stride for RDIs */ + if (rsrc_data->index < 3) + cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + + rsrc_data->hw_regs->stride)); + + bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] = (1 << rsrc_data->index); + + /* enable ubwc if needed*/ + if (rsrc_data->en_ubwc) { + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version:%d rc:%d", + camera_hw_version, rc); + return rc; + } + if ((camera_hw_version > CAM_CPAS_TITAN_NONE) && + (camera_hw_version < CAM_CPAS_TITAN_175_V100)) { + struct cam_vfe_bus_ver2_reg_offset_ubwc_client + *ubwc_regs; + + ubwc_regs = + (struct + cam_vfe_bus_ver2_reg_offset_ubwc_client *) + rsrc_data->hw_regs->ubwc_regs; + val = cam_io_r_mb(common_data->mem_base + + ubwc_regs->mode_cfg_0); + val |= 0x1; + cam_io_w_mb(val, common_data->mem_base + + ubwc_regs->mode_cfg_0); + } else if ((camera_hw_version == CAM_CPAS_TITAN_175_V100) || + (camera_hw_version == CAM_CPAS_TITAN_175_V101) || + (camera_hw_version == CAM_CPAS_TITAN_175_V120) || + (camera_hw_version == CAM_CPAS_TITAN_175_V130)) { + struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client + *ubwc_regs; + + ubwc_regs = + (struct + cam_vfe_bus_ver2_reg_offset_ubwc_3_client *) + rsrc_data->hw_regs->ubwc_regs; + val = cam_io_r_mb(common_data->mem_base + + ubwc_regs->mode_cfg_0); + val |= 0x1; + cam_io_w_mb(val, common_data->mem_base + + ubwc_regs->mode_cfg_0); + } else { + CAM_ERR(CAM_ISP, "Invalid HW version: %d", + camera_hw_version); + return -EINVAL; + } + } + + /* Enable WM */ + cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + + rsrc_data->hw_regs->cfg); + + CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index, + rsrc_data->width, rsrc_data->height); + CAM_DBG(CAM_ISP, "WM res %d pk_fmt = %d", rsrc_data->index, + rsrc_data->pack_fmt & PACKER_FMT_MAX); + CAM_DBG(CAM_ISP, "WM res %d stride = %d, burst len = %d", + rsrc_data->index, rsrc_data->stride, 0xf); + CAM_DBG(CAM_ISP, "enable WM res %d offset 0x%x val 0x%x", + rsrc_data->index, (uint32_t) rsrc_data->hw_regs->cfg, + rsrc_data->en_cfg); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return rc; +} + +static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res) +{ + int rc = 0; + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_vfe_bus_ver2_common_data *common_data = + rsrc_data->common_data; + + /* Disable WM */ + cam_io_w_mb(0x0, + common_data->mem_base + rsrc_data->hw_regs->cfg); + + /* Disable all register access, reply on global reset */ + + wm_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_handle_wm_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + return -EPERM; +} + +static int cam_vfe_bus_handle_wm_done_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + int rc = CAM_VFE_IRQ_STATUS_ERR; + struct cam_isp_resource_node *wm_res = handler_priv; + struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = + (wm_res == NULL) ? NULL : wm_res->res_priv; + uint32_t *cam_ife_irq_regs; + uint32_t status_reg; + + if (!evt_payload || !wm_res || !rsrc_data) + return rc; + + CAM_DBG(CAM_ISP, "addr of evt_payload = %llx core index:0x%x", + (uint64_t)evt_payload, evt_payload->core_index); + CAM_DBG(CAM_ISP, "bus_irq_status_0: = %x", evt_payload->irq_reg_val[0]); + CAM_DBG(CAM_ISP, "bus_irq_status_1: = %x", evt_payload->irq_reg_val[1]); + CAM_DBG(CAM_ISP, "bus_irq_status_2: = %x", evt_payload->irq_reg_val[2]); + CAM_DBG(CAM_ISP, "bus_irq_comp_err: = %x", evt_payload->irq_reg_val[3]); + CAM_DBG(CAM_ISP, "bus_irq_comp_owrt: = %x", + evt_payload->irq_reg_val[4]); + CAM_DBG(CAM_ISP, "bus_irq_dual_comp_err: = %x", + evt_payload->irq_reg_val[5]); + CAM_DBG(CAM_ISP, "bus_irq_dual_comp_owrt: = %x", + evt_payload->irq_reg_val[6]); + + cam_ife_irq_regs = evt_payload->irq_reg_val; + status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1]; + + if (status_reg & BIT(rsrc_data->index)) { + cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &= + ~BIT(rsrc_data->index); + rc = CAM_VFE_IRQ_STATUS_SUCCESS; + evt_payload->evt_id = CAM_ISP_HW_EVENT_DONE; + } + CAM_DBG(CAM_ISP, "status_reg %x rc %d wm_idx %d", + status_reg, rc, rsrc_data->index); + + return rc; +} + + +static int cam_vfe_bus_err_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_vfe_bus_ver2_priv *bus_priv = handler_priv; + struct cam_vfe_bus_ver2_common_data *common_data; + struct cam_isp_hw_event_info evt_info; + uint32_t val = 0; + + if (!handler_priv || !evt_payload_priv) + return -EINVAL; + + evt_payload = evt_payload_priv; + common_data = &bus_priv->common_data; + + val = evt_payload->debug_status_0; + CAM_ERR(CAM_ISP, "Bus Violation: debug_status_0 = 0x%x", val); + + if (val & 0x01) + CAM_INFO(CAM_ISP, "RDI 0 violation"); + + if (val & 0x02) + CAM_INFO(CAM_ISP, "RDI 1 violation"); + + if (val & 0x04) + CAM_INFO(CAM_ISP, "RDI 2 violation"); + + if (val & 0x08) + CAM_INFO(CAM_ISP, "VID Y 1:1 UBWC violation"); + + if (val & 0x010) + CAM_INFO(CAM_ISP, "VID C 1:1 UBWC violation"); + + if (val & 0x020) + CAM_INFO(CAM_ISP, "VID YC 4:1 violation"); + + if (val & 0x040) + CAM_INFO(CAM_ISP, "VID YC 16:1 violation"); + + if (val & 0x080) + CAM_INFO(CAM_ISP, "FD Y violation"); + + if (val & 0x0100) + CAM_INFO(CAM_ISP, "FD C violation"); + + if (val & 0x0200) + CAM_INFO(CAM_ISP, "RAW DUMP violation"); + + if (val & 0x0400) + CAM_INFO(CAM_ISP, "PDAF violation"); + + if (val & 0x0800) + CAM_INFO(CAM_ISP, "STATs HDR BE violation"); + + if (val & 0x01000) + CAM_INFO(CAM_ISP, "STATs HDR BHIST violation"); + + if (val & 0x02000) + CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation"); + + if (val & 0x04000) + CAM_INFO(CAM_ISP, "STATs BF violation"); + + if (val & 0x08000) + CAM_INFO(CAM_ISP, "STATs AWB BG UBWC violation"); + + if (val & 0x010000) + CAM_INFO(CAM_ISP, "STATs BHIST violation"); + + if (val & 0x020000) + CAM_INFO(CAM_ISP, "STATs RS violation"); + + if (val & 0x040000) + CAM_INFO(CAM_ISP, "STATs CS violation"); + + if (val & 0x080000) + CAM_INFO(CAM_ISP, "STATs IHIST violation"); + + if (val & 0x0100000) + CAM_INFO(CAM_ISP, "DISP Y 1:1 UBWC violation"); + + if (val & 0x0200000) + CAM_INFO(CAM_ISP, "DISP C 1:1 UBWC violation"); + + if (val & 0x0400000) + CAM_INFO(CAM_ISP, "DISP YC 4:1 violation"); + + if (val & 0x0800000) + CAM_INFO(CAM_ISP, "DISP YC 16:1 violation"); + + cam_vfe_bus_put_evt_payload(common_data, &evt_payload); + + evt_info.hw_idx = common_data->core_index; + evt_info.res_type = CAM_ISP_RESOURCE_VFE_OUT; + evt_info.res_id = CAM_VFE_BUS_VER2_VFE_OUT_MAX; + + if (common_data->event_cb) + common_data->event_cb(NULL, CAM_ISP_HW_EVENT_ERROR, + (void *)&evt_info); + + return 0; +} + +static int cam_vfe_bus_init_wm_resource(uint32_t index, + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_vfe_bus_ver2_hw_info *ver2_hw_info, + struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data; + + rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data), + GFP_KERNEL); + if (!rsrc_data) { + CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv"); + return -ENOMEM; + } + wm_res->res_priv = rsrc_data; + + rsrc_data->index = index; + rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index]; + rsrc_data->common_data = &ver2_bus_priv->common_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = NULL; + wm_res->stop = NULL; + wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half; + wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half; + wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_vfe_bus_deinit_wm_resource( + struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = NULL; + wm_res->stop = NULL; + wm_res->top_half_handler = NULL; + wm_res->bottom_half_handler = NULL; + wm_res->hw_intf = NULL; + + rsrc_data = wm_res->res_priv; + wm_res->res_priv = NULL; + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static void cam_vfe_bus_add_wm_to_comp_grp( + struct cam_isp_resource_node *comp_grp, + uint32_t composite_mask) +{ + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv; + + rsrc_data->composite_mask |= composite_mask; +} + +static void cam_vfe_bus_match_comp_grp( + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_isp_resource_node **comp_grp, + uint32_t comp_grp_local_idx, + uint32_t unique_id) +{ + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; + struct cam_isp_resource_node *comp_grp_local = NULL; + + list_for_each_entry(comp_grp_local, + &ver2_bus_priv->used_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx && + rsrc_data->unique_id == unique_id) { + /* Match found */ + *comp_grp = comp_grp_local; + return; + } + } + + *comp_grp = NULL; +} + +static int cam_vfe_bus_acquire_comp_grp( + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_isp_out_port_generic_info *out_port_info, + void *tasklet, + uint32_t unique_id, + uint32_t is_dual, + uint32_t is_master, + enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core, + struct cam_isp_resource_node **comp_grp) +{ + int rc = 0; + uint32_t bus_comp_grp_id; + struct cam_isp_resource_node *comp_grp_local = NULL; + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; + + bus_comp_grp_id = cam_vfe_bus_comp_grp_id_convert( + out_port_info->comp_grp_id); + /* Perform match only if there is valid comp grp request */ + if (out_port_info->comp_grp_id != CAM_ISP_RES_COMP_GROUP_NONE) { + /* Check if matching comp_grp already acquired */ + cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local, + bus_comp_grp_id, unique_id); + } + + if (!comp_grp_local) { + /* First find a free group */ + if (is_dual) { + CAM_DBG(CAM_ISP, "Acquire dual comp group"); + if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) { + CAM_ERR(CAM_ISP, "No Free Composite Group"); + return -ENODEV; + } + comp_grp_local = list_first_entry( + &ver2_bus_priv->free_dual_comp_grp, + struct cam_isp_resource_node, list); + rsrc_data = comp_grp_local->res_priv; + rc = cam_vfe_bus_ver2_get_intra_client_mask( + dual_slave_core, + comp_grp_local->hw_intf->hw_idx, + &rsrc_data->intra_client_mask); + if (rc) + return rc; + } else { + CAM_DBG(CAM_ISP, "Acquire comp group"); + if (list_empty(&ver2_bus_priv->free_comp_grp)) { + CAM_ERR(CAM_ISP, "No Free Composite Group"); + return -ENODEV; + } + comp_grp_local = list_first_entry( + &ver2_bus_priv->free_comp_grp, + struct cam_isp_resource_node, list); + rsrc_data = comp_grp_local->res_priv; + } + + list_del(&comp_grp_local->list); + comp_grp_local->tasklet_info = tasklet; + comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + rsrc_data->is_master = is_master; + rsrc_data->composite_mask = 0; + rsrc_data->unique_id = unique_id; + rsrc_data->comp_grp_local_idx = bus_comp_grp_id; + + if (is_master) + rsrc_data->addr_sync_mode = 0; + else + rsrc_data->addr_sync_mode = 1; + + list_add_tail(&comp_grp_local->list, + &ver2_bus_priv->used_comp_grp); + + } else { + rsrc_data = comp_grp_local->res_priv; + /* Do not support runtime change in composite mask */ + if (comp_grp_local->res_state == + CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "Invalid State %d Comp Grp %u", + comp_grp_local->res_state, + rsrc_data->comp_grp_type); + return -EBUSY; + } + } + + CAM_DBG(CAM_ISP, "Comp Grp type %u", rsrc_data->comp_grp_type); + + rsrc_data->acquire_dev_cnt++; + *comp_grp = comp_grp_local; + + return rc; +} + +static int cam_vfe_bus_release_comp_grp( + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_isp_resource_node *in_comp_grp) +{ + struct cam_isp_resource_node *comp_grp = NULL; + struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL; + int match_found = 0; + + if (!in_comp_grp) { + CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_comp_grp); + return -EINVAL; + } + + if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "Already released Comp Grp"); + return 0; + } + + if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "Invalid State %d", + in_comp_grp->res_state); + return -EBUSY; + } + + in_rsrc_data = in_comp_grp->res_priv; + CAM_DBG(CAM_ISP, "Comp Grp type %u", in_rsrc_data->comp_grp_type); + + list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) { + if (comp_grp == in_comp_grp) { + match_found = 1; + break; + } + } + + if (!match_found) { + CAM_ERR(CAM_ISP, "Could not find matching Comp Grp type %u", + in_rsrc_data->comp_grp_type); + return -ENODEV; + } + + in_rsrc_data->acquire_dev_cnt--; + if (in_rsrc_data->acquire_dev_cnt == 0) { + list_del(&comp_grp->list); + + in_rsrc_data->unique_id = 0; + in_rsrc_data->comp_grp_local_idx = CAM_VFE_BUS_COMP_GROUP_NONE; + in_rsrc_data->composite_mask = 0; + in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX; + in_rsrc_data->addr_sync_mode = 0; + + comp_grp->tasklet_info = NULL; + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + if (in_rsrc_data->comp_grp_type >= + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && + in_rsrc_data->comp_grp_type <= + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) + list_add_tail(&comp_grp->list, + &ver2_bus_priv->free_dual_comp_grp); + else if (in_rsrc_data->comp_grp_type >= + CAM_VFE_BUS_VER2_COMP_GRP_0 && + in_rsrc_data->comp_grp_type <= + CAM_VFE_BUS_VER2_COMP_GRP_5) + list_add_tail(&comp_grp->list, + &ver2_bus_priv->free_comp_grp); + } + + return 0; +} + +static int cam_vfe_bus_start_comp_grp( + struct cam_isp_resource_node *comp_grp, + uint32_t *bus_irq_reg_mask) +{ + int rc = 0; + uint32_t addr_sync_cfg; + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = + comp_grp->res_priv; + struct cam_vfe_bus_ver2_common_data *common_data = + rsrc_data->common_data; + + CAM_DBG(CAM_ISP, "comp group id:%d streaming state:%d", + rsrc_data->comp_grp_type, comp_grp->res_state); + + cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base + + rsrc_data->hw_regs->comp_mask); + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + return 0; + + CAM_DBG(CAM_ISP, "composite_mask is 0x%x", rsrc_data->composite_mask); + CAM_DBG(CAM_ISP, "composite_mask addr 0x%x", + rsrc_data->hw_regs->comp_mask); + + if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && + rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) { + int dual_comp_grp = (rsrc_data->comp_grp_type - + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0); + + if (rsrc_data->is_master) { + int intra_client_en = cam_io_r_mb( + common_data->mem_base + + common_data->common_reg->dual_master_comp_cfg); + + /* + * 2 Bits per comp_grp. Hence left shift by + * comp_grp * 2 + */ + intra_client_en |= + (rsrc_data->intra_client_mask << + (dual_comp_grp * 2)); + + cam_io_w_mb(intra_client_en, common_data->mem_base + + common_data->common_reg->dual_master_comp_cfg); + + bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = + (1 << dual_comp_grp); + } + + CAM_DBG(CAM_ISP, "addr_sync_mask addr 0x%x", + rsrc_data->hw_regs->addr_sync_mask); + cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base + + rsrc_data->hw_regs->addr_sync_mask); + + addr_sync_cfg = cam_io_r_mb(common_data->mem_base + + common_data->common_reg->addr_sync_cfg); + addr_sync_cfg |= (rsrc_data->addr_sync_mode << dual_comp_grp); + /* + * 2 Bits per dual_comp_grp. dual_comp_grp stats at bit number + * 8. Hence left shift cdual_comp_grp dual comp_grp * 2 and + * add 8 + */ + addr_sync_cfg |= + (rsrc_data->intra_client_mask << + ((dual_comp_grp * 2) + + CAM_VFE_BUS_ADDR_SYNC_INTRA_CLIENT_SHIFT)); + cam_io_w_mb(addr_sync_cfg, common_data->mem_base + + common_data->common_reg->addr_sync_cfg); + + common_data->addr_no_sync &= ~(rsrc_data->composite_mask); + cam_io_w_mb(common_data->addr_no_sync, common_data->mem_base + + common_data->common_reg->addr_sync_no_sync); + CAM_DBG(CAM_ISP, "addr_sync_cfg: 0x%x addr_no_sync_cfg: 0x%x", + addr_sync_cfg, common_data->addr_no_sync); + } else { + /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */ + bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] = + (1 << (rsrc_data->comp_grp_type + 5)); + } + + CAM_DBG(CAM_ISP, "VFE start COMP_GRP%d", rsrc_data->comp_grp_type); + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return rc; +} + +static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp) +{ + int rc = 0; + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + return rc; +} + +static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + return -EPERM; +} + +static int cam_vfe_bus_handle_comp_done_bottom_half(void *handler_priv, + void *evt_payload_priv, uint32_t *comp_mask) +{ + int rc = CAM_VFE_IRQ_STATUS_ERR; + struct cam_isp_resource_node *comp_grp = handler_priv; + struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv; + uint32_t *cam_ife_irq_regs; + uint32_t status_reg; + uint32_t comp_err_reg; + uint32_t comp_grp_id; + + CAM_DBG(CAM_ISP, "comp grp type %d", rsrc_data->comp_grp_type); + + if (!evt_payload) + return rc; + + cam_ife_irq_regs = evt_payload->irq_reg_val; + + switch (rsrc_data->comp_grp_type) { + case CAM_VFE_BUS_VER2_COMP_GRP_0: + case CAM_VFE_BUS_VER2_COMP_GRP_1: + case CAM_VFE_BUS_VER2_COMP_GRP_2: + case CAM_VFE_BUS_VER2_COMP_GRP_3: + case CAM_VFE_BUS_VER2_COMP_GRP_4: + case CAM_VFE_BUS_VER2_COMP_GRP_5: + comp_grp_id = (rsrc_data->comp_grp_type - + CAM_VFE_BUS_VER2_COMP_GRP_0); + + /* Check for Regular composite error */ + status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0]; + + comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR]; + if ((status_reg & BIT(11)) && + (comp_err_reg & rsrc_data->composite_mask)) { + /* Check for Regular composite error */ + evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR; + rc = CAM_VFE_IRQ_STATUS_ERR_COMP; + break; + } + + comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT]; + /* Check for Regular composite Overwrite */ + if ((status_reg & BIT(12)) && + (comp_err_reg & rsrc_data->composite_mask)) { + evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR; + rc = CAM_VFE_IRQ_STATUS_COMP_OWRT; + break; + } + + /* Regular Composite SUCCESS */ + if (status_reg & BIT(comp_grp_id + 5)) { + evt_payload->evt_id = CAM_ISP_HW_EVENT_DONE; + rc = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + CAM_DBG(CAM_ISP, "status reg = 0x%x, bit index = %d rc %d", + status_reg, (comp_grp_id + 5), rc); + break; + + case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0: + case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1: + case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2: + case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3: + case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4: + case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5: + comp_grp_id = (rsrc_data->comp_grp_type - + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0); + + /* Check for DUAL composite error */ + status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2]; + + comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR]; + if ((status_reg & BIT(6)) && + (comp_err_reg & rsrc_data->composite_mask)) { + /* Check for DUAL composite error */ + evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR; + rc = CAM_VFE_IRQ_STATUS_ERR_COMP; + break; + } + + /* Check for Dual composite Overwrite */ + comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT]; + if ((status_reg & BIT(7)) && + (comp_err_reg & rsrc_data->composite_mask)) { + evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR; + rc = CAM_VFE_IRQ_STATUS_COMP_OWRT; + break; + } + + /* DUAL Composite SUCCESS */ + if (status_reg & BIT(comp_grp_id)) { + evt_payload->evt_id = CAM_ISP_HW_EVENT_DONE; + rc = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + break; + default: + rc = CAM_VFE_IRQ_STATUS_ERR; + CAM_ERR(CAM_ISP, "Invalid comp_grp_type %u", + rsrc_data->comp_grp_type); + break; + } + + *comp_mask = rsrc_data->composite_mask; + + return rc; +} + +static int cam_vfe_bus_init_comp_grp(uint32_t index, + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_vfe_bus_ver2_hw_info *ver2_hw_info, + struct cam_isp_resource_node *comp_grp) +{ + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; + + rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data), + GFP_KERNEL); + if (!rsrc_data) + return -ENOMEM; + + comp_grp->res_priv = rsrc_data; + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&comp_grp->list); + + rsrc_data->comp_grp_type = index; + rsrc_data->common_data = &ver2_bus_priv->common_data; + rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index]; + rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX; + + if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && + rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) + list_add_tail(&comp_grp->list, + &ver2_bus_priv->free_dual_comp_grp); + else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0 + && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5) + list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp); + + comp_grp->start = NULL; + comp_grp->stop = NULL; + comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half; + comp_grp->bottom_half_handler = NULL; + comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_vfe_bus_deinit_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = + comp_grp->res_priv; + + comp_grp->start = NULL; + comp_grp->stop = NULL; + comp_grp->top_half_handler = NULL; + comp_grp->bottom_half_handler = NULL; + comp_grp->hw_intf = NULL; + + list_del_init(&comp_grp->list); + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + + comp_grp->res_priv = NULL; + + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "comp_grp_priv is NULL"); + return -ENODEV; + } + kfree(rsrc_data); + + return 0; +} + +static int cam_vfe_bus_get_secure_mode(void *priv, void *cmd_args, + uint32_t arg_size) +{ + bool *mode = cmd_args; + struct cam_isp_resource_node *res = + (struct cam_isp_resource_node *) priv; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = + (struct cam_vfe_bus_ver2_vfe_out_data *)res->res_priv; + + *mode = + (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? + true : false; + + return 0; +} + +static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args, + uint32_t args_size) +{ + int rc = -ENODEV; + int i; + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id; + uint32_t format; + int num_wm; + uint32_t client_done_mask; + struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv; + struct cam_vfe_acquire_args *acq_args = acquire_args; + struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + uint32_t secure_caps = 0, mode; + + if (!bus_priv || !acquire_args) { + CAM_ERR(CAM_ISP, "Invalid Param"); + return -EINVAL; + } + + out_acquire_args = &acq_args->vfe_out; + format = out_acquire_args->out_port_info->format; + + CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x", + out_acquire_args->out_port_info->res_type); + + vfe_out_res_id = cam_vfe_bus_get_out_res_id( + out_acquire_args->out_port_info->res_type); + if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX) + return -ENODEV; + + num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format); + if (num_wm < 1) + return -EINVAL; + + rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id]; + if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d", + vfe_out_res_id, rsrc_node->res_state); + return -EBUSY; + } + + rsrc_data = rsrc_node->res_priv; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + + secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->out_type); + mode = out_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); + + ver2_bus_priv->tasklet_info = acq_args->tasklet; + rsrc_data->num_wm = num_wm; + rsrc_node->res_id = out_acquire_args->out_port_info->res_type; + rsrc_node->tasklet_info = acq_args->tasklet; + rsrc_node->cdm_ops = out_acquire_args->cdm_ops; + rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops; + + /* Reserve Composite Group */ + if (num_wm > 1 || (out_acquire_args->is_dual) || + (out_acquire_args->out_port_info->comp_grp_id > + CAM_ISP_RES_COMP_GROUP_NONE && + out_acquire_args->out_port_info->comp_grp_id < + CAM_ISP_RES_COMP_GROUP_ID_MAX)) { + + rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + out_acquire_args->unique_id, + out_acquire_args->is_dual, + out_acquire_args->is_master, + out_acquire_args->dual_slave_core, + &rsrc_data->comp_grp); + if (rc) { + CAM_ERR(CAM_ISP, + "VFE%d Comp_Grp acquire fail for Out %d rc=%d", + rsrc_data->common_data->core_index, + vfe_out_res_id, rc); + return rc; + } + } + + /* Reserve WM */ + for (i = 0; i < num_wm; i++) { + rc = cam_vfe_bus_acquire_wm(ver2_bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + vfe_out_res_id, + i, + &rsrc_data->wm_res[i], + &client_done_mask, + out_acquire_args->is_dual); + if (rc) { + CAM_ERR(CAM_ISP, + "VFE%d WM acquire failed for Out %d rc=%d", + rsrc_data->common_data->core_index, + vfe_out_res_id, rc); + goto release_wm; + } + + if (rsrc_data->comp_grp) + cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp, + client_done_mask); + } + + rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + out_acquire_args->rsrc_node = rsrc_node; + + CAM_DBG(CAM_ISP, "Acquire successful"); + return rc; + +release_wm: + for (i--; i >= 0; i--) + cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]); + + cam_vfe_bus_release_comp_grp(ver2_bus_priv, + rsrc_data->comp_grp); + + return rc; +} + +static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args, + uint32_t args_size) +{ + uint32_t i; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver2_vfe_out_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_out = release_args; + rsrc_data = vfe_out->res_priv; + + if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Invalid resource state:%d", + vfe_out->res_state); + } + + for (i = 0; i < rsrc_data->num_wm; i++) + cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]); + rsrc_data->num_wm = 0; + + if (rsrc_data->comp_grp) + cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); + rsrc_data->comp_grp = NULL; + + vfe_out->tasklet_info = NULL; + vfe_out->cdm_ops = NULL; + rsrc_data->cdm_util_ops = NULL; + + secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->out_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_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +static int cam_vfe_bus_start_vfe_out( + struct cam_isp_resource_node *vfe_out) +{ + int rc = 0, i; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver2_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX]; + + 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 index %d", rsrc_data->out_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; + } + + memset(bus_irq_reg_mask, 0, sizeof(bus_irq_reg_mask)); + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i], + bus_irq_reg_mask); + + if (rsrc_data->comp_grp) { + memset(bus_irq_reg_mask, 0, sizeof(bus_irq_reg_mask)); + rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp, + bus_irq_reg_mask); + } + + vfe_out->irq_handle = cam_irq_controller_subscribe_irq( + common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1, + bus_irq_reg_mask, vfe_out, vfe_out->top_half_handler, + vfe_out->bottom_half_handler, vfe_out->tasklet_info, + &tasklet_bh_api); + + if (vfe_out->irq_handle < 1) { + CAM_ERR(CAM_ISP, "Subscribe IRQ failed for res_id %d", + vfe_out->res_id); + vfe_out->irq_handle = 0; + return -EFAULT; + } + + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return rc; +} + +static int cam_vfe_bus_stop_vfe_out( + struct cam_isp_resource_node *vfe_out) +{ + int rc = 0, i; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver2_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; + + if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE || + vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "vfe_out res_state is %d", vfe_out->res_state); + return rc; + } + + if (rsrc_data->comp_grp) + rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp); + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]); + + if (vfe_out->irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + common_data->bus_irq_controller, + vfe_out->irq_handle); + vfe_out->irq_handle = 0; + } + + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_irq_evt_payload *evt_payload; + + vfe_out = th_payload->handler_priv; + if (!vfe_out) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + + rsrc_data = vfe_out->res_priv; + + CAM_DBG(CAM_ISP, "IRQ status_0 = 0x%x", th_payload->evt_status_arr[0]); + CAM_DBG(CAM_ISP, "IRQ status_1 = 0x%x", th_payload->evt_status_arr[1]); + CAM_DBG(CAM_ISP, "IRQ status_2 = 0x%x", th_payload->evt_status_arr[2]); + + rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "IRQ status_0 = 0x%x status_1 = 0x%x status_2 = 0x%x", + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1], + th_payload->evt_status_arr[2]); + + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + evt_payload->core_index = rsrc_data->common_data->core_index; + evt_payload->evt_id = evt_id; + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_bus_handle_vfe_out_done_bottom_half( + void *handler_priv, + void *evt_payload_priv) +{ + int rc = -EINVAL; + struct cam_isp_resource_node *vfe_out = handler_priv; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv; + struct cam_isp_hw_event_info evt_info; + void *ctx = NULL; + uint32_t evt_id = 0; + uint32_t comp_mask = 0; + int num_out = 0, i = 0; + struct cam_vfe_bus_irq_evt_payload *evt_payload = + evt_payload_priv; + uint32_t out_list[CAM_VFE_BUS_VER2_VFE_OUT_MAX] = {0}; + + /* + * If this resource has Composite Group then we only handle + * Composite done. We acquire Composite if number of WM > 1. + * So Else case is only one individual buf_done = WM[0]. + */ + if (rsrc_data->comp_grp) { + rc = cam_vfe_bus_handle_comp_done_bottom_half( + rsrc_data->comp_grp, evt_payload_priv, &comp_mask); + } else { + rc = rsrc_data->wm_res[0]->bottom_half_handler( + rsrc_data->wm_res[0], evt_payload_priv); + } + + ctx = rsrc_data->priv; + + switch (rc) { + case CAM_VFE_IRQ_STATUS_SUCCESS: + evt_id = evt_payload->evt_id; + + evt_info.res_type = vfe_out->res_type; + evt_info.hw_idx = vfe_out->hw_intf->hw_idx; + if (rsrc_data->comp_grp) { + cam_vfe_bus_get_comp_vfe_out_res_id_list( + comp_mask, out_list, &num_out); + for (i = 0; i < num_out; i++) { + evt_info.res_id = out_list[i]; + if (rsrc_data->common_data->event_cb) + rsrc_data->common_data->event_cb(ctx, + evt_id, (void *)&evt_info); + } + } else { + evt_info.res_id = vfe_out->res_id; + if (rsrc_data->common_data->event_cb) + rsrc_data->common_data->event_cb(ctx, evt_id, + (void *)&evt_info); + } + break; + default: + break; + } + + cam_vfe_bus_put_evt_payload(rsrc_data->common_data, &evt_payload); + CAM_DBG(CAM_ISP, "vfe_out %d rc %d", rsrc_data->out_type, rc); + + return rc; +} + +static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_vfe_bus_ver2_hw_info *ver2_hw_info) +{ + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + int rc = 0; + int32_t vfe_out_type = + ver2_hw_info->vfe_out_hw_info[index].vfe_out_type; + + if (vfe_out_type < 0 || + vfe_out_type >= CAM_VFE_BUS_VER2_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d", + vfe_out_type); + return -EINVAL; + } + + vfe_out = &ver2_bus_priv->vfe_out[vfe_out_type]; + if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || + vfe_out->res_priv) { + CAM_ERR(CAM_ISP, + "Error. Looks like same resource is init again"); + return -EFAULT; + } + + rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data), + GFP_KERNEL); + if (!rsrc_data) { + rc = -ENOMEM; + return rc; + } + + vfe_out->res_priv = rsrc_data; + + vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT; + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&vfe_out->list); + + rsrc_data->out_type = + ver2_hw_info->vfe_out_hw_info[index].vfe_out_type; + rsrc_data->common_data = &ver2_bus_priv->common_data; + rsrc_data->max_width = + ver2_hw_info->vfe_out_hw_info[index].max_width; + rsrc_data->max_height = + ver2_hw_info->vfe_out_hw_info[index].max_height; + rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + + vfe_out->start = cam_vfe_bus_start_vfe_out; + vfe_out->stop = cam_vfe_bus_stop_vfe_out; + vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half; + vfe_out->bottom_half_handler = + cam_vfe_bus_handle_vfe_out_done_bottom_half; + vfe_out->process_cmd = cam_vfe_bus_process_cmd; + vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf; + vfe_out->irq_handle = 0; + + return 0; +} + +static int cam_vfe_bus_deinit_vfe_out_resource( + struct cam_isp_resource_node *vfe_out) +{ + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv; + + if (vfe_out->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_out->start = NULL; + vfe_out->stop = NULL; + vfe_out->top_half_handler = NULL; + vfe_out->bottom_half_handler = NULL; + vfe_out->hw_intf = NULL; + vfe_out->irq_handle = 0; + + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&vfe_out->list); + vfe_out->res_priv = NULL; + + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_vfe_bus_ver2_priv *bus_priv; + int rc = 0; + + bus_priv = th_payload->handler_priv; + CAM_DBG(CAM_ISP, "Enter"); + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.bus_irq_controller); + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; +} + +static int cam_vfe_bus_error_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int i = 0, rc = 0; + struct cam_vfe_bus_ver2_priv *bus_priv = + th_payload->handler_priv; + struct cam_vfe_bus_irq_evt_payload *evt_payload; + + CAM_ERR_RATE_LIMIT(CAM_ISP, "Bus Err IRQ"); + for (i = 0; i < th_payload->num_registers; i++) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "vfe:%d: IRQ_Status%d: 0x%x", + bus_priv->common_data.core_index, i, + th_payload->evt_status_arr[i]); + } + cam_irq_controller_disable_irq(bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + + rc = cam_vfe_bus_get_evt_payload(&bus_priv->common_data, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Cannot get payload"); + return rc; + } + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->core_index = bus_priv->common_data.core_index; + evt_payload->evt_id = evt_id; + evt_payload->debug_status_0 = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->debug_status_0); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static void cam_vfe_bus_update_ubwc_meta_addr( + uint32_t *reg_val_pair, + uint32_t *j, + void *regs, + uint64_t image_buf) +{ + uint32_t camera_hw_version; + struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_regs; + struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *ubwc_3_regs; + int rc = 0; + + if (!regs || !reg_val_pair || !j) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc: %d", rc); + goto end; + } else if ((camera_hw_version < CAM_CPAS_TITAN_170_V100) || + (camera_hw_version > CAM_CPAS_TITAN_175_V130)) { + CAM_ERR(CAM_ISP, "Invalid HW version: %d", + camera_hw_version); + goto end; + } + + switch (camera_hw_version) { + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_170_V120: + ubwc_regs = + (struct cam_vfe_bus_ver2_reg_offset_ubwc_client *)regs; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_addr, + image_buf); + break; + case CAM_CPAS_TITAN_175_V100: + case CAM_CPAS_TITAN_175_V101: + case CAM_CPAS_TITAN_175_V120: + case CAM_CPAS_TITAN_175_V130: + ubwc_3_regs = + (struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *) + regs; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_3_regs->meta_addr, + image_buf); + break; + default: + break; + } +end: + return; +} + +static int cam_vfe_bus_update_ubwc_3_regs( + struct cam_vfe_bus_ver2_wm_resource_data *wm_data, + uint32_t *reg_val_pair, uint32_t i, uint32_t *j) +{ + struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *ubwc_regs; + int rc = 0; + + if (!wm_data || !reg_val_pair || !j) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + ubwc_regs = (struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *) + wm_data->hw_regs->ubwc_regs; + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + wm_data->hw_regs->packer_cfg, wm_data->packer_cfg); + CAM_DBG(CAM_ISP, "WM %d packer cfg 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + if (wm_data->is_dual) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->tile_cfg, wm_data->tile_cfg); + } else { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->tile_cfg, wm_data->tile_cfg); + CAM_DBG(CAM_ISP, "WM %d tile cfg 0x%x", + wm_data->index, reg_val_pair[*j-1]); + } + + if (wm_data->is_dual) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->h_init, wm_data->offset); + } else { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->h_init, wm_data->h_init); + CAM_DBG(CAM_ISP, "WM %d h_init 0x%x", + wm_data->index, reg_val_pair[*j-1]); + } + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->v_init, wm_data->v_init); + CAM_DBG(CAM_ISP, "WM %d v_init 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_stride, wm_data->ubwc_meta_stride); + CAM_DBG(CAM_ISP, "WM %d meta stride 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->mode_cfg_0, wm_data->ubwc_mode_cfg_0); + CAM_DBG(CAM_ISP, "WM %d ubwc_mode_cfg_0 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->mode_cfg_1, wm_data->ubwc_mode_cfg_1); + CAM_DBG(CAM_ISP, "WM %d ubwc_mode_cfg_1 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_offset, wm_data->ubwc_meta_offset); + CAM_DBG(CAM_ISP, "WM %d ubwc meta offset 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + if (wm_data->ubwc_bandwidth_limit) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->bw_limit, wm_data->ubwc_bandwidth_limit); + CAM_DBG(CAM_ISP, "WM %d ubwc bw limit 0x%x", + wm_data->index, wm_data->ubwc_bandwidth_limit); + } + +end: + return rc; +} + +static int cam_vfe_bus_update_ubwc_legacy_regs( + struct cam_vfe_bus_ver2_wm_resource_data *wm_data, + uint32_t camera_hw_version, uint32_t *reg_val_pair, + uint32_t i, uint32_t *j) +{ + struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_regs; + uint32_t ubwc_bw_limit = 0; + int rc = 0; + + if (!wm_data || !reg_val_pair || !j) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + ubwc_regs = (struct cam_vfe_bus_ver2_reg_offset_ubwc_client *) + wm_data->hw_regs->ubwc_regs; + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + wm_data->hw_regs->packer_cfg, wm_data->packer_cfg); + CAM_DBG(CAM_ISP, "WM %d packer cfg 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + if (wm_data->is_dual) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->tile_cfg, wm_data->tile_cfg); + } else { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->tile_cfg, wm_data->tile_cfg); + CAM_DBG(CAM_ISP, "WM %d tile cfg 0x%x", + wm_data->index, reg_val_pair[*j-1]); + } + + if (wm_data->is_dual) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->h_init, wm_data->offset); + } else { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->h_init, wm_data->h_init); + CAM_DBG(CAM_ISP, "WM %d h_init 0x%x", + wm_data->index, reg_val_pair[*j-1]); + } + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->v_init, wm_data->v_init); + CAM_DBG(CAM_ISP, "WM %d v_init 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_stride, wm_data->ubwc_meta_stride); + CAM_DBG(CAM_ISP, "WM %d meta stride 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->mode_cfg_0, wm_data->ubwc_mode_cfg_0); + CAM_DBG(CAM_ISP, "WM %d ubwc_mode_cfg_0 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_offset, wm_data->ubwc_meta_offset); + CAM_DBG(CAM_ISP, "WM %d ubwc meta offset 0x%x", + wm_data->index, reg_val_pair[*j-1]); + + if (camera_hw_version == CAM_CPAS_TITAN_170_V110) { + switch (wm_data->format) { + case CAM_FORMAT_UBWC_TP10: + ubwc_bw_limit = 0x8 | BIT(0); + break; + case CAM_FORMAT_UBWC_NV12_4R: + ubwc_bw_limit = 0xB | BIT(0); + break; + default: + ubwc_bw_limit = 0; + break; + } + } + + if (ubwc_bw_limit) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->bw_limit, ubwc_bw_limit); + CAM_DBG(CAM_ISP, "WM %d ubwc bw limit 0x%x", + wm_data->index, ubwc_bw_limit); + } + +end: + return rc; +} + +static int cam_vfe_bus_update_ubwc_regs( + struct cam_vfe_bus_ver2_wm_resource_data *wm_data, + uint32_t *reg_val_pair, uint32_t i, uint32_t *j) +{ + uint32_t camera_hw_version; + int rc = 0; + + if (!wm_data || !reg_val_pair || !j) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc: %d", rc); + goto end; + } else if ((camera_hw_version <= CAM_CPAS_TITAN_NONE) || + (camera_hw_version >= CAM_CPAS_TITAN_MAX)) { + CAM_ERR(CAM_ISP, "Invalid HW version: %d", + camera_hw_version); + rc = -EINVAL; + goto end; + } + switch (camera_hw_version) { + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_170_V120: + rc = cam_vfe_bus_update_ubwc_legacy_regs( + wm_data, camera_hw_version, reg_val_pair, i, j); + break; + case CAM_CPAS_TITAN_175_V100: + case CAM_CPAS_TITAN_175_V101: + case CAM_CPAS_TITAN_175_V120: + case CAM_CPAS_TITAN_175_V130: + rc = cam_vfe_bus_update_ubwc_3_regs( + wm_data, reg_val_pair, i, j); + break; + default: + break; + } + + if (rc) + CAM_ERR(CAM_ISP, "Failed to update ubwc regs rc:%d", rc); + +end: + return rc; +} + +static int cam_vfe_bus_update_wm(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_buf; + struct cam_buf_io_cfg *io_cfg; + struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_client = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, k, size = 0; + uint32_t frame_inc = 0, val; + uint32_t loop_size = 0; + + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + update_buf->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + if (update_buf->wm_update->num_buf != vfe_out_data->num_wm) { + CAM_ERR(CAM_ISP, + "Failed! Invalid number buffers:%d required:%d", + update_buf->wm_update->num_buf, vfe_out_data->num_wm); + return -EINVAL; + } + + reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; + io_cfg = update_buf->wm_update->io_cfg; + + for (i = 0, j = 0; i < vfe_out_data->num_wm; 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 %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = vfe_out_data->wm_res[i]->res_priv; + ubwc_client = wm_data->hw_regs->ubwc_regs; + /* update width register */ + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->buffer_width_cfg, + wm_data->width); + CAM_DBG(CAM_ISP, "WM %d image width 0x%x", + wm_data->index, reg_val_pair[j-1]); + + /* For initial configuration program all bus registers */ + val = io_cfg->planes[i].plane_stride; + CAM_DBG(CAM_ISP, "before stride %d", val); + val = ALIGNUP(val, 16); + if (val != io_cfg->planes[i].plane_stride && + val != wm_data->stride) + CAM_WARN(CAM_ISP, + "Warning stride %u expected %u", + io_cfg->planes[i].plane_stride, + val); + + if ((wm_data->stride != val || + !wm_data->init_cfg_done) && (wm_data->index >= 3)) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->stride, + io_cfg->planes[i].plane_stride); + wm_data->stride = val; + CAM_DBG(CAM_ISP, "WM %d image stride 0x%x", + wm_data->index, reg_val_pair[j-1]); + } + + if (wm_data->en_ubwc) { + if (!wm_data->hw_regs->ubwc_regs) { + CAM_ERR(CAM_ISP, + "No UBWC register to configure."); + return -EINVAL; + } + if (wm_data->ubwc_updated) { + wm_data->ubwc_updated = false; + cam_vfe_bus_update_ubwc_regs( + wm_data, reg_val_pair, i, &j); + } + + /* UBWC meta address */ + cam_vfe_bus_update_ubwc_meta_addr( + reg_val_pair, &j, + wm_data->hw_regs->ubwc_regs, + update_buf->wm_update->image_buf[i]); + CAM_DBG(CAM_ISP, "WM %d ubwc meta addr 0x%llx", + wm_data->index, + update_buf->wm_update->image_buf[i]); + } + + if (wm_data->en_ubwc) { + frame_inc = ALIGNUP(io_cfg->planes[i].plane_stride * + io_cfg->planes[i].slice_height, 4096); + frame_inc += io_cfg->planes[i].meta_size; + CAM_DBG(CAM_ISP, + "WM %d frm %d: ht: %d stride %d meta: %d", + wm_data->index, frame_inc, + io_cfg->planes[i].slice_height, + io_cfg->planes[i].plane_stride, + io_cfg->planes[i].meta_size); + } else { + frame_inc = io_cfg->planes[i].plane_stride * + io_cfg->planes[i].slice_height; + } + + if (wm_data->index < 3) + loop_size = wm_data->irq_subsample_period + 1; + else + loop_size = 1; + + /* WM Image address */ + for (k = 0; k < loop_size; k++) { + if (wm_data->en_ubwc) + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i] + + io_cfg->planes[i].meta_size + + k * frame_inc); + else + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i] + + wm_data->offset + k * frame_inc); + CAM_DBG(CAM_ISP, "WM %d image address 0x%x", + wm_data->index, reg_val_pair[j-1]); + } + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_inc, frame_inc); + CAM_DBG(CAM_ISP, "WM %d frame_inc %d", + wm_data->index, reg_val_pair[j-1]); + + + /* enable the WM */ + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->cfg, + wm_data->en_cfg); + + /* set initial configuration done */ + if (!wm_data->init_cfg_done) + wm_data->init_cfg_done = true; + } + + size = vfe_out_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_out_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_update_hfr(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_hfr; + struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_isp_port_hfr_config *hfr_cfg = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + update_hfr = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + update_hfr->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; + hfr_cfg = update_hfr->hfr_update; + + for (i = 0, j = 0; i < vfe_out_data->num_wm; 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 %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = vfe_out_data->wm_res[i]->res_priv; + + if (wm_data->index <= 2 && hfr_cfg->subsample_period > 3) { + CAM_ERR(CAM_ISP, + "RDI doesn't support irq subsample period %d", + hfr_cfg->subsample_period); + return -EINVAL; + } + + if ((wm_data->framedrop_pattern != + hfr_cfg->framedrop_pattern) || + !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_pattern, + hfr_cfg->framedrop_pattern); + wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern; + CAM_DBG(CAM_ISP, "WM %d framedrop pattern 0x%x", + wm_data->index, wm_data->framedrop_pattern); + } + + if (wm_data->framedrop_period != hfr_cfg->framedrop_period || + !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_period, + hfr_cfg->framedrop_period); + wm_data->framedrop_period = hfr_cfg->framedrop_period; + CAM_DBG(CAM_ISP, "WM %d framedrop period 0x%x", + wm_data->index, wm_data->framedrop_period); + } + + if (wm_data->irq_subsample_period != hfr_cfg->subsample_period + || !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_period, + hfr_cfg->subsample_period); + wm_data->irq_subsample_period = + hfr_cfg->subsample_period; + CAM_DBG(CAM_ISP, "WM %d irq subsample period 0x%x", + wm_data->index, wm_data->irq_subsample_period); + } + + if (wm_data->irq_subsample_pattern != hfr_cfg->subsample_pattern + || !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_pattern, + hfr_cfg->subsample_pattern); + wm_data->irq_subsample_pattern = + hfr_cfg->subsample_pattern; + CAM_DBG(CAM_ISP, "WM %d irq subsample pattern 0x%x", + wm_data->index, wm_data->irq_subsample_pattern); + } + + /* set initial configuration done */ + if (!wm_data->hfr_cfg_done) + wm_data->hfr_cfg_done = true; + } + + size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2); + + /* cdm util returns dwords, need to convert to bytes */ + if ((size * 4) > update_hfr->cmd.size) { + CAM_ERR(CAM_ISP, + "Failed! Buf size:%d insufficient, expected size:%d", + update_hfr->cmd.size, size); + return -ENOMEM; + } + + vfe_out_data->cdm_util_ops->cdm_write_regrandom( + update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + update_hfr->cmd.used_bytes = size * 4; + + return 0; +} + +static int cam_vfe_bus_update_ubwc_config(void *cmd_args) +{ + struct cam_isp_hw_get_cmd_update *update_ubwc; + struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_ubwc_plane_cfg_v1 *ubwc_plane_cfg = NULL; + uint32_t i; + int rc = 0; + + if (!cmd_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + update_ubwc = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + update_ubwc->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Invalid data"); + rc = -EINVAL; + goto end; + } + + ubwc_plane_cfg = update_ubwc->ubwc_update; + + for (i = 0; i < vfe_out_data->num_wm; i++) { + + wm_data = vfe_out_data->wm_res[i]->res_priv; + if (i > 0) + ubwc_plane_cfg++; + + if (!wm_data->hw_regs->ubwc_regs) { + CAM_ERR(CAM_ISP, + "No UBWC register to configure."); + rc = -EINVAL; + goto end; + } + + if (!wm_data->en_ubwc) { + CAM_ERR(CAM_ISP, "UBWC Disabled"); + rc = -EINVAL; + goto end; + } + + if (wm_data->packer_cfg != + ubwc_plane_cfg->packer_config || + !wm_data->init_cfg_done) { + wm_data->packer_cfg = ubwc_plane_cfg->packer_config; + wm_data->ubwc_updated = true; + } + + if ((!wm_data->is_dual) && ((wm_data->tile_cfg != + ubwc_plane_cfg->tile_config) + || !wm_data->init_cfg_done)) { + wm_data->tile_cfg = ubwc_plane_cfg->tile_config; + wm_data->ubwc_updated = true; + } + + if ((!wm_data->is_dual) && ((wm_data->h_init != + ubwc_plane_cfg->h_init) || + !wm_data->init_cfg_done)) { + wm_data->h_init = ubwc_plane_cfg->h_init; + wm_data->ubwc_updated = true; + } + + if (wm_data->v_init != ubwc_plane_cfg->v_init || + !wm_data->init_cfg_done) { + wm_data->v_init = ubwc_plane_cfg->v_init; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_meta_stride != + ubwc_plane_cfg->meta_stride || + !wm_data->init_cfg_done) { + wm_data->ubwc_meta_stride = ubwc_plane_cfg->meta_stride; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_mode_cfg_0 != + ubwc_plane_cfg->mode_config_0 || + !wm_data->init_cfg_done) { + wm_data->ubwc_mode_cfg_0 = + ubwc_plane_cfg->mode_config_0; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_mode_cfg_1 != + ubwc_plane_cfg->mode_config_1 || + !wm_data->init_cfg_done) { + wm_data->ubwc_mode_cfg_1 = + ubwc_plane_cfg->mode_config_1; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_meta_offset != + ubwc_plane_cfg->meta_offset || + !wm_data->init_cfg_done) { + wm_data->ubwc_meta_offset = ubwc_plane_cfg->meta_offset; + wm_data->ubwc_updated = true; + } + } + +end: + return rc; +} + +static int cam_vfe_bus_update_ubwc_config_v2(void *cmd_args) +{ + struct cam_isp_hw_get_cmd_update *update_ubwc; + struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_vfe_generic_ubwc_config *ubwc_generic_cfg = NULL; + struct cam_vfe_generic_ubwc_plane_config *ubwc_generic_plane_cfg = NULL; + uint32_t i; + int rc = 0; + + if (!cmd_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + update_ubwc = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + update_ubwc->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Invalid data"); + rc = -EINVAL; + goto end; + } + + ubwc_generic_cfg = update_ubwc->ubwc_config; + + for (i = 0; i < vfe_out_data->num_wm; i++) { + + wm_data = vfe_out_data->wm_res[i]->res_priv; + ubwc_generic_plane_cfg = &ubwc_generic_cfg->ubwc_plane_cfg[i]; + + if (!wm_data->hw_regs->ubwc_regs) { + CAM_ERR(CAM_ISP, + "No UBWC register to configure."); + rc = -EINVAL; + goto end; + } + + if (!wm_data->en_ubwc) { + CAM_ERR(CAM_ISP, "UBWC Disabled"); + rc = -EINVAL; + goto end; + } + + if (wm_data->packer_cfg != + ubwc_generic_plane_cfg->packer_config || + !wm_data->init_cfg_done) { + wm_data->packer_cfg = + ubwc_generic_plane_cfg->packer_config; + wm_data->ubwc_updated = true; + } + + if ((!wm_data->is_dual) && ((wm_data->tile_cfg != + ubwc_generic_plane_cfg->tile_config) + || !wm_data->init_cfg_done)) { + wm_data->tile_cfg = ubwc_generic_plane_cfg->tile_config; + wm_data->ubwc_updated = true; + } + + if ((!wm_data->is_dual) && ((wm_data->h_init != + ubwc_generic_plane_cfg->h_init) || + !wm_data->init_cfg_done)) { + wm_data->h_init = ubwc_generic_plane_cfg->h_init; + wm_data->ubwc_updated = true; + } + + if (wm_data->v_init != ubwc_generic_plane_cfg->v_init || + !wm_data->init_cfg_done) { + wm_data->v_init = ubwc_generic_plane_cfg->v_init; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_meta_stride != + ubwc_generic_plane_cfg->meta_stride || + !wm_data->init_cfg_done) { + wm_data->ubwc_meta_stride = + ubwc_generic_plane_cfg->meta_stride; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_mode_cfg_0 != + ubwc_generic_plane_cfg->mode_config_0 || + !wm_data->init_cfg_done) { + wm_data->ubwc_mode_cfg_0 = + ubwc_generic_plane_cfg->mode_config_0; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_mode_cfg_1 != + ubwc_generic_plane_cfg->mode_config_1 || + !wm_data->init_cfg_done) { + wm_data->ubwc_mode_cfg_1 = + ubwc_generic_plane_cfg->mode_config_1; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_meta_offset != + ubwc_generic_plane_cfg->meta_offset || + !wm_data->init_cfg_done) { + wm_data->ubwc_meta_offset = + ubwc_generic_plane_cfg->meta_offset; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_lossy_threshold_0 != + ubwc_generic_plane_cfg->lossy_threshold_0 || + !wm_data->init_cfg_done) { + wm_data->ubwc_lossy_threshold_0 = + ubwc_generic_plane_cfg->lossy_threshold_0; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_lossy_threshold_1 != + ubwc_generic_plane_cfg->lossy_threshold_1 || + !wm_data->init_cfg_done) { + wm_data->ubwc_lossy_threshold_1 = + ubwc_generic_plane_cfg->lossy_threshold_1; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_bandwidth_limit != + ubwc_generic_plane_cfg->bandwidth_limit || + !wm_data->init_cfg_done) { + wm_data->ubwc_bandwidth_limit = + ubwc_generic_plane_cfg->bandwidth_limit; + wm_data->ubwc_updated = true; + } + } + +end: + return rc; +} + + +static int cam_vfe_bus_update_stripe_cfg(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv; + struct cam_isp_hw_dual_isp_update_args *stripe_args; + struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_isp_dual_stripe_config *stripe_config; + uint32_t outport_id, ports_plane_idx, i; + + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + stripe_args = (struct cam_isp_hw_dual_isp_update_args *)cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + stripe_args->res->res_priv; + + if (!vfe_out_data) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + outport_id = stripe_args->res->res_id & 0xFF; + if (stripe_args->res->res_id < CAM_ISP_IFE_OUT_RES_BASE || + stripe_args->res->res_id >= CAM_ISP_IFE_OUT_RES_MAX) + return 0; + + ports_plane_idx = (stripe_args->split_id * + (stripe_args->dual_cfg->num_ports * CAM_PACKET_MAX_PLANES)) + + (outport_id * CAM_PACKET_MAX_PLANES); + for (i = 0; i < vfe_out_data->num_wm; i++) { + wm_data = vfe_out_data->wm_res[i]->res_priv; + stripe_config = (struct cam_isp_dual_stripe_config *) + &stripe_args->dual_cfg->stripes[ports_plane_idx + i]; + wm_data->width = stripe_config->width; + wm_data->offset = stripe_config->offset; + wm_data->tile_cfg = stripe_config->tileconfig; + CAM_DBG(CAM_ISP, "id:%x wm:%d width:0x%x offset:%x tilecfg:%x", + stripe_args->res->res_id, i, wm_data->width, + wm_data->offset, wm_data->tile_cfg); + } + + 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_out(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_out(hw_priv); +} + +static int cam_vfe_bus_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv; + uint32_t top_irq_reg_mask[2] = {0}; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + if (bus_priv->common_data.hw_init) + return 0; + + top_irq_reg_mask[0] = (1 << 9); + + 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_ver2_handle_irq, + NULL, + NULL, + NULL); + + if (bus_priv->irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ"); + bus_priv->irq_handle = 0; + 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 (bus_priv->error_irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS error IRQ %d", + bus_priv->error_irq_handle); + bus_priv->error_irq_handle = 0; + return -EFAULT; + } + } + + /*Set Debug Registers*/ + cam_io_w_mb(CAM_VFE_BUS_SET_DEBUG_REG, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->debug_status_cfg); + + /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */ + cam_io_w_mb(0x0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->addr_sync_frame_hdr); + + /* no clock gating at bus input */ + cam_io_w_mb(0xFFFFF, bus_priv->common_data.mem_base + 0x0000200C); + + /* BUS_WR_TEST_BUS_CTRL */ + cam_io_w_mb(0x0, bus_priv->common_data.mem_base + 0x0000211C); + + /* if addr_no_sync has default value then config the addr no sync reg */ + cam_io_w_mb(CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL, + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->addr_sync_no_sync); + + bus_priv->common_data.hw_init = true; + + return 0; +} + +static int cam_vfe_bus_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv; + int rc = 0, i; + unsigned long flags; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Error: Invalid args"); + return -EINVAL; + } + + if (!bus_priv->common_data.hw_init) + return 0; + + if (bus_priv->error_irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + 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); + bus_priv->irq_handle = 0; + } + + spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + list_add_tail(&bus_priv->common_data.evt_payload[i].list, + &bus_priv->common_data.free_payload_list); + } + bus_priv->common_data.hw_init = false; + spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); + + 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; + struct cam_vfe_bus_ver2_priv *bus_priv; + + 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: + rc = cam_vfe_bus_update_wm(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + rc = cam_vfe_bus_update_hfr(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = cam_vfe_bus_get_secure_mode(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + rc = cam_vfe_bus_update_stripe_cfg(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + if (bus_priv->error_irq_handle) { + CAM_DBG(CAM_ISP, "Mask off bus error irq handler"); + rc = cam_irq_controller_unsubscribe_irq( + bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + bus_priv->error_irq_handle = 0; + } + break; + case CAM_ISP_HW_CMD_UBWC_UPDATE: + rc = cam_vfe_bus_update_ubwc_config(cmd_args); + break; + case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: + rc = cam_vfe_bus_update_ubwc_config_v2(cmd_args); + break; + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", + cmd_type); + break; + } + + return rc; +} + +int cam_vfe_bus_ver2_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_ver2_priv *bus_priv = NULL; + struct cam_vfe_bus *vfe_bus_local; + struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info; + + CAM_DBG(CAM_ISP, "Enter"); + + 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_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_ver2_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 = ver2_hw_info->num_client; + bus_priv->num_out = ver2_hw_info->num_out; + 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 = &ver2_hw_info->common_reg; + bus_priv->common_data.addr_no_sync = + CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL; + bus_priv->common_data.hw_init = false; + + mutex_init(&bus_priv->common_data.bus_mutex); + + rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base, + &ver2_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; + } + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info, + &bus_priv->bus_client[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Init WM failed rc=%d", rc); + goto deinit_wm; + } + } + + for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) { + rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info, + &bus_priv->comp_grp[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Init Comp Grp failed rc=%d", rc); + goto deinit_comp_grp; + } + } + + for (i = 0; i < bus_priv->num_out; i++) { + rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, + bus_hw_info); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc); + goto deinit_vfe_out; + } + } + + spin_lock_init(&bus_priv->common_data.spin_lock); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + list_add_tail(&bus_priv->common_data.evt_payload[i].list, + &bus_priv->common_data.free_payload_list); + } + + vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out; + vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out; + 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_ver2_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; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; + +deinit_vfe_out: + if (i < 0) + i = CAM_VFE_BUS_VER2_VFE_OUT_MAX; + for (--i; i >= 0; i--) + cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]); + +deinit_comp_grp: + if (i < 0) + i = CAM_VFE_BUS_VER2_COMP_GRP_MAX; + for (--i; i >= 0; i--) + cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]); + +deinit_wm: + if (i < 0) + i = bus_priv->num_client; + for (--i; i >= 0; i--) + cam_vfe_bus_deinit_wm_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_ver2_deinit( + struct cam_vfe_bus **vfe_bus) +{ + int i, rc = 0; + struct cam_vfe_bus_ver2_priv *bus_priv = NULL; + struct cam_vfe_bus *vfe_bus_local; + unsigned long flags; + + 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; + } + + spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + bus_priv->common_data.hw_init = false; + spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Deinit WM failed rc=%d", rc); + } + + for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) { + rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Deinit Comp Grp failed rc=%d", rc); + } + + for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) { + rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Deinit VFE Out failed rc=%d", rc); + } + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + 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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h new file mode 100644 index 000000000000..cac3adf65a93 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_BUS_VER2_H_ +#define _CAM_VFE_BUS_VER2_H_ + +#include "cam_irq_controller.h" +#include "cam_vfe_bus.h" + +#define CAM_VFE_BUS_VER2_MAX_CLIENTS 24 + +enum cam_vfe_bus_ver2_vfe_core_id { + CAM_VFE_BUS_VER2_VFE_CORE_0, + CAM_VFE_BUS_VER2_VFE_CORE_1, + CAM_VFE_BUS_VER2_VFE_CORE_MAX, +}; + +enum cam_vfe_bus_ver2_comp_grp_type { + CAM_VFE_BUS_VER2_COMP_GRP_0, + CAM_VFE_BUS_VER2_COMP_GRP_1, + CAM_VFE_BUS_VER2_COMP_GRP_2, + CAM_VFE_BUS_VER2_COMP_GRP_3, + CAM_VFE_BUS_VER2_COMP_GRP_4, + CAM_VFE_BUS_VER2_COMP_GRP_5, + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0, + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1, + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2, + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3, + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4, + CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5, + CAM_VFE_BUS_VER2_COMP_GRP_MAX, +}; + +enum cam_vfe_bus_ver2_vfe_out_type { + CAM_VFE_BUS_VER2_VFE_OUT_RDI0, + CAM_VFE_BUS_VER2_VFE_OUT_RDI1, + CAM_VFE_BUS_VER2_VFE_OUT_RDI2, + CAM_VFE_BUS_VER2_VFE_OUT_RDI3, + CAM_VFE_BUS_VER2_VFE_OUT_FULL, + CAM_VFE_BUS_VER2_VFE_OUT_DS4, + CAM_VFE_BUS_VER2_VFE_OUT_DS16, + CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP, + CAM_VFE_BUS_VER2_VFE_OUT_FD, + CAM_VFE_BUS_VER2_VFE_OUT_PDAF, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS, + CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST, + CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, + CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP, + CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP, + CAM_VFE_BUS_VER2_VFE_OUT_2PD, + CAM_VFE_BUS_VER2_VFE_OUT_MAX, +}; + +/* + * struct cam_vfe_bus_ver2_reg_offset_common: + * + * @Brief: Common registers across all BUS Clients + */ +struct cam_vfe_bus_ver2_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 dual_master_comp_cfg; + struct cam_irq_controller_reg_info irq_reg_info; + uint32_t comp_error_status; + uint32_t comp_ovrwr_status; + uint32_t dual_comp_error_status; + uint32_t dual_comp_ovrwr_status; + uint32_t addr_sync_cfg; + uint32_t addr_sync_frame_hdr; + uint32_t addr_sync_no_sync; + uint32_t debug_status_cfg; + uint32_t debug_status_0; +}; + +/* + * struct cam_vfe_bus_ver2_reg_offset_ubwc_client: + * + * @Brief: UBWC register offsets for BUS Clients + */ +struct cam_vfe_bus_ver2_reg_offset_ubwc_client { + uint32_t tile_cfg; + uint32_t h_init; + uint32_t v_init; + uint32_t meta_addr; + uint32_t meta_offset; + uint32_t meta_stride; + uint32_t mode_cfg_0; + uint32_t bw_limit; +}; + +/* + * struct cam_vfe_bus_ver2_reg_offset_ubwc_client: + * + * @Brief: UBWC register offsets for BUS Clients + */ +struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client { + uint32_t tile_cfg; + uint32_t h_init; + uint32_t v_init; + uint32_t meta_addr; + uint32_t meta_offset; + uint32_t meta_stride; + uint32_t mode_cfg_0; + uint32_t mode_cfg_1; + uint32_t bw_limit; +}; + + +/* + * struct cam_vfe_bus_ver2_reg_offset_bus_client: + * + * @Brief: Register offsets for BUS Clients + */ +struct cam_vfe_bus_ver2_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 packer_cfg; + uint32_t stride; + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + uint32_t frame_inc; + uint32_t burst_limit; + void *ubwc_regs; +}; + +/* + * struct cam_vfe_bus_ver2_reg_offset_comp_grp: + * + * @Brief: Register offsets for Composite Group registers + * comp_mask: Comp group register address + * addr_sync_mask:Address sync group register address + */ +struct cam_vfe_bus_ver2_reg_offset_comp_grp { + uint32_t comp_mask; + uint32_t addr_sync_mask; +}; + +/* + * struct cam_vfe_bus_ver2_vfe_out_hw_info: + * + * @Brief: HW capability of VFE Bus Client + */ +struct cam_vfe_bus_ver2_vfe_out_hw_info { + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_type; + uint32_t max_width; + uint32_t max_height; +}; + +/* + * struct cam_vfe_bus_ver2_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_ver2_hw_info { + struct cam_vfe_bus_ver2_reg_offset_common common_reg; + uint32_t num_client; + struct cam_vfe_bus_ver2_reg_offset_bus_client + bus_client_reg[CAM_VFE_BUS_VER2_MAX_CLIENTS]; + struct cam_vfe_bus_ver2_reg_offset_comp_grp + comp_grp_reg[CAM_VFE_BUS_VER2_COMP_GRP_MAX]; + uint32_t num_out; + struct cam_vfe_bus_ver2_vfe_out_hw_info + vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; +}; + +/* + * cam_vfe_bus_ver2_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_ver2_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_ver2_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @vfe_bus: Pointer to vfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_bus_ver2_deinit(struct cam_vfe_bus **vfe_bus); + +#endif /* _CAM_VFE_BUS_VER2_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c new file mode 100644 index 000000000000..f0dea326a8b0 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -0,0 +1,3924 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#include +#include +#include +#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_ver3.h" +#include "cam_vfe_core.h" +#include "cam_vfe_soc.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + +static const char drv_name[] = "vfe_bus"; + +#define CAM_VFE_BUS_VER3_IRQ_REG0 0 +#define CAM_VFE_BUS_VER3_IRQ_REG1 1 +#define CAM_VFE_BUS_VER3_IRQ_MAX 2 + +#define CAM_VFE_BUS_VER3_PAYLOAD_MAX 256 + +#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFFFF +#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFFFF +#define CAM_VFE_BUS_VER3_INTRA_CLIENT_MASK 0x3 + +#define MAX_BUF_UPDATE_REG_NUM \ + ((sizeof(struct cam_vfe_bus_ver3_reg_offset_bus_client) + \ + sizeof(struct cam_vfe_bus_ver3_reg_offset_ubwc_client))/4) +#define MAX_REG_VAL_PAIR_SIZE \ + (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) + +static uint32_t bus_error_irq_mask[2] = { + 0xC0000000, + 0x00000000, +}; + +enum cam_vfe_bus_ver3_packer_format { + PACKER_FMT_VER3_PLAIN_128, + PACKER_FMT_VER3_PLAIN_8, + PACKER_FMT_VER3_PLAIN_8_ODD_EVEN, + PACKER_FMT_VER3_PLAIN_8_LSB_MSB_10, + PACKER_FMT_VER3_PLAIN_8_LSB_MSB_10_ODD_EVEN, + PACKER_FMT_VER3_PLAIN_16_10BPP, + PACKER_FMT_VER3_PLAIN_16_12BPP, + PACKER_FMT_VER3_PLAIN_16_14BPP, + PACKER_FMT_VER3_PLAIN_16_16BPP, + PACKER_FMT_VER3_PLAIN_32, + PACKER_FMT_VER3_PLAIN_64, + PACKER_FMT_VER3_TP_10, + PACKER_FMT_VER3_MAX, +}; + +struct cam_vfe_bus_ver3_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_ver3_reg_offset_common *common_reg; + uint32_t io_buf_update[ + MAX_REG_VAL_PAIR_SIZE]; + + struct cam_vfe_bus_irq_evt_payload evt_payload[ + CAM_VFE_BUS_VER3_PAYLOAD_MAX]; + 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 addr_no_sync; + uint32_t comp_done_shift; + bool is_lite; + bool hw_init; + cam_hw_mgr_event_cb_func event_cb; + int rup_irq_handle[CAM_VFE_BUS_VER3_SRC_GRP_MAX]; +}; + +struct cam_vfe_bus_ver3_wm_resource_data { + uint32_t index; + struct cam_vfe_bus_ver3_common_data *common_data; + struct cam_vfe_bus_ver3_reg_offset_bus_client *hw_regs; + + bool init_cfg_done; + bool hfr_cfg_done; + + uint32_t offset; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; + enum cam_vfe_bus_ver3_packer_format pack_fmt; + + uint32_t burst_len; + + uint32_t en_ubwc; + bool ubwc_updated; + uint32_t packer_cfg; + uint32_t h_init; + uint32_t ubwc_meta_addr; + uint32_t ubwc_meta_cfg; + uint32_t ubwc_mode_cfg; + uint32_t ubwc_stats_ctrl; + uint32_t ubwc_ctrl_2; + + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + + uint32_t en_cfg; + uint32_t is_dual; + + uint32_t ubwc_lossy_threshold_0; + uint32_t ubwc_lossy_threshold_1; + uint32_t ubwc_offset_lossy_variance; + uint32_t ubwc_bandwidth_limit; +}; + +struct cam_vfe_bus_ver3_comp_grp_data { + enum cam_vfe_bus_ver3_comp_grp_type comp_grp_type; + struct cam_vfe_bus_ver3_common_data *common_data; + + uint32_t is_master; + uint32_t is_dual; + uint32_t dual_slave_core; + uint32_t intra_client_mask; + uint32_t addr_sync_mode; + uint32_t composite_mask; + + uint32_t acquire_dev_cnt; + uint32_t irq_trigger_cnt; + uint32_t ubwc_static_ctrl; +}; + +struct cam_vfe_bus_ver3_vfe_out_data { + uint32_t out_type; + uint32_t source_group; + struct cam_vfe_bus_ver3_common_data *common_data; + + uint32_t num_wm; + struct cam_isp_resource_node *wm_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_out_list; + + uint32_t is_master; + uint32_t is_dual; + + uint32_t format; + uint32_t max_width; + uint32_t max_height; + struct cam_cdm_utils_ops *cdm_util_ops; + uint32_t secure_mode; + void *priv; +}; + +struct cam_vfe_bus_ver3_priv { + struct cam_vfe_bus_ver3_common_data common_data; + uint32_t num_client; + uint32_t num_out; + uint32_t top_irq_shift; + + struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER3_MAX_CLIENTS]; + struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER3_COMP_GRP_MAX]; + struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; + + struct list_head free_comp_grp; + struct list_head used_comp_grp; + + int irq_handle; + int error_irq_handle; + void *tasklet_info; +}; + +static int cam_vfe_bus_ver3_process_cmd( + struct cam_isp_resource_node *priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size); + +static int cam_vfe_bus_ver3_get_evt_payload( + struct cam_vfe_bus_ver3_common_data *common_data, + struct cam_vfe_bus_irq_evt_payload **evt_payload) +{ + int rc; + + spin_lock(&common_data->spin_lock); + + if (!common_data->hw_init) { + *evt_payload = NULL; + CAM_ERR_RATE_LIMIT(CAM_ISP, "VFE:%d Bus uninitialized", + common_data->core_index); + rc = -EPERM; + goto done; + } + + if (list_empty(&common_data->free_payload_list)) { + *evt_payload = NULL; + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free BUS event payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&common_data->free_payload_list, + struct cam_vfe_bus_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + rc = 0; +done: + spin_unlock(&common_data->spin_lock); + return rc; +} + +static int cam_vfe_bus_ver3_put_evt_payload( + struct cam_vfe_bus_ver3_common_data *common_data, + struct cam_vfe_bus_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!common_data) { + CAM_ERR(CAM_ISP, "Invalid param common_data NULL"); + return -EINVAL; + } + + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&common_data->spin_lock, flags); + if (common_data->hw_init) + list_add_tail(&(*evt_payload)->list, + &common_data->free_payload_list); + spin_unlock_irqrestore(&common_data->spin_lock, flags); + + *evt_payload = NULL; + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_bus_ver3_get_intra_client_mask( + enum cam_vfe_bus_ver3_vfe_core_id dual_slave_core, + enum cam_vfe_bus_ver3_vfe_core_id current_core, + uint32_t *intra_client_mask) +{ + int rc = 0; + uint32_t version_based_intra_client_mask = 0x1; + + *intra_client_mask = 0; + + if (dual_slave_core == current_core) { + CAM_ERR(CAM_ISP, + "Invalid params. Same core as Master and Slave"); + return -EINVAL; + } + + switch (current_core) { + case CAM_VFE_BUS_VER3_VFE_CORE_0: + switch (dual_slave_core) { + case CAM_VFE_BUS_VER3_VFE_CORE_1: + *intra_client_mask = version_based_intra_client_mask; + break; + default: + CAM_ERR(CAM_ISP, "Invalid value for slave core %u", + dual_slave_core); + rc = -EINVAL; + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_CORE_1: + switch (dual_slave_core) { + case CAM_VFE_BUS_VER3_VFE_CORE_0: + *intra_client_mask = version_based_intra_client_mask; + break; + default: + CAM_ERR(CAM_ISP, "Invalid value for slave core %u", + dual_slave_core); + rc = -EINVAL; + break; + } + break; + default: + CAM_ERR(CAM_ISP, + "Invalid value for master core %u", current_core); + rc = -EINVAL; + break; + } + + return rc; +} + +static bool cam_vfe_bus_ver3_can_be_secure(uint32_t out_type) +{ + switch (out_type) { + case CAM_VFE_BUS_VER3_VFE_OUT_FULL: + case CAM_VFE_BUS_VER3_VFE_OUT_DS4: + case CAM_VFE_BUS_VER3_VFE_OUT_DS16: + case CAM_VFE_BUS_VER3_VFE_OUT_FD: + case CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP: + case CAM_VFE_BUS_VER3_VFE_OUT_RDI0: + case CAM_VFE_BUS_VER3_VFE_OUT_RDI1: + case CAM_VFE_BUS_VER3_VFE_OUT_RDI2: + case CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP: + case CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP: + case CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP: + return true; + + case CAM_VFE_BUS_VER3_VFE_OUT_2PD: + case CAM_VFE_BUS_VER3_VFE_OUT_LCR: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST: + default: + return false; + } +} + +static enum cam_vfe_bus_ver3_vfe_out_type + cam_vfe_bus_ver3_get_out_res_id(uint32_t res_type) +{ + switch (res_type) { + case CAM_ISP_IFE_OUT_RES_FULL: + return CAM_VFE_BUS_VER3_VFE_OUT_FULL; + case CAM_ISP_IFE_OUT_RES_DS4: + return CAM_VFE_BUS_VER3_VFE_OUT_DS4; + case CAM_ISP_IFE_OUT_RES_DS16: + return CAM_VFE_BUS_VER3_VFE_OUT_DS16; + case CAM_ISP_IFE_OUT_RES_FD: + return CAM_VFE_BUS_VER3_VFE_OUT_FD; + case CAM_ISP_IFE_OUT_RES_RAW_DUMP: + return CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP; + case CAM_ISP_IFE_OUT_RES_2PD: + return CAM_VFE_BUS_VER3_VFE_OUT_2PD; + case CAM_ISP_IFE_OUT_RES_RDI_0: + return CAM_VFE_BUS_VER3_VFE_OUT_RDI0; + case CAM_ISP_IFE_OUT_RES_RDI_1: + return CAM_VFE_BUS_VER3_VFE_OUT_RDI1; + case CAM_ISP_IFE_OUT_RES_RDI_2: + return CAM_VFE_BUS_VER3_VFE_OUT_RDI2; + case CAM_ISP_IFE_OUT_RES_RDI_3: + return CAM_VFE_BUS_VER3_VFE_OUT_RDI3; + case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE; + case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST; + case CAM_ISP_IFE_OUT_RES_STATS_TL_BG: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG; + case CAM_ISP_IFE_OUT_RES_STATS_BF: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF; + case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG; + case CAM_ISP_IFE_OUT_RES_STATS_BHIST: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST; + case CAM_ISP_IFE_OUT_RES_STATS_RS: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS; + case CAM_ISP_IFE_OUT_RES_STATS_CS: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS; + case CAM_ISP_IFE_OUT_RES_STATS_IHIST: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST; + case CAM_ISP_IFE_OUT_RES_FULL_DISP: + return CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP; + case CAM_ISP_IFE_OUT_RES_DS4_DISP: + return CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP; + case CAM_ISP_IFE_OUT_RES_DS16_DISP: + return CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP; + case CAM_ISP_IFE_OUT_RES_LCR: + return CAM_VFE_BUS_VER3_VFE_OUT_LCR; + default: + return CAM_VFE_BUS_VER3_VFE_OUT_MAX; + } +} + +static int cam_vfe_bus_ver3_get_num_wm( + enum cam_vfe_bus_ver3_vfe_out_type res_type, + uint32_t format) +{ + switch (res_type) { + case CAM_VFE_BUS_VER3_VFE_OUT_RDI0: + case CAM_VFE_BUS_VER3_VFE_OUT_RDI1: + case CAM_VFE_BUS_VER3_VFE_OUT_RDI2: + case CAM_VFE_BUS_VER3_VFE_OUT_RDI3: + switch (format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_DPCM_10_6_10: + case CAM_FORMAT_DPCM_10_8_10: + case CAM_FORMAT_DPCM_12_6_12: + case CAM_FORMAT_DPCM_12_8_12: + case CAM_FORMAT_DPCM_14_8_14: + case CAM_FORMAT_DPCM_14_10_14: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN32_20: + case CAM_FORMAT_PLAIN128: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_FULL: + case CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP: + switch (format) { + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_TP10: + case CAM_FORMAT_UBWC_NV12: + case CAM_FORMAT_UBWC_NV12_4R: + case CAM_FORMAT_UBWC_TP10: + case CAM_FORMAT_UBWC_P010: + case CAM_FORMAT_PLAIN16_10: + return 2; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_FD: + switch (format) { + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_TP10: + case CAM_FORMAT_PLAIN16_10: + return 2; + case CAM_FORMAT_Y_ONLY: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_DS4: + case CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP: + case CAM_VFE_BUS_VER3_VFE_OUT_DS16: + case CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP: + switch (format) { + case CAM_FORMAT_PD8: + case CAM_FORMAT_PD10: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP: + switch (format) { + case CAM_FORMAT_ARGB_14: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_2PD: + switch (format) { + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN64: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS: + switch (format) { + case CAM_FORMAT_PLAIN64: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS: + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST: + switch (format) { + case CAM_FORMAT_PLAIN16_16: + return 1; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_LCR: + return 1; + default: + break; + } + + CAM_ERR(CAM_ISP, "Unsupported format %u for out_type:0x%X", + format, res_type); + + return -EINVAL; +} + +static int cam_vfe_bus_ver3_get_wm_idx( + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, + enum cam_vfe_bus_plane_type plane, + bool is_lite) +{ + int wm_idx = -1; + + switch (vfe_out_res_id) { + case CAM_VFE_BUS_VER3_VFE_OUT_RDI0: + switch (plane) { + case PLANE_Y: + if (is_lite) + wm_idx = 0; + else + wm_idx = 23; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_RDI1: + switch (plane) { + case PLANE_Y: + if (is_lite) + wm_idx = 1; + else + wm_idx = 24; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_RDI2: + switch (plane) { + case PLANE_Y: + if (is_lite) + wm_idx = 2; + else + wm_idx = 25; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_RDI3: + switch (plane) { + case PLANE_Y: + wm_idx = 3; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_FULL: + switch (plane) { + case PLANE_Y: + wm_idx = 0; + break; + case PLANE_C: + wm_idx = 1; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_DS4: + switch (plane) { + case PLANE_Y: + wm_idx = 2; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_DS16: + switch (plane) { + case PLANE_Y: + wm_idx = 3; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_FD: + switch (plane) { + case PLANE_Y: + wm_idx = 8; + break; + case PLANE_C: + wm_idx = 9; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP: + switch (plane) { + case PLANE_Y: + wm_idx = 10; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_2PD: + switch (plane) { + case PLANE_Y: + wm_idx = 21; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE: + switch (plane) { + case PLANE_Y: + wm_idx = 12; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 13; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG: + switch (plane) { + case PLANE_Y: + wm_idx = 14; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF: + switch (plane) { + case PLANE_Y: + wm_idx = 20; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG: + switch (plane) { + case PLANE_Y: + wm_idx = 15; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 16; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS: + switch (plane) { + case PLANE_Y: + wm_idx = 17; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS: + switch (plane) { + case PLANE_Y: + wm_idx = 18; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 19; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP: + switch (plane) { + case PLANE_Y: + wm_idx = 4; + break; + case PLANE_C: + wm_idx = 5; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP: + switch (plane) { + case PLANE_Y: + wm_idx = 6; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP: + switch (plane) { + case PLANE_Y: + wm_idx = 7; + break; + default: + break; + } + break; + case CAM_VFE_BUS_VER3_VFE_OUT_LCR: + switch (plane) { + case PLANE_Y: + wm_idx = 22; + break; + default: + break; + } + default: + break; + } + + return wm_idx; +} + +static int cam_vfe_bus_ver3_get_comp_vfe_out_res_id_list( + uint32_t comp_mask, uint32_t *out_list, int *num_out, bool is_lite) +{ + int count = 0; + + if (is_lite) + goto vfe_lite; + + if (comp_mask & 0x3) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL; + + if (comp_mask & 0x4) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4; + + if (comp_mask & 0x8) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16; + + if (comp_mask & 0x30) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL_DISP; + + if (comp_mask & 0x40) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4_DISP; + + if (comp_mask & 0x80) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16_DISP; + + if (comp_mask & 0x300) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FD; + + if (comp_mask & 0x400) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RAW_DUMP; + + if (comp_mask & 0x1000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_HDR_BE; + + if (comp_mask & 0x2000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST; + + if (comp_mask & 0x4000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_TL_BG; + + if (comp_mask & 0x8000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_AWB_BG; + + if (comp_mask & 0x10000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BHIST; + + if (comp_mask & 0x20000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_RS; + + if (comp_mask & 0x40000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_CS; + + if (comp_mask & 0x80000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_IHIST; + + if (comp_mask & 0x100000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BF; + + if (comp_mask & 0x200000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_2PD; + + if (comp_mask & 0x400000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_LCR; + + if (comp_mask & 0x800000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_0; + + if (comp_mask & 0x1000000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_1; + + if (comp_mask & 0x2000000) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_2; + + *num_out = count; + return 0; + +vfe_lite: + if (comp_mask & 0x1) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_0; + + if (comp_mask & 0x2) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_1; + + if (comp_mask & 0x4) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_2; + + if (comp_mask & 0x8) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_3; + + *num_out = count; + return 0; +} + +static enum cam_vfe_bus_ver3_packer_format + cam_vfe_bus_ver3_get_packer_fmt(uint32_t out_fmt, int wm_index) +{ + switch (out_fmt) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PD8: + return PACKER_FMT_VER3_PLAIN_128; + case CAM_FORMAT_PLAIN8: + return PACKER_FMT_VER3_PLAIN_8; + case CAM_FORMAT_NV21: + if ((wm_index == 1) || (wm_index == 3) || (wm_index == 5)) + return PACKER_FMT_VER3_PLAIN_8_LSB_MSB_10_ODD_EVEN; + case CAM_FORMAT_NV12: + case CAM_FORMAT_UBWC_NV12: + case CAM_FORMAT_UBWC_NV12_4R: + case CAM_FORMAT_Y_ONLY: + return PACKER_FMT_VER3_PLAIN_8_LSB_MSB_10; + case CAM_FORMAT_PLAIN16_10: + return PACKER_FMT_VER3_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return PACKER_FMT_VER3_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return PACKER_FMT_VER3_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN16_16: + return PACKER_FMT_VER3_PLAIN_16_16BPP; + case CAM_FORMAT_PLAIN32: + case CAM_FORMAT_ARGB: + return PACKER_FMT_VER3_PLAIN_32; + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_ARGB_16: + case CAM_FORMAT_PD10: + return PACKER_FMT_VER3_PLAIN_64; + case CAM_FORMAT_UBWC_TP10: + case CAM_FORMAT_TP10: + return PACKER_FMT_VER3_TP_10; + default: + return PACKER_FMT_VER3_MAX; + } +} + +static int cam_vfe_bus_ver3_handle_rup_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_irq_evt_payload *evt_payload; + + vfe_out = th_payload->handler_priv; + if (!vfe_out) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + + rsrc_data = vfe_out->res_priv; + + CAM_DBG(CAM_ISP, "VFE:%d Bus IRQ status_0: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0]); + + rc = cam_vfe_bus_ver3_get_evt_payload(rsrc_data->common_data, + &evt_payload); + + if (rc) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "VFE:%d Bus IRQ status_0: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0]); + return rc; + } + + evt_payload->core_index = rsrc_data->common_data->core_index; + evt_payload->evt_id = evt_id; + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_vfe_bus_ver3_handle_rup_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + int ret = CAM_VFE_IRQ_STATUS_ERR; + struct cam_vfe_bus_irq_evt_payload *payload; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_isp_hw_event_info evt_info; + uint32_t irq_status; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, "Invalid params"); + return ret; + } + + payload = evt_payload_priv; + vfe_out = handler_priv; + rsrc_data = vfe_out->res_priv; + + if (!rsrc_data->common_data->event_cb) { + CAM_ERR(CAM_ISP, "Callback to HW MGR not found"); + return ret; + } + + irq_status = payload->irq_reg_val[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; + + evt_info.hw_idx = rsrc_data->common_data->core_index; + evt_info.res_type = CAM_ISP_RESOURCE_VFE_IN; + + if (!rsrc_data->common_data->is_lite) { + if (irq_status & 0x1) { + CAM_DBG(CAM_ISP, "VFE:%d Received CAMIF RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_CAMIF; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x2) { + CAM_DBG(CAM_ISP, "VFE:%d Received PDLIB RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_PDLIB; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x4) + CAM_DBG(CAM_ISP, "VFE:%d Received LCR RUP", + evt_info.hw_idx); + + if (irq_status & 0x8) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI0 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI0; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x10) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI1 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI1; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x20) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI2 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI2; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + } else { + if (irq_status & 0x1) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI0 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI0; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x2) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI1 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI1; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x4) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI2 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI2; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + + if (irq_status & 0x8) { + CAM_DBG(CAM_ISP, "VFE:%d Received RDI3 RUP", + evt_info.hw_idx); + evt_info.res_id = CAM_ISP_HW_VFE_IN_RDI3; + rsrc_data->common_data->event_cb( + rsrc_data->priv, CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + } + } + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + + CAM_DBG(CAM_ISP, + "VFE:%d Bus RUP IRQ status_0:0x%X rc:%d", + evt_info.hw_idx, CAM_ISP_HW_EVENT_REG_UPDATE, irq_status, ret); + + cam_vfe_bus_ver3_put_evt_payload(rsrc_data->common_data, &payload); + + return ret; +} + +static int cam_vfe_bus_ver3_acquire_wm( + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_isp_out_port_generic_info *out_port_info, + void *tasklet, + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, + enum cam_vfe_bus_plane_type plane, + struct cam_isp_resource_node **wm_res, + uint32_t *client_done_mask, + uint32_t is_dual, + enum cam_vfe_bus_ver3_comp_grp_type *comp_grp_id) +{ + int32_t wm_idx = 0; + struct cam_isp_resource_node *wm_res_local = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data = NULL; + + *wm_res = NULL; + + /* VFE OUT to WM is fixed. */ + wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, plane, + ver3_bus_priv->common_data.is_lite); + if (wm_idx < 0 || wm_idx >= ver3_bus_priv->num_client || + plane > PLANE_C) { + CAM_ERR(CAM_ISP, + "Unsupported VFE out_type:0x%X plane:%d wm_idx:%d max_idx:%d", + vfe_out_res_id, plane, wm_idx, + ver3_bus_priv->num_client - 1); + return -EINVAL; + } + + wm_res_local = &ver3_bus_priv->bus_client[wm_idx]; + if (wm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "WM:%d not available state:%d", + wm_idx, wm_res_local->res_state); + return -EALREADY; + } + wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + wm_res_local->tasklet_info = tasklet; + + rsrc_data = wm_res_local->res_priv; + rsrc_data->format = out_port_info->format; + rsrc_data->pack_fmt = cam_vfe_bus_ver3_get_packer_fmt(rsrc_data->format, + wm_idx); + + rsrc_data->width = out_port_info->width; + rsrc_data->height = out_port_info->height; + rsrc_data->is_dual = is_dual; + /* Set WM offset value to default */ + rsrc_data->offset = 0; + CAM_DBG(CAM_ISP, "WM:%d width %d height %d", rsrc_data->index, + rsrc_data->width, rsrc_data->height); + + if (ver3_bus_priv->common_data.is_lite) + goto rdi_config; + + if (rsrc_data->index > 22) { +rdi_config: + /* WM 23-25 refers to RDI 0/ RDI 1/RDI 2 */ + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_PLAIN128: + rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->pack_fmt = 0x0; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + case CAM_FORMAT_PLAIN8: + rsrc_data->en_cfg = 0x1; + rsrc_data->pack_fmt = 0x1; + rsrc_data->stride = rsrc_data->width * 2; + break; + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN32_20: + rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->pack_fmt = 0x0; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + case CAM_FORMAT_PLAIN64: + rsrc_data->en_cfg = 0x1; + rsrc_data->pack_fmt = 0xA; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported RDI format %d", + rsrc_data->format); + return -EINVAL; + } + } else if ((rsrc_data->index < 2) || + (rsrc_data->index == 8) || (rsrc_data->index == 9) || + (rsrc_data->index == 4) || (rsrc_data->index == 5)) { + /* + * WM 0-1 FULL_OUT, WM 8-9 FD_OUT, + * WM 4-5 FULL_DISP + */ + switch (rsrc_data->format) { + case CAM_FORMAT_UBWC_NV12_4R: + rsrc_data->en_ubwc = 1; + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_UBWC_NV12: + rsrc_data->en_ubwc = 1; + /* Fall through for NV12 */ + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + case CAM_FORMAT_Y_ONLY: + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_UBWC_TP10: + rsrc_data->en_ubwc = 1; + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_TP10: + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + case CAM_FORMAT_PLAIN16_10: + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d", + rsrc_data->format); + return -EINVAL; + } + rsrc_data->en_cfg = 0x1; + } else if (rsrc_data->index == 20) { + /* WM 20 stats BAF */ + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } else if (rsrc_data->index > 11 && rsrc_data->index < 20) { + /* WM 12-19 stats */ + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } else if (rsrc_data->index == 21) { + /* WM 21 PD */ + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } else if (rsrc_data->index == 10) { + /* WM 10 Raw dump */ + rsrc_data->stride = rsrc_data->width; + rsrc_data->en_cfg = 0x1; + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x10; + } else if (rsrc_data->index == 22) { + switch (rsrc_data->format) { + case CAM_FORMAT_PLAIN16_16: + rsrc_data->stride = ALIGNUP(rsrc_data->width * 2, 8); + rsrc_data->en_cfg = 0x1; + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x10; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d", + rsrc_data->format); + return -EINVAL; + } + } else if ((rsrc_data->index == 2) || (rsrc_data->index == 3) || + (rsrc_data->index == 6) || (rsrc_data->index == 7)) { + /* Write master 2-3 and 6-7 DS ports */ + + rsrc_data->height = rsrc_data->height / 2; + rsrc_data->width = rsrc_data->width / 2; + rsrc_data->en_cfg = 0x1; + + } else { + CAM_ERR(CAM_ISP, "Invalid WM:%d requested", rsrc_data->index); + return -EINVAL; + } + + *wm_res = wm_res_local; + *comp_grp_id = rsrc_data->hw_regs->comp_group; + *client_done_mask |= (1 << wm_idx); + + CAM_DBG(CAM_ISP, + "VFE:%d WM:%d processed width:%d height:%d format:0x%X en_ubwc:%d", + rsrc_data->common_data->core_index, rsrc_data->index, + rsrc_data->width, rsrc_data->height, rsrc_data->format, + rsrc_data->en_ubwc); + return 0; +} + +static int cam_vfe_bus_ver3_release_wm(void *bus_priv, + struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data = + wm_res->res_priv; + + rsrc_data->offset = 0; + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 0; + rsrc_data->format = 0; + rsrc_data->pack_fmt = 0; + rsrc_data->burst_len = 0; + rsrc_data->irq_subsample_period = 0; + rsrc_data->irq_subsample_pattern = 0; + rsrc_data->framedrop_period = 0; + rsrc_data->framedrop_pattern = 0; + rsrc_data->packer_cfg = 0; + rsrc_data->en_ubwc = 0; + rsrc_data->h_init = 0; + rsrc_data->ubwc_meta_addr = 0; + rsrc_data->ubwc_meta_cfg = 0; + rsrc_data->ubwc_mode_cfg = 0; + rsrc_data->ubwc_stats_ctrl = 0; + rsrc_data->ubwc_ctrl_2 = 0; + rsrc_data->init_cfg_done = false; + rsrc_data->hfr_cfg_done = false; + rsrc_data->ubwc_updated = false; + rsrc_data->en_cfg = 0; + rsrc_data->is_dual = 0; + + rsrc_data->ubwc_lossy_threshold_0 = 0; + rsrc_data->ubwc_lossy_threshold_1 = 0; + rsrc_data->ubwc_offset_lossy_variance = 0; + rsrc_data->ubwc_bandwidth_limit = 0; + wm_res->tasklet_info = NULL; + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + CAM_DBG(CAM_ISP, "VFE:%d Release WM:%d", + rsrc_data->common_data->core_index, rsrc_data->index); + + return 0; +} + +static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) +{ + int val = 0; + struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_vfe_bus_ver3_common_data *common_data = + rsrc_data->common_data; + struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_regs; + + ubwc_regs = (struct cam_vfe_bus_ver3_reg_offset_ubwc_client *) + rsrc_data->hw_regs->ubwc_regs; + + cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit); + + cam_io_w((rsrc_data->height << 16) | rsrc_data->width, + common_data->mem_base + rsrc_data->hw_regs->image_cfg_0); + cam_io_w(rsrc_data->pack_fmt, + common_data->mem_base + rsrc_data->hw_regs->packer_cfg); + + /* Configure stride for RDIs on full IFE */ + if (!common_data->is_lite && rsrc_data->index > 22) + cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + + rsrc_data->hw_regs->image_cfg_2)); + + /* Configure stride for RDIs on IFE lite */ + if (common_data->is_lite) + cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + + rsrc_data->hw_regs->image_cfg_2)); + + /* enable ubwc if needed*/ + if (rsrc_data->en_ubwc) { + val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg); + val |= 0x1; + cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg); + } + + /* Enable WM */ + cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + + rsrc_data->hw_regs->cfg); + + CAM_DBG(CAM_ISP, + "Start VFE:%d WM:%d offset:0x%X en_cfg:0x%X width:%d height:%d", + rsrc_data->common_data->core_index, rsrc_data->index, + (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg, + rsrc_data->width, rsrc_data->height); + CAM_DBG(CAM_ISP, "WM:%d pk_fmt:%d stride:%d burst len:%d", + rsrc_data->index, rsrc_data->pack_fmt & PACKER_FMT_VER3_MAX, + rsrc_data->stride, 0xF); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + +static int cam_vfe_bus_ver3_stop_wm(struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_vfe_bus_ver3_common_data *common_data = + rsrc_data->common_data; + + /* Disable WM */ + cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg); + CAM_DBG(CAM_ISP, "Stop VFE:%d WM:%d", + rsrc_data->common_data->core_index, rsrc_data->index); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + rsrc_data->init_cfg_done = false; + rsrc_data->hfr_cfg_done = false; + rsrc_data->ubwc_updated = false; + + return 0; +} + +static int cam_vfe_bus_ver3_handle_wm_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + return -EPERM; +} + +static int cam_vfe_bus_ver3_handle_wm_done_bottom_half(void *wm_node, + void *evt_payload_priv) +{ + return -EPERM; +} + +static int cam_vfe_bus_ver3_init_wm_resource(uint32_t index, + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_vfe_bus_ver3_hw_info *ver3_hw_info, + struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data; + + rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver3_wm_resource_data), + GFP_KERNEL); + if (!rsrc_data) { + CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv"); + return -ENOMEM; + } + wm_res->res_priv = rsrc_data; + + rsrc_data->index = index; + rsrc_data->hw_regs = &ver3_hw_info->bus_client_reg[index]; + rsrc_data->common_data = &ver3_bus_priv->common_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = cam_vfe_bus_ver3_start_wm; + wm_res->stop = cam_vfe_bus_ver3_stop_wm; + wm_res->top_half_handler = cam_vfe_bus_ver3_handle_wm_done_top_half; + wm_res->bottom_half_handler = + cam_vfe_bus_ver3_handle_wm_done_bottom_half; + wm_res->hw_intf = ver3_bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_vfe_bus_ver3_deinit_wm_resource( + struct cam_isp_resource_node *wm_res) +{ + struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = NULL; + wm_res->stop = NULL; + wm_res->top_half_handler = NULL; + wm_res->bottom_half_handler = NULL; + wm_res->hw_intf = NULL; + + rsrc_data = wm_res->res_priv; + wm_res->res_priv = NULL; + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static void cam_vfe_bus_ver3_add_wm_to_comp_grp( + struct cam_isp_resource_node *comp_grp, + uint32_t composite_mask) +{ + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = comp_grp->res_priv; + + rsrc_data->composite_mask |= composite_mask; +} + +static bool cam_vfe_bus_ver3_match_comp_grp( + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_isp_resource_node **comp_grp, + uint32_t comp_grp_id) +{ + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = NULL; + struct cam_isp_resource_node *comp_grp_local = NULL; + + list_for_each_entry(comp_grp_local, + &ver3_bus_priv->used_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_type == comp_grp_id) { + /* Match found */ + *comp_grp = comp_grp_local; + return true; + } + } + + list_for_each_entry(comp_grp_local, + &ver3_bus_priv->free_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_type == comp_grp_id) { + /* Match found */ + *comp_grp = comp_grp_local; + list_del(&comp_grp_local->list); + list_add_tail(&comp_grp_local->list, + &ver3_bus_priv->used_comp_grp); + return false; + } + } + + *comp_grp = NULL; + return false; +} + +static int cam_vfe_bus_ver3_acquire_comp_grp( + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_isp_out_port_generic_info *out_port_info, + void *tasklet, + uint32_t is_dual, + uint32_t is_master, + enum cam_vfe_bus_ver3_vfe_core_id dual_slave_core, + struct cam_isp_resource_node **comp_grp, + enum cam_vfe_bus_ver3_comp_grp_type comp_grp_id) +{ + int rc = 0; + struct cam_isp_resource_node *comp_grp_local = NULL; + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = NULL; + bool previously_acquired = false; + + if (comp_grp_id >= CAM_VFE_BUS_VER3_COMP_GRP_0 && + comp_grp_id <= CAM_VFE_BUS_VER3_COMP_GRP_13) { + /* Check if matching comp_grp has already been acquired */ + previously_acquired = cam_vfe_bus_ver3_match_comp_grp( + ver3_bus_priv, &comp_grp_local, comp_grp_id); + } + + if (!comp_grp_local) { + CAM_ERR(CAM_ISP, "Invalid comp_grp:%d", comp_grp_id); + return -ENODEV; + } + + rsrc_data = comp_grp_local->res_priv; + + if (!previously_acquired) { + if (is_dual) { + rc = cam_vfe_bus_ver3_get_intra_client_mask( + dual_slave_core, + comp_grp_local->hw_intf->hw_idx, + &rsrc_data->intra_client_mask); + if (rc) + return rc; + } + + comp_grp_local->tasklet_info = tasklet; + comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + rsrc_data->is_master = is_master; + rsrc_data->is_dual = is_dual; + + if (is_master) + rsrc_data->addr_sync_mode = 0; + else + rsrc_data->addr_sync_mode = 1; + + } else { + rsrc_data = comp_grp_local->res_priv; + /* Do not support runtime change in composite mask */ + if (comp_grp_local->res_state == + CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "Invalid State %d comp_grp:%u", + comp_grp_local->res_state, + rsrc_data->comp_grp_type); + return -EBUSY; + } + } + + CAM_DBG(CAM_ISP, "Acquire VFE:%d comp_grp:%u", + rsrc_data->common_data->core_index, rsrc_data->comp_grp_type); + + rsrc_data->acquire_dev_cnt++; + *comp_grp = comp_grp_local; + + return rc; +} + +static int cam_vfe_bus_ver3_release_comp_grp( + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_isp_resource_node *in_comp_grp) +{ + struct cam_isp_resource_node *comp_grp = NULL; + struct cam_vfe_bus_ver3_comp_grp_data *in_rsrc_data = NULL; + int match_found = 0; + + if (!in_comp_grp) { + CAM_ERR(CAM_ISP, "Invalid Params comp_grp %pK", in_comp_grp); + return -EINVAL; + } + + if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "Already released comp_grp"); + return 0; + } + + if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "Invalid State %d", + in_comp_grp->res_state); + return -EBUSY; + } + + in_rsrc_data = in_comp_grp->res_priv; + CAM_DBG(CAM_ISP, "Release VFE:%d comp_grp:%u", + ver3_bus_priv->common_data.core_index, + in_rsrc_data->comp_grp_type); + + list_for_each_entry(comp_grp, &ver3_bus_priv->used_comp_grp, list) { + if (comp_grp == in_comp_grp) { + match_found = 1; + break; + } + } + + if (!match_found) { + CAM_ERR(CAM_ISP, "Could not find comp_grp:%u", + in_rsrc_data->comp_grp_type); + return -ENODEV; + } + + in_rsrc_data->acquire_dev_cnt--; + if (in_rsrc_data->acquire_dev_cnt == 0) { + list_del(&comp_grp->list); + + in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER3_VFE_CORE_MAX; + in_rsrc_data->addr_sync_mode = 0; + in_rsrc_data->composite_mask = 0; + + comp_grp->tasklet_info = NULL; + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + list_add_tail(&comp_grp->list, &ver3_bus_priv->free_comp_grp); + } + + return 0; +} + +static int cam_vfe_bus_ver3_start_comp_grp( + struct cam_isp_resource_node *comp_grp, uint32_t *bus_irq_reg_mask) +{ + int rc = 0; + uint32_t val; + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_common_data *common_data = NULL; + + rsrc_data = comp_grp->res_priv; + common_data = rsrc_data->common_data; + + CAM_DBG(CAM_ISP, + "Start VFE:%d comp_grp:%d streaming state:%d comp_mask:0x%X", + rsrc_data->common_data->core_index, + rsrc_data->comp_grp_type, comp_grp->res_state, + rsrc_data->composite_mask); + + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + return 0; + + if (rsrc_data->is_dual) { + if (rsrc_data->is_master) { + val = cam_io_r_mb(common_data->mem_base + + common_data->common_reg->comp_cfg_0); + + val |= (0x1 << (rsrc_data->comp_grp_type + 14)); + + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->comp_cfg_0); + + val = cam_io_r_mb(common_data->mem_base + + common_data->common_reg->comp_cfg_1); + + val |= (0x1 << rsrc_data->comp_grp_type); + + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->comp_cfg_1); + } else { + val = cam_io_r_mb(common_data->mem_base + + common_data->common_reg->comp_cfg_0); + + val |= (0x1 << rsrc_data->comp_grp_type); + val |= (0x1 << (rsrc_data->comp_grp_type + 14)); + + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->comp_cfg_0); + + val = cam_io_r_mb(common_data->mem_base + + common_data->common_reg->comp_cfg_1); + + val |= (0x1 << rsrc_data->comp_grp_type); + + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->comp_cfg_1); + } + } + + if (rsrc_data->ubwc_static_ctrl) { + val = cam_io_r_mb(common_data->mem_base + + common_data->common_reg->ubwc_static_ctrl); + val |= rsrc_data->ubwc_static_ctrl; + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->ubwc_static_ctrl); + } + + bus_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_REG0] = + (0x1 << (rsrc_data->comp_grp_type + + rsrc_data->common_data->comp_done_shift)); + + CAM_DBG(CAM_ISP, "Start Done VFE:%d comp_grp:%d bus_irq_mask_0: 0x%X", + rsrc_data->common_data->core_index, + rsrc_data->comp_grp_type, + bus_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_REG0]); + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return rc; +} + +static int cam_vfe_bus_ver3_stop_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + return 0; +} + +static int cam_vfe_bus_ver3_handle_comp_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + return -EPERM; +} + +static int cam_vfe_bus_ver3_handle_comp_done_bottom_half( + void *handler_priv, + void *evt_payload_priv, + uint32_t *comp_mask) +{ + int rc = CAM_VFE_IRQ_STATUS_ERR; + struct cam_isp_resource_node *comp_grp = handler_priv; + struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = comp_grp->res_priv; + uint32_t *cam_ife_irq_regs; + uint32_t status_0; + + if (!evt_payload) + return rc; + + if (rsrc_data->is_dual && (!rsrc_data->is_master)) { + CAM_ERR(CAM_ISP, "Invalid comp_grp:%u is_master:%u", + rsrc_data->comp_grp_type, rsrc_data->is_master); + return rc; + } + + cam_ife_irq_regs = evt_payload->irq_reg_val; + status_0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; + + if (status_0 & BIT(rsrc_data->comp_grp_type + + rsrc_data->common_data->comp_done_shift)) { + evt_payload->evt_id = CAM_ISP_HW_EVENT_DONE; + rc = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + CAM_DBG(CAM_ISP, "VFE:%d comp_grp:%d Bus IRQ status_0: 0x%X rc:%d", + rsrc_data->common_data->core_index, rsrc_data->comp_grp_type, + status_0, rc); + + *comp_mask = rsrc_data->composite_mask; + + return rc; +} + +static int cam_vfe_bus_ver3_init_comp_grp(uint32_t index, + struct cam_hw_soc_info *soc_info, + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_vfe_bus_ver3_hw_info *ver3_hw_info, + struct cam_isp_resource_node *comp_grp) +{ + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = NULL; + struct cam_vfe_soc_private *vfe_soc_private = soc_info->soc_private; + int ddr_type = 0; + + rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver3_comp_grp_data), + GFP_KERNEL); + if (!rsrc_data) + return -ENOMEM; + + comp_grp->res_priv = rsrc_data; + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&comp_grp->list); + + rsrc_data->comp_grp_type = index; + rsrc_data->common_data = &ver3_bus_priv->common_data; + rsrc_data->dual_slave_core = CAM_VFE_BUS_VER3_VFE_CORE_MAX; + + if (rsrc_data->comp_grp_type != CAM_VFE_BUS_VER3_COMP_GRP_0 && + rsrc_data->comp_grp_type != CAM_VFE_BUS_VER3_COMP_GRP_1) + rsrc_data->ubwc_static_ctrl = 0; + else { + ddr_type = of_fdt_get_ddrtype(); + if ((ddr_type == DDR_TYPE_LPDDR5) || + (ddr_type == DDR_TYPE_LPDDR5X)) + rsrc_data->ubwc_static_ctrl = + vfe_soc_private->ubwc_static_ctrl[1]; + else + rsrc_data->ubwc_static_ctrl = + vfe_soc_private->ubwc_static_ctrl[0]; + } + + list_add_tail(&comp_grp->list, &ver3_bus_priv->free_comp_grp); + + comp_grp->top_half_handler = cam_vfe_bus_ver3_handle_comp_done_top_half; + comp_grp->hw_intf = ver3_bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_vfe_bus_ver3_deinit_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = + comp_grp->res_priv; + + comp_grp->start = NULL; + comp_grp->stop = NULL; + comp_grp->top_half_handler = NULL; + comp_grp->bottom_half_handler = NULL; + comp_grp->hw_intf = NULL; + + list_del_init(&comp_grp->list); + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + + comp_grp->res_priv = NULL; + + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "comp_grp_priv is NULL"); + return -ENODEV; + } + kfree(rsrc_data); + + return 0; +} + +static int cam_vfe_bus_ver3_get_secure_mode(void *priv, void *cmd_args, + uint32_t arg_size) +{ + bool *mode = cmd_args; + struct cam_isp_resource_node *res = + (struct cam_isp_resource_node *) priv; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = + (struct cam_vfe_bus_ver3_vfe_out_data *)res->res_priv; + + *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? + true : false; + + return 0; +} + +static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, + uint32_t args_size) +{ + int rc = -ENODEV; + int i; + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id; + uint32_t format; + int num_wm; + struct cam_vfe_bus_ver3_priv *ver3_bus_priv = bus_priv; + struct cam_vfe_acquire_args *acq_args = acquire_args; + struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + uint32_t secure_caps = 0, mode; + enum cam_vfe_bus_ver3_comp_grp_type comp_grp_id; + uint32_t client_done_mask = 0; + + if (!bus_priv || !acquire_args) { + CAM_ERR(CAM_ISP, "Invalid Param"); + return -EINVAL; + } + + out_acquire_args = &acq_args->vfe_out; + format = out_acquire_args->out_port_info->format; + + CAM_DBG(CAM_ISP, "VFE:%d Acquire out_type:0x%X", + ver3_bus_priv->common_data.core_index, + out_acquire_args->out_port_info->res_type); + + vfe_out_res_id = cam_vfe_bus_ver3_get_out_res_id( + out_acquire_args->out_port_info->res_type); + if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_MAX) + return -ENODEV; + + num_wm = cam_vfe_bus_ver3_get_num_wm(vfe_out_res_id, format); + if (num_wm < 1) + return -EINVAL; + + rsrc_node = &ver3_bus_priv->vfe_out[vfe_out_res_id]; + if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "VFE:%d out_type:0x%X resource not available state:%d", + ver3_bus_priv->common_data.core_index, + vfe_out_res_id, rsrc_node->res_state); + return -EBUSY; + } + + rsrc_data = rsrc_node->res_priv; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + + secure_caps = cam_vfe_bus_ver3_can_be_secure( + rsrc_data->out_type); + mode = out_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); + + ver3_bus_priv->tasklet_info = acq_args->tasklet; + rsrc_data->num_wm = num_wm; + rsrc_node->res_id = out_acquire_args->out_port_info->res_type; + rsrc_node->tasklet_info = acq_args->tasklet; + rsrc_node->cdm_ops = out_acquire_args->cdm_ops; + rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops; + + /* Acquire WM and retrieve COMP GRP ID */ + for (i = 0; i < num_wm; i++) { + rc = cam_vfe_bus_ver3_acquire_wm(ver3_bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + vfe_out_res_id, + i, + &rsrc_data->wm_res[i], + &client_done_mask, + out_acquire_args->is_dual, + &comp_grp_id); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to acquire WM VFE:%d out_type:%d rc:%d", + rsrc_data->common_data->core_index, + vfe_out_res_id, rc); + goto release_wm; + } + } + + /* Acquire composite group using COMP GRP ID */ + rc = cam_vfe_bus_ver3_acquire_comp_grp(ver3_bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + out_acquire_args->is_dual, + out_acquire_args->is_master, + out_acquire_args->dual_slave_core, + &rsrc_data->comp_grp, + comp_grp_id); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to acquire comp_grp VFE:%d out_typp:%d rc:%d", + rsrc_data->common_data->core_index, + vfe_out_res_id, rc); + return rc; + } + + rsrc_data->is_dual = out_acquire_args->is_dual; + rsrc_data->is_master = out_acquire_args->is_master; + + cam_vfe_bus_ver3_add_wm_to_comp_grp(rsrc_data->comp_grp, + client_done_mask); + + rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + out_acquire_args->rsrc_node = rsrc_node; + + CAM_DBG(CAM_ISP, "Acquire successful"); + return rc; + +release_wm: + for (i--; i >= 0; i--) + cam_vfe_bus_ver3_release_wm(ver3_bus_priv, + rsrc_data->wm_res[i]); + + cam_vfe_bus_ver3_release_comp_grp(ver3_bus_priv, rsrc_data->comp_grp); + + return rc; +} + +static int cam_vfe_bus_ver3_release_vfe_out(void *bus_priv, void *release_args, + uint32_t args_size) +{ + uint32_t i; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver3_vfe_out_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_out = release_args; + rsrc_data = vfe_out->res_priv; + + if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, + "Invalid resource state:%d VFE:%d out_type:0x%X", + vfe_out->res_state, rsrc_data->common_data->core_index, + vfe_out->res_id); + } + + for (i = 0; i < rsrc_data->num_wm; i++) + cam_vfe_bus_ver3_release_wm(bus_priv, rsrc_data->wm_res[i]); + rsrc_data->num_wm = 0; + + if (rsrc_data->comp_grp) + cam_vfe_bus_ver3_release_comp_grp(bus_priv, + rsrc_data->comp_grp); + rsrc_data->comp_grp = NULL; + + vfe_out->tasklet_info = NULL; + vfe_out->cdm_ops = NULL; + rsrc_data->cdm_util_ops = NULL; + + secure_caps = cam_vfe_bus_ver3_can_be_secure(rsrc_data->out_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_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +static int cam_vfe_bus_ver3_start_vfe_out( + struct cam_isp_resource_node *vfe_out) +{ + int rc = 0, i; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_MAX]; + uint32_t rup_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_MAX]; + uint32_t source_group = 0; + + if (!vfe_out) { + CAM_ERR(CAM_ISP, "Invalid input"); + return -EINVAL; + } + + rsrc_data = vfe_out->res_priv; + common_data = rsrc_data->common_data; + source_group = rsrc_data->source_group; + + CAM_DBG(CAM_ISP, "Start VFE:%d out_type:0x%X", + rsrc_data->common_data->core_index, rsrc_data->out_type); + + if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, + "Invalid resource state:%d VFE:%d out_type:0x%X", + vfe_out->res_state, rsrc_data->common_data->core_index, + rsrc_data->out_type); + return -EACCES; + } + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_vfe_bus_ver3_start_wm(rsrc_data->wm_res[i]); + + memset(bus_irq_reg_mask, 0, sizeof(bus_irq_reg_mask)); + rc = cam_vfe_bus_ver3_start_comp_grp(rsrc_data->comp_grp, + bus_irq_reg_mask); + + if (rsrc_data->is_dual && !rsrc_data->is_master) + goto end; + + vfe_out->irq_handle = cam_irq_controller_subscribe_irq( + common_data->bus_irq_controller, + CAM_IRQ_PRIORITY_1, + bus_irq_reg_mask, + vfe_out, + vfe_out->top_half_handler, + vfe_out->bottom_half_handler, + vfe_out->tasklet_info, + &tasklet_bh_api); + + if (vfe_out->irq_handle < 1) { + CAM_ERR(CAM_ISP, "Subscribe IRQ failed for VFE out_res %d", + vfe_out->res_id); + vfe_out->irq_handle = 0; + return -EFAULT; + } + + if (!common_data->rup_irq_handle[source_group]) { + memset(rup_irq_reg_mask, 0, sizeof(rup_irq_reg_mask)); + rup_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_REG0] |= + 0x1 << source_group; + + CAM_DBG(CAM_ISP, + "VFE:%d out_type:0x%X bus_irq_mask_0:0x%X for RUP", + rsrc_data->common_data->core_index, rsrc_data->out_type, + rup_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_REG0]); + + common_data->rup_irq_handle[source_group] = + cam_irq_controller_subscribe_irq( + common_data->bus_irq_controller, + CAM_IRQ_PRIORITY_1, + rup_irq_reg_mask, + vfe_out, + cam_vfe_bus_ver3_handle_rup_top_half, + cam_vfe_bus_ver3_handle_rup_bottom_half, + vfe_out->tasklet_info, + &tasklet_bh_api); + + if (common_data->rup_irq_handle[source_group] < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe RUP IRQ"); + common_data->rup_irq_handle[source_group] = 0; + return -EFAULT; + } + } + +end: + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return rc; +} + +static int cam_vfe_bus_ver3_stop_vfe_out( + struct cam_isp_resource_node *vfe_out) +{ + int rc = 0, i; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_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; + + if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE || + vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "Stop VFE:%d out_type:0x%X state:%d", + rsrc_data->common_data->core_index, rsrc_data->out_type, + vfe_out->res_state); + return rc; + } + + rc = cam_vfe_bus_ver3_stop_comp_grp(rsrc_data->comp_grp); + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_vfe_bus_ver3_stop_wm(rsrc_data->wm_res[i]); + + if (common_data->rup_irq_handle[rsrc_data->source_group]) { + rc = cam_irq_controller_unsubscribe_irq( + common_data->bus_irq_controller, + common_data->rup_irq_handle[rsrc_data->source_group]); + common_data->rup_irq_handle[rsrc_data->source_group] = 0; + } + + if (vfe_out->irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + common_data->bus_irq_controller, + vfe_out->irq_handle); + vfe_out->irq_handle = 0; + } + + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_irq_evt_payload *evt_payload; + + vfe_out = th_payload->handler_priv; + if (!vfe_out) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + + rsrc_data = vfe_out->res_priv; + + CAM_DBG(CAM_ISP, "VFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + + rc = cam_vfe_bus_ver3_get_evt_payload(rsrc_data->common_data, + &evt_payload); + + if (rc) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "VFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + evt_payload->core_index = rsrc_data->common_data->core_index; + evt_payload->evt_id = evt_id; + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( + void *handler_priv, + void *evt_payload_priv) +{ + int rc = -EINVAL, num_out = 0, i = 0; + struct cam_isp_resource_node *vfe_out = handler_priv; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = vfe_out->res_priv; + struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_isp_hw_event_info evt_info; + void *ctx = NULL; + uint32_t evt_id = 0, comp_mask = 0; + uint32_t out_list[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; + + rc = cam_vfe_bus_ver3_handle_comp_done_bottom_half( + rsrc_data->comp_grp, evt_payload_priv, &comp_mask); + CAM_DBG(CAM_ISP, "VFE:%d out_type:0x%X rc:%d", + rsrc_data->common_data->core_index, rsrc_data->out_type, + rsrc_data->out_type, rc); + + ctx = rsrc_data->priv; + memset(out_list, 0, sizeof(out_list)); + + switch (rc) { + case CAM_VFE_IRQ_STATUS_SUCCESS: + evt_id = evt_payload->evt_id; + + evt_info.res_type = vfe_out->res_type; + evt_info.hw_idx = vfe_out->hw_intf->hw_idx; + + rc = cam_vfe_bus_ver3_get_comp_vfe_out_res_id_list( + comp_mask, out_list, &num_out, + rsrc_data->common_data->is_lite); + for (i = 0; i < num_out; i++) { + evt_info.res_id = out_list[i]; + if (rsrc_data->common_data->event_cb) + rsrc_data->common_data->event_cb(ctx, evt_id, + (void *)&evt_info); + } + break; + default: + break; + } + + cam_vfe_bus_ver3_put_evt_payload(rsrc_data->common_data, &evt_payload); + + return rc; +} + +static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, + struct cam_vfe_bus_ver3_priv *ver3_bus_priv, + struct cam_vfe_bus_ver3_hw_info *ver3_hw_info) +{ + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + int rc = 0; + int32_t vfe_out_type = + ver3_hw_info->vfe_out_hw_info[index].vfe_out_type; + + if (vfe_out_type < 0 || + vfe_out_type >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d", + vfe_out_type); + return -EINVAL; + } + + vfe_out = &ver3_bus_priv->vfe_out[vfe_out_type]; + if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || + vfe_out->res_priv) { + CAM_ERR(CAM_ISP, "vfe_out_type %d has already been initialized", + vfe_out_type); + return -EFAULT; + } + + rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver3_vfe_out_data), + GFP_KERNEL); + if (!rsrc_data) { + rc = -ENOMEM; + return rc; + } + + vfe_out->res_priv = rsrc_data; + + vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT; + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&vfe_out->list); + + rsrc_data->source_group = + ver3_hw_info->vfe_out_hw_info[index].source_group; + rsrc_data->out_type = + ver3_hw_info->vfe_out_hw_info[index].vfe_out_type; + rsrc_data->common_data = &ver3_bus_priv->common_data; + rsrc_data->max_width = + ver3_hw_info->vfe_out_hw_info[index].max_width; + rsrc_data->max_height = + ver3_hw_info->vfe_out_hw_info[index].max_height; + rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + + vfe_out->start = cam_vfe_bus_ver3_start_vfe_out; + vfe_out->stop = cam_vfe_bus_ver3_stop_vfe_out; + vfe_out->top_half_handler = + cam_vfe_bus_ver3_handle_vfe_out_done_top_half; + vfe_out->bottom_half_handler = + cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half; + vfe_out->process_cmd = cam_vfe_bus_ver3_process_cmd; + vfe_out->hw_intf = ver3_bus_priv->common_data.hw_intf; + vfe_out->irq_handle = 0; + + return 0; +} + +static int cam_vfe_bus_ver3_deinit_vfe_out_resource( + struct cam_isp_resource_node *vfe_out) +{ + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = vfe_out->res_priv; + + if (vfe_out->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, "VFE:%d out_type:%d already deinitialized", + rsrc_data->common_data->core_index, + rsrc_data->out_type); + return 0; + } + + vfe_out->start = NULL; + vfe_out->stop = NULL; + vfe_out->top_half_handler = NULL; + vfe_out->bottom_half_handler = NULL; + vfe_out->hw_intf = NULL; + vfe_out->irq_handle = 0; + + vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&vfe_out->list); + vfe_out->res_priv = NULL; + + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static void cam_vfe_bus_ver3_print_dimensions( + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, + enum cam_vfe_bus_plane_type plane, + struct cam_vfe_bus_ver3_priv *bus_priv) +{ + struct cam_isp_resource_node *wm_res = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + int wm_idx = 0; + + wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, plane, + bus_priv->common_data.is_lite); + + if (wm_idx < 0 || wm_idx >= bus_priv->num_client || plane > PLANE_C) { + CAM_ERR(CAM_ISP, + "Unsupported VFE out_type:0x%X plane:%d wm_idx:%d max_idx:%d", + vfe_out_res_id, plane, wm_idx, + bus_priv->num_client - 1); + return; + } + + wm_res = &bus_priv->bus_client[wm_idx]; + wm_data = wm_res->res_priv; + + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u", + wm_data->common_data->core_index, wm_idx, wm_data->width, + wm_data->height, wm_data->stride, wm_data->h_init, + wm_data->en_cfg); +} + +static int cam_vfe_bus_ver3_handle_irq(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_vfe_bus_ver3_priv *bus_priv; + int rc = 0; + + bus_priv = th_payload->handler_priv; + CAM_DBG(CAM_ISP, "Enter"); + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.bus_irq_controller); + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; +} + +static int cam_vfe_bus_ver3_err_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int i = 0, rc = 0; + struct cam_vfe_bus_ver3_priv *bus_priv = + th_payload->handler_priv; + struct cam_vfe_bus_irq_evt_payload *evt_payload; + + CAM_ERR_RATE_LIMIT(CAM_ISP, "VFE:%d BUS Err IRQ", + bus_priv->common_data.core_index); + for (i = 0; i < th_payload->num_registers; i++) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "VFE:%d BUS IRQ status_%d: 0x%X", + bus_priv->common_data.core_index, i, + th_payload->evt_status_arr[i]); + } + cam_irq_controller_disable_irq(bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + + rc = cam_vfe_bus_ver3_get_evt_payload(&bus_priv->common_data, + &evt_payload); + if (rc) + return rc; + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->core_index = bus_priv->common_data.core_index; + + evt_payload->ccif_violation_status = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->ccif_violation_status); + + evt_payload->image_size_violation_status = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->image_size_violation_status); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_vfe_bus_ver3_err_irq_bottom_half( + void *handler_priv, void *evt_payload_priv) +{ + struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_vfe_bus_ver3_priv *bus_priv = handler_priv; + struct cam_vfe_bus_ver3_common_data *common_data; + struct cam_isp_hw_event_info evt_info; + uint32_t val = 0, image_size_violation = 0, ccif_violation = 0; + + if (!handler_priv || !evt_payload_priv) + return -EINVAL; + + common_data = &bus_priv->common_data; + + val = evt_payload->irq_reg_val[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; + image_size_violation = (val >> 31) & 0x1; + ccif_violation = (val >> 30) & 0x1; + + CAM_ERR(CAM_ISP, + "VFE:%d BUS Violation image_size_violation %d ccif_violation %d", + bus_priv->common_data.core_index, image_size_violation, + ccif_violation); + CAM_INFO(CAM_ISP, + "image_size_violation_status 0x%X ccif_violation_status 0x%X", + evt_payload->image_size_violation_status, + evt_payload->ccif_violation_status); + + if (common_data->is_lite) { + if (image_size_violation) { + val = evt_payload->image_size_violation_status; + + if (val & 0x01) { + CAM_INFO(CAM_ISP, + "RDI 0 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + PLANE_Y, + bus_priv); + } + + if (val & 0x02) { + CAM_INFO(CAM_ISP, + "RDI 1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + PLANE_Y, + bus_priv); + } + + if (val & 0x04) { + CAM_INFO(CAM_ISP, + "RDI 2 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + PLANE_Y, + bus_priv); + } + + if (val & 0x08) { + CAM_INFO(CAM_ISP, + "RDI 3 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI3, + PLANE_Y, + bus_priv); + } + } + + if (ccif_violation) { + val = evt_payload->ccif_violation_status; + + if (val & 0x01) + CAM_INFO(CAM_ISP, + "RDI 0 ccif violation"); + + if (val & 0x02) + CAM_INFO(CAM_ISP, + "RDI 1 ccif violation"); + + if (val & 0x04) + CAM_INFO(CAM_ISP, + "RDI 2 ccif violation"); + + if (val & 0x08) + CAM_INFO(CAM_ISP, + "RDI 3 ccif violation"); + } + + goto end; + } + + if (image_size_violation) { + val = evt_payload->image_size_violation_status; + + if (val & 0x01) { + CAM_INFO(CAM_ISP, "VID Y 1:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_FULL, + PLANE_Y, + bus_priv); + } + + if (val & 0x02) { + CAM_INFO(CAM_ISP, "VID C 1:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_FULL, + PLANE_C, + bus_priv); + } + + if (val & 0x04) { + CAM_INFO(CAM_ISP, "VID YC 4:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_DS4, + PLANE_Y, + bus_priv); + } + + if (val & 0x08) { + CAM_INFO(CAM_ISP, "VID YC 16:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_DS16, + PLANE_Y, + bus_priv); + } + + if (val & 0x010) { + CAM_INFO(CAM_ISP, "DISP Y 1:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + PLANE_Y, + bus_priv); + } + + if (val & 0x020) { + CAM_INFO(CAM_ISP, "DISP C 1:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + PLANE_C, + bus_priv); + } + + if (val & 0x040) { + CAM_INFO(CAM_ISP, "DISP YC 4:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, + PLANE_Y, + bus_priv); + } + + if (val & 0x080) { + CAM_INFO(CAM_ISP, "DISP YC 16:1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, + PLANE_Y, + bus_priv); + } + + if (val & 0x0100) { + CAM_INFO(CAM_ISP, "FD Y image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_FD, + PLANE_Y, + bus_priv); + } + + if (val & 0x0200) { + CAM_INFO(CAM_ISP, "FD C image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_FD, + PLANE_C, + bus_priv); + } + + if (val & 0x0400) { + CAM_INFO(CAM_ISP, + "PIXEL RAW DUMP image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, + PLANE_Y, + bus_priv); + } + + if (val & 0x01000) { + CAM_INFO(CAM_ISP, "STATS HDR BE image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, + PLANE_Y, + bus_priv); + } + + if (val & 0x02000) { + CAM_INFO(CAM_ISP, + "STATS HDR BHIST image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, + PLANE_Y, + bus_priv); + } + + if (val & 0x04000) { + CAM_INFO(CAM_ISP, + "STATS TINTLESS BG image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, + PLANE_Y, + bus_priv); + } + + if (val & 0x08000) { + CAM_INFO(CAM_ISP, "STATS AWB BG image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, + PLANE_Y, + bus_priv); + } + + if (val & 0x010000) { + CAM_INFO(CAM_ISP, "STATS BHIST image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, + PLANE_Y, + bus_priv); + } + + if (val & 0x020000) { + CAM_INFO(CAM_ISP, "STATS RS image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, + PLANE_Y, + bus_priv); + } + + if (val & 0x040000) { + CAM_INFO(CAM_ISP, "STATS CS image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, + PLANE_Y, + bus_priv); + } + + if (val & 0x080000) { + CAM_INFO(CAM_ISP, "STATS IHIST image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, + PLANE_Y, + bus_priv); + } + + if (val & 0x0100000) { + CAM_INFO(CAM_ISP, "STATS BAF image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, + PLANE_Y, + bus_priv); + } + + if (val & 0x0200000) { + CAM_INFO(CAM_ISP, "PD image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_2PD, + PLANE_Y, + bus_priv); + } + + if (val & 0x0400000) { + CAM_INFO(CAM_ISP, "LCR image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_LCR, + PLANE_Y, + bus_priv); + } + + if (val & 0x0800000) { + CAM_INFO(CAM_ISP, "RDI 0 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + PLANE_Y, + bus_priv); + } + + if (val & 0x01000000) { + CAM_INFO(CAM_ISP, "RDI 1 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + PLANE_Y, + bus_priv); + } + + if (val & 0x02000000) { + CAM_INFO(CAM_ISP, "RDI 2 image size violation"); + cam_vfe_bus_ver3_print_dimensions( + CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + PLANE_Y, + bus_priv); + } + + } + + if (ccif_violation) { + val = evt_payload->ccif_violation_status; + + if (val & 0x01) + CAM_INFO(CAM_ISP, "VID Y 1:1 ccif violation"); + + if (val & 0x02) + CAM_INFO(CAM_ISP, "VID C 1:1 ccif violation"); + + if (val & 0x04) + CAM_INFO(CAM_ISP, "VID YC 4:1 ccif violation"); + + if (val & 0x08) + CAM_INFO(CAM_ISP, "VID YC 16:1 ccif violation"); + + if (val & 0x010) + CAM_INFO(CAM_ISP, "DISP Y 1:1 ccif violation"); + + if (val & 0x020) + CAM_INFO(CAM_ISP, "DISP C 1:1 ccif violation"); + + if (val & 0x040) + CAM_INFO(CAM_ISP, "DISP YC 4:1 ccif violation"); + + if (val & 0x080) + CAM_INFO(CAM_ISP, "DISP YC 16:1 ccif violation"); + + if (val & 0x0100) + CAM_INFO(CAM_ISP, "FD Y ccif violation"); + + if (val & 0x0200) + CAM_INFO(CAM_ISP, "FD C ccif violation"); + + if (val & 0x0400) + CAM_INFO(CAM_ISP, "PIXEL RAW DUMP ccif violation"); + + if (val & 0x01000) + CAM_INFO(CAM_ISP, "STATS HDR BE ccif violation"); + + if (val & 0x02000) + CAM_INFO(CAM_ISP, "STATS HDR BHIST ccif violation"); + + if (val & 0x04000) + CAM_INFO(CAM_ISP, "STATS TINTLESS BG ccif violation"); + + if (val & 0x08000) + CAM_INFO(CAM_ISP, "STATS AWB BG ccif violation"); + + if (val & 0x010000) + CAM_INFO(CAM_ISP, "STATS BHIST ccif violation"); + + if (val & 0x020000) + CAM_INFO(CAM_ISP, "STATS RS ccif violation"); + + if (val & 0x040000) + CAM_INFO(CAM_ISP, "STATS CS ccif violation"); + + if (val & 0x080000) + CAM_INFO(CAM_ISP, "STATS IHIST ccif violation"); + + if (val & 0x0100000) + CAM_INFO(CAM_ISP, "STATS BAF ccif violation"); + + if (val & 0x0200000) + CAM_INFO(CAM_ISP, "PD ccif violation"); + + if (val & 0x0400000) + CAM_INFO(CAM_ISP, "LCR ccif violation"); + + if (val & 0x0800000) + CAM_INFO(CAM_ISP, "RDI 0 ccif violation"); + + if (val & 0x01000000) + CAM_INFO(CAM_ISP, "RDI 1 ccif violation"); + + if (val & 0x02000000) + CAM_INFO(CAM_ISP, "RDI 2 ccif violation"); + + } + +end: + cam_vfe_bus_ver3_put_evt_payload(common_data, &evt_payload); + + evt_info.hw_idx = common_data->core_index; + evt_info.res_type = CAM_ISP_RESOURCE_VFE_OUT; + evt_info.res_id = CAM_VFE_BUS_VER3_VFE_OUT_MAX; + evt_info.err_type = CAM_VFE_IRQ_STATUS_VIOLATION; + + if (common_data->event_cb) + common_data->event_cb(NULL, CAM_ISP_HW_EVENT_ERROR, + (void *)&evt_info); + return 0; +} + +static void cam_vfe_bus_ver3_update_ubwc_meta_addr( + uint32_t *reg_val_pair, + uint32_t *j, + void *regs, + uint64_t image_buf) +{ + struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_regs; + + if (!regs || !reg_val_pair || !j) { + CAM_ERR(CAM_ISP, "Invalid args"); + goto end; + } + + ubwc_regs = (struct cam_vfe_bus_ver3_reg_offset_ubwc_client *)regs; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_addr, image_buf); + +end: + return; +} + +static int cam_vfe_bus_ver3_update_ubwc_regs( + struct cam_vfe_bus_ver3_wm_resource_data *wm_data, + uint32_t *reg_val_pair, uint32_t i, uint32_t *j) +{ + struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_regs; + int rc = 0; + + if (!wm_data || !reg_val_pair || !j) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + ubwc_regs = (struct cam_vfe_bus_ver3_reg_offset_ubwc_client *) + wm_data->hw_regs->ubwc_regs; + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + wm_data->hw_regs->packer_cfg, wm_data->packer_cfg); + CAM_DBG(CAM_ISP, "WM:%d packer cfg 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->meta_cfg, wm_data->ubwc_meta_cfg); + CAM_DBG(CAM_ISP, "WM:%d meta stride 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->mode_cfg, wm_data->ubwc_mode_cfg); + CAM_DBG(CAM_ISP, "WM:%d ubwc_mode_cfg 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->ctrl_2, wm_data->ubwc_ctrl_2); + CAM_DBG(CAM_ISP, "WM:%d ubwc_ctrl_2 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->lossy_thresh0, wm_data->ubwc_lossy_threshold_0); + CAM_DBG(CAM_ISP, "WM:%d lossy_thresh0 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->lossy_thresh1, wm_data->ubwc_lossy_threshold_1); + CAM_DBG(CAM_ISP, "WM:%d lossy_thresh1 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->off_lossy_var, wm_data->ubwc_offset_lossy_variance); + CAM_DBG(CAM_ISP, "WM:%d off_lossy_var 0x%X", + wm_data->index, reg_val_pair[*j-1]); + + if (wm_data->ubwc_bandwidth_limit) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, + ubwc_regs->bw_limit, wm_data->ubwc_bandwidth_limit); + CAM_DBG(CAM_ISP, "WM:%d ubwc bw limit 0x%X", + wm_data->index, wm_data->ubwc_bandwidth_limit); + } + +end: + return rc; +} + +static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_buf; + struct cam_buf_io_cfg *io_cfg; + struct cam_vfe_bus_ver3_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_client = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, k, size = 0; + uint32_t frame_inc = 0, val; + uint32_t loop_size = 0; + + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + update_buf->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + if (update_buf->wm_update->num_buf != vfe_out_data->num_wm) { + CAM_ERR(CAM_ISP, + "Failed! Invalid number buffers:%d required:%d", + update_buf->wm_update->num_buf, vfe_out_data->num_wm); + return -EINVAL; + } + + reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; + io_cfg = update_buf->wm_update->io_cfg; + + for (i = 0, j = 0; i < vfe_out_data->num_wm; 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 %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = vfe_out_data->wm_res[i]->res_priv; + ubwc_client = wm_data->hw_regs->ubwc_regs; + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->cfg, wm_data->en_cfg); + CAM_DBG(CAM_ISP, "WM:%d en_cfg 0x%X", + wm_data->index, reg_val_pair[j-1]); + + val = (wm_data->height << 16) | wm_data->width; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_0, val); + CAM_DBG(CAM_ISP, "WM:%d image height and width 0x%X", + wm_data->index, reg_val_pair[j-1]); + + /* For initial configuration program all bus registers */ + val = io_cfg->planes[i].plane_stride; + CAM_DBG(CAM_ISP, "before stride %d", val); + val = ALIGNUP(val, 16); + if (val != io_cfg->planes[i].plane_stride && + val != wm_data->stride) + CAM_WARN(CAM_ISP, "Warning stride %u expected %u", + io_cfg->planes[i].plane_stride, val); + + if ((wm_data->stride != val || + !wm_data->init_cfg_done) && + (!bus_priv->common_data.is_lite && + wm_data->index < 23)) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_2, + io_cfg->planes[i].plane_stride); + wm_data->stride = val; + CAM_DBG(CAM_ISP, "WM:%d image stride 0x%X", + wm_data->index, reg_val_pair[j-1]); + } + + if (wm_data->en_ubwc) { + if (!wm_data->hw_regs->ubwc_regs) { + CAM_ERR(CAM_ISP, + "No UBWC register to configure."); + return -EINVAL; + } + if (wm_data->ubwc_updated) { + wm_data->ubwc_updated = false; + cam_vfe_bus_ver3_update_ubwc_regs( + wm_data, reg_val_pair, i, &j); + } + + /* UBWC meta address */ + cam_vfe_bus_ver3_update_ubwc_meta_addr( + reg_val_pair, &j, + wm_data->hw_regs->ubwc_regs, + update_buf->wm_update->image_buf[i]); + CAM_DBG(CAM_ISP, "WM:%d ubwc meta addr 0x%llx", + wm_data->index, + update_buf->wm_update->image_buf[i]); + } + + if (wm_data->en_ubwc) { + frame_inc = ALIGNUP(io_cfg->planes[i].plane_stride * + io_cfg->planes[i].slice_height, 4096); + frame_inc += io_cfg->planes[i].meta_size; + CAM_DBG(CAM_ISP, + "WM:%d frm %d: ht: %d stride %d meta: %d", + wm_data->index, frame_inc, + io_cfg->planes[i].slice_height, + io_cfg->planes[i].plane_stride, + io_cfg->planes[i].meta_size); + } else { + frame_inc = io_cfg->planes[i].plane_stride * + io_cfg->planes[i].slice_height; + } + + if (!(wm_data->en_cfg & (0x3 << 16))) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_1, wm_data->h_init); + CAM_DBG(CAM_ISP, "WM:%d h_init 0x%X", + wm_data->index, reg_val_pair[j-1]); + } + + if ((!bus_priv->common_data.is_lite && wm_data->index > 22) || + bus_priv->common_data.is_lite) + loop_size = wm_data->irq_subsample_period + 1; + else + loop_size = 1; + + /* WM Image address */ + for (k = 0; k < loop_size; k++) { + if (wm_data->en_ubwc) + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i] + + io_cfg->planes[i].meta_size + + k * frame_inc); + else if (wm_data->en_cfg & (0x3 << 16)) + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + (update_buf->wm_update->image_buf[i] + + wm_data->offset + k * frame_inc)); + else + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + (update_buf->wm_update->image_buf[i] + + k * frame_inc)); + + CAM_DBG(CAM_ISP, "WM:%d image address 0x%X", + wm_data->index, reg_val_pair[j-1]); + } + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_incr, frame_inc); + CAM_DBG(CAM_ISP, "WM:%d frame_inc %d", + wm_data->index, reg_val_pair[j-1]); + + + /* enable the WM */ + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->cfg, + wm_data->en_cfg); + + /* set initial configuration done */ + if (!wm_data->init_cfg_done) + wm_data->init_cfg_done = true; + } + + size = vfe_out_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_out_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_ver3_update_hfr(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_hfr; + struct cam_vfe_bus_ver3_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_isp_port_hfr_config *hfr_cfg = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + update_hfr = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + update_hfr->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; + hfr_cfg = update_hfr->hfr_update; + + for (i = 0, j = 0; i < vfe_out_data->num_wm; 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 %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = vfe_out_data->wm_res[i]->res_priv; + + if (((!bus_priv->common_data.is_lite && wm_data->index > 22) || + bus_priv->common_data.is_lite) && + hfr_cfg->subsample_period > 3) { + CAM_ERR(CAM_ISP, + "RDI doesn't support irq subsample period %d", + hfr_cfg->subsample_period); + return -EINVAL; + } + + if ((wm_data->framedrop_pattern != + hfr_cfg->framedrop_pattern) || + !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_pattern, + hfr_cfg->framedrop_pattern); + wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern; + CAM_DBG(CAM_ISP, "WM:%d framedrop pattern 0x%X", + wm_data->index, wm_data->framedrop_pattern); + } + + if (wm_data->framedrop_period != hfr_cfg->framedrop_period || + !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_period, + hfr_cfg->framedrop_period); + wm_data->framedrop_period = hfr_cfg->framedrop_period; + CAM_DBG(CAM_ISP, "WM:%d framedrop period 0x%X", + wm_data->index, wm_data->framedrop_period); + } + + if (wm_data->irq_subsample_period != hfr_cfg->subsample_period + || !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_period, + hfr_cfg->subsample_period); + wm_data->irq_subsample_period = + hfr_cfg->subsample_period; + CAM_DBG(CAM_ISP, "WM:%d irq subsample period 0x%X", + wm_data->index, wm_data->irq_subsample_period); + } + + if (wm_data->irq_subsample_pattern != hfr_cfg->subsample_pattern + || !wm_data->hfr_cfg_done) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_pattern, + hfr_cfg->subsample_pattern); + wm_data->irq_subsample_pattern = + hfr_cfg->subsample_pattern; + CAM_DBG(CAM_ISP, "WM:%d irq subsample pattern 0x%X", + wm_data->index, wm_data->irq_subsample_pattern); + } + + /* set initial configuration done */ + if (!wm_data->hfr_cfg_done) + wm_data->hfr_cfg_done = true; + } + + size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2); + + /* cdm util returns dwords, need to convert to bytes */ + if ((size * 4) > update_hfr->cmd.size) { + CAM_ERR(CAM_ISP, + "Failed! Buf size:%d insufficient, expected size:%d", + update_hfr->cmd.size, size); + return -ENOMEM; + } + + vfe_out_data->cdm_util_ops->cdm_write_regrandom( + update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + update_hfr->cmd.used_bytes = size * 4; + + return 0; +} + +static int cam_vfe_bus_ver3_update_ubwc_config_v2(void *cmd_args) +{ + struct cam_isp_hw_get_cmd_update *update_ubwc; + struct cam_vfe_bus_ver3_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_vfe_generic_ubwc_config *ubwc_generic_cfg = NULL; + struct cam_vfe_generic_ubwc_plane_config *ubwc_generic_plane_cfg = NULL; + uint32_t i; + int rc = 0; + + if (!cmd_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + rc = -EINVAL; + goto end; + } + + update_ubwc = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + update_ubwc->res->res_priv; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Invalid data"); + rc = -EINVAL; + goto end; + } + + ubwc_generic_cfg = update_ubwc->ubwc_config; + + for (i = 0; i < vfe_out_data->num_wm; i++) { + + wm_data = vfe_out_data->wm_res[i]->res_priv; + ubwc_generic_plane_cfg = &ubwc_generic_cfg->ubwc_plane_cfg[i]; + + if (!wm_data->hw_regs->ubwc_regs) { + CAM_ERR(CAM_ISP, + "No UBWC register to configure."); + rc = -EINVAL; + goto end; + } + + if (!wm_data->en_ubwc) { + CAM_ERR(CAM_ISP, "UBWC Disabled"); + rc = -EINVAL; + goto end; + } + + if (wm_data->packer_cfg != + ubwc_generic_plane_cfg->packer_config || + !wm_data->init_cfg_done) { + wm_data->packer_cfg = + ubwc_generic_plane_cfg->packer_config; + wm_data->ubwc_updated = true; + } + + if ((!wm_data->is_dual) && ((wm_data->h_init != + ubwc_generic_plane_cfg->h_init) || + !wm_data->init_cfg_done)) { + wm_data->h_init = ubwc_generic_plane_cfg->h_init; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_meta_cfg != + ubwc_generic_plane_cfg->meta_stride || + !wm_data->init_cfg_done) { + wm_data->ubwc_meta_cfg = + ubwc_generic_plane_cfg->meta_stride; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_mode_cfg != + ubwc_generic_plane_cfg->mode_config_0 || + !wm_data->init_cfg_done) { + wm_data->ubwc_mode_cfg = + ubwc_generic_plane_cfg->mode_config_0; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_ctrl_2 != + ubwc_generic_plane_cfg->ctrl_2 || + !wm_data->init_cfg_done) { + wm_data->ubwc_ctrl_2 = + ubwc_generic_plane_cfg->ctrl_2; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_lossy_threshold_0 != + ubwc_generic_plane_cfg->lossy_threshold_0 || + !wm_data->init_cfg_done) { + wm_data->ubwc_lossy_threshold_0 = + ubwc_generic_plane_cfg->lossy_threshold_0; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_lossy_threshold_1 != + ubwc_generic_plane_cfg->lossy_threshold_1 || + !wm_data->init_cfg_done) { + wm_data->ubwc_lossy_threshold_1 = + ubwc_generic_plane_cfg->lossy_threshold_1; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_offset_lossy_variance != + ubwc_generic_plane_cfg->lossy_var_offset || + !wm_data->init_cfg_done) { + wm_data->ubwc_offset_lossy_variance = + ubwc_generic_plane_cfg->lossy_var_offset; + wm_data->ubwc_updated = true; + } + + if (wm_data->ubwc_bandwidth_limit != + ubwc_generic_plane_cfg->bandwidth_limit || + !wm_data->init_cfg_done) { + wm_data->ubwc_bandwidth_limit = + ubwc_generic_plane_cfg->bandwidth_limit; + wm_data->ubwc_updated = true; + } + } + +end: + return rc; +} + +static int cam_vfe_bus_ver3_update_stripe_cfg(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_priv *bus_priv; + struct cam_isp_hw_dual_isp_update_args *stripe_args; + struct cam_vfe_bus_ver3_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_isp_dual_stripe_config *stripe_config; + uint32_t outport_id, ports_plane_idx, i; + + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + stripe_args = (struct cam_isp_hw_dual_isp_update_args *)cmd_args; + + vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + stripe_args->res->res_priv; + + if (!vfe_out_data) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + outport_id = stripe_args->res->res_id & 0xFF; + if (stripe_args->res->res_id < CAM_ISP_IFE_OUT_RES_BASE || + stripe_args->res->res_id >= CAM_ISP_IFE_OUT_RES_MAX) + return 0; + + ports_plane_idx = (stripe_args->split_id * + (stripe_args->dual_cfg->num_ports * CAM_PACKET_MAX_PLANES)) + + (outport_id * CAM_PACKET_MAX_PLANES); + for (i = 0; i < vfe_out_data->num_wm; i++) { + wm_data = vfe_out_data->wm_res[i]->res_priv; + stripe_config = (struct cam_isp_dual_stripe_config *) + &stripe_args->dual_cfg->stripes[ports_plane_idx + i]; + wm_data->width = stripe_config->width; + + /* + * UMD sends buffer offset address as offset for clients + * programmed to operate in frame/index based mode and h_init + * value as offset for clients programmed to operate in line + * based mode. + */ + + if (wm_data->en_cfg & (0x3 << 16)) + wm_data->offset = stripe_config->offset; + else + wm_data->h_init = stripe_config->offset; + + CAM_DBG(CAM_ISP, + "out_type:0x%X WM:%d width:%d offset:0x%X h_init:%d", + stripe_args->res->res_id, wm_data->index, + wm_data->width, wm_data->offset, wm_data->h_init); + } + + return 0; +} + +static int cam_vfe_bus_ver3_update_wm_config( + void *cmd_args) +{ + int i; + struct cam_isp_hw_get_cmd_update *wm_config_update; + struct cam_vfe_bus_ver3_vfe_out_data *vfe_out_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_isp_vfe_wm_config *wm_config = NULL; + + if (!cmd_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + wm_config_update = cmd_args; + vfe_out_data = wm_config_update->res->res_priv; + wm_config = wm_config_update->wm_config; + + if (!vfe_out_data || !vfe_out_data->cdm_util_ops || !wm_config) { + CAM_ERR(CAM_ISP, "Invalid data"); + return -EINVAL; + } + + for (i = 0; i < vfe_out_data->num_wm; i++) { + wm_data = vfe_out_data->wm_res[i]->res_priv; + + if (wm_config->wm_mode > 0x2) { + CAM_ERR(CAM_ISP, "Invalid wm_mode: 0x%X WM:%d", + wm_config->wm_mode, wm_data->index); + return -EINVAL; + } + + wm_data->en_cfg = (wm_config->wm_mode << 16) | 0x1; + wm_data->height = wm_config->height; + wm_data->width = wm_config->width; + + CAM_DBG(CAM_ISP, + "WM:%d en_cfg:0x%X height:%d width:%d", + wm_data->index, wm_data->en_cfg, wm_data->height, + wm_data->width); + } + + return 0; +} + +static int cam_vfe_bus_ver3_start_hw(void *hw_priv, + void *start_hw_args, uint32_t arg_size) +{ + return cam_vfe_bus_ver3_start_vfe_out(hw_priv); +} + +static int cam_vfe_bus_ver3_stop_hw(void *hw_priv, + void *stop_hw_args, uint32_t arg_size) +{ + return cam_vfe_bus_ver3_stop_vfe_out(hw_priv); +} + +static int cam_vfe_bus_ver3_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_priv *bus_priv = hw_priv; + uint32_t top_irq_reg_mask[3] = {0}; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + if (bus_priv->common_data.hw_init) + return 0; + + top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift); + + 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_ver3_handle_irq, + NULL, + NULL, + NULL); + + if (bus_priv->irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ"); + bus_priv->irq_handle = 0; + 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_ver3_err_irq_top_half, + cam_vfe_bus_ver3_err_irq_bottom_half, + bus_priv->tasklet_info, + &tasklet_bh_api); + + if (bus_priv->error_irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS Error IRQ"); + bus_priv->error_irq_handle = 0; + return -EFAULT; + } + } + + /* no clock gating at bus input */ + CAM_INFO(CAM_ISP, "Overriding clock gating at bus input"); + cam_io_w_mb(0x3FFFFFF, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->cgc_ovd); + + /* BUS_WR_TEST_BUS_CTRL */ + cam_io_w_mb(0x0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->test_bus_ctrl); + + bus_priv->common_data.hw_init = true; + + return 0; +} + +static int cam_vfe_bus_ver3_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_priv *bus_priv = hw_priv; + int rc = 0, i; + unsigned long flags; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Error: Invalid args"); + return -EINVAL; + } + + if (!bus_priv->common_data.hw_init) + return 0; + + if (bus_priv->error_irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + 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); + bus_priv->irq_handle = 0; + } + + spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_VFE_BUS_VER3_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + list_add_tail(&bus_priv->common_data.evt_payload[i].list, + &bus_priv->common_data.free_payload_list); + } + bus_priv->common_data.hw_init = false; + spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); + + return rc; +} + +static int __cam_vfe_bus_ver3_process_cmd(void *priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + return cam_vfe_bus_ver3_process_cmd(priv, cmd_type, cmd_args, arg_size); +} + +static int cam_vfe_bus_ver3_process_cmd( + struct cam_isp_resource_node *priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = -EINVAL; + struct cam_vfe_bus_ver3_priv *bus_priv; + + 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: + rc = cam_vfe_bus_ver3_update_wm(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + rc = cam_vfe_bus_ver3_update_hfr(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = cam_vfe_bus_ver3_get_secure_mode(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + rc = cam_vfe_bus_ver3_update_stripe_cfg(priv, + cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + if (bus_priv->error_irq_handle) { + CAM_DBG(CAM_ISP, "Mask off bus error irq handler"); + rc = cam_irq_controller_unsubscribe_irq( + bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + bus_priv->error_irq_handle = 0; + } + break; + case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: + rc = cam_vfe_bus_ver3_update_ubwc_config_v2(cmd_args); + break; + case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: + rc = cam_vfe_bus_ver3_update_wm_config(cmd_args); + break; + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", + cmd_type); + break; + } + + return rc; +} + +int cam_vfe_bus_ver3_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_ver3_priv *bus_priv = NULL; + struct cam_vfe_bus *vfe_bus_local; + struct cam_vfe_bus_ver3_hw_info *ver3_hw_info = bus_hw_info; + struct cam_vfe_soc_private *soc_private = NULL; + + CAM_DBG(CAM_ISP, "Enter"); + + 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_hw_info); + CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller); + rc = -EINVAL; + goto end; + } + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + rc = -ENODEV; + 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_ver3_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 = ver3_hw_info->num_client; + bus_priv->num_out = ver3_hw_info->num_out; + bus_priv->top_irq_shift = ver3_hw_info->top_irq_shift; + 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 = &ver3_hw_info->common_reg; + bus_priv->common_data.comp_done_shift = + ver3_hw_info->comp_done_shift; + bus_priv->common_data.hw_init = false; + + bus_priv->common_data.is_lite = soc_private->is_ife_lite; + + for (i = 0; i < CAM_VFE_BUS_VER3_SRC_GRP_MAX; i++) + bus_priv->common_data.rup_irq_handle[i] = 0; + + mutex_init(&bus_priv->common_data.bus_mutex); + + rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base, + &ver3_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; + } + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_vfe_bus_ver3_init_wm_resource(i, bus_priv, bus_hw_info, + &bus_priv->bus_client[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "VFE:%d init WM:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + goto deinit_wm; + } + } + + for (i = 0; i < CAM_VFE_BUS_VER3_COMP_GRP_MAX; i++) { + rc = cam_vfe_bus_ver3_init_comp_grp(i, soc_info, + bus_priv, bus_hw_info, + &bus_priv->comp_grp[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "VFE:%d init comp_grp:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + goto deinit_comp_grp; + } + } + + for (i = 0; i < bus_priv->num_out; i++) { + rc = cam_vfe_bus_ver3_init_vfe_out_resource(i, bus_priv, + bus_hw_info); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "VFE:%d init out_type:0x%X failed rc:%d", + bus_priv->common_data.core_index, i, rc); + goto deinit_vfe_out; + } + } + + spin_lock_init(&bus_priv->common_data.spin_lock); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_VFE_BUS_VER3_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + list_add_tail(&bus_priv->common_data.evt_payload[i].list, + &bus_priv->common_data.free_payload_list); + } + + vfe_bus_local->hw_ops.reserve = cam_vfe_bus_ver3_acquire_vfe_out; + vfe_bus_local->hw_ops.release = cam_vfe_bus_ver3_release_vfe_out; + vfe_bus_local->hw_ops.start = cam_vfe_bus_ver3_start_hw; + vfe_bus_local->hw_ops.stop = cam_vfe_bus_ver3_stop_hw; + vfe_bus_local->hw_ops.init = cam_vfe_bus_ver3_init_hw; + vfe_bus_local->hw_ops.deinit = cam_vfe_bus_ver3_deinit_hw; + vfe_bus_local->top_half_handler = cam_vfe_bus_ver3_handle_irq; + vfe_bus_local->bottom_half_handler = NULL; + vfe_bus_local->hw_ops.process_cmd = __cam_vfe_bus_ver3_process_cmd; + + *vfe_bus = vfe_bus_local; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; + +deinit_vfe_out: + if (i < 0) + i = CAM_VFE_BUS_VER3_VFE_OUT_MAX; + for (--i; i >= 0; i--) + cam_vfe_bus_ver3_deinit_vfe_out_resource(&bus_priv->vfe_out[i]); + +deinit_comp_grp: + if (i < 0) + i = CAM_VFE_BUS_VER3_COMP_GRP_MAX; + for (--i; i >= 0; i--) + cam_vfe_bus_ver3_deinit_comp_grp(&bus_priv->comp_grp[i]); + +deinit_wm: + if (i < 0) + i = bus_priv->num_client; + for (--i; i >= 0; i--) + cam_vfe_bus_ver3_deinit_wm_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_ver3_deinit( + struct cam_vfe_bus **vfe_bus) +{ + int i, rc = 0; + struct cam_vfe_bus_ver3_priv *bus_priv = NULL; + struct cam_vfe_bus *vfe_bus_local; + unsigned long flags; + + 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; + } + + spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_VFE_BUS_VER3_PAYLOAD_MAX; i++) + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + bus_priv->common_data.hw_init = false; + spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_vfe_bus_ver3_deinit_wm_resource( + &bus_priv->bus_client[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "VFE:%d deinit WM:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + } + + for (i = 0; i < CAM_VFE_BUS_VER3_COMP_GRP_MAX; i++) { + rc = cam_vfe_bus_ver3_deinit_comp_grp(&bus_priv->comp_grp[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "VFE:%d deinit comp_grp:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + } + + for (i = 0; i < CAM_VFE_BUS_VER3_VFE_OUT_MAX; i++) { + rc = cam_vfe_bus_ver3_deinit_vfe_out_resource( + &bus_priv->vfe_out[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "VFE:%d deinit out_type:0x%X failed rc:%d", + bus_priv->common_data.core_index, i, rc); + } + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + 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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h new file mode 100644 index 000000000000..c5b4ab69fa9f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_VFE_BUS_VER3_H_ +#define _CAM_VFE_BUS_VER3_H_ + +#include "cam_irq_controller.h" +#include "cam_vfe_bus.h" + +#define CAM_VFE_BUS_VER3_MAX_CLIENTS 26 +#define CAM_VFE_BUS_VER3_MAX_SUB_GRPS 6 + +enum cam_vfe_bus_ver3_vfe_core_id { + CAM_VFE_BUS_VER3_VFE_CORE_0, + CAM_VFE_BUS_VER3_VFE_CORE_1, + CAM_VFE_BUS_VER3_VFE_CORE_MAX, +}; + +enum cam_vfe_bus_ver3_src_grp { + CAM_VFE_BUS_VER3_SRC_GRP_0, + CAM_VFE_BUS_VER3_SRC_GRP_1, + CAM_VFE_BUS_VER3_SRC_GRP_2, + CAM_VFE_BUS_VER3_SRC_GRP_3, + CAM_VFE_BUS_VER3_SRC_GRP_4, + CAM_VFE_BUS_VER3_SRC_GRP_5, + CAM_VFE_BUS_VER3_SRC_GRP_MAX, +}; + +enum cam_vfe_bus_ver3_comp_grp_type { + CAM_VFE_BUS_VER3_COMP_GRP_0, + CAM_VFE_BUS_VER3_COMP_GRP_1, + CAM_VFE_BUS_VER3_COMP_GRP_2, + CAM_VFE_BUS_VER3_COMP_GRP_3, + CAM_VFE_BUS_VER3_COMP_GRP_4, + CAM_VFE_BUS_VER3_COMP_GRP_5, + CAM_VFE_BUS_VER3_COMP_GRP_6, + CAM_VFE_BUS_VER3_COMP_GRP_7, + CAM_VFE_BUS_VER3_COMP_GRP_8, + CAM_VFE_BUS_VER3_COMP_GRP_9, + CAM_VFE_BUS_VER3_COMP_GRP_10, + CAM_VFE_BUS_VER3_COMP_GRP_11, + CAM_VFE_BUS_VER3_COMP_GRP_12, + CAM_VFE_BUS_VER3_COMP_GRP_13, + CAM_VFE_BUS_VER3_COMP_GRP_MAX, +}; + +enum cam_vfe_bus_ver3_vfe_out_type { + CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + CAM_VFE_BUS_VER3_VFE_OUT_RDI3, + CAM_VFE_BUS_VER3_VFE_OUT_FULL, + CAM_VFE_BUS_VER3_VFE_OUT_DS4, + CAM_VFE_BUS_VER3_VFE_OUT_DS16, + CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, + CAM_VFE_BUS_VER3_VFE_OUT_FD, + CAM_VFE_BUS_VER3_VFE_OUT_PDAF, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, + CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, + CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, + CAM_VFE_BUS_VER3_VFE_OUT_2PD, + CAM_VFE_BUS_VER3_VFE_OUT_LCR, + CAM_VFE_BUS_VER3_VFE_OUT_MAX, +}; + +/* + * struct cam_vfe_bus_ver3_reg_offset_common: + * + * @Brief: Common registers across all BUS Clients + */ +struct cam_vfe_bus_ver3_reg_offset_common { + uint32_t hw_version; + uint32_t cgc_ovd; + uint32_t comp_cfg_0; + uint32_t comp_cfg_1; + uint32_t if_frameheader_cfg[CAM_VFE_BUS_VER3_MAX_SUB_GRPS]; + uint32_t ubwc_static_ctrl; + uint32_t pwr_iso_cfg; + uint32_t overflow_status_clear; + uint32_t ccif_violation_status; + uint32_t overflow_status; + uint32_t image_size_violation_status; + uint32_t debug_status_top_cfg; + uint32_t debug_status_top; + uint32_t test_bus_ctrl; + struct cam_irq_controller_reg_info irq_reg_info; +}; + +/* + * struct cam_vfe_bus_ver3_reg_offset_ubwc_client: + * + * @Brief: UBWC register offsets for BUS Clients + */ +struct cam_vfe_bus_ver3_reg_offset_ubwc_client { + uint32_t meta_addr; + uint32_t meta_cfg; + uint32_t mode_cfg; + uint32_t stats_ctrl; + uint32_t ctrl_2; + uint32_t lossy_thresh0; + uint32_t lossy_thresh1; + uint32_t off_lossy_var; + uint32_t bw_limit; +}; + +/* + * struct cam_vfe_bus_ver3_reg_offset_bus_client: + * + * @Brief: Register offsets for BUS Clients + */ +struct cam_vfe_bus_ver3_reg_offset_bus_client { + uint32_t cfg; + uint32_t image_addr; + uint32_t frame_incr; + uint32_t image_cfg_0; + uint32_t image_cfg_1; + uint32_t image_cfg_2; + uint32_t packer_cfg; + uint32_t frame_header_addr; + uint32_t frame_header_incr; + uint32_t frame_header_cfg; + uint32_t line_done_cfg; + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + uint32_t burst_limit; + uint32_t system_cache_cfg; + void *ubwc_regs; + uint32_t addr_status_0; + uint32_t addr_status_1; + uint32_t addr_status_2; + uint32_t addr_status_3; + uint32_t debug_status_cfg; + uint32_t debug_status_0; + uint32_t debug_status_1; + uint32_t comp_group; +}; + +/* + * struct cam_vfe_bus_ver3_vfe_out_hw_info: + * + * @Brief: HW capability of VFE Bus Client + */ +struct cam_vfe_bus_ver3_vfe_out_hw_info { + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_type; + uint32_t max_width; + uint32_t max_height; + uint32_t source_group; +}; + +/* + * struct cam_vfe_bus_ver3_hw_info: + * + * @Brief: HW register info for entire Bus + * + * @common_reg: Common register details + * @num_client: Total number of write clients + * @bus_client_reg: Bus client register info + * @vfe_out_hw_info: VFE output capability + * @comp_done_shift: Mask shift for comp done mask + * @top_irq_shift: Mask shift for top level BUS WR irq + */ +struct cam_vfe_bus_ver3_hw_info { + struct cam_vfe_bus_ver3_reg_offset_common common_reg; + uint32_t num_client; + struct cam_vfe_bus_ver3_reg_offset_bus_client + bus_client_reg[CAM_VFE_BUS_VER3_MAX_CLIENTS]; + uint32_t num_out; + struct cam_vfe_bus_ver3_vfe_out_hw_info + vfe_out_hw_info[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; + uint32_t comp_done_shift; + uint32_t top_irq_shift; +}; + +/* + * cam_vfe_bus_ver3_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_ver3_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_ver3_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @vfe_bus: Pointer to vfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_bus_ver3_deinit(struct cam_vfe_bus **vfe_bus); + +#endif /* _CAM_VFE_BUS_VER3_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h new file mode 100644 index 000000000000..97336a2da3b8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_BUS_H_ +#define _CAM_VFE_BUS_H_ + +#include +#include "cam_hw_intf.h" +#include "cam_isp_hw.h" + +#define CAM_VFE_BUS_VER_1_0 0x1000 +#define CAM_VFE_BUS_VER_2_0 0x2000 +#define CAM_VFE_BUS_VER_3_0 0x3000 + +#define CAM_VFE_BUS_RD_VER_1_0 0x1000 + +#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \ + do { \ + buf_array[(index)++] = offset; \ + buf_array[(index)++] = val; \ + } while (0) + +#define ALIGNUP(value, alignment) \ + ((value + alignment - 1) / alignment * alignment) + +enum cam_vfe_bus_plane_type { + PLANE_Y, + PLANE_C, + PLANE_MAX, +}; + +enum cam_vfe_bus_type { + BUS_TYPE_WR, + BUS_TYPE_RD, + BUS_TYPE_MAX, +}; + +/* + * struct cam_vfe_bus: + * + * @Brief: Bus interface structure + * + * @bus_priv: Private data of BUS + * @hw_ops: Hardware interface functions + * @top_half_handler: Top Half handler function + * @bottom_half_handler: Bottom Half handler function + */ +struct cam_vfe_bus { + void *bus_priv; + + struct cam_hw_ops hw_ops; + CAM_IRQ_HANDLER_TOP_HALF top_half_handler; + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; +}; + +/* + * cam_vfe_bus_init() + * + * @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 + * @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_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, + void *vfe_irq_controller, + struct cam_vfe_bus **vfe_bus); + +/* + * cam_vfe_bus_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @bus_version: Version of BUS to deinitialize + * @vfe_bus: Pointer to vfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_vfe_bus_deinit(uint32_t bus_version, + struct cam_vfe_bus **vfe_bus); + +#endif /* _CAM_VFE_BUS_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile new file mode 100644 index 000000000000..0ed6a870efa9 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o cam_vfe_top.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_top_ver3.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_ver3.o cam_vfe_rdi.o cam_vfe_fe_ver1.o cam_vfe_camif_lite_ver3.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c new file mode 100644 index 000000000000..0c1179c69776 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#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_irq_controller.h" +#include "cam_tasklet_util.h" +#include "cam_vfe_camif_lite_ver2.h" +#include "cam_debug_util.h" +#include "cam_cdm_util.h" + +struct cam_vfe_mux_camif_lite_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_vfe_camif_lite_ver2_reg *camif_lite_reg; + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_camif_lite_ver2_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; + enum cam_isp_hw_sync_mode sync_mode; + + cam_hw_mgr_event_cb_func event_cb; + void *priv; + int irq_err_handle; + int irq_handle; + void *vfe_irq_controller; + struct cam_vfe_top_irq_evt_payload + evt_payload[CAM_VFE_CAMIF_LITE_EVT_MAX]; + struct list_head free_payload_list; + spinlock_t spin_lock; +}; + +static int cam_vfe_camif_lite_get_evt_payload( + struct cam_vfe_mux_camif_lite_data *camif_lite_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&camif_lite_priv->spin_lock); + if (list_empty(&camif_lite_priv->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&camif_lite_priv->free_payload_list, + struct cam_vfe_top_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + rc = 0; +done: + spin_unlock(&camif_lite_priv->spin_lock); + return rc; +} + +static int cam_vfe_camif_lite_put_evt_payload( + struct cam_vfe_mux_camif_lite_data *camif_lite_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!camif_lite_priv) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&camif_lite_priv->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, + &camif_lite_priv->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&camif_lite_priv->spin_lock, flags); + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_camif_lite_err_irq_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_lite_node; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + bool error_flag = false; + + CAM_DBG(CAM_ISP, "IRQ status_0 = %x, IRQ status_1 = %x", + th_payload->evt_status_arr[0], th_payload->evt_status_arr[1]); + + camif_lite_node = th_payload->handler_priv; + camif_lite_priv = camif_lite_node->res_priv; + /* + * need to handle overflow condition here, otherwise irq storm + * will block everything + */ + if (th_payload->evt_status_arr[1] || (th_payload->evt_status_arr[0] & + camif_lite_priv->reg_data->lite_err_irq_mask0)) { + CAM_ERR(CAM_ISP, + "CAMIF LITE ERR VFE:%d IRQ STATUS_0=0x%x STATUS_1=0x%x", + camif_lite_node->hw_intf->hw_idx, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + CAM_ERR(CAM_ISP, "Stopping further IRQ processing from VFE:%d", + camif_lite_node->hw_intf->hw_idx); + cam_irq_controller_disable_irq( + camif_lite_priv->vfe_irq_controller, + camif_lite_priv->irq_err_handle); + cam_irq_controller_clear_and_mask(evt_id, + camif_lite_priv->vfe_irq_controller); + error_flag = true; + } + + rc = cam_vfe_camif_lite_get_evt_payload(camif_lite_priv, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "IRQ STATUS_0=0x%x STATUS_1=0x%x", + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->irq_reg_val[i] = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->violation_status); + + if (error_flag) + CAM_INFO(CAM_ISP, "Violation status = 0x%x", + evt_payload->irq_reg_val[i]); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + + +static int cam_vfe_camif_lite_get_reg_update( + struct cam_isp_resource_node *camif_lite_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_camif_lite_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; + } + + 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 = camif_lite_res->res_priv; + reg_val_pair[0] = rsrc_data->camif_lite_reg->reg_update_cmd; + reg_val_pair[1] = rsrc_data->reg_data->dual_pd_reg_update_cmd_data; + CAM_DBG(CAM_ISP, "CAMIF Lite reg_update_cmd %x offset %x", + 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_camif_lite_ver2_acquire_resource( + struct cam_isp_resource_node *camif_lite_res, + void *acquire_param) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_data; + struct cam_vfe_acquire_args *acquire_data; + int rc = 0; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + camif_lite_data = (struct cam_vfe_mux_camif_lite_data *) + camif_lite_res->res_priv; + acquire_data = (struct cam_vfe_acquire_args *)acquire_param; + + camif_lite_data->sync_mode = acquire_data->vfe_in.sync_mode; + camif_lite_data->event_cb = acquire_data->event_cb; + camif_lite_data->priv = acquire_data->priv; + + CAM_DBG(CAM_ISP, "hw id:%d sync_mode=%d", + camif_lite_res->hw_intf->hw_idx, + camif_lite_data->sync_mode); + return rc; +} + +static int cam_vfe_camif_lite_resource_start( + struct cam_isp_resource_node *camif_lite_res) +{ + struct cam_vfe_mux_camif_lite_data *rsrc_data; + uint32_t val = 0; + int rc = 0; + uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + if (camif_lite_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Error! Invalid camif lite res res_state:%d", + camif_lite_res->res_state); + return -EINVAL; + } + + rsrc_data = (struct cam_vfe_mux_camif_lite_data *) + camif_lite_res->res_priv; + + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->lite_err_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->lite_err_irq_mask1; + + /* vfe core config */ + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg); + + if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + val |= (1 << rsrc_data->reg_data->extern_reg_update_shift); + + val |= (1 << rsrc_data->reg_data->dual_pd_path_sel_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 val:%d", + camif_lite_res->hw_intf->hw_idx, val); + + /* epoch config with 20 line */ + cam_io_w_mb(rsrc_data->reg_data->lite_epoch_line_cfg, + rsrc_data->mem_base + + rsrc_data->camif_lite_reg->lite_epoch_irq); + + camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Reg Update */ + cam_io_w_mb(rsrc_data->reg_data->dual_pd_reg_update_cmd_data, + rsrc_data->mem_base + + rsrc_data->camif_lite_reg->reg_update_cmd); + CAM_DBG(CAM_ISP, "hw id:%d RUP val:%d", + camif_lite_res->hw_intf->hw_idx, + rsrc_data->reg_data->dual_pd_reg_update_cmd_data); + + if (!rsrc_data->irq_err_handle) { + rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + err_irq_mask, + camif_lite_res, + cam_vfe_camif_lite_err_irq_top_half, + camif_lite_res->bottom_half_handler, + camif_lite_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { + CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_err_handle = 0; + } + } + + CAM_DBG(CAM_ISP, "Start Camif Lite IFE %d Done", + camif_lite_res->hw_intf->hw_idx); + return rc; +} + +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; + int rc = 0; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + if ((camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) || + (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; + + if (camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + if (camif_lite_priv->irq_handle) { + cam_irq_controller_unsubscribe_irq( + camif_lite_priv->vfe_irq_controller, + camif_lite_priv->irq_handle); + camif_lite_priv->irq_handle = 0; + } + + if (camif_lite_priv->irq_err_handle) { + cam_irq_controller_unsubscribe_irq( + camif_lite_priv->vfe_irq_controller, + camif_lite_priv->irq_err_handle); + camif_lite_priv->irq_err_handle = 0; + } + + return rc; +} + +static int cam_vfe_camif_lite_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_camif_lite_get_reg_update(rsrc_node, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: + break; + default: + CAM_ERR(CAM_ISP, + "unsupported process command:%d", cmd_type); + break; + } + + return rc; +} + +static int cam_vfe_camif_lite_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_lite_node; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + + camif_lite_node = th_payload->handler_priv; + camif_lite_priv = camif_lite_node->res_priv; + + CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]); + CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]); + + rc = cam_vfe_camif_lite_get_evt_payload(camif_lite_priv, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "IRQ status0=0x%x status1=0x%x", + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_camif_lite_handle_irq_bottom_half( + void *handler_priv, + void *evt_payload_priv) +{ + int ret = CAM_VFE_IRQ_STATUS_MAX; + struct cam_isp_resource_node *camif_lite_node; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_top_irq_evt_payload *payload; + struct cam_isp_hw_event_info evt_info; + uint32_t irq_status0; + uint32_t irq_status1; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, "Invalid params"); + return ret; + } + + camif_lite_node = handler_priv; + camif_lite_priv = camif_lite_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]; + + evt_info.hw_idx = camif_lite_node->hw_intf->hw_idx; + evt_info.res_id = camif_lite_node->res_id; + evt_info.res_type = camif_lite_node->res_type; + + CAM_DBG(CAM_ISP, "irq_status_0 = 0x%x irq_status_1 = 0x%x", + irq_status0, irq_status1); + + if (irq_status0 & camif_lite_priv->reg_data->lite_sof_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF Lite Received SOF", + evt_info.hw_idx); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_lite_priv->reg_data->lite_epoch0_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF Lite Received EPOCH", + evt_info.hw_idx); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_lite_priv->reg_data->dual_pd_reg_upd_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF Lite hReceived REG_UPDATE_ACK", + evt_info.hw_idx); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_lite_priv->reg_data->lite_eof_irq_mask) { + CAM_DBG(CAM_ISP, "VF:%d CAMIF Lite Received EOF", + evt_info.hw_idx); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if ((irq_status0 & camif_lite_priv->reg_data->lite_err_irq_mask0) || + (irq_status1 & camif_lite_priv->reg_data->lite_err_irq_mask1)) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE Received ERROR", + evt_info.hw_idx); + + if (camif_lite_priv->event_cb) + camif_lite_priv->event_cb(camif_lite_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + } + + cam_vfe_camif_lite_put_evt_payload(camif_lite_priv, &payload); + + CAM_DBG(CAM_ISP, "returning status = %d", ret); + return ret; +} + +int cam_vfe_camif_lite_ver2_init( + struct cam_hw_intf *hw_intf, + struct cam_hw_soc_info *soc_info, + void *camif_lite_hw_info, + struct cam_isp_resource_node *camif_lite_node, + void *vfe_irq_controller) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_priv = NULL; + struct cam_vfe_camif_lite_ver2_hw_info *camif_lite_info = + camif_lite_hw_info; + int i = 0; + + camif_lite_priv = kzalloc(sizeof(*camif_lite_priv), + GFP_KERNEL); + if (!camif_lite_priv) + return -ENOMEM; + + camif_lite_node->res_priv = camif_lite_priv; + + camif_lite_priv->mem_base = + soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base; + camif_lite_priv->camif_lite_reg = camif_lite_info->camif_lite_reg; + camif_lite_priv->common_reg = camif_lite_info->common_reg; + camif_lite_priv->reg_data = camif_lite_info->reg_data; + camif_lite_priv->hw_intf = hw_intf; + camif_lite_priv->soc_info = soc_info; + camif_lite_priv->vfe_irq_controller = vfe_irq_controller; + + camif_lite_node->init = NULL; + camif_lite_node->deinit = NULL; + camif_lite_node->start = cam_vfe_camif_lite_resource_start; + camif_lite_node->stop = cam_vfe_camif_lite_resource_stop; + camif_lite_node->process_cmd = cam_vfe_camif_lite_process_cmd; + camif_lite_node->top_half_handler = + cam_vfe_camif_lite_handle_irq_top_half; + camif_lite_node->bottom_half_handler = + cam_vfe_camif_lite_handle_irq_bottom_half; + + spin_lock_init(&camif_lite_priv->spin_lock); + INIT_LIST_HEAD(&camif_lite_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_LITE_EVT_MAX; i++) { + INIT_LIST_HEAD(&camif_lite_priv->evt_payload[i].list); + list_add_tail(&camif_lite_priv->evt_payload[i].list, + &camif_lite_priv->free_payload_list); + } + + return 0; +} + +int cam_vfe_camif_lite_ver2_deinit( + struct cam_isp_resource_node *camif_lite_node) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_priv = + camif_lite_node->res_priv; + int i = 0; + + INIT_LIST_HEAD(&camif_lite_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_LITE_EVT_MAX; i++) + INIT_LIST_HEAD(&camif_lite_priv->evt_payload[i].list); + + camif_lite_node->start = NULL; + camif_lite_node->stop = NULL; + camif_lite_node->process_cmd = NULL; + camif_lite_node->top_half_handler = NULL; + camif_lite_node->bottom_half_handler = NULL; + + camif_lite_node->res_priv = NULL; + + if (!camif_lite_priv) { + CAM_ERR(CAM_ISP, "Error! camif_priv is NULL"); + return -ENODEV; + } + + kfree(camif_lite_priv); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.h new file mode 100644 index 000000000000..7813e55f508b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_CAMIF_LITE_VER2_H_ +#define _CAM_VFE_CAMIF_LITE_VER2_H_ + +#include "cam_isp_hw.h" +#include "cam_vfe_top.h" + +#define CAM_VFE_CAMIF_LITE_EVT_MAX 256 + +struct cam_vfe_camif_lite_ver2_reg { + uint32_t camif_lite_cmd; + uint32_t camif_lite_config; + uint32_t lite_skip_period; + uint32_t lite_irq_subsample_pattern; + uint32_t lite_epoch_irq; + uint32_t reg_update_cmd; +}; + +struct cam_vfe_camif_lite_ver2_reg_data { + uint32_t dual_pd_reg_update_cmd_data; + uint32_t lite_epoch_line_cfg; + uint32_t lite_sof_irq_mask; + uint32_t lite_epoch0_irq_mask; + uint32_t dual_pd_reg_upd_irq_mask; + uint32_t lite_eof_irq_mask; + uint32_t lite_err_irq_mask0; + uint32_t lite_err_irq_mask1; + uint32_t lite_subscribe_irq_mask0; + uint32_t lite_subscribe_irq_mask1; + uint32_t extern_reg_update_shift; + uint32_t dual_pd_path_sel_shift; +}; + +struct cam_vfe_camif_lite_ver2_hw_info { + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_camif_lite_ver2_reg *camif_lite_reg; + struct cam_vfe_camif_lite_ver2_reg_data *reg_data; +}; + +int cam_vfe_camif_lite_ver2_acquire_resource( + struct cam_isp_resource_node *camif_lite_res, + void *acquire_param); + +int cam_vfe_camif_lite_ver2_init( + struct cam_hw_intf *hw_intf, + struct cam_hw_soc_info *soc_info, + void *camif_lite_hw_info, + struct cam_isp_resource_node *camif_lite_node, + void *vfe_irq_controller); + +int cam_vfe_camif_lite_ver2_deinit( + struct cam_isp_resource_node *camif_node); + +#endif /* _CAM_VFE_CAMIF_LITE_VER2_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c new file mode 100644 index 000000000000..bf527440e2d7 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -0,0 +1,1145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#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_ver3.h" +#include "cam_irq_controller.h" +#include "cam_tasklet_util.h" +#include "cam_vfe_camif_lite_ver3.h" +#include "cam_debug_util.h" +#include "cam_cdm_util.h" + +struct cam_vfe_mux_camif_lite_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_vfe_camif_lite_ver3_reg *camif_lite_reg; + struct cam_vfe_top_ver3_reg_offset_common *common_reg; + struct cam_vfe_camif_lite_ver3_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; + enum cam_isp_hw_sync_mode sync_mode; + struct cam_vfe_camif_common_cfg cam_common_cfg; + + cam_hw_mgr_event_cb_func event_cb; + void *priv; + int irq_err_handle; + int irq_handle; + void *vfe_irq_controller; + struct list_head free_payload_list; + spinlock_t spin_lock; + uint32_t camif_debug; + struct cam_vfe_top_irq_evt_payload + evt_payload[CAM_VFE_CAMIF_LITE_EVT_MAX]; +}; + +static int cam_vfe_camif_lite_get_evt_payload( + struct cam_vfe_mux_camif_lite_data *camif_lite_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&camif_lite_priv->spin_lock); + if (list_empty(&camif_lite_priv->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free CAMIF LITE event payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&camif_lite_priv->free_payload_list, + struct cam_vfe_top_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + rc = 0; +done: + spin_unlock(&camif_lite_priv->spin_lock); + return rc; +} + +static int cam_vfe_camif_lite_put_evt_payload( + struct cam_vfe_mux_camif_lite_data *camif_lite_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!camif_lite_priv) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&camif_lite_priv->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, + &camif_lite_priv->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&camif_lite_priv->spin_lock, flags); + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_camif_lite_err_irq_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_lite_node; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + struct cam_vfe_soc_private *soc_private = NULL; + bool error_flag = false; + + camif_lite_node = th_payload->handler_priv; + camif_lite_priv = camif_lite_node->res_priv; + + soc_private = camif_lite_priv->soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + /* + * need to handle overflow condition here, otherwise irq storm + * will block everything + */ + if (th_payload->evt_status_arr[2] || (th_payload->evt_status_arr[0] & + camif_lite_priv->reg_data->error_irq_mask0)) { + CAM_ERR(CAM_ISP, + "VFE:%d CAMIF LITE:%d Err IRQ status_1: 0x%X status_2: 0x%X", + camif_lite_node->hw_intf->hw_idx, + camif_lite_node->res_id, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[2]); + CAM_ERR(CAM_ISP, "Stopping further IRQ processing from VFE:%d", + camif_lite_node->hw_intf->hw_idx); + cam_irq_controller_disable_irq( + camif_lite_priv->vfe_irq_controller, + camif_lite_priv->irq_err_handle); + cam_irq_controller_clear_and_mask(evt_id, + camif_lite_priv->vfe_irq_controller); + error_flag = true; + } + + rc = cam_vfe_camif_lite_get_evt_payload(camif_lite_priv, &evt_payload); + if (rc) + return rc; + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->irq_reg_val[i] = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->violation_status); + + if (error_flag && !soc_private->is_ife_lite) + CAM_INFO(CAM_ISP, "Violation status = 0x%X", + evt_payload->irq_reg_val[i]); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + + +static int cam_vfe_camif_lite_get_reg_update( + struct cam_isp_resource_node *camif_lite_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_camif_lite_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: cdm args %pK", cdm_args); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CAMIF LITE:%d get RUP", camif_lite_res->res_id); + + 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; + } + + 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 = camif_lite_res->res_priv; + reg_val_pair[0] = rsrc_data->camif_lite_reg->reg_update_cmd; + reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data; + CAM_DBG(CAM_ISP, "CAMIF LITE:%d reg_update_cmd 0x%X offset 0x%X", + camif_lite_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_camif_lite_ver3_acquire_resource( + struct cam_isp_resource_node *camif_lite_res, + void *acquire_param) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_data; + struct cam_vfe_acquire_args *acquire_data; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + camif_lite_data = (struct cam_vfe_mux_camif_lite_data *) + camif_lite_res->res_priv; + acquire_data = (struct cam_vfe_acquire_args *)acquire_param; + + camif_lite_data->sync_mode = acquire_data->vfe_in.sync_mode; + camif_lite_data->event_cb = acquire_data->event_cb; + camif_lite_data->priv = acquire_data->priv; + + CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF LITE:%d sync_mode=%d", + camif_lite_res->hw_intf->hw_idx, + camif_lite_res->res_id, + camif_lite_data->sync_mode); + return 0; +} + +static int cam_vfe_camif_lite_resource_start( + struct cam_isp_resource_node *camif_lite_res) +{ + struct cam_vfe_mux_camif_lite_data *rsrc_data; + struct cam_vfe_soc_private *soc_private = NULL; + uint32_t val = 0; + int rc = 0; + uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + if (camif_lite_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Invalid camif lite res res_state:%d", + camif_lite_res->res_state); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CAMIF LITE:%d Start", camif_lite_res->res_id); + + rsrc_data = (struct cam_vfe_mux_camif_lite_data *) + camif_lite_res->res_priv; + + soc_private = rsrc_data->soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + if (soc_private->is_ife_lite) + goto skip_core_cfg; + + /* vfe core config */ + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_0); + + if (camif_lite_res->res_id == CAM_ISP_HW_VFE_IN_LCR && + rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + val |= (1 << rsrc_data->reg_data->extern_reg_update_shift); + + if (camif_lite_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) { + val |= (1 << rsrc_data->reg_data->operating_mode_shift); + val |= (rsrc_data->cam_common_cfg.input_mux_sel_pdaf & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_MUXSEL_PDAF; + } + + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_0); + + CAM_DBG(CAM_ISP, "VFE:%d core_cfg val:%d", + camif_lite_res->hw_intf->hw_idx, val); + + /* epoch config */ + cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg, + rsrc_data->mem_base + + rsrc_data->camif_lite_reg->lite_epoch_irq); + +skip_core_cfg: + /* Enable Camif */ + cam_io_w_mb(0x1, + rsrc_data->mem_base + + rsrc_data->camif_lite_reg->lite_module_config); + + camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Reg Update */ + cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, + rsrc_data->mem_base + + rsrc_data->camif_lite_reg->reg_update_cmd); + + memset(err_irq_mask, 0, sizeof(err_irq_mask)); + memset(irq_mask, 0, sizeof(irq_mask)); + + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->error_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = + rsrc_data->reg_data->error_irq_mask2; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->subscribe_irq_mask1; + + if (!rsrc_data->irq_handle) { + rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_0, + irq_mask, + camif_lite_res, + camif_lite_res->top_half_handler, + camif_lite_res->bottom_half_handler, + camif_lite_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_handle < 1) { + CAM_ERR(CAM_ISP, "IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_handle = 0; + } + } + + if (!rsrc_data->irq_err_handle) { + rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + err_irq_mask, + camif_lite_res, + cam_vfe_camif_lite_err_irq_top_half, + camif_lite_res->bottom_half_handler, + camif_lite_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { + CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_err_handle = 0; + } + } + + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Start Done", + camif_lite_res->hw_intf->hw_idx, + camif_lite_res->res_id); + return rc; +} + +static int cam_vfe_camif_lite_reg_dump( + struct cam_isp_resource_node *camif_lite_res) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_soc_private *soc_private = NULL; + uint32_t offset, val, wm_idx; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Error, Invalid input arguments"); + return -EINVAL; + } + + if ((camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) || + (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; + + soc_private = camif_lite_priv->soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + CAM_INFO(CAM_ISP, "IFE:%d TOP", camif_lite_priv->hw_intf->hw_idx); + if (!soc_private->is_ife_lite) { + for (offset = 0x0; offset <= 0x1FC; offset += 0x4) { + if (offset == 0x1C || offset == 0x34 || + offset == 0x38 || offset == 0x90) + continue; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + } + } else { + for (offset = 0x0; offset <= 0x74; offset += 0x4) { + if (offset == 0xC || offset == 0x20 || offset == 0x24) + continue; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + } + } + + if (camif_lite_res->res_id != CAM_ISP_HW_VFE_IN_RDI0) + goto dump_rdi_1; + + CAM_INFO(CAM_ISP, "IFE:%d RDI0 CAMIF", + camif_lite_priv->hw_intf->hw_idx); + if (!soc_private->is_ife_lite) { + for (offset = 0x9A00; offset <= 0x9BFC; offset += 0x4) { + if (offset == 0x9A08) + offset = 0x9A60; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x9A60) + offset = 0x9A64; + else if (offset == 0x9A70) + offset = 0x9AEC; + } + } else { + for (offset = 0x1200; offset <= 0x13FC; offset += 0x4) { + if (offset == 0x1208) + offset = 0x1260; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x1260) + offset = 0x1264; + else if (offset == 0x1270) + offset = 0x12EC; + } + } + + goto wr_dump; + +dump_rdi_1: + if (camif_lite_res->res_id != CAM_ISP_HW_VFE_IN_RDI1) + goto dump_rdi_2; + + CAM_INFO(CAM_ISP, "IFE:%d RDI1 CAMIF", + camif_lite_priv->hw_intf->hw_idx); + if (!soc_private->is_ife_lite) { + for (offset = 0x9C00; offset <= 0x9DFC; offset += 0x4) { + if (offset == 0x9A08) + offset = 0x9A60; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x9A60) + offset = 0x9A64; + else if (offset == 0x9A70) + offset = 0x9BEC; + } + } else { + for (offset = 0x1400; offset <= 0x15FC; offset += 0x4) { + if (offset == 0x1408) + offset = 0x1460; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x1460) + offset = 0x1464; + else if (offset == 0x1470) + offset = 0x15EC; + } + } + + goto wr_dump; + +dump_rdi_2: + if (camif_lite_res->res_id != CAM_ISP_HW_VFE_IN_RDI2) + goto dump_rdi_3; + + CAM_INFO(CAM_ISP, "IFE:%d RDI2 CAMIF", + camif_lite_priv->hw_intf->hw_idx); + if (!soc_private->is_ife_lite) { + for (offset = 0x9E00; offset <= 0x9FFC; offset += 0x4) { + if (offset == 0x9E08) + offset = 0x9E60; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x9E60) + offset = 0x9E64; + else if (offset == 0x9E80) + offset = 0x9FEC; + } + } else { + for (offset = 0x1600; offset <= 0x17FC; offset += 0x4) { + if (offset == 0x1608) + offset = 0x1660; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x1660) + offset = 0x1664; + else if (offset == 0x1670) + offset = 0x17EC; + } + } + + goto wr_dump; + +dump_rdi_3: + if (camif_lite_res->res_id != CAM_ISP_HW_VFE_IN_RDI3) + goto dump_pdlib; + + CAM_INFO(CAM_ISP, "IFE:%d RDI3 CAMIF", + camif_lite_priv->hw_intf->hw_idx); + if (soc_private->is_ife_lite) { + for (offset = 0x1800; offset <= 0x19FC; offset += 0x4) { + if (offset == 0x1808) + offset = 0x1860; + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0x1860) + offset = 0x1864; + else if (offset == 0x1870) + offset = 0x19EC; + } + } + + goto wr_dump; + +dump_pdlib: + if (camif_lite_res->res_id != CAM_ISP_HW_VFE_IN_PDLIB) + goto dump_lcr; + + CAM_INFO(CAM_ISP, "IFE:%d PDLIB CAMIF", + camif_lite_priv->hw_intf->hw_idx); + for (offset = 0xA400; offset <= 0xA5FC; offset += 0x4) { + if (offset == 0xA408) + offset = 0xA460; + val = cam_soc_util_r(camif_lite_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0xA460) + offset = 0xA464; + else if (offset == 0xA470) + offset = 0xA5EC; + } + + CAM_INFO(CAM_ISP, "IFE:%d CLC PDLIB", + camif_lite_priv->hw_intf->hw_idx); + for (offset = 0xA600; offset <= 0xA718; offset += 0x4) { + val = cam_soc_util_r(camif_lite_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val); + } + + goto wr_dump; + +dump_lcr: + CAM_INFO(CAM_ISP, "IFE:%d LCR CAMIF", camif_lite_priv->hw_intf->hw_idx); + for (offset = 0xA000; offset <= 0xA1FC; offset += 0x4) { + if (offset == 0xA008) + offset = 0xA060; + val = cam_soc_util_r(camif_lite_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0xA060) + offset = 0xA064; + else if (offset == 0xA070) + offset = 0xA1EC; + } + + CAM_INFO(CAM_ISP, "IFE:%d CLC LCR", camif_lite_priv->hw_intf->hw_idx); + for (offset = 0xA200; offset <= 0xA3FC; offset += 0x4) { + if (offset == 0xA208) + offset = 0xA260; + else if (offset == 0xA288) + offset = 0xA3F8; + val = cam_soc_util_r(camif_lite_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + if (offset == 0xA260) + offset = 0xA264; + else if (offset == 0xA280) + offset = 0xA1EC; + } + +wr_dump: + if (!soc_private->is_ife_lite) + goto end_dump; + + CAM_INFO(CAM_ISP, "IFE:%d LITE BUS WR", + camif_lite_priv->hw_intf->hw_idx); + for (offset = 0x1A00; offset <= 0x1AE0; offset += 0x4) { + val = cam_soc_util_r(camif_lite_priv->soc_info, 0, offset); + CAM_DBG(CAM_ISP, "offset 0x%X value 0x%X", offset, val); + } + + for (wm_idx = 0; wm_idx <= 3; wm_idx++) { + for (offset = 0x1C00 + 0x100 * wm_idx; offset < (0x1C00 + + 0x100 * wm_idx + 0x84); offset += 0x4) { + val = cam_soc_util_r(camif_lite_priv->soc_info, + 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", + offset, val); + } + } + +end_dump: + return 0; +} + +static int cam_vfe_camif_lite_resource_stop( + struct cam_isp_resource_node *camif_lite_res) +{ + struct cam_vfe_mux_camif_lite_data *rsrc_data; + int rc = 0; + + if (!camif_lite_res) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Stop", + camif_lite_res->hw_intf->hw_idx, + camif_lite_res->res_id); + + if ((camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) || + (camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)) + return 0; + + rsrc_data = + (struct cam_vfe_mux_camif_lite_data *)camif_lite_res->res_priv; + + /* Disable Camif */ + cam_io_w_mb(0x0, rsrc_data->mem_base + + rsrc_data->camif_lite_reg->lite_module_config); + + if (camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + if (rsrc_data->irq_handle > 0) { + cam_irq_controller_unsubscribe_irq( + rsrc_data->vfe_irq_controller, + rsrc_data->irq_handle); + rsrc_data->irq_handle = 0; + } + + if (rsrc_data->irq_err_handle > 0) { + cam_irq_controller_unsubscribe_irq( + rsrc_data->vfe_irq_controller, + rsrc_data->irq_err_handle); + rsrc_data->irq_err_handle = 0; + } + + return rc; +} + +static int cam_vfe_camif_lite_ver3_core_config( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_core_config_args *vfe_core_cfg = + (struct cam_vfe_core_config_args *)cmd_args; + + camif_lite_priv = + (struct cam_vfe_mux_camif_lite_data *)rsrc_node->res_priv; + camif_lite_priv->cam_common_cfg.vid_ds16_r2pd = + vfe_core_cfg->core_config.vid_ds16_r2pd; + camif_lite_priv->cam_common_cfg.vid_ds4_r2pd = + vfe_core_cfg->core_config.vid_ds4_r2pd; + camif_lite_priv->cam_common_cfg.disp_ds16_r2pd = + vfe_core_cfg->core_config.disp_ds16_r2pd; + camif_lite_priv->cam_common_cfg.disp_ds4_r2pd = + vfe_core_cfg->core_config.disp_ds4_r2pd; + camif_lite_priv->cam_common_cfg.dsp_streaming_tap_point = + vfe_core_cfg->core_config.dsp_streaming_tap_point; + camif_lite_priv->cam_common_cfg.ihist_src_sel = + vfe_core_cfg->core_config.ihist_src_sel; + camif_lite_priv->cam_common_cfg.hdr_be_src_sel = + vfe_core_cfg->core_config.hdr_be_src_sel; + camif_lite_priv->cam_common_cfg.hdr_bhist_src_sel = + vfe_core_cfg->core_config.hdr_bhist_src_sel; + camif_lite_priv->cam_common_cfg.input_mux_sel_pdaf = + vfe_core_cfg->core_config.input_mux_sel_pdaf; + camif_lite_priv->cam_common_cfg.input_mux_sel_pp = + vfe_core_cfg->core_config.input_mux_sel_pp; + + return 0; +} + +static int cam_vfe_camif_lite_process_cmd( + struct cam_isp_resource_node *rsrc_node, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = -EINVAL; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv = NULL; + + 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_camif_lite_get_reg_update(rsrc_node, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_CORE_CONFIG: + rc = cam_vfe_camif_lite_ver3_core_config(rsrc_node, cmd_args); + break; + case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: + camif_lite_priv = (struct cam_vfe_mux_camif_lite_data *) + rsrc_node->res_priv; + camif_lite_priv->camif_debug = *((uint32_t *)cmd_args); + break; + default: + CAM_ERR(CAM_ISP, + "unsupported process command:%d", cmd_type); + break; + } + + return rc; +} + +static void cam_vfe_camif_lite_print_status(uint32_t *status, + int err_type, bool is_ife_lite) +{ + uint32_t violation_mask = 0x3F00, violation_status = 0; + uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; + + if (!status) { + CAM_ERR(CAM_ISP, "Invalid params"); + return; + } + + bus_overflow_status = status[CAM_IFE_IRQ_REGISTERS_MAX]; + violation_status = status[CAM_IFE_IRQ_VIOLATION_STATUS]; + status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; + status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; + + if (is_ife_lite) + goto ife_lite; + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) { + if (status_0 & 0x200000) + CAM_INFO(CAM_ISP, "RDI2 FRAME DROP"); + + if (status_0 & 0x400000) + CAM_INFO(CAM_ISP, "RDI1 FRAME DROP"); + + if (status_0 & 0x800000) + CAM_INFO(CAM_ISP, "RDI0 FRAME DROP"); + + if (status_0 & 0x1000000) + CAM_INFO(CAM_ISP, "PD PIPE FRAME DROP"); + + if (status_0 & 0x8000000) + CAM_INFO(CAM_ISP, "RDI2 OVERFLOW"); + + if (status_0 & 0x10000000) + CAM_INFO(CAM_ISP, "RDI1 OVERFLOW"); + + if (status_0 & 0x20000000) + CAM_INFO(CAM_ISP, "RDI0 OVERFLOW"); + + if (status_0 & 0x40000000) + CAM_INFO(CAM_ISP, "PD PIPE OVERFLOW"); + } + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && bus_overflow_status) { + if (bus_overflow_status & 0x0800) + CAM_INFO(CAM_ISP, "CAMIF PD BUS OVERFLOW"); + + if (bus_overflow_status & 0x0400000) + CAM_INFO(CAM_ISP, "LCR BUS OVERFLOW"); + + if (bus_overflow_status & 0x0800000) + CAM_INFO(CAM_ISP, "RDI0 BUS OVERFLOW"); + + if (bus_overflow_status & 0x01000000) + CAM_INFO(CAM_ISP, "RDI1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x02000000) + CAM_INFO(CAM_ISP, "RDI2 BUS OVERFLOW"); + + return; + } + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { + CAM_INFO(CAM_ISP, "PDLIB / LCR Module hang"); + /* print debug registers here */ + return; + } + + if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { + if (status_2 & 0x02000) + CAM_INFO(CAM_ISP, "PD CAMIF VIOLATION"); + + if (status_2 & 0x04000) + CAM_INFO(CAM_ISP, "PD VIOLATION"); + + if (status_2 & 0x08000) + CAM_INFO(CAM_ISP, "LCR CAMIF VIOLATION"); + + if (status_2 & 0x010000) + CAM_INFO(CAM_ISP, "LCR VIOLATION"); + + if (status_2 & 0x020000) + CAM_INFO(CAM_ISP, "RDI0 CAMIF VIOLATION"); + + if (status_2 & 0x040000) + CAM_INFO(CAM_ISP, "RDI1 CAMIF VIOLATION"); + + if (status_2 & 0x080000) + CAM_INFO(CAM_ISP, "RDI2 CAMIF VIOLATION"); + } + + if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION && violation_status) { + if (violation_mask & violation_status) + CAM_INFO(CAM_ISP, "LCR VIOLATION Module ID:%d", + violation_mask & violation_status); + + violation_mask = 0x0F0000; + if (violation_mask & violation_status) + CAM_INFO(CAM_ISP, "PD VIOLATION Module ID:%d", + violation_mask & violation_status); + + } + + return; + +ife_lite: + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) { + if (status_0 & 0x100) + CAM_INFO(CAM_ISP, "RDI3 FRAME DROP"); + + if (status_0 & 0x80) + CAM_INFO(CAM_ISP, "RDI2 FRAME DROP"); + + if (status_0 & 0x40) + CAM_INFO(CAM_ISP, "RDI1 FRAME DROP"); + + if (status_0 & 0x20) + CAM_INFO(CAM_ISP, "RDI0 FRAME DROP"); + + if (status_0 & 0x8) + CAM_INFO(CAM_ISP, "RDI3 OVERFLOW"); + + if (status_0 & 0x4) + CAM_INFO(CAM_ISP, "RDI2 OVERFLOW"); + + if (status_0 & 0x2) + CAM_INFO(CAM_ISP, "RDI1 OVERFLOW"); + + if (status_0 & 0x1) + CAM_INFO(CAM_ISP, "RDI0 OVERFLOW"); + } + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && bus_overflow_status) { + if (bus_overflow_status & 0x01) + CAM_INFO(CAM_ISP, "RDI0 BUS OVERFLOW"); + + if (bus_overflow_status & 0x02) + CAM_INFO(CAM_ISP, "RDI1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x04) + CAM_INFO(CAM_ISP, "RDI2 BUS OVERFLOW"); + + if (bus_overflow_status & 0x08) + CAM_INFO(CAM_ISP, "RDI3 BUS OVERFLOW"); + } + + if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { + if (status_2 & 0x100) + CAM_INFO(CAM_ISP, "RDI0 CAMIF VIOLATION"); + + if (status_2 & 0x200) + CAM_INFO(CAM_ISP, "RDI1 CAMIF VIOLATION"); + + if (status_2 & 0x400) + CAM_INFO(CAM_ISP, "RDI2 CAMIF VIOLATION"); + + if (status_2 & 0x800) + CAM_INFO(CAM_ISP, "RDI3 CAMIF VIOLATION"); + } +} + +static int cam_vfe_camif_lite_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_lite_node; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + + camif_lite_node = th_payload->handler_priv; + camif_lite_priv = camif_lite_node->res_priv; + + CAM_DBG(CAM_ISP, + "VFE:%d CAMIF LITE:%d IRQ status_0: 0x%X status_1: 0x%X status_2: 0x%X", + camif_lite_node->hw_intf->hw_idx, + camif_lite_node->res_id, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1], + th_payload->evt_status_arr[2]); + + rc = cam_vfe_camif_lite_get_evt_payload(camif_lite_priv, &evt_payload); + if (rc) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "VFE:%d CAMIF LITE:%d IRQ status_0: 0x%X status_1: 0x%X status_2: 0x%X", + camif_lite_node->hw_intf->hw_idx, + camif_lite_node->res_id, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1], + th_payload->evt_status_arr[2]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_camif_lite_handle_irq_bottom_half( + void *handler_priv, + void *evt_payload_priv) +{ + int ret = CAM_VFE_IRQ_STATUS_MAX; + struct cam_isp_resource_node *camif_lite_node; + struct cam_vfe_mux_camif_lite_data *camif_lite_priv; + struct cam_vfe_top_irq_evt_payload *payload; + struct cam_isp_hw_event_info evt_info; + struct cam_vfe_soc_private *soc_private = NULL; + uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX + 1]; + int i = 0; + bool is_ife_lite = true; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, "Invalid params"); + return ret; + } + + camif_lite_node = handler_priv; + camif_lite_priv = camif_lite_node->res_priv; + payload = evt_payload_priv; + + soc_private = camif_lite_priv->soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + is_ife_lite = soc_private->is_ife_lite; + + memset(irq_status, 0, + sizeof(uint32_t) * (CAM_IFE_IRQ_REGISTERS_MAX + 1)); + for (i = 0; i < CAM_IFE_IRQ_REGISTERS_MAX; i++) + irq_status[i] = payload->irq_reg_val[i]; + + evt_info.hw_idx = camif_lite_node->hw_intf->hw_idx; + evt_info.res_id = camif_lite_node->res_id; + evt_info.res_type = camif_lite_node->res_type; + + CAM_DBG(CAM_ISP, + "VFE:%d CAMIF LITE:%d IRQ status_0: 0x%X status_1: 0x%X status_2: 0x%X", + evt_info.hw_idx, evt_info.res_id, + irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0], + irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1], + irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]); + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_lite_priv->reg_data->sof_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received SOF", + evt_info.hw_idx, evt_info.res_id); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + + if (camif_lite_priv->event_cb) + camif_lite_priv->event_cb(camif_lite_priv->priv, + CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_lite_priv->reg_data->epoch0_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received EPOCH", + evt_info.hw_idx, evt_info.res_id); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + + if (camif_lite_priv->event_cb) + camif_lite_priv->event_cb(camif_lite_priv->priv, + CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_lite_priv->reg_data->eof_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received EOF", + evt_info.hw_idx, evt_info.res_id); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + + if (camif_lite_priv->event_cb) + camif_lite_priv->event_cb(camif_lite_priv->priv, + CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + & camif_lite_priv->reg_data->error_irq_mask0) { + CAM_ERR(CAM_ISP, "VFE:%d Overflow", + camif_lite_node->hw_intf->hw_idx); + + evt_info.err_type = CAM_VFE_IRQ_STATUS_OVERFLOW; + + if (camif_lite_priv->event_cb) + camif_lite_priv->event_cb(camif_lite_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = + cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->bus_overflow_status); + + ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + + cam_vfe_camif_lite_print_status(irq_status, ret, is_ife_lite); + + if (camif_lite_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) + cam_vfe_camif_lite_reg_dump(camif_lite_node); + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { + CAM_ERR(CAM_ISP, "VFE:%d Violation", + camif_lite_node->hw_intf->hw_idx); + + evt_info.err_type = CAM_VFE_IRQ_STATUS_VIOLATION; + + if (camif_lite_priv->event_cb) + camif_lite_priv->event_cb(camif_lite_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_VIOLATION; + + cam_vfe_camif_lite_print_status(irq_status, ret, is_ife_lite); + + if (camif_lite_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) + cam_vfe_camif_lite_reg_dump(camif_lite_node); + } + + cam_vfe_camif_lite_put_evt_payload(camif_lite_priv, &payload); + + CAM_DBG(CAM_ISP, "returning status = %d", ret); + return ret; +} + +int cam_vfe_camif_lite_ver3_init( + struct cam_hw_intf *hw_intf, + struct cam_hw_soc_info *soc_info, + void *camif_lite_hw_info, + struct cam_isp_resource_node *camif_lite_node, + void *vfe_irq_controller) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_priv = NULL; + struct cam_vfe_camif_lite_ver3_hw_info *camif_lite_info = + camif_lite_hw_info; + int i = 0; + + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Init", + camif_lite_node->res_id, camif_lite_node->res_id); + + camif_lite_priv = kzalloc(sizeof(*camif_lite_priv), + GFP_KERNEL); + if (!camif_lite_priv) + return -ENOMEM; + + camif_lite_node->res_priv = camif_lite_priv; + + camif_lite_priv->mem_base = + soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base; + camif_lite_priv->camif_lite_reg = camif_lite_info->camif_lite_reg; + camif_lite_priv->common_reg = camif_lite_info->common_reg; + camif_lite_priv->reg_data = camif_lite_info->reg_data; + camif_lite_priv->hw_intf = hw_intf; + camif_lite_priv->soc_info = soc_info; + camif_lite_priv->vfe_irq_controller = vfe_irq_controller; + + camif_lite_node->init = NULL; + camif_lite_node->deinit = NULL; + camif_lite_node->start = cam_vfe_camif_lite_resource_start; + camif_lite_node->stop = cam_vfe_camif_lite_resource_stop; + camif_lite_node->process_cmd = cam_vfe_camif_lite_process_cmd; + camif_lite_node->top_half_handler = + cam_vfe_camif_lite_handle_irq_top_half; + camif_lite_node->bottom_half_handler = + cam_vfe_camif_lite_handle_irq_bottom_half; + + spin_lock_init(&camif_lite_priv->spin_lock); + INIT_LIST_HEAD(&camif_lite_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_LITE_EVT_MAX; i++) { + INIT_LIST_HEAD(&camif_lite_priv->evt_payload[i].list); + list_add_tail(&camif_lite_priv->evt_payload[i].list, + &camif_lite_priv->free_payload_list); + } + + return 0; +} + +int cam_vfe_camif_lite_ver3_deinit( + struct cam_isp_resource_node *camif_lite_node) +{ + struct cam_vfe_mux_camif_lite_data *camif_lite_priv = + camif_lite_node->res_priv; + int i = 0; + + CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Deinit", + camif_lite_node->hw_intf->hw_idx, camif_lite_node->res_id); + + INIT_LIST_HEAD(&camif_lite_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_LITE_EVT_MAX; i++) + INIT_LIST_HEAD(&camif_lite_priv->evt_payload[i].list); + + camif_lite_node->start = NULL; + camif_lite_node->stop = NULL; + camif_lite_node->process_cmd = NULL; + camif_lite_node->top_half_handler = NULL; + camif_lite_node->bottom_half_handler = NULL; + + camif_lite_node->res_priv = NULL; + + if (!camif_lite_priv) { + CAM_ERR(CAM_ISP, "Error. camif_priv is NULL"); + return -ENODEV; + } + + kfree(camif_lite_priv); + + return 0; +} + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h new file mode 100644 index 000000000000..ad8e44ef8e6c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_CAMIF_LITE_VER3_H_ +#define _CAM_VFE_CAMIF_LITE_VER3_H_ + +#include "cam_isp_hw.h" +#include "cam_vfe_top.h" + +#define CAM_VFE_RDI_VER2_MAX 4 +#define CAM_VFE_CAMIF_LITE_EVT_MAX 256 + +struct cam_vfe_camif_lite_ver3_reg { + uint32_t lite_hw_version; + uint32_t lite_hw_status; + uint32_t lite_module_config; + uint32_t lite_skip_period; + uint32_t lite_irq_subsample_pattern; + uint32_t lite_epoch_irq; + uint32_t lite_debug_1; + uint32_t lite_debug_0; + uint32_t lite_test_bus_ctrl; + uint32_t camif_lite_spare; + uint32_t reg_update_cmd; +}; + +struct cam_vfe_camif_lite_ver3_reg_data { + uint32_t extern_reg_update_shift; + uint32_t operating_mode_shift; + uint32_t input_mux_sel_shift; + uint32_t reg_update_cmd_data; + uint32_t epoch_line_cfg; + uint32_t sof_irq_mask; + uint32_t epoch0_irq_mask; + uint32_t epoch1_irq_mask; + uint32_t eof_irq_mask; + uint32_t error_irq_mask0; + uint32_t error_irq_mask2; + uint32_t subscribe_irq_mask1; + uint32_t enable_diagnostic_hw; +}; + +struct cam_vfe_camif_lite_ver3_hw_info { + struct cam_vfe_top_ver3_reg_offset_common *common_reg; + struct cam_vfe_camif_lite_ver3_reg *camif_lite_reg; + struct cam_vfe_camif_lite_ver3_reg_data *reg_data; +}; + +int cam_vfe_camif_lite_ver3_acquire_resource( + struct cam_isp_resource_node *camif_lite_res, + void *acquire_param); + +int cam_vfe_camif_lite_ver3_init( + struct cam_hw_intf *hw_intf, + struct cam_hw_soc_info *soc_info, + void *camif_lite_hw_info, + struct cam_isp_resource_node *camif_lite_node, + void *vfe_irq_controller); + +int cam_vfe_camif_lite_ver3_deinit( + struct cam_isp_resource_node *camif_node); + +#endif /* _CAM_VFE_CAMIF_LITE_VER3_H_ */ + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c new file mode 100644 index 000000000000..d641d647b65a --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -0,0 +1,881 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#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_irq_controller.h" +#include "cam_tasklet_util.h" +#include "cam_vfe_camif_ver2.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_camif_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_vfe_camif_ver2_reg *camif_reg; + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_camif_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; + + cam_hw_mgr_event_cb_func event_cb; + void *priv; + int irq_err_handle; + int irq_handle; + void *vfe_irq_controller; + struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_CAMIF_EVT_MAX]; + struct list_head free_payload_list; + spinlock_t spin_lock; + + 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 camif_debug; +}; + +static int cam_vfe_camif_get_evt_payload( + struct cam_vfe_mux_camif_data *camif_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&camif_priv->spin_lock); + if (list_empty(&camif_priv->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&camif_priv->free_payload_list, + struct cam_vfe_top_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); +done: + spin_unlock(&camif_priv->spin_lock); + return rc; +} + +static int cam_vfe_camif_put_evt_payload( + struct cam_vfe_mux_camif_data *camif_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!camif_priv) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&camif_priv->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, &camif_priv->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&camif_priv->spin_lock, flags); + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_camif_err_irq_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_node; + struct cam_vfe_mux_camif_data *camif_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + bool error_flag = false; + + CAM_DBG(CAM_ISP, "IRQ status_0 = %x, IRQ status_1 = %x", + th_payload->evt_status_arr[0], th_payload->evt_status_arr[1]); + + camif_node = th_payload->handler_priv; + camif_priv = camif_node->res_priv; + /* + * need to handle overflow condition here, otherwise irq storm + * will block everything + */ + if (th_payload->evt_status_arr[1] || (th_payload->evt_status_arr[0] & + camif_priv->reg_data->error_irq_mask0)) { + CAM_ERR(CAM_ISP, + "Camif Error: vfe:%d: IRQ STATUS_0=0x%x STATUS_1=0x%x", + camif_node->hw_intf->hw_idx, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + CAM_ERR(CAM_ISP, "Stopping further IRQ processing from vfe=%d", + camif_node->hw_intf->hw_idx); + cam_irq_controller_disable_irq(camif_priv->vfe_irq_controller, + camif_priv->irq_err_handle); + cam_irq_controller_clear_and_mask(evt_id, + camif_priv->vfe_irq_controller); + error_flag = true; + } + + rc = cam_vfe_camif_get_evt_payload(camif_priv, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "IRQ STATUS_0=0x%x STATUS_1=0x%x", + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->irq_reg_val[i] = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->violation_status); + + if (error_flag) + CAM_INFO(CAM_ISP, "Violation status = 0x%x", + evt_payload->irq_reg_val[2]); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_vfe_camif_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_camif_get_reg_update( + struct cam_isp_resource_node *camif_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_camif_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; + } + + 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 = camif_res->res_priv; + reg_val_pair[0] = rsrc_data->camif_reg->reg_update_cmd; + reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data; + CAM_DBG(CAM_ISP, "CAMIF reg_update_cmd %x offset %x", + 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_camif_ver2_acquire_resource( + struct cam_isp_resource_node *camif_res, + void *acquire_param) +{ + struct cam_vfe_mux_camif_data *camif_data; + struct cam_vfe_acquire_args *acquire_data; + + int rc = 0; + + camif_data = (struct cam_vfe_mux_camif_data *)camif_res->res_priv; + acquire_data = (struct cam_vfe_acquire_args *)acquire_param; + + rc = cam_vfe_camif_validate_pix_pattern( + acquire_data->vfe_in.in_port->test_pattern); + if (rc) + return rc; + + camif_data->sync_mode = acquire_data->vfe_in.sync_mode; + camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern; + camif_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode; + camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start; + camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop; + camif_data->first_line = acquire_data->vfe_in.in_port->line_start; + camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; + camif_data->event_cb = acquire_data->event_cb; + camif_data->priv = acquire_data->priv; + + CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d", + camif_res->hw_intf->hw_idx, + camif_data->pix_pattern, camif_data->dsp_mode); + return rc; +} + +static int cam_vfe_camif_resource_init( + struct cam_isp_resource_node *camif_res, + void *init_args, uint32_t arg_size) +{ + struct cam_vfe_mux_camif_data *camif_data; + struct cam_hw_soc_info *soc_info; + int rc = 0; + + if (!camif_res) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + camif_data = (struct cam_vfe_mux_camif_data *)camif_res->res_priv; + + soc_info = camif_data->soc_info; + + if ((camif_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) && + (camif_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_camif_resource_deinit( + struct cam_isp_resource_node *camif_res, + void *init_args, uint32_t arg_size) +{ + struct cam_vfe_mux_camif_data *camif_data; + struct cam_hw_soc_info *soc_info; + int rc = 0; + + if (!camif_res) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + camif_data = (struct cam_vfe_mux_camif_data *)camif_res->res_priv; + + soc_info = camif_data->soc_info; + + if ((camif_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) && + (camif_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_camif_resource_start( + struct cam_isp_resource_node *camif_res) +{ + struct cam_vfe_mux_camif_data *rsrc_data; + uint32_t val = 0; + uint32_t epoch0_irq_mask; + uint32_t epoch1_irq_mask; + uint32_t computed_epoch_line_cfg; + int rc = 0; + uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + struct cam_vfe_soc_private *soc_private; + + if (!camif_res) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + if (camif_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Error! Invalid camif res res_state:%d", + camif_res->res_state); + return -EINVAL; + } + + rsrc_data = (struct cam_vfe_mux_camif_data *)camif_res->res_priv; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->error_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->error_irq_mask1; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->subscribe_irq_mask0; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->subscribe_irq_mask1; + + 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); + 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); + } + + cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg); + + CAM_DBG(CAM_ISP, "hw id:%d core_cfg val:%d", camif_res->hw_intf->hw_idx, + 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 */ + 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) + + 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->camif_reg->epoch_irq); + CAM_DBG(CAM_ISP, "first_line: %u\n" + "last_line: %u\n" + "epoch_line_cfg: 0x%x", + rsrc_data->first_line, + rsrc_data->last_line, + computed_epoch_line_cfg); + break; + } + + camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Reg Update */ + cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, + rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd); + CAM_DBG(CAM_ISP, "hw id:%d RUP val:%d", camif_res->hw_intf->hw_idx, + 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; + + if (rsrc_data->camif_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->camif_reg->vfe_diag_config); + val |= rsrc_data->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->camif_reg->vfe_diag_config); + } + + if (!rsrc_data->irq_handle) { + rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_0, + irq_mask, + camif_res, + camif_res->top_half_handler, + camif_res->bottom_half_handler, + camif_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_handle < 1) { + CAM_ERR(CAM_ISP, "IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_handle = 0; + } + } + + if (!rsrc_data->irq_err_handle) { + rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + err_irq_mask, + camif_res, + cam_vfe_camif_err_irq_top_half, + camif_res->bottom_half_handler, + camif_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { + CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_err_handle = 0; + } + } + + CAM_DBG(CAM_ISP, "Start Camif IFE %d Done", camif_res->hw_intf->hw_idx); + return 0; +} + +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_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 < 0x1160; 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); + } + + 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); + } + + 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, + "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 || + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + CAM_INFO(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); + + } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { + 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); + + 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); + } + + return 0; +} + +static int cam_vfe_camif_resource_stop( + struct cam_isp_resource_node *camif_res) +{ + struct cam_vfe_mux_camif_data *camif_priv; + struct cam_vfe_camif_ver2_reg *camif_reg; + int rc = 0; + uint32_t val = 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; + camif_reg = camif_priv->camif_reg; + + if ((camif_priv->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) && + (camif_priv->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) { + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->common_reg->core_cfg); + val &= (~(1 << camif_priv->reg_data->dsp_en_shift)); + cam_io_w_mb(val, camif_priv->mem_base + + camif_priv->common_reg->core_cfg); + } + + if (camif_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + camif_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->camif_reg->vfe_diag_config); + if (val & camif_priv->reg_data->enable_diagnostic_hw) { + val &= ~camif_priv->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, camif_priv->mem_base + + camif_priv->camif_reg->vfe_diag_config); + } + + if (camif_priv->irq_handle) { + cam_irq_controller_unsubscribe_irq( + camif_priv->vfe_irq_controller, camif_priv->irq_handle); + camif_priv->irq_handle = 0; + } + + if (camif_priv->irq_err_handle) { + cam_irq_controller_unsubscribe_irq( + camif_priv->vfe_irq_controller, + camif_priv->irq_err_handle); + camif_priv->irq_err_handle = 0; + } + + return rc; +} + +static int cam_vfe_camif_sof_irq_debug( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_data *camif_priv; + uint32_t *enable_sof_irq = (uint32_t *)cmd_args; + + camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + + if (*enable_sof_irq == 1) + camif_priv->enable_sof_irq_debug = true; + else + camif_priv->enable_sof_irq_debug = false; + + return 0; +} + +static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = -EINVAL; + struct cam_vfe_mux_camif_data *camif_priv = NULL; + + 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_camif_get_reg_update(rsrc_node, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG: + rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args); + break; + case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: + camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + camif_priv->camif_debug = *((uint32_t *)cmd_args); + break; + default: + CAM_ERR(CAM_ISP, + "unsupported process command:%d", cmd_type); + break; + } + + return rc; +} + +static int cam_vfe_camif_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_node; + struct cam_vfe_mux_camif_data *camif_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + + camif_node = th_payload->handler_priv; + camif_priv = camif_node->res_priv; + + CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]); + CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]); + + rc = cam_vfe_camif_get_evt_payload(camif_priv, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "IRQ status0=0x%x status1=0x%x", + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + int ret = CAM_VFE_IRQ_STATUS_MAX; + struct cam_isp_resource_node *camif_node; + struct cam_vfe_mux_camif_data *camif_priv; + struct cam_vfe_top_irq_evt_payload *payload; + struct cam_isp_hw_event_info evt_info; + uint32_t irq_status0; + uint32_t irq_status1; + uint32_t val; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, "Invalid params"); + return ret; + } + + camif_node = handler_priv; + camif_priv = camif_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]; + + evt_info.hw_idx = camif_node->hw_intf->hw_idx; + evt_info.res_id = camif_node->res_id; + evt_info.res_type = camif_node->res_type; + + CAM_DBG(CAM_ISP, "irq_status_0 = 0x%x irq_status_1 = 0x%x", + irq_status0, irq_status1); + + if (irq_status0 & camif_priv->reg_data->sof_irq_mask) { + if ((camif_priv->enable_sof_irq_debug) && + (camif_priv->irq_debug_cnt <= + CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "Received SOF"); + + camif_priv->irq_debug_cnt++; + if (camif_priv->irq_debug_cnt == + CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) { + camif_priv->enable_sof_irq_debug = + false; + camif_priv->irq_debug_cnt = 0; + } + } else + CAM_DBG(CAM_ISP, "Received SOF"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_priv->reg_data->epoch0_irq_mask) { + CAM_DBG(CAM_ISP, "Received EPOCH"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_priv->reg_data->reg_update_irq_mask) { + CAM_DBG(CAM_ISP, "Received REG_UPDATE_ACK"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_priv->reg_data->eof_irq_mask) { + CAM_DBG(CAM_ISP, "Received EOF"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status0 & camif_priv->reg_data->error_irq_mask0) { + CAM_DBG(CAM_ISP, "Received ERROR"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + CAM_INFO(CAM_ISP, "Violation status = %x", + payload->irq_reg_val[2]); + + ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) + cam_vfe_camif_reg_dump(camif_node->res_priv); + } + + if (irq_status1 & camif_priv->reg_data->error_irq_mask1) { + CAM_DBG(CAM_ISP, "Received ERROR"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + CAM_INFO(CAM_ISP, "Violation status = %x", + payload->irq_reg_val[2]); + + ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) + cam_vfe_camif_reg_dump(camif_node->res_priv); + } + + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r(camif_priv->mem_base + + camif_priv->camif_reg->vfe_diag_sensor_status); + CAM_DBG(CAM_ISP, "VFE_DIAG_SENSOR_STATUS: 0x%x", + camif_priv->mem_base, val); + } + + cam_vfe_camif_put_evt_payload(camif_priv, &payload); + + CAM_DBG(CAM_ISP, "returning status = %d", ret); + return ret; +} + +int cam_vfe_camif_ver2_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, + void *vfe_irq_controller) +{ + struct cam_vfe_mux_camif_data *camif_priv = NULL; + struct cam_vfe_camif_ver2_hw_info *camif_info = camif_hw_info; + int i = 0; + + camif_priv = kzalloc(sizeof(struct cam_vfe_mux_camif_data), + GFP_KERNEL); + if (!camif_priv) { + CAM_DBG(CAM_ISP, "Error! Failed to alloc for camif_priv"); + return -ENOMEM; + } + + camif_node->res_priv = camif_priv; + + camif_priv->mem_base = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base; + camif_priv->camif_reg = camif_info->camif_reg; + camif_priv->common_reg = camif_info->common_reg; + camif_priv->reg_data = camif_info->reg_data; + camif_priv->hw_intf = hw_intf; + camif_priv->soc_info = soc_info; + camif_priv->vfe_irq_controller = vfe_irq_controller; + + camif_node->init = cam_vfe_camif_resource_init; + camif_node->deinit = cam_vfe_camif_resource_deinit; + camif_node->start = cam_vfe_camif_resource_start; + camif_node->stop = cam_vfe_camif_resource_stop; + camif_node->process_cmd = cam_vfe_camif_process_cmd; + camif_node->top_half_handler = cam_vfe_camif_handle_irq_top_half; + camif_node->bottom_half_handler = cam_vfe_camif_handle_irq_bottom_half; + + spin_lock_init(&camif_priv->spin_lock); + INIT_LIST_HEAD(&camif_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_EVT_MAX; i++) { + INIT_LIST_HEAD(&camif_priv->evt_payload[i].list); + list_add_tail(&camif_priv->evt_payload[i].list, + &camif_priv->free_payload_list); + } + + return 0; +} + +int cam_vfe_camif_ver2_deinit( + struct cam_isp_resource_node *camif_node) +{ + struct cam_vfe_mux_camif_data *camif_priv = camif_node->res_priv; + int i = 0; + + INIT_LIST_HEAD(&camif_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_EVT_MAX; i++) + INIT_LIST_HEAD(&camif_priv->evt_payload[i].list); + + camif_node->start = NULL; + camif_node->stop = NULL; + camif_node->process_cmd = NULL; + camif_node->top_half_handler = NULL; + camif_node->bottom_half_handler = NULL; + + camif_node->res_priv = NULL; + + if (!camif_priv) { + CAM_ERR(CAM_ISP, "Error! camif_priv is NULL"); + return -ENODEV; + } + + kfree(camif_priv); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h new file mode 100644 index 000000000000..f071a0627bbc --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_CAMIF_VER2_H_ +#define _CAM_VFE_CAMIF_VER2_H_ + +#include "cam_isp_hw.h" +#include "cam_vfe_top.h" + +struct cam_vfe_camif_ver2_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; +}; + +struct cam_vfe_camif_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 subscribe_irq_mask0; + uint32_t subscribe_irq_mask1; + + uint32_t enable_diagnostic_hw; +}; + +struct cam_vfe_camif_ver2_hw_info { + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_camif_ver2_reg *camif_reg; + struct cam_vfe_camif_reg_data *reg_data; +}; + +int cam_vfe_camif_ver2_acquire_resource( + struct cam_isp_resource_node *camif_res, + void *acquire_param); + +int cam_vfe_camif_ver2_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, + void *vfe_irq_controller); + +int cam_vfe_camif_ver2_deinit( + struct cam_isp_resource_node *camif_node); + +#endif /* _CAM_VFE_CAMIF_VER2_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c new file mode 100644 index 000000000000..450d03428c63 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -0,0 +1,1299 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#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_ver3.h" +#include "cam_irq_controller.h" +#include "cam_tasklet_util.h" +#include "cam_vfe_camif_ver3.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_camif_ver3_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_vfe_camif_ver3_pp_clc_reg *camif_reg; + struct cam_vfe_top_ver3_reg_offset_common *common_reg; + struct cam_vfe_camif_ver3_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; + struct cam_vfe_camif_common_cfg cam_common_cfg; + + cam_hw_mgr_event_cb_func event_cb; + void *priv; + int irq_err_handle; + int irq_handle; + void *vfe_irq_controller; + struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_CAMIF_EVT_MAX]; + struct list_head free_payload_list; + spinlock_t spin_lock; + + 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 camif_debug; +}; + +static int cam_vfe_camif_ver3_get_evt_payload( + struct cam_vfe_mux_camif_ver3_data *camif_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&camif_priv->spin_lock); + if (list_empty(&camif_priv->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free CAMIF event payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&camif_priv->free_payload_list, + struct cam_vfe_top_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); +done: + spin_unlock(&camif_priv->spin_lock); + return rc; +} + +static int cam_vfe_camif_ver3_put_evt_payload( + struct cam_vfe_mux_camif_ver3_data *camif_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!camif_priv) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&camif_priv->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, &camif_priv->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&camif_priv->spin_lock, flags); + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_camif_ver3_err_irq_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_node; + struct cam_vfe_mux_camif_ver3_data *camif_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + bool error_flag = false; + + camif_node = th_payload->handler_priv; + camif_priv = camif_node->res_priv; + /* + * need to handle overflow condition here, otherwise irq storm + * will block everything + */ + if (th_payload->evt_status_arr[2] || (th_payload->evt_status_arr[0] & + camif_priv->reg_data->error_irq_mask0)) { + CAM_ERR(CAM_ISP, + "VFE:%d CAMIF Err IRQ status_0: 0x%X status_2: 0x%X", + camif_node->hw_intf->hw_idx, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[2]); + CAM_ERR(CAM_ISP, "Stopping further IRQ processing from VFE:%d", + camif_node->hw_intf->hw_idx); + cam_irq_controller_disable_irq(camif_priv->vfe_irq_controller, + camif_priv->irq_err_handle); + cam_irq_controller_clear_and_mask(evt_id, + camif_priv->vfe_irq_controller); + error_flag = true; + } + + rc = cam_vfe_camif_ver3_get_evt_payload(camif_priv, &evt_payload); + if (rc) + return rc; + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->irq_reg_val[i] = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->violation_status); + + if (error_flag) + CAM_INFO(CAM_ISP, "Violation status = 0x%X", + evt_payload->irq_reg_val[i]); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_vfe_camif_ver3_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_camif_ver3_get_reg_update( + struct cam_isp_resource_node *camif_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_camif_ver3_data *rsrc_data = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Invalid arg size: %d expected:%ld", + arg_size, sizeof(struct cam_isp_hw_get_cmd_update)); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res) { + CAM_ERR(CAM_ISP, "Invalid args: %pK", cdm_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; + } + + 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*4)); + return -EINVAL; + } + + rsrc_data = camif_res->res_priv; + reg_val_pair[0] = rsrc_data->camif_reg->reg_update_cmd; + reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data; + CAM_DBG(CAM_ISP, "VFE:%d CAMIF reg_update_cmd 0x%X offset 0x%X", + camif_res->hw_intf->hw_idx, + 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_camif_ver3_acquire_resource( + struct cam_isp_resource_node *camif_res, + void *acquire_param) +{ + struct cam_vfe_mux_camif_ver3_data *camif_data; + struct cam_vfe_acquire_args *acquire_data; + int rc = 0; + + camif_data = (struct cam_vfe_mux_camif_ver3_data *) + camif_res->res_priv; + acquire_data = (struct cam_vfe_acquire_args *)acquire_param; + + rc = cam_vfe_camif_ver3_validate_pix_pattern( + acquire_data->vfe_in.in_port->test_pattern); + + if (rc) { + CAM_ERR(CAM_ISP, "Validate pix pattern failed, rc = %d", rc); + return rc; + } + + camif_data->sync_mode = acquire_data->vfe_in.sync_mode; + camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern; + camif_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode; + camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start; + camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop; + camif_data->first_line = acquire_data->vfe_in.in_port->line_start; + camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; + camif_data->event_cb = acquire_data->event_cb; + camif_data->priv = acquire_data->priv; + + CAM_DBG(CAM_ISP, "VFE:%d CAMIF pix_pattern:%d dsp_mode=%d", + camif_res->hw_intf->hw_idx, + camif_data->pix_pattern, camif_data->dsp_mode); + + return rc; +} + +static int cam_vfe_camif_ver3_resource_init( + struct cam_isp_resource_node *camif_res, + void *init_args, uint32_t arg_size) +{ + struct cam_vfe_mux_camif_ver3_data *camif_data; + struct cam_hw_soc_info *soc_info; + int rc = 0; + + if (!camif_res) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + camif_data = (struct cam_vfe_mux_camif_ver3_data *) + camif_res->res_priv; + + soc_info = camif_data->soc_info; + + if ((camif_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) && + (camif_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, rc = %d", rc); + } + + /* All auto clock gating disabled by default */ + CAM_INFO(CAM_ISP, "overriding clock gating"); + cam_io_w_mb(0xFFFFFFFF, camif_data->mem_base + + camif_data->common_reg->core_cgc_ovd_0); + + cam_io_w_mb(0xFF, camif_data->mem_base + + camif_data->common_reg->core_cgc_ovd_1); + + cam_io_w_mb(0x1, camif_data->mem_base + + camif_data->common_reg->ahb_cgc_ovd); + + cam_io_w_mb(0x1, camif_data->mem_base + + camif_data->common_reg->noc_cgc_ovd); + + return rc; +} + +static int cam_vfe_camif_ver3_resource_deinit( + struct cam_isp_resource_node *camif_res, + void *init_args, uint32_t arg_size) +{ + struct cam_vfe_mux_camif_ver3_data *camif_data; + struct cam_hw_soc_info *soc_info; + int rc = 0; + + if (!camif_res) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + camif_data = (struct cam_vfe_mux_camif_ver3_data *) + camif_res->res_priv; + + soc_info = camif_data->soc_info; + + if ((camif_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) && + (camif_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_camif_ver3_resource_start( + struct cam_isp_resource_node *camif_res) +{ + struct cam_vfe_mux_camif_ver3_data *rsrc_data; + uint32_t val = 0; + uint32_t epoch0_line_cfg; + uint32_t epoch1_line_cfg; + uint32_t computed_epoch_line_cfg; + int rc = 0; + uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + struct cam_vfe_soc_private *soc_private; + + if (!camif_res) { + CAM_ERR(CAM_ISP, "Error, Invalid input arguments"); + return -EINVAL; + } + + if (camif_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Error, Invalid camif res res_state:%d", + camif_res->res_state); + return -EINVAL; + } + + memset(err_irq_mask, 0, sizeof(err_irq_mask)); + memset(irq_mask, 0, sizeof(irq_mask)); + + rsrc_data = (struct cam_vfe_mux_camif_ver3_data *)camif_res->res_priv; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->error_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = + rsrc_data->reg_data->error_irq_mask2; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->subscribe_irq_mask1; + + 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); + val |= (1 << rsrc_data->reg_data->pp_camif_cfg_en_shift); + val |= (1 << rsrc_data->reg_data->pp_camif_cfg_ife_out_en_shift); + cam_io_w_mb(val, + rsrc_data->mem_base + rsrc_data->camif_reg->module_cfg); + CAM_DBG(CAM_ISP, "write module_cfg val = 0x%X", val); + + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_0); + + /* AF stitching by hw disabled by default + * PP CAMIF currently operates only in offline mode + */ + + 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->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + val |= (1 << rsrc_data->reg_data->pp_extern_reg_update_shift); + + if ((rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) || + (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_MASTER)) + val |= (1 << rsrc_data->reg_data->dual_ife_pix_en_shift); + + val |= (~rsrc_data->cam_common_cfg.vid_ds16_r2pd & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_VID_DS16_R2PD; + val |= (~rsrc_data->cam_common_cfg.vid_ds4_r2pd & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_VID_DS4_R2PD; + val |= (~rsrc_data->cam_common_cfg.disp_ds16_r2pd & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_DISP_DS16_R2PD; + val |= (~rsrc_data->cam_common_cfg.disp_ds4_r2pd & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_DISP_DS4_R2PD; + val |= (rsrc_data->cam_common_cfg.dsp_streaming_tap_point & 0x3) << + CAM_SHIFT_TOP_CORE_CFG_DSP_STREAMING; + val |= (rsrc_data->cam_common_cfg.ihist_src_sel & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_STATS_IHIST; + val |= (rsrc_data->cam_common_cfg.hdr_be_src_sel & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BE; + val |= (rsrc_data->cam_common_cfg.hdr_bhist_src_sel & 0x1) << + CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BHIST; + val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) << + CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP; + + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_0); + + /* epoch config */ + switch (soc_private->cpas_version) { + case CAM_CPAS_TITAN_480_V100: + epoch0_line_cfg = ((rsrc_data->last_line - + rsrc_data->first_line) / 4) + + rsrc_data->first_line; + /* epoch line cfg will still be configured at midpoint of the + * frame width. We use '/ 4' instead of '/ 2' + * cause it is multipixel path + */ + epoch1_line_cfg = rsrc_data->reg_data->epoch_line_cfg & + 0xFFFF; + computed_epoch_line_cfg = (epoch1_line_cfg << 16) | + epoch0_line_cfg; + cam_io_w_mb(computed_epoch_line_cfg, + rsrc_data->mem_base + + rsrc_data->camif_reg->epoch_irq_cfg); + CAM_DBG(CAM_ISP, "epoch_line_cfg: 0x%X", + computed_epoch_line_cfg); + break; + default: + CAM_ERR(CAM_ISP, "Hardware version not proper: 0x%X", + soc_private->cpas_version); + return -EINVAL; + break; + } + + camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Reg Update */ + cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, + rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd); + CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X", + camif_res->hw_intf->hw_idx, + 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; + + if (rsrc_data->camif_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->common_reg->diag_config); + val |= rsrc_data->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->diag_config); + } + + if (!rsrc_data->irq_handle) { + rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_0, + irq_mask, + camif_res, + camif_res->top_half_handler, + camif_res->bottom_half_handler, + camif_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_handle < 1) { + CAM_ERR(CAM_ISP, "IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_handle = 0; + } + } + + if (!rsrc_data->irq_err_handle) { + rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + err_irq_mask, + camif_res, + cam_vfe_camif_ver3_err_irq_top_half, + camif_res->bottom_half_handler, + camif_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { + CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_err_handle = 0; + } + } + + CAM_DBG(CAM_ISP, "VFE:%d CAMIF Start Done", camif_res->hw_intf->hw_idx); + return 0; +} + +static int cam_vfe_camif_ver3_reg_dump( + struct cam_isp_resource_node *camif_res) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv; + 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_ver3_data *)camif_res->res_priv; + + CAM_INFO(CAM_ISP, "IFE:%d TOP", camif_res->hw_intf->hw_idx); + for (offset = 0x0; offset <= 0x1FC; offset += 0x4) { + if (offset == 0x1C || offset == 0x34 || + offset == 0x38 || offset == 0x90) + continue; + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val); + } + + CAM_INFO(CAM_ISP, "IFE:%d PP CLC PREPROCESS", + camif_res->hw_intf->hw_idx); + for (offset = 0x2200; offset <= 0x23FC; offset += 0x4) { + if (offset == 0x2208) + offset = 0x2260; + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val); + if (offset == 0x2260) + offset = 0x23F4; + } + + CAM_INFO(CAM_ISP, "IFE:%d PP CLC CAMIF", camif_res->hw_intf->hw_idx); + for (offset = 0x2600; offset <= 0x27FC; offset += 0x4) { + if (offset == 0x2608) + offset = 0x2660; + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val); + if (offset == 0x2660) + offset = 0x2664; + else if (offset == 0x2680) + offset = 0x27EC; + } + + CAM_INFO(CAM_ISP, "IFE:%d PP CLC Modules", camif_res->hw_intf->hw_idx); + for (offset = 0x2800; offset <= 0x8FFC; 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_INFO(CAM_ISP, "IFE:%d BUS WR", camif_res->hw_intf->hw_idx); + for (offset = 0xAA00; offset <= 0xAADC; offset += 0x4) { + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_DBG(CAM_ISP, "offset 0x%X value 0x%X", offset, val); + } + + for (wm_idx = 0; wm_idx <= 25; wm_idx++) { + for (offset = 0xAC00 + 0x100 * wm_idx; + offset < 0xAC84 + 0x100 * wm_idx; 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); + } + } + + return 0; +} + +static int cam_vfe_camif_ver3_resource_stop( + struct cam_isp_resource_node *camif_res) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv; + struct cam_vfe_camif_ver3_pp_clc_reg *camif_reg; + int rc = 0; + uint32_t val = 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_ver3_data *)camif_res->res_priv; + camif_reg = camif_priv->camif_reg; + + if ((camif_priv->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) && + (camif_priv->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) { + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->common_reg->core_cfg_0); + val &= (~(1 << camif_priv->reg_data->dsp_en_shift)); + cam_io_w_mb(val, camif_priv->mem_base + + camif_priv->common_reg->core_cfg_0); + } + + if (camif_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + camif_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->common_reg->diag_config); + if (val & camif_priv->reg_data->enable_diagnostic_hw) { + val &= ~camif_priv->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, camif_priv->mem_base + + camif_priv->common_reg->diag_config); + } + + if (camif_priv->irq_handle) { + cam_irq_controller_unsubscribe_irq( + camif_priv->vfe_irq_controller, camif_priv->irq_handle); + camif_priv->irq_handle = 0; + } + + if (camif_priv->irq_err_handle) { + cam_irq_controller_unsubscribe_irq( + camif_priv->vfe_irq_controller, + camif_priv->irq_err_handle); + camif_priv->irq_err_handle = 0; + } + + return rc; +} + +static int cam_vfe_camif_ver3_core_config( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv; + struct cam_vfe_core_config_args *vfe_core_cfg = + (struct cam_vfe_core_config_args *)cmd_args; + + camif_priv = + (struct cam_vfe_mux_camif_ver3_data *)rsrc_node->res_priv; + camif_priv->cam_common_cfg.vid_ds16_r2pd = + vfe_core_cfg->core_config.vid_ds16_r2pd; + camif_priv->cam_common_cfg.vid_ds4_r2pd = + vfe_core_cfg->core_config.vid_ds4_r2pd; + camif_priv->cam_common_cfg.disp_ds16_r2pd = + vfe_core_cfg->core_config.disp_ds16_r2pd; + camif_priv->cam_common_cfg.disp_ds4_r2pd = + vfe_core_cfg->core_config.disp_ds4_r2pd; + camif_priv->cam_common_cfg.dsp_streaming_tap_point = + vfe_core_cfg->core_config.dsp_streaming_tap_point; + camif_priv->cam_common_cfg.ihist_src_sel = + vfe_core_cfg->core_config.ihist_src_sel; + camif_priv->cam_common_cfg.hdr_be_src_sel = + vfe_core_cfg->core_config.hdr_be_src_sel; + camif_priv->cam_common_cfg.hdr_bhist_src_sel = + vfe_core_cfg->core_config.hdr_bhist_src_sel; + camif_priv->cam_common_cfg.input_mux_sel_pdaf = + vfe_core_cfg->core_config.input_mux_sel_pdaf; + camif_priv->cam_common_cfg.input_mux_sel_pp = + vfe_core_cfg->core_config.input_mux_sel_pp; + + return 0; +} + +static int cam_vfe_camif_ver3_sof_irq_debug( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv; + uint32_t *enable_sof_irq = (uint32_t *)cmd_args; + + camif_priv = + (struct cam_vfe_mux_camif_ver3_data *)rsrc_node->res_priv; + + if (*enable_sof_irq == 1) + camif_priv->enable_sof_irq_debug = true; + else + camif_priv->enable_sof_irq_debug = false; + + return 0; +} + +static int cam_vfe_camif_ver3_process_cmd( + struct cam_isp_resource_node *rsrc_node, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = -EINVAL; + struct cam_vfe_mux_camif_ver3_data *camif_priv = NULL; + + if (!rsrc_node || !cmd_args) { + CAM_ERR(CAM_ISP, + "Invalid input arguments rsesource node:%pK cmd_args:%pK", + rsrc_node, cmd_args); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + rc = cam_vfe_camif_ver3_get_reg_update(rsrc_node, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG: + rc = cam_vfe_camif_ver3_sof_irq_debug(rsrc_node, cmd_args); + break; + case CAM_ISP_HW_CMD_CORE_CONFIG: + rc = cam_vfe_camif_ver3_core_config(rsrc_node, cmd_args); + break; + case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: + camif_priv = (struct cam_vfe_mux_camif_ver3_data *) + rsrc_node->res_priv; + camif_priv->camif_debug = *((uint32_t *)cmd_args); + break; + default: + CAM_ERR(CAM_ISP, + "unsupported process command:%d", cmd_type); + break; + } + + return rc; +} + +static void cam_vfe_camif_ver3_print_status(uint32_t *status, + int err_type) +{ + uint32_t violation_mask = 0x3F, module_id = 0; + uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; + + if (!status) { + CAM_ERR(CAM_ISP, "Invalid params"); + return; + } + + bus_overflow_status = status[CAM_IFE_IRQ_REGISTERS_MAX]; + status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; + status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) { + if (status_0 & 0x0200) + CAM_INFO(CAM_ISP, "DSP OVERFLOW"); + + if (status_0 & 0x2000000) + CAM_INFO(CAM_ISP, "PIXEL PIPE FRAME DROP"); + + if (status_0 & 0x80000000) + CAM_INFO(CAM_ISP, "PIXEL PIPE OVERFLOW"); + } + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && bus_overflow_status) { + if (bus_overflow_status & 0x01) + CAM_INFO(CAM_ISP, "VID Y 1:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x02) + CAM_INFO(CAM_ISP, "VID C 1:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x04) + CAM_INFO(CAM_ISP, "VID YC 4:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x08) + CAM_INFO(CAM_ISP, "VID YC 16:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x010) + CAM_INFO(CAM_ISP, "DISP Y 1:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x020) + CAM_INFO(CAM_ISP, "DISP C 1:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x040) + CAM_INFO(CAM_ISP, "DISP YC 4:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x080) + CAM_INFO(CAM_ISP, "DISP YC 16:1 BUS OVERFLOW"); + + if (bus_overflow_status & 0x0100) + CAM_INFO(CAM_ISP, "FD Y BUS OVERFLOW"); + + if (bus_overflow_status & 0x0200) + CAM_INFO(CAM_ISP, "FD C BUS OVERFLOW"); + + if (bus_overflow_status & 0x0400) + CAM_INFO(CAM_ISP, "PIXEL RAW DUMP BUS OVERFLOW"); + + if (bus_overflow_status & 0x01000) + CAM_INFO(CAM_ISP, "STATS HDR BE BUS OVERFLOW"); + + if (bus_overflow_status & 0x02000) + CAM_INFO(CAM_ISP, "STATS HDR BHIST BUS OVERFLOW"); + + if (bus_overflow_status & 0x04000) + CAM_INFO(CAM_ISP, "STATS TINTLESS BG BUS OVERFLOW"); + + if (bus_overflow_status & 0x08000) + CAM_INFO(CAM_ISP, "STATS AWB BG BUS OVERFLOW"); + + if (bus_overflow_status & 0x010000) + CAM_INFO(CAM_ISP, "STATS BHIST BUS OVERFLOW"); + + if (bus_overflow_status & 0x020000) + CAM_INFO(CAM_ISP, "STATS RS BUS OVERFLOW"); + + if (bus_overflow_status & 0x040000) + CAM_INFO(CAM_ISP, "STATS CS BUS OVERFLOW"); + + if (bus_overflow_status & 0x080000) + CAM_INFO(CAM_ISP, "STATS IHIST BUS OVERFLOW"); + + if (bus_overflow_status & 0x0100000) + CAM_INFO(CAM_ISP, "STATS BAF BUS OVERFLOW"); + + if (bus_overflow_status & 0x0200000) + CAM_INFO(CAM_ISP, "PDAF BUS OVERFLOW"); + + return; + } + + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { + CAM_INFO(CAM_ISP, "PIXEL PIPE Module hang"); + /* print debug registers */ + return; + } + + if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { + if (status_2 & 0x080) + CAM_INFO(CAM_ISP, "DSP IFE PROTOCOL VIOLATION"); + + if (status_2 & 0x0100) + CAM_INFO(CAM_ISP, "IFE DSP TX PROTOCOL VIOLATION"); + + if (status_2 & 0x0200) + CAM_INFO(CAM_ISP, "DSP IFE RX PROTOCOL VIOLATION"); + + if (status_2 & 0x0400) + CAM_INFO(CAM_ISP, "PP PREPROCESS VIOLATION"); + + if (status_2 & 0x0800) + CAM_INFO(CAM_ISP, "PP CAMIF VIOLATION"); + + if (status_2 & 0x01000) + CAM_INFO(CAM_ISP, "PP VIOLATION"); + + if (status_2 & 0x0100000) + CAM_INFO(CAM_ISP, + "DSP_TX_VIOLATION:overflow on DSP interface TX path FIFO"); + + if (status_2 & 0x0200000) + CAM_INFO(CAM_ISP, + "DSP_RX_VIOLATION:overflow on DSP interface RX path FIFO"); + + if (status_2 & 0x10000000) + CAM_INFO(CAM_ISP, "DSP ERROR VIOLATION"); + + if (status_2 & 0x20000000) + CAM_INFO(CAM_ISP, + "DIAG VIOLATION: HBI is less than the minimum required HBI"); + } + + if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION && + status[CAM_IFE_IRQ_VIOLATION_STATUS]) { + module_id = + violation_mask & status[CAM_IFE_IRQ_VIOLATION_STATUS]; + CAM_INFO(CAM_ISP, "PIXEL PIPE VIOLATION Module ID:%d", + module_id); + + switch (module_id) { + case 0: + CAM_INFO(CAM_ISP, "DEMUX"); + break; + case 1: + CAM_INFO(CAM_ISP, "CHROMA_UP"); + break; + case 2: + CAM_INFO(CAM_ISP, "PEDESTAL"); + break; + case 3: + CAM_INFO(CAM_ISP, "LINEARIZATION"); + break; + case 4: + CAM_INFO(CAM_ISP, "BPC_PDPC"); + break; + case 5: + CAM_INFO(CAM_ISP, "HDR_BINCORRECT"); + break; + case 6: + CAM_INFO(CAM_ISP, "ABF"); + break; + case 7: + CAM_INFO(CAM_ISP, "LSC"); + break; + case 8: + CAM_INFO(CAM_ISP, "DEMOSAIC"); + break; + case 9: + CAM_INFO(CAM_ISP, "COLOR_CORRECT"); + break; + case 10: + CAM_INFO(CAM_ISP, "GTM"); + break; + case 11: + CAM_INFO(CAM_ISP, "GLUT"); + break; + case 12: + CAM_INFO(CAM_ISP, "COLOR_XFORM"); + break; + case 13: + CAM_INFO(CAM_ISP, "CROP_RND_CLAMP_PIXEL_RAW_OUT"); + break; + case 14: + CAM_INFO(CAM_ISP, "DOWNSCALE_MN_Y_FD_OUT"); + break; + case 15: + CAM_INFO(CAM_ISP, "DOWNSCALE_MN_C_FD_OUT"); + break; + case 16: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_MN_Y_FD_OUT"); + break; + case 17: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_MN_C_FD_OUT"); + break; + case 18: + CAM_INFO(CAM_ISP, "DOWNSCALE_MN_Y_DISP_OUT"); + break; + case 19: + CAM_INFO(CAM_ISP, "DOWNSCALE_MN_C_DISP_OUT"); + break; + case 20: + CAM_INFO(CAM_ISP, + "module: CROP_RND_CLAMP_POST_DOWNSCALE_MN_Y_DISP_OUT"); + break; + case 21: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_MN_C_DISP_OUT"); + break; + case 22: + CAM_INFO(CAM_ISP, "DOWNSCALE_4TO1_Y_DISP_DS4_OUT"); + break; + case 23: + CAM_INFO(CAM_ISP, "DOWNSCALE_4TO1_C_DISP_DS4_OUT"); + break; + case 24: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_4TO1_Y_DISP_DS4_OUT"); + break; + case 25: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_4TO1_C_DISP_DS4_OUT"); + break; + case 26: + CAM_INFO(CAM_ISP, "DOWNSCALE_4TO1_Y_DISP_DS16_OUT"); + break; + case 27: + CAM_INFO(CAM_ISP, "DOWNSCALE_4TO1_C_DISP_DS16_OUT"); + break; + case 28: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_4TO1_Y_DISP_DS16_OUT"); + break; + case 29: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_4TO1_C_DISP_DS16_OUT"); + break; + case 30: + CAM_INFO(CAM_ISP, "DOWNSCALE_MN_Y_VID_OUT"); + break; + case 31: + CAM_INFO(CAM_ISP, "DOWNSCALE_MN_C_VID_OUT"); + break; + case 32: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_MN_Y_VID_OUT"); + break; + case 33: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_MN_C_VID_OUT"); + break; + case 34: + CAM_INFO(CAM_ISP, "DSX_Y_VID_OUT"); + break; + case 35: + CAM_INFO(CAM_ISP, "DSX_C_VID_OUT"); + break; + case 36: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DSX_Y_VID_OUT"); + break; + case 37: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DSX_C_VID_OUT"); + break; + case 38: + CAM_INFO(CAM_ISP, + "DOWNSCALE_4TO1_Y_VID_DS16_OUT"); + break; + case 39: + CAM_INFO(CAM_ISP, + "DOWNSCALE_4TO1_C_VID_DS16_OUT"); + break; + case 40: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_4TO1_Y_VID_DS16_OUT"); + break; + case 41: + CAM_INFO(CAM_ISP, + "CROP_RND_CLAMP_POST_DOWNSCALE_4TO1_C_VID_DS16_OUT"); + break; + case 42: + CAM_INFO(CAM_ISP, "BLS"); + break; + case 43: + CAM_INFO(CAM_ISP, "STATS_TINTLESS_BG"); + break; + case 44: + CAM_INFO(CAM_ISP, "STATS_HDR_BHIST"); + break; + case 45: + CAM_INFO(CAM_ISP, "STATS_HDR_BE"); + break; + case 46: + CAM_INFO(CAM_ISP, "STATS_AWB_BG"); + break; + case 47: + CAM_INFO(CAM_ISP, "STATS_BHIST"); + break; + case 48: + CAM_INFO(CAM_ISP, "STATS_BAF"); + break; + case 49: + CAM_INFO(CAM_ISP, "STATS_RS"); + break; + case 50: + CAM_INFO(CAM_ISP, "STATS_CS"); + break; + case 51: + CAM_INFO(CAM_ISP, "STATS_IHIST"); + break; + default: + CAM_ERR(CAM_ISP, + "Invalid Module ID:%d", module_id); + break; + } + } +} + +static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *camif_node; + struct cam_vfe_mux_camif_ver3_data *camif_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + + camif_node = th_payload->handler_priv; + camif_priv = camif_node->res_priv; + + CAM_DBG(CAM_ISP, + "VFE:%d CAMIF IRQ status_0: 0x%X status_1: 0x%X status_2: 0x%X", + camif_node->hw_intf->hw_idx, th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1], th_payload->evt_status_arr[2]); + + rc = cam_vfe_camif_ver3_get_evt_payload(camif_priv, &evt_payload); + if (rc) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "VFE:%d CAMIF IRQ status_0: 0x%X status_1: 0x%X status_2: 0x%X", + camif_node->hw_intf->hw_idx, th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1], th_payload->evt_status_arr[2]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + int ret = CAM_VFE_IRQ_STATUS_ERR; + struct cam_isp_resource_node *camif_node; + struct cam_vfe_mux_camif_ver3_data *camif_priv; + struct cam_vfe_top_irq_evt_payload *payload; + struct cam_isp_hw_event_info evt_info; + uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX + 1] = {0}; + int i = 0; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, + "Invalid params handle_priv:%pK, evt_payload_priv:%pK", + handler_priv, evt_payload_priv); + return ret; + } + + camif_node = handler_priv; + camif_priv = camif_node->res_priv; + payload = evt_payload_priv; + + for (i = 0; i < CAM_IFE_IRQ_REGISTERS_MAX; i++) + irq_status[i] = payload->irq_reg_val[i]; + + evt_info.hw_idx = camif_node->hw_intf->hw_idx; + evt_info.res_id = camif_node->res_id; + evt_info.res_type = camif_node->res_type; + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->sof_irq_mask) { + if ((camif_priv->enable_sof_irq_debug) && + (camif_priv->irq_debug_cnt <= + CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE:%d Received SOF", + evt_info.hw_idx); + + camif_priv->irq_debug_cnt++; + if (camif_priv->irq_debug_cnt == + CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) { + camif_priv->enable_sof_irq_debug = + false; + camif_priv->irq_debug_cnt = 0; + } + } else + CAM_DBG(CAM_ISP, "VFE:%d Received SOF", + evt_info.hw_idx); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->epoch0_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->eof_irq_mask) { + CAM_DBG(CAM_ISP, "VFE:%d Received EOF", evt_info.hw_idx); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + & camif_priv->reg_data->error_irq_mask0) { + CAM_ERR(CAM_ISP, "VFE:%d Overflow", evt_info.hw_idx); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = + cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->bus_overflow_status); + + ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + + cam_vfe_camif_ver3_print_status(irq_status, ret); + + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) + cam_vfe_camif_ver3_reg_dump(camif_node); + } + + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { + CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_VIOLATION; + + cam_vfe_camif_ver3_print_status(irq_status, ret); + + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) + cam_vfe_camif_ver3_reg_dump(camif_node); + } + + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + CAM_DBG(CAM_ISP, "VFE:%d VFE_DIAG_SENSOR_STATUS: 0x%X", + evt_info.hw_idx, camif_priv->mem_base, + cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->diag_sensor_status_0)); + } + + cam_vfe_camif_ver3_put_evt_payload(camif_priv, &payload); + + CAM_DBG(CAM_ISP, "returning status = %d", ret); + return ret; +} + +int cam_vfe_camif_ver3_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, + void *vfe_irq_controller) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv = NULL; + struct cam_vfe_camif_ver3_hw_info *camif_info = camif_hw_info; + int i = 0; + + camif_priv = kzalloc(sizeof(struct cam_vfe_mux_camif_ver3_data), + GFP_KERNEL); + if (!camif_priv) + return -ENOMEM; + + camif_node->res_priv = camif_priv; + + camif_priv->mem_base = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base; + camif_priv->camif_reg = camif_info->camif_reg; + camif_priv->common_reg = camif_info->common_reg; + camif_priv->reg_data = camif_info->reg_data; + camif_priv->hw_intf = hw_intf; + camif_priv->soc_info = soc_info; + camif_priv->vfe_irq_controller = vfe_irq_controller; + + camif_node->init = cam_vfe_camif_ver3_resource_init; + camif_node->deinit = cam_vfe_camif_ver3_resource_deinit; + camif_node->start = cam_vfe_camif_ver3_resource_start; + camif_node->stop = cam_vfe_camif_ver3_resource_stop; + camif_node->process_cmd = cam_vfe_camif_ver3_process_cmd; + camif_node->top_half_handler = cam_vfe_camif_ver3_handle_irq_top_half; + camif_node->bottom_half_handler = + cam_vfe_camif_ver3_handle_irq_bottom_half; + spin_lock_init(&camif_priv->spin_lock); + INIT_LIST_HEAD(&camif_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_EVT_MAX; i++) { + INIT_LIST_HEAD(&camif_priv->evt_payload[i].list); + list_add_tail(&camif_priv->evt_payload[i].list, + &camif_priv->free_payload_list); + } + + return 0; +} + +int cam_vfe_camif_ver3_deinit( + struct cam_isp_resource_node *camif_node) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv; + int i = 0; + + if (!camif_node) { + CAM_ERR(CAM_ISP, "Error, camif_node is NULL %pK", camif_node); + return -ENODEV; + } + + camif_priv = camif_node->res_priv; + + INIT_LIST_HEAD(&camif_priv->free_payload_list); + for (i = 0; i < CAM_VFE_CAMIF_EVT_MAX; i++) + INIT_LIST_HEAD(&camif_priv->evt_payload[i].list); + + camif_priv = camif_node->res_priv; + + camif_node->start = NULL; + camif_node->stop = NULL; + camif_node->process_cmd = NULL; + camif_node->top_half_handler = NULL; + camif_node->bottom_half_handler = NULL; + camif_node->res_priv = NULL; + + if (!camif_priv) { + CAM_ERR(CAM_ISP, "Error, camif_priv is NULL %pK", camif_priv); + return -ENODEV; + } + + kfree(camif_priv); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h new file mode 100644 index 000000000000..3c82ca2ba7d6 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_CAMIF_VER3_H_ +#define _CAM_VFE_CAMIF_VER3_H_ + +#include "cam_isp_hw.h" +#include "cam_vfe_top.h" + +struct cam_vfe_camif_ver3_pp_clc_reg { + uint32_t hw_version; + uint32_t hw_status; + uint32_t module_cfg; + uint32_t pdaf_raw_crop_width_cfg; + uint32_t pdaf_raw_crop_height_cfg; + uint32_t line_skip_pattern; + uint32_t pixel_skip_pattern; + uint32_t period_cfg; + uint32_t irq_subsample_pattern; + uint32_t epoch_irq_cfg; + uint32_t debug_1; + uint32_t debug_0; + uint32_t test_bus_ctrl; + uint32_t spare; + uint32_t reg_update_cmd; +}; + +struct cam_vfe_camif_ver3_reg_data { + uint32_t pp_extern_reg_update_shift; + uint32_t dual_pd_extern_reg_update_shift; + uint32_t extern_reg_update_mask; + uint32_t dual_ife_pix_en_shift; + uint32_t operating_mode_shift; + uint32_t input_mux_sel_shift; + + 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 epoch1_irq_mask; + uint32_t eof_irq_mask; + uint32_t error_irq_mask0; + uint32_t error_irq_mask2; + uint32_t subscribe_irq_mask1; + + uint32_t enable_diagnostic_hw; + uint32_t pp_camif_cfg_en_shift; + uint32_t pp_camif_cfg_ife_out_en_shift; +}; + +struct cam_vfe_camif_ver3_hw_info { + struct cam_vfe_top_ver3_reg_offset_common *common_reg; + struct cam_vfe_camif_ver3_pp_clc_reg *camif_reg; + struct cam_vfe_camif_ver3_reg_data *reg_data; +}; + +int cam_vfe_camif_ver3_acquire_resource( + struct cam_isp_resource_node *camif_res, + void *acquire_param); + +int cam_vfe_camif_ver3_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, + void *vfe_irq_controller); + +int cam_vfe_camif_ver3_deinit( + struct cam_isp_resource_node *camif_node); + +#endif /* _CAM_VFE_CAMIF_VER3_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c new file mode 100644 index 000000000000..98c84ad77d93 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c @@ -0,0 +1,615 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#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; + } + + 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 reg_update_cmd 0x%x offset 0x%x", + 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(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", 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); + + 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_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; + struct cam_isp_hw_event_info evt_info; + 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]; + + evt_info.hw_idx = fe_node->hw_intf->hw_idx; + evt_info.res_id = fe_node->res_id; + evt_info.res_type = fe_node->res_type; + + CAM_DBG(CAM_ISP, "event ID, irq_status_0 = 0x%x", irq_status0); + + 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; + } + + if (irq_status0 & fe_priv->reg_data->epoch0_irq_mask) { + CAM_DBG(CAM_ISP, "Received EPOCH"); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + 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; + } + + if (irq_status0 & fe_priv->reg_data->eof_irq_mask) { + CAM_DBG(CAM_ISP, "Received EOF"); + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + if (irq_status1 & fe_priv->reg_data->error_irq_mask1) { + CAM_DBG(CAM_ISP, "Received ERROR"); + ret = CAM_ISP_HW_ERROR_OVERFLOW; + evt_info.err_type = CAM_VFE_IRQ_STATUS_OVERFLOW; + cam_vfe_fe_reg_dump(fe_node); + } else { + ret = CAM_ISP_HW_ERROR_NONE; + } + + 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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h new file mode 100644 index 000000000000..6974a568fd6c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c new file mode 100644 index 000000000000..0b230ce19621 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_vfe_rdi.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_isp_hw.h" +#include "cam_vfe_hw_intf.h" +#include "cam_vfe_top_ver2.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_cdm_util.h" +#include "cam_irq_controller.h" +#include "cam_tasklet_util.h" + +struct cam_vfe_mux_rdi_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_rdi_ver2_reg *rdi_reg; + struct cam_vfe_rdi_common_reg_data *rdi_common_reg_data; + struct cam_vfe_rdi_reg_data *reg_data; + + cam_hw_mgr_event_cb_func event_cb; + void *priv; + int irq_err_handle; + int irq_handle; + void *vfe_irq_controller; + struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_RDI_EVT_MAX]; + struct list_head free_payload_list; + spinlock_t spin_lock; + + enum cam_isp_hw_sync_mode sync_mode; +}; + +static int cam_vfe_rdi_get_evt_payload( + struct cam_vfe_mux_rdi_data *rdi_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&rdi_priv->spin_lock); + if (list_empty(&rdi_priv->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload"); + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&rdi_priv->free_payload_list, + struct cam_vfe_top_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + rc = 0; +done: + spin_unlock(&rdi_priv->spin_lock); + return rc; +} + +static int cam_vfe_rdi_put_evt_payload( + struct cam_vfe_mux_rdi_data *rdi_priv, + struct cam_vfe_top_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!rdi_priv) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&rdi_priv->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, &rdi_priv->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&rdi_priv->spin_lock, flags); + + CAM_DBG(CAM_ISP, "Done"); + return 0; +} + +static int cam_vfe_rdi_err_irq_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *rdi_node; + struct cam_vfe_mux_rdi_data *rdi_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + bool error_flag = false; + + CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]); + + rdi_node = th_payload->handler_priv; + rdi_priv = rdi_node->res_priv; + /* + * need to handle overflow condition here, otherwise irq storm + * will block everything + */ + if (th_payload->evt_status_arr[1]) { + CAM_ERR(CAM_ISP, + "RDI Error: vfe:%d: STATUS_1=0x%x", + rdi_node->hw_intf->hw_idx, + th_payload->evt_status_arr[1]); + CAM_ERR(CAM_ISP, "Stopping further IRQ processing from vfe=%d", + rdi_node->hw_intf->hw_idx); + cam_irq_controller_disable_irq(rdi_priv->vfe_irq_controller, + rdi_priv->irq_err_handle); + cam_irq_controller_clear_and_mask(evt_id, + rdi_priv->vfe_irq_controller); + error_flag = true; + } + + rc = cam_vfe_rdi_get_evt_payload(rdi_priv, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "STATUS_1=0x%x", + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->irq_reg_val[i] = cam_io_r(rdi_priv->mem_base + + rdi_priv->common_reg->violation_status); + + if (error_flag) + CAM_INFO(CAM_ISP, "Violation status = 0x%x", + evt_payload->irq_reg_val[i]); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_vfe_rdi_get_reg_update( + struct cam_isp_resource_node *rdi_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_rdi_data *rsrc_data = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error - Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res) { + CAM_ERR(CAM_ISP, "Error - 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, "Error - Invalid CDM ops"); + return -EINVAL; + } + + 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, + "Error - buf size:%d is not sufficient, expected: %d", + cdm_args->cmd.size, size * 4); + return -EINVAL; + } + + 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; + CAM_DBG(CAM_ISP, "RDI%d reg_update_cmd %x", + rdi_res->res_id - CAM_ISP_HW_VFE_IN_RDI0, reg_val_pair[1]); + + 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_rdi_ver2_acquire_resource( + struct cam_isp_resource_node *rdi_res, + void *acquire_param) +{ + struct cam_vfe_mux_rdi_data *rdi_data; + struct cam_vfe_acquire_args *acquire_data; + + rdi_data = (struct cam_vfe_mux_rdi_data *)rdi_res->res_priv; + acquire_data = (struct cam_vfe_acquire_args *)acquire_param; + + rdi_data->event_cb = acquire_data->event_cb; + rdi_data->priv = acquire_data->priv; + rdi_data->sync_mode = acquire_data->vfe_in.sync_mode; + + return 0; +} + +static int cam_vfe_rdi_resource_start( + struct cam_isp_resource_node *rdi_res) +{ + struct cam_vfe_mux_rdi_data *rsrc_data; + int rc = 0; + uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + + if (!rdi_res) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + if (rdi_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Error! Invalid rdi res res_state:%d", + rdi_res->res_state); + return -EINVAL; + } + + rsrc_data = (struct cam_vfe_mux_rdi_data *)rdi_res->res_priv; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->rdi_common_reg_data->error_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->rdi_common_reg_data->error_irq_mask1; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->rdi_common_reg_data->subscribe_irq_mask0; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->rdi_common_reg_data->subscribe_irq_mask1; + + rdi_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Reg Update */ + cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, + rsrc_data->mem_base + rsrc_data->rdi_reg->reg_update_cmd); + + if (!rsrc_data->irq_err_handle) { + rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + err_irq_mask, + rdi_res, + cam_vfe_rdi_err_irq_top_half, + rdi_res->bottom_half_handler, + rdi_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { + CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_err_handle = 0; + } + } + + if (!rdi_res->rdi_only_ctx) + goto end; + + if (!rsrc_data->irq_handle) { + rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_0, + irq_mask, + rdi_res, + rdi_res->top_half_handler, + rdi_res->bottom_half_handler, + rdi_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->irq_handle < 1) { + CAM_ERR(CAM_ISP, "IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->irq_handle = 0; + } + } + + CAM_DBG(CAM_ISP, "Start RDI %d", + rdi_res->res_id - CAM_ISP_HW_VFE_IN_RDI0); +end: + return rc; +} + + +static int cam_vfe_rdi_resource_stop( + struct cam_isp_resource_node *rdi_res) +{ + struct cam_vfe_mux_rdi_data *rdi_priv; + int rc = 0; + + if (!rdi_res) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + if (rdi_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED || + rdi_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) + return 0; + + rdi_priv = (struct cam_vfe_mux_rdi_data *)rdi_res->res_priv; + + if (rdi_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + rdi_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + if (rdi_priv->irq_handle) { + cam_irq_controller_unsubscribe_irq( + rdi_priv->vfe_irq_controller, rdi_priv->irq_handle); + rdi_priv->irq_handle = 0; + } + + if (rdi_priv->irq_err_handle) { + cam_irq_controller_unsubscribe_irq( + rdi_priv->vfe_irq_controller, rdi_priv->irq_err_handle); + rdi_priv->irq_err_handle = 0; + } + + return rc; +} + +static int cam_vfe_rdi_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, "Error! Invalid input arguments"); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + rc = cam_vfe_rdi_get_reg_update(rsrc_node, cmd_args, + arg_size); + break; + default: + CAM_ERR(CAM_ISP, + "unsupported RDI process command:%d", cmd_type); + break; + } + + return rc; +} + +static int cam_vfe_rdi_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *rdi_node; + struct cam_vfe_mux_rdi_data *rdi_priv; + struct cam_vfe_top_irq_evt_payload *evt_payload; + + rdi_node = th_payload->handler_priv; + rdi_priv = rdi_node->res_priv; + + CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]); + CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]); + + rc = cam_vfe_rdi_get_evt_payload(rdi_priv, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "IRQ status0=0x%x status1=0x%x", + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + int ret = CAM_VFE_IRQ_STATUS_ERR; + struct cam_isp_resource_node *rdi_node; + struct cam_vfe_mux_rdi_data *rdi_priv; + struct cam_vfe_top_irq_evt_payload *payload; + struct cam_isp_hw_event_info evt_info; + uint32_t irq_status0; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, "Invalid params"); + return ret; + } + + rdi_node = handler_priv; + rdi_priv = rdi_node->res_priv; + payload = evt_payload_priv; + + irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; + + evt_info.hw_idx = rdi_node->hw_intf->hw_idx; + evt_info.res_id = rdi_node->res_id; + evt_info.res_type = rdi_node->res_type; + + CAM_DBG(CAM_ISP, "irq_status_0 = %x", irq_status0); + + if (irq_status0 & rdi_priv->reg_data->sof_irq_mask) { + CAM_DBG(CAM_ISP, "Received SOF"); + + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } else if (irq_status0 & rdi_priv->reg_data->reg_update_irq_mask) { + CAM_DBG(CAM_ISP, "Received REG UPDATE"); + + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + + cam_vfe_rdi_put_evt_payload(rdi_priv, &payload); + CAM_DBG(CAM_ISP, "returing status = %d", ret); + return ret; +} + +int cam_vfe_rdi_ver2_init( + struct cam_hw_intf *hw_intf, + struct cam_hw_soc_info *soc_info, + void *rdi_hw_info, + struct cam_isp_resource_node *rdi_node, + void *vfe_irq_controller) +{ + struct cam_vfe_mux_rdi_data *rdi_priv = NULL; + struct cam_vfe_rdi_ver2_hw_info *rdi_info = rdi_hw_info; + int i = 0; + + rdi_priv = kzalloc(sizeof(struct cam_vfe_mux_rdi_data), + GFP_KERNEL); + if (!rdi_priv) { + CAM_DBG(CAM_ISP, "Error! Failed to alloc for rdi_priv"); + return -ENOMEM; + } + + rdi_node->res_priv = rdi_priv; + + rdi_priv->mem_base = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base; + rdi_priv->hw_intf = hw_intf; + rdi_priv->common_reg = rdi_info->common_reg; + rdi_priv->rdi_reg = rdi_info->rdi_reg; + rdi_priv->vfe_irq_controller = vfe_irq_controller; + rdi_priv->rdi_common_reg_data = rdi_info->common_reg_data; + + switch (rdi_node->res_id) { + case CAM_ISP_HW_VFE_IN_RDI0: + rdi_priv->reg_data = rdi_info->reg_data[0]; + break; + case CAM_ISP_HW_VFE_IN_RDI1: + rdi_priv->reg_data = rdi_info->reg_data[1]; + break; + case CAM_ISP_HW_VFE_IN_RDI2: + rdi_priv->reg_data = rdi_info->reg_data[2]; + break; + case CAM_ISP_HW_VFE_IN_RDI3: + if (rdi_info->reg_data[3]) { + rdi_priv->reg_data = rdi_info->reg_data[3]; + } else { + CAM_ERR(CAM_ISP, "Error! RDI3 is not supported"); + goto err_init; + } + break; + default: + CAM_DBG(CAM_ISP, "invalid Resource id:%d", rdi_node->res_id); + goto err_init; + } + + rdi_node->start = cam_vfe_rdi_resource_start; + rdi_node->stop = cam_vfe_rdi_resource_stop; + rdi_node->process_cmd = cam_vfe_rdi_process_cmd; + rdi_node->top_half_handler = cam_vfe_rdi_handle_irq_top_half; + rdi_node->bottom_half_handler = cam_vfe_rdi_handle_irq_bottom_half; + + spin_lock_init(&rdi_priv->spin_lock); + INIT_LIST_HEAD(&rdi_priv->free_payload_list); + for (i = 0; i < CAM_VFE_RDI_EVT_MAX; i++) { + INIT_LIST_HEAD(&rdi_priv->evt_payload[i].list); + list_add_tail(&rdi_priv->evt_payload[i].list, + &rdi_priv->free_payload_list); + } + + return 0; +err_init: + kfree(rdi_priv); + return -EINVAL; +} + +int cam_vfe_rdi_ver2_deinit( + struct cam_isp_resource_node *rdi_node) +{ + struct cam_vfe_mux_rdi_data *rdi_priv = rdi_node->res_priv; + int i = 0; + + INIT_LIST_HEAD(&rdi_priv->free_payload_list); + for (i = 0; i < CAM_VFE_RDI_EVT_MAX; i++) + INIT_LIST_HEAD(&rdi_priv->evt_payload[i].list); + + rdi_node->start = NULL; + rdi_node->stop = NULL; + rdi_node->process_cmd = NULL; + rdi_node->top_half_handler = NULL; + rdi_node->bottom_half_handler = NULL; + + rdi_node->res_priv = NULL; + + if (!rdi_priv) { + CAM_ERR(CAM_ISP, "Error! rdi_priv NULL"); + return -ENODEV; + } + kfree(rdi_priv); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h new file mode 100644 index 000000000000..c570e84a011c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_RDI_H_ +#define _CAM_VFE_RDI_H_ + +#include "cam_isp_hw.h" +#include "cam_vfe_top.h" + +#define CAM_VFE_RDI_VER2_MAX 4 + +#define CAM_VFE_RDI_EVT_MAX 256 + +struct cam_vfe_rdi_ver2_reg { + uint32_t reg_update_cmd; +}; + +struct cam_vfe_rdi_common_reg_data { + uint32_t subscribe_irq_mask0; + uint32_t subscribe_irq_mask1; + uint32_t error_irq_mask0; + uint32_t error_irq_mask1; + uint32_t error_irq_mask2; + uint32_t rdi_frame_drop_mask; +}; + +struct cam_vfe_rdi_reg_data { + uint32_t reg_update_cmd_data; + uint32_t sof_irq_mask; + uint32_t reg_update_irq_mask; +}; +struct cam_vfe_rdi_ver2_hw_info { + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_rdi_ver2_reg *rdi_reg; + struct cam_vfe_rdi_common_reg_data *common_reg_data; + struct cam_vfe_rdi_reg_data *reg_data[CAM_VFE_RDI_VER2_MAX]; +}; + +int cam_vfe_rdi_ver2_acquire_resource( + struct cam_isp_resource_node *rdi_res, + void *acquire_param); + +int cam_vfe_rdi_ver2_init( + struct cam_hw_intf *hw_intf, + struct cam_hw_soc_info *soc_info, + void *rdi_hw_info, + struct cam_isp_resource_node *rdi_node, + void *vfe_irq_controller); + +int cam_vfe_rdi_ver2_deinit( + struct cam_isp_resource_node *rdi_node); + +#endif /* _CAM_VFE_RDI_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c new file mode 100644 index 000000000000..077f89060bca --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_vfe_top.h" +#include "cam_vfe_top_ver2.h" +#include "cam_vfe_top_ver3.h" +#include "cam_debug_util.h" + +int cam_vfe_top_init(uint32_t top_version, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + void *vfe_irq_controller, + struct cam_vfe_top **vfe_top) +{ + int rc = -EINVAL; + + switch (top_version) { + case CAM_VFE_TOP_VER_2_0: + rc = cam_vfe_top_ver2_init(soc_info, hw_intf, top_hw_info, + vfe_irq_controller, vfe_top); + break; + case CAM_VFE_TOP_VER_3_0: + rc = cam_vfe_top_ver3_init(soc_info, hw_intf, top_hw_info, + vfe_irq_controller, vfe_top); + break; + default: + CAM_ERR(CAM_ISP, "Error! Unsupported Version %x", top_version); + break; + } + + return rc; +} + +int cam_vfe_top_deinit(uint32_t top_version, + struct cam_vfe_top **vfe_top) +{ + int rc = -EINVAL; + + switch (top_version) { + case CAM_VFE_TOP_VER_2_0: + rc = cam_vfe_top_ver2_deinit(vfe_top); + break; + case CAM_VFE_TOP_VER_3_0: + rc = cam_vfe_top_ver3_deinit(vfe_top); + break; + default: + CAM_ERR(CAM_ISP, "Error! Unsupported Version %x", top_version); + break; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c new file mode 100644 index 000000000000..78a72eb6846a --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -0,0 +1,1059 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_io_util.h" +#include "cam_cdm_util.h" +#include "cam_vfe_hw_intf.h" +#include "cam_vfe_top.h" +#include "cam_vfe_top_ver2.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_vfe_soc.h" + +#define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00003F9F +#define CAM_VFE_HW_RESET_HW_VAL 0x00003F87 +#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 + +struct cam_vfe_top_ver2_common_data { + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *hw_intf; + struct cam_vfe_top_ver2_reg_offset_common *common_reg; +}; + +struct cam_vfe_top_ver2_priv { + struct cam_vfe_top_ver2_common_data common_data; + struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER2_MUX_MAX]; + unsigned long hw_clk_rate; + 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 * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; + uint32_t last_counter; + uint64_t total_bw_applied; + enum cam_vfe_bw_control_action + axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX]; +}; + +static int cam_vfe_top_mux_get_base(struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + uint32_t size = 0; + uint32_t mem_base = 0; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error! Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error! 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; + } + + size = cdm_util_ops->cdm_required_size_changebase(); + /* 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; + } + + mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE( + top_priv->common_data.soc_info, VFE_CORE_BASE_IDX); + CAM_DBG(CAM_ISP, "core %d mem_base 0x%x", + top_priv->common_data.soc_info->index, mem_base); + + cdm_util_ops->cdm_write_changebase( + cdm_args->cmd.cmd_buf_addr, mem_base); + cdm_args->cmd.used_bytes = (size * 4); + + return 0; +} + +static int cam_vfe_top_set_hw_clk_rate( + struct cam_vfe_top_ver2_priv *top_priv) +{ + struct cam_hw_soc_info *soc_info = NULL; + int i, rc = 0; + unsigned long max_clk_rate = 0; + + soc_info = top_priv->common_data.soc_info; + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + if (top_priv->req_clk_rate[i] > max_clk_rate) + max_clk_rate = top_priv->req_clk_rate[i]; + } + if (max_clk_rate == top_priv->hw_clk_rate) + return 0; + + CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu", + soc_info->clk_name[soc_info->src_clk_idx], + soc_info->src_clk_idx, max_clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); + + if (!rc) + top_priv->hw_clk_rate = max_clk_rate; + else + CAM_ERR(CAM_ISP, "Set Clock rate failed, rc=%d", rc); + + return rc; +} + +static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( + struct cam_vfe_top_ver2_priv *top_priv, + uint64_t *to_be_applied_bw) +{ + uint32_t i, j; + int vote_idx = -1; + uint64_t max_bw = 0; + uint64_t total_bw; + struct cam_axi_vote *curr_l_vote; + + for (i = 0; i < (CAM_VFE_TOP_VER2_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) { + total_bw = 0; + curr_l_vote = &top_priv->last_vote[i]; + for (j = 0; j < curr_l_vote->num_paths; j++) { + if (total_bw > + (U64_MAX - + curr_l_vote->axi_path[j].camnoc_bw)) { + CAM_ERR(CAM_ISP, "Overflow at idx: %d", j); + return NULL; + } + + total_bw += curr_l_vote->axi_path[j].camnoc_bw; + } + + if (total_bw > max_bw) { + vote_idx = i; + max_bw = total_bw; + } + } + + if (vote_idx < 0) + return NULL; + + *to_be_applied_bw = max_bw; + + return &top_priv->last_vote[vote_idx]; +} + +static int cam_vfe_top_set_axi_bw_vote( + struct cam_vfe_top_ver2_priv *top_priv, + bool start_stop) +{ + struct cam_axi_vote agg_vote = {0}; + struct cam_axi_vote *to_be_applied_axi_vote = NULL; + int rc = 0; + uint32_t i; + uint32_t num_paths = 0; + uint64_t total_bw_new_vote = 0; + bool bw_unchanged = true; + struct cam_hw_soc_info *soc_info = + top_priv->common_data.soc_info; + struct cam_vfe_soc_private *soc_private = + soc_info->soc_private; + bool apply_bw_update = false; + + 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) { + if (num_paths + + top_priv->req_axi_vote[i].num_paths > + CAM_CPAS_MAX_PATHS_PER_CLIENT) { + CAM_ERR(CAM_ISP, + "Required paths(%d) more than max(%d)", + num_paths + + top_priv->req_axi_vote[i].num_paths, + CAM_CPAS_MAX_PATHS_PER_CLIENT); + return -EINVAL; + } + + memcpy(&agg_vote.axi_path[num_paths], + &top_priv->req_axi_vote[i].axi_path[0], + top_priv->req_axi_vote[i].num_paths * + sizeof( + struct cam_axi_per_path_bw_vote)); + num_paths += top_priv->req_axi_vote[i].num_paths; + } + } + + agg_vote.num_paths = num_paths; + + for (i = 0; i < agg_vote.num_paths; i++) { + CAM_DBG(CAM_PERF, + "ife[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + top_priv->last_counter, + cam_cpas_axi_util_path_type_to_string( + agg_vote.axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + agg_vote.axi_path[i].transac_type), + agg_vote.axi_path[i].camnoc_bw, + agg_vote.axi_path[i].mnoc_ab_bw, + agg_vote.axi_path[i].mnoc_ib_bw); + + total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; + } + + memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, + sizeof(struct cam_axi_vote)); + top_priv->last_counter = (top_priv->last_counter + 1) % + (CAM_VFE_TOP_VER2_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); + + if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + bw_unchanged = false; + + CAM_DBG(CAM_PERF, + "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, + bw_unchanged, start_stop); + + if (bw_unchanged) { + CAM_DBG(CAM_ISP, "BW config unchanged"); + return 0; + } + + if (start_stop) { + /* need to vote current request immediately */ + to_be_applied_axi_vote = &agg_vote; + /* 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] = agg_vote; + top_priv->last_counter = (top_priv->last_counter + 1) % + (CAM_VFE_TOP_VER2_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); + } else { + /* + * Find max bw request in last few frames. This will the bw + * that we want to vote to CPAS now. + */ + to_be_applied_axi_vote = + cam_vfe_top_delay_bw_reduction(top_priv, + &total_bw_new_vote); + if (!to_be_applied_axi_vote) { + CAM_ERR(CAM_ISP, "to_be_applied_axi_vote is NULL"); + return -EINVAL; + } + } + + for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "ife[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + cam_cpas_axi_util_path_type_to_string( + to_be_applied_axi_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + to_be_applied_axi_vote->axi_path[i].transac_type), + to_be_applied_axi_vote->axi_path[i].camnoc_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); + } + + if ((to_be_applied_axi_vote->num_paths != + top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + apply_bw_update = true; + + CAM_DBG(CAM_PERF, + "ife[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, + apply_bw_update, start_stop); + + if (apply_bw_update) { + rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, + to_be_applied_axi_vote); + if (!rc) { + memcpy(&top_priv->applied_axi_vote, + to_be_applied_axi_vote, + sizeof(struct cam_axi_vote)); + top_priv->total_bw_applied = total_bw_new_vote; + } 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) +{ + struct cam_vfe_clock_update_args *clk_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int i, rc = 0; + + clk_update = + (struct cam_vfe_clock_update_args *)cmd_args; + res = clk_update->node_res; + + if (!res || !res->hw_intf->hw_priv) { + CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + return -EINVAL; + } + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + top_priv->req_clk_rate[i] = clk_update->clk_rate; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_DBG(CAM_ISP, + "VFE:%d Not ready to set clocks yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else + rc = cam_vfe_top_set_hw_clk_rate(top_priv); + + return rc; +} + +static int cam_vfe_top_bw_update_v2( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bw_update_args_v2 *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_update = (struct cam_vfe_bw_update_args_v2 *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(top_priv, false); + } + + return rc; +} + +static int cam_vfe_top_bw_update( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bw_update_args *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + struct cam_axi_vote *mux_axi_vote; + bool vid_exists = false; + bool rdi_exists = false; + + bw_update = (struct cam_vfe_bw_update_args *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + CAM_DBG(CAM_ISP, "res_id=%d, BW=[%lld %lld]", + res->res_id, bw_update->camnoc_bw_bytes, + bw_update->external_bw_bytes); + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + mux_axi_vote = &top_priv->req_axi_vote[i]; + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + mux_axi_vote->num_paths = 1; + if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && + (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_RDI0 + + (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); + } else { + /* + * Vote all bw into VIDEO path as we cannot + * differentiate to which path this has to go + */ + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_VID; + } + + mux_axi_vote->axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + mux_axi_vote->axi_path[0].camnoc_bw = + bw_update->camnoc_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ib_bw = + bw_update->external_bw_bytes; + /* Make ddr bw same as mnoc bw */ + mux_axi_vote->axi_path[0].ddr_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].ddr_ib_bw = + bw_update->external_bw_bytes; + + top_priv->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + + if (mux_axi_vote->num_paths == 1) { + if (mux_axi_vote->axi_path[0].path_data_type == + CAM_AXI_PATH_DATA_IFE_VID) + vid_exists = true; + else if ((mux_axi_vote->axi_path[0].path_data_type >= + CAM_AXI_PATH_DATA_IFE_RDI0) && + (mux_axi_vote->axi_path[0].path_data_type <= + CAM_AXI_PATH_DATA_IFE_RDI3)) + rdi_exists = true; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(top_priv, false); + } + + return rc; +} + +static int cam_vfe_top_bw_control( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bw_control_args *bw_ctrl = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args; + res = bw_ctrl->node_res; + + if (!res || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + top_priv->axi_vote_control[i] = bw_ctrl->action; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); + } + + return rc; +} + +static int cam_vfe_top_mux_get_reg_update( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; + + if (cmd_update->res->process_cmd) + return cmd_update->res->process_cmd(cmd_update->res, + CAM_ISP_HW_CMD_GET_REG_UPDATE, cmd_args, arg_size); + + return -EINVAL; +} + +int cam_vfe_top_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_top_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver2_priv *top_priv = device_priv; + + top_priv->hw_clk_rate = 0; + + return 0; +} + +int cam_vfe_top_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver2_priv *top_priv = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_top_ver2_reg_offset_common *reg_common = NULL; + uint32_t *reset_reg_args = reset_core_args; + uint32_t reset_reg_val; + + if (!top_priv || !reset_reg_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + switch (*reset_reg_args) { + case CAM_VFE_HW_RESET_HW_AND_REG: + reset_reg_val = CAM_VFE_HW_RESET_HW_AND_REG_VAL; + break; + default: + reset_reg_val = CAM_VFE_HW_RESET_HW_VAL; + break; + } + + CAM_DBG(CAM_ISP, "reset reg value: %x", reset_reg_val); + soc_info = top_priv->common_data.soc_info; + reg_common = top_priv->common_data.common_reg; + + /* Mask All the IRQs except RESET */ + cam_io_w_mb((1 << 31), + CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX) + 0x5C); + + /* Reset HW */ + cam_io_w_mb(reset_reg_val, + CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX) + + reg_common->global_reset_cmd); + + CAM_DBG(CAM_ISP, "Reset HW exit"); + return 0; +} + +int cam_vfe_top_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver2_priv *top_priv; + struct cam_vfe_acquire_args *args; + struct cam_vfe_hw_vfe_in_acquire_args *acquire_args; + uint32_t i; + int rc = -EINVAL; + + if (!device_priv || !reserve_args) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + args = (struct cam_vfe_acquire_args *)reserve_args; + acquire_args = &args->vfe_in; + + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == acquire_args->res_id && + top_priv->mux_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + + if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { + rc = cam_vfe_camif_ver2_acquire_resource( + &top_priv->mux_rsrc[i], + args); + if (rc) + break; + } + + if (acquire_args->res_id == + CAM_ISP_HW_VFE_IN_PDLIB) { + rc = cam_vfe_camif_lite_ver2_acquire_resource( + &top_priv->mux_rsrc[i], + args); + if (rc) + 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 = + CAM_ISP_RESOURCE_STATE_RESERVED; + acquire_args->rsrc_node = + &top_priv->mux_rsrc[i]; + + rc = 0; + break; + } + } + + return rc; + +} + +int cam_vfe_top_release(void *device_priv, + void *release_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver2_priv *top_priv; + struct cam_isp_resource_node *mux_res; + + if (!device_priv || !release_args) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + mux_res = (struct cam_isp_resource_node *)release_args; + + CAM_DBG(CAM_ISP, "Resource in state %d", mux_res->res_state); + if (mux_res->res_state < CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Error! Resource in Invalid res_state :%d", + mux_res->res_state); + return -EINVAL; + } + mux_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +int cam_vfe_top_start(void *device_priv, + void *start_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver2_priv *top_priv; + struct cam_isp_resource_node *mux_res; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + + if (!device_priv || !start_args) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + mux_res = (struct cam_isp_resource_node *)start_args; + hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + + if (hw_info->hw_state == CAM_HW_STATE_POWER_UP) { + rc = cam_vfe_top_set_hw_clk_rate(top_priv); + if (rc) { + CAM_ERR(CAM_ISP, + "set_hw_clk_rate failed, rc=%d", rc); + return rc; + } + + rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); + if (rc) { + CAM_ERR(CAM_ISP, + "set_axi_bw_vote failed, rc=%d", rc); + return rc; + } + + if (mux_res->start) { + rc = mux_res->start(mux_res); + } else { + CAM_ERR(CAM_ISP, + "Invalid res id:%d", mux_res->res_id); + rc = -EINVAL; + } + } else { + CAM_ERR(CAM_ISP, "VFE HW not powered up"); + rc = -EPERM; + } + + return rc; +} + +int cam_vfe_top_stop(void *device_priv, + void *stop_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver2_priv *top_priv; + struct cam_isp_resource_node *mux_res; + struct cam_hw_info *hw_info = NULL; + int i, rc = 0; + + if (!device_priv || !stop_args) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + mux_res = (struct cam_isp_resource_node *)stop_args; + hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + + if ((mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) || + (mux_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || + (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); + } else { + CAM_ERR(CAM_ISP, "Invalid res id:%d", mux_res->res_id); + return -EINVAL; + } + + if (!rc) { + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == mux_res->res_id) { + top_priv->req_clk_rate[i] = 0; + top_priv->req_clk_rate[i] = 0; + top_priv->req_axi_vote[i].axi_path[0].camnoc_bw + = 0; + top_priv->req_axi_vote[i].axi_path[0].mnoc_ab_bw + = 0; + top_priv->req_axi_vote[i].axi_path[0].mnoc_ib_bw + = 0; + top_priv->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_EXCLUDE; + break; + } + } + } + + return rc; +} + +int cam_vfe_top_read(void *device_priv, + void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_top_write(void *device_priv, + void *write_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_vfe_top_ver2_priv *top_priv; + + if (!device_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "Error! Invalid arguments"); + return -EINVAL; + } + top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_CHANGE_BASE: + rc = cam_vfe_top_mux_get_base(top_priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + rc = cam_vfe_top_mux_get_reg_update(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_CLOCK_UPDATE: + 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); + break; + case CAM_ISP_HW_CMD_BW_UPDATE_V2: + rc = cam_vfe_top_bw_update_v2(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_BW_CONTROL: + rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size); + break; + default: + rc = -EINVAL; + CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type); + break; + } + + return rc; +} + +int cam_vfe_top_ver2_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + void *vfe_irq_controller, + struct cam_vfe_top **vfe_top_ptr) +{ + int i, j, rc = 0; + 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; + + vfe_top = kzalloc(sizeof(struct cam_vfe_top), GFP_KERNEL); + if (!vfe_top) { + CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe_top"); + rc = -ENOMEM; + goto end; + } + + top_priv = kzalloc(sizeof(struct cam_vfe_top_ver2_priv), + GFP_KERNEL); + if (!top_priv) { + CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe_top_priv"); + rc = -ENOMEM; + goto free_vfe_top; + } + vfe_top->top_priv = top_priv; + top_priv->hw_clk_rate = 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; + top_priv->mux_rsrc[i].hw_intf = hw_intf; + top_priv->mux_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + top_priv->req_clk_rate[i] = 0; + + 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; + + rc = cam_vfe_camif_ver2_init(hw_intf, soc_info, + &ver2_hw_info->camif_hw_info, + &top_priv->mux_rsrc[i], vfe_irq_controller); + if (rc) + goto deinit_resources; + } else if (ver2_hw_info->mux_type[i] == + CAM_VFE_CAMIF_LITE_VER_2_0) { + top_priv->mux_rsrc[i].res_id = + CAM_ISP_HW_VFE_IN_PDLIB; + + rc = cam_vfe_camif_lite_ver2_init(hw_intf, soc_info, + &ver2_hw_info->camif_lite_hw_info, + &top_priv->mux_rsrc[i], vfe_irq_controller); + + if (rc) + goto deinit_resources; + } else if (ver2_hw_info->mux_type[i] == + CAM_VFE_RDI_VER_1_0) { + /* set the RDI resource id */ + top_priv->mux_rsrc[i].res_id = + CAM_ISP_HW_VFE_IN_RDI0 + j++; + + rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info, + &ver2_hw_info->rdi_hw_info, + &top_priv->mux_rsrc[i], vfe_irq_controller); + 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]); + } + } + + vfe_top->hw_ops.get_hw_caps = cam_vfe_top_get_hw_caps; + vfe_top->hw_ops.init = cam_vfe_top_init_hw; + vfe_top->hw_ops.reset = cam_vfe_top_reset; + vfe_top->hw_ops.reserve = cam_vfe_top_reserve; + vfe_top->hw_ops.release = cam_vfe_top_release; + vfe_top->hw_ops.start = cam_vfe_top_start; + vfe_top->hw_ops.stop = cam_vfe_top_stop; + vfe_top->hw_ops.read = cam_vfe_top_read; + vfe_top->hw_ops.write = cam_vfe_top_write; + vfe_top->hw_ops.process_cmd = cam_vfe_top_process_cmd; + *vfe_top_ptr = vfe_top; + + top_priv->common_data.soc_info = soc_info; + top_priv->common_data.hw_intf = hw_intf; + top_priv->common_data.common_reg = ver2_hw_info->common_reg; + + return rc; + +deinit_resources: + for (--i; i >= 0; i--) { + if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) { + if (cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i])) + CAM_ERR(CAM_ISP, "Camif Deinit failed"); + } else if (ver2_hw_info->mux_type[i] == + CAM_VFE_CAMIF_LITE_VER_2_0) { + 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_VFE_IN_RD_VER_1_0) { + if (cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i])) + CAM_ERR(CAM_ISP, "VFE FE deinit failed"); + } else { + if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i])) + CAM_ERR(CAM_ISP, "RDI Deinit failed"); + } + top_priv->mux_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + } + kfree(vfe_top->top_priv); + +free_vfe_top: + kfree(vfe_top); +end: + return rc; +} + +int cam_vfe_top_ver2_deinit(struct cam_vfe_top **vfe_top_ptr) +{ + int i, rc = 0; + struct cam_vfe_top_ver2_priv *top_priv = NULL; + struct cam_vfe_top *vfe_top; + + if (!vfe_top_ptr) { + CAM_ERR(CAM_ISP, "Error! Invalid input"); + return -EINVAL; + } + + vfe_top = *vfe_top_ptr; + if (!vfe_top) { + CAM_ERR(CAM_ISP, "Error! vfe_top NULL"); + return -ENODEV; + } + + top_priv = vfe_top->top_priv; + if (!top_priv) { + CAM_ERR(CAM_ISP, "Error! vfe_top_priv NULL"); + rc = -ENODEV; + goto free_vfe_top; + } + + for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + top_priv->mux_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + if (top_priv->mux_rsrc[i].res_type == + CAM_VFE_CAMIF_VER_2_0) { + rc = cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]); + if (rc) + CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", + rc); + } else if (top_priv->mux_rsrc[i].res_type == + CAM_VFE_CAMIF_LITE_VER_2_0) { + rc = cam_vfe_camif_lite_ver2_deinit( + &top_priv->mux_rsrc[i]); + if (rc) + CAM_ERR(CAM_ISP, + "Camif lite deinit failed rc=%d", rc); + } else if (top_priv->mux_rsrc[i].res_type == + CAM_VFE_RDI_VER_1_0) { + 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); + } + } + kfree(vfe_top->top_priv); + +free_vfe_top: + kfree(vfe_top); + *vfe_top_ptr = NULL; + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h new file mode 100644 index 000000000000..82e30b4285a5 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_TOP_VER2_H_ +#define _CAM_VFE_TOP_VER2_H_ + +#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 6 + +enum cam_vfe_top_ver2_module_type { + CAM_VFE_TOP_VER2_MODULE_LENS, + CAM_VFE_TOP_VER2_MODULE_STATS, + CAM_VFE_TOP_VER2_MODULE_COLOR, + CAM_VFE_TOP_VER2_MODULE_ZOOM, + CAM_VFE_TOP_VER2_MODULE_MAX, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl { + uint32_t reset; + uint32_t cgc_ovd; + uint32_t enable; +}; + +struct cam_vfe_top_ver2_reg_offset_common { + uint32_t hw_version; + uint32_t hw_capability; + uint32_t lens_feature; + uint32_t stats_feature; + uint32_t color_feature; + uint32_t zoom_feature; + uint32_t global_reset_cmd; + struct cam_vfe_top_ver2_reg_offset_module_ctrl + *module_ctrl[CAM_VFE_TOP_VER2_MODULE_MAX]; + uint32_t bus_cgc_ovd; + uint32_t core_cfg; + uint32_t three_D_cfg; + uint32_t violation_status; + uint32_t reg_update_cmd; +}; + +struct cam_vfe_top_ver2_hw_info { + struct cam_vfe_top_ver2_reg_offset_common *common_reg; + 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]; +}; + +int cam_vfe_top_ver2_init(struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + void *vfe_irq_controller, + struct cam_vfe_top **vfe_top_ptr); + +int cam_vfe_top_ver2_deinit(struct cam_vfe_top **vfe_top); + +#endif /* _CAM_VFE_TOP_VER2_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c new file mode 100644 index 000000000000..578b0771821f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -0,0 +1,1101 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_io_util.h" +#include "cam_cdm_util.h" +#include "cam_vfe_hw_intf.h" +#include "cam_vfe_top.h" +#include "cam_vfe_top_ver3.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_vfe_soc.h" + +#define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00000003 +#define CAM_VFE_HW_RESET_HW_VAL 0x007F0000 +#define CAM_VFE_LITE_HW_RESET_AND_REG_VAL 0x00000002 +#define CAM_VFE_LITE_HW_RESET_HW_VAL 0x0000003D +#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 + +struct cam_vfe_top_ver3_common_data { + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *hw_intf; + struct cam_vfe_top_ver3_reg_offset_common *common_reg; +}; + +struct cam_vfe_top_ver3_priv { + struct cam_vfe_top_ver3_common_data common_data; + struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER3_MUX_MAX]; + unsigned long hw_clk_rate; + struct cam_axi_vote applied_axi_vote; + struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER3_MUX_MAX]; + unsigned long req_clk_rate[CAM_VFE_TOP_VER3_MUX_MAX]; + struct cam_axi_vote last_vote[CAM_VFE_TOP_VER3_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; + uint32_t last_counter; + uint64_t total_bw_applied; + enum cam_vfe_bw_control_action + axi_vote_control[CAM_VFE_TOP_VER3_MUX_MAX]; +}; + +static int cam_vfe_top_ver3_mux_get_base(struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + uint32_t size = 0; + uint32_t mem_base = 0; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error, Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error, 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; + } + + size = cdm_util_ops->cdm_required_size_changebase(); + /* 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; + } + + mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE( + top_priv->common_data.soc_info, VFE_CORE_BASE_IDX); + CAM_DBG(CAM_ISP, "core %d mem_base 0x%x", + top_priv->common_data.soc_info->index, mem_base); + + cdm_util_ops->cdm_write_changebase( + cdm_args->cmd.cmd_buf_addr, mem_base); + cdm_args->cmd.used_bytes = (size * 4); + + return 0; +} + +static int cam_vfe_top_ver3_set_hw_clk_rate( + struct cam_vfe_top_ver3_priv *top_priv) +{ + struct cam_hw_soc_info *soc_info = NULL; + int i, rc = 0; + unsigned long max_clk_rate = 0; + + soc_info = top_priv->common_data.soc_info; + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->req_clk_rate[i] > max_clk_rate) + max_clk_rate = top_priv->req_clk_rate[i]; + } + if (max_clk_rate == top_priv->hw_clk_rate) + return 0; + + CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu", + soc_info->clk_name[soc_info->src_clk_idx], + soc_info->src_clk_idx, max_clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); + + if (!rc) + top_priv->hw_clk_rate = max_clk_rate; + else + CAM_ERR(CAM_ISP, "Set Clock rate failed, rc=%d", rc); + + return rc; +} + +static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( + struct cam_vfe_top_ver3_priv *top_priv, + uint64_t *to_be_applied_bw) +{ + uint32_t i, j; + int vote_idx = -1; + uint64_t max_bw = 0; + uint64_t total_bw; + struct cam_axi_vote *curr_l_vote; + + for (i = 0; i < (CAM_VFE_TOP_VER3_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) { + total_bw = 0; + curr_l_vote = &top_priv->last_vote[i]; + for (j = 0; j < curr_l_vote->num_paths; j++) { + if (total_bw > + (U64_MAX - + curr_l_vote->axi_path[j].camnoc_bw)) { + CAM_ERR(CAM_ISP, "Overflow at idx: %d", j); + return NULL; + } + + total_bw += curr_l_vote->axi_path[j].camnoc_bw; + } + + if (total_bw > max_bw) { + vote_idx = i; + max_bw = total_bw; + } + } + + if (vote_idx < 0) + return NULL; + + *to_be_applied_bw = max_bw; + + return &top_priv->last_vote[vote_idx]; +} + +static int cam_vfe_top_ver3_set_axi_bw_vote( + struct cam_vfe_top_ver3_priv *top_priv, + bool start_stop) +{ + struct cam_axi_vote agg_vote = {0}; + struct cam_axi_vote *to_be_applied_axi_vote = NULL; + int rc = 0; + uint32_t i; + uint32_t num_paths = 0; + uint64_t total_bw_new_vote = 0; + bool bw_unchanged = true; + struct cam_hw_soc_info *soc_info = + top_priv->common_data.soc_info; + struct cam_vfe_soc_private *soc_private = + soc_info->soc_private; + bool apply_bw_update = false; + + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->axi_vote_control[i] == + CAM_VFE_BW_CONTROL_INCLUDE) { + if (num_paths + + top_priv->req_axi_vote[i].num_paths > + CAM_CPAS_MAX_PATHS_PER_CLIENT) { + CAM_ERR(CAM_ISP, + "Required paths(%d) more than max(%d)", + num_paths + + top_priv->req_axi_vote[i].num_paths, + CAM_CPAS_MAX_PATHS_PER_CLIENT); + return -EINVAL; + } + + memcpy(&agg_vote.axi_path[num_paths], + &top_priv->req_axi_vote[i].axi_path[0], + top_priv->req_axi_vote[i].num_paths * + sizeof( + struct cam_axi_per_path_bw_vote)); + num_paths += top_priv->req_axi_vote[i].num_paths; + } + } + + agg_vote.num_paths = num_paths; + + for (i = 0; i < agg_vote.num_paths; i++) { + CAM_DBG(CAM_PERF, + "ife[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + top_priv->last_counter, + cam_cpas_axi_util_path_type_to_string( + agg_vote.axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + agg_vote.axi_path[i].transac_type), + agg_vote.axi_path[i].camnoc_bw, + agg_vote.axi_path[i].mnoc_ab_bw, + agg_vote.axi_path[i].mnoc_ib_bw); + + total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; + } + + memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, + sizeof(struct cam_axi_vote)); + top_priv->last_counter = (top_priv->last_counter + 1) % + (CAM_VFE_TOP_VER3_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); + + if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + bw_unchanged = false; + + CAM_DBG(CAM_PERF, + "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, + bw_unchanged, start_stop); + + if (bw_unchanged) { + CAM_DBG(CAM_ISP, "BW config unchanged"); + return 0; + } + + if (start_stop) { + /* need to vote current request immediately */ + to_be_applied_axi_vote = &agg_vote; + /* Reset everything, we can start afresh */ + memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * + (CAM_VFE_TOP_VER3_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES)); + top_priv->last_counter = 0; + top_priv->last_vote[top_priv->last_counter] = agg_vote; + top_priv->last_counter = (top_priv->last_counter + 1) % + (CAM_VFE_TOP_VER3_MUX_MAX * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); + } else { + /* + * Find max bw request in last few frames. This will the bw + * that we want to vote to CPAS now. + */ + to_be_applied_axi_vote = + cam_vfe_top_delay_bw_reduction(top_priv, + &total_bw_new_vote); + if (!to_be_applied_axi_vote) { + CAM_ERR(CAM_ISP, "to_be_applied_axi_vote is NULL"); + return -EINVAL; + } + } + + for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "ife[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + cam_cpas_axi_util_path_type_to_string( + to_be_applied_axi_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + to_be_applied_axi_vote->axi_path[i].transac_type), + to_be_applied_axi_vote->axi_path[i].camnoc_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); + } + + if ((to_be_applied_axi_vote->num_paths != + top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + apply_bw_update = true; + + CAM_DBG(CAM_PERF, + "ife[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, + apply_bw_update, start_stop); + + if (apply_bw_update) { + rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, + to_be_applied_axi_vote); + if (!rc) { + memcpy(&top_priv->applied_axi_vote, + to_be_applied_axi_vote, + sizeof(struct cam_axi_vote)); + top_priv->total_bw_applied = total_bw_new_vote; + } else { + CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc); + } + } + + return rc; +} + +static int cam_vfe_top_fs_update( + struct cam_vfe_top_ver3_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_ver3_clock_update( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_clock_update_args *clk_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int i, rc = 0; + + clk_update = + (struct cam_vfe_clock_update_args *)cmd_args; + res = clk_update->node_res; + + if (!res || !res->hw_intf->hw_priv) { + CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + return -EINVAL; + } + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + top_priv->req_clk_rate[i] = clk_update->clk_rate; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_DBG(CAM_ISP, + "VFE:%d Not ready to set clocks yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else + rc = cam_vfe_top_ver3_set_hw_clk_rate(top_priv); + + return rc; +} + +static int cam_vfe_top_ver3_bw_update_v2( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bw_update_args_v2 *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_update = (struct cam_vfe_bw_update_args_v2 *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, false); + } + + return rc; +} + +static int cam_vfe_top_ver3_bw_update( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bw_update_args *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + struct cam_axi_vote *mux_axi_vote; + bool vid_exists = false; + bool rdi_exists = false; + + bw_update = (struct cam_vfe_bw_update_args *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + CAM_DBG(CAM_ISP, "res_id=%d, BW=[%lld %lld]", + res->res_id, bw_update->camnoc_bw_bytes, + bw_update->external_bw_bytes); + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + mux_axi_vote = &top_priv->req_axi_vote[i]; + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + mux_axi_vote->num_paths = 1; + if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && + (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_RDI0 + + (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); + } else { + /* + * Vote all bw into VIDEO path as we cannot + * differentiate to which path this has to go + */ + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_VID; + } + + mux_axi_vote->axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + mux_axi_vote->axi_path[0].camnoc_bw = + bw_update->camnoc_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ib_bw = + bw_update->external_bw_bytes; + /* Make ddr bw same as mnoc bw */ + mux_axi_vote->axi_path[0].ddr_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].ddr_ib_bw = + bw_update->external_bw_bytes; + + top_priv->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + + if (mux_axi_vote->num_paths == 1) { + if (mux_axi_vote->axi_path[0].path_data_type == + CAM_AXI_PATH_DATA_IFE_VID) + vid_exists = true; + else if ((mux_axi_vote->axi_path[0].path_data_type >= + CAM_AXI_PATH_DATA_IFE_RDI0) && + (mux_axi_vote->axi_path[0].path_data_type <= + CAM_AXI_PATH_DATA_IFE_RDI3)) + rdi_exists = true; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, false); + } + + return rc; +} + +static int cam_vfe_core_config_control( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_core_config_args *core_config = cmd_args; + + if (core_config->node_res->process_cmd) + return core_config->node_res->process_cmd(core_config->node_res, + CAM_ISP_HW_CMD_CORE_CONFIG, cmd_args, arg_size); + + return -EINVAL; +} + +static int cam_vfe_top_ver3_bw_control( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bw_control_args *bw_ctrl = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args; + res = bw_ctrl->node_res; + + if (!res || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == res->res_id) { + top_priv->axi_vote_control[i] = bw_ctrl->action; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, true); + } + + return rc; +} + +static int cam_vfe_top_ver3_mux_get_reg_update( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; + + if (cmd_update->res->process_cmd) + return cmd_update->res->process_cmd(cmd_update->res, + CAM_ISP_HW_CMD_GET_REG_UPDATE, cmd_args, arg_size); + + return -EINVAL; +} + +int cam_vfe_top_ver3_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_top_ver3_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver3_priv *top_priv = device_priv; + + top_priv->hw_clk_rate = 0; + + return 0; +} + +int cam_vfe_top_ver3_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver3_priv *top_priv = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + struct cam_vfe_top_ver3_reg_offset_common *reg_common = NULL; + uint32_t *reset_reg_args = reset_core_args; + uint32_t reset_reg_val; + + if (!top_priv || !reset_reg_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + soc_info = top_priv->common_data.soc_info; + reg_common = top_priv->common_data.common_reg; + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + return -ENODEV; + } + + switch (*reset_reg_args) { + case CAM_VFE_HW_RESET_HW_AND_REG: + if (!soc_private->is_ife_lite) + reset_reg_val = CAM_VFE_HW_RESET_HW_AND_REG_VAL; + else + reset_reg_val = CAM_VFE_LITE_HW_RESET_AND_REG_VAL; + break; + default: + if (!soc_private->is_ife_lite) + reset_reg_val = CAM_VFE_HW_RESET_HW_VAL; + else + reset_reg_val = CAM_VFE_LITE_HW_RESET_HW_VAL; + break; + } + /* override due to hw limitation */ + if (!soc_private->is_ife_lite) + reset_reg_val = CAM_VFE_HW_RESET_HW_AND_REG_VAL; + else + reset_reg_val = CAM_VFE_LITE_HW_RESET_AND_REG_VAL; + + CAM_DBG(CAM_ISP, "reset reg value: 0x%x", reset_reg_val); + + /* Mask All the IRQs except RESET */ + if (!soc_private->is_ife_lite) + cam_io_w_mb(0x00000001, + CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX) + + 0x3C); + else + cam_io_w_mb(0x00020000, + CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX) + + 0x28); + + /* Reset HW */ + cam_io_w_mb(reset_reg_val, + CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX) + + reg_common->global_reset_cmd); + + CAM_DBG(CAM_ISP, "Reset HW exit"); + return 0; +} + +int cam_vfe_top_ver3_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver3_priv *top_priv; + struct cam_vfe_acquire_args *args; + struct cam_vfe_hw_vfe_in_acquire_args *acquire_args; + uint32_t i; + int rc = -EINVAL; + + if (!device_priv || !reserve_args) { + CAM_ERR(CAM_ISP, "Error, Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + args = (struct cam_vfe_acquire_args *)reserve_args; + acquire_args = &args->vfe_in; + + CAM_DBG(CAM_ISP, "res id %d", acquire_args->res_id); + + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == acquire_args->res_id && + top_priv->mux_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + + if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { + rc = cam_vfe_camif_ver3_acquire_resource( + &top_priv->mux_rsrc[i], + args); + if (rc) + break; + } + + if (acquire_args->res_id >= CAM_ISP_HW_VFE_IN_RDI0 && + acquire_args->res_id < CAM_ISP_HW_VFE_IN_MAX) { + rc = cam_vfe_camif_lite_ver3_acquire_resource( + &top_priv->mux_rsrc[i], + args); + if (rc) + 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 = + CAM_ISP_RESOURCE_STATE_RESERVED; + acquire_args->rsrc_node = + &top_priv->mux_rsrc[i]; + + rc = 0; + break; + } + } + + return rc; + +} + +int cam_vfe_top_ver3_release(void *device_priv, + void *release_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver3_priv *top_priv; + struct cam_isp_resource_node *mux_res; + + if (!device_priv || !release_args) { + CAM_ERR(CAM_ISP, "Error, Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + mux_res = (struct cam_isp_resource_node *)release_args; + + CAM_DBG(CAM_ISP, "Resource in state %d", mux_res->res_state); + if (mux_res->res_state < CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Error, Resource in Invalid res_state :%d", + mux_res->res_state); + return -EINVAL; + } + mux_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +int cam_vfe_top_ver3_start(void *device_priv, + void *start_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver3_priv *top_priv; + struct cam_isp_resource_node *mux_res; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + + if (!device_priv || !start_args) { + CAM_ERR(CAM_ISP, "Error, Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + mux_res = (struct cam_isp_resource_node *)start_args; + hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + + if (hw_info->hw_state == CAM_HW_STATE_POWER_UP) { + rc = cam_vfe_top_ver3_set_hw_clk_rate(top_priv); + if (rc) { + CAM_ERR(CAM_ISP, + "set_hw_clk_rate failed, rc=%d", rc); + return rc; + } + + rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, true); + if (rc) { + CAM_ERR(CAM_ISP, + "set_axi_bw_vote failed, rc=%d", rc); + return rc; + } + + if (mux_res->start) { + rc = mux_res->start(mux_res); + } else { + CAM_ERR(CAM_ISP, + "Invalid res id:%d", mux_res->res_id); + rc = -EINVAL; + } + } else { + CAM_ERR(CAM_ISP, "VFE HW not powered up"); + rc = -EPERM; + } + + return rc; +} + +int cam_vfe_top_ver3_stop(void *device_priv, + void *stop_args, uint32_t arg_size) +{ + struct cam_vfe_top_ver3_priv *top_priv; + struct cam_isp_resource_node *mux_res; + struct cam_hw_info *hw_info = NULL; + int i, rc = 0; + + if (!device_priv || !stop_args) { + CAM_ERR(CAM_ISP, "Error, Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + mux_res = (struct cam_isp_resource_node *)stop_args; + hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + + if (mux_res->res_id < CAM_ISP_HW_VFE_IN_MAX) { + rc = mux_res->stop(mux_res); + } else { + CAM_ERR(CAM_ISP, "Invalid res id:%d", mux_res->res_id); + return -EINVAL; + } + + if (!rc) { + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + if (top_priv->mux_rsrc[i].res_id == mux_res->res_id) { + top_priv->req_clk_rate[i] = 0; + memset(&top_priv->req_axi_vote[i], 0, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_EXCLUDE; + break; + } + } + } + + return rc; +} + +int cam_vfe_top_ver3_read(void *device_priv, + void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_top_ver3_write(void *device_priv, + void *write_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_vfe_top_ver3_priv *top_priv; + + if (!device_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "Error, Invalid arguments"); + return -EINVAL; + } + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_CHANGE_BASE: + rc = cam_vfe_top_ver3_mux_get_base(top_priv, + cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + rc = cam_vfe_top_ver3_mux_get_reg_update(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_CLOCK_UPDATE: + rc = cam_vfe_top_ver3_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_ver3_bw_update(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_BW_UPDATE_V2: + rc = cam_vfe_top_ver3_bw_update_v2(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_BW_CONTROL: + rc = cam_vfe_top_ver3_bw_control(top_priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_CORE_CONFIG: + rc = cam_vfe_core_config_control(top_priv, cmd_args, arg_size); + break; + default: + rc = -EINVAL; + CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type); + break; + } + + return rc; +} + +int cam_vfe_top_ver3_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + void *vfe_irq_controller, + struct cam_vfe_top **vfe_top_ptr) +{ + int i, j, rc = 0; + struct cam_vfe_top_ver3_priv *top_priv = NULL; + struct cam_vfe_top_ver3_hw_info *ver3_hw_info = top_hw_info; + struct cam_vfe_top *vfe_top; + + vfe_top = kzalloc(sizeof(struct cam_vfe_top), GFP_KERNEL); + if (!vfe_top) { + CAM_DBG(CAM_ISP, "Error, Failed to alloc for vfe_top"); + rc = -ENOMEM; + goto end; + } + + top_priv = kzalloc(sizeof(struct cam_vfe_top_ver3_priv), + GFP_KERNEL); + if (!top_priv) { + CAM_DBG(CAM_ISP, "Error, Failed to alloc for vfe_top_priv"); + rc = -ENOMEM; + goto free_vfe_top; + } + vfe_top->top_priv = top_priv; + top_priv->hw_clk_rate = 0; + + for (i = 0, j = 0; i < CAM_VFE_TOP_VER3_MUX_MAX && + j < CAM_VFE_RDI_VER2_MAX; i++) { + top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN; + top_priv->mux_rsrc[i].hw_intf = hw_intf; + top_priv->mux_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + top_priv->req_clk_rate[i] = 0; + + if (ver3_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_3_0) { + top_priv->mux_rsrc[i].res_id = + CAM_ISP_HW_VFE_IN_CAMIF; + + rc = cam_vfe_camif_ver3_init(hw_intf, soc_info, + &ver3_hw_info->camif_hw_info, + &top_priv->mux_rsrc[i], vfe_irq_controller); + if (rc) + goto deinit_resources; + } else if (ver3_hw_info->mux_type[i] == + CAM_VFE_PDLIB_VER_1_0) { + /* set the PDLIB resource id */ + top_priv->mux_rsrc[i].res_id = + CAM_ISP_HW_VFE_IN_PDLIB; + + rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, + &ver3_hw_info->pdlib_hw_info, + &top_priv->mux_rsrc[i], vfe_irq_controller); + if (rc) + goto deinit_resources; + } else if (ver3_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, + &ver3_hw_info->fe_hw_info, + &top_priv->mux_rsrc[i]); + if (rc) + goto deinit_resources; + } else if (ver3_hw_info->mux_type[i] == + CAM_VFE_RDI_VER_1_0) { + /* set the RDI resource id */ + top_priv->mux_rsrc[i].res_id = + CAM_ISP_HW_VFE_IN_RDI0 + j; + + rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, + ver3_hw_info->rdi_hw_info[j++], + &top_priv->mux_rsrc[i], vfe_irq_controller); + if (rc) + goto deinit_resources; + } else if (ver3_hw_info->mux_type[i] == + CAM_VFE_LCR_VER_1_0) { + /* set the LCR resource id */ + top_priv->mux_rsrc[i].res_id = + CAM_ISP_HW_VFE_IN_LCR; + + rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, + &ver3_hw_info->lcr_hw_info, + &top_priv->mux_rsrc[i], vfe_irq_controller); + if (rc) + goto deinit_resources; + } else { + CAM_WARN(CAM_ISP, "Invalid mux type: %u", + ver3_hw_info->mux_type[i]); + } + } + + vfe_top->hw_ops.get_hw_caps = cam_vfe_top_ver3_get_hw_caps; + vfe_top->hw_ops.init = cam_vfe_top_ver3_init_hw; + vfe_top->hw_ops.reset = cam_vfe_top_ver3_reset; + vfe_top->hw_ops.reserve = cam_vfe_top_ver3_reserve; + vfe_top->hw_ops.release = cam_vfe_top_ver3_release; + vfe_top->hw_ops.start = cam_vfe_top_ver3_start; + vfe_top->hw_ops.stop = cam_vfe_top_ver3_stop; + vfe_top->hw_ops.read = cam_vfe_top_ver3_read; + vfe_top->hw_ops.write = cam_vfe_top_ver3_write; + vfe_top->hw_ops.process_cmd = cam_vfe_top_ver3_process_cmd; + *vfe_top_ptr = vfe_top; + + top_priv->common_data.soc_info = soc_info; + top_priv->common_data.hw_intf = hw_intf; + top_priv->common_data.common_reg = ver3_hw_info->common_reg; + + return rc; + +deinit_resources: + for (--i; i >= 0; i--) { + if (ver3_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_3_0) { + if (cam_vfe_camif_ver3_deinit(&top_priv->mux_rsrc[i])) + CAM_ERR(CAM_ISP, "Camif Deinit failed"); + } else if (ver3_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { + if (cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i])) + CAM_ERR(CAM_ISP, "Camif fe Deinit failed"); + } else { + if (cam_vfe_camif_lite_ver3_deinit( + &top_priv->mux_rsrc[i])) + CAM_ERR(CAM_ISP, + "Camif lite res id %d Deinit failed", + top_priv->mux_rsrc[i].res_id); + } + top_priv->mux_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + } + + kfree(vfe_top->top_priv); +free_vfe_top: + kfree(vfe_top); +end: + return rc; +} + +int cam_vfe_top_ver3_deinit(struct cam_vfe_top **vfe_top_ptr) +{ + int i, rc = 0; + struct cam_vfe_top_ver3_priv *top_priv = NULL; + struct cam_vfe_top *vfe_top; + + if (!vfe_top_ptr) { + CAM_ERR(CAM_ISP, "Error, Invalid input"); + return -EINVAL; + } + + vfe_top = *vfe_top_ptr; + if (!vfe_top) { + CAM_ERR(CAM_ISP, "Error, vfe_top NULL"); + return -ENODEV; + } + + top_priv = vfe_top->top_priv; + if (!top_priv) { + CAM_ERR(CAM_ISP, "Error, vfe_top_priv NULL"); + rc = -ENODEV; + goto free_vfe_top; + } + + for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + top_priv->mux_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + if (top_priv->mux_rsrc[i].res_type == + CAM_VFE_CAMIF_VER_3_0) { + rc = cam_vfe_camif_ver3_deinit(&top_priv->mux_rsrc[i]); + if (rc) + CAM_ERR(CAM_ISP, "Camif 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); + } else { + rc = cam_vfe_camif_lite_ver3_deinit( + &top_priv->mux_rsrc[i]); + if (rc) + CAM_ERR(CAM_ISP, + "Camif lite res id %d Deinit failed", + top_priv->mux_rsrc[i].res_id); + } + } + + kfree(vfe_top->top_priv); + +free_vfe_top: + kfree(vfe_top); + *vfe_top_ptr = NULL; + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h new file mode 100644 index 000000000000..1ae8e5d54a4d --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_TOP_VER3_H_ +#define _CAM_VFE_TOP_VER3_H_ + +#include "cam_vfe_camif_ver3.h" +#include "cam_vfe_camif_lite_ver3.h" +#include "cam_vfe_fe_ver1.h" + +#define CAM_VFE_TOP_VER3_MUX_MAX 6 + +#define CAM_SHIFT_TOP_CORE_CFG_MUXSEL_PDAF 31 +#define CAM_SHIFT_TOP_CORE_CFG_VID_DS16_R2PD 30 +#define CAM_SHIFT_TOP_CORE_CFG_VID_DS4_R2PD 29 +#define CAM_SHIFT_TOP_CORE_CFG_DISP_DS16_R2PD 28 +#define CAM_SHIFT_TOP_CORE_CFG_DISP_DS4_R2PD 27 +#define CAM_SHIFT_TOP_CORE_CFG_DSP_STREAMING 25 +#define CAM_SHIFT_TOP_CORE_CFG_STATS_IHIST 10 +#define CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BE 9 +#define CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BHIST 8 +#define CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP 5 + +struct cam_vfe_top_ver3_reg_offset_common { + uint32_t hw_version; + uint32_t titan_version; + uint32_t hw_capability; + uint32_t lens_feature; + uint32_t stats_feature; + uint32_t color_feature; + uint32_t zoom_feature; + uint32_t global_reset_cmd; + uint32_t core_cgc_ovd_0; + uint32_t core_cgc_ovd_1; + uint32_t ahb_cgc_ovd; + uint32_t noc_cgc_ovd; + uint32_t bus_cgc_ovd; + uint32_t core_cfg_0; + uint32_t core_cfg_1; + uint32_t reg_update_cmd; + uint32_t trigger_cdm_events; + uint32_t violation_status; + uint32_t sbi_frame_idx; + uint32_t dsp_status; + uint32_t diag_config; + uint32_t diag_sensor_status_0; + uint32_t diag_sensor_status_1; + uint32_t bus_overflow_status; +}; + +struct cam_vfe_camif_common_cfg { + uint32_t vid_ds16_r2pd; + uint32_t vid_ds4_r2pd; + uint32_t disp_ds16_r2pd; + uint32_t disp_ds4_r2pd; + uint32_t dsp_streaming_tap_point; + uint32_t ihist_src_sel; + uint32_t hdr_be_src_sel; + uint32_t hdr_bhist_src_sel; + uint32_t input_mux_sel_pdaf; + uint32_t input_mux_sel_pp; +}; + +struct cam_vfe_top_ver3_hw_info { + struct cam_vfe_top_ver3_reg_offset_common *common_reg; + struct cam_vfe_camif_ver3_hw_info camif_hw_info; + struct cam_vfe_camif_lite_ver3_hw_info pdlib_hw_info; + struct cam_vfe_camif_lite_ver3_hw_info + *rdi_hw_info[CAM_VFE_RDI_VER2_MAX]; + struct cam_vfe_camif_lite_ver3_hw_info lcr_hw_info; + struct cam_vfe_fe_ver1_hw_info fe_hw_info; + uint32_t mux_type[CAM_VFE_TOP_VER3_MUX_MAX]; +}; + +int cam_vfe_top_ver3_init(struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + void *vfe_irq_controller, + struct cam_vfe_top **vfe_top); + +int cam_vfe_top_ver3_deinit(struct cam_vfe_top **vfe_top); + +#endif /* _CAM_VFE_TOP_VER3_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h new file mode 100644 index 000000000000..932cab858a70 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_TOP_H_ +#define _CAM_VFE_TOP_H_ + +#include "cam_hw_intf.h" +#include "cam_isp_hw.h" + +#define CAM_VFE_TOP_VER_1_0 0x100000 +#define CAM_VFE_TOP_VER_2_0 0x200000 +#define CAM_VFE_TOP_VER_3_0 0x300000 + +#define CAM_VFE_CAMIF_VER_1_0 0x10 +#define CAM_VFE_CAMIF_VER_2_0 0x20 +#define CAM_VFE_CAMIF_VER_3_0 0x30 + +#define CAM_VFE_CAMIF_LITE_VER_2_0 0x02 + +#define CAM_VFE_RDI_VER_1_0 0x1000 +#define CAM_VFE_IN_RD_VER_1_0 0x2000 + +#define CAM_VFE_LCR_VER_1_0 0x100 +#define CAM_VFE_PDLIB_VER_1_0 0x10000 + +/* + * Debug values for camif module + */ +#define CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS BIT(0) +#define CAMIF_DEBUG_ENABLE_REG_DUMP BIT(1) +#define CAM_VFE_CAMIF_EVT_MAX 256 + +struct cam_vfe_top { + void *top_priv; + struct cam_hw_ops hw_ops; +}; + +int cam_vfe_top_init(uint32_t top_version, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + void *vfe_irq_controller, + struct cam_vfe_top **vfe_top); + +int cam_vfe_top_deinit(uint32_t top_version, + struct cam_vfe_top **vfe_top); + +#endif /* _CAM_VFE_TOP_H_*/ diff --git a/drivers/cam_jpeg/Makefile b/drivers/cam_jpeg/Makefile new file mode 100644 index 000000000000..3b9bbdbedb7b --- /dev/null +++ b/drivers/cam_jpeg/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/ + +obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_dev.o cam_jpeg_context.o diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c new file mode 100644 index 000000000000..e28aae21e7d9 --- /dev/null +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_mem_mgr.h" +#include "cam_jpeg_context.h" +#include "cam_context_utils.h" +#include "cam_debug_util.h" +#include "cam_packet_util.h" + +static const char jpeg_dev_name[] = "jpeg"; + +static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + int rc = 0; + int closest_port; + bool b_mem_found = false; + + + if (!ctx) { + CAM_ERR(CAM_JPEG, "Invalid ctx"); + return -EINVAL; + } + + CAM_INFO(CAM_JPEG, "iommu fault for jpeg ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + pf_dbg_entry = &(req->pf_data); + closest_port = -1; + CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &b_mem_found); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to dump pf info"); + + if (b_mem_found) + CAM_ERR(CAM_JPEG, "Found page fault in req %lld %d", + req->request_id, rc); + } + return rc; +} + +static int __cam_jpeg_ctx_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_acquire_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_JPEG, "Unable to Acquire device %d", rc); + else + ctx->state = CAM_CTX_ACQUIRED; + + return rc; +} + +static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_JPEG, "Unable to release device %d", rc); + + ctx->state = CAM_CTX_AVAILABLE; + + return rc; +} + +static int __cam_jpeg_ctx_flush_dev_in_acquired(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_flush_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_ICP, "Failed to flush device"); + + return rc; +} + +static int __cam_jpeg_ctx_config_dev_in_acquired(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + return cam_context_prepare_dev_to_hw(ctx, cmd); +} + +static int __cam_jpeg_ctx_handle_buf_done_in_acquired(void *ctx, + uint32_t evt_id, void *done) +{ + return cam_context_buf_done_from_hw(ctx, done, evt_id); +} + +static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_stop_dev_to_hw(ctx); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed in Stop dev, rc=%d", rc); + return rc; + } + + return rc; +} + +/* top state machine */ +static struct cam_ctx_ops + cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = { }, + .crm_ops = { }, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available, + }, + .crm_ops = { }, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .release_dev = __cam_jpeg_ctx_release_dev_in_acquired, + .config_dev = __cam_jpeg_ctx_config_dev_in_acquired, + .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, + .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, + }, + .crm_ops = { }, + .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, + .pagefault_ops = cam_jpeg_context_dump_active_request, + }, +}; + +int cam_jpeg_context_init(struct cam_jpeg_context *ctx, + struct cam_context *ctx_base, + struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id) +{ + int rc; + int i; + + if (!ctx || !ctx_base) { + CAM_ERR(CAM_JPEG, "Invalid Context"); + rc = -EFAULT; + goto err; + } + + memset(ctx, 0, sizeof(*ctx)); + + ctx->base = ctx_base; + + for (i = 0; i < CAM_CTX_REQ_MAX; i++) + ctx->req_base[i].req_priv = ctx; + + rc = cam_context_init(ctx_base, jpeg_dev_name, CAM_JPEG, ctx_id, + NULL, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_JPEG, "Camera Context Base init failed"); + goto err; + } + + ctx_base->state_machine = cam_jpeg_ctx_state_machine; + ctx_base->ctx_priv = ctx; + +err: + return rc; +} + +int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx) +{ + if (!ctx || !ctx->base) { + CAM_ERR(CAM_JPEG, "Invalid params: %pK", ctx); + return -EINVAL; + } + + cam_context_deinit(ctx->base); + + memset(ctx, 0, sizeof(*ctx)); + + return 0; +} diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h new file mode 100644 index 000000000000..739dc6fd4525 --- /dev/null +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_JPEG_CONTEXT_H_ +#define _CAM_JPEG_CONTEXT_H_ + +#include + +#include "cam_context.h" +#include "cam_jpeg_hw_mgr_intf.h" + +#define CAM_JPEG_HW_EVENT_MAX 20 + +/** + * struct cam_jpeg_context - Jpeg context + * @base: Base jpeg cam context object + * @req_base: Common request structure + */ +struct cam_jpeg_context { + struct cam_context *base; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; +}; + +/* cam jpeg context irq handling function type */ +typedef int (*cam_jpeg_hw_event_cb_func)( + struct cam_jpeg_context *ctx_jpeg, + void *evt_data); + +/** + * struct cam_jpeg_ctx_irq_ops - Function table for handling IRQ callbacks + * + * @irq_ops: Array of handle function pointers. + * + */ +struct cam_jpeg_ctx_irq_ops { + cam_jpeg_hw_event_cb_func irq_ops[CAM_JPEG_HW_EVENT_MAX]; +}; + +/** + * cam_jpeg_context_init() + * + * @brief: Initialization function for the JPEG context + * + * @ctx: JPEG context obj to be initialized + * @ctx_base: Context base from cam_context + * @hw_intf: JPEG hw manager interface + * @ctx_id: ID for this context + * + */ +int cam_jpeg_context_init(struct cam_jpeg_context *ctx, + struct cam_context *ctx_base, + struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id); + +/** + * cam_jpeg_context_deinit() + * + * @brief: Deinitialize function for the JPEG context + * + * @ctx: JPEG context obj to be deinitialized + * + */ +int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx); + +#endif /* __CAM_JPEG_CONTEXT_H__ */ diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c new file mode 100644 index 000000000000..0a68ce997283 --- /dev/null +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "cam_node.h" +#include "cam_hw_mgr_intf.h" +#include "cam_jpeg_hw_mgr_intf.h" +#include "cam_jpeg_dev.h" +#include "cam_debug_util.h" +#include "cam_smmu_api.h" + +#define CAM_JPEG_DEV_NAME "cam-jpeg" + +static struct cam_jpeg_dev g_jpeg_dev; + +static void cam_jpeg_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_JPEG, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + +static const struct of_device_id cam_jpeg_dt_match[] = { + { + .compatible = "qcom,cam-jpeg" + }, + { } +}; + +static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + + mutex_lock(&g_jpeg_dev.jpeg_mutex); + g_jpeg_dev.open_cnt++; + mutex_unlock(&g_jpeg_dev.jpeg_mutex); + + return 0; +} + +static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = 0; + struct cam_node *node = v4l2_get_subdevdata(sd); + + + mutex_lock(&g_jpeg_dev.jpeg_mutex); + if (g_jpeg_dev.open_cnt <= 0) { + CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); + rc = -EINVAL; + goto end; + } + + g_jpeg_dev.open_cnt--; + + if (!node) { + CAM_ERR(CAM_JPEG, "Node ptr is NULL"); + rc = -EINVAL; + goto end; + } + + if (g_jpeg_dev.open_cnt == 0) + cam_node_shutdown(node); + +end: + mutex_unlock(&g_jpeg_dev.jpeg_mutex); + return rc; +} + +static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { + .close = cam_jpeg_subdev_close, + .open = cam_jpeg_subdev_open, +}; + +static int cam_jpeg_dev_remove(struct platform_device *pdev) +{ + int rc; + int i; + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]); + if (rc) + CAM_ERR(CAM_JPEG, "JPEG context %d deinit failed %d", + i, rc); + } + + rc = cam_subdev_remove(&g_jpeg_dev.sd); + if (rc) + CAM_ERR(CAM_JPEG, "Unregister failed %d", rc); + + return rc; +} + +static int cam_jpeg_dev_probe(struct platform_device *pdev) +{ + int rc; + int i; + struct cam_hw_mgr_intf hw_mgr_intf; + struct cam_node *node; + int iommu_hdl = -1; + + g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; + rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, + CAM_JPEG_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_JPEG, "JPEG cam_subdev_probe failed %d", rc); + goto err; + } + node = (struct cam_node *)g_jpeg_dev.sd.token; + + rc = cam_jpeg_hw_mgr_init(pdev->dev.of_node, + (uint64_t *)&hw_mgr_intf, &iommu_hdl); + if (rc) { + CAM_ERR(CAM_JPEG, "Can not initialize JPEG HWmanager %d", rc); + goto unregister; + } + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_jpeg_context_init(&g_jpeg_dev.ctx_jpeg[i], + &g_jpeg_dev.ctx[i], + &node->hw_mgr_intf, + i); + if (rc) { + CAM_ERR(CAM_JPEG, "JPEG context init failed %d %d", + i, rc); + goto ctx_init_fail; + } + } + + rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_CTX_MAX, + CAM_JPEG_DEV_NAME); + if (rc) { + CAM_ERR(CAM_JPEG, "JPEG node init failed %d", rc); + goto ctx_init_fail; + } + + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_jpeg_dev_iommu_fault_handler, node); + + mutex_init(&g_jpeg_dev.jpeg_mutex); + + CAM_INFO(CAM_JPEG, "Camera JPEG probe complete"); + + return rc; + +ctx_init_fail: + for (--i; i >= 0; i--) + if (cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i])) + CAM_ERR(CAM_JPEG, "deinit fail %d %d", i, rc); +unregister: + if (cam_subdev_remove(&g_jpeg_dev.sd)) + CAM_ERR(CAM_JPEG, "remove fail %d", rc); +err: + return rc; +} + +static struct platform_driver jpeg_driver = { + .probe = cam_jpeg_dev_probe, + .remove = cam_jpeg_dev_remove, + .driver = { + .name = "cam_jpeg", + .owner = THIS_MODULE, + .of_match_table = cam_jpeg_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_jpeg_dev_init_module(void) +{ + return platform_driver_register(&jpeg_driver); +} + +static void __exit cam_jpeg_dev_exit_module(void) +{ + platform_driver_unregister(&jpeg_driver); +} + +module_init(cam_jpeg_dev_init_module); +module_exit(cam_jpeg_dev_exit_module); +MODULE_DESCRIPTION("MSM JPEG driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_jpeg/cam_jpeg_dev.h b/drivers/cam_jpeg/cam_jpeg_dev.h new file mode 100644 index 000000000000..4961527de1a7 --- /dev/null +++ b/drivers/cam_jpeg/cam_jpeg_dev.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_JPEG_DEV_H_ +#define _CAM_JPEG_DEV_H_ + +#include "cam_subdev.h" +#include "cam_hw_mgr_intf.h" +#include "cam_context.h" +#include "cam_jpeg_context.h" + +/** + * struct cam_jpeg_dev - Camera JPEG V4l2 device node + * + * @sd: Commone camera subdevice node + * @node: Pointer to jpeg subdevice + * @ctx: JPEG base context storage + * @ctx_jpeg: JPEG private context storage + * @jpeg_mutex: Jpeg dev mutex + * @open_cnt: Open device count + */ +struct cam_jpeg_dev { + struct cam_subdev sd; + struct cam_node *node; + struct cam_context ctx[CAM_CTX_MAX]; + struct cam_jpeg_context ctx_jpeg[CAM_CTX_MAX]; + struct mutex jpeg_mutex; + int32_t open_cnt; +}; +#endif /* __CAM_JPEG_DEV_H__ */ diff --git a/drivers/cam_jpeg/jpeg_hw/Makefile b/drivers/cam_jpeg/jpeg_hw/Makefile new file mode 100644 index 000000000000..f189bd13a244 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include/ + +obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_hw_mgr.o diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c new file mode 100644 index 000000000000..b395bc396c70 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -0,0 +1,1602 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cam_packet_util.h" +#include "cam_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_jpeg_hw_mgr_intf.h" +#include "cam_jpeg_hw_mgr.h" +#include "cam_smmu_api.h" +#include "cam_mem_mgr.h" +#include "cam_req_mgr_workq.h" +#include "cam_mem_mgr.h" +#include "cam_cdm_intf_api.h" +#include "cam_debug_util.h" +#include "cam_common_util.h" + +#define CAM_JPEG_HW_ENTRIES_MAX 20 +#define CAM_JPEG_CHBASE 0 +#define CAM_JPEG_CFG 1 +#define CAM_JPEG_PARAM 2 + +static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr; + +static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status, + int32_t result_size, void *data); +static int cam_jpeg_mgr_process_cmd(void *priv, void *data); + +static int cam_jpeg_mgr_process_irq(void *priv, void *data) +{ + int rc = 0; + int mem_hdl = 0; + struct cam_jpeg_process_irq_work_data_t *task_data; + struct cam_jpeg_hw_mgr *hw_mgr; + int32_t i; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + struct cam_hw_done_event_data buf_data; + struct cam_jpeg_set_irq_cb irq_cb; + uintptr_t dev_type = 0; + uintptr_t kaddr; + uint32_t *cmd_buf_kaddr; + size_t cmd_buf_len; + struct cam_jpeg_config_inout_param_info *p_params; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + struct crm_workq_task *task; + struct cam_jpeg_process_frame_work_data_t *wq_task_data; + + if (!data || !priv) { + CAM_ERR(CAM_JPEG, "Invalid data"); + return -EINVAL; + } + + task_data = data; + hw_mgr = &g_jpeg_hw_mgr; + + ctx_data = (struct cam_jpeg_hw_ctx_data *)task_data->data; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + return -EINVAL; + } + + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex); + + p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; + + if (hw_mgr->device_in_use[dev_type][0] == false || + p_cfg_req == NULL) { + CAM_ERR(CAM_JPEG, "irq for old request %d", rc); + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); + return -EINVAL; + } + + irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; + irq_cb.data = NULL; + irq_cb.b_set_cb = false; + if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) { + CAM_ERR(CAM_JPEG, "process_cmd null "); + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); + return -EINVAL; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) { + CAM_ERR(CAM_JPEG, "CMD_SET_IRQ_CB failed %d", rc); + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); + return rc; + } + + if (hw_mgr->devices[dev_type][0]->hw_ops.deinit) { + rc = hw_mgr->devices[dev_type][0]->hw_ops.deinit( + hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to Deinit %lu HW", dev_type); + } + + hw_mgr->device_in_use[dev_type][0] = false; + hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL; + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); + + task = cam_req_mgr_workq_get_task( + g_jpeg_hw_mgr.work_process_frame); + if (!task) { + CAM_ERR(CAM_JPEG, "no empty task"); + return -EINVAL; + } + + wq_task_data = (struct cam_jpeg_process_frame_work_data_t *) + task->payload; + if (!task_data) { + CAM_ERR(CAM_JPEG, "task_data is NULL"); + return -EINVAL; + } + wq_task_data->data = (void *)dev_type; + wq_task_data->request_id = 0; + wq_task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_jpeg_mgr_process_cmd; + rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr, + CRM_TASK_PRIORITY_0); + if (rc) { + CAM_ERR(CAM_JPEG, "could not enque task %d", rc); + return rc; + } + + mem_hdl = + p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].handle; + rc = cam_mem_get_cpu_buf(mem_hdl, &kaddr, &cmd_buf_len); + if (rc) { + CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d", + hw_mgr->iommu_hdl, rc); + return rc; + } + + cmd_buf_kaddr = (uint32_t *)kaddr; + + cmd_buf_kaddr = + (cmd_buf_kaddr + + (p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset + / sizeof(uint32_t))); + + p_params = (struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr; + + p_params->output_size = task_data->result_size; + CAM_DBG(CAM_JPEG, "Encoded Size %d", task_data->result_size); + + buf_data.num_handles = + p_cfg_req->hw_cfg_args.num_out_map_entries; + for (i = 0; i < buf_data.num_handles; i++) { + buf_data.resource_handle[i] = + p_cfg_req->hw_cfg_args.out_map_entries[i].resource_handle; + } + buf_data.request_id = + PTR_TO_U64(p_cfg_req->hw_cfg_args.priv); + ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); + + list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list); + return rc; +} + +static int cam_jpeg_hw_mgr_cb( + uint32_t irq_status, int32_t result_size, void *data) +{ + int32_t rc; + unsigned long flags; + struct cam_jpeg_hw_mgr *hw_mgr = &g_jpeg_hw_mgr; + struct crm_workq_task *task; + struct cam_jpeg_process_irq_work_data_t *task_data; + + spin_lock_irqsave(&hw_mgr->hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task( + g_jpeg_hw_mgr.work_process_irq_cb); + if (!task) { + CAM_ERR(CAM_JPEG, "no empty task"); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags); + return -ENOMEM; + } + + task_data = (struct cam_jpeg_process_irq_work_data_t *)task->payload; + task_data->data = data; + task_data->irq_status = irq_status; + task_data->result_size = result_size; + task_data->type = CAM_JPEG_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_jpeg_mgr_process_irq; + + rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags); + + return rc; +} + +static int cam_jpeg_mgr_get_free_ctx(struct cam_jpeg_hw_mgr *hw_mgr) +{ + int i = 0; + int num_ctx = CAM_JPEG_CTX_MAX; + + for (i = 0; i < num_ctx; i++) { + mutex_lock(&hw_mgr->ctx_data[i].ctx_mutex); + if (hw_mgr->ctx_data[i].in_use == false) { + hw_mgr->ctx_data[i].in_use = true; + mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex); + break; + } + mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex); + } + + return i; +} + + +static int cam_jpeg_mgr_release_ctx( + struct cam_jpeg_hw_mgr *hw_mgr, struct cam_jpeg_hw_ctx_data *ctx_data) +{ + if (!ctx_data) { + CAM_ERR(CAM_JPEG, "invalid ctx_data %pK", ctx_data); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is already un-used: %pK", ctx_data); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + + ctx_data->in_use = false; + mutex_unlock(&ctx_data->ctx_mutex); + + return 0; +} + +static int cam_jpeg_insert_cdm_change_base( + struct cam_hw_config_args *config_args, + struct cam_jpeg_hw_ctx_data *ctx_data, + struct cam_jpeg_hw_mgr *hw_mgr) +{ + int rc = 0; + uint32_t dev_type; + struct cam_cdm_bl_request *cdm_cmd; + uint32_t size; + uint32_t mem_cam_base; + uintptr_t iova_addr; + uint32_t *ch_base_iova_addr; + size_t ch_base_len; + + rc = cam_mem_get_cpu_buf( + config_args->hw_update_entries[CAM_JPEG_CHBASE].handle, + &iova_addr, &ch_base_len); + if (rc) { + CAM_ERR(CAM_JPEG, + "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); + ch_base_iova_addr = (uint32_t *)iova_addr; + ch_base_iova_addr = (ch_base_iova_addr + + (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset / + sizeof(uint32_t))); + + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + mem_cam_base = hw_mgr->cdm_reg_map[dev_type][0]->mem_cam_base; + size = + hw_mgr->cdm_info[dev_type][0].cdm_ops->cdm_required_size_changebase(); + hw_mgr->cdm_info[dev_type][0].cdm_ops->cdm_write_changebase( + ch_base_iova_addr, mem_cam_base); + + cdm_cmd = ctx_data->cdm_cmd; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = + config_args->hw_update_entries[CAM_JPEG_CHBASE].handle; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = + config_args->hw_update_entries[CAM_JPEG_CHBASE].offset; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = size * sizeof(uint32_t); + cdm_cmd->cmd_arrary_count++; + + ch_base_iova_addr += size; + *ch_base_iova_addr = 0; + ch_base_iova_addr += size; + *ch_base_iova_addr = 0; + + return rc; +} + +static int cam_jpeg_mgr_process_cmd(void *priv, void *data) +{ + int rc; + int i = 0; + struct cam_jpeg_hw_mgr *hw_mgr = priv; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + struct cam_hw_config_args *config_args = NULL; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + uintptr_t request_id = 0; + struct cam_jpeg_process_frame_work_data_t *task_data = + (struct cam_jpeg_process_frame_work_data_t *)data; + uint32_t dev_type; + struct cam_jpeg_set_irq_cb irq_cb; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + struct cam_hw_done_event_data buf_data; + struct cam_hw_config_args *hw_cfg_args = NULL; + + if (!hw_mgr || !task_data) { + CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK", + hw_mgr, task_data); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + if (list_empty(&hw_mgr->hw_config_req_list)) { + CAM_DBG(CAM_JPEG, "no available request"); + rc = -EFAULT; + goto end; + } + + p_cfg_req = list_first_entry(&hw_mgr->hw_config_req_list, + struct cam_jpeg_hw_cfg_req, list); + if (!p_cfg_req) { + CAM_ERR(CAM_JPEG, "no request"); + rc = -EFAULT; + goto end; + } + + if (false == hw_mgr->device_in_use[p_cfg_req->dev_type][0]) { + hw_mgr->device_in_use[p_cfg_req->dev_type][0] = true; + hw_mgr->dev_hw_cfg_args[p_cfg_req->dev_type][0] = p_cfg_req; + list_del_init(&p_cfg_req->list); + } else { + CAM_DBG(CAM_JPEG, "Not dequeing, just return"); + rc = -EFAULT; + goto end; + } + + config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args; + request_id = task_data->request_id; + if (request_id != (uintptr_t)config_args->priv) { + CAM_DBG(CAM_JPEG, "not a recent req %zd %zd", + request_id, (uintptr_t)config_args->priv); + } + + if (!config_args->num_hw_update_entries) { + CAM_ERR(CAM_JPEG, "No hw update enteries are available"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + rc = -EINVAL; + goto end_unusedev; + } + + ctx_data = (struct cam_jpeg_hw_ctx_data *)config_args->ctxt_to_hw_map; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + rc = -EINVAL; + goto end_unusedev; + } + + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + if (dev_type != p_cfg_req->dev_type) + CAM_WARN(CAM_JPEG, "dev types not same something wrong"); + + if (!hw_mgr->devices[dev_type][0]->hw_ops.init) { + CAM_ERR(CAM_JPEG, "hw op init null "); + rc = -EFAULT; + goto end; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.init( + hw_mgr->devices[dev_type][0]->hw_priv, + ctx_data, + sizeof(ctx_data)); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to Init %d HW", dev_type); + goto end; + } + + irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; + irq_cb.data = (void *)ctx_data; + irq_cb.b_set_cb = true; + if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) { + CAM_ERR(CAM_JPEG, "op process_cmd null "); + rc = -EFAULT; + goto end_callcb; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) { + CAM_ERR(CAM_JPEG, "SET_IRQ_CB failed %d", rc); + goto end_callcb; + } + + if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { + CAM_ERR(CAM_JPEG, "op reset null "); + rc = -EFAULT; + goto end_callcb; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( + hw_mgr->devices[dev_type][0]->hw_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + goto end_callcb; + } + + cdm_cmd = ctx_data->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = false; + cdm_cmd->userdata = NULL; + cdm_cmd->cookie = 0; + cdm_cmd->cmd_arrary_count = 0; + + rc = cam_jpeg_insert_cdm_change_base(config_args, + ctx_data, hw_mgr); + if (rc) { + CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); + goto end_callcb; + } + + CAM_DBG(CAM_JPEG, "num hw up %d", config_args->num_hw_update_entries); + for (i = CAM_JPEG_CFG; i < (config_args->num_hw_update_entries - 1); + i++) { + cmd = (config_args->hw_update_entries + i); + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle + = cmd->handle; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = + cmd->offset; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = + cmd->len; + CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", + i, cmd->handle, cmd->offset, cmd->len); + cdm_cmd->cmd_arrary_count++; + } + + rc = cam_cdm_submit_bls( + hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); + goto end_callcb; + } + + if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { + CAM_ERR(CAM_JPEG, "op start null "); + rc = -EINVAL; + goto end_callcb; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.start( + hw_mgr->devices[dev_type][0]->hw_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to start hw %d", + rc); + goto end_callcb; + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; + +end_callcb: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + if (p_cfg_req) { + hw_cfg_args = &p_cfg_req->hw_cfg_args; + buf_data.num_handles = + hw_cfg_args->num_out_map_entries; + for (i = 0; i < buf_data.num_handles; i++) { + buf_data.resource_handle[i] = + hw_cfg_args->out_map_entries[i].resource_handle; + } + buf_data.request_id = + (uintptr_t)p_cfg_req->hw_cfg_args.priv; + ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); + } +end_unusedev: + mutex_lock(&hw_mgr->hw_mgr_mutex); + hw_mgr->device_in_use[p_cfg_req->dev_type][0] = false; + hw_mgr->dev_hw_cfg_args[p_cfg_req->dev_type][0] = NULL; + +end: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) +{ + int rc; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_config_args *config_args = config_hw_args; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + uintptr_t request_id = 0; + struct cam_hw_update_entry *hw_update_entries; + struct crm_workq_task *task; + struct cam_jpeg_process_frame_work_data_t *task_data; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + + if (!hw_mgr || !config_args) { + CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK", + hw_mgr, config_args); + return -EINVAL; + } + + if (!config_args->num_hw_update_entries) { + CAM_ERR(CAM_JPEG, "No hw update enteries are available"); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + ctx_data = (struct cam_jpeg_hw_ctx_data *)config_args->ctxt_to_hw_map; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + if (list_empty(&hw_mgr->free_req_list)) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_JPEG, "list empty"); + return -ENOMEM; + } + + p_cfg_req = list_first_entry(&hw_mgr->free_req_list, + struct cam_jpeg_hw_cfg_req, list); + list_del_init(&p_cfg_req->list); + + /* Update Currently Processing Config Request */ + p_cfg_req->hw_cfg_args = *config_args; + p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + request_id = (uintptr_t)config_args->priv; + p_cfg_req->req_id = request_id; + hw_update_entries = config_args->hw_update_entries; + CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd", + ctx_data, request_id, (uintptr_t)config_args->priv); + task = cam_req_mgr_workq_get_task(g_jpeg_hw_mgr.work_process_frame); + if (!task) { + CAM_ERR(CAM_JPEG, "no empty task"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + rc = -ENOMEM; + goto err_after_dq_free_list; + } + + + task_data = (struct cam_jpeg_process_frame_work_data_t *) + task->payload; + if (!task_data) { + CAM_ERR(CAM_JPEG, "task_data is NULL"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + rc = -EINVAL; + goto err_after_dq_free_list; + } + CAM_DBG(CAM_JPEG, "cfge %pK num %d", + p_cfg_req->hw_cfg_args.hw_update_entries, + p_cfg_req->hw_cfg_args.num_hw_update_entries); + + list_add_tail(&p_cfg_req->list, &hw_mgr->hw_config_req_list); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + task_data->data = (void *)(uintptr_t)p_cfg_req->dev_type; + task_data->request_id = request_id; + task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_jpeg_mgr_process_cmd; + + rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr, + CRM_TASK_PRIORITY_0); + if (rc) { + CAM_ERR(CAM_JPEG, "failed to enqueue task %d", rc); + goto err_after_get_task; + } + + return rc; + +err_after_get_task: + list_del_init(&p_cfg_req->list); +err_after_dq_free_list: + list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list); + + return rc; +} + +static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + uint64_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_JPEG, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get src buf address fail"); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_JPEG, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_JPEG, + "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x", + j, io_cfg[i].planes[j].width, + io_cfg[i].planes[j].height, + (int32_t)src_buf_size, + (unsigned int)iova_addr, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + + iova_addr += io_cfg[i].offsets[j]; + } + } +} + +static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, + void *prepare_hw_update_args) +{ + int rc, i, j, k; + struct cam_hw_prepare_update_args *prepare_args = + prepare_hw_update_args; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + struct cam_packet *packet = NULL; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_buf_io_cfg *io_cfg_ptr = NULL; + struct cam_kmd_buf_info kmd_buf; + + if (!prepare_args || !hw_mgr) { + CAM_ERR(CAM_JPEG, "Invalid args %pK %pK", + prepare_args, hw_mgr); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + ctx_data = (struct cam_jpeg_hw_ctx_data *)prepare_args->ctxt_to_hw_map; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + packet = prepare_args->packet; + if (!packet) { + CAM_ERR(CAM_JPEG, "received packet is NULL"); + return -EINVAL; + } + + if (((packet->header.op_code & 0xff) != CAM_JPEG_OPCODE_ENC_UPDATE) && + ((packet->header.op_code + & 0xff) != CAM_JPEG_OPCODE_DMA_UPDATE)) { + CAM_ERR(CAM_JPEG, "Invalid Opcode in pkt: %d", + packet->header.op_code & 0xff); + return -EINVAL; + } + + rc = cam_packet_util_validate_packet(packet, prepare_args->remain_len); + if (rc) { + CAM_ERR(CAM_JPEG, "invalid packet %d", rc); + return rc; + } + + if ((packet->num_cmd_buf > 5) || !packet->num_patches || + !packet->num_io_configs) { + CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u", + packet->num_cmd_buf, + packet->num_patches); + return -EINVAL; + } + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *)&packet->payload + + (packet->cmd_buf_offset / 4)); + CAM_DBG(CAM_JPEG, "packet = %pK cmd_desc = %pK size = %lu", + (void *)packet, (void *)cmd_desc, + sizeof(struct cam_cmd_buf_desc)); + + rc = cam_packet_util_process_patches(packet, hw_mgr->iommu_hdl, -1); + if (rc) { + CAM_ERR(CAM_JPEG, "Patch processing failed %d", rc); + return rc; + } + + io_cfg_ptr = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + CAM_DBG(CAM_JPEG, "packet = %pK io_cfg_ptr = %pK size = %lu", + (void *)packet, (void *)io_cfg_ptr, + sizeof(struct cam_buf_io_cfg)); + prepare_args->pf_data->packet = packet; + + prepare_args->num_out_map_entries = 0; + + for (i = 0, j = 0, k = 0; i < packet->num_io_configs; i++) { + if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) { + prepare_args->in_map_entries[j].resource_handle = + io_cfg_ptr[i].resource_type; + prepare_args->in_map_entries[j++].sync_id = + io_cfg_ptr[i].fence; + prepare_args->num_in_map_entries++; + } else { + prepare_args->in_map_entries[k].resource_handle = + io_cfg_ptr[i].resource_type; + prepare_args->out_map_entries[k++].sync_id = + io_cfg_ptr[i].fence; + prepare_args->num_out_map_entries++; + } + CAM_DBG(CAM_JPEG, "dir[%d]: %u, fence: %u", + i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence); + } + + + j = prepare_args->num_hw_update_entries; + rc = cam_packet_util_get_kmd_buffer(packet, &kmd_buf); + if (rc) { + CAM_ERR(CAM_JPEG, "get kmd buf failed %d", rc); + return rc; + } + /* fill kmd buf info into 1st hw update entry */ + prepare_args->hw_update_entries[j].len = + (uint32_t)kmd_buf.used_bytes; + prepare_args->hw_update_entries[j].handle = + (uint32_t)kmd_buf.handle; + prepare_args->hw_update_entries[j].offset = + (uint32_t)kmd_buf.offset; + j++; + + for (i = 0; i < packet->num_cmd_buf; i++, j++) { + prepare_args->hw_update_entries[j].len = + (uint32_t)cmd_desc[i].length; + prepare_args->hw_update_entries[j].handle = + (uint32_t)cmd_desc[i].mem_handle; + prepare_args->hw_update_entries[j].offset = + (uint32_t)cmd_desc[i].offset; + } + prepare_args->num_hw_update_entries = j; + prepare_args->priv = (void *)(uintptr_t)packet->header.request_id; + + CAM_DBG(CAM_JPEG, "will wait on input sync sync_id %d", + prepare_args->in_map_entries[0].sync_id); + + return rc; +} + +static void cam_jpeg_mgr_stop_deinit_dev(struct cam_jpeg_hw_mgr *hw_mgr, + struct cam_jpeg_hw_cfg_req *p_cfg_req, uint32_t dev_type) +{ + int rc = 0; + struct cam_jpeg_set_irq_cb irq_cb; + + /* stop reset Unregister CB and deinit */ + irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; + irq_cb.data = NULL; + irq_cb.b_set_cb = false; + if (hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) { + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) + CAM_ERR(CAM_JPEG, "SET_IRQ_CB fail %d", rc); + } else { + CAM_ERR(CAM_JPEG, "process_cmd null %d", dev_type); + } + + if (hw_mgr->devices[dev_type][0]->hw_ops.stop) { + rc = hw_mgr->devices[dev_type][0]->hw_ops.stop( + hw_mgr->devices[dev_type][0]->hw_priv, + NULL, 0); + if (rc) + CAM_ERR(CAM_JPEG, "stop fail %d", rc); + } else { + CAM_ERR(CAM_JPEG, "op stop null %d", dev_type); + } + + if (hw_mgr->devices[dev_type][0]->hw_ops.deinit) { + rc = hw_mgr->devices[dev_type][0]->hw_ops.deinit( + hw_mgr->devices[dev_type][0]->hw_priv, + NULL, 0); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to Deinit %d HW %d", + dev_type, rc); + } else { + CAM_ERR(CAM_JPEG, "op deinit null %d", dev_type); + } + + hw_mgr->device_in_use[dev_type][0] = false; + hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL; +} + +static int cam_jpeg_mgr_flush(void *hw_mgr_priv, + struct cam_jpeg_hw_ctx_data *ctx_data) +{ + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + uint32_t dev_type; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + struct cam_jpeg_hw_cfg_req *cfg_req = NULL, *req_temp = NULL; + + CAM_DBG(CAM_JPEG, "E: JPEG flush ctx"); + + if (!hw_mgr || !ctx_data) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; + if (hw_mgr->device_in_use[dev_type][0] == true && + p_cfg_req != NULL) { + if ((struct cam_jpeg_hw_ctx_data *) + p_cfg_req->hw_cfg_args.ctxt_to_hw_map == ctx_data) { + cam_jpeg_mgr_stop_deinit_dev(hw_mgr, p_cfg_req, + dev_type); + list_del_init(&p_cfg_req->list); + list_add_tail(&p_cfg_req->list, + &hw_mgr->free_req_list); + } + } + + list_for_each_entry_safe(cfg_req, req_temp, + &hw_mgr->hw_config_req_list, list) { + if ((struct cam_jpeg_hw_ctx_data *) + cfg_req->hw_cfg_args.ctxt_to_hw_map != ctx_data) + continue; + + list_del_init(&cfg_req->list); + list_add_tail(&cfg_req->list, &hw_mgr->free_req_list); + } + + CAM_DBG(CAM_JPEG, "X: JPEG flush ctx"); + + return 0; +} + +static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv, + struct cam_jpeg_hw_ctx_data *ctx_data, + struct cam_hw_flush_args *flush_args) +{ + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_jpeg_hw_cfg_req *cfg_req = NULL; + struct cam_jpeg_hw_cfg_req *req_temp = NULL; + long request_id = 0; + uint32_t dev_type; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + bool b_req_found = false; + + CAM_DBG(CAM_JPEG, "E: JPEG flush req"); + + if (!hw_mgr || !ctx_data || !flush_args) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + + if (flush_args->num_req_pending) + return 0; + + request_id = (uintptr_t)flush_args->flush_req_active[0]; + + if (!flush_args->num_req_active) + return 0; + + if (request_id <= 0) { + CAM_ERR(CAM_JPEG, "Invalid red id %ld", request_id); + return -EINVAL; + } + + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; + if (hw_mgr->device_in_use[dev_type][0] == true && + p_cfg_req != NULL) { + if (((struct cam_jpeg_hw_ctx_data *) + p_cfg_req->hw_cfg_args.ctxt_to_hw_map == ctx_data) && + (p_cfg_req->req_id == request_id)) { + cam_jpeg_mgr_stop_deinit_dev(hw_mgr, p_cfg_req, + dev_type); + list_del_init(&p_cfg_req->list); + list_add_tail(&p_cfg_req->list, + &hw_mgr->free_req_list); + b_req_found = true; + } + } + + list_for_each_entry_safe(cfg_req, req_temp, + &hw_mgr->hw_config_req_list, list) { + if ((struct cam_jpeg_hw_ctx_data *) + cfg_req->hw_cfg_args.ctxt_to_hw_map != ctx_data) + continue; + + if (cfg_req->req_id != request_id) + continue; + + list_del_init(&cfg_req->list); + list_add_tail(&cfg_req->list, &hw_mgr->free_req_list); + b_req_found = true; + break; + } + + if (!b_req_found) { + CAM_ERR(CAM_JPEG, "req not found %ld", request_id); + return -EINVAL; + } + + CAM_DBG(CAM_JPEG, "X: JPEG flush req"); + return 0; +} + +static int cam_jpeg_mgr_hw_flush(void *hw_mgr_priv, void *flush_hw_args) +{ + int rc = 0; + struct cam_hw_flush_args *flush_args = flush_hw_args; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + + if (!hw_mgr || !flush_args || !flush_args->ctxt_to_hw_map) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + mutex_lock(&hw_mgr->hw_mgr_mutex); + + ctx_data = (struct cam_jpeg_hw_ctx_data *)flush_args->ctxt_to_hw_map; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + if ((flush_args->flush_type >= CAM_FLUSH_TYPE_MAX) || + (flush_args->flush_type < CAM_FLUSH_TYPE_REQ)) { + CAM_ERR(CAM_JPEG, "Invalid flush type: %d", + flush_args->flush_type); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + switch (flush_args->flush_type) { + case CAM_FLUSH_TYPE_ALL: + rc = cam_jpeg_mgr_flush(hw_mgr_priv, ctx_data); + if ((rc)) + CAM_ERR(CAM_JPEG, "Flush failed %d", rc); + break; + case CAM_FLUSH_TYPE_REQ: + rc = cam_jpeg_mgr_flush_req(hw_mgr_priv, ctx_data, flush_args); + break; + default: + CAM_ERR(CAM_JPEG, "Invalid flush type: %d", + flush_args->flush_type); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +} + +static int cam_jpeg_mgr_hw_stop(void *hw_mgr_priv, void *stop_hw_args) +{ + int rc; + struct cam_hw_stop_args *stop_args = + (struct cam_hw_stop_args *)stop_hw_args; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + + if (!hw_mgr || !stop_args || !stop_args->ctxt_to_hw_map) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + mutex_lock(&hw_mgr->hw_mgr_mutex); + + ctx_data = (struct cam_jpeg_hw_ctx_data *)stop_args->ctxt_to_hw_map; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + rc = cam_jpeg_mgr_flush(hw_mgr_priv, ctx_data); + if ((rc)) + CAM_ERR(CAM_JPEG, "flush failed %d", rc); + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +} + +static int cam_jpeg_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) +{ + int rc; + struct cam_hw_release_args *release_hw = release_hw_args; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + uint32_t dev_type; + + if (!hw_mgr || !release_hw || !release_hw->ctxt_to_hw_map) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + + ctx_data = (struct cam_jpeg_hw_ctx_data *)release_hw->ctxt_to_hw_map; + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 0) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_JPEG, "Error Unbalanced deinit"); + return -EFAULT; + } + + hw_mgr->cdm_info[dev_type][0].ref_cnt--; + if (!(hw_mgr->cdm_info[dev_type][0].ref_cnt)) { + if (cam_cdm_stream_off( + hw_mgr->cdm_info[dev_type][0].cdm_handle)) { + CAM_ERR(CAM_JPEG, "CDM stream off failed %d", + hw_mgr->cdm_info[dev_type][0].cdm_handle); + } + /* release cdm handle */ + cam_cdm_release(hw_mgr->cdm_info[dev_type][0].cdm_handle); + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + rc = cam_jpeg_mgr_release_ctx(hw_mgr, ctx_data); + if (rc) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_JPEG, "JPEG release ctx failed"); + kfree(ctx_data->cdm_cmd); + ctx_data->cdm_cmd = NULL; + + return -EINVAL; + } + + kfree(ctx_data->cdm_cmd); + ctx_data->cdm_cmd = NULL; + CAM_DBG(CAM_JPEG, "handle %llu", ctx_data); + + return rc; +} + +static int cam_jpeg_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) +{ + int rc = 0; + int32_t ctx_id = 0; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + struct cam_hw_acquire_args *args = acquire_hw_args; + struct cam_jpeg_acquire_dev_info jpeg_dev_acquire_info; + struct cam_cdm_acquire_data cdm_acquire; + uint32_t dev_type; + uint32_t size = 0; + + if ((!hw_mgr_priv) || (!acquire_hw_args)) { + CAM_ERR(CAM_JPEG, "Invalid params: %pK %pK", hw_mgr_priv, + acquire_hw_args); + return -EINVAL; + } + + if (args->num_acq > 1) { + CAM_ERR(CAM_JPEG, + "number of resources are wrong: %u", + args->num_acq); + return -EINVAL; + } + + if (copy_from_user(&jpeg_dev_acquire_info, + (void __user *)args->acquire_info, + sizeof(jpeg_dev_acquire_info))) { + CAM_ERR(CAM_JPEG, "copy failed"); + return -EFAULT; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + ctx_id = cam_jpeg_mgr_get_free_ctx(hw_mgr); + if (ctx_id >= CAM_JPEG_CTX_MAX) { + CAM_ERR(CAM_JPEG, "No free ctx space in hw_mgr"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EFAULT; + } + + ctx_data = &hw_mgr->ctx_data[ctx_id]; + + ctx_data->cdm_cmd = + kzalloc(((sizeof(struct cam_cdm_bl_request)) + + ((CAM_JPEG_HW_ENTRIES_MAX - 1) * + sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); + if (!ctx_data->cdm_cmd) { + rc = -ENOMEM; + goto jpeg_release_ctx; + } + + mutex_lock(&ctx_data->ctx_mutex); + ctx_data->jpeg_dev_acquire_info = jpeg_dev_acquire_info; + mutex_unlock(&ctx_data->ctx_mutex); + + if (ctx_data->jpeg_dev_acquire_info.dev_type >= + CAM_JPEG_RES_TYPE_MAX) { + rc = -EINVAL; + goto acq_cdm_hdl_failed; + } + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + if (!hw_mgr->cdm_info[dev_type][0].ref_cnt) { + + if (dev_type == CAM_JPEG_RES_TYPE_ENC) { + memcpy(cdm_acquire.identifier, + "jpegenc", sizeof("jpegenc")); + } else { + memcpy(cdm_acquire.identifier, + "jpegdma", sizeof("jpegdma")); + } + cdm_acquire.cell_index = 0; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ctx_data; + if (hw_mgr->cdm_reg_map[dev_type][0]) { + cdm_acquire.base_array[0] = + hw_mgr->cdm_reg_map[dev_type][0]; + } + cdm_acquire.base_array_cnt = 1; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = NULL; + + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to acquire the CDM HW %d", + rc); + rc = -EFAULT; + goto acq_cdm_hdl_failed; + } + hw_mgr->cdm_info[dev_type][0].cdm_handle = cdm_acquire.handle; + hw_mgr->cdm_info[dev_type][0].cdm_ops = cdm_acquire.ops; + hw_mgr->cdm_info[dev_type][0].ref_cnt++; + } else { + hw_mgr->cdm_info[dev_type][0].ref_cnt++; + } + + size = + hw_mgr->cdm_info[dev_type][0].cdm_ops->cdm_required_size_changebase(); + + if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1) + if (cam_cdm_stream_on( + hw_mgr->cdm_info[dev_type][0].cdm_handle)) { + CAM_ERR(CAM_JPEG, "Can not start cdm (%d)!", + hw_mgr->cdm_info[dev_type][0].cdm_handle); + rc = -EFAULT; + goto start_cdm_hdl_failed; + } + + mutex_lock(&ctx_data->ctx_mutex); + ctx_data->context_priv = args->context_data; + + args->ctxt_to_hw_map = (void *)&(hw_mgr->ctx_data[ctx_id]); + + mutex_unlock(&ctx_data->ctx_mutex); + + hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb; + + + if (copy_to_user((void __user *)args->acquire_info, + &jpeg_dev_acquire_info, + sizeof(jpeg_dev_acquire_info))) { + rc = -EFAULT; + goto copy_to_user_failed; + } + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + CAM_DBG(CAM_JPEG, "success ctx_data= %pK", ctx_data); + + return rc; + +copy_to_user_failed: + if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1) + cam_cdm_stream_off(hw_mgr->cdm_info[dev_type][0].cdm_handle); +start_cdm_hdl_failed: + if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1) + cam_cdm_release(hw_mgr->cdm_info[dev_type][0].cdm_handle); + hw_mgr->cdm_info[dev_type][0].ref_cnt--; +acq_cdm_hdl_failed: + kfree(ctx_data->cdm_cmd); +jpeg_release_ctx: + cam_jpeg_mgr_release_ctx(hw_mgr, ctx_data); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +} + +static int cam_jpeg_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) +{ + int rc; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query_cap = hw_caps_args; + + if (!hw_mgr_priv || !hw_caps_args) { + CAM_ERR(CAM_JPEG, "Invalid params: %pK %pK", + hw_mgr_priv, hw_caps_args); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), + &g_jpeg_hw_mgr.jpeg_caps, + sizeof(struct cam_jpeg_query_cap_cmd))) { + CAM_ERR(CAM_JPEG, "copy_to_user failed"); + rc = -EFAULT; + goto copy_error; + } + CAM_DBG(CAM_JPEG, "Success"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return 0; + +copy_error: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_jpeg_setup_workqs(void) +{ + int rc, i; + + rc = cam_req_mgr_workq_create( + "jpeg_command_queue", + CAM_JPEG_WORKQ_NUM_TASK, + &g_jpeg_hw_mgr.work_process_frame, + CRM_WORKQ_USAGE_NON_IRQ, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc); + goto work_process_frame_failed; + } + + rc = cam_req_mgr_workq_create( + "jpeg_message_queue", + CAM_JPEG_WORKQ_NUM_TASK, + &g_jpeg_hw_mgr.work_process_irq_cb, + CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc); + goto work_process_irq_cb_failed; + } + + g_jpeg_hw_mgr.process_frame_work_data = + kzalloc(sizeof(struct cam_jpeg_process_frame_work_data_t) * + CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL); + if (!g_jpeg_hw_mgr.process_frame_work_data) { + rc = -ENOMEM; + goto work_process_frame_data_failed; + } + + g_jpeg_hw_mgr.process_irq_cb_work_data = + kzalloc(sizeof(struct cam_jpeg_process_irq_work_data_t) * + CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL); + if (!g_jpeg_hw_mgr.process_irq_cb_work_data) { + rc = -ENOMEM; + goto work_process_irq_cb_data_failed; + } + + for (i = 0; i < CAM_JPEG_WORKQ_NUM_TASK; i++) + g_jpeg_hw_mgr.work_process_irq_cb->task.pool[i].payload = + &g_jpeg_hw_mgr.process_irq_cb_work_data[i]; + + for (i = 0; i < CAM_JPEG_WORKQ_NUM_TASK; i++) + g_jpeg_hw_mgr.work_process_frame->task.pool[i].payload = + &g_jpeg_hw_mgr.process_frame_work_data[i]; + + INIT_LIST_HEAD(&g_jpeg_hw_mgr.hw_config_req_list); + INIT_LIST_HEAD(&g_jpeg_hw_mgr.free_req_list); + for (i = 0; i < CAM_JPEG_HW_CFG_Q_MAX; i++) { + INIT_LIST_HEAD(&(g_jpeg_hw_mgr.req_list[i].list)); + list_add_tail(&(g_jpeg_hw_mgr.req_list[i].list), + &(g_jpeg_hw_mgr.free_req_list)); + } + + return rc; + +work_process_irq_cb_data_failed: + kfree(g_jpeg_hw_mgr.process_frame_work_data); +work_process_frame_data_failed: + cam_req_mgr_workq_destroy(&g_jpeg_hw_mgr.work_process_irq_cb); +work_process_irq_cb_failed: + cam_req_mgr_workq_destroy(&g_jpeg_hw_mgr.work_process_frame); +work_process_frame_failed: + + return rc; +} + +static int cam_jpeg_init_devices(struct device_node *of_node, + uint32_t *p_num_enc_dev, + uint32_t *p_num_dma_dev) +{ + int count, i, rc; + uint32_t num_dev; + uint32_t num_dma_dev; + const char *name = NULL; + struct device_node *child_node = NULL; + struct platform_device *child_pdev = NULL; + struct cam_hw_intf *child_dev_intf = NULL; + struct cam_hw_info *enc_hw = NULL; + struct cam_hw_info *dma_hw = NULL; + struct cam_hw_soc_info *enc_soc_info = NULL; + struct cam_hw_soc_info *dma_soc_info = NULL; + + if (!p_num_enc_dev || !p_num_dma_dev) { + rc = -EINVAL; + goto num_dev_failed; + } + count = of_property_count_strings(of_node, "compat-hw-name"); + if (!count) { + CAM_ERR(CAM_JPEG, + "no compat hw found in dev tree, count = %d", + count); + rc = -EINVAL; + goto num_dev_failed; + } + + rc = of_property_read_u32(of_node, "num-jpeg-enc", &num_dev); + if (rc) { + CAM_ERR(CAM_JPEG, "read num enc devices failed %d", rc); + goto num_enc_failed; + } + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kzalloc( + sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]) { + rc = -ENOMEM; + CAM_ERR(CAM_JPEG, "getting number of dma dev nodes failed"); + goto num_enc_failed; + } + + rc = of_property_read_u32(of_node, "num-jpeg-dma", &num_dma_dev); + if (rc) { + CAM_ERR(CAM_JPEG, "get num dma dev nodes failed %d", rc); + goto num_dma_failed; + } + + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kzalloc( + sizeof(struct cam_hw_intf *) * num_dma_dev, GFP_KERNEL); + if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]) { + rc = -ENOMEM; + goto num_dma_failed; + } + + for (i = 0; i < count; i++) { + rc = of_property_read_string_index(of_node, "compat-hw-name", + i, &name); + if (rc) { + CAM_ERR(CAM_JPEG, "getting dev object name failed"); + goto compat_hw_name_failed; + } + + child_node = of_find_node_by_name(NULL, name); + if (!child_node) { + CAM_ERR(CAM_JPEG, + "error! Cannot find node in dtsi %s", name); + rc = -ENODEV; + goto compat_hw_name_failed; + } + + child_pdev = of_find_device_by_node(child_node); + if (!child_pdev) { + CAM_ERR(CAM_JPEG, "failed to find device on bus %s", + child_node->name); + rc = -ENODEV; + of_node_put(child_node); + goto compat_hw_name_failed; + } + + child_dev_intf = (struct cam_hw_intf *)platform_get_drvdata( + child_pdev); + if (!child_dev_intf) { + CAM_ERR(CAM_JPEG, "no child device"); + of_node_put(child_node); + rc = -ENODEV; + goto compat_hw_name_failed; + } + CAM_DBG(CAM_JPEG, "child_intf %pK type %d id %d", + child_dev_intf, + child_dev_intf->hw_type, + child_dev_intf->hw_idx); + + if ((child_dev_intf->hw_type == CAM_JPEG_DEV_ENC && + child_dev_intf->hw_idx >= num_dev) || + (child_dev_intf->hw_type == CAM_JPEG_DEV_DMA && + child_dev_intf->hw_idx >= num_dma_dev)) { + CAM_ERR(CAM_JPEG, "index out of range"); + rc = -ENODEV; + goto compat_hw_name_failed; + } + g_jpeg_hw_mgr.devices[child_dev_intf->hw_type] + [child_dev_intf->hw_idx] = child_dev_intf; + + of_node_put(child_node); + } + + enc_hw = (struct cam_hw_info *) + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_priv; + enc_soc_info = &enc_hw->soc_info; + g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_ENC][0] = + &enc_soc_info->reg_map[0]; + dma_hw = (struct cam_hw_info *) + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_priv; + dma_soc_info = &dma_hw->soc_info; + g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_DMA][0] = + &dma_soc_info->reg_map[0]; + + *p_num_enc_dev = num_dev; + *p_num_dma_dev = num_dma_dev; + + return rc; + +compat_hw_name_failed: + kfree(g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]); +num_dma_failed: + kfree(g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]); +num_enc_failed: +num_dev_failed: + + return rc; +} + +static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_JPEG, "Invalid arguments"); + return -EINVAL; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_jpeg_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->iommu_hdl, + 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_JPEG, "Invalid cmd"); + } + + return rc; +} + +int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, + int *iommu_hdl) +{ + int i, rc; + uint32_t num_dev; + uint32_t num_dma_dev; + struct cam_hw_mgr_intf *hw_mgr_intf; + struct cam_iommu_handle cdm_handles; + + hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl; + if (!of_node || !hw_mgr_intf) { + CAM_ERR(CAM_JPEG, "Invalid args of_node %pK hw_mgr %pK", + of_node, hw_mgr_intf); + return -EINVAL; + } + + memset(hw_mgr_hdl, 0x0, sizeof(struct cam_hw_mgr_intf)); + hw_mgr_intf->hw_mgr_priv = &g_jpeg_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_jpeg_mgr_get_hw_caps; + hw_mgr_intf->hw_acquire = cam_jpeg_mgr_acquire_hw; + hw_mgr_intf->hw_release = cam_jpeg_mgr_release_hw; + hw_mgr_intf->hw_prepare_update = cam_jpeg_mgr_prepare_hw_update; + hw_mgr_intf->hw_config = cam_jpeg_mgr_config_hw; + hw_mgr_intf->hw_flush = cam_jpeg_mgr_hw_flush; + hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop; + hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd; + + mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex); + spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock); + + for (i = 0; i < CAM_JPEG_CTX_MAX; i++) + mutex_init(&g_jpeg_hw_mgr.ctx_data[i].ctx_mutex); + + rc = cam_jpeg_init_devices(of_node, &num_dev, &num_dma_dev); + if (rc) { + CAM_ERR(CAM_JPEG, "jpeg init devices %d", rc); + goto smmu_get_failed; + } + + rc = cam_smmu_get_handle("jpeg", &g_jpeg_hw_mgr.iommu_hdl); + if (rc) { + CAM_ERR(CAM_JPEG, "jpeg get iommu handle failed %d", rc); + goto smmu_get_failed; + } + + CAM_DBG(CAM_JPEG, "mmu handle :%d", g_jpeg_hw_mgr.iommu_hdl); + + rc = cam_cdm_get_iommu_handle("jpegenc", &cdm_handles); + if (rc) { + CAM_ERR(CAM_JPEG, "acquire cdm iommu handle Fail %d", rc); + g_jpeg_hw_mgr.cdm_iommu_hdl = -1; + g_jpeg_hw_mgr.cdm_iommu_hdl_secure = -1; + goto cdm_iommu_failed; + } + g_jpeg_hw_mgr.cdm_iommu_hdl = cdm_handles.non_secure; + g_jpeg_hw_mgr.cdm_iommu_hdl_secure = cdm_handles.secure; + + g_jpeg_hw_mgr.jpeg_caps.dev_iommu_handle.non_secure = + g_jpeg_hw_mgr.iommu_hdl; + g_jpeg_hw_mgr.jpeg_caps.dev_iommu_handle.secure = + g_jpeg_hw_mgr.iommu_sec_hdl; + g_jpeg_hw_mgr.jpeg_caps.cdm_iommu_handle.non_secure = + g_jpeg_hw_mgr.cdm_iommu_hdl; + g_jpeg_hw_mgr.jpeg_caps.cdm_iommu_handle.secure = + g_jpeg_hw_mgr.cdm_iommu_hdl_secure; + g_jpeg_hw_mgr.jpeg_caps.num_enc = num_dev; + g_jpeg_hw_mgr.jpeg_caps.num_dma = num_dma_dev; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.major = 4; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.minor = 2; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.incr = 0; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.reserved = 0; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.major = 4; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.minor = 2; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.incr = 0; + g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.reserved = 0; + + rc = cam_jpeg_setup_workqs(); + if (rc) { + CAM_ERR(CAM_JPEG, "setup work qs failed %d", rc); + goto cdm_iommu_failed; + } + + if (iommu_hdl) + *iommu_hdl = g_jpeg_hw_mgr.iommu_hdl; + + return rc; + +cdm_iommu_failed: + cam_smmu_destroy_handle(g_jpeg_hw_mgr.iommu_hdl); + g_jpeg_hw_mgr.iommu_hdl = 0; +smmu_get_failed: + mutex_destroy(&g_jpeg_hw_mgr.hw_mgr_mutex); + for (i = 0; i < CAM_JPEG_CTX_MAX; i++) + mutex_destroy(&g_jpeg_hw_mgr.ctx_data[i].ctx_mutex); + + return rc; +} diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h new file mode 100644 index 000000000000..e482c11a82bd --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_HW_MGR_H +#define CAM_JPEG_HW_MGR_H + +#include +#include +#include + +#include "cam_jpeg_hw_intf.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" +#include "cam_req_mgr_workq.h" +#include "cam_mem_mgr.h" + +#define CAM_JPEG_WORKQ_NUM_TASK 30 +#define CAM_JPEG_WORKQ_TASK_CMD_TYPE 1 +#define CAM_JPEG_WORKQ_TASK_MSG_TYPE 2 +#define CAM_JPEG_HW_CFG_Q_MAX 50 + +/** + * struct cam_jpeg_process_frame_work_data_t + * + * @type: Task type + * @data: Pointer to command data + * @request_id: Request id + */ +struct cam_jpeg_process_frame_work_data_t { + uint32_t type; + void *data; + uintptr_t request_id; +}; + +/** + * struct cam_jpeg_process_irq_work_data_t + * + * @type: Task type + * @data: Pointer to message data + * @result_size: Result size of enc/dma + * @irq_status: IRQ status + */ +struct cam_jpeg_process_irq_work_data_t { + uint32_t type; + void *data; + int32_t result_size; + uint32_t irq_status; +}; + +/** + * struct cam_jpeg_hw_cdm_info_t + * + * @ref_cnt: Ref count of how many times device type is acquired + * @cdm_handle: Cdm handle + * @cdm_ops: Cdm ops struct + */ +struct cam_jpeg_hw_cdm_info_t { + int ref_cnt; + uint32_t cdm_handle; + struct cam_cdm_utils_ops *cdm_ops; +}; + +/** + * struct cam_jpeg_hw_cfg_req_t + * + * @list_head: List head + * @hw_cfg_args: Hw config args + * @dev_type: Dev type for cfg request + * @req_id: Request Id + */ +struct cam_jpeg_hw_cfg_req { + struct list_head list; + struct cam_hw_config_args hw_cfg_args; + uint32_t dev_type; + uintptr_t req_id; +}; + +/** + * struct cam_jpeg_hw_ctx_data + * + * @context_priv: Context private data, cam_context from + * acquire. + * @ctx_mutex: Mutex for context + * @jpeg_dev_acquire_info: Acquire device info + * @ctxt_event_cb: Context callback function + * @in_use: Flag for context usage + * @wait_complete: Completion info + * @cdm_cmd: Cdm cmd submitted for that context. + */ +struct cam_jpeg_hw_ctx_data { + void *context_priv; + struct mutex ctx_mutex; + struct cam_jpeg_acquire_dev_info jpeg_dev_acquire_info; + cam_hw_event_cb_func ctxt_event_cb; + bool in_use; + struct completion wait_complete; + struct cam_cdm_bl_request *cdm_cmd; +}; + +/** + * struct cam_jpeg_hw_mgr + * @hw_mgr_mutex: Mutex for JPEG hardware manager + * @hw_mgr_lock: Spinlock for JPEG hardware manager + * @ctx_data: Context data + * @jpeg_caps: JPEG capabilities + * @iommu_hdl: Non secure IOMMU handle + * @iommu_sec_hdl: Secure IOMMU handle + * @work_process_frame: Work queue for hw config requests + * @work_process_irq_cb: Work queue for processing IRQs. + * @process_frame_work_data: Work data pool for hw config + * requests + * @process_irq_cb_work_data: Work data pool for irq requests + * @cdm_iommu_hdl: Iommu handle received from cdm + * @cdm_iommu_hdl_secure: Secure iommu handle received from cdm + * @devices: Core hw Devices of JPEG hardware manager + * @cdm_info: Cdm info for each core device. + * @cdm_reg_map: Regmap of each device for cdm. + * @device_in_use: Flag device being used for an active request + * @dev_hw_cfg_args: Current cfg request per core dev + * @hw_config_req_list: Pending hw update requests list + * @free_req_list: Free nodes for above list + * @req_list: Nodes of hw update list + */ +struct cam_jpeg_hw_mgr { + struct mutex hw_mgr_mutex; + spinlock_t hw_mgr_lock; + struct cam_jpeg_hw_ctx_data ctx_data[CAM_JPEG_CTX_MAX]; + struct cam_jpeg_query_cap_cmd jpeg_caps; + int32_t iommu_hdl; + int32_t iommu_sec_hdl; + struct cam_req_mgr_core_workq *work_process_frame; + struct cam_req_mgr_core_workq *work_process_irq_cb; + struct cam_jpeg_process_frame_work_data_t *process_frame_work_data; + struct cam_jpeg_process_irq_work_data_t *process_irq_cb_work_data; + int cdm_iommu_hdl; + int cdm_iommu_hdl_secure; + + struct cam_hw_intf **devices[CAM_JPEG_DEV_TYPE_MAX]; + struct cam_jpeg_hw_cdm_info_t cdm_info[CAM_JPEG_DEV_TYPE_MAX] + [CAM_JPEG_NUM_DEV_PER_RES_MAX]; + struct cam_soc_reg_map *cdm_reg_map[CAM_JPEG_DEV_TYPE_MAX] + [CAM_JPEG_NUM_DEV_PER_RES_MAX]; + uint32_t device_in_use[CAM_JPEG_DEV_TYPE_MAX] + [CAM_JPEG_NUM_DEV_PER_RES_MAX]; + struct cam_jpeg_hw_cfg_req *dev_hw_cfg_args[CAM_JPEG_DEV_TYPE_MAX] + [CAM_JPEG_NUM_DEV_PER_RES_MAX]; + + struct list_head hw_config_req_list; + struct list_head free_req_list; + struct cam_jpeg_hw_cfg_req req_list[CAM_JPEG_HW_CFG_Q_MAX]; +}; + +#endif /* CAM_JPEG_HW_MGR_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h new file mode 100644 index 000000000000..1b93547fdf25 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_HW_INTF_H +#define CAM_JPEG_HW_INTF_H + +#include "cam_cpas_api.h" + +#define CAM_JPEG_CTX_MAX 8 +#define CAM_JPEG_DEV_PER_TYPE_MAX 1 + +#define CAM_JPEG_CMD_BUF_MAX_SIZE 128 +#define CAM_JPEG_MSG_BUF_MAX_SIZE CAM_JPEG_CMD_BUF_MAX_SIZE + +#define JPEG_VOTE 640000000 + +enum cam_jpeg_hw_type { + CAM_JPEG_DEV_ENC, + CAM_JPEG_DEV_DMA, +}; + +struct cam_jpeg_set_irq_cb { + int32_t (*jpeg_hw_mgr_cb)(uint32_t irq_status, + int32_t result_size, void *data); + void *data; + uint32_t b_set_cb; +}; + +enum cam_jpeg_cmd_type { + CAM_JPEG_CMD_CDM_CFG, + CAM_JPEG_CMD_SET_IRQ_CB, + CAM_JPEG_CMD_MAX, +}; + +#endif diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h new file mode 100644 index 000000000000..30c51f7cfcfd --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_HW_MGR_INTF_H +#define CAM_JPEG_HW_MGR_INTF_H + +#include +#include +#include + +int cam_jpeg_hw_mgr_init(struct device_node *of_node, + uint64_t *hw_mgr_hdl, int *iommu_hdl); + +#endif /* CAM_JPEG_HW_MGR_INTF_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile new file mode 100644 index 000000000000..f0162f98833a --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw + +obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_dev.o jpeg_dma_core.o jpeg_dma_soc.o diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c new file mode 100644 index 000000000000..31b116cc7698 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "jpeg_dma_core.h" +#include "jpeg_dma_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_jpeg_hw_intf.h" +#include "cam_jpeg_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +int cam_jpeg_dma_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + int rc; + + if (!device_priv) { + CAM_ERR(CAM_JPEG, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + + if (!soc_info || !core_info) { + CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + mutex_lock(&core_info->core_mutex); + if (++core_info->ref_count > 1) { + mutex_unlock(&core_info->core_mutex); + return 0; + } + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 2; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = JPEG_VOTE; + axi_vote.axi_path[0].mnoc_ab_bw = JPEG_VOTE; + axi_vote.axi_path[0].mnoc_ib_bw = JPEG_VOTE; + axi_vote.axi_path[1].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[1].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[1].camnoc_bw = JPEG_VOTE; + axi_vote.axi_path[1].mnoc_ab_bw = JPEG_VOTE; + axi_vote.axi_path[1].mnoc_ib_bw = JPEG_VOTE; + + + rc = cam_cpas_start(core_info->cpas_handle, + &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_JPEG, "cpass start failed: %d", rc); + goto cpas_failed; + } + + rc = cam_jpeg_dma_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc); + goto soc_failed; + } + + mutex_unlock(&core_info->core_mutex); + + return 0; + +soc_failed: + cam_cpas_stop(core_info->cpas_handle); +cpas_failed: + --core_info->ref_count; + mutex_unlock(&core_info->core_mutex); + + return rc; +} + +int cam_jpeg_dma_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + int rc; + + if (!device_priv) { + CAM_ERR(CAM_JPEG, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + if (!soc_info || !core_info) { + CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + mutex_lock(&core_info->core_mutex); + if (--core_info->ref_count > 0) { + mutex_unlock(&core_info->core_mutex); + return 0; + } + + if (core_info->ref_count < 0) { + CAM_ERR(CAM_JPEG, "ref cnt %d", core_info->ref_count); + core_info->ref_count = 0; + mutex_unlock(&core_info->core_mutex); + return -EFAULT; + } + + rc = cam_jpeg_dma_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_JPEG, "soc enable failed %d", rc); + + rc = cam_cpas_stop(core_info->cpas_handle); + if (rc) + CAM_ERR(CAM_JPEG, "cpas stop failed: %d", rc); + + mutex_unlock(&core_info->core_mutex); + + return 0; +} + +int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = device_priv; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + int rc; + + if (!device_priv) { + CAM_ERR(CAM_JPEG, "Invalid arguments"); + return -EINVAL; + } + + if (cmd_type >= CAM_JPEG_CMD_MAX) { + CAM_ERR(CAM_JPEG, "Invalid command : %x", cmd_type); + return -EINVAL; + } + + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + + switch (cmd_type) { + case CAM_JPEG_CMD_SET_IRQ_CB: + { + struct cam_jpeg_set_irq_cb *irq_cb = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_JPEG, "cmd args NULL"); + return -EINVAL; + } + if (irq_cb->b_set_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb = + irq_cb->jpeg_hw_mgr_cb; + core_info->irq_cb.data = irq_cb->data; + } else { + core_info->irq_cb.jpeg_hw_mgr_cb = NULL; + core_info->irq_cb.data = NULL; + } + rc = 0; + break; + } + default: + rc = -EINVAL; + break; + } + + return rc; +} + +irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) +{ + return IRQ_HANDLED; +} diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h new file mode 100644 index 000000000000..dc3a1c13fe82 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_DMA_CORE_H +#define CAM_JPEG_DMA_CORE_H + +#include +#include +#include +#include + +#include "cam_jpeg_hw_intf.h" + +struct cam_jpeg_dma_device_hw_info { + uint32_t reserved; +}; + +enum cam_jpeg_dma_core_state { + CAM_JPEG_DMA_CORE_NOT_READY, + CAM_JPEG_DMA_CORE_READY, + CAM_JPEG_DMA_CORE_RESETTING, + CAM_JPEG_DMA_CORE_STATE_MAX, +}; + +struct cam_jpeg_dma_device_core_info { + enum cam_jpeg_dma_core_state core_state; + struct cam_jpeg_dma_device_hw_info *jpeg_dma_hw_info; + uint32_t cpas_handle; + struct cam_jpeg_set_irq_cb irq_cb; + int32_t ref_count; + struct mutex core_mutex; +}; + +int cam_jpeg_dma_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_jpeg_dma_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); +irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data); + +#endif /* CAM_JPEG_DMA_CORE_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c new file mode 100644 index 000000000000..ce82c5e799c5 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "jpeg_dma_core.h" +#include "jpeg_dma_soc.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_io_util.h" +#include "cam_jpeg_hw_intf.h" +#include "cam_jpeg_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { + .reserved = 0, +}; +EXPORT_SYMBOL(cam_jpeg_dma_hw_info); + +static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, + struct cam_jpeg_dma_device_core_info *core_info, + uint32_t hw_idx) +{ + struct cam_cpas_register_params cpas_register_params; + int rc; + + cpas_register_params.dev = soc_info->dev; + memcpy(cpas_register_params.identifier, "jpeg-dma", + sizeof("jpeg-dma")); + cpas_register_params.cam_cpas_client_cb = NULL; + cpas_register_params.cell_index = hw_idx; + cpas_register_params.userdata = NULL; + + rc = cam_cpas_register_client(&cpas_register_params); + if (rc) { + CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc); + return rc; + } + core_info->cpas_handle = cpas_register_params.client_handle; + + return rc; +} + +static int cam_jpeg_dma_unregister_cpas( + struct cam_jpeg_dma_device_core_info *core_info) +{ + int rc; + + rc = cam_cpas_unregister_client(core_info->cpas_handle); + if (rc) + CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc); + core_info->cpas_handle = 0; + + return rc; +} + +static int cam_jpeg_dma_remove(struct platform_device *pdev) +{ + struct cam_hw_info *jpeg_dma_dev = NULL; + struct cam_hw_intf *jpeg_dma_dev_intf = NULL; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + int rc; + + jpeg_dma_dev_intf = platform_get_drvdata(pdev); + if (!jpeg_dma_dev_intf) { + CAM_ERR(CAM_JPEG, "error No data in pdev"); + return -EINVAL; + } + + jpeg_dma_dev = jpeg_dma_dev_intf->hw_priv; + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "error HW data is NULL"); + rc = -ENODEV; + goto free_jpeg_hw_intf; + } + + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + if (!core_info) { + CAM_ERR(CAM_JPEG, "error core data NULL"); + goto deinit_soc; + } + + rc = cam_jpeg_dma_unregister_cpas(core_info); + if (rc) + CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); + + mutex_destroy(&core_info->core_mutex); + kfree(core_info); + +deinit_soc: + rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&jpeg_dma_dev->hw_mutex); + kfree(jpeg_dma_dev); + +free_jpeg_hw_intf: + kfree(jpeg_dma_dev_intf); + return rc; +} + +static int cam_jpeg_dma_probe(struct platform_device *pdev) +{ + struct cam_hw_info *jpeg_dma_dev = NULL; + struct cam_hw_intf *jpeg_dma_dev_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + int rc; + + jpeg_dma_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!jpeg_dma_dev_intf) + return -ENOMEM; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &jpeg_dma_dev_intf->hw_idx); + + jpeg_dma_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!jpeg_dma_dev) { + rc = -ENOMEM; + goto error_alloc_dev; + } + jpeg_dma_dev->soc_info.pdev = pdev; + jpeg_dma_dev->soc_info.dev = &pdev->dev; + jpeg_dma_dev->soc_info.dev_name = pdev->name; + jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev; + jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw; + jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw; + jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd; + jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA; + + platform_set_drvdata(pdev, jpeg_dma_dev_intf); + jpeg_dma_dev->core_info = + kzalloc(sizeof(struct cam_jpeg_dma_device_core_info), + GFP_KERNEL); + if (!jpeg_dma_dev->core_info) { + rc = -ENOMEM; + goto error_alloc_core; + } + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_JPEG, " No jpeg_dma hardware info"); + rc = -EINVAL; + goto error_match_dev; + } + hw_info = (struct cam_jpeg_dma_device_hw_info *)match_dev->data; + core_info->jpeg_dma_hw_info = hw_info; + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + mutex_init(&core_info->core_mutex); + + rc = cam_jpeg_dma_init_soc_resources(&jpeg_dma_dev->soc_info, + cam_jpeg_dma_irq, + jpeg_dma_dev); + if (rc) { + CAM_ERR(CAM_JPEG, "failed to init_soc %d", rc); + goto error_init_soc; + } + + rc = cam_jpeg_dma_register_cpas(&jpeg_dma_dev->soc_info, + core_info, jpeg_dma_dev_intf->hw_idx); + if (rc) { + CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc); + goto error_reg_cpas; + } + jpeg_dma_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&jpeg_dma_dev->hw_mutex); + spin_lock_init(&jpeg_dma_dev->hw_lock); + init_completion(&jpeg_dma_dev->hw_complete); + + CAM_DBG(CAM_JPEG, " hwidx %d", jpeg_dma_dev_intf->hw_idx); + + return rc; + +error_reg_cpas: + rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); +error_init_soc: + mutex_destroy(&core_info->core_mutex); +error_match_dev: + kfree(jpeg_dma_dev->core_info); +error_alloc_core: + kfree(jpeg_dma_dev); +error_alloc_dev: + kfree(jpeg_dma_dev_intf); + return rc; +} + +static const struct of_device_id cam_jpeg_dma_dt_match[] = { + { + .compatible = "qcom,cam_jpeg_dma", + .data = &cam_jpeg_dma_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_jpeg_dma_dt_match); + +static struct platform_driver cam_jpeg_dma_driver = { + .probe = cam_jpeg_dma_probe, + .remove = cam_jpeg_dma_remove, + .driver = { + .name = "cam-jpeg-dma", + .owner = THIS_MODULE, + .of_match_table = cam_jpeg_dma_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_jpeg_dma_init_module(void) +{ + return platform_driver_register(&cam_jpeg_dma_driver); +} + +static void __exit cam_jpeg_dma_exit_module(void) +{ + platform_driver_unregister(&cam_jpeg_dma_driver); +} + +module_init(cam_jpeg_dma_init_module); +module_exit(cam_jpeg_dma_exit_module); +MODULE_DESCRIPTION("CAM JPEG_DMA driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c new file mode 100644 index 000000000000..9dda8f284c35 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "jpeg_dma_soc.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t jpeg_dma_irq_handler, void *irq_data) +{ + int rc; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) + return rc; + + rc = cam_soc_util_request_platform_resource(soc_info, + jpeg_dma_irq_handler, + irq_data); + if (rc) + CAM_ERR(CAM_JPEG, "init soc failed %d", rc); + + return rc; +} + +int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, true); + if (rc) + CAM_ERR(CAM_JPEG, "enable platform failed %d", rc); + + return rc; +} + +int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) + CAM_ERR(CAM_JPEG, "disable platform failed %d", rc); + + return rc; +} diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h new file mode 100644 index 000000000000..a0c07489ee77 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_JPEG_DMA_SOC_H_ +#define _CAM_JPEG_DMA_SOC_H_ + +#include "cam_soc_util.h" + +int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t jpeg_dma_irq_handler, void *irq_data); + +int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +#endif /* _CAM_JPEG_DMA_SOC_H_*/ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile new file mode 100644 index 000000000000..159c54bbed0c --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw + +obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_dev.o jpeg_enc_core.o jpeg_enc_soc.o diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..79b0805d0348 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_ENC_HW_INFO_TITAN170_H +#define CAM_JPEG_ENC_HW_INFO_TITAN170_H + +#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001 +#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000 + +#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000 +#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a + +#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK 0x8000000 +#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_SHIFT 0x0000001b + +#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800 +#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b + +#define CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF (0x1<<19) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR (0x1<<20) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR (0x1<<21) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF (0x1<<22) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW (0x1<<23) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM (0x1<<24) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ (0x1<<25) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM (0x1<<26) +#define CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK (0x1<<29) + +#define CAM_JPEG_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK +#define CAM_JPEG_HW_MASK_COMP_RESET_ACK \ + CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK +#define CAM_JPEG_HW_MASK_COMP_ERR \ + (CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM | \ + CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK) + +static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x1c, + .int_status = 0x20, + .int_mask = 0x18, + .hw_cmd = 0x10, + .reset_cmd = 0x8, + .encode_size = 0x180, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x00032093, + .hw_cmd_stop = 0x00000002, + }, + .int_status = { + .framedone = CAM_JPEG_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK, + .iserror = CAM_JPEG_HW_MASK_COMP_ERR, + .stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK, + } +}; + +#endif /* CAM_JPEG_ENC_HW_INFO_TITAN170_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c new file mode 100644 index 000000000000..0b7bb7386553 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "jpeg_enc_core.h" +#include "jpeg_enc_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_jpeg_hw_intf.h" +#include "cam_jpeg_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +#define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.framedone) +#define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.resetdone) +#define CAM_JPEG_HW_IRQ_IS_ERR(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.iserror) +#define CAM_JPEG_HW_IRQ_IS_STOP_DONE(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.stopdone) + +#define CAM_JPEG_ENC_RESET_TIMEOUT msecs_to_jiffies(500) + +int cam_jpeg_enc_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_enc_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + int rc; + + if (!device_priv) { + CAM_ERR(CAM_JPEG, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + + if (!soc_info || !core_info) { + CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + mutex_lock(&core_info->core_mutex); + if (++core_info->ref_count > 1) { + mutex_unlock(&core_info->core_mutex); + return 0; + } + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 2; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = JPEG_VOTE; + axi_vote.axi_path[0].mnoc_ab_bw = JPEG_VOTE; + axi_vote.axi_path[0].mnoc_ib_bw = JPEG_VOTE; + axi_vote.axi_path[1].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[1].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[1].camnoc_bw = JPEG_VOTE; + axi_vote.axi_path[1].mnoc_ab_bw = JPEG_VOTE; + axi_vote.axi_path[1].mnoc_ib_bw = JPEG_VOTE; + + + rc = cam_cpas_start(core_info->cpas_handle, + &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_JPEG, "cpass start failed: %d", rc); + goto cpas_failed; + } + + rc = cam_jpeg_enc_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc); + goto soc_failed; + } + + mutex_unlock(&core_info->core_mutex); + + return 0; + +soc_failed: + cam_cpas_stop(core_info->cpas_handle); +cpas_failed: + --core_info->ref_count; + mutex_unlock(&core_info->core_mutex); + + return rc; +} + +int cam_jpeg_enc_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_enc_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + int rc; + + if (!device_priv) { + CAM_ERR(CAM_JPEG, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + if (!soc_info || !core_info) { + CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + mutex_lock(&core_info->core_mutex); + if (--core_info->ref_count > 0) { + mutex_unlock(&core_info->core_mutex); + return 0; + } + + if (core_info->ref_count < 0) { + CAM_ERR(CAM_JPEG, "ref cnt %d", core_info->ref_count); + core_info->ref_count = 0; + mutex_unlock(&core_info->core_mutex); + return -EFAULT; + } + + rc = cam_jpeg_enc_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_JPEG, "soc disable failed %d", rc); + + rc = cam_cpas_stop(core_info->cpas_handle); + if (rc) + CAM_ERR(CAM_JPEG, "cpas stop failed: %d", rc); + + mutex_unlock(&core_info->core_mutex); + + return 0; +} + +irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data) +{ + struct cam_hw_info *jpeg_enc_dev = data; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + uint32_t irq_status = 0; + uint32_t encoded_size = 0; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_enc_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + + if (!jpeg_enc_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return IRQ_HANDLED; + } + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + hw_info = core_info->jpeg_enc_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + irq_status = cam_io_r_mb(mem_base + + core_info->jpeg_enc_hw_info->reg_offset.int_status); + + cam_io_w_mb(irq_status, + soc_info->reg_map[0].mem_base + + core_info->jpeg_enc_hw_info->reg_offset.int_clr); + + CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d", + irq_num, irq_status, core_info->core_state); + + if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) { + spin_lock(&jpeg_enc_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_ENC_CORE_READY) { + encoded_size = cam_io_r_mb(mem_base + + core_info->jpeg_enc_hw_info->reg_offset.encode_size); + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + encoded_size, + core_info->irq_cb.data); + } else { + CAM_ERR(CAM_JPEG, "unexpected done, no cb"); + } + } else { + CAM_ERR(CAM_JPEG, "unexpected done irq"); + } + core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY; + spin_unlock(&jpeg_enc_dev->hw_lock); + } + if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status, hw_info)) { + spin_lock(&jpeg_enc_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) { + core_info->core_state = CAM_JPEG_ENC_CORE_READY; + complete(&jpeg_enc_dev->hw_complete); + } else { + CAM_ERR(CAM_JPEG, "unexpected reset irq"); + } + spin_unlock(&jpeg_enc_dev->hw_lock); + } + if (CAM_JPEG_HW_IRQ_IS_STOP_DONE(irq_status, hw_info)) { + spin_lock(&jpeg_enc_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) { + core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY; + complete(&jpeg_enc_dev->hw_complete); + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + -1, + core_info->irq_cb.data); + } + } else { + CAM_ERR(CAM_JPEG, "unexpected abort irq"); + } + spin_unlock(&jpeg_enc_dev->hw_lock); + } + /* Unexpected/unintended HW interrupt */ + if (CAM_JPEG_HW_IRQ_IS_ERR(irq_status, hw_info)) { + spin_lock(&jpeg_enc_dev->hw_lock); + core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY; + CAM_ERR_RATE_LIMIT(CAM_JPEG, + "error irq_num %d irq_status = %x , core_state %d", + irq_num, irq_status, core_info->core_state); + + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + -1, + core_info->irq_cb.data); + } + spin_unlock(&jpeg_enc_dev->hw_lock); + } + + return IRQ_HANDLED; +} + +int cam_jpeg_enc_reset_hw(void *data, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_enc_dev = data; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_enc_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + unsigned long rem_jiffies; + + if (!jpeg_enc_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + /* maskdisable.clrirq.maskenable.resetcmd */ + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + hw_info = core_info->jpeg_enc_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_enc_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) { + CAM_ERR(CAM_JPEG, "alrady resetting"); + spin_unlock(&jpeg_enc_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return 0; + } + + reinit_completion(&jpeg_enc_dev->hw_complete); + core_info->core_state = CAM_JPEG_ENC_CORE_RESETTING; + spin_unlock(&jpeg_enc_dev->hw_lock); + + cam_io_w_mb(hw_info->reg_val.int_mask_disable_all, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.int_clr_clearall, + mem_base + hw_info->reg_offset.int_clr); + cam_io_w_mb(hw_info->reg_val.int_mask_enable_all, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.reset_cmd, + mem_base + hw_info->reg_offset.reset_cmd); + + rem_jiffies = wait_for_completion_timeout(&jpeg_enc_dev->hw_complete, + CAM_JPEG_ENC_RESET_TIMEOUT); + if (!rem_jiffies) { + CAM_ERR(CAM_JPEG, "error Reset Timeout"); + core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY; + } + + mutex_unlock(&core_info->core_mutex); + return 0; +} + +int cam_jpeg_enc_start_hw(void *data, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_enc_dev = data; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_enc_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + + if (!jpeg_enc_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + hw_info = core_info->jpeg_enc_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) { + CAM_ERR(CAM_JPEG, "Error not ready"); + return -EINVAL; + } + + cam_io_w_mb(hw_info->reg_val.hw_cmd_start, + mem_base + hw_info->reg_offset.hw_cmd); + + return 0; +} + +int cam_jpeg_enc_stop_hw(void *data, + void *stop_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_enc_dev = data; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_enc_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + unsigned long rem_jiffies; + + if (!jpeg_enc_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + hw_info = core_info->jpeg_enc_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_enc_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) { + CAM_ERR(CAM_JPEG, "alrady stopping"); + spin_unlock(&jpeg_enc_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return 0; + } + + reinit_completion(&jpeg_enc_dev->hw_complete); + core_info->core_state = CAM_JPEG_ENC_CORE_ABORTING; + spin_unlock(&jpeg_enc_dev->hw_lock); + + cam_io_w_mb(hw_info->reg_val.hw_cmd_stop, + mem_base + hw_info->reg_offset.hw_cmd); + + rem_jiffies = wait_for_completion_timeout(&jpeg_enc_dev->hw_complete, + CAM_JPEG_ENC_RESET_TIMEOUT); + if (!rem_jiffies) { + CAM_ERR(CAM_JPEG, "error Reset Timeout"); + core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY; + } + + mutex_unlock(&core_info->core_mutex); + return 0; +} + +int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_enc_dev = device_priv; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + int rc; + + if (!device_priv) { + CAM_ERR(CAM_JPEG, "Invalid arguments"); + return -EINVAL; + } + + if (cmd_type >= CAM_JPEG_CMD_MAX) { + CAM_ERR(CAM_JPEG, "Invalid command : %x", cmd_type); + return -EINVAL; + } + + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + + switch (cmd_type) { + case CAM_JPEG_CMD_SET_IRQ_CB: + { + struct cam_jpeg_set_irq_cb *irq_cb = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_JPEG, "cmd args NULL"); + return -EINVAL; + } + if (irq_cb->b_set_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb = + irq_cb->jpeg_hw_mgr_cb; + core_info->irq_cb.data = irq_cb->data; + } else { + core_info->irq_cb.jpeg_hw_mgr_cb = NULL; + core_info->irq_cb.data = NULL; + } + rc = 0; + break; + } + default: + rc = -EINVAL; + break; + } + if (rc) + CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc); + return rc; +} diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h new file mode 100644 index 000000000000..df9341c90c77 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_ENC_CORE_H +#define CAM_JPEG_ENC_CORE_H + +#include +#include +#include +#include + +#include "cam_jpeg_hw_intf.h" + +struct cam_jpeg_enc_reg_offsets { + uint32_t hw_version; + uint32_t int_status; + uint32_t int_clr; + uint32_t int_mask; + uint32_t hw_cmd; + uint32_t reset_cmd; + uint32_t encode_size; +}; + +struct cam_jpeg_enc_regval { + uint32_t int_clr_clearall; + uint32_t int_mask_disable_all; + uint32_t int_mask_enable_all; + uint32_t hw_cmd_start; + uint32_t reset_cmd; + uint32_t hw_cmd_stop; +}; + +struct cam_jpeg_enc_int_status { + uint32_t framedone; + uint32_t resetdone; + uint32_t iserror; + uint32_t stopdone; +}; + +struct cam_jpeg_enc_device_hw_info { + struct cam_jpeg_enc_reg_offsets reg_offset; + struct cam_jpeg_enc_regval reg_val; + struct cam_jpeg_enc_int_status int_status; +}; + +enum cam_jpeg_enc_core_state { + CAM_JPEG_ENC_CORE_NOT_READY, + CAM_JPEG_ENC_CORE_READY, + CAM_JPEG_ENC_CORE_RESETTING, + CAM_JPEG_ENC_CORE_ABORTING, + CAM_JPEG_ENC_CORE_STATE_MAX, +}; + +struct cam_jpeg_enc_device_core_info { + enum cam_jpeg_enc_core_state core_state; + struct cam_jpeg_enc_device_hw_info *jpeg_enc_hw_info; + uint32_t cpas_handle; + struct cam_jpeg_set_irq_cb irq_cb; + int32_t ref_count; + struct mutex core_mutex; +}; + +int cam_jpeg_enc_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_jpeg_enc_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_jpeg_enc_start_hw(void *device_priv, + void *start_hw_args, uint32_t arg_size); +int cam_jpeg_enc_stop_hw(void *device_priv, + void *stop_hw_args, uint32_t arg_size); +int cam_jpeg_enc_reset_hw(void *device_priv, + void *reset_hw_args, uint32_t arg_size); +int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); +irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data); + +#endif /* CAM_JPEG_ENC_CORE_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c new file mode 100644 index 000000000000..8eb8ec367850 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "jpeg_enc_core.h" +#include "jpeg_enc_soc.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_io_util.h" +#include "cam_jpeg_hw_intf.h" +#include "cam_jpeg_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "cam_jpeg_enc_hw_info_ver_4_2_0.h" + +static int cam_jpeg_enc_register_cpas(struct cam_hw_soc_info *soc_info, + struct cam_jpeg_enc_device_core_info *core_info, + uint32_t hw_idx) +{ + struct cam_cpas_register_params cpas_register_params; + int rc; + + cpas_register_params.dev = soc_info->dev; + memcpy(cpas_register_params.identifier, "jpeg-enc", + sizeof("jpeg-enc")); + cpas_register_params.cam_cpas_client_cb = NULL; + cpas_register_params.cell_index = hw_idx; + cpas_register_params.userdata = NULL; + + rc = cam_cpas_register_client(&cpas_register_params); + if (rc) { + CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc); + return rc; + } + core_info->cpas_handle = cpas_register_params.client_handle; + + return rc; +} + +static int cam_jpeg_enc_unregister_cpas( + struct cam_jpeg_enc_device_core_info *core_info) +{ + int rc; + + rc = cam_cpas_unregister_client(core_info->cpas_handle); + if (rc) + CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc); + core_info->cpas_handle = 0; + + return rc; +} + +static int cam_jpeg_enc_remove(struct platform_device *pdev) +{ + struct cam_hw_info *jpeg_enc_dev = NULL; + struct cam_hw_intf *jpeg_enc_dev_intf = NULL; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + int rc; + + jpeg_enc_dev_intf = platform_get_drvdata(pdev); + if (!jpeg_enc_dev_intf) { + CAM_ERR(CAM_JPEG, "error No data in pdev"); + return -EINVAL; + } + + jpeg_enc_dev = jpeg_enc_dev_intf->hw_priv; + if (!jpeg_enc_dev) { + CAM_ERR(CAM_JPEG, "error HW data is NULL"); + rc = -ENODEV; + goto free_jpeg_hw_intf; + } + + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + if (!core_info) { + CAM_ERR(CAM_JPEG, "error core data NULL"); + goto deinit_soc; + } + + rc = cam_jpeg_enc_unregister_cpas(core_info); + if (rc) + CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); + + mutex_destroy(&core_info->core_mutex); + kfree(core_info); + +deinit_soc: + rc = cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&jpeg_enc_dev->hw_mutex); + kfree(jpeg_enc_dev); + +free_jpeg_hw_intf: + kfree(jpeg_enc_dev_intf); + return rc; +} + +static int cam_jpeg_enc_probe(struct platform_device *pdev) +{ + struct cam_hw_info *jpeg_enc_dev = NULL; + struct cam_hw_intf *jpeg_enc_dev_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + struct cam_jpeg_enc_device_hw_info *hw_info = NULL; + int rc; + + jpeg_enc_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!jpeg_enc_dev_intf) + return -ENOMEM; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &jpeg_enc_dev_intf->hw_idx); + + jpeg_enc_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!jpeg_enc_dev) { + rc = -ENOMEM; + goto error_alloc_dev; + } + jpeg_enc_dev->soc_info.pdev = pdev; + jpeg_enc_dev->soc_info.dev = &pdev->dev; + jpeg_enc_dev->soc_info.dev_name = pdev->name; + jpeg_enc_dev_intf->hw_priv = jpeg_enc_dev; + jpeg_enc_dev_intf->hw_ops.init = cam_jpeg_enc_init_hw; + jpeg_enc_dev_intf->hw_ops.deinit = cam_jpeg_enc_deinit_hw; + jpeg_enc_dev_intf->hw_ops.start = cam_jpeg_enc_start_hw; + jpeg_enc_dev_intf->hw_ops.stop = cam_jpeg_enc_stop_hw; + jpeg_enc_dev_intf->hw_ops.reset = cam_jpeg_enc_reset_hw; + jpeg_enc_dev_intf->hw_ops.process_cmd = cam_jpeg_enc_process_cmd; + jpeg_enc_dev_intf->hw_type = CAM_JPEG_DEV_ENC; + + platform_set_drvdata(pdev, jpeg_enc_dev_intf); + jpeg_enc_dev->core_info = + kzalloc(sizeof(struct cam_jpeg_enc_device_core_info), + GFP_KERNEL); + if (!jpeg_enc_dev->core_info) { + rc = -ENOMEM; + goto error_alloc_core; + } + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_JPEG, " No jpeg_enc hardware info"); + rc = -EINVAL; + goto error_match_dev; + } + hw_info = (struct cam_jpeg_enc_device_hw_info *)match_dev->data; + core_info->jpeg_enc_hw_info = hw_info; + core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY; + mutex_init(&core_info->core_mutex); + + rc = cam_jpeg_enc_init_soc_resources(&jpeg_enc_dev->soc_info, + cam_jpeg_enc_irq, + jpeg_enc_dev); + if (rc) { + CAM_ERR(CAM_JPEG, " failed to init_soc %d", rc); + goto error_init_soc; + } + + rc = cam_jpeg_enc_register_cpas(&jpeg_enc_dev->soc_info, + core_info, jpeg_enc_dev_intf->hw_idx); + if (rc) { + CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc); + goto error_reg_cpas; + } + jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&jpeg_enc_dev->hw_mutex); + spin_lock_init(&jpeg_enc_dev->hw_lock); + init_completion(&jpeg_enc_dev->hw_complete); + + return rc; + +error_reg_cpas: + cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info); +error_init_soc: + mutex_destroy(&core_info->core_mutex); +error_match_dev: + kfree(jpeg_enc_dev->core_info); +error_alloc_core: + kfree(jpeg_enc_dev); +error_alloc_dev: + kfree(jpeg_enc_dev_intf); + + return rc; +} + +static const struct of_device_id cam_jpeg_enc_dt_match[] = { + { + .compatible = "qcom,cam_jpeg_enc", + .data = &cam_jpeg_enc_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_jpeg_enc_dt_match); + +static struct platform_driver cam_jpeg_enc_driver = { + .probe = cam_jpeg_enc_probe, + .remove = cam_jpeg_enc_remove, + .driver = { + .name = "cam-jpeg-enc", + .owner = THIS_MODULE, + .of_match_table = cam_jpeg_enc_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_jpeg_enc_init_module(void) +{ + return platform_driver_register(&cam_jpeg_enc_driver); +} + +static void __exit cam_jpeg_enc_exit_module(void) +{ + platform_driver_unregister(&cam_jpeg_enc_driver); +} + +module_init(cam_jpeg_enc_init_module); +module_exit(cam_jpeg_enc_exit_module); +MODULE_DESCRIPTION("CAM JPEG_ENC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c new file mode 100644 index 000000000000..4a5d9e0a9b60 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "jpeg_enc_soc.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t jpeg_enc_irq_handler, void *irq_data) +{ + int rc; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) + return rc; + + rc = cam_soc_util_request_platform_resource(soc_info, + jpeg_enc_irq_handler, + irq_data); + if (rc) + CAM_ERR(CAM_JPEG, "init soc failed %d", rc); + + return rc; +} + +int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, true); + if (rc) + CAM_ERR(CAM_JPEG, "enable platform failed %d", rc); + + return rc; +} + +int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) + CAM_ERR(CAM_JPEG, "disable platform failed %d", rc); + + return rc; +} diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h new file mode 100644 index 000000000000..e0fb0103de75 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_JPEG_ENC_SOC_H_ +#define _CAM_JPEG_ENC_SOC_H_ + +#include "cam_soc_util.h" + +int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t jpeg_enc_irq_handler, void *irq_data); + +int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +#endif /* _CAM_JPEG_ENC_SOC_H_*/ diff --git a/drivers/cam_lrme/Makefile b/drivers/cam_lrme/Makefile new file mode 100644 index 000000000000..afc585ebf374 --- /dev/null +++ b/drivers/cam_lrme/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/ + +obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_dev.o cam_lrme_context.o diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c new file mode 100644 index 000000000000..3270d77af5fe --- /dev/null +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include + +#include "cam_debug_util.h" +#include "cam_lrme_context.h" + +static const char lrme_dev_name[] = "lrme"; + +static int __cam_lrme_ctx_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc = 0; + uintptr_t ctxt_to_hw_map = (uintptr_t)ctx->ctxt_to_hw_map; + struct cam_lrme_context *lrme_ctx = ctx->ctx_priv; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_acquire_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to acquire"); + return rc; + } + + ctxt_to_hw_map |= (lrme_ctx->index << CAM_LRME_CTX_INDEX_SHIFT); + ctx->ctxt_to_hw_map = (void *)ctxt_to_hw_map; + + ctx->state = CAM_CTX_ACQUIRED; + + return rc; +} + +static int __cam_lrme_ctx_release_dev_in_acquired(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to release"); + return rc; + } + + ctx->state = CAM_CTX_AVAILABLE; + + return rc; +} + +static int __cam_lrme_ctx_start_dev_in_acquired(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_start_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to start"); + return rc; + } + + ctx->state = CAM_CTX_ACTIVATED; + + return rc; +} + +static int __cam_lrme_ctx_config_dev_in_activated(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_prepare_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to config"); + return rc; + } + + return rc; +} + +static int __cam_lrme_ctx_flush_dev_in_activated(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + int rc; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_flush_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_LRME, "Failed to flush device"); + + return rc; +} +static int __cam_lrme_ctx_stop_dev_in_activated(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_stop_dev_to_hw(ctx); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to stop dev"); + return rc; + } + + ctx->state = CAM_CTX_ACQUIRED; + + return rc; +} + +static int __cam_lrme_ctx_release_dev_in_activated(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = __cam_lrme_ctx_stop_dev_in_activated(ctx, NULL); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to stop"); + return rc; + } + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to release"); + return rc; + } + + ctx->state = CAM_CTX_AVAILABLE; + + return rc; +} + +static int __cam_lrme_ctx_handle_irq_in_activated(void *context, + uint32_t evt_id, void *evt_data) +{ + int rc; + + CAM_DBG(CAM_LRME, "Enter"); + + rc = cam_context_buf_done_from_hw(context, evt_data, evt_id); + if (rc) { + CAM_ERR(CAM_LRME, "Failed in buf done, rc=%d", rc); + return rc; + } + + return rc; +} + +/* top state machine */ +static struct cam_ctx_ops + cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = __cam_lrme_ctx_acquire_dev_in_available, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .config_dev = __cam_lrme_ctx_config_dev_in_activated, + .release_dev = __cam_lrme_ctx_release_dev_in_acquired, + .start_dev = __cam_lrme_ctx_start_dev_in_acquired, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Ready */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Activate */ + { + .ioctl_ops = { + .config_dev = __cam_lrme_ctx_config_dev_in_activated, + .release_dev = __cam_lrme_ctx_release_dev_in_activated, + .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, + .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, + }, + .crm_ops = {}, + .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, + }, +}; + +int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, + struct cam_context *base_ctx, + struct cam_hw_mgr_intf *hw_intf, + uint32_t index) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter"); + + if (!base_ctx || !lrme_ctx) { + CAM_ERR(CAM_LRME, "Invalid input"); + return -EINVAL; + } + + memset(lrme_ctx, 0, sizeof(*lrme_ctx)); + + rc = cam_context_init(base_ctx, lrme_dev_name, CAM_LRME, index, + NULL, hw_intf, lrme_ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to init context"); + return rc; + } + lrme_ctx->base = base_ctx; + lrme_ctx->index = index; + base_ctx->ctx_priv = lrme_ctx; + base_ctx->state_machine = cam_lrme_ctx_state_machine; + + return rc; +} + +int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter"); + + if (!lrme_ctx) { + CAM_ERR(CAM_LRME, "No ctx to deinit"); + return -EINVAL; + } + + rc = cam_context_deinit(lrme_ctx->base); + + memset(lrme_ctx, 0, sizeof(*lrme_ctx)); + return rc; +} diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h new file mode 100644 index 000000000000..8dfdc36501a9 --- /dev/null +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_CONTEXT_H_ +#define _CAM_LRME_CONTEXT_H_ + +#include "cam_context.h" +#include "cam_context_utils.h" +#include "cam_hw_mgr_intf.h" +#include "cam_req_mgr_interface.h" + +#define CAM_LRME_CTX_INDEX_SHIFT 32 + +/** + * struct cam_lrme_context + * + * @base : Base context pointer for this LRME context + * @req_base : List of base request for this LRME context + */ +struct cam_lrme_context { + struct cam_context *base; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + uint64_t index; +}; + +int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, + struct cam_context *base_ctx, struct cam_hw_mgr_intf *hw_intf, + uint32_t index); +int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx); + +#endif /* _CAM_LRME_CONTEXT_H_ */ diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c new file mode 100644 index 000000000000..7c09f2b435f5 --- /dev/null +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "cam_subdev.h" +#include "cam_node.h" +#include "cam_lrme_context.h" +#include "cam_lrme_hw_mgr.h" +#include "cam_lrme_hw_mgr_intf.h" + +#define CAM_LRME_DEV_NAME "cam-lrme" + +/** + * struct cam_lrme_dev + * + * @sd : Subdev information + * @ctx : List of base contexts + * @lrme_ctx : List of LRME contexts + * @lock : Mutex for LRME subdev + * @open_cnt : Open count of LRME subdev + */ +struct cam_lrme_dev { + struct cam_subdev sd; + struct cam_context ctx[CAM_CTX_MAX]; + struct cam_lrme_context lrme_ctx[CAM_CTX_MAX]; + struct mutex lock; + uint32_t open_cnt; +}; + +static struct cam_lrme_dev *g_lrme_dev; + +static int cam_lrme_dev_buf_done_cb(void *ctxt_to_hw_map, uint32_t evt_id, + void *evt_data) +{ + uint64_t index; + struct cam_context *ctx; + int rc; + + index = CAM_LRME_DECODE_CTX_INDEX(ctxt_to_hw_map); + CAM_DBG(CAM_LRME, "ctx index %llu, evt_id %u\n", index, evt_id); + ctx = &g_lrme_dev->ctx[index]; + rc = ctx->irq_cb_intf(ctx, evt_id, evt_data); + if (rc) + CAM_ERR(CAM_LRME, "irq callback failed"); + + return rc; +} + +static int cam_lrme_dev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_lrme_dev *lrme_dev = g_lrme_dev; + + if (!lrme_dev) { + CAM_ERR(CAM_LRME, + "LRME Dev not initialized, dev=%pK", lrme_dev); + return -ENODEV; + } + + mutex_lock(&lrme_dev->lock); + lrme_dev->open_cnt++; + mutex_unlock(&lrme_dev->lock); + + return 0; +} + +static int cam_lrme_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = 0; + struct cam_lrme_dev *lrme_dev = g_lrme_dev; + struct cam_node *node = v4l2_get_subdevdata(sd); + + if (!lrme_dev) { + CAM_ERR(CAM_LRME, "Invalid args"); + return -ENODEV; + } + + mutex_lock(&lrme_dev->lock); + if (lrme_dev->open_cnt <= 0) { + CAM_DBG(CAM_LRME, "LRME subdev is already closed"); + rc = -EINVAL; + goto end; + } + + lrme_dev->open_cnt--; + if (!node) { + CAM_ERR(CAM_LRME, "Node is NULL"); + rc = -EINVAL; + goto end; + } + + if (lrme_dev->open_cnt == 0) + cam_node_shutdown(node); + +end: + mutex_unlock(&lrme_dev->lock); + return rc; +} + +static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { + .open = cam_lrme_dev_open, + .close = cam_lrme_dev_close, +}; + +static int cam_lrme_dev_probe(struct platform_device *pdev) +{ + int rc; + int i; + struct cam_hw_mgr_intf hw_mgr_intf; + struct cam_node *node; + + g_lrme_dev = kzalloc(sizeof(struct cam_lrme_dev), GFP_KERNEL); + if (!g_lrme_dev) { + CAM_ERR(CAM_LRME, "No memory"); + return -ENOMEM; + } + g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops; + + mutex_init(&g_lrme_dev->lock); + + rc = cam_subdev_probe(&g_lrme_dev->sd, pdev, CAM_LRME_DEV_NAME, + CAM_LRME_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_LRME, "LRME cam_subdev_probe failed"); + goto free_mem; + } + node = (struct cam_node *)g_lrme_dev->sd.token; + + rc = cam_lrme_hw_mgr_init(&hw_mgr_intf, cam_lrme_dev_buf_done_cb); + if (rc) { + CAM_ERR(CAM_LRME, "Can not initialized LRME HW manager"); + goto unregister; + } + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_lrme_context_init(&g_lrme_dev->lrme_ctx[i], + &g_lrme_dev->ctx[i], + &node->hw_mgr_intf, i); + if (rc) { + CAM_ERR(CAM_LRME, "LRME context init failed"); + goto deinit_ctx; + } + } + + rc = cam_node_init(node, &hw_mgr_intf, g_lrme_dev->ctx, CAM_CTX_MAX, + CAM_LRME_DEV_NAME); + if (rc) { + CAM_ERR(CAM_LRME, "LRME node init failed"); + goto deinit_ctx; + } + + CAM_DBG(CAM_LRME, "%s probe complete", g_lrme_dev->sd.name); + + return 0; + +deinit_ctx: + for (--i; i >= 0; i--) { + if (cam_lrme_context_deinit(&g_lrme_dev->lrme_ctx[i])) + CAM_ERR(CAM_LRME, "LRME context %d deinit failed", i); + } +unregister: + if (cam_subdev_remove(&g_lrme_dev->sd)) + CAM_ERR(CAM_LRME, "Failed in subdev remove"); +free_mem: + kfree(g_lrme_dev); + + return rc; +} + +static int cam_lrme_dev_remove(struct platform_device *pdev) +{ + int i; + int rc = 0; + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_lrme_context_deinit(&g_lrme_dev->lrme_ctx[i]); + if (rc) + CAM_ERR(CAM_LRME, "LRME context %d deinit failed", i); + } + + rc = cam_lrme_hw_mgr_deinit(); + if (rc) + CAM_ERR(CAM_LRME, "Failed in hw mgr deinit, rc=%d", rc); + + rc = cam_subdev_remove(&g_lrme_dev->sd); + if (rc) + CAM_ERR(CAM_LRME, "Unregister failed"); + + mutex_destroy(&g_lrme_dev->lock); + kfree(g_lrme_dev); + g_lrme_dev = NULL; + + return rc; +} + +static const struct of_device_id cam_lrme_dt_match[] = { + { + .compatible = "qcom,cam-lrme" + }, + {} +}; + +static struct platform_driver cam_lrme_driver = { + .probe = cam_lrme_dev_probe, + .remove = cam_lrme_dev_remove, + .driver = { + .name = "cam_lrme", + .owner = THIS_MODULE, + .of_match_table = cam_lrme_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_lrme_dev_init_module(void) +{ + return platform_driver_register(&cam_lrme_driver); +} + +static void __exit cam_lrme_dev_exit_module(void) +{ + platform_driver_unregister(&cam_lrme_driver); +} + +module_init(cam_lrme_dev_init_module); +module_exit(cam_lrme_dev_exit_module); +MODULE_DESCRIPTION("MSM LRME driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_lrme/lrme_hw_mgr/Makefile b/drivers/cam_lrme/lrme_hw_mgr/Makefile new file mode 100644 index 000000000000..3387c3d0f062 --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw +ccflags-y += -I$(srctree)/techpack/camera +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_mgr.o diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c new file mode 100644 index 000000000000..90b3f3fa442a --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -0,0 +1,1155 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_soc_util.h" +#include "cam_mem_mgr_api.h" +#include "cam_smmu_api.h" +#include "cam_packet_util.h" +#include "cam_lrme_context.h" +#include "cam_lrme_hw_intf.h" +#include "cam_lrme_hw_core.h" +#include "cam_lrme_hw_soc.h" +#include "cam_lrme_hw_mgr_intf.h" +#include "cam_lrme_hw_mgr.h" + +static struct cam_lrme_hw_mgr g_lrme_hw_mgr; + +static int cam_lrme_mgr_util_reserve_device(struct cam_lrme_hw_mgr *hw_mgr, + struct cam_lrme_acquire_args *lrme_acquire_args) +{ + int i, index = 0; + uint32_t min_ctx = UINT_MAX; + struct cam_lrme_device *hw_device = NULL; + + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (!hw_mgr->device_count) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_LRME, "No device is registered"); + return -EINVAL; + } + + for (i = 0; i < hw_mgr->device_count && i < CAM_LRME_HW_MAX; i++) { + hw_device = &hw_mgr->hw_device[i]; + if (!hw_device->num_context) { + index = i; + break; + } + if (hw_device->num_context < min_ctx) { + min_ctx = hw_device->num_context; + index = i; + } + } + + hw_device = &hw_mgr->hw_device[index]; + hw_device->num_context++; + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + CAM_DBG(CAM_LRME, "reserve device index %d", index); + + return index; +} + +static int cam_lrme_mgr_util_get_device(struct cam_lrme_hw_mgr *hw_mgr, + uint32_t device_index, struct cam_lrme_device **hw_device) +{ + if (!hw_mgr) { + CAM_ERR(CAM_LRME, "invalid params hw_mgr %pK", hw_mgr); + return -EINVAL; + } + + if (device_index >= CAM_LRME_HW_MAX) { + CAM_ERR(CAM_LRME, "Wrong device index %d", device_index); + return -EINVAL; + } + + *hw_device = &hw_mgr->hw_device[device_index]; + + return 0; +} + +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; + + if (!packet) { + CAM_ERR(CAM_LRME, "Invalid args"); + return -EINVAL; + } + + CAM_DBG(CAM_LRME, "Packet request=%d, op_code=0x%x, size=%d, flags=%d", + packet->header.request_id, packet->header.op_code, + packet->header.size, packet->header.flags); + CAM_DBG(CAM_LRME, + "Packet cmdbuf(offset=%d, num=%d) io(offset=%d, num=%d)", + packet->cmd_buf_offset, packet->num_cmd_buf, + packet->io_configs_offset, packet->num_io_configs); + CAM_DBG(CAM_LRME, + "Packet Patch(offset=%d, num=%d) kmd(offset=%d, num=%d)", + packet->patch_offset, packet->num_patches, + packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index); + + 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, + packet->io_configs_offset, packet->header.size); + return -EINVAL; + } + + if (!packet->num_io_configs) { + CAM_ERR(CAM_LRME, "no io configs"); + return -EINVAL; + } + + cmd_desc = (struct cam_cmd_buf_desc *)((uint8_t *)&packet->payload + + packet->cmd_buf_offset); + + for (i = 0; i < packet->num_cmd_buf; i++) { + if (!cmd_desc[i].length) + continue; + + CAM_DBG(CAM_LRME, + "CmdBuf[%d] hdl=%d, offset=%d, size=%d, len=%d, type=%d, meta_data=%d", + i, + cmd_desc[i].mem_handle, cmd_desc[i].offset, + cmd_desc[i].size, cmd_desc[i].length, cmd_desc[i].type, + cmd_desc[i].meta_data); + + rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); + if (rc) { + CAM_ERR(CAM_LRME, "Invalid cmd buffer %d", i); + return rc; + } + } + + return 0; +} + +static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl, + struct cam_hw_prepare_update_args *prepare, + struct cam_lrme_hw_io_buffer *input_buf, + struct cam_lrme_hw_io_buffer *output_buf, uint32_t io_buf_size) +{ + int rc = -EINVAL; + uint32_t num_in_buf, num_out_buf, i, j, plane; + struct cam_buf_io_cfg *io_cfg; + uint64_t io_addr[CAM_PACKET_MAX_PLANES]; + size_t size; + + num_in_buf = 0; + num_out_buf = 0; + io_cfg = (struct cam_buf_io_cfg *)((uint8_t *) + &prepare->packet->payload + + prepare->packet->io_configs_offset); + + for (i = 0; i < prepare->packet->num_io_configs; i++) { + CAM_DBG(CAM_LRME, + "IOConfig[%d] : handle[%d] Dir[%d] Res[%d] Fence[%d], Format[%d]", + i, io_cfg[i].mem_handle[0], io_cfg[i].direction, + io_cfg[i].resource_type, + io_cfg[i].fence, io_cfg[i].format); + + memset(io_addr, 0, sizeof(io_addr)); + for (plane = 0; plane < CAM_PACKET_MAX_PLANES; plane++) { + if (!io_cfg[i].mem_handle[plane]) + break; + + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[plane], + iommu_hdl, &io_addr[plane], &size); + if (rc) { + CAM_ERR(CAM_LRME, "Cannot get io buf for %d %d", + plane, rc); + 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", + io_cfg[i].direction, plane, io_addr[plane]); + } + + switch (io_cfg[i].direction) { + case CAM_BUF_INPUT: { + if (num_in_buf >= io_buf_size) { + CAM_ERR(CAM_LRME, + "Invalid number of buffers %d %d %d", + num_in_buf, num_out_buf, io_buf_size); + return -EINVAL; + } + prepare->in_map_entries[num_in_buf].resource_handle = + io_cfg[i].resource_type; + prepare->in_map_entries[num_in_buf].sync_id = + io_cfg[i].fence; + + input_buf[num_in_buf].valid = true; + for (j = 0; j < plane; j++) + input_buf[num_in_buf].io_addr[j] = io_addr[j]; + input_buf[num_in_buf].num_plane = plane; + input_buf[num_in_buf].io_cfg = &io_cfg[i]; + + num_in_buf++; + break; + } + case CAM_BUF_OUTPUT: { + if (num_out_buf >= io_buf_size) { + CAM_ERR(CAM_LRME, + "Invalid number of buffers %d %d %d", + num_in_buf, num_out_buf, io_buf_size); + return -EINVAL; + } + prepare->out_map_entries[num_out_buf].resource_handle = + io_cfg[i].resource_type; + prepare->out_map_entries[num_out_buf].sync_id = + io_cfg[i].fence; + + output_buf[num_out_buf].valid = true; + for (j = 0; j < plane; j++) + output_buf[num_out_buf].io_addr[j] = io_addr[j]; + output_buf[num_out_buf].num_plane = plane; + output_buf[num_out_buf].io_cfg = &io_cfg[i]; + + num_out_buf++; + break; + } + default: + CAM_ERR(CAM_LRME, "Unsupported io direction %d", + io_cfg[i].direction); + return -EINVAL; + } + } + prepare->num_in_map_entries = num_in_buf; + prepare->num_out_map_entries = num_out_buf; + + return 0; +} + +static int cam_lrme_mgr_util_prepare_hw_update_entries( + struct cam_lrme_hw_mgr *hw_mgr, + struct cam_hw_prepare_update_args *prepare, + struct cam_lrme_hw_cmd_config_args *config_args, + struct cam_kmd_buf_info *kmd_buf_info) +{ + int i, rc = 0; + struct cam_lrme_device *hw_device = NULL; + uint32_t *kmd_buf_addr; + uint32_t num_entry; + uint32_t kmd_buf_max_size; + uint32_t kmd_buf_used_bytes = 0; + struct cam_hw_update_entry *hw_entry; + struct cam_cmd_buf_desc *cmd_desc = NULL; + + hw_device = config_args->hw_device; + if (!hw_device) { + CAM_ERR(CAM_LRME, "Invalid hw_device"); + return -EINVAL; + } + + kmd_buf_addr = (uint32_t *)((uint8_t *)kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes); + kmd_buf_max_size = kmd_buf_info->size - kmd_buf_info->used_bytes; + + config_args->cmd_buf_addr = kmd_buf_addr; + config_args->size = kmd_buf_max_size; + config_args->config_buf_size = 0; + + if (hw_device->hw_intf.hw_ops.process_cmd) { + rc = hw_device->hw_intf.hw_ops.process_cmd( + hw_device->hw_intf.hw_priv, + CAM_LRME_HW_CMD_PREPARE_HW_UPDATE, + config_args, + sizeof(struct cam_lrme_hw_cmd_config_args)); + if (rc) { + CAM_ERR(CAM_LRME, + "Failed in CMD_PREPARE_HW_UPDATE %d", rc); + return rc; + } + } else { + CAM_ERR(CAM_LRME, "Can't find handle function"); + return -EINVAL; + } + + kmd_buf_used_bytes += config_args->config_buf_size; + + if (!kmd_buf_used_bytes || (kmd_buf_used_bytes > kmd_buf_max_size)) { + CAM_ERR(CAM_LRME, "Invalid kmd used bytes %d (%d)", + kmd_buf_used_bytes, kmd_buf_max_size); + return -ENOMEM; + } + + hw_entry = prepare->hw_update_entries; + num_entry = 0; + + if (config_args->config_buf_size) { + if ((num_entry + 1) >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_LRME, "Insufficient HW entries :%d %d", + num_entry, prepare->max_hw_update_entries); + return -EINVAL; + } + + hw_entry[num_entry].handle = kmd_buf_info->handle; + hw_entry[num_entry].len = config_args->config_buf_size; + hw_entry[num_entry].offset = kmd_buf_info->offset; + + kmd_buf_info->used_bytes += config_args->config_buf_size; + kmd_buf_info->offset += config_args->config_buf_size; + num_entry++; + } + + cmd_desc = (struct cam_cmd_buf_desc *)((uint8_t *) + &prepare->packet->payload + prepare->packet->cmd_buf_offset); + + for (i = 0; i < prepare->packet->num_cmd_buf; i++) { + if (!cmd_desc[i].length) + continue; + + if ((num_entry + 1) >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_LRME, "Exceed max num of entry"); + return -EINVAL; + } + + hw_entry[num_entry].handle = cmd_desc[i].mem_handle; + hw_entry[num_entry].len = cmd_desc[i].length; + hw_entry[num_entry].offset = cmd_desc[i].offset; + num_entry++; + } + prepare->num_hw_update_entries = num_entry; + + CAM_DBG(CAM_LRME, "FinalConfig : hw_entries=%d, Sync(in=%d, out=%d)", + prepare->num_hw_update_entries, prepare->num_in_map_entries, + prepare->num_out_map_entries); + + return rc; +} + +static void cam_lrme_mgr_util_put_frame_req( + struct list_head *src_list, + struct list_head *list, + spinlock_t *lock) +{ + spin_lock(lock); + list_add_tail(list, src_list); + spin_unlock(lock); +} + +static int cam_lrme_mgr_util_get_frame_req( + struct list_head *src_list, + struct cam_lrme_frame_request **frame_req, + spinlock_t *lock) +{ + int rc = 0; + struct cam_lrme_frame_request *req_ptr = NULL; + + spin_lock(lock); + if (!list_empty(src_list)) { + req_ptr = list_first_entry(src_list, + struct cam_lrme_frame_request, frame_list); + list_del_init(&req_ptr->frame_list); + } else { + rc = -ENOENT; + } + *frame_req = req_ptr; + spin_unlock(lock); + + return rc; +} + + +static int cam_lrme_mgr_util_submit_req(void *priv, void *data) +{ + struct cam_lrme_device *hw_device; + struct cam_lrme_hw_mgr *hw_mgr; + struct cam_lrme_frame_request *frame_req = NULL; + struct cam_lrme_hw_submit_args submit_args; + struct cam_lrme_mgr_work_data *work_data; + int rc; + int req_prio = 0; + + if (!priv) { + CAM_ERR(CAM_LRME, "worker doesn't have private data"); + return -EINVAL; + } + + hw_mgr = (struct cam_lrme_hw_mgr *)priv; + work_data = (struct cam_lrme_mgr_work_data *)data; + hw_device = work_data->hw_device; + + rc = cam_lrme_mgr_util_get_frame_req( + &hw_device->frame_pending_list_high, &frame_req, + &hw_device->high_req_lock); + + if (!frame_req) { + rc = cam_lrme_mgr_util_get_frame_req( + &hw_device->frame_pending_list_normal, &frame_req, + &hw_device->normal_req_lock); + if (frame_req) + req_prio = 1; + } + + if (!frame_req) { + CAM_DBG(CAM_LRME, "No pending request"); + return 0; + } + + if (hw_device->hw_intf.hw_ops.process_cmd) { + submit_args.hw_update_entries = frame_req->hw_update_entries; + submit_args.num_hw_update_entries = + frame_req->num_hw_update_entries; + submit_args.frame_req = frame_req; + + rc = hw_device->hw_intf.hw_ops.process_cmd( + hw_device->hw_intf.hw_priv, + CAM_LRME_HW_CMD_SUBMIT, + &submit_args, sizeof(struct cam_lrme_hw_submit_args)); + + if (rc == -EBUSY) + CAM_DBG(CAM_LRME, "device busy"); + else if (rc) + CAM_ERR(CAM_LRME, "submit request failed rc %d", rc); + if (rc) { + req_prio == 0 ? spin_lock(&hw_device->high_req_lock) : + spin_lock(&hw_device->normal_req_lock); + list_add(&frame_req->frame_list, + (req_prio == 0 ? + &hw_device->frame_pending_list_high : + &hw_device->frame_pending_list_normal)); + req_prio == 0 ? spin_unlock(&hw_device->high_req_lock) : + spin_unlock(&hw_device->normal_req_lock); + } + if (rc == -EBUSY) + rc = 0; + } else { + req_prio == 0 ? spin_lock(&hw_device->high_req_lock) : + spin_lock(&hw_device->normal_req_lock); + list_add(&frame_req->frame_list, + (req_prio == 0 ? + &hw_device->frame_pending_list_high : + &hw_device->frame_pending_list_normal)); + req_prio == 0 ? spin_unlock(&hw_device->high_req_lock) : + spin_unlock(&hw_device->normal_req_lock); + rc = -EINVAL; + } + + CAM_DBG(CAM_LRME, "End of submit, rc %d", rc); + + return rc; +} + +static int cam_lrme_mgr_util_schedule_frame_req( + struct cam_lrme_hw_mgr *hw_mgr, struct cam_lrme_device *hw_device) +{ + int rc = 0; + struct crm_workq_task *task; + struct cam_lrme_mgr_work_data *work_data; + + task = cam_req_mgr_workq_get_task(hw_device->work); + if (!task) { + CAM_ERR(CAM_LRME, "Can not get task for worker"); + return -ENOMEM; + } + + work_data = (struct cam_lrme_mgr_work_data *)task->payload; + work_data->hw_device = hw_device; + + task->process_cb = cam_lrme_mgr_util_submit_req; + CAM_DBG(CAM_LRME, "enqueue submit task"); + rc = cam_req_mgr_workq_enqueue_task(task, hw_mgr, CRM_TASK_PRIORITY_0); + + return rc; +} + +static int cam_lrme_mgr_util_release(struct cam_lrme_hw_mgr *hw_mgr, + uint32_t device_index) +{ + int rc = 0; + struct cam_lrme_device *hw_device; + + rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device); + if (rc) { + CAM_ERR(CAM_LRME, "Error in getting device %d", rc); + return rc; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + hw_device->num_context--; + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +} + +static int cam_lrme_mgr_cb(void *data, + struct cam_lrme_hw_cb_args *cb_args) +{ + struct cam_lrme_hw_mgr *hw_mgr = &g_lrme_hw_mgr; + int rc = 0; + bool frame_abort = true; + struct cam_lrme_frame_request *frame_req; + struct cam_lrme_device *hw_device; + + if (!data || !cb_args) { + CAM_ERR(CAM_LRME, "Invalid input args"); + return -EINVAL; + } + + hw_device = (struct cam_lrme_device *)data; + frame_req = cb_args->frame_req; + + if (cb_args->cb_type & CAM_LRME_CB_PUT_FRAME) { + memset(frame_req, 0x0, sizeof(*frame_req)); + INIT_LIST_HEAD(&frame_req->frame_list); + cam_lrme_mgr_util_put_frame_req(&hw_mgr->frame_free_list, + &frame_req->frame_list, + &hw_mgr->free_req_lock); + cb_args->cb_type &= ~CAM_LRME_CB_PUT_FRAME; + frame_req = NULL; + } + + if (cb_args->cb_type & CAM_LRME_CB_COMP_REG_UPDATE) { + cb_args->cb_type &= ~CAM_LRME_CB_COMP_REG_UPDATE; + CAM_DBG(CAM_LRME, "Reg update"); + } + + if (!frame_req) + return rc; + + if (cb_args->cb_type & CAM_LRME_CB_BUF_DONE) { + cb_args->cb_type &= ~CAM_LRME_CB_BUF_DONE; + frame_abort = false; + } else if (cb_args->cb_type & CAM_LRME_CB_ERROR) { + cb_args->cb_type &= ~CAM_LRME_CB_ERROR; + frame_abort = true; + } else { + CAM_ERR(CAM_LRME, "Wrong cb type %d, req %lld", + cb_args->cb_type, frame_req->req_id); + return -EINVAL; + } + + if (hw_mgr->event_cb) { + struct cam_hw_done_event_data buf_data; + + buf_data.request_id = frame_req->req_id; + CAM_DBG(CAM_LRME, "frame req %llu, frame_abort %d", + frame_req->req_id, frame_abort); + rc = hw_mgr->event_cb(frame_req->ctxt_to_hw_map, + frame_abort, &buf_data); + } else { + CAM_ERR(CAM_LRME, "No cb function"); + } + memset(frame_req, 0x0, sizeof(*frame_req)); + INIT_LIST_HEAD(&frame_req->frame_list); + cam_lrme_mgr_util_put_frame_req(&hw_mgr->frame_free_list, + &frame_req->frame_list, + &hw_mgr->free_req_lock); + + rc = cam_lrme_mgr_util_schedule_frame_req(hw_mgr, hw_device); + + return rc; +} + +static int cam_lrme_mgr_get_caps(void *hw_mgr_priv, void *hw_get_caps_args) +{ + int rc = 0; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *args = hw_get_caps_args; + + if (sizeof(struct cam_lrme_query_cap_cmd) != args->size) { + CAM_ERR(CAM_LRME, + "sizeof(struct cam_query_cap_cmd) = %zu, args->size = %d", + sizeof(struct cam_query_cap_cmd), args->size); + return -EFAULT; + } + + if (copy_to_user(u64_to_user_ptr(args->caps_handle), + &(hw_mgr->lrme_caps), + sizeof(struct cam_lrme_query_cap_cmd))) { + CAM_ERR(CAM_LRME, "copy to user failed"); + return -EFAULT; + } + + return rc; +} + +static int cam_lrme_mgr_hw_acquire(void *hw_mgr_priv, void *hw_acquire_args) +{ + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_acquire_args *args = + (struct cam_hw_acquire_args *)hw_acquire_args; + struct cam_lrme_acquire_args lrme_acquire_args; + uintptr_t device_index; + + if (!hw_mgr_priv || !args) { + CAM_ERR(CAM_LRME, + "Invalid input params hw_mgr_priv %pK, acquire_args %pK", + hw_mgr_priv, args); + return -EINVAL; + } + + if (copy_from_user(&lrme_acquire_args, + (void __user *)args->acquire_info, + sizeof(struct cam_lrme_acquire_args))) { + CAM_ERR(CAM_LRME, "Failed to copy acquire args from user"); + return -EFAULT; + } + + device_index = cam_lrme_mgr_util_reserve_device(hw_mgr, + &lrme_acquire_args); + CAM_DBG(CAM_LRME, "Get device id %llu", device_index); + + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Get wrong device id %lu", device_index); + return -EINVAL; + } + + /* device_index is the right 4 bit in ctxt_to_hw_map */ + args->ctxt_to_hw_map = (void *)device_index; + + return 0; +} + +static int cam_lrme_mgr_hw_release(void *hw_mgr_priv, void *hw_release_args) +{ + int rc = 0; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_release_args *args = + (struct cam_hw_release_args *)hw_release_args; + uint64_t device_index; + + if (!hw_mgr_priv || !hw_release_args) { + CAM_ERR(CAM_LRME, "Invalid arguments %pK, %pK", + hw_mgr_priv, hw_release_args); + return -EINVAL; + } + + device_index = CAM_LRME_DECODE_DEVICE_INDEX(args->ctxt_to_hw_map); + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Invalid device index %llu", device_index); + return -EPERM; + } + + rc = cam_lrme_mgr_util_release(hw_mgr, device_index); + if (rc) + CAM_ERR(CAM_LRME, "Failed in release device, rc=%d", rc); + + return rc; +} + +static int cam_lrme_mgr_hw_flush(void *hw_mgr_priv, void *hw_flush_args) +{ int rc = 0, i; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_flush_args *args; + struct cam_lrme_device *hw_device; + struct cam_lrme_frame_request *frame_req = NULL, *req_to_flush = NULL; + struct cam_lrme_frame_request **req_list = NULL; + uint32_t device_index; + struct cam_lrme_hw_flush_args lrme_flush_args; + uint32_t priority; + + if (!hw_mgr_priv || !hw_flush_args) { + CAM_ERR(CAM_LRME, "Invalid args %pK %pK", + hw_mgr_priv, hw_flush_args); + return -EINVAL; + } + + args = (struct cam_hw_flush_args *)hw_flush_args; + device_index = ((uintptr_t)args->ctxt_to_hw_map & 0xF); + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Invalid device index %d", device_index); + return -EPERM; + } + + rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device); + if (rc) { + CAM_ERR(CAM_LRME, "Error in getting device %d", rc); + goto end; + } + + req_list = (struct cam_lrme_frame_request **)args->flush_req_pending; + for (i = 0; i < args->num_req_pending; i++) { + frame_req = req_list[i]; + memset(frame_req, 0x0, sizeof(*frame_req)); + cam_lrme_mgr_util_put_frame_req(&hw_mgr->frame_free_list, + &frame_req->frame_list, &hw_mgr->free_req_lock); + } + + req_list = (struct cam_lrme_frame_request **)args->flush_req_active; + for (i = 0; i < args->num_req_active; i++) { + frame_req = req_list[i]; + priority = CAM_LRME_DECODE_PRIORITY(args->ctxt_to_hw_map); + spin_lock((priority == CAM_LRME_PRIORITY_HIGH) ? + &hw_device->high_req_lock : + &hw_device->normal_req_lock); + if (!list_empty(&frame_req->frame_list)) { + list_del_init(&frame_req->frame_list); + cam_lrme_mgr_util_put_frame_req( + &hw_mgr->frame_free_list, + &frame_req->frame_list, + &hw_mgr->free_req_lock); + } else + req_to_flush = frame_req; + spin_unlock((priority == CAM_LRME_PRIORITY_HIGH) ? + &hw_device->high_req_lock : + &hw_device->normal_req_lock); + } + if (!req_to_flush) + goto end; + if (hw_device->hw_intf.hw_ops.flush) { + lrme_flush_args.ctxt_to_hw_map = req_to_flush->ctxt_to_hw_map; + lrme_flush_args.flush_type = args->flush_type; + lrme_flush_args.req_to_flush = req_to_flush; + rc = hw_device->hw_intf.hw_ops.flush(hw_device->hw_intf.hw_priv, + &lrme_flush_args, + sizeof(lrme_flush_args)); + if (rc) { + CAM_ERR(CAM_LRME, "Failed in HW Stop %d", rc); + goto end; + } + } else { + CAM_ERR(CAM_LRME, "No stop ops"); + goto end; + } + +end: + return rc; +} + + +static int cam_lrme_mgr_hw_start(void *hw_mgr_priv, void *hw_start_args) +{ + int rc = 0; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_start_args *args = + (struct cam_hw_start_args *)hw_start_args; + struct cam_lrme_device *hw_device; + uint32_t device_index; + + if (!hw_mgr || !args) { + CAM_ERR(CAM_LRME, "Invalid input params"); + return -EINVAL; + } + + device_index = CAM_LRME_DECODE_DEVICE_INDEX(args->ctxt_to_hw_map); + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Invalid device index %d", device_index); + return -EPERM; + } + + CAM_DBG(CAM_LRME, "Start device index %d", device_index); + + rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to get hw device"); + return rc; + } + + if (hw_device->hw_intf.hw_ops.start) { + rc = hw_device->hw_intf.hw_ops.start( + hw_device->hw_intf.hw_priv, NULL, 0); + } else { + CAM_ERR(CAM_LRME, "Invalid start function"); + return -EINVAL; + } + + rc = hw_device->hw_intf.hw_ops.process_cmd( + hw_device->hw_intf.hw_priv, + CAM_LRME_HW_CMD_DUMP_REGISTER, + &g_lrme_hw_mgr.debugfs_entry.dump_register, + sizeof(bool)); + + return rc; +} + +static int cam_lrme_mgr_hw_stop(void *hw_mgr_priv, void *stop_args) +{ + int rc = 0; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_stop_args *args = + (struct cam_hw_stop_args *)stop_args; + struct cam_lrme_device *hw_device; + uint32_t device_index; + + if (!hw_mgr_priv || !stop_args) { + CAM_ERR(CAM_LRME, "Invalid arguments"); + return -EINVAL; + } + + device_index = CAM_LRME_DECODE_DEVICE_INDEX(args->ctxt_to_hw_map); + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Invalid device index %d", device_index); + return -EPERM; + } + + CAM_DBG(CAM_LRME, "Stop device index %d", device_index); + + rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to get hw device"); + return rc; + } + + if (hw_device->hw_intf.hw_ops.stop) { + rc = hw_device->hw_intf.hw_ops.stop( + hw_device->hw_intf.hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_LRME, "Failed in HW stop %d", rc); + goto end; + } + } + +end: + return rc; +} + +static int cam_lrme_mgr_hw_prepare_update(void *hw_mgr_priv, + void *hw_prepare_update_args) +{ + int rc = 0, i; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_prepare_update_args *args = + (struct cam_hw_prepare_update_args *)hw_prepare_update_args; + struct cam_lrme_device *hw_device; + struct cam_kmd_buf_info kmd_buf; + struct cam_lrme_hw_cmd_config_args config_args; + struct cam_lrme_frame_request *frame_req = NULL; + uint32_t device_index; + + if (!hw_mgr_priv || !hw_prepare_update_args) { + CAM_ERR(CAM_LRME, "Invalid args %pK %pK", + hw_mgr_priv, hw_prepare_update_args); + return -EINVAL; + } + + device_index = CAM_LRME_DECODE_DEVICE_INDEX(args->ctxt_to_hw_map); + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Invalid device index %d", device_index); + return -EPERM; + } + + rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device); + if (rc) { + CAM_ERR(CAM_LRME, "Error in getting device %d", rc); + goto error; + } + + 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; + } + + rc = cam_packet_util_get_kmd_buffer(args->packet, &kmd_buf); + if (rc) { + CAM_ERR(CAM_LRME, "Error in get kmd buf buffer %d", rc); + goto error; + } + + CAM_DBG(CAM_LRME, + "KMD Buf : hdl=%d, cpu_addr=%pK, offset=%d, size=%d, used=%d", + kmd_buf.handle, kmd_buf.cpu_addr, kmd_buf.offset, + kmd_buf.size, kmd_buf.used_bytes); + + rc = cam_packet_util_process_patches(args->packet, + hw_mgr->device_iommu.non_secure, hw_mgr->device_iommu.secure); + if (rc) { + CAM_ERR(CAM_LRME, "Patch packet failed, rc=%d", rc); + return rc; + } + + memset(&config_args, 0, sizeof(config_args)); + config_args.hw_device = hw_device; + + rc = cam_lrme_mgr_util_prepare_io_buffer( + hw_mgr->device_iommu.non_secure, args, + config_args.input_buf, config_args.output_buf, + CAM_LRME_MAX_IO_BUFFER); + if (rc) { + CAM_ERR(CAM_LRME, "Error in prepare IO Buf %d", rc); + goto error; + } + /* Check port number */ + if (args->num_in_map_entries == 0 || args->num_out_map_entries == 0) { + CAM_ERR(CAM_LRME, "Error in port number in %d, out %d", + args->num_in_map_entries, args->num_out_map_entries); + rc = -EINVAL; + goto error; + } + + rc = cam_lrme_mgr_util_prepare_hw_update_entries(hw_mgr, args, + &config_args, &kmd_buf); + if (rc) { + CAM_ERR(CAM_LRME, "Error in hw update entries %d", rc); + goto error; + } + + rc = cam_lrme_mgr_util_get_frame_req(&hw_mgr->frame_free_list, + &frame_req, &hw_mgr->free_req_lock); + if (rc || !frame_req) { + CAM_ERR(CAM_LRME, "Can not get free frame request"); + goto error; + } + + frame_req->ctxt_to_hw_map = args->ctxt_to_hw_map; + frame_req->req_id = args->packet->header.request_id; + frame_req->hw_device = hw_device; + frame_req->num_hw_update_entries = args->num_hw_update_entries; + for (i = 0; i < args->num_hw_update_entries; i++) + frame_req->hw_update_entries[i] = args->hw_update_entries[i]; + + args->priv = frame_req; + + CAM_DBG(CAM_LRME, "FramePrepare : Frame[%lld]", frame_req->req_id); + + return 0; + +error: + return rc; +} + +static int cam_lrme_mgr_hw_config(void *hw_mgr_priv, + void *hw_config_args) +{ + int rc = 0; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_config_args *args = + (struct cam_hw_config_args *)hw_config_args; + struct cam_lrme_frame_request *frame_req; + struct cam_lrme_device *hw_device = NULL; + enum cam_lrme_hw_mgr_ctx_priority priority; + + if (!hw_mgr_priv || !hw_config_args) { + CAM_ERR(CAM_LRME, "Invalid arguments, hw_mgr %pK, config %pK", + hw_mgr_priv, hw_config_args); + return -EINVAL; + } + + if (!args->num_hw_update_entries) { + CAM_ERR(CAM_LRME, "No hw update entries"); + return -EINVAL; + } + + frame_req = (struct cam_lrme_frame_request *)args->priv; + if (!frame_req) { + CAM_ERR(CAM_LRME, "No frame request"); + return -EINVAL; + } + + hw_device = frame_req->hw_device; + if (!hw_device) + return -EINVAL; + + priority = CAM_LRME_DECODE_PRIORITY(args->ctxt_to_hw_map); + if (priority == CAM_LRME_PRIORITY_HIGH) { + cam_lrme_mgr_util_put_frame_req( + &hw_device->frame_pending_list_high, + &frame_req->frame_list, &hw_device->high_req_lock); + } else { + cam_lrme_mgr_util_put_frame_req( + &hw_device->frame_pending_list_normal, + &frame_req->frame_list, &hw_device->normal_req_lock); + } + + CAM_DBG(CAM_LRME, "schedule req %llu", frame_req->req_id); + rc = cam_lrme_mgr_util_schedule_frame_req(hw_mgr, hw_device); + + return rc; +} + +static int cam_lrme_mgr_create_debugfs_entry(void) +{ + int rc = 0; + + g_lrme_hw_mgr.debugfs_entry.dentry = + debugfs_create_dir("camera_lrme", NULL); + if (!g_lrme_hw_mgr.debugfs_entry.dentry) { + CAM_ERR(CAM_LRME, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_bool("dump_register", + 0644, + g_lrme_hw_mgr.debugfs_entry.dentry, + &g_lrme_hw_mgr.debugfs_entry.dump_register)) { + CAM_ERR(CAM_LRME, "failed to create dump register entry"); + rc = -ENOMEM; + goto err; + } + + return rc; + +err: + debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); + g_lrme_hw_mgr.debugfs_entry.dentry = NULL; + return rc; +} + + +int cam_lrme_mgr_register_device( + struct cam_hw_intf *lrme_hw_intf, + struct cam_iommu_handle *device_iommu, + struct cam_iommu_handle *cdm_iommu) +{ + struct cam_lrme_device *hw_device; + char buf[128]; + int i, rc; + + hw_device = &g_lrme_hw_mgr.hw_device[lrme_hw_intf->hw_idx]; + + g_lrme_hw_mgr.device_iommu = *device_iommu; + g_lrme_hw_mgr.cdm_iommu = *cdm_iommu; + + memcpy(&hw_device->hw_intf, lrme_hw_intf, sizeof(struct cam_hw_intf)); + + spin_lock_init(&hw_device->high_req_lock); + spin_lock_init(&hw_device->normal_req_lock); + INIT_LIST_HEAD(&hw_device->frame_pending_list_high); + INIT_LIST_HEAD(&hw_device->frame_pending_list_normal); + + rc = snprintf(buf, sizeof(buf), "cam_lrme_device_submit_worker%d", + lrme_hw_intf->hw_idx); + CAM_DBG(CAM_LRME, "Create submit workq for %s", buf); + rc = cam_req_mgr_workq_create(buf, + CAM_LRME_WORKQ_NUM_TASK, + &hw_device->work, CRM_WORKQ_USAGE_NON_IRQ, + 0); + if (rc) { + CAM_ERR(CAM_LRME, + "Unable to create a worker, rc=%d", rc); + return rc; + } + + for (i = 0; i < CAM_LRME_WORKQ_NUM_TASK; i++) + hw_device->work->task.pool[i].payload = + &hw_device->work_data[i]; + + if (hw_device->hw_intf.hw_ops.process_cmd) { + struct cam_lrme_hw_cmd_set_cb cb_args; + + cb_args.cam_lrme_hw_mgr_cb = cam_lrme_mgr_cb; + cb_args.data = hw_device; + + rc = hw_device->hw_intf.hw_ops.process_cmd( + hw_device->hw_intf.hw_priv, + CAM_LRME_HW_CMD_REGISTER_CB, + &cb_args, sizeof(cb_args)); + if (rc) { + CAM_ERR(CAM_LRME, "Register cb failed"); + goto destroy_workqueue; + } + CAM_DBG(CAM_LRME, "cb registered"); + } + + if (hw_device->hw_intf.hw_ops.get_hw_caps) { + rc = hw_device->hw_intf.hw_ops.get_hw_caps( + hw_device->hw_intf.hw_priv, &hw_device->hw_caps, + sizeof(hw_device->hw_caps)); + if (rc) + CAM_ERR(CAM_LRME, "Get caps failed"); + } else { + CAM_ERR(CAM_LRME, "No get_hw_caps function"); + goto destroy_workqueue; + } + g_lrme_hw_mgr.lrme_caps.dev_caps[lrme_hw_intf->hw_idx] = + hw_device->hw_caps; + g_lrme_hw_mgr.device_count++; + g_lrme_hw_mgr.lrme_caps.device_iommu = g_lrme_hw_mgr.device_iommu; + g_lrme_hw_mgr.lrme_caps.cdm_iommu = g_lrme_hw_mgr.cdm_iommu; + g_lrme_hw_mgr.lrme_caps.num_devices = g_lrme_hw_mgr.device_count; + + hw_device->valid = true; + + CAM_DBG(CAM_LRME, "device registration done"); + return 0; + +destroy_workqueue: + cam_req_mgr_workq_destroy(&hw_device->work); + + return rc; +} + +int cam_lrme_mgr_deregister_device(int device_index) +{ + struct cam_lrme_device *hw_device; + + hw_device = &g_lrme_hw_mgr.hw_device[device_index]; + cam_req_mgr_workq_destroy(&hw_device->work); + memset(hw_device, 0x0, sizeof(struct cam_lrme_device)); + g_lrme_hw_mgr.device_count--; + + return 0; +} + +int cam_lrme_hw_mgr_deinit(void) +{ + mutex_destroy(&g_lrme_hw_mgr.hw_mgr_mutex); + memset(&g_lrme_hw_mgr, 0x0, sizeof(g_lrme_hw_mgr)); + + return 0; +} + +int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, + cam_hw_event_cb_func cam_lrme_dev_buf_done_cb) +{ + int i, rc = 0; + struct cam_lrme_frame_request *frame_req; + + if (!hw_mgr_intf) + return -EINVAL; + + CAM_DBG(CAM_LRME, "device count %d", g_lrme_hw_mgr.device_count); + if (g_lrme_hw_mgr.device_count > CAM_LRME_HW_MAX) { + CAM_ERR(CAM_LRME, "Invalid count of devices"); + return -EINVAL; + } + + memset(hw_mgr_intf, 0, sizeof(*hw_mgr_intf)); + + mutex_init(&g_lrme_hw_mgr.hw_mgr_mutex); + spin_lock_init(&g_lrme_hw_mgr.free_req_lock); + INIT_LIST_HEAD(&g_lrme_hw_mgr.frame_free_list); + + /* Init hw mgr frame requests and add to free list */ + for (i = 0; i < CAM_CTX_REQ_MAX * CAM_CTX_MAX; i++) { + frame_req = &g_lrme_hw_mgr.frame_req[i]; + + memset(frame_req, 0x0, sizeof(*frame_req)); + INIT_LIST_HEAD(&frame_req->frame_list); + + list_add_tail(&frame_req->frame_list, + &g_lrme_hw_mgr.frame_free_list); + } + + hw_mgr_intf->hw_mgr_priv = &g_lrme_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_lrme_mgr_get_caps; + hw_mgr_intf->hw_acquire = cam_lrme_mgr_hw_acquire; + hw_mgr_intf->hw_release = cam_lrme_mgr_hw_release; + hw_mgr_intf->hw_start = cam_lrme_mgr_hw_start; + hw_mgr_intf->hw_stop = cam_lrme_mgr_hw_stop; + hw_mgr_intf->hw_prepare_update = cam_lrme_mgr_hw_prepare_update; + hw_mgr_intf->hw_config = cam_lrme_mgr_hw_config; + hw_mgr_intf->hw_read = NULL; + hw_mgr_intf->hw_write = NULL; + hw_mgr_intf->hw_close = NULL; + hw_mgr_intf->hw_flush = cam_lrme_mgr_hw_flush; + + g_lrme_hw_mgr.event_cb = cam_lrme_dev_buf_done_cb; + + cam_lrme_mgr_create_debugfs_entry(); + + CAM_DBG(CAM_LRME, "Hw mgr init done"); + return rc; +} diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h new file mode 100644 index 000000000000..bc77e726d3e6 --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_HW_MGR_H_ +#define _CAM_LRME_HW_MGR_H_ + +#include +#include + +#include +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "cam_hw_mgr_intf.h" +#include "cam_req_mgr_workq.h" +#include "cam_lrme_hw_intf.h" +#include "cam_context.h" + +#define CAM_LRME_HW_MAX 1 +#define CAM_LRME_WORKQ_NUM_TASK 10 + +#define CAM_LRME_DECODE_DEVICE_INDEX(ctxt_to_hw_map) \ + ((uintptr_t)ctxt_to_hw_map & 0xF) + +#define CAM_LRME_DECODE_PRIORITY(ctxt_to_hw_map) \ + (((uintptr_t)ctxt_to_hw_map & 0xF0) >> 4) + +#define CAM_LRME_DECODE_CTX_INDEX(ctxt_to_hw_map) \ + ((uint64_t)(uintptr_t)ctxt_to_hw_map >> CAM_LRME_CTX_INDEX_SHIFT) + +/** + * enum cam_lrme_hw_mgr_ctx_priority + * + * CAM_LRME_PRIORITY_HIGH : High priority client + * CAM_LRME_PRIORITY_NORMAL : Normal priority client + */ +enum cam_lrme_hw_mgr_ctx_priority { + CAM_LRME_PRIORITY_HIGH, + CAM_LRME_PRIORITY_NORMAL, +}; + +/** + * struct cam_lrme_mgr_work_data : HW Mgr work data + * + * @hw_device : Pointer to the hw device + */ +struct cam_lrme_mgr_work_data { + struct cam_lrme_device *hw_device; +}; + +/** + * struct cam_lrme_debugfs_entry : debugfs entry struct + * + * @dentry : entry of debugfs + * @dump_register : flag to dump registers + */ +struct cam_lrme_debugfs_entry { + struct dentry *dentry; + bool dump_register; +}; + +/** + * struct cam_lrme_device : LRME HW device + * + * @hw_caps : HW device's capabilities + * @hw_intf : HW device's interface information + * @num_context : Number of contexts using this device + * @valid : Whether this device is valid + * @work : HW device's work queue + * @work_data : HW device's work data + * @frame_pending_list_high : High priority request queue + * @frame_pending_list_normal : Normal priority request queue + * @high_req_lock : Spinlock of high priority queue + * @normal_req_lock : Spinlock of normal priority queue + */ +struct cam_lrme_device { + struct cam_lrme_dev_cap hw_caps; + struct cam_hw_intf hw_intf; + uint32_t num_context; + bool valid; + struct cam_req_mgr_core_workq *work; + struct cam_lrme_mgr_work_data work_data[CAM_LRME_WORKQ_NUM_TASK]; + struct list_head frame_pending_list_high; + struct list_head frame_pending_list_normal; + spinlock_t high_req_lock; + spinlock_t normal_req_lock; +}; + +/** + * struct cam_lrme_hw_mgr : LRME HW manager + * + * @device_count : Number of HW devices + * @frame_free_list : List of free frame request + * @hw_mgr_mutex : Mutex to protect HW manager data + * @free_req_lock :Spinlock to protect frame_free_list + * @hw_device : List of HW devices + * @device_iommu : Device iommu + * @cdm_iommu : cdm iommu + * @frame_req : List of frame request to use + * @lrme_caps : LRME capabilities + * @event_cb : IRQ callback function + * @debugfs_entry : debugfs entry to set debug prop + */ +struct cam_lrme_hw_mgr { + uint32_t device_count; + struct list_head frame_free_list; + struct mutex hw_mgr_mutex; + spinlock_t free_req_lock; + struct cam_lrme_device hw_device[CAM_LRME_HW_MAX]; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + struct cam_lrme_frame_request frame_req[CAM_CTX_REQ_MAX * CAM_CTX_MAX]; + struct cam_lrme_query_cap_cmd lrme_caps; + cam_hw_event_cb_func event_cb; + struct cam_lrme_debugfs_entry debugfs_entry; +}; + +int cam_lrme_mgr_register_device(struct cam_hw_intf *lrme_hw_intf, + struct cam_iommu_handle *device_iommu, + struct cam_iommu_handle *cdm_iommu); +int cam_lrme_mgr_deregister_device(int device_index); + +#endif /* _CAM_LRME_HW_MGR_H_ */ diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr_intf.h b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr_intf.h new file mode 100644 index 000000000000..df6ea0eac798 --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr_intf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_HW_MGR_INTF_H_ +#define _CAM_LRME_HW_MGR_INTF_H_ + +#include + +#include "cam_debug_util.h" +#include "cam_hw_mgr_intf.h" + +int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, + cam_hw_event_cb_func cam_lrme_dev_buf_done_cb); +int cam_lrme_hw_mgr_deinit(void); + +#endif /* _CAM_LRME_HW_MGR_INTF_H_ */ diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile new file mode 100644 index 000000000000..8df30c0f44de --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw +ccflags-y += -I$(srctree)/techpack/camera0 +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_dev.o cam_lrme_hw_core.o cam_lrme_hw_soc.o diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c new file mode 100644 index 000000000000..b736708fa99d --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c @@ -0,0 +1,1274 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_lrme_hw_core.h" +#include "cam_lrme_hw_soc.h" +#include "cam_smmu_api.h" + +static void cam_lrme_dump_registers(void __iomem *base) +{ + /* dump the clc registers */ + cam_io_dump(base, 0x60, (0xc0 - 0x60) / 0x4); + /* dump the fe and we registers */ + cam_io_dump(base, 0x200, (0x29c - 0x200) / 0x4); + cam_io_dump(base, 0x2f0, (0x330 - 0x2f0) / 0x4); + cam_io_dump(base, 0x500, (0x5b4 - 0x500) / 0x4); + cam_io_dump(base, 0x700, (0x778 - 0x700) / 0x4); + cam_io_dump(base, 0x800, (0x878 - 0x800) / 0x4); + /* dump lrme sw registers, interrupts */ + cam_io_dump(base, 0x900, (0x928 - 0x900) / 0x4); +} + +static void cam_lrme_cdm_write_reg_val_pair(uint32_t *buffer, + uint32_t *index, uint32_t reg_offset, uint32_t reg_value) +{ + buffer[(*index)++] = reg_offset; + buffer[(*index)++] = reg_value; +} + +static void cam_lrme_hw_util_fill_fe_reg(struct cam_lrme_hw_io_buffer *io_buf, + uint32_t index, uint32_t *reg_val_pair, uint32_t *num_cmd, + struct cam_lrme_hw_info *hw_info) +{ + uint32_t reg_val; + + /* 1. config buffer size */ + 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, + reg_val); + + CAM_DBG(CAM_LRME, + "width %d", io_buf->io_cfg->planes[0].width); + CAM_DBG(CAM_LRME, + "height %d", io_buf->io_cfg->planes[0].height); + + /* 2. config image address */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_rd_reg.bus_client_reg[index].addr_image, + io_buf->io_addr[0]); + + CAM_DBG(CAM_LRME, "io addr %llu", io_buf->io_addr[0]); + + /* 3. config stride */ + reg_val = io_buf->io_cfg->planes[0].plane_stride; + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_rd_reg.bus_client_reg[index].rd_stride, + reg_val); + + CAM_DBG(CAM_LRME, "plane_stride %d", + io_buf->io_cfg->planes[0].plane_stride); + + /* 4. enable client */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_rd_reg.bus_client_reg[index].core_cfg, 0x1); + + /* 5. unpack_cfg */ + if (io_buf->io_cfg->format == CAM_FORMAT_PD10) + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0, + 0x0); + else if (io_buf->io_cfg->format == CAM_FORMAT_Y_ONLY || + io_buf->io_cfg->format == CAM_FORMAT_PLAIN8 || + io_buf->io_cfg->format == CAM_FORMAT_NV12 || + io_buf->io_cfg->format == CAM_FORMAT_NV21) + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0, + 0x1); + else if (io_buf->io_cfg->format == CAM_FORMAT_PLAIN16_10) + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0, + 0x22); + else + CAM_ERR(CAM_LRME, "Unsupported format %d", + io_buf->io_cfg->format); +} + +static void cam_lrme_hw_util_fill_we_reg(struct cam_lrme_hw_io_buffer *io_buf, + uint32_t index, uint32_t *reg_val_pair, uint32_t *num_cmd, + struct cam_lrme_hw_info *hw_info) +{ + /* config client mode */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_wr_reg.bus_client_reg[index].cfg, + 0x1); + + /* image address */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_wr_reg.bus_client_reg[index].addr_image, + io_buf->io_addr[0]); + CAM_DBG(CAM_LRME, "io addr %llu", io_buf->io_addr[0]); + + /* buffer width and height */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_wr_reg.bus_client_reg[index].buffer_width_cfg, + io_buf->io_cfg->planes[0].width); + CAM_DBG(CAM_LRME, "width %d", io_buf->io_cfg->planes[0].width); + + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_wr_reg.bus_client_reg[index].buffer_height_cfg, + io_buf->io_cfg->planes[0].height); + CAM_DBG(CAM_LRME, "height %d", io_buf->io_cfg->planes[0].height); + + /* packer cfg */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_wr_reg.bus_client_reg[index].packer_cfg, + (index == 0) ? 0x1 : 0x5); + + /* client stride */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, + hw_info->bus_wr_reg.bus_client_reg[index].wr_stride, + io_buf->io_cfg->planes[0].plane_stride); + CAM_DBG(CAM_LRME, "plane_stride %d", + io_buf->io_cfg->planes[0].plane_stride); +} + + +static int cam_lrme_hw_util_process_config_hw(struct cam_hw_info *lrme_hw, + struct cam_lrme_hw_cmd_config_args *config_args) +{ + int i; + struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info; + struct cam_lrme_cdm_info *hw_cdm_info; + uint32_t *cmd_buf_addr = config_args->cmd_buf_addr; + uint32_t reg_val_pair[CAM_LRME_MAX_REG_PAIR_NUM]; + struct cam_lrme_hw_io_buffer *io_buf; + struct cam_lrme_hw_info *hw_info = + ((struct cam_lrme_core *)lrme_hw->core_info)->hw_info; + uint32_t num_cmd = 0; + uint32_t size; + uint32_t mem_base, available_size = config_args->size; + uint32_t output_res_mask = 0, input_res_mask = 0; + + + if (!cmd_buf_addr) { + CAM_ERR(CAM_LRME, "Invalid input args"); + return -EINVAL; + } + + hw_cdm_info = + ((struct cam_lrme_core *)lrme_hw->core_info)->hw_cdm_info; + + for (i = 0; i < CAM_LRME_MAX_IO_BUFFER; i++) { + io_buf = &config_args->input_buf[i]; + + if (io_buf->valid == false) + break; + + if (io_buf->io_cfg->direction != CAM_BUF_INPUT) { + CAM_ERR(CAM_LRME, "Incorrect direction %d %d", + io_buf->io_cfg->direction, CAM_BUF_INPUT); + return -EINVAL; + } + CAM_DBG(CAM_LRME, + "resource_type %d", io_buf->io_cfg->resource_type); + + switch (io_buf->io_cfg->resource_type) { + case CAM_LRME_IO_TYPE_TAR: + cam_lrme_hw_util_fill_fe_reg(io_buf, 0, reg_val_pair, + &num_cmd, hw_info); + + input_res_mask |= CAM_LRME_INPUT_PORT_TYPE_TAR; + break; + case CAM_LRME_IO_TYPE_REF: + cam_lrme_hw_util_fill_fe_reg(io_buf, 1, reg_val_pair, + &num_cmd, hw_info); + + input_res_mask |= CAM_LRME_INPUT_PORT_TYPE_REF; + break; + default: + CAM_ERR(CAM_LRME, "wrong resource_type %d", + io_buf->io_cfg->resource_type); + return -EINVAL; + } + } + + for (i = 0; i < CAM_LRME_BUS_RD_MAX_CLIENTS; i++) + if (!((input_res_mask >> i) & 0x1)) + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, &num_cmd, + hw_info->bus_rd_reg.bus_client_reg[i].core_cfg, + 0x0); + + for (i = 0; i < CAM_LRME_MAX_IO_BUFFER; i++) { + io_buf = &config_args->output_buf[i]; + + if (io_buf->valid == false) + break; + + if (io_buf->io_cfg->direction != CAM_BUF_OUTPUT) { + CAM_ERR(CAM_LRME, "Incorrect direction %d %d", + io_buf->io_cfg->direction, CAM_BUF_INPUT); + return -EINVAL; + } + + CAM_DBG(CAM_LRME, "resource_type %d", + io_buf->io_cfg->resource_type); + switch (io_buf->io_cfg->resource_type) { + case CAM_LRME_IO_TYPE_DS2: + cam_lrme_hw_util_fill_we_reg(io_buf, 0, reg_val_pair, + &num_cmd, hw_info); + + output_res_mask |= CAM_LRME_OUTPUT_PORT_TYPE_DS2; + break; + case CAM_LRME_IO_TYPE_RES: + cam_lrme_hw_util_fill_we_reg(io_buf, 1, reg_val_pair, + &num_cmd, hw_info); + + output_res_mask |= CAM_LRME_OUTPUT_PORT_TYPE_RES; + break; + + default: + CAM_ERR(CAM_LRME, "wrong resource_type %d", + io_buf->io_cfg->resource_type); + return -EINVAL; + } + } + + for (i = 0; i < CAM_LRME_BUS_RD_MAX_CLIENTS; i++) + if (!((output_res_mask >> i) & 0x1)) + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, &num_cmd, + hw_info->bus_wr_reg.bus_client_reg[i].cfg, 0x0); + + if (output_res_mask) { + /* write composite mask */ + cam_lrme_cdm_write_reg_val_pair(reg_val_pair, &num_cmd, + hw_info->bus_wr_reg.common_reg.composite_mask_0, + output_res_mask); + } + + size = hw_cdm_info->cdm_ops->cdm_required_size_changebase(); + if ((size * 4) > available_size) { + CAM_ERR(CAM_LRME, "buf size:%d is not sufficient, expected: %d", + available_size, size); + return -EINVAL; + } + + mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE(soc_info, CAM_LRME_BASE_IDX); + + hw_cdm_info->cdm_ops->cdm_write_changebase(cmd_buf_addr, mem_base); + cmd_buf_addr += size; + available_size -= (size * 4); + + size = hw_cdm_info->cdm_ops->cdm_required_size_reg_random( + num_cmd / 2); + + if ((size * 4) > available_size) { + CAM_ERR(CAM_LRME, "buf size:%d is not sufficient, expected: %d", + available_size, size); + return -ENOMEM; + } + + hw_cdm_info->cdm_ops->cdm_write_regrandom(cmd_buf_addr, num_cmd / 2, + reg_val_pair); + cmd_buf_addr += size; + available_size -= (size * 4); + + config_args->config_buf_size = + config_args->size - available_size; + + return 0; +} + +static int cam_lrme_hw_util_submit_go(struct cam_hw_info *lrme_hw) +{ + struct cam_lrme_core *lrme_core; + struct cam_hw_soc_info *soc_info; + struct cam_lrme_hw_info *hw_info; + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + hw_info = lrme_core->hw_info; + soc_info = &lrme_hw->soc_info; + + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.cmd); + + return 0; +} + +static int cam_lrme_hw_util_reset(struct cam_hw_info *lrme_hw, + uint32_t reset_type) +{ + struct cam_lrme_core *lrme_core; + struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info; + struct cam_lrme_hw_info *hw_info; + long time_left; + + lrme_core = lrme_hw->core_info; + hw_info = lrme_core->hw_info; + + switch (reset_type) { + case CAM_LRME_HW_RESET_TYPE_HW_RESET: + reinit_completion(&lrme_core->reset_complete); + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_rst_cmd); + time_left = wait_for_completion_timeout( + &lrme_core->reset_complete, + msecs_to_jiffies(CAM_LRME_HW_RESET_TIMEOUT)); + if (time_left <= 0) { + CAM_ERR(CAM_LRME, + "HW reset wait failed time_left=%ld", + time_left); + return -ETIMEDOUT; + } + break; + case CAM_LRME_HW_RESET_TYPE_SW_RESET: + cam_io_w_mb(0x3, soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.sw_reset); + cam_io_w_mb(0x3, soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.sw_reset); + reinit_completion(&lrme_core->reset_complete); + cam_io_w_mb(0x2, soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_rst_cmd); + time_left = wait_for_completion_timeout( + &lrme_core->reset_complete, + msecs_to_jiffies(CAM_LRME_HW_RESET_TIMEOUT)); + if (time_left <= 0) { + CAM_ERR(CAM_LRME, + "SW reset wait failed time_left=%ld", + time_left); + return -ETIMEDOUT; + } + break; + } + + return 0; +} + +int cam_lrme_hw_util_get_caps(struct cam_hw_info *lrme_hw, + struct cam_lrme_dev_cap *hw_caps) +{ + struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info; + struct cam_lrme_hw_info *hw_info = + ((struct cam_lrme_core *)lrme_hw->core_info)->hw_info; + uint32_t reg_value; + + if (!hw_info) { + CAM_ERR(CAM_LRME, "Invalid hw info data"); + return -EINVAL; + } + + reg_value = cam_io_r_mb(soc_info->reg_map[0].mem_base + + hw_info->clc_reg.clc_hw_version); + hw_caps->clc_hw_version.gen = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1C); + hw_caps->clc_hw_version.rev = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->clc_hw_version.step = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + reg_value = cam_io_r_mb(soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.hw_version); + hw_caps->bus_rd_hw_version.gen = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1C); + hw_caps->bus_rd_hw_version.rev = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->bus_rd_hw_version.step = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + reg_value = cam_io_r_mb(soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.hw_version); + hw_caps->bus_wr_hw_version.gen = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1C); + hw_caps->bus_wr_hw_version.rev = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->bus_wr_hw_version.step = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + reg_value = cam_io_r_mb(soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_hw_version); + hw_caps->top_hw_version.gen = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1C); + hw_caps->top_hw_version.rev = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->top_hw_version.step = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + reg_value = cam_io_r_mb(soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_titan_version); + hw_caps->top_titan_version.gen = + CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1C); + hw_caps->top_titan_version.rev = + CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + hw_caps->top_titan_version.step = + CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + + return 0; +} + +static int cam_lrme_hw_util_submit_req(struct cam_lrme_core *lrme_core, + struct cam_lrme_frame_request *frame_req) +{ + struct cam_lrme_cdm_info *hw_cdm_info = + lrme_core->hw_cdm_info; + struct cam_cdm_bl_request *cdm_cmd = hw_cdm_info->cdm_cmd; + struct cam_hw_update_entry *cmd; + int i, rc = 0; + + if (frame_req->num_hw_update_entries > 0) { + cdm_cmd->cmd_arrary_count = frame_req->num_hw_update_entries; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = false; + cdm_cmd->userdata = NULL; + cdm_cmd->cookie = 0; + + for (i = 0; i <= frame_req->num_hw_update_entries; i++) { + cmd = (frame_req->hw_update_entries + i); + cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i].offset = cmd->offset; + cdm_cmd->cmd[i].len = cmd->len; + } + + rc = cam_cdm_submit_bls(hw_cdm_info->cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to submit cdm commands"); + return -EINVAL; + } + } else { + CAM_ERR(CAM_LRME, "No hw update entry"); + rc = -EINVAL; + } + + return rc; +} + +static int cam_lrme_hw_util_flush_ctx(struct cam_hw_info *lrme_hw, + void *ctxt_to_hw_map) +{ + int rc = -ENODEV; + struct cam_lrme_core *lrme_core = lrme_hw->core_info; + struct cam_lrme_hw_cb_args cb_args; + struct cam_lrme_frame_request *req_proc, *req_submit; + struct cam_lrme_hw_submit_args submit_args; + + rc = cam_lrme_hw_util_reset(lrme_hw, CAM_LRME_HW_RESET_TYPE_HW_RESET); + if (rc) { + CAM_ERR(CAM_LRME, "reset failed"); + return rc; + } + + lrme_core->state = CAM_LRME_CORE_STATE_IDLE; + req_proc = lrme_core->req_proc; + req_submit = lrme_core->req_submit; + lrme_core->req_proc = NULL; + lrme_core->req_submit = NULL; + + if (req_submit && req_submit->ctxt_to_hw_map == ctxt_to_hw_map) { + cb_args.cb_type = CAM_LRME_CB_PUT_FRAME; + cb_args.frame_req = req_submit; + if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb) + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb( + lrme_core->hw_mgr_cb.data, &cb_args); + } else if (req_submit) { + submit_args.frame_req = req_submit; + submit_args.hw_update_entries = req_submit->hw_update_entries; + submit_args.num_hw_update_entries = + req_submit->num_hw_update_entries; + rc = cam_lrme_hw_util_submit_req(lrme_core, req_submit); + if (rc) + CAM_ERR(CAM_LRME, "Submit failed"); + lrme_core->req_submit = req_submit; + cam_lrme_hw_util_submit_go(lrme_hw); + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PENDING; + } + + if (req_proc && req_proc->ctxt_to_hw_map == ctxt_to_hw_map) { + cb_args.cb_type = CAM_LRME_CB_PUT_FRAME; + cb_args.frame_req = req_proc; + if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb) + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb( + lrme_core->hw_mgr_cb.data, &cb_args); + } else if (req_proc) { + submit_args.frame_req = req_proc; + submit_args.hw_update_entries = req_proc->hw_update_entries; + submit_args.num_hw_update_entries = + req_proc->num_hw_update_entries; + rc = cam_lrme_hw_util_submit_req(lrme_core, req_proc); + if (rc) + CAM_ERR(CAM_LRME, "Submit failed"); + lrme_core->req_submit = req_proc; + cam_lrme_hw_util_submit_go(lrme_hw); + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PENDING; + } + + return rc; +} + +static int cam_lrme_hw_util_flush_req(struct cam_hw_info *lrme_hw, + struct cam_lrme_frame_request *req_to_flush) +{ + int rc = -ENODEV; + struct cam_lrme_core *lrme_core = lrme_hw->core_info; + struct cam_lrme_hw_cb_args cb_args; + struct cam_lrme_frame_request *req_proc, *req_submit; + struct cam_lrme_hw_submit_args submit_args; + + rc = cam_lrme_hw_util_reset(lrme_hw, CAM_LRME_HW_RESET_TYPE_HW_RESET); + if (rc) { + CAM_ERR(CAM_LRME, "reset failed"); + return rc; + } + + lrme_core->state = CAM_LRME_CORE_STATE_IDLE; + req_proc = lrme_core->req_proc; + req_submit = lrme_core->req_submit; + lrme_core->req_proc = NULL; + lrme_core->req_submit = NULL; + + if (req_submit && req_submit == req_to_flush) { + cb_args.cb_type = CAM_LRME_CB_PUT_FRAME; + cb_args.frame_req = req_submit; + if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb) + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb( + lrme_core->hw_mgr_cb.data, &cb_args); + } else if (req_submit) { + submit_args.frame_req = req_submit; + submit_args.hw_update_entries = req_submit->hw_update_entries; + submit_args.num_hw_update_entries = + req_submit->num_hw_update_entries; + rc = cam_lrme_hw_util_submit_req(lrme_core, req_submit); + if (rc) + CAM_ERR(CAM_LRME, "Submit failed"); + lrme_core->req_submit = req_submit; + cam_lrme_hw_util_submit_go(lrme_hw); + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PENDING; + } + + if (req_proc && req_proc == req_to_flush) { + cb_args.cb_type = CAM_LRME_CB_PUT_FRAME; + cb_args.frame_req = req_proc; + if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb) + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb( + lrme_core->hw_mgr_cb.data, &cb_args); + } else if (req_proc) { + submit_args.frame_req = req_proc; + submit_args.hw_update_entries = req_proc->hw_update_entries; + submit_args.num_hw_update_entries = + req_proc->num_hw_update_entries; + rc = cam_lrme_hw_util_submit_req(lrme_core, req_proc); + if (rc) + CAM_ERR(CAM_LRME, "Submit failed"); + lrme_core->req_submit = req_proc; + cam_lrme_hw_util_submit_go(lrme_hw); + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PENDING; + } + + return rc; +} + + +static int cam_lrme_hw_util_process_err(struct cam_hw_info *lrme_hw) +{ + struct cam_lrme_core *lrme_core = lrme_hw->core_info; + struct cam_lrme_frame_request *req_proc, *req_submit; + struct cam_lrme_hw_cb_args cb_args; + int rc; + + req_proc = lrme_core->req_proc; + req_submit = lrme_core->req_submit; + cb_args.cb_type = CAM_LRME_CB_ERROR; + + if ((lrme_core->state != CAM_LRME_CORE_STATE_PROCESSING) && + (lrme_core->state != CAM_LRME_CORE_STATE_REQ_PENDING) && + (lrme_core->state != CAM_LRME_CORE_STATE_REQ_PROC_PEND)) { + CAM_ERR(CAM_LRME, "Get error irq in wrong state %d", + lrme_core->state); + } + + cam_lrme_dump_registers(lrme_hw->soc_info.reg_map[0].mem_base); + + CAM_ERR_RATE_LIMIT(CAM_LRME, "Start recovery"); + lrme_core->state = CAM_LRME_CORE_STATE_RECOVERY; + rc = cam_lrme_hw_util_reset(lrme_hw, CAM_LRME_HW_RESET_TYPE_HW_RESET); + if (rc) + CAM_ERR(CAM_LRME, "Failed to reset"); + + lrme_core->req_proc = NULL; + lrme_core->req_submit = NULL; + if (!rc) + lrme_core->state = CAM_LRME_CORE_STATE_IDLE; + + cb_args.frame_req = req_proc; + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->hw_mgr_cb.data, + &cb_args); + + cb_args.frame_req = req_submit; + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->hw_mgr_cb.data, + &cb_args); + + return rc; +} + +static int cam_lrme_hw_util_process_reg_update( + struct cam_hw_info *lrme_hw, struct cam_lrme_hw_cb_args *cb_args) +{ + struct cam_lrme_core *lrme_core = lrme_hw->core_info; + int rc = 0; + + cb_args->cb_type |= CAM_LRME_CB_COMP_REG_UPDATE; + if (lrme_core->state == CAM_LRME_CORE_STATE_REQ_PENDING) { + lrme_core->state = CAM_LRME_CORE_STATE_PROCESSING; + } else { + CAM_ERR(CAM_LRME, "Reg update in wrong state %d", + lrme_core->state); + rc = cam_lrme_hw_util_process_err(lrme_hw); + if (rc) + CAM_ERR(CAM_LRME, "Failed to reset"); + return -EINVAL; + } + + lrme_core->req_proc = lrme_core->req_submit; + lrme_core->req_submit = NULL; + + if (lrme_core->dump_flag) + cam_lrme_dump_registers(lrme_hw->soc_info.reg_map[0].mem_base); + + return 0; +} + +static int cam_lrme_hw_util_process_idle( + struct cam_hw_info *lrme_hw, struct cam_lrme_hw_cb_args *cb_args) +{ + struct cam_lrme_core *lrme_core = lrme_hw->core_info; + int rc = 0; + + cb_args->cb_type |= CAM_LRME_CB_BUF_DONE; + switch (lrme_core->state) { + case CAM_LRME_CORE_STATE_REQ_PROC_PEND: + cam_lrme_hw_util_submit_go(lrme_hw); + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PENDING; + break; + + case CAM_LRME_CORE_STATE_PROCESSING: + lrme_core->state = CAM_LRME_CORE_STATE_IDLE; + break; + + default: + CAM_ERR(CAM_LRME, "Idle in wrong state %d", + lrme_core->state); + rc = cam_lrme_hw_util_process_err(lrme_hw); + return rc; + } + cb_args->frame_req = lrme_core->req_proc; + lrme_core->req_proc = NULL; + + return 0; +} + +void cam_lrme_set_irq(struct cam_hw_info *lrme_hw, + enum cam_lrme_irq_set set) +{ + struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info; + struct cam_lrme_core *lrme_core = lrme_hw->core_info; + struct cam_lrme_hw_info *hw_info = lrme_core->hw_info; + + switch (set) { + case CAM_LRME_IRQ_ENABLE: + cam_io_w_mb(0xFFFF, + soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_irq_mask); + cam_io_w_mb(0xFFFFF, + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_mask_0); + cam_io_w_mb(0xFFFFF, + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_mask_1); + cam_io_w_mb(0xFFFFF, + soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.irq_mask); + break; + + case CAM_LRME_IRQ_DISABLE: + cam_io_w_mb(0x0, + soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_irq_mask); + cam_io_w_mb(0x0, + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_mask_0); + cam_io_w_mb(0x0, + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_mask_1); + cam_io_w_mb(0x0, + soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.irq_mask); + break; + } +} + + +int cam_lrme_hw_process_irq(void *priv, void *data) +{ + struct cam_lrme_hw_work_data *work_data; + struct cam_hw_info *lrme_hw; + struct cam_lrme_core *lrme_core; + int rc = 0; + uint32_t top_irq_status, fe_irq_status; + uint32_t *we_irq_status; + struct cam_lrme_hw_cb_args cb_args; + + if (!data || !priv) { + CAM_ERR(CAM_LRME, "Invalid data %pK %pK", data, priv); + return -EINVAL; + } + + memset(&cb_args, 0, sizeof(struct cam_lrme_hw_cb_args)); + lrme_hw = (struct cam_hw_info *)priv; + work_data = (struct cam_lrme_hw_work_data *)data; + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + top_irq_status = work_data->top_irq_status; + fe_irq_status = work_data->fe_irq_status; + we_irq_status = work_data->we_irq_status; + + CAM_DBG(CAM_LRME, + "top status %x, fe status %x, we status0 %x, we status1 %x", + top_irq_status, fe_irq_status, we_irq_status[0], + we_irq_status[1]); + CAM_DBG(CAM_LRME, "Current state %d", lrme_core->state); + + 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); + if (rc) + CAM_ERR(CAM_LRME, "Process error failed"); + goto end; + } + + if (we_irq_status[0] & (1 << 1)) { + CAM_DBG(CAM_LRME, "reg update"); + rc = cam_lrme_hw_util_process_reg_update(lrme_hw, &cb_args); + if (rc) { + CAM_ERR(CAM_LRME, "Process reg_update failed"); + goto end; + } + } + + if (top_irq_status & (1 << 4)) { + CAM_DBG(CAM_LRME, "IDLE"); + if (!lrme_core->req_proc) { + CAM_DBG(CAM_LRME, "No frame request to process idle"); + goto end; + } + rc = cam_lrme_hw_util_process_idle(lrme_hw, &cb_args); + if (rc) { + CAM_ERR(CAM_LRME, "Process idle failed"); + goto end; + } + } + + if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb) { + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb( + lrme_core->hw_mgr_cb.data, &cb_args); + } else { + CAM_ERR(CAM_LRME, "No hw mgr cb"); + rc = -EINVAL; + } + +end: + mutex_unlock(&lrme_hw->hw_mutex); + return rc; +} + +int cam_lrme_hw_start(void *hw_priv, void *hw_start_args, uint32_t arg_size) +{ + struct cam_hw_info *lrme_hw = (struct cam_hw_info *)hw_priv; + int rc = 0; + struct cam_lrme_core *lrme_core; + + if (!lrme_hw) { + CAM_ERR(CAM_LRME, + "Invalid input params, lrme_hw %pK", + lrme_hw); + return -EINVAL; + } + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + + mutex_lock(&lrme_hw->hw_mutex); + + if (lrme_hw->open_count > 0) { + lrme_hw->open_count++; + CAM_DBG(CAM_LRME, "This device is activated before"); + goto unlock; + } + + rc = cam_lrme_soc_enable_resources(lrme_hw); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to enable soc resources"); + goto unlock; + } + + rc = cam_lrme_hw_util_reset(lrme_hw, CAM_LRME_HW_RESET_TYPE_HW_RESET); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to reset hw"); + goto disable_soc; + } + + if (lrme_core->hw_cdm_info) { + struct cam_lrme_cdm_info *hw_cdm_info = + lrme_core->hw_cdm_info; + + rc = cam_cdm_stream_on(hw_cdm_info->cdm_handle); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to stream on cdm"); + goto disable_soc; + } + } + + lrme_hw->hw_state = CAM_HW_STATE_POWER_UP; + lrme_hw->open_count++; + lrme_core->state = CAM_LRME_CORE_STATE_IDLE; + + CAM_DBG(CAM_LRME, "open count %d", lrme_hw->open_count); + mutex_unlock(&lrme_hw->hw_mutex); + return rc; + +disable_soc: + if (cam_lrme_soc_disable_resources(lrme_hw)) + CAM_ERR(CAM_LRME, "Error in disable soc resources"); +unlock: + CAM_DBG(CAM_LRME, "open count %d", lrme_hw->open_count); + mutex_unlock(&lrme_hw->hw_mutex); + return rc; +} + +int cam_lrme_hw_stop(void *hw_priv, void *hw_stop_args, uint32_t arg_size) +{ + struct cam_hw_info *lrme_hw = (struct cam_hw_info *)hw_priv; + int rc = 0; + struct cam_lrme_core *lrme_core; + + if (!lrme_hw) { + CAM_ERR(CAM_LRME, "Invalid argument"); + return -EINVAL; + } + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + + mutex_lock(&lrme_hw->hw_mutex); + + if (lrme_hw->open_count == 0 || + lrme_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_ERR(CAM_LRME, "Error Unbalanced stop"); + return -EINVAL; + } + lrme_hw->open_count--; + + CAM_DBG(CAM_LRME, "open count %d", lrme_hw->open_count); + + if (lrme_hw->open_count) + goto unlock; + + lrme_core->req_proc = NULL; + lrme_core->req_submit = NULL; + + if (lrme_core->hw_cdm_info) { + struct cam_lrme_cdm_info *hw_cdm_info = + lrme_core->hw_cdm_info; + + rc = cam_cdm_stream_off(hw_cdm_info->cdm_handle); + if (rc) { + CAM_ERR(CAM_LRME, + "Failed in CDM StreamOff, handle=0x%x, rc=%d", + hw_cdm_info->cdm_handle, rc); + goto unlock; + } + } + + rc = cam_lrme_soc_disable_resources(lrme_hw); + if (rc) + CAM_ERR(CAM_LRME, "Failed in Disable SOC, rc=%d", rc); + + lrme_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + if (lrme_core->state == CAM_LRME_CORE_STATE_IDLE) { + lrme_core->state = CAM_LRME_CORE_STATE_INIT; + } else { + CAM_ERR(CAM_LRME, "HW in wrong state %d", lrme_core->state); + rc = -EINVAL; + } + +unlock: + mutex_unlock(&lrme_hw->hw_mutex); + return rc; +} + +int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args, + uint32_t arg_size) +{ + struct cam_hw_info *lrme_hw = (struct cam_hw_info *)hw_priv; + struct cam_lrme_core *lrme_core; + struct cam_lrme_hw_submit_args *args = + (struct cam_lrme_hw_submit_args *)hw_submit_args; + int rc = 0; + struct cam_lrme_frame_request *frame_req; + + + if (!hw_priv || !hw_submit_args) { + CAM_ERR(CAM_LRME, "Invalid input"); + return -EINVAL; + } + + if (sizeof(struct cam_lrme_hw_submit_args) != arg_size) { + CAM_ERR(CAM_LRME, + "size of args %zu, arg_size %d", + sizeof(struct cam_lrme_hw_submit_args), arg_size); + return -EINVAL; + } + + frame_req = args->frame_req; + + mutex_lock(&lrme_hw->hw_mutex); + + if (lrme_hw->open_count == 0) { + CAM_ERR(CAM_LRME, "HW is not open"); + mutex_unlock(&lrme_hw->hw_mutex); + return -EINVAL; + } + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + if (lrme_core->state != CAM_LRME_CORE_STATE_IDLE && + lrme_core->state != CAM_LRME_CORE_STATE_PROCESSING) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_DBG(CAM_LRME, "device busy, can not submit, state %d", + lrme_core->state); + return -EBUSY; + } + + if (lrme_core->req_submit != NULL) { + CAM_ERR(CAM_LRME, "req_submit is not NULL"); + return -EBUSY; + } + + rc = cam_lrme_hw_util_submit_req(lrme_core, frame_req); + if (rc) { + CAM_ERR(CAM_LRME, "Submit req failed"); + goto error; + } + + switch (lrme_core->state) { + case CAM_LRME_CORE_STATE_PROCESSING: + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PROC_PEND; + break; + + case CAM_LRME_CORE_STATE_IDLE: + cam_lrme_hw_util_submit_go(lrme_hw); + lrme_core->state = CAM_LRME_CORE_STATE_REQ_PENDING; + break; + + default: + CAM_ERR(CAM_LRME, "Wrong hw state"); + rc = -EINVAL; + goto error; + } + + lrme_core->req_submit = frame_req; + + mutex_unlock(&lrme_hw->hw_mutex); + CAM_DBG(CAM_LRME, "Release lock, submit done for req %llu", + frame_req->req_id); + + return 0; + +error: + mutex_unlock(&lrme_hw->hw_mutex); + + return rc; + +} + +int cam_lrme_hw_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) +{ + struct cam_hw_info *lrme_hw = hw_priv; + struct cam_lrme_core *lrme_core; + struct cam_lrme_hw_reset_args *lrme_reset_args = reset_core_args; + int rc; + + if (!hw_priv) { + CAM_ERR(CAM_LRME, "Invalid input args"); + return -EINVAL; + } + + if (!reset_core_args || + sizeof(struct cam_lrme_hw_reset_args) != arg_size) { + CAM_ERR(CAM_LRME, "Invalid reset args"); + return -EINVAL; + } + + lrme_core = lrme_hw->core_info; + + mutex_lock(&lrme_hw->hw_mutex); + if (lrme_core->state == CAM_LRME_CORE_STATE_RECOVERY) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_ERR(CAM_LRME, "Reset not allowed in %d state", + lrme_core->state); + return -EINVAL; + } + + lrme_core->state = CAM_LRME_CORE_STATE_RECOVERY; + + rc = cam_lrme_hw_util_reset(lrme_hw, lrme_reset_args->reset_type); + if (rc) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_ERR(CAM_FD, "Failed to reset"); + return rc; + } + + lrme_core->state = CAM_LRME_CORE_STATE_IDLE; + + mutex_unlock(&lrme_hw->hw_mutex); + + return 0; +} + +int cam_lrme_hw_flush(void *hw_priv, void *hw_flush_args, uint32_t arg_size) +{ + struct cam_lrme_core *lrme_core = NULL; + struct cam_hw_info *lrme_hw = hw_priv; + struct cam_lrme_hw_flush_args *flush_args = + (struct cam_lrme_hw_flush_args *)hw_flush_args; + int rc = -ENODEV; + + if (!hw_priv) { + CAM_ERR(CAM_LRME, "Invalid arguments %pK", hw_priv); + return -EINVAL; + } + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + + mutex_lock(&lrme_hw->hw_mutex); + + if (lrme_core->state != CAM_LRME_CORE_STATE_PROCESSING && + lrme_core->state != CAM_LRME_CORE_STATE_REQ_PENDING && + lrme_core->state != CAM_LRME_CORE_STATE_REQ_PROC_PEND) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_DBG(CAM_LRME, "Flush is not needed in %d state", + lrme_core->state); + return 0; + } + + if (!lrme_core->req_proc && !lrme_core->req_submit) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_DBG(CAM_LRME, "no req in device"); + return 0; + } + + switch (flush_args->flush_type) { + case CAM_FLUSH_TYPE_ALL: + if ((!lrme_core->req_submit || + lrme_core->req_submit->ctxt_to_hw_map != + flush_args->ctxt_to_hw_map) && + (!lrme_core->req_proc || + lrme_core->req_proc->ctxt_to_hw_map != + flush_args->ctxt_to_hw_map)) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_DBG(CAM_LRME, "hw running on different ctx"); + return 0; + } + rc = cam_lrme_hw_util_flush_ctx(lrme_hw, + flush_args->ctxt_to_hw_map); + if (rc) + CAM_ERR(CAM_LRME, "Flush all failed"); + break; + + case CAM_FLUSH_TYPE_REQ: + if ((!lrme_core->req_submit || + lrme_core->req_submit != flush_args->req_to_flush) && + (!lrme_core->req_proc || + lrme_core->req_proc != flush_args->req_to_flush)) { + mutex_unlock(&lrme_hw->hw_mutex); + CAM_DBG(CAM_LRME, "hw running on different ctx"); + return 0; + } + rc = cam_lrme_hw_util_flush_req(lrme_hw, + flush_args->req_to_flush); + if (rc) + CAM_ERR(CAM_LRME, "Flush req failed"); + break; + + default: + CAM_ERR(CAM_LRME, "Unsupported flush type"); + break; + } + + mutex_unlock(&lrme_hw->hw_mutex); + + return rc; +} + +int cam_lrme_hw_get_caps(void *hw_priv, void *get_hw_cap_args, + uint32_t arg_size) +{ + struct cam_hw_info *lrme_hw; + struct cam_lrme_core *lrme_core; + struct cam_lrme_dev_cap *lrme_hw_caps = + (struct cam_lrme_dev_cap *)get_hw_cap_args; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_LRME, "Invalid input pointers %pK %pK", + hw_priv, get_hw_cap_args); + return -EINVAL; + } + + lrme_hw = (struct cam_hw_info *)hw_priv; + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + *lrme_hw_caps = lrme_core->hw_caps; + + return 0; +} + +irqreturn_t cam_lrme_hw_irq(int irq_num, void *data) +{ + struct cam_hw_info *lrme_hw; + struct cam_lrme_core *lrme_core; + struct cam_hw_soc_info *soc_info; + struct cam_lrme_hw_info *hw_info; + struct crm_workq_task *task; + struct cam_lrme_hw_work_data *work_data; + uint32_t top_irq_status, fe_irq_status, we_irq_status0, we_irq_status1; + int rc; + + if (!data) { + CAM_ERR(CAM_LRME, "Invalid data in IRQ callback"); + return IRQ_NONE; + } + + lrme_hw = (struct cam_hw_info *)data; + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + soc_info = &lrme_hw->soc_info; + hw_info = lrme_core->hw_info; + + top_irq_status = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_irq_status); + CAM_DBG(CAM_LRME, "top_irq_status %x", top_irq_status); + cam_io_w_mb(top_irq_status, + soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_irq_clear); + top_irq_status &= CAM_LRME_TOP_IRQ_MASK; + + fe_irq_status = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.irq_status); + CAM_DBG(CAM_LRME, "fe_irq_status %x", fe_irq_status); + cam_io_w_mb(fe_irq_status, + soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.irq_clear); + fe_irq_status &= CAM_LRME_FE_IRQ_MASK; + + we_irq_status0 = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_status_0); + CAM_DBG(CAM_LRME, "we_irq_status[0] %x", we_irq_status0); + cam_io_w_mb(we_irq_status0, + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_clear_0); + we_irq_status0 &= CAM_LRME_WE_IRQ_MASK_0; + + we_irq_status1 = cam_io_r_mb( + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_status_1); + CAM_DBG(CAM_LRME, "we_irq_status[1] %x", we_irq_status1); + cam_io_w_mb(we_irq_status1, + soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_clear_1); + we_irq_status1 &= CAM_LRME_WE_IRQ_MASK_1; + + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + hw_info->titan_reg.top_irq_cmd); + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + hw_info->bus_wr_reg.common_reg.irq_cmd); + cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base + + hw_info->bus_rd_reg.common_reg.irq_cmd); + + if (top_irq_status & 0x1) { + complete(&lrme_core->reset_complete); + top_irq_status &= (~0x1); + } + + if (top_irq_status || fe_irq_status || + we_irq_status0 || we_irq_status1) { + task = cam_req_mgr_workq_get_task(lrme_core->work); + if (!task) { + CAM_ERR(CAM_LRME, "no empty task available"); + return IRQ_NONE; + } + work_data = (struct cam_lrme_hw_work_data *)task->payload; + work_data->top_irq_status = top_irq_status; + work_data->fe_irq_status = fe_irq_status; + work_data->we_irq_status[0] = we_irq_status0; + work_data->we_irq_status[1] = we_irq_status1; + task->process_cb = cam_lrme_hw_process_irq; + rc = cam_req_mgr_workq_enqueue_task(task, data, + CRM_TASK_PRIORITY_0); + if (rc) + CAM_ERR(CAM_LRME, + "Failed in enqueue work task, rc=%d", rc); + } + + return IRQ_HANDLED; +} + +int cam_lrme_hw_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *lrme_hw = (struct cam_hw_info *)hw_priv; + int rc = 0; + + switch (cmd_type) { + case CAM_LRME_HW_CMD_PREPARE_HW_UPDATE: { + struct cam_lrme_hw_cmd_config_args *config_args; + + config_args = (struct cam_lrme_hw_cmd_config_args *)cmd_args; + rc = cam_lrme_hw_util_process_config_hw(lrme_hw, config_args); + break; + } + + case CAM_LRME_HW_CMD_REGISTER_CB: { + struct cam_lrme_hw_cmd_set_cb *cb_args; + struct cam_lrme_device *hw_device; + struct cam_lrme_core *lrme_core = + (struct cam_lrme_core *)lrme_hw->core_info; + cb_args = (struct cam_lrme_hw_cmd_set_cb *)cmd_args; + lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb = + cb_args->cam_lrme_hw_mgr_cb; + lrme_core->hw_mgr_cb.data = cb_args->data; + hw_device = cb_args->data; + rc = 0; + break; + } + + case CAM_LRME_HW_CMD_SUBMIT: { + struct cam_lrme_hw_submit_args *submit_args; + + submit_args = (struct cam_lrme_hw_submit_args *)cmd_args; + rc = cam_lrme_hw_submit_req(hw_priv, + submit_args, arg_size); + break; + } + + case CAM_LRME_HW_CMD_DUMP_REGISTER: { + struct cam_lrme_core *lrme_core = + (struct cam_lrme_core *)lrme_hw->core_info; + lrme_core->dump_flag = *(bool *)cmd_args; + CAM_DBG(CAM_LRME, "dump_flag %d", lrme_core->dump_flag); + break; + } + + default: + break; + } + + return rc; +} diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h new file mode 100644 index 000000000000..accb5a8b5827 --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h @@ -0,0 +1,451 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_HW_CORE_H_ +#define _CAM_LRME_HW_CORE_H_ + +#include +#include +#include +#include +#include + +#include "cam_common_util.h" +#include "cam_debug_util.h" +#include "cam_io_util.h" +#include "cam_cpas_api.h" +#include "cam_cdm_intf_api.h" +#include "cam_lrme_hw_intf.h" +#include "cam_lrme_hw_soc.h" +#include "cam_req_mgr_workq.h" + +#define CAM_LRME_HW_RESET_TIMEOUT 3000 + +#define CAM_LRME_BUS_RD_MAX_CLIENTS 2 +#define CAM_LRME_BUS_WR_MAX_CLIENTS 2 + +#define CAM_LRME_HW_WORKQ_NUM_TASK 30 + +#define CAM_LRME_TOP_IRQ_MASK 0x19 +#define CAM_LRME_WE_IRQ_MASK_0 0x2 +#define CAM_LRME_WE_IRQ_MASK_1 0x0 +#define CAM_LRME_FE_IRQ_MASK 0x0 + +#define CAM_LRME_MAX_REG_PAIR_NUM 60 + +/** + * enum cam_lrme_irq_set + * + * @CAM_LRME_IRQ_ENABLE : Enable irqs + * @CAM_LRME_IRQ_DISABLE : Disable irqs + */ +enum cam_lrme_irq_set { + CAM_LRME_IRQ_ENABLE, + CAM_LRME_IRQ_DISABLE, +}; + +/** + * struct cam_lrme_cdm_info : information used to submit cdm command + * + * @cdm_handle : CDM handle for this device + * @cdm_ops : CDM ops + * @cdm_cmd : CDM command pointer + */ +struct cam_lrme_cdm_info { + uint32_t cdm_handle; + struct cam_cdm_utils_ops *cdm_ops; + struct cam_cdm_bl_request *cdm_cmd; +}; + +/** + * struct cam_lrme_hw_work_data : Work data for HW work queue + * + * @top_irq_status : Top registers irq status + * @fe_irq_status : FE engine irq status + * @we_irq_status : WE engine irq status + */ +struct cam_lrme_hw_work_data { + uint32_t top_irq_status; + uint32_t fe_irq_status; + uint32_t we_irq_status[2]; +}; + +/** + * enum cam_lrme_core_state : LRME core states + * + * @CAM_LRME_CORE_STATE_UNINIT : LRME is in uninit state + * @CAM_LRME_CORE_STATE_INIT : LRME is in init state after probe + * @ CAM_LRME_CORE_STATE_IDLE : LRME is in idle state. Hardware is in + * this state when no frame is processing + * or waiting for this core. + * @CAM_LRME_CORE_STATE_REQ_PENDING : LRME is in pending state. One frame is + * waiting for processing + * @CAM_LRME_CORE_STATE_PROCESSING : LRME is in processing state. HW manager + * can submit one more frame to HW + * @CAM_LRME_CORE_STATE_REQ_PROC_PEND : Indicate two frames are inside HW. + * @CAM_LRME_CORE_STATE_RECOVERY : Indicate core is in the process of reset + * @CAM_LRME_CORE_STATE_MAX : upper limit of states + */ +enum cam_lrme_core_state { + CAM_LRME_CORE_STATE_UNINIT, + CAM_LRME_CORE_STATE_INIT, + CAM_LRME_CORE_STATE_IDLE, + CAM_LRME_CORE_STATE_REQ_PENDING, + CAM_LRME_CORE_STATE_PROCESSING, + CAM_LRME_CORE_STATE_REQ_PROC_PEND, + CAM_LRME_CORE_STATE_RECOVERY, + CAM_LRME_CORE_STATE_MAX, +}; + +/** + * struct cam_lrme_core : LRME HW core information + * + * @hw_info : Pointer to base HW information structure + * @device_iommu : Device iommu handle + * @cdm_iommu : CDM iommu handle + * @hw_caps : Hardware capabilities + * @state : Hardware state + * @reset_complete : Reset completion + * @work : Hardware workqueue to handle irq events + * @work_data : Work data used by hardware workqueue + * @hw_mgr_cb : Hw manager callback + * @req_proc : Pointer to the processing frame request + * @req_submit : Pointer to the frame request waiting for processing + * @hw_cdm_info : CDM information used by this device + * @hw_idx : Hardware index + */ +struct cam_lrme_core { + struct cam_lrme_hw_info *hw_info; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + struct cam_lrme_dev_cap hw_caps; + enum cam_lrme_core_state state; + struct completion reset_complete; + struct cam_req_mgr_core_workq *work; + struct cam_lrme_hw_work_data work_data[CAM_LRME_HW_WORKQ_NUM_TASK]; + struct cam_lrme_hw_cmd_set_cb hw_mgr_cb; + struct cam_lrme_frame_request *req_proc; + struct cam_lrme_frame_request *req_submit; + struct cam_lrme_cdm_info *hw_cdm_info; + uint32_t hw_idx; + bool dump_flag; +}; + +/** + * struct cam_lrme_bus_rd_reg_common : Offsets of FE common registers + * + * @hw_version : Offset of hw_version register + * @hw_capability : Offset of hw_capability register + * @sw_reset : Offset of sw_reset register + * @cgc_override : Offset of cgc_override register + * @irq_mask : Offset of irq_mask register + * @irq_clear : Offset of irq_clear register + * @irq_cmd : Offset of irq_cmd register + * @irq_status : Offset of irq_status register + * @cmd : Offset of cmd register + * @irq_set : Offset of irq_set register + * @misr_reset : Offset of misr_reset register + * @security_cfg : Offset of security_cfg register + * @pwr_iso_cfg : Offset of pwr_iso_cfg register + * @pwr_iso_seed : Offset of pwr_iso_seed register + * @test_bus_ctrl : Offset of test_bus_ctrl register + * @spare : Offset of spare register + */ +struct cam_lrme_bus_rd_reg_common { + uint32_t hw_version; + uint32_t hw_capability; + uint32_t sw_reset; + uint32_t cgc_override; + uint32_t irq_mask; + uint32_t irq_clear; + uint32_t irq_cmd; + uint32_t irq_status; + uint32_t cmd; + uint32_t irq_set; + uint32_t misr_reset; + uint32_t security_cfg; + uint32_t pwr_iso_cfg; + uint32_t pwr_iso_seed; + uint32_t test_bus_ctrl; + uint32_t spare; +}; + +/** + * struct cam_lrme_bus_wr_reg_common : Offset of WE common registers + * @hw_version : Offset of hw_version register + * @hw_capability : Offset of hw_capability register + * @sw_reset : Offset of sw_reset register + * @cgc_override : Offset of cgc_override register + * @misr_reset : Offset of misr_reset register + * @pwr_iso_cfg : Offset of pwr_iso_cfg register + * @test_bus_ctrl : Offset of test_bus_ctrl register + * @composite_mask_0 : Offset of composite_mask_0 register + * @irq_mask_0 : Offset of irq_mask_0 register + * @irq_mask_1 : Offset of irq_mask_1 register + * @irq_clear_0 : Offset of irq_clear_0 register + * @irq_clear_1 : Offset of irq_clear_1 register + * @irq_status_0 : Offset of irq_status_0 register + * @irq_status_1 : Offset of irq_status_1 register + * @irq_cmd : Offset of irq_cmd register + * @irq_set_0 : Offset of irq_set_0 register + * @irq_set_1 : Offset of irq_set_1 register + * @addr_fifo_status : Offset of addr_fifo_status register + * @frame_header_cfg0 : Offset of frame_header_cfg0 register + * @frame_header_cfg1 : Offset of frame_header_cfg1 register + * @spare : Offset of spare register + */ +struct cam_lrme_bus_wr_reg_common { + uint32_t hw_version; + uint32_t hw_capability; + uint32_t sw_reset; + uint32_t cgc_override; + uint32_t misr_reset; + uint32_t pwr_iso_cfg; + uint32_t test_bus_ctrl; + uint32_t composite_mask_0; + uint32_t irq_mask_0; + uint32_t irq_mask_1; + uint32_t irq_clear_0; + uint32_t irq_clear_1; + uint32_t irq_status_0; + uint32_t irq_status_1; + uint32_t irq_cmd; + uint32_t irq_set_0; + uint32_t irq_set_1; + uint32_t addr_fifo_status; + uint32_t frame_header_cfg0; + uint32_t frame_header_cfg1; + uint32_t spare; +}; + +/** + * struct cam_lrme_bus_rd_bus_client : Offset of FE registers + * + * @core_cfg : Offset of core_cfg register + * @ccif_meta_data : Offset of ccif_meta_data register + * @addr_image : Offset of addr_image register + * @rd_buffer_size : Offset of rd_buffer_size register + * @rd_stride : Offset of rd_stride register + * @unpack_cfg_0 : Offset of unpack_cfg_0 register + * @latency_buff_allocation : Offset of latency_buff_allocation register + * @burst_limit_cfg : Offset of burst_limit_cfg register + * @misr_cfg_0 : Offset of misr_cfg_0 register + * @misr_cfg_1 : Offset of misr_cfg_1 register + * @misr_rd_val : Offset of misr_rd_val register + * @debug_status_cfg : Offset of debug_status_cfg register + * @debug_status_0 : Offset of debug_status_0 register + * @debug_status_1 : Offset of debug_status_1 register + */ +struct cam_lrme_bus_rd_bus_client { + uint32_t core_cfg; + uint32_t ccif_meta_data; + uint32_t addr_image; + uint32_t rd_buffer_size; + uint32_t rd_stride; + uint32_t unpack_cfg_0; + uint32_t latency_buff_allocation; + uint32_t burst_limit_cfg; + uint32_t misr_cfg_0; + uint32_t misr_cfg_1; + uint32_t misr_rd_val; + uint32_t debug_status_cfg; + uint32_t debug_status_0; + uint32_t debug_status_1; +}; + +/** + * struct cam_lrme_bus_wr_bus_client : Offset of WE registers + * + * @status_0 : Offset of status_0 register + * @status_1 : Offset of status_1 register + * @cfg : Offset of cfg register + * @addr_frame_header : Offset of addr_frame_header register + * @frame_header_cfg : Offset of frame_header_cfg register + * @addr_image : Offset of addr_image register + * @addr_image_offset : Offset of addr_image_offset register + * @buffer_width_cfg : Offset of buffer_width_cfg register + * @buffer_height_cfg : Offset of buffer_height_cfg register + * @packer_cfg : Offset of packer_cfg register + * @wr_stride : Offset of wr_stride register + * @irq_subsample_cfg_period : Offset of irq_subsample_cfg_period register + * @irq_subsample_cfg_pattern : Offset of irq_subsample_cfg_pattern register + * @burst_limit_cfg : Offset of burst_limit_cfg register + * @misr_cfg : Offset of misr_cfg register + * @misr_rd_word_sel : Offset of misr_rd_word_sel register + * @misr_val : Offset of misr_val register + * @debug_status_cfg : Offset of debug_status_cfg register + * @debug_status_0 : Offset of debug_status_0 register + * @debug_status_1 : Offset of debug_status_1 register + */ +struct cam_lrme_bus_wr_bus_client { + uint32_t status_0; + uint32_t status_1; + uint32_t cfg; + uint32_t addr_frame_header; + uint32_t frame_header_cfg; + uint32_t addr_image; + uint32_t addr_image_offset; + uint32_t buffer_width_cfg; + uint32_t buffer_height_cfg; + uint32_t packer_cfg; + uint32_t wr_stride; + uint32_t irq_subsample_cfg_period; + uint32_t irq_subsample_cfg_pattern; + uint32_t burst_limit_cfg; + uint32_t misr_cfg; + uint32_t misr_rd_word_sel; + uint32_t misr_val; + uint32_t debug_status_cfg; + uint32_t debug_status_0; + uint32_t debug_status_1; +}; + +/** + * struct cam_lrme_bus_rd_hw_info : FE registers information + * + * @common_reg : FE common register + * @bus_client_reg : List of FE bus registers information + */ +struct cam_lrme_bus_rd_hw_info { + struct cam_lrme_bus_rd_reg_common common_reg; + struct cam_lrme_bus_rd_bus_client + bus_client_reg[CAM_LRME_BUS_RD_MAX_CLIENTS]; +}; + +/** + * struct cam_lrme_bus_wr_hw_info : WE engine registers information + * + * @common_reg : WE common register + * @bus_client_reg : List of WE bus registers information + */ +struct cam_lrme_bus_wr_hw_info { + struct cam_lrme_bus_wr_reg_common common_reg; + struct cam_lrme_bus_wr_bus_client + bus_client_reg[CAM_LRME_BUS_WR_MAX_CLIENTS]; +}; + +/** + * struct cam_lrme_clc_reg : Offset of clc registers + * + * @clc_hw_version : Offset of clc_hw_version register + * @clc_hw_status : Offset of clc_hw_status register + * @clc_hw_status_dbg : Offset of clc_hw_status_dbg register + * @clc_module_cfg : Offset of clc_module_cfg register + * @clc_moduleformat : Offset of clc_moduleformat register + * @clc_rangestep : Offset of clc_rangestep register + * @clc_offset : Offset of clc_offset register + * @clc_maxallowedsad : Offset of clc_maxallowedsad register + * @clc_minallowedtarmad : Offset of clc_minallowedtarmad register + * @clc_meaningfulsaddiff : Offset of clc_meaningfulsaddiff register + * @clc_minsaddiffdenom : Offset of clc_minsaddiffdenom register + * @clc_robustnessmeasuredistmap_0 : Offset of measuredistmap_0 register + * @clc_robustnessmeasuredistmap_1 : Offset of measuredistmap_1 register + * @clc_robustnessmeasuredistmap_2 : Offset of measuredistmap_2 register + * @clc_robustnessmeasuredistmap_3 : Offset of measuredistmap_3 register + * @clc_robustnessmeasuredistmap_4 : Offset of measuredistmap_4 register + * @clc_robustnessmeasuredistmap_5 : Offset of measuredistmap_5 register + * @clc_robustnessmeasuredistmap_6 : Offset of measuredistmap_6 register + * @clc_robustnessmeasuredistmap_7 : Offset of measuredistmap_7 register + * @clc_ds_crop_horizontal : Offset of clc_ds_crop_horizontal register + * @clc_ds_crop_vertical : Offset of clc_ds_crop_vertical register + * @clc_tar_pd_unpacker : Offset of clc_tar_pd_unpacker register + * @clc_ref_pd_unpacker : Offset of clc_ref_pd_unpacker register + * @clc_sw_override : Offset of clc_sw_override register + * @clc_tar_height : Offset of clc_tar_height register + * @clc_test_bus_ctrl : Offset of clc_test_bus_ctrl register + * @clc_spare : Offset of clc_spare register + */ +struct cam_lrme_clc_reg { + uint32_t clc_hw_version; + uint32_t clc_hw_status; + uint32_t clc_hw_status_dbg; + uint32_t clc_module_cfg; + uint32_t clc_moduleformat; + uint32_t clc_rangestep; + uint32_t clc_offset; + uint32_t clc_maxallowedsad; + uint32_t clc_minallowedtarmad; + uint32_t clc_meaningfulsaddiff; + uint32_t clc_minsaddiffdenom; + uint32_t clc_robustnessmeasuredistmap_0; + uint32_t clc_robustnessmeasuredistmap_1; + uint32_t clc_robustnessmeasuredistmap_2; + uint32_t clc_robustnessmeasuredistmap_3; + uint32_t clc_robustnessmeasuredistmap_4; + uint32_t clc_robustnessmeasuredistmap_5; + uint32_t clc_robustnessmeasuredistmap_6; + uint32_t clc_robustnessmeasuredistmap_7; + uint32_t clc_ds_crop_horizontal; + uint32_t clc_ds_crop_vertical; + uint32_t clc_tar_pd_unpacker; + uint32_t clc_ref_pd_unpacker; + uint32_t clc_sw_override; + uint32_t clc_tar_height; + uint32_t clc_ref_height; + uint32_t clc_test_bus_ctrl; + uint32_t clc_spare; +}; + +/** + * struct cam_lrme_titan_reg : Offset of LRME top registers + * + * @top_hw_version : Offset of top_hw_version register + * @top_titan_version : Offset of top_titan_version register + * @top_rst_cmd : Offset of top_rst_cmd register + * @top_core_clk_cfg : Offset of top_core_clk_cfg register + * @top_irq_status : Offset of top_irq_status register + * @top_irq_mask : Offset of top_irq_mask register + * @top_irq_clear : Offset of top_irq_clear register + * @top_irq_set : Offset of top_irq_set register + * @top_irq_cmd : Offset of top_irq_cmd register + * @top_violation_status : Offset of top_violation_status register + * @top_spare : Offset of top_spare register + */ +struct cam_lrme_titan_reg { + uint32_t top_hw_version; + uint32_t top_titan_version; + uint32_t top_rst_cmd; + uint32_t top_core_clk_cfg; + uint32_t top_irq_status; + uint32_t top_irq_mask; + uint32_t top_irq_clear; + uint32_t top_irq_set; + uint32_t top_irq_cmd; + uint32_t top_violation_status; + uint32_t top_spare; +}; + +/** + * struct cam_lrme_hw_info : LRME registers information + * + * @clc_reg : LRME CLC registers + * @bus_rd_reg : LRME FE registers + * @bus_wr_reg : LRME WE registers + * @titan_reg : LRME top reisters + */ +struct cam_lrme_hw_info { + struct cam_lrme_clc_reg clc_reg; + struct cam_lrme_bus_rd_hw_info bus_rd_reg; + struct cam_lrme_bus_wr_hw_info bus_wr_reg; + struct cam_lrme_titan_reg titan_reg; +}; + +int cam_lrme_hw_process_irq(void *priv, void *data); +int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args, + uint32_t arg_size); +int cam_lrme_hw_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size); +int cam_lrme_hw_stop(void *hw_priv, void *stop_args, uint32_t arg_size); +int cam_lrme_hw_get_caps(void *hw_priv, void *get_hw_cap_args, + uint32_t arg_size); +irqreturn_t cam_lrme_hw_irq(int irq_num, void *data); +int cam_lrme_hw_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); +int cam_lrme_hw_util_get_caps(struct cam_hw_info *lrme_hw, + struct cam_lrme_dev_cap *hw_caps); +int cam_lrme_hw_start(void *hw_priv, void *hw_init_args, uint32_t arg_size); +int cam_lrme_hw_flush(void *hw_priv, void *hw_flush_args, uint32_t arg_size); +void cam_lrme_set_irq(struct cam_hw_info *lrme_hw, enum cam_lrme_irq_set set); + +#endif /* _CAM_LRME_HW_CORE_H_ */ diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c new file mode 100644 index 000000000000..20828f629b4d --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_subdev.h" +#include "cam_lrme_hw_intf.h" +#include "cam_lrme_hw_core.h" +#include "cam_lrme_hw_soc.h" +#include "cam_lrme_hw_reg.h" +#include "cam_req_mgr_workq.h" +#include "cam_lrme_hw_mgr.h" +#include "cam_mem_mgr_api.h" +#include "cam_smmu_api.h" + +static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core, + struct cam_hw_info *lrme_hw) +{ + int rc, i; + struct cam_cdm_bl_request *cdm_cmd; + struct cam_cdm_acquire_data cdm_acquire; + struct cam_lrme_cdm_info *hw_cdm_info; + + hw_cdm_info = kzalloc(sizeof(struct cam_lrme_cdm_info), + GFP_KERNEL); + if (!hw_cdm_info) { + CAM_ERR(CAM_LRME, "No memory for hw_cdm_info"); + return -ENOMEM; + } + + cdm_cmd = kzalloc((sizeof(struct cam_cdm_bl_request) + + ((CAM_LRME_MAX_HW_ENTRIES - 1) * + sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); + if (!cdm_cmd) { + CAM_ERR(CAM_LRME, "No memory for cdm_cmd"); + kfree(hw_cdm_info); + return -ENOMEM; + } + + memset(&cdm_acquire, 0, sizeof(cdm_acquire)); + strlcpy(cdm_acquire.identifier, "lrmecdm", sizeof("lrmecdm")); + cdm_acquire.cell_index = lrme_hw->soc_info.index; + cdm_acquire.handle = 0; + cdm_acquire.userdata = hw_cdm_info; + cdm_acquire.cam_cdm_callback = NULL; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.base_array_cnt = lrme_hw->soc_info.num_reg_map; + for (i = 0; i < lrme_hw->soc_info.num_reg_map; i++) + cdm_acquire.base_array[i] = &lrme_hw->soc_info.reg_map[i]; + + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_LRME, "Can't acquire cdm"); + goto error; + } + + hw_cdm_info->cdm_cmd = cdm_cmd; + hw_cdm_info->cdm_ops = cdm_acquire.ops; + hw_cdm_info->cdm_handle = cdm_acquire.handle; + + lrme_core->hw_cdm_info = hw_cdm_info; + CAM_DBG(CAM_LRME, "cdm acquire done"); + + return 0; +error: + kfree(cdm_cmd); + kfree(hw_cdm_info); + return rc; +} + +static int cam_lrme_hw_dev_probe(struct platform_device *pdev) +{ + struct cam_hw_info *lrme_hw; + struct cam_hw_intf lrme_hw_intf; + struct cam_lrme_core *lrme_core; + const struct of_device_id *match_dev = NULL; + struct cam_lrme_hw_info *hw_info; + int rc, i; + + lrme_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!lrme_hw) { + CAM_ERR(CAM_LRME, "No memory to create lrme_hw"); + return -ENOMEM; + } + + lrme_core = kzalloc(sizeof(struct cam_lrme_core), GFP_KERNEL); + if (!lrme_core) { + CAM_ERR(CAM_LRME, "No memory to create lrme_core"); + kfree(lrme_hw); + return -ENOMEM; + } + + lrme_hw->core_info = lrme_core; + lrme_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + lrme_hw->soc_info.pdev = pdev; + lrme_hw->soc_info.dev = &pdev->dev; + lrme_hw->soc_info.dev_name = pdev->name; + lrme_hw->open_count = 0; + lrme_core->state = CAM_LRME_CORE_STATE_INIT; + + mutex_init(&lrme_hw->hw_mutex); + spin_lock_init(&lrme_hw->hw_lock); + init_completion(&lrme_hw->hw_complete); + init_completion(&lrme_core->reset_complete); + + rc = cam_req_mgr_workq_create("cam_lrme_hw_worker", + CAM_LRME_HW_WORKQ_NUM_TASK, + &lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_LRME, "Unable to create a workq, rc=%d", rc); + goto free_memory; + } + + for (i = 0; i < CAM_LRME_HW_WORKQ_NUM_TASK; i++) + lrme_core->work->task.pool[i].payload = + &lrme_core->work_data[i]; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev || !match_dev->data) { + CAM_ERR(CAM_LRME, "No Of_match data, %pK", match_dev); + rc = -EINVAL; + goto destroy_workqueue; + } + hw_info = (struct cam_lrme_hw_info *)match_dev->data; + lrme_core->hw_info = hw_info; + + rc = cam_lrme_soc_init_resources(&lrme_hw->soc_info, + cam_lrme_hw_irq, lrme_hw); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to init soc, rc=%d", rc); + goto destroy_workqueue; + } + + rc = cam_lrme_hw_dev_util_cdm_acquire(lrme_core, lrme_hw); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to acquire cdm"); + goto deinit_platform_res; + } + + rc = cam_smmu_get_handle("lrme", &lrme_core->device_iommu.non_secure); + if (rc) { + CAM_ERR(CAM_LRME, "Get iommu handle failed"); + goto release_cdm; + } + + rc = cam_lrme_hw_start(lrme_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to hw init, rc=%d", rc); + goto detach_smmu; + } + + rc = cam_lrme_hw_util_get_caps(lrme_hw, &lrme_core->hw_caps); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to get hw caps, rc=%d", rc); + if (cam_lrme_hw_stop(lrme_hw, NULL, 0)) + CAM_ERR(CAM_LRME, "Failed in hw deinit"); + goto detach_smmu; + } + + rc = cam_lrme_hw_stop(lrme_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to deinit hw, rc=%d", rc); + goto detach_smmu; + } + + lrme_core->hw_idx = lrme_hw->soc_info.index; + lrme_hw_intf.hw_priv = lrme_hw; + lrme_hw_intf.hw_idx = lrme_hw->soc_info.index; + lrme_hw_intf.hw_ops.get_hw_caps = cam_lrme_hw_get_caps; + lrme_hw_intf.hw_ops.init = NULL; + lrme_hw_intf.hw_ops.deinit = NULL; + lrme_hw_intf.hw_ops.reset = cam_lrme_hw_reset; + lrme_hw_intf.hw_ops.reserve = NULL; + lrme_hw_intf.hw_ops.release = NULL; + lrme_hw_intf.hw_ops.start = cam_lrme_hw_start; + lrme_hw_intf.hw_ops.stop = cam_lrme_hw_stop; + lrme_hw_intf.hw_ops.read = NULL; + lrme_hw_intf.hw_ops.write = NULL; + lrme_hw_intf.hw_ops.process_cmd = cam_lrme_hw_process_cmd; + lrme_hw_intf.hw_ops.flush = cam_lrme_hw_flush; + lrme_hw_intf.hw_type = CAM_HW_LRME; + + rc = cam_cdm_get_iommu_handle("lrmecdm", &lrme_core->cdm_iommu); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to acquire the CDM iommu handles"); + goto detach_smmu; + } + + rc = cam_lrme_mgr_register_device(&lrme_hw_intf, + &lrme_core->device_iommu, + &lrme_core->cdm_iommu); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to register device"); + goto detach_smmu; + } + + platform_set_drvdata(pdev, lrme_hw); + CAM_DBG(CAM_LRME, "LRME-%d probe successful", lrme_hw_intf.hw_idx); + + return rc; + +detach_smmu: + cam_smmu_destroy_handle(lrme_core->device_iommu.non_secure); +release_cdm: + cam_cdm_release(lrme_core->hw_cdm_info->cdm_handle); + kfree(lrme_core->hw_cdm_info->cdm_cmd); + kfree(lrme_core->hw_cdm_info); +deinit_platform_res: + if (cam_lrme_soc_deinit_resources(&lrme_hw->soc_info)) + CAM_ERR(CAM_LRME, "Failed in soc deinit"); + mutex_destroy(&lrme_hw->hw_mutex); +destroy_workqueue: + cam_req_mgr_workq_destroy(&lrme_core->work); +free_memory: + mutex_destroy(&lrme_hw->hw_mutex); + kfree(lrme_hw); + kfree(lrme_core); + + return rc; +} + +static int cam_lrme_hw_dev_remove(struct platform_device *pdev) +{ + int rc = 0; + struct cam_hw_info *lrme_hw; + struct cam_lrme_core *lrme_core; + + lrme_hw = platform_get_drvdata(pdev); + if (!lrme_hw) { + CAM_ERR(CAM_LRME, "Invalid lrme_hw from fd_hw_intf"); + rc = -ENODEV; + goto deinit_platform_res; + } + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + if (!lrme_core) { + CAM_ERR(CAM_LRME, "Invalid lrme_core from fd_hw"); + rc = -EINVAL; + goto deinit_platform_res; + } + + cam_smmu_destroy_handle(lrme_core->device_iommu.non_secure); + cam_cdm_release(lrme_core->hw_cdm_info->cdm_handle); + cam_lrme_mgr_deregister_device(lrme_core->hw_idx); + + kfree(lrme_core->hw_cdm_info->cdm_cmd); + kfree(lrme_core->hw_cdm_info); + kfree(lrme_core); + +deinit_platform_res: + rc = cam_lrme_soc_deinit_resources(&lrme_hw->soc_info); + if (rc) + CAM_ERR(CAM_LRME, "Error in LRME soc deinit, rc=%d", rc); + + mutex_destroy(&lrme_hw->hw_mutex); + kfree(lrme_hw); + + return rc; +} + +static const struct of_device_id cam_lrme_hw_dt_match[] = { + { + .compatible = "qcom,lrme", + .data = &cam_lrme10_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_lrme_hw_dt_match); + +static struct platform_driver cam_lrme_hw_driver = { + .probe = cam_lrme_hw_dev_probe, + .remove = cam_lrme_hw_dev_remove, + .driver = { + .name = "cam_lrme_hw", + .owner = THIS_MODULE, + .of_match_table = cam_lrme_hw_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_lrme_hw_init_module(void) +{ + return platform_driver_register(&cam_lrme_hw_driver); +} + +static void __exit cam_lrme_hw_exit_module(void) +{ + platform_driver_unregister(&cam_lrme_hw_driver); +} + +module_init(cam_lrme_hw_init_module); +module_exit(cam_lrme_hw_exit_module); +MODULE_DESCRIPTION("CAM LRME HW driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h new file mode 100644 index 000000000000..b74d53700419 --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_HW_INTF_H_ +#define _CAM_LRME_HW_INTF_H_ + +#include +#include +#include +#include +#include +#include + +#include "cam_io_util.h" +#include "cam_soc_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_subdev.h" +#include "cam_cpas_api.h" +#include "cam_hw_mgr_intf.h" +#include "cam_debug_util.h" + + +#define CAM_LRME_MAX_IO_BUFFER 2 +#define CAM_LRME_MAX_HW_ENTRIES 5 + +#define CAM_LRME_BASE_IDX 0 + +/** + * enum cam_lrme_hw_type : Enum for LRME HW type + * + * @CAM_HW_LRME : LRME HW type + */ +enum cam_lrme_hw_type { + CAM_HW_LRME, +}; + +/** + * enum cam_lrme_cb_type : HW manager call back type + * + * @CAM_LRME_CB_BUF_DONE : Indicate buf done has been generated + * @CAM_LRME_CB_COMP_REG_UPDATE : Indicate receiving WE comp reg update + * @CAM_LRME_CB_PUT_FRAME : Request HW manager to put back the frame + * @CAM_LRME_CB_ERROR : Indicate error irq has been generated + */ +enum cam_lrme_cb_type { + CAM_LRME_CB_BUF_DONE = 1, + CAM_LRME_CB_COMP_REG_UPDATE = 1 << 1, + CAM_LRME_CB_PUT_FRAME = 1 << 2, + CAM_LRME_CB_ERROR = 1 << 3, +}; + +/** + * enum cam_lrme_hw_cmd_type : HW CMD type + * + * @CAM_LRME_HW_CMD_prepare_hw_update : Prepare HW update + * @CAM_LRME_HW_CMD_REGISTER_CB : register HW manager callback + * @CAM_LRME_HW_CMD_SUBMIT : Submit frame to HW + * @CAM_LRME_HW_CMD_DUMP_REGISTER : dump register values + */ +enum cam_lrme_hw_cmd_type { + CAM_LRME_HW_CMD_PREPARE_HW_UPDATE, + CAM_LRME_HW_CMD_REGISTER_CB, + CAM_LRME_HW_CMD_SUBMIT, + CAM_LRME_HW_CMD_DUMP_REGISTER, +}; + +/** + * enum cam_lrme_hw_reset_type : Type of reset + * + * @CAM_LRME_HW_RESET_TYPE_HW_RESET : HW reset + * @CAM_LRME_HW_RESET_TYPE_SW_RESET : SW reset + */ +enum cam_lrme_hw_reset_type { + CAM_LRME_HW_RESET_TYPE_HW_RESET, + CAM_LRME_HW_RESET_TYPE_SW_RESET, +}; + +/** + *struct cam_lrme_frame_request : LRME frame request + * + * @frame_list : List head + * @req_id : Request ID + * @ctxt_to_hw_map : Information about context id, priority and device id + * @hw_device : Pointer to HW device + * @hw_update_entries : List of hw_update_entries + * @num_hw_update_entries : number of hw_update_entries + */ +struct cam_lrme_frame_request { + struct list_head frame_list; + uint64_t req_id; + void *ctxt_to_hw_map; + struct cam_lrme_device *hw_device; + struct cam_hw_update_entry hw_update_entries[CAM_LRME_MAX_HW_ENTRIES]; + uint32_t num_hw_update_entries; +}; + +/** + * struct cam_lrme_hw_io_buffer : IO buffer information + * + * @valid : Indicate whether this IO config is valid + * @io_cfg : Pointer to IO configuration + * @num_buf : Number of buffers + * @num_plane : Number of planes + * @io_addr : List of IO address + */ +struct cam_lrme_hw_io_buffer { + bool valid; + struct cam_buf_io_cfg *io_cfg; + uint32_t num_buf; + uint32_t num_plane; + uint64_t io_addr[CAM_PACKET_MAX_PLANES]; +}; + +/** + * struct cam_lrme_hw_cmd_config_args : Args for prepare HW update + * + * @hw_device : Pointer to HW device + * @input_buf : List of input buffers + * @output_buf : List of output buffers + * @cmd_buf_addr : Pointer to available KMD buffer + * @size : Available KMD buffer size + * @config_buf_size : Size used to prepare update + */ +struct cam_lrme_hw_cmd_config_args { + struct cam_lrme_device *hw_device; + struct cam_lrme_hw_io_buffer input_buf[CAM_LRME_MAX_IO_BUFFER]; + struct cam_lrme_hw_io_buffer output_buf[CAM_LRME_MAX_IO_BUFFER]; + uint32_t *cmd_buf_addr; + uint32_t size; + uint32_t config_buf_size; +}; + +/** + * struct cam_lrme_hw_flush_args : Args for flush HW + * + * @ctxt_to_hw_map : Identity of context + * @req_to_flush : Pointer to the frame need to flush in + * case of single frame flush + * @flush_type : Flush type + */ +struct cam_lrme_hw_flush_args { + void *ctxt_to_hw_map; + struct cam_lrme_frame_request *req_to_flush; + uint32_t flush_type; +}; + +/** + * struct cam_lrme_hw_reset_args : Args for reset HW + * + * @reset_type : Enum cam_lrme_hw_reset_type + */ +struct cam_lrme_hw_reset_args { + uint32_t reset_type; +}; + +/** + * struct cam_lrme_hw_cb_args : HW manager callback args + * + * @cb_type : Callback event type + * @frame_req : Pointer to the frame associated with the cb + */ +struct cam_lrme_hw_cb_args { + uint32_t cb_type; + struct cam_lrme_frame_request *frame_req; +}; + +/** + * struct cam_lrme_hw_cmd_set_cb : Args for set callback function + * + * @cam_lrme_hw_mgr_cb : Callback function pointer + * @data : Data sent along with callback function + */ +struct cam_lrme_hw_cmd_set_cb { + int (*cam_lrme_hw_mgr_cb)(void *data, + struct cam_lrme_hw_cb_args *args); + void *data; +}; + +/** + * struct cam_lrme_hw_submit_args : Args for submit request + * + * @hw_update_entries : List of hw update entries used to program registers + * @num_hw_update_entries : Number of hw update entries + * @frame_req : Pointer to the frame request + */ +struct cam_lrme_hw_submit_args { + struct cam_hw_update_entry *hw_update_entries; + uint32_t num_hw_update_entries; + struct cam_lrme_frame_request *frame_req; +}; + +#endif /* _CAM_LRME_HW_INTF_H_ */ diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h new file mode 100644 index 000000000000..17eb25b0facf --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_HW_REG_H_ +#define _CAM_LRME_HW_REG_H_ + +#include "cam_lrme_hw_core.h" + +static struct cam_lrme_hw_info cam_lrme10_hw_info = { + .clc_reg = { + .clc_hw_version = 0x00000000, + .clc_hw_status = 0x00000004, + .clc_hw_status_dbg = 0x00000008, + .clc_module_cfg = 0x00000060, + .clc_moduleformat = 0x000000A8, + .clc_rangestep = 0x00000068, + .clc_offset = 0x0000006C, + .clc_maxallowedsad = 0x00000070, + .clc_minallowedtarmad = 0x00000074, + .clc_meaningfulsaddiff = 0x00000078, + .clc_minsaddiffdenom = 0x0000007C, + .clc_robustnessmeasuredistmap_0 = 0x00000080, + .clc_robustnessmeasuredistmap_1 = 0x00000084, + .clc_robustnessmeasuredistmap_2 = 0x00000088, + .clc_robustnessmeasuredistmap_3 = 0x0000008C, + .clc_robustnessmeasuredistmap_4 = 0x00000090, + .clc_robustnessmeasuredistmap_5 = 0x00000094, + .clc_robustnessmeasuredistmap_6 = 0x00000098, + .clc_robustnessmeasuredistmap_7 = 0x0000009C, + .clc_ds_crop_horizontal = 0x000000A0, + .clc_ds_crop_vertical = 0x000000A4, + .clc_tar_pd_unpacker = 0x000000AC, + .clc_ref_pd_unpacker = 0x000000B0, + .clc_sw_override = 0x000000B4, + .clc_tar_height = 0x000000B8, + .clc_ref_height = 0x000000BC, + .clc_test_bus_ctrl = 0x000001F8, + .clc_spare = 0x000001FC, + }, + .bus_rd_reg = { + .common_reg = { + .hw_version = 0x00000200, + .hw_capability = 0x00000204, + .sw_reset = 0x00000208, + .cgc_override = 0x0000020C, + .irq_mask = 0x00000210, + .irq_clear = 0x00000214, + .irq_cmd = 0x00000218, + .irq_status = 0x0000021C, + .cmd = 0x00000220, + .irq_set = 0x00000224, + .misr_reset = 0x0000022C, + .security_cfg = 0x00000230, + .pwr_iso_cfg = 0x00000234, + .pwr_iso_seed = 0x00000238, + .test_bus_ctrl = 0x00000248, + .spare = 0x0000024C, + }, + .bus_client_reg = { + /* bus client 0 */ + { + .core_cfg = 0x00000250, + .ccif_meta_data = 0x00000254, + .addr_image = 0x00000258, + .rd_buffer_size = 0x0000025C, + .rd_stride = 0x00000260, + .unpack_cfg_0 = 0x00000264, + .latency_buff_allocation = 0x00000278, + .burst_limit_cfg = 0x00000280, + .misr_cfg_0 = 0x00000284, + .misr_cfg_1 = 0x00000288, + .misr_rd_val = 0x0000028C, + .debug_status_cfg = 0x00000290, + .debug_status_0 = 0x00000294, + .debug_status_1 = 0x00000298, + }, + /* bus client 1 */ + { + .core_cfg = 0x000002F0, + .ccif_meta_data = 0x000002F4, + .addr_image = 0x000002F8, + .rd_buffer_size = 0x000002FC, + .rd_stride = 0x00000300, + .unpack_cfg_0 = 0x00000304, + .latency_buff_allocation = 0x00000318, + .burst_limit_cfg = 0x00000320, + .misr_cfg_0 = 0x00000324, + .misr_cfg_1 = 0x00000328, + .misr_rd_val = 0x0000032C, + .debug_status_cfg = 0x00000330, + .debug_status_0 = 0x00000334, + .debug_status_1 = 0x00000338, + }, + }, + }, + .bus_wr_reg = { + .common_reg = { + .hw_version = 0x00000500, + .hw_capability = 0x00000504, + .sw_reset = 0x00000508, + .cgc_override = 0x0000050C, + .misr_reset = 0x000005C8, + .pwr_iso_cfg = 0x000005CC, + .test_bus_ctrl = 0x0000061C, + .composite_mask_0 = 0x00000510, + .irq_mask_0 = 0x00000544, + .irq_mask_1 = 0x00000548, + .irq_clear_0 = 0x00000550, + .irq_clear_1 = 0x00000554, + .irq_status_0 = 0x0000055C, + .irq_status_1 = 0x00000560, + .irq_cmd = 0x00000568, + .irq_set_0 = 0x000005BC, + .irq_set_1 = 0x000005C0, + .addr_fifo_status = 0x000005A8, + .frame_header_cfg0 = 0x000005AC, + .frame_header_cfg1 = 0x000005B0, + .spare = 0x00000620, + }, + .bus_client_reg = { + /* bus client 0 */ + { + .status_0 = 0x00000700, + .status_1 = 0x00000704, + .cfg = 0x00000708, + .addr_frame_header = 0x0000070C, + .frame_header_cfg = 0x00000710, + .addr_image = 0x00000714, + .addr_image_offset = 0x00000718, + .buffer_width_cfg = 0x0000071C, + .buffer_height_cfg = 0x00000720, + .packer_cfg = 0x00000724, + .wr_stride = 0x00000728, + .irq_subsample_cfg_period = 0x00000748, + .irq_subsample_cfg_pattern = 0x0000074C, + .burst_limit_cfg = 0x0000075C, + .misr_cfg = 0x00000760, + .misr_rd_word_sel = 0x00000764, + .misr_val = 0x00000768, + .debug_status_cfg = 0x0000076C, + .debug_status_0 = 0x00000770, + .debug_status_1 = 0x00000774, + }, + /* bus client 1 */ + { + .status_0 = 0x00000800, + .status_1 = 0x00000804, + .cfg = 0x00000808, + .addr_frame_header = 0x0000080C, + .frame_header_cfg = 0x00000810, + .addr_image = 0x00000814, + .addr_image_offset = 0x00000818, + .buffer_width_cfg = 0x0000081C, + .buffer_height_cfg = 0x00000820, + .packer_cfg = 0x00000824, + .wr_stride = 0x00000828, + .irq_subsample_cfg_period = 0x00000848, + .irq_subsample_cfg_pattern = 0x0000084C, + .burst_limit_cfg = 0x0000085C, + .misr_cfg = 0x00000860, + .misr_rd_word_sel = 0x00000864, + .misr_val = 0x00000868, + .debug_status_cfg = 0x0000086C, + .debug_status_0 = 0x00000870, + .debug_status_1 = 0x00000874, + }, + }, + }, + .titan_reg = { + .top_hw_version = 0x00000900, + .top_titan_version = 0x00000904, + .top_rst_cmd = 0x00000908, + .top_core_clk_cfg = 0x00000920, + .top_irq_status = 0x0000090C, + .top_irq_mask = 0x00000910, + .top_irq_clear = 0x00000914, + .top_irq_set = 0x00000918, + .top_irq_cmd = 0x0000091C, + .top_violation_status = 0x00000924, + .top_spare = 0x000009FC, + }, +}; + +#endif /* _CAM_LRME_HW_REG_H_ */ diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c new file mode 100644 index 000000000000..ba227d2223eb --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_lrme_hw_core.h" +#include "cam_lrme_hw_soc.h" + + +int cam_lrme_soc_enable_resources(struct cam_hw_info *lrme_hw) +{ + struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info; + struct cam_lrme_soc_private *soc_private = + (struct cam_lrme_soc_private *)soc_info->soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + int rc = 0; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 2; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = 7200000; + axi_vote.axi_path[0].mnoc_ab_bw = 7200000; + axi_vote.axi_path[0].mnoc_ib_bw = 7200000; + axi_vote.axi_path[1].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[1].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[1].camnoc_bw = 7200000; + axi_vote.axi_path[1].mnoc_ab_bw = 7200000; + axi_vote.axi_path[1].mnoc_ib_bw = 7200000; + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to start cpas, rc %d", rc); + return -EFAULT; + } + + rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_SVS_VOTE, + true); + if (rc) { + CAM_ERR(CAM_LRME, + "Failed to enable platform resource, rc %d", rc); + goto stop_cpas; + } + + cam_lrme_set_irq(lrme_hw, CAM_LRME_IRQ_ENABLE); + + return rc; + +stop_cpas: + if (cam_cpas_stop(soc_private->cpas_handle)) + CAM_ERR(CAM_LRME, "Failed to stop cpas"); + + return rc; +} + +int cam_lrme_soc_disable_resources(struct cam_hw_info *lrme_hw) +{ + struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info; + struct cam_lrme_soc_private *soc_private; + int rc = 0; + + soc_private = soc_info->soc_private; + + cam_lrme_set_irq(lrme_hw, CAM_LRME_IRQ_DISABLE); + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to disable platform resource"); + return rc; + } + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_LRME, "Failed to stop cpas"); + + return rc; +} + +int cam_lrme_soc_init_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, void *private_data) +{ + struct cam_lrme_soc_private *soc_private; + struct cam_cpas_register_params cpas_register_param; + int rc; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_LRME, "Failed in get_dt_properties, rc=%d", rc); + return rc; + } + + rc = cam_soc_util_request_platform_resource(soc_info, irq_handler, + private_data); + if (rc) { + CAM_ERR(CAM_LRME, "Failed in request_platform_resource rc=%d", + rc); + return rc; + } + + soc_private = kzalloc(sizeof(struct cam_lrme_soc_private), GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto release_res; + } + soc_info->soc_private = soc_private; + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, + "lrmecpas", CAM_HW_IDENTIFIER_LENGTH); + cpas_register_param.cell_index = soc_info->index; + cpas_register_param.dev = &soc_info->pdev->dev; + cpas_register_param.userdata = private_data; + cpas_register_param.cam_cpas_client_cb = NULL; + + rc = cam_cpas_register_client(&cpas_register_param); + if (rc) { + CAM_ERR(CAM_LRME, "CPAS registration failed"); + goto free_soc_private; + } + soc_private->cpas_handle = cpas_register_param.client_handle; + CAM_DBG(CAM_LRME, "CPAS handle=%d", soc_private->cpas_handle); + + return rc; + +free_soc_private: + kfree(soc_info->soc_private); + soc_info->soc_private = NULL; +release_res: + cam_soc_util_release_platform_resource(soc_info); + + return rc; +} + +int cam_lrme_soc_deinit_resources(struct cam_hw_soc_info *soc_info) +{ + struct cam_lrme_soc_private *soc_private = + (struct cam_lrme_soc_private *)soc_info->soc_private; + int rc; + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_LRME, "Unregister cpas failed, handle=%d, rc=%d", + soc_private->cpas_handle, rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_ERR(CAM_LRME, "release platform failed, rc=%d", rc); + + kfree(soc_info->soc_private); + soc_info->soc_private = NULL; + + return rc; +} diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h new file mode 100644 index 000000000000..d77ac2bfdb63 --- /dev/null +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_HW_SOC_H_ +#define _CAM_LRME_HW_SOC_H_ + +#include "cam_soc_util.h" + +struct cam_lrme_soc_private { + uint32_t cpas_handle; +}; + +int cam_lrme_soc_enable_resources(struct cam_hw_info *lrme_hw); +int cam_lrme_soc_disable_resources(struct cam_hw_info *lrme_hw); +int cam_lrme_soc_init_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, void *private_data); +int cam_lrme_soc_deinit_resources(struct cam_hw_soc_info *soc_info); + +#endif /* _CAM_LRME_HW_SOC_H_ */ diff --git a/drivers/cam_req_mgr/Makefile b/drivers/cam_req_mgr/Makefile new file mode 100644 index 000000000000..375d17133193 --- /dev/null +++ b/drivers/cam_req_mgr/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree) + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_core.o\ + cam_req_mgr_dev.o \ + cam_req_mgr_util.o \ + cam_req_mgr_workq.o \ + cam_mem_mgr.o \ + cam_req_mgr_timer.o \ + cam_req_mgr_debug.o diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c new file mode 100644 index 000000000000..73ac694eeafa --- /dev/null +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -0,0 +1,1391 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_req_mgr_util.h" +#include "cam_mem_mgr.h" +#include "cam_smmu_api.h" +#include "cam_debug_util.h" + +static struct cam_mem_table tbl; +static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED); + +static int cam_mem_util_get_dma_dir(uint32_t flags) +{ + int rc = -EINVAL; + + if (flags & CAM_MEM_FLAG_HW_READ_ONLY) + rc = DMA_TO_DEVICE; + else if (flags & CAM_MEM_FLAG_HW_WRITE_ONLY) + rc = DMA_FROM_DEVICE; + else if (flags & CAM_MEM_FLAG_HW_READ_WRITE) + rc = DMA_BIDIRECTIONAL; + else if (flags & CAM_MEM_FLAG_PROTECTED_MODE) + rc = DMA_BIDIRECTIONAL; + + return rc; +} + +static int cam_mem_util_map_cpu_va(struct dma_buf *dmabuf, + uintptr_t *vaddr, + size_t *len) +{ + int i, j, rc; + void *addr; + + /* + * dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() + * need to be called in pair to avoid stability issue. + */ + rc = dma_buf_begin_cpu_access(dmabuf, DMA_BIDIRECTIONAL); + if (rc) { + CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc); + return rc; + } + + /* + * Code could be simplified if ION support of dma_buf_vmap is + * available. This workaround takes the avandaage that ion_alloc + * returns a virtually contiguous memory region, so we just need + * to _kmap each individual page and then only use the virtual + * address returned from the first call to _kmap. + */ + for (i = 0; i < PAGE_ALIGN(dmabuf->size) / PAGE_SIZE; i++) { + addr = dma_buf_kmap(dmabuf, i); + if (IS_ERR_OR_NULL(addr)) { + CAM_ERR(CAM_MEM, "kernel map fail"); + for (j = 0; j < i; j++) + dma_buf_kunmap(dmabuf, + j, + (void *)(*vaddr + (j * PAGE_SIZE))); + *vaddr = 0; + *len = 0; + rc = -ENOSPC; + goto fail; + } + if (i == 0) + *vaddr = (uint64_t)addr; + } + + *len = dmabuf->size; + + return 0; + +fail: + dma_buf_end_cpu_access(dmabuf, DMA_BIDIRECTIONAL); + return rc; +} +static int cam_mem_util_unmap_cpu_va(struct dma_buf *dmabuf, + uint64_t vaddr) +{ + int i, rc = 0, page_num; + + if (!dmabuf || !vaddr) { + CAM_ERR(CAM_MEM, "Invalid input args %pK %llX", dmabuf, vaddr); + return -EINVAL; + } + + page_num = PAGE_ALIGN(dmabuf->size) / PAGE_SIZE; + + for (i = 0; i < page_num; i++) { + dma_buf_kunmap(dmabuf, i, + (void *)(vaddr + (i * PAGE_SIZE))); + } + + /* + * dma_buf_begin_cpu_access() and + * dma_buf_end_cpu_access() need to be called in pair + * to avoid stability issue. + */ + rc = dma_buf_end_cpu_access(dmabuf, DMA_BIDIRECTIONAL); + if (rc) { + CAM_ERR(CAM_MEM, "Failed in end cpu access, dmabuf=%pK", + dmabuf); + return rc; + } + + return rc; +} + +int cam_mem_mgr_init(void) +{ + int i; + int bitmap_size; + + memset(tbl.bufq, 0, sizeof(tbl.bufq)); + + bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long); + tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!tbl.bitmap) + return -ENOMEM; + + tbl.bits = bitmap_size * BITS_PER_BYTE; + bitmap_zero(tbl.bitmap, tbl.bits); + /* We need to reserve slot 0 because 0 is invalid */ + set_bit(0, tbl.bitmap); + + for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) { + tbl.bufq[i].fd = -1; + tbl.bufq[i].buf_handle = -1; + } + mutex_init(&tbl.m_lock); + + atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED); + + return 0; +} + +static int32_t cam_mem_get_slot(void) +{ + int32_t idx; + + mutex_lock(&tbl.m_lock); + idx = find_first_zero_bit(tbl.bitmap, tbl.bits); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { + mutex_unlock(&tbl.m_lock); + return -ENOMEM; + } + + set_bit(idx, tbl.bitmap); + tbl.bufq[idx].active = true; + mutex_init(&tbl.bufq[idx].q_lock); + mutex_unlock(&tbl.m_lock); + + return idx; +} + +static void cam_mem_put_slot(int32_t idx) +{ + mutex_lock(&tbl.m_lock); + mutex_lock(&tbl.bufq[idx].q_lock); + tbl.bufq[idx].active = false; + mutex_unlock(&tbl.bufq[idx].q_lock); + mutex_destroy(&tbl.bufq[idx].q_lock); + clear_bit(idx, tbl.bitmap); + mutex_unlock(&tbl.m_lock); +} + +int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, + uint64_t *iova_ptr, size_t *len_ptr) +{ + int rc = 0, idx; + + *len_ptr = 0; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) + return -EINVAL; + + if (!tbl.bufq[idx].active) + return -EINVAL; + + mutex_lock(&tbl.bufq[idx].q_lock); + if (buf_handle != tbl.bufq[idx].buf_handle) { + rc = -EINVAL; + goto handle_mismatch; + } + + if (CAM_MEM_MGR_IS_SECURE_HDL(buf_handle)) + rc = cam_smmu_get_stage2_iova(mmu_handle, + tbl.bufq[idx].fd, + iova_ptr, + len_ptr); + else + rc = cam_smmu_get_iova(mmu_handle, + tbl.bufq[idx].fd, + iova_ptr, + len_ptr); + if (rc) { + CAM_ERR(CAM_MEM, + "fail to map buf_hdl:0x%x, mmu_hdl: 0x%x for fd:%d", + buf_handle, mmu_handle, tbl.bufq[idx].fd); + goto handle_mismatch; + } + + CAM_DBG(CAM_MEM, + "handle:0x%x fd:%d iova_ptr:%pK len_ptr:%llu", + mmu_handle, tbl.bufq[idx].fd, iova_ptr, *len_ptr); +handle_mismatch: + mutex_unlock(&tbl.bufq[idx].q_lock); + return rc; +} +EXPORT_SYMBOL(cam_mem_get_io_buf); + +int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) +{ + int idx; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!buf_handle || !vaddr_ptr || !len) + return -EINVAL; + + idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) + return -EINVAL; + + if (!tbl.bufq[idx].active) + return -EPERM; + + if (buf_handle != tbl.bufq[idx].buf_handle) + return -EINVAL; + + if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS)) + return -EINVAL; + + if (tbl.bufq[idx].kmdvaddr) { + *vaddr_ptr = tbl.bufq[idx].kmdvaddr; + *len = tbl.bufq[idx].len; + } else { + CAM_ERR(CAM_MEM, "No KMD access was requested for 0x%x handle", + buf_handle); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(cam_mem_get_cpu_buf); + +int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) +{ + int rc = 0, idx; + uint32_t cache_dir; + unsigned long dmabuf_flag = 0; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!cmd) + return -EINVAL; + + idx = CAM_MEM_MGR_GET_HDL_IDX(cmd->buf_handle); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) + return -EINVAL; + + mutex_lock(&tbl.bufq[idx].q_lock); + + if (!tbl.bufq[idx].active) { + rc = -EINVAL; + goto end; + } + + if (cmd->buf_handle != tbl.bufq[idx].buf_handle) { + rc = -EINVAL; + goto end; + } + + rc = dma_buf_get_flags(tbl.bufq[idx].dma_buf, &dmabuf_flag); + if (rc) { + CAM_ERR(CAM_MEM, "cache get flags failed %d", rc); + goto end; + } + + if (dmabuf_flag & ION_FLAG_CACHED) { + switch (cmd->mem_cache_ops) { + case CAM_MEM_CLEAN_CACHE: + cache_dir = DMA_TO_DEVICE; + break; + case CAM_MEM_INV_CACHE: + cache_dir = DMA_FROM_DEVICE; + break; + case CAM_MEM_CLEAN_INV_CACHE: + cache_dir = DMA_BIDIRECTIONAL; + break; + default: + CAM_ERR(CAM_MEM, + "invalid cache ops :%d", cmd->mem_cache_ops); + rc = -EINVAL; + goto end; + } + } else { + CAM_DBG(CAM_MEM, "BUF is not cached"); + goto end; + } + + rc = dma_buf_begin_cpu_access(tbl.bufq[idx].dma_buf, + (cmd->mem_cache_ops == CAM_MEM_CLEAN_INV_CACHE) ? + DMA_BIDIRECTIONAL : DMA_TO_DEVICE); + if (rc) { + CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc); + goto end; + } + + rc = dma_buf_end_cpu_access(tbl.bufq[idx].dma_buf, + cache_dir); + if (rc) { + CAM_ERR(CAM_MEM, "dma end access failed rc=%d", rc); + goto end; + } + +end: + mutex_unlock(&tbl.bufq[idx].q_lock); + return rc; +} +EXPORT_SYMBOL(cam_mem_mgr_cache_ops); + +static int cam_mem_util_get_dma_buf(size_t len, + unsigned int heap_id_mask, + unsigned int flags, + struct dma_buf **buf) +{ + int rc = 0; + + if (!buf) { + CAM_ERR(CAM_MEM, "Invalid params"); + return -EINVAL; + } + + *buf = ion_alloc(len, heap_id_mask, flags); + if (IS_ERR_OR_NULL(*buf)) + return -ENOMEM; + + return rc; +} + +static int cam_mem_util_get_dma_buf_fd(size_t len, + size_t align, + unsigned int heap_id_mask, + unsigned int flags, + struct dma_buf **buf, + int *fd) +{ + struct dma_buf *dmabuf = NULL; + int rc = 0; + + if (!buf || !fd) { + CAM_ERR(CAM_MEM, "Invalid params, buf=%pK, fd=%pK", buf, fd); + return -EINVAL; + } + + *buf = ion_alloc(len, heap_id_mask, flags); + if (IS_ERR_OR_NULL(*buf)) + return -ENOMEM; + + *fd = dma_buf_fd(*buf, O_CLOEXEC); + if (*fd < 0) { + CAM_ERR(CAM_MEM, "get fd fail, *fd=%d", *fd); + rc = -EINVAL; + goto get_fd_fail; + } + + /* + * increment the ref count so that ref count becomes 2 here + * when we close fd, refcount becomes 1 and when we do + * dmap_put_buf, ref count becomes 0 and memory will be freed. + */ + dmabuf = dma_buf_get(*fd); + if (IS_ERR_OR_NULL(dmabuf)) { + CAM_ERR(CAM_MEM, "dma_buf_get failed, *fd=%d", *fd); + rc = -EINVAL; + } + + return rc; + +get_fd_fail: + dma_buf_put(*buf); + return rc; +} + +static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd, + struct dma_buf **dmabuf, + int *fd) +{ + uint32_t heap_id; + uint32_t ion_flag = 0; + int rc; + + if ((cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) && + (cmd->flags & CAM_MEM_FLAG_CDSP_OUTPUT)) { + heap_id = ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); + ion_flag |= + ION_FLAG_SECURE | ION_FLAG_CP_CAMERA | ION_FLAG_CP_CDSP; + } else if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) { + heap_id = ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); + ion_flag |= ION_FLAG_SECURE | ION_FLAG_CP_CAMERA; + } else { + heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) | + ION_HEAP(ION_CAMERA_HEAP_ID); + } + + if (cmd->flags & CAM_MEM_FLAG_CACHE) + ion_flag |= ION_FLAG_CACHED; + else + ion_flag &= ~ION_FLAG_CACHED; + + rc = cam_mem_util_get_dma_buf_fd(cmd->len, + cmd->align, + heap_id, + ion_flag, + dmabuf, + fd); + + return rc; +} + + +static int cam_mem_util_check_alloc_flags(struct cam_mem_mgr_alloc_cmd *cmd) +{ + 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); + return -EINVAL; + } + + if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE && + cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) { + CAM_ERR(CAM_MEM, "Kernel mapping in secure mode not allowed"); + return -EINVAL; + } + + return 0; +} + +static int cam_mem_util_check_map_flags(struct cam_mem_mgr_map_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 %d exceeded maximum(%d)", + cmd->num_hdl, CAM_MEM_MMU_MAX_HANDLE); + return -EINVAL; + } + + if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE && + cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) { + CAM_ERR(CAM_MEM, + "Kernel mapping in secure mode not allowed, flags=0x%x", + cmd->flags); + return -EINVAL; + } + + if (cmd->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) { + CAM_ERR(CAM_MEM, + "Shared memory buffers are not allowed to be mapped"); + return -EINVAL; + } + + return 0; +} + +static int cam_mem_util_map_hw_va(uint32_t flags, + int32_t *mmu_hdls, + int32_t num_hdls, + int fd, + dma_addr_t *hw_vaddr, + size_t *len, + enum cam_smmu_region_id region) +{ + int i; + int rc = -1; + int dir = cam_mem_util_get_dma_dir(flags); + + if (dir < 0) { + CAM_ERR(CAM_MEM, "fail to map DMA direction, dir=%d", dir); + return dir; + } + + CAM_DBG(CAM_MEM, + "map_hw_va : fd = %d, flags = 0x%x, dir=%d, num_hdls=%d", + fd, flags, dir, num_hdls); + + if (flags & CAM_MEM_FLAG_PROTECTED_MODE) { + for (i = 0; i < num_hdls; i++) { + rc = cam_smmu_map_stage2_iova(mmu_hdls[i], + fd, + dir, + hw_vaddr, + len); + + if (rc < 0) { + CAM_ERR(CAM_MEM, + "Failed to securely map to smmu, i=%d, fd=%d, dir=%d, mmu_hdl=%d, rc=%d", + i, fd, dir, mmu_hdls[i], rc); + goto multi_map_fail; + } + } + } else { + for (i = 0; i < num_hdls; i++) { + rc = cam_smmu_map_user_iova(mmu_hdls[i], + fd, + dir, + (dma_addr_t *)hw_vaddr, + len, + region); + + if (rc < 0) { + CAM_ERR(CAM_MEM, + "Failed to map to smmu, i=%d, fd=%d, dir=%d, mmu_hdl=%d, region=%d, rc=%d", + i, fd, dir, mmu_hdls[i], region, rc); + goto multi_map_fail; + } + } + } + + return rc; +multi_map_fail: + if (flags & CAM_MEM_FLAG_PROTECTED_MODE) + for (--i; i > 0; i--) + cam_smmu_unmap_stage2_iova(mmu_hdls[i], fd); + else + for (--i; i > 0; i--) + cam_smmu_unmap_user_iova(mmu_hdls[i], + fd, + CAM_SMMU_REGION_IO); + return rc; + +} + +int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) +{ + int rc; + int32_t idx; + struct dma_buf *dmabuf = NULL; + int fd = -1; + dma_addr_t hw_vaddr = 0; + size_t len; + uintptr_t kvaddr = 0; + size_t klen; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_MEM, " Invalid argument"); + return -EINVAL; + } + len = cmd->len; + + rc = cam_mem_util_check_alloc_flags(cmd); + if (rc) { + CAM_ERR(CAM_MEM, "Invalid flags: flags = 0x%X, rc=%d", + cmd->flags, rc); + return rc; + } + + rc = cam_mem_util_ion_alloc(cmd, + &dmabuf, + &fd); + if (rc) { + CAM_ERR(CAM_MEM, + "Ion Alloc failed, len=%llu, align=%llu, flags=0x%x, num_hdl=%d", + cmd->len, cmd->align, cmd->flags, cmd->num_hdl); + return rc; + } + + idx = cam_mem_get_slot(); + if (idx < 0) { + CAM_ERR(CAM_MEM, "Failed in getting mem slot, idx=%d", idx); + rc = -ENOMEM; + goto slot_fail; + } + + if ((cmd->flags & CAM_MEM_FLAG_HW_READ_WRITE) || + (cmd->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) || + (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE)) { + + enum cam_smmu_region_id region; + + if (cmd->flags & CAM_MEM_FLAG_HW_READ_WRITE) + region = CAM_SMMU_REGION_IO; + + + if (cmd->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) + region = CAM_SMMU_REGION_SHARED; + + if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) + region = CAM_SMMU_REGION_SECHEAP; + + rc = cam_mem_util_map_hw_va(cmd->flags, + cmd->mmu_hdls, + cmd->num_hdl, + fd, + &hw_vaddr, + &len, + region); + + if (rc) { + CAM_ERR(CAM_MEM, + "Failed in map_hw_va, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", + cmd->flags, fd, region, cmd->num_hdl, rc); + goto map_hw_fail; + } + } + + mutex_lock(&tbl.bufq[idx].q_lock); + tbl.bufq[idx].fd = fd; + tbl.bufq[idx].dma_buf = NULL; + tbl.bufq[idx].flags = cmd->flags; + tbl.bufq[idx].buf_handle = GET_MEM_HANDLE(idx, fd); + if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) + CAM_MEM_MGR_SET_SECURE_HDL(tbl.bufq[idx].buf_handle, true); + + if (cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) { + rc = cam_mem_util_map_cpu_va(dmabuf, &kvaddr, &klen); + if (rc) { + CAM_ERR(CAM_MEM, "dmabuf: %pK mapping failed: %d", + dmabuf, rc); + goto map_kernel_fail; + } + } + + tbl.bufq[idx].kmdvaddr = kvaddr; + tbl.bufq[idx].vaddr = hw_vaddr; + tbl.bufq[idx].dma_buf = dmabuf; + tbl.bufq[idx].len = cmd->len; + tbl.bufq[idx].num_hdl = cmd->num_hdl; + memcpy(tbl.bufq[idx].hdls, cmd->mmu_hdls, + sizeof(int32_t) * cmd->num_hdl); + tbl.bufq[idx].is_imported = false; + mutex_unlock(&tbl.bufq[idx].q_lock); + + cmd->out.buf_handle = tbl.bufq[idx].buf_handle; + cmd->out.fd = tbl.bufq[idx].fd; + cmd->out.vaddr = 0; + + CAM_DBG(CAM_MEM, + "fd=%d, flags=0x%x, num_hdl=%d, idx=%d, buf handle=%x, len=%zu", + cmd->out.fd, cmd->flags, cmd->num_hdl, idx, cmd->out.buf_handle, + tbl.bufq[idx].len); + + return rc; + +map_kernel_fail: + mutex_unlock(&tbl.bufq[idx].q_lock); +map_hw_fail: + cam_mem_put_slot(idx); +slot_fail: + dma_buf_put(dmabuf); + return rc; +} + +int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) +{ + int32_t idx; + int rc; + struct dma_buf *dmabuf; + dma_addr_t hw_vaddr = 0; + size_t len = 0; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!cmd || (cmd->fd < 0)) { + CAM_ERR(CAM_MEM, "Invalid argument"); + return -EINVAL; + } + + if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) { + CAM_ERR(CAM_MEM, "Num of mmu hdl %d exceeded maximum(%d)", + cmd->num_hdl, CAM_MEM_MMU_MAX_HANDLE); + return -EINVAL; + } + + rc = cam_mem_util_check_map_flags(cmd); + if (rc) { + CAM_ERR(CAM_MEM, "Invalid flags: flags = %X", cmd->flags); + return rc; + } + + dmabuf = dma_buf_get(cmd->fd); + if (IS_ERR_OR_NULL((void *)(dmabuf))) { + CAM_ERR(CAM_MEM, "Failed to import dma_buf fd"); + return -EINVAL; + } + + if ((cmd->flags & CAM_MEM_FLAG_HW_READ_WRITE) || + (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE)) { + rc = cam_mem_util_map_hw_va(cmd->flags, + cmd->mmu_hdls, + cmd->num_hdl, + cmd->fd, + &hw_vaddr, + &len, + CAM_SMMU_REGION_IO); + if (rc) { + CAM_ERR(CAM_MEM, + "Failed in map_hw_va, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", + cmd->flags, cmd->fd, CAM_SMMU_REGION_IO, + cmd->num_hdl, rc); + goto map_fail; + } + } + + idx = cam_mem_get_slot(); + if (idx < 0) { + rc = -ENOMEM; + goto map_fail; + } + + mutex_lock(&tbl.bufq[idx].q_lock); + tbl.bufq[idx].fd = cmd->fd; + tbl.bufq[idx].dma_buf = NULL; + tbl.bufq[idx].flags = cmd->flags; + tbl.bufq[idx].buf_handle = GET_MEM_HANDLE(idx, cmd->fd); + if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) + CAM_MEM_MGR_SET_SECURE_HDL(tbl.bufq[idx].buf_handle, true); + tbl.bufq[idx].kmdvaddr = 0; + + if (cmd->num_hdl > 0) + tbl.bufq[idx].vaddr = hw_vaddr; + else + tbl.bufq[idx].vaddr = 0; + + tbl.bufq[idx].dma_buf = dmabuf; + tbl.bufq[idx].len = len; + tbl.bufq[idx].num_hdl = cmd->num_hdl; + memcpy(tbl.bufq[idx].hdls, cmd->mmu_hdls, + sizeof(int32_t) * cmd->num_hdl); + tbl.bufq[idx].is_imported = true; + mutex_unlock(&tbl.bufq[idx].q_lock); + + cmd->out.buf_handle = tbl.bufq[idx].buf_handle; + cmd->out.vaddr = 0; + + CAM_DBG(CAM_MEM, + "fd=%d, flags=0x%x, num_hdl=%d, idx=%d, buf handle=%x, len=%zu", + cmd->fd, cmd->flags, cmd->num_hdl, idx, cmd->out.buf_handle, + tbl.bufq[idx].len); + + return rc; + +map_fail: + dma_buf_put(dmabuf); + return rc; +} + +static int cam_mem_util_unmap_hw_va(int32_t idx, + enum cam_smmu_region_id region, + enum cam_smmu_mapping_client client) +{ + int i; + uint32_t flags; + int32_t *mmu_hdls; + int num_hdls; + int fd; + int rc = 0; + + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { + CAM_ERR(CAM_MEM, "Incorrect index"); + return -EINVAL; + } + + flags = tbl.bufq[idx].flags; + mmu_hdls = tbl.bufq[idx].hdls; + num_hdls = tbl.bufq[idx].num_hdl; + fd = tbl.bufq[idx].fd; + + CAM_DBG(CAM_MEM, + "unmap_hw_va : idx=%d, fd=%x, flags=0x%x, num_hdls=%d, client=%d", + idx, fd, flags, num_hdls, client); + + if (flags & CAM_MEM_FLAG_PROTECTED_MODE) { + for (i = 0; i < num_hdls; i++) { + rc = cam_smmu_unmap_stage2_iova(mmu_hdls[i], fd); + if (rc < 0) { + CAM_ERR(CAM_MEM, + "Failed in secure unmap, i=%d, fd=%d, mmu_hdl=%d, rc=%d", + i, fd, mmu_hdls[i], rc); + goto unmap_end; + } + } + } else { + for (i = 0; i < num_hdls; i++) { + if (client == CAM_SMMU_MAPPING_USER) { + rc = cam_smmu_unmap_user_iova(mmu_hdls[i], + fd, region); + } else if (client == CAM_SMMU_MAPPING_KERNEL) { + rc = cam_smmu_unmap_kernel_iova(mmu_hdls[i], + tbl.bufq[idx].dma_buf, region); + } else { + CAM_ERR(CAM_MEM, + "invalid caller for unmapping : %d", + client); + rc = -EINVAL; + } + if (rc < 0) { + CAM_ERR(CAM_MEM, + "Failed in unmap, i=%d, fd=%d, mmu_hdl=%d, region=%d, rc=%d", + i, fd, mmu_hdls[i], region, rc); + goto unmap_end; + } + } + } + + return rc; + +unmap_end: + CAM_ERR(CAM_MEM, "unmapping failed"); + return rc; +} + +static void cam_mem_mgr_unmap_active_buf(int idx) +{ + enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED; + + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) + region = CAM_SMMU_REGION_SHARED; + else if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE) + region = CAM_SMMU_REGION_IO; + + cam_mem_util_unmap_hw_va(idx, region, CAM_SMMU_MAPPING_USER); +} + +static int cam_mem_mgr_cleanup_table(void) +{ + int i; + + mutex_lock(&tbl.m_lock); + for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) { + if (!tbl.bufq[i].active) { + CAM_DBG(CAM_MEM, + "Buffer inactive at idx=%d, continuing", i); + continue; + } else { + CAM_DBG(CAM_MEM, + "Active buffer at idx=%d, possible leak needs unmapping", + i); + cam_mem_mgr_unmap_active_buf(i); + } + + mutex_lock(&tbl.bufq[i].q_lock); + if (tbl.bufq[i].dma_buf) { + dma_buf_put(tbl.bufq[i].dma_buf); + tbl.bufq[i].dma_buf = NULL; + } + tbl.bufq[i].fd = -1; + tbl.bufq[i].flags = 0; + tbl.bufq[i].buf_handle = -1; + tbl.bufq[i].vaddr = 0; + tbl.bufq[i].len = 0; + memset(tbl.bufq[i].hdls, 0, + sizeof(int32_t) * tbl.bufq[i].num_hdl); + tbl.bufq[i].num_hdl = 0; + tbl.bufq[i].dma_buf = NULL; + tbl.bufq[i].active = false; + mutex_unlock(&tbl.bufq[i].q_lock); + mutex_destroy(&tbl.bufq[i].q_lock); + } + + bitmap_zero(tbl.bitmap, tbl.bits); + /* We need to reserve slot 0 because 0 is invalid */ + set_bit(0, tbl.bitmap); + mutex_unlock(&tbl.m_lock); + + return 0; +} + +void cam_mem_mgr_deinit(void) +{ + atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED); + cam_mem_mgr_cleanup_table(); + mutex_lock(&tbl.m_lock); + bitmap_zero(tbl.bitmap, tbl.bits); + kfree(tbl.bitmap); + tbl.bitmap = NULL; + mutex_unlock(&tbl.m_lock); + mutex_destroy(&tbl.m_lock); +} + +static int cam_mem_util_unmap(int32_t idx, + enum cam_smmu_mapping_client client) +{ + int rc = 0; + enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED; + + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { + CAM_ERR(CAM_MEM, "Incorrect index"); + return -EINVAL; + } + + CAM_DBG(CAM_MEM, "Flags = %X idx %d", tbl.bufq[idx].flags, idx); + + mutex_lock(&tbl.m_lock); + if ((!tbl.bufq[idx].active) && + (tbl.bufq[idx].vaddr) == 0) { + CAM_WARN(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); + mutex_unlock(&tbl.m_lock); + return 0; + } + + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS) { + if (tbl.bufq[idx].dma_buf && tbl.bufq[idx].kmdvaddr) { + rc = cam_mem_util_unmap_cpu_va(tbl.bufq[idx].dma_buf, + tbl.bufq[idx].kmdvaddr); + if (rc) + CAM_ERR(CAM_MEM, + "Failed, dmabuf=%pK, kmdvaddr=%pK", + tbl.bufq[idx].dma_buf, + (void *) tbl.bufq[idx].kmdvaddr); + } + } + + /* SHARED flag gets precedence, all other flags after it */ + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) { + region = CAM_SMMU_REGION_SHARED; + } else { + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE) + region = CAM_SMMU_REGION_IO; + } + + if ((tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE) || + (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) || + (tbl.bufq[idx].flags & CAM_MEM_FLAG_PROTECTED_MODE)) { + if (cam_mem_util_unmap_hw_va(idx, region, client)) + CAM_ERR(CAM_MEM, "Failed, dmabuf=%pK", + tbl.bufq[idx].dma_buf); + if (client == CAM_SMMU_MAPPING_KERNEL) + tbl.bufq[idx].dma_buf = NULL; + } + + mutex_lock(&tbl.bufq[idx].q_lock); + tbl.bufq[idx].flags = 0; + tbl.bufq[idx].buf_handle = -1; + tbl.bufq[idx].vaddr = 0; + memset(tbl.bufq[idx].hdls, 0, + sizeof(int32_t) * CAM_MEM_MMU_MAX_HANDLE); + + CAM_DBG(CAM_MEM, + "Ion buf at idx = %d freeing fd = %d, imported %d, dma_buf %pK", + idx, tbl.bufq[idx].fd, + tbl.bufq[idx].is_imported, + tbl.bufq[idx].dma_buf); + + if (tbl.bufq[idx].dma_buf) + dma_buf_put(tbl.bufq[idx].dma_buf); + + tbl.bufq[idx].fd = -1; + tbl.bufq[idx].dma_buf = NULL; + tbl.bufq[idx].is_imported = false; + tbl.bufq[idx].len = 0; + tbl.bufq[idx].num_hdl = 0; + tbl.bufq[idx].active = false; + mutex_unlock(&tbl.bufq[idx].q_lock); + mutex_destroy(&tbl.bufq[idx].q_lock); + clear_bit(idx, tbl.bitmap); + mutex_unlock(&tbl.m_lock); + + return rc; +} + +int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd) +{ + int idx; + int rc; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_MEM, "Invalid argument"); + return -EINVAL; + } + + idx = CAM_MEM_MGR_GET_HDL_IDX(cmd->buf_handle); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { + CAM_ERR(CAM_MEM, "Incorrect index %d extracted from mem handle", + idx); + return -EINVAL; + } + + if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Released buffer state should be active"); + return -EINVAL; + } + + if (tbl.bufq[idx].buf_handle != cmd->buf_handle) { + CAM_ERR(CAM_MEM, + "Released buf handle %d not matching within table %d, idx=%d", + cmd->buf_handle, tbl.bufq[idx].buf_handle, idx); + return -EINVAL; + } + + CAM_DBG(CAM_MEM, "Releasing hdl = %x, idx = %d", cmd->buf_handle, idx); + rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_USER); + + return rc; +} + +int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, + struct cam_mem_mgr_memory_desc *out) +{ + struct dma_buf *buf = NULL; + int ion_fd = -1; + int rc = 0; + uint32_t heap_id; + int32_t ion_flag = 0; + uintptr_t kvaddr; + dma_addr_t iova = 0; + size_t request_len = 0; + uint32_t mem_handle; + int32_t idx; + int32_t smmu_hdl = 0; + int32_t num_hdl = 0; + + enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!inp || !out) { + CAM_ERR(CAM_MEM, "Invalid params"); + return -EINVAL; + } + + if (!(inp->flags & CAM_MEM_FLAG_HW_READ_WRITE || + inp->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS || + inp->flags & CAM_MEM_FLAG_CACHE)) { + CAM_ERR(CAM_MEM, "Invalid flags for request mem"); + return -EINVAL; + } + + if (inp->flags & CAM_MEM_FLAG_CACHE) + ion_flag |= ION_FLAG_CACHED; + else + ion_flag &= ~ION_FLAG_CACHED; + + heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) | + ION_HEAP(ION_CAMERA_HEAP_ID); + + rc = cam_mem_util_get_dma_buf(inp->size, + heap_id, + ion_flag, + &buf); + + if (rc) { + CAM_ERR(CAM_MEM, "ION alloc failed for shared buffer"); + goto ion_fail; + } else { + CAM_DBG(CAM_MEM, "Got dma_buf = %pK", buf); + } + + /* + * we are mapping kva always here, + * update flags so that we do unmap properly + */ + inp->flags |= CAM_MEM_FLAG_KMD_ACCESS; + rc = cam_mem_util_map_cpu_va(buf, &kvaddr, &request_len); + if (rc) { + CAM_ERR(CAM_MEM, "Failed to get kernel vaddr"); + goto map_fail; + } + + if (!inp->smmu_hdl) { + CAM_ERR(CAM_MEM, "Invalid SMMU handle"); + rc = -EINVAL; + goto smmu_fail; + } + + /* SHARED flag gets precedence, all other flags after it */ + if (inp->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) { + region = CAM_SMMU_REGION_SHARED; + } else { + if (inp->flags & CAM_MEM_FLAG_HW_READ_WRITE) + region = CAM_SMMU_REGION_IO; + } + + rc = cam_smmu_map_kernel_iova(inp->smmu_hdl, + buf, + CAM_SMMU_MAP_RW, + &iova, + &request_len, + region); + + if (rc < 0) { + CAM_ERR(CAM_MEM, "SMMU mapping failed"); + goto smmu_fail; + } + + smmu_hdl = inp->smmu_hdl; + num_hdl = 1; + + idx = cam_mem_get_slot(); + if (idx < 0) { + rc = -ENOMEM; + goto slot_fail; + } + + mutex_lock(&tbl.bufq[idx].q_lock); + mem_handle = GET_MEM_HANDLE(idx, ion_fd); + tbl.bufq[idx].dma_buf = buf; + tbl.bufq[idx].fd = -1; + tbl.bufq[idx].flags = inp->flags; + tbl.bufq[idx].buf_handle = mem_handle; + tbl.bufq[idx].kmdvaddr = kvaddr; + + tbl.bufq[idx].vaddr = iova; + + tbl.bufq[idx].len = inp->size; + tbl.bufq[idx].num_hdl = num_hdl; + memcpy(tbl.bufq[idx].hdls, &smmu_hdl, + sizeof(int32_t)); + tbl.bufq[idx].is_imported = false; + mutex_unlock(&tbl.bufq[idx].q_lock); + + out->kva = kvaddr; + out->iova = (uint32_t)iova; + out->smmu_hdl = smmu_hdl; + out->mem_handle = mem_handle; + out->len = inp->size; + out->region = region; + + return rc; +slot_fail: + cam_smmu_unmap_kernel_iova(inp->smmu_hdl, + buf, region); +smmu_fail: + cam_mem_util_unmap_cpu_va(buf, kvaddr); +map_fail: + dma_buf_put(buf); +ion_fail: + return rc; +} +EXPORT_SYMBOL(cam_mem_mgr_request_mem); + +int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp) +{ + int32_t idx; + int rc; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!inp) { + CAM_ERR(CAM_MEM, "Invalid argument"); + return -EINVAL; + } + + idx = CAM_MEM_MGR_GET_HDL_IDX(inp->mem_handle); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { + CAM_ERR(CAM_MEM, "Incorrect index extracted from mem handle"); + return -EINVAL; + } + + if (!tbl.bufq[idx].active) { + if (tbl.bufq[idx].vaddr == 0) { + CAM_ERR(CAM_MEM, "buffer is released already"); + return 0; + } + CAM_ERR(CAM_MEM, "Released buffer state should be active"); + return -EINVAL; + } + + if (tbl.bufq[idx].buf_handle != inp->mem_handle) { + CAM_ERR(CAM_MEM, + "Released buf handle not matching within table"); + return -EINVAL; + } + + CAM_DBG(CAM_MEM, "Releasing hdl = %X", inp->mem_handle); + rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_KERNEL); + + return rc; +} +EXPORT_SYMBOL(cam_mem_mgr_release_mem); + +int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, + enum cam_smmu_region_id region, + struct cam_mem_mgr_memory_desc *out) +{ + struct dma_buf *buf = NULL; + int rc = 0; + int ion_fd = -1; + uint32_t heap_id; + dma_addr_t iova = 0; + size_t request_len = 0; + uint32_t mem_handle; + int32_t idx; + int32_t smmu_hdl = 0; + int32_t num_hdl = 0; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!inp || !out) { + CAM_ERR(CAM_MEM, "Invalid param(s)"); + return -EINVAL; + } + + if (!inp->smmu_hdl) { + CAM_ERR(CAM_MEM, "Invalid SMMU handle"); + return -EINVAL; + } + + if (region != CAM_SMMU_REGION_SECHEAP) { + CAM_ERR(CAM_MEM, "Only secondary heap supported"); + return -EINVAL; + } + + heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) | + ION_HEAP(ION_CAMERA_HEAP_ID); + rc = cam_mem_util_get_dma_buf(inp->size, + heap_id, + 0, + &buf); + + if (rc) { + CAM_ERR(CAM_MEM, "ION alloc failed for sec heap buffer"); + goto ion_fail; + } else { + CAM_DBG(CAM_MEM, "Got dma_buf = %pK", buf); + } + + rc = cam_smmu_reserve_sec_heap(inp->smmu_hdl, + buf, + &iova, + &request_len); + + if (rc) { + CAM_ERR(CAM_MEM, "Reserving secondary heap failed"); + goto smmu_fail; + } + + smmu_hdl = inp->smmu_hdl; + num_hdl = 1; + + idx = cam_mem_get_slot(); + if (idx < 0) { + rc = -ENOMEM; + goto slot_fail; + } + + mutex_lock(&tbl.bufq[idx].q_lock); + mem_handle = GET_MEM_HANDLE(idx, ion_fd); + tbl.bufq[idx].fd = -1; + tbl.bufq[idx].dma_buf = buf; + tbl.bufq[idx].flags = inp->flags; + tbl.bufq[idx].buf_handle = mem_handle; + tbl.bufq[idx].kmdvaddr = 0; + + tbl.bufq[idx].vaddr = iova; + + tbl.bufq[idx].len = request_len; + tbl.bufq[idx].num_hdl = num_hdl; + memcpy(tbl.bufq[idx].hdls, &smmu_hdl, + sizeof(int32_t)); + tbl.bufq[idx].is_imported = false; + mutex_unlock(&tbl.bufq[idx].q_lock); + + out->kva = 0; + out->iova = (uint32_t)iova; + out->smmu_hdl = smmu_hdl; + out->mem_handle = mem_handle; + out->len = request_len; + out->region = region; + + return rc; + +slot_fail: + cam_smmu_release_sec_heap(smmu_hdl); +smmu_fail: + dma_buf_put(buf); +ion_fail: + return rc; +} +EXPORT_SYMBOL(cam_mem_mgr_reserve_memory_region); + +int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp) +{ + int32_t idx; + int rc; + int32_t smmu_hdl; + + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + + if (!inp) { + CAM_ERR(CAM_MEM, "Invalid argument"); + return -EINVAL; + } + + if (inp->region != CAM_SMMU_REGION_SECHEAP) { + CAM_ERR(CAM_MEM, "Only secondary heap supported"); + return -EINVAL; + } + + idx = CAM_MEM_MGR_GET_HDL_IDX(inp->mem_handle); + if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { + CAM_ERR(CAM_MEM, "Incorrect index extracted from mem handle"); + return -EINVAL; + } + + if (!tbl.bufq[idx].active) { + if (tbl.bufq[idx].vaddr == 0) { + CAM_ERR(CAM_MEM, "buffer is released already"); + return 0; + } + CAM_ERR(CAM_MEM, "Released buffer state should be active"); + return -EINVAL; + } + + if (tbl.bufq[idx].buf_handle != inp->mem_handle) { + CAM_ERR(CAM_MEM, + "Released buf handle not matching within table"); + return -EINVAL; + } + + if (tbl.bufq[idx].num_hdl != 1) { + CAM_ERR(CAM_MEM, + "Sec heap region should have only one smmu hdl"); + return -ENODEV; + } + + memcpy(&smmu_hdl, tbl.bufq[idx].hdls, + sizeof(int32_t)); + if (inp->smmu_hdl != smmu_hdl) { + CAM_ERR(CAM_MEM, + "Passed SMMU handle doesn't match with internal hdl"); + return -ENODEV; + } + + rc = cam_smmu_release_sec_heap(inp->smmu_hdl); + if (rc) { + CAM_ERR(CAM_MEM, + "Sec heap region release failed"); + return -ENODEV; + } + + CAM_DBG(CAM_MEM, "Releasing hdl = %X", inp->mem_handle); + rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_KERNEL); + if (rc) + CAM_ERR(CAM_MEM, "unmapping secondary heap failed"); + + return rc; +} +EXPORT_SYMBOL(cam_mem_mgr_free_memory_region); diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h new file mode 100644 index 000000000000..6ce30db66fe3 --- /dev/null +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_MEM_MGR_H_ +#define _CAM_MEM_MGR_H_ + +#include +#include +#include +#include "cam_mem_mgr_api.h" + +#define CAM_MEM_BUFQ_MAX 1024 + +/* Enum for possible mem mgr states */ +enum cam_mem_mgr_state { + CAM_MEM_MGR_UNINITIALIZED, + CAM_MEM_MGR_INITIALIZED, +}; + +/*Enum for possible SMMU operations */ +enum cam_smmu_mapping_client { + CAM_SMMU_MAPPING_USER, + CAM_SMMU_MAPPING_KERNEL, +}; + +/** + * struct cam_mem_buf_queue + * + * @dma_buf: pointer to the allocated dma_buf in the table + * @q_lock: mutex lock for buffer + * @hdls: list of mapped handles + * @num_hdl: number of handles + * @fd: file descriptor of buffer + * @buf_handle: unique handle for buffer + * @align: alignment for allocation + * @len: size of buffer + * @flags: attributes of buffer + * @vaddr: IOVA of buffer + * @kmdvaddr: Kernel virtual address + * @active: state of the buffer + * @is_imported: Flag indicating if buffer is imported from an FD in user space + */ +struct cam_mem_buf_queue { + struct dma_buf *dma_buf; + struct mutex q_lock; + int32_t hdls[CAM_MEM_MMU_MAX_HANDLE]; + int32_t num_hdl; + int32_t fd; + int32_t buf_handle; + int32_t align; + size_t len; + uint32_t flags; + uint64_t vaddr; + uintptr_t kmdvaddr; + bool active; + bool is_imported; +}; + +/** + * struct cam_mem_table + * + * @m_lock: mutex lock for table + * @bitmap: bitmap of the mem mgr utility + * @bits: max bits of the utility + * @bufq: array of buffers + */ +struct cam_mem_table { + struct mutex m_lock; + void *bitmap; + size_t bits; + struct cam_mem_buf_queue bufq[CAM_MEM_BUFQ_MAX]; +}; + +/** + * @brief: Allocates and maps buffer + * + * @cmd: Allocation information + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd); + +/** + * @brief: Releases a buffer reference + * + * @cmd: Buffer release information + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd); + +/** + * @brief Maps a buffer + * + * @cmd: Buffer mapping information + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd); + +/** + * @brief: Perform cache ops on the buffer + * + * @cmd: Cache ops information + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd); + +/** + * @brief: Initializes the memory manager + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_init(void); + +/** + * @brief: Tears down the memory manager + * + * @return None + */ +void cam_mem_mgr_deinit(void); + +#endif /* _CAM_MEM_MGR_H_ */ diff --git a/drivers/cam_req_mgr/cam_mem_mgr_api.h b/drivers/cam_req_mgr/cam_mem_mgr_api.h new file mode 100644 index 000000000000..6141e7cc136b --- /dev/null +++ b/drivers/cam_req_mgr/cam_mem_mgr_api.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_MEM_MGR_API_H_ +#define _CAM_MEM_MGR_API_H_ + +#include +#include "../cam_smmu/cam_smmu_api.h" + +/** + * struct cam_mem_mgr_request_desc + * + * @size : Size of memory requested for allocation + * @align : Alignment of requested memory + * @smmu_hdl: SMMU handle to identify context bank where memory will be mapped + * @flags : Flags to indicate cached/uncached property + * @region : Region where memory should be allocated + */ +struct cam_mem_mgr_request_desc { + uint64_t size; + uint64_t align; + int32_t smmu_hdl; + uint32_t flags; +}; + +/** + * struct cam_mem_mgr_memory_desc + * + * @kva : Kernel virtual address of allocated memory + * @iova : IOVA of allocated memory + * @smmu_hdl : SMMU handle of allocated memory + * @mem_handle : Mem handle identifying allocated memory + * @len : Length of allocated memory + * @region : Region to which allocated memory belongs + */ +struct cam_mem_mgr_memory_desc { + uintptr_t kva; + uint32_t iova; + int32_t smmu_hdl; + uint32_t mem_handle; + uint64_t len; + enum cam_smmu_region_id region; +}; + +/** + * @brief: Requests a memory buffer + * + * @inp: Information specifying requested buffer properties + * @out: Information about allocated buffer + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, + struct cam_mem_mgr_memory_desc *out); + +/** + * @brief: Releases a memory buffer + * + * @inp: Information specifying buffer to be released + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp); + +/** + * @brief: Returns IOVA information about buffer + * + * @buf_handle: Handle of the buffer + * @mmu_handle: SMMU handle where buffer is mapped + * @iova_ptr : Pointer to mmu's iova + * @len_ptr : Length of the buffer + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, + uint64_t *iova_ptr, size_t *len_ptr); + +/** + * @brief: This indicates begin of CPU access. + * Also returns CPU address information about DMA buffer + * + * @buf_handle: Handle for the buffer + * @vaddr_ptr : pointer to kernel virtual address + * @len_ptr : Length of the buffer + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, + size_t *len); + +static inline bool cam_mem_is_secure_buf(int32_t buf_handle) +{ + return CAM_MEM_MGR_IS_SECURE_HDL(buf_handle); +} + +/** + * @brief: Reserves a memory region + * + * @inp: Information specifying requested region properties + * @region : Region which is to be reserved + * @out : Information about reserved region + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, + enum cam_smmu_region_id region, + struct cam_mem_mgr_memory_desc *out); + +/** + * @brief: Frees a memory region + * + * @inp : Information about region which is to be freed + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp); + +#endif /* _CAM_MEM_MGR_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c new file mode 100644 index 000000000000..9f11077f05c4 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -0,0 +1,3242 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include "cam_req_mgr_interface.h" +#include "cam_req_mgr_util.h" +#include "cam_req_mgr_core.h" +#include "cam_req_mgr_workq.h" +#include "cam_req_mgr_debug.h" +#include "cam_trace.h" +#include "cam_debug_util.h" +#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; + link->retry_cnt = 0; +} + +void cam_req_mgr_handle_core_shutdown(void) +{ + struct cam_req_mgr_core_session *session; + struct cam_req_mgr_core_session *tsession; + struct cam_req_mgr_session_info ses_info; + + if (!list_empty(&g_crm_core_dev->session_head)) { + list_for_each_entry_safe(session, tsession, + &g_crm_core_dev->session_head, entry) { + ses_info.session_hdl = + session->session_hdl; + cam_req_mgr_destroy_session(&ses_info); + } + } +} + +static int __cam_req_mgr_setup_payload(struct cam_req_mgr_core_workq *workq) +{ + int32_t i = 0; + int rc = 0; + struct crm_task_payload *task_data = NULL; + + task_data = kcalloc( + workq->task.num_task, sizeof(*task_data), + GFP_KERNEL); + if (!task_data) { + rc = -ENOMEM; + } else { + for (i = 0; i < workq->task.num_task; i++) + workq->task.pool[i].payload = &task_data[i]; + } + + return rc; +} + +/** + * __cam_req_mgr_find_pd_tbl() + * + * @brief : Find pipeline delay based table pointer which matches delay + * @tbl : Pointer to list of request table + * @delay : Pipeline delay value to be searched for comparison + * + * @return : pointer to request table for matching pipeline delay table. + * + */ +static struct cam_req_mgr_req_tbl *__cam_req_mgr_find_pd_tbl( + struct cam_req_mgr_req_tbl *tbl, int32_t delay) +{ + if (!tbl) + return NULL; + + do { + if (delay != tbl->pd) + tbl = tbl->next; + else + return tbl; + } while (tbl != NULL); + + return NULL; +} + +/** + * __cam_req_mgr_inc_idx() + * + * @brief : Increment val passed by step size and rollover after max_val + * @val : value to be incremented + * @step : amount/step by which val is incremented + * @max_val : max val after which idx will roll over + * + */ +static void __cam_req_mgr_inc_idx(int32_t *val, int32_t step, int32_t max_val) +{ + *val = (*val + step) % max_val; +} + +/** + * __cam_req_mgr_dec_idx() + * + * @brief : Decrement val passed by step size and rollover after max_val + * @val : value to be decremented + * @step : amount/step by which val is decremented + * @max_val : after zero value will roll over to max val + * + */ +static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val) +{ + *val = *val - step; + if (*val < 0) + *val = max_val + (*val); +} + +/** + * __cam_req_mgr_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_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--; + 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 rc; +} + +/** + * __cam_req_mgr_notify_error_on_link() + * + * @brief : Notify userspace on exceeding max retry + * attempts to apply same req + * @link : link on which the req could not be applied + * + */ +static int __cam_req_mgr_notify_error_on_link( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_connected_device *dev) +{ + struct cam_req_mgr_core_session *session = NULL; + struct cam_req_mgr_message msg; + int rc = 0, pd; + + session = (struct cam_req_mgr_core_session *)link->parent; + + pd = dev->dev_info.p_delay; + if (pd >= CAM_PIPELINE_DELAY_MAX) { + CAM_ERR(CAM_CRM, "pd : %d is more than expected", pd); + return -EINVAL; + } + + CAM_ERR(CAM_CRM, + "Notifying userspace to trigger recovery on link 0x%x for session %d", + link->link_hdl, session->session_hdl); + + memset(&msg, 0, sizeof(msg)); + + msg.session_hdl = session->session_hdl; + msg.u.err_msg.error_type = CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + msg.u.err_msg.request_id = + link->req.apply_data[pd].req_id; + msg.u.err_msg.link_hdl = link->link_hdl; + + CAM_DBG(CAM_CRM, "Failed for device: %s while applying request: %lld", + dev->dev_info.name, link->req.apply_data[pd].req_id); + + rc = cam_req_mgr_notify_message(&msg, + V4L_EVENT_CAM_REQ_MGR_ERROR, + V4L_EVENT_CAM_REQ_MGR_EVENT); + + if (rc) + CAM_ERR(CAM_CRM, + "Error in notifying recovery for session %d link 0x%x rc %d", + session->session_hdl, link->link_hdl, rc); + + return rc; +} + +/** + * __cam_req_mgr_traverse() + * + * @brief : Traverse through pd tables, it will internally cover all linked + * pd tables. Each pd table visited will check if idx passed to its + * in ready state. If ready means all devices linked to the pd table + * have this request id packet ready. Then it calls subsequent pd + * tbl with new idx. New idx value takes into account the delta + * between current pd table and next one. + * @traverse_data: contains all the info to traverse through pd tables + * + * @return: 0 for success, negative for failure + * + */ +static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) +{ + int rc = 0; + int32_t next_idx = traverse_data->idx; + int32_t curr_idx = traverse_data->idx; + struct cam_req_mgr_req_tbl *tbl; + struct cam_req_mgr_apply *apply_data; + struct cam_req_mgr_tbl_slot *slot = NULL; + + if (!traverse_data->tbl || !traverse_data->apply_data) { + CAM_ERR(CAM_CRM, "NULL pointer %pK %pK", + traverse_data->tbl, traverse_data->apply_data); + traverse_data->result = 0; + return -EINVAL; + } + + tbl = traverse_data->tbl; + apply_data = traverse_data->apply_data; + slot = &tbl->slot[curr_idx]; + CAM_DBG(CAM_CRM, + "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", + tbl->pd, curr_idx, tbl->slot[curr_idx].state, + tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, + traverse_data->in_q->slot[curr_idx].skip_idx); + + /* 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 || + tbl->skip_traverse > 0) { + if (tbl->next) { + __cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta, + tbl->num_slots); + traverse_data->idx = next_idx; + traverse_data->tbl = tbl->next; + rc = __cam_req_mgr_traverse(traverse_data); + } + if (rc >= 0) { + SET_SUCCESS_BIT(traverse_data->result, tbl->pd); + + if (traverse_data->validate_only == false) { + apply_data[tbl->pd].pd = tbl->pd; + apply_data[tbl->pd].req_id = + CRM_GET_REQ_ID( + traverse_data->in_q, curr_idx); + apply_data[tbl->pd].idx = curr_idx; + + CAM_DBG(CAM_CRM, "req_id: %lld with pd of %d", + apply_data[tbl->pd].req_id, + apply_data[tbl->pd].pd); + /* + * If traverse is successful decrement + * traverse skip + */ + if (tbl->skip_traverse > 0) { + apply_data[tbl->pd].req_id = -1; + tbl->skip_traverse--; + } + } + } else { + /* linked pd table is not ready for this traverse yet */ + return rc; + } + } else { + /* This pd table is not ready to proceed with asked idx */ + CAM_INFO(CAM_CRM, + "Skip Frame: req: %lld not ready pd: %d open_req count: %d", + CRM_GET_REQ_ID(traverse_data->in_q, curr_idx), + tbl->pd, + traverse_data->open_req_cnt); + SET_FAILURE_BIT(traverse_data->result, tbl->pd); + return -EAGAIN; + } + return 0; +} + +/** + * __cam_req_mgr_in_q_skip_idx() + * + * @brief : Decrement val passed by step size and rollover after max_val + * @in_q : input queue pointer + * @idx : Sets skip_idx bit of the particular slot to true so when traverse + * happens for this idx, no req will be submitted for devices + * handling this idx. + * + */ +static void __cam_req_mgr_in_q_skip_idx(struct cam_req_mgr_req_queue *in_q, + int32_t idx) +{ + in_q->slot[idx].req_id = -1; + in_q->slot[idx].skip_idx = 1; + in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; + CAM_DBG(CAM_CRM, "SET IDX SKIP on slot= %d", idx); +} + +/** + * __cam_req_mgr_tbl_set_id() + * + * @brief : Set unique id to table + * @tbl : pipeline based table which requires new id + * @req : pointer to request data wihch contains num_tables counter + * + */ +static void __cam_req_mgr_tbl_set_id(struct cam_req_mgr_req_tbl *tbl, + struct cam_req_mgr_req_data *req) +{ + if (!tbl) + return; + do { + tbl->id = req->num_tbl++; + CAM_DBG(CAM_CRM, "%d: pd %d skip_traverse %d delta %d", + tbl->id, tbl->pd, tbl->skip_traverse, + tbl->pd_delta); + tbl = tbl->next; + } while (tbl != NULL); +} + +/** + * __cam_req_mgr_tbl_set_all_skip_cnt() + * + * @brief : Each pd table sets skip value based on delta between itself and + * max pd value. During initial streamon or bubble case this is + * used. That way each pd table skips required num of traverse and + * align themselve with req mgr connected devs. + * @l_tbl : iterates through list of pd tables and sets skip traverse + * + */ +static void __cam_req_mgr_tbl_set_all_skip_cnt( + struct cam_req_mgr_req_tbl **l_tbl) +{ + struct cam_req_mgr_req_tbl *tbl = *l_tbl; + int32_t max_pd; + + if (!tbl) + return; + + max_pd = tbl->pd; + do { + tbl->skip_traverse = max_pd - tbl->pd; + CAM_DBG(CAM_CRM, "%d: pd %d skip_traverse %d delta %d", + tbl->id, tbl->pd, tbl->skip_traverse, + tbl->pd_delta); + tbl = tbl->next; + } while (tbl != NULL); +} + +/** + * __cam_req_mgr_reset_req_slot() + * + * @brief : reset specified idx/slot in input queue as well as all pd tables + * @link : link pointer + * @idx : slot index which will be reset + * + */ +static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, + int32_t idx) +{ + struct cam_req_mgr_slot *slot; + struct cam_req_mgr_req_tbl *tbl = link->req.l_tbl; + struct cam_req_mgr_req_queue *in_q = link->req.in_q; + + slot = &in_q->slot[idx]; + CAM_DBG(CAM_CRM, "RESET: idx: %d: slot->status %d", idx, slot->status); + + /* Check if CSL has already pushed new request*/ + if (slot->status == CRM_SLOT_STATUS_REQ_ADDED) + return; + + /* Reset input queue slot */ + slot->req_id = -1; + slot->skip_idx = 0; + slot->recover = 0; + slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + slot->status = CRM_SLOT_STATUS_NO_REQ; + + /* Reset all pd table slot */ + while (tbl != NULL) { + CAM_DBG(CAM_CRM, "pd: %d: idx %d state %d", + tbl->pd, idx, tbl->slot[idx].state); + tbl->slot[idx].req_ready_map = 0; + tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; + tbl = tbl->next; + } +} + +/** + * __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 + * request, req mgr still needs to submit pending request ids to + * 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 int __cam_req_mgr_check_next_req_slot( + struct cam_req_mgr_core_link *link) +{ + 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); + slot = &in_q->slot[idx]; + + CAM_DBG(CAM_CRM, "idx: %d: slot->status %d", idx, slot->status); + + /* 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; +} + +/** + * __cam_req_mgr_send_req() + * + * @brief : send request id to be applied to each device connected on link + * @link : pointer to link whose input queue and req tbl are + * traversed through + * @in_q : pointer to input request queue + * + * @return : 0 for success, negative for failure + * + */ +static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, + struct cam_req_mgr_req_queue *in_q, uint32_t trigger, + struct cam_req_mgr_connected_device **failed_dev) +{ + int rc = 0, pd, i, idx; + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_apply_request apply_req; + struct cam_req_mgr_link_evt_data evt_data; + struct cam_req_mgr_tbl_slot *slot = NULL; + + apply_req.link_hdl = link->link_hdl; + apply_req.report_if_bubble = 0; + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + if (!dev) + continue; + pd = dev->dev_info.p_delay; + if (pd >= CAM_PIPELINE_DELAY_MAX) { + CAM_WARN(CAM_CRM, "pd %d greater than max", + pd); + continue; + } + + idx = link->req.apply_data[pd].idx; + slot = &dev->pd_tbl->slot[idx]; + /* + * Just let flash go for this request and other + * device get restricted + */ + + if ((slot->skip_next_frame != true) || + (slot->dev_hdl != dev->dev_hdl)) + continue; + + if (!(dev->dev_info.trigger & trigger)) + continue; + + apply_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = + link->req.apply_data[pd].req_id; + apply_req.trigger_point = trigger; + if (dev->ops && dev->ops->apply_req) { + rc = dev->ops->apply_req(&apply_req); + if (rc) + return rc; + CAM_DBG(CAM_REQ, + "SEND: link_hdl: %x pd: %d req_id %lld", + link->link_hdl, pd, apply_req.request_id); + slot->skip_next_frame = false; + slot->is_applied = true; + return -EAGAIN; + } + } + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + if (dev) { + pd = dev->dev_info.p_delay; + if (pd >= CAM_PIPELINE_DELAY_MAX) { + CAM_WARN(CAM_CRM, "pd %d greater than max", + pd); + continue; + } + if (link->req.apply_data[pd].skip_idx || + link->req.apply_data[pd].req_id < 0) { + CAM_DBG(CAM_CRM, "skip %d req_id %lld", + link->req.apply_data[pd].skip_idx, + link->req.apply_data[pd].req_id); + continue; + } + if (!(dev->dev_info.trigger & trigger)) + continue; + + apply_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = + link->req.apply_data[pd].req_id; + idx = link->req.apply_data[pd].idx; + slot = &dev->pd_tbl->slot[idx]; + apply_req.report_if_bubble = + in_q->slot[idx].recover; + + if ((slot->dev_hdl == dev->dev_hdl) && + (slot->is_applied == true)) { + slot->is_applied = false; + continue; + } + + apply_req.trigger_point = trigger; + CAM_DBG(CAM_REQ, + "SEND: link_hdl: %x pd %d req_id %lld", + link->link_hdl, pd, apply_req.request_id); + if (dev->ops && dev->ops->apply_req) { + rc = dev->ops->apply_req(&apply_req); + if (rc < 0) { + *failed_dev = dev; + break; + } + + if (pd == link->max_delay) + link->open_req_cnt--; + } + trace_cam_req_mgr_apply_request(link, &apply_req, dev); + } + } + if (rc < 0) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "APPLY FAILED pd %d req_id %lld", + dev->dev_info.p_delay, apply_req.request_id); + /* Apply req failed notify already applied devs */ + for (; i >= 0; i--) { + dev = &link->l_dev[i]; + evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_ERR; + evt_data.dev_hdl = dev->dev_hdl; + evt_data.link_hdl = link->link_hdl; + evt_data.req_id = apply_req.request_id; + evt_data.u.error = CRM_KMD_ERR_BUBBLE; + if (dev->ops && dev->ops->process_evt) + dev->ops->process_evt(&evt_data); + } + } + return rc; +} + +/** + * __cam_req_mgr_check_link_is_ready() + * + * @brief : traverse through all request tables and see if all devices are + * ready to apply request settings. + * @link : pointer to link whose input queue and req tbl are + * traversed through + * @idx : index within input request queue + * @validate_only : Whether to validate only and/or update settings + * + * @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) +{ + int rc; + struct cam_req_mgr_traverse traverse_data; + struct cam_req_mgr_req_queue *in_q; + struct cam_req_mgr_apply *apply_data; + + in_q = link->req.in_q; + + apply_data = link->req.apply_data; + + if (validate_only == false) { + memset(apply_data, 0, + sizeof(struct cam_req_mgr_apply) * CAM_PIPELINE_DELAY_MAX); + } + + traverse_data.apply_data = apply_data; + traverse_data.idx = idx; + traverse_data.tbl = link->req.l_tbl; + traverse_data.in_q = in_q; + traverse_data.result = 0; + traverse_data.validate_only = validate_only; + 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 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, + "READY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld", + link->link_hdl, idx, + apply_data[2].req_id, + apply_data[1].req_id, + apply_data[0].req_id); + } else + rc = -EAGAIN; + + return rc; +} + +/** + * __cam_req_mgr_find_slot_for_req() + * + * @brief : Find idx from input queue at which req id is enqueued + * @in_q : input request queue pointer + * @req_id : request id which needs to be searched in input queue + * + * @return : slot index where passed request id is stored, -1 for failure + * + */ +static int32_t __cam_req_mgr_find_slot_for_req( + struct cam_req_mgr_req_queue *in_q, int64_t req_id) +{ + int32_t idx, i; + struct cam_req_mgr_slot *slot; + + idx = in_q->rd_idx; + for (i = 0; i < in_q->num_slots; i++) { + slot = &in_q->slot[idx]; + if (slot->req_id == req_id) { + CAM_DBG(CAM_CRM, + "req: %lld found at idx: %d status: %d sync_mode: %d", + req_id, idx, slot->status, slot->sync_mode); + break; + } + __cam_req_mgr_dec_idx(&idx, 1, in_q->num_slots); + } + if (i >= in_q->num_slots) + idx = -1; + + return idx; +} + +/** + * __cam_req_mgr_check_sync_for_mslave() + * + * @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 int __cam_req_mgr_check_sync_for_mslave( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_slot *slot) +{ + 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; + int32_t sync_num_slots = 0; + + if (!link->sync_link) { + CAM_ERR(CAM_CRM, "Sync link null"); + return -EINVAL; + } + + sync_link = link->sync_link; + req_id = slot->req_id; + sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + + CAM_DBG(CAM_CRM, + "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); + + 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; + } + + 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; + } + + 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 (sync_link->initial_skip) { + CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + 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; + } + + 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 + sync_num_slots) % + sync_num_slots) >= 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 + sync_num_slots) % + sync_num_slots) >= 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; + } + } + } + + 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_check_sync_request_is_ready() + * + * @brief : processes requests during sync mode + * @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 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, sync_rd_idx = 0, rc = 0; + int32_t sync_num_slots = 0; + bool ready = true, sync_ready = true; + + if (!link->sync_link) { + CAM_ERR(CAM_CRM, "Sync link null"); + return -EINVAL; + } + + sync_link = link->sync_link; + req_id = slot->req_id; + sync_num_slots = sync_link->req.in_q->num_slots; + + CAM_DBG(CAM_REQ, + "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; + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + return -EAGAIN; + } + + 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); + ready = false; + } + + sync_slot_idx = __cam_req_mgr_find_slot_for_req( + sync_link->req.in_q, req_id); + if (sync_slot_idx == -1) { + CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", + req_id, sync_link->link_hdl); + sync_ready = false; + } + + 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 + sync_num_slots) % + sync_num_slots) >= 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); + return -EAGAIN; + } + + rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); + if (rc) { + CAM_DBG(CAM_CRM, + "Req: %lld [My link] not ready on link: %x, rc=%d", + req_id, link->link_hdl, rc); + ready = false; + } + + 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); + sync_ready = false; + } + + /* + * If both of them are ready or not ready, then just + * skip this sof and don't skip sync link next SOF. + */ + if (sync_ready != ready) { + CAM_DBG(CAM_CRM, + "Req: %lld ready %d sync_ready %d, ignore sync link next SOF", + req_id, ready, sync_ready); + link->sync_link_sof_skip = true; + return -EINVAL; + } else if (ready == false) { + CAM_DBG(CAM_CRM, + "Req: %lld not ready on link: %x", + req_id, link->link_hdl); + return -EINVAL; + } + + 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_req() + * + * @brief : processes read index in request queue and traverse through table + * @link : pointer to link whose input queue and req tbl are + * traversed through + * + * @return : 0 for success, negative for failure + * + */ +static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, + uint32_t trigger) +{ + int rc = 0, idx; + int reset_step = 0; + struct cam_req_mgr_slot *slot = NULL; + struct cam_req_mgr_req_queue *in_q; + struct cam_req_mgr_core_session *session; + struct cam_req_mgr_connected_device *dev; + + in_q = link->req.in_q; + session = (struct cam_req_mgr_core_session *)link->parent; + mutex_lock(&session->lock); + /* + * Check if new read index, + * - if in pending state, traverse again to complete + * transaction of this read index. + * - if in applied_state, somthign wrong. + * - if in no_req state, no new req + */ + CAM_DBG(CAM_REQ, "SOF Req[%lld] idx %d req_status %d link_hdl %x", + in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx, + in_q->slot[in_q->rd_idx].status, link->link_hdl); + + slot = &in_q->slot[in_q->rd_idx]; + if (slot->status == CRM_SLOT_STATUS_NO_REQ) { + CAM_DBG(CAM_CRM, "No Pending req"); + rc = 0; + goto error; + } + + if ((trigger != CAM_TRIGGER_POINT_SOF) && + (trigger != CAM_TRIGGER_POINT_EOF)) + goto error; + + if ((trigger == CAM_TRIGGER_POINT_EOF) && + (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) { + CAM_DBG(CAM_CRM, "Applying for last SOF fails"); + rc = -EINVAL; + goto error; + } + + if (trigger == CAM_TRIGGER_POINT_SOF) { + if (link->trigger_mask) { + CAM_ERR_RATE_LIMIT(CAM_CRM, + "Applying for last EOF fails"); + rc = -EINVAL; + goto error; + } + + 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) { + /* + * If traverse result is not success, then some devices + * are not ready with packet for the asked request id, + * hence try again in next sof + */ + slot->status = CRM_SLOT_STATUS_REQ_PENDING; + spin_lock_bh(&link->link_state_spin_lock); + if (link->state == CAM_CRM_LINK_STATE_ERR) { + /* + * During error recovery all tables should be + * ready, don't expect to enter here. + * @TODO: gracefully handle if recovery fails. + */ + CAM_ERR_RATE_LIMIT(CAM_CRM, + "FATAL recovery cant finish idx %d status %d", + in_q->rd_idx, + in_q->slot[in_q->rd_idx].status); + rc = -EPERM; + } + spin_unlock_bh(&link->link_state_spin_lock); + goto error; + } + } + + rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger, &dev); + if (rc < 0) { + /* Apply req failed retry at next sof */ + slot->status = CRM_SLOT_STATUS_REQ_PENDING; + + link->retry_cnt++; + if (link->retry_cnt == MAXIMUM_RETRY_ATTEMPTS) { + CAM_DBG(CAM_CRM, + "Max retry attempts reached on link[0x%x] for req [%lld]", + link->link_hdl, + in_q->slot[in_q->rd_idx].req_id); + __cam_req_mgr_notify_error_on_link(link, dev); + link->retry_cnt = 0; + } + } else { + if (link->retry_cnt) + link->retry_cnt = 0; + + link->trigger_mask |= trigger; + + CAM_DBG(CAM_CRM, "Applied req[%lld] on link[%x] success", + slot->req_id, link->link_hdl); + spin_lock_bh(&link->link_state_spin_lock); + if (link->state == CAM_CRM_LINK_STATE_ERR) { + CAM_WARN(CAM_CRM, "Err recovery done idx %d", + in_q->rd_idx); + link->state = CAM_CRM_LINK_STATE_READY; + } + spin_unlock_bh(&link->link_state_spin_lock); + + if (link->sync_link_sof_skip) + link->sync_link_sof_skip = false; + + if (link->trigger_mask == link->subscribe_event) { + slot->status = CRM_SLOT_STATUS_REQ_APPLIED; + link->trigger_mask = 0; + CAM_DBG(CAM_CRM, "req %d is applied on link %x", + slot->req_id, + link->link_hdl); + idx = in_q->rd_idx; + reset_step = link->max_delay; + if (link->sync_link) { + if ((link->in_msync_mode) && + (link->sync_link->is_master)) + reset_step = + link->sync_link->max_delay; + } + __cam_req_mgr_dec_idx( + &idx, reset_step + 1, + in_q->num_slots); + __cam_req_mgr_reset_req_slot(link, idx); + } + } + + mutex_unlock(&session->lock); + return rc; +error: + mutex_unlock(&session->lock); + return rc; +} + +/** + * __cam_req_mgr_add_tbl_to_link() + * + * @brief : Add table to list under link sorted by pd decremeting order + * @l_tbl : list of pipeline delay tables. + * @new_tbl : new tbl which will be appended to above list as per its pd value + * + */ +static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl, + struct cam_req_mgr_req_tbl *new_tbl) +{ + struct cam_req_mgr_req_tbl *tbl; + + if (!(*l_tbl) || (*l_tbl)->pd < new_tbl->pd) { + new_tbl->next = *l_tbl; + if (*l_tbl) { + new_tbl->pd_delta = + new_tbl->pd - (*l_tbl)->pd; + } + *l_tbl = new_tbl; + } else { + tbl = *l_tbl; + + /* Reach existing tbl which has less pd value */ + while (tbl->next != NULL && + new_tbl->pd < tbl->next->pd) { + tbl = tbl->next; + } + if (tbl->next != NULL) { + new_tbl->pd_delta = + new_tbl->pd - tbl->next->pd; + } else { + /* This is last table in linked list*/ + new_tbl->pd_delta = 0; + } + new_tbl->next = tbl->next; + tbl->next = new_tbl; + tbl->pd_delta = tbl->pd - new_tbl->pd; + } + CAM_DBG(CAM_CRM, "added pd %d tbl to link delta %d", new_tbl->pd, + new_tbl->pd_delta); +} + +/** + * __cam_req_mgr_create_pd_tbl() + * + * @brief : Creates new request table for new delay value + * @delay : New pd table allocated will have this delay value + * + * @return : pointer to newly allocated table, NULL for failure + * + */ +static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay) +{ + struct cam_req_mgr_req_tbl *tbl = + kzalloc(sizeof(struct cam_req_mgr_req_tbl), GFP_KERNEL); + if (tbl != NULL) { + tbl->num_slots = MAX_REQ_SLOTS; + CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots); + } + + return tbl; +} + +/** + * __cam_req_mgr_destroy_all_tbl() + * + * @brief : This func will destroy all pipeline delay based req table structs + * @l_tbl : pointer to first table in list and it has max pd . + * + */ +static void __cam_req_mgr_destroy_all_tbl(struct cam_req_mgr_req_tbl **l_tbl) +{ + struct cam_req_mgr_req_tbl *tbl = *l_tbl, *temp; + + CAM_DBG(CAM_CRM, "*l_tbl %pK", tbl); + while (tbl != NULL) { + temp = tbl->next; + kfree(tbl); + tbl = temp; + } + *l_tbl = NULL; +} + +/** + * __cam_req_mgr_setup_in_q() + * + * @brief : Initialize req table data + * @req : request data pointer + * + * @return: 0 for success, negative for failure + * + */ +static int __cam_req_mgr_setup_in_q(struct cam_req_mgr_req_data *req) +{ + int i; + struct cam_req_mgr_req_queue *in_q = req->in_q; + + if (!in_q) { + CAM_ERR(CAM_CRM, "NULL in_q"); + return -EINVAL; + } + + mutex_lock(&req->lock); + in_q->num_slots = MAX_REQ_SLOTS; + + for (i = 0; i < in_q->num_slots; i++) { + in_q->slot[i].idx = i; + in_q->slot[i].req_id = -1; + in_q->slot[i].skip_idx = 0; + in_q->slot[i].status = CRM_SLOT_STATUS_NO_REQ; + } + + in_q->wr_idx = 0; + in_q->rd_idx = 0; + mutex_unlock(&req->lock); + + return 0; +} + +/** + * __cam_req_mgr_reset_req_tbl() + * + * @brief : Initialize req table data + * @req : request queue pointer + * + * @return: 0 for success, negative for failure + * + */ +static int __cam_req_mgr_reset_in_q(struct cam_req_mgr_req_data *req) +{ + struct cam_req_mgr_req_queue *in_q = req->in_q; + + if (!in_q) { + CAM_ERR(CAM_CRM, "NULL in_q"); + return -EINVAL; + } + + mutex_lock(&req->lock); + memset(in_q->slot, 0, + sizeof(struct cam_req_mgr_slot) * in_q->num_slots); + in_q->num_slots = 0; + + in_q->wr_idx = 0; + in_q->rd_idx = 0; + mutex_unlock(&req->lock); + + return 0; +} + +/** + * __cam_req_mgr_notify_sof_freeze() + * + * @brief : Notify devices on link on detecting a SOF freeze + * @link : link on which the sof freeze was detected + * + */ +static void __cam_req_mgr_notify_sof_freeze( + struct cam_req_mgr_core_link *link) +{ + int i = 0; + struct cam_req_mgr_link_evt_data evt_data; + struct cam_req_mgr_connected_device *dev = NULL; + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_SOF_FREEZE; + evt_data.dev_hdl = dev->dev_hdl; + evt_data.link_hdl = link->link_hdl; + evt_data.req_id = 0; + evt_data.u.error = CRM_KMD_ERR_FATAL; + if (dev->ops && dev->ops->process_evt) + dev->ops->process_evt(&evt_data); + } +} + +/** + * __cam_req_mgr_process_sof_freeze() + * + * @brief : Apoptosis - Handles case when connected devices are not responding + * @priv : link information + * @data : task data + * + */ +static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) +{ + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_core_session *session = NULL; + struct cam_req_mgr_message msg; + int rc = 0; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + return -EINVAL; + } + + link = (struct cam_req_mgr_core_link *)priv; + session = (struct cam_req_mgr_core_session *)link->parent; + + CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x", + session->session_hdl, link->link_hdl); + + __cam_req_mgr_notify_sof_freeze(link); + memset(&msg, 0, sizeof(msg)); + + msg.session_hdl = session->session_hdl; + msg.u.err_msg.error_type = CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + msg.u.err_msg.request_id = 0; + msg.u.err_msg.link_hdl = link->link_hdl; + + rc = cam_req_mgr_notify_message(&msg, + V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT); + + if (rc) + CAM_ERR(CAM_CRM, + "Error notifying SOF freeze for session %d link 0x%x rc %d", + session->session_hdl, link->link_hdl, rc); + + return rc; +} + +/** + * __cam_req_mgr_sof_freeze() + * + * @brief : Callback function for timer timeout indicating SOF freeze + * @data : timer pointer + * + */ +static void __cam_req_mgr_sof_freeze(struct timer_list *timer_data) +{ + struct cam_req_mgr_timer *timer = + container_of(timer_data, struct cam_req_mgr_timer, sys_timer); + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct crm_task_payload *task_data; + + if (!timer) { + CAM_ERR(CAM_CRM, "NULL timer"); + return; + } + + link = (struct cam_req_mgr_core_link *)timer->parent; + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "No empty task"); + return; + } + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_FREEZE; + task->process_cb = &__cam_req_mgr_process_sof_freeze; + cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); +} + +/** + * __cam_req_mgr_create_subdevs() + * + * @brief : Create new crm subdev to link with realtime devices + * @l_dev : list of subdevs internal to crm + * @num_dev : num of subdevs to be created for link + * + * @return : pointer to allocated list of devices + */ +static int __cam_req_mgr_create_subdevs( + struct cam_req_mgr_connected_device **l_dev, int32_t num_dev) +{ + int rc = 0; + *l_dev = kzalloc(sizeof(struct cam_req_mgr_connected_device) * + num_dev, GFP_KERNEL); + if (!*l_dev) + rc = -ENOMEM; + + return rc; +} + +/** + * __cam_req_mgr_destroy_subdev() + * + * @brief : Cleans up the subdevs allocated by crm for link + * @l_device : pointer to list of subdevs crm created + * + */ +static void __cam_req_mgr_destroy_subdev( + struct cam_req_mgr_connected_device *l_device) +{ + kfree(l_device); + l_device = NULL; +} + +/** + * __cam_req_mgr_destroy_link_info() + * + * @brief : Unlinks all devices on the link + * @link : pointer to link + * + * @return : returns if unlink for any device was success or failure + */ +static int __cam_req_mgr_disconnect_link(struct cam_req_mgr_core_link *link) +{ + int32_t i = 0; + struct cam_req_mgr_connected_device *dev; + struct cam_req_mgr_core_dev_link_setup link_data; + int rc = 0; + + link_data.link_enable = 0; + link_data.link_hdl = link->link_hdl; + link_data.crm_cb = NULL; + link_data.subscribe_event = 0; + + /* Using device ops unlink devices */ + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + if (dev == NULL) + continue; + + link_data.dev_hdl = dev->dev_hdl; + if (dev->ops && dev->ops->link_setup) { + rc = dev->ops->link_setup(&link_data); + if (rc) + CAM_ERR(CAM_CRM, + "Unlink failed dev name %s hdl %x", + dev->dev_info.name, + dev->dev_hdl); + } + dev->dev_hdl = 0; + dev->parent = NULL; + dev->ops = NULL; + } + + return rc; +} + +/** + * __cam_req_mgr_destroy_link_info() + * + * @brief : Cleans up the mem allocated while linking + * @link : pointer to link, mem associated with this link is freed + */ +static void __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link) +{ + __cam_req_mgr_destroy_all_tbl(&link->req.l_tbl); + __cam_req_mgr_reset_in_q(&link->req); + link->req.num_tbl = 0; + mutex_destroy(&link->req.lock); + + link->pd_mask = 0; + link->num_devs = 0; + link->max_delay = 0; +} + +/** + * __cam_req_mgr_reserve_link() + * + * @brief: Reserves one link data struct within session + * @session: session identifier + * + * @return: pointer to link reserved + * + */ +static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( + struct cam_req_mgr_core_session *session) +{ + struct cam_req_mgr_core_link *link; + struct cam_req_mgr_req_queue *in_q; + int i; + + if (!session || !g_crm_core_dev) { + CAM_ERR(CAM_CRM, "NULL session/core_dev ptr"); + return NULL; + } + + if (session->num_links >= MAXIMUM_LINKS_PER_SESSION) { + CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d", + session->num_links, MAXIMUM_LINKS_PER_SESSION); + 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 = kzalloc(sizeof(struct cam_req_mgr_req_queue), + GFP_KERNEL); + if (!in_q) { + CAM_ERR(CAM_CRM, "failed to create input queue, no mem"); + return NULL; + } + + mutex_lock(&link->lock); + link->num_devs = 0; + link->max_delay = 0; + memset(in_q->slot, 0, + sizeof(struct cam_req_mgr_slot) * MAX_REQ_SLOTS); + link->req.in_q = in_q; + in_q->num_slots = 0; + link->state = CAM_CRM_LINK_STATE_IDLE; + link->parent = (void *)session; + link->sync_link = NULL; + mutex_unlock(&link->lock); + + mutex_lock(&session->lock); + /* Loop through and find a free index */ + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { + if (!session->links[i]) { + CAM_DBG(CAM_CRM, + "Free link index %d found, num_links=%d", + i, session->num_links); + session->links[i] = link; + break; + } + } + + if (i == MAXIMUM_LINKS_PER_SESSION) { + CAM_ERR(CAM_CRM, "Free link index not found"); + goto error; + } + + session->num_links++; + CAM_DBG(CAM_CRM, "Active session links (%d)", + session->num_links); + mutex_unlock(&session->lock); + + return link; +error: + mutex_unlock(&session->lock); + kfree(in_q); + return NULL; +} + +/* + * __cam_req_mgr_free_link() + * + * @brief: Frees the link and its request queue + * + * @link: link identifier + * + */ +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; + i = link - g_links; + CAM_DBG(CAM_CRM, "free link index %d", i); + cam_req_mgr_core_link_reset(link); + atomic_set(&g_links[i].is_used, 0); +} + +/** + * __cam_req_mgr_unreserve_link() + * + * @brief : Removes the link data struct from the session and frees it + * @session: session identifier + * @link : link identifier + * + */ +static void __cam_req_mgr_unreserve_link( + struct cam_req_mgr_core_session *session, + struct cam_req_mgr_core_link *link) +{ + int i; + + if (!session || !link) { + CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK", + session, link); + return; + } + + mutex_lock(&session->lock); + if (!session->num_links) { + CAM_WARN(CAM_CRM, "No active link or invalid state: hdl %x", + link->link_hdl); + mutex_unlock(&session->lock); + return; + } + + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { + if (session->links[i] == link) + session->links[i] = NULL; + + 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); + __cam_req_mgr_free_link(link); +} + +/* Workqueue context processing section */ + +/** + * cam_req_mgr_process_send_req() + * + * @brief: This runs in workque thread context. Call core funcs to send + * apply request id to drivers. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +int cam_req_mgr_process_send_req(void *priv, void *data) +{ + int rc = 0; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_send_request *send_req = NULL; + struct cam_req_mgr_req_queue *in_q = NULL; + struct cam_req_mgr_connected_device *dev; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + link = (struct cam_req_mgr_core_link *)priv; + send_req = (struct cam_req_mgr_send_request *)data; + in_q = send_req->in_q; + + rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF, &dev); +end: + return rc; +} + +/** + * cam_req_mgr_process_flush_req() + * + * @brief: This runs in workque thread context. Call core funcs to check + * which requests need to be removed/cancelled. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +int cam_req_mgr_process_flush_req(void *priv, void *data) +{ + int rc = 0, i = 0, idx = -1; + struct cam_req_mgr_flush_info *flush_info = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_req_queue *in_q = NULL; + struct cam_req_mgr_slot *slot = NULL; + struct cam_req_mgr_connected_device *device = NULL; + struct cam_req_mgr_flush_request flush_req; + struct crm_task_payload *task_data = NULL; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + link = (struct cam_req_mgr_core_link *)priv; + task_data = (struct crm_task_payload *)data; + flush_info = (struct cam_req_mgr_flush_info *)&task_data->u; + CAM_DBG(CAM_REQ, "link_hdl %x req_id %lld type %d", + flush_info->link_hdl, + flush_info->req_id, + flush_info->flush_type); + + in_q = link->req.in_q; + + trace_cam_flush_req(link, flush_info); + + 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; + slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + slot->skip_idx = 1; + slot->status = CRM_SLOT_STATUS_NO_REQ; + } + in_q->wr_idx = 0; + in_q->rd_idx = 0; + } else if (flush_info->flush_type == + CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + idx = __cam_req_mgr_find_slot_for_req(in_q, flush_info->req_id); + if (idx < 0) { + CAM_ERR(CAM_CRM, "req_id %lld not found in input queue", + flush_info->req_id); + } 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); + } + } + + for (i = 0; i < link->num_devs; i++) { + device = &link->l_dev[i]; + flush_req.link_hdl = flush_info->link_hdl; + flush_req.dev_hdl = device->dev_hdl; + flush_req.req_id = flush_info->req_id; + flush_req.type = flush_info->flush_type; + /* @TODO: error return handling from drivers */ + if (device->ops && device->ops->flush_req) + rc = device->ops->flush_req(&flush_req); + } + complete(&link->workq_comp); + mutex_unlock(&link->req.lock); + +end: + return rc; +} + +/** + * cam_req_mgr_process_sched_req() + * + * @brief: This runs in workque thread context. Call core funcs to check + * which peding requests can be processed. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +int cam_req_mgr_process_sched_req(void *priv, void *data) +{ + int rc = 0; + struct cam_req_mgr_sched_request *sched_req = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_req_queue *in_q = NULL; + struct cam_req_mgr_slot *slot = NULL; + struct crm_task_payload *task_data = NULL; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + link = (struct cam_req_mgr_core_link *)priv; + task_data = (struct crm_task_payload *)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 is_master:%d", + sched_req->link_hdl, sched_req->req_id, + in_q->wr_idx, sched_req->sync_mode, + link->is_master); + + mutex_lock(&link->req.lock); + slot = &in_q->slot[in_q->wr_idx]; + + if (slot->status != CRM_SLOT_STATUS_NO_REQ && + slot->status != CRM_SLOT_STATUS_REQ_APPLIED) + CAM_WARN(CAM_CRM, "in_q overwrite %d", slot->status); + + slot->status = CRM_SLOT_STATUS_REQ_ADDED; + slot->req_id = sched_req->req_id; + slot->sync_mode = sched_req->sync_mode; + slot->skip_idx = 0; + 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: + return rc; +} + +/** + * cam_req_mgr_process_add_req() + * + * @brief: This runs in workque thread context. Call core funcs to check + * which peding requests can be processed. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +int cam_req_mgr_process_add_req(void *priv, void *data) +{ + int rc = 0, i = 0, idx; + struct cam_req_mgr_add_request *add_req = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_connected_device *device = NULL; + struct cam_req_mgr_req_tbl *tbl = NULL; + struct cam_req_mgr_tbl_slot *slot = NULL; + struct crm_task_payload *task_data = NULL; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + + link = (struct cam_req_mgr_core_link *)priv; + task_data = (struct crm_task_payload *)data; + add_req = (struct cam_req_mgr_add_request *)&task_data->u; + + for (i = 0; i < link->num_devs; i++) { + device = &link->l_dev[i]; + if (device->dev_hdl == add_req->dev_hdl) { + tbl = device->pd_tbl; + break; + } + } + if (!tbl) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "dev_hdl not found %x, %x %x", + add_req->dev_hdl, + link->l_dev[0].dev_hdl, + link->l_dev[1].dev_hdl); + rc = -EINVAL; + goto end; + } + /* + * Go through request table and add + * request id to proper table + * 1. find req slot in in_q matching req_id.sent by dev + * 2. goto table of this device based on p_delay + * 3. mark req_ready_map with this dev_bit. + */ + + mutex_lock(&link->req.lock); + idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id); + if (idx < 0) { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q for dev %s on link 0x%x", + add_req->req_id, device->dev_info.name, link->link_hdl); + rc = -EBADSLT; + mutex_unlock(&link->req.lock); + goto end; + } + + slot = &tbl->slot[idx]; + slot->is_applied = false; + if ((add_req->skip_before_applying & 0xFF) > slot->inject_delay) { + slot->inject_delay = (add_req->skip_before_applying & 0xFF); + slot->dev_hdl = add_req->dev_hdl; + if (add_req->skip_before_applying & SKIP_NEXT_FRAME) + slot->skip_next_frame = true; + CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %llu", + add_req->req_id, + (add_req->skip_before_applying & 0xFF)); + } + + if (slot->state != CRM_REQ_STATE_PENDING && + slot->state != CRM_REQ_STATE_EMPTY) { + CAM_WARN(CAM_CRM, + "Unexpected state %d for slot %d map %x for dev %s on link 0x%x", + slot->state, idx, slot->req_ready_map, + device->dev_info.name, link->link_hdl); + } + + slot->state = CRM_REQ_STATE_PENDING; + slot->req_ready_map |= (1 << device->dev_bit); + + CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x", + idx, add_req->dev_hdl, add_req->req_id, tbl->pd, + slot->req_ready_map); + + trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); + + if (slot->req_ready_map == tbl->dev_mask) { + 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); + +end: + return rc; +} + +/** + * cam_req_mgr_process_error() + * + * @brief: This runs in workque thread context. bubble /err recovery. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +int cam_req_mgr_process_error(void *priv, void *data) +{ + int rc = 0, idx = -1, i; + struct cam_req_mgr_error_notify *err_info = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_req_queue *in_q = NULL; + struct cam_req_mgr_slot *slot = NULL; + struct cam_req_mgr_connected_device *device = NULL; + struct cam_req_mgr_link_evt_data evt_data; + struct crm_task_payload *task_data = NULL; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + link = (struct cam_req_mgr_core_link *)priv; + task_data = (struct crm_task_payload *)data; + err_info = (struct cam_req_mgr_error_notify *)&task_data->u; + CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld error %d", + err_info->link_hdl, + err_info->req_id, + err_info->error); + + in_q = link->req.in_q; + + mutex_lock(&link->req.lock); + if (err_info->error == CRM_KMD_ERR_BUBBLE) { + idx = __cam_req_mgr_find_slot_for_req(in_q, err_info->req_id); + if (idx < 0) { + CAM_ERR_RATE_LIMIT(CAM_CRM, + "req_id %lld not found in input queue", + err_info->req_id); + } else { + CAM_DBG(CAM_CRM, "req_id %lld found at idx %d", + err_info->req_id, idx); + slot = &in_q->slot[idx]; + if (!slot->recover) { + CAM_WARN(CAM_CRM, + "err recovery disabled req_id %lld", + err_info->req_id); + mutex_unlock(&link->req.lock); + return 0; + } else 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 recovered %d", + err_info->req_id, slot->status); + mutex_unlock(&link->req.lock); + return -EINVAL; + } + /* Notify all devices in the link about error */ + for (i = 0; i < link->num_devs; i++) { + device = &link->l_dev[i]; + if (device != NULL) { + evt_data.dev_hdl = device->dev_hdl; + evt_data.evt_type = + CAM_REQ_MGR_LINK_EVT_ERR; + evt_data.link_hdl = link->link_hdl; + evt_data.req_id = err_info->req_id; + evt_data.u.error = err_info->error; + if (device->ops && + device->ops->process_evt) + rc = device->ops->process_evt( + &evt_data); + } + } + /* Bring processing pointer to bubbled req id */ + __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl); + in_q->rd_idx = idx; + in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_ERR; + spin_unlock_bh(&link->link_state_spin_lock); + } + } + mutex_unlock(&link->req.lock); + +end: + return rc; +} + +/** + * cam_req_mgr_process_trigger() + * + * @brief: This runs in workque thread context. Call core funcs to check + * which peding requests can be processed. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +static int cam_req_mgr_process_trigger(void *priv, void *data) +{ + int rc = 0; + struct cam_req_mgr_trigger_notify *trigger_data = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_req_queue *in_q = NULL; + struct crm_task_payload *task_data = NULL; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + link = (struct cam_req_mgr_core_link *)priv; + task_data = (struct crm_task_payload *)data; + trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u; + + CAM_DBG(CAM_REQ, "link_hdl %x frame_id %lld, trigger %x\n", + trigger_data->link_hdl, + trigger_data->frame_id, + trigger_data->trigger); + + in_q = link->req.in_q; + + mutex_lock(&link->req.lock); + /* + * Check if current read index is in applied state, if yes make it free + * and increment read index to next slot. + */ + CAM_DBG(CAM_CRM, "link_hdl %x curent idx %d req_status %d", + link->link_hdl, in_q->rd_idx, in_q->slot[in_q->rd_idx].status); + + spin_lock_bh(&link->link_state_spin_lock); + if (link->state == CAM_CRM_LINK_STATE_ERR) + CAM_WARN(CAM_CRM, "Error recovery idx %d status %d", + in_q->rd_idx, + in_q->slot[in_q->rd_idx].status); + + spin_unlock_bh(&link->link_state_spin_lock); + + if (in_q->slot[in_q->rd_idx].status == CRM_SLOT_STATUS_REQ_APPLIED) { + /* + * Do NOT reset req q slot data here, it can not be done + * here because we need to preserve the data to handle bubble. + * + * 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", + link->link_hdl, in_q->slot[in_q->rd_idx].req_id); + 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); + +release_lock: + mutex_unlock(&link->req.lock); +end: + return rc; +} + +/** + * __cam_req_mgr_dev_handle_to_name() + * + * @brief : Finds device name based on the device handle + * @dev_hdl : Device handle whose name is to be found + * @link : Link on which the device is connected + * @return : String containing the device name + * + */ +static const char *__cam_req_mgr_dev_handle_to_name( + int32_t dev_hdl, struct cam_req_mgr_core_link *link) +{ + struct cam_req_mgr_connected_device *dev = NULL; + int i = 0; + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + + if (dev_hdl == dev->dev_hdl) + return dev->dev_info.name; + } + + return "Invalid dev_hdl"; +} + +/* Linked devices' Callback section */ + +/** + * cam_req_mgr_cb_add_req() + * + * @brief : Drivers call this function to notify new packet is available. + * @add_req : Information about new request available at a device. + * + * @return : 0 on success, negative in case of failure + * + */ +static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) +{ + int rc = 0, idx; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_add_request *dev_req; + struct crm_task_payload *task_data; + + if (!add_req) { + CAM_ERR(CAM_CRM, "sof_data is NULL"); + return -EINVAL; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(add_req->link_hdl); + + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", add_req->link_hdl); + return -EINVAL; + } + + CAM_DBG(CAM_REQ, "dev name %s dev_hdl %d dev req %lld", + __cam_req_mgr_dev_handle_to_name(add_req->dev_hdl, link), + add_req->dev_hdl, add_req->req_id); + + mutex_lock(&link->lock); + spin_lock_bh(&link->link_state_spin_lock); + if (link->state < CAM_CRM_LINK_STATE_READY) { + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + rc = -EPERM; + spin_unlock_bh(&link->link_state_spin_lock); + goto end; + } + spin_unlock_bh(&link->link_state_spin_lock); + + /* Validate if req id is present in input queue */ + idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id); + if (idx < 0) { + CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id); + rc = -ENOENT; + goto end; + } + + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task dev %x req %lld", + add_req->dev_hdl, add_req->req_id); + rc = -EBUSY; + goto end; + } + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_DEV_ADD_REQ; + dev_req = (struct cam_req_mgr_add_request *)&task_data->u; + dev_req->req_id = add_req->req_id; + dev_req->link_hdl = add_req->link_hdl; + dev_req->dev_hdl = add_req->dev_hdl; + dev_req->skip_before_applying = add_req->skip_before_applying; + task->process_cb = &cam_req_mgr_process_add_req; + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); + CAM_DBG(CAM_CRM, "X: dev %x dev req %lld", + add_req->dev_hdl, add_req->req_id); + +end: + mutex_unlock(&link->lock); + return rc; +} + +/** + * cam_req_mgr_cb_notify_err() + * + * @brief : Error received from device, sends bubble recovery + * @err_info : contains information about error occurred like bubble/overflow + * + * @return : 0 on success, negative in case of failure + * + */ +static int cam_req_mgr_cb_notify_err( + struct cam_req_mgr_error_notify *err_info) +{ + int rc = 0; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_error_notify *notify_err; + struct crm_task_payload *task_data; + + if (!err_info) { + CAM_ERR(CAM_CRM, "err_info is NULL"); + rc = -EINVAL; + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(err_info->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl); + rc = -EINVAL; + goto end; + } + + spin_lock_bh(&link->link_state_spin_lock); + if (link->state != CAM_CRM_LINK_STATE_READY) { + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + spin_unlock_bh(&link->link_state_spin_lock); + rc = -EPERM; + goto end; + } + crm_timer_reset(link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); + + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id); + rc = -EBUSY; + goto end; + } + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; + notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; + notify_err->req_id = err_info->req_id; + notify_err->link_hdl = err_info->link_hdl; + notify_err->dev_hdl = err_info->dev_hdl; + notify_err->error = err_info->error; + task->process_cb = &cam_req_mgr_process_error; + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); + +end: + return rc; +} + +/** + * cam_req_mgr_cb_notify_trigger() + * + * @brief : SOF received from device, sends trigger through workqueue + * @sof_data: contains information about frame_id, link etc. + * + * @return : 0 on success + * + */ +static int cam_req_mgr_cb_notify_trigger( + struct cam_req_mgr_trigger_notify *trigger_data) +{ + int rc = 0; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_trigger_notify *notify_trigger; + struct crm_task_payload *task_data; + + if (!trigger_data) { + CAM_ERR(CAM_CRM, "sof_data is NULL"); + rc = -EINVAL; + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(trigger_data->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", trigger_data->link_hdl); + rc = -EINVAL; + goto end; + } + + spin_lock_bh(&link->link_state_spin_lock); + if (link->state < CAM_CRM_LINK_STATE_READY) { + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + spin_unlock_bh(&link->link_state_spin_lock); + rc = -EPERM; + goto end; + } + crm_timer_reset(link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); + + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "no empty task frame %lld", + trigger_data->frame_id); + rc = -EBUSY; + goto end; + } + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF; + notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u; + notify_trigger->frame_id = trigger_data->frame_id; + notify_trigger->link_hdl = trigger_data->link_hdl; + notify_trigger->dev_hdl = trigger_data->dev_hdl; + notify_trigger->trigger = trigger_data->trigger; + task->process_cb = &cam_req_mgr_process_trigger; + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); + +end: + return rc; +} + +static struct cam_req_mgr_crm_cb cam_req_mgr_ops = { + .notify_trigger = cam_req_mgr_cb_notify_trigger, + .notify_err = cam_req_mgr_cb_notify_err, + .add_req = cam_req_mgr_cb_add_req, +}; + +/** + * __cam_req_mgr_setup_link_info() + * + * @brief : Sets up input queue, create pd based tables, communicate with + * devs connected on this link and setup communication. + * @link : pointer to link to setup + * @link_info : link_info coming from CSL to prepare link + * + * @return : 0 on success, negative in case of failure + * + */ +static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, + struct cam_req_mgr_link_info *link_info) +{ + int rc = 0, i = 0; + struct cam_req_mgr_core_dev_link_setup link_data; + struct cam_req_mgr_connected_device *dev; + struct cam_req_mgr_req_tbl *pd_tbl; + enum cam_pipeline_delay max_delay; + uint32_t subscribe_event = 0; + + if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) + return -EPERM; + + mutex_init(&link->req.lock); + CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock); + link->req.num_tbl = 0; + + rc = __cam_req_mgr_setup_in_q(&link->req); + if (rc < 0) + return rc; + + max_delay = CAM_PIPELINE_DELAY_0; + for (i = 0; i < link_info->num_devices; i++) { + dev = &link->l_dev[i]; + /* Using dev hdl, get ops ptr to communicate with device */ + dev->ops = (struct cam_req_mgr_kmd_ops *) + cam_get_device_ops(link_info->dev_hdls[i]); + if (!dev->ops || + !dev->ops->get_dev_info || + !dev->ops->link_setup) { + CAM_ERR(CAM_CRM, "FATAL: device ops NULL"); + rc = -ENXIO; + goto error; + } + dev->dev_hdl = link_info->dev_hdls[i]; + dev->parent = (void *)link; + dev->dev_info.dev_hdl = dev->dev_hdl; + rc = dev->ops->get_dev_info(&dev->dev_info); + + trace_cam_req_mgr_connect_device(link, &dev->dev_info); + + CAM_DBG(CAM_CRM, + "%x: connected: %s, id %d, delay %d, trigger %x", + link_info->session_hdl, dev->dev_info.name, + dev->dev_info.dev_id, dev->dev_info.p_delay, + dev->dev_info.trigger); + if (rc < 0 || + dev->dev_info.p_delay >= + CAM_PIPELINE_DELAY_MAX || + dev->dev_info.p_delay < + CAM_PIPELINE_DELAY_0) { + CAM_ERR(CAM_CRM, "get device info failed"); + goto error; + } else { + CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d", + link_info->session_hdl, + dev->dev_info.name, + dev->dev_info.p_delay); + if (dev->dev_info.p_delay > max_delay) + max_delay = dev->dev_info.p_delay; + + subscribe_event |= (uint32_t)dev->dev_info.trigger; + } + } + + link->subscribe_event = subscribe_event; + link_data.link_enable = 1; + link_data.link_hdl = link->link_hdl; + link_data.crm_cb = &cam_req_mgr_ops; + link_data.max_delay = max_delay; + link_data.subscribe_event = subscribe_event; + + for (i = 0; i < link_info->num_devices; i++) { + dev = &link->l_dev[i]; + + link_data.dev_hdl = dev->dev_hdl; + /* + * For unique pipeline delay table create request + * tracking table + */ + if (link->pd_mask & (1 << dev->dev_info.p_delay)) { + pd_tbl = __cam_req_mgr_find_pd_tbl(link->req.l_tbl, + dev->dev_info.p_delay); + if (!pd_tbl) { + CAM_ERR(CAM_CRM, "pd %d tbl not found", + dev->dev_info.p_delay); + rc = -ENXIO; + goto error; + } + } else { + pd_tbl = __cam_req_mgr_create_pd_tbl( + dev->dev_info.p_delay); + if (pd_tbl == NULL) { + CAM_ERR(CAM_CRM, "create new pd tbl failed"); + rc = -ENXIO; + goto error; + } + pd_tbl->pd = dev->dev_info.p_delay; + link->pd_mask |= (1 << pd_tbl->pd); + /* + * Add table to list and also sort list + * from max pd to lowest + */ + __cam_req_mgr_add_tbl_to_link(&link->req.l_tbl, pd_tbl); + } + dev->dev_bit = pd_tbl->dev_count++; + dev->pd_tbl = pd_tbl; + pd_tbl->dev_mask |= (1 << dev->dev_bit); + + /* Communicate with dev to establish the link */ + dev->ops->link_setup(&link_data); + + if (link->max_delay < dev->dev_info.p_delay) + link->max_delay = dev->dev_info.p_delay; + } + link->num_devs = link_info->num_devices; + + /* Assign id for pd tables */ + __cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req); + + /* At start, expect max pd devices, all are in skip state */ + __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl); + + return 0; + +error: + __cam_req_mgr_destroy_link_info(link); + return rc; +} + +/* IOCTLs handling section */ +int cam_req_mgr_create_session( + struct cam_req_mgr_session_info *ses_info) +{ + int rc = 0; + int32_t session_hdl; + struct cam_req_mgr_core_session *cam_session = NULL; + + if (!ses_info) { + CAM_DBG(CAM_CRM, "NULL session info pointer"); + return -EINVAL; + } + mutex_lock(&g_crm_core_dev->crm_lock); + cam_session = kzalloc(sizeof(*cam_session), + GFP_KERNEL); + if (!cam_session) { + rc = -ENOMEM; + goto end; + } + + session_hdl = cam_create_session_hdl((void *)cam_session); + if (session_hdl < 0) { + CAM_ERR(CAM_CRM, "unable to create session_hdl = %x", + session_hdl); + rc = session_hdl; + kfree(cam_session); + goto end; + } + ses_info->session_hdl = session_hdl; + + mutex_init(&cam_session->lock); + CAM_DBG(CAM_CRM, "LOCK_DBG session lock %pK", &cam_session->lock); + + mutex_lock(&cam_session->lock); + cam_session->session_hdl = session_hdl; + cam_session->num_links = 0; + cam_session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + list_add(&cam_session->entry, &g_crm_core_dev->session_head); + mutex_unlock(&cam_session->lock); +end: + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + +/** + * __cam_req_mgr_unlink() + * + * @brief : Unlink devices on a link structure from the session + * @link : Pointer to the link structure + * + * @return: 0 for success, negative for failure + * + */ +static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) +{ + int rc; + + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_IDLE; + spin_unlock_bh(&link->link_state_spin_lock); + + rc = __cam_req_mgr_disconnect_link(link); + if (rc) + CAM_ERR(CAM_CORE, + "Unlink for all devices was not successful"); + + mutex_lock(&link->lock); + /* Destroy timer of link */ + crm_timer_exit(&link->watchdog); + + /* Destroy workq of link */ + cam_req_mgr_workq_destroy(&link->workq); + + /* Cleanup request tables and unlink devices */ + __cam_req_mgr_destroy_link_info(link); + + /* Free memory holding data of linked devs */ + __cam_req_mgr_destroy_subdev(link->l_dev); + + /* Destroy the link handle */ + rc = cam_destroy_device_hdl(link->link_hdl); + 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; +} + +int cam_req_mgr_destroy_session( + struct cam_req_mgr_session_info *ses_info) +{ + int rc; + int i; + struct cam_req_mgr_core_session *cam_session = NULL; + struct cam_req_mgr_core_link *link; + + if (!ses_info) { + CAM_DBG(CAM_CRM, "NULL session info pointer"); + return -EINVAL; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + cam_session = (struct cam_req_mgr_core_session *) + cam_get_device_priv(ses_info->session_hdl); + if (!cam_session) { + CAM_ERR(CAM_CRM, "failed to get session priv"); + rc = -ENOENT; + goto end; + + } + if (cam_session->num_links) { + CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d", + ses_info->session_hdl, + cam_session->num_links); + + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { + link = cam_session->links[i]; + + if (!link) + continue; + + /* Ignore return value since session is going away */ + __cam_req_mgr_unlink(link); + __cam_req_mgr_free_link(link); + } + } + list_del(&cam_session->entry); + mutex_destroy(&cam_session->lock); + kfree(cam_session); + + rc = cam_destroy_session_hdl(ses_info->session_hdl); + if (rc < 0) + CAM_ERR(CAM_CRM, "unable to destroy session_hdl = %x rc %d", + ses_info->session_hdl, rc); + +end: + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + +int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) +{ + int rc = 0; + int wq_flag = 0; + char buf[128]; + struct cam_create_dev_hdl root_dev; + struct cam_req_mgr_core_session *cam_session; + struct cam_req_mgr_core_link *link; + + if (!link_info) { + CAM_DBG(CAM_CRM, "NULL pointer"); + return -EINVAL; + } + if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) { + CAM_ERR(CAM_CRM, "Invalid num devices %d", + link_info->num_devices); + 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; + } + + /* Allocate link struct and map it with session's request queue */ + link = __cam_req_mgr_reserve_link(cam_session); + if (!link) { + CAM_ERR(CAM_CRM, "failed to reserve new link"); + mutex_unlock(&g_crm_core_dev->crm_lock); + return -EINVAL; + } + CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl); + + memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl)); + root_dev.session_hdl = link_info->session_hdl; + root_dev.priv = (void *)link; + + mutex_lock(&link->lock); + /* Create unique dev handle for link */ + link->link_hdl = cam_create_device_hdl(&root_dev); + if (link->link_hdl < 0) { + CAM_ERR(CAM_CRM, + "Insufficient memory to create new device handle"); + rc = link->link_hdl; + 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, + link_info->num_devices); + if (rc < 0) { + CAM_ERR(CAM_CRM, + "Insufficient memory to create new crm subdevs"); + goto create_subdev_failed; + } + + /* Using device ops query connected devs, prepare request tables */ + rc = __cam_req_mgr_setup_link_info(link, link_info); + if (rc < 0) + goto setup_failed; + + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_READY; + spin_unlock_bh(&link->link_state_spin_lock); + + /* Create worker for current link */ + snprintf(buf, sizeof(buf), "%x-%x", + link_info->session_hdl, link->link_hdl); + wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL; + rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS, + &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag); + if (rc < 0) { + CAM_ERR(CAM_CRM, "FATAL: unable to create worker"); + __cam_req_mgr_destroy_link_info(link); + goto setup_failed; + } + + /* Assign payload to workqueue tasks */ + rc = __cam_req_mgr_setup_payload(link->workq); + if (rc < 0) { + __cam_req_mgr_destroy_link_info(link); + cam_req_mgr_workq_destroy(&link->workq); + goto setup_failed; + } + + mutex_unlock(&link->lock); + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +setup_failed: + __cam_req_mgr_destroy_subdev(link->l_dev); +create_subdev_failed: + cam_destroy_device_hdl(link->link_hdl); + link_info->link_hdl = -1; +link_hdl_fail: + mutex_unlock(&link->lock); + __cam_req_mgr_unreserve_link(cam_session, link); + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + +int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info) +{ + int rc = 0; + struct cam_req_mgr_core_session *cam_session; + struct cam_req_mgr_core_link *link; + + if (!unlink_info) { + CAM_ERR(CAM_CRM, "NULL pointer"); + return -EINVAL; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + CAM_DBG(CAM_CRM, "link_hdl %x", unlink_info->link_hdl); + + /* session hdl's priv data is cam session struct */ + cam_session = (struct cam_req_mgr_core_session *) + cam_get_device_priv(unlink_info->session_hdl); + if (!cam_session) { + CAM_ERR(CAM_CRM, "NULL pointer"); + mutex_unlock(&g_crm_core_dev->crm_lock); + return -EINVAL; + } + + /* link hdl's priv data is core_link struct */ + link = cam_get_device_priv(unlink_info->link_hdl); + if (!link) { + CAM_ERR(CAM_CRM, "NULL pointer"); + rc = -EINVAL; + goto done; + } + + rc = __cam_req_mgr_unlink(link); + + /* Free curent link and put back into session's free pool of links */ + __cam_req_mgr_unreserve_link(cam_session, link); + +done: + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + +int cam_req_mgr_schedule_request( + struct cam_req_mgr_sched_request *sched_req) +{ + int rc = 0; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_core_session *session = NULL; + struct cam_req_mgr_sched_request *sched; + struct crm_task_payload task_data; + + if (!sched_req) { + CAM_ERR(CAM_CRM, "csl_req is NULL"); + return -EINVAL; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(sched_req->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", sched_req->link_hdl); + rc = -EINVAL; + goto end; + } + + session = (struct cam_req_mgr_core_session *)link->parent; + if (!session) { + CAM_WARN(CAM_CRM, "session ptr NULL %x", sched_req->link_hdl); + rc = -EINVAL; + 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); + + task_data.type = CRM_WORKQ_TASK_SCHED_REQ; + sched = (struct cam_req_mgr_sched_request *)&task_data.u; + sched->req_id = sched_req->req_id; + sched->sync_mode = sched_req->sync_mode; + sched->link_hdl = sched_req->link_hdl; + if (session->force_err_recovery == AUTO_RECOVERY) { + sched->bubble_enable = sched_req->bubble_enable; + } else { + sched->bubble_enable = + (session->force_err_recovery == FORCE_ENABLE_RECOVERY) ? 1 : 0; + } + + rc = cam_req_mgr_process_sched_req(link, &task_data); + + CAM_DBG(CAM_REQ, "Open req %lld on link 0x%x with sync_mode %d", + sched_req->req_id, sched_req->link_hdl, sched_req->sync_mode); +end: + mutex_unlock(&g_crm_core_dev->crm_lock); + 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) +{ + int rc = 0; + struct cam_req_mgr_core_session *cam_session; + struct cam_req_mgr_core_link *link1 = NULL; + struct cam_req_mgr_core_link *link2 = NULL; + + if (!sync_info) { + CAM_ERR(CAM_CRM, "NULL pointer"); + return -EINVAL; + } + + if ((sync_info->num_links < 0) || + (sync_info->num_links > + MAX_LINKS_PER_SESSION)) { + CAM_ERR(CAM_CRM, "Invalid num links %d", sync_info->num_links); + 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]); + 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(sync_info->session_hdl); + if (!cam_session) { + CAM_ERR(CAM_CRM, "NULL pointer"); + mutex_unlock(&g_crm_core_dev->crm_lock); + return -EINVAL; + } + + mutex_lock(&cam_session->lock); + + CAM_DBG(CAM_CRM, "link handles %x %x", + sync_info->link_hdls[0], sync_info->link_hdls[1]); + + /* only two links existing per session in dual cam use case*/ + link1 = cam_get_device_priv(sync_info->link_hdls[0]); + if (!link1) { + CAM_ERR(CAM_CRM, "link1 NULL pointer"); + rc = -EINVAL; + goto done; + } + + link2 = cam_get_device_priv(sync_info->link_hdls[1]); + if (!link2) { + CAM_ERR(CAM_CRM, "link2 NULL pointer"); + rc = -EINVAL; + goto done; + } + + link1->sync_link_sof_skip = false; + link1->sync_link = NULL; + + link2->sync_link_sof_skip = false; + 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, + "Sync config on link1 0x%x & link2 0x%x with sync_mode %d", + link1->link_hdl, link2->link_hdl, cam_session->sync_mode); + +done: + mutex_unlock(&cam_session->lock); + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + +int cam_req_mgr_flush_requests( + struct cam_req_mgr_flush_info *flush_info) +{ + int rc = 0; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_flush_info *flush; + struct crm_task_payload *task_data; + struct cam_req_mgr_core_session *session = NULL; + + if (!flush_info) { + CAM_ERR(CAM_CRM, "flush req is NULL"); + rc = -EFAULT; + goto end; + } + if (flush_info->flush_type >= CAM_REQ_MGR_FLUSH_TYPE_MAX) { + CAM_ERR(CAM_CRM, "incorrect flush type %x", + flush_info->flush_type); + rc = -EINVAL; + goto end; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + /* session hdl's priv data is cam session struct */ + session = (struct cam_req_mgr_core_session *) + cam_get_device_priv(flush_info->session_hdl); + if (!session) { + CAM_ERR(CAM_CRM, "Invalid session %x", flush_info->session_hdl); + rc = -EINVAL; + goto end; + } + if (session->num_links <= 0) { + CAM_WARN(CAM_CRM, "No active links in session %x", + flush_info->session_hdl); + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(flush_info->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", flush_info->link_hdl); + rc = -EINVAL; + goto end; + } + + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + rc = -ENOMEM; + goto end; + } + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_FLUSH_REQ; + flush = (struct cam_req_mgr_flush_info *)&task_data->u; + flush->req_id = flush_info->req_id; + flush->link_hdl = flush_info->link_hdl; + flush->flush_type = flush_info->flush_type; + task->process_cb = &cam_req_mgr_process_flush_req; + init_completion(&link->workq_comp); + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); + + /* Blocking call */ + rc = wait_for_completion_timeout( + &link->workq_comp, + msecs_to_jiffies(CAM_REQ_MGR_SCHED_REQ_TIMEOUT)); +end: + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + +int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) +{ + int rc = 0; + int i, j; + struct cam_req_mgr_core_link *link = NULL; + + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_link_evt_data evt_data; + + if (!control) { + CAM_ERR(CAM_CRM, "Control command is NULL"); + rc = -EINVAL; + goto end; + } + + 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; + goto end; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + for (i = 0; i < control->num_links; i++) { + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(control->link_hdls[i]); + if (!link) { + CAM_ERR(CAM_CRM, "Link(%d) is NULL on session 0x%x", + i, control->session_hdl); + rc = -EINVAL; + break; + } + + mutex_lock(&link->lock); + if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) { + /* Start SOF watchdog timer */ + rc = crm_timer_init(&link->watchdog, + CAM_REQ_MGR_WATCHDOG_TIMEOUT, link, + &__cam_req_mgr_sof_freeze); + if (rc < 0) { + CAM_ERR(CAM_CRM, + "SOF timer start fails: link=0x%x", + link->link_hdl); + rc = -EFAULT; + } + /* notify nodes */ + for (j = 0; j < link->num_devs; j++) { + dev = &link->l_dev[j]; + evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_RESUME; + evt_data.link_hdl = link->link_hdl; + evt_data.dev_hdl = dev->dev_hdl; + evt_data.req_id = 0; + if (dev->ops && dev->ops->process_evt) + dev->ops->process_evt(&evt_data); + } + } else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) { + /* Destroy SOF watchdog timer */ + spin_lock_bh(&link->link_state_spin_lock); + crm_timer_exit(&link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); + /* notify nodes */ + for (j = 0; j < link->num_devs; j++) { + dev = &link->l_dev[j]; + evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_PAUSE; + evt_data.link_hdl = link->link_hdl; + evt_data.dev_hdl = dev->dev_hdl; + evt_data.req_id = 0; + if (dev->ops && dev->ops->process_evt) + dev->ops->process_evt(&evt_data); + } + } else { + CAM_ERR(CAM_CRM, "Invalid link control command"); + rc = -EINVAL; + } + mutex_unlock(&link->lock); + } + mutex_unlock(&g_crm_core_dev->crm_lock); +end: + return rc; +} + + +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) { + CAM_WARN(CAM_CRM, "core device is already initialized"); + return 0; + } + g_crm_core_dev = kzalloc(sizeof(*g_crm_core_dev), + GFP_KERNEL); + if (!g_crm_core_dev) + return -ENOMEM; + + CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev); + INIT_LIST_HEAD(&g_crm_core_dev->session_head); + 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; +} + +int cam_req_mgr_core_device_deinit(void) +{ + if (!g_crm_core_dev) { + CAM_ERR(CAM_CRM, "NULL pointer"); + return -EINVAL; + } + + CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev); + mutex_destroy(&g_crm_core_dev->crm_lock); + kfree(g_crm_core_dev); + g_crm_core_dev = NULL; + + return 0; +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h new file mode 100644 index 000000000000..9a6acbc2c43e --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -0,0 +1,470 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_REQ_MGR_CORE_H_ +#define _CAM_REQ_MGR_CORE_H_ + +#include +#include "cam_req_mgr_interface.h" +#include "cam_req_mgr_core_defs.h" +#include "cam_req_mgr_timer.h" + +#define CAM_REQ_MGR_MAX_LINKED_DEV 16 +#define MAX_REQ_SLOTS 48 + +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 +#define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 +#define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 + +#define FORCE_DISABLE_RECOVERY 2 +#define FORCE_ENABLE_RECOVERY 1 +#define AUTO_RECOVERY 0 + +#define CRM_WORKQ_NUM_TASKS 60 + +#define MAX_SYNC_COUNT 65535 + +#define SYNC_LINK_SOF_CNT_MAX_LMT 1 + +#define MAXIMUM_LINKS_PER_SESSION 4 + +#define MAXIMUM_RETRY_ATTEMPTS 3 + +/** + * enum crm_workq_task_type + * @codes: to identify which type of task is present + */ +enum crm_workq_task_type { + CRM_WORKQ_TASK_GET_DEV_INFO, + CRM_WORKQ_TASK_SETUP_LINK, + CRM_WORKQ_TASK_DEV_ADD_REQ, + CRM_WORKQ_TASK_APPLY_REQ, + CRM_WORKQ_TASK_NOTIFY_SOF, + CRM_WORKQ_TASK_NOTIFY_ERR, + CRM_WORKQ_TASK_NOTIFY_FREEZE, + CRM_WORKQ_TASK_SCHED_REQ, + CRM_WORKQ_TASK_FLUSH_REQ, + CRM_WORKQ_TASK_INVALID, +}; + +/** + * struct crm_task_payload + * @type : to identify which type of task is present + * @u : union of payload of all types of tasks supported + * @sched_req : contains info of incoming reqest from CSL to CRM + * @flush_info : contains info of cancelled reqest + * @dev_req : contains tracking info of available req id at device + * @send_req : contains info of apply settings to be sent to devs in link + * @apply_req : contains info of which request is applied at device + * @notify_trigger : contains notification from IFE to CRM about trigger + * @notify_err : contains error info happened while processing request + * - + */ +struct crm_task_payload { + enum crm_workq_task_type type; + union { + struct cam_req_mgr_sched_request sched_req; + struct cam_req_mgr_flush_info flush_info; + struct cam_req_mgr_add_request dev_req; + struct cam_req_mgr_send_request send_req; + struct cam_req_mgr_trigger_notify notify_trigger; + struct cam_req_mgr_error_notify notify_err; + } u; +}; + +/** + * enum crm_req_state + * State machine for life cycle of request in pd table + * EMPTY : indicates req slot is empty + * PENDING : indicates req slot is waiting for reqs from all devs + * READY : indicates req slot is ready to be sent to devs + * INVALID : indicates req slot is not in valid state + */ +enum crm_req_state { + CRM_REQ_STATE_EMPTY, + CRM_REQ_STATE_PENDING, + CRM_REQ_STATE_READY, + CRM_REQ_STATE_INVALID, +}; + +/** + * enum crm_slot_status + * State machine for life cycle of request in input queue + * NO_REQ : empty slot + * REQ_ADDED : new entry in slot + * PENDING : waiting for next trigger to apply + * APPLIED : req is sent to all devices + * INVALID : invalid state + */ +enum crm_slot_status { + CRM_SLOT_STATUS_NO_REQ, + CRM_SLOT_STATUS_REQ_ADDED, + CRM_SLOT_STATUS_REQ_PENDING, + CRM_SLOT_STATUS_REQ_APPLIED, + CRM_SLOT_STATUS_INVALID, +}; + +/** + * enum cam_req_mgr_link_state + * State machine for life cycle of link in crm + * AVAILABLE : link available + * IDLE : link initialized but not ready yet + * READY : link is ready for use + * ERR : link has encountered error + * MAX : invalid state + */ +enum cam_req_mgr_link_state { + CAM_CRM_LINK_STATE_AVAILABLE, + CAM_CRM_LINK_STATE_IDLE, + CAM_CRM_LINK_STATE_READY, + CAM_CRM_LINK_STATE_ERR, + CAM_CRM_LINK_STATE_MAX, +}; + +/** + * struct cam_req_mgr_traverse + * @idx : slot index + * @result : contains which all tables were able to apply successfully + * @tbl : pointer of pipeline delay based request table + * @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 + * @open_req_cnt : Count of open requests yet to be serviced in the kernel. + */ +struct cam_req_mgr_traverse { + int32_t idx; + uint32_t result; + struct cam_req_mgr_req_tbl *tbl; + struct cam_req_mgr_apply *apply_data; + struct cam_req_mgr_req_queue *in_q; + bool validate_only; + int32_t open_req_cnt; +}; + +/** + * struct cam_req_mgr_apply + * @idx : corresponding input queue slot index + * @pd : pipeline delay of device + * @req_id : req id for dev with above pd to process + * @skip_idx: skip applying settings when this is set. + */ +struct cam_req_mgr_apply { + int32_t idx; + int32_t pd; + int64_t req_id; + int32_t skip_idx; +}; + +/** + * struct cam_req_mgr_tbl_slot + * @idx : slot index + * @req_ready_map : mask tracking which all devices have request ready + * @state : state machine for life cycle of a slot + * @inject_delay : insert extra bubbling for flash type of use cases + * @dev_hdl : stores the dev_hdl, who is having higher inject delay + * @skip_next_frame : flag to drop the frame after skip_before_apply frame + * @is_applied : flag to identify if request is already applied to + * device. + */ +struct cam_req_mgr_tbl_slot { + int32_t idx; + uint32_t req_ready_map; + enum crm_req_state state; + uint32_t inject_delay; + int32_t dev_hdl; + bool skip_next_frame; + bool is_applied; +}; + +/** + * struct cam_req_mgr_req_tbl + * @id : table indetifier + * @pd : pipeline delay of table + * @dev_count : num of devices having same pipeline delay + * @dev_mask : mask to track which devices are linked + * @skip_traverse : to indicate how many traverses need to be dropped + * by this table especially in the beginning or bubble recovery + * @next : pointer to next pipeline delay request table + * @pd_delta : differnce between this table's pipeline delay and next + * @num_slots : number of request slots present in the table + * @slot : array of slots tracking requests availability at devices + */ +struct cam_req_mgr_req_tbl { + int32_t id; + int32_t pd; + int32_t dev_count; + int32_t dev_mask; + int32_t skip_traverse; + struct cam_req_mgr_req_tbl *next; + int32_t pd_delta; + int32_t num_slots; + struct cam_req_mgr_tbl_slot slot[MAX_REQ_SLOTS]; +}; + +/** + * struct cam_req_mgr_slot + * - Internal Book keeping + * @idx : slot index + * @skip_idx : if req id in this slot needs to be skipped/not applied + * @status : state machine for life cycle of a slot + * - members updated due to external events + * @recover : if user enabled recovery for this request. + * @req_id : mask tracking which all devices have request ready + * @sync_mode : Sync mode in which req id in this slot has to applied + */ +struct cam_req_mgr_slot { + int32_t idx; + int32_t skip_idx; + enum crm_slot_status status; + int32_t recover; + int64_t req_id; + int32_t sync_mode; +}; + +/** + * struct cam_req_mgr_req_queue + * @num_slots : max num of input queue slots + * @slot : request slot holding incoming request id and bubble info. + * @rd_idx : indicates slot index currently in process. + * @wr_idx : indicates slot index to hold new upcoming req. + */ +struct cam_req_mgr_req_queue { + int32_t num_slots; + struct cam_req_mgr_slot slot[MAX_REQ_SLOTS]; + int32_t rd_idx; + int32_t wr_idx; +}; + +/** + * struct cam_req_mgr_req_data + * @in_q : Poiner to Input request queue + * @l_tbl : unique pd request tables. + * @num_tbl : how many unique pd value devices are present + * @apply_data : Holds information about request id for a request + * @lock : mutex lock protecting request data ops. + */ +struct cam_req_mgr_req_data { + struct cam_req_mgr_req_queue *in_q; + struct cam_req_mgr_req_tbl *l_tbl; + int32_t num_tbl; + struct cam_req_mgr_apply apply_data[CAM_PIPELINE_DELAY_MAX]; + struct mutex lock; +}; + +/** + * struct cam_req_mgr_connected_device + * - Device Properties + * @dev_hdl : device handle + * @dev_bit : unique bit assigned to device in link + * - Device characteristics + * @pd_tbl : tracks latest available req id at this device + * @dev_info : holds dev characteristics such as pipeline delay, dev name + * @ops : holds func pointer to call methods on this device + * @parent : pvt data - like link which this dev hdl belongs to + */ +struct cam_req_mgr_connected_device { + int32_t dev_hdl; + int64_t dev_bit; + struct cam_req_mgr_req_tbl *pd_tbl; + struct cam_req_mgr_device_info dev_info; + struct cam_req_mgr_kmd_ops *ops; + void *parent; +}; + +/** + * struct cam_req_mgr_core_link + * - Link Properties + * @link_hdl : Link identifier + * @num_devs : num of connected devices to this link + * @max_delay : Max of pipeline delay of all connected devs + * @workq : Pointer to handle workq related jobs + * @pd_mask : each set bit indicates the device with pd equal to + * bit position is available. + * - List of connected devices + * @l_dev : List of connected devices to this link + * - Request handling data struct + * @req : req data holder. + * - Timer + * @watchdog : watchdog timer to recover from sof freeze + * - Link private data + * @workq_comp : conditional variable to block user thread for workq + * to finish schedule request processing + * @state : link state machine + * @parent : pvt data - link's parent is session + * @lock : mutex lock to guard link data operations + * @link_state_spin_lock : spin lock to protect link state variable + * @subscribe_event : irqs that link subscribes, IFE should send + * 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 + * @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 + * @retry_cnt : Counter that tracks number of attempts to apply + * the same req + */ +struct cam_req_mgr_core_link { + int32_t link_hdl; + int32_t num_devs; + enum cam_pipeline_delay max_delay; + struct cam_req_mgr_core_workq *workq; + int32_t pd_mask; + struct cam_req_mgr_connected_device *l_dev; + struct cam_req_mgr_req_data req; + struct cam_req_mgr_timer *watchdog; + struct completion workq_comp; + enum cam_req_mgr_link_state state; + void *parent; + struct mutex lock; + spinlock_t link_state_spin_lock; + uint32_t subscribe_event; + uint32_t trigger_mask; + struct cam_req_mgr_core_link *sync_link; + 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; + uint32_t retry_cnt; +}; + +/** + * struct cam_req_mgr_core_session + * - Session Properties + * @session_hdl : session identifier + * @num_links : num of active links for current session + * - Links of this session + * @links : pointer to array of links within session + * @in_q : Input request queue one per session + * - Session private data + * @entry : pvt data - entry in the list of sessions + * @lock : pvt data - spin lock to guard session data + * - Debug data + * @force_err_recovery : For debugging, we can force bubble recovery + * to be always ON or always OFF using debugfs. + * @sync_mode : Sync mode for this session links + */ +struct cam_req_mgr_core_session { + int32_t session_hdl; + uint32_t num_links; + struct cam_req_mgr_core_link *links[MAXIMUM_LINKS_PER_SESSION]; + struct list_head entry; + struct mutex lock; + int32_t force_err_recovery; + int32_t sync_mode; +}; + +/** + * struct cam_req_mgr_core_device + * - Core camera request manager data struct + * @session_head : list head holding sessions + * @crm_lock : mutex lock to protect session creation & destruction + */ +struct cam_req_mgr_core_device { + struct list_head session_head; + struct mutex crm_lock; +}; + +/** + * cam_req_mgr_create_session() + * @brief : creates session + * @ses_info : output param for session handle + * + * called as part of session creation. + */ +int cam_req_mgr_create_session(struct cam_req_mgr_session_info *ses_info); + +/** + * cam_req_mgr_destroy_session() + * @brief : destroy session + * @ses_info : session handle info, input param + * + * Called as part of session destroy + * return success/failure + */ +int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info); + +/** + * cam_req_mgr_link() + * @brief : creates a link for a session + * @link_info : handle and session info to create a link + * + * link is formed in a session for multiple devices. it creates + * a unique link handle for the link and is specific to a + * session. Returns link handle + */ +int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info); + +/** + * cam_req_mgr_unlink() + * @brief : destroy a link in a session + * @unlink_info : session and link handle info + * + * link is destroyed in a session + */ +int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info); + +/** + * cam_req_mgr_schedule_request() + * @brief: Request is scheduled + * @sched_req: request id, session and link id info, bubble recovery info + */ +int cam_req_mgr_schedule_request( + struct cam_req_mgr_sched_request *sched_req); + +/** + * cam_req_mgr_sync_mode_setup() + * @brief: sync for links in a session + * @sync_info: session, links info and master link info + */ +int cam_req_mgr_sync_config(struct cam_req_mgr_sync_mode *sync_info); + +/** + * cam_req_mgr_flush_requests() + * @brief: flush all requests + * @flush_info: requests related to link and session + */ +int cam_req_mgr_flush_requests( + struct cam_req_mgr_flush_info *flush_info); + +/** + * cam_req_mgr_core_device_init() + * @brief: initialize crm core + */ +int cam_req_mgr_core_device_init(void); + +/** + * cam_req_mgr_core_device_deinit() + * @brief: cleanp crm core + */ +int cam_req_mgr_core_device_deinit(void); + +/** + * cam_req_mgr_handle_core_shutdown() + * @brief: Handles camera close + */ +void cam_req_mgr_handle_core_shutdown(void); + +/** + * cam_req_mgr_link_control() + * @brief: Handles link control operations + * @control: Link control command + */ +int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control); + +#endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_core_defs.h b/drivers/cam_req_mgr/cam_req_mgr_core_defs.h new file mode 100644 index 000000000000..fbaa7de494f7 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_core_defs.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_REQ_MGR_CORE_DEFS_H_ +#define _CAM_REQ_MGR_CORE_DEFS_H_ + +#define CRM_TRACE_ENABLE 0 +#define CRM_DEBUG_MUTEX 0 + +#define SET_SUCCESS_BIT(ret, pd) (ret |= (1 << (pd))) + +#define SET_FAILURE_BIT(ret, pd) (ret &= (~(1 << (pd)))) + +#define CRM_GET_REQ_ID(in_q, idx) in_q->slot[idx].req_id + +#endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c new file mode 100644 index 000000000000..6b428c41c1b0 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_req_mgr_debug.h" + +#define MAX_SESS_INFO_LINE_BUFF_LEN 256 + +static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; + +static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) +{ + struct cam_req_mgr_core_device *core_dev = data; + struct cam_req_mgr_core_session *session; + int rc = 0; + + mutex_lock(&core_dev->crm_lock); + + if (!list_empty(&core_dev->session_head)) { + list_for_each_entry(session, + &core_dev->session_head, entry) { + session->force_err_recovery = val; + } + } + + mutex_unlock(&core_dev->crm_lock); + + return rc; +} + +static int cam_req_mgr_debug_get_bubble_recovery(void *data, u64 *val) +{ + struct cam_req_mgr_core_device *core_dev = data; + struct cam_req_mgr_core_session *session; + + mutex_lock(&core_dev->crm_lock); + + if (!list_empty(&core_dev->session_head)) { + session = list_first_entry(&core_dev->session_head, + struct cam_req_mgr_core_session, + entry); + *val = session->force_err_recovery; + } + mutex_unlock(&core_dev->crm_lock); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(bubble_recovery, cam_req_mgr_debug_get_bubble_recovery, + cam_req_mgr_debug_set_bubble_recovery, "%lld\n"); + +static int session_info_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t session_info_read(struct file *t_file, char *t_char, + size_t t_size_t, loff_t *t_loff_t) +{ + int i; + char *out_buffer = sess_info_buffer; + char line_buffer[MAX_SESS_INFO_LINE_BUFF_LEN] = {0}; + struct cam_req_mgr_core_device *core_dev = + (struct cam_req_mgr_core_device *) t_file->private_data; + struct cam_req_mgr_core_session *session; + + memset(out_buffer, 0, MAX_SESS_INFO_LINE_BUFF_LEN); + + mutex_lock(&core_dev->crm_lock); + + if (!list_empty(&core_dev->session_head)) { + list_for_each_entry(session, + &core_dev->session_head, entry) { + snprintf(line_buffer, sizeof(line_buffer), + "session_hdl = %x \t" + "num_links = %d\n", + session->session_hdl, session->num_links); + strlcat(out_buffer, line_buffer, + sizeof(sess_info_buffer)); + for (i = 0; i < session->num_links; i++) { + snprintf(line_buffer, sizeof(line_buffer), + "link_hdl[%d] = 0x%x, num_devs connected = %d\n", + i, session->links[i]->link_hdl, + session->links[i]->num_devs); + strlcat(out_buffer, line_buffer, + sizeof(sess_info_buffer)); + } + } + } + + mutex_unlock(&core_dev->crm_lock); + + return simple_read_from_buffer(t_char, t_size_t, + t_loff_t, out_buffer, strlen(out_buffer)); +} + +static ssize_t session_info_write(struct file *t_file, + const char *t_char, size_t t_size_t, loff_t *t_loff_t) +{ + memset(sess_info_buffer, 0, MAX_SESS_INFO_LINE_BUFF_LEN); + + return 0; +} + +static const struct file_operations session_info = { + .open = session_info_open, + .read = session_info_read, + .write = session_info_write, +}; + +int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) +{ + struct dentry *debugfs_root; + char dirname[32] = {0}; + + snprintf(dirname, sizeof(dirname), "cam_req_mgr"); + debugfs_root = debugfs_create_dir(dirname, NULL); + if (!debugfs_root) + return -ENOMEM; + + if (!debugfs_create_file("sessions_info", 0644, + debugfs_root, core_dev, &session_info)) + return -ENOMEM; + + if (!debugfs_create_file("bubble_recovery", 0644, + debugfs_root, core_dev, &bubble_recovery)) + return -ENOMEM; + + return 0; +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.h b/drivers/cam_req_mgr/cam_req_mgr_debug.h new file mode 100644 index 000000000000..dc72c522d140 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_DEBUG_H_ +#define _CAM_REQ_MGR_DEBUG_H_ + +#include +#include "cam_req_mgr_core.h" + +int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev); + +#endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c new file mode 100644 index 000000000000..74d5cfff8d60 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -0,0 +1,752 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_req_mgr_dev.h" +#include "cam_req_mgr_util.h" +#include "cam_req_mgr_core.h" +#include "cam_subdev.h" +#include "cam_mem_mgr.h" +#include "cam_debug_util.h" +#include "cam_common_util.h" +#include + +#define CAM_REQ_MGR_EVENT_MAX 30 + +static struct cam_req_mgr_device g_dev; +struct kmem_cache *g_cam_req_mgr_timer_cachep; + +static int cam_media_device_setup(struct device *dev) +{ + int rc; + + g_dev.v4l2_dev->mdev = kzalloc(sizeof(*g_dev.v4l2_dev->mdev), + GFP_KERNEL); + if (!g_dev.v4l2_dev->mdev) { + rc = -ENOMEM; + goto mdev_fail; + } + + media_device_init(g_dev.v4l2_dev->mdev); + g_dev.v4l2_dev->mdev->dev = dev; + strlcpy(g_dev.v4l2_dev->mdev->model, CAM_REQ_MGR_VNODE_NAME, + sizeof(g_dev.v4l2_dev->mdev->model)); + + rc = media_device_register(g_dev.v4l2_dev->mdev); + if (rc) + goto media_fail; + + return rc; + +media_fail: + kfree(g_dev.v4l2_dev->mdev); + g_dev.v4l2_dev->mdev = NULL; +mdev_fail: + return rc; +} + +static void cam_media_device_cleanup(void) +{ + media_entity_cleanup(&g_dev.video->entity); + media_device_unregister(g_dev.v4l2_dev->mdev); + kfree(g_dev.v4l2_dev->mdev); + g_dev.v4l2_dev->mdev = NULL; +} + +static int cam_v4l2_device_setup(struct device *dev) +{ + int rc; + + g_dev.v4l2_dev = kzalloc(sizeof(*g_dev.v4l2_dev), + GFP_KERNEL); + if (!g_dev.v4l2_dev) + return -ENOMEM; + + rc = v4l2_device_register(dev, g_dev.v4l2_dev); + if (rc) + goto reg_fail; + + return rc; + +reg_fail: + kfree(g_dev.v4l2_dev); + g_dev.v4l2_dev = NULL; + return rc; +} + +static void cam_v4l2_device_cleanup(void) +{ + v4l2_device_unregister(g_dev.v4l2_dev); + kfree(g_dev.v4l2_dev); + g_dev.v4l2_dev = NULL; +} + +static int cam_req_mgr_open(struct file *filep) +{ + int rc; + + mutex_lock(&g_dev.cam_lock); + if (g_dev.open_cnt >= 1) { + rc = -EALREADY; + goto end; + } + + rc = v4l2_fh_open(filep); + if (rc) { + CAM_ERR(CAM_CRM, "v4l2_fh_open failed: %d", rc); + goto end; + } + + spin_lock_bh(&g_dev.cam_eventq_lock); + g_dev.cam_eventq = filep->private_data; + spin_unlock_bh(&g_dev.cam_eventq_lock); + + g_dev.open_cnt++; + rc = cam_mem_mgr_init(); + if (rc) { + g_dev.open_cnt--; + CAM_ERR(CAM_CRM, "mem mgr init failed"); + goto mem_mgr_init_fail; + } + + mutex_unlock(&g_dev.cam_lock); + return rc; + +mem_mgr_init_fail: + v4l2_fh_release(filep); +end: + mutex_unlock(&g_dev.cam_lock); + return rc; +} + +static unsigned int cam_req_mgr_poll(struct file *f, + struct poll_table_struct *pll_table) +{ + int rc = 0; + struct v4l2_fh *eventq = f->private_data; + + if (!eventq) + return -EINVAL; + + poll_wait(f, &eventq->wait, pll_table); + if (v4l2_event_pending(eventq)) + rc = POLLPRI; + + return rc; +} + +static int cam_req_mgr_close(struct file *filep) +{ + struct v4l2_subdev *sd; + struct v4l2_fh *vfh = filep->private_data; + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); + + mutex_lock(&g_dev.cam_lock); + + if (g_dev.open_cnt <= 0) { + mutex_unlock(&g_dev.cam_lock); + return -EINVAL; + } + + cam_req_mgr_handle_core_shutdown(); + + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) + continue; + if (sd->internal_ops && sd->internal_ops->close) { + CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", + sd->name); + sd->internal_ops->close(sd, subdev_fh); + } + } + + g_dev.open_cnt--; + v4l2_fh_release(filep); + + spin_lock_bh(&g_dev.cam_eventq_lock); + g_dev.cam_eventq = NULL; + spin_unlock_bh(&g_dev.cam_eventq_lock); + + cam_req_mgr_util_free_hdls(); + cam_mem_mgr_deinit(); + mutex_unlock(&g_dev.cam_lock); + + return 0; +} + +static struct v4l2_file_operations g_cam_fops = { + .owner = THIS_MODULE, + .open = cam_req_mgr_open, + .poll = cam_req_mgr_poll, + .release = cam_req_mgr_close, + .unlocked_ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = video_ioctl2, +#endif +}; + +static int cam_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + return v4l2_event_subscribe(fh, sub, CAM_REQ_MGR_EVENT_MAX, NULL); +} + +static int cam_unsubscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + return v4l2_event_unsubscribe(fh, sub); +} + +static long cam_private_ioctl(struct file *file, void *fh, + bool valid_prio, unsigned int cmd, void *arg) +{ + int rc; + struct cam_control *k_ioctl; + + if ((!arg) || (cmd != VIDIOC_CAM_CONTROL)) + return -EINVAL; + + k_ioctl = (struct cam_control *)arg; + + if (!k_ioctl->handle) + return -EINVAL; + + switch (k_ioctl->op_code) { + case CAM_REQ_MGR_CREATE_SESSION: { + struct cam_req_mgr_session_info ses_info; + + if (k_ioctl->size != sizeof(ses_info)) + return -EINVAL; + + if (copy_from_user(&ses_info, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_session_info))) { + return -EFAULT; + } + + rc = cam_req_mgr_create_session(&ses_info); + if (!rc) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &ses_info, + sizeof(struct cam_req_mgr_session_info))) + rc = -EFAULT; + } + break; + + case CAM_REQ_MGR_DESTROY_SESSION: { + struct cam_req_mgr_session_info ses_info; + + if (k_ioctl->size != sizeof(ses_info)) + return -EINVAL; + + if (copy_from_user(&ses_info, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_session_info))) { + return -EFAULT; + } + + rc = cam_req_mgr_destroy_session(&ses_info); + } + break; + + case CAM_REQ_MGR_LINK: { + struct cam_req_mgr_link_info link_info; + + if (k_ioctl->size != sizeof(link_info)) + return -EINVAL; + + if (copy_from_user(&link_info, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_link_info))) { + return -EFAULT; + } + + rc = cam_req_mgr_link(&link_info); + if (!rc) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &link_info, + sizeof(struct cam_req_mgr_link_info))) + rc = -EFAULT; + } + break; + + case CAM_REQ_MGR_UNLINK: { + struct cam_req_mgr_unlink_info unlink_info; + + if (k_ioctl->size != sizeof(unlink_info)) + return -EINVAL; + + if (copy_from_user(&unlink_info, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_unlink_info))) { + return -EFAULT; + } + + rc = cam_req_mgr_unlink(&unlink_info); + } + break; + + case CAM_REQ_MGR_SCHED_REQ: { + struct cam_req_mgr_sched_request sched_req; + + if (k_ioctl->size != sizeof(sched_req)) + return -EINVAL; + + if (copy_from_user(&sched_req, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_sched_request))) { + return -EFAULT; + } + + rc = cam_req_mgr_schedule_request(&sched_req); + } + break; + + case CAM_REQ_MGR_FLUSH_REQ: { + struct cam_req_mgr_flush_info flush_info; + + if (k_ioctl->size != sizeof(flush_info)) + return -EINVAL; + + if (copy_from_user(&flush_info, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_flush_info))) { + return -EFAULT; + } + + rc = cam_req_mgr_flush_requests(&flush_info); + } + break; + + case CAM_REQ_MGR_SYNC_MODE: { + struct cam_req_mgr_sync_mode sync_info; + + if (k_ioctl->size != sizeof(sync_info)) + return -EINVAL; + + if (copy_from_user(&sync_info, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_sync_mode))) { + return -EFAULT; + } + + rc = cam_req_mgr_sync_config(&sync_info); + } + break; + case CAM_REQ_MGR_ALLOC_BUF: { + struct cam_mem_mgr_alloc_cmd cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_mem_mgr_alloc_cmd))) { + rc = -EFAULT; + break; + } + + rc = cam_mem_mgr_alloc_and_map(&cmd); + if (!rc) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &cmd, sizeof(struct cam_mem_mgr_alloc_cmd))) { + rc = -EFAULT; + break; + } + } + break; + case CAM_REQ_MGR_MAP_BUF: { + struct cam_mem_mgr_map_cmd cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_mem_mgr_map_cmd))) { + rc = -EFAULT; + break; + } + + rc = cam_mem_mgr_map(&cmd); + if (!rc) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &cmd, sizeof(struct cam_mem_mgr_map_cmd))) { + rc = -EFAULT; + break; + } + } + break; + case CAM_REQ_MGR_RELEASE_BUF: { + struct cam_mem_mgr_release_cmd cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_mem_mgr_release_cmd))) { + rc = -EFAULT; + break; + } + + rc = cam_mem_mgr_release(&cmd); + } + break; + case CAM_REQ_MGR_CACHE_OPS: { + struct cam_mem_cache_ops_cmd cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_mem_cache_ops_cmd))) { + rc = -EFAULT; + break; + } + + rc = cam_mem_mgr_cache_ops(&cmd); + if (rc) + rc = -EINVAL; + } + break; + case CAM_REQ_MGR_LINK_CONTROL: { + struct cam_req_mgr_link_control cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_link_control))) { + rc = -EFAULT; + break; + } + + rc = cam_req_mgr_link_control(&cmd); + if (rc) + rc = -EINVAL; + } + break; + default: + return -ENOIOCTLCMD; + } + + return rc; +} + +static const struct v4l2_ioctl_ops g_cam_ioctl_ops = { + .vidioc_subscribe_event = cam_subscribe_event, + .vidioc_unsubscribe_event = cam_unsubscribe_event, + .vidioc_default = cam_private_ioctl, +}; + +static int cam_video_device_setup(void) +{ + int rc; + + g_dev.video = video_device_alloc(); + if (!g_dev.video) { + rc = -ENOMEM; + goto video_fail; + } + + g_dev.video->v4l2_dev = g_dev.v4l2_dev; + + strlcpy(g_dev.video->name, "cam-req-mgr", + sizeof(g_dev.video->name)); + g_dev.video->release = video_device_release; + g_dev.video->fops = &g_cam_fops; + g_dev.video->ioctl_ops = &g_cam_ioctl_ops; + g_dev.video->minor = -1; + g_dev.video->vfl_type = VFL_TYPE_GRABBER; + rc = video_register_device(g_dev.video, VFL_TYPE_GRABBER, -1); + if (rc) + goto v4l2_fail; + + rc = media_entity_pads_init(&g_dev.video->entity, 0, NULL); + if (rc) + goto entity_fail; + + g_dev.video->entity.function = CAM_VNODE_DEVICE_TYPE; + g_dev.video->entity.name = video_device_node_name(g_dev.video); + + return rc; + +entity_fail: + video_unregister_device(g_dev.video); +v4l2_fail: + video_device_release(g_dev.video); + g_dev.video = NULL; +video_fail: + return rc; +} + +int cam_req_mgr_notify_message(struct cam_req_mgr_message *msg, + uint32_t id, + uint32_t type) +{ + struct v4l2_event event; + struct cam_req_mgr_message *ev_header; + + if (!msg) + return -EINVAL; + + event.id = id; + event.type = type; + ev_header = CAM_REQ_MGR_GET_PAYLOAD_PTR(event, + struct cam_req_mgr_message); + memcpy(ev_header, msg, sizeof(struct cam_req_mgr_message)); + v4l2_event_queue(g_dev.video, &event); + + return 0; +} +EXPORT_SYMBOL(cam_req_mgr_notify_message); + +void cam_video_device_cleanup(void) +{ + video_unregister_device(g_dev.video); + video_device_release(g_dev.video); + g_dev.video = NULL; +} + +void cam_register_subdev_fops(struct v4l2_file_operations *fops) +{ + *fops = v4l2_subdev_fops; +} +EXPORT_SYMBOL(cam_register_subdev_fops); + +int cam_register_subdev(struct cam_subdev *csd) +{ + struct v4l2_subdev *sd; + int rc; + + if (g_dev.state != true) { + CAM_ERR(CAM_CRM, "camera root device not ready yet"); + return -ENODEV; + } + + if (!csd || !csd->name) { + CAM_ERR(CAM_CRM, "invalid arguments"); + return -EINVAL; + } + + mutex_lock(&g_dev.dev_lock); + if ((g_dev.subdev_nodes_created) && + (csd->sd_flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) { + CAM_ERR(CAM_CRM, + "dynamic node is not allowed, name: %s, type :%d", + csd->name, csd->ent_function); + rc = -EINVAL; + goto reg_fail; + } + + sd = &csd->sd; + v4l2_subdev_init(sd, csd->ops); + sd->internal_ops = csd->internal_ops; + snprintf(sd->name, ARRAY_SIZE(sd->name), csd->name); + v4l2_set_subdevdata(sd, csd->token); + + sd->flags = csd->sd_flags; + sd->entity.num_pads = 0; + sd->entity.pads = NULL; + sd->entity.function = csd->ent_function; + + rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); + if (rc) { + CAM_ERR(CAM_CRM, "register subdev failed"); + goto reg_fail; + } + g_dev.count++; + +reg_fail: + mutex_unlock(&g_dev.dev_lock); + return rc; +} +EXPORT_SYMBOL(cam_register_subdev); + +int cam_unregister_subdev(struct cam_subdev *csd) +{ + if (g_dev.state != true) { + CAM_ERR(CAM_CRM, "camera root device not ready yet"); + return -ENODEV; + } + + mutex_lock(&g_dev.dev_lock); + v4l2_device_unregister_subdev(&csd->sd); + g_dev.count--; + mutex_unlock(&g_dev.dev_lock); + + return 0; +} +EXPORT_SYMBOL(cam_unregister_subdev); + +static int cam_req_mgr_remove(struct platform_device *pdev) +{ + cam_req_mgr_core_device_deinit(); + cam_req_mgr_util_deinit(); + cam_media_device_cleanup(); + cam_video_device_cleanup(); + cam_v4l2_device_cleanup(); + mutex_destroy(&g_dev.dev_lock); + g_dev.state = false; + g_dev.subdev_nodes_created = false; + + return 0; +} + +static int cam_req_mgr_probe(struct platform_device *pdev) +{ + int rc; + + rc = cam_v4l2_device_setup(&pdev->dev); + if (rc) + return rc; + + rc = cam_media_device_setup(&pdev->dev); + if (rc) + goto media_setup_fail; + + rc = cam_video_device_setup(); + if (rc) + goto video_setup_fail; + + g_dev.open_cnt = 0; + mutex_init(&g_dev.cam_lock); + spin_lock_init(&g_dev.cam_eventq_lock); + g_dev.subdev_nodes_created = false; + mutex_init(&g_dev.dev_lock); + + rc = cam_req_mgr_util_init(); + if (rc) { + CAM_ERR(CAM_CRM, "cam req mgr util init is failed"); + goto req_mgr_util_fail; + } + + rc = cam_req_mgr_core_device_init(); + if (rc) { + CAM_ERR(CAM_CRM, "core device setup failed"); + goto req_mgr_core_fail; + } + + g_dev.state = true; + + if (g_cam_req_mgr_timer_cachep == NULL) { + g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", + sizeof(struct cam_req_mgr_timer), 64, + SLAB_CONSISTENCY_CHECKS | SLAB_RED_ZONE | + SLAB_POISON | SLAB_STORE_USER, NULL); + if (!g_cam_req_mgr_timer_cachep) + CAM_ERR(CAM_CRM, + "Failed to create kmem_cache for crm_timer"); + else + CAM_DBG(CAM_CRM, "Name : %s", + g_cam_req_mgr_timer_cachep->name); + } + + return rc; + +req_mgr_core_fail: + cam_req_mgr_util_deinit(); +req_mgr_util_fail: + mutex_destroy(&g_dev.dev_lock); + mutex_destroy(&g_dev.cam_lock); + cam_video_device_cleanup(); +video_setup_fail: + cam_media_device_cleanup(); +media_setup_fail: + cam_v4l2_device_cleanup(); + return rc; +} + +static const struct of_device_id cam_req_mgr_dt_match[] = { + {.compatible = "qcom,cam-req-mgr"}, + {} +}; +MODULE_DEVICE_TABLE(of, cam_dt_match); + +static struct platform_driver cam_req_mgr_driver = { + .probe = cam_req_mgr_probe, + .remove = cam_req_mgr_remove, + .driver = { + .name = "cam_req_mgr", + .owner = THIS_MODULE, + .of_match_table = cam_req_mgr_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_dev_mgr_create_subdev_nodes(void) +{ + int rc; + struct v4l2_subdev *sd; + + if (!g_dev.v4l2_dev) + return -EINVAL; + + if (g_dev.state != true) { + CAM_ERR(CAM_CRM, "camera root device not ready yet"); + return -ENODEV; + } + + mutex_lock(&g_dev.dev_lock); + if (g_dev.subdev_nodes_created) { + rc = -EEXIST; + goto create_fail; + } + + rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); + if (rc) { + CAM_ERR(CAM_CRM, "failed to register the sub devices"); + goto create_fail; + } + + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) + continue; + sd->entity.name = video_device_node_name(sd->devnode); + CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); + } + + g_dev.subdev_nodes_created = true; + +create_fail: + mutex_unlock(&g_dev.dev_lock); + return rc; +} + +static int __init cam_req_mgr_init(void) +{ + return platform_driver_register(&cam_req_mgr_driver); +} + +static int __init cam_req_mgr_late_init(void) +{ + return cam_dev_mgr_create_subdev_nodes(); +} + +static void __exit cam_req_mgr_exit(void) +{ + platform_driver_unregister(&cam_req_mgr_driver); +} + +module_init(cam_req_mgr_init); +late_initcall(cam_req_mgr_late_init); +module_exit(cam_req_mgr_exit); +MODULE_DESCRIPTION("Camera Request Manager"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h new file mode 100644 index 000000000000..48ad09ce5ee2 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_DEV_H_ +#define _CAM_REQ_MGR_DEV_H_ + +/** + * struct cam_req_mgr_device - a camera request manager device + * + * @video: pointer to struct video device. + * @v4l2_dev: pointer to struct v4l2 device. + * @subdev_nodes_created: flag to check the created state. + * @count: number of subdevices registered. + * @dev_lock: lock for the subdevice count. + * @state: state of the root device. + * @open_cnt: open count of subdev + * @cam_lock: per file handle lock + * @cam_eventq: event queue + * @cam_eventq_lock: lock for event queue + */ +struct cam_req_mgr_device { + struct video_device *video; + struct v4l2_device *v4l2_dev; + bool subdev_nodes_created; + int count; + struct mutex dev_lock; + bool state; + int32_t open_cnt; + struct mutex cam_lock; + struct v4l2_fh *cam_eventq; + spinlock_t cam_eventq_lock; +}; + +#define CAM_REQ_MGR_GET_PAYLOAD_PTR(ev, type) \ + (type *)((char *)ev.u.data) + +int cam_req_mgr_notify_message(struct cam_req_mgr_message *msg, + uint32_t id, + uint32_t type); + +#endif /* _CAM_REQ_MGR_DEV_H_ */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h new file mode 100644 index 000000000000..40c9050afbb5 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_INTERFACE_H +#define _CAM_REQ_MGR_INTERFACE_H + +#include +#include +#include "cam_req_mgr_core_defs.h" +#include "cam_req_mgr_util.h" + +struct cam_req_mgr_trigger_notify; +struct cam_req_mgr_error_notify; +struct cam_req_mgr_add_request; +struct cam_req_mgr_device_info; +struct cam_req_mgr_core_dev_link_setup; +struct cam_req_mgr_apply_request; +struct cam_req_mgr_flush_request; +struct cam_req_mgr_link_evt_data; + +#define SKIP_NEXT_FRAME 0x100 + +/* Request Manager -- camera device driver interface */ +/** + * @brief: camera kernel drivers to cam req mgr communication + * + * @cam_req_mgr_notify_trigger: for device which generates trigger to inform CRM + * @cam_req_mgr_notify_err : device use this to inform about different errors + * @cam_req_mgr_add_req : to info CRm about new rqeuest received from + * userspace + */ +typedef int (*cam_req_mgr_notify_trigger)( + struct cam_req_mgr_trigger_notify *); +typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); +typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); + +/** + * @brief: cam req mgr to camera device drivers + * + * @cam_req_mgr_get_dev_info: to fetch details about device linked + * @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 cancel request + * cam_req_mgr_process_evt : generic events + */ +typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); +typedef int (*cam_req_mgr_link_setup)( + struct cam_req_mgr_core_dev_link_setup *); +typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); +typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); +typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); + +/** + * @brief : cam_req_mgr_crm_cb - func table + * + * @notify_trigger : payload for trigger indication event + * @notify_err : payload for different error occurred at device + * @add_req : payload to inform which device and what request is received + */ +struct cam_req_mgr_crm_cb { + cam_req_mgr_notify_trigger notify_trigger; + cam_req_mgr_notify_err notify_err; + cam_req_mgr_add_req add_req; +}; + +/** + * @brief : cam_req_mgr_kmd_ops - func table + * + * @get_dev_info : payload to fetch device details + * @link_setup : payload to establish link with device + * @apply_req : payload to apply request id on a device linked + * @flush_req : payload to flush request + * @process_evt : payload to generic event + */ +struct cam_req_mgr_kmd_ops { + cam_req_mgr_get_dev_info get_dev_info; + cam_req_mgr_link_setup link_setup; + cam_req_mgr_apply_req apply_req; + cam_req_mgr_flush_req flush_req; + cam_req_mgr_process_evt process_evt; +}; + +/** + * enum cam_pipeline_delay + * @brief : enumerator for different pipeline delays in camera + * + * @DELAY_0 : device processed settings on same frame + * @DELAY_1 : device processed settings after 1 frame + * @DELAY_2 : device processed settings after 2 frames + * @DELAY_MAX : maximum supported pipeline delay + */ +enum cam_pipeline_delay { + CAM_PIPELINE_DELAY_0, + CAM_PIPELINE_DELAY_1, + CAM_PIPELINE_DELAY_2, + CAM_PIPELINE_DELAY_MAX, +}; + +/** + * @CAM_TRIGGER_POINT_SOF : Trigger point for SOF + * @CAM_TRIGGER_POINT_EOF : Trigger point for EOF + */ +#define CAM_TRIGGER_POINT_SOF (1 << 0) +#define CAM_TRIGGER_POINT_EOF (1 << 1) + +/** + * enum cam_req_status + * @brief : enumerator for request status + * + * @SUCCESS : device processed settings successfully + * @FAILED : device processed settings failed + * @MAX : invalid status value + */ +enum cam_req_status { + CAM_REQ_STATUS_SUCCESS, + CAM_REQ_STATUS_FAILED, + CAM_REQ_STATUS_MAX, +}; + +/** + * enum cam_req_mgr_device_error + * @brief : enumerator for different errors occurred at device + * + * @NOT_FOUND : settings asked by request manager is not found + * @BUBBLE : device hit timing issue and is able to recover + * @FATAL : device is in bad shape and can not recover from error + * @PAGE_FAULT : Page fault while accessing memory + * @OVERFLOW : Bus Overflow for IFE/VFE + * @TIMEOUT : Timeout from cci or bus. + * @MAX : Invalid error value + */ +enum cam_req_mgr_device_error { + CRM_KMD_ERR_NOT_FOUND, + CRM_KMD_ERR_BUBBLE, + CRM_KMD_ERR_FATAL, + CRM_KMD_ERR_PAGE_FAULT, + CRM_KMD_ERR_OVERFLOW, + CRM_KMD_ERR_TIMEOUT, + CRM_KMD_ERR_MAX, +}; + +/** + * enum cam_req_mgr_device_id + * @brief : enumerator for different devices in subsystem + * + * @CAM_REQ_MGR : request manager itself + * @SENSOR : sensor device + * @FLASH : LED flash or dual LED device + * @ACTUATOR : lens mover + * @IFE : Image processing device + * @EXTERNAL_1 : third party device + * @EXTERNAL_2 : third party device + * @EXTERNAL_3 : third party device + * @MAX : invalid device id + */ +enum cam_req_mgr_device_id { + CAM_REQ_MGR_DEVICE, + CAM_REQ_MGR_DEVICE_SENSOR, + CAM_REQ_MGR_DEVICE_FLASH, + CAM_REQ_MGR_DEVICE_ACTUATOR, + CAM_REQ_MGR_DEVICE_IFE, + CAM_REQ_MGR_DEVICE_EXTERNAL_1, + CAM_REQ_MGR_DEVICE_EXTERNAL_2, + CAM_REQ_MGR_DEVICE_EXTERNAL_3, + CAM_REQ_MGR_DEVICE_ID_MAX, +}; + +/* Camera device driver to Req Mgr device interface */ + +/** + * enum cam_req_mgr_link_evt_type + * @CAM_REQ_MGR_LINK_EVT_ERR : error on the link from any of the + * connected devices + * @CAM_REQ_MGR_LINK_EVT_PAUSE : to pause the link + * @CAM_REQ_MGR_LINK_EVT_RESUME : resumes the link which was paused + * @CAM_REQ_MGR_LINK_EVT_SOF_FREEZE : request manager has detected an sof freeze + * @CAM_REQ_MGR_LINK_EVT_MAX : invalid event type + */ +enum cam_req_mgr_link_evt_type { + CAM_REQ_MGR_LINK_EVT_ERR, + CAM_REQ_MGR_LINK_EVT_PAUSE, + CAM_REQ_MGR_LINK_EVT_RESUME, + CAM_REQ_MGR_LINK_EVT_SOF_FREEZE, + CAM_REQ_MGR_LINK_EVT_MAX, +}; + +/** + * struct cam_req_mgr_trigger_notify + * @link_hdl : link identifier + * @dev_hdl : device handle which has sent this req id + * @frame_id : frame id for internal tracking + * @trigger : trigger point of this notification, CRM will send apply + * only to the devices which subscribe to this point. + */ +struct cam_req_mgr_trigger_notify { + int32_t link_hdl; + int32_t dev_hdl; + int64_t frame_id; + uint32_t trigger; +}; + +/** + * struct cam_req_mgr_error_notify + * @link_hdl : link identifier + * @dev_hdl : device handle which has sent this req id + * @req_id : req id which hit error + * @error : what error device hit while processing this req + */ +struct cam_req_mgr_error_notify { + int32_t link_hdl; + int32_t dev_hdl; + uint64_t req_id; + enum cam_req_mgr_device_error error; +}; + +/** + * struct cam_req_mgr_add_request + * @link_hdl : link identifier + * @dev_hdl : device handle which has sent this req id + * @req_id : req id which device is ready to process + * @skip_before_applying : before applying req mgr introduce bubble + * by not sending request to device/s. + * ex: IFE and Flash + */ +struct cam_req_mgr_add_request { + int32_t link_hdl; + int32_t dev_hdl; + uint64_t req_id; + uint32_t skip_before_applying; +}; + + +/* CRM to KMD devices */ +/** + * struct cam_req_mgr_device_info + * @dev_hdl : Input_param : device handle for reference + * @name : link link or unlink + * @dev_id : device id info + * @p_delay : delay between time settings applied and take effect + * @trigger : Trigger point for the client + * + */ +struct cam_req_mgr_device_info { + int32_t dev_hdl; + char name[256]; + enum cam_req_mgr_device_id dev_id; + enum cam_pipeline_delay p_delay; + uint32_t trigger; +}; + +/** + * struct cam_req_mgr_core_dev_link_setup + * @link_enable : link link or unlink + * @link_hdl : link identifier + * @dev_hdl : device handle for reference + * @max_delay : max pipeline delay on this link + * @crm_cb : callback funcs to communicate with req mgr + * @subscribe_event : the mask of trigger points this link subscribes + * + */ +struct cam_req_mgr_core_dev_link_setup { + int32_t link_enable; + int32_t link_hdl; + int32_t dev_hdl; + enum cam_pipeline_delay max_delay; + struct cam_req_mgr_crm_cb *crm_cb; + uint32_t subscribe_event; +}; + +/** + * struct cam_req_mgr_apply_request + * @link_hdl : link identifier + * @dev_hdl : device handle for cross check + * @request_id : request id settings to apply + * @report_if_bubble : report to crm if failure in applying + * @trigger_point : the trigger point of this apply + * + */ +struct cam_req_mgr_apply_request { + int32_t link_hdl; + int32_t dev_hdl; + uint64_t request_id; + int32_t report_if_bubble; + uint32_t trigger_point; +}; + +/** + * struct cam_req_mgr_flush_request + * @link_hdl : link identifier + * @dev_hdl : device handle for cross check + * @type : cancel request type flush all or a request + * @request_id : request id to cancel + * + */ +struct cam_req_mgr_flush_request { + int32_t link_hdl; + int32_t dev_hdl; + uint32_t type; + uint64_t req_id; +}; + +/** + * struct cam_req_mgr_event_data + * @link_hdl : link handle + * @req_id : request id + * + */ +struct cam_req_mgr_link_evt_data { + int32_t link_hdl; + int32_t dev_hdl; + uint64_t req_id; + + enum cam_req_mgr_link_evt_type evt_type; + union { + enum cam_req_mgr_device_error error; + } u; +}; + +/** + * struct cam_req_mgr_send_request + * @link_hdl : link identifier + * @idx : slot idx + * + */ +struct cam_req_mgr_send_request { + int32_t link_hdl; + struct cam_req_mgr_req_queue *in_q; +}; +#endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_timer.c b/drivers/cam_req_mgr/cam_req_mgr_timer.c new file mode 100644 index 000000000000..ba44534fa48d --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_timer.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_req_mgr_timer.h" +#include "cam_debug_util.h" + +void crm_timer_reset(struct cam_req_mgr_timer *crm_timer) +{ + if (!crm_timer) + return; + CAM_DBG(CAM_CRM, "Starting timer to fire in %d ms. (jiffies=%lu)\n", + crm_timer->expires, jiffies); + mod_timer(&crm_timer->sys_timer, + (jiffies + msecs_to_jiffies(crm_timer->expires))); +} + +void crm_timer_callback(struct timer_list *timer_data) +{ + struct cam_req_mgr_timer *timer = + container_of(timer_data, struct cam_req_mgr_timer, sys_timer); + if (!timer) { + CAM_ERR(CAM_CRM, "NULL timer"); + return; + } + CAM_DBG(CAM_CRM, "timer %pK parent %pK", timer, timer->parent); + crm_timer_reset(timer); +} + +void crm_timer_modify(struct cam_req_mgr_timer *crm_timer, + int32_t expires) +{ + CAM_DBG(CAM_CRM, "new time %d", expires); + if (crm_timer) { + crm_timer->expires = expires; + crm_timer_reset(crm_timer); + } +} + +int crm_timer_init(struct cam_req_mgr_timer **timer, + int32_t expires, void *parent, void (*timer_cb)(struct timer_list *)) +{ + int ret = 0; + struct cam_req_mgr_timer *crm_timer = NULL; + + CAM_DBG(CAM_CRM, "init timer %d %pK", expires, *timer); + if (*timer == NULL) { + if (g_cam_req_mgr_timer_cachep) { + crm_timer = kmem_cache_alloc(g_cam_req_mgr_timer_cachep, + __GFP_ZERO | GFP_KERNEL); + if (!crm_timer) { + ret = -ENOMEM; + goto end; + } + } + + else { + ret = -ENOMEM; + goto end; + } + + if (timer_cb != NULL) + crm_timer->timer_cb = timer_cb; + else + crm_timer->timer_cb = crm_timer_callback; + + crm_timer->expires = expires; + crm_timer->parent = parent; + timer_setup(&crm_timer->sys_timer, + crm_timer->timer_cb, 0); + crm_timer_reset(crm_timer); + *timer = crm_timer; + } else { + CAM_WARN(CAM_CRM, "Timer already exists!!"); + ret = -EINVAL; + } +end: + return ret; +} +void crm_timer_exit(struct cam_req_mgr_timer **crm_timer) +{ + CAM_DBG(CAM_CRM, "destroy timer %pK @ %pK", *crm_timer, crm_timer); + if (*crm_timer) { + del_timer_sync(&(*crm_timer)->sys_timer); + if (g_cam_req_mgr_timer_cachep) + kmem_cache_free(g_cam_req_mgr_timer_cachep, *crm_timer); + *crm_timer = NULL; + } +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_timer.h b/drivers/cam_req_mgr/cam_req_mgr_timer.h new file mode 100644 index 000000000000..9f9ba71a3879 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_timer.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_TIMER_H_ +#define _CAM_REQ_MGR_TIMER_H_ + +#include +#include + +#include "cam_req_mgr_core_defs.h" + +/** struct cam_req_mgr_timer + * @expires : timeout value for timer + * @sys_timer : system timer variable + * @parent : priv data - link pointer + * @timer_cb : callback func which will be called when timeout expires + */ +struct cam_req_mgr_timer { + int32_t expires; + struct timer_list sys_timer; + void *parent; + void (*timer_cb)(struct timer_list *timer_data); +}; + +/** + * crm_timer_modify() + * @brief : allows ser to modify expiry time. + * @timer : timer which will be reset to expires values + */ +void crm_timer_modify(struct cam_req_mgr_timer *crm_timer, + int32_t expires); + +/** + * crm_timer_reset() + * @brief : destroys the timer allocated. + * @timer : timer which will be reset to expires values + */ +void crm_timer_reset(struct cam_req_mgr_timer *timer); + +/** + * crm_timer_init() + * @brief : create a new general purpose timer. + * timer utility takes care of allocating memory and deleting + * @timer : double pointer to new timer allocated + * @expires : Timeout value to fire callback + * @parent : void pointer which caller can use for book keeping + * @timer_cb : caller can chose to use its own callback function when + * timer fires the timeout. If no value is set timer util + * will use default. + */ +int crm_timer_init(struct cam_req_mgr_timer **timer, + int32_t expires, void *parent, void (*timer_cb)(struct timer_list *)); + +/** + * crm_timer_exit() + * @brief : destroys the timer allocated. + * @timer : timer pointer which will be freed + */ +void crm_timer_exit(struct cam_req_mgr_timer **timer); + +extern struct kmem_cache *g_cam_req_mgr_timer_cachep; +#endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c new file mode 100644 index 000000000000..54ab1680b112 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__ + +#include +#include +#include +#include +#include +#include +#include +#include "cam_req_mgr_util.h" +#include "cam_debug_util.h" + +static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; +static DEFINE_SPINLOCK(hdl_tbl_lock); + +int cam_req_mgr_util_init(void) +{ + int rc = 0; + int bitmap_size; + static struct cam_req_mgr_util_hdl_tbl *hdl_tbl_local; + + if (hdl_tbl) { + rc = -EINVAL; + CAM_ERR(CAM_CRM, "Hdl_tbl is already present"); + goto hdl_tbl_check_failed; + } + + hdl_tbl_local = kzalloc(sizeof(*hdl_tbl), GFP_KERNEL); + if (!hdl_tbl_local) { + rc = -ENOMEM; + goto hdl_tbl_alloc_failed; + } + spin_lock_bh(&hdl_tbl_lock); + if (hdl_tbl) { + spin_unlock_bh(&hdl_tbl_lock); + rc = -EEXIST; + kfree(hdl_tbl_local); + goto hdl_tbl_check_failed; + } + hdl_tbl = hdl_tbl_local; + spin_unlock_bh(&hdl_tbl_lock); + + bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long); + hdl_tbl->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!hdl_tbl->bitmap) { + rc = -ENOMEM; + goto bitmap_alloc_fail; + } + hdl_tbl->bits = bitmap_size * BITS_PER_BYTE; + + return rc; + +bitmap_alloc_fail: + kfree(hdl_tbl); + hdl_tbl = NULL; +hdl_tbl_alloc_failed: +hdl_tbl_check_failed: + return rc; +} + +int cam_req_mgr_util_deinit(void) +{ + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR(CAM_CRM, "Hdl tbl is NULL"); + spin_unlock_bh(&hdl_tbl_lock); + return -EINVAL; + } + + kfree(hdl_tbl->bitmap); + hdl_tbl->bitmap = NULL; + kfree(hdl_tbl); + hdl_tbl = NULL; + spin_unlock_bh(&hdl_tbl_lock); + + return 0; +} + +int cam_req_mgr_util_free_hdls(void) +{ + int i = 0; + + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR(CAM_CRM, "Hdl tbl is NULL"); + spin_unlock_bh(&hdl_tbl_lock); + return -EINVAL; + } + + for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) { + if (hdl_tbl->hdl[i].state == HDL_ACTIVE) { + CAM_ERR(CAM_CRM, "Dev handle = %x session_handle = %x", + hdl_tbl->hdl[i].hdl_value, + hdl_tbl->hdl[i].session_hdl); + hdl_tbl->hdl[i].state = HDL_FREE; + clear_bit(i, hdl_tbl->bitmap); + } + } + bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES); + spin_unlock_bh(&hdl_tbl_lock); + + return 0; +} + +static int32_t cam_get_free_handle_index(void) +{ + int idx; + + idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits); + + if (idx >= CAM_REQ_MGR_MAX_HANDLES || idx < 0) + return -ENOSR; + + set_bit(idx, hdl_tbl->bitmap); + + return idx; +} + +int32_t cam_create_session_hdl(void *priv) +{ + int idx; + int rand = 0; + int32_t handle = 0; + + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR(CAM_CRM, "Hdl tbl is NULL"); + spin_unlock_bh(&hdl_tbl_lock); + return -EINVAL; + } + + idx = cam_get_free_handle_index(); + if (idx < 0) { + CAM_ERR(CAM_CRM, "Unable to create session handle"); + spin_unlock_bh(&hdl_tbl_lock); + return idx; + } + + get_random_bytes(&rand, CAM_REQ_MGR_RND1_BYTES); + handle = GET_DEV_HANDLE(rand, HDL_TYPE_SESSION, idx); + hdl_tbl->hdl[idx].session_hdl = handle; + hdl_tbl->hdl[idx].hdl_value = handle; + hdl_tbl->hdl[idx].type = HDL_TYPE_SESSION; + hdl_tbl->hdl[idx].state = HDL_ACTIVE; + hdl_tbl->hdl[idx].priv = priv; + hdl_tbl->hdl[idx].ops = NULL; + spin_unlock_bh(&hdl_tbl_lock); + + return handle; +} + +int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) +{ + int idx; + int rand = 0; + int32_t handle; + + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR(CAM_CRM, "Hdl tbl is NULL"); + spin_unlock_bh(&hdl_tbl_lock); + return -EINVAL; + } + + idx = cam_get_free_handle_index(); + if (idx < 0) { + CAM_ERR(CAM_CRM, "Unable to create device handle"); + spin_unlock_bh(&hdl_tbl_lock); + return idx; + } + + get_random_bytes(&rand, CAM_REQ_MGR_RND1_BYTES); + handle = GET_DEV_HANDLE(rand, HDL_TYPE_DEV, idx); + hdl_tbl->hdl[idx].session_hdl = hdl_data->session_hdl; + hdl_tbl->hdl[idx].hdl_value = handle; + hdl_tbl->hdl[idx].type = HDL_TYPE_DEV; + hdl_tbl->hdl[idx].state = HDL_ACTIVE; + hdl_tbl->hdl[idx].priv = hdl_data->priv; + hdl_tbl->hdl[idx].ops = hdl_data->ops; + spin_unlock_bh(&hdl_tbl_lock); + + pr_debug("%s: handle = %x", __func__, handle); + return handle; +} + +void *cam_get_device_priv(int32_t dev_hdl) +{ + int idx; + int type; + void *priv; + + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "Hdl tbl is NULL"); + goto device_priv_fail; + } + + idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); + if (idx >= CAM_REQ_MGR_MAX_HANDLES) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx"); + goto device_priv_fail; + } + + if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid state"); + goto device_priv_fail; + } + + type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl); + if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid type"); + goto device_priv_fail; + } + + if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid hdl"); + goto device_priv_fail; + } + + priv = hdl_tbl->hdl[idx].priv; + spin_unlock_bh(&hdl_tbl_lock); + + return priv; + +device_priv_fail: + spin_unlock_bh(&hdl_tbl_lock); + return NULL; +} + +void *cam_get_device_ops(int32_t dev_hdl) +{ + int idx; + int type; + void *ops; + + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR(CAM_CRM, "Hdl tbl is NULL"); + goto device_ops_fail; + } + + idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); + if (idx >= CAM_REQ_MGR_MAX_HANDLES) { + CAM_ERR(CAM_CRM, "Invalid idx"); + goto device_ops_fail; + } + + if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) { + CAM_ERR(CAM_CRM, "Invalid state"); + goto device_ops_fail; + } + + type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl); + if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) { + CAM_ERR(CAM_CRM, "Invalid type"); + goto device_ops_fail; + } + + if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) { + CAM_ERR(CAM_CRM, "Invalid hdl"); + goto device_ops_fail; + } + + ops = hdl_tbl->hdl[idx].ops; + spin_unlock_bh(&hdl_tbl_lock); + + return ops; + +device_ops_fail: + spin_unlock_bh(&hdl_tbl_lock); + return NULL; +} + +static int cam_destroy_hdl(int32_t dev_hdl, int dev_hdl_type) +{ + int idx; + int type; + + spin_lock_bh(&hdl_tbl_lock); + if (!hdl_tbl) { + CAM_ERR(CAM_CRM, "Hdl tbl is NULL"); + goto destroy_hdl_fail; + } + + idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); + if (idx >= CAM_REQ_MGR_MAX_HANDLES) { + CAM_ERR(CAM_CRM, "Invalid idx %d", idx); + goto destroy_hdl_fail; + } + + if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) { + CAM_ERR(CAM_CRM, "Invalid state"); + goto destroy_hdl_fail; + } + + type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl); + if (type != dev_hdl_type) { + CAM_ERR(CAM_CRM, "Invalid type %d, %d", type, dev_hdl_type); + goto destroy_hdl_fail; + } + + if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) { + CAM_ERR(CAM_CRM, "Invalid hdl"); + goto destroy_hdl_fail; + } + + hdl_tbl->hdl[idx].state = HDL_FREE; + hdl_tbl->hdl[idx].ops = NULL; + hdl_tbl->hdl[idx].priv = NULL; + clear_bit(idx, hdl_tbl->bitmap); + spin_unlock_bh(&hdl_tbl_lock); + + return 0; + +destroy_hdl_fail: + spin_unlock_bh(&hdl_tbl_lock); + return -EINVAL; +} + +int cam_destroy_device_hdl(int32_t dev_hdl) +{ + return cam_destroy_hdl(dev_hdl, HDL_TYPE_DEV); +} + +int cam_destroy_session_hdl(int32_t dev_hdl) +{ + return cam_destroy_hdl(dev_hdl, HDL_TYPE_SESSION); +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h new file mode 100644 index 000000000000..f22c6cbae8ef --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_UTIL_API_H_ +#define _CAM_REQ_MGR_UTIL_API_H_ + +#include +#include "cam_req_mgr_util_priv.h" + +/** + * state of a handle(session/device) + * @HDL_FREE: free handle + * @HDL_ACTIVE: active handles + */ +enum hdl_state { + HDL_FREE, + HDL_ACTIVE +}; + +/** + * handle type + * @HDL_TYPE_DEV: for device and link + * @HDL_TYPE_SESSION: for session + */ +enum hdl_type { + HDL_TYPE_DEV = 1, + HDL_TYPE_SESSION +}; + +/** + * struct handle + * @session_hdl: session handle + * @hdl_value: Allocated handle + * @type: session/device handle + * @state: free/used + * @ops: ops structure + * @priv: private data of a handle + */ +struct handle { + int32_t session_hdl; + uint32_t hdl_value; + enum hdl_type type; + enum hdl_state state; + void *ops; + void *priv; +}; + +/** + * struct cam_req_mgr_util_hdl_tbl + * @hdl: row of handles + * @bitmap: bit map to get free hdl row idx + * @bits: size of bit map in bits + */ +struct cam_req_mgr_util_hdl_tbl { + struct handle hdl[CAM_REQ_MGR_MAX_HANDLES]; + void *bitmap; + size_t bits; +}; + +/** + * cam_req_mgr_util APIs for KMD drivers and cam_req_mgr + * @session_hdl: session_hdl info + * @v4l2_sub_dev_flag: flag to create v4l2 sub device + * @media_entity_flag: flag for media entity + * @reserved: reserved field + * @ops: ops pointer for a device handle + * @priv: private data for a device handle + */ +struct cam_create_dev_hdl { + int32_t session_hdl; + int32_t v4l2_sub_dev_flag; + int32_t media_entity_flag; + int32_t reserved; + void *ops; + void *priv; +}; + +/** + * cam_create_session_hdl() - create a session handle + * @priv: private data for a session handle + * + * cam_req_mgr core calls this function to get + * a unique session handle. Returns a unique session + * handle + */ +int32_t cam_create_session_hdl(void *priv); + +/** + * cam_create_device_hdl() - create a device handle + * @hdl_data: session hdl, flags, ops and priv dara as input + * + * cam_req_mgr_core calls this function to get + * session and link handles + * KMD drivers calls this function to create + * a device handle. Returns a unique device handle + */ +int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data); + +/** + * cam_get_device_priv() - get private data of a handle + * @dev_hdl: handle for a session/link/device + * + * cam_req_mgr_core and KMD drivers use this function to + * get private data of a handle. Returns a private data + * structure pointer. + */ +void *cam_get_device_priv(int32_t dev_hdl); + +/** + * cam_get_device_ops() - get ops of a handle + * @dev_hdl: handle for a session/link/device + * + * cam_req_mgr_core and KMD drivers use this function to + * get ops of a handle. Returns a pointer to ops. + */ +void *cam_get_device_ops(int32_t dev_hdl); + +/** + * cam_destroy_device_hdl() - destroy device handle + * @dev_hdl: handle for a link/device. + * + * Returns success/failure + */ +int32_t cam_destroy_device_hdl(int32_t dev_hdl); + +/** + * cam_destroy_session_hdl() - destroy device handle + * @dev_hdl: handle for a session + * + * Returns success/failure + */ +int32_t cam_destroy_session_hdl(int32_t dev_hdl); + + +/* Internal functions */ +/** + * cam_req_mgr_util_init() - init function of cam_req_mgr_util + * + * This is called as part of probe function to initialize + * handle table, bitmap, locks + */ +int cam_req_mgr_util_init(void); + +/** + * cam_req_mgr_util_deinit() - deinit function of cam_req_mgr_util + * + * This function is called in case of probe failure + */ +int32_t cam_req_mgr_util_deinit(void); + +/** + * cam_req_mgr_util_free_hdls() - free handles in case of crash + * + * Called from cam_req_mgr_dev release function to make sure + * all data structures are cleaned to avoid leaks + * + * cam_req_mgr core can call this function at the end of + * camera to make sure all stale entries are printed and + * cleaned + */ +int32_t cam_req_mgr_util_free_hdls(void); + +#endif /* _CAM_REQ_MGR_UTIL_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_util_priv.h b/drivers/cam_req_mgr/cam_req_mgr_util_priv.h new file mode 100644 index 000000000000..075f5c34702d --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_util_priv.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_UTIL_PRIV_H_ +#define _CAM_REQ_MGR_UTIL_PRIV_H_ + +/** + * handle format: + * @bits (0-7): handle index + * @bits (8-11): handle type + * @bits (12-15): reserved + * @bits (16-23): random bits + * @bits (24-31): zeros + */ + +#define CAM_REQ_MGR_HDL_SIZE 32 +#define CAM_REQ_MGR_RND1_SIZE 8 +#define CAM_REQ_MGR_RVD_SIZE 4 +#define CAM_REQ_MGR_HDL_TYPE_SIZE 4 +#define CAM_REQ_MGR_HDL_IDX_SIZE 8 + +#define CAM_REQ_MGR_RND1_POS 24 +#define CAM_REQ_MGR_RVD_POS 16 +#define CAM_REQ_MGR_HDL_TYPE_POS 12 + +#define CAM_REQ_MGR_RND1_BYTES 1 + +#define CAM_REQ_MGR_HDL_TYPE_MASK ((1 << CAM_REQ_MGR_HDL_TYPE_SIZE) - 1) + +#define GET_DEV_HANDLE(rnd1, type, idx) \ + ((rnd1 << (CAM_REQ_MGR_RND1_POS - CAM_REQ_MGR_RND1_SIZE)) | \ + (0x0 << (CAM_REQ_MGR_RVD_POS - CAM_REQ_MGR_RVD_SIZE)) | \ + (type << (CAM_REQ_MGR_HDL_TYPE_POS - CAM_REQ_MGR_HDL_TYPE_SIZE)) | \ + (idx << (CAM_REQ_MGR_HDL_IDX_POS - CAM_REQ_MGR_HDL_IDX_SIZE))) \ + +#define CAM_REQ_MGR_GET_HDL_IDX(hdl) (hdl & CAM_REQ_MGR_HDL_IDX_MASK) +#define CAM_REQ_MGR_GET_HDL_TYPE(hdl) \ + ((hdl >> CAM_REQ_MGR_HDL_IDX_POS) & CAM_REQ_MGR_HDL_TYPE_MASK) + +#endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.c b/drivers/cam_req_mgr/cam_req_mgr_workq.c new file mode 100644 index 000000000000..29d98503f305 --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_req_mgr_workq.h" +#include "cam_debug_util.h" + +#define WORKQ_ACQUIRE_LOCK(workq, flags) {\ + if ((workq)->in_irq) \ + spin_lock_irqsave(&(workq)->lock_bh, (flags)); \ + else \ + spin_lock_bh(&(workq)->lock_bh); \ +} + +#define WORKQ_RELEASE_LOCK(workq, flags) {\ + if ((workq)->in_irq) \ + spin_unlock_irqrestore(&(workq)->lock_bh, (flags)); \ + else \ + spin_unlock_bh(&(workq)->lock_bh); \ +} + +struct crm_workq_task *cam_req_mgr_workq_get_task( + struct cam_req_mgr_core_workq *workq) +{ + struct crm_workq_task *task = NULL; + unsigned long flags = 0; + + if (!workq) + return NULL; + + WORKQ_ACQUIRE_LOCK(workq, flags); + if (list_empty(&workq->task.empty_head)) + goto end; + + task = list_first_entry(&workq->task.empty_head, + struct crm_workq_task, entry); + if (task) { + atomic_sub(1, &workq->task.free_cnt); + list_del_init(&task->entry); + } + +end: + WORKQ_RELEASE_LOCK(workq, flags); + + return task; +} + +static void cam_req_mgr_workq_put_task(struct crm_workq_task *task) +{ + struct cam_req_mgr_core_workq *workq = + (struct cam_req_mgr_core_workq *)task->parent; + unsigned long flags = 0; + + list_del_init(&task->entry); + task->cancel = 0; + task->process_cb = NULL; + task->priv = NULL; + WORKQ_ACQUIRE_LOCK(workq, flags); + list_add_tail(&task->entry, + &workq->task.empty_head); + atomic_add(1, &workq->task.free_cnt); + WORKQ_RELEASE_LOCK(workq, flags); +} + +/** + * cam_req_mgr_process_task() - Process the enqueued task + * @task: pointer to task workq thread shall process + */ +static int cam_req_mgr_process_task(struct crm_workq_task *task) +{ + struct cam_req_mgr_core_workq *workq = NULL; + + if (!task) + return -EINVAL; + + workq = (struct cam_req_mgr_core_workq *)task->parent; + if (task->process_cb) + task->process_cb(task->priv, task->payload); + else + CAM_WARN(CAM_CRM, "FATAL:no task handler registered for workq"); + cam_req_mgr_workq_put_task(task); + + return 0; +} + +/** + * cam_req_mgr_process_workq() - main loop handling + * @w: workqueue task pointer + */ +static void cam_req_mgr_process_workq(struct work_struct *w) +{ + struct cam_req_mgr_core_workq *workq = NULL; + struct crm_workq_task *task; + int32_t i = CRM_TASK_PRIORITY_0; + unsigned long flags = 0; + + if (!w) { + CAM_ERR(CAM_CRM, "NULL task pointer can not schedule"); + return; + } + workq = (struct cam_req_mgr_core_workq *) + container_of(w, struct cam_req_mgr_core_workq, work); + + while (i < CRM_TASK_PRIORITY_MAX) { + WORKQ_ACQUIRE_LOCK(workq, flags); + while (!list_empty(&workq->task.process_head[i])) { + task = list_first_entry(&workq->task.process_head[i], + struct crm_workq_task, entry); + atomic_sub(1, &workq->task.pending_cnt); + list_del_init(&task->entry); + WORKQ_RELEASE_LOCK(workq, flags); + cam_req_mgr_process_task(task); + CAM_DBG(CAM_CRM, "processed task %pK free_cnt %d", + task, atomic_read(&workq->task.free_cnt)); + WORKQ_ACQUIRE_LOCK(workq, flags); + } + WORKQ_RELEASE_LOCK(workq, flags); + i++; + } +} + +int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, + void *priv, int32_t prio) +{ + int rc = 0; + struct cam_req_mgr_core_workq *workq = NULL; + unsigned long flags = 0; + + if (!task) { + CAM_WARN(CAM_CRM, "NULL task pointer can not schedule"); + rc = -EINVAL; + goto end; + } + workq = (struct cam_req_mgr_core_workq *)task->parent; + if (!workq) { + CAM_DBG(CAM_CRM, "NULL workq pointer suspect mem corruption"); + rc = -EINVAL; + goto end; + } + + if (task->cancel == 1) { + cam_req_mgr_workq_put_task(task); + CAM_WARN(CAM_CRM, "task aborted and queued back to pool"); + rc = 0; + goto end; + } + task->priv = priv; + task->priority = + (prio < CRM_TASK_PRIORITY_MAX && prio >= CRM_TASK_PRIORITY_0) + ? prio : CRM_TASK_PRIORITY_0; + + WORKQ_ACQUIRE_LOCK(workq, flags); + if (!workq->job) { + rc = -EINVAL; + WORKQ_RELEASE_LOCK(workq, flags); + goto end; + } + + list_add_tail(&task->entry, + &workq->task.process_head[task->priority]); + + atomic_add(1, &workq->task.pending_cnt); + CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d", + task, atomic_read(&workq->task.pending_cnt)); + + queue_work(workq->job, &workq->work); + WORKQ_RELEASE_LOCK(workq, flags); +end: + return rc; +} + +int cam_req_mgr_workq_create(char *name, int32_t num_tasks, + struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq, + int flags) +{ + int32_t i, wq_flags = 0, max_active_tasks = 0; + struct crm_workq_task *task; + struct cam_req_mgr_core_workq *crm_workq = NULL; + char buf[128] = "crm_workq-"; + + if (!*workq) { + crm_workq = kzalloc(sizeof(struct cam_req_mgr_core_workq), + GFP_KERNEL); + if (crm_workq == NULL) + return -ENOMEM; + + wq_flags |= WQ_UNBOUND; + if (flags & CAM_WORKQ_FLAG_HIGH_PRIORITY) + wq_flags |= WQ_HIGHPRI; + + if (flags & CAM_WORKQ_FLAG_SERIAL) + max_active_tasks = 1; + + strlcat(buf, name, sizeof(buf)); + CAM_DBG(CAM_CRM, "create workque crm_workq-%s", name); + crm_workq->job = alloc_workqueue(buf, + wq_flags, max_active_tasks, NULL); + if (!crm_workq->job) { + kfree(crm_workq); + return -ENOMEM; + } + + /* Workq attributes initialization */ + INIT_WORK(&crm_workq->work, cam_req_mgr_process_workq); + spin_lock_init(&crm_workq->lock_bh); + CAM_DBG(CAM_CRM, "LOCK_DBG workq %s lock %pK", + name, &crm_workq->lock_bh); + + /* Task attributes initialization */ + atomic_set(&crm_workq->task.pending_cnt, 0); + atomic_set(&crm_workq->task.free_cnt, 0); + for (i = CRM_TASK_PRIORITY_0; i < CRM_TASK_PRIORITY_MAX; i++) + INIT_LIST_HEAD(&crm_workq->task.process_head[i]); + INIT_LIST_HEAD(&crm_workq->task.empty_head); + crm_workq->in_irq = in_irq; + crm_workq->task.num_task = num_tasks; + crm_workq->task.pool = 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", + sizeof(struct crm_workq_task) * + crm_workq->task.num_task); + kfree(crm_workq); + return -ENOMEM; + } + + for (i = 0; i < crm_workq->task.num_task; i++) { + task = &crm_workq->task.pool[i]; + task->parent = (void *)crm_workq; + /* Put all tasks in free pool */ + INIT_LIST_HEAD(&task->entry); + cam_req_mgr_workq_put_task(task); + } + *workq = crm_workq; + CAM_DBG(CAM_CRM, "free tasks %d", + atomic_read(&crm_workq->task.free_cnt)); + } + + return 0; +} + +void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq) +{ + unsigned long flags = 0; + struct workqueue_struct *job; + + CAM_DBG(CAM_CRM, "destroy workque %pK", crm_workq); + if (*crm_workq) { + WORKQ_ACQUIRE_LOCK(*crm_workq, flags); + if ((*crm_workq)->job) { + job = (*crm_workq)->job; + (*crm_workq)->job = NULL; + WORKQ_RELEASE_LOCK(*crm_workq, flags); + destroy_workqueue(job); + } else { + WORKQ_RELEASE_LOCK(*crm_workq, flags); + } + + /* Destroy workq payload data */ + kfree((*crm_workq)->task.pool[0].payload); + (*crm_workq)->task.pool[0].payload = NULL; + kfree((*crm_workq)->task.pool); + kfree(*crm_workq); + *crm_workq = NULL; + } +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.h b/drivers/cam_req_mgr/cam_req_mgr_workq.h new file mode 100644 index 000000000000..f938710b69ae --- /dev/null +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_REQ_MGR_WORKQ_H_ +#define _CAM_REQ_MGR_WORKQ_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "cam_req_mgr_core.h" + +/* Flag to create a high priority workq */ +#define CAM_WORKQ_FLAG_HIGH_PRIORITY (1 << 0) + +/* + * This flag ensures only one task from a given + * workq will execute at any given point on any + * given CPU. + */ +#define CAM_WORKQ_FLAG_SERIAL (1 << 1) + +/* Task priorities, lower the number higher the priority*/ +enum crm_task_priority { + CRM_TASK_PRIORITY_0, + CRM_TASK_PRIORITY_1, + CRM_TASK_PRIORITY_MAX, +}; + +/* workqueue will be used from irq context or not */ +enum crm_workq_context { + CRM_WORKQ_USAGE_NON_IRQ, + CRM_WORKQ_USAGE_IRQ, + CRM_WORKQ_USAGE_INVALID, +}; + +/** struct crm_workq_task + * @priority : caller can assign priority to task based on type. + * @payload : depending of user of task this payload type will change + * @process_cb : registered callback called by workq when task enqueued is + * ready for processing in workq thread context + * @parent : workq's parent is link which is enqqueing taks to this workq + * @entry : list head of this list entry is worker's empty_head + * @cancel : if caller has got free task from pool but wants to abort + * or put back without using it + * @priv : when task is enqueuer caller can attach priv along which + * it will get in process callback + * @ret : return value in future to use for blocking calls + */ +struct crm_workq_task { + int32_t priority; + void *payload; + int32_t (*process_cb)(void *priv, void *data); + void *parent; + struct list_head entry; + uint8_t cancel; + void *priv; + int32_t ret; +}; + +/** struct cam_req_mgr_core_workq + * @work : work token used by workqueue + * @job : workqueue internal job struct + * task - + * @lock_bh : lock for task structs + * @in_irq : set true if workque can be used in irq context + * @free_cnt : num of free/available tasks + * @empty_head : list head of available taska which can be used + * or acquired in order to enqueue a task to workq + * @pool : pool of tasks used for handling events in workq context + * @num_task : size of tasks pool + * - + */ +struct cam_req_mgr_core_workq { + struct work_struct work; + struct workqueue_struct *job; + spinlock_t lock_bh; + uint32_t in_irq; + + /* tasks */ + struct { + struct mutex lock; + atomic_t pending_cnt; + atomic_t free_cnt; + + struct list_head process_head[CRM_TASK_PRIORITY_MAX]; + struct list_head empty_head; + struct crm_workq_task *pool; + uint32_t num_task; + } task; +}; + +/** + * cam_req_mgr_workq_create() + * @brief : create a workqueue + * @name : Name of the workque to be allocated, it is combination + * of session handle and link handle + * @num_task : Num_tasks to be allocated for workq + * @workq : Double pointer worker + * @in_irq : Set to one if workq might be used in irq context + * @flags : Bitwise OR of Flags for workq behavior. + * e.g. CAM_REQ_MGR_WORKQ_HIGH_PRIORITY | CAM_REQ_MGR_WORKQ_SERIAL + * This function will allocate and create workqueue and pass + * the workq pointer to caller. + */ +int cam_req_mgr_workq_create(char *name, int32_t num_tasks, + struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq, + int flags); + +/** + * cam_req_mgr_workq_destroy() + * @brief: destroy workqueue + * @workq: pointer to worker data struct + * this function will destroy workqueue and clean up resources + * associated with worker such as tasks. + */ +void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **workq); + +/** + * cam_req_mgr_workq_enqueue_task() + * @brief: Enqueue task in worker queue + * @task : task to be processed by worker + * @priv : clients private data + * @prio : task priority + * process callback func + */ +int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, + void *priv, int32_t prio); + +/** + * cam_req_mgr_workq_get_task() + * @brief: Returns empty task pointer for use + * @workq: workque used for processing + */ +struct crm_workq_task *cam_req_mgr_workq_get_task( + struct cam_req_mgr_core_workq *workq); + +#endif diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h new file mode 100644 index 000000000000..385643d5e532 --- /dev/null +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SUBDEV_H_ +#define _CAM_SUBDEV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#define CAM_SUBDEVICE_EVENT_MAX 30 + +/** + * struct cam_subdev - describes a camera sub-device + * + * @pdev: Pointer to the platform device + * @sd: V4l2 subdevice + * @ops: V4l2 subdecie operations + * @internal_ops: V4l2 subdevice internal operations + * @name: Name of the sub-device. Please notice that the name + * must be unique. + * @sd_flags: Subdev flags. Can be: + * %V4L2_SUBDEV_FL_HAS_DEVNODE - Set this flag if + * this subdev needs a device node. + * %V4L2_SUBDEV_FL_HAS_EVENTS - Set this flag if + * this subdev generates events. + * @token: Pointer to cookie of the client driver + * @ent_function: Media entity function type. Can be: + * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. + * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. + * + * Each instance of a subdev driver should create this struct, either + * stand-alone or embedded in a larger struct. This structure should be + * initialized/registered by cam_register_subdev + * + */ +struct cam_subdev { + struct platform_device *pdev; + struct v4l2_subdev sd; + const struct v4l2_subdev_ops *ops; + const struct v4l2_subdev_internal_ops *internal_ops; + char *name; + u32 sd_flags; + void *token; + u32 ent_function; +}; + +/** + * cam_subdev_probe() + * + * @brief: Camera Subdevice node probe function for v4l2 setup + * + * @sd: Camera subdevice object + * @name: Name of the subdevice node + * @dev_type: Subdevice node type + * + */ +int cam_subdev_probe(struct cam_subdev *sd, struct platform_device *pdev, + char *name, uint32_t dev_type); + +/** + * cam_subdev_remove() + * + * @brief: Called when subdevice node is unloaded + * + * @sd: Camera subdevice node object + * + */ +int cam_subdev_remove(struct cam_subdev *sd); + +/** + * cam_register_subdev_fops() + * + * @brief: This common utility function assigns subdev ops + * + * @fops: v4l file operations + */ +void cam_register_subdev_fops(struct v4l2_file_operations *fops); + +/** + * cam_register_subdev() + * + * @brief: This is the common utility function to be called by each camera + * subdevice node when it tries to register itself to the camera + * request manager + * + * @sd: Pointer to struct cam_subdev. + */ +int cam_register_subdev(struct cam_subdev *sd); + +/** + * cam_unregister_subdev() + * + * @brief: This is the common utility function to be called by each camera + * subdevice node when it tries to unregister itself from the + * camera request manger + * + * @sd: Pointer to struct cam_subdev. + */ +int cam_unregister_subdev(struct cam_subdev *sd); + +#endif /* _CAM_SUBDEV_H_ */ diff --git a/drivers/cam_sensor_module/Makefile b/drivers/cam_sensor_module/Makefile new file mode 100644 index 000000000000..6925b3aba80f --- /dev/null +++ b/drivers/cam_sensor_module/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_res_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_utils/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cci/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/ diff --git a/drivers/cam_sensor_module/cam_actuator/Makefile b/drivers/cam_sensor_module/cam_actuator/Makefile new file mode 100644 index 000000000000..a51b8fea65bb --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator_dev.o cam_actuator_core.o cam_actuator_soc.o diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c new file mode 100644 index 000000000000..c609b8f85015 --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -0,0 +1,981 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "cam_actuator_core.h" +#include "cam_sensor_util.h" +#include "cam_trace.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) +{ + int rc = 0; + + power_info->power_setting_size = 1; + power_info->power_setting = + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_setting) + return -ENOMEM; + + power_info->power_setting[0].seq_type = SENSOR_VAF; + power_info->power_setting[0].seq_val = CAM_VAF; + power_info->power_setting[0].config_val = 1; + power_info->power_setting[0].delay = 2; + + power_info->power_down_setting_size = 1; + power_info->power_down_setting = + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_down_setting) { + rc = -ENOMEM; + goto free_power_settings; + } + + power_info->power_down_setting[0].seq_type = SENSOR_VAF; + power_info->power_down_setting[0].seq_val = CAM_VAF; + power_info->power_down_setting[0].config_val = 0; + + return rc; + +free_power_settings: + kfree(power_info->power_setting); + power_info->power_setting = NULL; + power_info->power_setting_size = 0; + return rc; +} + +static int32_t cam_actuator_power_up(struct cam_actuator_ctrl_t *a_ctrl) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = + &a_ctrl->soc_info; + struct cam_actuator_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + soc_private = + (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + + if ((power_info->power_setting == NULL) && + (power_info->power_down_setting == NULL)) { + CAM_INFO(CAM_ACTUATOR, + "Using default power settings"); + rc = cam_actuator_construct_default_power_setting(power_info); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Construct default actuator power setting failed."); + return rc; + } + } + + /* Parse and fill vreg params for power up settings */ + rc = msm_camera_fill_vreg_params( + &a_ctrl->soc_info, + power_info->power_setting, + power_info->power_setting_size); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "failed to fill vreg params for power up rc:%d", rc); + return rc; + } + + /* Parse and fill vreg params for power down settings*/ + rc = msm_camera_fill_vreg_params( + &a_ctrl->soc_info, + power_info->power_down_setting, + power_info->power_down_setting_size); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "failed to fill vreg params power down rc:%d", rc); + return rc; + } + + power_info->dev = soc_info->dev; + + rc = cam_sensor_core_power_up(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "failed in actuator power up rc %d", rc); + return rc; + } + + rc = camera_io_init(&a_ctrl->io_master_info); + if (rc < 0) + CAM_ERR(CAM_ACTUATOR, "cci init failed: rc: %d", rc); + + return rc; +} + +static int32_t cam_actuator_power_down(struct cam_actuator_ctrl_t *a_ctrl) +{ + int32_t rc = 0; + struct cam_sensor_power_ctrl_t *power_info; + struct cam_hw_soc_info *soc_info = &a_ctrl->soc_info; + struct cam_actuator_soc_private *soc_private; + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "failed: a_ctrl %pK", a_ctrl); + return -EINVAL; + } + + soc_private = + (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + soc_info = &a_ctrl->soc_info; + + if (!power_info) { + CAM_ERR(CAM_ACTUATOR, "failed: power_info %pK", power_info); + return -EINVAL; + } + rc = cam_sensor_util_power_down(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_ACTUATOR, "power down the core is failed:%d", rc); + return rc; + } + + camera_io_release(&a_ctrl->io_master_info); + + return rc; +} + +static int32_t cam_actuator_i2c_modes_util( + struct camera_io_master *io_master_info, + struct i2c_settings_list *i2c_list) +{ + int32_t rc = 0; + uint32_t i, size; + + if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) { + rc = camera_io_dev_write(io_master_info, + &(i2c_list->i2c_settings)); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed to random write I2C settings: %d", + rc); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + rc = camera_io_dev_write_continuous( + io_master_info, + &(i2c_list->i2c_settings), + 0); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed to seq write I2C settings: %d", + rc); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_BURST) { + rc = camera_io_dev_write_continuous( + io_master_info, + &(i2c_list->i2c_settings), + 1); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed to burst write I2C settings: %d", + rc); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { + size = i2c_list->i2c_settings.size; + for (i = 0; i < size; i++) { + rc = camera_io_dev_poll( + io_master_info, + i2c_list->i2c_settings.reg_setting[i].reg_addr, + i2c_list->i2c_settings.reg_setting[i].reg_data, + i2c_list->i2c_settings.reg_setting[i].data_mask, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.reg_setting[i].delay); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "i2c poll apply setting Fail: %d", rc); + return rc; + } + } + } + + return rc; +} + +int32_t cam_actuator_slaveInfo_pkt_parser(struct cam_actuator_ctrl_t *a_ctrl, + uint32_t *cmd_buf, size_t len) +{ + int32_t rc = 0; + struct cam_cmd_i2c_info *i2c_info; + + if (!a_ctrl || !cmd_buf || (len < sizeof(struct cam_cmd_i2c_info))) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args"); + return -EINVAL; + } + + i2c_info = (struct cam_cmd_i2c_info *)cmd_buf; + if (a_ctrl->io_master_info.master_type == CCI_MASTER) { + a_ctrl->io_master_info.cci_client->cci_i2c_master = + a_ctrl->cci_i2c_master; + a_ctrl->io_master_info.cci_client->i2c_freq_mode = + i2c_info->i2c_freq_mode; + a_ctrl->io_master_info.cci_client->sid = + i2c_info->slave_addr >> 1; + CAM_DBG(CAM_ACTUATOR, "Slave addr: 0x%x Freq Mode: %d", + i2c_info->slave_addr, i2c_info->i2c_freq_mode); + } else if (a_ctrl->io_master_info.master_type == I2C_MASTER) { + a_ctrl->io_master_info.client->addr = i2c_info->slave_addr; + CAM_DBG(CAM_ACTUATOR, "Slave addr: 0x%x", i2c_info->slave_addr); + } else { + CAM_ERR(CAM_ACTUATOR, "Invalid Master type: %d", + a_ctrl->io_master_info.master_type); + rc = -EINVAL; + } + + return rc; +} + +int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl, + struct i2c_settings_array *i2c_set) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0; + + if (a_ctrl == NULL || i2c_set == NULL) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args"); + return -EINVAL; + } + + if (i2c_set->is_settings_valid != 1) { + CAM_ERR(CAM_ACTUATOR, " Invalid settings"); + return -EINVAL; + } + + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + rc = cam_actuator_i2c_modes_util( + &(a_ctrl->io_master_info), + i2c_list); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed to apply settings: %d", + rc); + } else { + CAM_DBG(CAM_ACTUATOR, + "Success:request ID: %d", + i2c_set->request_id); + } + } + + return rc; +} + +int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply) +{ + int32_t rc = 0, request_id, del_req_id; + struct cam_actuator_ctrl_t *a_ctrl = NULL; + + if (!apply) { + CAM_ERR(CAM_ACTUATOR, "Invalid Input Args"); + return -EINVAL; + } + + a_ctrl = (struct cam_actuator_ctrl_t *) + cam_get_device_priv(apply->dev_hdl); + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Device data is NULL"); + return -EINVAL; + } + request_id = apply->request_id % MAX_PER_FRAME_ARRAY; + + trace_cam_apply_req("Actuator", apply->request_id); + + CAM_DBG(CAM_ACTUATOR, "Request Id: %lld", apply->request_id); + mutex_lock(&(a_ctrl->actuator_mutex)); + if ((apply->request_id == + a_ctrl->i2c_data.per_frame[request_id].request_id) && + (a_ctrl->i2c_data.per_frame[request_id].is_settings_valid) + == 1) { + rc = cam_actuator_apply_settings(a_ctrl, + &a_ctrl->i2c_data.per_frame[request_id]); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed in applying the request: %lld\n", + apply->request_id); + goto release_mutex; + } + } + del_req_id = (request_id + + MAX_PER_FRAME_ARRAY - MAX_SYSTEM_PIPELINE_DELAY) % + MAX_PER_FRAME_ARRAY; + + if (apply->request_id > + a_ctrl->i2c_data.per_frame[del_req_id].request_id) { + a_ctrl->i2c_data.per_frame[del_req_id].request_id = 0; + rc = delete_request(&a_ctrl->i2c_data.per_frame[del_req_id]); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Fail deleting the req: %d err: %d\n", + del_req_id, rc); + goto release_mutex; + } + } else { + CAM_DBG(CAM_ACTUATOR, "No Valid Req to clean Up"); + } + +release_mutex: + mutex_unlock(&(a_ctrl->actuator_mutex)); + return rc; +} + +int32_t cam_actuator_establish_link( + struct cam_req_mgr_core_dev_link_setup *link) +{ + struct cam_actuator_ctrl_t *a_ctrl = NULL; + + if (!link) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args"); + return -EINVAL; + } + + a_ctrl = (struct cam_actuator_ctrl_t *) + cam_get_device_priv(link->dev_hdl); + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Device data is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + if (link->link_enable) { + a_ctrl->bridge_intf.link_hdl = link->link_hdl; + a_ctrl->bridge_intf.crm_cb = link->crm_cb; + } else { + a_ctrl->bridge_intf.link_hdl = -1; + a_ctrl->bridge_intf.crm_cb = NULL; + } + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + +static void cam_actuator_update_req_mgr( + struct cam_actuator_ctrl_t *a_ctrl, + struct cam_packet *csl_packet) +{ + struct cam_req_mgr_add_request add_req; + + add_req.link_hdl = a_ctrl->bridge_intf.link_hdl; + add_req.req_id = csl_packet->header.request_id; + add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl; + add_req.skip_before_applying = 0; + + if (a_ctrl->bridge_intf.crm_cb && + a_ctrl->bridge_intf.crm_cb->add_req) { + a_ctrl->bridge_intf.crm_cb->add_req(&add_req); + CAM_DBG(CAM_ACTUATOR, "Request Id: %lld added to CRM", + add_req.req_id); + } else { + CAM_ERR(CAM_ACTUATOR, "Can't add Request ID: %lld to CRM", + csl_packet->header.request_id); + } +} + +int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info) +{ + if (!info) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args"); + return -EINVAL; + } + + info->dev_id = CAM_REQ_MGR_DEVICE_ACTUATOR; + strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name)); + info->p_delay = 1; + info->trigger = CAM_TRIGGER_POINT_SOF; + + return 0; +} + +int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, + void *arg) +{ + int32_t rc = 0; + 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; + struct cam_config_dev_cmd config; + struct i2c_data_settings *i2c_data = NULL; + struct i2c_settings_array *i2c_reg_settings = NULL; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_actuator_soc_private *soc_private = NULL; + struct cam_sensor_power_ctrl_t *power_info = NULL; + + if (!a_ctrl || !arg) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args"); + return -EINVAL; + } + + soc_private = + (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private; + + power_info = &soc_private->power_info; + + ioctl_ctrl = (struct cam_control *)arg; + if (copy_from_user(&config, + u64_to_user_ptr(ioctl_ctrl->handle), + sizeof(config))) + return -EFAULT; + rc = cam_mem_get_cpu_buf(config.packet_handle, + &generic_pkt_ptr, &len_of_buff); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %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_ACTUATOR, + "Inval cam_packet strut size: %zu, len_of_buff: %zu", + sizeof(struct cam_packet), len_of_buff); + rc = -EINVAL; + goto end; + } + + 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 end; + } + + CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code); + + if ((csl_packet->header.op_code & 0xFFFFFF) != + CAM_ACTUATOR_PACKET_OPCODE_INIT && + csl_packet->header.request_id <= a_ctrl->last_flush_req + && a_ctrl->last_flush_req != 0) { + CAM_DBG(CAM_ACTUATOR, + "reject request %lld, last request to flush %lld", + csl_packet->header.request_id, a_ctrl->last_flush_req); + rc = -EINVAL; + goto end; + } + + if (csl_packet->header.request_id > a_ctrl->last_flush_req) + a_ctrl->last_flush_req = 0; + + switch (csl_packet->header.op_code & 0xFFFFFF) { + case CAM_ACTUATOR_PACKET_OPCODE_INIT: + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + /* Loop through multiple command buffers */ + for (i = 0; i < csl_packet->num_cmd_buf; i++) { + total_cmd_buf_in_bytes = cmd_desc[i].length; + if (!total_cmd_buf_in_bytes) + continue; + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &generic_ptr, &len_of_buff); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf"); + goto end; + } + cmd_buf = (uint32_t *)generic_ptr; + if (!cmd_buf) { + CAM_ERR(CAM_ACTUATOR, "invalid cmd buf"); + rc = -EINVAL; + goto end; + } + 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 end; + } + 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: + CAM_DBG(CAM_ACTUATOR, + "Received slave info buffer"); + rc = cam_actuator_slaveInfo_pkt_parser( + a_ctrl, cmd_buf, remain_len); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed to parse slave info: %d", rc); + goto end; + } + break; + case CAMERA_SENSOR_CMD_TYPE_PWR_UP: + case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN: + CAM_DBG(CAM_ACTUATOR, + "Received power settings buffer"); + rc = cam_sensor_update_power_settings( + cmd_buf, + total_cmd_buf_in_bytes, + power_info, remain_len); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "Failed:parse power settings: %d", + rc); + goto end; + } + break; + default: + CAM_DBG(CAM_ACTUATOR, + "Received initSettings buffer"); + i2c_data = &(a_ctrl->i2c_data); + i2c_reg_settings = + &i2c_data->init_settings; + + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + rc = cam_sensor_i2c_command_parser( + &a_ctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed:parse init settings: %d", + rc); + goto end; + } + break; + } + } + + if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) { + rc = cam_actuator_power_up(a_ctrl); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + " Actuator Power up failed"); + goto end; + } + a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG; + } + + rc = cam_actuator_apply_settings(a_ctrl, + &a_ctrl->i2c_data.init_settings); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings"); + goto end; + } + + /* Delete the request even if the apply is failed */ + rc = delete_request(&a_ctrl->i2c_data.init_settings); + if (rc < 0) { + CAM_WARN(CAM_ACTUATOR, + "Fail in deleting the Init settings"); + rc = 0; + } + break; + case CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS: + if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_ACTUATOR, + "Not in right state to move lens: %d", + a_ctrl->cam_act_state); + goto end; + } + a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_NOW; + + i2c_data = &(a_ctrl->i2c_data); + i2c_reg_settings = &i2c_data->init_settings; + + i2c_data->init_settings.request_id = + csl_packet->header.request_id; + i2c_reg_settings->is_settings_valid = 1; + offset = (uint32_t *)&csl_packet->payload; + offset += csl_packet->cmd_buf_offset / sizeof(uint32_t); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser( + &a_ctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Auto move lens parsing failed: %d", rc); + goto end; + } + cam_actuator_update_req_mgr(a_ctrl, csl_packet); + break; + case CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS: + if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_ACTUATOR, + "Not in right state to move lens: %d", + a_ctrl->cam_act_state); + goto end; + } + + a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_LATER; + i2c_data = &(a_ctrl->i2c_data); + i2c_reg_settings = &i2c_data->per_frame[ + csl_packet->header.request_id % MAX_PER_FRAME_ARRAY]; + + i2c_reg_settings->request_id = + csl_packet->header.request_id; + i2c_reg_settings->is_settings_valid = 1; + offset = (uint32_t *)&csl_packet->payload; + offset += csl_packet->cmd_buf_offset / sizeof(uint32_t); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser( + &a_ctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Manual move lens parsing failed: %d", rc); + goto end; + } + + cam_actuator_update_req_mgr(a_ctrl, csl_packet); + break; + case CAM_PKT_NOP_OPCODE: + if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) { + CAM_WARN(CAM_ACTUATOR, + "Received NOP packets in invalid state: %d", + a_ctrl->cam_act_state); + rc = -EINVAL; + goto end; + } + 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 end; + } + +end: + return rc; +} + +void cam_actuator_shutdown(struct cam_actuator_ctrl_t *a_ctrl) +{ + int rc = 0; + struct cam_actuator_soc_private *soc_private = + (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = + &soc_private->power_info; + + if (a_ctrl->cam_act_state == CAM_ACTUATOR_INIT) + return; + + if (a_ctrl->cam_act_state >= CAM_ACTUATOR_CONFIG) { + rc = cam_actuator_power_down(a_ctrl); + if (rc < 0) + CAM_ERR(CAM_ACTUATOR, "Actuator Power down failed"); + a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE; + } + + if (a_ctrl->cam_act_state >= CAM_ACTUATOR_ACQUIRE) { + rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_ACTUATOR, "destroying dhdl failed"); + a_ctrl->bridge_intf.device_hdl = -1; + a_ctrl->bridge_intf.link_hdl = -1; + a_ctrl->bridge_intf.session_hdl = -1; + } + + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_setting_size = 0; + power_info->power_down_setting_size = 0; + + a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; +} + +int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, + void *arg) +{ + int rc = 0; + struct cam_control *cmd = (struct cam_control *)arg; + struct cam_actuator_soc_private *soc_private = NULL; + struct cam_sensor_power_ctrl_t *power_info = NULL; + + if (!a_ctrl || !cmd) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args"); + return -EINVAL; + } + + soc_private = + (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private; + + power_info = &soc_private->power_info; + + if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_ACTUATOR, "Invalid handle type: %d", + cmd->handle_type); + return -EINVAL; + } + + CAM_DBG(CAM_ACTUATOR, "Opcode to Actuator: %d", cmd->op_code); + + mutex_lock(&(a_ctrl->actuator_mutex)); + switch (cmd->op_code) { + case CAM_ACQUIRE_DEV: { + struct cam_sensor_acquire_dev actuator_acq_dev; + struct cam_create_dev_hdl bridge_params; + + if (a_ctrl->bridge_intf.device_hdl != -1) { + CAM_ERR(CAM_ACTUATOR, "Device is already acquired"); + rc = -EINVAL; + goto release_mutex; + } + rc = copy_from_user(&actuator_acq_dev, + u64_to_user_ptr(cmd->handle), + sizeof(actuator_acq_dev)); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "Failed Copying from user\n"); + goto release_mutex; + } + + bridge_params.session_hdl = actuator_acq_dev.session_handle; + bridge_params.ops = &a_ctrl->bridge_intf.ops; + bridge_params.v4l2_sub_dev_flag = 0; + bridge_params.media_entity_flag = 0; + bridge_params.priv = a_ctrl; + + actuator_acq_dev.device_handle = + cam_create_device_hdl(&bridge_params); + a_ctrl->bridge_intf.device_hdl = actuator_acq_dev.device_handle; + a_ctrl->bridge_intf.session_hdl = + actuator_acq_dev.session_handle; + + CAM_DBG(CAM_ACTUATOR, "Device Handle: %d", + actuator_acq_dev.device_handle); + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &actuator_acq_dev, + sizeof(struct cam_sensor_acquire_dev))) { + CAM_ERR(CAM_ACTUATOR, "Failed Copy to User"); + rc = -EFAULT; + goto release_mutex; + } + + a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE; + } + break; + case CAM_RELEASE_DEV: { + if (a_ctrl->cam_act_state == CAM_ACTUATOR_START) { + rc = -EINVAL; + CAM_WARN(CAM_ACTUATOR, + "Cant release actuator: in start state"); + goto release_mutex; + } + + if (a_ctrl->cam_act_state == CAM_ACTUATOR_CONFIG) { + rc = cam_actuator_power_down(a_ctrl); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Actuator Power down failed"); + goto release_mutex; + } + } + + if (a_ctrl->bridge_intf.device_hdl == -1) { + CAM_ERR(CAM_ACTUATOR, "link hdl: %d device hdl: %d", + a_ctrl->bridge_intf.device_hdl, + a_ctrl->bridge_intf.link_hdl); + rc = -EINVAL; + goto release_mutex; + } + + if (a_ctrl->bridge_intf.link_hdl != -1) { + CAM_ERR(CAM_ACTUATOR, + "Device [%d] still active on link 0x%x", + a_ctrl->cam_act_state, + a_ctrl->bridge_intf.link_hdl); + rc = -EAGAIN; + goto release_mutex; + } + + rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_ACTUATOR, "destroying the device hdl"); + a_ctrl->bridge_intf.device_hdl = -1; + a_ctrl->bridge_intf.link_hdl = -1; + a_ctrl->bridge_intf.session_hdl = -1; + a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; + a_ctrl->last_flush_req = 0; + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_down_setting_size = 0; + power_info->power_setting_size = 0; + } + break; + case CAM_QUERY_CAP: { + struct cam_actuator_query_cap actuator_cap = {0}; + + actuator_cap.slot_info = a_ctrl->soc_info.index; + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &actuator_cap, + sizeof(struct cam_actuator_query_cap))) { + CAM_ERR(CAM_ACTUATOR, "Failed Copy to User"); + rc = -EFAULT; + goto release_mutex; + } + } + break; + case CAM_START_DEV: { + if (a_ctrl->cam_act_state != CAM_ACTUATOR_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_ACTUATOR, + "Not in right state to start : %d", + a_ctrl->cam_act_state); + goto release_mutex; + } + a_ctrl->cam_act_state = CAM_ACTUATOR_START; + a_ctrl->last_flush_req = 0; + } + break; + case CAM_STOP_DEV: { + struct i2c_settings_array *i2c_set = NULL; + int i; + + if (a_ctrl->cam_act_state != CAM_ACTUATOR_START) { + rc = -EINVAL; + CAM_WARN(CAM_ACTUATOR, + "Not in right state to stop : %d", + a_ctrl->cam_act_state); + goto release_mutex; + } + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(a_ctrl->i2c_data.per_frame[i]); + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + } + } + a_ctrl->last_flush_req = 0; + a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG; + } + break; + case CAM_CONFIG_DEV: { + a_ctrl->setting_apply_state = + ACT_APPLY_SETTINGS_LATER; + rc = cam_actuator_i2c_pkt_parse(a_ctrl, arg); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "Failed in actuator Parsing"); + goto release_mutex; + } + + if (a_ctrl->setting_apply_state == + ACT_APPLY_SETTINGS_NOW) { + rc = cam_actuator_apply_settings(a_ctrl, + &a_ctrl->i2c_data.init_settings); + if (rc < 0) + CAM_ERR(CAM_ACTUATOR, + "Cannot apply Update settings"); + + /* Delete the request even if the apply is failed */ + rc = delete_request(&a_ctrl->i2c_data.init_settings); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed in Deleting the Init Pkt: %d", + rc); + goto release_mutex; + } + } + } + break; + default: + CAM_ERR(CAM_ACTUATOR, "Invalid Opcode %d", cmd->op_code); + } + +release_mutex: + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return rc; +} + +int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req) +{ + int32_t rc = 0, i; + uint32_t cancel_req_id_found = 0; + struct cam_actuator_ctrl_t *a_ctrl = NULL; + struct i2c_settings_array *i2c_set = NULL; + + if (!flush_req) + return -EINVAL; + + a_ctrl = (struct cam_actuator_ctrl_t *) + cam_get_device_priv(flush_req->dev_hdl); + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Device data is NULL"); + return -EINVAL; + } + + if (a_ctrl->i2c_data.per_frame == NULL) { + CAM_ERR(CAM_ACTUATOR, "i2c frame data is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + a_ctrl->last_flush_req = flush_req->req_id; + CAM_DBG(CAM_ACTUATOR, "last reqest to flush is %lld", + flush_req->req_id); + } + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(a_ctrl->i2c_data.per_frame[i]); + + if ((flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) + && (i2c_set->request_id != flush_req->req_id)) + continue; + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_ACTUATOR, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + + if (flush_req->type == + CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + cancel_req_id_found = 1; + break; + } + } + } + + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && + !cancel_req_id_found) + CAM_DBG(CAM_ACTUATOR, + "Flush request id:%lld not found in the pending list", + flush_req->req_id); + mutex_unlock(&(a_ctrl->actuator_mutex)); + return rc; +} diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.h new file mode 100644 index 000000000000..e5636f26ce36 --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ACTUATOR_CORE_H_ +#define _CAM_ACTUATOR_CORE_H_ + +#include "cam_actuator_dev.h" + +/** + * @power_info: power setting info to control the power + * + * This API construct the default actuator power setting. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int32_t cam_actuator_construct_default_power_setting( + struct cam_sensor_power_ctrl_t *power_info); + +/** + * @apply: Req mgr structure for applying request + * + * This API applies the request that is mentioned + */ +int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply); + +/** + * @info: Sub device info to req mgr + * + * This API publish the subdevice info to req mgr + */ +int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info); + +/** + * @flush: Req mgr structure for flushing request + * + * This API flushes the request that is mentioned + */ +int cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush); + + +/** + * @link: Link setup info + * + * This API establishes link actuator subdevice with req mgr + */ +int32_t cam_actuator_establish_link( + struct cam_req_mgr_core_dev_link_setup *link); + +/** + * @a_ctrl: Actuator ctrl structure + * @arg: Camera control command argument + * + * This API handles the camera control argument reached to actuator + */ +int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, void *arg); + +/** + * @a_ctrl: Actuator ctrl structure + * + * This API handles the shutdown ioctl/close + */ +void cam_actuator_shutdown(struct cam_actuator_ctrl_t *a_ctrl); + +#endif /* _CAM_ACTUATOR_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c new file mode 100644 index 000000000000..46bd99fc9e29 --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_actuator_dev.h" +#include "cam_req_mgr_dev.h" +#include "cam_actuator_soc.h" +#include "cam_actuator_core.h" +#include "cam_trace.h" + +static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_actuator_driver_cmd(a_ctrl, arg); + break; + default: + CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd"); + rc = -EINVAL; + break; + } + return rc; +} + +#ifdef CONFIG_COMPAT +static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int32_t rc = 0; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_ACTUATOR, + "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + cmd = VIDIOC_CAM_CONTROL; + rc = cam_actuator_subdev_ioctl(sd, cmd, &cmd_data); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "Failed in actuator subdev handling rc: %d", + rc); + return rc; + } + break; + default: + CAM_ERR(CAM_ACTUATOR, "Invalid compat ioctl: %d", cmd); + rc = -EINVAL; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_ACTUATOR, + "Failed to copy to user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + return rc; +} +#endif + +static int cam_actuator_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + cam_actuator_shutdown(a_ctrl); + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + +static struct v4l2_subdev_core_ops cam_actuator_subdev_core_ops = { + .ioctl = cam_actuator_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_actuator_init_subdev_do_ioctl, +#endif +}; + +static struct v4l2_subdev_ops cam_actuator_subdev_ops = { + .core = &cam_actuator_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops cam_actuator_internal_ops = { + .close = cam_actuator_subdev_close, +}; + +static int cam_actuator_init_subdev(struct cam_actuator_ctrl_t *a_ctrl) +{ + int rc = 0; + + a_ctrl->v4l2_dev_str.internal_ops = + &cam_actuator_internal_ops; + a_ctrl->v4l2_dev_str.ops = + &cam_actuator_subdev_ops; + strlcpy(a_ctrl->device_name, CAMX_ACTUATOR_DEV_NAME, + sizeof(a_ctrl->device_name)); + a_ctrl->v4l2_dev_str.name = + a_ctrl->device_name; + a_ctrl->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + a_ctrl->v4l2_dev_str.ent_function = + CAM_ACTUATOR_DEVICE_TYPE; + a_ctrl->v4l2_dev_str.token = a_ctrl; + + rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str)); + if (rc) + CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); + + return rc; +} + +static int32_t cam_actuator_driver_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int32_t rc = 0; + int32_t i = 0; + struct cam_actuator_ctrl_t *a_ctrl; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_actuator_soc_private *soc_private = NULL; + + if (client == NULL || id == NULL) { + CAM_ERR(CAM_ACTUATOR, "Invalid Args client: %pK id: %pK", + client, id); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + CAM_ERR(CAM_ACTUATOR, "%s :: i2c_check_functionality failed", + client->name); + rc = -EFAULT; + return rc; + } + + /* Create sensor control structure */ + a_ctrl = kzalloc(sizeof(*a_ctrl), GFP_KERNEL); + if (!a_ctrl) + return -ENOMEM; + + i2c_set_clientdata(client, a_ctrl); + + soc_private = kzalloc(sizeof(struct cam_actuator_soc_private), + GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto free_ctrl; + } + a_ctrl->soc_info.soc_private = soc_private; + + a_ctrl->io_master_info.client = client; + soc_info = &a_ctrl->soc_info; + soc_info->dev = &client->dev; + soc_info->dev_name = client->name; + a_ctrl->io_master_info.master_type = I2C_MASTER; + + rc = cam_actuator_parse_dt(a_ctrl, &client->dev); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "failed: cam_sensor_parse_dt rc %d", rc); + goto free_soc; + } + + rc = cam_actuator_init_subdev(a_ctrl); + if (rc) + goto free_soc; + + if (soc_private->i2c_info.slave_addr != 0) + a_ctrl->io_master_info.client->addr = + soc_private->i2c_info.slave_addr; + + a_ctrl->i2c_data.per_frame = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (a_ctrl->i2c_data.per_frame == NULL) { + rc = -ENOMEM; + goto unreg_subdev; + } + + INIT_LIST_HEAD(&(a_ctrl->i2c_data.init_settings.list_head)); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD(&(a_ctrl->i2c_data.per_frame[i].list_head)); + + a_ctrl->bridge_intf.device_hdl = -1; + a_ctrl->bridge_intf.link_hdl = -1; + a_ctrl->bridge_intf.ops.get_dev_info = + cam_actuator_publish_dev_info; + a_ctrl->bridge_intf.ops.link_setup = + cam_actuator_establish_link; + a_ctrl->bridge_intf.ops.apply_req = + cam_actuator_apply_request; + a_ctrl->last_flush_req = 0; + a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; + + return rc; + +unreg_subdev: + cam_unregister_subdev(&(a_ctrl->v4l2_dev_str)); +free_soc: + kfree(soc_private); +free_ctrl: + kfree(a_ctrl); + return rc; +} + +static int32_t cam_actuator_platform_remove(struct platform_device *pdev) +{ + int32_t rc = 0; + struct cam_actuator_ctrl_t *a_ctrl; + struct cam_actuator_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + a_ctrl = platform_get_drvdata(pdev); + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL"); + 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(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; +} + +static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client) +{ + struct cam_actuator_ctrl_t *a_ctrl = + i2c_get_clientdata(client); + struct cam_actuator_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + /* Handle I2C Devices */ + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL"); + 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; + + /*Free Allocated Mem */ + kfree(a_ctrl->i2c_data.per_frame); + a_ctrl->i2c_data.per_frame = NULL; + a_ctrl->soc_info.soc_private = NULL; + v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL); + kfree(a_ctrl); + + return 0; +} + +static const struct of_device_id cam_actuator_driver_dt_match[] = { + {.compatible = "qcom,actuator"}, + {} +}; + +static int32_t cam_actuator_driver_platform_probe( + struct platform_device *pdev) +{ + int32_t rc = 0; + int32_t i = 0; + struct cam_actuator_ctrl_t *a_ctrl = NULL; + struct cam_actuator_soc_private *soc_private = NULL; + + /* Create actuator control structure */ + a_ctrl = devm_kzalloc(&pdev->dev, + sizeof(struct cam_actuator_ctrl_t), GFP_KERNEL); + if (!a_ctrl) + return -ENOMEM; + + /*fill in platform device*/ + a_ctrl->v4l2_dev_str.pdev = pdev; + a_ctrl->soc_info.pdev = pdev; + a_ctrl->soc_info.dev = &pdev->dev; + a_ctrl->soc_info.dev_name = pdev->name; + a_ctrl->io_master_info.master_type = CCI_MASTER; + + a_ctrl->io_master_info.cci_client = kzalloc(sizeof( + struct cam_sensor_cci_client), GFP_KERNEL); + if (!(a_ctrl->io_master_info.cci_client)) { + rc = -ENOMEM; + goto free_ctrl; + } + + soc_private = kzalloc(sizeof(struct cam_actuator_soc_private), + GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto free_cci_client; + } + a_ctrl->soc_info.soc_private = soc_private; + soc_private->power_info.dev = &pdev->dev; + + a_ctrl->i2c_data.per_frame = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (a_ctrl->i2c_data.per_frame == NULL) { + rc = -ENOMEM; + goto free_soc; + } + + INIT_LIST_HEAD(&(a_ctrl->i2c_data.init_settings.list_head)); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD(&(a_ctrl->i2c_data.per_frame[i].list_head)); + + rc = cam_actuator_parse_dt(a_ctrl, &(pdev->dev)); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "Paring actuator dt failed rc %d", rc); + goto free_mem; + } + + /* Fill platform device id*/ + pdev->id = a_ctrl->soc_info.index; + + rc = cam_actuator_init_subdev(a_ctrl); + if (rc) + goto free_mem; + + a_ctrl->bridge_intf.device_hdl = -1; + a_ctrl->bridge_intf.link_hdl = -1; + a_ctrl->bridge_intf.ops.get_dev_info = + cam_actuator_publish_dev_info; + a_ctrl->bridge_intf.ops.link_setup = + cam_actuator_establish_link; + a_ctrl->bridge_intf.ops.apply_req = + cam_actuator_apply_request; + a_ctrl->bridge_intf.ops.flush_req = + cam_actuator_flush_request; + a_ctrl->last_flush_req = 0; + + platform_set_drvdata(pdev, a_ctrl); + a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; + + return rc; + +free_mem: + kfree(a_ctrl->i2c_data.per_frame); +free_soc: + kfree(soc_private); +free_cci_client: + kfree(a_ctrl->io_master_info.cci_client); +free_ctrl: + devm_kfree(&pdev->dev, a_ctrl); + return rc; +} + +MODULE_DEVICE_TABLE(of, cam_actuator_driver_dt_match); + +static struct platform_driver cam_actuator_platform_driver = { + .probe = cam_actuator_driver_platform_probe, + .driver = { + .name = "qcom,actuator", + .owner = THIS_MODULE, + .of_match_table = cam_actuator_driver_dt_match, + .suppress_bind_attrs = true, + }, + .remove = cam_actuator_platform_remove, +}; + +static const struct i2c_device_id i2c_id[] = { + {ACTUATOR_DRIVER_I2C, (kernel_ulong_t)NULL}, + { } +}; + +static struct i2c_driver cam_actuator_driver_i2c = { + .id_table = i2c_id, + .probe = cam_actuator_driver_i2c_probe, + .remove = cam_actuator_driver_i2c_remove, + .driver = { + .name = ACTUATOR_DRIVER_I2C, + }, +}; + +static int __init cam_actuator_driver_init(void) +{ + int32_t rc = 0; + + rc = platform_driver_register(&cam_actuator_platform_driver); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "platform_driver_register failed rc = %d", rc); + return rc; + } + rc = i2c_add_driver(&cam_actuator_driver_i2c); + if (rc) + CAM_ERR(CAM_ACTUATOR, "i2c_add_driver failed rc = %d", rc); + + return rc; +} + +static void __exit cam_actuator_driver_exit(void) +{ + platform_driver_unregister(&cam_actuator_platform_driver); + i2c_del_driver(&cam_actuator_driver_i2c); +} + +module_init(cam_actuator_driver_init); +module_exit(cam_actuator_driver_exit); +MODULE_DESCRIPTION("cam_actuator_driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h new file mode 100644 index 000000000000..9c704c0cd48e --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_ACTUATOR_DEV_H_ +#define _CAM_ACTUATOR_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_sensor_util.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +#define NUM_MASTERS 2 +#define NUM_QUEUES 2 + +#define TRUE 1 +#define FALSE 0 + +#define ACTUATOR_DRIVER_I2C "i2c_actuator" +#define CAMX_ACTUATOR_DEV_NAME "cam-actuator-driver" + +#define MSM_ACTUATOR_MAX_VREGS (10) +#define ACTUATOR_MAX_POLL_COUNT 10 + + +enum cam_actuator_apply_state_t { + ACT_APPLY_SETTINGS_NOW, + ACT_APPLY_SETTINGS_LATER, +}; + +enum cam_actuator_state { + CAM_ACTUATOR_INIT, + CAM_ACTUATOR_ACQUIRE, + CAM_ACTUATOR_CONFIG, + CAM_ACTUATOR_START, +}; + +/** + * struct cam_actuator_i2c_info_t - I2C info + * @slave_addr : slave address + * @i2c_freq_mode : i2c frequency mode + */ +struct cam_actuator_i2c_info_t { + uint16_t slave_addr; + uint8_t i2c_freq_mode; +}; + +struct cam_actuator_soc_private { + struct cam_actuator_i2c_info_t i2c_info; + struct cam_sensor_power_ctrl_t power_info; +}; + +/** + * struct intf_params + * @device_hdl: Device Handle + * @session_hdl: Session Handle + * @ops: KMD operations + * @crm_cb: Callback API pointers + */ +struct intf_params { + int32_t device_hdl; + int32_t session_hdl; + int32_t link_hdl; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; +}; + +/** + * struct cam_actuator_ctrl_t + * @i2c_driver: I2C device info + * @pdev: Platform device + * @cci_i2c_master: I2C structure + * @io_master_info: Information about the communication master + * @actuator_mutex: Actuator mutex + * @act_apply_state: Actuator settings aRegulator config + * @id: Cell Index + * @res_apply_state: Actuator settings apply state + * @cam_act_state: Actuator state + * @gconf: GPIO config + * @pinctrl_info: Pinctrl information + * @v4l2_dev_str: V4L2 device structure + * @i2c_data: I2C register settings structure + * @act_info: Sensor query cap structure + * @of_node: Node ptr + * @device_name: Device name + * @last_flush_req: Last request to flush + */ +struct cam_actuator_ctrl_t { + struct i2c_driver *i2c_driver; + enum cci_i2c_master_t cci_i2c_master; + enum cci_device_num cci_num; + struct camera_io_master io_master_info; + struct cam_hw_soc_info soc_info; + struct mutex actuator_mutex; + uint32_t id; + enum cam_actuator_apply_state_t setting_apply_state; + enum cam_actuator_state cam_act_state; + uint8_t cam_pinctrl_status; + struct cam_subdev v4l2_dev_str; + struct i2c_data_settings i2c_data; + struct cam_actuator_query_cap act_info; + struct intf_params bridge_intf; + char device_name[20]; + uint32_t last_flush_req; +}; + +#endif /* _CAM_ACTUATOR_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c new file mode 100644 index 000000000000..3ee629e3f1ca --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "cam_actuator_soc.h" +#include "cam_soc_util.h" + +int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl, + struct device *dev) +{ + int32_t rc = 0; + struct cam_hw_soc_info *soc_info = &a_ctrl->soc_info; + struct cam_actuator_soc_private *soc_private = + (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + struct device_node *of_node = NULL; + struct device_node *of_parent = NULL; + + /* Initialize mutex */ + mutex_init(&(a_ctrl->actuator_mutex)); + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "parsing common soc dt(rc %d)", rc); + return rc; + } + + of_node = soc_info->dev->of_node; + + if (a_ctrl->io_master_info.master_type == CCI_MASTER) { + rc = of_property_read_u32(of_node, "cci-master", + &(a_ctrl->cci_i2c_master)); + CAM_DBG(CAM_ACTUATOR, "cci-master %d, rc %d", + a_ctrl->cci_i2c_master, rc); + if ((rc < 0) || (a_ctrl->cci_i2c_master >= MASTER_MAX)) { + CAM_ERR(CAM_ACTUATOR, + "Wrong info: rc: %d, dt CCI master:%d", + rc, a_ctrl->cci_i2c_master); + rc = -EFAULT; + return rc; + } + + of_parent = of_get_parent(of_node); + if (of_property_read_u32(of_parent, "cell-index", + &a_ctrl->cci_num) < 0) + /* Set default master 0 */ + a_ctrl->cci_num = CCI_DEVICE_0; + a_ctrl->io_master_info.cci_client->cci_device = a_ctrl->cci_num; + CAM_DBG(CAM_ACTUATOR, "cci-device %d", a_ctrl->cci_num); + } + + if (!soc_info->gpio_data) { + CAM_INFO(CAM_ACTUATOR, "No GPIO found"); + rc = 0; + return rc; + } + + if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { + CAM_INFO(CAM_ACTUATOR, "No GPIO found"); + return -EINVAL; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &power_info->gpio_num_info); + if ((rc < 0) || (!power_info->gpio_num_info)) { + CAM_ERR(CAM_ACTUATOR, "No/Error Actuator GPIOs"); + return -EINVAL; + } + return rc; +} diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.h new file mode 100644 index 000000000000..65b4fb99fa03 --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ACTUATOR_SOC_H_ +#define _CAM_ACTUATOR_SOC_H_ + +#include "cam_actuator_dev.h" + +/** + * @a_ctrl: Actuator ctrl structure + * + * This API parses actuator device tree + */ +int cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl, + struct device *dev); + +#endif /* _CAM_ACTUATOR_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_cci/Makefile b/drivers/cam_sensor_module/cam_cci/Makefile new file mode 100644 index 000000000000..82734cb81445 --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/camera/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree) + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cci_dev.o cam_cci_core.o cam_cci_soc.o diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c new file mode 100644 index 000000000000..8701c6b9d62e --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -0,0 +1,1727 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_cci_core.h" +#include "cam_cci_dev.h" + +static int32_t cam_cci_convert_type_to_num_bytes( + enum camera_sensor_i2c_type type) +{ + int32_t num_bytes; + + switch (type) { + case CAMERA_SENSOR_I2C_TYPE_BYTE: + num_bytes = 1; + break; + case CAMERA_SENSOR_I2C_TYPE_WORD: + num_bytes = 2; + break; + case CAMERA_SENSOR_I2C_TYPE_3B: + num_bytes = 3; + break; + case CAMERA_SENSOR_I2C_TYPE_DWORD: + num_bytes = 4; + break; + default: + CAM_ERR(CAM_CCI, "failed: %d", type); + num_bytes = 0; + break; + } + return num_bytes; +} + +static void cam_cci_flush_queue(struct cci_device *cci_dev, + enum cci_i2c_master_t master) +{ + int32_t rc = 0; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + + cam_io_w_mb(1 << master, base + CCI_HALT_REQ_ADDR); + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); + if (rc < 0) { + CAM_ERR(CAM_CCI, "wait failed"); + } else if (rc == 0) { + CAM_ERR(CAM_CCI, "wait timeout"); + + /* Set reset pending flag to TRUE */ + cci_dev->cci_master_info[master].reset_pending = TRUE; + + /* Set proper mask to RESET CMD address based on MASTER */ + if (master == MASTER_0) + cam_io_w_mb(CCI_M0_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + else + cam_io_w_mb(CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + + /* wait for reset done irq */ + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT); + if (rc <= 0) + CAM_ERR(CAM_CCI, "wait failed %d", rc); + } +} + +static int32_t cam_cci_validate_queue(struct cci_device *cci_dev, + uint32_t len, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + int32_t rc = 0; + uint32_t read_val = 0; + uint32_t reg_offset = master * 0x200 + queue * 0x100; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + unsigned long flags; + + read_val = cam_io_r_mb(base + + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d", + read_val, len, + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size); + if ((read_val + len + 1) > + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size) { + uint32_t reg_val = 0; + uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8); + + CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD"); + cam_io_w_mb(report_val, + base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset); + read_val++; + CAM_DBG(CAM_CCI, + "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d, queue: %d", + read_val, queue); + cam_io_w_mb(read_val, base + + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); + reg_val = 1 << ((master * 2) + queue); + CAM_DBG(CAM_CCI, "CCI_QUEUE_START_ADDR"); + spin_lock_irqsave( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + atomic_set( + &cci_dev->cci_master_info[master].done_pending[queue], + 1); + cam_io_w_mb(reg_val, base + + CCI_QUEUE_START_ADDR); + CAM_DBG(CAM_CCI, "wait_for_completion_timeout"); + atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1); + spin_unlock_irqrestore( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].report_q[queue], + CCI_TIMEOUT); + if (rc <= 0) { + CAM_ERR(CAM_CCI, "Wait_for_completion_timeout: rc: %d", + rc); + if (rc == 0) + rc = -ETIMEDOUT; + cam_cci_flush_queue(cci_dev, master); + return rc; + } + rc = cci_dev->cci_master_info[master].status; + if (rc < 0) + CAM_ERR(CAM_CCI, "Failed rc %d", rc); + } + + return rc; +} + +static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev, + uint32_t val, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + int32_t rc = 0; + uint32_t reg_offset = master * 0x200 + queue * 0x100; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + + if (!cci_dev) { + CAM_ERR(CAM_CCI, "Failed"); + return -EINVAL; + } + + rc = cam_cci_validate_queue(cci_dev, 1, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Failed %d", rc); + return rc; + } + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset, val); + cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset); + return rc; +} + +static int32_t cam_cci_lock_queue(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue, uint32_t en) +{ + uint32_t val; + + if (queue != PRIORITY_QUEUE) + return 0; + + val = en ? CCI_I2C_LOCK_CMD : CCI_I2C_UNLOCK_CMD; + return cam_cci_write_i2c_queue(cci_dev, val, master, queue); +} + +#ifdef DUMP_CCI_REGISTERS +static void cam_cci_dump_registers(struct cci_device *cci_dev, + enum cci_i2c_master_t master, enum cci_i2c_queue_t queue) +{ + uint32_t read_val = 0; + uint32_t i = 0; + uint32_t reg_offset = 0; + void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base; + + /* CCI Top Registers */ + CAM_INFO(CAM_CCI, "****CCI TOP Registers ****"); + for (i = 0; i < DEBUG_TOP_REG_COUNT; i++) { + reg_offset = DEBUG_TOP_REG_START + i * 4; + read_val = cam_io_r_mb(base + reg_offset); + CAM_INFO(CAM_CCI, "offset = 0x%X value = 0x%X", + reg_offset, read_val); + } + + /* CCI Master registers */ + CAM_INFO(CAM_CCI, "****CCI MASTER %d Registers ****", + master); + for (i = 0; i < DEBUG_MASTER_REG_COUNT; i++) { + reg_offset = DEBUG_MASTER_REG_START + master*0x100 + i * 4; + read_val = cam_io_r_mb(base + reg_offset); + CAM_INFO(CAM_CCI, "offset = 0x%X value = 0x%X", + reg_offset, read_val); + } + + /* CCI Master Queue registers */ + CAM_INFO(CAM_CCI, " **** CCI MASTER%d QUEUE%d Registers ****", + master, queue); + for (i = 0; i < DEBUG_MASTER_QUEUE_REG_COUNT; i++) { + reg_offset = DEBUG_MASTER_QUEUE_REG_START + master*0x200 + + queue*0x100 + i * 4; + read_val = cam_io_r_mb(base + reg_offset); + CAM_INFO(CAM_CCI, "offset = 0x%X value = 0x%X", + reg_offset, read_val); + } + + /* CCI Interrupt registers */ + CAM_INFO(CAM_CCI, " ****CCI Interrupt Registers ****"); + for (i = 0; i < DEBUG_INTR_REG_COUNT; i++) { + reg_offset = DEBUG_INTR_REG_START + i * 4; + read_val = cam_io_r_mb(base + reg_offset); + CAM_INFO(CAM_CCI, "offset = 0x%X value = 0x%X", + reg_offset, read_val); + } +} +#endif + +static uint32_t cam_cci_wait(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + int32_t rc = 0; + + if (!cci_dev) { + CAM_ERR(CAM_CCI, "failed"); + return -EINVAL; + } + + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].report_q[queue], CCI_TIMEOUT); + CAM_DBG(CAM_CCI, "wait DONE_for_completion_timeout"); + + if (rc <= 0) { +#ifdef DUMP_CCI_REGISTERS + cam_cci_dump_registers(cci_dev, master, queue); +#endif + CAM_ERR(CAM_CCI, "wait for queue: %d", queue); + if (rc == 0) + rc = -ETIMEDOUT; + cam_cci_flush_queue(cci_dev, master); + return rc; + } + rc = cci_dev->cci_master_info[master].status; + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + + return 0; +} + +static void cam_cci_load_report_cmd(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + + uint32_t reg_offset = master * 0x200 + queue * 0x100; + uint32_t read_val = cam_io_r_mb(base + + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); + uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8); + + CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD curr_w_cnt: %d", read_val); + cam_io_w_mb(report_val, + base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset); + read_val++; + + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d", read_val); + cam_io_w_mb(read_val, base + + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); +} + +static int32_t cam_cci_wait_report_cmd(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + unsigned long flags; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + + uint32_t reg_val = 1 << ((master * 2) + queue); + + cam_cci_load_report_cmd(cci_dev, master, queue); + spin_lock_irqsave( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1); + atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1); + spin_unlock_irqrestore( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + cam_io_w_mb(reg_val, base + + CCI_QUEUE_START_ADDR); + + return cam_cci_wait(cci_dev, master, queue); +} + +static int32_t cam_cci_transfer_end(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + int32_t rc = 0; + unsigned long flags; + + spin_lock_irqsave( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) { + spin_unlock_irqrestore( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + rc = cam_cci_lock_queue(cci_dev, master, queue, 0); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc: %d", rc); + return rc; + } + rc = cam_cci_wait_report_cmd(cci_dev, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + } else { + atomic_set( + &cci_dev->cci_master_info[master].done_pending[queue], + 1); + spin_unlock_irqrestore( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + rc = cam_cci_wait(cci_dev, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + rc = cam_cci_lock_queue(cci_dev, master, queue, 0); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + rc = cam_cci_wait_report_cmd(cci_dev, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Failed rc %d", rc); + return rc; + } + } + + return rc; +} + +static int32_t cam_cci_get_queue_free_size(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + uint32_t read_val = 0; + uint32_t reg_offset = master * 0x200 + queue * 0x100; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + + read_val = cam_io_r_mb(base + + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d max %d", read_val, + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size); + return ((cci_dev->cci_i2c_queue_info[master][queue].max_queue_size) - + read_val); +} + +static void cam_cci_process_half_q(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + unsigned long flags; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + uint32_t reg_val = 1 << ((master * 2) + queue); + + spin_lock_irqsave(&cci_dev->cci_master_info[master].lock_q[queue], + flags); + if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) { + cam_cci_load_report_cmd(cci_dev, master, queue); + atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1); + cam_io_w_mb(reg_val, base + + CCI_QUEUE_START_ADDR); + } + spin_unlock_irqrestore(&cci_dev->cci_master_info[master].lock_q[queue], + flags); +} + +static int32_t cam_cci_process_full_q(struct cci_device *cci_dev, + enum cci_i2c_master_t master, + enum cci_i2c_queue_t queue) +{ + int32_t rc = 0; + unsigned long flags; + + + spin_lock_irqsave(&cci_dev->cci_master_info[master].lock_q[queue], + flags); + if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 1) { + atomic_set( + &cci_dev->cci_master_info[master].done_pending[queue], + 1); + spin_unlock_irqrestore( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + rc = cam_cci_wait(cci_dev, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + } else { + spin_unlock_irqrestore( + &cci_dev->cci_master_info[master].lock_q[queue], flags); + rc = cam_cci_wait_report_cmd(cci_dev, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + } + + return rc; +} + +static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev, + struct cam_cci_ctrl *c_ctrl, uint32_t cmd_size, + struct cam_sensor_i2c_reg_array *i2c_cmd, uint32_t *pack) +{ + uint8_t i; + uint32_t len = 0; + uint8_t data_len = 0, addr_len = 0; + uint8_t pack_max_len; + struct cam_sensor_i2c_reg_setting *msg; + struct cam_sensor_i2c_reg_array *cmd = i2c_cmd; + uint32_t size = cmd_size; + + if (!cci_dev || !c_ctrl) { + CAM_ERR(CAM_CCI, "failed"); + return -EINVAL; + } + + msg = &c_ctrl->cfg.cci_i2c_write_cfg; + *pack = 0; + + if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ || + c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) { + addr_len = cam_cci_convert_type_to_num_bytes(msg->addr_type); + len = (size + addr_len) <= (cci_dev->payload_size) ? + (size + addr_len):cci_dev->payload_size; + } else { + addr_len = cam_cci_convert_type_to_num_bytes(msg->addr_type); + data_len = cam_cci_convert_type_to_num_bytes(msg->data_type); + len = data_len + addr_len; + pack_max_len = size < (cci_dev->payload_size-len) ? + size : (cci_dev->payload_size-len); + for (i = 0; i < pack_max_len;) { + if (cmd->delay || ((cmd - i2c_cmd) >= (cmd_size - 1))) + break; + if (cmd->reg_addr + 1 == + (cmd+1)->reg_addr) { + len += data_len; + if (len > cci_dev->payload_size) { + len = len - data_len; + break; + } + (*pack)++; + } else { + break; + } + i += data_len; + cmd++; + } + } + + if (len > cci_dev->payload_size) { + CAM_ERR(CAM_CCI, "Len error: %d", len); + return -EINVAL; + } + + len += 1; /*add i2c WR command*/ + len = len/4 + 1; + + return len; +} + +static uint32_t cam_cci_cycles_per_ms(unsigned long clk) +{ + uint32_t cycles_per_us; + + if (clk) { + cycles_per_us = ((clk/1000)*256)/1000; + } else { + CAM_ERR(CAM_CCI, "failed: Can use default: %d", + CYCLES_PER_MICRO_SEC_DEFAULT); + cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT; + } + + return cycles_per_us; +} + +void cam_cci_get_clk_rates(struct cci_device *cci_dev, + struct cam_cci_ctrl *c_ctrl) + +{ + int32_t src_clk_idx, j; + uint32_t cci_clk_src; + unsigned long clk; + struct cam_cci_clk_params_t *clk_params = NULL; + + enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; + struct cam_hw_soc_info *soc_info = &cci_dev->soc_info; + + if (i2c_freq_mode >= I2C_MAX_MODES || + i2c_freq_mode < I2C_STANDARD_MODE) { + CAM_ERR(CAM_CCI, "Invalid frequency mode: %d", + (int32_t)i2c_freq_mode); + cci_dev->clk_level_index = -1; + return; + } + + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; + cci_clk_src = clk_params->cci_clk_src; + + src_clk_idx = soc_info->src_clk_idx; + + if (src_clk_idx < 0) { + cci_dev->cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT; + cci_dev->clk_level_index = 0; + return; + } + + if (cci_clk_src == 0) { + clk = soc_info->clk_rate[0][src_clk_idx]; + cci_dev->cycles_per_us = cam_cci_cycles_per_ms(clk); + cci_dev->clk_level_index = 0; + return; + } + + for (j = 0; j < CAM_MAX_VOTE; j++) { + clk = soc_info->clk_rate[j][src_clk_idx]; + if (clk == cci_clk_src) { + cci_dev->cycles_per_us = cam_cci_cycles_per_ms(clk); + cci_dev->clk_level_index = j; + return; + } + } +} + +static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev, + struct cam_cci_ctrl *c_ctrl) +{ + struct cam_cci_clk_params_t *clk_params = NULL; + enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; + enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + + if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { + CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode); + return -EINVAL; + } + + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; + + if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode) + return 0; + if (master == MASTER_0) { + cam_io_w_mb(clk_params->hw_thigh << 16 | + clk_params->hw_tlow, + base + CCI_I2C_M0_SCL_CTL_ADDR); + cam_io_w_mb(clk_params->hw_tsu_sto << 16 | + clk_params->hw_tsu_sta, + base + CCI_I2C_M0_SDA_CTL_0_ADDR); + cam_io_w_mb(clk_params->hw_thd_dat << 16 | + clk_params->hw_thd_sta, + base + CCI_I2C_M0_SDA_CTL_1_ADDR); + cam_io_w_mb(clk_params->hw_tbuf, + base + CCI_I2C_M0_SDA_CTL_2_ADDR); + cam_io_w_mb(clk_params->hw_scl_stretch_en << 8 | + clk_params->hw_trdhld << 4 | clk_params->hw_tsp, + base + CCI_I2C_M0_MISC_CTL_ADDR); + } else if (master == MASTER_1) { + cam_io_w_mb(clk_params->hw_thigh << 16 | + clk_params->hw_tlow, + base + CCI_I2C_M1_SCL_CTL_ADDR); + cam_io_w_mb(clk_params->hw_tsu_sto << 16 | + clk_params->hw_tsu_sta, + base + CCI_I2C_M1_SDA_CTL_0_ADDR); + cam_io_w_mb(clk_params->hw_thd_dat << 16 | + clk_params->hw_thd_sta, + base + CCI_I2C_M1_SDA_CTL_1_ADDR); + cam_io_w_mb(clk_params->hw_tbuf, + base + CCI_I2C_M1_SDA_CTL_2_ADDR); + cam_io_w_mb(clk_params->hw_scl_stretch_en << 8 | + clk_params->hw_trdhld << 4 | clk_params->hw_tsp, + base + CCI_I2C_M1_MISC_CTL_ADDR); + } + cci_dev->i2c_freq_mode[master] = i2c_freq_mode; + + return 0; +} + +static int32_t cam_cci_data_queue(struct cci_device *cci_dev, + struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, + enum cci_i2c_sync sync_en) +{ + uint16_t i = 0, j = 0, k = 0, h = 0, len = 0; + int32_t rc = 0, free_size = 0, en_seq_write = 0; + uint8_t data[12]; + struct cam_sensor_i2c_reg_setting *i2c_msg = + &c_ctrl->cfg.cci_i2c_write_cfg; + struct cam_sensor_i2c_reg_array *i2c_cmd = i2c_msg->reg_setting; + enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; + uint16_t reg_addr = 0, cmd_size = i2c_msg->size; + uint32_t read_val = 0, reg_offset, val, delay = 0; + uint32_t max_queue_size, queue_size = 0, cmd = 0; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + unsigned long flags; + + if (i2c_cmd == NULL) { + CAM_ERR(CAM_CCI, "Failed: i2c cmd is NULL"); + return -EINVAL; + } + + if ((!cmd_size) || (cmd_size > CCI_I2C_MAX_WRITE)) { + CAM_ERR(CAM_CCI, "failed: invalid cmd_size %d", + cmd_size); + return -EINVAL; + } + + CAM_DBG(CAM_CCI, "addr type %d data type %d cmd_size %d", + i2c_msg->addr_type, i2c_msg->data_type, cmd_size); + + if (i2c_msg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { + CAM_ERR(CAM_CCI, "failed: invalid addr_type 0x%X", + i2c_msg->addr_type); + return -EINVAL; + } + if (i2c_msg->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { + CAM_ERR(CAM_CCI, "failed: invalid data_type 0x%X", + i2c_msg->data_type); + return -EINVAL; + } + reg_offset = master * 0x200 + queue * 0x100; + + cam_io_w_mb(cci_dev->cci_wait_sync_cfg.cid, + base + CCI_SET_CID_SYNC_TIMER_ADDR + + cci_dev->cci_wait_sync_cfg.csid * + CCI_SET_CID_SYNC_TIMER_OFFSET); + + val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 | + c_ctrl->cci_info->retries << 16 | + c_ctrl->cci_info->id_map << 18; + + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset, val); + cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset); + + spin_lock_irqsave(&cci_dev->cci_master_info[master].lock_q[queue], + flags); + atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0); + spin_unlock_irqrestore(&cci_dev->cci_master_info[master].lock_q[queue], + flags); + + max_queue_size = + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size; + + if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ) + queue_size = max_queue_size; + else + queue_size = max_queue_size/2; + reg_addr = i2c_cmd->reg_addr; + + if (sync_en == MSM_SYNC_ENABLE && cci_dev->valid_sync && + cmd_size < max_queue_size) { + val = CCI_I2C_WAIT_SYNC_CMD | + ((cci_dev->cci_wait_sync_cfg.line) << 4); + cam_io_w_mb(val, + base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + reg_offset); + } + + rc = cam_cci_lock_queue(cci_dev, master, queue, 1); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed line %d", rc); + return rc; + } + + while (cmd_size) { + uint32_t pack = 0; + + len = cam_cci_calc_cmd_len(cci_dev, c_ctrl, cmd_size, + i2c_cmd, &pack); + if (len <= 0) { + CAM_ERR(CAM_CCI, "failed"); + return -EINVAL; + } + + read_val = cam_io_r_mb(base + + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); + CAM_DBG(CAM_CCI, "CUR_WORD_CNT_ADDR %d len %d max %d", + read_val, len, max_queue_size); + /* + 1 - space alocation for Report CMD */ + if ((read_val + len + 1) > queue_size) { + if ((read_val + len + 1) > max_queue_size) { + rc = cam_cci_process_full_q(cci_dev, + master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc: %d", rc); + return rc; + } + continue; + } + cam_cci_process_half_q(cci_dev, master, queue); + } + + CAM_DBG(CAM_CCI, "cmd_size %d addr 0x%x data 0x%x", + cmd_size, i2c_cmd->reg_addr, i2c_cmd->reg_data); + delay = i2c_cmd->delay; + i = 0; + data[i++] = CCI_I2C_WRITE_CMD; + + /* + * in case of multiple command + * MSM_CCI_I2C_WRITE : address is not continuous, so update + * address for a new packet. + * MSM_CCI_I2C_WRITE_SEQ : address is continuous, need to keep + * the incremented address for a + * new packet + */ + if (c_ctrl->cmd == MSM_CCI_I2C_WRITE || + c_ctrl->cmd == MSM_CCI_I2C_WRITE_ASYNC || + c_ctrl->cmd == MSM_CCI_I2C_WRITE_SYNC || + c_ctrl->cmd == MSM_CCI_I2C_WRITE_SYNC_BLOCK) + reg_addr = i2c_cmd->reg_addr; + + if (en_seq_write == 0) { + /* either byte or word addr */ + if (i2c_msg->addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) + data[i++] = reg_addr; + else { + data[i++] = (reg_addr & 0xFF00) >> 8; + data[i++] = reg_addr & 0x00FF; + } + } + /* max of 10 data bytes */ + do { + if (i2c_msg->data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + data[i++] = i2c_cmd->reg_data; + if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ) + reg_addr++; + } else { + if ((i + 1) <= cci_dev->payload_size) { + switch (i2c_msg->data_type) { + case CAMERA_SENSOR_I2C_TYPE_DWORD: + data[i++] = (i2c_cmd->reg_data & + 0xFF000000) >> 24; + /* fallthrough */ + case CAMERA_SENSOR_I2C_TYPE_3B: + data[i++] = (i2c_cmd->reg_data & + 0x00FF0000) >> 16; + /* fallthrough */ + case CAMERA_SENSOR_I2C_TYPE_WORD: + data[i++] = (i2c_cmd->reg_data & + 0x0000FF00) >> 8; + /* fallthrough */ + case CAMERA_SENSOR_I2C_TYPE_BYTE: + data[i++] = i2c_cmd->reg_data & + 0x000000FF; + break; + default: + CAM_ERR(CAM_CCI, + "invalid data type: %d", + i2c_msg->data_type); + return -EINVAL; + } + + if (c_ctrl->cmd == + MSM_CCI_I2C_WRITE_SEQ) + reg_addr++; + } else + break; + } + i2c_cmd++; + --cmd_size; + } while (((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ || + c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) || pack--) && + (cmd_size > 0) && (i <= cci_dev->payload_size)); + free_size = cam_cci_get_queue_free_size(cci_dev, master, + queue); + if ((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ || + c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) && + ((i-1) == MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11) && + cci_dev->support_seq_write && cmd_size > 0 && + free_size > BURST_MIN_FREE_SIZE) { + data[0] |= 0xF0; + en_seq_write = 1; + } else { + data[0] |= ((i-1) << 4); + en_seq_write = 0; + } + len = ((i-1)/4) + 1; + + read_val = cam_io_r_mb(base + + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); + for (h = 0, k = 0; h < len; h++) { + cmd = 0; + for (j = 0; (j < 4 && k < i); j++) + cmd |= (data[k++] << (j * 8)); + CAM_DBG(CAM_CCI, + "LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d", + cmd, queue, len, read_val); + cam_io_w_mb(cmd, base + + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + master * 0x200 + queue * 0x100); + + read_val += 1; + cam_io_w_mb(read_val, base + + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); + } + + if ((delay > 0) && (delay < CCI_MAX_DELAY) && + en_seq_write == 0) { + cmd = (uint32_t)((delay * cci_dev->cycles_per_us) / + 0x100); + cmd <<= 4; + cmd |= CCI_I2C_WAIT_CMD; + CAM_DBG(CAM_CCI, + "CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd); + cam_io_w_mb(cmd, base + + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + + master * 0x200 + queue * 0x100); + read_val += 1; + cam_io_w_mb(read_val, base + + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); + } + } + + rc = cam_cci_transfer_end(cci_dev, master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "failed rc %d", rc); + return rc; + } + + return rc; +} + +static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + int32_t rc = 0; + uint32_t val = 0, i = 0, j = 0, irq_mask_update = 0; + unsigned long rem_jiffies, flags; + int32_t read_words = 0, exp_words = 0; + int32_t index = 0, first_byte = 0, total_read_words = 0; + enum cci_i2c_master_t master; + enum cci_i2c_queue_t queue = QUEUE_1; + struct cci_device *cci_dev = NULL; + struct cam_cci_read_cfg *read_cfg = NULL; + struct cam_hw_soc_info *soc_info = NULL; + void __iomem *base = NULL; + + cci_dev = v4l2_get_subdevdata(sd); + master = c_ctrl->cci_info->cci_i2c_master; + read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; + + if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX + || c_ctrl->cci_info->cci_i2c_master < 0) { + CAM_ERR(CAM_CCI, "Invalid I2C master addr"); + return -EINVAL; + } + + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + + mutex_lock(&cci_dev->cci_master_info[master].mutex); + if (cci_dev->cci_master_info[master].is_first_req) { + 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); + 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 + * avoid overflow / underflow of queue + */ + rc = cam_cci_validate_queue(cci_dev, + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1, + master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc); + 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_q; + } + + if (read_cfg->data == NULL) { + CAM_ERR(CAM_CCI, "Data ptr is NULL"); + 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_q; + } + + CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d", + c_ctrl->cci_info->sid, c_ctrl->cci_info->retries, + c_ctrl->cci_info->id_map); + val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 | + c_ctrl->cci_info->retries << 16 | + c_ctrl->cci_info->id_map << 18; + 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_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_q; + } + + val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4); + for (i = 0; i < read_cfg->addr_type; i++) { + val |= ((read_cfg->addr >> (i << 3)) & 0xFF) << + ((read_cfg->addr_type - i) << 3); + } + + 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_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_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_q; + } + + val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + + master * 0x200 + queue * 0x100); + CAM_DBG(CAM_CCI, "cur word cnt 0x%x", val); + cam_io_w_mb(val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + + master * 0x200 + queue * 0x100); + + val = 1 << ((master * 2) + queue); + cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); + + exp_words = ((read_cfg->num_byte / 4) + 1); + CAM_DBG(CAM_CCI, "waiting for threshold [exp_words %d]", exp_words); + + while (total_read_words != exp_words) { + rem_jiffies = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].th_complete, + CCI_TIMEOUT); + if (!rem_jiffies) { + rc = -ETIMEDOUT; + val = cam_io_r_mb(base + + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + + master * 0x100); + CAM_ERR(CAM_CCI, + "wait_for_completion_timeout rc = %d FIFO buf_lvl:0x%x", + rc, val); +#ifdef DUMP_CCI_REGISTERS + cam_cci_dump_registers(cci_dev, master, queue); +#endif + cam_cci_flush_queue(cci_dev, master); + goto rel_mutex_q; + } + + read_words = cam_io_r_mb(base + + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); + if (read_words <= 0) { + CAM_DBG(CAM_CCI, "FIFO Buffer lvl is 0"); + continue; + } + + j++; + CAM_DBG(CAM_CCI, "Iteration: %u read_words %d", j, read_words); + + total_read_words += read_words; + while (read_words > 0) { + val = cam_io_r_mb(base + + CCI_I2C_M0_READ_DATA_ADDR + master * 0x100); + for (i = 0; (i < 4) && + (index < read_cfg->num_byte); i++) { + CAM_DBG(CAM_CCI, "i:%d index:%d", i, index); + if (!first_byte) { + CAM_DBG(CAM_CCI, "sid 0x%x", + val & 0xFF); + first_byte++; + } else { + read_cfg->data[index] = + (val >> (i * 8)) & 0xFF; + CAM_DBG(CAM_CCI, "data[%d] 0x%x", index, + read_cfg->data[index]); + index++; + } + } + read_words--; + } + + CAM_DBG(CAM_CCI, "Iteraion:%u total_read_words %d", + j, total_read_words); + + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled) { + irq_mask_update = + cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR) | + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + if (master == MASTER_0 && cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) + irq_mask_update |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + else if (master == MASTER_1 && cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) + irq_mask_update |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + cam_io_w_mb(irq_mask_update, + base + CCI_IRQ_MASK_1_ADDR); + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + + if (total_read_words == exp_words) { + /* + * This wait is for RD_DONE irq, if RD_DONE is + * triggered we will call complete on both threshold + * & read done waits. As part of the threshold wait + * we will be draining the entire buffer out. This + * wait is to compensate for the complete invoked for + * RD_DONE exclusively. + */ + rem_jiffies = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].rd_done, + CCI_TIMEOUT); + if (!rem_jiffies) { + rc = -ETIMEDOUT; + val = cam_io_r_mb(base + + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + + master * 0x100); + CAM_ERR(CAM_CCI, + "Failed to receive RD_DONE irq rc = %d FIFO buf_lvl:0x%x", + rc, val); + #ifdef DUMP_CCI_REGISTERS + cam_cci_dump_registers(cci_dev, + master, queue); + #endif + cam_cci_flush_queue(cci_dev, master); + goto rel_mutex_q; + } + break; + } + } + + CAM_DBG(CAM_CCI, "Burst read successful words_read %d", + total_read_words); + +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; +} + +static int32_t cam_cci_read(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + int32_t rc = 0; + uint32_t val = 0; + int32_t read_words = 0, exp_words = 0; + int32_t index = 0, first_byte = 0; + uint32_t i = 0; + enum cci_i2c_master_t master; + enum cci_i2c_queue_t queue = QUEUE_1; + struct cci_device *cci_dev = NULL; + struct cam_cci_read_cfg *read_cfg = NULL; + struct cam_hw_soc_info *soc_info = NULL; + void __iomem *base = NULL; + + cci_dev = v4l2_get_subdevdata(sd); + master = c_ctrl->cci_info->cci_i2c_master; + read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; + + if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX + || c_ctrl->cci_info->cci_i2c_master < 0) { + CAM_ERR(CAM_CCI, "Invalid I2C master addr"); + return -EINVAL; + } + + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + + mutex_lock(&cci_dev->cci_master_info[master].mutex); + if (cci_dev->cci_master_info[master].is_first_req) { + 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_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 + * avoid overflow / underflow of queue + */ + rc = cam_cci_validate_queue(cci_dev, + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1, + master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc); + 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_q; + } + + if (read_cfg->data == NULL) { + CAM_ERR(CAM_CCI, "Data ptr is NULL"); + goto rel_mutex_q; + } + + CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue); + CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d", + c_ctrl->cci_info->sid, c_ctrl->cci_info->retries, + c_ctrl->cci_info->id_map); + val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 | + c_ctrl->cci_info->retries << 16 | + c_ctrl->cci_info->id_map << 18; + 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_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_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_q; + } + + val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4); + for (i = 0; i < read_cfg->addr_type; i++) { + val |= ((read_cfg->addr >> (i << 3)) & 0xFF) << + ((read_cfg->addr_type - i) << 3); + } + + 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_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_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_q; + } + + val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + + master * 0x200 + queue * 0x100); + CAM_DBG(CAM_CCI, "cur word cnt 0x%x", val); + cam_io_w_mb(val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + + master * 0x200 + queue * 0x100); + + val = 1 << ((master * 2) + queue); + cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); + CAM_DBG(CAM_CCI, + "waiting_for_rd_done [exp_words: %d]", + ((read_cfg->num_byte / 4) + 1)); + + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT); + if (rc <= 0) { +#ifdef DUMP_CCI_REGISTERS + cam_cci_dump_registers(cci_dev, master, queue); +#endif + if (rc == 0) + rc = -ETIMEDOUT; + val = cam_io_r_mb(base + + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); + CAM_ERR(CAM_CCI, + "wait_for_completion_timeout rc = %d FIFO buf_lvl: 0x%x", + rc, val); + cam_cci_flush_queue(cci_dev, master); + goto rel_mutex_q; + } else { + rc = 0; + } + + read_words = cam_io_r_mb(base + + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); + exp_words = ((read_cfg->num_byte / 4) + 1); + if (read_words != exp_words) { + CAM_ERR(CAM_CCI, "read_words = %d, exp words = %d", + read_words, exp_words); + memset(read_cfg->data, 0, read_cfg->num_byte); + rc = -EINVAL; + goto rel_mutex_q; + } + index = 0; + CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte); + first_byte = 0; + while (read_words > 0) { + val = cam_io_r_mb(base + + CCI_I2C_M0_READ_DATA_ADDR + master * 0x100); + CAM_DBG(CAM_CCI, "read val 0x%x", val); + for (i = 0; (i < 4) && (index < read_cfg->num_byte); i++) { + CAM_DBG(CAM_CCI, "i:%d index:%d", i, index); + if (!first_byte) { + CAM_DBG(CAM_CCI, "sid 0x%x", val & 0xFF); + first_byte++; + } else { + read_cfg->data[index] = + (val >> (i * 8)) & 0xFF; + CAM_DBG(CAM_CCI, "data[%d] 0x%x", index, + read_cfg->data[index]); + index++; + } + } + read_words--; + } +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; +} + +static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, + enum cci_i2c_sync sync_en) +{ + int32_t rc = 0; + struct cci_device *cci_dev; + enum cci_i2c_master_t master; + + cci_dev = v4l2_get_subdevdata(sd); + + if (cci_dev->cci_state != CCI_STATE_ENABLED) { + CAM_ERR(CAM_CCI, "invalid cci state %d", + cci_dev->cci_state); + return -EINVAL; + } + master = c_ctrl->cci_info->cci_i2c_master; + CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d", + 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) { + 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); + 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 + * avoid overflow / underflow of queue + */ + rc = cam_cci_validate_queue(cci_dev, + cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1, + master, queue); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", + rc); + goto ERROR; + } + if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { + CAM_ERR(CAM_CCI, "More than max retries"); + 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); + 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; +} + +static void cam_cci_write_async_helper(struct work_struct *work) +{ + int rc; + struct cci_device *cci_dev; + struct cci_write_async *write_async = + container_of(work, struct cci_write_async, work); + struct cam_sensor_i2c_reg_setting *i2c_msg; + enum cci_i2c_master_t master; + struct cam_cci_master_info *cci_master_info; + + cci_dev = write_async->cci_dev; + i2c_msg = &write_async->c_ctrl.cfg.cci_i2c_write_cfg; + master = write_async->c_ctrl.cci_info->cci_i2c_master; + cci_master_info = &cci_dev->cci_master_info[master]; + + mutex_lock(&cci_master_info->mutex_q[write_async->queue]); + rc = cam_cci_i2c_write(&(cci_dev->v4l2_dev_str.sd), + &write_async->c_ctrl, write_async->queue, write_async->sync_en); + mutex_unlock(&cci_master_info->mutex_q[write_async->queue]); + if (rc < 0) + CAM_ERR(CAM_CCI, "failed rc: %d", rc); + + kfree(write_async->c_ctrl.cfg.cci_i2c_write_cfg.reg_setting); + kfree(write_async); +} + +static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, + enum cci_i2c_sync sync_en) +{ + int32_t rc = 0; + struct cci_write_async *write_async; + struct cci_device *cci_dev; + struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg; + struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg_w; + + cci_dev = v4l2_get_subdevdata(sd); + + write_async = kzalloc(sizeof(*write_async), GFP_KERNEL); + if (!write_async) + return -ENOMEM; + + + INIT_WORK(&write_async->work, cam_cci_write_async_helper); + write_async->cci_dev = cci_dev; + write_async->c_ctrl = *c_ctrl; + write_async->queue = queue; + write_async->sync_en = sync_en; + + cci_i2c_write_cfg = &c_ctrl->cfg.cci_i2c_write_cfg; + cci_i2c_write_cfg_w = &write_async->c_ctrl.cfg.cci_i2c_write_cfg; + + if (cci_i2c_write_cfg->size == 0) { + kfree(write_async); + return -EINVAL; + } + + cci_i2c_write_cfg_w->reg_setting = + kzalloc(sizeof(struct cam_sensor_i2c_reg_array)* + cci_i2c_write_cfg->size, GFP_KERNEL); + if (!cci_i2c_write_cfg_w->reg_setting) { + CAM_ERR(CAM_CCI, "Couldn't allocate memory"); + kfree(write_async); + return -ENOMEM; + } + memcpy(cci_i2c_write_cfg_w->reg_setting, + cci_i2c_write_cfg->reg_setting, + (sizeof(struct cam_sensor_i2c_reg_array)* + cci_i2c_write_cfg->size)); + + cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type; + cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type; + cci_i2c_write_cfg_w->data_type = cci_i2c_write_cfg->data_type; + cci_i2c_write_cfg_w->size = cci_i2c_write_cfg->size; + cci_i2c_write_cfg_w->delay = cci_i2c_write_cfg->delay; + + queue_work(cci_dev->write_wq[write_async->queue], &write_async->work); + + return rc; +} + +static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + int32_t rc = 0; + struct cci_device *cci_dev = NULL; + enum cci_i2c_master_t master; + struct cam_cci_read_cfg *read_cfg = NULL; + uint16_t read_bytes = 0; + + if (!sd || !c_ctrl) { + CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl); + return -EINVAL; + } + if (!c_ctrl->cci_info) { + CAM_ERR(CAM_CCI, "cci_info NULL"); + return -EINVAL; + } + cci_dev = v4l2_get_subdevdata(sd); + if (!cci_dev) { + CAM_ERR(CAM_CCI, "cci_dev NULL"); + return -EINVAL; + } + if (cci_dev->cci_state != CCI_STATE_ENABLED) { + CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state); + return -EINVAL; + } + + if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX + || c_ctrl->cci_info->cci_i2c_master < 0) { + CAM_ERR(CAM_CCI, "Invalid I2C master addr"); + return -EINVAL; + } + + master = c_ctrl->cci_info->cci_i2c_master; + read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; + if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) { + CAM_ERR(CAM_CCI, "read num bytes 0"); + rc = -EINVAL; + goto ERROR; + } + + read_bytes = read_cfg->num_byte; + + /* + * To avoid any conflicts due to back to back trigger of + * THRESHOLD irq's, we reinit the threshold wait before + * we load the burst read cmd. + */ + reinit_completion(&cci_dev->cci_master_info[master].th_complete); + + CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes); + do { + if (read_bytes >= CCI_I2C_MAX_BYTE_COUNT) + read_cfg->num_byte = CCI_I2C_MAX_BYTE_COUNT; + else + read_cfg->num_byte = read_bytes; + + if (read_cfg->num_byte >= CCI_READ_MAX) { + cci_dev->is_burst_read = true; + rc = cam_cci_burst_read(sd, c_ctrl); + } else { + cci_dev->is_burst_read = false; + rc = cam_cci_read(sd, c_ctrl); + } + if (rc) { + CAM_ERR(CAM_CCI, "failed to read rc:%d", rc); + goto ERROR; + } + + if (read_bytes >= CCI_I2C_MAX_BYTE_COUNT) { + read_cfg->addr += (CCI_I2C_MAX_BYTE_COUNT / + read_cfg->data_type); + read_cfg->data += CCI_I2C_MAX_BYTE_COUNT; + read_bytes -= CCI_I2C_MAX_BYTE_COUNT; + } else { + read_bytes = 0; + } + } while (read_bytes); + +ERROR: + cci_dev->is_burst_read = false; + return rc; +} + +static int32_t cam_cci_i2c_set_sync_prms(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + int32_t rc = 0; + struct cci_device *cci_dev; + + cci_dev = v4l2_get_subdevdata(sd); + if (!cci_dev || !c_ctrl) { + CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + cci_dev, c_ctrl); + rc = -EINVAL; + return rc; + } + cci_dev->cci_wait_sync_cfg = c_ctrl->cfg.cci_wait_sync_cfg; + cci_dev->valid_sync = cci_dev->cci_wait_sync_cfg.csid < 0 ? 0 : 1; + + return rc; +} + +static int32_t cam_cci_release(struct v4l2_subdev *sd) +{ + uint8_t rc = 0; + struct cci_device *cci_dev; + + cci_dev = v4l2_get_subdevdata(sd); + + rc = cam_cci_soc_release(cci_dev); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Failed in releasing the cci: %d", rc); + return rc; + } + + return rc; +} + +static int32_t cam_cci_write(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + int32_t rc = 0; + struct cci_device *cci_dev; + enum cci_i2c_master_t master; + struct cam_cci_master_info *cci_master_info; + uint32_t i; + + cci_dev = v4l2_get_subdevdata(sd); + if (!cci_dev || !c_ctrl) { + CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + cci_dev, c_ctrl); + rc = -EINVAL; + return rc; + } + + master = c_ctrl->cci_info->cci_i2c_master; + + if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX + || c_ctrl->cci_info->cci_i2c_master < 0) { + CAM_ERR(CAM_CCI, "Invalid I2C master addr"); + return -EINVAL; + } + + cci_master_info = &cci_dev->cci_master_info[master]; + + switch (c_ctrl->cmd) { + case MSM_CCI_I2C_WRITE_SYNC_BLOCK: + mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]); + rc = cam_cci_i2c_write(sd, c_ctrl, + SYNC_QUEUE, MSM_SYNC_ENABLE); + mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]); + break; + case MSM_CCI_I2C_WRITE_SYNC: + rc = cam_cci_i2c_write_async(sd, c_ctrl, + SYNC_QUEUE, MSM_SYNC_ENABLE); + break; + case MSM_CCI_I2C_WRITE: + case MSM_CCI_I2C_WRITE_SEQ: + case MSM_CCI_I2C_WRITE_BURST: + for (i = 0; i < NUM_QUEUES; i++) { + if (mutex_trylock(&cci_master_info->mutex_q[i])) { + rc = cam_cci_i2c_write(sd, c_ctrl, i, + MSM_SYNC_DISABLE); + mutex_unlock(&cci_master_info->mutex_q[i]); + return rc; + } + } + mutex_lock(&cci_master_info->mutex_q[PRIORITY_QUEUE]); + rc = cam_cci_i2c_write(sd, c_ctrl, + PRIORITY_QUEUE, MSM_SYNC_DISABLE); + mutex_unlock(&cci_master_info->mutex_q[PRIORITY_QUEUE]); + break; + case MSM_CCI_I2C_WRITE_ASYNC: + rc = cam_cci_i2c_write_async(sd, c_ctrl, + PRIORITY_QUEUE, MSM_SYNC_DISABLE); + break; + default: + rc = -ENOIOCTLCMD; + } + + return rc; +} + +int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, + struct cam_cci_ctrl *cci_ctrl) +{ + int32_t rc = 0; + struct cci_device *cci_dev = v4l2_get_subdevdata(sd); + CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); + + switch (cci_ctrl->cmd) { + case MSM_CCI_INIT: + mutex_lock(&cci_dev->init_mutex); + rc = cam_cci_init(sd, cci_ctrl); + mutex_unlock(&cci_dev->init_mutex); + break; + case MSM_CCI_RELEASE: + mutex_lock(&cci_dev->init_mutex); + rc = cam_cci_release(sd); + mutex_unlock(&cci_dev->init_mutex); + break; + case MSM_CCI_I2C_READ: + rc = cam_cci_read_bytes(sd, cci_ctrl); + break; + case MSM_CCI_I2C_WRITE: + case MSM_CCI_I2C_WRITE_SEQ: + case MSM_CCI_I2C_WRITE_BURST: + case MSM_CCI_I2C_WRITE_SYNC: + case MSM_CCI_I2C_WRITE_ASYNC: + case MSM_CCI_I2C_WRITE_SYNC_BLOCK: + rc = cam_cci_write(sd, cci_ctrl); + break; + case MSM_CCI_GPIO_WRITE: + break; + case MSM_CCI_SET_SYNC_CID: + rc = cam_cci_i2c_set_sync_prms(sd, cci_ctrl); + break; + + default: + rc = -ENOIOCTLCMD; + } + + cci_ctrl->status = rc; + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.h b/drivers/cam_sensor_module/cam_cci/cam_cci_core.h new file mode 100644 index 000000000000..aeaee32502ec --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_CCI_CORE_H_ +#define _CAM_CCI_CORE_H_ + +#include +#include +#include "cam_cci_dev.h" +#include "cam_cci_soc.h" + +/** + * @cci_dev: CCI device structure + * @c_ctrl: CCI control structure + * + * This API gets CCI clk rates + */ +void cam_cci_get_clk_rates(struct cci_device *cci_dev, + struct cam_cci_ctrl *c_ctrl); + +/** + * @sd: V4L2 sub device + * @c_ctrl: CCI control structure + * + * This API handles I2C operations for CCI + */ +int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, + struct cam_cci_ctrl *cci_ctrl); + +/** + * @irq_num: IRQ number + * @data: CCI private structure + * + * This API handles CCI IRQs + */ +irqreturn_t cam_cci_irq(int irq_num, void *data); + +#endif /* _CAM_CCI_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c new file mode 100644 index 000000000000..5f155df4dc44 --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -0,0 +1,521 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_cci_dev.h" +#include "../../cam_req_mgr/cam_req_mgr_dev.h" +#include "cam_cci_soc.h" +#include "cam_cci_core.h" + +#define CCI_MAX_DELAY 1000000 + +static struct v4l2_subdev *g_cci_subdev[MAX_CCI]; + +struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) +{ + if (cci_dev_index < MAX_CCI) + return g_cci_subdev[cci_dev_index]; + return NULL; +} + +static long cam_cci_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int32_t rc = 0; + + if (arg == NULL) { + CAM_ERR(CAM_CCI, "Invalid Args"); + return rc; + } + + switch (cmd) { + case VIDIOC_MSM_CCI_CFG: + rc = cam_cci_core_cfg(sd, arg); + break; + case VIDIOC_CAM_CONTROL: + break; + default: + CAM_ERR(CAM_CCI, "Invalid ioctl cmd: %d", cmd); + rc = -ENOIOCTLCMD; + } + + return rc; +} + +#ifdef CONFIG_COMPAT +static long cam_cci_subdev_compat_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + return cam_cci_subdev_ioctl(sd, cmd, NULL); +} +#endif + +irqreturn_t cam_cci_irq(int irq_num, void *data) +{ + uint32_t irq_status0, irq_status1, reg_bmsk; + uint32_t irq_update_rd_done = 0; + struct cci_device *cci_dev = data; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + void __iomem *base = soc_info->reg_map[0].mem_base; + unsigned long flags; + bool rd_done_th_assert = false; + + irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR); + irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR); + CAM_DBG(CAM_CCI, "BASE: %pK", base); + CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1); + + if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { + struct cam_cci_master_info *cci_master_info; + if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) { + cci_master_info = &cci_dev->cci_master_info[MASTER_0]; + cci_dev->cci_master_info[MASTER_0].reset_pending = + FALSE; + if (!cci_master_info->status) + complete(&cci_master_info->reset_complete); + cci_master_info->status = 0; + } + if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) { + cci_master_info = &cci_dev->cci_master_info[MASTER_1]; + cci_dev->cci_master_info[MASTER_1].reset_pending = + FALSE; + if (!cci_master_info->status) + complete(&cci_master_info->reset_complete); + cci_master_info->status = 0; + } + } + + if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) && + (irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD)) { + cci_dev->cci_master_info[MASTER_0].status = 0; + rd_done_th_assert = true; + complete(&cci_dev->cci_master_info[MASTER_0].th_complete); + complete(&cci_dev->cci_master_info[MASTER_0].rd_done); + } + if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) && + (!rd_done_th_assert)) { + cci_dev->cci_master_info[MASTER_0].status = 0; + rd_done_th_assert = true; + if (cci_dev->is_burst_read) + complete( + &cci_dev->cci_master_info[MASTER_0].th_complete); + complete(&cci_dev->cci_master_info[MASTER_0].rd_done); + } + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && + (!rd_done_th_assert)) { + cci_dev->cci_master_info[MASTER_0].status = 0; + complete(&cci_dev->cci_master_info[MASTER_0].th_complete); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK) { + struct cam_cci_master_info *cci_master_info; + + cci_master_info = &cci_dev->cci_master_info[MASTER_0]; + spin_lock_irqsave( + &cci_dev->cci_master_info[MASTER_0].lock_q[QUEUE_0], + flags); + atomic_set(&cci_master_info->q_free[QUEUE_0], 0); + cci_master_info->status = 0; + if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) { + complete(&cci_master_info->report_q[QUEUE_0]); + atomic_set(&cci_master_info->done_pending[QUEUE_0], 0); + } + spin_unlock_irqrestore( + &cci_dev->cci_master_info[MASTER_0].lock_q[QUEUE_0], + flags); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK) { + struct cam_cci_master_info *cci_master_info; + + cci_master_info = &cci_dev->cci_master_info[MASTER_0]; + spin_lock_irqsave( + &cci_dev->cci_master_info[MASTER_0].lock_q[QUEUE_1], + flags); + atomic_set(&cci_master_info->q_free[QUEUE_1], 0); + cci_master_info->status = 0; + if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) { + complete(&cci_master_info->report_q[QUEUE_1]); + atomic_set(&cci_master_info->done_pending[QUEUE_1], 0); + } + spin_unlock_irqrestore( + &cci_dev->cci_master_info[MASTER_0].lock_q[QUEUE_1], + flags); + } + rd_done_th_assert = false; + if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) && + (irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD)) { + cci_dev->cci_master_info[MASTER_1].status = 0; + rd_done_th_assert = true; + complete(&cci_dev->cci_master_info[MASTER_1].th_complete); + complete(&cci_dev->cci_master_info[MASTER_1].rd_done); + } + 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; + rd_done_th_assert = true; + if (cci_dev->is_burst_read) + complete( + &cci_dev->cci_master_info[MASTER_1].th_complete); + complete(&cci_dev->cci_master_info[MASTER_1].rd_done); + } + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && + (!rd_done_th_assert)) { + cci_dev->cci_master_info[MASTER_1].status = 0; + complete(&cci_dev->cci_master_info[MASTER_1].th_complete); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK) { + struct cam_cci_master_info *cci_master_info; + + cci_master_info = &cci_dev->cci_master_info[MASTER_1]; + spin_lock_irqsave( + &cci_dev->cci_master_info[MASTER_1].lock_q[QUEUE_0], + flags); + atomic_set(&cci_master_info->q_free[QUEUE_0], 0); + cci_master_info->status = 0; + if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) { + complete(&cci_master_info->report_q[QUEUE_0]); + atomic_set(&cci_master_info->done_pending[QUEUE_0], 0); + } + spin_unlock_irqrestore( + &cci_dev->cci_master_info[MASTER_1].lock_q[QUEUE_0], + flags); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK) { + struct cam_cci_master_info *cci_master_info; + + cci_master_info = &cci_dev->cci_master_info[MASTER_1]; + spin_lock_irqsave( + &cci_dev->cci_master_info[MASTER_1].lock_q[QUEUE_1], + flags); + atomic_set(&cci_master_info->q_free[QUEUE_1], 0); + cci_master_info->status = 0; + if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) { + complete(&cci_master_info->report_q[QUEUE_1]); + atomic_set(&cci_master_info->done_pending[QUEUE_1], 0); + } + spin_unlock_irqrestore( + &cci_dev->cci_master_info[MASTER_1].lock_q[QUEUE_1], + flags); + } + if (irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE) + CAM_DBG(CAM_CCI, "RD_PAUSE ON MASTER_0"); + + if (irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_PAUSE) + CAM_DBG(CAM_CCI, "RD_PAUSE ON MASTER_1"); + + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) { + cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE; + cam_io_w_mb(CCI_M0_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK_BMSK) { + cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE; + cam_io_w_mb(CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { + cci_dev->cci_master_info[MASTER_0].status = -EINVAL; + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) + CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x", + base, irq_status0); + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) + CAM_ERR(CAM_CCI, + "Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x", + base, irq_status0); + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) + CAM_ERR(CAM_CCI, + "Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x", + base, irq_status0); + cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { + cci_dev->cci_master_info[MASTER_1].status = -EINVAL; + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) + CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x", + base, irq_status0); + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) + CAM_ERR(CAM_CCI, + "Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x", + base, irq_status0); + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) + CAM_ERR(CAM_CCI, + "Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x", + base, irq_status0); + cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); + } + + cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); + + reg_bmsk = CCI_IRQ_MASK_1_RMSK; + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && + !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK)) { + reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + spin_lock_irqsave(&cci_dev->lock_status, flags); + cci_dev->irqs_disabled |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && + !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK)) { + reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + spin_lock_irqsave(&cci_dev->lock_status, flags); + cci_dev->irqs_disabled |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + + if (reg_bmsk != CCI_IRQ_MASK_1_RMSK) { + cam_io_w_mb(reg_bmsk, base + CCI_IRQ_MASK_1_ADDR); + CAM_DBG(CAM_CCI, "Updating the reg mask for irq1: 0x%x", + reg_bmsk); + } else if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK || + irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) { + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) { + irq_update_rd_done |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + cci_dev->irqs_disabled &= + ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) { + irq_update_rd_done |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + cci_dev->irqs_disabled &= + ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + } + + if (irq_update_rd_done != 0) { + irq_update_rd_done |= cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(irq_update_rd_done, base + CCI_IRQ_MASK_1_ADDR); + } + + + cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR); + cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); + return IRQ_HANDLED; +} + +static int cam_cci_irq_routine(struct v4l2_subdev *sd, u32 status, + bool *handled) +{ + struct cci_device *cci_dev = v4l2_get_subdevdata(sd); + irqreturn_t ret; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + + ret = cam_cci_irq(soc_info->irq_line->start, cci_dev); + *handled = TRUE; + return 0; +} + +static struct v4l2_subdev_core_ops cci_subdev_core_ops = { + .ioctl = cam_cci_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_cci_subdev_compat_ioctl, +#endif + .interrupt_service_routine = cam_cci_irq_routine, +}; + +static const struct v4l2_subdev_ops cci_subdev_ops = { + .core = &cci_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops cci_subdev_intern_ops; + +static struct v4l2_file_operations cci_v4l2_subdev_fops; + +static long cam_cci_subdev_do_ioctl( + struct file *file, unsigned int cmd, void *arg) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + + return cam_cci_subdev_ioctl(sd, cmd, NULL); +} + +static long cam_cci_subdev_fops_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return video_usercopy(file, cmd, arg, cam_cci_subdev_do_ioctl); +} + +#ifdef CONFIG_COMPAT +static long cam_cci_subdev_fops_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + + return v4l2_subdev_call(sd, core, ioctl, cmd, NULL); +} +#endif + +static int cam_cci_platform_probe(struct platform_device *pdev) +{ + struct cam_cpas_register_params cpas_parms; + struct cci_device *new_cci_dev; + struct cam_hw_soc_info *soc_info = NULL; + int rc = 0; + + new_cci_dev = kzalloc(sizeof(struct cci_device), + GFP_KERNEL); + if (!new_cci_dev) + return -ENOMEM; + + soc_info = &new_cci_dev->soc_info; + + new_cci_dev->v4l2_dev_str.pdev = pdev; + + soc_info->pdev = pdev; + soc_info->dev = &pdev->dev; + soc_info->dev_name = pdev->name; + + rc = cam_cci_parse_dt_info(pdev, new_cci_dev); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Resource get Failed: %d", rc); + goto cci_no_resource; + } + + new_cci_dev->v4l2_dev_str.internal_ops = + &cci_subdev_intern_ops; + new_cci_dev->v4l2_dev_str.ops = + &cci_subdev_ops; + strlcpy(new_cci_dev->device_name, CAMX_CCI_DEV_NAME, + sizeof(new_cci_dev->device_name)); + new_cci_dev->v4l2_dev_str.name = + new_cci_dev->device_name; + new_cci_dev->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + new_cci_dev->v4l2_dev_str.ent_function = + CAM_CCI_DEVICE_TYPE; + new_cci_dev->v4l2_dev_str.token = + new_cci_dev; + + rc = cam_register_subdev(&(new_cci_dev->v4l2_dev_str)); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Fail with cam_register_subdev"); + goto cci_no_resource; + } + + platform_set_drvdata(pdev, &(new_cci_dev->v4l2_dev_str.sd)); + v4l2_set_subdevdata(&new_cci_dev->v4l2_dev_str.sd, new_cci_dev); + if (soc_info->index >= MAX_CCI) { + CAM_ERR(CAM_CCI, "Invalid index: %d max supported:%d", + soc_info->index, MAX_CCI-1); + goto cci_no_resource; + } + + g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; + mutex_init(&(new_cci_dev->init_mutex)); + CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); + + cam_register_subdev_fops(&cci_v4l2_subdev_fops); + cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl; +#ifdef CONFIG_COMPAT + cci_v4l2_subdev_fops.compat_ioctl32 = + cam_cci_subdev_fops_compat_ioctl; +#endif + + cpas_parms.cam_cpas_client_cb = NULL; + cpas_parms.cell_index = soc_info->index; + cpas_parms.dev = &pdev->dev; + cpas_parms.userdata = new_cci_dev; + strlcpy(cpas_parms.identifier, "cci", CAM_HW_IDENTIFIER_LENGTH); + rc = cam_cpas_register_client(&cpas_parms); + if (rc) { + CAM_ERR(CAM_CCI, "CPAS registration failed"); + goto cci_no_resource; + } + CAM_DBG(CAM_CCI, "CPAS registration successful handle=%d", + cpas_parms.client_handle); + new_cci_dev->cpas_handle = cpas_parms.client_handle; + + return rc; +cci_no_resource: + kfree(new_cci_dev); + return rc; +} + +static int cam_cci_device_remove(struct platform_device *pdev) +{ + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); + struct cci_device *cci_dev = + v4l2_get_subdevdata(subdev); + + cam_cpas_unregister_client(cci_dev->cpas_handle); + cam_cci_soc_remove(pdev, cci_dev); + devm_kfree(&pdev->dev, cci_dev); + return 0; +} + +static const struct of_device_id cam_cci_dt_match[] = { + {.compatible = "qcom,cci"}, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_cci_dt_match); + +static struct platform_driver cci_driver = { + .probe = cam_cci_platform_probe, + .remove = cam_cci_device_remove, + .driver = { + .name = CAMX_CCI_DEV_NAME, + .owner = THIS_MODULE, + .of_match_table = cam_cci_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int cam_cci_assign_fops(void) +{ + struct v4l2_subdev *sd; + int i = 0; + + for (; i < MAX_CCI; i++) { + sd = g_cci_subdev[i]; + if (!sd) + return 0; + if (!(sd->devnode)) { + CAM_ERR(CAM_CCI, + "Invalid dev node:%pK offset: %d", + sd->devnode, i); + return -EINVAL; + } + sd->devnode->fops = &cci_v4l2_subdev_fops; + } + + return 0; +} + +static int __init cam_cci_late_init(void) +{ + return cam_cci_assign_fops(); +} + +static int __init cam_cci_init_module(void) +{ + return platform_driver_register(&cci_driver); +} + +static void __exit cam_cci_exit_module(void) +{ + platform_driver_unregister(&cci_driver); +} + +module_init(cam_cci_init_module); +late_initcall(cam_cci_late_init); +module_exit(cam_cci_exit_module); +MODULE_DESCRIPTION("MSM CCI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h new file mode 100644 index 000000000000..4bc1d34af3d2 --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CCI_DEV_H_ +#define _CAM_CCI_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../cam_req_mgr/cam_subdev.h" +#include +#include "cam_cci_hwreg.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +#define V4L2_IDENT_CCI 50005 +#define CCI_I2C_QUEUE_0_SIZE 128 +#define CCI_I2C_QUEUE_1_SIZE 32 +#define CYCLES_PER_MICRO_SEC_DEFAULT 4915 +#define CCI_MAX_DELAY 1000000 + +#define CCI_TIMEOUT msecs_to_jiffies(1500) + +#define NUM_MASTERS 2 +#define NUM_QUEUES 2 + +#define TRUE 1 +#define FALSE 0 + +#define CCI_PINCTRL_STATE_DEFAULT "cci_default" +#define CCI_PINCTRL_STATE_SLEEP "cci_suspend" + +#define CCI_NUM_CLK_MAX 16 +#define CCI_NUM_CLK_CASES 5 +#define CCI_CLK_SRC_NAME "cci_src_clk" +#define MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_10 10 +#define MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11 11 +#define BURST_MIN_FREE_SIZE 8 +#define MAX_LRME_V4l2_EVENTS 30 + +/* Max bytes that can be read per CCI read transaction */ +#define CCI_READ_MAX 256 +#define CCI_I2C_READ_MAX_RETRIES 3 +#define CCI_I2C_MAX_READ 8192 +#define CCI_I2C_MAX_WRITE 8192 +#define CCI_I2C_MAX_BYTE_COUNT 65535 + +#define CAMX_CCI_DEV_NAME "cam-cci-driver" + +#define MAX_CCI 2 + +#define PRIORITY_QUEUE (QUEUE_0) +#define SYNC_QUEUE (QUEUE_1) + +enum cci_i2c_sync { + MSM_SYNC_DISABLE, + MSM_SYNC_ENABLE, +}; + +enum cam_cci_cmd_type { + MSM_CCI_INIT, + MSM_CCI_RELEASE, + MSM_CCI_SET_SID, + MSM_CCI_SET_FREQ, + MSM_CCI_SET_SYNC_CID, + MSM_CCI_I2C_READ, + MSM_CCI_I2C_WRITE, + MSM_CCI_I2C_WRITE_SEQ, + MSM_CCI_I2C_WRITE_BURST, + MSM_CCI_I2C_WRITE_ASYNC, + MSM_CCI_GPIO_WRITE, + MSM_CCI_I2C_WRITE_SYNC, + MSM_CCI_I2C_WRITE_SYNC_BLOCK, +}; + +enum cci_i2c_queue_t { + QUEUE_0, + QUEUE_1, + QUEUE_INVALID, +}; + +struct cam_cci_wait_sync_cfg { + uint16_t cid; + int16_t csid; + uint16_t line; + uint16_t delay; +}; + +struct cam_cci_gpio_cfg { + uint16_t gpio_queue; + uint16_t i2c_queue; +}; + +struct cam_cci_read_cfg { + uint32_t addr; + uint16_t addr_type; + uint8_t *data; + uint16_t num_byte; + uint16_t data_type; +}; + +struct cam_cci_i2c_queue_info { + uint32_t max_queue_size; + uint32_t report_id; + uint32_t irq_en; + uint32_t capture_rep_data; +}; + +struct cam_cci_master_info { + uint32_t status; + atomic_t q_free[NUM_QUEUES]; + uint8_t q_lock[NUM_QUEUES]; + uint8_t reset_pending; + struct mutex mutex; + struct completion reset_complete; + struct completion rd_done; + struct completion th_complete; + struct mutex mutex_q[NUM_QUEUES]; + 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 { + uint16_t hw_thigh; + uint16_t hw_tlow; + uint16_t hw_tsu_sto; + uint16_t hw_tsu_sta; + uint16_t hw_thd_dat; + uint16_t hw_thd_sta; + uint16_t hw_tbuf; + uint8_t hw_scl_stretch_en; + uint8_t hw_trdhld; + uint8_t hw_tsp; + uint32_t cci_clk_src; +}; + +enum cam_cci_state_t { + CCI_STATE_ENABLED, + CCI_STATE_DISABLED, +}; + +/** + * struct cci_device + * @pdev: Platform device + * @subdev: V4L2 sub device + * @base: Base address of CCI device + * @hw_version: Hardware version + * @ref_count: Reference Count + * @cci_state: CCI state machine + * @num_clk: Number of CCI clock + * @cci_clk: CCI clock structure + * @cci_clk_info: CCI clock information + * @cam_cci_i2c_queue_info: CCI queue information + * @i2c_freq_mode: I2C frequency of operations + * @cci_clk_params: CCI hw clk params + * @cci_gpio_tbl: CCI GPIO table + * @cci_gpio_tbl_size: GPIO table size + * @cci_pinctrl: Pinctrl structure + * @cci_pinctrl_status: CCI pinctrl status + * @cci_clk_src: CCI clk src rate + * @cci_vreg: CCI regulator structure + * @cci_reg_ptr: CCI individual regulator structure + * @regulator_count: Regulator count + * @support_seq_write: Set this flag when sequential write is enabled + * @write_wq: Work queue structure + * @valid_sync: Is it a valid sync with CSID + * @v4l2_dev_str: V4L2 device structure + * @cci_wait_sync_cfg: CCI sync config + * @cycles_per_us: Cycles per micro sec + * @payload_size: CCI packet payload size + * @irq_status1: Store irq_status1 to be cleared after + * draining FIFO buffer for burst read + * @lock_status: to protect changes to irq_status1 + * @is_burst_read: Flag to determine if we are performing + * a burst read operation or not + * @irqs_disabled: Mask for IRQs that are disabled + * @init_mutex: Mutex for maintaining refcount for attached + * devices to cci during init/deinit. + */ +struct cci_device { + struct v4l2_subdev subdev; + struct cam_hw_soc_info soc_info; + uint32_t hw_version; + uint8_t ref_count; + enum cam_cci_state_t cci_state; + struct cam_cci_i2c_queue_info + cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES]; + struct cam_cci_master_info cci_master_info[NUM_MASTERS]; + enum i2c_freq_mode i2c_freq_mode[NUM_MASTERS]; + struct cam_cci_clk_params_t cci_clk_params[I2C_MAX_MODES]; + struct msm_pinctrl_info cci_pinctrl; + uint8_t cci_pinctrl_status; + uint8_t support_seq_write; + struct workqueue_struct *write_wq[MASTER_MAX]; + struct cam_cci_wait_sync_cfg cci_wait_sync_cfg; + uint8_t valid_sync; + struct cam_subdev v4l2_dev_str; + uint32_t cycles_per_us; + int32_t clk_level_index; + uint8_t payload_size; + char device_name[20]; + uint32_t cpas_handle; + uint32_t irq_status1; + spinlock_t lock_status; + bool is_burst_read; + uint32_t irqs_disabled; + struct mutex init_mutex; +}; + +enum cam_cci_i2c_cmd_type { + CCI_I2C_SET_PARAM_CMD = 1, + CCI_I2C_WAIT_CMD, + CCI_I2C_WAIT_SYNC_CMD, + CCI_I2C_WAIT_GPIO_EVENT_CMD, + CCI_I2C_TRIG_I2C_EVENT_CMD, + CCI_I2C_LOCK_CMD, + CCI_I2C_UNLOCK_CMD, + CCI_I2C_REPORT_CMD, + CCI_I2C_WRITE_CMD, + CCI_I2C_READ_CMD, + CCI_I2C_WRITE_DISABLE_P_CMD, + CCI_I2C_READ_DISABLE_P_CMD, + CCI_I2C_WRITE_CMD2, + CCI_I2C_WRITE_CMD3, + CCI_I2C_REPEAT_CMD, + CCI_I2C_INVALID_CMD, +}; + +enum cam_cci_gpio_cmd_type { + CCI_GPIO_SET_PARAM_CMD = 1, + CCI_GPIO_WAIT_CMD, + CCI_GPIO_WAIT_SYNC_CMD, + CCI_GPIO_WAIT_GPIO_IN_EVENT_CMD, + CCI_GPIO_WAIT_I2C_Q_TRIG_EVENT_CMD, + CCI_GPIO_OUT_CMD, + CCI_GPIO_TRIG_EVENT_CMD, + CCI_GPIO_REPORT_CMD, + CCI_GPIO_REPEAT_CMD, + CCI_GPIO_CONTINUE_CMD, + CCI_GPIO_INVALID_CMD, +}; + +struct cam_sensor_cci_client { + struct v4l2_subdev *cci_subdev; + uint32_t freq; + enum i2c_freq_mode i2c_freq_mode; + enum cci_i2c_master_t cci_i2c_master; + uint16_t sid; + uint16_t cid; + uint32_t timeout; + uint16_t retries; + uint16_t id_map; + uint16_t cci_device; +}; + +struct cam_cci_ctrl { + int32_t status; + struct cam_sensor_cci_client *cci_info; + enum cam_cci_cmd_type cmd; + union { + struct cam_sensor_i2c_reg_setting cci_i2c_write_cfg; + struct cam_cci_read_cfg cci_i2c_read_cfg; + struct cam_cci_wait_sync_cfg cci_wait_sync_cfg; + struct cam_cci_gpio_cfg gpio_cfg; + } cfg; +}; + +struct cci_write_async { + struct cci_device *cci_dev; + struct cam_cci_ctrl c_ctrl; + enum cci_i2c_queue_t queue; + struct work_struct work; + enum cci_i2c_sync sync_en; +}; + +irqreturn_t cam_cci_irq(int irq_num, void *data); + +#ifdef CONFIG_SPECTRA_CAMERA +extern struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index); +#else +static inline struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) +{ + return NULL; +} +#endif + +#define VIDIOC_MSM_CCI_CFG \ + _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl *) + +#endif /* _CAM_CCI_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h b/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h new file mode 100644 index 000000000000..f00b854e9533 --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CCI_HWREG_ +#define _CAM_CCI_HWREG_ + +#define CCI_HW_VERSION_ADDR 0x00000000 +#define CCI_RESET_CMD_ADDR 0x00000004 +#define CCI_RESET_CMD_RMSK 0x0f73f3f7 +#define CCI_M0_RESET_RMSK 0x3F1 +#define CCI_M1_RESET_RMSK 0x3F001 +#define CCI_QUEUE_START_ADDR 0x00000008 +#define CCI_SET_CID_SYNC_TIMER_ADDR 0x00000010 +#define CCI_SET_CID_SYNC_TIMER_OFFSET 0x00000004 +#define CCI_I2C_M0_SCL_CTL_ADDR 0x00000100 +#define CCI_I2C_M0_SDA_CTL_0_ADDR 0x00000104 +#define CCI_I2C_M0_SDA_CTL_1_ADDR 0x00000108 +#define CCI_I2C_M0_SDA_CTL_2_ADDR 0x0000010c +#define CCI_I2C_M0_READ_DATA_ADDR 0x00000118 +#define CCI_I2C_M0_MISC_CTL_ADDR 0x00000110 +#define CCI_I2C_M0_READ_BUF_LEVEL_ADDR 0x0000011C +#define CCI_HALT_REQ_ADDR 0x00000034 +#define CCI_M0_HALT_REQ_RMSK 0x1 +#define CCI_M1_HALT_REQ_RMSK 0x2 +#define CCI_I2C_M1_SCL_CTL_ADDR 0x00000200 +#define CCI_I2C_M1_SDA_CTL_0_ADDR 0x00000204 +#define CCI_I2C_M1_SDA_CTL_1_ADDR 0x00000208 +#define CCI_I2C_M1_SDA_CTL_2_ADDR 0x0000020c +#define CCI_I2C_M1_MISC_CTL_ADDR 0x00000210 +#define CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR 0x00000304 +#define CCI_I2C_M0_Q0_CUR_CMD_ADDR 0x00000308 +#define CCI_I2C_M0_Q0_REPORT_STATUS_ADDR 0x0000030c +#define CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR 0x00000300 +#define CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x00000310 +#define CCI_IRQ_MASK_0_ADDR 0x00000c04 +#define CCI_IRQ_MASK_0_RMSK 0x7fff7ff7 +#define CCI_IRQ_MASK_1_ADDR 0x00000c10 +#define CCI_IRQ_MASK_1_RMSK 0x00110000 +#define CCI_IRQ_CLEAR_0_ADDR 0x00000c08 +#define CCI_IRQ_CLEAR_1_ADDR 0x00000c14 +#define CCI_IRQ_STATUS_0_ADDR 0x00000c0c +#define CCI_IRQ_STATUS_1_ADDR 0x00000c18 +#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK_BMSK 0x4000000 +#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK 0x2000000 +#define CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK 0x1000000 +#define CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK 0x100000 +#define CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK 0x10000 +#define CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK 0x1000 +#define CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD 0x100000 +#define CCI_IRQ_STATUS_1_I2C_M1_RD_PAUSE 0x200000 +#define CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK 0x100 +#define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10 +#define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6 +#define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000 +#define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK 0x18000000 +#define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK 0x60000000 +#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK 0xEE0 +#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK 0xEE0000 +#define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK 0x6 +#define CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK 0x6000 +#define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK 0x1 +#define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD 0x10000 +#define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE 0x20000 +#define CCI_I2C_M0_RD_THRESHOLD_ADDR 0x00000120 +#define CCI_I2C_M1_RD_THRESHOLD_ADDR 0x00000220 +#define CCI_I2C_RD_THRESHOLD_VALUE 0x30 +#define CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x00000c00 + +#define DEBUG_TOP_REG_START 0x0 +#define DEBUG_TOP_REG_COUNT 14 +#define DEBUG_MASTER_REG_START 0x100 +#define DEBUG_MASTER_REG_COUNT 9 +#define DEBUG_MASTER_QUEUE_REG_START 0x300 +#define DEBUG_MASTER_QUEUE_REG_COUNT 7 +#define DEBUG_INTR_REG_START 0xC00 +#define DEBUG_INTR_REG_COUNT 7 +#endif /* _CAM_CCI_HWREG_ */ diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c new file mode 100644 index 000000000000..633196c983aa --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_cci_dev.h" +#include "cam_cci_core.h" + +int cam_cci_init(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + uint8_t i = 0, j = 0; + int32_t rc = 0; + struct cci_device *cci_dev; + enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + struct cam_hw_soc_info *soc_info = NULL; + void __iomem *base = NULL; + + cci_dev = v4l2_get_subdevdata(sd); + if (!cci_dev || !c_ctrl) { + CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + cci_dev, c_ctrl); + rc = -EINVAL; + return rc; + } + + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + + if (!soc_info || !base) { + CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + soc_info, base); + rc = -EINVAL; + return rc; + } + + CAM_DBG(CAM_CCI, "Base address %pK", base); + + if (cci_dev->ref_count++) { + CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count); + CAM_DBG(CAM_CCI, "master %d", master); + if (master < MASTER_MAX && master >= 0) { + mutex_lock(&cci_dev->cci_master_info[master].mutex); + flush_workqueue(cci_dev->write_wq[master]); + /* Re-initialize the completion */ + reinit_completion( + &cci_dev->cci_master_info[master].reset_complete); + reinit_completion( + &cci_dev->cci_master_info[master].rd_done); + for (i = 0; i < NUM_QUEUES; i++) + reinit_completion( + &cci_dev->cci_master_info[master].report_q[i]); + /* Set reset pending flag to TRUE */ + cci_dev->cci_master_info[master].reset_pending = TRUE; + /* Set proper mask to RESET CMD address */ + if (master == MASTER_0) + cam_io_w_mb(CCI_M0_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + else + cam_io_w_mb(CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + /* wait for reset done irq */ + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT); + if (rc <= 0) + CAM_ERR(CAM_CCI, "wait failed %d", rc); + mutex_unlock(&cci_dev->cci_master_info[master].mutex); + } + return 0; + } + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = + CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(cci_dev->cpas_handle, + &ahb_vote, &axi_vote); + if (rc != 0) + CAM_ERR(CAM_CCI, "CPAS start failed"); + + cam_cci_get_clk_rates(cci_dev, c_ctrl); + + /* Re-initialize the completion */ + reinit_completion(&cci_dev->cci_master_info[master].reset_complete); + reinit_completion(&cci_dev->cci_master_info[master].rd_done); + for (i = 0; i < NUM_QUEUES; i++) + reinit_completion( + &cci_dev->cci_master_info[master].report_q[i]); + + /* Enable Regulators and IRQ*/ + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_LOWSVS_VOTE, true); + if (rc < 0) { + CAM_DBG(CAM_CCI, "request platform resources failed"); + goto platform_enable_failed; + } + + cci_dev->hw_version = cam_io_r_mb(base + + CCI_HW_VERSION_ADDR); + CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version); + + cci_dev->payload_size = + MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; + cci_dev->support_seq_write = 1; + + for (i = 0; i < NUM_MASTERS; i++) { + for (j = 0; j < NUM_QUEUES; j++) { + if (j == QUEUE_0) + cci_dev->cci_i2c_queue_info[i][j].max_queue_size + = CCI_I2C_QUEUE_0_SIZE; + else + cci_dev->cci_i2c_queue_info[i][j].max_queue_size + = CCI_I2C_QUEUE_1_SIZE; + + CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i, + cci_dev->cci_i2c_queue_info[i][j].max_queue_size, + cci_dev->cci_i2c_queue_info[i][j].max_queue_size); + } + } + + cci_dev->cci_master_info[master].reset_pending = TRUE; + cam_io_w_mb(CCI_RESET_CMD_RMSK, base + + CCI_RESET_CMD_ADDR); + cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); + rc = wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT); + if (rc <= 0) { + CAM_ERR(CAM_CCI, "wait_for_completion_timeout"); + if (rc == 0) + rc = -ETIMEDOUT; + goto reset_complete_failed; + } + for (i = 0; i < MASTER_MAX; i++) + cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, + base + CCI_IRQ_MASK_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, + base + CCI_IRQ_CLEAR_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, + base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, + base + CCI_IRQ_CLEAR_1_ADDR); + cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); + + for (i = 0; i < MASTER_MAX; i++) { + if (!cci_dev->write_wq[i]) { + CAM_ERR(CAM_CCI, "Failed to flush write wq"); + rc = -ENOMEM; + goto reset_complete_failed; + } else { + flush_workqueue(cci_dev->write_wq[i]); + } + } + + /* Set RD FIFO threshold for M0 & M1 */ + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M0_RD_THRESHOLD_ADDR); + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M1_RD_THRESHOLD_ADDR); + + cci_dev->cci_state = CCI_STATE_ENABLED; + + return 0; + +reset_complete_failed: + cam_soc_util_disable_platform_resource(soc_info, 1, 1); + +platform_enable_failed: + cci_dev->ref_count--; + cam_cpas_stop(cci_dev->cpas_handle); + + return rc; +} + +void cam_cci_soc_remove(struct platform_device *pdev, + struct cci_device *cci_dev) +{ + struct cam_hw_soc_info *soc_info = &cci_dev->soc_info; + + cam_soc_util_release_platform_resource(soc_info); +} + +static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) +{ + uint8_t i = 0, j = 0; + + 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( + &new_cci_dev->cci_master_info[i].th_complete); + init_completion( + &new_cci_dev->cci_master_info[i].rd_done); + + for (j = 0; j < NUM_QUEUES; j++) { + mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]); + init_completion( + &new_cci_dev->cci_master_info[i].report_q[j]); + spin_lock_init( + &new_cci_dev->cci_master_info[i].lock_q[j]); + } + } + spin_lock_init(&new_cci_dev->lock_status); +} + +static void cam_cci_init_default_clk_params(struct cci_device *cci_dev, + uint8_t index) +{ + /* default clock params are for 100Khz */ + cci_dev->cci_clk_params[index].hw_thigh = 201; + cci_dev->cci_clk_params[index].hw_tlow = 174; + cci_dev->cci_clk_params[index].hw_tsu_sto = 204; + cci_dev->cci_clk_params[index].hw_tsu_sta = 231; + cci_dev->cci_clk_params[index].hw_thd_dat = 22; + cci_dev->cci_clk_params[index].hw_thd_sta = 162; + cci_dev->cci_clk_params[index].hw_tbuf = 227; + cci_dev->cci_clk_params[index].hw_scl_stretch_en = 0; + cci_dev->cci_clk_params[index].hw_trdhld = 6; + cci_dev->cci_clk_params[index].hw_tsp = 3; + cci_dev->cci_clk_params[index].cci_clk_src = 37500000; +} + +static void cam_cci_init_clk_params(struct cci_device *cci_dev) +{ + int32_t rc = 0; + uint32_t val = 0; + uint8_t count = 0; + struct device_node *of_node = cci_dev->v4l2_dev_str.pdev->dev.of_node; + struct device_node *src_node = NULL; + + for (count = 0; count < I2C_MAX_MODES; count++) { + + if (count == I2C_STANDARD_MODE) + src_node = of_find_node_by_name(of_node, + "qcom,i2c_standard_mode"); + else if (count == I2C_FAST_MODE) + src_node = of_find_node_by_name(of_node, + "qcom,i2c_fast_mode"); + else if (count == I2C_FAST_PLUS_MODE) + src_node = of_find_node_by_name(of_node, + "qcom,i2c_fast_plus_mode"); + else + src_node = of_find_node_by_name(of_node, + "qcom,i2c_custom_mode"); + + rc = of_property_read_u32(src_node, "hw-thigh", &val); + CAM_DBG(CAM_CCI, "hw-thigh %d, rc %d", val, rc); + if (!rc) { + cci_dev->cci_clk_params[count].hw_thigh = val; + rc = of_property_read_u32(src_node, "hw-tlow", + &val); + CAM_DBG(CAM_CCI, "hw-tlow %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_tlow = val; + rc = of_property_read_u32(src_node, "hw-tsu-sto", + &val); + CAM_DBG(CAM_CCI, "hw-tsu-sto %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_tsu_sto = val; + rc = of_property_read_u32(src_node, "hw-tsu-sta", + &val); + CAM_DBG(CAM_CCI, "hw-tsu-sta %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_tsu_sta = val; + rc = of_property_read_u32(src_node, "hw-thd-dat", + &val); + CAM_DBG(CAM_CCI, "hw-thd-dat %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_thd_dat = val; + rc = of_property_read_u32(src_node, "hw-thd-sta", + &val); + CAM_DBG(CAM_CCI, "hw-thd-sta %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_thd_sta = val; + rc = of_property_read_u32(src_node, "hw-tbuf", + &val); + CAM_DBG(CAM_CCI, "hw-tbuf %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_tbuf = val; + rc = of_property_read_u32(src_node, + "hw-scl-stretch-en", &val); + CAM_DBG(CAM_CCI, "hw-scl-stretch-en %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_scl_stretch_en = val; + rc = of_property_read_u32(src_node, "hw-trdhld", + &val); + CAM_DBG(CAM_CCI, "hw-trdhld %d, rc %d", + val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_trdhld = val; + rc = of_property_read_u32(src_node, "hw-tsp", + &val); + CAM_DBG(CAM_CCI, "hw-tsp %d, rc %d", val, rc); + } + if (!rc) { + cci_dev->cci_clk_params[count].hw_tsp = val; + val = 0; + rc = of_property_read_u32(src_node, "cci-clk-src", + &val); + CAM_DBG(CAM_CCI, "cci-clk-src %d, rc %d", val, rc); + cci_dev->cci_clk_params[count].cci_clk_src = val; + } else + cam_cci_init_default_clk_params(cci_dev, count); + + of_node_put(src_node); + } +} + +int cam_cci_parse_dt_info(struct platform_device *pdev, + struct cci_device *new_cci_dev) +{ + int rc = 0, i = 0; + struct cam_hw_soc_info *soc_info = + &new_cci_dev->soc_info; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_CCI, "Parsing DT data failed:%d", rc); + return -EINVAL; + } + + new_cci_dev->ref_count = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, + cam_cci_irq, new_cci_dev); + if (rc < 0) { + CAM_ERR(CAM_CCI, "requesting platform resources failed:%d", rc); + return -EINVAL; + } + new_cci_dev->v4l2_dev_str.pdev = pdev; + cam_cci_init_cci_params(new_cci_dev); + cam_cci_init_clk_params(new_cci_dev); + + rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (rc) + CAM_ERR(CAM_CCI, "failed to add child nodes, rc=%d", rc); + + for (i = 0; i < MASTER_MAX; i++) { + new_cci_dev->write_wq[i] = create_singlethread_workqueue( + "cam_cci_wq"); + if (!new_cci_dev->write_wq[i]) + CAM_ERR(CAM_CCI, "Failed to create write wq"); + } + CAM_DBG(CAM_CCI, "Exit"); + return 0; +} + +int cam_cci_soc_release(struct cci_device *cci_dev) +{ + uint8_t i = 0, rc = 0; + struct cam_hw_soc_info *soc_info = + &cci_dev->soc_info; + + if (!cci_dev->ref_count || cci_dev->cci_state != CCI_STATE_ENABLED) { + CAM_ERR(CAM_CCI, "invalid ref count %d / cci state %d", + cci_dev->ref_count, cci_dev->cci_state); + return -EINVAL; + } + if (--cci_dev->ref_count) { + CAM_DBG(CAM_CCI, "ref_count Exit %d", cci_dev->ref_count); + return 0; + } + for (i = 0; i < MASTER_MAX; i++) + if (cci_dev->write_wq[i]) + flush_workqueue(cci_dev->write_wq[i]); + + for (i = 0; i < MASTER_MAX; i++) + cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_CCI, "platform resources disable failed, rc=%d", + rc); + return rc; + } + + cci_dev->cci_state = CCI_STATE_DISABLED; + cci_dev->cycles_per_us = 0; + + cam_cpas_stop(cci_dev->cpas_handle); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h new file mode 100644 index 000000000000..f0cdfe822cd3 --- /dev/null +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CCI_SOC_H_ +#define _CAM_CCI_SOC_H_ + +#include "cam_cci_core.h" +#include "cam_soc_util.h" + +/** + * @sd: V4L2 sub device + * @c_ctrl: CCI control structure + * + * This API initializes the CCI and acquires SOC resources + */ +int cam_cci_init(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl); + +/** + * @cci_dev: CCI device structure + * + * This API releases the CCI and its SOC resources + */ +int cam_cci_soc_release(struct cci_device *cci_dev); + +/** + * @pdev: Platform device + * @new_cci_dev: CCI device structure + * + * This API parses CCI device tree + */ +int cam_cci_parse_dt_info(struct platform_device *pdev, + struct cci_device *new_cci_dev); + +/** + * @pdev: Platform device + * @cci_dev: CCI device structure + * + * This API puts all SOC resources + */ +void cam_cci_soc_remove(struct platform_device *pdev, + struct cci_device *cci_dev); +#endif /* _CAM_CCI_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/Makefile b/drivers/cam_sensor_module/cam_csiphy/Makefile new file mode 100644 index 000000000000..88ab6ed9a1bb --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy_soc.o cam_csiphy_dev.o cam_csiphy_core.o diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c new file mode 100644 index 000000000000..adf9ef82ee45 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -0,0 +1,971 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_csiphy_core.h" +#include "cam_csiphy_dev.h" +#include "cam_csiphy_soc.h" +#include "cam_common_util.h" +#include "cam_packet_util.h" + + +#include +#include + +#define SCM_SVC_CAMERASS 0x18 +#define SECURE_SYSCALL_ID 0x6 +#define SECURE_SYSCALL_ID_2 0x7 + +#define LANE_MASK_2PH 0x1F +#define LANE_MASK_3PH 0x7 + +static int csiphy_dump; +module_param(csiphy_dump, int, 0644); + +static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, + bool protect, int32_t offset) +{ + struct scm_desc desc = {0}; + + if (offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); + return -EINVAL; + } + + desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL); + desc.args[0] = protect; + desc.args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset]; + + if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID_2), + &desc)) { + CAM_ERR(CAM_CSIPHY, "scm call to hypervisor failed"); + return -EINVAL; + } + + return 0; +} + +int32_t cam_csiphy_get_instance_offset( + struct csiphy_device *csiphy_dev, + int32_t dev_handle) +{ + int32_t i; + + if (csiphy_dev->acquire_count > + CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); + return -EINVAL; + } + + for (i = 0; i < csiphy_dev->acquire_count; i++) { + if (dev_handle == + csiphy_dev->bridge_intf.device_hdl[i]) + break; + } + + return i; +} + +void cam_csiphy_query_cap(struct csiphy_device *csiphy_dev, + struct cam_csiphy_query_cap *csiphy_cap) +{ + struct cam_hw_soc_info *soc_info = &csiphy_dev->soc_info; + + csiphy_cap->slot_info = soc_info->index; + csiphy_cap->version = csiphy_dev->hw_version; + csiphy_cap->clk_lane = csiphy_dev->clk_lane; +} + +void cam_csiphy_reset(struct csiphy_device *csiphy_dev) +{ + int32_t i; + void __iomem *base = NULL; + uint32_t size = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_reset_array_size; + struct cam_hw_soc_info *soc_info = &csiphy_dev->soc_info; + + base = soc_info->reg_map[0].mem_base; + + for (i = 0; i < size; i++) { + cam_io_w_mb( + csiphy_dev->ctrl_reg->csiphy_reset_reg[i].reg_data, + base + + csiphy_dev->ctrl_reg->csiphy_reset_reg[i].reg_addr); + + usleep_range(csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay + * 1000, csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay + * 1000 + 10); + } +} + +int32_t cam_csiphy_update_secure_info( + struct csiphy_device *csiphy_dev, + struct cam_csiphy_info *cam_cmd_csiphy_info, + struct cam_config_dev_cmd *cfg_dev) +{ + uint32_t clock_lane, adj_lane_mask, temp; + int32_t offset; + + if (csiphy_dev->acquire_count >= + CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); + return -EINVAL; + } + + offset = cam_csiphy_get_instance_offset(csiphy_dev, + cfg_dev->dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + return -EINVAL; + } + + if (cam_cmd_csiphy_info->combo_mode) + clock_lane = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_combo_ck_ln; + else + clock_lane = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_clock_lane; + + adj_lane_mask = cam_cmd_csiphy_info->lane_mask & LANE_MASK_2PH & + ~clock_lane; + temp = adj_lane_mask & (clock_lane - 1); + adj_lane_mask = + ((adj_lane_mask & (~(clock_lane - 1))) >> 1) | temp; + + if (cam_cmd_csiphy_info->csiphy_3phase) + adj_lane_mask = cam_cmd_csiphy_info->lane_mask & LANE_MASK_3PH; + + csiphy_dev->csiphy_info.secure_mode[offset] = 1; + + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = + adj_lane_mask << (csiphy_dev->soc_info.index * + (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) + + (!cam_cmd_csiphy_info->csiphy_3phase) * + (CAM_CSIPHY_MAX_CPHY_LANES)); + + return 0; +} + +int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, + struct cam_config_dev_cmd *cfg_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"); + return -EINVAL; + } + + rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle, + &generic_pkt_ptr, &len); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc); + return rc; + } + + remain_len = len; + if ((sizeof(struct cam_packet) > len) || + ((size_t)cfg_dev->offset >= len - sizeof(struct cam_packet))) { + CAM_ERR(CAM_CSIPHY, + "Inval cam_packet strut size: %zu, len_of_buff: %zu", + sizeof(struct cam_packet), len); + rc = -EINVAL; + return rc; + } + + remain_len -= (size_t)cfg_dev->offset; + csl_packet = (struct cam_packet *) + (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; + return rc; + } + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset / 4); + + rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, + &generic_ptr, &len); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, + "Failed to get cmd buf Mem address : %d", rc); + return rc; + } + + 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; + return rc; + } + + cmd_buf = (uint32_t *)generic_ptr; + cmd_buf += cmd_desc->offset / 4; + cam_cmd_csiphy_info = (struct cam_csiphy_info *)cmd_buf; + + csiphy_dev->config_count++; + csiphy_dev->csiphy_info.lane_cnt += cam_cmd_csiphy_info->lane_cnt; + csiphy_dev->csiphy_info.lane_mask |= cam_cmd_csiphy_info->lane_mask; + csiphy_dev->csiphy_info.csiphy_3phase = + cam_cmd_csiphy_info->csiphy_3phase; + csiphy_dev->csiphy_info.combo_mode |= cam_cmd_csiphy_info->combo_mode; + if (cam_cmd_csiphy_info->combo_mode == 1) { + csiphy_dev->csiphy_info.settle_time_combo_sensor = + cam_cmd_csiphy_info->settle_time; + csiphy_dev->csiphy_info.data_rate_combo_sensor = + cam_cmd_csiphy_info->data_rate; + } else { + csiphy_dev->csiphy_info.settle_time = + cam_cmd_csiphy_info->settle_time; + csiphy_dev->csiphy_info.data_rate = + cam_cmd_csiphy_info->data_rate; + } + + + if (cam_cmd_csiphy_info->secure_mode == 1) + cam_csiphy_update_secure_info(csiphy_dev, + cam_cmd_csiphy_info, cfg_dev); + + return rc; +} + +void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev) +{ + int32_t i; + void __iomem *csiphybase = + csiphy_dev->soc_info.reg_map[0].mem_base; + + for (i = 0; i < csiphy_dev->num_irq_registers; i++) + cam_io_w_mb( + csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_data, + csiphybase + + csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr); +} + +void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) +{ + int i = 0, j = 0; + uint64_t phy_data_rate = 0; + void __iomem *csiphybase = NULL; + ssize_t num_table_entries = 0; + struct data_rate_settings_t *settings_table = NULL; + + if ((csiphy_device == NULL) || + (csiphy_device->ctrl_reg == NULL) || + (csiphy_device->ctrl_reg->data_rates_settings_table == NULL)) { + CAM_DBG(CAM_CSIPHY, + "Data rate specific register table not found"); + return; + } + + phy_data_rate = csiphy_device->csiphy_info.data_rate; + csiphybase = + csiphy_device->soc_info.reg_map[0].mem_base; + settings_table = + csiphy_device->ctrl_reg->data_rates_settings_table; + num_table_entries = + settings_table->num_data_rate_settings; + + CAM_DBG(CAM_CSIPHY, "required data rate : %llu", phy_data_rate); + for (i = 0; i < num_table_entries; i++) { + struct data_rate_reg_info_t *drate_settings = + settings_table->data_rate_settings; + uint64_t bandwidth = + drate_settings[i].bandwidth; + ssize_t num_reg_entries = + drate_settings[i].data_rate_reg_array_size; + + if (phy_data_rate > bandwidth) { + CAM_DBG(CAM_CSIPHY, + "Skipping table [%d] %llu required: %llu", + i, bandwidth, phy_data_rate); + continue; + } + + CAM_DBG(CAM_CSIPHY, + "table[%d] BW : %llu Selected", i, bandwidth); + for (j = 0; j < num_reg_entries; j++) { + uint32_t reg_addr = + drate_settings[i].csiphy_data_rate_regs[j].reg_addr; + + uint32_t reg_data = + drate_settings[i].csiphy_data_rate_regs[j].reg_data; + + CAM_DBG(CAM_CSIPHY, + "writing reg : %x val : %x", + reg_addr, reg_data); + cam_io_w_mb(reg_data, + csiphybase + reg_addr); + } + break; + } +} + +void cam_csiphy_cphy_irq_disable(struct csiphy_device *csiphy_dev) +{ + int32_t i; + void __iomem *csiphybase = + csiphy_dev->soc_info.reg_map[0].mem_base; + + for (i = 0; i < csiphy_dev->num_irq_registers; i++) + cam_io_w_mb(0x0, csiphybase + + csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr); +} + +irqreturn_t cam_csiphy_irq(int irq_num, void *data) +{ + uint32_t irq; + uint8_t i; + struct csiphy_device *csiphy_dev = + (struct csiphy_device *)data; + struct cam_hw_soc_info *soc_info = NULL; + struct csiphy_reg_parms_t *csiphy_reg = NULL; + void __iomem *base = NULL; + + if (!csiphy_dev) { + CAM_ERR(CAM_CSIPHY, "Invalid Args"); + return IRQ_NONE; + } + + soc_info = &csiphy_dev->soc_info; + base = csiphy_dev->soc_info.reg_map[0].mem_base; + csiphy_reg = &csiphy_dev->ctrl_reg->csiphy_reg; + + for (i = 0; i < csiphy_dev->num_irq_registers; i++) { + irq = cam_io_r(base + + csiphy_reg->mipi_csiphy_interrupt_status0_addr + + (0x4 * i)); + cam_io_w_mb(irq, base + + csiphy_reg->mipi_csiphy_interrupt_clear0_addr + + (0x4 * i)); + CAM_ERR_RATE_LIMIT(CAM_CSIPHY, + "CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x", + soc_info->index, i, irq); + cam_io_w_mb(0x0, base + + csiphy_reg->mipi_csiphy_interrupt_clear0_addr + + (0x4 * i)); + } + cam_io_w_mb(0x1, base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr); + cam_io_w_mb(0x0, base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr); + + return IRQ_HANDLED; +} + +int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) +{ + int32_t rc = 0; + uint32_t lane_enable = 0, mask = 1, size = 0; + uint16_t lane_mask = 0, i = 0, cfg_size = 0, temp = 0; + uint8_t lane_cnt, lane_pos = 0; + uint16_t settle_cnt = 0; + void __iomem *csiphybase; + struct csiphy_reg_t *csiphy_common_reg = NULL; + struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE]; + + lane_cnt = csiphy_dev->csiphy_info.lane_cnt; + csiphybase = csiphy_dev->soc_info.reg_map[0].mem_base; + + if (!csiphybase) { + CAM_ERR(CAM_CSIPHY, "csiphybase NULL"); + return -EINVAL; + } + + if (!csiphy_dev->csiphy_info.csiphy_3phase) { + if (csiphy_dev->csiphy_info.combo_mode == 1) + reg_array = + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg; + else + reg_array = + csiphy_dev->ctrl_reg->csiphy_2ph_reg; + csiphy_dev->num_irq_registers = 11; + cfg_size = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_config_array_size; + + lane_mask = csiphy_dev->csiphy_info.lane_mask & LANE_MASK_2PH; + for (i = 0; i < MAX_DPHY_DATA_LN; i++) { + if (mask == 0x2) { + if (lane_mask & mask) + lane_enable |= 0x80; + i--; + } else if (lane_mask & mask) { + lane_enable |= 0x1 << (i<<1); + } + mask <<= 1; + } + } else { + if (csiphy_dev->csiphy_info.combo_mode == 1) { + if (csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg) + reg_array = + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg; + else { + reg_array = + csiphy_dev->ctrl_reg->csiphy_3ph_reg; + CAM_ERR(CAM_CSIPHY, + "Unsupported configuration, Falling back to CPHY mode"); + } + } else + reg_array = + csiphy_dev->ctrl_reg->csiphy_3ph_reg; + csiphy_dev->num_irq_registers = 11; + cfg_size = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_3ph_config_array_size; + + lane_mask = csiphy_dev->csiphy_info.lane_mask & LANE_MASK_3PH; + mask = lane_mask; + while (mask != 0) { + temp = (i << 1)+1; + lane_enable |= ((mask & 0x1) << temp); + mask >>= 1; + i++; + } + } + + size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; + + for (i = 0; i < size; i++) { + csiphy_common_reg = &csiphy_dev->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_LANE_ENABLE: + cam_io_w_mb(lane_enable, + csiphybase + csiphy_common_reg->reg_addr); + usleep_range(csiphy_common_reg->delay * 1000, + csiphy_common_reg->delay * 1000 + 10); + break; + case CSIPHY_DEFAULT_PARAMS: + cam_io_w_mb(csiphy_common_reg->reg_data, + csiphybase + csiphy_common_reg->reg_addr); + usleep_range(csiphy_common_reg->delay * 1000, + csiphy_common_reg->delay * 1000 + 10); + break; + case CSIPHY_2PH_REGS: + if (!csiphy_dev->csiphy_info.csiphy_3phase) { + cam_io_w_mb(csiphy_common_reg->reg_data, + csiphybase + + csiphy_common_reg->reg_addr); + usleep_range(csiphy_common_reg->delay * 1000, + csiphy_common_reg->delay * 1000 + 10); + } + break; + case CSIPHY_3PH_REGS: + if (csiphy_dev->csiphy_info.csiphy_3phase) { + cam_io_w_mb(csiphy_common_reg->reg_data, + csiphybase + + csiphy_common_reg->reg_addr); + usleep_range(csiphy_common_reg->delay * 1000, + csiphy_common_reg->delay * 1000 + 10); + } + break; + default: + break; + } + } + + while (lane_mask) { + if (!(lane_mask & 0x1)) { + lane_pos++; + lane_mask >>= 1; + continue; + } + + settle_cnt = (csiphy_dev->csiphy_info.settle_time / 200000000); + if (csiphy_dev->csiphy_info.combo_mode == 1 && + (lane_pos >= 3)) + settle_cnt = + (csiphy_dev->csiphy_info.settle_time_combo_sensor / + 200000000); + for (i = 0; i < cfg_size; i++) { + switch (reg_array[lane_pos][i].csiphy_param_type) { + case CSIPHY_LANE_ENABLE: + cam_io_w_mb(lane_enable, + csiphybase + + reg_array[lane_pos][i].reg_addr); + break; + case CSIPHY_DEFAULT_PARAMS: + cam_io_w_mb(reg_array[lane_pos][i].reg_data, + csiphybase + + reg_array[lane_pos][i].reg_addr); + break; + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + cam_io_w_mb(settle_cnt & 0xFF, + csiphybase + + reg_array[lane_pos][i].reg_addr); + break; + case CSIPHY_SETTLE_CNT_HIGHER_BYTE: + cam_io_w_mb((settle_cnt >> 8) & 0xFF, + csiphybase + + reg_array[lane_pos][i].reg_addr); + break; + default: + CAM_DBG(CAM_CSIPHY, "Do Nothing"); + break; + } + if (reg_array[lane_pos][i].delay > 0) { + usleep_range(reg_array[lane_pos][i].delay*1000, + reg_array[lane_pos][i].delay*1000 + 10); + } + } + lane_mask >>= 1; + lane_pos++; + } + + if (csiphy_dev->csiphy_info.csiphy_3phase) + cam_csiphy_cphy_data_rate_config(csiphy_dev); + + cam_csiphy_cphy_irq_config(csiphy_dev); + + return rc; +} + +void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) +{ + struct cam_hw_soc_info *soc_info; + int32_t i = 0; + + if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) + return; + + if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { + soc_info = &csiphy_dev->soc_info; + + for (i = 0; i < csiphy_dev->acquire_count; i++) { + if (csiphy_dev->csiphy_info.secure_mode[i]) + cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, i); + + csiphy_dev->csiphy_info.secure_mode[i] = + CAM_SECURE_MODE_NON_SECURE; + + csiphy_dev->csiphy_cpas_cp_reg_mask[i] = 0; + } + + cam_csiphy_reset(csiphy_dev); + cam_soc_util_disable_platform_resource(soc_info, true, true); + + cam_cpas_stop(csiphy_dev->cpas_handle); + csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; + } + + if (csiphy_dev->csiphy_state == CAM_CSIPHY_ACQUIRE) { + if (csiphy_dev->bridge_intf.device_hdl[0] != -1) + cam_destroy_device_hdl( + csiphy_dev->bridge_intf.device_hdl[0]); + if (csiphy_dev->bridge_intf.device_hdl[1] != -1) + cam_destroy_device_hdl( + csiphy_dev->bridge_intf.device_hdl[1]); + csiphy_dev->bridge_intf.device_hdl[0] = -1; + csiphy_dev->bridge_intf.device_hdl[1] = -1; + csiphy_dev->bridge_intf.link_hdl[0] = -1; + csiphy_dev->bridge_intf.link_hdl[1] = -1; + csiphy_dev->bridge_intf.session_hdl[0] = -1; + csiphy_dev->bridge_intf.session_hdl[1] = -1; + } + + csiphy_dev->ref_count = 0; + csiphy_dev->is_acquired_dev_combo_mode = 0; + csiphy_dev->acquire_count = 0; + csiphy_dev->start_dev_count = 0; + csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; +} + +static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev, + struct cam_config_dev_cmd *p_submit_cmd) +{ + struct cam_csiphy_info cam_cmd_csiphy_info; + int32_t rc = 0; + + if (copy_from_user(&cam_cmd_csiphy_info, + u64_to_user_ptr(p_submit_cmd->packet_handle), + sizeof(struct cam_csiphy_info))) { + CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n"); + rc = -EFAULT; + } else { + csiphy_dev->csiphy_info.lane_cnt = + cam_cmd_csiphy_info.lane_cnt; + csiphy_dev->csiphy_info.lane_cnt = + cam_cmd_csiphy_info.lane_cnt; + csiphy_dev->csiphy_info.lane_mask = + cam_cmd_csiphy_info.lane_mask; + csiphy_dev->csiphy_info.csiphy_3phase = + cam_cmd_csiphy_info.csiphy_3phase; + csiphy_dev->csiphy_info.combo_mode = + cam_cmd_csiphy_info.combo_mode; + csiphy_dev->csiphy_info.settle_time = + cam_cmd_csiphy_info.settle_time; + csiphy_dev->csiphy_info.data_rate = + cam_cmd_csiphy_info.data_rate; + CAM_DBG(CAM_CSIPHY, + "%s CONFIG_DEV_EXT settle_time= %lld lane_cnt=%d lane_mask=0x%x", + __func__, + csiphy_dev->csiphy_info.settle_time, + csiphy_dev->csiphy_info.lane_cnt, + csiphy_dev->csiphy_info.lane_mask); + } + + return rc; +} + +int32_t cam_csiphy_core_cfg(void *phy_dev, + void *arg) +{ + struct csiphy_device *csiphy_dev = + (struct csiphy_device *)phy_dev; + struct intf_params *bridge_intf = NULL; + struct cam_control *cmd = (struct cam_control *)arg; + int32_t rc = 0; + + if (!csiphy_dev || !cmd) { + CAM_ERR(CAM_CSIPHY, "Invalid input args"); + return -EINVAL; + } + + if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_CSIPHY, "Invalid handle type: %d", + cmd->handle_type); + return -EINVAL; + } + + CAM_DBG(CAM_CSIPHY, "Opcode received: %d", cmd->op_code); + mutex_lock(&csiphy_dev->mutex); + switch (cmd->op_code) { + case CAM_ACQUIRE_DEV: { + struct cam_sensor_acquire_dev csiphy_acq_dev; + struct cam_csiphy_acquire_dev_info csiphy_acq_params; + + 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)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + goto release_mutex; + } + + csiphy_acq_params.combo_mode = 0; + + if (copy_from_user(&csiphy_acq_params, + u64_to_user_ptr(csiphy_acq_dev.info_handle), + sizeof(csiphy_acq_params))) { + CAM_ERR(CAM_CSIPHY, + "Failed copying from User"); + goto release_mutex; + } + + if (csiphy_dev->acquire_count == 2) { + CAM_ERR(CAM_CSIPHY, + "CSIPHY device do not allow more than 2 acquires"); + rc = -EINVAL; + goto release_mutex; + } + + if ((csiphy_acq_params.combo_mode == 1) && + (csiphy_dev->is_acquired_dev_combo_mode == 1)) { + CAM_ERR(CAM_CSIPHY, + "Multiple Combo Acq are not allowed: cm: %d, acm: %d", + csiphy_acq_params.combo_mode, + csiphy_dev->is_acquired_dev_combo_mode); + rc = -EINVAL; + goto release_mutex; + } + + if ((csiphy_acq_params.combo_mode != 1) && + (csiphy_dev->is_acquired_dev_combo_mode != 1) && + (csiphy_dev->acquire_count == 1)) { + CAM_ERR(CAM_CSIPHY, + "Multiple Acquires are not allowed cm: %d acm: %d", + csiphy_acq_params.combo_mode, + csiphy_dev->is_acquired_dev_combo_mode); + rc = -EINVAL; + goto release_mutex; + } + + bridge_params.ops = NULL; + bridge_params.session_hdl = csiphy_acq_dev.session_handle; + bridge_params.v4l2_sub_dev_flag = 0; + bridge_params.media_entity_flag = 0; + bridge_params.priv = csiphy_dev; + + if (csiphy_acq_params.combo_mode >= 2) { + CAM_ERR(CAM_CSIPHY, "Invalid combo_mode %d", + csiphy_acq_params.combo_mode); + rc = -EINVAL; + goto release_mutex; + } + + csiphy_acq_dev.device_handle = + cam_create_device_hdl(&bridge_params); + bridge_intf = &csiphy_dev->bridge_intf; + bridge_intf->device_hdl[csiphy_acq_params.combo_mode] + = csiphy_acq_dev.device_handle; + bridge_intf->session_hdl[csiphy_acq_params.combo_mode] = + csiphy_acq_dev.session_handle; + + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &csiphy_acq_dev, + sizeof(struct cam_sensor_acquire_dev))) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + rc = -EINVAL; + goto release_mutex; + } + if (csiphy_acq_params.combo_mode == 1) + csiphy_dev->is_acquired_dev_combo_mode = 1; + + csiphy_dev->acquire_count++; + csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; + } + break; + case CAM_QUERY_CAP: { + struct cam_csiphy_query_cap csiphy_cap = {0}; + + cam_csiphy_query_cap(csiphy_dev, &csiphy_cap); + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &csiphy_cap, sizeof(struct cam_csiphy_query_cap))) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + rc = -EINVAL; + goto release_mutex; + } + } + break; + case CAM_STOP_DEV: { + int32_t offset, rc = 0; + struct cam_start_stop_dev_cmd config; + + rc = copy_from_user(&config, (void __user *)cmd->handle, + sizeof(config)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + goto release_mutex; + } + + if ((csiphy_dev->csiphy_state != CAM_CSIPHY_START) || + !csiphy_dev->start_dev_count) { + CAM_ERR(CAM_CSIPHY, "Not in right state to stop : %d", + csiphy_dev->csiphy_state); + goto release_mutex; + } + + offset = cam_csiphy_get_instance_offset(csiphy_dev, + config.dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + goto release_mutex; + } + + if (--csiphy_dev->start_dev_count) { + CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d", + csiphy_dev->start_dev_count); + if (csiphy_dev->csiphy_info.secure_mode[offset]) + cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, offset); + + csiphy_dev->csiphy_info.secure_mode[offset] = + CAM_SECURE_MODE_NON_SECURE; + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0; + + goto release_mutex; + } + + if (csiphy_dev->csiphy_info.secure_mode[offset]) + cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, offset); + + csiphy_dev->csiphy_info.secure_mode[offset] = + CAM_SECURE_MODE_NON_SECURE; + + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; + + rc = cam_csiphy_disable_hw(csiphy_dev); + if (rc < 0) + CAM_ERR(CAM_CSIPHY, "Failed in csiphy release"); + + rc = cam_cpas_stop(csiphy_dev->cpas_handle); + if (rc < 0) + CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc); + + csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; + } + break; + case CAM_RELEASE_DEV: { + struct cam_release_dev_cmd release; + + if (!csiphy_dev->acquire_count) { + CAM_ERR(CAM_CSIPHY, "No valid devices to release"); + rc = -EINVAL; + goto release_mutex; + } + + if (copy_from_user(&release, + u64_to_user_ptr(cmd->handle), + sizeof(release))) { + rc = -EFAULT; + goto release_mutex; + } + + rc = cam_destroy_device_hdl(release.dev_handle); + if (rc < 0) + CAM_ERR(CAM_CSIPHY, "destroying the device hdl"); + if (release.dev_handle == + csiphy_dev->bridge_intf.device_hdl[0]) { + csiphy_dev->bridge_intf.device_hdl[0] = -1; + csiphy_dev->bridge_intf.link_hdl[0] = -1; + csiphy_dev->bridge_intf.session_hdl[0] = -1; + } else { + csiphy_dev->bridge_intf.device_hdl[1] = -1; + csiphy_dev->bridge_intf.link_hdl[1] = -1; + csiphy_dev->bridge_intf.session_hdl[1] = -1; + csiphy_dev->is_acquired_dev_combo_mode = 0; + } + + csiphy_dev->config_count--; + csiphy_dev->acquire_count--; + + if (csiphy_dev->acquire_count == 0) + csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; + + if (csiphy_dev->config_count == 0) { + CAM_DBG(CAM_CSIPHY, "reset csiphy_info"); + csiphy_dev->csiphy_info.lane_mask = 0; + csiphy_dev->csiphy_info.lane_cnt = 0; + csiphy_dev->csiphy_info.combo_mode = 0; + } + } + break; + case CAM_CONFIG_DEV: { + struct cam_config_dev_cmd config; + + if (copy_from_user(&config, + u64_to_user_ptr(cmd->handle), + sizeof(config))) { + rc = -EFAULT; + } else { + rc = cam_cmd_buf_parser(csiphy_dev, &config); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Fail in cmd buf parser"); + goto release_mutex; + } + } + break; + } + case CAM_START_DEV: { + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + struct cam_start_stop_dev_cmd config; + int32_t offset; + + rc = copy_from_user(&config, (void __user *)cmd->handle, + sizeof(config)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + goto release_mutex; + } + + if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { + csiphy_dev->start_dev_count++; + goto release_mutex; + } + + offset = cam_csiphy_get_instance_offset(csiphy_dev, + config.dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + goto release_mutex; + } + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(csiphy_dev->cpas_handle, + &ahb_vote, &axi_vote); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "voting CPAS: %d", rc); + goto release_mutex; + } + + if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) { + rc = cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_SECURE, offset); + 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; + } + } + + rc = cam_csiphy_enable_hw(csiphy_dev); + if (rc != 0) { + CAM_ERR(CAM_CSIPHY, "cam_csiphy_enable_hw failed"); + cam_cpas_stop(csiphy_dev->cpas_handle); + goto release_mutex; + } + rc = cam_csiphy_config_dev(csiphy_dev); + if (csiphy_dump == 1) + cam_csiphy_mem_dmp(&csiphy_dev->soc_info); + + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "cam_csiphy_config_dev failed"); + cam_csiphy_disable_hw(csiphy_dev); + cam_cpas_stop(csiphy_dev->cpas_handle); + goto release_mutex; + } + csiphy_dev->start_dev_count++; + csiphy_dev->csiphy_state = CAM_CSIPHY_START; + } + break; + case CAM_CONFIG_DEV_EXTERNAL: { + struct cam_config_dev_cmd submit_cmd; + + if (copy_from_user(&submit_cmd, + u64_to_user_ptr(cmd->handle), + sizeof(struct cam_config_dev_cmd))) { + CAM_ERR(CAM_CSIPHY, "failed copy config ext\n"); + rc = -EFAULT; + } else { + rc = cam_csiphy_external_cmd(csiphy_dev, &submit_cmd); + } + break; + } + default: + CAM_ERR(CAM_CSIPHY, "Invalid Opcode: %d", cmd->op_code); + rc = -EINVAL; + goto release_mutex; + } + +release_mutex: + mutex_unlock(&csiphy_dev->mutex); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h new file mode 100644 index 000000000000..237fa787f226 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_CORE_H_ +#define _CAM_CSIPHY_CORE_H_ + +#include +#include "cam_csiphy_dev.h" +#include +#include +#include + +/** + * @csiphy_dev: CSIPhy device structure + * + * This API programs CSIPhy IRQ registers + */ +void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev); + +/** + * @csiphy_dev: CSIPhy device structure + * + * This API resets CSIPhy hardware + */ +void cam_csiphy_reset(struct csiphy_device *csiphy_dev); + +/** + * @csiphy_dev: CSIPhy device structure + * @arg: Camera control command argument + * + * This API handles the camera control argument reached to CSIPhy + */ +int cam_csiphy_core_cfg(void *csiphy_dev, void *arg); + +/** + * @irq_num: IRQ number + * @data: CSIPhy device structure + * + * This API handles CSIPhy IRQs + */ +irqreturn_t cam_csiphy_irq(int irq_num, void *data); + +/** + * @csiphy_dev: CSIPhy device structure + * + * This API handles the CSIPhy close + */ +void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev); + +#endif /* _CAM_CSIPHY_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c new file mode 100644 index 000000000000..3325071905ba --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_csiphy_dev.h" +#include "cam_req_mgr_dev.h" +#include "cam_csiphy_soc.h" +#include "cam_csiphy_core.h" +#include + +static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + int rc = 0; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_core_cfg(csiphy_dev, arg); + if (rc != 0) { + CAM_ERR(CAM_CSIPHY, "in configuring the device"); + return rc; + } + break; + default: + CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + break; + } + + return rc; +} + +static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct csiphy_device *csiphy_dev = + v4l2_get_subdevdata(sd); + + if (!csiphy_dev) { + CAM_ERR(CAM_CSIPHY, "csiphy_dev ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&csiphy_dev->mutex); + cam_csiphy_shutdown(csiphy_dev); + mutex_unlock(&csiphy_dev->mutex); + + return 0; +} + +#ifdef CONFIG_COMPAT +static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + int32_t rc = 0; + struct cam_control cmd_data; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_CSIPHY, "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + /* All the arguments converted to 64 bit here + * Passed to the api in core.c + */ + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_subdev_ioctl(sd, cmd, &cmd_data); + break; + default: + CAM_ERR(CAM_CSIPHY, "Invalid compat ioctl cmd: %d", cmd); + rc = -EINVAL; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_CSIPHY, + "Failed to copy to user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + + return rc; +} +#endif + +static struct v4l2_subdev_core_ops csiphy_subdev_core_ops = { + .ioctl = cam_csiphy_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_csiphy_subdev_compat_ioctl, +#endif +}; + +static const struct v4l2_subdev_ops csiphy_subdev_ops = { + .core = &csiphy_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops csiphy_subdev_intern_ops = { + .close = cam_csiphy_subdev_close, +}; + +static int32_t cam_csiphy_platform_probe(struct platform_device *pdev) +{ + struct cam_cpas_register_params cpas_parms; + struct csiphy_device *new_csiphy_dev; + int32_t rc = 0; + + new_csiphy_dev = devm_kzalloc(&pdev->dev, + sizeof(struct csiphy_device), GFP_KERNEL); + if (!new_csiphy_dev) + return -ENOMEM; + + new_csiphy_dev->ctrl_reg = kzalloc(sizeof(struct csiphy_ctrl_t), + GFP_KERNEL); + if (!new_csiphy_dev->ctrl_reg) { + devm_kfree(&pdev->dev, new_csiphy_dev); + return -ENOMEM; + } + + mutex_init(&new_csiphy_dev->mutex); + new_csiphy_dev->v4l2_dev_str.pdev = pdev; + + new_csiphy_dev->soc_info.pdev = pdev; + new_csiphy_dev->soc_info.dev = &pdev->dev; + new_csiphy_dev->soc_info.dev_name = pdev->name; + new_csiphy_dev->ref_count = 0; + + rc = cam_csiphy_parse_dt_info(pdev, new_csiphy_dev); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "DT parsing failed: %d", rc); + goto csiphy_no_resource; + } + + new_csiphy_dev->v4l2_dev_str.internal_ops = + &csiphy_subdev_intern_ops; + new_csiphy_dev->v4l2_dev_str.ops = + &csiphy_subdev_ops; + strlcpy(new_csiphy_dev->device_name, CAMX_CSIPHY_DEV_NAME, + sizeof(new_csiphy_dev->device_name)); + new_csiphy_dev->v4l2_dev_str.name = + new_csiphy_dev->device_name; + new_csiphy_dev->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + new_csiphy_dev->v4l2_dev_str.ent_function = + CAM_CSIPHY_DEVICE_TYPE; + new_csiphy_dev->v4l2_dev_str.token = + new_csiphy_dev; + + rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "cam_register_subdev Failed rc: %d", rc); + goto csiphy_no_resource; + } + + platform_set_drvdata(pdev, &(new_csiphy_dev->v4l2_dev_str.sd)); + + new_csiphy_dev->bridge_intf.device_hdl[0] = -1; + new_csiphy_dev->bridge_intf.device_hdl[1] = -1; + new_csiphy_dev->bridge_intf.ops.get_dev_info = + NULL; + new_csiphy_dev->bridge_intf.ops.link_setup = + NULL; + new_csiphy_dev->bridge_intf.ops.apply_req = + NULL; + + new_csiphy_dev->acquire_count = 0; + new_csiphy_dev->start_dev_count = 0; + new_csiphy_dev->is_acquired_dev_combo_mode = 0; + + cpas_parms.cam_cpas_client_cb = NULL; + cpas_parms.cell_index = new_csiphy_dev->soc_info.index; + cpas_parms.dev = &pdev->dev; + cpas_parms.userdata = new_csiphy_dev; + + strlcpy(cpas_parms.identifier, "csiphy", CAM_HW_IDENTIFIER_LENGTH); + rc = cam_cpas_register_client(&cpas_parms); + if (rc) { + CAM_ERR(CAM_CSIPHY, "CPAS registration failed rc: %d", rc); + goto csiphy_no_resource; + } + CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d", + cpas_parms.client_handle); + new_csiphy_dev->cpas_handle = cpas_parms.client_handle; + + return rc; +csiphy_no_resource: + mutex_destroy(&new_csiphy_dev->mutex); + kfree(new_csiphy_dev->ctrl_reg); + devm_kfree(&pdev->dev, new_csiphy_dev); + return rc; +} + + +static int32_t cam_csiphy_device_remove(struct platform_device *pdev) +{ + struct v4l2_subdev *subdev = + platform_get_drvdata(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; +} + +static const struct of_device_id cam_csiphy_dt_match[] = { + {.compatible = "qcom,csiphy"}, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_csiphy_dt_match); + +static struct platform_driver csiphy_driver = { + .probe = cam_csiphy_platform_probe, + .remove = cam_csiphy_device_remove, + .driver = { + .name = CAMX_CSIPHY_DEV_NAME, + .owner = THIS_MODULE, + .of_match_table = cam_csiphy_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int32_t __init cam_csiphy_init_module(void) +{ + return platform_driver_register(&csiphy_driver); +} + +static void __exit cam_csiphy_exit_module(void) +{ + platform_driver_unregister(&csiphy_driver); +} + +module_init(cam_csiphy_init_module); +module_exit(cam_csiphy_exit_module); +MODULE_DESCRIPTION("CAM CSIPHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h new file mode 100644 index 000000000000..7453db1e0658 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_DEV_H_ +#define _CAM_CSIPHY_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_soc_util.h" +#include "cam_debug_util.h" + +#define MAX_CSIPHY 6 +#define MAX_DPHY_DATA_LN 4 +#define MAX_LRME_V4l2_EVENTS 30 +#define CSIPHY_NUM_CLK_MAX 16 +#define MAX_CSIPHY_REG_ARRAY 70 +#define MAX_CSIPHY_CMN_REG_ARRAY 5 + +#define MAX_LANES 5 +#define MAX_SETTINGS_PER_LANE 43 +#define MAX_DATA_RATES 3 +#define MAX_DATA_RATE_REGS 30 + +#define MAX_REGULATOR 5 +#define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver" + +#define CSIPHY_POWER_UP 0 +#define CSIPHY_POWER_DOWN 1 + +#define CSIPHY_DEFAULT_PARAMS 0 +#define CSIPHY_LANE_ENABLE 1 +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 +#define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3 +#define CSIPHY_DNP_PARAMS 4 +#define CSIPHY_2PH_REGS 5 +#define CSIPHY_3PH_REGS 6 + +#define CSIPHY_MAX_INSTANCES 2 + +#define CAM_CSIPHY_MAX_DPHY_LANES 4 +#define CAM_CSIPHY_MAX_CPHY_LANES 3 + +#define ENABLE_IRQ false + +#undef CDBG +#ifdef CAM_CSIPHY_CORE_DEBUG +#define CDBG(fmt, args...) pr_err(fmt, ##args) +#else +#define CDBG(fmt, args...) pr_debug(fmt, ##args) +#endif + +enum cam_csiphy_state { + CAM_CSIPHY_INIT, + CAM_CSIPHY_ACQUIRE, + CAM_CSIPHY_START, +}; + +/** + * struct csiphy_reg_parms_t + * @mipi_csiphy_glbl_irq_cmd_addr: CSIPhy irq addr + * @mipi_csiphy_interrupt_status0_addr: + * CSIPhy interrupt status addr + * @mipi_csiphy_interrupt_mask0_addr: + * CSIPhy interrupt mask addr + * @mipi_csiphy_interrupt_mask_val: + * CSIPhy interrupt mask val + * @mipi_csiphy_interrupt_clear0_addr: + * CSIPhy interrupt clear addr + * @csiphy_version: CSIPhy Version + * @csiphy_common_array_size: CSIPhy common array size + * @csiphy_reset_array_size: CSIPhy reset array size + * @csiphy_2ph_config_array_size: 2ph settings size + * @csiphy_3ph_config_array_size: 3ph settings size + * @csiphy_cpas_cp_bits_per_phy: CP bits per phy + * @csiphy_cpas_cp_is_interleaved: checks whether cp bits + * are interleaved or not + * @csiphy_cpas_cp_2ph_offset: cp register 2ph offset + * @csiphy_cpas_cp_3ph_offset: cp register 3ph offset + * @csiphy_2ph_clock_lane: clock lane in 2ph + * @csiphy_2ph_combo_ck_ln: clk lane in combo 2ph + */ +struct csiphy_reg_parms_t { +/*MIPI CSI PHY registers*/ + uint32_t mipi_csiphy_glbl_irq_cmd_addr; + uint32_t mipi_csiphy_interrupt_status0_addr; + uint32_t mipi_csiphy_interrupt_mask0_addr; + uint32_t mipi_csiphy_interrupt_mask_val; + uint32_t mipi_csiphy_interrupt_mask_addr; + uint32_t mipi_csiphy_interrupt_clear0_addr; + uint32_t csiphy_version; + uint32_t csiphy_common_array_size; + uint32_t csiphy_reset_array_size; + uint32_t csiphy_2ph_config_array_size; + uint32_t csiphy_3ph_config_array_size; + uint32_t csiphy_cpas_cp_bits_per_phy; + uint32_t csiphy_cpas_cp_is_interleaved; + uint32_t csiphy_cpas_cp_2ph_offset; + uint32_t csiphy_cpas_cp_3ph_offset; + uint32_t csiphy_2ph_clock_lane; + uint32_t csiphy_2ph_combo_ck_ln; +}; + +/** + * struct intf_params + * @device_hdl: Device Handle + * @session_hdl: Session Handle + * @ops: KMD operations + * @crm_cb: Callback API pointers + */ +struct intf_params { + int32_t device_hdl[CSIPHY_MAX_INSTANCES]; + int32_t session_hdl[CSIPHY_MAX_INSTANCES]; + int32_t link_hdl[CSIPHY_MAX_INSTANCES]; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; +}; + +/** + * struct csiphy_reg_t + * @reg_addr: Register address + * @reg_data: Register data + * @delay: Delay + * @csiphy_param_type: CSIPhy parameter type + */ +struct csiphy_reg_t { + int32_t reg_addr; + int32_t reg_data; + int32_t delay; + uint32_t csiphy_param_type; +}; + +struct csiphy_device; + +/* + * struct data_rate_reg_info_t + * @bandwidth: max bandwidth supported by this reg settings + * @data_rate_reg_array_size: number of reg value pairs in the array + * @csiphy_data_rate_regs: array of data rate specific reg value pairs + */ +struct data_rate_reg_info_t { + uint64_t bandwidth; + ssize_t data_rate_reg_array_size; + struct csiphy_reg_t csiphy_data_rate_regs[MAX_DATA_RATE_REGS]; +}; + +/** + * struct data_rate_settings_t + * @num_data_rate_settings: number of valid settings + * present in the data rate settings array + * @data_rate_settings: array of regsettings which are specific to + * data rate + */ +struct data_rate_settings_t { + ssize_t num_data_rate_settings; + struct data_rate_reg_info_t data_rate_settings[MAX_DATA_RATES]; +}; + +/** + * struct csiphy_ctrl_t + * @csiphy_reg: Register address + * @csiphy_common_reg: Common register set + * @csiphy_reset_reg: Reset register set + * @csiphy_2ph_reg: 2phase register set + * @csiphy_2ph_combo_mode_reg: + * 2phase combo register set + * @csiphy_3ph_reg: 3phase register set + * @csiphy_2ph_3ph_mode_reg: + * 2 phase 3phase combo register set + * @getclockvoting: function pointer which + * is used to find the clock voting + * for the sensor output data rate + * @data_rate_settings_table: + * Table which maintains the resgister + * settings specific to data rate + */ +struct csiphy_ctrl_t { + struct csiphy_reg_parms_t csiphy_reg; + struct csiphy_reg_t *csiphy_common_reg; + struct csiphy_reg_t *csiphy_irq_reg; + struct csiphy_reg_t *csiphy_reset_reg; + struct csiphy_reg_t (*csiphy_2ph_reg)[MAX_SETTINGS_PER_LANE]; + struct csiphy_reg_t (*csiphy_2ph_combo_mode_reg)[MAX_SETTINGS_PER_LANE]; + struct csiphy_reg_t (*csiphy_3ph_reg)[MAX_SETTINGS_PER_LANE]; + struct csiphy_reg_t (*csiphy_2ph_3ph_mode_reg)[MAX_SETTINGS_PER_LANE]; + enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev); + struct data_rate_settings_t *data_rates_settings_table; +}; + +/** + * cam_csiphy_param: Provides cmdbuffer structre + * @lane_mask : Lane mask details + * @lane_assign : Lane sensor will be using + * @csiphy_3phase : Mentions DPHY or CPHY + * @combo_mode : Info regarding combo_mode is enable / disable + * @lane_cnt : Total number of lanes + * @reserved + * @3phase : Details whether 3Phase / 2Phase operation + * @settle_time : Settling time in ms + * @settle_time_combo_sensor : Settling time in ms + * @data_rate : Data rate in mbps + * @data_rate_combo_sensor: data rate of combo sensor + * in the the same phy + * + */ +struct cam_csiphy_param { + uint16_t lane_mask; + uint16_t lane_assign; + uint8_t csiphy_3phase; + uint8_t combo_mode; + uint8_t lane_cnt; + uint8_t secure_mode[CSIPHY_MAX_INSTANCES]; + uint64_t settle_time; + uint64_t settle_time_combo_sensor; + uint64_t data_rate; + uint64_t data_rate_combo_sensor; +}; + +/** + * struct csiphy_device + * @pdev: Platform device + * @irq: Interrupt structure + * @base: Base address + * @hw_version: Hardware Version + * @csiphy_state: CSIPhy state + * @ctrl_reg: CSIPhy control registers + * @num_clk: Number of clocks + * @csiphy_max_clk: Max timer clock rate + * @num_vreg: Number of regulators + * @csiphy_clk: Clock structure + * @csiphy_clk_info: Clock information structure + * @csiphy_vreg: Regulator structure + * @csiphy_reg_ptr: Regulator structure + * @csiphy_3p_clk_info: 3Phase clock information + * @csiphy_3p_clk: 3Phase clocks structure + * @csi_3phase: Is it a 3Phase mode + * @ref_count: Reference count + * @clk_lane: Clock lane + * @acquire_count: Acquire device count + * @start_dev_count: Start count + * @is_acquired_dev_combo_mode: Flag that mentions whether already acquired + * device is for combo mode + * @soc_info: SOC information + * @cpas_handle: CPAS handle + * @config_count: Config reg count + * @csiphy_cpas_cp_reg_mask: CP reg mask for phy instance + */ +struct csiphy_device { + struct mutex mutex; + uint32_t hw_version; + enum cam_csiphy_state csiphy_state; + struct csiphy_ctrl_t *ctrl_reg; + uint32_t csiphy_max_clk; + struct msm_cam_clk_info csiphy_3p_clk_info[2]; + struct clk *csiphy_3p_clk[2]; + unsigned char csi_3phase; + int32_t ref_count; + uint16_t lane_mask[MAX_CSIPHY]; + uint8_t is_csiphy_3phase_hw; + uint8_t is_divisor_32_comp; + uint8_t num_irq_registers; + struct cam_subdev v4l2_dev_str; + struct cam_csiphy_param csiphy_info; + struct intf_params bridge_intf; + uint32_t clk_lane; + uint32_t acquire_count; + uint32_t start_dev_count; + char device_name[20]; + uint32_t is_acquired_dev_combo_mode; + struct cam_hw_soc_info soc_info; + uint32_t cpas_handle; + uint32_t config_count; + uint64_t csiphy_cpas_cp_reg_mask[CSIPHY_MAX_INSTANCES]; +}; + +#endif /* _CAM_CSIPHY_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c new file mode 100644 index 000000000000..4dd5273e0438 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_csiphy_soc.h" +#include "cam_csiphy_core.h" +#include "include/cam_csiphy_1_1_hwreg.h" +#include "include/cam_csiphy_1_0_hwreg.h" +#include "include/cam_csiphy_1_2_hwreg.h" +#include "include/cam_csiphy_1_2_1_hwreg.h" +#include "include/cam_csiphy_2_0_hwreg.h" + +#define CSIPHY_DIVISOR_16 16 +#define CSIPHY_DIVISOR_32 32 +#define CSIPHY_DIVISOR_8 8 +#define BYTES_PER_REGISTER 4 +#define NUM_REGISTER_PER_LINE 4 +#define REG_OFFSET(__start, __i) ((__start) + ((__i) * BYTES_PER_REGISTER)) + +static int cam_io_phy_dump(void __iomem *base_addr, + uint32_t start_offset, int size) +{ + char line_str[128]; + char *p_str; + int i; + uint32_t data; + + CAM_INFO(CAM_CSIPHY, "addr=%pK offset=0x%x size=%d", + base_addr, start_offset, size); + + if (!base_addr || (size <= 0)) + return -EINVAL; + + line_str[0] = '\0'; + p_str = line_str; + for (i = 0; i < size; i++) { + if (i % NUM_REGISTER_PER_LINE == 0) { + snprintf(p_str, 12, "0x%08x: ", + REG_OFFSET(start_offset, i)); + p_str += 11; + } + data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i)); + snprintf(p_str, 9, "%08x ", data); + p_str += 8; + if ((i + 1) % NUM_REGISTER_PER_LINE == 0) { + CAM_ERR(CAM_CSIPHY, "%s", line_str); + line_str[0] = '\0'; + p_str = line_str; + } + } + if (line_str[0] != '\0') + CAM_ERR(CAM_CSIPHY, "%s", line_str); + + return 0; +} + +int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info) +{ + int32_t rc = 0; + resource_size_t size = 0; + void __iomem *addr = NULL; + + if (!soc_info) { + rc = -EINVAL; + CAM_ERR(CAM_CSIPHY, "invalid input %d", rc); + return rc; + } + addr = soc_info->reg_map[0].mem_base; + size = resource_size(soc_info->mem_block[0]); + rc = cam_io_phy_dump(addr, 0, (size >> 2)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "generating dump failed %d", rc); + return rc; + } + return rc; +} + +enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev) +{ + CAM_DBG(CAM_CSIPHY, "voting for SVS"); + return CAM_SVS_VOTE; +} + +enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) +{ + uint32_t cam_vote_level = 0; + uint32_t last_valid_vote = 0; + struct cam_hw_soc_info *soc_info; + uint64_t phy_data_rate = csiphy_dev->csiphy_info.data_rate; + + soc_info = &csiphy_dev->soc_info; + + if (csiphy_dev->is_acquired_dev_combo_mode) + phy_data_rate = max(phy_data_rate, + csiphy_dev->csiphy_info.data_rate_combo_sensor); + + if (csiphy_dev->csiphy_info.csiphy_3phase) { + if (csiphy_dev->is_divisor_32_comp) + do_div(phy_data_rate, CSIPHY_DIVISOR_32); + else + do_div(phy_data_rate, CSIPHY_DIVISOR_16); + } else { + do_div(phy_data_rate, CSIPHY_DIVISOR_8); + } + + /* round off to next integer */ + phy_data_rate += 1; + + for (cam_vote_level = 0; + cam_vote_level < CAM_MAX_VOTE; cam_vote_level++) { + if (soc_info->clk_level_valid[cam_vote_level] != true) + continue; + + if (soc_info->clk_rate[cam_vote_level][0] > + phy_data_rate) { + CAM_DBG(CAM_CSIPHY, + "match detected %s : %llu:%d level : %d", + soc_info->clk_name[0], + phy_data_rate, + soc_info->clk_rate[cam_vote_level][0], + cam_vote_level); + return cam_vote_level; + } + last_valid_vote = cam_vote_level; + } + return last_valid_vote; +} + +int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev) +{ + int32_t rc = 0; + struct cam_hw_soc_info *soc_info; + enum cam_vote_level vote_level = CAM_SVS_VOTE; + + soc_info = &csiphy_dev->soc_info; + + if (csiphy_dev->ref_count++) { + CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d", + csiphy_dev->ref_count); + return rc; + } + + vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev); + rc = cam_soc_util_enable_platform_resource(soc_info, true, + vote_level, ENABLE_IRQ); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d", + rc); + return rc; + } + + rc = cam_soc_util_set_src_clk_rate(soc_info, + soc_info->clk_rate[0][soc_info->src_clk_idx]); + + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "csiphy_clk_set_rate failed rc: %d", rc); + goto csiphy_disable_platform_resource; + } + + cam_csiphy_reset(csiphy_dev); + + return rc; + + +csiphy_disable_platform_resource: + cam_soc_util_disable_platform_resource(soc_info, true, true); + + return rc; +} + +int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev) +{ + struct cam_hw_soc_info *soc_info; + + if (!csiphy_dev || !csiphy_dev->ref_count) { + CAM_ERR(CAM_CSIPHY, "csiphy dev NULL / ref_count ZERO"); + return 0; + } + soc_info = &csiphy_dev->soc_info; + + if (--csiphy_dev->ref_count) { + CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d", + csiphy_dev->ref_count); + return 0; + } + + cam_csiphy_reset(csiphy_dev); + + cam_soc_util_disable_platform_resource(soc_info, true, true); + + return 0; +} + +int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, + struct csiphy_device *csiphy_dev) +{ + int32_t rc = 0, i = 0; + uint32_t clk_cnt = 0; + char *csi_3p_clk_name = "csi_phy_3p_clk"; + char *csi_3p_clk_src_name = "csiphy_3p_clk_src"; + struct cam_hw_soc_info *soc_info; + + csiphy_dev->is_csiphy_3phase_hw = 0; + soc_info = &csiphy_dev->soc_info; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "parsing common soc dt(rc %d)", rc); + return rc; + } + + csiphy_dev->is_csiphy_3phase_hw = 0; + + if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.0")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_0_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = + csiphy_3ph_v1_0_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_0; + csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_1_0; + csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_0; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_0; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->hw_version = CSIPHY_VERSION_V10; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.1")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_1_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_1_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_1_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = + csiphy_3ph_v1_1_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_1; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_1; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_1; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_1; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->hw_version = CSIPHY_VERSION_V11; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = true; + csiphy_dev->hw_version = CSIPHY_VERSION_V12; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.1")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_1_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_1_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_1_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2_1; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2_1; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2_1; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_1; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = true; + csiphy_dev->hw_version = CSIPHY_VERSION_V121; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2_1; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.2")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->hw_version = CSIPHY_VERSION_V12; + csiphy_dev->clk_lane = 0; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v2.0")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v2_0_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v2_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_2_0; + csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_2_0; + csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_2_0; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v2_0; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->hw_version = CSIPHY_VERSION_V20; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + } else { + CAM_ERR(CAM_CSIPHY, "invalid hw version : 0x%x", + csiphy_dev->hw_version); + rc = -EINVAL; + return rc; + } + + if (soc_info->num_clk > CSIPHY_NUM_CLK_MAX) { + CAM_ERR(CAM_CSIPHY, "invalid clk count=%d, max is %d", + soc_info->num_clk, CSIPHY_NUM_CLK_MAX); + return -EINVAL; + } + for (i = 0; i < soc_info->num_clk; i++) { + if (!strcmp(soc_info->clk_name[i], + csi_3p_clk_src_name)) { + csiphy_dev->csiphy_3p_clk_info[0].clk_name = + soc_info->clk_name[i]; + csiphy_dev->csiphy_3p_clk_info[0].clk_rate = + soc_info->clk_rate[0][i]; + csiphy_dev->csiphy_3p_clk[0] = + soc_info->clk[i]; + continue; + } else if (!strcmp(soc_info->clk_name[i], + csi_3p_clk_name)) { + csiphy_dev->csiphy_3p_clk_info[1].clk_name = + soc_info->clk_name[i]; + csiphy_dev->csiphy_3p_clk_info[1].clk_rate = + soc_info->clk_rate[0][i]; + csiphy_dev->csiphy_3p_clk[1] = + soc_info->clk[i]; + continue; + } + + CAM_DBG(CAM_CSIPHY, "clk_rate[%d] = %d", clk_cnt, + soc_info->clk_rate[0][clk_cnt]); + clk_cnt++; + } + + csiphy_dev->csiphy_max_clk = + soc_info->clk_rate[0][soc_info->src_clk_idx]; + + rc = cam_soc_util_request_platform_resource(&csiphy_dev->soc_info, + cam_csiphy_irq, csiphy_dev); + + return rc; +} + +int32_t cam_csiphy_soc_release(struct csiphy_device *csiphy_dev) +{ + if (!csiphy_dev) { + CAM_ERR(CAM_CSIPHY, "csiphy dev NULL"); + return 0; + } + + cam_soc_util_release_platform_resource(&csiphy_dev->soc_info); + + return 0; +} diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h new file mode 100644 index 000000000000..c02b9556add4 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_SOC_H_ +#define _CAM_CSIPHY_SOC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_csiphy_dev.h" +#include "cam_csiphy_core.h" + +#undef CDBG +#define CDBG(fmt, args...) pr_debug(fmt, ##args) + +#define CSI_3PHASE_HW 1 +#define CSIPHY_VERSION_V35 0x35 +#define CSIPHY_VERSION_V10 0x10 +#define CSIPHY_VERSION_V11 0x11 +#define CSIPHY_VERSION_V12 0x12 +#define CSIPHY_VERSION_V121 0x121 +#define CSIPHY_VERSION_V20 0x20 + +/** + * @csiphy_dev: CSIPhy device structure + * + * This API release SOC related parameters + */ +int cam_csiphy_soc_release(struct csiphy_device *csiphy_dev); + +/** + * @pdev: Platform device + * @csiphy_dev: CSIPhy device structure + * + * This API parses csiphy device tree information + */ +int cam_csiphy_parse_dt_info(struct platform_device *pdev, + struct csiphy_device *csiphy_dev); + +/** + * @csiphy_dev: CSIPhy device structure + * + * This API enables SOC related parameters + */ +int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev); + +/** + * @csiphy_dev: CSIPhy device structure + * + * This API disables SOC related parameters + */ +int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev); + +/** + * @soc_info: Soc info of cam hw driver module + * + * This API dumps memory for the entire mapped region + * (needs to be macro enabled before use) + */ +int cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info); + +#endif /* _CAM_CSIPHY_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h new file mode 100644 index 000000000000..e910162858b3 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_0_HWREG_H_ +#define _CAM_CSIPHY_1_0_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_0 = { + .mipi_csiphy_interrupt_status0_addr = 0x8B0, + .mipi_csiphy_interrupt_clear0_addr = 0x858, + .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_common_array_size = 5, + .csiphy_reset_array_size = 5, + .csiphy_2ph_config_array_size = 14, + .csiphy_3ph_config_array_size = 19, +}; + +struct csiphy_reg_t csiphy_common_reg_1_0[] = { + {0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_1_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_1_0[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_2ph_v1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x14, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_0_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x0A, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x14, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x0A, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t csiphy_3ph_v1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x015C, 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x035C, 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x055C, 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_3ph_v1_0_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x015C, 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x035C, 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x055C, 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +#endif /* _CAM_CSIPHY_1_0_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h new file mode 100644 index 000000000000..30b61067a792 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h @@ -0,0 +1,499 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_1_HWREG_H_ +#define _CAM_CSIPHY_1_1_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_1 = { + .mipi_csiphy_interrupt_status0_addr = 0x8B0, + .mipi_csiphy_interrupt_clear0_addr = 0x858, + .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_common_array_size = 5, + .csiphy_reset_array_size = 5, + .csiphy_2ph_config_array_size = 14, + .csiphy_3ph_config_array_size = 43, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_1[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_1_1[] = { + {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_1_1[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct +csiphy_reg_t csiphy_2ph_v1_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_1_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x31, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x31, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x31, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x31, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x31, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct +csiphy_reg_t csiphy_3ph_v1_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0144, 0xB6, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0x5F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0x8E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x59, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x24, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09AC, 0x55, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x2B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0344, 0xB6, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0x5F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0x8E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x59, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x24, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AAC, 0x55, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x2B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0544, 0xB6, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0x5F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0x8E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x59, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x24, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BAC, 0x55, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x2B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_3ph_v1_1_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0144, 0xB6, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0x5F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0x8E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x59, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09AC, 0x55, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x2B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0344, 0xB6, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0x5F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0x8E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x59, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AAC, 0x55, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x2B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0544, 0xB6, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0x5F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0x8E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x59, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x48, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BAC, 0x55, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x2B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +#endif /* _CAM_CSIPHY_D5_0_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h new file mode 100644 index 000000000000..4f9fd086a97d --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -0,0 +1,491 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_2_1_HWREG_H_ +#define _CAM_CSIPHY_1_2_1_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_2_1 = { + .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 = 5, + .csiphy_2ph_config_array_size = 21, + .csiphy_3ph_config_array_size = 34, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_2_1[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, + {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_1_2_1[] = { + {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE}, + {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_irq_reg_1_2_1[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct +csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_2_1_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, +}; + +struct +csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct data_rate_settings_t data_rate_delta_table_1_2_1 = { + .num_data_rate_settings = 3, + .data_rate_settings = { + { + /* (2.5 * 10**3 * 2.28) rounded value*/ + .bandwidth = 5700000000, + .data_rate_reg_array_size = 12, + .csiphy_data_rate_regs = { + {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + } + }, + { + /* (3.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 7980000000, + .data_rate_reg_array_size = 24, + .csiphy_data_rate_regs = { + {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + /* (4.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 10260000000, + .data_rate_reg_array_size = 24, + .csiphy_data_rate_regs = { + {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + } + } +}; + +#endif /* _CAM_CSIPHY_1_2_1_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h new file mode 100644 index 000000000000..6ee9e155b93d --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -0,0 +1,512 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_2_HWREG_H_ +#define _CAM_CSIPHY_1_2_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_2 = { + .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 = 5, + .csiphy_2ph_config_array_size = 22, + .csiphy_3ph_config_array_size = 38, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_2[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, + {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, +}; + +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}, +}; + +struct csiphy_reg_t csiphy_irq_reg_1_2[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct +csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, +}; + +struct +csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x015C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x035C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x055C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct data_rate_settings_t data_rate_delta_table = { + .num_data_rate_settings = 3, + .data_rate_settings = { + { + /* (2.5 * 10**3 * 2.28) rounded value*/ + .bandwidth = 5700000000, + .data_rate_reg_array_size = 12, + .csiphy_data_rate_regs = { + {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + } + }, + { + /* (3.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 7980000000, + .data_rate_reg_array_size = 24, + .csiphy_data_rate_regs = { + {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + /* (4.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 10260000000, + .data_rate_reg_array_size = 24, + .csiphy_data_rate_regs = { + {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + } + } +}; +#endif /* _CAM_CSIPHY_1_2_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h new file mode 100644 index 000000000000..cbd0dc582b32 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h @@ -0,0 +1,289 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_2_0_HWREG_H_ +#define _CAM_CSIPHY_2_0_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +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_2ph_config_array_size = 15, + .csiphy_3ph_config_array_size = 17, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +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}, + {0x0164, 0x00, 0x00, CSIPHY_2PH_REGS}, + {0x0364, 0x00, 0x00, CSIPHY_2PH_REGS}, + {0x0564, 0x00, 0x00, CSIPHY_2PH_REGS}, +}; + +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}, +}; + +struct csiphy_reg_t csiphy_irq_reg_2_0[] = { + {0x082c, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xff, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xfb, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xef, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_2ph_v2_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v2_0_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xD7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x3F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t csiphy_3ph_v2_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x015C, 0x23, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0x70, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x17, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x035C, 0x23, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0x70, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x17, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x055C, 0x23, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0x70, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x17, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +#endif /* _CAM_CSIPHY_2_0_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_eeprom/Makefile b/drivers/cam_sensor_module/cam_eeprom/Makefile new file mode 100644 index 000000000000..e52bc01dc5a5 --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom_dev.o cam_eeprom_core.o cam_eeprom_soc.o diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c new file mode 100644 index 000000000000..b211471adf00 --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -0,0 +1,1506 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_eeprom_core.h" +#include "cam_eeprom_soc.h" +#include "cam_debug_util.h" +#include "cam_common_util.h" +#include "cam_packet_util.h" + +#define MAX_READ_SIZE 0x7FFFF + +/** + * cam_eeprom_read_memory() - read map data into buffer + * @e_ctrl: eeprom control struct + * @block: block to be read + * + * This function iterates through blocks stored in block->map, reads each + * region and concatenate them into the pre-allocated block->mapdata + */ +static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_eeprom_memory_block_t *block) +{ + int rc = 0; + int j; + struct cam_sensor_i2c_reg_setting i2c_reg_settings = {0}; + struct cam_sensor_i2c_reg_array i2c_reg_array = {0}; + struct cam_eeprom_memory_map_t *emap = block->map; + struct cam_eeprom_soc_private *eb_info = NULL; + uint8_t *memptr = block->mapdata; + + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "e_ctrl is NULL"); + return -EINVAL; + } + + eb_info = (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + + for (j = 0; j < block->num_map; j++) { + CAM_DBG(CAM_EEPROM, "slave-addr = 0x%X", emap[j].saddr); + if (emap[j].saddr) { + eb_info->i2c_info.slave_addr = emap[j].saddr; + rc = cam_eeprom_update_i2c_info(e_ctrl, + &eb_info->i2c_info); + if (rc) { + CAM_ERR(CAM_EEPROM, + "failed: to update i2c info rc %d", + rc); + return rc; + } + } + + if (emap[j].page.valid_size) { + i2c_reg_settings.addr_type = emap[j].page.addr_type; + i2c_reg_settings.data_type = emap[j].page.data_type; + i2c_reg_settings.size = 1; + i2c_reg_array.reg_addr = emap[j].page.addr; + i2c_reg_array.reg_data = emap[j].page.data; + i2c_reg_array.delay = emap[j].page.delay; + i2c_reg_settings.reg_setting = &i2c_reg_array; + rc = camera_io_dev_write(&e_ctrl->io_master_info, + &i2c_reg_settings); + if (rc) { + CAM_ERR(CAM_EEPROM, "page write failed rc %d", + rc); + return rc; + } + memptr = block->mapdata + emap[j].mem.valid_size; + } + + if (emap[j].pageen.valid_size) { + i2c_reg_settings.addr_type = emap[j].pageen.addr_type; + i2c_reg_settings.data_type = emap[j].pageen.data_type; + i2c_reg_settings.size = 1; + i2c_reg_array.reg_addr = emap[j].pageen.addr; + i2c_reg_array.reg_data = emap[j].pageen.data; + i2c_reg_array.delay = emap[j].pageen.delay; + i2c_reg_settings.reg_setting = &i2c_reg_array; + rc = camera_io_dev_write(&e_ctrl->io_master_info, + &i2c_reg_settings); + if (rc) { + CAM_ERR(CAM_EEPROM, "page enable failed rc %d", + rc); + return rc; + } + } + + if (emap[j].poll.valid_size) { + rc = camera_io_dev_poll(&e_ctrl->io_master_info, + emap[j].poll.addr, emap[j].poll.data, + 0, emap[j].poll.addr_type, + emap[j].poll.data_type, + emap[j].poll.delay); + if (rc) { + CAM_ERR(CAM_EEPROM, "poll failed rc %d", + rc); + return rc; + } + } + + if (emap[j].mem.valid_size) { + rc = camera_io_dev_read_seq(&e_ctrl->io_master_info, + emap[j].mem.addr, memptr, + emap[j].mem.addr_type, + emap[j].mem.data_type, + emap[j].mem.valid_size); + if (rc) { + CAM_ERR(CAM_EEPROM, "read failed rc %d", + rc); + return rc; + } + memptr += emap[j].mem.valid_size; + } + + if (emap[j].pageen.valid_size) { + i2c_reg_settings.addr_type = emap[j].pageen.addr_type; + i2c_reg_settings.data_type = emap[j].pageen.data_type; + i2c_reg_settings.size = 1; + i2c_reg_array.reg_addr = emap[j].pageen.addr; + i2c_reg_array.reg_data = 0; + i2c_reg_array.delay = emap[j].pageen.delay; + i2c_reg_settings.reg_setting = &i2c_reg_array; + rc = camera_io_dev_write(&e_ctrl->io_master_info, + &i2c_reg_settings); + if (rc) { + CAM_ERR(CAM_EEPROM, + "page disable failed rc %d", + rc); + return rc; + } + } + } + return rc; +} + +/** + * cam_eeprom_power_up - Power up eeprom hardware + * @e_ctrl: ctrl structure + * @power_info: power up/down info for eeprom + * + * Returns success or failure + */ +static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_sensor_power_ctrl_t *power_info) +{ + int32_t rc = 0; + struct cam_hw_soc_info *soc_info = + &e_ctrl->soc_info; + + /* Parse and fill vreg params for power up settings */ + rc = msm_camera_fill_vreg_params( + &e_ctrl->soc_info, + power_info->power_setting, + power_info->power_setting_size); + if (rc) { + CAM_ERR(CAM_EEPROM, + "failed to fill power up vreg params rc:%d", rc); + return rc; + } + + /* Parse and fill vreg params for power down settings*/ + rc = msm_camera_fill_vreg_params( + &e_ctrl->soc_info, + power_info->power_down_setting, + power_info->power_down_setting_size); + if (rc) { + CAM_ERR(CAM_EEPROM, + "failed to fill power down vreg params rc:%d", rc); + return rc; + } + + power_info->dev = soc_info->dev; + + rc = cam_sensor_core_power_up(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed in eeprom power up rc %d", rc); + return rc; + } + + if (e_ctrl->io_master_info.master_type == CCI_MASTER) { + rc = camera_io_init(&(e_ctrl->io_master_info)); + if (rc) { + CAM_ERR(CAM_EEPROM, "cci_init failed"); + return -EINVAL; + } + } + return rc; +} + +/** + * cam_eeprom_power_down - Power down eeprom hardware + * @e_ctrl: ctrl structure + * + * Returns success or failure + */ +static int cam_eeprom_power_down(struct cam_eeprom_ctrl_t *e_ctrl) +{ + struct cam_sensor_power_ctrl_t *power_info; + struct cam_hw_soc_info *soc_info; + struct cam_eeprom_soc_private *soc_private; + int rc = 0; + + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "failed: e_ctrl %pK", e_ctrl); + return -EINVAL; + } + + soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + soc_info = &e_ctrl->soc_info; + + if (!power_info) { + CAM_ERR(CAM_EEPROM, "failed: power_info %pK", power_info); + return -EINVAL; + } + rc = cam_sensor_util_power_down(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "power down the core is failed:%d", rc); + return rc; + } + + if (e_ctrl->io_master_info.master_type == CCI_MASTER) + camera_io_release(&(e_ctrl->io_master_info)); + + return rc; +} + +/** + * cam_eeprom_match_id - match eeprom id + * @e_ctrl: ctrl structure + * + * Returns success or failure + */ +static int cam_eeprom_match_id(struct cam_eeprom_ctrl_t *e_ctrl) +{ + int rc; + struct camera_io_master *client = &e_ctrl->io_master_info; + uint8_t id[2]; + + rc = cam_spi_query_id(client, 0, CAMERA_SENSOR_I2C_TYPE_WORD, + &id[0], 2); + if (rc) + return rc; + CAM_DBG(CAM_EEPROM, "read 0x%x 0x%x, check 0x%x 0x%x", + id[0], id[1], client->spi_client->mfr_id0, + client->spi_client->device_id0); + if (id[0] != client->spi_client->mfr_id0 + || id[1] != client->spi_client->device_id0) + return -ENODEV; + return 0; +} + +/** + * cam_eeprom_parse_read_memory_map - Parse memory map + * @of_node: device node + * @e_ctrl: ctrl structure + * + * Returns success or failure + */ +int32_t cam_eeprom_parse_read_memory_map(struct device_node *of_node, + struct cam_eeprom_ctrl_t *e_ctrl) +{ + int32_t rc = 0; + struct cam_eeprom_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "failed: e_ctrl is NULL"); + return -EINVAL; + } + + soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + + rc = cam_eeprom_parse_dt_memory_map(of_node, &e_ctrl->cal_data); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: eeprom dt parse rc %d", rc); + return rc; + } + rc = cam_eeprom_power_up(e_ctrl, power_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: eeprom power up rc %d", rc); + goto data_mem_free; + } + + e_ctrl->cam_eeprom_state = CAM_EEPROM_CONFIG; + if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE) { + rc = cam_eeprom_match_id(e_ctrl); + if (rc) { + CAM_DBG(CAM_EEPROM, "eeprom not matching %d", rc); + goto power_down; + } + } + rc = cam_eeprom_read_memory(e_ctrl, &e_ctrl->cal_data); + if (rc) { + CAM_ERR(CAM_EEPROM, "read_eeprom_memory failed"); + goto power_down; + } + + rc = cam_eeprom_power_down(e_ctrl); + if (rc) + CAM_ERR(CAM_EEPROM, "failed: eeprom power down rc %d", rc); + + e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE; + return rc; +power_down: + cam_eeprom_power_down(e_ctrl); +data_mem_free: + vfree(e_ctrl->cal_data.mapdata); + vfree(e_ctrl->cal_data.map); + e_ctrl->cal_data.num_data = 0; + e_ctrl->cal_data.num_map = 0; + e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE; + return rc; +} + +/** + * cam_eeprom_get_dev_handle - get device handle + * @e_ctrl: ctrl structure + * @arg: Camera control command argument + * + * Returns success or failure + */ +static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl, + void *arg) +{ + struct cam_sensor_acquire_dev eeprom_acq_dev; + struct cam_create_dev_hdl bridge_params; + struct cam_control *cmd = (struct cam_control *)arg; + + if (e_ctrl->bridge_intf.device_hdl != -1) { + CAM_ERR(CAM_EEPROM, "Device is already acquired"); + return -EFAULT; + } + if (copy_from_user(&eeprom_acq_dev, + u64_to_user_ptr(cmd->handle), + sizeof(eeprom_acq_dev))) { + CAM_ERR(CAM_EEPROM, + "EEPROM:ACQUIRE_DEV: copy from user failed"); + return -EFAULT; + } + + bridge_params.session_hdl = eeprom_acq_dev.session_handle; + bridge_params.ops = &e_ctrl->bridge_intf.ops; + bridge_params.v4l2_sub_dev_flag = 0; + bridge_params.media_entity_flag = 0; + bridge_params.priv = e_ctrl; + + eeprom_acq_dev.device_handle = + cam_create_device_hdl(&bridge_params); + e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle; + e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle; + + CAM_DBG(CAM_EEPROM, "Device Handle: %d", eeprom_acq_dev.device_handle); + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &eeprom_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { + CAM_ERR(CAM_EEPROM, "EEPROM:ACQUIRE_DEV: copy to user failed"); + return -EFAULT; + } + return 0; +} + +/** + * cam_eeprom_update_slaveInfo - Update slave info + * @e_ctrl: ctrl structure + * @cmd_buf: command buffer + * + * Returns success or failure + */ +static int32_t cam_eeprom_update_slaveInfo(struct cam_eeprom_ctrl_t *e_ctrl, + void *cmd_buf) +{ + int32_t rc = 0; + struct cam_eeprom_soc_private *soc_private; + struct cam_cmd_i2c_info *cmd_i2c_info = NULL; + + soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + cmd_i2c_info = (struct cam_cmd_i2c_info *)cmd_buf; + soc_private->i2c_info.slave_addr = cmd_i2c_info->slave_addr; + soc_private->i2c_info.i2c_freq_mode = cmd_i2c_info->i2c_freq_mode; + + rc = cam_eeprom_update_i2c_info(e_ctrl, + &soc_private->i2c_info); + CAM_DBG(CAM_EEPROM, "Slave addr: 0x%x Freq Mode: %d", + soc_private->i2c_info.slave_addr, + soc_private->i2c_info.i2c_freq_mode); + + return rc; +} + +/** + * cam_eeprom_parse_memory_map - Parse memory map info + * @data: memory block data + * @cmd_buf: command buffer + * @cmd_length: command buffer length + * @num_map: memory map size + * @cmd_length_bytes: command length processed in this function + * + * Returns success or failure + */ +static int32_t cam_eeprom_parse_memory_map( + struct cam_eeprom_memory_block_t *data, + void *cmd_buf, int cmd_length, uint32_t *cmd_length_bytes, + int *num_map, size_t remain_buf_len) +{ + int32_t rc = 0; + int32_t cnt = 0; + int32_t processed_size = 0; + uint8_t generic_op_code; + struct cam_eeprom_memory_map_t *map = data->map; + struct common_header *cmm_hdr = + (struct common_header *)cmd_buf; + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_random_wr *i2c_random_wr = NULL; + 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->fifth_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 || + *num_map >= MSM_EEPROM_MAX_MEM_MAP_CNT) { + 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; + + if (i2c_random_wr->header.count == 0 || + i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT || + (size_t)*num_map > U16_MAX - i2c_random_wr->header.count) { + CAM_ERR(CAM_EEPROM, "OOB Error"); + return -EINVAL; + } + cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) + + ((i2c_random_wr->header.count - 1) * + sizeof(struct i2c_random_wr_payload)); + + if (cmd_length_in_bytes > remain_buf_len) { + CAM_ERR(CAM_EEPROM, "Not enough buffer remaining"); + return -EINVAL; + } + for (cnt = 0; cnt < (i2c_random_wr->header.count); + cnt++) { + map[*num_map + cnt].page.addr = + i2c_random_wr->random_wr_payload[cnt].reg_addr; + map[*num_map + cnt].page.addr_type = + i2c_random_wr->header.addr_type; + map[*num_map + cnt].page.data = + i2c_random_wr->random_wr_payload[cnt].reg_data; + map[*num_map + cnt].page.data_type = + i2c_random_wr->header.data_type; + map[*num_map + cnt].page.valid_size = 1; + } + + *num_map += (i2c_random_wr->header.count - 1); + cmd_buf += cmd_length_in_bytes / sizeof(int32_t); + processed_size += + cmd_length_in_bytes; + break; + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD: + i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf; + cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd); + + if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) { + CAM_ERR(CAM_EEPROM, + "int overflow on eeprom memory block"); + return -EINVAL; + } + map[*num_map].mem.addr = i2c_cont_rd->reg_addr; + map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type; + map[*num_map].mem.data_type = i2c_cont_rd->header.data_type; + map[*num_map].mem.valid_size = + i2c_cont_rd->header.count; + cmd_buf += cmd_length_in_bytes / sizeof(int32_t); + processed_size += + cmd_length_in_bytes; + data->num_data += map[*num_map].mem.valid_size; + break; + case CAMERA_SENSOR_CMD_TYPE_WAIT: + if (generic_op_code == + CAMERA_SENSOR_WAIT_OP_HW_UCND || + generic_op_code == + CAMERA_SENSOR_WAIT_OP_SW_UCND) { + i2c_uncond_wait = + (struct cam_cmd_unconditional_wait *)cmd_buf; + cmd_length_in_bytes = + sizeof(struct cam_cmd_unconditional_wait); + + if (*num_map < 1) { + CAM_ERR(CAM_EEPROM, + "invalid map number, num_map=%d", + *num_map); + return -EINVAL; + } + + /* + * Though delay is added all of them, but delay will + * be applicable to only one of them as only one of + * them will have valid_size set to >= 1. + */ + map[*num_map - 1].mem.delay = i2c_uncond_wait->delay; + map[*num_map - 1].page.delay = i2c_uncond_wait->delay; + map[*num_map - 1].pageen.delay = i2c_uncond_wait->delay; + } else if (generic_op_code == + CAMERA_SENSOR_WAIT_OP_COND) { + i2c_poll = (struct cam_cmd_conditional_wait *)cmd_buf; + cmd_length_in_bytes = + sizeof(struct cam_cmd_conditional_wait); + + map[*num_map].poll.addr = i2c_poll->reg_addr; + map[*num_map].poll.addr_type = i2c_poll->addr_type; + map[*num_map].poll.data = i2c_poll->reg_data; + map[*num_map].poll.data_type = i2c_poll->data_type; + map[*num_map].poll.delay = i2c_poll->timeout; + map[*num_map].poll.valid_size = 1; + } + cmd_buf += cmd_length_in_bytes / sizeof(int32_t); + processed_size += + cmd_length_in_bytes; + break; + default: + break; + } + + *cmd_length_bytes = processed_size; + return rc; +} + +static struct i2c_settings_list* + cam_eeprom_get_i2c_ptr(struct i2c_settings_array *i2c_reg_settings, + uint32_t size) +{ + struct i2c_settings_list *tmp; + + tmp = kzalloc(sizeof(struct i2c_settings_list), GFP_KERNEL); + + if (tmp != NULL) + list_add_tail(&(tmp->list), + &(i2c_reg_settings->list_head)); + else + return NULL; + + tmp->seq_settings.reg_data = + kcalloc(size, sizeof(uint8_t), GFP_KERNEL); + if (tmp->seq_settings.reg_data == NULL) { + list_del(&(tmp->list)); + kfree(tmp); + tmp = NULL; + return NULL; + } + tmp->seq_settings.size = size; + + return tmp; +} + +static int32_t cam_eeprom_handle_continuous_write( + struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_cmd_i2c_continuous_wr *cam_cmd_i2c_continuous_wr, + struct i2c_settings_array *i2c_reg_settings, + uint32_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt = 0; + + + CAM_DBG(CAM_EEPROM, "Total Size: %d", + cam_cmd_i2c_continuous_wr->header.count); + + i2c_list = cam_eeprom_get_i2c_ptr(i2c_reg_settings, + cam_cmd_i2c_continuous_wr->header.count); + if (i2c_list == NULL || + i2c_list->seq_settings.reg_data == NULL) { + CAM_ERR(CAM_SENSOR, "Failed in allocating i2c_list"); + return -ENOMEM; + } + + *cmd_length_in_bytes = (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 (cam_cmd_i2c_continuous_wr->header.op_code == + CAMERA_SENSOR_I2C_OP_CONT_WR_BRST) + i2c_list->op_code = CAM_SENSOR_I2C_WRITE_BURST; + else if (cam_cmd_i2c_continuous_wr->header.op_code == + CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN) + i2c_list->op_code = CAM_SENSOR_I2C_WRITE_SEQ; + else { + rc = -EINVAL; + goto deallocate_i2c_list; + } + + i2c_list->seq_settings.addr_type = + cam_cmd_i2c_continuous_wr->header.addr_type; + + CAM_ERR(CAM_EEPROM, "Write Address: 0x%x", + cam_cmd_i2c_continuous_wr->reg_addr); + if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + i2c_list->op_code = CAM_SENSOR_I2C_WRITE_RANDOM; + e_ctrl->eebin_info.start_address = + cam_cmd_i2c_continuous_wr->reg_addr; + e_ctrl->eebin_info.size = + cam_cmd_i2c_continuous_wr->header.count; + CAM_DBG(CAM_EEPROM, "Header Count: %d", + cam_cmd_i2c_continuous_wr->header.count); + e_ctrl->eebin_info.is_valid = 1; + + i2c_list->seq_settings.reg_addr = + cam_cmd_i2c_continuous_wr->reg_addr; + } else + CAM_ERR(CAM_EEPROM, "Burst Mode Not Supported\n"); + + (*offset) += cnt; + *list = &(i2c_list->list); + return rc; +deallocate_i2c_list: + kfree(i2c_list); + return rc; +} + +static int32_t cam_eeprom_handle_delay( + uint32_t **cmd_buf, + uint16_t generic_op_code, + struct i2c_settings_array *i2c_reg_settings, + uint32_t offset, uint32_t *byte_cnt, + struct list_head *list_ptr, + size_t remain_buf_len) +{ + int32_t rc = 0; + struct i2c_settings_list *i2c_list = NULL; + struct cam_cmd_unconditional_wait *cmd_uncond_wait = + (struct cam_cmd_unconditional_wait *) *cmd_buf; + + if (remain_buf_len < (sizeof(struct cam_cmd_unconditional_wait))) { + CAM_ERR(CAM_EEPROM, "Not Enough buffer"); + return -EINVAL; + } + + if (list_ptr == NULL) { + CAM_ERR(CAM_SENSOR, "Invalid list ptr"); + return -EINVAL; + } + + if (offset > 0) { + i2c_list = + list_entry(list_ptr, struct i2c_settings_list, list); + if (generic_op_code == + CAMERA_SENSOR_WAIT_OP_HW_UCND) + i2c_list->i2c_settings.reg_setting[offset - 1].delay = + cmd_uncond_wait->delay; + else + i2c_list->i2c_settings.delay = + cmd_uncond_wait->delay; + (*cmd_buf) += + sizeof( + struct cam_cmd_unconditional_wait) / sizeof(uint32_t); + (*byte_cnt) += + sizeof( + struct cam_cmd_unconditional_wait); + } else { + CAM_ERR(CAM_SENSOR, "Delay Rxed before any buffer: %d", offset); + return -EINVAL; + } + + return rc; +} + +/** + * cam_eeprom_parse_write_memory_packet - Write eeprom packet + * @csl_packet: csl packet received + * @e_ctrl: ctrl structure + * + * Returns success or failure + */ +static int32_t cam_eeprom_parse_write_memory_packet( + struct cam_packet *csl_packet, + struct cam_eeprom_ctrl_t *e_ctrl) +{ + struct cam_cmd_buf_desc *cmd_desc = NULL; + uint32_t *offset = NULL; + int32_t i, rc = 0; + 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; + uint32_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_info *i2c_info = NULL; + + + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + CAM_DBG(CAM_EEPROM, "Number of Command Buffers: %d", + csl_packet->num_cmd_buf); + for (i = 0; i < csl_packet->num_cmd_buf; i++) { + struct list_head *list = NULL; + uint16_t generic_op_code; + uint32_t off = 0; + int master; + struct cam_sensor_cci_client *cci; + + total_cmd_buf_in_bytes = cmd_desc[i].length; + processed_cmd_buf_in_bytes = 0; + + if (!total_cmd_buf_in_bytes) + continue; + + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &generic_pkt_addr, &pkt_len); + if (rc) { + CAM_ERR(CAM_EEPROM, "Failed to get cpu buf"); + return rc; + } + + cmd_buf = (uint32_t *)generic_pkt_addr; + if (!cmd_buf) { + CAM_ERR(CAM_EEPROM, "invalid cmd buf"); + rc = -EINVAL; + goto end; + } + + 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 end; + } + + 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 end; + } + + master = e_ctrl->io_master_info.master_type; + cci = e_ctrl->io_master_info.cci_client; + 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 buffer"); + rc = -EINVAL; + goto end; + } + cmm_hdr = (struct common_header *)cmd_buf; + generic_op_code = cmm_hdr->fifth_byte; + + 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 end; + } + if (master == CCI_MASTER) { + cci->cci_i2c_master = + e_ctrl->cci_i2c_master; + cci->i2c_freq_mode = + i2c_info->i2c_freq_mode; + cci->sid = + i2c_info->slave_addr >> 1; + CAM_DBG(CAM_EEPROM, + "Slave addr: 0x%x Freq Mode: %d", + i2c_info->slave_addr, + i2c_info->i2c_freq_mode); + } else if (master == I2C_MASTER) { + e_ctrl->io_master_info.client->addr = + i2c_info->slave_addr; + CAM_DBG(CAM_EEPROM, + "Slave addr: 0x%x", + i2c_info->slave_addr); + } else if (master == SPI_MASTER) { + CAM_ERR(CAM_EEPROM, + "No Need of Slave Info"); + } else { + CAM_ERR(CAM_EEPROM, + "Invalid Master type: %d", + master); + rc = -EINVAL; + goto end; + } + cmd_length_in_bytes = + sizeof(struct cam_cmd_i2c_info); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/4; + break; + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR: { + struct cam_cmd_i2c_continuous_wr + *cam_cmd_i2c_continuous_wr = + (struct cam_cmd_i2c_continuous_wr *) + cmd_buf; + if ((remain_len - processed_cmd_buf_in_bytes) < + sizeof(struct cam_cmd_i2c_continuous_wr)) { + CAM_ERR(CAM_EEPROM, "Not enough buf"); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_EEPROM, + "CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR"); + rc = cam_eeprom_handle_continuous_write( + e_ctrl, + cam_cmd_i2c_continuous_wr, + &(e_ctrl->wr_settings), + &cmd_length_in_bytes, &off, &list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in continuous write %d", rc); + goto end; + } + + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + break; + } + case CAMERA_SENSOR_CMD_TYPE_WAIT: { + CAM_DBG(CAM_EEPROM, + "CAMERA_SENSOR_CMD_TYPE_WAIT"); + if (generic_op_code == + CAMERA_SENSOR_WAIT_OP_HW_UCND || + generic_op_code == + CAMERA_SENSOR_WAIT_OP_SW_UCND) { + + rc = cam_eeprom_handle_delay( + &cmd_buf, generic_op_code, + &(e_ctrl->wr_settings), off, + &cmd_length_in_bytes, + list, (remain_len - + processed_cmd_buf_in_bytes)); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, + "delay hdl failed: %d", + rc); + goto end; + } + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + } else { + CAM_ERR(CAM_EEPROM, + "Wrong Wait Command: %d", + generic_op_code); + rc = -EINVAL; + goto end; + } + break; + } + default: + CAM_ERR(CAM_EEPROM, + "Invalid Cmd_type rxed: %d\n", + cmm_hdr->cmd_type); + rc = -EINVAL; + break; + } + } + } + +end: + return rc; +} + +/** + * cam_eeprom_init_pkt_parser - Parse eeprom packet + * @e_ctrl: ctrl structure + * @csl_packet: csl packet received + * + * Returns success or failure + */ +static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_packet *csl_packet) +{ + int32_t rc = 0; + int i = 0; + struct cam_cmd_buf_desc *cmd_desc = NULL; + uint32_t *offset = NULL; + 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; + uint32_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_info *i2c_info = NULL; + int num_map = -1; + struct cam_eeprom_memory_map_t *map = NULL; + struct cam_eeprom_soc_private *soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + + e_ctrl->cal_data.map = vzalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE * + MSM_EEPROM_MAX_MEM_MAP_CNT) * + (sizeof(struct cam_eeprom_memory_map_t))); + if (!e_ctrl->cal_data.map) { + rc = -ENOMEM; + CAM_ERR(CAM_EEPROM, "failed"); + return rc; + } + map = e_ctrl->cal_data.map; + + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + /* Loop through multiple command buffers */ + for (i = 0; i < csl_packet->num_cmd_buf; i++) { + total_cmd_buf_in_bytes = cmd_desc[i].length; + processed_cmd_buf_in_bytes = 0; + if (!total_cmd_buf_in_bytes) + continue; + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &generic_pkt_addr, &pkt_len); + if (rc) { + CAM_ERR(CAM_EEPROM, "Failed to get cpu buf"); + return rc; + } + cmd_buf = (uint32_t *)generic_pkt_addr; + if (!cmd_buf) { + CAM_ERR(CAM_EEPROM, "invalid cmd buf"); + rc = -EINVAL; + goto end; + } + + 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 end; + } + 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 end; + } + /* 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 end; + } + 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 end; + } + /* Configure the following map slave address */ + map[num_map + 1].saddr = i2c_info->slave_addr; + rc = cam_eeprom_update_slaveInfo(e_ctrl, + cmd_buf); + cmd_length_in_bytes = + sizeof(struct cam_cmd_i2c_info); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + break; + case CAMERA_SENSOR_CMD_TYPE_PWR_UP: + 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, + (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"); + goto end; + } + break; + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD: + case CAMERA_SENSOR_CMD_TYPE_WAIT: + num_map++; + rc = cam_eeprom_parse_memory_map( + &e_ctrl->cal_data, cmd_buf, + total_cmd_buf_in_bytes, + &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); + break; + default: + CAM_ERR(CAM_EEPROM, "Invalid cmd_type 0x%x", + cmm_hdr->cmd_type); + rc = -EINVAL; + goto end; + } + } + e_ctrl->cal_data.num_map = num_map + 1; + } + +end: + return rc; +} + +/** + * cam_eeprom_get_cal_data - parse the userspace IO config and + * copy read data to share with userspace + * @e_ctrl: ctrl structure + * @csl_packet: csl packet received + * + * Returns success or failure + */ +static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_packet *csl_packet) +{ + struct cam_buf_io_cfg *io_cfg; + uint32_t i = 0; + int rc = 0; + 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 + + csl_packet->io_configs_offset); + + CAM_DBG(CAM_EEPROM, "number of IO configs: %d:", + csl_packet->num_io_configs); + + for (i = 0; i < csl_packet->num_io_configs; i++) { + CAM_DBG(CAM_EEPROM, "Direction: %d:", io_cfg->direction); + 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; + return rc; + } + + remain_len = buf_size - io_cfg->offsets[0]; + CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n", + (void *)buf_addr, buf_size); + + read_buffer = (uint8_t *)buf_addr; + if (!read_buffer) { + CAM_ERR(CAM_EEPROM, + "invalid buffer to copy data"); + rc = -EINVAL; + return rc; + } + read_buffer += io_cfg->offsets[0]; + + if (remain_len < e_ctrl->cal_data.num_data) { + CAM_ERR(CAM_EEPROM, + "failed to copy, Invalid size"); + rc = -EINVAL; + return rc; + } + + 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); + } else { + CAM_ERR(CAM_EEPROM, "Invalid direction"); + rc = -EINVAL; + } + } + + return rc; +} + +static int32_t delete_eeprom_request(struct i2c_settings_array *i2c_array) +{ + struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL; + int32_t rc = 0; + + if (i2c_array == NULL) { + CAM_ERR(CAM_SENSOR, "FATAL:: Invalid argument"); + return -EINVAL; + } + + list_for_each_entry_safe(i2c_list, i2c_next, + &(i2c_array->list_head), list) { + kfree(i2c_list->seq_settings.reg_data); + list_del(&(i2c_list->list)); + kfree(i2c_list); + } + INIT_LIST_HEAD(&(i2c_array->list_head)); + i2c_array->is_settings_valid = 0; + + return rc; +} + +/** + * cam_eeprom_write - Write Packet + * @e_ctrl: ctrl structure + * + * Returns success or failure + */ +static int32_t cam_eeprom_write(struct cam_eeprom_ctrl_t *e_ctrl) +{ + int32_t rc = 0; + struct i2c_settings_array *i2c_set = NULL; + struct i2c_settings_list *i2c_list = NULL; + + i2c_set = &e_ctrl->wr_settings; + + if (i2c_set->is_settings_valid == 1) { + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + rc = camera_io_dev_write_continuous( + &e_ctrl->io_master_info, + &i2c_list->i2c_settings, 1); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, + "Error in EEPROM write"); + goto del_req; + } + } + } + +del_req: + delete_eeprom_request(i2c_set); + return rc; +} + +/** + * cam_eeprom_pkt_parse - Parse csl packet + * @e_ctrl: ctrl structure + * @arg: Camera control command argument + * + * Returns success or failure + */ +static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) +{ + int32_t rc = 0; + struct cam_control *ioctl_ctrl = NULL; + 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; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + + ioctl_ctrl = (struct cam_control *)arg; + + if (copy_from_user(&dev_config, + u64_to_user_ptr(ioctl_ctrl->handle), + sizeof(dev_config))) + return -EFAULT; + rc = cam_mem_get_cpu_buf(dev_config.packet_handle, + &generic_pkt_addr, &pkt_len); + if (rc) { + CAM_ERR(CAM_EEPROM, + "error in converting command Handle Error: %d", rc); + return rc; + } + + 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, + "Inval cam_packet strut size: %zu, len_of_buff: %zu", + sizeof(struct cam_packet), pkt_len); + rc = -EINVAL; + return rc; + } + + 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_EEPROM, "Invalid packet params"); + rc = -EINVAL; + return rc; + } + + switch (csl_packet->header.op_code & 0xFFFFFF) { + case CAM_EEPROM_PACKET_OPCODE_INIT: + if (e_ctrl->userspace_probe == false) { + rc = cam_eeprom_parse_read_memory_map( + e_ctrl->soc_info.dev->of_node, e_ctrl); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "Failed: rc : %d", rc); + return rc; + } + rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet); + vfree(e_ctrl->cal_data.mapdata); + vfree(e_ctrl->cal_data.map); + e_ctrl->cal_data.num_data = 0; + e_ctrl->cal_data.num_map = 0; + CAM_DBG(CAM_EEPROM, + "Returning the data using kernel probe"); + break; + } + rc = cam_eeprom_init_pkt_parser(e_ctrl, csl_packet); + if (rc) { + CAM_ERR(CAM_EEPROM, + "Failed in parsing the pkt"); + return rc; + } + + e_ctrl->cal_data.mapdata = + vzalloc(e_ctrl->cal_data.num_data); + if (!e_ctrl->cal_data.mapdata) { + rc = -ENOMEM; + CAM_ERR(CAM_EEPROM, "failed"); + goto error; + } + + if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE) { + rc = cam_eeprom_match_id(e_ctrl); + if (rc) { + CAM_DBG(CAM_EEPROM, + "eeprom not matching %d", rc); + goto memdata_free; + } + } + + rc = cam_eeprom_power_up(e_ctrl, + &soc_private->power_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed rc %d", rc); + goto memdata_free; + } + + e_ctrl->cam_eeprom_state = CAM_EEPROM_CONFIG; + rc = cam_eeprom_read_memory(e_ctrl, &e_ctrl->cal_data); + if (rc) { + CAM_ERR(CAM_EEPROM, + "read_eeprom_memory failed"); + goto power_down; + } + + rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet); + rc = cam_eeprom_power_down(e_ctrl); + e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE; + vfree(e_ctrl->cal_data.mapdata); + vfree(e_ctrl->cal_data.map); + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_setting_size = 0; + power_info->power_down_setting_size = 0; + e_ctrl->cal_data.num_data = 0; + e_ctrl->cal_data.num_map = 0; + break; + case CAM_EEPROM_WRITE: { + struct i2c_settings_array *i2c_reg_settings = + &e_ctrl->wr_settings; + + i2c_reg_settings->is_settings_valid = 1; + rc = cam_eeprom_parse_write_memory_packet( + csl_packet, e_ctrl); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "Failed: rc : %d", rc); + return rc; + } + + rc = cam_eeprom_power_up(e_ctrl, + &soc_private->power_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed power up rc %d", rc); + goto memdata_free; + } + + usleep_range(10*1000, 11*1000); + CAM_DBG(CAM_EEPROM, + "Calling Erase : %d start Address: 0x%x size: %d", + rc, e_ctrl->eebin_info.start_address, + e_ctrl->eebin_info.size); + + rc = camera_io_dev_erase(&e_ctrl->io_master_info, + e_ctrl->eebin_info.start_address, + e_ctrl->eebin_info.size); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "Failed in erase : %d", rc); + return rc; + } + + /* Buffer time margin */ + usleep_range(10*1000, 11*1000); + + rc = cam_eeprom_write(e_ctrl); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "Failed: rc : %d", rc); + return rc; + } + + rc = cam_eeprom_power_down(e_ctrl); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed power down rc %d", rc); + goto memdata_free; + } + + break; + } + default: + CAM_ERR(CAM_EEPROM, "Invalid op-code 0x%x", + csl_packet->header.op_code & 0xFFFFFF); + rc = -EINVAL; + break; + } + + return rc; +power_down: + cam_eeprom_power_down(e_ctrl); +memdata_free: + vfree(e_ctrl->cal_data.mapdata); +error: + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + vfree(e_ctrl->cal_data.map); + e_ctrl->cal_data.num_data = 0; + e_ctrl->cal_data.num_map = 0; + e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE; + return rc; +} + +void cam_eeprom_shutdown(struct cam_eeprom_ctrl_t *e_ctrl) +{ + int rc; + struct cam_eeprom_soc_private *soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + + if (e_ctrl->cam_eeprom_state == CAM_EEPROM_INIT) + return; + + if (e_ctrl->cam_eeprom_state == CAM_EEPROM_CONFIG) { + rc = cam_eeprom_power_down(e_ctrl); + if (rc < 0) + CAM_ERR(CAM_EEPROM, "EEPROM Power down failed"); + e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE; + } + + if (e_ctrl->cam_eeprom_state == CAM_EEPROM_ACQUIRE) { + rc = cam_destroy_device_hdl(e_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_EEPROM, "destroying the device hdl"); + + e_ctrl->bridge_intf.device_hdl = -1; + e_ctrl->bridge_intf.link_hdl = -1; + e_ctrl->bridge_intf.session_hdl = -1; + + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_setting_size = 0; + power_info->power_down_setting_size = 0; + } + + e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT; +} + +/** + * cam_eeprom_driver_cmd - Handle eeprom cmds + * @e_ctrl: ctrl structure + * @arg: Camera control command argument + * + * Returns success or failure + */ +int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) +{ + int rc = 0; + struct cam_eeprom_query_cap_t eeprom_cap = {0}; + struct cam_control *cmd = (struct cam_control *)arg; + + if (!e_ctrl || !cmd) { + CAM_ERR(CAM_EEPROM, "Invalid Arguments"); + return -EINVAL; + } + + if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_EEPROM, "Invalid handle type: %d", + cmd->handle_type); + return -EINVAL; + } + + mutex_lock(&(e_ctrl->eeprom_mutex)); + switch (cmd->op_code) { + case CAM_QUERY_CAP: + eeprom_cap.slot_info = e_ctrl->soc_info.index; + if (e_ctrl->userspace_probe == false) + eeprom_cap.eeprom_kernel_probe = true; + else + eeprom_cap.eeprom_kernel_probe = false; + + eeprom_cap.is_multimodule_mode = + e_ctrl->is_multimodule_mode; + + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &eeprom_cap, + sizeof(struct cam_eeprom_query_cap_t))) { + CAM_ERR(CAM_EEPROM, "Failed Copy to User"); + return -EFAULT; + goto release_mutex; + } + CAM_DBG(CAM_EEPROM, "eeprom_cap: ID: %d", eeprom_cap.slot_info); + break; + case CAM_ACQUIRE_DEV: + rc = cam_eeprom_get_dev_handle(e_ctrl, arg); + if (rc) { + CAM_ERR(CAM_EEPROM, "Failed to acquire dev"); + goto release_mutex; + } + e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE; + break; + case CAM_RELEASE_DEV: + if (e_ctrl->cam_eeprom_state != CAM_EEPROM_ACQUIRE) { + rc = -EINVAL; + CAM_WARN(CAM_EEPROM, + "Not in right state to release : %d", + e_ctrl->cam_eeprom_state); + goto release_mutex; + } + + if (e_ctrl->bridge_intf.device_hdl == -1) { + CAM_ERR(CAM_EEPROM, + "Invalid Handles: link hdl: %d device hdl: %d", + e_ctrl->bridge_intf.device_hdl, + e_ctrl->bridge_intf.link_hdl); + rc = -EINVAL; + goto release_mutex; + } + rc = cam_destroy_device_hdl(e_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_EEPROM, + "failed in destroying the device hdl"); + e_ctrl->bridge_intf.device_hdl = -1; + e_ctrl->bridge_intf.link_hdl = -1; + e_ctrl->bridge_intf.session_hdl = -1; + e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT; + break; + case CAM_CONFIG_DEV: + rc = cam_eeprom_pkt_parse(e_ctrl, arg); + if (rc) { + CAM_ERR(CAM_EEPROM, "Failed in eeprom pkt Parsing"); + goto release_mutex; + } + break; + default: + CAM_DBG(CAM_EEPROM, "invalid opcode"); + break; + } + +release_mutex: + mutex_unlock(&(e_ctrl->eeprom_mutex)); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.h new file mode 100644 index 000000000000..6a1e867542cb --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_EEPROM_CORE_H_ +#define _CAM_EEPROM_CORE_H_ + +#include "cam_eeprom_dev.h" + +int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg); +int32_t cam_eeprom_parse_read_memory_map(struct device_node *of_node, + struct cam_eeprom_ctrl_t *e_ctrl); +/** + * @e_ctrl: EEPROM ctrl structure + * + * This API handles the shutdown ioctl/close + */ +void cam_eeprom_shutdown(struct cam_eeprom_ctrl_t *e_ctrl); + +#endif +/* _CAM_EEPROM_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c new file mode 100644 index 000000000000..328541553b59 --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_eeprom_dev.h" +#include "cam_req_mgr_dev.h" +#include "cam_eeprom_soc.h" +#include "cam_eeprom_core.h" +#include "cam_debug_util.h" + +static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_driver_cmd(e_ctrl, arg); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + +static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_eeprom_ctrl_t *e_ctrl = + v4l2_get_subdevdata(sd); + + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "e_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(e_ctrl->eeprom_mutex)); + cam_eeprom_shutdown(e_ctrl); + mutex_unlock(&(e_ctrl->eeprom_mutex)); + + return 0; +} + +int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_eeprom_i2c_info_t *i2c_info) +{ + struct cam_sensor_cci_client *cci_client = NULL; + + if (e_ctrl->io_master_info.master_type == CCI_MASTER) { + cci_client = e_ctrl->io_master_info.cci_client; + if (!cci_client) { + CAM_ERR(CAM_EEPROM, "failed: cci_client %pK", + cci_client); + return -EINVAL; + } + cci_client->cci_i2c_master = e_ctrl->cci_i2c_master; + cci_client->sid = (i2c_info->slave_addr) >> 1; + cci_client->retries = 3; + cci_client->id_map = 0; + cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode; + } else if (e_ctrl->io_master_info.master_type == I2C_MASTER) { + e_ctrl->io_master_info.client->addr = i2c_info->slave_addr; + CAM_DBG(CAM_EEPROM, "Slave addr: 0x%x", i2c_info->slave_addr); + } else if (e_ctrl->io_master_info.master_type == SPI_MASTER) { + CAM_ERR(CAM_EEPROM, "Slave addr: 0x%x Freq Mode: %d", + i2c_info->slave_addr, i2c_info->i2c_freq_mode); + } + return 0; +} + +#ifdef CONFIG_COMPAT +static long cam_eeprom_init_subdev_do_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int32_t rc = 0; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_EEPROM, + "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_subdev_ioctl(sd, cmd, &cmd_data); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, + "Failed in eeprom suddev handling rc %d", + rc); + return rc; + } + break; + default: + CAM_ERR(CAM_EEPROM, "Invalid compat ioctl: %d", cmd); + rc = -EINVAL; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_EEPROM, + "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + return rc; +} +#endif + +static const struct v4l2_subdev_internal_ops cam_eeprom_internal_ops = { + .close = cam_eeprom_subdev_close, +}; + +static struct v4l2_subdev_core_ops cam_eeprom_subdev_core_ops = { + .ioctl = cam_eeprom_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_eeprom_init_subdev_do_ioctl, +#endif +}; + +static struct v4l2_subdev_ops cam_eeprom_subdev_ops = { + .core = &cam_eeprom_subdev_core_ops, +}; + +static int cam_eeprom_init_subdev(struct cam_eeprom_ctrl_t *e_ctrl) +{ + int rc = 0; + + e_ctrl->v4l2_dev_str.internal_ops = &cam_eeprom_internal_ops; + e_ctrl->v4l2_dev_str.ops = &cam_eeprom_subdev_ops; + strlcpy(e_ctrl->device_name, CAM_EEPROM_NAME, + sizeof(e_ctrl->device_name)); + e_ctrl->v4l2_dev_str.name = e_ctrl->device_name; + e_ctrl->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE; + e_ctrl->v4l2_dev_str.token = e_ctrl; + + rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str)); + if (rc) + CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev"); + + return rc; +} + +static int cam_eeprom_i2c_driver_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = NULL; + struct cam_eeprom_soc_private *soc_private = NULL; + struct cam_hw_soc_info *soc_info = NULL; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + CAM_ERR(CAM_EEPROM, "i2c_check_functionality failed"); + goto probe_failure; + } + + e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL); + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "kzalloc failed"); + rc = -ENOMEM; + goto probe_failure; + } + + soc_private = kzalloc(sizeof(*soc_private), GFP_KERNEL); + if (!soc_private) + goto ectrl_free; + + e_ctrl->soc_info.soc_private = soc_private; + + i2c_set_clientdata(client, e_ctrl); + + mutex_init(&(e_ctrl->eeprom_mutex)); + + INIT_LIST_HEAD(&(e_ctrl->wr_settings.list_head)); + soc_info = &e_ctrl->soc_info; + soc_info->dev = &client->dev; + soc_info->dev_name = client->name; + e_ctrl->io_master_info.master_type = I2C_MASTER; + e_ctrl->io_master_info.client = client; + e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE; + e_ctrl->cal_data.mapdata = NULL; + e_ctrl->cal_data.map = NULL; + e_ctrl->userspace_probe = false; + + rc = cam_eeprom_parse_dt(e_ctrl); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: soc init rc %d", rc); + goto free_soc; + } + + rc = cam_eeprom_update_i2c_info(e_ctrl, &soc_private->i2c_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: to update i2c info rc %d", rc); + goto free_soc; + } + + rc = cam_eeprom_init_subdev(e_ctrl); + if (rc) + goto free_soc; + + if (soc_private->i2c_info.slave_addr != 0) + e_ctrl->io_master_info.client->addr = + soc_private->i2c_info.slave_addr; + + e_ctrl->bridge_intf.device_hdl = -1; + 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; + e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT; + + return rc; +free_soc: + kfree(soc_private); +ectrl_free: + kfree(e_ctrl); +probe_failure: + return rc; +} + +static int cam_eeprom_i2c_driver_remove(struct i2c_client *client) +{ + int i; + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct cam_eeprom_ctrl_t *e_ctrl; + struct cam_eeprom_soc_private *soc_private; + struct cam_hw_soc_info *soc_info; + + if (!sd) { + CAM_ERR(CAM_EEPROM, "Subdevice is NULL"); + return -EINVAL; + } + + e_ctrl = (struct cam_eeprom_ctrl_t *)v4l2_get_subdevdata(sd); + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "eeprom device is NULL"); + return -EINVAL; + } + + soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + if (!soc_private) { + CAM_ERR(CAM_EEPROM, "soc_info.soc_private is NULL"); + 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); + v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL); + kfree(e_ctrl); + + return 0; +} + +static int cam_eeprom_spi_setup(struct spi_device *spi) +{ + struct cam_eeprom_ctrl_t *e_ctrl = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_sensor_spi_client *spi_client; + struct cam_eeprom_soc_private *eb_info; + struct cam_sensor_power_ctrl_t *power_info = NULL; + int rc = 0; + + e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL); + if (!e_ctrl) + return -ENOMEM; + + soc_info = &e_ctrl->soc_info; + soc_info->dev = &spi->dev; + soc_info->dev_name = spi->modalias; + + e_ctrl->v4l2_dev_str.ops = &cam_eeprom_subdev_ops; + e_ctrl->userspace_probe = false; + e_ctrl->cal_data.mapdata = NULL; + e_ctrl->cal_data.map = NULL; + + spi_client = kzalloc(sizeof(*spi_client), GFP_KERNEL); + if (!spi_client) { + kfree(e_ctrl); + return -ENOMEM; + } + + eb_info = kzalloc(sizeof(*eb_info), GFP_KERNEL); + if (!eb_info) + goto spi_free; + e_ctrl->soc_info.soc_private = eb_info; + + e_ctrl->eeprom_device_type = MSM_CAMERA_SPI_DEVICE; + e_ctrl->io_master_info.spi_client = spi_client; + e_ctrl->io_master_info.master_type = SPI_MASTER; + spi_client->spi_master = spi; + INIT_LIST_HEAD(&(e_ctrl->wr_settings.list_head)); + power_info = &eb_info->power_info; + power_info->dev = &spi->dev; + + /* set spi instruction info */ + spi_client->retry_delay = 1; + spi_client->retries = 0; + + /* Initialize mutex */ + mutex_init(&(e_ctrl->eeprom_mutex)); + + e_ctrl->bridge_intf.device_hdl = -1; + rc = cam_eeprom_parse_dt(e_ctrl); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: spi soc init rc %d", rc); + goto board_free; + } + + rc = cam_eeprom_spi_parse_of(spi_client); + if (rc) { + CAM_ERR(CAM_EEPROM, "Device tree parsing error"); + goto board_free; + } + + rc = cam_eeprom_init_subdev(e_ctrl); + if (rc) + goto board_free; + + 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); + return rc; + +board_free: + kfree(e_ctrl->soc_info.soc_private); +spi_free: + kfree(spi_client); + kfree(e_ctrl); + return rc; +} + +static int cam_eeprom_spi_driver_probe(struct spi_device *spi) +{ + spi->bits_per_word = 8; + spi->mode = SPI_MODE_0; + spi_setup(spi); + + CAM_DBG(CAM_EEPROM, "irq[%d] cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x]", + spi->irq, spi->chip_select, (spi->mode & SPI_CPHA) ? 1 : 0, + (spi->mode & SPI_CPOL) ? 1 : 0, + (spi->mode & SPI_CS_HIGH) ? 1 : 0); + CAM_DBG(CAM_EEPROM, "max_speed[%u]", spi->max_speed_hz); + + return cam_eeprom_spi_setup(spi); +} + +static int cam_eeprom_spi_driver_remove(struct spi_device *sdev) +{ + int i; + struct v4l2_subdev *sd = spi_get_drvdata(sdev); + struct cam_eeprom_ctrl_t *e_ctrl; + struct cam_eeprom_soc_private *soc_private; + struct cam_hw_soc_info *soc_info; + + if (!sd) { + CAM_ERR(CAM_EEPROM, "Subdevice is NULL"); + return -EINVAL; + } + + e_ctrl = (struct cam_eeprom_ctrl_t *)v4l2_get_subdevdata(sd); + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "eeprom device is NULL"); + return -EINVAL; + } + + 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(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; + } + v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL); + kfree(e_ctrl); + + return 0; +} + +static int32_t cam_eeprom_platform_driver_probe( + struct platform_device *pdev) +{ + int32_t rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = NULL; + struct cam_eeprom_soc_private *soc_private = NULL; + + e_ctrl = kzalloc(sizeof(struct cam_eeprom_ctrl_t), GFP_KERNEL); + if (!e_ctrl) + return -ENOMEM; + + e_ctrl->soc_info.pdev = pdev; + e_ctrl->soc_info.dev = &pdev->dev; + e_ctrl->soc_info.dev_name = pdev->name; + e_ctrl->eeprom_device_type = MSM_CAMERA_PLATFORM_DEVICE; + e_ctrl->cal_data.mapdata = NULL; + e_ctrl->cal_data.map = NULL; + e_ctrl->userspace_probe = false; + + e_ctrl->io_master_info.master_type = CCI_MASTER; + e_ctrl->io_master_info.cci_client = kzalloc( + sizeof(struct cam_sensor_cci_client), GFP_KERNEL); + if (!e_ctrl->io_master_info.cci_client) { + rc = -ENOMEM; + goto free_e_ctrl; + } + + soc_private = kzalloc(sizeof(struct cam_eeprom_soc_private), + GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto free_cci_client; + } + e_ctrl->soc_info.soc_private = soc_private; + soc_private->power_info.dev = &pdev->dev; + + /* Initialize mutex */ + mutex_init(&(e_ctrl->eeprom_mutex)); + rc = cam_eeprom_parse_dt(e_ctrl); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: soc init rc %d", rc); + goto free_soc; + } + rc = cam_eeprom_update_i2c_info(e_ctrl, &soc_private->i2c_info); + if (rc) { + CAM_ERR(CAM_EEPROM, "failed: to update i2c info rc %d", rc); + goto free_soc; + } + + INIT_LIST_HEAD(&(e_ctrl->wr_settings.list_head)); + rc = cam_eeprom_init_subdev(e_ctrl); + if (rc) + goto free_soc; + + e_ctrl->bridge_intf.device_hdl = -1; + 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); + e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT; + + return rc; +free_soc: + kfree(soc_private); +free_cci_client: + kfree(e_ctrl->io_master_info.cci_client); +free_e_ctrl: + kfree(e_ctrl); + + return rc; +} + +static int cam_eeprom_platform_driver_remove(struct platform_device *pdev) +{ + int i; + struct cam_eeprom_ctrl_t *e_ctrl; + struct cam_hw_soc_info *soc_info; + + e_ctrl = platform_get_drvdata(pdev); + if (!e_ctrl) { + CAM_ERR(CAM_EEPROM, "eeprom device is NULL"); + 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; +} + +static const struct of_device_id cam_eeprom_dt_match[] = { + { .compatible = "qcom,eeprom" }, + { } +}; + + +MODULE_DEVICE_TABLE(of, cam_eeprom_dt_match); + +static struct platform_driver cam_eeprom_platform_driver = { + .driver = { + .name = "qcom,eeprom", + .owner = THIS_MODULE, + .of_match_table = cam_eeprom_dt_match, + .suppress_bind_attrs = true, + }, + .probe = cam_eeprom_platform_driver_probe, + .remove = cam_eeprom_platform_driver_remove, +}; + +static const struct i2c_device_id cam_eeprom_i2c_id[] = { + { "msm_eeprom", (kernel_ulong_t)NULL}, + { } +}; + +static struct i2c_driver cam_eeprom_i2c_driver = { + .id_table = cam_eeprom_i2c_id, + .probe = cam_eeprom_i2c_driver_probe, + .remove = cam_eeprom_i2c_driver_remove, + .driver = { + .name = "msm_eeprom", + }, +}; + +static struct spi_driver cam_eeprom_spi_driver = { + .driver = { + .name = "qcom_eeprom", + .owner = THIS_MODULE, + .of_match_table = cam_eeprom_dt_match, + }, + .probe = cam_eeprom_spi_driver_probe, + .remove = cam_eeprom_spi_driver_remove, +}; +static int __init cam_eeprom_driver_init(void) +{ + int rc = 0; + + rc = platform_driver_register(&cam_eeprom_platform_driver); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "platform_driver_register failed rc = %d", + rc); + return rc; + } + + rc = spi_register_driver(&cam_eeprom_spi_driver); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "spi_register_driver failed rc = %d", rc); + return rc; + } + + rc = i2c_add_driver(&cam_eeprom_i2c_driver); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "i2c_add_driver failed rc = %d", rc); + return rc; + } + + return rc; +} + +static void __exit cam_eeprom_driver_exit(void) +{ + platform_driver_unregister(&cam_eeprom_platform_driver); + spi_unregister_driver(&cam_eeprom_spi_driver); + i2c_del_driver(&cam_eeprom_i2c_driver); +} + +module_init(cam_eeprom_driver_init); +module_exit(cam_eeprom_driver_exit); +MODULE_DESCRIPTION("CAM EEPROM driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h new file mode 100644 index 000000000000..2bac99f8c298 --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_EEPROM_DEV_H_ +#define _CAM_EEPROM_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_soc_util.h" + +#define DEFINE_MSM_MUTEX(mutexname) \ + static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) + +#define PROPERTY_MAXSIZE 32 + +#define MSM_EEPROM_MEMORY_MAP_MAX_SIZE 80 +#define MSM_EEPROM_MAX_MEM_MAP_CNT 8 +#define MSM_EEPROM_MEM_MAP_PROPERTIES_CNT 8 + +enum cam_eeprom_state { + CAM_EEPROM_INIT, + CAM_EEPROM_ACQUIRE, + CAM_EEPROM_CONFIG, +}; + +/** + * struct cam_eeprom_map_t - eeprom map + * @data_type : Data type + * @addr_type : Address type + * @addr : Address + * @data : data + * @delay : Delay + * + */ +struct cam_eeprom_map_t { + uint32_t valid_size; + uint32_t addr; + uint32_t addr_type; + uint32_t data; + uint32_t data_type; + uint32_t delay; +}; + +/** + * struct cam_eeprom_memory_map_t - eeprom memory map types + * @page : page memory + * @pageen : pageen memory + * @poll : poll memory + * @mem : mem + * @saddr : slave addr + * + */ +struct cam_eeprom_memory_map_t { + struct cam_eeprom_map_t page; + struct cam_eeprom_map_t pageen; + struct cam_eeprom_map_t poll; + struct cam_eeprom_map_t mem; + uint32_t saddr; +}; + +/** + * struct cam_eeprom_memory_block_t - eeprom mem block info + * @map : eeprom memory map + * @num_map : number of map blocks + * @mapdata : map data + * @cmd_type : size of total mapdata + * + */ +struct cam_eeprom_memory_block_t { + struct cam_eeprom_memory_map_t *map; + uint32_t num_map; + uint8_t *mapdata; + uint32_t num_data; +}; + +/** + * struct cam_eeprom_cmm_t - camera multimodule + * @cmm_support : cmm support flag + * @cmm_compression : cmm compression flag + * @cmm_offset : cmm data start offset + * @cmm_size : cmm data size + * + */ +struct cam_eeprom_cmm_t { + uint32_t cmm_support; + uint32_t cmm_compression; + uint32_t cmm_offset; + uint32_t cmm_size; +}; + +/** + * struct cam_eeprom_i2c_info_t - I2C info + * @slave_addr : slave address + * @i2c_freq_mode : i2c frequency mode + * + */ +struct cam_eeprom_i2c_info_t { + uint16_t slave_addr; + uint8_t i2c_freq_mode; +}; + +/** + * struct cam_eeprom_soc_private - eeprom soc private data structure + * @eeprom_name : eeprom name + * @i2c_info : i2c info structure + * @power_info : eeprom power info + * @cmm_data : cmm data + * + */ +struct cam_eeprom_soc_private { + const char *eeprom_name; + struct cam_eeprom_i2c_info_t i2c_info; + struct cam_sensor_power_ctrl_t power_info; + struct cam_eeprom_cmm_t cmm_data; +}; + +/** + * struct cam_eeprom_intf_params - bridge interface params + * @device_hdl : Device Handle + * @session_hdl : Session Handle + * @ops : KMD operations + * @crm_cb : Callback API pointers + */ +struct cam_eeprom_intf_params { + int32_t device_hdl; + int32_t session_hdl; + int32_t link_hdl; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; +}; + +struct eebin_info { + uint32_t start_address; + uint32_t size; + uint32_t is_valid; +}; + +/** + * struct cam_eeprom_ctrl_t - EEPROM control structure + * @pdev : platform device + * @spi : spi device + * @eeprom_mutex : eeprom mutex + * @soc_info : eeprom soc related info + * @io_master_info : Information about the communication master + * @gpio_num_info : gpio info + * @cci_i2c_master : I2C structure + * @v4l2_dev_str : V4L2 device structure + * @bridge_intf : bridge interface params + * @cam_eeprom_state : eeprom_device_state + * @userspace_probe : flag indicates userspace or kernel probe + * @cal_data : Calibration data + * @device_name : Device name + * @is_multimodule_mode : To identify multimodule node + * @wr_settings : I2C write settings + * @eebin_info : EEBIN address, size info + */ +struct cam_eeprom_ctrl_t { + struct platform_device *pdev; + struct spi_device *spi; + struct mutex eeprom_mutex; + struct cam_hw_soc_info soc_info; + struct camera_io_master io_master_info; + struct msm_camera_gpio_num_info *gpio_num_info; + enum cci_i2c_master_t cci_i2c_master; + enum cci_device_num cci_num; + struct cam_subdev v4l2_dev_str; + struct cam_eeprom_intf_params bridge_intf; + enum msm_camera_device_type_t eeprom_device_type; + enum cam_eeprom_state cam_eeprom_state; + bool userspace_probe; + struct cam_eeprom_memory_block_t cal_data; + char device_name[20]; + uint16_t is_multimodule_mode; + struct i2c_settings_array wr_settings; + struct eebin_info eebin_info; +}; + +int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, + struct cam_eeprom_i2c_info_t *i2c_info); + +#endif /*_CAM_EEPROM_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c new file mode 100644 index 000000000000..33f80b0c9716 --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_eeprom_soc.h" +#include "cam_debug_util.h" + +#define cam_eeprom_spi_parse_cmd(spi_dev, name, out) \ + { \ + spi_dev->cmd_tbl.name.opcode = out[0]; \ + spi_dev->cmd_tbl.name.addr_len = out[1]; \ + spi_dev->cmd_tbl.name.dummy_len = out[2]; \ + spi_dev->cmd_tbl.name.delay_intv = out[3]; \ + spi_dev->cmd_tbl.name.delay_count = out[4]; \ + } + +int cam_eeprom_spi_parse_of(struct cam_sensor_spi_client *spi_dev) +{ + int rc = -EFAULT; + uint32_t tmp[5]; + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-read", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, read, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get read data"); + return -EFAULT; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-readseq", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, read_seq, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get readseq data"); + return -EFAULT; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-queryid", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, query_id, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get queryid data"); + return -EFAULT; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-pprog", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, page_program, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get page program data"); + return -EFAULT; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-wenable", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, write_enable, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get write enable data"); + return rc; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-readst", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, read_status, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get readdst data"); + return rc; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "spiop-erase", tmp, 5); + if (!rc) { + cam_eeprom_spi_parse_cmd(spi_dev, erase, tmp); + } else { + CAM_ERR(CAM_EEPROM, "Failed to get erase data"); + return rc; + } + + rc = of_property_read_u32_array(spi_dev->spi_master->dev.of_node, + "eeprom-id", tmp, 2); + if (rc) { + CAM_ERR(CAM_EEPROM, "Failed to get eeprom id"); + return rc; + } + + spi_dev->mfr_id0 = tmp[0]; + spi_dev->device_id0 = tmp[1]; + + return 0; +} + +/* + * cam_eeprom_parse_memory_map() - parse memory map in device node + * @of: device node + * @data: memory block for output + * + * This functions parses @of to fill @data. It allocates map itself, parses + * the @of node, calculate total data length, and allocates required buffer. + * It only fills the map, but does not perform actual reading. + */ +int cam_eeprom_parse_dt_memory_map(struct device_node *node, + struct cam_eeprom_memory_block_t *data) +{ + int i, rc = 0; + char property[PROPERTY_MAXSIZE]; + uint32_t count = MSM_EEPROM_MEM_MAP_PROPERTIES_CNT; + struct cam_eeprom_memory_map_t *map; + + snprintf(property, PROPERTY_MAXSIZE, "num-blocks"); + rc = of_property_read_u32(node, property, &data->num_map); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "failed: num-blocks not available rc %d", + rc); + return rc; + } + + map = vzalloc((sizeof(*map) * data->num_map)); + if (!map) { + rc = -ENOMEM; + return rc; + } + data->map = map; + + for (i = 0; i < data->num_map; i++) { + snprintf(property, PROPERTY_MAXSIZE, "page%d", i); + rc = of_property_read_u32_array(node, property, + (uint32_t *) &map[i].page, count); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "failed: page not available rc %d", + rc); + goto ERROR; + } + + snprintf(property, PROPERTY_MAXSIZE, "pageen%d", i); + rc = of_property_read_u32_array(node, property, + (uint32_t *) &map[i].pageen, count); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "pageen not needed"); + + snprintf(property, PROPERTY_MAXSIZE, "saddr%d", i); + rc = of_property_read_u32_array(node, property, + (uint32_t *) &map[i].saddr, 1); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "saddr not needed - block %d", i); + + snprintf(property, PROPERTY_MAXSIZE, "poll%d", i); + rc = of_property_read_u32_array(node, property, + (uint32_t *) &map[i].poll, count); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "failed: poll not available rc %d", + rc); + goto ERROR; + } + + snprintf(property, PROPERTY_MAXSIZE, "mem%d", i); + rc = of_property_read_u32_array(node, property, + (uint32_t *) &map[i].mem, count); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "failed: mem not available rc %d", + rc); + goto ERROR; + } + data->num_data += map[i].mem.valid_size; + } + + data->mapdata = vzalloc(data->num_data); + if (!data->mapdata) { + rc = -ENOMEM; + goto ERROR; + } + return rc; + +ERROR: + vfree(data->map); + memset(data, 0, sizeof(*data)); + return rc; +} + +/** + * @e_ctrl: ctrl structure + * + * Parses eeprom dt + */ +static int cam_eeprom_get_dt_data(struct cam_eeprom_ctrl_t *e_ctrl) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = &e_ctrl->soc_info; + struct cam_eeprom_soc_private *soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + struct device_node *of_node = NULL; + + of_node = soc_info->dev->of_node; + + if (e_ctrl->userspace_probe == false) { + rc = cam_get_dt_power_setting_data(of_node, + soc_info, power_info); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "failed in getting power settings"); + return rc; + } + } + + if (!soc_info->gpio_data) { + CAM_INFO(CAM_EEPROM, "No GPIO found"); + return 0; + } + + if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { + CAM_INFO(CAM_EEPROM, "No GPIO found"); + return -EINVAL; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &power_info->gpio_num_info); + if ((rc < 0) || (!power_info->gpio_num_info)) { + CAM_ERR(CAM_EEPROM, "No/Error EEPROM GPIOs"); + return -EINVAL; + } + + return rc; +} + +/** + * @eb_info: eeprom private data structure + * @of_node: eeprom device node + * + * This function parses the eeprom dt to get the MM data + */ +static int cam_eeprom_cmm_dts(struct cam_eeprom_soc_private *eb_info, + struct device_node *of_node) +{ + int rc = 0; + struct cam_eeprom_cmm_t *cmm_data = &eb_info->cmm_data; + + cmm_data->cmm_support = + of_property_read_bool(of_node, "cmm-data-support"); + if (!cmm_data->cmm_support) { + CAM_DBG(CAM_EEPROM, "No cmm support"); + return 0; + } + + cmm_data->cmm_compression = + of_property_read_bool(of_node, "cmm-data-compressed"); + + rc = of_property_read_u32(of_node, "cmm-data-offset", + &cmm_data->cmm_offset); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "No MM offset data rc %d", rc); + + rc = of_property_read_u32(of_node, "cmm-data-size", + &cmm_data->cmm_size); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "No MM size data rc %d", rc); + + CAM_DBG(CAM_EEPROM, "cmm_compr %d, cmm_offset %d, cmm_size %d", + cmm_data->cmm_compression, cmm_data->cmm_offset, + cmm_data->cmm_size); + return 0; +} + +/** + * @e_ctrl: ctrl structure + * + * This function is called from cam_eeprom_platform/i2c/spi_driver_probe + * it parses the eeprom dt node and decides for userspace or kernel probe. + */ +int cam_eeprom_parse_dt(struct cam_eeprom_ctrl_t *e_ctrl) +{ + int i, rc = 0; + struct cam_hw_soc_info *soc_info = &e_ctrl->soc_info; + struct device_node *of_node = NULL; + struct device_node *of_parent = NULL; + struct cam_eeprom_soc_private *soc_private = + (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private; + uint32_t temp; + + if (!soc_info->dev) { + CAM_ERR(CAM_EEPROM, "Dev is NULL"); + return -EINVAL; + } + + e_ctrl->is_multimodule_mode = false; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "Failed to read DT properties rc : %d", rc); + return rc; + } + + of_node = soc_info->dev->of_node; + + if (of_property_read_bool(of_node, "multimodule-support")) { + CAM_DBG(CAM_UTIL, "Multi Module is Supported"); + e_ctrl->is_multimodule_mode = true; + } + + rc = of_property_read_string(of_node, "eeprom-name", + &soc_private->eeprom_name); + if (rc < 0) { + CAM_DBG(CAM_EEPROM, "kernel probe is not enabled"); + e_ctrl->userspace_probe = true; + } + + if (e_ctrl->io_master_info.master_type == CCI_MASTER) { + rc = of_property_read_u32(of_node, "cci-master", + &e_ctrl->cci_i2c_master); + if (rc < 0 || (e_ctrl->cci_i2c_master >= MASTER_MAX)) { + CAM_DBG(CAM_EEPROM, "failed rc %d", rc); + rc = -EFAULT; + return rc; + } + + of_parent = of_get_parent(of_node); + if (of_property_read_u32(of_parent, "cell-index", + &e_ctrl->cci_num) < 0) + /* Set default master 0 */ + e_ctrl->cci_num = CCI_DEVICE_0; + + e_ctrl->io_master_info.cci_client->cci_device = e_ctrl->cci_num; + CAM_DBG(CAM_EEPROM, "cci-index %d", e_ctrl->cci_num, rc); + } + + if (e_ctrl->io_master_info.master_type == SPI_MASTER) { + rc = cam_eeprom_cmm_dts(soc_private, soc_info->dev->of_node); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "MM data not available rc %d", rc); + } + + rc = cam_eeprom_get_dt_data(e_ctrl); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "failed: eeprom get dt data rc %d", rc); + + if ((e_ctrl->userspace_probe == false) && + (e_ctrl->io_master_info.master_type != SPI_MASTER)) { + rc = of_property_read_u32(of_node, "slave-addr", &temp); + if (rc < 0) + CAM_DBG(CAM_EEPROM, "failed: no slave-addr rc %d", rc); + + soc_private->i2c_info.slave_addr = temp; + + rc = of_property_read_u32(of_node, "i2c-freq-mode", &temp); + soc_private->i2c_info.i2c_freq_mode = temp; + if (rc < 0) { + CAM_ERR(CAM_EEPROM, + "i2c-freq-mode read fail %d", rc); + soc_private->i2c_info.i2c_freq_mode = 0; + } + if (soc_private->i2c_info.i2c_freq_mode >= I2C_MAX_MODES) { + CAM_ERR(CAM_EEPROM, "invalid i2c_freq_mode = %d", + soc_private->i2c_info.i2c_freq_mode); + soc_private->i2c_info.i2c_freq_mode = 0; + } + CAM_DBG(CAM_EEPROM, "slave-addr = 0x%X", + soc_private->i2c_info.slave_addr); + } + + for (i = 0; i < soc_info->num_clk; i++) { + soc_info->clk[i] = devm_clk_get(soc_info->dev, + soc_info->clk_name[i]); + if (!soc_info->clk[i]) { + CAM_ERR(CAM_EEPROM, "get failed for %s", + soc_info->clk_name[i]); + rc = -ENOENT; + return rc; + } + } + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h new file mode 100644 index 000000000000..ed37989eb2d7 --- /dev/null +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_EEPROM_SOC_H_ +#define _CAM_EEPROM_SOC_H_ + +#include "cam_eeprom_dev.h" + +int cam_eeprom_spi_parse_of(struct cam_sensor_spi_client *client); + +int cam_eeprom_parse_dt_memory_map(struct device_node *of, + struct cam_eeprom_memory_block_t *data); + +int cam_eeprom_parse_dt(struct cam_eeprom_ctrl_t *e_ctrl); +#endif/* _CAM_EEPROM_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_flash/Makefile b/drivers/cam_sensor_module/cam_flash/Makefile new file mode 100644 index 000000000000..dfc2bc2c8c8c --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash_dev.o cam_flash_core.o cam_flash_soc.o diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c new file mode 100644 index 000000000000..293d1422b393 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -0,0 +1,1812 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include + +#include "cam_sensor_cmn_header.h" +#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 (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; + } + } else { + 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; +} + +static int cam_flash_pmic_flush_nrt(struct cam_flash_ctrl *fctrl) +{ + int j = 0; + struct cam_flash_frame_setting *nrt_settings; + + if (!fctrl) + return -EINVAL; + + nrt_settings = &fctrl->nrt_info; + + if (nrt_settings->cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO) { + fctrl->flash_init_setting.cmn_attr.is_settings_valid = false; + } else if ((nrt_settings->cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) || + (nrt_settings->cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_RER) || + (nrt_settings->cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE)) { + fctrl->nrt_info.cmn_attr.is_settings_valid = false; + fctrl->nrt_info.cmn_attr.count = 0; + fctrl->nrt_info.num_iterations = 0; + fctrl->nrt_info.led_on_delay_ms = 0; + fctrl->nrt_info.led_off_delay_ms = 0; + for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++) + fctrl->nrt_info.led_current_ma[j] = 0; + } + + return 0; +} + +static int cam_flash_i2c_flush_nrt(struct cam_flash_ctrl *fctrl) +{ + int rc = 0; + + if (fctrl->i2c_data.init_settings.is_settings_valid == true) { + rc = delete_request(&fctrl->i2c_data.init_settings); + if (rc) { + CAM_WARN(CAM_FLASH, + "Failed to delete Init i2c_setting: %d", + rc); + return rc; + } + } + if (fctrl->i2c_data.config_settings.is_settings_valid == true) { + rc = delete_request(&fctrl->i2c_data.config_settings); + if (rc) { + CAM_WARN(CAM_FLASH, + "Failed to delete NRT i2c_setting: %d", + rc); + return rc; + } + } + + return rc; +} + +static int cam_flash_construct_default_power_setting( + struct cam_sensor_power_ctrl_t *power_info) +{ + int rc = 0; + + power_info->power_setting_size = 1; + power_info->power_setting = + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_setting) + return -ENOMEM; + + power_info->power_setting[0].seq_type = SENSOR_CUSTOM_REG1; + power_info->power_setting[0].seq_val = CAM_V_CUSTOM1; + power_info->power_setting[0].config_val = 0; + power_info->power_setting[0].delay = 2; + + power_info->power_down_setting_size = 1; + power_info->power_down_setting = + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_down_setting) { + rc = -ENOMEM; + goto free_power_settings; + } + + power_info->power_down_setting[0].seq_type = SENSOR_CUSTOM_REG1; + power_info->power_down_setting[0].seq_val = CAM_V_CUSTOM1; + power_info->power_down_setting[0].config_val = 0; + + return rc; + +free_power_settings: + kfree(power_info->power_setting); + power_info->power_setting = NULL; + power_info->power_setting_size = 0; + return rc; +} + +int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable) +{ + int rc = 0; + + if (!(fctrl->switch_trigger)) { + CAM_ERR(CAM_FLASH, "Invalid argument"); + return -EINVAL; + } + + if (regulator_enable) { + rc = cam_flash_prepare(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + fctrl->last_flush_req = 0; + } + + if (!regulator_enable) { + if ((fctrl->flash_state == CAM_FLASH_STATE_START) && + (fctrl->is_regulator_enabled == true)) { + rc = cam_flash_prepare(fctrl, false); + if (rc) + CAM_ERR(CAM_FLASH, + "Disable Regulator Failed rc: %d", rc); + } + } + + return rc; +} + +int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = &fctrl->soc_info; + struct cam_sensor_power_ctrl_t *power_info = + &fctrl->power_info; + + if (!power_info || !soc_info) { + CAM_ERR(CAM_FLASH, "Power Info is NULL"); + return -EINVAL; + } + power_info->dev = soc_info->dev; + + if (regulator_enable && (fctrl->is_regulator_enabled == false)) { + if ((power_info->power_setting == NULL) && + (power_info->power_down_setting == NULL)) { + CAM_INFO(CAM_FLASH, + "Using default power settings"); + rc = cam_flash_construct_default_power_setting( + power_info); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "Construct default pwr setting failed rc: %d", + rc); + return rc; + } + } + + rc = cam_sensor_core_power_up(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "power up the core is failed:%d", + rc); + goto free_pwr_settings; + } + + rc = camera_io_init(&(fctrl->io_master_info)); + if (rc) { + CAM_ERR(CAM_FLASH, "cci_init failed: rc: %d", rc); + cam_sensor_util_power_down(power_info, soc_info); + goto free_pwr_settings; + } + fctrl->is_regulator_enabled = true; + } else if ((!regulator_enable) && + (fctrl->is_regulator_enabled == true)) { + rc = cam_sensor_util_power_down(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "power down the core is failed:%d", + rc); + return rc; + } + camera_io_release(&(fctrl->io_master_info)); + fctrl->is_regulator_enabled = false; + goto free_pwr_settings; + } + return rc; + +free_pwr_settings: + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_setting_size = 0; + power_info->power_down_setting_size = 0; + + return rc; +} + +int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id) +{ + int rc = 0; + int i = 0, j = 0; + int frame_offset = 0; + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Device data is NULL"); + return -EINVAL; + } + + if (type == FLUSH_ALL) { + /* flush all requests*/ + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + fctrl->per_frame[i].cmn_attr.request_id = 0; + fctrl->per_frame[i].cmn_attr.is_settings_valid = false; + fctrl->per_frame[i].cmn_attr.count = 0; + for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++) + fctrl->per_frame[i].led_current_ma[j] = 0; + } + + cam_flash_pmic_flush_nrt(fctrl); + } else if ((type == FLUSH_REQ) && (req_id != 0)) { + /* flush request with req_id*/ + frame_offset = req_id % MAX_PER_FRAME_ARRAY; + fctrl->per_frame[frame_offset].cmn_attr.request_id = 0; + fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid = + false; + fctrl->per_frame[frame_offset].cmn_attr.count = 0; + for (i = 0; i < CAM_FLASH_MAX_LED_TRIGGERS; i++) + fctrl->per_frame[frame_offset].led_current_ma[i] = 0; + } else if ((type == FLUSH_REQ) && (req_id == 0)) { + /* Handels NonRealTime usecase */ + cam_flash_pmic_flush_nrt(fctrl); + } else { + CAM_ERR(CAM_FLASH, "Invalid arguments"); + return -EINVAL; + } + + return rc; +} + +int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id) +{ + int rc = 0; + int i = 0; + uint32_t cancel_req_id_found = 0; + struct i2c_settings_array *i2c_set = NULL; + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Device data is NULL"); + return -EINVAL; + } + if ((type == FLUSH_REQ) && (req_id == 0)) { + /* This setting will be called only when NonRealTime + * settings needs to clean. + */ + cam_flash_i2c_flush_nrt(fctrl); + } else { + /* All other usecase will be handle here */ + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(fctrl->i2c_data.per_frame[i]); + + if ((type == FLUSH_REQ) && + (i2c_set->request_id != req_id)) + continue; + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_FLASH, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + + if (type == FLUSH_REQ) { + cancel_req_id_found = 1; + break; + } + } + } + } + + if ((type == FLUSH_REQ) && (req_id != 0) && + (!cancel_req_id_found)) + CAM_DBG(CAM_FLASH, + "Flush request id:%lld not found in the pending list", + req_id); + + return rc; +} + +int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) +{ + int rc = 0; + struct cam_flash_ctrl *fctrl = NULL; + + fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(flush->dev_hdl); + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Device data is NULL"); + return -EINVAL; + } + + 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); + goto end; + } + } else if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + rc = fctrl->func_tbl.flush_req(fctrl, + FLUSH_REQ, flush->req_id); + if (rc) { + CAM_ERR(CAM_FLASH, "FLUSH_REQ failed rc: %d", rc); + goto end; + } + } +end: + mutex_unlock(&fctrl->flash_mutex); + return rc; +} + +static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, + struct cam_flash_frame_setting *flash_data, enum camera_flash_opcode op) +{ + uint32_t curr = 0, max_current = 0; + struct cam_flash_private_soc *soc_private = NULL; + int i = 0; + + if (!flash_ctrl || !flash_data) { + CAM_ERR(CAM_FLASH, "Fctrl or Data NULL"); + return -EINVAL; + } + + soc_private = (struct cam_flash_private_soc *) + flash_ctrl->soc_info.soc_private; + + if (op == CAMERA_SENSOR_FLASH_OP_FIRELOW) { + 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 = 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 = 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); + return -EINVAL; + } + + if (flash_ctrl->switch_trigger) + cam_res_mgr_led_trigger_event( + flash_ctrl->switch_trigger, + (enum led_brightness)LED_SWITCH_ON); + + return 0; +} + +int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) +{ + if (!flash_ctrl) { + CAM_ERR(CAM_FLASH, "Flash control Null"); + return -EINVAL; + } + + if (flash_ctrl->switch_trigger) + cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger, + (enum led_brightness)LED_SWITCH_OFF); + + flash_ctrl->flash_state = CAM_FLASH_STATE_START; + return 0; +} + +static int cam_flash_low( + struct cam_flash_ctrl *flash_ctrl, + struct cam_flash_frame_setting *flash_data) +{ + int i = 0, rc = 0; + + if (!flash_data) { + CAM_ERR(CAM_FLASH, "Flash Data Null"); + return -EINVAL; + } + + for (i = 0; i < flash_ctrl->flash_num_sources; i++) + if (flash_ctrl->flash_trigger[i]) + cam_res_mgr_led_trigger_event( + flash_ctrl->flash_trigger[i], + LED_OFF); + + rc = cam_flash_ops(flash_ctrl, flash_data, + CAMERA_SENSOR_FLASH_OP_FIRELOW); + if (rc) + CAM_ERR(CAM_FLASH, "Fire Torch failed: %d", rc); + + return rc; +} + +static int cam_flash_high( + struct cam_flash_ctrl *flash_ctrl, + struct cam_flash_frame_setting *flash_data) +{ + int i = 0, rc = 0; + + if (!flash_data) { + CAM_ERR(CAM_FLASH, "Flash Data Null"); + return -EINVAL; + } + + for (i = 0; i < flash_ctrl->torch_num_sources; i++) + if (flash_ctrl->torch_trigger[i]) + cam_res_mgr_led_trigger_event( + flash_ctrl->torch_trigger[i], + LED_OFF); + + rc = cam_flash_ops(flash_ctrl, flash_data, + CAMERA_SENSOR_FLASH_OP_FIREHIGH); + if (rc) + CAM_ERR(CAM_FLASH, "Fire Flash Failed: %d", rc); + + return rc; +} + +static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl, + uint64_t req_id) +{ + int i = 0, rc = 0; + uint64_t top = 0, del_req_id = 0; + + if (req_id != 0) { + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + if ((req_id >= + fctrl->i2c_data.per_frame[i].request_id) && + (top < + fctrl->i2c_data.per_frame[i].request_id) && + (fctrl->i2c_data.per_frame[i].is_settings_valid + == 1)) { + del_req_id = top; + top = fctrl->i2c_data.per_frame[i].request_id; + } + } + + if (top < req_id) { + if ((((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) >= BATCH_SIZE_MAX) || + (((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) <= -BATCH_SIZE_MAX)) + del_req_id = req_id; + } + + if (!del_req_id) + return rc; + + CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", + top, del_req_id); + } + fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id); + return 0; +} + +static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl, + uint64_t req_id) +{ + int i = 0; + struct cam_flash_frame_setting *flash_data = NULL; + uint64_t top = 0, del_req_id = 0; + + if (req_id != 0) { + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + flash_data = &fctrl->per_frame[i]; + if (req_id >= flash_data->cmn_attr.request_id && + flash_data->cmn_attr.is_settings_valid + == 1) { + if (top < flash_data->cmn_attr.request_id) { + del_req_id = top; + top = flash_data->cmn_attr.request_id; + } else if (top > + flash_data->cmn_attr.request_id && + del_req_id < + flash_data->cmn_attr.request_id) { + del_req_id = + flash_data->cmn_attr.request_id; + } + } + } + + if (top < req_id) { + if ((((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) >= BATCH_SIZE_MAX) || + (((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) <= -BATCH_SIZE_MAX)) + del_req_id = req_id; + } + + if (!del_req_id) + return 0; + + CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", + top, del_req_id); + } + + fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id); + return 0; +} + +static int32_t cam_flash_slaveInfo_pkt_parser(struct cam_flash_ctrl *fctrl, + 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; + fctrl->io_master_info.cci_client->i2c_freq_mode = + i2c_info->i2c_freq_mode; + fctrl->io_master_info.cci_client->sid = + i2c_info->slave_addr >> 1; + CAM_DBG(CAM_FLASH, "Slave addr: 0x%x Freq Mode: %d", + i2c_info->slave_addr, i2c_info->i2c_freq_mode); + } else if (fctrl->io_master_info.master_type == I2C_MASTER) { + fctrl->io_master_info.client->addr = i2c_info->slave_addr; + CAM_DBG(CAM_FLASH, "Slave addr: 0x%x", i2c_info->slave_addr); + } else { + CAM_ERR(CAM_FLASH, "Invalid Master type: %d", + fctrl->io_master_info.master_type); + rc = -EINVAL; + } + + return rc; +} + +int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, + uint64_t req_id) +{ + struct i2c_settings_list *i2c_list; + struct i2c_settings_array *i2c_set = NULL; + int frame_offset = 0, rc = 0; + + if (req_id == 0) { + /* NonRealTime Init settings*/ + if (fctrl->i2c_data.init_settings.is_settings_valid == true) { + list_for_each_entry(i2c_list, + &(fctrl->i2c_data.init_settings.list_head), + list) { + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply init settings: %d", + rc); + return rc; + } + } + } + /* NonRealTime (Widget/RER/INIT_FIRE settings) */ + if (fctrl->i2c_data.config_settings.is_settings_valid == true) { + list_for_each_entry(i2c_list, + &(fctrl->i2c_data.config_settings.list_head), + list) { + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply NRT settings: %d", rc); + return rc; + } + } + } + } else { + /* RealTime */ + frame_offset = req_id % MAX_PER_FRAME_ARRAY; + i2c_set = &fctrl->i2c_data.per_frame[frame_offset]; + if ((i2c_set->is_settings_valid == true) && + (i2c_set->request_id == req_id)) { + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + rc = cam_sensor_util_i2c_apply_setting( + &(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply settings: %d", rc); + return rc; + } + } + } + } + + cam_flash_i2c_delete_req(fctrl, req_id); + return rc; +} + +int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, + uint64_t req_id) +{ + int rc = 0, i = 0; + int frame_offset = 0; + uint16_t num_iterations; + struct cam_flash_frame_setting *flash_data = NULL; + + if (req_id == 0) { + if (fctrl->nrt_info.cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE) { + flash_data = &fctrl->nrt_info; + CAM_DBG(CAM_REQ, + "FLASH_INIT_FIRE req_id: %u flash_opcode: %d", + req_id, flash_data->opcode); + + if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIREHIGH) { + if (fctrl->flash_state == + CAM_FLASH_STATE_START) { + CAM_WARN(CAM_FLASH, + "Wrong state :Prev state: %d", + fctrl->flash_state); + return -EINVAL; + } + + rc = cam_flash_high(fctrl, flash_data); + if (rc) + CAM_ERR(CAM_FLASH, + "FLASH ON failed : %d", rc); + } + if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIRELOW) { + if (fctrl->flash_state == + CAM_FLASH_STATE_START) { + CAM_WARN(CAM_FLASH, + "Wrong state :Prev state: %d", + fctrl->flash_state); + return -EINVAL; + } + + rc = cam_flash_low(fctrl, flash_data); + if (rc) + CAM_ERR(CAM_FLASH, + "TORCH ON failed : %d", rc); + } + if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_OFF) { + rc = cam_flash_off(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "LED OFF FAILED: %d", + rc); + return rc; + } + } + } else if (fctrl->nrt_info.cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) { + flash_data = &fctrl->nrt_info; + CAM_DBG(CAM_REQ, + "FLASH_WIDGET req_id: %u flash_opcode: %d", + req_id, flash_data->opcode); + + if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIRELOW) { + rc = cam_flash_low(fctrl, flash_data); + if (rc) { + CAM_ERR(CAM_FLASH, + "Torch ON failed : %d", + rc); + goto nrt_del_req; + } + } else if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_OFF) { + rc = cam_flash_off(fctrl); + if (rc) + CAM_ERR(CAM_FLASH, + "LED off failed: %d", + rc); + } + } else if (fctrl->nrt_info.cmn_attr.cmd_type == + CAMERA_SENSOR_FLASH_CMD_TYPE_RER) { + flash_data = &fctrl->nrt_info; + if (fctrl->flash_state != CAM_FLASH_STATE_START) { + rc = cam_flash_off(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "Flash off failed: %d", + rc); + goto nrt_del_req; + } + } + CAM_DBG(CAM_REQ, "FLASH_RER req_id: %u", req_id); + + num_iterations = flash_data->num_iterations; + for (i = 0; i < num_iterations; i++) { + /* Turn On Torch */ + if (fctrl->flash_state == + CAM_FLASH_STATE_START) { + rc = cam_flash_low(fctrl, flash_data); + if (rc) { + CAM_ERR(CAM_FLASH, + "Fire Torch Failed"); + goto nrt_del_req; + } + + usleep_range( + flash_data->led_on_delay_ms * 1000, + flash_data->led_on_delay_ms * 1000 + + 100); + } + /* Turn Off Torch */ + rc = cam_flash_off(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "Flash off failed: %d", rc); + continue; + } + fctrl->flash_state = CAM_FLASH_STATE_START; + usleep_range( + flash_data->led_off_delay_ms * 1000, + flash_data->led_off_delay_ms * 1000 + 100); + } + } + } else { + frame_offset = req_id % MAX_PER_FRAME_ARRAY; + flash_data = &fctrl->per_frame[frame_offset]; + CAM_DBG(CAM_REQ, "FLASH_RT req_id: %u flash_opcode: %d", + req_id, flash_data->opcode); + + if ((flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREHIGH) && + (flash_data->cmn_attr.is_settings_valid) && + (flash_data->cmn_attr.request_id == req_id)) { + /* Turn On Flash */ + if (fctrl->flash_state == CAM_FLASH_STATE_START) { + rc = cam_flash_high(fctrl, flash_data); + if (rc) { + CAM_ERR(CAM_FLASH, + "Flash ON failed: rc= %d", + rc); + goto apply_setting_err; + } + } + } else if ((flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIRELOW) && + (flash_data->cmn_attr.is_settings_valid) && + (flash_data->cmn_attr.request_id == req_id)) { + /* Turn On Torch */ + if (fctrl->flash_state == CAM_FLASH_STATE_START) { + rc = cam_flash_low(fctrl, flash_data); + if (rc) { + CAM_ERR(CAM_FLASH, + "Torch ON failed: rc= %d", + rc); + goto apply_setting_err; + } + } + } else if ((flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) && + (flash_data->cmn_attr.is_settings_valid) && + (flash_data->cmn_attr.request_id == req_id)) { + rc = cam_flash_off(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "Flash off failed %d", rc); + goto apply_setting_err; + } + } else if (flash_data->opcode == CAM_PKT_NOP_OPCODE) { + CAM_DBG(CAM_FLASH, "NOP Packet"); + } else { + rc = -EINVAL; + CAM_ERR(CAM_FLASH, "Invalid opcode: %d req_id: %llu", + flash_data->opcode, req_id); + goto apply_setting_err; + } + } + +nrt_del_req: + cam_flash_pmic_delete_req(fctrl, req_id); +apply_setting_err: + return rc; +} + +int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) +{ + int rc = 0, i = 0; + uintptr_t generic_ptr; + uint32_t total_cmd_buf_in_bytes = 0; + uint32_t processed_cmd_buf_in_bytes = 0; + uint16_t cmd_length_in_bytes = 0; + 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_flash_init *flash_init = NULL; + struct common_header *cmn_hdr = NULL; + struct cam_control *ioctl_ctrl = NULL; + struct cam_packet *csl_packet = NULL; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_config_dev_cmd config; + struct cam_req_mgr_add_request add_req; + struct i2c_data_settings *i2c_data = NULL; + struct i2c_settings_array *i2c_reg_settings = NULL; + struct cam_sensor_power_ctrl_t *power_info = NULL; + + if (!fctrl || !arg) { + CAM_ERR(CAM_FLASH, "fctrl/arg is NULL"); + return -EINVAL; + } + /* getting CSL Packet */ + ioctl_ctrl = (struct cam_control *)arg; + + if (copy_from_user((&config), (void __user *) ioctl_ctrl->handle, + sizeof(config))) { + CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed"); + return -EFAULT; + } + + rc = cam_mem_get_cpu_buf(config.packet_handle, + &generic_ptr, &len_of_buffer); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed in getting the packet : %d", rc); + return rc; + } + 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, + "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*/ + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + /* Loop through multiple command buffers */ + for (i = 1; i < csl_packet->num_cmd_buf; i++) { + total_cmd_buf_in_bytes = cmd_desc[i].length; + processed_cmd_buf_in_bytes = 0; + if (!total_cmd_buf_in_bytes) + continue; + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &generic_ptr, &len_of_buffer); + if (rc < 0) { + CAM_ERR(CAM_FLASH, "Failed to get cpu buf"); + return rc; + } + cmd_buf = (uint32_t *)generic_ptr; + if (!cmd_buf) { + 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; + + /* Loop through cmd formats in one cmd buffer */ + CAM_DBG(CAM_FLASH, + "command Type: %d,Processed: %d,Total: %d", + cmn_hdr->cmd_type, processed_cmd_buf_in_bytes, + 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 = + sizeof(struct cam_flash_init); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + break; + case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: + rc = cam_flash_slaveInfo_pkt_parser( + fctrl, cmd_buf, remain_len); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "Failed parsing slave info: rc: %d", + rc); + return rc; + } + cmd_length_in_bytes = + sizeof(struct cam_cmd_i2c_info); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + break; + case CAMERA_SENSOR_CMD_TYPE_PWR_UP: + case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN: + CAM_DBG(CAM_FLASH, + "Received power settings"); + cmd_length_in_bytes = + total_cmd_buf_in_bytes; + rc = cam_sensor_update_power_settings( + cmd_buf, + total_cmd_buf_in_bytes, + &fctrl->power_info, remain_len); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed update power settings"); + return rc; + } + break; + default: + CAM_DBG(CAM_FLASH, + "Received initSettings"); + i2c_data = &(fctrl->i2c_data); + i2c_reg_settings = + &fctrl->i2c_data.init_settings; + + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + rc = cam_sensor_i2c_command_parser( + &fctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "pkt parsing failed: %d", rc); + return rc; + } + cmd_length_in_bytes = + cmd_desc[i].length; + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + + break; + } + } + power_info = &fctrl->power_info; + if (!power_info) { + CAM_ERR(CAM_FLASH, "Power_info is NULL"); + return -EINVAL; + } + + /* Parse and fill vreg params for power up settings */ + rc = msm_camera_fill_vreg_params(&fctrl->soc_info, + power_info->power_setting, + power_info->power_setting_size); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed to fill vreg params for power up rc:%d", + rc); + return rc; + } + + /* Parse and fill vreg params for power down settings*/ + rc = msm_camera_fill_vreg_params( + &fctrl->soc_info, + power_info->power_down_setting, + power_info->power_down_setting_size); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed to fill vreg params power down rc:%d", + rc); + return rc; + } + + rc = fctrl->func_tbl.power_ops(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + + rc = fctrl->func_tbl.apply_setting(fctrl, 0); + if (rc) { + CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc); + return rc; + } + + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; + break; + } + case CAM_FLASH_PACKET_OPCODE_SET_OPS: { + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; + /* add support for handling i2c_data*/ + i2c_reg_settings = + &fctrl->i2c_data.per_frame[frm_offset]; + if (i2c_reg_settings->is_settings_valid == true) { + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = false; + goto update_req_mgr; + } + i2c_reg_settings->is_settings_valid = true; + i2c_reg_settings->request_id = + csl_packet->header.request_id; + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser( + &fctrl->io_master_info, + i2c_reg_settings, cmd_desc, 1); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in parsing i2c packets"); + return rc; + } + break; + } + case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: { + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + + /* add support for handling i2c_data*/ + i2c_reg_settings = &fctrl->i2c_data.config_settings; + if (i2c_reg_settings->is_settings_valid == true) { + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = false; + + rc = delete_request(i2c_reg_settings); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in Deleting the err: %d", rc); + return rc; + } + } + i2c_reg_settings->is_settings_valid = true; + i2c_reg_settings->request_id = + csl_packet->header.request_id; + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser( + &fctrl->io_master_info, + i2c_reg_settings, cmd_desc, 1); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in parsing i2c NRT packets"); + return rc; + } + rc = fctrl->func_tbl.apply_setting(fctrl, 0); + if (rc) + CAM_ERR(CAM_FLASH, + "Apply setting failed: %d", rc); + return rc; + } + case CAM_PKT_NOP_OPCODE: { + if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || + (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { + CAM_WARN(CAM_FLASH, + "Rxed NOP packets without linking"); + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; + fctrl->i2c_data.per_frame[frm_offset].is_settings_valid + = false; + return 0; + } + + CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u", + csl_packet->header.request_id); + goto update_req_mgr; + } + default: + CAM_ERR(CAM_FLASH, "Wrong Opcode : %d", + (csl_packet->header.op_code & 0xFFFFFF)); + return -EINVAL; + } +update_req_mgr: + if (((csl_packet->header.op_code & 0xFFFFF) == + CAM_PKT_NOP_OPCODE) || + ((csl_packet->header.op_code & 0xFFFFF) == + CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + add_req.link_hdl = fctrl->bridge_intf.link_hdl; + add_req.req_id = csl_packet->header.request_id; + add_req.dev_hdl = fctrl->bridge_intf.device_hdl; + + if ((csl_packet->header.op_code & 0xFFFFF) == + CAM_FLASH_PACKET_OPCODE_SET_OPS) + add_req.skip_before_applying = 1; + else + add_req.skip_before_applying = 0; + + if (fctrl->bridge_intf.crm_cb && + fctrl->bridge_intf.crm_cb->add_req) + fctrl->bridge_intf.crm_cb->add_req(&add_req); + CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); + } + return rc; +} + +int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) +{ + int rc = 0, i = 0; + 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; + struct common_header *cmn_hdr; + struct cam_config_dev_cmd config; + struct cam_req_mgr_add_request add_req = {0}; + struct cam_flash_init *cam_flash_info = NULL; + struct cam_flash_set_rer *flash_rer_info = NULL; + 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; + + if (copy_from_user((&config), + u64_to_user_ptr(ioctl_ctrl->handle), + sizeof(config))) { + CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed"); + rc = -EFAULT; + return rc; + } + + rc = cam_mem_get_cpu_buf(config.packet_handle, + &generic_ptr, &len_of_buffer); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed in getting the packet: %d", rc); + return rc; + } + + 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, + "Inval cam_packet strut size: %zu, len_of_buff: %zu", + sizeof(struct cam_packet), len_of_buffer); + rc = -EINVAL; + return rc; + } + + 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"); + rc = -EINVAL; + return rc; + } + + 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 %d", + csl_packet->header.request_id, fctrl->last_flush_req); + rc = -EINVAL; + return rc; + } + + 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*/ + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, + &cmd_buf_ptr, &len_of_buffer); + if (rc) { + CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc); + return rc; + } + 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; + return rc; + } + 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; + + switch (cam_flash_info->cmd_type) { + case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO: { + CAM_DBG(CAM_FLASH, "INIT_INFO CMD CALLED"); + fctrl->flash_init_setting.cmn_attr.request_id = 0; + fctrl->flash_init_setting.cmn_attr.is_settings_valid = + true; + fctrl->flash_type = cam_flash_info->flash_type; + fctrl->is_regulator_enabled = false; + fctrl->nrt_info.cmn_attr.cmd_type = + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO; + + rc = fctrl->func_tbl.power_ops(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + + fctrl->flash_state = + CAM_FLASH_STATE_CONFIG; + break; + } + 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; + return rc; + } + + 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; + return rc; + } + if (flash_operation_info->count > + CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "led count out of limit"); + rc = -EINVAL; + return rc; + } + fctrl->nrt_info.cmn_attr.count = + flash_operation_info->count; + fctrl->nrt_info.cmn_attr.request_id = 0; + fctrl->nrt_info.opcode = + flash_operation_info->opcode; + fctrl->nrt_info.cmn_attr.cmd_type = + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE; + for (i = 0; + i < flash_operation_info->count; i++) + fctrl->nrt_info.led_current_ma[i] = + flash_operation_info->led_current_ma[i]; + + rc = fctrl->func_tbl.apply_setting(fctrl, 0); + if (rc) + CAM_ERR(CAM_FLASH, + "Apply setting failed: %d", + rc); + + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; + break; + } + default: + CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d", + cam_flash_info->cmd_type); + rc = -EINVAL; + return rc; + } + break; + } + case CAM_FLASH_PACKET_OPCODE_SET_OPS: { + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; + flash_data = &fctrl->per_frame[frm_offset]; + + if (flash_data->cmn_attr.is_settings_valid == true) { + flash_data->cmn_attr.request_id = 0; + flash_data->cmn_attr.is_settings_valid = false; + for (i = 0; i < flash_data->cmn_attr.count; i++) + flash_data->led_current_ma[i] = 0; + } + + flash_data->cmn_attr.request_id = csl_packet->header.request_id; + 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, + &cmd_buf_ptr, &len_of_buffer); + if (rc) { + CAM_ERR(CAM_FLASH, "Fail in get buffer: 0x%x", + cmd_desc->mem_handle); + return rc; + } + + 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; + return rc; + } + 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; + return rc; + } + cmn_hdr = (struct common_header *)cmd_buf; + + switch (cmn_hdr->cmd_type) { + case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: { + CAM_DBG(CAM_FLASH, + "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called"); + if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || + (fctrl->flash_state == + CAM_FLASH_STATE_ACQUIRE)) { + CAM_WARN(CAM_FLASH, + "Rxed Flash fire ops without linking"); + flash_data->cmn_attr.is_settings_valid = false; + return -EINVAL; + } + if (remain_len < sizeof(struct cam_flash_set_on_off)) { + CAM_ERR(CAM_FLASH, "Not enough buffer"); + rc = -EINVAL; + return rc; + } + + 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; + return rc; + } + if (flash_operation_info->count > + CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "led count out of limit"); + rc = -EINVAL; + return rc; + } + + flash_data->opcode = flash_operation_info->opcode; + flash_data->cmn_attr.count = + flash_operation_info->count; + for (i = 0; i < flash_operation_info->count; i++) + flash_data->led_current_ma[i] + = flash_operation_info->led_current_ma[i]; + + if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) + add_req.skip_before_applying |= SKIP_NEXT_FRAME; + } + break; + default: + CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d", + cmn_hdr->cmd_type); + rc = -EINVAL; + return rc; + } + break; + } + case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: { + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + 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, + &cmd_buf_ptr, &len_of_buffer); + if (rc) { + CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc); + return rc; + } + + 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; + return rc; + } + 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; + return rc; + } + 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; + return rc; + } + if (flash_operation_info->count > + CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "led count out of limit"); + rc = -EINVAL; + return rc; + } + + fctrl->nrt_info.cmn_attr.count = + flash_operation_info->count; + fctrl->nrt_info.cmn_attr.request_id = 0; + fctrl->nrt_info.opcode = + flash_operation_info->opcode; + fctrl->nrt_info.cmn_attr.cmd_type = + CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET; + + for (i = 0; i < flash_operation_info->count; i++) + fctrl->nrt_info.led_current_ma[i] = + flash_operation_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; + } + 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; + return rc; + } + flash_query_info = + (struct cam_flash_query_curr *)cmd_buf; + + 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; + } + 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; + return rc; + } + flash_rer_info = (struct cam_flash_set_rer *)cmd_buf; + if (!flash_rer_info) { + CAM_ERR(CAM_FLASH, + "flash_rer_info Null"); + rc = -EINVAL; + return rc; + } + if (flash_rer_info->count > + CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "led count out of limit"); + rc = -EINVAL; + return rc; + } + + fctrl->nrt_info.cmn_attr.cmd_type = + CAMERA_SENSOR_FLASH_CMD_TYPE_RER; + fctrl->nrt_info.opcode = flash_rer_info->opcode; + fctrl->nrt_info.cmn_attr.count = flash_rer_info->count; + fctrl->nrt_info.cmn_attr.request_id = 0; + fctrl->nrt_info.num_iterations = + flash_rer_info->num_iteration; + fctrl->nrt_info.led_on_delay_ms = + flash_rer_info->led_on_delay_ms; + fctrl->nrt_info.led_off_delay_ms = + flash_rer_info->led_off_delay_ms; + + for (i = 0; i < flash_rer_info->count; i++) + 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; + } + default: + CAM_ERR(CAM_FLASH, "Wrong cmd_type : %d", + cmn_hdr->cmd_type); + rc = -EINVAL; + return rc; + } + + break; + } + case CAM_PKT_NOP_OPCODE: { + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; + if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || + (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { + CAM_WARN(CAM_FLASH, + "Rxed NOP packets without linking"); + fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid + = false; + return -EINVAL; + } + + fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid = false; + fctrl->per_frame[frm_offset].cmn_attr.request_id = 0; + 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); + break; + } + default: + CAM_ERR(CAM_FLASH, "Wrong Opcode : %d", + (csl_packet->header.op_code & 0xFFFFFF)); + rc = -EINVAL; + return rc; + } + + if (((csl_packet->header.op_code & 0xFFFFF) == + CAM_PKT_NOP_OPCODE) || + ((csl_packet->header.op_code & 0xFFFFF) == + CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + add_req.link_hdl = fctrl->bridge_intf.link_hdl; + add_req.req_id = csl_packet->header.request_id; + add_req.dev_hdl = fctrl->bridge_intf.device_hdl; + + if ((csl_packet->header.op_code & 0xFFFFF) == + CAM_FLASH_PACKET_OPCODE_SET_OPS) + add_req.skip_before_applying |= 1; + else + add_req.skip_before_applying = 0; + + if (fctrl->bridge_intf.crm_cb && + fctrl->bridge_intf.crm_cb->add_req) + fctrl->bridge_intf.crm_cb->add_req(&add_req); + CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); + } + + return rc; +} + +int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info) +{ + info->dev_id = CAM_REQ_MGR_DEVICE_FLASH; + strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name)); + info->p_delay = CAM_FLASH_PIPELINE_DELAY; + info->trigger = CAM_TRIGGER_POINT_SOF; + return 0; +} + +int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link) +{ + struct cam_flash_ctrl *fctrl = NULL; + + if (!link) + return -EINVAL; + + fctrl = (struct cam_flash_ctrl *)cam_get_device_priv(link->dev_hdl); + if (!fctrl) { + CAM_ERR(CAM_FLASH, " Device data is NULL"); + return -EINVAL; + } + mutex_lock(&fctrl->flash_mutex); + if (link->link_enable) { + fctrl->bridge_intf.link_hdl = link->link_hdl; + fctrl->bridge_intf.crm_cb = link->crm_cb; + } else { + fctrl->bridge_intf.link_hdl = -1; + fctrl->bridge_intf.crm_cb = NULL; + } + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + +int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) +{ + int rc = 0; + + if (fctrl->bridge_intf.device_hdl != 1) { + rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl); + if (rc) + CAM_ERR(CAM_FLASH, + "Failed in destroying device handle rc = %d", + rc); + 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; +} + +void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) +{ + int rc; + + if (fctrl->flash_state == CAM_FLASH_STATE_INIT) + return; + + if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || + (fctrl->flash_state == CAM_FLASH_STATE_START)) { + fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + rc = fctrl->func_tbl.power_ops(fctrl, false); + if (rc) + CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", + rc); + } + + rc = cam_flash_release_dev(fctrl); + if (rc) + CAM_ERR(CAM_FLASH, "Release failed rc: %d", rc); + + fctrl->flash_state = CAM_FLASH_STATE_INIT; +} + +int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_flash_ctrl *fctrl = NULL; + + if (!apply) + return -EINVAL; + + fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(apply->dev_hdl); + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Device data is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + rc = fctrl->func_tbl.apply_setting(fctrl, apply->request_id); + if (rc) + CAM_ERR(CAM_FLASH, "apply_setting failed with rc=%d", + rc); + mutex_unlock(&fctrl->flash_mutex); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/cam_sensor_module/cam_flash/cam_flash_core.h new file mode 100644 index 000000000000..6cafe927cdbb --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FLASH_CORE_H_ +#define _CAM_FLASH_CORE_H_ + +#include +#include "cam_flash_dev.h" + +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); + + +#endif /*_CAM_FLASH_CORE_H_*/ diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c new file mode 100644 index 000000000000..d0610667e626 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -0,0 +1,652 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_flash_dev.h" +#include "cam_flash_soc.h" +#include "cam_flash_core.h" +#include "cam_common_util.h" + +static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, + void *arg, struct cam_flash_private_soc *soc_private) +{ + int rc = 0; + int i = 0; + struct cam_control *cmd = (struct cam_control *)arg; + + if (!fctrl || !arg) { + CAM_ERR(CAM_FLASH, "fctrl/arg is NULL with arg:%pK fctrl%pK", + fctrl, arg); + return -EINVAL; + } + + if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_FLASH, "Invalid handle type: %d", + cmd->handle_type); + return -EINVAL; + } + + mutex_lock(&(fctrl->flash_mutex)); + switch (cmd->op_code) { + case CAM_ACQUIRE_DEV: { + struct cam_sensor_acquire_dev flash_acq_dev; + struct cam_create_dev_hdl bridge_params; + + CAM_DBG(CAM_FLASH, "CAM_ACQUIRE_DEV"); + + if (fctrl->flash_state != CAM_FLASH_STATE_INIT) { + CAM_ERR(CAM_FLASH, + "Cannot apply Acquire dev: Prev state: %d", + fctrl->flash_state); + rc = -EINVAL; + goto release_mutex; + } + + if (fctrl->bridge_intf.device_hdl != -1) { + CAM_ERR(CAM_FLASH, "Device is already acquired"); + rc = -EINVAL; + goto release_mutex; + } + + rc = copy_from_user(&flash_acq_dev, + u64_to_user_ptr(cmd->handle), + sizeof(flash_acq_dev)); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed Copying from User"); + goto release_mutex; + } + + bridge_params.session_hdl = flash_acq_dev.session_handle; + bridge_params.ops = &fctrl->bridge_intf.ops; + bridge_params.v4l2_sub_dev_flag = 0; + bridge_params.media_entity_flag = 0; + bridge_params.priv = fctrl; + + flash_acq_dev.device_handle = + cam_create_device_hdl(&bridge_params); + fctrl->bridge_intf.device_hdl = + flash_acq_dev.device_handle; + fctrl->bridge_intf.session_hdl = + flash_acq_dev.session_handle; + + rc = copy_to_user(u64_to_user_ptr(cmd->handle), + &flash_acq_dev, + sizeof(struct cam_sensor_acquire_dev)); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed Copy to User with rc = %d", + rc); + rc = -EFAULT; + goto release_mutex; + } + fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE; + break; + } + case CAM_RELEASE_DEV: { + CAM_DBG(CAM_FLASH, "CAM_RELEASE_DEV"); + if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || + (fctrl->flash_state == CAM_FLASH_STATE_START)) { + CAM_WARN(CAM_FLASH, + "Wrong state for Release dev: Prev state:%d", + fctrl->flash_state); + } + + if (fctrl->bridge_intf.device_hdl == -1 && + fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE) { + CAM_ERR(CAM_FLASH, + "Invalid Handle: Link Hdl: %d device hdl: %d", + fctrl->bridge_intf.device_hdl, + fctrl->bridge_intf.link_hdl); + rc = -EINVAL; + goto release_mutex; + } + + if (fctrl->bridge_intf.link_hdl != -1) { + CAM_ERR(CAM_FLASH, + "Device [%d] still active on link 0x%x", + fctrl->flash_state, + fctrl->bridge_intf.link_hdl); + rc = -EAGAIN; + goto release_mutex; + } + + if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || + (fctrl->flash_state == CAM_FLASH_STATE_START)) + fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + + if (cam_flash_release_dev(fctrl)) + CAM_WARN(CAM_FLASH, + "Failed in destroying the device Handle"); + + if (fctrl->func_tbl.power_ops(fctrl, false)) + CAM_WARN(CAM_FLASH, "Power Down Failed"); + + fctrl->flash_state = CAM_FLASH_STATE_INIT; + break; + } + case CAM_QUERY_CAP: { + struct cam_flash_query_cap_info flash_cap = {0}; + + CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); + flash_cap.slot_info = fctrl->soc_info.index; + for (i = 0; i < fctrl->flash_num_sources; i++) { + flash_cap.max_current_flash[i] = + soc_private->flash_max_current[i]; + flash_cap.max_duration_flash[i] = + soc_private->flash_max_duration[i]; + } + + for (i = 0; i < fctrl->torch_num_sources; i++) + flash_cap.max_current_torch[i] = + soc_private->torch_max_current[i]; + + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &flash_cap, sizeof(struct cam_flash_query_cap_info))) { + CAM_ERR(CAM_FLASH, "Failed Copy to User"); + rc = -EFAULT; + goto release_mutex; + } + break; + } + case CAM_START_DEV: { + CAM_DBG(CAM_FLASH, "CAM_START_DEV"); + if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || + (fctrl->flash_state == CAM_FLASH_STATE_START)) { + CAM_WARN(CAM_FLASH, + "Cannot apply Start Dev: Prev state: %d", + fctrl->flash_state); + rc = -EINVAL; + goto release_mutex; + } + + fctrl->flash_state = CAM_FLASH_STATE_START; + break; + } + case CAM_STOP_DEV: { + CAM_DBG(CAM_FLASH, "CAM_STOP_DEV ENTER"); + if (fctrl->flash_state != CAM_FLASH_STATE_START) { + CAM_WARN(CAM_FLASH, + "Cannot apply Stop dev: Prev state is: %d", + fctrl->flash_state); + rc = -EINVAL; + 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; + } + case CAM_CONFIG_DEV: { + CAM_DBG(CAM_FLASH, "CAM_CONFIG_DEV"); + rc = fctrl->func_tbl.parser(fctrl, arg); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed Flash Config: rc=%d\n", rc); + goto release_mutex; + } + break; + } + default: + CAM_ERR(CAM_FLASH, "Invalid Opcode: %d", cmd->op_code); + rc = -EINVAL; + } + +release_mutex: + mutex_unlock(&(fctrl->flash_mutex)); + return rc; +} + +static int32_t cam_flash_init_default_params(struct cam_flash_ctrl *fctrl) +{ + /* Validate input parameters */ + if (!fctrl) { + CAM_ERR(CAM_FLASH, "failed: invalid params fctrl %pK", + fctrl); + return -EINVAL; + } + + CAM_DBG(CAM_FLASH, + "master_type: %d", fctrl->io_master_info.master_type); + /* Initialize cci_client */ + if (fctrl->io_master_info.master_type == CCI_MASTER) { + fctrl->io_master_info.cci_client = kzalloc(sizeof( + struct cam_sensor_cci_client), GFP_KERNEL); + if (!(fctrl->io_master_info.cci_client)) + return -ENOMEM; + } else if (fctrl->io_master_info.master_type == I2C_MASTER) { + if (!(fctrl->io_master_info.client)) + return -EINVAL; + } else { + CAM_ERR(CAM_FLASH, + "Invalid master / Master type Not supported"); + return -EINVAL; + } + + return 0; +} + +static const struct of_device_id cam_flash_dt_match[] = { + {.compatible = "qcom,camera-flash", .data = NULL}, + {} +}; + +static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_flash_ctrl *fctrl = NULL; + struct cam_flash_private_soc *soc_private = NULL; + + CAM_DBG(CAM_FLASH, "Enter"); + + fctrl = v4l2_get_subdevdata(sd); + soc_private = fctrl->soc_info.soc_private; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: { + rc = cam_flash_driver_cmd(fctrl, arg, + soc_private); + break; + } + default: + CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); + rc = -EINVAL; + break; + } + + CAM_DBG(CAM_FLASH, "Exit"); + return rc; +} + +#ifdef CONFIG_COMPAT +static long cam_flash_subdev_do_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int32_t rc = 0; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_FLASH, + "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: { + rc = cam_flash_subdev_ioctl(sd, cmd, &cmd_data); + if (rc) + CAM_ERR(CAM_FLASH, "cam_flash_ioctl failed"); + break; + } + default: + CAM_ERR(CAM_FLASH, "Invalid compat ioctl cmd_type:%d", + cmd); + rc = -EINVAL; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_FLASH, + "Failed to copy to user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + + return rc; +} +#endif + +static int cam_flash_platform_remove(struct platform_device *pdev) +{ + struct cam_flash_ctrl *fctrl; + + fctrl = platform_get_drvdata(pdev); + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash device is NULL"); + return 0; + } + + 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; +} + +static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) +{ + int32_t rc = 0; + struct cam_flash_ctrl *fctrl = i2c_get_clientdata(client); + /* Handle I2C Devices */ + if (!fctrl) { + 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; + kfree(fctrl); + return rc; +} + +static int cam_flash_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_flash_ctrl *fctrl = + v4l2_get_subdevdata(sd); + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + +static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = { + .ioctl = cam_flash_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_flash_subdev_do_ioctl +#endif +}; + +static struct v4l2_subdev_ops cam_flash_subdev_ops = { + .core = &cam_flash_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops cam_flash_internal_ops = { + .close = cam_flash_subdev_close, +}; + +static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) +{ + int rc = 0; + + fctrl->v4l2_dev_str.internal_ops = + &cam_flash_internal_ops; + fctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops; + fctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME; + fctrl->v4l2_dev_str.sd_flags = + V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; + fctrl->v4l2_dev_str.token = fctrl; + + rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); + if (rc) + CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc); + + return rc; +} + +static int32_t cam_flash_platform_probe(struct platform_device *pdev) +{ + int32_t rc = 0, i = 0; + struct cam_flash_ctrl *fctrl = NULL; + struct device_node *of_parent = NULL; + + CAM_DBG(CAM_FLASH, "Enter"); + if (!pdev->dev.of_node) { + CAM_ERR(CAM_FLASH, "of_node NULL"); + return -EINVAL; + } + + fctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL); + if (!fctrl) + return -ENOMEM; + + fctrl->pdev = pdev; + fctrl->soc_info.pdev = pdev; + fctrl->soc_info.dev = &pdev->dev; + fctrl->soc_info.dev_name = pdev->name; + + platform_set_drvdata(pdev, fctrl); + + rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "cam_flash_get_dt_data failed with %d", rc); + kfree(fctrl); + return -EINVAL; + } + + if (of_find_property(pdev->dev.of_node, "cci-master", NULL)) { + /* Get CCI master */ + rc = of_property_read_u32(pdev->dev.of_node, "cci-master", + &fctrl->cci_i2c_master); + CAM_DBG(CAM_FLASH, "cci-master %d, rc %d", + fctrl->cci_i2c_master, rc); + if (rc < 0) { + /* Set default master 0 */ + fctrl->cci_i2c_master = MASTER_0; + rc = 0; + } + + fctrl->io_master_info.master_type = CCI_MASTER; + rc = cam_flash_init_default_params(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed: cam_flash_init_default_params rc %d", + rc); + return rc; + } + + of_parent = of_get_parent(pdev->dev.of_node); + if (of_property_read_u32(of_parent, "cell-index", + &fctrl->cci_num) < 0) + /* Set default master 0 */ + fctrl->cci_num = CCI_DEVICE_0; + + fctrl->io_master_info.cci_client->cci_device = fctrl->cci_num; + CAM_DBG(CAM_FLASH, "cci-index %d", fctrl->cci_num, rc); + + fctrl->i2c_data.per_frame = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (fctrl->i2c_data.per_frame == NULL) { + CAM_ERR(CAM_FLASH, "No Memory"); + rc = -ENOMEM; + goto free_cci_resource; + } + + INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD( + &(fctrl->i2c_data.per_frame[i].list_head)); + + fctrl->func_tbl.parser = cam_flash_i2c_pkt_parser; + fctrl->func_tbl.apply_setting = cam_flash_i2c_apply_setting; + fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops; + fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request; + } else { + /* PMIC Flash */ + fctrl->func_tbl.parser = cam_flash_pmic_pkt_parser; + fctrl->func_tbl.apply_setting = cam_flash_pmic_apply_setting; + fctrl->func_tbl.power_ops = cam_flash_pmic_power_ops; + fctrl->func_tbl.flush_req = cam_flash_pmic_flush_request; + } + + rc = cam_flash_init_subdev(fctrl); + if (rc) { + if (fctrl->io_master_info.cci_client != NULL) + goto free_cci_resource; + else + goto free_resource; + } + + fctrl->bridge_intf.device_hdl = -1; + fctrl->bridge_intf.link_hdl = -1; + fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; + 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; + CAM_DBG(CAM_FLASH, "Probe success"); + return rc; + +free_cci_resource: + kfree(fctrl->io_master_info.cci_client); + fctrl->io_master_info.cci_client = NULL; +free_resource: + kfree(fctrl->i2c_data.per_frame); + kfree(fctrl->soc_info.soc_private); + cam_soc_util_release_platform_resource(&fctrl->soc_info); + fctrl->i2c_data.per_frame = NULL; + fctrl->soc_info.soc_private = NULL; + kfree(fctrl); + fctrl = NULL; + return rc; +} + +static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int32_t rc = 0, i = 0; + struct cam_flash_ctrl *fctrl; + + if (client == NULL || id == NULL) { + CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK", + client, id); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed", + client->name); + return -EFAULT; + } + + /* Create sensor control structure */ + fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL); + if (!fctrl) + return -ENOMEM; + + i2c_set_clientdata(client, fctrl); + + fctrl->io_master_info.client = client; + fctrl->soc_info.dev = &client->dev; + fctrl->soc_info.dev_name = client->name; + fctrl->io_master_info.master_type = I2C_MASTER; + + rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc); + goto free_ctrl; + } + + rc = cam_flash_init_subdev(fctrl); + if (rc) + goto free_ctrl; + + fctrl->i2c_data.per_frame = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (fctrl->i2c_data.per_frame == NULL) { + rc = -ENOMEM; + goto unreg_subdev; + } + + INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head)); + + fctrl->func_tbl.parser = cam_flash_i2c_pkt_parser; + fctrl->func_tbl.apply_setting = cam_flash_i2c_apply_setting; + fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops; + fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request; + + fctrl->bridge_intf.device_hdl = -1; + fctrl->bridge_intf.link_hdl = -1; + fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; + 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; + + return rc; + +unreg_subdev: + cam_unregister_subdev(&(fctrl->v4l2_dev_str)); +free_ctrl: + kfree(fctrl); + fctrl = NULL; + return rc; +} + +MODULE_DEVICE_TABLE(of, cam_flash_dt_match); + +static struct platform_driver cam_flash_platform_driver = { + .probe = cam_flash_platform_probe, + .remove = cam_flash_platform_remove, + .driver = { + .name = "CAM-FLASH-DRIVER", + .owner = THIS_MODULE, + .of_match_table = cam_flash_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static const struct i2c_device_id i2c_id[] = { + {FLASH_DRIVER_I2C, (kernel_ulong_t)NULL}, + { } +}; + +static struct i2c_driver cam_flash_i2c_driver = { + .id_table = i2c_id, + .probe = cam_flash_i2c_driver_probe, + .remove = cam_flash_i2c_driver_remove, + .driver = { + .name = FLASH_DRIVER_I2C, + }, +}; + +static int32_t __init cam_flash_init_module(void) +{ + int32_t rc = 0; + + rc = platform_driver_register(&cam_flash_platform_driver); + if (rc == 0) { + CAM_DBG(CAM_FLASH, "platform probe success"); + return 0; + } + + rc = i2c_add_driver(&cam_flash_i2c_driver); + if (rc) + CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc); + return rc; +} + +static void __exit cam_flash_exit_module(void) +{ + platform_driver_unregister(&cam_flash_platform_driver); + i2c_del_driver(&cam_flash_i2c_driver); +} + +module_init(cam_flash_init_module); +module_exit(cam_flash_exit_module); +MODULE_DESCRIPTION("CAM FLASH"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h new file mode 100644 index 000000000000..c4f17656ace0 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FLASH_DEV_H_ +#define _CAM_FLASH_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_req_mgr_util.h" +#include "cam_req_mgr_interface.h" +#include "cam_subdev.h" +#include "cam_mem_mgr.h" +#include "cam_sensor_cmn_header.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_sensor_io.h" +#include "cam_flash_core.h" + +#define CAMX_FLASH_DEV_NAME "cam-flash-dev" + +#define CAM_FLASH_PIPELINE_DELAY 1 + +#define FLASH_DRIVER_I2C "i2c_flash" + +#define CAM_FLASH_PACKET_OPCODE_INIT 0 +#define CAM_FLASH_PACKET_OPCODE_SET_OPS 1 +#define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2 + +struct cam_flash_ctrl; + +enum cam_flash_switch_trigger_ops { + LED_SWITCH_OFF = 0, + LED_SWITCH_ON, +}; + +enum cam_flash_state { + CAM_FLASH_STATE_INIT, + CAM_FLASH_STATE_ACQUIRE, + CAM_FLASH_STATE_CONFIG, + CAM_FLASH_STATE_START, +}; + +enum cam_flash_flush_type { + FLUSH_ALL = 0, + FLUSH_REQ, + FLUSH_MAX, +}; + +/** + * struct cam_flash_intf_params + * @device_hdl : Device Handle + * @session_hdl : Session Handle + * @link_hdl : Link Handle + * @ops : KMD operations + * @crm_cb : Callback API pointers + */ +struct cam_flash_intf_params { + int32_t device_hdl; + int32_t session_hdl; + int32_t link_hdl; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; +}; + +/** + * struct cam_flash_common_attr + * @is_settings_valid : Notify the valid settings + * @request_id : Request id provided by umd + * @count : Number of led count + * @cmd_type : Command buffer type + */ +struct cam_flash_common_attr { + bool is_settings_valid; + uint64_t request_id; + uint16_t count; + uint8_t cmd_type; +}; + +/** + * struct flash_init_packet + * @cmn_attr : Provides common attributes + * @flash_type : Flash type(PMIC/I2C/GPIO) + */ +struct cam_flash_init_packet { + struct cam_flash_common_attr cmn_attr; + uint8_t flash_type; +}; + +/** + * struct flash_frame_setting + * @cmn_attr : Provides common attributes + * @num_iterations : Iterations used to perform RER + * @led_on_delay_ms : LED on time in milisec + * @led_off_delay_ms : LED off time in milisec + * @opcode : Command buffer opcode + * @led_current_ma[] : LED current array in miliamps + * + */ +struct cam_flash_frame_setting { + struct cam_flash_common_attr cmn_attr; + uint16_t num_iterations; + uint16_t led_on_delay_ms; + uint16_t led_off_delay_ms; + int8_t opcode; + uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; +}; + +/** + * struct cam_flash_private_soc + * @switch_trigger_name : Switch trigger name + * @flash_trigger_name : Flash trigger name array + * @flash_op_current : Flash operational current + * @flash_max_current : Max supported current for LED in flash mode + * @flash_max_duration : Max turn on duration for LED in Flash mode + * @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 { + const char *switch_trigger_name; + const char *flash_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS]; + uint32_t flash_op_current[CAM_FLASH_MAX_LED_TRIGGERS]; + uint32_t flash_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; + uint32_t flash_max_duration[CAM_FLASH_MAX_LED_TRIGGERS]; + 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 { + int (*parser)(struct cam_flash_ctrl *fctrl, void *arg); + int (*apply_setting)(struct cam_flash_ctrl *fctrl, uint64_t req_id); + int (*power_ops)(struct cam_flash_ctrl *fctrl, bool regulator_enable); + int (*flush_req)(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id); +}; + +/** + * struct cam_flash_ctrl + * @soc_info : Soc related information + * @pdev : Platform device + * @per_frame[] : Per_frame setting array + * @nrt_info : NonRealTime settings + * @of_node : Of Node ptr + * @v4l2_dev_str : V4L2 device structure + * @bridge_intf : CRM interface + * @flash_init_setting : Init command buffer structure + * @switch_trigger : Switch trigger ptr + * @flash_num_sources : Number of flash sources + * @torch_num_source : Number of torch sources + * @flash_mutex : Mutex for flash operations + * @flash_state : Current flash state (LOW/OFF/ON/INIT) + * @flash_type : Flash types (PMIC/I2C/GPIO) + * @is_regulator_enable : Regulator disable/enable notifier + * @func_tbl : Function table for different HW + * (e.g. i2c/pmic/gpio) + * @flash_trigger : Flash trigger ptr + * @torch_trigger : Torch trigger ptr + * @cci_i2c_master : I2C structure + * @cci_device_num : cci parent cell index + * @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; + struct platform_device *pdev; + struct cam_sensor_power_ctrl_t power_info; + struct cam_flash_frame_setting per_frame[MAX_PER_FRAME_ARRAY]; + struct cam_flash_frame_setting nrt_info; + struct device_node *of_node; + struct cam_subdev v4l2_dev_str; + struct cam_flash_intf_params bridge_intf; + struct cam_flash_init_packet flash_init_setting; + struct led_trigger *switch_trigger; + uint32_t flash_num_sources; + uint32_t torch_num_sources; + struct mutex flash_mutex; + enum cam_flash_state flash_state; + uint8_t flash_type; + bool is_regulator_enabled; + struct cam_flash_func_tbl func_tbl; + struct led_trigger *flash_trigger[CAM_FLASH_MAX_LED_TRIGGERS]; + struct led_trigger *torch_trigger[CAM_FLASH_MAX_LED_TRIGGERS]; +/* I2C related setting */ + enum cci_i2c_master_t cci_i2c_master; + enum cci_device_num cci_num; + 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); +int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg); +int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id); +int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id); +int cam_flash_off(struct cam_flash_ctrl *fctrl); +int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable); +int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable); +int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id); +int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type, uint64_t req_id); +void cam_flash_shutdown(struct cam_flash_ctrl *fctrl); +int cam_flash_release_dev(struct cam_flash_ctrl *fctrl); + +#endif /*_CAM_FLASH_DEV_H_*/ diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c new file mode 100644 index 000000000000..762977f4b968 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "cam_flash_soc.h" +#include "cam_res_mgr_api.h" + +static int32_t cam_get_source_node_info( + struct device_node *of_node, + struct cam_flash_ctrl *fctrl, + struct cam_flash_private_soc *soc_private) +{ + int32_t rc = 0; + uint32_t count = 0, i = 0; + struct device_node *flash_src_node = NULL; + 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_WARN(CAM_FLASH, "switch_src_node NULL"); + } else { + rc = of_property_read_string(switch_src_node, + "qcom,default-led-trigger", + &soc_private->switch_trigger_name); + if (rc) { + CAM_ERR(CAM_FLASH, + "default-led-trigger read failed rc=%d", rc); + } else { + CAM_DBG(CAM_FLASH, "switch trigger %s", + soc_private->switch_trigger_name); + cam_res_mgr_led_trigger_register( + soc_private->switch_trigger_name, + &fctrl->switch_trigger); + } + + of_node_put(switch_src_node); + } + + if (of_get_property(of_node, "flash-source", &count)) { + count /= sizeof(uint32_t); + + if (count > CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "Invalid LED count: %d", count); + return -EINVAL; + } + + fctrl->flash_num_sources = count; + + for (i = 0; i < count; i++) { + flash_src_node = of_parse_phandle(of_node, + "flash-source", i); + if (!flash_src_node) { + CAM_WARN(CAM_FLASH, "flash_src_node NULL"); + continue; + } + + rc = of_property_read_string(flash_src_node, + "qcom,default-led-trigger", + &soc_private->flash_trigger_name[i]); + if (rc) { + CAM_WARN(CAM_FLASH, + "defalut-led-trigger read failed rc=%d", rc); + of_node_put(flash_src_node); + continue; + } + + 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_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_INFO(CAM_FLASH, + "max-duration prop unavailable: %d", + rc); + rc = 0; + } + of_node_put(flash_src_node); + + CAM_DBG(CAM_FLASH, "MainFlashMaxCurrent[%d]: %d", + i, soc_private->flash_max_current[i]); + } + } + + if (of_get_property(of_node, "torch-source", &count)) { + count /= sizeof(uint32_t); + if (count > CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "Invalid LED count : %d", count); + return -EINVAL; + } + + fctrl->torch_num_sources = count; + + CAM_DBG(CAM_FLASH, "torch_num_sources = %d", + fctrl->torch_num_sources); + for (i = 0; i < count; i++) { + torch_src_node = of_parse_phandle(of_node, + "torch-source", i); + if (!torch_src_node) { + CAM_WARN(CAM_FLASH, "torch_src_node NULL"); + continue; + } + + rc = of_property_read_string(torch_src_node, + "qcom,default-led-trigger", + &soc_private->torch_trigger_name[i]); + if (rc < 0) { + CAM_WARN(CAM_FLASH, + "default-trigger read failed"); + of_node_put(torch_src_node); + 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, + "op-current prop unavailable: %d", rc); + rc = 0; + } + + of_node_put(torch_src_node); + + CAM_DBG(CAM_FLASH, "TorchMaxCurrent[%d]: %d", + i, soc_private->torch_max_current[i]); + } + } + + return rc; +} + +int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, + struct cam_hw_soc_info *soc_info) +{ + int32_t rc = 0; + struct device_node *of_node = NULL; + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "NULL flash control structure"); + return -EINVAL; + } + + soc_info->soc_private = + kzalloc(sizeof(struct cam_flash_private_soc), GFP_KERNEL); + if (!soc_info->soc_private) { + rc = -ENOMEM; + goto release_soc_res; + } + of_node = fctrl->pdev->dev.of_node; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "Get_dt_properties failed rc %d", rc); + goto free_soc_private; + } + + rc = cam_get_source_node_info(of_node, fctrl, soc_info->soc_private); + if (rc) { + CAM_ERR(CAM_FLASH, + "cam_flash_get_pmic_source_info failed rc %d", rc); + goto free_soc_private; + } + return rc; + +free_soc_private: + kfree(soc_info->soc_private); + soc_info->soc_private = NULL; +release_soc_res: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h new file mode 100644 index 000000000000..cfe7c3464f64 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FLASH_SOC_H_ +#define _CAM_FLASH_SOC_H_ + +#include "cam_flash_dev.h" + +int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, + struct cam_hw_soc_info *soc_info); + +#endif /*_CAM_FLASH_SOC_H_*/ diff --git a/drivers/cam_sensor_module/cam_ois/Makefile b/drivers/cam_sensor_module/cam_ois/Makefile new file mode 100644 index 000000000000..e987a2257e9e --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c new file mode 100644 index 000000000000..b6035252a234 --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -0,0 +1,843 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include "cam_ois_core.h" +#include "cam_ois_soc.h" +#include "cam_sensor_util.h" +#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) +{ + int rc = 0; + + power_info->power_setting_size = 1; + power_info->power_setting = + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_setting) + return -ENOMEM; + + power_info->power_setting[0].seq_type = SENSOR_VAF; + power_info->power_setting[0].seq_val = CAM_VAF; + power_info->power_setting[0].config_val = 1; + power_info->power_setting[0].delay = 2; + + power_info->power_down_setting_size = 1; + power_info->power_down_setting = + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_down_setting) { + rc = -ENOMEM; + goto free_power_settings; + } + + power_info->power_down_setting[0].seq_type = SENSOR_VAF; + power_info->power_down_setting[0].seq_val = CAM_VAF; + power_info->power_down_setting[0].config_val = 0; + + return rc; + +free_power_settings: + kfree(power_info->power_setting); + power_info->power_setting = NULL; + power_info->power_setting_size = 0; + return rc; +} + + +/** + * cam_ois_get_dev_handle - get device handle + * @o_ctrl: ctrl structure + * @arg: Camera control command argument + * + * Returns success or failure + */ +static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, + void *arg) +{ + struct cam_sensor_acquire_dev ois_acq_dev; + struct cam_create_dev_hdl bridge_params; + struct cam_control *cmd = (struct cam_control *)arg; + + if (o_ctrl->bridge_intf.device_hdl != -1) { + CAM_ERR(CAM_OIS, "Device is already acquired"); + return -EFAULT; + } + if (copy_from_user(&ois_acq_dev, u64_to_user_ptr(cmd->handle), + sizeof(ois_acq_dev))) + return -EFAULT; + + bridge_params.session_hdl = ois_acq_dev.session_handle; + bridge_params.ops = &o_ctrl->bridge_intf.ops; + bridge_params.v4l2_sub_dev_flag = 0; + bridge_params.media_entity_flag = 0; + bridge_params.priv = o_ctrl; + + ois_acq_dev.device_handle = + cam_create_device_hdl(&bridge_params); + o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle; + o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle; + + CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle); + if (copy_to_user(u64_to_user_ptr(cmd->handle), &ois_acq_dev, + sizeof(struct cam_sensor_acquire_dev))) { + CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed"); + return -EFAULT; + } + return 0; +} + +static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = + &o_ctrl->soc_info; + struct cam_ois_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + soc_private = + (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + + if ((power_info->power_setting == NULL) && + (power_info->power_down_setting == NULL)) { + CAM_INFO(CAM_OIS, + "Using default power settings"); + rc = cam_ois_construct_default_power_setting(power_info); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Construct default ois power setting failed."); + return rc; + } + } + + /* Parse and fill vreg params for power up settings */ + rc = msm_camera_fill_vreg_params( + soc_info, + power_info->power_setting, + power_info->power_setting_size); + if (rc) { + CAM_ERR(CAM_OIS, + "failed to fill vreg params for power up rc:%d", rc); + return rc; + } + + /* Parse and fill vreg params for power down settings*/ + rc = msm_camera_fill_vreg_params( + soc_info, + power_info->power_down_setting, + power_info->power_down_setting_size); + if (rc) { + CAM_ERR(CAM_OIS, + "failed to fill vreg params for power down rc:%d", rc); + return rc; + } + + power_info->dev = soc_info->dev; + + rc = cam_sensor_core_power_up(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_OIS, "failed in ois power up rc %d", rc); + return rc; + } + + rc = camera_io_init(&o_ctrl->io_master_info); + if (rc) + CAM_ERR(CAM_OIS, "cci_init failed: rc: %d", rc); + + return rc; +} + +/** + * cam_ois_power_down - power down OIS device + * @o_ctrl: ctrl structure + * + * Returns success or failure + */ +static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl) +{ + int32_t rc = 0; + struct cam_sensor_power_ctrl_t *power_info; + struct cam_hw_soc_info *soc_info = + &o_ctrl->soc_info; + struct cam_ois_soc_private *soc_private; + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "failed: o_ctrl %pK", o_ctrl); + return -EINVAL; + } + + soc_private = + (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + soc_info = &o_ctrl->soc_info; + + if (!power_info) { + CAM_ERR(CAM_OIS, "failed: power_info %pK", power_info); + return -EINVAL; + } + + rc = cam_sensor_util_power_down(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_OIS, "power down the core is failed:%d", rc); + return rc; + } + + camera_io_release(&o_ctrl->io_master_info); + + return rc; +} + +static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, + struct i2c_settings_array *i2c_set) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0; + uint32_t i, size; + + if (o_ctrl == NULL || i2c_set == NULL) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + if (i2c_set->is_settings_valid != 1) { + CAM_ERR(CAM_OIS, " Invalid settings"); + return -EINVAL; + } + + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) { + rc = camera_io_dev_write(&(o_ctrl->io_master_info), + &(i2c_list->i2c_settings)); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed in Applying i2c wrt settings"); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { + size = i2c_list->i2c_settings.size; + for (i = 0; i < size; i++) { + rc = camera_io_dev_poll( + &(o_ctrl->io_master_info), + i2c_list->i2c_settings.reg_setting[i].reg_addr, + i2c_list->i2c_settings.reg_setting[i].reg_data, + i2c_list->i2c_settings.reg_setting[i].data_mask, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.reg_setting[i].delay); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "i2c poll apply setting Fail"); + return rc; + } + } + } + } + + return rc; +} + +static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, + uint32_t *cmd_buf, size_t len) +{ + int32_t rc = 0; + struct cam_cmd_ois_info *ois_info; + + if (!o_ctrl || !cmd_buf || len < sizeof(struct cam_cmd_ois_info)) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + ois_info = (struct cam_cmd_ois_info *)cmd_buf; + if (o_ctrl->io_master_info.master_type == CCI_MASTER) { + o_ctrl->io_master_info.cci_client->i2c_freq_mode = + ois_info->i2c_freq_mode; + o_ctrl->io_master_info.cci_client->sid = + 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, 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), + sizeof(struct cam_ois_opcode)); + CAM_DBG(CAM_OIS, "Slave addr: 0x%x Freq Mode: %d", + ois_info->slave_addr, ois_info->i2c_freq_mode); + } else if (o_ctrl->io_master_info.master_type == I2C_MASTER) { + o_ctrl->io_master_info.client->addr = ois_info->slave_addr; + CAM_DBG(CAM_OIS, "Slave addr: 0x%x", ois_info->slave_addr); + } else { + CAM_ERR(CAM_OIS, "Invalid Master type : %d", + o_ctrl->io_master_info.master_type); + rc = -EINVAL; + } + + return rc; +} + +static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) +{ + uint16_t total_bytes = 0; + uint8_t *ptr = NULL; + int32_t rc = 0, cnt; + uint32_t fw_size; + const struct firmware *fw = NULL; + const char *fw_name_prog = NULL; + const char *fw_name_coeff = NULL; + char name_prog[32] = {0}; + char name_coeff[32] = {0}; + struct device *dev = &(o_ctrl->pdev->dev); + struct cam_sensor_i2c_reg_setting i2c_reg_setting; + struct page *page = NULL; + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + snprintf(name_coeff, 32, "%s.coeff", o_ctrl->ois_name); + + snprintf(name_prog, 32, "%s.prog", o_ctrl->ois_name); + + /* cast pointer as const pointer*/ + fw_name_prog = name_prog; + fw_name_coeff = name_coeff; + + /* Load FW */ + rc = request_firmware(&fw, fw_name_prog, dev); + if (rc) { + CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog); + return rc; + } + + total_bytes = fw->size; + i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE; + i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; + i2c_reg_setting.size = total_bytes; + i2c_reg_setting.delay = 0; + fw_size = PAGE_ALIGN(sizeof(struct cam_sensor_i2c_reg_array) * + total_bytes) >> PAGE_SHIFT; + page = cma_alloc(dev_get_cma_area((o_ctrl->soc_info.dev)), + fw_size, 0, GFP_KERNEL); + if (!page) { + CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); + release_firmware(fw); + return -ENOMEM; + } + + i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) ( + page_address(page)); + + for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes; + cnt++, ptr++) { + i2c_reg_setting.reg_setting[cnt].reg_addr = + o_ctrl->opcode.prog; + i2c_reg_setting.reg_setting[cnt].reg_data = *ptr; + i2c_reg_setting.reg_setting[cnt].delay = 0; + i2c_reg_setting.reg_setting[cnt].data_mask = 0; + } + + rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), + &i2c_reg_setting, 1); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); + goto release_firmware; + } + cma_release(dev_get_cma_area((o_ctrl->soc_info.dev)), + page, fw_size); + page = NULL; + fw_size = 0; + release_firmware(fw); + + rc = request_firmware(&fw, fw_name_coeff, dev); + if (rc) { + CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff); + return rc; + } + + total_bytes = fw->size; + i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE; + i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; + i2c_reg_setting.size = total_bytes; + i2c_reg_setting.delay = 0; + fw_size = PAGE_ALIGN(sizeof(struct cam_sensor_i2c_reg_array) * + total_bytes) >> PAGE_SHIFT; + page = cma_alloc(dev_get_cma_area((o_ctrl->soc_info.dev)), + fw_size, 0, GFP_KERNEL); + if (!page) { + CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); + release_firmware(fw); + return -ENOMEM; + } + + i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) ( + page_address(page)); + + for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes; + cnt++, ptr++) { + i2c_reg_setting.reg_setting[cnt].reg_addr = + o_ctrl->opcode.coeff; + i2c_reg_setting.reg_setting[cnt].reg_data = *ptr; + i2c_reg_setting.reg_setting[cnt].delay = 0; + i2c_reg_setting.reg_setting[cnt].data_mask = 0; + } + + rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), + &i2c_reg_setting, 1); + if (rc < 0) + CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); + +release_firmware: + cma_release(dev_get_cma_area((o_ctrl->soc_info.dev)), + page, fw_size); + release_firmware(fw); + + return rc; +} + +/** + * cam_ois_pkt_parse - Parse csl packet + * @o_ctrl: ctrl structure + * @arg: Camera control command argument + * + * Returns success or failure + */ +static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) +{ + int32_t rc = 0; + int32_t i = 0; + uint32_t total_cmd_buf_in_bytes = 0; + struct common_header *cmm_hdr = NULL; + uintptr_t generic_ptr; + struct cam_control *ioctl_ctrl = NULL; + struct cam_config_dev_cmd dev_config; + struct i2c_settings_array *i2c_reg_settings = NULL; + 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; + struct cam_ois_soc_private *soc_private = + (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + + ioctl_ctrl = (struct cam_control *)arg; + if (copy_from_user(&dev_config, + u64_to_user_ptr(ioctl_ctrl->handle), + sizeof(dev_config))) + return -EFAULT; + rc = cam_mem_get_cpu_buf(dev_config.packet_handle, + &generic_pkt_addr, &pkt_len); + if (rc) { + CAM_ERR(CAM_OIS, + "error in converting command Handle Error: %d", rc); + return rc; + } + + 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, + "Inval cam_packet strut size: %zu, len_of_buff: %zu", + sizeof(struct cam_packet), pkt_len); + return -EINVAL; + } + + 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"); + return -EINVAL; + } + + + switch (csl_packet->header.op_code & 0xFFFFFF) { + case CAM_OIS_PACKET_OPCODE_INIT: + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + /* Loop through multiple command buffers */ + for (i = 0; i < csl_packet->num_cmd_buf; i++) { + total_cmd_buf_in_bytes = cmd_desc[i].length; + if (!total_cmd_buf_in_bytes) + continue; + + 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 : 0x%x", + cmd_desc[i].mem_handle); + return rc; + } + cmd_buf = (uint32_t *)generic_ptr; + if (!cmd_buf) { + CAM_ERR(CAM_OIS, "invalid cmd buf"); + return -EINVAL; + } + + 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"); + return -EINVAL; + } + 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, remain_len); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed in parsing slave info"); + return rc; + } + break; + case CAMERA_SENSOR_CMD_TYPE_PWR_UP: + case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN: + CAM_DBG(CAM_OIS, + "Received power settings buffer"); + rc = cam_sensor_update_power_settings( + cmd_buf, + total_cmd_buf_in_bytes, + power_info, remain_len); + if (rc) { + CAM_ERR(CAM_OIS, + "Failed: parse power settings"); + return rc; + } + break; + default: + if (o_ctrl->i2c_init_data.is_settings_valid == 0) { + CAM_DBG(CAM_OIS, + "Received init settings"); + i2c_reg_settings = + &(o_ctrl->i2c_init_data); + i2c_reg_settings->is_settings_valid = 1; + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser( + &o_ctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "init parsing failed: %d", rc); + return rc; + } + } else if ((o_ctrl->is_ois_calib != 0) && + (o_ctrl->i2c_calib_data.is_settings_valid == + 0)) { + CAM_DBG(CAM_OIS, + "Received calib settings"); + i2c_reg_settings = &(o_ctrl->i2c_calib_data); + i2c_reg_settings->is_settings_valid = 1; + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser( + &o_ctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Calib parsing failed: %d", rc); + return rc; + } + } + break; + } + } + + 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; + } + o_ctrl->cam_ois_state = CAM_OIS_CONFIG; + } + + if (o_ctrl->ois_fw_flag) { + rc = cam_ois_fw_download(o_ctrl); + if (rc) { + CAM_ERR(CAM_OIS, "Failed OIS FW Download"); + goto pwr_dwn; + } + } + + rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data); + if (rc < 0) { + CAM_ERR(CAM_OIS, "Cannot apply Init settings"); + goto pwr_dwn; + } + + if (o_ctrl->is_ois_calib) { + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_calib_data); + if (rc) { + CAM_ERR(CAM_OIS, "Cannot apply calib data"); + goto pwr_dwn; + } + } + + rc = delete_request(&o_ctrl->i2c_init_data); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting Init data: rc: %d", rc); + rc = 0; + } + rc = delete_request(&o_ctrl->i2c_calib_data); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting Calibration data: rc: %d", rc); + rc = 0; + } + break; + case CAM_OIS_PACKET_OPCODE_OIS_CONTROL: + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_OIS, + "Not in right state to control OIS: %d", + o_ctrl->cam_ois_state); + return rc; + } + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + i2c_reg_settings = &(o_ctrl->i2c_mode_data); + i2c_reg_settings->is_settings_valid = 1; + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); + return rc; + } + + rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, "Cannot apply mode settings"); + return rc; + } + + rc = delete_request(i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Fail deleting Mode data: rc: %d", rc); + return rc; + } + break; + default: + CAM_ERR(CAM_OIS, "Invalid Opcode: %d", + (csl_packet->header.op_code & 0xFFFFFF)); + return -EINVAL; + } + + if (!rc) + return rc; +pwr_dwn: + cam_ois_power_down(o_ctrl); + return rc; +} + +void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl) +{ + int rc = 0; + struct cam_ois_soc_private *soc_private = + (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + + if (o_ctrl->cam_ois_state == CAM_OIS_INIT) + return; + + if (o_ctrl->cam_ois_state >= CAM_OIS_CONFIG) { + rc = cam_ois_power_down(o_ctrl); + if (rc < 0) + CAM_ERR(CAM_OIS, "OIS Power down failed"); + o_ctrl->cam_ois_state = CAM_OIS_ACQUIRE; + } + + if (o_ctrl->cam_ois_state >= CAM_OIS_ACQUIRE) { + rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_OIS, "destroying the device hdl"); + o_ctrl->bridge_intf.device_hdl = -1; + o_ctrl->bridge_intf.link_hdl = -1; + o_ctrl->bridge_intf.session_hdl = -1; + } + + if (o_ctrl->i2c_mode_data.is_settings_valid == 1) + delete_request(&o_ctrl->i2c_mode_data); + + if (o_ctrl->i2c_calib_data.is_settings_valid == 1) + delete_request(&o_ctrl->i2c_calib_data); + + if (o_ctrl->i2c_init_data.is_settings_valid == 1) + delete_request(&o_ctrl->i2c_init_data); + + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_down_setting_size = 0; + power_info->power_setting_size = 0; + + o_ctrl->cam_ois_state = CAM_OIS_INIT; +} + +/** + * cam_ois_driver_cmd - Handle ois cmds + * @e_ctrl: ctrl structure + * @arg: Camera control command argument + * + * Returns success or failure + */ +int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg) +{ + int rc = 0; + struct cam_ois_query_cap_t ois_cap = {0}; + struct cam_control *cmd = (struct cam_control *)arg; + struct cam_ois_soc_private *soc_private = NULL; + struct cam_sensor_power_ctrl_t *power_info = NULL; + + if (!o_ctrl || !cmd) { + CAM_ERR(CAM_OIS, "Invalid arguments"); + return -EINVAL; + } + + if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_OIS, "Invalid handle type: %d", + cmd->handle_type); + return -EINVAL; + } + + soc_private = + (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; + power_info = &soc_private->power_info; + + mutex_lock(&(o_ctrl->ois_mutex)); + switch (cmd->op_code) { + case CAM_QUERY_CAP: + ois_cap.slot_info = o_ctrl->soc_info.index; + + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &ois_cap, + sizeof(struct cam_ois_query_cap_t))) { + CAM_ERR(CAM_OIS, "Failed Copy to User"); + rc = -EFAULT; + goto release_mutex; + } + CAM_DBG(CAM_OIS, "ois_cap: ID: %d", ois_cap.slot_info); + break; + case CAM_ACQUIRE_DEV: + rc = cam_ois_get_dev_handle(o_ctrl, arg); + if (rc) { + CAM_ERR(CAM_OIS, "Failed to acquire dev"); + goto release_mutex; + } + + o_ctrl->cam_ois_state = CAM_OIS_ACQUIRE; + break; + case CAM_START_DEV: + if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_OIS, + "Not in right state for start : %d", + o_ctrl->cam_ois_state); + goto release_mutex; + } + o_ctrl->cam_ois_state = CAM_OIS_START; + break; + case CAM_CONFIG_DEV: + rc = cam_ois_pkt_parse(o_ctrl, arg); + if (rc) { + CAM_ERR(CAM_OIS, "Failed in ois pkt Parsing"); + goto release_mutex; + } + break; + case CAM_RELEASE_DEV: + if (o_ctrl->cam_ois_state == CAM_OIS_START) { + rc = -EINVAL; + CAM_WARN(CAM_OIS, + "Cant release ois: in start state"); + goto release_mutex; + } + + if (o_ctrl->cam_ois_state == CAM_OIS_CONFIG) { + rc = cam_ois_power_down(o_ctrl); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS Power down failed"); + goto release_mutex; + } + } + + if (o_ctrl->bridge_intf.device_hdl == -1) { + CAM_ERR(CAM_OIS, "link hdl: %d device hdl: %d", + o_ctrl->bridge_intf.device_hdl, + o_ctrl->bridge_intf.link_hdl); + rc = -EINVAL; + goto release_mutex; + } + rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_OIS, "destroying the device hdl"); + o_ctrl->bridge_intf.device_hdl = -1; + o_ctrl->bridge_intf.link_hdl = -1; + o_ctrl->bridge_intf.session_hdl = -1; + o_ctrl->cam_ois_state = CAM_OIS_INIT; + + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_down_setting_size = 0; + power_info->power_setting_size = 0; + + if (o_ctrl->i2c_mode_data.is_settings_valid == 1) + delete_request(&o_ctrl->i2c_mode_data); + + if (o_ctrl->i2c_calib_data.is_settings_valid == 1) + delete_request(&o_ctrl->i2c_calib_data); + + if (o_ctrl->i2c_init_data.is_settings_valid == 1) + delete_request(&o_ctrl->i2c_init_data); + + break; + case CAM_STOP_DEV: + if (o_ctrl->cam_ois_state != CAM_OIS_START) { + rc = -EINVAL; + CAM_WARN(CAM_OIS, + "Not in right state for stop : %d", + o_ctrl->cam_ois_state); + } + o_ctrl->cam_ois_state = CAM_OIS_CONFIG; + break; + default: + CAM_ERR(CAM_OIS, "invalid opcode"); + goto release_mutex; + } +release_mutex: + mutex_unlock(&(o_ctrl->ois_mutex)); + return rc; +} diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.h b/drivers/cam_sensor_module/cam_ois/cam_ois_core.h new file mode 100644 index 000000000000..33abe8b75c72 --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_OIS_CORE_H_ +#define _CAM_OIS_CORE_H_ + +#include +#include "cam_ois_dev.h" + +#define OIS_NAME_LEN 32 + +/** + * @power_info: power setting info to control the power + * + * This API construct the default ois power setting. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int32_t cam_ois_construct_default_power_setting( + struct cam_sensor_power_ctrl_t *power_info); + + +int cam_ois_driver_cmd(struct cam_ois_ctrl_t *e_ctrl, void *arg); + +/** + * @o_ctrl: OIS ctrl structure + * + * This API handles the shutdown ioctl/close + */ +void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl); + +#endif +/* _CAM_OIS_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c new file mode 100644 index 000000000000..10044cec6efd --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_ois_dev.h" +#include "cam_req_mgr_dev.h" +#include "cam_ois_soc.h" +#include "cam_ois_core.h" +#include "cam_debug_util.h" + +static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_driver_cmd(o_ctrl, arg); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + +static int cam_ois_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_ois_ctrl_t *o_ctrl = + v4l2_get_subdevdata(sd); + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "o_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(o_ctrl->ois_mutex)); + cam_ois_shutdown(o_ctrl); + mutex_unlock(&(o_ctrl->ois_mutex)); + + return 0; +} + +static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl, + struct cam_ois_i2c_info_t *i2c_info) +{ + struct cam_sensor_cci_client *cci_client = NULL; + + if (o_ctrl->io_master_info.master_type == CCI_MASTER) { + cci_client = o_ctrl->io_master_info.cci_client; + if (!cci_client) { + CAM_ERR(CAM_OIS, "failed: cci_client %pK", + cci_client); + return -EINVAL; + } + cci_client->cci_i2c_master = o_ctrl->cci_i2c_master; + cci_client->sid = (i2c_info->slave_addr) >> 1; + cci_client->retries = 3; + cci_client->id_map = 0; + cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode; + } + + return 0; +} + +#ifdef CONFIG_COMPAT +static long cam_ois_init_subdev_do_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int32_t rc = 0; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_OIS, + "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_subdev_ioctl(sd, cmd, &cmd_data); + if (rc) { + CAM_ERR(CAM_OIS, + "Failed in ois suddev handling rc %d", + rc); + return rc; + } + break; + default: + CAM_ERR(CAM_OIS, "Invalid compat ioctl: %d", cmd); + rc = -EINVAL; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_OIS, + "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + return rc; +} +#endif + +static const struct v4l2_subdev_internal_ops cam_ois_internal_ops = { + .close = cam_ois_subdev_close, +}; + +static struct v4l2_subdev_core_ops cam_ois_subdev_core_ops = { + .ioctl = cam_ois_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_ois_init_subdev_do_ioctl, +#endif +}; + +static struct v4l2_subdev_ops cam_ois_subdev_ops = { + .core = &cam_ois_subdev_core_ops, +}; + +static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl) +{ + int rc = 0; + + o_ctrl->v4l2_dev_str.internal_ops = &cam_ois_internal_ops; + o_ctrl->v4l2_dev_str.ops = &cam_ois_subdev_ops; + strlcpy(o_ctrl->device_name, CAM_OIS_NAME, + sizeof(o_ctrl->device_name)); + o_ctrl->v4l2_dev_str.name = o_ctrl->device_name; + o_ctrl->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE; + o_ctrl->v4l2_dev_str.token = o_ctrl; + + rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str)); + if (rc) + CAM_ERR(CAM_OIS, "fail to create subdev"); + + return rc; +} + +static int cam_ois_i2c_driver_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = NULL; + struct cam_ois_soc_private *soc_private = NULL; + + if (client == NULL || id == NULL) { + CAM_ERR(CAM_OIS, "Invalid Args client: %pK id: %pK", + client, id); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + CAM_ERR(CAM_OIS, "i2c_check_functionality failed"); + goto probe_failure; + } + + o_ctrl = kzalloc(sizeof(*o_ctrl), GFP_KERNEL); + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "kzalloc failed"); + rc = -ENOMEM; + goto probe_failure; + } + + i2c_set_clientdata(client, o_ctrl); + + o_ctrl->soc_info.dev = &client->dev; + o_ctrl->soc_info.dev_name = client->name; + o_ctrl->ois_device_type = MSM_CAMERA_I2C_DEVICE; + o_ctrl->io_master_info.master_type = I2C_MASTER; + o_ctrl->io_master_info.client = client; + + soc_private = kzalloc(sizeof(struct cam_ois_soc_private), + GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto octrl_free; + } + + o_ctrl->soc_info.soc_private = soc_private; + rc = cam_ois_driver_soc_init(o_ctrl); + if (rc) { + CAM_ERR(CAM_OIS, "failed: cam_sensor_parse_dt rc %d", rc); + goto soc_free; + } + + rc = cam_ois_init_subdev_param(o_ctrl); + if (rc) + goto soc_free; + + o_ctrl->cam_ois_state = CAM_OIS_INIT; + + return rc; + +soc_free: + kfree(soc_private); +octrl_free: + kfree(o_ctrl); +probe_failure: + return rc; +} + +static int cam_ois_i2c_driver_remove(struct i2c_client *client) +{ + int i; + struct cam_ois_ctrl_t *o_ctrl = i2c_get_clientdata(client); + struct cam_hw_soc_info *soc_info; + struct cam_ois_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "ois device is NULL"); + 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(o_ctrl->soc_info.soc_private); + v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL); + kfree(o_ctrl); + + return 0; +} + +static int32_t cam_ois_platform_driver_probe( + struct platform_device *pdev) +{ + int32_t rc = 0; + struct cam_ois_ctrl_t *o_ctrl = NULL; + struct cam_ois_soc_private *soc_private = NULL; + + o_ctrl = kzalloc(sizeof(struct cam_ois_ctrl_t), GFP_KERNEL); + if (!o_ctrl) + return -ENOMEM; + + o_ctrl->soc_info.pdev = pdev; + o_ctrl->pdev = pdev; + o_ctrl->soc_info.dev = &pdev->dev; + o_ctrl->soc_info.dev_name = pdev->name; + + o_ctrl->ois_device_type = MSM_CAMERA_PLATFORM_DEVICE; + + o_ctrl->io_master_info.master_type = CCI_MASTER; + o_ctrl->io_master_info.cci_client = kzalloc( + sizeof(struct cam_sensor_cci_client), GFP_KERNEL); + if (!o_ctrl->io_master_info.cci_client) + goto free_o_ctrl; + + soc_private = kzalloc(sizeof(struct cam_ois_soc_private), + GFP_KERNEL); + if (!soc_private) { + rc = -ENOMEM; + goto free_cci_client; + } + o_ctrl->soc_info.soc_private = soc_private; + soc_private->power_info.dev = &pdev->dev; + + INIT_LIST_HEAD(&(o_ctrl->i2c_init_data.list_head)); + INIT_LIST_HEAD(&(o_ctrl->i2c_calib_data.list_head)); + INIT_LIST_HEAD(&(o_ctrl->i2c_mode_data.list_head)); + mutex_init(&(o_ctrl->ois_mutex)); + rc = cam_ois_driver_soc_init(o_ctrl); + if (rc) { + CAM_ERR(CAM_OIS, "failed: soc init rc %d", rc); + goto free_soc; + } + + rc = cam_ois_init_subdev_param(o_ctrl); + if (rc) + goto free_soc; + + rc = cam_ois_update_i2c_info(o_ctrl, &soc_private->i2c_info); + if (rc) { + CAM_ERR(CAM_OIS, "failed: to update i2c info rc %d", rc); + goto unreg_subdev; + } + o_ctrl->bridge_intf.device_hdl = -1; + + platform_set_drvdata(pdev, o_ctrl); + o_ctrl->cam_ois_state = CAM_OIS_INIT; + + return rc; +unreg_subdev: + cam_unregister_subdev(&(o_ctrl->v4l2_dev_str)); +free_soc: + kfree(soc_private); +free_cci_client: + kfree(o_ctrl->io_master_info.cci_client); +free_o_ctrl: + kfree(o_ctrl); + return rc; +} + +static int cam_ois_platform_driver_remove(struct platform_device *pdev) +{ + int i; + struct cam_ois_ctrl_t *o_ctrl; + struct cam_ois_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + struct cam_hw_soc_info *soc_info; + + o_ctrl = platform_get_drvdata(pdev); + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "ois device is NULL"); + 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(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; +} + +static const struct of_device_id cam_ois_dt_match[] = { + { .compatible = "qcom,ois" }, + { } +}; + + +MODULE_DEVICE_TABLE(of, cam_ois_dt_match); + +static struct platform_driver cam_ois_platform_driver = { + .driver = { + .name = "qcom,ois", + .owner = THIS_MODULE, + .of_match_table = cam_ois_dt_match, + }, + .probe = cam_ois_platform_driver_probe, + .remove = cam_ois_platform_driver_remove, +}; +static const struct i2c_device_id cam_ois_i2c_id[] = { + { "msm_ois", (kernel_ulong_t)NULL}, + { } +}; + +static struct i2c_driver cam_ois_i2c_driver = { + .id_table = cam_ois_i2c_id, + .probe = cam_ois_i2c_driver_probe, + .remove = cam_ois_i2c_driver_remove, + .driver = { + .name = "msm_ois", + }, +}; + +static struct cam_ois_registered_driver_t registered_driver = { + 0, 0}; + +static int __init cam_ois_driver_init(void) +{ + int rc = 0; + + rc = platform_driver_register(&cam_ois_platform_driver); + if (rc) { + CAM_ERR(CAM_OIS, "platform_driver_register failed rc = %d", + rc); + return rc; + } + + registered_driver.platform_driver = 1; + + rc = i2c_add_driver(&cam_ois_i2c_driver); + if (rc) { + CAM_ERR(CAM_OIS, "i2c_add_driver failed rc = %d", rc); + return rc; + } + + registered_driver.i2c_driver = 1; + return rc; +} + +static void __exit cam_ois_driver_exit(void) +{ + if (registered_driver.platform_driver) + platform_driver_unregister(&cam_ois_platform_driver); + + if (registered_driver.i2c_driver) + i2c_del_driver(&cam_ois_i2c_driver); +} + +module_init(cam_ois_driver_init); +module_exit(cam_ois_driver_exit); +MODULE_DESCRIPTION("CAM OIS driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h new file mode 100644 index 000000000000..0c2a450fe058 --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_OIS_DEV_H_ +#define _CAM_OIS_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_soc_util.h" + +#define DEFINE_MSM_MUTEX(mutexname) \ + static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) + +enum cam_ois_state { + CAM_OIS_INIT, + CAM_OIS_ACQUIRE, + CAM_OIS_CONFIG, + CAM_OIS_START, +}; + +/** + * struct cam_ois_registered_driver_t - registered driver info + * @platform_driver : flag indicates if platform driver is registered + * @i2c_driver : flag indicates if i2c driver is registered + * + */ +struct cam_ois_registered_driver_t { + bool platform_driver; + bool i2c_driver; +}; + +/** + * struct cam_ois_i2c_info_t - I2C info + * @slave_addr : slave address + * @i2c_freq_mode : i2c frequency mode + * + */ +struct cam_ois_i2c_info_t { + uint16_t slave_addr; + uint8_t i2c_freq_mode; +}; + +/** + * struct cam_ois_soc_private - ois soc private data structure + * @ois_name : ois name + * @i2c_info : i2c info structure + * @power_info : ois power info + * + */ +struct cam_ois_soc_private { + const char *ois_name; + struct cam_ois_i2c_info_t i2c_info; + struct cam_sensor_power_ctrl_t power_info; +}; + +/** + * struct cam_ois_intf_params - bridge interface params + * @device_hdl : Device Handle + * @session_hdl : Session Handle + * @ops : KMD operations + * @crm_cb : Callback API pointers + */ +struct cam_ois_intf_params { + int32_t device_hdl; + int32_t session_hdl; + int32_t link_hdl; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; +}; + +/** + * struct cam_ois_ctrl_t - OIS ctrl private data + * @pdev : platform device + * @ois_mutex : ois mutex + * @soc_info : ois soc related info + * @io_master_info : Information about the communication master + * @cci_i2c_master : I2C structure + * @v4l2_dev_str : V4L2 device structure + * @bridge_intf : bridge interface params + * @i2c_init_data : ois i2c init settings + * @i2c_mode_data : ois i2c mode settings + * @i2c_calib_data : ois i2c calib settings + * @ois_device_type : ois device type + * @cam_ois_state : ois_device_state + * @ois_name : ois name + * @ois_fw_flag : flag for firmware download + * @is_ois_calib : flag for Calibration data + * @opcode : ois opcode + * @device_name : Device name + * + */ +struct cam_ois_ctrl_t { + struct platform_device *pdev; + struct mutex ois_mutex; + struct cam_hw_soc_info soc_info; + struct camera_io_master io_master_info; + enum cci_i2c_master_t cci_i2c_master; + enum cci_device_num cci_num; + struct cam_subdev v4l2_dev_str; + struct cam_ois_intf_params bridge_intf; + struct i2c_settings_array i2c_init_data; + struct i2c_settings_array i2c_calib_data; + struct i2c_settings_array i2c_mode_data; + enum msm_camera_device_type_t ois_device_type; + enum cam_ois_state cam_ois_state; + char device_name[20]; + char ois_name[32]; + uint8_t ois_fw_flag; + uint8_t is_ois_calib; + struct cam_ois_opcode opcode; +}; + +#endif /*_CAM_OIS_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c new file mode 100644 index 000000000000..9c14d87e233d --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "cam_ois_soc.h" +#include "cam_debug_util.h" + +/** + * @e_ctrl: ctrl structure + * + * Parses ois dt + */ +static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl) +{ + int i, rc = 0; + struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info; + struct cam_ois_soc_private *soc_private = + (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; + struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + struct device_node *of_node = NULL; + + of_node = soc_info->dev->of_node; + + if (!of_node) { + CAM_ERR(CAM_OIS, "of_node is NULL, device type %d", + o_ctrl->ois_device_type); + return -EINVAL; + } + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_OIS, "cam_soc_util_get_dt_properties rc %d", + rc); + return rc; + } + + if (!soc_info->gpio_data) { + CAM_INFO(CAM_OIS, "No GPIO found"); + return 0; + } + + if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { + CAM_INFO(CAM_OIS, "No GPIO found"); + return -EINVAL; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &power_info->gpio_num_info); + if ((rc < 0) || (!power_info->gpio_num_info)) { + CAM_ERR(CAM_OIS, "No/Error OIS GPIOs"); + return -EINVAL; + } + + for (i = 0; i < soc_info->num_clk; i++) { + soc_info->clk[i] = devm_clk_get(soc_info->dev, + soc_info->clk_name[i]); + if (!soc_info->clk[i]) { + CAM_ERR(CAM_SENSOR, "get failed for %s", + soc_info->clk_name[i]); + rc = -ENOENT; + return rc; + } + } + + return rc; +} +/** + * @o_ctrl: ctrl structure + * + * This function is called from cam_ois_platform/i2c_driver_probe, it parses + * the ois dt node. + */ +int cam_ois_driver_soc_init(struct cam_ois_ctrl_t *o_ctrl) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info; + struct device_node *of_node = NULL; + struct device_node *of_parent = NULL; + + if (!soc_info->dev) { + CAM_ERR(CAM_OIS, "soc_info is not initialized"); + return -EINVAL; + } + + of_node = soc_info->dev->of_node; + if (!of_node) { + CAM_ERR(CAM_OIS, "dev.of_node NULL"); + return -EINVAL; + } + + if (o_ctrl->ois_device_type == MSM_CAMERA_PLATFORM_DEVICE) { + rc = of_property_read_u32(of_node, "cci-master", + &o_ctrl->cci_i2c_master); + if (rc < 0) { + CAM_DBG(CAM_OIS, "failed rc %d", rc); + return rc; + } + + of_parent = of_get_parent(of_node); + if (of_property_read_u32(of_parent, "cell-index", + &o_ctrl->cci_num) < 0) + /* Set default master 0 */ + o_ctrl->cci_num = CCI_DEVICE_0; + + o_ctrl->io_master_info.cci_client->cci_device = o_ctrl->cci_num; + CAM_DBG(CAM_OIS, "cci-device %d", o_ctrl->cci_num, rc); + + } + + rc = cam_ois_get_dt_data(o_ctrl); + if (rc < 0) + CAM_DBG(CAM_OIS, "failed: ois get dt data rc %d", rc); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.h b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.h new file mode 100644 index 000000000000..fd2c209c7504 --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ +#ifndef _CAM_OIS_SOC_H_ +#define _CAM_OIS_SOC_H_ + +#include "cam_ois_dev.h" + +int cam_ois_driver_soc_init(struct cam_ois_ctrl_t *o_ctrl); + +#endif/* _CAM_OIS_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_res_mgr/Makefile b/drivers/cam_sensor_module/cam_res_mgr/Makefile new file mode 100644 index 000000000000..5bc9889b40e9 --- /dev/null +++ b/drivers/cam_sensor_module/cam_res_mgr/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +#ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_res_mgr.o diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c new file mode 100644 index 000000000000..c87540f7950f --- /dev/null +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -0,0 +1,739 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "cam_debug_util.h" +#include "cam_res_mgr_api.h" +#include "cam_res_mgr_private.h" + +static struct cam_res_mgr *cam_res; + +static void cam_res_mgr_free_res(void) +{ + struct cam_dev_res *dev_res, *dev_temp; + struct cam_gpio_res *gpio_res, *gpio_temp; + struct cam_flash_res *flash_res, *flash_temp; + + if (!cam_res) + return; + + mutex_lock(&cam_res->gpio_res_lock); + list_for_each_entry_safe(gpio_res, gpio_temp, + &cam_res->gpio_res_list, list) { + list_for_each_entry_safe(dev_res, dev_temp, + &gpio_res->dev_list, list) { + list_del_init(&dev_res->list); + kfree(dev_res); + } + list_del_init(&gpio_res->list); + kfree(gpio_res); + } + mutex_unlock(&cam_res->gpio_res_lock); + + mutex_lock(&cam_res->flash_res_lock); + list_for_each_entry_safe(flash_res, flash_temp, + &cam_res->flash_res_list, list) { + list_del_init(&flash_res->list); + kfree(flash_res); + } + mutex_unlock(&cam_res->flash_res_lock); + + mutex_lock(&cam_res->clk_res_lock); + cam_res->shared_clk_ref_count = 0; + mutex_unlock(&cam_res->clk_res_lock); +} + +void cam_res_mgr_led_trigger_register(const char *name, struct led_trigger **tp) +{ + bool found = false; + struct cam_flash_res *flash_res; + + if (!cam_res) { + /* + * If this driver not probed, then just register the + * led trigger. + */ + led_trigger_register_simple(name, tp); + return; + } + + mutex_lock(&cam_res->flash_res_lock); + list_for_each_entry(flash_res, &cam_res->flash_res_list, list) { + if (!strcmp(flash_res->name, name)) { + found = true; + break; + } + } + mutex_unlock(&cam_res->flash_res_lock); + + if (found) { + *tp = flash_res->trigger; + } else { + flash_res = kzalloc(sizeof(struct cam_flash_res), GFP_KERNEL); + if (!flash_res) { + CAM_ERR(CAM_RES, + "Failed to malloc memory for flash_res:%s", + name); + *tp = NULL; + return; + } + + led_trigger_register_simple(name, tp); + INIT_LIST_HEAD(&flash_res->list); + flash_res->trigger = *tp; + flash_res->name = name; + + mutex_lock(&cam_res->flash_res_lock); + list_add_tail(&flash_res->list, &cam_res->flash_res_list); + mutex_unlock(&cam_res->flash_res_lock); + } +} +EXPORT_SYMBOL(cam_res_mgr_led_trigger_register); + +void cam_res_mgr_led_trigger_unregister(struct led_trigger *tp) +{ + bool found = false; + struct cam_flash_res *flash_res; + + if (!cam_res) { + /* + * If this driver not probed, then just unregister the + * led trigger. + */ + led_trigger_unregister_simple(tp); + return; + } + + mutex_lock(&cam_res->flash_res_lock); + list_for_each_entry(flash_res, &cam_res->flash_res_list, list) { + if (flash_res->trigger == tp) { + found = true; + break; + } + } + + if (found) { + led_trigger_unregister_simple(tp); + list_del_init(&flash_res->list); + kfree(flash_res); + } + mutex_unlock(&cam_res->flash_res_lock); +} +EXPORT_SYMBOL(cam_res_mgr_led_trigger_unregister); + +void cam_res_mgr_led_trigger_event(struct led_trigger *trig, + enum led_brightness brightness) +{ + bool found = false; + struct cam_flash_res *flash_res; + + if (!cam_res) { + /* + * If this driver not probed, then just trigger + * the led event. + */ + led_trigger_event(trig, brightness); + return; + } + + mutex_lock(&cam_res->flash_res_lock); + list_for_each_entry(flash_res, &cam_res->flash_res_list, list) { + if (flash_res->trigger == trig) { + found = true; + break; + } + } + mutex_unlock(&cam_res->flash_res_lock); + + if (found) + led_trigger_event(trig, brightness); +} +EXPORT_SYMBOL(cam_res_mgr_led_trigger_event); + +int cam_res_mgr_shared_pinctrl_init(void) +{ + struct cam_soc_pinctrl_info *pinctrl_info; + + /* + * We allow the cam_res is NULL or shared_gpio_enabled + * is false, it means this driver no probed or doesn't + * have shared gpio in this device. + */ + if (!cam_res || !cam_res->shared_gpio_enabled) { + CAM_DBG(CAM_RES, "Not support shared gpio."); + 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; + } + + pinctrl_info = &cam_res->dt.pinctrl_info; + + pinctrl_info->pinctrl = + devm_pinctrl_get(cam_res->dev); + 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; + } + + pinctrl_info->gpio_state_active = + pinctrl_lookup_state(pinctrl_info->pinctrl, + CAM_RES_MGR_DEFAULT); + if (IS_ERR_OR_NULL(pinctrl_info->gpio_state_active)) { + 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; + } + + pinctrl_info->gpio_state_suspend = + pinctrl_lookup_state(pinctrl_info->pinctrl, + CAM_RES_MGR_SLEEP); + if (IS_ERR_OR_NULL(pinctrl_info->gpio_state_suspend)) { + 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; + } + + cam_res->pstatus = PINCTRL_STATUS_GOT; + mutex_unlock(&cam_res->gpio_res_lock); + + return 0; +} +EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_init); + +static bool cam_res_mgr_shared_pinctrl_check_hold(void) +{ + int index = 0; + int dev_num = 0; + bool hold = false; + struct list_head *list; + struct cam_gpio_res *gpio_res; + struct cam_res_mgr_dt *dt = &cam_res->dt; + + for (; index < dt->num_shared_gpio; index++) { + list_for_each_entry(gpio_res, + &cam_res->gpio_res_list, list) { + + if (gpio_res->gpio == + dt->shared_gpio[index]) { + list_for_each(list, &gpio_res->dev_list) + dev_num++; + + if (dev_num >= 2) { + hold = true; + break; + } + } + } + } + + if (cam_res->shared_clk_ref_count > 1) + hold = true; + + return hold; +} + +void cam_res_mgr_shared_pinctrl_put(void) +{ + struct cam_soc_pinctrl_info *pinctrl_info; + + if (!cam_res || !cam_res->shared_gpio_enabled) { + CAM_DBG(CAM_RES, "Not support shared gpio."); + return; + } + + mutex_lock(&cam_res->gpio_res_lock); + if (cam_res->pstatus == PINCTRL_STATUS_PUT) { + CAM_DBG(CAM_RES, "The shared pinctrl already been put"); + mutex_unlock(&cam_res->gpio_res_lock); + return; + } + + if (cam_res_mgr_shared_pinctrl_check_hold()) { + CAM_INFO(CAM_RES, "Need hold put this pinctrl"); + mutex_unlock(&cam_res->gpio_res_lock); + return; + } + + pinctrl_info = &cam_res->dt.pinctrl_info; + + devm_pinctrl_put(pinctrl_info->pinctrl); + + cam_res->pstatus = PINCTRL_STATUS_PUT; + mutex_unlock(&cam_res->gpio_res_lock); +} +EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_put); + +int cam_res_mgr_shared_pinctrl_select_state(bool active) +{ + int rc = 0; + struct cam_soc_pinctrl_info *pinctrl_info; + + if (!cam_res || !cam_res->shared_gpio_enabled) { + CAM_DBG(CAM_RES, "Not support shared gpio."); + return 0; + } + + mutex_lock(&cam_res->gpio_res_lock); + if (cam_res->pstatus == PINCTRL_STATUS_PUT) { + CAM_DBG(CAM_RES, "The shared pinctrl alerady been put.!"); + mutex_unlock(&cam_res->gpio_res_lock); + return 0; + } + + pinctrl_info = &cam_res->dt.pinctrl_info; + + if (active && (cam_res->pstatus != PINCTRL_STATUS_ACTIVE)) { + rc = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->gpio_state_active); + cam_res->pstatus = PINCTRL_STATUS_ACTIVE; + } else if (!active && + !cam_res_mgr_shared_pinctrl_check_hold()) { + rc = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->gpio_state_suspend); + cam_res->pstatus = PINCTRL_STATUS_SUSPEND; + } + + mutex_unlock(&cam_res->gpio_res_lock); + + return rc; +} +EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_select_state); + +int cam_res_mgr_shared_pinctrl_post_init(void) +{ + int ret = 0; + struct cam_soc_pinctrl_info *pinctrl_info; + + if (!cam_res || !cam_res->shared_gpio_enabled) { + CAM_DBG(CAM_RES, "Not support shared gpio."); + return ret; + } + + mutex_lock(&cam_res->gpio_res_lock); + if (cam_res->pstatus == PINCTRL_STATUS_PUT) { + CAM_DBG(CAM_RES, "The shared pinctrl alerady been put.!"); + mutex_unlock(&cam_res->gpio_res_lock); + return ret; + } + + pinctrl_info = &cam_res->dt.pinctrl_info; + + /* + * If no gpio resource in gpio_res_list, and + * no shared clk now, it means this device + * don't have shared gpio. + */ + if (list_empty(&cam_res->gpio_res_list) && + cam_res->shared_clk_ref_count < 1) { + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->gpio_state_suspend); + devm_pinctrl_put(pinctrl_info->pinctrl); + cam_res->pstatus = PINCTRL_STATUS_PUT; + } + mutex_unlock(&cam_res->gpio_res_lock); + + return ret; +} +EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_post_init); + +static int cam_res_mgr_add_device(struct device *dev, + struct cam_gpio_res *gpio_res) +{ + struct cam_dev_res *dev_res = NULL; + + dev_res = kzalloc(sizeof(struct cam_dev_res), GFP_KERNEL); + if (!dev_res) + return -ENOMEM; + + dev_res->dev = dev; + INIT_LIST_HEAD(&dev_res->list); + + list_add_tail(&dev_res->list, &gpio_res->dev_list); + + return 0; +} + +static bool cam_res_mgr_gpio_is_shared(uint gpio) +{ + int index = 0; + 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; +} + +int cam_res_mgr_gpio_request(struct device *dev, uint gpio, + unsigned long flags, const char *label) +{ + int rc = 0; + bool found = false; + struct cam_gpio_res *gpio_res = NULL; + + if (cam_res && cam_res->shared_gpio_enabled) { + mutex_lock(&cam_res->gpio_res_lock); + list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { + if (gpio == gpio_res->gpio) { + found = true; + break; + } + } + mutex_unlock(&cam_res->gpio_res_lock); + } + + /* + * found equal to false has two situation: + * 1. shared gpio not enabled + * 2. shared gpio enabled, but not find this gpio + * from the gpio_res_list + * These two situation both need request gpio. + */ + if (!found) { + rc = gpio_request_one(gpio, flags, label); + if (rc) { + CAM_ERR(CAM_RES, "gpio %d:%s request fails", + gpio, label); + return rc; + } + } + + /* + * If the gpio is in the shared list, and not find + * from gpio_res_list, then insert a cam_gpio_res + * to gpio_res_list. + */ + if (!found && cam_res + && cam_res->shared_gpio_enabled && + cam_res_mgr_gpio_is_shared(gpio)) { + + gpio_res = kzalloc(sizeof(struct cam_gpio_res), GFP_KERNEL); + if (!gpio_res) + return -ENOMEM; + + gpio_res->gpio = gpio; + gpio_res->power_on_count = 0; + 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; + } + + list_add_tail(&gpio_res->list, &cam_res->gpio_res_list); + mutex_unlock(&cam_res->gpio_res_lock); + } + + if (found && cam_res + && cam_res->shared_gpio_enabled) { + struct cam_dev_res *dev_res = NULL; + + found = 0; + mutex_lock(&cam_res->gpio_res_lock); + list_for_each_entry(dev_res, &gpio_res->dev_list, list) { + if (dev_res->dev == dev) { + found = 1; + break; + } + } + + if (!found) + rc = cam_res_mgr_add_device(dev, gpio_res); + + mutex_unlock(&cam_res->gpio_res_lock); + } + + return rc; +} +EXPORT_SYMBOL(cam_res_mgr_gpio_request); + +static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) +{ + bool found = false; + bool need_free = true; + int dev_num = 0; + struct cam_gpio_res *gpio_res = NULL; + + if (cam_res && cam_res->shared_gpio_enabled) { + mutex_lock(&cam_res->gpio_res_lock); + list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { + if (gpio == gpio_res->gpio) { + found = true; + break; + } + } + mutex_unlock(&cam_res->gpio_res_lock); + } + + if (found && cam_res + && cam_res->shared_gpio_enabled) { + struct list_head *list; + struct cam_dev_res *dev_res = NULL; + + mutex_lock(&cam_res->gpio_res_lock); + /* Count the dev number in the dev_list */ + list_for_each(list, &gpio_res->dev_list) + dev_num++; + + /* + * Need free the gpio if only has last 1 device + * in the dev_list, otherwise, not free this + * gpio. + */ + if (dev_num == 1) { + dev_res = list_first_entry(&gpio_res->dev_list, + struct cam_dev_res, list); + list_del_init(&dev_res->list); + kfree(dev_res); + + list_del_init(&gpio_res->list); + kfree(gpio_res); + } else { + list_for_each_entry(dev_res, + &gpio_res->dev_list, list) { + if (dev_res->dev == dev) { + list_del_init(&dev_res->list); + kfree(dev_res); + need_free = false; + break; + } + } + } + mutex_unlock(&cam_res->gpio_res_lock); + } + + if (need_free) + gpio_free(gpio); +} + +void cam_res_mgr_gpio_free_arry(struct device *dev, + const struct gpio *array, size_t num) +{ + while (num--) + cam_res_mgr_gpio_free(dev, (array[num]).gpio); +} +EXPORT_SYMBOL(cam_res_mgr_gpio_free_arry); + +int cam_res_mgr_gpio_set_value(unsigned int gpio, int value) +{ + int rc = 0; + bool found = false; + struct cam_gpio_res *gpio_res = NULL; + + if (cam_res && cam_res->shared_gpio_enabled) { + mutex_lock(&cam_res->gpio_res_lock); + list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { + if (gpio == gpio_res->gpio) { + found = true; + break; + } + } + mutex_unlock(&cam_res->gpio_res_lock); + } + + /* + * Set the value directly if can't find the gpio from + * gpio_res_list, otherwise, need add ref count support + **/ + if (!found) { + gpio_set_value_cansleep(gpio, value); + } else { + if (value) { + gpio_res->power_on_count++; + if (gpio_res->power_on_count < 2) { + gpio_set_value_cansleep(gpio, value); + CAM_DBG(CAM_RES, + "Shared GPIO(%d) : HIGH", gpio); + } + } else { + gpio_res->power_on_count--; + if (gpio_res->power_on_count < 1) { + gpio_set_value_cansleep(gpio, value); + CAM_DBG(CAM_RES, + "Shared GPIO(%d) : LOW", gpio); + } + } + } + + return rc; +} +EXPORT_SYMBOL(cam_res_mgr_gpio_set_value); + +void cam_res_mgr_shared_clk_config(bool value) +{ + if (!cam_res) + return; + + mutex_lock(&cam_res->clk_res_lock); + if (value) + cam_res->shared_clk_ref_count++; + else + cam_res->shared_clk_ref_count--; + mutex_unlock(&cam_res->clk_res_lock); +} +EXPORT_SYMBOL(cam_res_mgr_shared_clk_config); + +static int cam_res_mgr_parse_dt(struct device *dev) +{ + int rc = 0; + struct device_node *of_node = NULL; + struct cam_res_mgr_dt *dt = &cam_res->dt; + + of_node = dev->of_node; + + dt->num_shared_gpio = of_property_count_u32_elems(of_node, + "shared-gpios"); + + if (dt->num_shared_gpio > MAX_SHARED_GPIO_SIZE || + dt->num_shared_gpio <= 0) { + /* + * Not really an error, it means dtsi not configure + * the shared gpio. + */ + CAM_DBG(CAM_RES, "Invalid GPIO number %d. No shared gpio.", + dt->num_shared_gpio); + return -EINVAL; + } + + rc = of_property_read_u32_array(of_node, "shared-gpios", + dt->shared_gpio, dt->num_shared_gpio); + if (rc) { + CAM_ERR(CAM_RES, "Get shared gpio array failed."); + return -EINVAL; + } + + dt->pinctrl_info.pinctrl = devm_pinctrl_get(dev); + if (IS_ERR_OR_NULL(dt->pinctrl_info.pinctrl)) { + CAM_ERR(CAM_RES, "Pinctrl not available"); + return -EINVAL; + } + + /* + * Check the pinctrl state to make sure the gpio + * shared enabled. + */ + dt->pinctrl_info.gpio_state_active = + pinctrl_lookup_state(dt->pinctrl_info.pinctrl, + CAM_RES_MGR_DEFAULT); + if (IS_ERR_OR_NULL(dt->pinctrl_info.gpio_state_active)) { + CAM_ERR(CAM_RES, + "Failed to get the active state pinctrl handle"); + return -EINVAL; + } + + dt->pinctrl_info.gpio_state_suspend = + pinctrl_lookup_state(dt->pinctrl_info.pinctrl, + CAM_RES_MGR_SLEEP); + if (IS_ERR_OR_NULL(dt->pinctrl_info.gpio_state_suspend)) { + CAM_ERR(CAM_RES, + "Failed to get the active state pinctrl handle"); + return -EINVAL; + } + + devm_pinctrl_put(dt->pinctrl_info.pinctrl); + + return rc; +} + +static int cam_res_mgr_probe(struct platform_device *pdev) +{ + int rc = 0; + + cam_res = kzalloc(sizeof(*cam_res), GFP_KERNEL); + if (!cam_res) + return -ENOMEM; + + cam_res->dev = &pdev->dev; + mutex_init(&cam_res->flash_res_lock); + mutex_init(&cam_res->gpio_res_lock); + mutex_init(&cam_res->clk_res_lock); + + rc = cam_res_mgr_parse_dt(&pdev->dev); + if (rc) { + CAM_INFO(CAM_RES, "Disable shared gpio support."); + cam_res->shared_gpio_enabled = false; + } else { + CAM_INFO(CAM_RES, "Enable shared gpio support."); + cam_res->shared_gpio_enabled = true; + } + + cam_res->shared_clk_ref_count = 0; + cam_res->pstatus = PINCTRL_STATUS_PUT; + + INIT_LIST_HEAD(&cam_res->gpio_res_list); + INIT_LIST_HEAD(&cam_res->flash_res_list); + + return 0; +} + +static int cam_res_mgr_remove(struct platform_device *pdev) +{ + if (cam_res) { + cam_res_mgr_free_res(); + kfree(cam_res); + cam_res = NULL; + } + + return 0; +} + +static const struct of_device_id cam_res_mgr_dt_match[] = { + {.compatible = "qcom,cam-res-mgr"}, + {} +}; +MODULE_DEVICE_TABLE(of, cam_res_mgr_dt_match); + +static struct platform_driver cam_res_mgr_driver = { + .probe = cam_res_mgr_probe, + .remove = cam_res_mgr_remove, + .driver = { + .name = "cam_res_mgr", + .owner = THIS_MODULE, + .of_match_table = cam_res_mgr_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_res_mgr_init(void) +{ + return platform_driver_register(&cam_res_mgr_driver); +} + +static void __exit cam_res_mgr_exit(void) +{ + platform_driver_unregister(&cam_res_mgr_driver); +} + +module_init(cam_res_mgr_init); +module_exit(cam_res_mgr_exit); +MODULE_DESCRIPTION("Camera resource manager driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h new file mode 100644 index 000000000000..e259ba7f2c78 --- /dev/null +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __CAM_RES_MGR_API_H__ +#define __CAM_RES_MGR_API_H__ + +#include + +/** + * @brief: Register the led trigger + * + * The newly registered led trigger is assigned to flash_res_list. + * + * @name : Pointer to int led trigger name + * @tp : Save the returned led trigger + * + * @return None + */ +void cam_res_mgr_led_trigger_register(const char *name, + struct led_trigger **tp); + +/** + * @brief: Unregister the led trigger + * + * Free the flash_res if this led trigger isn't used by other device . + * + * @tp : Pointer to the led trigger + * + * @return None + */ +void cam_res_mgr_led_trigger_unregister(struct led_trigger *tp); + +/** + * @brief: Trigger the event to led core + * + * @trig : Pointer to the led trigger + * @brightness : The brightness need to fire + * + * @return None + */ +void cam_res_mgr_led_trigger_event(struct led_trigger *trig, + enum led_brightness brightness); + +/** + * @brief: Get the corresponding pinctrl of dev + * + * Init the shared pinctrl if shared pinctrl enabled. + * + * @return None + */ +int cam_res_mgr_shared_pinctrl_init(void); + +/** + * @brief: Put the pinctrl + * + * Put the shared pinctrl. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +void cam_res_mgr_shared_pinctrl_put(void); + +/** + * @brief: Select the corresponding state + * + * Active state can be selected directly, but need hold to suspend the + * pinctrl if the gpios in this pinctrl also held by other pinctrl. + * + * @active : The flag to indicate whether active or suspend + * the shared pinctrl. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_res_mgr_shared_pinctrl_select_state(bool active); + +/** + * @brief: Post init shared pinctrl + * + * Post init to check if the device really has shared gpio, + * suspend and put the pinctrl if not use shared gpio. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_res_mgr_shared_pinctrl_post_init(void); + +/** + * @brief: Request a gpio + * + * Will alloc a gpio_res for the new gpio, other find the corresponding + * gpio_res. + * + * @dev : Pointer to the device + * @gpio : The GPIO number + * @flags : GPIO configuration as specified by GPIOF_* + * @label : A literal description string of this GPIO + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_res_mgr_gpio_request(struct device *dev, unsigned int gpio, + unsigned long flags, const char *label); + +/** + * @brief: Free a array GPIO + * + * Free the GPIOs and release corresponding gpio_res. + * + * @dev : Pointer to the device + * @gpio : Array of the GPIO number + * @num : The number of gpio + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +void cam_res_mgr_gpio_free_arry(struct device *dev, + const struct gpio *array, size_t num); + +/** + * @brief: Set GPIO power level + * + * Add ref count support for shared GPIOs. + * + * @gpio : The GPIO number + * @value : The power level need to setup + * + * @return Status of operation. Negative in case of error. Zero otherwise. + * -EINVAL will be returned if the gpio can't be found in gpio_res_list. + */ +int cam_res_mgr_gpio_set_value(unsigned int gpio, int value); + +/** + * @brief: Config the shared clk ref count + * + * Config the shared clk ref count.. + * + * @value : get or put the shared clk. + * + * @return None + */ +void cam_res_mgr_shared_clk_config(bool value); + +#endif /* __CAM_RES_MGR_API_H__ */ diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h new file mode 100644 index 000000000000..48611f6fbd7e --- /dev/null +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __CAM_RES_MGR_PRIVATE_H__ +#define __CAM_RES_MGR_PRIVATE_H__ + +#include +#include +#include "cam_soc_util.h" + +#define MAX_SHARED_GPIO_SIZE 16 + +/* pinctrl states name */ +#define CAM_RES_MGR_SLEEP "cam_res_mgr_suspend" +#define CAM_RES_MGR_DEFAULT "cam_res_mgr_default" + +/** + * enum pinctrl_status - Enum for pinctrl status + */ +enum pinctrl_status { + PINCTRL_STATUS_GOT = 0, + PINCTRL_STATUS_ACTIVE, + PINCTRL_STATUS_SUSPEND, + PINCTRL_STATUS_PUT, +}; + +/** + * struct cam_dev_res + * + * @list : List member used to append this node to a dev list + * @dev : Device pointer associated with device + */ +struct cam_dev_res { + struct list_head list; + struct device *dev; +}; + +/** + * struct cam_gpio_res + * + * @list : List member used to append this node to a gpio list + * @dev_list : List the device which request this gpio + * @gpio : Gpio value + * @power_on_count : Record the power on times of this gpio + */ +struct cam_gpio_res { + struct list_head list; + struct list_head dev_list; + unsigned int gpio; + int power_on_count; +}; + +/** + * struct cam_pinctrl_res + * + * @list : List member used to append this node to a linked list + * @name : Pointer to the flash trigger's name. + * @trigger : Pointer to the flash trigger + */ +struct cam_flash_res { + struct list_head list; + const char *name; + struct led_trigger *trigger; +}; + +/** + * struct cam_res_mgr_dt + * + * @shared_gpio : Shared gpios list in the device tree + * @num_shared_gpio : The number of shared gpio + * @pinctrl_info : Pinctrl information + */ +struct cam_res_mgr_dt { + uint shared_gpio[MAX_SHARED_GPIO_SIZE]; + int num_shared_gpio; + struct cam_soc_pinctrl_info pinctrl_info; +}; + +/** + * struct cam_pinctrl_res + * + * @dev : Pointer to the device + * @dt : Device tree resource + * @shared_gpio_enabled : The flag to indicate if support shared gpio + * @pstatus : Shared pinctrl status + * @gpio_res_list : List head of the gpio resource + * @flash_res_list : List head of the flash resource + * @gpio_res_lock : GPIO resource lock + * @flash_res_lock : Flash resource lock + * @clk_res_lock : Clk resource lock + */ +struct cam_res_mgr { + struct device *dev; + struct cam_res_mgr_dt dt; + + bool shared_gpio_enabled; + enum pinctrl_status pstatus; + + uint shared_clk_ref_count; + + struct list_head gpio_res_list; + struct list_head flash_res_list; + struct mutex gpio_res_lock; + struct mutex flash_res_lock; + struct mutex clk_res_lock; +}; + +#endif /* __CAM_RES_MGR_PRIVATE_H__ */ diff --git a/drivers/cam_sensor_module/cam_sensor/Makefile b/drivers/cam_sensor_module/cam_sensor/Makefile new file mode 100644 index 000000000000..641b1c490329 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_dev.o cam_sensor_core.o cam_sensor_soc.o diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c new file mode 100644 index 000000000000..680cf4f302bc --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -0,0 +1,1325 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "cam_sensor_core.h" +#include "cam_sensor_util.h" +#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, + struct cam_packet *csl_packet) +{ + struct cam_req_mgr_add_request add_req; + + add_req.link_hdl = s_ctrl->bridge_intf.link_hdl; + add_req.req_id = csl_packet->header.request_id; + CAM_DBG(CAM_SENSOR, " Rxed Req Id: %lld", + csl_packet->header.request_id); + add_req.dev_hdl = s_ctrl->bridge_intf.device_hdl; + add_req.skip_before_applying = 0; + if (s_ctrl->bridge_intf.crm_cb && + s_ctrl->bridge_intf.crm_cb->add_req) + s_ctrl->bridge_intf.crm_cb->add_req(&add_req); + + CAM_DBG(CAM_SENSOR, " add req to req mgr: %lld", + add_req.req_id); +} + +static void cam_sensor_release_stream_rsc( + struct cam_sensor_ctrl_t *s_ctrl) +{ + struct i2c_settings_array *i2c_set = NULL; + int rc; + + i2c_set = &(s_ctrl->i2c_data.streamoff_settings); + if (i2c_set->is_settings_valid == 1) { + i2c_set->is_settings_valid = -1; + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "failed while deleting Streamoff settings"); + } + + i2c_set = &(s_ctrl->i2c_data.streamon_settings); + if (i2c_set->is_settings_valid == 1) { + i2c_set->is_settings_valid = -1; + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "failed while deleting Streamon settings"); + } +} + +static void cam_sensor_release_per_frame_resource( + struct cam_sensor_ctrl_t *s_ctrl) +{ + struct i2c_settings_array *i2c_set = NULL; + int i, rc; + + if (s_ctrl->i2c_data.per_frame != NULL) { + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(s_ctrl->i2c_data.per_frame[i]); + if (i2c_set->is_settings_valid == 1) { + i2c_set->is_settings_valid = -1; + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + } + } + } +} + +static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, + void *arg) +{ + int32_t rc = 0; + uintptr_t generic_ptr; + struct cam_control *ioctl_ctrl = NULL; + struct cam_packet *csl_packet = NULL; + 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; + + ioctl_ctrl = (struct cam_control *)arg; + + if (ioctl_ctrl->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_SENSOR, "Invalid Handle Type"); + return -EINVAL; + } + + if (copy_from_user(&config, + u64_to_user_ptr(ioctl_ctrl->handle), + sizeof(config))) + return -EFAULT; + + rc = cam_mem_get_cpu_buf( + config.packet_handle, + &generic_ptr, + &len_of_buff); + if (rc < 0) { + 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 end; + } + + remain_len -= (size_t)config.offset; + csl_packet = (struct cam_packet *)(generic_ptr + + (uint32_t)config.offset); + + if (cam_packet_util_validate_packet(csl_packet, + remain_len)) { + CAM_ERR(CAM_SENSOR, "Invalid packet params"); + rc = -EINVAL; + goto end; + + } + + 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_ERR(CAM_SENSOR, + "reject request %lld, last request to flush %u", + csl_packet->header.request_id, s_ctrl->last_flush_req); + rc = -EINVAL; + goto end; + } + + if (csl_packet->header.request_id > s_ctrl->last_flush_req) + s_ctrl->last_flush_req = 0; + + i2c_data = &(s_ctrl->i2c_data); + CAM_DBG(CAM_SENSOR, "Header OpCode: %d", csl_packet->header.op_code); + switch (csl_packet->header.op_code & 0xFFFFFF) { + case CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG: { + i2c_reg_settings = &i2c_data->init_settings; + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG: { + i2c_reg_settings = &i2c_data->config_settings; + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON: { + if (s_ctrl->streamon_count > 0) + goto end; + + s_ctrl->streamon_count = s_ctrl->streamon_count + 1; + i2c_reg_settings = &i2c_data->streamon_settings; + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF: { + if (s_ctrl->streamoff_count > 0) + goto end; + + s_ctrl->streamoff_count = s_ctrl->streamoff_count + 1; + i2c_reg_settings = &i2c_data->streamoff_settings; + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + break; + } + + case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: { + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || + (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { + CAM_WARN(CAM_SENSOR, + "Rxed Update packets without linking"); + goto end; + } + + i2c_reg_settings = + &i2c_data->per_frame[csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY]; + CAM_DBG(CAM_SENSOR, "Received Packet: %lld req: %lld", + csl_packet->header.request_id % MAX_PER_FRAME_ARRAY, + csl_packet->header.request_id); + if (i2c_reg_settings->is_settings_valid == 1) { + CAM_ERR(CAM_SENSOR, + "Already some pkt in offset req : %lld", + csl_packet->header.request_id); + /* + * Update req mgr even in case of failure. + * This will help not to wait indefinitely + * and freeze. If this log is triggered then + * fix it. + */ + cam_sensor_update_req_mgr(s_ctrl, csl_packet); + goto end; + } + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: { + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || + (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { + CAM_WARN(CAM_SENSOR, + "Rxed NOP packets without linking"); + goto end; + } + + cam_sensor_update_req_mgr(s_ctrl, csl_packet); + goto end; + } + default: + CAM_ERR(CAM_SENSOR, "Invalid Packet Header"); + rc = -EINVAL; + goto end; + } + + offset = (uint32_t *)&csl_packet->payload; + offset += csl_packet->cmd_buf_offset / 4; + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + rc = cam_sensor_i2c_command_parser(&s_ctrl->io_master_info, + i2c_reg_settings, cmd_desc, 1); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc); + goto end; + } + + if ((csl_packet->header.op_code & 0xFFFFFF) == + CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE) { + i2c_reg_settings->request_id = + csl_packet->header.request_id; + cam_sensor_update_req_mgr(s_ctrl, csl_packet); + } + +end: + return rc; +} + +static int32_t cam_sensor_i2c_modes_util( + struct camera_io_master *io_master_info, + struct i2c_settings_list *i2c_list) +{ + int32_t rc = 0; + uint32_t i, size; + + if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) { + rc = camera_io_dev_write(io_master_info, + &(i2c_list->i2c_settings)); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to random write I2C settings: %d", + rc); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + rc = camera_io_dev_write_continuous( + io_master_info, + &(i2c_list->i2c_settings), + 0); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to seq write I2C settings: %d", + rc); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_BURST) { + rc = camera_io_dev_write_continuous( + io_master_info, + &(i2c_list->i2c_settings), + 1); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to burst write I2C settings: %d", + rc); + return rc; + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { + size = i2c_list->i2c_settings.size; + for (i = 0; i < size; i++) { + rc = camera_io_dev_poll( + io_master_info, + i2c_list->i2c_settings.reg_setting[i].reg_addr, + i2c_list->i2c_settings.reg_setting[i].reg_data, + i2c_list->i2c_settings.reg_setting[i].data_mask, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.reg_setting[i].delay); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "i2c poll apply setting Fail: %d", rc); + return rc; + } + } + } + + return rc; +} + +int32_t cam_sensor_update_i2c_info(struct cam_cmd_i2c_info *i2c_info, + struct cam_sensor_ctrl_t *s_ctrl) +{ + int32_t rc = 0; + struct cam_sensor_cci_client *cci_client = NULL; + + if (s_ctrl->io_master_info.master_type == CCI_MASTER) { + cci_client = s_ctrl->io_master_info.cci_client; + if (!cci_client) { + CAM_ERR(CAM_SENSOR, "failed: cci_client %pK", + cci_client); + return -EINVAL; + } + cci_client->cci_i2c_master = s_ctrl->cci_i2c_master; + cci_client->sid = i2c_info->slave_addr >> 1; + cci_client->retries = 3; + cci_client->id_map = 0; + cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode; + CAM_DBG(CAM_SENSOR, " Master: %d sid: %d freq_mode: %d", + cci_client->cci_i2c_master, i2c_info->slave_addr, + i2c_info->i2c_freq_mode); + } + + s_ctrl->sensordata->slave_info.sensor_slave_addr = + i2c_info->slave_addr; + return rc; +} + +int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info, + struct cam_sensor_ctrl_t *s_ctrl) +{ + int32_t rc = 0; + + s_ctrl->sensordata->slave_info.sensor_id_reg_addr = + probe_info->reg_addr; + s_ctrl->sensordata->slave_info.sensor_id = + probe_info->expected_data; + s_ctrl->sensordata->slave_info.sensor_id_mask = + probe_info->data_mask; + /* Userspace passes the pipeline delay in reserved field */ + s_ctrl->pipeline_delay = + probe_info->reserved; + + s_ctrl->sensor_probe_addr_type = probe_info->addr_type; + s_ctrl->sensor_probe_data_type = probe_info->data_type; + CAM_DBG(CAM_SENSOR, + "Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x sensor_pipeline_delay:0x%x", + s_ctrl->sensordata->slave_info.sensor_id_reg_addr, + s_ctrl->sensordata->slave_info.sensor_id, + s_ctrl->sensordata->slave_info.sensor_id_mask, + s_ctrl->pipeline_delay); + return rc; +} + +int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf, + struct cam_sensor_ctrl_t *s_ctrl, + int32_t cmd_buf_num, uint32_t cmd_buf_length, size_t remain_len) +{ + int32_t rc = 0; + + switch (cmd_buf_num) { + case 0: { + 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) { + CAM_ERR(CAM_SENSOR, "Failed in Updating the i2c Info"); + return rc; + } + probe_info = (struct cam_cmd_probe *) + (cmd_buf + sizeof(struct cam_cmd_i2c_info)); + rc = cam_sensor_update_slave_info(probe_info, s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Updating the slave Info"); + return rc; + } + cmd_buf = probe_info; + } + break; + case 1: { + rc = cam_sensor_update_power_settings(cmd_buf, + cmd_buf_length, &s_ctrl->sensordata->power_info, + remain_len); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in updating power settings"); + return rc; + } + } + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid command buffer"); + break; + } + return rc; +} + +int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl) +{ + int rc = 0, i; + uint32_t *cmd_buf; + void *ptr; + size_t len; + 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); + if (rc < 0) { + 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 end; + } + + 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 end; + } + + 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"); + rc = -EINVAL; + goto end; + } + if (pkt->num_cmd_buf != 2) { + CAM_ERR(CAM_SENSOR, "Expected More Command Buffers : %d", + pkt->num_cmd_buf); + rc = -EINVAL; + goto end; + } + + for (i = 0; i < pkt->num_cmd_buf; i++) { + if (!(cmd_desc[i].length)) + continue; + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &cmd_buf1, &len); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to parse the command Buffer Header"); + goto end; + } + if (cmd_desc[i].offset >= len) { + CAM_ERR(CAM_SENSOR, + "offset past length of buffer"); + rc = -EINVAL; + goto end; + } + 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 end; + } + 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, remain_len); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to parse the command Buffer Header"); + goto end; + } + } + +end: + return rc; +} + +void cam_sensor_query_cap(struct cam_sensor_ctrl_t *s_ctrl, + struct cam_sensor_query_cap *query_cap) +{ + query_cap->pos_roll = s_ctrl->sensordata->pos_roll; + query_cap->pos_pitch = s_ctrl->sensordata->pos_pitch; + query_cap->pos_yaw = s_ctrl->sensordata->pos_yaw; + query_cap->secure_camera = 0; + query_cap->actuator_slot_id = + s_ctrl->sensordata->subdev_id[SUB_MODULE_ACTUATOR]; + query_cap->csiphy_slot_id = + s_ctrl->sensordata->subdev_id[SUB_MODULE_CSIPHY]; + query_cap->eeprom_slot_id = + s_ctrl->sensordata->subdev_id[SUB_MODULE_EEPROM]; + query_cap->flash_slot_id = + s_ctrl->sensordata->subdev_id[SUB_MODULE_LED_FLASH]; + query_cap->ois_slot_id = + s_ctrl->sensordata->subdev_id[SUB_MODULE_OIS]; + query_cap->slot_info = + s_ctrl->soc_info.index; +} + +static uint16_t cam_sensor_id_by_mask(struct cam_sensor_ctrl_t *s_ctrl, + uint32_t chipid) +{ + uint16_t sensor_id = (uint16_t)(chipid & 0xFFFF); + int16_t sensor_id_mask = s_ctrl->sensordata->slave_info.sensor_id_mask; + + if (!sensor_id_mask) + sensor_id_mask = ~sensor_id_mask; + + sensor_id &= sensor_id_mask; + sensor_id_mask &= -sensor_id_mask; + sensor_id_mask -= 1; + while (sensor_id_mask) { + sensor_id_mask >>= 1; + sensor_id >>= 1; + } + return sensor_id; +} + +void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl) +{ + struct cam_sensor_power_ctrl_t *power_info = + &s_ctrl->sensordata->power_info; + int rc = 0; + + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) && + (s_ctrl->is_probe_succeed == 0)) + return; + + cam_sensor_release_stream_rsc(s_ctrl); + cam_sensor_release_per_frame_resource(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, "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; + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_setting_size = 0; + power_info->power_down_setting_size = 0; + s_ctrl->streamon_count = 0; + s_ctrl->streamoff_count = 0; + s_ctrl->is_probe_succeed = 0; + s_ctrl->last_flush_req = 0; + s_ctrl->sensor_state = CAM_SENSOR_INIT; +} + +int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl) +{ + int rc = 0; + uint32_t chipid = 0; + struct cam_camera_slave_info *slave_info; + + slave_info = &(s_ctrl->sensordata->slave_info); + + if (!slave_info) { + CAM_ERR(CAM_SENSOR, " failed: %pK", + slave_info); + return -EINVAL; + } + + rc = camera_io_dev_read( + &(s_ctrl->io_master_info), + slave_info->sensor_id_reg_addr, + &chipid, CAMERA_SENSOR_I2C_TYPE_WORD, + CAMERA_SENSOR_I2C_TYPE_WORD); + + CAM_DBG(CAM_SENSOR, "read id: 0x%x expected id 0x%x:", + chipid, slave_info->sensor_id); + + if (cam_sensor_id_by_mask(s_ctrl, chipid) != slave_info->sensor_id) { + CAM_WARN(CAM_SENSOR, "read id: 0x%x expected id 0x%x:", + chipid, slave_info->sensor_id); + return -ENODEV; + } + return rc; +} + +int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, + void *arg) +{ + int rc = 0; + struct cam_control *cmd = (struct cam_control *)arg; + struct cam_sensor_power_ctrl_t *power_info = + &s_ctrl->sensordata->power_info; + if (!s_ctrl || !arg) { + CAM_ERR(CAM_SENSOR, "s_ctrl is NULL"); + return -EINVAL; + } + + if (cmd->op_code != CAM_SENSOR_PROBE_CMD) { + if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { + CAM_ERR(CAM_SENSOR, "Invalid handle type: %d", + cmd->handle_type); + return -EINVAL; + } + } + + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + switch (cmd->op_code) { + case CAM_SENSOR_PROBE_CMD: { + if (s_ctrl->is_probe_succeed == 1) { + CAM_ERR(CAM_SENSOR, + "Already Sensor Probed in the slot"); + break; + } + + if (cmd->handle_type == + CAM_HANDLE_MEM_HANDLE) { + rc = cam_handle_mem_ptr(cmd->handle, s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Get Buffer Handle Failed"); + goto release_mutex; + } + } else { + CAM_ERR(CAM_SENSOR, "Invalid Command Type: %d", + cmd->handle_type); + rc = -EINVAL; + goto release_mutex; + } + + /* Parse and fill vreg params for powerup settings */ + rc = msm_camera_fill_vreg_params( + &s_ctrl->soc_info, + s_ctrl->sensordata->power_info.power_setting, + s_ctrl->sensordata->power_info.power_setting_size); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Fail in filling vreg params for PUP rc %d", + rc); + goto free_power_settings; + } + + /* Parse and fill vreg params for powerdown settings*/ + rc = msm_camera_fill_vreg_params( + &s_ctrl->soc_info, + s_ctrl->sensordata->power_info.power_down_setting, + s_ctrl->sensordata->power_info.power_down_setting_size); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Fail in filling vreg params for PDOWN rc %d", + rc); + goto free_power_settings; + } + + /* Power up and probe sensor */ + rc = cam_sensor_power_up(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "power up failed"); + goto free_power_settings; + } + + /* Match sensor ID */ + rc = cam_sensor_match_id(s_ctrl); + if (rc < 0) { + cam_sensor_power_down(s_ctrl); + msleep(20); + goto free_power_settings; + } + + CAM_INFO(CAM_SENSOR, + "Probe success,slot:%d,slave_addr:0x%x,sensor_id:0x%x", + s_ctrl->soc_info.index, + s_ctrl->sensordata->slave_info.sensor_slave_addr, + s_ctrl->sensordata->slave_info.sensor_id); + + rc = cam_sensor_power_down(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "fail in Sensor Power Down"); + goto free_power_settings; + } + /* + * Set probe succeeded flag to 1 so that no other camera shall + * probed on this slot + */ + s_ctrl->is_probe_succeed = 1; + s_ctrl->sensor_state = CAM_SENSOR_INIT; + } + break; + case CAM_ACQUIRE_DEV: { + struct cam_sensor_acquire_dev sensor_acq_dev; + struct cam_create_dev_hdl bridge_params; + + if ((s_ctrl->is_probe_succeed == 0) || + (s_ctrl->sensor_state != CAM_SENSOR_INIT)) { + CAM_WARN(CAM_SENSOR, + "Not in right state to aquire %d", + s_ctrl->sensor_state); + rc = -EINVAL; + goto release_mutex; + } + + if (s_ctrl->bridge_intf.device_hdl != -1) { + CAM_ERR(CAM_SENSOR, "Device is already acquired"); + rc = -EINVAL; + goto release_mutex; + } + rc = copy_from_user(&sensor_acq_dev, + u64_to_user_ptr(cmd->handle), + sizeof(sensor_acq_dev)); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed Copying from user"); + goto release_mutex; + } + + bridge_params.session_hdl = sensor_acq_dev.session_handle; + bridge_params.ops = &s_ctrl->bridge_intf.ops; + bridge_params.v4l2_sub_dev_flag = 0; + bridge_params.media_entity_flag = 0; + bridge_params.priv = s_ctrl; + + sensor_acq_dev.device_handle = + cam_create_device_hdl(&bridge_params); + s_ctrl->bridge_intf.device_hdl = sensor_acq_dev.device_handle; + s_ctrl->bridge_intf.session_hdl = sensor_acq_dev.session_handle; + + CAM_DBG(CAM_SENSOR, "Device Handle: %d", + sensor_acq_dev.device_handle); + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &sensor_acq_dev, + sizeof(struct cam_sensor_acquire_dev))) { + CAM_ERR(CAM_SENSOR, "Failed Copy to User"); + rc = -EFAULT; + goto release_mutex; + } + + rc = cam_sensor_power_up(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Sensor Power up failed"); + goto release_mutex; + } + + s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; + s_ctrl->last_flush_req = 0; + CAM_INFO(CAM_SENSOR, + "CAM_ACQUIRE_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", + s_ctrl->sensordata->slave_info.sensor_id, + s_ctrl->sensordata->slave_info.sensor_slave_addr); + } + break; + case CAM_RELEASE_DEV: { + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || + (s_ctrl->sensor_state == CAM_SENSOR_START)) { + rc = -EINVAL; + CAM_WARN(CAM_SENSOR, + "Not in right state to release : %d", + s_ctrl->sensor_state); + goto release_mutex; + } + + if (s_ctrl->bridge_intf.link_hdl != -1) { + CAM_ERR(CAM_SENSOR, + "Device [%d] still active on link 0x%x", + s_ctrl->sensor_state, + s_ctrl->bridge_intf.link_hdl); + rc = -EAGAIN; + goto release_mutex; + } + + rc = cam_sensor_power_down(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Sensor Power Down failed"); + goto release_mutex; + } + + cam_sensor_release_per_frame_resource(s_ctrl); + cam_sensor_release_stream_rsc(s_ctrl); + if (s_ctrl->bridge_intf.device_hdl == -1) { + CAM_ERR(CAM_SENSOR, + "Invalid Handles: link hdl: %d device hdl: %d", + s_ctrl->bridge_intf.device_hdl, + s_ctrl->bridge_intf.link_hdl); + rc = -EINVAL; + goto release_mutex; + } + rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "failed in destroying the device hdl"); + s_ctrl->bridge_intf.device_hdl = -1; + s_ctrl->bridge_intf.link_hdl = -1; + s_ctrl->bridge_intf.session_hdl = -1; + + s_ctrl->sensor_state = CAM_SENSOR_INIT; + CAM_INFO(CAM_SENSOR, + "CAM_RELEASE_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", + s_ctrl->sensordata->slave_info.sensor_id, + s_ctrl->sensordata->slave_info.sensor_slave_addr); + s_ctrl->streamon_count = 0; + s_ctrl->streamoff_count = 0; + s_ctrl->last_flush_req = 0; + } + break; + case CAM_QUERY_CAP: { + struct cam_sensor_query_cap sensor_cap; + + cam_sensor_query_cap(s_ctrl, &sensor_cap); + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &sensor_cap, sizeof(struct cam_sensor_query_cap))) { + CAM_ERR(CAM_SENSOR, "Failed Copy to User"); + rc = -EFAULT; + goto release_mutex; + } + break; + } + case CAM_START_DEV: { + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || + (s_ctrl->sensor_state == CAM_SENSOR_START)) { + rc = -EINVAL; + CAM_WARN(CAM_SENSOR, + "Not in right state to start : %d", + s_ctrl->sensor_state); + goto release_mutex; + } + + if (s_ctrl->i2c_data.streamon_settings.is_settings_valid && + (s_ctrl->i2c_data.streamon_settings.request_id == 0)) { + rc = cam_sensor_apply_settings(s_ctrl, 0, + CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "cannot apply streamon settings"); + goto release_mutex; + } + } + s_ctrl->sensor_state = CAM_SENSOR_START; + CAM_INFO(CAM_SENSOR, + "CAM_START_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", + s_ctrl->sensordata->slave_info.sensor_id, + s_ctrl->sensordata->slave_info.sensor_slave_addr); + } + break; + case CAM_STOP_DEV: { + if (s_ctrl->sensor_state != CAM_SENSOR_START) { + rc = -EINVAL; + CAM_WARN(CAM_SENSOR, + "Not in right state to stop : %d", + s_ctrl->sensor_state); + goto release_mutex; + } + + if (s_ctrl->i2c_data.streamoff_settings.is_settings_valid && + (s_ctrl->i2c_data.streamoff_settings.request_id == 0)) { + rc = cam_sensor_apply_settings(s_ctrl, 0, + CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "cannot apply streamoff settings"); + } + } + + cam_sensor_release_per_frame_resource(s_ctrl); + s_ctrl->last_flush_req = 0; + s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; + CAM_INFO(CAM_SENSOR, + "CAM_STOP_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", + s_ctrl->sensordata->slave_info.sensor_id, + s_ctrl->sensordata->slave_info.sensor_slave_addr); + } + break; + case CAM_CONFIG_DEV: { + rc = cam_sensor_i2c_pkt_parse(s_ctrl, arg); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed i2c pkt parse: %d", rc); + goto release_mutex; + } + if (s_ctrl->i2c_data.init_settings.is_settings_valid && + (s_ctrl->i2c_data.init_settings.request_id == 0)) { + + rc = cam_sensor_apply_settings(s_ctrl, 0, + CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG); + + s_ctrl->i2c_data.init_settings.request_id = -1; + + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "cannot apply init settings"); + delete_request(&s_ctrl->i2c_data.init_settings); + goto release_mutex; + } + rc = delete_request(&s_ctrl->i2c_data.init_settings); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Fail in deleting the Init settings"); + goto release_mutex; + } + } + + if (s_ctrl->i2c_data.config_settings.is_settings_valid && + (s_ctrl->i2c_data.config_settings.request_id == 0)) { + rc = cam_sensor_apply_settings(s_ctrl, 0, + CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG); + + s_ctrl->i2c_data.config_settings.request_id = -1; + + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "cannot apply config settings"); + delete_request( + &s_ctrl->i2c_data.config_settings); + goto release_mutex; + } + rc = delete_request(&s_ctrl->i2c_data.config_settings); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Fail in deleting the config settings"); + goto release_mutex; + } + s_ctrl->sensor_state = CAM_SENSOR_CONFIG; + } + } + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid Opcode: %d", cmd->op_code); + rc = -EINVAL; + goto release_mutex; + } + +release_mutex: + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return rc; + +free_power_settings: + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_down_setting_size = 0; + power_info->power_setting_size = 0; + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return rc; +} + +int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info) +{ + int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + + if (!info) + return -EINVAL; + + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(info->dev_hdl); + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + return -EINVAL; + } + + info->dev_id = CAM_REQ_MGR_DEVICE_SENSOR; + strlcpy(info->name, CAM_SENSOR_NAME, sizeof(info->name)); + if (s_ctrl->pipeline_delay >= 1 && s_ctrl->pipeline_delay <= 3) + info->p_delay = s_ctrl->pipeline_delay; + else + info->p_delay = 2; + info->trigger = CAM_TRIGGER_POINT_SOF; + + return rc; +} + +int cam_sensor_establish_link(struct cam_req_mgr_core_dev_link_setup *link) +{ + struct cam_sensor_ctrl_t *s_ctrl = NULL; + + if (!link) + return -EINVAL; + + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(link->dev_hdl); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + return -EINVAL; + } + + mutex_lock(&s_ctrl->cam_sensor_mutex); + if (link->link_enable) { + s_ctrl->bridge_intf.link_hdl = link->link_hdl; + s_ctrl->bridge_intf.crm_cb = link->crm_cb; + } else { + s_ctrl->bridge_intf.link_hdl = -1; + s_ctrl->bridge_intf.crm_cb = NULL; + } + mutex_unlock(&s_ctrl->cam_sensor_mutex); + + return 0; +} + +int cam_sensor_power(struct v4l2_subdev *sd, int on) +{ + struct cam_sensor_ctrl_t *s_ctrl = v4l2_get_subdevdata(sd); + + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + if (!on && s_ctrl->sensor_state == CAM_SENSOR_START) { + cam_sensor_power_down(s_ctrl); + s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; + } + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + + return 0; +} + +int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl) +{ + int rc; + struct cam_sensor_power_ctrl_t *power_info; + struct cam_camera_slave_info *slave_info; + struct cam_hw_soc_info *soc_info = + &s_ctrl->soc_info; + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "failed: %pK", s_ctrl); + return -EINVAL; + } + + power_info = &s_ctrl->sensordata->power_info; + slave_info = &(s_ctrl->sensordata->slave_info); + + if (!power_info || !slave_info) { + CAM_ERR(CAM_SENSOR, "failed: %pK %pK", power_info, slave_info); + return -EINVAL; + } + + if (s_ctrl->bob_pwm_switch) { + rc = cam_sensor_bob_pwm_mode_switch(soc_info, + s_ctrl->bob_reg_index, true); + if (rc) { + CAM_WARN(CAM_SENSOR, + "BoB PWM setup failed rc: %d", rc); + rc = 0; + } + } + + rc = cam_sensor_core_power_up(power_info, soc_info); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc); + return rc; + } + + rc = camera_io_init(&(s_ctrl->io_master_info)); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "cci_init failed: rc: %d", rc); + + return rc; +} + +int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl) +{ + struct cam_sensor_power_ctrl_t *power_info; + struct cam_hw_soc_info *soc_info; + int rc = 0; + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "failed: s_ctrl %pK", s_ctrl); + return -EINVAL; + } + + power_info = &s_ctrl->sensordata->power_info; + soc_info = &s_ctrl->soc_info; + + if (!power_info) { + CAM_ERR(CAM_SENSOR, "failed: power_info %pK", power_info); + return -EINVAL; + } + rc = cam_sensor_util_power_down(power_info, soc_info); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "power down the core is failed:%d", rc); + return rc; + } + + if (s_ctrl->bob_pwm_switch) { + rc = cam_sensor_bob_pwm_mode_switch(soc_info, + s_ctrl->bob_reg_index, false); + if (rc) { + CAM_WARN(CAM_SENSOR, + "BoB PWM setup failed rc: %d", rc); + rc = 0; + } + } + + camera_io_release(&(s_ctrl->io_master_info)); + + return rc; +} + +int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, + int64_t req_id, enum cam_sensor_packet_opcodes opcode) +{ + int rc = 0, offset, i; + uint64_t top = 0, del_req_id = 0; + struct i2c_settings_array *i2c_set = NULL; + struct i2c_settings_list *i2c_list; + + if (req_id == 0) { + switch (opcode) { + case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON: { + i2c_set = &s_ctrl->i2c_data.streamon_settings; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG: { + i2c_set = &s_ctrl->i2c_data.init_settings; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG: { + i2c_set = &s_ctrl->i2c_data.config_settings; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF: { + i2c_set = &s_ctrl->i2c_data.streamoff_settings; + break; + } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: + case CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE: + default: + return 0; + } + if (i2c_set->is_settings_valid == 1) { + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + rc = cam_sensor_i2c_modes_util( + &(s_ctrl->io_master_info), + i2c_list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to apply settings: %d", + rc); + return rc; + } + } + } + } else { + offset = req_id % MAX_PER_FRAME_ARRAY; + i2c_set = &(s_ctrl->i2c_data.per_frame[offset]); + if (i2c_set->is_settings_valid == 1 && + i2c_set->request_id == req_id) { + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + rc = cam_sensor_i2c_modes_util( + &(s_ctrl->io_master_info), + i2c_list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to apply settings: %d", + rc); + return rc; + } + } + } else { + CAM_DBG(CAM_SENSOR, + "Invalid/NOP request to apply: %lld", req_id); + } + + /* Change the logic dynamically */ + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + if ((req_id >= + s_ctrl->i2c_data.per_frame[i].request_id) && + (top < + s_ctrl->i2c_data.per_frame[i].request_id) && + (s_ctrl->i2c_data.per_frame[i].is_settings_valid + == 1)) { + del_req_id = top; + top = s_ctrl->i2c_data.per_frame[i].request_id; + } + } + + if (top < req_id) { + if ((((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) >= BATCH_SIZE_MAX) || + (((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) <= -BATCH_SIZE_MAX)) + del_req_id = req_id; + } + + if (!del_req_id) + return rc; + + CAM_DBG(CAM_SENSOR, "top: %llu, del_req_id:%llu", + top, del_req_id); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + if ((del_req_id > + s_ctrl->i2c_data.per_frame[i].request_id) && ( + s_ctrl->i2c_data.per_frame[i].is_settings_valid + == 1)) { + s_ctrl->i2c_data.per_frame[i].request_id = 0; + rc = delete_request( + &(s_ctrl->i2c_data.per_frame[i])); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "Delete request Fail:%lld rc:%d", + del_req_id, rc); + } + } + } + + return rc; +} + +int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply) +{ + int32_t rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + + if (!apply) + return -EINVAL; + + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(apply->dev_hdl); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + return -EINVAL; + } + CAM_DBG(CAM_REQ, " Sensor update req id: %lld", apply->request_id); + trace_cam_apply_req("Sensor", apply->request_id); + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + rc = cam_sensor_apply_settings(s_ctrl, apply->request_id, + CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return rc; +} + +int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) +{ + int32_t rc = 0, i; + uint32_t cancel_req_id_found = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + struct i2c_settings_array *i2c_set = NULL; + + if (!flush_req) + return -EINVAL; + + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(flush_req->dev_hdl); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + 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; + } + + 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", + flush_req->req_id); + } + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(s_ctrl->i2c_data.per_frame[i]); + + if ((flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) + && (i2c_set->request_id != flush_req->req_id)) + continue; + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + + if (flush_req->type == + CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + cancel_req_id_found = 1; + break; + } + } + } + + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && + !cancel_req_id_found) + CAM_DBG(CAM_SENSOR, + "Flush request id:%lld not found in the pending list", + flush_req->req_id); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return rc; +} diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h new file mode 100644 index 000000000000..b7a5923a6a70 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_CORE_H_ +#define _CAM_SENSOR_CORE_H_ + +#include "cam_sensor_dev.h" + +/** + * @s_ctrl: Sensor ctrl structure + * + * This API powers up the camera sensor module + */ +int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl); + +/** + * @s_ctrl: Sensor ctrl structure + * + * This API powers down the camera sensor module + */ +int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl); + +/** + * @sd: V4L2 subdevice + * @on: Turn off/on flag + * + * This API powers down the sensor module + */ +int cam_sensor_power(struct v4l2_subdev *sd, int on); + +/** + * @s_ctrl: Sensor ctrl structure + * @req_id: Request id + * @opcode: opcode for settings + * + * This API applies the req_id settings to sensor + */ +int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, int64_t req_id, + enum cam_sensor_packet_opcodes opcode); + +/** + * @apply: Req mgr structure for applying request + * + * This API applies the request that is mentioned + */ +int cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply); + +/** + * @flush: Req mgr structure for flushing request + * + * This API flushes the request that is mentioned + */ +int cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush); + +/** + * @info: Sub device info to req mgr + * + * Publish the subdevice info + */ +int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info); + +/** + * @link: Link setup info + * + * This API establishes link with sensor subdevice with req mgr + */ +int cam_sensor_establish_link(struct cam_req_mgr_core_dev_link_setup *link); + +/** + * @s_ctrl: Sensor ctrl structure + * @arg: Camera control command argument + * + * This API handles the camera control argument reached to sensor + */ +int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, void *arg); + +/** + * @s_ctrl: Sensor ctrl structure + * + * This API handles the camera sensor close/shutdown + */ +void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl); + +#endif /* _CAM_SENSOR_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c new file mode 100644 index 000000000000..f847079c730a --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_sensor_dev.h" +#include "cam_req_mgr_dev.h" +#include "cam_sensor_soc.h" +#include "cam_sensor_core.h" + +static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_sensor_driver_cmd(s_ctrl, arg); + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); + rc = -EINVAL; + break; + } + return rc; +} + +static int cam_sensor_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "s_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + cam_sensor_shutdown(s_ctrl); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + + return 0; +} + +#ifdef CONFIG_COMPAT +static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + struct cam_control cmd_data; + int32_t rc = 0; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + CAM_ERR(CAM_SENSOR, "Failed to copy from user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_sensor_subdev_ioctl(sd, cmd, &cmd_data); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "cam_sensor_subdev_ioctl failed"); + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid compat ioctl cmd_type: %d", cmd); + rc = -EINVAL; + } + + if (!rc) { + if (copy_to_user((void __user *)arg, &cmd_data, + sizeof(cmd_data))) { + CAM_ERR(CAM_SENSOR, + "Failed to copy to user_ptr=%pK size=%zu", + (void __user *)arg, sizeof(cmd_data)); + rc = -EFAULT; + } + } + + return rc; +} + +#endif +static struct v4l2_subdev_core_ops cam_sensor_subdev_core_ops = { + .ioctl = cam_sensor_subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = cam_sensor_init_subdev_do_ioctl, +#endif + .s_power = cam_sensor_power, +}; + +static struct v4l2_subdev_ops cam_sensor_subdev_ops = { + .core = &cam_sensor_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops cam_sensor_internal_ops = { + .close = cam_sensor_subdev_close, +}; + +static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) +{ + int rc = 0; + + s_ctrl->v4l2_dev_str.internal_ops = + &cam_sensor_internal_ops; + s_ctrl->v4l2_dev_str.ops = + &cam_sensor_subdev_ops; + strlcpy(s_ctrl->device_name, CAMX_SENSOR_DEV_NAME, + sizeof(s_ctrl->device_name)); + s_ctrl->v4l2_dev_str.name = + s_ctrl->device_name; + s_ctrl->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + s_ctrl->v4l2_dev_str.ent_function = + CAM_SENSOR_DEVICE_TYPE; + s_ctrl->v4l2_dev_str.token = s_ctrl; + + rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); + if (rc) + CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); + + return rc; +} + +static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int32_t rc = 0; + int i = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + struct cam_hw_soc_info *soc_info = NULL; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + CAM_ERR(CAM_SENSOR, + "%s :i2c_check_functionality failed", client->name); + return -EFAULT; + } + + /* Create sensor control structure */ + s_ctrl = kzalloc(sizeof(*s_ctrl), GFP_KERNEL); + if (!s_ctrl) + return -ENOMEM; + + i2c_set_clientdata(client, s_ctrl); + + s_ctrl->io_master_info.client = client; + soc_info = &s_ctrl->soc_info; + soc_info->dev = &client->dev; + soc_info->dev_name = client->name; + + /* Initialize sensor device type */ + s_ctrl->of_node = client->dev.of_node; + s_ctrl->io_master_info.master_type = I2C_MASTER; + s_ctrl->is_probe_succeed = 0; + s_ctrl->last_flush_req = 0; + + rc = cam_sensor_parse_dt(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "cam_sensor_parse_dt rc %d", rc); + goto free_s_ctrl; + } + + rc = cam_sensor_init_subdev_params(s_ctrl); + if (rc) + goto free_s_ctrl; + + s_ctrl->i2c_data.per_frame = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (s_ctrl->i2c_data.per_frame == NULL) { + rc = -ENOMEM; + goto unreg_subdev; + } + + INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); + + s_ctrl->bridge_intf.device_hdl = -1; + s_ctrl->bridge_intf.link_hdl = -1; + s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; + s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; + s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; + s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request; + + s_ctrl->sensordata->power_info.dev = soc_info->dev; + + return rc; +unreg_subdev: + cam_unregister_subdev(&(s_ctrl->v4l2_dev_str)); +free_s_ctrl: + kfree(s_ctrl); + return rc; +} + +static int cam_sensor_platform_remove(struct platform_device *pdev) +{ + int i; + struct cam_sensor_ctrl_t *s_ctrl; + struct cam_hw_soc_info *soc_info; + + s_ctrl = platform_get_drvdata(pdev); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "sensor device is NULL"); + 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; +} + +static int cam_sensor_driver_i2c_remove(struct i2c_client *client) +{ + int i; + struct cam_sensor_ctrl_t *s_ctrl = i2c_get_clientdata(client); + struct cam_hw_soc_info *soc_info; + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "sensor device is NULL"); + 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; +} + +static const struct of_device_id cam_sensor_driver_dt_match[] = { + {.compatible = "qcom,cam-sensor"}, + {} +}; + +static int32_t cam_sensor_driver_platform_probe( + struct platform_device *pdev) +{ + int32_t rc = 0, i = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + struct cam_hw_soc_info *soc_info = NULL; + + /* Create sensor control structure */ + s_ctrl = devm_kzalloc(&pdev->dev, + sizeof(struct cam_sensor_ctrl_t), GFP_KERNEL); + if (!s_ctrl) + return -ENOMEM; + + soc_info = &s_ctrl->soc_info; + soc_info->pdev = pdev; + soc_info->dev = &pdev->dev; + soc_info->dev_name = pdev->name; + + /* Initialize sensor device type */ + s_ctrl->of_node = pdev->dev.of_node; + s_ctrl->is_probe_succeed = 0; + s_ctrl->last_flush_req = 0; + + /*fill in platform device*/ + s_ctrl->pdev = pdev; + + s_ctrl->io_master_info.master_type = CCI_MASTER; + + rc = cam_sensor_parse_dt(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed: cam_sensor_parse_dt rc %d", rc); + goto free_s_ctrl; + } + + /* Fill platform device id*/ + pdev->id = soc_info->index; + + rc = cam_sensor_init_subdev_params(s_ctrl); + if (rc) + goto free_s_ctrl; + + s_ctrl->i2c_data.per_frame = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (s_ctrl->i2c_data.per_frame == NULL) { + rc = -ENOMEM; + goto unreg_subdev; + } + + INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); + + s_ctrl->bridge_intf.device_hdl = -1; + s_ctrl->bridge_intf.link_hdl = -1; + s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; + s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; + s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; + s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request; + + s_ctrl->sensordata->power_info.dev = &pdev->dev; + platform_set_drvdata(pdev, s_ctrl); + s_ctrl->sensor_state = CAM_SENSOR_INIT; + + return rc; +unreg_subdev: + cam_unregister_subdev(&(s_ctrl->v4l2_dev_str)); +free_s_ctrl: + devm_kfree(&pdev->dev, s_ctrl); + return rc; +} + +MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match); + +static struct platform_driver cam_sensor_platform_driver = { + .probe = cam_sensor_driver_platform_probe, + .driver = { + .name = "qcom,camera", + .owner = THIS_MODULE, + .of_match_table = cam_sensor_driver_dt_match, + .suppress_bind_attrs = true, + }, + .remove = cam_sensor_platform_remove, +}; + +static const struct i2c_device_id i2c_id[] = { + {SENSOR_DRIVER_I2C, (kernel_ulong_t)NULL}, + { } +}; + +static struct i2c_driver cam_sensor_driver_i2c = { + .id_table = i2c_id, + .probe = cam_sensor_driver_i2c_probe, + .remove = cam_sensor_driver_i2c_remove, + .driver = { + .name = SENSOR_DRIVER_I2C, + }, +}; + +static int __init cam_sensor_driver_init(void) +{ + int32_t rc = 0; + + rc = platform_driver_register(&cam_sensor_platform_driver); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "platform_driver_register Failed: rc = %d", + rc); + return rc; + } + + rc = i2c_add_driver(&cam_sensor_driver_i2c); + if (rc) + CAM_ERR(CAM_SENSOR, "i2c_add_driver failed rc = %d", rc); + + return rc; +} + +static void __exit cam_sensor_driver_exit(void) +{ + platform_driver_unregister(&cam_sensor_platform_driver); + i2c_del_driver(&cam_sensor_driver_i2c); +} + +module_init(cam_sensor_driver_init); +module_exit(cam_sensor_driver_exit); +MODULE_DESCRIPTION("cam_sensor_driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h new file mode 100644 index 000000000000..86676a4c8f0a --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_DEV_H_ +#define _CAM_SENSOR_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_debug_util.h" + +#define NUM_MASTERS 2 +#define NUM_QUEUES 2 + +#define TRUE 1 +#define FALSE 0 + +#undef CDBG +#ifdef CAM_SENSOR_DEBUG +#define CDBG(fmt, args...) pr_err(fmt, ##args) +#else +#define CDBG(fmt, args...) pr_debug(fmt, ##args) +#endif + +#define SENSOR_DRIVER_I2C "i2c_camera" +#define CAMX_SENSOR_DEV_NAME "cam-sensor-driver" + +enum cam_sensor_state_t { + CAM_SENSOR_INIT, + CAM_SENSOR_ACQUIRE, + CAM_SENSOR_CONFIG, + CAM_SENSOR_START, +}; + +/** + * struct intf_params + * @device_hdl: Device Handle + * @session_hdl: Session Handle + * @link_hdl: Link Handle + * @ops: KMD operations + * @crm_cb: Callback API pointers + */ +struct intf_params { + int32_t device_hdl; + int32_t session_hdl; + int32_t link_hdl; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; +}; + +/** + * struct cam_sensor_ctrl_t: Camera control structure + * @pdev: Platform device + * @cam_sensor_mutex: Sensor mutex + * @sensordata: Sensor board Information + * @cci_i2c_master: I2C structure + * @io_master_info: Information about the communication master + * @sensor_state: Sensor states + * @is_probe_succeed: Probe succeeded or not + * @id: Cell Index + * @of_node: Of node ptr + * @v4l2_dev_str: V4L2 device structure + * @sensor_probe_addr_type: Sensor probe address type + * @sensor_probe_data_type: Sensor probe data type + * @i2c_data: Sensor I2C register settings + * @sensor_info: Sensor query cap structure + * @bridge_intf: Bridge interface structure + * @device_name: Sensor device structure + * @streamon_count: Count to hold the number of times stream on called + * @streamoff_count: Count to hold the number of times stream off called + * @bob_reg_index: Hold to BoB regulator index + * @bob_pwm_switch: Boolean flag to switch into PWM mode for BoB regulator + * @last_flush_req: Last request to flush + * @pipeline_delay: Sensor pipeline delay + */ +struct cam_sensor_ctrl_t { + struct platform_device *pdev; + struct cam_hw_soc_info soc_info; + struct mutex cam_sensor_mutex; + struct cam_sensor_board_info *sensordata; + enum cci_i2c_master_t cci_i2c_master; + enum cci_device_num cci_num; + struct camera_io_master io_master_info; + enum cam_sensor_state_t sensor_state; + uint8_t is_probe_succeed; + uint32_t id; + struct device_node *of_node; + struct cam_subdev v4l2_dev_str; + uint8_t sensor_probe_addr_type; + uint8_t sensor_probe_data_type; + struct i2c_data_settings i2c_data; + struct cam_sensor_query_cap sensor_info; + struct intf_params bridge_intf; + char device_name[20]; + uint32_t streamon_count; + uint32_t streamoff_count; + int bob_reg_index; + bool bob_pwm_switch; + uint32_t last_flush_req; + uint16_t pipeline_delay; +}; + +#endif /* _CAM_SENSOR_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c new file mode 100644 index 000000000000..2c25ee0aa6f0 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "cam_sensor_soc.h" +#include "cam_soc_util.h" + +int32_t cam_sensor_get_sub_module_index(struct device_node *of_node, + struct cam_sensor_board_info *s_info) +{ + int rc = 0, i = 0; + uint32_t val = 0; + struct device_node *src_node = NULL; + struct cam_sensor_board_info *sensor_info; + + sensor_info = s_info; + + for (i = 0; i < SUB_MODULE_MAX; i++) + sensor_info->subdev_id[i] = -1; + + src_node = of_parse_phandle(of_node, "actuator-src", 0); + if (!src_node) { + CAM_DBG(CAM_SENSOR, "src_node NULL"); + } else { + rc = of_property_read_u32(src_node, "cell-index", &val); + CAM_DBG(CAM_SENSOR, "actuator cell index %d, rc %d", val, rc); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + of_node_put(src_node); + return rc; + } + sensor_info->subdev_id[SUB_MODULE_ACTUATOR] = val; + of_node_put(src_node); + } + + src_node = of_parse_phandle(of_node, "ois-src", 0); + if (!src_node) { + CAM_DBG(CAM_SENSOR, "src_node NULL"); + } else { + rc = of_property_read_u32(src_node, "cell-index", &val); + CAM_DBG(CAM_SENSOR, " ois cell index %d, rc %d", val, rc); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + of_node_put(src_node); + return rc; + } + sensor_info->subdev_id[SUB_MODULE_OIS] = val; + of_node_put(src_node); + } + + src_node = of_parse_phandle(of_node, "eeprom-src", 0); + if (!src_node) { + CAM_DBG(CAM_SENSOR, "eeprom src_node NULL"); + } else { + rc = of_property_read_u32(src_node, "cell-index", &val); + CAM_DBG(CAM_SENSOR, "eeprom cell index %d, rc %d", val, rc); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + of_node_put(src_node); + return rc; + } + sensor_info->subdev_id[SUB_MODULE_EEPROM] = val; + of_node_put(src_node); + } + + src_node = of_parse_phandle(of_node, "led-flash-src", 0); + if (!src_node) { + CAM_DBG(CAM_SENSOR, " src_node NULL"); + } else { + rc = of_property_read_u32(src_node, "cell-index", &val); + CAM_DBG(CAM_SENSOR, "led flash cell index %d, rc %d", val, rc); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + of_node_put(src_node); + return rc; + } + sensor_info->subdev_id[SUB_MODULE_LED_FLASH] = val; + of_node_put(src_node); + } + + rc = of_property_read_u32(of_node, "csiphy-sd-index", &val); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "paring the dt node for csiphy rc %d", rc); + else + sensor_info->subdev_id[SUB_MODULE_CSIPHY] = val; + + return rc; +} + +static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl) +{ + int32_t rc = 0; + int i = 0; + struct cam_sensor_board_info *sensordata = NULL; + struct device_node *of_node = s_ctrl->of_node; + struct device_node *of_parent = NULL; + struct cam_hw_soc_info *soc_info = &s_ctrl->soc_info; + + s_ctrl->sensordata = kzalloc(sizeof(*sensordata), GFP_KERNEL); + if (!s_ctrl->sensordata) + return -ENOMEM; + + sensordata = s_ctrl->sensordata; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed to read DT properties rc %d", rc); + goto FREE_SENSOR_DATA; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &sensordata->power_info.gpio_num_info); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed to read gpios %d", rc); + goto FREE_SENSOR_DATA; + } + + s_ctrl->id = soc_info->index; + + /* Validate cell_id */ + if (s_ctrl->id >= MAX_CAMERAS) { + CAM_ERR(CAM_SENSOR, "Failed invalid cell_id %d", s_ctrl->id); + rc = -EINVAL; + goto FREE_SENSOR_DATA; + } + + /* Store the index of BoB regulator if it is available */ + for (i = 0; i < soc_info->num_rgltr; i++) { + if (!strcmp(soc_info->rgltr_name[i], + "cam_bob")) { + CAM_DBG(CAM_SENSOR, + "i: %d cam_bob", i); + s_ctrl->bob_reg_index = i; + soc_info->rgltr[i] = devm_regulator_get(soc_info->dev, + soc_info->rgltr_name[i]); + if (IS_ERR_OR_NULL(soc_info->rgltr[i])) { + CAM_WARN(CAM_SENSOR, + "Regulator: %s get failed", + soc_info->rgltr_name[i]); + soc_info->rgltr[i] = NULL; + } else { + if (!of_property_read_bool(of_node, + "pwm-switch")) { + CAM_DBG(CAM_SENSOR, + "No BoB PWM switch param defined"); + s_ctrl->bob_pwm_switch = false; + } else { + s_ctrl->bob_pwm_switch = true; + } + } + } + } + + /* Read subdev info */ + rc = cam_sensor_get_sub_module_index(of_node, sensordata); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed to get sub module index, rc=%d", + rc); + goto FREE_SENSOR_DATA; + } + + if (s_ctrl->io_master_info.master_type == CCI_MASTER) { + /* Get CCI master */ + rc = of_property_read_u32(of_node, "cci-master", + &s_ctrl->cci_i2c_master); + CAM_DBG(CAM_SENSOR, "cci-master %d, rc %d", + s_ctrl->cci_i2c_master, rc); + if (rc < 0) { + /* Set default master 0 */ + s_ctrl->cci_i2c_master = MASTER_0; + rc = 0; + } + + of_parent = of_get_parent(of_node); + if (of_property_read_u32(of_parent, "cell-index", + &s_ctrl->cci_num) < 0) + /* Set default master 0 */ + s_ctrl->cci_num = CCI_DEVICE_0; + + CAM_DBG(CAM_SENSOR, "cci-index %d", s_ctrl->cci_num); + } + + if (of_property_read_u32(of_node, "sensor-position-pitch", + &sensordata->pos_pitch) < 0) { + CAM_DBG(CAM_SENSOR, "Invalid sensor position"); + sensordata->pos_pitch = 360; + } + if (of_property_read_u32(of_node, "sensor-position-roll", + &sensordata->pos_roll) < 0) { + CAM_DBG(CAM_SENSOR, "Invalid sensor position"); + sensordata->pos_roll = 360; + } + if (of_property_read_u32(of_node, "sensor-position-yaw", + &sensordata->pos_yaw) < 0) { + CAM_DBG(CAM_SENSOR, "Invalid sensor position"); + sensordata->pos_yaw = 360; + } + + return rc; + +FREE_SENSOR_DATA: + kfree(sensordata); + return rc; +} + +int32_t msm_sensor_init_default_params(struct cam_sensor_ctrl_t *s_ctrl) +{ + /* Validate input parameters */ + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "failed: invalid params s_ctrl %pK", + s_ctrl); + return -EINVAL; + } + + CAM_DBG(CAM_SENSOR, + "master_type: %d", s_ctrl->io_master_info.master_type); + /* Initialize cci_client */ + if (s_ctrl->io_master_info.master_type == CCI_MASTER) { + s_ctrl->io_master_info.cci_client = kzalloc(sizeof( + struct cam_sensor_cci_client), GFP_KERNEL); + if (!(s_ctrl->io_master_info.cci_client)) + return -ENOMEM; + + s_ctrl->io_master_info.cci_client->cci_device + = s_ctrl->cci_num; + } else if (s_ctrl->io_master_info.master_type == I2C_MASTER) { + if (!(s_ctrl->io_master_info.client)) + return -EINVAL; + } else { + CAM_ERR(CAM_SENSOR, + "Invalid master / Master type Not supported"); + return -EINVAL; + } + + return 0; +} + +int32_t cam_sensor_parse_dt(struct cam_sensor_ctrl_t *s_ctrl) +{ + int32_t i, rc = 0; + struct cam_hw_soc_info *soc_info = &s_ctrl->soc_info; + + /* Parse dt information and store in sensor control structure */ + rc = cam_sensor_driver_get_dt_data(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed to get dt data rc %d", rc); + return rc; + } + + /* Initialize mutex */ + mutex_init(&(s_ctrl->cam_sensor_mutex)); + + /* Initialize default parameters */ + for (i = 0; i < soc_info->num_clk; i++) { + soc_info->clk[i] = devm_clk_get(soc_info->dev, + soc_info->clk_name[i]); + if (!soc_info->clk[i]) { + CAM_ERR(CAM_SENSOR, "get failed for %s", + soc_info->clk_name[i]); + rc = -ENOENT; + return rc; + } + } + rc = msm_sensor_init_default_params(s_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "failed: msm_sensor_init_default_params rc %d", rc); + goto FREE_DT_DATA; + } + + return rc; + +FREE_DT_DATA: + kfree(s_ctrl->sensordata); + s_ctrl->sensordata = NULL; + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.h new file mode 100644 index 000000000000..99862da046ff --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_SOC_H_ +#define _CAM_SENSOR_SOC_H_ + +#include "cam_sensor_dev.h" + +/** + * @s_ctrl: Sensor ctrl structure + * + * Parses sensor dt + */ +int cam_sensor_parse_dt(struct cam_sensor_ctrl_t *s_ctrl); + +#endif /* _CAM_SENSOR_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_sensor_io/Makefile b/drivers/cam_sensor_module/cam_sensor_io/Makefile new file mode 100644 index 000000000000..34ab4315aa92 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o cam_sensor_spi.o diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c new file mode 100644 index 000000000000..a5e780a2e119 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_sensor_cmn_header.h" +#include "cam_sensor_i2c.h" +#include "cam_cci_dev.h" + +int32_t cam_cci_i2c_read(struct cam_sensor_cci_client *cci_client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + int32_t rc = -EINVAL; + unsigned char buf[CAMERA_SENSOR_I2C_TYPE_DWORD]; + struct cam_cci_ctrl cci_ctrl; + + if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + return rc; + + cci_ctrl.cmd = MSM_CCI_I2C_READ; + cci_ctrl.cci_info = cci_client; + cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr; + cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = addr_type; + cci_ctrl.cfg.cci_i2c_read_cfg.data_type = data_type; + cci_ctrl.cfg.cci_i2c_read_cfg.data = buf; + cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = data_type; + rc = v4l2_subdev_call(cci_client->cci_subdev, + core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "rc = %d", rc); + return rc; + } + + rc = cci_ctrl.status; + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) + *data = buf[0]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) + *data = buf[0] << 8 | buf[1]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) + *data = buf[0] << 16 | buf[1] << 8 | buf[2]; + else + *data = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3]; + + return rc; +} + +int32_t cam_camera_cci_i2c_read_seq(struct cam_sensor_cci_client *cci_client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t num_byte) +{ + int32_t rc = -EFAULT; + unsigned char *buf = NULL; + int i = 0; + struct cam_cci_ctrl cci_ctrl; + + if ((addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + || (data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + || (num_byte > I2C_REG_DATA_MAX)) { + CAM_ERR(CAM_SENSOR, "addr_type %d num_byte %d", addr_type, + num_byte); + return rc; + } + + buf = kzalloc(num_byte, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + cci_ctrl.cmd = MSM_CCI_I2C_READ; + cci_ctrl.cci_info = cci_client; + cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr; + cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = addr_type; + cci_ctrl.cfg.cci_i2c_read_cfg.data_type = data_type; + cci_ctrl.cfg.cci_i2c_read_cfg.data = buf; + cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = num_byte; + cci_ctrl.status = -EFAULT; + rc = v4l2_subdev_call(cci_client->cci_subdev, + core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl); + rc = cci_ctrl.status; + CAM_DBG(CAM_SENSOR, "addr = 0x%x, rc = %d", addr, rc); + for (i = 0; i < num_byte; i++) { + data[i] = buf[i]; + CAM_DBG(CAM_SENSOR, "Byte %d: Data: 0x%x\n", i, data[i]); + } + kfree(buf); + return rc; +} + +static int32_t cam_cci_i2c_write_table_cmd( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting, + enum cam_cci_cmd_type cmd) +{ + int32_t rc = -EINVAL; + struct cam_cci_ctrl cci_ctrl; + + if (!client || !write_setting) + return rc; + + if (write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + return rc; + + cci_ctrl.cmd = cmd; + cci_ctrl.cci_info = client->cci_client; + cci_ctrl.cfg.cci_i2c_write_cfg.reg_setting = + write_setting->reg_setting; + cci_ctrl.cfg.cci_i2c_write_cfg.data_type = write_setting->data_type; + cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = write_setting->addr_type; + cci_ctrl.cfg.cci_i2c_write_cfg.size = write_setting->size; + rc = v4l2_subdev_call(client->cci_client->cci_subdev, + core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed rc = %d", rc); + return rc; + } + rc = cci_ctrl.status; + if (write_setting->delay > 20) + msleep(write_setting->delay); + else if (write_setting->delay) + usleep_range(write_setting->delay * 1000, (write_setting->delay + * 1000) + 1000); + + return rc; +} + + +int32_t cam_cci_i2c_write_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + return cam_cci_i2c_write_table_cmd(client, write_setting, + MSM_CCI_I2C_WRITE); +} + +int32_t cam_cci_i2c_write_continuous_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting, + uint8_t cam_sensor_i2c_write_flag) +{ + int32_t rc = 0; + + if (cam_sensor_i2c_write_flag == 1) + rc = cam_cci_i2c_write_table_cmd(client, write_setting, + MSM_CCI_I2C_WRITE_BURST); + else if (cam_sensor_i2c_write_flag == 0) + rc = cam_cci_i2c_write_table_cmd(client, write_setting, + MSM_CCI_I2C_WRITE_SEQ); + + return rc; +} + +static int32_t cam_cci_i2c_compare(struct cam_sensor_cci_client *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type data_type, + enum camera_sensor_i2c_type addr_type) +{ + int32_t rc; + uint32_t reg_data = 0; + + rc = cam_cci_i2c_read(client, addr, ®_data, + addr_type, data_type); + if (rc < 0) + return rc; + + reg_data = reg_data & 0xFFFF; + if (data == (reg_data & ~data_mask)) + return I2C_COMPARE_MATCH; + return I2C_COMPARE_MISMATCH; +} + +int32_t cam_cci_i2c_poll(struct cam_sensor_cci_client *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type data_type, + enum camera_sensor_i2c_type addr_type, + uint32_t delay_ms) +{ + int32_t rc = -EINVAL; + int32_t i = 0; + + CAM_DBG(CAM_SENSOR, "addr: 0x%x data: 0x%x dt: %d", + addr, data, data_type); + + if (delay_ms > MAX_POLL_DELAY_MS) { + CAM_ERR(CAM_SENSOR, "invalid delay = %d max_delay = %d", + delay_ms, MAX_POLL_DELAY_MS); + return -EINVAL; + } + for (i = 0; i < delay_ms; i++) { + rc = cam_cci_i2c_compare(client, + addr, data, data_mask, data_type, addr_type); + if (!rc) + return rc; + + usleep_range(1000, 1010); + } + + /* If rc is 1 then read is successful but poll is failure */ + if (rc == 1) + CAM_ERR(CAM_SENSOR, "poll failed rc=%d(non-fatal)", rc); + + if (rc < 0) + CAM_ERR(CAM_SENSOR, "poll failed rc=%d", rc); + + return rc; +} + +int32_t cam_sensor_cci_i2c_util(struct cam_sensor_cci_client *cci_client, + uint16_t cci_cmd) +{ + int32_t rc = 0; + struct cam_cci_ctrl cci_ctrl; + + cci_ctrl.cmd = cci_cmd; + cci_ctrl.cci_info = cci_client; + rc = v4l2_subdev_call(cci_client->cci_subdev, + core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "Failed rc = %d", rc); + return rc; + } + return cci_ctrl.status; +} diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h new file mode 100644 index 000000000000..752b7fdd8a22 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_I2C_H_ +#define _CAM_SENSOR_I2C_H_ + +#include +#include +#include +#include "cam_cci_dev.h" +#include "cam_sensor_io.h" + +#define I2C_POLL_TIME_MS 5 +#define MAX_POLL_DELAY_MS 100 + +#define I2C_COMPARE_MATCH 0 +#define I2C_COMPARE_MISMATCH 1 + +#define I2C_REG_DATA_MAX (8*1024) + +/** + * @client: CCI client structure + * @data: I2C data + * @addr_type: I2c address type + * @data_type: I2C data type + * + * This API handles CCI read + */ +int32_t cam_cci_i2c_read(struct cam_sensor_cci_client *client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type); + +/** + * @client: CCI client structure + * @addr: I2c address + * @data: I2C data + * @addr_type: I2c address type + * @data_type: I2c data type + * @num_byte: number of bytes + * + * This API handles CCI sequential read + */ +int32_t cam_camera_cci_i2c_read_seq(struct cam_sensor_cci_client *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t num_byte); + +/** + * @client: CCI client structure + * @write_setting: I2C register setting + * + * This API handles CCI random write + */ +int32_t cam_cci_i2c_write_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting); + +/** + * @client: CCI client structure + * @write_setting: I2C register setting + * @cam_sensor_i2c_write_flag: burst or seq write + * + * This API handles CCI continuous write + */ +int32_t cam_cci_i2c_write_continuous_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting, + uint8_t cam_sensor_i2c_write_flag); + +/** + * @cci_client: CCI client structure + * @cci_cmd: CCI command type + * + * Does I2C call to I2C functionalities + */ +int32_t cam_sensor_cci_i2c_util(struct cam_sensor_cci_client *cci_client, + uint16_t cci_cmd); + +/** + * @client: CCI client structure + * @addr: I2C address + * @data: I2C data + * @data_mask: I2C data mask + * @data_type: I2C data type + * @addr_type: I2C addr type + * @delay_ms: Delay in milli seconds + * + * This API implements CCI based I2C poll + */ +int32_t cam_cci_i2c_poll(struct cam_sensor_cci_client *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type data_type, + enum camera_sensor_i2c_type addr_type, + uint32_t delay_ms); + + +/** + * cam_qup_i2c_read : QUP based i2c read + * @client : QUP I2C client structure + * @data : I2C data + * @addr_type : I2c address type + * @data_type : I2C data type + * + * This API handles QUP I2C read + */ + +int32_t cam_qup_i2c_read(struct i2c_client *client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type); + +/** + * cam_qup_i2c_read_seq : QUP based I2C sequential read + * @client : QUP I2C client structure + * @data : I2C data + * @addr_type : I2c address type + * @num_bytes : number of bytes to read + * This API handles QUP I2C Sequential read + */ + +int32_t cam_qup_i2c_read_seq(struct i2c_client *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint32_t num_byte); + +/** + * cam_qup_i2c_poll : QUP based I2C poll operation + * @client : QUP I2C client structure + * @addr : I2C address + * @data : I2C data + * @data_mask : I2C data mask + * @data_type : I2C data type + * @addr_type : I2C addr type + * @delay_ms : Delay in milli seconds + * + * This API implements QUP based I2C poll + */ + +int32_t cam_qup_i2c_poll(struct i2c_client *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t delay_ms); + +/** + * cam_qup_i2c_write_table : QUP based I2C write random + * @client : QUP I2C client structure + * @write_setting : I2C register settings + * + * This API handles QUP I2C random write + */ + +int32_t cam_qup_i2c_write_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting); + +/** + * cam_qup_i2c_write_continuous_write: QUP based I2C write continuous(Burst/Seq) + * @client: QUP I2C client structure + * @write_setting: I2C register setting + * @cam_sensor_i2c_write_flag: burst or seq write + * + * This API handles QUP continuous write + */ +int32_t cam_qup_i2c_write_continuous_table( + struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting, + uint8_t cam_sensor_i2c_write_flag); + +#endif /*_CAM_SENSOR_I2C_H*/ diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c new file mode 100644 index 000000000000..108c47923eb7 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_sensor_io.h" +#include "cam_sensor_i2c.h" + +int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, + uint32_t addr, uint16_t data, uint32_t data_mask, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t delay_ms) +{ + int16_t mask = data_mask & 0xFF; + + if (!io_master_info) { + CAM_ERR(CAM_SENSOR, "Invalid Args"); + return -EINVAL; + } + + if (io_master_info->master_type == CCI_MASTER) { + return cam_cci_i2c_poll(io_master_info->cci_client, + addr, data, mask, data_type, addr_type, delay_ms); + } else if (io_master_info->master_type == I2C_MASTER) { + return cam_qup_i2c_poll(io_master_info->client, + addr, data, data_mask, addr_type, data_type, + delay_ms); + } else { + CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", + io_master_info->master_type); + return -EINVAL; + } +} + +int32_t camera_io_dev_erase(struct camera_io_master *io_master_info, + uint32_t addr, uint32_t size) +{ + int rc = 0; + + if (!io_master_info) { + CAM_ERR(CAM_SENSOR, "Invalid Args"); + return -EINVAL; + } + + if (size == 0) + return rc; + + if (io_master_info->master_type == SPI_MASTER) { + CAM_DBG(CAM_SENSOR, "Calling SPI Erase"); + return cam_spi_erase(io_master_info, addr, + CAMERA_SENSOR_I2C_TYPE_WORD, size); + } else if (io_master_info->master_type == I2C_MASTER || + io_master_info->master_type == CCI_MASTER) { + CAM_ERR(CAM_SENSOR, "Erase not supported on master :%d", + io_master_info->master_type); + rc = -EINVAL; + } else { + CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", + io_master_info->master_type); + rc = -EINVAL; + } + return rc; +} + +int32_t camera_io_dev_read(struct camera_io_master *io_master_info, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + if (!io_master_info) { + CAM_ERR(CAM_SENSOR, "Invalid Args"); + return -EINVAL; + } + + if (io_master_info->master_type == CCI_MASTER) { + return cam_cci_i2c_read(io_master_info->cci_client, + addr, data, addr_type, data_type); + } else if (io_master_info->master_type == I2C_MASTER) { + return cam_qup_i2c_read(io_master_info->client, + addr, data, addr_type, data_type); + } else if (io_master_info->master_type == SPI_MASTER) { + return cam_spi_read(io_master_info, + addr, data, addr_type, data_type); + } else { + CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", + io_master_info->master_type); + return -EINVAL; + } + return 0; +} + +int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, int32_t num_bytes) +{ + if (io_master_info->master_type == CCI_MASTER) { + return cam_camera_cci_i2c_read_seq(io_master_info->cci_client, + addr, data, addr_type, data_type, num_bytes); + } else if (io_master_info->master_type == I2C_MASTER) { + return cam_qup_i2c_read_seq(io_master_info->client, + addr, data, addr_type, num_bytes); + } else if (io_master_info->master_type == SPI_MASTER) { + return cam_spi_read_seq(io_master_info, + addr, data, addr_type, num_bytes); + } else if (io_master_info->master_type == SPI_MASTER) { + return cam_spi_write_seq(io_master_info, + addr, data, addr_type, num_bytes); + } else { + CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", + io_master_info->master_type); + return -EINVAL; + } + return 0; +} + +int32_t camera_io_dev_write(struct camera_io_master *io_master_info, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + if (!write_setting || !io_master_info) { + CAM_ERR(CAM_SENSOR, + "Input parameters not valid ws: %pK ioinfo: %pK", + write_setting, io_master_info); + return -EINVAL; + } + + if (!write_setting->reg_setting) { + CAM_ERR(CAM_SENSOR, "Invalid Register Settings"); + return -EINVAL; + } + + if (io_master_info->master_type == CCI_MASTER) { + return cam_cci_i2c_write_table(io_master_info, + write_setting); + } else if (io_master_info->master_type == I2C_MASTER) { + return cam_qup_i2c_write_table(io_master_info, + write_setting); + } else if (io_master_info->master_type == SPI_MASTER) { + return cam_spi_write_table(io_master_info, + write_setting); + } else { + CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", + io_master_info->master_type); + return -EINVAL; + } +} + +int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info, + struct cam_sensor_i2c_reg_setting *write_setting, + uint8_t cam_sensor_i2c_write_flag) +{ + if (!write_setting || !io_master_info) { + CAM_ERR(CAM_SENSOR, + "Input parameters not valid ws: %pK ioinfo: %pK", + write_setting, io_master_info); + return -EINVAL; + } + + if (!write_setting->reg_setting) { + CAM_ERR(CAM_SENSOR, "Invalid Register Settings"); + return -EINVAL; + } + + if (io_master_info->master_type == CCI_MASTER) { + return cam_cci_i2c_write_continuous_table(io_master_info, + write_setting, cam_sensor_i2c_write_flag); + } else if (io_master_info->master_type == I2C_MASTER) { + return cam_qup_i2c_write_continuous_table(io_master_info, + write_setting, cam_sensor_i2c_write_flag); + } else if (io_master_info->master_type == SPI_MASTER) { + return cam_spi_write_table(io_master_info, + write_setting); + } else { + CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d", + io_master_info->master_type); + return -EINVAL; + } +} + +int32_t camera_io_init(struct camera_io_master *io_master_info) +{ + if (!io_master_info) { + CAM_ERR(CAM_SENSOR, "Invalid Args"); + return -EINVAL; + } + + if (io_master_info->master_type == CCI_MASTER) { + io_master_info->cci_client->cci_subdev = + cam_cci_get_subdev(io_master_info->cci_client->cci_device); + return cam_sensor_cci_i2c_util(io_master_info->cci_client, + MSM_CCI_INIT); + } else if ((io_master_info->master_type == I2C_MASTER) || + (io_master_info->master_type == SPI_MASTER)) { + return 0; + } + + return -EINVAL; +} + +int32_t camera_io_release(struct camera_io_master *io_master_info) +{ + if (!io_master_info) { + CAM_ERR(CAM_SENSOR, "Invalid Args"); + return -EINVAL; + } + + if (io_master_info->master_type == CCI_MASTER) { + return cam_sensor_cci_i2c_util(io_master_info->cci_client, + MSM_CCI_RELEASE); + } else if ((io_master_info->master_type == I2C_MASTER) || + (io_master_info->master_type == SPI_MASTER)) { + return 0; + } + + return -EINVAL; +} diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h new file mode 100644 index 000000000000..3c49212d2d6f --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_IO_H_ +#define _CAM_SENSOR_IO_H_ + +#include + +#include "cam_sensor_cmn_header.h" + +#define CCI_MASTER 1 +#define I2C_MASTER 2 +#define SPI_MASTER 3 + +/** + * @master_type: CCI master type + * @client: I2C client information structure + * @cci_client: CCI client information structure + * @spi_client: SPI client information structure + */ +struct camera_io_master { + int master_type; + struct i2c_client *client; + struct cam_sensor_cci_client *cci_client; + struct cam_sensor_spi_client *spi_client; +}; + +/** + * @io_master_info: I2C/SPI master information + * @addr: I2C address + * @data: I2C data + * @addr_type: I2C addr_type + * @data_type: I2C data type + * + * This API abstracts read functionality based on master type + */ +int32_t camera_io_dev_read(struct camera_io_master *io_master_info, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type); + +/** + * @io_master_info: I2C/SPI master information + * @addr: I2C address + * @data: I2C data + * @addr_type: I2C addr type + * @data_type: I2C data type + * @num_bytes: number of bytes + * + * This API abstracts read functionality based on master type + */ +int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + int32_t num_bytes); + +/** + * @io_master_info: I2C/SPI master information + * + * This API initializes the I2C/SPI master based on master type + */ +int32_t camera_io_init(struct camera_io_master *io_master_info); + +/** + * @io_master_info: I2C/SPI master information + * + * This API releases the I2C/SPI master based on master type + */ +int32_t camera_io_release(struct camera_io_master *io_master_info); + +/** + * @io_master_info: I2C/SPI master information + * @write_setting: write settings information + * + * This API abstracts write functionality based on master type + */ +int32_t camera_io_dev_write(struct camera_io_master *io_master_info, + struct cam_sensor_i2c_reg_setting *write_setting); + +/** + * @io_master_info: I2C/SPI master information + * @write_setting: write settings information + * @cam_sensor_i2c_write_flag: differentiate between burst & seq + * + * This API abstracts write functionality based on master type and + * write flag for continuous write + */ +int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info, + struct cam_sensor_i2c_reg_setting *write_setting, + uint8_t cam_sensor_i2c_write_flag); + +int32_t camera_io_dev_erase(struct camera_io_master *io_master_info, + uint32_t addr, uint32_t size); +/** + * @io_master_info: I2C/SPI master information + * @addr: I2C address + * @data: I2C data + * @data_mask: I2C data mask + * @data_type: I2C data type + * @addr_type: I2C address type + * @delay_ms: delay in milli seconds + * + * This API abstracts poll functionality based on master type + */ +int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, + uint32_t addr, uint16_t data, uint32_t data_mask, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t delay_ms); + +#include "cam_sensor_i2c.h" +#include "cam_sensor_spi.h" +#endif /* _CAM_SENSOR_IO_H_ */ diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c new file mode 100644 index 000000000000..a9fd0881aabf --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c @@ -0,0 +1,530 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_sensor_cmn_header.h" +#include "cam_sensor_i2c.h" +#include "cam_sensor_io.h" + +#define I2C_REG_DATA_MAX (8*1024) +#define I2C_REG_MAX_BUF_SIZE 8 + +static int32_t cam_qup_i2c_rxdata( + struct i2c_client *dev_client, unsigned char *rxdata, + enum camera_sensor_i2c_type addr_type, + int data_length) +{ + int32_t rc = 0; + uint16_t saddr = dev_client->addr >> 1; + struct i2c_msg msgs[] = { + { + .addr = saddr, + .flags = 0, + .len = addr_type, + .buf = rxdata, + }, + { + .addr = saddr, + .flags = I2C_M_RD, + .len = data_length, + .buf = rxdata, + }, + }; + rc = i2c_transfer(dev_client->adapter, msgs, 2); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); + return rc; +} + + +static int32_t cam_qup_i2c_txdata( + struct camera_io_master *dev_client, unsigned char *txdata, + int length) +{ + int32_t rc = 0; + uint16_t saddr = dev_client->client->addr >> 1; + struct i2c_msg msg[] = { + { + .addr = saddr, + .flags = 0, + .len = length, + .buf = txdata, + }, + }; + rc = i2c_transfer(dev_client->client->adapter, msg, 1); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); + return rc; +} + +int32_t cam_qup_i2c_read(struct i2c_client *client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + int32_t rc = -EINVAL; + unsigned char *buf = NULL; + + if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { + CAM_ERR(CAM_SENSOR, "Failed with addr/data_type verfication"); + return rc; + } + + buf = kzalloc(addr_type + data_type, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = addr >> 8; + buf[1] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = addr >> 16; + buf[1] = addr >> 8; + buf[2] = addr; + } else { + buf[0] = addr >> 24; + buf[1] = addr >> 16; + buf[2] = addr >> 8; + buf[3] = addr; + } + + rc = cam_qup_i2c_rxdata(client, buf, addr_type, data_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + goto read_fail; + } + + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) + *data = buf[0]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) + *data = buf[0] << 8 | buf[1]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) + *data = buf[0] << 16 | buf[1] << 8 | buf[2]; + else + *data = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3]; + + CAM_DBG(CAM_SENSOR, "addr = 0x%x data: 0x%x", addr, *data); +read_fail: + kfree(buf); + buf = NULL; + return rc; +} + +int32_t cam_qup_i2c_read_seq(struct i2c_client *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint32_t num_byte) +{ + int32_t rc = -EFAULT; + unsigned char *buf = NULL; + int i; + + if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { + CAM_ERR(CAM_SENSOR, "Failed with addr_type verification"); + return rc; + } + + if ((num_byte == 0) || (num_byte > I2C_REG_DATA_MAX)) { + CAM_ERR(CAM_SENSOR, "num_byte:0x%x max supported:0x%x", + num_byte, I2C_REG_DATA_MAX); + return rc; + } + + buf = kzalloc(addr_type + num_byte, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = addr >> BITS_PER_BYTE; + buf[1] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = addr >> 16; + buf[1] = addr >> 8; + buf[2] = addr; + } else { + buf[0] = addr >> 24; + buf[1] = addr >> 16; + buf[2] = addr >> 8; + buf[3] = addr; + } + + rc = cam_qup_i2c_rxdata(client, buf, addr_type, num_byte); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + goto read_seq_fail; + } + + for (i = 0; i < num_byte; i++) + data[i] = buf[i]; + +read_seq_fail: + kfree(buf); + buf = NULL; + return rc; +} + +static int32_t cam_qup_i2c_compare(struct i2c_client *client, + uint32_t addr, uint32_t data, uint16_t data_mask, + enum camera_sensor_i2c_type data_type, + enum camera_sensor_i2c_type addr_type) +{ + int32_t rc; + uint32_t reg_data = 0; + + rc = cam_qup_i2c_read(client, addr, ®_data, + addr_type, data_type); + if (rc < 0) + return rc; + + reg_data = reg_data & 0xFFFF; + if (data != (reg_data & ~data_mask)) + return I2C_COMPARE_MISMATCH; + + return I2C_COMPARE_MATCH; +} + +int32_t cam_qup_i2c_poll(struct i2c_client *client, + uint32_t addr, uint16_t data, uint16_t data_mask, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type, + uint32_t delay_ms) +{ + int32_t rc = 0; + int i = 0; + + if ((delay_ms > MAX_POLL_DELAY_MS) || (delay_ms == 0)) { + CAM_ERR(CAM_SENSOR, "invalid delay = %d max_delay = %d", + delay_ms, MAX_POLL_DELAY_MS); + return -EINVAL; + } + + if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) + return -EINVAL; + + for (i = 0; i < delay_ms; i++) { + rc = cam_qup_i2c_compare(client, + addr, data, data_mask, data_type, addr_type); + if (rc == I2C_COMPARE_MATCH) + return rc; + + usleep_range(1000, 1010); + } + /* If rc is MISMATCH then read is successful but poll is failure */ + if (rc == I2C_COMPARE_MISMATCH) + CAM_ERR(CAM_SENSOR, "poll failed rc=%d(non-fatal)", rc); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "poll failed rc=%d", rc); + + return rc; +} + +static int32_t cam_qup_i2c_write(struct camera_io_master *client, + struct cam_sensor_i2c_reg_array *reg_setting, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + int32_t rc = 0; + unsigned char *buf = NULL; + uint8_t len = 0; + + buf = kzalloc(I2C_REG_MAX_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (!buf) { + CAM_ERR(CAM_SENSOR, "Buffer memory allocation failed"); + return -ENOMEM; + } + + CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d", + reg_setting->reg_addr, data_type); + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + len = 1; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = reg_setting->reg_addr >> 8; + buf[1] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]); + len = 2; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = reg_setting->reg_addr >> 16; + buf[1] = reg_setting->reg_addr >> 8; + buf[2] = reg_setting->reg_addr; + len = 3; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[0] = reg_setting->reg_addr >> 24; + buf[1] = reg_setting->reg_addr >> 16; + buf[2] = reg_setting->reg_addr >> 8; + buf[3] = reg_setting->reg_addr; + len = 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid I2C addr type"); + rc = -EINVAL; + goto deallocate_buffer; + } + + CAM_DBG(CAM_SENSOR, "Data: 0x%x", reg_setting->reg_data); + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[len] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + len += 1; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[len] = reg_setting->reg_data >> 8; + buf[len+1] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]); + len += 2; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[len] = reg_setting->reg_data >> 16; + buf[len + 1] = reg_setting->reg_data >> 8; + buf[len + 2] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]); + len += 3; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[len] = reg_setting->reg_data >> 24; + buf[len + 1] = reg_setting->reg_data >> 16; + buf[len + 2] = reg_setting->reg_data >> 8; + buf[len + 3] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]); + CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+3, buf[len+3]); + len += 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid Data Type"); + rc = -EINVAL; + goto deallocate_buffer; + } + + rc = cam_qup_i2c_txdata(client, buf, len); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + +deallocate_buffer: + kfree(buf); + return rc; +} + +int32_t cam_qup_i2c_write_table(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int32_t rc = -EINVAL; + struct cam_sensor_i2c_reg_array *reg_setting; + + if (!client || !write_setting) + return rc; + + if ((write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || (write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))) + return rc; + + reg_setting = write_setting->reg_setting; + + for (i = 0; i < write_setting->size; i++) { + CAM_DBG(CAM_SENSOR, "addr 0x%x data 0x%x", + reg_setting->reg_addr, reg_setting->reg_data); + + rc = cam_qup_i2c_write(client, reg_setting, + write_setting->addr_type, write_setting->data_type); + if (rc < 0) + break; + reg_setting++; + } + + if (write_setting->delay > 20) + msleep(write_setting->delay); + else if (write_setting->delay) + usleep_range(write_setting->delay * 1000, (write_setting->delay + * 1000) + 1000); + + return rc; +} + +static int32_t cam_qup_i2c_write_seq(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int32_t rc = 0; + struct cam_sensor_i2c_reg_array *reg_setting; + + reg_setting = write_setting->reg_setting; + + for (i = 0; i < write_setting->size; i++) { + reg_setting->reg_addr += i; + rc = cam_qup_i2c_write(client, reg_setting, + write_setting->addr_type, write_setting->data_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Sequential i2c write failed: rc: %d", rc); + break; + } + reg_setting++; + } + + if (write_setting->delay > 20) + msleep(write_setting->delay); + else if (write_setting->delay) + usleep_range(write_setting->delay * 1000, (write_setting->delay + * 1000) + 1000); + + return rc; +} + +static int32_t cam_qup_i2c_write_burst(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int32_t rc = 0; + uint32_t len = 0; + unsigned char *buf = NULL; + struct cam_sensor_i2c_reg_array *reg_setting; + enum camera_sensor_i2c_type addr_type; + enum camera_sensor_i2c_type data_type; + + buf = kzalloc((write_setting->addr_type + + (write_setting->size * write_setting->data_type)), + GFP_KERNEL); + + if (!buf) { + CAM_ERR(CAM_SENSOR, "BUF is NULL"); + return -ENOMEM; + } + + reg_setting = write_setting->reg_setting; + addr_type = write_setting->addr_type; + data_type = write_setting->data_type; + + CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d", + reg_setting->reg_addr, data_type); + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + len = 1; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = reg_setting->reg_addr >> 8; + buf[1] = reg_setting->reg_addr; + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]); + len = 2; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = reg_setting->reg_addr >> 16; + buf[1] = reg_setting->reg_addr >> 8; + buf[2] = reg_setting->reg_addr; + len = 3; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[0] = reg_setting->reg_addr >> 24; + buf[1] = reg_setting->reg_addr >> 16; + buf[2] = reg_setting->reg_addr >> 8; + buf[3] = reg_setting->reg_addr; + len = 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid I2C addr type"); + rc = -EINVAL; + goto free_res; + } + + for (i = 0; i < write_setting->size; i++) { + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[len] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + len += 1; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[len] = reg_setting->reg_data >> 8; + buf[len+1] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+1, buf[len+1]); + len += 2; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[len] = reg_setting->reg_data >> 16; + buf[len + 1] = reg_setting->reg_data >> 8; + buf[len + 2] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+2, buf[len+2]); + len += 3; + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { + buf[len] = reg_setting->reg_data >> 24; + buf[len + 1] = reg_setting->reg_data >> 16; + buf[len + 2] = reg_setting->reg_data >> 8; + buf[len + 3] = reg_setting->reg_data; + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len, buf[len]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+1, buf[len+1]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+2, buf[len+2]); + CAM_DBG(CAM_SENSOR, + "Byte %d: 0x%x", len+3, buf[len+3]); + len += 4; + } else { + CAM_ERR(CAM_SENSOR, "Invalid Data Type"); + rc = -EINVAL; + goto free_res; + } + reg_setting++; + } + + if (len > (write_setting->addr_type + + (write_setting->size * write_setting->data_type))) { + CAM_ERR(CAM_SENSOR, "Invalid Length: %u | Expected length: %u", + len, (write_setting->addr_type + + (write_setting->size * write_setting->data_type))); + rc = -EINVAL; + goto free_res; + } + + rc = cam_qup_i2c_txdata(client, buf, len); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "failed rc: %d", rc); + +free_res: + kfree(buf); + return rc; +} + +int32_t cam_qup_i2c_write_continuous_table(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_settings, + uint8_t cam_sensor_i2c_write_flag) +{ + int32_t rc = 0; + + if (!client || !write_settings) + return -EINVAL; + + if ((write_settings->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_settings->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || (write_settings->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || write_settings->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))) + return -EINVAL; + + if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_BURST) + rc = cam_qup_i2c_write_burst(client, write_settings); + else if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_SEQ) + rc = cam_qup_i2c_write_seq(client, write_settings); + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c new file mode 100644 index 000000000000..cf6987b09eac --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c @@ -0,0 +1,615 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_sensor_spi.h" +#include "cam_debug_util.h" + +static int cam_spi_txfr(struct spi_device *spi, char *txbuf, + char *rxbuf, int num_byte) +{ + struct spi_transfer txfr; + struct spi_message msg; + + memset(&txfr, 0, sizeof(txfr)); + txfr.tx_buf = txbuf; + txfr.rx_buf = rxbuf; + txfr.len = num_byte; + spi_message_init(&msg); + spi_message_add_tail(&txfr, &msg); + + return spi_sync(spi, &msg); +} + +static int cam_spi_txfr_read(struct spi_device *spi, char *txbuf, + char *rxbuf, int txlen, int rxlen) +{ + struct spi_transfer tx; + struct spi_transfer rx; + struct spi_message m; + + memset(&tx, 0, sizeof(tx)); + memset(&rx, 0, sizeof(rx)); + tx.tx_buf = txbuf; + rx.rx_buf = rxbuf; + tx.len = txlen; + rx.len = rxlen; + spi_message_init(&m); + spi_message_add_tail(&tx, &m); + spi_message_add_tail(&rx, &m); + return spi_sync(spi, &m); +} + +/** + * cam_set_addr() - helper function to set transfer address + * @addr: device address + * @addr_len: the addr field length of an instruction + * @type: type (i.e. byte-length) of @addr + * @str: shifted address output, must be zeroed when passed in + * + * This helper function sets @str based on the addr field length of an + * instruction and the data length. + */ +static void cam_set_addr(uint32_t addr, uint8_t addr_len, + enum camera_sensor_i2c_type addr_type, + char *str) +{ + if (!addr_len) + return; + + if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + str[0] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + str[0] = addr >> 8; + str[1] = addr; + } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { + str[0] = addr >> 16; + str[1] = addr >> 8; + str[2] = addr; + } else { + str[0] = addr >> 24; + str[1] = addr >> 16; + str[2] = addr >> 8; + str[3] = addr; + } +} + +/** + * cam_spi_tx_helper() - wrapper for SPI transaction + * @client: io client + * @inst: inst of this transaction + * @addr: device addr following the inst + * @data: output byte array (could be NULL) + * @num_byte: size of @data + * @tx, rx: optional transfer buffer. It must be at least header + * + @num_byte long. + * + * This is the core function for SPI transaction, except for writes. It first + * checks address type, then allocates required memory for tx/rx buffers. + * It sends out , and optionally receives @num_byte of response, + * if @data is not NULL. This function does not check for wait conditions, + * and will return immediately once bus transaction finishes. + * + * This function will allocate buffers of header + @num_byte long. For + * large transfers, the allocation could fail. External buffer @tx, @rx + * should be passed in to bypass allocation. The size of buffer should be + * at least header + num_byte long. Since buffer is managed externally, + * @data will be ignored, and read results will be in @rx. + * @tx, @rx also can be used for repeated transfers to improve performance. + */ +static int32_t cam_spi_tx_helper(struct camera_io_master *client, + struct cam_camera_spi_inst *inst, uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint32_t num_byte, char *tx, char *rx) +{ + int32_t rc = -EINVAL; + struct spi_device *spi = client->spi_client->spi_master; + struct device *dev = NULL; + char *ctx = NULL, *crx = NULL; + uint32_t len, hlen; + uint8_t retries = client->spi_client->retries; + uint32_t txr = 0, rxr = 0; + struct page *page_tx = NULL, *page_rx = NULL; + + hlen = cam_camera_spi_get_hlen(inst); + len = hlen + num_byte; + dev = &(spi->dev); + + if (!dev) { + CAM_ERR(CAM_SENSOR, "Invalid arguments"); + return -EINVAL; + } + + if (tx) { + ctx = tx; + } else { + txr = PAGE_ALIGN(len) >> PAGE_SHIFT; + page_tx = cma_alloc(dev_get_cma_area(dev), + txr, 0, GFP_KERNEL); + if (!page_tx) + return -ENOMEM; + + ctx = page_address(page_tx); + } + + if (num_byte) { + if (rx) { + crx = rx; + } else { + rxr = PAGE_ALIGN(len) >> PAGE_SHIFT; + page_rx = cma_alloc(dev_get_cma_area(dev), + rxr, 0, GFP_KERNEL); + if (!page_rx) { + if (!tx) + cma_release(dev_get_cma_area(dev), + page_tx, txr); + + return -ENOMEM; + } + crx = page_address(page_rx); + } + } else { + crx = NULL; + } + + ctx[0] = inst->opcode; + cam_set_addr(addr, inst->addr_len, addr_type, ctx + 1); + while ((rc = cam_spi_txfr(spi, ctx, crx, len)) && retries) { + retries--; + msleep(client->spi_client->retry_delay); + } + if (rc < 0) { + CAM_ERR(CAM_EEPROM, "failed: spi txfr rc %d", rc); + goto out; + } + if (data && num_byte && !rx) + memcpy(data, crx + hlen, num_byte); + +out: + if (!tx) + cma_release(dev_get_cma_area(dev), page_tx, txr); + if (!rx) + cma_release(dev_get_cma_area(dev), page_rx, rxr); + return rc; +} + +static int32_t cam_spi_tx_read(struct camera_io_master *client, + struct cam_camera_spi_inst *inst, uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint32_t num_byte, char *tx, char *rx) +{ + int32_t rc = -EINVAL; + struct spi_device *spi = client->spi_client->spi_master; + char *ctx = NULL, *crx = NULL; + uint32_t hlen; + uint8_t retries = client->spi_client->retries; + + hlen = cam_camera_spi_get_hlen(inst); + if (tx) { + ctx = tx; + } else { + ctx = kzalloc(hlen, GFP_KERNEL | GFP_DMA); + if (!ctx) + return -ENOMEM; + } + if (num_byte) { + if (rx) { + crx = rx; + } else { + crx = kzalloc(num_byte, GFP_KERNEL | GFP_DMA); + if (!crx) { + if (!tx) + kfree(ctx); + return -ENOMEM; + } + } + } else { + crx = NULL; + } + + ctx[0] = inst->opcode; + cam_set_addr(addr, inst->addr_len, addr_type, ctx + 1); + + CAM_DBG(CAM_EEPROM, "tx(%u): %02x %02x %02x %02x", hlen, ctx[0], + ctx[1], ctx[2], ctx[3]); + while ((rc = cam_spi_txfr_read(spi, ctx, crx, hlen, num_byte)) + && retries) { + retries--; + msleep(client->spi_client->retry_delay); + } + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + goto out; + } + if (data && num_byte && !rx) + memcpy(data, crx, num_byte); +out: + if (!tx) + kfree(ctx); + if (!rx) + kfree(crx); + return rc; +} + +int cam_spi_read(struct camera_io_master *client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + int rc = -EINVAL; + uint8_t temp[CAMERA_SENSOR_I2C_TYPE_MAX]; + + if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX + || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID + || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { + CAM_ERR(CAM_SENSOR, "Failed with addr/data_type verification"); + return rc; + } + + rc = cam_spi_tx_read(client, + &client->spi_client->cmd_tbl.read, addr, &temp[0], + addr_type, data_type, NULL, NULL); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + return rc; + } + + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) + *data = temp[0]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) + *data = (temp[0] << BITS_PER_BYTE) | temp[1]; + else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) + *data = (temp[0] << 16 | temp[1] << 8 | temp[2]); + else + *data = (temp[0] << 24 | temp[1] << 16 | temp[2] << 8 | + temp[3]); + + CAM_DBG(CAM_SENSOR, "addr 0x%x, data %u", addr, *data); + return rc; +} + +int32_t cam_spi_read_seq(struct camera_io_master *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, int32_t num_bytes) +{ + if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) { + CAM_ERR(CAM_SENSOR, "Failed with addr_type verification"); + return -EINVAL; + } + + if (num_bytes == 0) { + CAM_ERR(CAM_SENSOR, "num_byte: 0x%x", num_bytes); + return -EINVAL; + } + + CAM_DBG(CAM_SENSOR, "Read Seq addr: 0x%x NB:%d", + addr, num_bytes); + return cam_spi_tx_helper(client, + &client->spi_client->cmd_tbl.read_seq, addr, data, + addr_type, num_bytes, NULL, NULL); +} + +int cam_spi_query_id(struct camera_io_master *client, + uint32_t addr, enum camera_sensor_i2c_type addr_type, + uint8_t *data, uint32_t num_byte) +{ + CAM_DBG(CAM_SENSOR, "SPI Queryid : 0x%x, addr: 0x%x", + client->spi_client->cmd_tbl.query_id, addr); + return cam_spi_tx_helper(client, + &client->spi_client->cmd_tbl.query_id, + addr, data, addr_type, num_byte, NULL, NULL); +} + +static int32_t cam_spi_read_status_reg( + struct camera_io_master *client, uint8_t *status, + enum camera_sensor_i2c_type addr_type) +{ + struct cam_camera_spi_inst *rs = + &client->spi_client->cmd_tbl.read_status; + + if (rs->addr_len != 0) { + CAM_ERR(CAM_SENSOR, "not implemented yet"); + return -ENXIO; + } + return cam_spi_tx_helper(client, rs, 0, status, + addr_type, 1, NULL, NULL); +} + +static int32_t cam_spi_device_busy(struct camera_io_master *client, + uint8_t *busy, enum camera_sensor_i2c_type addr_type) +{ + int rc; + uint8_t st = 0; + + rc = cam_spi_read_status_reg(client, &st, addr_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed to read status reg"); + return rc; + } + *busy = st & client->spi_client->busy_mask; + return 0; +} + +static int32_t cam_spi_wait(struct camera_io_master *client, + struct cam_camera_spi_inst *inst, + enum camera_sensor_i2c_type addr_type) +{ + uint8_t busy; + int i, rc; + + CAM_DBG(CAM_SENSOR, "op 0x%x wait start", inst->opcode); + for (i = 0; i < inst->delay_count; i++) { + rc = cam_spi_device_busy(client, &busy, addr_type); + if (rc < 0) + return rc; + if (!busy) + break; + msleep(inst->delay_intv); + CAM_DBG(CAM_SENSOR, "op 0x%x wait", inst->opcode); + } + if (i > inst->delay_count) { + CAM_ERR(CAM_SENSOR, "op %x timed out", inst->opcode); + return -ETIMEDOUT; + } + CAM_DBG(CAM_SENSOR, "op %x finished", inst->opcode); + return 0; +} + +static int32_t cam_spi_write_enable(struct camera_io_master *client, + enum camera_sensor_i2c_type addr_type) +{ + struct cam_camera_spi_inst *we = + &client->spi_client->cmd_tbl.write_enable; + int rc; + + if (we->opcode == 0) + return 0; + if (we->addr_len != 0) { + CAM_ERR(CAM_SENSOR, "not implemented yet"); + return -EINVAL; + } + rc = cam_spi_tx_helper(client, we, 0, NULL, addr_type, + 0, NULL, NULL); + if (rc < 0) + CAM_ERR(CAM_SENSOR, "write enable failed"); + return rc; +} + +/** + * cam_spi_page_program() - core function to perform write + * @client: need for obtaining SPI device + * @addr: address to program on device + * @data: data to write + * @len: size of data + * @tx: tx buffer, size >= header + len + * + * This function performs SPI write, and has no boundary check. Writing range + * should not cross page boundary, or data will be corrupted. Transaction is + * guaranteed to be finished when it returns. This function should never be + * used outside cam_spi_write_seq(). + */ +static int32_t cam_spi_page_program(struct camera_io_master *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + uint16_t len, uint8_t *tx) +{ + int rc; + struct cam_camera_spi_inst *pg = + &client->spi_client->cmd_tbl.page_program; + struct spi_device *spi = client->spi_client->spi_master; + uint8_t retries = client->spi_client->retries; + uint8_t header_len = sizeof(pg->opcode) + pg->addr_len + pg->dummy_len; + + CAM_DBG(CAM_SENSOR, "addr 0x%x, size 0x%x", addr, len); + rc = cam_spi_write_enable(client, addr_type); + if (rc < 0) + return rc; + memset(tx, 0, header_len); + tx[0] = pg->opcode; + cam_set_addr(addr, pg->addr_len, addr_type, tx + 1); + memcpy(tx + header_len, data, len); + CAM_DBG(CAM_SENSOR, "tx(%u): %02x %02x %02x %02x", + len, tx[0], tx[1], tx[2], tx[3]); + while ((rc = spi_write(spi, tx, len + header_len)) && retries) { + rc = cam_spi_wait(client, pg, addr_type); + msleep(client->spi_client->retry_delay); + retries--; + } + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed %d", rc); + return rc; + } + rc = cam_spi_wait(client, pg, addr_type); + return rc; +} + +int cam_spi_write(struct camera_io_master *client, + uint32_t addr, uint32_t data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type) +{ + struct cam_camera_spi_inst *pg = + &client->spi_client->cmd_tbl.page_program; + uint8_t header_len = sizeof(pg->opcode) + pg->addr_len + pg->dummy_len; + uint16_t len = 0; + char buf[CAMERA_SENSOR_I2C_TYPE_MAX]; + char *tx; + int rc = -EINVAL; + + if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + || (data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (data_type != CAMERA_SENSOR_I2C_TYPE_MAX)) + return rc; + + CAM_DBG(CAM_EEPROM, "Data: 0x%x", data); + len = header_len + (uint8_t)data_type; + tx = kmalloc(len, GFP_KERNEL | GFP_DMA); + if (!tx) + goto NOMEM; + + if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { + buf[0] = data; + CAM_DBG(CAM_EEPROM, "Byte %d: 0x%x", len, buf[0]); + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + buf[0] = (data >> BITS_PER_BYTE) & 0x00FF; + buf[1] = (data & 0x00FF); + } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { + buf[0] = (data >> 16) & 0x00FF; + buf[1] = (data >> 8) & 0x00FF; + buf[2] = (data & 0x00FF); + } else { + buf[0] = (data >> 24) & 0x00FF; + buf[1] = (data >> 16) & 0x00FF; + buf[2] = (data >> 8) & 0x00FF; + buf[3] = (data & 0x00FF); + } + + rc = cam_spi_page_program(client, addr, buf, + addr_type, data_type, tx); + if (rc < 0) + goto ERROR; + goto OUT; +NOMEM: + CAM_ERR(CAM_SENSOR, "memory allocation failed"); + return -ENOMEM; +ERROR: + CAM_ERR(CAM_SENSOR, "error write"); +OUT: + kfree(tx); + return rc; +} + +int32_t cam_spi_write_seq(struct camera_io_master *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, uint32_t num_byte) +{ + struct cam_camera_spi_inst *pg = + &client->spi_client->cmd_tbl.page_program; + const uint32_t page_size = client->spi_client->page_size; + uint8_t header_len = sizeof(pg->opcode) + pg->addr_len + pg->dummy_len; + uint16_t len; + uint32_t cur_len, end; + char *tx, *pdata = data; + int rc = -EINVAL; + + if ((addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) || + (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID)) + return rc; + /* single page write */ + if ((addr % page_size) + num_byte <= page_size) { + len = header_len + num_byte; + tx = kmalloc(len, GFP_KERNEL | GFP_DMA); + if (!tx) + goto NOMEM; + rc = cam_spi_page_program(client, addr, data, addr_type, + num_byte, tx); + if (rc < 0) + goto ERROR; + goto OUT; + } + /* multi page write */ + len = header_len + page_size; + tx = kmalloc(len, GFP_KERNEL | GFP_DMA); + if (!tx) + goto NOMEM; + while (num_byte) { + end = min(page_size, (addr % page_size) + num_byte); + cur_len = end - (addr % page_size); + CAM_ERR(CAM_SENSOR, "Addr: 0x%x curr_len: 0x%x pgSize: %d", + addr, cur_len, page_size); + rc = cam_spi_page_program(client, addr, pdata, addr_type, + cur_len, tx); + if (rc < 0) + goto ERROR; + addr += cur_len; + pdata += cur_len; + num_byte -= cur_len; + } + goto OUT; +NOMEM: + pr_err("%s: memory allocation failed\n", __func__); + return -ENOMEM; +ERROR: + pr_err("%s: error write\n", __func__); +OUT: + kfree(tx); + return rc; +} + +int cam_spi_write_table(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + int i; + int rc = -EFAULT; + struct cam_sensor_i2c_reg_array *reg_setting; + uint16_t client_addr_type; + enum camera_sensor_i2c_type addr_type; + + if (!client || !write_setting) + return rc; + + if ((write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) + || (write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID) + || (write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) + return rc; + + reg_setting = write_setting->reg_setting; + client_addr_type = write_setting->addr_type; + addr_type = write_setting->addr_type; + for (i = 0; i < write_setting->size; i++) { + CAM_DBG(CAM_SENSOR, "addr %x data %x", + reg_setting->reg_addr, reg_setting->reg_data); + rc = cam_spi_write(client, + reg_setting->reg_addr, reg_setting->reg_data, + write_setting->addr_type, write_setting->data_type); + if (rc < 0) + break; + reg_setting++; + } + if (write_setting->delay > 20) + msleep(write_setting->delay); + else if (write_setting->delay) + usleep_range(write_setting->delay * 1000, + (write_setting->delay + * 1000) + 1000); + addr_type = client_addr_type; + return rc; +} + +int cam_spi_erase(struct camera_io_master *client, uint32_t addr, + enum camera_sensor_i2c_type addr_type, uint32_t size) +{ + struct cam_camera_spi_inst *se = &client->spi_client->cmd_tbl.erase; + int rc = 0; + uint32_t cur; + uint32_t end = addr + size; + uint32_t erase_size = client->spi_client->erase_size; + + end = addr + size; + for (cur = rounddown(addr, erase_size); cur < end; cur += erase_size) { + CAM_ERR(CAM_SENSOR, "%s: erasing 0x%x size: %d\n", + __func__, cur, erase_size); + rc = cam_spi_write_enable(client, addr_type); + if (rc < 0) + return rc; + rc = cam_spi_tx_helper(client, se, cur, NULL, addr_type, 0, + NULL, NULL); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "%s: erase failed\n", __func__); + return rc; + } + rc = cam_spi_wait(client, se, addr_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "%s: erase timedout\n", __func__); + return rc; + } + } + + return rc; +} diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h new file mode 100644 index 000000000000..7a9c44332c49 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_SPI_H_ +#define _CAM_SENSOR_SPI_H_ + +#include +#include +#include +#include "cam_sensor_i2c.h" + +#define MAX_SPI_SIZE 110 +#define SPI_DYNAMIC_ALLOC + +struct cam_camera_spi_inst { + uint8_t opcode; + uint8_t addr_len; + uint8_t dummy_len; + uint8_t delay_intv; + uint8_t delay_count; +}; + +struct cam_spi_write_burst_data { + u8 data_msb; + u8 data_lsb; +}; + +struct cam_spi_write_burst_packet { + u8 cmd; + u8 addr_msb; + u8 addr_lsb; + struct cam_spi_write_burst_data data_arr[MAX_SPI_SIZE]; +}; + +struct cam_camera_burst_info { + uint32_t burst_addr; + uint32_t burst_start; + uint32_t burst_len; + uint32_t chunk_size; +}; + +struct cam_camera_spi_inst_tbl { + struct cam_camera_spi_inst read; + struct cam_camera_spi_inst read_seq; + struct cam_camera_spi_inst query_id; + struct cam_camera_spi_inst page_program; + struct cam_camera_spi_inst write_enable; + struct cam_camera_spi_inst read_status; + struct cam_camera_spi_inst erase; +}; + +struct cam_sensor_spi_client { + struct spi_device *spi_master; + struct cam_camera_spi_inst_tbl cmd_tbl; + uint8_t device_id0; + uint8_t device_id1; + uint8_t mfr_id0; + uint8_t mfr_id1; + uint8_t retry_delay; + uint8_t retries; + uint8_t busy_mask; + uint16_t page_size; + uint32_t erase_size; +}; +static __always_inline +uint16_t cam_camera_spi_get_hlen(struct cam_camera_spi_inst *inst) +{ + return sizeof(inst->opcode) + inst->addr_len + inst->dummy_len; +} + +int cam_spi_read(struct camera_io_master *client, + uint32_t addr, uint32_t *data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type); + +int cam_spi_read_seq(struct camera_io_master *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, + int32_t num_bytes); + +int cam_spi_query_id(struct camera_io_master *client, + uint32_t addr, + enum camera_sensor_i2c_type addr_type, + uint8_t *data, uint32_t num_byte); + +int cam_spi_write(struct camera_io_master *client, + uint32_t addr, uint32_t data, + enum camera_sensor_i2c_type addr_type, + enum camera_sensor_i2c_type data_type); + +int cam_spi_write_table(struct camera_io_master *client, + struct cam_sensor_i2c_reg_setting *write_setting); + +int cam_spi_erase(struct camera_io_master *client, + uint32_t addr, enum camera_sensor_i2c_type addr_type, + uint32_t size); + +int cam_spi_write_seq(struct camera_io_master *client, + uint32_t addr, uint8_t *data, + enum camera_sensor_i2c_type addr_type, uint32_t num_byte); +#endif diff --git a/drivers/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/cam_sensor_module/cam_sensor_utils/Makefile new file mode 100644 index 000000000000..4813d33a5bc5 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_utils/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(src) + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_util.o diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h new file mode 100644 index 000000000000..a5699342dce0 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -0,0 +1,396 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_CMN_HEADER_ +#define _CAM_SENSOR_CMN_HEADER_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_REGULATOR 5 +#define MAX_POWER_CONFIG 12 + +#define MAX_PER_FRAME_ARRAY 32 +#define BATCH_SIZE_MAX 16 + +#define CAM_SENSOR_NAME "cam-sensor" +#define CAM_ACTUATOR_NAME "cam-actuator" +#define CAM_CSIPHY_NAME "cam-csiphy" +#define CAM_FLASH_NAME "cam-flash" +#define CAM_EEPROM_NAME "cam-eeprom" +#define CAM_OIS_NAME "cam-ois" + +#define MAX_SYSTEM_PIPELINE_DELAY 2 + +#define CAM_PKT_NOP_OPCODE 127 + +enum camera_sensor_cmd_type { + CAMERA_SENSOR_CMD_TYPE_INVALID, + CAMERA_SENSOR_CMD_TYPE_PROBE, + CAMERA_SENSOR_CMD_TYPE_PWR_UP, + CAMERA_SENSOR_CMD_TYPE_PWR_DOWN, + CAMERA_SENSOR_CMD_TYPE_I2C_INFO, + CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR, + CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD, + CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR, + CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD, + CAMERA_SENSOR_CMD_TYPE_WAIT, + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO, + CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE, + CAMERA_SENSOR_FLASH_CMD_TYPE_RER, + CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR, + CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET, + CAMERA_SENSOR_CMD_TYPE_RD_DATA, + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE, + CAMERA_SENSOR_CMD_TYPE_MAX, +}; + +enum camera_sensor_i2c_op_code { + CAMERA_SENSOR_I2C_OP_INVALID, + CAMERA_SENSOR_I2C_OP_RNDM_WR, + CAMERA_SENSOR_I2C_OP_RNDM_WR_VERF, + CAMERA_SENSOR_I2C_OP_CONT_WR_BRST, + CAMERA_SENSOR_I2C_OP_CONT_WR_BRST_VERF, + CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN, + CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN_VERF, + CAMERA_SENSOR_I2C_OP_MAX, +}; + +enum camera_sensor_wait_op_code { + CAMERA_SENSOR_WAIT_OP_INVALID, + CAMERA_SENSOR_WAIT_OP_COND, + CAMERA_SENSOR_WAIT_OP_HW_UCND, + CAMERA_SENSOR_WAIT_OP_SW_UCND, + CAMERA_SENSOR_WAIT_OP_MAX, +}; + +enum camera_flash_opcode { + CAMERA_SENSOR_FLASH_OP_INVALID, + CAMERA_SENSOR_FLASH_OP_OFF, + CAMERA_SENSOR_FLASH_OP_FIRELOW, + CAMERA_SENSOR_FLASH_OP_FIREHIGH, + CAMERA_SENSOR_FLASH_OP_MAX, +}; + +enum camera_sensor_i2c_type { + CAMERA_SENSOR_I2C_TYPE_INVALID, + CAMERA_SENSOR_I2C_TYPE_BYTE, + CAMERA_SENSOR_I2C_TYPE_WORD, + CAMERA_SENSOR_I2C_TYPE_3B, + CAMERA_SENSOR_I2C_TYPE_DWORD, + CAMERA_SENSOR_I2C_TYPE_MAX, +}; + +enum i2c_freq_mode { + I2C_STANDARD_MODE, + I2C_FAST_MODE, + I2C_CUSTOM_MODE, + I2C_FAST_PLUS_MODE, + I2C_MAX_MODES, +}; + +enum position_roll { + ROLL_0 = 0, + ROLL_90 = 90, + ROLL_180 = 180, + ROLL_270 = 270, + ROLL_INVALID = 360, +}; + +enum position_yaw { + FRONT_CAMERA_YAW = 0, + REAR_CAMERA_YAW = 180, + INVALID_YAW = 360, +}; + +enum position_pitch { + LEVEL_PITCH = 0, + INVALID_PITCH = 360, +}; + +enum sensor_sub_module { + SUB_MODULE_SENSOR, + SUB_MODULE_ACTUATOR, + SUB_MODULE_EEPROM, + SUB_MODULE_LED_FLASH, + SUB_MODULE_CSID, + SUB_MODULE_CSIPHY, + SUB_MODULE_OIS, + SUB_MODULE_EXT, + SUB_MODULE_MAX, +}; + +enum msm_camera_power_seq_type { + SENSOR_MCLK, + SENSOR_VANA, + SENSOR_VDIG, + SENSOR_VIO, + SENSOR_VAF, + SENSOR_VAF_PWDM, + SENSOR_CUSTOM_REG1, + SENSOR_CUSTOM_REG2, + SENSOR_RESET, + SENSOR_STANDBY, + SENSOR_CUSTOM_GPIO1, + SENSOR_CUSTOM_GPIO2, + SENSOR_SEQ_TYPE_MAX, +}; + +enum cam_sensor_packet_opcodes { + CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON, + CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE, + CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG, + CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE, + CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, + CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF, + CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127 +}; + +enum cam_actuator_packet_opcodes { + CAM_ACTUATOR_PACKET_OPCODE_INIT, + CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS, + CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS +}; + +enum cam_eeprom_packet_opcodes { + CAM_EEPROM_PACKET_OPCODE_INIT, + CAM_EEPROM_WRITE +}; + +enum cam_ois_packet_opcodes { + CAM_OIS_PACKET_OPCODE_INIT, + CAM_OIS_PACKET_OPCODE_OIS_CONTROL +}; + +enum msm_bus_perf_setting { + S_INIT, + S_PREVIEW, + S_VIDEO, + S_CAPTURE, + S_ZSL, + S_STEREO_VIDEO, + S_STEREO_CAPTURE, + S_DEFAULT, + S_LIVESHOT, + S_DUAL, + S_EXIT +}; + +enum msm_camera_device_type_t { + MSM_CAMERA_I2C_DEVICE, + MSM_CAMERA_PLATFORM_DEVICE, + MSM_CAMERA_SPI_DEVICE, +}; + +enum cam_flash_device_type { + CAMERA_FLASH_DEVICE_TYPE_PMIC = 0, + CAMERA_FLASH_DEVICE_TYPE_I2C, + CAMERA_FLASH_DEVICE_TYPE_GPIO, +}; + +enum cci_i2c_master_t { + MASTER_0, + MASTER_1, + MASTER_MAX, +}; + +enum cci_device_num { + CCI_DEVICE_0, + CCI_DEVICE_1, + CCI_DEVICE_MAX, +}; + +enum camera_vreg_type { + VREG_TYPE_DEFAULT, + VREG_TYPE_CUSTOM, +}; + +enum cam_sensor_i2c_cmd_type { + CAM_SENSOR_I2C_WRITE_RANDOM, + CAM_SENSOR_I2C_WRITE_BURST, + CAM_SENSOR_I2C_WRITE_SEQ, + CAM_SENSOR_I2C_READ, + CAM_SENSOR_I2C_POLL +}; + +struct common_header { + uint32_t first_word; + uint8_t fifth_byte; + uint8_t cmd_type; + uint16_t reserved; +}; + +struct camera_vreg_t { + const char *reg_name; + int min_voltage; + int max_voltage; + int op_mode; + uint32_t delay; + const char *custom_vreg_name; + enum camera_vreg_type type; +}; + +struct msm_camera_gpio_num_info { + uint16_t gpio_num[SENSOR_SEQ_TYPE_MAX]; + uint8_t valid[SENSOR_SEQ_TYPE_MAX]; +}; + +struct msm_cam_clk_info { + const char *clk_name; + long clk_rate; + uint32_t delay; +}; + +struct msm_pinctrl_info { + struct pinctrl *pinctrl; + struct pinctrl_state *gpio_state_active; + struct pinctrl_state *gpio_state_suspend; + bool use_pinctrl; +}; + +struct cam_sensor_i2c_reg_array { + uint32_t reg_addr; + uint32_t reg_data; + uint32_t delay; + uint32_t data_mask; +}; + +struct cam_sensor_i2c_reg_setting { + struct cam_sensor_i2c_reg_array *reg_setting; + uint32_t size; + enum camera_sensor_i2c_type addr_type; + enum camera_sensor_i2c_type data_type; + unsigned short delay; +}; + +struct cam_sensor_i2c_seq_reg { + uint32_t reg_addr; + uint8_t *reg_data; + uint32_t size; + enum camera_sensor_i2c_type addr_type; +}; + +struct i2c_settings_list { + struct cam_sensor_i2c_reg_setting i2c_settings; + struct cam_sensor_i2c_seq_reg seq_settings; + enum cam_sensor_i2c_cmd_type op_code; + struct list_head list; +}; + +struct i2c_settings_array { + struct list_head list_head; + int32_t is_settings_valid; + int64_t request_id; +}; + +struct i2c_data_settings { + struct i2c_settings_array init_settings; + struct i2c_settings_array config_settings; + struct i2c_settings_array streamon_settings; + struct i2c_settings_array streamoff_settings; + struct i2c_settings_array *per_frame; +}; + +struct cam_sensor_power_ctrl_t { + struct device *dev; + struct cam_sensor_power_setting *power_setting; + uint16_t power_setting_size; + struct cam_sensor_power_setting *power_down_setting; + uint16_t power_down_setting_size; + struct msm_camera_gpio_num_info *gpio_num_info; + struct msm_pinctrl_info pinctrl_info; + uint8_t cam_pinctrl_status; +}; + +struct cam_camera_slave_info { + uint16_t sensor_slave_addr; + uint16_t sensor_id_reg_addr; + uint16_t sensor_id; + uint16_t sensor_id_mask; +}; + +struct msm_sensor_init_params { + int modes_supported; + unsigned int sensor_mount_angle; +}; + +enum msm_sensor_camera_id_t { + CAMERA_0, + CAMERA_1, + CAMERA_2, + CAMERA_3, + CAMERA_4, + CAMERA_5, + CAMERA_6, + MAX_CAMERAS, +}; + +struct msm_sensor_id_info_t { + unsigned short sensor_id_reg_addr; + unsigned short sensor_id; + unsigned short sensor_id_mask; +}; + +enum msm_sensor_output_format_t { + MSM_SENSOR_BAYER, + MSM_SENSOR_YCBCR, + MSM_SENSOR_META, +}; + +struct cam_sensor_power_setting { + enum msm_camera_power_seq_type seq_type; + unsigned short seq_val; + long config_val; + unsigned short delay; + void *data[10]; +}; + +struct cam_sensor_board_info { + struct cam_camera_slave_info slave_info; + int32_t sensor_mount_angle; + int32_t secure_mode; + int modes_supported; + int32_t pos_roll; + int32_t pos_yaw; + int32_t pos_pitch; + int32_t subdev_id[SUB_MODULE_MAX]; + int32_t subdev_intf[SUB_MODULE_MAX]; + const char *misc_regulator; + struct cam_sensor_power_ctrl_t power_info; +}; + +enum msm_camera_vreg_name_t { + CAM_VDIG, + CAM_VIO, + CAM_VANA, + CAM_VAF, + CAM_V_CUSTOM1, + CAM_V_CUSTOM2, + CAM_VREG_MAX, +}; + +struct msm_camera_gpio_conf { + void *cam_gpiomux_conf_tbl; + uint8_t cam_gpiomux_conf_tbl_size; + struct gpio *cam_gpio_common_tbl; + uint8_t cam_gpio_common_tbl_size; + struct gpio *cam_gpio_req_tbl; + uint8_t cam_gpio_req_tbl_size; + uint32_t gpio_no_mux; + uint32_t *camera_off_table; + uint8_t camera_off_table_size; + uint32_t *camera_on_table; + uint8_t camera_on_table_size; + struct msm_camera_gpio_num_info *gpio_num_info; +}; + +#endif /* _CAM_SENSOR_CMN_HEADER_ */ diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c new file mode 100644 index 000000000000..4a2a2a8855b2 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -0,0 +1,2057 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_sensor_util.h" +#include +#include "cam_res_mgr_api.h" + +#define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend" +#define CAM_SENSOR_PINCTRL_STATE_DEFAULT "cam_default" + +#define VALIDATE_VOLTAGE(min, max, config_val) ((config_val) && \ + (config_val >= min) && (config_val <= max)) + +static struct i2c_settings_list* + cam_sensor_get_i2c_ptr(struct i2c_settings_array *i2c_reg_settings, + uint32_t size) +{ + struct i2c_settings_list *tmp; + + tmp = kzalloc(sizeof(struct i2c_settings_list), GFP_KERNEL); + + if (tmp != NULL) + list_add_tail(&(tmp->list), + &(i2c_reg_settings->list_head)); + else + return NULL; + + tmp->i2c_settings.reg_setting = (struct cam_sensor_i2c_reg_array *) + vzalloc(size * sizeof(struct cam_sensor_i2c_reg_array)); + if (tmp->i2c_settings.reg_setting == NULL) { + list_del(&(tmp->list)); + kfree(tmp); + return NULL; + } + tmp->i2c_settings.size = size; + + return tmp; +} + +int32_t delete_request(struct i2c_settings_array *i2c_array) +{ + struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL; + int32_t rc = 0; + + if (i2c_array == NULL) { + CAM_ERR(CAM_SENSOR, "FATAL:: Invalid argument"); + return -EINVAL; + } + + list_for_each_entry_safe(i2c_list, i2c_next, + &(i2c_array->list_head), list) { + vfree(i2c_list->i2c_settings.reg_setting); + list_del(&(i2c_list->list)); + kfree(i2c_list); + } + INIT_LIST_HEAD(&(i2c_array->list_head)); + i2c_array->is_settings_valid = 0; + + return rc; +} + +int32_t cam_sensor_handle_delay( + uint32_t **cmd_buf, + uint16_t generic_op_code, + struct i2c_settings_array *i2c_reg_settings, + uint32_t offset, uint32_t *byte_cnt, + struct list_head *list_ptr) +{ + int32_t rc = 0; + struct cam_cmd_unconditional_wait *cmd_uncond_wait = + (struct cam_cmd_unconditional_wait *) *cmd_buf; + struct i2c_settings_list *i2c_list = NULL; + + if (list_ptr == NULL) { + CAM_ERR(CAM_SENSOR, "Invalid list ptr"); + return -EINVAL; + } + + if (offset > 0) { + i2c_list = + list_entry(list_ptr, struct i2c_settings_list, list); + if (generic_op_code == + CAMERA_SENSOR_WAIT_OP_HW_UCND) + i2c_list->i2c_settings.reg_setting[offset - 1].delay = + cmd_uncond_wait->delay; + else + i2c_list->i2c_settings.delay = cmd_uncond_wait->delay; + (*cmd_buf) += + sizeof( + struct cam_cmd_unconditional_wait) / sizeof(uint32_t); + (*byte_cnt) += + sizeof( + struct cam_cmd_unconditional_wait); + } else { + CAM_ERR(CAM_SENSOR, "Delay Rxed Before any buffer: %d", offset); + return -EINVAL; + } + + return rc; +} + +int32_t cam_sensor_handle_poll( + uint32_t **cmd_buf, + struct i2c_settings_array *i2c_reg_settings, + uint32_t *byte_cnt, int32_t *offset, + struct list_head **list_ptr) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0; + struct cam_cmd_conditional_wait *cond_wait + = (struct cam_cmd_conditional_wait *) *cmd_buf; + + i2c_list = + cam_sensor_get_i2c_ptr(i2c_reg_settings, 1); + if (!i2c_list || !i2c_list->i2c_settings.reg_setting) { + CAM_ERR(CAM_SENSOR, "Failed in allocating mem for list"); + return -ENOMEM; + } + + i2c_list->op_code = CAM_SENSOR_I2C_POLL; + i2c_list->i2c_settings.data_type = + cond_wait->data_type; + i2c_list->i2c_settings.addr_type = + cond_wait->addr_type; + i2c_list->i2c_settings.reg_setting->reg_addr = + cond_wait->reg_addr; + i2c_list->i2c_settings.reg_setting->reg_data = + cond_wait->reg_data; + i2c_list->i2c_settings.reg_setting->delay = + cond_wait->timeout; + + (*cmd_buf) += sizeof(struct cam_cmd_conditional_wait) / + sizeof(uint32_t); + (*byte_cnt) += sizeof(struct cam_cmd_conditional_wait); + + *offset = 1; + *list_ptr = &(i2c_list->list); + + return rc; +} + +int32_t cam_sensor_handle_random_write( + struct cam_cmd_i2c_random_wr *cam_cmd_i2c_random_wr, + struct i2c_settings_array *i2c_reg_settings, + uint32_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt; + + i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, + cam_cmd_i2c_random_wr->header.count); + if (i2c_list == NULL || + i2c_list->i2c_settings.reg_setting == NULL) { + CAM_ERR(CAM_SENSOR, "Failed in allocating i2c_list"); + return -ENOMEM; + } + + *cmd_length_in_bytes = (sizeof(struct i2c_rdwr_header) + + sizeof(struct i2c_random_wr_payload) * + (cam_cmd_i2c_random_wr->header.count)); + i2c_list->op_code = CAM_SENSOR_I2C_WRITE_RANDOM; + i2c_list->i2c_settings.addr_type = + cam_cmd_i2c_random_wr->header.addr_type; + i2c_list->i2c_settings.data_type = + cam_cmd_i2c_random_wr->header.data_type; + + for (cnt = 0; cnt < (cam_cmd_i2c_random_wr->header.count); + cnt++) { + i2c_list->i2c_settings.reg_setting[cnt].reg_addr = + cam_cmd_i2c_random_wr->random_wr_payload[cnt].reg_addr; + i2c_list->i2c_settings.reg_setting[cnt].reg_data = + cam_cmd_i2c_random_wr->random_wr_payload[cnt].reg_data; + i2c_list->i2c_settings.reg_setting[cnt].data_mask = 0; + } + *offset = cnt; + *list = &(i2c_list->list); + + return rc; +} + +static int32_t cam_sensor_handle_continuous_write( + struct cam_cmd_i2c_continuous_wr *cam_cmd_i2c_continuous_wr, + struct i2c_settings_array *i2c_reg_settings, + uint32_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt; + + i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, + cam_cmd_i2c_continuous_wr->header.count); + if (i2c_list == NULL || + i2c_list->i2c_settings.reg_setting == NULL) { + CAM_ERR(CAM_SENSOR, "Failed in allocating i2c_list"); + return -ENOMEM; + } + + *cmd_length_in_bytes = (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 (cam_cmd_i2c_continuous_wr->header.op_code == + CAMERA_SENSOR_I2C_OP_CONT_WR_BRST) + i2c_list->op_code = CAM_SENSOR_I2C_WRITE_BURST; + else if (cam_cmd_i2c_continuous_wr->header.op_code == + CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN) + i2c_list->op_code = CAM_SENSOR_I2C_WRITE_SEQ; + else + return -EINVAL; + + i2c_list->i2c_settings.addr_type = + cam_cmd_i2c_continuous_wr->header.addr_type; + i2c_list->i2c_settings.data_type = + cam_cmd_i2c_continuous_wr->header.data_type; + i2c_list->i2c_settings.size = + cam_cmd_i2c_continuous_wr->header.count; + + for (cnt = 0; cnt < (cam_cmd_i2c_continuous_wr->header.count); + cnt++) { + i2c_list->i2c_settings.reg_setting[cnt].reg_addr = + cam_cmd_i2c_continuous_wr->reg_addr; + i2c_list->i2c_settings.reg_setting[cnt].reg_data = + cam_cmd_i2c_continuous_wr->data_read[cnt].reg_data; + i2c_list->i2c_settings.reg_setting[cnt].data_mask = 0; + } + *offset = cnt; + *list = &(i2c_list->list); + + return rc; +} + +static int cam_sensor_handle_slave_info( + struct camera_io_master *io_master, + uint32_t *cmd_buf) +{ + int rc = 0; + struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf; + + if (io_master == NULL || cmd_buf == NULL) { + CAM_ERR(CAM_SENSOR, "Invalid args"); + return -EINVAL; + } + + switch (io_master->master_type) { + case CCI_MASTER: + io_master->cci_client->sid = (i2c_info->slave_addr >> 1); + io_master->cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode; + break; + + case I2C_MASTER: + io_master->client->addr = i2c_info->slave_addr; + break; + + case SPI_MASTER: + break; + + default: + CAM_ERR(CAM_SENSOR, "Invalid master type: %d", + io_master->master_type); + rc = -EINVAL; + break; + } + + return rc; +} + +/** + * Name : cam_sensor_i2c_command_parser + * Description : Parse CSL CCI packet and apply register settings + * Parameters : s_ctrl input/output sub_device + * arg input cam_control + * Description : + * Handle multiple I2C RD/WR and WAIT cmd formats in one command + * buffer, for example, a command buffer of m x RND_WR + 1 x HW_ + * WAIT + n x RND_WR with num_cmd_buf = 1. Do not exepect RD/WR + * with different cmd_type and op_code in one command buffer. + */ +int cam_sensor_i2c_command_parser( + struct camera_io_master *io_master, + struct i2c_settings_array *i2c_reg_settings, + struct cam_cmd_buf_desc *cmd_desc, + int32_t num_cmd_buffers) +{ + int16_t rc = 0, i = 0; + 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; + struct common_header *cmm_hdr; + uint16_t generic_op_code; + uint32_t byte_cnt = 0; + uint32_t j = 0; + struct list_head *list = NULL; + + /* + * It is not expected the same settings to + * be spread across multiple cmd buffers + */ + CAM_DBG(CAM_SENSOR, "Total cmd Buf in Bytes: %d", + cmd_desc[i].length); + + if (!cmd_desc[i].length) + continue; + + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &generic_ptr, &len_of_buff); + 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); + + remain_len -= cmd_desc[i].offset; + 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 end; + } + cmm_hdr = (struct common_header *)cmd_buf; + generic_op_code = cmm_hdr->fifth_byte; + switch (cmm_hdr->cmd_type) { + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: { + uint32_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_random_wr + *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 end; + } + 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 end; + } + + rc = cam_sensor_handle_random_write( + cam_cmd_i2c_random_wr, + i2c_reg_settings, + &cmd_length_in_bytes, &j, &list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in random write %d", rc); + rc = -EINVAL; + goto end; + } + + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + break; + } + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR: { + uint32_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_continuous_wr + *cam_cmd_i2c_continuous_wr = + (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"); + rc = -EINVAL; + goto end; + } + + 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"); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_continuous_write( + cam_cmd_i2c_continuous_wr, + i2c_reg_settings, + &cmd_length_in_bytes, &j, &list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in continuous write %d", rc); + goto end; + } + + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + 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"); + rc = -EINVAL; + goto end; + } + 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, + list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "delay hdl failed: %d", + rc); + goto end; + } + + } else if (generic_op_code == + CAMERA_SENSOR_WAIT_OP_COND) { + rc = cam_sensor_handle_poll( + &cmd_buf, i2c_reg_settings, + &byte_cnt, &j, &list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Random read fail: %d", + rc); + goto end; + } + } else { + CAM_ERR(CAM_SENSOR, + "Wrong Wait Command: %d", + generic_op_code); + rc = -EINVAL; + goto end; + } + 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 end; + } + rc = cam_sensor_handle_slave_info( + io_master, cmd_buf); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Handle slave info failed with rc: %d", + rc); + goto end; + } + cmd_length_in_bytes = + sizeof(struct cam_cmd_i2c_info); + cmd_buf += + cmd_length_in_bytes / sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + break; + } + default: + CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d", + cmm_hdr->cmd_type); + rc = -EINVAL; + goto end; + } + } + i2c_reg_settings->is_settings_valid = 1; + } + +end: + return rc; +} + +int cam_sensor_util_i2c_apply_setting( + struct camera_io_master *io_master_info, + struct i2c_settings_list *i2c_list) +{ + int32_t rc = 0; + uint32_t i, size; + + switch (i2c_list->op_code) { + case CAM_SENSOR_I2C_WRITE_RANDOM: { + rc = camera_io_dev_write(io_master_info, + &(i2c_list->i2c_settings)); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to random write I2C settings: %d", + rc); + return rc; + } + break; + } + case CAM_SENSOR_I2C_WRITE_SEQ: { + rc = camera_io_dev_write_continuous( + io_master_info, &(i2c_list->i2c_settings), 0); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to seq write I2C settings: %d", + rc); + return rc; + } + break; + } + case CAM_SENSOR_I2C_WRITE_BURST: { + rc = camera_io_dev_write_continuous( + io_master_info, &(i2c_list->i2c_settings), 1); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to burst write I2C settings: %d", + rc); + return rc; + } + break; + } + case CAM_SENSOR_I2C_POLL: { + size = i2c_list->i2c_settings.size; + for (i = 0; i < size; i++) { + rc = camera_io_dev_poll( + io_master_info, + i2c_list->i2c_settings.reg_setting[i].reg_addr, + i2c_list->i2c_settings.reg_setting[i].reg_data, + i2c_list->i2c_settings.reg_setting[i].data_mask, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.reg_setting[i].delay); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "i2c poll apply setting Fail: %d", rc); + return rc; + } + } + break; + } + default: + CAM_ERR(CAM_SENSOR, "Wrong Opcode: %d", i2c_list->op_code); + rc = -EINVAL; + break; + } + + return rc; +} + +int32_t msm_camera_fill_vreg_params( + struct cam_hw_soc_info *soc_info, + struct cam_sensor_power_setting *power_setting, + uint16_t power_setting_size) +{ + int32_t rc = 0, j = 0, i = 0; + int num_vreg; + + /* Validate input parameters */ + if (!soc_info || !power_setting) { + CAM_ERR(CAM_SENSOR, "failed: soc_info %pK power_setting %pK", + soc_info, power_setting); + return -EINVAL; + } + + num_vreg = soc_info->num_rgltr; + + if ((num_vreg <= 0) || (num_vreg > CAM_SOC_MAX_REGULATOR)) { + CAM_ERR(CAM_SENSOR, "failed: num_vreg %d", num_vreg); + return -EINVAL; + } + + for (i = 0; i < power_setting_size; i++) { + + if (power_setting[i].seq_type < SENSOR_MCLK || + power_setting[i].seq_type >= SENSOR_SEQ_TYPE_MAX) { + CAM_ERR(CAM_SENSOR, "failed: Invalid Seq type: %d", + power_setting[i].seq_type); + return -EINVAL; + } + + switch (power_setting[i].seq_type) { + case SENSOR_VDIG: + for (j = 0; j < num_vreg; j++) { + if (!strcmp(soc_info->rgltr_name[j], + "cam_vdig")) { + + CAM_DBG(CAM_SENSOR, + "i: %d j: %d cam_vdig", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + break; + } + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + + case SENSOR_VIO: + for (j = 0; j < num_vreg; j++) { + + if (!strcmp(soc_info->rgltr_name[j], + "cam_vio")) { + CAM_DBG(CAM_SENSOR, + "i: %d j: %d cam_vio", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + break; + } + + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + + case SENSOR_VANA: + for (j = 0; j < num_vreg; j++) { + + if (!strcmp(soc_info->rgltr_name[j], + "cam_vana")) { + CAM_DBG(CAM_SENSOR, + "i: %d j: %d cam_vana", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + break; + } + + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + + case SENSOR_VAF: + for (j = 0; j < num_vreg; j++) { + + if (!strcmp(soc_info->rgltr_name[j], + "cam_vaf")) { + CAM_DBG(CAM_SENSOR, + "i: %d j: %d cam_vaf", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + + break; + } + + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + + case SENSOR_CUSTOM_REG1: + for (j = 0; j < num_vreg; j++) { + + if (!strcmp(soc_info->rgltr_name[j], + "cam_v_custom1")) { + CAM_DBG(CAM_SENSOR, + "i:%d j:%d cam_vcustom1", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + break; + } + + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + case SENSOR_CUSTOM_REG2: + for (j = 0; j < num_vreg; j++) { + + if (!strcmp(soc_info->rgltr_name[j], + "cam_v_custom2")) { + CAM_DBG(CAM_SENSOR, + "i:%d j:%d cam_vcustom2", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + break; + } + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + default: + break; + } + } + + return rc; +} + +int cam_sensor_util_request_gpio_table( + struct cam_hw_soc_info *soc_info, int gpio_en) +{ + int rc = 0, i = 0; + uint8_t size = 0; + struct cam_soc_gpio_data *gpio_conf = + soc_info->gpio_data; + struct gpio *gpio_tbl = NULL; + + if (!gpio_conf) { + CAM_INFO(CAM_SENSOR, "No GPIO data"); + return 0; + } + + if (gpio_conf->cam_gpio_common_tbl_size <= 0) { + CAM_INFO(CAM_SENSOR, "No GPIO entry"); + return -EINVAL; + } + + gpio_tbl = gpio_conf->cam_gpio_req_tbl; + size = gpio_conf->cam_gpio_req_tbl_size; + + if (!gpio_tbl || !size) { + CAM_ERR(CAM_SENSOR, "invalid gpio_tbl %pK / size %d", + gpio_tbl, size); + return -EINVAL; + } + + for (i = 0; i < size; i++) { + CAM_DBG(CAM_SENSOR, "i: %d, gpio %d dir %ld", i, + gpio_tbl[i].gpio, gpio_tbl[i].flags); + } + + if (gpio_en) { + for (i = 0; i < size; i++) { + rc = cam_res_mgr_gpio_request(soc_info->dev, + gpio_tbl[i].gpio, + gpio_tbl[i].flags, gpio_tbl[i].label); + if (rc) { + /* + * After GPIO request fails, contine to + * apply new gpios, outout a error message + * for driver bringup debug + */ + CAM_ERR(CAM_SENSOR, "gpio %d:%s request fails", + gpio_tbl[i].gpio, gpio_tbl[i].label); + } + } + } else { + cam_res_mgr_gpio_free_arry(soc_info->dev, gpio_tbl, size); + } + + 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, + 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; + struct cam_sensor_power_setting *pwr_settings; + void *ptr = cmd_buf, *scr; + 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 || 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; + } + + power_info->power_setting_size = 0; + power_info->power_setting = + kzalloc(sizeof(struct cam_sensor_power_setting) * + MAX_POWER_CONFIG, GFP_KERNEL); + if (!power_info->power_setting) + return -ENOMEM; + + power_info->power_down_setting_size = 0; + power_info->power_down_setting = + kzalloc(sizeof(struct cam_sensor_power_setting) * + MAX_POWER_CONFIG, GFP_KERNEL); + if (!power_info->power_down_setting) { + kfree(power_info->power_setting); + power_info->power_setting = NULL; + power_info->power_setting_size = 0; + return -ENOMEM; + } + + 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) + || (pwr_cmd->count >= SENSOR_SEQ_TYPE_MAX)) { + CAM_ERR(CAM_SENSOR, + "pwr_up setting size %d, pwr_cmd->count: %d", + power_info->power_setting_size, + pwr_cmd->count); + rc = -EINVAL; + goto free_power_settings; + } + scr = ptr + sizeof(struct cam_cmd_power); + tot_size = tot_size + sizeof(struct cam_cmd_power); + + if (pwr_cmd->count == 0) + CAM_WARN(CAM_SENSOR, "pwr_up_size is zero"); + + for (i = 0; i < pwr_cmd->count; i++, pwr_up++) { + power_info->power_setting[pwr_up].seq_type = + pwr_cmd->power_settings[i].power_seq_type; + power_info->power_setting[pwr_up].config_val = + pwr_cmd->power_settings[i].config_val_low; + power_info->power_setting[pwr_up].delay = 0; + if (i) { + scr = scr + + sizeof( + struct cam_power_settings); + tot_size = tot_size + + sizeof( + struct cam_power_settings); + } + if (tot_size > cmd_length) { + CAM_ERR(CAM_SENSOR, + "Error: Cmd Buffer is wrong"); + rc = -EINVAL; + goto free_power_settings; + } + CAM_DBG(CAM_SENSOR, + "Seq Type[%d]: %d Config_val: %ld", pwr_up, + power_info->power_setting[pwr_up].seq_type, + power_info->power_setting[pwr_up].config_val); + } + last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP; + ptr = (void *) scr; + cmm_hdr = (struct common_header *)ptr; + } else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT) { + struct cam_cmd_unconditional_wait *wait_cmd = + (struct cam_cmd_unconditional_wait *)ptr; + if ((wait_cmd->op_code == + CAMERA_SENSOR_WAIT_OP_SW_UCND) && + (last_cmd_type == + CAMERA_SENSOR_CMD_TYPE_PWR_UP)) { + if (pwr_up > 0) { + pwr_settings = + &power_info->power_setting[pwr_up - 1]; + pwr_settings->delay += + wait_cmd->delay; + } else { + CAM_ERR(CAM_SENSOR, + "Delay is expected only after valid power up setting"); + } + } else if ((wait_cmd->op_code == + CAMERA_SENSOR_WAIT_OP_SW_UCND) && + (last_cmd_type == + CAMERA_SENSOR_CMD_TYPE_PWR_DOWN)) { + if (pwr_down > 0) { + pwr_settings = + &power_info->power_down_setting[ + pwr_down - 1]; + pwr_settings->delay += + wait_cmd->delay; + } else { + CAM_ERR(CAM_SENSOR, + "Delay is expected only after valid power up setting"); + } + } else { + CAM_DBG(CAM_SENSOR, "Invalid op code: %d", + wait_cmd->op_code); + } + + tot_size = tot_size + + sizeof(struct cam_cmd_unconditional_wait); + if (tot_size > cmd_length) { + CAM_ERR(CAM_SENSOR, "Command Buffer is wrong"); + return -EINVAL; + } + scr = (void *) (wait_cmd); + ptr = (void *) + (scr + + sizeof(struct cam_cmd_unconditional_wait)); + CAM_DBG(CAM_SENSOR, "ptr: %pK sizeof: %d Next: %pK", + scr, (int32_t)sizeof( + struct cam_cmd_unconditional_wait), ptr); + + cmm_hdr = (struct common_header *)ptr; + } else if (cmm_hdr->cmd_type == + CAMERA_SENSOR_CMD_TYPE_PWR_DOWN) { + struct cam_cmd_power *pwr_cmd = + (struct cam_cmd_power *)ptr; + + 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) || (pwr_cmd->count >= + SENSOR_SEQ_TYPE_MAX)) { + CAM_ERR(CAM_SENSOR, + "pwr_down_setting_size %d, pwr_cmd->count: %d", + power_info->power_down_setting_size, + pwr_cmd->count); + rc = -EINVAL; + goto free_power_settings; + } + + if (pwr_cmd->count == 0) + CAM_ERR(CAM_SENSOR, "pwr_down size is zero"); + + for (i = 0; i < pwr_cmd->count; i++, pwr_down++) { + pwr_settings = + &power_info->power_down_setting[pwr_down]; + pwr_settings->seq_type = + pwr_cmd->power_settings[i].power_seq_type; + pwr_settings->config_val = + pwr_cmd->power_settings[i].config_val_low; + power_info->power_down_setting[pwr_down].delay + = 0; + if (i) { + scr = scr + + sizeof( + struct cam_power_settings); + tot_size = + tot_size + + sizeof( + struct cam_power_settings); + } + if (tot_size > cmd_length) { + CAM_ERR(CAM_SENSOR, + "Command Buffer is wrong"); + rc = -EINVAL; + goto free_power_settings; + } + CAM_DBG(CAM_SENSOR, + "Seq Type[%d]: %d Config_val: %ld", + pwr_down, pwr_settings->seq_type, + pwr_settings->config_val); + } + last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN; + ptr = (void *) scr; + cmm_hdr = (struct common_header *)ptr; + } else { + CAM_ERR(CAM_SENSOR, + "Error: Un expected Header Type: %d", + cmm_hdr->cmd_type); + rc = -EINVAL; + goto free_power_settings; + } + } + + return rc; +free_power_settings: + kfree(power_info->power_down_setting); + kfree(power_info->power_setting); + power_info->power_down_setting = NULL; + power_info->power_setting = NULL; + power_info->power_down_setting_size = 0; + power_info->power_setting_size = 0; + return rc; +} + +int cam_get_dt_power_setting_data(struct device_node *of_node, + struct cam_hw_soc_info *soc_info, + struct cam_sensor_power_ctrl_t *power_info) +{ + int rc = 0, i; + int count = 0; + const char *seq_name = NULL; + uint32_t *array = NULL; + struct cam_sensor_power_setting *ps; + int c, end; + + if (!power_info) + return -EINVAL; + + count = of_property_count_strings(of_node, "qcom,cam-power-seq-type"); + power_info->power_setting_size = count; + + CAM_DBG(CAM_SENSOR, "qcom,cam-power-seq-type count %d", count); + + if (count <= 0) + return 0; + + ps = kcalloc(count, sizeof(*ps), GFP_KERNEL); + if (!ps) + return -ENOMEM; + power_info->power_setting = ps; + + for (i = 0; i < count; i++) { + rc = of_property_read_string_index(of_node, + "qcom,cam-power-seq-type", i, &seq_name); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed"); + goto ERROR1; + } + CAM_DBG(CAM_SENSOR, "seq_name[%d] = %s", i, seq_name); + if (!strcmp(seq_name, "cam_vio")) { + ps[i].seq_type = SENSOR_VIO; + } else if (!strcmp(seq_name, "cam_vana")) { + ps[i].seq_type = SENSOR_VANA; + } else if (!strcmp(seq_name, "cam_clk")) { + ps[i].seq_type = SENSOR_MCLK; + } else { + CAM_ERR(CAM_SENSOR, "unrecognized seq-type %s", + seq_name); + rc = -EILSEQ; + goto ERROR1; + } + CAM_DBG(CAM_SENSOR, "seq_type[%d] %d", i, ps[i].seq_type); + } + + array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL); + if (!array) { + rc = -ENOMEM; + goto ERROR1; + } + + rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-cfg-val", + array, count); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed "); + goto ERROR2; + } + + for (i = 0; i < count; i++) { + ps[i].config_val = array[i]; + CAM_DBG(CAM_SENSOR, "power_setting[%d].config_val = %ld", i, + ps[i].config_val); + } + + rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-delay", + array, count); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed"); + goto ERROR2; + } + for (i = 0; i < count; i++) { + ps[i].delay = array[i]; + CAM_DBG(CAM_SENSOR, "power_setting[%d].delay = %d", i, + ps[i].delay); + } + kfree(array); + + power_info->power_down_setting = + kcalloc(count, sizeof(*ps), GFP_KERNEL); + + if (!power_info->power_down_setting) { + CAM_ERR(CAM_SENSOR, "failed"); + rc = -ENOMEM; + goto ERROR1; + } + + power_info->power_down_setting_size = count; + + end = count - 1; + + for (c = 0; c < count; c++) { + power_info->power_down_setting[c] = ps[end]; + end--; + } + return rc; +ERROR2: + kfree(array); +ERROR1: + kfree(ps); + return rc; +} + +int cam_sensor_util_init_gpio_pin_tbl( + struct cam_hw_soc_info *soc_info, + struct msm_camera_gpio_num_info **pgpio_num_info) +{ + int rc = 0, val = 0; + uint32_t gpio_array_size; + struct device_node *of_node = NULL; + struct cam_soc_gpio_data *gconf = NULL; + struct msm_camera_gpio_num_info *gpio_num_info = NULL; + + if (!soc_info->dev) { + CAM_ERR(CAM_SENSOR, "device node NULL"); + return -EINVAL; + } + + of_node = soc_info->dev->of_node; + + gconf = soc_info->gpio_data; + if (!gconf) { + CAM_ERR(CAM_SENSOR, "No gpio_common_table is found"); + return -EINVAL; + } + + if (!gconf->cam_gpio_common_tbl) { + CAM_ERR(CAM_SENSOR, "gpio_common_table is not initialized"); + return -EINVAL; + } + + gpio_array_size = gconf->cam_gpio_common_tbl_size; + + if (!gpio_array_size) { + CAM_ERR(CAM_SENSOR, "invalid size of gpio table"); + return -EINVAL; + } + + *pgpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info), + GFP_KERNEL); + if (!*pgpio_num_info) + return -ENOMEM; + gpio_num_info = *pgpio_num_info; + + rc = of_property_read_u32(of_node, "gpio-vana", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "read gpio-vana failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-vana invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_VANA] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_VANA] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-vana %d", + gpio_num_info->gpio_num[SENSOR_VANA]); + } + + rc = of_property_read_u32(of_node, "gpio-vio", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "read gpio-vio failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-vio invalid %d", val); + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_VIO] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_VIO] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-vio %d", + gpio_num_info->gpio_num[SENSOR_VIO]); + } + + rc = of_property_read_u32(of_node, "gpio-vaf", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "read gpio-vaf failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-vaf invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_VAF] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_VAF] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-vaf %d", + gpio_num_info->gpio_num[SENSOR_VAF]); + } + + rc = of_property_read_u32(of_node, "gpio-vdig", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "read gpio-vdig failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-vdig invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_VDIG] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_VDIG] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-vdig %d", + gpio_num_info->gpio_num[SENSOR_VDIG]); + } + + rc = of_property_read_u32(of_node, "gpio-reset", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "read gpio-reset failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-reset invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_RESET] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_RESET] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-reset %d", + gpio_num_info->gpio_num[SENSOR_RESET]); + } + + rc = of_property_read_u32(of_node, "gpio-standby", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "read gpio-standby failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-standby invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_STANDBY] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_STANDBY] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-standby %d", + gpio_num_info->gpio_num[SENSOR_STANDBY]); + } + + rc = of_property_read_u32(of_node, "gpio-af-pwdm", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "read gpio-af-pwdm failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-af-pwdm invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_VAF_PWDM] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_VAF_PWDM] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-af-pwdm %d", + gpio_num_info->gpio_num[SENSOR_VAF_PWDM]); + } + + rc = of_property_read_u32(of_node, "gpio-custom1", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "read gpio-custom1 failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-custom1 invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_CUSTOM_GPIO1] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-custom1 %d", + gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1]); + } + + rc = of_property_read_u32(of_node, "gpio-custom2", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "read gpio-custom2 failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-custom2 invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_CUSTOM_GPIO2] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-custom2 %d", + gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2]); + } else { + rc = 0; + } + + return rc; + +free_gpio_info: + kfree(gpio_num_info); + gpio_num_info = NULL; + return rc; +} + +int msm_camera_pinctrl_init( + struct msm_pinctrl_info *sensor_pctrl, struct device *dev) +{ + + sensor_pctrl->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR_OR_NULL(sensor_pctrl->pinctrl)) { + CAM_DBG(CAM_SENSOR, "Getting pinctrl handle failed"); + return -EINVAL; + } + sensor_pctrl->gpio_state_active = + pinctrl_lookup_state(sensor_pctrl->pinctrl, + CAM_SENSOR_PINCTRL_STATE_DEFAULT); + if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_active)) { + CAM_ERR(CAM_SENSOR, + "Failed to get the active state pinctrl handle"); + return -EINVAL; + } + sensor_pctrl->gpio_state_suspend + = pinctrl_lookup_state(sensor_pctrl->pinctrl, + CAM_SENSOR_PINCTRL_STATE_SLEEP); + if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_suspend)) { + CAM_ERR(CAM_SENSOR, + "Failed to get the suspend state pinctrl handle"); + return -EINVAL; + } + + return 0; +} + +int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info, + int bob_reg_idx, bool flag) +{ + int rc = 0; + uint32_t op_current = + (flag == true) ? soc_info->rgltr_op_mode[bob_reg_idx] : 0; + + if (soc_info->rgltr[bob_reg_idx] != NULL) { + rc = regulator_set_load(soc_info->rgltr[bob_reg_idx], + op_current); + if (rc) + CAM_WARN(CAM_SENSOR, + "BoB PWM SetLoad failed rc: %d", rc); + } + + return rc; +} + +int msm_cam_sensor_handle_reg_gpio(int seq_type, + struct msm_camera_gpio_num_info *gpio_num_info, int val) +{ + int gpio_offset = -1; + + if (!gpio_num_info) { + CAM_INFO(CAM_SENSOR, "Input Parameters are not proper"); + return 0; + } + + CAM_DBG(CAM_SENSOR, "Seq type: %d, config: %d", seq_type, val); + + gpio_offset = seq_type; + + if (gpio_num_info->valid[gpio_offset] == 1) { + CAM_DBG(CAM_SENSOR, "VALID GPIO offset: %d, seqtype: %d", + gpio_offset, seq_type); + cam_res_mgr_gpio_set_value( + gpio_num_info->gpio_num + [gpio_offset], val); + } + + return 0; +} + +static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl, + struct cam_hw_soc_info *soc_info, int32_t index) +{ + int32_t num_vreg = 0, j = 0, rc = 0, idx = 0; + struct cam_sensor_power_setting *ps = NULL; + struct cam_sensor_power_setting *pd = NULL; + + num_vreg = soc_info->num_rgltr; + + pd = &ctrl->power_down_setting[index]; + + for (j = 0; j < num_vreg; j++) { + if (!strcmp(soc_info->rgltr_name[j], "cam_clk")) { + ps = NULL; + for (idx = 0; idx < ctrl->power_setting_size; idx++) { + if (ctrl->power_setting[idx].seq_type == + pd->seq_type) { + ps = &ctrl->power_setting[idx]; + break; + } + } + + if (ps != NULL) { + CAM_DBG(CAM_SENSOR, "Disable MCLK Regulator"); + rc = cam_soc_util_regulator_disable( + soc_info->rgltr[j], + soc_info->rgltr_name[j], + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + soc_info->rgltr_op_mode[j], + soc_info->rgltr_delay[j]); + + if (rc) { + CAM_ERR(CAM_SENSOR, + "MCLK REG DISALBE FAILED: %d", + rc); + return rc; + } + + ps->data[0] = + soc_info->rgltr[j]; + + regulator_put( + soc_info->rgltr[j]); + soc_info->rgltr[j] = NULL; + } + } + } + + return rc; +} + +int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, + struct cam_hw_soc_info *soc_info) +{ + int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0, i = 0; + int32_t vreg_idx = -1; + struct cam_sensor_power_setting *power_setting = NULL; + struct msm_camera_gpio_num_info *gpio_num_info = NULL; + + CAM_DBG(CAM_SENSOR, "Enter"); + if (!ctrl) { + CAM_ERR(CAM_SENSOR, "Invalid ctrl handle"); + return -EINVAL; + } + + gpio_num_info = ctrl->gpio_num_info; + num_vreg = soc_info->num_rgltr; + + if ((num_vreg <= 0) || (num_vreg > CAM_SOC_MAX_REGULATOR)) { + CAM_ERR(CAM_SENSOR, "failed: num_vreg %d", num_vreg); + return -EINVAL; + } + + if (soc_info->use_shared_clk) + cam_res_mgr_shared_clk_config(true); + + ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev); + if (ret < 0) { + /* Some sensor subdev no pinctrl. */ + CAM_DBG(CAM_SENSOR, "Initialization of pinctrl failed"); + ctrl->cam_pinctrl_status = 0; + } else { + ctrl->cam_pinctrl_status = 1; + } + + if (cam_res_mgr_shared_pinctrl_init()) { + CAM_ERR(CAM_SENSOR, + "Failed to init shared pinctrl"); + return -EINVAL; + } + + rc = cam_sensor_util_request_gpio_table(soc_info, 1); + if (rc < 0) + no_gpio = rc; + + if (ctrl->cam_pinctrl_status) { + ret = pinctrl_select_state( + ctrl->pinctrl_info.pinctrl, + ctrl->pinctrl_info.gpio_state_active); + if (ret) + CAM_ERR(CAM_SENSOR, "cannot set pin to active state"); + } + + ret = cam_res_mgr_shared_pinctrl_select_state(true); + if (ret) + CAM_ERR(CAM_SENSOR, + "Cannot set shared pin to active state"); + + CAM_DBG(CAM_SENSOR, "power setting size: %d", ctrl->power_setting_size); + + for (index = 0; index < ctrl->power_setting_size; index++) { + CAM_DBG(CAM_SENSOR, "index: %d", index); + power_setting = &ctrl->power_setting[index]; + if (!power_setting) { + CAM_ERR(CAM_SENSOR, + "Invalid power up settings for index %d", + index); + return -EINVAL; + } + + CAM_DBG(CAM_SENSOR, "seq_type %d", power_setting->seq_type); + + switch (power_setting->seq_type) { + case SENSOR_MCLK: + if (power_setting->seq_val >= soc_info->num_clk) { + CAM_ERR(CAM_SENSOR, "clk index %d >= max %u", + power_setting->seq_val, + soc_info->num_clk); + goto power_up_failed; + } + for (j = 0; j < num_vreg; j++) { + if (!strcmp(soc_info->rgltr_name[j], + "cam_clk")) { + CAM_DBG(CAM_SENSOR, + "Enable cam_clk: %d", j); + + soc_info->rgltr[j] = + regulator_get( + soc_info->dev, + soc_info->rgltr_name[j]); + + if (IS_ERR_OR_NULL( + soc_info->rgltr[j])) { + rc = PTR_ERR( + soc_info->rgltr[j]); + rc = rc ? rc : -EINVAL; + CAM_ERR(CAM_SENSOR, + "vreg %s %d", + soc_info->rgltr_name[j], + rc); + soc_info->rgltr[j] = NULL; + goto power_up_failed; + } + + rc = cam_soc_util_regulator_enable( + soc_info->rgltr[j], + soc_info->rgltr_name[j], + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + soc_info->rgltr_op_mode[j], + soc_info->rgltr_delay[j]); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Reg enable failed"); + goto power_up_failed; + } + power_setting->data[0] = + soc_info->rgltr[j]; + } + } + if (power_setting->config_val) + soc_info->clk_rate[0][power_setting->seq_val] = + power_setting->config_val; + + for (j = 0; j < soc_info->num_clk; j++) { + rc = cam_soc_util_clk_enable(soc_info->clk[j], + soc_info->clk_name[j], + soc_info->clk_rate[0][j]); + if (rc) + break; + } + + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "clk enable failed"); + goto power_up_failed; + } + break; + case SENSOR_RESET: + case SENSOR_STANDBY: + case SENSOR_CUSTOM_GPIO1: + case SENSOR_CUSTOM_GPIO2: + if (no_gpio) { + CAM_ERR(CAM_SENSOR, "request gpio failed"); + return no_gpio; + } + if (!gpio_num_info) { + CAM_ERR(CAM_SENSOR, "Invalid gpio_num_info"); + goto power_up_failed; + } + CAM_DBG(CAM_SENSOR, "gpio set val %d", + gpio_num_info->gpio_num + [power_setting->seq_type]); + + rc = msm_cam_sensor_handle_reg_gpio( + power_setting->seq_type, + gpio_num_info, + (int) power_setting->config_val); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Error in handling VREG GPIO"); + goto power_up_failed; + } + break; + case SENSOR_VANA: + case SENSOR_VDIG: + case SENSOR_VIO: + case SENSOR_VAF: + case SENSOR_VAF_PWDM: + case SENSOR_CUSTOM_REG1: + case SENSOR_CUSTOM_REG2: + if (power_setting->seq_val == INVALID_VREG) + break; + + if (power_setting->seq_val >= CAM_VREG_MAX) { + CAM_ERR(CAM_SENSOR, "vreg index %d >= max %d", + power_setting->seq_val, + CAM_VREG_MAX); + goto power_up_failed; + } + if (power_setting->seq_val < num_vreg) { + CAM_DBG(CAM_SENSOR, "Enable Regulator"); + vreg_idx = power_setting->seq_val; + + soc_info->rgltr[vreg_idx] = + regulator_get(soc_info->dev, + soc_info->rgltr_name[vreg_idx]); + if (IS_ERR_OR_NULL( + soc_info->rgltr[vreg_idx])) { + rc = PTR_ERR(soc_info->rgltr[vreg_idx]); + rc = rc ? rc : -EINVAL; + + CAM_ERR(CAM_SENSOR, "%s get failed %d", + soc_info->rgltr_name[vreg_idx], + rc); + + soc_info->rgltr[vreg_idx] = NULL; + goto power_up_failed; + } + + rc = cam_soc_util_regulator_enable( + soc_info->rgltr[vreg_idx], + soc_info->rgltr_name[vreg_idx], + soc_info->rgltr_min_volt[vreg_idx], + soc_info->rgltr_max_volt[vreg_idx], + soc_info->rgltr_op_mode[vreg_idx], + soc_info->rgltr_delay[vreg_idx]); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Reg Enable failed for %s", + soc_info->rgltr_name[vreg_idx]); + goto power_up_failed; + } + power_setting->data[0] = + soc_info->rgltr[vreg_idx]; + } else { + CAM_ERR(CAM_SENSOR, "usr_idx:%d dts_idx:%d", + power_setting->seq_val, num_vreg); + } + + rc = msm_cam_sensor_handle_reg_gpio( + power_setting->seq_type, + gpio_num_info, 1); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Error in handling VREG GPIO"); + goto power_up_failed; + } + break; + default: + CAM_ERR(CAM_SENSOR, "error power seq type %d", + power_setting->seq_type); + break; + } + if (power_setting->delay > 20) + msleep(power_setting->delay); + else if (power_setting->delay) + usleep_range(power_setting->delay * 1000, + (power_setting->delay * 1000) + 1000); + } + + ret = cam_res_mgr_shared_pinctrl_post_init(); + if (ret) + CAM_ERR(CAM_SENSOR, + "Failed to post init shared pinctrl"); + + return 0; +power_up_failed: + CAM_ERR(CAM_SENSOR, "failed"); + for (index--; index >= 0; index--) { + CAM_DBG(CAM_SENSOR, "index %d", index); + power_setting = &ctrl->power_setting[index]; + CAM_DBG(CAM_SENSOR, "type %d", + power_setting->seq_type); + switch (power_setting->seq_type) { + case SENSOR_MCLK: + for (i = soc_info->num_clk - 1; i >= 0; i--) { + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + } + ret = cam_config_mclk_reg(ctrl, soc_info, index); + if (ret < 0) { + CAM_ERR(CAM_SENSOR, + "config clk reg failed rc: %d", ret); + continue; + } + break; + case SENSOR_RESET: + case SENSOR_STANDBY: + case SENSOR_CUSTOM_GPIO1: + case SENSOR_CUSTOM_GPIO2: + if (!gpio_num_info) + continue; + if (!gpio_num_info->valid + [power_setting->seq_type]) + continue; + cam_res_mgr_gpio_set_value( + gpio_num_info->gpio_num + [power_setting->seq_type], GPIOF_OUT_INIT_LOW); + break; + case SENSOR_VANA: + case SENSOR_VDIG: + case SENSOR_VIO: + case SENSOR_VAF: + case SENSOR_VAF_PWDM: + case SENSOR_CUSTOM_REG1: + case SENSOR_CUSTOM_REG2: + if (power_setting->seq_val < num_vreg) { + CAM_DBG(CAM_SENSOR, "Disable Regulator"); + vreg_idx = power_setting->seq_val; + + rc = cam_soc_util_regulator_disable( + soc_info->rgltr[vreg_idx], + soc_info->rgltr_name[vreg_idx], + soc_info->rgltr_min_volt[vreg_idx], + soc_info->rgltr_max_volt[vreg_idx], + soc_info->rgltr_op_mode[vreg_idx], + soc_info->rgltr_delay[vreg_idx]); + + if (rc) { + CAM_ERR(CAM_SENSOR, + "Fail to disalbe reg: %s", + soc_info->rgltr_name[vreg_idx]); + soc_info->rgltr[vreg_idx] = NULL; + msm_cam_sensor_handle_reg_gpio( + power_setting->seq_type, + gpio_num_info, + GPIOF_OUT_INIT_LOW); + continue; + } + power_setting->data[0] = + soc_info->rgltr[vreg_idx]; + + regulator_put(soc_info->rgltr[vreg_idx]); + soc_info->rgltr[vreg_idx] = NULL; + } else { + CAM_ERR(CAM_SENSOR, "seq_val:%d > num_vreg: %d", + power_setting->seq_val, num_vreg); + } + + msm_cam_sensor_handle_reg_gpio(power_setting->seq_type, + gpio_num_info, GPIOF_OUT_INIT_LOW); + + break; + default: + CAM_ERR(CAM_SENSOR, "error power seq type %d", + power_setting->seq_type); + break; + } + if (power_setting->delay > 20) { + msleep(power_setting->delay); + } else if (power_setting->delay) { + usleep_range(power_setting->delay * 1000, + (power_setting->delay * 1000) + 1000); + } + } + + if (ctrl->cam_pinctrl_status) { + ret = pinctrl_select_state( + ctrl->pinctrl_info.pinctrl, + ctrl->pinctrl_info.gpio_state_suspend); + if (ret) + CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state"); + devm_pinctrl_put(ctrl->pinctrl_info.pinctrl); + } + + if (soc_info->use_shared_clk) + cam_res_mgr_shared_clk_config(false); + + cam_res_mgr_shared_pinctrl_select_state(false); + cam_res_mgr_shared_pinctrl_put(); + + ctrl->cam_pinctrl_status = 0; + + cam_sensor_util_request_gpio_table(soc_info, 0); + + return rc; +} + +static struct cam_sensor_power_setting* +msm_camera_get_power_settings(struct cam_sensor_power_ctrl_t *ctrl, + enum msm_camera_power_seq_type seq_type, + uint16_t seq_val) +{ + struct cam_sensor_power_setting *power_setting, *ps = NULL; + int idx; + + for (idx = 0; idx < ctrl->power_setting_size; idx++) { + power_setting = &ctrl->power_setting[idx]; + if (power_setting->seq_type == seq_type && + power_setting->seq_val == seq_val) { + ps = power_setting; + return ps; + } + + } + + return ps; +} + +int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, + struct cam_hw_soc_info *soc_info) +{ + int index = 0, ret = 0, num_vreg = 0, i; + struct cam_sensor_power_setting *pd = NULL; + struct cam_sensor_power_setting *ps = NULL; + struct msm_camera_gpio_num_info *gpio_num_info = NULL; + + CAM_DBG(CAM_SENSOR, "Enter"); + if (!ctrl || !soc_info) { + CAM_ERR(CAM_SENSOR, "failed ctrl %pK", ctrl); + return -EINVAL; + } + + gpio_num_info = ctrl->gpio_num_info; + num_vreg = soc_info->num_rgltr; + + if ((num_vreg <= 0) || (num_vreg > CAM_SOC_MAX_REGULATOR)) { + CAM_ERR(CAM_SENSOR, "failed: num_vreg %d", num_vreg); + return -EINVAL; + } + + if (ctrl->power_down_setting_size > MAX_POWER_CONFIG) { + CAM_ERR(CAM_SENSOR, "Invalid: power setting size %d", + ctrl->power_setting_size); + return -EINVAL; + } + + for (index = 0; index < ctrl->power_down_setting_size; index++) { + CAM_DBG(CAM_SENSOR, "power_down_index %d", index); + pd = &ctrl->power_down_setting[index]; + if (!pd) { + CAM_ERR(CAM_SENSOR, + "Invalid power down settings for index %d", + index); + return -EINVAL; + } + + ps = NULL; + CAM_DBG(CAM_SENSOR, "seq_type %d", pd->seq_type); + switch (pd->seq_type) { + case SENSOR_MCLK: + for (i = soc_info->num_clk - 1; i >= 0; i--) { + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + } + + ret = cam_config_mclk_reg(ctrl, soc_info, index); + if (ret < 0) { + CAM_ERR(CAM_SENSOR, + "config clk reg failed rc: %d", ret); + continue; + } + break; + case SENSOR_RESET: + case SENSOR_STANDBY: + case SENSOR_CUSTOM_GPIO1: + case SENSOR_CUSTOM_GPIO2: + + if (!gpio_num_info->valid[pd->seq_type]) + continue; + + cam_res_mgr_gpio_set_value( + gpio_num_info->gpio_num + [pd->seq_type], + (int) pd->config_val); + + break; + case SENSOR_VANA: + case SENSOR_VDIG: + case SENSOR_VIO: + case SENSOR_VAF: + case SENSOR_VAF_PWDM: + case SENSOR_CUSTOM_REG1: + case SENSOR_CUSTOM_REG2: + if (pd->seq_val == INVALID_VREG) + break; + + ps = msm_camera_get_power_settings( + ctrl, pd->seq_type, + pd->seq_val); + if (ps) { + if (pd->seq_val < num_vreg) { + CAM_DBG(CAM_SENSOR, + "Disable Regulator"); + ret = cam_soc_util_regulator_disable( + soc_info->rgltr[ps->seq_val], + soc_info->rgltr_name[ps->seq_val], + soc_info->rgltr_min_volt[ps->seq_val], + soc_info->rgltr_max_volt[ps->seq_val], + soc_info->rgltr_op_mode[ps->seq_val], + soc_info->rgltr_delay[ps->seq_val]); + if (ret) { + CAM_ERR(CAM_SENSOR, + "Reg: %s disable failed", + soc_info->rgltr_name[ + ps->seq_val]); + soc_info->rgltr[ps->seq_val] = + NULL; + msm_cam_sensor_handle_reg_gpio( + pd->seq_type, + gpio_num_info, + GPIOF_OUT_INIT_LOW); + continue; + } + ps->data[0] = + soc_info->rgltr[ps->seq_val]; + regulator_put( + soc_info->rgltr[ps->seq_val]); + soc_info->rgltr[ps->seq_val] = NULL; + } else { + CAM_ERR(CAM_SENSOR, + "seq_val:%d > num_vreg: %d", + pd->seq_val, + num_vreg); + } + } else + CAM_ERR(CAM_SENSOR, + "error in power up/down seq"); + + ret = msm_cam_sensor_handle_reg_gpio(pd->seq_type, + gpio_num_info, GPIOF_OUT_INIT_LOW); + + if (ret < 0) + CAM_ERR(CAM_SENSOR, + "Error disabling VREG GPIO"); + break; + default: + CAM_ERR(CAM_SENSOR, "error power seq type %d", + pd->seq_type); + break; + } + if (pd->delay > 20) + msleep(pd->delay); + else if (pd->delay) + usleep_range(pd->delay * 1000, + (pd->delay * 1000) + 1000); + } + + if (ctrl->cam_pinctrl_status) { + ret = pinctrl_select_state( + ctrl->pinctrl_info.pinctrl, + ctrl->pinctrl_info.gpio_state_suspend); + if (ret) + CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state"); + + devm_pinctrl_put(ctrl->pinctrl_info.pinctrl); + } + + if (soc_info->use_shared_clk) + cam_res_mgr_shared_clk_config(false); + + cam_res_mgr_shared_pinctrl_select_state(false); + cam_res_mgr_shared_pinctrl_put(); + + ctrl->cam_pinctrl_status = 0; + + cam_sensor_util_request_gpio_table(soc_info, 0); + + return 0; +} diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h new file mode 100644 index 000000000000..69679f8c76e7 --- /dev/null +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SENSOR_UTIL_H_ +#define _CAM_SENSOR_UTIL_H_ + +#include +#include +#include +#include +#include +#include "cam_sensor_cmn_header.h" +#include "../../cam_req_mgr/cam_req_mgr_util.h" +#include "../../cam_req_mgr/cam_req_mgr_interface.h" +#include "../../cam_req_mgr/cam_mem_mgr.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_sensor_io.h" + +#define INVALID_VREG 100 + +int cam_get_dt_power_setting_data(struct device_node *of_node, + struct cam_hw_soc_info *soc_info, + struct cam_sensor_power_ctrl_t *power_info); + +int msm_camera_pinctrl_init + (struct msm_pinctrl_info *sensor_pctrl, struct device *dev); + +int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, + struct i2c_settings_array *i2c_reg_settings, + struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers); + +int cam_sensor_util_i2c_apply_setting(struct camera_io_master *io_master_info, + struct i2c_settings_list *i2c_list); + +int32_t delete_request(struct i2c_settings_array *i2c_array); +int cam_sensor_util_request_gpio_table( + struct cam_hw_soc_info *soc_info, int gpio_en); + +int cam_sensor_util_init_gpio_pin_tbl( + struct cam_hw_soc_info *soc_info, + struct msm_camera_gpio_num_info **pgpio_num_info); +int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, + struct cam_hw_soc_info *soc_info); + +int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, + struct cam_hw_soc_info *soc_info); + +int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info, + struct cam_sensor_power_setting *power_setting, + uint16_t power_setting_size); + +int32_t cam_sensor_update_power_settings(void *cmd_buf, + 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); +#endif /* _CAM_SENSOR_UTIL_H_ */ diff --git a/drivers/cam_smmu/Makefile b/drivers/cam_smmu/Makefile new file mode 100644 index 000000000000..c82e3978d028 --- /dev/null +++ b/drivers/cam_smmu/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu_api.o diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c new file mode 100644 index 000000000000..7084f38daaaa --- /dev/null +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -0,0 +1,3570 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_smmu_api.h" +#include "cam_debug_util.h" + +#define SHARED_MEM_POOL_GRANULARITY 16 + +#define IOMMU_INVALID_DIR -1 +#define BYTE_SIZE 8 +#define COOKIE_NUM_BYTE 2 +#define COOKIE_SIZE (BYTE_SIZE*COOKIE_NUM_BYTE) +#define COOKIE_MASK ((1<> COOKIE_SIZE) & COOKIE_MASK) + +static int g_num_pf_handled = 4; +module_param(g_num_pf_handled, int, 0644); + +struct firmware_alloc_info { + struct device *fw_dev; + void *fw_kva; + dma_addr_t fw_dma_hdl; +}; + +struct firmware_alloc_info icp_fw; + +struct cam_smmu_work_payload { + int idx; + struct iommu_domain *domain; + struct device *dev; + unsigned long iova; + int flags; + void *token; + struct list_head list; +}; + +enum cam_protection_type { + CAM_PROT_INVALID, + CAM_NON_SECURE, + CAM_SECURE, + CAM_PROT_MAX, +}; + +enum cam_iommu_type { + CAM_SMMU_INVALID, + CAM_QSMMU, + CAM_ARM_SMMU, + CAM_SMMU_MAX, +}; + +enum cam_smmu_buf_state { + CAM_SMMU_BUFF_EXIST, + CAM_SMMU_BUFF_NOT_EXIST, +}; + +enum cam_smmu_init_dir { + CAM_SMMU_TABLE_INIT, + CAM_SMMU_TABLE_DEINIT, +}; + +struct scratch_mapping { + void *bitmap; + size_t bits; + unsigned int order; + dma_addr_t base; +}; + +struct secheap_buf_info { + struct dma_buf *buf; + struct dma_buf_attachment *attach; + struct sg_table *table; +}; + +struct cam_context_bank_info { + struct device *dev; + struct iommu_domain *domain; + dma_addr_t va_start; + size_t va_len; + const char *name; + bool is_secure; + uint8_t scratch_buf_support; + uint8_t firmware_support; + uint8_t shared_support; + uint8_t io_support; + uint8_t secheap_support; + uint8_t qdss_support; + dma_addr_t qdss_phy_addr; + bool is_fw_allocated; + bool is_secheap_allocated; + bool is_qdss_allocated; + + struct scratch_mapping scratch_map; + struct gen_pool *shared_mem_pool; + + struct cam_smmu_region_info scratch_info; + struct cam_smmu_region_info firmware_info; + struct cam_smmu_region_info shared_info; + struct cam_smmu_region_info io_info; + struct cam_smmu_region_info secheap_info; + struct cam_smmu_region_info qdss_info; + struct secheap_buf_info secheap_buf; + + struct list_head smmu_buf_list; + struct list_head smmu_buf_kernel_list; + struct mutex lock; + int handle; + enum cam_smmu_ops_param state; + + cam_smmu_client_page_fault_handler handler[CAM_SMMU_CB_MAX]; + void *token[CAM_SMMU_CB_MAX]; + int cb_count; + int secure_count; + int pf_count; +}; + +struct cam_iommu_cb_set { + struct cam_context_bank_info *cb_info; + u32 cb_num; + u32 cb_init_count; + struct work_struct smmu_work; + struct mutex payload_list_lock; + struct list_head payload_list; + u32 non_fatal_fault; +}; + +static const struct of_device_id msm_cam_smmu_dt_match[] = { + { .compatible = "qcom,msm-cam-smmu", }, + { .compatible = "qcom,msm-cam-smmu-cb", }, + { .compatible = "qcom,msm-cam-smmu-fw-dev", }, + {} +}; + +struct cam_dma_buff_info { + struct dma_buf *buf; + struct dma_buf_attachment *attach; + struct sg_table *table; + enum dma_data_direction dir; + enum cam_smmu_region_id region_id; + int iommu_dir; + int ref_count; + dma_addr_t paddr; + struct list_head list; + int ion_fd; + size_t len; + size_t phys_len; +}; + +struct cam_sec_buff_info { + struct dma_buf *buf; + enum dma_data_direction dir; + int ref_count; + dma_addr_t paddr; + struct list_head list; + int ion_fd; + size_t len; +}; + +static const char *qdss_region_name = "qdss"; + +static struct cam_iommu_cb_set iommu_cb_set; + +static enum dma_data_direction cam_smmu_translate_dir( + enum cam_smmu_map_dir dir); + +static int cam_smmu_check_handle_unique(int hdl); + +static int cam_smmu_create_iommu_handle(int idx); + +static int cam_smmu_create_add_handle_in_table(char *name, + int *hdl); + +static struct cam_dma_buff_info *cam_smmu_find_mapping_by_ion_index(int idx, + int ion_fd); + +static struct cam_dma_buff_info *cam_smmu_find_mapping_by_dma_buf(int idx, + struct dma_buf *buf); + +static struct cam_sec_buff_info *cam_smmu_find_mapping_by_sec_buf_idx(int idx, + int ion_fd); + +static int cam_smmu_init_scratch_map(struct scratch_mapping *scratch_map, + dma_addr_t base, size_t size, + int order); + +static int cam_smmu_alloc_scratch_va(struct scratch_mapping *mapping, + size_t size, + dma_addr_t *iova); + +static int cam_smmu_free_scratch_va(struct scratch_mapping *mapping, + dma_addr_t addr, size_t size); + +static struct cam_dma_buff_info *cam_smmu_find_mapping_by_virt_address(int idx, + dma_addr_t virt_addr); + +static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, + enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, + size_t *len_ptr, enum cam_smmu_region_id region_id); + +static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, + struct dma_buf *buf, enum dma_data_direction dma_dir, + dma_addr_t *paddr_ptr, size_t *len_ptr, + enum cam_smmu_region_id region_id); + +static int cam_smmu_alloc_scratch_buffer_add_to_list(int idx, + size_t virt_len, + size_t phys_len, + unsigned int iommu_dir, + dma_addr_t *virt_addr); + +static int cam_smmu_unmap_buf_and_remove_from_list( + struct cam_dma_buff_info *mapping_info, int idx); + +static int cam_smmu_free_scratch_buffer_remove_from_list( + struct cam_dma_buff_info *mapping_info, + int idx); + +static void cam_smmu_clean_user_buffer_list(int idx); + +static void cam_smmu_clean_kernel_buffer_list(int idx); + +static void cam_smmu_print_user_list(int idx); + +static void cam_smmu_print_kernel_list(int idx); + +static void cam_smmu_print_table(void); + +static int cam_smmu_probe(struct platform_device *pdev); + +static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr); + +static void cam_smmu_page_fault_work(struct work_struct *work) +{ + int j; + int idx; + struct cam_smmu_work_payload *payload; + uint32_t buf_info; + + mutex_lock(&iommu_cb_set.payload_list_lock); + if (list_empty(&iommu_cb_set.payload_list)) { + CAM_ERR(CAM_SMMU, "Payload list empty"); + mutex_unlock(&iommu_cb_set.payload_list_lock); + return; + } + + payload = list_first_entry(&iommu_cb_set.payload_list, + struct cam_smmu_work_payload, + list); + list_del(&payload->list); + mutex_unlock(&iommu_cb_set.payload_list_lock); + + /* Dereference the payload to call the handler */ + idx = payload->idx; + buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova); + if (buf_info != 0) + CAM_INFO(CAM_SMMU, "closest buf 0x%x idx %d", buf_info, idx); + + for (j = 0; j < CAM_SMMU_CB_MAX; j++) { + if ((iommu_cb_set.cb_info[idx].handler[j])) { + iommu_cb_set.cb_info[idx].handler[j]( + payload->domain, + payload->dev, + payload->iova, + payload->flags, + iommu_cb_set.cb_info[idx].token[j], + buf_info); + } + } + kfree(payload); +} + +static void cam_smmu_print_user_list(int idx) +{ + struct cam_dma_buff_info *mapping; + + CAM_ERR(CAM_SMMU, "index = %d", idx); + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + CAM_ERR(CAM_SMMU, + "ion_fd = %d, paddr= 0x%pK, len = %u, region = %d", + mapping->ion_fd, (void *)mapping->paddr, + (unsigned int)mapping->len, + mapping->region_id); + } +} + +static void cam_smmu_print_kernel_list(int idx) +{ + struct cam_dma_buff_info *mapping; + + CAM_ERR(CAM_SMMU, "index = %d", idx); + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list, list) { + CAM_ERR(CAM_SMMU, + "dma_buf = %pK, paddr= 0x%pK, len = %u, region = %d", + mapping->buf, (void *)mapping->paddr, + (unsigned int)mapping->len, + mapping->region_id); + } +} + +static void cam_smmu_print_table(void) +{ + int i; + + for (i = 0; i < iommu_cb_set.cb_num; i++) { + CAM_ERR(CAM_SMMU, "i= %d, handle= %d, name_addr=%pK", i, + (int)iommu_cb_set.cb_info[i].handle, + (void *)iommu_cb_set.cb_info[i].name); + CAM_ERR(CAM_SMMU, "dev = %pK", iommu_cb_set.cb_info[i].dev); + } +} + +static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr) +{ + struct cam_dma_buff_info *mapping, *closest_mapping = NULL; + unsigned long start_addr, end_addr, current_addr; + uint32_t buf_handle = 0; + + long delta = 0, lowest_delta = 0; + + current_addr = (unsigned long)vaddr; + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + start_addr = (unsigned long)mapping->paddr; + end_addr = (unsigned long)mapping->paddr + mapping->len; + + if (start_addr <= current_addr && current_addr <= end_addr) { + closest_mapping = mapping; + CAM_INFO(CAM_SMMU, + "Found va 0x%lx in:0x%lx-0x%lx, fd %d cb:%s", + current_addr, start_addr, + end_addr, mapping->ion_fd, + iommu_cb_set.cb_info[idx].name); + goto end; + } else { + if (start_addr > current_addr) + delta = start_addr - current_addr; + else + delta = current_addr - end_addr - 1; + + if (delta < lowest_delta || lowest_delta == 0) { + lowest_delta = delta; + closest_mapping = mapping; + } + CAM_DBG(CAM_SMMU, + "approx va %lx not in range: %lx-%lx fd = %0x", + current_addr, start_addr, + end_addr, mapping->ion_fd); + } + } + +end: + if (closest_mapping) { + buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd); + CAM_INFO(CAM_SMMU, + "Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x", + closest_mapping->ion_fd, current_addr, + (unsigned long)closest_mapping->paddr, + (unsigned long)closest_mapping->paddr + mapping->len, + closest_mapping->buf, + buf_handle); + } else + CAM_INFO(CAM_SMMU, + "Cannot find vaddr:%lx in SMMU %s virt address", + current_addr, iommu_cb_set.cb_info[idx].name); + + return buf_handle; +} + +void cam_smmu_set_client_page_fault_handler(int handle, + cam_smmu_client_page_fault_handler handler_cb, void *token) +{ + int idx, i = 0; + + if (!token || (handle == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: token is NULL or invalid handle"); + return; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return; + } + + if (handler_cb) { + if (iommu_cb_set.cb_info[idx].cb_count == CAM_SMMU_CB_MAX) { + CAM_ERR(CAM_SMMU, + "%s Should not regiester more handlers", + iommu_cb_set.cb_info[idx].name); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return; + } + + iommu_cb_set.cb_info[idx].cb_count++; + + for (i = 0; i < iommu_cb_set.cb_info[idx].cb_count; i++) { + if (iommu_cb_set.cb_info[idx].token[i] == NULL) { + iommu_cb_set.cb_info[idx].token[i] = token; + iommu_cb_set.cb_info[idx].handler[i] = + handler_cb; + break; + } + } + } else { + for (i = 0; i < CAM_SMMU_CB_MAX; i++) { + if (iommu_cb_set.cb_info[idx].token[i] == token) { + iommu_cb_set.cb_info[idx].token[i] = NULL; + iommu_cb_set.cb_info[idx].handler[i] = + NULL; + iommu_cb_set.cb_info[idx].cb_count--; + break; + } + } + if (i == CAM_SMMU_CB_MAX) + CAM_ERR(CAM_SMMU, + "Error: hdl %x no matching tokens: %s", + handle, iommu_cb_set.cb_info[idx].name); + } + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +} + +void cam_smmu_unset_client_page_fault_handler(int handle, void *token) +{ + int idx, i = 0; + + if (!token || (handle == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: token is NULL or invalid handle"); + return; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return; + } + + for (i = 0; i < CAM_SMMU_CB_MAX; i++) { + if (iommu_cb_set.cb_info[idx].token[i] == token) { + iommu_cb_set.cb_info[idx].token[i] = NULL; + iommu_cb_set.cb_info[idx].handler[i] = + NULL; + iommu_cb_set.cb_info[idx].cb_count--; + break; + } + } + if (i == CAM_SMMU_CB_MAX) + CAM_ERR(CAM_SMMU, "Error: hdl %x no matching tokens: %s", + handle, iommu_cb_set.cb_info[idx].name); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +} + +static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, + struct device *dev, unsigned long iova, + int flags, void *token) +{ + char *cb_name; + int idx; + struct cam_smmu_work_payload *payload; + + if (!token) { + CAM_ERR(CAM_SMMU, "Error: token is NULL"); + CAM_ERR(CAM_SMMU, "Error: domain = %pK, device = %pK", + domain, dev); + CAM_ERR(CAM_SMMU, "iova = %lX, flags = %d", iova, flags); + return -EINVAL; + } + + cb_name = (char *)token; + /* Check whether it is in the table */ + for (idx = 0; idx < iommu_cb_set.cb_num; idx++) { + if (!strcmp(iommu_cb_set.cb_info[idx].name, cb_name)) + break; + } + + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: index is not valid, index = %d, token = %s", + idx, cb_name); + return -EINVAL; + } + + if (++iommu_cb_set.cb_info[idx].pf_count > g_num_pf_handled) { + CAM_INFO_RATE_LIMIT(CAM_SMMU, "PF already handled %d %d %d", + g_num_pf_handled, idx, + iommu_cb_set.cb_info[idx].pf_count); + return -EINVAL; + } + + payload = kzalloc(sizeof(struct cam_smmu_work_payload), GFP_ATOMIC); + if (!payload) + return -EINVAL; + + payload->domain = domain; + payload->dev = dev; + payload->iova = iova; + payload->flags = flags; + payload->token = token; + payload->idx = idx; + + mutex_lock(&iommu_cb_set.payload_list_lock); + list_add_tail(&payload->list, &iommu_cb_set.payload_list); + mutex_unlock(&iommu_cb_set.payload_list_lock); + + cam_smmu_page_fault_work(&iommu_cb_set.smmu_work); + + return -EINVAL; +} + +static int cam_smmu_translate_dir_to_iommu_dir( + enum cam_smmu_map_dir dir) +{ + switch (dir) { + case CAM_SMMU_MAP_READ: + return IOMMU_READ; + case CAM_SMMU_MAP_WRITE: + return IOMMU_WRITE; + case CAM_SMMU_MAP_RW: + return IOMMU_READ|IOMMU_WRITE; + case CAM_SMMU_MAP_INVALID: + default: + CAM_ERR(CAM_SMMU, "Error: Direction is invalid. dir = %d", dir); + break; + }; + return IOMMU_INVALID_DIR; +} + +static enum dma_data_direction cam_smmu_translate_dir( + enum cam_smmu_map_dir dir) +{ + switch (dir) { + case CAM_SMMU_MAP_READ: + return DMA_FROM_DEVICE; + case CAM_SMMU_MAP_WRITE: + return DMA_TO_DEVICE; + case CAM_SMMU_MAP_RW: + return DMA_BIDIRECTIONAL; + case CAM_SMMU_MAP_INVALID: + default: + CAM_ERR(CAM_SMMU, "Error: Direction is invalid. dir = %d", + (int)dir); + break; + } + return DMA_NONE; +} + +void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops) +{ + unsigned int i; + int j = 0; + + for (i = 0; i < iommu_cb_set.cb_num; i++) { + iommu_cb_set.cb_info[i].handle = HANDLE_INIT; + INIT_LIST_HEAD(&iommu_cb_set.cb_info[i].smmu_buf_list); + INIT_LIST_HEAD(&iommu_cb_set.cb_info[i].smmu_buf_kernel_list); + iommu_cb_set.cb_info[i].state = CAM_SMMU_DETACH; + iommu_cb_set.cb_info[i].dev = NULL; + iommu_cb_set.cb_info[i].cb_count = 0; + iommu_cb_set.cb_info[i].pf_count = 0; + for (j = 0; j < CAM_SMMU_CB_MAX; j++) { + iommu_cb_set.cb_info[i].token[j] = NULL; + iommu_cb_set.cb_info[i].handler[j] = NULL; + } + if (ops == CAM_SMMU_TABLE_INIT) + mutex_init(&iommu_cb_set.cb_info[i].lock); + else + mutex_destroy(&iommu_cb_set.cb_info[i].lock); + } +} + +static int cam_smmu_check_handle_unique(int hdl) +{ + int i; + + if (hdl == HANDLE_INIT) { + CAM_DBG(CAM_SMMU, + "iommu handle is init number. Need to try again"); + return 1; + } + + for (i = 0; i < iommu_cb_set.cb_num; i++) { + if (iommu_cb_set.cb_info[i].handle == HANDLE_INIT) + continue; + + if (iommu_cb_set.cb_info[i].handle == hdl) { + CAM_DBG(CAM_SMMU, "iommu handle %d conflicts", + (int)hdl); + return 1; + } + } + return 0; +} + +/** + * use low 2 bytes for handle cookie + */ +static int cam_smmu_create_iommu_handle(int idx) +{ + int rand, hdl = 0; + + get_random_bytes(&rand, COOKIE_NUM_BYTE); + hdl = GET_SMMU_HDL(idx, rand); + CAM_DBG(CAM_SMMU, "create handle value = %x", (int)hdl); + return hdl; +} + +static int cam_smmu_attach_device(int idx) +{ + int rc; + struct cam_context_bank_info *cb = &iommu_cb_set.cb_info[idx]; + + /* attach the mapping to device */ + rc = iommu_attach_device(cb->domain, cb->dev); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: ARM IOMMU attach failed. ret = %d", + rc); + rc = -ENODEV; + } + + return rc; +} + +static int cam_smmu_create_add_handle_in_table(char *name, + int *hdl) +{ + int i; + int handle; + + /* create handle and add in the iommu hardware table */ + for (i = 0; i < iommu_cb_set.cb_num; i++) { + if (!strcmp(iommu_cb_set.cb_info[i].name, name)) { + mutex_lock(&iommu_cb_set.cb_info[i].lock); + if (iommu_cb_set.cb_info[i].handle != HANDLE_INIT) { + if (iommu_cb_set.cb_info[i].is_secure) + iommu_cb_set.cb_info[i].secure_count++; + + mutex_unlock(&iommu_cb_set.cb_info[i].lock); + if (iommu_cb_set.cb_info[i].is_secure) { + *hdl = iommu_cb_set.cb_info[i].handle; + return 0; + } + + CAM_ERR(CAM_SMMU, + "Error: %s already got handle 0x%x", + name, iommu_cb_set.cb_info[i].handle); + + return -EINVAL; + } + + /* make sure handle is unique */ + do { + handle = cam_smmu_create_iommu_handle(i); + } while (cam_smmu_check_handle_unique(handle)); + + /* put handle in the table */ + iommu_cb_set.cb_info[i].handle = handle; + iommu_cb_set.cb_info[i].cb_count = 0; + if (iommu_cb_set.cb_info[i].is_secure) + iommu_cb_set.cb_info[i].secure_count++; + *hdl = handle; + CAM_DBG(CAM_SMMU, "%s creates handle 0x%x", + name, handle); + mutex_unlock(&iommu_cb_set.cb_info[i].lock); + return 0; + } + } + + CAM_ERR(CAM_SMMU, "Error: Cannot find name %s or all handle exist", + name); + cam_smmu_print_table(); + return -EINVAL; +} + +static int cam_smmu_init_scratch_map(struct scratch_mapping *scratch_map, + dma_addr_t base, size_t size, + int order) +{ + unsigned int count = size >> (PAGE_SHIFT + order); + unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long); + int err = 0; + + if (!count) { + err = -EINVAL; + CAM_ERR(CAM_SMMU, "Page count is zero, size passed = %zu", + size); + goto bail; + } + + scratch_map->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!scratch_map->bitmap) { + err = -ENOMEM; + goto bail; + } + + scratch_map->base = base; + scratch_map->bits = BITS_PER_BYTE * bitmap_size; + scratch_map->order = order; + +bail: + return err; +} + +static int cam_smmu_alloc_scratch_va(struct scratch_mapping *mapping, + size_t size, + dma_addr_t *iova) +{ + unsigned int order = get_order(size); + unsigned int align = 0; + unsigned int count, start; + + count = ((PAGE_ALIGN(size) >> PAGE_SHIFT) + + (1 << mapping->order) - 1) >> mapping->order; + + /* + * Transparently, add a guard page to the total count of pages + * to be allocated + */ + count++; + + if (order > mapping->order) + align = (1 << (order - mapping->order)) - 1; + + start = bitmap_find_next_zero_area(mapping->bitmap, mapping->bits, 0, + count, align); + + if (start > mapping->bits) + return -ENOMEM; + + bitmap_set(mapping->bitmap, start, count); + *iova = mapping->base + (start << (mapping->order + PAGE_SHIFT)); + + return 0; +} + +static int cam_smmu_free_scratch_va(struct scratch_mapping *mapping, + dma_addr_t addr, size_t size) +{ + unsigned int start = (addr - mapping->base) >> + (mapping->order + PAGE_SHIFT); + unsigned int count = ((size >> PAGE_SHIFT) + + (1 << mapping->order) - 1) >> mapping->order; + + if (!addr) { + CAM_ERR(CAM_SMMU, "Error: Invalid address"); + return -EINVAL; + } + + if (start + count > mapping->bits) { + CAM_ERR(CAM_SMMU, "Error: Invalid page bits in scratch map"); + return -EINVAL; + } + + /* + * Transparently, add a guard page to the total count of pages + * to be freed + */ + count++; + bitmap_clear(mapping->bitmap, start, count); + + return 0; +} + +static struct cam_dma_buff_info *cam_smmu_find_mapping_by_virt_address(int idx, + dma_addr_t virt_addr) +{ + struct cam_dma_buff_info *mapping; + + list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list, + list) { + if (mapping->paddr == virt_addr) { + CAM_DBG(CAM_SMMU, "Found virtual address %lx", + (unsigned long)virt_addr); + return mapping; + } + } + + CAM_ERR(CAM_SMMU, "Error: Cannot find virtual address %lx by index %d", + (unsigned long)virt_addr, idx); + return NULL; +} + +static struct cam_dma_buff_info *cam_smmu_find_mapping_by_ion_index(int idx, + int ion_fd) +{ + struct cam_dma_buff_info *mapping; + + if (ion_fd < 0) { + CAM_ERR(CAM_SMMU, "Invalid fd %d", ion_fd); + return NULL; + } + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, + list) { + if (mapping->ion_fd == ion_fd) { + CAM_DBG(CAM_SMMU, "find ion_fd %d", ion_fd); + return mapping; + } + } + + CAM_ERR(CAM_SMMU, "Error: Cannot find entry by index %d", idx); + + return NULL; +} + +static struct cam_dma_buff_info *cam_smmu_find_mapping_by_dma_buf(int idx, + struct dma_buf *buf) +{ + struct cam_dma_buff_info *mapping; + + if (!buf) { + CAM_ERR(CAM_SMMU, "Invalid dma_buf"); + return NULL; + } + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list, + list) { + if (mapping->buf == buf) { + CAM_DBG(CAM_SMMU, "find dma_buf %pK", buf); + return mapping; + } + } + + CAM_ERR(CAM_SMMU, "Error: Cannot find entry by index %d", idx); + + return NULL; +} + +static struct cam_sec_buff_info *cam_smmu_find_mapping_by_sec_buf_idx(int idx, + int ion_fd) +{ + struct cam_sec_buff_info *mapping; + + list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list, + list) { + if (mapping->ion_fd == ion_fd) { + CAM_DBG(CAM_SMMU, "find ion_fd %d", ion_fd); + return mapping; + } + } + CAM_ERR(CAM_SMMU, "Error: Cannot find fd %d by index %d", + ion_fd, idx); + return NULL; +} + +static void cam_smmu_clean_user_buffer_list(int idx) +{ + int ret; + struct cam_dma_buff_info *mapping_info, *temp; + + list_for_each_entry_safe(mapping_info, temp, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + CAM_DBG(CAM_SMMU, "Free mapping address %pK, i = %d, fd = %d", + (void *)mapping_info->paddr, idx, + mapping_info->ion_fd); + + if (mapping_info->ion_fd == 0xDEADBEEF) + /* Clean up scratch buffers */ + ret = cam_smmu_free_scratch_buffer_remove_from_list( + mapping_info, idx); + else + /* Clean up regular mapped buffers */ + ret = cam_smmu_unmap_buf_and_remove_from_list( + mapping_info, + idx); + + if (ret < 0) { + CAM_ERR(CAM_SMMU, "Buffer delete failed: idx = %d", + idx); + CAM_ERR(CAM_SMMU, + "Buffer delete failed: addr = %lx, fd = %d", + (unsigned long)mapping_info->paddr, + mapping_info->ion_fd); + /* + * Ignore this error and continue to delete other + * buffers in the list + */ + continue; + } + } +} + +static void cam_smmu_clean_kernel_buffer_list(int idx) +{ + int ret; + struct cam_dma_buff_info *mapping_info, *temp; + + list_for_each_entry_safe(mapping_info, temp, + &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list, list) { + CAM_DBG(CAM_SMMU, + "Free mapping address %pK, i = %d, dma_buf = %pK", + (void *)mapping_info->paddr, idx, + mapping_info->buf); + + /* Clean up regular mapped buffers */ + ret = cam_smmu_unmap_buf_and_remove_from_list( + mapping_info, + idx); + + if (ret < 0) { + CAM_ERR(CAM_SMMU, + "Buffer delete in kernel list failed: idx = %d", + idx); + CAM_ERR(CAM_SMMU, + "Buffer delete failed: addr = %lx, dma_buf = %pK", + (unsigned long)mapping_info->paddr, + mapping_info->buf); + /* + * Ignore this error and continue to delete other + * buffers in the list + */ + continue; + } + } +} + +static int cam_smmu_attach(int idx) +{ + int ret; + + if (iommu_cb_set.cb_info[idx].state == CAM_SMMU_ATTACH) { + ret = -EALREADY; + } else if (iommu_cb_set.cb_info[idx].state == CAM_SMMU_DETACH) { + ret = cam_smmu_attach_device(idx); + if (ret < 0) { + CAM_ERR(CAM_SMMU, "Error: ATTACH fail"); + return -ENODEV; + } + iommu_cb_set.cb_info[idx].state = CAM_SMMU_ATTACH; + ret = 0; + } else { + CAM_ERR(CAM_SMMU, "Error: Not detach/attach: %d", + iommu_cb_set.cb_info[idx].state); + ret = -EINVAL; + } + + return ret; +} + +static int cam_smmu_detach_device(int idx) +{ + int rc = 0; + struct cam_context_bank_info *cb = &iommu_cb_set.cb_info[idx]; + + /* detach the mapping to device if not already detached */ + if (iommu_cb_set.cb_info[idx].state == CAM_SMMU_DETACH) { + rc = -EALREADY; + } else if (iommu_cb_set.cb_info[idx].state == CAM_SMMU_ATTACH) { + iommu_detach_device(cb->domain, cb->dev); + iommu_cb_set.cb_info[idx].state = CAM_SMMU_DETACH; + } + + return rc; +} + +static int cam_smmu_alloc_iova(size_t size, + int32_t smmu_hdl, uint32_t *iova) +{ + int rc = 0; + int idx; + uint32_t vaddr = 0; + + if (!iova || !size || (smmu_hdl == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); + return -EINVAL; + } + + CAM_DBG(CAM_SMMU, "Allocating iova size = %zu for smmu hdl=%X", + size, smmu_hdl); + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + return -EINVAL; + } + + if (iommu_cb_set.cb_info[idx].handle != smmu_hdl) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, smmu_hdl); + rc = -EINVAL; + goto get_addr_end; + } + + if (!iommu_cb_set.cb_info[idx].shared_support) { + CAM_ERR(CAM_SMMU, + "Error: Shared memory not supported for hdl = %X", + smmu_hdl); + rc = -EINVAL; + goto get_addr_end; + } + + vaddr = gen_pool_alloc(iommu_cb_set.cb_info[idx].shared_mem_pool, size); + if (!vaddr) + return -ENOMEM; + + *iova = vaddr; + +get_addr_end: + return rc; +} + +static int cam_smmu_free_iova(uint32_t addr, size_t size, + int32_t smmu_hdl) +{ + int rc = 0; + int idx; + + if (!size || (smmu_hdl == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + return -EINVAL; + } + + if (iommu_cb_set.cb_info[idx].handle != smmu_hdl) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, smmu_hdl); + rc = -EINVAL; + goto get_addr_end; + } + + gen_pool_free(iommu_cb_set.cb_info[idx].shared_mem_pool, addr, size); + +get_addr_end: + return rc; +} + +int cam_smmu_alloc_firmware(int32_t smmu_hdl, + dma_addr_t *iova, + uintptr_t *cpuva, + size_t *len) +{ + int rc; + int32_t idx; + size_t firmware_len = 0; + size_t firmware_start = 0; + struct iommu_domain *domain; + + if (!iova || !len || !cpuva || (smmu_hdl == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + rc = -EINVAL; + goto end; + } + + if (!iommu_cb_set.cb_info[idx].firmware_support) { + CAM_ERR(CAM_SMMU, + "Firmware memory not supported for this SMMU handle"); + rc = -EINVAL; + goto end; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].is_fw_allocated) { + CAM_ERR(CAM_SMMU, "Trying to allocate twice"); + rc = -ENOMEM; + goto unlock_and_end; + } + + firmware_len = iommu_cb_set.cb_info[idx].firmware_info.iova_len; + firmware_start = iommu_cb_set.cb_info[idx].firmware_info.iova_start; + CAM_DBG(CAM_SMMU, "Firmware area len from DT = %zu", firmware_len); + + icp_fw.fw_kva = dma_alloc_coherent(icp_fw.fw_dev, + firmware_len, + &icp_fw.fw_dma_hdl, + GFP_KERNEL); + if (!icp_fw.fw_kva) { + CAM_ERR(CAM_SMMU, "FW memory alloc failed"); + rc = -ENOMEM; + goto unlock_and_end; + } else { + CAM_DBG(CAM_SMMU, "DMA alloc returned fw = %pK, hdl = %pK", + icp_fw.fw_kva, (void *)icp_fw.fw_dma_hdl); + } + + domain = iommu_cb_set.cb_info[idx].domain; + rc = iommu_map(domain, + firmware_start, + icp_fw.fw_dma_hdl, + firmware_len, + IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV); + + if (rc) { + CAM_ERR(CAM_SMMU, "Failed to map FW into IOMMU"); + rc = -ENOMEM; + goto alloc_fail; + } + iommu_cb_set.cb_info[idx].is_fw_allocated = true; + + *iova = iommu_cb_set.cb_info[idx].firmware_info.iova_start; + *cpuva = (uintptr_t)icp_fw.fw_kva; + *len = firmware_len; + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + + return rc; + +alloc_fail: + dma_free_coherent(icp_fw.fw_dev, + firmware_len, + icp_fw.fw_kva, + icp_fw.fw_dma_hdl); +unlock_and_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +end: + return rc; +} +EXPORT_SYMBOL(cam_smmu_alloc_firmware); + +int cam_smmu_dealloc_firmware(int32_t smmu_hdl) +{ + int rc = 0; + int32_t idx; + size_t firmware_len = 0; + size_t firmware_start = 0; + struct iommu_domain *domain; + size_t unmapped = 0; + + if (smmu_hdl == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + rc = -EINVAL; + goto end; + } + + if (!iommu_cb_set.cb_info[idx].firmware_support) { + CAM_ERR(CAM_SMMU, + "Firmware memory not supported for this SMMU handle"); + rc = -EINVAL; + goto end; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (!iommu_cb_set.cb_info[idx].is_fw_allocated) { + CAM_ERR(CAM_SMMU, + "Trying to deallocate firmware that is not allocated"); + rc = -ENOMEM; + goto unlock_and_end; + } + + firmware_len = iommu_cb_set.cb_info[idx].firmware_info.iova_len; + firmware_start = iommu_cb_set.cb_info[idx].firmware_info.iova_start; + domain = iommu_cb_set.cb_info[idx].domain; + unmapped = iommu_unmap(domain, + firmware_start, + firmware_len); + + if (unmapped != firmware_len) { + CAM_ERR(CAM_SMMU, "Only %zu unmapped out of total %zu", + unmapped, + firmware_len); + rc = -EINVAL; + } + + dma_free_coherent(icp_fw.fw_dev, + firmware_len, + icp_fw.fw_kva, + icp_fw.fw_dma_hdl); + + icp_fw.fw_kva = 0; + icp_fw.fw_dma_hdl = 0; + + iommu_cb_set.cb_info[idx].is_fw_allocated = false; + +unlock_and_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +end: + return rc; +} +EXPORT_SYMBOL(cam_smmu_dealloc_firmware); + +int cam_smmu_alloc_qdss(int32_t smmu_hdl, + dma_addr_t *iova, + size_t *len) +{ + int rc; + int32_t idx; + size_t qdss_len = 0; + size_t qdss_start = 0; + dma_addr_t qdss_phy_addr; + struct iommu_domain *domain; + + if (!iova || !len || (smmu_hdl == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + rc = -EINVAL; + goto end; + } + + if (!iommu_cb_set.cb_info[idx].qdss_support) { + CAM_ERR(CAM_SMMU, + "QDSS memory not supported for this SMMU handle"); + rc = -EINVAL; + goto end; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].is_qdss_allocated) { + CAM_ERR(CAM_SMMU, "Trying to allocate twice"); + rc = -ENOMEM; + goto unlock_and_end; + } + + qdss_len = iommu_cb_set.cb_info[idx].qdss_info.iova_len; + qdss_start = iommu_cb_set.cb_info[idx].qdss_info.iova_start; + qdss_phy_addr = iommu_cb_set.cb_info[idx].qdss_phy_addr; + CAM_DBG(CAM_SMMU, "QDSS area len from DT = %zu", qdss_len); + + domain = iommu_cb_set.cb_info[idx].domain; + rc = iommu_map(domain, + qdss_start, + qdss_phy_addr, + qdss_len, + IOMMU_READ|IOMMU_WRITE); + + if (rc) { + CAM_ERR(CAM_SMMU, "Failed to map QDSS into IOMMU"); + goto unlock_and_end; + } + + iommu_cb_set.cb_info[idx].is_qdss_allocated = true; + + *iova = iommu_cb_set.cb_info[idx].qdss_info.iova_start; + *len = qdss_len; + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + + return rc; + +unlock_and_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +end: + return rc; +} +EXPORT_SYMBOL(cam_smmu_alloc_qdss); + +int cam_smmu_dealloc_qdss(int32_t smmu_hdl) +{ + int rc = 0; + int32_t idx; + size_t qdss_len = 0; + size_t qdss_start = 0; + struct iommu_domain *domain; + size_t unmapped = 0; + + if (smmu_hdl == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + rc = -EINVAL; + goto end; + } + + if (!iommu_cb_set.cb_info[idx].qdss_support) { + CAM_ERR(CAM_SMMU, + "QDSS memory not supported for this SMMU handle"); + rc = -EINVAL; + goto end; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (!iommu_cb_set.cb_info[idx].is_qdss_allocated) { + CAM_ERR(CAM_SMMU, + "Trying to deallocate qdss that is not allocated"); + rc = -ENOMEM; + goto unlock_and_end; + } + + qdss_len = iommu_cb_set.cb_info[idx].qdss_info.iova_len; + qdss_start = iommu_cb_set.cb_info[idx].qdss_info.iova_start; + domain = iommu_cb_set.cb_info[idx].domain; + unmapped = iommu_unmap(domain, qdss_start, qdss_len); + + if (unmapped != qdss_len) { + CAM_ERR(CAM_SMMU, "Only %zu unmapped out of total %zu", + unmapped, + qdss_len); + rc = -EINVAL; + } + + iommu_cb_set.cb_info[idx].is_qdss_allocated = false; + +unlock_and_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +end: + return rc; +} +EXPORT_SYMBOL(cam_smmu_dealloc_qdss); + +int cam_smmu_get_io_region_info(int32_t smmu_hdl, + dma_addr_t *iova, size_t *len) +{ + int32_t idx; + + if (!iova || !len || (smmu_hdl == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + return -EINVAL; + } + + if (!iommu_cb_set.cb_info[idx].io_support) { + CAM_ERR(CAM_SMMU, + "I/O memory not supported for this SMMU handle"); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + *iova = iommu_cb_set.cb_info[idx].io_info.iova_start; + *len = iommu_cb_set.cb_info[idx].io_info.iova_len; + + CAM_DBG(CAM_SMMU, + "I/O area for hdl = %x start addr = %pK len = %zu", + smmu_hdl, *iova, *len); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + + return 0; +} + +int cam_smmu_get_region_info(int32_t smmu_hdl, + enum cam_smmu_region_id region_id, + struct cam_smmu_region_info *region_info) +{ + int32_t idx; + struct cam_context_bank_info *cb = NULL; + + if (!region_info) { + CAM_ERR(CAM_SMMU, "Invalid region_info pointer"); + return -EINVAL; + } + + if (smmu_hdl == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Invalid handle"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, "Handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + cb = &iommu_cb_set.cb_info[idx]; + if (!cb) { + CAM_ERR(CAM_SMMU, "SMMU context bank pointer invalid"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -EINVAL; + } + + switch (region_id) { + case CAM_SMMU_REGION_FIRMWARE: + if (!cb->firmware_support) { + CAM_ERR(CAM_SMMU, "Firmware not supported"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -ENODEV; + } + region_info->iova_start = cb->firmware_info.iova_start; + region_info->iova_len = cb->firmware_info.iova_len; + break; + case CAM_SMMU_REGION_SHARED: + if (!cb->shared_support) { + CAM_ERR(CAM_SMMU, "Shared mem not supported"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -ENODEV; + } + region_info->iova_start = cb->shared_info.iova_start; + region_info->iova_len = cb->shared_info.iova_len; + break; + case CAM_SMMU_REGION_SCRATCH: + if (!cb->scratch_buf_support) { + CAM_ERR(CAM_SMMU, "Scratch memory not supported"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -ENODEV; + } + region_info->iova_start = cb->scratch_info.iova_start; + region_info->iova_len = cb->scratch_info.iova_len; + break; + case CAM_SMMU_REGION_IO: + if (!cb->io_support) { + CAM_ERR(CAM_SMMU, "IO memory not supported"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -ENODEV; + } + region_info->iova_start = cb->io_info.iova_start; + region_info->iova_len = cb->io_info.iova_len; + break; + case CAM_SMMU_REGION_SECHEAP: + if (!cb->secheap_support) { + CAM_ERR(CAM_SMMU, "Secondary heap not supported"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -ENODEV; + } + region_info->iova_start = cb->secheap_info.iova_start; + region_info->iova_len = cb->secheap_info.iova_len; + break; + default: + CAM_ERR(CAM_SMMU, "Invalid region id: %d for smmu hdl: %X", + smmu_hdl, region_id); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -EINVAL; + } + + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return 0; +} +EXPORT_SYMBOL(cam_smmu_get_region_info); + +int cam_smmu_reserve_sec_heap(int32_t smmu_hdl, + struct dma_buf *buf, + dma_addr_t *iova, + size_t *request_len) +{ + struct secheap_buf_info *secheap_buf = NULL; + size_t size = 0; + uint32_t sec_heap_iova = 0; + size_t sec_heap_iova_len = 0; + int idx; + int rc = 0; + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + return -EINVAL; + } + + if (!iommu_cb_set.cb_info[idx].secheap_support) { + CAM_ERR(CAM_SMMU, "Secondary heap not supported"); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + + if (iommu_cb_set.cb_info[idx].is_secheap_allocated) { + CAM_ERR(CAM_SMMU, "Trying to allocate secheap twice"); + rc = -ENOMEM; + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; + } + + if (IS_ERR_OR_NULL(buf)) { + rc = PTR_ERR(buf); + CAM_ERR(CAM_SMMU, + "Error: dma get buf failed. rc = %d", rc); + goto err_out; + } + + secheap_buf = &iommu_cb_set.cb_info[idx].secheap_buf; + secheap_buf->buf = buf; + secheap_buf->attach = dma_buf_attach(secheap_buf->buf, + iommu_cb_set.cb_info[idx].dev); + if (IS_ERR_OR_NULL(secheap_buf->attach)) { + rc = PTR_ERR(secheap_buf->attach); + CAM_ERR(CAM_SMMU, "Error: dma buf attach failed"); + goto err_put; + } + + secheap_buf->table = dma_buf_map_attachment(secheap_buf->attach, + DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(secheap_buf->table)) { + rc = PTR_ERR(secheap_buf->table); + CAM_ERR(CAM_SMMU, "Error: dma buf map attachment failed"); + goto err_detach; + } + + sec_heap_iova = iommu_cb_set.cb_info[idx].secheap_info.iova_start; + sec_heap_iova_len = iommu_cb_set.cb_info[idx].secheap_info.iova_len; + size = iommu_map_sg(iommu_cb_set.cb_info[idx].domain, + sec_heap_iova, + secheap_buf->table->sgl, + secheap_buf->table->nents, + IOMMU_READ | IOMMU_WRITE); + if (size != sec_heap_iova_len) { + CAM_ERR(CAM_SMMU, "IOMMU mapping failed"); + goto err_unmap_sg; + } + + iommu_cb_set.cb_info[idx].is_secheap_allocated = true; + *iova = (uint32_t)sec_heap_iova; + *request_len = sec_heap_iova_len; + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + + return rc; + +err_unmap_sg: + dma_buf_unmap_attachment(secheap_buf->attach, + secheap_buf->table, + DMA_BIDIRECTIONAL); +err_detach: + dma_buf_detach(secheap_buf->buf, + secheap_buf->attach); +err_put: + dma_buf_put(secheap_buf->buf); +err_out: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_reserve_sec_heap); + +int cam_smmu_release_sec_heap(int32_t smmu_hdl) +{ + int idx; + size_t size = 0; + uint32_t sec_heap_iova = 0; + size_t sec_heap_iova_len = 0; + struct secheap_buf_info *secheap_buf = NULL; + + idx = GET_SMMU_TABLE_IDX(smmu_hdl); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, smmu_hdl); + return -EINVAL; + } + + if (!iommu_cb_set.cb_info[idx].secheap_support) { + CAM_ERR(CAM_SMMU, "Secondary heap not supported"); + return -EINVAL; + } + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + + if (!iommu_cb_set.cb_info[idx].is_secheap_allocated) { + CAM_ERR(CAM_SMMU, "Trying to release secheap twice"); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -ENOMEM; + } + + secheap_buf = &iommu_cb_set.cb_info[idx].secheap_buf; + sec_heap_iova = iommu_cb_set.cb_info[idx].secheap_info.iova_start; + sec_heap_iova_len = iommu_cb_set.cb_info[idx].secheap_info.iova_len; + + size = iommu_unmap(iommu_cb_set.cb_info[idx].domain, + sec_heap_iova, + sec_heap_iova_len); + if (size != sec_heap_iova_len) { + CAM_ERR(CAM_SMMU, "Failed: Unmapped = %zu, requested = %zu", + size, + sec_heap_iova_len); + } + + dma_buf_unmap_attachment(secheap_buf->attach, + secheap_buf->table, DMA_BIDIRECTIONAL); + dma_buf_detach(secheap_buf->buf, secheap_buf->attach); + dma_buf_put(secheap_buf->buf); + iommu_cb_set.cb_info[idx].is_secheap_allocated = false; + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + + return 0; +} +EXPORT_SYMBOL(cam_smmu_release_sec_heap); + +static int cam_smmu_map_buffer_validate(struct dma_buf *buf, + int idx, enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, + size_t *len_ptr, enum cam_smmu_region_id region_id, + struct cam_dma_buff_info **mapping_info) +{ + struct dma_buf_attachment *attach = NULL; + struct sg_table *table = NULL; + struct iommu_domain *domain; + size_t size = 0; + uint32_t iova = 0; + int rc = 0; + + if (IS_ERR_OR_NULL(buf)) { + rc = PTR_ERR(buf); + CAM_ERR(CAM_SMMU, + "Error: dma get buf failed. rc = %d", rc); + goto err_out; + } + + if (!mapping_info) { + rc = -EINVAL; + CAM_ERR(CAM_SMMU, "Error: mapping_info is invalid"); + goto err_out; + } + + attach = dma_buf_attach(buf, iommu_cb_set.cb_info[idx].dev); + if (IS_ERR_OR_NULL(attach)) { + rc = PTR_ERR(attach); + CAM_ERR(CAM_SMMU, "Error: dma buf attach failed"); + goto err_put; + } + + if (region_id == CAM_SMMU_REGION_SHARED) { + table = dma_buf_map_attachment(attach, dma_dir); + if (IS_ERR_OR_NULL(table)) { + rc = PTR_ERR(table); + CAM_ERR(CAM_SMMU, "Error: dma map attachment failed"); + goto err_detach; + } + + domain = iommu_cb_set.cb_info[idx].domain; + if (!domain) { + CAM_ERR(CAM_SMMU, "CB has no domain set"); + goto err_unmap_sg; + } + + rc = cam_smmu_alloc_iova(*len_ptr, + iommu_cb_set.cb_info[idx].handle, + &iova); + + if (rc < 0) { + CAM_ERR(CAM_SMMU, + "IOVA alloc failed for shared memory, size=%zu, idx=%d, handle=%d", + *len_ptr, idx, + iommu_cb_set.cb_info[idx].handle); + goto err_unmap_sg; + } + + size = iommu_map_sg(domain, iova, table->sgl, table->nents, + IOMMU_READ | IOMMU_WRITE); + + if (size < 0) { + CAM_ERR(CAM_SMMU, "IOMMU mapping failed"); + rc = cam_smmu_free_iova(iova, + size, iommu_cb_set.cb_info[idx].handle); + if (rc) + CAM_ERR(CAM_SMMU, "IOVA free failed"); + rc = -ENOMEM; + goto err_unmap_sg; + } else { + CAM_DBG(CAM_SMMU, + "iommu_map_sg returned iova=%pK, size=%zu", + iova, size); + *paddr_ptr = iova; + *len_ptr = size; + } + } else if (region_id == CAM_SMMU_REGION_IO) { + attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; + + table = dma_buf_map_attachment(attach, dma_dir); + if (IS_ERR_OR_NULL(table)) { + rc = PTR_ERR(table); + CAM_ERR(CAM_SMMU, "Error: dma map attachment failed"); + goto err_detach; + } + + *paddr_ptr = sg_dma_address(table->sgl); + *len_ptr = (size_t)buf->size; + } else { + CAM_ERR(CAM_SMMU, "Error: Wrong region id passed"); + rc = -EINVAL; + goto err_unmap_sg; + } + + CAM_DBG(CAM_SMMU, "iova=%pK, region_id=%d, paddr=%pK, len=%d", + iova, region_id, *paddr_ptr, *len_ptr); + + if (table->sgl) { + CAM_DBG(CAM_SMMU, + "DMA buf: %pK, device: %pK, attach: %pK, table: %pK", + (void *)buf, + (void *)iommu_cb_set.cb_info[idx].dev, + (void *)attach, (void *)table); + CAM_DBG(CAM_SMMU, "table sgl: %pK, rc: %d, dma_address: 0x%x", + (void *)table->sgl, rc, + (unsigned int)table->sgl->dma_address); + } else { + rc = -EINVAL; + CAM_ERR(CAM_SMMU, "Error: table sgl is null"); + goto err_unmap_sg; + } + + /* fill up mapping_info */ + *mapping_info = kzalloc(sizeof(struct cam_dma_buff_info), GFP_KERNEL); + if (!(*mapping_info)) { + rc = -ENOSPC; + goto err_alloc; + } + + (*mapping_info)->buf = buf; + (*mapping_info)->attach = attach; + (*mapping_info)->table = table; + (*mapping_info)->paddr = *paddr_ptr; + (*mapping_info)->len = *len_ptr; + (*mapping_info)->dir = dma_dir; + (*mapping_info)->ref_count = 1; + (*mapping_info)->region_id = region_id; + + if (!*paddr_ptr || !*len_ptr) { + CAM_ERR(CAM_SMMU, "Error: Space Allocation failed"); + kfree(*mapping_info); + *mapping_info = NULL; + rc = -ENOSPC; + goto err_alloc; + } + CAM_DBG(CAM_SMMU, "idx=%d, dma_buf=%pK, dev=%pK, paddr=%pK, len=%u", + idx, buf, (void *)iommu_cb_set.cb_info[idx].dev, + (void *)*paddr_ptr, (unsigned int)*len_ptr); + + return 0; + +err_alloc: + if (region_id == CAM_SMMU_REGION_SHARED) { + cam_smmu_free_iova(iova, + size, + iommu_cb_set.cb_info[idx].handle); + + iommu_unmap(iommu_cb_set.cb_info[idx].domain, + *paddr_ptr, + *len_ptr); + } +err_unmap_sg: + dma_buf_unmap_attachment(attach, table, dma_dir); +err_detach: + dma_buf_detach(buf, attach); +err_put: + dma_buf_put(buf); +err_out: + return rc; +} + + +static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, + enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, + size_t *len_ptr, enum cam_smmu_region_id region_id) +{ + int rc = -1; + struct cam_dma_buff_info *mapping_info = NULL; + struct dma_buf *buf = NULL; + + /* returns the dma_buf structure related to an fd */ + buf = dma_buf_get(ion_fd); + + rc = cam_smmu_map_buffer_validate(buf, idx, dma_dir, paddr_ptr, len_ptr, + region_id, &mapping_info); + + if (rc) { + CAM_ERR(CAM_SMMU, "buffer validation failure"); + return rc; + } + + mapping_info->ion_fd = ion_fd; + /* add to the list */ + list_add(&mapping_info->list, + &iommu_cb_set.cb_info[idx].smmu_buf_list); + + return 0; +} + +static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, + struct dma_buf *buf, enum dma_data_direction dma_dir, + dma_addr_t *paddr_ptr, size_t *len_ptr, + enum cam_smmu_region_id region_id) +{ + int rc = -1; + struct cam_dma_buff_info *mapping_info = NULL; + + rc = cam_smmu_map_buffer_validate(buf, idx, dma_dir, paddr_ptr, len_ptr, + region_id, &mapping_info); + + if (rc) { + CAM_ERR(CAM_SMMU, "buffer validation failure"); + return rc; + } + + mapping_info->ion_fd = -1; + + /* add to the list */ + list_add(&mapping_info->list, + &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list); + + return 0; +} + + +static int cam_smmu_unmap_buf_and_remove_from_list( + struct cam_dma_buff_info *mapping_info, + int idx) +{ + int rc; + size_t size; + struct iommu_domain *domain; + + if ((!mapping_info->buf) || (!mapping_info->table) || + (!mapping_info->attach)) { + CAM_ERR(CAM_SMMU, + "Error: Invalid params dev = %pK, table = %pK", + (void *)iommu_cb_set.cb_info[idx].dev, + (void *)mapping_info->table); + CAM_ERR(CAM_SMMU, "Error:dma_buf = %pK, attach = %pK", + (void *)mapping_info->buf, + (void *)mapping_info->attach); + return -EINVAL; + } + + if (mapping_info->region_id == CAM_SMMU_REGION_SHARED) { + CAM_DBG(CAM_SMMU, + "Removing SHARED buffer paddr = %pK, len = %zu", + (void *)mapping_info->paddr, mapping_info->len); + + domain = iommu_cb_set.cb_info[idx].domain; + + size = iommu_unmap(domain, + mapping_info->paddr, + mapping_info->len); + + if (size != mapping_info->len) { + CAM_ERR(CAM_SMMU, "IOMMU unmap failed"); + CAM_ERR(CAM_SMMU, "Unmapped = %zu, requested = %zu", + size, + mapping_info->len); + } + + rc = cam_smmu_free_iova(mapping_info->paddr, + mapping_info->len, + iommu_cb_set.cb_info[idx].handle); + + if (rc) + CAM_ERR(CAM_SMMU, "IOVA free failed"); + + } else if (mapping_info->region_id == CAM_SMMU_REGION_IO) { + mapping_info->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; + } + + dma_buf_unmap_attachment(mapping_info->attach, + mapping_info->table, mapping_info->dir); + dma_buf_detach(mapping_info->buf, mapping_info->attach); + dma_buf_put(mapping_info->buf); + + mapping_info->buf = NULL; + + list_del_init(&mapping_info->list); + + /* free one buffer */ + kfree(mapping_info); + return 0; +} + +static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx, + int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + struct cam_dma_buff_info *mapping; + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + if (mapping->ion_fd == ion_fd) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + +static enum cam_smmu_buf_state cam_smmu_check_dma_buf_in_list(int idx, + struct dma_buf *buf, dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + struct cam_dma_buff_info *mapping; + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list, list) { + if (mapping->buf == buf) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + +static enum cam_smmu_buf_state cam_smmu_check_secure_fd_in_list(int idx, + int ion_fd, dma_addr_t *paddr_ptr, + size_t *len_ptr) +{ + struct cam_sec_buff_info *mapping; + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, + list) { + if (mapping->ion_fd == ion_fd) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + mapping->ref_count++; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + +static enum cam_smmu_buf_state cam_smmu_validate_secure_fd_in_list(int idx, + int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + struct cam_sec_buff_info *mapping; + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, + list) { + if (mapping->ion_fd == ion_fd) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + +int cam_smmu_get_handle(char *identifier, int *handle_ptr) +{ + int ret = 0; + + if (!identifier) { + CAM_ERR(CAM_SMMU, "Error: iommu hardware name is NULL"); + return -EINVAL; + } + + if (!handle_ptr) { + CAM_ERR(CAM_SMMU, "Error: handle pointer is NULL"); + return -EINVAL; + } + + /* create and put handle in the table */ + ret = cam_smmu_create_add_handle_in_table(identifier, handle_ptr); + if (ret < 0) + CAM_ERR(CAM_SMMU, "Error: %s get handle fail", identifier); + + return ret; +} +EXPORT_SYMBOL(cam_smmu_get_handle); + +int cam_smmu_ops(int handle, enum cam_smmu_ops_param ops) +{ + int ret = 0, idx; + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, "Error: Index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -EINVAL; + } + + switch (ops) { + case CAM_SMMU_ATTACH: { + ret = cam_smmu_attach(idx); + break; + } + case CAM_SMMU_DETACH: { + ret = cam_smmu_detach_device(idx); + break; + } + case CAM_SMMU_VOTE: + case CAM_SMMU_DEVOTE: + default: + CAM_ERR(CAM_SMMU, "Error: idx = %d, ops = %d", idx, ops); + ret = -EINVAL; + } + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return ret; +} +EXPORT_SYMBOL(cam_smmu_ops); + +static int cam_smmu_alloc_scratch_buffer_add_to_list(int idx, + size_t virt_len, + size_t phys_len, + unsigned int iommu_dir, + dma_addr_t *virt_addr) +{ + unsigned long nents = virt_len / phys_len; + struct cam_dma_buff_info *mapping_info = NULL; + size_t unmapped; + dma_addr_t iova = 0; + struct scatterlist *sg; + int i = 0; + int rc; + struct iommu_domain *domain = NULL; + struct page *page; + struct sg_table *table = NULL; + + CAM_DBG(CAM_SMMU, "nents = %lu, idx = %d, virt_len = %zx", + nents, idx, virt_len); + CAM_DBG(CAM_SMMU, "phys_len = %zx, iommu_dir = %d, virt_addr = %pK", + phys_len, iommu_dir, virt_addr); + + /* + * This table will go inside the 'mapping' structure + * where it will be held until put_scratch_buffer is called + */ + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) { + rc = -ENOMEM; + goto err_table_alloc; + } + + rc = sg_alloc_table(table, nents, GFP_KERNEL); + if (rc < 0) { + rc = -EINVAL; + goto err_sg_alloc; + } + + page = alloc_pages(GFP_KERNEL, get_order(phys_len)); + if (!page) { + rc = -ENOMEM; + goto err_page_alloc; + } + + /* Now we create the sg list */ + for_each_sg(table->sgl, sg, table->nents, i) + sg_set_page(sg, page, phys_len, 0); + + + /* Get the domain from within our cb_set struct and map it*/ + domain = iommu_cb_set.cb_info[idx].domain; + + rc = cam_smmu_alloc_scratch_va(&iommu_cb_set.cb_info[idx].scratch_map, + virt_len, &iova); + + if (rc < 0) { + CAM_ERR(CAM_SMMU, + "Could not find valid iova for scratch buffer"); + goto err_iommu_map; + } + + if (iommu_map_sg(domain, + iova, + table->sgl, + table->nents, + iommu_dir) != virt_len) { + CAM_ERR(CAM_SMMU, "iommu_map_sg() failed"); + goto err_iommu_map; + } + + /* Now update our mapping information within the cb_set struct */ + mapping_info = kzalloc(sizeof(struct cam_dma_buff_info), GFP_KERNEL); + if (!mapping_info) { + rc = -ENOMEM; + goto err_mapping_info; + } + + mapping_info->ion_fd = 0xDEADBEEF; + mapping_info->buf = NULL; + mapping_info->attach = NULL; + mapping_info->table = table; + mapping_info->paddr = iova; + mapping_info->len = virt_len; + mapping_info->iommu_dir = iommu_dir; + mapping_info->ref_count = 1; + mapping_info->phys_len = phys_len; + mapping_info->region_id = CAM_SMMU_REGION_SCRATCH; + + CAM_DBG(CAM_SMMU, "paddr = %pK, len = %zx, phys_len = %zx", + (void *)mapping_info->paddr, + mapping_info->len, mapping_info->phys_len); + + list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list); + + *virt_addr = (dma_addr_t)iova; + + CAM_DBG(CAM_SMMU, "mapped virtual address = %lx", + (unsigned long)*virt_addr); + return 0; + +err_mapping_info: + unmapped = iommu_unmap(domain, iova, virt_len); + if (unmapped != virt_len) + CAM_ERR(CAM_SMMU, "Unmapped only %zx instead of %zx", + unmapped, virt_len); +err_iommu_map: + __free_pages(page, get_order(phys_len)); +err_page_alloc: + sg_free_table(table); +err_sg_alloc: + kfree(table); +err_table_alloc: + return rc; +} + +static int cam_smmu_free_scratch_buffer_remove_from_list( + struct cam_dma_buff_info *mapping_info, + int idx) +{ + int rc = 0; + size_t unmapped; + struct iommu_domain *domain = + iommu_cb_set.cb_info[idx].domain; + struct scratch_mapping *scratch_map = + &iommu_cb_set.cb_info[idx].scratch_map; + + if (!mapping_info->table) { + CAM_ERR(CAM_SMMU, + "Error: Invalid params: dev = %pK, table = %pK", + (void *)iommu_cb_set.cb_info[idx].dev, + (void *)mapping_info->table); + return -EINVAL; + } + + /* Clean up the mapping_info struct from the list */ + unmapped = iommu_unmap(domain, mapping_info->paddr, mapping_info->len); + if (unmapped != mapping_info->len) + CAM_ERR(CAM_SMMU, "Unmapped only %zx instead of %zx", + unmapped, mapping_info->len); + + rc = cam_smmu_free_scratch_va(scratch_map, + mapping_info->paddr, + mapping_info->len); + if (rc < 0) { + CAM_ERR(CAM_SMMU, + "Error: Invalid iova while freeing scratch buffer"); + rc = -EINVAL; + } + + __free_pages(sg_page(mapping_info->table->sgl), + get_order(mapping_info->phys_len)); + sg_free_table(mapping_info->table); + kfree(mapping_info->table); + list_del_init(&mapping_info->list); + + kfree(mapping_info); + mapping_info = NULL; + + return rc; +} + +int cam_smmu_get_scratch_iova(int handle, + enum cam_smmu_map_dir dir, + dma_addr_t *paddr_ptr, + size_t virt_len, + size_t phys_len) +{ + int idx, rc; + unsigned int iommu_dir; + + if (!paddr_ptr || !virt_len || !phys_len) { + CAM_ERR(CAM_SMMU, "Error: Input pointer or lengths invalid"); + return -EINVAL; + } + + if (virt_len < phys_len) { + CAM_ERR(CAM_SMMU, "Error: virt_len > phys_len"); + return -EINVAL; + } + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + iommu_dir = cam_smmu_translate_dir_to_iommu_dir(dir); + if (iommu_dir == IOMMU_INVALID_DIR) { + CAM_ERR(CAM_SMMU, + "Error: translate direction failed. dir = %d", dir); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto error; + } + + if (!iommu_cb_set.cb_info[idx].scratch_buf_support) { + CAM_ERR(CAM_SMMU, + "Error: Context bank does not support scratch bufs"); + rc = -EINVAL; + goto error; + } + + CAM_DBG(CAM_SMMU, "smmu handle = %x, idx = %d, dir = %d", + handle, idx, dir); + CAM_DBG(CAM_SMMU, "virt_len = %zx, phys_len = %zx", + phys_len, virt_len); + + if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) { + CAM_ERR(CAM_SMMU, + "Err:Dev %s should call SMMU attach before map buffer", + iommu_cb_set.cb_info[idx].name); + rc = -EINVAL; + goto error; + } + + if (!IS_ALIGNED(virt_len, PAGE_SIZE)) { + CAM_ERR(CAM_SMMU, + "Requested scratch buffer length not page aligned"); + rc = -EINVAL; + goto error; + } + + if (!IS_ALIGNED(virt_len, phys_len)) { + CAM_ERR(CAM_SMMU, + "Requested virt length not aligned with phys length"); + rc = -EINVAL; + goto error; + } + + rc = cam_smmu_alloc_scratch_buffer_add_to_list(idx, + virt_len, + phys_len, + iommu_dir, + paddr_ptr); + if (rc < 0) + CAM_ERR(CAM_SMMU, "Error: mapping or add list fail"); + +error: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} + +int cam_smmu_put_scratch_iova(int handle, + dma_addr_t paddr) +{ + int idx; + int rc = -1; + struct cam_dma_buff_info *mapping_info; + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + /* find index in the iommu_cb_set.cb_info */ + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto handle_err; + } + + if (!iommu_cb_set.cb_info[idx].scratch_buf_support) { + CAM_ERR(CAM_SMMU, + "Error: Context bank does not support scratch buffers"); + rc = -EINVAL; + goto handle_err; + } + + /* Based on virtual address and index, we can find mapping info + * of the scratch buffer + */ + mapping_info = cam_smmu_find_mapping_by_virt_address(idx, paddr); + if (!mapping_info) { + CAM_ERR(CAM_SMMU, "Error: Invalid params"); + rc = -ENODEV; + goto handle_err; + } + + /* unmapping one buffer from device */ + rc = cam_smmu_free_scratch_buffer_remove_from_list(mapping_info, idx); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: unmap or remove list fail"); + goto handle_err; + } + +handle_err: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} + +static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, + enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, + size_t *len_ptr) +{ + int rc = 0; + struct dma_buf *dmabuf = NULL; + struct dma_buf_attachment *attach = NULL; + struct sg_table *table = NULL; + struct cam_sec_buff_info *mapping_info; + + /* clean the content from clients */ + *paddr_ptr = (dma_addr_t)NULL; + *len_ptr = (size_t)0; + + dmabuf = dma_buf_get(ion_fd); + if (IS_ERR_OR_NULL((void *)(dmabuf))) { + CAM_ERR(CAM_SMMU, + "Error: dma buf get failed, idx=%d, ion_fd=%d", + idx, ion_fd); + rc = PTR_ERR(dmabuf); + goto err_out; + } + + /* + * ion_phys() is deprecated. call dma_buf_attach() and + * dma_buf_map_attachment() to get the buffer's physical + * address. + */ + attach = dma_buf_attach(dmabuf, iommu_cb_set.cb_info[idx].dev); + if (IS_ERR_OR_NULL(attach)) { + CAM_ERR(CAM_SMMU, + "Error: dma buf attach failed, idx=%d, ion_fd=%d", + idx, ion_fd); + rc = PTR_ERR(attach); + goto err_put; + } + + attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; + + table = dma_buf_map_attachment(attach, dma_dir); + if (IS_ERR_OR_NULL(table)) { + CAM_ERR(CAM_SMMU, "Error: dma buf map attachment failed"); + rc = PTR_ERR(table); + goto err_detach; + } + + /* return addr and len to client */ + *paddr_ptr = sg_phys(table->sgl); + *len_ptr = (size_t)sg_dma_len(table->sgl); + + /* fill up mapping_info */ + mapping_info = kzalloc(sizeof(struct cam_sec_buff_info), GFP_KERNEL); + if (!mapping_info) { + rc = -ENOMEM; + goto err_unmap_sg; + } + + mapping_info->ion_fd = ion_fd; + mapping_info->paddr = *paddr_ptr; + mapping_info->len = *len_ptr; + mapping_info->dir = dma_dir; + mapping_info->ref_count = 1; + mapping_info->buf = dmabuf; + + CAM_DBG(CAM_SMMU, "idx=%d, ion_fd=%d, dev=%pK, paddr=%pK, len=%u", + idx, ion_fd, + (void *)iommu_cb_set.cb_info[idx].dev, + (void *)*paddr_ptr, (unsigned int)*len_ptr); + + /* add to the list */ + list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list); + + return 0; + +err_unmap_sg: + dma_buf_unmap_attachment(attach, table, dma_dir); +err_detach: + dma_buf_detach(dmabuf, attach); +err_put: + dma_buf_put(dmabuf); +err_out: + return rc; +} + +int cam_smmu_map_stage2_iova(int handle, + int ion_fd, enum cam_smmu_map_dir dir, + dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + int idx, rc; + enum dma_data_direction dma_dir; + enum cam_smmu_buf_state buf_state; + + if (!paddr_ptr || !len_ptr) { + CAM_ERR(CAM_SMMU, + "Error: Invalid inputs, paddr_ptr:%pK, len_ptr: %pK", + paddr_ptr, len_ptr); + return -EINVAL; + } + /* clean the content from clients */ + *paddr_ptr = (dma_addr_t)NULL; + *len_ptr = (size_t)0; + + dma_dir = cam_smmu_translate_dir(dir); + if (dma_dir == DMA_NONE) { + CAM_ERR(CAM_SMMU, + "Error: translate direction failed. dir = %d", dir); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if ((handle == HANDLE_INIT) || + (idx < 0) || + (idx >= iommu_cb_set.cb_num)) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + if (!iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't map secure mem to non secure cb, idx=%d", + idx); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, idx=%d, table_hdl=%x, hdl=%x", + idx, iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto get_addr_end; + } + + buf_state = cam_smmu_check_secure_fd_in_list(idx, ion_fd, paddr_ptr, + len_ptr); + if (buf_state == CAM_SMMU_BUFF_EXIST) { + CAM_DBG(CAM_SMMU, + "fd:%d already in list idx:%d, handle=%d give same addr back", + ion_fd, idx, handle); + rc = 0; + goto get_addr_end; + } + rc = cam_smmu_map_stage2_buffer_and_add_to_list(idx, ion_fd, dma_dir, + paddr_ptr, len_ptr); + if (rc < 0) { + CAM_ERR(CAM_SMMU, + "Error: mapping or add list fail, idx=%d, handle=%d, fd=%d, rc=%d", + idx, handle, ion_fd, rc); + goto get_addr_end; + } + +get_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_map_stage2_iova); + +static int cam_smmu_secure_unmap_buf_and_remove_from_list( + struct cam_sec_buff_info *mapping_info, + int idx) +{ + if (!mapping_info) { + CAM_ERR(CAM_SMMU, "Error: List doesn't exist"); + return -EINVAL; + } + dma_buf_put(mapping_info->buf); + list_del_init(&mapping_info->list); + + CAM_DBG(CAM_SMMU, "unmap fd: %d, idx : %d", mapping_info->ion_fd, idx); + + /* free one buffer */ + kfree(mapping_info); + return 0; +} + +int cam_smmu_unmap_stage2_iova(int handle, int ion_fd) +{ + int idx, rc; + struct cam_sec_buff_info *mapping_info; + + /* find index in the iommu_cb_set.cb_info */ + idx = GET_SMMU_TABLE_IDX(handle); + if ((handle == HANDLE_INIT) || + (idx < 0) || + (idx >= iommu_cb_set.cb_num)) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + if (!iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't unmap secure mem from non secure cb"); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto put_addr_end; + } + + /* based on ion fd and index, we can find mapping info of buffer */ + mapping_info = cam_smmu_find_mapping_by_sec_buf_idx(idx, ion_fd); + if (!mapping_info) { + CAM_ERR(CAM_SMMU, + "Error: Invalid params! idx = %d, fd = %d", + idx, ion_fd); + rc = -EINVAL; + goto put_addr_end; + } + + mapping_info->ref_count--; + if (mapping_info->ref_count > 0) { + CAM_DBG(CAM_SMMU, + "idx: %d fd = %d ref_count: %d", + idx, ion_fd, mapping_info->ref_count); + rc = 0; + goto put_addr_end; + } + mapping_info->ref_count = 0; + + /* unmapping one buffer from device */ + rc = cam_smmu_secure_unmap_buf_and_remove_from_list(mapping_info, idx); + if (rc) { + CAM_ERR(CAM_SMMU, "Error: unmap or remove list fail"); + goto put_addr_end; + } + +put_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_unmap_stage2_iova); + +static int cam_smmu_map_iova_validate_params(int handle, + enum cam_smmu_map_dir dir, + dma_addr_t *paddr_ptr, size_t *len_ptr, + enum cam_smmu_region_id region_id) +{ + int idx, rc = 0; + enum dma_data_direction dma_dir; + + if (!paddr_ptr || !len_ptr) { + CAM_ERR(CAM_SMMU, "Input pointers are invalid"); + return -EINVAL; + } + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Invalid handle"); + return -EINVAL; + } + + /* clean the content from clients */ + *paddr_ptr = (dma_addr_t)NULL; + if (region_id != CAM_SMMU_REGION_SHARED) + *len_ptr = (size_t)0; + + dma_dir = cam_smmu_translate_dir(dir); + if (dma_dir == DMA_NONE) { + CAM_ERR(CAM_SMMU, "translate direction failed. dir = %d", dir); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, "handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + return rc; +} + +int cam_smmu_map_user_iova(int handle, int ion_fd, + enum cam_smmu_map_dir dir, dma_addr_t *paddr_ptr, + size_t *len_ptr, enum cam_smmu_region_id region_id) +{ + int idx, rc = 0; + enum cam_smmu_buf_state buf_state; + enum dma_data_direction dma_dir; + + rc = cam_smmu_map_iova_validate_params(handle, dir, paddr_ptr, + len_ptr, region_id); + if (rc) { + CAM_ERR(CAM_SMMU, "initial checks failed, unable to proceed"); + return rc; + } + + dma_dir = (enum dma_data_direction)dir; + idx = GET_SMMU_TABLE_IDX(handle); + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't map non-secure mem to secure cb idx=%d", + idx); + rc = -EINVAL; + goto get_addr_end; + } + + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "hdl is not valid, idx=%d, table_hdl = %x, hdl = %x", + idx, iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto get_addr_end; + } + + if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) { + CAM_ERR(CAM_SMMU, + "Err:Dev %s should call SMMU attach before map buffer", + iommu_cb_set.cb_info[idx].name); + rc = -EINVAL; + goto get_addr_end; + } + + buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr); + if (buf_state == CAM_SMMU_BUFF_EXIST) { + CAM_ERR(CAM_SMMU, + "fd:%d already in list idx:%d, handle=%d, give same addr back", + ion_fd, idx, handle); + rc = -EALREADY; + goto get_addr_end; + } + + rc = cam_smmu_map_buffer_and_add_to_list(idx, ion_fd, dma_dir, + paddr_ptr, len_ptr, region_id); + if (rc < 0) + CAM_ERR(CAM_SMMU, + "mapping or add list fail, idx=%d, fd=%d, region=%d, rc=%d", + idx, ion_fd, region_id, rc); + +get_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_map_user_iova); + +int cam_smmu_map_kernel_iova(int handle, struct dma_buf *buf, + enum cam_smmu_map_dir dir, dma_addr_t *paddr_ptr, + size_t *len_ptr, enum cam_smmu_region_id region_id) +{ + int idx, rc = 0; + enum cam_smmu_buf_state buf_state; + enum dma_data_direction dma_dir; + + rc = cam_smmu_map_iova_validate_params(handle, dir, paddr_ptr, + len_ptr, region_id); + if (rc) { + CAM_ERR(CAM_SMMU, "initial checks failed, unable to proceed"); + return rc; + } + + dma_dir = cam_smmu_translate_dir(dir); + idx = GET_SMMU_TABLE_IDX(handle); + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't map non-secure mem to secure cb"); + rc = -EINVAL; + goto get_addr_end; + } + + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, "hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto get_addr_end; + } + + if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) { + CAM_ERR(CAM_SMMU, + "Err:Dev %s should call SMMU attach before map buffer", + iommu_cb_set.cb_info[idx].name); + rc = -EINVAL; + goto get_addr_end; + } + + buf_state = cam_smmu_check_dma_buf_in_list(idx, buf, + paddr_ptr, len_ptr); + if (buf_state == CAM_SMMU_BUFF_EXIST) { + CAM_ERR(CAM_SMMU, + "dma_buf :%pK already in the list", buf); + rc = -EALREADY; + goto get_addr_end; + } + + rc = cam_smmu_map_kernel_buffer_and_add_to_list(idx, buf, dma_dir, + paddr_ptr, len_ptr, region_id); + if (rc < 0) + CAM_ERR(CAM_SMMU, "mapping or add list fail"); + +get_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_map_kernel_iova); + +int cam_smmu_get_iova(int handle, int ion_fd, + dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + int idx, rc = 0; + enum cam_smmu_buf_state buf_state; + + if (!paddr_ptr || !len_ptr) { + CAM_ERR(CAM_SMMU, "Error: Input pointers are invalid"); + return -EINVAL; + } + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + /* clean the content from clients */ + *paddr_ptr = (dma_addr_t)NULL; + *len_ptr = (size_t)0; + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + if (iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't get non-secure mem from secure cb"); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto get_addr_end; + } + + buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr); + if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) { + CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd); + rc = -EINVAL; + goto get_addr_end; + } + +get_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_get_iova); + +int cam_smmu_get_stage2_iova(int handle, int ion_fd, + dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + int idx, rc = 0; + enum cam_smmu_buf_state buf_state; + + if (!paddr_ptr || !len_ptr) { + CAM_ERR(CAM_SMMU, "Error: Input pointers are invalid"); + return -EINVAL; + } + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + /* clean the content from clients */ + *paddr_ptr = (dma_addr_t)NULL; + *len_ptr = (size_t)0; + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + if (!iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't get secure mem from non secure cb"); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto get_addr_end; + } + + buf_state = cam_smmu_validate_secure_fd_in_list(idx, + ion_fd, + paddr_ptr, + len_ptr); + + if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) { + CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd); + rc = -EINVAL; + goto get_addr_end; + } + +get_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_get_stage2_iova); + +static int cam_smmu_unmap_validate_params(int handle) +{ + int idx; + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + /* find index in the iommu_cb_set.cb_info */ + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + return 0; +} + +int cam_smmu_unmap_user_iova(int handle, + int ion_fd, enum cam_smmu_region_id region_id) +{ + int idx, rc; + struct cam_dma_buff_info *mapping_info; + + rc = cam_smmu_unmap_validate_params(handle); + if (rc) { + CAM_ERR(CAM_SMMU, "unmap util validation failure"); + return rc; + } + + idx = GET_SMMU_TABLE_IDX(handle); + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't unmap non-secure mem from secure cb"); + rc = -EINVAL; + goto unmap_end; + } + + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto unmap_end; + } + + /* Based on ion_fd & index, we can find mapping info of buffer */ + mapping_info = cam_smmu_find_mapping_by_ion_index(idx, ion_fd); + + if (!mapping_info) { + CAM_ERR(CAM_SMMU, + "Error: Invalid params idx = %d, fd = %d", + idx, ion_fd); + rc = -EINVAL; + goto unmap_end; + } + + /* Unmapping one buffer from device */ + CAM_DBG(CAM_SMMU, "SMMU: removing buffer idx = %d", idx); + rc = cam_smmu_unmap_buf_and_remove_from_list(mapping_info, idx); + if (rc < 0) + CAM_ERR(CAM_SMMU, "Error: unmap or remove list fail"); + +unmap_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_unmap_user_iova); + +int cam_smmu_unmap_kernel_iova(int handle, + struct dma_buf *buf, enum cam_smmu_region_id region_id) +{ + int idx, rc; + struct cam_dma_buff_info *mapping_info; + + rc = cam_smmu_unmap_validate_params(handle); + if (rc) { + CAM_ERR(CAM_SMMU, "unmap util validation failure"); + return rc; + } + + idx = GET_SMMU_TABLE_IDX(handle); + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].is_secure) { + CAM_ERR(CAM_SMMU, + "Error: can't unmap non-secure mem from secure cb"); + rc = -EINVAL; + goto unmap_end; + } + + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto unmap_end; + } + + /* Based on dma_buf & index, we can find mapping info of buffer */ + mapping_info = cam_smmu_find_mapping_by_dma_buf(idx, buf); + + if (!mapping_info) { + CAM_ERR(CAM_SMMU, + "Error: Invalid params idx = %d, dma_buf = %pK", + idx, buf); + rc = -EINVAL; + goto unmap_end; + } + + /* Unmapping one buffer from device */ + CAM_DBG(CAM_SMMU, "SMMU: removing buffer idx = %d", idx); + rc = cam_smmu_unmap_buf_and_remove_from_list(mapping_info, idx); + if (rc < 0) + CAM_ERR(CAM_SMMU, "Error: unmap or remove list fail"); + +unmap_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_unmap_kernel_iova); + + +int cam_smmu_put_iova(int handle, int ion_fd) +{ + int idx; + int rc = 0; + struct cam_dma_buff_info *mapping_info; + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + /* find index in the iommu_cb_set.cb_info */ + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + rc = -EINVAL; + goto put_addr_end; + } + + /* based on ion fd and index, we can find mapping info of buffer */ + mapping_info = cam_smmu_find_mapping_by_ion_index(idx, ion_fd); + if (!mapping_info) { + CAM_ERR(CAM_SMMU, "Error: Invalid params idx = %d, fd = %d", + idx, ion_fd); + rc = -EINVAL; + goto put_addr_end; + } + +put_addr_end: + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return rc; +} +EXPORT_SYMBOL(cam_smmu_put_iova); + +int cam_smmu_destroy_handle(int handle) +{ + int idx; + + if (handle == HANDLE_INIT) { + CAM_ERR(CAM_SMMU, "Error: Invalid handle"); + return -EINVAL; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return -EINVAL; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -EINVAL; + } + + if (!list_empty_careful(&iommu_cb_set.cb_info[idx].smmu_buf_list)) { + CAM_ERR(CAM_SMMU, "UMD %s buffer list is not clean", + iommu_cb_set.cb_info[idx].name); + cam_smmu_print_user_list(idx); + cam_smmu_clean_user_buffer_list(idx); + } + + if (!list_empty_careful( + &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list)) { + CAM_ERR(CAM_SMMU, "KMD %s buffer list is not clean", + iommu_cb_set.cb_info[idx].name); + cam_smmu_print_kernel_list(idx); + cam_smmu_clean_kernel_buffer_list(idx); + } + + if (iommu_cb_set.cb_info[idx].is_secure) { + if (iommu_cb_set.cb_info[idx].secure_count == 0) { + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return -EPERM; + } + + iommu_cb_set.cb_info[idx].secure_count--; + if (iommu_cb_set.cb_info[idx].secure_count == 0) { + iommu_cb_set.cb_info[idx].cb_count = 0; + iommu_cb_set.cb_info[idx].handle = HANDLE_INIT; + } + + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return 0; + } + + iommu_cb_set.cb_info[idx].cb_count = 0; + iommu_cb_set.cb_info[idx].handle = HANDLE_INIT; + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return 0; +} +EXPORT_SYMBOL(cam_smmu_destroy_handle); + +static void cam_smmu_deinit_cb(struct cam_context_bank_info *cb) +{ + if (cb->io_support && cb->domain) { + cb->domain = NULL; + } + + if (cb->shared_support) { + gen_pool_destroy(cb->shared_mem_pool); + cb->shared_mem_pool = NULL; + } + + if (cb->scratch_buf_support) { + kfree(cb->scratch_map.bitmap); + cb->scratch_map.bitmap = NULL; + } +} + +static void cam_smmu_release_cb(struct platform_device *pdev) +{ + int i = 0; + + for (i = 0; i < iommu_cb_set.cb_num; i++) + cam_smmu_deinit_cb(&iommu_cb_set.cb_info[i]); + + devm_kfree(&pdev->dev, iommu_cb_set.cb_info); + iommu_cb_set.cb_num = 0; +} + +static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, + struct device *dev) +{ + int rc = 0; + + if (!cb || !dev) { + CAM_ERR(CAM_SMMU, "Error: invalid input params"); + return -EINVAL; + } + + cb->dev = dev; + cb->is_fw_allocated = false; + cb->is_secheap_allocated = false; + + /* Create a pool with 64K granularity for supporting shared memory */ + if (cb->shared_support) { + cb->shared_mem_pool = gen_pool_create( + SHARED_MEM_POOL_GRANULARITY, -1); + + if (!cb->shared_mem_pool) + return -ENOMEM; + + rc = gen_pool_add(cb->shared_mem_pool, + cb->shared_info.iova_start, + cb->shared_info.iova_len, + -1); + + CAM_DBG(CAM_SMMU, "Shared mem start->%lX", + (unsigned long)cb->shared_info.iova_start); + CAM_DBG(CAM_SMMU, "Shared mem len->%zu", + cb->shared_info.iova_len); + + if (rc) { + CAM_ERR(CAM_SMMU, "Genpool chunk creation failed"); + gen_pool_destroy(cb->shared_mem_pool); + cb->shared_mem_pool = NULL; + return rc; + } + } + + if (cb->scratch_buf_support) { + rc = cam_smmu_init_scratch_map(&cb->scratch_map, + cb->scratch_info.iova_start, + cb->scratch_info.iova_len, + 0); + if (rc < 0) { + CAM_ERR(CAM_SMMU, + "Error: failed to create scratch map"); + rc = -ENODEV; + goto end; + } + } + + /* create a virtual mapping */ + if (cb->io_support) { + cb->domain = iommu_get_domain_for_dev(dev); + if (IS_ERR(cb->domain)) { + CAM_ERR(CAM_SMMU, "Error: create domain Failed"); + rc = -ENODEV; + goto end; + } + cb->state = CAM_SMMU_ATTACH; + } else { + CAM_ERR(CAM_SMMU, "Context bank does not have IO region"); + rc = -ENODEV; + goto end; + } + + return rc; +end: + if (cb->shared_support) { + gen_pool_destroy(cb->shared_mem_pool); + cb->shared_mem_pool = NULL; + } + + if (cb->scratch_buf_support) { + kfree(cb->scratch_map.bitmap); + cb->scratch_map.bitmap = NULL; + } + + return rc; +} + +static int cam_alloc_smmu_context_banks(struct device *dev) +{ + struct device_node *domains_child_node = NULL; + + if (!dev) { + CAM_ERR(CAM_SMMU, "Error: Invalid device"); + return -ENODEV; + } + + iommu_cb_set.cb_num = 0; + + /* traverse thru all the child nodes and increment the cb count */ + for_each_available_child_of_node(dev->of_node, domains_child_node) { + if (of_device_is_compatible(domains_child_node, + "qcom,msm-cam-smmu-cb")) + iommu_cb_set.cb_num++; + + if (of_device_is_compatible(domains_child_node, + "qcom,qsmmu-cam-cb")) + iommu_cb_set.cb_num++; + } + + if (iommu_cb_set.cb_num == 0) { + CAM_ERR(CAM_SMMU, "Error: no context banks present"); + return -ENOENT; + } + + /* allocate memory for the context banks */ + iommu_cb_set.cb_info = devm_kzalloc(dev, + iommu_cb_set.cb_num * sizeof(struct cam_context_bank_info), + GFP_KERNEL); + + if (!iommu_cb_set.cb_info) { + CAM_ERR(CAM_SMMU, "Error: cannot allocate context banks"); + return -ENOMEM; + } + + cam_smmu_reset_iommu_table(CAM_SMMU_TABLE_INIT); + iommu_cb_set.cb_init_count = 0; + + CAM_DBG(CAM_SMMU, "no of context banks :%d", iommu_cb_set.cb_num); + return 0; +} + +static int cam_smmu_get_memory_regions_info(struct device_node *of_node, + struct cam_context_bank_info *cb) +{ + int rc = 0; + struct device_node *mem_map_node = NULL; + struct device_node *child_node = NULL; + const char *region_name; + int num_regions = 0; + + if (!of_node || !cb) { + CAM_ERR(CAM_SMMU, "Invalid argument(s)"); + return -EINVAL; + } + + mem_map_node = of_get_child_by_name(of_node, "iova-mem-map"); + cb->is_secure = of_property_read_bool(of_node, "qcom,secure-cb"); + + /* + * We always expect a memory map node, except when it is a secure + * context bank. + */ + if (!mem_map_node) { + if (cb->is_secure) + return 0; + CAM_ERR(CAM_SMMU, "iova-mem-map not present"); + return -EINVAL; + } + + for_each_available_child_of_node(mem_map_node, child_node) { + uint32_t region_start; + uint32_t region_len; + uint32_t region_id; + uint32_t qdss_region_phy_addr = 0; + + num_regions++; + rc = of_property_read_string(child_node, + "iova-region-name", ®ion_name); + if (rc < 0) { + of_node_put(mem_map_node); + CAM_ERR(CAM_SMMU, "IOVA region not found"); + return -EINVAL; + } + + rc = of_property_read_u32(child_node, + "iova-region-start", ®ion_start); + if (rc < 0) { + of_node_put(mem_map_node); + CAM_ERR(CAM_SMMU, "Failed to read iova-region-start"); + return -EINVAL; + } + + rc = of_property_read_u32(child_node, + "iova-region-len", ®ion_len); + if (rc < 0) { + of_node_put(mem_map_node); + CAM_ERR(CAM_SMMU, "Failed to read iova-region-len"); + return -EINVAL; + } + + rc = of_property_read_u32(child_node, + "iova-region-id", ®ion_id); + if (rc < 0) { + of_node_put(mem_map_node); + CAM_ERR(CAM_SMMU, "Failed to read iova-region-id"); + return -EINVAL; + } + + if (strcmp(region_name, qdss_region_name) == 0) { + rc = of_property_read_u32(child_node, + "qdss-phy-addr", &qdss_region_phy_addr); + if (rc < 0) { + of_node_put(mem_map_node); + CAM_ERR(CAM_SMMU, + "Failed to read qdss phy addr"); + return -EINVAL; + } + } + + switch (region_id) { + case CAM_SMMU_REGION_FIRMWARE: + cb->firmware_support = 1; + cb->firmware_info.iova_start = region_start; + cb->firmware_info.iova_len = region_len; + break; + case CAM_SMMU_REGION_SHARED: + cb->shared_support = 1; + cb->shared_info.iova_start = region_start; + cb->shared_info.iova_len = region_len; + break; + case CAM_SMMU_REGION_SCRATCH: + cb->scratch_buf_support = 1; + cb->scratch_info.iova_start = region_start; + cb->scratch_info.iova_len = region_len; + break; + case CAM_SMMU_REGION_IO: + cb->io_support = 1; + cb->io_info.iova_start = region_start; + cb->io_info.iova_len = region_len; + break; + case CAM_SMMU_REGION_SECHEAP: + cb->secheap_support = 1; + cb->secheap_info.iova_start = region_start; + cb->secheap_info.iova_len = region_len; + break; + case CAM_SMMU_REGION_QDSS: + cb->qdss_support = 1; + cb->qdss_info.iova_start = region_start; + cb->qdss_info.iova_len = region_len; + cb->qdss_phy_addr = qdss_region_phy_addr; + break; + default: + CAM_ERR(CAM_SMMU, + "Incorrect region id present in DT file: %d", + region_id); + } + + CAM_DBG(CAM_SMMU, "Found label -> %s", cb->name); + CAM_DBG(CAM_SMMU, "Found region -> %s", region_name); + CAM_DBG(CAM_SMMU, "region_start -> %X", region_start); + CAM_DBG(CAM_SMMU, "region_len -> %X", region_len); + CAM_DBG(CAM_SMMU, "region_id -> %X", region_id); + } + of_node_put(mem_map_node); + + if (!num_regions) { + CAM_ERR(CAM_SMMU, + "No memory regions found, at least one needed"); + rc = -ENODEV; + } + + return rc; +} + +static int cam_populate_smmu_context_banks(struct device *dev, + enum cam_iommu_type type) +{ + int rc = 0; + struct cam_context_bank_info *cb; + struct device *ctx = NULL; + + if (!dev) { + CAM_ERR(CAM_SMMU, "Error: Invalid device"); + return -ENODEV; + } + + /* check the bounds */ + if (iommu_cb_set.cb_init_count >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, "Error: populate more than allocated cb"); + rc = -EBADHANDLE; + goto cb_init_fail; + } + + /* read the context bank from cb set */ + cb = &iommu_cb_set.cb_info[iommu_cb_set.cb_init_count]; + + /* set the name of the context bank */ + rc = of_property_read_string(dev->of_node, "label", &cb->name); + if (rc < 0) { + CAM_ERR(CAM_SMMU, + "Error: failed to read label from sub device"); + goto cb_init_fail; + } + + rc = cam_smmu_get_memory_regions_info(dev->of_node, + cb); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: Getting region info"); + return rc; + } + + if (cb->is_secure) { + /* increment count to next bank */ + cb->dev = dev; + iommu_cb_set.cb_init_count++; + return 0; + } + + /* set up the iommu mapping for the context bank */ + if (type == CAM_QSMMU) { + CAM_ERR(CAM_SMMU, "Error: QSMMU ctx not supported for : %s", + cb->name); + return -ENODEV; + } + + ctx = dev; + CAM_DBG(CAM_SMMU, "getting Arm SMMU ctx : %s", cb->name); + + rc = cam_smmu_setup_cb(cb, ctx); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: failed to setup cb : %s", cb->name); + goto cb_init_fail; + } + if (cb->io_support && cb->domain) + iommu_set_fault_handler(cb->domain, + cam_smmu_iommu_fault_handler, + (void *)cb->name); + /* increment count to next bank */ + iommu_cb_set.cb_init_count++; + + CAM_DBG(CAM_SMMU, "X: cb init count :%d", iommu_cb_set.cb_init_count); + +cb_init_fail: + return rc; +} + +static int cam_smmu_probe(struct platform_device *pdev) +{ + int rc = 0; + struct device *dev = &pdev->dev; + + if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu")) { + rc = cam_alloc_smmu_context_banks(dev); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: allocating context banks"); + return -ENOMEM; + } + } + if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu-cb")) { + rc = cam_populate_smmu_context_banks(dev, CAM_ARM_SMMU); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: populating context banks"); + cam_smmu_release_cb(pdev); + return -ENOMEM; + } + return rc; + } + if (of_device_is_compatible(dev->of_node, "qcom,qsmmu-cam-cb")) { + rc = cam_populate_smmu_context_banks(dev, CAM_QSMMU); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: populating context banks"); + return -ENOMEM; + } + return rc; + } + + if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu-fw-dev")) { + icp_fw.fw_dev = &pdev->dev; + icp_fw.fw_kva = NULL; + icp_fw.fw_dma_hdl = 0; + return rc; + } + + /* probe through all the subdevices */ + rc = of_platform_populate(pdev->dev.of_node, msm_cam_smmu_dt_match, + NULL, &pdev->dev); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: populating devices"); + } else { + INIT_WORK(&iommu_cb_set.smmu_work, cam_smmu_page_fault_work); + mutex_init(&iommu_cb_set.payload_list_lock); + INIT_LIST_HEAD(&iommu_cb_set.payload_list); + } + + return rc; +} + +static int cam_smmu_remove(struct platform_device *pdev) +{ + /* release all the context banks and memory allocated */ + cam_smmu_reset_iommu_table(CAM_SMMU_TABLE_DEINIT); + if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-cam-smmu")) + cam_smmu_release_cb(pdev); + return 0; +} + +static struct platform_driver cam_smmu_driver = { + .probe = cam_smmu_probe, + .remove = cam_smmu_remove, + .driver = { + .name = "msm_cam_smmu", + .owner = THIS_MODULE, + .of_match_table = msm_cam_smmu_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_smmu_init_module(void) +{ + return platform_driver_register(&cam_smmu_driver); +} + +static void __exit cam_smmu_exit_module(void) +{ + platform_driver_unregister(&cam_smmu_driver); +} + +module_init(cam_smmu_init_module); +module_exit(cam_smmu_exit_module); +MODULE_DESCRIPTION("MSM Camera SMMU driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h new file mode 100644 index 000000000000..6932505f0aaf --- /dev/null +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -0,0 +1,395 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SMMU_API_H_ +#define _CAM_SMMU_API_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*Enum for possible CAM SMMU operations */ +enum cam_smmu_ops_param { + CAM_SMMU_ATTACH, + CAM_SMMU_DETACH, + CAM_SMMU_VOTE, + CAM_SMMU_DEVOTE, + CAM_SMMU_OPS_INVALID +}; + +enum cam_smmu_map_dir { + CAM_SMMU_MAP_READ, + CAM_SMMU_MAP_WRITE, + CAM_SMMU_MAP_RW, + CAM_SMMU_MAP_INVALID +}; + +enum cam_smmu_region_id { + CAM_SMMU_REGION_FIRMWARE, + CAM_SMMU_REGION_SHARED, + CAM_SMMU_REGION_SCRATCH, + CAM_SMMU_REGION_IO, + CAM_SMMU_REGION_SECHEAP, + CAM_SMMU_REGION_QDSS +}; + +/** + * @brief : Callback function type that gets called back on cam + * smmu page fault. + * + * @param domain : Iommu domain received in iommu page fault handler + * @param dev : Device received in iommu page fault handler + * @param iova : IOVA where page fault occurred + * @param flags : Flags received in iommu page fault handler + * @param token : Userdata given during callback registration + * @param buf_info : Closest mapped buffer info + */ +typedef void (*cam_smmu_client_page_fault_handler)(struct iommu_domain *domain, + struct device *dev, unsigned long iova, int flags, void *token, + uint32_t buf_info); + +/** + * @brief : Structure to store region information + * + * @param iova_start : Start address of region + * @param iova_len : length of region + */ +struct cam_smmu_region_info { + dma_addr_t iova_start; + size_t iova_len; +}; + +/** + * @brief : Gets an smmu handle + * + * @param identifier: Unique identifier to be used by clients which they + * should get from device tree. CAM SMMU driver will + * not enforce how this string is obtained and will + * only validate this against the list of permitted + * identifiers + * @param handle_ptr: Based on the indentifier, CAM SMMU drivier will + * fill the handle pointed by handle_ptr + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_get_handle(char *identifier, int *handle_ptr); + +/** + * @brief : Performs IOMMU operations + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * @param op : Operation to be performed. Can be either CAM_SMMU_ATTACH + * or CAM_SMMU_DETACH + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_ops(int handle, enum cam_smmu_ops_param op); + +/** + * @brief : Maps user space IOVA for calling driver + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * @param ion_fd: ION handle identifying the memory buffer. + * @dir : Mapping direction: which will traslate toDMA_BIDIRECTIONAL, + * DMA_TO_DEVICE or DMA_FROM_DEVICE + * @dma_addr : Pointer to physical address where mapped address will be + * returned if region_id is CAM_SMMU_REGION_IO. If region_id is + * CAM_SMMU_REGION_SHARED, dma_addr is used as an input parameter + * which specifies the cpu virtual address to map. + * @len_ptr : Length of buffer mapped returned by CAM SMMU driver. + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_map_user_iova(int handle, + int ion_fd, enum cam_smmu_map_dir dir, + dma_addr_t *dma_addr, size_t *len_ptr, + enum cam_smmu_region_id region_id); + +/** + * @brief : Maps kernel space IOVA for calling driver + * + * @param handle : Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * @param buf : dma_buf allocated for kernel usage in mem_mgr + * @dir : Mapping direction: which will traslate toDMA_BIDIRECTIONAL, + * DMA_TO_DEVICE or DMA_FROM_DEVICE + * @dma_addr : Pointer to physical address where mapped address will be + * returned if region_id is CAM_SMMU_REGION_IO. If region_id is + * CAM_SMMU_REGION_SHARED, dma_addr is used as an input + * parameter which specifies the cpu virtual address to map. + * @len_ptr : Length of buffer mapped returned by CAM SMMU driver. + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_map_kernel_iova(int handle, + struct dma_buf *buf, enum cam_smmu_map_dir dir, + dma_addr_t *dma_addr, size_t *len_ptr, + enum cam_smmu_region_id region_id); + +/** + * @brief : Unmaps user space IOVA for calling driver + * + * @param handle: Handle to identify the CAMSMMU client (VFE, CPP, FD etc.) + * @param ion_fd: ION handle identifying the memory buffer. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_unmap_user_iova(int handle, + int ion_fd, enum cam_smmu_region_id region_id); + +/** + * @brief : Unmaps kernel IOVA for calling driver + * + * @param handle: Handle to identify the CAMSMMU client (VFE, CPP, FD etc.) + * @param buf : dma_buf allocated for the kernel + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_unmap_kernel_iova(int handle, + struct dma_buf *buf, enum cam_smmu_region_id region_id); + +/** + * @brief : Allocates a scratch buffer + * + * This function allocates a scratch virtual buffer of length virt_len in the + * device virtual address space mapped to phys_len physically contiguous bytes + * in that device's SMMU. + * + * virt_len and phys_len are expected to be aligned to PAGE_SIZE and with each + * other, otherwise -EINVAL is returned. + * + * -EINVAL will be returned if virt_len is less than phys_len. + * + * Passing a too large phys_len might also cause failure if that much size is + * not available for allocation in a physically contiguous way. + * + * @param handle : Handle to identify the CAMSMMU client (VFE, CPP, FD etc.) + * @param dir : Direction of mapping which will translate to IOMMU_READ + * IOMMU_WRITE or a bit mask of both. + * @param paddr_ptr: Device virtual address that the client device will be + * able to read from/write to + * @param virt_len : Virtual length of the scratch buffer + * @param phys_len : Physical length of the scratch buffer + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ + +int cam_smmu_get_scratch_iova(int handle, + enum cam_smmu_map_dir dir, + dma_addr_t *paddr_ptr, + size_t virt_len, + size_t phys_len); + +/** + * @brief : Frees a scratch buffer + * + * This function frees a scratch buffer and releases the corresponding SMMU + * mappings. + * + * @param handle : Handle to identify the CAMSMMU client (IFE, ICP, etc.) + * @param paddr : Device virtual address of client's scratch buffer that + * will be freed. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ + +int cam_smmu_put_scratch_iova(int handle, + dma_addr_t paddr); + +/** + *@brief : Destroys an smmu handle + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_destroy_handle(int handle); + +/** + * @brief : Finds index by handle in the smmu client table + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * @return Index of SMMU client. Nagative in case of error. + */ +int cam_smmu_find_index_by_handle(int hdl); + +/** + * @brief : Registers smmu fault handler for client + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * @param handler_cb: It is triggered in IOMMU page fault + * @param token: It is input param when trigger page fault handler + */ +void cam_smmu_set_client_page_fault_handler(int handle, + cam_smmu_client_page_fault_handler handler_cb, void *token); + +/** + * @brief : Unregisters smmu fault handler for client + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) + * @param token: It is input param when trigger page fault handler + */ +void cam_smmu_unset_client_page_fault_handler(int handle, void *token); + +/** + * @brief Maps memory from an ION fd into IOVA space + * + * @param handle: SMMU handle identifying the context bank to map to + * @param ion_fd: ION fd of memory to map to + * @param paddr_ptr: Pointer IOVA address that will be returned + * @param len_ptr: Length of memory mapped + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_get_iova(int handle, int ion_fd, + dma_addr_t *paddr_ptr, size_t *len_ptr); + +/** + * @brief Maps memory from an ION fd into IOVA space + * + * @param handle: SMMU handle identifying the secure context bank to map to + * @param ion_fd: ION fd of memory to map to + * @param paddr_ptr: Pointer IOVA address that will be returned + * @param len_ptr: Length of memory mapped + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_get_stage2_iova(int handle, int ion_fd, + dma_addr_t *paddr_ptr, size_t *len_ptr); + +/** + * @brief Unmaps memory from context bank + * + * @param handle: SMMU handle identifying the context bank + * @param ion_fd: ION fd of memory to unmap + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_put_iova(int handle, int ion_fd); + +/** + * @brief Maps secure memory for SMMU handle + * + * @param handle: SMMU handle identifying secure context bank + * @param ion_fd: ION fd to map securely + * @param dir: DMA Direction for the mapping + * @param dma_addr: Returned IOVA address after mapping + * @param len_ptr: Length of memory mapped + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_map_stage2_iova(int handle, + int ion_fd, enum cam_smmu_map_dir dir, dma_addr_t *dma_addr, + size_t *len_ptr); + +/** + * @brief Unmaps secure memopry for SMMU handle + * + * @param handle: SMMU handle identifying secure context bank + * @param ion_fd: ION fd to unmap + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_unmap_stage2_iova(int handle, int ion_fd); + +/** + * @brief Allocates firmware for context bank + * + * @param smmu_hdl: SMMU handle identifying context bank + * @param iova: IOVA address of allocated firmware + * @param kvaddr: CPU mapped address of allocated firmware + * @param len: Length of allocated firmware memory + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_alloc_firmware(int32_t smmu_hdl, + dma_addr_t *iova, + uintptr_t *kvaddr, + size_t *len); + +/** + * @brief Deallocates firmware memory for context bank + * + * @param smmu_hdl: SMMU handle identifying the context bank + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_dealloc_firmware(int32_t smmu_hdl); + +/** + * @brief Gets region information specified by smmu handle and region id + * + * @param smmu_hdl: SMMU handle identifying the context bank + * @param region_id: Region id for which information is desired + * @param region_info: Struct populated with region information + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_get_region_info(int32_t smmu_hdl, + enum cam_smmu_region_id region_id, + struct cam_smmu_region_info *region_info); + +/** + * @brief Reserves secondary heap + * + * @param smmu_hdl: SMMU handle identifying the context bank + * @param iova: IOVA of secondary heap after reservation has completed + * @param buf: Allocated dma_buf for secondary heap + * @param request_len: Length of secondary heap after reservation has completed + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_reserve_sec_heap(int32_t smmu_hdl, + struct dma_buf *buf, + dma_addr_t *iova, + size_t *request_len); + +/** + * @brief Releases secondary heap + * + * @param smmu_hdl: SMMU handle identifying the context bank + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_release_sec_heap(int32_t smmu_hdl); + +/** + * @brief Allocates qdss for context bank + * + * @param smmu_hdl: SMMU handle identifying context bank + * @param iova: IOVA address of allocated qdss + * @param len: Length of allocated qdss memory + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_alloc_qdss(int32_t smmu_hdl, + dma_addr_t *iova, + size_t *len); + +/** + * @brief Deallocates qdss memory for context bank + * + * @param smmu_hdl: SMMU handle identifying the context bank + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_dealloc_qdss(int32_t smmu_hdl); + +/** + * @brief Get start addr & len of I/O region for a given cb + * + * @param smmu_hdl: SMMU handle identifying the context bank + * @param iova: IOVA address of allocated I/O region + * @param len: Length of allocated I/O memory + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_smmu_get_io_region_info(int32_t smmu_hdl, + dma_addr_t *iova, size_t *len); + +#endif /* _CAM_SMMU_API_H_ */ diff --git a/drivers/cam_sync/Makefile b/drivers/cam_sync/Makefile new file mode 100644 index 000000000000..b0868f522549 --- /dev/null +++ b/drivers/cam_sync/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(src) + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sync.o cam_sync_util.o diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c new file mode 100644 index 000000000000..5342de04da8f --- /dev/null +++ b/drivers/cam_sync/cam_sync.c @@ -0,0 +1,1094 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "cam_sync_util.h" +#include "cam_debug_util.h" +#include "cam_common_util.h" + +struct sync_device *sync_dev; + +/* + * Flag to determine whether to enqueue cb of a + * signaled fence onto the workq or invoke it + * directly in the same context + */ +static bool trigger_cb_without_switch; + +int cam_sync_create(int32_t *sync_obj, const char *name) +{ + int rc; + long idx; + bool bit; + + do { + idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS); + if (idx >= CAM_SYNC_MAX_OBJS) + return -ENOMEM; + CAM_DBG(CAM_SYNC, "Index location available at idx: %ld", idx); + bit = test_and_set_bit(idx, sync_dev->bitmap); + } while (bit); + + spin_lock_bh(&sync_dev->row_spinlocks[idx]); + rc = cam_sync_init_row(sync_dev->sync_table, idx, name, + CAM_SYNC_TYPE_INDV); + if (rc) { + CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld", + idx); + clear_bit(idx, sync_dev->bitmap); + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + return -EINVAL; + } + + *sync_obj = idx; + CAM_DBG(CAM_SYNC, "sync_obj: %i", *sync_obj); + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + + return rc; +} + +int cam_sync_register_callback(sync_callback cb_func, + void *userdata, int32_t sync_obj) +{ + struct sync_callback_info *sync_cb; + struct sync_table_row *row = NULL; + int status = 0; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0 || !cb_func) + return -EINVAL; + + spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); + row = sync_dev->sync_table + sync_obj; + + if (row->state == CAM_SYNC_STATE_INVALID) { + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj %d", + sync_obj); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return -EINVAL; + } + + sync_cb = kzalloc(sizeof(*sync_cb), GFP_ATOMIC); + if (!sync_cb) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return -ENOMEM; + } + + /* Trigger callback if sync object is already in SIGNALED state */ + if ((row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS || + row->state == CAM_SYNC_STATE_SIGNALED_ERROR) && + (!row->remaining)) { + if (trigger_cb_without_switch) { + CAM_DBG(CAM_SYNC, "Invoke callback for sync object:%d", + sync_obj); + status = row->state; + kfree(sync_cb); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + cb_func(sync_obj, status, userdata); + } else { + sync_cb->callback_func = cb_func; + sync_cb->cb_data = userdata; + sync_cb->sync_obj = sync_obj; + INIT_WORK(&sync_cb->cb_dispatch_work, + cam_sync_util_cb_dispatch); + sync_cb->status = row->state; + CAM_DBG(CAM_SYNC, "Enqueue callback for sync object:%d", + sync_cb->sync_obj); + queue_work(sync_dev->work_queue, + &sync_cb->cb_dispatch_work); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + } + + return 0; + } + + sync_cb->callback_func = cb_func; + sync_cb->cb_data = userdata; + sync_cb->sync_obj = sync_obj; + INIT_WORK(&sync_cb->cb_dispatch_work, cam_sync_util_cb_dispatch); + list_add_tail(&sync_cb->list, &row->callback_list); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + + return 0; +} + +int cam_sync_deregister_callback(sync_callback cb_func, + void *userdata, int32_t sync_obj) +{ + struct sync_table_row *row = NULL; + struct sync_callback_info *sync_cb, *temp; + bool found = false; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); + row = sync_dev->sync_table + sync_obj; + + if (row->state == CAM_SYNC_STATE_INVALID) { + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj = %d", + sync_obj); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return -EINVAL; + } + + CAM_DBG(CAM_SYNC, "deregistered callback for sync object:%d", + sync_obj); + list_for_each_entry_safe(sync_cb, temp, &row->callback_list, list) { + if (sync_cb->callback_func == cb_func && + sync_cb->cb_data == userdata) { + list_del_init(&sync_cb->list); + kfree(sync_cb); + found = true; + } + } + + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return found ? 0 : -ENOENT; +} + +int cam_sync_signal(int32_t sync_obj, uint32_t status) +{ + struct sync_table_row *row = NULL; + struct sync_table_row *parent_row = NULL; + struct sync_parent_info *parent_info, *temp_parent_info; + struct list_head parents_list; + int rc = 0; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) { + CAM_ERR(CAM_SYNC, "Error: Out of range sync obj (0 <= %d < %d)", + sync_obj, CAM_SYNC_MAX_OBJS); + return -EINVAL; + } + row = sync_dev->sync_table + sync_obj; + spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); + if (row->state == CAM_SYNC_STATE_INVALID) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj = %d", + sync_obj); + return -EINVAL; + } + + if (row->type == CAM_SYNC_TYPE_GROUP) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + CAM_ERR(CAM_SYNC, + "Error: Signaling a GROUP sync object = %d", + sync_obj); + return -EINVAL; + } + + 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); + return -EALREADY; + } + + if (status != CAM_SYNC_STATE_SIGNALED_SUCCESS && + status != CAM_SYNC_STATE_SIGNALED_ERROR) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + CAM_ERR(CAM_SYNC, + "Error: signaling with undefined status = %d", + status); + return -EINVAL; + } + + if (!atomic_dec_and_test(&row->ref_cnt)) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return 0; + } + + row->state = status; + cam_sync_util_dispatch_signaled_cb(sync_obj, status); + + /* copy parent list to local and release child lock */ + INIT_LIST_HEAD(&parents_list); + list_splice_init(&row->parents_list, &parents_list); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + + if (list_empty(&parents_list)) + return 0; + + /* + * Now iterate over all parents of this object and if they too need to + * be signaled dispatch cb's + */ + list_for_each_entry_safe(parent_info, + temp_parent_info, + &parents_list, + list) { + parent_row = sync_dev->sync_table + parent_info->sync_id; + spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); + parent_row->remaining--; + + rc = cam_sync_util_update_parent_state( + parent_row, + status); + if (rc) { + CAM_ERR(CAM_SYNC, "Invalid parent state %d", + parent_row->state); + spin_unlock_bh( + &sync_dev->row_spinlocks[parent_info->sync_id]); + kfree(parent_info); + continue; + } + + if (!parent_row->remaining) + cam_sync_util_dispatch_signaled_cb( + parent_info->sync_id, parent_row->state); + + spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); + list_del_init(&parent_info->list); + kfree(parent_info); + } + + return 0; +} + +int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj) +{ + int rc; + long idx = 0; + bool bit; + + if (!sync_obj || !merged_obj) { + CAM_ERR(CAM_SYNC, "Invalid pointer(s)"); + return -EINVAL; + } + + if (num_objs <= 1) { + CAM_ERR(CAM_SYNC, "Single object merge is not allowed"); + return -EINVAL; + } + + if (cam_common_util_remove_duplicate_arr(sync_obj, num_objs) + != num_objs) { + CAM_ERR(CAM_SYNC, "The obj list has duplicate fence"); + return -EINVAL; + } + + do { + idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS); + if (idx >= CAM_SYNC_MAX_OBJS) + return -ENOMEM; + bit = test_and_set_bit(idx, sync_dev->bitmap); + } while (bit); + + spin_lock_bh(&sync_dev->row_spinlocks[idx]); + rc = cam_sync_init_group_object(sync_dev->sync_table, + idx, sync_obj, + num_objs); + if (rc < 0) { + CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld", + idx); + clear_bit(idx, sync_dev->bitmap); + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + return -EINVAL; + } + CAM_DBG(CAM_SYNC, "Init row at idx:%ld to merge objects", idx); + *merged_obj = idx; + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + + return 0; +} + +int cam_sync_get_obj_ref(int32_t sync_obj) +{ + struct sync_table_row *row = NULL; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + row = sync_dev->sync_table + sync_obj; + + spin_lock(&sync_dev->row_spinlocks[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); + return -EINVAL; + } + + atomic_inc(&row->ref_cnt); + spin_unlock(&sync_dev->row_spinlocks[sync_obj]); + CAM_DBG(CAM_SYNC, "get ref for obj %d", sync_obj); + + return 0; +} + +int cam_sync_put_obj_ref(int32_t sync_obj) +{ + struct sync_table_row *row = NULL; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + row = sync_dev->sync_table + sync_obj; + atomic_dec(&row->ref_cnt); + CAM_DBG(CAM_SYNC, "put ref for obj %d", sync_obj); + + return 0; +} + +int cam_sync_destroy(int32_t sync_obj) +{ + CAM_DBG(CAM_SYNC, "sync_obj: %i", sync_obj); + return cam_sync_deinit_object(sync_dev->sync_table, sync_obj); +} + +int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms) +{ + unsigned long timeleft; + int rc = -EINVAL; + struct sync_table_row *row = NULL; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + row = sync_dev->sync_table + sync_obj; + + if (row->state == CAM_SYNC_STATE_INVALID) { + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj = %d", + sync_obj); + return -EINVAL; + } + + timeleft = wait_for_completion_timeout(&row->signaled, + msecs_to_jiffies(timeout_ms)); + + if (!timeleft) { + CAM_ERR(CAM_SYNC, + "Error: timed out for sync obj = %d", sync_obj); + rc = -ETIMEDOUT; + } else { + switch (row->state) { + case CAM_SYNC_STATE_INVALID: + case CAM_SYNC_STATE_ACTIVE: + case CAM_SYNC_STATE_SIGNALED_ERROR: + CAM_ERR(CAM_SYNC, + "Error: Wait on invalid state = %d, obj = %d", + row->state, sync_obj); + rc = -EINVAL; + break; + case CAM_SYNC_STATE_SIGNALED_SUCCESS: + rc = 0; + break; + default: + rc = -EINVAL; + break; + } + } + + return rc; +} + +static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl) +{ + struct cam_sync_info sync_create; + int result; + + if (k_ioctl->size != sizeof(struct cam_sync_info)) + return -EINVAL; + + if (!k_ioctl->ioctl_ptr) + return -EINVAL; + + if (copy_from_user(&sync_create, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + result = cam_sync_create(&sync_create.sync_obj, + sync_create.name); + + if (!result) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->ioctl_ptr), + &sync_create, + k_ioctl->size)) + return -EFAULT; + + return result; +} + +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)) + return -EINVAL; + + if (!k_ioctl->ioctl_ptr) + return -EINVAL; + + if (copy_from_user(&sync_signal, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + /* need to get ref for UMD signaled fences */ + 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); +} + +static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl) +{ + struct cam_sync_merge sync_merge; + uint32_t *sync_objs; + uint32_t num_objs; + uint32_t size; + int result; + + if (k_ioctl->size != sizeof(struct cam_sync_merge)) + return -EINVAL; + + if (!k_ioctl->ioctl_ptr) + return -EINVAL; + + if (copy_from_user(&sync_merge, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + if (sync_merge.num_objs >= CAM_SYNC_MAX_OBJS) + return -EINVAL; + + size = sizeof(uint32_t) * sync_merge.num_objs; + sync_objs = kzalloc(size, GFP_ATOMIC); + + if (!sync_objs) + return -ENOMEM; + + if (copy_from_user(sync_objs, + u64_to_user_ptr(sync_merge.sync_objs), + sizeof(uint32_t) * sync_merge.num_objs)) { + kfree(sync_objs); + return -EFAULT; + } + + num_objs = sync_merge.num_objs; + + result = cam_sync_merge(sync_objs, + num_objs, + &sync_merge.merged); + + if (!result) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->ioctl_ptr), + &sync_merge, + k_ioctl->size)) { + kfree(sync_objs); + return -EFAULT; + } + + kfree(sync_objs); + + return result; +} + +static int cam_sync_handle_wait(struct cam_private_ioctl_arg *k_ioctl) +{ + struct cam_sync_wait sync_wait; + + if (k_ioctl->size != sizeof(struct cam_sync_wait)) + return -EINVAL; + + if (!k_ioctl->ioctl_ptr) + return -EINVAL; + + if (copy_from_user(&sync_wait, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + k_ioctl->result = cam_sync_wait(sync_wait.sync_obj, + sync_wait.timeout_ms); + + return 0; +} + +static int cam_sync_handle_destroy(struct cam_private_ioctl_arg *k_ioctl) +{ + struct cam_sync_info sync_create; + + if (k_ioctl->size != sizeof(struct cam_sync_info)) + return -EINVAL; + + if (!k_ioctl->ioctl_ptr) + return -EINVAL; + + if (copy_from_user(&sync_create, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + return cam_sync_destroy(sync_create.sync_obj); +} + +static int cam_sync_handle_register_user_payload( + struct cam_private_ioctl_arg *k_ioctl) +{ + struct cam_sync_userpayload_info userpayload_info; + struct sync_user_payload *user_payload_kernel; + struct sync_user_payload *user_payload_iter; + struct sync_user_payload *temp_upayload_kernel; + uint32_t sync_obj; + struct sync_table_row *row = NULL; + + if (k_ioctl->size != sizeof(struct cam_sync_userpayload_info)) + return -EINVAL; + + if (!k_ioctl->ioctl_ptr) + return -EINVAL; + + if (copy_from_user(&userpayload_info, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + sync_obj = userpayload_info.sync_obj; + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + user_payload_kernel = kzalloc(sizeof(*user_payload_kernel), GFP_KERNEL); + if (!user_payload_kernel) + return -ENOMEM; + + memcpy(user_payload_kernel->payload_data, + userpayload_info.payload, + CAM_SYNC_PAYLOAD_WORDS * sizeof(__u64)); + + spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); + row = sync_dev->sync_table + sync_obj; + + if (row->state == CAM_SYNC_STATE_INVALID) { + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj = %d", + sync_obj); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + kfree(user_payload_kernel); + return -EINVAL; + } + + if (row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS || + row->state == CAM_SYNC_STATE_SIGNALED_ERROR) { + + cam_sync_util_send_v4l2_event(CAM_SYNC_V4L_EVENT_ID_CB_TRIG, + sync_obj, + row->state, + user_payload_kernel->payload_data, + CAM_SYNC_USER_PAYLOAD_SIZE * sizeof(__u64)); + + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + kfree(user_payload_kernel); + return 0; + } + + list_for_each_entry_safe(user_payload_iter, + temp_upayload_kernel, + &row->user_payload_list, + list) { + if (user_payload_iter->payload_data[0] == + user_payload_kernel->payload_data[0] && + user_payload_iter->payload_data[1] == + user_payload_kernel->payload_data[1]) { + + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + kfree(user_payload_kernel); + return -EALREADY; + } + } + + list_add_tail(&user_payload_kernel->list, &row->user_payload_list); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return 0; +} + +static int cam_sync_handle_deregister_user_payload( + struct cam_private_ioctl_arg *k_ioctl) +{ + struct cam_sync_userpayload_info userpayload_info; + struct sync_user_payload *user_payload_kernel, *temp; + uint32_t sync_obj; + struct sync_table_row *row = NULL; + + if (k_ioctl->size != sizeof(struct cam_sync_userpayload_info)) { + CAM_ERR(CAM_SYNC, "Incorrect ioctl size"); + return -EINVAL; + } + + if (!k_ioctl->ioctl_ptr) { + CAM_ERR(CAM_SYNC, "Invalid embedded ioctl ptr"); + return -EINVAL; + } + + if (copy_from_user(&userpayload_info, + u64_to_user_ptr(k_ioctl->ioctl_ptr), + k_ioctl->size)) + return -EFAULT; + + sync_obj = userpayload_info.sync_obj; + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); + row = sync_dev->sync_table + sync_obj; + + if (row->state == CAM_SYNC_STATE_INVALID) { + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj = %d", + sync_obj); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return -EINVAL; + } + + list_for_each_entry_safe(user_payload_kernel, temp, + &row->user_payload_list, list) { + if (user_payload_kernel->payload_data[0] == + userpayload_info.payload[0] && + user_payload_kernel->payload_data[1] == + userpayload_info.payload[1]) { + list_del_init(&user_payload_kernel->list); + kfree(user_payload_kernel); + } + } + + spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); + return 0; +} + +static long cam_sync_dev_ioctl(struct file *filep, void *fh, + bool valid_prio, unsigned int cmd, void *arg) +{ + int32_t rc; + struct sync_device *sync_dev = video_drvdata(filep); + struct cam_private_ioctl_arg k_ioctl; + + if (!sync_dev) { + CAM_ERR(CAM_SYNC, "sync_dev NULL"); + return -EINVAL; + } + + if (!arg) + return -EINVAL; + + if (cmd != CAM_PRIVATE_IOCTL_CMD) + return -ENOIOCTLCMD; + + k_ioctl = *(struct cam_private_ioctl_arg *)arg; + + switch (k_ioctl.id) { + case CAM_SYNC_CREATE: + rc = cam_sync_handle_create(&k_ioctl); + break; + case CAM_SYNC_DESTROY: + rc = cam_sync_handle_destroy(&k_ioctl); + break; + case CAM_SYNC_REGISTER_PAYLOAD: + rc = cam_sync_handle_register_user_payload( + &k_ioctl); + break; + case CAM_SYNC_DEREGISTER_PAYLOAD: + rc = cam_sync_handle_deregister_user_payload( + &k_ioctl); + break; + case CAM_SYNC_SIGNAL: + rc = cam_sync_handle_signal(&k_ioctl); + break; + case CAM_SYNC_MERGE: + rc = cam_sync_handle_merge(&k_ioctl); + break; + case CAM_SYNC_WAIT: + rc = cam_sync_handle_wait(&k_ioctl); + ((struct cam_private_ioctl_arg *)arg)->result = + k_ioctl.result; + break; + default: + rc = -ENOIOCTLCMD; + } + + return rc; +} + +static unsigned int cam_sync_poll(struct file *f, + struct poll_table_struct *pll_table) +{ + int rc = 0; + struct v4l2_fh *eventq = f->private_data; + + if (!eventq) + return -EINVAL; + + poll_wait(f, &eventq->wait, pll_table); + + if (v4l2_event_pending(eventq)) + rc = POLLPRI; + + return rc; +} + +static int cam_sync_open(struct file *filep) +{ + int rc; + struct sync_device *sync_dev = video_drvdata(filep); + + if (!sync_dev) { + CAM_ERR(CAM_SYNC, "Sync device NULL"); + return -ENODEV; + } + + mutex_lock(&sync_dev->table_lock); + if (sync_dev->open_cnt >= 1) { + mutex_unlock(&sync_dev->table_lock); + return -EALREADY; + } + + rc = v4l2_fh_open(filep); + if (!rc) { + sync_dev->open_cnt++; + spin_lock_bh(&sync_dev->cam_sync_eventq_lock); + sync_dev->cam_sync_eventq = filep->private_data; + spin_unlock_bh(&sync_dev->cam_sync_eventq_lock); + } else { + CAM_ERR(CAM_SYNC, "v4l2_fh_open failed : %d", rc); + } + mutex_unlock(&sync_dev->table_lock); + + return rc; +} + +static int cam_sync_close(struct file *filep) +{ + int rc = 0; + int i; + struct sync_device *sync_dev = video_drvdata(filep); + + if (!sync_dev) { + CAM_ERR(CAM_SYNC, "Sync device NULL"); + rc = -ENODEV; + return rc; + } + mutex_lock(&sync_dev->table_lock); + sync_dev->open_cnt--; + if (!sync_dev->open_cnt) { + for (i = 1; i < CAM_SYNC_MAX_OBJS; i++) { + struct sync_table_row *row = + sync_dev->sync_table + i; + + /* + * Signal all ACTIVE objects as ERR, but we don't + * care about the return status here apart from logging + * it. + */ + if (row->state == CAM_SYNC_STATE_ACTIVE) { + rc = cam_sync_signal(i, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc < 0) + CAM_ERR(CAM_SYNC, + "Cleanup signal fail idx:%d\n", + i); + } + } + + /* + * Flush the work queue to wait for pending signal callbacks to + * finish + */ + flush_workqueue(sync_dev->work_queue); + + /* + * Now that all callbacks worker threads have finished, + * destroy the sync objects + */ + for (i = 1; i < CAM_SYNC_MAX_OBJS; i++) { + struct sync_table_row *row = + sync_dev->sync_table + i; + + if (row->state != CAM_SYNC_STATE_INVALID) { + rc = cam_sync_destroy(i); + if (rc < 0) + CAM_ERR(CAM_SYNC, + "Cleanup destroy fail:idx:%d\n", + i); + } + } + } + mutex_unlock(&sync_dev->table_lock); + spin_lock_bh(&sync_dev->cam_sync_eventq_lock); + sync_dev->cam_sync_eventq = NULL; + spin_unlock_bh(&sync_dev->cam_sync_eventq_lock); + v4l2_fh_release(filep); + + return rc; +} + +int cam_sync_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + return v4l2_event_subscribe(fh, sub, CAM_SYNC_MAX_V4L2_EVENTS, NULL); +} + +int cam_sync_unsubscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + return v4l2_event_unsubscribe(fh, sub); +} + +static const struct v4l2_ioctl_ops g_cam_sync_ioctl_ops = { + .vidioc_subscribe_event = cam_sync_subscribe_event, + .vidioc_unsubscribe_event = cam_sync_unsubscribe_event, + .vidioc_default = cam_sync_dev_ioctl, +}; + +static struct v4l2_file_operations cam_sync_v4l2_fops = { + .owner = THIS_MODULE, + .open = cam_sync_open, + .release = cam_sync_close, + .poll = cam_sync_poll, + .unlocked_ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = video_ioctl2, +#endif +}; + +#if defined(CONFIG_MEDIA_CONTROLLER) +static int cam_sync_media_controller_init(struct sync_device *sync_dev, + struct platform_device *pdev) +{ + int rc; + + sync_dev->v4l2_dev.mdev = kzalloc(sizeof(struct media_device), + GFP_KERNEL); + if (!sync_dev->v4l2_dev.mdev) + return -ENOMEM; + + media_device_init(sync_dev->v4l2_dev.mdev); + strlcpy(sync_dev->v4l2_dev.mdev->model, CAM_SYNC_DEVICE_NAME, + sizeof(sync_dev->v4l2_dev.mdev->model)); + sync_dev->v4l2_dev.mdev->dev = &(pdev->dev); + + rc = media_device_register(sync_dev->v4l2_dev.mdev); + if (rc < 0) + goto register_fail; + + rc = media_entity_pads_init(&sync_dev->vdev->entity, 0, NULL); + if (rc < 0) + goto entity_fail; + + return 0; + +entity_fail: + media_device_unregister(sync_dev->v4l2_dev.mdev); +register_fail: + media_device_cleanup(sync_dev->v4l2_dev.mdev); + return rc; +} + +static void cam_sync_media_controller_cleanup(struct sync_device *sync_dev) +{ + media_entity_cleanup(&sync_dev->vdev->entity); + media_device_unregister(sync_dev->v4l2_dev.mdev); + media_device_cleanup(sync_dev->v4l2_dev.mdev); + kfree(sync_dev->v4l2_dev.mdev); +} + +static void cam_sync_init_entity(struct sync_device *sync_dev) +{ + sync_dev->vdev->entity.function = CAM_SYNC_DEVICE_TYPE; + sync_dev->vdev->entity.name = + video_device_node_name(sync_dev->vdev); +} +#else +static int cam_sync_media_controller_init(struct sync_device *sync_dev, + struct platform_device *pdev) +{ + return 0; +} + +static void cam_sync_media_controller_cleanup(struct sync_device *sync_dev) +{ +} + +static void cam_sync_init_entity(struct sync_device *sync_dev) +{ +} +#endif + +static int cam_sync_create_debugfs(void) +{ + sync_dev->dentry = debugfs_create_dir("camera_sync", NULL); + + if (!sync_dev->dentry) { + CAM_ERR(CAM_SYNC, "Failed to create sync dir"); + return -ENOMEM; + } + + if (!debugfs_create_bool("trigger_cb_without_switch", + 0644, sync_dev->dentry, + &trigger_cb_without_switch)) { + CAM_ERR(CAM_SYNC, + "failed to create trigger_cb_without_switch entry"); + return -ENOMEM; + } + + return 0; +} + +static int cam_sync_probe(struct platform_device *pdev) +{ + int rc; + int idx; + + sync_dev = kzalloc(sizeof(*sync_dev), GFP_KERNEL); + if (!sync_dev) + return -ENOMEM; + + mutex_init(&sync_dev->table_lock); + spin_lock_init(&sync_dev->cam_sync_eventq_lock); + + for (idx = 0; idx < CAM_SYNC_MAX_OBJS; idx++) + spin_lock_init(&sync_dev->row_spinlocks[idx]); + + sync_dev->vdev = video_device_alloc(); + if (!sync_dev->vdev) { + rc = -ENOMEM; + goto vdev_fail; + } + + rc = cam_sync_media_controller_init(sync_dev, pdev); + if (rc < 0) + goto mcinit_fail; + + sync_dev->vdev->v4l2_dev = &sync_dev->v4l2_dev; + + rc = v4l2_device_register(&(pdev->dev), sync_dev->vdev->v4l2_dev); + if (rc < 0) + goto register_fail; + + strlcpy(sync_dev->vdev->name, CAM_SYNC_NAME, + sizeof(sync_dev->vdev->name)); + sync_dev->vdev->release = video_device_release; + sync_dev->vdev->fops = &cam_sync_v4l2_fops; + sync_dev->vdev->ioctl_ops = &g_cam_sync_ioctl_ops; + sync_dev->vdev->minor = -1; + sync_dev->vdev->vfl_type = VFL_TYPE_GRABBER; + rc = video_register_device(sync_dev->vdev, + VFL_TYPE_GRABBER, -1); + if (rc < 0) + goto v4l2_fail; + + cam_sync_init_entity(sync_dev); + video_set_drvdata(sync_dev->vdev, sync_dev); + memset(&sync_dev->sync_table, 0, sizeof(sync_dev->sync_table)); + memset(&sync_dev->bitmap, 0, sizeof(sync_dev->bitmap)); + bitmap_zero(sync_dev->bitmap, CAM_SYNC_MAX_OBJS); + + /* + * We treat zero as invalid handle, so we will keep the 0th bit set + * always + */ + set_bit(0, sync_dev->bitmap); + + sync_dev->work_queue = alloc_workqueue(CAM_SYNC_WORKQUEUE_NAME, + WQ_HIGHPRI | WQ_UNBOUND, 1); + + if (!sync_dev->work_queue) { + CAM_ERR(CAM_SYNC, + "Error: high priority work queue creation failed"); + rc = -ENOMEM; + goto v4l2_fail; + } + + trigger_cb_without_switch = false; + cam_sync_create_debugfs(); + + return rc; + +v4l2_fail: + v4l2_device_unregister(sync_dev->vdev->v4l2_dev); +register_fail: + cam_sync_media_controller_cleanup(sync_dev); +mcinit_fail: + video_device_release(sync_dev->vdev); +vdev_fail: + mutex_destroy(&sync_dev->table_lock); + kfree(sync_dev); + return rc; +} + +static int cam_sync_remove(struct platform_device *pdev) +{ + v4l2_device_unregister(sync_dev->vdev->v4l2_dev); + cam_sync_media_controller_cleanup(sync_dev); + video_device_release(sync_dev->vdev); + debugfs_remove_recursive(sync_dev->dentry); + sync_dev->dentry = NULL; + kfree(sync_dev); + sync_dev = NULL; + + return 0; +} + +static struct platform_device cam_sync_device = { + .name = "cam_sync", + .id = -1, +}; + +static struct platform_driver cam_sync_driver = { + .probe = cam_sync_probe, + .remove = cam_sync_remove, + .driver = { + .name = "cam_sync", + .owner = THIS_MODULE, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_sync_init(void) +{ + int rc; + + rc = platform_device_register(&cam_sync_device); + if (rc) + return -ENODEV; + + return platform_driver_register(&cam_sync_driver); +} + +static void __exit cam_sync_exit(void) +{ + int idx; + + for (idx = 0; idx < CAM_SYNC_MAX_OBJS; idx++) + spin_lock_init(&sync_dev->row_spinlocks[idx]); + platform_driver_unregister(&cam_sync_driver); + platform_device_unregister(&cam_sync_device); + kfree(sync_dev); +} + +module_init(cam_sync_init); +module_exit(cam_sync_exit); +MODULE_DESCRIPTION("Camera sync driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sync/cam_sync_api.h b/drivers/cam_sync/cam_sync_api.h new file mode 100644 index 000000000000..3d99bc15eb18 --- /dev/null +++ b/drivers/cam_sync/cam_sync_api.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __CAM_SYNC_API_H__ +#define __CAM_SYNC_API_H__ + +#include +#include +#include +#include +#include + +#define SYNC_DEBUG_NAME_LEN 63 +typedef void (*sync_callback)(int32_t sync_obj, int status, void *data); + +/* Kernel APIs */ + +/** + * @brief: Creates a sync object + * + * The newly created sync obj is assigned to sync_obj. + * sync object. + * + * @param sync_obj : Pointer to int referencing the sync object. + * @param name : Optional parameter associating a name with the sync object for + * debug purposes. Only first SYNC_DEBUG_NAME_LEN bytes are accepted, + * rest will be ignored. + * + * @return Status of operation. Zero in case of success. + * -EINVAL will be returned if sync_obj is an invalid pointer. + * -ENOMEM will be returned if the kernel can't allocate space for + * sync object. + */ +int cam_sync_create(int32_t *sync_obj, const char *name); + +/** + * @brief: Registers a callback with a sync object + * + * @param cb_func: Pointer to callback to be registered + * @param userdata: Opaque pointer which will be passed back with callback. + * @param sync_obj: int referencing the sync object. + * + * @return Status of operation. Zero in case of success. + * -EINVAL will be returned if userdata is invalid. + * -ENOMEM will be returned if cb_func is invalid. + * + */ +int cam_sync_register_callback(sync_callback cb_func, + void *userdata, int32_t sync_obj); + +/** + * @brief: De-registers a callback with a sync object + * + * @param cb_func: Pointer to callback to be de-registered + * @param userdata: Opaque pointer which will be passed back with callback. + * @param sync_obj: int referencing the sync object. + * + * @return Status of operation. Zero in case of success. + * -EINVAL will be returned if userdata is invalid. + * -ENOMEM will be returned if cb_func is invalid. + */ +int cam_sync_deregister_callback(sync_callback cb_func, + void *userdata, int32_t sync_obj); + +/** + * @brief: Signals a sync object with the status argument. + * + * This function will signal the sync object referenced by the sync_obj + * parameter and when doing so, will trigger callbacks in both user space and + * kernel. Callbacks will triggered asynchronously and their order of execution + * is not guaranteed. The status parameter will indicate whether the entity + * performing the signaling wants to convey an error case or a success case. + * + * @param sync_obj: int referencing the sync object. + * @param status: Status of the signaling. Can be either SYNC_SIGNAL_ERROR or + * SYNC_SIGNAL_SUCCESS. + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_signal(int32_t sync_obj, uint32_t status); + +/** + * @brief: Merges multiple sync objects + * + * This function will merge multiple sync objects into a sync group. + * + * @param sync_obj: pointer to a block of ints to be merged + * @param num_objs: Number of ints in the block + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj); + +/** + * @brief: get ref count of sync obj + * + * This function will increment ref count for the sync object, and the ref + * count will be decremented when this sync object is signaled. + * + * @param sync_obj: sync object + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_get_obj_ref(int32_t sync_obj); + +/** + * @brief: put ref count of sync obj + * + * This function will decrement ref count for the sync object. + * + * @param sync_obj: sync object + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_put_obj_ref(int32_t sync_obj); + +/** + * @brief: Destroys a sync object + * + * @param sync_obj: int referencing the sync object to be destroyed + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_destroy(int32_t sync_obj); + +/** + * @brief: Waits for a sync object synchronously + * + * Does a wait on the sync object identified by sync_obj for a maximum + * of timeout_ms milliseconds. Must not be called from interrupt context as + * this API can sleep. Should be called from process context only. + * + * @param sync_obj: int referencing the sync object to be waited upon + * @timeout_ms sync_obj: Timeout in ms. + * + * @return 0 upon success, -EINVAL if sync object is in bad state or arguments + * are invalid, -ETIMEDOUT if wait times out. + */ +int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms); + + +#endif /* __CAM_SYNC_API_H__ */ diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h new file mode 100644 index 000000000000..68a9804adf45 --- /dev/null +++ b/drivers/cam_sync/cam_sync_private.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __CAM_SYNC_PRIVATE_H__ +#define __CAM_SYNC_PRIVATE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CAM_SYNC_DBG +#define CDBG(fmt, args...) pr_err(fmt, ##args) +#else +#define CDBG(fmt, args...) pr_debug(fmt, ##args) +#endif + +#define CAM_SYNC_OBJ_NAME_LEN 64 +#define CAM_SYNC_MAX_OBJS 1024 +#define CAM_SYNC_MAX_V4L2_EVENTS 50 +#define CAM_SYNC_DEBUG_FILENAME "cam_debug" +#define CAM_SYNC_DEBUG_BASEDIR "cam" +#define CAM_SYNC_DEBUG_BUF_SIZE 32 +#define CAM_SYNC_PAYLOAD_WORDS 2 +#define CAM_SYNC_NAME "cam_sync" +#define CAM_SYNC_WORKQUEUE_NAME "HIPRIO_SYNC_WORK_QUEUE" + +#define CAM_SYNC_TYPE_INDV 0 +#define CAM_SYNC_TYPE_GROUP 1 + +/** + * enum sync_type - Enum to indicate the type of sync object, + * i.e. individual or group. + * + * @SYNC_TYPE_INDV : Object is an individual sync object + * @SYNC_TYPE_GROUP : Object is a group sync object + */ +enum sync_type { + SYNC_TYPE_INDV, + SYNC_TYPE_GROUP +}; + +/** + * enum sync_list_clean_type - Enum to indicate the type of list clean action + * to be peformed, i.e. specific sync ID or all list sync ids. + * + * @SYNC_CLEAN_ONE : Specific object to be cleaned in the list + * @SYNC_CLEAN_ALL : Clean all objects in the list + */ +enum sync_list_clean_type { + SYNC_LIST_CLEAN_ONE, + SYNC_LIST_CLEAN_ALL +}; + +/** + * struct sync_parent_info - Single node of information about a parent + * of a sync object, usually part of the parents linked list + * + * @sync_id : Sync object id of parent + * @list : List member used to append this node to a linked list + */ +struct sync_parent_info { + int32_t sync_id; + struct list_head list; +}; + +/** + * struct sync_parent_info - Single node of information about a child + * of a sync object, usually part of the children linked list + * + * @sync_id : Sync object id of child + * @list : List member used to append this node to a linked list + */ +struct sync_child_info { + int32_t sync_id; + struct list_head list; +}; + + +/** + * struct sync_callback_info - Single node of information about a kernel + * callback registered on a sync object + * + * @callback_func : Callback function, registered by client driver + * @cb_data : Callback data, registered by client driver + * @status........ : Status with which callback will be invoked in client + * @sync_obj : Sync id of the object for which callback is registered + * @cb_dispatch_work : Work representing the call dispatch + * @list : List member used to append this node to a linked list + */ +struct sync_callback_info { + sync_callback callback_func; + void *cb_data; + int status; + int32_t sync_obj; + struct work_struct cb_dispatch_work; + struct list_head list; +}; + +/** + * struct sync_user_payload - Single node of information about a user space + * payload registered from user space + * + * @payload_data : Payload data, opaque to kernel + * @list : List member used to append this node to a linked list + */ +struct sync_user_payload { + uint64_t payload_data[CAM_SYNC_PAYLOAD_WORDS]; + struct list_head list; +}; + +/** + * struct sync_table_row - Single row of information about a sync object, used + * for internal book keeping in the sync driver + * + * @name : Optional string representation of the sync object + * @type : Type of the sync object (individual or group) + * @sync_id : Integer id representing this sync object + * @parents_list : Linked list of parents of this sync object + * @children_list : Linked list of children of this sync object + * @state : State (INVALID, ACTIVE, SIGNALED_SUCCESS or + * SIGNALED_ERROR) + * @remaining : Count of remaining children that not been signaled + * @signaled : Completion variable on which block calls will wait + * @callback_list : Linked list of kernel callbacks registered + * @user_payload_list : LInked list of user space payloads registered + * @ref_cnt : ref count of the number of usage of the fence. + */ +struct sync_table_row { + char name[CAM_SYNC_OBJ_NAME_LEN]; + enum sync_type type; + int32_t sync_id; + /* List of parents, which are merged objects */ + struct list_head parents_list; + /* List of children, which constitute the merged object */ + struct list_head children_list; + uint32_t state; + uint32_t remaining; + struct completion signaled; + struct list_head callback_list; + struct list_head user_payload_list; + atomic_t ref_cnt; +}; + +/** + * struct cam_signalable_info - Information for a single sync object that is + * ready to be signaled + * + * @sync_obj : Sync object id of signalable object + * @status : Status with which to signal + * @list : List member used to append this node to a linked list + */ +struct cam_signalable_info { + int32_t sync_obj; + uint32_t status; + struct list_head list; +}; + +/** + * struct sync_device - Internal struct to book keep sync driver details + * + * @vdev : Video device + * @v4l2_dev : V4L2 device + * @sync_table : Table of all sync objects + * @row_spinlocks : Spinlock array, one for each row in the table + * @table_lock : Mutex used to lock the table + * @open_cnt : Count of file open calls made on the sync driver + * @dentry : Debugfs entry + * @work_queue : Work queue used for dispatching kernel callbacks + * @cam_sync_eventq : Event queue used to dispatch user payloads to user space + * @bitmap : Bitmap representation of all sync objects + */ +struct sync_device { + struct video_device *vdev; + struct v4l2_device v4l2_dev; + struct sync_table_row sync_table[CAM_SYNC_MAX_OBJS]; + spinlock_t row_spinlocks[CAM_SYNC_MAX_OBJS]; + struct mutex table_lock; + int open_cnt; + struct dentry *dentry; + struct workqueue_struct *work_queue; + struct v4l2_fh *cam_sync_eventq; + spinlock_t cam_sync_eventq_lock; + DECLARE_BITMAP(bitmap, CAM_SYNC_MAX_OBJS); +}; + + +#endif /* __CAM_SYNC_PRIVATE_H__ */ diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c new file mode 100644 index 000000000000..d7e0f4125290 --- /dev/null +++ b/drivers/cam_sync/cam_sync_util.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#include "cam_sync_util.h" + +int cam_sync_util_find_and_set_empty_row(struct sync_device *sync_dev, + long *idx) +{ + int rc = 0; + + mutex_lock(&sync_dev->table_lock); + + *idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS); + + if (*idx < CAM_SYNC_MAX_OBJS) + set_bit(*idx, sync_dev->bitmap); + else + rc = -1; + + mutex_unlock(&sync_dev->table_lock); + + return rc; +} + +int cam_sync_init_row(struct sync_table_row *table, + uint32_t idx, const char *name, uint32_t type) +{ + struct sync_table_row *row = table + idx; + + if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS) + return -EINVAL; + + memset(row, 0, sizeof(*row)); + + if (name) + strlcpy(row->name, name, SYNC_DEBUG_NAME_LEN); + INIT_LIST_HEAD(&row->parents_list); + INIT_LIST_HEAD(&row->children_list); + row->type = type; + row->sync_id = idx; + row->state = CAM_SYNC_STATE_ACTIVE; + row->remaining = 0; + atomic_set(&row->ref_cnt, 0); + init_completion(&row->signaled); + INIT_LIST_HEAD(&row->callback_list); + INIT_LIST_HEAD(&row->user_payload_list); + CAM_DBG(CAM_SYNC, + "row name:%s sync_id:%i [idx:%u] row_state:%u ", + row->name, row->sync_id, idx, row->state); + + return 0; +} + +int cam_sync_init_group_object(struct sync_table_row *table, + uint32_t idx, + uint32_t *sync_objs, + uint32_t num_objs) +{ + int i, rc = 0; + struct sync_child_info *child_info; + struct sync_parent_info *parent_info; + struct sync_table_row *row = table + idx; + struct sync_table_row *child_row = NULL; + + cam_sync_init_row(table, idx, "merged_fence", CAM_SYNC_TYPE_GROUP); + + /* + * While traversing for children, parent's row list is updated with + * child info and each child's row is updated with parent info. + * If any child state is ERROR or SUCCESS, it will not be added to list. + */ + for (i = 0; i < num_objs; i++) { + child_row = table + sync_objs[i]; + spin_lock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + + /* validate child */ + if ((child_row->type == CAM_SYNC_TYPE_GROUP) || + (child_row->state == CAM_SYNC_STATE_INVALID)) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + CAM_ERR(CAM_SYNC, + "Invalid child fence:%i state:%u type:%u", + child_row->sync_id, child_row->state, + child_row->type); + rc = -EINVAL; + goto clean_children_info; + } + + /* check for child's state */ + if (child_row->state == CAM_SYNC_STATE_SIGNALED_ERROR) { + row->state = CAM_SYNC_STATE_SIGNALED_ERROR; + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + continue; + } + if (child_row->state != CAM_SYNC_STATE_ACTIVE) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + continue; + } + + row->remaining++; + + /* Add child info */ + child_info = kzalloc(sizeof(*child_info), GFP_ATOMIC); + if (!child_info) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + rc = -ENOMEM; + goto clean_children_info; + } + child_info->sync_id = sync_objs[i]; + list_add_tail(&child_info->list, &row->children_list); + + /* Add parent info */ + parent_info = kzalloc(sizeof(*parent_info), GFP_ATOMIC); + if (!parent_info) { + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + rc = -ENOMEM; + goto clean_children_info; + } + parent_info->sync_id = idx; + list_add_tail(&parent_info->list, &child_row->parents_list); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + } + + if (!row->remaining) { + if (row->state != CAM_SYNC_STATE_SIGNALED_ERROR) + row->state = CAM_SYNC_STATE_SIGNALED_SUCCESS; + complete_all(&row->signaled); + } + + return 0; + +clean_children_info: + row->state = CAM_SYNC_STATE_INVALID; + for (i = i-1; i >= 0; i--) { + spin_lock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + child_row = table + sync_objs[i]; + cam_sync_util_cleanup_parents_list(child_row, + SYNC_LIST_CLEAN_ONE, idx); + spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); + } + + cam_sync_util_cleanup_children_list(row, SYNC_LIST_CLEAN_ALL, 0); + return rc; +} + +int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) +{ + struct sync_table_row *row = table + idx; + struct sync_child_info *child_info, *temp_child; + struct sync_callback_info *sync_cb, *temp_cb; + struct sync_parent_info *parent_info, *temp_parent; + struct sync_user_payload *upayload_info, *temp_upayload; + struct sync_table_row *child_row = NULL, *parent_row = NULL; + struct list_head temp_child_list, temp_parent_list; + + if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS) + return -EINVAL; + + CAM_DBG(CAM_SYNC, + "row name:%s sync_id:%i [idx:%u] row_state:%u", + row->name, row->sync_id, idx, row->state); + + spin_lock_bh(&sync_dev->row_spinlocks[idx]); + if (row->state == CAM_SYNC_STATE_INVALID) { + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj: idx = %d", + idx); + return -EINVAL; + } + + if (row->state == CAM_SYNC_STATE_ACTIVE) + CAM_DBG(CAM_SYNC, + "Destroying an active sync object name:%s id:%i", + row->name, row->sync_id); + + row->state = CAM_SYNC_STATE_INVALID; + + /* Object's child and parent objects will be added into this list */ + INIT_LIST_HEAD(&temp_child_list); + INIT_LIST_HEAD(&temp_parent_list); + + list_for_each_entry_safe(child_info, temp_child, &row->children_list, + list) { + if (child_info->sync_id <= 0) + continue; + + list_del_init(&child_info->list); + list_add_tail(&child_info->list, &temp_child_list); + } + + list_for_each_entry_safe(parent_info, temp_parent, &row->parents_list, + list) { + if (parent_info->sync_id <= 0) + continue; + + list_del_init(&parent_info->list); + list_add_tail(&parent_info->list, &temp_parent_list); + } + + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + + /* Cleanup the child to parent link from child list */ + while (!list_empty(&temp_child_list)) { + child_info = list_first_entry(&temp_child_list, + struct sync_child_info, list); + child_row = sync_dev->sync_table + child_info->sync_id; + + spin_lock_bh(&sync_dev->row_spinlocks[child_info->sync_id]); + + if (child_row->state == CAM_SYNC_STATE_INVALID) { + list_del_init(&child_info->list); + spin_unlock_bh(&sync_dev->row_spinlocks[ + child_info->sync_id]); + kfree(child_info); + continue; + } + + if (child_row->state == CAM_SYNC_STATE_ACTIVE) + CAM_DBG(CAM_SYNC, + "Warning: destroying active child sync obj = %d", + child_info->sync_id); + + cam_sync_util_cleanup_parents_list(child_row, + SYNC_LIST_CLEAN_ONE, idx); + + list_del_init(&child_info->list); + spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]); + kfree(child_info); + } + + /* Cleanup the parent to child link */ + while (!list_empty(&temp_parent_list)) { + parent_info = list_first_entry(&temp_parent_list, + struct sync_parent_info, list); + parent_row = sync_dev->sync_table + parent_info->sync_id; + + spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); + + if (parent_row->state == CAM_SYNC_STATE_INVALID) { + list_del_init(&parent_info->list); + spin_unlock_bh(&sync_dev->row_spinlocks[ + parent_info->sync_id]); + kfree(parent_info); + continue; + } + + if (parent_row->state == CAM_SYNC_STATE_ACTIVE) + CAM_DBG(CAM_SYNC, + "Warning: destroying active parent sync obj = %d", + parent_info->sync_id); + + cam_sync_util_cleanup_children_list(parent_row, + SYNC_LIST_CLEAN_ONE, idx); + + list_del_init(&parent_info->list); + spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); + kfree(parent_info); + } + + spin_lock_bh(&sync_dev->row_spinlocks[idx]); + list_for_each_entry_safe(upayload_info, temp_upayload, + &row->user_payload_list, list) { + list_del_init(&upayload_info->list); + kfree(upayload_info); + } + + list_for_each_entry_safe(sync_cb, temp_cb, + &row->callback_list, list) { + list_del_init(&sync_cb->list); + kfree(sync_cb); + } + + memset(row, 0, sizeof(*row)); + clear_bit(idx, sync_dev->bitmap); + INIT_LIST_HEAD(&row->callback_list); + INIT_LIST_HEAD(&row->parents_list); + INIT_LIST_HEAD(&row->children_list); + INIT_LIST_HEAD(&row->user_payload_list); + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + + CAM_DBG(CAM_SYNC, "Destroying sync obj:%d successful", idx); + return 0; +} + +void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work) +{ + struct sync_callback_info *cb_info = container_of(cb_dispatch_work, + struct sync_callback_info, + cb_dispatch_work); + + cb_info->callback_func(cb_info->sync_obj, + cb_info->status, + cb_info->cb_data); + + kfree(cb_info); +} + +void cam_sync_util_dispatch_signaled_cb(int32_t sync_obj, + uint32_t status) +{ + struct sync_callback_info *sync_cb; + struct sync_user_payload *payload_info; + struct sync_callback_info *temp_sync_cb; + struct sync_table_row *signalable_row; + struct sync_user_payload *temp_payload_info; + + signalable_row = sync_dev->sync_table + sync_obj; + if (signalable_row->state == CAM_SYNC_STATE_INVALID) { + CAM_DBG(CAM_SYNC, + "Accessing invalid sync object:%i", sync_obj); + return; + } + + /* Dispatch kernel callbacks if any were registered earlier */ + list_for_each_entry_safe(sync_cb, + temp_sync_cb, &signalable_row->callback_list, list) { + sync_cb->status = status; + list_del_init(&sync_cb->list); + queue_work(sync_dev->work_queue, + &sync_cb->cb_dispatch_work); + } + + /* Dispatch user payloads if any were registered earlier */ + list_for_each_entry_safe(payload_info, temp_payload_info, + &signalable_row->user_payload_list, list) { + spin_lock_bh(&sync_dev->cam_sync_eventq_lock); + if (!sync_dev->cam_sync_eventq) { + spin_unlock_bh( + &sync_dev->cam_sync_eventq_lock); + break; + } + spin_unlock_bh(&sync_dev->cam_sync_eventq_lock); + cam_sync_util_send_v4l2_event( + CAM_SYNC_V4L_EVENT_ID_CB_TRIG, + sync_obj, + status, + payload_info->payload_data, + CAM_SYNC_PAYLOAD_WORDS * sizeof(__u64)); + + list_del_init(&payload_info->list); + /* + * We can free the list node here because + * sending V4L event will make a deep copy + * anyway + */ + kfree(payload_info); + } + + /* + * This needs to be done because we want to unblock anyone + * who might be blocked and waiting on this sync object + */ + complete_all(&signalable_row->signaled); +} + +void cam_sync_util_send_v4l2_event(uint32_t id, + uint32_t sync_obj, + int status, + void *payload, + int len) +{ + struct v4l2_event event; + __u64 *payload_data = NULL; + struct cam_sync_ev_header *ev_header = NULL; + + event.id = id; + event.type = CAM_SYNC_V4L_EVENT; + + ev_header = CAM_SYNC_GET_HEADER_PTR(event); + ev_header->sync_obj = sync_obj; + ev_header->status = status; + + payload_data = CAM_SYNC_GET_PAYLOAD_PTR(event, __u64); + memcpy(payload_data, payload, len); + + v4l2_event_queue(sync_dev->vdev, &event); + CAM_DBG(CAM_SYNC, "send v4l2 event for sync_obj :%d", + sync_obj); +} + +int cam_sync_util_update_parent_state(struct sync_table_row *parent_row, + int new_state) +{ + int rc = 0; + + switch (parent_row->state) { + case CAM_SYNC_STATE_ACTIVE: + case CAM_SYNC_STATE_SIGNALED_SUCCESS: + parent_row->state = new_state; + break; + + case CAM_SYNC_STATE_SIGNALED_ERROR: + break; + + case CAM_SYNC_STATE_INVALID: + default: + rc = -EINVAL; + break; + } + + return rc; +} + +void cam_sync_util_cleanup_children_list(struct sync_table_row *row, + uint32_t list_clean_type, uint32_t sync_obj) +{ + struct sync_child_info *child_info = NULL; + struct sync_child_info *temp_child_info = NULL; + uint32_t curr_sync_obj; + + list_for_each_entry_safe(child_info, + temp_child_info, &row->children_list, list) { + if ((list_clean_type == SYNC_LIST_CLEAN_ONE) && + (child_info->sync_id != sync_obj)) + continue; + + curr_sync_obj = child_info->sync_id; + list_del_init(&child_info->list); + kfree(child_info); + + if ((list_clean_type == SYNC_LIST_CLEAN_ONE) && + (curr_sync_obj == sync_obj)) + break; + } +} + +void cam_sync_util_cleanup_parents_list(struct sync_table_row *row, + uint32_t list_clean_type, uint32_t sync_obj) +{ + struct sync_parent_info *parent_info = NULL; + struct sync_parent_info *temp_parent_info = NULL; + uint32_t curr_sync_obj; + + list_for_each_entry_safe(parent_info, + temp_parent_info, &row->parents_list, list) { + if ((list_clean_type == SYNC_LIST_CLEAN_ONE) && + (parent_info->sync_id != sync_obj)) + continue; + + curr_sync_obj = parent_info->sync_id; + list_del_init(&parent_info->list); + kfree(parent_info); + + if ((list_clean_type == SYNC_LIST_CLEAN_ONE) && + (curr_sync_obj == sync_obj)) + break; + } +} diff --git a/drivers/cam_sync/cam_sync_util.h b/drivers/cam_sync/cam_sync_util.h new file mode 100644 index 000000000000..e114c33c655a --- /dev/null +++ b/drivers/cam_sync/cam_sync_util.h @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __CAM_SYNC_UTIL_H__ +#define __CAM_SYNC_UTIL_H__ + + +#include +#include "cam_sync_private.h" +#include "cam_debug_util.h" + +extern struct sync_device *sync_dev; + +/** + * @brief: Finds an empty row in the sync table and sets its corresponding bit + * in the bit array + * + * @param sync_dev : Pointer to the sync device instance + * @param idx : Pointer to an long containing the index found in the bit + * array + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_util_find_and_set_empty_row(struct sync_device *sync_dev, + long *idx); + +/** + * @brief: Function to initialize an empty row in the sync table. This should be + * called only for individual sync objects. + * + * @param table : Pointer to the sync objects table + * @param idx : Index of row to initialize + * @param name : Optional string representation of the sync object. Should be + * 63 characters or less + * @param type : type of row to be initialized + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_init_row(struct sync_table_row *table, + uint32_t idx, const char *name, uint32_t type); + +/** + * @brief: Function to uninitialize a row in the sync table + * + * @param table : Pointer to the sync objects table + * @param idx : Index of row to initialize + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx); + +/** + * @brief: Function to initialize a row in the sync table when the object is a + * group object, also known as a merged sync object + * + * @param table : Pointer to the sync objects table + * @param idx : Index of row to initialize + * @param sync_objs : Array of sync objects which will merged + * or grouped together + * @param num_objs : Number of sync objects in the array + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +int cam_sync_init_group_object(struct sync_table_row *table, + uint32_t idx, + uint32_t *sync_objs, + uint32_t num_objs); + +int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx); + +/** + * @brief: Function to dispatch a kernel callback for a sync callback + * + * @param cb_dispatch_work : Pointer to the work_struct that needs to be + * dispatched + * + * @return None + */ +void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work); + +/** + * @brief: Function to dispatch callbacks for a signaled sync object + * + * @sync_obj : Sync object that is signaled + * @status : Status of the signaled object + * + * @return None + */ +void cam_sync_util_dispatch_signaled_cb(int32_t sync_obj, + uint32_t status); + +/** + * @brief: Function to send V4L event to user space + * @param id : V4L event id to send + * @param sync_obj : Sync obj for which event needs to be sent + * @param status : Status of the event + * @payload : Payload that needs to be sent to user space + * @len : Length of the payload + * + * @return None + */ +void cam_sync_util_send_v4l2_event(uint32_t id, + uint32_t sync_obj, + int status, + void *payload, + int len); + +/** + * @brief: Function which gets the next state of the sync object based on the + * current state and the new state + * + * @param current_state : Current state of the sync object + * @param new_state : New state of the sync object + * + * @return Next state of the sync object + */ +int cam_sync_util_update_parent_state(struct sync_table_row *parent_row, + int new_state); + +/** + * @brief: Function to clean up the children of a sync object + * @row : Row whose child list to clean + * @list_clean_type : Clean specific object or clean all objects + * @sync_obj : Sync object to be clean if list clean type is + * SYNC_LIST_CLEAN_ONE + * + * @return None + */ +void cam_sync_util_cleanup_children_list(struct sync_table_row *row, + uint32_t list_clean_type, uint32_t sync_obj); + +/** + * @brief: Function to clean up the parents of a sync object + * @row : Row whose parent list to clean + * @list_clean_type : Clean specific object or clean all objects + * @sync_obj : Sync object to be clean if list clean type is + * SYNC_LIST_CLEAN_ONE + * + * @return None + */ +void cam_sync_util_cleanup_parents_list(struct sync_table_row *row, + uint32_t list_clean_type, uint32_t sync_obj); + +#endif /* __CAM_SYNC_UTIL_H__ */ diff --git a/drivers/cam_utils/Makefile b/drivers/cam_utils/Makefile new file mode 100644 index 000000000000..fb8c48eeeb04 --- /dev/null +++ b/drivers/cam_utils/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/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/cam_utils/cam_common_util.c b/drivers/cam_utils/cam_common_util.c new file mode 100644 index 000000000000..dbcb31d7bf0e --- /dev/null +++ b/drivers/cam_utils/cam_common_util.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_common_util.h" +#include "cam_debug_util.h" + +int cam_common_util_get_string_index(const char **strings, + uint32_t num_strings, const char *matching_string, uint32_t *index) +{ + int i; + + for (i = 0; i < num_strings; i++) { + if (strnstr(strings[i], matching_string, strlen(strings[i]))) { + CAM_DBG(CAM_UTIL, "matched %s : %d\n", + matching_string, i); + *index = i; + return 0; + } + } + + return -EINVAL; +} + +uint32_t cam_common_util_remove_duplicate_arr(int32_t *arr, uint32_t num) +{ + int i, j; + uint32_t wr_idx = 1; + + if (!arr) { + CAM_ERR(CAM_UTIL, "Null input array"); + return 0; + } + + for (i = 1; i < num; i++) { + for (j = 0; j < wr_idx ; j++) { + if (arr[i] == arr[j]) + break; + } + if (j == wr_idx) + arr[wr_idx++] = arr[i]; + } + + return wr_idx; +} diff --git a/drivers/cam_utils/cam_common_util.h b/drivers/cam_utils/cam_common_util.h new file mode 100644 index 000000000000..e202bae5b761 --- /dev/null +++ b/drivers/cam_utils/cam_common_util.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_COMMON_UTIL_H_ +#define _CAM_COMMON_UTIL_H_ + +#include +#include + +#define CAM_BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift) + +#define PTR_TO_U64(ptr) ((uint64_t)(uintptr_t)ptr) +#define U64_TO_PTR(ptr) ((void *)(uintptr_t)ptr) + +/** + * cam_common_util_get_string_index() + * + * @brief Match the string from list of strings to return + * matching index + * + * @strings: Pointer to list of strings + * @num_strings: Number of strings in 'strings' + * @matching_string: String to match + * @index: Pointer to index to return matching index + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_common_util_get_string_index(const char **strings, + uint32_t num_strings, const char *matching_string, uint32_t *index); + +/** + * cam_common_util_remove_duplicate_arr() + * + * @brief Move all the unique integers to the start of + * the array and return the number of unique integers + * + * @array: Pointer to the first integer of array + * @num: Number of elements in array + * + * @return: Number of unique integers in array + */ +uint32_t cam_common_util_remove_duplicate_arr(int32_t *array, + uint32_t num); + +#endif /* _CAM_COMMON_UTIL_H_ */ diff --git a/drivers/cam_utils/cam_cx_ipeak.c b/drivers/cam_utils/cam_cx_ipeak.c new file mode 100644 index 000000000000..b0f93ba045e0 --- /dev/null +++ b/drivers/cam_utils/cam_cx_ipeak.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#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/cam_utils/cam_cx_ipeak.h b/drivers/cam_utils/cam_cx_ipeak.h new file mode 100644 index 000000000000..ab06952b86a8 --- /dev/null +++ b/drivers/cam_utils/cam_cx_ipeak.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CX_IPEAK_H_ +#define _CAM_CX_IPEAK_H_ + +#include "cam_soc_util.h" + +int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info); + +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_CX_IPEAK_H_ */ diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c new file mode 100644 index 000000000000..3c178f1e77ac --- /dev/null +++ b/drivers/cam_utils/cam_debug_util.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundataion. All rights reserved. + */ + +#include +#include + +#include "cam_debug_util.h" + +static uint debug_mdl; +module_param(debug_mdl, uint, 0644); + +const char *cam_get_module_name(unsigned int module_id) +{ + const char *name = NULL; + + switch (module_id) { + case CAM_CDM: + name = "CAM-CDM"; + break; + case CAM_CORE: + name = "CAM-CORE"; + break; + case CAM_CRM: + name = "CAM-CRM"; + break; + case CAM_CPAS: + name = "CAM-CPAS"; + break; + case CAM_ISP: + name = "CAM-ISP"; + break; + case CAM_SENSOR: + name = "CAM-SENSOR"; + break; + case CAM_SMMU: + name = "CAM-SMMU"; + break; + case CAM_SYNC: + name = "CAM-SYNC"; + break; + case CAM_ICP: + name = "CAM-ICP"; + break; + case CAM_JPEG: + name = "CAM-JPEG"; + break; + case CAM_FD: + name = "CAM-FD"; + break; + case CAM_LRME: + name = "CAM-LRME"; + break; + case CAM_FLASH: + name = "CAM-FLASH"; + break; + case CAM_ACTUATOR: + name = "CAM-ACTUATOR"; + break; + case CAM_CCI: + name = "CAM-CCI"; + break; + case CAM_CSIPHY: + name = "CAM-CSIPHY"; + break; + case CAM_EEPROM: + name = "CAM-EEPROM"; + break; + case CAM_UTIL: + name = "CAM-UTIL"; + break; + case CAM_CTXT: + name = "CAM-CTXT"; + break; + case CAM_HFI: + name = "CAM-HFI"; + break; + case CAM_OIS: + name = "CAM-OIS"; + break; + case CAM_IRQ_CTRL: + name = "CAM-IRQ-CTRL"; + break; + case CAM_MEM: + name = "CAM-MEM"; + break; + case CAM_PERF: + name = "CAM-PERF"; + break; + case CAM_REQ: + name = "CAM-REQ"; + break; + default: + name = "CAM"; + break; + } + + return name; +} + +void cam_debug_log(unsigned int module_id, const char *func, const int line, + const char *fmt, ...) +{ + char str_buffer[STR_BUFFER_MAX_LENGTH]; + va_list args; + + va_start(args, fmt); + + if (debug_mdl & module_id) { + vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args); + pr_info("CAM_DBG: %s: %s: %d: %s\n", + cam_get_module_name(module_id), + func, line, str_buffer); + va_end(args); + } +} diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h new file mode 100644 index 000000000000..7380312dcde0 --- /dev/null +++ b/drivers/cam_utils/cam_debug_util.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_DEBUG_UTIL_H_ +#define _CAM_DEBUG_UTIL_H_ + +#define CAM_CDM (1 << 0) +#define CAM_CORE (1 << 1) +#define CAM_CPAS (1 << 2) +#define CAM_ISP (1 << 3) +#define CAM_CRM (1 << 4) +#define CAM_SENSOR (1 << 5) +#define CAM_SMMU (1 << 6) +#define CAM_SYNC (1 << 7) +#define CAM_ICP (1 << 8) +#define CAM_JPEG (1 << 9) +#define CAM_FD (1 << 10) +#define CAM_LRME (1 << 11) +#define CAM_FLASH (1 << 12) +#define CAM_ACTUATOR (1 << 13) +#define CAM_CCI (1 << 14) +#define CAM_CSIPHY (1 << 15) +#define CAM_EEPROM (1 << 16) +#define CAM_UTIL (1 << 17) +#define CAM_HFI (1 << 18) +#define CAM_CTXT (1 << 19) +#define CAM_OIS (1 << 20) +#define CAM_RES (1 << 21) +#define CAM_MEM (1 << 22) + +/* CAM_IRQ_CTRL: For events in irq controller */ +#define CAM_IRQ_CTRL (1 << 23) + +/* CAM_REQ: Tracks a request submitted to KMD */ +#define CAM_REQ (1 << 24) + +/* CAM_PERF: Used for performance (clock, BW etc) logs */ +#define CAM_PERF (1 << 25) + +#define STR_BUFFER_MAX_LENGTH 1024 + +/* + * cam_debug_log() + * + * @brief : Get the Module name from module ID and print + * respective debug logs + * + * @module_id : Respective Module ID which is calling this function + * @func : Function which is calling to print logs + * @line : Line number associated with the function which is calling + * to print log + * @fmt : Formatted string which needs to be print in the log + * + */ +void cam_debug_log(unsigned int module_id, const char *func, const int line, + const char *fmt, ...); + +/* + * cam_get_module_name() + * + * @brief : Get the module name from module ID + * + * @module_id : Module ID which is using this function + */ +const char *cam_get_module_name(unsigned int module_id); + +/* + * CAM_ERR + * @brief : This Macro will print error logs + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_ERR(__module, fmt, args...) \ + pr_err("CAM_ERR: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, __LINE__, ##args) +/* + * CAM_WARN + * @brief : This Macro will print warning logs + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_WARN(__module, fmt, args...) \ + pr_warn("CAM_WARN: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, __LINE__, ##args) +/* + * CAM_INFO + * @brief : This Macro will print Information logs + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_INFO(__module, fmt, args...) \ + pr_info("CAM_INFO: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, __LINE__, ##args) + +/* + * CAM_INFO_RATE_LIMIT + * @brief : This Macro will print info logs with ratelimit + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_INFO_RATE_LIMIT(__module, fmt, args...) \ + pr_err_ratelimited("CAM_INFO: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, __LINE__, ##args) + +/* + * CAM_DBG + * @brief : This Macro will print debug logs when enabled using GROUP + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_DBG(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) + +/* + * CAM_ERR_RATE_LIMIT + * @brief : This Macro will print error print logs with ratelimit + */ +#define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ + pr_err_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, __LINE__, ##args) + +#endif /* _CAM_DEBUG_UTIL_H_ */ diff --git a/drivers/cam_utils/cam_io_util.c b/drivers/cam_utils/cam_io_util.c new file mode 100644 index 000000000000..d35320e7e487 --- /dev/null +++ b/drivers/cam_utils/cam_io_util.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2011-2014, 2017-2018, The Linux Foundation. + * All rights reserved. + */ + +#include +#include +#include +#include "cam_io_util.h" +#include "cam_debug_util.h" + +int cam_io_w(uint32_t data, void __iomem *addr) +{ + if (!addr) + return -EINVAL; + + CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + writel_relaxed_no_log(data, addr); + + return 0; +} + +int cam_io_w_mb(uint32_t data, void __iomem *addr) +{ + if (!addr) + return -EINVAL; + + CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + /* Ensure previous writes are done */ + wmb(); + writel_relaxed_no_log(data, addr); + /* Ensure previous writes are done */ + wmb(); + + return 0; +} + +uint32_t cam_io_r(void __iomem *addr) +{ + uint32_t data; + + if (!addr) { + CAM_ERR(CAM_UTIL, "Invalid args"); + return 0; + } + + data = readl_relaxed(addr); + CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + + return data; +} + +uint32_t cam_io_r_mb(void __iomem *addr) +{ + uint32_t data; + + if (!addr) { + CAM_ERR(CAM_UTIL, "Invalid args"); + return 0; + } + + /* Ensure previous read is done */ + rmb(); + data = readl_relaxed(addr); + CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + /* Ensure previous read is done */ + rmb(); + + return data; +} + +int cam_io_memcpy(void __iomem *dest_addr, + void __iomem *src_addr, uint32_t len) +{ + int i; + uint32_t *d = (uint32_t *) dest_addr; + uint32_t *s = (uint32_t *) src_addr; + + if (!dest_addr || !src_addr) + return -EINVAL; + + CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len); + + for (i = 0; i < len/4; i++) { + CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s); + writel_relaxed(*s++, d++); + } + + return 0; +} + +int cam_io_memcpy_mb(void __iomem *dest_addr, + void __iomem *src_addr, uint32_t len) +{ + int i; + uint32_t *d = (uint32_t *) dest_addr; + uint32_t *s = (uint32_t *) src_addr; + + if (!dest_addr || !src_addr) + return -EINVAL; + + CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len); + + /* + * Do not use cam_io_w_mb to avoid double wmb() after a write + * and before the next write. + */ + wmb(); + for (i = 0; i < (len / 4); i++) { + CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s); + writel_relaxed(*s++, d++); + } + /* Ensure previous writes are done */ + wmb(); + + return 0; +} + +int cam_io_poll_value(void __iomem *addr, uint32_t wait_data, uint32_t retry, + unsigned long min_usecs, unsigned long max_usecs) +{ + uint32_t tmp, cnt = 0; + int rc = 0; + + if (!addr) + return -EINVAL; + + tmp = readl_relaxed(addr); + while ((tmp != wait_data) && (cnt++ < retry)) { + if (min_usecs > 0 && max_usecs > 0) + usleep_range(min_usecs, max_usecs); + tmp = readl_relaxed(addr); + } + + if (cnt > retry) { + CAM_DBG(CAM_UTIL, "Poll failed by value"); + rc = -EINVAL; + } + + return rc; +} + +int cam_io_poll_value_wmask(void __iomem *addr, uint32_t wait_data, + uint32_t bmask, uint32_t retry, unsigned long min_usecs, + unsigned long max_usecs) +{ + uint32_t tmp, cnt = 0; + int rc = 0; + + if (!addr) + return -EINVAL; + + tmp = readl_relaxed(addr); + while (((tmp & bmask) != wait_data) && (cnt++ < retry)) { + if (min_usecs > 0 && max_usecs > 0) + usleep_range(min_usecs, max_usecs); + tmp = readl_relaxed(addr); + } + + if (cnt > retry) { + CAM_DBG(CAM_UTIL, "Poll failed with mask"); + rc = -EINVAL; + } + + return rc; +} + +int cam_io_w_same_offset_block(const uint32_t *data, void __iomem *addr, + uint32_t len) +{ + int i; + + if (!data || !len || !addr) + return -EINVAL; + + for (i = 0; i < len; i++) { + CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK", + i, len, data[i], addr); + writel_relaxed(data[i], addr); + } + + return 0; +} + +int cam_io_w_mb_same_offset_block(const uint32_t *data, void __iomem *addr, + uint32_t len) +{ + int i; + + if (!data || !len || !addr) + return -EINVAL; + + for (i = 0; i < len; i++) { + CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK", + i, len, data[i], addr); + /* Ensure previous writes are done */ + wmb(); + writel_relaxed(data[i], addr); + } + + return 0; +} + +#define __OFFSET(__i) (data[__i][0]) +#define __VAL(__i) (data[__i][1]) +int cam_io_w_offset_val_block(const uint32_t data[][2], + void __iomem *addr_base, uint32_t len) +{ + int i; + + if (!data || !len || !addr_base) + return -EINVAL; + + for (i = 0; i < len; i++) { + CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x", + i, len, __VAL(i), addr_base, __OFFSET(i)); + writel_relaxed(__VAL(i), addr_base + __OFFSET(i)); + } + + return 0; +} + +int cam_io_w_mb_offset_val_block(const uint32_t data[][2], + void __iomem *addr_base, uint32_t len) +{ + int i; + + if (!data || !len || !addr_base) + return -EINVAL; + + /* Ensure write is done */ + wmb(); + for (i = 0; i < len; i++) { + CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x", + i, len, __VAL(i), addr_base, __OFFSET(i)); + writel_relaxed(__VAL(i), addr_base + __OFFSET(i)); + } + + return 0; +} + +#define BYTES_PER_REGISTER 4 +#define NUM_REGISTER_PER_LINE 4 +#define REG_OFFSET(__start, __i) (__start + (__i * BYTES_PER_REGISTER)) +int cam_io_dump(void __iomem *base_addr, uint32_t start_offset, int size) +{ + char line_str[128]; + char *p_str; + int i; + uint32_t data; + + CAM_DBG(CAM_UTIL, "addr=%pK offset=0x%x size=%d", + base_addr, start_offset, size); + + if (!base_addr || (size <= 0)) + return -EINVAL; + + line_str[0] = '\0'; + p_str = line_str; + for (i = 0; i < size; i++) { + if (i % NUM_REGISTER_PER_LINE == 0) { + snprintf(p_str, 12, "0x%08x: ", + REG_OFFSET(start_offset, i)); + p_str += 11; + } + data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i)); + snprintf(p_str, 9, "%08x ", data); + p_str += 8; + if ((i + 1) % NUM_REGISTER_PER_LINE == 0) { + CAM_ERR(CAM_UTIL, "%s", line_str); + line_str[0] = '\0'; + p_str = line_str; + } + } + if (line_str[0] != '\0') + CAM_ERR(CAM_UTIL, "%s", line_str); + + return 0; +} diff --git a/drivers/cam_utils/cam_io_util.h b/drivers/cam_utils/cam_io_util.h new file mode 100644 index 000000000000..66aaeaa45d55 --- /dev/null +++ b/drivers/cam_utils/cam_io_util.h @@ -0,0 +1,232 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2011-2014, 2017-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IO_UTIL_H_ +#define _CAM_IO_UTIL_H_ + +#include + +/** + * cam_io_w() + * + * @brief: Camera IO util for register write + * + * @data: Value to be written + * @addr: Address used to write the value + * + * @return: Success or Failure + */ +int cam_io_w(uint32_t data, void __iomem *addr); + +/** + * cam_io_w_mb() + * + * @brief: Camera IO util for register write with memory barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call wmb() independently in the caller. + * + * @data: Value to be written + * @addr: Address used to write the value + * + * @return: Success or Failure + */ +int cam_io_w_mb(uint32_t data, void __iomem *addr); + +/** + * cam_io_r() + * + * @brief: Camera IO util for register read + * + * @addr: Address of register to be read + * + * @return: Value read from the register address + */ +uint32_t cam_io_r(void __iomem *addr); + +/** + * cam_io_r_mb() + * + * @brief: Camera IO util for register read with memory barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call rmb() independently in the caller. + * + * @addr: Address of register to be read + * + * @return: Value read from the register address + */ +uint32_t cam_io_r_mb(void __iomem *addr); + +/** + * cam_io_memcpy() + * + * @brief: Camera IO util for memory to register copy + * + * @dest_addr: Destination register address + * @src_addr: Source regiser address + * @len: Range to be copied + * + * @return: Success or Failure + */ +int cam_io_memcpy(void __iomem *dest_addr, + void __iomem *src_addr, uint32_t len); + +/** + * cam_io_memcpy_mb() + * + * @brief: Camera IO util for memory to register copy + * with barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call wmb() independently in the caller. + * + * @dest_addr: Destination register address + * @src_addr: Source regiser address + * @len: Range to be copied + * + * @return: Success or Failure + */ +int cam_io_memcpy_mb(void __iomem *dest_addr, + void __iomem *src_addr, uint32_t len); + +/** + * cam_io_poll_value_wmask() + * + * @brief: Poll register value with bitmask. + * + * @addr: Register address to be polled + * @wait_data: Wait until @bmask read from @addr matches this data + * @bmask: Bit mask + * @retry: Number of retry + * @min_usecs: Minimum time to wait for retry + * @max_usecs: Maximum time to wait for retry + * + * @return: Success or Failure + * + * This function can sleep so it should not be called from interrupt + * handler, spin_lock etc. + */ +int cam_io_poll_value_wmask(void __iomem *addr, uint32_t wait_data, + uint32_t bmask, uint32_t retry, unsigned long min_usecs, + unsigned long max_usecs); + +/** + * cam_io_poll_value() + * + * @brief: Poll register value + * + * @addr: Register address to be polled + * @wait_data: Wait until value read from @addr matches this data + * @retry: Number of retry + * @min_usecs: Minimum time to wait for retry + * @max_usecs: Maximum time to wait for retry + * + * @return: Success or Failure + * + * This function can sleep so it should not be called from interrupt + * handler, spin_lock etc. + */ +int cam_io_poll_value(void __iomem *addr, uint32_t wait_data, uint32_t retry, + unsigned long min_usecs, unsigned long max_usecs); + +/** + * cam_io_w_same_offset_block() + * + * @brief: Write a block of data to same address + * + * @data: Block data to be written + * @addr: Register offset to be written. + * @len: Number of the data to be written + * + * @return: Success or Failure + */ +int cam_io_w_same_offset_block(const uint32_t *data, void __iomem *addr, + uint32_t len); + +/** + * cam_io_w_mb_same_offset_block() + * + * @brief: Write a block of data to same address with barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call wmb() independently in the caller. + * + * @data: Block data to be written + * @addr: Register offset to be written. + * @len: Number of the data to be written + * + * @return: Success or Failure + */ +int cam_io_w_mb_same_offset_block(const uint32_t *data, void __iomem *addr, + uint32_t len); + +/** + * cam_io_w_offset_val_block() + * + * @brief: This API is to write a block of registers + * represented by a 2 dimensional array table with + * register offset and value pair + * + * offset0, value0, + * offset1, value1, + * offset2, value2, + * and so on... + * + * @data: Pointer to 2-dimensional offset-value array + * @addr_base: Base address to which offset will be added to + * get the register address + * @len: Length of offset-value pair array to be written in + * number of uin32_t + * + * @return: Success or Failure + * + */ +int32_t cam_io_w_offset_val_block(const uint32_t data[][2], + void __iomem *addr_base, uint32_t len); + +/** + * cam_io_w_mb_offset_val_block() + * + * @brief: This API is to write a block of registers + * represented by a 2 dimensional array table with + * register offset and value pair with memory barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call wmb() independently in the caller. + * The OFFSETS NEED to be different because of the way + * barrier is used here. + * + * offset0, value0, + * offset1, value1, + * offset2, value2, + * and so on... + * + * @data: Pointer to 2-dimensional offset-value array + * @addr_base: Base address to which offset will be added to + * get the register address + * @len: Length of offset-value pair array to be written in + * number of uin32_t + * + * @return: Success or Failure + * + */ +int32_t cam_io_w_mb_offset_val_block(const uint32_t data[][2], + void __iomem *addr_base, uint32_t len); + +/** + * cam_io_dump() + * + * @brief: Camera IO util for dumping a range of register + * + * @base_addr: Start register address for the dumping + * @start_offset: Start register offset for the dump + * @size: Size specifying the range for dumping + * + * @return: Success or Failure + */ +int cam_io_dump(void __iomem *base_addr, uint32_t start_offset, int size); + +#endif /* _CAM_IO_UTIL_H_ */ diff --git a/drivers/cam_utils/cam_packet_util.c b/drivers/cam_utils/cam_packet_util.c new file mode 100644 index 000000000000..4eadee666219 --- /dev/null +++ b/drivers/cam_utils/cam_packet_util.c @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include + +#include "cam_mem_mgr.h" +#include "cam_packet_util.h" +#include "cam_debug_util.h" + +int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr, + size_t *len) +{ + int rc = 0; + uintptr_t kmd_buf_addr = 0; + + rc = cam_mem_get_cpu_buf(handle, &kmd_buf_addr, len); + if (rc) { + CAM_ERR(CAM_UTIL, "Unable to get the virtual address %d", rc); + } else { + if (kmd_buf_addr && *len) { + *buf_addr = (uint32_t *)kmd_buf_addr; + } else { + CAM_ERR(CAM_UTIL, "Invalid addr and length :%zd", *len); + rc = -ENOMEM; + } + } + return rc; +} + +int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc) +{ + if ((cmd_desc->length > cmd_desc->size) || + (cmd_desc->mem_handle <= 0)) { + CAM_ERR(CAM_UTIL, "invalid cmd arg %d %d %d %d", + cmd_desc->offset, cmd_desc->length, + cmd_desc->mem_handle, cmd_desc->size); + return -EINVAL; + } + + return 0; +} + +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); + + 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; + } + + return 0; +} + +int cam_packet_util_get_kmd_buffer(struct cam_packet *packet, + struct cam_kmd_buf_info *kmd_buf) +{ + int rc = 0; + size_t len = 0; + size_t remain_len = 0; + struct cam_cmd_buf_desc *cmd_desc; + uint32_t *cpu_addr; + + if (!packet || !kmd_buf) { + CAM_ERR(CAM_UTIL, "Invalid arg %pK %pK", packet, kmd_buf); + 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); + cmd_desc += packet->kmd_cmd_buf_index; + + rc = cam_packet_util_validate_cmd_desc(cmd_desc); + if (rc) + return rc; + + rc = cam_packet_util_get_cmd_mem_addr(cmd_desc->mem_handle, &cpu_addr, + &len); + if (rc) + return rc; + + 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, + cmd_desc->size - cmd_desc->length); + CAM_DBG(CAM_UTIL, "hdl 0x%x, cmd offset %d, kmd offset %d, addr 0x%pK", + cmd_desc->mem_handle, cmd_desc->offset, + packet->kmd_cmd_buf_offset, cpu_addr); + + kmd_buf->cpu_addr = cpu_addr; + kmd_buf->handle = cmd_desc->mem_handle; + kmd_buf->offset = cmd_desc->offset + packet->kmd_cmd_buf_offset; + kmd_buf->size = cmd_desc->size - cmd_desc->length; + kmd_buf->used_bytes = 0; + + return rc; +} + +int cam_packet_util_process_patches(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl) +{ + struct cam_patch_desc *patch_desc = NULL; + dma_addr_t iova_addr; + uintptr_t cpu_addr = 0; + uint32_t temp; + uint32_t *dst_cpu_addr; + uint32_t *src_buf_iova_addr; + size_t dst_buf_len; + size_t src_buf_size; + int i; + int rc = 0; + int32_t hdl; + + /* process patch descriptor */ + patch_desc = (struct cam_patch_desc *) + ((uint32_t *) &packet->payload + + packet->patch_offset/4); + CAM_DBG(CAM_UTIL, "packet = %pK patch_desc = %pK size = %lu", + (void *)packet, (void *)patch_desc, + 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, + hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "unable to get src buf address"); + return rc; + } + src_buf_iova_addr = (uint32_t *)iova_addr; + temp = iova_addr; + + rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl, + &cpu_addr, &dst_buf_len); + if (rc < 0 || !cpu_addr || (dst_buf_len == 0)) { + CAM_ERR(CAM_UTIL, "unable to get dst buf address"); + return rc; + } + dst_cpu_addr = (uint32_t *)cpu_addr; + + CAM_DBG(CAM_UTIL, "i = %d patch info = %x %x %x %x", i, + 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; + + *dst_cpu_addr = temp; + + CAM_DBG(CAM_UTIL, + "patch is done for dst %pK with src %pK value %llx", + dst_cpu_addr, src_buf_iova_addr, + *((uint64_t *)dst_cpu_addr)); + } + + return rc; +} + +int cam_packet_util_process_generic_cmd_buffer( + struct cam_cmd_buf_desc *cmd_buf, + cam_packet_generic_blob_handler blob_handler_cb, void *user_data) +{ + int rc = 0; + 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; + + if (!cmd_buf || !blob_handler_cb) { + CAM_ERR(CAM_UTIL, "Invalid args %pK %pK", + cmd_buf, blob_handler_cb); + return -EINVAL; + } + + if (!cmd_buf->length || !cmd_buf->size) { + CAM_ERR(CAM_UTIL, "Invalid cmd buf size %d %d", + cmd_buf->length, cmd_buf->size); + return -EINVAL; + } + + rc = cam_mem_get_cpu_buf(cmd_buf->mem_handle, &cpu_addr, &buf_size); + if (rc || !cpu_addr || (buf_size == 0)) { + CAM_ERR(CAM_UTIL, "Failed in Get cpu addr, rc=%d, cpu_addr=%pK", + rc, (void *)cpu_addr); + 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); + + CAM_DBG(CAM_UTIL, + "GenericCmdBuffer cpuaddr=%pK, blobptr=%pK, len=%d", + (void *)cpu_addr, (void *)blob_ptr, cmd_buf->length); + + len_read = 0; + while (len_read < cmd_buf->length) { + blob_type = + ((*blob_ptr) & CAM_GENERIC_BLOB_CMDBUFFER_TYPE_MASK) >> + CAM_GENERIC_BLOB_CMDBUFFER_TYPE_SHIFT; + blob_size = + ((*blob_ptr) & CAM_GENERIC_BLOB_CMDBUFFER_SIZE_MASK) >> + CAM_GENERIC_BLOB_CMDBUFFER_SIZE_SHIFT; + + blob_block_size = sizeof(uint32_t) + + (((blob_size + sizeof(uint32_t) - 1) / + sizeof(uint32_t)) * sizeof(uint32_t)); + + CAM_DBG(CAM_UTIL, + "Blob type=%d size=%d block_size=%d len_read=%d total=%d", + blob_type, blob_size, blob_block_size, len_read, + cmd_buf->length); + + if (len_read + blob_block_size > cmd_buf->length) { + CAM_ERR(CAM_UTIL, "Invalid Blob %d %d %d %d", + blob_type, blob_size, len_read, + cmd_buf->length); + rc = -EINVAL; + goto end; + } + + len_read += blob_block_size; + + rc = blob_handler_cb(user_data, blob_type, blob_size, + (uint8_t *)(blob_ptr + 1)); + if (rc) { + CAM_ERR(CAM_UTIL, "Error in handling blob type %d %d", + blob_type, blob_size); + goto end; + } + + blob_ptr += (blob_block_size / sizeof(uint32_t)); + } + +end: + return rc; +} diff --git a/drivers/cam_utils/cam_packet_util.h b/drivers/cam_utils/cam_packet_util.h new file mode 100644 index 000000000000..d5fc8f70ec07 --- /dev/null +++ b/drivers/cam_utils/cam_packet_util.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_PACKET_UTIL_H_ +#define _CAM_PACKET_UTIL_H_ + +#include + +/** + * @brief KMD scratch buffer information + * + * @handle: Memory handle + * @cpu_addr: Cpu address + * @offset: Offset from the start of the buffer + * @size: Size of the buffer + * @used_bytes: Used memory in bytes + * + */ +struct cam_kmd_buf_info { + int handle; + uint32_t *cpu_addr; + uint32_t offset; + uint32_t size; + uint32_t used_bytes; +}; + +/* Generic Cmd Buffer blob callback function type */ +typedef int (*cam_packet_generic_blob_handler)(void *user_data, + uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data); + +/** + * cam_packet_util_get_cmd_mem_addr() + * + * @brief Get command buffer address + * + * @handle: Command buffer memory handle + * @buf_addr: Command buffer cpu mapped address + * @len: Command buffer length + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr, + size_t *len); + +/** + * cam_packet_util_validate_packet() + * + * @brief Validate the packet + * + * @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, + size_t remain_len); + +/** + * cam_packet_util_validate_cmd_desc() + * + * @brief Validate the packet + * + * @cmd_desc: Command descriptor to be validated + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc); + +/** + * cam_packet_util_get_kmd_buffer() + * + * @brief Get the kmd buffer from the packet command descriptor + * + * @packet: Packet data + * @kmd_buf: Extracted the KMD buffer information + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_packet_util_get_kmd_buffer(struct cam_packet *packet, + struct cam_kmd_buf_info *kmd_buf_info); + +/** + * cam_packet_util_process_patches() + * + * @brief: Replace the handle in Packet to Address using the + * information from patches. + * + * @packet: Input packet containing Command Buffers and Patches + * @iommu_hdl: IOMMU handle of the HW Device that received the packet + * @sec_iommu_hdl: Secure IOMMU handle of the HW Device that + * received the packet + * + * @return: 0: Success + * Negative: Failure + */ +int cam_packet_util_process_patches(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl); + +/** + * cam_packet_util_process_generic_cmd_buffer() + * + * @brief: Process Generic Blob command buffer. This utility + * function process the command buffer and calls the + * blob_handle_cb callback for each blob that exists + * in the command buffer. + * + * @cmd_buf: Generic Blob Cmd Buffer handle + * @blob_handler_cb: Callback pointer to call for each blob exists in the + * command buffer + * @user_data: User data to be passed while callback + * + * @return: 0: Success + * Negative: Failure + */ +int cam_packet_util_process_generic_cmd_buffer( + struct cam_cmd_buf_desc *cmd_buf, + cam_packet_generic_blob_handler blob_handler_cb, void *user_data); + +#endif /* _CAM_PACKET_UTIL_H_ */ diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c new file mode 100644 index 000000000000..4f031ee720b0 --- /dev/null +++ b/drivers/cam_utils/cam_soc_util.c @@ -0,0 +1,1752 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_cx_ipeak.h" + +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() + * + * @brief: Returns the string for a given clk level + * + * @level: Clock level + * + * @return: String corresponding to the clk level + */ +static const char *cam_soc_util_get_string_from_level( + enum cam_vote_level level) +{ + switch (level) { + case CAM_SUSPEND_VOTE: + return ""; + case CAM_MINSVS_VOTE: + return "MINSVS[1]"; + case CAM_LOWSVS_VOTE: + return "LOWSVS[2]"; + case CAM_SVS_VOTE: + return "SVS[3]"; + case CAM_SVSL1_VOTE: + return "SVSL1[4]"; + case CAM_NOMINAL_VOTE: + return "NOM[5]"; + case CAM_NOMINALL1_VOTE: + return "NOML1[6]"; + case CAM_TURBO_VOTE: + return "TURBO[7]"; + default: + return ""; + } +} + +/** + * cam_soc_util_get_supported_clk_levels() + * + * @brief: Returns the string of all the supported clk levels for + * the given device + * + * @soc_info: Device soc information + * + * @return: String containing all supported clk levels + */ +static const char *cam_soc_util_get_supported_clk_levels( + struct cam_hw_soc_info *soc_info) +{ + int i = 0; + + memset(supported_clk_info, 0, sizeof(supported_clk_info)); + strlcat(supported_clk_info, "Supported levels: ", + sizeof(supported_clk_info)); + + for (i = 0; i < CAM_MAX_VOTE; i++) { + if (soc_info->clk_level_valid[i] == true) { + strlcat(supported_clk_info, + cam_soc_util_get_string_from_level(i), + sizeof(supported_clk_info)); + strlcat(supported_clk_info, " ", + sizeof(supported_clk_info)); + } + } + + strlcat(supported_clk_info, "\n", sizeof(supported_clk_info)); + return supported_clk_info; +} + +static int cam_soc_util_clk_lvl_options_open(struct inode *inode, + struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t cam_soc_util_clk_lvl_options_read(struct file *file, + char __user *clk_info, size_t size_t, loff_t *loff_t) +{ + struct cam_hw_soc_info *soc_info = + (struct cam_hw_soc_info *)file->private_data; + const char *display_string = + cam_soc_util_get_supported_clk_levels(soc_info); + + return simple_read_from_buffer(clk_info, size_t, loff_t, display_string, + strlen(display_string)); +} + +static const struct file_operations cam_soc_util_clk_lvl_options = { + .open = cam_soc_util_clk_lvl_options_open, + .read = cam_soc_util_clk_lvl_options_read, +}; + +static int cam_soc_util_set_clk_lvl(void *data, u64 val) +{ + struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data; + + if (val <= CAM_SUSPEND_VOTE || val >= CAM_MAX_VOTE) + return 0; + + if (soc_info->clk_level_valid[val] == true) + soc_info->clk_level_override = val; + else + soc_info->clk_level_override = 0; + + return 0; +} + +static int cam_soc_util_get_clk_lvl(void *data, u64 *val) +{ + struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data; + + *val = soc_info->clk_level_override; + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control, + cam_soc_util_get_clk_lvl, cam_soc_util_set_clk_lvl, "%08llu"); + +/** + * cam_soc_util_create_clk_lvl_debugfs() + * + * @brief: Creates debugfs files to view/control device clk rates + * + * @soc_info: Device soc information + * + * @return: Success or failure + */ +static int cam_soc_util_create_clk_lvl_debugfs( + struct cam_hw_soc_info *soc_info) +{ + struct dentry *dentry = NULL; + + if (!soc_info) { + CAM_ERR(CAM_UTIL, "soc info is NULL"); + return -EINVAL; + } + + if (soc_info->dentry) + return 0; + + memset(debugfs_dir_name, 0, sizeof(debugfs_dir_name)); + strlcat(debugfs_dir_name, "clk_dir_", sizeof(debugfs_dir_name)); + strlcat(debugfs_dir_name, soc_info->dev_name, sizeof(debugfs_dir_name)); + + dentry = soc_info->dentry; + dentry = debugfs_create_dir(debugfs_dir_name, NULL); + if (!dentry) { + CAM_ERR(CAM_UTIL, "failed to create debug directory"); + return -ENOMEM; + } + + if (!debugfs_create_file("clk_lvl_options", 0444, + dentry, soc_info, &cam_soc_util_clk_lvl_options)) { + CAM_ERR(CAM_UTIL, "failed to create clk_lvl_options"); + goto err; + } + + if (!debugfs_create_file("clk_lvl_control", 0644, + dentry, soc_info, &cam_soc_util_clk_lvl_control)) { + CAM_ERR(CAM_UTIL, "failed to create clk_lvl_control"); + goto err; + } + + CAM_DBG(CAM_UTIL, "clk lvl debugfs for %s successfully created", + soc_info->dev_name); + + return 0; + +err: + debugfs_remove_recursive(dentry); + dentry = NULL; + return -ENOMEM; +} + +/** + * cam_soc_util_remove_clk_lvl_debugfs() + * + * @brief: Removes the debugfs files used to view/control + * device clk rates + * + * @soc_info: Device soc information + * + */ +static void cam_soc_util_remove_clk_lvl_debugfs( + struct cam_hw_soc_info *soc_info) +{ + debugfs_remove_recursive(soc_info->dentry); + soc_info->dentry = NULL; +} + +int cam_soc_util_get_level_from_string(const char *string, + enum cam_vote_level *level) +{ + if (!level) + return -EINVAL; + + if (!strcmp(string, "suspend")) { + *level = CAM_SUSPEND_VOTE; + } else if (!strcmp(string, "minsvs")) { + *level = CAM_MINSVS_VOTE; + } else if (!strcmp(string, "lowsvs")) { + *level = CAM_LOWSVS_VOTE; + } else if (!strcmp(string, "svs")) { + *level = CAM_SVS_VOTE; + } else if (!strcmp(string, "svs_l1")) { + *level = CAM_SVSL1_VOTE; + } else if (!strcmp(string, "nominal")) { + *level = CAM_NOMINAL_VOTE; + } else if (!strcmp(string, "nominal_l1")) { + *level = CAM_NOMINALL1_VOTE; + } else if (!strcmp(string, "turbo")) { + *level = CAM_TURBO_VOTE; + } else { + CAM_ERR(CAM_UTIL, "Invalid string %s", string); + return -EINVAL; + } + + return 0; +} + +/** + * cam_soc_util_get_clk_level_to_apply() + * + * @brief: Get the clock level to apply. If the requested level + * is not valid, bump the level to next available valid + * level. If no higher level found, return failure. + * + * @soc_info: Device soc struct to be populated + * @req_level: Requested level + * @apply_level Level to apply + * + * @return: success or failure + */ +static int cam_soc_util_get_clk_level_to_apply( + struct cam_hw_soc_info *soc_info, enum cam_vote_level req_level, + enum cam_vote_level *apply_level) +{ + if (req_level >= CAM_MAX_VOTE) { + CAM_ERR(CAM_UTIL, "Invalid clock level parameter %d", + req_level); + return -EINVAL; + } + + if (soc_info->clk_level_valid[req_level] == true) { + *apply_level = req_level; + } else { + int i; + + for (i = (req_level + 1); i < CAM_MAX_VOTE; i++) + if (soc_info->clk_level_valid[i] == true) { + *apply_level = i; + break; + } + + if (i == CAM_MAX_VOTE) { + CAM_ERR(CAM_UTIL, + "No valid clock level found to apply, req=%d", + req_level); + return -EINVAL; + } + } + + CAM_DBG(CAM_UTIL, "Req level %d, Applying %d", + req_level, *apply_level); + + return 0; +} + +int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info) +{ + if (!soc_info) { + CAM_ERR(CAM_UTIL, "Invalid arguments"); + return -EINVAL; + } + + if (!soc_info->irq_line) { + CAM_ERR(CAM_UTIL, "No IRQ line available"); + return -ENODEV; + } + + enable_irq(soc_info->irq_line->start); + + return 0; +} + +int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info) +{ + if (!soc_info) { + CAM_ERR(CAM_UTIL, "Invalid arguments"); + return -EINVAL; + } + + if (!soc_info->irq_line) { + CAM_ERR(CAM_UTIL, "No IRQ line available"); + return -ENODEV; + } + + disable_irq(soc_info->irq_line->start); + + return 0; +} + +long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_index, unsigned long clk_rate) +{ + if (!soc_info || (clk_index >= soc_info->num_clk) || (clk_rate == 0)) { + CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d %lu", + soc_info, clk_index, clk_rate); + return clk_rate; + } + + return clk_round_rate(soc_info->clk[clk_index], clk_rate); +} + +int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info, + uint32_t clk_index, unsigned long flags) +{ + if (!soc_info || (clk_index >= soc_info->num_clk)) { + CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d", + soc_info, clk_index); + return -EINVAL; + } + + return clk_set_flags(soc_info->clk[clk_index], flags); +} + +/** + * cam_soc_util_set_clk_rate() + * + * @brief: Sets the given rate for the clk requested for + * + * @clk: Clock structure information for which rate is to be set + * @clk_name: Name of the clock for which rate is being set + * @clk_rate Clock rate to be set + * + * @return: Success or failure + */ +static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, + int32_t clk_rate) +{ + int rc = 0; + long clk_rate_round; + + if (!clk || !clk_name) + return -EINVAL; + + CAM_DBG(CAM_UTIL, "set %s, rate %d", clk_name, clk_rate); + if (clk_rate > 0) { + clk_rate_round = clk_round_rate(clk, clk_rate); + CAM_DBG(CAM_UTIL, "new_rate %ld", clk_rate_round); + if (clk_rate_round < 0) { + CAM_ERR(CAM_UTIL, "round failed for clock %s rc = %ld", + clk_name, clk_rate_round); + return clk_rate_round; + } + rc = clk_set_rate(clk, clk_rate_round); + if (rc) { + CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name); + return rc; + } + } else if (clk_rate == INIT_RATE) { + clk_rate_round = clk_get_rate(clk); + CAM_DBG(CAM_UTIL, "init new_rate %ld", clk_rate_round); + if (clk_rate_round == 0) { + clk_rate_round = clk_round_rate(clk, 0); + if (clk_rate_round <= 0) { + CAM_ERR(CAM_UTIL, "round rate failed on %s", + clk_name); + return clk_rate_round; + } + } + rc = clk_set_rate(clk, clk_rate_round); + if (rc) { + CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name); + return rc; + } + } + + return rc; +} + +int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, + int32_t clk_rate) +{ + int32_t src_clk_idx; + struct clk *clk = NULL; + int32_t apply_level; + uint32_t clk_level_override = 0; + + if (!soc_info || (soc_info->src_clk_idx < 0)) + return -EINVAL; + + src_clk_idx = soc_info->src_clk_idx; + clk_level_override = soc_info->clk_level_override; + if (clk_level_override && clk_rate) + clk_rate = + soc_info->clk_rate[clk_level_override][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); + +} + +int cam_soc_util_clk_put(struct clk **clk) +{ + if (!(*clk)) { + CAM_ERR(CAM_UTIL, "Invalid params clk"); + return -EINVAL; + } + + clk_put(*clk); + *clk = NULL; + + return 0; +} + +static struct clk *cam_soc_util_option_clk_get(struct device_node *np, + int index) +{ + struct of_phandle_args clkspec; + struct clk *clk; + int rc; + + if (index < 0) + return ERR_PTR(-EINVAL); + + rc = of_parse_phandle_with_args(np, "clocks-option", "#clock-cells", + index, &clkspec); + if (rc) + return ERR_PTR(rc); + + clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); + + return clk; +} + +int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info, + const char *clk_name, struct clk **clk, int32_t *clk_index, + int32_t *clk_rate) +{ + int index = 0; + int rc = 0; + struct device_node *of_node = NULL; + + if (!soc_info || !clk_name || !clk) { + CAM_ERR(CAM_UTIL, + "Invalid params soc_info %pK clk_name %s clk %pK", + soc_info, clk_name, clk); + return -EINVAL; + } + + of_node = soc_info->dev->of_node; + + index = of_property_match_string(of_node, "clock-names-option", + clk_name); + + if (index < 0) { + CAM_INFO(CAM_UTIL, "No clk data for %s", clk_name); + *clk_index = -1; + *clk = ERR_PTR(-EINVAL); + return -EINVAL; + } + + *clk = cam_soc_util_option_clk_get(of_node, index); + if (IS_ERR(*clk)) { + CAM_ERR(CAM_UTIL, "No clk named %s found. Dev %s", clk_name, + soc_info->dev_name); + *clk_index = -1; + return -EFAULT; + } + *clk_index = index; + + rc = of_property_read_u32_index(of_node, "clock-rates-option", + index, clk_rate); + if (rc) { + CAM_ERR(CAM_UTIL, + "Error reading clock-rates clk_name %s index %d", + clk_name, index); + cam_soc_util_clk_put(clk); + *clk_rate = 0; + return rc; + } + + /* + * Option clocks are assumed to be available to single Device here. + * Hence use INIT_RATE instead of NO_SET_RATE. + */ + *clk_rate = (*clk_rate == 0) ? (int32_t)INIT_RATE : *clk_rate; + + CAM_DBG(CAM_UTIL, "clk_name %s index %d clk_rate %d", + clk_name, *clk_index, *clk_rate); + + return 0; +} + +int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name, + int32_t clk_rate) +{ + int rc = 0; + + if (!clk || !clk_name) + return -EINVAL; + + rc = cam_soc_util_set_clk_rate(clk, clk_name, clk_rate); + if (rc) + return rc; + + rc = clk_prepare_enable(clk); + if (rc) { + CAM_ERR(CAM_UTIL, "enable failed for %s: rc(%d)", clk_name, rc); + return rc; + } + + return rc; +} + +int cam_soc_util_clk_disable(struct clk *clk, const char *clk_name) +{ + if (!clk || !clk_name) + return -EINVAL; + + CAM_DBG(CAM_UTIL, "disable %s", clk_name); + clk_disable_unprepare(clk); + + return 0; +} + +/** + * cam_soc_util_clk_enable_default() + * + * @brief: This function enables the default clocks present + * in soc_info + * + * @soc_info: Device soc struct to be populated + * @clk_level: Clk level to apply while enabling + * + * @return: success or failure + */ +int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, + enum cam_vote_level clk_level) +{ + int i, rc = 0; + enum cam_vote_level apply_level; + + if ((soc_info->num_clk == 0) || + (soc_info->num_clk >= CAM_SOC_MAX_CLK)) { + CAM_ERR(CAM_UTIL, "Invalid number of clock %d", + soc_info->num_clk); + return -EINVAL; + } + + rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level, + &apply_level); + 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]); + } + + return rc; +} + +/** + * cam_soc_util_clk_disable_default() + * + * @brief: This function disables the default clocks present + * in soc_info + * + * @soc_info: device soc struct to be populated + * + * @return: success or failure + */ +void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info) +{ + int i; + + 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]); +} + +/** + * cam_soc_util_get_dt_clk_info() + * + * @brief: Parse the DT and populate the Clock properties + * + * @soc_info: device soc struct to be populated + * @src_clk_str name of src clock that has rate control + * + * @return: success or failure + */ +static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info) +{ + struct device_node *of_node = NULL; + int count; + int num_clk_rates, num_clk_levels; + int i, j, rc; + int32_t num_clk_level_strings; + const char *src_clk_str = NULL; + const char *clk_control_debugfs = NULL; + const char *clk_cntl_lvl_string = NULL; + enum cam_vote_level level; + + if (!soc_info || !soc_info->dev) + return -EINVAL; + + of_node = soc_info->dev->of_node; + + if (!of_property_read_bool(of_node, "use-shared-clk")) { + CAM_DBG(CAM_UTIL, "No shared clk parameter defined"); + soc_info->use_shared_clk = false; + } else { + soc_info->use_shared_clk = true; + } + + count = of_property_count_strings(of_node, "clock-names"); + + 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; + return rc; + } + if (count <= 0) { + CAM_DBG(CAM_UTIL, "No clock-names found"); + count = 0; + soc_info->num_clk = count; + return 0; + } + soc_info->num_clk = count; + + for (i = 0; i < count; i++) { + rc = of_property_read_string_index(of_node, "clock-names", + i, &(soc_info->clk_name[i])); + CAM_DBG(CAM_UTIL, "clock-names[%d] = %s", + i, soc_info->clk_name[i]); + if (rc) { + CAM_ERR(CAM_UTIL, + "i= %d count= %d reading clock-names failed", + i, count); + return rc; + } + } + + num_clk_rates = of_property_count_u32_elems(of_node, "clock-rates"); + if (num_clk_rates <= 0) { + CAM_ERR(CAM_UTIL, "reading clock-rates count failed"); + return -EINVAL; + } + + if ((num_clk_rates % soc_info->num_clk) != 0) { + CAM_ERR(CAM_UTIL, + "mismatch clk/rates, No of clocks=%d, No of rates=%d", + soc_info->num_clk, num_clk_rates); + return -EINVAL; + } + + num_clk_levels = (num_clk_rates / soc_info->num_clk); + + num_clk_level_strings = of_property_count_strings(of_node, + "clock-cntl-level"); + if (num_clk_level_strings != num_clk_levels) { + CAM_ERR(CAM_UTIL, + "Mismatch No of levels=%d, No of level string=%d", + num_clk_levels, num_clk_level_strings); + return -EINVAL; + } + + for (i = 0; i < num_clk_levels; i++) { + rc = of_property_read_string_index(of_node, + "clock-cntl-level", i, &clk_cntl_lvl_string); + if (rc) { + CAM_ERR(CAM_UTIL, + "Error reading clock-cntl-level, rc=%d", rc); + return rc; + } + + rc = cam_soc_util_get_level_from_string(clk_cntl_lvl_string, + &level); + if (rc) + return rc; + + CAM_DBG(CAM_UTIL, + "[%d] : %s %d", i, clk_cntl_lvl_string, level); + soc_info->clk_level_valid[level] = true; + for (j = 0; j < soc_info->num_clk; j++) { + rc = of_property_read_u32_index(of_node, "clock-rates", + ((i * soc_info->num_clk) + j), + &soc_info->clk_rate[level][j]); + if (rc) { + CAM_ERR(CAM_UTIL, + "Error reading clock-rates, rc=%d", + rc); + return rc; + } + + soc_info->clk_rate[level][j] = + (soc_info->clk_rate[level][j] == 0) ? + (int32_t)NO_SET_RATE : + soc_info->clk_rate[level][j]; + + CAM_DBG(CAM_UTIL, "soc_info->clk_rate[%d][%d] = %d", + level, j, + soc_info->clk_rate[level][j]); + } + } + + soc_info->src_clk_idx = -1; + rc = of_property_read_string_index(of_node, "src-clock-name", 0, + &src_clk_str); + if (rc || !src_clk_str) { + CAM_DBG(CAM_UTIL, "No src_clk_str found"); + rc = 0; + goto end; + } + + for (i = 0; i < soc_info->num_clk; i++) { + if (strcmp(soc_info->clk_name[i], src_clk_str) == 0) { + soc_info->src_clk_idx = i; + CAM_DBG(CAM_UTIL, "src clock = %s, index = %d", + src_clk_str, i); + break; + } + } + + rc = of_property_read_string_index(of_node, + "clock-control-debugfs", 0, &clk_control_debugfs); + if (rc || !clk_control_debugfs) { + CAM_DBG(CAM_UTIL, "No clock_control_debugfs property found"); + rc = 0; + goto end; + } + + 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; +} + +int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, + enum cam_vote_level clk_level) +{ + int i, rc = 0; + enum cam_vote_level apply_level; + + if ((soc_info->num_clk == 0) || + (soc_info->num_clk >= CAM_SOC_MAX_CLK)) { + CAM_ERR(CAM_UTIL, "Invalid number of clock %d", + soc_info->num_clk); + return -EINVAL; + } + + rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level, + &apply_level); + 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 < 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; +}; + +static int cam_soc_util_get_dt_gpio_req_tbl(struct device_node *of_node, + struct cam_soc_gpio_data *gconf, uint16_t *gpio_array, + uint16_t gpio_array_size) +{ + int32_t rc = 0, i = 0; + uint32_t count = 0; + uint32_t *val_array = NULL; + + if (!of_get_property(of_node, "gpio-req-tbl-num", &count)) + return 0; + + count /= sizeof(uint32_t); + if (!count) { + CAM_ERR(CAM_UTIL, "gpio-req-tbl-num 0"); + return 0; + } + + val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL); + if (!val_array) + return -ENOMEM; + + gconf->cam_gpio_req_tbl = kcalloc(count, sizeof(struct gpio), + GFP_KERNEL); + if (!gconf->cam_gpio_req_tbl) { + rc = -ENOMEM; + goto free_val_array; + } + gconf->cam_gpio_req_tbl_size = count; + + rc = of_property_read_u32_array(of_node, "gpio-req-tbl-num", + val_array, count); + if (rc) { + CAM_ERR(CAM_UTIL, "failed in reading gpio-req-tbl-num, rc = %d", + rc); + goto free_gpio_req_tbl; + } + + for (i = 0; i < count; i++) { + if (val_array[i] >= gpio_array_size) { + CAM_ERR(CAM_UTIL, "gpio req tbl index %d invalid", + val_array[i]); + goto free_gpio_req_tbl; + } + gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]]; + CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].gpio = %d", i, + gconf->cam_gpio_req_tbl[i].gpio); + } + + rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags", + val_array, count); + if (rc) { + CAM_ERR(CAM_UTIL, "Failed in gpio-req-tbl-flags, rc %d", rc); + goto free_gpio_req_tbl; + } + + for (i = 0; i < count; i++) { + gconf->cam_gpio_req_tbl[i].flags = val_array[i]; + CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].flags = %ld", i, + gconf->cam_gpio_req_tbl[i].flags); + } + + for (i = 0; i < count; i++) { + rc = of_property_read_string_index(of_node, + "gpio-req-tbl-label", i, + &gconf->cam_gpio_req_tbl[i].label); + if (rc) { + CAM_ERR(CAM_UTIL, "Failed rc %d", rc); + goto free_gpio_req_tbl; + } + CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].label = %s", i, + gconf->cam_gpio_req_tbl[i].label); + } + + kfree(val_array); + + return rc; + +free_gpio_req_tbl: + kfree(gconf->cam_gpio_req_tbl); +free_val_array: + kfree(val_array); + gconf->cam_gpio_req_tbl_size = 0; + + return rc; +} + +static int cam_soc_util_get_gpio_info(struct cam_hw_soc_info *soc_info) +{ + int32_t rc = 0, i = 0; + uint16_t *gpio_array = NULL; + int16_t gpio_array_size = 0; + struct cam_soc_gpio_data *gconf = NULL; + struct device_node *of_node = NULL; + + if (!soc_info || !soc_info->dev) + return -EINVAL; + + of_node = soc_info->dev->of_node; + + /* Validate input parameters */ + if (!of_node) { + CAM_ERR(CAM_UTIL, "Invalid param of_node"); + return -EINVAL; + } + + gpio_array_size = of_gpio_count(of_node); + + if (gpio_array_size <= 0) + return 0; + + CAM_DBG(CAM_UTIL, "gpio count %d", gpio_array_size); + + gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL); + if (!gpio_array) + goto free_gpio_conf; + + for (i = 0; i < gpio_array_size; i++) { + gpio_array[i] = of_get_gpio(of_node, i); + CAM_DBG(CAM_UTIL, "gpio_array[%d] = %d", i, gpio_array[i]); + } + + gconf = kzalloc(sizeof(*gconf), GFP_KERNEL); + if (!gconf) + return -ENOMEM; + + rc = cam_soc_util_get_dt_gpio_req_tbl(of_node, gconf, gpio_array, + gpio_array_size); + if (rc) { + CAM_ERR(CAM_UTIL, "failed in msm_camera_get_dt_gpio_req_tbl"); + goto free_gpio_array; + } + + gconf->cam_gpio_common_tbl = kcalloc(gpio_array_size, + sizeof(struct gpio), GFP_KERNEL); + if (!gconf->cam_gpio_common_tbl) { + rc = -ENOMEM; + goto free_gpio_array; + } + + for (i = 0; i < gpio_array_size; i++) + gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i]; + + gconf->cam_gpio_common_tbl_size = gpio_array_size; + soc_info->gpio_data = gconf; + kfree(gpio_array); + + return rc; + +free_gpio_array: + kfree(gpio_array); +free_gpio_conf: + kfree(gconf); + soc_info->gpio_data = NULL; + + return rc; +} + +static int cam_soc_util_request_gpio_table( + struct cam_hw_soc_info *soc_info, bool gpio_en) +{ + int rc = 0, i = 0; + uint8_t size = 0; + struct cam_soc_gpio_data *gpio_conf = + soc_info->gpio_data; + struct gpio *gpio_tbl = NULL; + + + if (!gpio_conf) { + CAM_DBG(CAM_UTIL, "No GPIO entry"); + return 0; + } + if (gpio_conf->cam_gpio_common_tbl_size <= 0) { + CAM_ERR(CAM_UTIL, "GPIO table size is invalid"); + return -EINVAL; + } + size = gpio_conf->cam_gpio_req_tbl_size; + gpio_tbl = gpio_conf->cam_gpio_req_tbl; + + if (!gpio_tbl || !size) { + CAM_ERR(CAM_UTIL, "Invalid gpio_tbl %pK / size %d", + gpio_tbl, size); + return -EINVAL; + } + for (i = 0; i < size; i++) { + CAM_DBG(CAM_UTIL, "i=%d, gpio=%d dir=%ld", i, + gpio_tbl[i].gpio, gpio_tbl[i].flags); + } + if (gpio_en) { + for (i = 0; i < size; i++) { + rc = gpio_request_one(gpio_tbl[i].gpio, + gpio_tbl[i].flags, gpio_tbl[i].label); + if (rc) { + /* + * After GPIO request fails, contine to + * apply new gpios, outout a error message + * for driver bringup debug + */ + CAM_ERR(CAM_UTIL, "gpio %d:%s request fails", + gpio_tbl[i].gpio, gpio_tbl[i].label); + } + } + } else { + gpio_free_array(gpio_tbl, size); + } + + return rc; +} + +static int cam_soc_util_get_dt_regulator_info + (struct cam_hw_soc_info *soc_info) +{ + int rc = 0, count = 0, i = 0; + struct device_node *of_node = NULL; + + if (!soc_info || !soc_info->dev) { + CAM_ERR(CAM_UTIL, "Invalid parameters"); + return -EINVAL; + } + + of_node = soc_info->dev->of_node; + + soc_info->num_rgltr = 0; + count = of_property_count_strings(of_node, "regulator-names"); + if (count != -EINVAL) { + if (count <= 0) { + CAM_ERR(CAM_UTIL, "no regulators found"); + count = 0; + return -EINVAL; + } + + soc_info->num_rgltr = count; + + } else { + CAM_DBG(CAM_UTIL, "No regulators node found"); + return 0; + } + + for (i = 0; i < soc_info->num_rgltr; i++) { + rc = of_property_read_string_index(of_node, + "regulator-names", i, &soc_info->rgltr_name[i]); + CAM_DBG(CAM_UTIL, "rgltr_name[%d] = %s", + i, soc_info->rgltr_name[i]); + if (rc) { + CAM_ERR(CAM_UTIL, "no regulator resource at cnt=%d", i); + return -ENODEV; + } + } + + if (!of_property_read_bool(of_node, "rgltr-cntrl-support")) { + CAM_DBG(CAM_UTIL, "No regulator control parameter defined"); + soc_info->rgltr_ctrl_support = false; + return 0; + } + + soc_info->rgltr_ctrl_support = true; + + rc = of_property_read_u32_array(of_node, "rgltr-min-voltage", + soc_info->rgltr_min_volt, soc_info->num_rgltr); + if (rc) { + CAM_ERR(CAM_UTIL, "No minimum volatage value found, rc=%d", rc); + return -EINVAL; + } + + rc = of_property_read_u32_array(of_node, "rgltr-max-voltage", + soc_info->rgltr_max_volt, soc_info->num_rgltr); + if (rc) { + CAM_ERR(CAM_UTIL, "No maximum volatage value found, rc=%d", rc); + return -EINVAL; + } + + rc = of_property_read_u32_array(of_node, "rgltr-load-current", + soc_info->rgltr_op_mode, soc_info->num_rgltr); + if (rc) { + CAM_ERR(CAM_UTIL, "No Load curent found rc=%d", rc); + return -EINVAL; + } + + return rc; +} + +int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + struct device_node *of_node = NULL; + int count = 0, i = 0, rc = 0; + + if (!soc_info || !soc_info->dev) + return -EINVAL; + + of_node = soc_info->dev->of_node; + + rc = of_property_read_u32(of_node, "cell-index", &soc_info->index); + if (rc) { + CAM_ERR(CAM_UTIL, "device %s failed to read cell-index", + soc_info->dev_name); + return rc; + } + + count = of_property_count_strings(of_node, "reg-names"); + if (count <= 0) { + CAM_DBG(CAM_UTIL, "no reg-names found for: %s", + soc_info->dev_name); + count = 0; + } + soc_info->num_mem_block = count; + + for (i = 0; i < soc_info->num_mem_block; i++) { + rc = of_property_read_string_index(of_node, "reg-names", i, + &soc_info->mem_block_name[i]); + if (rc) { + CAM_ERR(CAM_UTIL, "failed to read reg-names at %d", i); + return rc; + } + soc_info->mem_block[i] = + platform_get_resource_byname(soc_info->pdev, + IORESOURCE_MEM, soc_info->mem_block_name[i]); + + if (!soc_info->mem_block[i]) { + CAM_ERR(CAM_UTIL, "no mem resource by name %s", + soc_info->mem_block_name[i]); + rc = -ENODEV; + return rc; + } + } + + if (soc_info->num_mem_block > 0) { + rc = of_property_read_u32_array(of_node, "reg-cam-base", + soc_info->mem_block_cam_base, soc_info->num_mem_block); + if (rc) { + CAM_ERR(CAM_UTIL, "Error reading register offsets"); + return rc; + } + } + + rc = of_property_read_string_index(of_node, "interrupt-names", 0, + &soc_info->irq_name); + if (rc) { + CAM_DBG(CAM_UTIL, "No interrupt line preset for: %s", + soc_info->dev_name); + rc = 0; + } else { + soc_info->irq_line = + platform_get_resource_byname(soc_info->pdev, + IORESOURCE_IRQ, soc_info->irq_name); + if (!soc_info->irq_line) { + CAM_ERR(CAM_UTIL, "no irq resource"); + rc = -ENODEV; + return rc; + } + } + + rc = of_property_read_string_index(of_node, "compatible", 0, + (const char **)&soc_info->compatible); + if (rc) { + CAM_DBG(CAM_UTIL, "No compatible string present for: %s", + soc_info->dev_name); + rc = 0; + } + + rc = cam_soc_util_get_dt_regulator_info(soc_info); + if (rc) + return rc; + + rc = cam_soc_util_get_dt_clk_info(soc_info); + if (rc) + return rc; + + rc = cam_soc_util_get_gpio_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; +} + +/** + * cam_soc_util_get_regulator() + * + * @brief: Get regulator resource named vdd + * + * @dev: Device associated with regulator + * @reg: Return pointer to be filled with regulator on success + * @rgltr_name: Name of regulator to get + * + * @return: 0 for Success, negative value for failure + */ +static int cam_soc_util_get_regulator(struct device *dev, + struct regulator **reg, const char *rgltr_name) +{ + int rc = 0; + *reg = regulator_get(dev, rgltr_name); + if (IS_ERR_OR_NULL(*reg)) { + rc = PTR_ERR(*reg); + rc = rc ? rc : -EINVAL; + CAM_ERR(CAM_UTIL, "Regulator %s get failed %d", rgltr_name, rc); + *reg = NULL; + } + return rc; +} + +int cam_soc_util_regulator_disable(struct regulator *rgltr, + const char *rgltr_name, uint32_t rgltr_min_volt, + uint32_t rgltr_max_volt, uint32_t rgltr_op_mode, + uint32_t rgltr_delay_ms) +{ + int32_t rc = 0; + + if (!rgltr) { + CAM_ERR(CAM_UTIL, "Invalid NULL parameter"); + return -EINVAL; + } + + rc = regulator_disable(rgltr); + if (rc) { + CAM_ERR(CAM_UTIL, "%s regulator disable failed", rgltr_name); + return rc; + } + + if (rgltr_delay_ms > 20) + msleep(rgltr_delay_ms); + else if (rgltr_delay_ms) + usleep_range(rgltr_delay_ms * 1000, + (rgltr_delay_ms * 1000) + 1000); + + if (regulator_count_voltages(rgltr) > 0) { + regulator_set_load(rgltr, 0); + regulator_set_voltage(rgltr, 0, rgltr_max_volt); + } + + return rc; +} + + +int cam_soc_util_regulator_enable(struct regulator *rgltr, + const char *rgltr_name, + uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, + uint32_t rgltr_op_mode, uint32_t rgltr_delay) +{ + int32_t rc = 0; + + if (!rgltr) { + CAM_ERR(CAM_UTIL, "Invalid NULL parameter"); + return -EINVAL; + } + + if (regulator_count_voltages(rgltr) > 0) { + CAM_DBG(CAM_UTIL, "voltage min=%d, max=%d", + rgltr_min_volt, rgltr_max_volt); + + rc = regulator_set_voltage( + rgltr, rgltr_min_volt, rgltr_max_volt); + if (rc) { + CAM_ERR(CAM_UTIL, "%s set voltage failed", rgltr_name); + return rc; + } + + rc = regulator_set_load(rgltr, rgltr_op_mode); + if (rc) { + CAM_ERR(CAM_UTIL, "%s set optimum mode failed", + rgltr_name); + return rc; + } + } + + rc = regulator_enable(rgltr); + if (rc) { + CAM_ERR(CAM_UTIL, "%s regulator_enable failed", rgltr_name); + return rc; + } + + if (rgltr_delay > 20) + msleep(rgltr_delay); + else if (rgltr_delay) + usleep_range(rgltr_delay * 1000, + (rgltr_delay * 1000) + 1000); + + return rc; +} + +static int cam_soc_util_request_pinctrl( + struct cam_hw_soc_info *soc_info) +{ + + struct cam_soc_pinctrl_info *device_pctrl = &soc_info->pinctrl_info; + struct device *dev = soc_info->dev; + + device_pctrl->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR_OR_NULL(device_pctrl->pinctrl)) { + CAM_DBG(CAM_UTIL, "Pinctrl not available"); + device_pctrl->pinctrl = NULL; + return 0; + } + device_pctrl->gpio_state_active = + pinctrl_lookup_state(device_pctrl->pinctrl, + CAM_SOC_PINCTRL_STATE_DEFAULT); + if (IS_ERR_OR_NULL(device_pctrl->gpio_state_active)) { + CAM_ERR(CAM_UTIL, + "Failed to get the active state pinctrl handle"); + device_pctrl->gpio_state_active = NULL; + return -EINVAL; + } + device_pctrl->gpio_state_suspend + = pinctrl_lookup_state(device_pctrl->pinctrl, + CAM_SOC_PINCTRL_STATE_SLEEP); + if (IS_ERR_OR_NULL(device_pctrl->gpio_state_suspend)) { + CAM_ERR(CAM_UTIL, + "Failed to get the suspend state pinctrl handle"); + device_pctrl->gpio_state_suspend = NULL; + return -EINVAL; + } + return 0; +} + +static void cam_soc_util_regulator_disable_default( + struct cam_hw_soc_info *soc_info) +{ + int j = 0; + uint32_t num_rgltr = soc_info->num_rgltr; + + for (j = num_rgltr-1; j >= 0; j--) { + if (soc_info->rgltr_ctrl_support == true) { + cam_soc_util_regulator_disable(soc_info->rgltr[j], + soc_info->rgltr_name[j], + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + soc_info->rgltr_op_mode[j], + soc_info->rgltr_delay[j]); + } else { + if (soc_info->rgltr[j]) + regulator_disable(soc_info->rgltr[j]); + } + } +} + +static int cam_soc_util_regulator_enable_default( + struct cam_hw_soc_info *soc_info) +{ + int j = 0, rc = 0; + uint32_t num_rgltr = soc_info->num_rgltr; + + for (j = 0; j < num_rgltr; j++) { + if (soc_info->rgltr_ctrl_support == true) { + rc = cam_soc_util_regulator_enable(soc_info->rgltr[j], + soc_info->rgltr_name[j], + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + soc_info->rgltr_op_mode[j], + soc_info->rgltr_delay[j]); + } else { + if (soc_info->rgltr[j]) + rc = regulator_enable(soc_info->rgltr[j]); + } + + if (rc) { + CAM_ERR(CAM_UTIL, "%s enable failed", + soc_info->rgltr_name[j]); + goto disable_rgltr; + } + } + + return rc; +disable_rgltr: + + for (j--; j >= 0; j--) { + if (soc_info->rgltr_ctrl_support == true) { + cam_soc_util_regulator_disable(soc_info->rgltr[j], + soc_info->rgltr_name[j], + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + soc_info->rgltr_op_mode[j], + soc_info->rgltr_delay[j]); + } else { + if (soc_info->rgltr[j]) + regulator_disable(soc_info->rgltr[j]); + } + } + + return rc; +} + +int cam_soc_util_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t handler, void *irq_data) +{ + int i = 0, rc = 0; + + if (!soc_info || !soc_info->dev) { + CAM_ERR(CAM_UTIL, "Invalid parameters"); + return -EINVAL; + } + + for (i = 0; i < soc_info->num_mem_block; i++) { + if (soc_info->reserve_mem) { + if (!request_mem_region(soc_info->mem_block[i]->start, + resource_size(soc_info->mem_block[i]), + soc_info->mem_block_name[i])){ + CAM_ERR(CAM_UTIL, + "Error Mem region request Failed:%s", + soc_info->mem_block_name[i]); + rc = -ENOMEM; + goto unmap_base; + } + } + soc_info->reg_map[i].mem_base = ioremap( + soc_info->mem_block[i]->start, + resource_size(soc_info->mem_block[i])); + if (!soc_info->reg_map[i].mem_base) { + CAM_ERR(CAM_UTIL, "i= %d base NULL", i); + rc = -ENOMEM; + goto unmap_base; + } + soc_info->reg_map[i].mem_cam_base = + soc_info->mem_block_cam_base[i]; + soc_info->reg_map[i].size = + resource_size(soc_info->mem_block[i]); + soc_info->num_reg_map++; + } + + for (i = 0; i < soc_info->num_rgltr; i++) { + if (soc_info->rgltr_name[i] == NULL) { + CAM_ERR(CAM_UTIL, "can't find regulator name"); + goto put_regulator; + } + + rc = cam_soc_util_get_regulator(soc_info->dev, + &soc_info->rgltr[i], + soc_info->rgltr_name[i]); + if (rc) + goto put_regulator; + } + + if (soc_info->irq_line) { + rc = devm_request_irq(soc_info->dev, soc_info->irq_line->start, + handler, IRQF_TRIGGER_RISING, + soc_info->irq_name, irq_data); + if (rc) { + CAM_ERR(CAM_UTIL, "irq request fail"); + rc = -EBUSY; + goto put_regulator; + } + disable_irq(soc_info->irq_line->start); + soc_info->irq_data = irq_data; + } + + /* Get Clock */ + for (i = 0; i < soc_info->num_clk; i++) { + soc_info->clk[i] = clk_get(soc_info->dev, + soc_info->clk_name[i]); + if (!soc_info->clk[i]) { + CAM_ERR(CAM_UTIL, "get failed for %s", + soc_info->clk_name[i]); + rc = -ENOENT; + goto put_clk; + } + } + + rc = cam_soc_util_request_pinctrl(soc_info); + if (rc) + CAM_DBG(CAM_UTIL, "Failed in request pinctrl, rc=%d", rc); + + rc = cam_soc_util_request_gpio_table(soc_info, true); + if (rc) { + CAM_ERR(CAM_UTIL, "Failed in request gpio table, rc=%d", rc); + goto put_clk; + } + + if (soc_info->clk_control_enable) + cam_soc_util_create_clk_lvl_debugfs(soc_info); + + return rc; + +put_clk: + if (i == -1) + i = soc_info->num_clk; + for (i = i - 1; i >= 0; i--) { + if (soc_info->clk[i]) { + clk_put(soc_info->clk[i]); + soc_info->clk[i] = NULL; + } + } + + if (soc_info->irq_line) { + disable_irq(soc_info->irq_line->start); + devm_free_irq(soc_info->dev, + soc_info->irq_line->start, irq_data); + } + +put_regulator: + if (i == -1) + i = soc_info->num_rgltr; + for (i = i - 1; i >= 0; i--) { + if (soc_info->rgltr[i]) { + regulator_disable(soc_info->rgltr[i]); + regulator_put(soc_info->rgltr[i]); + soc_info->rgltr[i] = NULL; + } + } + +unmap_base: + if (i == -1) + i = soc_info->num_reg_map; + for (i = i - 1; i >= 0; i--) { + if (soc_info->reserve_mem) + release_mem_region(soc_info->mem_block[i]->start, + resource_size(soc_info->mem_block[i])); + iounmap(soc_info->reg_map[i].mem_base); + soc_info->reg_map[i].mem_base = NULL; + soc_info->reg_map[i].size = 0; + } + + return rc; +} + +int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info) +{ + int i; + + if (!soc_info || !soc_info->dev) { + CAM_ERR(CAM_UTIL, "Invalid parameter"); + return -EINVAL; + } + + for (i = soc_info->num_clk - 1; i >= 0; i--) { + clk_put(soc_info->clk[i]); + soc_info->clk[i] = NULL; + } + + for (i = soc_info->num_rgltr - 1; i >= 0; i--) { + if (soc_info->rgltr[i]) { + regulator_put(soc_info->rgltr[i]); + soc_info->rgltr[i] = NULL; + } + } + + for (i = soc_info->num_reg_map - 1; i >= 0; i--) { + iounmap(soc_info->reg_map[i].mem_base); + soc_info->reg_map[i].mem_base = NULL; + soc_info->reg_map[i].size = 0; + } + + if (soc_info->irq_line) { + disable_irq(soc_info->irq_line->start); + devm_free_irq(soc_info->dev, + soc_info->irq_line->start, soc_info->irq_data); + } + + if (soc_info->pinctrl_info.pinctrl) + devm_pinctrl_put(soc_info->pinctrl_info.pinctrl); + + + /* release for gpio */ + cam_soc_util_request_gpio_table(soc_info, false); + + if (soc_info->clk_control_enable) + cam_soc_util_remove_clk_lvl_debugfs(soc_info); + + return 0; +} + +int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, + bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq) +{ + int rc = 0; + + if (!soc_info) + return -EINVAL; + + rc = cam_soc_util_regulator_enable_default(soc_info); + if (rc) { + CAM_ERR(CAM_UTIL, "Regulators enable failed"); + return rc; + } + + if (enable_clocks) { + rc = cam_soc_util_clk_enable_default(soc_info, clk_level); + if (rc) + goto disable_regulator; + } + + if (enable_irq) { + rc = cam_soc_util_irq_enable(soc_info); + if (rc) + goto disable_clk; + } + + if (soc_info->pinctrl_info.pinctrl && + soc_info->pinctrl_info.gpio_state_active) { + rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl, + soc_info->pinctrl_info.gpio_state_active); + + if (rc) + goto disable_irq; + } + + return rc; + +disable_irq: + if (enable_irq) + cam_soc_util_irq_disable(soc_info); + +disable_clk: + if (enable_clocks) + cam_soc_util_clk_disable_default(soc_info); + +disable_regulator: + cam_soc_util_regulator_disable_default(soc_info); + + + return rc; +} + +int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, + bool disable_clocks, bool disable_irq) +{ + int rc = 0; + + if (!soc_info) + return -EINVAL; + + if (disable_irq) + rc |= cam_soc_util_irq_disable(soc_info); + + if (disable_clocks) + cam_soc_util_clk_disable_default(soc_info); + + cam_soc_util_regulator_disable_default(soc_info); + + if (soc_info->pinctrl_info.pinctrl && + soc_info->pinctrl_info.gpio_state_suspend) + rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl, + soc_info->pinctrl_info.gpio_state_suspend); + + return rc; +} + +int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info, + uint32_t base_index, uint32_t offset, int size) +{ + void __iomem *base_addr = NULL; + + CAM_DBG(CAM_UTIL, "base_idx %u size=%d", base_index, size); + + if (!soc_info || base_index >= soc_info->num_reg_map || + size <= 0 || (offset + size) >= + CAM_SOC_GET_REG_MAP_SIZE(soc_info, base_index)) + return -EINVAL; + + base_addr = CAM_SOC_GET_REG_MAP_START(soc_info, base_index); + + /* + * All error checking already done above, + * hence ignoring the return value below. + */ + cam_io_dump(base_addr, offset, size); + + return 0; +} + +uint32_t cam_soc_util_get_vote_level(struct cam_hw_soc_info *soc_info, + uint64_t clock_rate) +{ + int i = 0; + + if (!clock_rate) + return CAM_SVS_VOTE; + + for (i = 0; i < CAM_MAX_VOTE; i++) { + if (soc_info->clk_level_valid[i] && + soc_info->clk_rate[i][soc_info->src_clk_idx] >= + clock_rate) { + CAM_DBG(CAM_UTIL, + "Clock rate %lld, selected clock level %d", + clock_rate, i); + return i; + } + } + + return CAM_TURBO_VOTE; +} diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h new file mode 100644 index 000000000000..bfa6183bf739 --- /dev/null +++ b/drivers/cam_utils/cam_soc_util.h @@ -0,0 +1,638 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SOC_UTIL_H_ +#define _CAM_SOC_UTIL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cam_io_util.h" + +#define NO_SET_RATE -1 +#define INIT_RATE -2 + +/* maximum number of device block */ +#define CAM_SOC_MAX_BLOCK 7 + +/* maximum number of device base */ +#define CAM_SOC_MAX_BASE CAM_SOC_MAX_BLOCK + +/* maximum number of device regulator */ +#define CAM_SOC_MAX_REGULATOR 5 + +/* maximum number of device clock */ +#define CAM_SOC_MAX_CLK 32 + +/* DDR device types */ +#define DDR_TYPE_LPDDR4 6 +#define DDR_TYPE_LPDDR4X 7 +#define DDR_TYPE_LPDDR5 8 +#define DDR_TYPE_LPDDR5X 9 + +/** + * enum cam_vote_level - Enum for voting level + * + * @CAM_SUSPEND_VOTE : Suspend vote + * @CAM_MINSVS_VOTE : Min SVS vote + * @CAM_LOWSVS_VOTE : Low SVS vote + * @CAM_SVS_VOTE : SVS vote + * @CAM_SVSL1_VOTE : SVS Plus vote + * @CAM_NOMINAL_VOTE : Nominal vote + * @CAM_NOMINALL1_VOTE: Nominal plus vote + * @CAM_TURBO_VOTE : Turbo vote + * @CAM_MAX_VOTE : Max voting level, This is invalid level. + */ +enum cam_vote_level { + CAM_SUSPEND_VOTE, + CAM_MINSVS_VOTE, + CAM_LOWSVS_VOTE, + CAM_SVS_VOTE, + CAM_SVSL1_VOTE, + CAM_NOMINAL_VOTE, + CAM_NOMINALL1_VOTE, + CAM_TURBO_VOTE, + CAM_MAX_VOTE, +}; + +/* pinctrl states */ +#define CAM_SOC_PINCTRL_STATE_SLEEP "cam_suspend" +#define CAM_SOC_PINCTRL_STATE_DEFAULT "cam_default" + +/** + * struct cam_soc_reg_map: Information about the mapped register space + * + * @mem_base: Starting location of MAPPED register space + * @mem_cam_base: Starting offset of this register space compared + * to ENTIRE Camera register space + * @size: Size of register space + **/ +struct cam_soc_reg_map { + void __iomem *mem_base; + uint32_t mem_cam_base; + resource_size_t size; +}; + +/** + * struct cam_soc_pinctrl_info: Information about pinctrl data + * + * @pinctrl: pintrl object + * @gpio_state_active: default pinctrl state + * @gpio_state_suspend suspend state of pinctrl + **/ +struct cam_soc_pinctrl_info { + struct pinctrl *pinctrl; + struct pinctrl_state *gpio_state_active; + struct pinctrl_state *gpio_state_suspend; +}; + +/** + * struct cam_soc_gpio_data: Information about the gpio pins + * + * @cam_gpio_common_tbl: It is list of al the gpios present in gpios node + * @cam_gpio_common_tbl_size: It is equal to number of gpios prsent in + * gpios node in DTSI + * @cam_gpio_req_tbl It is list of al the requesetd gpios + * @cam_gpio_req_tbl_size: It is size of requested gpios + **/ +struct cam_soc_gpio_data { + struct gpio *cam_gpio_common_tbl; + uint8_t cam_gpio_common_tbl_size; + struct gpio *cam_gpio_req_tbl; + uint8_t cam_gpio_req_tbl_size; +}; + +/** + * struct cam_hw_soc_info: Soc information pertaining to specific instance of + * Camera hardware driver module + * + * @pdev: Platform device pointer + * @device: Device pointer + * @hw_version: Camera device version + * @index: Instance id for the camera device + * @dev_name: Device Name + * @irq_name: Name of the irq associated with the device + * @irq_line: Irq resource + * @irq_data: Private data that is passed when IRQ is requested + * @compatible: Compatible string associated with the device + * @num_mem_block: Number of entry in the "reg-names" + * @mem_block_name: Array of the reg block name + * @mem_block_cam_base: Array of offset of this register space compared + * to ENTIRE Camera register space + * @mem_block: Associated resource structs + * @reg_map: Array of Mapped register info for the "reg-names" + * @num_reg_map: Number of mapped register space associated + * with mem_block. num_reg_map = num_mem_block in + * most cases + * @reserve_mem: Whether to reserve memory for Mem blocks + * @num_rgltr: Number of regulators + * @rgltr_name: Array of regulator names + * @rgltr_ctrl_support: Whether regulator control is supported + * @rgltr_min_volt: Array of minimum regulator voltage + * @rgltr_max_volt: Array of maximum regulator voltage + * @rgltr_op_mode: Array of regulator operation mode + * @rgltr_type: Array of regulator names + * @rgltr: Array of associated regulator resources + * @rgltr_delay: Array of regulator delay values + * @num_clk: Number of clocks + * @clk_name: Array of clock names + * @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 + * @pinctrl_info: Pointer to pinctrl info + * @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 { + struct platform_device *pdev; + struct device *dev; + uint32_t hw_version; + uint32_t index; + const char *dev_name; + const char *irq_name; + struct resource *irq_line; + void *irq_data; + const char *compatible; + + uint32_t num_mem_block; + const char *mem_block_name[CAM_SOC_MAX_BLOCK]; + uint32_t mem_block_cam_base[CAM_SOC_MAX_BLOCK]; + struct resource *mem_block[CAM_SOC_MAX_BLOCK]; + struct cam_soc_reg_map reg_map[CAM_SOC_MAX_BASE]; + uint32_t num_reg_map; + uint32_t reserve_mem; + + uint32_t num_rgltr; + const char *rgltr_name[CAM_SOC_MAX_REGULATOR]; + uint32_t rgltr_ctrl_support; + uint32_t rgltr_min_volt[CAM_SOC_MAX_REGULATOR]; + uint32_t rgltr_max_volt[CAM_SOC_MAX_REGULATOR]; + uint32_t rgltr_op_mode[CAM_SOC_MAX_REGULATOR]; + uint32_t rgltr_type[CAM_SOC_MAX_REGULATOR]; + struct regulator *rgltr[CAM_SOC_MAX_REGULATOR]; + uint32_t rgltr_delay[CAM_SOC_MAX_REGULATOR]; + + uint32_t use_shared_clk; + uint32_t num_clk; + 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]; + + struct cam_soc_gpio_data *gpio_data; + struct cam_soc_pinctrl_info pinctrl_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; +}; + +/* + * CAM_SOC_GET_REG_MAP_START + * + * @brief: This MACRO will get the mapped starting address + * where the register space can be accessed + * + * @__soc_info: Device soc information + * @__base_index: Index of register space in the HW block + * + * @return: Returns a pointer to the mapped register memory + */ +#define CAM_SOC_GET_REG_MAP_START(__soc_info, __base_index) \ + ((!__soc_info || __base_index >= __soc_info->num_reg_map) ? \ + NULL : __soc_info->reg_map[__base_index].mem_base) + +/* + * CAM_SOC_GET_REG_MAP_CAM_BASE + * + * @brief: This MACRO will get the cam_base of the + * register space + * + * @__soc_info: Device soc information + * @__base_index: Index of register space in the HW block + * + * @return: Returns an int32_t value. + * Failure: -1 + * Success: Starting offset of register space compared + * to entire Camera Register Map + */ +#define CAM_SOC_GET_REG_MAP_CAM_BASE(__soc_info, __base_index) \ + ((!__soc_info || __base_index >= __soc_info->num_reg_map) ? \ + -1 : __soc_info->reg_map[__base_index].mem_cam_base) + +/* + * CAM_SOC_GET_REG_MAP_SIZE + * + * @brief: This MACRO will get the size of the mapped + * register space + * + * @__soc_info: Device soc information + * @__base_index: Index of register space in the HW block + * + * @return: Returns a uint32_t value. + * Failure: 0 + * Success: Non-zero size of mapped register space + */ +#define CAM_SOC_GET_REG_MAP_SIZE(__soc_info, __base_index) \ + ((!__soc_info || __base_index >= __soc_info->num_reg_map) ? \ + 0 : __soc_info->reg_map[__base_index].size) + +/** + * cam_soc_util_get_level_from_string() + * + * @brief: Get the associated vote level for the input string + * + * @string: Input string to compare with. + * @level: Vote level corresponds to input string. + * + * @return: Success or failure + */ +int cam_soc_util_get_level_from_string(const char *string, + enum cam_vote_level *level); + +/** + * cam_soc_util_get_dt_properties() + * + * @brief: Parse the DT and populate the common properties that + * are part of the soc_info structure - register map, + * clocks, regulators, irq, etc. + * + * @soc_info: Device soc struct to be populated + * + * @return: Success or failure + */ +int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info); + +/** + * cam_soc_util_request_platform_resource() + * + * @brief: Request regulator, irq, and clock resources + * + * @soc_info: Device soc information + * @handler: Irq handler function pointer + * @irq_data: Irq handler function CB data + * + * @return: Success or failure + */ +int cam_soc_util_request_platform_resource(struct cam_hw_soc_info *soc_info, + irq_handler_t handler, void *irq_data); + +/** + * cam_soc_util_release_platform_resource() + * + * @brief: Release regulator, irq, and clock resources + * + * @soc_info: Device soc information + * + * @return: Success or failure + */ +int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info); + +/** + * cam_soc_util_enable_platform_resource() + * + * @brief: Enable regulator, irq resources + * + * @soc_info: Device soc information + * @enable_clocks: Boolean flag: + * TRUE: Enable all clocks in soc_info Now. + * False: Don't enable clocks Now. Driver will + * enable independently. + * @clk_level: Clock level to be applied. + * Applicable only if enable_clocks is true + * Valid range : 0 to (CAM_MAX_VOTE - 1) + * @enable_irq: Boolean flag: + * TRUE: Enable IRQ in soc_info Now. + * False: Don't enable IRQ Now. Driver will + * enable independently. + * + * @return: Success or failure + */ +int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info, + bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq); + +/** + * cam_soc_util_disable_platform_resource() + * + * @brief: Disable regulator, irq resources + * + * @soc_info: Device soc information + * @disable_irq: Boolean flag: + * TRUE: Disable IRQ in soc_info Now. + * False: Don't disable IRQ Now. Driver will + * disable independently. + * + * @return: Success or failure + */ +int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, + bool disable_clocks, bool disable_irq); + +/** + * cam_soc_util_get_clk_round_rate() + * + * @brief: Get the rounded clock rate for the given clock's + * clock rate value + * + * @soc_info: Device soc information + * @clk_index: Clock index in soc_info for which round rate is needed + * @clk_rate: Input clock rate for which rounded rate is needed + * + * @return: Rounded clock rate + */ +long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_index, unsigned long clk_rate); + +/** + * cam_soc_util_set_clk_flags() + * + * @brief: Camera SOC util to set the flags for a specified clock + * + * @soc_info: Device soc information + * @clk_index: Clock index in soc_info for which flags are to be set + * @flags: Flags to set + * + * @return: Success or Failure + */ +int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info, + uint32_t clk_index, unsigned long flags); + +/** + * cam_soc_util_set_src_clk_rate() + * + * @brief: Set the rate on the source clock. + * + * @soc_info: Device soc information + * @clk_rate: Clock rate associated with the src clk + * + * @return: success or failure + */ +int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, + int32_t clk_rate); + +/** + * cam_soc_util_get_option_clk_by_name() + * + * @brief: Get reference to optional clk using name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to find reference for + * @clk: Clock reference pointer to be filled if Success + * @clk_index: Clk index in the option clk array to be returned + * @clk_rate: Clk rate in the option clk array + * + * @return: 0: Success + * Negative: Failure + */ +int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info, + const char *clk_name, struct clk **clk, int32_t *clk_index, + int32_t *clk_rate); + +/** + * cam_soc_util_clk_put() + * + * @brief: Put clock specified in params + * + * @clk: Reference to the Clock that needs to be put + * + * @return: Success or failure + */ +int cam_soc_util_clk_put(struct clk **clk); + +/** + * cam_soc_util_clk_enable() + * + * @brief: Enable clock specified in params + * + * @clk: Clock that needs to be turned ON + * @clk_name: Clocks name associated with clk + * @clk_rate: Clocks rate associated with clk + * + * @return: Success or failure + */ +int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name, + int32_t clk_rate); + +/** + * cam_soc_util_set_clk_rate_level() + * + * @brief: Apply clock rates for the requested level. + * This applies the new requested level for all + * the clocks listed in DT based on their values. + * + * @soc_info: Device soc information + * @clk_level: Clock level number to set + * + * @return: Success or failure + */ +int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, + enum cam_vote_level clk_level); + +/** + * cam_soc_util_clk_disable() + * + * @brief: Disable clock specified in params + * + * @clk: Clock that needs to be turned OFF + * @clk_name: Clocks name associated with clk + * + * @return: Success or failure + */ +int cam_soc_util_clk_disable(struct clk *clk, const char *clk_name); + +/** + * cam_soc_util_irq_enable() + * + * @brief: Enable IRQ in SOC + * + * @soc_info: Device soc information + * + * @return: Success or failure + */ +int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info); + +/** + * cam_soc_util_irq_disable() + * + * @brief: Disable IRQ in SOC + * + * @soc_info: Device soc information + * + * @return: Success or failure + */ +int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info); + +/** + * cam_soc_util_regulator_enable() + * + * @brief: Enable single regulator + * + * @rgltr Regulator that needs to be turned ON + * @rgltr_name Associated Regulator name + * @rgltr_min_volt: Requested minimum volatage + * @rgltr_max_volt: Requested maximum volatage + * @rgltr_op_mode: Requested Load + * @rgltr_delay: Requested delay needed aaftre enabling regulator + * + * @return: Success or failure + */ +int cam_soc_util_regulator_enable(struct regulator *rgltr, + const char *rgltr_name, + uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, + uint32_t rgltr_op_mode, uint32_t rgltr_delay); + +/** + * cam_soc_util_regulator_enable() + * + * @brief: Disable single regulator + * + * @rgltr Regulator that needs to be turned ON + * @rgltr_name Associated Regulator name + * @rgltr_min_volt: Requested minimum volatage + * @rgltr_max_volt: Requested maximum volatage + * @rgltr_op_mode: Requested Load + * @rgltr_delay: Requested delay needed aaftre enabling regulator + * + * @return: Success or failure + */ +int cam_soc_util_regulator_disable(struct regulator *rgltr, + const char *rgltr_name, + uint32_t rgltr_min_volt, uint32_t rgltr_max_volt, + uint32_t rgltr_op_mode, uint32_t rgltr_delay); + + +/** + * cam_soc_util_w() + * + * @brief: Camera SOC util for register write + * + * @soc_info: Device soc information + * @base_index: Index of register space in the HW block + * @offset: Offset of register to be read + * @data: Value to be written + * + * @return: Success or Failure + */ +static inline int cam_soc_util_w(struct cam_hw_soc_info *soc_info, + uint32_t base_index, uint32_t offset, uint32_t data) +{ + if (!CAM_SOC_GET_REG_MAP_START(soc_info, base_index)) + return -EINVAL; + return cam_io_w(data, + CAM_SOC_GET_REG_MAP_START(soc_info, base_index) + offset); +} + +/** + * cam_soc_util_w_mb() + * + * @brief: Camera SOC util for register write with memory barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call wmb() independently in the caller. + * + * @soc_info: Device soc information + * @base_index: Index of register space in the HW block + * @offset: Offset of register to be read + * @data: Value to be written + * + * @return: Success or Failure + */ +static inline int cam_soc_util_w_mb(struct cam_hw_soc_info *soc_info, + uint32_t base_index, uint32_t offset, uint32_t data) +{ + if (!CAM_SOC_GET_REG_MAP_START(soc_info, base_index)) + return -EINVAL; + return cam_io_w_mb(data, + CAM_SOC_GET_REG_MAP_START(soc_info, base_index) + offset); +} + +/** + * cam_soc_util_r() + * + * @brief: Camera SOC util for register read + * + * @soc_info: Device soc information + * @base_index: Index of register space in the HW block + * @offset: Offset of register to be read + * + * @return: Value read from the register address + */ +static inline uint32_t cam_soc_util_r(struct cam_hw_soc_info *soc_info, + uint32_t base_index, uint32_t offset) +{ + if (!CAM_SOC_GET_REG_MAP_START(soc_info, base_index)) + return 0; + return cam_io_r( + CAM_SOC_GET_REG_MAP_START(soc_info, base_index) + offset); +} + +/** + * cam_soc_util_r_mb() + * + * @brief: Camera SOC util for register read with memory barrier. + * Memory Barrier is only before the write to ensure the + * order. If need to ensure this write is also flushed + * call rmb() independently in the caller. + * + * @soc_info: Device soc information + * @base_index: Index of register space in the HW block + * @offset: Offset of register to be read + * + * @return: Value read from the register address + */ +static inline uint32_t cam_soc_util_r_mb(struct cam_hw_soc_info *soc_info, + uint32_t base_index, uint32_t offset) +{ + if (!CAM_SOC_GET_REG_MAP_START(soc_info, base_index)) + return 0; + return cam_io_r_mb( + CAM_SOC_GET_REG_MAP_START(soc_info, base_index) + offset); +} + +/** + * cam_soc_util_reg_dump() + * + * @brief: Camera SOC util for dumping a range of register + * + * @soc_info: Device soc information + * @base_index: Index of register space in the HW block + * @offset: Start register offset for the dump + * @size: Size specifying the range for dump + * + * @return: Success or Failure + */ +int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info, + uint32_t base_index, uint32_t offset, int size); + +void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info); + +int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, + enum cam_vote_level clk_level); + +uint32_t cam_soc_util_get_vote_level(struct cam_hw_soc_info *soc_info, + uint64_t clock_rate); + +#endif /* _CAM_SOC_UTIL_H_ */ diff --git a/drivers/cam_utils/cam_trace.c b/drivers/cam_utils/cam_trace.c new file mode 100644 index 000000000000..d4a6c9279081 --- /dev/null +++ b/drivers/cam_utils/cam_trace.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +/* Instantiate tracepoints */ +#define CREATE_TRACE_POINTS +#include "cam_trace.h" diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h new file mode 100644 index 000000000000..95bc95da9e75 --- /dev/null +++ b/drivers/cam_utils/cam_trace.h @@ -0,0 +1,301 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#if !defined(_CAM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _CAM_TRACE_H + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM camera +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE ../../techpack/camera/drivers/cam_utils/cam_trace + +#include +#include +#include "cam_req_mgr_core.h" +#include "cam_req_mgr_interface.h" +#include "cam_context.h" + +TRACE_EVENT(cam_context_state, + TP_PROTO(const char *name, struct cam_context *ctx), + TP_ARGS(name, ctx), + TP_STRUCT__entry( + __field(void*, ctx) + __field(uint32_t, state) + __string(name, name) + ), + TP_fast_assign( + __entry->ctx = ctx; + __entry->state = ctx->state; + __assign_str(name, name); + ), + TP_printk( + "%s: State ctx=%p ctx_state=%u", + __get_str(name), __entry->ctx, __entry->state + ) +); + +TRACE_EVENT(cam_isp_activated_irq, + TP_PROTO(struct cam_context *ctx, unsigned int substate, + unsigned int event, uint64_t timestamp), + TP_ARGS(ctx, substate, event, timestamp), + TP_STRUCT__entry( + __field(void*, ctx) + __field(uint32_t, state) + __field(uint32_t, substate) + __field(uint32_t, event) + __field(uint64_t, ts) + ), + TP_fast_assign( + __entry->ctx = ctx; + __entry->state = ctx->state; + __entry->substate = substate; + __entry->event = event; + __entry->ts = timestamp; + ), + TP_printk( + "ISP: IRQ ctx=%p ctx_state=%u substate=%u event=%u ts=%llu", + __entry->ctx, __entry->state, __entry->substate, + __entry->event, __entry->ts + ) +); + +TRACE_EVENT(cam_icp_fw_dbg, + TP_PROTO(char *dbg_message, uint64_t timestamp), + TP_ARGS(dbg_message, timestamp), + TP_STRUCT__entry( + __string(dbg_message, dbg_message) + __field(uint64_t, timestamp) + ), + TP_fast_assign( + __assign_str(dbg_message, dbg_message); + __entry->timestamp = timestamp; + ), + TP_printk( + "%llu %s: ", + __entry->timestamp, __get_str(dbg_message) + ) +); + +TRACE_EVENT(cam_buf_done, + TP_PROTO(const char *ctx_type, struct cam_context *ctx, + struct cam_ctx_request *req), + TP_ARGS(ctx_type, ctx, req), + TP_STRUCT__entry( + __string(ctx_type, ctx_type) + __field(void*, ctx) + __field(uint64_t, request) + ), + TP_fast_assign( + __assign_str(ctx_type, ctx_type); + __entry->ctx = ctx; + __entry->request = req->request_id; + ), + TP_printk( + "%5s: BufDone ctx=%p request=%llu", + __get_str(ctx_type), __entry->ctx, __entry->request + ) +); + +TRACE_EVENT(cam_apply_req, + TP_PROTO(const char *entity, uint64_t req_id), + TP_ARGS(entity, req_id), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint64_t, req_id) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->req_id = req_id; + ), + TP_printk( + "%8s: ApplyRequest request=%llu", + __get_str(entity), __entry->req_id + ) +); + +TRACE_EVENT(cam_flush_req, + TP_PROTO(struct cam_req_mgr_core_link *link, + struct cam_req_mgr_flush_info *info), + TP_ARGS(link, info), + TP_STRUCT__entry( + __field(uint32_t, type) + __field(int64_t, req_id) + __field(void*, link) + __field(void*, session) + ), + TP_fast_assign( + __entry->type = info->flush_type; + __entry->req_id = info->req_id; + __entry->link = link; + __entry->session = link->parent; + ), + TP_printk( + "FlushRequest type=%u request=%llu link=%pK session=%pK", + __entry->type, __entry->req_id, __entry->link, + __entry->session + ) +); + +TRACE_EVENT(cam_req_mgr_connect_device, + TP_PROTO(struct cam_req_mgr_core_link *link, + struct cam_req_mgr_device_info *info), + TP_ARGS(link, info), + TP_STRUCT__entry( + __string(name, info->name) + __field(uint32_t, id) + __field(uint32_t, delay) + __field(void*, link) + __field(void*, session) + ), + TP_fast_assign( + __assign_str(name, info->name); + __entry->id = info->dev_id; + __entry->delay = info->p_delay; + __entry->link = link; + __entry->session = link->parent; + ), + TP_printk( + "ReqMgr Connect name=%s id=%u pd=%d link=%pK session=%pK", + __get_str(name), __entry->id, __entry->delay, + __entry->link, __entry->session + ) +); + +TRACE_EVENT(cam_req_mgr_apply_request, + TP_PROTO(struct cam_req_mgr_core_link *link, + struct cam_req_mgr_apply_request *req, + struct cam_req_mgr_connected_device *dev), + TP_ARGS(link, req, dev), + TP_STRUCT__entry( + __string(name, dev->dev_info.name) + __field(uint32_t, dev_id) + __field(uint64_t, req_id) + __field(void*, link) + __field(void*, session) + ), + TP_fast_assign( + __assign_str(name, dev->dev_info.name); + __entry->dev_id = dev->dev_info.dev_id; + __entry->req_id = req->request_id; + __entry->link = link; + __entry->session = link->parent; + ), + TP_printk( + "ReqMgr ApplyRequest devname=%s devid=%u request=%lld link=%pK session=%pK", + __get_str(name), __entry->dev_id, __entry->req_id, + __entry->link, __entry->session + ) +); + +TRACE_EVENT(cam_req_mgr_add_req, + TP_PROTO(struct cam_req_mgr_core_link *link, + int idx, struct cam_req_mgr_add_request *add_req, + struct cam_req_mgr_req_tbl *tbl, + struct cam_req_mgr_connected_device *dev), + TP_ARGS(link, idx, add_req, tbl, dev), + TP_STRUCT__entry( + __string(name, dev->dev_info.name) + __field(uint32_t, dev_id) + __field(uint64_t, req_id) + __field(uint32_t, slot_id) + __field(uint32_t, delay) + __field(uint32_t, readymap) + __field(uint32_t, devicemap) + __field(void*, link) + __field(void*, session) + ), + TP_fast_assign( + __assign_str(name, dev->dev_info.name); + __entry->dev_id = dev->dev_info.dev_id; + __entry->req_id = add_req->req_id; + __entry->slot_id = idx; + __entry->delay = tbl->pd; + __entry->readymap = tbl->slot[idx].req_ready_map; + __entry->devicemap = tbl->dev_mask; + __entry->link = link; + __entry->session = link->parent; + ), + TP_printk( + "ReqMgr AddRequest devname=%s devid=%d request=%lld slot=%d pd=%d readymap=%x devicemap=%d link=%pK session=%pK", + __get_str(name), __entry->dev_id, __entry->req_id, + __entry->slot_id, __entry->delay, __entry->readymap, + __entry->devicemap, __entry->link, __entry->session + ) +); + +TRACE_EVENT(cam_submit_to_hw, + TP_PROTO(const char *entity, uint64_t req_id), + TP_ARGS(entity, req_id), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint64_t, req_id) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->req_id = req_id; + ), + TP_printk( + "%8s: submit request=%llu", + __get_str(entity), __entry->req_id + ) +); + +TRACE_EVENT(cam_irq_activated, + TP_PROTO(const char *entity, uint32_t irq_type), + TP_ARGS(entity, irq_type), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint32_t, irq_type) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->irq_type = irq_type; + ), + TP_printk( + "%8s: got irq type=%d", + __get_str(entity), __entry->irq_type + ) +); + +TRACE_EVENT(cam_irq_handled, + TP_PROTO(const char *entity, uint32_t irq_type), + TP_ARGS(entity, irq_type), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint32_t, irq_type) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->irq_type = irq_type; + ), + TP_printk( + "%8s: handled irq type=%d", + __get_str(entity), __entry->irq_type + ) +); + +TRACE_EVENT(cam_cdm_cb, + TP_PROTO(const char *entity, uint32_t status), + TP_ARGS(entity, status), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint32_t, status) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->status = status; + ), + TP_printk( + "%8s: cdm cb status=%d", + __get_str(entity), __entry->status + ) +); + +#endif /* _CAM_TRACE_H */ + +/* This part must be outside protection */ +#include diff --git a/include/Kbuild b/include/Kbuild new file mode 100644 index 000000000000..bab1145bc7a7 --- /dev/null +++ b/include/Kbuild @@ -0,0 +1,2 @@ +# Top-level Makefile calls into asm-$(ARCH) +# List only non-arch directories below diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild new file mode 100644 index 000000000000..93dffc4bac8d --- /dev/null +++ b/include/uapi/Kbuild @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note + +header-y += media/ diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild new file mode 100644 index 000000000000..e7971dac1051 --- /dev/null +++ b/include/uapi/media/Kbuild @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note + +header-y += cam_cpas.h +header-y += cam_defs.h +header-y += cam_fd.h +header-y += cam_icp.h +header-y += cam_isp.h +header-y += cam_isp_vfe.h +header-y += cam_isp_ife.h +header-y += cam_jpeg.h +header-y += cam_req_mgr.h +header-y += cam_sensor.h +header-y += cam_sync.h +header-y += cam_lrme.h diff --git a/include/uapi/media/cam_cpas.h b/include/uapi/media/cam_cpas.h new file mode 100644 index 000000000000..a3d3ca9d5a71 --- /dev/null +++ b/include/uapi/media/cam_cpas.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_CPAS_H__ +#define __UAPI_CAM_CPAS_H__ + +#include "cam_defs.h" + +#define CAM_FAMILY_CAMERA_SS 1 +#define CAM_FAMILY_CPAS_SS 2 + +/* AXI BW Voting Version */ +#define CAM_AXI_BW_VOTING_V2 2 + +/* AXI BW Voting Transaction Type */ +#define CAM_AXI_TRANSACTION_READ 0 +#define CAM_AXI_TRANSACTION_WRITE 1 + +/* AXI BW Voting Path Data Type */ +#define CAM_AXI_PATH_DATA_IFE_START_OFFSET 0 +#define CAM_AXI_PATH_DATA_IFE_LINEAR (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 0) +#define CAM_AXI_PATH_DATA_IFE_VID (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 1) +#define CAM_AXI_PATH_DATA_IFE_DISP (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 2) +#define CAM_AXI_PATH_DATA_IFE_STATS (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 3) +#define CAM_AXI_PATH_DATA_IFE_RDI0 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 4) +#define CAM_AXI_PATH_DATA_IFE_RDI1 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 5) +#define CAM_AXI_PATH_DATA_IFE_RDI2 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 6) +#define CAM_AXI_PATH_DATA_IFE_RDI3 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 7) +#define CAM_AXI_PATH_DATA_IFE_PDAF (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 8) +#define CAM_AXI_PATH_DATA_IFE_PIXEL_RAW \ + (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 9) +#define CAM_AXI_PATH_DATA_IFE_MAX_OFFSET \ + (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 31) + +#define CAM_AXI_PATH_DATA_IPE_START_OFFSET 32 +#define CAM_AXI_PATH_DATA_IPE_RD_IN (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 0) +#define CAM_AXI_PATH_DATA_IPE_RD_REF (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 1) +#define CAM_AXI_PATH_DATA_IPE_WR_VID (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 2) +#define CAM_AXI_PATH_DATA_IPE_WR_DISP (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 3) +#define CAM_AXI_PATH_DATA_IPE_WR_REF (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 4) +#define CAM_AXI_PATH_DATA_IPE_MAX_OFFSET \ + (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 31) + +#define CAM_AXI_PATH_DATA_ALL 256 + +/** + * struct cam_cpas_query_cap - CPAS query device capability payload + * + * @camera_family : Camera family type + * @reserved : Reserved field for alignment + * @camera_version : Camera platform version + * @cpas_version : Camera CPAS version within camera platform + * + */ +struct cam_cpas_query_cap { + uint32_t camera_family; + uint32_t reserved; + struct cam_hw_version camera_version; + struct cam_hw_version cpas_version; +}; + +/** + * struct cam_axi_per_path_bw_vote - Per path bandwidth vote information + * + * @usage_data client usage data (left/right/rdi) + * @transac_type Transaction type on the path (read/write) + * @path_data_type Path for which vote is given (video, display, rdi) + * @reserved Reserved for alignment + * @camnoc_bw CAMNOC bw for this path + * @mnoc_ab_bw MNOC AB bw for this path + * @mnoc_ib_bw MNOC IB bw for this path + * @ddr_ab_bw DDR AB bw for this path + * @ddr_ib_bw DDR IB bw for this path + */ +struct cam_axi_per_path_bw_vote { + uint32_t usage_data; + uint32_t transac_type; + uint32_t path_data_type; + uint32_t reserved; + uint64_t camnoc_bw; + uint64_t mnoc_ab_bw; + uint64_t mnoc_ib_bw; + uint64_t ddr_ab_bw; + uint64_t ddr_ib_bw; +}; + +#endif /* __UAPI_CAM_CPAS_H__ */ diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h new file mode 100644 index 000000000000..8bc561314027 --- /dev/null +++ b/include/uapi/media/cam_defs.h @@ -0,0 +1,746 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_DEFS_H__ +#define __UAPI_CAM_DEFS_H__ + +#include +#include +#include + + +/* camera op codes */ +#define CAM_COMMON_OPCODE_BASE 0x100 +#define CAM_QUERY_CAP (CAM_COMMON_OPCODE_BASE + 0x1) +#define CAM_ACQUIRE_DEV (CAM_COMMON_OPCODE_BASE + 0x2) +#define CAM_START_DEV (CAM_COMMON_OPCODE_BASE + 0x3) +#define CAM_STOP_DEV (CAM_COMMON_OPCODE_BASE + 0x4) +#define CAM_CONFIG_DEV (CAM_COMMON_OPCODE_BASE + 0x5) +#define CAM_RELEASE_DEV (CAM_COMMON_OPCODE_BASE + 0x6) +#define CAM_SD_SHUTDOWN (CAM_COMMON_OPCODE_BASE + 0x7) +#define CAM_FLUSH_REQ (CAM_COMMON_OPCODE_BASE + 0x8) +#define CAM_COMMON_OPCODE_MAX (CAM_COMMON_OPCODE_BASE + 0x9) + +#define CAM_COMMON_OPCODE_BASE_v2 0x150 +#define CAM_ACQUIRE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x1) +#define CAM_RELEASE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x2) + +#define CAM_EXT_OPCODE_BASE 0x200 +#define CAM_CONFIG_DEV_EXTERNAL (CAM_EXT_OPCODE_BASE + 0x1) + +/* camera handle type */ +#define CAM_HANDLE_USER_POINTER 1 +#define CAM_HANDLE_MEM_HANDLE 2 + +/* Generic Blob CmdBuffer header properties */ +#define CAM_GENERIC_BLOB_CMDBUFFER_SIZE_MASK 0xFFFFFF00 +#define CAM_GENERIC_BLOB_CMDBUFFER_SIZE_SHIFT 8 +#define CAM_GENERIC_BLOB_CMDBUFFER_TYPE_MASK 0xFF +#define CAM_GENERIC_BLOB_CMDBUFFER_TYPE_SHIFT 0 + +/* Command Buffer Types */ +#define CAM_CMD_BUF_DMI 0x1 +#define CAM_CMD_BUF_DMI16 0x2 +#define CAM_CMD_BUF_DMI32 0x3 +#define CAM_CMD_BUF_DMI64 0x4 +#define CAM_CMD_BUF_DIRECT 0x5 +#define CAM_CMD_BUF_INDIRECT 0x6 +#define CAM_CMD_BUF_I2C 0x7 +#define CAM_CMD_BUF_FW 0x8 +#define CAM_CMD_BUF_GENERIC 0x9 +#define CAM_CMD_BUF_LEGACY 0xA + +/* UBWC API Version */ +#define CAM_UBWC_CFG_VERSION_1 1 +#define CAM_UBWC_CFG_VERSION_2 2 + +#define CAM_MAX_ACQ_RES 5 +#define CAM_MAX_HW_SPLIT 3 + + +/** + * enum flush_type_t - Identifies the various flush types + * + * @CAM_FLUSH_TYPE_REQ: Flush specific request + * @CAM_FLUSH_TYPE_ALL: Flush all requests belonging to a context + * @CAM_FLUSH_TYPE_MAX: Max enum to validate flush type + * + */ +enum flush_type_t { + CAM_FLUSH_TYPE_REQ, + CAM_FLUSH_TYPE_ALL, + CAM_FLUSH_TYPE_MAX +}; + +/** + * struct cam_control - Structure used by ioctl control for camera + * + * @op_code: This is the op code for camera control + * @size: Control command size + * @handle_type: User pointer or shared memory handle + * @reserved: Reserved field for 64 bit alignment + * @handle: Control command payload + */ +struct cam_control { + uint32_t op_code; + uint32_t size; + uint32_t handle_type; + uint32_t reserved; + uint64_t handle; +}; + +/* camera IOCTL */ +#define VIDIOC_CAM_CONTROL \ + _IOWR('V', BASE_VIDIOC_PRIVATE, struct cam_control) + +/** + * struct cam_hw_version - Structure for HW version of camera devices + * + * @major : Hardware version major + * @minor : Hardware version minor + * @incr : Hardware version increment + * @reserved : Reserved for 64 bit aligngment + */ +struct cam_hw_version { + uint32_t major; + uint32_t minor; + uint32_t incr; + uint32_t reserved; +}; + +/** + * struct cam_iommu_handle - Structure for IOMMU handles of camera hw devices + * + * @non_secure: Device Non Secure IOMMU handle + * @secure: Device Secure IOMMU handle + * + */ +struct cam_iommu_handle { + int32_t non_secure; + int32_t secure; +}; + +/* camera secure mode */ +#define CAM_SECURE_MODE_NON_SECURE 0 +#define CAM_SECURE_MODE_SECURE 1 + +/* Camera Format Type */ +#define CAM_FORMAT_BASE 0 +#define CAM_FORMAT_MIPI_RAW_6 1 +#define CAM_FORMAT_MIPI_RAW_8 2 +#define CAM_FORMAT_MIPI_RAW_10 3 +#define CAM_FORMAT_MIPI_RAW_12 4 +#define CAM_FORMAT_MIPI_RAW_14 5 +#define CAM_FORMAT_MIPI_RAW_16 6 +#define CAM_FORMAT_MIPI_RAW_20 7 +#define CAM_FORMAT_QTI_RAW_8 8 +#define CAM_FORMAT_QTI_RAW_10 9 +#define CAM_FORMAT_QTI_RAW_12 10 +#define CAM_FORMAT_QTI_RAW_14 11 +#define CAM_FORMAT_PLAIN8 12 +#define CAM_FORMAT_PLAIN16_8 13 +#define CAM_FORMAT_PLAIN16_10 14 +#define CAM_FORMAT_PLAIN16_12 15 +#define CAM_FORMAT_PLAIN16_14 16 +#define CAM_FORMAT_PLAIN16_16 17 +#define CAM_FORMAT_PLAIN32_20 18 +#define CAM_FORMAT_PLAIN64 19 +#define CAM_FORMAT_PLAIN128 20 +#define CAM_FORMAT_ARGB 21 +#define CAM_FORMAT_ARGB_10 22 +#define CAM_FORMAT_ARGB_12 23 +#define CAM_FORMAT_ARGB_14 24 +#define CAM_FORMAT_DPCM_10_6_10 25 +#define CAM_FORMAT_DPCM_10_8_10 26 +#define CAM_FORMAT_DPCM_12_6_12 27 +#define CAM_FORMAT_DPCM_12_8_12 28 +#define CAM_FORMAT_DPCM_14_8_14 29 +#define CAM_FORMAT_DPCM_14_10_14 30 +#define CAM_FORMAT_NV21 31 +#define CAM_FORMAT_NV12 32 +#define CAM_FORMAT_TP10 33 +#define CAM_FORMAT_YUV422 34 +#define CAM_FORMAT_PD8 35 +#define CAM_FORMAT_PD10 36 +#define CAM_FORMAT_UBWC_NV12 37 +#define CAM_FORMAT_UBWC_NV12_4R 38 +#define CAM_FORMAT_UBWC_TP10 39 +#define CAM_FORMAT_UBWC_P010 40 +#define CAM_FORMAT_PLAIN8_SWAP 41 +#define CAM_FORMAT_PLAIN8_10 42 +#define CAM_FORMAT_PLAIN8_10_SWAP 43 +#define CAM_FORMAT_YV12 44 +#define CAM_FORMAT_Y_ONLY 45 +#define CAM_FORMAT_DPCM_12_10_12 46 +#define CAM_FORMAT_PLAIN32 47 +#define CAM_FORMAT_ARGB_16 48 +#define CAM_FORMAT_MAX 49 + +/* camera rotaion */ +#define CAM_ROTATE_CW_0_DEGREE 0 +#define CAM_ROTATE_CW_90_DEGREE 1 +#define CAM_RORATE_CW_180_DEGREE 2 +#define CAM_ROTATE_CW_270_DEGREE 3 + +/* camera Color Space */ +#define CAM_COLOR_SPACE_BASE 0 +#define CAM_COLOR_SPACE_BT601_FULL 1 +#define CAM_COLOR_SPACE_BT601625 2 +#define CAM_COLOR_SPACE_BT601525 3 +#define CAM_COLOR_SPACE_BT709 4 +#define CAM_COLOR_SPACE_DEPTH 5 +#define CAM_COLOR_SPACE_MAX 6 + +/* camera buffer direction */ +#define CAM_BUF_INPUT 1 +#define CAM_BUF_OUTPUT 2 +#define CAM_BUF_IN_OUT 3 + +/* camera packet device Type */ +#define CAM_PACKET_DEV_BASE 0 +#define CAM_PACKET_DEV_IMG_SENSOR 1 +#define CAM_PACKET_DEV_ACTUATOR 2 +#define CAM_PACKET_DEV_COMPANION 3 +#define CAM_PACKET_DEV_EEPOM 4 +#define CAM_PACKET_DEV_CSIPHY 5 +#define CAM_PACKET_DEV_OIS 6 +#define CAM_PACKET_DEV_FLASH 7 +#define CAM_PACKET_DEV_FD 8 +#define CAM_PACKET_DEV_JPEG_ENC 9 +#define CAM_PACKET_DEV_JPEG_DEC 10 +#define CAM_PACKET_DEV_VFE 11 +#define CAM_PACKET_DEV_CPP 12 +#define CAM_PACKET_DEV_CSID 13 +#define CAM_PACKET_DEV_ISPIF 14 +#define CAM_PACKET_DEV_IFE 15 +#define CAM_PACKET_DEV_ICP 16 +#define CAM_PACKET_DEV_LRME 17 +#define CAM_PACKET_DEV_MAX 18 + + +/* constants */ +#define CAM_PACKET_MAX_PLANES 3 + +/** + * struct cam_plane_cfg - Plane configuration info + * + * @width: Plane width in pixels + * @height: Plane height in lines + * @plane_stride: Plane stride in pixel + * @slice_height: Slice height in line (not used by ISP) + * @meta_stride: UBWC metadata stride + * @meta_size: UBWC metadata plane size + * @meta_offset: UBWC metadata offset + * @packer_config: UBWC packer config + * @mode_config: UBWC mode config + * @tile_config: UBWC tile config + * @h_init: UBWC horizontal initial coordinate in pixels + * @v_init: UBWC vertical initial coordinate in lines + * + */ +struct cam_plane_cfg { + uint32_t width; + uint32_t height; + uint32_t plane_stride; + uint32_t slice_height; + uint32_t meta_stride; + uint32_t meta_size; + uint32_t meta_offset; + uint32_t packer_config; + uint32_t mode_config; + uint32_t tile_config; + uint32_t h_init; + uint32_t v_init; +}; + +/** + * struct cam_ubwc_plane_cfg_v1 - UBWC Plane configuration info + * + * @port_type: Port Type + * @meta_stride: UBWC metadata stride + * @meta_size: UBWC metadata plane size + * @meta_offset: UBWC metadata offset + * @packer_config: UBWC packer config + * @mode_config_0: UBWC mode config 0 + * @mode_config_1: UBWC 3 mode config 1 + * @tile_config: UBWC tile config + * @h_init: UBWC horizontal initial coordinate in pixels + * @v_init: UBWC vertical initial coordinate in lines + * + */ +struct cam_ubwc_plane_cfg_v1 { + uint32_t port_type; + uint32_t meta_stride; + uint32_t meta_size; + uint32_t meta_offset; + uint32_t packer_config; + uint32_t mode_config_0; + uint32_t mode_config_1; + uint32_t tile_config; + uint32_t h_init; + uint32_t v_init; +}; + +/** + * struct cam_ubwc_plane_cfg_v2 - UBWC Plane configuration info + * + * @port_type: Port Type + * @meta_stride: UBWC metadata stride + * @meta_size: UBWC metadata plane size + * @meta_offset: UBWC metadata offset + * @packer_config: UBWC packer config + * @mode_config: UBWC mode config + * @static ctrl: UBWC static ctrl + * @ctrl_2: UBWC ctrl 2 + * @tile_config: UBWC tile config + * @h_init: UBWC horizontal initial coordinate in pixels + * @v_init: UBWC vertical initial coordinate in lines + * @stats_ctrl_2: UBWC stats control + * @lossy_threshold0 UBWC lossy threshold 0 + * @lossy_threshold1 UBWC lossy threshold 1 + * @lossy_var_offset UBWC offset variance thrshold + * + */ +struct cam_ubwc_plane_cfg_v2 { + uint32_t port_type; + uint32_t meta_stride; + uint32_t meta_size; + uint32_t meta_offset; + uint32_t packer_config; + uint32_t mode_config_0; + uint32_t mode_config_1; + uint32_t tile_config; + uint32_t h_init; + uint32_t v_init; + uint32_t static_ctrl; + uint32_t ctrl_2; + uint32_t stats_ctrl_2; + uint32_t lossy_threshold_0; + uint32_t lossy_threshold_1; + uint32_t lossy_var_offset; + uint32_t bandwidth_limit; + uint32_t reserved[3]; +}; +/** + * struct cam_cmd_buf_desc - Command buffer descriptor + * + * @mem_handle: Command buffer handle + * @offset: Command start offset + * @size: Size of the command buffer in bytes + * @length: Used memory in command buffer in bytes + * @type: Type of the command buffer + * @meta_data: Data type for private command buffer + * Between UMD and KMD + * + */ +struct cam_cmd_buf_desc { + int32_t mem_handle; + uint32_t offset; + uint32_t size; + uint32_t length; + uint32_t type; + uint32_t meta_data; +}; + +/** + * struct cam_buf_io_cfg - Buffer io configuration for buffers + * + * @mem_handle: Mem_handle array for the buffers. + * @offsets: Offsets for each planes in the buffer + * @planes: Per plane information + * @width: Main plane width in pixel + * @height: Main plane height in lines + * @format: Format of the buffer + * @color_space: Color space for the buffer + * @color_pattern: Color pattern in the buffer + * @bpp: Bit per pixel + * @rotation: Rotation information for the buffer + * @resource_type: Resource type associated with the buffer + * @fence: Fence handle + * @early_fence: Fence handle for early signal + * @aux_cmd_buf: An auxiliary command buffer that may be + * used for programming the IO + * @direction: Direction of the config + * @batch_size: Batch size in HFR mode + * @subsample_pattern: Subsample pattern. Used in HFR mode. It + * should be consistent with batchSize and + * CAMIF programming. + * @subsample_period: Subsample period. Used in HFR mode. It + * should be consistent with batchSize and + * CAMIF programming. + * @framedrop_pattern: Framedrop pattern + * @framedrop_period: Framedrop period + * @flag: Flags for extra information + * @direction: Buffer direction: input or output + * @padding: Padding for the structure + * + */ +struct cam_buf_io_cfg { + int32_t mem_handle[CAM_PACKET_MAX_PLANES]; + uint32_t offsets[CAM_PACKET_MAX_PLANES]; + struct cam_plane_cfg planes[CAM_PACKET_MAX_PLANES]; + uint32_t format; + uint32_t color_space; + uint32_t color_pattern; + uint32_t bpp; + uint32_t rotation; + uint32_t resource_type; + int32_t fence; + int32_t early_fence; + struct cam_cmd_buf_desc aux_cmd_buf; + uint32_t direction; + uint32_t batch_size; + uint32_t subsample_pattern; + uint32_t subsample_period; + uint32_t framedrop_pattern; + uint32_t framedrop_period; + uint32_t flag; + uint32_t padding; +}; + +/** + * struct cam_packet_header - Camera packet header + * + * @op_code: Camera packet opcode + * @size: Size of the camera packet in bytes + * @request_id: Request id for this camera packet + * @flags: Flags for the camera packet + * @padding: Padding + * + */ +struct cam_packet_header { + uint32_t op_code; + uint32_t size; + uint64_t request_id; + uint32_t flags; + uint32_t padding; +}; + +/** + * struct cam_patch_desc - Patch structure + * + * @dst_buf_hdl: Memory handle for the dest buffer + * @dst_offset: Offset byte in the dest buffer + * @src_buf_hdl: Memory handle for the source buffer + * @src_offset: Offset byte in the source buffer + * + */ +struct cam_patch_desc { + int32_t dst_buf_hdl; + uint32_t dst_offset; + int32_t src_buf_hdl; + uint32_t src_offset; +}; + +/** + * struct cam_packet - Camera packet structure + * + * @header: Camera packet header + * @cmd_buf_offset: Command buffer start offset + * @num_cmd_buf: Number of the command buffer in the packet + * @io_config_offset: Buffer io configuration start offset + * @num_io_configs: Number of the buffer io configurations + * @patch_offset: Patch offset for the patch structure + * @num_patches: Number of the patch structure + * @kmd_cmd_buf_index: Command buffer index which contains extra + * space for the KMD buffer + * @kmd_cmd_buf_offset: Offset from the beginning of the command + * buffer for KMD usage. + * @payload: Camera packet payload + * + */ +struct cam_packet { + struct cam_packet_header header; + uint32_t cmd_buf_offset; + uint32_t num_cmd_buf; + uint32_t io_configs_offset; + uint32_t num_io_configs; + uint32_t patch_offset; + uint32_t num_patches; + uint32_t kmd_cmd_buf_index; + uint32_t kmd_cmd_buf_offset; + uint64_t payload[1]; + +}; + +/** + * struct cam_release_dev_cmd - Control payload for release devices + * + * @session_handle: Session handle for the release + * @dev_handle: Device handle for the release + */ +struct cam_release_dev_cmd { + int32_t session_handle; + int32_t dev_handle; +}; + +/** + * struct cam_start_stop_dev_cmd - Control payload for start/stop device + * + * @session_handle: Session handle for the start/stop command + * @dev_handle: Device handle for the start/stop command + * + */ +struct cam_start_stop_dev_cmd { + int32_t session_handle; + int32_t dev_handle; +}; + +/** + * struct cam_config_dev_cmd - Command payload for configure device + * + * @session_handle: Session handle for the command + * @dev_handle: Device handle for the command + * @offset: Offset byte in the packet handle. + * @packet_handle: Packet memory handle for the actual packet: + * struct cam_packet. + * + */ +struct cam_config_dev_cmd { + int32_t session_handle; + int32_t dev_handle; + uint64_t offset; + uint64_t packet_handle; +}; + +/** + * struct cam_query_cap_cmd - Payload for query device capability + * + * @size: Handle size + * @handle_type: User pointer or shared memory handle + * @caps_handle: Device specific query command payload + * + */ +struct cam_query_cap_cmd { + uint32_t size; + uint32_t handle_type; + uint64_t caps_handle; +}; + +/** + * struct cam_acquire_dev_cmd - Control payload for acquire devices + * + * @session_handle: Session handle for the acquire command + * @dev_handle: Device handle to be returned + * @handle_type: Resource handle type: + * 1 = user pointer, 2 = mem handle + * @num_resources: Number of the resources to be acquired + * @resources_hdl: Resource handle that refers to the actual + * resource array. Each item in this + * array is device specific resource structure + * + */ +struct cam_acquire_dev_cmd { + int32_t session_handle; + int32_t dev_handle; + uint32_t handle_type; + uint32_t num_resources; + uint64_t resource_hdl; +}; + +/* + * In old version, while acquiring device the num_resources in + * struct cam_acquire_dev_cmd will be a valid value. During ACQUIRE_DEV + * KMD driver will return dev_handle as well as associate HW to handle. + * If num_resources is set to the constant below, we are using + * the new version and we do not acquire HW in ACQUIRE_DEV IOCTL. + * ACQUIRE_DEV will only return handle and we should receive + * ACQUIRE_HW IOCTL after ACQUIRE_DEV and that is when the HW + * is associated with the dev_handle. + * + * (Data type): uint32_t + */ +#define CAM_API_COMPAT_CONSTANT 0xFEFEFEFE + +#define CAM_ACQUIRE_HW_STRUCT_VERSION_1 1 +#define CAM_ACQUIRE_HW_STRUCT_VERSION_2 2 + +/** + * struct cam_acquire_hw_cmd_v1 - Control payload for acquire HW IOCTL (Ver 1) + * + * @struct_version: = CAM_ACQUIRE_HW_STRUCT_VERSION_1 for this struct + * This value should be the first 32-bits in any structure + * related to this IOCTL. So that if the struct needs to + * change, we can first read the starting 32-bits, get the + * version number and then typecast the data to struct + * accordingly. + * @reserved: Reserved field for 64-bit alignment + * @session_handle: Session handle for the acquire command + * @dev_handle: Device handle to be returned + * @handle_type: Tells you how to interpret the variable resource_hdl- + * 1 = user pointer, 2 = mem handle + * @data_size: Total size of data contained in memory pointed + * to by resource_hdl + * @resource_hdl: Resource handle that refers to the actual + * resource data. + */ +struct cam_acquire_hw_cmd_v1 { + uint32_t struct_version; + uint32_t reserved; + int32_t session_handle; + int32_t dev_handle; + uint32_t handle_type; + uint32_t data_size; + uint64_t resource_hdl; +}; + +/** + * struct cam_acquired_hw_info - Update the acquired hardware info + * + * @acquired_hw_id: Acquired hardware mask + * @acquired_hw_path: Acquired path mask for an input + * if input splits into multiple paths, + * its updated per hardware + * valid_acquired_hw: Valid num of acquired hardware + */ +struct cam_acquired_hw_info { + uint32_t acquired_hw_id[CAM_MAX_ACQ_RES]; + uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; + uint32_t valid_acquired_hw; +}; + +/** + * struct cam_acquire_hw_cmd_v2 - Control payload for acquire HW IOCTL (Ver 2) + * + * @struct_version: = CAM_ACQUIRE_HW_STRUCT_VERSION_2 for this struct + * This value should be the first 32-bits in any structure + * related to this IOCTL. So that if the struct needs to + * change, we can first read the starting 32-bits, get the + * version number and then typecast the data to struct + * accordingly. + * @reserved: Reserved field for 64-bit alignment + * @session_handle: Session handle for the acquire command + * @dev_handle: Device handle to be returned + * @handle_type: Tells you how to interpret the variable resource_hdl- + * 1 = user pointer, 2 = mem handle + * @data_size: Total size of data contained in memory pointed + * to by resource_hdl + * @resource_hdl: Resource handle that refers to the actual + * resource data. + */ +struct cam_acquire_hw_cmd_v2 { + uint32_t struct_version; + uint32_t reserved; + int32_t session_handle; + int32_t dev_handle; + uint32_t handle_type; + uint32_t data_size; + uint64_t resource_hdl; + struct cam_acquired_hw_info hw_info; +}; + +#define CAM_RELEASE_HW_STRUCT_VERSION_1 1 + +/** + * struct cam_release_hw_cmd_v1 - Control payload for release HW IOCTL (Ver 1) + * + * @struct_version: = CAM_RELEASE_HW_STRUCT_VERSION_1 for this struct + * This value should be the first 32-bits in any structure + * related to this IOCTL. So that if the struct needs to + * change, we can first read the starting 32-bits, get the + * version number and then typecast the data to struct + * accordingly. + * @reserved: Reserved field for 64-bit alignment + * @session_handle: Session handle for the release + * @dev_handle: Device handle for the release + */ +struct cam_release_hw_cmd_v1 { + uint32_t struct_version; + uint32_t reserved; + int32_t session_handle; + int32_t dev_handle; +}; + +/** + * struct cam_flush_dev_cmd - Control payload for flush devices + * + * @version: Version + * @session_handle: Session handle for the acquire command + * @dev_handle: Device handle to be returned + * @flush_type: Flush type: + * 0 = flush specific request + * 1 = flush all + * @reserved: Reserved for 64 bit aligngment + * @req_id: Request id that needs to cancel + * + */ +struct cam_flush_dev_cmd { + uint64_t version; + int32_t session_handle; + int32_t dev_handle; + uint32_t flush_type; + uint32_t reserved; + int64_t req_id; +}; + +/** + * struct cam_ubwc_config - UBWC Configuration Payload + * + * @api_version: UBWC config api version + * @num_ports: Number of ports to be configured + * @ubwc_plane_config: Array of UBWC configurations per port + * Size [CAM_PACKET_MAX_PLANES - 1] per port + * as UBWC is supported on Y & C planes + * and therefore a max size of 2 planes + * + */ +struct cam_ubwc_config { + uint32_t api_version; + uint32_t num_ports; + struct cam_ubwc_plane_cfg_v1 + ubwc_plane_cfg[1][CAM_PACKET_MAX_PLANES - 1]; +}; + +/** + * struct cam_ubwc_config_v2 - UBWC Configuration Payload + * + * @api_version: UBWC config api version + * @num_ports: Number of ports to be configured + * @ubwc_plane_config: Array of UBWC configurations per port + * Size [CAM_PACKET_MAX_PLANES - 1] per port + * as UBWC is supported on Y & C planes + * and therefore a max size of 2 planes + * + */ +struct cam_ubwc_config_v2 { + uint32_t api_version; + uint32_t num_ports; + struct cam_ubwc_plane_cfg_v2 + ubwc_plane_cfg[1][CAM_PACKET_MAX_PLANES - 1]; +}; + +/** + * struct cam_cmd_mem_region_info - + * Cmd buffer region info + * + * @mem_handle : Memory handle of the region + * @offset : Offset if any + * @size : Size of the region + * @flags : Flags if any + */ +struct cam_cmd_mem_region_info { + int32_t mem_handle; + uint32_t offset; + uint32_t size; + uint32_t flags; +}; + +/** + * struct cam_cmd_mem_regions - + * List of multiple memory descriptors of + * of different regions + * + * @version : Version number + * @num_regions : Number of regions + * @map_info_array : Array of all the regions + */ +struct cam_cmd_mem_regions { + uint32_t version; + uint32_t num_regions; + struct cam_cmd_mem_region_info map_info_array[1]; +}; + + +#endif /* __UAPI_CAM_DEFS_H__ */ diff --git a/include/uapi/media/cam_fd.h b/include/uapi/media/cam_fd.h new file mode 100644 index 000000000000..f456683b3779 --- /dev/null +++ b/include/uapi/media/cam_fd.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_FD_H__ +#define __UAPI_CAM_FD_H__ + +#include "cam_defs.h" + +#define CAM_FD_MAX_FACES 35 +#define CAM_FD_RAW_RESULT_ENTRIES 512 + +/* FD Op Codes */ +#define CAM_PACKET_OPCODES_FD_FRAME_UPDATE 0x0 + +/* FD Command Buffer identifiers */ +#define CAM_FD_CMD_BUFFER_ID_GENERIC 0x0 +#define CAM_FD_CMD_BUFFER_ID_CDM 0x1 +#define CAM_FD_CMD_BUFFER_ID_MAX 0x2 + +/* FD Blob types */ +#define CAM_FD_BLOB_TYPE_SOC_CLOCK_BW_REQUEST 0x0 +#define CAM_FD_BLOB_TYPE_RAW_RESULTS_REQUIRED 0x1 + +/* FD Resource IDs */ +#define CAM_FD_INPUT_PORT_ID_IMAGE 0x0 +#define CAM_FD_INPUT_PORT_ID_MAX 0x1 + +#define CAM_FD_OUTPUT_PORT_ID_RESULTS 0x0 +#define CAM_FD_OUTPUT_PORT_ID_RAW_RESULTS 0x1 +#define CAM_FD_OUTPUT_PORT_ID_WORK_BUFFER 0x2 +#define CAM_FD_OUTPUT_PORT_ID_MAX 0x3 + +/** + * struct cam_fd_soc_clock_bw_request - SOC clock, bandwidth request info + * + * @clock_rate : Clock rate required while processing frame + * @bandwidth : Bandwidth required while processing frame + * @reserved : Reserved for future use + */ +struct cam_fd_soc_clock_bw_request { + uint64_t clock_rate; + uint64_t bandwidth; + uint64_t reserved[4]; +}; + +/** + * struct cam_fd_face - Face properties + * + * @prop1 : Property 1 of face + * @prop2 : Property 2 of face + * @prop3 : Property 3 of face + * @prop4 : Property 4 of face + * + * Do not change this layout, this is inline with how HW writes + * these values directly when the buffer is programmed to HW + */ +struct cam_fd_face { + uint32_t prop1; + uint32_t prop2; + uint32_t prop3; + uint32_t prop4; +}; + +/** + * struct cam_fd_results - FD results layout + * + * @faces : Array of faces with face properties + * @face_count : Number of faces detected + * @reserved : Reserved for alignment + * + * Do not change this layout, this is inline with how HW writes + * these values directly when the buffer is programmed to HW + */ +struct cam_fd_results { + struct cam_fd_face faces[CAM_FD_MAX_FACES]; + uint32_t face_count; + uint32_t reserved[3]; +}; + +/** + * struct cam_fd_hw_caps - Face properties + * + * @core_version : FD core version + * @wrapper_version : FD wrapper version + * @raw_results_available : Whether raw results are available on this HW + * @supported_modes : Modes supported by this HW. + * @reserved : Reserved for future use + */ +struct cam_fd_hw_caps { + struct cam_hw_version core_version; + struct cam_hw_version wrapper_version; + uint32_t raw_results_available; + uint32_t supported_modes; + uint64_t reserved; +}; + +/** + * struct cam_fd_query_cap_cmd - FD Query capabilities information + * + * @device_iommu : FD IOMMU handles + * @cdm_iommu : CDM iommu handles + * @hw_caps : FD HW capabilities + * @reserved : Reserved for alignment + */ +struct cam_fd_query_cap_cmd { + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + struct cam_fd_hw_caps hw_caps; + uint64_t reserved; +}; + +/** + * struct cam_fd_acquire_dev_info - FD acquire device information + * + * @clk_bw_request : SOC clock, bandwidth request + * @priority : Priority for this acquire + * @mode : Mode in which to run FD HW. + * @get_raw_results : Whether this acquire needs face raw results + * while frame processing + * @reserved : Reserved field for 64 bit alignment + */ +struct cam_fd_acquire_dev_info { + struct cam_fd_soc_clock_bw_request clk_bw_request; + uint32_t priority; + uint32_t mode; + uint32_t get_raw_results; + uint32_t reserved[13]; +}; + +#endif /* __UAPI_CAM_FD_H__ */ diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h new file mode 100644 index 000000000000..969de271e054 --- /dev/null +++ b/include/uapi/media/cam_icp.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_ICP_H__ +#define __UAPI_CAM_ICP_H__ + +#include "cam_defs.h" +#include "cam_cpas.h" + +/* icp, ipe, bps, cdm(ipe/bps) are used in querycap */ +#define CAM_ICP_DEV_TYPE_A5 1 +#define CAM_ICP_DEV_TYPE_IPE 2 +#define CAM_ICP_DEV_TYPE_BPS 3 +#define CAM_ICP_DEV_TYPE_IPE_CDM 4 +#define CAM_ICP_DEV_TYPE_BPS_CDM 5 +#define CAM_ICP_DEV_TYPE_MAX 5 + +/* definitions needed for icp aquire device */ +#define CAM_ICP_RES_TYPE_BPS 1 +#define CAM_ICP_RES_TYPE_IPE_RT 2 +#define CAM_ICP_RES_TYPE_IPE 3 +#define CAM_ICP_RES_TYPE_MAX 4 + +/* packet opcode types */ +#define CAM_ICP_OPCODE_IPE_UPDATE 0 +#define CAM_ICP_OPCODE_BPS_UPDATE 1 +#define CAM_ICP_OPCODE_IPE_SETTINGS 2 +#define CAM_ICP_OPCODE_BPS_SETTINGS 3 + + +/* IPE input port resource type */ +#define CAM_ICP_IPE_INPUT_IMAGE_FULL 0x0 +#define CAM_ICP_IPE_INPUT_IMAGE_DS4 0x1 +#define CAM_ICP_IPE_INPUT_IMAGE_DS16 0x2 +#define CAM_ICP_IPE_INPUT_IMAGE_DS64 0x3 +#define CAM_ICP_IPE_INPUT_IMAGE_FULL_REF 0x4 +#define CAM_ICP_IPE_INPUT_IMAGE_DS4_REF 0x5 +#define CAM_ICP_IPE_INPUT_IMAGE_DS16_REF 0x6 +#define CAM_ICP_IPE_INPUT_IMAGE_DS64_REF 0x7 + +/* IPE output port resource type */ +#define CAM_ICP_IPE_OUTPUT_IMAGE_DISPLAY 0x8 +#define CAM_ICP_IPE_OUTPUT_IMAGE_VIDEO 0x9 +#define CAM_ICP_IPE_OUTPUT_IMAGE_FULL_REF 0xA +#define CAM_ICP_IPE_OUTPUT_IMAGE_DS4_REF 0xB +#define CAM_ICP_IPE_OUTPUT_IMAGE_DS16_REF 0xC +#define CAM_ICP_IPE_OUTPUT_IMAGE_DS64_REF 0xD + +#define CAM_ICP_IPE_IMAGE_MAX 0xE + +/* BPS input port resource type */ +#define CAM_ICP_BPS_INPUT_IMAGE 0x0 + +/* BPS output port resource type */ +#define CAM_ICP_BPS_OUTPUT_IMAGE_FULL 0x1 +#define CAM_ICP_BPS_OUTPUT_IMAGE_DS4 0x2 +#define CAM_ICP_BPS_OUTPUT_IMAGE_DS16 0x3 +#define CAM_ICP_BPS_OUTPUT_IMAGE_DS64 0x4 +#define CAM_ICP_BPS_OUTPUT_IMAGE_STATS_BG 0x5 +#define CAM_ICP_BPS_OUTPUT_IMAGE_STATS_BHIST 0x6 +#define CAM_ICP_BPS_OUTPUT_IMAGE_REG1 0x7 +#define CAM_ICP_BPS_OUTPUT_IMAGE_REG2 0x8 + +#define CAM_ICP_BPS_IO_IMAGES_MAX 0x9 + +/* Command meta types */ +#define CAM_ICP_CMD_META_GENERIC_BLOB 0x1 + +/* Generic blob types */ +#define CAM_ICP_CMD_GENERIC_BLOB_CLK 0x1 +#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO 0x2 +#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_MAP 0x3 +#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_UNMAP 0x4 +#define CAM_ICP_CMD_GENERIC_BLOB_CLK_V2 0x5 + +/** + * struct cam_icp_clk_bw_request_v2 + * + * @budget_ns: Time required to process frame + * @frame_cycles: Frame cycles needed to process the frame + * @rt_flag: Flag to indicate real time stream + * @reserved: For memory alignment + * @num_paths: Number of axi paths in bw request + * @axi_path: Per path vote info for IPE/BPS + */ +struct cam_icp_clk_bw_request_v2 { + uint64_t budget_ns; + uint32_t frame_cycles; + uint32_t rt_flag; + uint32_t reserved; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[1]; +}; + +/** + * struct cam_icp_clk_bw_request + * + * @budget_ns: Time required to process frame + * @frame_cycles: Frame cycles needed to process the frame + * @rt_flag: Flag to indicate real time stream + * @uncompressed_bw: Bandwidth required to process frame + * @compressed_bw: Compressed bandwidth to process frame + */ +struct cam_icp_clk_bw_request { + uint64_t budget_ns; + uint32_t frame_cycles; + uint32_t rt_flag; + uint64_t uncompressed_bw; + uint64_t compressed_bw; +}; + +/** + * struct cam_icp_dev_ver - Device information for particular hw type + * + * This is used to get device version info of + * ICP, IPE, BPS and CDM related IPE and BPS from firmware + * and use this info in CAM_QUERY_CAP IOCTL + * + * @dev_type: hardware type for the cap info(icp, ipe, bps, cdm(ipe/bps)) + * @reserved: reserved field + * @hw_ver: major, minor and incr values of a device version + */ +struct cam_icp_dev_ver { + uint32_t dev_type; + uint32_t reserved; + struct cam_hw_version hw_ver; +}; + +/** + * struct cam_icp_ver - ICP version info + * + * This strcuture is used for fw and api version + * this is used to get firmware version and api version from firmware + * and use this info in CAM_QUERY_CAP IOCTL + * + * @major: FW version major + * @minor: FW version minor + * @revision: FW version increment + */ +struct cam_icp_ver { + uint32_t major; + uint32_t minor; + uint32_t revision; + uint32_t reserved; +}; + +/** + * struct cam_icp_query_cap_cmd - ICP query device capability payload + * + * @dev_iommu_handle: icp iommu handles for secure/non secure modes + * @cdm_iommu_handle: iommu handles for secure/non secure modes + * @fw_version: firmware version info + * @api_version: api version info + * @num_ipe: number of ipes + * @num_bps: number of bps + * @dev_ver: returned device capability array + */ +struct cam_icp_query_cap_cmd { + struct cam_iommu_handle dev_iommu_handle; + struct cam_iommu_handle cdm_iommu_handle; + struct cam_icp_ver fw_version; + struct cam_icp_ver api_version; + uint32_t num_ipe; + uint32_t num_bps; + struct cam_icp_dev_ver dev_ver[CAM_ICP_DEV_TYPE_MAX]; +}; + +/** + * struct cam_icp_res_info - ICP output resource info + * + * @format: format of the resource + * @width: width in pixels + * @height: height in lines + * @fps: fps + */ +struct cam_icp_res_info { + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t fps; +}; + +/** + * struct cam_icp_acquire_dev_info - An ICP device info + * + * @scratch_mem_size: Output param - size of scratch memory + * @dev_type: device type (IPE_RT/IPE_NON_RT/BPS) + * @io_config_cmd_size: size of IO config command + * @io_config_cmd_handle: IO config command for each acquire + * @secure_mode: camera mode (secure/non secure) + * @chain_info: chaining info of FW device handles + * @in_res: resource info used for clock and bandwidth calculation + * @num_out_res: number of output resources + * @out_res: output resource + */ +struct cam_icp_acquire_dev_info { + uint32_t scratch_mem_size; + uint32_t dev_type; + uint32_t io_config_cmd_size; + int32_t io_config_cmd_handle; + uint32_t secure_mode; + int32_t chain_info; + struct cam_icp_res_info in_res; + uint32_t num_out_res; + struct cam_icp_res_info out_res[1]; +} __attribute__((__packed__)); + +#endif /* __UAPI_CAM_ICP_H__ */ diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h new file mode 100644 index 000000000000..0191d2ced633 --- /dev/null +++ b/include/uapi/media/cam_isp.h @@ -0,0 +1,693 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_ISP_H__ +#define __UAPI_CAM_ISP_H__ + +#include "cam_defs.h" +#include "cam_isp_vfe.h" +#include "cam_isp_ife.h" +#include "cam_cpas.h" + +/* ISP driver name */ +#define CAM_ISP_DEV_NAME "cam-isp" + +/* HW type */ +#define CAM_ISP_HW_BASE 0 +#define CAM_ISP_HW_CSID 1 +#define CAM_ISP_HW_VFE 2 +#define CAM_ISP_HW_IFE 3 +#define CAM_ISP_HW_ISPIF 4 +#define CAM_ISP_HW_MAX 5 + +/* Color Pattern */ +#define CAM_ISP_PATTERN_BAYER_RGRGRG 0 +#define CAM_ISP_PATTERN_BAYER_GRGRGR 1 +#define CAM_ISP_PATTERN_BAYER_BGBGBG 2 +#define CAM_ISP_PATTERN_BAYER_GBGBGB 3 +#define CAM_ISP_PATTERN_YUV_YCBYCR 4 +#define CAM_ISP_PATTERN_YUV_YCRYCB 5 +#define CAM_ISP_PATTERN_YUV_CBYCRY 6 +#define CAM_ISP_PATTERN_YUV_CRYCBY 7 +#define CAM_ISP_PATTERN_MAX 8 + +/* Usage Type */ +#define CAM_ISP_RES_USAGE_SINGLE 0 +#define CAM_ISP_RES_USAGE_DUAL 1 +#define CAM_ISP_RES_USAGE_MAX 2 + +/* Resource ID */ +#define CAM_ISP_RES_ID_PORT 0 +#define CAM_ISP_RES_ID_CLK 1 +#define CAM_ISP_RES_ID_MAX 2 + +/* Resource Type - Type of resource for the resource id + * defined in cam_isp_vfe.h, cam_isp_ife.h + */ + +/* Lane Type in input resource for Port */ +#define CAM_ISP_LANE_TYPE_DPHY 0 +#define CAM_ISP_LANE_TYPE_CPHY 1 +#define CAM_ISP_LANE_TYPE_MAX 2 + +/* ISP Resurce Composite Group ID */ +#define CAM_ISP_RES_COMP_GROUP_NONE 0 +#define CAM_ISP_RES_COMP_GROUP_ID_0 1 +#define CAM_ISP_RES_COMP_GROUP_ID_1 2 +#define CAM_ISP_RES_COMP_GROUP_ID_2 3 +#define CAM_ISP_RES_COMP_GROUP_ID_3 4 +#define CAM_ISP_RES_COMP_GROUP_ID_4 5 +#define CAM_ISP_RES_COMP_GROUP_ID_5 6 +#define CAM_ISP_RES_COMP_GROUP_ID_MAX 6 + +/* ISP packet opcode for ISP */ +#define CAM_ISP_PACKET_OP_BASE 0 +#define CAM_ISP_PACKET_INIT_DEV 1 +#define CAM_ISP_PACKET_UPDATE_DEV 2 +#define CAM_ISP_PACKET_OP_MAX 3 + +/* ISP packet meta_data type for command buffer */ +#define CAM_ISP_PACKET_META_BASE 0 +#define CAM_ISP_PACKET_META_LEFT 1 +#define CAM_ISP_PACKET_META_RIGHT 2 +#define CAM_ISP_PACKET_META_COMMON 3 +#define CAM_ISP_PACKET_META_DMI_LEFT 4 +#define CAM_ISP_PACKET_META_DMI_RIGHT 5 +#define CAM_ISP_PACKET_META_DMI_COMMON 6 +#define CAM_ISP_PACKET_META_CLOCK 7 +#define CAM_ISP_PACKET_META_CSID 8 +#define CAM_ISP_PACKET_META_DUAL_CONFIG 9 +#define CAM_ISP_PACKET_META_GENERIC_BLOB_LEFT 10 +#define CAM_ISP_PACKET_META_GENERIC_BLOB_RIGHT 11 +#define CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON 12 + +/* DSP mode */ +#define CAM_ISP_DSP_MODE_NONE 0 +#define CAM_ISP_DSP_MODE_ONE_WAY 1 +#define CAM_ISP_DSP_MODE_ROUND 2 + +/* ISP Generic Cmd Buffer Blob types */ +#define CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG 0 +#define CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 +#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 +#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2 6 +#define CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG 7 +#define CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG 8 +#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 9 + +#define CAM_ISP_VC_DT_CFG 4 + +#define CAM_ISP_IFE0_HW 0x1 +#define CAM_ISP_IFE1_HW 0x2 +#define CAM_ISP_IFE0_LITE_HW 0x4 +#define CAM_ISP_IFE1_LITE_HW 0x8 +#define CAM_ISP_IFE2_LITE_HW 0x10 + +#define CAM_ISP_PXL_PATH 0x1 +#define CAM_ISP_PPP_PATH 0x2 +#define CAM_ISP_LCR_PATH 0x4 +#define CAM_ISP_RDI0_PATH 0x8 +#define CAM_ISP_RDI1_PATH 0x10 +#define CAM_ISP_RDI2_PATH 0x20 +#define CAM_ISP_RDI3_PATH 0x40 + +/* Per Path Usage Data */ +#define CAM_ISP_USAGE_INVALID 0 +#define CAM_ISP_USAGE_LEFT_PX 1 +#define CAM_ISP_USAGE_RIGHT_PX 2 +#define CAM_ISP_USAGE_RDI 3 + +/* Query devices */ +/** + * struct cam_isp_dev_cap_info - A cap info for particular hw type + * + * @hw_type: Hardware type for the cap info + * @reserved: reserved field for alignment + * @hw_version: Hardware version + * + */ +struct cam_isp_dev_cap_info { + uint32_t hw_type; + uint32_t reserved; + struct cam_hw_version hw_version; +}; + +/** + * struct cam_isp_query_cap_cmd - ISP query device capability payload + * + * @device_iommu: returned iommu handles for device + * @cdm_iommu: returned iommu handles for cdm + * @num_dev: returned number of device capabilities + * @reserved: reserved field for alignment + * @dev_caps: returned device capability array + * + */ +struct cam_isp_query_cap_cmd { + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + int32_t num_dev; + uint32_t reserved; + struct cam_isp_dev_cap_info dev_caps[CAM_ISP_HW_MAX]; +}; + +/* Acquire Device */ +/** + * struct cam_isp_out_port_info - An output port resource info + * + * @res_type: output resource type defined in file + * cam_isp_vfe.h or cam_isp_ife.h + * @format: output format of the resource + * @wdith: output width in pixels + * @height: output height in lines + * @comp_grp_id: composite group id for the resource. + * @split_point: split point in pixels for the dual VFE. + * @secure_mode: flag to tell if output should be run in secure + * mode or not. See cam_defs.h for definition + * @reserved: reserved field for alignment + * + */ +struct cam_isp_out_port_info { + uint32_t res_type; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t comp_grp_id; + uint32_t split_point; + uint32_t secure_mode; + uint32_t reserved; +}; + +/** + * struct cam_isp_out_port_info_v2 - An output port resource info + * + * @res_type: output resource type defined in file + * cam_isp_vfe.h or cam_isp_ife.h + * @format: output format of the resource + * @wdith: output width in pixels + * @height: output height in lines + * @comp_grp_id: composite group id for the resource. + * @split_point: split point in pixels for the dual VFE. + * @secure_mode: flag to tell if output should be run in secure + * mode or not. See cam_defs.h for definition + * @wm_mode: WM mode + * @out_port_res1: Output reserved field + * @out_port_res2: Output reserved field + * + */ +struct cam_isp_out_port_info_v2 { + uint32_t res_type; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t comp_grp_id; + uint32_t split_point; + uint32_t secure_mode; + uint32_t wm_mode; + uint32_t out_port_res1; + uint32_t out_port_res2; +}; + +/** + * struct cam_isp_in_port_info - An input port resource info + * + * @res_type: input resource type define in file + * cam_isp_vfe.h or cam_isp_ife.h + * @lane_type: lane type: c-phy or d-phy. + * @lane_num: active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * @vc: input virtual channel number + * @dt: input data type number + * @format: input format + * @test_pattern: test pattern for the testgen + * @usage_type: whether dual vfe is required + * @left_start: left input start offset in pixels + * @left_stop: left input stop offset in pixels + * @left_width: left input width in pixels + * @right_start: right input start offset in pixels. + * Only for Dual VFE + * @right_stop: right input stop offset in pixels. + * Only for Dual VFE + * @right_width: right input width in pixels. + * Only for dual VFE + * @line_start: top of the line number + * @line_stop: bottome of the line number + * @height: input height in lines + * @pixel_clk; sensor output clock + * @batch_size: batch size for HFR mode + * @dsp_mode: DSP stream mode (Defines as CAM_ISP_DSP_MODE_*) + * @hbi_cnt: HBI count for the camif input + * @reserved: Reserved field for alignment + * @num_out_res: number of the output resource associated + * @data: payload that contains the output resources + * + */ +struct cam_isp_in_port_info { + uint32_t res_type; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; + uint32_t vc; + uint32_t dt; + uint32_t format; + uint32_t test_pattern; + uint32_t usage_type; + uint32_t left_start; + uint32_t left_stop; + uint32_t left_width; + uint32_t right_start; + uint32_t right_stop; + uint32_t right_width; + uint32_t line_start; + uint32_t line_stop; + uint32_t height; + uint32_t pixel_clk; + uint32_t batch_size; + uint32_t dsp_mode; + uint32_t hbi_cnt; + uint32_t reserved; + uint32_t num_out_res; + struct cam_isp_out_port_info data[1]; +}; + +/** + * struct cam_isp_in_port_info_v2 - An input port resource info + * + * @res_type: input resource type define in file + * cam_isp_vfe.h or cam_isp_ife.h + * @lane_type: lane type: c-phy or d-phy. + * @lane_num: active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * @vc: input virtual channel number + * @dt: input data type number + * @num_valid_vc_dt: valid vc and dt in array + * @format: input format + * @test_pattern: test pattern for the testgen + * @usage_type: whether dual vfe is required + * @left_start: left input start offset in pixels + * @left_stop: left input stop offset in pixels + * @left_width: left input width in pixels + * @right_start: right input start offset in pixels. + * Only for Dual VFE + * @right_stop: right input stop offset in pixels. + * only for Dual VFE + * @right_width: right input width in pixels. + * only for dual VFE + * @line_start: top of the line number + * @line_stop: bottome of the line number + * @height: input height in lines + * @pixel_clk; sensor output clock + * @batch_size: batch size for HFR mode + * @dsp_mode: DSP stream mode (Defines as CAM_ISP_DSP_MODE_*) + * @hbi_cnt: HBI count for the camif input + * @cust_node: if any custom HW block is present before IFE + * @num_out_res: number of the output resource associated + * @horizontal_bin: Horizontal Binning info + * @qcfa_bin: Quadra Binning info + * @csid_res_1: payload for future use + * @csid_res_2: payload for future use + * @ife_res_1: payload for future use + * @ife_res_2: payload for future use + * @data: payload that contains the output resources + * + */ +struct cam_isp_in_port_info_v2 { + uint32_t res_type; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; + uint32_t vc[CAM_ISP_VC_DT_CFG]; + uint32_t dt[CAM_ISP_VC_DT_CFG]; + uint32_t num_valid_vc_dt; + uint32_t format; + uint32_t test_pattern; + uint32_t usage_type; + uint32_t left_start; + uint32_t left_stop; + uint32_t left_width; + uint32_t right_start; + uint32_t right_stop; + uint32_t right_width; + uint32_t line_start; + uint32_t line_stop; + uint32_t height; + uint32_t pixel_clk; + uint32_t batch_size; + uint32_t dsp_mode; + uint32_t hbi_cnt; + uint32_t cust_node; + uint32_t num_out_res; + uint32_t offline_mode; + uint32_t horizontal_bin; + uint32_t qcfa_bin; + uint32_t csid_res_1; + uint32_t csid_res_2; + uint32_t ife_res_1; + uint32_t ife_res_2; + struct cam_isp_out_port_info_v2 data[1]; +}; + +/** + * struct cam_isp_resource - A resource bundle + * + * @resoruce_id: resource id for the resource bundle + * @length: length of the while resource blob + * @handle_type: type of the resource handle + * @reserved: reserved field for alignment + * @res_hdl: resource handle that points to the + * resource array; + * + */ +struct cam_isp_resource { + uint32_t resource_id; + uint32_t length; + uint32_t handle_type; + uint32_t reserved; + uint64_t res_hdl; +}; + +/** + * struct cam_isp_port_hfr_config - HFR configuration for this port + * + * @resource_type: Resource type + * @subsample_pattern: Subsample pattern. Used in HFR mode. It + * should be consistent with batchSize and + * CAMIF programming. + * @subsample_period: Subsample period. Used in HFR mode. It + * should be consistent with batchSize and + * CAMIF programming. + * @framedrop_pattern: Framedrop pattern + * @framedrop_period: Framedrop period + * @reserved: Reserved for alignment + */ +struct cam_isp_port_hfr_config { + uint32_t resource_type; + uint32_t subsample_pattern; + uint32_t subsample_period; + uint32_t framedrop_pattern; + uint32_t framedrop_period; + uint32_t reserved; +} __attribute__((packed)); + +/** + * struct cam_isp_resource_hfr_config - Resource HFR configuration + * + * @num_ports: Number of ports + * @reserved: Reserved for alignment + * @port_hfr_config: HFR configuration for each IO port + */ +struct cam_isp_resource_hfr_config { + uint32_t num_ports; + uint32_t reserved; + struct cam_isp_port_hfr_config port_hfr_config[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_dual_split_params - dual isp spilt parameters + * + * @split_point: Split point information x, where (0 < x < width) + * left ISP's input ends at x + righ padding and + * Right ISP's input starts at x - left padding + * @right_padding: Padding added past the split point for left + * ISP's input + * @left_padding: Padding added before split point for right + * ISP's input + * @reserved: Reserved filed for alignment + * + */ +struct cam_isp_dual_split_params { + uint32_t split_point; + uint32_t right_padding; + uint32_t left_padding; + uint32_t reserved; +}; + +/** + * struct cam_isp_dual_stripe_config - stripe config per bus client + * + * @offset: Start horizontal offset relative to + * output buffer + * In UBWC mode, this value indicates the H_INIT + * value in pixel + * @width: Width of the stripe in bytes + * @tileconfig Ubwc meta tile config. Contain the partial + * tile info + * @port_id: port id of ISP output + * + */ +struct cam_isp_dual_stripe_config { + uint32_t offset; + uint32_t width; + uint32_t tileconfig; + uint32_t port_id; +}; + +/** + * struct cam_isp_dual_config - dual isp configuration + * + * @num_ports Number of isp output ports + * @reserved Reserved field for alignment + * @split_params: Inpput split parameters + * @stripes: Stripe information + * + */ +struct cam_isp_dual_config { + uint32_t num_ports; + uint32_t reserved; + struct cam_isp_dual_split_params split_params; + struct cam_isp_dual_stripe_config stripes[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_clock_config - Clock configuration + * + * @usage_type: Usage type (Single/Dual) + * @num_rdi: Number of RDI votes + * @left_pix_hz: Pixel Clock for Left ISP + * @right_pix_hz: Pixel Clock for Right ISP, valid only if Dual + * @rdi_hz: RDI Clock. ISP clock will be max of RDI and + * PIX clocks. For a particular context which ISP + * HW the RDI is allocated to is not known to UMD. + * Hence pass the clock and let KMD decide. + */ +struct cam_isp_clock_config { + uint32_t usage_type; + uint32_t num_rdi; + uint64_t left_pix_hz; + uint64_t right_pix_hz; + uint64_t rdi_hz[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_csid_clock_config - CSID clock configuration + * + * @csid_clock CSID clock + */ +struct cam_isp_csid_clock_config { + uint64_t csid_clock; +} __attribute__((packed)); + +/** + * struct cam_isp_bw_vote - Bandwidth vote information + * + * @resource_id: Resource ID + * @reserved: Reserved field for alignment + * @cam_bw_bps: Bandwidth vote for CAMNOC + * @ext_bw_bps: Bandwidth vote for path-to-DDR after CAMNOC + */ +struct cam_isp_bw_vote { + uint32_t resource_id; + uint32_t reserved; + uint64_t cam_bw_bps; + uint64_t ext_bw_bps; +} __attribute__((packed)); + +/** + * struct cam_isp_bw_config - Bandwidth configuration + * + * @usage_type: Usage type (Single/Dual) + * @num_rdi: Number of RDI votes + * @left_pix_vote: Bandwidth vote for left ISP + * @right_pix_vote: Bandwidth vote for right ISP + * @rdi_vote: RDI bandwidth requirements + */ +struct cam_isp_bw_config { + uint32_t usage_type; + uint32_t num_rdi; + struct cam_isp_bw_vote left_pix_vote; + struct cam_isp_bw_vote right_pix_vote; + struct cam_isp_bw_vote rdi_vote[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_bw_config_v2 - Bandwidth configuration + * + * @usage_type: Usage type (Single/Dual) + * @num_paths: Number of axi data paths + * @axi_path Per path vote info + */ +struct cam_isp_bw_config_v2 { + uint32_t usage_type; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[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)); + +/** + * struct cam_isp_core_config - ISP core registers configuration + * + * @version: Version info + * @vid_ds16_r2pd: Enables Y and C merging PD output for video DS16 + * @vid_ds4_r2pd: Enables Y and C merging PD output for video DS4 + * @disp_ds16_r2pd: Enables Y and C merging PD output for disp DS16 + * @disp_ds4_r2pd: Enables Y and C merging PD output for disp DS4 + * @dsp_streaming_tap_point: This selects source for DSP streaming interface + * @ihist_src_sel: Selects input for IHIST module + * @hdr_be_src_sel: Selects input for HDR BE module + * @hdr_bhist_src_sel: Selects input for HDR BHIST module + * @input_mux_sel_pdaf: Selects input for PDAF + * @input_mux_sel_pp: Selects input for Pixel Pipe + * @reserved: Reserved + */ +struct cam_isp_core_config { + uint32_t version; + uint32_t vid_ds16_r2pd; + uint32_t vid_ds4_r2pd; + uint32_t disp_ds16_r2pd; + uint32_t disp_ds4_r2pd; + uint32_t dsp_streaming_tap_point; + uint32_t ihist_src_sel; + uint32_t hdr_be_src_sel; + uint32_t hdr_bhist_src_sel; + uint32_t input_mux_sel_pdaf; + uint32_t input_mux_sel_pp; + uint32_t reserved; +} __attribute__((packed)); + +/** + * struct cam_isp_acquire_hw_info - ISP acquire HW params + * + * @common_info_version : Version of common info struct used + * @common_info_size : Size of common info struct used + * @common_info_offset : Offset of common info from start of data + * @num_inputs : Number of inputs + * @input_info_version : Version of input info struct used + * @input_info_size : Size of input info struct used + * @input_info_offset : Offset of input info from start of data + * @data : Start of data region + */ +struct cam_isp_acquire_hw_info { + uint16_t common_info_version; + uint16_t common_info_size; + uint32_t common_info_offset; + uint32_t num_inputs; + uint32_t input_info_version; + uint32_t input_info_size; + uint32_t input_info_offset; + uint64_t data; +}; + +/** + * struct cam_isp_vfe_wm_config - VFE write master config per port + * + * @port_type : Unique ID of output port + * @wm_mode : Write master mode + * 0x0 - Line based mode + * 0x1 - Frame based mode + * 0x2 - Index based mode, valid for BAF only + * @h_init : Horizontal starting coordinate in pixels. Must be a + * multiple of 3 for TP10 format + * @height : Height in pixels + * @width : Width in pixels + * @virtual_frame_en : Enabling virtual frame will prevent actual request from + * being sent to NOC + * @stride : Write master stride + * @offset : Write master offset + * @reserved_1 : Reserved field for Write master config + * @reserved_2 : Reserved field for Write master config + * @reserved_3 : Reserved field for Write master config + * @reserved_4 : Reserved field for Write master config + */ +struct cam_isp_vfe_wm_config { + uint32_t port_type; + uint32_t wm_mode; + uint32_t h_init; + uint32_t height; + uint32_t width; + uint32_t virtual_frame_en; + uint32_t stride; + uint32_t offset; + uint32_t reserved_1; + uint32_t reserved_2; + uint32_t reserved_3; + uint32_t reserved_4; +}; + +/** + * struct cam_isp_vfe_out_config - VFE write master config + * + * @num_ports : Number of ports + * @reserved : Reserved field + * @wm_config : VFE out config + */ +struct cam_isp_vfe_out_config { + uint32_t num_ports; + uint32_t reserved; + struct cam_isp_vfe_wm_config wm_config[1]; +}; + +#define CAM_ISP_ACQUIRE_COMMON_VER0 0x1000 + +#define CAM_ISP_ACQUIRE_COMMON_SIZE_VER0 0x0 + +#define CAM_ISP_ACQUIRE_INPUT_VER0 0x2000 + +#define CAM_ISP_ACQUIRE_INPUT_SIZE_VER0 sizeof(struct cam_isp_in_port_info) + +#define CAM_ISP_ACQUIRE_OUT_VER0 0x3000 + +#define CAM_ISP_ACQUIRE_OUT_SIZE_VER0 sizeof(struct cam_isp_out_port_info) + +#endif /* __UAPI_CAM_ISP_H__ */ diff --git a/include/uapi/media/cam_isp_ife.h b/include/uapi/media/cam_isp_ife.h new file mode 100644 index 000000000000..7ce826d94a78 --- /dev/null +++ b/include/uapi/media/cam_isp_ife.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_ISP_IFE_H__ +#define __UAPI_CAM_ISP_IFE_H__ + +/* IFE output port resource type (global unique)*/ +#define CAM_ISP_IFE_OUT_RES_BASE 0x3000 + +#define CAM_ISP_IFE_OUT_RES_FULL (CAM_ISP_IFE_OUT_RES_BASE + 0) +#define CAM_ISP_IFE_OUT_RES_DS4 (CAM_ISP_IFE_OUT_RES_BASE + 1) +#define CAM_ISP_IFE_OUT_RES_DS16 (CAM_ISP_IFE_OUT_RES_BASE + 2) +#define CAM_ISP_IFE_OUT_RES_RAW_DUMP (CAM_ISP_IFE_OUT_RES_BASE + 3) +#define CAM_ISP_IFE_OUT_RES_FD (CAM_ISP_IFE_OUT_RES_BASE + 4) +#define CAM_ISP_IFE_OUT_RES_PDAF (CAM_ISP_IFE_OUT_RES_BASE + 5) +#define CAM_ISP_IFE_OUT_RES_RDI_0 (CAM_ISP_IFE_OUT_RES_BASE + 6) +#define CAM_ISP_IFE_OUT_RES_RDI_1 (CAM_ISP_IFE_OUT_RES_BASE + 7) +#define CAM_ISP_IFE_OUT_RES_RDI_2 (CAM_ISP_IFE_OUT_RES_BASE + 8) +#define CAM_ISP_IFE_OUT_RES_RDI_3 (CAM_ISP_IFE_OUT_RES_BASE + 9) +#define CAM_ISP_IFE_OUT_RES_STATS_HDR_BE (CAM_ISP_IFE_OUT_RES_BASE + 10) +#define CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST (CAM_ISP_IFE_OUT_RES_BASE + 11) +#define CAM_ISP_IFE_OUT_RES_STATS_TL_BG (CAM_ISP_IFE_OUT_RES_BASE + 12) +#define CAM_ISP_IFE_OUT_RES_STATS_BF (CAM_ISP_IFE_OUT_RES_BASE + 13) +#define CAM_ISP_IFE_OUT_RES_STATS_AWB_BG (CAM_ISP_IFE_OUT_RES_BASE + 14) +#define CAM_ISP_IFE_OUT_RES_STATS_BHIST (CAM_ISP_IFE_OUT_RES_BASE + 15) +#define CAM_ISP_IFE_OUT_RES_STATS_RS (CAM_ISP_IFE_OUT_RES_BASE + 16) +#define CAM_ISP_IFE_OUT_RES_STATS_CS (CAM_ISP_IFE_OUT_RES_BASE + 17) +#define CAM_ISP_IFE_OUT_RES_STATS_IHIST (CAM_ISP_IFE_OUT_RES_BASE + 18) +#define CAM_ISP_IFE_OUT_RES_FULL_DISP (CAM_ISP_IFE_OUT_RES_BASE + 19) +#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_RDI_RD (CAM_ISP_IFE_OUT_RES_BASE + 23) +#define CAM_ISP_IFE_OUT_RES_LCR (CAM_ISP_IFE_OUT_RES_BASE + 24) + +#define CAM_ISP_IFE_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_BASE + 25) + + +/* IFE input port resource type (global unique) */ +#define CAM_ISP_IFE_IN_RES_BASE 0x4000 + +#define CAM_ISP_IFE_IN_RES_TPG (CAM_ISP_IFE_IN_RES_BASE + 0) +#define CAM_ISP_IFE_IN_RES_PHY_0 (CAM_ISP_IFE_IN_RES_BASE + 1) +#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_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_isp_vfe.h b/include/uapi/media/cam_isp_vfe.h new file mode 100644 index 000000000000..5f9ce7a49108 --- /dev/null +++ b/include/uapi/media/cam_isp_vfe.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_ISP_VFE_H__ +#define __UAPI_CAM_ISP_VFE_H__ + +/* VFE output port resource type (global unique) */ +#define CAM_ISP_VFE_OUT_RES_BASE 0x1000 + +#define CAM_ISP_VFE_OUT_RES_ENC (CAM_ISP_VFE_OUT_RES_BASE + 0) +#define CAM_ISP_VFE_OUT_RES_VIEW (CAM_ISP_VFE_OUT_RES_BASE + 1) +#define CAM_ISP_VFE_OUT_RES_VID (CAM_ISP_VFE_OUT_RES_BASE + 2) +#define CAM_ISP_VFE_OUT_RES_RDI_0 (CAM_ISP_VFE_OUT_RES_BASE + 3) +#define CAM_ISP_VFE_OUT_RES_RDI_1 (CAM_ISP_VFE_OUT_RES_BASE + 4) +#define CAM_ISP_VFE_OUT_RES_RDI_2 (CAM_ISP_VFE_OUT_RES_BASE + 5) +#define CAM_ISP_VFE_OUT_RES_RDI_3 (CAM_ISP_VFE_OUT_RES_BASE + 6) +#define CAM_ISP_VFE_OUT_RES_STATS_AEC (CAM_ISP_VFE_OUT_RES_BASE + 7) +#define CAM_ISP_VFE_OUT_RES_STATS_AF (CAM_ISP_VFE_OUT_RES_BASE + 8) +#define CAM_ISP_VFE_OUT_RES_STATS_AWB (CAM_ISP_VFE_OUT_RES_BASE + 9) +#define CAM_ISP_VFE_OUT_RES_STATS_RS (CAM_ISP_VFE_OUT_RES_BASE + 10) +#define CAM_ISP_VFE_OUT_RES_STATS_CS (CAM_ISP_VFE_OUT_RES_BASE + 11) +#define CAM_ISP_VFE_OUT_RES_STATS_IHIST (CAM_ISP_VFE_OUT_RES_BASE + 12) +#define CAM_ISP_VFE_OUT_RES_STATS_SKIN (CAM_ISP_VFE_OUT_RES_BASE + 13) +#define CAM_ISP_VFE_OUT_RES_STATS_BG (CAM_ISP_VFE_OUT_RES_BASE + 14) +#define CAM_ISP_VFE_OUT_RES_STATS_BF (CAM_ISP_VFE_OUT_RES_BASE + 15) +#define CAM_ISP_VFE_OUT_RES_STATS_BE (CAM_ISP_VFE_OUT_RES_BASE + 16) +#define CAM_ISP_VFE_OUT_RES_STATS_BHIST (CAM_ISP_VFE_OUT_RES_BASE + 17) +#define CAM_ISP_VFE_OUT_RES_STATS_BF_SCALE (CAM_ISP_VFE_OUT_RES_BASE + 18) +#define CAM_ISP_VFE_OUT_RES_STATS_HDR_BE (CAM_ISP_VFE_OUT_RES_BASE + 19) +#define CAM_ISP_VFE_OUT_RES_STATS_HDR_BHIST (CAM_ISP_VFE_OUT_RES_BASE + 20) +#define CAM_ISP_VFE_OUT_RES_STATS_AEC_BG (CAM_ISP_VFE_OUT_RES_BASE + 21) +#define CAM_ISP_VFE_OUT_RES_CAMIF_RAW (CAM_ISP_VFE_OUT_RES_BASE + 22) +#define CAM_ISP_VFE_OUT_RES_IDEAL_RAW (CAM_ISP_VFE_OUT_RES_BASE + 23) +#define CAM_ISP_VFE_OUT_RES_MAX (CAM_ISP_VFE_OUT_RES_BASE + 24) + +/* VFE input port_ resource type (global unique) */ +#define CAM_ISP_VFE_IN_RES_BASE 0x2000 + +#define CAM_ISP_VFE_IN_RES_TPG (CAM_ISP_VFE_IN_RES_BASE + 0) +#define CAM_ISP_VFE_IN_RES_PHY_0 (CAM_ISP_VFE_IN_RES_BASE + 1) +#define CAM_ISP_VFE_IN_RES_PHY_1 (CAM_ISP_VFE_IN_RES_BASE + 2) +#define CAM_ISP_VFE_IN_RES_PHY_2 (CAM_ISP_VFE_IN_RES_BASE + 3) +#define CAM_ISP_VFE_IN_RES_PHY_3 (CAM_ISP_VFE_IN_RES_BASE + 4) +#define CAM_ISP_VFE_IN_RES_FE (CAM_ISP_VFE_IN_RES_BASE + 5) +#define CAM_ISP_VFE_IN_RES_MAX (CAM_ISP_VFE_IN_RES_BASE + 6) + +#endif /* __UAPI_CAM_ISP_VFE_H__ */ diff --git a/include/uapi/media/cam_jpeg.h b/include/uapi/media/cam_jpeg.h new file mode 100644 index 000000000000..6513bbae740b --- /dev/null +++ b/include/uapi/media/cam_jpeg.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_JPEG_H__ +#define __UAPI_CAM_JPEG_H__ + +#include "cam_defs.h" + +/* enc, dma, cdm(enc/dma) are used in querycap */ +#define CAM_JPEG_DEV_TYPE_ENC 0 +#define CAM_JPEG_DEV_TYPE_DMA 1 +#define CAM_JPEG_DEV_TYPE_MAX 2 + +#define CAM_JPEG_NUM_DEV_PER_RES_MAX 1 + +/* definitions needed for jpeg aquire device */ +#define CAM_JPEG_RES_TYPE_ENC 0 +#define CAM_JPEG_RES_TYPE_DMA 1 +#define CAM_JPEG_RES_TYPE_MAX 2 + +/* packet opcode types */ +#define CAM_JPEG_OPCODE_ENC_UPDATE 0 +#define CAM_JPEG_OPCODE_DMA_UPDATE 1 + +/* ENC input port resource type */ +#define CAM_JPEG_ENC_INPUT_IMAGE 0x0 + +/* ENC output port resource type */ +#define CAM_JPEG_ENC_OUTPUT_IMAGE 0x1 + +#define CAM_JPEG_ENC_IO_IMAGES_MAX 0x2 + +/* DMA input port resource type */ +#define CAM_JPEG_DMA_INPUT_IMAGE 0x0 + +/* DMA output port resource type */ +#define CAM_JPEG_DMA_OUTPUT_IMAGE 0x1 + +#define CAM_JPEG_DMA_IO_IMAGES_MAX 0x2 + +#define CAM_JPEG_IMAGE_MAX 0x2 + +/** + * struct cam_jpeg_dev_ver - Device information for particular hw type + * + * This is used to get device version info of JPEG ENC, JPEG DMA + * from hardware and use this info in CAM_QUERY_CAP IOCTL + * + * @size : Size of struct passed + * @dev_type: Hardware type for the cap info(jpeg enc, jpeg dma) + * @hw_ver: Major, minor and incr values of a device version + */ +struct cam_jpeg_dev_ver { + uint32_t size; + uint32_t dev_type; + struct cam_hw_version hw_ver; +}; + +/** + * struct cam_jpeg_query_cap_cmd - JPEG query device capability payload + * + * @dev_iommu_handle: Jpeg iommu handles for secure/non secure + * modes + * @cdm_iommu_handle: Iommu handles for secure/non secure modes + * @num_enc: Number of encoder + * @num_dma: Number of dma + * @dev_ver: Returned device capability array + */ +struct cam_jpeg_query_cap_cmd { + struct cam_iommu_handle dev_iommu_handle; + struct cam_iommu_handle cdm_iommu_handle; + uint32_t num_enc; + uint32_t num_dma; + struct cam_jpeg_dev_ver dev_ver[CAM_JPEG_DEV_TYPE_MAX]; +}; + +/** + * struct cam_jpeg_res_info - JPEG output resource info + * + * @format: Format of the resource + * @width: Width in pixels + * @height: Height in lines + * @fps: Fps + */ +struct cam_jpeg_res_info { + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t fps; +}; + +/** + * struct cam_jpeg_acquire_dev_info - An JPEG device info + * + * @dev_type: Device type (ENC/DMA) + * @reserved: Reserved Bytes + * @in_res: In resource info + * @in_res: Iut resource info + */ +struct cam_jpeg_acquire_dev_info { + uint32_t dev_type; + uint32_t reserved; + struct cam_jpeg_res_info in_res; + struct cam_jpeg_res_info out_res; +}; + +/** + * struct cam_jpeg_config_inout_param_info - JPEG Config time + * input output params + * + * @clk_index: Input Param- clock selection index.(-1 default) + * @output_size: Output Param - jpeg encode/dma output size in + * bytes + */ +struct cam_jpeg_config_inout_param_info { + int32_t clk_index; + int32_t output_size; +}; + +#endif /* __UAPI_CAM_JPEG_H__ */ diff --git a/include/uapi/media/cam_lrme.h b/include/uapi/media/cam_lrme.h new file mode 100644 index 000000000000..90e3e76e0624 --- /dev/null +++ b/include/uapi/media/cam_lrme.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_LRME_H__ +#define __UAPI_CAM_LRME_H__ + +#include "cam_defs.h" + +/* LRME Resource Types */ + +enum CAM_LRME_IO_TYPE { + CAM_LRME_IO_TYPE_TAR, + CAM_LRME_IO_TYPE_REF, + CAM_LRME_IO_TYPE_RES, + CAM_LRME_IO_TYPE_DS2, +}; + +#define CAM_LRME_INPUT_PORT_TYPE_TAR (1 << 0) +#define CAM_LRME_INPUT_PORT_TYPE_REF (1 << 1) + +#define CAM_LRME_OUTPUT_PORT_TYPE_DS2 (1 << 0) +#define CAM_LRME_OUTPUT_PORT_TYPE_RES (1 << 1) + +#define CAM_LRME_DEV_MAX 1 + + +struct cam_lrme_hw_version { + uint32_t gen; + uint32_t rev; + uint32_t step; +}; + +struct cam_lrme_dev_cap { + struct cam_lrme_hw_version clc_hw_version; + struct cam_lrme_hw_version bus_rd_hw_version; + struct cam_lrme_hw_version bus_wr_hw_version; + struct cam_lrme_hw_version top_hw_version; + struct cam_lrme_hw_version top_titan_version; +}; + +/** + * struct cam_lrme_query_cap_cmd - LRME query device capability payload + * + * @dev_iommu_handle: LRME iommu handles for secure/non secure + * modes + * @cdm_iommu_handle: Iommu handles for secure/non secure modes + * @num_devices: number of hardware devices + * @dev_caps: Returned device capability array + */ +struct cam_lrme_query_cap_cmd { + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + uint32_t num_devices; + struct cam_lrme_dev_cap dev_caps[CAM_LRME_DEV_MAX]; +}; + +struct cam_lrme_soc_info { + uint64_t clock_rate; + uint64_t bandwidth; + uint64_t reserved[4]; +}; + +struct cam_lrme_acquire_args { + struct cam_lrme_soc_info lrme_soc_info; +}; + +#endif /* __UAPI_CAM_LRME_H__ */ diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h new file mode 100644 index 000000000000..f495eb883fcd --- /dev/null +++ b/include/uapi/media/cam_req_mgr.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_LINUX_CAM_REQ_MGR_H +#define __UAPI_LINUX_CAM_REQ_MGR_H + +#include +#include +#include +#include +#include "cam_defs.h" + +#define CAM_REQ_MGR_VNODE_NAME "cam-req-mgr-devnode" + +#define CAM_DEVICE_TYPE_BASE (MEDIA_ENT_F_OLD_BASE) +#define CAM_VNODE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE) +#define CAM_SENSOR_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 1) +#define CAM_IFE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 2) +#define CAM_ICP_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 3) +#define CAM_LRME_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 4) +#define CAM_JPEG_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 5) +#define CAM_FD_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 6) +#define CAM_CPAS_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 7) +#define CAM_CSIPHY_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 8) +#define CAM_ACTUATOR_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 9) +#define CAM_CCI_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 10) +#define CAM_FLASH_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 11) +#define CAM_EEPROM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 12) +#define CAM_OIS_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 13) + +/* cam_req_mgr hdl info */ +#define CAM_REQ_MGR_HDL_IDX_POS 8 +#define CAM_REQ_MGR_HDL_IDX_MASK ((1 << CAM_REQ_MGR_HDL_IDX_POS) - 1) +#define CAM_REQ_MGR_GET_HDL_IDX(hdl) (hdl & CAM_REQ_MGR_HDL_IDX_MASK) + +/** + * Max handles supported by cam_req_mgr + * It includes both session and device handles + */ +#define CAM_REQ_MGR_MAX_HANDLES 64 +#define MAX_LINKS_PER_SESSION 2 + +/* V4L event type which user space will subscribe to */ +#define V4L_EVENT_CAM_REQ_MGR_EVENT (V4L2_EVENT_PRIVATE_START + 0) + +/* Specific event ids to get notified in user space */ +#define V4L_EVENT_CAM_REQ_MGR_SOF 0 +#define V4L_EVENT_CAM_REQ_MGR_ERROR 1 +#define V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS 2 + +/* SOF Event status */ +#define CAM_REQ_MGR_SOF_EVENT_SUCCESS 0 +#define CAM_REQ_MGR_SOF_EVENT_ERROR 1 + +/* Link control operations */ +#define CAM_REQ_MGR_LINK_ACTIVATE 0 +#define CAM_REQ_MGR_LINK_DEACTIVATE 1 + +/** + * Request Manager : flush_type + * @CAM_REQ_MGR_FLUSH_TYPE_ALL: Req mgr will remove all the pending + * requests from input/processing queue. + * @CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ: Req mgr will remove only particular + * request id from input/processing queue. + * @CAM_REQ_MGR_FLUSH_TYPE_MAX: Max number of the flush type + * @opcode: CAM_REQ_MGR_FLUSH_REQ + */ +#define CAM_REQ_MGR_FLUSH_TYPE_ALL 0 +#define CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ 1 +#define CAM_REQ_MGR_FLUSH_TYPE_MAX 2 + +/** + * Request Manager : Sync Mode type + * @CAM_REQ_MGR_SYNC_MODE_NO_SYNC: Req mgr will apply non-sync mode for this + * request. + * @CAM_REQ_MGR_SYNC_MODE_SYNC: Req mgr will apply sync mode for this request. + */ +#define CAM_REQ_MGR_SYNC_MODE_NO_SYNC 0 +#define CAM_REQ_MGR_SYNC_MODE_SYNC 1 + +/** + * struct cam_req_mgr_event_data + * @session_hdl: session handle + * @link_hdl: link handle + * @frame_id: frame id + * @reserved: reserved for 64 bit aligngment + * @req_id: request id + * @tv_sec: timestamp in seconds + * @tv_usec: timestamp in micro seconds + */ +struct cam_req_mgr_event_data { + int32_t session_hdl; + int32_t link_hdl; + int32_t frame_id; + int32_t reserved; + int64_t req_id; + uint64_t tv_sec; + uint64_t tv_usec; +}; + +/** + * struct cam_req_mgr_session_info + * @session_hdl: In/Output param - session_handle + * @opcode1: CAM_REQ_MGR_CREATE_SESSION + * @opcode2: CAM_REQ_MGR_DESTROY_SESSION + */ +struct cam_req_mgr_session_info { + int32_t session_hdl; + int32_t reserved; +}; + +/** + * struct cam_req_mgr_link_info + * @session_hdl: Input param - Identifier for CSL session + * @num_devices: Input Param - Num of devices to be linked + * @dev_hdls: Input param - List of device handles to be linked + * @link_hdl: Output Param -Identifier for link + * @opcode: CAM_REQ_MGR_LINK + */ +struct cam_req_mgr_link_info { + int32_t session_hdl; + uint32_t num_devices; + int32_t dev_hdls[CAM_REQ_MGR_MAX_HANDLES]; + int32_t link_hdl; +}; + +/** + * struct cam_req_mgr_unlink_info + * @session_hdl: input param - session handle + * @link_hdl: input param - link handle + * @opcode: CAM_REQ_MGR_UNLINK + */ +struct cam_req_mgr_unlink_info { + int32_t session_hdl; + int32_t link_hdl; +}; + +/** + * struct cam_req_mgr_flush_info + * @brief: User can tell drivers to flush a particular request id or + * flush all requests from its pending processing queue. Flush is a + * blocking call and driver shall ensure all requests are flushed + * before returning. + * @session_hdl: Input param - Identifier for CSL session + * @link_hdl: Input Param -Identifier for link + * @flush_type: User can cancel a particular req id or can flush + * all requests in queue + * @reserved: reserved for 64 bit aligngment + * @req_id: field is valid only if flush type is cancel request + * for flush all this field value is not considered. + * @opcode: CAM_REQ_MGR_FLUSH_REQ + */ +struct cam_req_mgr_flush_info { + int32_t session_hdl; + int32_t link_hdl; + uint32_t flush_type; + uint32_t reserved; + int64_t req_id; +}; + +/** struct cam_req_mgr_sched_info + * @session_hdl: Input param - Identifier for CSL session + * @link_hdl: Input Param -Identifier for link + * inluding itself. + * @bubble_enable: Input Param - Cam req mgr will do bubble recovery if this + * flag is set. + * @sync_mode: Type of Sync mode for this request + * @req_id: Input Param - Request Id from which all requests will be flushed + */ +struct cam_req_mgr_sched_request { + int32_t session_hdl; + int32_t link_hdl; + int32_t bubble_enable; + int32_t sync_mode; + int64_t req_id; +}; + +/** + * struct cam_req_mgr_sync_mode + * @session_hdl: Input param - Identifier for CSL session + * @sync_mode: Input Param - Type of sync mode + * @num_links: Input Param - Num of links in sync mode (Valid only + * when sync_mode is one of SYNC enabled modes) + * @link_hdls: Input Param - Array of link handles to be in sync mode + * (Valid only when sync_mode is one of SYNC + * enabled modes) + * @master_link_hdl: Input Param - To dictate which link's SOF drives system + * (Valid only when sync_mode is one of SYNC + * enabled modes) + * + * @opcode: CAM_REQ_MGR_SYNC_MODE + */ +struct cam_req_mgr_sync_mode { + int32_t session_hdl; + int32_t sync_mode; + int32_t num_links; + int32_t link_hdls[MAX_LINKS_PER_SESSION]; + int32_t master_link_hdl; + int32_t reserved; +}; + +/** + * struct cam_req_mgr_link_control + * @ops: Link operations: activate/deactive + * @session_hdl: Input param - Identifier for CSL session + * @num_links: Input Param - Num of links + * @reserved: reserved field + * @link_hdls: Input Param - Links to be activated/deactivated + * + * @opcode: CAM_REQ_MGR_LINK_CONTROL + */ +struct cam_req_mgr_link_control { + int32_t ops; + int32_t session_hdl; + int32_t num_links; + int32_t reserved; + int32_t link_hdls[MAX_LINKS_PER_SESSION]; +}; + +/** + * cam_req_mgr specific opcode ids + */ +#define CAM_REQ_MGR_CREATE_DEV_NODES (CAM_COMMON_OPCODE_MAX + 1) +#define CAM_REQ_MGR_CREATE_SESSION (CAM_COMMON_OPCODE_MAX + 2) +#define CAM_REQ_MGR_DESTROY_SESSION (CAM_COMMON_OPCODE_MAX + 3) +#define CAM_REQ_MGR_LINK (CAM_COMMON_OPCODE_MAX + 4) +#define CAM_REQ_MGR_UNLINK (CAM_COMMON_OPCODE_MAX + 5) +#define CAM_REQ_MGR_SCHED_REQ (CAM_COMMON_OPCODE_MAX + 6) +#define CAM_REQ_MGR_FLUSH_REQ (CAM_COMMON_OPCODE_MAX + 7) +#define CAM_REQ_MGR_SYNC_MODE (CAM_COMMON_OPCODE_MAX + 8) +#define CAM_REQ_MGR_ALLOC_BUF (CAM_COMMON_OPCODE_MAX + 9) +#define CAM_REQ_MGR_MAP_BUF (CAM_COMMON_OPCODE_MAX + 10) +#define CAM_REQ_MGR_RELEASE_BUF (CAM_COMMON_OPCODE_MAX + 11) +#define CAM_REQ_MGR_CACHE_OPS (CAM_COMMON_OPCODE_MAX + 12) +#define CAM_REQ_MGR_LINK_CONTROL (CAM_COMMON_OPCODE_MAX + 13) +/* end of cam_req_mgr opcodes */ + +#define CAM_MEM_FLAG_HW_READ_WRITE (1<<0) +#define CAM_MEM_FLAG_HW_READ_ONLY (1<<1) +#define CAM_MEM_FLAG_HW_WRITE_ONLY (1<<2) +#define CAM_MEM_FLAG_KMD_ACCESS (1<<3) +#define CAM_MEM_FLAG_UMD_ACCESS (1<<4) +#define CAM_MEM_FLAG_PROTECTED_MODE (1<<5) +#define CAM_MEM_FLAG_CMD_BUF_TYPE (1<<6) +#define CAM_MEM_FLAG_PIXEL_BUF_TYPE (1<<7) +#define CAM_MEM_FLAG_STATS_BUF_TYPE (1<<8) +#define CAM_MEM_FLAG_PACKET_BUF_TYPE (1<<9) +#define CAM_MEM_FLAG_CACHE (1<<10) +#define CAM_MEM_FLAG_HW_SHARED_ACCESS (1<<11) +#define CAM_MEM_FLAG_CDSP_OUTPUT (1<<12) + +#define CAM_MEM_MMU_MAX_HANDLE 16 + +/* Maximum allowed buffers in existence */ +#define CAM_MEM_BUFQ_MAX 1024 + +#define CAM_MEM_MGR_SECURE_BIT_POS 15 +#define CAM_MEM_MGR_HDL_IDX_SIZE 15 +#define CAM_MEM_MGR_HDL_FD_SIZE 16 +#define CAM_MEM_MGR_HDL_IDX_END_POS 16 +#define CAM_MEM_MGR_HDL_FD_END_POS 32 + +#define CAM_MEM_MGR_HDL_IDX_MASK ((1 << CAM_MEM_MGR_HDL_IDX_SIZE) - 1) + +#define GET_MEM_HANDLE(idx, fd) \ + ((idx & CAM_MEM_MGR_HDL_IDX_MASK) | \ + (fd << (CAM_MEM_MGR_HDL_FD_END_POS - CAM_MEM_MGR_HDL_FD_SIZE))) \ + +#define GET_FD_FROM_HANDLE(hdl) \ + (hdl >> (CAM_MEM_MGR_HDL_FD_END_POS - CAM_MEM_MGR_HDL_FD_SIZE)) \ + +#define CAM_MEM_MGR_GET_HDL_IDX(hdl) (hdl & CAM_MEM_MGR_HDL_IDX_MASK) + +#define CAM_MEM_MGR_SET_SECURE_HDL(hdl, flag) \ + ((flag) ? (hdl |= (1 << CAM_MEM_MGR_SECURE_BIT_POS)) : \ + ((hdl) &= ~(1 << CAM_MEM_MGR_SECURE_BIT_POS))) + +#define CAM_MEM_MGR_IS_SECURE_HDL(hdl) \ + (((hdl) & \ + (1<> CAM_MEM_MGR_SECURE_BIT_POS) + +/** + * memory allocation type + */ +#define CAM_MEM_DMA_NONE 0 +#define CAM_MEM_DMA_BIDIRECTIONAL 1 +#define CAM_MEM_DMA_TO_DEVICE 2 +#define CAM_MEM_DMA_FROM_DEVICE 3 + + +/** + * memory cache operation + */ +#define CAM_MEM_CLEAN_CACHE 1 +#define CAM_MEM_INV_CACHE 2 +#define CAM_MEM_CLEAN_INV_CACHE 3 + + +/** + * struct cam_mem_alloc_out_params + * @buf_handle: buffer handle + * @fd: output buffer file descriptor + * @vaddr: virtual address pointer + */ +struct cam_mem_alloc_out_params { + uint32_t buf_handle; + int32_t fd; + uint64_t vaddr; +}; + +/** + * struct cam_mem_map_out_params + * @buf_handle: buffer handle + * @reserved: reserved for future + * @vaddr: virtual address pointer + */ +struct cam_mem_map_out_params { + uint32_t buf_handle; + uint32_t reserved; + uint64_t vaddr; +}; + +/** + * struct cam_mem_mgr_alloc_cmd + * @len: size of buffer to allocate + * @align: alignment of the buffer + * @mmu_hdls: array of mmu handles + * @num_hdl: number of handles + * @flags: flags of the buffer + * @out: out params + */ +/* CAM_REQ_MGR_ALLOC_BUF */ +struct cam_mem_mgr_alloc_cmd { + uint64_t len; + uint64_t align; + int32_t mmu_hdls[CAM_MEM_MMU_MAX_HANDLE]; + uint32_t num_hdl; + uint32_t flags; + struct cam_mem_alloc_out_params out; +}; + +/** + * struct cam_mem_mgr_map_cmd + * @mmu_hdls: array of mmu handles + * @num_hdl: number of handles + * @flags: flags of the buffer + * @fd: output buffer file descriptor + * @reserved: reserved field + * @out: out params + */ + +/* CAM_REQ_MGR_MAP_BUF */ +struct cam_mem_mgr_map_cmd { + int32_t mmu_hdls[CAM_MEM_MMU_MAX_HANDLE]; + uint32_t num_hdl; + uint32_t flags; + int32_t fd; + uint32_t reserved; + struct cam_mem_map_out_params out; +}; + +/** + * struct cam_mem_mgr_map_cmd + * @buf_handle: buffer handle + * @reserved: reserved field + */ +/* CAM_REQ_MGR_RELEASE_BUF */ +struct cam_mem_mgr_release_cmd { + int32_t buf_handle; + uint32_t reserved; +}; + +/** + * struct cam_mem_mgr_map_cmd + * @buf_handle: buffer handle + * @ops: cache operations + */ +/* CAM_REQ_MGR_CACHE_OPS */ +struct cam_mem_cache_ops_cmd { + int32_t buf_handle; + uint32_t mem_cache_ops; +}; + +/** + * Request Manager : error message type + * @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 + * @error_type: type of error + * @request_id: request id of frame + * @device_hdl: device handle + * @linke_hdl: link_hdl + * @resource_size: size of the resource + */ +struct cam_req_mgr_error_msg { + uint32_t error_type; + uint32_t request_id; + int32_t device_hdl; + int32_t link_hdl; + uint64_t resource_size; +}; + +/** + * struct cam_req_mgr_frame_msg + * @request_id: request id of the frame + * @frame_id: frame id of the frame + * @timestamp: timestamp of the frame + * @link_hdl: link handle associated with this message + * @sof_status: sof status success or fail + */ +struct cam_req_mgr_frame_msg { + uint64_t request_id; + uint64_t frame_id; + uint64_t timestamp; + int32_t link_hdl; + uint32_t sof_status; +}; + +/** + * struct cam_req_mgr_message + * @session_hdl: session to which the frame belongs to + * @reserved: reserved field + * @u: union which can either be error or frame message + */ +struct cam_req_mgr_message { + int32_t session_hdl; + int32_t reserved; + union { + struct cam_req_mgr_error_msg err_msg; + struct cam_req_mgr_frame_msg frame_msg; + } u; +}; +#endif /* __UAPI_LINUX_CAM_REQ_MGR_H */ diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h new file mode 100644 index 000000000000..57a5c4674ca2 --- /dev/null +++ b/include/uapi/media/cam_sensor.h @@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_SENSOR_H__ +#define __UAPI_CAM_SENSOR_H__ + +#include +#include +#include "cam_defs.h" + +#define CAM_SENSOR_PROBE_CMD (CAM_COMMON_OPCODE_MAX + 1) +#define CAM_FLASH_MAX_LED_TRIGGERS 3 +#define MAX_OIS_NAME_SIZE 32 +#define CAM_CSIPHY_SECURE_MODE_ENABLED 1 +/** + * struct cam_sensor_query_cap - capabilities info for sensor + * + * @slot_info : Indicates about the slotId or cell Index + * @secure_camera : Camera is in secure/Non-secure mode + * @pos_pitch : Sensor position pitch + * @pos_roll : Sensor position roll + * @pos_yaw : Sensor position yaw + * @actuator_slot_id : Actuator slot id which connected to sensor + * @eeprom_slot_id : EEPROM slot id which connected to sensor + * @ois_slot_id : OIS slot id which connected to sensor + * @flash_slot_id : Flash slot id which connected to sensor + * @csiphy_slot_id : CSIphy slot id which connected to sensor + * + */ +struct cam_sensor_query_cap { + uint32_t slot_info; + uint32_t secure_camera; + uint32_t pos_pitch; + uint32_t pos_roll; + uint32_t pos_yaw; + uint32_t actuator_slot_id; + uint32_t eeprom_slot_id; + uint32_t ois_slot_id; + uint32_t flash_slot_id; + uint32_t csiphy_slot_id; +} __attribute__((packed)); + +/** + * struct cam_csiphy_query_cap - capabilities info for csiphy + * + * @slot_info : Indicates about the slotId or cell Index + * @version : CSIphy version + * @clk lane : Of the 5 lanes, informs lane configured + * as clock lane + * @reserved + */ +struct cam_csiphy_query_cap { + uint32_t slot_info; + uint32_t version; + uint32_t clk_lane; + uint32_t reserved; +} __attribute__((packed)); + +/** + * struct cam_actuator_query_cap - capabilities info for actuator + * + * @slot_info : Indicates about the slotId or cell Index + * @reserved + */ +struct cam_actuator_query_cap { + uint32_t slot_info; + uint32_t reserved; +} __attribute__((packed)); + +/** + * struct cam_eeprom_query_cap_t - capabilities info for eeprom + * + * @slot_info : Indicates about the slotId or cell Index + * @eeprom_kernel_probe : Indicates about the kernel or userspace probe + */ +struct cam_eeprom_query_cap_t { + uint32_t slot_info; + uint16_t eeprom_kernel_probe; + uint16_t is_multimodule_mode; +} __attribute__((packed)); + +/** + * struct cam_ois_query_cap_t - capabilities info for ois + * + * @slot_info : Indicates about the slotId or cell Index + */ +struct cam_ois_query_cap_t { + uint32_t slot_info; + uint16_t reserved; +} __attribute__((packed)); + +/** + * struct cam_cmd_i2c_info - Contains slave I2C related info + * + * @slave_addr : Slave address + * @i2c_freq_mode : 4 bits are used for I2c freq mode + * @cmd_type : Explains type of command + */ +struct cam_cmd_i2c_info { + uint32_t slave_addr; + uint8_t i2c_freq_mode; + uint8_t cmd_type; + uint16_t reserved; +} __attribute__((packed)); + +/** + * struct cam_ois_opcode - Contains OIS opcode + * + * @prog : OIS FW prog register address + * @coeff : OIS FW coeff register address + * @pheripheral : OIS pheripheral + * @memory : OIS memory + */ +struct cam_ois_opcode { + uint32_t prog; + uint32_t coeff; + uint32_t pheripheral; + uint32_t memory; +} __attribute__((packed)); + +/** + * struct cam_cmd_ois_info - Contains OIS slave info + * + * @slave_addr : OIS i2c slave address + * @i2c_freq_mode : i2c frequency mode + * @cmd_type : Explains type of command + * @ois_fw_flag : indicates if fw is present or not + * @is_ois_calib : indicates the calibration data is available + * @ois_name : OIS name + * @opcode : opcode + */ +struct cam_cmd_ois_info { + uint16_t slave_addr; + uint8_t i2c_freq_mode; + uint8_t cmd_type; + uint8_t ois_fw_flag; + uint8_t is_ois_calib; + char ois_name[MAX_OIS_NAME_SIZE]; + struct cam_ois_opcode opcode; +} __attribute__((packed)); + +/** + * struct cam_cmd_probe - Contains sensor slave info + * + * @data_type : Slave register data type + * @addr_type : Slave register address type + * @op_code : Don't Care + * @cmd_type : Explains type of command + * @reg_addr : Slave register address + * @expected_data : Data expected at slave register address + * @data_mask : Data mask if only few bits are valid + * @camera_id : Indicates the slot to which camera + * needs to be probed + * @reserved + */ +struct cam_cmd_probe { + uint8_t data_type; + uint8_t addr_type; + uint8_t op_code; + uint8_t cmd_type; + uint32_t reg_addr; + uint32_t expected_data; + uint32_t data_mask; + uint16_t camera_id; + uint16_t reserved; +} __attribute__((packed)); + +/** + * struct cam_power_settings - Contains sensor power setting info + * + * @power_seq_type : Type of power sequence + * @reserved + * @config_val_low : Lower 32 bit value configuration value + * @config_val_high : Higher 32 bit value configuration value + * + */ +struct cam_power_settings { + uint16_t power_seq_type; + uint16_t reserved; + uint32_t config_val_low; + uint32_t config_val_high; +} __attribute__((packed)); + +/** + * struct cam_cmd_power - Explains about the power settings + * + * @count : Number of power settings follows + * @reserved + * @cmd_type : Explains type of command + * @power_settings : Contains power setting info + */ +struct cam_cmd_power { + uint32_t count; + uint8_t reserved; + uint8_t cmd_type; + uint16_t more_reserved; + struct cam_power_settings power_settings[1]; +} __attribute__((packed)); + +/** + * struct i2c_rdwr_header - header of READ/WRITE I2C command + * + * @ count : Number of registers / data / reg-data pairs + * @ op_code : Operation code + * @ cmd_type : Command buffer type + * @ data_type : I2C data type + * @ addr_type : I2C address type + * @ reserved + */ +struct i2c_rdwr_header { + uint32_t count; + uint8_t op_code; + uint8_t cmd_type; + uint8_t data_type; + uint8_t addr_type; +} __attribute__((packed)); + +/** + * struct i2c_random_wr_payload - payload for I2C random write + * + * @ reg_addr : Register address + * @ reg_data : Register data + * + */ +struct i2c_random_wr_payload { + uint32_t reg_addr; + uint32_t reg_data; +} __attribute__((packed)); + +/** + * struct cam_cmd_i2c_random_wr - I2C random write command + * @ header : header of READ/WRITE I2C command + * @ random_wr_payload : payload for I2C random write + */ +struct cam_cmd_i2c_random_wr { + struct i2c_rdwr_header header; + struct i2c_random_wr_payload random_wr_payload[1]; +} __attribute__((packed)); + +/** + * struct cam_cmd_read - I2C read command + * @ reg_data : Register data + * @ reserved + */ +struct cam_cmd_read { + uint32_t reg_data; + uint32_t reserved; +} __attribute__((packed)); + +/** + * struct cam_cmd_i2c_continuous_wr - I2C continuous write command + * @ header : header of READ/WRITE I2C command + * @ reg_addr : Register address + * @ data_read : I2C read command + */ +struct cam_cmd_i2c_continuous_wr { + struct i2c_rdwr_header header; + uint32_t reg_addr; + struct cam_cmd_read data_read[1]; +} __attribute__((packed)); + +/** + * struct cam_cmd_i2c_random_rd - I2C random read command + * @ header : header of READ/WRITE I2C command + * @ data_read : I2C read command + */ +struct cam_cmd_i2c_random_rd { + struct i2c_rdwr_header header; + struct cam_cmd_read data_read[1]; +} __attribute__((packed)); + +/** + * struct cam_cmd_i2c_continuous_rd - I2C continuous continuous read command + * @ header : header of READ/WRITE I2C command + * @ reg_addr : Register address + * + */ +struct cam_cmd_i2c_continuous_rd { + struct i2c_rdwr_header header; + uint32_t reg_addr; +} __attribute__((packed)); + +/** + * struct cam_cmd_conditional_wait - Conditional wait command + * @data_type : Data type + * @addr_type : Address type + * @op_code : Opcode + * @cmd_type : Explains type of command + * @timeout : Timeout for retries + * @reserved + * @reg_addr : Register Address + * @reg_data : Register data + * @data_mask : Data mask if only few bits are valid + * @camera_id : Indicates the slot to which camera + * needs to be probed + * + */ +struct cam_cmd_conditional_wait { + uint8_t data_type; + uint8_t addr_type; + uint16_t reserved; + uint8_t op_code; + uint8_t cmd_type; + uint16_t timeout; + uint32_t reg_addr; + uint32_t reg_data; + uint32_t data_mask; +} __attribute__((packed)); + +/** + * struct cam_cmd_unconditional_wait - Un-conditional wait command + * @delay : Delay + * @op_code : Opcode + * @cmd_type : Explains type of command + */ +struct cam_cmd_unconditional_wait { + int16_t delay; + int16_t reserved; + uint8_t op_code; + uint8_t cmd_type; + uint16_t reserved1; +} __attribute__((packed)); + +/** + * cam_csiphy_info: Provides cmdbuffer structre + * @lane_mask : Lane mask details + * @lane_assign : Lane sensor will be using + * @csiphy_3phase : Total number of lanes + * @combo_mode : Info regarding combo_mode is enable / disable + * @lane_cnt : Total number of lanes + * @secure_mode : Secure mode flag to enable / disable + * @3phase : Details whether 3Phase / 2Phase operation + * @settle_time : Settling time in ms + * @data_rate : Data rate + * + */ +struct cam_csiphy_info { + uint16_t lane_mask; + uint16_t lane_assign; + uint8_t csiphy_3phase; + uint8_t combo_mode; + uint8_t lane_cnt; + uint8_t secure_mode; + uint64_t settle_time; + uint64_t data_rate; +} __attribute__((packed)); + +/** + * cam_csiphy_acquire_dev_info : Information needed for + * csiphy at the time of acquire + * @combo_mode : Indicates the device mode of operation + * @reserved + * + */ +struct cam_csiphy_acquire_dev_info { + uint32_t combo_mode; + uint32_t reserved; +} __attribute__((packed)); + +/** + * cam_sensor_acquire_dev : Updates sensor acuire cmd + * @device_handle : Updates device handle + * @session_handle : Session handle for acquiring device + * @handle_type : Resource handle type + * @reserved + * @info_handle : Handle to additional info + * needed for sensor sub modules + * + */ +struct cam_sensor_acquire_dev { + uint32_t session_handle; + uint32_t device_handle; + uint32_t handle_type; + uint32_t reserved; + uint64_t info_handle; +} __attribute__((packed)); + +/** + * cam_sensor_streamon_dev : StreamOn command for the sensor + * @session_handle : Session handle for acquiring device + * @device_handle : Updates device handle + * @handle_type : Resource handle type + * @reserved + * @info_handle : Information Needed at the time of streamOn + * + */ +struct cam_sensor_streamon_dev { + uint32_t session_handle; + uint32_t device_handle; + uint32_t handle_type; + uint32_t reserved; + uint64_t info_handle; +} __attribute__((packed)); + +/** + * struct cam_flash_init : Init command for the flash + * @flash_type : flash hw type + * @reserved + * @cmd_type : command buffer type + */ +struct cam_flash_init { + uint8_t flash_type; + uint16_t reserved; + uint8_t cmd_type; +} __attribute__((packed)); + +/** + * struct cam_flash_set_rer : RedEyeReduction command buffer + * + * @count : Number of flash leds + * @opcode : Command buffer opcode + * CAM_FLASH_FIRE_RER + * @cmd_type : command buffer operation type + * @num_iteration : Number of led turn on/off sequence + * @reserved + * @led_on_delay_ms : flash led turn on time in ms + * @led_off_delay_ms : flash led turn off time in ms + * @led_current_ma : flash led current in ma + * + */ +struct cam_flash_set_rer { + uint32_t count; + uint8_t opcode; + uint8_t cmd_type; + uint16_t num_iteration; + uint32_t led_on_delay_ms; + uint32_t led_off_delay_ms; + uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; +} __attribute__((packed)); + +/** + * struct cam_flash_set_on_off : led turn on/off command buffer + * + * @count : Number of Flash leds + * @opcode : command buffer opcodes + * CAM_FLASH_FIRE_LOW + * CAM_FLASH_FIRE_HIGH + * CAM_FLASH_OFF + * @cmd_type : command buffer operation type + * @led_current_ma : flash led current in ma + * + */ +struct cam_flash_set_on_off { + uint32_t count; + uint8_t opcode; + uint8_t cmd_type; + uint16_t reserved; + uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; +} __attribute__((packed)); + +/** + * struct cam_flash_query_curr : query current command buffer + * + * @reserved + * @opcode : command buffer opcode + * @cmd_type : command buffer operation type + * @query_current_ma : battery current in ma + * + */ +struct cam_flash_query_curr { + uint16_t reserved; + uint8_t opcode; + uint8_t cmd_type; + uint32_t query_current_ma; +} __attribute__ ((packed)); + +/** + * struct cam_flash_query_cap : capabilities info for flash + * + * @slot_info : Indicates about the slotId or cell Index + * @max_current_flash : max supported current for flash + * @max_duration_flash : max flash turn on duration + * @max_current_torch : max supported current for torch + * + */ +struct cam_flash_query_cap_info { + uint32_t slot_info; + uint32_t max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS]; + uint32_t max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; + uint32_t max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; +} __attribute__ ((packed)); + +#endif diff --git a/include/uapi/media/cam_sync.h b/include/uapi/media/cam_sync.h new file mode 100644 index 000000000000..d1ab63fd4294 --- /dev/null +++ b/include/uapi/media/cam_sync.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_SYNC_H__ +#define __UAPI_CAM_SYNC_H__ + +#include +#include +#include +#include + +#define CAM_SYNC_DEVICE_NAME "cam_sync_device" + +/* V4L event which user space will subscribe to */ +#define CAM_SYNC_V4L_EVENT (V4L2_EVENT_PRIVATE_START + 0) + +/* Specific event ids to get notified in user space */ +#define CAM_SYNC_V4L_EVENT_ID_CB_TRIG 0 + +/* Size of opaque payload sent to kernel for safekeeping until signal time */ +#define CAM_SYNC_USER_PAYLOAD_SIZE 2 + +/* Device type for sync device needed for device discovery */ +#define CAM_SYNC_DEVICE_TYPE (MEDIA_ENT_F_OLD_BASE) + +#define CAM_SYNC_GET_PAYLOAD_PTR(ev, type) \ + (type *)((char *)ev.u.data + sizeof(struct cam_sync_ev_header)) + +#define CAM_SYNC_GET_HEADER_PTR(ev) \ + ((struct cam_sync_ev_header *)ev.u.data) + +#define CAM_SYNC_STATE_INVALID 0 +#define CAM_SYNC_STATE_ACTIVE 1 +#define CAM_SYNC_STATE_SIGNALED_SUCCESS 2 +#define CAM_SYNC_STATE_SIGNALED_ERROR 3 + +/** + * struct cam_sync_ev_header - Event header for sync event notification + * + * @sync_obj: Sync object + * @status: Status of the object + */ +struct cam_sync_ev_header { + int32_t sync_obj; + int32_t status; +}; + +/** + * struct cam_sync_info - Sync object creation information + * + * @name: Optional string representation of the sync object + * @sync_obj: Sync object returned after creation in kernel + */ +struct cam_sync_info { + char name[64]; + int32_t sync_obj; +}; + +/** + * struct cam_sync_signal - Sync object signaling struct + * + * @sync_obj: Sync object to be signaled + * @sync_state: State of the sync object to which it should be signaled + */ +struct cam_sync_signal { + int32_t sync_obj; + uint32_t sync_state; +}; + +/** + * struct cam_sync_merge - Merge information for sync objects + * + * @sync_objs: Pointer to sync objects + * @num_objs: Number of objects in the array + * @merged: Merged sync object + */ +struct cam_sync_merge { + __u64 sync_objs; + uint32_t num_objs; + int32_t merged; +}; + +/** + * struct cam_sync_userpayload_info - Payload info from user space + * + * @sync_obj: Sync object for which payload has to be registered for + * @reserved: Reserved + * @payload: Pointer to user payload + */ +struct cam_sync_userpayload_info { + int32_t sync_obj; + uint32_t reserved; + __u64 payload[CAM_SYNC_USER_PAYLOAD_SIZE]; +}; + +/** + * struct cam_sync_wait - Sync object wait information + * + * @sync_obj: Sync object to wait on + * @reserved: Reserved + * @timeout_ms: Timeout in milliseconds + */ +struct cam_sync_wait { + int32_t sync_obj; + uint32_t reserved; + uint64_t timeout_ms; +}; + +/** + * struct cam_private_ioctl_arg - Sync driver ioctl argument + * + * @id: IOCTL command id + * @size: Size of command payload + * @result: Result of command execution + * @reserved: Reserved + * @ioctl_ptr: Pointer to user data + */ +struct cam_private_ioctl_arg { + __u32 id; + __u32 size; + __u32 result; + __u32 reserved; + __u64 ioctl_ptr; +}; + +#define CAM_PRIVATE_IOCTL_CMD \ + _IOWR('V', BASE_VIDIOC_PRIVATE, struct cam_private_ioctl_arg) + +#define CAM_SYNC_CREATE 0 +#define CAM_SYNC_DESTROY 1 +#define CAM_SYNC_SIGNAL 2 +#define CAM_SYNC_MERGE 3 +#define CAM_SYNC_REGISTER_PAYLOAD 4 +#define CAM_SYNC_DEREGISTER_PAYLOAD 5 +#define CAM_SYNC_WAIT 6 + +#endif /* __UAPI_CAM_SYNC_H__ */ From c28468e27892b0f8e6f3cab3e39719d1d9e9812d Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Thu, 23 May 2019 07:16:09 -0700 Subject: [PATCH 004/790] msm: camera: Add custom ratelimit logs and use for old blob type Adding custom ratelimited log types and use it in generic blob handler for isp and icp. Change-Id: Iec6c94f41506839055c5e0036d2e343849dc12b5 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Karthik Anantha Ram --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 +- drivers/cam_utils/cam_debug_util.h | 81 ++++++++++++++++++- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 2a77519d92cb..9cb19fae68c9 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4118,7 +4118,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, switch (blob_type) { case CAM_ICP_CMD_GENERIC_BLOB_CLK: - CAM_WARN(CAM_ICP, + CAM_WARN_RATE_LIMIT_CUSTOM(CAM_ICP, 300, 1, "Using deprecated blob type GENERIC_BLOB_CLK"); if (blob_size != sizeof(struct cam_icp_clk_bw_request)) { CAM_ERR(CAM_ICP, "Mismatch blob size %d expected %lu", diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index cb0b341b981f..07a7c196522c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4625,7 +4625,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, struct cam_isp_bw_config *bw_config; struct cam_isp_prepare_hw_update_data *prepare_hw_data; - CAM_WARN(CAM_ISP, "Deprecated Blob TYPE_BW_CONFIG"); + CAM_WARN_RATE_LIMIT_CUSTOM(CAM_ISP, 300, 1, + "Deprecated Blob TYPE_BW_CONFIG"); if (blob_size < sizeof(struct cam_isp_bw_config)) { CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); return -EINVAL; diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 7380312dcde0..55f316b41da4 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_DEBUG_UTIL_H_ @@ -109,7 +109,7 @@ const char *cam_get_module_name(unsigned int module_id); * @args : Arguments which needs to be print in log */ #define CAM_INFO_RATE_LIMIT(__module, fmt, args...) \ - pr_err_ratelimited("CAM_INFO: %s: %s: %d " fmt "\n", \ + pr_info_ratelimited("CAM_INFO: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, __LINE__, ##args) /* @@ -130,5 +130,82 @@ const char *cam_get_module_name(unsigned int module_id); #define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ pr_err_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, __LINE__, ##args) +/* + * CAM_WARN_RATE_LIMIT + * @brief : This Macro will print warning logs with ratelimit + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_WARN_RATE_LIMIT(__module, fmt, args...) \ + pr_warn_ratelimited("CAM_WARN: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, __LINE__, ##args) + +/* + * CAM_WARN_RATE_LIMIT_CUSTOM + * @brief : This Macro will print warn logs with custom ratelimit + * + * @__module : Respective module id which is been calling this Macro + * @interval : Time interval in seconds + * @burst : No of logs to print in interval time + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_WARN_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ + ({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + (interval * HZ), \ + burst); \ + if (__ratelimit(&_rs)) \ + pr_warn( \ + "CAM_WARN: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + }) + +/* + * CAM_INFO_RATE_LIMIT_CUSTOM + * @brief : This Macro will print info logs with custom ratelimit + * + * @__module : Respective module id which is been calling this Macro + * @interval : Time interval in seconds + * @burst : No of logs to print in interval time + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_INFO_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ + ({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + (interval * HZ), \ + burst); \ + if (__ratelimit(&_rs)) \ + pr_info( \ + "CAM_INFO: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + }) + +/* + * CAM_ERR_RATE_LIMIT_CUSTOM + * @brief : This Macro will print error logs with custom ratelimit + * + * @__module : Respective module id which is been calling this Macro + * @interval : Time interval in seconds + * @burst : No of logs to print in interval time + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_ERR_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ + ({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + (interval * HZ), \ + burst); \ + if (__ratelimit(&_rs)) \ + pr_err( \ + "CAM_ERR: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + }) #endif /* _CAM_DEBUG_UTIL_H_ */ From 396a4cc5761c12c0ad084225d1aa74b4a854fcec Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Thu, 23 May 2019 08:13:23 -0700 Subject: [PATCH 005/790] msm: camera: Add LCR in axi bw vote and checks for memory free Adding LCR resource id in isp bw voting for axi bw voting v1 path and v2 path. Also, adding checks for unwanted memory free during cpas probe. Change-Id: Ib3dca34727b640326893fb227b160a42dab457fc Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_soc.c | 13 +++++--- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 36 +++++---------------- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index 9dd24cdaa3d1..6c34dd0687e6 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -102,12 +102,17 @@ int cam_cpas_node_tree_cleanup(struct cam_cpas *cpas_core, } for (i = 0; i < CAM_CPAS_MAX_TREE_LEVELS; i++) { - of_node_put(soc_private->level_node[i]); - soc_private->level_node[i] = NULL; + if (soc_private->level_node[i]) { + of_node_put(soc_private->level_node[i]); + soc_private->level_node[i] = NULL; + } + } + + if (soc_private->camera_bus_node) { + of_node_put(soc_private->camera_bus_node); + soc_private->camera_bus_node = NULL; } - of_node_put(soc_private->camera_bus_node); - soc_private->camera_bus_node = NULL; mutex_destroy(&cpas_core->tree_lock); return 0; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 07a7c196522c..2895e6f9d824 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2715,7 +2715,8 @@ static int cam_isp_classify_vote_info( if ((hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_RD) || - (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB)) { + (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || + (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_LCR)) { if (split_idx == CAM_ISP_HW_SPLIT_LEFT) { if (*camif_l_bw_updated) return rc; @@ -2890,8 +2891,11 @@ 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) - || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_RD)) + if ((hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) || + (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_RD) || + (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) + || (hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_LCR)) if (i == CAM_ISP_HW_SPLIT_LEFT) { if (camif_l_bw_updated) continue; @@ -2925,32 +2929,8 @@ static int cam_isp_blob_bw_update( bw_config->rdi_vote[idx].cam_bw_bps; ext_bw_bps = bw_config->rdi_vote[idx].ext_bw_bps; - } else if (hw_mgr_res->res_id == - CAM_ISP_HW_VFE_IN_PDLIB) { - if (i == CAM_ISP_HW_SPLIT_LEFT) { - if (camif_l_bw_updated) - continue; - - cam_bw_bps = - bw_config->left_pix_vote.cam_bw_bps; - ext_bw_bps = - bw_config->left_pix_vote.ext_bw_bps; - - camif_l_bw_updated = true; - } else { - if (camif_r_bw_updated) - continue; - - cam_bw_bps = - bw_config->right_pix_vote.cam_bw_bps; - ext_bw_bps = - bw_config->right_pix_vote.ext_bw_bps; - - camif_r_bw_updated = true; - } } else { - if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_LCR - && hw_mgr_res->hw_res[i]) { + if (hw_mgr_res->hw_res[i]) { CAM_ERR(CAM_ISP, "Invalid res_id %u", hw_mgr_res->res_id); rc = -EINVAL; From 40047f58dfcf74a0ac9372bb262394ac0bb33f25 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 11 Jun 2019 11:31:11 -0700 Subject: [PATCH 006/790] msm: camera: core : Validate the dev name during the node ioctl handler Validate the context device name with node name. If device name is not matching return the error. Change-Id: I8dee4e6f64e17b0d1e486077a2c8b0df562a702e Signed-off-by: Rishabh Jain --- drivers/cam_core/cam_context.c | 2 +- drivers/cam_core/cam_context.h | 7 ++- drivers/cam_core/cam_node.c | 44 ++++++++++++++++++- drivers/cam_core/cam_node.h | 5 +-- drivers/cam_fd/cam_fd_context.c | 4 +- drivers/cam_icp/cam_icp_context.c | 2 +- drivers/cam_isp/cam_isp_context.c | 2 +- drivers/cam_jpeg/cam_jpeg_context.c | 2 +- drivers/cam_lrme/cam_lrme_context.c | 4 +- .../cam_actuator/cam_actuator_dev.h | 5 ++- drivers/cam_sensor_module/cam_csiphy/Makefile | 1 + .../cam_csiphy/cam_csiphy_dev.h | 4 +- drivers/cam_sensor_module/cam_eeprom/Makefile | 2 + .../cam_eeprom/cam_eeprom_dev.h | 4 +- .../cam_flash/cam_flash_dev.c | 2 + .../cam_flash/cam_flash_dev.h | 3 ++ drivers/cam_sensor_module/cam_ois/Makefile | 1 + .../cam_sensor_module/cam_ois/cam_ois_dev.h | 7 +-- .../cam_sensor/cam_sensor_dev.h | 5 ++- 19 files changed, 83 insertions(+), 23 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 85908a3b6a4d..d2ec399e2895 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -519,7 +519,7 @@ int cam_context_init(struct cam_context *ctx, mutex_init(&ctx->sync_mutex); spin_lock_init(&ctx->lock); - ctx->dev_name = dev_name; + strlcpy(ctx->dev_name, dev_name, CAM_CTX_DEV_NAME_MAX_LENGTH); ctx->dev_id = dev_id; ctx->ctx_id = ctx_id; ctx->last_flush_req = 0; diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 55fd376f33d6..1583dd06df3f 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -15,6 +15,9 @@ /* Forward declarations */ struct cam_context; +/* max device name string length*/ +#define CAM_CTX_DEV_NAME_MAX_LENGTH 20 + /* max request number */ #define CAM_CTX_REQ_MAX 20 #define CAM_CTX_CFG_MAX 20 @@ -177,7 +180,7 @@ struct cam_ctx_ops { * */ struct cam_context { - const char *dev_name; + char dev_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; uint64_t dev_id; uint32_t ctx_id; struct list_head list; diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 1ef4aa59302e..9c4c6f242336 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -27,7 +27,7 @@ static void cam_node_print_ctx_state( spin_lock_bh(&ctx->lock); CAM_INFO(CAM_CORE, "[%s][%d] : state=%d, refcount=%d, active_req_list=%d, pending_req_list=%d, wait_req_list=%d, free_req_list=%d", - ctx->dev_name ? ctx->dev_name : "null", + ctx->dev_name, i, ctx->state, atomic_read(&(ctx->refcount.refcount.refs)), list_empty(&ctx->active_req_list), @@ -148,6 +148,12 @@ static int __cam_node_handle_acquire_hw_v1(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + rc = cam_context_handle_acquire_hw(ctx, acquire); if (rc) { CAM_ERR(CAM_CORE, "Acquire device failed for node %s", @@ -226,6 +232,12 @@ static int __cam_node_handle_start_dev(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + rc = cam_context_handle_start_dev(ctx, start); if (rc) CAM_ERR(CAM_CORE, "Start failure for node %s", node->name); @@ -259,6 +271,12 @@ static int __cam_node_handle_stop_dev(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + rc = cam_context_handle_stop_dev(ctx, stop); if (rc) CAM_ERR(CAM_CORE, "Stop failure for node %s", node->name); @@ -292,6 +310,12 @@ static int __cam_node_handle_config_dev(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + rc = cam_context_handle_config_dev(ctx, config); if (rc) CAM_ERR(CAM_CORE, "Config failure for node %s", node->name); @@ -325,6 +349,12 @@ static int __cam_node_handle_flush_dev(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + rc = cam_context_handle_flush_dev(ctx, flush); if (rc) CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name); @@ -358,6 +388,12 @@ static int __cam_node_handle_release_dev(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + if (ctx->state > CAM_CTX_UNINIT && ctx->state < CAM_CTX_STATE_MAX) { rc = cam_context_handle_release_dev(ctx, release); if (rc) @@ -413,6 +449,12 @@ static int __cam_node_handle_release_hw_v1(struct cam_node *node, return -EINVAL; } + if (strcmp(node->name, ctx->dev_name)) { + CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + node->name, ctx->dev_name); + return -EINVAL; + } + rc = cam_context_handle_release_hw(ctx, release); if (rc) CAM_ERR(CAM_CORE, "context release failed node %s", node->name); diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h index ad49c4b619a9..062d0213115c 100644 --- a/drivers/cam_core/cam_node.h +++ b/drivers/cam_core/cam_node.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_NODE_H_ @@ -11,7 +11,6 @@ #include "cam_hw_mgr_intf.h" #include "cam_req_mgr_interface.h" -#define CAM_NODE_NAME_LENGTH_MAX 256 #define CAM_NODE_STATE_UNINIT 0 #define CAM_NODE_STATE_INIT 1 @@ -31,7 +30,7 @@ * */ struct cam_node { - char name[CAM_NODE_NAME_LENGTH_MAX]; + char name[CAM_CTX_DEV_NAME_MAX_LENGTH]; uint32_t state; /* context pool */ diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index 427fcf788081..8805859abb00 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -10,7 +10,7 @@ #include "cam_fd_context.h" #include "cam_trace.h" -static const char fd_dev_name[] = "fd"; +static const char fd_dev_name[] = "cam-fd"; /* Functions in Available state */ static int __cam_fd_ctx_acquire_dev_in_available(struct cam_context *ctx, diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index c7d9c63f8429..86876a35b671 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -20,7 +20,7 @@ #include "cam_debug_util.h" #include "cam_packet_util.h" -static const char icp_dev_name[] = "icp"; +static const char icp_dev_name[] = "cam-icp"; static int cam_icp_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 7e1fa25910b2..282bf55cbf4f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -20,7 +20,7 @@ #include "cam_isp_context.h" #include "cam_common_util.h" -static const char isp_dev_name[] = "isp"; +static const char isp_dev_name[] = "cam-isp"; #define INC_STATE_MONITOR_HEAD(head) \ (atomic64_add_return(1, head) % \ diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index e28aae21e7d9..b16a9dfed011 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -14,7 +14,7 @@ #include "cam_debug_util.h" #include "cam_packet_util.h" -static const char jpeg_dev_name[] = "jpeg"; +static const char jpeg_dev_name[] = "cam-jpeg"; static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info) diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index 3270d77af5fe..ae8f93c500ef 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -9,7 +9,7 @@ #include "cam_debug_util.h" #include "cam_lrme_context.h" -static const char lrme_dev_name[] = "lrme"; +static const char lrme_dev_name[] = "cam-lrme"; static int __cam_lrme_ctx_acquire_dev_in_available(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h index 9c704c0cd48e..e4e5e4305246 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -25,6 +25,7 @@ #include "cam_sensor_util.h" #include "cam_soc_util.h" #include "cam_debug_util.h" +#include "cam_context.h" #define NUM_MASTERS 2 #define NUM_QUEUES 2 @@ -83,6 +84,7 @@ struct intf_params { /** * struct cam_actuator_ctrl_t + * @device_name: Device name * @i2c_driver: I2C device info * @pdev: Platform device * @cci_i2c_master: I2C structure @@ -98,10 +100,10 @@ struct intf_params { * @i2c_data: I2C register settings structure * @act_info: Sensor query cap structure * @of_node: Node ptr - * @device_name: Device name * @last_flush_req: Last request to flush */ struct cam_actuator_ctrl_t { + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct i2c_driver *i2c_driver; enum cci_i2c_master_t cci_i2c_master; enum cci_device_num cci_num; @@ -116,7 +118,6 @@ struct cam_actuator_ctrl_t { struct i2c_data_settings i2c_data; struct cam_actuator_query_cap act_info; struct intf_params bridge_intf; - char device_name[20]; uint32_t last_flush_req; }; diff --git a/drivers/cam_sensor_module/cam_csiphy/Makefile b/drivers/cam_sensor_module/cam_csiphy/Makefile index 88ab6ed9a1bb..eb23b89c2108 100644 --- a/drivers/cam_sensor_module/cam_csiphy/Makefile +++ b/drivers/cam_sensor_module/cam_csiphy/Makefile @@ -8,5 +8,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_u ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy_soc.o cam_csiphy_dev.o cam_csiphy_core.o diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 7453db1e0658..2bae9a51529b 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -26,6 +26,7 @@ #include #include "cam_soc_util.h" #include "cam_debug_util.h" +#include "cam_context.h" #define MAX_CSIPHY 6 #define MAX_DPHY_DATA_LN 4 @@ -235,6 +236,7 @@ struct cam_csiphy_param { /** * struct csiphy_device + * @device_name: Device name * @pdev: Platform device * @irq: Interrupt structure * @base: Base address @@ -263,6 +265,7 @@ struct cam_csiphy_param { * @csiphy_cpas_cp_reg_mask: CP reg mask for phy instance */ struct csiphy_device { + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct mutex mutex; uint32_t hw_version; enum cam_csiphy_state csiphy_state; @@ -282,7 +285,6 @@ struct csiphy_device { uint32_t clk_lane; uint32_t acquire_count; uint32_t start_dev_count; - char device_name[20]; uint32_t is_acquired_dev_combo_mode; struct cam_hw_soc_info soc_info; uint32_t cpas_handle; diff --git a/drivers/cam_sensor_module/cam_eeprom/Makefile b/drivers/cam_sensor_module/cam_eeprom/Makefile index e52bc01dc5a5..850b16787c11 100644 --- a/drivers/cam_sensor_module/cam_eeprom/Makefile +++ b/drivers/cam_sensor_module/cam_eeprom/Makefile @@ -8,4 +8,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_u ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core + obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom_dev.o cam_eeprom_core.o cam_eeprom_soc.o diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h index 2bac99f8c298..6bf08d11ed6a 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -22,6 +22,7 @@ #include #include #include "cam_soc_util.h" +#include "cam_context.h" #define DEFINE_MSM_MUTEX(mutexname) \ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) @@ -152,6 +153,7 @@ struct eebin_info { /** * struct cam_eeprom_ctrl_t - EEPROM control structure + * @device_name : Device name * @pdev : platform device * @spi : spi device * @eeprom_mutex : eeprom mutex @@ -170,6 +172,7 @@ struct eebin_info { * @eebin_info : EEBIN address, size info */ struct cam_eeprom_ctrl_t { + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct platform_device *pdev; struct spi_device *spi; struct mutex eeprom_mutex; @@ -184,7 +187,6 @@ struct cam_eeprom_ctrl_t { enum cam_eeprom_state cam_eeprom_state; bool userspace_probe; struct cam_eeprom_memory_block_t cal_data; - char device_name[20]; uint16_t is_multimodule_mode; struct i2c_settings_array wr_settings; struct eebin_info eebin_info; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index d0610667e626..5eccfd8aa11b 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -379,6 +379,8 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) { int rc = 0; + strlcpy(fctrl->device_name, CAM_FLASH_NAME, + sizeof(fctrl->device_name)); fctrl->v4l2_dev_str.internal_ops = &cam_flash_internal_ops; fctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index c4f17656ace0..8bd5b9115f05 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -28,6 +28,7 @@ #include "cam_debug_util.h" #include "cam_sensor_io.h" #include "cam_flash_core.h" +#include "cam_context.h" #define CAMX_FLASH_DEV_NAME "cam-flash-dev" @@ -153,6 +154,7 @@ struct cam_flash_func_tbl { /** * struct cam_flash_ctrl + * @device_name : Device name * @soc_info : Soc related information * @pdev : Platform device * @per_frame[] : Per_frame setting array @@ -179,6 +181,7 @@ struct cam_flash_func_tbl { * @last_flush_req : last request to flush */ struct cam_flash_ctrl { + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct cam_hw_soc_info soc_info; struct platform_device *pdev; struct cam_sensor_power_ctrl_t power_info; diff --git a/drivers/cam_sensor_module/cam_ois/Makefile b/drivers/cam_sensor_module/cam_ois/Makefile index e987a2257e9e..345203739517 100644 --- a/drivers/cam_sensor_module/cam_ois/Makefile +++ b/drivers/cam_sensor_module/cam_ois/Makefile @@ -8,5 +8,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index 0c2a450fe058..1808a2b2f0c6 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_OIS_DEV_H_ #define _CAM_OIS_DEV_H_ @@ -20,6 +20,7 @@ #include #include #include "cam_soc_util.h" +#include "cam_context.h" #define DEFINE_MSM_MUTEX(mutexname) \ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) @@ -83,6 +84,7 @@ struct cam_ois_intf_params { /** * struct cam_ois_ctrl_t - OIS ctrl private data + * @device_name : ois device_name * @pdev : platform device * @ois_mutex : ois mutex * @soc_info : ois soc related info @@ -95,7 +97,6 @@ struct cam_ois_intf_params { * @i2c_calib_data : ois i2c calib settings * @ois_device_type : ois device type * @cam_ois_state : ois_device_state - * @ois_name : ois name * @ois_fw_flag : flag for firmware download * @is_ois_calib : flag for Calibration data * @opcode : ois opcode @@ -103,6 +104,7 @@ struct cam_ois_intf_params { * */ struct cam_ois_ctrl_t { + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct platform_device *pdev; struct mutex ois_mutex; struct cam_hw_soc_info soc_info; @@ -116,7 +118,6 @@ struct cam_ois_ctrl_t { struct i2c_settings_array i2c_mode_data; enum msm_camera_device_type_t ois_device_type; enum cam_ois_state cam_ois_state; - char device_name[20]; char ois_name[32]; uint8_t ois_fw_flag; uint8_t is_ois_calib; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h index 86676a4c8f0a..37e0affdf991 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -23,6 +23,7 @@ #include #include #include "cam_debug_util.h" +#include "cam_context.h" #define NUM_MASTERS 2 #define NUM_QUEUES 2 @@ -65,6 +66,7 @@ struct intf_params { /** * struct cam_sensor_ctrl_t: Camera control structure + * @device_name: Sensor device name * @pdev: Platform device * @cam_sensor_mutex: Sensor mutex * @sensordata: Sensor board Information @@ -80,7 +82,6 @@ struct intf_params { * @i2c_data: Sensor I2C register settings * @sensor_info: Sensor query cap structure * @bridge_intf: Bridge interface structure - * @device_name: Sensor device structure * @streamon_count: Count to hold the number of times stream on called * @streamoff_count: Count to hold the number of times stream off called * @bob_reg_index: Hold to BoB regulator index @@ -89,6 +90,7 @@ struct intf_params { * @pipeline_delay: Sensor pipeline delay */ struct cam_sensor_ctrl_t { + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; struct platform_device *pdev; struct cam_hw_soc_info soc_info; struct mutex cam_sensor_mutex; @@ -106,7 +108,6 @@ struct cam_sensor_ctrl_t { struct i2c_data_settings i2c_data; struct cam_sensor_query_cap sensor_info; struct intf_params bridge_intf; - char device_name[20]; uint32_t streamon_count; uint32_t streamoff_count; int bob_reg_index; From aeffc3147d8af1f5157b5a4f9279e5e1cb3f075f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 11 Jun 2019 11:32:53 -0700 Subject: [PATCH 007/790] msm: camera: Adds state variable in mem manager Add state variable for camera mem manager to show initialization status. Ensure that all operations are rejected before initialization. Change-Id: I1ddbaaf6fbed59e4804476562c97f6895d99e916 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_req_mgr/cam_mem_mgr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 73ac694eeafa..b7f77506d004 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -234,6 +234,11 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) return -EINVAL; } + if (!atomic_read(&cam_mem_mgr_state)) { + CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); + return -EINVAL; + } + if (!buf_handle || !vaddr_ptr || !len) return -EINVAL; From f8b0159a3e6dbdc551986bf38c36f95950ce85f7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 11 Jun 2019 11:34:01 -0700 Subject: [PATCH 008/790] msm: camera: Update dynamic clock voting for csiphy Update the clock voting, datarate settings for csiphy version 1.2.2. Change-Id: I7b08819c1918d2eeec530733d42828e092bf2aa9 Signed-off-by: Shankar Ravi --- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 4dd5273e0438..f66f8de722eb 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -302,10 +302,14 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_common_reg_1_2; csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_2; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic; csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = true; csiphy_dev->hw_version = CSIPHY_VERSION_V12; csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; From 391b3fa3d62f2ecfe2ce44b2dad694695cb8599f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 11 Jun 2019 11:34:49 -0700 Subject: [PATCH 009/790] msm: camera: Update csiphy settings for lito Update the register settings for CPHY 3phase. Change-Id: I5cdc5cd348f9f861215206c59e674efdcdc7159c Signed-off-by: Shankar Ravi --- .../cam_csiphy/cam_csiphy_soc.c | 7 +- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 86 ++++++------------- 2 files changed, 31 insertions(+), 62 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index f66f8de722eb..a6aba5940181 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -302,14 +302,13 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_common_reg_1_2; csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_2; - csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; - csiphy_dev->is_divisor_32_comp = true; + csiphy_dev->is_divisor_32_comp = false; csiphy_dev->hw_version = CSIPHY_VERSION_V12; csiphy_dev->clk_lane = 0; - csiphy_dev->ctrl_reg->data_rates_settings_table = - &data_rate_delta_table; + csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 6ee9e155b93d..d99c4ee3758a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -12,10 +12,10 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .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 = 5, - .csiphy_2ph_config_array_size = 22, - .csiphy_3ph_config_array_size = 38, + .csiphy_common_array_size = 5, + .csiphy_reset_array_size = 4, + .csiphy_2ph_config_array_size = 21, + .csiphy_3ph_config_array_size = 32, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -23,17 +23,15 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { struct csiphy_reg_t csiphy_common_reg_1_2[] = { {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, - {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, - {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, }; 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}, }; @@ -71,11 +69,10 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -99,7 +96,6 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -123,7 +119,6 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -147,7 +142,6 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -171,7 +165,6 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -195,11 +188,10 @@ struct csiphy_reg_t {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -223,7 +215,6 @@ struct csiphy_reg_t {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -247,7 +238,6 @@ struct csiphy_reg_t {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -271,7 +261,6 @@ struct csiphy_reg_t {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -295,14 +284,13 @@ struct csiphy_reg_t {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, }; struct csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { - {0x015C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -310,10 +298,10 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x016C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -331,29 +319,23 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { - {0x035C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x036C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -371,18 +353,12 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { - {0x055C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -390,10 +366,10 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x056C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -411,15 +387,9 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; From 7fd239ba2485784d8863662e3049d5b089865846 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 11 Jun 2019 11:36:01 -0700 Subject: [PATCH 010/790] msm: camera: Enable top debug status cfg register In case of VFE Overflow print additional debug information based on whether the overflow is on bus side or in the IFE modules. Change-Id: I292bab0e75824bd1f151a4824f25220784c81172 Signed-off-by: Vishalsingh Hajeri Signed-off-by: Venkat Chinta --- drivers/cam_cpas/cam_cpas_hw.c | 6 +- .../isp_hw/include/cam_vfe_hw_intf.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 16 +++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 9 ++ .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 113 +++++++++++++++--- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h | 1 + .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 92 ++++++++++++-- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.h | 1 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h | 15 +++ 9 files changed, 218 insertions(+), 36 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index f7bf5a22129f..d180b4ecf9aa 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -377,15 +377,13 @@ static int cam_cpas_hw_reg_read(struct cam_hw_info *cpas_hw, if (!CAM_CPAS_CLIENT_VALID(client_indx)) return -EINVAL; - mutex_lock(&cpas_core->client_mutex[client_indx]); cpas_client = cpas_core->cpas_client[client_indx]; if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started", client_indx, cpas_client->data.identifier, cpas_client->data.cell_index); - rc = -EPERM; - goto unlock_client; + return -EPERM; } if (mb) @@ -397,8 +395,6 @@ static int cam_cpas_hw_reg_read(struct cam_hw_info *cpas_hw, *value = reg_value; -unlock_client: - mutex_unlock(&cpas_core->client_mutex[client_indx]); return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 7944cbc8933f..a1d1c6a60881 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -60,6 +60,7 @@ enum cam_vfe_hw_irq_regs { CAM_IFE_IRQ_CAMIF_REG_STATUS1 = 1, CAM_IFE_IRQ_CAMIF_REG_STATUS2 = 2, CAM_IFE_IRQ_VIOLATION_STATUS = 3, + CAM_IFE_IRQ_BUS_OVERFLOW_STATUS = 4, CAM_IFE_IRQ_REGISTERS_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index e855a54dc723..48eb7f1b028d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -80,6 +80,7 @@ static struct cam_vfe_camif_ver3_reg_data vfe_480_camif_reg_data = { .enable_diagnostic_hw = 0x1, .pp_camif_cfg_en_shift = 0, .pp_camif_cfg_ife_out_en_shift = 8, + .top_debug_cfg_en = 1, }; static struct cam_vfe_top_ver3_reg_offset_common vfe480_top_common_reg = { @@ -106,6 +107,21 @@ static struct cam_vfe_top_ver3_reg_offset_common vfe480_top_common_reg = { .diag_sensor_status_0 = 0x00000068, .diag_sensor_status_1 = 0x00000098, .bus_overflow_status = 0x0000AA68, + .top_debug_cfg = 0x000000DC, + .top_debug_0 = 0x00000080, + .top_debug_1 = 0x00000084, + .top_debug_2 = 0x00000088, + .top_debug_3 = 0x0000008C, + .top_debug_4 = 0x0000009C, + .top_debug_5 = 0x000000A0, + .top_debug_6 = 0x000000A4, + .top_debug_7 = 0x000000A8, + .top_debug_8 = 0x000000AC, + .top_debug_9 = 0x000000B0, + .top_debug_10 = 0x000000B4, + .top_debug_11 = 0x000000B8, + .top_debug_12 = 0x000000BC, + .top_debug_13 = 0x000000C0, }; static struct cam_vfe_camif_lite_ver3_reg vfe480_camif_rdi[3] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index c9d66ed94e97..221c372f72b1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -48,6 +48,11 @@ static struct cam_vfe_top_ver3_reg_offset_common vfe48x_top_common_reg = { .diag_config = 0x00000050, .diag_sensor_status_0 = 0x00000054, .bus_overflow_status = 0x00001A68, + .top_debug_cfg = 0x00000074, + .top_debug_0 = 0x0000005C, + .top_debug_1 = 0x00000068, + .top_debug_2 = 0x0000006C, + .top_debug_3 = 0x00000070, }; static struct cam_vfe_camif_lite_ver3_reg vfe48x_camif_rdi[4] = { @@ -118,6 +123,7 @@ static struct cam_vfe_camif_lite_ver3_reg_data vfe48x_camif_rdi_reg_data[4] = { .error_irq_mask2 = 0x100, .subscribe_irq_mask1 = 0x3, .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x1, }, { .extern_reg_update_shift = 0, @@ -131,6 +137,7 @@ static struct cam_vfe_camif_lite_ver3_reg_data vfe48x_camif_rdi_reg_data[4] = { .error_irq_mask2 = 0x200, .subscribe_irq_mask1 = 0x30, .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x1, }, { .extern_reg_update_shift = 0, @@ -144,6 +151,7 @@ static struct cam_vfe_camif_lite_ver3_reg_data vfe48x_camif_rdi_reg_data[4] = { .error_irq_mask2 = 0x400, .subscribe_irq_mask1 = 0x300, .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x1, }, { .extern_reg_update_shift = 0, @@ -157,6 +165,7 @@ static struct cam_vfe_camif_lite_ver3_reg_data vfe48x_camif_rdi_reg_data[4] = { .error_irq_mask2 = 0x800, .subscribe_irq_mask1 = 0x3000, .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x1, }, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index bf527440e2d7..e71754098e80 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -17,6 +17,7 @@ #include "cam_vfe_camif_lite_ver3.h" #include "cam_debug_util.h" #include "cam_cdm_util.h" +#include "cam_cpas_api.h" struct cam_vfe_mux_camif_lite_data { void __iomem *mem_base; @@ -142,9 +143,8 @@ static int cam_vfe_camif_lite_err_irq_top_half( evt_payload->irq_reg_val[i] = cam_io_r(camif_lite_priv->mem_base + camif_lite_priv->common_reg->violation_status); - if (error_flag && !soc_private->is_ife_lite) - CAM_INFO(CAM_ISP, "Violation status = 0x%X", - evt_payload->irq_reg_val[i]); + evt_payload->irq_reg_val[++i] = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->bus_overflow_status); th_payload->evt_payload_priv = evt_payload; @@ -308,6 +308,10 @@ skip_core_cfg: memset(err_irq_mask, 0, sizeof(err_irq_mask)); memset(irq_mask, 0, sizeof(irq_mask)); + /* config debug status registers */ + cam_io_w_mb(rsrc_data->reg_data->top_debug_cfg_en, rsrc_data->mem_base + + rsrc_data->common_reg->top_debug_cfg); + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = rsrc_data->reg_data->error_irq_mask0; err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = @@ -726,23 +730,93 @@ static int cam_vfe_camif_lite_process_cmd( return rc; } +static void cam_vfe_camif_lite_overflow_debug_info(uint32_t *status, + struct cam_vfe_mux_camif_lite_data *camif_lite_priv) +{ + uint32_t bus_overflow_status = 0; + struct cam_vfe_soc_private *soc_private = NULL; + uint32_t val0, val1, val2, val3; + + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; + soc_private = camif_lite_priv->soc_info->soc_private; + + if (bus_overflow_status) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + CAM_INFO(CAM_ISP, + "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", + val0, val1, val2); + + } else { + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_0); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_1); + val2 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_2); + val3 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_3); + CAM_INFO(CAM_ISP, + "status_0: 0x%X status_1: 0x%X status_2: 0x%X status_3: 0x%X", + val0, val1, val2, val3); + + if (soc_private->is_ife_lite) + return; + + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_4); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_5); + val2 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_6); + val3 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_7); + CAM_INFO(CAM_ISP, + "status_4: 0x%X status_5: 0x%X status_6: 0x%X status_7: 0x%X", + val0, val1, val2, val3); + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_8); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_9); + val2 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_10); + val3 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_11); + CAM_INFO(CAM_ISP, + "status_8: 0x%X status_9: 0x%X status_10: 0x%X status_11: 0x%X", + val0, val1, val2, val3); + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_12); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_13); + CAM_INFO(CAM_ISP, "status_12: 0x%X status_13: 0x%X", + val0, val1); + } +} + static void cam_vfe_camif_lite_print_status(uint32_t *status, - int err_type, bool is_ife_lite) + int err_type, struct cam_vfe_mux_camif_lite_data *camif_lite_priv) { uint32_t violation_mask = 0x3F00, violation_status = 0; uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; + struct cam_vfe_soc_private *soc_private = NULL; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } - bus_overflow_status = status[CAM_IFE_IRQ_REGISTERS_MAX]; + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; violation_status = status[CAM_IFE_IRQ_VIOLATION_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; + soc_private = camif_lite_priv->soc_info->soc_private; - if (is_ife_lite) + if (soc_private->is_ife_lite) goto ife_lite; if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) { @@ -792,7 +866,8 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "PDLIB / LCR Module hang"); - /* print debug registers here */ + /* print debug registers */ + cam_vfe_camif_lite_overflow_debug_info(status, camif_lite_priv); return; } @@ -874,6 +949,13 @@ ife_lite: CAM_INFO(CAM_ISP, "RDI3 BUS OVERFLOW"); } + if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { + CAM_INFO(CAM_ISP, "RDI hang"); + /* print debug registers */ + cam_vfe_camif_lite_overflow_debug_info(status, camif_lite_priv); + return; + } + if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { if (status_2 & 0x100) CAM_INFO(CAM_ISP, "RDI0 CAMIF VIOLATION"); @@ -942,9 +1024,8 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; struct cam_vfe_soc_private *soc_private = NULL; - uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX + 1]; + uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; int i = 0; - bool is_ife_lite = true; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -961,10 +1042,6 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( return -ENODEV; } - is_ife_lite = soc_private->is_ife_lite; - - memset(irq_status, 0, - sizeof(uint32_t) * (CAM_IFE_IRQ_REGISTERS_MAX + 1)); for (i = 0; i < CAM_IFE_IRQ_REGISTERS_MAX; i++) irq_status[i] = payload->irq_reg_val[i]; @@ -1023,13 +1100,10 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( camif_lite_priv->event_cb(camif_lite_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); - irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = - cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->bus_overflow_status); - ret = CAM_VFE_IRQ_STATUS_OVERFLOW; - cam_vfe_camif_lite_print_status(irq_status, ret, is_ife_lite); + cam_vfe_camif_lite_print_status(irq_status, ret, + camif_lite_priv); if (camif_lite_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_lite_reg_dump(camif_lite_node); @@ -1047,7 +1121,8 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( ret = CAM_VFE_IRQ_STATUS_VIOLATION; - cam_vfe_camif_lite_print_status(irq_status, ret, is_ife_lite); + cam_vfe_camif_lite_print_status(irq_status, ret, + camif_lite_priv); if (camif_lite_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_lite_reg_dump(camif_lite_node); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h index ad8e44ef8e6c..54a38bdf41ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.h @@ -40,6 +40,7 @@ struct cam_vfe_camif_lite_ver3_reg_data { uint32_t error_irq_mask2; uint32_t subscribe_irq_mask1; uint32_t enable_diagnostic_hw; + uint32_t top_debug_cfg_en; }; struct cam_vfe_camif_lite_ver3_hw_info { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 450d03428c63..e4a05a1031b7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -141,9 +141,8 @@ static int cam_vfe_camif_ver3_err_irq_top_half( evt_payload->irq_reg_val[i] = cam_io_r(camif_priv->mem_base + camif_priv->common_reg->violation_status); - if (error_flag) - CAM_INFO(CAM_ISP, "Violation status = 0x%X", - evt_payload->irq_reg_val[i]); + evt_payload->irq_reg_val[++i] = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->bus_overflow_status); th_payload->evt_payload_priv = evt_payload; @@ -374,6 +373,10 @@ static int cam_vfe_camif_ver3_resource_start( return -ENODEV; } + /* config debug status registers */ + cam_io_w_mb(rsrc_data->reg_data->top_debug_cfg_en, rsrc_data->mem_base + + rsrc_data->common_reg->top_debug_cfg); + /*config vfe core*/ val = (rsrc_data->pix_pattern << rsrc_data->reg_data->pixel_pattern_shift); @@ -733,8 +736,76 @@ static int cam_vfe_camif_ver3_process_cmd( return rc; } + +static void cam_vfe_camif_ver3_overflow_debug_info(uint32_t *status, + struct cam_vfe_mux_camif_ver3_data *camif_priv) +{ + struct cam_vfe_soc_private *soc_private; + uint32_t bus_overflow_status; + uint32_t val0, val1, val2, val3; + + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; + soc_private = camif_priv->soc_info->soc_private; + + if (bus_overflow_status) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + CAM_INFO(CAM_ISP, + "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", + val0, val1, val2); + } else { + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_0); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_1); + val2 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_2); + val3 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_3); + CAM_INFO(CAM_ISP, + "status_0: 0x%X status_1: 0x%X status_2: 0x%X status_3: 0x%X", + val0, val1, val2, val3); + + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_4); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_5); + val2 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_6); + val3 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_7); + CAM_INFO(CAM_ISP, + "status_4: 0x%X status_5: 0x%X status_6: 0x%X status_7: 0x%X", + val0, val1, val2, val3); + + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_8); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_9); + val2 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_10); + val3 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_11); + CAM_INFO(CAM_ISP, + "status_8: 0x%X status_9: 0x%X status_10: 0x%X status_11: 0x%X", + val0, val1, val2, val3); + + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_12); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_13); + CAM_INFO(CAM_ISP, "status_12: 0x%X status_13: 0x%X", + val0, val1); + } + +} + static void cam_vfe_camif_ver3_print_status(uint32_t *status, - int err_type) + int err_type, struct cam_vfe_mux_camif_ver3_data *camif_priv) { uint32_t violation_mask = 0x3F, module_id = 0; uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; @@ -744,7 +815,7 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, return; } - bus_overflow_status = status[CAM_IFE_IRQ_REGISTERS_MAX]; + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; @@ -829,6 +900,7 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "PIXEL PIPE Module hang"); /* print debug registers */ + cam_vfe_camif_ver3_overflow_debug_info(status, camif_priv); return; } @@ -1100,7 +1172,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_mux_camif_ver3_data *camif_priv; struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; - uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX + 1] = {0}; + uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; int i = 0; if (!handler_priv || !evt_payload_priv) { @@ -1177,13 +1249,9 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); - irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = - cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->bus_overflow_status); - ret = CAM_VFE_IRQ_STATUS_OVERFLOW; - cam_vfe_camif_ver3_print_status(irq_status, ret); + cam_vfe_camif_ver3_print_status(irq_status, ret, camif_priv); if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_ver3_reg_dump(camif_node); @@ -1198,7 +1266,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_VIOLATION; - cam_vfe_camif_ver3_print_status(irq_status, ret); + cam_vfe_camif_ver3_print_status(irq_status, ret, camif_priv); if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_ver3_reg_dump(camif_node); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h index 3c82ca2ba7d6..40d8e40ae852 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -56,6 +56,7 @@ struct cam_vfe_camif_ver3_reg_data { uint32_t enable_diagnostic_hw; uint32_t pp_camif_cfg_en_shift; uint32_t pp_camif_cfg_ife_out_en_shift; + uint32_t top_debug_cfg_en; }; struct cam_vfe_camif_ver3_hw_info { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h index 1ae8e5d54a4d..dd0bb94c42c7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -48,6 +48,21 @@ struct cam_vfe_top_ver3_reg_offset_common { uint32_t diag_sensor_status_0; uint32_t diag_sensor_status_1; uint32_t bus_overflow_status; + uint32_t top_debug_cfg; + uint32_t top_debug_0; + uint32_t top_debug_1; + uint32_t top_debug_2; + uint32_t top_debug_3; + uint32_t top_debug_4; + uint32_t top_debug_5; + uint32_t top_debug_6; + uint32_t top_debug_7; + uint32_t top_debug_8; + uint32_t top_debug_9; + uint32_t top_debug_10; + uint32_t top_debug_11; + uint32_t top_debug_12; + uint32_t top_debug_13; }; struct cam_vfe_camif_common_cfg { From 2c55550c19d2f4bd75f2230a9db076ae343a30fa Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 11 Jun 2019 11:40:17 -0700 Subject: [PATCH 011/790] msm: camera: isp: Add debugfs parameter for state monitor dump This change adds a debugfs parameter to enable isp context state monitor dump rather than always print by default. This change also changes isp context substate to HALT only after stop hw is complete. Change-Id: I1025a46e9be63b4ee5808c2eb44672687d901c2e Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 44 ++++++++++++++++++++++++++----- drivers/cam_isp/cam_isp_context.h | 12 +++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 282bf55cbf4f..84f5e4937a9e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -22,6 +22,8 @@ static const char isp_dev_name[] = "cam-isp"; +static struct cam_isp_ctx_debug isp_ctx_debug; + #define INC_STATE_MONITOR_HEAD(head) \ (atomic64_add_return(1, head) % \ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) @@ -3440,12 +3442,6 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( (struct cam_isp_context *) ctx->ctx_priv; struct cam_isp_stop_args stop_isp; - /* Mask off all the incoming hardware events */ - spin_lock_bh(&ctx->lock); - 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); - /* stop hw first */ if (ctx_isp->hw_ctx) { stop.ctxt_to_hw_map = ctx_isp->hw_ctx; @@ -3462,6 +3458,12 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( &stop); } + /* Mask off all the incoming hardware events */ + spin_lock_bh(&ctx->lock); + 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); + while (!list_empty(&ctx->pending_req_list)) { req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); @@ -3725,7 +3727,8 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, } else { CAM_DBG(CAM_ISP, "No handle function for substate %d", ctx_isp->substate_activated); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp); + if (isp_ctx_debug.enable_state_monitor_dump) + __cam_isp_ctx_dump_state_monitor_array(ctx_isp); } CAM_DBG(CAM_ISP, "Exit: State %d Substate %d", @@ -3867,6 +3870,31 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, return rc; } +static int cam_isp_context_debug_register(void) +{ + isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", + NULL); + + if (!isp_ctx_debug.dentry) { + CAM_ERR(CAM_ISP, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_u32("enable_state_monitor_dump", + 0644, + isp_ctx_debug.dentry, + &isp_ctx_debug.enable_state_monitor_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_state_monitor_dump"); + goto err; + } + + return 0; + +err: + debugfs_remove_recursive(isp_ctx_debug.dentry); + return -ENOMEM; +} + int cam_isp_context_init(struct cam_isp_context *ctx, struct cam_context *ctx_base, struct cam_req_mgr_kmd_ops *crm_node_intf, @@ -3918,6 +3946,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx, CAM_ISP_CTX_ACTIVATED_MAX; } atomic64_set(&ctx->state_monitor_head, -1); + + cam_isp_context_debug_register(); err: return rc; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index bbf39b5617cf..1f5bd1048f5b 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -70,6 +70,18 @@ enum cam_isp_state_change_trigger { CAM_ISP_STATE_CHANGE_TRIGGER_MAX }; +/** + * struct cam_isp_ctx_debug - Contains debug parameters + * + * @dentry: Debugfs entry + * @enable_state_monitor_dump: Enable isp state monitor dump + * + */ +struct cam_isp_ctx_debug { + struct dentry *dentry; + uint32_t enable_state_monitor_dump; +}; + /** * struct cam_isp_ctx_irq_ops - Function table for handling IRQ callbacks * From 657d77d87d2474394bc22a50a62c9a0aecb1a16f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 19 Jun 2019 12:17:30 -0700 Subject: [PATCH 012/790] msm: camera: icp: Protect icp context access at time of pagefault Take mutex before acessing icp context to prevent improper free. Change-Id: If2fd2c66dd9a00f1ab5c9ec1710573c2921dce6a Signed-off-by: Prakasha Nayak --- drivers/cam_icp/cam_icp_context.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 86876a35b671..6e043fd95c63 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -37,6 +37,14 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova, return -EINVAL; } + mutex_lock(&ctx->ctx_mutex); + + if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) { + CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d", + ctx->ctx_id, ctx->state); + goto end; + } + CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d", ctx->ctx_id, ctx->state); @@ -55,6 +63,8 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova, req->request_id, rc); } +end: + mutex_unlock(&ctx->ctx_mutex); return rc; } From eedac0e21c2c6158976b501775778750d06845c7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 19 Jun 2019 12:19:58 -0700 Subject: [PATCH 013/790] msm: camera: Correct the return logic for error case Currently for the flush request error case, mutex unlock is executed without mutex lock which result in instability of system. This change returns with appropriate error code if error occurs. Change-Id: I2ff0056002c7d96a7100295f2ed6ba5cc0da2254 Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_req_mgr_core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 9f11077f05c4..e6c9d97b1c97 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3057,14 +3057,12 @@ int cam_req_mgr_flush_requests( if (!flush_info) { CAM_ERR(CAM_CRM, "flush req is NULL"); - rc = -EFAULT; - goto end; + return -EFAULT; } if (flush_info->flush_type >= CAM_REQ_MGR_FLUSH_TYPE_MAX) { CAM_ERR(CAM_CRM, "incorrect flush type %x", flush_info->flush_type); - rc = -EINVAL; - goto end; + return -EINVAL; } mutex_lock(&g_crm_core_dev->crm_lock); From af6455ddfd65a021203668a6d9b8cd1c36bfe077 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 24 May 2019 16:51:50 -0700 Subject: [PATCH 014/790] msm: camera: cpas: Add updated QoS settings for kona Adding updated values for registers in camnoc address space which determine QoS for different axi bw paths. Change-Id: I6a24b7650f542938fd9720ae86a0330b5d4fd048 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 106 +++++++------------ 1 file changed, 38 insertions(+), 68 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h index d4782d7df110..cbb521d30778 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -203,27 +203,25 @@ static struct cam_camnoc_specific .port_type = CAM_CAMNOC_CDM, .enable = true, .priority_lut_low = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ - .value = 0x22222222, + .value = 0x0, }, .priority_lut_high = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ - .value = 0x22222222, + .value = 0x0, }, .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x38, /* CDM_URGENCY_LOW */ - .mask = 0x7, /* CDM_URGENCY_LOW_READ_MASK */ - .shift = 0x0, /* CDM_URGENCY_LOW_READ_SHIFT */ - .value = 0x2, + .value = 0x3, }, .danger_lut = { .enable = false, @@ -247,25 +245,25 @@ static struct cam_camnoc_specific .port_type = CAM_CAMNOC_FD, .enable = true, .priority_lut_low = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x630, /* FD_PRIORITYLUT_LOW */ - .value = 0x44444444, + .value = 0x0, }, .priority_lut_high = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x634, /* FD_PRIORITYLUT_HIGH */ - .value = 0x44444444, + .value = 0x0, }, .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x638, /* FD_URGENCY_LOW */ - .value = 0x2, + .value = 0x33, }, .danger_lut = { .enable = false, @@ -305,13 +303,9 @@ static struct cam_camnoc_specific .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ - /* IFE_LINEAR_URGENCY_LOW_WRITE_MASK */ - .mask = 0x70, - /* IFE_LINEAR_URGENCY_LOW_WRITE_SHIFT */ - .shift = 0x4, - .value = 3, + .value = 0x1030, }, .danger_lut = { .enable = true, @@ -323,7 +317,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ - .value = 0x1, + .value = 0xFFF0, }, .ubwc_ctl = { /* @@ -338,41 +332,37 @@ static struct cam_camnoc_specific .port_type = CAM_CAMNOC_IFE_RDI_RD, .enable = true, .priority_lut_low = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x0, }, .priority_lut_high = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ - .value = 0x66666666, + .value = 0x0, }, .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ - /* IFE_RDI_RD_URGENCY_LOW_WRITE_MASK */ - .mask = 0x70, - /* IFE_RDI_RD_URGENCY_LOW_WRITE_SHIFT */ - .shift = 0x4, - .value = 3, + .value = 0x3, }, .danger_lut = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ - .value = 0xFFFFFF00, + .value = 0x0, }, .safe_lut = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ - .value = 0x1, + .value = 0x0, }, .ubwc_ctl = { /* @@ -403,13 +393,9 @@ static struct cam_camnoc_specific .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x1438, /* IFE_RDI_WR_URGENCY_LOW */ - /* IFE_RDI_WR_URGENCY_LOW_WRITE_MASK */ - .mask = 0x70, - /* IFE_RDI_WR_URGENCY_LOW_WRITE_SHIFT */ - .shift = 0x4, - .value = 3, + .value = 0x1030, }, .danger_lut = { .enable = true, @@ -421,7 +407,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_SAFELUT_LOW */ - .value = 0x1, + .value = 0xFFF0, }, .ubwc_ctl = { /* @@ -452,13 +438,9 @@ static struct cam_camnoc_specific .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x1A38, /* IFE_UBWC_STATS_URGENCY_LOW */ - /* IFE_UBWC_STATS_URGENCY_LOW_WRITE_MASK */ - .mask = 0x70, - /* IFE_UBWC_STATS_URGENCY_LOW_WRITE_SHIFT */ - .shift = 0x4, - .value = 3, + .value = 0x1030, }, .danger_lut = { .enable = true, @@ -470,7 +452,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_SAFELUT_LOW */ - .value = 0x1, + .value = 0xFFF0, }, .ubwc_ctl = { /* @@ -489,14 +471,14 @@ static struct cam_camnoc_specific .port_type = CAM_CAMNOC_IPE0_RD, .enable = true, .priority_lut_low = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ .value = 0x33333333, }, .priority_lut_high = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -505,13 +487,9 @@ static struct cam_camnoc_specific .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ - /* IPE0_RD_URGENCY_LOW_READ_MASK */ - .mask = 0x7, - /* IPE0_RD_URGENCY_LOW_READ_SHIFT */ - .shift = 0x0, - .value = 3, + .value = 0x3, }, .danger_lut = { .enable = false, @@ -544,14 +522,14 @@ static struct cam_camnoc_specific .port_type = CAM_CAMNOC_IPE1_BPS_RD, .enable = true, .priority_lut_low = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ .value = 0x33333333, }, .priority_lut_high = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ @@ -560,13 +538,9 @@ static struct cam_camnoc_specific .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ - /* IPE1_BPS_RD_URGENCY_LOW_READ_MASK */ - .mask = 0x7, - /* IPE1_BPS_RD_URGENCY_LOW_READ_SHIFT */ - .shift = 0x0, - .value = 3, + .value = 0x3, }, .danger_lut = { .enable = false, @@ -615,13 +589,9 @@ static struct cam_camnoc_specific .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, - .masked_value = 1, + .masked_value = 0, .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ - /* IPE_BPS_WR_URGENCY_LOW_WRITE_MASK */ - .mask = 0x70, - /* IPE_BPS_WR_URGENCY_LOW_WRITE_SHIFT */ - .shift = 0x4, - .value = 3, + .value = 0x30, }, .danger_lut = { .enable = false, From e7e5e70f17403c3eb8be3076d5d020cab7b984c0 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 4 Jun 2019 16:46:56 -0700 Subject: [PATCH 015/790] msm: camera: ife: Enable sample drop on CSID RDI paths This change enables CSID sample drop on RDI paths by default. The sample drop pattern, as always, is set to 0 at init. This allows the userspace driver to simply program sample drop pattern on desired RDI paths to obtain sample dropped output without having to also overwrite config register to enable drop. This change also takes care of programming max value to sample drop period on version 480 hardware due to hardware limitations. It also adds a separate header file for CSID Lite version 480 hardware. Change-Id: I6e8ace1df3241b7ab4e34d9a13b382f5dde8b4f3 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 7 + .../isp_hw/ife_csid_hw/cam_ife_csid480.h | 2 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 37 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 + .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c | 13 +- .../isp_hw/ife_csid_hw/cam_ife_csid_lite480.h | 339 ++++++++++++++++++ .../isp_hw/include/cam_ife_csid_hw_intf.h | 2 + 7 files changed, 392 insertions(+), 12 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 2895e6f9d824..fac5c41aa1a4 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1568,6 +1568,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( csid_acquire.out_port = in_port->data; csid_acquire.node_res = NULL; csid_acquire.crop_enable = crop_enable; + csid_acquire.drop_enable = false; hw_intf = cid_res->hw_res[i]->hw_intf; @@ -1697,6 +1698,12 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; csid_acquire.node_res = NULL; + /* + * Enable RDI pixel drop by default. CSID will enable only for + * ver 480 HW to allow userspace to control pixel drop pattern. + */ + csid_acquire.drop_enable = true; + /* Enable RDI crop for single ife use case only */ if (in_port->usage_type) csid_acquire.crop_enable = false; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h index c18a21ff7c32..f8eee4109b65 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -354,6 +354,8 @@ static struct cam_ife_csid_common_reg_offset .plain_fmt_shit_val = 10, .crop_v_en_shift_val = 6, .crop_h_en_shift_val = 5, + .drop_v_en_shift_val = 4, + .drop_h_en_shift_val = 3, .crop_shift = 16, .ipp_irq_mask_all = 0x7FFF, .rdi_irq_mask_all = 0x7FFF, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index cce05296f04a..a41d203d4402 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1015,6 +1015,7 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->start_line = reserve->in_port->line_start; path_data->end_line = reserve->in_port->line_stop; path_data->crop_enable = reserve->crop_enable; + path_data->drop_enable = reserve->drop_enable; CAM_DBG(CAM_ISP, "Res id: %d height:%d line_start %d line_stop %d crop_en %d", @@ -1589,10 +1590,6 @@ static int cam_ife_csid_init_config_pxl_path( csid_reg->cmn_reg->crop_v_en_shift_val) | (1 << 1) | 1; - val |= (1 << pxl_reg->pix_store_en_shift_val); - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + - pxl_reg->csid_pxl_cfg0_addr); - rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); if (rc) { CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); @@ -1600,6 +1597,16 @@ static int cam_ife_csid_init_config_pxl_path( } CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); + if (camera_hw_version == CAM_CPAS_TITAN_480_V100) + val |= (path_data->drop_enable << + csid_reg->cmn_reg->drop_h_en_shift_val) | + (path_data->drop_enable << + csid_reg->cmn_reg->drop_v_en_shift_val); + + val |= (1 << pxl_reg->pix_store_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + if (path_data->is_valid_vc1_dt1 && camera_hw_version == CAM_CPAS_TITAN_480_V100) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -2012,9 +2019,6 @@ static int cam_ife_csid_init_config_rdi_path( csid_reg->cmn_reg->crop_v_en_shift_val) | (1 << 2) | 3; - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + - csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); - rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); if (rc) { CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); @@ -2022,6 +2026,15 @@ static int cam_ife_csid_init_config_rdi_path( } CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); + if (camera_hw_version == CAM_CPAS_TITAN_480_V100) + val |= (path_data->drop_enable << + csid_reg->cmn_reg->drop_h_en_shift_val) | + (path_data->drop_enable << + csid_reg->cmn_reg->drop_v_en_shift_val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + if (path_data->is_valid_vc1_dt1 && camera_hw_version == CAM_CPAS_TITAN_480_V100) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -2077,8 +2090,16 @@ static int cam_ife_csid_init_config_rdi_path( /* set pixel drop pattern to 0 and period to 1 */ cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_pattern_addr); - cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + + /* Write max value to pixel drop period due to a bug in ver 480 HW */ + if (camera_hw_version == CAM_CPAS_TITAN_480_V100 && + path_data->drop_enable) + cam_io_w_mb(0x1F, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_period_addr); + else + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_period_addr); + /* set line drop pattern to 0 and period to 1 */ cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_rpp_line_drop_pattern_addr); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index a3c54fed7c03..a68c56188c5f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -303,6 +303,8 @@ struct cam_ife_csid_common_reg_offset { uint32_t plain_fmt_shit_val; uint32_t crop_v_en_shift_val; uint32_t crop_h_en_shift_val; + uint32_t drop_v_en_shift_val; + uint32_t drop_h_en_shift_val; uint32_t crop_shift; uint32_t ipp_irq_mask_all; uint32_t rdi_irq_mask_all; @@ -410,6 +412,7 @@ struct cam_ife_csid_cid_data { * @out_format: output format * @crop_enable: crop is enable or disabled, if enabled * then remaining parameters are valid. + * @drop_enable: flag to indicate pixel drop enable or disable * @start_pixel: start pixel * @end_pixel: end_pixel * @width: width @@ -435,6 +438,7 @@ struct cam_ife_csid_path_cfg { uint32_t in_format; uint32_t out_format; bool crop_enable; + bool drop_enable; uint32_t start_pixel; uint32_t end_pixel; uint32_t width; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c index 0a80f1a51cf5..07d555b17009 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c @@ -5,27 +5,32 @@ #include #include "cam_ife_csid_lite17x.h" +#include "cam_ife_csid_lite480.h" #include "cam_ife_csid_core.h" #include "cam_ife_csid_dev.h" #define CAM_CSID_LITE_DRV_NAME "csid_lite" -static struct cam_ife_csid_hw_info cam_ife_csid_lite_hw_info = { +static struct cam_ife_csid_hw_info cam_ife_csid_lite_17x_hw_info = { .csid_reg = &cam_ife_csid_lite_17x_reg_offset, }; +static struct cam_ife_csid_hw_info cam_ife_csid_lite_480_hw_info = { + .csid_reg = &cam_ife_csid_lite_480_reg_offset, +}; + static const struct of_device_id cam_ife_csid_lite_dt_match[] = { { .compatible = "qcom,csid-lite170", - .data = &cam_ife_csid_lite_hw_info, + .data = &cam_ife_csid_lite_17x_hw_info, }, { .compatible = "qcom,csid-lite175", - .data = &cam_ife_csid_lite_hw_info, + .data = &cam_ife_csid_lite_17x_hw_info, }, { .compatible = "qcom,csid-lite480", - .data = &cam_ife_csid_lite_hw_info, + .data = &cam_ife_csid_lite_480_hw_info, }, {} }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h new file mode 100644 index 000000000000..ca4373b62814 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_LITE_480_H_ +#define _CAM_IFE_CSID_LITE_480_H_ + +#include "cam_ife_csid_core.h" + +static struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_480_rdi_0_reg_offset = { + .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_err_recovery_cfg0_addr = 0x2b0, + .csid_rdi_err_recovery_cfg1_addr = 0x2b4, + .csid_rdi_err_recovery_cfg2_addr = 0x2b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x2bc, + .csid_rdi_byte_cntr_ping_addr = 0x2e0, + .csid_rdi_byte_cntr_pong_addr = 0x2e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_480_rdi_1_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_err_recovery_cfg0_addr = 0x3b0, + .csid_rdi_err_recovery_cfg1_addr = 0x3b4, + .csid_rdi_err_recovery_cfg2_addr = 0x3b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x3bc, + .csid_rdi_byte_cntr_ping_addr = 0x3e0, + .csid_rdi_byte_cntr_pong_addr = 0x3e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_480_rdi_2_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_err_recovery_cfg0_addr = 0x4b0, + .csid_rdi_err_recovery_cfg1_addr = 0x4b4, + .csid_rdi_err_recovery_cfg2_addr = 0x4b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x4bc, + .csid_rdi_byte_cntr_ping_addr = 0x4e0, + .csid_rdi_byte_cntr_pong_addr = 0x4e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_lite_480_rdi_3_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_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_err_recovery_cfg0_addr = 0x5b0, + .csid_rdi_err_recovery_cfg1_addr = 0x5b4, + .csid_rdi_err_recovery_cfg2_addr = 0x5b8, + .csid_rdi_multi_vcdt_cfg0_addr = 0x5bc, + .csid_rdi_byte_cntr_ping_addr = 0x5e0, + .csid_rdi_byte_cntr_pong_addr = 0x5e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_csi2_rx_reg_offset + cam_ife_csid_lite_480_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_de_scramble_cfg0_addr = 0x114, + .csid_csi2_rx_de_scramble_cfg1_addr = 0x118, + .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, + + .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 = 0x3, +}; + +static struct cam_ife_csid_csi2_tpg_reg_offset + cam_ife_csid_lite_480_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_lite_480_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 = 4, + .minor_version = 8, + .version_incr = 0, + .num_rdis = 4, + .num_pix = 0, + .num_ppp = 0, + .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, + .drop_v_en_shift_val = 4, + .drop_h_en_shift_val = 3, + .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, +}; + +static struct cam_ife_csid_reg_offset cam_ife_csid_lite_480_reg_offset = { + .cmn_reg = &cam_ife_csid_lite_480_cmn_reg_offset, + .csi2_reg = &cam_ife_csid_lite_480_csi2_reg_offset, + .ipp_reg = NULL, + .ppp_reg = NULL, + .rdi_reg = { + &cam_ife_csid_lite_480_rdi_0_reg_offset, + &cam_ife_csid_lite_480_rdi_1_reg_offset, + &cam_ife_csid_lite_480_rdi_2_reg_offset, + &cam_ife_csid_lite_480_rdi_3_reg_offset, + }, + .tpg_reg = &cam_ife_csid_lite_480_tpg_reg_offset, +}; + +#endif /*_CAM_IFE_CSID_LITE480_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 247dfc5960fb..777dfdb5d145 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -115,6 +115,7 @@ struct cam_isp_in_port_generic_info { * reserve * @node_res : Reserved resource structure pointer * @crop_enable : Flag to indicate CSID crop enable + * @drop_enable : Flag to indicate CSID drop enable * */ struct cam_csid_hw_reserve_resource_args { @@ -127,6 +128,7 @@ struct cam_csid_hw_reserve_resource_args { uint32_t cid; struct cam_isp_resource_node *node_res; bool crop_enable; + bool drop_enable; }; /** From a52b95db19457a892f69c2df188065198a56720d Mon Sep 17 00:00:00 2001 From: Abhilash Kumar Date: Wed, 19 Jun 2019 16:53:51 +0530 Subject: [PATCH 016/790] msm: camera: cpas: QoS setting for IFE1 It corrects QoS value for IFE1. Change-Id: Iab70f9262cb275be575704206f09c820327564ab Signed-off-by: Abhilash Kumar --- drivers/cam_cpas/cpas_top/cpastop_v175_130.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h index fe6e274c5668..43c1068cc22c 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h @@ -387,7 +387,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3248, /* SPECIFIC_IFE1_SAFELUT_LOW */ - .value = 0xF, + .value = 0xFFFFFFFF, }, .ubwc_ctl = { /* From 146826aa4158127367909d4fb83960622bdce422 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 29 May 2019 10:24:40 -0700 Subject: [PATCH 017/790] msm: camera: eeprom: Fix OOB condition for memory map count Fix OOB check for memory map count to access correct memory map. Change-Id: Ifa3d323103725e4df57e86295bb7567835654b71 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index b211471adf00..c067ff08c3ae 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -435,7 +435,8 @@ static int32_t cam_eeprom_parse_memory_map( validate_size = sizeof(struct cam_cmd_unconditional_wait); if (remain_buf_len < validate_size || - *num_map >= MSM_EEPROM_MAX_MEM_MAP_CNT) { + *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT * + MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) { CAM_ERR(CAM_EEPROM, "not enough buffer"); return -EINVAL; } @@ -445,7 +446,9 @@ static int32_t cam_eeprom_parse_memory_map( if (i2c_random_wr->header.count == 0 || i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT || - (size_t)*num_map > U16_MAX - i2c_random_wr->header.count) { + (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT * + MSM_EEPROM_MEMORY_MAP_MAX_SIZE) - + i2c_random_wr->header.count)) { CAM_ERR(CAM_EEPROM, "OOB Error"); return -EINVAL; } From 326d40f7f167ef23a0190d77aa7fb833924db9b2 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 18 Jun 2019 15:51:26 -0700 Subject: [PATCH 018/790] msm: camera: eeprom: Increase memory map count For write operation while read memory memptr should not need to increase as it leads to crash. This change removes that increase opertion. Also, increasing map count to support more data reading for eeprom. Change-Id: Ie71deb225c2513e7c18229d174a9a0e129fdd1f7 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c | 1 - drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index c067ff08c3ae..c1320d97f644 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -70,7 +70,6 @@ static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl, rc); return rc; } - memptr = block->mapdata + emap[j].mem.valid_size; } if (emap[j].pageen.valid_size) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h index 6bf08d11ed6a..41817e97eae1 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -30,7 +30,7 @@ #define PROPERTY_MAXSIZE 32 #define MSM_EEPROM_MEMORY_MAP_MAX_SIZE 80 -#define MSM_EEPROM_MAX_MEM_MAP_CNT 8 +#define MSM_EEPROM_MAX_MEM_MAP_CNT 100 #define MSM_EEPROM_MEM_MAP_PROPERTIES_CNT 8 enum cam_eeprom_state { From c952930533a5ed73de5b7dc76e9dd73ed9c56715 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Mon, 24 Jun 2019 16:48:27 -0700 Subject: [PATCH 019/790] msm: camera: isp: Add CSID binning Add support to configure CSID binning Change-Id: I09b76b287c243149c89cba958a786f7476c8addb Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 4 ++++ .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h | 2 ++ .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 8 ++++++++ .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h | 3 +++ .../isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h | 2 ++ .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 8 ++++++++ 6 files changed, 27 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index fac5c41aa1a4..75f157f0d5b8 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2147,6 +2147,8 @@ static int cam_ife_mgr_acquire_get_unified_structure_v0( port_info->dsp_mode = in->dsp_mode; port_info->hbi_cnt = in->hbi_cnt; port_info->cust_node = 0; + port_info->horizontal_bin = 0; + port_info->qcfa_bin = 0; port_info->num_out_res = in->num_out_res; port_info->data = kcalloc(in->num_out_res, @@ -2246,6 +2248,8 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2( port_info->dsp_mode = in->dsp_mode; port_info->hbi_cnt = in->hbi_cnt; port_info->cust_node = in->cust_node; + port_info->horizontal_bin = in->horizontal_bin; + port_info->qcfa_bin = in->qcfa_bin; port_info->num_out_res = in->num_out_res; port_info->data = kcalloc(in->num_out_res, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h index f8eee4109b65..b545ccc2a246 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -50,6 +50,8 @@ static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_480_ipp_reg_offset = { /* configurations */ .pix_store_en_shift_val = 7, .early_eof_en_shift_val = 29, + .horizontal_bin_en_shift_val = 2, + .quad_cfa_bin_en_shift_val = 30, .ccif_violation_en = 1, .overflow_ctrl_en = 1, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index a41d203d4402..252c1a5aa36a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1016,6 +1016,8 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->end_line = reserve->in_port->line_stop; path_data->crop_enable = reserve->crop_enable; path_data->drop_enable = reserve->drop_enable; + path_data->horizontal_bin = reserve->in_port->horizontal_bin; + path_data->qcfa_bin = reserve->in_port->qcfa_bin; CAM_DBG(CAM_ISP, "Res id: %d height:%d line_start %d line_stop %d crop_en %d", @@ -1603,6 +1605,12 @@ static int cam_ife_csid_init_config_pxl_path( (path_data->drop_enable << csid_reg->cmn_reg->drop_v_en_shift_val); + if (path_data->horizontal_bin || path_data->qcfa_bin) { + val |= (1 << pxl_reg->horizontal_bin_en_shift_val); + if (path_data->qcfa_bin) + val |= (1 << pxl_reg->quad_cfa_bin_en_shift_val); + } + val |= (1 << pxl_reg->pix_store_en_shift_val); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index a68c56188c5f..3e998858b596 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -133,6 +133,7 @@ struct cam_ife_csid_pxl_reg_offset { /* configuration */ uint32_t pix_store_en_shift_val; uint32_t early_eof_en_shift_val; + uint32_t horizontal_bin_en_shift_val; uint32_t quad_cfa_bin_en_shift_val; uint32_t ccif_violation_en; uint32_t overflow_ctrl_en; @@ -448,6 +449,8 @@ struct cam_ife_csid_path_cfg { enum cam_isp_hw_sync_mode sync_mode; uint32_t master_idx; uint64_t clk_rate; + uint32_t horizontal_bin; + uint32_t qcfa_bin; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 777dfdb5d145..d8ba811c7ad5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -95,6 +95,8 @@ struct cam_isp_in_port_generic_info { uint32_t hbi_cnt; uint32_t cust_node; uint32_t num_out_res; + uint32_t horizontal_bin; + uint32_t qcfa_bin; struct cam_isp_out_port_generic_info *data; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index e4a05a1031b7..bbc25bc96045 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -49,6 +49,8 @@ struct cam_vfe_mux_camif_ver3_data { bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; + uint32_t horizontal_bin; + uint32_t qcfa_bin; }; static int cam_vfe_camif_ver3_get_evt_payload( @@ -250,6 +252,9 @@ int cam_vfe_camif_ver3_acquire_resource( camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop; camif_data->first_line = acquire_data->vfe_in.in_port->line_start; camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; + camif_data->horizontal_bin = + acquire_data->vfe_in.in_port->horizontal_bin; + camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin; camif_data->event_cb = acquire_data->event_cb; camif_data->priv = acquire_data->priv; @@ -441,6 +446,9 @@ static int cam_vfe_camif_ver3_resource_start( * frame width. We use '/ 4' instead of '/ 2' * cause it is multipixel path */ + if (rsrc_data->horizontal_bin || rsrc_data->qcfa_bin) + epoch0_line_cfg >>= 1; + epoch1_line_cfg = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; computed_epoch_line_cfg = (epoch1_line_cfg << 16) | From a0129f5975378d62be93617c5f85f94fb1702aa6 Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Thu, 13 Jun 2019 06:16:03 +0530 Subject: [PATCH 020/790] msm: camera: icp: setting QoS for a5 firmware It sets the bus access priority for A5 core. Change-Id: Ic110bc10d14ea512f79dfff361e61db4e9db6fe7 Signed-off-by: Alok Pandey --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 9 +++++++++ drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 2 ++ drivers/cam_icp/icp_hw/a5_hw/a5_soc.c | 7 +++++++ drivers/cam_icp/icp_hw/a5_hw/a5_soc.h | 1 + 4 files changed, 19 insertions(+) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index baac5ff5976c..f7d94b2ce679 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -241,6 +241,7 @@ int cam_a5_init_hw(void *device_priv, struct cam_hw_info *a5_dev = device_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_a5_device_core_info *core_info = NULL; + struct a5_soc_info *a5_soc_info; struct cam_icp_cpas_vote cpas_vote; int rc = 0; @@ -258,6 +259,8 @@ int cam_a5_init_hw(void *device_priv, return -EINVAL; } + a5_soc_info = soc_info->soc_private; + cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; cpas_vote.axi_vote.num_paths = 1; @@ -291,6 +294,12 @@ int cam_a5_init_hw(void *device_priv, CAM_ERR(CAM_ICP, "cpas stop is failed"); else core_info->cpas_start = false; + } else { + CAM_DBG(CAM_ICP, "a5_qos %d", a5_soc_info->a5_qos_val); + if (a5_soc_info->a5_qos_val) + cam_io_w_mb(a5_soc_info->a5_qos_val, + soc_info->reg_map[A5_SIERRA_BASE].mem_base + + ICP_SIERRA_A5_CSR_ACCESS); } error: diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h index a5c0fffde1d1..6c46b3ac8784 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -20,6 +20,8 @@ #define A5_WDT_0 0x2 #define A5_WDT_1 0x4 +#define ICP_SIERRA_A5_CSR_ACCESS 0x3C + #define ELF_GUARD_PAGE (2 * 1024 * 1024) struct cam_a5_device_hw_info { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c index bcdc12632356..62a88ac87f67 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c @@ -40,6 +40,13 @@ static int cam_a5_get_dt_properties(struct cam_hw_soc_info *soc_info) goto end; } + rc = of_property_read_u32(of_node, "qos-val", + &a5_soc_info->a5_qos_val); + if (rc < 0) { + CAM_WARN(CAM_ICP, "QoS need not be set"); + a5_soc_info->a5_qos_val = 0; + } + ubwc_cfg_ext = &a5_soc_info->uconfig.ubwc_cfg_ext; num_ubwc_cfg = of_property_count_u32_elems(of_node, "ubwc-ipe-fetch-cfg"); diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h index eadf9d726696..c44bcde120fb 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h @@ -20,6 +20,7 @@ struct a5_ubwc_cfg_ext { struct a5_soc_info { char *fw_name; bool ubwc_config_ext; + uint32_t a5_qos_val; union { uint32_t ubwc_cfg[ICP_UBWC_MAX]; struct a5_ubwc_cfg_ext ubwc_cfg_ext; From f1135e91b97e2c28e84e389a83714e9a67070675 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 5 Jul 2019 13:10:11 -0700 Subject: [PATCH 021/790] msm: camara: sync: Add callback registration logic for synx Synx driver is dependent on camera driver for registering callback functions of sync driver. This change invert the logic, and camera driver will register the callback functions for synx driver at the time of sync driver probe. Change-Id: I2dbee15ba4c7a9dde336a4bb1f2a4dddcd90348b Signed-off-by: Jigarkumar Zala --- drivers/cam_sync/Makefile | 1 + drivers/cam_sync/cam_sync.c | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sync/Makefile b/drivers/cam_sync/Makefile index b0868f522549..e15ed0ce8931 100644 --- a/drivers/cam_sync/Makefile +++ b/drivers/cam_sync/Makefile @@ -2,6 +2,7 @@ ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-$(CONFIG_MSM_GLOBAL_SYNX) += -I$(srctree)/drivers/media/platform/msm/synx ccflags-y += -I$(src) obj-$(CONFIG_SPECTRA_CAMERA) += cam_sync.o cam_sync_util.o diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 5342de04da8f..10ed0cdecebf 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -13,6 +13,9 @@ #include "cam_debug_util.h" #include "cam_common_util.h" +#ifdef CONFIG_MSM_GLOBAL_SYNX +#include +#endif struct sync_device *sync_dev; /* @@ -956,6 +959,25 @@ static int cam_sync_create_debugfs(void) return 0; } +#ifdef CONFIG_MSM_GLOBAL_SYNX +static void cam_sync_register_synx_bind_ops(void) +{ + int rc = 0; + struct synx_register_params params; + + params.name = CAM_SYNC_NAME; + params.type = SYNX_TYPE_CSL; + params.ops.register_callback = cam_sync_register_callback; + params.ops.deregister_callback = cam_sync_deregister_callback; + params.ops.enable_signaling = cam_sync_get_obj_ref; + params.ops.signal = cam_sync_signal; + + rc = synx_register_ops(¶ms); + if (rc) + CAM_ERR(CAM_SYNC, "synx registration fail with %d", rc); +} +#endif + static int cam_sync_probe(struct platform_device *pdev) { int rc; @@ -1023,7 +1045,9 @@ static int cam_sync_probe(struct platform_device *pdev) trigger_cb_without_switch = false; cam_sync_create_debugfs(); - +#ifdef CONFIG_MSM_GLOBAL_SYNX + cam_sync_register_synx_bind_ops(); +#endif return rc; v4l2_fail: From 4f13d6fe1f0ebb39d66a63091b152e6b182c6155 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 26 Jun 2019 16:33:51 -0700 Subject: [PATCH 022/790] msm: camera: cpas: Update SafeLut values in CAMNOC QoS settings for Kona Update SafeLut values for ife paths in CAMNOC QoS settings according to recommended settings in CAMNOC HPG. Change-Id: I12fa796757f4fe000e47ab2074c7ee88165864ab Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h index cbb521d30778..fcf25383ec66 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -317,7 +317,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ - .value = 0xFFF0, + .value = 0x000F, }, .ubwc_ctl = { /* @@ -407,7 +407,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_SAFELUT_LOW */ - .value = 0xFFF0, + .value = 0x000F, }, .ubwc_ctl = { /* @@ -452,7 +452,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_SAFELUT_LOW */ - .value = 0xFFF0, + .value = 0x000F, }, .ubwc_ctl = { /* From 2f6c89b46f9b4a7cf130c11c1e15cd874c9171c4 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 27 Jun 2019 22:14:38 +0800 Subject: [PATCH 023/790] msm: camera: csid: add csiphy4 and csiphy5 support Add csiphy4 and csiphy5 support. Change-Id: I8523523556671ed6ffd7f880af2d18043c30d4eb Signed-off-by: Depeng Shao --- drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h | 2 +- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h index b545ccc2a246..cfa8e152b4c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -291,7 +291,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, + .csi2_rx_phy_num_mask = 0x7, }; static struct cam_ife_csid_csi2_tpg_reg_offset diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h index ca4373b62814..7d9a53567ee6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h @@ -247,7 +247,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, + .csi2_rx_phy_num_mask = 0x7, }; static struct cam_ife_csid_csi2_tpg_reg_offset From 93e8362a07cb856193e61a7b953a29656afae521 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 11:57:38 -0700 Subject: [PATCH 024/790] msm: camera: cpas: Enable camnoc interrupts Enable camnoc interrupts to get notifications for UBWC encoder and decoder errors. Change-Id: Ie7d89dcaf4c81e9ce5af9f28e9a5e0a9cf3eeaa8 Signed-off-by: Suresh Vankadara Signed-off-by: Jigarkumar Zala --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 4 ++++ drivers/cam_cpas/cpas_top/cpastop_v175_130.h | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 57eb9de92be4..33ee95888fd8 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -334,6 +334,9 @@ static int cam_cpastop_reset_irq(struct cam_hw_info *cpas_hw) { int i; + if (camnoc_info->irq_sbm->sbm_enable.enable == false) + return 0; + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, &camnoc_info->irq_sbm->sbm_clear); for (i = 0; i < camnoc_info->irq_err_size; i++) { @@ -508,6 +511,7 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) { int i; + cam_cpastop_reset_irq(cpas_hw); for (i = 0; i < camnoc_info->specific_size; i++) { if (camnoc_info->specific[i].enable) { cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h index 43c1068cc22c..2d3d96ea819a 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h @@ -67,18 +67,19 @@ static struct cam_camnoc_irq_err .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x3BA0, /* SPECIFIC_IFE02_ENCERREN_LOW */ + .offset = 0x3BA0, /* SPECIFIC_IFE0_MAIN_ENCERREN_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x3B90, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */ + /* SPECIFIC_IFE0_MAIN_ENCERRSTATUS_LOW */ + .offset = 0x3B90, }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x3B98, /* SPECIFIC_IFE02_ENCERRCLR_LOW */ + .offset = 0x3B98, /* SPECIFIC_IFE0_MAIN_ENCERRCLR_LOW */ .value = 1, }, }, @@ -89,18 +90,19 @@ static struct cam_camnoc_irq_err .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x55a0, /* SPECIFIC_IFE13_ENCERREN_LOW */ + .offset = 0x55A0, /* SPECIFIC_IFE1_WR_ENCERREN_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x5590, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */ + /* SPECIFIC_IFE1_WR_ENCERRSTATUS_LOW */ + .offset = 0x5590, }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x5598, /* SPECIFIC_IFE13_ENCERRCLR_LOW */ + .offset = 0x5598, /* SPECIFIC_IFE1_WR_ENCERRCLR_LOW */ .value = 1, }, }, @@ -133,7 +135,7 @@ static struct cam_camnoc_irq_err .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x2Ba0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */ + .offset = 0x2BA0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */ .value = 1, }, .err_status = { From 13bec8b88ea7065788bf24f1aa29dc94aa784e14 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 11:58:49 -0700 Subject: [PATCH 025/790] Revert "msm: camera: ife: Stop tasklet after deinit" This reverts commit ff736fcb813649b3998fca3d732145f341235cf5. The above change was committed to prevent tasklet deinit before ISRs have completed execution due to erratic delays in tasklet scheduling on early builds which was not stable. As builds have stabilized now, we need to revert to normal driver behavior for stop sequence. Change-Id: I57127d3fe6fbbd5579241c1cfc978362ba302aef Signed-off-by: Venkat Chinta Signed-off-by: Jigarkumar Zala --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 75f157f0d5b8..473a274eaf5c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3334,19 +3334,17 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) 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) { - cam_tasklet_stop(ctx->common.tasklet_info); + if (stop_isp->stop_only) goto end; - } if (cam_cdm_stream_off(ctx->cdm_handle)) CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); cam_ife_hw_mgr_deinit_hw(ctx); - cam_tasklet_stop(ctx->common.tasklet_info); - CAM_DBG(CAM_ISP, "Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc); From b630768467b2ea046f1fe8db6c73e0c9696a92b7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 11:59:44 -0700 Subject: [PATCH 026/790] msm: camera: icp: Add support for semi real time device types Add support for IPE/BPS semi real time device types. Change-Id: I1d9974eb796ce1723205072651d53ecb84023e88 Signed-off-by: Karthik Anantha Ram Signed-off-by: Vishalsingh Hajeri Signed-off-by: Jigarkumar Zala --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 9cb19fae68c9..57a88f5a3070 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -5012,10 +5012,31 @@ static int cam_icp_get_acquire_info(struct cam_icp_hw_mgr *hw_mgr, return 0; } +static uint32_t cam_icp_unify_dev_type( + uint32_t dev_type) +{ + switch (dev_type) { + case CAM_ICP_RES_TYPE_BPS: + return CAM_ICP_RES_TYPE_BPS; + case CAM_ICP_RES_TYPE_BPS_RT: + return CAM_ICP_RES_TYPE_BPS; + case CAM_ICP_RES_TYPE_BPS_SEMI_RT: + return CAM_ICP_RES_TYPE_BPS; + case CAM_ICP_RES_TYPE_IPE: + return CAM_ICP_RES_TYPE_IPE; + case CAM_ICP_RES_TYPE_IPE_RT: + return CAM_ICP_RES_TYPE_IPE; + case CAM_ICP_RES_TYPE_IPE_SEMI_RT: + return CAM_ICP_RES_TYPE_IPE; + default: + return CAM_ICP_RES_TYPE_MAX; + } +} + static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { int rc = 0, bitmap_size = 0; - uint32_t ctx_id = 0; + uint32_t ctx_id = 0, dev_type; uint64_t io_buf_addr; size_t io_buf_size; struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; @@ -5108,6 +5129,10 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto create_handle_failed; } + CAM_DBG(CAM_ICP, + "created stream handle for dev_type %u", + icp_dev_acquire_info->dev_type); + cmd_mem_region.num_regions = 1; cmd_mem_region.map_info_array[0].mem_handle = icp_dev_acquire_info->io_config_cmd_handle; @@ -5167,10 +5192,12 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) /* Start context timer*/ cam_icp_ctx_timer_start(ctx_data); hw_mgr->ctxt_cnt++; + dev_type = cam_icp_unify_dev_type(icp_dev_acquire_info->dev_type); + icp_dev_acquire_info->dev_type = dev_type; mutex_unlock(&hw_mgr->hw_mgr_mutex); - CAM_DBG(CAM_ICP, "Acquire Done for ctx_id %u dev name %s dev type %d", - ctx_data->ctx_id, cam_icp_dev_type_to_name( - icp_dev_acquire_info->dev_type), + + CAM_DBG(CAM_ICP, "Acquire Done for ctx_id %u dev type %d", + ctx_data->ctx_id, icp_dev_acquire_info->dev_type); return 0; From d707886ae1570d5b1eafe53151cbd8f756b1c7dd Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:03:32 -0700 Subject: [PATCH 027/790] msm: camera: isp: Move bw voting functions to common file for vfe Currently, vfe top has different files for different targets. Some of the APIs are unchanged between these files. In order to avoid duplication of code and make sure no change is missed between different versions of vfe top, a common file is added to vfe top for unchanged APIs. With the common top, number of input resources are moved to architecture specific header files to ensure special conditions need not be created for a particular architecture in common code. Move bw voting related APIs to this common file. Change-Id: Ibcb9519a206c25d42c9e7f0336f8d588a8240717 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Jigarkumar Zala --- .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 3 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 3 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile | 2 +- .../vfe_hw/vfe_top/cam_vfe_top_common.c | 373 ++++++++++++ .../vfe_hw/vfe_top/cam_vfe_top_common.h | 44 ++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 558 ++++-------------- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h | 6 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 549 ++++------------- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h | 6 +- 13 files changed, 646 insertions(+), 902 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index 748c324f5496..663bc247b27f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE170_H_ @@ -166,6 +166,7 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { NULL, }, }, + .num_mux = 4, .mux_type = { CAM_VFE_CAMIF_VER_2_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index db61bfbdc84b..6823b6386b91 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -201,6 +201,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = { NULL, }, }, + .num_mux = 5, .mux_type = { CAM_VFE_CAMIF_VER_2_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 03a6409324d8..8acd77d1f1e2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -254,6 +254,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = { .fe_reg = &vfe175_130_fe_reg, .reg_data = &vfe_175_130_fe_reg_data, }, + .num_mux = 6, .mux_type = { CAM_VFE_CAMIF_VER_2_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 48eb7f1b028d..ae65df7c1126 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -304,6 +304,7 @@ static struct cam_vfe_top_ver3_hw_info vfe480_top_hw_info = { .camif_lite_reg = &vfe480_camif_lcr, .reg_data = &vfe480_camif_lcr_reg_data, }, + .num_mux = 6, .mux_type = { CAM_VFE_CAMIF_VER_3_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index 0c94b63be2e0..f356d6c24b20 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE17X_H_ @@ -97,6 +97,7 @@ static struct cam_vfe_top_ver2_hw_info vfe17x_top_hw_info = { &vfe17x_rdi_3_data, }, }, + .num_mux = 4, .mux_type = { CAM_VFE_RDI_VER_1_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 221c372f72b1..c19ade50bec9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -199,6 +199,7 @@ static struct cam_vfe_top_ver3_hw_info vfe48x_top_hw_info = { .rdi_hw_info[1] = &vfe48x_rdi_hw_info[1], .rdi_hw_info[2] = &vfe48x_rdi_hw_info[2], .rdi_hw_info[3] = &vfe48x_rdi_hw_info[3], + .num_mux = 4, .mux_type = { CAM_VFE_RDI_VER_1_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile index 0ed6a870efa9..2ab4651e4271 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile @@ -13,6 +13,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o cam_vfe_top.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o cam_vfe_top.o cam_vfe_top_common.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_top_ver3.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_ver3.o cam_vfe_rdi.o cam_vfe_fe_ver1.o cam_vfe_camif_lite_ver3.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c new file mode 100644 index 000000000000..2eae53205c8c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_vfe_top_common.h" +#include "cam_debug_util.h" + +static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( + struct cam_vfe_top_priv_common *top_common, + uint64_t *to_be_applied_bw) +{ + uint32_t i, j; + int vote_idx = -1; + uint64_t max_bw = 0; + uint64_t total_bw; + struct cam_axi_vote *curr_l_vote; + + for (i = 0; i < CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES; i++) { + total_bw = 0; + curr_l_vote = &top_common->last_vote[i]; + for (j = 0; j < curr_l_vote->num_paths; j++) { + if (total_bw > + (U64_MAX - + curr_l_vote->axi_path[j].camnoc_bw)) { + CAM_ERR(CAM_PERF, + "ife[%d] : Integer overflow at hist idx: %d, path: %d, total_bw = %llu, camnoc_bw = %llu", + top_common->hw_idx, i, j, total_bw, + curr_l_vote->axi_path[j].camnoc_bw); + return NULL; + } + + total_bw += curr_l_vote->axi_path[j].camnoc_bw; + } + + if (total_bw > max_bw) { + vote_idx = i; + max_bw = total_bw; + } + } + + if (vote_idx < 0) + return NULL; + + *to_be_applied_bw = max_bw; + + return &top_common->last_vote[vote_idx]; +} + +int cam_vfe_top_set_axi_bw_vote(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, bool start_stop) +{ + struct cam_axi_vote agg_vote = {0}; + struct cam_axi_vote *to_be_applied_axi_vote = NULL; + int rc = 0; + uint32_t i; + uint32_t num_paths = 0; + uint64_t total_bw_new_vote = 0; + bool bw_unchanged = true; + bool apply_bw_update = false; + + for (i = 0; i < top_common->num_mux; i++) { + if (top_common->axi_vote_control[i] == + CAM_VFE_BW_CONTROL_INCLUDE) { + if (num_paths + + top_common->req_axi_vote[i].num_paths > + CAM_CPAS_MAX_PATHS_PER_CLIENT) { + CAM_ERR(CAM_PERF, + "Required paths(%d) more than max(%d)", + num_paths + + top_common->req_axi_vote[i].num_paths, + CAM_CPAS_MAX_PATHS_PER_CLIENT); + return -EINVAL; + } + + memcpy(&agg_vote.axi_path[num_paths], + &top_common->req_axi_vote[i].axi_path[0], + top_common->req_axi_vote[i].num_paths * + sizeof( + struct cam_axi_per_path_bw_vote)); + num_paths += top_common->req_axi_vote[i].num_paths; + } + } + + agg_vote.num_paths = num_paths; + + for (i = 0; i < agg_vote.num_paths; i++) { + CAM_DBG(CAM_PERF, + "ife[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", + top_common->hw_idx, + top_common->last_counter, + cam_cpas_axi_util_path_type_to_string( + agg_vote.axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + agg_vote.axi_path[i].transac_type), + agg_vote.axi_path[i].camnoc_bw, + agg_vote.axi_path[i].mnoc_ab_bw, + agg_vote.axi_path[i].mnoc_ib_bw); + + total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; + } + + memcpy(&top_common->last_vote[top_common->last_counter], &agg_vote, + sizeof(struct cam_axi_vote)); + top_common->last_counter = (top_common->last_counter + 1) % + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES; + + if ((agg_vote.num_paths != top_common->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_common->total_bw_applied)) + bw_unchanged = false; + + CAM_DBG(CAM_PERF, + "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", + top_common->hw_idx, top_common->total_bw_applied, + total_bw_new_vote, bw_unchanged, start_stop); + + if (bw_unchanged) { + CAM_DBG(CAM_PERF, "BW config unchanged"); + return 0; + } + + if (start_stop) { + /* need to vote current request immediately */ + to_be_applied_axi_vote = &agg_vote; + /* Reset everything, we can start afresh */ + memset(top_common->last_vote, 0x0, sizeof(struct cam_axi_vote) * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); + top_common->last_counter = 0; + top_common->last_vote[top_common->last_counter] = agg_vote; + top_common->last_counter = (top_common->last_counter + 1) % + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES; + } else { + /* + * Find max bw request in last few frames. This will the bw + * that we want to vote to CPAS now. + */ + to_be_applied_axi_vote = + cam_vfe_top_delay_bw_reduction(top_common, + &total_bw_new_vote); + if (!to_be_applied_axi_vote) { + CAM_ERR(CAM_PERF, "to_be_applied_axi_vote is NULL"); + return -EINVAL; + } + } + + for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "ife[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", + top_common->hw_idx, + cam_cpas_axi_util_path_type_to_string( + to_be_applied_axi_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + to_be_applied_axi_vote->axi_path[i].transac_type), + to_be_applied_axi_vote->axi_path[i].camnoc_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); + } + + if ((to_be_applied_axi_vote->num_paths != + top_common->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_common->total_bw_applied)) + apply_bw_update = true; + + CAM_DBG(CAM_PERF, + "ife[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", + top_common->hw_idx, top_common->total_bw_applied, + total_bw_new_vote, apply_bw_update, start_stop); + + if (apply_bw_update) { + rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, + to_be_applied_axi_vote); + if (!rc) { + memcpy(&top_common->applied_axi_vote, + to_be_applied_axi_vote, + sizeof(struct cam_axi_vote)); + top_common->total_bw_applied = total_bw_new_vote; + } else { + CAM_ERR(CAM_PERF, "BW request failed, rc=%d", rc); + } + } + + return rc; +} + +int cam_vfe_top_bw_update_v2(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bw_update_args_v2 *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_update = (struct cam_vfe_bw_update_args_v2 *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < top_common->num_mux; i++) { + if (top_common->mux_rsrc[i].res_id == res->res_id) { + memcpy(&top_common->req_axi_vote[i], + &bw_update->isp_vote, + sizeof(struct cam_axi_vote)); + top_common->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_PERF, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(soc_private, top_common, + false); + } + + return rc; +} + +int cam_vfe_top_bw_update(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bw_update_args *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + struct cam_axi_vote *mux_axi_vote; + bool vid_exists = false; + bool rdi_exists = false; + + bw_update = (struct cam_vfe_bw_update_args *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + CAM_DBG(CAM_PERF, "res_id=%d, BW=[%lld %lld]", + res->res_id, bw_update->camnoc_bw_bytes, + bw_update->external_bw_bytes); + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < top_common->num_mux; i++) { + mux_axi_vote = &top_common->req_axi_vote[i]; + if (top_common->mux_rsrc[i].res_id == res->res_id) { + mux_axi_vote->num_paths = 1; + if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && + (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_RDI0 + + (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); + } else { + /* + * Vote all bw into VIDEO path as we cannot + * differentiate to which path this has to go + */ + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_VID; + } + + mux_axi_vote->axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + mux_axi_vote->axi_path[0].camnoc_bw = + bw_update->camnoc_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ib_bw = + bw_update->external_bw_bytes; + /* Make ddr bw same as mnoc bw */ + mux_axi_vote->axi_path[0].ddr_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].ddr_ib_bw = + bw_update->external_bw_bytes; + + top_common->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + + if (mux_axi_vote->num_paths == 1) { + if (mux_axi_vote->axi_path[0].path_data_type == + CAM_AXI_PATH_DATA_IFE_VID) + vid_exists = true; + else if ((mux_axi_vote->axi_path[0].path_data_type >= + CAM_AXI_PATH_DATA_IFE_RDI0) && + (mux_axi_vote->axi_path[0].path_data_type <= + CAM_AXI_PATH_DATA_IFE_RDI3)) + rdi_exists = true; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_PERF, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(soc_private, top_common, + false); + } + + return rc; +} + +int cam_vfe_top_bw_control(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bw_control_args *bw_ctrl = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args; + res = bw_ctrl->node_res; + + if (!res || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < top_common->num_mux; i++) { + if (top_common->mux_rsrc[i].res_id == res->res_id) { + top_common->axi_vote_control[i] = bw_ctrl->action; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_PERF, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(soc_private, top_common, true); + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h new file mode 100644 index 000000000000..03be713e6068 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_TOP_COMMON_H_ +#define _CAM_VFE_TOP_COMMON_H_ + +#define CAM_VFE_TOP_MUX_MAX 6 +#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 18 + +#include "cam_cpas_api.h" +#include "cam_vfe_hw_intf.h" +#include "cam_vfe_soc.h" + +struct cam_vfe_top_priv_common { + struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_MUX_MAX]; + uint32_t num_mux; + uint32_t hw_idx; + struct cam_axi_vote applied_axi_vote; + struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_MUX_MAX]; + struct cam_axi_vote last_vote[ + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; + uint32_t last_counter; + uint64_t total_bw_applied; + enum cam_vfe_bw_control_action axi_vote_control[CAM_VFE_TOP_MUX_MAX]; +}; + +int cam_vfe_top_set_axi_bw_vote(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, bool start_stop); + +int cam_vfe_top_bw_update_v2(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size); + +int cam_vfe_top_bw_update(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size); + +int cam_vfe_top_bw_control(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size); + +#endif /* _CAM_VFE_TOP_COMMON_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 78a72eb6846a..e057b15aee43 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -10,12 +10,10 @@ #include "cam_vfe_top.h" #include "cam_vfe_top_ver2.h" #include "cam_debug_util.h" -#include "cam_cpas_api.h" #include "cam_vfe_soc.h" #define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00003F9F #define CAM_VFE_HW_RESET_HW_VAL 0x00003F87 -#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 struct cam_vfe_top_ver2_common_data { struct cam_hw_soc_info *soc_info; @@ -25,17 +23,10 @@ struct cam_vfe_top_ver2_common_data { struct cam_vfe_top_ver2_priv { struct cam_vfe_top_ver2_common_data common_data; - struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER2_MUX_MAX]; unsigned long hw_clk_rate; - 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 * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; - uint32_t last_counter; - uint64_t total_bw_applied; - enum cam_vfe_bw_control_action - axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX]; + unsigned long req_clk_rate[ + CAM_VFE_TOP_MUX_MAX]; + struct cam_vfe_top_priv_common top_common; }; static int cam_vfe_top_mux_get_base(struct cam_vfe_top_ver2_priv *top_priv, @@ -94,14 +85,14 @@ static int cam_vfe_top_set_hw_clk_rate( soc_info = top_priv->common_data.soc_info; - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) max_clk_rate = top_priv->req_clk_rate[i]; } if (max_clk_rate == top_priv->hw_clk_rate) return 0; - CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu", + CAM_DBG(CAM_PERF, "VFE: Clock name=%s idx=%d clk=%llu", soc_info->clk_name[soc_info->src_clk_idx], soc_info->src_clk_idx, max_clk_rate); @@ -110,196 +101,7 @@ static int cam_vfe_top_set_hw_clk_rate( if (!rc) top_priv->hw_clk_rate = max_clk_rate; else - CAM_ERR(CAM_ISP, "Set Clock rate failed, rc=%d", rc); - - return rc; -} - -static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( - struct cam_vfe_top_ver2_priv *top_priv, - uint64_t *to_be_applied_bw) -{ - uint32_t i, j; - int vote_idx = -1; - uint64_t max_bw = 0; - uint64_t total_bw; - struct cam_axi_vote *curr_l_vote; - - for (i = 0; i < (CAM_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) { - total_bw = 0; - curr_l_vote = &top_priv->last_vote[i]; - for (j = 0; j < curr_l_vote->num_paths; j++) { - if (total_bw > - (U64_MAX - - curr_l_vote->axi_path[j].camnoc_bw)) { - CAM_ERR(CAM_ISP, "Overflow at idx: %d", j); - return NULL; - } - - total_bw += curr_l_vote->axi_path[j].camnoc_bw; - } - - if (total_bw > max_bw) { - vote_idx = i; - max_bw = total_bw; - } - } - - if (vote_idx < 0) - return NULL; - - *to_be_applied_bw = max_bw; - - return &top_priv->last_vote[vote_idx]; -} - -static int cam_vfe_top_set_axi_bw_vote( - struct cam_vfe_top_ver2_priv *top_priv, - bool start_stop) -{ - struct cam_axi_vote agg_vote = {0}; - struct cam_axi_vote *to_be_applied_axi_vote = NULL; - int rc = 0; - uint32_t i; - uint32_t num_paths = 0; - uint64_t total_bw_new_vote = 0; - bool bw_unchanged = true; - struct cam_hw_soc_info *soc_info = - top_priv->common_data.soc_info; - struct cam_vfe_soc_private *soc_private = - soc_info->soc_private; - bool apply_bw_update = false; - - 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) { - if (num_paths + - top_priv->req_axi_vote[i].num_paths > - CAM_CPAS_MAX_PATHS_PER_CLIENT) { - CAM_ERR(CAM_ISP, - "Required paths(%d) more than max(%d)", - num_paths + - top_priv->req_axi_vote[i].num_paths, - CAM_CPAS_MAX_PATHS_PER_CLIENT); - return -EINVAL; - } - - memcpy(&agg_vote.axi_path[num_paths], - &top_priv->req_axi_vote[i].axi_path[0], - top_priv->req_axi_vote[i].num_paths * - sizeof( - struct cam_axi_per_path_bw_vote)); - num_paths += top_priv->req_axi_vote[i].num_paths; - } - } - - agg_vote.num_paths = num_paths; - - for (i = 0; i < agg_vote.num_paths; i++) { - CAM_DBG(CAM_PERF, - "ife[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", - top_priv->common_data.hw_intf->hw_idx, - top_priv->last_counter, - cam_cpas_axi_util_path_type_to_string( - agg_vote.axi_path[i].path_data_type), - cam_cpas_axi_util_trans_type_to_string( - agg_vote.axi_path[i].transac_type), - agg_vote.axi_path[i].camnoc_bw, - agg_vote.axi_path[i].mnoc_ab_bw, - agg_vote.axi_path[i].mnoc_ib_bw); - - total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; - } - - memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, - sizeof(struct cam_axi_vote)); - top_priv->last_counter = (top_priv->last_counter + 1) % - (CAM_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); - - if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || - (total_bw_new_vote != top_priv->total_bw_applied)) - bw_unchanged = false; - - CAM_DBG(CAM_PERF, - "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", - top_priv->common_data.hw_intf->hw_idx, - top_priv->total_bw_applied, total_bw_new_vote, - bw_unchanged, start_stop); - - if (bw_unchanged) { - CAM_DBG(CAM_ISP, "BW config unchanged"); - return 0; - } - - if (start_stop) { - /* need to vote current request immediately */ - to_be_applied_axi_vote = &agg_vote; - /* 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] = agg_vote; - top_priv->last_counter = (top_priv->last_counter + 1) % - (CAM_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); - } else { - /* - * Find max bw request in last few frames. This will the bw - * that we want to vote to CPAS now. - */ - to_be_applied_axi_vote = - cam_vfe_top_delay_bw_reduction(top_priv, - &total_bw_new_vote); - if (!to_be_applied_axi_vote) { - CAM_ERR(CAM_ISP, "to_be_applied_axi_vote is NULL"); - return -EINVAL; - } - } - - for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { - CAM_DBG(CAM_PERF, - "ife[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", - top_priv->common_data.hw_intf->hw_idx, - cam_cpas_axi_util_path_type_to_string( - to_be_applied_axi_vote->axi_path[i].path_data_type), - cam_cpas_axi_util_trans_type_to_string( - to_be_applied_axi_vote->axi_path[i].transac_type), - to_be_applied_axi_vote->axi_path[i].camnoc_bw, - to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, - to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); - } - - if ((to_be_applied_axi_vote->num_paths != - top_priv->applied_axi_vote.num_paths) || - (total_bw_new_vote != top_priv->total_bw_applied)) - apply_bw_update = true; - - CAM_DBG(CAM_PERF, - "ife[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", - top_priv->common_data.hw_intf->hw_idx, - top_priv->total_bw_applied, total_bw_new_vote, - apply_bw_update, start_stop); - - if (apply_bw_update) { - rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, - to_be_applied_axi_vote); - if (!rc) { - memcpy(&top_priv->applied_axi_vote, - to_be_applied_axi_vote, - sizeof(struct cam_axi_vote)); - top_priv->total_bw_applied = total_bw_new_vote; - } else { - CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc); - } - } + CAM_ERR(CAM_PERF, "Set Clock rate failed, rc=%d", rc); return rc; } @@ -331,7 +133,7 @@ static int cam_vfe_top_clock_update( res = clk_update->node_res; if (!res || !res->hw_intf->hw_priv) { - CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + CAM_ERR(CAM_PERF, "Invalid input res %pK", res); return -EINVAL; } @@ -339,21 +141,21 @@ static int cam_vfe_top_clock_update( if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + CAM_ERR(CAM_PERF, "VFE:%d Invalid res_type:%d res id%d", res->hw_intf->hw_idx, res->res_type, res->res_id); return -EINVAL; } - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == res->res_id) { top_priv->req_clk_rate[i] = clk_update->clk_rate; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_DBG(CAM_ISP, + CAM_DBG(CAM_PERF, "VFE:%d Not ready to set clocks yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); @@ -363,193 +165,6 @@ static int cam_vfe_top_clock_update( return rc; } -static int cam_vfe_top_bw_update_v2( - struct cam_vfe_top_ver2_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_update_args_v2 *bw_update = NULL; - struct cam_isp_resource_node *res = NULL; - struct cam_hw_info *hw_info = NULL; - int rc = 0; - int i; - - bw_update = (struct cam_vfe_bw_update_args_v2 *)cmd_args; - res = bw_update->node_res; - - if (!res || !res->hw_intf || !res->hw_intf->hw_priv) - return -EINVAL; - - hw_info = res->hw_intf->hw_priv; - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", - res->hw_intf->hw_idx, res->res_type, - res->res_id); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, - sizeof(struct cam_axi_vote)); - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - -static int cam_vfe_top_bw_update( - struct cam_vfe_top_ver2_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_update_args *bw_update = NULL; - struct cam_isp_resource_node *res = NULL; - struct cam_hw_info *hw_info = NULL; - int rc = 0; - int i; - struct cam_axi_vote *mux_axi_vote; - bool vid_exists = false; - bool rdi_exists = false; - - bw_update = (struct cam_vfe_bw_update_args *)cmd_args; - res = bw_update->node_res; - - if (!res || !res->hw_intf || !res->hw_intf->hw_priv) - return -EINVAL; - - hw_info = res->hw_intf->hw_priv; - - CAM_DBG(CAM_ISP, "res_id=%d, BW=[%lld %lld]", - res->res_id, bw_update->camnoc_bw_bytes, - bw_update->external_bw_bytes); - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", - res->hw_intf->hw_idx, res->res_type, - res->res_id); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - mux_axi_vote = &top_priv->req_axi_vote[i]; - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - mux_axi_vote->num_paths = 1; - if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && - (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_RDI0 + - (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); - } else { - /* - * Vote all bw into VIDEO path as we cannot - * differentiate to which path this has to go - */ - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_VID; - } - - mux_axi_vote->axi_path[0].transac_type = - CAM_AXI_TRANSACTION_WRITE; - mux_axi_vote->axi_path[0].camnoc_bw = - bw_update->camnoc_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ib_bw = - bw_update->external_bw_bytes; - /* Make ddr bw same as mnoc bw */ - mux_axi_vote->axi_path[0].ddr_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].ddr_ib_bw = - bw_update->external_bw_bytes; - - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - - if (mux_axi_vote->num_paths == 1) { - if (mux_axi_vote->axi_path[0].path_data_type == - CAM_AXI_PATH_DATA_IFE_VID) - vid_exists = true; - else if ((mux_axi_vote->axi_path[0].path_data_type >= - CAM_AXI_PATH_DATA_IFE_RDI0) && - (mux_axi_vote->axi_path[0].path_data_type <= - CAM_AXI_PATH_DATA_IFE_RDI3)) - rdi_exists = true; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - -static int cam_vfe_top_bw_control( - struct cam_vfe_top_ver2_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_control_args *bw_ctrl = NULL; - struct cam_isp_resource_node *res = NULL; - struct cam_hw_info *hw_info = NULL; - int rc = 0; - int i; - - bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args; - res = bw_ctrl->node_res; - - if (!res || !res->hw_intf->hw_priv) - return -EINVAL; - - hw_info = res->hw_intf->hw_priv; - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", - res->hw_intf->hw_idx, res->res_type, - res->res_id); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - top_priv->axi_vote_control[i] = bw_ctrl->action; - break; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); - } - - return rc; -} - static int cam_vfe_top_mux_get_reg_update( struct cam_vfe_top_ver2_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -638,14 +253,15 @@ int cam_vfe_top_reserve(void *device_priv, acquire_args = &args->vfe_in; - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == acquire_args->res_id && - top_priv->mux_rsrc[i].res_state == + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + acquire_args->res_id && + top_priv->top_common.mux_rsrc[i].res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { rc = cam_vfe_camif_ver2_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -654,7 +270,7 @@ int cam_vfe_top_reserve(void *device_priv, if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_PDLIB) { rc = cam_vfe_camif_lite_ver2_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -662,18 +278,20 @@ int cam_vfe_top_reserve(void *device_priv, if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) { rc = cam_vfe_fe_ver1_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.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 = + top_priv->top_common.mux_rsrc[i].cdm_ops = + acquire_args->cdm_ops; + top_priv->top_common.mux_rsrc[i].tasklet_info = + args->tasklet; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_RESERVED; acquire_args->rsrc_node = - &top_priv->mux_rsrc[i]; + &top_priv->top_common.mux_rsrc[i]; rc = 0; break; @@ -715,6 +333,8 @@ int cam_vfe_top_start(void *device_priv, struct cam_vfe_top_ver2_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int rc = 0; if (!device_priv || !start_args) { @@ -723,6 +343,13 @@ int cam_vfe_top_start(void *device_priv, } top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } + mux_res = (struct cam_isp_resource_node *)start_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; @@ -734,7 +361,8 @@ int cam_vfe_top_start(void *device_priv, return rc; } - rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); + rc = cam_vfe_top_set_axi_bw_vote(soc_private, + &top_priv->top_common, true); if (rc) { CAM_ERR(CAM_ISP, "set_axi_bw_vote failed, rc=%d", rc); @@ -785,17 +413,18 @@ int cam_vfe_top_stop(void *device_priv, } if (!rc) { - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == mux_res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + mux_res->res_id) { top_priv->req_clk_rate[i] = 0; top_priv->req_clk_rate[i] = 0; - top_priv->req_axi_vote[i].axi_path[0].camnoc_bw - = 0; - top_priv->req_axi_vote[i].axi_path[0].mnoc_ab_bw - = 0; - top_priv->req_axi_vote[i].axi_path[0].mnoc_ib_bw - = 0; - top_priv->axi_vote_control[i] = + top_priv->top_common.req_axi_vote[i] + .axi_path[0].camnoc_bw = 0; + top_priv->top_common.req_axi_vote[i] + .axi_path[0].mnoc_ab_bw = 0; + top_priv->top_common.req_axi_vote[i] + .axi_path[0].mnoc_ib_bw = 0; + top_priv->top_common.axi_vote_control[i] = CAM_VFE_BW_CONTROL_EXCLUDE; break; } @@ -822,12 +451,20 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, { int rc = 0; struct cam_vfe_top_ver2_priv *top_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; if (!device_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Error! Invalid arguments"); return -EINVAL; } top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: @@ -846,15 +483,16 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE: - rc = cam_vfe_top_bw_update(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: - rc = cam_vfe_top_bw_update_v2(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update_v2(soc_private, + &top_priv->top_common, cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: - rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size); + rc = cam_vfe_top_bw_control(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; default: rc = -EINVAL; @@ -891,56 +529,69 @@ int cam_vfe_top_ver2_init( rc = -ENOMEM; goto free_vfe_top; } + vfe_top->top_priv = top_priv; top_priv->hw_clk_rate = 0; + if (ver2_hw_info->num_mux > CAM_VFE_TOP_MUX_MAX) { + CAM_ERR(CAM_ISP, "Invalid number of input rsrc: %d, max: %d", + ver2_hw_info->num_mux, CAM_VFE_TOP_MUX_MAX); + rc = -EINVAL; + goto free_top_priv; + } - 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; - top_priv->mux_rsrc[i].hw_intf = hw_intf; - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.num_mux = ver2_hw_info->num_mux; + + for (i = 0, j = 0; i < top_priv->top_common.num_mux; i++) { + top_priv->top_common.mux_rsrc[i].res_type = + CAM_ISP_RESOURCE_VFE_IN; + top_priv->top_common.mux_rsrc[i].hw_intf = hw_intf; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; top_priv->req_clk_rate[i] = 0; if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) { - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_CAMIF; rc = cam_vfe_camif_ver2_init(hw_intf, soc_info, &ver2_hw_info->camif_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_LITE_VER_2_0) { - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_PDLIB; rc = cam_vfe_camif_lite_ver2_init(hw_intf, soc_info, &ver2_hw_info->camif_lite_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver2_hw_info->mux_type[i] == CAM_VFE_RDI_VER_1_0) { /* set the RDI resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RDI0 + j++; rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info, &ver2_hw_info->rdi_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); 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 = + top_priv->top_common.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]); + &top_priv->top_common.mux_rsrc[i]); if (rc) goto deinit_resources; } else { @@ -963,6 +614,7 @@ int cam_vfe_top_ver2_init( top_priv->common_data.soc_info = soc_info; top_priv->common_data.hw_intf = hw_intf; + top_priv->top_common.hw_idx = hw_intf->hw_idx; top_priv->common_data.common_reg = ver2_hw_info->common_reg; return rc; @@ -970,26 +622,30 @@ int cam_vfe_top_ver2_init( deinit_resources: for (--i; i >= 0; i--) { if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) { - if (cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_camif_ver2_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif Deinit failed"); } else if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_LITE_VER_2_0) { if (cam_vfe_camif_lite_ver2_deinit( - &top_priv->mux_rsrc[i])) + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif lite deinit failed"); } else if (ver2_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { - if (cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "VFE FE deinit failed"); } else { - if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_rdi_ver2_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "RDI Deinit failed"); } - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; } - kfree(vfe_top->top_priv); +free_top_priv: + kfree(vfe_top->top_priv); free_vfe_top: kfree(vfe_top); end: @@ -1020,35 +676,39 @@ int cam_vfe_top_ver2_deinit(struct cam_vfe_top **vfe_top_ptr) goto free_vfe_top; } - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - top_priv->mux_rsrc[i].res_state = + for (i = 0; i < top_priv->top_common.num_mux; i++) { + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; - if (top_priv->mux_rsrc[i].res_type == + if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_CAMIF_VER_2_0) { - rc = cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_camif_ver2_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_CAMIF_LITE_VER_2_0) { rc = cam_vfe_camif_lite_ver2_deinit( - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif lite deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_RDI_VER_1_0) { - rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_rdi_ver2_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "RDI deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_IN_RD_VER_1_0) { - rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); } } + kfree(vfe_top->top_priv); free_vfe_top: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h index 82e30b4285a5..961bf954aaa1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h @@ -10,8 +10,7 @@ #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 6 +#include "cam_vfe_top_common.h" enum cam_vfe_top_ver2_module_type { CAM_VFE_TOP_VER2_MODULE_LENS, @@ -50,7 +49,8 @@ struct cam_vfe_top_ver2_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]; + uint32_t num_mux; + uint32_t mux_type[CAM_VFE_TOP_MUX_MAX]; }; int cam_vfe_top_ver2_init(struct cam_hw_soc_info *soc_info, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 578b0771821f..a4fbe67aa955 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -10,14 +10,12 @@ #include "cam_vfe_top.h" #include "cam_vfe_top_ver3.h" #include "cam_debug_util.h" -#include "cam_cpas_api.h" #include "cam_vfe_soc.h" #define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00000003 #define CAM_VFE_HW_RESET_HW_VAL 0x007F0000 #define CAM_VFE_LITE_HW_RESET_AND_REG_VAL 0x00000002 #define CAM_VFE_LITE_HW_RESET_HW_VAL 0x0000003D -#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 struct cam_vfe_top_ver3_common_data { struct cam_hw_soc_info *soc_info; @@ -27,17 +25,10 @@ struct cam_vfe_top_ver3_common_data { struct cam_vfe_top_ver3_priv { struct cam_vfe_top_ver3_common_data common_data; - struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER3_MUX_MAX]; unsigned long hw_clk_rate; - struct cam_axi_vote applied_axi_vote; - struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER3_MUX_MAX]; - unsigned long req_clk_rate[CAM_VFE_TOP_VER3_MUX_MAX]; - struct cam_axi_vote last_vote[CAM_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; - uint32_t last_counter; - uint64_t total_bw_applied; - enum cam_vfe_bw_control_action - axi_vote_control[CAM_VFE_TOP_VER3_MUX_MAX]; + unsigned long req_clk_rate[ + CAM_VFE_TOP_MUX_MAX]; + struct cam_vfe_top_priv_common top_common; }; static int cam_vfe_top_ver3_mux_get_base(struct cam_vfe_top_ver3_priv *top_priv, @@ -96,14 +87,14 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( soc_info = top_priv->common_data.soc_info; - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) max_clk_rate = top_priv->req_clk_rate[i]; } if (max_clk_rate == top_priv->hw_clk_rate) return 0; - CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu", + CAM_DBG(CAM_PERF, "VFE: Clock name=%s idx=%d clk=%llu", soc_info->clk_name[soc_info->src_clk_idx], soc_info->src_clk_idx, max_clk_rate); @@ -112,196 +103,7 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( if (!rc) top_priv->hw_clk_rate = max_clk_rate; else - CAM_ERR(CAM_ISP, "Set Clock rate failed, rc=%d", rc); - - return rc; -} - -static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( - struct cam_vfe_top_ver3_priv *top_priv, - uint64_t *to_be_applied_bw) -{ - uint32_t i, j; - int vote_idx = -1; - uint64_t max_bw = 0; - uint64_t total_bw; - struct cam_axi_vote *curr_l_vote; - - for (i = 0; i < (CAM_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) { - total_bw = 0; - curr_l_vote = &top_priv->last_vote[i]; - for (j = 0; j < curr_l_vote->num_paths; j++) { - if (total_bw > - (U64_MAX - - curr_l_vote->axi_path[j].camnoc_bw)) { - CAM_ERR(CAM_ISP, "Overflow at idx: %d", j); - return NULL; - } - - total_bw += curr_l_vote->axi_path[j].camnoc_bw; - } - - if (total_bw > max_bw) { - vote_idx = i; - max_bw = total_bw; - } - } - - if (vote_idx < 0) - return NULL; - - *to_be_applied_bw = max_bw; - - return &top_priv->last_vote[vote_idx]; -} - -static int cam_vfe_top_ver3_set_axi_bw_vote( - struct cam_vfe_top_ver3_priv *top_priv, - bool start_stop) -{ - struct cam_axi_vote agg_vote = {0}; - struct cam_axi_vote *to_be_applied_axi_vote = NULL; - int rc = 0; - uint32_t i; - uint32_t num_paths = 0; - uint64_t total_bw_new_vote = 0; - bool bw_unchanged = true; - struct cam_hw_soc_info *soc_info = - top_priv->common_data.soc_info; - struct cam_vfe_soc_private *soc_private = - soc_info->soc_private; - bool apply_bw_update = false; - - if (!soc_private) { - CAM_ERR(CAM_ISP, "Error soc_private NULL"); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->axi_vote_control[i] == - CAM_VFE_BW_CONTROL_INCLUDE) { - if (num_paths + - top_priv->req_axi_vote[i].num_paths > - CAM_CPAS_MAX_PATHS_PER_CLIENT) { - CAM_ERR(CAM_ISP, - "Required paths(%d) more than max(%d)", - num_paths + - top_priv->req_axi_vote[i].num_paths, - CAM_CPAS_MAX_PATHS_PER_CLIENT); - return -EINVAL; - } - - memcpy(&agg_vote.axi_path[num_paths], - &top_priv->req_axi_vote[i].axi_path[0], - top_priv->req_axi_vote[i].num_paths * - sizeof( - struct cam_axi_per_path_bw_vote)); - num_paths += top_priv->req_axi_vote[i].num_paths; - } - } - - agg_vote.num_paths = num_paths; - - for (i = 0; i < agg_vote.num_paths; i++) { - CAM_DBG(CAM_PERF, - "ife[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", - top_priv->common_data.hw_intf->hw_idx, - top_priv->last_counter, - cam_cpas_axi_util_path_type_to_string( - agg_vote.axi_path[i].path_data_type), - cam_cpas_axi_util_trans_type_to_string( - agg_vote.axi_path[i].transac_type), - agg_vote.axi_path[i].camnoc_bw, - agg_vote.axi_path[i].mnoc_ab_bw, - agg_vote.axi_path[i].mnoc_ib_bw); - - total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; - } - - memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, - sizeof(struct cam_axi_vote)); - top_priv->last_counter = (top_priv->last_counter + 1) % - (CAM_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); - - if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || - (total_bw_new_vote != top_priv->total_bw_applied)) - bw_unchanged = false; - - CAM_DBG(CAM_PERF, - "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", - top_priv->common_data.hw_intf->hw_idx, - top_priv->total_bw_applied, total_bw_new_vote, - bw_unchanged, start_stop); - - if (bw_unchanged) { - CAM_DBG(CAM_ISP, "BW config unchanged"); - return 0; - } - - if (start_stop) { - /* need to vote current request immediately */ - to_be_applied_axi_vote = &agg_vote; - /* Reset everything, we can start afresh */ - memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * - (CAM_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES)); - top_priv->last_counter = 0; - top_priv->last_vote[top_priv->last_counter] = agg_vote; - top_priv->last_counter = (top_priv->last_counter + 1) % - (CAM_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); - } else { - /* - * Find max bw request in last few frames. This will the bw - * that we want to vote to CPAS now. - */ - to_be_applied_axi_vote = - cam_vfe_top_delay_bw_reduction(top_priv, - &total_bw_new_vote); - if (!to_be_applied_axi_vote) { - CAM_ERR(CAM_ISP, "to_be_applied_axi_vote is NULL"); - return -EINVAL; - } - } - - for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { - CAM_DBG(CAM_PERF, - "ife[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", - top_priv->common_data.hw_intf->hw_idx, - cam_cpas_axi_util_path_type_to_string( - to_be_applied_axi_vote->axi_path[i].path_data_type), - cam_cpas_axi_util_trans_type_to_string( - to_be_applied_axi_vote->axi_path[i].transac_type), - to_be_applied_axi_vote->axi_path[i].camnoc_bw, - to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, - to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); - } - - if ((to_be_applied_axi_vote->num_paths != - top_priv->applied_axi_vote.num_paths) || - (total_bw_new_vote != top_priv->total_bw_applied)) - apply_bw_update = true; - - CAM_DBG(CAM_PERF, - "ife[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", - top_priv->common_data.hw_intf->hw_idx, - top_priv->total_bw_applied, total_bw_new_vote, - apply_bw_update, start_stop); - - if (apply_bw_update) { - rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, - to_be_applied_axi_vote); - if (!rc) { - memcpy(&top_priv->applied_axi_vote, - to_be_applied_axi_vote, - sizeof(struct cam_axi_vote)); - top_priv->total_bw_applied = total_bw_new_vote; - } else { - CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc); - } - } + CAM_ERR(CAM_PERF, "Set Clock rate failed, rc=%d", rc); return rc; } @@ -333,7 +135,7 @@ static int cam_vfe_top_ver3_clock_update( res = clk_update->node_res; if (!res || !res->hw_intf->hw_priv) { - CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + CAM_ERR(CAM_PERF, "Invalid input res %pK", res); return -EINVAL; } @@ -341,21 +143,21 @@ static int cam_vfe_top_ver3_clock_update( if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + CAM_ERR(CAM_PERF, "VFE:%d Invalid res_type:%d res id%d", res->hw_intf->hw_idx, res->res_type, res->res_id); return -EINVAL; } - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == res->res_id) { top_priv->req_clk_rate[i] = clk_update->clk_rate; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_DBG(CAM_ISP, + CAM_DBG(CAM_PERF, "VFE:%d Not ready to set clocks yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); @@ -365,148 +167,6 @@ static int cam_vfe_top_ver3_clock_update( return rc; } -static int cam_vfe_top_ver3_bw_update_v2( - struct cam_vfe_top_ver3_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_update_args_v2 *bw_update = NULL; - struct cam_isp_resource_node *res = NULL; - struct cam_hw_info *hw_info = NULL; - int rc = 0; - int i; - - bw_update = (struct cam_vfe_bw_update_args_v2 *)cmd_args; - res = bw_update->node_res; - - if (!res || !res->hw_intf || !res->hw_intf->hw_priv) - return -EINVAL; - - hw_info = res->hw_intf->hw_priv; - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", - res->hw_intf->hw_idx, res->res_type, - res->res_id); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, - sizeof(struct cam_axi_vote)); - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - -static int cam_vfe_top_ver3_bw_update( - struct cam_vfe_top_ver3_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_update_args *bw_update = NULL; - struct cam_isp_resource_node *res = NULL; - struct cam_hw_info *hw_info = NULL; - int rc = 0; - int i; - struct cam_axi_vote *mux_axi_vote; - bool vid_exists = false; - bool rdi_exists = false; - - bw_update = (struct cam_vfe_bw_update_args *)cmd_args; - res = bw_update->node_res; - - if (!res || !res->hw_intf || !res->hw_intf->hw_priv) - return -EINVAL; - - hw_info = res->hw_intf->hw_priv; - - CAM_DBG(CAM_ISP, "res_id=%d, BW=[%lld %lld]", - res->res_id, bw_update->camnoc_bw_bytes, - bw_update->external_bw_bytes); - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", - res->hw_intf->hw_idx, res->res_type, - res->res_id); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - mux_axi_vote = &top_priv->req_axi_vote[i]; - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - mux_axi_vote->num_paths = 1; - if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && - (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_RDI0 + - (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); - } else { - /* - * Vote all bw into VIDEO path as we cannot - * differentiate to which path this has to go - */ - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_VID; - } - - mux_axi_vote->axi_path[0].transac_type = - CAM_AXI_TRANSACTION_WRITE; - mux_axi_vote->axi_path[0].camnoc_bw = - bw_update->camnoc_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ib_bw = - bw_update->external_bw_bytes; - /* Make ddr bw same as mnoc bw */ - mux_axi_vote->axi_path[0].ddr_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].ddr_ib_bw = - bw_update->external_bw_bytes; - - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - - if (mux_axi_vote->num_paths == 1) { - if (mux_axi_vote->axi_path[0].path_data_type == - CAM_AXI_PATH_DATA_IFE_VID) - vid_exists = true; - else if ((mux_axi_vote->axi_path[0].path_data_type >= - CAM_AXI_PATH_DATA_IFE_RDI0) && - (mux_axi_vote->axi_path[0].path_data_type <= - CAM_AXI_PATH_DATA_IFE_RDI3)) - rdi_exists = true; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - static int cam_vfe_core_config_control( struct cam_vfe_top_ver3_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -520,51 +180,6 @@ static int cam_vfe_core_config_control( return -EINVAL; } -static int cam_vfe_top_ver3_bw_control( - struct cam_vfe_top_ver3_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_control_args *bw_ctrl = NULL; - struct cam_isp_resource_node *res = NULL; - struct cam_hw_info *hw_info = NULL; - int rc = 0; - int i; - - bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args; - res = bw_ctrl->node_res; - - if (!res || !res->hw_intf->hw_priv) - return -EINVAL; - - hw_info = res->hw_intf->hw_priv; - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", - res->hw_intf->hw_idx, res->res_type, - res->res_id); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - top_priv->axi_vote_control[i] = bw_ctrl->action; - break; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, true); - } - - return rc; -} - static int cam_vfe_top_ver3_mux_get_reg_update( struct cam_vfe_top_ver3_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -680,14 +295,15 @@ int cam_vfe_top_ver3_reserve(void *device_priv, CAM_DBG(CAM_ISP, "res id %d", acquire_args->res_id); - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == acquire_args->res_id && - top_priv->mux_rsrc[i].res_state == + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + acquire_args->res_id && + top_priv->top_common.mux_rsrc[i].res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { rc = cam_vfe_camif_ver3_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -696,7 +312,7 @@ int cam_vfe_top_ver3_reserve(void *device_priv, if (acquire_args->res_id >= CAM_ISP_HW_VFE_IN_RDI0 && acquire_args->res_id < CAM_ISP_HW_VFE_IN_MAX) { rc = cam_vfe_camif_lite_ver3_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -704,18 +320,20 @@ int cam_vfe_top_ver3_reserve(void *device_priv, if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) { rc = cam_vfe_fe_ver1_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.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 = + top_priv->top_common.mux_rsrc[i].cdm_ops = + acquire_args->cdm_ops; + top_priv->top_common.mux_rsrc[i].tasklet_info = + args->tasklet; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_RESERVED; acquire_args->rsrc_node = - &top_priv->mux_rsrc[i]; + &top_priv->top_common.mux_rsrc[i]; rc = 0; break; @@ -757,6 +375,8 @@ int cam_vfe_top_ver3_start(void *device_priv, struct cam_vfe_top_ver3_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int rc = 0; if (!device_priv || !start_args) { @@ -765,6 +385,13 @@ int cam_vfe_top_ver3_start(void *device_priv, } top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } + mux_res = (struct cam_isp_resource_node *)start_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; @@ -776,7 +403,8 @@ int cam_vfe_top_ver3_start(void *device_priv, return rc; } - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, true); + rc = cam_vfe_top_set_axi_bw_vote(soc_private, + &top_priv->top_common, true); if (rc) { CAM_ERR(CAM_ISP, "set_axi_bw_vote failed, rc=%d", rc); @@ -823,12 +451,13 @@ int cam_vfe_top_ver3_stop(void *device_priv, } if (!rc) { - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == mux_res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + mux_res->res_id) { top_priv->req_clk_rate[i] = 0; - memset(&top_priv->req_axi_vote[i], 0, - sizeof(struct cam_axi_vote)); - top_priv->axi_vote_control[i] = + memset(&top_priv->top_common.req_axi_vote[i], + 0, sizeof(struct cam_axi_vote)); + top_priv->top_common.axi_vote_control[i] = CAM_VFE_BW_CONTROL_EXCLUDE; break; } @@ -855,12 +484,21 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, { int rc = 0; struct cam_vfe_top_ver3_priv *top_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; if (!device_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Error, Invalid arguments"); return -EINVAL; } + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: @@ -880,15 +518,16 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE: - rc = cam_vfe_top_ver3_bw_update(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: - rc = cam_vfe_top_ver3_bw_update_v2(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update_v2(soc_private, + &top_priv->top_common, cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: - rc = cam_vfe_top_ver3_bw_control(top_priv, cmd_args, arg_size); + rc = cam_vfe_top_bw_control(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_CORE_CONFIG: rc = cam_vfe_core_config_control(top_priv, cmd_args, arg_size); @@ -928,68 +567,82 @@ int cam_vfe_top_ver3_init( rc = -ENOMEM; goto free_vfe_top; } + vfe_top->top_priv = top_priv; top_priv->hw_clk_rate = 0; + if (ver3_hw_info->num_mux > CAM_VFE_TOP_MUX_MAX) { + CAM_ERR(CAM_ISP, "Invalid number of input rsrc: %d, max: %d", + ver3_hw_info->num_mux, CAM_VFE_TOP_MUX_MAX); + rc = -EINVAL; + goto free_top_priv; + } - for (i = 0, j = 0; i < CAM_VFE_TOP_VER3_MUX_MAX && + top_priv->top_common.num_mux = ver3_hw_info->num_mux; + + for (i = 0, j = 0; i < top_priv->top_common.num_mux && j < CAM_VFE_RDI_VER2_MAX; i++) { - top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN; - top_priv->mux_rsrc[i].hw_intf = hw_intf; - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].res_type = + CAM_ISP_RESOURCE_VFE_IN; + top_priv->top_common.mux_rsrc[i].hw_intf = hw_intf; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; top_priv->req_clk_rate[i] = 0; if (ver3_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_3_0) { - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_CAMIF; rc = cam_vfe_camif_ver3_init(hw_intf, soc_info, &ver3_hw_info->camif_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_PDLIB_VER_1_0) { /* set the PDLIB resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_PDLIB; rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, &ver3_hw_info->pdlib_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { /* set the RD resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RD; rc = cam_vfe_fe_ver1_init(hw_intf, soc_info, &ver3_hw_info->fe_hw_info, - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_RDI_VER_1_0) { /* set the RDI resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RDI0 + j; rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, ver3_hw_info->rdi_hw_info[j++], - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_LCR_VER_1_0) { /* set the LCR resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_LCR; rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, &ver3_hw_info->lcr_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else { @@ -1012,6 +665,7 @@ int cam_vfe_top_ver3_init( top_priv->common_data.soc_info = soc_info; top_priv->common_data.hw_intf = hw_intf; + top_priv->top_common.hw_idx = hw_intf->hw_idx; top_priv->common_data.common_reg = ver3_hw_info->common_reg; return rc; @@ -1019,22 +673,26 @@ int cam_vfe_top_ver3_init( deinit_resources: for (--i; i >= 0; i--) { if (ver3_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_3_0) { - if (cam_vfe_camif_ver3_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_camif_ver3_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif Deinit failed"); } else if (ver3_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { - if (cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif fe Deinit failed"); } else { if (cam_vfe_camif_lite_ver3_deinit( - &top_priv->mux_rsrc[i])) + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif lite res id %d Deinit failed", - top_priv->mux_rsrc[i].res_id); + top_priv->top_common.mux_rsrc[i] + .res_id); } - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; } +free_top_priv: kfree(vfe_top->top_priv); free_vfe_top: kfree(vfe_top); @@ -1066,28 +724,31 @@ int cam_vfe_top_ver3_deinit(struct cam_vfe_top **vfe_top_ptr) goto free_vfe_top; } - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - top_priv->mux_rsrc[i].res_state = + for (i = 0; i < top_priv->top_common.num_mux; i++) { + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; - if (top_priv->mux_rsrc[i].res_type == + if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_CAMIF_VER_3_0) { - rc = cam_vfe_camif_ver3_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_camif_ver3_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_IN_RD_VER_1_0) { - rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); } else { rc = cam_vfe_camif_lite_ver3_deinit( - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif lite res id %d Deinit failed", - top_priv->mux_rsrc[i].res_id); + top_priv->top_common.mux_rsrc[i] + .res_id); } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h index dd0bb94c42c7..14c96097cdf6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -9,8 +9,7 @@ #include "cam_vfe_camif_ver3.h" #include "cam_vfe_camif_lite_ver3.h" #include "cam_vfe_fe_ver1.h" - -#define CAM_VFE_TOP_VER3_MUX_MAX 6 +#include "cam_vfe_top_common.h" #define CAM_SHIFT_TOP_CORE_CFG_MUXSEL_PDAF 31 #define CAM_SHIFT_TOP_CORE_CFG_VID_DS16_R2PD 30 @@ -86,7 +85,8 @@ struct cam_vfe_top_ver3_hw_info { *rdi_hw_info[CAM_VFE_RDI_VER2_MAX]; struct cam_vfe_camif_lite_ver3_hw_info lcr_hw_info; struct cam_vfe_fe_ver1_hw_info fe_hw_info; - uint32_t mux_type[CAM_VFE_TOP_VER3_MUX_MAX]; + uint32_t num_mux; + uint32_t mux_type[CAM_VFE_TOP_MUX_MAX]; }; int cam_vfe_top_ver3_init(struct cam_hw_soc_info *soc_info, From 692d184a62181624590b3681de50e3bdc4ec65b7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:04:10 -0700 Subject: [PATCH 028/790] msm: camera: icp: lock before updating clock status Clock status can be updated in two ways, either through timer or through the recovery. In case the clock is not available during the recovery then it would try to access registers which are unclocked. To prevent this before updating the clock status spinlock should be acquired. Change-Id: I16aea5e7dafacfe6b520699af195194d5d171c7c Signed-off-by: Tejas Prajapati Signed-off-by: Jigarkumar Zala --- drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 5 +++++ drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index 73075a4ec379..7deea1c94d84 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -306,6 +306,7 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, struct cam_bps_device_core_info *core_info = NULL; struct cam_bps_device_hw_info *hw_info = NULL; int rc = 0; + unsigned long flags; if (!device_priv) { CAM_ERR(CAM_ICP, "Invalid arguments"); @@ -395,12 +396,16 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, } break; case CAM_ICP_BPS_CMD_DISABLE_CLK: + spin_lock_irqsave(&bps_dev->hw_lock, flags); if (core_info->clk_enable == true) cam_bps_toggle_clk(soc_info, false); core_info->clk_enable = false; + spin_unlock_irqrestore(&bps_dev->hw_lock, flags); break; case CAM_ICP_BPS_CMD_RESET: + spin_lock_irqsave(&bps_dev->hw_lock, flags); rc = cam_bps_cmd_reset(soc_info, core_info); + spin_unlock_irqrestore(&bps_dev->hw_lock, flags); break; default: CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type); diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 82d0ebe54cc4..614c748f0d85 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -305,6 +305,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, struct cam_ipe_device_core_info *core_info = NULL; struct cam_ipe_device_hw_info *hw_info = NULL; int rc = 0; + unsigned long flags; if (!device_priv) { CAM_ERR(CAM_ICP, "Invalid arguments"); @@ -389,12 +390,16 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, } break; case CAM_ICP_IPE_CMD_DISABLE_CLK: + spin_lock_irqsave(&ipe_dev->hw_lock, flags); if (core_info->clk_enable == true) cam_ipe_toggle_clk(soc_info, false); core_info->clk_enable = false; + spin_unlock_irqrestore(&ipe_dev->hw_lock, flags); break; case CAM_ICP_IPE_CMD_RESET: + spin_lock_irqsave(&ipe_dev->hw_lock, flags); rc = cam_ipe_cmd_reset(soc_info, core_info); + spin_unlock_irqrestore(&ipe_dev->hw_lock, flags); break; default: CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type); From 55c3fecc4baa49418183eaae560eae901eae14eb Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:05:42 -0700 Subject: [PATCH 029/790] msm: camera: lrme : Fix for lrme_hw null dereference Fixes lrme_hw pointer when lrme_hw becomes null returns with -ENODEV. Change-Id: Ic2c15ebad868b056be4ce4ac28196960a1889292 Signed-off-by: Mangalaram ARCHANA Signed-off-by: Jigarkumar Zala --- drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c index 20828f629b4d..4e2609648b30 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -237,8 +237,7 @@ static int cam_lrme_hw_dev_remove(struct platform_device *pdev) lrme_hw = platform_get_drvdata(pdev); if (!lrme_hw) { CAM_ERR(CAM_LRME, "Invalid lrme_hw from fd_hw_intf"); - rc = -ENODEV; - goto deinit_platform_res; + return -ENODEV; } lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; From 44abb0120ddbdd95e166e3993868704399d09bf0 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:22:39 -0700 Subject: [PATCH 030/790] msm: camera: cpas: Enable camnoc ubwc irqs for kona A notification is needed for camnoc ubwc encoder and decoder errors in kona which were previously disabled. Update camnoc irq register offsets and enable camnoc irq for ubwc. Change-Id: I74b7264c537122a7bda618e8be03c4ac97c23000 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Jigarkumar Zala --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 3 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 15 +++++ drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 68 ++++++++++---------- drivers/cam_cpas/include/cam_cpas_api.h | 12 ++++ 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 57eb9de92be4..0a21693732a2 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -424,6 +424,7 @@ static void cam_cpastop_work(struct work_struct *work) cpas_core, soc_info, &irq_data.u.slave_err); break; + case CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR: case CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR: case CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR: case CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: @@ -431,6 +432,8 @@ static void cam_cpastop_work(struct work_struct *work) cpas_core, soc_info, i, &irq_data.u.enc_err); break; + case CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR: + case CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR: case CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR: cam_cpastop_handle_ubwc_dec_err( cpas_core, soc_info, i, diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 8a8c61a21914..bdcf00da90b7 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -17,12 +17,21 @@ * observed at any slave port is logged into * the error logger register and an IRQ is * triggered + * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR: Triggered if any error + * detected in the IFE UBWC- + * Stats encoder instance * @CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error * detected in the IFE0 UBWC * encoder instance * @CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR : Triggered if any error * detected in the IFE1 or IFE3 * UBWC encoder instance + * @CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR: Triggered if any error + * detected in the IPE1/BPS read + * path decoder instance + * @CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR : Triggered if any error detected + * in the IPE0 read path decoder + * instance * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR: Triggered if any error * detected in the IPE/BPS * UBWC decoder instance @@ -43,6 +52,8 @@ enum cam_camnoc_hw_irq_type { CAM_CAMNOC_HW_IRQ_SLAVE_ERROR = CAM_CAMNOC_IRQ_SLAVE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR = CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR = @@ -51,6 +62,10 @@ enum cam_camnoc_hw_irq_type { CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR = CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR = + CAM_CAMNOC_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, + CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR = + CAM_CAMNOC_IRQ_IPE0_UBWC_DECODE_ERROR, CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR = CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR, CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR = diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h index fcf25383ec66..510b97062fbc 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -11,28 +11,26 @@ static struct cam_camnoc_irq_sbm cam_cpas_v480_100_irq_sbm = { .sbm_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, - .enable = false, - .offset = 0x2040, /* SBM_FAULTINEN0_LOW */ - .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ - 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + .enable = true, + .offset = 0x3840, /* SBM_FAULTINEN0_LOW */ + .value = 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 */ + 0x40 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ 0x0), }, .sbm_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */ + .offset = 0x3848, /* SBM_FAULTINSTATUS0_LOW */ }, .sbm_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */ - .value = TEST_IRQ_ENABLE ? 0x6 : 0x2, + .offset = 0x3880, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x5 : 0x1, } }; @@ -40,89 +38,89 @@ static struct cam_camnoc_irq_err cam_cpas_v480_100_irq_err[] = { { .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, - .enable = true, + .enable = false, .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */ + .offset = 0x7008, /* ERL_MAINCTL_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */ + .offset = 0x7010, /* ERL_ERRVLD_LOW */ }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */ + .offset = 0x7018, /* ERL_ERRCLR_LOW */ .value = 1, }, }, { - .irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR, + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_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, /* IFE02_ENCERREN_LOW */ + .offset = 0x1BA0, /* IFE_UBWC_STATS_ENCERREN_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x590, /* IFE02_ENCERRSTATUS_LOW */ + .offset = 0x1B90, /* IFE_UBWC_STATS_ENCERRSTATUS_LOW */ }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x598, /* IFE02_ENCERRCLR_LOW */ + .offset = 0x1B98, /* IFE_UBWC_STATS_ENCERRCLR_LOW */ .value = 1, }, }, { - .irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR, + .irq_type = CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, .enable = true, .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x9a0, /* IFE13_ENCERREN_LOW */ + .offset = 0x2520, /* IPE1_BPS_RD_DECERREN_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x990, /* IFE13_ENCERRSTATUS_LOW */ + .offset = 0x2510, /* IPE1_BPS_RD_DECERRSTATUS_LOW */ }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x998, /* IFE13_ENCERRCLR_LOW */ + .offset = 0x2518, /* IPE1_BPS_RD_DECERRCLR_LOW */ .value = 1, }, }, { - .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR, + .irq_type = CAM_CAMNOC_HW_IRQ_IPE0_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, /* IBL_RD_DECERREN_LOW */ + .offset = 0x1F20, /* IPE0_RD_DECERREN_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0xd10, /* IBL_RD_DECERRSTATUS_LOW */ + .offset = 0x1F10, /* IPE0_RD_DECERRSTATUS_LOW */ }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0xd18, /* IBL_RD_DECERRCLR_LOW */ + .offset = 0x1F18, /* IPE0_RD_DECERRCLR_LOW */ .value = 1, }, }, @@ -133,36 +131,36 @@ static struct cam_camnoc_irq_err .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x11a0, /* IBL_WR_ENCERREN_LOW */ + .offset = 0x29A0, /* IPE_BPS_WR_ENCERREN_LOW */ .value = 1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x1190, - /* IBL_WR_ENCERRSTATUS_LOW */ + .offset = 0x2990, + /* IPE_BPS_WR_ENCERRSTATUS_LOW */ }, .err_clear = { .access_type = CAM_REG_TYPE_WRITE, .enable = true, - .offset = 0x1198, /* IBL_WR_ENCERRCLR_LOW */ + .offset = 0x2998, /* IPE_BPS_WR_ENCERRCLR_LOW */ .value = 1, }, }, { .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, - .enable = true, + .enable = false, .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */ + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ .value = 0x1, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */ + .offset = 0x3890, /* SBM_FLAGOUTSTATUS0_LOW */ }, .err_clear = { .enable = false, @@ -179,17 +177,17 @@ static struct cam_camnoc_irq_err { .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, .enable = TEST_IRQ_ENABLE ? true : false, - .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */ + .sbm_port = 0x40, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ .err_enable = { .access_type = CAM_REG_TYPE_READ_WRITE, .enable = true, - .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */ + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ .value = 0x5, }, .err_status = { .access_type = CAM_REG_TYPE_READ, .enable = true, - .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */ + .offset = 0x3890, /* SBM_FLAGOUTSTATUS0_LOW */ }, .err_clear = { .enable = false, diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 932f4b2abf88..1126053e2b33 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -57,6 +57,9 @@ enum cam_cpas_hw_version { * observed at any slave port is logged into * the error logger register and an IRQ is * triggered + * @CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR: Triggered if any error detected + * in the IFE UBWC-Stats encoder + * instance * @CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error detected * in the IFE0 UBWC encoder instance * @CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR : Triggered if any error detected @@ -67,6 +70,12 @@ enum cam_cpas_hw_version { * @CAM_CAMNOC_IRQ_IFE1_WR_UBWC_ENCODE_ERROR : Triggered if any error detected * in the IFE1 UBWC encoder * instance + * @CAM_CAMNOC_IRQ_IPE1_BPS_UBWC_DECODE_ERROR: Triggered if any error detected + * in the IPE1/BPS read path decoder + * instance + * @CAM_CAMNOC_IRQ_IPE0_UBWC_DECODE_ERROR : Triggered if any error detected + * in the IPE0 read path decoder + * instance * @CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR: Triggered if any error detected * in the IPE/BPS UBWC decoder * instance @@ -78,10 +87,13 @@ enum cam_cpas_hw_version { */ enum cam_camnoc_irq_type { CAM_CAMNOC_IRQ_SLAVE_ERROR, + CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, + CAM_CAMNOC_IRQ_IPE0_UBWC_DECODE_ERROR, CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR, CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_AHB_TIMEOUT, From 87c82dcf6a5a12715dfaa3354462b2121f8d9eb5 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:23:14 -0700 Subject: [PATCH 031/790] msm: camera: smmu: Set the segment size for the context banks Set the right segment size in the driver for dma_map_sg to allow for partial cache maintanence. Change-Id: I6c439f23e957eb667bf959c830b120c0390e41b1 Signed-off-by: Karthik Anantha Ram Signed-off-by: Jigarkumar Zala --- drivers/cam_smmu/cam_smmu_api.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 7084f38daaaa..a60e02492a4c 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3474,9 +3474,24 @@ static int cam_populate_smmu_context_banks(struct device *dev, iommu_set_fault_handler(cb->domain, cam_smmu_iommu_fault_handler, (void *)cb->name); + + if (!dev->dma_parms) + dev->dma_parms = devm_kzalloc(dev, + sizeof(*dev->dma_parms), GFP_KERNEL); + + if (!dev->dma_parms) { + CAM_WARN(CAM_SMMU, + "Failed to allocate dma_params"); + dev->dma_parms = NULL; + goto end; + } + + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + dma_set_seg_boundary(dev, DMA_BIT_MASK(64)); + +end: /* increment count to next bank */ iommu_cb_set.cb_init_count++; - CAM_DBG(CAM_SMMU, "X: cb init count :%d", iommu_cb_set.cb_init_count); cb_init_fail: @@ -3488,6 +3503,7 @@ static int cam_smmu_probe(struct platform_device *pdev) int rc = 0; struct device *dev = &pdev->dev; + dev->dma_parms = NULL; if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu")) { rc = cam_alloc_smmu_context_banks(dev); if (rc < 0) { @@ -3536,8 +3552,15 @@ static int cam_smmu_probe(struct platform_device *pdev) static int cam_smmu_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + /* release all the context banks and memory allocated */ cam_smmu_reset_iommu_table(CAM_SMMU_TABLE_DEINIT); + if (dev && dev->dma_parms) { + devm_kfree(dev, dev->dma_parms); + dev->dma_parms = NULL; + } + if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-cam-smmu")) cam_smmu_release_cb(pdev); return 0; From 4a8af1ed194f3289a78b657946f07b4a073a7169 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:23:53 -0700 Subject: [PATCH 032/790] msm: camera: isp: Fix rdi only usecase Initialize common_reg data for rdi. Adds acquire handling for RDI usecase. Change-Id: I06cc9bf86af834ceeb145e9b49586c97b6f1a461 Signed-off-by: Trishansh Bhardwaj Signed-off-by: Jigarkumar Zala --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 8 ++++++++ .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 4 +++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index f356d6c24b20..aab38c791637 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -56,6 +56,13 @@ static struct cam_vfe_rdi_ver2_reg vfe17x_rdi_reg = { .reg_update_cmd = 0x000004AC, }; +static struct cam_vfe_rdi_common_reg_data vfe17x_rdi_reg_data = { + .subscribe_irq_mask0 = 0x780001E0, + .subscribe_irq_mask1 = 0x0, + .error_irq_mask0 = 0x0, + .error_irq_mask1 = 0x3C, +}; + static struct cam_vfe_rdi_reg_data vfe17x_rdi_0_data = { .reg_update_cmd_data = 0x2, .sof_irq_mask = 0x8000000, @@ -90,6 +97,7 @@ static struct cam_vfe_top_ver2_hw_info vfe17x_top_hw_info = { .rdi_hw_info = { .common_reg = &vfe17x_top_common_reg, .rdi_reg = &vfe17x_rdi_reg, + .common_reg_data = &vfe17x_rdi_reg_data, .reg_data = { &vfe17x_rdi_0_data, &vfe17x_rdi_1_data, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index 0b230ce19621..3cc92551b79c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -413,7 +413,9 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); ret = CAM_VFE_IRQ_STATUS_SUCCESS; - } else if (irq_status0 & rdi_priv->reg_data->reg_update_irq_mask) { + } + + if (irq_status0 & rdi_priv->reg_data->reg_update_irq_mask) { CAM_DBG(CAM_ISP, "Received REG UPDATE"); if (rdi_priv->event_cb) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index e057b15aee43..c5225c540722 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -276,6 +276,17 @@ int cam_vfe_top_reserve(void *device_priv, break; } + if ((acquire_args->res_id >= + CAM_ISP_HW_VFE_IN_RDI0) && + (acquire_args->res_id <= + CAM_ISP_HW_VFE_IN_RDI3)) { + rc = cam_vfe_rdi_ver2_acquire_resource( + &top_priv->top_common.mux_rsrc[i], + args); + if (rc) + break; + } + if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) { rc = cam_vfe_fe_ver1_acquire_resource( &top_priv->top_common.mux_rsrc[i], From 4767766efb1c98a667936410af2f3425faa330b8 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:24:35 -0700 Subject: [PATCH 033/790] msm: camera: Fix usage of invalid array index Fix array index validation number of axi ports while setup/cleanup axi related settings. Also validate the array index for slot index for CRM and updates operation accordingly. Change-Id: Ic42939b7c59a5602b82a19f558030552bf3c0b72 Signed-off-by: Jigarkumar Zala --- drivers/cam_cpas/cam_cpas_hw.c | 12 ++++++++++++ drivers/cam_req_mgr/cam_req_mgr_core.c | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index d180b4ecf9aa..1a7a5e2b053e 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -236,6 +236,12 @@ static int cam_cpas_util_axi_cleanup(struct cam_cpas *cpas_core, { int i = 0; + if (cpas_core->num_axi_ports > CAM_CPAS_MAX_AXI_PORTS) { + CAM_ERR(CAM_CPAS, "Invalid num_axi_ports: %d", + cpas_core->num_axi_ports); + return -EINVAL; + } + for (i = 0; i < cpas_core->num_axi_ports; i++) { cam_cpas_util_unregister_bus_client( &cpas_core->axi_port[i].bus_client); @@ -252,6 +258,12 @@ static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core, int i = 0, rc = 0; struct device_node *axi_port_mnoc_node = NULL; + if (cpas_core->num_axi_ports > CAM_CPAS_MAX_AXI_PORTS) { + CAM_ERR(CAM_CPAS, "Invalid num_axi_ports: %d", + cpas_core->num_axi_ports); + return -EINVAL; + } + for (i = 0; i < cpas_core->num_axi_ports; i++) { axi_port_mnoc_node = cpas_core->axi_port[i].axi_port_node; rc = cam_cpas_util_register_bus_client(soc_info, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index e6c9d97b1c97..6e660a393824 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -979,6 +979,7 @@ static int __cam_req_mgr_check_sync_req_is_ready( CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", req_id, sync_link->link_hdl); sync_ready = false; + return -EAGAIN; } sync_rd_idx = sync_link->req.in_q->rd_idx; From 6761503d24604eb8f518fa1d415ae6a60d97668f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 13:21:20 -0700 Subject: [PATCH 034/790] msm: camera: crm: Increase the device handles to 128 Increasing the device handles to 128 to support more pipelines. Change-Id: Id0322cba095091e6168d8541d432628d8422a641 Signed-off-by: Mangalaram ARCHANA Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_req_mgr_core.c | 160 +++++++++++++++++++++---- drivers/cam_req_mgr/cam_req_mgr_core.h | 7 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 37 ++++-- include/uapi/media/cam_req_mgr.h | 18 ++- 4 files changed, 192 insertions(+), 30 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 6e660a393824..f4867d5d828e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2438,7 +2438,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = { * */ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, - struct cam_req_mgr_link_info *link_info) + struct cam_req_mgr_ver_info *link_info) { int rc = 0, i = 0; struct cam_req_mgr_core_dev_link_setup link_data; @@ -2446,10 +2446,16 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, struct cam_req_mgr_req_tbl *pd_tbl; enum cam_pipeline_delay max_delay; uint32_t subscribe_event = 0; - - if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) - return -EPERM; - + if (link_info->version == VERSION_1) { + if (link_info->u.link_info_v1.num_devices > + CAM_REQ_MGR_MAX_HANDLES) + return -EPERM; + } + else if (link_info->version == VERSION_2) { + if (link_info->u.link_info_v2.num_devices > + CAM_REQ_MGR_MAX_HANDLES_V2) + return -EPERM; + } mutex_init(&link->req.lock); CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock); link->req.num_tbl = 0; @@ -2459,11 +2465,12 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, return rc; max_delay = CAM_PIPELINE_DELAY_0; - for (i = 0; i < link_info->num_devices; i++) { + for (i = 0; i < link_info->u.link_info_v1.num_devices; i++) { dev = &link->l_dev[i]; /* Using dev hdl, get ops ptr to communicate with device */ dev->ops = (struct cam_req_mgr_kmd_ops *) - cam_get_device_ops(link_info->dev_hdls[i]); + cam_get_device_ops( + link_info->u.link_info_v1.dev_hdls[i]); if (!dev->ops || !dev->ops->get_dev_info || !dev->ops->link_setup) { @@ -2471,7 +2478,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, rc = -ENXIO; goto error; } - dev->dev_hdl = link_info->dev_hdls[i]; + dev->dev_hdl = link_info->u.link_info_v1.dev_hdls[i]; dev->parent = (void *)link; dev->dev_info.dev_hdl = dev->dev_hdl; rc = dev->ops->get_dev_info(&dev->dev_info); @@ -2480,7 +2487,8 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, CAM_DBG(CAM_CRM, "%x: connected: %s, id %d, delay %d, trigger %x", - link_info->session_hdl, dev->dev_info.name, + link_info->u.link_info_v1.session_hdl, + dev->dev_info.name, dev->dev_info.dev_id, dev->dev_info.p_delay, dev->dev_info.trigger); if (rc < 0 || @@ -2492,7 +2500,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, goto error; } else { CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d", - link_info->session_hdl, + link_info->u.link_info_v1.session_hdl, dev->dev_info.name, dev->dev_info.p_delay); if (dev->dev_info.p_delay > max_delay) @@ -2509,7 +2517,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, link_data.max_delay = max_delay; link_data.subscribe_event = subscribe_event; - for (i = 0; i < link_info->num_devices; i++) { + for (i = 0; i < link_info->u.link_info_v1.num_devices; i++) { dev = &link->l_dev[i]; link_data.dev_hdl = dev->dev_hdl; @@ -2552,7 +2560,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, if (link->max_delay < dev->dev_info.p_delay) link->max_delay = dev->dev_info.p_delay; } - link->num_devs = link_info->num_devices; + link->num_devs = link_info->u.link_info_v1.num_devices; /* Assign id for pd tables */ __cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req); @@ -2710,7 +2718,7 @@ end: return rc; } -int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) +int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info) { int rc = 0; int wq_flag = 0; @@ -2723,9 +2731,9 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) CAM_DBG(CAM_CRM, "NULL pointer"); return -EINVAL; } - if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) { + if (link_info->u.link_info_v1.num_devices > CAM_REQ_MGR_MAX_HANDLES) { CAM_ERR(CAM_CRM, "Invalid num devices %d", - link_info->num_devices); + link_info->u.link_info_v1.num_devices); return -EINVAL; } @@ -2733,7 +2741,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) /* 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); + cam_get_device_priv(link_info->u.link_info_v1.session_hdl); if (!cam_session) { CAM_DBG(CAM_CRM, "NULL pointer"); mutex_unlock(&g_crm_core_dev->crm_lock); @@ -2750,7 +2758,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl); memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl)); - root_dev.session_hdl = link_info->session_hdl; + root_dev.session_hdl = link_info->u.link_info_v1.session_hdl; root_dev.priv = (void *)link; mutex_lock(&link->lock); @@ -2762,12 +2770,12 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) rc = link->link_hdl; goto link_hdl_fail; } - link_info->link_hdl = link->link_hdl; + link_info->u.link_info_v1.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, - link_info->num_devices); + link_info->u.link_info_v1.num_devices); if (rc < 0) { CAM_ERR(CAM_CRM, "Insufficient memory to create new crm subdevs"); @@ -2785,7 +2793,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) /* Create worker for current link */ snprintf(buf, sizeof(buf), "%x-%x", - link_info->session_hdl, link->link_hdl); + link_info->u.link_info_v1.session_hdl, link->link_hdl); wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL; rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS, &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag); @@ -2810,7 +2818,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 = -1; + link_info->u.link_info_v1.link_hdl = -1; link_hdl_fail: mutex_unlock(&link->lock); __cam_req_mgr_unreserve_link(cam_session, link); @@ -2818,6 +2826,116 @@ link_hdl_fail: return rc; } +int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) +{ + int rc = 0; + int wq_flag = 0; + char buf[128]; + struct cam_create_dev_hdl root_dev; + struct cam_req_mgr_core_session *cam_session; + struct cam_req_mgr_core_link *link; + + if (!link_info) { + CAM_DBG(CAM_CRM, "NULL pointer"); + return -EINVAL; + } + if (link_info->u.link_info_v2.num_devices > + CAM_REQ_MGR_MAX_HANDLES_V2) { + CAM_ERR(CAM_CRM, "Invalid num devices %d", + link_info->u.link_info_v2.num_devices); + 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->u.link_info_v2.session_hdl); + if (!cam_session) { + CAM_DBG(CAM_CRM, "NULL pointer"); + mutex_unlock(&g_crm_core_dev->crm_lock); + return -EINVAL; + } + + /* Allocate link struct and map it with session's request queue */ + link = __cam_req_mgr_reserve_link(cam_session); + if (!link) { + CAM_ERR(CAM_CRM, "failed to reserve new link"); + mutex_unlock(&g_crm_core_dev->crm_lock); + return -EINVAL; + } + CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl); + + memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl)); + root_dev.session_hdl = link_info->u.link_info_v2.session_hdl; + root_dev.priv = (void *)link; + + mutex_lock(&link->lock); + /* Create unique dev handle for link */ + link->link_hdl = cam_create_device_hdl(&root_dev); + if (link->link_hdl < 0) { + CAM_ERR(CAM_CRM, + "Insufficient memory to create new device handle"); + rc = link->link_hdl; + goto link_hdl_fail; + } + link_info->u.link_info_v2.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, + link_info->u.link_info_v2.num_devices); + if (rc < 0) { + CAM_ERR(CAM_CRM, + "Insufficient memory to create new crm subdevs"); + goto create_subdev_failed; + } + + /* Using device ops query connected devs, prepare request tables */ + rc = __cam_req_mgr_setup_link_info(link, link_info); + if (rc < 0) + goto setup_failed; + + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_READY; + spin_unlock_bh(&link->link_state_spin_lock); + + /* Create worker for current link */ + snprintf(buf, sizeof(buf), "%x-%x", + link_info->u.link_info_v2.session_hdl, link->link_hdl); + wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL; + rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS, + &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag); + if (rc < 0) { + CAM_ERR(CAM_CRM, "FATAL: unable to create worker"); + __cam_req_mgr_destroy_link_info(link); + goto setup_failed; + } + + /* Assign payload to workqueue tasks */ + rc = __cam_req_mgr_setup_payload(link->workq); + if (rc < 0) { + __cam_req_mgr_destroy_link_info(link); + cam_req_mgr_workq_destroy(&link->workq); + goto setup_failed; + } + + mutex_unlock(&link->lock); + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +setup_failed: + __cam_req_mgr_destroy_subdev(link->l_dev); +create_subdev_failed: + cam_destroy_device_hdl(link->link_hdl); + link_info->u.link_info_v2.link_hdl = -1; +link_hdl_fail: + mutex_unlock(&link->lock); + __cam_req_mgr_unreserve_link(cam_session, link); + mutex_unlock(&g_crm_core_dev->crm_lock); + return rc; +} + + int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info) { int rc = 0; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 9a6acbc2c43e..8eb15bec802d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -31,6 +31,9 @@ #define MAXIMUM_RETRY_ATTEMPTS 3 +#define VERSION_1 1 +#define VERSION_2 2 + /** * enum crm_workq_task_type * @codes: to identify which type of task is present @@ -408,7 +411,9 @@ int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info); * a unique link handle for the link and is specific to a * session. Returns link handle */ -int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info); +int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info); +int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info); + /** * cam_req_mgr_unlink() diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 74d5cfff8d60..b1a05cc14b9a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #include @@ -261,27 +261,50 @@ static long cam_private_ioctl(struct file *file, void *fh, break; case CAM_REQ_MGR_LINK: { - struct cam_req_mgr_link_info link_info; + struct cam_req_mgr_ver_info ver_info; - if (k_ioctl->size != sizeof(link_info)) + if (k_ioctl->size != sizeof(ver_info.u.link_info_v1)) return -EINVAL; - if (copy_from_user(&link_info, + if (copy_from_user(&ver_info.u.link_info_v1, u64_to_user_ptr(k_ioctl->handle), sizeof(struct cam_req_mgr_link_info))) { return -EFAULT; } - - rc = cam_req_mgr_link(&link_info); + ver_info.version = VERSION_1; + rc = cam_req_mgr_link(&ver_info); if (!rc) if (copy_to_user( u64_to_user_ptr(k_ioctl->handle), - &link_info, + &ver_info.u.link_info_v1, sizeof(struct cam_req_mgr_link_info))) rc = -EFAULT; } break; + case CAM_REQ_MGR_LINK_V2: { + struct cam_req_mgr_ver_info ver_info; + + if (k_ioctl->size != sizeof(ver_info.u.link_info_v2)) + return -EINVAL; + + if (copy_from_user(&ver_info.u.link_info_v2, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_req_mgr_link_info_v2))) { + return -EFAULT; + } + + ver_info.version = VERSION_2; + rc = cam_req_mgr_link_v2(&ver_info); + if (!rc) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &ver_info.u.link_info_v2, + sizeof(struct cam_req_mgr_link_info_v2))) + rc = -EFAULT; + } + break; + case CAM_REQ_MGR_UNLINK: { struct cam_req_mgr_unlink_info unlink_info; diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index f495eb883fcd..a8c12e2d7c0d 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_LINUX_CAM_REQ_MGR_H @@ -40,6 +40,7 @@ * It includes both session and device handles */ #define CAM_REQ_MGR_MAX_HANDLES 64 +#define CAM_REQ_MGR_MAX_HANDLES_V2 128 #define MAX_LINKS_PER_SESSION 2 /* V4L event type which user space will subscribe to */ @@ -126,6 +127,20 @@ struct cam_req_mgr_link_info { int32_t link_hdl; }; +struct cam_req_mgr_link_info_v2 { + int32_t session_hdl; + uint32_t num_devices; + int32_t dev_hdls[CAM_REQ_MGR_MAX_HANDLES_V2]; + int32_t link_hdl; +}; + +struct cam_req_mgr_ver_info { + uint32_t version; + union { + struct cam_req_mgr_link_info link_info_v1; + struct cam_req_mgr_link_info_v2 link_info_v2; + } u; +}; /** * struct cam_req_mgr_unlink_info * @session_hdl: input param - session handle @@ -235,6 +250,7 @@ struct cam_req_mgr_link_control { #define CAM_REQ_MGR_RELEASE_BUF (CAM_COMMON_OPCODE_MAX + 11) #define CAM_REQ_MGR_CACHE_OPS (CAM_COMMON_OPCODE_MAX + 12) #define CAM_REQ_MGR_LINK_CONTROL (CAM_COMMON_OPCODE_MAX + 13) +#define CAM_REQ_MGR_LINK_V2 (CAM_COMMON_OPCODE_MAX + 14) /* end of cam_req_mgr opcodes */ #define CAM_MEM_FLAG_HW_READ_WRITE (1<<0) From aa0f96d02cdf7dbc41b3346fa8312cad23b9f2a6 Mon Sep 17 00:00:00 2001 From: Mangalaram ARCHANA Date: Fri, 31 May 2019 12:01:37 +0530 Subject: [PATCH 035/790] msm: camera: crm: Handle link setup based on version With the increase in the device handles, the corresponding link info structure is changed. Handle setting up link based on the right structure version. Change-Id: I0d21866ba0bc4abfe78941e191688773441ce03f Signed-off-by: Mangalaram ARCHANA Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_req_mgr_core.c | 65 ++++++++++++++++++-------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index f4867d5d828e..a9edecc44ab4 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2440,7 +2440,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = { static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, struct cam_req_mgr_ver_info *link_info) { - int rc = 0, i = 0; + int rc = 0, i = 0, num_devices = 0; struct cam_req_mgr_core_dev_link_setup link_data; struct cam_req_mgr_connected_device *dev; struct cam_req_mgr_req_tbl *pd_tbl; @@ -2465,12 +2465,21 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, return rc; max_delay = CAM_PIPELINE_DELAY_0; - for (i = 0; i < link_info->u.link_info_v1.num_devices; i++) { + if (link_info->version == VERSION_1) + num_devices = link_info->u.link_info_v1.num_devices; + else if (link_info->version == VERSION_2) + num_devices = link_info->u.link_info_v2.num_devices; + for (i = 0; i < num_devices; i++) { dev = &link->l_dev[i]; /* Using dev hdl, get ops ptr to communicate with device */ - dev->ops = (struct cam_req_mgr_kmd_ops *) - cam_get_device_ops( - link_info->u.link_info_v1.dev_hdls[i]); + if (link_info->version == VERSION_1) + dev->ops = (struct cam_req_mgr_kmd_ops *) + cam_get_device_ops( + link_info->u.link_info_v1.dev_hdls[i]); + else if (link_info->version == VERSION_2) + dev->ops = (struct cam_req_mgr_kmd_ops *) + cam_get_device_ops( + link_info->u.link_info_v2.dev_hdls[i]); if (!dev->ops || !dev->ops->get_dev_info || !dev->ops->link_setup) { @@ -2478,19 +2487,29 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, rc = -ENXIO; goto error; } - dev->dev_hdl = link_info->u.link_info_v1.dev_hdls[i]; + if (link_info->version == VERSION_1) + dev->dev_hdl = link_info->u.link_info_v1.dev_hdls[i]; + else if (link_info->version == VERSION_2) + dev->dev_hdl = link_info->u.link_info_v2.dev_hdls[i]; dev->parent = (void *)link; dev->dev_info.dev_hdl = dev->dev_hdl; rc = dev->ops->get_dev_info(&dev->dev_info); trace_cam_req_mgr_connect_device(link, &dev->dev_info); - - CAM_DBG(CAM_CRM, - "%x: connected: %s, id %d, delay %d, trigger %x", - link_info->u.link_info_v1.session_hdl, - dev->dev_info.name, - dev->dev_info.dev_id, dev->dev_info.p_delay, - dev->dev_info.trigger); + if (link_info->version == VERSION_1) + CAM_DBG(CAM_CRM, + "%x: connected: %s, id %d, delay %d, trigger %x", + link_info->u.link_info_v1.session_hdl, + dev->dev_info.name, + dev->dev_info.dev_id, dev->dev_info.p_delay, + dev->dev_info.trigger); + else if (link_info->version == VERSION_2) + CAM_DBG(CAM_CRM, + "%x: connected: %s, id %d, delay %d, trigger %x", + link_info->u.link_info_v2.session_hdl, + dev->dev_info.name, + dev->dev_info.dev_id, dev->dev_info.p_delay, + dev->dev_info.trigger); if (rc < 0 || dev->dev_info.p_delay >= CAM_PIPELINE_DELAY_MAX || @@ -2499,10 +2518,18 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, CAM_ERR(CAM_CRM, "get device info failed"); goto error; } else { - CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d", - link_info->u.link_info_v1.session_hdl, - dev->dev_info.name, - dev->dev_info.p_delay); + if (link_info->version == VERSION_1) { + CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d", + link_info->u.link_info_v1.session_hdl, + dev->dev_info.name, + dev->dev_info.p_delay); + } + else if (link_info->version == VERSION_2) { + CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d", + link_info->u.link_info_v2.session_hdl, + dev->dev_info.name, + dev->dev_info.p_delay); + } if (dev->dev_info.p_delay > max_delay) max_delay = dev->dev_info.p_delay; @@ -2517,7 +2544,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, link_data.max_delay = max_delay; link_data.subscribe_event = subscribe_event; - for (i = 0; i < link_info->u.link_info_v1.num_devices; i++) { + for (i = 0; i < num_devices; i++) { dev = &link->l_dev[i]; link_data.dev_hdl = dev->dev_hdl; @@ -2560,7 +2587,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, if (link->max_delay < dev->dev_info.p_delay) link->max_delay = dev->dev_info.p_delay; } - link->num_devs = link_info->u.link_info_v1.num_devices; + link->num_devs = num_devices; /* Assign id for pd tables */ __cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req); From a89607a875135eec2c179dbc094b7fd444d9b574 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 11 Jul 2019 20:15:40 +0800 Subject: [PATCH 036/790] Camera: sensor: Power off the sensor if no gpios Power off the sensor if no gpios at the time of power on, since some regulator and clk need to be released. Change-Id: Ie200459276b5327a1627e8839ec404c3c26f4205 Signed-off-by: Depeng Shao Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 4a2a2a8855b2..f5ea2dc04a3d 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1658,7 +1658,7 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, case SENSOR_CUSTOM_GPIO2: if (no_gpio) { CAM_ERR(CAM_SENSOR, "request gpio failed"); - return no_gpio; + goto power_up_failed; } if (!gpio_num_info) { CAM_ERR(CAM_SENSOR, "Invalid gpio_num_info"); From f458d1d231787b9ec53a1c8551d098d9b9cbe7d5 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 6 Aug 2019 10:46:50 -0700 Subject: [PATCH 037/790] msm: camera: isp: Add support for QCFA CSID binning Add support to configure CSID binning for QCFA. Change-Id: I9e2673d89f521a4b4fddc41ad1217ffe229d8b01 Signed-off-by: Tejas Prajapati Signed-off-by: Trishansh Bhardwaj Signed-off-by: Jigarkumar Zala --- drivers/cam_cpas/cam_cpas_intf.c | 27 ++++++++ drivers/cam_cpas/cam_cpas_soc.c | 42 ++++++++++++ drivers/cam_cpas/cam_cpas_soc.h | 2 + drivers/cam_cpas/include/cam_cpas_api.h | 13 ++++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 68 +++++++++++++++++++ .../isp_hw/ife_csid_hw/cam_ife_csid175_200.h | 3 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 29 ++++++++ .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 ++ .../isp_hw/include/cam_ife_csid_hw_intf.h | 9 +++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + 10 files changed, 197 insertions(+), 1 deletion(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index e43d9f01ec2c..d1b32a0d916a 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -12,9 +12,11 @@ #include #include #include +#include #include "cam_subdev.h" #include "cam_cpas_hw_intf.h" +#include "cam_cpas_soc.h" #define CAM_CPAS_DEV_NAME "cam-cpas" #define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done) @@ -104,6 +106,31 @@ const char *cam_cpas_axi_util_trans_type_to_string( } EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string); +int cam_cpas_is_feature_supported(uint32_t flag) +{ + struct cam_hw_info *cpas_hw = NULL; + struct cam_cpas_private_soc *soc_private = NULL; + uint32_t feature_mask; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv; + soc_private = + (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private; + feature_mask = soc_private->feature_mask; + + if (flag >= CAM_CPAS_FUSE_FEATURE_MAX) { + CAM_ERR(CAM_CPAS, "Unknown feature flag %x", flag); + return -EINVAL; + } + + return feature_mask & flag ? 1 : 0; +} +EXPORT_SYMBOL(cam_cpas_is_feature_supported); + int cam_cpas_get_cpas_hw_version(uint32_t *hw_version) { struct cam_hw_info *cpas_hw = NULL; diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index 6c34dd0687e6..c86753dd24d9 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -349,6 +349,45 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, return 0; } + +int cam_cpas_get_hw_features(struct platform_device *pdev, + struct cam_cpas_private_soc *soc_private) +{ + struct device_node *of_node; + void *fuse; + uint32_t fuse_addr, fuse_bit; + uint32_t fuse_val = 0, feature_bit_pos; + int count = 0, i = 0; + + of_node = pdev->dev.of_node; + count = of_property_count_u32_elems(of_node, "cam_hw_fuse"); + + for (i = 0; (i + 3) <= count; i = i + 3) { + of_property_read_u32_index(of_node, "cam_hw_fuse", i, + &feature_bit_pos); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1, + &fuse_addr); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2, + &fuse_bit); + CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d", + feature_bit_pos, fuse_addr, fuse_bit); + + fuse = ioremap(fuse_addr, 4); + if (fuse) { + fuse_val = cam_io_r(fuse); + if (fuse_val & BIT(fuse_bit)) + soc_private->feature_mask |= feature_bit_pos; + else + soc_private->feature_mask &= ~feature_bit_pos; + } + CAM_INFO(CAM_CPAS, "fuse %pK, fuse_val %x, feature_mask %x", + fuse, fuse_val, soc_private->feature_mask); + + } + + return 0; +} + int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, struct platform_device *pdev, struct cam_cpas_private_soc *soc_private) { @@ -363,6 +402,7 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, } of_node = pdev->dev.of_node; + soc_private->feature_mask = 0xFFFFFFFF; rc = of_property_read_string(of_node, "arch-compat", &soc_private->arch_compat); @@ -372,6 +412,8 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, return rc; } + cam_cpas_get_hw_features(pdev, soc_private); + soc_private->camnoc_axi_min_ib_bw = 0; rc = of_property_read_u64(of_node, "camnoc-axi-min-ib-bw", diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index 7921cd4b956e..fea9c3c97593 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -87,6 +87,7 @@ struct cam_cpas_tree_node { * @camnoc_axi_clk_bw_margin : BW Margin in percentage to add while calculating * camnoc axi clock * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target + * @feature_mask: feature mask value for hw supported features * */ struct cam_cpas_private_soc { @@ -103,6 +104,7 @@ struct cam_cpas_private_soc { uint32_t camnoc_bus_width; uint32_t camnoc_axi_clk_bw_margin; uint64_t camnoc_axi_min_ib_bw; + uint32_t feature_mask; }; void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 1126053e2b33..7c551dfcf8a5 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -525,6 +525,19 @@ int cam_cpas_get_hw_info( int cam_cpas_get_cpas_hw_version( uint32_t *hw_version); +/** + * cam_cpas_is_feature_supported() + * + * @brief: API to get camera features + * + * @flag : Camera hw features to check + * + * @return 1 if feature is supported + * + */ +int cam_cpas_is_feature_supported( + uint32_t flag); + /** * cam_cpas_axi_util_path_type_to_string() * diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 75f157f0d5b8..e58a965492da 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4236,6 +4236,54 @@ static int cam_isp_blob_csid_clock_update( return rc; } +static int cam_isp_blob_csid_qcfa_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_csid_qcfa_config *qcfa_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; + struct cam_ife_csid_qcfa_update_args csid_qcfa_upd_args; + int rc = -EINVAL; + uint32_t i; + + ctx = prepare->ctxt_to_hw_map; + + CAM_DBG(CAM_ISP, + "csid binning=%d", qcfa_config->csid_binning); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + + if (!hw_mgr_res->hw_res[i] || + hw_mgr_res->res_id != CAM_IFE_PIX_PATH_RES_IPP) + continue; + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + csid_qcfa_upd_args.qcfa_binning = + qcfa_config->csid_binning; + CAM_DBG(CAM_ISP, "i= %d QCFA binning=%d\n", + i, csid_qcfa_upd_args.qcfa_binning); + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED, + &csid_qcfa_upd_args, + sizeof( + struct cam_ife_csid_qcfa_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "QCFA Update failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + static int cam_isp_blob_core_cfg_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, @@ -4848,6 +4896,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, clock_config, prepare); if (rc) CAM_ERR(CAM_ISP, "Clock Update Failed"); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG: { + struct cam_isp_csid_qcfa_config *qcfa_config; + + if (blob_size < sizeof(struct cam_isp_csid_qcfa_config)) { + CAM_ERR(CAM_ISP, + "Invalid qcfa blob size %u expected %u", + blob_size, + sizeof(struct cam_isp_csid_qcfa_config)); + return -EINVAL; + } + + qcfa_config = (struct cam_isp_csid_qcfa_config *)blob_data; + + rc = cam_isp_blob_csid_qcfa_update(blob_type, blob_info, + qcfa_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "QCFA Update Failed rc: %d", rc); + } break; case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h index 7d47da31e4a8..869fd8cd61c9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_175_200_H_ @@ -47,6 +47,7 @@ static struct cam_ife_csid_pxl_reg_offset /* configurations */ .pix_store_en_shift_val = 7, .early_eof_en_shift_val = 29, + .quad_cfa_bin_en_shift_val = 30, .ccif_violation_en = 1, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 252c1a5aa36a..9503f204d410 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -8,6 +8,8 @@ #include #include +#include + #include "cam_ife_csid_core.h" #include "cam_isp_hw.h" #include "cam_soc_util.h" @@ -1611,6 +1613,10 @@ static int cam_ife_csid_init_config_pxl_path( val |= (1 << pxl_reg->quad_cfa_bin_en_shift_val); } + if (is_ipp && csid_hw->binning_supported && + csid_hw->binning_enable) + val |= (1 << pxl_reg->quad_cfa_bin_en_shift_val); + val |= (1 << pxl_reg->pix_store_en_shift_val); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); @@ -3124,6 +3130,23 @@ static int cam_ife_csid_set_csid_clock( return 0; } +static int cam_ife_csid_set_csid_qcfa( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_csid_qcfa_update_args *qcfa_update = NULL; + + if (!csid_hw) + return -EINVAL; + + qcfa_update = + (struct cam_ife_csid_qcfa_update_args *)cmd_args; + + csid_hw->binning_supported = qcfa_update->qcfa_binning; + CAM_DBG(CAM_ISP, "CSID QCFA binning %d", csid_hw->binning_supported); + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -3158,6 +3181,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE: rc = cam_ife_csid_set_csid_clock(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED: + rc = cam_ife_csid_set_csid_qcfa(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -3601,6 +3627,9 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, goto err; } + if (cam_cpas_is_feature_supported(CAM_CPAS_QCFA_BINNING_ENABLE) == 1) + ife_csid_hw->binning_enable = 1; + ife_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_ife_csid_get_hw_caps; ife_csid_hw->hw_intf->hw_ops.init = cam_ife_csid_init_hw; ife_csid_hw->hw_intf->hw_ops.deinit = cam_ife_csid_deinit_hw; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 3e998858b596..d4a3a840d969 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -482,6 +482,8 @@ struct cam_ife_csid_path_cfg { * @irq_debug_cnt: Counter to track sof irq's when above flag is set. * @error_irq_count Error IRQ count, if continuous error irq comes * need to stop the CSID and mask interrupts. + * @binning_enable Flag is set if hardware supports QCFA binning + * @binning_supported Flag is set if sensor supports QCFA binning * */ struct cam_ife_csid_hw { @@ -510,6 +512,8 @@ struct cam_ife_csid_hw { uint32_t error_irq_count; uint32_t device_enabled; spinlock_t lock_state; + uint32_t binning_enable; + uint32_t binning_supported; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index d8ba811c7ad5..e31cddc91b11 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -222,5 +222,14 @@ struct cam_ife_csid_clock_update_args { uint64_t clk_rate; }; +/* + * struct cam_ife_csid_qcfa_update_args: + * + * @qcfa_binning: QCFA binning supported + */ +struct cam_ife_csid_qcfa_update_args { + uint32_t qcfa_binning; +}; + #endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 33254c1610ae..1e556137996d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -100,6 +100,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_UBWC_UPDATE_V2, CAM_ISP_HW_CMD_CORE_CONFIG, CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, + CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED, CAM_ISP_HW_CMD_MAX, }; From 45125cf020684446ee66753750ce138e3dee581b Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 19 Jul 2019 18:26:35 +0530 Subject: [PATCH 038/790] msm: camera: Fuse base secure camera enablement Query secure camera capability from fuse, and enable only if supported. Change-Id: I4ff3c5afbf7c924368c95af5517a047149124c3e Signed-off-by: Trishansh Bhardwaj Signed-off-by: Jigarkumar Zala --- .../cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index adf9ef82ee45..f4bdfff2cb97 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -10,9 +10,11 @@ #include "cam_common_util.h" #include "cam_packet_util.h" +#include #include #include +#include #define SCM_SVC_CAMERASS 0x18 #define SECURE_SYSCALL_ID 0x6 @@ -914,6 +916,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) { + if (cam_cpas_is_feature_supported( + CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { + CAM_ERR(CAM_CSIPHY, + "sec_cam: camera fuse bit not set"); + cam_cpas_stop(csiphy_dev->cpas_handle); + rc = -1; + goto release_mutex; + } + rc = cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_SECURE, offset); From a6efb05c3ffe97f2bd234f695870a5525249bb2d Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 17 Jul 2019 17:24:18 -0700 Subject: [PATCH 039/790] msm: camera: isp: Move req out of pending list before start This change moves init request out of pending list before starting hardware. Currently if we receive the first SOF and RUP IRQs before start_dev routine has completed, we miss pushing out the init request to free list on the first RUP as wait list will be empty. Change-Id: Icd53e0ebe0d12e264172058d836e6ccfcb7df0c2 Signed-off-by: Venkat Chinta Signed-off-by: Jigarkumar Zala --- drivers/cam_isp/cam_isp_context.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 84f5e4937a9e..9c0d4d6c2817 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3368,6 +3368,21 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } + /* + * In case of CSID TPG we might receive SOF and RUP IRQs + * before hw_mgr_intf->hw_start has returned. So move + * req out of pending list before hw_start and add it + * back to pending list if hw_start fails. + */ + list_del_init(&req->list); + + if (req_isp->num_fence_map_out) { + list_add_tail(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; + } else { + list_add_tail(&req->list, &ctx->wait_req_list); + } + start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.hw_config.request_id = req->request_id; start_isp.hw_config.hw_update_entries = req_isp->cfg; @@ -3401,18 +3416,12 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, CAM_ERR(CAM_ISP, "Start HW failed"); ctx->state = CAM_CTX_READY; trace_cam_context_state("ISP", ctx); + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); goto end; } CAM_DBG(CAM_ISP, "start device success ctx %u", ctx->ctx_id); - list_del_init(&req->list); - - if (req_isp->num_fence_map_out) { - list_add_tail(&req->list, &ctx->active_req_list); - ctx_isp->active_req_cnt++; - } else { - list_add_tail(&req->list, &ctx->wait_req_list); - } end: return rc; } From 306cc41267d5d5373fc3900df936f1daabd8010a Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 9 Jul 2019 16:44:28 -0700 Subject: [PATCH 040/790] msm: camera: Dynamic update of scalable clock This change updates the scalable clock based on hw src clock. Also, removed cam_soc_util_get_vote_level() as it is duplicating the functionality with cam_soc_util_get_clk_level() api. Change-Id: I001264d150849770ef664ecc206a66f8a4f54412 Signed-off-by: Jigarkumar Zala --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 18 +- drivers/cam_utils/cam_soc_util.c | 155 +++++++++++++----- drivers/cam_utils/cam_soc_util.h | 8 +- 3 files changed, 134 insertions(+), 47 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 9503f204d410..c48d320d0945 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1084,9 +1084,10 @@ end: static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) { int rc = 0; - const struct cam_ife_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; - uint32_t i, val, clk_lvl; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t i, val; + int clk_lvl; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1108,8 +1109,15 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) CAM_DBG(CAM_ISP, "CSID:%d init CSID HW", csid_hw->hw_intf->hw_idx); - clk_lvl = cam_soc_util_get_vote_level(soc_info, csid_hw->clk_rate); - CAM_DBG(CAM_ISP, "CSID clock lvl %u", clk_lvl); + rc = cam_soc_util_get_clk_level(soc_info, csid_hw->clk_rate, + soc_info->src_clk_idx, &clk_lvl); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get clk level for rate %d", + csid_hw->clk_rate); + goto err; + } + + CAM_DBG(CAM_ISP, "CSID clock lvl %d", clk_lvl); rc = cam_ife_csid_enable_soc_resources(soc_info, clk_lvl); if (rc) { diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 4f031ee720b0..e32a6ab21665 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -15,30 +15,41 @@ 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 cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, + int32_t clk_rate, int clk_idx, int32_t *clk_lvl) { int i; long clk_rate_round; - clk_rate_round = clk_round_rate(soc_info->clk[src_clk_idx], clk_rate); + if (!soc_info || (clk_idx < 0) || (clk_idx >= CAM_SOC_MAX_CLK)) { + CAM_ERR(CAM_UTIL, "Invalid src_clk_idx: %d", clk_idx); + *clk_lvl = -1; + return -EINVAL; + } + + clk_rate_round = clk_round_rate(soc_info->clk[clk_idx], clk_rate); if (clk_rate_round < 0) { CAM_ERR(CAM_UTIL, "round failed rc = %ld", clk_rate_round); + *clk_lvl = -1; return -EINVAL; } for (i = 0; i < CAM_MAX_VOTE; i++) { - if (soc_info->clk_rate[i][src_clk_idx] >= clk_rate_round) { + if ((soc_info->clk_level_valid[i]) && + (soc_info->clk_rate[i][clk_idx] >= + clk_rate_round)) { CAM_DBG(CAM_UTIL, "soc = %d round rate = %ld actual = %d", - soc_info->clk_rate[i][src_clk_idx], + soc_info->clk_rate[i][clk_idx], clk_rate_round, clk_rate); - return i; + *clk_lvl = i; + return 0; } } CAM_WARN(CAM_UTIL, "Invalid clock rate %ld", clk_rate_round); + *clk_lvl = -1; return -EINVAL; } @@ -426,13 +437,20 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, int32_t clk_rate) { + int rc = 0; + int i = 0; int32_t src_clk_idx; + int32_t scl_clk_idx; struct clk *clk = NULL; int32_t apply_level; uint32_t clk_level_override = 0; - if (!soc_info || (soc_info->src_clk_idx < 0)) + if (!soc_info || (soc_info->src_clk_idx < 0) || + (soc_info->src_clk_idx >= CAM_SOC_MAX_CLK)) { + CAM_ERR(CAM_UTIL, "Invalid src_clk_idx: %d", + soc_info ? soc_info->src_clk_idx : -1); return -EINVAL; + } src_clk_idx = soc_info->src_clk_idx; clk_level_override = soc_info->clk_level_override; @@ -441,21 +459,57 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, soc_info->clk_rate[clk_level_override][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", + rc = cam_soc_util_get_clk_level(soc_info, clk_rate, src_clk_idx, + &apply_level); + if (rc || (apply_level < 0) || (apply_level >= CAM_MAX_VOTE)) { + CAM_ERR(CAM_UTIL, + "set %s, rate %d dev_name = %s 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 -EINVAL; } - return cam_soc_util_set_clk_rate(clk, - soc_info->clk_name[src_clk_idx], clk_rate); + CAM_DBG(CAM_UTIL, "set %s, rate %d dev_name = %s apply level = %d", + soc_info->clk_name[src_clk_idx], clk_rate, + soc_info->dev_name, apply_level); + + if ((soc_info->cam_cx_ipeak_enable) && (clk_rate >= 0)) { + cam_cx_ipeak_update_vote_cx_ipeak(soc_info, + apply_level); + } + + rc = cam_soc_util_set_clk_rate(clk, + soc_info->clk_name[src_clk_idx], clk_rate); + if (rc) { + CAM_ERR(CAM_UTIL, + "SET_RATE Failed: src clk: %s, rate %d, dev_name = %s rc: %d", + soc_info->clk_name[src_clk_idx], clk_rate, + soc_info->dev_name, rc); + return rc; + } + + /* set clk rate for scalable clk if available */ + + for (i = 0; i < soc_info->scl_clk_count; i++) { + scl_clk_idx = soc_info->scl_clk_idx[i]; + if (scl_clk_idx < 0) { + CAM_DBG(CAM_UTIL, "Scl clk index invalid"); + continue; + } + clk = soc_info->clk[scl_clk_idx]; + rc = cam_soc_util_set_clk_rate(clk, + soc_info->clk_name[scl_clk_idx], + soc_info->clk_rate[apply_level][scl_clk_idx]); + if (rc) { + CAM_WARN(CAM_UTIL, + "SET_RATE Failed: scl clk: %s, rate %d dev_name = %s, rc: %d", + soc_info->clk_name[scl_clk_idx], + soc_info->clk_rate[apply_level][scl_clk_idx], + soc_info->dev_name, rc); + } + } + + return 0; } int cam_soc_util_clk_put(struct clk **clk) @@ -686,6 +740,7 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info) int i, j, rc; int32_t num_clk_level_strings; const char *src_clk_str = NULL; + const char *scl_clk_str = NULL; const char *clk_control_debugfs = NULL; const char *clk_cntl_lvl_string = NULL; enum cam_vote_level level; @@ -813,6 +868,48 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info) } } + /* scalable clk info parsing */ + soc_info->scl_clk_count = 0; + soc_info->scl_clk_count = of_property_count_strings(of_node, + "scl-clk-names"); + if ((soc_info->scl_clk_count <= 0) || + (soc_info->scl_clk_count > CAM_SOC_MAX_CLK)) { + if (soc_info->scl_clk_count == -EINVAL) { + CAM_DBG(CAM_UTIL, "scl_clk_name prop not avialable"); + } else if ((soc_info->scl_clk_count == -ENODATA) || + (soc_info->scl_clk_count > CAM_SOC_MAX_CLK)) { + CAM_ERR(CAM_UTIL, "Invalid scl_clk_count: %d", + soc_info->scl_clk_count); + return -EINVAL; + } + CAM_DBG(CAM_UTIL, "Invalid scl_clk count: %d", + soc_info->scl_clk_count); + soc_info->scl_clk_count = -1; + } else { + CAM_DBG(CAM_UTIL, "No of scalable clocks: %d", + soc_info->scl_clk_count); + for (i = 0; i < soc_info->scl_clk_count; i++) { + rc = of_property_read_string_index(of_node, + "scl-clk-names", i, + (const char **)&scl_clk_str); + if (rc || !scl_clk_str) { + CAM_WARN(CAM_UTIL, "scl_clk_str is NULL"); + soc_info->scl_clk_idx[i] = -1; + continue; + } + for (j = 0; j < soc_info->num_clk; j++) { + if (strnstr(scl_clk_str, soc_info->clk_name[j], + strlen(scl_clk_str))) { + soc_info->scl_clk_idx[i] = j; + CAM_DBG(CAM_UTIL, + "scl clock = %s, index = %d", + scl_clk_str, j); + break; + } + } + } + } + rc = of_property_read_string_index(of_node, "clock-control-debugfs", 0, &clk_control_debugfs); if (rc || !clk_control_debugfs) { @@ -1728,25 +1825,3 @@ int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info, return 0; } - -uint32_t cam_soc_util_get_vote_level(struct cam_hw_soc_info *soc_info, - uint64_t clock_rate) -{ - int i = 0; - - if (!clock_rate) - return CAM_SVS_VOTE; - - for (i = 0; i < CAM_MAX_VOTE; i++) { - if (soc_info->clk_level_valid[i] && - soc_info->clk_rate[i][soc_info->src_clk_idx] >= - clock_rate) { - CAM_DBG(CAM_UTIL, - "Clock rate %lld, selected clock level %d", - clock_rate, i); - return i; - } - } - - return CAM_TURBO_VOTE; -} diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index bfa6183bf739..2ddd4de2d86c 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -152,6 +152,8 @@ struct cam_soc_gpio_data { * @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 + * @scl_clk_count: Number of scalable clocks present + * @scl_clk_idx: Index of scalable clocks * @gpio_data: Pointer to gpio info * @pinctrl_info: Pointer to pinctrl info * @dentry: Debugfs entry @@ -198,6 +200,8 @@ struct cam_hw_soc_info { int32_t prev_clk_level; int32_t src_clk_idx; bool clk_level_valid[CAM_MAX_VOTE]; + int32_t scl_clk_count; + int32_t scl_clk_idx[CAM_SOC_MAX_CLK]; struct cam_soc_gpio_data *gpio_data; struct cam_soc_pinctrl_info pinctrl_info; @@ -632,7 +636,7 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info); int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level); -uint32_t cam_soc_util_get_vote_level(struct cam_hw_soc_info *soc_info, - uint64_t clock_rate); +int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, + int32_t clk_rate, int clk_idx, int32_t *clk_lvl); #endif /* _CAM_SOC_UTIL_H_ */ From 82ee45360e1de6d7dccb81fa8a03a135d9b5a3cc Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Tue, 30 Jul 2019 04:11:17 -0700 Subject: [PATCH 041/790] Revert "msm: camera: icp: lock before updating clock status" This reverts commit 6094f6654bd6ddc7f6df54b19cb8e6697bf3111c. The change introduces a lock around a code that can cause sleep. It results in abnormal operation of camera functionality. Reverting this change will lead to original problem of stability. That need to be addressed. Change-Id: I3899d6992350bc466e89ee1ca1834a8a7fbd0269 Signed-off-by: Alok Pandey --- drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 5 ----- drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index 7deea1c94d84..73075a4ec379 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -306,7 +306,6 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, struct cam_bps_device_core_info *core_info = NULL; struct cam_bps_device_hw_info *hw_info = NULL; int rc = 0; - unsigned long flags; if (!device_priv) { CAM_ERR(CAM_ICP, "Invalid arguments"); @@ -396,16 +395,12 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, } break; case CAM_ICP_BPS_CMD_DISABLE_CLK: - spin_lock_irqsave(&bps_dev->hw_lock, flags); if (core_info->clk_enable == true) cam_bps_toggle_clk(soc_info, false); core_info->clk_enable = false; - spin_unlock_irqrestore(&bps_dev->hw_lock, flags); break; case CAM_ICP_BPS_CMD_RESET: - spin_lock_irqsave(&bps_dev->hw_lock, flags); rc = cam_bps_cmd_reset(soc_info, core_info); - spin_unlock_irqrestore(&bps_dev->hw_lock, flags); break; default: CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type); diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 614c748f0d85..82d0ebe54cc4 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -305,7 +305,6 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, struct cam_ipe_device_core_info *core_info = NULL; struct cam_ipe_device_hw_info *hw_info = NULL; int rc = 0; - unsigned long flags; if (!device_priv) { CAM_ERR(CAM_ICP, "Invalid arguments"); @@ -390,16 +389,12 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, } break; case CAM_ICP_IPE_CMD_DISABLE_CLK: - spin_lock_irqsave(&ipe_dev->hw_lock, flags); if (core_info->clk_enable == true) cam_ipe_toggle_clk(soc_info, false); core_info->clk_enable = false; - spin_unlock_irqrestore(&ipe_dev->hw_lock, flags); break; case CAM_ICP_IPE_CMD_RESET: - spin_lock_irqsave(&ipe_dev->hw_lock, flags); rc = cam_ipe_cmd_reset(soc_info, core_info); - spin_unlock_irqrestore(&ipe_dev->hw_lock, flags); break; default: CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type); From 21c100461f35784510b2700fa0401017c893070f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 6 Aug 2019 11:24:02 -0700 Subject: [PATCH 042/790] Camera: uapi: add uapi csiphy4 and csiphy5 support Add Uapi csiphy4 and csiphy5 support. Change-Id: Ie5d78a389f0cbc454fa261182a3d04030d13d307 Signed-off-by: Jigarkumar Zala --- include/uapi/media/cam_isp_ife.h | 6 ++++-- include/uapi/media/cam_isp_vfe.h | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/uapi/media/cam_isp_ife.h b/include/uapi/media/cam_isp_ife.h index 7ce826d94a78..34c1b3bd2bfe 100644 --- a/include/uapi/media/cam_isp_ife.h +++ b/include/uapi/media/cam_isp_ife.h @@ -46,7 +46,9 @@ #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_RD (CAM_ISP_IFE_IN_RES_BASE + 5) -#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 6) +#define CAM_ISP_IFE_IN_RES_PHY_4 (CAM_ISP_IFE_IN_RES_BASE + 5) +#define CAM_ISP_IFE_IN_RES_PHY_5 (CAM_ISP_IFE_IN_RES_BASE + 6) +#define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 7) +#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 8) #endif /* __UAPI_CAM_ISP_IFE_H__ */ diff --git a/include/uapi/media/cam_isp_vfe.h b/include/uapi/media/cam_isp_vfe.h index 5f9ce7a49108..497093902ba3 100644 --- a/include/uapi/media/cam_isp_vfe.h +++ b/include/uapi/media/cam_isp_vfe.h @@ -43,7 +43,9 @@ #define CAM_ISP_VFE_IN_RES_PHY_1 (CAM_ISP_VFE_IN_RES_BASE + 2) #define CAM_ISP_VFE_IN_RES_PHY_2 (CAM_ISP_VFE_IN_RES_BASE + 3) #define CAM_ISP_VFE_IN_RES_PHY_3 (CAM_ISP_VFE_IN_RES_BASE + 4) -#define CAM_ISP_VFE_IN_RES_FE (CAM_ISP_VFE_IN_RES_BASE + 5) -#define CAM_ISP_VFE_IN_RES_MAX (CAM_ISP_VFE_IN_RES_BASE + 6) +#define CAM_ISP_VFE_IN_RES_PHY_4 (CAM_ISP_VFE_IN_RES_BASE + 5) +#define CAM_ISP_VFE_IN_RES_PHY_5 (CAM_ISP_VFE_IN_RES_BASE + 6) +#define CAM_ISP_VFE_IN_RES_FE (CAM_ISP_VFE_IN_RES_BASE + 7) +#define CAM_ISP_VFE_IN_RES_MAX (CAM_ISP_VFE_IN_RES_BASE + 8) #endif /* __UAPI_CAM_ISP_VFE_H__ */ From 47f89a6efa85ab36e3c52ae05c185d8a6cdb2ab0 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 2 Apr 2019 15:54:37 -0700 Subject: [PATCH 043/790] camera: uapi: Add uapi support for semi real time device types Add uapi support for IPE/BPS semi real time device types. Change-Id: I12c733f51afdd70159f22f23be5967fc852549ca Signed-off-by: Jigarkumar Zala --- include/uapi/media/cam_icp.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h index 969de271e054..ac683bffa4ce 100644 --- a/include/uapi/media/cam_icp.h +++ b/include/uapi/media/cam_icp.h @@ -18,10 +18,13 @@ #define CAM_ICP_DEV_TYPE_MAX 5 /* definitions needed for icp aquire device */ -#define CAM_ICP_RES_TYPE_BPS 1 -#define CAM_ICP_RES_TYPE_IPE_RT 2 -#define CAM_ICP_RES_TYPE_IPE 3 -#define CAM_ICP_RES_TYPE_MAX 4 +#define CAM_ICP_RES_TYPE_BPS 1 +#define CAM_ICP_RES_TYPE_IPE_RT 2 +#define CAM_ICP_RES_TYPE_IPE 3 +#define CAM_ICP_RES_TYPE_IPE_SEMI_RT 4 +#define CAM_ICP_RES_TYPE_BPS_RT 5 +#define CAM_ICP_RES_TYPE_BPS_SEMI_RT 6 +#define CAM_ICP_RES_TYPE_MAX 7 /* packet opcode types */ #define CAM_ICP_OPCODE_IPE_UPDATE 0 From d31033b31fd92f6e7abc549d8c7b33151808a921 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 4 Jul 2019 15:03:06 +0530 Subject: [PATCH 044/790] Camera: uapi: Add uapi support for QCFA CSID binning Add uapi support to configure CSID binning for QCFA. Change-Id: Ic992c11d04319b6e8329963c032501b07002b484 Signed-off-by: Tejas Prajapati Signed-off-by: Trishansh Bhardwaj Signed-off-by: Jigarkumar Zala --- include/uapi/media/cam_isp.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h index 0191d2ced633..ee6440a90023 100644 --- a/include/uapi/media/cam_isp.h +++ b/include/uapi/media/cam_isp.h @@ -99,6 +99,7 @@ #define CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG 7 #define CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG 8 #define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 9 +#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG 12 #define CAM_ISP_VC_DT_CFG 4 @@ -491,6 +492,15 @@ struct cam_isp_csid_clock_config { uint64_t csid_clock; } __attribute__((packed)); +/** + * struct cam_isp_csid_qcfa_config - CSID qcfa binning support configuration + * + * @csid_binning CSID binning + */ +struct cam_isp_csid_qcfa_config { + uint32_t csid_binning; +} __attribute__((packed)); + /** * struct cam_isp_bw_vote - Bandwidth vote information * From ce61a07996fa8083d957c3214b0bdaf5e8325452 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 14:02:31 -0700 Subject: [PATCH 045/790] msm: camera: Update uapi structure for OIS Userspace is sending slave address as 32bit, and in order to parse the correct data kernel space needs to match this bit pattern. This change updates the structure to accommodate it. Change-Id: Ib136bbd1656dba9da75d3b07c494caeebf03dfcb Signed-off-by: Jigarkumar Zala --- include/uapi/media/cam_sensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h index 57a5c4674ca2..5e1918a9a116 100644 --- a/include/uapi/media/cam_sensor.h +++ b/include/uapi/media/cam_sensor.h @@ -132,7 +132,7 @@ struct cam_ois_opcode { * @opcode : opcode */ struct cam_cmd_ois_info { - uint16_t slave_addr; + uint32_t slave_addr; uint8_t i2c_freq_mode; uint8_t cmd_type; uint8_t ois_fw_flag; From 05b312bca9b6bc5fe32b6fcb47122dbec09f6f4c Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 9 Jul 2019 17:09:33 -0700 Subject: [PATCH 046/790] Camera: Add support for LITO target This change add config support for LITO target. Change-Id: Ia4a191c862f9886bb35fbd792ae786d027d5cc7e Signed-off-by: Jigarkumar Zala --- Makefile | 30 +++++++++++++++++++++--------- config/konacameraconf.h | 16 ++++++++-------- config/litocamera.conf | 4 ++++ config/litocameraconf.h | 7 +++++++ 4 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 config/litocamera.conf create mode 100644 config/litocameraconf.h diff --git a/Makefile b/Makefile index f844d98cbdc6..b7c0d7853cc7 100644 --- a/Makefile +++ b/Makefile @@ -5,19 +5,31 @@ ifeq ($(CONFIG_ARCH_KONA), y) include $(srctree)/techpack/camera/config/konacamera.conf endif -# Use USERINCLUDE when you must reference the UAPI directories only. -USERINCLUDE += \ - -I$(srctree)/techpack/camera/include/uapi - -# Use LINUXINCLUDE when you must reference the include/ directory. -# Needed to be compatible with the O= option -LINUXINCLUDE += \ - -I$(srctree)/techpack/camera/include/uapi \ - -I$(srctree)/techpack/camera/include +ifeq ($(CONFIG_ARCH_LITO), y) +include $(srctree)/techpack/camera/config/litocamera.conf +endif ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h endif +ifeq ($(CONFIG_ARCH_LITO), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/litocameraconf.h +endif + +ifdef CONFIG_SPECTRA_CAMERA +# Use USERINCLUDE when you must reference the UAPI directories only. +USERINCLUDE += \ + -I$(srctree)/techpack/camera/include/uapi + +# Use LINUXINCLUDE when you must reference the include/ directory. +# Needed to be compatible with the O= option +LINUXINCLUDE += \ + -I$(srctree)/techpack/camera/include/uapi \ + -I$(srctree)/techpack/camera/include obj-y += drivers/ +else +$(info Target not found) +endif diff --git a/config/konacameraconf.h b/config/konacameraconf.h index e0cf514fe3cf..875b95587ab6 100644 --- a/config/konacameraconf.h +++ b/config/konacameraconf.h @@ -1,8 +1,8 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. - */ - - -#define CONFIG_SPECTRA_CAMERA 1 - +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#define CONFIG_SPECTRA_CAMERA 1 + diff --git a/config/litocamera.conf b/config/litocamera.conf new file mode 100644 index 000000000000..451723eebce3 --- /dev/null +++ b/config/litocamera.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2019, The Linux Foundation. All rights reserved. + +export CONFIG_SPECTRA_CAMERA=y diff --git a/config/litocameraconf.h b/config/litocameraconf.h new file mode 100644 index 000000000000..1a7714018004 --- /dev/null +++ b/config/litocameraconf.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 + From b2bd543adf23a2a9dbae9e0b91afb3209b527820 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Wed, 31 Jul 2019 15:29:13 -0700 Subject: [PATCH 047/790] msm: camera: isp: Dump page fault info for pending request If bubble report is set from usersapce we move the active request back to pending request list while handling error. We need to iterate through pending request list as well when dumping page fault info for erroneous request. Change-Id: I2458313affbae6cb161f077eef7bdd0263c43ae2 Signed-off-by: Vishalsingh Hajeri Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/cam_isp_context.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9c0d4d6c2817..d88adebea4f7 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3876,6 +3876,36 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, req->request_id, rc); } + /* + * In certain scenarios we observe both overflow and SMMU pagefault + * for a particular request. If overflow is handled before page fault + * we need to traverse through pending request list because if + * bubble recovery is enabled on any request we move that request + * and all the subsequent requests to the pending list while handling + * overflow error. + */ + + CAM_INFO(CAM_ISP, + "Iterating over pending req list of isp ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->pending_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + hw_update_data = &req_isp->hw_update_data; + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &mem_found); + if (rc) + CAM_ERR(CAM_ISP, "Failed to dump pf info"); + + if (mem_found) + CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", + req->request_id, rc); + } + return rc; } From 632d56473bfa029f5c53b71fb402979333a4b884 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 22 Jul 2019 12:33:17 -0700 Subject: [PATCH 048/790] msm: camera: Add uapi definitions for camera reg dump For debugging, there are a set of register values that user space needs. Based on the offset and range given, values can be dumped into an out buffer to be further processed. Add uapi support for this reg dump. Change-Id: I6e6f89625a505158a6bf8932ebb9d0ae78bf0129 Signed-off-by: Mukund Madhusudan Atre --- include/uapi/media/cam_defs.h | 114 ++++++++++++++++++++++++++++++++++ include/uapi/media/cam_isp.h | 29 +++++---- 2 files changed, 130 insertions(+), 13 deletions(-) diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h index 8bc561314027..ce73b79f9590 100644 --- a/include/uapi/media/cam_defs.h +++ b/include/uapi/media/cam_defs.h @@ -219,6 +219,18 @@ struct cam_iommu_handle { #define CAM_PACKET_DEV_LRME 17 #define CAM_PACKET_DEV_MAX 18 +/* Register base type */ +#define CAM_REG_DUMP_BASE_TYPE_ISP_LEFT 1 +#define CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT 2 +#define CAM_REG_DUMP_BASE_TYPE_CAMNOC 3 + +/* Register dump read type */ +#define CAM_REG_DUMP_READ_TYPE_CONT_RANGE 1 +#define CAM_REG_DUMP_READ_TYPE_DMI 2 + +/* Max number of config writes to read from DMI */ +#define CAM_REG_DUMP_DMI_CONFIG_MAX 5 + /* constants */ #define CAM_PACKET_MAX_PLANES 3 @@ -742,5 +754,107 @@ struct cam_cmd_mem_regions { struct cam_cmd_mem_region_info map_info_array[1]; }; +/** + * struct cam_reg_write_desc - Register write descriptor + * + * @offset : Register offset at which 'value' needs to written + * @value : Register value to write + */ +struct cam_reg_write_desc { + uint32_t offset; + uint32_t value; +}; + +/** + * struct cam_reg_range_read_desc - Descriptor to provide read info + * + * @offset : Register offset address to start with + * @num_values : Number of values to read + */ +struct cam_reg_range_read_desc { + uint32_t offset; + uint32_t num_values; +}; + +/** + * struct cam_dmi_read_desc - Descriptor to provide DMI read info + * + * @num_pre_writes : Number of registers to write before reading DMI data + * @num_post_writes : Number of registers to write after reading DMI data + * @pre_read_config : Registers to write before reading DMI data + * @dmi_data_read : DMI Register, number of values to read to dump + * DMI data + * @post_read_config : Registers to write after reading DMI data + */ +struct cam_dmi_read_desc { + uint32_t num_pre_writes; + uint32_t num_post_writes; + struct cam_reg_write_desc pre_read_config[ + CAM_REG_DUMP_DMI_CONFIG_MAX]; + struct cam_reg_range_read_desc dmi_data_read; + struct cam_reg_write_desc post_read_config[ + CAM_REG_DUMP_DMI_CONFIG_MAX]; +}; + +/** + * struct cam_reg_read_info - Register read info for both reg continuous read + * or DMI read + * + * @type : Whether Register range read or DMI read + * @reg_read : Range of registers to read + * @dmi_read : DMI data to read + */ +struct cam_reg_read_info { + uint32_t type; + uint32_t reserved; + union { + struct cam_reg_range_read_desc reg_read; + struct cam_dmi_read_desc dmi_read; + }; +}; + +/** + * struct cam_reg_dump_out_buffer -Buffer info for dump data to be provided + * + * @req_id : Request ID corresponding to reg dump data + * @bytes_written : Number of bytes written + * @dump_data : Register dump data + */ +struct cam_reg_dump_out_buffer { + uint64_t req_id; + uint32_t bytes_written; + uint32_t dump_data[1]; +}; + +/** + * struct cam_reg_dump_desc - Descriptor to provide dump info + * + * @reg_base_type : Register base type, e.g. ISP_LEFT, ISP_RIGHT, CAMNOC + * @dump_buffer_offset : Offset from base of mem_handle at which Register dump + * will be written for this set + * @dump_buffer_size : Available size in bytes for writing dump values + * @num_read_range : Number register range reads (Continuous + DMI) + * @read_range : Read range info + */ +struct cam_reg_dump_desc { + uint32_t reg_base_type; + uint32_t dump_buffer_offset; + uint32_t dump_buffer_size; + uint32_t num_read_range; + struct cam_reg_read_info read_range[1]; +}; + +/** + * struct cam_reg_dump_input_info - Info about required dump sets + * + * @num_dump_sets : Number of different dump sets (base types) given + * @dump_set_offsets : Points to the given dump description structures + * (cam_reg_dump_desc) + */ +struct cam_reg_dump_input_info { + uint32_t num_dump_sets; + uint32_t dump_set_offsets[1]; +}; + #endif /* __UAPI_CAM_DEFS_H__ */ diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h index ee6440a90023..03767466094f 100644 --- a/include/uapi/media/cam_isp.h +++ b/include/uapi/media/cam_isp.h @@ -69,19 +69,22 @@ #define CAM_ISP_PACKET_OP_MAX 3 /* ISP packet meta_data type for command buffer */ -#define CAM_ISP_PACKET_META_BASE 0 -#define CAM_ISP_PACKET_META_LEFT 1 -#define CAM_ISP_PACKET_META_RIGHT 2 -#define CAM_ISP_PACKET_META_COMMON 3 -#define CAM_ISP_PACKET_META_DMI_LEFT 4 -#define CAM_ISP_PACKET_META_DMI_RIGHT 5 -#define CAM_ISP_PACKET_META_DMI_COMMON 6 -#define CAM_ISP_PACKET_META_CLOCK 7 -#define CAM_ISP_PACKET_META_CSID 8 -#define CAM_ISP_PACKET_META_DUAL_CONFIG 9 -#define CAM_ISP_PACKET_META_GENERIC_BLOB_LEFT 10 -#define CAM_ISP_PACKET_META_GENERIC_BLOB_RIGHT 11 -#define CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON 12 +#define CAM_ISP_PACKET_META_BASE 0 +#define CAM_ISP_PACKET_META_LEFT 1 +#define CAM_ISP_PACKET_META_RIGHT 2 +#define CAM_ISP_PACKET_META_COMMON 3 +#define CAM_ISP_PACKET_META_DMI_LEFT 4 +#define CAM_ISP_PACKET_META_DMI_RIGHT 5 +#define CAM_ISP_PACKET_META_DMI_COMMON 6 +#define CAM_ISP_PACKET_META_CLOCK 7 +#define CAM_ISP_PACKET_META_CSID 8 +#define CAM_ISP_PACKET_META_DUAL_CONFIG 9 +#define CAM_ISP_PACKET_META_GENERIC_BLOB_LEFT 10 +#define CAM_ISP_PACKET_META_GENERIC_BLOB_RIGHT 11 +#define CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON 12 +#define CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST 13 +#define CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH 14 +#define CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR 15 /* DSP mode */ #define CAM_ISP_DSP_MODE_NONE 0 From 827791eafa3c8db89f76490dd6eb31acfcdefd90 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Thu, 8 Aug 2019 15:46:47 -0700 Subject: [PATCH 049/790] msm: camera: Add support for reg dump to command buffers Certain register values are required by user space during flush to apply settings accordingly. Also, support for dumping registers at the time of error is needed for debugging. Add support for dumping register values in a range of offsets to given cmd buffer. Change-Id: I5912118809f7a7dd701a555639d1057ffe665ce1 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_core/cam_hw_mgr_intf.h | 10 + drivers/cam_isp/cam_isp_context.c | 28 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 159 +++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 11 + .../hw_utils/cam_isp_packet_parser.c | 20 ++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 6 + drivers/cam_utils/cam_soc_util.c | 275 ++++++++++++++++++ drivers/cam_utils/cam_soc_util.h | 24 ++ 9 files changed, 531 insertions(+), 3 deletions(-) diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 56138c33091d..b7b6ae1bb6b7 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -21,6 +21,9 @@ /* maximum buf done irqs */ #define CAM_NUM_OUT_PER_COMP_IRQ_MAX 12 +/* Maximum reg dump cmd buffer entries in a context */ +#define CAM_REG_DUMP_MAX_BUF_ENTRIES 10 + /* hardware event callback function type */ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, void *evt_data); @@ -166,6 +169,8 @@ struct cam_hw_mgr_dump_pf_data { * @max_in_map_entries: Maximum input fence mapping supported * @in_map_entries: Actual input fence mapping list (returned) * @num_in_map_entries: Number of acutal input fence mapping (returned) + * @reg_dump_buf_desc: cmd buffer descriptors for reg dump + * @num_reg_dump_buf: Count of descriptors in reg_dump_buf_desc * @priv: Private pointer of hw update * @pf_data: Debug data for page fault * @@ -183,6 +188,9 @@ struct cam_hw_prepare_update_args { uint32_t max_in_map_entries; struct cam_hw_fence_map_entry *in_map_entries; uint32_t num_in_map_entries; + struct cam_cmd_buf_desc reg_dump_buf_desc[ + CAM_REG_DUMP_MAX_BUF_ENTRIES]; + uint32_t num_reg_dump_buf; void *priv; struct cam_hw_mgr_dump_pf_data *pf_data; }; @@ -266,6 +274,8 @@ struct cam_hw_dump_pf_args { enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, CAM_HW_MGR_CMD_DUMP_PF_INFO, + CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH, + CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR, }; /** diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d88adebea4f7..638478cb56e1 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1116,6 +1116,22 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW)) notify.error = CRM_KMD_ERR_OVERFLOW; + + if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) || + (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW) || + (error_type == CAM_ISP_HW_ERROR_VIOLATION)) { + struct cam_hw_cmd_args hw_cmd_args; + + memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); + hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR; + rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_cmd_args); + if (rc) { + CAM_ERR(CAM_ISP, "Reg dump on error failed rc: %d", rc); + rc = 0; + } + } /* * The error is likely caused by first request on the active list. * If active list is empty check wait list (maybe error hit as soon @@ -1932,6 +1948,8 @@ static int __cam_isp_ctx_flush_req_in_top_state( { int rc = 0; struct cam_isp_context *ctx_isp; + struct cam_hw_cmd_args hw_cmd_args; + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { @@ -1945,6 +1963,16 @@ 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); + memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); + hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH; + rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_cmd_args); + if (rc) { + CAM_ERR(CAM_ISP, "Reg dump on flush failed rc: %d", rc); + rc = 0; + } + atomic_set(&ctx_isp->process_bubble, 0); return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index faf2fb02e924..96a12a707dd3 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2077,7 +2077,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, ctx = userdata; if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { - complete(&ctx->config_done_complete); + complete_all(&ctx->config_done_complete); CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", handle, userdata, status, cookie, ctx->ctx_index); @@ -3059,8 +3059,8 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, cdm_cmd->cmd[i].len = cmd->len; } - if (cfg->init_packet) - init_completion(&ctx->config_done_complete); + reinit_completion(&ctx->config_done_complete); + ctx->applied_req_id = cfg->request_id; CAM_DBG(CAM_ISP, "Submit to CDM"); rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); @@ -5058,6 +5058,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, prepare->num_hw_update_entries = 0; prepare->num_in_map_entries = 0; prepare->num_out_map_entries = 0; + prepare->num_reg_dump_buf = 0; memset(&prepare_hw_data->bw_config[0], 0x0, sizeof(prepare_hw_data->bw_config[0]) * @@ -5123,6 +5124,15 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, if (((prepare->packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_INIT_DEV) { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV; + ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; + if ((ctx->num_reg_dump_buf) && (ctx->num_reg_dump_buf < + CAM_REG_DUMP_MAX_BUF_ENTRIES)) { + memcpy(ctx->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare->num_reg_dump_buf); + } + goto end; } else prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV; @@ -5279,6 +5289,118 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, } } +static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, + void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr, + uint32_t *reg_base_idx) +{ + int rc = 0; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ife_hw_mgr_ctx *ctx = + (struct cam_ife_hw_mgr_ctx *) hw_mgr_ctx; + + *soc_info_ptr = NULL; + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF) + continue; + + switch (reg_base_type) { + case CAM_REG_DUMP_BASE_TYPE_CAMNOC: + case CAM_REG_DUMP_BASE_TYPE_ISP_LEFT: + if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]) + continue; + + rc = hw_mgr_res->hw_res[ + CAM_ISP_HW_SPLIT_LEFT]->process_cmd( + hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT], + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info, + sizeof(void *)); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in regspace data query split idx: %d rc : %d", + CAM_ISP_HW_SPLIT_LEFT, rc); + return rc; + } + + if (reg_base_type == CAM_REG_DUMP_BASE_TYPE_ISP_LEFT) + *reg_base_idx = 0; + else + *reg_base_idx = 1; + + *soc_info_ptr = soc_info; + break; + case CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT: + if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]) + continue; + + rc = hw_mgr_res->hw_res[ + CAM_ISP_HW_SPLIT_RIGHT]->process_cmd( + hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT], + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info, + sizeof(void *)); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in regspace data query split idx: %d rc : %d", + CAM_ISP_HW_SPLIT_RIGHT, rc); + return rc; + } + + *reg_base_idx = 0; + *soc_info_ptr = soc_info; + break; + default: + CAM_ERR(CAM_ISP, + "Unrecognized reg base type: %d", + reg_base_type); + return -EINVAL; + } + } + + return rc; +} + +static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, + uint32_t meta_type) +{ + int rc, i; + + if (!ctx->num_reg_dump_buf) { + CAM_DBG(CAM_ISP, + "Zero command buffers for reg dump req_id: [%llu] ctx idx: [%llu] meta_type: %d", + ctx->applied_req_id, ctx->ctx_index, meta_type); + return 0; + } + + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(30)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, + "config done completion timeout rc=%d ctx_index %d", + rc, ctx->ctx_index); + rc = 0; + } + + for (i = 0; i < ctx->num_reg_dump_buf; i++) { + CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %d req_type: %d", + ctx->reg_dump_buf_desc[i].meta_data, meta_type); + if (ctx->reg_dump_buf_desc[i].meta_data == meta_type) { + rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, + &ctx->reg_dump_buf_desc[i], + ctx->applied_req_id, + cam_ife_mgr_regspace_data_cb); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %d", + i, rc, ctx->applied_req_id, meta_type); + return -EINVAL; + } + } + } + + return 0; +} + static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -5342,6 +5464,37 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) hw_cmd_args->u.pf_args.buf_info, hw_cmd_args->u.pf_args.mem_found); break; + case CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH: + if (ctx->last_dump_flush_req_id == ctx->applied_req_id) + return 0; + + ctx->last_dump_flush_req_id = ctx->applied_req_id; + + rc = cam_ife_mgr_handle_reg_dump(ctx, + CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump on flush failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + return rc; + } + + break; + case CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR: + if (ctx->last_dump_err_req_id == ctx->applied_req_id) + return 0; + + ctx->last_dump_err_req_id = ctx->applied_req_id; + rc = cam_ife_mgr_handle_reg_dump(ctx, + CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump on error failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + return rc; + } + + break; default: CAM_ERR(CAM_ISP, "Invalid cmd"); } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 16143b014ebf..698b0c60ca9b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -124,6 +124,11 @@ struct cam_ife_hw_mgr_debug { * context * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete + * @reg_dump_buf_desc: cmd buffer descriptors for reg dump + * @num_reg_dump_buf: Count of descriptors in reg_dump_buf_desc + * @applied_req_id: Last request id to be applied + * @last_dump_flush_req_id Last req id for which reg dump on flush was called + * @last_dump_err_req_id Last req id for which reg dump on error was called * @init_done indicate whether init hw is done * @is_fe_enable indicate whether fetch engine\read path is enabled * @is_dual indicate whether context is in dual VFE mode @@ -161,6 +166,12 @@ struct cam_ife_hw_mgr_ctx { atomic_t overflow_pending; uint32_t is_rdi_only_context; struct completion config_done_complete; + struct cam_cmd_buf_desc reg_dump_buf_desc[ + CAM_REG_DUMP_MAX_BUF_ENTRIES]; + uint32_t num_reg_dump_buf; + uint64_t applied_req_id; + uint64_t last_dump_flush_req_id; + uint64_t last_dump_err_req_id; bool init_done; bool is_fe_enable; bool is_dual; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index be098a619aaf..48928bccc472 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -420,6 +420,26 @@ int cam_isp_add_command_buffers( num_ent = prepare->num_hw_update_entries; } break; + case CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH: + case CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR: + if (split_id == CAM_ISP_HW_SPLIT_LEFT) { + if (prepare->num_reg_dump_buf >= + CAM_REG_DUMP_MAX_BUF_ENTRIES) { + CAM_ERR(CAM_ISP, + "Descriptor count out of bounds: %d", + prepare->num_reg_dump_buf); + return -EINVAL; + } + prepare->reg_dump_buf_desc[ + prepare->num_reg_dump_buf] = + cmd_desc[i]; + prepare->num_reg_dump_buf++; + CAM_DBG(CAM_ISP, + "Added command buffer: %d desc_count: %d", + cmd_desc[i].meta_data, + prepare->num_reg_dump_buf); + } + break; default: CAM_ERR(CAM_ISP, "invalid cdm command meta data %d", cmd_meta_data); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 1e556137996d..741b41d4cccf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -101,6 +101,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CORE_CONFIG, CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED, + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index bbc25bc96045..7e9aa91689c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -735,6 +735,12 @@ static int cam_vfe_camif_ver3_process_cmd( rsrc_node->res_priv; camif_priv->camif_debug = *((uint32_t *)cmd_args); break; + case CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA: + camif_priv = (struct cam_vfe_mux_camif_ver3_data *) + rsrc_node->res_priv; + *((struct cam_hw_soc_info **)cmd_args) = camif_priv->soc_info; + rc = 0; + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index e32a6ab21665..99e349a66c61 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -11,6 +11,7 @@ #include "cam_soc_util.h" #include "cam_debug_util.h" #include "cam_cx_ipeak.h" +#include "cam_mem_mgr.h" static char supported_clk_info[256]; static char debugfs_dir_name[64]; @@ -1825,3 +1826,277 @@ int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info, return 0; } + +static int cam_soc_util_dump_cont_reg_range( + struct cam_hw_soc_info *soc_info, + struct cam_reg_range_read_desc *reg_read, uint32_t base_idx, + struct cam_reg_dump_out_buffer *dump_out_buf, size_t max_out_size) +{ + int i = 0; + uint32_t write_idx = 0; + + if (!soc_info || !dump_out_buf) { + CAM_ERR(CAM_UTIL, + "Invalid input args soc_info: %pK, dump_out_buffer: %pK", + soc_info, dump_out_buf); + return -EINVAL; + } + + if (reg_read->num_values >= ((max_out_size - + (size_t)dump_out_buf->bytes_written) / sizeof(uint32_t))) { + CAM_ERR(CAM_UTIL, + "Invalid num values to read: %d max values: %d bytes written: %d", + reg_read->num_values, (max_out_size / + sizeof(uint32_t)), dump_out_buf->bytes_written); + return -EINVAL; + } + + write_idx = dump_out_buf->bytes_written / sizeof(uint32_t); + for (i = 0; i < reg_read->num_values; i++) { + dump_out_buf->dump_data[write_idx++] = reg_read->offset + + (i * 4); + dump_out_buf->dump_data[write_idx++] = + cam_soc_util_r(soc_info, base_idx, + (reg_read->offset + (i * 4))); + dump_out_buf->bytes_written += (2 * sizeof(uint32_t)); + } + + return 0; +} + +static int cam_soc_util_dump_dmi_reg_range( + struct cam_hw_soc_info *soc_info, + struct cam_dmi_read_desc *dmi_read, uint32_t base_idx, + struct cam_reg_dump_out_buffer *dump_out_buf, size_t max_out_size) +{ + int i = 0; + uint32_t write_idx = 0; + + if (!soc_info || !dump_out_buf) { + CAM_ERR(CAM_UTIL, + "Invalid input args soc_info: %pK, dump_out_buffer: %pK", + soc_info, dump_out_buf); + return -EINVAL; + } + + if (dmi_read->num_pre_writes > CAM_REG_DUMP_DMI_CONFIG_MAX || + dmi_read->num_post_writes > CAM_REG_DUMP_DMI_CONFIG_MAX) { + CAM_ERR(CAM_UTIL, + "Invalid number of requested writes, pre: %d post: %d", + dmi_read->num_pre_writes, dmi_read->num_post_writes); + return -EINVAL; + } + + if (dmi_read->dmi_data_read.num_values >= ((max_out_size - + (size_t)dump_out_buf->bytes_written) / sizeof(uint32_t))) { + CAM_ERR(CAM_UTIL, + "Invalid num values to read: %d max values: %d bytes written: %d", + dmi_read->dmi_data_read.num_values, (max_out_size / + sizeof(uint32_t)), dump_out_buf->bytes_written); + return -EINVAL; + } + + write_idx = dump_out_buf->bytes_written / sizeof(uint32_t); + for (i = 0; i < dmi_read->num_pre_writes; i++) { + cam_soc_util_w_mb(soc_info, base_idx, + dmi_read->pre_read_config[i].offset, + dmi_read->pre_read_config[i].value); + dump_out_buf->dump_data[write_idx++] = + dmi_read->pre_read_config[i].offset; + dump_out_buf->dump_data[write_idx++] = + dmi_read->pre_read_config[i].value; + dump_out_buf->bytes_written += (2 * sizeof(uint32_t)); + } + + for (i = 0; i < dmi_read->dmi_data_read.num_values; i++) { + dump_out_buf->dump_data[write_idx++] = + dmi_read->dmi_data_read.offset; + dump_out_buf->dump_data[write_idx++] = + cam_soc_util_r_mb(soc_info, base_idx, + dmi_read->dmi_data_read.offset); + dump_out_buf->bytes_written += (2 * sizeof(uint32_t)); + } + + for (i = 0; i < dmi_read->num_post_writes; i++) { + cam_soc_util_w_mb(soc_info, base_idx, + dmi_read->post_read_config[i].offset, + dmi_read->post_read_config[i].value); + } + + return 0; +} + +int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, + struct cam_cmd_buf_desc *cmd_desc, uint64_t req_id, + cam_soc_util_regspace_data_cb reg_data_cb) +{ + int rc = 0, i, j; + uintptr_t cpu_addr = 0; + uintptr_t cmd_buf_start = 0; + uintptr_t cmd_in_data_end = 0; + uintptr_t cmd_buf_end = 0; + uint32_t reg_base_type = 0; + size_t buf_size = 0, remain_len = 0; + size_t max_out_size = 0; + struct cam_reg_dump_input_info *reg_input_info = NULL; + struct cam_reg_dump_desc *reg_dump_desc = NULL; + struct cam_reg_dump_out_buffer *dump_out_buf = NULL; + struct cam_reg_read_info *reg_read_info = NULL; + struct cam_hw_soc_info *soc_info; + uint32_t reg_base_idx = 0; + + if (!ctx || !cmd_desc || !reg_data_cb) { + CAM_ERR(CAM_UTIL, "Invalid args to reg dump [%pK] [%pK]", + cmd_desc, reg_data_cb); + return -EINVAL; + } + + if (!cmd_desc->length || !cmd_desc->size) { + CAM_ERR(CAM_UTIL, "Invalid cmd buf size %d %d", + cmd_desc->length, cmd_desc->size); + return -EINVAL; + } + + rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, &cpu_addr, &buf_size); + if (rc || !cpu_addr || (buf_size == 0)) { + CAM_ERR(CAM_UTIL, "Failed in Get cpu addr, rc=%d, cpu_addr=%pK", + rc, (void *)cpu_addr); + return rc; + } + + CAM_DBG(CAM_UTIL, "Get cpu buf success req_id: %llu buf_size: %zu", + req_id, buf_size); + if ((buf_size < sizeof(uint32_t)) || + ((size_t)cmd_desc->offset > (buf_size - sizeof(uint32_t)))) { + CAM_ERR(CAM_UTIL, "Invalid offset for cmd buf: %zu", + (size_t)cmd_desc->offset); + return -EINVAL; + } + + remain_len = buf_size - (size_t)cmd_desc->offset; + if (remain_len < (size_t)cmd_desc->length) { + CAM_ERR(CAM_UTIL, "Invalid length for cmd buf: %zu", + (size_t)cmd_desc->length); + return -EINVAL; + } + + cmd_buf_start = (uintptr_t)(((uint8_t *)cpu_addr) + cmd_desc->offset); + cmd_in_data_end = (uintptr_t)(((uint8_t *)cmd_buf_start) + + cmd_desc->length); + cmd_buf_end = (uintptr_t)(((uint8_t *)cmd_buf_start) + + cmd_desc->size); + if (cmd_buf_end < cmd_in_data_end) { + CAM_ERR(CAM_UTIL, + "Invalid length and size for cmd buf: [%zu] [%zu]", + (size_t)cmd_desc->length, (size_t)cmd_desc->size); + return -EINVAL; + } + + CAM_DBG(CAM_UTIL, + "Buffer params start [%pK] input_end [%pK] buf_end [%pK]", + cmd_buf_start, cmd_in_data_end, cmd_buf_end); + reg_input_info = (struct cam_reg_dump_input_info *) cmd_buf_start; + if (!reg_input_info->num_dump_sets) { + CAM_ERR(CAM_UTIL, "Zero dump sets found in input info"); + return -EINVAL; + } + + CAM_DBG(CAM_UTIL, + "reg_input_info req_id: %llu ctx %pK num_dump_sets: %d", + req_id, ctx, reg_input_info->num_dump_sets); + for (i = 0; i < reg_input_info->num_dump_sets; i++) { + if ((remain_len - sizeof(uint32_t)) <= + (size_t)reg_input_info->dump_set_offsets[i]) { + CAM_ERR(CAM_UTIL, + "Invalid dump set offset: [%zu], remain len: [%zu]", + (size_t)reg_input_info->dump_set_offsets[i], + remain_len); + return -EINVAL; + } + + reg_dump_desc = (struct cam_reg_dump_desc *) + ((uint8_t *)cmd_buf_start + + reg_input_info->dump_set_offsets[i]); + if (!reg_dump_desc->num_read_range) { + CAM_ERR(CAM_UTIL, "Zero ranges found in input info"); + return -EINVAL; + } + + if ((remain_len - sizeof(uint32_t)) + <= (size_t)reg_dump_desc->dump_buffer_offset) { + CAM_ERR(CAM_UTIL, + "Invalid out buffer offset: [%zu], remain len: [%zu]", + (size_t)reg_dump_desc->dump_buffer_offset, + remain_len); + return -EINVAL; + } + + dump_out_buf = (struct cam_reg_dump_out_buffer *) + ((uint8_t *)cmd_buf_start + + reg_dump_desc->dump_buffer_offset); + dump_out_buf->req_id = req_id; + dump_out_buf->bytes_written = 0; + max_out_size = (size_t)(cmd_desc->size - + reg_dump_desc->dump_buffer_offset); + + reg_base_type = reg_dump_desc->reg_base_type; + if (reg_base_type == 0 || reg_base_type > + CAM_REG_DUMP_BASE_TYPE_CAMNOC) { + CAM_ERR(CAM_UTIL, + "Invalid Reg dump base type: %d", + reg_base_type); + return -EINVAL; + } + + rc = reg_data_cb(reg_base_type, ctx, &soc_info, ®_base_idx); + if (rc || !soc_info) { + CAM_ERR(CAM_UTIL, + "Reg space data callback failed rc: %d soc_info: [%pK]", + rc, soc_info); + return -EINVAL; + } + + if (reg_base_idx > soc_info->num_reg_map) { + CAM_ERR(CAM_UTIL, + "Invalid reg base idx: %d num reg map: %d", + reg_base_idx, soc_info->num_reg_map); + return -EINVAL; + } + + CAM_DBG(CAM_UTIL, + "Reg data callback success req_id: %llu base_type: %d base_idx: %d num_read_range: %d", + req_id, reg_base_type, reg_base_idx, + reg_dump_desc->num_read_range); + for (j = 0; j < reg_dump_desc->num_read_range; j++) { + CAM_DBG(CAM_UTIL, + "Number of bytes written to cmd buffer: %u req_id: %llu", + dump_out_buf->bytes_written, req_id); + reg_read_info = ®_dump_desc->read_range[j]; + if (reg_read_info->type == + CAM_REG_DUMP_READ_TYPE_CONT_RANGE) { + rc = cam_soc_util_dump_cont_reg_range(soc_info, + ®_read_info->reg_read, reg_base_idx, + dump_out_buf, max_out_size); + } else if (reg_read_info->type == + CAM_REG_DUMP_READ_TYPE_DMI) { + rc = cam_soc_util_dump_dmi_reg_range(soc_info, + ®_read_info->dmi_read, reg_base_idx, + dump_out_buf, max_out_size); + } else { + CAM_ERR(CAM_UTIL, + "Invalid Reg dump read type: %d", + reg_read_info->type); + return -EINVAL; + } + + if (rc) { + CAM_ERR(CAM_UTIL, + "Reg range read failed rc: %d reg_base_idx: %d dump_out_buf: %pK", + rc, reg_base_idx, dump_out_buf); + return rc; + } + } + } + + return 0; +} diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 2ddd4de2d86c..ad2382b835ef 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -18,6 +18,7 @@ #include #include "cam_io_util.h" +#include #define NO_SET_RATE -1 #define INIT_RATE -2 @@ -639,4 +640,27 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, int32_t clk_rate, int clk_idx, int32_t *clk_lvl); +/* Callback to get reg space data for specific HW */ +typedef int (*cam_soc_util_regspace_data_cb)(uint32_t reg_base_type, + void *ctx, struct cam_hw_soc_info **soc_info_ptr, + uint32_t *reg_base_idx); + +/** + * cam_soc_util_reg_dump_to_cmd_buf() + * + * @brief: Camera SOC util for dumping sets of register ranges to + * to command buffer + * + * @ctx: Context info from specific hardware manager + * @cmd_desc: Command buffer descriptor + * @req_id: Last applied req id for which reg dump is required + * @reg_data_cb: Callback function to get reg space info based on type + * in command buffer + * + * @return: Success or Failure + */ +int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, + struct cam_cmd_buf_desc *cmd_desc, uint64_t req_id, + cam_soc_util_regspace_data_cb reg_data_cb); + #endif /* _CAM_SOC_UTIL_H_ */ From 519d453d0d4daaeadbd27f683e5391b6575adf3f Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 12 Jul 2019 11:07:34 -0700 Subject: [PATCH 050/790] msm: camera: icp: Update A5 clock per frame A5 (ICP) clock corners IPE clock source. This change updates ICP clock based on the rate updated for IPE. Change-Id: I2c0b711d34ea8ab8ccf458ecb77402ecf6bf967e Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 19 ++++++++ drivers/cam_icp/icp_hw/a5_hw/a5_soc.c | 44 +++++++++++++++++++ drivers/cam_icp/icp_hw/a5_hw/a5_soc.h | 2 + .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 16 ++++++- .../icp_hw_mgr/include/cam_a5_hw_intf.h | 3 +- .../icp_hw_mgr/include/cam_icp_hw_intf.h | 5 +++ drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 10 ++++- 7 files changed, 95 insertions(+), 4 deletions(-) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index f7d94b2ce679..d6e2970b09ee 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -519,6 +519,25 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, break; } + case CAM_ICP_A5_CMD_CLK_UPDATE: { + int32_t clk_level = 0; + + if (!cmd_args) { + CAM_ERR(CAM_ICP, "Invalid args"); + return -EINVAL; + } + + clk_level = *((int32_t *)cmd_args); + CAM_DBG(CAM_ICP, + "Update ICP clock to level [%d]", clk_level); + rc = cam_a5_update_clk_rate(soc_info, clk_level); + if (rc) + CAM_ERR(CAM_ICP, + "Failed to update clk to level: %d rc: %d", + clk_level, rc); + + break; + } default: break; } diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c index 62a88ac87f67..d0629612193a 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c @@ -196,3 +196,47 @@ int cam_a5_disable_soc_resources(struct cam_hw_soc_info *soc_info) return rc; } + +int cam_a5_update_clk_rate(struct cam_hw_soc_info *soc_info, + int32_t clk_level) +{ + int32_t src_clk_idx = 0; + int32_t clk_rate = 0; + + if (!soc_info) { + CAM_ERR(CAM_ICP, "Invalid args"); + return -EINVAL; + } + + if ((clk_level < 0) || (clk_level >= CAM_MAX_VOTE)) { + CAM_ERR(CAM_ICP, "clock level %d is not valid", + clk_level); + return -EINVAL; + } + + if (!soc_info->clk_level_valid[clk_level]) { + CAM_ERR(CAM_ICP, + "Clock level %d not supported", + clk_level); + return -EINVAL; + } + + src_clk_idx = soc_info->src_clk_idx; + if ((src_clk_idx < 0) || (src_clk_idx >= CAM_SOC_MAX_CLK)) { + CAM_WARN(CAM_ICP, "src_clk not defined for %s", + soc_info->dev_name); + return -EINVAL; + } + + clk_rate = soc_info->clk_rate[clk_level][src_clk_idx]; + if ((soc_info->clk_level_valid[CAM_TURBO_VOTE]) && + (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && + (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { + CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d", + clk_rate, + soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); + clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; + } + + return cam_soc_util_set_src_clk_rate(soc_info, clk_rate); +} diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h index c44bcde120fb..480364df1fd6 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h @@ -34,4 +34,6 @@ int cam_a5_enable_soc_resources(struct cam_hw_soc_info *soc_info); int cam_a5_disable_soc_resources(struct cam_hw_soc_info *soc_info); +int cam_a5_update_clk_rate(struct cam_hw_soc_info *soc_info, + int32_t clk_level); #endif diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 57a88f5a3070..fc7942bc42bf 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1320,12 +1320,14 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, struct cam_hw_intf *ipe0_dev_intf = NULL; struct cam_hw_intf *ipe1_dev_intf = NULL; struct cam_hw_intf *bps_dev_intf = NULL; + struct cam_hw_intf *a5_dev_intf = NULL; struct cam_hw_intf *dev_intf = NULL; struct cam_a5_clk_update_cmd clk_upd_cmd; ipe0_dev_intf = hw_mgr->ipe0_dev_intf; ipe1_dev_intf = hw_mgr->ipe1_dev_intf; bps_dev_intf = hw_mgr->bps_dev_intf; + a5_dev_intf = hw_mgr->a5_dev_intf; if ((!ipe0_dev_intf) || (!bps_dev_intf)) { @@ -1347,16 +1349,26 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, ctx_data->icp_dev_acquire_info->dev_type); clk_upd_cmd.curr_clk_rate = curr_clk_rate; clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; + clk_upd_cmd.clk_level = -1; dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, &clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd)); - if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS) - if (ipe1_dev_intf) + if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS) { + if (ipe1_dev_intf) { ipe1_dev_intf->hw_ops.process_cmd( ipe1_dev_intf->hw_priv, id, &clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd)); + } + + /* update a5 clock */ + CAM_DBG(CAM_ICP, "Update ICP clk to level [%d]", + clk_upd_cmd.clk_level); + a5_dev_intf->hw_ops.process_cmd(a5_dev_intf->hw_priv, + CAM_ICP_A5_CMD_CLK_UPDATE, &clk_upd_cmd.clk_level, + sizeof(clk_upd_cmd.clk_level)); + } return 0; } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h index 397592a4410c..5d4371483acc 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef CAM_A5_HW_INTF_H @@ -26,6 +26,7 @@ enum cam_icp_a5_cmd_type { CAM_ICP_A5_CMD_CPAS_STOP, CAM_ICP_A5_CMD_UBWC_CFG, CAM_ICP_A5_CMD_PC_PREP, + CAM_ICP_A5_CMD_CLK_UPDATE, CAM_ICP_A5_CMD_MAX, }; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h index aadf27fef485..80a724b53d94 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h @@ -25,9 +25,14 @@ enum cam_a5_hw_type { * * @curr_clk_rate: clk rate to HW * @ipe_bps_pc_enable power collpase enable flag + * @clk_level: clk level corresponding to the clk rate + * populated as output while the clk is being + * updated to the given rate */ struct cam_a5_clk_update_cmd { uint32_t curr_clk_rate; bool ipe_bps_pc_enable; + int32_t clk_level; }; + #endif diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 82d0ebe54cc4..9ea8f51bb914 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -361,6 +361,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, struct cam_a5_clk_update_cmd *clk_upd_cmd = (struct cam_a5_clk_update_cmd *)cmd_args; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; + int32_t clk_level = 0, err = 0; CAM_DBG(CAM_ICP, "ipe_src_clk rate = %d", (int)clk_rate); if (!core_info->clk_enable) { @@ -386,8 +387,15 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_ipe_update_clk_rate(soc_info, clk_rate); if (rc) CAM_ERR(CAM_ICP, "Failed to update clk"); - } + + err = cam_soc_util_get_clk_level(soc_info, + clk_rate, soc_info->src_clk_idx, + &clk_level); + if (err == 0) + clk_upd_cmd->clk_level = clk_level; + break; + } case CAM_ICP_IPE_CMD_DISABLE_CLK: if (core_info->clk_enable == true) cam_ipe_toggle_clk(soc_info, false); From 360454feef09207fdbbfba03f91c1d96c026a1b4 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 21 May 2019 16:37:46 -0700 Subject: [PATCH 051/790] msm: camera: icp: Avoid accessing frame process data in the kernel IPE/BPS frame process data keeps changing one needs to update the kernel hfi header accordingly everytime. This change avoids accessing those structs in the kernel. Userspace will ensure resetting the struct to a default value. Change-Id: If224befa89643f44997bb6e826f8dfcfac5d08d1 Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 49 +------------------ 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index fc7942bc42bf..84ea1ac6323f 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3836,16 +3836,12 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, uint32_t *fw_cmd_buf_iova_addr) { int rc = 0; - int i, j, k; + int i; int num_cmd_buf = 0; uint64_t addr; size_t len; struct cam_cmd_buf_desc *cmd_desc = NULL; uintptr_t cpu_addr = 0; - struct ipe_frame_process_data *frame_process_data = NULL; - struct bps_frame_process_data *bps_frame_process_data = NULL; - struct frame_set *ipe_set = NULL; - struct frame_buffer *bps_bufs = NULL; cmd_desc = (struct cam_cmd_buf_desc *) ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); @@ -3893,49 +3889,6 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, return -EINVAL; } - if (ctx_data->icp_dev_acquire_info->dev_type != - CAM_ICP_RES_TYPE_BPS) { - CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr); - frame_process_data = (struct ipe_frame_process_data *)cpu_addr; - CAM_DBG(CAM_ICP, "%u %u %u", frame_process_data->max_num_cores, - frame_process_data->target_time, - frame_process_data->frames_in_batch); - frame_process_data->strip_lib_out_addr = 0; - frame_process_data->iq_settings_addr = 0; - frame_process_data->scratch_buffer_addr = 0; - frame_process_data->ubwc_stats_buffer_addr = 0; - frame_process_data->cdm_buffer_addr = 0; - frame_process_data->cdm_prog_base = 0; - for (i = 0; i < frame_process_data->frames_in_batch; i++) { - ipe_set = &frame_process_data->framesets[i]; - for (j = 0; j < IPE_IO_IMAGES_MAX; j++) { - for (k = 0; k < MAX_NUM_OF_IMAGE_PLANES; k++) { - ipe_set->buffers[j].buf_ptr[k] = 0; - ipe_set->buffers[j].meta_buf_ptr[k] = 0; - } - } - } - } else { - CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr); - bps_frame_process_data = - (struct bps_frame_process_data *)cpu_addr; - CAM_DBG(CAM_ICP, "%u %u", - bps_frame_process_data->max_num_cores, - bps_frame_process_data->target_time); - bps_frame_process_data->ubwc_stats_buffer_addr = 0; - bps_frame_process_data->cdm_buffer_addr = 0; - bps_frame_process_data->iq_settings_addr = 0; - bps_frame_process_data->strip_lib_out_addr = 0; - bps_frame_process_data->cdm_prog_addr = 0; - for (i = 0; i < BPS_IO_IMAGES_MAX; i++) { - bps_bufs = &bps_frame_process_data->buffers[i]; - for (j = 0; j < MAX_NUM_OF_IMAGE_PLANES; j++) { - bps_bufs->buf_ptr[j] = 0; - bps_bufs->meta_buf_ptr[j] = 0; - } - } - } - return rc; } From f2a0cc111f44f0ffb625ffcddb3155c0b1afa07a Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 18 Jul 2019 15:03:05 -0700 Subject: [PATCH 052/790] msm: camera: reqmgr: Dump device name as part of frame skip log Currently we can infer only the pd of the device whose request was not available on time leading to a frame skip. This change identifies and logs the device name to ease debugging. Change-Id: I49a3cd84611b21626c68395b11f0ef52bffb62db Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_req_mgr/cam_req_mgr_core.c | 60 +++++++++++++++++++++++--- drivers/cam_req_mgr/cam_req_mgr_core.h | 29 ++++++++++--- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index a9edecc44ab4..3147eeab0a7b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -167,6 +167,40 @@ static int __cam_req_mgr_inject_delay( return rc; } +/** + * __cam_req_mgr_find_dev_name() + * + * @brief : Find the dev name whose req is not ready + * @link : link info + * @req_id : req_id which is not ready + * @pd : pipeline delay + * @masked_val : masked value holds the bit for all devices + * that don't have the req_id ready for a given + * pipeline delay + * @pd : pipeline delay + * + */ +static void __cam_req_mgr_find_dev_name( + struct cam_req_mgr_core_link *link, + int64_t req_id, uint32_t pd, uint32_t masked_val) +{ + 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 == pd) { + if (masked_val & (1 << dev->dev_bit)) + continue; + + CAM_INFO(CAM_CRM, + "Skip Frame: req: %lld not ready on link: 0x%x for pd: %d dev: %s open_req count: %d", + req_id, link->link_hdl, pd, dev->dev_info.name, + link->open_req_cnt); + } + } +} + /** * __cam_req_mgr_notify_error_on_link() * @@ -296,14 +330,15 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) } } else { /* This pd table is not ready to proceed with asked idx */ - CAM_INFO(CAM_CRM, - "Skip Frame: req: %lld not ready pd: %d open_req count: %d", - CRM_GET_REQ_ID(traverse_data->in_q, curr_idx), - tbl->pd, - traverse_data->open_req_cnt); + traverse_data->result_data.req_id = + CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); + traverse_data->result_data.pd = tbl->pd; + traverse_data->result_data.masked_value = + (tbl->dev_mask & slot->req_ready_map); SET_FAILURE_BIT(traverse_data->result, tbl->pd); return -EAGAIN; } + return 0; } @@ -650,6 +685,9 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.tbl = link->req.l_tbl; traverse_data.in_q = in_q; traverse_data.result = 0; + traverse_data.result_data.masked_value = 0; + traverse_data.result_data.pd = 0; + traverse_data.result_data.req_id = 0; traverse_data.validate_only = validate_only; traverse_data.open_req_cnt = link->open_req_cnt; @@ -669,8 +707,13 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, apply_data[2].req_id, apply_data[1].req_id, apply_data[0].req_id); - } else + } else { rc = -EAGAIN; + __cam_req_mgr_find_dev_name(link, + traverse_data.result_data.req_id, + traverse_data.result_data.pd, + traverse_data.result_data.masked_value); + } return rc; } @@ -2104,6 +2147,7 @@ int cam_req_mgr_process_error(void *priv, void *data) spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_ERR; spin_unlock_bh(&link->link_state_spin_lock); + link->open_req_cnt++; } } mutex_unlock(&link->req.lock); @@ -2580,7 +2624,9 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, dev->dev_bit = pd_tbl->dev_count++; dev->pd_tbl = pd_tbl; pd_tbl->dev_mask |= (1 << dev->dev_bit); - + CAM_DBG(CAM_CRM, "dev_bit %u name %s pd %u mask %d", + dev->dev_bit, dev->dev_info.name, pd_tbl->pd, + pd_tbl->dev_mask); /* Communicate with dev to establish the link */ dev->ops->link_setup(&link_data); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 8eb15bec802d..aeede7a87166 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -125,10 +125,24 @@ enum cam_req_mgr_link_state { CAM_CRM_LINK_STATE_MAX, }; +/** + * struct cam_req_mgr_traverse_result + * @req_id : Req id that is not ready + * @pd : pipeline delay + * @masked_value : Holds the dev bit for devices not ready + * for the given request + */ +struct cam_req_mgr_traverse_result { + int64_t req_id; + uint32_t pd; + uint32_t masked_value; +}; + /** * struct cam_req_mgr_traverse * @idx : slot index * @result : contains which all tables were able to apply successfully + * @result_data : holds the result of traverse in case it fails * @tbl : pointer of pipeline delay based request table * @apply_data : pointer which various tables will update during traverse * @in_q : input request queue pointer @@ -136,13 +150,14 @@ enum cam_req_mgr_link_state { * @open_req_cnt : Count of open requests yet to be serviced in the kernel. */ struct cam_req_mgr_traverse { - int32_t idx; - uint32_t result; - struct cam_req_mgr_req_tbl *tbl; - struct cam_req_mgr_apply *apply_data; - struct cam_req_mgr_req_queue *in_q; - bool validate_only; - int32_t open_req_cnt; + int32_t idx; + uint32_t result; + struct cam_req_mgr_traverse_result result_data; + struct cam_req_mgr_req_tbl *tbl; + struct cam_req_mgr_apply *apply_data; + struct cam_req_mgr_req_queue *in_q; + bool validate_only; + int32_t open_req_cnt; }; /** From 5b016ad22077f42e852f86663f080ea6cb7f3bef Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 9 Aug 2019 12:56:12 -0700 Subject: [PATCH 053/790] Camera: Correct makefiles for correct header inclusion Correct some Makefiles and drivers header inclusion. Change-Id: Iec3e6e0333ae55e8f1cff9780723e0dad954ff83 Signed-off-by: Jigarkumar Zala --- drivers/Makefile | 26 +++++++++---------- drivers/cam_cdm/Makefile | 4 +-- drivers/cam_cdm/cam_cdm_hw_core.c | 2 +- drivers/cam_core/Makefile | 2 +- drivers/cam_core/cam_context_utils.c | 4 +-- drivers/cam_cpas/Makefile | 2 +- drivers/cam_cpas/cam_cpas_intf.c | 4 +-- drivers/cam_cpas/camss_top/Makefile | 2 +- drivers/cam_cpas/cpas_top/Makefile | 2 +- drivers/cam_fd/Makefile | 2 +- drivers/cam_fd/fd_hw_mgr/Makefile | 2 +- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 4 +-- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h | 2 +- drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile | 2 +- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h | 4 +-- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h | 6 ++--- drivers/cam_icp/Makefile | 2 +- drivers/cam_icp/cam_icp_context.c | 6 ++--- drivers/cam_icp/cam_icp_subdev.c | 6 ++--- drivers/cam_icp/hfi.c | 2 +- drivers/cam_icp/icp_hw/Makefile | 2 +- drivers/cam_icp/icp_hw/a5_hw/Makefile | 2 +- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 2 +- drivers/cam_icp/icp_hw/bps_hw/Makefile | 2 +- drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile | 2 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 6 ++--- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 +- .../icp_hw_mgr/include/cam_a5_hw_intf.h | 4 +-- .../icp_hw_mgr/include/cam_bps_hw_intf.h | 4 +-- .../icp_hw_mgr/include/cam_ipe_hw_intf.h | 4 +-- .../icp_hw/include/cam_icp_hw_mgr_intf.h | 4 +-- drivers/cam_icp/icp_hw/ipe_hw/Makefile | 2 +- drivers/cam_isp/Makefile | 2 +- drivers/cam_isp/cam_isp_context.h | 4 +-- drivers/cam_isp/cam_isp_dev.c | 2 +- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile | 2 +- .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c | 2 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 2 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 2 +- drivers/cam_jpeg/Makefile | 2 +- drivers/cam_jpeg/cam_jpeg_context.h | 2 +- drivers/cam_lrme/Makefile | 2 +- drivers/cam_req_mgr/Makefile | 6 ++--- drivers/cam_req_mgr/cam_mem_mgr_api.h | 2 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 4 +-- drivers/cam_req_mgr/cam_req_mgr_util.c | 2 +- .../cam_sensor_module/cam_actuator/Makefile | 4 ++- drivers/cam_sensor_module/cam_cci/Makefile | 5 ++-- .../cam_sensor_module/cam_cci/cam_cci_core.h | 2 +- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 2 +- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 4 +-- drivers/cam_sensor_module/cam_csiphy/Makefile | 2 +- .../cam_csiphy/cam_csiphy_dev.c | 2 +- .../cam_csiphy/cam_csiphy_dev.h | 2 +- drivers/cam_sensor_module/cam_eeprom/Makefile | 2 +- .../cam_eeprom/cam_eeprom_core.c | 2 +- .../cam_eeprom/cam_eeprom_dev.h | 2 +- drivers/cam_sensor_module/cam_flash/Makefile | 5 ++-- .../cam_flash/cam_flash_core.h | 2 +- .../cam_flash/cam_flash_dev.h | 4 +-- drivers/cam_sensor_module/cam_ois/Makefile | 3 ++- .../cam_sensor_module/cam_ois/cam_ois_dev.h | 2 +- .../cam_sensor_module/cam_res_mgr/Makefile | 2 +- drivers/cam_sensor_module/cam_sensor/Makefile | 2 +- .../cam_sensor_module/cam_sensor_io/Makefile | 2 +- .../cam_sensor_io/cam_sensor_i2c.h | 2 +- .../cam_sensor_io/cam_sensor_io.h | 2 +- .../cam_sensor_io/cam_sensor_spi.h | 2 +- .../cam_sensor_utils/Makefile | 2 +- .../cam_sensor_utils/cam_sensor_cmn_header.h | 4 +-- .../cam_sensor_utils/cam_sensor_util.c | 2 +- .../cam_sensor_utils/cam_sensor_util.h | 6 ++--- drivers/cam_smmu/Makefile | 2 +- drivers/cam_smmu/cam_smmu_api.c | 2 +- drivers/cam_sync/Makefile | 2 +- drivers/cam_utils/Makefile | 2 +- drivers/cam_utils/cam_trace.c | 2 +- drivers/cam_utils/cam_trace.h | 2 +- include/uapi/media/cam_cpas.h | 2 +- include/uapi/media/cam_fd.h | 4 +-- include/uapi/media/cam_icp.h | 4 +-- include/uapi/media/cam_isp.h | 8 +++--- include/uapi/media/cam_jpeg.h | 4 +-- include/uapi/media/cam_lrme.h | 4 +-- include/uapi/media/cam_req_mgr.h | 2 +- include/uapi/media/cam_sensor.h | 2 +- 86 files changed, 138 insertions(+), 133 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index 28d4762a55df..9e0aee9f69e3 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,13 +1,13 @@ -obj-y += cam_req_mgr/ -obj-y += cam_utils/ -obj-y += cam_core/ -obj-y += cam_sync/ -obj-y += cam_smmu/ -obj-y += cam_cpas/ -obj-y += cam_cdm/ -obj-y += cam_isp/ -obj-y += cam_sensor_module/ -obj-y += cam_icp/ -obj-y += cam_jpeg/ -obj-y += cam_fd/ -obj-y += cam_lrme/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_utils/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_core/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sync/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpas/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_module/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme/ diff --git a/drivers/cam_cdm/Makefile b/drivers/cam_cdm/Makefile index 2b5b712cbbb3..323a523011a2 100644 --- a/drivers/cam_cdm/Makefile +++ b/drivers/cam_cdm/Makefile @@ -1,12 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm_util.o cam_cdm_intf.o cam_cdm_soc.o\ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm_soc.o cam_cdm_util.o cam_cdm_intf.o\ cam_cdm_core_common.o cam_cdm_virtual_core.o \ cam_cdm_hw_core.o diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 40dba7352f32..bf251a823819 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include "cam_soc_util.h" #include "cam_smmu_api.h" #include "cam_cdm_intf_api.h" diff --git a/drivers/cam_core/Makefile b/drivers/cam_core/Makefile index 986b65f0ecd4..e117039fc3ab 100644 --- a/drivers/cam_core/Makefile +++ b/drivers/cam_core/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 6b6b17743d1b..34dc7b81d454 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -7,8 +7,8 @@ #include #include #include -#include -#include +#include +#include #include "cam_context.h" #include "cam_context_utils.h" diff --git a/drivers/cam_cpas/Makefile b/drivers/cam_cpas/Makefile index e0af486932f1..6fc8f9830cec 100644 --- a/drivers/cam_cpas/Makefile +++ b/drivers/cam_cpas/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index d1b32a0d916a..a1d8b4026059 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include #include "cam_subdev.h" diff --git a/drivers/cam_cpas/camss_top/Makefile b/drivers/cam_cpas/camss_top/Makefile index 902e74e20607..de11b7136563 100644 --- a/drivers/cam_cpas/camss_top/Makefile +++ b/drivers/cam_cpas/camss_top/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_cpas/cpas_top/Makefile b/drivers/cam_cpas/cpas_top/Makefile index 2db4c393c65d..0306b14ef14a 100644 --- a/drivers/cam_cpas/cpas_top/Makefile +++ b/drivers/cam_cpas/cpas_top/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_fd/Makefile b/drivers/cam_fd/Makefile index 20fd941327ed..92356a35d8c8 100644 --- a/drivers/cam_fd/Makefile +++ b/drivers/cam_fd/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_fd/fd_hw_mgr/Makefile b/drivers/cam_fd/fd_hw_mgr/Makefile index cc15876c9602..8db8097679b5 100644 --- a/drivers/cam_fd/fd_hw_mgr/Makefile +++ b/drivers/cam_fd/fd_hw_mgr/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index 0d7e709ad38f..fad7caff6437 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -5,8 +5,8 @@ #include #include -#include -#include +#include +#include #include "cam_io_util.h" #include "cam_soc_util.h" diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h index 351cae971a42..49bc5bbc1b07 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include "cam_hw.h" #include "cam_hw_intf.h" #include "cam_cpas_api.h" diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile b/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile index fd43ca7a4546..6a53cc67f7e6 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h index 22f9130d9cd1..1f8815e72f20 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h @@ -9,8 +9,8 @@ #include #include #include -#include -#include +#include +#include #include "cam_common_util.h" #include "cam_debug_util.h" diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h index 040bd161e006..e35e5e520b7b 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -9,9 +9,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include "cam_io_util.h" #include "cam_soc_util.h" diff --git a/drivers/cam_icp/Makefile b/drivers/cam_icp/Makefile index b41c6cf1fb65..aec65fc06f4b 100644 --- a/drivers/cam_icp/Makefile +++ b/drivers/cam_icp/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 6e043fd95c63..ec23a6ee9d96 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -7,9 +7,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include "cam_node.h" #include "cam_context.h" #include "cam_context_utils.h" diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index f6dbaec5f133..bdb2ed5f900b 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -17,9 +17,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include "cam_req_mgr_dev.h" #include "cam_subdev.h" #include "cam_node.h" diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 06ad9de00eac..783b5c3723be 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/cam_icp/icp_hw/Makefile b/drivers/cam_icp/icp_hw/Makefile index e07836a01f12..68b36f706604 100644 --- a/drivers/cam_icp/icp_hw/Makefile +++ b/drivers/cam_icp/icp_hw/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_icp/icp_hw/a5_hw/Makefile b/drivers/cam_icp/icp_hw/a5_hw/Makefile index db80567488a0..9c3aac09a137 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/Makefile +++ b/drivers/cam_icp/icp_hw/a5_hw/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index f7d94b2ce679..5a2b7868fb4c 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include "cam_io_util.h" #include "cam_a5_hw_intf.h" #include "cam_hw.h" diff --git a/drivers/cam_icp/icp_hw/bps_hw/Makefile b/drivers/cam_icp/icp_hw/bps_hw/Makefile index 2abf88310cbd..491e6a16492b 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/Makefile +++ b/drivers/cam_icp/icp_hw/bps_hw/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile b/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile index 2d06413e74ca..b87d5dba817a 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/hw_utils/include diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 57a88f5a3070..17c26a654eb2 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -16,9 +16,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include "cam_sync_api.h" #include "cam_packet_util.h" diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 3fa1ee0e0f8f..fb7fff082114 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include "cam_icp_hw_intf.h" #include "cam_hw_mgr_intf.h" #include "cam_hw_intf.h" diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h index 397592a4410c..eaa56a48802e 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h @@ -7,8 +7,8 @@ #define CAM_A5_HW_INTF_H #include -#include -#include +#include +#include #include "cam_hw_mgr_intf.h" #include "cam_icp_hw_intf.h" diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h index e02022435d8b..f2628e41640b 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h @@ -6,8 +6,8 @@ #ifndef CAM_BPS_HW_INTF_H #define CAM_BPS_HW_INTF_H -#include -#include +#include +#include #include "cam_hw_mgr_intf.h" #include "cam_icp_hw_intf.h" diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h index 836a56492447..ea14ee623fb3 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h @@ -6,8 +6,8 @@ #ifndef CAM_IPE_HW_INTF_H #define CAM_IPE_HW_INTF_H -#include -#include +#include +#include #include "cam_hw_mgr_intf.h" #include "cam_icp_hw_intf.h" diff --git a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h index 25fbe2b8f6c5..d87c7ef238df 100644 --- a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h +++ b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h @@ -7,8 +7,8 @@ #define CAM_ICP_HW_MGR_INTF_H #include -#include -#include +#include +#include #include "cam_cpas_api.h" #define ICP_CLK_TURBO_HZ 600000000 diff --git a/drivers/cam_icp/icp_hw/ipe_hw/Makefile b/drivers/cam_icp/icp_hw/ipe_hw/Makefile index 5055e12dff2a..d57373c332e0 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/Makefile +++ b/drivers/cam_icp/icp_hw/ipe_hw/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_isp/Makefile b/drivers/cam_isp/Makefile index 069350122c7b..86ad96d61cb7 100644 --- a/drivers/cam_isp/Makefile +++ b/drivers/cam_isp/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 1f5bd1048f5b..5aefa690697a 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include #include "cam_context.h" #include "cam_isp_hw_mgr_intf.h" diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index b93ae3fd5b82..9c3f33181ae6 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include "cam_isp_dev.h" #include "cam_hw_mgr_intf.h" #include "cam_isp_hw_mgr_intf.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile index bdf6d3ee981b..d5ab83c81dd7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile @@ -3,7 +3,7 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/isp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c index ca2d443747f7..ebf8115723a5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c @@ -10,7 +10,7 @@ #include "cam_debug_util.h" #include "cam_cdm_util.h" #include "cam_hw_intf.h" -#include "../../cam_ife_hw_mgr.h" +#include "cam_ife_hw_mgr.h" #include "cam_vfe_hw_intf.h" #include "cam_irq_controller.h" #include "cam_tasklet_util.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 2a452c0d874d..990807b51acd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -10,7 +10,7 @@ #include "cam_debug_util.h" #include "cam_cdm_util.h" #include "cam_hw_intf.h" -#include "../../cam_ife_hw_mgr.h" +#include "cam_ife_hw_mgr.h" #include "cam_vfe_hw_intf.h" #include "cam_irq_controller.h" #include "cam_tasklet_util.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index f0dea326a8b0..0ec5ba8c084f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -11,7 +11,7 @@ #include "cam_debug_util.h" #include "cam_cdm_util.h" #include "cam_hw_intf.h" -#include "../../cam_ife_hw_mgr.h" +#include "cam_ife_hw_mgr.h" #include "cam_vfe_hw_intf.h" #include "cam_irq_controller.h" #include "cam_tasklet_util.h" diff --git a/drivers/cam_jpeg/Makefile b/drivers/cam_jpeg/Makefile index 3b9bbdbedb7b..471f870e4c73 100644 --- a/drivers/cam_jpeg/Makefile +++ b/drivers/cam_jpeg/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h index 739dc6fd4525..3a11865a6051 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.h +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -6,7 +6,7 @@ #ifndef _CAM_JPEG_CONTEXT_H_ #define _CAM_JPEG_CONTEXT_H_ -#include +#include #include "cam_context.h" #include "cam_jpeg_hw_mgr_intf.h" diff --git a/drivers/cam_lrme/Makefile b/drivers/cam_lrme/Makefile index afc585ebf374..72cdba4da04c 100644 --- a/drivers/cam_lrme/Makefile +++ b/drivers/cam_lrme/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync diff --git a/drivers/cam_req_mgr/Makefile b/drivers/cam_req_mgr/Makefile index 375d17133193..50599d879255 100644 --- a/drivers/cam_req_mgr/Makefile +++ b/drivers/cam_req_mgr/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree) +ccflags-y += -I$(src) obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_core.o\ cam_req_mgr_dev.o \ diff --git a/drivers/cam_req_mgr/cam_mem_mgr_api.h b/drivers/cam_req_mgr/cam_mem_mgr_api.h index 6141e7cc136b..0bbf094ee1e8 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr_api.h +++ b/drivers/cam_req_mgr/cam_mem_mgr_api.h @@ -7,7 +7,7 @@ #define _CAM_MEM_MGR_API_H_ #include -#include "../cam_smmu/cam_smmu_api.h" +#include "cam_smmu_api.h" /** * struct cam_mem_mgr_request_desc diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index b1a05cc14b9a..718942552bc7 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" #include "cam_req_mgr_core.h" diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 54ab1680b112..f833f667de97 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "cam_req_mgr_util.h" #include "cam_debug_util.h" diff --git a/drivers/cam_sensor_module/cam_actuator/Makefile b/drivers/cam_sensor_module/cam_actuator/Makefile index a51b8fea65bb..e61c6eeba3c0 100644 --- a/drivers/cam_sensor_module/cam_actuator/Makefile +++ b/drivers/cam_sensor_module/cam_actuator/Makefile @@ -1,12 +1,14 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator_dev.o cam_actuator_core.o cam_actuator_soc.o diff --git a/drivers/cam_sensor_module/cam_cci/Makefile b/drivers/cam_sensor_module/cam_cci/Makefile index 82734cb81445..a1301bf41d5d 100644 --- a/drivers/cam_sensor_module/cam_cci/Makefile +++ b/drivers/cam_sensor_module/cam_cci/Makefile @@ -1,11 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media -ccflags-y += -I$(srctree)/techpack/camera/drivers/camera/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/include/uapi +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu ccflags-y += -I$(srctree) obj-$(CONFIG_SPECTRA_CAMERA) += cam_cci_dev.o cam_cci_core.o cam_cci_soc.o diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.h b/drivers/cam_sensor_module/cam_cci/cam_cci_core.h index aeaee32502ec..739fd303b236 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.h @@ -6,7 +6,7 @@ #define _CAM_CCI_CORE_H_ #include -#include +#include #include "cam_cci_dev.h" #include "cam_cci_soc.h" diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 5f155df4dc44..e30574da5c0b 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -4,7 +4,7 @@ */ #include "cam_cci_dev.h" -#include "../../cam_req_mgr/cam_req_mgr_dev.h" +#include "cam_req_mgr_dev.h" #include "cam_cci_soc.h" #include "cam_cci_core.h" diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 4bc1d34af3d2..439e3058a70b 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -18,14 +18,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include -#include "../../cam_req_mgr/cam_subdev.h" +#include "cam_subdev.h" #include #include "cam_cci_hwreg.h" #include "cam_soc_util.h" diff --git a/drivers/cam_sensor_module/cam_csiphy/Makefile b/drivers/cam_sensor_module/cam_csiphy/Makefile index eb23b89c2108..d98b84574363 100644 --- a/drivers/cam_sensor_module/cam_csiphy/Makefile +++ b/drivers/cam_sensor_module/cam_csiphy/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 3325071905ba..ba98d9adcc2d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -7,7 +7,7 @@ #include "cam_req_mgr_dev.h" #include "cam_csiphy_soc.h" #include "cam_csiphy_core.h" -#include +#include static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 2bae9a51529b..78c7a848cd81 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/cam_sensor_module/cam_eeprom/Makefile b/drivers/cam_sensor_module/cam_eeprom/Makefile index 850b16787c11..7a676c1135a0 100644 --- a/drivers/cam_sensor_module/cam_eeprom/Makefile +++ b/drivers/cam_sensor_module/cam_eeprom/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index c1320d97f644..6600c92d8132 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -5,7 +5,7 @@ #include #include -#include +#include #include "cam_eeprom_core.h" #include "cam_eeprom_soc.h" diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h index 41817e97eae1..66f8aaddc958 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "cam_soc_util.h" #include "cam_context.h" diff --git a/drivers/cam_sensor_module/cam_flash/Makefile b/drivers/cam_sensor_module/cam_flash/Makefile index dfc2bc2c8c8c..da9e9e1b19cb 100644 --- a/drivers/cam_sensor_module/cam_flash/Makefile +++ b/drivers/cam_sensor_module/cam_flash/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr @@ -9,6 +9,7 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash_dev.o cam_flash_core.o cam_flash_soc.o diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/cam_sensor_module/cam_flash/cam_flash_core.h index 6cafe927cdbb..c382809dbb92 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.h @@ -6,7 +6,7 @@ #ifndef _CAM_FLASH_CORE_H_ #define _CAM_FLASH_CORE_H_ -#include +#include #include "cam_flash_dev.h" int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 8bd5b9115f05..43ed13406e3d 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include #include "cam_req_mgr_util.h" #include "cam_req_mgr_interface.h" #include "cam_subdev.h" diff --git a/drivers/cam_sensor_module/cam_ois/Makefile b/drivers/cam_sensor_module/cam_ois/Makefile index 345203739517..fa7fabc0f055 100644 --- a/drivers/cam_sensor_module/cam_ois/Makefile +++ b/drivers/cam_sensor_module/cam_ois/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io @@ -8,6 +8,7 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index 1808a2b2f0c6..788243ae9da0 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/cam_sensor_module/cam_res_mgr/Makefile b/drivers/cam_sensor_module/cam_res_mgr/Makefile index 5bc9889b40e9..1c8ccb0e3bf4 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/Makefile +++ b/drivers/cam_sensor_module/cam_res_mgr/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -#ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +#ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_sensor_module/cam_sensor/Makefile b/drivers/cam_sensor_module/cam_sensor/Makefile index 641b1c490329..d3a6fbb6c3e4 100644 --- a/drivers/cam_sensor_module/cam_sensor/Makefile +++ b/drivers/cam_sensor_module/cam_sensor/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_sensor_module/cam_sensor_io/Makefile b/drivers/cam_sensor_module/cam_sensor_io/Makefile index 34ab4315aa92..5b11171fa087 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/Makefile +++ b/drivers/cam_sensor_module/cam_sensor_io/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h index 752b7fdd8a22..def8be55bc8b 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include "cam_cci_dev.h" #include "cam_sensor_io.h" diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h index 3c49212d2d6f..f70709997e69 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h @@ -6,7 +6,7 @@ #ifndef _CAM_SENSOR_IO_H_ #define _CAM_SENSOR_IO_H_ -#include +#include #include "cam_sensor_cmn_header.h" diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h index 7a9c44332c49..73d7ea9456ba 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include "cam_sensor_i2c.h" #define MAX_SPI_SIZE 110 diff --git a/drivers/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/cam_sensor_module/cam_sensor_utils/Makefile index 4813d33a5bc5..d822b2a733cf 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/Makefile +++ b/drivers/cam_sensor_module/cam_sensor_utils/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index a5699342dce0..e43e8abe0809 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -13,8 +13,8 @@ #include #include #include -#include -#include +#include +#include #define MAX_REGULATOR 5 #define MAX_POWER_CONFIG 12 diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index f5ea2dc04a3d..0d82579e7999 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -5,7 +5,7 @@ #include #include "cam_sensor_util.h" -#include +#include "cam_mem_mgr.h" #include "cam_res_mgr_api.h" #define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend" diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 69679f8c76e7..c923efe61dc5 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -12,9 +12,9 @@ #include #include #include "cam_sensor_cmn_header.h" -#include "../../cam_req_mgr/cam_req_mgr_util.h" -#include "../../cam_req_mgr/cam_req_mgr_interface.h" -#include "../../cam_req_mgr/cam_mem_mgr.h" +#include "cam_req_mgr_util.h" +#include "cam_req_mgr_interface.h" +#include #include "cam_soc_util.h" #include "cam_debug_util.h" #include "cam_sensor_io.h" diff --git a/drivers/cam_smmu/Makefile b/drivers/cam_smmu/Makefile index c82e3978d028..b674b48ceb2d 100644 --- a/drivers/cam_smmu/Makefile +++ b/drivers/cam_smmu/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index a60e02492a4c..478a00657f3b 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "cam_smmu_api.h" #include "cam_debug_util.h" diff --git a/drivers/cam_sync/Makefile b/drivers/cam_sync/Makefile index e15ed0ce8931..40efdf4dd794 100644 --- a/drivers/cam_sync/Makefile +++ b/drivers/cam_sync/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-$(CONFIG_MSM_GLOBAL_SYNX) += -I$(srctree)/drivers/media/platform/msm/synx ccflags-y += -I$(src) diff --git a/drivers/cam_utils/Makefile b/drivers/cam_utils/Makefile index fb8c48eeeb04..e17c2f50bb95 100644 --- a/drivers/cam_utils/Makefile +++ b/drivers/cam_utils/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media +ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ diff --git a/drivers/cam_utils/cam_trace.c b/drivers/cam_utils/cam_trace.c index d4a6c9279081..9b45091b4b85 100644 --- a/drivers/cam_utils/cam_trace.c +++ b/drivers/cam_utils/cam_trace.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */ /* Instantiate tracepoints */ diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h index 95bc95da9e75..838997590771 100644 --- a/drivers/cam_utils/cam_trace.h +++ b/drivers/cam_utils/cam_trace.h @@ -14,7 +14,7 @@ #define TRACE_INCLUDE_FILE ../../techpack/camera/drivers/cam_utils/cam_trace #include -#include +#include #include "cam_req_mgr_core.h" #include "cam_req_mgr_interface.h" #include "cam_context.h" diff --git a/include/uapi/media/cam_cpas.h b/include/uapi/media/cam_cpas.h index a3d3ca9d5a71..b85ab068f9e8 100644 --- a/include/uapi/media/cam_cpas.h +++ b/include/uapi/media/cam_cpas.h @@ -6,7 +6,7 @@ #ifndef __UAPI_CAM_CPAS_H__ #define __UAPI_CAM_CPAS_H__ -#include "cam_defs.h" +#include #define CAM_FAMILY_CAMERA_SS 1 #define CAM_FAMILY_CPAS_SS 2 diff --git a/include/uapi/media/cam_fd.h b/include/uapi/media/cam_fd.h index f456683b3779..126be4555f69 100644 --- a/include/uapi/media/cam_fd.h +++ b/include/uapi/media/cam_fd.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_FD_H__ #define __UAPI_CAM_FD_H__ -#include "cam_defs.h" +#include #define CAM_FD_MAX_FACES 35 #define CAM_FD_RAW_RESULT_ENTRIES 512 diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h index ac683bffa4ce..4b5419d2f21d 100644 --- a/include/uapi/media/cam_icp.h +++ b/include/uapi/media/cam_icp.h @@ -6,8 +6,8 @@ #ifndef __UAPI_CAM_ICP_H__ #define __UAPI_CAM_ICP_H__ -#include "cam_defs.h" -#include "cam_cpas.h" +#include +#include /* icp, ipe, bps, cdm(ipe/bps) are used in querycap */ #define CAM_ICP_DEV_TYPE_A5 1 diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h index ee6440a90023..956ad9880fee 100644 --- a/include/uapi/media/cam_isp.h +++ b/include/uapi/media/cam_isp.h @@ -6,10 +6,10 @@ #ifndef __UAPI_CAM_ISP_H__ #define __UAPI_CAM_ISP_H__ -#include "cam_defs.h" -#include "cam_isp_vfe.h" -#include "cam_isp_ife.h" -#include "cam_cpas.h" +#include +#include +#include +#include /* ISP driver name */ #define CAM_ISP_DEV_NAME "cam-isp" diff --git a/include/uapi/media/cam_jpeg.h b/include/uapi/media/cam_jpeg.h index 6513bbae740b..fd0ed2a2cfdb 100644 --- a/include/uapi/media/cam_jpeg.h +++ b/include/uapi/media/cam_jpeg.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_JPEG_H__ #define __UAPI_CAM_JPEG_H__ -#include "cam_defs.h" +#include /* enc, dma, cdm(enc/dma) are used in querycap */ #define CAM_JPEG_DEV_TYPE_ENC 0 diff --git a/include/uapi/media/cam_lrme.h b/include/uapi/media/cam_lrme.h index 90e3e76e0624..e3bd9449f7ef 100644 --- a/include/uapi/media/cam_lrme.h +++ b/include/uapi/media/cam_lrme.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_LRME_H__ #define __UAPI_CAM_LRME_H__ -#include "cam_defs.h" +#include /* LRME Resource Types */ diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index a8c12e2d7c0d..a1278dda9b09 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -10,7 +10,7 @@ #include #include #include -#include "cam_defs.h" +#include #define CAM_REQ_MGR_VNODE_NAME "cam-req-mgr-devnode" diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h index 5e1918a9a116..514e8bd946cd 100644 --- a/include/uapi/media/cam_sensor.h +++ b/include/uapi/media/cam_sensor.h @@ -8,7 +8,7 @@ #include #include -#include "cam_defs.h" +#include #define CAM_SENSOR_PROBE_CMD (CAM_COMMON_OPCODE_MAX + 1) #define CAM_FLASH_MAX_LED_TRIGGERS 3 From 3b1e74e59b958b943bba405f7b95ccd86a51daeb Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 23 Jul 2019 19:54:43 +0800 Subject: [PATCH 054/790] msm: camera: eeprom: Release the mutex even though got error Release the mutex even though got error. Change-Id: Iaeec418ce7db4623cede6c922869c6f8c69ab595 Signed-off-by: Depeng Shao Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index 6600c92d8132..c50230309c57 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -1450,7 +1450,7 @@ int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) &eeprom_cap, sizeof(struct cam_eeprom_query_cap_t))) { CAM_ERR(CAM_EEPROM, "Failed Copy to User"); - return -EFAULT; + rc = -EFAULT; goto release_mutex; } CAM_DBG(CAM_EEPROM, "eeprom_cap: ID: %d", eeprom_cap.slot_info); From 54070a35f24367d5663490d7ae4ad1f1886e8b5d Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 30 Jul 2019 17:21:46 -0700 Subject: [PATCH 055/790] msm: camera: ife: Add new controller for RUP IRQ Currently EPOCH IRQ handling is at a higher priority compared to RUP IRQ as RUP is fired at bus level. If RUP IRQ is not scheduled for handling by the time we receive EPOCH IRQ, EPOCH IRQ will be processed first and this will lead to missed SOF notification as the active request list might be empty. This change sets priority of both IRQs to the same by utilizing a new IRQ controller that is tasked with handling RUP from BUS. BUF_DONE is also subscribed to the same VFE top level BUS_WR IRQ but with a lower priority. IRQs for CAMIF Lite and RDI are subscribed to only if the ctx is RDI only. Change-Id: Id844ffe291e21ecfc7f7ed6fc53baf7e79dd2184 Signed-off-by: Venkat Chinta Signed-off-by: Mukund Madhusudan Atre --- .../irq_controller/cam_irq_controller.c | 36 +++++-- .../irq_controller/cam_irq_controller.h | 6 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 3 +- .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c | 2 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 2 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 99 +++++++++++++++---- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c | 6 +- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 50 ++++++++-- .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 4 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 50 ++++++++-- .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 4 +- 11 files changed, 208 insertions(+), 54 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index 8ed8b9f8b1a8..cc1fe18e05fd 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -53,6 +53,8 @@ struct cam_irq_evt_handler { * @clear_reg_offset: Offset of IRQ CLEAR register * @status_reg_offset: Offset of IRQ STATUS register * @top_half_enable_mask: Array of enabled bit_mask sorted by priority + * @pclear_mask: Partial mask to be cleared in case entire status + * register is not to be cleared */ struct cam_irq_register_obj { uint32_t index; @@ -60,6 +62,7 @@ struct cam_irq_register_obj { uint32_t clear_reg_offset; uint32_t status_reg_offset; uint32_t top_half_enable_mask[CAM_IRQ_PRIORITY_MAX]; + uint32_t pclear_mask; }; /** @@ -84,6 +87,8 @@ struct cam_irq_register_obj { * @hdl_idx: Unique identity of handler assigned on Subscribe. * Used to Unsubscribe. * @lock: Lock for use by controller + * @clear_all: Flag to indicate whether to clear entire status + * register */ struct cam_irq_controller { const char *name; @@ -98,6 +103,7 @@ struct cam_irq_controller { uint32_t hdl_idx; spinlock_t lock; struct cam_irq_th_payload th_payload; + bool clear_all; }; int cam_irq_controller_deinit(void **irq_controller) @@ -125,7 +131,8 @@ int cam_irq_controller_deinit(void **irq_controller) int cam_irq_controller_init(const char *name, void __iomem *mem_base, struct cam_irq_controller_reg_info *register_info, - void **irq_controller) + void **irq_controller, + bool clear_all) { struct cam_irq_controller *controller = NULL; int i, rc = 0; @@ -194,6 +201,7 @@ int cam_irq_controller_init(const char *name, controller->global_clear_bitmask = register_info->global_clear_bitmask; controller->global_clear_offset = register_info->global_clear_offset; controller->mem_base = mem_base; + controller->clear_all = clear_all; CAM_DBG(CAM_IRQ_CTRL, "global_clear_bitmask: 0x%x", controller->global_clear_bitmask); @@ -321,6 +329,9 @@ int cam_irq_controller_subscribe_irq(void *irq_controller, controller->irq_register_arr[i].top_half_enable_mask[priority] |= evt_bit_mask_arr[i]; + controller->irq_register_arr[i].pclear_mask + |= evt_bit_mask_arr[i]; + irq_mask = cam_io_r_mb(controller->mem_base + controller->irq_register_arr[i].mask_reg_offset); irq_mask |= evt_bit_mask_arr[i]; @@ -610,7 +621,8 @@ static void cam_irq_controller_th_processing( evt_handler->bottom_half, &bh_cmd); if (rc || !bh_cmd) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "No payload, IRQ handling frozen"); + "No payload, IRQ handling frozen for %s", + controller->name); continue; } } @@ -689,11 +701,19 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv) for (i = 0; i < controller->num_registers; i++) { irq_register = &controller->irq_register_arr[i]; controller->irq_status_arr[i] = cam_io_r_mb( - controller->mem_base + - controller->irq_register_arr[i].status_reg_offset); - cam_io_w_mb(controller->irq_status_arr[i], - controller->mem_base + - controller->irq_register_arr[i].clear_reg_offset); + controller->mem_base + irq_register->status_reg_offset); + + if (controller->clear_all) + cam_io_w_mb(controller->irq_status_arr[i], + controller->mem_base + + irq_register->clear_reg_offset); + else + cam_io_w_mb( + controller->irq_register_arr[i].pclear_mask & + controller->irq_status_arr[i], + controller->mem_base + + irq_register->clear_reg_offset); + CAM_DBG(CAM_IRQ_CTRL, "Read irq status%d (0x%x) = 0x%x", i, controller->irq_register_arr[i].status_reg_offset, controller->irq_status_arr[i]); diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h index caf21c5caf12..8fa0e951b714 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IRQ_CONTROLLER_H_ @@ -131,6 +131,7 @@ struct cam_irq_bh_api { * @register_info: Register Info structure associated with this Controller * @irq_controller: Pointer to IRQ Controller that will be filled if * initialization is successful + * @clear_all: Flag to indicate whether to clear entire status register * * @return: 0: Success * Negative: Failure @@ -138,7 +139,8 @@ struct cam_irq_bh_api { int cam_irq_controller_init(const char *name, void __iomem *mem_base, struct cam_irq_controller_reg_info *register_info, - void **irq_controller); + void **irq_controller, + bool clear_all); /* * cam_irq_controller_subscribe_irq() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 0fe3e9c79f35..0244e41d5a03 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -669,7 +669,8 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info, rc = cam_irq_controller_init(drv_name, CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX), - vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller); + vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller, + true); if (rc) { CAM_ERR(CAM_ISP, "Error, cam_irq_controller_init failed rc = %d", rc); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c index ebf8115723a5..314ebff70fc0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c @@ -1107,7 +1107,7 @@ int cam_vfe_bus_rd_ver1_init( 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); + &bus_priv->common_data.bus_irq_controller, true); if (rc) { CAM_ERR(CAM_ISP, "cam_irq_controller_init failed"); goto free_bus_priv; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 990807b51acd..9094f1409a66 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -3622,7 +3622,7 @@ int cam_vfe_bus_ver2_init( rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base, &ver2_hw_info->common_reg.irq_reg_info, - &bus_priv->common_data.bus_irq_controller); + &bus_priv->common_data.bus_irq_controller, true); if (rc) { CAM_ERR(CAM_ISP, "cam_irq_controller_init failed"); goto free_bus_priv; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 0ec5ba8c084f..16767270a272 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -66,6 +66,7 @@ struct cam_vfe_bus_ver3_common_data { void __iomem *mem_base; struct cam_hw_intf *hw_intf; void *bus_irq_controller; + void *rup_irq_controller; void *vfe_irq_controller; struct cam_vfe_bus_ver3_reg_offset_common *common_reg; uint32_t io_buf_update[ @@ -180,7 +181,8 @@ struct cam_vfe_bus_ver3_priv { struct list_head free_comp_grp; struct list_head used_comp_grp; - int irq_handle; + int bus_irq_handle; + int rup_irq_handle; int error_irq_handle; void *tasklet_info; }; @@ -2159,6 +2161,10 @@ static int cam_vfe_bus_ver3_start_vfe_out( return -EFAULT; } + if ((common_data->is_lite || source_group > CAM_VFE_BUS_VER3_SRC_GRP_0) + && !vfe_out->rdi_only_ctx) + goto end; + if (!common_data->rup_irq_handle[source_group]) { memset(rup_irq_reg_mask, 0, sizeof(rup_irq_reg_mask)); rup_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_REG0] |= @@ -2171,8 +2177,8 @@ static int cam_vfe_bus_ver3_start_vfe_out( common_data->rup_irq_handle[source_group] = cam_irq_controller_subscribe_irq( - common_data->bus_irq_controller, - CAM_IRQ_PRIORITY_1, + common_data->rup_irq_controller, + CAM_IRQ_PRIORITY_0, rup_irq_reg_mask, vfe_out, cam_vfe_bus_ver3_handle_rup_top_half, @@ -2222,7 +2228,7 @@ static int cam_vfe_bus_ver3_stop_vfe_out( if (common_data->rup_irq_handle[rsrc_data->source_group]) { rc = cam_irq_controller_unsubscribe_irq( - common_data->bus_irq_controller, + common_data->rup_irq_controller, common_data->rup_irq_handle[rsrc_data->source_group]); common_data->rup_irq_handle[rsrc_data->source_group] = 0; } @@ -2460,19 +2466,32 @@ static void cam_vfe_bus_ver3_print_dimensions( wm_data->en_cfg); } -static int cam_vfe_bus_ver3_handle_irq(uint32_t evt_id, +static int cam_vfe_bus_ver3_handle_bus_irq(uint32_t evt_id, struct cam_irq_th_payload *th_payload) { struct cam_vfe_bus_ver3_priv *bus_priv; int rc = 0; - bus_priv = th_payload->handler_priv; + bus_priv = th_payload->handler_priv; CAM_DBG(CAM_ISP, "Enter"); rc = cam_irq_controller_handle_irq(evt_id, bus_priv->common_data.bus_irq_controller); return (rc == IRQ_HANDLED) ? 0 : -EINVAL; } +static int cam_vfe_bus_ver3_handle_rup_irq(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_vfe_bus_ver3_priv *bus_priv; + int rc = 0; + + bus_priv = th_payload->handler_priv; + CAM_DBG(CAM_ISP, "Enter"); + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.rup_irq_controller); + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; +} + static int cam_vfe_bus_ver3_err_irq_top_half(uint32_t evt_id, struct cam_irq_th_payload *th_payload) { @@ -3539,19 +3558,35 @@ static int cam_vfe_bus_ver3_init_hw(void *hw_priv, top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift); - bus_priv->irq_handle = cam_irq_controller_subscribe_irq( + bus_priv->bus_irq_handle = cam_irq_controller_subscribe_irq( bus_priv->common_data.vfe_irq_controller, - CAM_IRQ_PRIORITY_2, + CAM_IRQ_PRIORITY_4, top_irq_reg_mask, bus_priv, - cam_vfe_bus_ver3_handle_irq, + cam_vfe_bus_ver3_handle_bus_irq, NULL, NULL, NULL); - if (bus_priv->irq_handle < 1) { - CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ"); - bus_priv->irq_handle = 0; + if (bus_priv->bus_irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS (buf_done) IRQ"); + bus_priv->bus_irq_handle = 0; + return -EFAULT; + } + + bus_priv->rup_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_ver3_handle_rup_irq, + NULL, + NULL, + NULL); + + if (bus_priv->rup_irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS (rup) IRQ"); + bus_priv->rup_irq_handle = 0; return -EFAULT; } @@ -3609,11 +3644,18 @@ static int cam_vfe_bus_ver3_deinit_hw(void *hw_priv, bus_priv->error_irq_handle = 0; } - if (bus_priv->irq_handle) { + if (bus_priv->bus_irq_handle) { rc = cam_irq_controller_unsubscribe_irq( bus_priv->common_data.vfe_irq_controller, - bus_priv->irq_handle); - bus_priv->irq_handle = 0; + bus_priv->bus_irq_handle); + bus_priv->bus_irq_handle = 0; + } + + if (bus_priv->rup_irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + bus_priv->common_data.vfe_irq_controller, + bus_priv->rup_irq_handle); + bus_priv->rup_irq_handle = 0; } spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); @@ -3698,6 +3740,7 @@ int cam_vfe_bus_ver3_init( struct cam_vfe_bus *vfe_bus_local; struct cam_vfe_bus_ver3_hw_info *ver3_hw_info = bus_hw_info; struct cam_vfe_soc_private *soc_private = NULL; + char rup_controller_name[12] = ""; CAM_DBG(CAM_ISP, "Enter"); @@ -3757,9 +3800,21 @@ int cam_vfe_bus_ver3_init( rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base, &ver3_hw_info->common_reg.irq_reg_info, - &bus_priv->common_data.bus_irq_controller); + &bus_priv->common_data.bus_irq_controller, true); if (rc) { - CAM_ERR(CAM_ISP, "cam_irq_controller_init failed"); + CAM_ERR(CAM_ISP, "Init bus_irq_controller failed"); + goto free_bus_priv; + } + + strlcat(rup_controller_name, drv_name, sizeof(rup_controller_name)); + strlcat(rup_controller_name, "_rup", sizeof(rup_controller_name)); + + rc = cam_irq_controller_init(rup_controller_name, + bus_priv->common_data.mem_base, + &ver3_hw_info->common_reg.irq_reg_info, + &bus_priv->common_data.rup_irq_controller, false); + if (rc) { + CAM_ERR(CAM_ISP, "Init rup_irq_controller failed"); goto free_bus_priv; } @@ -3812,7 +3867,7 @@ int cam_vfe_bus_ver3_init( vfe_bus_local->hw_ops.stop = cam_vfe_bus_ver3_stop_hw; vfe_bus_local->hw_ops.init = cam_vfe_bus_ver3_init_hw; vfe_bus_local->hw_ops.deinit = cam_vfe_bus_ver3_deinit_hw; - vfe_bus_local->top_half_handler = cam_vfe_bus_ver3_handle_irq; + vfe_bus_local->top_half_handler = NULL; vfe_bus_local->bottom_half_handler = NULL; vfe_bus_local->hw_ops.process_cmd = __cam_vfe_bus_ver3_process_cmd; @@ -3910,7 +3965,13 @@ int cam_vfe_bus_ver3_deinit( &bus_priv->common_data.bus_irq_controller); if (rc) CAM_ERR(CAM_ISP, - "Deinit IRQ Controller failed rc=%d", rc); + "Deinit BUS IRQ Controller failed rc=%d", rc); + + rc = cam_irq_controller_deinit( + &bus_priv->common_data.rup_irq_controller); + if (rc) + CAM_ERR(CAM_ISP, + "Deinit RUP IRQ Controller failed rc=%d", rc); mutex_destroy(&bus_priv->common_data.bus_mutex); kfree(vfe_bus_local->bus_priv); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c index 0c1179c69776..9ea8d74a35ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -287,7 +287,7 @@ static int cam_vfe_camif_lite_resource_start( if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_1, + CAM_IRQ_PRIORITY_0, err_irq_mask, camif_lite_res, cam_vfe_camif_lite_err_irq_top_half, @@ -448,13 +448,13 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( } if (irq_status0 & camif_lite_priv->reg_data->dual_pd_reg_upd_irq_mask) { - CAM_DBG(CAM_ISP, "VFE:%d CAMIF Lite hReceived REG_UPDATE_ACK", + CAM_DBG(CAM_ISP, "VFE:%d CAMIF Lite Received REG_UPDATE_ACK", evt_info.hw_idx); ret = CAM_VFE_IRQ_STATUS_SUCCESS; } if (irq_status0 & camif_lite_priv->reg_data->lite_eof_irq_mask) { - CAM_DBG(CAM_ISP, "VF:%d CAMIF Lite Received EOF", + CAM_DBG(CAM_ISP, "VFE:%d CAMIF Lite Received EOF", evt_info.hw_idx); ret = CAM_VFE_IRQ_STATUS_SUCCESS; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index e71754098e80..0fe61247055a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -33,6 +33,7 @@ struct cam_vfe_mux_camif_lite_data { void *priv; int irq_err_handle; int irq_handle; + int sof_irq_handle; void *vfe_irq_controller; struct list_head free_payload_list; spinlock_t spin_lock; @@ -312,17 +313,17 @@ skip_core_cfg: cam_io_w_mb(rsrc_data->reg_data->top_debug_cfg_en, rsrc_data->mem_base + rsrc_data->common_reg->top_debug_cfg); - err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = - rsrc_data->reg_data->error_irq_mask0; - err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = - rsrc_data->reg_data->error_irq_mask2; + if (!camif_lite_res->rdi_only_ctx) + goto subscribe_err; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = - rsrc_data->reg_data->subscribe_irq_mask1; + rsrc_data->reg_data->epoch0_irq_mask | + rsrc_data->reg_data->eof_irq_mask; if (!rsrc_data->irq_handle) { rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_0, + CAM_IRQ_PRIORITY_3, irq_mask, camif_lite_res, camif_lite_res->top_half_handler, @@ -336,16 +337,44 @@ skip_core_cfg: } } + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->sof_irq_mask; + + if (!rsrc_data->sof_irq_handle) { + rsrc_data->sof_irq_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + irq_mask, + camif_lite_res, + camif_lite_res->top_half_handler, + camif_lite_res->bottom_half_handler, + camif_lite_res->tasklet_info, + &tasklet_bh_api); + if (rsrc_data->sof_irq_handle < 1) { + CAM_ERR(CAM_ISP, "IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->sof_irq_handle = 0; + } + } + +subscribe_err: + + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->error_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = + rsrc_data->reg_data->error_irq_mask2; + if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_1, + CAM_IRQ_PRIORITY_0, err_irq_mask, camif_lite_res, cam_vfe_camif_lite_err_irq_top_half, camif_lite_res->bottom_half_handler, camif_lite_res->tasklet_info, &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); rc = -ENOMEM; @@ -653,6 +682,13 @@ static int cam_vfe_camif_lite_resource_stop( rsrc_data->irq_handle = 0; } + if (rsrc_data->sof_irq_handle > 0) { + cam_irq_controller_unsubscribe_irq( + rsrc_data->vfe_irq_controller, + rsrc_data->sof_irq_handle); + rsrc_data->sof_irq_handle = 0; + } + if (rsrc_data->irq_err_handle > 0) { cam_irq_controller_unsubscribe_irq( rsrc_data->vfe_irq_controller, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index d641d647b65a..0ed1c6ede3ce 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -436,7 +436,7 @@ static int cam_vfe_camif_resource_start( if (!rsrc_data->irq_handle) { rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_0, + CAM_IRQ_PRIORITY_1, irq_mask, camif_res, camif_res->top_half_handler, @@ -453,7 +453,7 @@ static int cam_vfe_camif_resource_start( if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_1, + CAM_IRQ_PRIORITY_0, err_irq_mask, camif_res, cam_vfe_camif_err_irq_top_half, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 7e9aa91689c3..8cf2fa9f7f93 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -34,6 +34,7 @@ struct cam_vfe_mux_camif_ver3_data { void *priv; int irq_err_handle; int irq_handle; + int sof_irq_handle; void *vfe_irq_controller; struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_CAMIF_EVT_MAX]; struct list_head free_payload_list; @@ -364,12 +365,6 @@ static int cam_vfe_camif_ver3_resource_start( memset(irq_mask, 0, sizeof(irq_mask)); rsrc_data = (struct cam_vfe_mux_camif_ver3_data *)camif_res->res_priv; - err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = - rsrc_data->reg_data->error_irq_mask0; - err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = - rsrc_data->reg_data->error_irq_mask2; - irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = - rsrc_data->reg_data->subscribe_irq_mask1; soc_private = rsrc_data->soc_info->soc_private; @@ -488,16 +483,26 @@ static int cam_vfe_camif_ver3_resource_start( rsrc_data->common_reg->diag_config); } + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->error_irq_mask0; + err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = + rsrc_data->reg_data->error_irq_mask2; + + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->epoch0_irq_mask | + rsrc_data->reg_data->eof_irq_mask; + if (!rsrc_data->irq_handle) { rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_0, + CAM_IRQ_PRIORITY_3, irq_mask, camif_res, camif_res->top_half_handler, camif_res->bottom_half_handler, camif_res->tasklet_info, &tasklet_bh_api); + if (rsrc_data->irq_handle < 1) { CAM_ERR(CAM_ISP, "IRQ handle subscribe failure"); rc = -ENOMEM; @@ -505,16 +510,38 @@ static int cam_vfe_camif_ver3_resource_start( } } + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = + rsrc_data->reg_data->sof_irq_mask; + + if (!rsrc_data->sof_irq_handle) { + rsrc_data->sof_irq_handle = cam_irq_controller_subscribe_irq( + rsrc_data->vfe_irq_controller, + CAM_IRQ_PRIORITY_1, + irq_mask, + camif_res, + camif_res->top_half_handler, + camif_res->bottom_half_handler, + camif_res->tasklet_info, + &tasklet_bh_api); + + if (rsrc_data->sof_irq_handle < 1) { + CAM_ERR(CAM_ISP, "SOF IRQ handle subscribe failure"); + rc = -ENOMEM; + rsrc_data->sof_irq_handle = 0; + } + } + if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_1, + CAM_IRQ_PRIORITY_0, err_irq_mask, camif_res, cam_vfe_camif_ver3_err_irq_top_half, camif_res->bottom_half_handler, camif_res->tasklet_info, &tasklet_bh_api); + if (rsrc_data->irq_err_handle < 1) { CAM_ERR(CAM_ISP, "Error IRQ handle subscribe failure"); rc = -ENOMEM; @@ -645,6 +672,13 @@ static int cam_vfe_camif_ver3_resource_stop( camif_priv->irq_handle = 0; } + if (camif_priv->sof_irq_handle) { + cam_irq_controller_unsubscribe_irq( + camif_priv->vfe_irq_controller, + camif_priv->sof_irq_handle); + camif_priv->sof_irq_handle = 0; + } + if (camif_priv->irq_err_handle) { cam_irq_controller_unsubscribe_irq( camif_priv->vfe_irq_controller, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index 3cc92551b79c..381de6b48fe9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -243,7 +243,7 @@ static int cam_vfe_rdi_resource_start( if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_1, + CAM_IRQ_PRIORITY_0, err_irq_mask, rdi_res, cam_vfe_rdi_err_irq_top_half, @@ -263,7 +263,7 @@ static int cam_vfe_rdi_resource_start( if (!rsrc_data->irq_handle) { rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, - CAM_IRQ_PRIORITY_0, + CAM_IRQ_PRIORITY_1, irq_mask, rdi_res, rdi_res->top_half_handler, From e8ceba2d024cda1b635a75e3c793aac1f1311373 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 12 Aug 2019 16:59:32 -0700 Subject: [PATCH 056/790] msm: camera: isp: Send shutter notification Shutter notification must be sent when moving request to free list if it was not sent out earlier due to missed EPOCH IRQ or delayed EPOCH IRQ handling. Change-Id: I9b3b039827bea24814fbea34e61abfc938f6bf2d Signed-off-by: Venkat Chinta Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/cam_isp_context.c | 119 ++++++++++++++++-------------- 1 file changed, 62 insertions(+), 57 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 638478cb56e1..9dfd4fb363f4 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -387,6 +387,63 @@ static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data) return ts; } +static void __cam_isp_ctx_send_sof_boot_timestamp( + struct cam_isp_context *ctx_isp, uint64_t request_id, + uint32_t sof_event_status) +{ + struct cam_req_mgr_message req_msg; + + req_msg.session_hdl = ctx_isp->base->session_hdl; + req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; + req_msg.u.frame_msg.request_id = request_id; + req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp; + req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; + req_msg.u.frame_msg.sof_status = sof_event_status; + + CAM_DBG(CAM_ISP, + "request id:%lld frame number:%lld boot time stamp:0x%llx", + request_id, ctx_isp->frame_id, + ctx_isp->boot_timestamp); + + if (cam_req_mgr_notify_message(&req_msg, + V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS, + V4L_EVENT_CAM_REQ_MGR_EVENT)) + CAM_ERR(CAM_ISP, + "Error in notifying the boot time for req id:%lld", + request_id); +} + + +static void __cam_isp_ctx_send_sof_timestamp( + struct cam_isp_context *ctx_isp, uint64_t request_id, + uint32_t sof_event_status) +{ + struct cam_req_mgr_message req_msg; + + req_msg.session_hdl = ctx_isp->base->session_hdl; + req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; + req_msg.u.frame_msg.request_id = request_id; + req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val; + req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; + req_msg.u.frame_msg.sof_status = sof_event_status; + + CAM_DBG(CAM_ISP, + "request id:%lld frame number:%lld SOF time stamp:0x%llx", + request_id, ctx_isp->frame_id, + ctx_isp->sof_timestamp_val); + CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status); + + if (cam_req_mgr_notify_message(&req_msg, + V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT)) + CAM_ERR(CAM_ISP, + "Error in notifying the sof time for req id:%lld", + request_id); + + __cam_isp_ctx_send_sof_boot_timestamp(ctx_isp, + request_id, sof_event_status); + +} + static void __cam_isp_ctx_handle_buf_done_fail_log( uint64_t request_id, struct cam_isp_ctx_req *req_isp) { @@ -537,6 +594,11 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( "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 { + if (ctx_isp->reported_req_id < buf_done_req_id) { + ctx_isp->reported_req_id = buf_done_req_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, + buf_done_req_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); @@ -551,63 +613,6 @@ end: return rc; } -static void __cam_isp_ctx_send_sof_boot_timestamp( - struct cam_isp_context *ctx_isp, uint64_t request_id, - uint32_t sof_event_status) -{ - struct cam_req_mgr_message req_msg; - - req_msg.session_hdl = ctx_isp->base->session_hdl; - req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; - req_msg.u.frame_msg.request_id = request_id; - req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp; - req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; - req_msg.u.frame_msg.sof_status = sof_event_status; - - CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld boot time stamp:0x%llx", - request_id, ctx_isp->frame_id, - ctx_isp->boot_timestamp); - - if (cam_req_mgr_notify_message(&req_msg, - V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS, - V4L_EVENT_CAM_REQ_MGR_EVENT)) - CAM_ERR(CAM_ISP, - "Error in notifying the boot time for req id:%lld", - request_id); -} - - -static void __cam_isp_ctx_send_sof_timestamp( - struct cam_isp_context *ctx_isp, uint64_t request_id, - uint32_t sof_event_status) -{ - struct cam_req_mgr_message req_msg; - - req_msg.session_hdl = ctx_isp->base->session_hdl; - req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; - req_msg.u.frame_msg.request_id = request_id; - req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val; - req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; - req_msg.u.frame_msg.sof_status = sof_event_status; - - CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld SOF time stamp:0x%llx", - request_id, ctx_isp->frame_id, - ctx_isp->sof_timestamp_val); - CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status); - - if (cam_req_mgr_notify_message(&req_msg, - V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT)) - CAM_ERR(CAM_ISP, - "Error in notifying the sof time for req id:%lld", - request_id); - - __cam_isp_ctx_send_sof_boot_timestamp(ctx_isp, - request_id, sof_event_status); - -} - static int __cam_isp_ctx_reg_upd_in_epoch_state( struct cam_isp_context *ctx_isp, void *evt_data) { From d7a8426091e2f3fed27803ac95e09d3cac6eb20d Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Sat, 10 Aug 2019 15:47:26 -0700 Subject: [PATCH 057/790] msm: camera: utils: Use pr_info for camera logs Use pr_info for camera warning and error logs to avoid sending to console (assuming info logs are disabled to console). All camera warning and error logs are anyway tagged with CAM_WARN and CAM_ERR, so using pr_info doesn't cause any information loss. Change-Id: Ib23fbad47c1dce4c45e3413d775303d681a1ff86 Signed-off-by: Pavan Kumar Chilamkurthi Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_utils/cam_debug_util.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 55f316b41da4..0491e6a214ac 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -75,7 +75,7 @@ const char *cam_get_module_name(unsigned int module_id); * @args : Arguments which needs to be print in log */ #define CAM_ERR(__module, fmt, args...) \ - pr_err("CAM_ERR: %s: %s: %d " fmt "\n", \ + pr_info("CAM_ERR: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, __LINE__, ##args) /* * CAM_WARN @@ -86,7 +86,7 @@ const char *cam_get_module_name(unsigned int module_id); * @args : Arguments which needs to be print in log */ #define CAM_WARN(__module, fmt, args...) \ - pr_warn("CAM_WARN: %s: %s: %d " fmt "\n", \ + pr_info("CAM_WARN: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, __LINE__, ##args) /* * CAM_INFO @@ -128,7 +128,7 @@ const char *cam_get_module_name(unsigned int module_id); * @brief : This Macro will print error print logs with ratelimit */ #define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ - pr_err_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ + pr_info_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, __LINE__, ##args) /* * CAM_WARN_RATE_LIMIT @@ -139,7 +139,7 @@ const char *cam_get_module_name(unsigned int module_id); * @args : Arguments which needs to be print in log */ #define CAM_WARN_RATE_LIMIT(__module, fmt, args...) \ - pr_warn_ratelimited("CAM_WARN: %s: %s: %d " fmt "\n", \ + pr_info_ratelimited("CAM_WARN: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, __LINE__, ##args) /* @@ -158,7 +158,7 @@ const char *cam_get_module_name(unsigned int module_id); (interval * HZ), \ burst); \ if (__ratelimit(&_rs)) \ - pr_warn( \ + pr_info( \ "CAM_WARN: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, \ __LINE__, ##args); \ @@ -202,7 +202,7 @@ const char *cam_get_module_name(unsigned int module_id); (interval * HZ), \ burst); \ if (__ratelimit(&_rs)) \ - pr_err( \ + pr_info( \ "CAM_ERR: %s: %s: %d " fmt "\n", \ cam_get_module_name(__module), __func__, \ __LINE__, ##args); \ From 6bf14f8fd417a345a9d488af9d358e28a841dac9 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Sat, 10 Aug 2019 02:56:50 -0700 Subject: [PATCH 058/790] msm: camera: isp: Look at next request for BUF_DONE event If the resource for which BUF_DONE event has come is already signalled in the oldest request, this BUF_DONE could be for the next request in the list. This can happen if the IRQ handling for BUF_DONE is delayed and by the time it is handled if the resources for the next request are already signalled along with other pending resources for the oldest request, we might handle resources which corresponds to next request first. If we do not look into next request and thus if we ignore these BUF_DONEs, we will never be done with the next request. Change-Id: I1b20aff0a68172bc8794d2c37f088ba2539d173d Signed-off-by: Pavan Kumar Chilamkurthi Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/cam_isp_context.c | 168 +++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 38 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9dfd4fb363f4..c51b8e4a2e5e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -456,48 +456,49 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( return; } - CAM_ERR(CAM_ISP, + CAM_WARN(CAM_ISP, "Prev Req[%lld] : num_out=%d, num_acked=%d, bubble : report=%d, detected=%d", request_id, req_isp->num_fence_map_out, req_isp->num_acked, req_isp->bubble_report, req_isp->bubble_detected); - CAM_ERR(CAM_ISP, + CAM_WARN(CAM_ISP, "Resource Handles that fail to generate buf_done in prev frame"); for (i = 0; i < req_isp->num_fence_map_out; i++) { - if (req_isp->fence_map_out[i].sync_id != -1) - CAM_ERR(CAM_ISP, + if (req_isp->fence_map_out[i].sync_id != -1) { + CAM_WARN(CAM_ISP, "Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]", __cam_isp_resource_handle_id_to_type( req_isp->fence_map_out[i].resource_handle), req_isp->fence_map_out[i].resource_handle, req_isp->fence_map_out[i].sync_id); + } } } -static int __cam_isp_ctx_handle_buf_done_in_activated_state( +static int __cam_isp_ctx_handle_buf_done_for_request( struct cam_isp_context *ctx_isp, + struct cam_ctx_request *req, struct cam_isp_hw_done_event_data *done, - uint32_t bubble_state) + uint32_t bubble_state, + struct cam_isp_hw_done_event_data *done_next_req) { int rc = 0; int i, j; - struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; uint64_t buf_done_req_id; - if (list_empty(&ctx->active_req_list)) { - CAM_DBG(CAM_ISP, "Buf done with no active request!"); - goto end; - } - - CAM_DBG(CAM_ISP, "Enter with bubble_state %d", bubble_state); - - req = list_first_entry(&ctx->active_req_list, - struct cam_ctx_request, list); - trace_cam_buf_done("ISP", ctx, req); req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", + bubble_state, req_isp->bubble_detected); + + if (done_next_req) { + done_next_req->num_handles = 0; + done_next_req->timestamp = done->timestamp; + } + for (i = 0; i < done->num_handles; i++) { for (j = 0; j < req_isp->num_fence_map_out; j++) { if (done->resource_handle[i] == @@ -514,8 +515,18 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( } if (req_isp->fence_map_out[j].sync_id == -1) { - __cam_isp_ctx_handle_buf_done_fail_log( - req->request_id, req_isp); + CAM_WARN(CAM_ISP, + "Duplicate BUF_DONE for req %lld : i=%d, j=%d, res=%s", + req->request_id, i, j, + __cam_isp_resource_handle_id_to_type( + done->resource_handle[i])); + + if (done_next_req) { + done_next_req->resource_handle + [done_next_req->num_handles++] = + done->resource_handle[i]; + } + continue; } @@ -609,7 +620,66 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); -end: + + return rc; +} + +static int __cam_isp_ctx_handle_buf_done_in_activated_state( + struct cam_isp_context *ctx_isp, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state) +{ + int rc = 0; + struct cam_ctx_request *req; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_done_event_data done_next_req; + + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_ISP, "Buf done with no active request"); + return 0; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + + rc = __cam_isp_ctx_handle_buf_done_for_request(ctx_isp, req, done, + bubble_state, &done_next_req); + + if (done_next_req.num_handles) { + struct cam_isp_hw_done_event_data unhandled_res; + struct cam_ctx_request *next_req = list_next_entry(req, list); + + if (next_req) { + /* + * Few resource handles are already signalled in the + * current request, lets check if there is another + * request waiting for these resources. This can + * happen if handling some of next request's buf done + * events are happening first before handling current + * request's remaining buf dones due to IRQ scheduling. + * Lets check only one more request as we will have + * maximum of 2 requests in active_list at any time. + */ + + CAM_WARN(CAM_ISP, + "Unhandled buf done resources for req %lld, trying next request %lld in active_list", + req->request_id, next_req->request_id); + + __cam_isp_ctx_handle_buf_done_for_request(ctx_isp, + next_req, &done_next_req, + bubble_state, &unhandled_res); + + if (unhandled_res.num_handles == 0) + CAM_INFO(CAM_ISP, + "BUF Done event handed for next request %lld", + next_req->request_id); + else + CAM_ERR(CAM_ISP, + "BUF Done not handled for next request %lld", + next_req->request_id); + } + } + return rc; } @@ -625,7 +695,7 @@ static int __cam_isp_ctx_reg_upd_in_epoch_state( return 0; } -static int __cam_isp_ctx_reg_upd_in_activated_state( +static int __cam_isp_ctx_reg_upd_in_applied_state( struct cam_isp_context *ctx_isp, void *evt_data) { int rc = 0; @@ -888,10 +958,11 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; notify.error = CRM_KMD_ERR_BUBBLE; + CAM_WARN(CAM_ISP, + "Notify CRM about Bubble req %lld frame %lld, ctx %u", + req->request_id, ctx_isp->frame_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); 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; } @@ -1038,11 +1109,11 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; notify.error = CRM_KMD_ERR_BUBBLE; - ctx->ctx_crm_intf->notify_err(¬ify); - atomic_set(&ctx_isp->process_bubble, 1); - CAM_DBG(CAM_REQ, + CAM_WARN(CAM_REQ, "Notify CRM about Bubble req_id %llu frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); + ctx->ctx_crm_intf->notify_err(¬ify); + atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; } @@ -1105,7 +1176,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, struct cam_ctx_request *req_temp; struct cam_isp_ctx_req *req_isp = NULL; struct cam_isp_ctx_req *req_isp_to_report = NULL; - struct cam_req_mgr_error_notify notify; + struct cam_req_mgr_error_notify notify = {}; uint64_t error_request_id; struct cam_hw_fence_map_entry *fence_map_out = NULL; struct cam_req_mgr_message req_msg; @@ -1295,8 +1366,10 @@ end: notify.error = CRM_KMD_ERR_FATAL; } - CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld ctx %u", - error_request_id, ctx_isp->frame_id, ctx->ctx_id); + CAM_WARN(CAM_ISP, + "Notify CRM: req %lld, frame %lld ctx %u, error %d", + error_request_id, ctx_isp->frame_id, ctx->ctx_id, + notify.error); ctx->ctx_crm_intf->notify_err(¬ify); @@ -1582,7 +1655,7 @@ static struct cam_isp_ctx_irq_ops .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_reg_upd_in_applied_state, __cam_isp_ctx_epoch_in_applied, __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_applied, @@ -1615,7 +1688,7 @@ static struct cam_isp_ctx_irq_ops .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_reg_upd_in_applied_state, __cam_isp_ctx_epoch_in_bubble_applied, NULL, __cam_isp_ctx_buf_done_in_bubble_applied, @@ -1688,7 +1761,7 @@ static struct cam_isp_ctx_irq_ops .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_reg_upd_in_applied_state, __cam_isp_ctx_epoch_in_bubble_applied, NULL, __cam_isp_ctx_buf_done_in_bubble_applied, @@ -1738,7 +1811,7 @@ 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, + CAM_INFO(CAM_ISP, "Processing bubble cannot apply Request Id %llu", apply->request_id); rc = -EAGAIN; @@ -1767,7 +1840,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state( req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (ctx_isp->active_req_cnt >= 2) { - CAM_ERR(CAM_ISP, + CAM_WARN(CAM_ISP, "Reject apply request (id %lld) due to congestion(cnt = %d) ctx %u", req->request_id, ctx_isp->active_req_cnt, @@ -1836,6 +1909,10 @@ static int __cam_isp_ctx_apply_req_in_sof( CAM_ISP_CTX_ACTIVATED_APPLIED); CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated); + if (rc) + CAM_DBG(CAM_ISP, "Apply failed in state %d, rc %d", + ctx_isp->substate_activated, rc); + return rc; } @@ -1852,6 +1929,10 @@ static int __cam_isp_ctx_apply_req_in_epoch( CAM_ISP_CTX_ACTIVATED_APPLIED); CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated); + if (rc) + CAM_DBG(CAM_ISP, "Apply failed in state %d, rc %d", + ctx_isp->substate_activated, rc); + return rc; } @@ -1868,6 +1949,10 @@ static int __cam_isp_ctx_apply_req_in_bubble( CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED); CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated); + if (rc) + CAM_DBG(CAM_ISP, "Apply failed in state %d, rc %d", + ctx_isp->substate_activated, rc); + return rc; } @@ -2244,9 +2329,12 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; notify.error = CRM_KMD_ERR_BUBBLE; + CAM_WARN(CAM_ISP, + "Notify CRM about Bubble req %lld frame %lld ctx %u", + req->request_id, + ctx_isp->frame_id, + ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); - CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld", - ctx_isp->frame_id); } else { req_isp->bubble_report = 0; } @@ -2507,6 +2595,10 @@ static int __cam_isp_ctx_rdi_only_apply_req_top_state( CAM_ISP_CTX_ACTIVATED_APPLIED); CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated); + if (rc) + CAM_ERR(CAM_ISP, "Apply failed in state %d, rc %d", + ctx_isp->substate_activated, rc); + return rc; } @@ -3740,8 +3832,8 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx, if (rc) CAM_ERR_RATE_LIMIT(CAM_ISP, - "Apply failed in active substate %d", - ctx_isp->substate_activated); + "Apply failed in active substate %d rc %d", + ctx_isp->substate_activated, rc); return rc; } From c4acb6a0256aa4a6b04725854c51ad2f054941e6 Mon Sep 17 00:00:00 2001 From: Suresh Vankadara Date: Tue, 13 Aug 2019 04:49:19 +0530 Subject: [PATCH 059/790] msm: camera: isp: schedule tasklet with priority To handle tasklet delays in hadling ISP inetrrupts use priority tasklet scheduling. Change-Id: I11961f51092c3f6876d2375595d9e5004f64c656 Signed-off-by: Suresh Vankadara Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c index 5145dadded28..a8ff7ff01e11 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c @@ -210,7 +210,7 @@ void cam_tasklet_enqueue_cmd( list_add_tail(&tasklet_cmd->list, &tasklet->used_cmd_list); spin_unlock_irqrestore(&tasklet->tasklet_lock, flags); - tasklet_schedule(&tasklet->tasklet); + tasklet_hi_schedule(&tasklet->tasklet); } int cam_tasklet_init( From 9712baaea9096f4e45be8aeb691e9a651354d6aa Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 24 Jul 2019 10:12:08 -0700 Subject: [PATCH 060/790] msm: camera: reqmgr: Update log for shutdown Add warn log to indicate shutdown has occurred. Also decrement the open req count after successfully applying a request. Change-Id: I1b420dff52e016f52e19c5572824e4ed6f53744b Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_req_mgr/cam_req_mgr_core.c | 4 +--- drivers/cam_req_mgr/cam_req_mgr_dev.c | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 3147eeab0a7b..287db0c46d2f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -625,9 +625,6 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, *failed_dev = dev; break; } - - if (pd == link->max_delay) - link->open_req_cnt--; } trace_cam_req_mgr_apply_request(link, &apply_req, dev); } @@ -1260,6 +1257,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, &idx, reset_step + 1, in_q->num_slots); __cam_req_mgr_reset_req_slot(link, idx); + link->open_req_cnt--; } } diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 718942552bc7..a30dc69a80d0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -151,6 +151,8 @@ static int cam_req_mgr_close(struct file *filep) struct v4l2_fh *vfh = filep->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); + CAM_WARN(CAM_CRM, + "release invoked associated userspace process has died"); mutex_lock(&g_dev.cam_lock); if (g_dev.open_cnt <= 0) { From 6ceb84f1b7356d926aaffe309a6de51154b750ae Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 22 Jul 2019 10:36:56 -0700 Subject: [PATCH 061/790] msm: camera: icp: log cleanup and header update This change cleans up a few logs and updates the HFI headers in line with the current FW. CRs-Fixed: 2513094 Change-Id: I8853ac3711ad3bf36ce59f6860082fa29dca0bf6 Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/fw_inc/hfi_session_defs.h | 20 ++++++++++++++--- drivers/cam_icp/fw_inc/hfi_sys_defs.h | 15 +++++++++++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 22 +++++++++++++------ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_session_defs.h b/drivers/cam_icp/fw_inc/hfi_session_defs.h index e50b5d147a2f..9ba7803d4f44 100644 --- a/drivers/cam_icp/fw_inc/hfi_session_defs.h +++ b/drivers/cam_icp/fw_inc/hfi_session_defs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HFI_SESSION_DEFS_H @@ -272,10 +272,20 @@ enum hfi_ipe_io_images { IPE_OUTPUT_IMAGE_DS4_REF, IPE_OUTPUT_IMAGE_DS16_REF, IPE_OUTPUT_IMAGE_DS64_REF, + IPE_INPUT2_IMAGE_FULL, + IPE_INPUT2_IMAGE_DSX, + IPE_INPUT_OUTPUT_SCRATCHBUFFER, IPE_INPUT_IMAGE_FIRST = IPE_INPUT_IMAGE_FULL, IPE_INPUT_IMAGE_LAST = IPE_INPUT_IMAGE_DS64_REF, + IPE_INPUT_IMAGE_REF_FIRST = IPE_INPUT_IMAGE_FULL_REF, + IPE_INPUT_IMAGE_REF_LAST = IPE_INPUT_IMAGE_DS64_REF, IPE_OUTPUT_IMAGE_FIRST = IPE_OUTPUT_IMAGE_DISPLAY, IPE_OUTPUT_IMAGE_LAST = IPE_OUTPUT_IMAGE_DS64_REF, + IPE_OUTPUT_IMAGE_REF_FIRST = IPE_OUTPUT_IMAGE_FULL_REF, + IPE_OUTPUT_IMAGE_REF_LAST = IPE_OUTPUT_IMAGE_DS64_REF, + IPE_INPUT2_IMAGE_FIRST = IPE_INPUT2_IMAGE_FULL, + IPE_INPUT2_IMAGE_LAST = IPE_INPUT2_IMAGE_DSX, + IPE_INPUT_OUTPUT_IMAGE_LAST = IPE_INPUT_OUTPUT_SCRATCHBUFFER, IPE_IO_IMAGES_MAX }; @@ -300,7 +310,6 @@ struct frame_buffer { } __packed; struct bps_frame_process_data { - struct frame_buffer buffers[BPS_IO_IMAGES_MAX]; uint32_t max_num_cores; uint32_t target_time; uint32_t ubwc_stats_buffer_addr; @@ -311,6 +320,7 @@ struct bps_frame_process_data { uint32_t strip_lib_out_addr; uint32_t cdm_prog_addr; uint32_t request_id; + struct frame_buffer buffers[BPS_IO_IMAGES_MAX]; }; enum hfi_ipe_image_format { @@ -465,7 +475,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; @@ -492,6 +501,11 @@ struct ipe_frame_process_data { uint32_t cdm_tf_ds4; uint32_t cdm_tf_ds16; uint32_t cdm_tf_ds64; + uint32_t cdm_dsx_dc4; + uint32_t cdm_dsx_dc16; + uint32_t cdm_dsz_dc64; + uint32_t cdm_mfhdr_full_pass; + uint32_t cdm_mfhdr_dcx; uint32_t request_id; uint32_t frames_in_batch; struct frame_set framesets[MAX_HFR_GROUP]; diff --git a/drivers/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/cam_icp/fw_inc/hfi_sys_defs.h index ddd9bf15c6aa..905b85a53633 100644 --- a/drivers/cam_icp/fw_inc/hfi_sys_defs.h +++ b/drivers/cam_icp/fw_inc/hfi_sys_defs.h @@ -67,6 +67,21 @@ #define HFI_CMD_SYS_PING (HFI_CMD_COMMON_START + 0x5) #define HFI_CMD_SYS_RESET (HFI_CMD_COMMON_START + 0x6) +/* General Frame process errors */ +#define CAMERAICP_SUCCESS 0 +#define CAMERAICP_EFAILED 1 +#define CAMERAICP_ENOMEMORY 2 +#define CAMERAICP_EBADSTATE 3 +#define CAMERAICP_EBADPARM 4 +#define CAMERAICP_EBADITEM 5 +#define CAMERAICP_EINVALIDFORMAT 6 +#define CAMERAICP_EUNSUPPORTED 7 +#define CAMERAICP_EOUTOFBOUND 8 +#define CAMERAICP_ETIMEDOUT 9 +#define CAMERAICP_EABORTED 10 +#define CAMERAICP_EHWVIOLATION 11 +#define CAMERAICP_ECDMERROR 12 + /* Core level commands */ /* IPE/BPS core Commands */ #define HFI_CMD_IPE_BPS_COMMON_START \ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 4da5c65412dc..c1ec110ea1d5 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1943,10 +1943,20 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) } idx = i; - if (flag == ICP_FRAME_PROCESS_FAILURE) - CAM_ERR(CAM_ICP, "Done with error: ctx_id %d req %llu dev %d", - ctx_data->ctx_id, request_id, - ctx_data->icp_dev_acquire_info->dev_type); + if (flag == ICP_FRAME_PROCESS_FAILURE) { + if (ioconfig_ack->err_type == CAMERAICP_EABORTED) + CAM_WARN(CAM_ICP, + "ctx_id %d req %llu dev %d has been aborted[flushed]", + ctx_data->ctx_id, request_id, + ctx_data->icp_dev_acquire_info->dev_type); + else + CAM_ERR(CAM_ICP, + "Done with error: %u on ctx_id %d dev %d for req %llu", + ioconfig_ack->err_type, + ctx_data->ctx_id, + ctx_data->icp_dev_acquire_info->dev_type, + request_id); + } buf_data.request_id = hfi_frame_process->request_id[idx]; ctx_data->ctxt_event_cb(ctx_data->context_priv, flag, &buf_data); @@ -1975,9 +1985,7 @@ static int cam_icp_mgr_process_msg_frame_process(uint32_t *msg_ptr) } ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; - if (ioconfig_ack->err_type != HFI_ERR_SYS_NONE) { - CAM_ERR(CAM_ICP, "failed with error : %u", - ioconfig_ack->err_type); + if (ioconfig_ack->err_type != CAMERAICP_SUCCESS) { cam_icp_mgr_handle_frame_process(msg_ptr, ICP_FRAME_PROCESS_FAILURE); return -EIO; From 65a6c306f9259ace0cfbf0bac02e81fcb8f168c1 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 21 Aug 2019 12:17:53 -0700 Subject: [PATCH 062/790] msm: camera: smmu: Dump ctx bank info in case of mapping failure When mapping fails for a given context bank, dump all the existing mappings for that context bank to understand the memory usage for that bank. CRs-Fixed: 2513106 Change-Id: Ia17b086dd76378da55cae509255309610820f53f Signed-off-by: Karthik Anantha Ram --- drivers/cam_smmu/cam_smmu_api.c | 90 ++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 478a00657f3b..55962a8f3e7a 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,9 @@ struct cam_context_bank_info { int cb_count; int secure_count; int pf_count; + + size_t io_mapping_size; + size_t shared_mapping_size; }; struct cam_iommu_cb_set { @@ -140,6 +144,8 @@ struct cam_iommu_cb_set { struct mutex payload_list_lock; struct list_head payload_list; u32 non_fatal_fault; + struct dentry *dentry; + bool cb_dump_enable; }; static const struct of_device_id msm_cam_smmu_dt_match[] = { @@ -237,6 +243,8 @@ static void cam_smmu_clean_user_buffer_list(int idx); static void cam_smmu_clean_kernel_buffer_list(int idx); +static void cam_smmu_dump_cb_info(int idx); + static void cam_smmu_print_user_list(int idx); static void cam_smmu_print_kernel_list(int idx); @@ -287,6 +295,50 @@ static void cam_smmu_page_fault_work(struct work_struct *work) kfree(payload); } +static void cam_smmu_dump_cb_info(int idx) +{ + struct cam_dma_buff_info *mapping, *mapping_temp; + size_t shared_reg_len = 0, io_reg_len = 0; + size_t shared_free_len = 0, io_free_len = 0; + uint32_t i = 0; + struct cam_context_bank_info *cb_info = + &iommu_cb_set.cb_info[idx]; + + if (cb_info->shared_support) { + shared_reg_len = cb_info->shared_info.iova_len; + shared_free_len = shared_reg_len - cb_info->shared_mapping_size; + } + + if (cb_info->io_support) { + io_reg_len = cb_info->io_info.iova_len; + io_free_len = io_reg_len - cb_info->io_mapping_size; + } + + CAM_ERR(CAM_SMMU, + "********** Context bank dump for %s **********", + cb_info->name); + CAM_ERR(CAM_SMMU, + "Usage: shared_usage=%u io_usage=%u shared_free=%u io_free=%u", + (unsigned int)cb_info->shared_mapping_size, + (unsigned int)cb_info->io_mapping_size, + (unsigned int)shared_free_len, + (unsigned int)io_free_len); + + if (iommu_cb_set.cb_dump_enable) { + list_for_each_entry_safe(mapping, mapping_temp, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + i++; + CAM_ERR(CAM_SMMU, + "%u. ion_fd=%d start=0x%x end=0x%x len=%u region=%d", + i, mapping->ion_fd, (void *)mapping->paddr, + ((uint64_t)mapping->paddr + + (uint64_t)mapping->len), + (unsigned int)mapping->len, + mapping->region_id); + } + } +} + static void cam_smmu_print_user_list(int idx) { struct cam_dma_buff_info *mapping; @@ -1712,6 +1764,7 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, *paddr_ptr = iova; *len_ptr = size; } + iommu_cb_set.cb_info[idx].shared_mapping_size += *len_ptr; } else if (region_id == CAM_SMMU_REGION_IO) { attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; @@ -1724,6 +1777,7 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, *paddr_ptr = sg_dma_address(table->sgl); *len_ptr = (size_t)buf->size; + iommu_cb_set.cb_info[idx].io_mapping_size += *len_ptr; } else { CAM_ERR(CAM_SMMU, "Error: Wrong region id passed"); rc = -EINVAL; @@ -1896,8 +1950,11 @@ static int cam_smmu_unmap_buf_and_remove_from_list( if (rc) CAM_ERR(CAM_SMMU, "IOVA free failed"); + iommu_cb_set.cb_info[idx].shared_mapping_size -= + mapping_info->len; } else if (mapping_info->region_id == CAM_SMMU_REGION_IO) { mapping_info->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; + iommu_cb_set.cb_info[idx].io_mapping_size -= mapping_info->len; } dma_buf_unmap_attachment(mapping_info->attach, @@ -2702,10 +2759,12 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, rc = cam_smmu_map_buffer_and_add_to_list(idx, ion_fd, dma_dir, paddr_ptr, len_ptr, region_id); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_SMMU, "mapping or add list fail, idx=%d, fd=%d, region=%d, rc=%d", idx, ion_fd, region_id, rc); + cam_smmu_dump_cb_info(idx); + } get_addr_end: mutex_unlock(&iommu_cb_set.cb_info[idx].lock); @@ -3498,6 +3557,31 @@ cb_init_fail: return rc; } +static int cam_smmu_create_debug_fs(void) +{ + iommu_cb_set.dentry = debugfs_create_dir("camera_smmu", + NULL); + + if (!iommu_cb_set.dentry) { + CAM_ERR(CAM_SMMU, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_bool("cb_dump_enable", + 0644, + iommu_cb_set.dentry, + &iommu_cb_set.cb_dump_enable)) { + CAM_ERR(CAM_SMMU, + "failed to create dump_enable_debug"); + goto err; + } + + return 0; +err: + debugfs_remove_recursive(iommu_cb_set.dentry); + return -ENOMEM; +} + static int cam_smmu_probe(struct platform_device *pdev) { int rc = 0; @@ -3547,6 +3631,7 @@ static int cam_smmu_probe(struct platform_device *pdev) INIT_LIST_HEAD(&iommu_cb_set.payload_list); } + cam_smmu_create_debug_fs(); return rc; } @@ -3563,6 +3648,9 @@ static int cam_smmu_remove(struct platform_device *pdev) if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-cam-smmu")) cam_smmu_release_cb(pdev); + + debugfs_remove_recursive(iommu_cb_set.dentry); + iommu_cb_set.dentry = NULL; return 0; } From b582eeddce1df6916d68c903521a7b9807287058 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Thu, 15 Aug 2019 15:39:05 -0700 Subject: [PATCH 063/790] msm: camera: isp: Add atomic flag instead of wait in handle error Errors in isp are handled in soft irq context, putting a wait for cdm done is not allowed. Add atomic flag for checking status of cdm and check it before reg dump to determine the request for which register values can be dumped in command buffer.This is only applicable to reg dump on error. CRs-Fixed: 2510557 Change-Id: If4bfedd1a62078392721c2ea0958da82087f5b26 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 25 ++++++++++++--------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 3 +++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 96a12a707dd3..8614292c54a7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2078,6 +2078,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { complete_all(&ctx->config_done_complete); + atomic_set(&ctx->cdm_done, 1); CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", handle, userdata, status, cookie, ctx->ctx_index); @@ -3063,6 +3064,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, ctx->applied_req_id = cfg->request_id; CAM_DBG(CAM_ISP, "Submit to CDM"); + atomic_set(&ctx->cdm_done, 0); rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); if (rc) { CAM_ERR(CAM_ISP, "Failed to apply the configs"); @@ -5371,15 +5373,9 @@ static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, return 0; } - rc = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies(30)); - if (rc <= 0) { - CAM_ERR(CAM_ISP, - "config done completion timeout rc=%d ctx_index %d", - rc, ctx->ctx_index); - rc = 0; - } + if (!atomic_read(&ctx->cdm_done)) + CAM_WARN_RATE_LIMIT(CAM_ISP, + "Reg dump values might be from more than one request"); for (i = 0; i < ctx->num_reg_dump_buf; i++) { CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %d req_type: %d", @@ -5468,8 +5464,17 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) if (ctx->last_dump_flush_req_id == ctx->applied_req_id) return 0; - ctx->last_dump_flush_req_id = ctx->applied_req_id; + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(30)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, + "config done completion timeout, Reg dump will be unreliable rc=%d ctx_index %d", + rc, ctx->ctx_index); + rc = 0; + } + ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH); if (rc) { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 698b0c60ca9b..09ba8bd9c43e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -122,6 +122,8 @@ struct cam_ife_hw_mgr_debug { * @eof_cnt eof count value per core, used for dual VFE * @overflow_pending flat to specify the overflow is pending for the * context + * @cdm_done flag to indicate cdm has finished writing shadow + * registers * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete * @reg_dump_buf_desc: cmd buffer descriptors for reg dump @@ -164,6 +166,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t epoch_cnt[CAM_IFE_HW_NUM_MAX]; uint32_t eof_cnt[CAM_IFE_HW_NUM_MAX]; atomic_t overflow_pending; + atomic_t cdm_done; uint32_t is_rdi_only_context; struct completion config_done_complete; struct cam_cmd_buf_desc reg_dump_buf_desc[ From 7c65c0fa21c681db863595662cdabde72b52a86a Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 18 Jul 2019 11:29:37 -0700 Subject: [PATCH 064/790] msm: camera: common: Clean shutdown and page fault sequence Avoid unnecessary logging during shutdown and pagefault in camera drivers. CRs-Fixed: 2500721 Change-Id: I2519d45da134306f906186dc25705fc1f84b1972 Signed-off-by: Karthik Anantha Ram --- drivers/cam_core/cam_context.c | 30 +++++++++++-------- drivers/cam_req_mgr/cam_req_mgr_core.c | 17 +++++++---- drivers/cam_req_mgr/cam_req_mgr_core.h | 7 ++++- drivers/cam_req_mgr/cam_req_mgr_dev.c | 2 +- drivers/cam_req_mgr/cam_req_mgr_util.c | 4 +-- .../cam_sensor/cam_sensor_core.c | 10 +++++-- 6 files changed, 45 insertions(+), 25 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index d2ec399e2895..4d4d4fc5c068 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -54,12 +54,15 @@ int cam_context_shutdown(struct cam_context *ctx) rc = -EINVAL; } - rc = cam_destroy_device_hdl(ctx->dev_hdl); - if (rc) - CAM_ERR(CAM_CORE, "destroy device hdl failed for node %s", - ctx->dev_name); - else - ctx->dev_hdl = -1; + if (ctx->dev_hdl != -1) { + rc = cam_destroy_device_hdl(ctx->dev_hdl); + if (rc) + CAM_ERR(CAM_CORE, + "destroy device hdl failed for node %s", + ctx->dev_name); + else + ctx->dev_hdl = -1; + } return rc; } @@ -237,12 +240,15 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, return -EINVAL; } - if (ctx->state_machine[ctx->state].pagefault_ops) { - rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova, - buf_info); - } else { - CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", - ctx->dev_hdl, ctx->state); + if ((ctx->state > CAM_CTX_AVAILABLE) && + (ctx->state < CAM_CTX_STATE_MAX)) { + if (ctx->state_machine[ctx->state].pagefault_ops) { + rc = ctx->state_machine[ctx->state].pagefault_ops( + ctx, iova, buf_info); + } else { + CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", + ctx->dev_hdl, ctx->state); + } } return rc; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 287db0c46d2f..6a8e5fed6e67 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -42,6 +42,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->initial_sync_req = -1; link->in_msync_mode = false; link->retry_cnt = 0; + link->is_shutdown = false; } void cam_req_mgr_handle_core_shutdown(void) @@ -55,7 +56,7 @@ void cam_req_mgr_handle_core_shutdown(void) &g_crm_core_dev->session_head, entry) { ses_info.session_hdl = session->session_hdl; - cam_req_mgr_destroy_session(&ses_info); + cam_req_mgr_destroy_session(&ses_info, true); } } } @@ -2707,10 +2708,12 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) link->state = CAM_CRM_LINK_STATE_IDLE; spin_unlock_bh(&link->link_state_spin_lock); - rc = __cam_req_mgr_disconnect_link(link); - if (rc) - CAM_ERR(CAM_CORE, - "Unlink for all devices was not successful"); + if (!link->is_shutdown) { + rc = __cam_req_mgr_disconnect_link(link); + if (rc) + CAM_ERR(CAM_CORE, + "Unlink for all devices was not successful"); + } mutex_lock(&link->lock); /* Destroy timer of link */ @@ -2738,7 +2741,8 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) } int cam_req_mgr_destroy_session( - struct cam_req_mgr_session_info *ses_info) + struct cam_req_mgr_session_info *ses_info, + bool is_shutdown) { int rc; int i; @@ -2771,6 +2775,7 @@ int cam_req_mgr_destroy_session( continue; /* Ignore return value since session is going away */ + link->is_shutdown = is_shutdown; __cam_req_mgr_unlink(link); __cam_req_mgr_free_link(link); } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index aeede7a87166..3837c1cd8061 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -332,6 +332,8 @@ struct cam_req_mgr_connected_device { * other link * @retry_cnt : Counter that tracks number of attempts to apply * the same req + * @is_shutdown : Flag to indicate if link needs to be disconnected + * as part of shutdown. */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -359,6 +361,7 @@ struct cam_req_mgr_core_link { bool in_msync_mode; int64_t initial_sync_req; uint32_t retry_cnt; + bool is_shutdown; }; /** @@ -411,11 +414,13 @@ int cam_req_mgr_create_session(struct cam_req_mgr_session_info *ses_info); * cam_req_mgr_destroy_session() * @brief : destroy session * @ses_info : session handle info, input param + * @is_shutdown: To indicate if devices on link need to be disconnected. * * Called as part of session destroy * return success/failure */ -int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info); +int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info, + bool is_shutdown); /** * cam_req_mgr_link() diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index a30dc69a80d0..d567dec91519 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -258,7 +258,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EFAULT; } - rc = cam_req_mgr_destroy_session(&ses_info); + rc = cam_req_mgr_destroy_session(&ses_info, false); } break; diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index f833f667de97..ce83e64363f5 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__ @@ -94,7 +94,7 @@ int cam_req_mgr_util_free_hdls(void) for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) { if (hdl_tbl->hdl[i].state == HDL_ACTIVE) { - CAM_ERR(CAM_CRM, "Dev handle = %x session_handle = %x", + CAM_WARN(CAM_CRM, "Dev handle = %x session_handle = %x", hdl_tbl->hdl[i].hdl_value, hdl_tbl->hdl[i].session_hdl); hdl_tbl->hdl[i].state = HDL_FREE; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 680cf4f302bc..2fa447dbace4 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -565,9 +565,13 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *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, "dhdl already destroyed: rc = %d", rc); + if (s_ctrl->bridge_intf.device_hdl != -1) { + rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl); + if (rc < 0) + 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; From 03e52e70d6d24311f960bd9830eb24634b402214 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 2 Aug 2019 11:06:22 -0700 Subject: [PATCH 065/790] msm: camera: isp: Dump previous acq ctx info on acq failure In case acquire hw fails, dump the previously acquired streams to infer the reason for the failure. CRs-Fixed: 2512474 Change-Id: I3ee2b85e0843ab4a605625950dc60366c0b50713 Signed-off-by: Karthik Anantha Ram --- drivers/cam_core/cam_context.c | 25 +++ drivers/cam_core/cam_context.h | 16 ++ drivers/cam_core/cam_context_utils.c | 29 +++ drivers/cam_core/cam_context_utils.h | 3 +- drivers/cam_core/cam_hw_mgr_intf.h | 16 ++ drivers/cam_core/cam_node.c | 16 +- drivers/cam_isp/cam_isp_context.c | 22 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 226 +++++++++++++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 3 + 9 files changed, 345 insertions(+), 11 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index d2ec399e2895..5e42f02dd9ad 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -493,6 +493,31 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } +int cam_context_handle_info_dump(void *context, + enum cam_context_dump_id id) +{ + int rc = 0; + struct cam_context *ctx = (struct cam_context *)context; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].dumpinfo_ops) + rc = ctx->state_machine[ctx->state].dumpinfo_ops(ctx, + id); + mutex_unlock(&ctx->ctx_mutex); + + if (rc) + CAM_WARN(CAM_CORE, + "Dump for id %u failed on ctx_id %u name %s state %d", + id, ctx->ctx_id, ctx->dev_name, ctx->state); + + return rc; +} + int cam_context_init(struct cam_context *ctx, const char *dev_name, uint64_t dev_id, diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 1583dd06df3f..854ea0067a27 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -138,6 +138,8 @@ struct cam_ctx_crm_ops { * @crm_ops: CRM to context interface function table * @irq_ops: Hardware event handle function * @pagefault_ops: Function to be called on page fault + * @dumpinfo_ops: Function to be invoked for dumping any + * context info * */ struct cam_ctx_ops { @@ -145,6 +147,7 @@ struct cam_ctx_ops { struct cam_ctx_crm_ops crm_ops; cam_hw_event_cb_func irq_ops; cam_hw_pagefault_cb_func pagefault_ops; + cam_ctx_info_dump_cb_func dumpinfo_ops; }; /** @@ -406,6 +409,19 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +/** + * cam_context_handle_info_dump() + * + * @brief: Handle any dump info for the context + * + * @ctx: Object pointer for cam_context + * @id: To indicate which info pertaining + * to that ctx needs to be dumped + * + */ +int cam_context_handle_info_dump(void *context, + enum cam_context_dump_id id); + /** * cam_context_deinit() * diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 34dc7b81d454..5ec9c6cdc7b1 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -1016,3 +1016,32 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, end: return rc; } + +int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx) +{ + int rc = 0; + struct cam_hw_cmd_args cmd_args; + + if (!ctx) { + CAM_ERR(CAM_CTXT, "Invalid input params"); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + if (ctx->hw_mgr_intf->hw_cmd) { + cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_ACQ_INFO; + ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &cmd_args); + } + +end: + return rc; +} diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h index c3483327ba81..087fdbf36544 100644 --- a/drivers/cam_core/cam_context_utils.h +++ b/drivers/cam_core/cam_context_utils.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_UTILS_H_ @@ -29,5 +29,6 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, struct cam_packet *packet, unsigned long iova, uint32_t buf_info, bool *mem_found); +int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx); #endif /* _CAM_CONTEXT_UTILS_H_ */ diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index b7b6ae1bb6b7..462b30119b50 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -24,6 +24,17 @@ /* Maximum reg dump cmd buffer entries in a context */ #define CAM_REG_DUMP_MAX_BUF_ENTRIES 10 +/** + * enum cam_context_dump_id - + * context dump type + * + */ +enum cam_context_dump_id { + CAM_CTX_DUMP_TYPE_NONE, + CAM_CTX_DUMP_ACQ_INFO, + CAM_CTX_DUMP_TYPE_MAX, +}; + /* hardware event callback function type */ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, void *evt_data); @@ -32,6 +43,10 @@ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, typedef int (*cam_hw_pagefault_cb_func)(void *context, unsigned long iova, uint32_t buf_info); +/* ctx dump callback function type */ +typedef int (*cam_ctx_info_dump_cb_func)(void *context, + enum cam_context_dump_id dump_id); + /** * struct cam_hw_update_entry - Entry for hardware config * @@ -276,6 +291,7 @@ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_DUMP_PF_INFO, CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH, CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR, + CAM_HW_MGR_CMD_DUMP_ACQ_INFO, }; /** diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 9c4c6f242336..4fefa2f35db3 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -122,6 +122,16 @@ err: return rc; } +static void __cam_node_handle_acquired_hw_dump( + struct cam_node *node) +{ + int i; + + for (i = 0; i < node->ctx_size; i++) + cam_context_handle_info_dump(&(node->ctx_list[i]), + CAM_CTX_DUMP_ACQ_INFO); +} + static int __cam_node_handle_acquire_hw_v1(struct cam_node *node, struct cam_acquire_hw_cmd_v1 *acquire) { @@ -158,6 +168,7 @@ static int __cam_node_handle_acquire_hw_v1(struct cam_node *node, if (rc) { CAM_ERR(CAM_CORE, "Acquire device failed for node %s", node->name); + __cam_node_handle_acquired_hw_dump(node); return rc; } @@ -197,6 +208,7 @@ static int __cam_node_handle_acquire_hw_v2(struct cam_node *node, if (rc) { CAM_ERR(CAM_CORE, "Acquire device failed for node %s", node->name); + __cam_node_handle_acquired_hw_dump(node); return rc; } @@ -734,7 +746,6 @@ 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"); } else if (api_version == 2) { rc = __cam_node_handle_acquire_hw_v2(node, acquire_ptr); if (rc) { @@ -742,7 +753,6 @@ 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, @@ -849,8 +859,6 @@ 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/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index c51b8e4a2e5e..46dfeb1915ca 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -139,6 +139,24 @@ static void __cam_isp_ctx_dump_state_monitor_array( } } +static int cam_isp_context_info_dump(void *context, + enum cam_context_dump_id id) +{ + struct cam_context *ctx = (struct cam_context *)context; + + switch (id) { + case CAM_CTX_DUMP_ACQ_INFO: { + cam_context_dump_hw_acq_info(ctx); + break; + } + default: + CAM_DBG(CAM_ISP, "DUMP id not valid %u", id); + break; + } + + return 0; +} + static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) { int i = 0, rc = 0; @@ -3365,7 +3383,6 @@ end: return rc; } - static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx, void *args) { @@ -3904,6 +3921,7 @@ static struct cam_ctx_ops }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, + .dumpinfo_ops = cam_isp_context_info_dump, }, /* Ready */ { @@ -3919,6 +3937,7 @@ static struct cam_ctx_ops }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, + .dumpinfo_ops = cam_isp_context_info_dump, }, /* Activated */ { @@ -3936,6 +3955,7 @@ static struct cam_ctx_ops }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_active_request, + .dumpinfo_ops = cam_isp_context_info_dump, }, }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 96a12a707dd3..b076583cada2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -471,6 +471,206 @@ static int cam_ife_hw_mgr_free_hw_res( return 0; } +static const char *cam_ife_hw_mgr_get_res_state( + uint32_t res_state) +{ + switch (res_state) { + case CAM_ISP_RESOURCE_STATE_UNAVAILABLE: + return "UNAVAILABLE"; + case CAM_ISP_RESOURCE_STATE_AVAILABLE: + return "AVAILABLE"; + case CAM_ISP_RESOURCE_STATE_RESERVED: + return "RESERVED"; + case CAM_ISP_RESOURCE_STATE_INIT_HW: + return "HW INIT DONE"; + case CAM_ISP_RESOURCE_STATE_STREAMING: + return "STREAMING"; + default: + return "INVALID STATE"; + } +} + +static const char *cam_ife_hw_mgr_get_csid_res_id( + uint32_t res_id) +{ + switch (res_id) { + case CAM_IFE_PIX_PATH_RES_RDI_0: + return "RDI_0"; + case CAM_IFE_PIX_PATH_RES_RDI_1: + return "RDI_1"; + case CAM_IFE_PIX_PATH_RES_RDI_2: + return "RDI_2"; + case CAM_IFE_PIX_PATH_RES_RDI_3: + return "RDI_3"; + case CAM_IFE_PIX_PATH_RES_IPP: + return "IPP"; + case CAM_IFE_PIX_PATH_RES_PPP: + return "PPP"; + default: + return "INVALID"; + } +} + +static const char *cam_ife_hw_mgr_get_src_res_id( + uint32_t res_id) +{ + switch (res_id) { + case CAM_ISP_HW_VFE_IN_CAMIF: + return "CAMIF"; + case CAM_ISP_HW_VFE_IN_TESTGEN: + return "TESTGEN"; + case CAM_ISP_HW_VFE_IN_RD: + return "BUS_RD"; + case CAM_ISP_HW_VFE_IN_RDI0: + return "RDI_0"; + case CAM_ISP_HW_VFE_IN_RDI1: + return "RDI_1"; + case CAM_ISP_HW_VFE_IN_RDI2: + return "RDI_2"; + case CAM_ISP_HW_VFE_IN_RDI3: + return "RDI_3"; + case CAM_ISP_HW_VFE_IN_PDLIB: + return "PDLIB"; + case CAM_ISP_HW_VFE_IN_LCR: + return "LCR"; + default: + return "INVALID"; + } +} + +static void cam_ife_hw_mgr_dump_src_acq_info( + struct cam_ife_hw_mgr_ctx *hwr_mgr_ctx, + uint32_t num_pix_port, uint32_t num_rdi_port) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res_temp = NULL; + struct cam_isp_resource_node *hw_res = NULL; + int i = 0; + + CAM_INFO(CAM_ISP, + "Acquired HW for ctx: %u with pix_port: %u rdi_port: %u", + hwr_mgr_ctx->ctx_index, num_pix_port, num_rdi_port); + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &hwr_mgr_ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) + CAM_INFO(CAM_ISP, + "IFE src split_id: %d res_id: %s hw_idx: %u state: %s", + i, + cam_ife_hw_mgr_get_src_res_id( + hw_res->res_id), + hw_res->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_state + (hw_res->res_state)); + } + } +} + +static void cam_ife_hw_mgr_dump_acq_data( + struct cam_ife_hw_mgr_ctx *hwr_mgr_ctx) +{ + struct cam_ife_hw_mgr_res *hw_mgr_res = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res_temp = NULL; + struct cam_isp_resource_node *hw_res = NULL; + struct timespec64 *ts = NULL; + uint64_t ms, tmp; + int i = 0, j = 0; + + ts = &hwr_mgr_ctx->ts; + tmp = ts->tv_sec; + ms = (ts->tv_nsec) / 1000000; + + CAM_INFO(CAM_ISP, + "**** %llu:%llu:%llu.%llu ctx_idx: %u rdi_only: %s is_dual: %s acquired ****", + (tmp / 3600) % 24, (tmp / 60) % 60, tmp % 60, ms, + hwr_mgr_ctx->ctx_index, + (hwr_mgr_ctx->is_rdi_only_context ? "true" : "false"), + (hwr_mgr_ctx->is_dual ? "true" : "false")); + + /* Iterate over CID resources */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &hwr_mgr_ctx->res_list_ife_cid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) { + CAM_INFO(CAM_ISP, + "CID split_id: %d res_id: %u hw_idx: %u state: %s", + i, hw_res->res_id, + hw_res->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_state + (hw_res->res_state)); + } + } + } + + /* Iterate over CSID resources */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &hwr_mgr_ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) + CAM_INFO(CAM_ISP, + "CSID split_id: %d res_id: %s hw_idx: %u state: %s", + i, + cam_ife_hw_mgr_get_csid_res_id( + hw_res->res_id), + hw_res->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_state + (hw_res->res_state)); + } + } + + /* Iterate over IFE IN resources */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &hwr_mgr_ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) + CAM_INFO(CAM_ISP, + "IFE src split_id: %d res_id: %s hw_idx: %u state: %s", + i, + cam_ife_hw_mgr_get_src_res_id( + hw_res->res_id), + hw_res->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_state + (hw_res->res_state)); + } + } + + /* Iterate over IFE RD resources */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &hwr_mgr_ctx->res_list_ife_in_rd, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) + CAM_INFO(CAM_ISP, + "IFE src_rd split_id: %d res_id: %s hw_idx: %u state: %s", + i, + cam_ife_hw_mgr_get_src_res_id( + hw_res->res_id), + hw_res->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_state + (hw_res->res_state)); + } + } + + /* Iterate over IFE OUT resources */ + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { + hw_mgr_res = &hwr_mgr_ctx->res_list_ife_out[i]; + hw_res = hw_mgr_res->hw_res[j]; + if (hw_res && hw_res->hw_intf) + CAM_INFO(CAM_ISP, + "IFE out split_id: %d res_id: 0x%x hw_idx: %u state: %s", + i, hw_res->res_id, + hw_res->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_state + (hw_res->res_state)); + } + } +} + static int cam_ife_mgr_csid_stop_hw( struct cam_ife_hw_mgr_ctx *ctx, struct list_head *stop_list, uint32_t base_idx, uint32_t stop_cmd) @@ -2400,8 +2600,11 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) if (rc) { CAM_ERR(CAM_ISP, "can not acquire resource"); + cam_ife_hw_mgr_dump_src_acq_info(ife_ctx, + total_pix_port, total_rdi_port); goto free_mem; } + kfree(in_port->data); kfree(in_port); in_port = NULL; @@ -2426,9 +2629,13 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->valid_acquired_hw = acquire_hw_info->num_inputs; - cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); + getnstimeofday64(&ife_ctx->ts); + CAM_INFO(CAM_ISP, + "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", + total_pix_port, total_rdi_port, + ife_ctx->is_dual, ife_ctx->ctx_index); - CAM_DBG(CAM_ISP, "Exit...(success)"); + cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); return 0; free_mem: @@ -2661,9 +2868,12 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->ctxt_to_hw_map = ife_ctx; ife_ctx->ctx_in_use = 1; - cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); + CAM_INFO(CAM_ISP, + "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", + total_pix_port, total_rdi_port, + ife_ctx->is_dual, ife_ctx->ctx_index); - CAM_DBG(CAM_ISP, "Exit...(success)"); + cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); return 0; free_res: @@ -3722,8 +3932,11 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->eof_cnt[i] = 0; ctx->epoch_cnt[i] = 0; } - CAM_DBG(CAM_ISP, "Exit...ctx id:%d", + + CAM_INFO(CAM_ISP, "Release HW success ctx id: %u", ctx->ctx_index); + + memset(&ctx->ts, 0, sizeof(struct timespec64)); cam_ife_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx); return rc; } @@ -5494,6 +5707,9 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } + break; + case CAM_HW_MGR_CMD_DUMP_ACQ_INFO: + cam_ife_hw_mgr_dump_acq_data(ctx); break; default: CAM_ERR(CAM_ISP, "Invalid cmd"); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 698b0c60ca9b..40ec7262122a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -7,6 +7,7 @@ #define _CAM_IFE_HW_MGR_H_ #include +#include #include "cam_isp_hw_mgr.h" #include "cam_vfe_hw_intf.h" #include "cam_ife_csid_hw_intf.h" @@ -132,6 +133,7 @@ struct cam_ife_hw_mgr_debug { * @init_done indicate whether init hw is done * @is_fe_enable indicate whether fetch engine\read path is enabled * @is_dual indicate whether context is in dual VFE mode + * @ts captured timestamp when the ctx is acquired */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -175,6 +177,7 @@ struct cam_ife_hw_mgr_ctx { bool init_done; bool is_fe_enable; bool is_dual; + struct timespec64 ts; }; /** From dd89a305c172e11f16a4d8c86715c0c84c496667 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 23 Aug 2019 15:53:08 -0700 Subject: [PATCH 066/790] Camera: Snap for drop 08/22/2019 Mainline 146 Change-Id: Ib81b69adb65dbbfc69798e06945e939a1ecf56ef Signed-off-by: Mukund Madhusudan Atre From 0a5b5c49616353d30dd318752d602ec2f2dc3a24 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 23 Aug 2019 15:58:55 -0700 Subject: [PATCH 067/790] Camera: Snap for drop 08/23/2019 Mainline 147 Change-Id: Ieac77fd6ce6f42d10e55b7154e1fb1056f70b0f8 Signed-off-by: Mukund Madhusudan Atre From f86cd9899de1e67c88330dfa79228b208a3e3a2a Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 26 Aug 2019 13:39:17 -0700 Subject: [PATCH 068/790] Camera: Snap for drop 08/26/2019 Mainline 148 Change-Id: I386b0e3158e27b975adae77146c6b6fafbf933c9 Signed-off-by: Mukund Madhusudan Atre From 95460b8f2e424a1c62438fa2e8f69a2d25c42d55 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 20 Aug 2019 13:22:42 +0800 Subject: [PATCH 069/790] msm: camera: isp: Fix RDI only early PCR issue RDI only context also need to get req from wait_req_list afte received RUP event in early PCR case. CRs-Fixed: 2511798 Change-Id: If2e8da36cf83dee1c348dd0d6c6ea916061a376e Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 46dfeb1915ca..b1ad05f45d2c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3518,11 +3518,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, */ list_del_init(&req->list); - if (req_isp->num_fence_map_out) { + if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) { + list_add_tail(&req->list, &ctx->wait_req_list); + } else { list_add_tail(&req->list, &ctx->active_req_list); ctx_isp->active_req_cnt++; - } else { - list_add_tail(&req->list, &ctx->wait_req_list); } start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; From 598dfb05afa5de9af8447a823e6a7482957c85c5 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 29 Aug 2019 11:07:04 +0800 Subject: [PATCH 070/790] msm: camera: isp: Correct the active req cnt assignment order We need to reset the active req cnt before assigning new value. Also move the log behind the active req cnt assignment. CRs-Fixed: 2517421 Change-Id: I38f418f79f5f1adcb8b29bc870f904cd1f925bfc Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index b1ad05f45d2c..4144bfc62a64 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -989,11 +989,11 @@ 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), 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); + 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); if (req->request_id > ctx_isp->reported_req_id) { request_id = req->request_id; @@ -1140,11 +1140,11 @@ 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) ctx %u", - req->request_id, ctx_isp->active_req_cnt); - ctx_isp->active_req_cnt++; list_del_init(&req->list); list_add_tail(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; + CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d) ctx %u", + req->request_id, ctx_isp->active_req_cnt); if (!req_isp->bubble_report) { if (req->request_id > ctx_isp->reported_req_id) { @@ -2361,9 +2361,9 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( * Always move the request to active list. Let buf done * function handles the rest. */ - ctx_isp->active_req_cnt++; list_del_init(&req->list); list_add_tail(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)", req->request_id, ctx_isp->active_req_cnt); @@ -3510,21 +3510,6 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } - /* - * In case of CSID TPG we might receive SOF and RUP IRQs - * before hw_mgr_intf->hw_start has returned. So move - * req out of pending list before hw_start and add it - * back to pending list if hw_start fails. - */ - list_del_init(&req->list); - - if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) { - list_add_tail(&req->list, &ctx->wait_req_list); - } else { - list_add_tail(&req->list, &ctx->active_req_list); - ctx_isp->active_req_cnt++; - } - start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.hw_config.request_id = req->request_id; start_isp.hw_config.hw_update_entries = req_isp->cfg; @@ -3544,6 +3529,21 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, atomic64_set(&ctx_isp->state_monitor_head, -1); + /* + * In case of CSID TPG we might receive SOF and RUP IRQs + * before hw_mgr_intf->hw_start has returned. So move + * req out of pending list before hw_start and add it + * back to pending list if hw_start fails. + */ + list_del_init(&req->list); + + if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) { + list_add_tail(&req->list, &ctx->wait_req_list); + } else { + list_add_tail(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; + } + /* * Only place to change state before calling the hw due to * hardware tasklet has higher priority that can cause the From 7e0fea6d1cb7423dd6e2d3de3c333e91f2f2f658 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 18 Jun 2019 18:57:01 -0700 Subject: [PATCH 071/790] msm: camera: ife: Add dentry to enable req dump This change adds a dentry to enable req dump in the case of hardware errors. CRs-Fixed: 2513939 Change-Id: I0ae5d6c658964bf33d0e4c1775413aaa9201f7a1 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 13 +++++++++++-- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 89b96ca65f4c..c9f950ca921a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6038,8 +6038,9 @@ static int cam_ife_hw_mgr_handle_hw_err( if (g_ife_hw_mgr.debug_cfg.enable_recovery) error_event_data.recovery_enabled = true; - else - error_event_data.recovery_enabled = false; + + if (g_ife_hw_mgr.debug_cfg.enable_req_dump) + error_event_data.enable_req_dump = true; rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, core_idx, &recovery_data); @@ -6502,6 +6503,14 @@ static int cam_ife_hw_mgr_debug_register(void) goto err; } + if (!debugfs_create_bool("enable_req_dump", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, + &g_ife_hw_mgr.debug_cfg.enable_req_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_req_dump"); + goto err; + } + if (!debugfs_create_file("ife_camif_debug", 0644, g_ife_hw_mgr.debug_cfg.dentry, NULL, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index ffd0a3ec090f..05ee264e93c9 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -90,7 +90,7 @@ struct cam_ife_hw_mgr_debug { uint64_t csid_debug; uint32_t enable_recovery; uint32_t camif_debug; - uint32_t enable_req_dump; + bool enable_req_dump; }; /** From 7642380776261641126aa327495349b763c98193 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 26 Aug 2019 16:21:55 -0700 Subject: [PATCH 072/790] msm: camera: isp: Add support for custom CSID This change adds support for custom csid HW and programming of user defined interfaces (UDI) in custom csid block. CRs-Fixed: 2515662 Change-Id: I4b226b3a3787fbc3e56eb285e9a4dbd6d62edefa Signed-off-by: Karthik Anantha Ram --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 689 ++++++++++++++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 76 +- .../isp_hw/ife_csid_hw/cam_ife_csid_dev.c | 2 +- .../isp_hw/ife_csid_hw/cam_ife_csid_soc.c | 11 +- .../isp_hw/ife_csid_hw/cam_ife_csid_soc.h | 5 +- .../isp_hw/include/cam_ife_csid_hw_intf.h | 5 + 6 files changed, 737 insertions(+), 51 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index c48d320d0945..ec41759cf50c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -445,6 +445,11 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + for (i = 0 ; i < csid_reg->cmn_reg->num_udis; i++) + cam_io_w_mb(csid_reg->cmn_reg->udi_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); @@ -571,7 +576,10 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, val |= CSID_PATH_INFO_RST_DONE; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_irq_mask_addr); - } else { + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { id = res->res_id; if (!csid_reg->rdi_reg[id]) { CAM_ERR(CAM_ISP, "CSID:%d RDI res not supported :%d", @@ -591,6 +599,31 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, val |= CSID_PATH_INFO_RST_DONE; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + if (!csid_reg->udi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d UDI res not supported :%d", + csid_hw->hw_intf->hw_idx, + res->res_id); + return -EINVAL; + } + + reset_strb_addr = + csid_reg->udi_reg[id]->csid_udi_rst_strobes_addr; + complete = + &csid_hw->csid_udin_complete[id]; + + /* Enable path reset done interrupt */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_irq_mask_addr); + val |= CSID_PATH_INFO_RST_DONE; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_irq_mask_addr); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id %u", res->res_id); + return -EINVAL; } init_completion(complete); @@ -623,10 +656,10 @@ end: } -static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, +int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, struct cam_csid_hw_reserve_resource_args *cid_reserv) { - int rc = 0, i; + int rc = 0, i, id; struct cam_ife_csid_cid_data *cid_data; uint32_t camera_hw_version; uint32_t valid_vc_dt; @@ -819,6 +852,20 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, goto end; } break; + case CAM_IFE_PIX_PATH_RES_UDI_0: + case CAM_IFE_PIX_PATH_RES_UDI_1: + case CAM_IFE_PIX_PATH_RES_UDI_2: + id = cid_reserv->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + if (csid_hw->udi_res[id].res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d UDI:%d resource not available", + csid_hw->hw_intf->hw_idx, + cid_reserv->res_id); + rc = -EINVAL; + goto end; + } + break; default: CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path", csid_hw->hw_intf->hw_idx); @@ -894,11 +941,10 @@ end: return rc; } - -static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, +int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, struct cam_csid_hw_reserve_resource_args *reserve) { - int rc = 0, i; + int rc = 0, i, id; struct cam_ife_csid_path_cfg *path_data; struct cam_isp_resource_node *res; @@ -998,6 +1044,28 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, res->res_id); } + break; + case CAM_IFE_PIX_PATH_RES_UDI_0: + case CAM_IFE_PIX_PATH_RES_UDI_1: + case CAM_IFE_PIX_PATH_RES_UDI_2: + id = reserve->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + if (csid_hw->udi_res[id].res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d UDI:%d resource not available %d", + csid_hw->hw_intf->hw_idx, + reserve->res_id, + csid_hw->udi_res[id].res_state); + rc = -EINVAL; + goto end; + } else { + res = &csid_hw->udi_res[id]; + CAM_DBG(CAM_ISP, + "CSID:%d UDI resource:%d acquire success", + csid_hw->hw_intf->hw_idx, + res->res_id); + } + break; default: CAM_ERR(CAM_ISP, "CSID:%d Invalid res id:%d", @@ -1020,6 +1088,7 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->drop_enable = reserve->drop_enable; path_data->horizontal_bin = reserve->in_port->horizontal_bin; path_data->qcfa_bin = reserve->in_port->qcfa_bin; + path_data->num_bytes_out = reserve->in_port->num_bytes_out; CAM_DBG(CAM_ISP, "Res id: %d height:%d line_start %d line_stop %d crop_en %d", @@ -1155,6 +1224,11 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) + cam_io_w_mb(csid_reg->cmn_reg->udi_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); @@ -2185,6 +2259,207 @@ static int cam_ife_csid_init_config_rdi_path( return rc; } +static int cam_ife_csid_init_config_udi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + struct cam_ife_csid_path_cfg *path_data; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t path_format = 0, plain_fmt = 0, val = 0, val1, id; + uint32_t format_measure_addr; + + path_data = (struct cam_ife_csid_path_cfg *)res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + if ((id >= CAM_IFE_CSID_UDI_MAX) || (!csid_reg->udi_reg[id])) { + CAM_ERR(CAM_ISP, "CSID:%d UDI:%d is not supported on HW", + csid_hw->hw_intf->hw_idx, id); + return -EINVAL; + } + + rc = cam_ife_csid_get_format_rdi(path_data->in_format, + path_data->out_format, &path_format, &plain_fmt); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to get format in_format: %u out_format: %u rc: %d", + path_data->in_format, path_data->out_format, rc); + return rc; + } + + /* if path decode format is payload only then UDI crop is not applied */ + if (path_format == 0xF) + path_data->crop_enable = false; + + /* + * UDI path config and enable the time stamp capture + * Enable the measurement blocks + */ + val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | + (path_format << csid_reg->cmn_reg->fmt_shift_val) | + (plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_h_en_shift_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_v_en_shift_val) | + (1 << 2) | 3; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_cfg0_addr); + + /* select the post irq sub sample strobe for time stamp capture */ + val1 = CSID_TIMESTAMP_STB_POST_IRQ; + + /* select the num bytes out per cycle */ + val1 |= (path_data->num_bytes_out << + csid_reg->cmn_reg->num_bytes_out_shift_val); + + cam_io_w_mb(val1, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_cfg1_addr); + + /* Enable Error Detection */ + if (csid_reg->udi_reg[id]->overflow_ctrl_en) { + val = csid_reg->udi_reg[id]->overflow_ctrl_en; + /* Overflow ctrl mode: 2 -> Detect overflow */ + val |= 0x8; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_err_recovery_cfg0_addr); + } + + /* set frame drop pattern to 0 and period to 1 */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_frm_drop_period_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_frm_drop_pattern_addr); + /* set IRQ sum sabmple */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_irq_subsample_period_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_irq_subsample_pattern_addr); + + /* set pixel drop pattern to 0 and period to 1 */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_rpp_pix_drop_pattern_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_rpp_pix_drop_period_addr); + /* set line drop pattern to 0 and period to 1 */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_rpp_line_drop_pattern_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_rpp_line_drop_period_addr); + + /* Configure the halt mode */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_ctrl_addr); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_cfg0_addr); + val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) + val |= csid_reg->cmn_reg->format_measure_en_val; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_cfg0_addr); + + format_measure_addr = + csid_reg->udi_reg[id]->csid_udi_format_measure_cfg0_addr; + + /* Enable the HBI/VBI counter */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + format_measure_addr); + val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + format_measure_addr); + } + + /* configure the rx packet capture based on csid debug set */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val = ((1 << + csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; + + return rc; +} + +static int cam_ife_csid_deinit_udi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + uint32_t id, val, format_measure_addr; + 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; + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + + if ((res->res_id < CAM_IFE_PIX_PATH_RES_UDI_0) || + (res->res_id > CAM_IFE_PIX_PATH_RES_UDI_2) || + (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) || + (!csid_reg->udi_reg[id])) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, + res->res_state); + return -EINVAL; + } + + /* Disable Error Recovery */ + if (csid_reg->udi_reg[id]->overflow_ctrl_en) { + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_err_recovery_cfg0_addr); + } + + format_measure_addr = + csid_reg->udi_reg[id]->csid_udi_format_measure_cfg0_addr; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_cfg0_addr); + val &= ~csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_cfg0_addr); + + /* Disable the HBI/VBI counter */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + format_measure_addr); + val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + format_measure_addr); + } + + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + static int cam_ife_csid_deinit_rdi_path( struct cam_ife_csid_hw *csid_hw, struct cam_isp_resource_node *res) @@ -2284,6 +2559,56 @@ static int cam_ife_csid_enable_rdi_path( return 0; } +static int cam_ife_csid_enable_udi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t id, val; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + + if ((res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) || + (res->res_id > CAM_IFE_PIX_PATH_RES_UDI_2) || + (res->res_id < CAM_IFE_PIX_PATH_RES_UDI_0) || + (!csid_reg->udi_reg[id])) { + CAM_ERR(CAM_ISP, + "CSID:%d invalid res type:%d res_id:%d state%d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + return -EINVAL; + } + + /*resume at frame boundary */ + cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_ctrl_addr); + + /* Enable the required UDI interrupts */ + val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW; + + if (csid_reg->udi_reg[id]->ccif_violation_en) + val |= CSID_PATH_ERROR_CCIF_VIOLATION; + + if (csid_reg->udi_reg[id]->overflow_ctrl_en) + val |= CSID_PATH_OVERFLOW_RECOVERY; + + 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) + val |= CSID_PATH_INFO_INPUT_EOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_irq_mask_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} static int cam_ife_csid_disable_rdi_path( struct cam_ife_csid_hw *csid_hw, @@ -2347,11 +2672,74 @@ static int cam_ife_csid_disable_rdi_path( return rc; } +static int cam_ife_csid_disable_udi_path( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res, + enum cam_ife_csid_halt_cmd stop_cmd) +{ + int rc = 0; + uint32_t id, val = 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; + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + + if ((res->res_id > CAM_IFE_PIX_PATH_RES_UDI_2) || + (res->res_id < CAM_IFE_PIX_PATH_RES_UDI_0) || + (!csid_reg->udi_reg[id])) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d Res:%d already in stopped state:%d", + csid_hw->hw_intf->hw_idx, + res->res_id, res->res_state); + return rc; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d Res:%d Invalid res_state%d", + csid_hw->hw_intf->hw_idx, res->res_id, + res->res_state); + return -EINVAL; + } + + if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY && + stop_cmd != CAM_CSID_HALT_IMMEDIATELY) { + CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d", + csid_hw->hw_intf->hw_idx, stop_cmd); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_id); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_irq_mask_addr); + + /* Halt the UDI path */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_ctrl_addr); + val &= ~0x3; + val |= stop_cmd; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[id]->csid_udi_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; + int rc = 0, id; 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; @@ -2370,9 +2758,22 @@ static int cam_ife_csid_poll_stop_status( } else if (res_id == CAM_IFE_PIX_PATH_RES_PPP) { csid_status_addr = csid_reg->ppp_reg->csid_pxl_status_addr; - } else { + } else if (res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { csid_status_addr = csid_reg->rdi_reg[res_id]->csid_rdi_status_addr; + } else if (res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + id = res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + csid_status_addr = + csid_reg->udi_reg[id]->csid_udi_status_addr; + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", res_id); + rc = -EINVAL; + break; } CAM_DBG(CAM_ISP, "start polling CSID:%d res_id:%d", @@ -2400,8 +2801,10 @@ static int cam_ife_csid_get_hbi_vbi( struct cam_isp_resource_node *res) { uint32_t hbi, vbi; + int32_t id; const struct cam_ife_csid_reg_offset *csid_reg; const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + const struct cam_ife_csid_udi_reg_offset *udi_reg; struct cam_hw_soc_info *soc_info; csid_reg = csid_hw->csid_info->csid_reg; @@ -2432,12 +2835,27 @@ static int cam_ife_csid_get_hbi_vbi( csid_reg->ppp_reg->csid_pxl_format_measure1_addr); vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_format_measure2_addr); - } else { + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { rdi_reg = csid_reg->rdi_reg[res->res_id]; hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + rdi_reg->csid_rdi_format_measure1_addr); vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + rdi_reg->csid_rdi_format_measure2_addr); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + udi_reg = csid_reg->udi_reg[id]; + hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + udi_reg->csid_udi_format_measure1_addr); + vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + udi_reg->csid_udi_format_measure2_addr); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id); + return -EINVAL; } CAM_INFO_RATE_LIMIT(CAM_ISP, @@ -2448,7 +2866,6 @@ static int cam_ife_csid_get_hbi_vbi( return 0; } - static int cam_ife_csid_get_time_stamp( struct cam_ife_csid_hw *csid_hw, void *cmd_args) { @@ -2457,6 +2874,7 @@ static int cam_ife_csid_get_time_stamp( const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + const struct cam_ife_csid_udi_reg_offset *udi_reg; struct timespec64 ts; uint32_t time_32, id; @@ -2494,7 +2912,10 @@ static int cam_ife_csid_get_time_stamp( time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_timestamp_curr0_sof_addr); - } else { + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { id = res->res_id; rdi_reg = csid_reg->rdi_reg[id]; time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -2504,6 +2925,21 @@ static int cam_ife_csid_get_time_stamp( time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + rdi_reg->csid_rdi_timestamp_curr0_sof_addr); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; + udi_reg = csid_reg->udi_reg[id]; + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + udi_reg->csid_udi_timestamp_curr1_sof_addr); + time_stamp->time_stamp_val = (uint64_t) time_32; + time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; + + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + udi_reg->csid_udi_timestamp_curr0_sof_addr); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id); + return -EINVAL; } time_stamp->time_stamp_val |= (uint64_t) time_32; @@ -2532,7 +2968,7 @@ static int cam_ife_csid_set_csid_debug(struct cam_ife_csid_hw *csid_hw, return 0; } -static int cam_ife_csid_get_hw_caps(void *hw_priv, +int cam_ife_csid_get_hw_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size) { int rc = 0; @@ -2567,7 +3003,7 @@ static int cam_ife_csid_get_hw_caps(void *hw_priv, return rc; } -static int cam_ife_csid_reset(void *hw_priv, +int cam_ife_csid_reset(void *hw_priv, void *reset_args, uint32_t arg_size) { struct cam_ife_csid_hw *csid_hw; @@ -2602,7 +3038,7 @@ static int cam_ife_csid_reset(void *hw_priv, return rc; } -static int cam_ife_csid_reserve(void *hw_priv, +int cam_ife_csid_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) { int rc = 0; @@ -2641,7 +3077,7 @@ static int cam_ife_csid_reserve(void *hw_priv, return rc; } -static int cam_ife_csid_release(void *hw_priv, +int cam_ife_csid_release(void *hw_priv, void *release_args, uint32_t arg_size) { int rc = 0; @@ -2762,7 +3198,7 @@ static int cam_ife_csid_reset_retain_sw_reg( return rc; } -static int cam_ife_csid_init_hw(void *hw_priv, +int cam_ife_csid_init_hw(void *hw_priv, void *init_args, uint32_t arg_size) { int rc = 0; @@ -2819,10 +3255,22 @@ static int cam_ife_csid_init_hw(void *hw_priv, break; case CAM_ISP_RESOURCE_PIX_PATH: if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP || - res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { rc = cam_ife_csid_init_config_pxl_path(csid_hw, res); - else + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { rc = cam_ife_csid_init_config_rdi_path(csid_hw, res); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + rc = cam_ife_csid_init_config_udi_path(csid_hw, res); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id); + rc = -EINVAL; + goto end; + } break; default: @@ -2847,7 +3295,7 @@ end: return rc; } -static int cam_ife_csid_deinit_hw(void *hw_priv, +int cam_ife_csid_deinit_hw(void *hw_priv, void *deinit_args, uint32_t arg_size) { int rc = 0; @@ -2882,10 +3330,22 @@ static int cam_ife_csid_deinit_hw(void *hw_priv, case CAM_ISP_RESOURCE_PIX_PATH: CAM_DBG(CAM_ISP, "De-Init Pix Path: %d\n", res->res_id); if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP || - res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { rc = cam_ife_csid_deinit_pxl_path(csid_hw, res); - else + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { rc = cam_ife_csid_deinit_rdi_path(csid_hw, res); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + rc = cam_ife_csid_deinit_udi_path(csid_hw, res); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id); + rc = -EINVAL; + goto end; + } break; default: @@ -2905,7 +3365,7 @@ end: return rc; } -static int cam_ife_csid_start(void *hw_priv, void *start_args, +int cam_ife_csid_start(void *hw_priv, void *start_args, uint32_t arg_size) { int rc = 0; @@ -2950,10 +3410,23 @@ static int cam_ife_csid_start(void *hw_priv, void *start_args, break; case CAM_ISP_RESOURCE_PIX_PATH: if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP || - res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { rc = cam_ife_csid_enable_pxl_path(csid_hw, res); - else + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { rc = cam_ife_csid_enable_rdi_path(csid_hw, res); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + rc = cam_ife_csid_enable_udi_path(csid_hw, res); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id); + rc = -EINVAL; + goto end; + } + break; default: CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", @@ -2965,7 +3438,7 @@ end: return rc; } -static int cam_ife_csid_stop(void *hw_priv, +int cam_ife_csid_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { int rc = 0; @@ -3008,12 +3481,25 @@ static int cam_ife_csid_stop(void *hw_priv, 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) + res->res_id == CAM_IFE_PIX_PATH_RES_PPP) { rc = cam_ife_csid_disable_pxl_path(csid_hw, res, csid_stop->stop_cmd); - else + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 || + res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) { rc = cam_ife_csid_disable_rdi_path(csid_hw, res, csid_stop->stop_cmd); + } else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 || + res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) { + rc = cam_ife_csid_disable_udi_path(csid_hw, + res, csid_stop->stop_cmd); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id: %u", + res->res_id); + return -EINVAL; + } break; default: @@ -3038,7 +3524,7 @@ static int cam_ife_csid_stop(void *hw_priv, } -static int cam_ife_csid_read(void *hw_priv, +int cam_ife_csid_read(void *hw_priv, void *read_args, uint32_t arg_size) { CAM_ERR(CAM_ISP, "CSID: un supported"); @@ -3046,7 +3532,7 @@ static int cam_ife_csid_read(void *hw_priv, return -EINVAL; } -static int cam_ife_csid_write(void *hw_priv, +int cam_ife_csid_write(void *hw_priv, void *write_args, uint32_t arg_size) { CAM_ERR(CAM_ISP, "CSID: un supported"); @@ -3107,6 +3593,21 @@ static int cam_ife_csid_sof_irq_debug( } } + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_irq_mask_addr); + if (val) { + if (sof_irq_enable) + val |= CSID_PATH_INFO_INPUT_SOF; + else + val &= ~CSID_PATH_INFO_INPUT_SOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_irq_mask_addr); + val = 0; + } + } + if (sof_irq_enable) { csid_hw->csid_debug |= CSID_DEBUG_ENABLE_SOF_IRQ; csid_hw->sof_irq_triggered = true; @@ -3210,7 +3711,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) const struct cam_ife_csid_reg_offset *csid_reg; const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg; uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0; - uint32_t irq_status_rdi[4] = {0, 0, 0, 0}; + uint32_t irq_status_rdi[CAM_IFE_CSID_RDI_MAX] = {0, 0, 0, 0}; + uint32_t irq_status_udi[CAM_IFE_CSID_UDI_MAX] = {0, 0, 0}; uint32_t val, irq_status_ppp = 0; bool fatal_err_detected = false; uint32_t sof_irq_debug_en = 0; @@ -3244,10 +3746,21 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) irq_status_ppp = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_irq_status_addr); + if (csid_reg->cmn_reg->num_rdis <= CAM_IFE_CSID_RDI_MAX) { + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + irq_status_rdi[i] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr); + } + } - for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) - irq_status_rdi[i] = cam_io_r_mb(soc_info->reg_map[0].mem_base + - csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr); + if (csid_reg->cmn_reg->num_udis <= CAM_IFE_CSID_UDI_MAX) { + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { + irq_status_udi[i] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_irq_status_addr); + } + } /* clear */ cam_io_w_mb(irq_status_rx, soc_info->reg_map[0].mem_base + @@ -3260,10 +3773,22 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) cam_io_w_mb(irq_status_ppp, soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_irq_clear_addr); - for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { - cam_io_w_mb(irq_status_rdi[i], soc_info->reg_map[0].mem_base + - csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + if (csid_reg->cmn_reg->num_rdis <= CAM_IFE_CSID_RDI_MAX) { + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + cam_io_w_mb(irq_status_rdi[i], + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + } } + + if (csid_reg->cmn_reg->num_udis <= CAM_IFE_CSID_UDI_MAX) { + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { + cam_io_w_mb(irq_status_udi[i], + soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_irq_clear_addr); + } + } + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); @@ -3271,9 +3796,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx); CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp); CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", irq_status_ppp); - CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x", irq_status_rdi[0]); - CAM_DBG(CAM_ISP, "irq_status_rdi1= 0x%x", irq_status_rdi[1]); - CAM_DBG(CAM_ISP, "irq_status_rdi2= 0x%x", irq_status_rdi[2]); + CAM_DBG(CAM_ISP, + "irq_status_rdi0= 0x%x irq_status_rdi1= 0x%x irq_status_rdi2= 0x%x", + irq_status_rdi[0], irq_status_rdi[1], irq_status_rdi[2]); + CAM_DBG(CAM_ISP, + "irq_status_udi0= 0x%x irq_status_udi1= 0x%x irq_status_udi2= 0x%x", + irq_status_udi[0], irq_status_udi[1], irq_status_udi[2]); if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "csi rx reset complete"); @@ -3578,6 +4106,46 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } } + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { + if (irq_status_udi[i] & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "CSID UDI%d reset complete", i); + complete(&csid_hw->csid_udin_complete[i]); + } + + if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_SOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID UDI:%d SOF received", i); + if (csid_hw->sof_irq_triggered) + csid_hw->irq_debug_cnt++; + } + + if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_EOF) && + (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID UDI:%d EOF received", i); + + if ((irq_status_udi[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) + CAM_WARN_RATE_LIMIT(CAM_ISP, + "CSID UDI :%d CCIF violation", i); + + if ((irq_status_udi[i] & CSID_PATH_OVERFLOW_RECOVERY)) + CAM_WARN_RATE_LIMIT(CAM_ISP, + "CSID UDI :%d Overflow due to back pressure", + i); + + if (irq_status_udi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d UDI fifo over flow", + csid_hw->hw_intf->hw_idx); + /* Stop UDI path immediately */ + cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, + soc_info->reg_map[0].mem_base + + csid_reg->udi_reg[i]->csid_udi_ctrl_addr); + } + } + if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_ife_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); csid_hw->irq_debug_cnt = 0; @@ -3588,7 +4156,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, - uint32_t csid_idx) + uint32_t csid_idx, bool is_custom) { int rc = -EINVAL; uint32_t i; @@ -3627,9 +4195,11 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, for (i = 0; i < CAM_IFE_CSID_RDI_MAX; i++) init_completion(&ife_csid_hw->csid_rdin_complete[i]); + for (i = 0; i < CAM_IFE_CSID_UDI_MAX; i++) + init_completion(&ife_csid_hw->csid_udin_complete[i]); rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info, - cam_ife_csid_irq, ife_csid_hw); + cam_ife_csid_irq, ife_csid_hw, is_custom); if (rc < 0) { CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc", csid_idx); goto err; @@ -3651,7 +4221,8 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->hw_intf->hw_ops.process_cmd = cam_ife_csid_process_cmd; num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->num_pix + - ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis + + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis; /* Initialize the CID resource */ for (i = 0; i < num_paths; i++) { ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID; @@ -3721,6 +4292,27 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->rdi_res[i].res_priv = path_data; } + /* Initialize the UDI resource */ + for (i = 0; i < ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis; + i++) { + /* res type is from UDI0 to UDI3 */ + ife_csid_hw->udi_res[i].res_type = + CAM_ISP_RESOURCE_PIX_PATH; + ife_csid_hw->udi_res[i].res_id = i + + CAM_IFE_PIX_PATH_RES_UDI_0; + ife_csid_hw->udi_res[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + ife_csid_hw->udi_res[i].hw_intf = ife_csid_hw->hw_intf; + + path_data = kzalloc(sizeof(*path_data), + GFP_KERNEL); + if (!path_data) { + rc = -ENOMEM; + goto err; + } + ife_csid_hw->udi_res[i].res_priv = path_data; + } + ife_csid_hw->csid_debug = 0; ife_csid_hw->error_irq_count = 0; @@ -3734,6 +4326,11 @@ err: i++) kfree(ife_csid_hw->rdi_res[i].res_priv); + for (i = 0; i < + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis; + i++) + kfree(ife_csid_hw->udi_res[i].res_priv); + for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++) kfree(ife_csid_hw->cid_res[i].res_priv); @@ -3741,7 +4338,7 @@ err: return rc; } - +EXPORT_SYMBOL(cam_ife_csid_hw_probe_init); int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw) { @@ -3761,6 +4358,11 @@ int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw) i++) { kfree(ife_csid_hw->rdi_res[i].res_priv); } + for (i = 0; i < + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis; + i++) { + kfree(ife_csid_hw->udi_res[i].res_priv); + } for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++) kfree(ife_csid_hw->cid_res[i].res_priv); @@ -3768,3 +4370,4 @@ int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw) return 0; } +EXPORT_SYMBOL(cam_ife_csid_hw_deinit); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index d4a3a840d969..e4c8bafb6303 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -9,6 +9,7 @@ #include "cam_hw.h" #include "cam_ife_csid_hw_intf.h" #include "cam_ife_csid_soc.h" +#include "cam_ife_csid_core.h" #define CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED BIT(0) #define CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED BIT(1) @@ -192,6 +193,59 @@ struct cam_ife_csid_rdi_reg_offset { uint32_t overflow_ctrl_en; }; +struct cam_ife_csid_udi_reg_offset { + uint32_t csid_udi_irq_status_addr; + uint32_t csid_udi_irq_mask_addr; + uint32_t csid_udi_irq_clear_addr; + uint32_t csid_udi_irq_set_addr; + + /* UDI N register address */ + uint32_t csid_udi_cfg0_addr; + uint32_t csid_udi_cfg1_addr; + uint32_t csid_udi_ctrl_addr; + uint32_t csid_udi_frm_drop_pattern_addr; + uint32_t csid_udi_frm_drop_period_addr; + uint32_t csid_udi_irq_subsample_pattern_addr; + uint32_t csid_udi_irq_subsample_period_addr; + uint32_t csid_udi_rpp_hcrop_addr; + uint32_t csid_udi_rpp_vcrop_addr; + uint32_t csid_udi_rpp_pix_drop_pattern_addr; + uint32_t csid_udi_rpp_pix_drop_period_addr; + uint32_t csid_udi_rpp_line_drop_pattern_addr; + uint32_t csid_udi_rpp_line_drop_period_addr; + uint32_t csid_udi_yuv_chroma_conversion_addr; + uint32_t csid_udi_rst_strobes_addr; + uint32_t csid_udi_status_addr; + uint32_t csid_udi_misr_val0_addr; + uint32_t csid_udi_misr_val1_addr; + uint32_t csid_udi_misr_val2_addr; + uint32_t csid_udi_misr_val3_addr; + uint32_t csid_udi_format_measure_cfg0_addr; + uint32_t csid_udi_format_measure_cfg1_addr; + uint32_t csid_udi_format_measure0_addr; + uint32_t csid_udi_format_measure1_addr; + uint32_t csid_udi_format_measure2_addr; + uint32_t csid_udi_timestamp_curr0_sof_addr; + uint32_t csid_udi_timestamp_curr1_sof_addr; + uint32_t csid_udi_timestamp_prev0_sof_addr; + uint32_t csid_udi_timestamp_prev1_sof_addr; + uint32_t csid_udi_timestamp_curr0_eof_addr; + uint32_t csid_udi_timestamp_curr1_eof_addr; + uint32_t csid_udi_timestamp_prev0_eof_addr; + uint32_t csid_udi_timestamp_prev1_eof_addr; + uint32_t csid_udi_err_recovery_cfg0_addr; + uint32_t csid_udi_err_recovery_cfg1_addr; + uint32_t csid_udi_err_recovery_cfg2_addr; + uint32_t csid_udi_multi_vcdt_cfg0_addr; + uint32_t csid_udi_byte_cntr_ping_addr; + uint32_t csid_udi_byte_cntr_pong_addr; + + /* configuration */ + uint32_t packing_format; + uint32_t ccif_violation_en; + uint32_t overflow_ctrl_en; +}; + struct cam_ife_csid_csi2_rx_reg_offset { uint32_t csid_csi2_rx_irq_status_addr; uint32_t csid_csi2_rx_irq_mask_addr; @@ -288,6 +342,7 @@ struct cam_ife_csid_common_reg_offset { uint32_t major_version; uint32_t minor_version; uint32_t version_incr; + uint32_t num_udis; uint32_t num_rdis; uint32_t num_pix; uint32_t num_ppp; @@ -310,8 +365,10 @@ struct cam_ife_csid_common_reg_offset { uint32_t ipp_irq_mask_all; uint32_t rdi_irq_mask_all; uint32_t ppp_irq_mask_all; + uint32_t udi_irq_mask_all; uint32_t measure_en_hbi_vbi_cnt_mask; uint32_t format_measure_en_val; + uint32_t num_bytes_out_shift_val; }; /** @@ -320,7 +377,9 @@ struct cam_ife_csid_common_reg_offset { * @cmn_reg: csid common registers info * @ipp_reg: ipp register offset information * @ppp_reg: ppp register offset information - * @rdi_reg: rdi register offser information + * @rdi_reg: rdi register offset information + * @udi_reg: udi register offset information + * @tpg_reg: tpg register offset information * */ struct cam_ife_csid_reg_offset { @@ -329,6 +388,7 @@ struct cam_ife_csid_reg_offset { const struct cam_ife_csid_pxl_reg_offset *ipp_reg; const struct cam_ife_csid_pxl_reg_offset *ppp_reg; const struct cam_ife_csid_rdi_reg_offset *rdi_reg[CAM_IFE_CSID_RDI_MAX]; + const struct cam_ife_csid_udi_reg_offset *udi_reg[CAM_IFE_CSID_UDI_MAX]; const struct cam_ife_csid_csi2_tpg_reg_offset *tpg_reg; }; @@ -427,6 +487,7 @@ struct cam_ife_csid_cid_data { * @master_idx: For Slave reservation, Give master IFE instance Index. * Slave will synchronize with master Start and stop operations * @clk_rate Clock rate + * @num_bytes_out: Number of output bytes per cycle * */ struct cam_ife_csid_path_cfg { @@ -451,6 +512,7 @@ struct cam_ife_csid_path_cfg { uint64_t clk_rate; uint32_t horizontal_bin; uint32_t qcfa_bin; + uint32_t num_bytes_out; }; /** @@ -468,12 +530,14 @@ struct cam_ife_csid_path_cfg { * @ipp_res: image pixel path resource * @ppp_res: phase pxl path resource * @rdi_res: raw dump image path resources + * @udi_res: udi path resources * @cid_res: cid resources state * @csid_top_reset_complete: csid top reset completion * @csid_csi2_reset_complete: csi2 reset completion * @csid_ipp_reset_complete: ipp reset completion * @csid_ppp_complete: ppp reset completion * @csid_rdin_reset_complete: rdi n completion + * @csid_udin_reset_complete: udi n completion * @csid_debug: csid debug information to enable the SOT, EOT, * SOF, EOF, measure etc in the csid hw * @clk_rate Clock rate @@ -499,12 +563,14 @@ struct cam_ife_csid_hw { struct cam_isp_resource_node ipp_res; struct cam_isp_resource_node ppp_res; struct cam_isp_resource_node rdi_res[CAM_IFE_CSID_RDI_MAX]; + struct cam_isp_resource_node udi_res[CAM_IFE_CSID_UDI_MAX]; struct cam_isp_resource_node cid_res[CAM_IFE_CSID_CID_MAX]; struct completion csid_top_complete; struct completion csid_csi2_complete; struct completion csid_ipp_complete; struct completion csid_ppp_complete; struct completion csid_rdin_complete[CAM_IFE_CSID_RDI_MAX]; + struct completion csid_udin_complete[CAM_IFE_CSID_UDI_MAX]; uint64_t csid_debug; uint64_t clk_rate; bool sof_irq_triggered; @@ -517,8 +583,14 @@ struct cam_ife_csid_hw { }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, - uint32_t csid_idx); + uint32_t csid_idx, bool is_custom); int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw); +int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, + struct cam_csid_hw_reserve_resource_args *cid_reserv); + +int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, + struct cam_csid_hw_reserve_resource_args *reserve); + #endif /* _CAM_IFE_CSID_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c index 05bf36899392..eca0e43a9b5e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c @@ -76,7 +76,7 @@ int cam_ife_csid_probe(struct platform_device *pdev) /* need to setup the pdev before call the ife hw probe init */ csid_dev->csid_info = csid_hw_data; - rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx); + rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx, false); if (rc) goto free_dev; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c index 3a6d3e8abf98..ede6dbc5ea6e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -39,7 +39,7 @@ static int cam_ife_csid_request_platform_resource( } int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, - irq_handler_t csid_irq_handler, void *irq_data) + irq_handler_t csid_irq_handler, void *irq_data, bool is_custom) { int rc = 0; struct cam_cpas_register_params cpas_register_param; @@ -66,8 +66,13 @@ int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, } memset(&cpas_register_param, 0, sizeof(cpas_register_param)); - strlcpy(cpas_register_param.identifier, "csid", - CAM_HW_IDENTIFIER_LENGTH); + if (is_custom) + strlcpy(cpas_register_param.identifier, "csid-custom", + CAM_HW_IDENTIFIER_LENGTH); + else + strlcpy(cpas_register_param.identifier, "csid", + CAM_HW_IDENTIFIER_LENGTH); + cpas_register_param.cell_index = soc_info->index; cpas_register_param.dev = soc_info->dev; rc = cam_cpas_register_client(&cpas_register_param); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h index 317dcb39a59b..4f76d084fba3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_SOC_H_ @@ -39,10 +39,11 @@ struct csid_device_soc_info { * @soc_info: soc info structure pointer * @csid_irq_handler: irq handler function to be registered * @irq_data: irq data for the callback function + * @is_custom: for custom csid hw * */ int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, - irq_handler_t csid_irq_handler, void *irq_data); + irq_handler_t csid_irq_handler, void *irq_data, bool is_custom); /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index e31cddc91b11..56ce59636dda 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -12,6 +12,7 @@ /* MAX IFE CSID instance */ #define CAM_IFE_CSID_HW_NUM_MAX 7 #define CAM_IFE_CSID_RDI_MAX 4 +#define CAM_IFE_CSID_UDI_MAX 3 /** * enum cam_ife_pix_path_res_id - Specify the csid patch @@ -23,6 +24,9 @@ enum cam_ife_pix_path_res_id { CAM_IFE_PIX_PATH_RES_RDI_3, CAM_IFE_PIX_PATH_RES_IPP, CAM_IFE_PIX_PATH_RES_PPP, + CAM_IFE_PIX_PATH_RES_UDI_0, + CAM_IFE_PIX_PATH_RES_UDI_1, + CAM_IFE_PIX_PATH_RES_UDI_2, CAM_IFE_PIX_PATH_RES_MAX, }; @@ -97,6 +101,7 @@ struct cam_isp_in_port_generic_info { uint32_t num_out_res; uint32_t horizontal_bin; uint32_t qcfa_bin; + uint32_t num_bytes_out; struct cam_isp_out_port_generic_info *data; }; From 02f76464135a71868aa200644f2266be27abda4a Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 26 Aug 2019 13:37:18 -0700 Subject: [PATCH 073/790] msm: camera: custom: Add uapi for custom HW This change adds uapi for custom HW block. CRs-Fixed: 2515662 Change-Id: Id4284594746a313ab09dad5c290cedc2b9edb62c Signed-off-by: Karthik Anantha Ram --- include/uapi/media/cam_custom.h | 198 +++++++++++++++++++++++++++++++ include/uapi/media/cam_req_mgr.h | 1 + 2 files changed, 199 insertions(+) create mode 100644 include/uapi/media/cam_custom.h diff --git a/include/uapi/media/cam_custom.h b/include/uapi/media/cam_custom.h new file mode 100644 index 000000000000..b36891f4a0dc --- /dev/null +++ b/include/uapi/media/cam_custom.h @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_CUSTOM_H__ +#define __UAPI_CAM_CUSTOM_H__ + +#include "cam_defs.h" + +/* Custom driver name */ +#define CAM_CUSTOM_DEV_NAME "cam-custom" + +#define CAM_CUSTOM_NUM_SUB_DEVICES 2 + +/* HW type */ +#define CAM_CUSTOM_HW1 0 +#define CAM_CUSTOM_HW2 1 + +/* output path resource id's */ +#define CAM_CUSTOM_OUT_RES_UDI_0 1 +#define CAM_CUSTOM_OUT_RES_UDI_1 2 +#define CAM_CUSTOM_OUT_RES_UDI_2 3 + +/* input resource for custom hw */ +#define CAM_CUSTOM_IN_RES_UDI_0 1 + +/* Resource ID */ +#define CAM_CUSTOM_RES_ID_PORT 0 + +/* Packet opcode for Custom */ +#define CAM_CUSTOM_PACKET_OP_BASE 0 +#define CAM_CUSTOM_PACKET_INIT_DEV 1 +#define CAM_CUSTOM_PACKET_UPDATE_DEV 2 +#define CAM_CUSTOM_PACKET_OP_MAX 3 + +/* max number of vc-dt cfg for a given input */ +#define CAM_CUSTOM_VC_DT_CFG_MAX 4 + +/* phy input resource types */ +#define CAM_CUSTOM_IN_RES_BASE 0x5000 +#define CAM_CUSTOM_IN_RES_PHY_0 (CAM_CUSTOM_IN_RES_BASE + 1) +#define CAM_CUSTOM_IN_RES_PHY_1 (CAM_CUSTOM_IN_RES_BASE + 2) +#define CAM_CUSTOM_IN_RES_PHY_2 (CAM_CUSTOM_IN_RES_BASE + 3) +#define CAM_CUSTOM_IN_RES_PHY_3 (CAM_CUSTOM_IN_RES_BASE + 4) + +/* Query devices */ +/** + * struct cam_custom_dev_cap_info - A cap info for particular hw type + * + * @hw_type: Custom HW type + * @hw_version: Hardware version + * + */ +struct cam_custom_dev_cap_info { + uint32_t hw_type; + uint32_t hw_version; +}; + +/** + * struct cam_custom_query_cap_cmd - Custom HW query device capability payload + * + * @device_iommu: returned iommu handles for device + * @cdm_iommu: returned iommu handles for cdm + * @num_dev: returned number of device capabilities + * @reserved: reserved field for alignment + * @dev_caps: returned device capability array + * + */ +struct cam_custom_query_cap_cmd { + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + int32_t num_dev; + uint32_t reserved; + struct cam_custom_dev_cap_info dev_caps[CAM_CUSTOM_NUM_SUB_DEVICES]; +}; + +/* Acquire Device */ +/** + * struct cam_custom_out_port_info - An output port resource info + * + * @res_type: output resource type + * @format: output format of the resource + * @custom_info 1-3: custom params + * @reserved: reserved field for alignment + * + */ +struct cam_custom_out_port_info { + uint32_t res_type; + uint32_t format; + uint32_t custom_info1; + uint32_t custom_info2; + uint32_t custom_info3; + uint32_t reserved; +}; + +/** + * struct cam_custom_in_port_info - An input port resource info + * + * @res_type: input resource type + * @lane_type: lane type: c-phy or d-phy. + * @lane_num: active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * @vc: input virtual channel number + * @dt: input data type number + * @num_valid_vc_dt: number of valid vc-dt + * @format: input format + * @test_pattern: test pattern for the testgen + * @usage_type: whether dual vfe is required + * @left_start: left input start offset in pixels + * @left_stop: left input stop offset in pixels + * @left_width: left input width in pixels + * @right_start: right input start offset in pixels. + * @right_stop: right input stop offset in pixels. + * @right_width: right input width in pixels. + * @line_start: top of the line number + * @line_stop: bottome of the line number + * @height: input height in lines + * @pixel_clk; sensor output clock + * @num_out_byte: number of valid output bytes per cycle + * @custom_info1: custom_info1 + * @custom_info2: custom info 2 + * @num_out_res: number of the output resource associated + * @data: payload that contains the output resources + * + */ +struct cam_custom_in_port_info { + uint32_t res_type; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; + uint32_t vc[CAM_CUSTOM_VC_DT_CFG_MAX]; + uint32_t dt[CAM_CUSTOM_VC_DT_CFG_MAX]; + uint32_t num_valid_vc_dt; + uint32_t format; + uint32_t test_pattern; + uint32_t usage_type; + uint32_t left_start; + uint32_t left_stop; + uint32_t left_width; + uint32_t right_start; + uint32_t right_stop; + uint32_t right_width; + uint32_t line_start; + uint32_t line_stop; + uint32_t height; + uint32_t pixel_clk; + uint32_t num_bytes_out; + uint32_t custom_info1; + uint32_t custom_info2; + uint32_t num_out_res; + struct cam_custom_out_port_info data[1]; +}; + +/** + * struct cam_custom_resource - A resource bundle + * + * @resoruce_id: resource id for the resource bundle + * @length: length of the while resource blob + * @handle_type: type of the resource handle + * @reserved: reserved field for alignment + * @res_hdl: resource handle that points to the + * resource array; + */ +struct cam_custom_resource { + uint32_t resource_id; + uint32_t length; + uint32_t handle_type; + uint32_t reserved; + uint64_t res_hdl; +}; + +/** + * struct cam_custom_cmd_buf_type_1 - cmd buf type 1 + * + * @custom_info: custom info + * @reserved: reserved + */ +struct cam_custom_cmd_buf_type_1 { + uint32_t custom_info; + uint32_t reserved; +}; + +/** + * struct cam_custom_cmd_buf_type_2 - cmd buf type 2 + * + * @custom_info1: Custom info 1 + * @custom_info2: Custom info 2 + * @custom_info3: Custom info 3 + * @reserved: reserved + */ +struct cam_custom_cmd_buf_type_2 { + uint32_t custom_info1; + uint32_t custom_info2; + uint32_t custom_info3; + uint32_t reserved; +}; +#endif /* __UAPI_CAM_CUSTOM_H__ */ diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index a1278dda9b09..36471a290ad3 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -29,6 +29,7 @@ #define CAM_FLASH_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 11) #define CAM_EEPROM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 12) #define CAM_OIS_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 13) +#define CAM_CUSTOM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 14) /* cam_req_mgr hdl info */ #define CAM_REQ_MGR_HDL_IDX_POS 8 From 9c771385d3db9828bddc66f1aca863f09ac1a2b7 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 26 Aug 2019 16:28:49 -0700 Subject: [PATCH 074/790] msm: camera: custom: Add support for custom HW This change provides a template to add any custom HW block. CRs-Fixed: 2515662 Change-Id: Ie707c27950a330658cdaa4b64b7e304f4d62a5b2 Signed-off-by: Karthik Anantha Ram --- drivers/Makefile | 1 + drivers/cam_cust/Makefile | 19 + drivers/cam_cust/cam_custom_context.c | 945 ++++++++++++ drivers/cam_cust/cam_custom_context.h | 115 ++ drivers/cam_cust/cam_custom_dev.c | 198 +++ drivers/cam_cust/cam_custom_dev.h | 34 + drivers/cam_cust/cam_custom_hw_mgr/Makefile | 20 + .../cam_custom_csid/Makefile | 16 + .../cam_custom_csid/cam_custom_csid480.h | 272 ++++ .../cam_custom_csid/cam_custom_csid_dev.c | 190 +++ .../cam_custom_csid/cam_custom_csid_dev.h | 12 + .../cam_custom_hw_mgr/cam_custom_hw1/Makefile | 10 + .../cam_custom_hw1/cam_custom_sub_mod_core.c | 337 +++++ .../cam_custom_hw1/cam_custom_sub_mod_core.h | 79 + .../cam_custom_hw1/cam_custom_sub_mod_dev.c | 162 ++ .../cam_custom_hw1/cam_custom_sub_mod_dev.h | 15 + .../cam_custom_hw1/cam_custom_sub_mod_soc.c | 160 ++ .../cam_custom_hw1/cam_custom_sub_mod_soc.h | 35 + .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 1329 +++++++++++++++++ .../cam_custom_hw_mgr/cam_custom_hw_mgr.h | 180 +++ .../cam_custom_hw_mgr/include/cam_custom_hw.h | 57 + .../include/cam_custom_hw_mgr_intf.h | 104 ++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 4 +- drivers/cam_utils/cam_debug_util.c | 3 + drivers/cam_utils/cam_debug_util.h | 1 + 25 files changed, 4297 insertions(+), 1 deletion(-) create mode 100644 drivers/cam_cust/Makefile create mode 100644 drivers/cam_cust/cam_custom_context.c create mode 100644 drivers/cam_cust/cam_custom_context.h create mode 100644 drivers/cam_cust/cam_custom_dev.c create mode 100644 drivers/cam_cust/cam_custom_dev.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/Makefile create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h create mode 100644 drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h diff --git a/drivers/Makefile b/drivers/Makefile index 9e0aee9f69e3..13edfb587419 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_cust/ diff --git a/drivers/cam_cust/Makefile b/drivers/cam_cust/Makefile new file mode 100644 index 000000000000..732b9593c38b --- /dev/null +++ b/drivers/cam_cust/Makefile @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_dev.o cam_custom_context.o diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c new file mode 100644 index 000000000000..5709530f7bf3 --- /dev/null +++ b/drivers/cam_cust/cam_custom_context.c @@ -0,0 +1,945 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "cam_mem_mgr.h" +#include "cam_sync_api.h" +#include "cam_req_mgr_dev.h" +#include "cam_trace.h" +#include "cam_debug_util.h" +#include "cam_packet_util.h" +#include "cam_context_utils.h" +#include "cam_custom_context.h" +#include "cam_common_util.h" + +static const char custom_dev_name[] = "custom hw"; + +static int __cam_custom_ctx_handle_irq_in_activated( + void *context, uint32_t evt_id, void *evt_data); + +static int __cam_custom_ctx_enqueue_request_in_order( + struct cam_context *ctx, struct cam_ctx_request *req) +{ + struct cam_ctx_request *req_current; + struct cam_ctx_request *req_prev; + struct list_head temp_list; + + INIT_LIST_HEAD(&temp_list); + spin_lock_bh(&ctx->lock); + if (list_empty(&ctx->pending_req_list)) { + list_add_tail(&req->list, &ctx->pending_req_list); + } else { + list_for_each_entry_safe_reverse( + req_current, req_prev, &ctx->pending_req_list, list) { + if (req->request_id < req_current->request_id) { + list_del_init(&req_current->list); + list_add(&req_current->list, &temp_list); + continue; + } else if (req->request_id == req_current->request_id) { + CAM_WARN(CAM_CUSTOM, + "Received duplicated request %lld", + req->request_id); + } + break; + } + list_add_tail(&req->list, &ctx->pending_req_list); + + if (!list_empty(&temp_list)) { + list_for_each_entry_safe( + req_current, req_prev, &temp_list, list) { + list_del_init(&req_current->list); + list_add_tail(&req_current->list, + &ctx->pending_req_list); + } + } + } + spin_unlock_bh(&ctx->lock); + return 0; +} + +static int __cam_custom_ctx_flush_req(struct cam_context *ctx, + struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req) +{ + int i, rc; + uint32_t cancel_req_id_found = 0; + struct cam_ctx_request *req; + struct cam_ctx_request *req_temp; + struct cam_custom_dev_ctx_req *req_custom; + struct list_head flush_list; + + INIT_LIST_HEAD(&flush_list); + if (list_empty(req_list)) { + CAM_DBG(CAM_CUSTOM, "request list is empty"); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + CAM_ERR(CAM_CUSTOM, "no request to cancel"); + return -EINVAL; + } else { + return 0; + } + } + + CAM_DBG(CAM_CUSTOM, "Flush [%u] in progress for req_id %llu", + flush_req->type, flush_req->req_id); + list_for_each_entry_safe(req, req_temp, req_list, list) { + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + if (req->request_id != flush_req->req_id) { + continue; + } else { + list_del_init(&req->list); + list_add_tail(&req->list, &flush_list); + cancel_req_id_found = 1; + break; + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &flush_list); + } + + list_for_each_entry_safe(req, req_temp, &flush_list, list) { + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + for (i = 0; i < req_custom->num_fence_map_out; i++) { + if (req_custom->fence_map_out[i].sync_id != -1) { + CAM_DBG(CAM_CUSTOM, + "Flush req 0x%llx, fence %d", + req->request_id, + req_custom->fence_map_out[i].sync_id); + rc = cam_sync_signal( + req_custom->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) + CAM_ERR_RATE_LIMIT(CAM_CUSTOM, + "signal fence failed\n"); + req_custom->fence_map_out[i].sync_id = -1; + } + } + list_add_tail(&req->list, &ctx->free_req_list); + } + + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && + !cancel_req_id_found) + CAM_DBG(CAM_CUSTOM, + "Flush request id:%lld is not found in the list", + flush_req->req_id); + + return 0; +} + +static int __cam_custom_ctx_flush_req_in_top_state( + struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush_req) +{ + int rc = 0; + + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + CAM_INFO(CAM_CUSTOM, "Last request id to flush is %lld", + flush_req->req_id); + ctx->last_flush_req = flush_req->req_id; + } + + spin_lock_bh(&ctx->lock); + rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); + spin_unlock_bh(&ctx->lock); + + return rc; +} + +static int __cam_custom_ctx_flush_req_in_ready( + struct cam_context *ctx, + struct cam_req_mgr_flush_request *flush_req) +{ + int rc = 0; + + CAM_DBG(CAM_CUSTOM, "try to flush pending list"); + spin_lock_bh(&ctx->lock); + rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); + + /* if nothing is in pending req list, change state to acquire */ + if (list_empty(&ctx->pending_req_list)) + ctx->state = CAM_CTX_ACQUIRED; + spin_unlock_bh(&ctx->lock); + + CAM_DBG(CAM_CUSTOM, "Flush request in ready state. next state %d", + ctx->state); + return rc; +} + +static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + ctx->link_hdl = -1; + ctx->ctx_crm_intf = NULL; + ctx->state = CAM_CTX_ACQUIRED; + + return 0; +} + +static int __cam_custom_stop_dev_core( + struct cam_context *ctx, struct cam_start_stop_dev_cmd *stop_cmd) +{ + int rc = 0; + uint32_t i; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + struct cam_ctx_request *req; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_hw_stop_args stop; + + if (ctx_custom->hw_ctx) { + stop.ctxt_to_hw_map = ctx_custom->hw_ctx; + + stop.args = NULL; + if (ctx->hw_mgr_intf->hw_stop) + ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop); + } + + while (!list_empty(&ctx->pending_req_list)) { + req = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + CAM_DBG(CAM_CUSTOM, + "signal fence in pending list. fence num %d", + req_custom->num_fence_map_out); + for (i = 0; i < req_custom->num_fence_map_out; i++) + if (req_custom->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_custom->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + } + + while (!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_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + CAM_DBG(CAM_CUSTOM, "signal fence in wait list. fence num %d", + req_custom->num_fence_map_out); + for (i = 0; i < req_custom->num_fence_map_out; i++) + if (req_custom->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_custom->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + } + + while (!list_empty(&ctx->active_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + CAM_DBG(CAM_CUSTOM, "signal fence in active list. fence num %d", + req_custom->num_fence_map_out); + for (i = 0; i < req_custom->num_fence_map_out; i++) + if (req_custom->fence_map_out[i].sync_id != -1) { + cam_sync_signal( + req_custom->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + } + list_add_tail(&req->list, &ctx->free_req_list); + } + ctx_custom->frame_id = 0; + ctx_custom->active_req_cnt = 0; + + CAM_DBG(CAM_CUSTOM, "Stop device success next state %d on ctx %u", + ctx->state, ctx->ctx_id); + + if (!stop_cmd) { + rc = __cam_custom_ctx_unlink_in_ready(ctx, NULL); + if (rc) + CAM_ERR(CAM_CUSTOM, "Unlink failed rc=%d", rc); + } + return rc; +} + +static int __cam_custom_stop_dev_in_activated(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *)ctx->ctx_priv; + + __cam_custom_stop_dev_core(ctx, cmd); + ctx_custom->init_received = false; + ctx->state = CAM_CTX_ACQUIRED; + + return 0; +} + +static int __cam_custom_release_dev_in_acquired(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + struct cam_req_mgr_flush_request flush_req; + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_CUSTOM, "Unable to release device"); + + ctx->ctx_crm_intf = NULL; + ctx->last_flush_req = 0; + ctx_custom->frame_id = 0; + ctx_custom->active_req_cnt = 0; + ctx_custom->init_received = false; + + if (!list_empty(&ctx->active_req_list)) + CAM_ERR(CAM_CUSTOM, "Active list is not empty"); + + /* Flush all the pending request list */ + flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; + flush_req.link_hdl = ctx->link_hdl; + flush_req.dev_hdl = ctx->dev_hdl; + + CAM_DBG(CAM_CUSTOM, "try to flush pending list"); + spin_lock_bh(&ctx->lock); + rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, + &flush_req); + spin_unlock_bh(&ctx->lock); + ctx->state = CAM_CTX_AVAILABLE; + + CAM_DBG(CAM_CUSTOM, "Release device success[%u] next state %d", + ctx->ctx_id, ctx->state); + + return rc; +} + +static int __cam_custom_ctx_apply_req_in_activated_state( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_ctx_request *req; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_custom_context *custom_ctx = NULL; + struct cam_hw_config_args cfg; + + if (list_empty(&ctx->pending_req_list)) { + CAM_ERR(CAM_CUSTOM, "No available request for Apply id %lld", + apply->request_id); + rc = -EFAULT; + goto end; + } + + custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; + spin_lock_bh(&ctx->lock); + req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, + list); + spin_unlock_bh(&ctx->lock); + + /* + * Check whether the request id is matching the tip + */ + if (req->request_id != apply->request_id) { + CAM_ERR_RATE_LIMIT(CAM_CUSTOM, + "Invalid Request Id asking %llu existing %llu", + apply->request_id, req->request_id); + rc = -EFAULT; + goto end; + } + + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + + cfg.ctxt_to_hw_map = custom_ctx->hw_ctx; + cfg.request_id = req->request_id; + cfg.hw_update_entries = req_custom->cfg; + cfg.num_hw_update_entries = req_custom->num_cfg; + cfg.priv = &req_custom->hw_update_data; + cfg.init_packet = 0; + + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_CUSTOM, + "Can not apply the configuration"); + } else { + spin_lock_bh(&ctx->lock); + list_del_init(&req->list); + if (!req->num_out_map_entries) { + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock_bh(&ctx->lock); + } else { + list_add_tail(&req->list, &ctx->active_req_list); + spin_unlock_bh(&ctx->lock); + /* + * for test purposes only-this should be + * triggered based on irq + */ + __cam_custom_ctx_handle_irq_in_activated(ctx, 0, NULL); + } + } + +end: + return rc; +} + +static int __cam_custom_ctx_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + struct cam_custom_context *custom_ctx; + + custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; + + if (cmd->num_resources > CAM_CUSTOM_DEV_CTX_RES_MAX) { + CAM_ERR(CAM_CUSTOM, "Too much resources in the acquire"); + rc = -ENOMEM; + return rc; + } + + if (cmd->handle_type != 1) { + CAM_ERR(CAM_CUSTOM, "Only user pointer is supported"); + rc = -EINVAL; + return rc; + } + + rc = cam_context_acquire_dev_to_hw(ctx, cmd); + if (!rc) { + ctx->state = CAM_CTX_ACQUIRED; + custom_ctx->hw_ctx = ctx->ctxt_to_hw_map; + } + + CAM_DBG(CAM_CUSTOM, "Acquire done %d", ctx->ctx_id); + return rc; +} + +static int __cam_custom_ctx_enqueue_init_request( + struct cam_context *ctx, struct cam_ctx_request *req) +{ + int rc = 0; + struct cam_ctx_request *req_old; + struct cam_custom_dev_ctx_req *req_custom_old; + struct cam_custom_dev_ctx_req *req_custom_new; + + spin_lock_bh(&ctx->lock); + if (list_empty(&ctx->pending_req_list)) { + list_add_tail(&req->list, &ctx->pending_req_list); + goto end; + } + + req_old = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + req_custom_old = (struct cam_custom_dev_ctx_req *) req_old->req_priv; + req_custom_new = (struct cam_custom_dev_ctx_req *) req->req_priv; + if (req_custom_old->hw_update_data.packet_opcode_type == + CAM_CUSTOM_PACKET_INIT_DEV) { + if ((req_custom_old->num_cfg + req_custom_new->num_cfg) >= + CAM_CUSTOM_CTX_CFG_MAX) { + CAM_WARN(CAM_CUSTOM, "Can not merge INIT pkt"); + rc = -ENOMEM; + } + + if (req_custom_old->num_fence_map_out != 0 || + req_custom_old->num_fence_map_in != 0) { + CAM_WARN(CAM_CUSTOM, "Invalid INIT pkt sequence"); + rc = -EINVAL; + } + + if (!rc) { + memcpy(req_custom_old->fence_map_out, + req_custom_new->fence_map_out, + sizeof(req_custom_new->fence_map_out[0])* + req_custom_new->num_fence_map_out); + req_custom_old->num_fence_map_out = + req_custom_new->num_fence_map_out; + + memcpy(req_custom_old->fence_map_in, + req_custom_new->fence_map_in, + sizeof(req_custom_new->fence_map_in[0])* + req_custom_new->num_fence_map_in); + req_custom_old->num_fence_map_in = + req_custom_new->num_fence_map_in; + + memcpy(&req_custom_old->cfg[req_custom_old->num_cfg], + req_custom_new->cfg, + sizeof(req_custom_new->cfg[0])* + req_custom_new->num_cfg); + req_custom_old->num_cfg += req_custom_new->num_cfg; + + req_old->request_id = req->request_id; + + list_add_tail(&req->list, &ctx->free_req_list); + } + } else { + CAM_WARN(CAM_CUSTOM, + "Received Update pkt before INIT pkt. req_id= %lld", + req->request_id); + rc = -EINVAL; + } +end: + spin_unlock_bh(&ctx->lock); + return rc; +} + +static int __cam_custom_ctx_config_dev(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc = 0, i; + struct cam_ctx_request *req = NULL; + struct cam_custom_dev_ctx_req *req_custom; + uintptr_t packet_addr; + struct cam_packet *packet; + size_t len = 0; + struct cam_hw_prepare_update_args cfg; + struct cam_req_mgr_add_request add_req; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + + /* get free request */ + spin_lock_bh(&ctx->lock); + if (!list_empty(&ctx->free_req_list)) { + req = list_first_entry(&ctx->free_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + } + spin_unlock_bh(&ctx->lock); + + if (!req) { + CAM_ERR(CAM_CUSTOM, "No more request obj free"); + return -ENOMEM; + } + + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + + /* for config dev, only memory handle is supported */ + /* map packet from the memhandle */ + rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, + &packet_addr, &len); + if (rc != 0) { + CAM_ERR(CAM_CUSTOM, "Can not get packet address"); + rc = -EINVAL; + goto free_req; + } + + packet = (struct cam_packet *)(packet_addr + (uint32_t)cmd->offset); + CAM_DBG(CAM_CUSTOM, "pack_handle %llx", cmd->packet_handle); + CAM_DBG(CAM_CUSTOM, "packet address is 0x%zx", packet_addr); + CAM_DBG(CAM_CUSTOM, "packet with length %zu, offset 0x%llx", + len, cmd->offset); + CAM_DBG(CAM_CUSTOM, "Packet request id %lld", + packet->header.request_id); + CAM_DBG(CAM_CUSTOM, "Packet size 0x%x", packet->header.size); + CAM_DBG(CAM_CUSTOM, "packet op %d", packet->header.op_code); + + if ((((packet->header.op_code) & 0xF) == + CAM_CUSTOM_PACKET_UPDATE_DEV) + && (packet->header.request_id <= ctx->last_flush_req)) { + CAM_DBG(CAM_CUSTOM, + "request %lld has been flushed, reject packet", + packet->header.request_id); + rc = -EINVAL; + goto free_req; + } + + /* preprocess the configuration */ + memset(&cfg, 0, sizeof(cfg)); + cfg.packet = packet; + cfg.ctxt_to_hw_map = ctx_custom->hw_ctx; + cfg.out_map_entries = req_custom->fence_map_out; + cfg.in_map_entries = req_custom->fence_map_in; + cfg.priv = &req_custom->hw_update_data; + cfg.pf_data = &(req->pf_data); + + rc = ctx->hw_mgr_intf->hw_prepare_update( + ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc != 0) { + CAM_ERR(CAM_CUSTOM, "Prepare config packet failed in HW layer"); + rc = -EFAULT; + goto free_req; + } + + req_custom->num_cfg = cfg.num_hw_update_entries; + req_custom->num_fence_map_out = cfg.num_out_map_entries; + req_custom->num_fence_map_in = cfg.num_in_map_entries; + req_custom->num_acked = 0; + + for (i = 0; i < req_custom->num_fence_map_out; i++) { + rc = cam_sync_get_obj_ref(req_custom->fence_map_out[i].sync_id); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Can't get ref for fence %d", + req_custom->fence_map_out[i].sync_id); + goto put_ref; + } + } + + CAM_DBG(CAM_CUSTOM, + "num_entry: %d, num fence out: %d, num fence in: %d", + req_custom->num_cfg, req_custom->num_fence_map_out, + req_custom->num_fence_map_in); + + req->request_id = packet->header.request_id; + req->status = 1; + + CAM_DBG(CAM_CUSTOM, "Packet request id %lld packet opcode:%d", + packet->header.request_id, + req_custom->hw_update_data.packet_opcode_type); + + if (req_custom->hw_update_data.packet_opcode_type == + CAM_CUSTOM_PACKET_INIT_DEV) { + if (ctx->state < CAM_CTX_ACTIVATED) { + rc = __cam_custom_ctx_enqueue_init_request(ctx, req); + if (rc) + CAM_ERR(CAM_CUSTOM, "Enqueue INIT pkt failed"); + ctx_custom->init_received = true; + } else { + rc = -EINVAL; + CAM_ERR(CAM_CUSTOM, "Recevied INIT pkt in wrong state"); + } + } else { + if (ctx->state >= CAM_CTX_READY && ctx->ctx_crm_intf->add_req) { + add_req.link_hdl = ctx->link_hdl; + add_req.dev_hdl = ctx->dev_hdl; + add_req.req_id = req->request_id; + add_req.skip_before_applying = 0; + rc = ctx->ctx_crm_intf->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_CUSTOM, + "Add req failed: req id=%llu", + req->request_id); + } else { + __cam_custom_ctx_enqueue_request_in_order( + ctx, req); + } + } else { + rc = -EINVAL; + CAM_ERR(CAM_CUSTOM, "Recevied Update in wrong state"); + } + } + + if (rc) + goto put_ref; + + CAM_DBG(CAM_CUSTOM, + "Preprocessing Config req_id %lld successful on ctx %u", + req->request_id, ctx->ctx_id); + + return rc; + +put_ref: + for (--i; i >= 0; i--) { + if (cam_sync_put_obj_ref(req_custom->fence_map_out[i].sync_id)) + CAM_ERR(CAM_CUSTOM, "Failed to put ref of fence %d", + req_custom->fence_map_out[i].sync_id); + } +free_req: + spin_lock_bh(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock_bh(&ctx->lock); + + return rc; + +} + +static int __cam_custom_ctx_config_dev_in_acquired(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc = 0; + + rc = __cam_custom_ctx_config_dev(ctx, cmd); + + if (!rc && (ctx->link_hdl >= 0)) + ctx->state = CAM_CTX_READY; + + return rc; +} + +static int __cam_custom_ctx_link_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *link) +{ + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + + ctx->link_hdl = link->link_hdl; + ctx->ctx_crm_intf = link->crm_cb; + ctx_custom->subscribe_event = link->subscribe_event; + + /* change state only if we had the init config */ + if (ctx_custom->init_received) + ctx->state = CAM_CTX_READY; + + CAM_DBG(CAM_CUSTOM, "next state %d", ctx->state); + + return 0; +} + +static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + ctx->link_hdl = -1; + ctx->ctx_crm_intf = NULL; + + return 0; +} + +static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_device_info *dev_info) +{ + dev_info->dev_hdl = ctx->dev_hdl; + strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); + dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; + dev_info->p_delay = 1; + dev_info->trigger = CAM_TRIGGER_POINT_SOF; + + return 0; +} + +static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc = 0; + struct cam_hw_config_args hw_config; + struct cam_ctx_request *req; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + + if (cmd->session_handle != ctx->session_hdl || + cmd->dev_handle != ctx->dev_hdl) { + rc = -EPERM; + goto end; + } + + if (list_empty(&ctx->pending_req_list)) { + /* should never happen */ + CAM_ERR(CAM_CUSTOM, "Start device with empty configuration"); + rc = -EFAULT; + goto end; + } else { + req = list_first_entry(&ctx->pending_req_list, + struct cam_ctx_request, list); + } + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + + if (!ctx_custom->hw_ctx) { + CAM_ERR(CAM_CUSTOM, "Wrong hw context pointer."); + rc = -EFAULT; + goto end; + } + + hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; + hw_config.request_id = req->request_id; + hw_config.hw_update_entries = req_custom->cfg; + hw_config.num_hw_update_entries = req_custom->num_cfg; + hw_config.priv = &req_custom->hw_update_data; + hw_config.init_packet = 1; + + ctx->state = CAM_CTX_ACTIVATED; + rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_config); + if (rc) { + /* HW failure. User need to clean up the resource */ + CAM_ERR(CAM_CUSTOM, "Start HW failed"); + ctx->state = CAM_CTX_READY; + goto end; + } + + CAM_DBG(CAM_CUSTOM, "start device success ctx %u", + ctx->ctx_id); + + spin_lock_bh(&ctx->lock); + list_del_init(&req->list); + if (req_custom->num_fence_map_out) + list_add_tail(&req->list, &ctx->active_req_list); + else + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock_bh(&ctx->lock); + +end: + return rc; +} + +static int __cam_custom_ctx_release_dev_in_activated(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc = 0; + + rc = __cam_custom_stop_dev_core(ctx, NULL); + if (rc) + CAM_ERR(CAM_CUSTOM, "Stop device failed rc=%d", rc); + + rc = __cam_custom_release_dev_in_acquired(ctx, cmd); + if (rc) + CAM_ERR(CAM_CUSTOM, "Release device failed rc=%d", rc); + + return rc; +} + +static int __cam_custom_ctx_unlink_in_activated(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + int rc = 0; + + CAM_WARN(CAM_CUSTOM, + "Received unlink in activated state. It's unexpected"); + + rc = __cam_custom_stop_dev_in_activated(ctx, NULL); + if (rc) + CAM_WARN(CAM_CUSTOM, "Stop device failed rc=%d", rc); + + rc = __cam_custom_ctx_unlink_in_ready(ctx, unlink); + if (rc) + CAM_ERR(CAM_CUSTOM, "Unlink failed rc=%d", rc); + + return rc; +} + +static int __cam_custom_ctx_process_evt(struct cam_context *ctx, + struct cam_req_mgr_link_evt_data *link_evt_data) +{ + switch (link_evt_data->evt_type) { + case CAM_REQ_MGR_LINK_EVT_ERR: + /* Handle error/bubble related issues */ + break; + default: + CAM_WARN(CAM_CUSTOM, "Unknown event from CRM"); + break; + } + + return 0; +} + +static int __cam_custom_ctx_handle_irq_in_activated(void *context, + uint32_t evt_id, void *evt_data) +{ + int rc; + struct cam_context *ctx = + (struct cam_context *)context; + + CAM_DBG(CAM_CUSTOM, "Enter %d", ctx->ctx_id); + + /* + * handle based on different irq's currently + * triggering only buf done if there are fences + */ + rc = cam_context_buf_done_from_hw(ctx, evt_data, 0); + if (rc) + CAM_ERR(CAM_CUSTOM, "Failed in buf done, rc=%d", rc); + + return rc; +} + +/* top state machine */ +static struct cam_ctx_ops + cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = + __cam_custom_ctx_acquire_dev_in_available, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .release_dev = __cam_custom_release_dev_in_acquired, + .config_dev = __cam_custom_ctx_config_dev_in_acquired, + }, + .crm_ops = { + .link = __cam_custom_ctx_link_in_acquired, + .unlink = __cam_custom_ctx_unlink_in_acquired, + .get_dev_info = + __cam_custom_ctx_get_dev_info_in_acquired, + .flush_req = __cam_custom_ctx_flush_req_in_top_state, + }, + .irq_ops = NULL, + .pagefault_ops = NULL, + }, + /* Ready */ + { + .ioctl_ops = { + .start_dev = __cam_custom_ctx_start_dev_in_ready, + .release_dev = __cam_custom_release_dev_in_acquired, + .config_dev = __cam_custom_ctx_config_dev, + }, + .crm_ops = { + .unlink = __cam_custom_ctx_unlink_in_ready, + .flush_req = __cam_custom_ctx_flush_req_in_ready, + }, + .irq_ops = NULL, + .pagefault_ops = NULL, + }, + /* Activated */ + { + .ioctl_ops = { + .stop_dev = __cam_custom_stop_dev_in_activated, + .release_dev = + __cam_custom_ctx_release_dev_in_activated, + .config_dev = __cam_custom_ctx_config_dev, + }, + .crm_ops = { + .unlink = __cam_custom_ctx_unlink_in_activated, + .apply_req = + __cam_custom_ctx_apply_req_in_activated_state, + .flush_req = __cam_custom_ctx_flush_req_in_top_state, + .process_evt = __cam_custom_ctx_process_evt, + }, + .irq_ops = __cam_custom_ctx_handle_irq_in_activated, + .pagefault_ops = NULL, + }, +}; + +int cam_custom_dev_context_init(struct cam_custom_context *ctx, + struct cam_context *ctx_base, + struct cam_req_mgr_kmd_ops *crm_node_intf, + struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id) +{ + int rc = -1, i = 0; + + if (!ctx || !ctx_base) { + CAM_ERR(CAM_CUSTOM, "Invalid Context"); + return -EINVAL; + } + + /* Custom HW context setup */ + memset(ctx, 0, sizeof(*ctx)); + + ctx->base = ctx_base; + ctx->frame_id = 0; + ctx->active_req_cnt = 0; + ctx->hw_ctx = NULL; + + for (i = 0; i < CAM_CTX_REQ_MAX; i++) { + ctx->req_base[i].req_priv = &ctx->req_custom[i]; + ctx->req_custom[i].base = &ctx->req_base[i]; + } + + /* camera context setup */ + rc = cam_context_init(ctx_base, custom_dev_name, CAM_CUSTOM, ctx_id, + crm_node_intf, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Camera Context Base init failed"); + return rc; + } + + /* link camera context with custom HW context */ + ctx_base->state_machine = cam_custom_dev_ctx_top_state_machine; + ctx_base->ctx_priv = ctx; + + return rc; +} + +int cam_custom_dev_context_deinit(struct cam_custom_context *ctx) +{ + if (ctx->base) + cam_context_deinit(ctx->base); + + memset(ctx, 0, sizeof(*ctx)); + return 0; +} diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h new file mode 100644 index 000000000000..91acf1e5ee80 --- /dev/null +++ b/drivers/cam_cust/cam_custom_context.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_CONTEXT_H_ +#define _CAM_CUSTOM_CONTEXT_H_ + +#include +#include +#include + +#include "cam_context.h" +#include "cam_custom_hw_mgr_intf.h" + +/* + * Maximum hw resource - This number is based on the maximum + * output port resource. The current maximum resource number + * is 2. + */ +#define CAM_CUSTOM_DEV_CTX_RES_MAX 2 + +#define CAM_CUSTOM_CTX_CFG_MAX 8 + +/* forward declaration */ +struct cam_custom_context; + +/** + * struct cam_custom_dev_ctx_req - Custom context request object + * + * @base: Common request object pointer + * @cfg: Custom hardware configuration array + * @num_cfg: Number of custom hardware configuration entries + * @fence_map_out: Output fence mapping array + * @num_fence_map_out: Number of the output fence map + * @fence_map_in: Input fence mapping array + * @num_fence_map_in: Number of input fence map + * @num_acked: Count to track acked entried for output. + * If count equals the number of fence out, it means + * the request has been completed. + * @hw_update_data: HW update data for this request + * + */ +struct cam_custom_dev_ctx_req { + struct cam_ctx_request *base; + struct cam_hw_update_entry cfg + [CAM_CUSTOM_CTX_CFG_MAX]; + uint32_t num_cfg; + struct cam_hw_fence_map_entry fence_map_out + [CAM_CUSTOM_DEV_CTX_RES_MAX]; + uint32_t num_fence_map_out; + struct cam_hw_fence_map_entry fence_map_in + [CAM_CUSTOM_DEV_CTX_RES_MAX]; + uint32_t num_fence_map_in; + uint32_t num_acked; + struct cam_custom_prepare_hw_update_data hw_update_data; +}; + +/** + * struct cam_custom_context - Custom device context + * @base: custom device context object + * @state_machine: state machine for Custom device context + * @state: Common context state + * @hw_ctx: HW object returned by the acquire device command + * @init_received: Indicate whether init config packet is received + * @subscribe_event: The irq event mask that CRM subscribes to, + * custom HW will invoke CRM cb at those event. + * @active_req_cnt: Counter for the active request + * @frame_id: Frame id tracking for the custom context + * @req_base: common request structure + * @req_custom: custom request structure + * + */ +struct cam_custom_context { + struct cam_context *base; + struct cam_ctx_ops *state_machine; + uint32_t state; + void *hw_ctx; + bool init_received; + uint32_t subscribe_event; + uint32_t active_req_cnt; + int64_t frame_id; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_custom_dev_ctx_req req_custom[CAM_CTX_REQ_MAX]; +}; + + +/** + * cam_custom_dev_context_init() + * + * @brief: Initialization function for the custom context + * + * @ctx: Custom context obj to be initialized + * @bridge_ops: Bridge call back funciton + * @hw_intf: Cust hw manager interface + * @ctx_id: ID for this context + * + */ +int cam_custom_dev_context_init(struct cam_custom_context *ctx, + struct cam_context *ctx_base, + struct cam_req_mgr_kmd_ops *bridge_ops, + struct cam_hw_mgr_intf *hw_intf, + uint32_t ctx_id); + +/** + * cam_custom_dev_context_deinit() + * + * @brief: Deinitialize function for the Custom context + * + * @ctx: Custom context obj to be deinitialized + * + */ +int cam_custom_dev_context_deinit(struct cam_custom_context *ctx); + +#endif /* _CAM_CUSTOM_CONTEXT_H_ */ diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c new file mode 100644 index 000000000000..76d4a7d0e17b --- /dev/null +++ b/drivers/cam_cust/cam_custom_dev.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cam_custom_dev.h" +#include "cam_hw_mgr_intf.h" +#include "cam_custom_hw_mgr_intf.h" +#include "cam_node.h" +#include "cam_debug_util.h" +#include "cam_smmu_api.h" + +static struct cam_custom_dev g_custom_dev; + +static void cam_custom_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_CUSTOM, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + +static const struct of_device_id cam_custom_dt_match[] = { + { + .compatible = "qcom,cam-custom" + }, + {} +}; + +static int cam_custom_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + mutex_lock(&g_custom_dev.custom_dev_mutex); + g_custom_dev.open_cnt++; + mutex_unlock(&g_custom_dev.custom_dev_mutex); + + return 0; +} + +static int cam_custom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = 0; + struct cam_node *node = v4l2_get_subdevdata(sd); + + mutex_lock(&g_custom_dev.custom_dev_mutex); + if (g_custom_dev.open_cnt <= 0) { + CAM_DBG(CAM_CUSTOM, "Custom subdev is already closed"); + rc = -EINVAL; + goto end; + } + + g_custom_dev.open_cnt--; + if (!node) { + CAM_ERR(CAM_CUSTOM, "Node ptr is NULL"); + rc = -EINVAL; + goto end; + } + + if (g_custom_dev.open_cnt == 0) + cam_node_shutdown(node); + +end: + mutex_unlock(&g_custom_dev.custom_dev_mutex); + return rc; +} + +static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { + .close = cam_custom_subdev_close, + .open = cam_custom_subdev_open, +}; + +static int cam_custom_dev_remove(struct platform_device *pdev) +{ + int rc = 0; + int i; + + /* clean up resources */ + for (i = 0; i < CAM_CUSTOM_HW_MAX_INSTANCES; i++) { + rc = cam_custom_dev_context_deinit(&g_custom_dev.ctx_custom[i]); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Custom context %d deinit failed", i); + } + + rc = cam_subdev_remove(&g_custom_dev.sd); + if (rc) + CAM_ERR(CAM_CUSTOM, "Unregister failed"); + + memset(&g_custom_dev, 0, sizeof(g_custom_dev)); + return 0; +} + +static int cam_custom_dev_probe(struct platform_device *pdev) +{ + int rc = -EINVAL; + int i; + struct cam_hw_mgr_intf hw_mgr_intf; + struct cam_node *node; + int iommu_hdl = -1; + + g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; + + rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME, + CAM_CUSTOM_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Custom device cam_subdev_probe failed!"); + goto err; + } + node = (struct cam_node *) g_custom_dev.sd.token; + + memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf)); + rc = cam_custom_hw_mgr_init(pdev->dev.of_node, + &hw_mgr_intf, &iommu_hdl); + if (rc != 0) { + CAM_ERR(CAM_CUSTOM, "Can not initialized Custom HW manager!"); + goto unregister; + } + + for (i = 0; i < CAM_CUSTOM_HW_MAX_INSTANCES; i++) { + rc = cam_custom_dev_context_init(&g_custom_dev.ctx_custom[i], + &g_custom_dev.ctx[i], + &node->crm_node_intf, + &node->hw_mgr_intf, + i); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Custom context init failed!"); + goto unregister; + } + } + + rc = cam_node_init(node, &hw_mgr_intf, g_custom_dev.ctx, + CAM_CUSTOM_HW_MAX_INSTANCES, CAM_CUSTOM_DEV_NAME); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Custom HW node init failed!"); + goto unregister; + } + + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_custom_dev_iommu_fault_handler, node); + + mutex_init(&g_custom_dev.custom_dev_mutex); + + CAM_DBG(CAM_CUSTOM, "Camera custom HW probe complete"); + + return 0; +unregister: + rc = cam_subdev_remove(&g_custom_dev.sd); +err: + return rc; +} + + +static struct platform_driver custom_driver = { + .probe = cam_custom_dev_probe, + .remove = cam_custom_dev_remove, + .driver = { + .name = "cam_custom", + .of_match_table = cam_custom_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_custom_dev_init_module(void) +{ + return platform_driver_register(&custom_driver); +} + +static void __exit cam_custom_dev_exit_module(void) +{ + platform_driver_unregister(&custom_driver); +} + +module_init(cam_custom_dev_init_module); +module_exit(cam_custom_dev_exit_module); +MODULE_DESCRIPTION("MSM CUSTOM driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cust/cam_custom_dev.h b/drivers/cam_cust/cam_custom_dev.h new file mode 100644 index 000000000000..77ea6badfe94 --- /dev/null +++ b/drivers/cam_cust/cam_custom_dev.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_DEV_H_ +#define _CAM_CUSTOM_DEV_H_ + +#include "cam_subdev.h" +#include "cam_hw_mgr_intf.h" +#include "cam_custom_hw_mgr.h" +#include "cam_context.h" +#include "cam_custom_context.h" + +#define CAM_CUSTOM_HW_MAX_INSTANCES 3 + +/** + * struct cam_custom_dev - Camera Custom V4l2 device node + * + * @sd: Common camera subdevice node + * @ctx: Custom base context storage + * @ctx_custom: Custom private context storage + * @custom_dev_mutex: Custom dev mutex + * @open_cnt: Open device count + */ +struct cam_custom_dev { + struct cam_subdev sd; + struct cam_context ctx[CAM_CUSTOM_HW_MAX_INSTANCES]; + struct cam_custom_context ctx_custom[CAM_CUSTOM_HW_MAX_INSTANCES]; + struct mutex custom_dev_mutex; + int32_t open_cnt; +}; + +#endif /* _CAM_CUSTOM_DEV_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/Makefile b/drivers/cam_cust/cam_custom_hw_mgr/Makefile new file mode 100644 index 000000000000..1e0917637b8e --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/Makefile @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw1/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw1/ cam_custom_csid/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw_mgr.o + diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile new file mode 100644 index 000000000000..ab36c8862888 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_csid_dev.o diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h new file mode 100644 index 000000000000..a55bb002ffc2 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_CSID_480_H_ +#define _CAM_CUSTOM_CSID_480_H_ + +#include "cam_ife_csid_core.h" + +#define CAM_CSID_VERSION_V480 0x40080000 + +static struct cam_ife_csid_udi_reg_offset + cam_custom_csid_480_udi_0_reg_offset = { + .csid_udi_irq_status_addr = 0x30, + .csid_udi_irq_mask_addr = 0x34, + .csid_udi_irq_clear_addr = 0x38, + .csid_udi_irq_set_addr = 0x3c, + .csid_udi_cfg0_addr = 0x200, + .csid_udi_cfg1_addr = 0x204, + .csid_udi_ctrl_addr = 0x208, + .csid_udi_frm_drop_pattern_addr = 0x20c, + .csid_udi_frm_drop_period_addr = 0x210, + .csid_udi_irq_subsample_pattern_addr = 0x214, + .csid_udi_irq_subsample_period_addr = 0x218, + .csid_udi_rpp_hcrop_addr = 0x21c, + .csid_udi_rpp_vcrop_addr = 0x220, + .csid_udi_rpp_pix_drop_pattern_addr = 0x224, + .csid_udi_rpp_pix_drop_period_addr = 0x228, + .csid_udi_rpp_line_drop_pattern_addr = 0x22c, + .csid_udi_rpp_line_drop_period_addr = 0x230, + .csid_udi_rst_strobes_addr = 0x240, + .csid_udi_status_addr = 0x250, + .csid_udi_misr_val0_addr = 0x254, + .csid_udi_misr_val1_addr = 0x258, + .csid_udi_misr_val2_addr = 0x25c, + .csid_udi_misr_val3_addr = 0x260, + .csid_udi_format_measure_cfg0_addr = 0x270, + .csid_udi_format_measure_cfg1_addr = 0x274, + .csid_udi_format_measure0_addr = 0x278, + .csid_udi_format_measure1_addr = 0x27c, + .csid_udi_format_measure2_addr = 0x280, + .csid_udi_timestamp_curr0_sof_addr = 0x290, + .csid_udi_timestamp_curr1_sof_addr = 0x294, + .csid_udi_timestamp_prev0_sof_addr = 0x298, + .csid_udi_timestamp_prev1_sof_addr = 0x29c, + .csid_udi_timestamp_curr0_eof_addr = 0x2a0, + .csid_udi_timestamp_curr1_eof_addr = 0x2a4, + .csid_udi_timestamp_prev0_eof_addr = 0x2a8, + .csid_udi_timestamp_prev1_eof_addr = 0x2ac, + .csid_udi_err_recovery_cfg0_addr = 0x2b0, + .csid_udi_err_recovery_cfg1_addr = 0x2b4, + .csid_udi_err_recovery_cfg2_addr = 0x2b8, + .csid_udi_multi_vcdt_cfg0_addr = 0x2bc, + .csid_udi_byte_cntr_ping_addr = 0x2e0, + .csid_udi_byte_cntr_pong_addr = 0x2e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_udi_reg_offset + cam_custom_csid_480_udi_1_reg_offset = { + .csid_udi_irq_status_addr = 0x40, + .csid_udi_irq_mask_addr = 0x44, + .csid_udi_irq_clear_addr = 0x48, + .csid_udi_irq_set_addr = 0x4c, + .csid_udi_cfg0_addr = 0x300, + .csid_udi_cfg1_addr = 0x304, + .csid_udi_ctrl_addr = 0x308, + .csid_udi_frm_drop_pattern_addr = 0x30c, + .csid_udi_frm_drop_period_addr = 0x310, + .csid_udi_irq_subsample_pattern_addr = 0x314, + .csid_udi_irq_subsample_period_addr = 0x318, + .csid_udi_rpp_hcrop_addr = 0x31c, + .csid_udi_rpp_vcrop_addr = 0x320, + .csid_udi_rpp_pix_drop_pattern_addr = 0x324, + .csid_udi_rpp_pix_drop_period_addr = 0x328, + .csid_udi_rpp_line_drop_pattern_addr = 0x32c, + .csid_udi_rpp_line_drop_period_addr = 0x330, + .csid_udi_rst_strobes_addr = 0x340, + .csid_udi_status_addr = 0x350, + .csid_udi_misr_val0_addr = 0x354, + .csid_udi_misr_val1_addr = 0x358, + .csid_udi_misr_val2_addr = 0x35c, + .csid_udi_misr_val3_addr = 0x360, + .csid_udi_format_measure_cfg0_addr = 0x370, + .csid_udi_format_measure_cfg1_addr = 0x374, + .csid_udi_format_measure0_addr = 0x378, + .csid_udi_format_measure1_addr = 0x37c, + .csid_udi_format_measure2_addr = 0x380, + .csid_udi_timestamp_curr0_sof_addr = 0x390, + .csid_udi_timestamp_curr1_sof_addr = 0x394, + .csid_udi_timestamp_prev0_sof_addr = 0x398, + .csid_udi_timestamp_prev1_sof_addr = 0x39c, + .csid_udi_timestamp_curr0_eof_addr = 0x3a0, + .csid_udi_timestamp_curr1_eof_addr = 0x3a4, + .csid_udi_timestamp_prev0_eof_addr = 0x3a8, + .csid_udi_timestamp_prev1_eof_addr = 0x3ac, + .csid_udi_err_recovery_cfg0_addr = 0x3b0, + .csid_udi_err_recovery_cfg1_addr = 0x3b4, + .csid_udi_err_recovery_cfg2_addr = 0x3b8, + .csid_udi_multi_vcdt_cfg0_addr = 0x3bc, + .csid_udi_byte_cntr_ping_addr = 0x3e0, + .csid_udi_byte_cntr_pong_addr = 0x3e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_udi_reg_offset + cam_custom_csid_480_udi_2_reg_offset = { + .csid_udi_irq_status_addr = 0x50, + .csid_udi_irq_mask_addr = 0x54, + .csid_udi_irq_clear_addr = 0x58, + .csid_udi_irq_set_addr = 0x5c, + .csid_udi_cfg0_addr = 0x400, + .csid_udi_cfg1_addr = 0x404, + .csid_udi_ctrl_addr = 0x408, + .csid_udi_frm_drop_pattern_addr = 0x40c, + .csid_udi_frm_drop_period_addr = 0x410, + .csid_udi_irq_subsample_pattern_addr = 0x414, + .csid_udi_irq_subsample_period_addr = 0x418, + .csid_udi_rpp_hcrop_addr = 0x41c, + .csid_udi_rpp_vcrop_addr = 0x420, + .csid_udi_rpp_pix_drop_pattern_addr = 0x424, + .csid_udi_rpp_pix_drop_period_addr = 0x428, + .csid_udi_rpp_line_drop_pattern_addr = 0x42c, + .csid_udi_rpp_line_drop_period_addr = 0x430, + .csid_udi_yuv_chroma_conversion_addr = 0x434, + .csid_udi_rst_strobes_addr = 0x440, + .csid_udi_status_addr = 0x450, + .csid_udi_misr_val0_addr = 0x454, + .csid_udi_misr_val1_addr = 0x458, + .csid_udi_misr_val2_addr = 0x45c, + .csid_udi_misr_val3_addr = 0x460, + .csid_udi_format_measure_cfg0_addr = 0x470, + .csid_udi_format_measure_cfg1_addr = 0x474, + .csid_udi_format_measure0_addr = 0x478, + .csid_udi_format_measure1_addr = 0x47c, + .csid_udi_format_measure2_addr = 0x480, + .csid_udi_timestamp_curr0_sof_addr = 0x490, + .csid_udi_timestamp_curr1_sof_addr = 0x494, + .csid_udi_timestamp_prev0_sof_addr = 0x498, + .csid_udi_timestamp_prev1_sof_addr = 0x49c, + .csid_udi_timestamp_curr0_eof_addr = 0x4a0, + .csid_udi_timestamp_curr1_eof_addr = 0x4a4, + .csid_udi_timestamp_prev0_eof_addr = 0x4a8, + .csid_udi_timestamp_prev1_eof_addr = 0x4ac, + .csid_udi_err_recovery_cfg0_addr = 0x4b0, + .csid_udi_err_recovery_cfg1_addr = 0x4b4, + .csid_udi_err_recovery_cfg2_addr = 0x4b8, + .csid_udi_multi_vcdt_cfg0_addr = 0x4bc, + .csid_udi_byte_cntr_ping_addr = 0x4e0, + .csid_udi_byte_cntr_pong_addr = 0x4e4, + /* configurations */ + .ccif_violation_en = 1, + .overflow_ctrl_en = 1, +}; + +static struct cam_ife_csid_csi2_rx_reg_offset + cam_custom_csid_480_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_de_scramble_cfg0_addr = 0x114, + .csid_csi2_rx_de_scramble_cfg1_addr = 0x118, + .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, + + .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 = 0x3, +}; + +static struct cam_ife_csid_common_reg_offset + cam_custom_csid_480_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 = 0, + .num_udis = 3, + .num_rdis = 0, + .num_pix = 0, + .num_ppp = 0, + .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 = 0, + .rdi_irq_mask_all = 0, + .ppp_irq_mask_all = 0, + .udi_irq_mask_all = 0x7FFF, + .measure_en_hbi_vbi_cnt_mask = 0xC, + .format_measure_en_val = 1, + .num_bytes_out_shift_val = 3, +}; + +static struct cam_ife_csid_reg_offset cam_custom_csid_480_reg_offset = { + .cmn_reg = &cam_custom_csid_480_cmn_reg_offset, + .csi2_reg = &cam_custom_csid_480_csi2_reg_offset, + .ipp_reg = NULL, + .ppp_reg = NULL, + .rdi_reg = { + NULL, + NULL, + NULL, + NULL, + }, + .udi_reg = { + &cam_custom_csid_480_udi_0_reg_offset, + &cam_custom_csid_480_udi_1_reg_offset, + &cam_custom_csid_480_udi_2_reg_offset, + }, + .tpg_reg = NULL, +}; + +#endif /*_CAM_IFE_CSID_480_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c new file mode 100644 index 000000000000..be472372aeb0 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include "linux/module.h" +#include "cam_custom_csid_dev.h" +#include "cam_ife_csid_core.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "cam_custom_csid480.h" +#include "cam_debug_util.h" + +#define CAM_CUSTOM_CSID_DRV_NAME "custom_csid" + +static struct cam_hw_intf *cam_custom_csid_hw_list[CAM_IFE_CSID_HW_NUM_MAX] = { + 0, 0, 0, 0}; + +static char csid_dev_name[16]; + +static struct cam_ife_csid_hw_info cam_custom_csid480_hw_info = { + .csid_reg = &cam_custom_csid_480_reg_offset, + .hw_dts_version = CAM_CSID_VERSION_V480, +}; + +static int cam_custom_csid_probe(struct platform_device *pdev) +{ + + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + struct cam_ife_csid_hw *csid_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_ife_csid_hw_info *csid_hw_data = NULL; + uint32_t csid_dev_idx; + int rc = 0; + + csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL); + if (!csid_hw_intf) { + rc = -ENOMEM; + goto err; + } + + csid_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!csid_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + csid_dev = kzalloc(sizeof(struct cam_ife_csid_hw), GFP_KERNEL); + if (!csid_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + /* get custom csid hw index */ + of_property_read_u32(pdev->dev.of_node, "cell-index", &csid_dev_idx); + /* get custom csid hw information */ + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_CUSTOM, + "No matching table for the CUSTOM CSID HW!"); + rc = -EINVAL; + goto free_dev; + } + + memset(csid_dev_name, 0, sizeof(csid_dev_name)); + snprintf(csid_dev_name, sizeof(csid_dev_name), + "csid-custom%1u", csid_dev_idx); + + csid_hw_intf->hw_idx = csid_dev_idx; + csid_hw_intf->hw_type = CAM_ISP_HW_TYPE_IFE_CSID; + csid_hw_intf->hw_priv = csid_hw_info; + + csid_hw_info->core_info = csid_dev; + csid_hw_info->soc_info.pdev = pdev; + csid_hw_info->soc_info.dev = &pdev->dev; + csid_hw_info->soc_info.dev_name = csid_dev_name; + csid_hw_info->soc_info.index = csid_dev_idx; + + csid_hw_data = (struct cam_ife_csid_hw_info *)match_dev->data; + csid_dev->csid_info = csid_hw_data; + + rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx, true); + if (rc) + goto free_dev; + + platform_set_drvdata(pdev, csid_dev); + CAM_DBG(CAM_CUSTOM, "CSID:%d probe successful for dev %s", + csid_hw_intf->hw_idx, csid_dev_name); + + if (csid_hw_intf->hw_idx < CAM_IFE_CSID_HW_NUM_MAX) + cam_custom_csid_hw_list[csid_hw_intf->hw_idx] = csid_hw_intf; + else + goto free_dev; + + return 0; + +free_dev: + kfree(csid_dev); +free_hw_info: + kfree(csid_hw_info); +free_hw_intf: + kfree(csid_hw_intf); +err: + return rc; +} + +static int cam_custom_csid_remove(struct platform_device *pdev) +{ + struct cam_ife_csid_hw *csid_dev = NULL; + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + + csid_dev = (struct cam_ife_csid_hw *)platform_get_drvdata(pdev); + csid_hw_intf = csid_dev->hw_intf; + csid_hw_info = csid_dev->hw_info; + + CAM_DBG(CAM_CUSTOM, "CSID:%d remove", + csid_dev->hw_intf->hw_idx); + + cam_ife_csid_hw_deinit(csid_dev); + + /*release the csid device memory */ + kfree(csid_dev); + kfree(csid_hw_info); + kfree(csid_hw_intf); + return 0; +} + +static const struct of_device_id cam_custom_csid_dt_match[] = { + { + .compatible = "qcom,csid-custom480", + .data = &cam_custom_csid480_hw_info + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_custom_csid_dt_match); + +static struct platform_driver cam_custom_csid_driver = { + .probe = cam_custom_csid_probe, + .driver = { + .name = "qcom,custom-csid", + .of_match_table = cam_custom_csid_dt_match, + .suppress_bind_attrs = true, + }, + .remove = cam_custom_csid_remove, +}; + +static int __init cam_custom_csid_driver_init(void) +{ + int32_t rc = 0; + + rc = platform_driver_register(&cam_custom_csid_driver); + if (rc < 0) + CAM_ERR(CAM_CUSTOM, "platform_driver_register Failed: rc = %d", + rc); + + return rc; +} + +int cam_custom_csid_hw_init(struct cam_hw_intf **custom_csid_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_custom_csid_hw_list[hw_idx]) { + *custom_csid_hw = cam_custom_csid_hw_list[hw_idx]; + } else { + *custom_csid_hw = NULL; + rc = -1; + } + + return rc; +} + +static void __exit cam_custom_csid_driver_exit(void) +{ + platform_driver_unregister(&cam_custom_csid_driver); +} + +module_init(cam_custom_csid_driver_init); +module_exit(cam_custom_csid_driver_exit); +MODULE_DESCRIPTION("cam_custom_csid_driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h new file mode 100644 index 000000000000..f0c086ccab18 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_DEV_H_ +#define _CAM_IFE_CSID_DEV_H_ + +#include "cam_debug_util.h" +#include "cam_custom_hw_mgr_intf.h" + +#endif /*_CAM_IFE_CSID_DEV_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile new file mode 100644 index 000000000000..4895219ffd06 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1 + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_sub_mod_soc.o cam_custom_sub_mod_dev.o cam_custom_sub_mod_core.o diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c new file mode 100644 index 000000000000..9ac5da25571e --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "cam_custom_sub_mod_core.h" + +int cam_custom_hw_sub_mod_get_hw_caps(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + /* Add HW Capabilities to be published */ + return rc; +} + +int cam_custom_hw_sub_mod_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *custom_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_custom_resource_node *custom_res = NULL; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + mutex_lock(&custom_hw->hw_mutex); + custom_hw->open_count++; + if (custom_hw->open_count > 1) { + mutex_unlock(&custom_hw->hw_mutex); + CAM_DBG(CAM_CUSTOM, + "Cam Custom has already been initialized cnt %d", + custom_hw->open_count); + return 0; + } + mutex_unlock(&custom_hw->hw_mutex); + + soc_info = &custom_hw->soc_info; + + /* Turn ON Regulators, Clocks and other SOC resources */ + rc = cam_custom_hw_sub_mod_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Enable SOC failed"); + rc = -EFAULT; + goto decrement_open_cnt; + } + + custom_res = (struct cam_custom_resource_node *)init_hw_args; + if (custom_res && custom_res->init) { + rc = custom_res->init(custom_res, NULL, 0); + if (rc) { + CAM_ERR(CAM_CUSTOM, "init Failed rc=%d", rc); + goto decrement_open_cnt; + } + } + + rc = cam_custom_hw_sub_mod_reset(hw_priv, NULL, 0); + if (rc < 0) { + CAM_ERR(CAM_CUSTOM, "Custom HW reset failed : %d", rc); + goto decrement_open_cnt; + } + /* Initialize all resources here */ + custom_hw->hw_state = CAM_HW_STATE_POWER_UP; + return rc; + +decrement_open_cnt: + mutex_lock(&custom_hw->hw_mutex); + custom_hw->open_count--; + mutex_unlock(&custom_hw->hw_mutex); + return rc; +} + +int cam_custom_hw_sub_mod_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *custom_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_custom_resource_node *custom_res = NULL; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + mutex_lock(&custom_hw->hw_mutex); + if (!custom_hw->open_count) { + mutex_unlock(&custom_hw->hw_mutex); + CAM_ERR(CAM_CUSTOM, "Error! Unbalanced deinit"); + return -EFAULT; + } + custom_hw->open_count--; + if (custom_hw->open_count) { + mutex_unlock(&custom_hw->hw_mutex); + CAM_DBG(CAM_CUSTOM, + "open_cnt non-zero =%d", custom_hw->open_count); + return 0; + } + mutex_unlock(&custom_hw->hw_mutex); + + soc_info = &custom_hw->soc_info; + + custom_res = (struct cam_custom_resource_node *)deinit_hw_args; + if (custom_res && custom_res->deinit) { + rc = custom_res->deinit(custom_res, NULL, 0); + if (rc) + CAM_ERR(CAM_CUSTOM, "deinit failed"); + } + + rc = cam_custom_hw_sub_mod_reset(hw_priv, NULL, 0); + + /* Turn OFF Regulators, Clocks and other SOC resources */ + CAM_DBG(CAM_CUSTOM, "Disable SOC resource"); + rc = cam_custom_hw_sub_mod_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_CUSTOM, "Disable SOC failed"); + + custom_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + + return rc; +} + +int cam_custom_hw_sub_mod_reset(void *hw_priv, + void *reserve_args, uint32_t arg_size) +{ + struct cam_hw_info *custom_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_CUSTOM, "Invalid input arguments"); + return -EINVAL; + } + + soc_info = &custom_hw->soc_info; + /* Do Reset of HW */ + return rc; +} + +int cam_custom_hw_sub_mod_reserve(void *hw_priv, + void *reserve_args, uint32_t arg_size) +{ + int rc = 0; + + if (!hw_priv || !reserve_args) { + CAM_ERR(CAM_CUSTOM, "Invalid input arguments"); + return -EINVAL; + } + + /*Reserve Args */ + return rc; +} + + +int cam_custom_hw_sub_mod_release(void *hw_priv, + void *release_args, uint32_t arg_size) +{ + struct cam_hw_info *custom_hw = hw_priv; + int rc = 0; + + if (!hw_priv || !release_args) { + CAM_ERR(CAM_CUSTOM, "Invalid input arguments"); + return -EINVAL; + } + + mutex_lock(&custom_hw->hw_mutex); + /* Release Resources */ + mutex_unlock(&custom_hw->hw_mutex); + + return rc; +} + + +int cam_custom_hw_sub_mod_start(void *hw_priv, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *custom_hw = hw_priv; + int rc = 0; + + if (!hw_priv || !start_args) { + CAM_ERR(CAM_CUSTOM, "Invalid input arguments"); + return -EINVAL; + } + + mutex_lock(&custom_hw->hw_mutex); + /* Start HW -- Stream On*/ + mutex_unlock(&custom_hw->hw_mutex); + + return rc; +} + +int cam_custom_hw_sub_mod_stop(void *hw_priv, + void *stop_args, uint32_t arg_size) +{ + struct cam_hw_info *custom_hw = hw_priv; + int rc = 0; + + if (!hw_priv || !stop_args) { + CAM_ERR(CAM_CUSTOM, "Invalid input arguments"); + return -EINVAL; + } + + mutex_lock(&custom_hw->hw_mutex); + /* Stop HW */ + mutex_unlock(&custom_hw->hw_mutex); + + return rc; +} + +int cam_custom_hw_sub_mod_read(void *hw_priv, + void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_custom_hw_sub_mod_write(void *hw_priv, + void *write_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_custom_hw_submit_req(void *hw_priv, void *hw_submit_args, + uint32_t arg_size) +{ + struct cam_hw_info *custom_dev = hw_priv; + struct cam_custom_sub_mod_req_to_dev *submit_req = + (struct cam_custom_sub_mod_req_to_dev *)hw_submit_args; + struct cam_custom_sub_mod_core_info *core_info = NULL; + + core_info = + (struct cam_custom_sub_mod_core_info *)custom_dev->core_info; + + spin_lock(&custom_dev->hw_lock); + if (core_info->curr_req) { + CAM_WARN(CAM_CUSTOM, "Req %lld still processed by %s", + core_info->curr_req->req_id, + custom_dev->soc_info.dev_name); + spin_unlock(&custom_dev->hw_lock); + return -EAGAIN; + } + + core_info->curr_req = submit_req; + spin_unlock(&custom_dev->hw_lock); + + /* Do other submit procedures */ + return 0; +} + +irqreturn_t cam_custom_hw_sub_mod_irq(int irq_num, void *data) +{ + struct cam_hw_info *custom_dev = data; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_custom_hw_cb_args cb_args; + struct cam_custom_sub_mod_core_info *core_info = NULL; + uint32_t irq_status = 0; + + if (!data) { + CAM_ERR(CAM_CUSTOM, "Invalid custom_dev_info"); + return IRQ_HANDLED; + } + + soc_info = &custom_dev->soc_info; + core_info = + (struct cam_custom_sub_mod_core_info *)custom_dev->core_info; + + irq_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + core_info->device_hw_info->irq_status); + + cam_io_w_mb(irq_status, + soc_info->reg_map[0].mem_base + + core_info->device_hw_info->irq_clear); + + spin_lock(&custom_dev->hw_lock); + cb_args.irq_status = irq_status; + cb_args.req_info = core_info->curr_req; + core_info->curr_req = NULL; + if (core_info->irq_cb.custom_hw_mgr_cb) + core_info->irq_cb.custom_hw_mgr_cb( + core_info->irq_cb.data, &cb_args); + spin_unlock(&custom_dev->hw_lock); + + return IRQ_HANDLED; +} + +int cam_custom_hw_sub_mod_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_custom_sub_mod_core_info *core_info = NULL; + unsigned long flag = 0; + int rc = 0; + + if (!hw_priv || !cmd_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + soc_info = &hw->soc_info; + core_info = hw->core_info; + /* Handle any custom process cmds */ + + switch (cmd_type) { + case CAM_CUSTOM_SET_IRQ_CB: { + struct cam_custom_sub_mod_set_irq_cb *irq_cb = cmd_args; + + CAM_DBG(CAM_CUSTOM, "Setting irq cb"); + spin_lock_irqsave(&hw->hw_lock, flag); + core_info->irq_cb.custom_hw_mgr_cb = irq_cb->custom_hw_mgr_cb; + core_info->irq_cb.data = irq_cb->data; + spin_unlock_irqrestore(&hw->hw_lock, flag); + break; + } + case CAM_CUSTOM_SUBMIT_REQ: { + rc = cam_custom_hw_submit_req(hw_priv, cmd_args, arg_size); + break; + } + default: + break; + } + + return rc; +} + + diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h new file mode 100644 index 000000000000..d27d578f6c8d --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_SUB_MOD_CORE_H_ +#define _CAM_CUSTOM_SUB_MOD_CORE_H_ + +#include "cam_debug_util.h" +#include "cam_custom_hw.h" +#include "cam_custom_sub_mod_soc.h" +#include "cam_custom_hw_mgr_intf.h" + +struct cam_custom_sub_mod_set_irq_cb { + int32_t (*custom_hw_mgr_cb)(void *data, + struct cam_custom_hw_cb_args *cb_args); + void *data; +}; + +struct cam_custom_sub_mod_req_to_dev { + uint64_t req_id; + uint32_t ctx_idx; + uint32_t dev_idx; +}; + +struct cam_custom_device_hw_info { + uint32_t hw_ver; + uint32_t irq_status; + uint32_t irq_mask; + uint32_t irq_clear; +}; + +struct cam_custom_sub_mod_core_info { + uint32_t cpas_handle; + bool cpas_start; + bool clk_enable; + struct cam_custom_sub_mod_set_irq_cb irq_cb; + struct cam_custom_sub_mod_req_to_dev *curr_req; + struct cam_custom_device_hw_info *device_hw_info; + struct cam_hw_info *custom_hw_info; +}; + +enum cam_custom_hw_resource_type { + CAM_CUSTOM_HW_RESOURCE_UNINT, + CAM_CUSTOM_HW_RESOURCE_SRC, + CAM_CUSTOM_HW_RESOURCE_MAX, +}; + +struct cam_custom_sub_mod_acq { + enum cam_custom_hw_resource_type rsrc_type; + int32_t acq; + struct cam_custom_resource_node *rsrc_node; +}; + +int cam_custom_hw_sub_mod_get_hw_caps(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_reset(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_reserve(void *hw_priv, + void *reserve_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_release(void *hw_priv, + void *release_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_start(void *hw_priv, + void *start_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_stop(void *hw_priv, + void *stop_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_read(void *hw_priv, + void *read_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_write(void *hw_priv, + void *write_args, uint32_t arg_size); +int cam_custom_hw_sub_mod_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); +irqreturn_t cam_custom_hw_sub_mod_irq(int irq_num, void *data); + +#endif /* _CAM_CUSTOM_SUB_MOD_CORE_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c new file mode 100644 index 000000000000..bd7d65913649 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include "cam_custom_sub_mod_dev.h" +#include "cam_custom_sub_mod_core.h" +#include "cam_custom_sub_mod_soc.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_custom_hw_sub_mod_list + [CAM_CUSTOM_SUB_MOD_MAX_INSTANCES] = {0, 0}; + +static char cam_custom_hw_sub_mod_name[8]; + +struct cam_custom_device_hw_info cam_custom_hw_info = { + .hw_ver = 0x0, + .irq_status = 0x0, + .irq_mask = 0x0, + .irq_clear = 0x0, +}; +EXPORT_SYMBOL(cam_custom_hw_info); + +int cam_custom_hw_sub_mod_init(struct cam_hw_intf **custom_hw, uint32_t hw_idx) +{ + int rc = 0; + + if (cam_custom_hw_sub_mod_list[hw_idx]) { + *custom_hw = cam_custom_hw_sub_mod_list[hw_idx]; + rc = 0; + } else { + *custom_hw = NULL; + rc = -ENODEV; + } + return 0; +} + +int cam_custom_hw_sub_mod_probe(struct platform_device *pdev) +{ + struct cam_hw_info *hw = NULL; + struct cam_hw_intf *hw_intf = NULL; + struct cam_custom_sub_mod_core_info *core_info = NULL; + int rc = 0; + + hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!hw_intf) + return -ENOMEM; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &hw_intf->hw_idx); + + hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!hw) { + rc = -ENOMEM; + goto free_hw_intf; + } + + memset(cam_custom_hw_sub_mod_name, 0, + sizeof(cam_custom_hw_sub_mod_name)); + snprintf(cam_custom_hw_sub_mod_name, sizeof(cam_custom_hw_sub_mod_name), + "custom_hw%1u", hw_intf->hw_idx); + + hw->soc_info.pdev = pdev; + hw->soc_info.dev = &pdev->dev; + hw->soc_info.dev_name = cam_custom_hw_sub_mod_name; + hw_intf->hw_priv = hw; + hw_intf->hw_ops.get_hw_caps = cam_custom_hw_sub_mod_get_hw_caps; + hw_intf->hw_ops.init = cam_custom_hw_sub_mod_init_hw; + hw_intf->hw_ops.deinit = cam_custom_hw_sub_mod_deinit_hw; + hw_intf->hw_ops.reset = cam_custom_hw_sub_mod_reset; + hw_intf->hw_ops.reserve = cam_custom_hw_sub_mod_reserve; + hw_intf->hw_ops.release = cam_custom_hw_sub_mod_release; + hw_intf->hw_ops.start = cam_custom_hw_sub_mod_start; + hw_intf->hw_ops.stop = cam_custom_hw_sub_mod_stop; + hw_intf->hw_ops.read = cam_custom_hw_sub_mod_read; + hw_intf->hw_ops.write = cam_custom_hw_sub_mod_write; + hw_intf->hw_ops.process_cmd = cam_custom_hw_sub_mod_process_cmd; + hw_intf->hw_type = CAM_CUSTOM_HW_TYPE_1; + + platform_set_drvdata(pdev, hw_intf); + + hw->core_info = kzalloc(sizeof(struct cam_custom_sub_mod_core_info), + GFP_KERNEL); + if (!hw->core_info) { + CAM_DBG(CAM_CUSTOM, "Failed to alloc for core"); + rc = -ENOMEM; + goto free_hw; + } + core_info = (struct cam_custom_sub_mod_core_info *)hw->core_info; + + core_info->custom_hw_info = hw; + + rc = cam_custom_hw_sub_mod_init_soc_resources(&hw->soc_info, + cam_custom_hw_sub_mod_irq, hw); + if (rc < 0) { + CAM_ERR(CAM_CUSTOM, "Failed to init soc rc=%d", rc); + goto free_core_info; + } + + /* Initialize HW */ + + hw->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&hw->hw_mutex); + spin_lock_init(&hw->hw_lock); + init_completion(&hw->hw_complete); + + if (hw_intf->hw_idx < CAM_CUSTOM_HW_SUB_MOD_MAX) + cam_custom_hw_sub_mod_list[hw_intf->hw_idx] = hw_intf; + + /* needs to be invoked when custom hw is in place */ + //cam_custom_hw_sub_mod_init_hw(hw, NULL, 0); + + CAM_DBG(CAM_CUSTOM, "Custom hw_idx[%d] probe successful", + hw_intf->hw_idx); + return rc; + +free_core_info: + kfree(hw->core_info); +free_hw: + kfree(hw); +free_hw_intf: + kfree(hw_intf); + return rc; +} + +static const struct of_device_id cam_custom_hw_sub_mod_dt_match[] = { + { + .compatible = "qcom,cam_custom_hw_sub_mod", + .data = &cam_custom_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_custom_hw_sub_mod_dt_match); + +static struct platform_driver cam_custom_hw_sub_mod_driver = { + .probe = cam_custom_hw_sub_mod_probe, + .driver = { + .name = CAM_CUSTOM_SUB_MOD_NAME, + .of_match_table = cam_custom_hw_sub_mod_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_custom_hw_sub_module_init(void) +{ + return platform_driver_register(&cam_custom_hw_sub_mod_driver); +} + +static void __exit cam_custom_hw_sub_module_exit(void) +{ + platform_driver_unregister(&cam_custom_hw_sub_mod_driver); +} + +module_init(cam_custom_hw_sub_module_init); +module_exit(cam_custom_hw_sub_module_exit); +MODULE_DESCRIPTION("CAM CUSTOM HW SUB MODULE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h new file mode 100644 index 000000000000..1da630ed5ec2 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_SUB_MOD_DEV_H_ +#define _CAM_CUSTOM_SUB_MOD_DEV_H_ + +#include "cam_custom_hw_mgr_intf.h" + +#define CAM_CUSTOM_SUB_MOD_NAME "cam_custom_sub_mod" + +#define CAM_CUSTOM_SUB_MOD_MAX_INSTANCES 2 + +#endif /* _CAM_CUSTOM_SUB_MOD_DEV_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c new file mode 100644 index 000000000000..0b517b93c6c0 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_cpas_api.h" +#include "cam_custom_sub_mod_soc.h" +#include "cam_debug_util.h" + +int cam_custom_hw_sub_mod_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, void *irq_data) +{ + int rc = 0; + struct cam_custom_hw_soc_private *soc_private = NULL; + struct cam_cpas_register_params cpas_register_param; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_CUSTOM, + "Error! Get DT properties failed rc=%d", rc); + /* For Test Purposes */ + return 0; + } + + soc_private = kzalloc(sizeof(struct cam_custom_hw_soc_private), + GFP_KERNEL); + if (!soc_private) { + CAM_DBG(CAM_CUSTOM, "Error! soc_private Alloc Failed"); + return -ENOMEM; + } + soc_info->soc_private = soc_private; + + rc = cam_soc_util_request_platform_resource(soc_info, irq_handler, + irq_data); + if (rc < 0) { + CAM_ERR(CAM_CUSTOM, + "Error! Request platform resources failed rc=%d", rc); + return rc; + } + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + + cpas_register_param.cell_index = soc_info->index; + cpas_register_param.dev = soc_info->dev; + cpas_register_param.cam_cpas_client_cb = NULL; + cpas_register_param.userdata = soc_info; + soc_private->cpas_handle = + cpas_register_param.client_handle; + + rc = cam_cpas_register_client(&cpas_register_param); + if (rc < 0) + goto release_soc; + + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} + +int cam_custom_hw_sub_mod_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_custom_hw_soc_private *soc_private = NULL; + + if (!soc_info) { + CAM_ERR(CAM_CUSTOM, "Error! soc_info NULL"); + return -ENODEV; + } + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_CUSTOM, "Error! soc_private NULL"); + return -ENODEV; + } + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_CUSTOM, "CPAS0 unregistration failed rc=%d", rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc < 0) + CAM_ERR(CAM_CUSTOM, + "Error! Release platform resources failed rc=%d", rc); + + kfree(soc_private); + + return rc; +} + +int cam_custom_hw_sub_mod_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_custom_hw_soc_private *soc_private = soc_info->soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; + axi_vote.num_paths = 2; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = 7200000; + axi_vote.axi_path[0].mnoc_ab_bw = 7200000; + axi_vote.axi_path[0].mnoc_ib_bw = 7200000; + axi_vote.axi_path[1].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[1].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[1].camnoc_bw = 512000000; + axi_vote.axi_path[1].mnoc_ab_bw = 512000000; + axi_vote.axi_path[1].mnoc_ib_bw = 512000000; + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Error! CPAS0 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) { + CAM_ERR(CAM_CUSTOM, "Error! enable platform failed rc=%d", rc); + goto stop_cpas; + } + + return 0; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); +end: + return rc; +} + +int cam_custom_hw_sub_mod_disable_soc_resources( + struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_custom_hw_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_CUSTOM, "Error! Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Disable platform failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Error! CPAS stop failed rc=%d", rc); + return rc; + } + + return rc; +} diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.h new file mode 100644 index 000000000000..e9c95d43d366 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_HW_SUB_MOD_SOC_H_ +#define _CAM_CUSTOM_HW_SUB_MOD_SOC_H_ + +#include "cam_soc_util.h" +/* + * struct cam_custom_hw_soc_private: + * + * @Brief: Private SOC data specific to Custom HW Driver + * + * @cpas_handle: Handle returned on registering with CPAS driver. + * This handle is used for all further interface + * with CPAS. + */ +struct cam_custom_hw_soc_private { + uint32_t cpas_handle; +}; + +int cam_custom_hw_sub_mod_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler, void *irq_data); + +int cam_custom_hw_sub_mod_deinit_soc_resources( + struct cam_hw_soc_info *soc_info); + +int cam_custom_hw_sub_mod_enable_soc_resources( + struct cam_hw_soc_info *soc_info); + +int cam_custom_hw_sub_mod_disable_soc_resources( + struct cam_hw_soc_info *soc_info); + +#endif /* _CAM_CUSTOM_HW_SUB_MOD_SOC_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c new file mode 100644 index 000000000000..1db06bb3ab1f --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -0,0 +1,1329 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cam_sync_api.h" +#include "cam_smmu_api.h" +#include "cam_req_mgr_workq.h" +#include "cam_custom_hw_mgr.h" +#include "cam_packet_util.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_mem_mgr_api.h" +#include "cam_common_util.h" +#include "cam_hw.h" + +static struct cam_custom_hw_mgr g_custom_hw_mgr; + +static int cam_custom_mgr_get_hw_caps(void *hw_mgr_priv, + void *hw_caps_args) +{ + int rc = 0; + struct cam_custom_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query = hw_caps_args; + struct cam_custom_query_cap_cmd custom_hw_cap; + struct cam_hw_info *cam_custom_hw; + struct cam_hw_soc_info *soc_info_hw; + + cam_custom_hw = (struct cam_hw_info *) + g_custom_hw_mgr.custom_hw[0]->hw_priv; + if (cam_custom_hw) + soc_info_hw = &cam_custom_hw->soc_info; + + CAM_DBG(CAM_CUSTOM, "enter"); + + if (query->handle_type != CAM_HANDLE_USER_POINTER) + CAM_ERR(CAM_CUSTOM, "Wrong Args"); + + if (copy_from_user(&custom_hw_cap, + u64_to_user_ptr(query->caps_handle), + sizeof(struct cam_custom_query_cap_cmd))) { + rc = -EFAULT; + return rc; + } + + custom_hw_cap.device_iommu.non_secure = hw_mgr->img_iommu_hdl; + custom_hw_cap.device_iommu.secure = -1; + + /* Initializing cdm handles to -1 */ + custom_hw_cap.cdm_iommu.non_secure = -1; + custom_hw_cap.cdm_iommu.secure = -1; + + custom_hw_cap.num_dev = 1; + custom_hw_cap.dev_caps[0].hw_type = 0; + custom_hw_cap.dev_caps[0].hw_version = 0; + + if (copy_to_user(u64_to_user_ptr(query->caps_handle), + &custom_hw_cap, sizeof(struct cam_custom_query_cap_cmd))) + rc = -EFAULT; + + CAM_DBG(CAM_CUSTOM, "exit rc :%d", rc); + return rc; +} + +enum cam_custom_hw_resource_state + cam_custom_hw_mgr_get_custom_res_state( + uint32_t in_rsrc_state) +{ + enum cam_custom_hw_resource_state rsrc_state; + + CAM_DBG(CAM_CUSTOM, "rsrc_state %x", in_rsrc_state); + + switch (in_rsrc_state) { + case CAM_ISP_RESOURCE_STATE_UNAVAILABLE: + rsrc_state = CAM_CUSTOM_HW_RESOURCE_STATE_UNAVAILABLE; + break; + case CAM_ISP_RESOURCE_STATE_AVAILABLE: + rsrc_state = CAM_CUSTOM_HW_RESOURCE_STATE_AVAILABLE; + break; + case CAM_ISP_RESOURCE_STATE_RESERVED: + rsrc_state = CAM_CUSTOM_HW_RESOURCE_STATE_RESERVED; + break; + case CAM_ISP_RESOURCE_STATE_INIT_HW: + rsrc_state = CAM_CUSTOM_HW_RESOURCE_STATE_INIT_HW; + break; + case CAM_ISP_RESOURCE_STATE_STREAMING: + rsrc_state = CAM_CUSTOM_HW_RESOURCE_STATE_STREAMING; + break; + default: + rsrc_state = CAM_CUSTOM_HW_RESOURCE_STATE_UNAVAILABLE; + CAM_DBG(CAM_CUSTOM, "invalid rsrc type"); + break; + } + + return rsrc_state; +} + +enum cam_isp_resource_state + cam_custom_hw_mgr_get_isp_res_state( + uint32_t in_rsrc_state) +{ + enum cam_isp_resource_state rsrc_state; + + CAM_DBG(CAM_CUSTOM, "rsrc_state %x", in_rsrc_state); + + switch (in_rsrc_state) { + case CAM_CUSTOM_HW_RESOURCE_STATE_UNAVAILABLE: + rsrc_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + break; + case CAM_CUSTOM_HW_RESOURCE_STATE_AVAILABLE: + rsrc_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + break; + case CAM_CUSTOM_HW_RESOURCE_STATE_RESERVED: + rsrc_state = CAM_ISP_RESOURCE_STATE_RESERVED; + break; + case CAM_CUSTOM_HW_RESOURCE_STATE_INIT_HW: + rsrc_state = CAM_ISP_RESOURCE_STATE_INIT_HW; + break; + case CAM_CUSTOM_HW_RESOURCE_STATE_STREAMING: + rsrc_state = CAM_ISP_RESOURCE_STATE_STREAMING; + break; + default: + rsrc_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + CAM_DBG(CAM_CUSTOM, "invalid rsrc type"); + break; + } + + return rsrc_state; +} + +enum cam_isp_resource_type + cam_custom_hw_mgr_get_isp_res_type( + enum cam_custom_hw_mgr_res_type res_type) +{ + switch (res_type) { + case CAM_CUSTOM_CID_HW: + return CAM_ISP_RESOURCE_CID; + case CAM_CUSTOM_CSID_HW: + return CAM_ISP_RESOURCE_PIX_PATH; + default: + return CAM_ISP_RESOURCE_MAX; + } +} + +static int cam_custom_hw_mgr_deinit_hw_res( + struct cam_custom_hw_mgr_res *hw_mgr_res) +{ + int rc = -1; + struct cam_isp_resource_node *isp_rsrc_node = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_rsrc_node = + (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; + if (!isp_rsrc_node) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + hw_intf = isp_rsrc_node->hw_intf; + if (hw_intf->hw_ops.deinit) { + CAM_DBG(CAM_CUSTOM, "DEINIT HW for res_id:%u", + hw_mgr_res->res_id); + rc = hw_intf->hw_ops.deinit(hw_intf->hw_priv, + isp_rsrc_node, sizeof(struct cam_isp_resource_node)); + if (rc) + goto err; + } + + return 0; + +err: + CAM_DBG(CAM_CUSTOM, "DEINIT HW failed for res_id:%u", + hw_mgr_res->res_id); + return rc; +} + +static int cam_custom_hw_mgr_stop_hw_res( + struct cam_custom_hw_mgr_res *hw_mgr_res) +{ + int rc = -1; + struct cam_csid_hw_stop_args stop_cmd; + struct cam_isp_resource_node *isp_rsrc_node = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_rsrc_node = + (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; + if (!isp_rsrc_node) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + hw_intf = isp_rsrc_node->hw_intf; + if (hw_intf->hw_ops.stop) { + CAM_DBG(CAM_CUSTOM, "STOP HW for res_id:%u", + hw_mgr_res->res_id); + stop_cmd.num_res = 1; + stop_cmd.node_res = &isp_rsrc_node; + stop_cmd.stop_cmd = CAM_CSID_HALT_AT_FRAME_BOUNDARY; + rc = hw_intf->hw_ops.stop(hw_intf->hw_priv, + &stop_cmd, sizeof(struct cam_csid_hw_stop_args)); + if (rc) + goto err; + } + + return 0; + +err: + CAM_DBG(CAM_CUSTOM, "STOP HW failed for res_id:%u", + hw_mgr_res->res_id); + return rc; +} + +static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) +{ + int rc = 0; + struct cam_hw_stop_args *stop_args = stop_hw_args; + struct cam_custom_hw_mgr_res *hw_mgr_res; + struct cam_custom_hw_mgr_ctx *ctx; + + if (!hw_mgr_priv || !stop_hw_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_custom_hw_mgr_ctx *) + stop_args->ctxt_to_hw_map; + + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_CUSTOM, " Enter...ctx id:%d", ctx->ctx_index); + + /* Stop custom cid here */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_cid, list) { + rc = cam_custom_hw_mgr_stop_hw_res(hw_mgr_res); + if (rc) + CAM_ERR(CAM_CUSTOM, "failed to stop hw %d", + hw_mgr_res->res_id); + } + + /* Stop custom csid here */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_csid, list) { + rc = cam_custom_hw_mgr_stop_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_CUSTOM, "failed to stop hw %d", + hw_mgr_res->res_id); + } + } + + + /* stop custom hw here */ + + /* Deinit custom cid here */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_cid, list) { + rc = cam_custom_hw_mgr_deinit_hw_res(hw_mgr_res); + if (rc) + CAM_ERR(CAM_CUSTOM, "failed to stop hw %d", + hw_mgr_res->res_id); + } + + /* Deinit custom csid here */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_csid, list) { + rc = cam_custom_hw_mgr_deinit_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_CUSTOM, "failed to stop hw %d", + hw_mgr_res->res_id); + } + } + + /* deinit custom rsrc */ + + return rc; +} + +static int cam_custom_hw_mgr_init_hw_res( + struct cam_custom_hw_mgr_res *hw_mgr_res) +{ + int rc = -1; + struct cam_isp_resource_node *isp_rsrc_node = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_rsrc_node = + (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; + if (!isp_rsrc_node) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + hw_intf = isp_rsrc_node->hw_intf; + if (hw_intf->hw_ops.init) { + CAM_DBG(CAM_CUSTOM, "INIT HW for res_id:%u", + hw_mgr_res->res_id); + rc = hw_intf->hw_ops.init(hw_intf->hw_priv, + isp_rsrc_node, sizeof(struct cam_isp_resource_node)); + if (rc) + goto err; + } + + return 0; + +err: + CAM_DBG(CAM_CUSTOM, "INIT HW failed for res_id:%u", + hw_mgr_res->res_id); + return rc; +} + +static int cam_custom_hw_mgr_start_hw_res( + struct cam_custom_hw_mgr_res *hw_mgr_res) +{ + int rc = -1; + struct cam_isp_resource_node *isp_rsrc_node = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_rsrc_node = + (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; + if (!isp_rsrc_node) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + hw_intf = isp_rsrc_node->hw_intf; + if (hw_intf->hw_ops.start) { + CAM_DBG(CAM_CUSTOM, "Start HW for res_id:%u", + hw_mgr_res->res_id); + rc = hw_intf->hw_ops.start(hw_intf->hw_priv, + isp_rsrc_node, sizeof(struct cam_isp_resource_node)); + if (rc) + goto err; + } + + return 0; + +err: + CAM_DBG(CAM_CUSTOM, "START HW failed for res_id:%u", + hw_mgr_res->res_id); + return rc; +} + +static int cam_custom_mgr_start_hw(void *hw_mgr_priv, + void *start_hw_args) +{ + int rc = 0; + struct cam_hw_config_args *hw_config; + struct cam_hw_stop_args stop_args; + struct cam_custom_hw_mgr_res *hw_mgr_res; + struct cam_custom_hw_mgr_ctx *ctx; + + if (!hw_mgr_priv || !start_hw_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + hw_config = (struct cam_hw_config_args *)start_hw_args; + + ctx = (struct cam_custom_hw_mgr_ctx *) + hw_config->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_CUSTOM, "Enter... ctx id:%d", + ctx->ctx_index); + + /* Init custom cid */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_cid, list) { + rc = cam_custom_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT CID(id :%d)", + hw_mgr_res->res_id); + goto deinit_hw; + } + } + + /* Init custom csid */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_csid, list) { + rc = cam_custom_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT CSID(id :%d)", + hw_mgr_res->res_id); + goto deinit_hw; + } + } + + + /* Init custom hw here */ + + /* Apply init config */ + + /* Start custom HW first */ + if (rc < 0) + goto err; + + /* Start custom csid */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_csid, list) { + rc = cam_custom_hw_mgr_start_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not START CSID(id :%d)", + hw_mgr_res->res_id); + goto err; + } + } + + /* Start custom cid */ + list_for_each_entry(hw_mgr_res, + &ctx->res_list_custom_cid, list) { + rc = cam_custom_hw_mgr_start_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not START CID(id :%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_CUSTOM, "Start success for ctx id:%d", ctx->ctx_index); + return 0; + +err: + stop_args.ctxt_to_hw_map = hw_config->ctxt_to_hw_map; + cam_custom_mgr_stop_hw(hw_mgr_priv, &stop_args); +deinit_hw: + /* deinit the hw previously initialized */ + CAM_DBG(CAM_CUSTOM, "Exit...(rc=%d)", rc); + return rc; +} + +static int cam_custom_mgr_read(void *hw_mgr_priv, void *read_args) +{ + return -EPERM; +} + +static int cam_custom_mgr_write(void *hw_mgr_priv, void *write_args) +{ + return -EPERM; +} + +static int cam_custom_hw_mgr_put_ctx( + struct list_head *src_list, + struct cam_custom_hw_mgr_ctx **custom_ctx) +{ + struct cam_custom_hw_mgr_ctx *ctx_ptr = NULL; + + ctx_ptr = *custom_ctx; + if (ctx_ptr) + list_add_tail(&ctx_ptr->list, src_list); + *custom_ctx = NULL; + return 0; +} + +static int cam_custom_hw_mgr_get_ctx( + struct list_head *src_list, + struct cam_custom_hw_mgr_ctx **custom_ctx) +{ + struct cam_custom_hw_mgr_ctx *ctx_ptr = NULL; + + if (!list_empty(src_list)) { + ctx_ptr = list_first_entry(src_list, + struct cam_custom_hw_mgr_ctx, list); + list_del_init(&ctx_ptr->list); + } else { + CAM_ERR(CAM_CUSTOM, "No more free custom hw mgr ctx"); + return -EINVAL; + } + *custom_ctx = ctx_ptr; + memset(ctx_ptr->sub_hw_list, 0, + sizeof(struct cam_custom_hw_mgr_res) * + CAM_CUSTOM_HW_RES_MAX); + + return 0; +} + +static int cam_custom_hw_mgr_put_res( + struct list_head *src_list, + struct cam_custom_hw_mgr_res **res) +{ + struct cam_custom_hw_mgr_res *res_ptr = NULL; + + res_ptr = *res; + if (res_ptr) + list_add_tail(&res_ptr->list, src_list); + + return 0; +} + +static int cam_custom_hw_mgr_get_res( + struct list_head *src_list, + struct cam_custom_hw_mgr_res **res) +{ + int rc = 0; + struct cam_custom_hw_mgr_res *res_ptr = NULL; + + if (!list_empty(src_list)) { + res_ptr = list_first_entry(src_list, + struct cam_custom_hw_mgr_res, list); + list_del_init(&res_ptr->list); + } else { + CAM_ERR(CAM_CUSTOM, "No more free custom ctx rsrc"); + rc = -1; + } + *res = res_ptr; + + return rc; +} + +static enum cam_ife_pix_path_res_id + cam_custom_hw_mgr_get_csid_res_type( + uint32_t out_port_type) +{ + enum cam_ife_pix_path_res_id path_id; + + CAM_DBG(CAM_CUSTOM, "out_port_type %x", out_port_type); + + switch (out_port_type) { + case CAM_CUSTOM_OUT_RES_UDI_0: + path_id = CAM_IFE_PIX_PATH_RES_UDI_0; + break; + case CAM_CUSTOM_OUT_RES_UDI_1: + path_id = CAM_IFE_PIX_PATH_RES_UDI_1; + break; + case CAM_CUSTOM_OUT_RES_UDI_2: + path_id = CAM_IFE_PIX_PATH_RES_UDI_2; + break; + default: + path_id = CAM_IFE_PIX_PATH_RES_MAX; + CAM_DBG(CAM_CUSTOM, "maximum rdi output type exceeded"); + break; + } + + CAM_DBG(CAM_CUSTOM, "out_port %x path_id %d", out_port_type, path_id); + + return path_id; +} + +static int cam_custom_hw_mgr_acquire_cid_res( + struct cam_custom_hw_mgr_ctx *custom_ctx, + struct cam_isp_in_port_generic_info *in_port, + struct cam_custom_hw_mgr_res **cid_res, + enum cam_ife_pix_path_res_id path_res_id, + struct cam_isp_resource_node **cid_rsrc_node) +{ + int rc = -1; + int i; + struct cam_custom_hw_mgr *custom_hw_mgr; + struct cam_hw_intf *hw_intf; + struct cam_custom_hw_mgr_res *cid_res_temp; + struct cam_csid_hw_reserve_resource_args csid_acquire; + struct cam_isp_resource_node *isp_rsrc_node; + struct cam_isp_out_port_generic_info *out_port = NULL; + + custom_hw_mgr = custom_ctx->hw_mgr; + *cid_res = NULL; + + rc = cam_custom_hw_mgr_get_res( + &custom_ctx->free_res_list, cid_res); + if (rc) { + CAM_ERR(CAM_CUSTOM, "No more free hw mgr resource"); + goto end; + } + + memset(&csid_acquire, 0, sizeof(csid_acquire)); + cid_res_temp = *cid_res; + csid_acquire.res_type = CAM_ISP_RESOURCE_CID; + csid_acquire.in_port = in_port; + csid_acquire.res_id = path_res_id; + csid_acquire.node_res = NULL; + CAM_DBG(CAM_CUSTOM, "path_res_id %d", path_res_id); + + if (in_port->num_out_res) + out_port = &(in_port->data[0]); + + for (i = 0; i < CAM_CUSTOM_CSID_HW_MAX; i++) { + if (!custom_hw_mgr->csid_devices[i]) + continue; + + hw_intf = custom_hw_mgr->csid_devices[i]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + /* since there is a need of 1 cid at this stage */ + if (rc) + continue; + else + break; + + } + + if (!csid_acquire.node_res) { + CAM_ERR(CAM_CUSTOM, + "Can not acquire custom cid resource for path %d", + path_res_id); + rc = -EAGAIN; + goto put_res; + } + + *cid_rsrc_node = csid_acquire.node_res; + isp_rsrc_node = csid_acquire.node_res; + cid_res_temp->rsrc_node = isp_rsrc_node; + cid_res_temp->res_type = CAM_CUSTOM_CID_HW; + cid_res_temp->res_id = isp_rsrc_node->res_id; + cam_custom_hw_mgr_put_res(&custom_ctx->res_list_custom_cid, + &cid_res_temp); + + CAM_DBG(CAM_CUSTOM, "CID acquired successfully %u", + isp_rsrc_node->res_id); + + return 0; + +put_res: + cam_custom_hw_mgr_put_res(&custom_ctx->free_res_list, cid_res); +end: + return rc; + +} + +static int cam_custom_hw_mgr_acquire_csid_res( + struct cam_custom_hw_mgr_ctx *custom_ctx, + struct cam_isp_in_port_generic_info *in_port_info) +{ + int rc = 0, i = 0; + struct cam_custom_hw_mgr *custom_hw_mgr; + struct cam_isp_out_port_generic_info *out_port; + struct cam_custom_hw_mgr_res *custom_csid_res; + struct cam_custom_hw_mgr_res *custom_cid_res; + struct cam_hw_intf *hw_intf; + struct cam_csid_hw_reserve_resource_args custom_csid_acquire; + enum cam_ife_pix_path_res_id path_res_id; + struct cam_isp_resource_node *isp_rsrc_node; + struct cam_isp_resource_node *cid_rsrc_node = NULL; + + custom_hw_mgr = custom_ctx->hw_mgr; + + for (i = 0; i < in_port_info->num_out_res; i++) { + out_port = &in_port_info->data[i]; + path_res_id = cam_custom_hw_mgr_get_csid_res_type( + out_port->res_type); + + if (path_res_id == CAM_IFE_PIX_PATH_RES_MAX) { + CAM_WARN(CAM_CUSTOM, "Invalid out port res_type %u", + out_port->res_type); + continue; + } + + rc = cam_custom_hw_mgr_acquire_cid_res(custom_ctx, in_port_info, + &custom_cid_res, path_res_id, &cid_rsrc_node); + if (rc) { + CAM_ERR(CAM_CUSTOM, "No free cid rsrc %d", rc); + goto end; + } + + rc = cam_custom_hw_mgr_get_res(&custom_ctx->free_res_list, + &custom_csid_res); + if (rc) { + CAM_ERR(CAM_CUSTOM, "No more free hw mgr rsrc"); + goto end; + } + + memset(&custom_csid_acquire, 0, sizeof(custom_csid_acquire)); + custom_csid_acquire.res_id = path_res_id; + custom_csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; + custom_csid_acquire.cid = cid_rsrc_node->res_id; + custom_csid_acquire.in_port = in_port_info; + custom_csid_acquire.out_port = out_port; + custom_csid_acquire.sync_mode = 0; + custom_csid_acquire.node_res = NULL; + + hw_intf = cid_rsrc_node->hw_intf; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &custom_csid_acquire, sizeof(custom_csid_acquire)); + if (rc) { + CAM_ERR(CAM_CUSTOM, + "Custom csid acquire failed for hw_idx %u rc %d", + hw_intf->hw_idx, rc); + goto put_res; + } + + if (custom_csid_acquire.node_res == NULL) { + CAM_ERR(CAM_CUSTOM, "Acquire custom csid failed"); + rc = -EAGAIN; + goto put_res; + } + + isp_rsrc_node = custom_csid_acquire.node_res; + custom_csid_res->rsrc_node = isp_rsrc_node; + custom_csid_res->res_type = CAM_CUSTOM_CSID_HW; + custom_csid_res->res_id = custom_csid_acquire.res_id; + cam_custom_hw_mgr_put_res( + &custom_ctx->res_list_custom_csid, + &custom_csid_res); + CAM_DBG(CAM_CUSTOM, "Custom CSID acquired for path %d", + path_res_id); + } + + return 0; + +put_res: + cam_custom_hw_mgr_put_res(&custom_ctx->free_res_list, + &custom_csid_res); +end: + return rc; +} + +static int cam_custom_hw_mgr_free_hw_res( + struct cam_custom_hw_mgr_res *hw_mgr_res) +{ + int rc = 0; + struct cam_isp_resource_node *isp_rsrc_node = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_rsrc_node = + (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; + if (!isp_rsrc_node) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + hw_intf = isp_rsrc_node->hw_intf; + if (hw_intf->hw_ops.release) { + CAM_DBG(CAM_CUSTOM, "RELEASE HW for res_id:%u", + hw_mgr_res->res_id); + rc = hw_intf->hw_ops.release(hw_intf->hw_priv, + isp_rsrc_node, sizeof(struct cam_isp_resource_node)); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Release HW failed for hw_idx %d", + hw_intf->hw_idx); + } + + /* caller should make sure the resource is in a list */ + list_del_init(&hw_mgr_res->list); + memset(hw_mgr_res, 0, sizeof(*hw_mgr_res)); + INIT_LIST_HEAD(&hw_mgr_res->list); + + return 0; +} + +static int cam_custom_hw_mgr_release_hw_for_ctx( + struct cam_custom_hw_mgr_ctx *custom_ctx) +{ + int rc = -1; + struct cam_custom_hw_mgr_res *hw_mgr_res; + struct cam_custom_hw_mgr_res *hw_mgr_res_temp; + + /* Release custom cid */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &custom_ctx->res_list_custom_cid, list) { + rc = cam_custom_hw_mgr_free_hw_res(hw_mgr_res); + if (rc) + CAM_ERR(CAM_ISP, "Can not release CID(id :%d)", + hw_mgr_res->res_id); + cam_custom_hw_mgr_put_res( + &custom_ctx->free_res_list, &hw_mgr_res); + } + + /* Release custom csid */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &custom_ctx->res_list_custom_csid, list) { + rc = cam_custom_hw_mgr_free_hw_res(hw_mgr_res); + if (rc) + CAM_ERR(CAM_ISP, "Can not release CSID(id :%d)", + hw_mgr_res->res_id); + cam_custom_hw_mgr_put_res( + &custom_ctx->free_res_list, &hw_mgr_res); + } + + /* Release custom HW Here */ + + return 0; +} +static int cam_custom_mgr_release_hw(void *hw_mgr_priv, + void *release_hw_args) +{ + int rc = 0; + struct cam_hw_release_args *release_args = release_hw_args; + struct cam_custom_hw_mgr_ctx *custom_ctx; + + if (!hw_mgr_priv || !release_hw_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + custom_ctx = + (struct cam_custom_hw_mgr_ctx *)release_args->ctxt_to_hw_map; + if (!custom_ctx || !custom_ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_CUSTOM, "Enter...ctx id:%d", + custom_ctx->ctx_index); + + cam_custom_hw_mgr_release_hw_for_ctx(custom_ctx); + list_del_init(&custom_ctx->list); + custom_ctx->ctx_in_use = 0; + cam_custom_hw_mgr_put_ctx(&g_custom_hw_mgr.free_ctx_list, &custom_ctx); + CAM_DBG(CAM_CUSTOM, "Release Exit.."); + return rc; +} + +static void cam_custom_hw_mgr_acquire_get_unified_dev_str( + struct cam_custom_in_port_info *in, + struct cam_isp_in_port_generic_info *gen_port_info) +{ + int i; + + gen_port_info->res_type = in->res_type + + CAM_ISP_IFE_IN_RES_BASE - CAM_CUSTOM_IN_RES_BASE; + gen_port_info->lane_type = in->lane_type; + gen_port_info->lane_num = in->lane_num; + gen_port_info->lane_cfg = in->lane_cfg; + gen_port_info->vc[0] = in->vc[0]; + gen_port_info->dt[0] = in->dt[0]; + gen_port_info->num_valid_vc_dt = in->num_valid_vc_dt; + gen_port_info->format = in->format; + gen_port_info->test_pattern = in->test_pattern; + gen_port_info->usage_type = in->usage_type; + gen_port_info->left_start = in->left_start; + gen_port_info->left_stop = in->left_stop; + gen_port_info->left_width = in->left_width; + gen_port_info->right_start = in->right_start; + gen_port_info->right_stop = in->right_stop; + gen_port_info->right_width = in->right_width; + gen_port_info->line_start = in->line_start; + gen_port_info->line_stop = in->line_stop; + gen_port_info->height = in->height; + gen_port_info->pixel_clk = in->pixel_clk; + gen_port_info->cust_node = 1; + gen_port_info->num_out_res = in->num_out_res; + gen_port_info->num_bytes_out = in->num_bytes_out; + + for (i = 0; i < in->num_out_res; i++) { + gen_port_info->data[i].res_type = in->data[i].res_type; + gen_port_info->data[i].format = in->data[i].format; + } +} + +static int cam_custom_mgr_acquire_hw_for_ctx( + struct cam_custom_hw_mgr_ctx *custom_ctx, + struct cam_isp_in_port_generic_info *in_port_info, + uint32_t *acquired_hw_id, uint32_t *acquired_hw_path) +{ + int rc = 0, i = 0; + struct cam_hw_intf *hw_intf; + struct cam_custom_hw_mgr *custom_hw_mgr; + struct cam_custom_sub_mod_acq acq; + + custom_hw_mgr = custom_ctx->hw_mgr; + + /* Acquire custom csid */ + rc = cam_custom_hw_mgr_acquire_csid_res(custom_ctx, in_port_info); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Custom csid acquire failed rc %d"); + goto err; + } + + /* Acquire custom hw */ + for (i = 0; i < CAM_CUSTOM_HW_SUB_MOD_MAX; i++) { + hw_intf = custom_hw_mgr->custom_hw[i]; + if (!hw_intf) + continue; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &acq, sizeof(acq)); + if (rc) { + CAM_DBG(CAM_CUSTOM, + "No custom resource from hw %d", + hw_intf->hw_idx); + continue; + } + /* need to be set in reserve based on HW being acquired */ + //custom_ctx->sub_hw_list[i].hw_res = acq.rsrc_node; + //custom_ctx->sub_hw_list[i].res_type = + //custom_ctx->sub_hw_list[i].res_id = ; + break; + } + +err: + return rc; +} + +static int cam_custom_mgr_acquire_hw( + void *hw_mgr_priv, + void *acquire_hw_args) +{ + int rc = -1; + int32_t i; + uint32_t in_port_length; + struct cam_custom_hw_mgr_ctx *custom_ctx; + struct cam_custom_hw_mgr *custom_hw_mgr; + struct cam_hw_acquire_args *acquire_args = + (struct cam_hw_acquire_args *) acquire_hw_args; + struct cam_custom_in_port_info *in_port_info; + struct cam_custom_resource *custom_rsrc; + struct cam_isp_in_port_generic_info *gen_port_info = NULL; + + if (!hw_mgr_priv || !acquire_args || (acquire_args->num_acq <= 0)) { + CAM_ERR(CAM_CUSTOM, "Invalid params"); + return -EINVAL; + } + + custom_hw_mgr = (struct cam_custom_hw_mgr *) hw_mgr_priv; + mutex_lock(&g_custom_hw_mgr.ctx_mutex); + rc = cam_custom_hw_mgr_get_ctx( + &custom_hw_mgr->free_ctx_list, &custom_ctx); + if (rc || !custom_ctx) { + CAM_ERR(CAM_CUSTOM, "Get custom hw context failed"); + mutex_unlock(&g_custom_hw_mgr.ctx_mutex); + goto err; + } + mutex_unlock(&g_custom_hw_mgr.ctx_mutex); + + /* Handle Acquire Here */ + custom_ctx->hw_mgr = custom_hw_mgr; + custom_ctx->cb_priv = acquire_args->context_data; + custom_ctx->event_cb = acquire_args->event_cb; + + custom_rsrc = kcalloc(acquire_args->num_acq, + sizeof(*custom_rsrc), GFP_KERNEL); + if (!custom_rsrc) { + rc = -ENOMEM; + goto free_ctx; + } + + CAM_DBG(CAM_CUSTOM, "start copy %d resources from user", + acquire_args->num_acq); + + if (copy_from_user(custom_rsrc, + (void __user *)acquire_args->acquire_info, + ((sizeof(*custom_rsrc)) * acquire_args->num_acq))) { + rc = -EFAULT; + goto free_ctx; + } + + for (i = 0; i < acquire_args->num_acq; i++) { + if (custom_rsrc[i].resource_id != CAM_CUSTOM_RES_ID_PORT) + continue; + + CAM_DBG(CAM_CUSTOM, "acquire no = %d total = %d", i, + acquire_args->num_acq); + + CAM_DBG(CAM_CUSTOM, + "start copy from user handle %lld with len = %d", + custom_rsrc[i].res_hdl, + custom_rsrc[i].length); + + in_port_length = sizeof(struct cam_custom_in_port_info); + if (in_port_length > custom_rsrc[i].length) { + CAM_ERR(CAM_CUSTOM, "buffer size is not enough"); + rc = -EINVAL; + goto free_res; + } + + in_port_info = memdup_user( + u64_to_user_ptr(custom_rsrc[i].res_hdl), + custom_rsrc[i].length); + + if (!IS_ERR(in_port_info)) { + if (in_port_info->num_out_res > + CAM_CUSTOM_HW_OUT_RES_MAX) { + CAM_ERR(CAM_CUSTOM, "too many output res %d", + in_port_info->num_out_res); + rc = -EINVAL; + kfree(in_port_info); + goto free_res; + } + + in_port_length = + sizeof(struct cam_custom_in_port_info) + + (in_port_info->num_out_res - 1) * + sizeof(struct cam_custom_out_port_info); + + if (in_port_length > custom_rsrc[i].length) { + CAM_ERR(CAM_CUSTOM, + "buffer size is not enough"); + rc = -EINVAL; + kfree(in_port_info); + goto free_res; + } + + gen_port_info = kzalloc( + sizeof(struct cam_isp_in_port_generic_info), + GFP_KERNEL); + if (gen_port_info == NULL) { + rc = -ENOMEM; + goto free_res; + } + + gen_port_info->data = kcalloc( + sizeof(struct cam_isp_out_port_generic_info), + in_port_info->num_out_res, GFP_KERNEL); + if (gen_port_info->data == NULL) { + kfree(gen_port_info); + gen_port_info = NULL; + rc = -ENOMEM; + goto free_res; + } + + cam_custom_hw_mgr_acquire_get_unified_dev_str( + in_port_info, gen_port_info); + + rc = cam_custom_mgr_acquire_hw_for_ctx(custom_ctx, + gen_port_info, &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + + kfree(in_port_info); + if (gen_port_info != NULL) { + kfree(gen_port_info->data); + kfree(gen_port_info); + gen_port_info = NULL; + } + + if (rc) { + CAM_ERR(CAM_CUSTOM, "can not acquire resource"); + goto free_res; + } + } else { + CAM_ERR(CAM_CUSTOM, + "Copy from user failed with in_port = %pK", + in_port_info); + rc = -EFAULT; + goto free_res; + } + } + + custom_ctx->ctx_in_use = 1; + acquire_args->ctxt_to_hw_map = custom_ctx; + CAM_DBG(CAM_CUSTOM, "Exit...(success)"); + return 0; + +free_res: + cam_custom_hw_mgr_release_hw_for_ctx(custom_ctx); +free_ctx: + cam_custom_hw_mgr_put_ctx(&custom_hw_mgr->free_ctx_list, &custom_ctx); +err: + CAM_DBG(CAM_CUSTOM, "Exit...(rc=%d)", rc); + return rc; +} + +static int cam_custom_add_io_buffers( + int iommu_hdl, + struct cam_hw_prepare_update_args *prepare) +{ + int rc = 0, i = 0; + int32_t hdl; + uint32_t plane_id; + struct cam_buf_io_cfg *io_cfg; + + io_cfg = (struct cam_buf_io_cfg *)((uint8_t *) + &prepare->packet->payload + + prepare->packet->io_configs_offset); + + /* Validate hw update entries */ + + for (i = 0; i < prepare->packet->num_io_configs; i++) { + CAM_DBG(CAM_CUSTOM, "======= io config idx %d ============", i); + CAM_DBG(CAM_CUSTOM, + "i %d req_id %llu resource_type:%d fence:%d direction %d", + i, prepare->packet->header.request_id, + io_cfg[i].resource_type, io_cfg[i].fence, + io_cfg[i].direction); + + CAM_DBG(CAM_CUSTOM, "format: %d", io_cfg[i].format); + + if (io_cfg[i].direction == CAM_BUF_OUTPUT) { + CAM_DBG(CAM_CUSTOM, + "output fence 0x%x", io_cfg[i].fence); + } else if (io_cfg[i].direction == CAM_BUF_INPUT) { + CAM_DBG(CAM_CUSTOM, + "input fence 0x%x", io_cfg[i].fence); + } else { + CAM_ERR(CAM_CUSTOM, "Invalid io config direction :%d", + io_cfg[i].direction); + return -EINVAL; + } + + for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) { + if (!io_cfg[i].mem_handle[plane_id]) + continue; + + hdl = io_cfg[i].mem_handle[plane_id]; + CAM_DBG(CAM_CUSTOM, "handle 0x%x for plane %d", + hdl, plane_id); + /* Use cam_mem_get_io_buf() to retrieve iova */ + } + + /* Do other I/O config operations */ + } + + return rc; +} + +static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, + void *prepare_hw_update_args) +{ + int rc = 0; + struct cam_hw_prepare_update_args *prepare; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_custom_prepare_hw_update_data *prepare_hw_data; + struct cam_custom_hw_mgr *hw_mgr; + struct cam_custom_hw_mgr_ctx *ctx = NULL; + uint32_t *ptr; + size_t len; + struct cam_custom_cmd_buf_type_1 *custom_buf_type1; + + if (!hw_mgr_priv || !prepare_hw_update_args) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + hw_mgr = (struct cam_custom_hw_mgr *) hw_mgr_priv; + prepare = + (struct cam_hw_prepare_update_args *) prepare_hw_update_args; + + CAM_DBG(CAM_CUSTOM, "Enter for req_id %lld", + prepare->packet->header.request_id); + + /* Prepare packet */ + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *)prepare->priv; + prepare_hw_data->packet_opcode_type = + (prepare->packet->header.op_code & 0xFFF); + ctx = (struct cam_custom_hw_mgr_ctx *) prepare->ctxt_to_hw_map; + + /* Test purposes-check the data in cmd buffer */ + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint8_t *)&prepare->packet->payload + + prepare->packet->cmd_buf_offset); + rc = cam_packet_util_get_cmd_mem_addr( + cmd_desc->mem_handle, &ptr, &len); + if (!rc) { + ptr += (cmd_desc->offset / 4); + custom_buf_type1 = + (struct cam_custom_cmd_buf_type_1 *)ptr; + CAM_DBG(CAM_CUSTOM, "frame num %u", + custom_buf_type1->custom_info); + } + + cam_custom_add_io_buffers(hw_mgr->img_iommu_hdl, prepare); + return 0; +} + +static int cam_custom_mgr_config_hw(void *hw_mgr_priv, + void *hw_config_args) +{ + int rc = 0; + int i = 0; + struct cam_custom_hw_mgr_ctx *custom_ctx; + struct cam_custom_hw_mgr_res *res; + struct cam_hw_config_args *cfg; + struct cam_hw_intf *hw_intf = NULL; + + CAM_DBG(CAM_CUSTOM, "Enter"); + if (!hw_mgr_priv || !hw_config_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + cfg = + (struct cam_hw_config_args *)hw_config_args; + custom_ctx = cfg->ctxt_to_hw_map; + + if (!custom_ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Invalid context parameters"); + return -EPERM; + } + + for (i = 0; i < CAM_CUSTOM_HW_SUB_MOD_MAX; i++) { + res = &custom_ctx->sub_hw_list[i]; + if (res->hw_res) { + hw_intf = res->hw_res->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + struct cam_custom_sub_mod_req_to_dev req_to_dev; + + req_to_dev.ctx_idx = custom_ctx->ctx_index; + req_to_dev.dev_idx = i; + req_to_dev.req_id = cfg->request_id; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_CUSTOM_SUBMIT_REQ, + &req_to_dev, sizeof(req_to_dev)); + } + } + } + + return rc; +} + +static int cam_custom_hw_mgr_irq_cb(void *data, + struct cam_custom_hw_cb_args *cb_args) +{ + struct cam_custom_sub_mod_req_to_dev *proc_req; + struct cam_hw_done_event_data evt_data; + struct cam_custom_hw_mgr_ctx *custom_ctx; + uint32_t ctx_idx; + + proc_req = cb_args->req_info; + ctx_idx = proc_req->ctx_idx; + custom_ctx = &g_custom_hw_mgr.ctx_pool[ctx_idx]; + + if (!custom_ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "ctx %u not in use", ctx_idx); + return 0; + } + + /* Based on irq status notify success/failure */ + + evt_data.request_id = proc_req->req_id; + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_EVENT_BUF_DONE, &evt_data); + + return 0; +} + +int cam_custom_hw_mgr_init(struct device_node *of_node, + struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) +{ + int rc = 0; + int i, j; + struct cam_custom_hw_mgr_ctx *ctx_pool; + struct cam_custom_sub_mod_set_irq_cb irq_cb_args; + struct cam_hw_intf *hw_intf = NULL; + + memset(&g_custom_hw_mgr, 0, sizeof(g_custom_hw_mgr)); + mutex_init(&g_custom_hw_mgr.ctx_mutex); + + /* fill custom hw intf information */ + for (i = 0; i < CAM_CUSTOM_HW_SUB_MOD_MAX; i++) { + /* Initialize sub modules */ + rc = cam_custom_hw_sub_mod_init( + &g_custom_hw_mgr.custom_hw[i], i); + + /* handle in case init fails */ + if (g_custom_hw_mgr.custom_hw[i]) { + hw_intf = g_custom_hw_mgr.custom_hw[i]; + if (hw_intf->hw_ops.process_cmd) { + irq_cb_args.custom_hw_mgr_cb = + cam_custom_hw_mgr_irq_cb; + irq_cb_args.data = + g_custom_hw_mgr.custom_hw[i]->hw_priv; + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_CUSTOM_SET_IRQ_CB, &irq_cb_args, + sizeof(irq_cb_args)); + } + } + } + + for (i = 0; i < CAM_CUSTOM_CSID_HW_MAX; i++) { + /* Initialize csid custom modules */ + rc = cam_custom_csid_hw_init( + &g_custom_hw_mgr.csid_devices[i], i); + } + + INIT_LIST_HEAD(&g_custom_hw_mgr.free_ctx_list); + INIT_LIST_HEAD(&g_custom_hw_mgr.used_ctx_list); + + /* + * for now, we only support one iommu handle. later + * we will need to setup more iommu handle for other + * use cases. + * Also, we have to release them once we have the + * deinit support + */ + if (cam_smmu_get_handle("custom", + &g_custom_hw_mgr.img_iommu_hdl)) { + CAM_ERR(CAM_CUSTOM, "Can not get iommu handle"); + return -EINVAL; + } + + for (i = 0; i < CAM_CTX_MAX; i++) { + memset(&g_custom_hw_mgr.ctx_pool[i], 0, + sizeof(g_custom_hw_mgr.ctx_pool[i])); + INIT_LIST_HEAD(&g_custom_hw_mgr.ctx_pool[i].list); + + ctx_pool = &g_custom_hw_mgr.ctx_pool[i]; + + /* init context pool */ + INIT_LIST_HEAD(&g_custom_hw_mgr.ctx_pool[i].free_res_list); + INIT_LIST_HEAD( + &g_custom_hw_mgr.ctx_pool[i].res_list_custom_csid); + INIT_LIST_HEAD( + &g_custom_hw_mgr.ctx_pool[i].res_list_custom_cid); + for (j = 0; j < CAM_CUSTOM_HW_RES_MAX; j++) { + INIT_LIST_HEAD( + &g_custom_hw_mgr.ctx_pool[i].res_pool[j].list); + list_add_tail( + &g_custom_hw_mgr.ctx_pool[i].res_pool[j].list, + &g_custom_hw_mgr.ctx_pool[i].free_res_list); + } + + g_custom_hw_mgr.ctx_pool[i].ctx_index = i; + g_custom_hw_mgr.ctx_pool[i].hw_mgr = &g_custom_hw_mgr; + + list_add_tail(&g_custom_hw_mgr.ctx_pool[i].list, + &g_custom_hw_mgr.free_ctx_list); + } + + /* fill return structure */ + hw_mgr_intf->hw_mgr_priv = &g_custom_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_custom_mgr_get_hw_caps; + hw_mgr_intf->hw_acquire = cam_custom_mgr_acquire_hw; + hw_mgr_intf->hw_start = cam_custom_mgr_start_hw; + hw_mgr_intf->hw_stop = cam_custom_mgr_stop_hw; + hw_mgr_intf->hw_read = cam_custom_mgr_read; + hw_mgr_intf->hw_write = cam_custom_mgr_write; + hw_mgr_intf->hw_release = cam_custom_mgr_release_hw; + hw_mgr_intf->hw_prepare_update = cam_custom_mgr_prepare_hw_update; + hw_mgr_intf->hw_config = cam_custom_mgr_config_hw; + + if (iommu_hdl) + *iommu_hdl = g_custom_hw_mgr.img_iommu_hdl; + + CAM_DBG(CAM_CUSTOM, "HW manager initialized"); + return 0; +} diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h new file mode 100644 index 000000000000..64f4555528bf --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_HW_MGR_H_ +#define _CAM_CUSTOM_HW_MGR_H_ + +#include +#include "cam_custom_hw_mgr_intf.h" +#include "cam_custom_sub_mod_core.h" +#include "cam_ife_csid_hw_intf.h" +#include "cam_isp_hw.h" +#include "cam_custom_hw.h" +#include +#include + +enum cam_custom_hw_mgr_res_type { + CAM_CUSTOM_HW_SUB_MODULE, + CAM_CUSTOM_CID_HW, + CAM_CUSTOM_CSID_HW, + CAM_CUSTOM_HW_MAX, +}; + +/* Needs to be suitably defined */ +#define CAM_CUSTOM_HW_OUT_RES_MAX 1 + +/** + * struct cam_custom_hw_mgr_res - HW resources for the Custom manager + * + * @list: used by the resource list + * @res_type: Custom manager resource type + * @res_id: resource id based on the resource type for root or + * leaf resource, it matches the KMD interface port id. + * For branch resource, it is defined by the Custom HW + * layer + * @rsrc_node: isp hw layer resource for csid/cid + * @hw_res: hw layer resource array. + */ +struct cam_custom_hw_mgr_res { + struct list_head list; + enum cam_custom_hw_mgr_res_type res_type; + uint32_t res_id; + void *rsrc_node; + struct cam_custom_resource_node *hw_res; +}; + + +/** + * struct ctx_base_info - Base hardware information for the context + * + * @idx: Base resource index + * + */ +struct ctx_base_info { + uint32_t idx; +}; + + +/** + * struct cam_custom_hw_mgr_ctx - Custom HW manager ctx object + * + * @list: used by the ctx list. + * @ctx_index: acquired context id. + * @hw_mgr: Custom hw mgr which owns this context + * @ctx_in_use: flag to tell whether context is active + * @res_list_custom_csid: custom csid modules for this context + * @res_list_custom_cid: custom cid modules for this context + * @sub_hw_list: HW submodules for this context + * @free_res_list: Free resources list for the branch node + * @res_pool: memory storage for the free resource list + * @base: device base index array contain the all + * Custom HW instance associated with this ctx. + * @num_base: number of valid base data in the base array + * @init_done: indicate whether init hw is done + * @event_cb: event_cb to ctx + * @cb_priv: data sent back with event_cb + * + */ +struct cam_custom_hw_mgr_ctx { + struct list_head list; + + uint32_t ctx_index; + struct cam_custom_hw_mgr *hw_mgr; + uint32_t ctx_in_use; + + struct list_head res_list_custom_csid; + struct list_head res_list_custom_cid; + struct cam_custom_hw_mgr_res sub_hw_list[ + CAM_CUSTOM_HW_RES_MAX]; + + struct list_head free_res_list; + struct cam_custom_hw_mgr_res res_pool[CAM_CUSTOM_HW_RES_MAX]; + struct ctx_base_info base[CAM_CUSTOM_HW_SUB_MOD_MAX]; + uint32_t num_base; + bool init_done; + cam_hw_event_cb_func event_cb; + void *cb_priv; +}; + +/** + * struct cam_custom_hw_mgr - Custom HW Manager + * + * @img_iommu_hdl: iommu handle + * @custom_hw: Custom device instances array. This will be filled by + * HW layer during initialization + * @csid_devices: Custom csid device instance array + * @ctx_mutex: mutex for the hw context pool + * @free_ctx_list: free hw context list + * @used_ctx_list: used hw context list + * @ctx_pool: context storage + * + */ +struct cam_custom_hw_mgr { + int img_iommu_hdl; + struct cam_hw_intf *custom_hw[CAM_CUSTOM_HW_SUB_MOD_MAX]; + struct cam_hw_intf *csid_devices[CAM_CUSTOM_CSID_HW_MAX]; + struct mutex ctx_mutex; + struct list_head free_ctx_list; + struct list_head used_ctx_list; + struct cam_custom_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; +}; + +/** + * cam_custom_hw_mgr_init() + * + * @brief: Initialize the Custom hardware manger. This is the + * etnry functinon for the Cust HW manager. + * + * @of_node: Device node + * @hw_mgr_intf: Custom hardware manager object returned + * @iommu_hdl: Iommu handle to be returned + * + */ +int cam_custom_hw_mgr_init(struct device_node *of_node, + struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); + + +/* Utility APIs */ + +/** + * cam_custom_hw_mgr_get_custom_res_state() + * + * @brief: Obtain equivalent custom rsrc state + * from isp rsrc state + * + * @in_rsrc_state: isp rsrc state + * + */ +enum cam_custom_hw_resource_state + cam_custom_hw_mgr_get_custom_res_state( + uint32_t in_rsrc_state); + +/** + * cam_custom_hw_mgr_get_isp_res_state() + * + * @brief: Obtain equivalent isp rsrc state + * from custom rsrc state + * + * @in_rsrc_state: custom rsrc state + * + */ +enum cam_isp_resource_state + cam_custom_hw_mgr_get_isp_res_state( + uint32_t in_rsrc_state); + +/** + * cam_custom_hw_mgr_get_isp_res_type() + * + * @brief: Obtain equivalent isp rsrc type + * from custom rsrc type + * + * @res_type: custom rsrc type + * + */ +enum cam_isp_resource_type + cam_custom_hw_mgr_get_isp_res_type( + enum cam_custom_hw_mgr_res_type res_type); + +#endif /* _CAM_CUSTOM_HW_MGR_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h new file mode 100644 index 000000000000..0fd557c14052 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_HW_H_ +#define _CAM_CUSTOM_HW_H_ + +#include +#include +#include +#include + +enum cam_custom_hw_resource_state { + CAM_CUSTOM_HW_RESOURCE_STATE_UNAVAILABLE = 0, + CAM_CUSTOM_HW_RESOURCE_STATE_AVAILABLE = 1, + CAM_CUSTOM_HW_RESOURCE_STATE_RESERVED = 2, + CAM_CUSTOM_HW_RESOURCE_STATE_INIT_HW = 3, + CAM_CUSTOM_HW_RESOURCE_STATE_STREAMING = 4, +}; + +/* + * struct cam_custom_resource_node: + * + * @Brief: Structure representing HW resource object + * + * @res_id: Unique resource ID within res_type objects + * for a particular HW + * @res_state: State of the resource + * @hw_intf: HW Interface of HW to which this resource + * belongs + * @res_priv: Private data of the resource + * @irq_handle: handle returned on subscribing for IRQ event + * @init: function pointer to init the HW resource + * @deinit: function pointer to deinit the HW resource + * @start: function pointer to start the HW resource + * @stop: function pointer to stop the HW resource + * @process_cmd: function pointer for processing commands + * specific to the resource + */ +struct cam_custom_resource_node { + uint32_t res_id; + enum cam_custom_hw_resource_state res_state; + struct cam_hw_intf *hw_intf; + void *res_priv; + int irq_handle; + + int (*init)(struct cam_custom_resource_node *rsrc_node, + void *init_args, uint32_t arg_size); + int (*deinit)(struct cam_custom_resource_node *rsrc_node, + void *deinit_args, uint32_t arg_size); + int (*start)(struct cam_custom_resource_node *rsrc_node); + int (*stop)(struct cam_custom_resource_node *rsrc_node); + int (*process_cmd)(struct cam_custom_resource_node *rsrc_node, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size); +}; +#endif /* _CAM_CUSTOM_HW_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h new file mode 100644 index 000000000000..b1fb1cb42913 --- /dev/null +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CUSTOM_HW_MGR_INTF_H_ +#define _CAM_CUSTOM_HW_MGR_INTF_H_ + +#include +#include +#include +#include +#include "cam_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" + +#define CAM_CUSTOM_HW_TYPE_1 1 + +#define CAM_CUSTOM_HW_RES_MAX 32 + +#define CAM_CUSTOM_HW_SUB_MOD_MAX 1 +#define CAM_CUSTOM_CSID_HW_MAX 1 + +enum cam_custom_hw_event_type { + CAM_CUSTOM_EVENT_TYPE_ERROR, + CAM_CUSTOM_EVENT_BUF_DONE, +}; + +enum cam_custom_cmd_types { + CAM_CUSTOM_CMD_NONE, + CAM_CUSTOM_SET_IRQ_CB, + CAM_CUSTOM_SUBMIT_REQ, +}; + +/** + * struct cam_custom_stop_args - hardware stop arguments + * + * @stop_only Send stop only to hw drivers. No Deinit to be + * done. + */ +struct cam_custom_stop_args { + bool stop_only; +}; + +/** + * struct cam_custom_start_args - custom hardware start arguments + * + * @hw_config: Hardware configuration commands. + * @start_only Send start only to hw drivers. No init to + * be done. + * + */ +struct cam_custom_start_args { + struct cam_hw_config_args hw_config; + bool start_only; +}; + +/** + * struct cam_custom_prepare_hw_update_data - hw prepare data + * + * @packet_opcode_type: Packet header opcode in the packet header + * this opcode defines, packet is init packet or + * update packet + * + */ +struct cam_custom_prepare_hw_update_data { + uint32_t packet_opcode_type; +}; + +/** + * struct cam_custom_hw_cb_args : HW manager callback args + * + * @irq_status : irq status + * @req_info : Pointer to the request info associated with the cb + */ +struct cam_custom_hw_cb_args { + uint32_t irq_status; + struct cam_custom_sub_mod_req_to_dev *req_info; +}; + +/** + * cam_custom_hw_sub_mod_init() + * + * @Brief: Initialize Custom HW device + * + * @custom_hw: cust_hw interface to fill in and return on + * successful initialization + * @hw_idx: Index of Custom HW + */ +int cam_custom_hw_sub_mod_init(struct cam_hw_intf **custom_hw, uint32_t hw_idx); + +/** + * cam_custom_csid_hw_init() + * + * @Brief: Initialize Custom HW device + * + * @custom_hw: cust_hw interface to fill in and return on + * successful initialization + * @hw_idx: Index of Custom HW + */ +int cam_custom_csid_hw_init( + struct cam_hw_intf **custom_hw, uint32_t hw_idx); + +#endif /* _CAM_CUSTOM_HW_MGR_INTF_H_ */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 40c9050afbb5..551bc85ae73c 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_INTERFACE_H @@ -151,6 +151,7 @@ enum cam_req_mgr_device_error { * @FLASH : LED flash or dual LED device * @ACTUATOR : lens mover * @IFE : Image processing device + * @CUSTOM : Custom HW block * @EXTERNAL_1 : third party device * @EXTERNAL_2 : third party device * @EXTERNAL_3 : third party device @@ -162,6 +163,7 @@ enum cam_req_mgr_device_id { CAM_REQ_MGR_DEVICE_FLASH, CAM_REQ_MGR_DEVICE_ACTUATOR, CAM_REQ_MGR_DEVICE_IFE, + CAM_REQ_MGR_DEVICE_CUSTOM_HW, CAM_REQ_MGR_DEVICE_EXTERNAL_1, CAM_REQ_MGR_DEVICE_EXTERNAL_2, CAM_REQ_MGR_DEVICE_EXTERNAL_3, diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index 3c178f1e77ac..274980f8bb64 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -91,6 +91,9 @@ const char *cam_get_module_name(unsigned int module_id) case CAM_REQ: name = "CAM-REQ"; break; + case CAM_CUSTOM: + name = "CAM-CUSTOM"; + break; default: name = "CAM"; break; diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 0491e6a214ac..181a1558a904 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -38,6 +38,7 @@ /* CAM_PERF: Used for performance (clock, BW etc) logs */ #define CAM_PERF (1 << 25) +#define CAM_CUSTOM (1 << 26) #define STR_BUFFER_MAX_LENGTH 1024 From 9556262e87effc7735455b6e16475a699b186caa Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 5 Aug 2019 19:18:44 -0700 Subject: [PATCH 075/790] msm: camera: ife: Correct sanitary check logic Current sanitary checks for integer overflow exhibit incorrect behavior if number of RDI/paths paths are filled in as zero. This change addresses that. CRs-Fixed: 2513939 Change-Id: Ib4cf369971f2d50be0ec167ff78f46fb0d985b33 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c9f950ca921a..941949aff311 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4846,7 +4846,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, } /* Check for integer overflow */ - if (clock_config->num_rdi != 1) { + if (clock_config->num_rdi > 1) { if (sizeof(uint64_t) > ((UINT_MAX - sizeof(struct cam_isp_clock_config)) / (clock_config->num_rdi - 1))) { @@ -4858,8 +4858,9 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, } } - if (blob_size < (sizeof(struct cam_isp_clock_config) + - sizeof(uint64_t) * (clock_config->num_rdi - 1))) { + if ((clock_config->num_rdi != 0) && (blob_size < + (sizeof(struct cam_isp_clock_config) + + sizeof(uint64_t) * (clock_config->num_rdi - 1)))) { CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", blob_size, sizeof(uint32_t) * 2 + sizeof(uint64_t) * @@ -4893,7 +4894,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, } /* Check for integer overflow */ - if (bw_config->num_rdi != 1) { + if (bw_config->num_rdi > 1) { if (sizeof(struct cam_isp_bw_vote) > ((UINT_MAX - sizeof(struct cam_isp_bw_config)) / (bw_config->num_rdi - 1))) { @@ -4905,9 +4906,10 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, } } - if (blob_size < (sizeof(struct cam_isp_bw_config) + + if ((bw_config->num_rdi != 0) && (blob_size < + (sizeof(struct cam_isp_bw_config) + (bw_config->num_rdi - 1) * - sizeof(struct cam_isp_bw_vote))) { + sizeof(struct cam_isp_bw_vote)))) { CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", blob_size, sizeof(struct cam_isp_bw_config) + (bw_config->num_rdi - 1) * @@ -4949,7 +4951,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, } /* Check for integer overflow */ - if (bw_config->num_paths != 1) { + if (bw_config->num_paths > 1) { if (sizeof(struct cam_axi_per_path_bw_vote) > ((UINT_MAX - sizeof(struct cam_isp_bw_config_v2)) / @@ -4963,8 +4965,9 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, } } - if (blob_size < (sizeof(struct cam_isp_bw_config_v2) + - ((bw_config->num_paths - 1) * + if ((bw_config->num_paths != 0) && (blob_size < + (sizeof(struct cam_isp_bw_config_v2) + + (bw_config->num_paths - 1) * sizeof(struct cam_axi_per_path_bw_vote)))) { CAM_ERR(CAM_ISP, "Invalid blob size: %u, num_paths: %u, bw_config size: %lu, per_path_vote size: %lu", From 6678f1003b26829dd6ca17455586c6861ce96d77 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 19 Aug 2019 12:55:04 -0700 Subject: [PATCH 076/790] msm: camera: ife: Use correct enum to convert resource ID to path Currently CSID path resource enum is being used to convert resource ID to path to notify UMD of acquired resources. This change addresses this inaccuracy. CRs-Fixed: 2513939 Change-Id: I8d31904dd9b8b500c3f4504142b153151cdcee71 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 62 ++++++++++++++------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 941949aff311..708390b72db8 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1327,34 +1327,56 @@ err: static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) { - if (hw_idx == 0) - return CAM_ISP_IFE0_HW; - else if (hw_idx == 1) - return CAM_ISP_IFE1_HW; - else if (hw_idx == 2) - return CAM_ISP_IFE0_LITE_HW; - else if (hw_idx == 3) - return CAM_ISP_IFE1_LITE_HW; - else if (hw_idx == 4) - return CAM_ISP_IFE2_LITE_HW; - return 0; + uint32_t hw_version, rc = 0; + + rc = cam_cpas_get_cpas_hw_version(&hw_version); + if (!rc) { + switch (hw_version) { + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_170_V120: + case CAM_CPAS_TITAN_175_V100: + case CAM_CPAS_TITAN_175_V101: + case CAM_CPAS_TITAN_175_V120: + case CAM_CPAS_TITAN_175_V130: + case CAM_CPAS_TITAN_480_V100: + if (hw_idx == 0) + return CAM_ISP_IFE0_HW; + else if (hw_idx == 1) + return CAM_ISP_IFE1_HW; + else if (hw_idx == 2) + return CAM_ISP_IFE0_LITE_HW; + else if (hw_idx == 3) + return CAM_ISP_IFE1_LITE_HW; + else if (hw_idx == 4) + return CAM_ISP_IFE2_LITE_HW; + break; + default: + CAM_ERR(CAM_ISP, "Invalid hw_version: 0x%X", + hw_version); + rc = -EINVAL; + break; + } + } + + return rc; } -static int cam_convert_res_id_to_hw_path(int path, bool acquire_lcr) +static int cam_convert_res_id_to_hw_path(int res_id) { - if (path == CAM_IFE_PIX_PATH_RES_IPP && acquire_lcr) + if (res_id == CAM_ISP_HW_VFE_IN_LCR) return CAM_ISP_LCR_PATH; - else if (path == CAM_IFE_PIX_PATH_RES_PPP) + else if (res_id == CAM_ISP_HW_VFE_IN_PDLIB) return CAM_ISP_PPP_PATH; - else if (path == CAM_IFE_PIX_PATH_RES_IPP) + else if (res_id == CAM_ISP_HW_VFE_IN_CAMIF) return CAM_ISP_PXL_PATH; - else if (path == CAM_IFE_PIX_PATH_RES_RDI_0) + else if (res_id == CAM_ISP_HW_VFE_IN_RDI0) return CAM_ISP_RDI0_PATH; - else if (path == CAM_IFE_PIX_PATH_RES_RDI_1) + else if (res_id == CAM_ISP_HW_VFE_IN_RDI1) return CAM_ISP_RDI1_PATH; - else if (path == CAM_IFE_PIX_PATH_RES_RDI_2) + else if (res_id == CAM_ISP_HW_VFE_IN_RDI2) return CAM_ISP_RDI2_PATH; - else if (path == CAM_IFE_PIX_PATH_RES_RDI_3) + else if (res_id == CAM_ISP_HW_VFE_IN_RDI3) return CAM_ISP_RDI3_PATH; return 0; } @@ -1480,7 +1502,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( } acquired_hw_path[i] |= cam_convert_res_id_to_hw_path( - ife_src_res->hw_res[i]->res_id, acquire_lcr); + ife_src_res->hw_res[i]->res_id); CAM_DBG(CAM_ISP, "acquire success IFE:%d res type :0x%x res id:0x%x", From 72eeacf17aa5cf2d6c76b06e1511a270ae4c7bdc Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 23 Aug 2019 17:28:48 -0700 Subject: [PATCH 077/790] msm: camera: common: Change log type to WARN When a request setting could not be applied by any device on the link, it does not indicate a fatal error. It only leads to a frame drop. Changing the apply failure logs to warn as opposed to error. CRs-Fixed: 2514752 Change-Id: Idbca2dbb06b0bbb4c380264cf31b665188306396 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 4 ++-- drivers/cam_req_mgr/cam_req_mgr_core.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 4144bfc62a64..718c01ec8ee5 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3841,14 +3841,14 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx, if (ctx_ops->crm_ops.apply_req) { rc = ctx_ops->crm_ops.apply_req(ctx, apply); } else { - CAM_ERR_RATE_LIMIT(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "No handle function in activated substate %d", ctx_isp->substate_activated); rc = -EFAULT; } if (rc) - CAM_ERR_RATE_LIMIT(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Apply failed in active substate %d rc %d", ctx_isp->substate_activated, rc); return rc; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 6a8e5fed6e67..cce35d45b581 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -631,7 +631,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, } } if (rc < 0) { - CAM_ERR_RATE_LIMIT(CAM_CRM, "APPLY FAILED pd %d req_id %lld", + CAM_WARN_RATE_LIMIT(CAM_CRM, "APPLY FAILED pd %d req_id %lld", dev->dev_info.p_delay, apply_req.request_id); /* Apply req failed notify already applied devs */ for (; i >= 0; i--) { From e8bc3c7cbca4ce790fdc8171d63e1a658cdda8c6 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 28 Aug 2019 16:05:02 -0700 Subject: [PATCH 078/790] msm: camera: ife: Add event count in error log This change adds event count in the error log that is printed when difference between the counts for the two full IFEs is greater than one in dual IFE mode. CRs-Fixed: 2513939 Change-Id: I4346406f36eae72e55f07bdb185a7f85566a4f37 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 708390b72db8..ad07052d7345 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6182,8 +6182,9 @@ static int cam_ife_hw_mgr_check_irq_for_dual_vfe( (event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "One of the VFE could not generate hw event %d", - hw_event_type); + "One of the VFE could not generate hw event %d core_0_cnt %d core_1_cnt %d", + hw_event_type, event_cnt[core_idx0], + event_cnt[core_idx1]); rc = -1; return rc; } From 19d814458b6d2093a65801e16b948ac8b3fe8023 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 28 Aug 2019 15:51:07 -0700 Subject: [PATCH 079/790] msm: camera: isp: Send notification to userspace ISP driver must notify the userspace when any hardware error occurs so that the userspace knows when to use the register dump. CRs-Fixed: 2513939 Change-Id: I0d9ba9a22c6f2494ba3cc837513b8989c6cc1119 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 718c01ec8ee5..bdce837a0da3 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1206,10 +1206,6 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, uint32_t error_type = error_event_data->error_type; CAM_DBG(CAM_ISP, "Enter error_type = %d", error_type); - if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) || - (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW)) - notify.error = CRM_KMD_ERR_OVERFLOW; - if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) || (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW) || @@ -1397,7 +1393,7 @@ end: * and to dump relevant info */ - if (notify.error == CRM_KMD_ERR_OVERFLOW) { + if (notify.error == CRM_KMD_ERR_FATAL) { 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 = From 99709eacd22fcc1e0ae840281b552b42135b4dea Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 2 Sep 2019 23:24:07 +0800 Subject: [PATCH 080/790] msm: camera: isp: Reset rdi only context flag Reset rdi only context flag during releasing device, otherwise it will affect non-rdi context at next time. CRs-Fixed: 2519406 Change-Id: I904f0cae664a7530b2b85342c9a6daba579cbccc Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index bdce837a0da3..c27df2ce7a93 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2750,6 +2750,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; + ctx_isp->rdi_only_context = false; atomic64_set(&ctx_isp->state_monitor_head, -1); From c51b7ee477654fea9b2048bd7e118bad1bd8bdb7 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 29 Aug 2019 23:32:09 -0700 Subject: [PATCH 081/790] msm: camera: isp: Clear only the IRQ bits that are being handled Do not clear the irq bits that are not handled by the bus irq controller. Clearing all bits by buf_done irq controller may clear RUP bit without handling, resulting missing RUP. CRs-Fixed: 2519423 Change-Id: I65c5efeafbda8f5face50e8c17078269daa37767 Signed-off-by: Pavan Kumar Chilamkurthi --- .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 16767270a272..9cdaeaa834c9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3800,7 +3800,7 @@ int cam_vfe_bus_ver3_init( rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base, &ver3_hw_info->common_reg.irq_reg_info, - &bus_priv->common_data.bus_irq_controller, true); + &bus_priv->common_data.bus_irq_controller, false); if (rc) { CAM_ERR(CAM_ISP, "Init bus_irq_controller failed"); goto free_bus_priv; From 6d4c852953eca72b950d9899904331e0c5571b01 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Tue, 20 Aug 2019 14:31:19 +0530 Subject: [PATCH 082/790] msm: camera: csiphy: Update cphy 3-phase registers for lito Update register settings for 3-phase cphy operation as per hpg. CRs-Fixed: 2505587 Change-Id: Ib9392f8055f7b74044edb9634d705b9c92b0ec0d Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 119 ++++++++---------- 1 file changed, 55 insertions(+), 64 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index d99c4ee3758a..ca3d1b2e0974 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -12,20 +12,19 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, - .csiphy_common_array_size = 5, + .csiphy_common_array_size = 4, .csiphy_reset_array_size = 4, .csiphy_2ph_config_array_size = 21, - .csiphy_3ph_config_array_size = 32, + .csiphy_3ph_config_array_size = 34, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; struct csiphy_reg_t csiphy_common_reg_1_2[] = { - {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0814, 0x2A, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, }; struct csiphy_reg_t csiphy_reset_reg_1_2[] = { @@ -290,7 +289,7 @@ struct csiphy_reg_t struct csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { - {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -322,9 +321,11 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09AC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { - {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -356,9 +357,11 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { - {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -390,6 +393,8 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -399,82 +404,68 @@ struct data_rate_settings_t data_rate_delta_table = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 12, + .data_rate_reg_array_size = 9, .csiphy_data_rate_regs = { - {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, } }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 24, + .data_rate_reg_array_size = 18, .csiphy_data_rate_regs = { - {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x2D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x2D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x2D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 24, + .data_rate_reg_array_size = 18, .csiphy_data_rate_regs = { - {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x10C, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, }, } } From 9653879d63607e4cd6c72f20115e55e7d1b44c6e Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Tue, 20 Aug 2019 14:53:43 +0530 Subject: [PATCH 083/790] msm: camera: csiphy: Update dphy 2-phase registers for lito Update register settings for 2-phase and 2-phase combo mode dphy as per hpg. CRs-Fixed: 2505587 Change-Id: I348c1ee3b5618e1439ab87cc33f366eda89f0f82 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 151 +++++++----------- 1 file changed, 61 insertions(+), 90 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index ca3d1b2e0974..2cf988ac0094 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -12,19 +12,20 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, - .csiphy_common_array_size = 4, + .csiphy_common_array_size = 5, .csiphy_reset_array_size = 4, - .csiphy_2ph_config_array_size = 21, + .csiphy_2ph_config_array_size = 18, .csiphy_3ph_config_array_size = 34, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; struct csiphy_reg_t csiphy_common_reg_1_2[] = { - {0x0814, 0x2A, 0x00, CSIPHY_LANE_ENABLE}, + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }; struct csiphy_reg_t csiphy_reset_reg_1_2[] = { @@ -52,12 +53,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0908, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -65,22 +60,19 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -88,22 +80,19 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A08, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -111,22 +100,19 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -134,22 +120,19 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -157,13 +140,16 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -171,12 +157,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0908, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -184,22 +164,19 @@ struct csiphy_reg_t {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -207,22 +184,19 @@ struct csiphy_reg_t {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -230,22 +204,19 @@ struct csiphy_reg_t {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -253,22 +224,19 @@ struct csiphy_reg_t {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C08, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -276,13 +244,16 @@ struct csiphy_reg_t {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, }; From f648ceeca6fa7f462a885b5ad22211b34f180746 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Thu, 22 Aug 2019 16:47:48 +0530 Subject: [PATCH 084/790] msm: camera: req_mgr: Increase v4l2 queue length EIS have 6 fences per request and uses 15 frame window. On camera close it signals ~90 fences at once. This can overflow v4l2 event queue. Increase v4l2 queue length for sync events to prevent overflow. CRs-Fixed: 2498880 Change-Id: Ie886318168e326c1525b4f8be5cacc5f70d0c477 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_sync/cam_sync_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index 68a9804adf45..a8612fdcd7c5 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef __CAM_SYNC_PRIVATE_H__ @@ -25,7 +25,7 @@ #define CAM_SYNC_OBJ_NAME_LEN 64 #define CAM_SYNC_MAX_OBJS 1024 -#define CAM_SYNC_MAX_V4L2_EVENTS 50 +#define CAM_SYNC_MAX_V4L2_EVENTS 100 #define CAM_SYNC_DEBUG_FILENAME "cam_debug" #define CAM_SYNC_DEBUG_BASEDIR "cam" #define CAM_SYNC_DEBUG_BUF_SIZE 32 From e4be9ecbfe0f4725a215662cb278763777cfd211 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Tue, 6 Aug 2019 15:24:57 -0700 Subject: [PATCH 085/790] msm: camera: utils: Add command buffer validation for reg dump The command buffer obtained from user has several offsets and sizes that need to be validated before accessing data. Also, out buffer offsets need to be checked before writing data. Add validation checks for parameters in command buffer for reg dump. CRs-Fixed: 2501003 Change-Id: I65b37befcefbd7f739663b6142d5d0eedcab25b4 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_utils/cam_soc_util.c | 276 ++++++++++++++++++++++--------- 1 file changed, 202 insertions(+), 74 deletions(-) diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 99e349a66c61..04f2f80b82ba 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -1830,53 +1830,81 @@ int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info, static int cam_soc_util_dump_cont_reg_range( struct cam_hw_soc_info *soc_info, struct cam_reg_range_read_desc *reg_read, uint32_t base_idx, - struct cam_reg_dump_out_buffer *dump_out_buf, size_t max_out_size) + struct cam_reg_dump_out_buffer *dump_out_buf, uintptr_t cmd_buf_end) { - int i = 0; + int i = 0, rc = 0; uint32_t write_idx = 0; - if (!soc_info || !dump_out_buf) { + if (!soc_info || !dump_out_buf || !reg_read || !cmd_buf_end) { CAM_ERR(CAM_UTIL, - "Invalid input args soc_info: %pK, dump_out_buffer: %pK", - soc_info, dump_out_buf); - return -EINVAL; + "Invalid input args soc_info: %pK, dump_out_buffer: %pK reg_read: %pK cmd_buf_end: %pK", + soc_info, dump_out_buf, reg_read, cmd_buf_end); + rc = -EINVAL; + goto end; } - if (reg_read->num_values >= ((max_out_size - - (size_t)dump_out_buf->bytes_written) / sizeof(uint32_t))) { + if ((reg_read->num_values) && ((reg_read->num_values > U32_MAX / 2) || + (sizeof(uint32_t) > ((U32_MAX - + sizeof(struct cam_reg_dump_out_buffer) - + dump_out_buf->bytes_written) / + (reg_read->num_values * 2))))) { CAM_ERR(CAM_UTIL, - "Invalid num values to read: %d max values: %d bytes written: %d", - reg_read->num_values, (max_out_size / - sizeof(uint32_t)), dump_out_buf->bytes_written); - return -EINVAL; + "Integer Overflow bytes_written: [%u] num_values: [%u]", + dump_out_buf->bytes_written, reg_read->num_values); + rc = -EOVERFLOW; + goto end; + } + + if ((cmd_buf_end - (uintptr_t)dump_out_buf) <= + (uintptr_t)(sizeof(struct cam_reg_dump_out_buffer) + - sizeof(uint32_t) + dump_out_buf->bytes_written + + (reg_read->num_values * 2 * sizeof(uint32_t)))) { + CAM_ERR(CAM_UTIL, + "Insufficient space in out buffer num_values: [%d] cmd_buf_end: %pK dump_out_buf: %pK", + reg_read->num_values, cmd_buf_end, + (uintptr_t)dump_out_buf); + rc = -EINVAL; + goto end; } write_idx = dump_out_buf->bytes_written / sizeof(uint32_t); for (i = 0; i < reg_read->num_values; i++) { + if ((reg_read->offset + (i * sizeof(uint32_t))) > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + (reg_read->offset + (i * sizeof(uint32_t))), + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + dump_out_buf->dump_data[write_idx++] = reg_read->offset + - (i * 4); + (i * sizeof(uint32_t)); dump_out_buf->dump_data[write_idx++] = cam_soc_util_r(soc_info, base_idx, - (reg_read->offset + (i * 4))); + (reg_read->offset + (i * sizeof(uint32_t)))); dump_out_buf->bytes_written += (2 * sizeof(uint32_t)); } - return 0; +end: + return rc; } static int cam_soc_util_dump_dmi_reg_range( struct cam_hw_soc_info *soc_info, struct cam_dmi_read_desc *dmi_read, uint32_t base_idx, - struct cam_reg_dump_out_buffer *dump_out_buf, size_t max_out_size) + struct cam_reg_dump_out_buffer *dump_out_buf, uintptr_t cmd_buf_end) { - int i = 0; + int i = 0, rc = 0; uint32_t write_idx = 0; - if (!soc_info || !dump_out_buf) { + if (!soc_info || !dump_out_buf || !dmi_read || !cmd_buf_end) { CAM_ERR(CAM_UTIL, "Invalid input args soc_info: %pK, dump_out_buffer: %pK", soc_info, dump_out_buf); - return -EINVAL; + rc = -EINVAL; + goto end; } if (dmi_read->num_pre_writes > CAM_REG_DUMP_DMI_CONFIG_MAX || @@ -1884,20 +1912,55 @@ static int cam_soc_util_dump_dmi_reg_range( CAM_ERR(CAM_UTIL, "Invalid number of requested writes, pre: %d post: %d", dmi_read->num_pre_writes, dmi_read->num_post_writes); - return -EINVAL; + rc = -EINVAL; + goto end; } - if (dmi_read->dmi_data_read.num_values >= ((max_out_size - - (size_t)dump_out_buf->bytes_written) / sizeof(uint32_t))) { + if ((dmi_read->num_pre_writes + dmi_read->dmi_data_read.num_values) + && ((dmi_read->num_pre_writes > U32_MAX / 2) || + (dmi_read->dmi_data_read.num_values > U32_MAX / 2) || + ((dmi_read->num_pre_writes * 2) > U32_MAX - + (dmi_read->dmi_data_read.num_values * 2)) || + (sizeof(uint32_t) > ((U32_MAX - + sizeof(struct cam_reg_dump_out_buffer) - + dump_out_buf->bytes_written) / ((dmi_read->num_pre_writes + + dmi_read->dmi_data_read.num_values) * 2))))) { CAM_ERR(CAM_UTIL, - "Invalid num values to read: %d max values: %d bytes written: %d", - dmi_read->dmi_data_read.num_values, (max_out_size / - sizeof(uint32_t)), dump_out_buf->bytes_written); - return -EINVAL; + "Integer Overflow bytes_written: [%u] num_pre_writes: [%u] num_values: [%u]", + dump_out_buf->bytes_written, dmi_read->num_pre_writes, + dmi_read->dmi_data_read.num_values); + rc = -EOVERFLOW; + goto end; + } + + if ((cmd_buf_end - (uintptr_t)dump_out_buf) <= + (uintptr_t)( + sizeof(struct cam_reg_dump_out_buffer) - sizeof(uint32_t) + + (dump_out_buf->bytes_written + + (dmi_read->num_pre_writes * 2 * sizeof(uint32_t)) + + (dmi_read->dmi_data_read.num_values * 2 * + sizeof(uint32_t))))) { + CAM_ERR(CAM_UTIL, + "Insufficient space in out buffer num_read_val: [%d] num_write_val: [%d] cmd_buf_end: %pK dump_out_buf: %pK", + dmi_read->dmi_data_read.num_values, + dmi_read->num_pre_writes, cmd_buf_end, + (uintptr_t)dump_out_buf); + rc = -EINVAL; + goto end; } write_idx = dump_out_buf->bytes_written / sizeof(uint32_t); for (i = 0; i < dmi_read->num_pre_writes; i++) { + if (dmi_read->pre_read_config[i].offset > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + dmi_read->pre_read_config[i].offset, + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + cam_soc_util_w_mb(soc_info, base_idx, dmi_read->pre_read_config[i].offset, dmi_read->pre_read_config[i].value); @@ -1908,6 +1971,16 @@ static int cam_soc_util_dump_dmi_reg_range( dump_out_buf->bytes_written += (2 * sizeof(uint32_t)); } + if (dmi_read->dmi_data_read.offset > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + dmi_read->dmi_data_read.offset, + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + for (i = 0; i < dmi_read->dmi_data_read.num_values; i++) { dump_out_buf->dump_data[write_idx++] = dmi_read->dmi_data_read.offset; @@ -1918,12 +1991,23 @@ static int cam_soc_util_dump_dmi_reg_range( } for (i = 0; i < dmi_read->num_post_writes; i++) { + if (dmi_read->post_read_config[i].offset > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + dmi_read->post_read_config[i].offset, + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + cam_soc_util_w_mb(soc_info, base_idx, dmi_read->post_read_config[i].offset, dmi_read->post_read_config[i].value); } - return 0; +end: + return rc; } int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, @@ -1937,7 +2021,6 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, uintptr_t cmd_buf_end = 0; uint32_t reg_base_type = 0; size_t buf_size = 0, remain_len = 0; - size_t max_out_size = 0; struct cam_reg_dump_input_info *reg_input_info = NULL; struct cam_reg_dump_desc *reg_dump_desc = NULL; struct cam_reg_dump_out_buffer *dump_out_buf = NULL; @@ -1961,7 +2044,7 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, if (rc || !cpu_addr || (buf_size == 0)) { CAM_ERR(CAM_UTIL, "Failed in Get cpu addr, rc=%d, cpu_addr=%pK", rc, (void *)cpu_addr); - return rc; + goto end; } CAM_DBG(CAM_UTIL, "Get cpu buf success req_id: %llu buf_size: %zu", @@ -1970,74 +2053,114 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, ((size_t)cmd_desc->offset > (buf_size - sizeof(uint32_t)))) { CAM_ERR(CAM_UTIL, "Invalid offset for cmd buf: %zu", (size_t)cmd_desc->offset); - return -EINVAL; + rc = -EINVAL; + goto end; } remain_len = buf_size - (size_t)cmd_desc->offset; - if (remain_len < (size_t)cmd_desc->length) { - CAM_ERR(CAM_UTIL, "Invalid length for cmd buf: %zu", - (size_t)cmd_desc->length); - return -EINVAL; + if ((remain_len < (size_t)cmd_desc->size) || (cmd_desc->size < + cmd_desc->length)) { + CAM_ERR(CAM_UTIL, + "Invalid params for cmd buf len: %zu size: %zu remain_len: %zu", + (size_t)cmd_desc->length, (size_t)cmd_desc->length, + remain_len); + rc = -EINVAL; + goto end; } - cmd_buf_start = (uintptr_t)(((uint8_t *)cpu_addr) + cmd_desc->offset); - cmd_in_data_end = (uintptr_t)(((uint8_t *)cmd_buf_start) + - cmd_desc->length); - cmd_buf_end = (uintptr_t)(((uint8_t *)cmd_buf_start) + - cmd_desc->size); - if (cmd_buf_end < cmd_in_data_end) { + cmd_buf_start = cpu_addr + (uintptr_t)cmd_desc->offset; + cmd_in_data_end = cmd_buf_start + (uintptr_t)cmd_desc->length; + cmd_buf_end = cmd_buf_start + (uintptr_t)cmd_desc->size; + if ((cmd_buf_end <= cmd_buf_start) || + (cmd_in_data_end <= cmd_buf_start)) { CAM_ERR(CAM_UTIL, - "Invalid length and size for cmd buf: [%zu] [%zu]", + "Invalid length or size for cmd buf: [%zu] [%zu]", (size_t)cmd_desc->length, (size_t)cmd_desc->size); - return -EINVAL; + rc = -EINVAL; + goto end; } CAM_DBG(CAM_UTIL, "Buffer params start [%pK] input_end [%pK] buf_end [%pK]", cmd_buf_start, cmd_in_data_end, cmd_buf_end); reg_input_info = (struct cam_reg_dump_input_info *) cmd_buf_start; - if (!reg_input_info->num_dump_sets) { - CAM_ERR(CAM_UTIL, "Zero dump sets found in input info"); - return -EINVAL; + if ((reg_input_info->num_dump_sets > 1) && (sizeof(uint32_t) > + ((U32_MAX - sizeof(struct cam_reg_dump_input_info)) / + (reg_input_info->num_dump_sets - 1)))) { + CAM_ERR(CAM_UTIL, + "Integer Overflow req_id: [%llu] num_dump_sets: [%u]", + req_id, reg_input_info->num_dump_sets); + rc = -EOVERFLOW; + goto end; + } + + if ((!reg_input_info->num_dump_sets) || + ((cmd_in_data_end - cmd_buf_start) <= (uintptr_t) + (sizeof(struct cam_reg_dump_input_info) + + ((reg_input_info->num_dump_sets - 1) * sizeof(uint32_t))))) { + CAM_ERR(CAM_UTIL, + "Invalid number of dump sets, req_id: [%llu] num_dump_sets: [%u]", + req_id, reg_input_info->num_dump_sets); + rc = -EINVAL; + goto end; } CAM_DBG(CAM_UTIL, "reg_input_info req_id: %llu ctx %pK num_dump_sets: %d", req_id, ctx, reg_input_info->num_dump_sets); for (i = 0; i < reg_input_info->num_dump_sets; i++) { - if ((remain_len - sizeof(uint32_t)) <= - (size_t)reg_input_info->dump_set_offsets[i]) { + if ((cmd_in_data_end - cmd_buf_start) <= (uintptr_t) + reg_input_info->dump_set_offsets[i]) { CAM_ERR(CAM_UTIL, - "Invalid dump set offset: [%zu], remain len: [%zu]", - (size_t)reg_input_info->dump_set_offsets[i], - remain_len); - return -EINVAL; + "Invalid dump set offset: [%pK], cmd_buf_start: [%pK] cmd_in_data_end: [%pK]", + (uintptr_t)reg_input_info->dump_set_offsets[i], + cmd_buf_start, cmd_in_data_end); + rc = -EINVAL; + goto end; } reg_dump_desc = (struct cam_reg_dump_desc *) - ((uint8_t *)cmd_buf_start + - reg_input_info->dump_set_offsets[i]); - if (!reg_dump_desc->num_read_range) { - CAM_ERR(CAM_UTIL, "Zero ranges found in input info"); - return -EINVAL; + (cmd_buf_start + + (uintptr_t)reg_input_info->dump_set_offsets[i]); + if ((reg_dump_desc->num_read_range > 1) && + (sizeof(struct cam_reg_read_info) > ((U32_MAX - + sizeof(struct cam_reg_dump_desc)) / + (reg_dump_desc->num_read_range - 1)))) { + CAM_ERR(CAM_UTIL, + "Integer Overflow req_id: [%llu] num_read_range: [%u]", + req_id, reg_dump_desc->num_read_range); + rc = -EOVERFLOW; + goto end; } - if ((remain_len - sizeof(uint32_t)) - <= (size_t)reg_dump_desc->dump_buffer_offset) { + if ((!reg_dump_desc->num_read_range) || + ((cmd_in_data_end - (uintptr_t)reg_dump_desc) <= + (uintptr_t)(sizeof(struct cam_reg_dump_desc) + + ((reg_dump_desc->num_read_range - 1) * + sizeof(struct cam_reg_read_info))))) { CAM_ERR(CAM_UTIL, - "Invalid out buffer offset: [%zu], remain len: [%zu]", - (size_t)reg_dump_desc->dump_buffer_offset, - remain_len); - return -EINVAL; + "Invalid number of read ranges, req_id: [%llu] num_read_range: [%d]", + req_id, reg_dump_desc->num_read_range); + rc = -EINVAL; + goto end; + } + + if ((cmd_buf_end - cmd_buf_start) <= (uintptr_t) + (reg_dump_desc->dump_buffer_offset + + sizeof(struct cam_reg_dump_out_buffer))) { + CAM_ERR(CAM_UTIL, + "Invalid out buffer offset: [%pK], cmd_buf_start: [%pK] cmd_buf_end: [%pK]", + (uintptr_t)reg_dump_desc->dump_buffer_offset, + cmd_buf_start, cmd_buf_end); + rc = -EINVAL; + goto end; } dump_out_buf = (struct cam_reg_dump_out_buffer *) - ((uint8_t *)cmd_buf_start + - reg_dump_desc->dump_buffer_offset); + (cmd_buf_start + + (uintptr_t)reg_dump_desc->dump_buffer_offset); dump_out_buf->req_id = req_id; dump_out_buf->bytes_written = 0; - max_out_size = (size_t)(cmd_desc->size - - reg_dump_desc->dump_buffer_offset); reg_base_type = reg_dump_desc->reg_base_type; if (reg_base_type == 0 || reg_base_type > @@ -2045,7 +2168,8 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, CAM_ERR(CAM_UTIL, "Invalid Reg dump base type: %d", reg_base_type); - return -EINVAL; + rc = -EINVAL; + goto end; } rc = reg_data_cb(reg_base_type, ctx, &soc_info, ®_base_idx); @@ -2053,14 +2177,16 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, CAM_ERR(CAM_UTIL, "Reg space data callback failed rc: %d soc_info: [%pK]", rc, soc_info); - return -EINVAL; + rc = -EINVAL; + goto end; } if (reg_base_idx > soc_info->num_reg_map) { CAM_ERR(CAM_UTIL, "Invalid reg base idx: %d num reg map: %d", reg_base_idx, soc_info->num_reg_map); - return -EINVAL; + rc = -EINVAL; + goto end; } CAM_DBG(CAM_UTIL, @@ -2076,27 +2202,29 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, CAM_REG_DUMP_READ_TYPE_CONT_RANGE) { rc = cam_soc_util_dump_cont_reg_range(soc_info, ®_read_info->reg_read, reg_base_idx, - dump_out_buf, max_out_size); + dump_out_buf, cmd_buf_end); } else if (reg_read_info->type == CAM_REG_DUMP_READ_TYPE_DMI) { rc = cam_soc_util_dump_dmi_reg_range(soc_info, ®_read_info->dmi_read, reg_base_idx, - dump_out_buf, max_out_size); + dump_out_buf, cmd_buf_end); } else { CAM_ERR(CAM_UTIL, "Invalid Reg dump read type: %d", reg_read_info->type); - return -EINVAL; + rc = -EINVAL; + goto end; } if (rc) { CAM_ERR(CAM_UTIL, "Reg range read failed rc: %d reg_base_idx: %d dump_out_buf: %pK", rc, reg_base_idx, dump_out_buf); - return rc; + goto end; } } } - return 0; +end: + return rc; } From 4329af66bd34c6a263e48ec95b900717192fca52 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 7 Aug 2019 14:10:45 -0700 Subject: [PATCH 086/790] msm: camera: isp: Add per request reg dump to command buffer For debugging, user space may request a specified register range values to be dumped to a command buffer every request. Add support for reg dump every request during cdm callback. Add debugfs flag for making sure per request dump is not enabled by mistake. CRs-Fixed: 2501003 Change-Id: I01a0f3bb00dd122b8037d513ec331c5c08fdf372 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 257 ++++++++++-------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 2 + .../hw_utils/cam_isp_packet_parser.c | 2 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 7 + 4 files changed, 157 insertions(+), 111 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index ad07052d7345..21e8dd00a3ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -58,6 +58,117 @@ static int cam_ife_hw_mgr_event_handler( uint32_t evt_id, void *evt_info); +static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, + void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr, + uint32_t *reg_base_idx) +{ + int rc = 0; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_ife_hw_mgr_res *hw_mgr_res_temp; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ife_hw_mgr_ctx *ctx = + (struct cam_ife_hw_mgr_ctx *) hw_mgr_ctx; + + *soc_info_ptr = NULL; + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &ctx->res_list_ife_src, list) { + if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF) + continue; + + switch (reg_base_type) { + case CAM_REG_DUMP_BASE_TYPE_CAMNOC: + case CAM_REG_DUMP_BASE_TYPE_ISP_LEFT: + if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]) + continue; + + rc = hw_mgr_res->hw_res[ + CAM_ISP_HW_SPLIT_LEFT]->process_cmd( + hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT], + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info, + sizeof(void *)); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in regspace data query split idx: %d rc : %d", + CAM_ISP_HW_SPLIT_LEFT, rc); + return rc; + } + + if (reg_base_type == CAM_REG_DUMP_BASE_TYPE_ISP_LEFT) + *reg_base_idx = 0; + else + *reg_base_idx = 1; + + *soc_info_ptr = soc_info; + break; + case CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT: + if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]) + continue; + + rc = hw_mgr_res->hw_res[ + CAM_ISP_HW_SPLIT_RIGHT]->process_cmd( + hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT], + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info, + sizeof(void *)); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in regspace data query split idx: %d rc : %d", + CAM_ISP_HW_SPLIT_RIGHT, rc); + return rc; + } + + *reg_base_idx = 0; + *soc_info_ptr = soc_info; + break; + default: + CAM_ERR(CAM_ISP, + "Unrecognized reg base type: %u", + reg_base_type); + return -EINVAL; + } + + break; + } + + return rc; +} + +static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, + struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf, + uint32_t meta_type) +{ + int rc = 0, i; + + if (!num_reg_dump_buf || !reg_dump_buf_desc) { + CAM_DBG(CAM_ISP, + "Invalid args for reg dump req_id: [%llu] ctx idx: [%u] meta_type: [%u]", + ctx->applied_req_id, ctx->ctx_index, meta_type); + return rc; + } + + if (!atomic_read(&ctx->cdm_done)) + CAM_WARN_RATE_LIMIT(CAM_ISP, + "Reg dump values might be from more than one request"); + + for (i = 0; i < num_reg_dump_buf; i++) { + CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %u req_type: %u", + reg_dump_buf_desc[i].meta_data, meta_type); + if (reg_dump_buf_desc[i].meta_data == meta_type) { + rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, + ®_dump_buf_desc[i], + ctx->applied_req_id, + cam_ife_mgr_regspace_data_cb); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", + i, rc, ctx->applied_req_id, meta_type); + return rc; + } + } + } + + return rc; +} + static int cam_ife_notify_safe_lut_scm(bool safe_trigger) { uint32_t camera_hw_version, rc = 0; @@ -2289,6 +2400,7 @@ err: void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, enum cam_cdm_cb_status status, uint64_t cookie) { + struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; struct cam_ife_hw_mgr_ctx *ctx = NULL; if (!userdata) { @@ -2296,11 +2408,18 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, return; } - ctx = userdata; + hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata; + ctx = (struct cam_ife_hw_mgr_ctx *)hw_update_data->ife_mgr_ctx; if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { complete_all(&ctx->config_done_complete); atomic_set(&ctx->cdm_done, 1); + if (g_ife_hw_mgr.debug_cfg.per_req_reg_dump) + cam_ife_mgr_handle_reg_dump(ctx, + hw_update_data->reg_dump_buf_desc, + hw_update_data->num_reg_dump_buf, + CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST); + CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", handle, userdata, status, cookie, ctx->ctx_index); @@ -3237,6 +3356,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, return -EINVAL; hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; + hw_update_data->ife_mgr_ctx = ctx; CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld", ctx, ctx->ctx_index, cfg->request_id); @@ -3282,7 +3402,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = true; - cdm_cmd->userdata = ctx; + cdm_cmd->userdata = hw_update_data; cdm_cmd->cookie = cfg->request_id; for (i = 0 ; i <= cfg->num_hw_update_entries; i++) { @@ -5374,8 +5494,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } goto end; - } else + } else { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV; + prepare_hw_data->num_reg_dump_buf = prepare->num_reg_dump_buf; + if ((prepare_hw_data->num_reg_dump_buf) && + (prepare_hw_data->num_reg_dump_buf < + CAM_REG_DUMP_MAX_BUF_ENTRIES)) { + memcpy(prepare_hw_data->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare_hw_data->num_reg_dump_buf); + } + } /* add reg update commands */ for (i = 0; i < ctx->num_base; i++) { @@ -5529,112 +5659,6 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, } } -static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, - void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr, - uint32_t *reg_base_idx) -{ - int rc = 0; - struct cam_ife_hw_mgr_res *hw_mgr_res; - struct cam_hw_soc_info *soc_info = NULL; - struct cam_ife_hw_mgr_ctx *ctx = - (struct cam_ife_hw_mgr_ctx *) hw_mgr_ctx; - - *soc_info_ptr = NULL; - list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { - if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF) - continue; - - switch (reg_base_type) { - case CAM_REG_DUMP_BASE_TYPE_CAMNOC: - case CAM_REG_DUMP_BASE_TYPE_ISP_LEFT: - if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]) - continue; - - rc = hw_mgr_res->hw_res[ - CAM_ISP_HW_SPLIT_LEFT]->process_cmd( - hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT], - CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info, - sizeof(void *)); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed in regspace data query split idx: %d rc : %d", - CAM_ISP_HW_SPLIT_LEFT, rc); - return rc; - } - - if (reg_base_type == CAM_REG_DUMP_BASE_TYPE_ISP_LEFT) - *reg_base_idx = 0; - else - *reg_base_idx = 1; - - *soc_info_ptr = soc_info; - break; - case CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT: - if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]) - continue; - - rc = hw_mgr_res->hw_res[ - CAM_ISP_HW_SPLIT_RIGHT]->process_cmd( - hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT], - CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, &soc_info, - sizeof(void *)); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed in regspace data query split idx: %d rc : %d", - CAM_ISP_HW_SPLIT_RIGHT, rc); - return rc; - } - - *reg_base_idx = 0; - *soc_info_ptr = soc_info; - break; - default: - CAM_ERR(CAM_ISP, - "Unrecognized reg base type: %d", - reg_base_type); - return -EINVAL; - } - } - - return rc; -} - -static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, - uint32_t meta_type) -{ - int rc, i; - - if (!ctx->num_reg_dump_buf) { - CAM_DBG(CAM_ISP, - "Zero command buffers for reg dump req_id: [%llu] ctx idx: [%llu] meta_type: %d", - ctx->applied_req_id, ctx->ctx_index, meta_type); - return 0; - } - - if (!atomic_read(&ctx->cdm_done)) - CAM_WARN_RATE_LIMIT(CAM_ISP, - "Reg dump values might be from more than one request"); - - for (i = 0; i < ctx->num_reg_dump_buf; i++) { - CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %d req_type: %d", - ctx->reg_dump_buf_desc[i].meta_data, meta_type); - if (ctx->reg_dump_buf_desc[i].meta_data == meta_type) { - rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, - &ctx->reg_dump_buf_desc[i], - ctx->applied_req_id, - cam_ife_mgr_regspace_data_cb); - if (rc) { - CAM_ERR(CAM_ISP, - "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %d", - i, rc, ctx->applied_req_id, meta_type); - return -EINVAL; - } - } - } - - return 0; -} - static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -5713,7 +5737,8 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) } ctx->last_dump_flush_req_id = ctx->applied_req_id; - rc = cam_ife_mgr_handle_reg_dump(ctx, + rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH); if (rc) { CAM_ERR(CAM_ISP, @@ -5728,7 +5753,8 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return 0; ctx->last_dump_err_req_id = ctx->applied_req_id; - rc = cam_ife_mgr_handle_reg_dump(ctx, + rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR); if (rc) { CAM_ERR(CAM_ISP, @@ -6544,6 +6570,15 @@ static int cam_ife_hw_mgr_debug_register(void) CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug"); goto err; } + + if (!debugfs_create_bool("per_req_reg_dump", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, + &g_ife_hw_mgr.debug_cfg.per_req_reg_dump)) { + CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); + goto err; + } + g_ife_hw_mgr.debug_cfg.enable_recovery = 0; return 0; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 05ee264e93c9..7e6b91bab916 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -83,6 +83,7 @@ struct ctx_base_info { * @enable_recovery: enable recovery * @enable_diag_sensor_status: enable sensor diagnosis status * @enable_req_dump: Enable request dump on HW errors + * @per_req_reg_dump: Enable per request reg dump * */ struct cam_ife_hw_mgr_debug { @@ -91,6 +92,7 @@ struct cam_ife_hw_mgr_debug { uint32_t enable_recovery; uint32_t camif_debug; bool enable_req_dump; + bool per_req_reg_dump; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 48928bccc472..b57500c16653 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -422,6 +422,7 @@ int cam_isp_add_command_buffers( break; case CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH: case CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR: + case CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST: if (split_id == CAM_ISP_HW_SPLIT_LEFT) { if (prepare->num_reg_dump_buf >= CAM_REG_DUMP_MAX_BUF_ENTRIES) { @@ -430,6 +431,7 @@ int cam_isp_add_command_buffers( prepare->num_reg_dump_buf); return -EINVAL; } + prepare->reg_dump_buf_desc[ prepare->num_reg_dump_buf] = cmd_desc[i]; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index fb39c02e25c8..6d5d0fd61c88 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -115,6 +115,7 @@ struct cam_isp_bw_config_internal { /** * struct cam_isp_prepare_hw_update_data - hw prepare data * + * @ife_mgr_ctx: IFE HW manager Context for current request * @packet_opcode_type: Packet header opcode in the packet header * this opcode defines, packet is init packet or * update packet @@ -123,14 +124,20 @@ struct cam_isp_bw_config_internal { * @bw_config_v2: BW config info for AXI bw voting v2 * @bw_config_valid: Flag indicating whether the bw_config at the index * is valid or not + * @reg_dump_buf_desc: cmd buffer descriptors for reg dump + * @num_reg_dump_buf: Count of descriptors in reg_dump_buf_desc * */ struct cam_isp_prepare_hw_update_data { + struct cam_ife_hw_mgr_ctx *ife_mgr_ctx; uint32_t packet_opcode_type; uint32_t bw_config_version; struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; struct cam_isp_bw_config_internal_v2 bw_config_v2[CAM_IFE_HW_NUM_MAX]; bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; + struct cam_cmd_buf_desc reg_dump_buf_desc[ + CAM_REG_DUMP_MAX_BUF_ENTRIES]; + uint32_t num_reg_dump_buf; }; From 3ef8ba0db6d1c3921e8e8803ce9ff3893176f318 Mon Sep 17 00:00:00 2001 From: Abhilash Kumar Date: Thu, 25 Apr 2019 21:18:33 +0530 Subject: [PATCH 087/790] msm: camera: common: Add validation check for cpu buffers before accessing Add validation check before accessing the packets and configs from the buffers. CRs-Fixed: 2360223, 2416463 Change-Id: I9a09bc7064fd7e7914f91576542181c301db926d Signed-off-by: Abhilash Kumar Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cdm/cam_cdm_hw_core.c | 11 +++++++++++ drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 12 +++++++++++- drivers/cam_icp/cam_icp_context.c | 18 ++++++++++++++++++ .../cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 14 ++++++++++++++ drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 8 ++++++++ 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index bf251a823819..3e84e2049554 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -473,6 +473,17 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, if ((!rc) && (hw_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 cmd offset: %u cmd length: %u", + cdm_cmd->cmd[i].offset, + cdm_cmd->cmd[i].len); + rc = -EINVAL; + break; + } + CAM_DBG(CAM_CDM, "Got the HW VA"); if (core->bl_tag >= (CAM_CDM_HWFIFO_SIZE - 1)) diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index fad7caff6437..b33dfa699647 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -582,13 +582,23 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl, iommu_hdl, &io_addr[plane], &size); if (rc) { CAM_ERR(CAM_FD, - "Invalid io buf %d %d %d %d", + "Failed to get io buf %u %u %u %d", io_cfg[i].direction, io_cfg[i].resource_type, plane, rc); return -ENOMEM; } + if (io_cfg[i].offsets[plane] >= size) { + CAM_ERR(CAM_FD, + "Invalid io buf %u %u %u %d %u %zu", + io_cfg[i].direction, + io_cfg[i].resource_type, plane, + i, io_cfg[i].offsets[plane], + size); + return -EINVAL; + } + io_addr[plane] += io_cfg[i].offsets[plane]; } diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index ec23a6ee9d96..34c5a60fe826 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -129,6 +129,7 @@ static int __cam_icp_config_dev_in_ready(struct cam_context *ctx, size_t len; uintptr_t packet_addr; struct cam_packet *packet; + size_t remain_len = 0; rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, &packet_addr, &len); @@ -139,9 +140,26 @@ static int __cam_icp_config_dev_in_ready(struct cam_context *ctx, return rc; } + remain_len = len; + if ((len < sizeof(struct cam_packet)) || + (cmd->offset >= (len - sizeof(struct cam_packet)))) { + CAM_ERR(CAM_CTXT, + "Invalid offset, len: %zu cmd offset: %llu sizeof packet: %zu", + len, cmd->offset, sizeof(struct cam_packet)); + return -EINVAL; + } + + remain_len -= (size_t)cmd->offset; packet = (struct cam_packet *) ((uint8_t *)packet_addr + (uint32_t)cmd->offset); + rc = cam_packet_util_validate_packet(packet, remain_len); + if (rc) { + CAM_ERR(CAM_CTXT, "Invalid packet params, remain length: %zu", + remain_len); + return rc; + } + if (((packet->header.op_code & 0xff) == CAM_ICP_OPCODE_IPE_SETTINGS) || ((packet->header.op_code & 0xff) == diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index c1ec110ea1d5..a63c7f72bb31 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3853,6 +3853,9 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, cmd_desc = (struct cam_cmd_buf_desc *) ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + rc = cam_packet_util_validate_cmd_desc(cmd_desc); + if (rc) + return rc; *fw_cmd_buf_iova_addr = 0; for (i = 0; i < packet->num_cmd_buf; i++, num_cmd_buf++) { @@ -3868,6 +3871,17 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, return rc; } *fw_cmd_buf_iova_addr = addr; + + if ((cmd_desc[i].offset >= len) || + ((len - cmd_desc[i].offset) < + cmd_desc[i].size)){ + CAM_ERR(CAM_ICP, + "Invalid offset, i: %d offset: %u len: %zu size: %zu", + i, cmd_desc[i].offset, + len, cmd_desc[i].size); + return -EINVAL; + } + *fw_cmd_buf_iova_addr = (*fw_cmd_buf_iova_addr + cmd_desc[i].offset); rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index b395bc396c70..c9ec8d1b39f1 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -149,6 +149,14 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) cmd_buf_kaddr = (uint32_t *)kaddr; + if ((p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset / + sizeof(uint32_t)) >= cmd_buf_len) { + CAM_ERR(CAM_JPEG, "Invalid offset: %u cmd buf len: %zu", + p_cfg_req->hw_cfg_args.hw_update_entries[ + CAM_JPEG_PARAM].offset, cmd_buf_len); + return -EINVAL; + } + cmd_buf_kaddr = (cmd_buf_kaddr + (p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset From b8e35c3397f09696cc87e6f2625d3ada6782e87e Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 20 Aug 2019 15:07:50 -0700 Subject: [PATCH 088/790] msm: camera: common: Update AHB vote for camera drivers As part of cpas start, all drivers will now request for LOW_SVS as opposed to SVS. The drivers also scale the AHB vote based on the corresponding HW's src clk voltage. CRs-Fixed: 2507919 Change-Id: I7fd35e9dd298deb1603812f39d50e4e9390b3aac Signed-off-by: Karthik Anantha Ram --- drivers/cam_cdm/cam_cdm_core_common.c | 2 +- drivers/cam_cdm/cam_cdm_hw_core.c | 2 +- drivers/cam_cpas/cam_cpas_hw.c | 47 ++++++++++++++++--- drivers/cam_cpas/cam_cpas_hw.h | 7 ++- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c | 2 +- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 7 ++- drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 16 ++++++- drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 17 +++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_soc.c | 2 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 2 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 25 ++++++++-- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 2 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 2 +- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c | 2 +- .../cam_sensor_module/cam_cci/cam_cci_soc.c | 2 +- .../cam_csiphy/cam_csiphy_core.c | 2 +- 16 files changed, 112 insertions(+), 27 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index 5401945c0e23..e903dc805ed0 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -274,7 +274,7 @@ int cam_cdm_stream_ops_internal(void *hw_priv, struct cam_axi_vote axi_vote = {0}; ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 3e84e2049554..7d0515b747a4 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -942,7 +942,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) cdm_core->cpas_handle = cpas_parms.client_handle; ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 1a7a5e2b053e..c6dddff25e2c 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -932,12 +932,14 @@ static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw, CAM_DBG(CAM_CPAS, "Required highest_level[%d]", highest_level); - rc = cam_cpas_util_vote_bus_client_level(ahb_bus_client, - highest_level); - if (rc) { - CAM_ERR(CAM_CPAS, "Failed in ahb vote, level=%d, rc=%d", - highest_level, rc); - goto unlock_bus_client; + if (cpas_core->ahb_bus_scaling_enable) { + rc = cam_cpas_util_vote_bus_client_level(ahb_bus_client, + highest_level); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in ahb vote, level=%d, rc=%d", + highest_level, rc); + goto unlock_bus_client; + } } rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info, highest_level); @@ -1661,6 +1663,33 @@ static int cam_cpas_util_get_internal_ops(struct platform_device *pdev, return rc; } +static int cam_cpas_util_create_debugfs( + struct cam_cpas *cpas_core) +{ + int rc = 0; + + cpas_core->dentry = debugfs_create_dir("camera_cpas", NULL); + if (!cpas_core->dentry) + return -ENOMEM; + + if (!debugfs_create_bool("ahb_bus_scaling_enable", + 0644, + cpas_core->dentry, + &cpas_core->ahb_bus_scaling_enable)) { + CAM_ERR(CAM_CPAS, + "failed to create ahb_bus_scaling_enable entry"); + rc = -ENOMEM; + goto err; + } + + return 0; + +err: + debugfs_remove_recursive(cpas_core->dentry); + cpas_core->dentry = NULL; + return rc; +} + int cam_cpas_hw_probe(struct platform_device *pdev, struct cam_hw_intf **hw_intf) { @@ -1803,6 +1832,10 @@ int cam_cpas_hw_probe(struct platform_device *pdev, if (rc) goto axi_cleanup; + rc = cam_cpas_util_create_debugfs(cpas_core); + if (rc) + CAM_WARN(CAM_CPAS, "Failed to create dentry"); + *hw_intf = cpas_hw_intf; return 0; @@ -1854,6 +1887,8 @@ int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf) cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client); cam_cpas_util_client_cleanup(cpas_hw); cam_cpas_soc_deinit_resources(&cpas_hw->soc_info); + debugfs_remove_recursive(cpas_core->dentry); + cpas_core->dentry = NULL; flush_workqueue(cpas_core->work_queue); destroy_workqueue(cpas_core->work_queue); mutex_destroy(&cpas_hw->hw_mutex); diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index 7b1eda841488..2b02fc411ff4 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -181,7 +181,10 @@ struct cam_cpas_axi_port { * @axi_port: AXI port info for a specific axi index * @internal_ops: CPAS HW internal ops * @work_queue: Work queue handle - * + * @irq_count: atomic irq count + * @irq_count_wq: wait variable to ensure all irq's are handled + * @dentry: debugfs file entry + * @ahb_bus_scaling_enable: ahb scaling based on src clk corner for bus */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; @@ -199,6 +202,8 @@ struct cam_cpas { struct workqueue_struct *work_queue; atomic_t irq_count; wait_queue_head_t irq_count_wq; + struct dentry *dentry; + bool ahb_bus_scaling_enable; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c index 56635aa6bce4..d05530ae4e17 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c @@ -143,7 +143,7 @@ int cam_fd_soc_enable_resources(struct cam_hw_soc_info *soc_info) int rc; ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 2; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 8c15000c791e..e4cb645b7af0 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -262,7 +262,7 @@ int cam_a5_init_hw(void *device_priv, a5_soc_info = soc_info->soc_private; cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; - cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.ahb_vote.vote.level = CAM_LOWSVS_VOTE; cpas_vote.axi_vote.num_paths = 1; cpas_vote.axi_vote.axi_path[0].path_data_type = CAM_ICP_DEFAULT_AXI_PATH; @@ -521,6 +521,7 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, } case CAM_ICP_A5_CMD_CLK_UPDATE: { int32_t clk_level = 0; + struct cam_ahb_vote ahb_vote; if (!cmd_args) { CAM_ERR(CAM_ICP, "Invalid args"); @@ -536,6 +537,10 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, "Failed to update clk to level: %d rc: %d", clk_level, rc); + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = clk_level; + cam_cpas_update_ahb_vote( + core_info->cpas_handle, &ahb_vote); break; } default: diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index 73075a4ec379..232f29c81db6 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -70,7 +70,7 @@ int cam_bps_init_hw(void *device_priv, } cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; - cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.ahb_vote.vote.level = CAM_LOWSVS_VOTE; cpas_vote.axi_vote.num_paths = 1; cpas_vote.axi_vote.axi_path[0].path_data_type = CAM_BPS_DEFAULT_AXI_PATH; @@ -366,7 +366,9 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_BPS_CMD_UPDATE_CLK: { struct cam_a5_clk_update_cmd *clk_upd_cmd = (struct cam_a5_clk_update_cmd *)cmd_args; + struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; + int32_t clk_level = 0, err = 0; CAM_DBG(CAM_ICP, "bps_src_clk rate = %d", (int)clk_rate); @@ -392,8 +394,20 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_bps_update_clk_rate(soc_info, clk_rate); if (rc) CAM_ERR(CAM_ICP, "Failed to update clk"); + + err = cam_soc_util_get_clk_level(soc_info, + clk_rate, soc_info->src_clk_idx, + &clk_level); + + if (!err) { + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = clk_level; + cam_cpas_update_ahb_vote( + core_info->cpas_handle, + &ahb_vote); } break; + } case CAM_ICP_BPS_CMD_DISABLE_CLK: if (core_info->clk_enable == true) cam_bps_toggle_clk(soc_info, false); diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 9ea8f51bb914..a0de07833b72 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -68,7 +68,7 @@ int cam_ipe_init_hw(void *device_priv, } cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; - cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.ahb_vote.vote.level = CAM_LOWSVS_VOTE; cpas_vote.axi_vote.num_paths = 1; cpas_vote.axi_vote.axi_path[0].path_data_type = CAM_IPE_DEFAULT_AXI_PATH; @@ -360,6 +360,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_IPE_CMD_UPDATE_CLK: { struct cam_a5_clk_update_cmd *clk_upd_cmd = (struct cam_a5_clk_update_cmd *)cmd_args; + struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; @@ -389,11 +390,17 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, CAM_ERR(CAM_ICP, "Failed to update clk"); err = cam_soc_util_get_clk_level(soc_info, - clk_rate, soc_info->src_clk_idx, - &clk_level); - if (err == 0) - clk_upd_cmd->clk_level = clk_level; + clk_rate, soc_info->src_clk_idx, + &clk_level); + if (!err) { + clk_upd_cmd->clk_level = clk_level; + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = clk_level; + cam_cpas_update_ahb_vote( + core_info->cpas_handle, + &ahb_vote); + } break; } case CAM_ICP_IPE_CMD_DISABLE_CLK: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c index ede6dbc5ea6e..7abcc64068ee 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -125,7 +125,7 @@ int cam_ife_csid_enable_soc_resources( soc_private = soc_info->soc_private; ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index cf899e97f326..77e2a059af57 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -232,7 +232,7 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info) soc_private = soc_info->soc_private; ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; if (strnstr(soc_info->compatible, "lite", strlen(soc_info->compatible))) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index a4fbe67aa955..743950bd01bc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -82,10 +82,14 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( struct cam_vfe_top_ver3_priv *top_priv) { struct cam_hw_soc_info *soc_info = NULL; - int i, rc = 0; + struct cam_vfe_soc_private *soc_private = NULL; + struct cam_ahb_vote ahb_vote; + int i, rc = 0, clk_lvl = -1; unsigned long max_clk_rate = 0; soc_info = top_priv->common_data.soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) @@ -100,11 +104,26 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); - if (!rc) + if (!rc) { top_priv->hw_clk_rate = max_clk_rate; - else + rc = cam_soc_util_get_clk_level(soc_info, max_clk_rate, + soc_info->src_clk_idx, &clk_lvl); + if (rc) { + CAM_WARN(CAM_ISP, + "Failed to get clk level for %s with clk_rate %llu src_idx %d rc %d", + soc_info->dev_name, max_clk_rate, + soc_info->src_clk_idx, rc); + rc = 0; + goto end; + } + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = clk_lvl; + cam_cpas_update_ahb_vote(soc_private->cpas_handle, &ahb_vote); + } else { CAM_ERR(CAM_PERF, "Set Clock rate failed, rc=%d", rc); + } +end: return rc; } diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c index 31b116cc7698..1304bbc71d38 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -55,7 +55,7 @@ int cam_jpeg_dma_init_hw(void *device_priv, } ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 2; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index 0b7bb7386553..4830bf58e89e 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -66,7 +66,7 @@ int cam_jpeg_enc_init_hw(void *device_priv, } ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 2; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c index ba227d2223eb..5ef984cba883 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c @@ -24,7 +24,7 @@ int cam_lrme_soc_enable_resources(struct cam_hw_info *lrme_hw) int rc = 0; ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 2; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 633196c983aa..092f42bbe0d9 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -73,7 +73,7 @@ int cam_cci_init(struct v4l2_subdev *sd, } ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index f4bdfff2cb97..6755eb2954ca 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -900,7 +900,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_SVS_VOTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; From 2d76f4238072adc0b2aa52318bb9b9b90d48b0a8 Mon Sep 17 00:00:00 2001 From: Prakasha Nayak Date: Fri, 13 Sep 2019 15:19:54 +0530 Subject: [PATCH 089/790] msm: camera: isp: Fix page fault dump for first request In case of page fault for first request, page fault information is not dumped since we are not initializing member variable in case of init request. CRs-Fixed: 2498880 Change-Id: Ie9ecda7434028e396392f3ac905ae80ae6ad6376 Signed-off-by: Prakasha Nayak --- drivers/cam_isp/cam_isp_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index c27df2ce7a93..0df3b063ce63 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -294,6 +294,9 @@ static int __cam_isp_ctx_enqueue_init_request( req_isp_new->num_cfg); req_isp_old->num_cfg += req_isp_new->num_cfg; + memcpy(&req_old->pf_data, &req->pf_data, + sizeof(struct cam_hw_mgr_dump_pf_data)); + req_old->request_id = req->request_id; list_add_tail(&req->list, &ctx->free_req_list); From 184ed6286f2bcc0c3532171aa5a2999a1631a655 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 19 Aug 2019 13:22:56 -0700 Subject: [PATCH 090/790] msm: camera: ife: Add support for RDI crop in dual IFE This change adds support for RDI crop in dual IFE usecases. The crop window for RDI is obtained by combining left and right IFE crop windows and width is calculated based on the crop window. If crop or drop is needed on RDI, decode format should not be programmed as payload only in order to enable RPP subpath. CRs-Fixed: 2513939 Change-Id: Iaaf64784372ef918802a684b33e16845fd7d2b3b Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 7 +- .../isp_hw/ife_csid_hw/cam_ife_csid175_200.h | 1 + .../isp_hw/ife_csid_hw/cam_ife_csid480.h | 1 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 108 ++++++++++++------ .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 1 + 5 files changed, 82 insertions(+), 36 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 21e8dd00a3ca..8e8da8753235 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2028,7 +2028,6 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( csid_acquire.cid = cid_res->hw_res[0]->res_id; csid_acquire.in_port = in_port; csid_acquire.out_port = out_port; - csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; csid_acquire.node_res = NULL; /* @@ -2036,12 +2035,12 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( * ver 480 HW to allow userspace to control pixel drop pattern. */ csid_acquire.drop_enable = true; + csid_acquire.crop_enable = true; - /* Enable RDI crop for single ife use case only */ if (in_port->usage_type) - csid_acquire.crop_enable = false; + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_MASTER; else - csid_acquire.crop_enable = true; + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; hw_intf = cid_res->hw_res[0]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h index 869fd8cd61c9..612379ec4bdd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -331,6 +331,7 @@ static struct cam_ife_csid_common_reg_offset .path_rst_stb_all = 0x7f, .path_rst_done_shift_val = 1, .path_en_shift_val = 31, + .packing_fmt_shift_val = 30, .dt_id_shift_val = 27, .vc_shift_val = 22, .dt_shift_val = 16, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h index cfa8e152b4c3..66c1b32d51b0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -349,6 +349,7 @@ static struct cam_ife_csid_common_reg_offset .path_rst_stb_all = 0x7f, .path_rst_done_shift_val = 1, .path_en_shift_val = 31, + .packing_fmt_shift_val = 30, .dt_id_shift_val = 27, .vc_shift_val = 22, .dt_shift_val = 16, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index ec41759cf50c..f3a4d967deaa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -72,8 +72,8 @@ static int cam_ife_csid_is_ipp_ppp_format_supported( } static int cam_ife_csid_get_format_rdi( - uint32_t in_format, uint32_t out_format, - uint32_t *decode_fmt, uint32_t *plain_fmt) + uint32_t in_format, uint32_t out_format, uint32_t *decode_fmt, + uint32_t *plain_fmt, uint32_t *packing_fmt, bool rpp) { int rc = 0; @@ -82,6 +82,10 @@ static int cam_ife_csid_get_format_rdi( switch (out_format) { case CAM_FORMAT_MIPI_RAW_6: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x0; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN8: *decode_fmt = 0x0; @@ -97,6 +101,10 @@ static int cam_ife_csid_get_format_rdi( case CAM_FORMAT_MIPI_RAW_8: case CAM_FORMAT_PLAIN128: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x1; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN8: *decode_fmt = 0x1; @@ -112,6 +120,10 @@ static int cam_ife_csid_get_format_rdi( case CAM_FORMAT_MIPI_RAW_10: case CAM_FORMAT_PLAIN128: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x2; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN16_10: *decode_fmt = 0x2; @@ -126,6 +138,10 @@ static int cam_ife_csid_get_format_rdi( switch (out_format) { case CAM_FORMAT_MIPI_RAW_12: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x3; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN16_12: *decode_fmt = 0x3; @@ -140,6 +156,10 @@ static int cam_ife_csid_get_format_rdi( switch (out_format) { case CAM_FORMAT_MIPI_RAW_14: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x4; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN16_14: *decode_fmt = 0x4; @@ -154,6 +174,10 @@ static int cam_ife_csid_get_format_rdi( switch (out_format) { case CAM_FORMAT_MIPI_RAW_16: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x5; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN16_16: *decode_fmt = 0x5; @@ -168,6 +192,10 @@ static int cam_ife_csid_get_format_rdi( switch (out_format) { case CAM_FORMAT_MIPI_RAW_20: *decode_fmt = 0xf; + if (rpp) { + *decode_fmt = 0x6; + *packing_fmt = 0x1; + } break; case CAM_FORMAT_PLAIN32_20: *decode_fmt = 0x6; @@ -947,6 +975,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, int rc = 0, i, id; struct cam_ife_csid_path_cfg *path_data; struct cam_isp_resource_node *res; + bool is_rdi = false; /* CSID CSI2 v2.0 supports 31 vc */ if (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX) { @@ -1042,6 +1071,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, "CSID:%d RDI resource:%d acquire success", csid_hw->hw_intf->hw_idx, res->res_id); + is_rdi = true; } break; @@ -1113,12 +1143,21 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->start_pixel = reserve->in_port->left_start; path_data->end_pixel = reserve->in_port->left_stop; path_data->width = reserve->in_port->left_width; - CAM_DBG(CAM_ISP, "CSID:%d master:startpixel 0x%x endpixel:0x%x", - csid_hw->hw_intf->hw_idx, path_data->start_pixel, - path_data->end_pixel); - CAM_DBG(CAM_ISP, "CSID:%d master:line start:0x%x line end:0x%x", - csid_hw->hw_intf->hw_idx, path_data->start_line, - path_data->end_line); + + if (is_rdi) { + path_data->end_pixel = reserve->in_port->right_stop; + path_data->width = path_data->end_pixel - + path_data->start_pixel + 1; + } + + CAM_DBG(CAM_ISP, + "CSID:%d res:%d master:startpixel 0x%x endpixel:0x%x", + csid_hw->hw_intf->hw_idx, reserve->res_id, + path_data->start_pixel, path_data->end_pixel); + CAM_DBG(CAM_ISP, + "CSID:%d res:%d master:line start:0x%x line end:0x%x", + csid_hw->hw_intf->hw_idx, reserve->res_id, + path_data->start_line, path_data->end_line); } else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { path_data->master_idx = reserve->master_idx; CAM_DBG(CAM_ISP, "CSID:%d master_idx=%d", @@ -1126,23 +1165,29 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->start_pixel = reserve->in_port->right_start; path_data->end_pixel = reserve->in_port->right_stop; path_data->width = reserve->in_port->right_width; - CAM_DBG(CAM_ISP, "CSID:%d slave:start:0x%x end:0x%x width 0x%x", - csid_hw->hw_intf->hw_idx, path_data->start_pixel, - path_data->end_pixel, path_data->width); - CAM_DBG(CAM_ISP, "CSID:%d slave:line start:0x%x line end:0x%x", - csid_hw->hw_intf->hw_idx, path_data->start_line, - path_data->end_line); + CAM_DBG(CAM_ISP, + "CSID:%d res:%d slave:start:0x%x end:0x%x width 0x%x", + csid_hw->hw_intf->hw_idx, reserve->res_id, + path_data->start_pixel, path_data->end_pixel, + path_data->width); + CAM_DBG(CAM_ISP, + "CSID:%d res:%d slave:line start:0x%x line end:0x%x", + csid_hw->hw_intf->hw_idx, reserve->res_id, + path_data->start_line, path_data->end_line); } else { path_data->width = reserve->in_port->left_width; path_data->start_pixel = reserve->in_port->left_start; path_data->end_pixel = reserve->in_port->left_stop; - CAM_DBG(CAM_ISP, "Res id: %d left width %d start: %d stop:%d", - reserve->res_id, reserve->in_port->left_width, + CAM_DBG(CAM_ISP, + "CSID:%d res:%d left width %d start: %d stop:%d", + csid_hw->hw_intf->hw_idx, reserve->res_id, + reserve->in_port->left_width, reserve->in_port->left_start, reserve->in_port->left_stop); } - CAM_DBG(CAM_ISP, "Res %d width %d height %d", reserve->res_id, + CAM_DBG(CAM_ISP, "CSID:%d res:%d width %d height %d", + csid_hw->hw_intf->hw_idx, reserve->res_id, path_data->width, path_data->height); reserve->node_res = res; @@ -2077,8 +2122,7 @@ static int cam_ife_csid_init_config_rdi_path( const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t path_format = 0, plain_fmt = 0, val = 0, id; - uint32_t format_measure_addr; - uint32_t camera_hw_version; + uint32_t format_measure_addr, camera_hw_version, packing_fmt = 0; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2092,14 +2136,11 @@ static int cam_ife_csid_init_config_rdi_path( } rc = cam_ife_csid_get_format_rdi(path_data->in_format, - path_data->out_format, &path_format, &plain_fmt); + path_data->out_format, &path_format, &plain_fmt, &packing_fmt, + path_data->crop_enable || path_data->drop_enable); if (rc) return rc; - /* if path decode format is payload only then RDI crop is not applied */ - if (path_format == 0xF) - path_data->crop_enable = 0; - /* * RDI path config and enable the time stamp capture * Enable the measurement blocks @@ -2122,11 +2163,15 @@ static int cam_ife_csid_init_config_rdi_path( } CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); - if (camera_hw_version == CAM_CPAS_TITAN_480_V100) + if (camera_hw_version == CAM_CPAS_TITAN_480_V100 || + camera_hw_version == CAM_CPAS_TITAN_175_V130) { val |= (path_data->drop_enable << csid_reg->cmn_reg->drop_h_en_shift_val) | (path_data->drop_enable << - csid_reg->cmn_reg->drop_v_en_shift_val); + csid_reg->cmn_reg->drop_v_en_shift_val) | + (packing_fmt << + csid_reg->cmn_reg->packing_fmt_shift_val); + } cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); @@ -2268,7 +2313,7 @@ static int cam_ife_csid_init_config_udi_path( const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t path_format = 0, plain_fmt = 0, val = 0, val1, id; - uint32_t format_measure_addr; + uint32_t format_measure_addr, packing_fmt = 0; path_data = (struct cam_ife_csid_path_cfg *)res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2282,7 +2327,8 @@ static int cam_ife_csid_init_config_udi_path( } rc = cam_ife_csid_get_format_rdi(path_data->in_format, - path_data->out_format, &path_format, &plain_fmt); + path_data->out_format, &path_format, &plain_fmt, &packing_fmt, + path_data->crop_enable || path_data->drop_enable); if (rc) { CAM_ERR(CAM_ISP, "Failed to get format in_format: %u out_format: %u rc: %d", @@ -2290,10 +2336,6 @@ static int cam_ife_csid_init_config_udi_path( return rc; } - /* if path decode format is payload only then UDI crop is not applied */ - if (path_format == 0xF) - path_data->crop_enable = false; - /* * UDI path config and enable the time stamp capture * Enable the measurement blocks @@ -2309,6 +2351,8 @@ static int cam_ife_csid_init_config_udi_path( csid_reg->cmn_reg->crop_v_en_shift_val) | (1 << 2) | 3; + val |= (packing_fmt << csid_reg->cmn_reg->packing_fmt_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->udi_reg[id]->csid_udi_cfg0_addr); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index e4c8bafb6303..7bfb0dac4231 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -352,6 +352,7 @@ struct cam_ife_csid_common_reg_offset { uint32_t path_rst_stb_all; uint32_t path_rst_done_shift_val; uint32_t path_en_shift_val; + uint32_t packing_fmt_shift_val; uint32_t dt_id_shift_val; uint32_t vc_shift_val; uint32_t dt_shift_val; From 36765c90e872dc80252fa652ea64efd4de186628 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Thu, 5 Sep 2019 16:47:51 +0530 Subject: [PATCH 091/790] msm: camera: csiphy: Update combo-mode dphy registers for csiphy 1.2 Update register settings for combo-mode dphy to fix UNBOUNDED_FRAME csid error observed on combo-mode sensor. CRs-Fixed: 2521347 Change-Id: I363ad48fc534aa95cc810bf03a0e4704aff6d07b Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 2cf988ac0094..83260c670448 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -14,7 +14,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .mipi_csiphy_glbl_irq_cmd_addr = 0x828, .csiphy_common_array_size = 5, .csiphy_reset_array_size = 4, - .csiphy_2ph_config_array_size = 18, + .csiphy_2ph_config_array_size = 19, .csiphy_3ph_config_array_size = 34, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -63,6 +63,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -83,6 +84,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -103,6 +105,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -123,6 +126,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -143,6 +147,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0600, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -167,6 +172,7 @@ struct csiphy_reg_t {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -187,6 +193,7 @@ struct csiphy_reg_t {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -207,6 +214,7 @@ struct csiphy_reg_t {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -227,6 +235,7 @@ struct csiphy_reg_t {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -247,6 +256,7 @@ struct csiphy_reg_t {0x0600, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, From 70c486722f5c2d4da67147b458281aaf21da1997 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 13 Sep 2019 15:52:38 -0700 Subject: [PATCH 092/790] msm: camera: common: Fix cpas register for custom hw The client handle is obtained by providing client identifier to cpas. Add identifier in custom hw registration for cpas to recognize client. Also, improve identifier string validation in cpas register client. CRs-Fixed: 2528679 Change-Id: I924f5c98a8affa26753710fa542c1bb651d0af13 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_hw.c | 6 ++++++ .../cam_custom_hw1/cam_custom_sub_mod_soc.c | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index c6dddff25e2c..dc7435516875 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1369,6 +1369,12 @@ static int cam_cpas_hw_register_client(struct cam_hw_info *cpas_hw, struct cam_cpas_private_soc *soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + if ((!register_params) || + (strlen(register_params->identifier) < 1)) { + CAM_ERR(CAM_CPAS, "Invalid cpas client identifier"); + return -EINVAL; + } + CAM_DBG(CAM_CPAS, "Register params : identifier=%s, cell_index=%d", register_params->identifier, register_params->cell_index); diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c index 0b517b93c6c0..9011ac9d5291 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c @@ -41,17 +41,20 @@ int cam_custom_hw_sub_mod_init_soc_resources(struct cam_hw_soc_info *soc_info, memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "custom", + 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 = NULL; cpas_register_param.userdata = soc_info; - soc_private->cpas_handle = - cpas_register_param.client_handle; rc = cam_cpas_register_client(&cpas_register_param); if (rc < 0) goto release_soc; + soc_private->cpas_handle = + cpas_register_param.client_handle; + return rc; release_soc: From 3aac10c09fcf9cb7e4530e0db6cb42a026e30768 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 20 Sep 2019 16:58:11 -0700 Subject: [PATCH 093/790] msm: camera: sensor: Update the flash init structure Currently there is mismatch of the cmd type byte position for the flash init structure, which casue the cmd type parsing failure for early PCR. This change move to cmd type to sixth byte to support the unificaiton with other flash uapi structures. Also, update respective header change with respect to uapi change. CRs-Fixed: 2432102 Change-Id: Ic4899b483b35013c5ad77a8894eb3bb4831de811 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_flash/cam_flash_dev.h | 4 ++-- include/uapi/media/cam_sensor.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 43ed13406e3d..29e352e47ce9 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -86,7 +86,7 @@ struct cam_flash_intf_params { struct cam_flash_common_attr { bool is_settings_valid; uint64_t request_id; - uint16_t count; + uint32_t count; uint8_t cmd_type; }; @@ -97,7 +97,7 @@ struct cam_flash_common_attr { */ struct cam_flash_init_packet { struct cam_flash_common_attr cmn_attr; - uint8_t flash_type; + uint32_t flash_type; }; /** diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h index 514e8bd946cd..cc86f2706c63 100644 --- a/include/uapi/media/cam_sensor.h +++ b/include/uapi/media/cam_sensor.h @@ -401,9 +401,10 @@ struct cam_sensor_streamon_dev { * @cmd_type : command buffer type */ struct cam_flash_init { - uint8_t flash_type; - uint16_t reserved; + uint32_t flash_type; + uint8_t reserved; uint8_t cmd_type; + uint16_t reserved1; } __attribute__((packed)); /** From 921bdca4b05bf169195b442561d1ee825e9698d9 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 13 Sep 2019 16:03:28 +0530 Subject: [PATCH 094/790] msm: camera: isp: Skip reapply of DMI config on bubble recovery Updating same DMI bank, which is consumed by HW, can result in violations so during bubble recvery skip updating DMI config. CRs-Fixed: 2511286 Change-Id: I1af2dbf2f1b49afcd4276d3f5759e5ba6d8da637 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_core/cam_hw_mgr_intf.h | 2 ++ drivers/cam_isp/cam_isp_context.c | 7 +++++ drivers/cam_isp/cam_isp_context.h | 2 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 24 ++++++++++++----- .../hw_utils/cam_isp_packet_parser.c | 27 ++++++++++++------- .../hw_utils/include/cam_isp_packet_parser.h | 10 ++++++- 6 files changed, 55 insertions(+), 17 deletions(-) diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 462b30119b50..33c306b2e6dc 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -234,6 +234,7 @@ struct cam_hw_stream_setttings { * @num_out_map_entries: Number of out map entries * @priv: Private pointer * @request_id: Request ID + * @reapply True if reapplying after bubble * */ struct cam_hw_config_args { @@ -245,6 +246,7 @@ struct cam_hw_config_args { void *priv; uint64_t request_id; bool init_packet; + bool reapply; }; /** diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 0df3b063ce63..0af4a5157343 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -633,6 +633,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( } list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); + req_isp->reapply = false; CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", @@ -969,6 +970,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; + req_isp->reapply = true; CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); if (req_isp->bubble_report && ctx->ctx_crm_intf && @@ -1121,6 +1123,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; + req_isp->reapply = true; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { @@ -1891,6 +1894,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state( cfg.num_hw_update_entries = req_isp->num_cfg; cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; + cfg.reapply = req_isp->reapply; rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (rc) { @@ -2037,6 +2041,7 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, req_isp->fence_map_out[i].sync_id = -1; } } + req_isp->reapply = false; list_add_tail(&req->list, &ctx->free_req_list); } @@ -2336,6 +2341,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; + req_isp->reapply = true; CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); if (req_isp->bubble_report && ctx->ctx_crm_intf && @@ -3516,6 +3522,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg; start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; + start_isp.hw_config.reapply = 0; start_isp.start_only = false; atomic_set(&ctx_isp->process_bubble, 0); diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 5aefa690697a..92db4433b429 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -108,6 +108,7 @@ struct cam_isp_ctx_irq_ops { * @bubble_report: Flag to track if bubble report is active on * current request * @hw_update_data: HW update data for this request + * @reapply: True if reapplying after bubble * */ struct cam_isp_ctx_req { @@ -124,6 +125,7 @@ struct cam_isp_ctx_req { int32_t bubble_report; struct cam_isp_prepare_hw_update_data hw_update_data; bool bubble_detected; + bool reapply; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 8e8da8753235..174b022fe004 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3327,7 +3327,7 @@ static int cam_isp_blob_bw_update( static int cam_ife_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) { - int rc = -1, i; + int rc = -1, i, skip = 0; struct cam_hw_config_args *cfg; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; @@ -3398,18 +3398,30 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, if (cfg->num_hw_update_entries > 0) { cdm_cmd = ctx->cdm_cmd; - cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = true; cdm_cmd->userdata = hw_update_data; cdm_cmd->cookie = cfg->request_id; - for (i = 0 ; i <= cfg->num_hw_update_entries; i++) { + for (i = 0 ; i < cfg->num_hw_update_entries; i++) { cmd = (cfg->hw_update_entries + i); - cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle; - cdm_cmd->cmd[i].offset = cmd->offset; - cdm_cmd->cmd[i].len = cmd->len; + + if (cfg->reapply && + cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i - skip].offset = cmd->offset; + cdm_cmd->cmd[i - skip].len = cmd->len; } + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; reinit_completion(&ctx->config_done_complete); ctx->applied_req_id = cfg->request_id; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index b57500c16653..9c95b587df26 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -63,6 +63,9 @@ int cam_isp_add_change_base( hw_entry[num_ent].handle = kmd_buf_info->handle; hw_entry[num_ent].len = get_base.cmd.used_bytes; hw_entry[num_ent].offset = kmd_buf_info->offset; + + /* Marking change base as IOCFG to reapply on bubble */ + hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, @@ -303,10 +306,8 @@ int cam_isp_add_command_buffers( hw_entry[num_ent].handle, hw_entry[num_ent].len, hw_entry[num_ent].offset); - - if (cmd_meta_data == - CAM_ISP_PACKET_META_DMI_LEFT) - hw_entry[num_ent].flags = 0x1; + hw_entry[num_ent].flags = + CAM_ISP_IQ_BL; num_ent++; } @@ -324,10 +325,8 @@ int cam_isp_add_command_buffers( hw_entry[num_ent].handle, hw_entry[num_ent].len, hw_entry[num_ent].offset); - - if (cmd_meta_data == - CAM_ISP_PACKET_META_DMI_RIGHT) - hw_entry[num_ent].flags = 0x1; + hw_entry[num_ent].flags = + CAM_ISP_IQ_BL; num_ent++; } break; @@ -343,8 +342,7 @@ int cam_isp_add_command_buffers( hw_entry[num_ent].handle, hw_entry[num_ent].len, hw_entry[num_ent].offset); - if (cmd_meta_data == CAM_ISP_PACKET_META_DMI_COMMON) - hw_entry[num_ent].flags = 0x1; + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; num_ent++; break; @@ -375,6 +373,7 @@ int cam_isp_add_command_buffers( rc); return rc; } + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; num_ent = prepare->num_hw_update_entries; } break; @@ -397,6 +396,7 @@ int cam_isp_add_command_buffers( rc); return rc; } + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; num_ent = prepare->num_hw_update_entries; } break; @@ -417,6 +417,7 @@ int cam_isp_add_command_buffers( "Failed in processing blobs %d", rc); return rc; } + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; num_ent = prepare->num_hw_update_entries; } break; @@ -819,6 +820,8 @@ int cam_isp_add_io_buffers( prepare->hw_update_entries[num_ent].len = io_cfg_used_bytes; prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; + prepare->hw_update_entries[num_ent].flags = + CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, @@ -919,6 +922,10 @@ int cam_isp_add_reg_update( prepare->hw_update_entries[num_ent].len = reg_update_size; prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; + + /* Marking reg update as IOCFG to reapply on bubble */ + prepare->hw_update_entries[num_ent].flags = + CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index 50161ea001f5..c9bd4c4430e9 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_PARSER_H_ @@ -13,6 +13,14 @@ #include "cam_hw_intf.h" #include "cam_packet_util.h" +/* enum cam_isp_cdm_bl_type - isp cdm packet type*/ +enum cam_isp_cdm_bl_type { + CAM_ISP_UNUSED_BL, + CAM_ISP_IQ_BL, + CAM_ISP_IOCFG_BL, + CAM_ISP_BL_MAX, +}; + /* * struct cam_isp_generic_blob_info * From 68c8d11ebac1a1b7851f0fd77eb6bab8e9cedf28 Mon Sep 17 00:00:00 2001 From: Suresh Vankadara Date: Wed, 21 Aug 2019 11:32:15 +0530 Subject: [PATCH 095/790] msm: camera: config: Add support for BENGAL target Add camera config support for BENGAL target. CRs-Fixed: 2531589 Change-Id: Ie0afa4acdcdcde2286a56f802b4f8246e711503f Signed-off-by: Suresh Vankadara --- Makefile | 9 +++++++++ config/bengalcamera.conf | 4 ++++ config/bengalcameraconf.h | 7 +++++++ 3 files changed, 20 insertions(+) create mode 100644 config/bengalcamera.conf create mode 100644 config/bengalcameraconf.h diff --git a/Makefile b/Makefile index b7c0d7853cc7..9e0b13785b58 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,10 @@ ifeq ($(CONFIG_ARCH_LITO), y) include $(srctree)/techpack/camera/config/litocamera.conf endif +ifeq ($(CONFIG_ARCH_BENGAL), y) +include $(srctree)/techpack/camera/config/bengalcamera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h @@ -19,6 +23,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/litocameraconf.h endif +ifeq ($(CONFIG_ARCH_BENGAL), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/bengalcameraconf.h +endif + ifdef CONFIG_SPECTRA_CAMERA # Use USERINCLUDE when you must reference the UAPI directories only. USERINCLUDE += \ diff --git a/config/bengalcamera.conf b/config/bengalcamera.conf new file mode 100644 index 000000000000..451723eebce3 --- /dev/null +++ b/config/bengalcamera.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2019, The Linux Foundation. All rights reserved. + +export CONFIG_SPECTRA_CAMERA=y diff --git a/config/bengalcameraconf.h b/config/bengalcameraconf.h new file mode 100644 index 000000000000..1a7714018004 --- /dev/null +++ b/config/bengalcameraconf.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 + From af2756b88fba34d61367476d23421ab10eac229a Mon Sep 17 00:00:00 2001 From: Suraj Dongre Date: Mon, 9 Sep 2019 20:26:37 -0700 Subject: [PATCH 096/790] msm: camera: jpeg: Fix jpeg hw hang after flush Add block formatter reset bit missing from reset cmd. CRs-Fixed: 2525580 Change-Id: I17afb362d945952ae63c50621058f1c5748281df Signed-off-by: Suraj Dongre --- .../jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h index 79b0805d0348..e610a9e7ee03 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_ENC_HW_INFO_TITAN170_H @@ -58,7 +58,7 @@ static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = { .int_mask_disable_all = 0x00000000, .int_mask_enable_all = 0xFFFFFFFF, .hw_cmd_start = 0x00000001, - .reset_cmd = 0x00032093, + .reset_cmd = 0x200320D3, .hw_cmd_stop = 0x00000002, }, .int_status = { From 68b30510379236b1e9e9949a152fd73152849ea1 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 19 Sep 2019 14:35:02 +0800 Subject: [PATCH 097/790] msm: camera: reqmgr: Add initial sync support Do the initial sync by SOF timestamp, if the gap between the initial SOF of link and the last SOF of sync link is less than half of frame druation, CRM should abandon this frame since this frame should sync with next frame of sync link. CRs-Fixed: 2492019 Change-Id: I204e3ed49bcf4ac7424aaf5109ad5ce3bc3a2789 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 6 ++ drivers/cam_req_mgr/cam_req_mgr_core.c | 93 ++++++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_core.h | 7 ++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 2 + 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 0af4a5157343..a9dc2663b96f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -787,6 +787,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld ctx %u", @@ -1461,6 +1462,7 @@ static int __cam_isp_ctx_fs2_sof_in_sof_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -1637,6 +1639,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -2249,6 +2252,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -2440,6 +2444,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -2510,6 +2515,7 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index cce35d45b581..4b872824041f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -43,6 +43,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; + link->initial_skip = true; + link->sof_timestamp = 0; + link->prev_sof_timestamp = 0; } void cam_req_mgr_handle_core_shutdown(void) @@ -689,6 +692,19 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.validate_only = validate_only; traverse_data.open_req_cnt = link->open_req_cnt; + /* + * Some no-sync mode requests are processed after link config, + * then process the sync mode requests after no-sync mode requests + * are handled, the initial_skip should be false when processing + * the sync mode requests. + */ + if (link->initial_skip) { + CAM_DBG(CAM_CRM, + "Set initial_skip to false for link %x", + link->link_hdl); + link->initial_skip = false; + } + /* * Traverse through all pd tables, if result is success, * apply the settings @@ -982,6 +998,7 @@ static int __cam_req_mgr_check_sync_req_is_ready( int64_t req_id = 0; int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; int32_t sync_num_slots = 0; + uint64_t sync_frame_duration = 0; bool ready = true, sync_ready = true; if (!link->sync_link) { @@ -997,6 +1014,57 @@ static int __cam_req_mgr_check_sync_req_is_ready( "link_hdl %x req %lld frame_skip_flag %d ", link->link_hdl, req_id, link->sync_link_sof_skip); + if (sync_link->initial_skip) { + link->initial_skip = false; + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + CAM_DBG(CAM_CRM, + "sync link %x not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + if (sync_link->prev_sof_timestamp) + sync_frame_duration = sync_link->sof_timestamp - + sync_link->prev_sof_timestamp; + else + sync_frame_duration = DEFAULT_FRAME_DURATION; + + CAM_DBG(CAM_CRM, + "sync link %x last frame_duration is %d ns", + sync_link->link_hdl, sync_frame_duration); + + if (link->initial_skip) { + link->initial_skip = false; + + if ((link->sof_timestamp > sync_link->sof_timestamp) && + (sync_link->sof_timestamp > 0) && + (link->sof_timestamp - sync_link->sof_timestamp) < + (sync_frame_duration / 2)) { + /* + * If this frame sync with the previous frame of sync + * link, then we need to skip this frame, since the + * previous frame of sync link is also skipped. + */ + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + CAM_DBG(CAM_CRM, + "This frame sync with previous sync_link %x frame", + sync_link->link_hdl); + return -EAGAIN; + } else if (link->sof_timestamp <= sync_link->sof_timestamp) { + /* + * Sometimes, link receives the SOF event is eariler + * than sync link in IFE CSID side, but link's SOF + * event is processed later than sync link's, then + * we need to skip this SOF event since the sync + * link's SOF event is also skipped. + */ + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + CAM_DBG(CAM_CRM, + "The previous frame of sync link is skipped"); + return -EAGAIN; + } + } + if (sync_link->sync_link_sof_skip) { CAM_DBG(CAM_REQ, "No req applied on corresponding SOF on sync link: %x", @@ -1097,10 +1165,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( * */ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, - uint32_t trigger) + struct cam_req_mgr_trigger_notify *trigger_data) { int rc = 0, idx; int reset_step = 0; + uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_core_session *session; @@ -1139,6 +1208,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } if (trigger == CAM_TRIGGER_POINT_SOF) { + /* + * Update the timestamp in session lock protection + * to avoid timing issue. + */ + link->prev_sof_timestamp = link->sof_timestamp; + link->sof_timestamp = trigger_data->sof_timestamp_val; + if (link->trigger_mask) { CAM_ERR_RATE_LIMIT(CAM_CRM, "Applying for last EOF fails"); @@ -2225,7 +2301,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) __cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots); } - rc = __cam_req_mgr_process_req(link, trigger_data->trigger); + rc = __cam_req_mgr_process_req(link, trigger_data); release_lock: mutex_unlock(&link->req.lock); @@ -2456,6 +2532,7 @@ static int cam_req_mgr_cb_notify_trigger( notify_trigger->link_hdl = trigger_data->link_hdl; notify_trigger->dev_hdl = trigger_data->dev_hdl; notify_trigger->trigger = trigger_data->trigger; + notify_trigger->sof_timestamp_val = trigger_data->sof_timestamp_val; task->process_cb = &cam_req_mgr_process_trigger; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); @@ -3215,8 +3292,6 @@ int cam_req_mgr_sync_config( 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; @@ -3227,6 +3302,16 @@ int cam_req_mgr_sync_config( link1->sync_link = link2; link2->sync_link = link1; __cam_req_mgr_set_master_link(link1, link2); + } else { + /* + * Reset below info after the mode is configured + * to NO-SYNC mode since they may be overridden + * if the sync config is invoked after SOF comes. + */ + link1->initial_skip = true; + link2->initial_skip = true; + link1->sof_timestamp = 0; + link2->sof_timestamp = 0; } cam_session->sync_mode = sync_info->sync_mode; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 3837c1cd8061..c790ce824244 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -25,6 +25,9 @@ #define MAX_SYNC_COUNT 65535 +/* Default frame rate is 30 */ +#define DEFAULT_FRAME_DURATION 33333333 + #define SYNC_LINK_SOF_CNT_MAX_LMT 1 #define MAXIMUM_LINKS_PER_SESSION 4 @@ -334,6 +337,8 @@ struct cam_req_mgr_connected_device { * the same req * @is_shutdown : Flag to indicate if link needs to be disconnected * as part of shutdown. + * @sof_timestamp_value : SOF timestamp value + * @prev_sof_timestamp : Previous SOF timestamp value */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -362,6 +367,8 @@ struct cam_req_mgr_core_link { int64_t initial_sync_req; uint32_t retry_cnt; bool is_shutdown; + uint64_t sof_timestamp; + uint64_t prev_sof_timestamp; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 551bc85ae73c..f4b662dd4138 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -196,12 +196,14 @@ enum cam_req_mgr_link_evt_type { * @frame_id : frame id for internal tracking * @trigger : trigger point of this notification, CRM will send apply * only to the devices which subscribe to this point. + * @sof_timestamp_val: Captured time stamp value at sof hw event */ struct cam_req_mgr_trigger_notify { int32_t link_hdl; int32_t dev_hdl; int64_t frame_id; uint32_t trigger; + uint64_t sof_timestamp_val; }; /** From 6b38f7e1bf78b68bb47a472c08ae944409abd2a6 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 19 Sep 2019 14:44:53 +0800 Subject: [PATCH 098/790] msm: camera: reqmgr: Verify the req of two links The req of two links should be same if current frame sync with previous frame of sync link, CRM can do self-correction based on this condition. CRs-Fixed: 2492019 Change-Id: Idb208958a850ec1fe12f12443e7ecc2e126970d8 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 53 ++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 4b872824041f..97e1dce27f8d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -995,7 +995,8 @@ static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_slot *slot) { struct cam_req_mgr_core_link *sync_link = NULL; - int64_t req_id = 0; + struct cam_req_mgr_slot *sync_rd_slot = NULL; + int64_t req_id = 0, sync_req_id = 0; int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; int32_t sync_num_slots = 0; uint64_t sync_frame_duration = 0; @@ -1009,6 +1010,9 @@ static int __cam_req_mgr_check_sync_req_is_ready( sync_link = link->sync_link; req_id = slot->req_id; sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; CAM_DBG(CAM_REQ, "link_hdl %x req %lld frame_skip_flag %d ", @@ -1091,12 +1095,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EAGAIN; } - 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 + sync_num_slots) % sync_num_slots) >= 1) && - (sync_link->req.in_q->slot[sync_rd_idx].status != + (sync_rd_slot->status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Req: %lld [other link] not next req to be applied on link: %x", @@ -1129,7 +1132,14 @@ static int __cam_req_mgr_check_sync_req_is_ready( CAM_DBG(CAM_CRM, "Req: %lld ready %d sync_ready %d, ignore sync link next SOF", req_id, ready, sync_ready); - link->sync_link_sof_skip = true; + + /* + * Only skip the frames if current frame sync with + * next frame of sync link. + */ + if (link->sof_timestamp - sync_link->sof_timestamp > + sync_frame_duration / 2) + link->sync_link_sof_skip = true; return -EINVAL; } else if (ready == false) { CAM_DBG(CAM_CRM, @@ -1138,6 +1148,41 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EINVAL; } + /* + * Do the self-correction when the frames are sync, + * we consider that the frames are synced if the + * difference of two SOF timestamp less than + * (sync_frame_duration / 5). + */ + if ((link->sof_timestamp > sync_link->sof_timestamp) && + (sync_link->sof_timestamp > 0) && + (link->sof_timestamp - sync_link->sof_timestamp < + sync_frame_duration / 5) && + (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { + + /* + * This means current frame should sync with next + * frame of sync link, then the request id of in + * rd slot of two links should be same. + */ + CAM_DBG(CAM_CRM, + "link %x req_id %lld, sync_link %x req_id %lld", + link->link_hdl, req_id, + sync_link->link_hdl, sync_req_id); + + if (req_id > sync_req_id) { + CAM_DBG(CAM_CRM, + "link %x too quickly, skip this frame", + link->link_hdl); + return -EAGAIN; + } else if (req_id < sync_req_id) { + CAM_DBG(CAM_CRM, + "sync link %x too quickly, skip next frame of sync link", + sync_link->link_hdl); + link->sync_link_sof_skip = true; + } + } + CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); From 2424e34228bd5cb4c3b0e02d406488ca406ec674 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 19 Sep 2019 14:20:15 +0530 Subject: [PATCH 099/790] msm: camera: isp: Register only one irq handler for rdi only context If RDI only context has two rdi ports enabled, then register single irq handler for both ports. This change help registering only one irq handlers for rdi only context. CRs-Fixed: 2521064 Change-Id: I201cf62b73dbfb20636821213afc7f2a4d6cf13c Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 18 ++++++++++++++++-- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 2 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 174b022fe004..598a836134ac 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -335,8 +335,6 @@ static int cam_ife_hw_mgr_start_hw_res( continue; hw_intf = isp_hw_res->hw_res[i]->hw_intf; if (hw_intf->hw_ops.start) { - isp_hw_res->hw_res[i]->rdi_only_ctx = - ctx->is_rdi_only_context; rc = hw_intf->hw_ops.start(hw_intf->hw_priv, isp_hw_res->hw_res[i], sizeof(struct cam_isp_resource_node)); @@ -3843,6 +3841,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_ife_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *rsrc_node = NULL; uint32_t i, camif_debug; + bool res_rdi_context_set = false; if (!hw_mgr_priv || !start_isp) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -3967,6 +3966,21 @@ start_only: ctx->ctx_index); /* Start the IFE mux in devices */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + switch (hw_mgr_res->res_id) { + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + if (!res_rdi_context_set) { + hw_mgr_res->hw_res[0]->rdi_only_ctx = + ctx->is_rdi_only_context; + res_rdi_context_set = true; + } + break; + default: + break; + } + rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); if (rc) { CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index 0fe61247055a..fba9f2afca21 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -225,7 +225,7 @@ int cam_vfe_camif_lite_ver3_acquire_resource( camif_lite_data->sync_mode = acquire_data->vfe_in.sync_mode; camif_lite_data->event_cb = acquire_data->event_cb; camif_lite_data->priv = acquire_data->priv; - + camif_lite_res->rdi_only_ctx = 0; CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF LITE:%d sync_mode=%d", camif_lite_res->hw_intf->hw_idx, camif_lite_res->res_id, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index 381de6b48fe9..7aaacde775f4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -201,6 +201,7 @@ int cam_vfe_rdi_ver2_acquire_resource( rdi_data->event_cb = acquire_data->event_cb; rdi_data->priv = acquire_data->priv; rdi_data->sync_mode = acquire_data->vfe_in.sync_mode; + rdi_res->rdi_only_ctx = 0; return 0; } From 6761d7b872b77b8e1a1caa3e34a377ea64c43974 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 20 Sep 2019 11:12:33 -0700 Subject: [PATCH 100/790] msm: camera: cpas: Change to enable bus scaling for AHB This change scales BW voting with src clock voltage corner. Adds a debugfs to disable this scaling. CRs-Fixed: 2531856 Change-Id: I266e34ca81f635954e60648366bcc4792f90fdb6 Signed-off-by: Karthik Anantha Ram --- drivers/cam_cpas/cam_cpas_hw.c | 9 +++++---- drivers/cam_cpas/cam_cpas_hw.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index dc7435516875..7ee738da4748 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -932,7 +932,7 @@ static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw, CAM_DBG(CAM_CPAS, "Required highest_level[%d]", highest_level); - if (cpas_core->ahb_bus_scaling_enable) { + if (!cpas_core->ahb_bus_scaling_disable) { rc = cam_cpas_util_vote_bus_client_level(ahb_bus_client, highest_level); if (rc) { @@ -1678,12 +1678,12 @@ static int cam_cpas_util_create_debugfs( if (!cpas_core->dentry) return -ENOMEM; - if (!debugfs_create_bool("ahb_bus_scaling_enable", + if (!debugfs_create_bool("ahb_bus_scaling_disable", 0644, cpas_core->dentry, - &cpas_core->ahb_bus_scaling_enable)) { + &cpas_core->ahb_bus_scaling_disable)) { CAM_ERR(CAM_CPAS, - "failed to create ahb_bus_scaling_enable entry"); + "failed to create ahb_bus_scaling_disable entry"); rc = -ENOMEM; goto err; } @@ -1735,6 +1735,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, cpas_hw->soc_info.dev = &pdev->dev; cpas_hw->soc_info.dev_name = pdev->name; cpas_hw->open_count = 0; + cpas_core->ahb_bus_scaling_disable = false; mutex_init(&cpas_hw->hw_mutex); spin_lock_init(&cpas_hw->hw_lock); init_completion(&cpas_hw->hw_complete); diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index 2b02fc411ff4..b3c01b3ee737 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -184,7 +184,7 @@ struct cam_cpas_axi_port { * @irq_count: atomic irq count * @irq_count_wq: wait variable to ensure all irq's are handled * @dentry: debugfs file entry - * @ahb_bus_scaling_enable: ahb scaling based on src clk corner for bus + * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; @@ -203,7 +203,7 @@ struct cam_cpas { atomic_t irq_count; wait_queue_head_t irq_count_wq; struct dentry *dentry; - bool ahb_bus_scaling_enable; + bool ahb_bus_scaling_disable; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); From f7d89d9bed88cf60f91c712b7cc3dd8cc1b535f9 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 23 Sep 2019 15:23:30 -0700 Subject: [PATCH 101/790] msm: camera: isp: Disable tasklet once This changes avoids disabling and killing inactive tasklet. CRs-Fixed: 2530034 Change-Id: If1b0b04684f9425f742b51e5eb4b6ec8107f2c75 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c index a8ff7ff01e11..458894f96a1b 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c @@ -296,6 +296,9 @@ void cam_tasklet_stop(void *tasklet_info) { struct cam_tasklet_info *tasklet = tasklet_info; + if (!atomic_read(&tasklet->tasklet_active)) + return; + atomic_set(&tasklet->tasklet_active, 0); tasklet_kill(&tasklet->tasklet); tasklet_disable(&tasklet->tasklet); From 00abd8fedadfa547403789512d1e7a89a84dd5d6 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 11 Sep 2019 15:54:56 -0700 Subject: [PATCH 102/790] msm: camera: isp: Add check for last flush request ID This change adds a check for last flush request ID before adding bubbled request to pending list. This prevents the request from sitting in pending list indefinitely. CRs-Fixed: 2533433 Change-Id: I82d641d42fe507e8eabf0bee0e9a2f0b98d9a802 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index a9dc2663b96f..cfb6a0accd7f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -619,12 +619,26 @@ static int __cam_isp_ctx_handle_buf_done_for_request( req_isp->num_acked = 0; 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], ctx %u", - req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); + if (buf_done_req_id <= ctx->last_flush_req) { + for (i = 0; i < req_isp->num_fence_map_out; i++) + cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + + list_add_tail(&req->list, &ctx->free_req_list); + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", + buf_done_req_id, ctx_isp->active_req_cnt, + ctx->ctx_id); + } else { + list_add(&req->list, &ctx->pending_req_list); + CAM_DBG(CAM_REQ, + "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 { if (ctx_isp->reported_req_id < buf_done_req_id) { ctx_isp->reported_req_id = buf_done_req_id; From 0eee5ccc3f77e56063cc8652c8b6a1c1fab12a32 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 17 Sep 2019 15:49:27 -0700 Subject: [PATCH 103/790] msm: camera: icp: Handle RT/NRT flags for IPE/BPS device types The device type is only needed to create the handle with FW, internally to the KMD we can unify the different device types. CRs-Fixed: 2534504 Change-Id: I92b77f54556d840f49136ea187df939350951078 Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a63c7f72bb31..91d87ecb3f6a 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -5061,6 +5061,9 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto acquire_info_failed; icp_dev_acquire_info = ctx_data->icp_dev_acquire_info; + dev_type = icp_dev_acquire_info->dev_type; + icp_dev_acquire_info->dev_type = + cam_icp_unify_dev_type(dev_type); CAM_DBG(CAM_ICP, "acquire io buf handle %d", icp_dev_acquire_info->io_config_cmd_handle); @@ -5109,7 +5112,7 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } CAM_DBG(CAM_ICP, "ping ack received"); - rc = cam_icp_mgr_create_handle(icp_dev_acquire_info->dev_type, + rc = cam_icp_mgr_create_handle(dev_type, ctx_data); if (rc) { CAM_ERR(CAM_ICP, "create handle failed"); @@ -5118,7 +5121,7 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) CAM_DBG(CAM_ICP, "created stream handle for dev_type %u", - icp_dev_acquire_info->dev_type); + dev_type); cmd_mem_region.num_regions = 1; cmd_mem_region.map_info_array[0].mem_handle = @@ -5179,13 +5182,11 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) /* Start context timer*/ cam_icp_ctx_timer_start(ctx_data); hw_mgr->ctxt_cnt++; - dev_type = cam_icp_unify_dev_type(icp_dev_acquire_info->dev_type); - icp_dev_acquire_info->dev_type = dev_type; mutex_unlock(&hw_mgr->hw_mgr_mutex); CAM_DBG(CAM_ICP, "Acquire Done for ctx_id %u dev type %d", ctx_data->ctx_id, - icp_dev_acquire_info->dev_type); + ctx_data->icp_dev_acquire_info->dev_type); return 0; From 3d8cdd5b7a702109caac471196fcea4edb82ec61 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Thu, 26 Sep 2019 17:46:39 -0700 Subject: [PATCH 104/790] msm: camera: ife: Assign primary RDI during start HW This change sets primary RDI source and out resources for a particular RDI only Context. This information is utilized during start HW resource to tell the driver if it should subscribe to IRQs. CRs-Fixed: 2521064 Change-Id: Ia5567b4432603db993c4783e60721be144c619f9 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 52 ++++++++++++++----- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 1 + 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 598a836134ac..aad24ae88cc2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1471,6 +1471,19 @@ static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) return rc; } +static int cam_convert_rdi_out_res_id_to_src(int res_id) +{ + if (res_id == CAM_ISP_IFE_OUT_RES_RDI_0) + return CAM_ISP_HW_VFE_IN_RDI0; + else if (res_id == CAM_ISP_IFE_OUT_RES_RDI_1) + return CAM_ISP_HW_VFE_IN_RDI1; + else if (res_id == CAM_ISP_IFE_OUT_RES_RDI_2) + return CAM_ISP_HW_VFE_IN_RDI2; + else if (res_id == CAM_ISP_IFE_OUT_RES_RDI_3) + return CAM_ISP_HW_VFE_IN_RDI3; + return CAM_ISP_HW_VFE_IN_MAX; +} + static int cam_convert_res_id_to_hw_path(int res_id) { if (res_id == CAM_ISP_HW_VFE_IN_LCR) @@ -3842,6 +3855,11 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_isp_resource_node *rsrc_node = NULL; uint32_t i, camif_debug; bool res_rdi_context_set = false; + uint32_t primary_rdi_src_res; + uint32_t primary_rdi_out_res; + + primary_rdi_src_res = CAM_ISP_HW_VFE_IN_MAX; + primary_rdi_out_res = CAM_ISP_IFE_OUT_RES_MAX; if (!hw_mgr_priv || !start_isp) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -3941,6 +3959,22 @@ start_only: ctx->ctx_index); /* start the IFE out devices */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + hw_mgr_res = &ctx->res_list_ife_out[i]; + switch (hw_mgr_res->res_id) { + case CAM_ISP_IFE_OUT_RES_RDI_0: + case CAM_ISP_IFE_OUT_RES_RDI_1: + case CAM_ISP_IFE_OUT_RES_RDI_2: + case CAM_ISP_IFE_OUT_RES_RDI_3: + if (!res_rdi_context_set && ctx->is_rdi_only_context) { + hw_mgr_res->hw_res[0]->rdi_only_ctx = + ctx->is_rdi_only_context; + res_rdi_context_set = true; + primary_rdi_out_res = hw_mgr_res->res_id; + } + break; + default: + break; + } rc = cam_ife_hw_mgr_start_hw_res( &ctx->res_list_ife_out[i], ctx); if (rc) { @@ -3962,23 +3996,17 @@ start_only: } } + if (primary_rdi_out_res < CAM_ISP_IFE_OUT_RES_MAX) + primary_rdi_src_res = + cam_convert_rdi_out_res_id_to_src(primary_rdi_out_res); + CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d", ctx->ctx_index); /* Start the IFE mux in devices */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { - switch (hw_mgr_res->res_id) { - case CAM_ISP_HW_VFE_IN_RDI0: - case CAM_ISP_HW_VFE_IN_RDI1: - case CAM_ISP_HW_VFE_IN_RDI2: - case CAM_ISP_HW_VFE_IN_RDI3: - if (!res_rdi_context_set) { - hw_mgr_res->hw_res[0]->rdi_only_ctx = + if (primary_rdi_src_res == hw_mgr_res->res_id) { + hw_mgr_res->hw_res[0]->rdi_only_ctx = ctx->is_rdi_only_context; - res_rdi_context_set = true; - } - break; - default: - break; } rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 9cdaeaa834c9..09407894b52a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1971,6 +1971,7 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, ver3_bus_priv->tasklet_info = acq_args->tasklet; rsrc_data->num_wm = num_wm; + rsrc_node->rdi_only_ctx = 0; rsrc_node->res_id = out_acquire_args->out_port_info->res_type; rsrc_node->tasklet_info = acq_args->tasklet; rsrc_node->cdm_ops = out_acquire_args->cdm_ops; From a5dc6c6caca6579ad4d846f58b7ebf6845abad3b Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 15 Aug 2019 13:07:05 -0700 Subject: [PATCH 105/790] msm: camera: ife: Do not enable CAMIF by default This change removes enabling CAMIF and CAMIF Lite module config programming by default. Henceforth these settings must be programmed by the userspace by adding them in command buffers. CRs-Fixed: 2513939 Change-Id: I739a57a392974056f358820f77bc2ae40451d9d6 Signed-off-by: Venkat Chinta --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 4 ---- .../isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 9 --------- 2 files changed, 13 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index fba9f2afca21..495e4afbd50a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -294,10 +294,6 @@ static int cam_vfe_camif_lite_resource_start( rsrc_data->camif_lite_reg->lite_epoch_irq); skip_core_cfg: - /* Enable Camif */ - cam_io_w_mb(0x1, - rsrc_data->mem_base + - rsrc_data->camif_lite_reg->lite_module_config); camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 8cf2fa9f7f93..c390b6f542d4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -377,15 +377,6 @@ static int cam_vfe_camif_ver3_resource_start( cam_io_w_mb(rsrc_data->reg_data->top_debug_cfg_en, rsrc_data->mem_base + rsrc_data->common_reg->top_debug_cfg); - /*config vfe core*/ - val = (rsrc_data->pix_pattern << - rsrc_data->reg_data->pixel_pattern_shift); - val |= (1 << rsrc_data->reg_data->pp_camif_cfg_en_shift); - val |= (1 << rsrc_data->reg_data->pp_camif_cfg_ife_out_en_shift); - cam_io_w_mb(val, - rsrc_data->mem_base + rsrc_data->camif_reg->module_cfg); - CAM_DBG(CAM_ISP, "write module_cfg val = 0x%X", val); - val = cam_io_r_mb(rsrc_data->mem_base + rsrc_data->common_reg->core_cfg_0); From 92a98f613795187d826ce0e2d012fbc1e1648b17 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 26 Sep 2019 19:24:40 -0700 Subject: [PATCH 106/790] msm: camera: ife: Add packing format support This change adds packing format field for CSID in IFE Lite for version 480 hardware. CRs-Fixed: 2537287 Change-Id: Ifa46b07218fefe46721f99e65291837500c413de Signed-off-by: Venkat Chinta --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h index 7d9a53567ee6..b77f2dfa350e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite480.h @@ -305,6 +305,7 @@ static struct cam_ife_csid_common_reg_offset .path_rst_stb_all = 0x7f, .path_rst_done_shift_val = 1, .path_en_shift_val = 31, + .packing_fmt_shift_val = 30, .dt_id_shift_val = 27, .vc_shift_val = 22, .dt_shift_val = 16, From aaab1ef87ebf45190016cdd36b6178795897d9d0 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 2 Aug 2019 16:03:51 -0700 Subject: [PATCH 107/790] msm: camera: isp: Stop HW immediately in flush When the userspace issues flush, ISP driver needs to ensure that wait and active list requests are flushed and corresponding buffer fences are signaled with error. For active and wait lists IFE hardware is stopped immediately. Therefore IFE must also be reset to ensure that VFE BUS FIFOs are cleared. Start IFE HW after receiving init packet again. CRs-Fixed: 2513939 Change-Id: I9a35ce05c24d6b63016e264a870d376eabb2b56f Signed-off-by: Venkat Chinta --- drivers/cam_core/cam_context.h | 5 +- drivers/cam_core/cam_hw_mgr_intf.h | 12 ++ drivers/cam_cust/cam_custom_context.c | 2 + drivers/cam_fd/cam_fd_context.c | 2 + drivers/cam_icp/cam_icp_context.c | 2 + drivers/cam_isp/cam_isp_context.c | 129 +++++++++++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 70 ++++++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 22 +-- drivers/cam_lrme/cam_lrme_context.c | 2 + 9 files changed, 216 insertions(+), 30 deletions(-) diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 854ea0067a27..2c1c685e76b8 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -32,8 +32,9 @@ enum cam_context_state { CAM_CTX_AVAILABLE = 1, CAM_CTX_ACQUIRED = 2, CAM_CTX_READY = 3, - CAM_CTX_ACTIVATED = 4, - CAM_CTX_STATE_MAX = 5, + CAM_CTX_FLUSHED = 4, + CAM_CTX_ACTIVATED = 5, + CAM_CTX_STATE_MAX = 6, }; /** diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 33c306b2e6dc..28426b8dc757 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -287,6 +287,16 @@ struct cam_hw_dump_pf_args { bool *mem_found; }; +/** + * struct cam_hw_reset_args -hw reset arguments + * + * @ctxt_to_hw_map: HW context from the acquire + * + */ +struct cam_hw_reset_args { + void *ctxt_to_hw_map; +}; + /* enum cam_hw_mgr_command - Hardware manager command type */ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, @@ -341,6 +351,7 @@ struct cam_hw_cmd_args { * @hw_open: Function pointer for HW init * @hw_close: Function pointer for HW deinit * @hw_flush: Function pointer for HW flush + * @hw_reset: Function pointer for HW reset * */ struct cam_hw_mgr_intf { @@ -361,6 +372,7 @@ struct cam_hw_mgr_intf { int (*hw_open)(void *hw_priv, void *fw_download_args); int (*hw_close)(void *hw_priv, void *hw_close_args); int (*hw_flush)(void *hw_priv, void *hw_flush_args); + int (*hw_reset)(void *hw_priv, void *hw_reset_args); }; #endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 5709530f7bf3..7f38392a7d57 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -874,6 +874,8 @@ static struct cam_ctx_ops .irq_ops = NULL, .pagefault_ops = NULL, }, + /* Flushed */ + {}, /* Activated */ { .ioctl_ops = { diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index 8805859abb00..ec6468f85dc0 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -189,6 +189,8 @@ static struct cam_ctx_ops .crm_ops = {}, .irq_ops = NULL, }, + /* Flushed */ + {}, /* Activated */ { .ioctl_ops = { diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 34c5a60fe826..7d2ef39e0aeb 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -250,6 +250,8 @@ static struct cam_ctx_ops .irq_ops = __cam_icp_handle_buf_done_in_ready, .pagefault_ops = cam_icp_context_dump_active_request, }, + /* Flushed */ + {}, /* Activated */ { .ioctl_ops = {}, diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index cfb6a0accd7f..2a3c6dbfcc61 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -31,6 +31,9 @@ static struct cam_isp_ctx_debug isp_ctx_debug; static int cam_isp_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info); +static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd); + static void __cam_isp_ctx_update_state_monitor_array( struct cam_isp_context *ctx_isp, enum cam_isp_state_change_trigger trigger_type, @@ -2072,13 +2075,15 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, } static int __cam_isp_ctx_flush_req_in_top_state( - struct cam_context *ctx, + struct cam_context *ctx, struct cam_req_mgr_flush_request *flush_req) { - int rc = 0; - struct cam_isp_context *ctx_isp; - struct cam_hw_cmd_args hw_cmd_args; - + int rc = 0; + struct cam_isp_context *ctx_isp; + struct cam_isp_stop_args stop_isp; + struct cam_hw_stop_args stop_args; + struct cam_hw_reset_args reset_args; + struct cam_hw_cmd_args hw_cmd_args; ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { @@ -2087,7 +2092,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( ctx->last_flush_req = flush_req->req_id; } - CAM_DBG(CAM_ISP, "try to flush pending list"); + CAM_DBG(CAM_ISP, "Flush pending list"); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); spin_unlock_bh(&ctx->lock); @@ -2102,6 +2107,47 @@ static int __cam_isp_ctx_flush_req_in_top_state( rc = 0; } + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + if (ctx->state <= CAM_CTX_READY) { + ctx->state = CAM_CTX_ACQUIRED; + goto end; + } + + stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; + stop_isp.stop_only = true; + stop_args.args = (void *)&stop_isp; + rc = ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop_args); + if (rc) + CAM_ERR(CAM_ISP, "Failed to stop HW in Flush rc: %d", + rc); + + CAM_DBG(CAM_ISP, "Flush wait and active lists"); + spin_lock_bh(&ctx->lock); + if (!list_empty(&ctx->wait_req_list)) + rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, + flush_req); + + if (!list_empty(&ctx->active_req_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); + + reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, + &reset_args); + if (rc) + CAM_ERR(CAM_ISP, "Failed to reset HW rc: %d", rc); + + ctx->state = CAM_CTX_FLUSHED; + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; + ctx_isp->init_received = false; + } + +end: atomic_set(&ctx_isp->process_bubble, 0); return rc; } @@ -3454,6 +3500,55 @@ static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_isp_ctx_config_dev_in_flushed(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc = 0; + struct cam_start_stop_dev_cmd start_cmd; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + if (!ctx_isp->hw_acquired) { + CAM_ERR(CAM_ISP, "HW is not acquired, reject packet"); + return -EINVAL; + } + + rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd); + if (rc) + return rc; + + if (!ctx_isp->init_received) { + CAM_WARN(CAM_ISP, + "Received update packet in flushed state, skip start"); + goto end; + } + + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW; + 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); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to resume HW rc: %d", rc); + return rc; + } + + start_cmd.dev_handle = cmd->dev_handle; + start_cmd.session_handle = cmd->session_handle; + rc = __cam_isp_ctx_start_dev_in_ready(ctx, &start_cmd); + if (rc) + CAM_ERR(CAM_ISP, + "Failed to re-start HW after flush rc: %d", rc); + +end: + CAM_DBG(CAM_ISP, "next state %d sub_state:%d", ctx->state, + ctx_isp->substate_activated); + return rc; +} + static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *link) { @@ -3543,7 +3638,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; - start_isp.start_only = false; + + if (ctx->state == CAM_CTX_FLUSHED) + start_isp.start_only = true; + else + start_isp.start_only = false; atomic_set(&ctx_isp->process_bubble, 0); ctx_isp->frame_id = 0; @@ -3966,6 +4065,22 @@ static struct cam_ctx_ops .pagefault_ops = cam_isp_context_dump_active_request, .dumpinfo_ops = cam_isp_context_info_dump, }, + /* Flushed */ + { + .ioctl_ops = { + .stop_dev = __cam_isp_ctx_stop_dev_in_activated, + .release_dev = __cam_isp_ctx_release_dev_in_activated, + .config_dev = __cam_isp_ctx_config_dev_in_flushed, + .release_hw = __cam_isp_ctx_release_hw_in_activated, + }, + .crm_ops = { + .unlink = __cam_isp_ctx_unlink_in_ready, + .process_evt = __cam_isp_ctx_process_evt, + }, + .irq_ops = NULL, + .pagefault_ops = cam_isp_context_dump_active_request, + .dumpinfo_ops = cam_isp_context_info_dump, + }, /* Activated */ { .ioctl_ops = { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index aad24ae88cc2..b9150e818dc5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -368,6 +368,11 @@ static void cam_ife_hw_mgr_stop_hw_res( if (!isp_hw_res->hw_res[i]) continue; hw_intf = isp_hw_res->hw_res[i]->hw_intf; + + if (isp_hw_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING) + continue; + if (hw_intf->hw_ops.stop) hw_intf->hw_ops.stop(hw_intf->hw_priv, isp_hw_res->hw_res[i], @@ -794,7 +799,9 @@ static int cam_ife_mgr_csid_stop_hw( cnt = 0; list_for_each_entry(hw_mgr_res, stop_list, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (!hw_mgr_res->hw_res[i]) + if (!hw_mgr_res->hw_res[i] || + (hw_mgr_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING)) continue; isp_res = hw_mgr_res->hw_res[i]; @@ -2722,6 +2729,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) cdm_acquire.handle); ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_ops = cdm_acquire.ops; + atomic_set(&ife_ctx->cdm_done, 1); acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; @@ -2910,6 +2918,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) cdm_acquire.handle); ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_ops = cdm_acquire.ops; + atomic_set(&ife_ctx->cdm_done, 1); isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; @@ -3623,13 +3632,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index); stop_isp = (struct cam_isp_stop_args *)stop_args->args; - if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_IMMEDIATELY) && - (stop_isp->stop_only)) { - CAM_ERR(CAM_ISP, "Invalid params hw_stop_cmd:%d stop_only:%d", - stop_isp->hw_stop_cmd, stop_isp->stop_only); - return -EPERM; - } - /* Set the csid halt command */ if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY; @@ -3663,7 +3665,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* Stop the master CSID path first */ cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, - master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY); + master_base_idx, csid_halt_type); /* stop rest of the CSID paths */ for (i = 0; i < ctx->num_base; i++) { @@ -3673,7 +3675,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) ctx->base[i].idx, i, master_base_idx); cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, - ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY); + ctx->base[i].idx, csid_halt_type); } CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx); @@ -3714,6 +3716,8 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_pause_hw(ctx); + wait_for_completion(&ctx->config_done_complete); + if (stop_isp->stop_only) goto end; @@ -3945,6 +3949,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) goto safe_disable; } +start_only: /* Apply initial configuration */ CAM_DBG(CAM_ISP, "Config HW"); rc = cam_ife_mgr_config_hw(hw_mgr_priv, &start_isp->hw_config); @@ -3953,8 +3958,6 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) goto cdm_streamoff; } -start_only: - CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); /* start the IFE out devices */ @@ -4081,6 +4084,48 @@ static int cam_ife_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_ife_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) +{ + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_reset_args *reset_args = hw_reset_args; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr_res; + int rc = 0, i = 0; + + if (!hw_mgr_priv || !hw_reset_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)reset_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "Reset CSID and VFE"); + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + rc = cam_ife_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to reset CSID:%d rc: %d", + hw_mgr_res->res_id, rc); + goto end; + } + } + + for (i = 0; i < ctx->num_base; i++) { + rc = cam_ife_mgr_reset_vfe_hw(hw_mgr, ctx->base[i].idx); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to reset VFE:%d rc: %d", + ctx->base[i].idx, rc); + goto end; + } + } + +end: + return rc; +} + static int cam_ife_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) { @@ -6807,6 +6852,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; + hw_mgr_intf->hw_reset = cam_ife_mgr_reset; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index f3a4d967deaa..256fea2e5bbd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -657,10 +657,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, init_completion(complete); reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all; - /* Enable the Test gen before reset */ - cam_io_w_mb(1, csid_hw->hw_info->soc_info.reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - /* Reset the corresponding ife csid path */ cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + reset_strb_addr); @@ -675,10 +671,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, rc = -ETIMEDOUT; } - /* Disable Test Gen after reset*/ - cam_io_w_mb(0, soc_info->reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - end: return rc; @@ -2101,7 +2093,7 @@ static int cam_ife_csid_disable_pxl_path( if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) { - /* configure Halt */ + /* configure Halt for master */ val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_ctrl_addr); val &= ~0x3; @@ -2110,6 +2102,18 @@ static int cam_ife_csid_disable_pxl_path( pxl_reg->csid_pxl_ctrl_addr); } + if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE && + stop_cmd == CAM_CSID_HALT_IMMEDIATELY) { + /* configure Halt for slave */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val &= ~0xF; + val |= stop_cmd; + val |= (CSID_HALT_MODE_MASTER << 2); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + } + return rc; } diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index ae8f93c500ef..fa544c7a089e 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -190,6 +190,8 @@ static struct cam_ctx_ops .crm_ops = {}, .irq_ops = NULL, }, + /* Flushed */ + {}, /* Activate */ { .ioctl_ops = { From 102db1e4e53d1cc4281e67db64a462e5045b55c8 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 27 Sep 2019 15:24:07 -0700 Subject: [PATCH 108/790] msm: camera: isp: Fix no reg dump when EPCR is enabled During second init request of EPCR, number of reg dump buffers was set to zero causing no reg dump. Add fix to ensure value is updated to ife ctx when it is non zero. CRs-Fixed: 2532096, 2532101 Change-Id: Ic16001314522cc5b227fc3c33d899c719fbaeacd Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b9150e818dc5..fd6ead740ddd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -140,8 +140,9 @@ static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, if (!num_reg_dump_buf || !reg_dump_buf_desc) { CAM_DBG(CAM_ISP, - "Invalid args for reg dump req_id: [%llu] ctx idx: [%u] meta_type: [%u]", - ctx->applied_req_id, ctx->ctx_index, meta_type); + "Invalid args for reg dump req_id: [%llu] ctx idx: [%u] meta_type: [%u] num_reg_dump_buf: [%u] reg_dump_buf_desc: [%pK]", + ctx->applied_req_id, ctx->ctx_index, meta_type, + num_reg_dump_buf, reg_dump_buf_desc); return rc; } @@ -5582,9 +5583,9 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, if (((prepare->packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_INIT_DEV) { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV; - ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; - if ((ctx->num_reg_dump_buf) && (ctx->num_reg_dump_buf < + if ((prepare->num_reg_dump_buf) && (prepare->num_reg_dump_buf < CAM_REG_DUMP_MAX_BUF_ENTRIES)) { + ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; memcpy(ctx->reg_dump_buf_desc, prepare->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * From 83aa86fe7929883b4c45735d37dbbd3aef24971f Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Fri, 27 Sep 2019 12:02:41 +0530 Subject: [PATCH 109/790] msm: camera: csiphy: Sensor: Update cphy 3-phase registers for lito Update register settings for CPHY mode as per the latest HPG (revision H). CRs-Fixed: 2534885 Change-Id: I4caade811792467ef7f3eeba85c4a4f5b9050b11 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 83260c670448..c9cbe845cc1b 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -15,7 +15,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .csiphy_common_array_size = 5, .csiphy_reset_array_size = 4, .csiphy_2ph_config_array_size = 19, - .csiphy_3ph_config_array_size = 34, + .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -302,8 +302,7 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09AC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -338,8 +337,7 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -374,8 +372,7 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; From aa2e549641ae81405431c5243bfcee897bae9adf Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 16 Aug 2019 17:39:19 -0700 Subject: [PATCH 110/790] msm: camera: ife: Program RDI clients in line based mode Gralloc allocated buffers are aligned before calculating stride, which can lead to corruption in frame based mode. This change programs RDI clients in line based mode when the output format is PLAIN_16 to prevent this. RDI clients support only PLAIN128 packing format and this change also enforces that. CRs-Fixed: 2513939 Change-Id: Ic079e4cfd34cb4a9a0edc1152ff40565cdab2a81 Signed-off-by: Venkat Chinta --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 09407894b52a..cae125315895 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1127,11 +1127,8 @@ static int cam_vfe_bus_ver3_acquire_wm( CAM_DBG(CAM_ISP, "WM:%d width %d height %d", rsrc_data->index, rsrc_data->width, rsrc_data->height); - if (ver3_bus_priv->common_data.is_lite) - goto rdi_config; - - if (rsrc_data->index > 22) { -rdi_config: + if (ver3_bus_priv->common_data.is_lite || (rsrc_data->index > 22)) { + rsrc_data->pack_fmt = 0x0; /* WM 23-25 refers to RDI 0/ RDI 1/RDI 2 */ switch (rsrc_data->format) { case CAM_FORMAT_MIPI_RAW_6: @@ -1142,31 +1139,28 @@ rdi_config: case CAM_FORMAT_MIPI_RAW_16: case CAM_FORMAT_MIPI_RAW_20: case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PLAIN32_20: rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; rsrc_data->height = 0; rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; - rsrc_data->pack_fmt = 0x0; rsrc_data->en_cfg = (0x1 << 16) | 0x1; break; case CAM_FORMAT_PLAIN8: rsrc_data->en_cfg = 0x1; - rsrc_data->pack_fmt = 0x1; rsrc_data->stride = rsrc_data->width * 2; break; case CAM_FORMAT_PLAIN16_10: case CAM_FORMAT_PLAIN16_12: case CAM_FORMAT_PLAIN16_14: case CAM_FORMAT_PLAIN16_16: - case CAM_FORMAT_PLAIN32_20: - rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; - rsrc_data->height = 0; - rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; - rsrc_data->pack_fmt = 0x0; - rsrc_data->en_cfg = (0x1 << 16) | 0x1; + rsrc_data->width = + ALIGNUP(rsrc_data->width * 2, 16) / 16; + rsrc_data->en_cfg = 0x1; break; case CAM_FORMAT_PLAIN64: + rsrc_data->width = + ALIGNUP(rsrc_data->width * 8, 16) / 16; rsrc_data->en_cfg = 0x1; - rsrc_data->pack_fmt = 0xA; break; default: CAM_ERR(CAM_ISP, "Unsupported RDI format %d", @@ -1376,16 +1370,6 @@ static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) cam_io_w(rsrc_data->pack_fmt, common_data->mem_base + rsrc_data->hw_regs->packer_cfg); - /* Configure stride for RDIs on full IFE */ - if (!common_data->is_lite && rsrc_data->index > 22) - cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + - rsrc_data->hw_regs->image_cfg_2)); - - /* Configure stride for RDIs on IFE lite */ - if (common_data->is_lite) - cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + - rsrc_data->hw_regs->image_cfg_2)); - /* enable ubwc if needed*/ if (rsrc_data->en_ubwc) { val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg); @@ -3076,10 +3060,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, CAM_WARN(CAM_ISP, "Warning stride %u expected %u", io_cfg->planes[i].plane_stride, val); - if ((wm_data->stride != val || - !wm_data->init_cfg_done) && - (!bus_priv->common_data.is_lite && - wm_data->index < 23)) { + if (wm_data->stride != val || !wm_data->init_cfg_done) { CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_2, io_cfg->planes[i].plane_stride); From 8c91109b74c7c4dee048cc4b901a842b1a2a1f1d Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 11 Sep 2019 15:00:07 -0700 Subject: [PATCH 111/790] msm: camera: core: Change return type Return different error number when new requests and update packets are rejected due to bad request ID. This allows userspace to differentiate this specific reason for failure. CRs-Fixed: 2518451 Change-Id: I0400c6f2b2e0baf99bee4b4a3736bb1eab646627 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 2 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 2a3c6dbfcc61..088ba4d1b504 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2920,7 +2920,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( CAM_INFO(CAM_ISP, "request %lld has been flushed, reject packet", packet->header.request_id); - rc = -EINVAL; + rc = -EBADR; goto free_req; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 97e1dce27f8d..4ca666beab0e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3209,7 +3209,7 @@ int cam_req_mgr_schedule_request( CAM_INFO(CAM_CRM, "request %lld is flushed, last_flush_id to flush %d", sched_req->req_id, link->last_flush_id); - rc = -EINVAL; + rc = -EBADR; goto end; } From 5c2bb432418960c0e9d7ed0f597b0e30b348e850 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Mon, 30 Sep 2019 16:43:18 -0700 Subject: [PATCH 112/790] msm: camera: isp: Re-apply Bubble request In certain scenario Buf_done failures are observed for the request which is in bubble state. Since we never get bufdone we inadvertently are stuck in Bubble state. This change will wait for a period of two frames to receive bufdone and recover from bubble state. If any bufdone IRQ is never generated within this time period, we remove the request from active list and add it back to pending request list. CRs-Fixed: 2506159 Change-Id: Ibcce21a1a87d0a64e49c6454391ca139fc7d1fa7 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/cam_isp_context.c | 48 +++++++++++++++++++++++++++++++ drivers/cam_isp/cam_isp_context.h | 2 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 088ba4d1b504..3ffb623f0d6d 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -637,6 +637,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( ctx->ctx_id); } else { list_add(&req->list, &ctx->pending_req_list); + ctx_isp->bubble_frame_cnt = 0; CAM_DBG(CAM_REQ, "Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u", req->request_id, ctx_isp->active_req_cnt, @@ -788,6 +789,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( struct cam_req_mgr_trigger_notify notify; struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; uint64_t request_id = 0; /* @@ -797,6 +799,48 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( * In this case, we need to skip the current notification. This * helps the state machine to catch up the delay. */ + + if (atomic_read(&ctx_isp->process_bubble)) { + + if (list_empty(&ctx->active_req_list)) { + CAM_ERR(CAM_ISP, + "No available active req in bubble"); + atomic_set(&ctx_isp->process_bubble, 0); + rc = -EINVAL; + return rc; + } + + spin_lock_bh(&ctx->lock); + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + spin_unlock_bh(&ctx->lock); + + if (ctx_isp->bubble_frame_cnt >= 1 && + req_isp->bubble_detected) { + req_isp->num_acked = 0; + ctx_isp->bubble_frame_cnt = 0; + req_isp->bubble_detected = false; + spin_lock_bh(&ctx->lock); + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + spin_unlock_bh(&ctx->lock); + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->active_req_cnt--; + CAM_DBG(CAM_REQ, + "Move active req: %lld to pending list(cnt = %d) [bubble re-apply], ctx %u", + req->request_id, + ctx_isp->active_req_cnt, ctx->ctx_id); + } else if (req_isp->bubble_detected) { + ctx_isp->bubble_frame_cnt++; + CAM_DBG(CAM_ISP, + "Waiting on bufdone for bubble req: %lld, since frame_cnt = %lld", + req->request_id, ctx_isp->bubble_frame_cnt); + } else + CAM_DBG(CAM_ISP, "Delayed bufdone for req: %lld", + req->request_id); + } + 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) { @@ -2148,6 +2192,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( } end: + ctx_isp->bubble_frame_cnt = 0; atomic_set(&ctx_isp->process_bubble, 0); return rc; } @@ -3648,6 +3693,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; + ctx_isp->bubble_frame_cnt = 0; ctx_isp->substate_activated = ctx_isp->rdi_only_context ? CAM_ISP_CTX_ACTIVATED_APPLIED : (req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH : @@ -3791,6 +3837,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; + ctx_isp->bubble_frame_cnt = 0; atomic_set(&ctx_isp->process_bubble, 0); atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -4243,6 +4290,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->frame_id = 0; ctx->active_req_cnt = 0; ctx->reported_req_id = 0; + ctx->bubble_frame_cnt = 0; ctx->hw_ctx = NULL; ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; ctx->substate_machine = cam_isp_ctx_activated_state_machine; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 92db4433b429..1151ca78c052 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -156,6 +156,7 @@ struct cam_isp_context_state_monitor { * @substate_actiavted: Current substate for the activated state. * @process_bubble: Atomic variable to check if ctx is still * processing bubble. + * @bubble_frame_cnt: Count number of frames since the req is in bubble * @substate_machine: ISP substate machine for external interface * @substate_machine_irq: ISP substate machine for irq handling * @req_base: Common request object storage @@ -184,6 +185,7 @@ struct cam_isp_context { int64_t frame_id; uint32_t substate_activated; atomic_t process_bubble; + uint32_t bubble_frame_cnt; struct cam_ctx_ops *substate_machine; struct cam_isp_ctx_irq_ops *substate_machine_irq; From f3af79222b16f1c18ce319edab4b33cd0c9c34e8 Mon Sep 17 00:00:00 2001 From: Abhilash Kumar Date: Tue, 24 Sep 2019 12:12:14 +0530 Subject: [PATCH 113/790] msm: camera: icp: Dump IOCONFIG during io config failure This change dumps IOCONFIG command for IPE and BPS in case of io config failure. CRs-Fixed: 2430046 Change-Id: Iae730f46e4b3f2e327ac10587896a4e755f96a38 Signed-off-by: Suresh Vankadara Signed-off-by: Abhilash Kumar --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 91d87ecb3f6a..289a6d2662d8 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -57,6 +57,37 @@ 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_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data, + int32_t buf_handle) +{ + uintptr_t vaddr_ptr; + uint32_t *ptr; + size_t len; + int rc, i; + char buf[512]; + int used = 0; + + rc = cam_mem_get_cpu_buf(buf_handle, &vaddr_ptr, &len); + if (rc) { + CAM_ERR(CAM_ICP, "Unable to get io_cfg buf address for %d", + ctx_data->ctx_id); + return rc; + } + + len = len / sizeof(uint32_t); + ptr = (uint32_t *)vaddr_ptr; + for (i = 0; i < len; i++) { + used += snprintf(buf + used, + sizeof(buf) - used, "0X%08X-", ptr[i]); + if (!(i % 8)) { + CAM_INFO(CAM_ICP, "%s: %s", __func__, buf); + used = 0; + } + } + + return rc; +} + static const char *cam_icp_dev_type_to_name( uint32_t dev_type) { @@ -5142,6 +5173,8 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr); if (rc) { CAM_ERR(CAM_ICP, "IO Config command failed %d", rc); + cam_icp_dump_io_cfg(ctx_data, + icp_dev_acquire_info->io_config_cmd_handle); goto ioconfig_failed; } From 259e6f55d0fb0de8bf6d426d228ef48dd12b6ab6 Mon Sep 17 00:00:00 2001 From: Mangalaram ARCHANA Date: Thu, 3 Oct 2019 10:49:52 +0530 Subject: [PATCH 114/790] msm: camera: req_mgr: Increase device handles in hdl_tbl Increasing device handles to 128 in handle table. CRs-Fixed: 2532741 Change-Id: I58278026d08865cd7935bf4f0dd04f6a594c6dbc Signed-off-by: Mangalaram ARCHANA --- drivers/cam_req_mgr/cam_req_mgr_util.c | 14 +++++++------- drivers/cam_req_mgr/cam_req_mgr_util.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index ce83e64363f5..88b6bf079e9c 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -45,7 +45,7 @@ int cam_req_mgr_util_init(void) hdl_tbl = hdl_tbl_local; spin_unlock_bh(&hdl_tbl_lock); - bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long); + bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES_V2) * sizeof(long); hdl_tbl->bitmap = kzalloc(bitmap_size, GFP_KERNEL); if (!hdl_tbl->bitmap) { rc = -ENOMEM; @@ -92,7 +92,7 @@ int cam_req_mgr_util_free_hdls(void) return -EINVAL; } - for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) { + for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) { if (hdl_tbl->hdl[i].state == HDL_ACTIVE) { CAM_WARN(CAM_CRM, "Dev handle = %x session_handle = %x", hdl_tbl->hdl[i].hdl_value, @@ -101,7 +101,7 @@ int cam_req_mgr_util_free_hdls(void) clear_bit(i, hdl_tbl->bitmap); } } - bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES); + bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES_V2); spin_unlock_bh(&hdl_tbl_lock); return 0; @@ -113,7 +113,7 @@ static int32_t cam_get_free_handle_index(void) idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits); - if (idx >= CAM_REQ_MGR_MAX_HANDLES || idx < 0) + if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) return -ENOSR; set_bit(idx, hdl_tbl->bitmap); @@ -201,7 +201,7 @@ void *cam_get_device_priv(int32_t dev_hdl) } idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); - if (idx >= CAM_REQ_MGR_MAX_HANDLES) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx"); goto device_priv_fail; } @@ -245,7 +245,7 @@ void *cam_get_device_ops(int32_t dev_hdl) } idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); - if (idx >= CAM_REQ_MGR_MAX_HANDLES) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { CAM_ERR(CAM_CRM, "Invalid idx"); goto device_ops_fail; } @@ -288,7 +288,7 @@ static int cam_destroy_hdl(int32_t dev_hdl, int dev_hdl_type) } idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); - if (idx >= CAM_REQ_MGR_MAX_HANDLES) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { CAM_ERR(CAM_CRM, "Invalid idx %d", idx); goto destroy_hdl_fail; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index f22c6cbae8ef..c0e339eedd9b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_UTIL_API_H_ @@ -54,7 +54,7 @@ struct handle { * @bits: size of bit map in bits */ struct cam_req_mgr_util_hdl_tbl { - struct handle hdl[CAM_REQ_MGR_MAX_HANDLES]; + struct handle hdl[CAM_REQ_MGR_MAX_HANDLES_V2]; void *bitmap; size_t bits; }; From 1aadfe80e81403d76bba0eaed3437ff330584087 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Wed, 9 Oct 2019 17:21:41 -0700 Subject: [PATCH 115/790] msm: camera: isp: Remove redundant use of spin lock Interrupts in activated state machine are already protected with spin_lock for context. No need to reuse the spin_lock in interrupt handling routine. CRs-Fixed: 2538876 Change-Id: Id86e7dc3419861cb8bce143c56923126a3dc3d3e Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/cam_isp_context.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 3ffb623f0d6d..53521e79b388 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -810,21 +810,17 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( return rc; } - spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->active_req_list, struct cam_ctx_request, list); req_isp = (struct cam_isp_ctx_req *) req->req_priv; - spin_unlock_bh(&ctx->lock); if (ctx_isp->bubble_frame_cnt >= 1 && req_isp->bubble_detected) { req_isp->num_acked = 0; ctx_isp->bubble_frame_cnt = 0; req_isp->bubble_detected = false; - spin_lock_bh(&ctx->lock); list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); - spin_unlock_bh(&ctx->lock); atomic_set(&ctx_isp->process_bubble, 0); ctx_isp->active_req_cnt--; CAM_DBG(CAM_REQ, From af27416f683b8f0985c2a4fdf8ade46d43afa777 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 11 Sep 2019 10:43:51 -0700 Subject: [PATCH 116/790] msm: camera: isp: Correct acquire dump log Print the split id correctly as part of the acquire failure dump. CRs-Fixed: 2541667 Change-Id: Ie7156e35458027e24cea1993e487bfe38fcc2324 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index fd6ead740ddd..0b224ade013e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -778,7 +778,7 @@ static void cam_ife_hw_mgr_dump_acq_data( if (hw_res && hw_res->hw_intf) CAM_INFO(CAM_ISP, "IFE out split_id: %d res_id: 0x%x hw_idx: %u state: %s", - i, hw_res->res_id, + j, hw_res->res_id, hw_res->hw_intf->hw_idx, cam_ife_hw_mgr_get_res_state (hw_res->res_state)); From 3619ae634bffed9c1b8f812d8f66fea89e2e2b1a Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 10 Sep 2019 17:18:47 +0530 Subject: [PATCH 117/790] msm: camera: reqmgr: Logs v4l2 event queue failure Kernel uses v4l2 events to communicate with userspace. If userspace is not dequeuing events and kernel is pushing more events then v4l2_event_queue fails silently. This change uses v4l2 callbacks to log v4l2_event_queue failure. CRs-Fixed: 2541894 Change-Id: I98f8f609f615104ec6dde569bf1f39de1eb368fc Signed-off-by: Trishansh Bhardwaj --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 3 +- drivers/cam_req_mgr/cam_mem_mgr.c | 4 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 45 ++++++++++++++++++- drivers/cam_sync/cam_sync.c | 17 ++++++- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 289a6d2662d8..994310f84b10 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4437,7 +4437,8 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], mmu_hdl, &iova_addr, &src_buf_size); if (rc < 0) { - CAM_ERR(CAM_UTIL, "get src buf address fail"); + CAM_ERR(CAM_UTIL, + "get src buf address fail rc %d", rc); continue; } if (iova_addr >> 32) { diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index b7f77506d004..49b7e09b2228 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -188,10 +188,10 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle); if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) - return -EINVAL; + return -ENOENT; if (!tbl.bufq[idx].active) - return -EINVAL; + return -EAGAIN; mutex_lock(&tbl.bufq[idx].q_lock); if (buf_handle != tbl.bufq[idx].buf_handle) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index d567dec91519..f2452d9c340c 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -197,10 +197,53 @@ static struct v4l2_file_operations g_cam_fops = { #endif }; +static void cam_v4l2_event_queue_notify_error(const struct v4l2_event *old, + struct v4l2_event *new) +{ + struct cam_req_mgr_message *ev_header; + + ev_header = CAM_REQ_MGR_GET_PAYLOAD_PTR((*old), + struct cam_req_mgr_message); + switch (old->id) { + case V4L_EVENT_CAM_REQ_MGR_SOF: + CAM_ERR(CAM_CRM, "Failed to notify SOF event"); + CAM_ERR(CAM_CRM, "Sess %X FrameId %lld ReqId %lld link %X", + ev_header->session_hdl, + ev_header->u.frame_msg.frame_id, + ev_header->u.frame_msg.request_id, + ev_header->u.frame_msg.link_hdl); + break; + case V4L_EVENT_CAM_REQ_MGR_ERROR: + CAM_ERR(CAM_CRM, "Failed to notify ERROR"); + CAM_ERR(CAM_CRM, "Sess %X ReqId %d Link %X Type %d", + ev_header->u.err_msg.error_type, + ev_header->u.err_msg.request_id, + ev_header->u.err_msg.link_hdl, + ev_header->u.err_msg.error_type); + break; + case V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS: + CAM_ERR(CAM_CRM, "Failed to notify BOOT_TS event"); + CAM_ERR(CAM_CRM, "Sess %X FrameId %lld ReqId %lld link %X", + ev_header->session_hdl, + ev_header->u.frame_msg.frame_id, + ev_header->u.frame_msg.request_id, + ev_header->u.frame_msg.link_hdl); + break; + default: + CAM_ERR(CAM_CRM, "Failed to notify crm event id %d", + old->id); + } +} + +static struct v4l2_subscribed_event_ops g_cam_v4l2_ops = { + .merge = cam_v4l2_event_queue_notify_error, +}; + static int cam_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { - return v4l2_event_subscribe(fh, sub, CAM_REQ_MGR_EVENT_MAX, NULL); + return v4l2_event_subscribe(fh, sub, CAM_REQ_MGR_EVENT_MAX, + &g_cam_v4l2_ops); } static int cam_unsubscribe_event(struct v4l2_fh *fh, diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 10ed0cdecebf..45d2793fb671 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -847,10 +847,25 @@ static int cam_sync_close(struct file *filep) return rc; } +static void cam_sync_event_queue_notify_error(const struct v4l2_event *old, + struct v4l2_event *new) +{ + struct cam_sync_ev_header *ev_header; + + ev_header = CAM_SYNC_GET_HEADER_PTR((*old)); + CAM_ERR(CAM_CRM, "Failed to notify event id %d fence %d statue %d", + old->id, ev_header->sync_obj, ev_header->status); +} + +static struct v4l2_subscribed_event_ops cam_sync_v4l2_ops = { + .merge = cam_sync_event_queue_notify_error, +}; + int cam_sync_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { - return v4l2_event_subscribe(fh, sub, CAM_SYNC_MAX_V4L2_EVENTS, NULL); + return v4l2_event_subscribe(fh, sub, CAM_SYNC_MAX_V4L2_EVENTS, + &cam_sync_v4l2_ops); } int cam_sync_unsubscribe_event(struct v4l2_fh *fh, From f8c60957192f77d1ed331bc2a8ed9e06d09ba6b5 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 10 Oct 2019 17:36:37 -0700 Subject: [PATCH 118/790] msm: camera: isp: Add log in flush This change adds a log in flush to indicate stop/restart HW complete. CRs-Fixed: 2545140 Change-Id: I0068f239c5efeb536d60a9de27577d46bdc66edd Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 53521e79b388..d7e243678a12 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2163,6 +2163,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( CAM_ERR(CAM_ISP, "Failed to stop HW in Flush rc: %d", rc); + CAM_INFO(CAM_ISP, "Stop HW complete. Reset HW next."); CAM_DBG(CAM_ISP, "Flush wait and active lists"); spin_lock_bh(&ctx->lock); if (!list_empty(&ctx->wait_req_list)) @@ -3553,12 +3554,13 @@ static int __cam_isp_ctx_config_dev_in_flushed(struct cam_context *ctx, if (!ctx_isp->hw_acquired) { CAM_ERR(CAM_ISP, "HW is not acquired, reject packet"); - return -EINVAL; + rc = -EINVAL; + goto end; } rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd); if (rc) - return rc; + goto end; if (!ctx_isp->init_received) { CAM_WARN(CAM_ISP, @@ -3574,7 +3576,7 @@ static int __cam_isp_ctx_config_dev_in_flushed(struct cam_context *ctx, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "Failed to resume HW rc: %d", rc); - return rc; + goto end; } start_cmd.dev_handle = cmd->dev_handle; @@ -3583,6 +3585,9 @@ static int __cam_isp_ctx_config_dev_in_flushed(struct cam_context *ctx, if (rc) CAM_ERR(CAM_ISP, "Failed to re-start HW after flush rc: %d", rc); + else + CAM_INFO(CAM_ISP, + "Received init after flush. Re-start HW complete."); end: CAM_DBG(CAM_ISP, "next state %d sub_state:%d", ctx->state, From 49d6a1b3c60a3fd4537c945013a33ed9f3c8db23 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 10 Oct 2019 15:21:53 -0700 Subject: [PATCH 119/790] msm: camera: isp: Add tasklet index to logs This change adds tasklet index to logs which shares a one-one mapping with ife hardware manager context ID. CRs-Fixed: 2545140 Change-Id: I879662c9d90e98c604d20d975b4973369ac7a41e Signed-off-by: Venkat Chinta --- .../isp_hw_mgr/hw_utils/cam_tasklet_util.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c index 458894f96a1b..356c9a0a8919 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c @@ -88,14 +88,16 @@ int cam_tasklet_get_cmd( } if (!atomic_read(&tasklet->tasklet_active)) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet idx:%d is not active", + tasklet->index); rc = -EPIPE; return rc; } spin_lock_irqsave(&tasklet->tasklet_lock, flags); if (list_empty(&tasklet->free_cmd_list)) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "No more free tasklet cmd"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "No more free tasklet cmd idx:%d", + tasklet->index); rc = -ENODEV; goto spin_unlock; } else { @@ -158,7 +160,7 @@ static int cam_tasklet_dequeue_cmd( *tasklet_cmd = NULL; - CAM_DBG(CAM_ISP, "Dequeue before lock."); + CAM_DBG(CAM_ISP, "Dequeue before lock tasklet idx:%d", tasklet->index); spin_lock_irqsave(&tasklet->tasklet_lock, flags); if (list_empty(&tasklet->used_cmd_list)) { CAM_DBG(CAM_ISP, "End of list reached. Exit"); @@ -198,11 +200,12 @@ void cam_tasklet_enqueue_cmd( } if (!atomic_read(&tasklet->tasklet_active)) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active\n"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active idx:%d", + tasklet->index); return; } - CAM_DBG(CAM_ISP, "Enqueue tasklet cmd"); + CAM_DBG(CAM_ISP, "Enqueue tasklet cmd idx:%d", tasklet->index); tasklet_cmd->bottom_half_handler = bottom_half_handler; tasklet_cmd->payload = evt_payload_priv; tasklet_cmd->handler_priv = handler_priv; @@ -273,7 +276,7 @@ int cam_tasklet_start(void *tasklet_info) int i = 0; if (atomic_read(&tasklet->tasklet_active)) { - CAM_ERR(CAM_ISP, "Tasklet already active. idx = %d", + CAM_ERR(CAM_ISP, "Tasklet already active idx:%d", tasklet->index); return -EBUSY; } From 11e7f2175420b10fe7c5ce229f785104ed29c3dd Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 10 Oct 2019 13:42:10 -0700 Subject: [PATCH 120/790] msm: camera: isp: Set error type to fatal This change sets error type to fatal by default when hardware errors occur. CRs-Fixed: 2545140 Change-Id: Ic530fe460e67b6d5ec26a6d9d5735f4c8b34affc Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d7e243678a12..67e6c7d05160 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1405,7 +1405,7 @@ move_to_pending: end: do { if (list_empty(&ctx->pending_req_list)) { - error_request_id = ctx_isp->last_applied_req_id + 1; + error_request_id = ctx_isp->last_applied_req_id; req_isp = NULL; break; } @@ -1436,13 +1436,11 @@ end: notify.link_hdl = ctx->link_hdl; notify.dev_hdl = ctx->dev_hdl; notify.req_id = error_request_id; + notify.error = CRM_KMD_ERR_FATAL; - if (req_isp_to_report && req_isp_to_report->bubble_report) { + if (req_isp_to_report && req_isp_to_report->bubble_report) if (error_event_data->recovery_enabled) notify.error = CRM_KMD_ERR_BUBBLE; - } else { - notify.error = CRM_KMD_ERR_FATAL; - } CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld ctx %u, error %d", From 1dfd3efd17c1e8a4410e859baa615fbe51332425 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 7 Oct 2019 12:03:49 -0700 Subject: [PATCH 121/790] msm: camera: ife: Disable early eof strobe This change disables early eof strobe for version 480 hardware due to hardware limitation. CRs-Fixed: 2545140 Change-Id: I727ba5950911caac76cd2046e9e7c1e6d7ca6d96 Signed-off-by: Venkat Chinta --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 256fea2e5bbd..af9f67286d82 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1773,8 +1773,11 @@ static int cam_ife_csid_init_config_pxl_path( CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", csid_hw->hw_intf->hw_idx, val); - /* Enable generating early eof strobe based on crop config */ - if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF)) { + /* Enable generating early eof strobe based on crop config. + * Skip for version 480 HW due to HW limitation. + */ + if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF) && + (camera_hw_version != CAM_CPAS_TITAN_480_V100)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); val |= (1 << pxl_reg->early_eof_en_shift_val); From 388c4f7280bd4d09b6f7726427ca554dcdc3586f Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 10 Oct 2019 11:26:39 -0700 Subject: [PATCH 122/790] msm: camera: reqmgr: Reset the pd tables as part of flush As part of flush only the request slots were reset, we need to reset the slots in each of the pd tables. CRs-Fixed: 2545130 Change-Id: I34054dea2e5849739df9dd0a77d908a9af9fe3be Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_core.c | 54 +++++++++++++++++++++----- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 4ca666beab0e..be08f48a5f72 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -416,6 +416,50 @@ static void __cam_req_mgr_tbl_set_all_skip_cnt( } while (tbl != NULL); } +/** + * __cam_req_mgr_flush_req_slot() + * + * @brief : reset all the slots/pd tables when flush is + * invoked + * @link : link pointer + * + */ +static void __cam_req_mgr_flush_req_slot( + struct cam_req_mgr_core_link *link) +{ + int idx = 0; + struct cam_req_mgr_slot *slot; + struct cam_req_mgr_req_tbl *tbl; + struct cam_req_mgr_req_queue *in_q = link->req.in_q; + + for (idx = 0; idx < in_q->num_slots; idx++) { + slot = &in_q->slot[idx]; + tbl = link->req.l_tbl; + CAM_DBG(CAM_CRM, + "RESET idx: %d req_id: %lld slot->status: %d", + idx, slot->req_id, slot->status); + + /* Reset input queue slot */ + slot->req_id = -1; + slot->skip_idx = 1; + slot->recover = 0; + slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + slot->status = CRM_SLOT_STATUS_NO_REQ; + + /* Reset all pd table slot */ + while (tbl != NULL) { + CAM_DBG(CAM_CRM, "pd: %d: idx %d state %d", + tbl->pd, idx, tbl->slot[idx].state); + tbl->slot[idx].req_ready_map = 0; + tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; + tbl = tbl->next; + } + } + + in_q->wr_idx = 0; + in_q->rd_idx = 0; +} + /** * __cam_req_mgr_reset_req_slot() * @@ -1966,15 +2010,7 @@ int cam_req_mgr_process_flush_req(void *priv, void *data) 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; - slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - slot->skip_idx = 1; - slot->status = CRM_SLOT_STATUS_NO_REQ; - } - in_q->wr_idx = 0; - in_q->rd_idx = 0; + __cam_req_mgr_flush_req_slot(link); } else if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { idx = __cam_req_mgr_find_slot_for_req(in_q, flush_info->req_id); From 422de0bbf49c799fc85bb1744b30897708309c74 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 10 Oct 2019 11:31:03 -0700 Subject: [PATCH 123/790] msm: camera: ife: Deinit input mux resources We must deinit IFE input mux resources before the check for open count. Without this change the last bus resource is the last to enter this function when open count reaches zero. So input mux resources are never deinitialized. CRs-Fixed: 2545140 Change-Id: I355afce7d631cdb00e3f6da0ba0be40c2e2b63a2 Signed-off-by: Venkat Chinta --- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 0244e41d5a03..11d6a602117c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -251,6 +251,13 @@ int cam_vfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) return -EINVAL; } + isp_res = (struct cam_isp_resource_node *)deinit_hw_args; + if (isp_res && isp_res->deinit) { + rc = isp_res->deinit(isp_res, NULL, 0); + if (rc) + CAM_ERR(CAM_ISP, "deinit failed"); + } + mutex_lock(&vfe_hw->hw_mutex); if (!vfe_hw->open_count) { mutex_unlock(&vfe_hw->hw_mutex); @@ -281,13 +288,6 @@ int cam_vfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) 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); - if (rc) - CAM_ERR(CAM_ISP, "deinit failed"); - } - rc = cam_vfe_reset(hw_priv, &reset_core_args, sizeof(uint32_t)); /* Turn OFF Regulators, Clocks and other SOC resources */ From 064d662a3cc352f7dfcf881d7b2ca276765d15a0 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 3 Oct 2019 12:19:02 -0700 Subject: [PATCH 124/790] msm: camera: isp: Update last applied request ID This change updates last applied request ID when init packets are applied and when stop ioctls are invoked. CRs-Fixed: 2539888 Change-Id: I113b7897740d6577a4757ce41f9fcb1fff8c56e9 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 67e6c7d05160..5698e73bbd32 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3683,6 +3683,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; + ctx_isp->last_applied_req_id = req->request_id; + if (ctx->state == CAM_CTX_FLUSHED) start_isp.start_only = true; else @@ -3837,6 +3839,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->bubble_frame_cnt = 0; + ctx_isp->last_applied_req_id = 0; atomic_set(&ctx_isp->process_bubble, 0); atomic64_set(&ctx_isp->state_monitor_head, -1); From a62a43252281382396ee1fbdd908bf4f8f32fc5b Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 15 Oct 2019 12:31:49 +0530 Subject: [PATCH 125/790] msm: camera: cpas: Fix TCSR register programming Program TCSR_CAMERA_HF_SF_ARES_GLITCH_MASK to ignore erroneous signals. CRs-Fixed: 2545751 Change-Id: Ie638136d364372b7a8309af1d9656a8c8b7772fc Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cpas/cam_cpas_hw.c | 2 +- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 11 +++++++++++ drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 4 +++- drivers/cam_cpas/cpas_top/cpastop_v175_130.h | 11 +++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 7ee738da4748..78e12fcd1090 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -44,7 +44,7 @@ int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, value = reg_info->value; } - CAM_DBG(CAM_CPAS, "Base[%d] Offset[0x%8x] Value[0x%8x]", + CAM_DBG(CAM_CPAS, "Base[%d] Offset[0x%08x] Value[0x%08x]", reg_base, reg_info->offset, value); cam_io_w_mb(value, soc_info->reg_map[reg_base_index].mem_base + diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 18151d1069a3..0543397a8482 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -7,6 +7,8 @@ #include #include +#include + #include "cam_cpas_hw_intf.h" #include "cam_cpas_hw.h" #include "cam_cpastop_hw.h" @@ -513,6 +515,10 @@ done: static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) { int i; + struct cam_cpas_hw_errata_wa_list *errata_wa_list = + camnoc_info->errata_wa_list; + struct cam_cpas_hw_errata_wa *errata_wa = + &errata_wa_list->tcsr_camera_hf_sf_ares_glitch; cam_cpastop_reset_irq(cpas_hw); for (i = 0; i < camnoc_info->specific_size; i++) { @@ -534,6 +540,11 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) } } + if (errata_wa->enable) { + scm_io_write(errata_wa->data.reg_info.offset, + errata_wa->data.reg_info.value); + } + return 0; } diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index bdcf00da90b7..a4d44a3feff6 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -208,10 +208,12 @@ struct cam_cpas_hw_errata_wa { * * @camnoc_flush_slave_pending_trans: Errata workaround info for flushing * camnoc slave pending transactions before turning off CPAS_TOP gdsc - * + * @tcsr_camera_hf_sf_ares_glitch: Errata workaround info from ignoring + * erroneous signals at camera start */ struct cam_cpas_hw_errata_wa_list { struct cam_cpas_hw_errata_wa camnoc_flush_slave_pending_trans; + struct cam_cpas_hw_errata_wa tcsr_camera_hf_sf_ares_glitch; }; /** diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h index 2d3d96ea819a..769e77fc3d6b 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h @@ -747,6 +747,17 @@ static struct cam_cpas_hw_errata_wa_list cam175_cpas130_errata_wa_list = { .value = 0, /* expected to be 0 */ }, }, + /* TZ owned register */ + .tcsr_camera_hf_sf_ares_glitch = { + .enable = true, + .data.reg_info = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + /* TCSR_CAMERA_HF_SF_ARES_GLITCH_MASK */ + .offset = 0x01FCA08C, + .value = 0x4, /* set bit[2] to 1 */ + }, + }, }; static struct cam_camnoc_info cam175_cpas130_camnoc_info = { From 3205f18e3c50d38075780e5878599b4b102eea84 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Mon, 14 Oct 2019 00:05:31 +0530 Subject: [PATCH 126/790] msm: camera: csiphy: Enable multi-datarate support for csiphy v1.2 Enable support for multiple data rates (2.5/3.5/4.5 Gsps) for csiphy v1.2 driver. CRs-Fixed: 2542855 Change-Id: Idbe299aca210e30d732304e77e2a8191c8809f09 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/cam_csiphy_soc.c | 5 +++-- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 18 ++++-------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index a6aba5940181..c5a8033aaffb 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -269,7 +269,7 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->hw_version = CSIPHY_VERSION_V12; csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = - &data_rate_delta_table; + &data_rate_delta_table_1_2; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v1.2.1")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_1_reg; @@ -308,7 +308,8 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->is_divisor_32_comp = false; csiphy_dev->hw_version = CSIPHY_VERSION_V12; csiphy_dev->clk_lane = 0; - csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index c9cbe845cc1b..cc6c1adb366c 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -376,17 +376,14 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { }, }; -struct data_rate_settings_t data_rate_delta_table = { +struct data_rate_settings_t data_rate_delta_table_1_2 = { .num_data_rate_settings = 3, .data_rate_settings = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 9, + .data_rate_reg_array_size = 6, .csiphy_data_rate_regs = { - {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -398,11 +395,8 @@ struct data_rate_settings_t data_rate_delta_table = { { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 18, + .data_rate_reg_array_size = 15, .csiphy_data_rate_regs = { - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -418,17 +412,13 @@ struct data_rate_settings_t data_rate_delta_table = { {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 18, + .data_rate_reg_array_size = 15, .csiphy_data_rate_regs = { - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, From 037967bc88dd727228eab18d1001b2d641102236 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Tue, 1 Oct 2019 12:31:36 -0700 Subject: [PATCH 127/790] msm: camera: ife: Dump ife camnoc debug registers ife camnoc debug registers need to dumped only when bus overflow status is set. CRs-Fixed: 2538876 Change-Id: I6f886f6e084380de62c0b4acaa48fa02fce01136 Signed-off-by: Vishalsingh Hajeri --- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 124 +++++++++--------- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 112 ++++++++-------- 2 files changed, 117 insertions(+), 119 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index 495e4afbd50a..bfb17d2145f8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -762,72 +762,57 @@ static int cam_vfe_camif_lite_process_cmd( return rc; } -static void cam_vfe_camif_lite_overflow_debug_info(uint32_t *status, +static void cam_vfe_camif_lite_overflow_debug_info( struct cam_vfe_mux_camif_lite_data *camif_lite_priv) { - uint32_t bus_overflow_status = 0; struct cam_vfe_soc_private *soc_private = NULL; uint32_t val0, val1, val2, val3; - bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; soc_private = camif_lite_priv->soc_info->soc_private; - if (bus_overflow_status) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - CAM_INFO(CAM_ISP, - "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", - val0, val1, val2); + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_0); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_1); + val2 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_2); + val3 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_3); + CAM_INFO(CAM_ISP, + "status_0: 0x%X status_1: 0x%X status_2: 0x%X status_3: 0x%X", + val0, val1, val2, val3); - } else { - val0 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_0); - val1 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_1); - val2 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_2); - val3 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_3); - CAM_INFO(CAM_ISP, - "status_0: 0x%X status_1: 0x%X status_2: 0x%X status_3: 0x%X", - val0, val1, val2, val3); + if (soc_private->is_ife_lite) + return; - if (soc_private->is_ife_lite) - return; - - val0 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_4); - val1 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_5); - val2 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_6); - val3 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_7); - CAM_INFO(CAM_ISP, - "status_4: 0x%X status_5: 0x%X status_6: 0x%X status_7: 0x%X", - val0, val1, val2, val3); - val0 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_8); - val1 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_9); - val2 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_10); - val3 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_11); - CAM_INFO(CAM_ISP, - "status_8: 0x%X status_9: 0x%X status_10: 0x%X status_11: 0x%X", - val0, val1, val2, val3); - val0 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_12); - val1 = cam_io_r(camif_lite_priv->mem_base + - camif_lite_priv->common_reg->top_debug_13); - CAM_INFO(CAM_ISP, "status_12: 0x%X status_13: 0x%X", - val0, val1); - } + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_4); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_5); + val2 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_6); + val3 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_7); + CAM_INFO(CAM_ISP, + "status_4: 0x%X status_5: 0x%X status_6: 0x%X status_7: 0x%X", + val0, val1, val2, val3); + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_8); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_9); + val2 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_10); + val3 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_11); + CAM_INFO(CAM_ISP, + "status_8: 0x%X status_9: 0x%X status_10: 0x%X status_11: 0x%X", + val0, val1, val2, val3); + val0 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_12); + val1 = cam_io_r(camif_lite_priv->mem_base + + camif_lite_priv->common_reg->top_debug_13); + CAM_INFO(CAM_ISP, "status_12: 0x%X status_13: 0x%X", + val0, val1); } static void cam_vfe_camif_lite_print_status(uint32_t *status, @@ -836,6 +821,7 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, uint32_t violation_mask = 0x3F00, violation_status = 0; uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private = NULL; + uint32_t val0, val1, val2; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -893,13 +879,21 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, if (bus_overflow_status & 0x02000000) CAM_INFO(CAM_ISP, "RDI2 BUS OVERFLOW"); - return; + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + CAM_INFO(CAM_ISP, + "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", + val0, val1, val2); } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "PDLIB / LCR Module hang"); /* print debug registers */ - cam_vfe_camif_lite_overflow_debug_info(status, camif_lite_priv); + cam_vfe_camif_lite_overflow_debug_info(camif_lite_priv); return; } @@ -979,12 +973,22 @@ ife_lite: if (bus_overflow_status & 0x08) CAM_INFO(CAM_ISP, "RDI3 BUS OVERFLOW"); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + CAM_INFO(CAM_ISP, + "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", + val0, val1, val2); } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "RDI hang"); /* print debug registers */ - cam_vfe_camif_lite_overflow_debug_info(status, camif_lite_priv); + cam_vfe_camif_lite_overflow_debug_info(camif_lite_priv); return; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index c390b6f542d4..8e5a30588c52 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -776,71 +776,53 @@ static int cam_vfe_camif_ver3_process_cmd( } -static void cam_vfe_camif_ver3_overflow_debug_info(uint32_t *status, +static void cam_vfe_camif_ver3_overflow_debug_info( struct cam_vfe_mux_camif_ver3_data *camif_priv) { - struct cam_vfe_soc_private *soc_private; - uint32_t bus_overflow_status; uint32_t val0, val1, val2, val3; - bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; - soc_private = camif_priv->soc_info->soc_private; + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_0); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_1); + val2 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_2); + val3 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_3); + CAM_INFO(CAM_ISP, + "status_0: 0x%X status_1: 0x%X status_2: 0x%X status_3: 0x%X", + val0, val1, val2, val3); - if (bus_overflow_status) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - CAM_INFO(CAM_ISP, - "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", - val0, val1, val2); - } else { - val0 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_0); - val1 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_1); - val2 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_2); - val3 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_3); - CAM_INFO(CAM_ISP, - "status_0: 0x%X status_1: 0x%X status_2: 0x%X status_3: 0x%X", - val0, val1, val2, val3); + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_4); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_5); + val2 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_6); + val3 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_7); + CAM_INFO(CAM_ISP, + "status_4: 0x%X status_5: 0x%X status_6: 0x%X status_7: 0x%X", + val0, val1, val2, val3); - val0 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_4); - val1 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_5); - val2 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_6); - val3 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_7); - CAM_INFO(CAM_ISP, - "status_4: 0x%X status_5: 0x%X status_6: 0x%X status_7: 0x%X", - val0, val1, val2, val3); - - val0 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_8); - val1 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_9); - val2 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_10); - val3 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_11); - CAM_INFO(CAM_ISP, - "status_8: 0x%X status_9: 0x%X status_10: 0x%X status_11: 0x%X", - val0, val1, val2, val3); - - val0 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_12); - val1 = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->top_debug_13); - CAM_INFO(CAM_ISP, "status_12: 0x%X status_13: 0x%X", - val0, val1); - } + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_8); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_9); + val2 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_10); + val3 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_11); + CAM_INFO(CAM_ISP, + "status_8: 0x%X status_9: 0x%X status_10: 0x%X status_11: 0x%X", + val0, val1, val2, val3); + val0 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_12); + val1 = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->top_debug_13); + CAM_INFO(CAM_ISP, "status_12: 0x%X status_13: 0x%X", + val0, val1); } static void cam_vfe_camif_ver3_print_status(uint32_t *status, @@ -848,6 +830,8 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, { uint32_t violation_mask = 0x3F, module_id = 0; uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; + struct cam_vfe_soc_private *soc_private; + uint32_t val0, val1, val2; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -933,13 +917,23 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, if (bus_overflow_status & 0x0200000) CAM_INFO(CAM_ISP, "PDAF BUS OVERFLOW"); + soc_private = camif_priv->soc_info->soc_private; + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + CAM_INFO(CAM_ISP, + "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", + val0, val1, val2); return; } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "PIXEL PIPE Module hang"); /* print debug registers */ - cam_vfe_camif_ver3_overflow_debug_info(status, camif_priv); + cam_vfe_camif_ver3_overflow_debug_info(camif_priv); return; } From 35bead08c397908b6344787382a150c484d1a42c Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 24 Sep 2019 13:01:20 +0530 Subject: [PATCH 128/790] msm: camera: common: Fix compilation issues for 32-bit arch Fix improper use of divide and modulo operator on 64 bit numbers. Fix variable type to work with both 32/64 bit arch. CRs-Fixed: 2543730 Change-Id: Ifa52d46dece3434d41308d284982a0cd8e17cd1b Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm_hw_core.c | 2 +- drivers/cam_cpas/cam_cpas_hw.c | 12 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 107 ++++++++++-------- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 4 +- drivers/cam_isp/cam_isp_context.c | 14 ++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 9 +- .../hw_utils/cam_isp_packet_parser.c | 4 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 +- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 2 +- drivers/cam_lrme/cam_lrme_context.h | 2 +- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 2 +- drivers/cam_req_mgr/cam_mem_mgr.c | 2 +- drivers/cam_req_mgr/cam_mem_mgr_api.h | 2 +- .../cam_csiphy/cam_csiphy_core.c | 15 ++- drivers/cam_smmu/cam_smmu_api.c | 2 +- 15 files changed, 105 insertions(+), 76 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 7d0515b747a4..f54f9d61b55f 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -413,7 +413,7 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, } for (i = 0; i < req->data->cmd_arrary_count ; i++) { - uint64_t hw_vaddr_ptr = 0; + dma_addr_t hw_vaddr_ptr = 0; size_t len = 0; if ((!cdm_cmd->cmd[i].len) && diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 78e12fcd1090..ae0368acdb05 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -424,7 +424,7 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( if (soc_private->control_camnoc_axi_clk) { struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; - uint64_t required_camnoc_bw = 0; + uint64_t required_camnoc_bw = 0, intermediate_result = 0; int32_t clk_rate = 0; for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) { @@ -440,15 +440,19 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( } } - required_camnoc_bw += (required_camnoc_bw * - soc_private->camnoc_axi_clk_bw_margin) / 100; + intermediate_result = required_camnoc_bw * + soc_private->camnoc_axi_clk_bw_margin; + do_div(intermediate_result, 100); + required_camnoc_bw += intermediate_result; if ((required_camnoc_bw > 0) && (required_camnoc_bw < soc_private->camnoc_axi_min_ib_bw)) required_camnoc_bw = soc_private->camnoc_axi_min_ib_bw; - clk_rate = required_camnoc_bw / soc_private->camnoc_bus_width; + intermediate_result = required_camnoc_bw; + do_div(intermediate_result, soc_private->camnoc_bus_width); + clk_rate = intermediate_result; CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %d", required_camnoc_bw, clk_rate); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 994310f84b10..786fd0e98f32 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -422,6 +422,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) (struct cam_icp_hw_ctx_data *)task_data->data; struct cam_icp_hw_mgr *hw_mgr = &icp_hw_mgr; uint32_t id; + uint64_t temp; struct cam_hw_intf *ipe0_dev_intf = NULL; struct cam_hw_intf *ipe1_dev_intf = NULL; struct cam_hw_intf *bps_dev_intf = NULL; @@ -521,16 +522,17 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) ctx_data->clk_info.base_clk = 0; clk_update.axi_vote.num_paths = 1; - clk_update.axi_vote.axi_path[0].camnoc_bw = - clk_info->uncompressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].mnoc_ab_bw = - clk_info->compressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].mnoc_ib_bw = - clk_info->compressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].ddr_ab_bw = - clk_info->compressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].ddr_ib_bw = - clk_info->compressed_bw / device_share_ratio; + + temp = clk_info->uncompressed_bw; + do_div(temp, device_share_ratio); + clk_update.axi_vote.axi_path[0].camnoc_bw = temp; + + temp = clk_info->compressed_bw; + do_div(temp, device_share_ratio); + clk_update.axi_vote.axi_path[0].mnoc_ab_bw = temp; + clk_update.axi_vote.axi_path[0].mnoc_ib_bw = temp; + clk_update.axi_vote.axi_path[0].ddr_ab_bw = temp; + clk_update.axi_vote.axi_path[0].ddr_ib_bw = temp; } else { int path_index; @@ -594,16 +596,21 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) if (device_share_ratio > 1) { for (i = 0; i < clk_update.axi_vote.num_paths; i++) { - clk_update.axi_vote.axi_path[i].camnoc_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].mnoc_ab_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].mnoc_ib_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].ddr_ab_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].ddr_ib_bw /= - device_share_ratio; + do_div( + clk_update.axi_vote.axi_path[i].camnoc_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].mnoc_ab_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].mnoc_ib_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].ddr_ab_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].ddr_ib_bw, + device_share_ratio); } } } @@ -780,7 +787,8 @@ static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles, uint64_t base_clk; uint64_t mul = 1000000000; - base_clk = (frame_cycles * mul) / budget; + base_clk = frame_cycles * mul; + do_div(base_clk, budget); CAM_DBG(CAM_ICP, "budget = %lld fc = %d ib = %lld base_clk = %lld", budget, frame_cycles, @@ -1408,6 +1416,7 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, struct cam_icp_hw_ctx_data *ctx_data) { uint32_t id; + uint64_t temp; int i = 0; struct cam_hw_intf *ipe0_dev_intf = NULL; struct cam_hw_intf *ipe1_dev_intf = NULL; @@ -1463,16 +1472,17 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, clk_update.axi_vote.axi_path[0].transac_type = CAM_IPE_DEFAULT_AXI_TRANSAC; } - clk_update.axi_vote.axi_path[0].camnoc_bw = - clk_info->uncompressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].mnoc_ab_bw = - clk_info->compressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].mnoc_ib_bw = - clk_info->compressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].ddr_ab_bw = - clk_info->compressed_bw / device_share_ratio; - clk_update.axi_vote.axi_path[0].ddr_ib_bw = - clk_info->compressed_bw / device_share_ratio; + + temp = clk_info->uncompressed_bw; + do_div(temp, device_share_ratio); + clk_update.axi_vote.axi_path[0].camnoc_bw = temp; + + temp = clk_info->compressed_bw; + do_div(temp, device_share_ratio); + clk_update.axi_vote.axi_path[0].mnoc_ab_bw = temp; + clk_update.axi_vote.axi_path[0].mnoc_ib_bw = temp; + clk_update.axi_vote.axi_path[0].ddr_ab_bw = temp; + clk_update.axi_vote.axi_path[0].ddr_ib_bw = temp; } else { clk_update.axi_vote.num_paths = clk_info->num_paths; memcpy(&clk_update.axi_vote.axi_path[0], @@ -1482,16 +1492,21 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, if (device_share_ratio > 1) { for (i = 0; i < clk_update.axi_vote.num_paths; i++) { - clk_update.axi_vote.axi_path[i].camnoc_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].mnoc_ab_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].mnoc_ib_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].ddr_ab_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].ddr_ib_bw /= - device_share_ratio; + do_div( + clk_update.axi_vote.axi_path[i].camnoc_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].mnoc_ab_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].mnoc_ib_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].ddr_ab_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].ddr_ib_bw, + device_share_ratio); } } } @@ -3877,7 +3892,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, int rc = 0; int i; int num_cmd_buf = 0; - uint64_t addr; + dma_addr_t addr; size_t len; struct cam_cmd_buf_desc *cmd_desc = NULL; uintptr_t cpu_addr = 0; @@ -4020,7 +4035,7 @@ static int cam_icp_process_stream_settings( { int rc = 0, i = 0; size_t packet_size, map_cmd_size, len; - uint64_t iova; + dma_addr_t iova; unsigned long rem_jiffies; int timeout = 5000; struct hfi_cmd_ipe_bps_map *map_cmd; @@ -4298,7 +4313,7 @@ static int cam_icp_process_generic_cmd_buffer( struct cam_packet *packet, struct cam_icp_hw_ctx_data *ctx_data, int32_t index, - uint64_t *io_buf_addr) + dma_addr_t *io_buf_addr) { int i, rc = 0; struct cam_cmd_buf_desc *cmd_desc = NULL; @@ -4394,7 +4409,7 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, bool *mem_found) { - uint64_t iova_addr; + dma_addr_t iova_addr; size_t src_buf_size; int i; int j; @@ -5056,7 +5071,7 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { int rc = 0, bitmap_size = 0; uint32_t ctx_id = 0, dev_type; - uint64_t io_buf_addr; + dma_addr_t io_buf_addr; size_t io_buf_size; struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_icp_hw_ctx_data *ctx_data = NULL; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index fb7fff082114..b26bfc0dff65 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -135,7 +135,7 @@ struct clk_work_data { */ struct icp_frame_info { uint64_t request_id; - uint64_t io_config; + dma_addr_t io_config; struct hfi_cmd_ipebps_async hfi_cfg_io_cmd; }; @@ -262,7 +262,7 @@ struct cam_icp_hw_ctx_data { struct icp_cmd_generic_blob { struct cam_icp_hw_ctx_data *ctx; uint32_t frame_info_idx; - uint64_t *io_buf_addr; + dma_addr_t *io_buf_addr; }; /** diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5698e73bbd32..17411f6dc762 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -24,9 +24,9 @@ static const char isp_dev_name[] = "cam-isp"; static struct cam_isp_ctx_debug isp_ctx_debug; -#define INC_STATE_MONITOR_HEAD(head) \ - (atomic64_add_return(1, head) % \ - CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) +#define INC_STATE_MONITOR_HEAD(head, ret) \ + div_u64_rem(atomic64_add_return(1, head),\ + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, (ret)) static int cam_isp_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info); @@ -39,7 +39,9 @@ static void __cam_isp_ctx_update_state_monitor_array( enum cam_isp_state_change_trigger trigger_type, uint64_t req_id) { - int iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head); + int iterator; + + INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head, &iterator); ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state = ctx_isp->substate_activated; @@ -117,8 +119,8 @@ static void __cam_isp_ctx_dump_state_monitor_array( oldest_entry = 0; } else { num_entries = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; - oldest_entry = (state_head + 1) % - CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; + div_u64_rem(state_head + 1, + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, &oldest_entry); } CAM_ERR(CAM_ISP, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 0b224ade013e..3c82c6b2f8e5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -689,16 +689,19 @@ static void cam_ife_hw_mgr_dump_acq_data( struct cam_ife_hw_mgr_res *hw_mgr_res_temp = NULL; struct cam_isp_resource_node *hw_res = NULL; struct timespec64 *ts = NULL; - uint64_t ms, tmp; + uint64_t ms, tmp, hrs, min, sec; int i = 0, j = 0; ts = &hwr_mgr_ctx->ts; tmp = ts->tv_sec; ms = (ts->tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); CAM_INFO(CAM_ISP, "**** %llu:%llu:%llu.%llu ctx_idx: %u rdi_only: %s is_dual: %s acquired ****", - (tmp / 3600) % 24, (tmp / 60) % 60, tmp % 60, ms, + hrs, min, sec, ms, hwr_mgr_ctx->ctx_index, (hwr_mgr_ctx->is_rdi_only_context ? "true" : "false"), (hwr_mgr_ctx->is_dual ? "true" : "false")); @@ -5688,7 +5691,7 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, bool *mem_found) { - uint64_t iova_addr; + dma_addr_t iova_addr; size_t src_buf_size; int i; int j; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 9c95b587df26..86a14229915f 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -465,8 +465,8 @@ int cam_isp_add_io_buffers( uint32_t size_isp_out, bool fill_fence) { - int rc = 0; - uint64_t io_addr[CAM_PACKET_MAX_PLANES]; + int rc = 0; + dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; struct cam_buf_io_cfg *io_cfg; struct cam_isp_resource_node *res; struct cam_ife_hw_mgr_res *hw_mgr_res; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 741b41d4cccf..7ac79feb2a9f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -201,7 +201,7 @@ struct cam_isp_hw_cmd_buf_update { * */ struct cam_isp_hw_get_wm_update { - uint64_t *image_buf; + dma_addr_t *image_buf; uint32_t num_buf; struct cam_buf_io_cfg *io_cfg; }; diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index c9ec8d1b39f1..9f331d46221c 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -611,7 +611,7 @@ static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, bool *mem_found) { - uint64_t iova_addr; + dma_addr_t iova_addr; size_t src_buf_size; int i; int j; diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h index 8dfdc36501a9..9fb88ed85f1b 100644 --- a/drivers/cam_lrme/cam_lrme_context.h +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -11,7 +11,7 @@ #include "cam_hw_mgr_intf.h" #include "cam_req_mgr_interface.h" -#define CAM_LRME_CTX_INDEX_SHIFT 32 +#define CAM_LRME_CTX_INDEX_SHIFT 16 /** * struct cam_lrme_context diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 90b3f3fa442a..40700bbce9e0 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -144,7 +144,7 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl, int rc = -EINVAL; uint32_t num_in_buf, num_out_buf, i, j, plane; struct cam_buf_io_cfg *io_cfg; - uint64_t io_addr[CAM_PACKET_MAX_PLANES]; + dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; size_t size; num_in_buf = 0; diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 49b7e09b2228..a0b1e66f8e0c 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -175,7 +175,7 @@ static void cam_mem_put_slot(int32_t idx) } int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, - uint64_t *iova_ptr, size_t *len_ptr) + dma_addr_t *iova_ptr, size_t *len_ptr) { int rc = 0, idx; diff --git a/drivers/cam_req_mgr/cam_mem_mgr_api.h b/drivers/cam_req_mgr/cam_mem_mgr_api.h index 0bbf094ee1e8..e216a46a3a6f 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr_api.h +++ b/drivers/cam_req_mgr/cam_mem_mgr_api.h @@ -75,7 +75,7 @@ int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp); * @return Status of operation. Negative in case of error. Zero otherwise. */ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, - uint64_t *iova_ptr, size_t *len_ptr); + dma_addr_t *iova_ptr, size_t *len_ptr); /** * @brief: This indicates begin of CPU access. diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 6755eb2954ca..9d5976d86f26 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -375,6 +375,7 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) uint16_t lane_mask = 0, i = 0, cfg_size = 0, temp = 0; uint8_t lane_cnt, lane_pos = 0; uint16_t settle_cnt = 0; + uint64_t intermediate_var; void __iomem *csiphybase; struct csiphy_reg_t *csiphy_common_reg = NULL; struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE]; @@ -484,12 +485,16 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) continue; } - settle_cnt = (csiphy_dev->csiphy_info.settle_time / 200000000); + intermediate_var = csiphy_dev->csiphy_info.settle_time; + do_div(intermediate_var, 200000000); + settle_cnt = intermediate_var; if (csiphy_dev->csiphy_info.combo_mode == 1 && - (lane_pos >= 3)) - settle_cnt = - (csiphy_dev->csiphy_info.settle_time_combo_sensor / - 200000000); + (lane_pos >= 3)) { + intermediate_var = + csiphy_dev->csiphy_info.settle_time_combo_sensor; + do_div(intermediate_var, 200000000); + settle_cnt = intermediate_var; + } for (i = 0; i < cfg_size; i++) { switch (reg_array[lane_pos][i].csiphy_param_type) { case CSIPHY_LANE_ENABLE: diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 55962a8f3e7a..784ea62e0925 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3546,7 +3546,7 @@ static int cam_populate_smmu_context_banks(struct device *dev, } dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); - dma_set_seg_boundary(dev, DMA_BIT_MASK(64)); + dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64)); end: /* increment count to next bank */ From 898869cd11640dab946477452be8470b3fda9cdb Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 16 Oct 2019 13:41:25 -0700 Subject: [PATCH 129/790] msm: camera: ife: Remove line start addition This change removes line start addition to epoch line config. After CSID crop is applied, the first line that CAMIF receives is already at the required line and therefore number of lines for epoch should just be half of the frame width. CRs-Fixed: 2546941 Change-Id: Ib12b1fc96cedf140672af03862aaf4be65ab38d8 Signed-off-by: Venkat Chinta --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 8e5a30588c52..12cdcb19f2c0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -425,9 +425,8 @@ static int cam_vfe_camif_ver3_resource_start( /* epoch config */ switch (soc_private->cpas_version) { case CAM_CPAS_TITAN_480_V100: - epoch0_line_cfg = ((rsrc_data->last_line - - rsrc_data->first_line) / 4) + - rsrc_data->first_line; + epoch0_line_cfg = (rsrc_data->last_line - + rsrc_data->first_line) / 4; /* epoch line cfg will still be configured at midpoint of the * frame width. We use '/ 4' instead of '/ 2' * cause it is multipixel path From 80560aa9383e3375414f1385bed6c8eb43a89c85 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 4 Oct 2019 09:52:24 -0700 Subject: [PATCH 130/790] msm: camera: isp: Add log for first SOF in EPCR This change adds a log for first SOF in early PCR. CRs-Fixed: 2546941 Change-Id: Iaca8695f0886fecba84e40b06798818b3f864c35 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 17411f6dc762..a06ce0b3d7b3 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1125,8 +1125,9 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id); - CAM_DBG(CAM_ISP, "next substate %d", - ctx_isp->substate_activated); + CAM_INFO(CAM_ISP, + "First SOF in EPCR ctx:%d frame_id:%lld next substate %d", + ctx->ctx_id, ctx_isp->frame_id, ctx_isp->substate_activated); return rc; } From faf531221131e59968c4ab1503c891c3c226da67 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Thu, 17 Oct 2019 14:58:21 +0530 Subject: [PATCH 131/790] msm: camera: csiphy: Update CPHY 3-phase registers for CSIPHY v1.2 Fix CSI_EXTRA_CTRL12 CPHY 3phase registers as per the latest HPG (rev. H). CRs-Fixed: 2542855 Change-Id: I6c2fbc66df52db71c454c86ee894c05d12e0dead Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index cc6c1adb366c..35e2a4ab1d6a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -334,7 +334,7 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -369,7 +369,7 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, From ec8b26eda2bbf98a99da0c8d03a06f1d4b256fd5 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 15 Oct 2019 17:24:18 -0700 Subject: [PATCH 132/790] msm: camera: ife: Remove duplicate add to port counters This change removes duplicate add to port counters during IFE acquire. CRs-Fixed: 2546941 Change-Id: Ie42838a2e66200a5a52cc27600bd25e430c0e3f0 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 3c82c6b2f8e5..05b41a7d8def 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2409,8 +2409,8 @@ static int cam_ife_mgr_acquire_hw_for_ctx( goto err; } - *num_pix_port += ipp_count + ppp_count + ife_rd_count + lcr_count; - *num_rdi_port += rdi_count; + *num_pix_port = ipp_count + ppp_count + ife_rd_count + lcr_count; + *num_rdi_port = rdi_count; return 0; err: From 69fc708d01521f60d972fdc478992ef73242e117 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 17 Oct 2019 18:31:30 -0700 Subject: [PATCH 133/790] msm: camera: icp: Fix AHB, AXI voting in icp Due to a mismatched internal structure num_paths for AXI voting is always set to 0 for ipe, bps which is causing not to vote any AXI bandwidth for these hws. After all contexts associated with a device go to inactive state, reduce the AHB vote to minimum value to make sure previously voted high AHB vote doesn't remain for the rest of camera session. CRs-Fixed: 2546088 Change-Id: I7621bb85280b2541ed37a87c9e486dd6be62ea24 Signed-off-by: Pavan Kumar Chilamkurthi --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 48 ++++++++++++++++--- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 + 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 786fd0e98f32..a02adb4cb202 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -431,6 +431,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) struct cam_icp_cpas_vote clk_update; int i = 0; int device_share_ratio = 1; + uint64_t total_ab_bw = 0; if (!ctx_data) { CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk"); @@ -494,10 +495,6 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) device_share_ratio = 2; - clk_update.ahb_vote.type = CAM_VOTE_DYNAMIC; - clk_update.ahb_vote.vote.freq = 0; - clk_update.ahb_vote_valid = false; - if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) { clk_update.axi_vote.num_paths = 1; if (ctx_data->icp_dev_acquire_info->dev_type == @@ -516,6 +513,8 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) clk_info->compressed_bw -= ctx_data->clk_info.compressed_bw; clk_info->uncompressed_bw -= ctx_data->clk_info.uncompressed_bw; + total_ab_bw = clk_info->compressed_bw; + ctx_data->clk_info.uncompressed_bw = 0; ctx_data->clk_info.compressed_bw = 0; ctx_data->clk_info.curr_fc = 0; @@ -580,6 +579,9 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) ctx_data->clk_info.axi_path[i].ddr_ab_bw; clk_info->axi_path[path_index].ddr_ib_bw -= ctx_data->clk_info.axi_path[i].ddr_ib_bw; + + total_ab_bw += + clk_info->axi_path[path_index].mnoc_ab_bw; } memset(&ctx_data->clk_info.axi_path[0], 0, @@ -616,6 +618,16 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) } clk_update.axi_vote_valid = true; + + if (total_ab_bw == 0) { + /* If no more contexts are active, reduce AHB vote to minimum */ + clk_update.ahb_vote.type = CAM_VOTE_ABSOLUTE; + clk_update.ahb_vote.vote.level = CAM_LOWSVS_VOTE; + clk_update.ahb_vote_valid = true; + } else { + clk_update.ahb_vote_valid = false; + } + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, &clk_update, sizeof(clk_update)); @@ -1061,7 +1073,8 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, if (!update_required) { CAM_DBG(CAM_ICP, - "Incoming BW hasn't changed, no update required"); + "Incoming BW hasn't changed, no update required, num_paths=%d", + clk_info->num_paths); return false; } @@ -1326,6 +1339,9 @@ static bool cam_icp_check_bw_update(struct cam_icp_hw_mgr *hw_mgr, } else if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V2) { clk_info_v2 = &ctx_data->hfi_frame_process.clk_info_v2[idx]; + CAM_DBG(CAM_ICP, "index=%d, num_paths=%d, ctx_data=%pK", + idx, clk_info_v2->num_paths, ctx_data); + bw_updated = cam_icp_update_bw_v2(hw_mgr, ctx_data, hw_mgr_clk_info, clk_info_v2, busy); @@ -4138,6 +4154,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, size_t io_buf_size, clk_update_size; int rc = 0; uintptr_t pResource; + uint32_t i = 0; if (!blob_data || (blob_size == 0)) { CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data, @@ -4241,9 +4258,26 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, clk_info->frame_cycles = clk_info_v2->frame_cycles; clk_info->rt_flag = clk_info_v2->rt_flag; - CAM_DBG(CAM_ICP, "budget=%llu, frame_cycle=%llu, rt_flag=%d", + CAM_DBG(CAM_ICP, + "budget=%llu, frame_cycle=%llu, rt_flag=%d, num_paths=%d, clk_update_size=%d, index=%d, ctx_data=%pK", clk_info_v2->budget_ns, clk_info_v2->frame_cycles, - clk_info_v2->rt_flag); + clk_info_v2->rt_flag, + clk_info_v2->num_paths, + clk_update_size, + index, + ctx_data); + + for (i = 0; i < clk_info_v2->num_paths; i++) { + CAM_DBG(CAM_ICP, + "[%d] : path_type=%d, trans_type=%d, camnoc=%lld, mnoc_ab=%lld, mnoc_ib=%lld", + i, + clk_info_v2->axi_path[i].path_data_type, + clk_info_v2->axi_path[i].transac_type, + clk_info_v2->axi_path[i].camnoc_bw, + clk_info_v2->axi_path[i].mnoc_ab_bw, + clk_info_v2->axi_path[i].mnoc_ib_bw); + } + break; case CAM_ICP_CMD_GENERIC_BLOB_CFG_IO: diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index b26bfc0dff65..7ca32efd9318 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -145,6 +145,7 @@ struct icp_frame_info { * @budget_ns: Time required to process frame * @frame_cycles: Frame cycles needed to process the frame * @rt_flag: Flag to indicate real time stream + * @reserved: Reserved filed. * @num_paths: Number of paths for per path bw vote * @axi_path: Per path vote info for IPE/BPS */ @@ -152,6 +153,7 @@ struct cam_icp_clk_bw_req_internal_v2 { uint64_t budget_ns; uint32_t frame_cycles; uint32_t rt_flag; + uint32_t reserved; uint32_t num_paths; struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; }; From 1fdbf849b90cd1f9d81b31cef4467fcba9e0d2ca Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Thu, 17 Oct 2019 17:34:47 +0530 Subject: [PATCH 134/790] msm: camera: ife: Add packing format support This change adds packing format field for CSID in IFE Lite for version 17x hardware. CRs-Fixed: 2547147 Change-Id: Ib6b8331af6a425314a507e18486c1fffd819007a Signed-off-by: Trishansh Bhardwaj --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h index 0573e30d151e..4d8783ce0c0f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_LITE17X_H_ @@ -286,6 +286,7 @@ static const struct cam_ife_csid_common_reg_offset .path_rst_stb_all = 0x7f, .path_rst_done_shift_val = 1, .path_en_shift_val = 31, + .packing_fmt_shift_val = 30, .dt_id_shift_val = 27, .vc_shift_val = 22, .dt_shift_val = 16, From efffa6d11a6db87eab41ac73e4d2079bd0ef1229 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Thu, 17 Oct 2019 11:36:29 -0700 Subject: [PATCH 135/790] msm: camera: isp: Dump isp req for cdm timeout Print out CDM command buffers to check for invalid command entry. CRs-Fixed: 2549972 Change-Id: I5998e62e4ba72fa67394ddf92a4680bc1c909597 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/cam_isp_context.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index a06ce0b3d7b3..56f51b124a43 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3734,6 +3734,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, CAM_ERR(CAM_ISP, "Start HW failed"); ctx->state = CAM_CTX_READY; trace_cam_context_state("ISP", ctx); + if (rc == -ETIMEDOUT) + cam_isp_ctx_dump_req(req_isp); list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); goto end; From 04cf1dd4ae4ce5a3ecaf3c7cff09c43198389278 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 17 Oct 2019 14:14:09 -0700 Subject: [PATCH 136/790] msm: camera: isp: Change state immediately in flush This commit changes the isp context state to flushed state immediately in order to ignore any further IRQs from the HW. CRs-Fixed: 2546941 Change-Id: I47f4999a3f51b581697e8dbfd07ef1539b478766 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 56 +++++++++++++++++++------------ 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 56f51b124a43..200e869f68bb 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -689,9 +689,10 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( if (done_next_req.num_handles) { struct cam_isp_hw_done_event_data unhandled_res; - struct cam_ctx_request *next_req = list_next_entry(req, list); + struct cam_ctx_request *next_req = list_last_entry( + &ctx->active_req_list, struct cam_ctx_request, list); - if (next_req) { + if (next_req->request_id != req->request_id) { /* * Few resource handles are already signalled in the * current request, lets check if there is another @@ -719,6 +720,10 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( CAM_ERR(CAM_ISP, "BUF Done not handled for next request %lld", next_req->request_id); + } else { + CAM_WARN(CAM_ISP, + "Req %lld only active request, spurious buf_done rxd", + req->request_id); } } @@ -2103,6 +2108,7 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, } } req_isp->reapply = false; + list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); } @@ -2127,33 +2133,37 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_hw_cmd_args hw_cmd_args; ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { - CAM_INFO(CAM_ISP, "Last request id to flush is %lld", - flush_req->req_id); - ctx->last_flush_req = flush_req->req_id; - } CAM_DBG(CAM_ISP, "Flush pending list"); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); spin_unlock_bh(&ctx->lock); - memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); - hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; - hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH; - rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, - &hw_cmd_args); - if (rc) { - CAM_ERR(CAM_ISP, "Reg dump on flush failed rc: %d", rc); - rc = 0; - } - if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { if (ctx->state <= CAM_CTX_READY) { ctx->state = CAM_CTX_ACQUIRED; goto end; } + spin_lock_bh(&ctx->lock); + ctx->state = CAM_CTX_FLUSHED; + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; + spin_unlock_bh(&ctx->lock); + + CAM_INFO(CAM_ISP, "Last request id to flush is %lld", + flush_req->req_id); + ctx->last_flush_req = flush_req->req_id; + + memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); + hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH; + rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_cmd_args); + if (rc) { + CAM_ERR(CAM_ISP, "Reg dump on flush failed rc: %d", rc); + rc = 0; + } + stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_isp.stop_only = true; @@ -2184,8 +2194,6 @@ static int __cam_isp_ctx_flush_req_in_top_state( if (rc) CAM_ERR(CAM_ISP, "Failed to reset HW rc: %d", rc); - ctx->state = CAM_CTX_FLUSHED; - ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; ctx_isp->init_received = false; } @@ -3025,10 +3033,12 @@ static int __cam_isp_ctx_config_dev_in_top_state( ctx_isp->init_received = true; } else { rc = -EINVAL; - CAM_ERR(CAM_ISP, "Recevied INIT pkt in wrong state"); + CAM_ERR(CAM_ISP, "Recevied INIT pkt in wrong state:%d", + ctx->state); } } else { - if (ctx->state >= CAM_CTX_READY && ctx->ctx_crm_intf->add_req) { + if (ctx->state != CAM_CTX_FLUSHED && ctx->state >= CAM_CTX_READY + && ctx->ctx_crm_intf->add_req) { add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; @@ -3043,7 +3053,9 @@ static int __cam_isp_ctx_config_dev_in_top_state( } } else { rc = -EINVAL; - CAM_ERR(CAM_ISP, "Recevied Update in wrong state"); + CAM_ERR(CAM_ISP, + "Recevied update req %lld in wrong state:%d", + req->request_id, ctx->state); } } if (rc) From cb1341b56b2a7ef13d4908b8a02b3a470595034b Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Tue, 1 Oct 2019 15:21:35 -0700 Subject: [PATCH 137/790] msm: camera: jpeg: Add plane stride & slice height debug info Add plane stride and slice height to debug info for verifying JPEG buffer configuration. CRs-Fixed: 2542420 Change-Id: I67fbb0a0da9104b4f9c412a558b62149abb8aec9 Signed-off-by: Karthik Jayakumar --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 9f331d46221c..27a12377d16e 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -663,15 +663,15 @@ static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, } CAM_INFO(CAM_JPEG, - "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x", + "pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x", j, 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], io_cfg[i].mem_handle[j]); - - iova_addr += io_cfg[i].offsets[j]; } } } From c23b66889006544bc477050ca39614ce97b61741 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 23 Oct 2019 20:06:51 -0700 Subject: [PATCH 138/790] msm: camera: isp: Limit sof_in_epoch log to first frame This change limits SOF in early PCR log to the first frame for that context. This log is needed to catch unexpected reg updates on first frame after stream on. CRs-Fixed: 2553728 Change-Id: Icad85aeab2b095a6b95889c933a2de34acebed80 Signed-off-by: Venkat Chinta Signed-off-by: Vishalsingh Hajeri Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_isp/cam_isp_context.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 200e869f68bb..722680b5c96a 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1130,8 +1130,13 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id); - CAM_INFO(CAM_ISP, - "First SOF in EPCR ctx:%d frame_id:%lld next substate %d", + if (ctx_isp->frame_id == 1) + CAM_INFO(CAM_ISP, + "First SOF in EPCR ctx:%d frame_id:%lld next substate %d", + ctx->ctx_id, ctx_isp->frame_id, + ctx_isp->substate_activated); + + CAM_DBG(CAM_ISP, "SOF in epoch ctx:%d frame_id:%lld next substate:%d", ctx->ctx_id, ctx_isp->frame_id, ctx_isp->substate_activated); return rc; From 09e2bdc6bfd6fe084586b295a904f19912046c69 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 28 Oct 2019 11:33:28 -0700 Subject: [PATCH 139/790] msm: camera: isp: Improve isp substate logging Improve sp substate logging to print state string instead of value. Add handler for reg_update in bubble state to print a warning log indicate the event. CRs-Fixed: 2523062 Change-Id: I95c6f16733a177cbf33099775d8ef7eb049a62b4 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_isp/cam_isp_context.c | 183 +++++++++++++++++++----------- drivers/cam_isp/cam_isp_context.h | 46 ++++---- 2 files changed, 140 insertions(+), 89 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 722680b5c96a..b251d75ac2f5 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -56,7 +56,7 @@ static void __cam_isp_ctx_update_state_monitor_array( } static const char *__cam_isp_ctx_substate_val_to_type( - uint32_t type) + enum cam_isp_ctx_activated_substate type) { switch (type) { case CAM_ISP_CTX_ACTIVATED_SOF: @@ -74,7 +74,7 @@ static const char *__cam_isp_ctx_substate_val_to_type( case CAM_ISP_CTX_ACTIVATED_HALT: return "HALT"; default: - return "CAM_ISP_CTX_INVALID_STATE"; + return "INVALID"; } } @@ -130,7 +130,7 @@ static void __cam_isp_ctx_dump_state_monitor_array( for (i = 0; i < num_entries; i++) { CAM_ERR(CAM_ISP, - "Index[%d] time[%d] : State[%s] Frame[%lld] ReqId[%llu] evt_type[%s]", + "Index[%d] time[%d] : Substate[%s] Frame[%lld] ReqId[%llu] evt_type[%s]", index, ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp, __cam_isp_ctx_substate_val_to_type( @@ -730,15 +730,19 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( return rc; } -static int __cam_isp_ctx_reg_upd_in_epoch_state( +static int __cam_isp_ctx_reg_upd_in_epoch_bubble_state( struct cam_isp_context *ctx_isp, void *evt_data) { if (ctx_isp->frame_id == 1) - CAM_DBG(CAM_ISP, "Reg update for early PCR"); + CAM_DBG(CAM_ISP, "Reg update in Substate[%s] for early PCR", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); else CAM_WARN(CAM_ISP, - "Unexpected reg update in activated substate:%d for frame_id:%lld", - ctx_isp->substate_activated, ctx_isp->frame_id); + "Unexpected reg update in activated Substate[%s] for frame_id:%lld", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), + ctx_isp->frame_id); return 0; } @@ -780,7 +784,9 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( * state so change substate here. */ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; - CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE, request_id); @@ -1073,8 +1079,9 @@ 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_DBG(CAM_ISP, "next substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); end: if (request_id == 0) { req = list_last_entry(&ctx->active_req_list, @@ -1132,12 +1139,15 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, if (ctx_isp->frame_id == 1) CAM_INFO(CAM_ISP, - "First SOF in EPCR ctx:%d frame_id:%lld next substate %d", + "First SOF in EPCR ctx:%d frame_id:%lld next substate %s", ctx->ctx_id, ctx_isp->frame_id, - ctx_isp->substate_activated); + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); - CAM_DBG(CAM_ISP, "SOF in epoch ctx:%d frame_id:%lld next substate:%d", - ctx->ctx_id, ctx_isp->frame_id, ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "SOF in epoch ctx:%d frame_id:%lld next substate:%s", + ctx->ctx_id, ctx_isp->frame_id, + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); return rc; } @@ -1237,7 +1247,9 @@ 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_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); end: req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request, list); @@ -1718,7 +1730,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( rc = -EFAULT; } - CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); end: if (req != NULL && !rc) { __cam_isp_ctx_update_state_monitor_array(ctx_isp, @@ -1757,7 +1771,7 @@ static struct cam_isp_ctx_irq_ops .irq_ops = { __cam_isp_ctx_handle_error, __cam_isp_ctx_sof_in_epoch, - __cam_isp_ctx_reg_upd_in_epoch_state, + __cam_isp_ctx_reg_upd_in_epoch_bubble_state, __cam_isp_ctx_notify_sof_in_activated_state, __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_epoch, @@ -1768,7 +1782,7 @@ static struct cam_isp_ctx_irq_ops .irq_ops = { __cam_isp_ctx_handle_error, __cam_isp_ctx_sof_in_activated_state, - NULL, + __cam_isp_ctx_reg_upd_in_epoch_bubble_state, __cam_isp_ctx_notify_sof_in_activated_state, __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_bubble, @@ -1830,7 +1844,7 @@ static struct cam_isp_ctx_irq_ops .irq_ops = { __cam_isp_ctx_handle_error, __cam_isp_ctx_sof_in_epoch, - __cam_isp_ctx_reg_upd_in_epoch_state, + __cam_isp_ctx_reg_upd_in_epoch_bubble_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, @@ -1841,7 +1855,7 @@ static struct cam_isp_ctx_irq_ops .irq_ops = { __cam_isp_ctx_handle_error, __cam_isp_ctx_sof_in_activated_state, - NULL, + __cam_isp_ctx_reg_upd_in_epoch_bubble_state, __cam_isp_ctx_notify_sof_in_activated_state, __cam_isp_ctx_notify_eof_in_activated_state, __cam_isp_ctx_buf_done_in_bubble, @@ -1876,7 +1890,7 @@ static struct cam_isp_ctx_irq_ops 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) + enum cam_isp_ctx_activated_substate next_state) { int rc = 0; struct cam_ctx_request *req; @@ -1926,8 +1940,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( goto end; } - CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u", - req->request_id, ctx_isp->substate_activated, ctx->ctx_id); + CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u", + req->request_id, + __cam_isp_ctx_substate_val_to_type(ctx_isp->substate_activated), + ctx->ctx_id); req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (ctx_isp->active_req_cnt >= 2) { @@ -1976,8 +1992,9 @@ static int __cam_isp_ctx_apply_req_in_activated_state( ctx_isp->last_applied_req_id = apply->request_id; list_del_init(&req->list); list_add_tail(&req->list, &ctx->wait_req_list); - CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld", - next_state, ctx_isp->last_applied_req_id); + CAM_DBG(CAM_ISP, "new substate Substate[%s], applied req %lld", + __cam_isp_ctx_substate_val_to_type(next_state), + ctx_isp->last_applied_req_id); spin_unlock_bh(&ctx->lock); __cam_isp_ctx_update_state_monitor_array(ctx_isp, @@ -1995,15 +2012,19 @@ static int __cam_isp_ctx_apply_req_in_sof( struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - CAM_DBG(CAM_ISP, "current substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "current Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); 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_DBG(CAM_ISP, "new Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); if (rc) - CAM_DBG(CAM_ISP, "Apply failed in state %d, rc %d", - ctx_isp->substate_activated, rc); + CAM_DBG(CAM_ISP, "Apply failed in Substate[%s], rc %d", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), rc); return rc; } @@ -2015,15 +2036,19 @@ static int __cam_isp_ctx_apply_req_in_epoch( struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - CAM_DBG(CAM_ISP, "current substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "current Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); 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_DBG(CAM_ISP, "new Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); if (rc) - CAM_DBG(CAM_ISP, "Apply failed in state %d, rc %d", - ctx_isp->substate_activated, rc); + CAM_DBG(CAM_ISP, "Apply failed in Substate[%s], rc %d", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), rc); return rc; } @@ -2035,15 +2060,19 @@ static int __cam_isp_ctx_apply_req_in_bubble( struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - CAM_DBG(CAM_ISP, "current substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "current Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); 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_DBG(CAM_ISP, "new Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); if (rc) - CAM_DBG(CAM_ISP, "Apply failed in state %d, rc %d", - ctx_isp->substate_activated, rc); + CAM_DBG(CAM_ISP, "Apply failed in Substate[%s], rc %d", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), rc); return rc; } @@ -2389,8 +2418,9 @@ 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_DBG(CAM_ISP, "next substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); return rc; } @@ -2411,7 +2441,9 @@ 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_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); return 0; } @@ -2507,7 +2539,9 @@ 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_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); end: return 0; } @@ -2579,8 +2613,9 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; - CAM_DBG(CAM_ISP, "next substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); return 0; } @@ -2644,7 +2679,9 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); - CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); return 0; error: @@ -2734,15 +2771,19 @@ static int __cam_isp_ctx_rdi_only_apply_req_top_state( struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - CAM_DBG(CAM_ISP, "current substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "current Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); 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_DBG(CAM_ISP, "new Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); if (rc) - CAM_ERR(CAM_ISP, "Apply failed in state %d, rc %d", - ctx_isp->substate_activated, rc); + CAM_ERR(CAM_ISP, "Apply failed in Substate[%s], rc %d", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), rc); return rc; } @@ -3808,7 +3849,9 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( spin_lock_bh(&ctx->lock); 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_DBG(CAM_ISP, "next Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); while (!list_empty(&ctx->pending_req_list)) { req = list_first_entry(&ctx->pending_req_list, @@ -4032,22 +4075,25 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx, (struct cam_isp_context *) ctx->ctx_priv; trace_cam_apply_req("ISP", apply->request_id); - CAM_DBG(CAM_ISP, "Enter: apply req in Substate %d request _id:%lld", - ctx_isp->substate_activated, apply->request_id); + CAM_DBG(CAM_ISP, "Enter: apply req in Substate[%s] request_id:%lld", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), apply->request_id); ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated]; if (ctx_ops->crm_ops.apply_req) { rc = ctx_ops->crm_ops.apply_req(ctx, apply); } else { CAM_WARN_RATE_LIMIT(CAM_ISP, - "No handle function in activated substate %d", - ctx_isp->substate_activated); + "No handle function in activated Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); rc = -EFAULT; } if (rc) CAM_WARN_RATE_LIMIT(CAM_ISP, - "Apply failed in active substate %d rc %d", - ctx_isp->substate_activated, rc); + "Apply failed in active Substate[%s] rc %d", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), rc); return rc; } @@ -4067,20 +4113,23 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id, __cam_isp_ctx_get_event_ts(evt_id, evt_data)); - CAM_DBG(CAM_ISP, "Enter: State %d, Substate %d, evt id %d", - ctx->state, ctx_isp->substate_activated, evt_id); + CAM_DBG(CAM_ISP, "Enter: State %d, Substate[%s], evt id %d", + ctx->state, __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), evt_id); irq_ops = &ctx_isp->substate_machine_irq[ctx_isp->substate_activated]; if (irq_ops->irq_ops[evt_id]) { rc = irq_ops->irq_ops[evt_id](ctx_isp, evt_data); } else { - CAM_DBG(CAM_ISP, "No handle function for substate %d", - ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "No handle function for Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); if (isp_ctx_debug.enable_state_monitor_dump) __cam_isp_ctx_dump_state_monitor_array(ctx_isp); } - CAM_DBG(CAM_ISP, "Exit: State %d Substate %d", - ctx->state, ctx_isp->substate_activated); + CAM_DBG(CAM_ISP, "Exit: State %d Substate[%s]", + ctx->state, __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); spin_unlock(&ctx->lock); return rc; } @@ -4358,7 +4407,9 @@ int cam_isp_context_deinit(struct cam_isp_context *ctx) cam_context_deinit(ctx->base); if (ctx->substate_activated != CAM_ISP_CTX_ACTIVATED_SOF) - CAM_ERR(CAM_ISP, "ISP context substate is invalid"); + CAM_ERR(CAM_ISP, "ISP context Substate[%s] is invalid", + __cam_isp_ctx_substate_val_to_type( + ctx->substate_activated)); memset(ctx, 0, sizeof(*ctx)); return rc; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 1151ca78c052..34f899f65b27 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -180,33 +180,33 @@ struct cam_isp_context_state_monitor { * */ struct cam_isp_context { - struct cam_context *base; + struct cam_context *base; - int64_t frame_id; - uint32_t substate_activated; - atomic_t process_bubble; - uint32_t bubble_frame_cnt; - struct cam_ctx_ops *substate_machine; - struct cam_isp_ctx_irq_ops *substate_machine_irq; + int64_t frame_id; + enum cam_isp_ctx_activated_substate substate_activated; + atomic_t process_bubble; + uint32_t bubble_frame_cnt; + struct cam_ctx_ops *substate_machine; + struct cam_isp_ctx_irq_ops *substate_machine_irq; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; - struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; - void *hw_ctx; - uint64_t sof_timestamp_val; - uint64_t boot_timestamp; - int32_t active_req_cnt; - int64_t reported_req_id; - uint32_t subscribe_event; - int64_t last_applied_req_id; - atomic64_t state_monitor_head; - struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ + void *hw_ctx; + uint64_t sof_timestamp_val; + uint64_t boot_timestamp; + int32_t active_req_cnt; + int64_t reported_req_id; + uint32_t subscribe_event; + int64_t last_applied_req_id; + atomic64_t state_monitor_head; + struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; - bool rdi_only_context; - bool hw_acquired; - bool init_received; - bool split_acquire; - unsigned int init_timestamp; + bool rdi_only_context; + bool hw_acquired; + bool init_received; + bool split_acquire; + unsigned int init_timestamp; }; /** From d1469c8f6a123d3a538044bdc8107172ffcfcd66 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Wed, 30 Oct 2019 13:39:40 +0530 Subject: [PATCH 140/790] msm: camera: isp: Set device enable flag after enable csid hardware Device enable flag is getting set after configuring the CSID csi rx and csid path configuration. If irq comes after configuring the csi rx hardware then irq handler is not handling as it is checking the device enable flag. So set device enable flag after enabling the hardware. CRs-Fixed: 2541840 Change-Id: I022b6dccef4153c34bc8cf99e7a18e2978f92d3f Signed-off-by: Ravikishore Pampana --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index af9f67286d82..96c88567dc31 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1194,6 +1194,7 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) struct cam_hw_soc_info *soc_info; uint32_t i, val; int clk_lvl; + unsigned long flags; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1274,6 +1275,10 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x", csid_hw->hw_intf->hw_idx, val); + spin_lock_irqsave(&csid_hw->lock_state, flags); + csid_hw->device_enabled = 1; + spin_unlock_irqrestore(&csid_hw->lock_state, flags); + return 0; disable_soc: @@ -3257,7 +3262,6 @@ 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))) { @@ -3338,9 +3342,6 @@ 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; From 4e9f21ee2747c133372160bf5078e56c4e885d0f Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 22 Oct 2019 16:52:22 +0530 Subject: [PATCH 141/790] msm: camera: reqmgr: Remove division on uint64_t Arm arch does not support dividing 64 bit integer, replacing it with do_div call. CRs-Fixed: 2543730 Change-Id: I86f8c706d20978b4c7bfd78c499dacb482c4d37a Signed-off-by: Trishansh Bhardwaj --- drivers/cam_req_mgr/cam_req_mgr_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index be08f48a5f72..427bc87d672e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1198,10 +1198,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( * difference of two SOF timestamp less than * (sync_frame_duration / 5). */ + do_div(sync_frame_duration, 5); if ((link->sof_timestamp > sync_link->sof_timestamp) && (sync_link->sof_timestamp > 0) && (link->sof_timestamp - sync_link->sof_timestamp < - sync_frame_duration / 5) && + sync_frame_duration) && (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { /* From 30b9eed071a10735947f2773711c698a37b76805 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Wed, 30 Oct 2019 15:22:06 +0530 Subject: [PATCH 142/790] msm: camera: common: Fix integer overflow in shift Various drivers are using right shift by 32 to check if dma address is 32 bit addressable. This will result in shift count overflow in 32 bit arch. CRs-Fixed: 2543730 Change-Id: I57e30bc9c0a8179c8d74f3bd3b6567bdfff60741 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a02adb4cb202..e82c04b44890 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4490,7 +4490,7 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, "get src buf address fail rc %d", rc); continue; } - if (iova_addr >> 32) { + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { CAM_ERR(CAM_ICP, "Invalid mapped address"); rc = -EINVAL; continue; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 05b41a7d8def..1f394d8bcad5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5740,7 +5740,7 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, io_cfg[i].mem_handle[j]); continue; } - if (iova_addr >> 32) { + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { CAM_ERR(CAM_ISP, "Invalid mapped address"); rc = -EINVAL; continue; diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 27a12377d16e..09b4b8d3e0f6 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -656,7 +656,7 @@ static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, CAM_ERR(CAM_UTIL, "get src buf address fail"); continue; } - if (iova_addr >> 32) { + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { CAM_ERR(CAM_JPEG, "Invalid mapped address"); rc = -EINVAL; continue; From bef4415dc8476866ec2651102667a717dd06fe25 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 29 Oct 2019 11:52:12 +0530 Subject: [PATCH 143/790] msm: camera: common: va_end should follow va_start Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function. CRs-Fixed: 2549155 Change-Id: I6a3214ce863c4af0425d061184cfa44682f89545 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_utils/cam_debug_util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index 274980f8bb64..1cd21b2a971d 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundataion. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundataion. All rights reserved. */ #include @@ -115,6 +115,7 @@ void cam_debug_log(unsigned int module_id, const char *func, const int line, pr_info("CAM_DBG: %s: %s: %d: %s\n", cam_get_module_name(module_id), func, line, str_buffer); - va_end(args); } + + va_end(args); } From a293b9bfe62f2624e0603e74476c5bd2bc21b620 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 28 Oct 2019 12:11:02 -0700 Subject: [PATCH 144/790] msm: camera: icp: Use CAM_PERF for clock, bw related logs Use CAM_PERF logging group while printing logs related to clock, bandwidth updates. CRs-Fixed: 2523062 Change-Id: Icaa912ae308c307d55e318c0861850093d0ee456 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 16 ++-- drivers/cam_icp/icp_hw/bps_hw/bps_soc.c | 2 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 91 ++++++++++--------- drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 16 ++-- drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 21 +++-- 6 files changed, 75 insertions(+), 73 deletions(-) diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index 232f29c81db6..8a079bd14202 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -40,7 +40,7 @@ static int cam_bps_cpas_vote(struct cam_bps_device_core_info *core_info, &cpas_vote->axi_vote); if (rc < 0) - CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc); + CAM_ERR(CAM_PERF, "cpas vote is failed: %d", rc); return rc; } @@ -171,7 +171,7 @@ static int cam_bps_handle_pc(struct cam_hw_info *bps_dev) hw_info->pwr_ctrl, true, 0x1); if ((pwr_status >> BPS_PWR_ON_MASK)) - CAM_WARN(CAM_ICP, "BPS: pwr_status(%x):pwr_ctrl(%x)", + CAM_WARN(CAM_PERF, "BPS: pwr_status(%x):pwr_ctrl(%x)", pwr_status, pwr_ctrl); } cam_bps_get_gdsc_control(soc_info); @@ -181,7 +181,7 @@ static int cam_bps_handle_pc(struct cam_hw_info *bps_dev) cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status); - CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", pwr_ctrl, pwr_status); return 0; @@ -203,7 +203,7 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); if (pwr_ctrl & BPS_COLLAPSE_MASK) { - CAM_DBG(CAM_ICP, "BPS: pwr_ctrl set(%x)", pwr_ctrl); + CAM_DBG(CAM_PERF, "BPS: pwr_ctrl set(%x)", pwr_ctrl); cam_cpas_reg_write(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, 0); @@ -214,7 +214,7 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status); - CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", pwr_ctrl, pwr_status); return rc; @@ -370,7 +370,7 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; - CAM_DBG(CAM_ICP, "bps_src_clk rate = %d", (int)clk_rate); + CAM_DBG(CAM_PERF, "bps_src_clk rate = %d", (int)clk_rate); if (!core_info->clk_enable) { if (clk_upd_cmd->ipe_bps_pc_enable) { @@ -390,10 +390,10 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, CAM_ERR(CAM_ICP, "BPS resume failed"); } } - CAM_DBG(CAM_ICP, "clock rate %d", clk_rate); + CAM_DBG(CAM_PERF, "clock rate %d", clk_rate); rc = cam_bps_update_clk_rate(soc_info, clk_rate); if (rc) - CAM_ERR(CAM_ICP, "Failed to update clk"); + CAM_ERR(CAM_PERF, "Failed to update clk %d", clk_rate); err = cam_soc_util_get_clk_level(soc_info, clk_rate, soc_info->src_clk_idx, diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c index bf152d1fc485..481eeafdb0b2 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c @@ -140,7 +140,7 @@ int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info, if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) && (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { - CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d", + CAM_DBG(CAM_PERF, "clk_rate %d greater than max, reset to %d", clk_rate, soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a02adb4cb202..a02671a9feea 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -182,7 +182,7 @@ static bool cam_icp_is_over_clk(struct cam_icp_hw_mgr *hw_mgr, curr_clk_idx = cam_icp_get_actual_clk_rate_idx(ctx_data, hw_mgr_clk_info->curr_clk); - CAM_DBG(CAM_ICP, "bc_idx = %d cc_idx = %d %d %d", + CAM_DBG(CAM_PERF, "bc_idx = %d cc_idx = %d %d %d", base_clk_idx, curr_clk_idx, hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk); @@ -202,7 +202,7 @@ static int cam_icp_get_lower_clk_rate(struct cam_icp_hw_mgr *hw_mgr, if (i > 0) return ctx_data->clk_info.clk_rate[i - 1]; - CAM_DBG(CAM_ICP, "Already clk at lower level"); + CAM_DBG(CAM_PERF, "Already clk at lower level"); return base_clk; } @@ -216,7 +216,7 @@ static int cam_icp_get_next_clk_rate(struct cam_icp_hw_mgr *hw_mgr, if (i < CAM_MAX_VOTE - 1) return ctx_data->clk_info.clk_rate[i + 1]; - CAM_DBG(CAM_ICP, "Already clk at higher level"); + CAM_DBG(CAM_PERF, "Already clk at higher level"); return base_clk; } @@ -256,7 +256,7 @@ static int cam_icp_supported_clk_rates(struct cam_icp_hw_mgr *hw_mgr, for (i = 0; i < CAM_MAX_VOTE; i++) { ctx_data->clk_info.clk_rate[i] = soc_info->clk_rate[i][soc_info->src_clk_idx]; - CAM_DBG(CAM_ICP, "clk_info[%d] = %d", + CAM_DBG(CAM_PERF, "clk_info[%d] = %d", i, ctx_data->clk_info.clk_rate[i]); } @@ -307,7 +307,7 @@ static int cam_icp_ctx_timer_reset(struct cam_icp_hw_ctx_data *ctx_data) { if (ctx_data && ctx_data->watch_dog) { ctx_data->watch_dog_reset_counter++; - CAM_DBG(CAM_ICP, "reset timer : ctx_id = %d, counter=%d", + CAM_DBG(CAM_PERF, "reset timer : ctx_id = %d, counter=%d", ctx_data->ctx_id, ctx_data->watch_dog_reset_counter); crm_timer_reset(ctx_data->watch_dog); } @@ -322,7 +322,7 @@ static void cam_icp_device_timer_reset(struct cam_icp_hw_mgr *hw_mgr, return; if (hw_mgr->clk_info[device_index].watch_dog) { - CAM_DBG(CAM_ICP, "reset timer : device_index = %d", + CAM_DBG(CAM_PERF, "reset timer : device_index = %d", device_index); crm_timer_reset(hw_mgr->clk_info[device_index].watch_dog); hw_mgr->clk_info[device_index].watch_dog_reset_counter++; @@ -396,7 +396,7 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data) goto done; } - CAM_DBG(CAM_ICP, "Disable %d", clk_info->hw_type); + CAM_DBG(CAM_PERF, "Disable %d", clk_info->hw_type); clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; @@ -441,7 +441,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) mutex_lock(&ctx_data->ctx_mutex); if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) || (ctx_data->watch_dog_reset_counter == 0)) { - CAM_DBG(CAM_ICP, "state %d, counter=%d", + CAM_DBG(CAM_PERF, "state %d, counter=%d", ctx_data->state, ctx_data->watch_dog_reset_counter); mutex_unlock(&ctx_data->ctx_mutex); return 0; @@ -453,7 +453,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) return -EBUSY; } - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u", ctx_data->ctx_id, ctx_data->clk_info.uncompressed_bw, @@ -560,7 +560,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) } if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { - CAM_WARN(CAM_ICP, + CAM_WARN(CAM_PERF, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i] .path_data_type, @@ -641,7 +641,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id, &clk_update, sizeof(clk_update)); - CAM_DBG(CAM_ICP, "X :ctx_id = %d curr_fc = %u bc = %u", + CAM_DBG(CAM_PERF, "X :ctx_id = %d curr_fc = %u bc = %u", ctx_data->ctx_id, ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk); mutex_unlock(&ctx_data->ctx_mutex); @@ -739,7 +739,7 @@ static int cam_icp_ctx_timer_start(struct cam_icp_hw_ctx_data *ctx_data) ctx_data->watch_dog_reset_counter = 0; - CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + CAM_DBG(CAM_PERF, "start timer : ctx_id = %d", ctx_data->ctx_id); return rc; } @@ -767,7 +767,7 @@ static int cam_icp_device_timer_start(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_ctx_timer_stop(struct cam_icp_hw_ctx_data *ctx_data) { if (ctx_data->watch_dog) { - CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + CAM_DBG(CAM_PERF, "stop timer : ctx_id = %d", ctx_data->ctx_id); ctx_data->watch_dog_reset_counter = 0; crm_timer_exit(&ctx_data->watch_dog); ctx_data->watch_dog = NULL; @@ -802,7 +802,7 @@ static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles, base_clk = frame_cycles * mul; do_div(base_clk, budget); - CAM_DBG(CAM_ICP, "budget = %lld fc = %d ib = %lld base_clk = %lld", + CAM_DBG(CAM_PERF, "budget = %lld fc = %d ib = %lld base_clk = %lld", budget, frame_cycles, (long long)(frame_cycles * mul), base_clk); @@ -818,7 +818,7 @@ static bool cam_icp_busy_prev_reqs(struct hfi_frame_process_info *frm_process, for (i = 0, cnt = 0; i < CAM_FRAME_CMD_MAX; i++) { if (frm_process->request_id[i]) { if (frm_process->fw_process_flag[i]) { - CAM_DBG(CAM_ICP, "r id = %lld busy = %d", + CAM_DBG(CAM_PERF, "r id = %lld busy = %d", frm_process->request_id[i], frm_process->fw_process_flag[i]); cnt++; @@ -1010,7 +1010,7 @@ static bool cam_icp_debug_clk_update(struct cam_icp_clk_info *hw_mgr_clk_info) hw_mgr_clk_info->curr_clk = icp_hw_mgr.icp_debug_clk; hw_mgr_clk_info->uncompressed_bw = icp_hw_mgr.icp_debug_clk; hw_mgr_clk_info->compressed_bw = icp_hw_mgr.icp_debug_clk; - CAM_DBG(CAM_ICP, "bc = %d cc = %d", + CAM_DBG(CAM_PERF, "bc = %d cc = %d", hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk); return true; } @@ -1025,7 +1025,7 @@ static bool cam_icp_default_clk_update(struct cam_icp_clk_info *hw_mgr_clk_info) hw_mgr_clk_info->curr_clk = icp_hw_mgr.icp_default_clk; hw_mgr_clk_info->uncompressed_bw = icp_hw_mgr.icp_default_clk; hw_mgr_clk_info->compressed_bw = icp_hw_mgr.icp_default_clk; - CAM_DBG(CAM_ICP, "bc = %d cc = %d", + CAM_DBG(CAM_PERF, "bc = %d cc = %d", hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk); return true; } @@ -1049,7 +1049,7 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, */ for (i = 0; i < clk_info->num_paths; i++) - CAM_DBG(CAM_ICP, "clk_info camnoc = %lld busy = %d", + CAM_DBG(CAM_PERF, "clk_info camnoc = %lld busy = %d", clk_info->axi_path[i].camnoc_bw, busy); if (clk_info->num_paths == ctx_data->clk_info.num_paths) { @@ -1072,7 +1072,7 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, } if (!update_required) { - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "Incoming BW hasn't changed, no update required, num_paths=%d", clk_info->num_paths); return false; @@ -1104,7 +1104,7 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, } if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { - CAM_WARN(CAM_ICP, + CAM_WARN(CAM_PERF, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i].path_data_type, CAM_AXI_PATH_DATA_IPE_START_OFFSET, @@ -1148,7 +1148,7 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, } if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { - CAM_WARN(CAM_ICP, + CAM_WARN(CAM_PERF, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i].path_data_type, CAM_AXI_PATH_DATA_IPE_START_OFFSET, @@ -1171,7 +1171,7 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, hw_mgr_clk_info->axi_path[path_index].ddr_ib_bw += ctx_data->clk_info.axi_path[i].ddr_ib_bw; - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "Consolidate Path Vote : Dev[%s] i[%d] path_idx[%d] : [%s %s] [%lld %lld]", cam_icp_dev_type_to_name( ctx_data->icp_dev_acquire_info->dev_type), @@ -1204,14 +1204,14 @@ static bool cam_icp_update_bw(struct cam_icp_hw_mgr *hw_mgr, * recalculate bandwidth of all contexts of same hardware and update * voting of bandwidth */ - CAM_DBG(CAM_ICP, "ubw ctx = %lld clk_info ubw = %lld busy = %d", + CAM_DBG(CAM_PERF, "ubw ctx = %lld clk_info ubw = %lld busy = %d", ctx_data->clk_info.uncompressed_bw, clk_info->uncompressed_bw, busy); if ((clk_info->uncompressed_bw == ctx_data->clk_info.uncompressed_bw) && (ctx_data->clk_info.uncompressed_bw == hw_mgr_clk_info->uncompressed_bw)) { - CAM_DBG(CAM_ICP, "Update not required bw=%lld", + CAM_DBG(CAM_PERF, "Update not required bw=%lld", ctx_data->clk_info.uncompressed_bw); return false; } @@ -1219,7 +1219,8 @@ static bool cam_icp_update_bw(struct cam_icp_hw_mgr *hw_mgr, if (busy && (ctx_data->clk_info.uncompressed_bw > clk_info->uncompressed_bw)) { - CAM_DBG(CAM_ICP, "Busy, Update not req existing=%lld, new=%lld", + CAM_DBG(CAM_PERF, + "Busy, Update not req existing=%lld, new=%lld", ctx_data->clk_info.uncompressed_bw, clk_info->uncompressed_bw); return false; @@ -1240,7 +1241,7 @@ static bool cam_icp_update_bw(struct cam_icp_hw_mgr *hw_mgr, ctx->clk_info.uncompressed_bw; hw_mgr_clk_info->compressed_bw += ctx->clk_info.compressed_bw; - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "Current context=[%lld %lld] Total=[%lld %lld]", ctx->clk_info.uncompressed_bw, ctx->clk_info.compressed_bw, @@ -1266,11 +1267,11 @@ static bool cam_icp_check_clk_update(struct cam_icp_hw_mgr *hw_mgr, if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_BPS); hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; - CAM_DBG(CAM_ICP, "Reset bps timer"); + CAM_DBG(CAM_PERF, "Reset bps timer"); } else { cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_IPE); hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; - CAM_DBG(CAM_ICP, "Reset ipe timer"); + CAM_DBG(CAM_PERF, "Reset ipe timer"); } if (icp_hw_mgr.icp_debug_clk) @@ -1280,7 +1281,7 @@ static bool cam_icp_check_clk_update(struct cam_icp_hw_mgr *hw_mgr, frame_info = &ctx_data->hfi_frame_process; req_id = frame_info->request_id[idx]; busy = cam_icp_busy_prev_reqs(frame_info, req_id); - CAM_DBG(CAM_ICP, "busy = %d req_id = %lld", busy, req_id); + CAM_DBG(CAM_PERF, "busy = %d req_id = %lld", busy, req_id); clk_info = &ctx_data->hfi_frame_process.clk_info[idx]; if (!clk_info->frame_cycles) @@ -1298,7 +1299,7 @@ static bool cam_icp_check_clk_update(struct cam_icp_hw_mgr *hw_mgr, rc = cam_icp_update_clk_free(hw_mgr, ctx_data, hw_mgr_clk_info, clk_info, base_clk); - CAM_DBG(CAM_ICP, "bc = %d cc = %d busy = %d overclk = %d uc = %d", + CAM_DBG(CAM_PERF, "bc = %d cc = %d busy = %d overclk = %d uc = %d", hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk, busy, hw_mgr_clk_info->over_clked, rc); @@ -1328,7 +1329,7 @@ static bool cam_icp_check_bw_update(struct cam_icp_hw_mgr *hw_mgr, if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) { clk_info = &ctx_data->hfi_frame_process.clk_info[idx]; - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "Ctx[%pK][%d] Req[%lld] Current camno=%lld, mnoc=%lld", ctx_data, ctx_data->ctx_id, req_id, hw_mgr_clk_info->uncompressed_bw, @@ -1339,14 +1340,14 @@ static bool cam_icp_check_bw_update(struct cam_icp_hw_mgr *hw_mgr, } else if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V2) { clk_info_v2 = &ctx_data->hfi_frame_process.clk_info_v2[idx]; - CAM_DBG(CAM_ICP, "index=%d, num_paths=%d, ctx_data=%pK", + CAM_DBG(CAM_PERF, "index=%d, num_paths=%d, ctx_data=%pK", idx, clk_info_v2->num_paths, ctx_data); bw_updated = cam_icp_update_bw_v2(hw_mgr, ctx_data, hw_mgr_clk_info, clk_info_v2, busy); for (i = 0; i < hw_mgr_clk_info->num_paths; i++) { - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "Final path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s", cam_cpas_axi_util_path_type_to_string( hw_mgr_clk_info->axi_path[i].path_data_type), @@ -1359,7 +1360,7 @@ static bool cam_icp_check_bw_update(struct cam_icp_hw_mgr *hw_mgr, ctx_data->icp_dev_acquire_info->dev_type)); } } else { - CAM_ERR(CAM_ICP, "Invalid bw config version: %d", + CAM_ERR(CAM_PERF, "Invalid bw config version: %d", ctx_data->bw_config_version); return false; } @@ -1418,7 +1419,7 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, } /* update a5 clock */ - CAM_DBG(CAM_ICP, "Update ICP clk to level [%d]", + CAM_DBG(CAM_PERF, "Update ICP clk to level [%d]", clk_upd_cmd.clk_level); a5_dev_intf->hw_ops.process_cmd(a5_dev_intf->hw_priv, CAM_ICP_A5_CMD_CLK_UPDATE, &clk_upd_cmd.clk_level, @@ -1625,7 +1626,7 @@ static int cam_icp_mgr_ipe_bps_resume(struct cam_icp_hw_mgr *hw_mgr, core_info_mask = ICP_PWR_CLP_IPE0; } - CAM_DBG(CAM_ICP, "core_info %X", core_info_mask); + CAM_DBG(CAM_PERF, "core_info %X", core_info_mask); if (icp_hw_mgr.ipe_bps_pc_flag) rc = hfi_enable_ipe_bps_pc(true, core_info_mask); else @@ -1657,7 +1658,7 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, dev = ctx_data->icp_dev_acquire_info->dev_type; if (dev == CAM_ICP_RES_TYPE_BPS) { - CAM_DBG(CAM_ICP, "bps ctx cnt %d", hw_mgr->bps_ctxt_cnt); + CAM_DBG(CAM_PERF, "bps ctx cnt %d", hw_mgr->bps_ctxt_cnt); if (ctx_data) --hw_mgr->bps_ctxt_cnt; @@ -1678,7 +1679,7 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, hw_mgr->bps_clk_state = false; } } else { - CAM_DBG(CAM_ICP, "ipe ctx cnt %d", hw_mgr->ipe_ctxt_cnt); + CAM_DBG(CAM_PERF, "ipe ctx cnt %d", hw_mgr->ipe_ctxt_cnt); if (ctx_data) --hw_mgr->ipe_ctxt_cnt; @@ -2935,7 +2936,7 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) struct cam_hw_intf *a5_dev_intf = NULL; struct cam_hw_info *a5_dev = NULL; - CAM_DBG(CAM_ICP, "ENTER"); + CAM_DBG(CAM_PERF, "ENTER"); a5_dev_intf = hw_mgr->a5_dev_intf; if (!a5_dev_intf) { @@ -2955,7 +2956,7 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); } a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); - CAM_DBG(CAM_ICP, "EXIT"); + CAM_DBG(CAM_PERF, "EXIT"); return rc; } @@ -4168,7 +4169,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, switch (blob_type) { case CAM_ICP_CMD_GENERIC_BLOB_CLK: - CAM_WARN_RATE_LIMIT_CUSTOM(CAM_ICP, 300, 1, + CAM_WARN_RATE_LIMIT_CUSTOM(CAM_PERF, 300, 1, "Using deprecated blob type GENERIC_BLOB_CLK"); if (blob_size != sizeof(struct cam_icp_clk_bw_request)) { CAM_ERR(CAM_ICP, "Mismatch blob size %d expected %lu", @@ -4192,7 +4193,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, soc_req = (struct cam_icp_clk_bw_request *)blob_data; *clk_info = *soc_req; - CAM_DBG(CAM_ICP, "budget:%llu fc: %llu %d BW %lld %lld", + CAM_DBG(CAM_PERF, "budget:%llu fc: %llu %d BW %lld %lld", clk_info->budget_ns, clk_info->frame_cycles, clk_info->rt_flag, clk_info->uncompressed_bw, clk_info->compressed_bw); @@ -4219,7 +4220,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, soc_req_v2 = (struct cam_icp_clk_bw_request_v2 *)blob_data; if (soc_req_v2->num_paths > CAM_ICP_MAX_PER_PATH_VOTES) { - CAM_ERR(CAM_ICP, "Invalid num paths: %d", + CAM_ERR(CAM_PERF, "Invalid num paths: %d", soc_req_v2->num_paths); return -EINVAL; } @@ -4258,7 +4259,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, clk_info->frame_cycles = clk_info_v2->frame_cycles; clk_info->rt_flag = clk_info_v2->rt_flag; - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "budget=%llu, frame_cycle=%llu, rt_flag=%d, num_paths=%d, clk_update_size=%d, index=%d, ctx_data=%pK", clk_info_v2->budget_ns, clk_info_v2->frame_cycles, clk_info_v2->rt_flag, @@ -4268,7 +4269,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, ctx_data); for (i = 0; i < clk_info_v2->num_paths; i++) { - CAM_DBG(CAM_ICP, + CAM_DBG(CAM_PERF, "[%d] : path_type=%d, trans_type=%d, camnoc=%lld, mnoc_ab=%lld, mnoc_ib=%lld", i, clk_info_v2->axi_path[i].path_data_type, diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index a0de07833b72..4263cf7ea669 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -39,7 +39,7 @@ static int cam_ipe_cpas_vote(struct cam_ipe_device_core_info *core_info, &cpas_vote->axi_vote); if (rc) - CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc); + CAM_ERR(CAM_PERF, "cpas vote is failed: %d", rc); return rc; } @@ -168,7 +168,7 @@ static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev) hw_info->pwr_ctrl, true, 0x1); if (pwr_status >> IPE_PWR_ON_MASK) - CAM_WARN(CAM_ICP, "BPS: pwr_status(%x):pwr_ctrl(%x)", + CAM_WARN(CAM_PERF, "BPS: pwr_status(%x):pwr_ctrl(%x)", pwr_status, pwr_ctrl); } @@ -179,7 +179,7 @@ static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev) cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status); - CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", pwr_ctrl, pwr_status); return 0; @@ -202,7 +202,7 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); if (pwr_ctrl & IPE_COLLAPSE_MASK) { - CAM_DBG(CAM_ICP, "IPE pwr_ctrl set(%x)", pwr_ctrl); + CAM_DBG(CAM_PERF, "IPE pwr_ctrl set(%x)", pwr_ctrl); cam_cpas_reg_write(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, 0); @@ -214,7 +214,7 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status); - CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x", + CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", pwr_ctrl, pwr_status); return rc; @@ -364,7 +364,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; - CAM_DBG(CAM_ICP, "ipe_src_clk rate = %d", (int)clk_rate); + CAM_DBG(CAM_PERF, "ipe_src_clk rate = %d", (int)clk_rate); if (!core_info->clk_enable) { if (clk_upd_cmd->ipe_bps_pc_enable) { cam_ipe_handle_pc(ipe_dev); @@ -383,11 +383,11 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, CAM_ERR(CAM_ICP, "bps resume failed"); } } - CAM_DBG(CAM_ICP, "clock rate %d", clk_rate); + CAM_DBG(CAM_PERF, "clock rate %d", clk_rate); rc = cam_ipe_update_clk_rate(soc_info, clk_rate); if (rc) - CAM_ERR(CAM_ICP, "Failed to update clk"); + CAM_ERR(CAM_PERF, "Failed to update clk %d", clk_rate); err = cam_soc_util_get_clk_level(soc_info, clk_rate, soc_info->src_clk_idx, diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c index a33c7b68bf97..11cc7f7a3317 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c @@ -143,7 +143,7 @@ int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) && (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { - CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d", + CAM_DBG(CAM_PERF, "clk_rate %d greater than max, reset to %d", clk_rate, soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 05b41a7d8def..f9e6e71550cd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3239,7 +3239,7 @@ static int cam_isp_blob_bw_update_v2( sizeof( struct cam_vfe_bw_update_args_v2)); if (rc) - CAM_ERR(CAM_ISP, + CAM_ERR(CAM_PERF, "BW Update failed rc: %d", rc); } else { CAM_WARN(CAM_ISP, "NULL hw_intf!"); @@ -3338,7 +3338,7 @@ static int cam_isp_blob_bw_update( &bw_upd_args, sizeof(struct cam_vfe_bw_update_args)); if (rc) - CAM_ERR(CAM_ISP, "BW Update failed"); + CAM_ERR(CAM_PERF, "BW Update failed"); } else CAM_WARN(CAM_ISP, "NULL hw_intf!"); } @@ -3387,7 +3387,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { - CAM_DBG(CAM_ISP, "idx=%d, bw_config_version=%d", + CAM_DBG(CAM_PERF, "idx=%d, bw_config_version=%d", ctx, ctx->ctx_index, i, hw_update_data->bw_config_version); @@ -3397,7 +3397,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, (struct cam_isp_bw_config *) &hw_update_data->bw_config[i], ctx); if (rc) - CAM_ERR(CAM_ISP, + CAM_ERR(CAM_PERF, "Bandwidth Update Failed rc: %d", rc); } else if (hw_update_data->bw_config_version == CAM_ISP_BW_CONFIG_V2) { @@ -3405,11 +3405,11 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, (struct cam_isp_bw_config_v2 *) &hw_update_data->bw_config_v2[i], ctx); if (rc) - CAM_ERR(CAM_ISP, + CAM_ERR(CAM_PERF, "Bandwidth Update Failed rc: %d", rc); } else { - CAM_ERR(CAM_ISP, + CAM_ERR(CAM_PERF, "Invalid bw config version: %d", hw_update_data->bw_config_version); } @@ -4876,7 +4876,7 @@ static int cam_isp_blob_clock_update( if (hw_intf && hw_intf->hw_ops.process_cmd) { clock_upd_args.node_res = hw_mgr_res->hw_res[i]; - CAM_DBG(CAM_ISP, + CAM_DBG(CAM_PERF, "res_id=%u i= %d clk=%llu\n", hw_mgr_res->res_id, i, clk_rate); @@ -4889,7 +4889,8 @@ static int cam_isp_blob_clock_update( sizeof( struct cam_vfe_clock_update_args)); if (rc) - CAM_ERR(CAM_ISP, "Clock Update failed"); + CAM_ERR(CAM_PERF, + "Clock Update failed"); } else CAM_WARN(CAM_ISP, "NULL hw_intf!"); } @@ -5115,14 +5116,14 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, rc = cam_isp_blob_clock_update(blob_type, blob_info, clock_config, prepare); if (rc) - CAM_ERR(CAM_ISP, "Clock Update Failed"); + CAM_ERR(CAM_PERF, "Clock Update Failed, rc=%d", rc); } break; case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: { struct cam_isp_bw_config *bw_config; struct cam_isp_prepare_hw_update_data *prepare_hw_data; - CAM_WARN_RATE_LIMIT_CUSTOM(CAM_ISP, 300, 1, + CAM_WARN_RATE_LIMIT_CUSTOM(CAM_PERF, 300, 1, "Deprecated Blob TYPE_BW_CONFIG"); if (blob_size < sizeof(struct cam_isp_bw_config)) { CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); From 2a7ffe96970fc0a5fa09934fb7b7c05b015e230d Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Wed, 30 Oct 2019 17:54:18 -0700 Subject: [PATCH 145/790] msm: camera: sync: Dump fence info in case of fence exhaust Add error message in case of fence exhaust. Add support to dump fence table in case of fence exhaust. CRs-Fixed: 2556458 Change-Id: I9910a04c69b54fe99541524b6581fa9994fd523f Signed-off-by: Karthik Jayakumar --- drivers/cam_sync/cam_sync.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 10ed0cdecebf..0fdc082790a0 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -25,6 +25,24 @@ struct sync_device *sync_dev; */ static bool trigger_cb_without_switch; +static void cam_sync_print_fence_table(void) +{ + int idx; + + for (idx = 0; idx < CAM_SYNC_MAX_OBJS; idx++) { + spin_lock_bh(&sync_dev->row_spinlocks[idx]); + CAM_INFO(CAM_SYNC, + "index[%u]: sync_id=%d, name=%s, type=%d, state=%d, ref_cnt=%d", + idx, + sync_dev->sync_table[idx].sync_id, + sync_dev->sync_table[idx].name, + sync_dev->sync_table[idx].type, + sync_dev->sync_table[idx].state, + sync_dev->sync_table[idx].ref_cnt); + spin_unlock_bh(&sync_dev->row_spinlocks[idx]); + } +} + int cam_sync_create(int32_t *sync_obj, const char *name) { int rc; @@ -33,8 +51,13 @@ int cam_sync_create(int32_t *sync_obj, const char *name) do { idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS); - if (idx >= CAM_SYNC_MAX_OBJS) + if (idx >= CAM_SYNC_MAX_OBJS) { + CAM_ERR(CAM_SYNC, + "Error: Unable to create sync idx = %d reached max!", + idx); + cam_sync_print_fence_table(); return -ENOMEM; + } CAM_DBG(CAM_SYNC, "Index location available at idx: %ld", idx); bit = test_and_set_bit(idx, sync_dev->bitmap); } while (bit); From 632c43cf64bed71de15e76fd29b74220690a62ee Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 31 Oct 2019 14:49:12 -0700 Subject: [PATCH 146/790] msm: camera: icp: Remove qcom soc dependency Remove soc_info from icp driver as it was unused. CRs-Fixed: 2557184 Change-Id: I7b85768502f825753ea4b9650b5c3f9df67643fb Signed-off-by: Karthik Jayakumar --- drivers/cam_icp/hfi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 783b5c3723be..b5d340cb424a 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "cam_io_util.h" #include "hfi_reg.h" @@ -20,7 +19,6 @@ #include "hfi_intf.h" #include "cam_icp_hw_mgr_intf.h" #include "cam_debug_util.h" -#include "cam_soc_util.h" #define HFI_VERSION_INFO_MAJOR_VAL 1 #define HFI_VERSION_INFO_MINOR_VAL 1 @@ -681,7 +679,7 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; - uint32_t hw_version, soc_version, fw_version, status = 0; + uint32_t hw_version, fw_version, status = 0; uint32_t retry_cnt = 0; struct sfr_buf *sfr_buffer; @@ -703,7 +701,6 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map)); g_hfi->hfi_state = HFI_DEINIT; - soc_version = socinfo_get_version(); if (debug) { cam_io_w_mb( (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN | From 8d6ec3bf3ced8f0603de9786cbae818e96099a5e Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Fri, 1 Nov 2019 14:01:40 -0700 Subject: [PATCH 147/790] msm: camera: uapi: Add camera subfolder Added a camera subfolder for the UAPI headers to be located in. This prevents the camera UAPI headers from overwriting upstream kernel headers. CRs-Fixed: 2554484 Change-Id: Ie1edbfe585bbd428a6e5d1a40b438d22bd7c06c0 Signed-off-by: Karthik Jayakumar --- include/Kbuild | 2 -- include/uapi/Kbuild | 3 --- include/uapi/{ => camera}/media/cam_cpas.h | 0 include/uapi/{ => camera}/media/cam_custom.h | 0 include/uapi/{ => camera}/media/cam_defs.h | 0 include/uapi/{ => camera}/media/cam_fd.h | 0 include/uapi/{ => camera}/media/cam_icp.h | 0 include/uapi/{ => camera}/media/cam_isp.h | 0 include/uapi/{ => camera}/media/cam_isp_ife.h | 0 include/uapi/{ => camera}/media/cam_isp_vfe.h | 0 include/uapi/{ => camera}/media/cam_jpeg.h | 0 include/uapi/{ => camera}/media/cam_lrme.h | 0 include/uapi/{ => camera}/media/cam_req_mgr.h | 0 include/uapi/{ => camera}/media/cam_sensor.h | 0 include/uapi/{ => camera}/media/cam_sync.h | 0 include/uapi/media/Kbuild | 14 -------------- 16 files changed, 19 deletions(-) delete mode 100644 include/Kbuild delete mode 100644 include/uapi/Kbuild rename include/uapi/{ => camera}/media/cam_cpas.h (100%) rename include/uapi/{ => camera}/media/cam_custom.h (100%) rename include/uapi/{ => camera}/media/cam_defs.h (100%) rename include/uapi/{ => camera}/media/cam_fd.h (100%) rename include/uapi/{ => camera}/media/cam_icp.h (100%) rename include/uapi/{ => camera}/media/cam_isp.h (100%) rename include/uapi/{ => camera}/media/cam_isp_ife.h (100%) rename include/uapi/{ => camera}/media/cam_isp_vfe.h (100%) rename include/uapi/{ => camera}/media/cam_jpeg.h (100%) rename include/uapi/{ => camera}/media/cam_lrme.h (100%) rename include/uapi/{ => camera}/media/cam_req_mgr.h (100%) rename include/uapi/{ => camera}/media/cam_sensor.h (100%) rename include/uapi/{ => camera}/media/cam_sync.h (100%) delete mode 100644 include/uapi/media/Kbuild diff --git a/include/Kbuild b/include/Kbuild deleted file mode 100644 index bab1145bc7a7..000000000000 --- a/include/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# Top-level Makefile calls into asm-$(ARCH) -# List only non-arch directories below diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild deleted file mode 100644 index 93dffc4bac8d..000000000000 --- a/include/uapi/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note - -header-y += media/ diff --git a/include/uapi/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h similarity index 100% rename from include/uapi/media/cam_cpas.h rename to include/uapi/camera/media/cam_cpas.h diff --git a/include/uapi/media/cam_custom.h b/include/uapi/camera/media/cam_custom.h similarity index 100% rename from include/uapi/media/cam_custom.h rename to include/uapi/camera/media/cam_custom.h diff --git a/include/uapi/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h similarity index 100% rename from include/uapi/media/cam_defs.h rename to include/uapi/camera/media/cam_defs.h diff --git a/include/uapi/media/cam_fd.h b/include/uapi/camera/media/cam_fd.h similarity index 100% rename from include/uapi/media/cam_fd.h rename to include/uapi/camera/media/cam_fd.h diff --git a/include/uapi/media/cam_icp.h b/include/uapi/camera/media/cam_icp.h similarity index 100% rename from include/uapi/media/cam_icp.h rename to include/uapi/camera/media/cam_icp.h diff --git a/include/uapi/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h similarity index 100% rename from include/uapi/media/cam_isp.h rename to include/uapi/camera/media/cam_isp.h diff --git a/include/uapi/media/cam_isp_ife.h b/include/uapi/camera/media/cam_isp_ife.h similarity index 100% rename from include/uapi/media/cam_isp_ife.h rename to include/uapi/camera/media/cam_isp_ife.h diff --git a/include/uapi/media/cam_isp_vfe.h b/include/uapi/camera/media/cam_isp_vfe.h similarity index 100% rename from include/uapi/media/cam_isp_vfe.h rename to include/uapi/camera/media/cam_isp_vfe.h diff --git a/include/uapi/media/cam_jpeg.h b/include/uapi/camera/media/cam_jpeg.h similarity index 100% rename from include/uapi/media/cam_jpeg.h rename to include/uapi/camera/media/cam_jpeg.h diff --git a/include/uapi/media/cam_lrme.h b/include/uapi/camera/media/cam_lrme.h similarity index 100% rename from include/uapi/media/cam_lrme.h rename to include/uapi/camera/media/cam_lrme.h diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h similarity index 100% rename from include/uapi/media/cam_req_mgr.h rename to include/uapi/camera/media/cam_req_mgr.h diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h similarity index 100% rename from include/uapi/media/cam_sensor.h rename to include/uapi/camera/media/cam_sensor.h diff --git a/include/uapi/media/cam_sync.h b/include/uapi/camera/media/cam_sync.h similarity index 100% rename from include/uapi/media/cam_sync.h rename to include/uapi/camera/media/cam_sync.h diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild deleted file mode 100644 index e7971dac1051..000000000000 --- a/include/uapi/media/Kbuild +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note - -header-y += cam_cpas.h -header-y += cam_defs.h -header-y += cam_fd.h -header-y += cam_icp.h -header-y += cam_isp.h -header-y += cam_isp_vfe.h -header-y += cam_isp_ife.h -header-y += cam_jpeg.h -header-y += cam_req_mgr.h -header-y += cam_sensor.h -header-y += cam_sync.h -header-y += cam_lrme.h From 15feb22bdd685e1f0b09b0cb14e3021cc7b19dbb Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Fri, 1 Nov 2019 14:59:32 -0700 Subject: [PATCH 148/790] msm: camera: core: Fix extraneous variable declaration Remove an extra variable declaration within a for loop. CRs-Fixed: 2554484 Change-Id: I89885eeb8f89893ad7054d54a694a040e4c0bfbb Signed-off-by: Karthik Jayakumar --- drivers/cam_core/cam_context_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 5ec9c6cdc7b1..dd5bcd455030 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -481,7 +481,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, return rc; put_ctx_ref: - for (j; j >= 0; j--) + for (; j >= 0; j--) cam_context_putref(ctx); put_ref: for (--i; i >= 0; i--) { From 93a5aef8185f86edec60390b1a19ae4ce56bef8d Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 5 Sep 2019 23:45:51 -0700 Subject: [PATCH 149/790] msm: camera: csiphy: Correct Dphy mission mode sequence DPHY mission mode sequence is not full functional for mission mode. Correct and add mandate register settings for the bringup of DPHY mission mode. CRs-Fixed: 2545921 Change-Id: Ia1bbf496c5aa993cf0e404c81f7b69b7b889c6f1 Signed-off-by: Jigarkumar Zala --- .../include/cam_csiphy_1_2_1_hwreg.h | 142 ++++++++---------- 1 file changed, 66 insertions(+), 76 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 4f9fd086a97d..c78af37b579e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -14,7 +14,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .mipi_csiphy_glbl_irq_cmd_addr = 0x828, .csiphy_common_array_size = 6, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 21, + .csiphy_2ph_config_array_size = 19, .csiphy_3ph_config_array_size = 34, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -55,118 +55,108 @@ struct csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0908, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A08, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; From 335b376e21f10f31662533afb6c8f22197ec517c Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 10 Oct 2019 17:22:23 -0700 Subject: [PATCH 150/790] msm: camera: csiphy: Update DPHY combo mode sequence DPHY combo mode bring up sequence is missing with some important register settings. Correct and update required register setting to bringup DPHY combo mode. CRs-Fixed: 2545921 Change-Id: I1dfb71f1775aa6d6b1173a7de7f14ce74eac08e1 Signed-off-by: Jigarkumar Zala --- .../include/cam_csiphy_1_2_1_hwreg.h | 144 +++++++++--------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index c78af37b579e..32fbf47eabd9 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -14,7 +14,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .mipi_csiphy_glbl_irq_cmd_addr = 0x828, .csiphy_common_array_size = 6, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 19, + .csiphy_2ph_config_array_size = 20, .csiphy_3ph_config_array_size = 34, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -71,6 +71,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -92,6 +93,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -113,6 +115,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -134,6 +137,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -155,6 +159,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -164,118 +169,113 @@ struct csiphy_reg_t csiphy_2ph_v1_2_1_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0908, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x070c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C08, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x060c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; From c1054611fda69d1131c51a661a0a3d27b2a62aec Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 4 Nov 2019 13:50:06 -0800 Subject: [PATCH 151/790] msm: camera: utils: Remove deprecated clk_set_flag functions Removed unused functions that called clk_set_flag, which has been deprecated in linux kernel 5.x. CRs-Fixed: 2554484 Change-Id: I0062383b0b059e6b359229f4b33470713289abb4 Signed-off-by: Karthik Jayakumar --- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c | 39 ------------------- drivers/cam_utils/cam_soc_util.c | 12 ------ drivers/cam_utils/cam_soc_util.h | 14 ------- 3 files changed, 65 deletions(-) diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c index d05530ae4e17..c3d5a68c6910 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c @@ -71,39 +71,6 @@ static int cam_fd_hw_soc_util_setup_regbase_indices( return 0; } -static int cam_fd_soc_set_clk_flags(struct cam_hw_soc_info *soc_info) -{ - int i, rc = 0; - - if (soc_info->num_clk > CAM_SOC_MAX_CLK) { - CAM_ERR(CAM_FD, "Invalid num clk %d", soc_info->num_clk); - return -EINVAL; - } - - /* set memcore and mem periphery logic flags to 0 */ - for (i = 0; i < soc_info->num_clk; i++) { - if ((strcmp(soc_info->clk_name[i], "fd_core_clk") == 0) || - (strcmp(soc_info->clk_name[i], "fd_core_uar_clk") == - 0)) { - rc = cam_soc_util_set_clk_flags(soc_info, i, - CLKFLAG_NORETAIN_MEM); - if (rc) - CAM_ERR(CAM_FD, - "Failed in NORETAIN_MEM i=%d, rc=%d", - i, rc); - - cam_soc_util_set_clk_flags(soc_info, i, - CLKFLAG_NORETAIN_PERIPH); - if (rc) - CAM_ERR(CAM_FD, - "Failed in NORETAIN_PERIPH i=%d, rc=%d", - i, rc); - } - } - - return rc; -} - void cam_fd_soc_register_write(struct cam_hw_soc_info *soc_info, enum cam_fd_reg_base reg_base, uint32_t reg_offset, uint32_t reg_value) { @@ -228,12 +195,6 @@ int cam_fd_soc_init_resources(struct cam_hw_soc_info *soc_info, return rc; } - rc = cam_fd_soc_set_clk_flags(soc_info); - if (rc) { - CAM_ERR(CAM_FD, "failed in set_clk_flags rc=%d", rc); - goto release_res; - } - soc_private = kzalloc(sizeof(struct cam_fd_soc_private), GFP_KERNEL); if (!soc_private) { rc = -ENOMEM; diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 04f2f80b82ba..4e3dacaa822c 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -368,18 +368,6 @@ long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, return clk_round_rate(soc_info->clk[clk_index], clk_rate); } -int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info, - uint32_t clk_index, unsigned long flags) -{ - if (!soc_info || (clk_index >= soc_info->num_clk)) { - CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d", - soc_info, clk_index); - return -EINVAL; - } - - return clk_set_flags(soc_info->clk[clk_index], flags); -} - /** * cam_soc_util_set_clk_rate() * diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index ad2382b835ef..64320ca7b91d 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -371,20 +371,6 @@ int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_index, unsigned long clk_rate); -/** - * cam_soc_util_set_clk_flags() - * - * @brief: Camera SOC util to set the flags for a specified clock - * - * @soc_info: Device soc information - * @clk_index: Clock index in soc_info for which flags are to be set - * @flags: Flags to set - * - * @return: Success or Failure - */ -int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info, - uint32_t clk_index, unsigned long flags); - /** * cam_soc_util_set_src_clk_rate() * From b46dcb39c451184c177747bfcc41744b04a9039e Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 4 Nov 2019 11:38:29 -0800 Subject: [PATCH 152/790] msm: camera: cci: Fix cam_cci_get_subdev for conditional compilation Fixes cci_get_subdev to return NULL or computed value depending on camera driver configuration. CRs-Fixed: 2554484 Change-Id: I79933ddf28e2c0d23739308b57b5b40d3b56d78e Signed-off-by: Karthik Jayakumar --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 11 +++++++++-- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 9 +-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index e30574da5c0b..4c2d7af6ca96 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -14,9 +14,16 @@ static struct v4l2_subdev *g_cci_subdev[MAX_CCI]; struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) { + struct v4l2_subdev *sub_device = NULL; + if (cci_dev_index < MAX_CCI) - return g_cci_subdev[cci_dev_index]; - return NULL; + sub_device = g_cci_subdev[cci_dev_index]; + else + CAM_WARN(CAM_CCI, "Index: %u is beyond max num CCI allowed: %u", + cci_dev_index, + MAX_CCI); + + return sub_device; } static long cam_cci_subdev_ioctl(struct v4l2_subdev *sd, diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 439e3058a70b..21e3e3c80ebe 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -298,14 +298,7 @@ struct cci_write_async { irqreturn_t cam_cci_irq(int irq_num, void *data); -#ifdef CONFIG_SPECTRA_CAMERA -extern struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index); -#else -static inline struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) -{ - return NULL; -} -#endif +struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index); #define VIDIOC_MSM_CCI_CFG \ _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl *) From e2085ffb7f216fb38c19c5d4da1cfd96ad41503f Mon Sep 17 00:00:00 2001 From: Mangalaram ARCHANA Date: Fri, 25 Oct 2019 11:55:18 +0530 Subject: [PATCH 153/790] msm: camera: cpas: Fix TCSR Register programming Fix TCSR Register programming to enable SAT. CRs-Fixed: 2553475 Change-Id: Iaeae7cd06dcbccaa8bf1f98657efff734d048b9f Signed-off-by: Mangalaram ARCHANA --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 0543397a8482..1f52e1993a5c 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -514,7 +514,7 @@ done: static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) { - int i; + int i, reg_val; struct cam_cpas_hw_errata_wa_list *errata_wa_list = camnoc_info->errata_wa_list; struct cam_cpas_hw_errata_wa *errata_wa = @@ -541,8 +541,9 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) } if (errata_wa->enable) { - scm_io_write(errata_wa->data.reg_info.offset, - errata_wa->data.reg_info.value); + reg_val = scm_io_read(errata_wa->data.reg_info.offset); + reg_val |= errata_wa->data.reg_info.value; + scm_io_write(errata_wa->data.reg_info.offset, reg_val); } return 0; From 17ea11cdec605a96a7e90a5e44f1c090e9d2d2ee Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 16 Oct 2019 13:36:57 -0700 Subject: [PATCH 154/790] msm: camera: reqmgr: Add provision to obtain exposure time Currently CRM watchdog timer expiry is fixed at 1 second. This will not hold good if the sensor exposure time is increased beyond 1 second. In such situations obtain the time from userspace, and modify the CRM watchdog timer accordingly. CRs-Fixed: 2530691 Change-Id: I6251bcb2b915a9e317caffd350220e249214c8b2 Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- include/uapi/media/cam_req_mgr.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index 36471a290ad3..59564609035a 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -183,6 +183,11 @@ struct cam_req_mgr_flush_info { * @bubble_enable: Input Param - Cam req mgr will do bubble recovery if this * flag is set. * @sync_mode: Type of Sync mode for this request + * @additional_timeout: Additional timeout value (in ms) associated with + * this request. This value needs to be 0 in cases where long exposure is + * not configured for the sensor.The max timeout that will be supported + * is 50000 ms + * @reserved: Reserved * @req_id: Input Param - Request Id from which all requests will be flushed */ struct cam_req_mgr_sched_request { @@ -190,6 +195,8 @@ struct cam_req_mgr_sched_request { int32_t link_hdl; int32_t bubble_enable; int32_t sync_mode; + int32_t additional_timeout; + int32_t reserved; int64_t req_id; }; @@ -406,11 +413,13 @@ struct cam_mem_cache_ops_cmd { * @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 + * @CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE: SOF freeze, 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 +#define CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE 4 /** * struct cam_req_mgr_error_msg From a6c3698b1f3e58adc36a77177de58882ba5870c9 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 18 Oct 2019 16:25:36 -0700 Subject: [PATCH 155/790] msm: camera: reqmgr: Add support to modify timer for long exposure In case of long exposure shots, watchdog timer needs to be modified according to the requested value to avoid trigger. Add support for modifying timer value and changing it back to normal. CRs-Fixed: 2530691 Change-Id: I97bdd92d2ed461066bbf746bc6293094a444f8a5 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_core.c | 96 ++++++++++++++++++++++++-- drivers/cam_req_mgr/cam_req_mgr_core.h | 22 +++--- 2 files changed, 104 insertions(+), 14 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 427bc87d672e..faa15479ecda 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -443,6 +443,7 @@ static void __cam_req_mgr_flush_req_slot( slot->req_id = -1; slot->skip_idx = 1; slot->recover = 0; + slot->additional_timeout = 0; slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; slot->status = CRM_SLOT_STATUS_NO_REQ; @@ -486,6 +487,7 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, slot->req_id = -1; slot->skip_idx = 0; slot->recover = 0; + slot->additional_timeout = 0; slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; slot->status = CRM_SLOT_STATUS_NO_REQ; @@ -499,6 +501,66 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, } } +/** + * __cam_req_mgr_validate_crm_wd_timer() + * + * @brief : Validate/modify the wd timer based on associated + * timeout with the request + * @link : link pointer + * + */ +static void __cam_req_mgr_validate_crm_wd_timer( + struct cam_req_mgr_core_link *link) +{ + int idx = 0; + int next_frame_timeout = 0, current_frame_timeout = 0; + struct cam_req_mgr_req_queue *in_q = link->req.in_q; + + idx = in_q->rd_idx; + __cam_req_mgr_dec_idx( + &idx, (link->max_delay - 1), + in_q->num_slots); + next_frame_timeout = in_q->slot[idx].additional_timeout; + CAM_DBG(CAM_CRM, + "rd_idx: %d idx: %d next_frame_timeout: %d ms", + in_q->rd_idx, idx, next_frame_timeout); + + idx = in_q->rd_idx; + __cam_req_mgr_dec_idx( + &idx, link->max_delay, + in_q->num_slots); + current_frame_timeout = in_q->slot[idx].additional_timeout; + CAM_DBG(CAM_CRM, + "rd_idx: %d idx: %d current_frame_timeout: %d ms", + in_q->rd_idx, idx, current_frame_timeout); + + if ((next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT) > + link->watchdog->expires) { + CAM_DBG(CAM_CRM, + "Modifying wd timer expiry from %d ms to %d ms", + link->watchdog->expires, + (next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); + crm_timer_modify(link->watchdog, + next_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } else if (current_frame_timeout) { + CAM_DBG(CAM_CRM, + "Reset wd timer to current frame from %d ms to %d ms", + link->watchdog->expires, + (current_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); + crm_timer_modify(link->watchdog, + current_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } else if (link->watchdog->expires > + CAM_REQ_MGR_WATCHDOG_TIMEOUT) { + CAM_DBG(CAM_CRM, + "Reset wd timer to default from %d ms to %d ms", + link->watchdog->expires, CAM_REQ_MGR_WATCHDOG_TIMEOUT); + crm_timer_modify(link->watchdog, + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } +} + /** * __cam_req_mgr_check_for_lower_pd_devices() * @@ -1275,9 +1337,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, * - if in applied_state, somthign wrong. * - if in no_req state, no new req */ - CAM_DBG(CAM_REQ, "SOF Req[%lld] idx %d req_status %d link_hdl %x", + CAM_DBG(CAM_REQ, + "SOF Req[%lld] idx %d req_status %d link_hdl %x wd_timeout %d ms", in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx, - in_q->slot[in_q->rd_idx].status, link->link_hdl); + in_q->slot[in_q->rd_idx].status, link->link_hdl, + in_q->slot[in_q->rd_idx].additional_timeout); slot = &in_q->slot[in_q->rd_idx]; if (slot->status == CRM_SLOT_STATUS_NO_REQ) { @@ -1393,6 +1457,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->trigger_mask |= trigger; + /* Check for any long exposure settings */ + __cam_req_mgr_validate_crm_wd_timer(link); + CAM_DBG(CAM_CRM, "Applied req[%lld] on link[%x] success", slot->req_id, link->link_hdl); spin_lock_bh(&link->link_state_spin_lock); @@ -1641,7 +1708,7 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) memset(&msg, 0, sizeof(msg)); msg.session_hdl = session->session_hdl; - msg.u.err_msg.error_type = CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + msg.u.err_msg.error_type = CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE; msg.u.err_msg.request_id = 0; msg.u.err_msg.link_hdl = link->link_hdl; @@ -2030,6 +2097,7 @@ int cam_req_mgr_process_flush_req(void *priv, void *data) mutex_unlock(&link->req.lock); return -EINVAL; } + slot->additional_timeout = 0; __cam_req_mgr_in_q_skip_idx(in_q, idx); } } @@ -2081,10 +2149,11 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) in_q = link->req.in_q; CAM_DBG(CAM_CRM, - "link_hdl %x req_id %lld at slot %d sync_mode %d is_master:%d", + "link_hdl %x req_id %lld at slot %d sync_mode %d is_master %d exp_timeout_val %d ms", sched_req->link_hdl, sched_req->req_id, in_q->wr_idx, sched_req->sync_mode, - link->is_master); + link->is_master, + sched_req->additional_timeout); mutex_lock(&link->req.lock); slot = &in_q->slot[in_q->wr_idx]; @@ -2098,6 +2167,22 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) slot->sync_mode = sched_req->sync_mode; slot->skip_idx = 0; slot->recover = sched_req->bubble_enable; + if (sched_req->additional_timeout < 0) { + CAM_WARN(CAM_CRM, + "Requested timeout is invalid [%dms]", + sched_req->additional_timeout); + slot->additional_timeout = 0; + } else if (sched_req->additional_timeout > + CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX) { + CAM_WARN(CAM_CRM, + "Requested timeout [%dms] max supported timeout [%dms] resetting to max", + sched_req->additional_timeout, + CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX); + slot->additional_timeout = CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX; + } else { + slot->additional_timeout = sched_req->additional_timeout; + } + link->open_req_cnt++; __cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots); @@ -3261,6 +3346,7 @@ int cam_req_mgr_schedule_request( sched->req_id = sched_req->req_id; sched->sync_mode = sched_req->sync_mode; sched->link_hdl = sched_req->link_hdl; + sched->additional_timeout = sched_req->additional_timeout; if (session->force_err_recovery == AUTO_RECOVERY) { sched->bubble_enable = sched_req->bubble_enable; } else { diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index c790ce824244..0afdc69b0445 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -13,9 +13,10 @@ #define CAM_REQ_MGR_MAX_LINKED_DEV 16 #define MAX_REQ_SLOTS 48 -#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 -#define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 -#define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 1000 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX 50000 +#define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 +#define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 #define FORCE_DISABLE_RECOVERY 2 #define FORCE_ENABLE_RECOVERY 1 @@ -226,13 +227,15 @@ struct cam_req_mgr_req_tbl { /** * struct cam_req_mgr_slot * - Internal Book keeping - * @idx : slot index - * @skip_idx : if req id in this slot needs to be skipped/not applied - * @status : state machine for life cycle of a slot + * @idx : slot index + * @skip_idx : if req id in this slot needs to be skipped/not applied + * @status : state machine for life cycle of a slot * - members updated due to external events - * @recover : if user enabled recovery for this request. - * @req_id : mask tracking which all devices have request ready - * @sync_mode : Sync mode in which req id in this slot has to applied + * @recover : if user enabled recovery for this request. + * @req_id : mask tracking which all devices have request ready + * @sync_mode : Sync mode in which req id in this slot has to applied + * @additional_timeout : Adjusted watchdog timeout value associated with + * this request */ struct cam_req_mgr_slot { int32_t idx; @@ -241,6 +244,7 @@ struct cam_req_mgr_slot { int32_t recover; int64_t req_id; int32_t sync_mode; + int32_t additional_timeout; }; /** From 524b1ab1d4d76c2ca3ae8dfe41b1a9966e1b21f3 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Tue, 5 Nov 2019 16:53:31 -0800 Subject: [PATCH 156/790] msm: camera: config: Makefile fixes to support legacy kernel build system Adds fixes to makefile in order to support legacy kernel build systems. CRs-Fixed: 2560543 Change-Id: Iab571871e5171aab501c41496cc09e3c5d942985 Signed-off-by: Karthik Jayakumar --- drivers/Makefile | 2 ++ drivers/cam_cdm/Makefile | 1 - drivers/cam_core/Makefile | 1 - drivers/cam_cpas/Makefile | 3 --- drivers/cam_cpas/camss_top/Makefile | 1 - drivers/cam_cpas/cpas_top/Makefile | 1 - drivers/cam_cust/cam_custom_context.h | 5 +++-- drivers/cam_cust/cam_custom_dev.c | 3 ++- .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 4 +++- .../cam_custom_hw_mgr/cam_custom_hw_mgr.h | 5 +++-- .../cam_custom_hw_mgr/include/cam_custom_hw.h | 3 ++- .../include/cam_custom_hw_mgr_intf.h | 4 +++- drivers/cam_fd/Makefile | 1 - drivers/cam_fd/fd_hw_mgr/Makefile | 1 - drivers/cam_icp/Makefile | 2 -- drivers/cam_icp/icp_hw/Makefile | 1 - drivers/cam_isp/Makefile | 1 - drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 4 +++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 5 +++-- .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c | 4 +++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 4 +++- .../vfe_hw/vfe_bus/include/cam_vfe_bus.h | 3 ++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c | 4 +++- drivers/cam_jpeg/Makefile | 1 - drivers/cam_lrme/Makefile | 1 - drivers/cam_lrme/lrme_hw_mgr/Makefile | 1 - drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile | 1 - drivers/cam_req_mgr/Makefile | 1 - .../cam_sensor_module/cam_actuator/Makefile | 1 - drivers/cam_sensor_module/cam_cci/Makefile | 1 - drivers/cam_sensor_module/cam_csiphy/Makefile | 1 - drivers/cam_sensor_module/cam_eeprom/Makefile | 1 - drivers/cam_sensor_module/cam_flash/Makefile | 2 -- drivers/cam_sensor_module/cam_ois/Makefile | 1 - drivers/cam_sensor_module/cam_res_mgr/Makefile | 1 - drivers/cam_sensor_module/cam_sensor/Makefile | 1 - .../cam_sensor_module/cam_sensor_io/Makefile | 1 - .../cam_sensor_utils/Makefile | 1 - drivers/cam_smmu/Makefile | 1 - drivers/cam_sync/Makefile | 1 - drivers/cam_utils/Makefile | 1 - drivers/cam_utils/cam_soc_util.h | 2 +- include/uapi/Kbuild | 18 ++++++++++++++++++ 43 files changed, 54 insertions(+), 48 deletions(-) create mode 100644 include/uapi/Kbuild diff --git a/drivers/Makefile b/drivers/Makefile index 13edfb587419..84beb97a75e9 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,3 +1,5 @@ +subdir-ccflags-y += -I$(srctree)/techpack/camera/include/uapi/camera + obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_utils/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_core/ diff --git a/drivers/cam_cdm/Makefile b/drivers/cam_cdm/Makefile index 323a523011a2..9ba81e385ab3 100644 --- a/drivers/cam_cdm/Makefile +++ b/drivers/cam_cdm/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_core/Makefile b/drivers/cam_core/Makefile index e117039fc3ab..d8dd1a48948f 100644 --- a/drivers/cam_core/Makefile +++ b/drivers/cam_core/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync diff --git a/drivers/cam_cpas/Makefile b/drivers/cam_cpas/Makefile index 6fc8f9830cec..947fbbf7d91e 100644 --- a/drivers/cam_cpas/Makefile +++ b/drivers/cam_cpas/Makefile @@ -1,11 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -#ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/cpas_top -#ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/camss_top ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree) diff --git a/drivers/cam_cpas/camss_top/Makefile b/drivers/cam_cpas/camss_top/Makefile index de11b7136563..8fc199fcf9eb 100644 --- a/drivers/cam_cpas/camss_top/Makefile +++ b/drivers/cam_cpas/camss_top/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_cpas/cpas_top/Makefile b/drivers/cam_cpas/cpas_top/Makefile index 0306b14ef14a..cbd65d8fdde8 100644 --- a/drivers/cam_cpas/cpas_top/Makefile +++ b/drivers/cam_cpas/cpas_top/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index 91acf1e5ee80..1c4b70abf3fd 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -7,8 +7,9 @@ #define _CAM_CUSTOM_CONTEXT_H_ #include -#include -#include + +#include +#include #include "cam_context.h" #include "cam_custom_hw_mgr_intf.h" diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index 76d4a7d0e17b..da95f36b9d7e 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -12,7 +12,8 @@ #include #include -#include +#include + #include "cam_custom_dev.h" #include "cam_hw_mgr_intf.h" #include "cam_custom_hw_mgr_intf.h" diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index 1db06bb3ab1f..694ac1bee2c0 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -7,9 +7,11 @@ #include #include #include + #include -#include +#include #include + #include "cam_sync_api.h" #include "cam_smmu_api.h" #include "cam_req_mgr_workq.h" diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h index 64f4555528bf..4a9b27be7467 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h @@ -12,8 +12,9 @@ #include "cam_ife_csid_hw_intf.h" #include "cam_isp_hw.h" #include "cam_custom_hw.h" -#include -#include + +#include +#include enum cam_custom_hw_mgr_res_type { CAM_CUSTOM_HW_SUB_MODULE, diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h index 0fd557c14052..c1d6a258cc55 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h @@ -9,7 +9,8 @@ #include #include #include -#include + +#include enum cam_custom_hw_resource_state { CAM_CUSTOM_HW_RESOURCE_STATE_UNAVAILABLE = 0, diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h index b1fb1cb42913..85492be28193 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -9,7 +9,9 @@ #include #include #include -#include + +#include + #include "cam_hw.h" #include "cam_hw_mgr_intf.h" #include "cam_hw_intf.h" diff --git a/drivers/cam_fd/Makefile b/drivers/cam_fd/Makefile index 92356a35d8c8..e74167e0611f 100644 --- a/drivers/cam_fd/Makefile +++ b/drivers/cam_fd/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_fd/fd_hw_mgr/Makefile b/drivers/cam_fd/fd_hw_mgr/Makefile index 8db8097679b5..7857618bd5f5 100644 --- a/drivers/cam_fd/fd_hw_mgr/Makefile +++ b/drivers/cam_fd/fd_hw_mgr/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_icp/Makefile b/drivers/cam_icp/Makefile index aec65fc06f4b..98a9ed931e72 100644 --- a/drivers/cam_icp/Makefile +++ b/drivers/cam_icp/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core @@ -9,7 +8,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc -ccflags-y += -I$(srctree)/techpack/camera ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ diff --git a/drivers/cam_icp/icp_hw/Makefile b/drivers/cam_icp/icp_hw/Makefile index 68b36f706604..5b61366cc5f5 100644 --- a/drivers/cam_icp/icp_hw/Makefile +++ b/drivers/cam_icp/icp_hw/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_isp/Makefile b/drivers/cam_isp/Makefile index 86ad96d61cb7..6459d449305c 100644 --- a/drivers/cam_isp/Makefile +++ b/drivers/cam_isp/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 3c82c6b2f8e5..b49b04a49e7b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7,8 +7,10 @@ #include #include #include + #include -#include +#include + #include "cam_smmu_api.h" #include "cam_req_mgr_workq.h" #include "cam_isp_hw_mgr_intf.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index af9f67286d82..b87f79f70881 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -5,8 +5,9 @@ #include #include -#include -#include + +#include +#include #include diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c index 314ebff70fc0..28e4218a7bd3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c @@ -5,7 +5,9 @@ #include #include -#include + +#include + #include "cam_io_util.h" #include "cam_debug_util.h" #include "cam_cdm_util.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index cae125315895..2351afcbf1dc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -6,7 +6,9 @@ #include #include -#include + +#include + #include "cam_io_util.h" #include "cam_debug_util.h" #include "cam_cdm_util.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h index 97336a2da3b8..2548c36016d1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h @@ -6,7 +6,8 @@ #ifndef _CAM_VFE_BUS_H_ #define _CAM_VFE_BUS_H_ -#include +#include + #include "cam_hw_intf.h" #include "cam_isp_hw.h" diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c index 98c84ad77d93..7815da674872 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c @@ -4,7 +4,9 @@ */ #include -#include + +#include + #include "cam_io_util.h" #include "cam_isp_hw_mgr_intf.h" #include "cam_isp_hw.h" diff --git a/drivers/cam_jpeg/Makefile b/drivers/cam_jpeg/Makefile index 471f870e4c73..03a132a8f8e6 100644 --- a/drivers/cam_jpeg/Makefile +++ b/drivers/cam_jpeg/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync diff --git a/drivers/cam_lrme/Makefile b/drivers/cam_lrme/Makefile index 72cdba4da04c..6aa9701dbd15 100644 --- a/drivers/cam_lrme/Makefile +++ b/drivers/cam_lrme/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync diff --git a/drivers/cam_lrme/lrme_hw_mgr/Makefile b/drivers/cam_lrme/lrme_hw_mgr/Makefile index 3387c3d0f062..37cd971bdccb 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/Makefile +++ b/drivers/cam_lrme/lrme_hw_mgr/Makefile @@ -9,7 +9,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw -ccflags-y += -I$(srctree)/techpack/camera ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw/ diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile index 8df30c0f44de..a1a15add9202 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile @@ -9,7 +9,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw -ccflags-y += -I$(srctree)/techpack/camera0 ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_dev.o cam_lrme_hw_core.o cam_lrme_hw_soc.o diff --git a/drivers/cam_req_mgr/Makefile b/drivers/cam_req_mgr/Makefile index 50599d879255..685688353468 100644 --- a/drivers/cam_req_mgr/Makefile +++ b/drivers/cam_req_mgr/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils diff --git a/drivers/cam_sensor_module/cam_actuator/Makefile b/drivers/cam_sensor_module/cam_actuator/Makefile index e61c6eeba3c0..480cea767710 100644 --- a/drivers/cam_sensor_module/cam_actuator/Makefile +++ b/drivers/cam_sensor_module/cam_actuator/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core diff --git a/drivers/cam_sensor_module/cam_cci/Makefile b/drivers/cam_sensor_module/cam_cci/Makefile index a1301bf41d5d..4a93880a7260 100644 --- a/drivers/cam_sensor_module/cam_cci/Makefile +++ b/drivers/cam_sensor_module/cam_cci/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include diff --git a/drivers/cam_sensor_module/cam_csiphy/Makefile b/drivers/cam_sensor_module/cam_csiphy/Makefile index d98b84574363..3cbc09d0b111 100644 --- a/drivers/cam_sensor_module/cam_csiphy/Makefile +++ b/drivers/cam_sensor_module/cam_csiphy/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_sensor_module/cam_eeprom/Makefile b/drivers/cam_sensor_module/cam_eeprom/Makefile index 7a676c1135a0..f978136982eb 100644 --- a/drivers/cam_sensor_module/cam_eeprom/Makefile +++ b/drivers/cam_sensor_module/cam_eeprom/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_sensor_module/cam_flash/Makefile b/drivers/cam_sensor_module/cam_flash/Makefile index da9e9e1b19cb..967d50dd25eb 100644 --- a/drivers/cam_sensor_module/cam_flash/Makefile +++ b/drivers/cam_sensor_module/cam_flash/Makefile @@ -1,7 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_sensor_module/cam_ois/Makefile b/drivers/cam_sensor_module/cam_ois/Makefile index fa7fabc0f055..8658af35e435 100644 --- a/drivers/cam_sensor_module/cam_ois/Makefile +++ b/drivers/cam_sensor_module/cam_ois/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_sensor_module/cam_res_mgr/Makefile b/drivers/cam_sensor_module/cam_res_mgr/Makefile index 1c8ccb0e3bf4..d0ba37e3763a 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/Makefile +++ b/drivers/cam_sensor_module/cam_res_mgr/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -#ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_sensor_module/cam_sensor/Makefile b/drivers/cam_sensor_module/cam_sensor/Makefile index d3a6fbb6c3e4..77ccd7fe2c97 100644 --- a/drivers/cam_sensor_module/cam_sensor/Makefile +++ b/drivers/cam_sensor_module/cam_sensor/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_sensor_module/cam_sensor_io/Makefile b/drivers/cam_sensor_module/cam_sensor_io/Makefile index 5b11171fa087..b41cd60c6cb8 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/Makefile +++ b/drivers/cam_sensor_module/cam_sensor_io/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils diff --git a/drivers/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/cam_sensor_module/cam_sensor_utils/Makefile index d822b2a733cf..8c76ba286ea2 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/Makefile +++ b/drivers/cam_sensor_module/cam_sensor_utils/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io diff --git a/drivers/cam_smmu/Makefile b/drivers/cam_smmu/Makefile index b674b48ceb2d..89b2c967ce79 100644 --- a/drivers/cam_smmu/Makefile +++ b/drivers/cam_smmu/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr diff --git a/drivers/cam_sync/Makefile b/drivers/cam_sync/Makefile index 40efdf4dd794..2f3247cb0894 100644 --- a/drivers/cam_sync/Makefile +++ b/drivers/cam_sync/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils ccflags-$(CONFIG_MSM_GLOBAL_SYNX) += -I$(srctree)/drivers/media/platform/msm/synx ccflags-y += -I$(src) diff --git a/drivers/cam_utils/Makefile b/drivers/cam_utils/Makefile index e17c2f50bb95..931478f0676e 100644 --- a/drivers/cam_utils/Makefile +++ b/drivers/cam_utils/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index ad2382b835ef..f31ee9f406ac 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -18,7 +18,7 @@ #include #include "cam_io_util.h" -#include +#include #define NO_SET_RATE -1 #define INIT_RATE -2 diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild new file mode 100644 index 000000000000..f84da02a5a82 --- /dev/null +++ b/include/uapi/Kbuild @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note + +# Legacy file used for kernel 4.19.x build system to install +# UAPI headers. + +header-y += camera/media/cam_cpas.h +header-y += camera/media/cam_custom.h +header-y += camera/media/cam_defs.h +header-y += camera/media/cam_fd.h +header-y += camera/media/cam_icp.h +header-y += camera/media/cam_isp_ife.h +header-y += camera/media/cam_isp_vfe.h +header-y += camera/media/cam_isp.h +header-y += camera/media/cam_jpeg.h +header-y += camera/media/cam_lrme.h +header-y += camera/media/cam_req_mgr.h +header-y += camera/media/cam_sensor.h +header-y += camera/media/cam_sync.h From fd1db0292d79364c7512cede28b8dd63b25cfe2e Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 24 Oct 2019 13:49:43 -0700 Subject: [PATCH 157/790] msm: camera: sensor: Remove true/false redefinitions Remove defines in header files that redefine true and false. CRs-Fixed: 2556282 Change-Id: Ibf87f35efd403faa05e72b070dcfca59e0196a29 Signed-off-by: Karthik Jayakumar --- .../cam_actuator/cam_actuator_dev.h | 4 ---- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 4 ++-- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 14 +++++++------- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 3 --- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 6 +++--- .../cam_sensor_module/cam_sensor/cam_sensor_dev.h | 3 --- 6 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h index e4e5e4305246..e4bfaed4414f 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -30,16 +30,12 @@ #define NUM_MASTERS 2 #define NUM_QUEUES 2 -#define TRUE 1 -#define FALSE 0 - #define ACTUATOR_DRIVER_I2C "i2c_actuator" #define CAMX_ACTUATOR_DEV_NAME "cam-actuator-driver" #define MSM_ACTUATOR_MAX_VREGS (10) #define ACTUATOR_MAX_POLL_COUNT 10 - enum cam_actuator_apply_state_t { ACT_APPLY_SETTINGS_NOW, ACT_APPLY_SETTINGS_LATER, diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 8701c6b9d62e..a0d1cbe058d9 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -49,8 +49,8 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev, } else if (rc == 0) { CAM_ERR(CAM_CCI, "wait timeout"); - /* Set reset pending flag to TRUE */ - cci_dev->cci_master_info[master].reset_pending = TRUE; + /* Set reset pending flag to true */ + cci_dev->cci_master_info[master].reset_pending = true; /* Set proper mask to RESET CMD address based on MASTER */ if (master == MASTER_0) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index e30574da5c0b..f377c07a6c36 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -69,18 +69,18 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { struct cam_cci_master_info *cci_master_info; - if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) { + if (cci_dev->cci_master_info[MASTER_0].reset_pending == true) { cci_master_info = &cci_dev->cci_master_info[MASTER_0]; cci_dev->cci_master_info[MASTER_0].reset_pending = - FALSE; + false; if (!cci_master_info->status) complete(&cci_master_info->reset_complete); cci_master_info->status = 0; } - if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) { + if (cci_dev->cci_master_info[MASTER_1].reset_pending == true) { cci_master_info = &cci_dev->cci_master_info[MASTER_1]; cci_dev->cci_master_info[MASTER_1].reset_pending = - FALSE; + false; if (!cci_master_info->status) complete(&cci_master_info->reset_complete); cci_master_info->status = 0; @@ -205,12 +205,12 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_DBG(CAM_CCI, "RD_PAUSE ON MASTER_1"); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) { - cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE; + cci_dev->cci_master_info[MASTER_0].reset_pending = true; cam_io_w_mb(CCI_M0_RESET_RMSK, base + CCI_RESET_CMD_ADDR); } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK_BMSK) { - cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE; + cci_dev->cci_master_info[MASTER_1].reset_pending = true; cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR); } @@ -316,7 +316,7 @@ static int cam_cci_irq_routine(struct v4l2_subdev *sd, u32 status, &cci_dev->soc_info; ret = cam_cci_irq(soc_info->irq_line->start, cci_dev); - *handled = TRUE; + *handled = true; return 0; } diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 439e3058a70b..56798feb5edf 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -42,9 +42,6 @@ #define NUM_MASTERS 2 #define NUM_QUEUES 2 -#define TRUE 1 -#define FALSE 0 - #define CCI_PINCTRL_STATE_DEFAULT "cci_default" #define CCI_PINCTRL_STATE_SLEEP "cci_suspend" diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 092f42bbe0d9..82f1c61cf8fe 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -52,8 +52,8 @@ int cam_cci_init(struct v4l2_subdev *sd, for (i = 0; i < NUM_QUEUES; i++) reinit_completion( &cci_dev->cci_master_info[master].report_q[i]); - /* Set reset pending flag to TRUE */ - cci_dev->cci_master_info[master].reset_pending = TRUE; + /* Set reset pending flag to true */ + cci_dev->cci_master_info[master].reset_pending = true; /* Set proper mask to RESET CMD address */ if (master == MASTER_0) cam_io_w_mb(CCI_M0_RESET_RMSK, @@ -131,7 +131,7 @@ int cam_cci_init(struct v4l2_subdev *sd, } } - cci_dev->cci_master_info[master].reset_pending = TRUE; + cci_dev->cci_master_info[master].reset_pending = true; cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h index 37e0affdf991..b1963e15eb59 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -28,9 +28,6 @@ #define NUM_MASTERS 2 #define NUM_QUEUES 2 -#define TRUE 1 -#define FALSE 0 - #undef CDBG #ifdef CAM_SENSOR_DEBUG #define CDBG(fmt, args...) pr_err(fmt, ##args) From 4e13a0294dc401f7c5caf7bf8527ac1f8f52dfc8 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 7 Nov 2019 19:34:58 -0800 Subject: [PATCH 158/790] msm: camera: cpas: Update ife_rd safe lut value Do not set safe_lut value for ife_rd path, default values is good as per recommendation. CRs-Fixed: 2561696 Change-Id: Icce19f7814329d2e96e94d18096aa12069626429 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h index 510b97062fbc..0d46e0ddcc20 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -357,7 +357,7 @@ static struct cam_camnoc_specific .value = 0x0, }, .safe_lut = { - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ .value = 0x0, From 69c67ebc90fbe9d712ac1bee8432f5b20175b6ac Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Thu, 31 Oct 2019 09:50:07 +0530 Subject: [PATCH 159/790] msm: camera: ife: calculate accurate boot timestamp at CSID SOF The boot timestamp is calculated in tasklet context. Due to system performance and scheduling delay, it may vary. It is somtimes causing failure for few time bound test cases. To handle above problem, This change also considers qtime difference to calculate accurate boot time at CSID each SOF. CRs-Fixed: 2557758 Change-Id: I36b21a0f2c12cc1c83c209ab01ea90c0ac226995 Signed-off-by: Alok Pandey --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 63 ++++++++++--------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 22 ++++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 ++ 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 41d02f06aaf0..998dfd743087 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5888,41 +5888,42 @@ static int cam_ife_mgr_cmd_get_sof_timestamp( struct cam_hw_intf *hw_intf; struct cam_csid_get_time_stamp_args csid_get_time; - 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]) - continue; + hw_mgr_res = list_first_entry(&ife_ctx->res_list_ife_csid, + struct cam_ife_hw_mgr_res, list); + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + 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) { /* - * 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 + * 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 */ - 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( - hw_intf->hw_priv, - CAM_IFE_CSID_CMD_GET_TIME_STAMP, - &csid_get_time, - sizeof( - struct cam_csid_get_time_stamp_args)); - if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { - *time_stamp = - csid_get_time.time_stamp_val; - *boot_time_stamp = - csid_get_time.boot_timestamp; - } + csid_get_time.node_res = + hw_mgr_res->hw_res[i]; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_CMD_GET_TIME_STAMP, + &csid_get_time, + sizeof( + struct cam_csid_get_time_stamp_args)); + if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { + *time_stamp = + csid_get_time.time_stamp_val; + *boot_time_stamp = + csid_get_time.boot_timestamp; } } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index af9f67286d82..f21c47e5f56d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -534,6 +534,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d", csid_hw->hw_intf->hw_idx, val); csid_hw->error_irq_count = 0; + csid_hw->prev_boot_timestamp = 0; return rc; } @@ -1329,6 +1330,7 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) 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; + csid_hw->prev_boot_timestamp = 0; return rc; } @@ -2928,6 +2930,7 @@ static int cam_ife_csid_get_time_stamp( const struct cam_ife_csid_udi_reg_offset *udi_reg; struct timespec64 ts; uint32_t time_32, id; + uint64_t time_delta; time_stamp = (struct cam_csid_get_time_stamp_args *)cmd_args; res = time_stamp->node_res; @@ -2999,9 +3002,22 @@ static int cam_ife_csid_get_time_stamp( CAM_IFE_CSID_QTIMER_MUL_FACTOR, CAM_IFE_CSID_QTIMER_DIV_FACTOR); - get_monotonic_boottime64(&ts); - time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) + - ts.tv_nsec); + if (!csid_hw->prev_boot_timestamp) { + get_monotonic_boottime64(&ts); + time_stamp->boot_timestamp = + (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + csid_hw->prev_qtimer_ts = 0; + CAM_DBG(CAM_ISP, "timestamp:%lld", + time_stamp->boot_timestamp); + } else { + time_delta = time_stamp->time_stamp_val - + csid_hw->prev_qtimer_ts; + time_stamp->boot_timestamp = + csid_hw->prev_boot_timestamp + time_delta; + } + csid_hw->prev_qtimer_ts = time_stamp->time_stamp_val; + csid_hw->prev_boot_timestamp = time_stamp->boot_timestamp; return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 7bfb0dac4231..863aec341899 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -550,6 +550,8 @@ struct cam_ife_csid_path_cfg { * @binning_enable Flag is set if hardware supports QCFA binning * @binning_supported Flag is set if sensor supports QCFA binning * + * @first_sof_ts first bootime stamp at the start + * @prev_qtimer_ts stores csid timestamp */ struct cam_ife_csid_hw { struct cam_hw_intf *hw_intf; @@ -581,6 +583,8 @@ struct cam_ife_csid_hw { spinlock_t lock_state; uint32_t binning_enable; uint32_t binning_supported; + uint64_t prev_boot_timestamp; + uint64_t prev_qtimer_ts; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, From fdd212fdf315445164ceaf3557adc41a41e75f0c Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 9 Sep 2019 22:48:13 -0700 Subject: [PATCH 160/790] msm: camera: common: Update uapi to support custom hw features This change provides provision to propagate frame id to userspace as part of shutter notification. The change also add new acquire params for IFE when custom HW is in the pipeline. CRs-Fixed: 2524308 Change-Id: Ia6f6efb1edc6e6a01d7b37aeb2787b1e98d8f81e Signed-off-by: Karthik Anantha Ram --- include/uapi/media/cam_isp.h | 5 +++++ include/uapi/media/cam_req_mgr.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h index 79314b59363f..e4778cfc9cc2 100644 --- a/include/uapi/media/cam_isp.h +++ b/include/uapi/media/cam_isp.h @@ -126,6 +126,11 @@ #define CAM_ISP_USAGE_RIGHT_PX 2 #define CAM_ISP_USAGE_RDI 3 +/* Acquire with custom hw */ +#define CAM_ISP_ACQ_CUSTOM_NONE 0 +#define CAM_ISP_ACQ_CUSTOM_PRIMARY 1 +#define CAM_ISP_ACQ_CUSTOM_SECONDARY 2 + /* Query devices */ /** * struct cam_isp_dev_cap_info - A cap info for particular hw type diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index 59564609035a..adfc1cb32f78 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -444,6 +444,9 @@ struct cam_req_mgr_error_msg { * @timestamp: timestamp of the frame * @link_hdl: link handle associated with this message * @sof_status: sof status success or fail + * @frame_id_meta: refers to the meta for + * that frame in specific usecases + * @reserved: reserved */ struct cam_req_mgr_frame_msg { uint64_t request_id; @@ -451,6 +454,8 @@ struct cam_req_mgr_frame_msg { uint64_t timestamp; int32_t link_hdl; uint32_t sof_status; + uint32_t frame_id_meta; + uint32_t reserved; }; /** From 7583d45a07c083aac9bda7a45bf45f4630ede849 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 4 Nov 2019 11:16:39 -0800 Subject: [PATCH 161/790] msm: camera: reqmgr: Change v4l2 notify error log type In case userspace fails to dequeue a v4l2 event with a valid request, kernel will dump that message as error and rest will be rate limited. CRs-Fixed: 2558548 Change-Id: I1c6769f47d0e1ca4a3ce5c6467f6c280104ae2b8 Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 42 ++++++++++++++++----------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index f2452d9c340c..cdb2210a2efb 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -204,31 +204,39 @@ static void cam_v4l2_event_queue_notify_error(const struct v4l2_event *old, ev_header = CAM_REQ_MGR_GET_PAYLOAD_PTR((*old), struct cam_req_mgr_message); + switch (old->id) { case V4L_EVENT_CAM_REQ_MGR_SOF: - CAM_ERR(CAM_CRM, "Failed to notify SOF event"); - CAM_ERR(CAM_CRM, "Sess %X FrameId %lld ReqId %lld link %X", - ev_header->session_hdl, - ev_header->u.frame_msg.frame_id, - ev_header->u.frame_msg.request_id, - ev_header->u.frame_msg.link_hdl); + case V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS: + if (ev_header->u.frame_msg.request_id) + CAM_ERR(CAM_CRM, + "Failed to notify %s Sess %X FrameId %lld FrameMeta %d ReqId %lld link %X", + ((old->id == V4L_EVENT_CAM_REQ_MGR_SOF) ? + "SOF_TS" : "BOOT_TS"), + ev_header->session_hdl, + ev_header->u.frame_msg.frame_id, + ev_header->u.frame_msg.frame_id_meta, + ev_header->u.frame_msg.request_id, + ev_header->u.frame_msg.link_hdl); + else + CAM_WARN_RATE_LIMIT_CUSTOM(CAM_CRM, 5, 1, + "Failed to notify %s Sess %X FrameId %lld FrameMeta %d ReqId %lld link %X", + ((old->id == V4L_EVENT_CAM_REQ_MGR_SOF) ? + "SOF_TS" : "BOOT_TS"), + ev_header->session_hdl, + ev_header->u.frame_msg.frame_id, + ev_header->u.frame_msg.frame_id_meta, + ev_header->u.frame_msg.request_id, + ev_header->u.frame_msg.link_hdl); break; case V4L_EVENT_CAM_REQ_MGR_ERROR: - CAM_ERR(CAM_CRM, "Failed to notify ERROR"); - CAM_ERR(CAM_CRM, "Sess %X ReqId %d Link %X Type %d", - ev_header->u.err_msg.error_type, + CAM_ERR(CAM_CRM, + "Failed to notify ERROR Sess %X ReqId %d Link %X Type %d", + ev_header->session_hdl, ev_header->u.err_msg.request_id, ev_header->u.err_msg.link_hdl, ev_header->u.err_msg.error_type); break; - case V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS: - CAM_ERR(CAM_CRM, "Failed to notify BOOT_TS event"); - CAM_ERR(CAM_CRM, "Sess %X FrameId %lld ReqId %lld link %X", - ev_header->session_hdl, - ev_header->u.frame_msg.frame_id, - ev_header->u.frame_msg.request_id, - ev_header->u.frame_msg.link_hdl); - break; default: CAM_ERR(CAM_CRM, "Failed to notify crm event id %d", old->id); From 8acdfccd8582a6a63fe4dac62bbbdb1dc340e674 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Wed, 23 Oct 2019 12:07:49 +0530 Subject: [PATCH 162/790] msm: camera: csiphy: Update registers for CSIPHY v1.2 Update register settings for CPHY/DPHY/combo DPHY modes as per the latest HPG (revision J). CRs-Fixed: 2563037 Change-Id: I137141a490bedce4632991e5eb12887d0c9fa30e Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 88 ++++++++----------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 35e2a4ab1d6a..e00e2bdf344d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -12,9 +12,9 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, - .csiphy_common_array_size = 5, + .csiphy_common_array_size = 6, .csiphy_reset_array_size = 4, - .csiphy_2ph_config_array_size = 19, + .csiphy_2ph_config_array_size = 18, .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -23,9 +23,10 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { struct csiphy_reg_t csiphy_common_reg_1_2[] = { {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, }; struct csiphy_reg_t csiphy_reset_reg_1_2[] = { @@ -55,18 +56,17 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -76,18 +76,17 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -97,18 +96,17 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -118,18 +116,17 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -139,18 +136,17 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -159,23 +155,22 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { }; struct csiphy_reg_t - csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { +csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0060, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -185,18 +180,17 @@ struct csiphy_reg_t {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -206,18 +200,17 @@ struct csiphy_reg_t {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0260, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -227,18 +220,17 @@ struct csiphy_reg_t {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0460, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -248,18 +240,17 @@ struct csiphy_reg_t {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0600, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x060C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -382,14 +373,11 @@ struct data_rate_settings_t data_rate_delta_table_1_2 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 6, + .data_rate_reg_array_size = 3, .csiphy_data_rate_regs = { {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, } }, { @@ -397,12 +385,12 @@ struct data_rate_settings_t data_rate_delta_table_1_2 = { .bandwidth = 7980000000, .data_rate_reg_array_size = 15, .csiphy_data_rate_regs = { + {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x2D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x2D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x2D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -419,21 +407,21 @@ struct data_rate_settings_t data_rate_delta_table_1_2 = { .bandwidth = 10260000000, .data_rate_reg_array_size = 15, .csiphy_data_rate_regs = { + {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x10C, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x30C, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x50C, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, }, } } From 97c65b5ff3e817f3e641e4b838c25da6fc3065de Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Wed, 6 Nov 2019 16:38:00 +0530 Subject: [PATCH 163/790] msm: camera: csiphy: Update reset sequence for csiphy v1.2 Add a transition of 1 to 0 in the PHY reset register during the PHY reset sequence to fix UNBOUNDED_FRAME errors for CPHY sensor. CRs-Fixed: 2563019 Change-Id: I019e4cfdfa2042416e62b306dca0448d6a05c3b8 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index e00e2bdf344d..20e14a354515 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -13,7 +13,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 = 6, - .csiphy_reset_array_size = 4, + .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 18, .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, @@ -33,6 +33,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}, }; From 313a84b8084a1a25b6fae7c7ebfc6658a32a4c6f Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Fri, 8 Nov 2019 13:33:36 +0530 Subject: [PATCH 164/790] msm: camera: csiphy: Fix csiphy v1.2 skew calibration settings Correct the skew calibration register settings in the DPHY sequence for csiphy v1.2. CRs-Fixed: 2563037 Change-Id: Idd97600b66dd00ff67db902dbd9d649aa005b4ec Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 20e14a354515..3bed231e0246 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -71,7 +71,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0060, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -111,7 +111,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0260, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -131,7 +131,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0460, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -151,7 +151,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0660, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, }, }; @@ -171,10 +171,10 @@ csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0060, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -211,10 +211,10 @@ csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0260, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -231,10 +231,10 @@ csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0460, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { From fc8ddd752d08cd9b95d512e361a977f46a2e3f0c Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 30 Oct 2019 18:30:06 +0530 Subject: [PATCH 165/790] msm: camera: isp: Notify CRM to pause SOF timer after flush Adding CRM interface to stop SOF timer from isp during flush. During flush hardware is getting stop and will not send SOF notification to CRM so need to pause SOF timer. Whenever SOF timer will get expire,do not need to send error to UMD during pause time. CRs-Fixed: 2564389 Change-Id: I6d85f2c658c30dbe211f0ec9d83bca323a5c265b Signed-off-by: Chandan Kumar Jha --- drivers/cam_isp/cam_isp_context.c | 9 ++++ drivers/cam_req_mgr/cam_req_mgr_core.c | 55 +++++++++++++++++++++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 16 ++++++ drivers/cam_req_mgr/cam_req_mgr_timer.h | 12 +++-- 4 files changed, 87 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index b251d75ac2f5..1a66070585e5 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2165,6 +2165,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_hw_stop_args stop_args; struct cam_hw_reset_args reset_args; struct cam_hw_cmd_args hw_cmd_args; + struct cam_req_mgr_timer_notify timer; ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; @@ -2210,6 +2211,14 @@ static int __cam_isp_ctx_flush_req_in_top_state( CAM_INFO(CAM_ISP, "Stop HW complete. Reset HW next."); CAM_DBG(CAM_ISP, "Flush wait and active lists"); + + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_timer) { + timer.link_hdl = ctx->link_hdl; + timer.dev_hdl = ctx->dev_hdl; + timer.state = false; + ctx->ctx_crm_intf->notify_timer(&timer); + } + spin_lock_bh(&ctx->lock); if (!list_empty(&ctx->wait_req_list)) rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index faa15479ecda..00677b9d864e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1744,6 +1744,10 @@ static void __cam_req_mgr_sof_freeze(struct timer_list *timer_data) } link = (struct cam_req_mgr_core_link *)timer->parent; + + if (link->watchdog->pause_timer) + return; + task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR(CAM_CRM, "No empty task"); @@ -2643,6 +2647,52 @@ end: return rc; } +/** + * cam_req_mgr_cb_notify_timer() + * + * @brief : Notify SOF timer to pause after flush + * @timer_data : contains information about frame_id, link etc. + * + * @return : 0 on success + * + */ +static int cam_req_mgr_cb_notify_timer( + struct cam_req_mgr_timer_notify *timer_data) +{ + int rc = 0; + struct cam_req_mgr_core_link *link = NULL; + + if (!timer_data) { + CAM_ERR(CAM_CRM, "timer data is NULL"); + rc = -EINVAL; + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(timer_data->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", timer_data->link_hdl); + rc = -EINVAL; + goto end; + } + + spin_lock_bh(&link->link_state_spin_lock); + if (link->state < CAM_CRM_LINK_STATE_READY) { + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + spin_unlock_bh(&link->link_state_spin_lock); + rc = -EPERM; + goto end; + } + spin_unlock_bh(&link->link_state_spin_lock); + + + if (!timer_data->state) + link->watchdog->pause_timer = true; + +end: + return rc; +} + /** * cam_req_mgr_cb_notify_trigger() * @@ -2682,6 +2732,10 @@ static int cam_req_mgr_cb_notify_trigger( rc = -EPERM; goto end; } + + if (link->watchdog->pause_timer) + link->watchdog->pause_timer = false; + crm_timer_reset(link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); @@ -2711,6 +2765,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = { .notify_trigger = cam_req_mgr_cb_notify_trigger, .notify_err = cam_req_mgr_cb_notify_err, .add_req = cam_req_mgr_cb_add_req, + .notify_timer = cam_req_mgr_cb_notify_timer, }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index f4b662dd4138..5df13b26e215 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -14,6 +14,7 @@ struct cam_req_mgr_trigger_notify; struct cam_req_mgr_error_notify; struct cam_req_mgr_add_request; +struct cam_req_mgr_timer_notify; struct cam_req_mgr_device_info; struct cam_req_mgr_core_dev_link_setup; struct cam_req_mgr_apply_request; @@ -35,6 +36,7 @@ typedef int (*cam_req_mgr_notify_trigger)( struct cam_req_mgr_trigger_notify *); typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); +typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *); /** * @brief: cam req mgr to camera device drivers @@ -64,6 +66,7 @@ struct cam_req_mgr_crm_cb { cam_req_mgr_notify_trigger notify_trigger; cam_req_mgr_notify_err notify_err; cam_req_mgr_add_req add_req; + cam_req_mgr_notify_timer notify_timer; }; /** @@ -206,6 +209,19 @@ struct cam_req_mgr_trigger_notify { uint64_t sof_timestamp_val; }; +/** + * struct cam_req_mgr_timer_notify + * @link_hdl : link identifier + * @dev_hdl : device handle which has sent this req id + * @frame_id : frame id for internal tracking + * @state : timer state i.e ON or OFF + */ +struct cam_req_mgr_timer_notify { + int32_t link_hdl; + int32_t dev_hdl; + bool state; +}; + /** * struct cam_req_mgr_error_notify * @link_hdl : link identifier diff --git a/drivers/cam_req_mgr/cam_req_mgr_timer.h b/drivers/cam_req_mgr/cam_req_mgr_timer.h index 9f9ba71a3879..be200f1b2693 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_timer.h +++ b/drivers/cam_req_mgr/cam_req_mgr_timer.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_TIMER_H_ @@ -12,16 +12,18 @@ #include "cam_req_mgr_core_defs.h" /** struct cam_req_mgr_timer - * @expires : timeout value for timer - * @sys_timer : system timer variable - * @parent : priv data - link pointer - * @timer_cb : callback func which will be called when timeout expires + * @expires : timeout value for timer + * @sys_timer : system timer variable + * @parent : priv data - link pointer + * @timer_cb : callback func which will be called when timeout expires + * @pause_timer : flag to pause SOF timer */ struct cam_req_mgr_timer { int32_t expires; struct timer_list sys_timer; void *parent; void (*timer_cb)(struct timer_list *timer_data); + bool pause_timer; }; /** From 1f409d4bca45932dade1b32feba90bad91068640 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 11 Nov 2019 11:46:42 +0530 Subject: [PATCH 166/790] msm: camera: reqmgr: Improve master slave sync If link is not ready on master epoch, but it becomes ready on slave epoch, then master skips apply and slave applies request and goes ahead of master. Fix this by skipping apply on slave if master slot in not in applied state. CRs-Fixed: 2562008 Change-Id: Ic612eedfeedf2a6ea50737a49a6f1f31a5de1dc2 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_req_mgr/cam_req_mgr_core.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 00677b9d864e..0a4af3c097d0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1106,6 +1106,8 @@ static int __cam_req_mgr_check_sync_req_is_ready( int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; int32_t sync_num_slots = 0; uint64_t sync_frame_duration = 0; + uint64_t sof_timestamp_delta = 0; + uint64_t master_slave_diff = 0; bool ready = true, sync_ready = true; if (!link->sync_link) { @@ -1139,6 +1141,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( else sync_frame_duration = DEFAULT_FRAME_DURATION; + sof_timestamp_delta = + link->sof_timestamp >= sync_link->sof_timestamp + ? link->sof_timestamp - sync_link->sof_timestamp + : sync_link->sof_timestamp - link->sof_timestamp; + CAM_DBG(CAM_CRM, "sync link %x last frame_duration is %d ns", sync_link->link_hdl, sync_frame_duration); @@ -1260,11 +1267,10 @@ static int __cam_req_mgr_check_sync_req_is_ready( * difference of two SOF timestamp less than * (sync_frame_duration / 5). */ - do_div(sync_frame_duration, 5); - if ((link->sof_timestamp > sync_link->sof_timestamp) && - (sync_link->sof_timestamp > 0) && - (link->sof_timestamp - sync_link->sof_timestamp < - sync_frame_duration) && + master_slave_diff = sync_frame_duration; + do_div(master_slave_diff, 5); + if ((sync_link->sof_timestamp > 0) && + (sof_timestamp_delta < master_slave_diff) && (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { /* @@ -1287,6 +1293,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( "sync link %x too quickly, skip next frame of sync link", sync_link->link_hdl); link->sync_link_sof_skip = true; + } else if (sync_link->req.in_q->slot[sync_slot_idx].status != + CRM_SLOT_STATUS_REQ_APPLIED) { + CAM_DBG(CAM_CRM, + "link %x other not applied", link->link_hdl); + return -EAGAIN; } } From a3b0bbaa8cf31466fcff9c3f6e1f6d7f4df8b219 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 16 Oct 2019 10:39:45 +0530 Subject: [PATCH 167/790] msm: camera: icp: icp debug improvement ON receiving HFI_EVENT_SYS_ERROR event_id as part of sys_error msg and event_data1 is set to HFI_ERR_SYS_FATAL, trigger the crash. CRs-Fixed: 2549369 Change-Id: Iddf56f46b2c07a703a787b0dedebd801081c93d6 Signed-off-by: Tejas Prajapati --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a7e6bd9e987f..8bc550bc188d 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -2361,6 +2361,10 @@ 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"); + if (event_notify->event_data1 == HFI_ERR_SYS_FATAL) { + CAM_ERR(CAM_ICP, "received HFI_ERR_SYS_FATAL"); + BUG(); + } rc = cam_icp_mgr_trigger_recovery(hw_mgr); cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); } From 09c9b6c054f25110aa69c941723c6cec7d9f0406 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 11 Nov 2019 11:59:21 +0530 Subject: [PATCH 168/790] msm: camera: icp: Increase MAX_PKT_SIZE_MSGQ for ICP Increase ICP_HFI_MAX_PKT_SIZE_MSGQ_IN_WORDS to improve workqueue delay tolerance. CRs-Fixed: 2564981 Change-Id: Ic61e79588a834e651e7b2f5e44acd3fcbc9d8f77 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_icp/fw_inc/hfi_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index f67a7044f26b..2a30c1451201 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -74,7 +74,7 @@ #define ICP_SHARED_MEM_IN_BYTES (1024 * 1024) #define ICP_UNCACHED_HEAP_SIZE_IN_BYTES (2 * 1024 * 1024) #define ICP_HFI_MAX_PKT_SIZE_IN_WORDS 25600 -#define ICP_HFI_MAX_PKT_SIZE_MSGQ_IN_WORDS 256 +#define ICP_HFI_MAX_PKT_SIZE_MSGQ_IN_WORDS 1024 #define ICP_HFI_QTBL_HOSTID1 0x01000000 #define ICP_HFI_QTBL_STATUS_ENABLED 0x00000001 From 2c2fea11c5534bfde20baa49a9c8b0fa8c1aef5c Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Wed, 13 Nov 2019 00:04:55 -0800 Subject: [PATCH 169/790] msm: camera: isp: Reset overflow pending flag in start hw While start hw, either a fresh start or resume after flush, reset the overflow pending flag as we reset the hw and start fresh with applying init packet. In case where overflow happening at the same time as halt immediately, we set overflow pending flag to true. Eventhough while halt immediate and resume scenario, we reset the hw, not resetting overflow pending flag causes not to apply any new packets while resume. CRs-Fixed: 2565049 Change-Id: Ia9c871402343306945fe1b8f8373659e52630fe2 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 35 +++++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 998dfd743087..94f1c75f6d20 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3358,9 +3358,10 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; - CAM_DBG(CAM_ISP, "Enter"); if (!hw_mgr_priv || !config_hw_args) { - CAM_ERR(CAM_ISP, "Invalid arguments"); + CAM_ERR(CAM_ISP, + "Invalid arguments, hw_mgr_priv=%pK, config_hw_args=%pK", + hw_mgr_priv, config_hw_args); return -EINVAL; } @@ -3368,21 +3369,28 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, ctx = (struct cam_ife_hw_mgr_ctx *)cfg->ctxt_to_hw_map; if (!ctx) { CAM_ERR(CAM_ISP, "Invalid context is used"); - return -EPERM; + return -EINVAL; } if (!ctx->ctx_in_use || !ctx->cdm_cmd) { - CAM_ERR(CAM_ISP, "Invalid context parameters"); + CAM_ERR(CAM_ISP, + "Invalid context parameters : ctx_in_use=%d, cdm_cmd=%pK", + ctx->ctx_in_use, ctx->cdm_cmd); + return -EPERM; + } + + if (atomic_read(&ctx->overflow_pending)) { + CAM_DBG(CAM_ISP, + "Ctx[%pK][%d] Overflow pending, cannot apply req %llu", + ctx, ctx->ctx_index, cfg->request_id); return -EPERM; } - if (atomic_read(&ctx->overflow_pending)) - return -EINVAL; hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; hw_update_data->ife_mgr_ctx = ctx; - CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld", - ctx, ctx->ctx_index, cfg->request_id); + CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", + ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { @@ -3454,7 +3462,9 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, atomic_set(&ctx->cdm_done, 0); rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); if (rc) { - CAM_ERR(CAM_ISP, "Failed to apply the configs"); + CAM_ERR(CAM_ISP, + "Failed to apply the configs for req %llu, rc %d", + cfg->request_id, rc); return rc; } @@ -3954,11 +3964,16 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } start_only: + + atomic_set(&ctx->overflow_pending, 0); + /* Apply initial configuration */ CAM_DBG(CAM_ISP, "Config HW"); rc = cam_ife_mgr_config_hw(hw_mgr_priv, &start_isp->hw_config); if (rc) { - CAM_ERR(CAM_ISP, "Config HW failed"); + CAM_ERR(CAM_ISP, + "Config HW failed, start_only=%d, rc=%d", + start_isp->start_only, rc); goto cdm_streamoff; } From 809c56ef1683d75ad0542638cda54f6b541519d8 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Mon, 11 Nov 2019 12:15:16 +0530 Subject: [PATCH 170/790] msm: camera: isp: csid hw register reset with IRQ CSID hw register reset is done with the the help of IRQ to make sure it is reset every time before we start a new session. CRs-Fixed: 2563958 Change-Id: I33c870003eb1e99d458b7650b5b3218f61cccd3b Signed-off-by: Tejas Prajapati --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 148 ++++++++++++------ .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 1 + 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 570d2ba0e484..2c58913ef1f3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -43,6 +43,8 @@ /* Max CSI Rx irq error count threshold value */ #define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 100 +static int cam_ife_csid_reset_regs( + struct cam_ife_csid_hw *csid_hw, bool reset_hw); static int cam_ife_csid_is_ipp_ppp_format_supported( uint32_t in_format) { @@ -419,7 +421,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) const struct cam_ife_csid_reg_offset *csid_reg; int rc = 0; uint32_t val = 0, i; - uint32_t status; + unsigned long flags; soc_info = &csid_hw->hw_info->soc_info; csid_reg = csid_hw->csid_info->csid_reg; @@ -434,6 +436,8 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) CAM_DBG(CAM_ISP, "CSID:%d Csid reset", csid_hw->hw_intf->hw_idx); + spin_lock_irqsave(&csid_hw->hw_info->hw_lock, flags); + /* Mask all interrupts */ cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); @@ -481,6 +485,8 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); + spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); + cam_io_w_mb(0x80, soc_info->reg_map[0].mem_base + csid_hw->csid_info->csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); @@ -497,37 +503,14 @@ 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 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); + /* reset HW regs first, then SW */ + rc = cam_ife_csid_reset_regs(csid_hw, true); + if (rc < 0) + goto end; + rc = cam_ife_csid_reset_regs(csid_hw, false); + if (rc < 0) + goto end; - 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); - - 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; - } - - 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) @@ -536,6 +519,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; +end: return rc; } @@ -655,7 +639,7 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, return -EINVAL; } - init_completion(complete); + reinit_completion(complete); reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all; /* Reset the corresponding ife csid path */ @@ -1240,6 +1224,8 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) if (rc) goto disable_soc; + spin_lock_irqsave(&csid_hw->hw_info->hw_lock, flags); + /* clear all interrupts */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_clear_addr); @@ -1271,6 +1257,8 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); + spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_hw_version_addr); CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x", @@ -1564,7 +1552,7 @@ static int cam_ife_csid_enable_csi2( } } - /*Enable the CSI2 rx inerrupts */ + /*Enable the CSI2 rx interrupts */ val = CSID_CSI2_RX_INFO_RST_DONE | CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW | CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW | @@ -3093,6 +3081,7 @@ int cam_ife_csid_reset(void *hw_priv, csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; reset = (struct cam_csid_reset_cfg_args *)reset_args; + mutex_lock(&csid_hw->hw_info->hw_mutex); switch (reset->reset_type) { case CAM_IFE_CSID_RESET_GLOBAL: rc = cam_ife_csid_global_reset(csid_hw); @@ -3106,6 +3095,7 @@ int cam_ife_csid_reset(void *hw_priv, rc = -EINVAL; break; } + mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; } @@ -3230,43 +3220,86 @@ end: return rc; } -static int cam_ife_csid_reset_retain_sw_reg( - struct cam_ife_csid_hw *csid_hw) +static int cam_ife_csid_reset_regs( + struct cam_ife_csid_hw *csid_hw, bool reset_hw) { int rc = 0; - uint32_t status; const struct cam_ife_csid_reg_offset *csid_reg = csid_hw->csid_info->csid_reg; struct cam_hw_soc_info *soc_info; + uint32_t val = 0; + unsigned long flags; soc_info = &csid_hw->hw_info->soc_info; + + reinit_completion(&csid_hw->csid_top_complete); + + spin_lock_irqsave(&csid_hw->hw_info->hw_lock, flags); + /* clear the top interrupt first */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_clear_addr); cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); - cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb, + if (reset_hw) { + /* enable top reset complete IRQ */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + } + + /* perform the top CSID registers reset */ + val = reset_hw ? csid_reg->cmn_reg->csid_rst_stb : + csid_reg->cmn_reg->csid_reg_rst_stb; + cam_io_w_mb(val, 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); + + /* + * for SW reset, we enable the IRQ after since the mask + * register has been reset + */ + if (!reset_hw) { + /* enable top reset complete IRQ */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + } + + spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); + CAM_DBG(CAM_ISP, "CSID reset start"); + rc = wait_for_completion_timeout(&csid_hw->csid_top_complete, + msecs_to_jiffies(IFE_CSID_TIMEOUT)); + if (rc <= 0) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_status_addr); + if (val & 0x1) { + /* clear top reset IRQ */ + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + CAM_DBG(CAM_ISP, "CSID:%d %s reset completed %d", + csid_hw->hw_intf->hw_idx, + reset_hw ? "hw" : "sw", + rc); + rc = 0; + goto end; + } + CAM_ERR(CAM_ISP, "CSID:%d csid_reset %s fail rc = %d", + csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", rc); rc = -ETIMEDOUT; + goto end; } else { - CAM_DBG(CAM_ISP, "CSID:%d hw reset completed %d", - csid_hw->hw_intf->hw_idx, rc); + CAM_DBG(CAM_ISP, "CSID:%d %s reset completed %d", + csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", rc); rc = 0; } - cam_io_w_mb(1, soc_info->reg_map[0].mem_base + - csid_reg->cmn_reg->csid_top_irq_clear_addr); - cam_io_w_mb(1, soc_info->reg_map[0].mem_base + - csid_reg->cmn_reg->csid_irq_cmd_addr); +end: return rc; } @@ -3351,9 +3384,9 @@ int cam_ife_csid_init_hw(void *hw_priv, break; } - rc = cam_ife_csid_reset_retain_sw_reg(csid_hw); + rc = cam_ife_csid_reset_regs(csid_hw, true); if (rc < 0) - CAM_ERR(CAM_ISP, "CSID: Failed in SW reset"); + CAM_ERR(CAM_ISP, "CSID: Failed in HW reset"); if (rc) cam_ife_csid_disable_hw(csid_hw); @@ -3830,7 +3863,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } } + spin_lock_irqsave(&csid_hw->hw_info->hw_lock, flags); /* clear */ + cam_io_w_mb(irq_status_top, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + cam_io_w_mb(irq_status_rx, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); if (csid_reg->cmn_reg->num_pix) @@ -3860,6 +3897,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); + spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); + CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", irq_status_top); CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx); CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp); @@ -3871,6 +3910,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) "irq_status_udi0= 0x%x irq_status_udi1= 0x%x irq_status_udi2= 0x%x", irq_status_udi[0], irq_status_udi[1], irq_status_udi[2]); + if (irq_status_top & CSID_TOP_IRQ_DONE) { + CAM_DBG(CAM_ISP, "csid top reset complete"); + complete(&csid_hw->csid_top_complete); + } + if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "csi rx reset complete"); complete(&csid_hw->csid_csi2_complete); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 863aec341899..4c2ac18089af 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -40,6 +40,7 @@ #define CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW BIT(26) #define CSID_CSI2_RX_INFO_RST_DONE BIT(27) +#define CSID_TOP_IRQ_DONE BIT(0) #define CSID_PATH_INFO_RST_DONE BIT(1) #define CSID_PATH_ERROR_FIFO_OVERFLOW BIT(2) #define CSID_PATH_INFO_SUBSAMPLED_EOF BIT(3) From 5f530223baa4897a4b8278638d8db8a0cae447b1 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 4 Nov 2019 12:13:04 +0530 Subject: [PATCH 171/790] msm: camera: core: Prevent crash on kref_put kref_put causes crash if refcount is zero. This change prevents crash by checking if refcount value. CRs-Fixed: 2553290 Change-Id: Ie9a950b289cdb2b8fca8c5d025be540d926eadbd Signed-off-by: Trishansh Bhardwaj --- drivers/cam_core/cam_context.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 642d530054d8..1c17422d01d0 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -597,7 +597,12 @@ int cam_context_deinit(struct cam_context *ctx) void cam_context_putref(struct cam_context *ctx) { - kref_put(&ctx->refcount, cam_node_put_ctxt_to_free_list); + if (kref_read(&ctx->refcount)) + kref_put(&ctx->refcount, cam_node_put_ctxt_to_free_list); + else + WARN(1, "ctx %s %d state %d devhdl %X\n", ctx->dev_name, + ctx->ctx_id, ctx->state, ctx->dev_hdl); + CAM_DBG(CAM_CORE, "ctx device hdl %ld, ref count %d, dev_name %s", ctx->dev_hdl, refcount_read(&(ctx->refcount.refcount)), From a27592f01b63d2291ca5031048aa19614d56660b Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 25 Sep 2019 20:27:50 -0700 Subject: [PATCH 172/790] msm: camera: custom: Add support for acquire_hw_v1 Split the acquire in custom node to acquire device and acquire hw to be in line with IFE for multicamera usecases. CRs-Fixed: 2524308 Change-Id: I7be7d5227dcd304d095d7e3d7fac32800fecc199 Signed-off-by: Karthik Anantha Ram --- drivers/cam_cust/cam_custom_context.c | 231 ++++++++++++++-- drivers/cam_cust/cam_custom_context.h | 2 + .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 249 ++++++++---------- include/uapi/media/cam_custom.h | 17 ++ 4 files changed, 334 insertions(+), 165 deletions(-) diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 7f38392a7d57..3e69ebd15109 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -19,7 +19,7 @@ #include "cam_custom_context.h" #include "cam_common_util.h" -static const char custom_dev_name[] = "custom hw"; +static const char custom_dev_name[] = "cam-custom"; static int __cam_custom_ctx_handle_irq_in_activated( void *context, uint32_t evt_id, void *evt_data); @@ -275,6 +275,67 @@ static int __cam_custom_stop_dev_in_activated(struct cam_context *ctx, return 0; } +static int __cam_custom_ctx_release_hw_in_top_state( + struct cam_context *ctx, void *cmd) +{ + int rc = 0; + struct cam_hw_release_args rel_arg; + struct cam_req_mgr_flush_request flush_req; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + if (custom_ctx->hw_ctx) { + rel_arg.ctxt_to_hw_map = custom_ctx->hw_ctx; + rc = ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, + &rel_arg); + custom_ctx->hw_ctx = NULL; + if (rc) + CAM_ERR(CAM_CUSTOM, + "Failed to release HW for ctx:%u", ctx->ctx_id); + } else { + CAM_ERR(CAM_CUSTOM, "No HW resources acquired for this ctx"); + } + + ctx->last_flush_req = 0; + custom_ctx->frame_id = 0; + custom_ctx->active_req_cnt = 0; + custom_ctx->hw_acquired = false; + custom_ctx->init_received = false; + + /* check for active requests as well */ + flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; + flush_req.link_hdl = ctx->link_hdl; + flush_req.dev_hdl = ctx->dev_hdl; + + CAM_DBG(CAM_CUSTOM, "try to flush pending list"); + spin_lock_bh(&ctx->lock); + rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, + &flush_req); + spin_unlock_bh(&ctx->lock); + ctx->state = CAM_CTX_ACQUIRED; + + CAM_DBG(CAM_CUSTOM, "Release HW success[%u] next state %d", + ctx->ctx_id, ctx->state); + + return rc; +} + +static int __cam_custom_ctx_release_hw_in_activated_state( + struct cam_context *ctx, void *cmd) +{ + int rc = 0; + + rc = __cam_custom_stop_dev_in_activated(ctx, NULL); + if (rc) + CAM_ERR(CAM_CUSTOM, "Stop device failed rc=%d", rc); + + rc = __cam_custom_ctx_release_hw_in_top_state(ctx, cmd); + if (rc) + CAM_ERR(CAM_CUSTOM, "Release hw failed rc=%d", rc); + + return rc; +} + static int __cam_custom_release_dev_in_acquired(struct cam_context *ctx, struct cam_release_dev_cmd *cmd) { @@ -283,14 +344,16 @@ static int __cam_custom_release_dev_in_acquired(struct cam_context *ctx, (struct cam_custom_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; - rc = cam_context_release_dev_to_hw(ctx, cmd); - if (rc) - CAM_ERR(CAM_CUSTOM, "Unable to release device"); + if (cmd && ctx_custom->hw_ctx) { + CAM_ERR(CAM_CUSTOM, "releasing hw"); + __cam_custom_ctx_release_hw_in_top_state(ctx, NULL); + } ctx->ctx_crm_intf = NULL; ctx->last_flush_req = 0; ctx_custom->frame_id = 0; ctx_custom->active_req_cnt = 0; + ctx_custom->hw_acquired = false; ctx_custom->init_received = false; if (!list_empty(&ctx->active_req_list)) @@ -381,33 +444,128 @@ end: return rc; } -static int __cam_custom_ctx_acquire_dev_in_available(struct cam_context *ctx, - struct cam_acquire_dev_cmd *cmd) +static int __cam_custom_ctx_acquire_hw_v1( + struct cam_context *ctx, void *args) { - int rc; - struct cam_custom_context *custom_ctx; + int rc = 0; + struct cam_acquire_hw_cmd_v1 *cmd = + (struct cam_acquire_hw_cmd_v1 *)args; + struct cam_hw_acquire_args param; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + struct cam_custom_acquire_hw_info *acquire_hw_info = NULL; - custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; - - if (cmd->num_resources > CAM_CUSTOM_DEV_CTX_RES_MAX) { - CAM_ERR(CAM_CUSTOM, "Too much resources in the acquire"); - rc = -ENOMEM; - return rc; + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CUSTOM, "HW interface is not ready"); + rc = -EFAULT; + goto end; } - if (cmd->handle_type != 1) { + CAM_DBG(CAM_CUSTOM, + "session_hdl 0x%x, hdl type %d, res %lld", + cmd->session_handle, cmd->handle_type, cmd->resource_hdl); + + if (cmd->handle_type != 1) { CAM_ERR(CAM_CUSTOM, "Only user pointer is supported"); rc = -EINVAL; + goto end; + } + + if (cmd->data_size < sizeof(*acquire_hw_info)) { + CAM_ERR(CAM_CUSTOM, "data_size is not a valid value"); + goto end; + } + + acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL); + if (!acquire_hw_info) { + rc = -ENOMEM; + goto end; + } + + CAM_DBG(CAM_CUSTOM, "start copy resources from user"); + + if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl, + cmd->data_size)) { + rc = -EFAULT; + goto free_res; + } + + memset(¶m, 0, sizeof(param)); + param.context_data = ctx; + param.event_cb = ctx->irq_cb_intf; + param.acquire_info_size = cmd->data_size; + param.acquire_info = (uint64_t) acquire_hw_info; + + /* call HW manager to reserve the resource */ + rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, + ¶m); + if (rc != 0) { + CAM_ERR(CAM_CUSTOM, "Acquire HW failed"); + goto free_res; + } + + ctx_custom->hw_ctx = param.ctxt_to_hw_map; + ctx_custom->hw_acquired = true; + ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + + CAM_DBG(CAM_CUSTOM, + "Acquire HW success on session_hdl 0x%xs for ctx_id %u", + ctx->session_hdl, ctx->ctx_id); + + kfree(acquire_hw_info); + return rc; + +free_res: + kfree(acquire_hw_info); +end: + return rc; +} + +static int __cam_custom_ctx_acquire_dev_in_available( + struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) +{ + int rc = 0; + struct cam_create_dev_hdl req_hdl_param; + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CUSTOM, "HW interface is not ready"); + rc = -EFAULT; return rc; } - rc = cam_context_acquire_dev_to_hw(ctx, cmd); - if (!rc) { - ctx->state = CAM_CTX_ACQUIRED; - custom_ctx->hw_ctx = ctx->ctxt_to_hw_map; + CAM_DBG(CAM_CUSTOM, + "session_hdl 0x%x, num_resources %d, hdl type %d, res %lld", + cmd->session_handle, cmd->num_resources, + cmd->handle_type, cmd->resource_hdl); + + if (cmd->num_resources != CAM_API_COMPAT_CONSTANT) { + CAM_ERR(CAM_CUSTOM, "Invalid num_resources 0x%x", + cmd->num_resources); + return -EINVAL; } - CAM_DBG(CAM_CUSTOM, "Acquire done %d", ctx->ctx_id); + req_hdl_param.session_hdl = cmd->session_handle; + req_hdl_param.v4l2_sub_dev_flag = 0; + req_hdl_param.media_entity_flag = 0; + req_hdl_param.ops = ctx->crm_ctx_intf; + req_hdl_param.priv = ctx; + + CAM_DBG(CAM_CUSTOM, "get device handle from bridge"); + ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param); + if (ctx->dev_hdl <= 0) { + rc = -EFAULT; + CAM_ERR(CAM_CUSTOM, "Can not create device handle"); + return rc; + } + + cmd->dev_handle = ctx->dev_hdl; + ctx->session_hdl = cmd->session_handle; + ctx->state = CAM_CTX_ACQUIRED; + + CAM_DBG(CAM_CUSTOM, + "Acquire dev success on session_hdl 0x%x for ctx %u", + cmd->session_handle, ctx->ctx_id); + return rc; } @@ -642,6 +800,13 @@ static int __cam_custom_ctx_config_dev_in_acquired(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { int rc = 0; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *) ctx->ctx_priv; + + if (!ctx_custom->hw_acquired) { + CAM_ERR(CAM_CUSTOM, "HW not acquired, reject config packet"); + return -EAGAIN; + } rc = __cam_custom_ctx_config_dev(ctx, cmd); @@ -826,6 +991,27 @@ static int __cam_custom_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_custom_ctx_acquire_hw_in_acquired( + struct cam_context *ctx, void *args) +{ + int rc = -EINVAL; + uint32_t api_version; + + if (!ctx || !args) { + CAM_ERR(CAM_CUSTOM, "Invalid input pointer"); + return rc; + } + + api_version = *((uint32_t *)args); + if (api_version == 1) + rc = __cam_custom_ctx_acquire_hw_v1(ctx, args); + else + CAM_ERR(CAM_CUSTOM, "Unsupported api version %d", + api_version); + + return rc; +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -847,8 +1033,10 @@ static struct cam_ctx_ops /* Acquired */ { .ioctl_ops = { + .acquire_hw = __cam_custom_ctx_acquire_hw_in_acquired, .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev_in_acquired, + .release_hw = __cam_custom_ctx_release_hw_in_top_state, }, .crm_ops = { .link = __cam_custom_ctx_link_in_acquired, @@ -866,6 +1054,7 @@ static struct cam_ctx_ops .start_dev = __cam_custom_ctx_start_dev_in_ready, .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev, + .release_hw = __cam_custom_ctx_release_hw_in_top_state, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -883,6 +1072,8 @@ static struct cam_ctx_ops .release_dev = __cam_custom_ctx_release_dev_in_activated, .config_dev = __cam_custom_ctx_config_dev, + .release_hw = + __cam_custom_ctx_release_hw_in_activated_state, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index 91acf1e5ee80..27268b20c526 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -67,6 +67,7 @@ struct cam_custom_dev_ctx_req { * custom HW will invoke CRM cb at those event. * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context + * @hw_acquired: Flag to indicate if HW is acquired for this context * @req_base: common request structure * @req_custom: custom request structure * @@ -80,6 +81,7 @@ struct cam_custom_context { uint32_t subscribe_event; uint32_t active_req_cnt; int64_t frame_id; + bool hw_acquired; struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; struct cam_custom_dev_ctx_req req_custom[CAM_CTX_REQ_MAX]; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index 1db06bb3ab1f..f2e5a1ff3407 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -380,7 +380,7 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, &ctx->res_list_custom_cid, list) { rc = cam_custom_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { - CAM_ERR(CAM_ISP, "Can not INIT CID(id :%d)", + CAM_ERR(CAM_CUSTOM, "Can not INIT CID(id :%d)", hw_mgr_res->res_id); goto deinit_hw; } @@ -391,7 +391,7 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, &ctx->res_list_custom_csid, list) { rc = cam_custom_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { - CAM_ERR(CAM_ISP, "Can not INIT CSID(id :%d)", + CAM_ERR(CAM_CUSTOM, "Can not INIT CSID(id :%d)", hw_mgr_res->res_id); goto deinit_hw; } @@ -411,7 +411,7 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, &ctx->res_list_custom_csid, list) { rc = cam_custom_hw_mgr_start_hw_res(hw_mgr_res); if (rc) { - CAM_ERR(CAM_ISP, "Can not START CSID(id :%d)", + CAM_ERR(CAM_CUSTOM, "Can not START CSID(id :%d)", hw_mgr_res->res_id); goto err; } @@ -422,7 +422,7 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, &ctx->res_list_custom_cid, list) { rc = cam_custom_hw_mgr_start_hw_res(hw_mgr_res); if (rc) { - CAM_ERR(CAM_ISP, "Can not START CID(id :%d)", + CAM_ERR(CAM_CUSTOM, "Can not START CID(id :%d)", hw_mgr_res->res_id); goto err; } @@ -760,7 +760,7 @@ static int cam_custom_hw_mgr_release_hw_for_ctx( &custom_ctx->res_list_custom_cid, list) { rc = cam_custom_hw_mgr_free_hw_res(hw_mgr_res); if (rc) - CAM_ERR(CAM_ISP, "Can not release CID(id :%d)", + CAM_ERR(CAM_CUSTOM, "Can not release CID(id :%d)", hw_mgr_res->res_id); cam_custom_hw_mgr_put_res( &custom_ctx->free_res_list, &hw_mgr_res); @@ -771,7 +771,7 @@ static int cam_custom_hw_mgr_release_hw_for_ctx( &custom_ctx->res_list_custom_csid, list) { rc = cam_custom_hw_mgr_free_hw_res(hw_mgr_res); if (rc) - CAM_ERR(CAM_ISP, "Can not release CSID(id :%d)", + CAM_ERR(CAM_CUSTOM, "Can not release CSID(id :%d)", hw_mgr_res->res_id); cam_custom_hw_mgr_put_res( &custom_ctx->free_res_list, &hw_mgr_res); @@ -811,41 +811,82 @@ static int cam_custom_mgr_release_hw(void *hw_mgr_priv, return rc; } -static void cam_custom_hw_mgr_acquire_get_unified_dev_str( - struct cam_custom_in_port_info *in, - struct cam_isp_in_port_generic_info *gen_port_info) +static int cam_custom_hw_mgr_acquire_get_unified_dev_str( + struct cam_custom_acquire_hw_info *acquire_hw_info, + uint32_t *input_size, + struct cam_isp_in_port_generic_info **gen_port_info) { - int i; + int32_t rc = 0, i; + uint32_t in_port_length = 0; + struct cam_custom_in_port_info *in = NULL; + struct cam_isp_in_port_generic_info *port_info = NULL; - gen_port_info->res_type = in->res_type + + in = (struct cam_custom_in_port_info *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset + *input_size); + + in_port_length = sizeof(struct cam_custom_in_port_info) + + (in->num_out_res - 1) * + sizeof(struct cam_custom_out_port_info); + + *input_size += in_port_length; + + if ((*input_size) > acquire_hw_info->input_info_size) { + CAM_ERR(CAM_CUSTOM, "Input is not proper"); + rc = -EINVAL; + return rc; + } + + port_info = kzalloc( + sizeof(struct cam_isp_in_port_generic_info), GFP_KERNEL); + + if (!port_info) + return -ENOMEM; + + port_info->res_type = in->res_type + CAM_ISP_IFE_IN_RES_BASE - CAM_CUSTOM_IN_RES_BASE; - gen_port_info->lane_type = in->lane_type; - gen_port_info->lane_num = in->lane_num; - gen_port_info->lane_cfg = in->lane_cfg; - gen_port_info->vc[0] = in->vc[0]; - gen_port_info->dt[0] = in->dt[0]; - gen_port_info->num_valid_vc_dt = in->num_valid_vc_dt; - gen_port_info->format = in->format; - gen_port_info->test_pattern = in->test_pattern; - gen_port_info->usage_type = in->usage_type; - gen_port_info->left_start = in->left_start; - gen_port_info->left_stop = in->left_stop; - gen_port_info->left_width = in->left_width; - gen_port_info->right_start = in->right_start; - gen_port_info->right_stop = in->right_stop; - gen_port_info->right_width = in->right_width; - gen_port_info->line_start = in->line_start; - gen_port_info->line_stop = in->line_stop; - gen_port_info->height = in->height; - gen_port_info->pixel_clk = in->pixel_clk; - gen_port_info->cust_node = 1; - gen_port_info->num_out_res = in->num_out_res; - gen_port_info->num_bytes_out = in->num_bytes_out; + port_info->lane_type = in->lane_type; + port_info->lane_num = in->lane_num; + port_info->lane_cfg = in->lane_cfg; + port_info->vc[0] = in->vc[0]; + port_info->dt[0] = in->dt[0]; + port_info->num_valid_vc_dt = in->num_valid_vc_dt; + port_info->format = in->format; + port_info->test_pattern = in->test_pattern; + port_info->usage_type = in->usage_type; + port_info->left_start = in->left_start; + port_info->left_stop = in->left_stop; + port_info->left_width = in->left_width; + port_info->right_start = in->right_start; + port_info->right_stop = in->right_stop; + port_info->right_width = in->right_width; + port_info->line_start = in->line_start; + port_info->line_stop = in->line_stop; + port_info->height = in->height; + port_info->pixel_clk = in->pixel_clk; + port_info->cust_node = 1; + port_info->num_out_res = in->num_out_res; + port_info->num_bytes_out = in->num_bytes_out; + + port_info->data = kcalloc(in->num_out_res, + sizeof(struct cam_isp_out_port_generic_info), + GFP_KERNEL); + if (port_info->data == NULL) { + rc = -ENOMEM; + goto release_port_mem; + } for (i = 0; i < in->num_out_res; i++) { - gen_port_info->data[i].res_type = in->data[i].res_type; - gen_port_info->data[i].format = in->data[i].format; + port_info->data[i].res_type = in->data[i].res_type; + port_info->data[i].format = in->data[i].format; } + + *gen_port_info = port_info; + return 0; + +release_port_mem: + kfree(port_info); + return rc; } static int cam_custom_mgr_acquire_hw_for_ctx( @@ -896,18 +937,16 @@ static int cam_custom_mgr_acquire_hw( void *hw_mgr_priv, void *acquire_hw_args) { - int rc = -1; - int32_t i; - uint32_t in_port_length; + int rc = -1, i; + uint32_t input_size = 0; struct cam_custom_hw_mgr_ctx *custom_ctx; struct cam_custom_hw_mgr *custom_hw_mgr; - struct cam_hw_acquire_args *acquire_args = - (struct cam_hw_acquire_args *) acquire_hw_args; - struct cam_custom_in_port_info *in_port_info; - struct cam_custom_resource *custom_rsrc; + struct cam_custom_acquire_hw_info *acquire_hw_info = NULL; struct cam_isp_in_port_generic_info *gen_port_info = NULL; + struct cam_hw_acquire_args *acquire_args = + (struct cam_hw_acquire_args *)acquire_hw_args; - if (!hw_mgr_priv || !acquire_args || (acquire_args->num_acq <= 0)) { + if (!hw_mgr_priv || !acquire_args) { CAM_ERR(CAM_CUSTOM, "Invalid params"); return -EINVAL; } @@ -923,127 +962,47 @@ static int cam_custom_mgr_acquire_hw( } mutex_unlock(&g_custom_hw_mgr.ctx_mutex); - /* Handle Acquire Here */ custom_ctx->hw_mgr = custom_hw_mgr; custom_ctx->cb_priv = acquire_args->context_data; custom_ctx->event_cb = acquire_args->event_cb; - custom_rsrc = kcalloc(acquire_args->num_acq, - sizeof(*custom_rsrc), GFP_KERNEL); - if (!custom_rsrc) { - rc = -ENOMEM; - goto free_ctx; - } + acquire_hw_info = + (struct cam_custom_acquire_hw_info *)acquire_args->acquire_info; - CAM_DBG(CAM_CUSTOM, "start copy %d resources from user", - acquire_args->num_acq); + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + rc = cam_custom_hw_mgr_acquire_get_unified_dev_str( + acquire_hw_info, &input_size, &gen_port_info); - if (copy_from_user(custom_rsrc, - (void __user *)acquire_args->acquire_info, - ((sizeof(*custom_rsrc)) * acquire_args->num_acq))) { - rc = -EFAULT; - goto free_ctx; - } - - for (i = 0; i < acquire_args->num_acq; i++) { - if (custom_rsrc[i].resource_id != CAM_CUSTOM_RES_ID_PORT) - continue; - - CAM_DBG(CAM_CUSTOM, "acquire no = %d total = %d", i, - acquire_args->num_acq); - - CAM_DBG(CAM_CUSTOM, - "start copy from user handle %lld with len = %d", - custom_rsrc[i].res_hdl, - custom_rsrc[i].length); - - in_port_length = sizeof(struct cam_custom_in_port_info); - if (in_port_length > custom_rsrc[i].length) { - CAM_ERR(CAM_CUSTOM, "buffer size is not enough"); - rc = -EINVAL; + if (rc < 0) { + CAM_ERR(CAM_CUSTOM, "Failed in parsing: %d", rc); goto free_res; } - in_port_info = memdup_user( - u64_to_user_ptr(custom_rsrc[i].res_hdl), - custom_rsrc[i].length); - - if (!IS_ERR(in_port_info)) { - if (in_port_info->num_out_res > - CAM_CUSTOM_HW_OUT_RES_MAX) { - CAM_ERR(CAM_CUSTOM, "too many output res %d", - in_port_info->num_out_res); - rc = -EINVAL; - kfree(in_port_info); - goto free_res; - } - - in_port_length = - sizeof(struct cam_custom_in_port_info) + - (in_port_info->num_out_res - 1) * - sizeof(struct cam_custom_out_port_info); - - if (in_port_length > custom_rsrc[i].length) { - CAM_ERR(CAM_CUSTOM, - "buffer size is not enough"); - rc = -EINVAL; - kfree(in_port_info); - goto free_res; - } - - gen_port_info = kzalloc( - sizeof(struct cam_isp_in_port_generic_info), - GFP_KERNEL); - if (gen_port_info == NULL) { - rc = -ENOMEM; - goto free_res; - } - - gen_port_info->data = kcalloc( - sizeof(struct cam_isp_out_port_generic_info), - in_port_info->num_out_res, GFP_KERNEL); - if (gen_port_info->data == NULL) { - kfree(gen_port_info); - gen_port_info = NULL; - rc = -ENOMEM; - goto free_res; - } - - cam_custom_hw_mgr_acquire_get_unified_dev_str( - in_port_info, gen_port_info); - - rc = cam_custom_mgr_acquire_hw_for_ctx(custom_ctx, - gen_port_info, &acquire_args->acquired_hw_id[i], - acquire_args->acquired_hw_path[i]); - - kfree(in_port_info); - if (gen_port_info != NULL) { - kfree(gen_port_info->data); - kfree(gen_port_info); - gen_port_info = NULL; - } - - if (rc) { - CAM_ERR(CAM_CUSTOM, "can not acquire resource"); - goto free_res; - } - } else { - CAM_ERR(CAM_CUSTOM, - "Copy from user failed with in_port = %pK", - in_port_info); - rc = -EFAULT; - goto free_res; + CAM_DBG(CAM_CUSTOM, "in_res_type %x", gen_port_info->res_type); + rc = cam_custom_mgr_acquire_hw_for_ctx(custom_ctx, + gen_port_info, &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + if (rc) { + CAM_ERR(CAM_CUSTOM, "can not acquire resource"); + goto free_mem; } + + kfree(gen_port_info->data); + kfree(gen_port_info); + gen_port_info = NULL; } custom_ctx->ctx_in_use = 1; acquire_args->ctxt_to_hw_map = custom_ctx; + cam_custom_hw_mgr_put_ctx(&custom_hw_mgr->used_ctx_list, &custom_ctx); CAM_DBG(CAM_CUSTOM, "Exit...(success)"); return 0; +free_mem: + kfree(gen_port_info->data); + kfree(gen_port_info); free_res: cam_custom_hw_mgr_release_hw_for_ctx(custom_ctx); -free_ctx: cam_custom_hw_mgr_put_ctx(&custom_hw_mgr->free_ctx_list, &custom_ctx); err: CAM_DBG(CAM_CUSTOM, "Exit...(rc=%d)", rc); diff --git a/include/uapi/media/cam_custom.h b/include/uapi/media/cam_custom.h index b36891f4a0dc..37edce171e4b 100644 --- a/include/uapi/media/cam_custom.h +++ b/include/uapi/media/cam_custom.h @@ -170,6 +170,23 @@ struct cam_custom_resource { uint64_t res_hdl; }; +/** + * struct cam_custom_acquire_hw_info - Custom acquire HW params + * + * @num_inputs : Number of inputs + * @input_info_size : Size of input info struct used + * @input_info_offset : Offset of input info from start of data + * @reserved : reserved + * @data : Start of data region + */ +struct cam_custom_acquire_hw_info { + uint32_t num_inputs; + uint32_t input_info_size; + uint32_t input_info_offset; + uint32_t reserved; + uint64_t data; +}; + /** * struct cam_custom_cmd_buf_type_1 - cmd buf type 1 * From dd1ac7b717dd142334ab76777db5603dd6b0e862 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Tue, 12 Nov 2019 12:22:39 -0800 Subject: [PATCH 173/790] msm: camera: req_mgr: Fix kmem_cache definition Add fixes to cam_req_mgr to include kmem_cache struct definitions. CRs-Fixed: 2554484 Change-Id: I368aa32e085431eff1976dfc09929e730d63b405 Signed-off-by: Karthik Jayakumar --- drivers/cam_req_mgr/Makefile | 2 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 6 +++++- drivers/cam_req_mgr/cam_req_mgr_timer.c | 4 +++- drivers/cam_req_mgr/cam_req_mgr_timer.h | 1 - 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/Makefile b/drivers/cam_req_mgr/Makefile index 50599d879255..8ecc89ffd8bb 100644 --- a/drivers/cam_req_mgr/Makefile +++ b/drivers/cam_req_mgr/Makefile @@ -4,7 +4,7 @@ ccflags-y += -I$(srctree)/techpack/camera/include/uapi ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(src) +ccflags-y += -I$(srctree)/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_core.o\ cam_req_mgr_dev.o \ diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index cdb2210a2efb..3f9db55ab9a1 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -6,12 +6,17 @@ #include #include #include +#include + +#include + #include #include #include #include #include #include + #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" #include "cam_req_mgr_core.h" @@ -19,7 +24,6 @@ #include "cam_mem_mgr.h" #include "cam_debug_util.h" #include "cam_common_util.h" -#include #define CAM_REQ_MGR_EVENT_MAX 30 diff --git a/drivers/cam_req_mgr/cam_req_mgr_timer.c b/drivers/cam_req_mgr/cam_req_mgr_timer.c index ba44534fa48d..eb2a6d599b0f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_timer.c +++ b/drivers/cam_req_mgr/cam_req_mgr_timer.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_timer.h" #include "cam_debug_util.h" +extern struct kmem_cache *g_cam_req_mgr_timer_cachep; + void crm_timer_reset(struct cam_req_mgr_timer *crm_timer) { if (!crm_timer) diff --git a/drivers/cam_req_mgr/cam_req_mgr_timer.h b/drivers/cam_req_mgr/cam_req_mgr_timer.h index be200f1b2693..d2e20498df9a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_timer.h +++ b/drivers/cam_req_mgr/cam_req_mgr_timer.h @@ -62,5 +62,4 @@ int crm_timer_init(struct cam_req_mgr_timer **timer, */ void crm_timer_exit(struct cam_req_mgr_timer **timer); -extern struct kmem_cache *g_cam_req_mgr_timer_cachep; #endif From 50e83233adebcbeafbc5d1463441806cda9952e7 Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Mon, 18 Nov 2019 14:00:11 -0800 Subject: [PATCH 174/790] msm: camera: sensor: Support for read operation Supporting read operation for sensor and sub modules OIS and actuator. CRs-Fixed: 2538801 Change-Id: I83ad154dd577d5a664c4d68792a90489e725fbfd Signed-off-by: Jigarkumar Zala Signed-off-by: Sureshnaidu Laveti --- .../cam_actuator/cam_actuator_core.c | 68 +++- .../cam_flash/cam_flash_core.c | 6 +- .../cam_sensor_module/cam_ois/cam_ois_core.c | 67 +++- .../cam_sensor/cam_sensor_core.c | 42 ++- .../cam_sensor/cam_sensor_dev.c | 4 +- .../cam_sensor_utils/cam_sensor_cmn_header.h | 13 +- .../cam_sensor_utils/cam_sensor_util.c | 308 +++++++++++++++++- .../cam_sensor_utils/cam_sensor_util.h | 7 +- 8 files changed, 495 insertions(+), 20 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index c609b8f85015..d886d8ebaecb 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -554,7 +554,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_sensor_i2c_command_parser( &a_ctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Failed:parse init settings: %d", @@ -612,7 +612,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_sensor_i2c_command_parser( &a_ctrl->io_master_info, i2c_reg_settings, - cmd_desc, 1); + cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Auto move lens parsing failed: %d", rc); @@ -643,7 +643,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_sensor_i2c_command_parser( &a_ctrl->io_master_info, i2c_reg_settings, - cmd_desc, 1); + cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Manual move lens parsing failed: %d", rc); @@ -662,6 +662,68 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, } cam_actuator_update_req_mgr(a_ctrl, csl_packet); break; + case CAM_ACTUATOR_PACKET_OPCODE_READ: { + struct cam_buf_io_cfg *io_cfg; + struct i2c_settings_array i2c_read_settings; + + if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_ACTUATOR, + "Not in right state to read actuator: %d", + a_ctrl->cam_act_state); + goto end; + } + CAM_DBG(CAM_ACTUATOR, "number of I/O configs: %d:", + csl_packet->num_io_configs); + if (csl_packet->num_io_configs == 0) { + CAM_ERR(CAM_ACTUATOR, "No I/O configs to process"); + rc = -EINVAL; + goto end; + } + + INIT_LIST_HEAD(&(i2c_read_settings.list_head)); + + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &csl_packet->payload + + csl_packet->io_configs_offset); + + if (io_cfg == NULL) { + CAM_ERR(CAM_ACTUATOR, "I/O config is invalid(NULL)"); + rc = -EINVAL; + goto end; + } + + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + i2c_read_settings.is_settings_valid = 1; + i2c_read_settings.request_id = 0; + rc = cam_sensor_i2c_command_parser(&a_ctrl->io_master_info, + &i2c_read_settings, + cmd_desc, 1, io_cfg); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "actuator read pkt parsing failed: %d", rc); + goto end; + } + + rc = cam_sensor_i2c_read_data( + &i2c_read_settings, + &a_ctrl->io_master_info); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, "cannot read data, rc:%d", rc); + delete_request(&i2c_read_settings); + goto end; + } + + rc = delete_request(&i2c_read_settings); + if (rc < 0) { + CAM_ERR(CAM_ACTUATOR, + "Failed in deleting the read settings"); + goto end; + } + break; + } default: CAM_ERR(CAM_ACTUATOR, "Wrong Opcode: %d", csl_packet->header.op_code & 0xFFFFFF); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 293d1422b393..063848104f63 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1070,7 +1070,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) rc = cam_sensor_i2c_command_parser( &fctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_FLASH, "pkt parsing failed: %d", rc); @@ -1150,7 +1150,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_sensor_i2c_command_parser( &fctrl->io_master_info, - i2c_reg_settings, cmd_desc, 1); + i2c_reg_settings, cmd_desc, 1, NULL); if (rc) { CAM_ERR(CAM_FLASH, "Failed in parsing i2c packets"); @@ -1181,7 +1181,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_sensor_i2c_command_parser( &fctrl->io_master_info, - i2c_reg_settings, cmd_desc, 1); + i2c_reg_settings, cmd_desc, 1, NULL); if (rc) { CAM_ERR(CAM_FLASH, "Failed in parsing i2c NRT packets"); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index b6035252a234..8ced8a28c309 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -540,7 +540,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) rc = cam_sensor_i2c_command_parser( &o_ctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "init parsing failed: %d", rc); @@ -557,7 +557,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) rc = cam_sensor_i2c_command_parser( &o_ctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "Calib parsing failed: %d", rc); @@ -629,7 +629,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, i2c_reg_settings, - cmd_desc, 1); + cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; @@ -648,6 +648,67 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) return rc; } break; + case CAM_OIS_PACKET_OPCODE_READ: { + struct cam_buf_io_cfg *io_cfg; + struct i2c_settings_array i2c_read_settings; + + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_OIS, + "Not in right state to read OIS: %d", + o_ctrl->cam_ois_state); + return rc; + } + CAM_DBG(CAM_OIS, "number of I/O configs: %d:", + csl_packet->num_io_configs); + if (csl_packet->num_io_configs == 0) { + CAM_ERR(CAM_OIS, "No I/O configs to process"); + rc = -EINVAL; + return rc; + } + + INIT_LIST_HEAD(&(i2c_read_settings.list_head)); + + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &csl_packet->payload + + csl_packet->io_configs_offset); + + if (io_cfg == NULL) { + CAM_ERR(CAM_OIS, "I/O config is invalid(NULL)"); + rc = -EINVAL; + return rc; + } + + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + i2c_read_settings.is_settings_valid = 1; + i2c_read_settings.request_id = 0; + rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, + &i2c_read_settings, + cmd_desc, 1, io_cfg); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS read pkt parsing failed: %d", rc); + return rc; + } + + rc = cam_sensor_i2c_read_data( + &i2c_read_settings, + &o_ctrl->io_master_info); + if (rc < 0) { + CAM_ERR(CAM_OIS, "cannot read data rc: %d", rc); + delete_request(&i2c_read_settings); + return rc; + } + + rc = delete_request(&i2c_read_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed in deleting the read settings"); + return rc; + } + break; + } default: CAM_ERR(CAM_OIS, "Invalid Opcode: %d", (csl_packet->header.op_code & 0xFFFFFF)); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 2fa447dbace4..6902122b3f66 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -87,6 +87,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, struct cam_control *ioctl_ctrl = NULL; struct cam_packet *csl_packet = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_buf_io_cfg *io_cfg = NULL; struct i2c_settings_array *i2c_reg_settings = NULL; size_t len_of_buff = 0; size_t remain_len = 0; @@ -187,7 +188,28 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, i2c_reg_settings->is_settings_valid = 1; break; } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_READ: { + i2c_reg_settings = &(i2c_data->read_settings); + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + CAM_DBG(CAM_SENSOR, "number of IO configs: %d:", + csl_packet->num_io_configs); + if (csl_packet->num_io_configs == 0) { + CAM_ERR(CAM_SENSOR, "No I/O configs to process"); + goto end; + } + + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &csl_packet->payload + + csl_packet->io_configs_offset); + + if (io_cfg == NULL) { + CAM_ERR(CAM_SENSOR, "I/O config is invalid(NULL)"); + goto end; + } + break; + } case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: { if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { @@ -239,7 +261,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_sensor_i2c_command_parser(&s_ctrl->io_master_info, - i2c_reg_settings, cmd_desc, 1); + i2c_reg_settings, cmd_desc, 1, io_cfg); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc); goto end; @@ -951,6 +973,24 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } s_ctrl->sensor_state = CAM_SENSOR_CONFIG; } + + if (s_ctrl->i2c_data.read_settings.is_settings_valid) { + rc = cam_sensor_i2c_read_data( + &s_ctrl->i2c_data.read_settings, + &s_ctrl->io_master_info); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "cannot read data: %d", rc); + delete_request(&s_ctrl->i2c_data.read_settings); + goto release_mutex; + } + rc = delete_request( + &s_ctrl->i2c_data.read_settings); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Fail in deleting the read settings"); + goto release_mutex; + } + } } break; default: diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index f847079c730a..765a1244a0aa 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include "cam_sensor_dev.h" @@ -179,6 +179,7 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); @@ -314,6 +315,7 @@ static int32_t cam_sensor_driver_platform_probe( INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index e43e8abe0809..563414e640cc 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -152,13 +152,15 @@ enum cam_sensor_packet_opcodes { CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE, CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF, + CAM_SENSOR_PACKET_OPCODE_SENSOR_READ, CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127 }; enum cam_actuator_packet_opcodes { CAM_ACTUATOR_PACKET_OPCODE_INIT, CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS, - CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS + CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS, + CAM_ACTUATOR_PACKET_OPCODE_READ }; enum cam_eeprom_packet_opcodes { @@ -168,7 +170,8 @@ enum cam_eeprom_packet_opcodes { enum cam_ois_packet_opcodes { CAM_OIS_PACKET_OPCODE_INIT, - CAM_OIS_PACKET_OPCODE_OIS_CONTROL + CAM_OIS_PACKET_OPCODE_OIS_CONTROL, + CAM_OIS_PACKET_OPCODE_READ }; enum msm_bus_perf_setting { @@ -218,7 +221,8 @@ enum cam_sensor_i2c_cmd_type { CAM_SENSOR_I2C_WRITE_RANDOM, CAM_SENSOR_I2C_WRITE_BURST, CAM_SENSOR_I2C_WRITE_SEQ, - CAM_SENSOR_I2C_READ, + CAM_SENSOR_I2C_READ_RANDOM, + CAM_SENSOR_I2C_READ_SEQ, CAM_SENSOR_I2C_POLL }; @@ -270,6 +274,8 @@ struct cam_sensor_i2c_reg_setting { enum camera_sensor_i2c_type addr_type; enum camera_sensor_i2c_type data_type; unsigned short delay; + uint8_t *read_buff; + uint32_t read_buff_len; }; struct cam_sensor_i2c_seq_reg { @@ -297,6 +303,7 @@ struct i2c_data_settings { struct i2c_settings_array config_settings; struct i2c_settings_array streamon_settings; struct i2c_settings_array streamoff_settings; + struct i2c_settings_array read_settings; struct i2c_settings_array *per_frame; }; diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 0d82579e7999..078e3e08657a 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -233,6 +233,134 @@ static int32_t cam_sensor_handle_continuous_write( return rc; } +static int32_t cam_sensor_get_io_buffer( + struct cam_buf_io_cfg *io_cfg, + struct cam_sensor_i2c_reg_setting *i2c_settings) +{ + uintptr_t buf_addr = 0x0; + size_t buf_size = 0; + int32_t rc = 0; + + if (io_cfg->direction == CAM_BUF_OUTPUT) { + rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0], + &buf_addr, &buf_size); + if ((rc < 0) || (!buf_addr)) { + CAM_ERR(CAM_SENSOR, + "invalid buffer, rc: %d, buf_addr: %pK", + rc, buf_addr); + return -EINVAL; + } + CAM_DBG(CAM_SENSOR, + "buf_addr: %pK, buf_size: %zu, offsetsize: %d", + (void *)buf_addr, buf_size, io_cfg->offsets[0]); + if (io_cfg->offsets[0] >= buf_size) { + CAM_ERR(CAM_SENSOR, + "invalid size:io_cfg->offsets[0]: %d, buf_size: %d", + io_cfg->offsets[0], buf_size); + return -EINVAL; + } + i2c_settings->read_buff = + (uint8_t *)buf_addr + io_cfg->offsets[0]; + i2c_settings->read_buff_len = + buf_size - io_cfg->offsets[0]; + } else { + CAM_ERR(CAM_SENSOR, "Invalid direction: %d", + io_cfg->direction); + rc = -EINVAL; + } + return rc; +} + +static int32_t cam_sensor_handle_random_read( + struct cam_cmd_i2c_random_rd *cmd_i2c_random_rd, + struct i2c_settings_array *i2c_reg_settings, + uint16_t *cmd_length_in_bytes, + int32_t *offset, + struct list_head **list, + struct cam_buf_io_cfg *io_cfg) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt = 0; + + i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, + cmd_i2c_random_rd->header.count); + if ((i2c_list == NULL) || + (i2c_list->i2c_settings.reg_setting == NULL)) { + CAM_ERR(CAM_SENSOR, + "Failed in allocating i2c_list: %pK", + i2c_list); + return -ENOMEM; + } + + rc = cam_sensor_get_io_buffer(io_cfg, &(i2c_list->i2c_settings)); + if (rc) { + CAM_ERR(CAM_SENSOR, "Failed to get read buffer: %d", rc); + } else { + *cmd_length_in_bytes = sizeof(struct i2c_rdwr_header) + + (sizeof(struct cam_cmd_read) * + (cmd_i2c_random_rd->header.count)); + i2c_list->op_code = CAM_SENSOR_I2C_READ_RANDOM; + i2c_list->i2c_settings.addr_type = + cmd_i2c_random_rd->header.addr_type; + i2c_list->i2c_settings.data_type = + cmd_i2c_random_rd->header.data_type; + i2c_list->i2c_settings.size = + cmd_i2c_random_rd->header.count; + + for (cnt = 0; cnt < (cmd_i2c_random_rd->header.count); + cnt++) { + i2c_list->i2c_settings.reg_setting[cnt].reg_addr = + cmd_i2c_random_rd->data_read[cnt].reg_data; + } + *offset = cnt; + *list = &(i2c_list->list); + } + + return rc; +} + +static int32_t cam_sensor_handle_continuous_read( + struct cam_cmd_i2c_continuous_rd *cmd_i2c_continuous_rd, + struct i2c_settings_array *i2c_reg_settings, + uint16_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list, + struct cam_buf_io_cfg *io_cfg) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt = 0; + + i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, 1); + if ((i2c_list == NULL) || + (i2c_list->i2c_settings.reg_setting == NULL)) { + CAM_ERR(CAM_SENSOR, + "Failed in allocating i2c_list: %pK", + i2c_list); + return -ENOMEM; + } + + rc = cam_sensor_get_io_buffer(io_cfg, &(i2c_list->i2c_settings)); + if (rc) { + CAM_ERR(CAM_SENSOR, "Failed to get read buffer: %d", rc); + } else { + *cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd); + i2c_list->op_code = CAM_SENSOR_I2C_READ_SEQ; + + i2c_list->i2c_settings.addr_type = + cmd_i2c_continuous_rd->header.addr_type; + i2c_list->i2c_settings.data_type = + cmd_i2c_continuous_rd->header.data_type; + i2c_list->i2c_settings.size = + cmd_i2c_continuous_rd->header.count; + i2c_list->i2c_settings.reg_setting[0].reg_addr = + cmd_i2c_continuous_rd->reg_addr; + + *offset = cnt; + *list = &(i2c_list->list); + } + + return rc; +} + static int cam_sensor_handle_slave_info( struct camera_io_master *io_master, uint32_t *cmd_buf) @@ -271,8 +399,11 @@ static int cam_sensor_handle_slave_info( /** * Name : cam_sensor_i2c_command_parser * Description : Parse CSL CCI packet and apply register settings - * Parameters : s_ctrl input/output sub_device - * arg input cam_control + * Parameters : io_master input master information + * i2c_reg_settings output register settings to fill + * cmd_desc input command description + * num_cmd_buffers input number of command buffers to process + * io_cfg input buffer details for read operation only * Description : * Handle multiple I2C RD/WR and WAIT cmd formats in one command * buffer, for example, a command buffer of m x RND_WR + 1 x HW_ @@ -283,11 +414,12 @@ int cam_sensor_i2c_command_parser( struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, struct cam_cmd_buf_desc *cmd_desc, - int32_t num_cmd_buffers) + int32_t num_cmd_buffers, + struct cam_buf_io_cfg *io_cfg) { int16_t rc = 0, i = 0; size_t len_of_buff = 0; - uintptr_t generic_ptr; + uintptr_t generic_ptr; uint16_t cmd_length_in_bytes = 0; size_t remain_len = 0; size_t tot_size = 0; @@ -472,7 +604,7 @@ int cam_sensor_i2c_command_parser( } case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: { if (remain_len - byte_cnt < - sizeof(struct cam_cmd_i2c_info)) { + sizeof(struct cam_cmd_i2c_info)) { CAM_ERR(CAM_SENSOR, "Not enough buffer space"); rc = -EINVAL; @@ -493,6 +625,88 @@ int cam_sensor_i2c_command_parser( byte_cnt += cmd_length_in_bytes; break; } + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD: { + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_random_rd *i2c_random_rd = + (struct cam_cmd_i2c_random_rd *)cmd_buf; + + if (remain_len - byte_cnt < + sizeof(struct cam_cmd_i2c_random_rd)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer space"); + rc = -EINVAL; + goto end; + } + + tot_size = sizeof(struct i2c_rdwr_header) + + (sizeof(struct cam_cmd_read) * + i2c_random_rd->header.count); + + if (tot_size > (remain_len - byte_cnt)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided %d, %d, %d", + tot_size, remain_len, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_random_read( + i2c_random_rd, + i2c_reg_settings, + &cmd_length_in_bytes, &j, &list, + io_cfg); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in random read %d", rc); + goto end; + } + + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + break; + } + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD: { + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_continuous_rd + *i2c_continuous_rd = + (struct cam_cmd_i2c_continuous_rd *)cmd_buf; + + if (remain_len - byte_cnt < + sizeof(struct cam_cmd_i2c_continuous_rd)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer space"); + rc = -EINVAL; + goto end; + } + + tot_size = + sizeof(struct cam_cmd_i2c_continuous_rd); + + if (tot_size > (remain_len - byte_cnt)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided %d, %d, %d", + tot_size, remain_len, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_continuous_read( + i2c_continuous_rd, + i2c_reg_settings, + &cmd_length_in_bytes, &j, &list, + io_cfg); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in continuous read %d", rc); + goto end; + } + + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + break; + } default: CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d", cmm_hdr->cmd_type); @@ -576,6 +790,90 @@ int cam_sensor_util_i2c_apply_setting( return rc; } +int32_t cam_sensor_i2c_read_data( + struct i2c_settings_array *i2c_settings, + struct camera_io_master *io_master_info) +{ + int32_t rc = 0; + struct i2c_settings_list *i2c_list; + uint32_t cnt = 0; + uint8_t *read_buff = NULL; + uint32_t buff_length = 0; + uint32_t read_length = 0; + + list_for_each_entry(i2c_list, + &(i2c_settings->list_head), list) { + read_buff = i2c_list->i2c_settings.read_buff; + buff_length = i2c_list->i2c_settings.read_buff_len; + if ((read_buff == NULL) || (buff_length == 0)) { + CAM_ERR(CAM_SENSOR, + "Invalid input buffer, buffer: %pK, length: %d", + read_buff, buff_length); + return -EINVAL; + } + + if (i2c_list->op_code == CAM_SENSOR_I2C_READ_RANDOM) { + read_length = i2c_list->i2c_settings.data_type * + i2c_list->i2c_settings.size; + if ((read_length > buff_length) || + (read_length < i2c_list->i2c_settings.size)) { + CAM_ERR(CAM_SENSOR, + "Invalid size, readLen:%d, bufLen:%d, size: %d", + read_length, buff_length, + i2c_list->i2c_settings.size); + return -EINVAL; + } + for (cnt = 0; cnt < (i2c_list->i2c_settings.size); + cnt++) { + struct cam_sensor_i2c_reg_array *reg_setting = + &(i2c_list->i2c_settings.reg_setting[cnt]); + rc = camera_io_dev_read(io_master_info, + reg_setting->reg_addr, + ®_setting->reg_data, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed: random read I2C settings: %d", + rc); + return rc; + } + if (i2c_list->i2c_settings.data_type < + CAMERA_SENSOR_I2C_TYPE_MAX) { + memcpy(read_buff, + ®_setting->reg_data, + i2c_list->i2c_settings.data_type); + read_buff += + i2c_list->i2c_settings.data_type; + } + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_READ_SEQ) { + read_length = i2c_list->i2c_settings.size; + if (read_length > buff_length) { + CAM_ERR(CAM_SENSOR, + "Invalid buffer size, readLen: %d, bufLen: %d", + read_length, buff_length); + return -EINVAL; + } + rc = camera_io_dev_read_seq( + io_master_info, + i2c_list->i2c_settings.reg_setting[0].reg_addr, + read_buff, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.size); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "failed: seq read I2C settings: %d", + rc); + return rc; + } + } + } + + return rc; +} + int32_t msm_camera_fill_vreg_params( struct cam_hw_soc_info *soc_info, struct cam_sensor_power_setting *power_setting, diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index c923efe61dc5..3600b5636cab 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -30,11 +30,16 @@ int msm_camera_pinctrl_init int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, - struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers); + struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers, + struct cam_buf_io_cfg *io_cfg); int cam_sensor_util_i2c_apply_setting(struct camera_io_master *io_master_info, struct i2c_settings_list *i2c_list); +int32_t cam_sensor_i2c_read_data( + struct i2c_settings_array *i2c_settings, + struct camera_io_master *io_master_info); + int32_t delete_request(struct i2c_settings_array *i2c_array); int cam_sensor_util_request_gpio_table( struct cam_hw_soc_info *soc_info, int gpio_en); From 8481d870a07492d5c00ec2879c256c9169a41ede Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 11 Nov 2019 17:52:04 -0800 Subject: [PATCH 175/790] msm: camera: isp: Update camera timestamps to ktime API Old API's returning struct timeval and struct timespec will be deprecated in future kernel versions as their tv_sec members will overflow in the year 2038 on 32-bit arhitectures. CRs-Fixed: 2564616 Change-Id: I6e3e37cf957daca992b66cad1134f49dd78961f5 Signed-off-by: Karthik Jayakumar --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 2 +- drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c9548fe42a6d..5e129731ec8d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2795,7 +2795,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->valid_acquired_hw = acquire_hw_info->num_inputs; - getnstimeofday64(&ife_ctx->ts); + ktime_get_real_ts64(&ife_ctx->ts); CAM_INFO(CAM_ISP, "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", total_pix_port, total_rdi_port, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 5c887c0ad329..64c7d0bcb50e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3004,7 +3004,7 @@ static int cam_ife_csid_get_time_stamp( CAM_IFE_CSID_QTIMER_DIV_FACTOR); if (!csid_hw->prev_boot_timestamp) { - get_monotonic_boottime64(&ts); + ktime_get_boottime_ts64(&ts); time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 11d6a602117c..a640353b6b5e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -381,7 +381,7 @@ void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp) { struct timespec ts; - get_monotonic_boottime(&ts); + ts = ktime_to_timespec(ktime_get_boottime()); time_stamp->mono_time.tv_sec = ts.tv_sec; time_stamp->mono_time.tv_usec = ts.tv_nsec/1000; } From 9a9e1a93e5bb12af0603684a54b174e30275f6ce Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 15 Sep 2019 19:40:24 -0700 Subject: [PATCH 176/790] msm: camera: cpas: Add cpas support for camera v580 platform Add register info. initial QoS settings info to program camera static settings for chipsets having camera v580. CRs-Fixed: 2528069 Change-Id: I6361140959ef64f35539612cf66604344adaea52 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 8 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 15 +- drivers/cam_cpas/cpas_top/cpastop_v580_100.h | 791 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 2 + 4 files changed, 814 insertions(+), 2 deletions(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v580_100.h diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 1f52e1993a5c..f91179b5aaa7 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -22,6 +22,7 @@ #include "cpastop_v175_120.h" #include "cpastop_v175_130.h" #include "cpastop_v480_100.h" +#include "cpastop_v580_100.h" struct cam_camnoc_info *camnoc_info; @@ -122,6 +123,10 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, (hw_caps->camera_version.minor == 8) && (hw_caps->camera_version.incr == 0)) { soc_info->hw_version = CAM_CPAS_TITAN_480_V100; + } else if ((hw_caps->camera_version.major == 5) && + (hw_caps->camera_version.minor == 8) && + (hw_caps->camera_version.incr == 0)) { + soc_info->hw_version = CAM_CPAS_TITAN_580_V100; } CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); @@ -624,6 +629,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_480_V100: camnoc_info = &cam480_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_580_V100: + camnoc_info = &cam580_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/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index a4d44a3feff6..7dbb5dd8fd38 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -20,6 +20,9 @@ * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR: Triggered if any error * detected in the IFE UBWC- * Stats encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR: Triggered if any error + * detected in the IFE UBWC- + * Stats 1 encoder instance * @CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error * detected in the IFE0 UBWC * encoder instance @@ -54,6 +57,8 @@ enum cam_camnoc_hw_irq_type { CAM_CAMNOC_IRQ_SLAVE_ERROR, CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR = CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR = CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR = @@ -86,8 +91,12 @@ enum cam_camnoc_hw_irq_type { * @CAM_CAMNOC_IFE02: Indicates IFE0, IFE2 HW connection to camnoc * @CAM_CAMNOC_IFE13: Indicates IFE1, IFE3 HW connection to camnoc * @CAM_CAMNOC_IFE_LINEAR: Indicates linear data from all IFEs to cammnoc - * @CAM_CAMNOC_IFE_UBWC_STATS: Indicates ubwc+stats from all IFEs to cammnoc - * @CAM_CAMNOC_IFE_RDI_WR: Indicates RDI write data from all IFEs to cammnoc + * @CAM_CAMNOC_IFE_UBWC_STATS: Indicates ubwc+stats from certain IFEs to cammnoc + * @CAM_CAMNOC_IFE_UBWC_STATS_1: Indicates ubwc+stats from certain + * IFEs to cammnoc + * @CAM_CAMNOC_IFE_RDI_WR: Indicates RDI write data from certain IFEs to cammnoc + * @CAM_CAMNOC_IFE_RDI_WR_1: Indicates RDI write data from certain + * IFEs to cammnoc * @CAM_CAMNOC_IFE_RDI_RD: Indicates RDI read data from all IFEs to cammnoc * @CAM_CAMNOC_IFE0123_RDI_WRITE: RDI write only for all IFEx * @CAM_CAMNOC_IFE0_NRDI_WRITE: IFE0 non-RDI write @@ -113,7 +122,9 @@ enum cam_camnoc_port_type { CAM_CAMNOC_IFE13, CAM_CAMNOC_IFE_LINEAR, CAM_CAMNOC_IFE_UBWC_STATS, + CAM_CAMNOC_IFE_UBWC_STATS_1, CAM_CAMNOC_IFE_RDI_WR, + CAM_CAMNOC_IFE_RDI_WR_1, CAM_CAMNOC_IFE_RDI_RD, CAM_CAMNOC_IFE0123_RDI_WRITE, CAM_CAMNOC_IFE0_NRDI_WRITE, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h new file mode 100644 index 000000000000..d79ca4af21bc --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h @@ -0,0 +1,791 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V580_100_H_ +#define _CPASTOP_V580_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v580_100_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3840, /* SBM_FAULTINEN0_LOW */ + .value = 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + 0x1000 | /* SBM_FAULTINEN0_LOW_PORT12_MASK */ + (TEST_IRQ_ENABLE ? + 0x40 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3848, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x3880, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x5 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v580_100_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = false, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x7008, /* ERL_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x7010, /* ERL_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x7018, /* ERL_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x1BA0, /* IFE_UBWC_STATS_0_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1B90, + /* IFE_UBWC_STATS_0_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1B98, /* IFE_UBWC_STATS_0_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2520, /* IPE1_BPS_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2510, /* IPE1_BPS_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2518, /* IPE1_BPS_RD_DECERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE0_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 = 0x1F20, /* IPE0_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1F10, /* IPE0_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1F18, /* IPE0_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 = 0x29A0, /* IPE_BPS_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2990, + /* IPE_BPS_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2998, /* IPE_BPS_WR_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = false, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* 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 = 0x40, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x1000, /* SBM_FAULTINSTATUS0_LOW_PORT12_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x77A0, /* IFE_UBWC_STATS_1_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x7790, + /* IFE_UBWC_STATS_1_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x7798, /* IFE_UBWC_STATS_1_ENCERRCLR_LOW */ + .value = 1, + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v580_100_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* CDM_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_RDI_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1048, /* IFE_RDI_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, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_RDI_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* IFE_RDI_WR_0_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1438, /* IFE_RDI_WR_0_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1440, /* IFE_RDI_WR_0_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_RDI_WR_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7430, /* IFE_RDI_WR_1_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7434, /* IFE_RDI_WR_1_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7438, /* IFE_RDI_WR_1_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7440, /* IFE_RDI_WR_1_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7448, /* IFE_RDI_WR_1_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_UBWC_STATS, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A34, + /* IFE_UBWC_STATS_0_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A38, /* IFE_UBWC_STATS_0_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A40, /* IFE_UBWC_STATS_0_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A48, /* IFE_UBWC_STATS_0_SAFELUT_LOW */ + .value = 0x000F, + }, + .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 = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_UBWC_STATS_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7630, /* IFE_UBWC_STATS_1_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7634, + /* IFE_UBWC_STATS_1_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7638, /* IFE_UBWC_STATS_1_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7640, /* IFE_UBWC_STATS_1_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7648, /* IFE_UBWC_STATS_1_SAFELUT_LOW */ + .value = 0x000F, + }, + .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 = 0x7788, /* IFE_UBWC_STATS_1_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE0_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E48, /* IPE0_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 = 0x1F08, /* IPE0_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE1_BPS_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2448, /* IPE1_BPS_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 = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2848, /* IPE_BPS_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 = 0x2988, /* IPE_BPS_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 = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E38, /* JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .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 = 0x3888, + .value = 0x100000, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam580_cpas100_err_logger_offsets = { + .mainctrl = 0x7008, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x7010, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x7020, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x7024, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x7028, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x702c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x7030, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x7034, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x7038, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x703c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam580_cpas100_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x3900, /* sbm_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam580_cpas100_camnoc_info = { + .specific = &cam_cpas_v580_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v580_100_camnoc_specific), + .irq_sbm = &cam_cpas_v580_100_irq_sbm, + .irq_err = &cam_cpas_v580_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v580_100_irq_err), + .err_logger = &cam580_cpas100_err_logger_offsets, + .errata_wa_list = &cam580_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP_V580_100_H_ */ + diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 7c551dfcf8a5..ebfdc70f9d59 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -46,6 +46,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_175_V120 = 0x175120, CAM_CPAS_TITAN_175_V130 = 0x175130, CAM_CPAS_TITAN_480_V100 = 0x480100, + CAM_CPAS_TITAN_580_V100 = 0x580100, CAM_CPAS_TITAN_MAX }; @@ -88,6 +89,7 @@ enum cam_cpas_hw_version { enum cam_camnoc_irq_type { CAM_CAMNOC_IRQ_SLAVE_ERROR, CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, From f5203c1106bd2d566b15083f9a1f3a9eba6c0aaf Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 2 Dec 2019 15:49:10 -0800 Subject: [PATCH 177/790] msm: camera: ope: Add uapi support to OPE driver OPE is camera offline engine, support is added to enable camera OPE hardware. CRs-Fixed: 2520602 Change-Id: I8b08ecb34323ee927f2be88707ad65ad2444447d Signed-off-by: Suresh Vankadara Signed-off-by: Ravikishore Pampana Signed-off-by: Pavan Kumar Chilamkurthi --- include/uapi/Kbuild | 1 + include/uapi/camera/media/cam_defs.h | 14 +- include/uapi/camera/media/cam_ope.h | 333 ++++++++++++++++++++++++ include/uapi/camera/media/cam_req_mgr.h | 1 + 4 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 include/uapi/camera/media/cam_ope.h diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild index f84da02a5a82..1062988cb673 100644 --- a/include/uapi/Kbuild +++ b/include/uapi/Kbuild @@ -16,3 +16,4 @@ header-y += camera/media/cam_lrme.h header-y += camera/media/cam_req_mgr.h header-y += camera/media/cam_sensor.h header-y += camera/media/cam_sync.h +header-y += camera/media/cam_ope.h diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index ce73b79f9590..23b4ba98f92a 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -178,6 +178,16 @@ struct cam_iommu_handle { #define CAM_FORMAT_ARGB_16 48 #define CAM_FORMAT_MAX 49 +/* Pixel Patterns */ +#define PIXEL_PATTERN_RGRGRG 0x0 +#define PIXEL_PATTERN_GRGRGR 0x1 +#define PIXEL_PATTERN_BGBGBG 0x2 +#define PIXEL_PATTERN_GBGBGB 0x3 +#define PIXEL_PATTERN_YCBYCR 0x4 +#define PIXEL_PATTERN_YCRYCB 0x5 +#define PIXEL_PATTERN_CBYCRY 0x6 +#define PIXEL_PATTERN_CRYCBY 0x7 + /* camera rotaion */ #define CAM_ROTATE_CW_0_DEGREE 0 #define CAM_ROTATE_CW_90_DEGREE 1 @@ -217,7 +227,9 @@ struct cam_iommu_handle { #define CAM_PACKET_DEV_IFE 15 #define CAM_PACKET_DEV_ICP 16 #define CAM_PACKET_DEV_LRME 17 -#define CAM_PACKET_DEV_MAX 18 +#define CAM_PACKET_DEV_TFE 18 +#define CAM_PACKET_DEV_OPE 19 +#define CAM_PACKET_DEV_MAX 20 /* Register base type */ #define CAM_REG_DUMP_BASE_TYPE_ISP_LEFT 1 diff --git a/include/uapi/camera/media/cam_ope.h b/include/uapi/camera/media/cam_ope.h new file mode 100644 index 000000000000..7b4ed57b778e --- /dev/null +++ b/include/uapi/camera/media/cam_ope.h @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_OPE_H__ +#define __UAPI_OPE_H__ + +#include "cam_defs.h" +#include "cam_cpas.h" + +#define OPE_DEV_NAME_SIZE 128 + +/* OPE HW TYPE */ +#define OPE_HW_TYPE_OPE 0x1 +#define OPE_HW_TYPE_OPE_CDM 0x2 +#define OPE_HW_TYPE_MAX 0x3 + +/* OPE Device type */ +#define OPE_DEV_TYPE_OPE_RT 0x1 +#define OPE_DEV_TYPE_OPE_NRT 0x2 +#define OPE_DEV_TYPE_OPE_SEMI_RT 0x3 +#define OPE_DEV_TYPE_MAX 0x4 + +/* OPE Input Res Ports */ +#define OPE_IN_RES_FULL 0x1 +#define OPE_IN_RES_MAX OPE_IN_RES_FULL + +/* OPE Output Res Ports */ +#define OPE_OUT_RES_VIDEO 0x1 +#define OPE_OUT_RES_DISP 0x2 +#define OPE_OUT_RES_ARGB 0x3 +#define OPE_OUT_RES_STATS_RS 0x4 +#define OPE_OUT_RES_STATS_IHIST 0x5 +#define OPE_OUT_RES_STATS_LTM 0x6 +#define OPE_OUT_RES_MAX OPE_OUT_RES_STATS_LTM + +/* OPE packet opcodes */ +#define OPE_OPCODE_CONFIG 0x1 + +/* OPE Command Buffer Scope */ +#define OPE_CMD_BUF_SCOPE_BATCH 0x1 +#define OPE_CMD_BUF_SCOPE_FRAME 0x2 +#define OPE_CMD_BUF_SCOPE_PASS 0x3 +#define OPE_CMD_BUF_SCOPE_STRIPE 0x4 + +/* OPE Command Buffer Types */ +#define OPE_CMD_BUF_TYPE_DIRECT 0x1 +#define OPE_CMD_BUF_TYPE_INDIRECT 0x2 + +/* OPE Command Buffer Usage */ +#define OPE_CMD_BUF_UMD 0x1 +#define OPE_CMD_BUF_KMD 0x2 +#define OPE_CMD_BUF_DEBUG 0x3 + +/* OPE Single/Double Buffered */ +#define OPE_CMD_BUF_SINGLE_BUFFERED 0x1 +#define OPE_CMD_BUF_DOUBLE_BUFFERED 0x2 + +/* Command meta types */ +#define OPE_CMD_META_GENERIC_BLOB 0x1 + +/* Generic blob types */ +#define OPE_CMD_GENERIC_BLOB_CLK_V2 0x1 + +/* Stripe location */ +#define OPE_STRIPE_FULL 0x0 +#define OPE_STRIPE_LEFT 0x1 +#define OPE_STRIPE_RIGHT 0x2 +#define OPE_STRIPE_MIDDLE 0x3 + +#define OPE_MAX_CMD_BUFS 64 +#define OPE_MAX_IO_BUFS (OPE_OUT_RES_MAX + OPE_IN_RES_MAX) +#define OPE_MAX_PASS 1 +#define OPE_MAX_PLANES 2 +#define OPE_MAX_STRIPES 32 +#define OPE_MAX_BATCH_SIZE 16 + +/** + * struct ope_stripe_info - OPE stripe Info + * + * @offset: Offset in Bytes + * @x_init: X_init + * @stripe_location: Stripe location (OPE_STRIPE_XXX) + * @width: Width of a stripe + * @disable_bus: Flag to disable BUS master + * @reserved: Reserved + * + */ +struct ope_stripe_info { + uint32_t offset; + uint32_t x_init; + uint32_t stripe_location; + uint32_t width; + uint32_t disable_bus; + uint32_t reserved; +}; + +/** + * struct ope_io_buf_info - OPE IO buffers meta + * + * @direction: Direction of a buffer of a port(Input/Output) + * @resource_type: Port type + * @num_planes: Number of planes for a port + * @reserved: Reserved + * @num_stripes: Stripes per plane + * @mem_handle: Memhandles of each Input/Output Port + * @plane_offset: Offsets of planes + * @length: Length of a plane buffer + * @plane_stride: Plane stride + * @height: Height of a plane buffer + * @format: Format + * @fence: Fence of a Port + * @stripe_info: Stripe Info + * + */ +struct ope_io_buf_info { + uint32_t direction; + uint32_t resource_type; + uint32_t num_planes; + uint32_t reserved; + uint32_t num_stripes[OPE_MAX_PLANES]; + uint32_t mem_handle[OPE_MAX_PLANES]; + uint32_t plane_offset[OPE_MAX_PLANES]; + uint32_t length[OPE_MAX_PLANES]; + uint32_t plane_stride[OPE_MAX_PLANES]; + uint32_t height[OPE_MAX_PLANES]; + uint32_t format; + uint32_t fence; + struct ope_stripe_info stripe_info[OPE_MAX_PLANES][OPE_MAX_STRIPES]; +}; + +/** + * struct ope_frame_set - OPE frameset + * + * @num_io_bufs: Number of I/O buffers + * @reserved: Reserved + * @io_buf: IO buffer info for all Input and Output ports + * + */ +struct ope_frame_set { + uint32_t num_io_bufs; + uint32_t reserved; + struct ope_io_buf_info io_buf[OPE_MAX_IO_BUFS]; +}; + +/** + * struct ope_cmd_buf_info - OPE command buffer meta + * + * @mem_handle: Memory handle for command buffer + * @offset: Offset of a command buffer + * @size: Size of command buffer + * @length: Length of a command buffer + * @cmd_buf_scope : Scope of a command buffer (OPE_CMD_BUF_SCOPE_XXX) + * @type: Command buffer type (OPE_CMD_BUF_TYPE_XXX) + * @cmd_buf_usage: Usage of command buffer ( OPE_CMD_BUF_USAGE_XXX) + * @stripe_idx: Stripe index in a req, It is valid for SCOPE_STRIPE + * @cmd_buf_pass_idx: Pass index + * @prefetch_disable: Prefecth disable flag + * + */ + +struct ope_cmd_buf_info { + uint32_t mem_handle; + uint32_t offset; + uint32_t size; + uint32_t length; + uint32_t cmd_buf_scope; + uint32_t type; + uint32_t cmd_buf_usage; + uint32_t cmd_buf_buffered; + uint32_t stripe_idx; + uint32_t cmd_buf_pass_idx; + uint32_t prefetch_disable; +}; + +/** + * struct ope_packet_payload - payload for a request + * + * @num_cmd_bufs: Number of command buffers + * @batch_size: Batch size in HFR mode + * @ope_cmd_buf_info: Command buffer meta data + * @ope_io_buf_info: Io buffer Info + * + */ +struct ope_frame_process { + uint32_t num_cmd_bufs[OPE_MAX_BATCH_SIZE]; + uint32_t batch_size; + struct ope_cmd_buf_info cmd_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_CMD_BUFS]; + struct ope_frame_set frame_set[OPE_MAX_BATCH_SIZE]; +}; + +/** + * struct ope_clk_bw_request_v2 - clock and bandwidth for a request + * + * @budget_ns: Time required to process frame + * @frame_cycles: Frame cycles needed to process the frame + * @rt_flag: Flag to indicate real time stream + * @reserved: For memory alignment + * @axi_path: Per path vote info for OPE + * + */ +struct ope_clk_bw_request_v2 { + uint64_t budget_ns; + uint32_t frame_cycles; + uint32_t rt_flag; + uint32_t reserved; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[1]; +}; + +/** + * struct ope_hw_ver - Device information for OPE + * + * This is used to get device version info of + * OPE, CDM and use this info in CAM_QUERY_CAP IOCTL + * + * @hw_type: Hardware type for the cap info(OPE_HW_TYPE_XXX) + * @reserved: Reserved field + * @hw_ver: Major, minor and incr values of a hardware version + * + */ +struct ope_hw_ver { + uint32_t hw_type; + uint32_t reserved; + struct cam_hw_version hw_ver; +}; + +/** + * struct ope_query_cap_cmd - OPE query device capability payload + * + * @dev_iommu_handle: OPE iommu handles for secure/non secure modes + * @cdm_iommu_handle: CDM iommu handles for secure/non secure modes + * @num_ope: Number of OPEs + * @reserved: Reserved Parameter + * @hw_ver: Hardware capability array + */ +struct ope_query_cap_cmd { + struct cam_iommu_handle dev_iommu_handle; + struct cam_iommu_handle cdm_iommu_handle; + uint32_t num_ope; + uint32_t reserved; + struct ope_hw_ver hw_ver[OPE_DEV_TYPE_MAX]; +}; + +/** + * struct ope_out_res_info - OPE Output resource info + * + * @res_id: Resource ID + * @format: Output resource format + * @width: Output width + * @height: Output Height + * @alignment: Alignment + * @packer_format: Packer format + * @subsample_period: Subsample period in HFR + * @subsample_pattern: Subsample pattern in HFR + * @pixel_pattern: Pixel pattern + * @reserved: Reserved Parameter + * + */ +struct ope_out_res_info { + uint32_t res_id; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t alignment; + uint32_t packer_format; + uint32_t subsample_period; + uint32_t subsample_pattern; + uint32_t pixel_pattern; + uint32_t reserved; +}; + +/** + * struct ope_in_res_info - OPE Input resource info + * + * @res_id: Resource ID + * @format: Input resource format + * @width: Input width + * @height: Input Height + * @pixel_pattern: Pixel pattern + * @alignment: Alignment + * @unpacker_format: Unpacker format + * @max_stripe_size: Max stripe size supported for this instance configuration + * @fps: Frames per second + * @reserved: Reserved Parameter + * + */ +struct ope_in_res_info { + uint32_t res_id; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t pixel_pattern; + uint32_t alignment; + uint32_t unpacker_format; + uint32_t max_stripe_size; + uint32_t fps; + uint32_t reserved; +}; + +/** + * struct ope_acquire_dev_info - OPE Acquire Info + * + * @hw_type: OPE HW Types (OPE) + * @dev_type: Nature of Device Instance (RT/NRT) + * @dev_name: Name of Device Instance + * @nrt_stripes_for_arb: Program num stripes in OPE CDM for NRT device + * before setting ARB bit + * @secure_mode: Mode of Device operation (Secure or Non Secure) + * @batch_size: Batch size + * @num_in_res: Number of input resources (OPE_IN_RES_XXX) + * @in_res: Input resource info + * @num_out_res: Number of output resources (OPE_OUT_RES_XXX) + * @reserved: Reserved Parameter + * @out_res: Output resource info + * + */ +struct ope_acquire_dev_info { + uint32_t hw_type; + uint32_t dev_type; + char dev_name[OPE_DEV_NAME_SIZE]; + uint32_t nrt_stripes_for_arb; + uint32_t secure_mode; + uint32_t batch_size; + uint32_t num_in_res; + struct ope_in_res_info in_res[OPE_IN_RES_MAX]; + uint32_t num_out_res; + uint32_t reserved; + struct ope_out_res_info out_res[OPE_OUT_RES_MAX]; +} __attribute__((__packed__)); + +#endif /* __UAPI_OPE_H__ */ diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index adfc1cb32f78..0e38f5ec44e5 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -30,6 +30,7 @@ #define CAM_EEPROM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 12) #define CAM_OIS_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 13) #define CAM_CUSTOM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 14) +#define CAM_OPE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 15) /* cam_req_mgr hdl info */ #define CAM_REQ_MGR_HDL_IDX_POS 8 From 02279f7bf6b0b158058c3feb9163b0bd448ef060 Mon Sep 17 00:00:00 2001 From: Suresh Vankadara Date: Fri, 16 Aug 2019 15:57:24 +0530 Subject: [PATCH 178/790] msm: camera: ope: Add dynamic clock support for OPE Dynamic clock and bandwidth support is added to OPE. CRs-Fixed: 2520602 Change-Id: I4ba4bb3b24e4ef47dea35810564cae69912ef72e Signed-off-by: Suresh Vankadara Signed-off-by: Pavan Kumar Chilamkurthi --- include/uapi/camera/media/cam_cpas.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/uapi/camera/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h index b85ab068f9e8..2a44d93497b4 100644 --- a/include/uapi/camera/media/cam_cpas.h +++ b/include/uapi/camera/media/cam_cpas.h @@ -43,6 +43,15 @@ #define CAM_AXI_PATH_DATA_IPE_MAX_OFFSET \ (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 31) +#define CAM_AXI_PATH_DATA_OPE_START_OFFSET 64 +#define CAM_AXI_PATH_DATA_OPE_RD_IN (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 0) +#define CAM_AXI_PATH_DATA_OPE_RD_REF (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 1) +#define CAM_AXI_PATH_DATA_OPE_WR_VID (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 2) +#define CAM_AXI_PATH_DATA_OPE_WR_DISP (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 3) +#define CAM_AXI_PATH_DATA_OPE_WR_REF (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 4) +#define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ + (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) + #define CAM_AXI_PATH_DATA_ALL 256 /** From 6b265f17508a85b0a5ec726275980773e76b3060 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 2 Dec 2019 15:44:37 -0800 Subject: [PATCH 179/790] msm: camera: tfe: Add uapi support to TFE driver TFE is thin front end hardware that capture and process the real time image. Support is added to enable the TFE hardware. CRs-Fixed: 2545590 Change-Id: Ie8efef77fabeeea28d70380c398089e6351e35e3 Signed-off-by: Ravikishore Pampana Signed-off-by: Pavan Kumar Chilamkurthi --- include/uapi/Kbuild | 2 + include/uapi/camera/media/cam_isp_tfe.h | 35 +++ include/uapi/camera/media/cam_req_mgr.h | 1 + include/uapi/camera/media/cam_tfe.h | 391 ++++++++++++++++++++++++ 4 files changed, 429 insertions(+) create mode 100644 include/uapi/camera/media/cam_isp_tfe.h create mode 100644 include/uapi/camera/media/cam_tfe.h diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild index 1062988cb673..7aa1e88b6a77 100644 --- a/include/uapi/Kbuild +++ b/include/uapi/Kbuild @@ -17,3 +17,5 @@ header-y += camera/media/cam_req_mgr.h header-y += camera/media/cam_sensor.h header-y += camera/media/cam_sync.h header-y += camera/media/cam_ope.h +header-y += camera/media/cam_isp_tfe.h +header-y += camera/media/cam_tfe.h diff --git a/include/uapi/camera/media/cam_isp_tfe.h b/include/uapi/camera/media/cam_isp_tfe.h new file mode 100644 index 000000000000..fc716311367d --- /dev/null +++ b/include/uapi/camera/media/cam_isp_tfe.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_ISP_TFE_H__ +#define __UAPI_CAM_ISP_TFE_H__ + +/* TFE output port resource id number */ +#define CAM_ISP_TFE_OUT_RES_BASE 0x1 + +#define CAM_ISP_TFE_OUT_RES_FULL (CAM_ISP_TFE_OUT_RES_BASE + 0) +#define CAM_ISP_TFE_OUT_RES_RAW_DUMP (CAM_ISP_TFE_OUT_RES_BASE + 1) +#define CAM_ISP_TFE_OUT_RES_PDAF (CAM_ISP_TFE_OUT_RES_BASE + 2) +#define CAM_ISP_TFE_OUT_RES_RDI_0 (CAM_ISP_TFE_OUT_RES_BASE + 3) +#define CAM_ISP_TFE_OUT_RES_RDI_1 (CAM_ISP_TFE_OUT_RES_BASE + 4) +#define CAM_ISP_TFE_OUT_RES_RDI_2 (CAM_ISP_TFE_OUT_RES_BASE + 5) +#define CAM_ISP_TFE_OUT_RES_STATS_HDR_BE (CAM_ISP_TFE_OUT_RES_BASE + 6) +#define CAM_ISP_TFE_OUT_RES_STATS_HDR_BHIST (CAM_ISP_TFE_OUT_RES_BASE + 7) +#define CAM_ISP_TFE_OUT_RES_STATS_TL_BG (CAM_ISP_TFE_OUT_RES_BASE + 8) +#define CAM_ISP_TFE_OUT_RES_STATS_BF (CAM_ISP_TFE_OUT_RES_BASE + 9) +#define CAM_ISP_TFE_OUT_RES_STATS_AWB_BG (CAM_ISP_TFE_OUT_RES_BASE + 10) +#define CAM_ISP_TFE_OUT_RES_MAX (CAM_ISP_TFE_OUT_RES_BASE + 11) + + +/* TFE input port resource type */ +#define CAM_ISP_TFE_IN_RES_BASE 0x1 + +#define CAM_ISP_TFE_IN_RES_TPG (CAM_ISP_TFE_IN_RES_BASE + 0) +#define CAM_ISP_TFE_IN_RES_PHY_0 (CAM_ISP_TFE_IN_RES_BASE + 1) +#define CAM_ISP_TFE_IN_RES_PHY_1 (CAM_ISP_TFE_IN_RES_BASE + 2) +#define CAM_ISP_TFE_IN_RES_PHY_2 (CAM_ISP_TFE_IN_RES_BASE + 3) +#define CAM_ISP_TFE_IN_RES_MAX (CAM_ISP_TFE_IN_RES_BASE + 4) + +#endif /* __UAPI_CAM_ISP_TFE_H__ */ diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 0e38f5ec44e5..934e9bdf4bb0 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -31,6 +31,7 @@ #define CAM_OIS_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 13) #define CAM_CUSTOM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 14) #define CAM_OPE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 15) +#define CAM_TFE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 16) /* cam_req_mgr hdl info */ #define CAM_REQ_MGR_HDL_IDX_POS 8 diff --git a/include/uapi/camera/media/cam_tfe.h b/include/uapi/camera/media/cam_tfe.h new file mode 100644 index 000000000000..9055f7fbe55c --- /dev/null +++ b/include/uapi/camera/media/cam_tfe.h @@ -0,0 +1,391 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_TFE_H__ +#define __UAPI_CAM_TFE_H__ + +#include "cam_defs.h" +#include "cam_isp_tfe.h" +#include "cam_cpas.h" + + +/* ISP TFE driver name */ +#define CAM_ISP_TFE_DEV_NAME "cam-isp" + +/* HW type */ +#define CAM_ISP_TFE_HW_BASE 0 +#define CAM_ISP_TFE_HW_CSID 1 +#define CAM_ISP_TFE_HW_TFE 2 +#define CAM_ISP_TFE_HW_MAX 3 + +/* Color Pattern */ +#define CAM_ISP_TFE_PATTERN_BAYER_RGRGRG 0 +#define CAM_ISP_TFE_PATTERN_BAYER_GRGRGR 1 +#define CAM_ISP_TFE_PATTERN_BAYER_BGBGBG 2 +#define CAM_ISP_TFE_PATTERN_BAYER_GBGBGB 3 +#define CAM_ISP_TFE_PATTERN_YUV_YCBYCR 4 +#define CAM_ISP_TFE_PATTERN_YUV_YCRYCB 5 +#define CAM_ISP_TFE_PATTERN_YUV_CBYCRY 6 +#define CAM_ISP_TFE_PATTERN_YUV_CRYCBY 7 +#define CAM_ISP_TFE_PATTERN_MAX 8 + +/* Usage Type */ +#define CAM_ISP_TFE_IN_RES_USAGE_SINGLE 0 +#define CAM_ISP_TFE_IN_RES_USAGE_DUAL 1 +#define CAM_ISP_TFE_IN_RES_USAGE_MAX 2 + +/* Resource ID */ +#define CAM_ISP_TFE_RES_ID_PORT 0 +#define CAM_ISP_TFE_RES_ID_MAX 1 + +/* Resource Type - Type of resource for the resource id + * defined in cam_isp_tfe.h + */ + +/* Lane Type in input resource for Port */ +#define CAM_ISP_TFE_IN_LANE_TYPE_DPHY 0 +#define CAM_ISP_TFE_IN_LANE_TYPE_CPHY 1 +#define CAM_ISP_TFE_IN_LANE_TYPE_MAX 2 + +/* ISP TFE packet opcode */ +#define CAM_ISP_TFE_PACKET_OP_BASE 0 +#define CAM_ISP_TFE_PACKET_INIT_DEV 1 +#define CAM_ISP_TFE_PACKET_CONFIG_DEV 2 +#define CAM_ISP_TFE_PACKET_OP_MAX 3 + +/* ISP TFE packet meta_data type for command buffer */ +#define CAM_ISP_TFE_PACKET_META_BASE 0 +#define CAM_ISP_TFE_PACKET_META_LEFT 1 +#define CAM_ISP_TFE_PACKET_META_RIGHT 2 +#define CAM_ISP_TFE_PACKET_META_COMMON 3 +#define CAM_ISP_TFE_PACKET_META_DUAL_CONFIG 4 +#define CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_COMMON 5 +#define CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST 6 +#define CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH 7 +#define CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR 8 + +/* ISP TFE Generic Cmd Buffer Blob types */ +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_HFR_CONFIG 0 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_CONFIG_V2 2 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 3 + +/* DSP mode */ +#define CAM_ISP_TFE_DSP_MODE_NONE 0 +#define CAM_ISP_TFE_DSP_MODE_ONE_WAY 1 +#define CAM_ISP_TFE_DSP_MODE_ROUND 2 + +/* Per Path Usage Data */ +#define CAM_ISP_TFE_USAGE_INVALID 0 +#define CAM_ISP_TFE_USAGE_LEFT_PX 1 +#define CAM_ISP_TFE_USAGE_RIGHT_PX 2 +#define CAM_ISP_TFE_USAGE_RDI 3 + +/* Query devices */ +/** + * struct cam_isp_tfe_dev_cap_info - A cap info for particular hw type + * + * @hw_type: Hardware type for the cap info + * @reserved: reserved field for alignment + * @hw_version: Hardware version + * + */ +struct cam_isp_tfe_dev_cap_info { + uint32_t hw_type; + uint32_t reserved; + struct cam_hw_version hw_version; +}; + +/** + * struct cam_isp_tfe_query_cap_cmd - ISP TFE query device + * capability payload + * + * @device_iommu: returned iommu handles for device + * @cdm_iommu: returned iommu handles for cdm + * @num_dev: returned number of device capabilities + * @reserved: reserved field for alignment + * @dev_caps: returned device capability array + * + */ +struct cam_isp_tfe_query_cap_cmd { + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + int32_t num_dev; + uint32_t reserved; + struct cam_isp_tfe_dev_cap_info dev_caps[CAM_ISP_TFE_HW_MAX]; +}; + +/* Acquire Device */ +/** + * struct cam_isp_tfe_out_port_info - An output port resource info + * + * @res_id: output resource id defined in file + * cam_isp_tfe.h + * @format: output format of the resource + * @width: output width in pixels + * @height: output height in lines + * @stride: output stride + * @comp_grp_id: composite group id for the resource. + * @secure_mode: flag to tell if output should be run in secure + * mode or not. See cam_defs.h for definition + * @wm_mode: wm mode + * @reserved: reserved field for alignment + * + */ +struct cam_isp_tfe_out_port_info { + uint32_t res_id; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t comp_grp_id; + uint32_t secure_mode; + uint32_t wm_mode; + uint32_t reserved; +}; + +/** + * struct cam_isp_tfe_in_port_info - An input port resource info + * + * @res_id: input resource id CAM_ISP_TFE_IN_RES_XXX + * @lane_type: lane type: c-phy or d-phy. + * @lane_num: active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * @vc: input virtual channel number + * @dt: input data type number + * @format: input format + * @pix_pattern: pixel pattern + * @usage_type: whether dual tfe is required + * @left_start: left input start offset in pixels + * @left_end: left input stop offset in pixels + * @left_width: left input width in pixels + * @right_start: right input start offset in pixels. + * Only for Dual TFE + * @right_end: right input stop offset in + * pixels. Only for Dual TFE + * @right_width: right input width in pixels. + * Only for dual TFE + * @line_start: top of the line number + * @line_stop: bottome of the line number + * @height: input height in lines + * @batch_size: batch size for HFR mode + * @dsp_mode: DSP stream mode(Defines as + * CAM_ISP_TFE_DSP_MODE_*) + * @sensor_width: sensor width + * @sensor_height: sensor height + * @hbi_value: sensor HBI value + * @vbi_value: sensor VBI value + * @sensor_fps: sensor fps + * @init_frame_drop init frame drop value. + * @num_out_res: number of the output resource associated + * @data: payload that contains the output resources, + * array of cam_isp_tfe_out_port_info data + * + */ +struct cam_isp_tfe_in_port_info { + uint32_t res_id; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; + uint32_t vc; + uint32_t dt; + uint32_t format; + uint32_t pix_pattern; + uint32_t usage_type; + uint32_t left_start; + uint32_t left_end; + uint32_t left_width; + uint32_t right_start; + uint32_t right_end; + uint32_t right_width; + uint32_t line_start; + uint32_t line_end; + uint32_t height; + uint32_t batch_size; + uint32_t dsp_mode; + uint32_t sensor_width; + uint32_t sensor_height; + uint32_t sensor_hbi; + uint32_t sensor_vbi; + uint32_t sensor_fps; + uint32_t init_frame_drop; + uint32_t num_out_res; + struct cam_isp_tfe_out_port_info data[1]; +}; + +/** + * struct cam_isp_tfe_resource - A resource bundle + * + * @resoruce_id: resource id for the resource bundle + * @length: length of the while resource blob + * @handle_type: type of the resource handle + * @reserved: reserved field for alignment + * @res_hdl: resource handle that points to the + * resource array + * + */ +struct cam_isp_tfe_resource { + uint32_t resource_id; + uint32_t length; + uint32_t handle_type; + uint32_t reserved; + uint64_t res_hdl; +}; + +/** + * struct cam_isp_tfe_port_hfr_config - HFR configuration for + * this port + * + * @resource_type: Resource type + * @subsample_pattern: Subsample pattern. Used in HFR mode. It + * should be consistent with batchSize and + * CAMIF programming. + * @subsample_period: Subsample period. Used in HFR mode. It + * should be consistent with batchSize and + * CAMIF programming. + * @framedrop_pattern: Framedrop pattern + * @framedrop_period: Framedrop period + * @reserved: Reserved for alignment + */ +struct cam_isp_tfe_port_hfr_config { + uint32_t resource_type; + uint32_t subsample_pattern; + uint32_t subsample_period; + uint32_t framedrop_pattern; + uint32_t framedrop_period; + uint32_t reserved; +} __attribute__((packed)); + +/** + * struct cam_isp_tfe_resource_hfr_config - Resource HFR + * configuration + * + * @num_ports: Number of ports + * @reserved: Reserved for alignment + * @port_hfr_config: HFR configuration for each IO port + */ +struct cam_isp_tfe_resource_hfr_config { + uint32_t num_ports; + uint32_t reserved; + struct cam_isp_tfe_port_hfr_config port_hfr_config[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_tfe_dual_stripe_config - stripe config per bus + * client + * + * @offset: Start horizontal offset relative to + * output buffer + * @width: Width of the stripe in pixels + * @port_id: Port id of ISP TFE output + * @reserved: Reserved for alignment + * + */ +struct cam_isp_tfe_dual_stripe_config { + uint32_t offset; + uint32_t width; + uint32_t port_id; + uint32_t reserved; +}; + +/** + * struct cam_isp_tfe_dual_config - dual isp configuration + * + * @num_ports Number of isp output ports + * @reserved Reserved field for alignment + * @stripes: Stripe information + * + */ +struct cam_isp_tfe_dual_config { + uint32_t num_ports; + uint32_t reserved; + struct cam_isp_tfe_dual_stripe_config stripes[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_tfe_clock_config - Clock configuration + * + * @usage_type: Usage type (Single/Dual) + * @num_rdi: Number of RDI votes + * @left_pix_hz: Pixel Clock for Left ISP + * @right_pix_hz: Pixel Clock for Right ISP + * valid only if Dual + * @rdi_hz: RDI Clock. ISP TFE clock will be + * max of RDI and PIX clocks. For a + * particular context which ISP TFE + * HW the RDI is allocated to is + * not known to UMD. Hence pass the + * clock and let KMD decide. + */ +struct cam_isp_tfe_clock_config { + uint32_t usage_type; + uint32_t num_rdi; + uint64_t left_pix_hz; + uint64_t right_pix_hz; + uint64_t rdi_hz[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_tfe_csid_clock_config - CSID clock + * configuration + * + * @csid_clock CSID clock + * @csi_phy_clock Phy clock valid if tpg is selected + */ +struct cam_isp_tfe_csid_clock_config { + uint64_t csid_clock; + uint64_t phy_clock; +} __attribute__((packed)); + +/** + * struct cam_isp_tfe_bw_config_v2 - Bandwidth configuration + * + * @usage_type: Usage type (Single/Dual) + * @num_paths: Number of axi data paths + * @axi_path Per path vote info + */ +struct cam_isp_tfe_bw_config_v2 { + uint32_t usage_type; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[1]; +} __attribute__((packed)); + +/** + * struct cam_isp_acquire_hw_info - ISP TFE acquire HW params + * + * @common_info_version : Version of common info struct used + * @common_info_size : Size of common info struct used + * @common_info_offset : Offset of common info from start of data + * @num_inputs : Number of inputs + * @input_info_version : Version of input info struct used + * @input_info_size : Size of input info struct used + * @input_info_offset : Offset of input info from start of data + * @data : Data pointer to point the cam_isp_tfe_in_port_info + * structure + */ +struct cam_isp_tfe_acquire_hw_info { + uint16_t common_info_version; + uint16_t common_info_size; + uint32_t common_info_offset; + uint32_t num_inputs; + uint32_t input_info_version; + uint32_t input_info_size; + uint32_t input_info_offset; + uint64_t data; +}; + +#define CAM_TFE_ACQUIRE_COMMON_VER0 0x1000 + +#define CAM_TFE_ACQUIRE_COMMON_SIZE_VER0 0x0 + +#define CAM_TFE_ACQUIRE_INPUT_VER0 0x2000 + +#define CAM_TFE_ACQUIRE_INPUT_SIZE_VER0 sizeof(struct cam_isp_tfe_in_port_info) + +#define CAM_TFE_ACQUIRE_OUT_VER0 0x3000 + +#define CAM_TFE_ACQUIRE_OUT_SIZE_VER0 sizeof(struct cam_isp_tfe_out_port_info) + +#endif /* __UAPI_CAM_TFE_H__ */ From 6283836b38ad59a2f9cc90e2cd543b917887993c Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 22 Nov 2019 12:06:48 -0800 Subject: [PATCH 180/790] msm: camera: sensor: Replace cma_alloc with vmalloc Replace cma_alloc() api with vmalloc() in order to accommodate kernel upgrade and DLKM/Builtin support. CRs-Fixed: 2572607 Change-Id: If8caaefe5ac333998bd8c4868f16e586ee749e8a Signed-off-by: Jigarkumar Zala --- .../cam_sensor_module/cam_ois/cam_ois_core.c | 39 +++++++++---------- .../cam_sensor_io/cam_sensor_spi.c | 37 ++++++++++-------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 8ced8a28c309..4a3cd853e22b 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -300,7 +300,7 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) char name_coeff[32] = {0}; struct device *dev = &(o_ctrl->pdev->dev); struct cam_sensor_i2c_reg_setting i2c_reg_setting; - struct page *page = NULL; + void *vaddr = NULL; if (!o_ctrl) { CAM_ERR(CAM_OIS, "Invalid Args"); @@ -327,18 +327,17 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; i2c_reg_setting.size = total_bytes; i2c_reg_setting.delay = 0; - fw_size = PAGE_ALIGN(sizeof(struct cam_sensor_i2c_reg_array) * - total_bytes) >> PAGE_SHIFT; - page = cma_alloc(dev_get_cma_area((o_ctrl->soc_info.dev)), - fw_size, 0, GFP_KERNEL); - if (!page) { - CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); + fw_size = (sizeof(struct cam_sensor_i2c_reg_array) * total_bytes); + vaddr = vmalloc(fw_size); + if (!vaddr) { + CAM_ERR(CAM_OIS, + "Failed in allocating i2c_array: fw_size: %u", fw_size); release_firmware(fw); return -ENOMEM; } i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) ( - page_address(page)); + vaddr); for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes; cnt++, ptr++) { @@ -355,9 +354,8 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); goto release_firmware; } - cma_release(dev_get_cma_area((o_ctrl->soc_info.dev)), - page, fw_size); - page = NULL; + vfree(vaddr); + vaddr = NULL; fw_size = 0; release_firmware(fw); @@ -372,18 +370,17 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; i2c_reg_setting.size = total_bytes; i2c_reg_setting.delay = 0; - fw_size = PAGE_ALIGN(sizeof(struct cam_sensor_i2c_reg_array) * - total_bytes) >> PAGE_SHIFT; - page = cma_alloc(dev_get_cma_area((o_ctrl->soc_info.dev)), - fw_size, 0, GFP_KERNEL); - if (!page) { - CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); + fw_size = (sizeof(struct cam_sensor_i2c_reg_array) * total_bytes); + vaddr = vmalloc(fw_size); + if (!vaddr) { + CAM_ERR(CAM_OIS, + "Failed in allocating i2c_array: fw_size: %u", fw_size); release_firmware(fw); return -ENOMEM; } i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) ( - page_address(page)); + vaddr); for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes; cnt++, ptr++) { @@ -400,10 +397,10 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); release_firmware: - cma_release(dev_get_cma_area((o_ctrl->soc_info.dev)), - page, fw_size); + vfree(vaddr); + vaddr = NULL; + fw_size = 0; release_firmware(fw); - return rc; } diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c index cf6987b09eac..3d09a4ea7eb3 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c @@ -111,7 +111,8 @@ static int32_t cam_spi_tx_helper(struct camera_io_master *client, uint32_t len, hlen; uint8_t retries = client->spi_client->retries; uint32_t txr = 0, rxr = 0; - struct page *page_tx = NULL, *page_rx = NULL; + void *vaddr_tx = NULL; + void *vaddr_rx = NULL; hlen = cam_camera_spi_get_hlen(inst); len = hlen + num_byte; @@ -125,30 +126,32 @@ static int32_t cam_spi_tx_helper(struct camera_io_master *client, if (tx) { ctx = tx; } else { - txr = PAGE_ALIGN(len) >> PAGE_SHIFT; - page_tx = cma_alloc(dev_get_cma_area(dev), - txr, 0, GFP_KERNEL); - if (!page_tx) + txr = len; + vaddr_tx = vmalloc(txr); + if (!vaddr_tx) { + CAM_ERR(CAM_SENSOR, + "Fail to allocate Memory: len: %u", txr); return -ENOMEM; + } - ctx = page_address(page_tx); + ctx = (char *)vaddr_tx; } if (num_byte) { if (rx) { crx = rx; } else { - rxr = PAGE_ALIGN(len) >> PAGE_SHIFT; - page_rx = cma_alloc(dev_get_cma_area(dev), - rxr, 0, GFP_KERNEL); - if (!page_rx) { + rxr = len; + vaddr_rx = vmalloc(rxr); + if (!vaddr_rx) { if (!tx) - cma_release(dev_get_cma_area(dev), - page_tx, txr); - + vfree(vaddr_tx); + CAM_ERR(CAM_SENSOR, + "Fail to allocate memory: len: %u", + rxr); return -ENOMEM; } - crx = page_address(page_rx); + crx = (char *)vaddr_rx; } } else { crx = NULL; @@ -169,9 +172,11 @@ static int32_t cam_spi_tx_helper(struct camera_io_master *client, out: if (!tx) - cma_release(dev_get_cma_area(dev), page_tx, txr); + vfree(vaddr_tx); + vaddr_tx = NULL; if (!rx) - cma_release(dev_get_cma_area(dev), page_rx, rxr); + vfree(vaddr_rx); + vaddr_rx = NULL; return rc; } From 02ac7654b8eb407a5bfcc17f95042b244b0aa112 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 5 Nov 2019 12:58:01 -0800 Subject: [PATCH 181/790] msm: camera: utils: Add stub function for cx_ipeak Add mandate check in order to compile and use the cx_ipeak related functionality. Also, update header with stub function. CRs-Fixed: 2572607 Change-Id: I2e07101f88b6a47ca1733d04b3aa126fdeae176b Signed-off-by: Jigarkumar Zala --- drivers/cam_utils/Makefile | 3 +++ drivers/cam_utils/cam_cx_ipeak.h | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/cam_utils/Makefile b/drivers/cam_utils/Makefile index 931478f0676e..58be3110cbf5 100644 --- a/drivers/cam_utils/Makefile +++ b/drivers/cam_utils/Makefile @@ -5,4 +5,7 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/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 + +ifdef CONFIG_QCOM_CX_IPEAK obj-$(CONFIG_SPECTRA_CAMERA) += cam_cx_ipeak.o +endif diff --git a/drivers/cam_utils/cam_cx_ipeak.h b/drivers/cam_utils/cam_cx_ipeak.h index ab06952b86a8..4c88fa345088 100644 --- a/drivers/cam_utils/cam_cx_ipeak.h +++ b/drivers/cam_utils/cam_cx_ipeak.h @@ -8,10 +8,30 @@ #include "cam_soc_util.h" +#ifndef CONFIG_QCOM_CX_IPEAK +static inline int cam_cx_ipeak_register_cx_ipeak + (struct cam_hw_soc_info *soc_info) +{ + return 0; +} + +static inline int cam_cx_ipeak_update_vote_cx_ipeak + (struct cam_hw_soc_info *soc_info, int32_t apply_level) +{ + return 0; +} + +static inline int cam_cx_ipeak_unvote_cx_ipeak + (struct cam_hw_soc_info *soc_info) +{ + return 0; +} +#else int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info); 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 #endif /* _CAM_CX_IPEAK_H_ */ From 6131f8a58e59d638f7ffd803e3926603955c87d0 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 27 Nov 2019 09:51:39 -0800 Subject: [PATCH 182/790] msm: camera: config: Enable module based compilation Currently all the modules are compiled based on single config flag. This change adds the capability for module based compilation with module based config flag for various targets. CRs-Fixed: 2569808 Change-Id: I054a555db04d1643b9da2d3f409d009c1fb2da9c Signed-off-by: Jigarkumar Zala --- config/bengalcamera.conf | 6 ++++++ config/bengalcameraconf.h | 6 ++++++ config/konacamera.conf | 7 ++++++- config/konacameraconf.h | 5 +++++ config/litocamera.conf | 6 ++++++ config/litocameraconf.h | 7 ++++++- 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/config/bengalcamera.conf b/config/bengalcamera.conf index 451723eebce3..051268ee0ff1 100644 --- a/config/bengalcamera.conf +++ b/config/bengalcamera.conf @@ -2,3 +2,9 @@ # Copyright (c) 2019, The Linux Foundation. All rights reserved. export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +export CONFIG_SPECTRA_LRME=y +export CONFIG_SPECTRA_FD=y diff --git a/config/bengalcameraconf.h b/config/bengalcameraconf.h index 1a7714018004..6d3b10779651 100644 --- a/config/bengalcameraconf.h +++ b/config/bengalcameraconf.h @@ -4,4 +4,10 @@ */ #define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 +#define CONFIG_SPECTRA_LRME 1 +#define CONFIG_SPECTRA_FD 1 diff --git a/config/konacamera.conf b/config/konacamera.conf index 9b08bcb80c2b..9d3834b98695 100644 --- a/config/konacamera.conf +++ b/config/konacamera.conf @@ -1 +1,6 @@ -export CONFIG_SPECTRA_CAMERA=y \ No newline at end of file +export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +export CONFIG_SPECTRA_FD=y diff --git a/config/konacameraconf.h b/config/konacameraconf.h index 875b95587ab6..971c8383e589 100644 --- a/config/konacameraconf.h +++ b/config/konacameraconf.h @@ -5,4 +5,9 @@ #define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 +#define CONFIG_SPECTRA_FD 1 diff --git a/config/litocamera.conf b/config/litocamera.conf index 451723eebce3..051268ee0ff1 100644 --- a/config/litocamera.conf +++ b/config/litocamera.conf @@ -2,3 +2,9 @@ # Copyright (c) 2019, The Linux Foundation. All rights reserved. export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +export CONFIG_SPECTRA_LRME=y +export CONFIG_SPECTRA_FD=y diff --git a/config/litocameraconf.h b/config/litocameraconf.h index 1a7714018004..08b473441ff5 100644 --- a/config/litocameraconf.h +++ b/config/litocameraconf.h @@ -4,4 +4,9 @@ */ #define CONFIG_SPECTRA_CAMERA 1 - +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 +#define CONFIG_SPECTRA_LRME 1 +#define CONFIG_SPECTRA_FD 1 From 03b6c2140fcd9b6008d20f75e6584e70ad78d0f3 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 22 Nov 2019 12:32:06 -0800 Subject: [PATCH 183/790] msm: camera: common: Make platform register centralized Currently camera modules platform registration/remove function is being called as a part of module_init function individually. Building camera as module, current infrastructure cannot support it, as DLKM only support single module_init/exit function. This change enables that support by combining all platform entry/remove functions centrally. Also, remove all submodule makefiles and combined into one root makefile in order to generate single kernel object file to dynamically loading the kernel module in case of DLKM compilation. CRs-Fixed: 2569808 Change-Id: I59db3ed6cef60123e474db2f222c39836056bd6e Signed-off-by: Jigarkumar Zala Signed-off-by: Karthik Jayakumar --- Makefile | 2 +- drivers/Makefile | 187 +++++++++++- drivers/cam_cdm/Makefile | 11 - drivers/cam_cdm/cam_cdm_hw_core.c | 6 +- drivers/cam_cdm/cam_cdm_intf.c | 6 +- drivers/cam_cdm/cam_cdm_intf_api.h | 23 +- drivers/cam_core/Makefile | 9 - drivers/cam_cpas/Makefile | 11 - drivers/cam_cpas/cam_cpas_hw_intf.h | 12 +- drivers/cam_cpas/cam_cpas_intf.c | 6 +- drivers/cam_cpas/camss_top/Makefile | 8 - drivers/cam_cpas/cpas_top/Makefile | 8 - drivers/cam_cust/Makefile | 19 -- drivers/cam_cust/cam_custom_dev.c | 6 +- drivers/cam_cust/cam_custom_dev.h | 10 + drivers/cam_cust/cam_custom_hw_mgr/Makefile | 20 -- .../cam_custom_csid/Makefile | 16 - .../cam_custom_csid/cam_custom_csid_dev.c | 6 +- .../cam_custom_csid/cam_custom_csid_dev.h | 17 +- .../cam_custom_hw_mgr/cam_custom_hw1/Makefile | 10 - .../cam_custom_hw1/cam_custom_sub_mod_dev.c | 6 +- .../cam_custom_hw1/cam_custom_sub_mod_dev.h | 10 + .../include/cam_custom_hw_mgr_intf.h | 2 - drivers/cam_fd/Makefile | 16 - drivers/cam_fd/cam_fd_dev.c | 8 +- drivers/cam_fd/cam_fd_dev.h | 20 ++ drivers/cam_fd/fd_hw_mgr/Makefile | 16 - drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile | 16 - .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c | 8 +- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h | 13 +- drivers/cam_icp/Makefile | 15 - drivers/cam_icp/cam_icp_subdev.c | 9 +- drivers/cam_icp/cam_icp_subdev.h | 20 ++ drivers/cam_icp/icp_hw/Makefile | 11 - drivers/cam_icp/icp_hw/a5_hw/Makefile | 14 - drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 11 + drivers/cam_icp/icp_hw/a5_hw/a5_dev.c | 8 +- drivers/cam_icp/icp_hw/bps_hw/Makefile | 14 - drivers/cam_icp/icp_hw/bps_hw/bps_core.h | 11 + drivers/cam_icp/icp_hw/bps_hw/bps_dev.c | 9 +- drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile | 19 -- drivers/cam_icp/icp_hw/ipe_hw/Makefile | 14 - drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h | 10 + drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c | 9 +- drivers/cam_isp/Makefile | 12 - drivers/cam_isp/cam_isp_dev.c | 6 +- drivers/cam_isp/cam_isp_dev.h | 12 +- drivers/cam_isp/isp_hw_mgr/Makefile | 17 -- drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile | 15 - .../hw_utils/irq_controller/Makefile | 5 - drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile | 4 - .../isp_hw_mgr/isp_hw/ife_csid_hw/Makefile | 14 - .../isp_hw/ife_csid_hw/cam_ife_csid17x.c | 6 +- .../isp_hw/ife_csid_hw/cam_ife_csid_dev.h | 24 +- .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c | 6 +- .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile | 16 - .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile | 17 -- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c | 7 +- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.h | 20 ++ .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile | 16 - .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile | 18 -- drivers/cam_jpeg/Makefile | 13 - drivers/cam_jpeg/cam_jpeg_dev.c | 6 +- drivers/cam_jpeg/cam_jpeg_dev.h | 13 +- drivers/cam_jpeg/jpeg_hw/Makefile | 15 - drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile | 13 - .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 10 + .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 9 +- drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile | 13 - .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h | 10 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 8 +- drivers/cam_lrme/Makefile | 15 - drivers/cam_lrme/cam_lrme_dev.c | 8 +- drivers/cam_lrme/cam_lrme_dev.h | 20 ++ drivers/cam_lrme/lrme_hw_mgr/Makefile | 15 - drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile | 14 - .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c | 6 +- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h | 12 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 18 +- drivers/cam_req_mgr/cam_req_mgr_dev.h | 20 +- drivers/cam_req_mgr/cam_subdev.h | 11 +- drivers/cam_sensor_module/Makefile | 12 - .../cam_sensor_module/cam_actuator/Makefile | 13 - .../cam_actuator/cam_actuator_dev.c | 8 +- .../cam_actuator/cam_actuator_dev.h | 16 +- drivers/cam_sensor_module/cam_cci/Makefile | 11 - .../cam_sensor_module/cam_cci/cam_cci_dev.c | 69 +---- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 10 + drivers/cam_sensor_module/cam_csiphy/Makefile | 12 - .../cam_csiphy/cam_csiphy_core.c | 2 +- .../cam_csiphy/cam_csiphy_dev.c | 8 +- .../cam_csiphy/cam_csiphy_dev.h | 16 +- drivers/cam_sensor_module/cam_eeprom/Makefile | 12 - .../cam_eeprom/cam_eeprom_dev.c | 6 +- .../cam_eeprom/cam_eeprom_dev.h | 11 + drivers/cam_sensor_module/cam_flash/Makefile | 13 - .../cam_flash/cam_flash_dev.c | 6 +- .../cam_flash/cam_flash_dev.h | 10 + drivers/cam_sensor_module/cam_ois/Makefile | 13 - .../cam_sensor_module/cam_ois/cam_ois_dev.c | 8 +- .../cam_sensor_module/cam_ois/cam_ois_dev.h | 10 + .../cam_sensor_module/cam_res_mgr/Makefile | 11 - .../cam_res_mgr/cam_res_mgr.c | 8 +- .../cam_res_mgr/cam_res_mgr_api.h | 12 +- drivers/cam_sensor_module/cam_sensor/Makefile | 12 - .../cam_sensor/cam_sensor_dev.c | 6 +- .../cam_sensor/cam_sensor_dev.h | 17 +- .../cam_sensor_module/cam_sensor_io/Makefile | 11 - .../cam_sensor_utils/Makefile | 12 - drivers/cam_smmu/Makefile | 6 - drivers/cam_smmu/cam_smmu_api.c | 6 +- drivers/cam_smmu/cam_smmu_api.h | 10 + drivers/cam_sync/Makefile | 7 - drivers/cam_sync/cam_sync.c | 7 +- drivers/cam_sync/cam_sync_api.h | 11 +- drivers/cam_utils/Makefile | 11 - drivers/camera_main.c | 274 ++++++++++++++++++ 117 files changed, 930 insertions(+), 903 deletions(-) delete mode 100644 drivers/cam_cdm/Makefile delete mode 100644 drivers/cam_core/Makefile delete mode 100644 drivers/cam_cpas/Makefile delete mode 100644 drivers/cam_cpas/camss_top/Makefile delete mode 100644 drivers/cam_cpas/cpas_top/Makefile delete mode 100644 drivers/cam_cust/Makefile delete mode 100644 drivers/cam_cust/cam_custom_hw_mgr/Makefile delete mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile delete mode 100644 drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile delete mode 100644 drivers/cam_fd/Makefile create mode 100644 drivers/cam_fd/cam_fd_dev.h delete mode 100644 drivers/cam_fd/fd_hw_mgr/Makefile delete mode 100644 drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile delete mode 100644 drivers/cam_icp/Makefile create mode 100644 drivers/cam_icp/cam_icp_subdev.h delete mode 100644 drivers/cam_icp/icp_hw/Makefile delete mode 100644 drivers/cam_icp/icp_hw/a5_hw/Makefile delete mode 100644 drivers/cam_icp/icp_hw/bps_hw/Makefile delete mode 100644 drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile delete mode 100644 drivers/cam_icp/icp_hw/ipe_hw/Makefile delete mode 100644 drivers/cam_isp/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.h delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile delete mode 100644 drivers/cam_jpeg/Makefile delete mode 100644 drivers/cam_jpeg/jpeg_hw/Makefile delete mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile delete mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile delete mode 100644 drivers/cam_lrme/Makefile create mode 100644 drivers/cam_lrme/cam_lrme_dev.h delete mode 100644 drivers/cam_lrme/lrme_hw_mgr/Makefile delete mode 100644 drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile delete mode 100644 drivers/cam_sensor_module/Makefile delete mode 100644 drivers/cam_sensor_module/cam_actuator/Makefile delete mode 100644 drivers/cam_sensor_module/cam_cci/Makefile delete mode 100644 drivers/cam_sensor_module/cam_csiphy/Makefile delete mode 100644 drivers/cam_sensor_module/cam_eeprom/Makefile delete mode 100644 drivers/cam_sensor_module/cam_flash/Makefile delete mode 100644 drivers/cam_sensor_module/cam_ois/Makefile delete mode 100644 drivers/cam_sensor_module/cam_res_mgr/Makefile delete mode 100644 drivers/cam_sensor_module/cam_sensor/Makefile delete mode 100644 drivers/cam_sensor_module/cam_sensor_io/Makefile delete mode 100644 drivers/cam_sensor_module/cam_sensor_utils/Makefile delete mode 100644 drivers/cam_smmu/Makefile delete mode 100644 drivers/cam_sync/Makefile delete mode 100644 drivers/cam_utils/Makefile create mode 100644 drivers/camera_main.c diff --git a/Makefile b/Makefile index 9e0b13785b58..7e135e4e13ae 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/bengalcameraconf.h endif -ifdef CONFIG_SPECTRA_CAMERA +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) # Use USERINCLUDE when you must reference the UAPI directories only. USERINCLUDE += \ -I$(srctree)/techpack/camera/include/uapi diff --git a/drivers/Makefile b/drivers/Makefile index 84beb97a75e9..a59a49ce1be5 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,16 +1,173 @@ -subdir-ccflags-y += -I$(srctree)/techpack/camera/include/uapi/camera +# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_utils/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_core/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sync/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpas/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_module/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cust/ +cameratree := $(srctree)/techpack/camera/drivers + +cam_include_dirs := $(shell dirname `find $(cameratree) -name '*.h'` | uniq) +ccflags-y += $(addprefix -I,$(cam_include_dirs)) + +ifneq (,$(filter $(CONFIG_MSM_GLOBAL_SYNX), y m)) +ccflags-y += -I$(srctree)/drivers/media/platform/msm/synx +endif + +subdir-ccflags-y += -I$(srctree)/techpack/camera/include/uapi/camera +ccflags-y += -I$(srctree) + +camera-y := \ + cam_req_mgr/cam_req_mgr_core.o \ + cam_req_mgr/cam_req_mgr_dev.o \ + cam_req_mgr/cam_req_mgr_util.o \ + cam_req_mgr/cam_mem_mgr.o \ + cam_req_mgr/cam_req_mgr_workq.o \ + cam_req_mgr/cam_req_mgr_timer.o \ + cam_req_mgr/cam_req_mgr_debug.o \ + cam_utils/cam_soc_util.o \ + cam_utils/cam_io_util.o \ + cam_utils/cam_packet_util.o \ + cam_utils/cam_debug_util.o \ + cam_utils/cam_trace.o \ + cam_utils/cam_common_util.o \ + cam_core/cam_context.o \ + cam_core/cam_context_utils.o \ + cam_core/cam_node.o \ + cam_core/cam_subdev.o \ + cam_smmu/cam_smmu_api.o \ + cam_sync/cam_sync.o \ + cam_sync/cam_sync_util.o \ + cam_cpas/cpas_top/cam_cpastop_hw.o \ + cam_cpas/camss_top/cam_camsstop_hw.o \ + cam_cpas/cam_cpas_soc.o \ + cam_cpas/cam_cpas_intf.o \ + cam_cpas/cam_cpas_hw.o \ + cam_cdm/cam_cdm_soc.o \ + cam_cdm/cam_cdm_util.o \ + cam_cdm/cam_cdm_intf.o \ + cam_cdm/cam_cdm_core_common.o \ + cam_cdm/cam_cdm_virtual_core.o \ + cam_cdm/cam_cdm_hw_core.o + +ifdef CONFIG_QCOM_CX_IPEAK +camera-y += cam_utils/cam_cx_ipeak.o +endif + +camera-$(CONFIG_SPECTRA_ISP) += \ + cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.o \ + cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.o \ + cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.o \ + cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.o \ + cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.o \ + cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.o \ + cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.o \ + cam_isp/isp_hw_mgr/cam_isp_hw_mgr.o \ + cam_isp/isp_hw_mgr/cam_ife_hw_mgr.o \ + cam_isp/cam_isp_dev.o \ + cam_isp/cam_isp_context.o + +camera-$(CONFIG_SPECTRA_ICP) += \ + cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.o \ + cam_icp/icp_hw/ipe_hw/ipe_dev.o \ + cam_icp/icp_hw/ipe_hw/ipe_core.o \ + cam_icp/icp_hw/ipe_hw/ipe_soc.o \ + cam_icp/icp_hw/a5_hw/a5_dev.o \ + cam_icp/icp_hw/a5_hw/a5_core.o \ + cam_icp/icp_hw/a5_hw/a5_soc.o \ + cam_icp/icp_hw/bps_hw/bps_dev.o \ + cam_icp/icp_hw/bps_hw/bps_core.o \ + cam_icp/icp_hw/bps_hw/bps_soc.o \ + cam_icp/cam_icp_subdev.o \ + cam_icp/cam_icp_context.o \ + cam_icp/hfi.o + +camera-$(CONFIG_SPECTRA_JPEG) += \ + cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.o \ + cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.o \ + cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.o \ + cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.o \ + cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.o \ + cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.o \ + cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.o \ + cam_jpeg/cam_jpeg_dev.o \ + cam_jpeg/cam_jpeg_context.o + +camera-$(CONFIG_SPECTRA_FD) += \ + cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.o \ + cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.o \ + cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.o \ + cam_fd/fd_hw_mgr/cam_fd_hw_mgr.o \ + cam_fd/cam_fd_dev.o \ + cam_fd/cam_fd_context.o + +camera-$(CONFIG_SPECTRA_LRME) += \ + cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.o \ + cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.o \ + cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.o \ + cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.o \ + cam_lrme/cam_lrme_dev.o \ + cam_lrme/cam_lrme_context.o + +camera-$(CONFIG_SPECTRA_SENSOR) += \ + cam_sensor_module/cam_actuator/cam_actuator_dev.o \ + cam_sensor_module/cam_actuator/cam_actuator_core.o \ + cam_sensor_module/cam_actuator/cam_actuator_soc.o \ + cam_sensor_module/cam_cci/cam_cci_dev.o \ + cam_sensor_module/cam_cci/cam_cci_core.o \ + cam_sensor_module/cam_cci/cam_cci_soc.o \ + cam_sensor_module/cam_csiphy/cam_csiphy_soc.o \ + cam_sensor_module/cam_csiphy/cam_csiphy_dev.o \ + cam_sensor_module/cam_csiphy/cam_csiphy_core.o \ + cam_sensor_module/cam_eeprom/cam_eeprom_dev.o \ + cam_sensor_module/cam_eeprom/cam_eeprom_core.o \ + cam_sensor_module/cam_eeprom/cam_eeprom_soc.o \ + cam_sensor_module/cam_ois/cam_ois_dev.o \ + cam_sensor_module/cam_ois/cam_ois_core.o \ + cam_sensor_module/cam_ois/cam_ois_soc.o \ + cam_sensor_module/cam_sensor/cam_sensor_dev.o \ + cam_sensor_module/cam_sensor/cam_sensor_core.o \ + cam_sensor_module/cam_sensor/cam_sensor_soc.o \ + cam_sensor_module/cam_sensor_io/cam_sensor_io.o \ + cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.o \ + cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.o \ + cam_sensor_module/cam_sensor_io/cam_sensor_spi.o \ + cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \ + cam_sensor_module/cam_res_mgr/cam_res_mgr.o + +camera-$(CONFIG_LEDS_QPNP_FLASH_V2) += \ + cam_sensor_module/cam_flash/cam_flash_dev.o \ + cam_sensor_module/cam_flash/cam_flash_core.o \ + cam_sensor_module/cam_flash/cam_flash_soc.o + +camera-$(CONFIG_SPECTRA_CUSTOM) += \ + cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.o \ + cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.o \ + cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.o \ + cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.o \ + cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.o \ + cam_cust/cam_custom_dev.o \ + cam_cust/cam_custom_context.o + +camera-y += camera_main.o + +obj-$(CONFIG_SPECTRA_CAMERA) += camera.o + +ifeq ($(CONFIG_SPECTRA_CAMERA),m) +$(info "SPECTRA CAMERA IS BUILT AS DLKM") +BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/camera.ko +endif diff --git a/drivers/cam_cdm/Makefile b/drivers/cam_cdm/Makefile deleted file mode 100644 index 9ba81e385ab3..000000000000 --- a/drivers/cam_cdm/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm_soc.o cam_cdm_util.o cam_cdm_intf.o\ - cam_cdm_core_common.o cam_cdm_virtual_core.o \ - cam_cdm_hw_core.o diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index f54f9d61b55f..5a59e4c611df 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1130,17 +1130,15 @@ static struct platform_driver cam_hw_cdm_driver = { }, }; -static int __init cam_hw_cdm_init_module(void) +int cam_hw_cdm_init_module(void) { return platform_driver_register(&cam_hw_cdm_driver); } -static void __exit cam_hw_cdm_exit_module(void) +void cam_hw_cdm_exit_module(void) { platform_driver_unregister(&cam_hw_cdm_driver); } -module_init(cam_hw_cdm_init_module); -module_exit(cam_hw_cdm_exit_module); MODULE_DESCRIPTION("MSM Camera HW CDM driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index 94e2f36d0544..990ee39f000c 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -557,17 +557,15 @@ static struct platform_driver cam_cdm_intf_driver = { }, }; -static int __init cam_cdm_intf_init_module(void) +int cam_cdm_intf_init_module(void) { return platform_driver_register(&cam_cdm_intf_driver); } -static void __exit cam_cdm_intf_exit_module(void) +void cam_cdm_intf_exit_module(void) { platform_driver_unregister(&cam_cdm_intf_driver); } -module_init(cam_cdm_intf_init_module); -module_exit(cam_cdm_intf_exit_module); MODULE_DESCRIPTION("MSM Camera CDM Intf driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index 3e89b22b1b18..93404353714f 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_API_H_ @@ -199,4 +199,25 @@ int cam_cdm_stream_off(uint32_t handle); */ int cam_cdm_reset_hw(uint32_t handle); +/** + * @brief : API to register CDM hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_hw_cdm_init_module(void); + +/** + * @brief : API to register CDM interface to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_cdm_intf_init_module(void); + +/** + * @brief : API to remove CDM interface from platform framework. + */ +void cam_cdm_intf_exit_module(void); + +/** + * @brief : API to remove CDM hw from platform framework. + */ +void cam_hw_cdm_exit_module(void); #endif /* _CAM_CDM_API_H_ */ diff --git a/drivers/cam_core/Makefile b/drivers/cam_core/Makefile deleted file mode 100644 index d8dd1a48948f..000000000000 --- a/drivers/cam_core/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(src) - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_context.o cam_context_utils.o cam_node.o cam_subdev.o diff --git a/drivers/cam_cpas/Makefile b/drivers/cam_cpas/Makefile deleted file mode 100644 index 947fbbf7d91e..000000000000 --- a/drivers/cam_cpas/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree) - -obj-$(CONFIG_SPECTRA_CAMERA) += cpas_top/ -obj-$(CONFIG_SPECTRA_CAMERA) += camss_top/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpas_soc.o cam_cpas_intf.o cam_cpas_hw.o \ No newline at end of file diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index 0926e6e3d8d1..1c3c146e24e7 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_INTF_H_ @@ -125,4 +125,14 @@ int cam_cpas_hw_probe(struct platform_device *pdev, struct cam_hw_intf **hw_intf); int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf); +/** + * @brief : API to register CPAS hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_cpas_dev_init_module(void); + +/** + * @brief : API to remove CPAS interface from platform framework. + */ +void cam_cpas_dev_exit_module(void); #endif /* _CAM_CPAS_HW_INTF_H_ */ diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index a1d8b4026059..f2a2e60d636e 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -736,17 +736,15 @@ static struct platform_driver cam_cpas_driver = { }, }; -static int __init cam_cpas_dev_init_module(void) +int cam_cpas_dev_init_module(void) { return platform_driver_register(&cam_cpas_driver); } -static void __exit cam_cpas_dev_exit_module(void) +void cam_cpas_dev_exit_module(void) { platform_driver_unregister(&cam_cpas_driver); } -module_init(cam_cpas_dev_init_module); -module_exit(cam_cpas_dev_exit_module); MODULE_DESCRIPTION("MSM CPAS driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cpas/camss_top/Makefile b/drivers/cam_cpas/camss_top/Makefile deleted file mode 100644 index 8fc199fcf9eb..000000000000 --- a/drivers/cam_cpas/camss_top/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_camsstop_hw.o diff --git a/drivers/cam_cpas/cpas_top/Makefile b/drivers/cam_cpas/cpas_top/Makefile deleted file mode 100644 index cbd65d8fdde8..000000000000 --- a/drivers/cam_cpas/cpas_top/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpastop_hw.o diff --git a/drivers/cam_cust/Makefile b/drivers/cam_cust/Makefile deleted file mode 100644 index 732b9593c38b..000000000000 --- a/drivers/cam_cust/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw_mgr/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_dev.o cam_custom_context.o diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index da95f36b9d7e..f36e5ad27cf2 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -183,17 +183,15 @@ static struct platform_driver custom_driver = { }, }; -static int __init cam_custom_dev_init_module(void) +int cam_custom_dev_init_module(void) { return platform_driver_register(&custom_driver); } -static void __exit cam_custom_dev_exit_module(void) +void cam_custom_dev_exit_module(void) { platform_driver_unregister(&custom_driver); } -module_init(cam_custom_dev_init_module); -module_exit(cam_custom_dev_exit_module); MODULE_DESCRIPTION("MSM CUSTOM driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cust/cam_custom_dev.h b/drivers/cam_cust/cam_custom_dev.h index 77ea6badfe94..7f8fa98004b8 100644 --- a/drivers/cam_cust/cam_custom_dev.h +++ b/drivers/cam_cust/cam_custom_dev.h @@ -31,4 +31,14 @@ struct cam_custom_dev { int32_t open_cnt; }; +/** + * @brief : API to register Custom hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_custom_dev_init_module(void); + +/** + * @brief : API to remove Custom hw interface from platform framework. + */ +void cam_custom_dev_exit_module(void); #endif /* _CAM_CUSTOM_DEV_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/Makefile b/drivers/cam_cust/cam_custom_hw_mgr/Makefile deleted file mode 100644 index 1e0917637b8e..000000000000 --- a/drivers/cam_cust/cam_custom_hw_mgr/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw1/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw1/ cam_custom_csid/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_hw_mgr.o - diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile deleted file mode 100644 index ab36c8862888..000000000000 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_csid_dev.o diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c index be472372aeb0..ca592a60fcb0 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c @@ -152,7 +152,7 @@ static struct platform_driver cam_custom_csid_driver = { .remove = cam_custom_csid_remove, }; -static int __init cam_custom_csid_driver_init(void) +int cam_custom_csid_driver_init(void) { int32_t rc = 0; @@ -179,12 +179,10 @@ int cam_custom_csid_hw_init(struct cam_hw_intf **custom_csid_hw, return rc; } -static void __exit cam_custom_csid_driver_exit(void) +void cam_custom_csid_driver_exit(void) { platform_driver_unregister(&cam_custom_csid_driver); } -module_init(cam_custom_csid_driver_init); -module_exit(cam_custom_csid_driver_exit); MODULE_DESCRIPTION("cam_custom_csid_driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h index f0c086ccab18..506469f76574 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.h @@ -3,10 +3,21 @@ * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ -#ifndef _CAM_IFE_CSID_DEV_H_ -#define _CAM_IFE_CSID_DEV_H_ +#ifndef _CAM_CUSTOM_CSID_DEV_H_ +#define _CAM_CUSTOM_CSID_DEV_H_ #include "cam_debug_util.h" #include "cam_custom_hw_mgr_intf.h" -#endif /*_CAM_IFE_CSID_DEV_H_ */ +/** + * @brief : API to register Custom CSID hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_custom_csid_driver_init(void); + +/** + * @brief : API to remove Custom CSID hw interface from platform framework. + */ +void cam_custom_csid_driver_exit(void); + +#endif /*_CAM_CUSTOM_CSID_DEV_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile deleted file mode 100644 index 4895219ffd06..000000000000 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1 - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_custom_sub_mod_soc.o cam_custom_sub_mod_dev.o cam_custom_sub_mod_core.o diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c index bd7d65913649..2a13e4979c15 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c @@ -146,17 +146,15 @@ static struct platform_driver cam_custom_hw_sub_mod_driver = { }, }; -static int __init cam_custom_hw_sub_module_init(void) +int cam_custom_hw_sub_module_init(void) { return platform_driver_register(&cam_custom_hw_sub_mod_driver); } -static void __exit cam_custom_hw_sub_module_exit(void) +void cam_custom_hw_sub_module_exit(void) { platform_driver_unregister(&cam_custom_hw_sub_mod_driver); } -module_init(cam_custom_hw_sub_module_init); -module_exit(cam_custom_hw_sub_module_exit); MODULE_DESCRIPTION("CAM CUSTOM HW SUB MODULE driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h index 1da630ed5ec2..4b9af3656cf2 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.h @@ -12,4 +12,14 @@ #define CAM_CUSTOM_SUB_MOD_MAX_INSTANCES 2 +/** + * @brief : API to register Custom submodule to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_custom_hw_sub_module_init(void); + +/** + * @brief : API to remove Custom submodule interface from platform framework. + */ +void cam_custom_hw_sub_module_exit(void); #endif /* _CAM_CUSTOM_SUB_MOD_DEV_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h index 85492be28193..0577cd6ef9cb 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -9,9 +9,7 @@ #include #include #include - #include - #include "cam_hw.h" #include "cam_hw_mgr_intf.h" #include "cam_hw_intf.h" diff --git a/drivers/cam_fd/Makefile b/drivers/cam_fd/Makefile deleted file mode 100644 index e74167e0611f..000000000000 --- a/drivers/cam_fd/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr/fd_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw_mgr/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_dev.o cam_fd_context.o diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index c92cea8fc9e9..1fa9e78d42a3 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -191,17 +191,15 @@ static struct platform_driver cam_fd_driver = { }, }; -static int __init cam_fd_dev_init_module(void) +int cam_fd_dev_init_module(void) { return platform_driver_register(&cam_fd_driver); } -static void __exit cam_fd_dev_exit_module(void) +void cam_fd_dev_exit_module(void) { platform_driver_unregister(&cam_fd_driver); } -module_init(cam_fd_dev_init_module); -module_exit(cam_fd_dev_exit_module); MODULE_DESCRIPTION("MSM FD driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_fd/cam_fd_dev.h b/drivers/cam_fd/cam_fd_dev.h new file mode 100644 index 000000000000..74db41b8dc71 --- /dev/null +++ b/drivers/cam_fd/cam_fd_dev.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_FD_DEV_H_ +#define _CAM_FD_DEV_H_ + +/** + * @brief : API to register FD Dev to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_fd_dev_init_module(void); + +/** + * @brief : API to remove FD Dev interface from platform framework. + */ +void cam_fd_dev_exit_module(void); + +#endif /* _CAM_FD_DEV_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/Makefile b/drivers/cam_fd/fd_hw_mgr/Makefile deleted file mode 100644 index 7857618bd5f5..000000000000 --- a/drivers/cam_fd/fd_hw_mgr/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr/fd_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_hw_mgr.o diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile b/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile deleted file mode 100644 index 6a53cc67f7e6..000000000000 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/include/uapi -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_fd/fd_hw_mgr/fd_hw -ccflags-y += -I$(srctree)/techpack/camera -ccflags-y += -I$(srctree)/techpack/camera/drivers/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/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c index 3498e6235279..7668dd622b90 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -219,17 +219,15 @@ static struct platform_driver cam_fd_hw_driver = { }, }; -static int __init cam_fd_hw_init_module(void) +int cam_fd_hw_init_module(void) { return platform_driver_register(&cam_fd_hw_driver); } -static void __exit cam_fd_hw_exit_module(void) +void cam_fd_hw_exit_module(void) { platform_driver_unregister(&cam_fd_hw_driver); } -module_init(cam_fd_hw_init_module); -module_exit(cam_fd_hw_exit_module); MODULE_DESCRIPTION("CAM FD HW driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h index e35e5e520b7b..7dd7d94f783a 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_INTF_H_ @@ -279,4 +279,15 @@ struct cam_fd_hw_cmd_set_irq_cb { void *data; }; +/** + * @brief : API to register FD Hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_fd_hw_init_module(void); + +/** + * @brief : API to remove FD Hw interface from platform framework. + */ +void cam_fd_hw_exit_module(void); + #endif /* _CAM_FD_HW_INTF_H_ */ diff --git a/drivers/cam_icp/Makefile b/drivers/cam_icp/Makefile deleted file mode 100644 index 98a9ed931e72..000000000000 --- a/drivers/cam_icp/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ - -obj-$(CONFIG_SPECTRA_CAMERA) += icp_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp_subdev.o cam_icp_context.o hfi.o diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index bdb2ed5f900b..62cfc96ab999 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -260,16 +260,15 @@ static struct platform_driver cam_icp_driver = { }, }; -static int __init cam_icp_init_module(void) +int cam_icp_init_module(void) { return platform_driver_register(&cam_icp_driver); } -static void __exit cam_icp_exit_module(void) +void cam_icp_exit_module(void) { platform_driver_unregister(&cam_icp_driver); } -module_init(cam_icp_init_module); -module_exit(cam_icp_exit_module); + MODULE_DESCRIPTION("MSM ICP driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/cam_icp_subdev.h b/drivers/cam_icp/cam_icp_subdev.h new file mode 100644 index 000000000000..af38e26a241b --- /dev/null +++ b/drivers/cam_icp/cam_icp_subdev.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_ICP_SUBDEV_H_ +#define _CAM_ICP_SUBDEV_H_ + +/** + * @brief : API to register ICP subdev to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_icp_init_module(void); + +/** + * @brief : API to remove ICP subdev from platform framework. + */ +void cam_icp_exit_module(void); + +#endif /* _CAM_ICP_SUBDEV_H_ */ diff --git a/drivers/cam_icp/icp_hw/Makefile b/drivers/cam_icp/icp_hw/Makefile deleted file mode 100644 index 5b61366cc5f5..000000000000 --- a/drivers/cam_icp/icp_hw/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += icp_hw_mgr/ a5_hw/ ipe_hw/ bps_hw/ diff --git a/drivers/cam_icp/icp_hw/a5_hw/Makefile b/drivers/cam_icp/icp_hw/a5_hw/Makefile deleted file mode 100644 index 9c3aac09a137..000000000000 --- a/drivers/cam_icp/icp_hw/a5_hw/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/include/uapi -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/a5_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += a5_dev.o a5_core.o a5_soc.o diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h index 6c46b3ac8784..f6edebbc3141 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -80,4 +80,15 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_a5_irq(int irq_num, void *data); + +/** + * @brief : API to register a5 hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_a5_init_module(void); + +/** + * @brief : API to remove a5 hw from platform framework. + */ +void cam_a5_exit_module(void); #endif /* CAM_A5_CORE_H */ diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c index b4f33d3e4dd3..ea1a8bb91e13 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -212,17 +212,15 @@ static struct platform_driver cam_a5_driver = { }, }; -static int __init cam_a5_init_module(void) +int cam_a5_init_module(void) { return platform_driver_register(&cam_a5_driver); } -static void __exit cam_a5_exit_module(void) +void cam_a5_exit_module(void) { platform_driver_unregister(&cam_a5_driver); } -module_init(cam_a5_init_module); -module_exit(cam_a5_exit_module); MODULE_DESCRIPTION("CAM A5 driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/icp_hw/bps_hw/Makefile b/drivers/cam_icp/icp_hw/bps_hw/Makefile deleted file mode 100644 index 491e6a16492b..000000000000 --- a/drivers/cam_icp/icp_hw/bps_hw/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/include/uapi -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/bps_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += bps_dev.o bps_core.o bps_soc.o diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.h b/drivers/cam_icp/icp_hw/bps_hw/bps_core.h index 162c5e65530c..f7577c36dff4 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.h +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.h @@ -36,4 +36,15 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_bps_irq(int irq_num, void *data); + +/** + * @brief : API to register BPS hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_bps_init_module(void); + +/** + * @brief : API to remove BPS Hw from platform framework. + */ +void cam_bps_exit_module(void); #endif /* CAM_BPS_CORE_H */ diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c index a80c27325b72..e2ebd76b502a 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -24,7 +24,6 @@ static struct cam_bps_device_hw_info cam_bps_hw_info = { .pwr_status = 0x58, .reserved = 0, }; -EXPORT_SYMBOL(cam_bps_hw_info); static char bps_dev_name[8]; @@ -191,17 +190,15 @@ static struct platform_driver cam_bps_driver = { }, }; -static int __init cam_bps_init_module(void) +int cam_bps_init_module(void) { return platform_driver_register(&cam_bps_driver); } -static void __exit cam_bps_exit_module(void) +void cam_bps_exit_module(void) { platform_driver_unregister(&cam_bps_driver); } -module_init(cam_bps_init_module); -module_exit(cam_bps_exit_module); MODULE_DESCRIPTION("CAM BPS driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile b/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile deleted file mode 100644 index b87d5dba817a..000000000000 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/include/uapi -ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/isp/isp_hw/isp_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/a5_hw/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp_hw_mgr.o diff --git a/drivers/cam_icp/icp_hw/ipe_hw/Makefile b/drivers/cam_icp/icp_hw/ipe_hw/Makefile deleted file mode 100644 index d57373c332e0..000000000000 --- a/drivers/cam_icp/icp_hw/ipe_hw/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/include/uapi -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/icp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/icp_hw/ipe_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_icp/fw_inc -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += ipe_dev.o ipe_core.o ipe_soc.o diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h index 1a15e9233896..c02ad58e3305 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.h @@ -36,4 +36,14 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_ipe_irq(int irq_num, void *data); +/** + * @brief : API to register IPE hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_ipe_init_module(void); + +/** + * @brief : API to remove IPE Hw from platform framework. + */ +void cam_ipe_exit_module(void); #endif /* CAM_IPE_CORE_H */ diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c index 0390488d92b3..c6c34f27c034 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -32,7 +32,6 @@ static struct cam_ipe_device_hw_info cam_ipe_hw_info[] = { .reserved = 0, }, }; -EXPORT_SYMBOL(cam_ipe_hw_info); static char ipe_dev_name[8]; @@ -183,17 +182,15 @@ static struct platform_driver cam_ipe_driver = { }, }; -static int __init cam_ipe_init_module(void) +int cam_ipe_init_module(void) { return platform_driver_register(&cam_ipe_driver); } -static void __exit cam_ipe_exit_module(void) +void cam_ipe_exit_module(void) { platform_driver_unregister(&cam_ipe_driver); } -module_init(cam_ipe_init_module); -module_exit(cam_ipe_exit_module); MODULE_DESCRIPTION("CAM IPE driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/Makefile b/drivers/cam_isp/Makefile deleted file mode 100644 index 6459d449305c..000000000000 --- a/drivers/cam_isp/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ - -obj-$(CONFIG_SPECTRA_CAMERA) += isp_hw_mgr/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_dev.o cam_isp_context.o diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 9c3f33181ae6..b2e2b18f8f85 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -181,17 +181,15 @@ static struct platform_driver isp_driver = { }, }; -static int __init cam_isp_dev_init_module(void) +int cam_isp_dev_init_module(void) { return platform_driver_register(&isp_driver); } -static void __exit cam_isp_dev_exit_module(void) +void cam_isp_dev_exit_module(void) { platform_driver_unregister(&isp_driver); } -module_init(cam_isp_dev_init_module); -module_exit(cam_isp_dev_exit_module); MODULE_DESCRIPTION("MSM ISP driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/cam_isp_dev.h b/drivers/cam_isp/cam_isp_dev.h index cf9140eb8c88..d58ab7a8274e 100644 --- a/drivers/cam_isp/cam_isp_dev.h +++ b/drivers/cam_isp/cam_isp_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_DEV_H_ @@ -28,4 +28,14 @@ struct cam_isp_dev { int32_t open_cnt; }; +/** + * @brief : API to register ISP Dev to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_isp_dev_init_module(void); + +/** + * @brief : API to remove ISP Dev from platform framework. + */ +void cam_isp_dev_exit_module(void); #endif /* __CAM_ISP_DEV_H__ */ diff --git a/drivers/cam_isp/isp_hw_mgr/Makefile b/drivers/cam_isp/isp_hw_mgr/Makefile deleted file mode 100644 index 33b808c934e3..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(src) - -obj-$(CONFIG_SPECTRA_CAMERA) += hw_utils/ isp_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_hw_mgr.o cam_ife_hw_mgr.o diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile b/drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile deleted file mode 100644 index ccdfc05f103d..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_tasklet_util.o cam_isp_packet_parser.o -obj-$(CONFIG_SPECTRA_CAMERA) += irq_controller/ diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile deleted file mode 100644 index fb595fe8f02a..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_irq_controller.o \ No newline at end of file diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile deleted file mode 100644 index 41c244c96572..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -obj-$(CONFIG_SPECTRA_CAMERA) += ife_csid_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += vfe_hw/ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile deleted file mode 100644 index 8ccd9f0b3f62..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_ife_csid_dev.o cam_ife_csid_soc.o cam_ife_csid_core.o -obj-$(CONFIG_SPECTRA_CAMERA) += cam_ife_csid17x.o cam_ife_csid_lite17x.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c index d88347caa388..8e34447f3634 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c @@ -70,17 +70,15 @@ static struct platform_driver cam_ife_csid17x_driver = { }, }; -static int __init cam_ife_csid17x_init_module(void) +int cam_ife_csid17x_init_module(void) { return platform_driver_register(&cam_ife_csid17x_driver); } -static void __exit cam_ife_csid17x_exit_module(void) +void cam_ife_csid17x_exit_module(void) { platform_driver_unregister(&cam_ife_csid17x_driver); } -module_init(cam_ife_csid17x_init_module); -module_exit(cam_ife_csid17x_exit_module); MODULE_DESCRIPTION("CAM IFE_CSID17X driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h index 1f8e4d05b74b..61bd875c1872 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_DEV_H_ @@ -13,4 +13,26 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data); int cam_ife_csid_probe(struct platform_device *pdev); int cam_ife_csid_remove(struct platform_device *pdev); +/** + * @brief : API to register CSID hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_ife_csid17x_init_module(void); + +/** + * @brief : API to register CSID Lite hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_ife_csid_lite_init_module(void); + +/** + * @brief : API to remove CSID Hw from platform framework. + */ +void cam_ife_csid17x_exit_module(void); + +/** + * @brief : API to remove CSID Lite Hw from platform framework. + */ +void cam_ife_csid_lite_exit_module(void); + #endif /*_CAM_IFE_CSID_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c index 07d555b17009..2bc6e8ce6284 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c @@ -47,17 +47,15 @@ static struct platform_driver cam_ife_csid_lite_driver = { }, }; -static int __init cam_ife_csid_lite_init_module(void) +int cam_ife_csid_lite_init_module(void) { return platform_driver_register(&cam_ife_csid_lite_driver); } -static void __exit cam_ife_csid_lite_exit_module(void) +void cam_ife_csid_lite_exit_module(void) { platform_driver_unregister(&cam_ife_csid_lite_driver); } -module_init(cam_ife_csid_lite_init_module); -module_exit(cam_ife_csid_lite_exit_module); MODULE_DESCRIPTION("CAM IFE_CSID_LITE driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile deleted file mode 100644 index 1609a7a04808..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_soc.o cam_vfe_dev.o cam_vfe_core.o -obj-$(CONFIG_SPECTRA_CAMERA) += vfe_bus/ vfe_top/ vfe17x/ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile deleted file mode 100644 index e129ea6999b0..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c index 5336352a4797..bb3c2b12df92 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c @@ -58,17 +58,16 @@ static struct platform_driver cam_vfe_driver = { }, }; -static int __init cam_vfe_init_module(void) +int cam_vfe_init_module(void) { return platform_driver_register(&cam_vfe_driver); } -static void __exit cam_vfe_exit_module(void) + +void cam_vfe_exit_module(void) { platform_driver_unregister(&cam_vfe_driver); } -module_init(cam_vfe_init_module); -module_exit(cam_vfe_exit_module); MODULE_DESCRIPTION("CAM VFE driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.h new file mode 100644 index 000000000000..5c2d1ef0eb1d --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_H_ +#define _CAM_VFE_H_ + +/** + * @brief : API to register VFE hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_vfe_init_module(void); + +/** + * @brief : API to remove VFE Hw from platform framework. + */ +void cam_vfe_exit_module(void); + +#endif /* _CAM_VFE_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile deleted file mode 100644 index d5ab83c81dd7..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_bus.o cam_vfe_bus_ver2.o cam_vfe_bus_rd_ver1.o cam_vfe_bus_ver3.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile deleted file mode 100644 index 2ab4651e4271..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o cam_vfe_top.o cam_vfe_top_common.o -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_top_ver3.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_ver3.o cam_vfe_rdi.o cam_vfe_fe_ver1.o cam_vfe_camif_lite_ver3.o diff --git a/drivers/cam_jpeg/Makefile b/drivers/cam_jpeg/Makefile deleted file mode 100644 index 03a132a8f8e6..000000000000 --- a/drivers/cam_jpeg/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/ - -obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_dev.o cam_jpeg_context.o diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 0a68ce997283..777ec5b4804b 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -185,17 +185,15 @@ static struct platform_driver jpeg_driver = { }, }; -static int __init cam_jpeg_dev_init_module(void) +int cam_jpeg_dev_init_module(void) { return platform_driver_register(&jpeg_driver); } -static void __exit cam_jpeg_dev_exit_module(void) +void cam_jpeg_dev_exit_module(void) { platform_driver_unregister(&jpeg_driver); } -module_init(cam_jpeg_dev_init_module); -module_exit(cam_jpeg_dev_exit_module); MODULE_DESCRIPTION("MSM JPEG driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_jpeg/cam_jpeg_dev.h b/drivers/cam_jpeg/cam_jpeg_dev.h index 4961527de1a7..f5b83d93422a 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.h +++ b/drivers/cam_jpeg/cam_jpeg_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_JPEG_DEV_H_ @@ -29,4 +29,15 @@ struct cam_jpeg_dev { struct mutex jpeg_mutex; int32_t open_cnt; }; + +/** + * @brief : API to register JPEG dev to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_jpeg_dev_init_module(void); + +/** + * @brief : API to remove JPEG dev from platform framework. + */ +void cam_jpeg_dev_exit_module(void); #endif /* __CAM_JPEG_DEV_H__ */ diff --git a/drivers/cam_jpeg/jpeg_hw/Makefile b/drivers/cam_jpeg/jpeg_hw/Makefile deleted file mode 100644 index f189bd13a244..000000000000 --- a/drivers/cam_jpeg/jpeg_hw/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include/ - -obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_hw_mgr.o diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile deleted file mode 100644 index f0162f98833a..000000000000 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw - -obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_dev.o jpeg_dma_core.o jpeg_dma_soc.o diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h index dc3a1c13fe82..6b7c8344a292 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -41,4 +41,14 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data); +/** + * @brief : API to register JPEG DMA hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_jpeg_dma_init_module(void); + +/** + * @brief : API to remove JPEG DMA Hw from platform framework. + */ +void cam_jpeg_dma_exit_module(void); #endif /* CAM_JPEG_DMA_CORE_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index ce82c5e799c5..f717d68c8eed 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -22,7 +22,6 @@ static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { .reserved = 0, }; -EXPORT_SYMBOL(cam_jpeg_dma_hw_info); static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, struct cam_jpeg_dma_device_core_info *core_info, @@ -217,17 +216,15 @@ static struct platform_driver cam_jpeg_dma_driver = { }, }; -static int __init cam_jpeg_dma_init_module(void) +int cam_jpeg_dma_init_module(void) { return platform_driver_register(&cam_jpeg_dma_driver); } -static void __exit cam_jpeg_dma_exit_module(void) +void cam_jpeg_dma_exit_module(void) { platform_driver_unregister(&cam_jpeg_dma_driver); } -module_init(cam_jpeg_dma_init_module); -module_exit(cam_jpeg_dma_exit_module); MODULE_DESCRIPTION("CAM JPEG_DMA driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile deleted file mode 100644 index 159c54bbed0c..000000000000 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw - -obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_dev.o jpeg_enc_core.o jpeg_enc_soc.o diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h index df9341c90c77..598158ad1e1f 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h @@ -76,4 +76,14 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data); +/** + * @brief : API to register JPEG ENC hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_jpeg_enc_init_module(void); + +/** + * @brief : API to remove JPEG ENC Hw from platform framework. + */ +void cam_jpeg_enc_exit_module(void); #endif /* CAM_JPEG_ENC_CORE_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index 8eb8ec367850..b6ab52f377c5 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -215,17 +215,15 @@ static struct platform_driver cam_jpeg_enc_driver = { }, }; -static int __init cam_jpeg_enc_init_module(void) +int cam_jpeg_enc_init_module(void) { return platform_driver_register(&cam_jpeg_enc_driver); } -static void __exit cam_jpeg_enc_exit_module(void) +void cam_jpeg_enc_exit_module(void) { platform_driver_unregister(&cam_jpeg_enc_driver); } -module_init(cam_jpeg_enc_init_module); -module_exit(cam_jpeg_enc_exit_module); MODULE_DESCRIPTION("CAM JPEG_ENC driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_lrme/Makefile b/drivers/cam_lrme/Makefile deleted file mode 100644 index 6aa9701dbd15..000000000000 --- a/drivers/cam_lrme/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/ - -obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw_mgr/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_dev.o cam_lrme_context.o diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 7c09f2b435f5..0670132fc8d5 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -219,17 +219,15 @@ static struct platform_driver cam_lrme_driver = { }, }; -static int __init cam_lrme_dev_init_module(void) +int cam_lrme_dev_init_module(void) { return platform_driver_register(&cam_lrme_driver); } -static void __exit cam_lrme_dev_exit_module(void) +void cam_lrme_dev_exit_module(void) { platform_driver_unregister(&cam_lrme_driver); } -module_init(cam_lrme_dev_init_module); -module_exit(cam_lrme_dev_exit_module); MODULE_DESCRIPTION("MSM LRME driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_lrme/cam_lrme_dev.h b/drivers/cam_lrme/cam_lrme_dev.h new file mode 100644 index 000000000000..e8f4dcfc72df --- /dev/null +++ b/drivers/cam_lrme/cam_lrme_dev.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_LRME_DEV_H_ +#define _CAM_LRME_DEV_H_ + +/** + * @brief : API to register LRME dev to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_lrme_dev_init_module(void); + +/** + * @brief : API to remove LRME dev from platform framework. + */ +void cam_lrme_dev_exit_module(void); + +#endif /* _CAM_LRME_DEV_H_ */ diff --git a/drivers/cam_lrme/lrme_hw_mgr/Makefile b/drivers/cam_lrme/lrme_hw_mgr/Makefile deleted file mode 100644 index 37cd971bdccb..000000000000 --- a/drivers/cam_lrme/lrme_hw_mgr/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_mgr.o diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile deleted file mode 100644 index a1a15add9202..000000000000 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_dev.o cam_lrme_hw_core.o cam_lrme_hw_soc.o diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c index 4e2609648b30..6ea5d343ec4e 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c @@ -287,17 +287,15 @@ static struct platform_driver cam_lrme_hw_driver = { }, }; -static int __init cam_lrme_hw_init_module(void) +int cam_lrme_hw_init_module(void) { return platform_driver_register(&cam_lrme_hw_driver); } -static void __exit cam_lrme_hw_exit_module(void) +void cam_lrme_hw_exit_module(void) { platform_driver_unregister(&cam_lrme_hw_driver); } -module_init(cam_lrme_hw_init_module); -module_exit(cam_lrme_hw_exit_module); MODULE_DESCRIPTION("CAM LRME HW driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h index b74d53700419..161b9b017597 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_LRME_HW_INTF_H_ @@ -192,4 +192,14 @@ struct cam_lrme_hw_submit_args { struct cam_lrme_frame_request *frame_req; }; +/** + * @brief : API to register LRME hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_lrme_hw_init_module(void); + +/** + * @brief : API to remove LRME Hw from platform framework. + */ +void cam_lrme_hw_exit_module(void); #endif /* _CAM_LRME_HW_INTF_H_ */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 3f9db55ab9a1..505a036e0c65 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -605,12 +605,6 @@ void cam_video_device_cleanup(void) g_dev.video = NULL; } -void cam_register_subdev_fops(struct v4l2_file_operations *fops) -{ - *fops = v4l2_subdev_fops; -} -EXPORT_SYMBOL(cam_register_subdev_fops); - int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -758,7 +752,7 @@ static const struct of_device_id cam_req_mgr_dt_match[] = { {.compatible = "qcom,cam-req-mgr"}, {} }; -MODULE_DEVICE_TABLE(of, cam_dt_match); +MODULE_DEVICE_TABLE(of, cam_req_mgr_dt_match); static struct platform_driver cam_req_mgr_driver = { .probe = cam_req_mgr_probe, @@ -810,23 +804,21 @@ create_fail: return rc; } -static int __init cam_req_mgr_init(void) +int cam_req_mgr_init(void) { return platform_driver_register(&cam_req_mgr_driver); } +EXPORT_SYMBOL(cam_req_mgr_init); -static int __init cam_req_mgr_late_init(void) +int cam_req_mgr_late_init(void) { return cam_dev_mgr_create_subdev_nodes(); } -static void __exit cam_req_mgr_exit(void) +void cam_req_mgr_exit(void) { platform_driver_unregister(&cam_req_mgr_driver); } -module_init(cam_req_mgr_init); -late_initcall(cam_req_mgr_late_init); -module_exit(cam_req_mgr_exit); MODULE_DESCRIPTION("Camera Request Manager"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 48ad09ce5ee2..0b7a1e943965 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -1,11 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_DEV_H_ #define _CAM_REQ_MGR_DEV_H_ +#include "media/cam_req_mgr.h" /** * struct cam_req_mgr_device - a camera request manager device * @@ -40,4 +41,21 @@ int cam_req_mgr_notify_message(struct cam_req_mgr_message *msg, uint32_t id, uint32_t type); +/** + * @brief : API to register REQ_MGR to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_req_mgr_init(void); + +/** + * @brief : API to register all subdev with v4l2 framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_req_mgr_late_init(void); + +/** + * @brief : API to remove REQ_MGR from platform framework. + */ +void cam_req_mgr_exit(void); + #endif /* _CAM_REQ_MGR_DEV_H_ */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index 385643d5e532..05aee58797b9 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SUBDEV_H_ @@ -74,15 +74,6 @@ int cam_subdev_probe(struct cam_subdev *sd, struct platform_device *pdev, */ int cam_subdev_remove(struct cam_subdev *sd); -/** - * cam_register_subdev_fops() - * - * @brief: This common utility function assigns subdev ops - * - * @fops: v4l file operations - */ -void cam_register_subdev_fops(struct v4l2_file_operations *fops); - /** * cam_register_subdev() * diff --git a/drivers/cam_sensor_module/Makefile b/drivers/cam_sensor_module/Makefile deleted file mode 100644 index 6925b3aba80f..000000000000 --- a/drivers/cam_sensor_module/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_res_mgr/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_utils/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cci/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/ diff --git a/drivers/cam_sensor_module/cam_actuator/Makefile b/drivers/cam_sensor_module/cam_actuator/Makefile deleted file mode 100644 index 480cea767710..000000000000 --- a/drivers/cam_sensor_module/cam_actuator/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils - - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator_dev.o cam_actuator_core.o cam_actuator_soc.o diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 46bd99fc9e29..92c9e6591012 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include "cam_actuator_dev.h" @@ -413,7 +413,7 @@ static struct i2c_driver cam_actuator_driver_i2c = { }, }; -static int __init cam_actuator_driver_init(void) +int cam_actuator_driver_init(void) { int32_t rc = 0; @@ -430,13 +430,11 @@ static int __init cam_actuator_driver_init(void) return rc; } -static void __exit cam_actuator_driver_exit(void) +void cam_actuator_driver_exit(void) { platform_driver_unregister(&cam_actuator_platform_driver); i2c_del_driver(&cam_actuator_driver_i2c); } -module_init(cam_actuator_driver_init); -module_exit(cam_actuator_driver_exit); MODULE_DESCRIPTION("cam_actuator_driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h index e4bfaed4414f..1ec575301cfc 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -64,13 +64,13 @@ struct cam_actuator_soc_private { }; /** - * struct intf_params + * struct actuator_intf_params * @device_hdl: Device Handle * @session_hdl: Session Handle * @ops: KMD operations * @crm_cb: Callback API pointers */ -struct intf_params { +struct actuator_intf_params { int32_t device_hdl; int32_t session_hdl; int32_t link_hdl; @@ -113,8 +113,18 @@ struct cam_actuator_ctrl_t { struct cam_subdev v4l2_dev_str; struct i2c_data_settings i2c_data; struct cam_actuator_query_cap act_info; - struct intf_params bridge_intf; + struct actuator_intf_params bridge_intf; uint32_t last_flush_req; }; +/** + * @brief : API to register Actuator hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_actuator_driver_init(void); + +/** + * @brief : API to remove Actuator Hw from platform framework. + */ +void cam_actuator_driver_exit(void); #endif /* _CAM_ACTUATOR_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_cci/Makefile b/drivers/cam_sensor_module/cam_cci/Makefile deleted file mode 100644 index 4a93880a7260..000000000000 --- a/drivers/cam_sensor_module/cam_cci/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree) - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cci_dev.o cam_cci_core.o cam_cci_soc.o diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index e52e16cb5f96..48552c82239b 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -308,7 +308,6 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cam_io_w_mb(irq_update_rd_done, base + CCI_IRQ_MASK_1_ADDR); } - cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR); cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); return IRQ_HANDLED; @@ -341,34 +340,6 @@ static const struct v4l2_subdev_ops cci_subdev_ops = { static const struct v4l2_subdev_internal_ops cci_subdev_intern_ops; -static struct v4l2_file_operations cci_v4l2_subdev_fops; - -static long cam_cci_subdev_do_ioctl( - struct file *file, unsigned int cmd, void *arg) -{ - struct video_device *vdev = video_devdata(file); - struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - - return cam_cci_subdev_ioctl(sd, cmd, NULL); -} - -static long cam_cci_subdev_fops_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return video_usercopy(file, cmd, arg, cam_cci_subdev_do_ioctl); -} - -#ifdef CONFIG_COMPAT -static long cam_cci_subdev_fops_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct video_device *vdev = video_devdata(file); - struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - - return v4l2_subdev_call(sd, core, ioctl, cmd, NULL); -} -#endif - static int cam_cci_platform_probe(struct platform_device *pdev) { struct cam_cpas_register_params cpas_parms; @@ -428,13 +399,6 @@ static int cam_cci_platform_probe(struct platform_device *pdev) mutex_init(&(new_cci_dev->init_mutex)); CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); - cam_register_subdev_fops(&cci_v4l2_subdev_fops); - cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl; -#ifdef CONFIG_COMPAT - cci_v4l2_subdev_fops.compat_ioctl32 = - cam_cci_subdev_fops_compat_ioctl; -#endif - cpas_parms.cam_cpas_client_cb = NULL; cpas_parms.cell_index = soc_info->index; cpas_parms.dev = &pdev->dev; @@ -485,44 +449,15 @@ static struct platform_driver cci_driver = { }, }; -static int cam_cci_assign_fops(void) -{ - struct v4l2_subdev *sd; - int i = 0; - - for (; i < MAX_CCI; i++) { - sd = g_cci_subdev[i]; - if (!sd) - return 0; - if (!(sd->devnode)) { - CAM_ERR(CAM_CCI, - "Invalid dev node:%pK offset: %d", - sd->devnode, i); - return -EINVAL; - } - sd->devnode->fops = &cci_v4l2_subdev_fops; - } - - return 0; -} - -static int __init cam_cci_late_init(void) -{ - return cam_cci_assign_fops(); -} - -static int __init cam_cci_init_module(void) +int cam_cci_init_module(void) { return platform_driver_register(&cci_driver); } -static void __exit cam_cci_exit_module(void) +void cam_cci_exit_module(void) { platform_driver_unregister(&cci_driver); } -module_init(cam_cci_init_module); -late_initcall(cam_cci_late_init); -module_exit(cam_cci_exit_module); MODULE_DESCRIPTION("MSM CCI driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index d65f5e5fd271..634a1c54dfe2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -297,6 +297,16 @@ irqreturn_t cam_cci_irq(int irq_num, void *data); struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index); +/** + * @brief : API to register CCI hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_cci_init_module(void); + +/** + * @brief : API to remove CCI Hw from platform framework. + */ +void cam_cci_exit_module(void); #define VIDIOC_MSM_CCI_CFG \ _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl *) diff --git a/drivers/cam_sensor_module/cam_csiphy/Makefile b/drivers/cam_sensor_module/cam_csiphy/Makefile deleted file mode 100644 index 3cbc09d0b111..000000000000 --- a/drivers/cam_sensor_module/cam_csiphy/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy_soc.o cam_csiphy_dev.o cam_csiphy_core.o diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 9d5976d86f26..fdab05b0e353 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -632,7 +632,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, { struct csiphy_device *csiphy_dev = (struct csiphy_device *)phy_dev; - struct intf_params *bridge_intf = NULL; + struct csiphy_intf_params *bridge_intf = NULL; struct cam_control *cmd = (struct cam_control *)arg; int32_t rc = 0; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index ba98d9adcc2d..0e15bcf9d2a5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include "cam_csiphy_dev.h" @@ -237,17 +237,15 @@ static struct platform_driver csiphy_driver = { }, }; -static int32_t __init cam_csiphy_init_module(void) +int32_t cam_csiphy_init_module(void) { return platform_driver_register(&csiphy_driver); } -static void __exit cam_csiphy_exit_module(void) +void cam_csiphy_exit_module(void) { platform_driver_unregister(&csiphy_driver); } -module_init(cam_csiphy_init_module); -module_exit(cam_csiphy_exit_module); MODULE_DESCRIPTION("CAM CSIPHY driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 78c7a848cd81..1e22c8c5288c 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -120,13 +120,13 @@ struct csiphy_reg_parms_t { }; /** - * struct intf_params + * struct csiphy_intf_params * @device_hdl: Device Handle * @session_hdl: Session Handle * @ops: KMD operations * @crm_cb: Callback API pointers */ -struct intf_params { +struct csiphy_intf_params { int32_t device_hdl[CSIPHY_MAX_INSTANCES]; int32_t session_hdl[CSIPHY_MAX_INSTANCES]; int32_t link_hdl[CSIPHY_MAX_INSTANCES]; @@ -281,7 +281,7 @@ struct csiphy_device { uint8_t num_irq_registers; struct cam_subdev v4l2_dev_str; struct cam_csiphy_param csiphy_info; - struct intf_params bridge_intf; + struct csiphy_intf_params bridge_intf; uint32_t clk_lane; uint32_t acquire_count; uint32_t start_dev_count; @@ -292,4 +292,14 @@ struct csiphy_device { uint64_t csiphy_cpas_cp_reg_mask[CSIPHY_MAX_INSTANCES]; }; +/** + * @brief : API to register CSIPHY hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int32_t cam_csiphy_init_module(void); + +/** + * @brief : API to remove CSIPHY Hw from platform framework. + */ +void cam_csiphy_exit_module(void); #endif /* _CAM_CSIPHY_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_eeprom/Makefile b/drivers/cam_sensor_module/cam_eeprom/Makefile deleted file mode 100644 index f978136982eb..000000000000 --- a/drivers/cam_sensor_module/cam_eeprom/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom_dev.o cam_eeprom_core.o cam_eeprom_soc.o diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 328541553b59..5fedbed5aa12 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -555,7 +555,7 @@ static struct spi_driver cam_eeprom_spi_driver = { .probe = cam_eeprom_spi_driver_probe, .remove = cam_eeprom_spi_driver_remove, }; -static int __init cam_eeprom_driver_init(void) +int cam_eeprom_driver_init(void) { int rc = 0; @@ -581,14 +581,12 @@ static int __init cam_eeprom_driver_init(void) return rc; } -static void __exit cam_eeprom_driver_exit(void) +void cam_eeprom_driver_exit(void) { platform_driver_unregister(&cam_eeprom_platform_driver); spi_unregister_driver(&cam_eeprom_spi_driver); i2c_del_driver(&cam_eeprom_i2c_driver); } -module_init(cam_eeprom_driver_init); -module_exit(cam_eeprom_driver_exit); MODULE_DESCRIPTION("CAM EEPROM driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h index 66f8aaddc958..7f2f27687485 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -195,4 +195,15 @@ struct cam_eeprom_ctrl_t { int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_i2c_info_t *i2c_info); +/** + * @brief : API to register EEPROM hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_eeprom_driver_init(void); + +/** + * @brief : API to remove EEPROM Hw from platform framework. + */ +void cam_eeprom_driver_exit(void); + #endif /*_CAM_EEPROM_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_flash/Makefile b/drivers/cam_sensor_module/cam_flash/Makefile deleted file mode 100644 index 967d50dd25eb..000000000000 --- a/drivers/cam_sensor_module/cam_flash/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash_dev.o cam_flash_core.o cam_flash_soc.o diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 5eccfd8aa11b..868d30a85900 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -626,7 +626,7 @@ static struct i2c_driver cam_flash_i2c_driver = { }, }; -static int32_t __init cam_flash_init_module(void) +int32_t cam_flash_init_module(void) { int32_t rc = 0; @@ -642,13 +642,11 @@ static int32_t __init cam_flash_init_module(void) return rc; } -static void __exit cam_flash_exit_module(void) +void cam_flash_exit_module(void) { platform_driver_unregister(&cam_flash_platform_driver); i2c_del_driver(&cam_flash_i2c_driver); } -module_init(cam_flash_init_module); -module_exit(cam_flash_exit_module); MODULE_DESCRIPTION("CAM FLASH"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 29e352e47ce9..59911a5fb3a8 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -225,4 +225,14 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, void cam_flash_shutdown(struct cam_flash_ctrl *fctrl); int cam_flash_release_dev(struct cam_flash_ctrl *fctrl); +/** + * @brief : API to register FLASH hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int32_t cam_flash_init_module(void); + +/** + * @brief : API to remove FLASH Hw from platform framework. + */ +void cam_flash_exit_module(void); #endif /*_CAM_FLASH_DEV_H_*/ diff --git a/drivers/cam_sensor_module/cam_ois/Makefile b/drivers/cam_sensor_module/cam_ois/Makefile deleted file mode 100644 index 8658af35e435..000000000000 --- a/drivers/cam_sensor_module/cam_ois/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 10044cec6efd..667cbb44eef8 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include "cam_ois_dev.h" @@ -384,7 +384,7 @@ static struct i2c_driver cam_ois_i2c_driver = { static struct cam_ois_registered_driver_t registered_driver = { 0, 0}; -static int __init cam_ois_driver_init(void) +int cam_ois_driver_init(void) { int rc = 0; @@ -407,7 +407,7 @@ static int __init cam_ois_driver_init(void) return rc; } -static void __exit cam_ois_driver_exit(void) +void cam_ois_driver_exit(void) { if (registered_driver.platform_driver) platform_driver_unregister(&cam_ois_platform_driver); @@ -416,7 +416,5 @@ static void __exit cam_ois_driver_exit(void) i2c_del_driver(&cam_ois_i2c_driver); } -module_init(cam_ois_driver_init); -module_exit(cam_ois_driver_exit); MODULE_DESCRIPTION("CAM OIS driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index 788243ae9da0..eb0a69d11278 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -124,4 +124,14 @@ struct cam_ois_ctrl_t { struct cam_ois_opcode opcode; }; +/** + * @brief : API to register OIS hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_ois_driver_init(void); + +/** + * @brief : API to remove OIS Hw from platform framework. + */ +void cam_ois_driver_exit(void); #endif /*_CAM_OIS_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_res_mgr/Makefile b/drivers/cam_sensor_module/cam_res_mgr/Makefile deleted file mode 100644 index d0ba37e3763a..000000000000 --- a/drivers/cam_sensor_module/cam_res_mgr/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_res_mgr.o diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index c87540f7950f..009043acbc29 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -723,17 +723,15 @@ static struct platform_driver cam_res_mgr_driver = { }, }; -static int __init cam_res_mgr_init(void) +int cam_res_mgr_init(void) { return platform_driver_register(&cam_res_mgr_driver); } -static void __exit cam_res_mgr_exit(void) +void cam_res_mgr_exit(void) { platform_driver_unregister(&cam_res_mgr_driver); } -module_init(cam_res_mgr_init); -module_exit(cam_res_mgr_exit); MODULE_DESCRIPTION("Camera resource manager driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h index e259ba7f2c78..b47c68dea675 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef __CAM_RES_MGR_API_H__ @@ -138,4 +138,14 @@ int cam_res_mgr_gpio_set_value(unsigned int gpio, int value); */ void cam_res_mgr_shared_clk_config(bool value); +/** + * @brief : API to register RES_MGR to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_res_mgr_init(void); + +/** + * @brief : API to remove RES_MGR from platform framework. + */ +void cam_res_mgr_exit(void); #endif /* __CAM_RES_MGR_API_H__ */ diff --git a/drivers/cam_sensor_module/cam_sensor/Makefile b/drivers/cam_sensor_module/cam_sensor/Makefile deleted file mode 100644 index 77ccd7fe2c97..000000000000 --- a/drivers/cam_sensor_module/cam_sensor/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_dev.o cam_sensor_core.o cam_sensor_soc.o diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 765a1244a0aa..848234196e3f 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -366,7 +366,7 @@ static struct i2c_driver cam_sensor_driver_i2c = { }, }; -static int __init cam_sensor_driver_init(void) +int cam_sensor_driver_init(void) { int32_t rc = 0; @@ -384,13 +384,11 @@ static int __init cam_sensor_driver_init(void) return rc; } -static void __exit cam_sensor_driver_exit(void) +void cam_sensor_driver_exit(void) { platform_driver_unregister(&cam_sensor_platform_driver); i2c_del_driver(&cam_sensor_driver_i2c); } -module_init(cam_sensor_driver_init); -module_exit(cam_sensor_driver_exit); MODULE_DESCRIPTION("cam_sensor_driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h index b1963e15eb59..8586ce51c87f 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -46,14 +46,14 @@ enum cam_sensor_state_t { }; /** - * struct intf_params + * struct sensor_intf_params * @device_hdl: Device Handle * @session_hdl: Session Handle * @link_hdl: Link Handle * @ops: KMD operations * @crm_cb: Callback API pointers */ -struct intf_params { +struct sensor_intf_params { int32_t device_hdl; int32_t session_hdl; int32_t link_hdl; @@ -104,7 +104,7 @@ struct cam_sensor_ctrl_t { uint8_t sensor_probe_data_type; struct i2c_data_settings i2c_data; struct cam_sensor_query_cap sensor_info; - struct intf_params bridge_intf; + struct sensor_intf_params bridge_intf; uint32_t streamon_count; uint32_t streamoff_count; int bob_reg_index; @@ -113,4 +113,15 @@ struct cam_sensor_ctrl_t { uint16_t pipeline_delay; }; +/** + * @brief : API to register SENSOR hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_sensor_driver_init(void); + +/** + * @brief : API to remove SENSOR Hw from platform framework. + */ +void cam_sensor_driver_exit(void); + #endif /* _CAM_SENSOR_DEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_sensor_io/Makefile b/drivers/cam_sensor_module/cam_sensor_io/Makefile deleted file mode 100644 index b41cd60c6cb8..000000000000 --- a/drivers/cam_sensor_module/cam_sensor_io/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o cam_sensor_spi.o diff --git a/drivers/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/cam_sensor_module/cam_sensor_utils/Makefile deleted file mode 100644 index 8c76ba286ea2..000000000000 --- a/drivers/cam_sensor_module/cam_sensor_utils/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(src) - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_util.o diff --git a/drivers/cam_smmu/Makefile b/drivers/cam_smmu/Makefile deleted file mode 100644 index 89b2c967ce79..000000000000 --- a/drivers/cam_smmu/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu_api.o diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 784ea62e0925..122ed77a7932 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3665,17 +3665,15 @@ static struct platform_driver cam_smmu_driver = { }, }; -static int __init cam_smmu_init_module(void) +int cam_smmu_init_module(void) { return platform_driver_register(&cam_smmu_driver); } -static void __exit cam_smmu_exit_module(void) +void cam_smmu_exit_module(void) { platform_driver_unregister(&cam_smmu_driver); } -module_init(cam_smmu_init_module); -module_exit(cam_smmu_exit_module); MODULE_DESCRIPTION("MSM Camera SMMU driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index 6932505f0aaf..057eb741458d 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -392,4 +392,14 @@ int cam_smmu_dealloc_qdss(int32_t smmu_hdl); int cam_smmu_get_io_region_info(int32_t smmu_hdl, dma_addr_t *iova, size_t *len); +/** + * @brief : API to register SMMU hw to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_smmu_init_module(void); + +/** + * @brief : API to remove SMMU Hw from platform framework. + */ +void cam_smmu_exit_module(void); #endif /* _CAM_SMMU_API_H_ */ diff --git a/drivers/cam_sync/Makefile b/drivers/cam_sync/Makefile deleted file mode 100644 index 2f3247cb0894..000000000000 --- a/drivers/cam_sync/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-$(CONFIG_MSM_GLOBAL_SYNX) += -I$(srctree)/drivers/media/platform/msm/synx -ccflags-y += -I$(src) - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_sync.o cam_sync_util.o diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 33b14f17ceb7..fb0e9495108d 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1128,10 +1128,9 @@ static struct platform_driver cam_sync_driver = { }, }; -static int __init cam_sync_init(void) +int cam_sync_init(void) { int rc; - rc = platform_device_register(&cam_sync_device); if (rc) return -ENODEV; @@ -1139,7 +1138,7 @@ static int __init cam_sync_init(void) return platform_driver_register(&cam_sync_driver); } -static void __exit cam_sync_exit(void) +void cam_sync_exit(void) { int idx; @@ -1150,7 +1149,5 @@ static void __exit cam_sync_exit(void) kfree(sync_dev); } -module_init(cam_sync_init); -module_exit(cam_sync_exit); MODULE_DESCRIPTION("Camera sync driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sync/cam_sync_api.h b/drivers/cam_sync/cam_sync_api.h index 3d99bc15eb18..bce22226f7c2 100644 --- a/drivers/cam_sync/cam_sync_api.h +++ b/drivers/cam_sync/cam_sync_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef __CAM_SYNC_API_H__ @@ -140,5 +140,14 @@ int cam_sync_destroy(int32_t sync_obj); */ int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms); +/** + * @brief : API to register SYNC to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_sync_init(void); +/** + * @brief : API to remove SYNC from platform framework. + */ +void cam_sync_exit(void); #endif /* __CAM_SYNC_API_H__ */ diff --git a/drivers/cam_utils/Makefile b/drivers/cam_utils/Makefile deleted file mode 100644 index 58be3110cbf5..000000000000 --- a/drivers/cam_utils/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/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 - -ifdef CONFIG_QCOM_CX_IPEAK -obj-$(CONFIG_SPECTRA_CAMERA) += cam_cx_ipeak.o -endif diff --git a/drivers/camera_main.c b/drivers/camera_main.c new file mode 100644 index 000000000000..28b40dbd284e --- /dev/null +++ b/drivers/camera_main.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ +#include +#include + +#include "cam_req_mgr_dev.h" +#include "cam_sync_api.h" +#include "cam_smmu_api.h" +#include "cam_cpas_hw_intf.h" +#include "cam_cdm_intf_api.h" + +#include "cam_ife_csid_dev.h" +#include "cam_vfe.h" +#include "cam_isp_dev.h" + +#include "cam_res_mgr_api.h" +#include "cam_cci_dev.h" +#include "cam_sensor_dev.h" +#include "cam_actuator_dev.h" +#include "cam_csiphy_dev.h" +#include "cam_eeprom_dev.h" +#include "cam_ois_dev.h" + +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +#include "cam_flash_dev.h" +#endif + +#include "a5_core.h" +#include "ipe_core.h" +#include "bps_core.h" +#include "cam_icp_subdev.h" + +#include "jpeg_dma_core.h" +#include "jpeg_enc_core.h" +#include "cam_jpeg_dev.h" + +#include "cam_fd_hw_intf.h" +#include "cam_fd_dev.h" + +#include "cam_lrme_hw_intf.h" +#include "cam_lrme_dev.h" + +#include "cam_custom_dev.h" +#include "cam_custom_csid_dev.h" +#include "cam_custom_sub_mod_dev.h" + +struct camera_submodule_component { + int (*init)(void); + void (*exit)(void); +}; + +struct camera_submodule { + char *name; + uint num_component; + const struct camera_submodule_component *component; +}; + +static const struct camera_submodule_component camera_base[] = { + {&cam_req_mgr_init, &cam_req_mgr_exit}, + {&cam_sync_init, &cam_sync_exit}, + {&cam_smmu_init_module, &cam_smmu_exit_module}, + {&cam_cpas_dev_init_module, &cam_cpas_dev_exit_module}, + {&cam_cdm_intf_init_module, &cam_cdm_intf_exit_module}, + {&cam_hw_cdm_init_module, &cam_hw_cdm_exit_module}, +}; + +static const struct camera_submodule_component camera_isp[] = { +#if IS_ENABLED(CONFIG_SPECTRA_ISP) + {&cam_ife_csid17x_init_module, &cam_ife_csid17x_exit_module}, + {&cam_ife_csid_lite_init_module, &cam_ife_csid_lite_exit_module}, + {&cam_vfe_init_module, &cam_vfe_exit_module}, + {&cam_isp_dev_init_module, &cam_isp_dev_exit_module}, +#endif +}; + +static const struct camera_submodule_component camera_sensor[] = { +#if IS_ENABLED(CONFIG_SPECTRA_SENSOR) + {&cam_res_mgr_init, &cam_res_mgr_exit}, + {&cam_cci_init_module, &cam_cci_exit_module}, + {&cam_csiphy_init_module, &cam_csiphy_exit_module}, + {&cam_actuator_driver_init, &cam_actuator_driver_exit}, + {&cam_sensor_driver_init, &cam_sensor_driver_exit}, + {&cam_eeprom_driver_init, &cam_eeprom_driver_exit}, + {&cam_ois_driver_init, &cam_ois_driver_exit}, +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) + {&cam_flash_init_module, &cam_flash_exit_module}, +#endif +#endif +}; + +static const struct camera_submodule_component camera_icp[] = { +#if IS_ENABLED(CONFIG_SPECTRA_ICP) + {&cam_a5_init_module, &cam_a5_exit_module}, + {&cam_ipe_init_module, &cam_ipe_exit_module}, + {&cam_bps_init_module, &cam_bps_exit_module}, + {&cam_icp_init_module, &cam_icp_exit_module}, +#endif +}; + +static const struct camera_submodule_component camera_jpeg[] = { +#if IS_ENABLED(CONFIG_SPECTRA_JPEG) + {&cam_jpeg_enc_init_module, &cam_jpeg_enc_exit_module}, + {&cam_jpeg_dma_init_module, &cam_jpeg_dma_exit_module}, + {&cam_jpeg_dev_init_module, &cam_jpeg_dev_exit_module}, +#endif +}; + +static const struct camera_submodule_component camera_fd[] = { +#if IS_ENABLED(CONFIG_SPECTRA_FD) + {&cam_fd_hw_init_module, &cam_fd_hw_exit_module}, + {&cam_fd_dev_init_module, &cam_fd_dev_exit_module}, +#endif +}; + +static const struct camera_submodule_component camera_lrme[] = { +#if IS_ENABLED(CONFIG_SPECTRA_LRME) + {&cam_lrme_hw_init_module, &cam_lrme_hw_exit_module}, + {&cam_lrme_dev_init_module, &cam_lrme_dev_exit_module}, +#endif +}; + +static const struct camera_submodule_component camera_custom[] = { +#if IS_ENABLED(CONFIG_SPECTRA_CUSTOM) + {&cam_custom_hw_sub_module_init, &cam_custom_hw_sub_module_exit}, + {&cam_custom_csid_driver_init, &cam_custom_csid_driver_exit}, + {&cam_custom_dev_init_module, &cam_custom_dev_exit_module}, +#endif +}; + +static const struct camera_submodule submodule_table[] = { + { + .name = "Camera BASE", + .num_component = ARRAY_SIZE(camera_base), + .component = camera_base, + }, + { + .name = "Camera ISP", + .num_component = ARRAY_SIZE(camera_isp), + .component = camera_isp, + }, + { + .name = "Camera SENSOR", + .num_component = ARRAY_SIZE(camera_sensor), + .component = camera_sensor + }, + { + .name = "Camera ICP", + .num_component = ARRAY_SIZE(camera_icp), + .component = camera_icp, + }, + { + .name = "Camera JPEG", + .num_component = ARRAY_SIZE(camera_jpeg), + .component = camera_jpeg, + }, + { + .name = "Camera FD", + .num_component = ARRAY_SIZE(camera_fd), + .component = camera_fd, + }, + { + .name = "Camera LRME", + .num_component = ARRAY_SIZE(camera_lrme), + .component = camera_lrme, + }, + { + .name = "Camera CUSTOM", + .num_component = ARRAY_SIZE(camera_custom), + .component = camera_custom, + } +}; + +static int camera_verify_submodules(void) +{ + int rc = 0; + int i, j, num_components; + + for (i = 0; i < ARRAY_SIZE(submodule_table); i++) { + num_components = submodule_table[i].num_component; + for (j = 0; j < num_components; j++) { + if (!submodule_table[i].component[j].init || + !submodule_table[i].component[j].exit) { + CAM_ERR(CAM_UTIL, + "%s module has init = %ps, exit = %ps", + submodule_table[i].name, + submodule_table[i].component[j].init, + submodule_table[i].component[j].exit); + rc = -EINVAL; + goto err; + } + } + } + +err: + return rc; +} + +static void camera_error_exit(int i, int j) +{ + uint num_exits; + + /* Exit from current submodule */ + for (j -= 1; j >= 0; j--) + submodule_table[i].component[j].exit(); + + /* Exit remaining submodules */ + for (i -= 1; i >= 0; i--) { + num_exits = submodule_table[i].num_component; + for (j = num_exits - 1; j >= 0; j--) + submodule_table[i].component[j].exit(); + } +} + +static int camera_init(void) +{ + int rc; + uint i, j, num_inits; + + rc = camera_verify_submodules(); + if (rc) + goto end_init; + + /* For Probing all available submodules */ + for (i = 0; i < ARRAY_SIZE(submodule_table); i++) { + num_inits = submodule_table[i].num_component; + for (j = 0; j < num_inits; j++) { + rc = submodule_table[i].component[j].init(); + if (rc) { + CAM_ERR(CAM_UTIL, + "%s module failure at %ps rc = %d", + submodule_table[i].name, + submodule_table[i].component[j].init, + rc); + camera_error_exit(i, j); + goto end_init; + } + } + } + + rc = cam_req_mgr_late_init(); + if (rc) { + CAM_ERR(CAM_UTIL, + "Late_init Sequence/Subdev node creation fail: rc = %d", + rc); + camera_error_exit(i, j); + goto end_init; + } + + CAM_INFO(CAM_UTIL, "Camera driver initialized"); + +end_init: + return rc; +} + +static void camera_exit(void) +{ + uint i, j, num_exits; + + for (i = ARRAY_SIZE(submodule_table) - 1; i >= 0; i--) { + num_exits = submodule_table[i].num_component; + for (j = num_exits - 1; j >= 0; j--) + submodule_table[i].component[j].exit(); + } + + CAM_INFO(CAM_UTIL, "Camera driver exited!"); +} + +module_init(camera_init); +module_exit(camera_exit); + +MODULE_DESCRIPTION("Spectra_Camera Driver"); +MODULE_LICENSE("GPL v2"); From 8a40a542fd3aebc307b9cdf959626f45a107ac38 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 25 Oct 2019 11:23:12 -0700 Subject: [PATCH 184/790] msm: camera: common: Add support for icc and switching bus scaling Add support for disabling bus scaling by moving bus driver references from cpas to cam utils. The references can be switched based on compile time flags in defconfig. Also, add interconnect support which has bw voting based on source and destination bus IDs. CRs-Fixed: 2525881 Change-Id: I2a78523c0cad41503fe32aeb7bf4c794a26b16b6 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Jigarkumar Zala --- drivers/Makefile | 8 ++ drivers/cam_cpas/cam_cpas_hw.c | 175 ++++++++---------------- drivers/cam_cpas/cam_cpas_hw.h | 31 ++--- drivers/cam_cpas/cam_cpas_soc.c | 198 +++++++++++++++++++++++++-- drivers/cam_cpas/cam_cpas_soc.h | 2 + drivers/cam_utils/cam_soc_bus.c | 232 ++++++++++++++++++++++++++++++++ drivers/cam_utils/cam_soc_bus.h | 96 +++++++++++++ drivers/cam_utils/cam_soc_icc.c | 149 ++++++++++++++++++++ 8 files changed, 737 insertions(+), 154 deletions(-) create mode 100644 drivers/cam_utils/cam_soc_bus.c create mode 100644 drivers/cam_utils/cam_soc_bus.h create mode 100644 drivers/cam_utils/cam_soc_icc.c diff --git a/drivers/Makefile b/drivers/Makefile index a59a49ce1be5..01e4e572c8bf 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -49,6 +49,14 @@ ifdef CONFIG_QCOM_CX_IPEAK camera-y += cam_utils/cam_cx_ipeak.o endif +ifneq (,$(filter $(CONFIG_QCOM_BUS_SCALING),y m)) +camera-y += cam_utils/cam_soc_bus.o +endif + +ifneq (,$(filter $(CONFIG_INTERCONNECT_QCOM),y m)) +camera-y += cam_utils/cam_soc_icc.o +endif + camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.o \ cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.o \ diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index ae0368acdb05..061d2594421a 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -56,73 +55,54 @@ int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, static int cam_cpas_util_vote_bus_client_level( struct cam_cpas_bus_client *bus_client, unsigned int level) { - if (!bus_client->valid || (bus_client->dyn_vote == true)) { - CAM_ERR(CAM_CPAS, "Invalid params %d %d", bus_client->valid, - bus_client->dyn_vote); - return -EINVAL; - } + int rc = 0; - if (level >= bus_client->num_usecases) { - CAM_ERR(CAM_CPAS, "Invalid vote level=%d, usecases=%d", level, - bus_client->num_usecases); - return -EINVAL; + if (!bus_client->valid) { + CAM_ERR(CAM_CPAS, "bus client not valid"); + rc = -EINVAL; + goto end; } if (level == bus_client->curr_vote_level) - return 0; + goto end; - CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] index[%d]", - bus_client->client_id, bus_client->name, level); - msm_bus_scale_client_update_request(bus_client->client_id, level); + rc = cam_soc_bus_client_update_request(bus_client->soc_bus_client, + level); + if (rc) { + CAM_ERR(CAM_CPAS, "Client: %s update request failed rc: %d", + bus_client->common_data.name, rc); + goto end; + } bus_client->curr_vote_level = level; - return 0; +end: + return rc; } static int cam_cpas_util_vote_bus_client_bw( struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib, bool camnoc_bw) { - struct msm_bus_paths *path; - struct msm_bus_scale_pdata *pdata; - int idx = 0; + int rc = 0; uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; + if (!bus_client->valid) { + CAM_ERR(CAM_CPAS, "bus client: %s not valid", + bus_client->common_data.name); + rc = -EINVAL; + goto end; + } + if (cam_min_camnoc_ib_bw > 0) min_camnoc_ib_bw = (uint64_t)cam_min_camnoc_ib_bw * 1000000L; - CAM_DBG(CAM_CPAS, "cam_min_camnoc_ib_bw = %d, min_camnoc_ib_bw=%llu", - cam_min_camnoc_ib_bw, min_camnoc_ib_bw); - - if (!bus_client->valid) { - CAM_ERR(CAM_CPAS, "bus client not valid"); - return -EINVAL; - } - - if ((bus_client->num_usecases != 2) || - (bus_client->num_paths != 1) || - (bus_client->dyn_vote != true)) { - CAM_ERR(CAM_CPAS, "dynamic update not allowed %d %d %d", - bus_client->num_usecases, bus_client->num_paths, - bus_client->dyn_vote); - return -EINVAL; - } + CAM_DBG(CAM_CPAS, + "Bus_client: %s, cam_min_camnoc_ib_bw = %d, min_camnoc_ib_bw=%llu", + bus_client->common_data.name, cam_min_camnoc_ib_bw, + min_camnoc_ib_bw); mutex_lock(&bus_client->lock); - - if (bus_client->curr_vote_level > 1) { - CAM_ERR(CAM_CPAS, "curr_vote_level %d cannot be greater than 1", - bus_client->curr_vote_level); - mutex_unlock(&bus_client->lock); - return -EINVAL; - } - - idx = bus_client->curr_vote_level; - idx = 1 - idx; - bus_client->curr_vote_level = idx; - mutex_unlock(&bus_client->lock); - - if (camnoc_bw == true) { + if (camnoc_bw) { if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_CAMNOC_AB_BW)) ab = CAM_CPAS_AXI_MIN_CAMNOC_AB_BW; @@ -136,96 +116,51 @@ static int cam_cpas_util_vote_bus_client_bw( ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW; } - pdata = bus_client->pdata; - path = &(pdata->usecase[idx]); - path->vectors[0].ab = ab; - path->vectors[0].ib = ib; + rc = cam_soc_bus_client_update_bw(bus_client->soc_bus_client, ab, ib); + if (rc) { + CAM_ERR(CAM_CPAS, + "Update bw failed, ab[%llu] ib[%llu]", + ab, ib); + goto unlock_client; + } - CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", - bus_client->client_id, bus_client->name, ab, ib, idx); - msm_bus_scale_client_update_request(bus_client->client_id, idx); - - return 0; +unlock_client: + mutex_unlock(&bus_client->lock); +end: + return rc; } static int cam_cpas_util_register_bus_client( struct cam_hw_soc_info *soc_info, struct device_node *dev_node, struct cam_cpas_bus_client *bus_client) { - struct msm_bus_scale_pdata *pdata = NULL; - uint32_t client_id; - int rc; + int rc = 0; - pdata = msm_bus_pdata_from_node(soc_info->pdev, - dev_node); - if (!pdata) { - CAM_ERR(CAM_CPAS, "failed get_pdata"); - return -EINVAL; + rc = cam_soc_bus_client_register(soc_info->pdev, dev_node, + &bus_client->soc_bus_client, &bus_client->common_data); + if (rc) { + CAM_ERR(CAM_CPAS, "Bus client: %s registertion failed ,rc: %d", + bus_client->common_data.name, rc); + return rc; } - - if ((pdata->num_usecases == 0) || - (pdata->usecase[0].num_paths == 0)) { - CAM_ERR(CAM_CPAS, "usecase=%d", pdata->num_usecases); - rc = -EINVAL; - goto error; - } - - client_id = msm_bus_scale_register_client(pdata); - if (!client_id) { - CAM_ERR(CAM_CPAS, "failed in register ahb bus client"); - rc = -EINVAL; - goto error; - } - - bus_client->dyn_vote = of_property_read_bool(dev_node, - "qcom,msm-bus-vector-dyn-vote"); - - if (bus_client->dyn_vote && (pdata->num_usecases != 2)) { - CAM_ERR(CAM_CPAS, "Excess or less vectors %d", - pdata->num_usecases); - rc = -EINVAL; - goto fail_unregister_client; - } - - msm_bus_scale_client_update_request(client_id, 0); - - bus_client->src = pdata->usecase[0].vectors[0].src; - bus_client->dst = pdata->usecase[0].vectors[0].dst; - bus_client->pdata = pdata; - bus_client->client_id = client_id; - bus_client->num_usecases = pdata->num_usecases; - bus_client->num_paths = pdata->usecase[0].num_paths; bus_client->curr_vote_level = 0; bus_client->valid = true; - bus_client->name = pdata->name; mutex_init(&bus_client->lock); - CAM_DBG(CAM_CPAS, "Bus Client=[%d][%s] : src=%d, dst=%d", - bus_client->client_id, bus_client->name, - bus_client->src, bus_client->dst); - return 0; -fail_unregister_client: - msm_bus_scale_unregister_client(bus_client->client_id); -error: - return rc; - } static int cam_cpas_util_unregister_bus_client( struct cam_cpas_bus_client *bus_client) { - if (!bus_client->valid) + if (!bus_client->valid) { + CAM_ERR(CAM_CPAS, "bus client not valid"); return -EINVAL; + } - if (bus_client->dyn_vote) - cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false); - else - cam_cpas_util_vote_bus_client_level(bus_client, 0); - - msm_bus_scale_unregister_client(bus_client->client_id); + cam_soc_bus_client_unregister(&bus_client->soc_bus_client); + bus_client->curr_vote_level = 0; bus_client->valid = false; - mutex_destroy(&bus_client->lock); return 0; @@ -765,7 +700,7 @@ vote_start_clients: continue; CAM_DBG(CAM_PERF, "Port[%s] : ab=%lld ib=%lld additional=%lld", - axi_port->axi_port_name, axi_port->ab_bw, + axi_port->bus_client.common_data.name, axi_port->ab_bw, axi_port->ib_bw, axi_port->additional_bw); if (axi_port->ab_bw) @@ -920,9 +855,9 @@ static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw, mutex_lock(&ahb_bus_client->lock); cpas_client->ahb_level = required_level; - CAM_DBG(CAM_CPAS, "Client=[%d][%s] required level[%d], curr_level[%d]", - ahb_bus_client->client_id, ahb_bus_client->name, - required_level, ahb_bus_client->curr_vote_level); + CAM_DBG(CAM_CPAS, "Client[%s] required level[%d], curr_level[%d]", + ahb_bus_client->common_data.name, required_level, + ahb_bus_client->curr_vote_level); if (required_level == ahb_bus_client->curr_vote_level) goto unlock_bus_client; diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index b3c01b3ee737..2b207a090a02 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -10,6 +10,7 @@ #include "cam_cpas_api.h" #include "cam_cpas_hw_intf.h" #include "cam_common_util.h" +#include "cam_soc_bus.h" #define CAM_CPAS_INFLIGHT_WORKS 5 #define CAM_CPAS_MAX_CLIENTS 40 @@ -117,37 +118,24 @@ struct cam_cpas_client { /** * struct cam_cpas_bus_client : Bus client information * - * @src: Bus master/src id - * @dst: Bus slave/dst id - * @pdata: Bus pdata information - * @client_id: Bus client id - * @num_usecases: Number of use cases for this client - * @num_paths: Number of paths for this client - * @curr_vote_level: current voted index - * @dyn_vote: Whether dynamic voting enabled - * @lock: Mutex lock used while voting on this client * @valid: Whether bus client is valid * @name: Name of the bus client - * + * @lock: Mutex lock used while voting on this client + * @curr_vote_level: current voted index + * @common_data: Common data fields for bus client + * @soc_bus_client: Bus client private information */ struct cam_cpas_bus_client { - int src; - int dst; - struct msm_bus_scale_pdata *pdata; - uint32_t client_id; - int num_usecases; - int num_paths; - unsigned int curr_vote_level; - bool dyn_vote; - struct mutex lock; bool valid; - const char *name; + struct mutex lock; + unsigned int curr_vote_level; + struct cam_soc_bus_client_common_data common_data; + void *soc_bus_client; }; /** * struct cam_cpas_axi_port : AXI port information * - * @axi_port_name: Name of this AXI port * @bus_client: bus client info for this port * @ib_bw_voting_needed: if this port can update ib bw dynamically * @axi_port_node: Node representing AXI Port info in device tree @@ -156,7 +144,6 @@ struct cam_cpas_bus_client { * @additional_bw: Additional bandwidth to cover non-hw cpas clients */ struct cam_cpas_axi_port { - const char *axi_port_name; struct cam_cpas_bus_client bus_client; bool ib_bw_voting_needed; struct device_node *axi_port_node; diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index c86753dd24d9..b8847626f0ff 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -163,7 +163,7 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, rc = of_property_read_u32(level_node, "level-index", &level_idx); if (rc) { - CAM_ERR(CAM_CPAS, "Error raeding level idx rc: %d", rc); + CAM_ERR(CAM_CPAS, "Error reading level idx rc: %d", rc); return rc; } if (level_idx >= CAM_CPAS_MAX_TREE_LEVELS) { @@ -229,19 +229,82 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, cpas_core->axi_port[mnoc_idx].axi_port_node = mnoc_node; - rc = of_property_read_string( - curr_node, "qcom,axi-port-name", - &cpas_core->axi_port[mnoc_idx] - .axi_port_name); - if (rc) { - CAM_ERR(CAM_CPAS, - "failed to read mnoc-port-name rc=%d", - rc); - return rc; + if (soc_private->bus_icc_based) { + struct of_phandle_args src_args = {0}, + dst_args = {0}; + + rc = of_property_read_string(mnoc_node, + "interconnect-names", + &cpas_core->axi_port[mnoc_idx] + .bus_client.common_data.name); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed to read interconnect-names rc=%d", + rc); + return rc; + } + + rc = of_parse_phandle_with_args( + mnoc_node, "interconnects", + "#interconnect-cells", 0, + &src_args); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed to read axi bus src info rc=%d", + rc); + return -EINVAL; + } + + of_node_put(src_args.np); + if (src_args.args_count != 1) { + CAM_ERR(CAM_CPAS, + "Invalid number of axi src args: %d", + src_args.args_count); + return -EINVAL; + } + + cpas_core->axi_port[mnoc_idx].bus_client + .common_data.src_id = src_args.args[0]; + + rc = of_parse_phandle_with_args( + mnoc_node, "interconnects", + "#interconnect-cells", 1, + &dst_args); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed to read axi bus dst info rc=%d", + rc); + return -EINVAL; + } + + of_node_put(dst_args.np); + if (dst_args.args_count != 1) { + CAM_ERR(CAM_CPAS, + "Invalid number of axi dst args: %d", + dst_args.args_count); + return -EINVAL; + } + + cpas_core->axi_port[mnoc_idx].bus_client + .common_data.dst_id = dst_args.args[0]; + cpas_core->axi_port[mnoc_idx].bus_client + .common_data.num_usecases = 2; + } else { + rc = of_property_read_string( + curr_node, "qcom,axi-port-name", + &cpas_core->axi_port[mnoc_idx] + .bus_client.common_data.name); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed to read mnoc-port-name rc=%d", + rc); + return rc; + } } + cpas_core->axi_port [mnoc_idx].ib_bw_voting_needed - = of_property_read_bool(curr_node, + = of_property_read_bool(curr_node, "ib-bw-voting-needed"); curr_node_ptr->axi_port_idx = mnoc_idx; mnoc_idx++; @@ -392,7 +455,8 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, struct platform_device *pdev, struct cam_cpas_private_soc *soc_private) { struct device_node *of_node; - int count = 0, i = 0, rc = 0; + struct of_phandle_args src_args = {0}, dst_args = {0}; + int count = 0, i = 0, rc = 0, num_bw_values = 0, num_levels = 0; struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; if (!soc_private || !pdev) { @@ -437,6 +501,116 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, soc_private->client_id_based = of_property_read_bool(of_node, "client-id-based"); + soc_private->bus_icc_based = of_property_read_bool(of_node, + "interconnects"); + + if (soc_private->bus_icc_based) { + rc = of_property_read_string(of_node, "interconnect-names", + &cpas_core->ahb_bus_client.common_data.name); + if (rc) { + CAM_ERR(CAM_CPAS, + "device %s failed to read interconnect-names", + pdev->name); + return rc; + } + + rc = of_parse_phandle_with_args(of_node, "interconnects", + "#interconnect-cells", 0, &src_args); + if (rc) { + CAM_ERR(CAM_CPAS, + "device %s failed to read ahb bus src info", + pdev->name); + return rc; + } + + of_node_put(src_args.np); + if (src_args.args_count != 1) { + CAM_ERR(CAM_CPAS, + "Invalid number of ahb src args: %d", + src_args.args_count); + return -EINVAL; + } + + cpas_core->ahb_bus_client.common_data.src_id = src_args.args[0]; + + rc = of_parse_phandle_with_args(of_node, "interconnects", + "#interconnect-cells", 1, &dst_args); + if (rc) { + CAM_ERR(CAM_CPAS, + "device %s failed to read ahb bus dst info", + pdev->name); + return rc; + } + + of_node_put(dst_args.np); + if (dst_args.args_count != 1) { + CAM_ERR(CAM_CPAS, + "Invalid number of ahb dst args: %d", + dst_args.args_count); + return -EINVAL; + } + + cpas_core->ahb_bus_client.common_data.dst_id = dst_args.args[0]; + + rc = of_property_read_u32(of_node, "cam-ahb-num-cases", + &cpas_core->ahb_bus_client.common_data.num_usecases); + if (rc) { + CAM_ERR(CAM_CPAS, + "device %s failed to read ahb num usecases", + pdev->name); + return rc; + } + + if (cpas_core->ahb_bus_client.common_data.num_usecases > + CAM_SOC_BUS_MAX_NUM_USECASES) { + CAM_ERR(CAM_UTIL, "Invalid number of usecases: %d", + cpas_core->ahb_bus_client.common_data + .num_usecases); + return -EINVAL; + } + + num_bw_values = of_property_count_u64_elems(of_node, + "cam-ahb-bw-KBps"); + if (num_bw_values <= 0) { + CAM_ERR(CAM_UTIL, "Error counting ahb bw values"); + return -EINVAL; + } + + num_levels = (num_bw_values / 2); + + if (num_levels != + cpas_core->ahb_bus_client.common_data.num_usecases) { + CAM_ERR(CAM_UTIL, "Invalid number of levels: %d", + num_bw_values/2); + return -EINVAL; + } + + for (i = 0; i < num_levels; i++) { + rc = of_property_read_u64_index(of_node, + "cam-ahb-bw-KBps", + (i * 2), + &cpas_core->ahb_bus_client.common_data + .bw_pair[i].ab); + if (rc) { + CAM_ERR(CAM_UTIL, + "Error reading ab bw value, rc=%d", + rc); + return rc; + } + + rc = of_property_read_u64_index(of_node, + "cam-ahb-bw-KBps", + ((i * 2) + 1), + &cpas_core->ahb_bus_client.common_data + .bw_pair[i].ib); + if (rc) { + CAM_ERR(CAM_UTIL, + "Error reading ib bw value, rc=%d", + rc); + return rc; + } + } + } count = of_property_count_strings(of_node, "client-names"); if (count <= 0) { diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index fea9c3c97593..ef5eb32337e6 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -74,6 +74,7 @@ struct cam_cpas_tree_node { * * @arch_compat: ARCH compatible string * @client_id_based: Whether clients are id based + * @bus_icc_based: Interconnect based bus interaction * @num_clients: Number of clients supported * @client_name: Client names * @tree_node: Array of pointers to all tree nodes required to calculate @@ -93,6 +94,7 @@ struct cam_cpas_tree_node { struct cam_cpas_private_soc { const char *arch_compat; bool client_id_based; + bool bus_icc_based; uint32_t num_clients; const char *client_name[CAM_CPAS_MAX_CLIENTS]; struct cam_cpas_tree_node *tree_node[CAM_CPAS_MAX_TREE_NODES]; diff --git a/drivers/cam_utils/cam_soc_bus.c b/drivers/cam_utils/cam_soc_bus.c new file mode 100644 index 000000000000..1cef2610b805 --- /dev/null +++ b/drivers/cam_utils/cam_soc_bus.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_soc_bus.h" + +/** + * struct cam_soc_bus_client_data : Bus client data + * + * @pdata: Bus pdata information + * @client_id: Bus client id + * @num_paths: Number of paths for this client + * @curr_vote_level: current voted index + * @dyn_vote: whether dynamic voting enabled + */ +struct cam_soc_bus_client_data { + struct msm_bus_scale_pdata *pdata; + uint32_t client_id; + int num_paths; + unsigned int curr_vote_level; + bool dyn_vote; +}; + +int cam_soc_bus_client_update_request(void *client, unsigned int idx) +{ + int rc = 0; + struct cam_soc_bus_client *bus_client = + (struct cam_soc_bus_client *) client; + struct cam_soc_bus_client_data *bus_client_data = + (struct cam_soc_bus_client_data *) bus_client->client_data; + + if (bus_client_data->dyn_vote) { + CAM_ERR(CAM_UTIL, + "Dyn update not allowed client[%d][%s], dyn_vote: %d", + bus_client_data->client_id, + bus_client->common_data->name, + bus_client_data->dyn_vote); + rc = -EINVAL; + goto end; + } + + if (idx >= bus_client->common_data->num_usecases) { + CAM_ERR(CAM_UTIL, "Invalid vote level=%d, usecases=%d", idx, + bus_client->common_data->num_usecases); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_UTIL, "Bus client=[%d][%s] index[%d]", + bus_client_data->client_id, bus_client->common_data->name, idx); + + rc = msm_bus_scale_client_update_request(bus_client_data->client_id, + idx); + if (rc) { + CAM_ERR(CAM_UTIL, + "Update request failed, client[%d][%s], idx: %d", + bus_client_data->client_id, + bus_client->common_data->name, idx); + goto end; + } + +end: + return rc; +} + +int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) +{ + int idx = 0; + struct msm_bus_paths *path; + struct msm_bus_scale_pdata *pdata; + struct cam_soc_bus_client *bus_client = + (struct cam_soc_bus_client *) client; + struct cam_soc_bus_client_data *bus_client_data = + (struct cam_soc_bus_client_data *) bus_client->client_data; + int rc = 0; + + if ((bus_client->common_data->num_usecases != 2) || + (bus_client_data->num_paths != 1) || + (!bus_client_data->dyn_vote)) { + CAM_ERR(CAM_UTIL, + "dynamic update not allowed Bus client=[%d][%s], %d %d %d", + bus_client_data->client_id, + bus_client->common_data->name, + bus_client->common_data->num_usecases, + bus_client_data->num_paths, + bus_client_data->dyn_vote); + rc = -EINVAL; + goto end; + } + + idx = bus_client_data->curr_vote_level; + idx = 1 - idx; + bus_client_data->curr_vote_level = idx; + + pdata = bus_client_data->pdata; + path = &(pdata->usecase[idx]); + path->vectors[0].ab = ab; + path->vectors[0].ib = ib; + + CAM_DBG(CAM_UTIL, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", + bus_client_data->client_id, bus_client->common_data->name, ab, + ib, idx); + rc = msm_bus_scale_client_update_request(bus_client_data->client_id, + idx); + if (rc) { + CAM_ERR(CAM_UTIL, + "Update request failed, client[%d][%s], idx: %d", + bus_client_data->client_id, + bus_client->common_data->name, idx); + return rc; + } + +end: + return rc; +} + +int cam_soc_bus_client_register(struct platform_device *pdev, + struct device_node *dev_node, void **client, + struct cam_soc_bus_client_common_data *common_data) +{ + struct msm_bus_scale_pdata *pdata = NULL; + struct cam_soc_bus_client *bus_client = NULL; + struct cam_soc_bus_client_data *bus_client_data = NULL; + uint32_t client_id; + int rc; + + bus_client = kzalloc(sizeof(struct cam_soc_bus_client), GFP_KERNEL); + if (!bus_client) { + CAM_ERR(CAM_UTIL, "Non Enought Memroy"); + rc = -ENOMEM; + goto end; + } + + *client = bus_client; + + bus_client_data = kzalloc(sizeof(struct cam_soc_bus_client_data), + GFP_KERNEL); + if (!bus_client_data) { + kfree(bus_client); + *client = NULL; + rc = -ENOMEM; + goto end; + } + + bus_client->client_data = bus_client_data; + pdata = msm_bus_pdata_from_node(pdev, + dev_node); + if (!pdata) { + CAM_ERR(CAM_UTIL, "failed get_pdata"); + rc = -EINVAL; + goto error; + } + + if ((pdata->num_usecases == 0) || + (pdata->usecase[0].num_paths == 0)) { + CAM_ERR(CAM_UTIL, "usecase=%d", pdata->num_usecases); + rc = -EINVAL; + goto error; + } + + client_id = msm_bus_scale_register_client(pdata); + if (!client_id) { + CAM_ERR(CAM_UTIL, "failed in register bus client_data"); + rc = -EINVAL; + goto error; + } + + bus_client->common_data = common_data; + + bus_client_data->dyn_vote = of_property_read_bool(dev_node, + "qcom,msm-bus-vector-dyn-vote"); + + if (bus_client_data->dyn_vote && (pdata->num_usecases != 2)) { + CAM_ERR(CAM_UTIL, "Excess or less vectors %d", + pdata->num_usecases); + rc = -EINVAL; + goto fail_unregister_client; + } + + rc = msm_bus_scale_client_update_request(client_id, 0); + if (rc) { + CAM_ERR(CAM_UTIL, "Bus client update request failed, rc = %d", + rc); + goto fail_unregister_client; + } + + bus_client->common_data->src_id = pdata->usecase[0].vectors[0].src; + bus_client->common_data->dst_id = pdata->usecase[0].vectors[0].dst; + bus_client_data->pdata = pdata; + bus_client_data->client_id = client_id; + bus_client->common_data->num_usecases = pdata->num_usecases; + bus_client_data->num_paths = pdata->usecase[0].num_paths; + bus_client->common_data->name = pdata->name; + + CAM_DBG(CAM_UTIL, "Bus Client=[%d][%s] : src=%d, dst=%d", + bus_client_data->client_id, bus_client->common_data->name, + bus_client->common_data->src_id, + bus_client->common_data->dst_id); + + return 0; +fail_unregister_client: + msm_bus_scale_unregister_client(bus_client_data->client_id); +error: + kfree(bus_client_data); + bus_client->client_data = NULL; + kfree(bus_client); + *client = NULL; +end: + return rc; + +} + +void cam_soc_bus_client_unregister(void **client) +{ + struct cam_soc_bus_client *bus_client = + (struct cam_soc_bus_client *) (*client); + struct cam_soc_bus_client_data *bus_client_data = + (struct cam_soc_bus_client_data *) bus_client->client_data; + + if (bus_client_data->dyn_vote) + cam_soc_bus_client_update_bw(bus_client, 0, 0); + else + cam_soc_bus_client_update_request(bus_client, 0); + + msm_bus_scale_unregister_client(bus_client_data->client_id); + kfree(bus_client_data); + bus_client->client_data = NULL; + kfree(bus_client); + *client = NULL; +} diff --git a/drivers/cam_utils/cam_soc_bus.h b/drivers/cam_utils/cam_soc_bus.h new file mode 100644 index 000000000000..518b6524d038 --- /dev/null +++ b/drivers/cam_utils/cam_soc_bus.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SOC_BUS_H_ +#define _CAM_SOC_BUS_H_ + +#include +#include +#include +#include "cam_debug_util.h" + +#define CAM_SOC_BUS_MAX_NUM_USECASES 8 + +/** + * struct cam_soc_bus_client_ab_ib : Bandwidth values for selected usecase + * + * @ab: Arbitrated Bandwidth + * @ib: Instantaneous Bandwidth + */ +struct cam_soc_bus_client_ab_ib { + uint64_t ab; + uint64_t ib; +}; + +/** + * struct cam_soc_bus_client_common_data : Common data fields for bus client + * + * @name: Name of bus client + * @src_id: Bus master/src id + * @dst_id: Bus slave/dst id + * @num_usecases: Number of use cases for this client + * @bw_pair: Bandwidth values for applicable usecases + */ +struct cam_soc_bus_client_common_data { + const char *name; + uint32_t src_id; + uint32_t dst_id; + int num_usecases; + struct cam_soc_bus_client_ab_ib bw_pair[CAM_SOC_BUS_MAX_NUM_USECASES]; +}; + +/** + * struct cam_soc_bus_client : Bus client information + * + * @client_data: Bus client data + * @common_data: Common data fields for bus client + */ +struct cam_soc_bus_client { + void *client_data; + struct cam_soc_bus_client_common_data *common_data; +}; + + +#if IS_REACHABLE(CONFIG_QCOM_BUS_SCALING) || \ + IS_REACHABLE(CONFIG_INTERCONNECT_QCOM) + +int cam_soc_bus_client_update_request(void *client, unsigned int idx); + +int cam_soc_bus_client_update_bw(void *client, uint64_t ab, + uint64_t ib); + +int cam_soc_bus_client_register(struct platform_device *pdev, + struct device_node *dev_node, void **client, + struct cam_soc_bus_client_common_data *common_data); + +void cam_soc_bus_client_unregister(void **client); + +#else +static inline int cam_soc_bus_client_update_request(void *client, + unsigned int idx) +{ + return 0; +} + +static inline int cam_soc_bus_client_update_bw(void *client, + uint64_t ab, uint64_t ib) +{ + return 0; +} + +static inline int cam_soc_bus_client_register( + struct platform_device *pdev, struct device_node *dev_node, + void **client, struct cam_soc_bus_client_common_data *common_data) +{ + return 0; +} + +static inline void cam_soc_bus_client_unregister(void **client) +{ +} + +#endif + +#endif /* _CAM_SOC_BUS_H_ */ diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c new file mode 100644 index 000000000000..0a22cecc3c08 --- /dev/null +++ b/drivers/cam_utils/cam_soc_icc.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_soc_bus.h" + +/** + * struct cam_soc_bus_client_data : Bus client data + * + * @icc_data: Bus icc path information + */ +struct cam_soc_bus_client_data { + struct icc_path *icc_data; +}; + +int cam_soc_bus_client_update_request(void *client, unsigned int idx) +{ + int rc = 0; + uint64_t ab = 0, ib = 0; + struct cam_soc_bus_client *bus_client = + (struct cam_soc_bus_client *) client; + struct cam_soc_bus_client_data *bus_client_data = + (struct cam_soc_bus_client_data *) bus_client->client_data; + + if (idx >= bus_client->common_data->num_usecases) { + CAM_ERR(CAM_UTIL, "Invalid vote level=%d, usecases=%d", idx, + bus_client->common_data->num_usecases); + rc = -EINVAL; + goto end; + } + + ab = bus_client->common_data->bw_pair[idx].ab; + ib = bus_client->common_data->bw_pair[idx].ib; + + CAM_DBG(CAM_UTIL, "Bus client=[%s] index[%d]", + bus_client->common_data->name, idx); + + rc = icc_set_bw(bus_client_data->icc_data, ab, ib); + if (rc) { + CAM_ERR(CAM_UTIL, + "Update request failed, client[%s], idx: %d", + bus_client->common_data->name, idx); + goto end; + } + +end: + return rc; +} + +int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) +{ + struct cam_soc_bus_client *bus_client = + (struct cam_soc_bus_client *) client; + struct cam_soc_bus_client_data *bus_client_data = + (struct cam_soc_bus_client_data *) bus_client->client_data; + int rc = 0; + + CAM_DBG(CAM_UTIL, "Bus client=[%s] :ab[%llu] ib[%llu]", + bus_client->common_data->name, ab, ib); + rc = icc_set_bw(bus_client_data->icc_data, ab, ib); + if (rc) { + CAM_ERR(CAM_UTIL, "Update request failed, client[%s]", + bus_client->common_data->name); + goto end; + } + +end: + return rc; +} + +int cam_soc_bus_client_register(struct platform_device *pdev, + struct device_node *dev_node, void **client, + struct cam_soc_bus_client_common_data *common_data) +{ + struct cam_soc_bus_client *bus_client = NULL; + struct cam_soc_bus_client_data *bus_client_data = NULL; + int rc = 0; + + bus_client = kzalloc(sizeof(struct cam_soc_bus_client), GFP_KERNEL); + if (!bus_client) { + CAM_ERR(CAM_UTIL, "soc bus client is NULL"); + rc = -ENOMEM; + goto end; + } + + *client = bus_client; + + bus_client_data = kzalloc(sizeof(struct cam_soc_bus_client_data), + GFP_KERNEL); + if (!bus_client_data) { + kfree(bus_client); + *client = NULL; + rc = -ENOMEM; + goto end; + } + + bus_client->client_data = bus_client_data; + bus_client_data->icc_data = icc_get(&pdev->dev, + bus_client->common_data->src_id, + bus_client->common_data->dst_id); + if (!bus_client_data->icc_data) { + CAM_ERR(CAM_UTIL, "failed in register bus client"); + rc = -EINVAL; + goto error; + } + + bus_client->common_data = common_data; + + rc = icc_set_bw(bus_client_data->icc_data, 0, 0); + if (rc) { + CAM_ERR(CAM_UTIL, "Bus client update request failed, rc = %d", + rc); + goto fail_unregister_client; + } + + CAM_DBG(CAM_UTIL, "Bus Client=[%s] : src=%d, dst=%d", + bus_client->common_data->name, bus_client->common_data->src_id, + bus_client->common_data->dst_id); + + return 0; + +fail_unregister_client: + icc_put(bus_client_data->icc_data); +error: + kfree(bus_client_data); + bus_client->client_data = NULL; + kfree(bus_client); + *client = NULL; +end: + return rc; + +} + +void cam_soc_bus_client_unregister(void **client) +{ + struct cam_soc_bus_client *bus_client = + (struct cam_soc_bus_client *) (*client); + struct cam_soc_bus_client_data *bus_client_data = + (struct cam_soc_bus_client_data *) bus_client->client_data; + + icc_put(bus_client_data->icc_data); + kfree(bus_client_data); + bus_client->client_data = NULL; + kfree(bus_client); + *client = NULL; + +} From 50c8c09ead7076e5070afbd80e07b0cefe15bbb5 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 4 Nov 2019 15:24:08 -0800 Subject: [PATCH 185/790] msm: camera: smmu: Move to ioremap APIs for using FW memory When loading the camera FW, use the appropriate APIs depending on the kernel version to map the FW region. CRs-Fixed: 2564857 Change-Id: I2104b63b54bce799c8e44f36c49042de86f78c7e Signed-off-by: Isaac J. Manjarres Signed-off-by: Karthik Jayakumar --- drivers/Makefile | 3 +- drivers/cam_req_mgr/Makefile | 1 + drivers/cam_req_mgr/cam_mem_mgr.c | 8 +++- drivers/cam_smmu/cam_smmu_api.c | 48 ++++++++------------- drivers/cam_utils/cam_compat.c | 71 +++++++++++++++++++++++++++++++ drivers/cam_utils/cam_compat.h | 32 ++++++++++++++ 6 files changed, 129 insertions(+), 34 deletions(-) create mode 100644 drivers/cam_utils/cam_compat.c create mode 100644 drivers/cam_utils/cam_compat.h diff --git a/drivers/Makefile b/drivers/Makefile index 01e4e572c8bf..06420672dab4 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -9,7 +9,7 @@ ifneq (,$(filter $(CONFIG_MSM_GLOBAL_SYNX), y m)) ccflags-y += -I$(srctree)/drivers/media/platform/msm/synx endif -subdir-ccflags-y += -I$(srctree)/techpack/camera/include/uapi/camera +ccflags-y += -I$(srctree)/techpack/camera/include/uapi/camera ccflags-y += -I$(srctree) camera-y := \ @@ -26,6 +26,7 @@ camera-y := \ cam_utils/cam_debug_util.o \ cam_utils/cam_trace.o \ cam_utils/cam_common_util.o \ + cam_utils/cam_compat.o \ cam_core/cam_context.o \ cam_core/cam_context_utils.o \ cam_core/cam_node.o \ diff --git a/drivers/cam_req_mgr/Makefile b/drivers/cam_req_mgr/Makefile index 41452f89d3b1..2aaed1301b53 100644 --- a/drivers/cam_req_mgr/Makefile +++ b/drivers/cam_req_mgr/Makefile @@ -3,6 +3,7 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/include/ ccflags-y += -I$(srctree)/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_core.o\ diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index a0b1e66f8e0c..559a1c42b008 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -6,11 +6,15 @@ #include #include #include -#include #include -#include #include +#include +#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE +#include +#endif + +#include "cam_compat.h" #include "cam_req_mgr_util.h" #include "cam_mem_mgr.h" #include "cam_smmu_api.h" diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 122ed77a7932..269982f444c2 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -10,13 +10,18 @@ #include #include #include +#include #include #include #include #include + #include #include + #include + +#include "cam_compat.h" #include "cam_smmu_api.h" #include "cam_debug_util.h" @@ -36,13 +41,7 @@ static int g_num_pf_handled = 4; module_param(g_num_pf_handled, int, 0644); -struct firmware_alloc_info { - struct device *fw_dev; - void *fw_kva; - dma_addr_t fw_dma_hdl; -}; - -struct firmware_alloc_info icp_fw; +struct cam_fw_alloc_info icp_fw; struct cam_smmu_work_payload { int idx; @@ -1172,23 +1171,17 @@ int cam_smmu_alloc_firmware(int32_t smmu_hdl, firmware_start = iommu_cb_set.cb_info[idx].firmware_info.iova_start; CAM_DBG(CAM_SMMU, "Firmware area len from DT = %zu", firmware_len); - icp_fw.fw_kva = dma_alloc_coherent(icp_fw.fw_dev, - firmware_len, - &icp_fw.fw_dma_hdl, - GFP_KERNEL); - if (!icp_fw.fw_kva) { - CAM_ERR(CAM_SMMU, "FW memory alloc failed"); - rc = -ENOMEM; + rc = cam_reserve_icp_fw(&icp_fw, firmware_len); + if (rc) goto unlock_and_end; - } else { + else CAM_DBG(CAM_SMMU, "DMA alloc returned fw = %pK, hdl = %pK", - icp_fw.fw_kva, (void *)icp_fw.fw_dma_hdl); - } + icp_fw.fw_kva, (void *)icp_fw.fw_hdl); domain = iommu_cb_set.cb_info[idx].domain; rc = iommu_map(domain, firmware_start, - icp_fw.fw_dma_hdl, + (phys_addr_t) icp_fw.fw_hdl, firmware_len, IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV); @@ -1207,10 +1200,7 @@ int cam_smmu_alloc_firmware(int32_t smmu_hdl, return rc; alloc_fail: - dma_free_coherent(icp_fw.fw_dev, - firmware_len, - icp_fw.fw_kva, - icp_fw.fw_dma_hdl); + cam_unreserve_icp_fw(&icp_fw, firmware_len); unlock_and_end: mutex_unlock(&iommu_cb_set.cb_info[idx].lock); end: @@ -1270,13 +1260,10 @@ int cam_smmu_dealloc_firmware(int32_t smmu_hdl) rc = -EINVAL; } - dma_free_coherent(icp_fw.fw_dev, - firmware_len, - icp_fw.fw_kva, - icp_fw.fw_dma_hdl); + cam_unreserve_icp_fw(&icp_fw, firmware_len); - icp_fw.fw_kva = 0; - icp_fw.fw_dma_hdl = 0; + icp_fw.fw_kva = NULL; + icp_fw.fw_hdl = 0; iommu_cb_set.cb_info[idx].is_fw_allocated = false; @@ -3184,9 +3171,8 @@ EXPORT_SYMBOL(cam_smmu_destroy_handle); static void cam_smmu_deinit_cb(struct cam_context_bank_info *cb) { - if (cb->io_support && cb->domain) { + if (cb->io_support && cb->domain) cb->domain = NULL; - } if (cb->shared_support) { gen_pool_destroy(cb->shared_mem_pool); @@ -3616,7 +3602,7 @@ static int cam_smmu_probe(struct platform_device *pdev) if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu-fw-dev")) { icp_fw.fw_dev = &pdev->dev; icp_fw.fw_kva = NULL; - icp_fw.fw_dma_hdl = 0; + icp_fw.fw_hdl = 0; return rc; } diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c new file mode 100644 index 000000000000..72ec49b5b6cd --- /dev/null +++ b/drivers/cam_utils/cam_compat.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + */ + +#include +#include + +#include "cam_compat.h" +#include "cam_debug_util.h" + +#if KERNEL_VERSION(5, 4, 0) >= LINUX_VERSION_CODE +int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) +{ + int rc = 0; + struct device_node *of_node; + struct device_node *mem_node; + struct resource res; + + of_node = (icp_fw->fw_dev)->of_node; + mem_node = of_parse_phandle(of_node, "memory-region", 0); + if (!mem_node) { + rc = -ENOMEM; + CAM_ERR(CAM_SMMU, "FW memory carveout not found"); + goto end; + } + rc = of_address_to_resource(mem_node, 0, &res); + of_node_put(mem_node); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Unable to get start of FW mem carveout"); + goto end; + } + icp_fw->fw_hdl = res.start; + icp_fw->fw_kva = ioremap_wc(icp_fw->fw_hdl, fw_length); + if (!icp_fw->fw_kva) { + CAM_ERR(CAM_SMMU, "Failed to map the FW."); + rc = -ENOMEM; + goto end; + } + memset_io(icp_fw->fw_kva, 0, fw_length); + +end: + return rc; +} + +void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) +{ + iounmap(icp_fw->fw_kva); +} +#else +int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) +{ + int rc = 0; + + icp_fw->fw_kva = dma_alloc_coherent(icp_fw->fw_dev, fw_length, + &icp_fw->fw_hdl, GFP_KERNEL); + + if (!icp_fw->fw_kva) { + CAM_ERR(CAM_SMMU, "FW memory alloc failed"); + rc = -ENOMEM; + } + + return rc; +} + +void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) +{ + dma_free_coherent(icp_fw->fw_dev, fw_length, icp_fw->fw_kva, + icp_fw->fw_hdl); +} +#endif diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h new file mode 100644 index 000000000000..caf0ac8e1556 --- /dev/null +++ b/drivers/cam_utils/cam_compat.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_COMPAT_H_ +#define _CAM_COMPAT_H_ + +#include + +#if KERNEL_VERSION(5, 4, 0) >= LINUX_VERSION_CODE + +#include +#include + +#else + +#include +#include + +#endif + +struct cam_fw_alloc_info { + struct device *fw_dev; + void *fw_kva; + uint64_t fw_hdl; +}; + +int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); +void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); + +#endif /* _CAM_COMPAT_H_ */ From 10891f69165584d4e63a21928f9077db3ca40f81 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 14 Oct 2019 10:05:54 -0700 Subject: [PATCH 186/790] msm: camera: utils: Migrate SCM calls Migrate secure world calls to qcom scm driver. CRs-Fixed: 2564857 Change-Id: I8eb7498e4f80ff7ac1e22b7dcd364048e5338746 Signed-off-by: Elliot Berman Signed-off-by: Karthik Jayakumar --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 9 +- .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 36 +----- drivers/cam_req_mgr/cam_mem_mgr.c | 4 - .../cam_csiphy/cam_csiphy_core.c | 39 +------ drivers/cam_smmu/cam_smmu_api.c | 2 - drivers/cam_utils/cam_compat.c | 108 +++++++++++++++++- drivers/cam_utils/cam_compat.h | 11 +- 8 files changed, 128 insertions(+), 83 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index f91179b5aaa7..9068dd3ebe08 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -7,8 +7,7 @@ #include #include -#include - +#include "cam_compat.h" #include "cam_cpas_hw_intf.h" #include "cam_cpas_hw.h" #include "cam_cpastop_hw.h" @@ -519,7 +518,7 @@ done: static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) { - int i, reg_val; + int i; struct cam_cpas_hw_errata_wa_list *errata_wa_list = camnoc_info->errata_wa_list; struct cam_cpas_hw_errata_wa *errata_wa = @@ -546,9 +545,7 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) } if (errata_wa->enable) { - reg_val = scm_io_read(errata_wa->data.reg_info.offset); - reg_val |= errata_wa->data.reg_info.value; - scm_io_write(errata_wa->data.reg_info.offset, reg_val); + cam_cpastop_scm_write(errata_wa); } return 0; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index afd08fb990a4..78226a5f32ac 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -8,10 +8,10 @@ #include #include -#include #include #include +#include "cam_compat.h" #include "cam_sync_api.h" #include "cam_smmu_api.h" #include "cam_req_mgr_workq.h" diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b02c7adf6fdc..679c2357117f 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -8,9 +8,9 @@ #include #include -#include #include +#include "cam_compat.h" #include "cam_smmu_api.h" #include "cam_req_mgr_workq.h" #include "cam_isp_hw_mgr_intf.h" @@ -28,8 +28,6 @@ #define CAM_IFE_HW_ENTRIES_MAX 20 -#define TZ_SVC_SMMU_PROGRAM 0x15 -#define TZ_SAFE_SYSCALL_ID 0x3 #define CAM_IFE_SAFE_DISABLE 0 #define CAM_IFE_SAFE_ENABLE 1 #define SMMU_SE_IFE 0 @@ -172,38 +170,6 @@ static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, return rc; } -static int cam_ife_notify_safe_lut_scm(bool safe_trigger) -{ - uint32_t camera_hw_version, rc = 0; - struct scm_desc desc = {0}; - - rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); - if (!rc) { - switch (camera_hw_version) { - case CAM_CPAS_TITAN_170_V100: - case CAM_CPAS_TITAN_170_V110: - case CAM_CPAS_TITAN_175_V100: - - desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL); - desc.args[0] = SMMU_SE_IFE; - desc.args[1] = safe_trigger; - - CAM_DBG(CAM_ISP, "Safe scm call %d", safe_trigger); - if (scm_call2(SCM_SIP_FNID(TZ_SVC_SMMU_PROGRAM, - TZ_SAFE_SYSCALL_ID), &desc)) { - CAM_ERR(CAM_ISP, - "scm call to Enable Safe failed"); - rc = -EINVAL; - } - break; - default: - break; - } - } - - return rc; -} - static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) { diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 559a1c42b008..f6eec4446cd5 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -10,10 +10,6 @@ #include #include -#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE -#include -#endif - #include "cam_compat.h" #include "cam_req_mgr_util.h" #include "cam_mem_mgr.h" diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index fdab05b0e353..ec8dd1ae685b 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -4,21 +4,17 @@ */ #include + +#include + +#include "cam_compat.h" #include "cam_csiphy_core.h" #include "cam_csiphy_dev.h" #include "cam_csiphy_soc.h" #include "cam_common_util.h" #include "cam_packet_util.h" - -#include - -#include -#include -#include - -#define SCM_SVC_CAMERASS 0x18 -#define SECURE_SYSCALL_ID 0x6 -#define SECURE_SYSCALL_ID_2 0x7 +#include "cam_mem_mgr.h" +#include "cam_cpas_api.h" #define LANE_MASK_2PH 0x1F #define LANE_MASK_3PH 0x7 @@ -26,29 +22,6 @@ static int csiphy_dump; module_param(csiphy_dump, int, 0644); -static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, - bool protect, int32_t offset) -{ - struct scm_desc desc = {0}; - - if (offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); - return -EINVAL; - } - - desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL); - desc.args[0] = protect; - desc.args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset]; - - if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID_2), - &desc)) { - CAM_ERR(CAM_CSIPHY, "scm call to hypervisor failed"); - return -EINVAL; - } - - return 0; -} - int32_t cam_csiphy_get_instance_offset( struct csiphy_device *csiphy_dev, int32_t dev_handle) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 269982f444c2..3043bee2192b 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -15,8 +15,6 @@ #include #include #include - -#include #include #include diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 72ec49b5b6cd..aa3c02bafb41 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -8,8 +8,9 @@ #include "cam_compat.h" #include "cam_debug_util.h" +#include "cam_cpas_api.h" -#if KERNEL_VERSION(5, 4, 0) >= LINUX_VERSION_CODE +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) { int rc = 0; @@ -47,6 +48,54 @@ void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) { iounmap(icp_fw->fw_kva); } + +int cam_ife_notify_safe_lut_scm(bool safe_trigger) +{ + const uint32_t smmu_se_ife = 0; + uint32_t camera_hw_version, rc = 0; + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (!rc && qcom_scm_smmu_notify_secure_lut(smmu_se_ife, safe_trigger)) { + switch (camera_hw_version) { + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_175_V100: + CAM_ERR(CAM_ISP, "scm call to enable safe failed"); + rc = -EINVAL; + break; + default: + break; + } + } + + return rc; +} + +int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, + bool protect, int32_t offset) +{ + int rc = 0; + + if (offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); + rc = -EINVAL; + } else if (qcom_scm_camera_protect_phy_lanes(protect, + csiphy_dev->csiphy_cpas_cp_reg_mask[offset])) { + CAM_ERR(CAM_CSIPHY, "SCM call to hypervisor failed"); + rc = -EINVAL; + } + + return 0; +} + +void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) +{ + int reg_val; + + qcom_scm_io_readl(errata_wa->data.reg_info.offset, ®_val); + reg_val |= errata_wa->data.reg_info.value; + qcom_scm_io_writel(errata_wa->data.reg_info.offset, reg_val); +} #else int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) { @@ -68,4 +117,61 @@ void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) dma_free_coherent(icp_fw->fw_dev, fw_length, icp_fw->fw_kva, icp_fw->fw_hdl); } + +int cam_ife_notify_safe_lut_scm(bool safe_trigger) +{ + const uint32_t smmu_se_ife = 0; + uint32_t camera_hw_version, rc = 0; + struct scm_desc description = { + .arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL), + .args[0] = smmu_se_ife, + .args[1] = safe_trigger, + }; + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (!rc && scm_call2(SCM_SIP_FNID(0x15, 0x3), &description)) { + switch (camera_hw_version) { + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_175_V100: + CAM_ERR(CAM_ISP, "scm call to enable safe failed"); + rc = -EINVAL; + break; + default: + break; + } + } + + return rc; +} + +int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, + bool protect, int32_t offset) +{ + int rc = 0; + struct scm_desc description = { + .arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL), + .args[0] = protect, + .args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset], + }; + + if (offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); + rc = -EINVAL; + } else if (scm_call2(SCM_SIP_FNID(0x18, 0x7), &description)) { + CAM_ERR(CAM_CSIPHY, "SCM call to hypervisor failed"); + rc = -EINVAL; + } + + return 0; +} + +void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) +{ + int reg_val; + + reg_val = scm_io_read(errata_wa->data.reg_info.offset); + reg_val |= errata_wa->data.reg_info.value; + scm_io_write(errata_wa->data.reg_info.offset, reg_val); +} #endif diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h index caf0ac8e1556..3e7bec620c53 100644 --- a/drivers/cam_utils/cam_compat.h +++ b/drivers/cam_utils/cam_compat.h @@ -8,15 +8,20 @@ #include -#if KERNEL_VERSION(5, 4, 0) >= LINUX_VERSION_CODE +#include "cam_csiphy_dev.h" +#include "cam_cpastop_hw.h" + +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE #include #include +#include #else #include #include +#include #endif @@ -28,5 +33,9 @@ struct cam_fw_alloc_info { int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); +void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa); +int cam_ife_notify_safe_lut_scm(bool safe_trigger); +int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, + bool protect, int32_t offset); #endif /* _CAM_COMPAT_H_ */ From 60da65a262f8cb5f17db9141e0b70dc9c92e762b Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 27 Nov 2019 10:17:32 -0800 Subject: [PATCH 187/790] msm: camera: config: Add target config to enable compilation Add lahaina configuration file to enable lahaina targets compilation. CRs-Fixed: 2569808 Change-Id: Idc85fd1d19acb4df4f09403d0e8171124489d68d Signed-off-by: Jigarkumar Zala Signed-off-by: Karthik Jayakumar Signed-off-by: Mukund Madhusudan Atre --- Makefile | 4 ++++ config/lahainacamera.conf | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 config/lahainacamera.conf diff --git a/Makefile b/Makefile index 7e135e4e13ae..d721be623d89 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,10 @@ ifeq ($(CONFIG_ARCH_BENGAL), y) include $(srctree)/techpack/camera/config/bengalcamera.conf endif +ifeq ($(CONFIG_ARCH_LAHAINA), y) +include $(srctree)/techpack/camera/config/lahainacamera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h diff --git a/config/lahainacamera.conf b/config/lahainacamera.conf new file mode 100644 index 000000000000..32abf9dbba5f --- /dev/null +++ b/config/lahainacamera.conf @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2019, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=y +$(info "SPECTRA_CAMERA IS STATIC") +else +$(info "SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +endif From ebbfb4d5dbb8efe4360ee5e1ebadefed2c38432d Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 16 Dec 2019 11:34:53 -0800 Subject: [PATCH 188/790] msm: camera: cpas: Fix parsing of static bw values for ICC The static values for AHB bw do not exceed u32, and using u64 parsing function to read it requires unnecessary device tree changes. Changing parsing function for bw values from 64-bit to 32-bit version. CRs-Fixed: 2584631 Change-Id: Ie7c685fd40a0ee390f997fbe6cf3610c2209e3f1 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_soc.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index b8847626f0ff..a55f4a97813f 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -569,13 +569,14 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, return -EINVAL; } - num_bw_values = of_property_count_u64_elems(of_node, + num_bw_values = of_property_count_u32_elems(of_node, "cam-ahb-bw-KBps"); if (num_bw_values <= 0) { CAM_ERR(CAM_UTIL, "Error counting ahb bw values"); return -EINVAL; } + CAM_DBG(CAM_CPAS, "AHB: num bw values %d", num_bw_values); num_levels = (num_bw_values / 2); if (num_levels != @@ -586,11 +587,11 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, } for (i = 0; i < num_levels; i++) { - rc = of_property_read_u64_index(of_node, + rc = of_property_read_u32_index(of_node, "cam-ahb-bw-KBps", (i * 2), - &cpas_core->ahb_bus_client.common_data - .bw_pair[i].ab); + (uint32_t *) &cpas_core->ahb_bus_client + .common_data.bw_pair[i].ab); if (rc) { CAM_ERR(CAM_UTIL, "Error reading ab bw value, rc=%d", @@ -598,17 +599,23 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, return rc; } - rc = of_property_read_u64_index(of_node, + rc = of_property_read_u32_index(of_node, "cam-ahb-bw-KBps", ((i * 2) + 1), - &cpas_core->ahb_bus_client.common_data - .bw_pair[i].ib); + (uint32_t *) &cpas_core->ahb_bus_client + .common_data.bw_pair[i].ib); if (rc) { CAM_ERR(CAM_UTIL, "Error reading ib bw value, rc=%d", rc); return rc; } + + CAM_DBG(CAM_CPAS, + "AHB: Level: %d, ab_value %llu, ib_value: %llu", + i, cpas_core->ahb_bus_client.common_data + .bw_pair[i].ab, cpas_core->ahb_bus_client + .common_data.bw_pair[i].ib); } } From 75f72b30a7c01aad41485637e9fe6b22d4a3414b Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 12 Nov 2019 05:51:21 -0800 Subject: [PATCH 189/790] msm: camera: isp: Add header file changes This commit adds header file changes for version 580 hardware. CRs-Fixed: 2582959 Change-Id: I14497249db4a09c170215839a788c7477932ff35 Signed-off-by: Venkat Chinta Signed-off-by: Vishalsingh Hajeri --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c | 9 ++ .../isp_hw/vfe_hw/vfe17x/cam_vfe580.h | 120 ++++++++++++++++++ .../vfe_hw/vfe_top/cam_vfe_camif_ver3.h | 1 + 3 files changed, 130 insertions(+) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c index bb3c2b12df92..e6f339e51825 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c @@ -8,6 +8,7 @@ #include "cam_vfe175.h" #include "cam_vfe175_130.h" #include "cam_vfe480.h" +#include "cam_vfe580.h" #include "cam_vfe_lite17x.h" #include "cam_vfe_lite48x.h" #include "cam_vfe_hw_intf.h" @@ -31,6 +32,10 @@ static const struct of_device_id cam_vfe_dt_match[] = { .compatible = "qcom,vfe480", .data = &cam_vfe480_hw_info, }, + { + .compatible = "qcom,vfe580", + .data = &cam_vfe580_hw_info, + }, { .compatible = "qcom,vfe-lite170", .data = &cam_vfe_lite17x_hw_info, @@ -43,6 +48,10 @@ static const struct of_device_id cam_vfe_dt_match[] = { .compatible = "qcom,vfe-lite480", .data = &cam_vfe_lite48x_hw_info, }, + { + .compatible = "qcom,vfe-lite580", + .data = &cam_vfe_lite48x_hw_info, + }, {} }; MODULE_DEVICE_TABLE(of, cam_vfe_dt_match); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h new file mode 100644 index 000000000000..76c8b400a305 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_VFE580_H_ +#define _CAM_VFE580_H_ +#include "cam_vfe480.h" +#include "cam_vfe_top_ver3.h" +#include "cam_vfe_core.h" + +static struct cam_vfe_camif_ver3_reg_data vfe_580_camif_reg_data = { + .pp_extern_reg_update_shift = 4, + .dual_pd_extern_reg_update_shift = 17, + .extern_reg_update_mask = 1, + .dual_ife_pix_en_shift = 3, + .dual_ife_sync_sel_shift = 18, + .operating_mode_shift = 11, + .input_mux_sel_shift = 5, + .pixel_pattern_shift = 24, + .pixel_pattern_mask = 0x7, + .dsp_mode_shift = 24, + .dsp_mode_mask = 0x1, + .dsp_en_shift = 23, + .dsp_en_mask = 0x1, + .reg_update_cmd_data = 0x41, + .epoch_line_cfg = 0x00000014, + .sof_irq_mask = 0x00000001, + .epoch0_irq_mask = 0x00000004, + .epoch1_irq_mask = 0x00000008, + .eof_irq_mask = 0x00000002, + .error_irq_mask0 = 0x82000200, + .error_irq_mask2 = 0x30301F80, + .subscribe_irq_mask1 = 0x00000007, + .enable_diagnostic_hw = 0x1, + .pp_camif_cfg_en_shift = 0, + .pp_camif_cfg_ife_out_en_shift = 8, + .top_debug_cfg_en = 1, +}; + +static struct cam_vfe_camif_lite_ver3_reg_data vfe580_camif_rdi1_reg_data = { + .extern_reg_update_shift = 0, + .input_mux_sel_shift = 7, + .reg_update_cmd_data = 0x4, + .epoch_line_cfg = 0x0, + .sof_irq_mask = 0x100, + .epoch0_irq_mask = 0x400, + .epoch1_irq_mask = 0x800, + .eof_irq_mask = 0x200, + .error_irq_mask0 = 0x10000000, + .error_irq_mask2 = 0x40000, + .subscribe_irq_mask1 = 0x300, + .enable_diagnostic_hw = 0x1, +}; + +struct cam_vfe_camif_lite_ver3_hw_info + vfe580_rdi_hw_info_arr[CAM_VFE_RDI_VER2_MAX] = { + { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_rdi[0], + .reg_data = &vfe480_camif_rdi_reg_data[0], + }, + { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_rdi[1], + .reg_data = &vfe580_camif_rdi1_reg_data, + }, + { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_rdi[2], + .reg_data = &vfe480_camif_rdi_reg_data[2], + }, +}; + +static struct cam_vfe_top_ver3_hw_info vfe580_top_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_reg = &vfe480_camif_reg, + .reg_data = &vfe_580_camif_reg_data, + }, + .pdlib_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_pd, + .reg_data = &vfe480_camif_pd_reg_data, + }, + .rdi_hw_info[0] = &vfe580_rdi_hw_info_arr[0], + .rdi_hw_info[1] = &vfe580_rdi_hw_info_arr[1], + .rdi_hw_info[2] = &vfe580_rdi_hw_info_arr[2], + .lcr_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_lcr, + .reg_data = &vfe480_camif_lcr_reg_data, + }, + .num_mux = 6, + .mux_type = { + CAM_VFE_CAMIF_VER_3_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_PDLIB_VER_1_0, + CAM_VFE_LCR_VER_1_0, + }, +}; + +struct cam_vfe_hw_info cam_vfe580_hw_info = { + .irq_reg_info = &vfe480_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_3_0, + .bus_hw_info = &vfe480_bus_hw_info, + + .bus_rd_version = CAM_VFE_BUS_RD_VER_1_0, + .bus_rd_hw_info = &vfe480_bus_rd_hw_info, + + .top_version = CAM_VFE_TOP_VER_3_0, + .top_hw_info = &vfe580_top_hw_info, +}; + +#endif /* _CAM_VFE580_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h index 40d8e40ae852..2c56c0e3d46c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -32,6 +32,7 @@ struct cam_vfe_camif_ver3_reg_data { uint32_t dual_pd_extern_reg_update_shift; uint32_t extern_reg_update_mask; uint32_t dual_ife_pix_en_shift; + uint32_t dual_ife_sync_sel_shift; uint32_t operating_mode_shift; uint32_t input_mux_sel_shift; From 4265f73698d9281569f7a10e8ea4f324d3625c1d Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Fri, 6 Dec 2019 16:54:28 -0800 Subject: [PATCH 190/790] msm: camera: common: Enable additional IFE hw Add IFE2 in UAPI header to return acquired IFE's hw index to userspace. CRs-Fixed: 2582959 Change-Id: I42de76453753245376f9a857d5a7de979da78333 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 16 ++++++++++++++++ include/uapi/camera/media/cam_isp.h | 9 ++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 679c2357117f..efb091d8dd84 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1438,6 +1438,22 @@ static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) return CAM_ISP_IFE1_LITE_HW; else if (hw_idx == 4) return CAM_ISP_IFE2_LITE_HW; + else if (hw_idx == 5) + return CAM_ISP_IFE3_LITE_HW; + else if (hw_idx == 6) + return CAM_ISP_IFE4_LITE_HW; + break; + case CAM_CPAS_TITAN_580_V100: + if (hw_idx == 0) + return CAM_ISP_IFE0_HW; + else if (hw_idx == 1) + return CAM_ISP_IFE1_HW; + else if (hw_idx == 2) + return CAM_ISP_IFE2_HW; + else if (hw_idx == 3) + return CAM_ISP_IFE0_LITE_HW; + else if (hw_idx == 4) + return CAM_ISP_IFE1_LITE_HW; break; default: CAM_ERR(CAM_ISP, "Invalid hw_version: 0x%X", diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index e4778cfc9cc2..30e2f0bb8483 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -108,9 +108,12 @@ #define CAM_ISP_IFE0_HW 0x1 #define CAM_ISP_IFE1_HW 0x2 -#define CAM_ISP_IFE0_LITE_HW 0x4 -#define CAM_ISP_IFE1_LITE_HW 0x8 -#define CAM_ISP_IFE2_LITE_HW 0x10 +#define CAM_ISP_IFE2_HW 0x4 +#define CAM_ISP_IFE0_LITE_HW 0x100 +#define CAM_ISP_IFE1_LITE_HW 0x200 +#define CAM_ISP_IFE2_LITE_HW 0x400 +#define CAM_ISP_IFE3_LITE_HW 0x800 +#define CAM_ISP_IFE4_LITE_HW 0x1000 #define CAM_ISP_PXL_PATH 0x1 #define CAM_ISP_PPP_PATH 0x2 From 42021c8b762bca34890d65178d3cf027e19c1c3e Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 9 Dec 2019 16:58:39 -0800 Subject: [PATCH 191/790] msm: camera: common: Add device caps for full devices during probe The v4l2 registration requires all devices that are not subdevs to have device caps field to be non zero. Add device caps for CRM and SYNC devices during probe. CRs-Fixed: 2582994 Change-Id: I804e7bc00d597debc39d1f71259cf607c60ed069 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 7 ++++++- drivers/cam_sync/cam_sync.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 505a036e0c65..3a2f1f72a439 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -555,9 +555,14 @@ static int cam_video_device_setup(void) g_dev.video->ioctl_ops = &g_cam_ioctl_ops; g_dev.video->minor = -1; g_dev.video->vfl_type = VFL_TYPE_GRABBER; + g_dev.video->device_caps |= V4L2_CAP_VIDEO_CAPTURE; rc = video_register_device(g_dev.video, VFL_TYPE_GRABBER, -1); - if (rc) + if (rc) { + CAM_ERR(CAM_CRM, + "video device registration failure rc = %d, name = %s, device_caps = %d", + rc, g_dev.video->name, g_dev.video->device_caps); goto v4l2_fail; + } rc = media_entity_pads_init(&g_dev.video->entity, 0, NULL); if (rc) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index fb0e9495108d..81b3625c3239 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1053,11 +1053,16 @@ static int cam_sync_probe(struct platform_device *pdev) sync_dev->vdev->fops = &cam_sync_v4l2_fops; sync_dev->vdev->ioctl_ops = &g_cam_sync_ioctl_ops; sync_dev->vdev->minor = -1; + sync_dev->vdev->device_caps |= V4L2_CAP_VIDEO_CAPTURE; sync_dev->vdev->vfl_type = VFL_TYPE_GRABBER; rc = video_register_device(sync_dev->vdev, VFL_TYPE_GRABBER, -1); - if (rc < 0) + if (rc < 0) { + CAM_ERR(CAM_SYNC, + "video device registration failure rc = %d, name = %s, device_caps = %d", + rc, sync_dev->vdev->name, sync_dev->vdev->device_caps); goto v4l2_fail; + } cam_sync_init_entity(sync_dev); video_set_drvdata(sync_dev->vdev, sync_dev); From 74bb0d575038ae257d7da9cefeda2c8ddbc34218 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 23 Dec 2019 09:26:54 -0800 Subject: [PATCH 192/790] msm: camera: memmgr: Add support to disable DelayedUnmap Add interface to umd to give an option whether to disable Delayed Unamp feature for a given buffer mapping. DelayedUnmap is enabled by default if umd doesn't explicitly asks for disable. CRs-Fixed: 2580128 Change-Id: I66f87a9dbdfc4d9cecdc02eb24c1c670c9985cae Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_req_mgr/cam_mem_mgr.c | 5 ++++ drivers/cam_smmu/cam_smmu_api.c | 36 +++++++++++++++---------- drivers/cam_smmu/cam_smmu_api.h | 7 ++--- include/uapi/camera/media/cam_req_mgr.h | 1 + 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index f6eec4446cd5..84bc7ce95bad 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -505,12 +505,16 @@ static int cam_mem_util_map_hw_va(uint32_t flags, int i; int rc = -1; int dir = cam_mem_util_get_dma_dir(flags); + bool dis_delayed_unmap = false; if (dir < 0) { CAM_ERR(CAM_MEM, "fail to map DMA direction, dir=%d", dir); return dir; } + if (flags & CAM_MEM_FLAG_DISABLE_DELAYED_UNMAP) + dis_delayed_unmap = true; + CAM_DBG(CAM_MEM, "map_hw_va : fd = %d, flags = 0x%x, dir=%d, num_hdls=%d", fd, flags, dir, num_hdls); @@ -534,6 +538,7 @@ static int cam_mem_util_map_hw_va(uint32_t flags, for (i = 0; i < num_hdls; i++) { rc = cam_smmu_map_user_iova(mmu_hdls[i], fd, + dis_delayed_unmap, dir, (dma_addr_t *)hw_vaddr, len, diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 3043bee2192b..78d1b2cee91e 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -215,8 +215,9 @@ static struct cam_dma_buff_info *cam_smmu_find_mapping_by_virt_address(int idx, dma_addr_t virt_addr); static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, - enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, - size_t *len_ptr, enum cam_smmu_region_id region_id); + bool dis_delayed_unmap, enum dma_data_direction dma_dir, + dma_addr_t *paddr_ptr, size_t *len_ptr, + enum cam_smmu_region_id region_id); static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, struct dma_buf *buf, enum dma_data_direction dma_dir, @@ -1676,7 +1677,7 @@ EXPORT_SYMBOL(cam_smmu_release_sec_heap); static int cam_smmu_map_buffer_validate(struct dma_buf *buf, int idx, enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, size_t *len_ptr, enum cam_smmu_region_id region_id, - struct cam_dma_buff_info **mapping_info) + bool dis_delayed_unmap, struct cam_dma_buff_info **mapping_info) { struct dma_buf_attachment *attach = NULL; struct sg_table *table = NULL; @@ -1751,7 +1752,8 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, } iommu_cb_set.cb_info[idx].shared_mapping_size += *len_ptr; } else if (region_id == CAM_SMMU_REGION_IO) { - attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; + if (!dis_delayed_unmap) + attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; table = dma_buf_map_attachment(attach, dma_dir); if (IS_ERR_OR_NULL(table)) { @@ -1769,8 +1771,9 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, goto err_unmap_sg; } - CAM_DBG(CAM_SMMU, "iova=%pK, region_id=%d, paddr=%pK, len=%d", - iova, region_id, *paddr_ptr, *len_ptr); + CAM_DBG(CAM_SMMU, + "iova=%pK, region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d", + iova, region_id, *paddr_ptr, *len_ptr, attach->dma_map_attrs); if (table->sgl) { CAM_DBG(CAM_SMMU, @@ -1838,8 +1841,9 @@ err_out: static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, - enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, - size_t *len_ptr, enum cam_smmu_region_id region_id) + bool dis_delayed_unmap, enum dma_data_direction dma_dir, + dma_addr_t *paddr_ptr, size_t *len_ptr, + enum cam_smmu_region_id region_id) { int rc = -1; struct cam_dma_buff_info *mapping_info = NULL; @@ -1849,7 +1853,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, buf = dma_buf_get(ion_fd); rc = cam_smmu_map_buffer_validate(buf, idx, dma_dir, paddr_ptr, len_ptr, - region_id, &mapping_info); + region_id, dis_delayed_unmap, &mapping_info); if (rc) { CAM_ERR(CAM_SMMU, "buffer validation failure"); @@ -1873,7 +1877,7 @@ static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, struct cam_dma_buff_info *mapping_info = NULL; rc = cam_smmu_map_buffer_validate(buf, idx, dma_dir, paddr_ptr, len_ptr, - region_id, &mapping_info); + region_id, false, &mapping_info); if (rc) { CAM_ERR(CAM_SMMU, "buffer validation failure"); @@ -1910,6 +1914,11 @@ static int cam_smmu_unmap_buf_and_remove_from_list( return -EINVAL; } + CAM_DBG(CAM_SMMU, + "region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d", + mapping_info->region_id, mapping_info->paddr, mapping_info->len, + mapping_info->attach->dma_map_attrs); + if (mapping_info->region_id == CAM_SMMU_REGION_SHARED) { CAM_DBG(CAM_SMMU, "Removing SHARED buffer paddr = %pK, len = %zu", @@ -1938,7 +1947,6 @@ static int cam_smmu_unmap_buf_and_remove_from_list( iommu_cb_set.cb_info[idx].shared_mapping_size -= mapping_info->len; } else if (mapping_info->region_id == CAM_SMMU_REGION_IO) { - mapping_info->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; iommu_cb_set.cb_info[idx].io_mapping_size -= mapping_info->len; } @@ -2691,7 +2699,7 @@ static int cam_smmu_map_iova_validate_params(int handle, return rc; } -int cam_smmu_map_user_iova(int handle, int ion_fd, +int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, enum cam_smmu_map_dir dir, dma_addr_t *paddr_ptr, size_t *len_ptr, enum cam_smmu_region_id region_id) { @@ -2742,8 +2750,8 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, goto get_addr_end; } - rc = cam_smmu_map_buffer_and_add_to_list(idx, ion_fd, dma_dir, - paddr_ptr, len_ptr, region_id); + rc = cam_smmu_map_buffer_and_add_to_list(idx, ion_fd, + dis_delayed_unmap, dma_dir, paddr_ptr, len_ptr, region_id); if (rc < 0) { CAM_ERR(CAM_SMMU, "mapping or add list fail, idx=%d, fd=%d, region=%d, rc=%d", diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index 057eb741458d..4c2a6a426ee3 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -98,6 +98,8 @@ int cam_smmu_ops(int handle, enum cam_smmu_ops_param op); * * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) * @param ion_fd: ION handle identifying the memory buffer. + * @param dis_delayed_unmap: Whether to disable Delayed Unmap feature + * for this mapping * @dir : Mapping direction: which will traslate toDMA_BIDIRECTIONAL, * DMA_TO_DEVICE or DMA_FROM_DEVICE * @dma_addr : Pointer to physical address where mapped address will be @@ -107,9 +109,8 @@ int cam_smmu_ops(int handle, enum cam_smmu_ops_param op); * @len_ptr : Length of buffer mapped returned by CAM SMMU driver. * @return Status of operation. Negative in case of error. Zero otherwise. */ -int cam_smmu_map_user_iova(int handle, - int ion_fd, enum cam_smmu_map_dir dir, - dma_addr_t *dma_addr, size_t *len_ptr, +int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, + enum cam_smmu_map_dir dir, dma_addr_t *dma_addr, size_t *len_ptr, enum cam_smmu_region_id region_id); /** diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 934e9bdf4bb0..b1170004281c 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -276,6 +276,7 @@ struct cam_req_mgr_link_control { #define CAM_MEM_FLAG_CACHE (1<<10) #define CAM_MEM_FLAG_HW_SHARED_ACCESS (1<<11) #define CAM_MEM_FLAG_CDSP_OUTPUT (1<<12) +#define CAM_MEM_FLAG_DISABLE_DELAYED_UNMAP (1<<13) #define CAM_MEM_MMU_MAX_HANDLE 16 From 7d7ed345608bd7ea5844a13c5cb2649ed53609c2 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Wed, 4 Dec 2019 14:33:28 +0530 Subject: [PATCH 193/790] msm: camera: isp: Change master slave combination for dual IFE For some targets, there is a requirement to have the lower IFE as master. Current implementation selects the higher IFE as the master. This commit changes the acquire logic to reserve the lower IFE first and then the higher IFE as slave. This logic is for dual ife use cases. For single IFE use case, acquire logic is not changed. Also, removes the hard coded check for master hw index during the irq handling. Stores the master hw index in ife hardware manager context and check against it. Change-Id: Ifd3a28e80a0a4d16e3d9278b7ed61290c620ec79 CRs-Fixed: 2582959 Signed-off-by: Gaurav Jindal Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 154 +++++++++++--------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 4 + 2 files changed, 93 insertions(+), 65 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index efb091d8dd84..de3d3d9fd942 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1004,7 +1004,7 @@ static int cam_ife_hw_mgr_acquire_res_bus_rd( /*TBD */ vfe_acquire.vfe_out.is_master = 1; vfe_acquire.vfe_out.dual_slave_core = - (hw_intf->hw_idx == 0) ? 1 : 0; + ife_ctx->slave_hw_idx; } else { vfe_acquire.vfe_out.is_master = 0; vfe_acquire.vfe_out.dual_slave_core = @@ -1015,7 +1015,7 @@ static int cam_ife_hw_mgr_acquire_res_bus_rd( 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; + ife_ctx->master_hw_idx; } rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, @@ -1197,7 +1197,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( /*TBD */ vfe_acquire.vfe_out.is_master = 1; vfe_acquire.vfe_out.dual_slave_core = - (hw_intf->hw_idx == 0) ? 1 : 0; + ife_ctx->slave_hw_idx; } else { vfe_acquire.vfe_out.is_master = 0; vfe_acquire.vfe_out.dual_slave_core = @@ -1208,9 +1208,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( 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; + ife_ctx->master_hw_idx; } - rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -1643,6 +1642,54 @@ err: return rc; } +static int cam_ife_hw_mgr_acquire_csid_hw( + struct cam_ife_hw_mgr *ife_hw_mgr, + struct cam_csid_hw_reserve_resource_args *csid_acquire, + bool is_start_lower_idx) +{ + int i; + int rc = -EINVAL; + struct cam_hw_intf *hw_intf; + + if (!ife_hw_mgr || !csid_acquire) { + CAM_ERR(CAM_ISP, + "Invalid args ife hw mgr %pK csid_acquire %pK", + ife_hw_mgr, csid_acquire); + return -EINVAL; + } + + if (is_start_lower_idx) { + 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(struct + cam_csid_hw_reserve_resource_args)); + if (!rc) + return rc; + } + return rc; + } + + for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; 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(struct + cam_csid_hw_reserve_resource_args)); + if (!rc) + return rc; + } + + return rc; +} + static int cam_ife_mgr_acquire_cid_res( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, @@ -1735,52 +1782,21 @@ static int cam_ife_mgr_acquire_cid_res( } /* Acquire Left if not already acquired */ - 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; + /* For dual IFE cases, start acquiring the lower idx first */ + if (ife_ctx->is_fe_enable || in_port->usage_type) + rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr, + &csid_acquire, true); + else + rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr, + &csid_acquire, false); - 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; - - 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; - } + if (rc || !csid_acquire.node_res) { + CAM_ERR(CAM_ISP, + "Can not acquire ife cid resource for path %d", + path_res_id); + goto put_res; } - + cid_res_temp->hw_res[acquired_cnt++] = csid_acquire.node_res; acquire_successful: CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d", @@ -1791,7 +1807,9 @@ acquire_successful: cid_res_temp->res_id = csid_acquire.node_res->res_id; cid_res_temp->is_dual_vfe = in_port->usage_type; ife_ctx->is_dual = (bool)in_port->usage_type; - + if (ife_ctx->is_dual) + ife_ctx->master_hw_idx = + cid_res_temp->hw_res[0]->hw_intf->hw_idx; if (in_port->num_out_res) cid_res_temp->is_secure = out_port->secure_mode; @@ -1828,6 +1846,8 @@ acquire_successful: goto end; } cid_res_temp->hw_res[1] = csid_acquire.node_res; + ife_ctx->slave_hw_idx = + cid_res_temp->hw_res[1]->hw_intf->hw_idx; CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d", in_port->usage_type); } @@ -6233,9 +6253,10 @@ static int cam_ife_hw_mgr_handle_hw_rup( switch (event_info->res_id) { case CAM_ISP_HW_VFE_IN_CAMIF: - if (ife_hw_mgr_ctx->is_dual) - if (event_info->hw_idx != 1) - break; + if ((ife_hw_mgr_ctx->is_dual) && + (event_info->hw_idx != + ife_hw_mgr_ctx->master_hw_idx)) + break; if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; @@ -6276,8 +6297,8 @@ static int cam_ife_hw_mgr_check_irq_for_dual_vfe( { int32_t rc = -1; uint32_t *event_cnt = NULL; - uint32_t core_idx0 = 0; - uint32_t core_idx1 = 1; + uint32_t master_hw_idx; + uint32_t slave_hw_idx; if (!ife_hw_mgr_ctx->is_dual) return 0; @@ -6296,24 +6317,27 @@ static int cam_ife_hw_mgr_check_irq_for_dual_vfe( return 0; } - if (event_cnt[core_idx0] == event_cnt[core_idx1]) { + master_hw_idx = ife_hw_mgr_ctx->master_hw_idx; + slave_hw_idx = ife_hw_mgr_ctx->slave_hw_idx; - event_cnt[core_idx0] = 0; - event_cnt[core_idx1] = 0; + if (event_cnt[master_hw_idx] == event_cnt[slave_hw_idx]) { + + event_cnt[master_hw_idx] = 0; + event_cnt[slave_hw_idx] = 0; rc = 0; return rc; } - if ((event_cnt[core_idx0] && - (event_cnt[core_idx0] - event_cnt[core_idx1] > 1)) || - (event_cnt[core_idx1] && - (event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) { + if ((event_cnt[master_hw_idx] && + (event_cnt[master_hw_idx] - event_cnt[slave_hw_idx] > 1)) || + (event_cnt[slave_hw_idx] && + (event_cnt[slave_hw_idx] - event_cnt[master_hw_idx] > 1))) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "One of the VFE could not generate hw event %d core_0_cnt %d core_1_cnt %d", - hw_event_type, event_cnt[core_idx0], - event_cnt[core_idx1]); + "One of the VFE could not generate hw event %d master[%d] core_cnt %d slave[%d] core_cnt %d", + hw_event_type, master_hw_idx, event_cnt[master_hw_idx], + slave_hw_idx, event_cnt[slave_hw_idx]); rc = -1; return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 7e6b91bab916..17a9e11834df 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -101,6 +101,8 @@ struct cam_ife_hw_mgr_debug { * @list: used by the ctx list. * @common: common acquired context data * @ctx_index: acquired context id. + * @master_hw_idx: hw index for master core + * @slave_hw_idx: hw index for slave core * @hw_mgr: IFE hw mgr which owns this context * @ctx_in_use: flag to tell whether context is active * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be @@ -144,6 +146,8 @@ struct cam_ife_hw_mgr_ctx { struct cam_isp_hw_mgr_ctx common; uint32_t ctx_index; + uint32_t master_hw_idx; + uint32_t slave_hw_idx; struct cam_ife_hw_mgr *hw_mgr; uint32_t ctx_in_use; From eef5866053570d15413c95f4da9fcba6358e3173 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 5 Jan 2020 16:54:50 -0800 Subject: [PATCH 194/790] msm: camera: isp: Add hw version checks and dt match string The platform register requires dt match string for csid to probe and correct cpas hw version is required for vfe to function. Add dt match strings and hw version checks in csid and vfe. CRs-Fixed: 2584631 Change-Id: Ieb2766fa6243bf4133b43f657a18aed7f04447be Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Vishalsingh Hajeri --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 5 ++-- .../isp_hw/ife_csid_hw/cam_ife_csid17x.c | 6 ++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 24 ++++++++++++------- .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c | 6 ++++- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 4 +++- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 3 ++- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 3 ++- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 8bc550bc188d..67cb42aa1661 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -5626,7 +5626,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, &query.camera_version, &query.cpas_version, &cam_caps); cam_cpas_get_cpas_hw_version(&camera_hw_version); - if (camera_hw_version == CAM_CPAS_TITAN_480_V100) { + if ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || + (camera_hw_version == CAM_CPAS_TITAN_580_V100)) { if (cam_caps & CPAS_TITAN_480_IPE0_BIT) icp_hw_mgr.ipe0_enable = true; if (cam_caps & CPAS_BPS_BIT) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c index 8e34447f3634..98155a08c036 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ @@ -54,6 +54,10 @@ static const struct of_device_id cam_ife_csid17x_dt_match[] = { .compatible = "qcom,csid480", .data = &cam_ife_csid480_hw_info, }, + { + .compatible = "qcom,csid580", + .data = &cam_ife_csid480_hw_info, + }, {} }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 2e57cd1f1155..3682823a496b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -339,7 +339,8 @@ static int cam_ife_match_vc_dt_pair(int32_t *vc, uint32_t *dt, return -EINVAL; } - if (camera_hw_version != CAM_CPAS_TITAN_480_V100) + if ((camera_hw_version != CAM_CPAS_TITAN_480_V100) && + (camera_hw_version != CAM_CPAS_TITAN_580_V100)) num_valid_vc_dt = 1; switch (num_valid_vc_dt) { @@ -771,6 +772,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, } break; case CAM_CPAS_TITAN_480_V100: + case CAM_CPAS_TITAN_580_V100: if (cid_reserv->in_port->cust_node == 1) { if (cid_reserv->in_port->usage_type == 1) { CAM_ERR(CAM_ISP, "Dual IFE is not supported"); @@ -1716,7 +1718,8 @@ static int cam_ife_csid_init_config_pxl_path( } CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); - if (camera_hw_version == CAM_CPAS_TITAN_480_V100) + if ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || + (camera_hw_version == CAM_CPAS_TITAN_580_V100)) val |= (path_data->drop_enable << csid_reg->cmn_reg->drop_h_en_shift_val) | (path_data->drop_enable << @@ -1737,7 +1740,8 @@ static int cam_ife_csid_init_config_pxl_path( pxl_reg->csid_pxl_cfg0_addr); if (path_data->is_valid_vc1_dt1 && - camera_hw_version == CAM_CPAS_TITAN_480_V100) { + ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || + (camera_hw_version == CAM_CPAS_TITAN_580_V100))) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_multi_vcdt_cfg0_addr); val |= ((path_data->vc1 << 2) | @@ -1773,7 +1777,8 @@ static int cam_ife_csid_init_config_pxl_path( * Skip for version 480 HW due to HW limitation. */ if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF) && - (camera_hw_version != CAM_CPAS_TITAN_480_V100)) { + (camera_hw_version != CAM_CPAS_TITAN_480_V100) && + (camera_hw_version != CAM_CPAS_TITAN_580_V100)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); val |= (1 << pxl_reg->early_eof_en_shift_val); @@ -2167,7 +2172,8 @@ static int cam_ife_csid_init_config_rdi_path( CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); if (camera_hw_version == CAM_CPAS_TITAN_480_V100 || - camera_hw_version == CAM_CPAS_TITAN_175_V130) { + camera_hw_version == CAM_CPAS_TITAN_175_V130 || + camera_hw_version == CAM_CPAS_TITAN_580_V100) { val |= (path_data->drop_enable << csid_reg->cmn_reg->drop_h_en_shift_val) | (path_data->drop_enable << @@ -2180,7 +2186,8 @@ static int cam_ife_csid_init_config_rdi_path( csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); if (path_data->is_valid_vc1_dt1 && - camera_hw_version == CAM_CPAS_TITAN_480_V100) { + ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || + (camera_hw_version == CAM_CPAS_TITAN_580_V100))) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_multi_vcdt_cfg0_addr); val |= ((path_data->vc1 << 2) | @@ -2236,7 +2243,8 @@ static int cam_ife_csid_init_config_rdi_path( csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_pattern_addr); /* Write max value to pixel drop period due to a bug in ver 480 HW */ - if (camera_hw_version == CAM_CPAS_TITAN_480_V100 && + if (((camera_hw_version == CAM_CPAS_TITAN_480_V100) || + (camera_hw_version == CAM_CPAS_TITAN_580_V100)) && path_data->drop_enable) cam_io_w_mb(0x1F, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_period_addr); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c index 2bc6e8ce6284..421218a0ee06 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -32,6 +32,10 @@ static const struct of_device_id cam_ife_csid_lite_dt_match[] = { .compatible = "qcom,csid-lite480", .data = &cam_ife_csid_lite_480_hw_info, }, + { + .compatible = "qcom,csid-lite580", + .data = &cam_ife_csid_lite_480_hw_info, + }, {} }; MODULE_DEVICE_TABLE(of, cam_ife_csid_lite_dt_match); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index a640353b6b5e..ae5713f455dd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -90,6 +90,7 @@ int cam_vfe_reset_irq_top_half(uint32_t evt_id, switch (soc_info->hw_version) { case CAM_CPAS_TITAN_480_V100: + case CAM_CPAS_TITAN_580_V100: if (!soc_private->is_ife_lite) { if (th_payload->evt_status_arr[0] & 0x1) { cam_io_w(0xFFFFFFFF, mem_base + @@ -330,6 +331,7 @@ int cam_vfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) switch (soc_info->hw_version) { case CAM_CPAS_TITAN_480_V100: + case CAM_CPAS_TITAN_580_V100: if (!soc_private->is_ife_lite) top_reset_irq_reg_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = CAM_VFE_48X_TOP_RESET_MASK; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 77e2a059af57..c0b555d37090 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -60,6 +60,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) switch (soc_info->hw_version) { case CAM_CPAS_TITAN_480_V100: + case CAM_CPAS_TITAN_580_V100: num_ubwc_cfg = of_property_count_u32_elems(of_node, "ubwc-static-cfg"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 12cdcb19f2c0..ef161d2b20b9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -425,6 +425,7 @@ static int cam_vfe_camif_ver3_resource_start( /* epoch config */ switch (soc_private->cpas_version) { case CAM_CPAS_TITAN_480_V100: + case CAM_CPAS_TITAN_580_V100: epoch0_line_cfg = (rsrc_data->last_line - rsrc_data->first_line) / 4; /* epoch line cfg will still be configured at midpoint of the From b8d55f649d8bdb1e7ba693383f48690b3f0380e7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 4 Nov 2019 10:13:48 -0800 Subject: [PATCH 195/790] msm: camera: sensor: Add support fo multiple regulator sources Currently image sensor need single source of the regulator per category. Some sensor needs extra analog voltage for the functionality, which require to draw power from multiple voltage regulator sources. This change extends supports to add multiple voltage sources for analog voltage. CRs-Fixed: 2584631 Change-Id: I2d76cfb0fb971758c0d596ffd543aa3926a8886d Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_dev.h | 1 - .../cam_sensor_utils/cam_sensor_cmn_header.h | 4 +- .../cam_sensor_utils/cam_sensor_util.c | 46 +++++++++++++++++++ drivers/cam_utils/cam_soc_util.h | 2 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 1e22c8c5288c..e1c0910b37c7 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -40,7 +40,6 @@ #define MAX_DATA_RATES 3 #define MAX_DATA_RATE_REGS 30 -#define MAX_REGULATOR 5 #define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver" #define CSIPHY_POWER_UP 0 diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 563414e640cc..bd0cb25c88a2 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -16,8 +16,7 @@ #include #include -#define MAX_REGULATOR 5 -#define MAX_POWER_CONFIG 12 +#define MAX_POWER_CONFIG 12 #define MAX_PER_FRAME_ARRAY 32 #define BATCH_SIZE_MAX 16 @@ -142,6 +141,7 @@ enum msm_camera_power_seq_type { SENSOR_STANDBY, SENSOR_CUSTOM_GPIO1, SENSOR_CUSTOM_GPIO2, + SENSOR_VANA1, SENSOR_SEQ_TYPE_MAX, }; diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 078e3e08657a..4b2b7781207e 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -980,6 +980,29 @@ int32_t msm_camera_fill_vreg_params( power_setting[i].seq_val = INVALID_VREG; break; + case SENSOR_VANA1: + for (j = 0; j < num_vreg; j++) { + if (!strcmp(soc_info->rgltr_name[j], + "cam_vana1")) { + CAM_DBG(CAM_SENSOR, + "i: %d j: %d cam_vana1", i, j); + power_setting[i].seq_val = j; + + if (VALIDATE_VOLTAGE( + soc_info->rgltr_min_volt[j], + soc_info->rgltr_max_volt[j], + power_setting[i].config_val)) { + soc_info->rgltr_min_volt[j] = + soc_info->rgltr_max_volt[j] = + power_setting[i].config_val; + } + break; + } + } + if (j == num_vreg) + power_setting[i].seq_val = INVALID_VREG; + break; + case SENSOR_VAF: for (j = 0; j < num_vreg; j++) { @@ -1406,6 +1429,8 @@ int cam_get_dt_power_setting_data(struct device_node *of_node, ps[i].seq_type = SENSOR_VIO; } else if (!strcmp(seq_name, "cam_vana")) { ps[i].seq_type = SENSOR_VANA; + } else if (!strcmp(seq_name, "cam_vana1")) { + ps[i].seq_type = SENSOR_VANA1; } else if (!strcmp(seq_name, "cam_clk")) { ps[i].seq_type = SENSOR_MCLK; } else { @@ -1533,6 +1558,24 @@ int cam_sensor_util_init_gpio_pin_tbl( gpio_num_info->gpio_num[SENSOR_VANA]); } + rc = of_property_read_u32(of_node, "gpio-vana1", &val); + if (rc != -EINVAL) { + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "read gpio-vana1 failed rc %d", rc); + goto free_gpio_info; + } else if (val >= gpio_array_size) { + CAM_ERR(CAM_SENSOR, "gpio-vana1 invalid %d", val); + rc = -EINVAL; + goto free_gpio_info; + } + gpio_num_info->gpio_num[SENSOR_VANA1] = + gconf->cam_gpio_common_tbl[val].gpio; + gpio_num_info->valid[SENSOR_VANA1] = 1; + + CAM_DBG(CAM_SENSOR, "gpio-vana1 %d", + gpio_num_info->gpio_num[SENSOR_VANA1]); + } + rc = of_property_read_u32(of_node, "gpio-vio", &val); if (rc != -EINVAL) { if (rc < 0) { @@ -1977,6 +2020,7 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, } break; case SENSOR_VANA: + case SENSOR_VANA1: case SENSOR_VDIG: case SENSOR_VIO: case SENSOR_VAF: @@ -2093,6 +2137,7 @@ power_up_failed: [power_setting->seq_type], GPIOF_OUT_INIT_LOW); break; case SENSOR_VANA: + case SENSOR_VANA1: case SENSOR_VDIG: case SENSOR_VIO: case SENSOR_VAF: @@ -2261,6 +2306,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, break; case SENSOR_VANA: + case SENSOR_VANA1: case SENSOR_VDIG: case SENSOR_VIO: case SENSOR_VAF: diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 9c3052d5938b..25c08fc1890d 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -30,7 +30,7 @@ #define CAM_SOC_MAX_BASE CAM_SOC_MAX_BLOCK /* maximum number of device regulator */ -#define CAM_SOC_MAX_REGULATOR 5 +#define CAM_SOC_MAX_REGULATOR 10 /* maximum number of device clock */ #define CAM_SOC_MAX_CLK 32 From 423e6d195c162cf313ef6f4c0ded9d35b10220fe Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Fri, 6 Dec 2019 20:10:27 -0800 Subject: [PATCH 196/790] msm: camera: ife: Sync master and slave IFE Program hw_sync_sel field in core_cfg register in case of dual ife. CRs-Fixed: 2582959 Change-Id: I8a60cb06991738872c4caf0120ea21e5954d208a Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 14 ++++++++-- .../isp_hw/include/cam_vfe_hw_intf.h | 6 +++- .../isp_hw/vfe_hw/vfe17x/cam_vfe580.h | 3 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 28 +++++++++++++++---- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.h | 3 +- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index de3d3d9fd942..36dbdc17e807 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -1550,6 +1550,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( else vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + vfe_acquire.vfe_in.is_dual = csid_res->is_dual_vfe; break; case CAM_IFE_PIX_PATH_RES_PPP: @@ -1590,12 +1591,21 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( hw_intf = ife_hw_mgr->ife_devices[ csid_res->hw_res[i]->hw_intf->hw_idx]; + if (i == CAM_ISP_HW_SPLIT_LEFT && + ife_src_res->is_dual_vfe) { + vfe_acquire.vfe_in.dual_hw_idx = + ife_ctx->slave_hw_idx; + } + /* fill in more acquire information as needed */ /* slave Camif resource, */ if (i == CAM_ISP_HW_SPLIT_RIGHT && - ife_src_res->is_dual_vfe) + ife_src_res->is_dual_vfe) { vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE; + vfe_acquire.vfe_in.dual_hw_idx = + ife_ctx->master_hw_idx; + } rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index a1d1c6a60881..24ae56de5014 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_HW_INTF_H_ @@ -137,6 +137,8 @@ struct cam_vfe_hw_vfe_out_acquire_args { * is successful * @res_id: Resource ID of resource to acquire if specific, * else CAM_ISP_HW_VFE_IN_MAX + * @dual_hw_idx: Slave core for this master core if dual vfe case + * @is_dual: flag to indicate if dual vfe case * @cdm_ops: CDM operations * @sync_mode: In case of Dual VFE, this is Master or Slave. * (Default is Master in case of Single VFE) @@ -145,6 +147,8 @@ struct cam_vfe_hw_vfe_out_acquire_args { struct cam_vfe_hw_vfe_in_acquire_args { struct cam_isp_resource_node *rsrc_node; uint32_t res_id; + uint32_t dual_hw_idx; + uint32_t is_dual; void *cdm_ops; enum cam_isp_hw_sync_mode sync_mode; struct cam_isp_in_port_generic_info *in_port; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h index 76c8b400a305..8bb01532e807 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ @@ -37,6 +37,7 @@ static struct cam_vfe_camif_ver3_reg_data vfe_580_camif_reg_data = { .pp_camif_cfg_en_shift = 0, .pp_camif_cfg_ife_out_en_shift = 8, .top_debug_cfg_en = 1, + .dual_vfe_sync_mask = 0x3, }; static struct cam_vfe_camif_lite_ver3_reg_data vfe580_camif_rdi1_reg_data = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 12cdcb19f2c0..6b5f8bf83371 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -52,6 +52,8 @@ struct cam_vfe_mux_camif_ver3_data { uint32_t camif_debug; uint32_t horizontal_bin; uint32_t qcfa_bin; + uint32_t dual_hw_idx; + uint32_t is_dual; }; static int cam_vfe_camif_ver3_get_evt_payload( @@ -258,6 +260,10 @@ int cam_vfe_camif_ver3_acquire_resource( camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin; camif_data->event_cb = acquire_data->event_cb; camif_data->priv = acquire_data->priv; + camif_data->is_dual = acquire_data->vfe_in.is_dual; + + if (acquire_data->vfe_in.is_dual) + camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx; CAM_DBG(CAM_ISP, "VFE:%d CAMIF pix_pattern:%d dsp_mode=%d", camif_res->hw_intf->hw_idx, @@ -387,10 +393,16 @@ static int cam_vfe_camif_ver3_resource_start( 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 (camif_res->hw_intf->hw_idx != CAM_ISP_HW_VFE_CORE_2) { + 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); + } else { + CAM_ERR(CAM_ISP, "Error, HVX not available for IFE_%d", + camif_res->hw_intf->hw_idx); + return -EINVAL; + } } if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) @@ -419,6 +431,12 @@ static int cam_vfe_camif_ver3_resource_start( val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) << CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP; + if (rsrc_data->is_dual && rsrc_data->reg_data->dual_vfe_sync_mask) { + val |= (((rsrc_data->dual_hw_idx & + rsrc_data->reg_data->dual_vfe_sync_mask) + 1) << + rsrc_data->reg_data->dual_ife_sync_sel_shift); + } + cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg_0); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h index 2c56c0e3d46c..e611d1ac62f2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_CAMIF_VER3_H_ @@ -58,6 +58,7 @@ struct cam_vfe_camif_ver3_reg_data { uint32_t pp_camif_cfg_en_shift; uint32_t pp_camif_cfg_ife_out_en_shift; uint32_t top_debug_cfg_en; + uint32_t dual_vfe_sync_mask; }; struct cam_vfe_camif_ver3_hw_info { From 4a019e7828598d7802f790fa5db443966745f3b7 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Wed, 8 Jan 2020 11:53:18 -0800 Subject: [PATCH 197/790] msm: camera: uapi: Add flags for additional IFE HW As part of acquire HW, kernel passes the IFE hw_idx to userspace. This change will enable the capability to pass the hw_idx of additional IFE HW enabled. CRs-Fixed: 2582959 Change-Id: I689b99d021c8d0f3440e46d09a5dcda3daaefcfc Signed-off-by: Vishalsingh Hajeri --- include/uapi/camera/media/cam_isp.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index 30e2f0bb8483..22e898b55cfc 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_ISP_H__ @@ -108,12 +108,12 @@ #define CAM_ISP_IFE0_HW 0x1 #define CAM_ISP_IFE1_HW 0x2 -#define CAM_ISP_IFE2_HW 0x4 -#define CAM_ISP_IFE0_LITE_HW 0x100 -#define CAM_ISP_IFE1_LITE_HW 0x200 -#define CAM_ISP_IFE2_LITE_HW 0x400 -#define CAM_ISP_IFE3_LITE_HW 0x800 -#define CAM_ISP_IFE4_LITE_HW 0x1000 +#define CAM_ISP_IFE0_LITE_HW 0x4 +#define CAM_ISP_IFE1_LITE_HW 0x8 +#define CAM_ISP_IFE2_LITE_HW 0x10 +#define CAM_ISP_IFE3_LITE_HW 0x20 +#define CAM_ISP_IFE4_LITE_HW 0x40 +#define CAM_ISP_IFE2_HW 0x100 #define CAM_ISP_PXL_PATH 0x1 #define CAM_ISP_PPP_PATH 0x2 From 80ccf69ac9142e4d561ec5bc62d0b8026277f494 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 27 Dec 2019 12:24:31 -0800 Subject: [PATCH 198/790] msm: camera: reqmgr: Change subdev register logic in camera req manager Due to deferred probes being dpendent on request manager to register v4l2 subdev, failures are seen if probes are delayed. Change logic for subdev registration to avoid failures due to delay. CRs-Fixed: 2584631 Change-Id: Ia01d5d27ff6a6e6dbbb8e3b25b9aa53ac2fa9e38 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 81 ++++++++------------------- drivers/cam_req_mgr/cam_req_mgr_dev.h | 8 --- drivers/cam_req_mgr/cam_subdev.h | 1 + drivers/camera_main.c | 9 --- 4 files changed, 25 insertions(+), 74 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 3a2f1f72a439..4c4bb5afacae 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -626,15 +626,6 @@ int cam_register_subdev(struct cam_subdev *csd) } mutex_lock(&g_dev.dev_lock); - if ((g_dev.subdev_nodes_created) && - (csd->sd_flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) { - CAM_ERR(CAM_CRM, - "dynamic node is not allowed, name: %s, type :%d", - csd->name, csd->ent_function); - rc = -EINVAL; - goto reg_fail; - } - sd = &csd->sd; v4l2_subdev_init(sd, csd->ops); sd->internal_ops = csd->internal_ops; @@ -646,11 +637,34 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; + if (csd->subdev_node_created) { + CAM_ERR(CAM_CRM, + "Dynamic Node is not allowed, name: %s, type: %d", + csd->name, csd->ent_function); + rc = -EINVAL; + goto reg_fail; + } + rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); goto reg_fail; } + + rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); + if (rc) { + CAM_ERR(CAM_CRM, + "Device Register subdev node failed: rc = %d", rc); + goto reg_fail; + + } + + if ((sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) { + sd->entity.name = video_device_node_name(sd->devnode); + CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); + } + + csd->subdev_node_created = true; g_dev.count++; reg_fail: @@ -684,7 +698,6 @@ static int cam_req_mgr_remove(struct platform_device *pdev) cam_v4l2_device_cleanup(); mutex_destroy(&g_dev.dev_lock); g_dev.state = false; - g_dev.subdev_nodes_created = false; return 0; } @@ -708,7 +721,6 @@ static int cam_req_mgr_probe(struct platform_device *pdev) g_dev.open_cnt = 0; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); - g_dev.subdev_nodes_created = false; mutex_init(&g_dev.dev_lock); rc = cam_req_mgr_util_init(); @@ -723,8 +735,6 @@ static int cam_req_mgr_probe(struct platform_device *pdev) goto req_mgr_core_fail; } - g_dev.state = true; - if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", sizeof(struct cam_req_mgr_timer), 64, @@ -738,6 +748,7 @@ static int cam_req_mgr_probe(struct platform_device *pdev) g_cam_req_mgr_timer_cachep->name); } + g_dev.state = true; return rc; req_mgr_core_fail: @@ -770,56 +781,12 @@ static struct platform_driver cam_req_mgr_driver = { }, }; -int cam_dev_mgr_create_subdev_nodes(void) -{ - int rc; - struct v4l2_subdev *sd; - - if (!g_dev.v4l2_dev) - return -EINVAL; - - if (g_dev.state != true) { - CAM_ERR(CAM_CRM, "camera root device not ready yet"); - return -ENODEV; - } - - mutex_lock(&g_dev.dev_lock); - if (g_dev.subdev_nodes_created) { - rc = -EEXIST; - goto create_fail; - } - - rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); - if (rc) { - CAM_ERR(CAM_CRM, "failed to register the sub devices"); - goto create_fail; - } - - list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { - if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) - continue; - sd->entity.name = video_device_node_name(sd->devnode); - CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); - } - - g_dev.subdev_nodes_created = true; - -create_fail: - mutex_unlock(&g_dev.dev_lock); - return rc; -} - int cam_req_mgr_init(void) { return platform_driver_register(&cam_req_mgr_driver); } EXPORT_SYMBOL(cam_req_mgr_init); -int cam_req_mgr_late_init(void) -{ - return cam_dev_mgr_create_subdev_nodes(); -} - void cam_req_mgr_exit(void) { platform_driver_unregister(&cam_req_mgr_driver); diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 0b7a1e943965..86381d90080b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -12,7 +12,6 @@ * * @video: pointer to struct video device. * @v4l2_dev: pointer to struct v4l2 device. - * @subdev_nodes_created: flag to check the created state. * @count: number of subdevices registered. * @dev_lock: lock for the subdevice count. * @state: state of the root device. @@ -24,7 +23,6 @@ struct cam_req_mgr_device { struct video_device *video; struct v4l2_device *v4l2_dev; - bool subdev_nodes_created; int count; struct mutex dev_lock; bool state; @@ -47,12 +45,6 @@ int cam_req_mgr_notify_message(struct cam_req_mgr_message *msg, */ int cam_req_mgr_init(void); -/** - * @brief : API to register all subdev with v4l2 framework. - * @return struct platform_device pointer on on success, or ERR_PTR() on error. - */ -int cam_req_mgr_late_init(void); - /** * @brief : API to remove REQ_MGR from platform framework. */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index 05aee58797b9..ef8e9fbac794 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -49,6 +49,7 @@ struct cam_subdev { u32 sd_flags; void *token; u32 ent_function; + bool subdev_node_created; }; /** diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 28b40dbd284e..d79d5bd1be04 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -239,15 +239,6 @@ static int camera_init(void) } } - rc = cam_req_mgr_late_init(); - if (rc) { - CAM_ERR(CAM_UTIL, - "Late_init Sequence/Subdev node creation fail: rc = %d", - rc); - camera_error_exit(i, j); - goto end_init; - } - CAM_INFO(CAM_UTIL, "Camera driver initialized"); end_init: From 17bedd020e7921cb67338c906b918d41355dae9c Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 23 Dec 2019 19:38:16 -0800 Subject: [PATCH 199/790] msm: camera: utils: Fix bus client register for icc The common data containing src and dst bus IDs necessary for bw voting is fed incorrectly. Fix passing of bus IDs for registering bus clients to be valid values. CRs-Fixed: 2584631 Change-Id: Ifee3a5ac345cf8df5cb775f5af633d8e146842d9 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_utils/cam_soc_icc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index 0a22cecc3c08..b9d507eea165 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -97,6 +97,7 @@ int cam_soc_bus_client_register(struct platform_device *pdev, } bus_client->client_data = bus_client_data; + bus_client->common_data = common_data; bus_client_data->icc_data = icc_get(&pdev->dev, bus_client->common_data->src_id, bus_client->common_data->dst_id); @@ -106,8 +107,6 @@ int cam_soc_bus_client_register(struct platform_device *pdev, goto error; } - bus_client->common_data = common_data; - rc = icc_set_bw(bus_client_data->icc_data, 0, 0); if (rc) { CAM_ERR(CAM_UTIL, "Bus client update request failed, rc = %d", From 737f25e61195350ba7e0f53cac8e73aac809eb1b Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 4 Dec 2019 18:39:25 -0800 Subject: [PATCH 200/790] msm: camera: sensor: Add CPHY and DPHY bringup sequence Add 3phase and 2phase_mission/combo mode sequence for lahaina target. CRs-Fixed: 2584631 Change-Id: Id2e207e46544e3f7d361803814eec725d28c3702 Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_soc.c | 23 +- .../cam_csiphy/cam_csiphy_soc.h | 3 +- .../include/cam_csiphy_1_2_3_hwreg.h | 394 ++++++++++++++++++ 3 files changed, 418 insertions(+), 2 deletions(-) create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index c5a8033aaffb..cc07b5eed5ab 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_csiphy_soc.h" @@ -9,6 +9,7 @@ #include "include/cam_csiphy_1_0_hwreg.h" #include "include/cam_csiphy_1_2_hwreg.h" #include "include/cam_csiphy_1_2_1_hwreg.h" +#include "include/cam_csiphy_1_2_3_hwreg.h" #include "include/cam_csiphy_2_0_hwreg.h" #define CSIPHY_DIVISOR_16 16 @@ -310,6 +311,26 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_1_2; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.3")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_3_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_3_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_3_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2_3; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2_3; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2_3; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_3; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->hw_version = CSIPHY_VERSION_V123; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2_3; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index c02b9556add4..e68ec2a58de0 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_SOC_H_ @@ -30,6 +30,7 @@ #define CSIPHY_VERSION_V11 0x11 #define CSIPHY_VERSION_V12 0x12 #define CSIPHY_VERSION_V121 0x121 +#define CSIPHY_VERSION_V123 0x123 #define CSIPHY_VERSION_V20 0x20 /** diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h new file mode 100644 index 000000000000..74a3c564ea45 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -0,0 +1,394 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_2_3_HWREG_H_ +#define _CAM_CSIPHY_1_2_3_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_2_3 = { + .mipi_csiphy_interrupt_status0_addr = 0x8B0, + .mipi_csiphy_interrupt_clear0_addr = 0x858, + .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_common_array_size = 7, + .csiphy_reset_array_size = 5, + .csiphy_2ph_config_array_size = 16, + .csiphy_3ph_config_array_size = 30, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x081C, 0x5A, 0x00, CSIPHY_3PH_REGS}, + {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_1_2_3[] = { + {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE}, + {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_irq_reg_1_2_3[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct +csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x000c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x040c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x060c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_2_3_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x000c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct +csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct data_rate_settings_t data_rate_delta_table_1_2_3 = { + .num_data_rate_settings = 3, + .data_rate_settings = { + { + /* (2.5 * 10**3 * 2.28) rounded value*/ + .bandwidth = 5700000000, + .data_rate_reg_array_size = 6, + .csiphy_data_rate_regs = { + {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + } + }, + { + /* (3.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 7980000000, + .data_rate_reg_array_size = 9, + .csiphy_data_rate_regs = { + {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + /* (4.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 10260000000, + .data_rate_reg_array_size = 9, + .csiphy_data_rate_regs = { + {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + } + } +}; + +#endif /* _CAM_CSIPHY_1_2_3_HWREG_H_ */ From 7b1dc048667c5c9191a2c18a28c4fff03fd9dc52 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 12 Dec 2019 15:42:48 -0800 Subject: [PATCH 201/790] msm: camera: config: Fix lahaina configuration Top-level Makefile doesn't export techpack configs. As such, we must revert to generating our own conf.h file instead of relying on autoconf.h. This has the side-effect of not allowing IS_REACHABLE/IS_ENABLED macro's from working on configs enabled within a techpack. CRs-Fixed: 2584631 Change-Id: I9c35b305b81c5a6a6892ca87ace9f69192fcca5b Signed-off-by: Karthik Jayakumar --- Makefile | 5 +++++ config/lahainacameraconf.h | 11 +++++++++++ drivers/Makefile | 2 +- drivers/camera_main.c | 40 ++++++++++++++++++-------------------- 4 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 config/lahainacameraconf.h diff --git a/Makefile b/Makefile index d721be623d89..c24393bede31 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/bengalcameraconf.h endif +ifeq ($(CONFIG_ARCH_LAHAINA), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/lahainacameraconf.h +endif + ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) # Use USERINCLUDE when you must reference the UAPI directories only. USERINCLUDE += \ diff --git a/config/lahainacameraconf.h b/config/lahainacameraconf.h new file mode 100644 index 000000000000..58a006d2e4cd --- /dev/null +++ b/config/lahainacameraconf.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 diff --git a/drivers/Makefile b/drivers/Makefile index 06420672dab4..ad2a01f4a08f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -46,7 +46,7 @@ camera-y := \ cam_cdm/cam_cdm_virtual_core.o \ cam_cdm/cam_cdm_hw_core.o -ifdef CONFIG_QCOM_CX_IPEAK +ifneq (,$(filter $(CONFIG_QCOM_CX_IPEAK),y m)) camera-y += cam_utils/cam_cx_ipeak.o endif diff --git a/drivers/camera_main.c b/drivers/camera_main.c index d79d5bd1be04..9286d0631958 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -46,6 +46,8 @@ #include "cam_custom_csid_dev.h" #include "cam_custom_sub_mod_dev.h" +#include "cam_debug_util.h" + struct camera_submodule_component { int (*init)(void); void (*exit)(void); @@ -67,7 +69,7 @@ static const struct camera_submodule_component camera_base[] = { }; static const struct camera_submodule_component camera_isp[] = { -#if IS_ENABLED(CONFIG_SPECTRA_ISP) +#ifdef CONFIG_SPECTRA_ISP {&cam_ife_csid17x_init_module, &cam_ife_csid17x_exit_module}, {&cam_ife_csid_lite_init_module, &cam_ife_csid_lite_exit_module}, {&cam_vfe_init_module, &cam_vfe_exit_module}, @@ -76,7 +78,7 @@ static const struct camera_submodule_component camera_isp[] = { }; static const struct camera_submodule_component camera_sensor[] = { -#if IS_ENABLED(CONFIG_SPECTRA_SENSOR) +#ifdef CONFIG_SPECTRA_SENSOR {&cam_res_mgr_init, &cam_res_mgr_exit}, {&cam_cci_init_module, &cam_cci_exit_module}, {&cam_csiphy_init_module, &cam_csiphy_exit_module}, @@ -91,7 +93,7 @@ static const struct camera_submodule_component camera_sensor[] = { }; static const struct camera_submodule_component camera_icp[] = { -#if IS_ENABLED(CONFIG_SPECTRA_ICP) +#ifdef CONFIG_SPECTRA_ICP {&cam_a5_init_module, &cam_a5_exit_module}, {&cam_ipe_init_module, &cam_ipe_exit_module}, {&cam_bps_init_module, &cam_bps_exit_module}, @@ -100,7 +102,7 @@ static const struct camera_submodule_component camera_icp[] = { }; static const struct camera_submodule_component camera_jpeg[] = { -#if IS_ENABLED(CONFIG_SPECTRA_JPEG) +#ifdef CONFIG_SPECTRA_JPEG {&cam_jpeg_enc_init_module, &cam_jpeg_enc_exit_module}, {&cam_jpeg_dma_init_module, &cam_jpeg_dma_exit_module}, {&cam_jpeg_dev_init_module, &cam_jpeg_dev_exit_module}, @@ -108,21 +110,21 @@ static const struct camera_submodule_component camera_jpeg[] = { }; static const struct camera_submodule_component camera_fd[] = { -#if IS_ENABLED(CONFIG_SPECTRA_FD) +#ifdef CONFIG_SPECTRA_FD {&cam_fd_hw_init_module, &cam_fd_hw_exit_module}, {&cam_fd_dev_init_module, &cam_fd_dev_exit_module}, #endif }; static const struct camera_submodule_component camera_lrme[] = { -#if IS_ENABLED(CONFIG_SPECTRA_LRME) +#ifdef CONFIG_SPECTRA_LRME {&cam_lrme_hw_init_module, &cam_lrme_hw_exit_module}, {&cam_lrme_dev_init_module, &cam_lrme_dev_exit_module}, #endif }; static const struct camera_submodule_component camera_custom[] = { -#if IS_ENABLED(CONFIG_SPECTRA_CUSTOM) +#ifdef CONFIG_SPECTRA_CUSTOM {&cam_custom_hw_sub_module_init, &cam_custom_hw_sub_module_exit}, {&cam_custom_csid_driver_init, &cam_custom_csid_driver_exit}, {&cam_custom_dev_init_module, &cam_custom_dev_exit_module}, @@ -188,16 +190,16 @@ static int camera_verify_submodules(void) submodule_table[i].component[j].init, submodule_table[i].component[j].exit); rc = -EINVAL; - goto err; + goto end; } } } -err: +end: return rc; } -static void camera_error_exit(int i, int j) +static void __camera_exit(int i, int j) { uint num_exits; @@ -225,6 +227,8 @@ static int camera_init(void) /* For Probing all available submodules */ for (i = 0; i < ARRAY_SIZE(submodule_table); i++) { num_inits = submodule_table[i].num_component; + CAM_DBG(CAM_UTIL, "Number of %s components: %u", + submodule_table[i].name, num_inits); for (j = 0; j < num_inits; j++) { rc = submodule_table[i].component[j].init(); if (rc) { @@ -233,13 +237,13 @@ static int camera_init(void) submodule_table[i].name, submodule_table[i].component[j].init, rc); - camera_error_exit(i, j); + __camera_exit(i, j); goto end_init; } } } - CAM_INFO(CAM_UTIL, "Camera driver initialized"); + CAM_INFO(CAM_UTIL, "Spectra camera driver initialized!"); end_init: return rc; @@ -247,19 +251,13 @@ end_init: static void camera_exit(void) { - uint i, j, num_exits; + __camera_exit(ARRAY_SIZE(submodule_table), 0); - for (i = ARRAY_SIZE(submodule_table) - 1; i >= 0; i--) { - num_exits = submodule_table[i].num_component; - for (j = num_exits - 1; j >= 0; j--) - submodule_table[i].component[j].exit(); - } - - CAM_INFO(CAM_UTIL, "Camera driver exited!"); + CAM_INFO(CAM_UTIL, "Spectra camera driver exited!"); } module_init(camera_init); module_exit(camera_exit); -MODULE_DESCRIPTION("Spectra_Camera Driver"); +MODULE_DESCRIPTION("Spectra camera driver"); MODULE_LICENSE("GPL v2"); From 12d9311463b924873b95131bb32ec0fa99cb2ba4 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 20 Dec 2019 14:29:58 +0530 Subject: [PATCH 202/790] msm: camera: ope: Add support to OPE driver OPE is camera offline engine, support is added to enable camera OPE hardware. CRs-Fixed: 2594541 Change-Id: I65c69f5763d05abf265b645b09c95c55fb290182 Signed-off-by: Suresh Vankadara Signed-off-by: Ravikishore Pampana Signed-off-by: Trishansh Bhardwaj --- drivers/Makefile | 11 + drivers/cam_ope/cam_ope_context.c | 273 ++ drivers/cam_ope/cam_ope_context.h | 44 + drivers/cam_ope/cam_ope_subdev.c | 277 ++ drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 2248 +++++++++++++++++ drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 399 +++ .../cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h | 16 + .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 693 +++++ .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h | 139 + .../ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c | 785 ++++++ .../ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h | 137 + drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 1781 +++++++++++++ drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h | 99 + drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 253 ++ .../cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h | 174 ++ drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 399 +++ .../cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h | 532 ++++ drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c | 136 + drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h | 33 + .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 246 ++ .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h | 41 + drivers/cam_utils/cam_debug_util.c | 7 +- drivers/cam_utils/cam_debug_util.h | 4 +- drivers/camera_main.c | 16 +- 24 files changed, 8740 insertions(+), 3 deletions(-) create mode 100644 drivers/cam_ope/cam_ope_context.c create mode 100644 drivers/cam_ope/cam_ope_context.h create mode 100644 drivers/cam_ope/cam_ope_subdev.c create mode 100644 drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c create mode 100644 drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h create mode 100644 drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c create mode 100644 drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h diff --git a/drivers/Makefile b/drivers/Makefile index ad2a01f4a08f..552ab12e52da 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -172,6 +172,17 @@ camera-$(CONFIG_SPECTRA_CUSTOM) += \ cam_cust/cam_custom_dev.o \ cam_cust/cam_custom_context.o +camera-$(CONFIG_SPECTRA_OPE) += \ + cam_ope/cam_ope_subdev.o \ + cam_ope/cam_ope_context.o \ + cam_ope/ope_hw_mgr/cam_ope_hw_mgr.o \ + cam_ope/ope_hw_mgr/ope_hw/ope_dev.o \ + cam_ope/ope_hw_mgr/ope_hw/ope_soc.o \ + cam_ope/ope_hw_mgr/ope_hw/ope_core.o \ + cam_ope/ope_hw_mgr/ope_hw/top/ope_top.o \ + cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.o\ + cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.o + camera-y += camera_main.o obj-$(CONFIG_SPECTRA_CAMERA) += camera.o diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c new file mode 100644 index 000000000000..83dd07be9de8 --- /dev/null +++ b/drivers/cam_ope/cam_ope_context.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cam_sync_api.h" +#include "cam_node.h" +#include "cam_context.h" +#include "cam_context_utils.h" +#include "cam_ope_context.h" +#include "cam_req_mgr_util.h" +#include "cam_mem_mgr.h" +#include "cam_trace.h" +#include "cam_debug_util.h" +#include "cam_packet_util.h" + +static const char ope_dev_name[] = "cam-ope"; + +static int cam_ope_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + int rc = 0; + bool b_mem_found = false; + + if (!ctx) { + CAM_ERR(CAM_OPE, "Invalid ctx"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) { + CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d", + ctx->ctx_id, ctx->state); + goto end; + } + + CAM_INFO(CAM_OPE, "iommu fault for ope ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_OPE, "req_id : %lld", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &b_mem_found); + if (rc) + CAM_ERR(CAM_OPE, "Failed to dump pf info"); + + if (b_mem_found) + CAM_ERR(CAM_OPE, "Found page fault in req %lld %d", + req->request_id, rc); + } + +end: + mutex_unlock(&ctx->ctx_mutex); + return rc; +} + +static int __cam_ope_acquire_dev_in_available(struct cam_context *ctx, + struct cam_acquire_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_acquire_dev_to_hw(ctx, cmd); + if (!rc) { + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("OPE", ctx); + } + + return rc; +} + +static int __cam_ope_release_dev_in_acquired(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_release_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_OPE, "Unable to release device"); + + ctx->state = CAM_CTX_AVAILABLE; + trace_cam_context_state("OPE", ctx); + return rc; +} + +static int __cam_ope_start_dev_in_acquired(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_start_dev_to_hw(ctx, cmd); + if (!rc) { + ctx->state = CAM_CTX_READY; + trace_cam_context_state("OPE", ctx); + } + + return rc; +} + +static int __cam_ope_flush_dev_in_ready(struct cam_context *ctx, + struct cam_flush_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_flush_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_OPE, "Failed to flush device"); + + return rc; +} + +static int __cam_ope_config_dev_in_ready(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc; + size_t len; + uintptr_t packet_addr; + + rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, + &packet_addr, &len); + if (rc) { + CAM_ERR(CAM_OPE, "[%s][%d] Can not get packet address", + ctx->dev_name, ctx->ctx_id); + rc = -EINVAL; + return rc; + } + + rc = cam_context_prepare_dev_to_hw(ctx, cmd); + + if (rc) + CAM_ERR(CAM_OPE, "Failed to prepare device"); + + return rc; +} + +static int __cam_ope_stop_dev_in_ready(struct cam_context *ctx, + struct cam_start_stop_dev_cmd *cmd) +{ + int rc; + + rc = cam_context_stop_dev_to_hw(ctx); + if (rc) + CAM_ERR(CAM_OPE, "Failed to stop device"); + + ctx->state = CAM_CTX_ACQUIRED; + trace_cam_context_state("OPE", ctx); + return rc; +} + +static int __cam_ope_release_dev_in_ready(struct cam_context *ctx, + struct cam_release_dev_cmd *cmd) +{ + int rc; + + rc = __cam_ope_stop_dev_in_ready(ctx, NULL); + if (rc) + CAM_ERR(CAM_OPE, "Failed to stop device"); + + rc = __cam_ope_release_dev_in_acquired(ctx, cmd); + if (rc) + CAM_ERR(CAM_OPE, "Failed to release device"); + + return rc; +} + +static int __cam_ope_handle_buf_done_in_ready(void *ctx, + uint32_t evt_id, void *done) +{ + return cam_context_buf_done_from_hw(ctx, done, evt_id); +} + +static struct cam_ctx_ops + cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = { + /* Uninit */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Available */ + { + .ioctl_ops = { + .acquire_dev = __cam_ope_acquire_dev_in_available, + }, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* Acquired */ + { + .ioctl_ops = { + .release_dev = __cam_ope_release_dev_in_acquired, + .start_dev = __cam_ope_start_dev_in_acquired, + .config_dev = __cam_ope_config_dev_in_ready, + .flush_dev = __cam_ope_flush_dev_in_ready, + }, + .crm_ops = {}, + .irq_ops = __cam_ope_handle_buf_done_in_ready, + .pagefault_ops = cam_ope_context_dump_active_request, + }, + /* Ready */ + { + .ioctl_ops = { + .stop_dev = __cam_ope_stop_dev_in_ready, + .release_dev = __cam_ope_release_dev_in_ready, + .config_dev = __cam_ope_config_dev_in_ready, + .flush_dev = __cam_ope_flush_dev_in_ready, + }, + .crm_ops = {}, + .irq_ops = __cam_ope_handle_buf_done_in_ready, + .pagefault_ops = cam_ope_context_dump_active_request, + }, + /* Activated */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + .pagefault_ops = cam_ope_context_dump_active_request, + }, +}; + +int cam_ope_context_init(struct cam_ope_context *ctx, + struct cam_hw_mgr_intf *hw_intf, uint32_t ctx_id) +{ + int rc; + + if ((!ctx) || (!ctx->base) || (!hw_intf)) { + CAM_ERR(CAM_OPE, "Invalid params: %pK %pK", ctx, hw_intf); + rc = -EINVAL; + goto err; + } + + rc = cam_context_init(ctx->base, ope_dev_name, CAM_OPE, ctx_id, + NULL, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + if (rc) { + CAM_ERR(CAM_OPE, "Camera Context Base init failed"); + goto err; + } + + ctx->base->state_machine = cam_ope_ctx_state_machine; + ctx->base->ctx_priv = ctx; + ctx->ctxt_to_hw_map = NULL; + +err: + return rc; +} + +int cam_ope_context_deinit(struct cam_ope_context *ctx) +{ + if ((!ctx) || (!ctx->base)) { + CAM_ERR(CAM_OPE, "Invalid params: %pK", ctx); + return -EINVAL; + } + + cam_context_deinit(ctx->base); + memset(ctx, 0, sizeof(*ctx)); + + return 0; +} + + diff --git a/drivers/cam_ope/cam_ope_context.h b/drivers/cam_ope/cam_ope_context.h new file mode 100644 index 000000000000..9d0779ce2b3d --- /dev/null +++ b/drivers/cam_ope/cam_ope_context.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_OPE_CONTEXT_H_ +#define _CAM_OPE_CONTEXT_H_ + +#include "cam_context.h" + +#define OPE_CTX_MAX 32 + +/** + * struct cam_ope_context - ope context + * @base: ope context object + * @state_machine: state machine for OPE context + * @req_base: common request structure + * @state: ope context state + * @ctxt_to_hw_map: context to FW handle mapping + */ +struct cam_ope_context { + struct cam_context *base; + struct cam_ctx_ops *state_machine; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + uint32_t state; + void *ctxt_to_hw_map; +}; + +/** + * cam_ope_context_init() - OPE context init + * @ctx: Pointer to context + * @hw_intf: Pointer to OPE hardware interface + * @ctx_id: ID for this context + */ +int cam_ope_context_init(struct cam_ope_context *ctx, + struct cam_hw_mgr_intf *hw_intf, uint32_t ctx_id); + +/** + * cam_ope_context_deinit() - OPE context deinit + * @ctx: Pointer to context + */ +int cam_ope_context_deinit(struct cam_ope_context *ctx); + +#endif /* _CAM_OPE_CONTEXT_H_ */ diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c new file mode 100644 index 000000000000..18ed0518992a --- /dev/null +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_req_mgr_dev.h" +#include "cam_subdev.h" +#include "cam_node.h" +#include "cam_context.h" +#include "cam_ope_context.h" +#include "cam_ope_hw_mgr_intf.h" +#include "cam_hw_mgr_intf.h" +#include "cam_debug_util.h" +#include "cam_smmu_api.h" + +#define OPE_DEV_NAME "cam-ope" + +struct cam_ope_subdev { + struct cam_subdev sd; + struct cam_node *node; + struct cam_context ctx[OPE_CTX_MAX]; + struct cam_ope_context ctx_ope[OPE_CTX_MAX]; + struct mutex ope_lock; + int32_t open_cnt; + int32_t reserved; +}; + +static struct cam_ope_subdev g_ope_dev; + +static void cam_ope_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_OPE, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + +static int cam_ope_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_hw_mgr_intf *hw_mgr_intf = NULL; + struct cam_node *node = v4l2_get_subdevdata(sd); + int rc = 0; + + mutex_lock(&g_ope_dev.ope_lock); + if (g_ope_dev.open_cnt >= 1) { + CAM_ERR(CAM_OPE, "OPE subdev is already opened"); + rc = -EALREADY; + goto end; + } + + if (!node) { + CAM_ERR(CAM_OPE, "Invalid args"); + rc = -EINVAL; + goto end; + } + + hw_mgr_intf = &node->hw_mgr_intf; + rc = hw_mgr_intf->hw_open(hw_mgr_intf->hw_mgr_priv, NULL); + if (rc < 0) { + CAM_ERR(CAM_OPE, "OPE HW open failed: %d", rc); + goto end; + } + g_ope_dev.open_cnt++; + CAM_DBG(CAM_OPE, "OPE HW open success: %d", rc); +end: + mutex_unlock(&g_ope_dev.ope_lock); + return rc; +} + +static int cam_ope_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = 0; + struct cam_hw_mgr_intf *hw_mgr_intf = NULL; + struct cam_node *node = v4l2_get_subdevdata(sd); + + mutex_lock(&g_ope_dev.ope_lock); + if (g_ope_dev.open_cnt <= 0) { + CAM_DBG(CAM_OPE, "OPE subdev is already closed"); + rc = -EINVAL; + goto end; + } + g_ope_dev.open_cnt--; + if (!node) { + CAM_ERR(CAM_OPE, "Invalid args"); + rc = -EINVAL; + goto end; + } + + hw_mgr_intf = &node->hw_mgr_intf; + if (!hw_mgr_intf) { + CAM_ERR(CAM_OPE, "hw_mgr_intf is not initialized"); + rc = -EINVAL; + goto end; + } + + rc = cam_node_shutdown(node); + if (rc < 0) { + CAM_ERR(CAM_OPE, "HW close failed"); + goto end; + } + CAM_DBG(CAM_OPE, "OPE HW close success: %d", rc); + +end: + mutex_unlock(&g_ope_dev.ope_lock); + return rc; +} + +const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { + .open = cam_ope_subdev_open, + .close = cam_ope_subdev_close, +}; + +static int cam_ope_subdev_probe(struct platform_device *pdev) +{ + int rc = 0, i = 0; + struct cam_node *node; + struct cam_hw_mgr_intf *hw_mgr_intf; + int iommu_hdl = -1; + + CAM_DBG(CAM_OPE, "OPE subdev probe start"); + if (!pdev) { + CAM_ERR(CAM_OPE, "pdev is NULL"); + return -EINVAL; + } + + g_ope_dev.sd.pdev = pdev; + g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops; + rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME, + CAM_OPE_DEVICE_TYPE); + if (rc) { + CAM_ERR(CAM_OPE, "OPE cam_subdev_probe failed:%d", rc); + return rc; + } + + node = (struct cam_node *) g_ope_dev.sd.token; + + hw_mgr_intf = kzalloc(sizeof(*hw_mgr_intf), GFP_KERNEL); + if (!hw_mgr_intf) { + rc = -EINVAL; + goto hw_alloc_fail; + } + + rc = cam_ope_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf, + &iommu_hdl); + if (rc) { + CAM_ERR(CAM_OPE, "OPE HW manager init failed: %d", rc); + goto hw_init_fail; + } + + for (i = 0; i < OPE_CTX_MAX; i++) { + g_ope_dev.ctx_ope[i].base = &g_ope_dev.ctx[i]; + rc = cam_ope_context_init(&g_ope_dev.ctx_ope[i], + hw_mgr_intf, i); + if (rc) { + CAM_ERR(CAM_OPE, "OPE context init failed"); + goto ctx_fail; + } + } + + rc = cam_node_init(node, hw_mgr_intf, g_ope_dev.ctx, + OPE_CTX_MAX, OPE_DEV_NAME); + if (rc) { + CAM_ERR(CAM_OPE, "OPE node init failed"); + goto ctx_fail; + } + + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_ope_dev_iommu_fault_handler, node); + + g_ope_dev.open_cnt = 0; + mutex_init(&g_ope_dev.ope_lock); + + CAM_DBG(CAM_OPE, "OPE subdev probe complete"); + + return rc; + +ctx_fail: + for (--i; i >= 0; i--) + cam_ope_context_deinit(&g_ope_dev.ctx_ope[i]); +hw_init_fail: + kfree(hw_mgr_intf); +hw_alloc_fail: + cam_subdev_remove(&g_ope_dev.sd); + return rc; +} + +static int cam_ope_subdev_remove(struct platform_device *pdev) +{ + int i; + struct v4l2_subdev *sd; + struct cam_subdev *subdev; + + if (!pdev) { + CAM_ERR(CAM_OPE, "pdev is NULL"); + return -ENODEV; + } + + sd = platform_get_drvdata(pdev); + if (!sd) { + CAM_ERR(CAM_OPE, "V4l2 subdev is NULL"); + return -ENODEV; + } + + subdev = v4l2_get_subdevdata(sd); + if (!subdev) { + CAM_ERR(CAM_OPE, "cam subdev is NULL"); + return -ENODEV; + } + + for (i = 0; i < OPE_CTX_MAX; i++) + cam_ope_context_deinit(&g_ope_dev.ctx_ope[i]); + cam_node_deinit(g_ope_dev.node); + cam_subdev_remove(&g_ope_dev.sd); + mutex_destroy(&g_ope_dev.ope_lock); + + return 0; +} + +static const struct of_device_id cam_ope_dt_match[] = { + {.compatible = "qcom,cam-ope"}, + {} +}; + + +static struct platform_driver cam_ope_driver = { + .probe = cam_ope_subdev_probe, + .remove = cam_ope_subdev_remove, + .driver = { + .name = "cam_ope", + .of_match_table = cam_ope_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_ope_subdev_init_module(void) +{ + return platform_driver_register(&cam_ope_driver); +} + +void cam_ope_subdev_exit_module(void) +{ + platform_driver_unregister(&cam_ope_driver); +} + +MODULE_DESCRIPTION("MSM OPE driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c new file mode 100644 index 000000000000..bb73190b1438 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -0,0 +1,2248 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cam_sync_api.h" +#include "cam_packet_util.h" +#include "cam_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_ope_hw_mgr_intf.h" +#include "cam_ope_hw_mgr.h" +#include "ope_hw.h" +#include "cam_smmu_api.h" +#include "cam_mem_mgr.h" +#include "cam_req_mgr_workq.h" +#include "cam_mem_mgr.h" +#include "cam_debug_util.h" +#include "cam_soc_util.h" +#include "cam_trace.h" +#include "cam_cpas_api.h" +#include "cam_common_util.h" +#include "cam_cdm_intf_api.h" +#include "cam_cdm_util.h" +#include "cam_cdm.h" +#include "ope_dev_intf.h" + +static struct cam_ope_hw_mgr *ope_hw_mgr; + +static int cam_ope_mgr_get_rsc_idx(struct cam_ope_ctx *ctx_data, + struct ope_io_buf_info *in_io_buf) +{ + int k = 0; + int rsc_idx = -EINVAL; + + if (in_io_buf->direction == CAM_BUF_INPUT) { + for (k = 0; k < OPE_IN_RES_MAX; k++) { + if (ctx_data->ope_acquire.in_res[k].res_id == + in_io_buf->resource_type) + break; + } + if (k == OPE_IN_RES_MAX) { + CAM_ERR(CAM_OPE, "Invalid res_id %d", + in_io_buf->resource_type); + goto end; + } + rsc_idx = k; + } else if (in_io_buf->direction == CAM_BUF_OUTPUT) { + for (k = 0; k < OPE_OUT_RES_MAX; k++) { + if (ctx_data->ope_acquire.out_res[k].res_id == + in_io_buf->resource_type) + break; + } + if (k == OPE_OUT_RES_MAX) { + CAM_ERR(CAM_OPE, "Invalid res_id %d", + in_io_buf->resource_type); + goto end; + } + rsc_idx = k; + } + +end: + return rsc_idx; +} + +static int cam_ope_mgr_process_cmd(void *priv, void *data) +{ + int rc; + struct ope_cmd_work_data *task_data = NULL; + struct cam_ope_ctx *ctx_data; + struct cam_cdm_bl_request *cdm_cmd; + + if (!data || !priv) { + CAM_ERR(CAM_OPE, "Invalid params%pK %pK", data, priv); + return -EINVAL; + } + + ctx_data = priv; + task_data = (struct ope_cmd_work_data *)data; + cdm_cmd = task_data->data; + + CAM_DBG(CAM_OPE, "cam_cdm_submit_bls: handle = %u", + ctx_data->ope_cdm.cdm_handle); + rc = cam_cdm_submit_bls(ctx_data->ope_cdm.cdm_handle, cdm_cmd); + + if (!rc) + ctx_data->req_cnt++; + else + CAM_ERR(CAM_OPE, "submit failed for %lld", cdm_cmd->cookie); + + return rc; +} + +static int cam_ope_mgr_reset_hw(void) +{ + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; + int i, rc = 0; + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RESET, + NULL, 0); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Reset failed: %d", rc); + return rc; + } + } + + return rc; +} + +static int cam_ope_req_timer_modify(struct cam_ope_ctx *ctx_data, + int32_t expires) +{ + if (ctx_data->req_watch_dog) { + CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + crm_timer_modify(ctx_data->req_watch_dog, expires); + } + return 0; +} + +static int cam_ope_req_timer_stop(struct cam_ope_ctx *ctx_data) +{ + if (ctx_data->req_watch_dog) { + CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + crm_timer_exit(&ctx_data->req_watch_dog); + ctx_data->req_watch_dog = NULL; + } + return 0; +} + +static int cam_ope_req_timer_reset(struct cam_ope_ctx *ctx_data) +{ + if (ctx_data && ctx_data->req_watch_dog) + crm_timer_reset(ctx_data->req_watch_dog); + + return 0; +} + + +static int cam_ope_mgr_reapply_config(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_ope_request *ope_req) +{ + int rc = 0; + uint64_t request_id = 0; + struct crm_workq_task *task; + struct ope_cmd_work_data *task_data; + + request_id = ope_req->request_id; + CAM_DBG(CAM_OPE, "reapply req_id = %lld", request_id); + + task = cam_req_mgr_workq_get_task(ope_hw_mgr->cmd_work); + if (!task) { + CAM_ERR(CAM_OPE, "no empty task"); + return -ENOMEM; + } + + task_data = (struct ope_cmd_work_data *)task->payload; + task_data->data = (void *)ope_req->cdm_cmd; + task_data->req_id = request_id; + task_data->type = OPE_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_ope_mgr_process_cmd; + rc = cam_req_mgr_workq_enqueue_task(task, ctx_data, + CRM_TASK_PRIORITY_0); + + return rc; +} + +static bool cam_ope_is_pending_request(struct cam_ope_ctx *ctx_data) +{ + return !bitmap_empty(ctx_data->bitmap, CAM_CTX_REQ_MAX); +} + +static int32_t cam_ope_process_request_timer(void *priv, void *data) +{ + struct ope_clk_work_data *task_data = (struct ope_clk_work_data *)data; + struct cam_ope_ctx *ctx_data = (struct cam_ope_ctx *)task_data->data; + + if (cam_ope_is_pending_request(ctx_data)) { + CAM_DBG(CAM_OPE, "pending requests means, issue is with HW"); + cam_cdm_handle_error(ctx_data->ope_cdm.cdm_handle); + cam_ope_req_timer_reset(ctx_data); + } else { + cam_ope_req_timer_modify(ctx_data, ~0); + } + return 0; +} + +static void cam_ope_req_timer_cb(struct timer_list *timer_data) +{ + unsigned long flags; + struct crm_workq_task *task; + struct ope_clk_work_data *task_data; + struct cam_req_mgr_timer *timer = + container_of(timer_data, struct cam_req_mgr_timer, sys_timer); + + spin_lock_irqsave(&ope_hw_mgr->hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task(ope_hw_mgr->timer_work); + if (!task) { + CAM_ERR(CAM_OPE, "no empty task"); + spin_unlock_irqrestore(&ope_hw_mgr->hw_mgr_lock, flags); + return; + } + + task_data = (struct ope_clk_work_data *)task->payload; + task_data->data = timer->parent; + task_data->type = OPE_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_ope_process_request_timer; + cam_req_mgr_workq_enqueue_task(task, ope_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&ope_hw_mgr->hw_mgr_lock, flags); +} + +static int cam_ope_start_req_timer(struct cam_ope_ctx *ctx_data) +{ + int rc = 0; + + rc = crm_timer_init(&ctx_data->req_watch_dog, + 200, ctx_data, &cam_ope_req_timer_cb); + if (rc) + CAM_ERR(CAM_ICP, "Failed to start timer"); + + return rc; +} + +static int cam_get_valid_ctx_id(void) +{ + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; + int i; + + + for (i = 0; i < OPE_CTX_MAX; i++) { + if (hw_mgr->ctx[i].ctx_state == OPE_CTX_STATE_ACQUIRED) + break; + } + + return i; +} + + +static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, + enum cam_cdm_cb_status status, uint64_t cookie) +{ + int rc = 0; + struct cam_ope_ctx *ctx; + struct cam_ope_request *ope_req; + struct cam_hw_done_event_data buf_data; + bool flag = false; + + if (!userdata) { + CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); + return; + } + + CAM_DBG(CAM_FD, "CDM hdl=%x, udata=%pK, status=%d, cookie=%llu", + handle, userdata, status, cookie); + + ctx = userdata; + ope_req = ctx->req_list[cookie]; + + mutex_lock(&ctx->ctx_mutex); + if (ctx->ctx_state != OPE_CTX_STATE_ACQUIRED) { + CAM_DBG(CAM_OPE, "ctx %u is in %d state", + ctx->ctx_id, ctx->ctx_state); + mutex_unlock(&ctx->ctx_mutex); + return; + } + + if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { + CAM_DBG(CAM_OPE, + "hdl=%x, udata=%pK, status=%d, cookie=%d req_id=%llu ctx_id=%d", + handle, userdata, status, cookie, + ope_req->request_id, ctx->ctx_id); + cam_ope_req_timer_reset(ctx); + } else if (status == CAM_CDM_CB_STATUS_HW_RESUBMIT) { + CAM_INFO(CAM_OPE, "After reset of CDM and OPE, reapply req"); + rc = cam_ope_mgr_reapply_config(ope_hw_mgr, ctx, ope_req); + if (!rc) + goto end; + } else { + CAM_ERR(CAM_OPE, + "CDM hdl=%x, udata=%pK, status=%d, cookie=%d req_id = %llu", + handle, userdata, status, cookie, ope_req->request_id); + CAM_ERR(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", + ope_req->request_id); + rc = cam_ope_mgr_reset_hw(); + flag = true; + } + + ctx->req_cnt--; + + buf_data.request_id = ope_req->request_id; + ope_req->request_id = 0; + kzfree(ctx->req_list[cookie]->cdm_cmd); + ctx->req_list[cookie]->cdm_cmd = NULL; + kzfree(ctx->req_list[cookie]); + ctx->req_list[cookie] = NULL; + clear_bit(cookie, ctx->bitmap); + ctx->ctxt_event_cb(ctx->context_priv, flag, &buf_data); + +end: + mutex_unlock(&ctx->ctx_mutex); +} + +static int32_t cam_ope_mgr_process_msg(void *priv, void *data) +{ + struct ope_msg_work_data *task_data; + struct cam_ope_hw_mgr *hw_mgr; + struct cam_ope_ctx *ctx; + uint32_t irq_status; + int32_t ctx_id; + int rc = 0, i; + + if (!data || !priv) { + CAM_ERR(CAM_OPE, "Invalid data"); + return -EINVAL; + } + + task_data = data; + hw_mgr = priv; + irq_status = task_data->irq_status; + ctx_id = cam_get_valid_ctx_id(); + if (ctx_id < 0) { + CAM_ERR(CAM_OPE, "No valid context to handle error"); + return ctx_id; + } + + ctx = &hw_mgr->ctx[ctx_id]; + + /* Indicate about this error to CDM and reset OPE*/ + rc = cam_cdm_handle_error(ctx->ope_cdm.cdm_handle); + + for (i = 0; i < hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RESET, + NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "OPE Dev acquire failed: %d", rc); + } + + return rc; +} + +int32_t cam_ope_hw_mgr_cb(uint32_t irq_status, void *data) +{ + int32_t rc = 0; + unsigned long flags; + struct cam_ope_hw_mgr *hw_mgr = data; + struct crm_workq_task *task; + struct ope_msg_work_data *task_data; + + if (!data) { + CAM_ERR(CAM_OPE, "irq cb data is NULL"); + return rc; + } + + spin_lock_irqsave(&hw_mgr->hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work); + if (!task) { + CAM_ERR(CAM_OPE, "no empty task"); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags); + return -ENOMEM; + } + + task_data = (struct ope_msg_work_data *)task->payload; + task_data->data = hw_mgr; + task_data->irq_status = irq_status; + task_data->type = OPE_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_ope_mgr_process_msg; + rc = cam_req_mgr_workq_enqueue_task(task, ope_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags); + + return rc; +} + +static int cam_ope_mgr_create_kmd_buf(struct cam_ope_hw_mgr *hw_mgr, + struct cam_packet *packet, + struct cam_hw_prepare_update_args *prepare_args, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uintptr_t ope_cmd_buf_addr) +{ + int i, rc = 0; + struct cam_ope_dev_prepare_req prepare_req; + + prepare_req.ctx_data = ctx_data; + prepare_req.hw_mgr = hw_mgr; + prepare_req.packet = packet; + prepare_req.prepare_args = prepare_args; + prepare_req.req_idx = req_idx; + prepare_req.kmd_buf_offset = 0; + prepare_req.frame_process = + (struct ope_frame_process *)ope_cmd_buf_addr; + + for (i = 0; i < ope_hw_mgr->num_ope; i++) + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_PREPARE, &prepare_req, sizeof(prepare_req)); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Dev prepare failed: %d", rc); + goto end; + } + +end: + return rc; +} + +static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, + struct cam_packet *packet, + struct cam_hw_prepare_update_args *prep_args, + struct cam_ope_ctx *ctx_data, uint32_t req_idx) +{ + + int i, j = 0, k = 0, l, rc = 0; + struct ope_io_buf *io_buf; + int32_t sync_in_obj[CAM_MAX_IN_RES]; + int32_t merged_sync_in_obj; + struct cam_ope_request *ope_request; + + ope_request = ctx_data->req_list[req_idx]; + prep_args->num_out_map_entries = 0; + prep_args->num_in_map_entries = 0; + + ope_request = ctx_data->req_list[req_idx]; + CAM_DBG(CAM_OPE, "E: req_idx = %u %x", req_idx, packet); + + for (i = 0; i < ope_request->num_batch; i++) { + for (l = 0; l < ope_request->num_io_bufs[i]; l++) { + io_buf = &ope_request->io_buf[i][l]; + if (io_buf->direction == CAM_BUF_INPUT) { + if (io_buf->fence != -1) { + sync_in_obj[j++] = io_buf->fence; + prep_args->num_in_map_entries++; + } else { + CAM_ERR(CAM_OPE, "Invalid fence %d %d", + io_buf->resource_type, + ope_request->request_id); + } + } else { + if (io_buf->fence != -1) { + prep_args->out_map_entries[k].sync_id = + io_buf->fence; + k++; + prep_args->num_out_map_entries++; + } else { + CAM_ERR(CAM_OPE, "Invalid fence %d %d", + io_buf->resource_type, + ope_request->request_id); + } + } + CAM_DBG(CAM_REQ, + "ctx_id: %u req_id: %llu dir[%d] %u, fence: %d", + ctx_data->ctx_id, packet->header.request_id, i, + io_buf->direction, io_buf->fence); + CAM_DBG(CAM_REQ, "rsc_type = %u fmt = %d", + io_buf->resource_type, + io_buf->format); + } + } + + if (prep_args->num_in_map_entries > 1) + prep_args->num_in_map_entries = + cam_common_util_remove_duplicate_arr( + sync_in_obj, prep_args->num_in_map_entries); + + if (prep_args->num_in_map_entries > 1) { + rc = cam_sync_merge(&sync_in_obj[0], + prep_args->num_in_map_entries, &merged_sync_in_obj); + if (rc) { + prep_args->num_out_map_entries = 0; + prep_args->num_in_map_entries = 0; + return rc; + } + + ope_request->in_resource = merged_sync_in_obj; + + prep_args->in_map_entries[0].sync_id = merged_sync_in_obj; + prep_args->num_in_map_entries = 1; + CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d", + ctx_data->ctx_id, packet->header.request_id, + merged_sync_in_obj); + } else if (prep_args->num_in_map_entries == 1) { + prep_args->in_map_entries[0].sync_id = sync_in_obj[0]; + prep_args->num_in_map_entries = 1; + ope_request->in_resource = 0; + CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]); + } else { + CAM_DBG(CAM_OPE, "No input fences"); + prep_args->num_in_map_entries = 0; + ope_request->in_resource = 0; + rc = -EINVAL; + } + return rc; +} + +static void cam_ope_mgr_print_stripe_info(uint32_t batch, + uint32_t io_buf, uint32_t plane, uint32_t stripe, + struct ope_stripe_io *stripe_info, uint64_t iova_addr) +{ + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d: E", + batch, io_buf, plane, stripe); + CAM_DBG(CAM_OPE, "width: %d s_w: %u s_h: %u s_s: %u", + stripe_info->width, stripe_info->width, + stripe_info->height, stripe_info->stride); + CAM_DBG(CAM_OPE, "s_xinit = %u iova = %x s_loc = %u", + stripe_info->s_location, stripe_info->x_init, + iova_addr); + CAM_DBG(CAM_OPE, "s_off = %u s_format = %u s_len = %u", + stripe_info->offset, stripe_info->format, + stripe_info->len); + CAM_DBG(CAM_OPE, "s_align = %u s_pack = %u s_unpack = %u", + stripe_info->alignment, stripe_info->pack_format, + stripe_info->unpack_format); + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d: E", + batch, io_buf, plane, stripe); +} + +static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, + struct cam_packet *packet, struct cam_ope_ctx *ctx_data, + uintptr_t frame_process_addr, size_t length, uint32_t req_idx) +{ + int rc = 0; + int i, j, k, l; + uint64_t iova_addr; + size_t len; + struct ope_frame_process *in_frame_process; + struct ope_frame_set *in_frame_set; + struct ope_io_buf_info *in_io_buf; + struct ope_stripe_info *in_stripe_info; + struct cam_ope_request *ope_request; + struct ope_io_buf *io_buf; + struct ope_stripe_io *stripe_info; + uint32_t alignment; + uint32_t rsc_idx; + uint32_t pack_format; + uint32_t unpack_format; + struct ope_in_res_info *in_res; + struct ope_out_res_info *out_res; + + in_frame_process = (struct ope_frame_process *)frame_process_addr; + + ope_request = ctx_data->req_list[req_idx]; + ope_request->num_batch = in_frame_process->batch_size; + + for (i = 0; i < in_frame_process->batch_size; i++) { + in_frame_set = &in_frame_process->frame_set[i]; + for (j = 0; j < in_frame_set->num_io_bufs; j++) { + in_io_buf = &in_frame_set->io_buf[j]; + CAM_DBG(CAM_OPE, "i:%d j:%d dir: %x rsc: %u plane: %d", + i, j, in_io_buf->direction, + in_io_buf->resource_type, + in_io_buf->num_planes); + for (k = 0; k < in_io_buf->num_planes; k++) { + CAM_DBG(CAM_OPE, "i:%d j:%d k:%d numstripe: %d", + i, j, k, in_io_buf->num_stripes[k]); + CAM_DBG(CAM_OPE, "m_hdl: %d len: %d", + in_io_buf->mem_handle[k], + in_io_buf->length[k]); + for (l = 0; l < in_io_buf->num_stripes[k]; + l++) { + in_stripe_info = + &in_io_buf->stripe_info[k][l]; + CAM_DBG(CAM_OPE, "i:%d j:%d k:%d l:%d", + i, j, k, l); + CAM_DBG(CAM_OPE, "%d s_loc:%d w:%d", + in_stripe_info->x_init, + in_stripe_info->stripe_location, + in_stripe_info->width); + CAM_DBG(CAM_OPE, "s_off: %d d_bus: %d", + in_stripe_info->offset, + in_stripe_info->disable_bus); + } + } + } + } + + for (i = 0; i < ope_request->num_batch; i++) { + in_frame_set = &in_frame_process->frame_set[i]; + ope_request->num_io_bufs[i] = in_frame_set->num_io_bufs; + if (in_frame_set->num_io_bufs > OPE_MAX_IO_BUFS) { + CAM_ERR(CAM_OPE, "Wrong number of io buffers: %d", + in_frame_set->num_io_bufs); + return -EINVAL; + } + + for (j = 0; j < in_frame_set->num_io_bufs; j++) { + in_io_buf = &in_frame_set->io_buf[j]; + io_buf = &ope_request->io_buf[i][j]; + if (in_io_buf->num_planes > OPE_MAX_PLANES) { + CAM_ERR(CAM_OPE, "wrong number of planes: %u", + in_io_buf->num_planes); + return -EINVAL; + } + + io_buf->num_planes = in_io_buf->num_planes; + io_buf->resource_type = in_io_buf->resource_type; + io_buf->direction = in_io_buf->direction; + io_buf->fence = in_io_buf->fence; + io_buf->format = in_io_buf->format; + + rc = cam_ope_mgr_get_rsc_idx(ctx_data, in_io_buf); + if (rc < 0) { + CAM_ERR(CAM_OPE, "Invalid rsc idx = %d", rc); + return rc; + } + rsc_idx = rc; + if (in_io_buf->direction == CAM_BUF_INPUT) { + in_res = + &ctx_data->ope_acquire.in_res[rsc_idx]; + alignment = in_res->alignment; + unpack_format = in_res->unpacker_format; + pack_format = 0; + } else if (in_io_buf->direction == CAM_BUF_OUTPUT) { + out_res = + &ctx_data->ope_acquire.out_res[rsc_idx]; + alignment = out_res->alignment; + pack_format = out_res->packer_format; + unpack_format = 0; + } + + CAM_DBG(CAM_OPE, "i:%d j:%d dir:%d rsc type:%d fmt:%d", + i, j, io_buf->direction, io_buf->resource_type, + io_buf->format); + for (k = 0; k < in_io_buf->num_planes; k++) { + io_buf->num_stripes[k] = + in_io_buf->num_stripes[k]; + rc = cam_mem_get_io_buf( + in_io_buf->mem_handle[k], + hw_mgr->iommu_hdl, &iova_addr, &len); + if (rc) { + CAM_ERR(CAM_OPE, "get buf failed: %d", + rc); + return -EINVAL; + } + if (len < in_io_buf->length[k]) { + CAM_ERR(CAM_OPE, "Invalid length"); + return -EINVAL; + } + iova_addr += in_io_buf->plane_offset[k]; + for (l = 0; l < in_io_buf->num_stripes[k]; + l++) { + in_stripe_info = + &in_io_buf->stripe_info[k][l]; + stripe_info = &io_buf->s_io[k][l]; + stripe_info->offset = + in_stripe_info->offset; + stripe_info->format = in_io_buf->format; + stripe_info->s_location = + in_stripe_info->stripe_location; + stripe_info->iova_addr = + iova_addr + stripe_info->offset; + stripe_info->width = + in_stripe_info->width; + stripe_info->height = + in_io_buf->height[k]; + stripe_info->stride = + in_io_buf->plane_stride[k]; + stripe_info->x_init = + in_stripe_info->x_init; + stripe_info->len = len; + stripe_info->alignment = alignment; + stripe_info->pack_format = pack_format; + stripe_info->unpack_format = + unpack_format; + cam_ope_mgr_print_stripe_info(i, j, + k, l, stripe_info, iova_addr); + } + } + } + } + + return rc; +} + +static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr, + struct cam_packet *packet, struct cam_ope_ctx *ctx_data, + uintptr_t frame_process_addr, size_t length, uint32_t req_idx) +{ + int rc = 0; + int i, j; + uint64_t iova_addr; + uint64_t iova_cdm_addr; + uintptr_t cpu_addr; + size_t len; + struct ope_frame_process *frame_process; + struct ope_cmd_buf_info *cmd_buf; + struct cam_ope_request *ope_request; + bool is_kmd_buf_valid = false; + + frame_process = (struct ope_frame_process *)frame_process_addr; + + if (frame_process->batch_size > OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch: %d", + frame_process->batch_size); + return -EINVAL; + } + + for (i = 0; i < frame_process->batch_size; i++) { + if (frame_process->num_cmd_bufs[i] > OPE_MAX_CMD_BUFS) { + CAM_ERR(CAM_OPE, "Invalid cmd bufs for batch %d %d", + i, frame_process->num_cmd_bufs[i]); + return -EINVAL; + } + } + + CAM_DBG(CAM_OPE, "cmd buf for req id = %lld b_size = %d", + packet->header.request_id, frame_process->batch_size); + + for (i = 0; i < frame_process->batch_size; i++) { + CAM_DBG(CAM_OPE, "batch: %d count %d", i, + frame_process->num_cmd_bufs[i]); + for (j = 0; j < frame_process->num_cmd_bufs[i]; j++) { + CAM_DBG(CAM_OPE, "batch: %d cmd_buf_idx :%d mem_hdl:%x", + i, j, frame_process->cmd_buf[i][j].mem_handle); + CAM_DBG(CAM_OPE, "size = %u scope = %d buf_type = %d", + frame_process->cmd_buf[i][j].size, + frame_process->cmd_buf[i][j].cmd_buf_scope, + frame_process->cmd_buf[i][j].type); + CAM_DBG(CAM_OPE, "usage = %d buffered = %d s_idx = %d", + frame_process->cmd_buf[i][j].cmd_buf_usage, + frame_process->cmd_buf[i][j].cmd_buf_buffered, + frame_process->cmd_buf[i][j].stripe_idx); + } + } + + ope_request = ctx_data->req_list[req_idx]; + ope_request->num_batch = frame_process->batch_size; + + for (i = 0; i < frame_process->batch_size; i++) { + for (j = 0; j < frame_process->num_cmd_bufs[i]; j++) { + cmd_buf = &frame_process->cmd_buf[i][j]; + + switch (cmd_buf->cmd_buf_scope) { + case OPE_CMD_BUF_SCOPE_FRAME: { + rc = cam_mem_get_io_buf(cmd_buf->mem_handle, + hw_mgr->iommu_hdl, &iova_addr, &len); + if (rc) { + CAM_ERR(CAM_OPE, "get cmd buffailed %x", + hw_mgr->iommu_hdl); + goto end; + } + iova_addr = iova_addr + cmd_buf->offset; + + rc = cam_mem_get_io_buf(cmd_buf->mem_handle, + hw_mgr->iommu_cdm_hdl, + &iova_cdm_addr, &len); + if (rc) { + CAM_ERR(CAM_OPE, "get cmd buffailed %x", + hw_mgr->iommu_hdl); + goto end; + } + iova_cdm_addr = iova_cdm_addr + cmd_buf->offset; + + rc = cam_mem_get_cpu_buf(cmd_buf->mem_handle, + &cpu_addr, &len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buffailed %x", + hw_mgr->iommu_hdl); + goto end; + } + cpu_addr = cpu_addr + + frame_process->cmd_buf[i][j].offset; + CAM_DBG(CAM_OPE, "Hdl %x size %d len %d off %d", + cmd_buf->mem_handle, cmd_buf->size, + cmd_buf->length, + cmd_buf->offset); + if (cmd_buf->cmd_buf_usage == OPE_CMD_BUF_KMD) { + ope_request->ope_kmd_buf.mem_handle = + cmd_buf->mem_handle; + ope_request->ope_kmd_buf.cpu_addr = + cpu_addr; + ope_request->ope_kmd_buf.iova_addr = + iova_addr; + ope_request->ope_kmd_buf.iova_cdm_addr = + iova_cdm_addr; + ope_request->ope_kmd_buf.len = len; + ope_request->ope_kmd_buf.size = + cmd_buf->size; + is_kmd_buf_valid = true; + CAM_DBG(CAM_OPE, "kbuf:%x io:%x cdm:%x", + ope_request->ope_kmd_buf.cpu_addr, + ope_request->ope_kmd_buf.iova_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + break; + } else if (cmd_buf->cmd_buf_usage == + OPE_CMD_BUF_DEBUG) { + ope_request->ope_debug_buf.cpu_addr = + cpu_addr; + ope_request->ope_debug_buf.iova_addr = + iova_addr; + ope_request->ope_debug_buf.len = + len; + ope_request->ope_debug_buf.size = + cmd_buf->size; + CAM_DBG(CAM_OPE, "dbg buf = %x", + ope_request->ope_debug_buf.cpu_addr); + break; + } + break; + } + case OPE_CMD_BUF_SCOPE_STRIPE: { + uint32_t num_cmd_bufs = 0; + uint32_t s_idx = 0; + + s_idx = cmd_buf->stripe_idx; + num_cmd_bufs = + ope_request->num_stripe_cmd_bufs[i][s_idx]; + + if (!num_cmd_bufs) + ope_request->num_stripes[i]++; + + ope_request->num_stripe_cmd_bufs[i][s_idx]++; + break; + } + + default: + break; + } + } + } + + + for (i = 0; i < frame_process->batch_size; i++) { + CAM_DBG(CAM_OPE, "num of stripes for batch %d is %d", + i, ope_request->num_stripes[i]); + for (j = 0; j < ope_request->num_stripes[i]; j++) { + CAM_DBG(CAM_OPE, "cmd buffers for stripe: %d:%d is %d", + i, j, ope_request->num_stripe_cmd_bufs[i][j]); + } + } + + if (!is_kmd_buf_valid) { + CAM_DBG(CAM_OPE, "Invalid kmd buffer"); + rc = -EINVAL; + } +end: + return rc; +} + +static int cam_ope_mgr_process_cmd_desc(struct cam_ope_hw_mgr *hw_mgr, + struct cam_packet *packet, struct cam_ope_ctx *ctx_data, + uintptr_t *ope_cmd_buf_addr, uint32_t req_idx) +{ + int rc = 0; + int i; + int num_cmd_buf = 0; + size_t len; + struct cam_cmd_buf_desc *cmd_desc = NULL; + uintptr_t cpu_addr = 0; + struct cam_ope_request *ope_request; + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + + *ope_cmd_buf_addr = 0; + for (i = 0; i < packet->num_cmd_buf; i++, num_cmd_buf++) { + if (cmd_desc[i].type != CAM_CMD_BUF_GENERIC || + cmd_desc[i].meta_data == OPE_CMD_META_GENERIC_BLOB) + continue; + + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &cpu_addr, &len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + num_cmd_buf = (num_cmd_buf > 0) ? + num_cmd_buf-- : 0; + goto end; + } + if ((len <= cmd_desc[i].offset) || + (cmd_desc[i].size < cmd_desc[i].length) || + ((len - cmd_desc[i].offset) < + cmd_desc[i].length)) { + CAM_ERR(CAM_OPE, "Invalid offset or length"); + goto end; + } + cpu_addr = cpu_addr + cmd_desc[i].offset; + *ope_cmd_buf_addr = cpu_addr; + } + + if (!cpu_addr) { + CAM_ERR(CAM_OPE, "invalid number of cmd buf"); + *ope_cmd_buf_addr = 0; + return -EINVAL; + } + + ope_request = ctx_data->req_list[req_idx]; + ope_request->request_id = packet->header.request_id; + ope_request->req_idx = req_idx; + + rc = cam_ope_mgr_process_cmd_buf_req(hw_mgr, packet, ctx_data, + cpu_addr, len, req_idx); + if (rc) { + CAM_ERR(CAM_OPE, "Process OPE cmd request is failed: %d", rc); + goto end; + } + + rc = cam_ope_mgr_process_cmd_io_buf_req(hw_mgr, packet, ctx_data, + cpu_addr, len, req_idx); + if (rc) { + CAM_ERR(CAM_OPE, "Process OPE cmd io request is failed: %d", + rc); + goto end; + } + + return rc; + +end: + *ope_cmd_buf_addr = 0; + return rc; +} + +static bool cam_ope_mgr_is_valid_inconfig(struct cam_packet *packet) +{ + int i, num_in_map_entries = 0; + bool in_config_valid = false; + struct cam_buf_io_cfg *io_cfg_ptr = NULL; + + io_cfg_ptr = (struct cam_buf_io_cfg *) ((uint32_t *) &packet->payload + + packet->io_configs_offset/4); + + for (i = 0 ; i < packet->num_io_configs; i++) + if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) + num_in_map_entries++; + + if (num_in_map_entries <= OPE_IN_RES_MAX) { + in_config_valid = true; + } else { + CAM_ERR(CAM_OPE, "In config entries(%u) more than allowed(%u)", + num_in_map_entries, OPE_IN_RES_MAX); + } + + CAM_DBG(CAM_OPE, "number of in_config info: %u %u %u %u", + packet->num_io_configs, OPE_MAX_IO_BUFS, + num_in_map_entries, OPE_IN_RES_MAX); + + return in_config_valid; +} + +static bool cam_ope_mgr_is_valid_outconfig(struct cam_packet *packet) +{ + int i, num_out_map_entries = 0; + bool out_config_valid = false; + struct cam_buf_io_cfg *io_cfg_ptr = NULL; + + io_cfg_ptr = (struct cam_buf_io_cfg *) ((uint32_t *) &packet->payload + + packet->io_configs_offset/4); + + for (i = 0 ; i < packet->num_io_configs; i++) + if (io_cfg_ptr[i].direction == CAM_BUF_OUTPUT) + num_out_map_entries++; + + if (num_out_map_entries <= OPE_OUT_RES_MAX) { + out_config_valid = true; + } else { + CAM_ERR(CAM_OPE, "Out config entries(%u) more than allowed(%u)", + num_out_map_entries, OPE_OUT_RES_MAX); + } + + CAM_DBG(CAM_OPE, "number of out_config info: %u %u %u %u", + packet->num_io_configs, OPE_MAX_IO_BUFS, + num_out_map_entries, OPE_OUT_RES_MAX); + + return out_config_valid; +} + +static int cam_ope_mgr_pkt_validation(struct cam_packet *packet) +{ + if ((packet->header.op_code & 0xff) != + OPE_OPCODE_CONFIG) { + CAM_ERR(CAM_OPE, "Invalid Opcode in pkt: %d", + packet->header.op_code & 0xff); + return -EINVAL; + } + + if (packet->num_io_configs > OPE_MAX_IO_BUFS) { + CAM_ERR(CAM_OPE, "Invalid number of io configs: %d %d", + OPE_MAX_IO_BUFS, packet->num_io_configs); + return -EINVAL; + } + + if (packet->num_cmd_buf > OPE_PACKET_MAX_CMD_BUFS) { + CAM_ERR(CAM_OPE, "Invalid number of cmd buffers: %d %d", + OPE_PACKET_MAX_CMD_BUFS, packet->num_cmd_buf); + return -EINVAL; + } + + if (!cam_ope_mgr_is_valid_inconfig(packet) || + !cam_ope_mgr_is_valid_outconfig(packet)) { + return -EINVAL; + } + + CAM_DBG(CAM_OPE, "number of cmd/patch info: %u %u %u %u", + packet->num_cmd_buf, + packet->num_io_configs, OPE_MAX_IO_BUFS, + packet->num_patches); + return 0; +} + +static int cam_ope_get_acquire_info(struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_acquire_args *args, + struct cam_ope_ctx *ctx) +{ + int i = 0; + + if (args->num_acq > 1) { + CAM_ERR(CAM_OPE, "Invalid number of resources: %d", + args->num_acq); + return -EINVAL; + } + + if (args->acquire_info_size < + sizeof(struct ope_acquire_dev_info)) { + CAM_ERR(CAM_OPE, "Invalid acquire size = %d", + args->acquire_info_size); + return -EINVAL; + } + + if (copy_from_user(&ctx->ope_acquire, + (void __user *)args->acquire_info, + sizeof(struct ope_acquire_dev_info))) { + CAM_ERR(CAM_OPE, "Failed in acquire"); + return -EFAULT; + } + + if (ctx->ope_acquire.secure_mode > CAM_SECURE_MODE_SECURE) { + CAM_ERR(CAM_OPE, "Invalid mode:%d", + ctx->ope_acquire.secure_mode); + return -EINVAL; + } + + if (ctx->ope_acquire.num_out_res > OPE_OUT_RES_MAX) { + CAM_ERR(CAM_OPE, "num of out resources exceeding : %u", + ctx->ope_acquire.num_out_res); + return -EINVAL; + } + + if (ctx->ope_acquire.num_in_res > OPE_IN_RES_MAX) { + CAM_ERR(CAM_OPE, "num of in resources exceeding : %u", + ctx->ope_acquire.num_in_res); + return -EINVAL; + } + + if (ctx->ope_acquire.dev_type >= OPE_DEV_TYPE_MAX) { + CAM_ERR(CAM_OPE, "Invalid device type: %d", + ctx->ope_acquire.dev_type); + return -EFAULT; + } + + if (ctx->ope_acquire.hw_type >= OPE_HW_TYPE_MAX) { + CAM_ERR(CAM_OPE, "Invalid HW type: %d", + ctx->ope_acquire.hw_type); + return -EFAULT; + } + + CAM_DBG(CAM_OPE, "top: %u %u %s %u %u %u %u %u", + ctx->ope_acquire.hw_type, ctx->ope_acquire.dev_type, + ctx->ope_acquire.dev_name, + ctx->ope_acquire.nrt_stripes_for_arb, + ctx->ope_acquire.secure_mode, ctx->ope_acquire.batch_size, + ctx->ope_acquire.num_in_res, ctx->ope_acquire.num_out_res); + + for (i = 0; i < ctx->ope_acquire.num_in_res; i++) { + CAM_DBG(CAM_OPE, "IN: %u %u %u %u %u %u %u %u", + ctx->ope_acquire.in_res[i].res_id, + ctx->ope_acquire.in_res[i].format, + ctx->ope_acquire.in_res[i].width, + ctx->ope_acquire.in_res[i].height, + ctx->ope_acquire.in_res[i].alignment, + ctx->ope_acquire.in_res[i].unpacker_format, + ctx->ope_acquire.in_res[i].max_stripe_size, + ctx->ope_acquire.in_res[i].fps); + } + + for (i = 0; i < ctx->ope_acquire.num_out_res; i++) { + CAM_DBG(CAM_OPE, "OUT: %u %u %u %u %u %u %u %u", + ctx->ope_acquire.out_res[i].res_id, + ctx->ope_acquire.out_res[i].format, + ctx->ope_acquire.out_res[i].width, + ctx->ope_acquire.out_res[i].height, + ctx->ope_acquire.out_res[i].alignment, + ctx->ope_acquire.out_res[i].packer_format, + ctx->ope_acquire.out_res[i].subsample_period, + ctx->ope_acquire.out_res[i].subsample_pattern); + } + + return 0; +} + +static int cam_ope_get_free_ctx(struct cam_ope_hw_mgr *hw_mgr) +{ + int i; + + i = find_first_zero_bit(hw_mgr->ctx_bitmap, hw_mgr->ctx_bits); + if (i >= OPE_CTX_MAX || i < 0) { + CAM_ERR(CAM_OPE, "Invalid ctx id = %d", i); + return -EINVAL; + } + + mutex_lock(&hw_mgr->ctx[i].ctx_mutex); + if (hw_mgr->ctx[i].ctx_state != OPE_CTX_STATE_FREE) { + CAM_ERR(CAM_OPE, "Invalid ctx %d state %d", + i, hw_mgr->ctx[i].ctx_state); + mutex_unlock(&hw_mgr->ctx[i].ctx_mutex); + return -EINVAL; + } + set_bit(i, hw_mgr->ctx_bitmap); + mutex_unlock(&hw_mgr->ctx[i].ctx_mutex); + + return i; +} + + +static int cam_ope_put_free_ctx(struct cam_ope_hw_mgr *hw_mgr, uint32_t ctx_id) +{ + if (ctx_id >= OPE_CTX_MAX) { + CAM_ERR(CAM_OPE, "Invalid ctx_id: %d", ctx_id); + return 0; + } + + hw_mgr->ctx[ctx_id].ctx_state = OPE_CTX_STATE_FREE; + clear_bit(ctx_id, hw_mgr->ctx_bitmap); + + return 0; +} + +static int cam_ope_mgr_get_hw_caps(void *hw_priv, void *hw_caps_args) +{ + struct cam_ope_hw_mgr *hw_mgr; + struct cam_query_cap_cmd *query_cap = hw_caps_args; + struct ope_hw_ver hw_ver; + int rc = 0, i; + + if (!hw_priv || !hw_caps_args) { + CAM_ERR(CAM_OPE, "Invalid args: %x %x", hw_priv, hw_caps_args); + return -EINVAL; + } + + hw_mgr = hw_priv; + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (copy_from_user(&hw_mgr->ope_caps, + u64_to_user_ptr(query_cap->caps_handle), + sizeof(struct ope_query_cap_cmd))) { + CAM_ERR(CAM_OPE, "copy_from_user failed: size = %d", + sizeof(struct ope_query_cap_cmd)); + rc = -EFAULT; + goto end; + } + + for (i = 0; i < hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.get_hw_caps( + hw_mgr->ope_dev_intf[i]->hw_priv, + &hw_ver, sizeof(hw_ver)); + if (rc) + goto end; + + hw_mgr->ope_caps.hw_ver[i] = hw_ver; + } + + hw_mgr->ope_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl; + hw_mgr->ope_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl; + hw_mgr->ope_caps.cdm_iommu_handle.non_secure = hw_mgr->iommu_cdm_hdl; + hw_mgr->ope_caps.cdm_iommu_handle.secure = hw_mgr->iommu_sec_cdm_hdl; + hw_mgr->ope_caps.num_ope = hw_mgr->num_ope; + + CAM_DBG(CAM_OPE, "iommu sec %d iommu ns %d cdm s %d cdm ns %d", + hw_mgr->ope_caps.dev_iommu_handle.secure, + hw_mgr->ope_caps.dev_iommu_handle.non_secure, + hw_mgr->ope_caps.cdm_iommu_handle.secure, + hw_mgr->ope_caps.cdm_iommu_handle.non_secure); + + if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), + &hw_mgr->ope_caps, sizeof(struct ope_query_cap_cmd))) { + CAM_ERR(CAM_OPE, "copy_to_user failed: size = %d", + sizeof(struct ope_query_cap_cmd)); + rc = -EFAULT; + } + +end: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) +{ + int rc = 0, i; + int ctx_id; + struct cam_ope_hw_mgr *hw_mgr = hw_priv; + struct cam_ope_ctx *ctx; + struct cam_hw_acquire_args *args = hw_acquire_args; + struct cam_ope_dev_acquire ope_dev_acquire; + struct cam_ope_dev_release ope_dev_release; + struct cam_cdm_acquire_data cdm_acquire; + struct cam_ope_dev_init init; + struct cam_ope_dev_clk_update clk_update; + struct cam_ope_dev_bw_update bw_update; + struct cam_ope_set_irq_cb irq_cb; + + if ((!hw_priv) || (!hw_acquire_args)) { + CAM_ERR(CAM_OPE, "Invalid args: %x %x", + hw_priv, hw_acquire_args); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + ctx_id = cam_ope_get_free_ctx(hw_mgr); + if (ctx_id < 0) { + CAM_ERR(CAM_OPE, "No free ctx"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return ctx_id; + } + + ctx = &hw_mgr->ctx[ctx_id]; + ctx->ctx_id = ctx_id; + mutex_lock(&ctx->ctx_mutex); + rc = cam_ope_get_acquire_info(hw_mgr, args, ctx); + if (rc < 0) { + CAM_ERR(CAM_OPE, "get_acquire info failed: %d", rc); + goto end; + } + + + if (!hw_mgr->ope_ctx_cnt) { + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + init.hfi_en = ope_hw_mgr->hfi_en; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.init( + hw_mgr->ope_dev_intf[i]->hw_priv, &init, + sizeof(init)); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Dev init failed: %d", rc); + goto end; + } + } + + /* Install IRQ CB */ + irq_cb.ope_hw_mgr_cb = cam_ope_hw_mgr_cb; + irq_cb.data = hw_mgr; + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + init.hfi_en = ope_hw_mgr->hfi_en; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Dev init failed: %d", rc); + goto ope_irq_set_failed; + } + } + } + + ope_dev_acquire.ctx_id = ctx_id; + ope_dev_acquire.ope_acquire = &ctx->ope_acquire; + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_ACQUIRE, + &ope_dev_acquire, sizeof(ope_dev_acquire)); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Dev acquire failed: %d", rc); + goto ope_dev_acquire_failed; + } + } + + memset(&cdm_acquire, 0, sizeof(cdm_acquire)); + strlcpy(cdm_acquire.identifier, "ope", sizeof("ope")); + if (ctx->ope_acquire.dev_type == OPE_DEV_TYPE_OPE_RT) + cdm_acquire.priority = CAM_CDM_BL_FIFO_3; + else if (ctx->ope_acquire.dev_type == + OPE_DEV_TYPE_OPE_NRT) + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; + else + goto ope_dev_acquire_failed; + + cdm_acquire.cell_index = 0; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ctx; + cdm_acquire.cam_cdm_callback = cam_ope_ctx_cdm_callback; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.base_array_cnt = 1; + cdm_acquire.base_array[0] = hw_mgr->cdm_reg_map[OPE_DEV_OPE][0]; + + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_OPE, "cdm_acquire is failed: %d", rc); + goto cdm_acquire_failed; + } + + ctx->ope_cdm.cdm_ops = cdm_acquire.ops; + ctx->ope_cdm.cdm_handle = cdm_acquire.handle; + + rc = cam_cdm_stream_on(cdm_acquire.handle); + if (rc) { + CAM_ERR(CAM_OPE, "cdm stream on failure: %d", rc); + goto cdm_stream_on_failure; + } + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + clk_update.clk_rate = 600000000; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_CLK_UPDATE, + &clk_update, sizeof(clk_update)); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Dev clk update failed: %d", rc); + goto ope_clk_update_failed; + } + } + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + bw_update.axi_vote.num_paths = 1; + bw_update.axi_vote_valid = true; + bw_update.axi_vote.axi_path[0].camnoc_bw = 600000000; + bw_update.axi_vote.axi_path[0].mnoc_ab_bw = 600000000; + bw_update.axi_vote.axi_path[0].mnoc_ib_bw = 600000000; + bw_update.axi_vote.axi_path[0].ddr_ab_bw = 600000000; + bw_update.axi_vote.axi_path[0].ddr_ib_bw = 600000000; + bw_update.axi_vote.axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + bw_update.axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_ALL; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_BW_UPDATE, + &bw_update, sizeof(bw_update)); + if (rc) { + CAM_ERR(CAM_OPE, "OPE Dev clk update failed: %d", rc); + goto ope_bw_update_failed; + } + } + + cam_ope_start_req_timer(ctx); + hw_mgr->ope_ctx_cnt++; + ctx->context_priv = args->context_data; + args->ctxt_to_hw_map = ctx; + ctx->ctxt_event_cb = args->event_cb; + ctx->ctx_state = OPE_CTX_STATE_ACQUIRED; + + mutex_unlock(&ctx->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; + +ope_clk_update_failed: +ope_bw_update_failed: +cdm_stream_on_failure: + cam_cdm_release(cdm_acquire.handle); + ctx->ope_cdm.cdm_ops = NULL; + ctx->ope_cdm.cdm_handle = 0; +cdm_acquire_failed: + ope_dev_release.ctx_id = ctx_id; + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RELEASE, + &ope_dev_release, sizeof(ope_dev_release)); + if (rc) + CAM_ERR(CAM_OPE, "OPE Dev release failed: %d", rc); + } + +ope_dev_acquire_failed: + if (!hw_mgr->ope_ctx_cnt) { + irq_cb.ope_hw_mgr_cb = NULL; + irq_cb.data = hw_mgr; + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + init.hfi_en = ope_hw_mgr->hfi_en; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + CAM_ERR(CAM_OPE, "OPE IRQ de register failed"); + } + } +ope_irq_set_failed: + if (!hw_mgr->ope_ctx_cnt) { + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.deinit( + hw_mgr->ope_dev_intf[i]->hw_priv, NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "OPE deinit fail: %d", rc); + } + } +end: + cam_ope_put_free_ctx(hw_mgr, ctx_id); + mutex_unlock(&ctx->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_ope_mgr_release_ctx(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) +{ + int i = 0, rc = 0; + struct cam_ope_dev_release ope_dev_release; + + if (ctx_id >= OPE_CTX_MAX) { + CAM_ERR(CAM_OPE, "ctx_id is wrong: %d", ctx_id); + return -EINVAL; + } + + mutex_lock(&hw_mgr->ctx[ctx_id].ctx_mutex); + if (hw_mgr->ctx[ctx_id].ctx_state != + OPE_CTX_STATE_ACQUIRED) { + mutex_unlock(&hw_mgr->ctx[ctx_id].ctx_mutex); + CAM_DBG(CAM_OPE, "ctx id: %d not in right state: %d", + ctx_id, hw_mgr->ctx[ctx_id].ctx_state); + return 0; + } + + hw_mgr->ctx[ctx_id].ctx_state = OPE_CTX_STATE_RELEASE; + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + ope_dev_release.ctx_id = ctx_id; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RELEASE, + &ope_dev_release, sizeof(ope_dev_release)); + if (rc) + CAM_ERR(CAM_OPE, "OPE Dev release failed: %d", rc); + } + + rc = cam_cdm_stream_off(hw_mgr->ctx[ctx_id].ope_cdm.cdm_handle); + if (rc) + CAM_ERR(CAM_OPE, "OPE CDM streamoff failed: %d", rc); + + rc = cam_cdm_release(hw_mgr->ctx[ctx_id].ope_cdm.cdm_handle); + if (rc) + CAM_ERR(CAM_OPE, "OPE CDM relase failed: %d", rc); + + + for (i = 0; i < CAM_CTX_REQ_MAX; i++) { + if (!hw_mgr->ctx[ctx_id].req_list[i]) + continue; + + if (hw_mgr->ctx[ctx_id].req_list[i]->cdm_cmd) { + kzfree(hw_mgr->ctx[ctx_id].req_list[i]->cdm_cmd); + hw_mgr->ctx[ctx_id].req_list[i]->cdm_cmd = NULL; + } + kzfree(hw_mgr->ctx[ctx_id].req_list[i]); + hw_mgr->ctx[ctx_id].req_list[i] = NULL; + clear_bit(i, hw_mgr->ctx[ctx_id].bitmap); + } + + cam_ope_req_timer_stop(&hw_mgr->ctx[ctx_id]); + hw_mgr->ctx[ctx_id].ope_cdm.cdm_handle = 0; + hw_mgr->ctx[ctx_id].req_cnt = 0; + cam_ope_put_free_ctx(hw_mgr, ctx_id); + hw_mgr->ope_ctx_cnt--; + mutex_unlock(&hw_mgr->ctx[ctx_id].ctx_mutex); + CAM_DBG(CAM_OPE, "X: ctx_id = %d", ctx_id); + + return 0; +} + +static int cam_ope_mgr_release_hw(void *hw_priv, void *hw_release_args) +{ + int i, rc = 0; + int ctx_id = 0; + struct cam_hw_release_args *release_hw = hw_release_args; + struct cam_ope_hw_mgr *hw_mgr = hw_priv; + struct cam_ope_ctx *ctx_data = NULL; + struct cam_ope_set_irq_cb irq_cb; + struct cam_hw_intf *dev_intf; + + if (!release_hw || !hw_mgr) { + CAM_ERR(CAM_OPE, "Invalid args: %pK %pK", release_hw, hw_mgr); + return -EINVAL; + } + + ctx_data = release_hw->ctxt_to_hw_map; + if (!ctx_data) { + CAM_ERR(CAM_OPE, "NULL ctx data"); + return -EINVAL; + } + + ctx_id = ctx_data->ctx_id; + if (ctx_id < 0 || ctx_id >= OPE_CTX_MAX) { + CAM_ERR(CAM_OPE, "Invalid ctx id: %d", ctx_id); + return -EINVAL; + } + + mutex_lock(&hw_mgr->ctx[ctx_id].ctx_mutex); + if (hw_mgr->ctx[ctx_id].ctx_state != OPE_CTX_STATE_ACQUIRED) { + CAM_DBG(CAM_OPE, "ctx is not in use: %d", ctx_id); + mutex_unlock(&hw_mgr->ctx[ctx_id].ctx_mutex); + return -EINVAL; + } + mutex_unlock(&hw_mgr->ctx[ctx_id].ctx_mutex); + + mutex_lock(&hw_mgr->hw_mgr_mutex); + rc = cam_ope_mgr_release_ctx(hw_mgr, ctx_id); + if (!hw_mgr->ope_ctx_cnt) { + CAM_DBG(CAM_OPE, "Last Release"); + if (!hw_mgr->ope_ctx_cnt) { + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + dev_intf = hw_mgr->ope_dev_intf[i]; + irq_cb.ope_hw_mgr_cb = NULL; + irq_cb.data = NULL; + rc = dev_intf->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) + CAM_ERR(CAM_OPE, "IRQ dereg failed: %d", + rc); + } + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + dev_intf = hw_mgr->ope_dev_intf[i]; + rc = dev_intf->hw_ops.deinit( + hw_mgr->ope_dev_intf[i]->hw_priv, + NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "deinit failed: %d", + rc); + } + } + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + CAM_DBG(CAM_OPE, "Release done for ctx_id %d", ctx_id); + return rc; +} + +static int cam_ope_mgr_prepare_hw_update(void *hw_priv, + void *hw_prepare_update_args) +{ + int rc = 0; + struct cam_packet *packet = NULL; + struct cam_ope_hw_mgr *hw_mgr = hw_priv; + struct cam_hw_prepare_update_args *prepare_args = + hw_prepare_update_args; + struct cam_ope_ctx *ctx_data = NULL; + uintptr_t ope_cmd_buf_addr; + uint32_t request_idx = 0; + struct cam_ope_request *ope_req; + + if ((!prepare_args) || (!hw_mgr) || (!prepare_args->packet)) { + CAM_ERR(CAM_OPE, "Invalid args: %x %x", + prepare_args, hw_mgr); + return -EINVAL; + } + + ctx_data = prepare_args->ctxt_to_hw_map; + if (!ctx_data) { + CAM_ERR(CAM_OPE, "Invalid Context"); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + if (ctx_data->ctx_state != OPE_CTX_STATE_ACQUIRED) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "ctx id %u is not acquired state: %d", + ctx_data->ctx_id, ctx_data->ctx_state); + return -EINVAL; + } + + packet = prepare_args->packet; + rc = cam_packet_util_validate_packet(packet, prepare_args->remain_len); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "packet validation is failed: %d", rc); + return rc; + } + + rc = cam_ope_mgr_pkt_validation(packet); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "ope packet validation is failed"); + return -EINVAL; + } + + rc = cam_packet_util_process_patches(packet, hw_mgr->iommu_cdm_hdl, + hw_mgr->iommu_sec_cdm_hdl); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "Patching is failed: %d", rc); + return -EINVAL; + } + + request_idx = find_first_zero_bit(ctx_data->bitmap, ctx_data->bits); + if (request_idx >= CAM_CTX_REQ_MAX || request_idx < 0) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "Invalid ctx req slot = %d", request_idx); + return -EINVAL; + } + set_bit(request_idx, ctx_data->bitmap); + + ctx_data->req_list[request_idx] = + kzalloc(sizeof(struct cam_ope_request), GFP_KERNEL); + if (!ctx_data->req_list[request_idx]) { + rc = -ENOMEM; + mutex_unlock(&ctx_data->ctx_mutex); + goto req_mem_alloc_failed; + } + + ope_req = ctx_data->req_list[request_idx]; + ope_req->cdm_cmd = + kzalloc(((sizeof(struct cam_cdm_bl_request)) + + ((OPE_MAX_CDM_BLS - 1) * + sizeof(struct cam_cdm_bl_cmd))), + GFP_KERNEL); + if (!ope_req->cdm_cmd) { + rc = -ENOMEM; + mutex_unlock(&ctx_data->ctx_mutex); + goto req_cdm_mem_alloc_failed; + } + + rc = cam_ope_mgr_process_cmd_desc(hw_mgr, packet, + ctx_data, &ope_cmd_buf_addr, request_idx); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "cmd desc processing failed: %d", rc); + goto end; + } + + rc = cam_ope_mgr_process_io_cfg(hw_mgr, packet, prepare_args, + ctx_data, request_idx); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "IO cfg processing failed: %d", rc); + goto end; + } + + rc = cam_ope_mgr_create_kmd_buf(hw_mgr, packet, prepare_args, + ctx_data, request_idx, ope_cmd_buf_addr); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "cam_ope_mgr_create_kmd_buf failed: %d", rc); + goto end; + } + + prepare_args->num_hw_update_entries = 1; + prepare_args->hw_update_entries[0].addr = + (uintptr_t)ctx_data->req_list[request_idx]->cdm_cmd; + prepare_args->priv = ctx_data->req_list[request_idx]; + + mutex_unlock(&ctx_data->ctx_mutex); + + return rc; + +end: + kzfree(ctx_data->req_list[request_idx]->cdm_cmd); + ctx_data->req_list[request_idx]->cdm_cmd = NULL; +req_cdm_mem_alloc_failed: + kzfree(ctx_data->req_list[request_idx]); + ctx_data->req_list[request_idx] = NULL; +req_mem_alloc_failed: + clear_bit(request_idx, ctx_data->bitmap); + return rc; +} + +static int cam_ope_mgr_handle_config_err( + struct cam_hw_config_args *config_args, + struct cam_ope_ctx *ctx_data) +{ + struct cam_hw_done_event_data buf_data; + struct cam_ope_request *ope_req; + uint32_t req_idx; + + ope_req = config_args->priv; + + buf_data.request_id = ope_req->request_id; + ctx_data->ctxt_event_cb(ctx_data->context_priv, false, &buf_data); + + req_idx = ope_req->req_idx; + ope_req->request_id = 0; + kzfree(ctx_data->req_list[req_idx]->cdm_cmd); + ctx_data->req_list[req_idx]->cdm_cmd = NULL; + kzfree(ctx_data->req_list[req_idx]); + ctx_data->req_list[req_idx] = NULL; + clear_bit(req_idx, ctx_data->bitmap); + + return 0; +} + +static int cam_ope_mgr_enqueue_config(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_hw_config_args *config_args) +{ + int rc = 0; + uint64_t request_id = 0; + struct crm_workq_task *task; + struct ope_cmd_work_data *task_data; + struct cam_hw_update_entry *hw_update_entries; + struct cam_ope_request *ope_req = NULL; + + ope_req = config_args->priv; + request_id = ope_req->request_id; + hw_update_entries = config_args->hw_update_entries; + CAM_DBG(CAM_OPE, "req_id = %lld %pK", request_id, config_args->priv); + + task = cam_req_mgr_workq_get_task(ope_hw_mgr->cmd_work); + if (!task) { + CAM_ERR(CAM_OPE, "no empty task"); + return -ENOMEM; + } + + task_data = (struct ope_cmd_work_data *)task->payload; + task_data->data = (void *)hw_update_entries->addr; + task_data->req_id = request_id; + task_data->type = OPE_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_ope_mgr_process_cmd; + rc = cam_req_mgr_workq_enqueue_task(task, ctx_data, + CRM_TASK_PRIORITY_0); + + return rc; +} + +static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args) +{ + int rc = 0; + struct cam_ope_hw_mgr *hw_mgr = hw_priv; + struct cam_hw_config_args *config_args = hw_config_args; + struct cam_ope_ctx *ctx_data = NULL; + struct cam_ope_request *ope_req = NULL; + struct cam_cdm_bl_request *cdm_cmd; + + CAM_DBG(CAM_OPE, "E"); + if (!hw_mgr || !config_args) { + CAM_ERR(CAM_OPE, "Invalid arguments %pK %pK", + hw_mgr, config_args); + return -EINVAL; + } + + if (!config_args->num_hw_update_entries) { + CAM_ERR(CAM_OPE, "No hw update enteries are available"); + return -EINVAL; + } + + ctx_data = config_args->ctxt_to_hw_map; + mutex_lock(&hw_mgr->hw_mgr_mutex); + mutex_lock(&ctx_data->ctx_mutex); + if (ctx_data->ctx_state != OPE_CTX_STATE_ACQUIRED) { + mutex_unlock(&ctx_data->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_OPE, "ctx id :%u is not in use", + ctx_data->ctx_id); + return -EINVAL; + } + + ope_req = config_args->priv; + cdm_cmd = (struct cam_cdm_bl_request *) + config_args->hw_update_entries->addr; + cdm_cmd->cookie = ope_req->req_idx; + + rc = cam_ope_mgr_enqueue_config(hw_mgr, ctx_data, config_args); + if (rc) + goto config_err; + + CAM_DBG(CAM_OPE, "req_id %llu, io config", ope_req->request_id); + + cam_ope_req_timer_modify(ctx_data, 200); + mutex_unlock(&ctx_data->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + + return rc; +config_err: + cam_ope_mgr_handle_config_err(config_args, ctx_data); + mutex_unlock(&ctx_data->ctx_mutex); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_ope_mgr_hw_open_u(void *hw_priv, void *fw_download_args) +{ + struct cam_ope_hw_mgr *hw_mgr; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_OPE, "Invalid args: %pK", hw_priv); + return -EINVAL; + } + + hw_mgr = hw_priv; + if (!hw_mgr->open_cnt) { + hw_mgr->open_cnt++; + } else { + rc = -EBUSY; + CAM_ERR(CAM_OPE, "Multiple opens are not supported"); + } + + return rc; +} + +static cam_ope_mgr_hw_close_u(void *hw_priv, void *hw_close_args) +{ + struct cam_ope_hw_mgr *hw_mgr; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_OPE, "Invalid args: %pK", hw_priv); + return -EINVAL; + } + + hw_mgr = hw_priv; + if (!hw_mgr->open_cnt) { + rc = -EINVAL; + CAM_ERR(CAM_OPE, "device is already closed"); + } else { + hw_mgr->open_cnt--; + } + + return rc; +} + +static int cam_ope_mgr_flush_req(struct cam_ope_ctx *ctx_data, + struct cam_hw_flush_args *flush_args) +{ + int idx; + int64_t request_id; + + request_id = *(int64_t *)flush_args->flush_req_pending[0]; + for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) { + if (!ctx_data->req_list[idx]) + continue; + + if (ctx_data->req_list[idx]->request_id != request_id) + continue; + + ctx_data->req_list[idx]->request_id = 0; + kzfree(ctx_data->req_list[idx]->cdm_cmd); + ctx_data->req_list[idx]->cdm_cmd = NULL; + kzfree(ctx_data->req_list[idx]); + ctx_data->req_list[idx] = NULL; + clear_bit(idx, ctx_data->bitmap); + } + + return 0; +} + +static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data, + struct cam_hw_flush_args *flush_args) +{ + int i, rc; + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; + + rc = cam_cdm_flush_hw(ctx_data->ope_cdm.cdm_handle); + + for (i = 0; i < hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RESET, + NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "OPE Dev reset failed: %d", rc); + } + + for (i = 0; i < CAM_CTX_REQ_MAX; i++) { + if (!ctx_data->req_list[i]) + continue; + + ctx_data->req_list[i]->request_id = 0; + kzfree(ctx_data->req_list[i]->cdm_cmd); + ctx_data->req_list[i]->cdm_cmd = NULL; + kzfree(ctx_data->req_list[i]); + ctx_data->req_list[i] = NULL; + clear_bit(i, ctx_data->bitmap); + } + + return rc; +} + +static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args) +{ + struct cam_hw_flush_args *flush_args = hw_flush_args; + struct cam_ope_ctx *ctx_data; + + if ((!hw_priv) || (!hw_flush_args)) { + CAM_ERR(CAM_OPE, "Input params are Null"); + return -EINVAL; + } + + ctx_data = flush_args->ctxt_to_hw_map; + if (!ctx_data) { + CAM_ERR(CAM_OPE, "Ctx data is NULL"); + return -EINVAL; + } + + if ((flush_args->flush_type >= CAM_FLUSH_TYPE_MAX) || + (flush_args->flush_type < CAM_FLUSH_TYPE_REQ)) { + CAM_ERR(CAM_OPE, "Invalid flush type: %d", + flush_args->flush_type); + return -EINVAL; + } + + CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d", + ctx_data->ctx_id, flush_args->flush_type); + + switch (flush_args->flush_type) { + case CAM_FLUSH_TYPE_ALL: + mutex_lock(&ctx_data->ctx_mutex); + cam_ope_mgr_flush_all(ctx_data, flush_args); + mutex_unlock(&ctx_data->ctx_mutex); + break; + case CAM_FLUSH_TYPE_REQ: + mutex_lock(&ctx_data->ctx_mutex); + if (flush_args->num_req_active) { + CAM_ERR(CAM_OPE, "Flush request is not supported"); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + if (flush_args->num_req_pending) + cam_ope_mgr_flush_req(ctx_data, flush_args); + mutex_unlock(&ctx_data->ctx_mutex); + break; + default: + CAM_ERR(CAM_OPE, "Invalid flush type: %d", + flush_args->flush_type); + return -EINVAL; + } + + return 0; +} + +static int cam_ope_mgr_alloc_devs(struct device_node *of_node) +{ + int rc; + uint32_t num_dev; + + rc = of_property_read_u32(of_node, "num-ope", &num_dev); + if (rc) { + CAM_ERR(CAM_OPE, "getting num of ope failed: %d", rc); + return -EINVAL; + } + + ope_hw_mgr->devices[OPE_DEV_OPE] = kzalloc( + sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); + if (!ope_hw_mgr->devices[OPE_DEV_OPE]) + return -ENOMEM; + + return 0; +} + +static int cam_ope_mgr_init_devs(struct device_node *of_node) +{ + int rc = 0; + int count, i; + const char *name = NULL; + struct device_node *child_node = NULL; + struct platform_device *child_pdev = NULL; + struct cam_hw_intf *child_dev_intf = NULL; + struct cam_hw_info *ope_dev; + struct cam_hw_soc_info *soc_info = NULL; + + rc = cam_ope_mgr_alloc_devs(of_node); + if (rc) + return rc; + + count = of_property_count_strings(of_node, "compat-hw-name"); + if (!count) { + CAM_ERR(CAM_OPE, "no compat hw found in dev tree, cnt = %d", + count); + rc = -EINVAL; + goto compat_hw_name_failed; + } + + for (i = 0; i < count; i++) { + rc = of_property_read_string_index(of_node, "compat-hw-name", + i, &name); + if (rc) { + CAM_ERR(CAM_OPE, "getting dev object name failed"); + goto compat_hw_name_failed; + } + + child_node = of_find_node_by_name(NULL, name); + if (!child_node) { + CAM_ERR(CAM_OPE, "Cannot find node in dtsi %s", name); + rc = -ENODEV; + goto compat_hw_name_failed; + } + + child_pdev = of_find_device_by_node(child_node); + if (!child_pdev) { + CAM_ERR(CAM_OPE, "failed to find device on bus %s", + child_node->name); + rc = -ENODEV; + of_node_put(child_node); + goto compat_hw_name_failed; + } + + child_dev_intf = (struct cam_hw_intf *)platform_get_drvdata( + child_pdev); + if (!child_dev_intf) { + CAM_ERR(CAM_OPE, "no child device"); + of_node_put(child_node); + goto compat_hw_name_failed; + } + ope_hw_mgr->devices[child_dev_intf->hw_type] + [child_dev_intf->hw_idx] = child_dev_intf; + + if (!child_dev_intf->hw_ops.process_cmd) + goto compat_hw_name_failed; + + of_node_put(child_node); + } + + ope_hw_mgr->num_ope = count; + for (i = 0; i < count; i++) { + ope_hw_mgr->ope_dev_intf[i] = + ope_hw_mgr->devices[OPE_DEV_OPE][i]; + ope_dev = ope_hw_mgr->ope_dev_intf[i]->hw_priv; + soc_info = &ope_dev->soc_info; + ope_hw_mgr->cdm_reg_map[i][0] = + soc_info->reg_map[0].mem_base; + } + + ope_hw_mgr->hfi_en = of_property_read_bool(of_node, "hfi_en"); + + return 0; +compat_hw_name_failed: + kfree(ope_hw_mgr->devices[OPE_DEV_OPE]); + ope_hw_mgr->devices[OPE_DEV_OPE] = NULL; + return rc; +} + +static int cam_ope_mgr_create_wq(void) +{ + + int rc; + int i; + + rc = cam_req_mgr_workq_create("ope_command_queue", OPE_WORKQ_NUM_TASK, + &ope_hw_mgr->cmd_work, CRM_WORKQ_USAGE_NON_IRQ, + 0); + if (rc) { + CAM_ERR(CAM_OPE, "unable to create a command worker"); + goto cmd_work_failed; + } + + rc = cam_req_mgr_workq_create("ope_message_queue", OPE_WORKQ_NUM_TASK, + &ope_hw_mgr->msg_work, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_OPE, "unable to create a message worker"); + goto msg_work_failed; + } + + rc = cam_req_mgr_workq_create("ope_timer_queue", OPE_WORKQ_NUM_TASK, + &ope_hw_mgr->timer_work, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) { + CAM_ERR(CAM_OPE, "unable to create a timer worker"); + goto timer_work_failed; + } + + ope_hw_mgr->cmd_work_data = + kzalloc(sizeof(struct ope_cmd_work_data) * OPE_WORKQ_NUM_TASK, + GFP_KERNEL); + if (!ope_hw_mgr->cmd_work_data) { + rc = -ENOMEM; + goto cmd_work_data_failed; + } + + ope_hw_mgr->msg_work_data = + kzalloc(sizeof(struct ope_msg_work_data) * OPE_WORKQ_NUM_TASK, + GFP_KERNEL); + if (!ope_hw_mgr->msg_work_data) { + rc = -ENOMEM; + goto msg_work_data_failed; + } + + ope_hw_mgr->timer_work_data = + kzalloc(sizeof(struct ope_clk_work_data) * OPE_WORKQ_NUM_TASK, + GFP_KERNEL); + if (!ope_hw_mgr->timer_work_data) { + rc = -ENOMEM; + goto timer_work_data_failed; + } + + for (i = 0; i < OPE_WORKQ_NUM_TASK; i++) + ope_hw_mgr->msg_work->task.pool[i].payload = + &ope_hw_mgr->msg_work_data[i]; + + for (i = 0; i < OPE_WORKQ_NUM_TASK; i++) + ope_hw_mgr->cmd_work->task.pool[i].payload = + &ope_hw_mgr->cmd_work_data[i]; + + for (i = 0; i < OPE_WORKQ_NUM_TASK; i++) + ope_hw_mgr->timer_work->task.pool[i].payload = + &ope_hw_mgr->timer_work_data[i]; + return 0; + + +timer_work_data_failed: + kfree(ope_hw_mgr->msg_work_data); +msg_work_data_failed: + kfree(ope_hw_mgr->cmd_work_data); +cmd_work_data_failed: + cam_req_mgr_workq_destroy(&ope_hw_mgr->timer_work); +timer_work_failed: + cam_req_mgr_workq_destroy(&ope_hw_mgr->msg_work); +msg_work_failed: + cam_req_mgr_workq_destroy(&ope_hw_mgr->cmd_work); +cmd_work_failed: + return rc; +} + + +int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, + int *iommu_hdl) +{ + int i, rc = 0, j; + struct cam_hw_mgr_intf *hw_mgr_intf; + struct cam_iommu_handle cdm_handles; + + if (!of_node || !hw_mgr_hdl) { + CAM_ERR(CAM_OPE, "Invalid args of_node %pK hw_mgr %pK", + of_node, hw_mgr_hdl); + return -EINVAL; + } + hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl; + + ope_hw_mgr = kzalloc(sizeof(struct cam_ope_hw_mgr), GFP_KERNEL); + if (!ope_hw_mgr) { + CAM_ERR(CAM_OPE, "Unable to allocate mem for: size = %d", + sizeof(struct cam_ope_hw_mgr)); + return -ENOMEM; + } + + hw_mgr_intf->hw_mgr_priv = ope_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_ope_mgr_get_hw_caps; + hw_mgr_intf->hw_acquire = cam_ope_mgr_acquire_hw; + hw_mgr_intf->hw_release = cam_ope_mgr_release_hw; + hw_mgr_intf->hw_start = NULL; + hw_mgr_intf->hw_stop = NULL; + hw_mgr_intf->hw_prepare_update = cam_ope_mgr_prepare_hw_update; + hw_mgr_intf->hw_config_stream_settings = NULL; + hw_mgr_intf->hw_config = cam_ope_mgr_config_hw; + hw_mgr_intf->hw_read = NULL; + hw_mgr_intf->hw_write = NULL; + hw_mgr_intf->hw_cmd = NULL; + hw_mgr_intf->hw_open = cam_ope_mgr_hw_open_u; + hw_mgr_intf->hw_close = cam_ope_mgr_hw_close_u; + hw_mgr_intf->hw_flush = cam_ope_mgr_hw_flush; + + ope_hw_mgr->secure_mode = false; + mutex_init(&ope_hw_mgr->hw_mgr_mutex); + spin_lock_init(&ope_hw_mgr->hw_mgr_lock); + + for (i = 0; i < OPE_CTX_MAX; i++) { + ope_hw_mgr->ctx[i].bitmap_size = + BITS_TO_LONGS(CAM_CTX_REQ_MAX) * + sizeof(long); + ope_hw_mgr->ctx[i].bitmap = kzalloc( + ope_hw_mgr->ctx[i].bitmap_size, GFP_KERNEL); + if (!ope_hw_mgr->ctx[i].bitmap) { + CAM_ERR(CAM_OPE, "bitmap allocation failed: size = %d", + ope_hw_mgr->ctx[i].bitmap_size); + rc = -ENOMEM; + goto ope_ctx_bitmap_failed; + } + ope_hw_mgr->ctx[i].bits = ope_hw_mgr->ctx[i].bitmap_size * + BITS_PER_BYTE; + mutex_init(&ope_hw_mgr->ctx[i].ctx_mutex); + } + + rc = cam_ope_mgr_init_devs(of_node); + if (rc) + goto dev_init_failed; + + ope_hw_mgr->ctx_bitmap_size = + BITS_TO_LONGS(OPE_CTX_MAX) * sizeof(long); + ope_hw_mgr->ctx_bitmap = kzalloc(ope_hw_mgr->ctx_bitmap_size, + GFP_KERNEL); + if (!ope_hw_mgr->ctx_bitmap) { + rc = -ENOMEM; + goto ctx_bitmap_alloc_failed; + } + + ope_hw_mgr->ctx_bits = ope_hw_mgr->ctx_bitmap_size * + BITS_PER_BYTE; + + rc = cam_smmu_get_handle("ope", &ope_hw_mgr->iommu_hdl); + if (rc) { + CAM_ERR(CAM_OPE, "get mmu handle failed: %d", rc); + goto ope_get_hdl_failed; + } + + rc = cam_smmu_get_handle("cam-secure", &ope_hw_mgr->iommu_sec_hdl); + if (rc) { + CAM_ERR(CAM_OPE, "get secure mmu handle failed: %d", rc); + goto secure_hdl_failed; + } + + rc = cam_cdm_get_iommu_handle("ope", &cdm_handles); + if (rc) { + CAM_ERR(CAM_OPE, "ope cdm handle get is failed: %d", rc); + goto ope_cdm_hdl_failed; + } + + ope_hw_mgr->iommu_cdm_hdl = cdm_handles.non_secure; + ope_hw_mgr->iommu_sec_cdm_hdl = cdm_handles.secure; + CAM_DBG(CAM_OPE, "iommu hdls %x %x cdm %x %x", + ope_hw_mgr->iommu_hdl, ope_hw_mgr->iommu_sec_hdl, + ope_hw_mgr->iommu_cdm_hdl, + ope_hw_mgr->iommu_sec_cdm_hdl); + + rc = cam_ope_mgr_create_wq(); + if (rc) + goto ope_wq_create_failed; + + if (iommu_hdl) + *iommu_hdl = ope_hw_mgr->iommu_hdl; + + return rc; + +ope_wq_create_failed: + ope_hw_mgr->iommu_cdm_hdl = -1; + ope_hw_mgr->iommu_sec_cdm_hdl = -1; +ope_cdm_hdl_failed: + cam_smmu_destroy_handle(ope_hw_mgr->iommu_sec_hdl); + ope_hw_mgr->iommu_sec_hdl = -1; +secure_hdl_failed: + cam_smmu_destroy_handle(ope_hw_mgr->iommu_hdl); + ope_hw_mgr->iommu_hdl = -1; +ope_get_hdl_failed: + kzfree(ope_hw_mgr->ctx_bitmap); + ope_hw_mgr->ctx_bitmap = NULL; + ope_hw_mgr->ctx_bitmap_size = 0; + ope_hw_mgr->ctx_bits = 0; +ctx_bitmap_alloc_failed: + kzfree(ope_hw_mgr->devices[OPE_DEV_OPE]); + ope_hw_mgr->devices[OPE_DEV_OPE] = NULL; +dev_init_failed: +ope_ctx_bitmap_failed: + mutex_destroy(&ope_hw_mgr->hw_mgr_mutex); + for (j = i - 1; j >= 0; j--) { + mutex_destroy(&ope_hw_mgr->ctx[j].ctx_mutex); + kzfree(ope_hw_mgr->ctx[j].bitmap); + ope_hw_mgr->ctx[j].bitmap = NULL; + ope_hw_mgr->ctx[j].bitmap_size = 0; + ope_hw_mgr->ctx[j].bits = 0; + } + kzfree(ope_hw_mgr); + ope_hw_mgr = NULL; + + return rc; +} + diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h new file mode 100644 index 000000000000..bd88ceb3d764 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -0,0 +1,399 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_HW_MGR_H +#define CAM_OPE_HW_MGR_H + +#include +#include +#include +#include "ope_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" +#include "cam_req_mgr_workq.h" +#include "cam_mem_mgr.h" +#include "cam_smmu_api.h" +#include "cam_soc_util.h" +#include "cam_req_mgr_timer.h" +#include "cam_context.h" +#include "ope_hw.h" +#include "cam_cdm_intf_api.h" +#include "cam_req_mgr_timer.h" + +#define OPE_CTX_MAX 32 +#define CAM_FRAME_CMD_MAX 20 + + +#define OPE_WORKQ_NUM_TASK 100 +#define OPE_WORKQ_TASK_CMD_TYPE 1 +#define OPE_WORKQ_TASK_MSG_TYPE 2 + +#define OPE_PACKET_SIZE 0 +#define OPE_PACKET_TYPE 1 +#define OPE_PACKET_OPCODE 2 + +#define OPE_PACKET_MAX_CMD_BUFS 4 + +#define OPE_MAX_OUTPUT_SUPPORTED 8 +#define OPE_MAX_INPUT_SUPPORTED 3 + +#define OPE_FRAME_PROCESS_SUCCESS 0 +#define OPE_FRAME_PROCESS_FAILURE 1 + +#define OPE_CTX_STATE_FREE 0 +#define OPE_CTX_STATE_IN_USE 1 +#define OPE_CTX_STATE_ACQUIRED 2 +#define OPE_CTX_STATE_RELEASE 3 + +#define OPE_CMDS OPE_MAX_CMD_BUFS +#define CAM_MAX_IN_RES 8 + +#define OPE_MAX_CDM_BLS 16 + +/** + * struct ope_cmd_work_data + * + * @type: Type of work data + * @data: Private data + * @req_id: Request Id + */ +struct ope_cmd_work_data { + uint32_t type; + void *data; + int64_t req_id; +}; + +/** + * struct ope_msg_work_data + * + * @type: Type of work data + * @data: Private data + * @irq_status: IRQ status + */ +struct ope_msg_work_data { + uint32_t type; + void *data; + uint32_t irq_status; +}; + +/** + * struct ope_clk_work_data + * + * @type: Type of work data + * @data: Private data + */ +struct ope_clk_work_data { + uint32_t type; + void *data; +}; + +/** + * struct cdm_dmi_cmd + * + * @length: Number of bytes in LUT + * @reserved: reserved bits + * @cmd: Command ID (CDMCmd) + * @addr: Address of the LUT in memory + * @DMIAddr: Address of the target DMI config register + * @DMISel: DMI identifier + */ +struct cdm_dmi_cmd { + unsigned int length : 16; + unsigned int reserved : 8; + unsigned int cmd : 8; + unsigned int addr; + unsigned int DMIAddr : 24; + unsigned int DMISel : 8; +} __attribute__((__packed__)); + +/** + * struct ope_debug_buffer + * + * @cpu_addr: CPU address + * @iova_addr: IOVA address + * @len: Buffer length + * @size: Buffer Size + */ +struct ope_debug_buffer { + uintptr_t cpu_addr; + dma_addr_t iova_addr; + size_t len; + uint32_t size; +}; + +/** + * struct ope_kmd_buffer + * + * @mem_handle: Memory handle + * @cpu_addr: CPU address + * @iova_addr: IOVA address + * @iova_cdm_addr: CDM IOVA address + * @len: Buffer length + * @size: Buffer Size + */ +struct ope_kmd_buffer { + uint32_t mem_handle; + uintptr_t cpu_addr; + dma_addr_t iova_addr; + dma_addr_t iova_cdm_addr; + size_t len; + uint32_t size; +}; + +struct ope_stripe_settings { + uintptr_t cpu_addr; + dma_addr_t iova_addr; + size_t len; + uint32_t size; + uint32_t buf_type; + uint32_t type_buffered; +}; + +/** + * struct ope_pass_settings + * + * @cpu_addr: CPU address + * @iova_addr: IOVA address + * @len: Buffer length + * @size: Buffer Size + * @idx: Pass Index + * @buf_type: Direct/Indirect type + * @type_buffered: SB/DB types + */ +struct ope_pass_settings { + uintptr_t cpu_addr; + dma_addr_t iova_addr; + size_t len; + uint32_t size; + uint32_t idx; + uint32_t buf_type; + uint32_t type_buffered; +}; + +/** + * struct ope_frame_settings + * + * @cpu_addr: CPU address + * @iova_addr: IOVA address + * @offset: offset + * @len: Buffer length + * @size: Buffer Size + * @buf_type: Direct/Indirect type + * @type_buffered: SB/DB types + * @prefecth_disable: Disable prefetch + */ +struct ope_frame_settings { + uintptr_t cpu_addr; + dma_addr_t iova_addr; + uint32_t offset; + size_t len; + uint32_t size; + uint32_t buf_type; + uint32_t type_buffered; + uint32_t prefecth_disable; +}; + +/** + * struct ope_stripe_io + * + * @format: Stripe format + * @s_location: Stripe location + * @cpu_addr: Stripe CPU address + * @iova_addr: Stripe IOVA address + * @width: Stripe width + * @height: Stripe height + * @stride: Stripe stride + * @unpack_format: Unpack format + * @pack_format: Packing format + * @alignment: Stripe alignment + * @offset: Stripe offset + * @x_init: X_init + * @subsample_period: Subsample period + * @subsample_pattern: Subsample pattern + * @len: Stripe buffer length + * @disable_bus: disable bus for the stripe + */ +struct ope_stripe_io { + uint32_t format; + uint32_t s_location; + uintptr_t cpu_addr; + dma_addr_t iova_addr; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t unpack_format; + uint32_t pack_format; + uint32_t alignment; + uint32_t offset; + uint32_t x_init; + uint32_t subsample_period; + uint32_t subsample_pattern; + size_t len; + uint32_t disable_bus; +}; + +/** + * struct ope_io_buf + * + * @direction: Direction of a buffer + * @resource_type: Resource type of IO Buffer + * @format: Format + * @fence: Fence + * @num_planes: Number of planes + * @num_stripes: Number of stripes + * @s_io: Stripe info + */ +struct ope_io_buf { + uint32_t direction; + uint32_t resource_type; + uint32_t format; + uint32_t fence; + uint32_t num_planes; + uint32_t num_stripes[OPE_MAX_PLANES]; + struct ope_stripe_io s_io[OPE_MAX_PLANES][OPE_MAX_STRIPES]; +}; + +/** + * struct cam_ope_request + * + * @request_id: Request Id + * @req_idx: Index in request list + * @state: Request state + * @num_batch: Number of batches + * @num_cmd_bufs: Number of command buffers + * @num_frame_bufs: Number of frame buffers + * @num_pass_bufs: Number of pass Buffers + * @num_stripes: Number of Stripes + * @num_io_bufs: Number of IO Buffers + * @in_resource: Input resource + * @num_stripe_cmd_bufs: Command buffers per stripe + * @ope_kmd_buf: KMD buffer for OPE programming + * @ope_debug_buf: Debug buffer + * @io_buf: IO config info of a request + * @cdm_cmd: CDM command for OPE CDM + */ +struct cam_ope_request { + uint64_t request_id; + uint32_t req_idx; + uint32_t state; + uint32_t num_batch; + uint32_t num_cmd_bufs; + uint32_t num_frame_bufs; + uint32_t num_pass_bufs; + uint32_t num_stripes[OPE_MAX_BATCH_SIZE]; + uint32_t num_io_bufs[OPE_MAX_BATCH_SIZE]; + uint32_t in_resource; + uint8_t num_stripe_cmd_bufs[OPE_MAX_BATCH_SIZE][OPE_MAX_STRIPES]; + struct ope_kmd_buffer ope_kmd_buf; + struct ope_debug_buffer ope_debug_buf; + struct ope_io_buf io_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_IO_BUFS]; + struct cam_cdm_bl_request *cdm_cmd; +}; + +/** + * struct cam_ope_cdm + * + * @cdm_handle: OPE CDM Handle + * @cdm_ops: OPE CDM Operations + */ +struct cam_ope_cdm { + uint32_t cdm_handle; + struct cam_cdm_utils_ops *cdm_ops; +}; + +/** + * struct cam_ope_ctx + * + * @context_priv: Private data of context + * @bitmap: Context bit map + * @bitmap_size: Context bit map size + * @bits: Context bit map bits + * @ctx_id: Context ID + * @ctx_state: State of a context + * @req_cnt: Requests count + * @ctx_mutex: Mutex for context + * @acquire_dev_cmd: Cam acquire command + * @ope_acquire: OPE acquire command + * @ctxt_event_cb: Callback of a context + * @req_list: Request List + * @ope_cdm: OPE CDM info + * @req_watch_dog: Watchdog for requests + */ +struct cam_ope_ctx { + void *context_priv; + size_t bitmap_size; + void *bitmap; + size_t bits; + uint32_t ctx_id; + uint32_t ctx_state; + uint32_t req_cnt; + struct mutex ctx_mutex; + struct cam_acquire_dev_cmd acquire_dev_cmd; + struct ope_acquire_dev_info ope_acquire; + cam_hw_event_cb_func ctxt_event_cb; + struct cam_ope_request *req_list[CAM_CTX_REQ_MAX]; + struct cam_ope_cdm ope_cdm; + struct cam_req_mgr_timer *req_watch_dog; +}; + +/** + * struct cam_ope_hw_mgr + * + * @open_cnt: OPE device open count + * @ope_ctx_cnt: Open context count + * @hw_mgr_mutex: Mutex for HW manager + * @hw_mgr_lock: Spinlock for HW manager + * @hfi_en: Flag for HFI + * @iommu_hdl: OPE Handle + * @iommu_sec_hdl: OPE Handle for secure + * @iommu_cdm_hdl: CDM Handle + * @iommu_sec_cdm_hdl: CDM Handle for secure + * @num_ope: Number of OPE + * @secure_mode: Mode of OPE operation + * @ctx_bitmap: Context bit map + * @ctx_bitmap_size: Context bit map size + * @ctx_bits: Context bit map bits + * @ctx: OPE context + * @devices: OPE devices + * @ope_caps: OPE capabilities + * @cmd_work: Command work + * @msg_work: Message work + * @timer_work: Timer work + * @cmd_work_data: Command work data + * @msg_work_data: Message work data + * @timer_work_data: Timer work data + * @ope_dev_intf: OPE device interface + * @cdm_reg_map: OPE CDM register map + */ +struct cam_ope_hw_mgr { + int32_t open_cnt; + uint32_t ope_ctx_cnt; + struct mutex hw_mgr_mutex; + spinlock_t hw_mgr_lock; + bool hfi_en; + int32_t iommu_hdl; + int32_t iommu_sec_hdl; + int32_t iommu_cdm_hdl; + int32_t iommu_sec_cdm_hdl; + uint32_t num_ope; + bool secure_mode; + void *ctx_bitmap; + size_t ctx_bitmap_size; + size_t ctx_bits; + struct cam_ope_ctx ctx[OPE_CTX_MAX]; + struct cam_hw_intf **devices[OPE_DEV_MAX]; + struct ope_query_cap_cmd ope_caps; + + struct cam_req_mgr_core_workq *cmd_work; + struct cam_req_mgr_core_workq *msg_work; + struct cam_req_mgr_core_workq *timer_work; + struct ope_cmd_work_data *cmd_work_data; + struct ope_msg_work_data *msg_work_data; + struct ope_clk_work_data *timer_work_data; + struct cam_hw_intf *ope_dev_intf[OPE_DEV_MAX]; + struct cam_soc_reg_map *cdm_reg_map[OPE_DEV_MAX][OPE_BASE_MAX]; +}; + +#endif /* CAM_OPE_HW_MGR_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h new file mode 100644 index 000000000000..89454d0e169d --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_HW_MGR_INTF_H +#define CAM_OPE_HW_MGR_INTF_H + +#include +#include +#include + +int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, + int *iommu_hdl); + +#endif /* CAM_OPE_HW_MGR_INTF_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c new file mode 100644 index 000000000000..3deb8ed92212 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -0,0 +1,693 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "ope_core.h" +#include "ope_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "cam_cdm_util.h" +#include "ope_hw.h" +#include "ope_dev_intf.h" +#include "ope_bus_rd.h" + +static struct ope_bus_rd *bus_rd; + +static int cam_ope_bus_rd_in_port_idx(uint32_t input_port_id) +{ + int i; + + for (i = 0; i < OPE_IN_RES_MAX; i++) + if (bus_rd->in_port_to_rm[i].input_port_id == + input_port_id) + return i; + + return -EINVAL; +} + +static int cam_ope_bus_rd_combo_idx(uint32_t format) +{ + int rc = -EINVAL; + + switch (format) { + case CAM_FORMAT_YUV422: + case CAM_FORMAT_NV21: + case CAM_FORMAT_NV12: + rc = BUS_RD_YUV; + break; + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_QTI_RAW_8: + case CAM_FORMAT_QTI_RAW_10: + case CAM_FORMAT_QTI_RAW_12: + case CAM_FORMAT_QTI_RAW_14: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN32_20: + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_PLAIN128: + rc = BUS_RD_BAYER; + break; + default: + break; + } + + CAM_DBG(CAM_OPE, "Input format = %u rc = %d", + format, rc); + return rc; +} + +static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t *kmd_buf, int batch_idx, + int io_idx, struct cam_ope_dev_prepare_req *prepare) +{ + int k, l, m; + uint32_t idx; + int32_t combo_idx; + uint32_t req_idx, count = 0, temp; + uint32_t temp_reg[128] = {0}; + uint32_t rm_id, header_size; + uint32_t rsc_type; + struct cam_hw_prepare_update_args *prepare_args; + struct cam_ope_ctx *ctx_data; + struct cam_ope_request *ope_request; + struct ope_io_buf *io_buf; + struct ope_stripe_io *stripe_io; + struct ope_bus_rd_ctx *bus_rd_ctx; + struct cam_ope_bus_rd_reg *rd_reg; + struct cam_ope_bus_rd_client_reg *rd_reg_client; + struct cam_ope_bus_rd_reg_val *rd_reg_val; + struct cam_ope_bus_rd_client_reg_val *rd_res_val_client; + struct ope_bus_in_port_to_rm *in_port_to_rm; + struct ope_bus_rd_io_port_cdm_info *io_port_cdm; + struct cam_cdm_utils_ops *cdm_ops; + struct ope_bus_rd_io_port_info *io_port_info; + + + if (ctx_id < 0 || !prepare) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare); + return NULL; + } + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx); + return NULL; + } + + if (io_idx >= OPE_MAX_IO_BUFS) { + CAM_ERR(CAM_OPE, "Invalid IO idx: %d", io_idx); + return NULL; + } + + prepare_args = prepare->prepare_args; + ctx_data = prepare->ctx_data; + req_idx = prepare->req_idx; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + ope_request = ctx_data->req_list[req_idx]; + CAM_DBG(CAM_OPE, "req_idx = %d req_id = %lld KMDbuf %x offset %d", + req_idx, ope_request->request_id, + kmd_buf, prepare->kmd_buf_offset); + bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + io_port_info = &bus_rd_ctx->io_port_info; + rd_reg = ope_hw_info->bus_rd_reg; + rd_reg_val = ope_hw_info->bus_rd_reg_val; + + io_buf = &ope_request->io_buf[batch_idx][io_idx]; + + CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d", + batch_idx, io_idx, io_buf->direction); + io_port_cdm = + &bus_rd_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; + in_port_to_rm = + &bus_rd->in_port_to_rm[io_buf->resource_type - 1]; + combo_idx = cam_ope_bus_rd_combo_idx(io_buf->format); + if (combo_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid combo_idx"); + return NULL; + } + + for (k = 0; k < io_buf->num_planes; k++) { + for (l = 0; l < io_buf->num_stripes[k]; l++) { + stripe_io = &io_buf->s_io[k][l]; + rsc_type = io_buf->resource_type - 1; + /* frame level info */ + /* stripe level info */ + rm_id = in_port_to_rm->rm_port_id[combo_idx][k]; + rd_reg_client = &rd_reg->rd_clients[rm_id]; + rd_res_val_client = &rd_reg_val->rd_clients[rm_id]; + + /* security cfg */ + temp_reg[count++] = rd_reg->offset + + rd_reg->security_cfg; + temp_reg[count++] = + ctx_data->ope_acquire.secure_mode; + + /* enable client */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->core_cfg; + temp_reg[count++] = 1; + + /* ccif meta data */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->ccif_meta_data; + temp = 0; + temp |= stripe_io->s_location & + rd_res_val_client->stripe_location_mask; + temp |= (io_port_info->pixel_pattern[rsc_type] & + rd_res_val_client->pix_pattern_mask) << + rd_res_val_client->pix_pattern_shift; + temp_reg[count++] = temp; + + /* Address of the Image */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->img_addr; + temp_reg[count++] = stripe_io->iova_addr; + + /* Buffer size */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->img_cfg; + temp = 0; + temp = stripe_io->height; + temp |= + (stripe_io->width & + rd_res_val_client->img_width_mask) << + rd_res_val_client->img_width_shift; + temp_reg[count++] = temp; + + /* stride */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->stride; + temp_reg[count++] = stripe_io->stride; + + /* Unpack cfg : Mode and alignment */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->unpack_cfg; + temp = 0; + temp |= (stripe_io->unpack_format & + rd_res_val_client->mode_mask) << + rd_res_val_client->mode_shift; + temp |= (stripe_io->alignment & + rd_res_val_client->alignment_mask) << + rd_res_val_client->alignment_shift; + temp_reg[count++] = temp; + + /* latency buffer allocation */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->latency_buf_allocation; + temp_reg[count++] = io_port_info->latency_buf_size; + + header_size = cdm_ops->cdm_get_cmd_header_size( + CAM_CDM_CMD_REG_RANDOM); + idx = io_port_cdm->num_s_cmd_bufs[l]; + io_port_cdm->s_cdm_info[l][idx].len = sizeof(temp) * + (count + header_size); + io_port_cdm->s_cdm_info[l][idx].offset = + prepare->kmd_buf_offset; + io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf; + io_port_cdm->num_s_cmd_bufs[l]++; + + kmd_buf = cdm_ops->cdm_write_regrandom( + kmd_buf, count/2, temp_reg); + prepare->kmd_buf_offset += ((count + header_size) * + sizeof(temp)); + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", + batch_idx, io_idx, k, l); + for (m = 0; m < count; m++) + CAM_DBG(CAM_OPE, "%d:temp:%x", + m, temp_reg[m]); + CAM_DBG(CAM_OPE, "kmd_buf:%x offset:%d", + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "%x count: %d size:%d", + temp_reg, count, header_size); + CAM_DBG(CAM_OPE, "RD cmdbufs:%d off:%d", + io_port_cdm->num_s_cmd_bufs[l], + io_port_cdm->s_cdm_info[l][idx].offset); + CAM_DBG(CAM_OPE, "len:%d", + io_port_cdm->s_cdm_info[l][idx].len); + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", + batch_idx, io_idx, k, l); + count = 0; + } + } + + return kmd_buf; +} + +static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + int i, j; + int32_t combo_idx; + uint32_t req_idx, count = 0, temp; + uint32_t temp_reg[32] = {0}; + uint32_t header_size; + uint32_t *kmd_buf; + struct cam_ope_dev_prepare_req *prepare; + struct cam_ope_ctx *ctx_data; + struct cam_ope_request *ope_request; + struct ope_io_buf *io_buf; + struct ope_bus_rd_ctx *bus_rd_ctx; + struct cam_ope_bus_rd_reg *rd_reg; + struct cam_ope_bus_rd_reg_val *rd_reg_val; + struct ope_bus_rd_io_port_cdm_batch *io_port_cdm_batch; + struct ope_bus_rd_io_port_cdm_info *io_port_cdm; + struct cam_cdm_utils_ops *cdm_ops; + + if (ctx_id < 0 || !data) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); + return -EINVAL; + } + prepare = data; + + ctx_data = prepare->ctx_data; + req_idx = prepare->req_idx; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + ope_request = ctx_data->req_list[req_idx]; + kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + prepare->kmd_buf_offset; + CAM_DBG(CAM_OPE, "req_idx = %d req_id = %lld", + req_idx, ope_request->request_id); + CAM_DBG(CAM_OPE, "KMD buf and offset = %x %d", + kmd_buf, prepare->kmd_buf_offset); + bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + io_port_cdm_batch = + &bus_rd_ctx->io_port_cdm_batch; + memset(io_port_cdm_batch, 0, + sizeof(struct ope_bus_rd_io_port_cdm_batch)); + rd_reg = ope_hw_info->bus_rd_reg; + rd_reg_val = ope_hw_info->bus_rd_reg_val; + + for (i = 0; i < ope_request->num_batch; i++) { + for (j = 0; j < ope_request->num_io_bufs[i]; j++) { + io_buf = &ope_request->io_buf[i][j]; + if (io_buf->direction != CAM_BUF_INPUT) + continue; + + CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d", + i, j, io_buf->direction); + io_port_cdm = + &bus_rd_ctx->io_port_cdm_batch.io_port_cdm[i]; + + combo_idx = cam_ope_bus_rd_combo_idx(io_buf->format); + if (combo_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid combo_idx"); + return combo_idx; + } + + kmd_buf = cam_ope_bus_rd_update(ope_hw_info, + ctx_id, kmd_buf, i, j, prepare); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + } + } + + if (!io_port_cdm) { + rc = -EINVAL; + goto end; + } + + /* Go command */ + count = 0; + temp_reg[count++] = rd_reg->offset + + rd_reg->input_if_cmd; + temp = 0; + temp |= rd_reg_val->go_cmd; + temp_reg[count++] = temp; + + header_size = + cdm_ops->cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); + io_port_cdm->go_cmd_addr = kmd_buf; + io_port_cdm->go_cmd_len = + sizeof(temp) * (count + header_size); + io_port_cdm->go_cmd_offset = + prepare->kmd_buf_offset; + kmd_buf = cdm_ops->cdm_write_regrandom( + kmd_buf, count/2, temp_reg); + prepare->kmd_buf_offset += + ((count + header_size) * sizeof(temp)); + CAM_DBG(CAM_OPE, "kmd_buf:%x,offset:%d", + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "t_reg:%xcount: %d size:%d", + temp_reg, count, header_size); + prepare->rd_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; + +end: + return rc; +} + +static int cam_ope_bus_rd_release(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0, i; + struct ope_acquire_dev_info *in_acquire; + struct ope_bus_rd_ctx *bus_rd_ctx; + + if (ctx_id < 0) { + CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id); + return -EINVAL; + } + + in_acquire = bus_rd->bus_rd_ctx[ctx_id].ope_acquire; + bus_rd->bus_rd_ctx[ctx_id].ope_acquire = NULL; + bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx->num_in_ports = 0; + + for (i = 0; i < bus_rd_ctx->num_in_ports; i++) { + bus_rd_ctx->io_port_info.input_port_id[i] = 0; + bus_rd_ctx->io_port_info.input_format_type[i - 1] = 0; + bus_rd_ctx->io_port_info.pixel_pattern[i - 1] = 0; + } + + return rc; +} + +static int cam_ope_bus_rd_acquire(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0, i; + struct ope_acquire_dev_info *in_acquire; + struct ope_bus_rd_ctx *bus_rd_ctx; + struct ope_bus_in_port_to_rm *in_port_to_rm; + struct cam_ope_bus_rd_reg_val *bus_rd_reg_val; + int combo_idx; + int in_port_idx; + + + if (ctx_id < 0 || !data || !ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x %x", + ctx_id, data, ope_hw_info); + return -EINVAL; + } + + bus_rd->bus_rd_ctx[ctx_id].ope_acquire = data; + in_acquire = data; + bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx->num_in_ports = in_acquire->num_in_res; + bus_rd_ctx->security_flag = in_acquire->secure_mode; + bus_rd_reg_val = ope_hw_info->bus_rd_reg_val; + + for (i = 0; i < in_acquire->num_in_res; i++) { + if (!in_acquire->in_res[i].width) + continue; + + CAM_DBG(CAM_OPE, "i = %d format = %u width = %x height = %x", + i, in_acquire->in_res[i].format, + in_acquire->in_res[i].width, + in_acquire->in_res[i].height); + CAM_DBG(CAM_OPE, "pix_pattern:%u alignment:%u unpack_format:%u", + in_acquire->in_res[i].pixel_pattern, + in_acquire->in_res[i].alignment, + in_acquire->in_res[i].unpacker_format); + CAM_DBG(CAM_OPE, "max_stripe = %u fps = %u", + in_acquire->in_res[i].max_stripe_size, + in_acquire->in_res[i].fps); + + in_port_idx = cam_ope_bus_rd_in_port_idx(i + 1); + if (in_port_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid in_port_idx: %d", i + 1); + rc = -EINVAL; + goto end; + } + + in_port_to_rm = &bus_rd->in_port_to_rm[in_port_idx]; + combo_idx = cam_ope_bus_rd_combo_idx( + in_acquire->in_res[i].format); + if (combo_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid format: %d", + in_acquire->in_res[i].format); + rc = -EINVAL; + goto end; + } + + if (!in_port_to_rm->num_rm[combo_idx]) { + CAM_ERR(CAM_OPE, "Invalid format for Input port"); + rc = -EINVAL; + goto end; + } + + bus_rd_ctx->io_port_info.input_port_id[i] = + in_acquire->in_res[i].res_id; + bus_rd_ctx->io_port_info.input_format_type[i] = + in_acquire->in_res[i].format; + if (in_acquire->in_res[i].pixel_pattern > + PIXEL_PATTERN_CRYCBY) { + CAM_ERR(CAM_OPE, "Invalid pix pattern = %u", + in_acquire->in_res[i].pixel_pattern); + rc = -EINVAL; + goto end; + } + + bus_rd_ctx->io_port_info.pixel_pattern[i] = + in_acquire->in_res[i].pixel_pattern; + bus_rd_ctx->io_port_info.latency_buf_size = + bus_rd_reg_val->latency_buf_size; + + CAM_DBG(CAM_OPE, "i:%d port_id = %u format %u pix_pattern = %u", + i, bus_rd_ctx->io_port_info.input_port_id[i], + bus_rd_ctx->io_port_info.input_format_type[i], + bus_rd_ctx->io_port_info.pixel_pattern[i]); + CAM_DBG(CAM_OPE, "latency_buf_size = %u", + bus_rd_ctx->io_port_info.latency_buf_size); + } + +end: + return rc; +} + +static int cam_ope_bus_rd_init(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + struct cam_ope_bus_rd_reg_val *bus_rd_reg_val; + struct cam_ope_bus_rd_reg *bus_rd_reg; + struct cam_ope_dev_init *dev_init = data; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + bus_rd_reg_val = ope_hw_info->bus_rd_reg_val; + bus_rd_reg = ope_hw_info->bus_rd_reg; + bus_rd_reg->base = dev_init->core_info->ope_hw_info->ope_bus_rd_base; + + /* OPE SW RESET */ + init_completion(&bus_rd->reset_complete); + + /* enable interrupt mask */ + cam_io_w_mb(bus_rd_reg_val->irq_mask, + ope_hw_info->bus_rd_reg->base + bus_rd_reg->irq_mask); + + cam_io_w_mb(bus_rd_reg_val->sw_reset, + ope_hw_info->bus_rd_reg->base + bus_rd_reg->sw_reset); + + rc = wait_for_completion_timeout( + &bus_rd->reset_complete, msecs_to_jiffies(30000)); + + if (!rc || rc < 0) { + CAM_ERR(CAM_OPE, "reset error result = %d", rc); + if (!rc) + rc = -ETIMEDOUT; + } else { + rc = 0; + } + + cam_io_w_mb(bus_rd_reg_val->irq_mask, + ope_hw_info->bus_rd_reg->base + bus_rd_reg->irq_mask); + + return rc; +} + +static int cam_ope_bus_rd_probe(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0, i, j, combo_idx, k; + struct cam_ope_bus_rd_reg_val *bus_rd_reg_val; + struct cam_ope_bus_rd_reg *bus_rd_reg; + struct ope_bus_in_port_to_rm *in_port_to_rm; + uint32_t input_port_idx; + uint32_t rm_idx; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + bus_rd = kzalloc(sizeof(struct ope_bus_rd), GFP_KERNEL); + if (!bus_rd) { + CAM_ERR(CAM_OPE, "Out of memory"); + return -ENOMEM; + } + bus_rd->ope_hw_info = ope_hw_info; + bus_rd_reg_val = ope_hw_info->bus_rd_reg_val; + bus_rd_reg = ope_hw_info->bus_rd_reg; + + for (i = 0; i < bus_rd_reg_val->num_clients; i++) { + input_port_idx = + bus_rd_reg_val->rd_clients[i].input_port_id - 1; + in_port_to_rm = &bus_rd->in_port_to_rm[input_port_idx]; + if (bus_rd_reg_val->rd_clients[i].format_type & + BUS_RD_COMBO_BAYER_MASK) { + combo_idx = BUS_RD_BAYER; + rm_idx = in_port_to_rm->num_rm[combo_idx]; + in_port_to_rm->input_port_id = + bus_rd_reg_val->rd_clients[i].input_port_id; + in_port_to_rm->rm_port_id[combo_idx][rm_idx] = + bus_rd_reg_val->rd_clients[i].rm_port_id; + if (!in_port_to_rm->num_rm[combo_idx]) + in_port_to_rm->num_combos++; + in_port_to_rm->num_rm[combo_idx]++; + } + if (bus_rd_reg_val->rd_clients[i].format_type & + BUS_RD_COMBO_YUV_MASK) { + combo_idx = BUS_RD_YUV; + rm_idx = in_port_to_rm->num_rm[combo_idx]; + in_port_to_rm->input_port_id = + bus_rd_reg_val->rd_clients[i].input_port_id; + in_port_to_rm->rm_port_id[combo_idx][rm_idx] = + bus_rd_reg_val->rd_clients[i].rm_port_id; + if (!in_port_to_rm->num_rm[combo_idx]) + in_port_to_rm->num_combos++; + in_port_to_rm->num_rm[combo_idx]++; + } + } + + for (i = 0; i < OPE_IN_RES_MAX; i++) { + in_port_to_rm = &bus_rd->in_port_to_rm[i]; + CAM_DBG(CAM_OPE, "input port id = %d num_combos = %d", + in_port_to_rm->input_port_id, + in_port_to_rm->num_combos); + for (j = 0; j < in_port_to_rm->num_combos; j++) { + CAM_DBG(CAM_OPE, "combo idx = %d num_rms = %d", + j, in_port_to_rm->num_rm[j]); + for (k = 0; k < in_port_to_rm->num_rm[j]; k++) { + CAM_DBG(CAM_OPE, "rm port id = %d", + in_port_to_rm->rm_port_id[j][k]); + } + } + } + + return rc; +} + +static int cam_ope_bus_rd_isr(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + uint32_t irq_status; + struct cam_ope_bus_rd_reg *bus_rd_reg; + struct cam_ope_bus_rd_reg_val *bus_rd_reg_val; + struct cam_ope_irq_data *irq_data = data; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + bus_rd_reg = ope_hw_info->bus_rd_reg; + bus_rd_reg_val = ope_hw_info->bus_rd_reg_val; + + /* Read and Clear Top Interrupt status */ + irq_status = cam_io_r_mb(bus_rd_reg->base + bus_rd_reg->irq_status); + cam_io_w_mb(irq_status, + bus_rd_reg->base + bus_rd_reg->irq_clear); + + cam_io_w_mb(bus_rd_reg_val->irq_set_clear, + bus_rd_reg->base + bus_rd_reg->irq_cmd); + + if (irq_status & bus_rd_reg_val->rst_done) { + complete(&bus_rd->reset_complete); + CAM_ERR(CAM_OPE, "ope bus rd reset done"); + } + + if ((irq_status & bus_rd_reg_val->violation) == + bus_rd_reg_val->violation) { + irq_data->error = 1; + CAM_ERR(CAM_OPE, "ope bus rd CCIF vioalation"); + } + + return rc; +} + +int cam_ope_bus_rd_process(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t cmd_id, void *data) +{ + int rc = -EINVAL; + + switch (cmd_id) { + case OPE_HW_PROBE: + CAM_DBG(CAM_OPE, "OPE_HW_PROBE: E"); + rc = cam_ope_bus_rd_probe(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_PROBE: X"); + break; + case OPE_HW_INIT: + CAM_DBG(CAM_OPE, "OPE_HW_INIT: E"); + rc = cam_ope_bus_rd_init(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_INIT: X"); + break; + case OPE_HW_ACQUIRE: + CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: E"); + rc = cam_ope_bus_rd_acquire(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: X"); + break; + case OPE_HW_RELEASE: + CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: E"); + rc = cam_ope_bus_rd_release(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: X"); + break; + case OPE_HW_PREPARE: + CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: E"); + rc = cam_ope_bus_rd_prepare(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: X"); + break; + case OPE_HW_ISR: + rc = cam_ope_bus_rd_isr(ope_hw_info, 0, data); + break; + case OPE_HW_DEINIT: + case OPE_HW_START: + case OPE_HW_STOP: + case OPE_HW_FLUSH: + case OPE_HW_CLK_UPDATE: + case OPE_HW_BW_UPDATE: + case OPE_HW_RESET: + case OPE_HW_SET_IRQ_CB: + rc = 0; + CAM_DBG(CAM_OPE, "Unhandled cmds: %d", cmd_id); + break; + default: + CAM_ERR(CAM_OPE, "Unsupported cmd: %d", cmd_id); + break; + } + + return rc; +} + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h new file mode 100644 index 000000000000..15a45a6bea51 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef OPE_BUS_RD_H +#define OPE_BUS_RD_H + +#include +#include +#include +#include "ope_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" +#include "cam_soc_util.h" +#include "cam_context.h" +#include "cam_ope_context.h" +#include "cam_ope_hw_mgr.h" + + +/** + * struct ope_bus_rd_cdm_info + * + * @offset: Offset + * @addr: Address + * @len: Length + */ +struct ope_bus_rd_cdm_info { + uint32_t offset; + uint32_t *addr; + uint32_t len; +}; + +/** + * struct ope_bus_rd_io_port_cdm_info + * + * @num_frames_cmds: Number of frame commands + * @f_cdm_info: Frame cdm info + * @num_stripes: Number of stripes + * @num_s_cmd_bufs: Number of stripe commands + * @s_cdm_info: Stripe cdm info + * @go_cmd_addr: GO command address + * @go_cmd_len: GO command length + */ +struct ope_bus_rd_io_port_cdm_info { + uint32_t num_frames_cmds; + struct ope_bus_rd_cdm_info f_cdm_info[MAX_RD_CLIENTS]; + uint32_t num_stripes; + uint32_t num_s_cmd_bufs[OPE_MAX_STRIPES]; + struct ope_bus_rd_cdm_info s_cdm_info[OPE_MAX_STRIPES][MAX_RD_CLIENTS]; + uint32_t go_cmd_offset; + uint32_t *go_cmd_addr; + uint32_t go_cmd_len; +}; + +/** + * struct ope_bus_rd_io_port_cdm_batch + * + * num_batch: Number of batches + * io_port_cdm: CDM IO Port Info + */ +struct ope_bus_rd_io_port_cdm_batch { + uint32_t num_batch; + struct ope_bus_rd_io_port_cdm_info io_port_cdm[OPE_MAX_BATCH_SIZE]; +}; + +/** + * struct ope_bus_rd_rm + * + * @rm_port_id: RM port ID + * @format_type: Format type + */ +struct ope_bus_rd_rm { + uint32_t rm_port_id; + uint32_t format_type; +}; + +/** + * struct ope_bus_in_port_to_rm + * + * @input_port_id: Intput port ID + * @num_combos: Number of combos + * @num_rm: Number of RMs + * @rm_port_id: RM port Id + */ +struct ope_bus_in_port_to_rm { + uint32_t input_port_id; + uint32_t num_combos; + uint32_t num_rm[BUS_RD_COMBO_MAX]; + uint32_t rm_port_id[BUS_RD_COMBO_MAX][MAX_RD_CLIENTS]; +}; + +/** + * struct ope_bus_rd_io_port_info + * + * @pixel_pattern: Pixel pattern + * @input_port_id: Port Id + * @input_format_type: Format type + * @latency_buf_size: Latency buffer size + */ +struct ope_bus_rd_io_port_info { + uint32_t pixel_pattern[OPE_IN_RES_MAX]; + uint32_t input_port_id[OPE_IN_RES_MAX]; + uint32_t input_format_type[OPE_IN_RES_MAX]; + uint32_t latency_buf_size; +}; + +/** + * struct ope_bus_rd_ctx + * + * @ope_acquire: OPE acquire structure + * @security_flag: security flag + * @num_in_ports: Number of in ports + * @io_port_info: IO port info + * @io_port_cdm_batch: IO port cdm info + */ +struct ope_bus_rd_ctx { + struct ope_acquire_dev_info *ope_acquire; + bool security_flag; + uint32_t num_in_ports; + struct ope_bus_rd_io_port_info io_port_info; + struct ope_bus_rd_io_port_cdm_batch io_port_cdm_batch; +}; + +/** + * struct ope_bus_rd + * + * @ope_hw_info: OPE hardware info + * @in_port_to_rm: IO port to RM mapping + * @bus_rd_ctx: RM context + */ +struct ope_bus_rd { + struct ope_hw *ope_hw_info; + struct ope_bus_in_port_to_rm in_port_to_rm[OPE_IN_RES_MAX]; + struct ope_bus_rd_ctx bus_rd_ctx[OPE_CTX_MAX]; + struct completion reset_complete; +}; +#endif /* OPE_BUS_RD_H */ + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c new file mode 100644 index 000000000000..7a1a2ca7b9cc --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c @@ -0,0 +1,785 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "ope_core.h" +#include "ope_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "ope_hw.h" +#include "ope_dev_intf.h" +#include "ope_bus_wr.h" +#include "cam_cdm_util.h" + +static struct ope_bus_wr *wr_info; + +static int cam_ope_bus_en_port_idx( + struct cam_ope_request *ope_request, + uint32_t batch_idx, + uint32_t output_port_id) +{ + int i; + struct ope_io_buf *io_buf; + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx); + return -EINVAL; + } + + for (i = 0; i < ope_request->num_io_bufs[batch_idx]; i++) { + io_buf = &ope_request->io_buf[batch_idx][i]; + if (io_buf->direction != CAM_BUF_OUTPUT) + continue; + if (io_buf->resource_type == output_port_id) + return i; + } + + return -EINVAL; +} +static int cam_ope_bus_wr_out_port_idx(uint32_t output_port_id) +{ + int i; + + for (i = 0; i < OPE_OUT_RES_MAX; i++) + if (wr_info->out_port_to_wm[i].output_port_id == output_port_id) + return i; + + return -EINVAL; +} + + +static int cam_ope_bus_wr_subsample( + struct cam_ope_ctx *ctx_data, + struct ope_hw *ope_hw_info, + struct cam_ope_bus_wr_client_reg *wr_reg_client, + struct ope_io_buf *io_buf, + uint32_t *temp_reg, uint32_t count, + int plane_idx, int stripe_idx) +{ + int k, l; + struct cam_ope_bus_wr_reg *wr_reg; + struct cam_ope_bus_wr_reg_val *wr_reg_val; + + wr_reg = ope_hw_info->bus_wr_reg; + wr_reg_val = ope_hw_info->bus_wr_reg_val; + + if (plane_idx >= OPE_MAX_PLANES) { + CAM_ERR(CAM_OPE, "Invalid plane idx: %d", plane_idx); + return count; + } + k = plane_idx; + l = stripe_idx; + + /* subsample period and pattern */ + if ((ctx_data->ope_acquire.dev_type == + OPE_DEV_TYPE_OPE_RT) && l == 0) { + temp_reg[count++] = wr_reg->offset + + wr_reg_client->subsample_period; + temp_reg[count++] = io_buf->num_stripes[k]; + + temp_reg[count++] = wr_reg->offset + + wr_reg_client->subsample_pattern; + temp_reg[count++] = 1 << + (io_buf->num_stripes[k] - 1); + } else if ((ctx_data->ope_acquire.dev_type == + OPE_DEV_TYPE_OPE_NRT) && + ((l % + ctx_data->ope_acquire.nrt_stripes_for_arb) == + 0)) { + if (io_buf->num_stripes[k] >= + (l + + ctx_data->ope_acquire.nrt_stripes_for_arb)){ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->subsample_period; + temp_reg[count++] = + ctx_data->ope_acquire.nrt_stripes_for_arb; + + temp_reg[count++] = wr_reg->offset + + wr_reg_client->subsample_pattern; + temp_reg[count++] = 1 << + (ctx_data->ope_acquire.nrt_stripes_for_arb - + 1); + } else { + temp_reg[count++] = wr_reg->offset + + wr_reg_client->subsample_period; + temp_reg[count++] = io_buf->num_stripes[k] - l; + + /* subsample pattern */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->subsample_pattern; + temp_reg[count++] = 1 << (io_buf->num_stripes[k] - + l - 1); + } + } + return count; +} + +static int cam_ope_bus_wr_release(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0, i; + struct ope_acquire_dev_info *in_acquire; + struct ope_bus_wr_ctx *bus_wr_ctx; + + if (ctx_id < 0) { + CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id); + return -EINVAL; + } + + in_acquire = wr_info->bus_wr_ctx[ctx_id].ope_acquire; + wr_info->bus_wr_ctx[ctx_id].ope_acquire = NULL; + bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + bus_wr_ctx->num_out_ports = 0; + + for (i = 0; i < bus_wr_ctx->num_out_ports; i++) { + bus_wr_ctx->io_port_info.output_port_id[i] = 0; + bus_wr_ctx->io_port_info.output_format_type[i - 1] = 0; + bus_wr_ctx->io_port_info.pixel_pattern[i - 1] = 0; + } + + return rc; +} + +static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, + int32_t ctx_id, struct cam_ope_dev_prepare_req *prepare, + int batch_idx, int io_idx, + uint32_t *kmd_buf, uint32_t *num_stripes) +{ + int k, l, out_port_idx; + uint32_t idx; + uint32_t num_wm_ports; + uint32_t comb_idx; + uint32_t req_idx; + uint32_t temp_reg[128]; + uint32_t count = 0; + uint32_t temp = 0; + uint32_t wm_port_id; + uint32_t header_size; + struct cam_hw_prepare_update_args *prepare_args; + struct cam_ope_ctx *ctx_data; + struct cam_ope_request *ope_request; + struct ope_io_buf *io_buf; + struct ope_stripe_io *stripe_io; + struct ope_bus_wr_ctx *bus_wr_ctx; + struct cam_ope_bus_wr_reg *wr_reg; + struct cam_ope_bus_wr_client_reg *wr_reg_client; + struct cam_ope_bus_wr_reg_val *wr_reg_val; + struct cam_ope_bus_wr_client_reg_val *wr_res_val_client; + struct ope_bus_out_port_to_wm *out_port_to_wm; + struct ope_bus_wr_io_port_cdm_batch *io_port_cdm_batch; + struct ope_bus_wr_io_port_cdm_info *io_port_cdm; + struct cam_cdm_utils_ops *cdm_ops; + + + if (ctx_id < 0 || !prepare) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare); + return NULL; + } + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx); + return NULL; + } + + if (io_idx >= OPE_MAX_IO_BUFS) { + CAM_ERR(CAM_OPE, "Invalid IO idx: %d", io_idx); + return NULL; + } + + prepare_args = prepare->prepare_args; + ctx_data = prepare->ctx_data; + req_idx = prepare->req_idx; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + ope_request = ctx_data->req_list[req_idx]; + bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; + wr_reg = ope_hw_info->bus_wr_reg; + wr_reg_val = ope_hw_info->bus_wr_reg_val; + + CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d req_id = %lld offset = %d", + kmd_buf, req_idx, ope_request->request_id, + prepare->kmd_buf_offset); + + io_buf = &ope_request->io_buf[batch_idx][io_idx]; + CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d", + batch_idx, io_idx, io_buf->direction); + + io_port_cdm = + &bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; + out_port_idx = + cam_ope_bus_wr_out_port_idx(io_buf->resource_type); + if (out_port_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid idx for rsc type: %d", + io_buf->resource_type); + return NULL; + } + out_port_to_wm = &wr_info->out_port_to_wm[out_port_idx]; + comb_idx = BUS_WR_YUV; + num_wm_ports = out_port_to_wm->num_wm[comb_idx]; + + for (k = 0; k < io_buf->num_planes; k++) { + *num_stripes = io_buf->num_stripes[k]; + for (l = 0; l < io_buf->num_stripes[k]; l++) { + stripe_io = &io_buf->s_io[k][l]; + CAM_DBG(CAM_OPE, "comb_idx = %d p_idx = %d s_idx = %d", + comb_idx, k, l); + /* frame level info */ + /* stripe level info */ + wm_port_id = out_port_to_wm->wm_port_id[comb_idx][k]; + wr_reg_client = &wr_reg->wr_clients[wm_port_id]; + wr_res_val_client = &wr_reg_val->wr_clients[wm_port_id]; + + /* Core cfg: enable, Mode */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->core_cfg; + temp = 0; + if (!stripe_io->disable_bus) + temp = wr_res_val_client->core_cfg_en; + temp |= ((wr_res_val_client->mode & + wr_res_val_client->mode_mask) << + wr_res_val_client->mode_shift); + temp_reg[count++] = temp; + + /* Address of the Image */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->img_addr; + temp_reg[count++] = stripe_io->iova_addr; + + /* Buffer size */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->img_cfg; + temp = 0; + temp = stripe_io->width; + temp |= (stripe_io->height & + wr_res_val_client->height_mask) << + wr_res_val_client->height_shift; + temp_reg[count++] = temp; + + /* x_init */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->x_init; + temp_reg[count++] = stripe_io->x_init; + + /* stride */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->stride; + temp_reg[count++] = stripe_io->stride; + + /* pack cfg : Format and alignment */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->pack_cfg; + temp = 0; + temp |= ((stripe_io->pack_format & + wr_res_val_client->format_mask) << + wr_res_val_client->format_shift); + temp |= ((stripe_io->alignment & + wr_res_val_client->alignment_mask) << + wr_res_val_client->alignment_shift); + temp_reg[count++] = temp; + + /* subsample period and pattern */ + count = cam_ope_bus_wr_subsample( + ctx_data, ope_hw_info, + wr_reg_client, io_buf, + temp_reg, count, k, l); + + header_size = cdm_ops->cdm_get_cmd_header_size( + CAM_CDM_CMD_REG_RANDOM); + idx = io_port_cdm->num_s_cmd_bufs[l]; + io_port_cdm->s_cdm_info[l][idx].len = + sizeof(temp) * (count + header_size); + io_port_cdm->s_cdm_info[l][idx].offset = + prepare->kmd_buf_offset; + io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf; + io_port_cdm->num_s_cmd_bufs[l]++; + + kmd_buf = cdm_ops->cdm_write_regrandom( + kmd_buf, count/2, temp_reg); + prepare->kmd_buf_offset += ((count + header_size) * + sizeof(temp)); + + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", + batch_idx, io_idx, k, l); + CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", + count, temp_reg, header_size); + CAM_DBG(CAM_OPE, "header_size:%d", header_size); + + CAM_DBG(CAM_OPE, "WR cmd bufs = %d", + io_port_cdm->num_s_cmd_bufs[l]); + CAM_DBG(CAM_OPE, "off:%d len:%d", + io_port_cdm->s_cdm_info[l][idx].offset, + io_port_cdm->s_cdm_info[l][idx].len); + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", + batch_idx, io_idx, k, l); + count = 0; + } + } + + return kmd_buf; +} + +static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, + int32_t ctx_id, struct cam_ope_dev_prepare_req *prepare, + int batch_idx, int io_idx, + uint32_t *kmd_buf, uint32_t num_stripes) +{ + int k, l; + uint32_t idx; + uint32_t num_wm_ports; + uint32_t comb_idx; + uint32_t req_idx; + uint32_t temp_reg[128]; + uint32_t count = 0; + uint32_t temp = 0; + uint32_t wm_port_id; + uint32_t header_size; + struct cam_ope_ctx *ctx_data; + struct ope_bus_wr_ctx *bus_wr_ctx; + struct cam_ope_bus_wr_reg *wr_reg; + struct cam_ope_bus_wr_client_reg *wr_reg_client; + struct ope_bus_out_port_to_wm *out_port_to_wm; + struct ope_bus_wr_io_port_cdm_batch *io_port_cdm_batch; + struct ope_bus_wr_io_port_cdm_info *io_port_cdm; + struct cam_cdm_utils_ops *cdm_ops; + + + if (ctx_id < 0 || !prepare) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare); + return NULL; + } + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx); + return NULL; + } + + ctx_data = prepare->ctx_data; + req_idx = prepare->req_idx; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; + wr_reg = ope_hw_info->bus_wr_reg; + + CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d", + kmd_buf, req_idx, prepare->kmd_buf_offset); + + io_port_cdm = + &bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; + out_port_to_wm = &wr_info->out_port_to_wm[io_idx]; + comb_idx = BUS_WR_YUV; + num_wm_ports = out_port_to_wm->num_wm[comb_idx]; + + for (k = 0; k < num_wm_ports; k++) { + for (l = 0; l < num_stripes; l++) { + CAM_DBG(CAM_OPE, "comb_idx = %d p_idx = %d s_idx = %d", + comb_idx, k, l); + /* frame level info */ + /* stripe level info */ + wm_port_id = out_port_to_wm->wm_port_id[comb_idx][k]; + wr_reg_client = &wr_reg->wr_clients[wm_port_id]; + + /* Core cfg: enable, Mode */ + temp_reg[count++] = wr_reg->offset + + wr_reg_client->core_cfg; + temp_reg[count++] = 0; + + header_size = cdm_ops->cdm_get_cmd_header_size( + CAM_CDM_CMD_REG_RANDOM); + idx = io_port_cdm->num_s_cmd_bufs[l]; + io_port_cdm->s_cdm_info[l][idx].len = + sizeof(temp) * (count + header_size); + io_port_cdm->s_cdm_info[l][idx].offset = + prepare->kmd_buf_offset; + io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf; + io_port_cdm->num_s_cmd_bufs[l]++; + + kmd_buf = cdm_ops->cdm_write_regrandom( + kmd_buf, count/2, temp_reg); + prepare->kmd_buf_offset += ((count + header_size) * + sizeof(temp)); + + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", + batch_idx, io_idx, k, l); + CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", + count, temp_reg, header_size); + CAM_DBG(CAM_OPE, "header_size:%d", header_size); + + CAM_DBG(CAM_OPE, "WR cmd bufs = %d", + io_port_cdm->num_s_cmd_bufs[l]); + CAM_DBG(CAM_OPE, "off:%d len:%d", + io_port_cdm->s_cdm_info[l][idx].offset, + io_port_cdm->s_cdm_info[l][idx].len); + CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", + batch_idx, io_idx, k, l); + count = 0; + } + } + + prepare->wr_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; + + return kmd_buf; +} + +static int cam_ope_bus_wr_prepare(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + int i, j = 0; + uint32_t req_idx; + uint32_t *kmd_buf; + struct cam_ope_dev_prepare_req *prepare; + struct cam_ope_ctx *ctx_data; + struct cam_ope_request *ope_request; + struct ope_io_buf *io_buf; + uint32_t temp; + int io_buf_idx; + uint32_t num_stripes = 0; + struct ope_bus_wr_io_port_cdm_batch *io_port_cdm_batch; + struct ope_bus_wr_ctx *bus_wr_ctx; + + if (ctx_id < 0 || !data) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); + return -EINVAL; + } + prepare = data; + ctx_data = prepare->ctx_data; + req_idx = prepare->req_idx; + bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + + ope_request = ctx_data->req_list[req_idx]; + kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + (prepare->kmd_buf_offset / sizeof(temp)); + + + CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d req_id = %lld offset = %d", + kmd_buf, req_idx, ope_request->request_id, + prepare->kmd_buf_offset); + + io_port_cdm_batch = &wr_info->bus_wr_ctx[ctx_id].io_port_cdm_batch; + memset(io_port_cdm_batch, 0, + sizeof(struct ope_bus_wr_io_port_cdm_batch)); + + for (i = 0; i < ope_request->num_batch; i++) { + for (j = 0; j < ope_request->num_io_bufs[i]; j++) { + io_buf = &ope_request->io_buf[i][j]; + CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d", + i, j, io_buf->direction); + if (io_buf->direction != CAM_BUF_OUTPUT) + continue; + + kmd_buf = cam_ope_bus_wr_update(ope_hw_info, + ctx_id, prepare, i, j, + kmd_buf, &num_stripes); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + } + } + + /* Disable WMs which are not enabled */ + for (i = 0; i < ope_request->num_batch; i++) { + for (j = OPE_OUT_RES_VIDEO; j <= OPE_OUT_RES_MAX; j++) { + io_buf_idx = cam_ope_bus_en_port_idx(ope_request, i, j); + if (io_buf_idx >= 0) + continue; + + io_buf_idx = cam_ope_bus_wr_out_port_idx(j); + if (io_buf_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid idx for rsc type:%d", + j); + return io_buf_idx; + } + kmd_buf = cam_ope_bus_wm_disable(ope_hw_info, + ctx_id, prepare, i, io_buf_idx, + kmd_buf, num_stripes); + } + } + prepare->wr_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; + +end: + return rc; +} + +static int cam_ope_bus_wr_acquire(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0, i; + struct ope_acquire_dev_info *in_acquire; + struct ope_bus_wr_ctx *bus_wr_ctx; + struct ope_bus_out_port_to_wm *out_port_to_wr; + int combo_idx; + int out_port_idx; + + if (ctx_id < 0 || !data) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); + return -EINVAL; + } + + wr_info->bus_wr_ctx[ctx_id].ope_acquire = data; + in_acquire = data; + bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + bus_wr_ctx->num_out_ports = in_acquire->num_out_res; + bus_wr_ctx->security_flag = in_acquire->secure_mode; + + for (i = 0; i < in_acquire->num_out_res; i++) { + if (!in_acquire->out_res[i].width) + continue; + + CAM_DBG(CAM_OPE, "i = %d format = %u width = %x height = %x", + i, in_acquire->out_res[i].format, + in_acquire->out_res[i].width, + in_acquire->out_res[i].height); + CAM_DBG(CAM_OPE, "pix_pattern:%u alignment:%u packer_format:%u", + in_acquire->out_res[i].pixel_pattern, + in_acquire->out_res[i].alignment, + in_acquire->out_res[i].packer_format); + CAM_DBG(CAM_OPE, "subsample_period = %u subsample_pattern = %u", + in_acquire->out_res[i].subsample_period, + in_acquire->out_res[i].subsample_pattern); + + out_port_idx = + cam_ope_bus_wr_out_port_idx(in_acquire->out_res[i].res_id); + if (out_port_idx < 0) { + CAM_DBG(CAM_OPE, "Invalid in_port_idx: %d", + in_acquire->out_res[i].res_id); + rc = -EINVAL; + goto end; + } + out_port_to_wr = &wr_info->out_port_to_wm[out_port_idx]; + combo_idx = BUS_WR_YUV; + if (!out_port_to_wr->num_wm[combo_idx]) { + CAM_DBG(CAM_OPE, "Invalid format for Input port"); + rc = -EINVAL; + goto end; + } + + bus_wr_ctx->io_port_info.output_port_id[i] = + in_acquire->out_res[i].res_id; + bus_wr_ctx->io_port_info.output_format_type[i] = + in_acquire->out_res[i].format; + if (in_acquire->out_res[i].pixel_pattern > + PIXEL_PATTERN_CRYCBY) { + CAM_DBG(CAM_OPE, "Invalid pix pattern = %u", + in_acquire->out_res[i].pixel_pattern); + rc = -EINVAL; + goto end; + } + + bus_wr_ctx->io_port_info.pixel_pattern[i] = + in_acquire->out_res[i].pixel_pattern; + bus_wr_ctx->io_port_info.latency_buf_size = 4096; + CAM_DBG(CAM_OPE, "i:%d port_id = %u format %u pix_pattern = %u", + i, bus_wr_ctx->io_port_info.output_port_id[i], + bus_wr_ctx->io_port_info.output_format_type[i], + bus_wr_ctx->io_port_info.pixel_pattern[i]); + CAM_DBG(CAM_OPE, "latency_buf_size = %u", + bus_wr_ctx->io_port_info.latency_buf_size); + } + +end: + return rc; +} + +static int cam_ope_bus_wr_init(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + struct cam_ope_bus_wr_reg_val *bus_wr_reg_val; + struct cam_ope_bus_wr_reg *bus_wr_reg; + struct cam_ope_dev_init *dev_init = data; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + wr_info->ope_hw_info = ope_hw_info; + bus_wr_reg_val = ope_hw_info->bus_wr_reg_val; + bus_wr_reg = ope_hw_info->bus_wr_reg; + bus_wr_reg->base = dev_init->core_info->ope_hw_info->ope_bus_wr_base; + + cam_io_w_mb(bus_wr_reg_val->irq_mask_0, + ope_hw_info->bus_wr_reg->base + bus_wr_reg->irq_mask_0); + cam_io_w_mb(bus_wr_reg_val->irq_mask_1, + ope_hw_info->bus_wr_reg->base + bus_wr_reg->irq_mask_1); + + return rc; +} + +static int cam_ope_bus_wr_probe(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0, i, j, combo_idx, k; + struct cam_ope_bus_wr_reg_val *bus_wr_reg_val; + struct ope_bus_out_port_to_wm *out_port_to_wm; + uint32_t output_port_idx; + uint32_t wm_idx; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + wr_info = kzalloc(sizeof(struct ope_bus_wr), GFP_KERNEL); + if (!wr_info) { + CAM_ERR(CAM_OPE, "Out of memory"); + return -ENOMEM; + } + + wr_info->ope_hw_info = ope_hw_info; + bus_wr_reg_val = ope_hw_info->bus_wr_reg_val; + + for (i = 0; i < bus_wr_reg_val->num_clients; i++) { + output_port_idx = + bus_wr_reg_val->wr_clients[i].output_port_id - 1; + out_port_to_wm = &wr_info->out_port_to_wm[output_port_idx]; + combo_idx = BUS_WR_YUV; + wm_idx = out_port_to_wm->num_wm[combo_idx]; + out_port_to_wm->output_port_id = + bus_wr_reg_val->wr_clients[i].output_port_id; + out_port_to_wm->wm_port_id[combo_idx][wm_idx] = + bus_wr_reg_val->wr_clients[i].wm_port_id; + if (!out_port_to_wm->num_wm[combo_idx]) + out_port_to_wm->num_combos++; + out_port_to_wm->num_wm[combo_idx]++; + } + + for (i = 0; i < OPE_OUT_RES_MAX; i++) { + out_port_to_wm = &wr_info->out_port_to_wm[i]; + CAM_DBG(CAM_OPE, "output port id = %d num_combos = %d", + out_port_to_wm->output_port_id, + out_port_to_wm->num_combos); + for (j = 0; j < out_port_to_wm->num_combos; j++) { + CAM_DBG(CAM_OPE, "combo idx = %d num_wms = %d", + j, out_port_to_wm->num_wm[j]); + for (k = 0; k < out_port_to_wm->num_wm[j]; k++) { + CAM_DBG(CAM_OPE, "wm port id = %d", + out_port_to_wm->wm_port_id[j][k]); + } + } + } + + return rc; +} + +static int cam_ope_bus_wr_isr(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + uint32_t irq_status_0, irq_status_1; + struct cam_ope_bus_wr_reg *bus_wr_reg; + struct cam_ope_bus_wr_reg_val *bus_wr_reg_val; + struct cam_ope_irq_data *irq_data = data; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + bus_wr_reg = ope_hw_info->bus_wr_reg; + bus_wr_reg_val = ope_hw_info->bus_wr_reg_val; + + /* Read and Clear Top Interrupt status */ + irq_status_0 = cam_io_r_mb(bus_wr_reg->base + bus_wr_reg->irq_status_0); + irq_status_1 = cam_io_r_mb(bus_wr_reg->base + bus_wr_reg->irq_status_1); + cam_io_w_mb(irq_status_0, + bus_wr_reg->base + bus_wr_reg->irq_clear_0); + cam_io_w_mb(irq_status_1, + bus_wr_reg->base + bus_wr_reg->irq_clear_1); + + cam_io_w_mb(bus_wr_reg_val->irq_set_clear, + bus_wr_reg->base + bus_wr_reg->irq_cmd); + + if (irq_status_0 & bus_wr_reg_val->cons_violation) { + irq_data->error = 1; + CAM_ERR(CAM_OPE, "ope bus wr cons_violation"); + } + + if (irq_status_0 & bus_wr_reg_val->violation) { + irq_data->error = 1; + CAM_ERR(CAM_OPE, "ope bus wr vioalation"); + } + + if (irq_status_0 & bus_wr_reg_val->img_size_violation) { + irq_data->error = 1; + CAM_ERR(CAM_OPE, "ope bus wr img_size_violation"); + } + + return rc; +} + +int cam_ope_bus_wr_process(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t cmd_id, void *data) +{ + int rc = 0; + + switch (cmd_id) { + case OPE_HW_PROBE: + CAM_DBG(CAM_OPE, "OPE_HW_PROBE: E"); + rc = cam_ope_bus_wr_probe(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_PROBE: X"); + break; + case OPE_HW_INIT: + CAM_DBG(CAM_OPE, "OPE_HW_INIT: E"); + rc = cam_ope_bus_wr_init(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_INIT: X"); + break; + case OPE_HW_ACQUIRE: + CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: E"); + rc = cam_ope_bus_wr_acquire(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: X"); + break; + case OPE_HW_RELEASE: + CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: E"); + rc = cam_ope_bus_wr_release(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: X"); + break; + case OPE_HW_PREPARE: + CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: E"); + rc = cam_ope_bus_wr_prepare(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: X"); + break; + case OPE_HW_DEINIT: + case OPE_HW_START: + case OPE_HW_STOP: + case OPE_HW_FLUSH: + case OPE_HW_CLK_UPDATE: + case OPE_HW_BW_UPDATE: + case OPE_HW_RESET: + case OPE_HW_SET_IRQ_CB: + rc = 0; + CAM_DBG(CAM_OPE, "Unhandled cmds: %d", cmd_id); + break; + case OPE_HW_ISR: + rc = cam_ope_bus_wr_isr(ope_hw_info, 0, NULL); + break; + default: + CAM_ERR(CAM_OPE, "Unsupported cmd: %d", cmd_id); + break; + } + + return rc; +} + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h new file mode 100644 index 000000000000..0eb052b1687b --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef OPE_BUS_WR_H +#define OPE_BUS_WR_H + +#include +#include +#include +#include "ope_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" +#include "cam_soc_util.h" +#include "cam_context.h" +#include "cam_ope_context.h" +#include "cam_ope_hw_mgr.h" + +/** + * struct ope_bus_wr_cdm_info + * + * @offset: Offset + * @addr: Address + * @len: Length + */ +struct ope_bus_wr_cdm_info { + uint32_t offset; + uint32_t *addr; + uint32_t len; +}; + +/** + * struct ope_bus_wr_io_port_cdm_info + * + * @num_frames_cmds: Number of frame commands + * @f_cdm_info: Frame cdm info + * @num_stripes: Number of stripes + * @num_s_cmd_bufs: Number of stripe commands + * @s_cdm_info: Stripe cdm info + * @go_cmd_addr: GO command address + * @go_cmd_len: GO command length + */ +struct ope_bus_wr_io_port_cdm_info { + uint32_t num_frames_cmds; + struct ope_bus_wr_cdm_info f_cdm_info[MAX_WR_CLIENTS]; + uint32_t num_stripes; + uint32_t num_s_cmd_bufs[OPE_MAX_STRIPES]; + struct ope_bus_wr_cdm_info s_cdm_info[OPE_MAX_STRIPES][MAX_WR_CLIENTS]; + uint32_t *go_cmd_addr; + uint32_t go_cmd_len; +}; + +/** + * struct ope_bus_wr_io_port_cdm_batch + * + * num_batch: Number of batches + * io_port_cdm: CDM IO Port Info + */ +struct ope_bus_wr_io_port_cdm_batch { + uint32_t num_batch; + struct ope_bus_wr_io_port_cdm_info io_port_cdm[OPE_MAX_BATCH_SIZE]; +}; + +/** + * struct ope_bus_wr_wm + * + * @wm_port_id: WM port ID + * @format_type: Format type + */ +struct ope_bus_wr_wm { + uint32_t wm_port_id; + uint32_t format_type; +}; + +/** + * struct ope_bus_out_port_to_wm + * + * @output_port_id: Output port ID + * @num_combos: Number of combos + * @num_wm: Number of WMs + * @wm_port_id: WM port Id + */ +struct ope_bus_out_port_to_wm { + uint32_t output_port_id; + uint32_t num_combos; + uint32_t num_wm[BUS_WR_COMBO_MAX]; + uint32_t wm_port_id[BUS_WR_COMBO_MAX][MAX_WR_CLIENTS]; +}; + +/** + * struct ope_bus_wr_io_port_info + * + * @pixel_pattern: Pixel pattern + * @output_port_id: Port Id + * @output_format_type: Format type + * @latency_buf_size: Latency buffer size + */ +struct ope_bus_wr_io_port_info { + uint32_t pixel_pattern[OPE_OUT_RES_MAX]; + uint32_t output_port_id[OPE_OUT_RES_MAX]; + uint32_t output_format_type[OPE_OUT_RES_MAX]; + uint32_t latency_buf_size; +}; + +/** + * struct ope_bus_wr_ctx + * + * @ope_acquire: OPE acquire structure + * @security_flag: security flag + * @num_out_ports: Number of out ports + * @io_port_info: IO port info + * @io_port_cdm_batch: IO port cdm info + */ +struct ope_bus_wr_ctx { + struct ope_acquire_dev_info *ope_acquire; + bool security_flag; + uint32_t num_out_ports; + struct ope_bus_wr_io_port_info io_port_info; + struct ope_bus_wr_io_port_cdm_batch io_port_cdm_batch; +}; + +/** + * struct ope_bus_wr + * + * @ope_hw_info: OPE hardware info + * @out_port_to_wm: IO port to WM mapping + * @bus_wr_ctx: WM context + */ +struct ope_bus_wr { + struct ope_hw *ope_hw_info; + struct ope_bus_out_port_to_wm out_port_to_wm[OPE_OUT_RES_MAX]; + struct ope_bus_wr_ctx bus_wr_ctx[OPE_CTX_MAX]; +}; + +#endif /* OPE_BUS_WR_H */ + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c new file mode 100644 index 000000000000..d2af4ebd2f1c --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -0,0 +1,1781 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "ope_core.h" +#include "ope_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "ope_hw.h" +#include "ope_dev_intf.h" +#include "cam_cdm_util.h" +#include "ope_bus_rd.h" +#include "ope_bus_wr.h" + +static int cam_ope_caps_vote(struct cam_ope_device_core_info *core_info, + struct cam_ope_dev_bw_update *cpas_vote) +{ + int rc = 0; + + if (cpas_vote->ahb_vote_valid) + rc = cam_cpas_update_ahb_vote(core_info->cpas_handle, + &cpas_vote->ahb_vote); + if (cpas_vote->axi_vote_valid) + rc = cam_cpas_update_axi_vote(core_info->cpas_handle, + &cpas_vote->axi_vote); + if (rc) + CAM_ERR(CAM_OPE, "cpas vote is failed: %d", rc); + + return rc; +} + +int cam_ope_get_hw_caps(void *hw_priv, void *get_hw_cap_args, + uint32_t arg_size) +{ + struct cam_hw_info *ope_dev = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ope_device_core_info *core_info = NULL; + struct ope_hw_ver *ope_hw_ver; + struct cam_ope_top_reg_val *top_reg_val; + + if (!hw_priv) { + CAM_ERR(CAM_OPE, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &ope_dev->soc_info; + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_OPE, "soc_info = %x core_info = %x", + soc_info, core_info); + return -EINVAL; + } + + if (!get_hw_cap_args) { + CAM_ERR(CAM_OPE, "Invalid caps"); + return -EINVAL; + } + + top_reg_val = core_info->ope_hw_info->ope_hw->top_reg_val; + ope_hw_ver = get_hw_cap_args; + ope_hw_ver->hw_type = core_info->hw_type; + ope_hw_ver->hw_ver.major = + (core_info->hw_version & top_reg_val->major_mask) >> + top_reg_val->major_shift; + ope_hw_ver->hw_ver.minor = + (core_info->hw_version & top_reg_val->minor_mask) >> + top_reg_val->minor_shift; + ope_hw_ver->hw_ver.incr = + (core_info->hw_version & top_reg_val->incr_mask) >> + top_reg_val->incr_shift; + + return 0; +} + +int cam_ope_start(void *hw_priv, void *start_args, uint32_t arg_size) +{ + return 0; +} + +int cam_ope_stop(void *hw_priv, void *start_args, uint32_t arg_size) +{ + return 0; +} + +int cam_ope_flush(void *hw_priv, void *flush_args, uint32_t arg_size) +{ + return 0; +} + +static int cam_ope_dev_process_init(struct ope_hw *ope_hw, + void *cmd_args) +{ + int rc = 0; + + rc = cam_ope_top_process(ope_hw, 0, OPE_HW_INIT, cmd_args); + if (rc) + goto top_init_fail; + + rc = cam_ope_bus_rd_process(ope_hw, 0, OPE_HW_INIT, cmd_args); + if (rc) + goto bus_rd_init_fail; + + rc = cam_ope_bus_wr_process(ope_hw, 0, OPE_HW_INIT, cmd_args); + if (rc) + goto bus_wr_init_fail; + + return rc; + +bus_wr_init_fail: + rc = cam_ope_bus_rd_process(ope_hw, 0, + OPE_HW_DEINIT, NULL); +bus_rd_init_fail: + rc = cam_ope_top_process(ope_hw, 0, + OPE_HW_DEINIT, NULL); +top_init_fail: + return rc; +} + +static int cam_ope_process_init(struct ope_hw *ope_hw, + void *cmd_args, bool hfi_en) +{ + if (!hfi_en) + return cam_ope_dev_process_init(ope_hw, cmd_args); + + CAM_ERR(CAM_OPE, "hfi_en is not supported"); + return -EINVAL; +} + +int cam_ope_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *ope_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ope_device_core_info *core_info = NULL; + struct cam_ope_cpas_vote cpas_vote; + int rc = 0; + struct cam_ope_dev_init *init; + struct ope_hw *ope_hw; + + if (!device_priv) { + CAM_ERR(CAM_OPE, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &ope_dev->soc_info; + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_OPE, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + ope_hw = core_info->ope_hw_info->ope_hw; + + + cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; + cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.axi_vote.num_paths = 1; + cpas_vote.axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_ALL; + cpas_vote.axi_vote.axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + cpas_vote.axi_vote.axi_path[0].camnoc_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote.ahb_vote, &cpas_vote.axi_vote); + if (rc) { + CAM_ERR(CAM_OPE, "cpass start failed: %d", rc); + return rc; + } + core_info->cpas_start = true; + + rc = cam_ope_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_OPE, "soc enable is failed : %d", rc); + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_OPE, "cpas stop is failed"); + else + core_info->cpas_start = false; + } else { + core_info->clk_enable = true; + } + + init = init_hw_args; + + core_info->ope_hw_info->hfi_en = init->hfi_en; + init->core_info = core_info; + + rc = cam_ope_process_init(ope_hw, init_hw_args, init->hfi_en); + + return rc; +} + +int cam_ope_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *ope_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ope_device_core_info *core_info = NULL; + int rc = 0; + + if (!device_priv) { + CAM_ERR(CAM_OPE, "Invalid cam_dev_info"); + return -EINVAL; + } + + soc_info = &ope_dev->soc_info; + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_OPE, "soc_info = %pK core_info = %pK", + soc_info, core_info); + return -EINVAL; + } + + rc = cam_ope_disable_soc_resources(soc_info, core_info->clk_enable); + if (rc) + CAM_ERR(CAM_OPE, "soc disable is failed : %d", rc); + core_info->clk_enable = false; + + if (core_info->cpas_start) { + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_OPE, "cpas stop is failed"); + else + core_info->cpas_start = false; + } + + return rc; +} + +static int cam_ope_dev_process_reset(struct ope_hw *ope_hw, void *cmd_args) +{ + int rc = 0; + + rc = cam_ope_top_process(ope_hw, -1, + OPE_HW_RESET, NULL); + + return rc; +} + +static int cam_ope_dev_process_release(struct ope_hw *ope_hw, void *cmd_args) +{ + int rc = 0; + struct cam_ope_dev_release *ope_dev_release; + + ope_dev_release = cmd_args; + rc = cam_ope_top_process(ope_hw, ope_dev_release->ctx_id, + OPE_HW_RELEASE, NULL); + + rc |= cam_ope_bus_rd_process(ope_hw, ope_dev_release->ctx_id, + OPE_HW_RELEASE, NULL); + + rc |= cam_ope_bus_wr_process(ope_hw, ope_dev_release->ctx_id, + OPE_HW_RELEASE, NULL); + + return rc; +} + +static int cam_ope_dev_process_acquire(struct ope_hw *ope_hw, void *cmd_args) +{ + int rc = 0; + struct cam_ope_dev_acquire *ope_dev_acquire; + + if (!cmd_args || !ope_hw) { + CAM_ERR(CAM_OPE, "Invalid arguments: %pK %pK", + cmd_args, ope_hw); + return -EINVAL; + } + + ope_dev_acquire = cmd_args; + rc = cam_ope_top_process(ope_hw, ope_dev_acquire->ctx_id, + OPE_HW_ACQUIRE, ope_dev_acquire->ope_acquire); + if (rc) + goto top_acquire_fail; + + rc = cam_ope_bus_rd_process(ope_hw, ope_dev_acquire->ctx_id, + OPE_HW_ACQUIRE, ope_dev_acquire->ope_acquire); + if (rc) + goto bus_rd_acquire_fail; + + rc = cam_ope_bus_wr_process(ope_hw, ope_dev_acquire->ctx_id, + OPE_HW_ACQUIRE, ope_dev_acquire->ope_acquire); + if (rc) + goto bus_wr_acquire_fail; + + return 0; + +bus_wr_acquire_fail: + rc = cam_ope_bus_rd_process(ope_hw, ope_dev_acquire->ctx_id, + OPE_HW_RELEASE, ope_dev_acquire->ope_acquire); +bus_rd_acquire_fail: + rc = cam_ope_top_process(ope_hw, ope_dev_acquire->ctx_id, + OPE_HW_RELEASE, ope_dev_acquire->ope_acquire); + if (rc) + goto top_acquire_fail; + +top_acquire_fail: + return rc; +} + +static int cam_ope_dev_prepare_cdm_request( + struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_prepare_update_args *prepare_args, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t kmd_buf_offset, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req, + uint32_t len, bool arbitrate) +{ + int i; + struct cam_ope_request *ope_request; + struct cam_cdm_bl_request *cdm_cmd; + uint32_t *kmd_buf; + + ope_request = ctx_data->req_list[req_idx]; + cdm_cmd = ope_request->cdm_cmd; + kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + kmd_buf_offset; + + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_HW_IOVA; + cdm_cmd->flag = true; + cdm_cmd->userdata = ctx_data; + cdm_cmd->cookie = req_idx; + cdm_cmd->gen_irq_arb = true; + + i = cdm_cmd->cmd_arrary_count; + cdm_cmd->cmd[i].bl_addr.hw_iova = + (uint32_t *)ope_request->ope_kmd_buf.iova_cdm_addr; + cdm_cmd->cmd[i].offset = kmd_buf_offset; + cdm_cmd->cmd[i].len = len; + cdm_cmd->cmd[i].arbitrate = arbitrate; + + cdm_cmd->cmd_arrary_count++; + + CAM_DBG(CAM_OPE, "CDM cmd:Req idx = %d req_id = %lld array cnt = %d", + cdm_cmd->cookie, ope_request->request_id, + cdm_cmd->cmd_arrary_count); + CAM_DBG(CAM_OPE, "CDM cmd:mem_hdl = %d offset = %d len = %d, iova 0x%x", + ope_request->ope_kmd_buf.mem_handle, kmd_buf_offset, len, + cdm_cmd->cmd[i].bl_addr.hw_iova); + + return 0; +} + +static int dump_dmi_cmd(uint32_t print_idx, + uint32_t *print_ptr, struct cdm_dmi_cmd *dmi_cmd, + uint32_t *temp) +{ + CAM_DBG(CAM_OPE, "%d:dma_ptr:%x l:%d", + print_idx, print_ptr, + dmi_cmd->length); + CAM_DBG(CAM_OPE, "%d:cmd:%hhx addr:%x", + print_ptr, dmi_cmd->cmd, + dmi_cmd->addr); + CAM_DBG(CAM_OPE, "%d: dmiadr:%x sel:%d", + print_idx, dmi_cmd->DMIAddr, + dmi_cmd->DMISel); + CAM_DBG(CAM_OPE, "%d: %x %x %x", + print_idx, + temp[0], temp[1], temp[2]); + + return 0; +} + +static int dump_frame_direct(uint32_t print_idx, + uint32_t *print_ptr, + struct ope_frame_process *frm_proc, + int batch_idx, int cmd_buf_idx) +{ + int len; + + if (cmd_buf_idx >= OPE_MAX_CMD_BUFS || + batch_idx >= OPE_MAX_BATCH_SIZE) + return 0; + + len = frm_proc->cmd_buf[batch_idx][cmd_buf_idx].length / 4; + CAM_DBG(CAM_OPE, "Frame DB : direct: E"); + for (print_idx = 0; print_idx < len; print_idx++) + CAM_DBG(CAM_OPE, "%d: %x", print_idx, print_ptr[print_idx]); + CAM_DBG(CAM_OPE, "Frame DB : direct: X"); + + return 0; +} + +static int dump_frame_cmd(struct ope_frame_process *frm_proc, + int i, int j, uint64_t iova_addr, uint32_t *kmd_buf, uint32_t buf_len) +{ + if (j >= OPE_MAX_CMD_BUFS || i >= OPE_MAX_BATCH_SIZE) + return 0; + + CAM_DBG(CAM_OPE, "Frame DB:scope:%d buffer:%d type:%d", + frm_proc->cmd_buf[i][j].cmd_buf_scope, + frm_proc->cmd_buf[i][j].cmd_buf_buffered, + frm_proc->cmd_buf[i][j].type); + CAM_DBG(CAM_OPE, "kmdbuf:%x memhdl:%x iova:%x %pK", + kmd_buf, + frm_proc->cmd_buf[i][j].mem_handle, + iova_addr, iova_addr); + CAM_DBG(CAM_OPE, "buflen:%d len:%d offset:%d", + buf_len, + frm_proc->cmd_buf[i][j].length, + frm_proc->cmd_buf[i][j].offset); + + return 0; +} + +static int dump_stripe_cmd(struct ope_frame_process *frm_proc, + uint32_t stripe_idx, int i, int k, uint64_t iova_addr, + uint32_t *kmd_buf, uint32_t buf_len) +{ + if (k >= OPE_MAX_CMD_BUFS) + return 0; + + CAM_DBG(CAM_OPE, "Stripe:%d scope:%d buffer:%d", + stripe_idx, + frm_proc->cmd_buf[i][k].cmd_buf_scope, + frm_proc->cmd_buf[i][k].cmd_buf_buffered); + CAM_DBG(CAM_OPE, "type:%d kmdbuf:%x memhdl:%x", + frm_proc->cmd_buf[i][k].type, kmd_buf, + frm_proc->cmd_buf[i][k].mem_handle); + CAM_DBG(CAM_OPE, "iova:%x %pK buflen:%d len:%d", + iova_addr, iova_addr, buf_len, + frm_proc->cmd_buf[i][k].length); + CAM_DBG(CAM_OPE, "offset:%d", + frm_proc->cmd_buf[i][k].offset); + return 0; +} + +static uint32_t *ope_create_frame_cmd_prefetch_dis( + struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t *kmd_buf, uint32_t buffered, int batch_idx, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int rc = 0, i, j; + uint32_t temp[3]; + struct cam_ope_request *ope_request; + struct cdm_dmi_cmd *dmi_cmd; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + uint64_t iova_addr; + uintptr_t cpu_addr; + size_t buf_len; + uint32_t print_idx; + uint32_t *print_ptr; + int num_dmi = 0; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[0]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[0]; + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid input: %d", batch_idx); + return NULL; + } + + i = batch_idx; + + for (j = 0; j < frm_proc->num_cmd_bufs[i]; j++) { + if (frm_proc->cmd_buf[i][j].cmd_buf_scope != + OPE_CMD_BUF_SCOPE_FRAME) + continue; + + if (frm_proc->cmd_buf[i][j].cmd_buf_usage == + OPE_CMD_BUF_KMD || + frm_proc->cmd_buf[i][j].cmd_buf_usage == + OPE_CMD_BUF_DEBUG) + continue; + + if (frm_proc->cmd_buf[i][j].prefetch_disable && + frm_proc->cmd_buf[i][j].cmd_buf_buffered != + buffered) + continue; + + if (!frm_proc->cmd_buf[i][j].mem_handle) + continue; + + rc = cam_mem_get_io_buf( + frm_proc->cmd_buf[i][j].mem_handle, + hw_mgr->iommu_cdm_hdl, &iova_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + return NULL; + } + iova_addr = iova_addr + frm_proc->cmd_buf[i][j].offset; + + rc = cam_mem_get_cpu_buf( + frm_proc->cmd_buf[i][j].mem_handle, + &cpu_addr, &buf_len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + return NULL; + } + + cpu_addr = cpu_addr + frm_proc->cmd_buf[i][j].offset; + if (frm_proc->cmd_buf[i][j].type == + OPE_CMD_BUF_TYPE_DIRECT) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + iova_addr, + frm_proc->cmd_buf[i][j].length); + print_ptr = (uint32_t *)cpu_addr; + dump_frame_direct(print_idx, print_ptr, + frm_proc, i, j); + } else { + num_dmi = frm_proc->cmd_buf[i][j].length / + sizeof(struct cdm_dmi_cmd); + CAM_DBG(CAM_OPE, "Frame DB : In direct: E"); + print_ptr = (uint32_t *)cpu_addr; + for (print_idx = 0; + print_idx < num_dmi; print_idx++) { + memcpy(temp, (const void *)print_ptr, + sizeof(struct cdm_dmi_cmd)); + dmi_cmd = (struct cdm_dmi_cmd *)temp; + kmd_buf = cdm_ops->cdm_write_dmi( + kmd_buf, + 0, dmi_cmd->DMIAddr, + dmi_cmd->DMISel, dmi_cmd->addr, + dmi_cmd->length); + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); + print_ptr += + sizeof(struct cdm_dmi_cmd) / + sizeof(uint32_t); + } + CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); + } + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); + } + return kmd_buf; + +} + +static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t *kmd_buf, uint32_t buffered, int batch_idx, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int rc = 0, i, j; + uint32_t temp[3]; + struct cam_ope_request *ope_request; + struct cdm_dmi_cmd *dmi_cmd; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + uint64_t iova_addr; + uintptr_t cpu_addr; + size_t buf_len; + uint32_t print_idx; + uint32_t *print_ptr; + int num_dmi = 0; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[0]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[0]; + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid input: %d", batch_idx); + return NULL; + } + i = batch_idx; + + for (j = 0; j < frm_proc->num_cmd_bufs[i]; j++) { + if (frm_proc->cmd_buf[i][j].cmd_buf_scope != + OPE_CMD_BUF_SCOPE_FRAME) + continue; + + if (frm_proc->cmd_buf[i][j].cmd_buf_usage == + OPE_CMD_BUF_KMD || + frm_proc->cmd_buf[i][j].cmd_buf_usage == + OPE_CMD_BUF_DEBUG) + continue; + + if (frm_proc->cmd_buf[i][j].cmd_buf_buffered != + buffered) + continue; + + if (!frm_proc->cmd_buf[i][j].mem_handle) + continue; + + rc = cam_mem_get_io_buf( + frm_proc->cmd_buf[i][j].mem_handle, + hw_mgr->iommu_cdm_hdl, &iova_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + return NULL; + } + iova_addr = iova_addr + frm_proc->cmd_buf[i][j].offset; + + rc = cam_mem_get_cpu_buf( + frm_proc->cmd_buf[i][j].mem_handle, + &cpu_addr, &buf_len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + return NULL; + } + + cpu_addr = cpu_addr + frm_proc->cmd_buf[i][j].offset; + if (frm_proc->cmd_buf[i][j].type == + OPE_CMD_BUF_TYPE_DIRECT) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + iova_addr, + frm_proc->cmd_buf[i][j].length); + print_ptr = (uint32_t *)cpu_addr; + dump_frame_direct(print_idx, print_ptr, + frm_proc, i, j); + } else { + num_dmi = frm_proc->cmd_buf[i][j].length / + sizeof(struct cdm_dmi_cmd); + CAM_DBG(CAM_OPE, "Frame DB : In direct: E"); + print_ptr = (uint32_t *)cpu_addr; + for (print_idx = 0; + print_idx < num_dmi; print_idx++) { + memcpy(temp, (const void *)print_ptr, + sizeof(struct cdm_dmi_cmd)); + dmi_cmd = (struct cdm_dmi_cmd *)temp; + kmd_buf = cdm_ops->cdm_write_dmi( + kmd_buf, + 0, dmi_cmd->DMIAddr, + dmi_cmd->DMISel, dmi_cmd->addr, + dmi_cmd->length); + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); + print_ptr += + sizeof(struct cdm_dmi_cmd) / + sizeof(uint32_t); + } + CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); + } + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); + } + return kmd_buf; + +} + +static uint32_t *ope_create_frame_wr(struct cam_ope_ctx *ctx_data, + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info, + uint32_t *kmd_buf, struct cam_ope_request *ope_request) +{ + struct cam_cdm_utils_ops *cdm_ops; + int i; + + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + for (i = 0; i < wr_cdm_info->num_frames_cmds; i++) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + wr_cdm_info->f_cdm_info[i].offset, + wr_cdm_info->f_cdm_info[i].len); + CAM_DBG(CAM_OPE, "FrameWR:i:%d kmdbuf:%x len:%d iova:%x %pK", + i, kmd_buf, wr_cdm_info->f_cdm_info[i].len, + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + } + return kmd_buf; +} + +static uint32_t *ope_create_frame_rd(struct cam_ope_ctx *ctx_data, + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info, + uint32_t *kmd_buf, struct cam_ope_request *ope_request) +{ + struct cam_cdm_utils_ops *cdm_ops; + int i; + + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + /* Frame 0 RD */ + for (i = 0; i < rd_cdm_info->num_frames_cmds; i++) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + rd_cdm_info->f_cdm_info[i].offset, + rd_cdm_info->f_cdm_info[i].len); + CAM_DBG(CAM_OPE, "FrameRD:i:%d kmdbuf:%x len:%d iova:%x %pK", + i, kmd_buf, rd_cdm_info->f_cdm_info[i].len, + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + } + return kmd_buf; +} + +static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t *kmd_buf, uint32_t buffered, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int rc = 0, i, j; + uint32_t temp[3]; + struct cam_ope_request *ope_request; + struct cdm_dmi_cmd *dmi_cmd; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + uint64_t iova_addr; + uintptr_t cpu_addr; + size_t buf_len; + uint32_t print_idx; + uint32_t *print_ptr; + int num_dmi = 0; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[0]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[0]; + + for (i = 0; i < frm_proc->batch_size; i++) { + for (j = 0; j < frm_proc->num_cmd_bufs[i]; j++) { + if (frm_proc->cmd_buf[i][j].cmd_buf_scope != + OPE_CMD_BUF_SCOPE_FRAME) + continue; + + if (frm_proc->cmd_buf[i][j].cmd_buf_usage == + OPE_CMD_BUF_KMD || + frm_proc->cmd_buf[i][j].cmd_buf_usage == + OPE_CMD_BUF_DEBUG) + continue; + + if (frm_proc->cmd_buf[i][j].cmd_buf_buffered != + buffered) + continue; + + if (!frm_proc->cmd_buf[i][j].mem_handle) + continue; + + rc = cam_mem_get_io_buf( + frm_proc->cmd_buf[i][j].mem_handle, + hw_mgr->iommu_cdm_hdl, &iova_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + return NULL; + } + iova_addr = iova_addr + frm_proc->cmd_buf[j][i].offset; + + rc = cam_mem_get_cpu_buf( + frm_proc->cmd_buf[i][j].mem_handle, + &cpu_addr, &buf_len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + hw_mgr->iommu_hdl); + return NULL; + } + + cpu_addr = cpu_addr + frm_proc->cmd_buf[i][j].offset; + if (frm_proc->cmd_buf[i][j].type == + OPE_CMD_BUF_TYPE_DIRECT) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + iova_addr, + frm_proc->cmd_buf[i][j].length); + print_ptr = (uint32_t *)cpu_addr; + dump_frame_direct(print_idx, print_ptr, + frm_proc, i, j); + } else { + num_dmi = frm_proc->cmd_buf[i][j].length / + sizeof(struct cdm_dmi_cmd); + CAM_DBG(CAM_OPE, "Frame DB : In direct: E"); + print_ptr = (uint32_t *)cpu_addr; + for (print_idx = 0; + print_idx < num_dmi; print_idx++) { + memcpy(temp, (const void *)print_ptr, + sizeof(struct cdm_dmi_cmd)); + dmi_cmd = (struct cdm_dmi_cmd *)temp; + kmd_buf = cdm_ops->cdm_write_dmi( + kmd_buf, + 0, dmi_cmd->DMIAddr, + dmi_cmd->DMISel, dmi_cmd->addr, + dmi_cmd->length); + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); + print_ptr += + sizeof(struct cdm_dmi_cmd) / + sizeof(uint32_t); + } + CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); + } + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); + } + } + return kmd_buf; +} + +static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + uint32_t *kmd_buf, + int batch_idx, + int s_idx, + uint32_t stripe_idx, + struct ope_frame_process *frm_proc) +{ + int rc = 0, i, j, k; + uint32_t temp[3]; + struct cdm_dmi_cmd *dmi_cmd; + uint64_t iova_addr; + uintptr_t cpu_addr; + size_t buf_len; + uint32_t print_idx; + uint32_t *print_ptr; + int num_dmi = 0; + struct cam_cdm_utils_ops *cdm_ops; + + if (s_idx >= OPE_MAX_CMD_BUFS || + batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid inputs: %d %d", + batch_idx, s_idx); + return NULL; + } + + i = batch_idx; + j = s_idx; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + /* cmd buffer stripes */ + for (k = 0; k < frm_proc->num_cmd_bufs[i]; k++) { + if (frm_proc->cmd_buf[i][k].cmd_buf_scope != + OPE_CMD_BUF_SCOPE_STRIPE) + continue; + + if (frm_proc->cmd_buf[i][k].stripe_idx != + stripe_idx) + continue; + + if (!frm_proc->cmd_buf[i][k].mem_handle) + continue; + + CAM_DBG(CAM_OPE, "process stripe %d", stripe_idx); + rc = cam_mem_get_io_buf(frm_proc->cmd_buf[i][k].mem_handle, + hw_mgr->iommu_cdm_hdl, + &iova_addr, &buf_len); + if (rc) { + CAM_DBG(CAM_OPE, "get cmd buf fail %x", + hw_mgr->iommu_hdl); + return NULL; + } + iova_addr = iova_addr + frm_proc->cmd_buf[i][k].offset; + rc = cam_mem_get_cpu_buf(frm_proc->cmd_buf[i][k].mem_handle, + &cpu_addr, &buf_len); + if (rc || !cpu_addr) { + CAM_DBG(CAM_OPE, "get cmd buf fail %x", + hw_mgr->iommu_hdl); + return NULL; + } + cpu_addr = cpu_addr + frm_proc->cmd_buf[i][k].offset; + + if (frm_proc->cmd_buf[i][k].type == OPE_CMD_BUF_TYPE_DIRECT) { + kmd_buf = cdm_ops->cdm_write_indirect( + kmd_buf, + iova_addr, + frm_proc->cmd_buf[i][k].length); + print_ptr = (uint32_t *)cpu_addr; + CAM_DBG(CAM_OPE, "Stripe:%d direct:E", + stripe_idx); + for (print_idx = 0; print_idx < + frm_proc->cmd_buf[i][k].length / 4; + print_idx++) { + CAM_DBG(CAM_OPE, "%d: %x", print_idx, + print_ptr[print_idx]); + } + CAM_DBG(CAM_OPE, "Stripe:%d direct:X", stripe_idx); + } else if (frm_proc->cmd_buf[i][k].type == + OPE_CMD_BUF_TYPE_INDIRECT) { + num_dmi = frm_proc->cmd_buf[i][j].length / + sizeof(struct cdm_dmi_cmd); + CAM_DBG(CAM_OPE, "Stripe:%d Indirect:E", stripe_idx); + print_ptr = (uint32_t *)cpu_addr; + for (print_idx = 0; print_idx < num_dmi; print_idx++) { + memcpy(temp, (const void *)print_ptr, + sizeof(struct cdm_dmi_cmd)); + dmi_cmd = (struct cdm_dmi_cmd *)temp; + kmd_buf = cdm_ops->cdm_write_dmi(kmd_buf, + 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, + dmi_cmd->addr, dmi_cmd->length); + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); + print_ptr += sizeof(struct cdm_dmi_cmd) / + sizeof(uint32_t); + } + CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx); + } + dump_stripe_cmd(frm_proc, stripe_idx, i, k, + iova_addr, kmd_buf, buf_len); + } + return kmd_buf; +} + +static uint32_t *ope_create_stripe_wr(struct cam_ope_ctx *ctx_data, + uint32_t stripe_idx, struct ope_bus_wr_io_port_cdm_info *wr_cdm_info, + struct cam_ope_request *ope_request, uint32_t *kmd_buf) +{ + struct cam_cdm_utils_ops *cdm_ops; + int k; + + if (stripe_idx >= OPE_MAX_STRIPES) { + CAM_ERR(CAM_OPE, "invalid s_idx = %d", stripe_idx); + return NULL; + } + + cdm_ops = ctx_data->ope_cdm.cdm_ops; + for (k = 0; k < wr_cdm_info->num_s_cmd_bufs[stripe_idx]; k++) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + wr_cdm_info->s_cdm_info[stripe_idx][k].offset, + wr_cdm_info->s_cdm_info[stripe_idx][k].len); + CAM_DBG(CAM_OPE, "WR stripe:%d %d kmdbuf:%x", + stripe_idx, k, kmd_buf); + CAM_DBG(CAM_OPE, "offset:%d len:%d iova:%x %pK", + wr_cdm_info->s_cdm_info[stripe_idx][k].offset, + wr_cdm_info->s_cdm_info[stripe_idx][k].len, + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + } + return kmd_buf; +} + +static uint32_t *ope_create_stripe_rd(struct cam_ope_ctx *ctx_data, + uint32_t stripe_idx, struct ope_bus_rd_io_port_cdm_info *rd_cdm_info, + struct cam_ope_request *ope_request, uint32_t *kmd_buf) +{ + struct cam_cdm_utils_ops *cdm_ops; + int k; + + if (stripe_idx >= OPE_MAX_STRIPES) { + CAM_ERR(CAM_OPE, "invalid s_idx = %d", stripe_idx); + return NULL; + } + + cdm_ops = ctx_data->ope_cdm.cdm_ops; + for (k = 0; k < rd_cdm_info->num_s_cmd_bufs[stripe_idx]; k++) { + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + rd_cdm_info->s_cdm_info[stripe_idx][k].offset, + rd_cdm_info->s_cdm_info[stripe_idx][k].len); + CAM_DBG(CAM_OPE, "WR stripe:%d %d kmdbuf:%x", + stripe_idx, k, kmd_buf); + CAM_DBG(CAM_OPE, "offset:%d len:%d iova:%x %pK", + rd_cdm_info->s_cdm_info[stripe_idx][k].offset, + rd_cdm_info->s_cdm_info[stripe_idx][k].len, + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + } + return kmd_buf; +} + +static uint32_t *ope_create_stripes_batch(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t *kmd_buf, int batch_idx, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int i, j; + struct cam_ope_request *ope_request; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + uint32_t stripe_idx = 0; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid input: %d", batch_idx); + return NULL; + } + i = batch_idx; + /* Stripes */ + + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[i]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[i]; + for (j = 0; j < ope_request->num_stripes[i]; j++) { + /* cmd buffer stripes */ + kmd_buf = ope_create_stripe_cmd(hw_mgr, ctx_data, + kmd_buf, i, j, stripe_idx, frm_proc); + if (!kmd_buf) + goto end; + + /* WR stripes */ + kmd_buf = ope_create_stripe_wr(ctx_data, stripe_idx, + wr_cdm_info, ope_request, kmd_buf); + if (!kmd_buf) + goto end; + + /* RD stripes */ + kmd_buf = ope_create_stripe_rd(ctx_data, stripe_idx, + rd_cdm_info, ope_request, kmd_buf); + if (!kmd_buf) + goto end; + + /* add go command */ + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + rd_cdm_info->go_cmd_offset, + rd_cdm_info->go_cmd_len); + + CAM_DBG(CAM_OPE, "Go cmd for stripe:%d kmd_buf:%x", + stripe_idx, kmd_buf); + CAM_DBG(CAM_OPE, "iova:%x %pK", + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + + /* wait for RUP done */ + kmd_buf = cdm_ops->cdm_write_wait_comp_event(kmd_buf, + OPE_WAIT_COMP_RUP, 0x0); + CAM_DBG(CAM_OPE, "wait RUP cmd stripe:%d kmd_buf:%x", + stripe_idx, kmd_buf); + stripe_idx++; + } + +end: + return kmd_buf; +} + +static uint32_t *ope_create_stripes(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t *kmd_buf, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int i, j; + struct cam_ope_request *ope_request; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + uint32_t stripe_idx = 0; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + /* Stripes */ + for (i = 0; i < frm_proc->batch_size; i++) { + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[i]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[i]; + for (j = 0; j < ope_request->num_stripes[i]; j++) { + /* cmd buffer stripes */ + kmd_buf = ope_create_stripe_cmd(hw_mgr, ctx_data, + kmd_buf, i, j, stripe_idx, frm_proc); + if (!kmd_buf) + goto end; + + /* WR stripes */ + kmd_buf = ope_create_stripe_wr(ctx_data, stripe_idx, + wr_cdm_info, ope_request, kmd_buf); + if (!kmd_buf) + goto end; + + /* RD stripes */ + kmd_buf = ope_create_stripe_rd(ctx_data, stripe_idx, + rd_cdm_info, ope_request, kmd_buf); + if (!kmd_buf) + goto end; + + /* add go command */ + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + rd_cdm_info->go_cmd_offset, + rd_cdm_info->go_cmd_len); + + CAM_DBG(CAM_OPE, "Go cmd for stripe:%d kmd_buf:%x", + stripe_idx, kmd_buf); + CAM_DBG(CAM_OPE, "iova:%x %pK", + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + + /* wait for RUP done */ + kmd_buf = cdm_ops->cdm_write_wait_comp_event(kmd_buf, + OPE_WAIT_COMP_RUP, 0x0); + CAM_DBG(CAM_OPE, "wait RUP cmd stripe:%d kmd_buf:%x", + stripe_idx, kmd_buf); + stripe_idx++; + } + } +end: + return kmd_buf; +} + +static uint32_t *ope_create_stripes_nrt(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t *kmd_buf, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req, + uint32_t kmd_buf_offset) +{ + int i, j; + struct cam_ope_request *ope_request; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + uint32_t stripe_idx = 0; + struct cam_cdm_utils_ops *cdm_ops; + uint32_t len; + uint32_t *cdm_kmd_start_addr; + int num_nrt_stripes, num_arb; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + cdm_kmd_start_addr = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + (kmd_buf_offset / sizeof(len)); + num_nrt_stripes = ctx_data->ope_acquire.nrt_stripes_for_arb; + num_arb = ope_request->num_stripes[0] / + ctx_data->ope_acquire.nrt_stripes_for_arb; + if (ope_request->num_stripes[0] % + ctx_data->ope_acquire.nrt_stripes_for_arb) + num_arb++; + CAM_DBG(CAM_OPE, "Number of ARB for snap: %d", num_arb); + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + /* Stripes */ + for (i = 0; i < frm_proc->batch_size; i++) { + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[i]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[i]; + for (j = 0; j < ope_request->num_stripes[i]; j++) { + CAM_DBG(CAM_OPE, "num_nrt_stripes = %d num_arb = %d", + num_nrt_stripes, num_arb); + if (!num_nrt_stripes) { + kmd_buf = cdm_ops->cdm_write_wait_comp_event( + kmd_buf, + OPE_WAIT_COMP_IDLE, 0x0); + len = (kmd_buf - cdm_kmd_start_addr) * + sizeof(uint32_t); + cam_ope_dev_prepare_cdm_request( + ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, + ope_dev_prepare_req->req_idx, + kmd_buf_offset, ope_dev_prepare_req, + len, true); + cdm_kmd_start_addr = kmd_buf; + kmd_buf_offset += len; + } + /* cmd buffer stripes */ + kmd_buf = ope_create_stripe_cmd(hw_mgr, ctx_data, + kmd_buf, i, j, stripe_idx, frm_proc); + if (!kmd_buf) + goto end; + + /* WR stripes */ + kmd_buf = ope_create_stripe_wr(ctx_data, stripe_idx, + wr_cdm_info, ope_request, kmd_buf); + if (!kmd_buf) + goto end; + + /* RD stripes */ + kmd_buf = ope_create_stripe_rd(ctx_data, stripe_idx, + rd_cdm_info, ope_request, kmd_buf); + if (!kmd_buf) + goto end; + + if (!num_nrt_stripes) { + /* For num_nrt_stripes create CDM BL with ARB */ + /* Add Frame level cmds in this condition */ + /* Frame 0 DB */ + kmd_buf = ope_create_frame_cmd(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_DOUBLE_BUFFERED, + ope_dev_prepare_req); + if (!kmd_buf) + goto end; + + /* Frame 0 SB */ + kmd_buf = ope_create_frame_cmd(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_SINGLE_BUFFERED, + ope_dev_prepare_req); + if (!kmd_buf) + goto end; + + /* Frame 0 WR */ + kmd_buf = ope_create_frame_wr(ctx_data, + wr_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) + goto end; + + /* Frame 0 RD */ + kmd_buf = ope_create_frame_rd(ctx_data, + rd_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) + goto end; + num_arb--; + num_nrt_stripes = + ctx_data->ope_acquire.nrt_stripes_for_arb; + } + // add go command + kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, + (uint32_t)ope_request->ope_kmd_buf.iova_cdm_addr + + rd_cdm_info->go_cmd_offset, + rd_cdm_info->go_cmd_len); + + CAM_DBG(CAM_OPE, "Go cmd for stripe:%d kmd_buf:%x", + stripe_idx, kmd_buf); + CAM_DBG(CAM_OPE, "iova:%x %pK", + ope_request->ope_kmd_buf.iova_cdm_addr, + ope_request->ope_kmd_buf.iova_cdm_addr); + + // wait for RUP done + kmd_buf = cdm_ops->cdm_write_wait_comp_event(kmd_buf, + OPE_WAIT_COMP_RUP, 0x0); + CAM_DBG(CAM_OPE, "wait RUP cmd stripe:%d kmd_buf:%x", + stripe_idx, kmd_buf); + stripe_idx++; + num_nrt_stripes--; + } + } +end: + return kmd_buf; +} + +static int cam_ope_dev_create_kmd_buf_nrt(struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_prepare_update_args *prepare_args, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t kmd_buf_offset, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int rc = 0; + uint32_t len; + struct cam_ope_request *ope_request; + uint32_t *kmd_buf; + uint32_t *cdm_kmd_start_addr; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + (kmd_buf_offset / sizeof(len)); + cdm_kmd_start_addr = kmd_buf; + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[0]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[0]; + + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + /* Frame 0 DB */ + kmd_buf = ope_create_frame_cmd(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_DOUBLE_BUFFERED, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame 0 SB */ + kmd_buf = ope_create_frame_cmd(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_SINGLE_BUFFERED, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame 0 WR */ + kmd_buf = ope_create_frame_wr(ctx_data, + wr_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame 0 RD */ + kmd_buf = ope_create_frame_rd(ctx_data, + rd_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Stripes */ + kmd_buf = ope_create_stripes_nrt(hw_mgr, ctx_data, req_idx, kmd_buf, + ope_dev_prepare_req, kmd_buf_offset); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Last arbitration if there are odd number of stripes */ + /* wait_idle_irq */ + kmd_buf = cdm_ops->cdm_write_wait_comp_event(kmd_buf, + OPE_WAIT_COMP_IDLE, 0x0); + + /* prepare CDM submit packet */ + len = (kmd_buf - cdm_kmd_start_addr) * sizeof(uint32_t); + cam_ope_dev_prepare_cdm_request(ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, + kmd_buf_offset, ope_dev_prepare_req, + len, false); +end: + return rc; +} + +static int cam_ope_dev_create_kmd_buf_batch(struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_prepare_update_args *prepare_args, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t kmd_buf_offset, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int rc = 0, i; + uint32_t len; + struct cam_ope_request *ope_request; + uint32_t *kmd_buf; + uint32_t *cdm_kmd_start_addr; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct ope_frame_process *frm_proc; + struct cam_cdm_utils_ops *cdm_ops; + + frm_proc = ope_dev_prepare_req->frame_process; + ope_request = ctx_data->req_list[req_idx]; + kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + kmd_buf_offset; + cdm_kmd_start_addr = kmd_buf; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + for (i = 0; i < frm_proc->batch_size; i++) { + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[i]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[i]; + + /* After second batch DB programming add prefecth dis */ + if (i) { + /* program db buffered prefecth disable cmds */ + kmd_buf = ope_create_frame_cmd_prefetch_dis(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_DOUBLE_BUFFERED, i, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + kmd_buf = + cdm_ops->cdm_write_wait_prefetch_disable( + kmd_buf, 0x0, + OPE_WAIT_COMP_IDLE, 0x0); + } + + /* Frame i DB */ + kmd_buf = ope_create_frame_cmd_batch(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_DOUBLE_BUFFERED, i, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame i SB */ + kmd_buf = ope_create_frame_cmd_batch(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_SINGLE_BUFFERED, i, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame i WR */ + kmd_buf = ope_create_frame_wr(ctx_data, + wr_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame i RD */ + kmd_buf = ope_create_frame_rd(ctx_data, + rd_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Stripe level programming for batch i */ + /* Stripes */ + kmd_buf = ope_create_stripes_batch(hw_mgr, ctx_data, req_idx, + kmd_buf, i, ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + } + + /* wait_idle_irq */ + kmd_buf = cdm_ops->cdm_write_wait_comp_event(kmd_buf, + OPE_WAIT_COMP_IDLE, 0x0); + + /* prepare CDM submit packet */ + len = (cdm_kmd_start_addr - kmd_buf) * sizeof(uint32_t); + cam_ope_dev_prepare_cdm_request(ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, ope_dev_prepare_req, + len, false); + +end: + return rc; +} + +static int cam_ope_dev_create_kmd_buf(struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_prepare_update_args *prepare_args, + struct cam_ope_ctx *ctx_data, uint32_t req_idx, + uint32_t kmd_buf_offset, + struct cam_ope_dev_prepare_req *ope_dev_prepare_req) +{ + int rc = 0; + uint32_t len; + struct cam_ope_request *ope_request; + uint32_t *kmd_buf; + uint32_t *cdm_kmd_start_addr; + struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; + struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; + struct cam_cdm_utils_ops *cdm_ops; + + + if (ctx_data->ope_acquire.dev_type == OPE_DEV_TYPE_OPE_NRT) { + return cam_ope_dev_create_kmd_buf_nrt( + ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, + ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, + ope_dev_prepare_req); + } + + if (ctx_data->ope_acquire.batch_size > 1) { + return cam_ope_dev_create_kmd_buf_batch( + ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, + ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, + ope_dev_prepare_req); + } + + ope_request = ctx_data->req_list[req_idx]; + kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + + (kmd_buf_offset / sizeof(len)); + cdm_kmd_start_addr = kmd_buf; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + wr_cdm_info = + &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[0]; + rd_cdm_info = + &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[0]; + + + CAM_DBG(CAM_OPE, "kmd_buf:%x req_idx:%d req_id:%lld offset:%d", + kmd_buf, req_idx, ope_request->request_id, kmd_buf_offset); + + /* Frame 0 DB */ + kmd_buf = ope_create_frame_cmd(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_DOUBLE_BUFFERED, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame 0 SB */ + kmd_buf = ope_create_frame_cmd(hw_mgr, + ctx_data, req_idx, + kmd_buf, OPE_CMD_BUF_SINGLE_BUFFERED, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame 0 WR */ + kmd_buf = ope_create_frame_wr(ctx_data, + wr_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Frame 0 RD */ + kmd_buf = ope_create_frame_rd(ctx_data, + rd_cdm_info, kmd_buf, ope_request); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* Stripes */ + kmd_buf = ope_create_stripes(hw_mgr, ctx_data, req_idx, kmd_buf, + ope_dev_prepare_req); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } + + /* wait_idle_irq */ + kmd_buf = cdm_ops->cdm_write_wait_comp_event(kmd_buf, + OPE_WAIT_COMP_IDLE, 0x0); + + CAM_DBG(CAM_OPE, "wait for idle IRQ: kmd_buf:%x", kmd_buf); + + /* prepare CDM submit packet */ + len = (kmd_buf - cdm_kmd_start_addr) * sizeof(uint32_t); + CAM_DBG(CAM_OPE, "kmd_start_addr:%x kmdbuf_addr:%x len:%d", + cdm_kmd_start_addr, kmd_buf, len); + cam_ope_dev_prepare_cdm_request( + ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, + ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, + ope_dev_prepare_req, + len, false); +end: + return rc; +} + +static int cam_ope_dev_process_prepare(struct ope_hw *ope_hw, void *cmd_args) +{ + int rc = 0; + struct cam_ope_dev_prepare_req *ope_dev_prepare_req; + + ope_dev_prepare_req = cmd_args; + + rc = cam_ope_top_process(ope_hw, ope_dev_prepare_req->ctx_data->ctx_id, + OPE_HW_PREPARE, ope_dev_prepare_req); + if (rc) + goto end; + + rc = cam_ope_bus_rd_process(ope_hw, + ope_dev_prepare_req->ctx_data->ctx_id, + OPE_HW_PREPARE, ope_dev_prepare_req); + if (rc) + goto end; + + rc = cam_ope_bus_wr_process(ope_hw, + ope_dev_prepare_req->ctx_data->ctx_id, + OPE_HW_PREPARE, ope_dev_prepare_req); + if (rc) + goto end; + + cam_ope_dev_create_kmd_buf(ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, ope_dev_prepare_req); + +end: + return rc; +} + +static int cam_ope_dev_process_probe(struct ope_hw *ope_hw, + void *cmd_args) +{ + cam_ope_top_process(ope_hw, -1, OPE_HW_PROBE, NULL); + cam_ope_bus_rd_process(ope_hw, -1, OPE_HW_PROBE, NULL); + cam_ope_bus_wr_process(ope_hw, -1, OPE_HW_PROBE, NULL); + + return 0; +} + +static int cam_ope_process_probe(struct ope_hw *ope_hw, + void *cmd_args, bool hfi_en) +{ + struct cam_ope_dev_probe *ope_probe = cmd_args; + + if (!ope_probe->hfi_en) + return cam_ope_dev_process_probe(ope_hw, cmd_args); + + return -EINVAL; +} + +static int cam_ope_process_reset(struct ope_hw *ope_hw, + void *cmd_args, bool hfi_en) +{ + if (!hfi_en) + return cam_ope_dev_process_reset(ope_hw, cmd_args); + + return -EINVAL; +} + +static int cam_ope_process_release(struct ope_hw *ope_hw, + void *cmd_args, bool hfi_en) +{ + if (!hfi_en) + return cam_ope_dev_process_release(ope_hw, cmd_args); + + return -EINVAL; +} + +static int cam_ope_process_acquire(struct ope_hw *ope_hw, + void *cmd_args, bool hfi_en) +{ + if (!hfi_en) + return cam_ope_dev_process_acquire(ope_hw, cmd_args); + + return -EINVAL; +} + +static int cam_ope_process_prepare(struct ope_hw *ope_hw, + void *cmd_args, bool hfi_en) +{ + if (!hfi_en) + return cam_ope_dev_process_prepare(ope_hw, cmd_args); + + return -EINVAL; +} + +int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_hw_info *ope_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ope_device_core_info *core_info = NULL; + struct ope_hw *ope_hw; + bool hfi_en; + unsigned long flags; + + if (!device_priv) { + CAM_ERR(CAM_OPE, "Invalid args %x for cmd %u", + device_priv, cmd_type); + return -EINVAL; + } + + soc_info = &ope_dev->soc_info; + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + if ((!soc_info) || (!core_info)) { + CAM_ERR(CAM_OPE, "soc_info = %x core_info = %x", + soc_info, core_info); + return -EINVAL; + } + + hfi_en = core_info->ope_hw_info->hfi_en; + ope_hw = core_info->ope_hw_info->ope_hw; + if (!ope_hw) { + CAM_ERR(CAM_OPE, "Invalid ope hw info"); + return -EINVAL; + } + + switch (cmd_type) { + case OPE_HW_PROBE: + rc = cam_ope_process_probe(ope_hw, cmd_args, hfi_en); + break; + case OPE_HW_ACQUIRE: + rc = cam_ope_process_acquire(ope_hw, cmd_args, hfi_en); + break; + case OPE_HW_RELEASE: + rc = cam_ope_process_release(ope_hw, cmd_args, hfi_en); + break; + case OPE_HW_PREPARE: + rc = cam_ope_process_prepare(ope_hw, cmd_args, hfi_en); + break; + case OPE_HW_START: + break; + case OPE_HW_STOP: + break; + case OPE_HW_FLUSH: + break; + case OPE_HW_RESET: + rc = cam_ope_process_reset(ope_hw, cmd_args, hfi_en); + break; + case OPE_HW_CLK_UPDATE: { + struct cam_ope_dev_clk_update *clk_upd_cmd = + (struct cam_ope_dev_clk_update *)cmd_args; + + rc = cam_ope_update_clk_rate(soc_info, clk_upd_cmd->clk_rate); + if (rc) + CAM_ERR(CAM_OPE, "Failed to update clk: %d", rc); + } + break; + case OPE_HW_BW_UPDATE: { + struct cam_ope_dev_bw_update *cpas_vote = cmd_args; + + if (!cmd_args) + return -EINVAL; + + rc = cam_ope_caps_vote(core_info, cpas_vote); + if (rc) + CAM_ERR(CAM_OPE, "failed to update bw: %d", rc); + } + break; + case OPE_HW_SET_IRQ_CB: { + struct cam_ope_set_irq_cb *irq_cb = cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_OPE, "cmd args NULL"); + return -EINVAL; + } + + spin_lock_irqsave(&ope_dev->hw_lock, flags); + core_info->irq_cb.ope_hw_mgr_cb = irq_cb->ope_hw_mgr_cb; + core_info->irq_cb.data = irq_cb->data; + spin_unlock_irqrestore(&ope_dev->hw_lock, flags); + } + break; + default: + break; + } + + return rc; +} + +irqreturn_t cam_ope_irq(int irq_num, void *data) +{ + struct cam_hw_info *ope_dev = data; + struct cam_ope_device_core_info *core_info = NULL; + struct ope_hw *ope_hw; + struct cam_ope_irq_data irq_data; + + if (!data) { + CAM_ERR(CAM_OPE, "Invalid cam_dev_info or query_cap args"); + return IRQ_HANDLED; + } + + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + ope_hw = core_info->ope_hw_info->ope_hw; + + irq_data.error = 0; + cam_ope_top_process(ope_hw, 0, OPE_HW_ISR, &irq_data); + cam_ope_bus_rd_process(ope_hw, 0, OPE_HW_ISR, &irq_data); + cam_ope_bus_wr_process(ope_hw, 0, OPE_HW_ISR, &irq_data); + + + spin_lock(&ope_dev->hw_lock); + if (core_info->irq_cb.ope_hw_mgr_cb && core_info->irq_cb.data) + if (irq_data.error) + core_info->irq_cb.ope_hw_mgr_cb(irq_data.error, + core_info->irq_cb.data); + spin_unlock(&ope_dev->hw_lock); + + + return IRQ_HANDLED; +} diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h new file mode 100644 index 000000000000..c4b7dd7f8e55 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_CORE_H +#define CAM_OPE_CORE_H + +#include +#include +#include +#include +#include +#include +#include "cam_cpas_api.h" +#include "ope_hw.h" +#include "ope_dev_intf.h" +/** + * struct cam_ope_cpas_vote + * @ahb_vote: AHB vote info + * @axi_vote: AXI vote info + * @ahb_vote_valid: Flag for ahb vote data + * @axi_vote_valid: flag for axi vote data + */ +struct cam_ope_cpas_vote { + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote; + uint32_t ahb_vote_valid; + uint32_t axi_vote_valid; +}; + +/** + * struct cam_ope_device_hw_info + * + * @ope_hw: OPE hardware + * @hw_idx: Hardware index + * @ope_cdm_base: Base address of CDM + * @ope_top_base: Base address of top + * @ope_qos_base: Base address of QOS + * @ope_pp_base: Base address of PP + * @ope_bus_rd_base: Base address of RD + * @ope_bus_wr_base: Base address of WM + * @hfi_en: HFI flag enable + * @reserved: Reserved + */ +struct cam_ope_device_hw_info { + struct ope_hw *ope_hw; + uint32_t hw_idx; + void *ope_cdm_base; + void *ope_top_base; + void *ope_qos_base; + void *ope_pp_base; + void *ope_bus_rd_base; + void *ope_bus_wr_base; + bool hfi_en; + uint32_t reserved; +}; + +/** + * struct cam_ope_device_core_info + * + * @ope_hw_info: OPE hardware info + * @hw_version: Hardware version + * @hw_idx: Hardware Index + * @hw_type: Hardware Type + * @cpas_handle: CPAS Handle + * @cpas_start: CPAS start flag + * @clk_enable: Clock enable flag + * @irq_cb: IRQ Callback + */ +struct cam_ope_device_core_info { + struct cam_ope_device_hw_info *ope_hw_info; + uint32_t hw_version; + uint32_t hw_idx; + uint32_t hw_type; + uint32_t cpas_handle; + bool cpas_start; + bool clk_enable; + struct cam_ope_set_irq_cb irq_cb; +}; + + +int cam_ope_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_ope_deinit_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_ope_start(void *device_priv, + void *start_args, uint32_t arg_size); +int cam_ope_stop(void *device_priv, + void *stop_args, uint32_t arg_size); +int cam_ope_flush(void *device_priv, + void *flush_args, uint32_t arg_size); +int cam_ope_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size); +int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); +irqreturn_t cam_ope_irq(int irq_num, void *data); + +#endif /* CAM_OPE_CORE_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c new file mode 100644 index 000000000000..1230fea487af --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "ope_core.h" +#include "ope_soc.h" +#include "cam_hw.h" +#include "ope_hw.h" +#include "cam_hw_intf.h" +#include "cam_io_util.h" +#include "cam_ope_hw_mgr_intf.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "ope_hw_100.h" +#include "ope_dev_intf.h" + +static struct cam_ope_device_hw_info ope_hw_info; +static struct ope_dev_soc ope_soc_info; +EXPORT_SYMBOL(ope_soc_info); + +static struct hw_version_reg ope_hw_version_reg = { + .hw_ver = 0x0, +}; + +static char ope_dev_name[8]; + +static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info, + struct cam_ope_device_core_info *core_info) +{ + int rc = 0; + + CAM_DBG(CAM_OPE, "soc_info = %x core_info = %x", + soc_info, core_info); + CAM_DBG(CAM_OPE, "CDM:%x TOP: %x QOS: %x PP: %x RD: %x WR: %x", + soc_info->reg_map[OPE_CDM_BASE].mem_base, + soc_info->reg_map[OPE_TOP_BASE].mem_base, + soc_info->reg_map[OPE_QOS_BASE].mem_base, + soc_info->reg_map[OPE_PP_BASE].mem_base, + soc_info->reg_map[OPE_BUS_RD].mem_base, + soc_info->reg_map[OPE_BUS_WR].mem_base); + CAM_DBG(CAM_OPE, "core: %x", + core_info->ope_hw_info->ope_cdm_base); + + core_info->ope_hw_info->ope_cdm_base = + soc_info->reg_map[OPE_CDM_BASE].mem_base; + core_info->ope_hw_info->ope_top_base = + soc_info->reg_map[OPE_TOP_BASE].mem_base; + core_info->ope_hw_info->ope_qos_base = + soc_info->reg_map[OPE_QOS_BASE].mem_base; + core_info->ope_hw_info->ope_pp_base = + soc_info->reg_map[OPE_PP_BASE].mem_base; + core_info->ope_hw_info->ope_bus_rd_base = + soc_info->reg_map[OPE_BUS_RD].mem_base; + core_info->ope_hw_info->ope_bus_wr_base = + soc_info->reg_map[OPE_BUS_WR].mem_base; + + core_info->hw_version = cam_io_r_mb( + core_info->ope_hw_info->ope_top_base + + ope_hw_version_reg.hw_ver); + + switch (core_info->hw_version) { + case OPE_HW_VER_1_0_0: + core_info->ope_hw_info->ope_hw = &ope_hw_100; + break; + default: + CAM_ERR(CAM_OPE, "Unsupported version : %u", + core_info->hw_version); + rc = -EINVAL; + break; + } + + ope_hw_100.top_reg->base = core_info->ope_hw_info->ope_top_base; + ope_hw_100.bus_rd_reg->base = core_info->ope_hw_info->ope_bus_rd_base; + ope_hw_100.bus_wr_reg->base = core_info->ope_hw_info->ope_bus_wr_base; + + return rc; +} + +int cam_ope_register_cpas(struct cam_hw_soc_info *soc_info, + struct cam_ope_device_core_info *core_info, + uint32_t hw_idx) +{ + struct cam_cpas_register_params cpas_register_params; + int rc; + + cpas_register_params.dev = &soc_info->pdev->dev; + memcpy(cpas_register_params.identifier, "ope", sizeof("ope")); + cpas_register_params.cam_cpas_client_cb = NULL; + cpas_register_params.cell_index = hw_idx; + cpas_register_params.userdata = NULL; + + rc = cam_cpas_register_client(&cpas_register_params); + if (rc < 0) { + CAM_ERR(CAM_OPE, "failed: %d", rc); + return rc; + } + core_info->cpas_handle = cpas_register_params.client_handle; + + return rc; +} + +int cam_ope_probe(struct platform_device *pdev) +{ + struct cam_hw_intf *ope_dev_intf = NULL; + struct cam_hw_info *ope_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_ope_device_core_info *core_info = NULL; + int rc = 0; + uint32_t hw_idx; + struct cam_ope_dev_probe ope_probe; + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &hw_idx); + + ope_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!ope_dev_intf) + return -ENOMEM; + + ope_dev_intf->hw_idx = hw_idx; + ope_dev_intf->hw_type = OPE_DEV_OPE; + ope_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!ope_dev) { + rc = -ENOMEM; + goto ope_dev_alloc_failed; + } + + memset(ope_dev_name, 0, sizeof(ope_dev_name)); + snprintf(ope_dev_name, sizeof(ope_dev_name), + "ope%1u", ope_dev_intf->hw_idx); + + ope_dev->soc_info.pdev = pdev; + ope_dev->soc_info.dev = &pdev->dev; + ope_dev->soc_info.dev_name = ope_dev_name; + ope_dev_intf->hw_priv = ope_dev; + ope_dev_intf->hw_ops.init = cam_ope_init_hw; + ope_dev_intf->hw_ops.deinit = cam_ope_deinit_hw; + ope_dev_intf->hw_ops.get_hw_caps = cam_ope_get_hw_caps; + ope_dev_intf->hw_ops.start = cam_ope_start; + ope_dev_intf->hw_ops.stop = cam_ope_stop; + ope_dev_intf->hw_ops.flush = cam_ope_flush; + ope_dev_intf->hw_ops.process_cmd = cam_ope_process_cmd; + + CAM_DBG(CAM_OPE, "type %d index %d", + ope_dev_intf->hw_type, + ope_dev_intf->hw_idx); + + platform_set_drvdata(pdev, ope_dev_intf); + + ope_dev->core_info = kzalloc(sizeof(struct cam_ope_device_core_info), + GFP_KERNEL); + if (!ope_dev->core_info) { + rc = -ENOMEM; + goto ope_core_alloc_failed; + } + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + core_info->ope_hw_info = &ope_hw_info; + ope_dev->soc_info.soc_private = &ope_soc_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + rc = -EINVAL; + CAM_DBG(CAM_OPE, "No ope hardware info"); + goto ope_match_dev_failed; + } + + rc = cam_ope_init_soc_resources(&ope_dev->soc_info, cam_ope_irq, + ope_dev); + if (rc < 0) { + CAM_ERR(CAM_OPE, "failed to init_soc"); + goto init_soc_failed; + } + + rc = cam_ope_enable_soc_resources(&ope_dev->soc_info); + if (rc < 0) { + CAM_ERR(CAM_OPE, "enable soc resorce failed: %d", rc); + goto enable_soc_failed; + } + + rc = cam_ope_init_hw_version(&ope_dev->soc_info, ope_dev->core_info); + if (rc) + goto init_hw_failure; + + core_info->hw_type = OPE_DEV_OPE; + core_info->hw_idx = hw_idx; + rc = cam_ope_register_cpas(&ope_dev->soc_info, + core_info, ope_dev_intf->hw_idx); + if (rc < 0) + goto register_cpas_failed; + + cam_ope_disable_soc_resources(&ope_dev->soc_info, true); + ope_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + + ope_probe.hfi_en = ope_soc_info.hfi_en; + cam_ope_process_cmd(ope_dev, OPE_HW_PROBE, + &ope_probe, sizeof(ope_probe)); + mutex_init(&ope_dev->hw_mutex); + spin_lock_init(&ope_dev->hw_lock); + init_completion(&ope_dev->hw_complete); + + CAM_DBG(CAM_OPE, "OPE%d probe successful", + ope_dev_intf->hw_idx); + return rc; + +init_hw_failure: +enable_soc_failed: +register_cpas_failed: +init_soc_failed: +ope_match_dev_failed: + kfree(ope_dev->core_info); +ope_core_alloc_failed: + kfree(ope_dev); +ope_dev_alloc_failed: + kfree(ope_dev_intf); + return rc; +} + +static const struct of_device_id cam_ope_dt_match[] = { + { + .compatible = "qcom,ope", + .data = &ope_hw_version_reg, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_ope_dt_match); + +static struct platform_driver cam_ope_driver = { + .probe = cam_ope_probe, + .driver = { + .name = "ope", + .of_match_table = cam_ope_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_ope_init_module(void) +{ + return platform_driver_register(&cam_ope_driver); +} + +void cam_ope_exit_module(void) +{ + platform_driver_unregister(&cam_ope_driver); +} + +MODULE_DESCRIPTION("CAM OPE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h new file mode 100644 index 000000000000..462752bd7f3d --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_DEV_INTF_H +#define CAM_OPE_DEV_INTF_H + +#include +#include "cam_ope_hw_mgr.h" +#include "cam_cdm_intf_api.h" +#include "cam_cpas_api.h" + + +#define OPE_HW_INIT 0x1 +#define OPE_HW_DEINIT 0x2 +#define OPE_HW_ACQUIRE 0x3 +#define OPE_HW_RELEASE 0x4 +#define OPE_HW_START 0x5 +#define OPE_HW_STOP 0x6 +#define OPE_HW_FLUSH 0x7 +#define OPE_HW_PREPARE 0x8 +#define OPE_HW_ISR 0x9 +#define OPE_HW_PROBE 0xA +#define OPE_HW_CLK_UPDATE 0xB +#define OPE_HW_BW_UPDATE 0xC +#define OPE_HW_RESET 0xD +#define OPE_HW_SET_IRQ_CB 0xE + +/** + * struct cam_ope_dev_probe + * + * @hfi_en: HFI enable flag + */ +struct cam_ope_dev_probe { + bool hfi_en; +}; + +/** + * struct cam_ope_dev_init + * + * @hfi_en: HFI enable flag + * @core_info: OPE core info + */ +struct cam_ope_dev_init { + bool hfi_en; + struct cam_ope_device_core_info *core_info; +}; + +/** + * struct cam_ope_dev_clk_update + * + * @clk_rate: Clock rate + */ +struct cam_ope_dev_clk_update { + uint32_t clk_rate; +}; + +/** + * struct cam_ope_dev_bw_update + * + * @ahb_vote: AHB vote info + * @axi_vote: AXI vote info + * @ahb_vote_valid: Flag for ahb vote + * @axi_vote_valid: Flag for axi vote + */ +struct cam_ope_dev_bw_update { + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote; + uint32_t ahb_vote_valid; + uint32_t axi_vote_valid; +}; + +/** + * struct cam_ope_dev_caps + * + * @hw_idx: Hardware index + * @hw_ver: Hardware version info + */ +struct cam_ope_dev_caps { + uint32_t hw_idx; + struct ope_hw_ver hw_ver; +}; + +/** + * struct cam_ope_dev_acquire + * + * @ctx_id: Context id + * @ope_acquire: OPE acquire info + * @bus_wr_ctx: Bus Write context + * @bus_rd_ctx: Bus Read context + */ +struct cam_ope_dev_acquire { + uint32_t ctx_id; + struct ope_acquire_dev_info *ope_acquire; + struct ope_bus_wr_ctx *bus_wr_ctx; + struct ope_bus_rd_ctx *bus_rd_ctx; +}; + +/** + * struct cam_ope_dev_release + * + * @ctx_id: Context id + * @bus_wr_ctx: Bus Write context + * @bus_rd_ctx: Bus Read context + */ +struct cam_ope_dev_release { + uint32_t ctx_id; + struct ope_bus_wr_ctx *bus_wr_ctx; + struct ope_bus_rd_ctx *bus_rd_ctx; +}; + +/** + * struct cam_ope_set_irq_cb + * + * @ope_hw_mgr_cb: Callback to hardware manager + * @data: Private data + */ +struct cam_ope_set_irq_cb { + int32_t (*ope_hw_mgr_cb)(uint32_t irq_status, void *data); + void *data; +}; + +/** + * struct cam_ope_irq_data + * + * @error: IRQ error + */ +struct cam_ope_irq_data { + uint32_t error; +}; + +/** + * struct cam_ope_dev_prepare_req + * + * @hw_mgr: OPE hardware manager + * @packet: Packet + * @prepare_args: Prepare request args + * @ctx_data: Context data + * @wr_cdm_batch: WM request + * @rd_cdm_batch: RD master request + * @frame_process: Frame process command + * @req_idx: Request Index + * @kmd_buf_offset: KMD buffer offset + */ +struct cam_ope_dev_prepare_req { + struct cam_ope_hw_mgr *hw_mgr; + struct cam_packet *packet; + struct cam_hw_prepare_update_args *prepare_args; + struct cam_ope_ctx *ctx_data; + struct ope_bus_wr_io_port_cdm_batch *wr_cdm_batch; + struct ope_bus_rd_io_port_cdm_batch *rd_cdm_batch; + struct ope_frame_process *frame_process; + uint32_t req_idx; + uint32_t kmd_buf_offset; +}; + +int cam_ope_top_process(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t cmd_id, void *data); + +int cam_ope_bus_rd_process(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t cmd_id, void *data); + +int cam_ope_bus_wr_process(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t cmd_id, void *data); + +int cam_ope_init_module(void); +void cam_ope_exit_module(void); + +int cam_ope_subdev_init_module(void); +void cam_ope_subdev_exit_module(void); + +#endif /* CAM_OPE_DEV_INTF_H */ + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h new file mode 100644 index 000000000000..28c1a4d5e2ed --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -0,0 +1,399 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_HW_H +#define CAM_OPE_HW_H + +#define OPE_HW_VER_1_0_0 0x10000000 + +#define OPE_DEV_OPE 0 +#define OPE_DEV_MAX 1 + +#define MAX_RD_CLIENTS 2 +#define MAX_WR_CLIENTS 8 + +#define OPE_CDM_BASE 0x0 +#define OPE_TOP_BASE 0x1 +#define OPE_QOS_BASE 0x2 +#define OPE_PP_BASE 0x3 +#define OPE_BUS_RD 0x4 +#define OPE_BUS_WR 0x5 +#define OPE_BASE_MAX 0x6 + + +#define BUS_RD_COMBO_BAYER_MASK 0x1 +#define BUS_RD_COMBO_YUV_MASK 0x2 +#define BUS_RD_COMBO_MAX 0x2 + +#define BUS_RD_BAYER 0x0 +#define BUS_RD_YUV 0x1 + +#define BUS_WR_COMBO_YUV_MASK 0x1 +#define BUS_WR_COMBO_MAX 0x1 + +#define BUS_WR_YUV 0x0 + +#define BUS_WR_VIDEO_Y 0x0 +#define BUS_WR_VIDEO_C 0x1 +#define BUS_WR_DISP_Y 0x2 +#define BUS_WR_DISP_C 0x3 +#define BUS_WR_ARGB 0x4 +#define BUS_WR_STATS_RS 0x5 +#define BUS_WR_STATS_IHIST 0x6 +#define BUS_WR_STATS_LTM 0x7 + +#define OPE_WAIT_COMP_RUP 0x1 +#define OPE_WAIT_COMP_WR_DONE 0x2 +#define OPE_WAIT_COMP_IDLE 0x4 +#define OPE_WAIT_COMP_GEN_IRQ 0x8 + +struct cam_ope_common { + uint32_t mode[CAM_FORMAT_MAX]; +}; + +struct cam_ope_top_reg { + void *base; + uint32_t offset; + uint32_t hw_version; + uint32_t reset_cmd; + uint32_t core_clk_cfg_ctrl_0; + uint32_t ahb_clk_cgc_ctrl; + uint32_t core_cfg; + uint32_t irq_status; + uint32_t irq_mask; + uint32_t irq_clear; + uint32_t irq_set; + uint32_t irq_cmd; + uint32_t violation_status; + uint32_t throttle_cnt_cfg; +}; + +struct cam_ope_top_reg_val { + uint32_t hw_version; + uint32_t major_mask; + uint32_t major_shift; + uint32_t minor_mask; + uint32_t minor_shift; + uint32_t incr_mask; + uint32_t incr_shift; + uint32_t irq_mask; + uint32_t irq_set_clear; + uint32_t sw_reset_cmd; + uint32_t hw_reset_cmd; + uint32_t core_clk_cfg_ctrl_0; + uint32_t ahb_clk_cgc_ctrl; + uint32_t input_format; + uint32_t input_format_mask; + uint32_t color_correct_src_sel; + uint32_t color_correct_src_sel_mask; + uint32_t stats_ihist_src_sel; + uint32_t stats_ihist_src_sel_mask; + uint32_t chroma_up_src_sel; + uint32_t chroma_up_src_sel_mask; + uint32_t argb_alpha; + uint32_t argb_alpha_mask; + uint32_t rs_throttle_cnt; + uint32_t rs_throttle_cnt_mask; + uint32_t ihist_throttle_cnt; + uint32_t ihist_throttle_cnt_mask; + uint32_t rst_done; + uint32_t we_done; + uint32_t fe_done; + uint32_t ope_violation; + uint32_t idle; +}; + +struct cam_ope_qos_reg { + void *base; + uint32_t offset; + uint32_t hw_version; + uint32_t hw_status; + uint32_t module_cfg; + uint32_t curve_cfg_0; + uint32_t curve_cfg_1; + uint32_t window_cfg; + uint32_t eos_status_0; + uint32_t eos_status_1; + uint32_t eos_status_2; +}; + +struct cam_ope_qos_reg_val { + uint32_t hw_version; + uint32_t proc_interval; + uint32_t proc_interval_mask; + uint32_t static_health; + uint32_t static_health_mask; + uint32_t module_cfg_en; + uint32_t module_cfg_en_mask; + uint32_t yexp_ymin_dec; + uint32_t yexp_ymin_dec_mask; + uint32_t ymin_inc; + uint32_t ymin_inc_mask; + uint32_t initial_delta; + uint32_t initial_delta_mask; + uint32_t window_cfg; +}; + +struct cam_ope_bus_rd_client_reg { + uint32_t core_cfg; + uint32_t ccif_meta_data; + uint32_t img_addr; + uint32_t img_cfg; + uint32_t stride; + uint32_t unpack_cfg; + uint32_t latency_buf_allocation; + uint32_t misr_cfg_0; + uint32_t misr_cfg_1; + uint32_t misr_rd_val; +}; + +struct cam_ope_bus_rd_reg { + void *base; + uint32_t offset; + uint32_t hw_version; + uint32_t sw_reset; + uint32_t cgc_override; + uint32_t irq_mask; + uint32_t irq_clear; + uint32_t irq_cmd; + uint32_t irq_status; + uint32_t input_if_cmd; + uint32_t irq_set; + uint32_t misr_reset; + uint32_t security_cfg; + uint32_t iso_cfg; + uint32_t iso_seed; + + uint32_t num_clients; + struct cam_ope_bus_rd_client_reg rd_clients[MAX_RD_CLIENTS]; +}; + +struct cam_ope_bus_rd_client_reg_val { + uint32_t core_cfg; + uint32_t stripe_location; + uint32_t stripe_location_mask; + uint32_t stripe_location_shift; + uint32_t pix_pattern; + uint32_t pix_pattern_mask; + uint32_t pix_pattern_shift; + uint32_t img_addr; + uint32_t img_width; + uint32_t img_width_mask; + uint32_t img_width_shift; + uint32_t img_height; + uint32_t img_height_mask; + uint32_t img_height_shift; + uint32_t stride; + uint32_t mode; + uint32_t mode_mask; + uint32_t mode_shift; + uint32_t alignment; + uint32_t alignment_mask; + uint32_t alignment_shift; + uint32_t latency_buf_allocation; + uint32_t misr_cfg_samp_mode; + uint32_t misr_cfg_samp_mode_mask; + uint32_t misr_cfg_en; + uint32_t misr_cfg_en_mask; + uint32_t misr_cfg_1; + uint32_t misr_rd_val; + uint32_t input_port_id; + uint32_t rm_port_id; + uint32_t format_type; + uint32_t num_combos_supported; +}; + +struct cam_ope_bus_rd_reg_val { + uint32_t hw_version; + uint32_t sw_reset; + uint32_t cgc_override; + uint32_t irq_mask; + uint32_t go_cmd; + uint32_t go_cmd_mask; + uint32_t ica_en; + uint32_t ica_en_mask; + uint32_t static_prg; + uint32_t static_prg_mask; + uint32_t go_cmd_sel; + uint32_t go_cmd_sel_mask; + uint32_t fs_sync_en; + uint32_t fs_sync_en_mask; + uint32_t misr_reset; + uint32_t security_cfg; + uint32_t iso_bpp_select; + uint32_t iso_bpp_select_mask; + uint32_t iso_pattern_select; + uint32_t iso_pattern_select_mask; + uint32_t iso_en; + uint32_t iso_en_mask; + uint32_t iso_seed; + uint32_t irq_set_clear; + uint32_t rst_done; + uint32_t rup_done; + uint32_t rd_buf_done; + uint32_t violation; + uint32_t latency_buf_size; + + uint32_t num_clients; + struct cam_ope_bus_rd_client_reg_val rd_clients[MAX_RD_CLIENTS]; +}; + +struct cam_ope_bus_wr_client_reg { + uint32_t core_cfg; + uint32_t img_addr; + uint32_t img_cfg; + uint32_t x_init; + uint32_t stride; + uint32_t pack_cfg; + uint32_t bw_limit; + uint32_t frame_header_addr; + uint32_t subsample_period; + uint32_t subsample_pattern; +}; + +struct cam_ope_bus_wr_reg { + void *base; + uint32_t offset; + uint32_t hw_version; + uint32_t cgc_override; + uint32_t irq_mask_0; + uint32_t irq_mask_1; + uint32_t irq_clear_0; + uint32_t irq_clear_1; + uint32_t irq_status_0; + uint32_t irq_status_1; + uint32_t irq_cmd; + uint32_t frame_header_cfg_0; + uint32_t local_frame_header_cfg_0; + uint32_t irq_set_0; + uint32_t irq_set_1; + uint32_t iso_cfg; + uint32_t violation_status; + uint32_t image_size_violation_status; + uint32_t misr_cfg_0; + uint32_t misr_cfg_1; + uint32_t misr_rd_sel; + uint32_t misr_reset; + uint32_t misr_val; + uint32_t num_clients; + struct cam_ope_bus_wr_client_reg wr_clients[MAX_WR_CLIENTS]; +}; + +struct cam_ope_bus_wr_client_reg_val { + uint32_t core_cfg_en; + uint32_t core_cfg_en_mask; + uint32_t core_cfg_en_shift; + uint32_t virtual_frame_en; + uint32_t virtual_frame_en_mask; + uint32_t virtual_frame_en_shift; + uint32_t frame_header_en; + uint32_t frame_header_en_mask; + uint32_t frame_header_en_shift; + uint32_t auto_recovery_en; + uint32_t auto_recovery_en_mask; + uint32_t auto_recovery_en_shift; + uint32_t mode; + uint32_t mode_mask; + uint32_t mode_shift; + uint32_t img_addr; + uint32_t width; + uint32_t width_mask; + uint32_t width_shift; + uint32_t height; + uint32_t height_mask; + uint32_t height_shift; + uint32_t x_init; + uint32_t stride; + uint32_t format; + uint32_t format_mask; + uint32_t format_shift; + uint32_t alignment; + uint32_t alignment_mask; + uint32_t alignment_shift; + uint32_t bw_limit_en; + uint32_t bw_limit_en_mask; + uint32_t bw_limit_counter; + uint32_t bw_limit_counter_mask; + uint32_t frame_header_addr; + uint32_t subsample_period; + uint32_t subsample_pattern; + uint32_t output_port_id; + uint32_t wm_port_id; + uint32_t format_type; + uint32_t num_combos_supported; +}; + +struct cam_ope_bus_wr_reg_val { + uint32_t hw_version; + uint32_t cgc_override; + uint32_t irq_mask_0; + uint32_t irq_mask_1; + uint32_t irq_set_clear; + uint32_t comp_rup_done; + uint32_t comp_buf_done; + uint32_t cons_violation; + uint32_t violation; + uint32_t img_size_violation; + uint32_t frame_header_cfg_0; + uint32_t local_frame_header_cfg_0; + uint32_t iso_cfg; + uint32_t misr_0_en; + uint32_t misr_0_en_mask; + uint32_t misr_1_en; + uint32_t misr_1_en_mask; + uint32_t misr_2_en; + uint32_t misr_2_en_mask; + uint32_t misr_3_en; + uint32_t misr_3_en_mask; + uint32_t misr_0_samp_mode; + uint32_t misr_0_samp_mode_mask; + uint32_t misr_1_samp_mode; + uint32_t misr_1_samp_mode_mask; + uint32_t misr_2_samp_mode; + uint32_t misr_2_samp_mode_mask; + uint32_t misr_3_samp_mode; + uint32_t misr_3_samp_mode_mask; + uint32_t misr_0_id; + uint32_t misr_0_id_mask; + uint32_t misr_1_id; + uint32_t misr_1_id_mask; + uint32_t misr_2_id; + uint32_t misr_2_id_mask; + uint32_t misr_3_id; + uint32_t misr_3_id_mask; + uint32_t misr_rd_misr_sel; + uint32_t misr_rd_misr_sel_mask; + uint32_t misr_rd_word_sel; + uint32_t misr_rd_word_sel_mask; + uint32_t misr_reset; + uint32_t misr_val; + + + uint32_t num_clients; + struct cam_ope_bus_wr_client_reg_val wr_clients[MAX_WR_CLIENTS]; +}; + +struct ope_hw { + struct cam_ope_top_reg *top_reg; + struct cam_ope_top_reg_val *top_reg_val; + + struct cam_ope_bus_rd_reg *bus_rd_reg; + struct cam_ope_bus_rd_reg_val *bus_rd_reg_val; + + struct cam_ope_bus_wr_reg *bus_wr_reg; + struct cam_ope_bus_wr_reg_val *bus_wr_reg_val; + + struct cam_ope_qos_reg *qos_reg; + struct cam_ope_qos_reg_val *qos_reg_val; + + struct cam_ope_common *common; +}; + +struct hw_version_reg { + uint32_t hw_ver; + uint32_t reserved; +}; + +#endif /* CAM_OPE_HW_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h new file mode 100644 index 000000000000..0970fc3816e6 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -0,0 +1,532 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_HW_100_H +#define CAM_OPE_HW_100_H + +#define OPE_BUS_RD_TYPE_BAYER 0x0 +#define OPE_BUS_RD_TYPE_YUV_Y 0x0 +#define OPE_BUS_RD_TYPE_YUC_C 0x1 + +#define OPE_BUS_WR_TYPE_VID_Y 0x0 +#define OPE_BUS_WR_TYPE_VID_C 0x1 +#define OPE_BUS_WR_TYPE_DISP_Y 0x2 +#define OPE_BUS_WR_TYPE_DISP_C 0x3 +#define OPE_BUS_WR_TYPE_ARGB 0x4 +#define OPE_BUS_WR_TYPE_RS 0x5 +#define OPE_BUS_WR_TYPE_IHIST 0x6 +#define OPE_BUS_WR_TYPE_LTM 0x7 + +enum cam_ope_bus_rd_unpacker_format { + BUS_RD_VER1_PACKER_FMT_PLAIN_128_BYPASS = 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_32_20BPP = 0x5, + BUS_RD_VER1_PACKER_FMT_ARGB16_10 = 0x6, + BUS_RD_VER1_PACKER_FMT_ARGB16_12 = 0x7, + BUS_RD_VER1_PACKER_FMT_ARGB16_14 = 0x8, + BUS_RD_VER1_PACKER_FMT_PLAIN_32 = 0x9, + BUS_RD_VER1_PACKER_FMT_PLAIN_64 = 0xA, + BUS_RD_VER1_PACKER_FMT_TP_10 = 0xB, + BUS_RD_VER1_PACKER_FMT_MIPI_8 = 0xC, + BUS_RD_VER1_PACKER_FMT_MIPI_10 = 0xD, + BUS_RD_VER1_PACKER_FMT_MIPI_12 = 0xE, + BUS_RD_VER1_PACKER_FMT_MIPI_14 = 0xF, + BUS_RD_VER1_PACKER_FMT_PLAIN_16_16BPP = 0x10, + BUS_RD_VER1_PACKER_FMT_BYPASS_SWAP = 0x11, + BUS_RD_VER1_PACKER_FMT_PLAIN_8_SWAP = 0x12, + BUS_RD_VER1_PACKER_FMT_MAX = 0x13, +}; + +static struct cam_ope_top_reg ope_top_reg = { + .offset = 0x400, + .hw_version = 0x0, + .reset_cmd = 0x4, + .core_clk_cfg_ctrl_0 = 0x8, + .ahb_clk_cgc_ctrl = 0xC, + .core_cfg = 0x10, + .irq_status = 0x14, + .irq_mask = 0x18, + .irq_clear = 0x1C, + .irq_set = 0x20, + .irq_cmd = 0x24, + .violation_status = 0x28, + .throttle_cnt_cfg = 0x2C, +}; + +static struct cam_ope_top_reg_val ope_top_reg_val = { + .hw_version = 0x10000000, + .major_mask = 0xFFFF, + .major_shift = 0x0, + .minor_mask = 0x0FFF0000, + .minor_shift = 0xF, + .incr_mask = 0xF0000000, + .incr_shift = 0x1B, + .irq_mask = 0x0000000F, + .sw_reset_cmd = 0x2, + .hw_reset_cmd = 0x1, + .irq_set_clear = 0x1, + .rst_done = 0x1, + .we_done = 0x2, + .fe_done = 0x4, + .ope_violation = 0x8, + .idle = 0x10, +}; + + +static struct cam_ope_bus_rd_reg_val ope_bus_rd_reg_val = { + .hw_version = 0x00050000, + .sw_reset = 0x1, + .cgc_override = 0x0, + .irq_mask = 0x30001, + .irq_set_clear = 0x1, + .rst_done = 0x1, + .rup_done = 0x2, + .rd_buf_done = 0xC, + .violation = 0x3000, + .go_cmd = 0x1, + .security_cfg = 0x0, + .latency_buf_size = 4096, + .num_clients = 0x2, + .rd_clients = { + { + .core_cfg = 0x1, + .stripe_location_mask = 0x3, + .stripe_location_shift = 0x0, + .pix_pattern_mask = 0x3F, + .pix_pattern_shift = 0x2, + .img_width_mask = 0xFFFF, + .img_width_shift = 0x10, + .img_height_mask = 0xFFFF, + .img_height_shift = 0x0, + .mode_mask = 0x1F, + .mode_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x5, + .latency_buf_allocation = 4096, + .input_port_id = OPE_IN_RES_FULL, + .rm_port_id = 0, + .format_type = BUS_RD_COMBO_BAYER_MASK | + BUS_RD_COMBO_YUV_MASK, + .num_combos_supported = 2, + }, + { + .core_cfg = 0x1, + .stripe_location_mask = 0x3, + .stripe_location_shift = 0x0, + .pix_pattern_mask = 0x3F, + .pix_pattern_shift = 0x2, + .img_width_mask = 0xFFFF, + .img_width_shift = 0x10, + .img_height_mask = 0xFFFF, + .img_height_shift = 0x0, + .mode_mask = 0x1F, + .mode_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x5, + .latency_buf_allocation = 4096, + .input_port_id = OPE_IN_RES_FULL, + .rm_port_id = 1, + .format_type = BUS_RD_COMBO_YUV_MASK, + .num_combos_supported = 1, + + }, + }, +}; + +static struct cam_ope_bus_rd_reg ope_bus_rd_reg = { + .offset = 0x4C00, + .hw_version = 0x0, + .sw_reset = 0x4, + .cgc_override = 0x8, + .irq_mask = 0xC, + .irq_clear = 0x10, + .irq_cmd = 0x14, + .irq_status = 0x18, + .input_if_cmd = 0x1C, + .irq_set = 0x20, + .misr_reset = 0x24, + .security_cfg = 0x28, + .iso_cfg = 0x2C, + .iso_seed = 0x30, + .num_clients = 0x2, + .rd_clients = { + { + .core_cfg = 0x50, + .ccif_meta_data = 0x54, + .img_addr = 0x58, + .img_cfg = 0x5C, + .stride = 0x60, + .unpack_cfg = 0x64, + .latency_buf_allocation = 0x78, + .misr_cfg_0 = 0x80, + .misr_cfg_1 = 0x84, + .misr_rd_val = 0x88, + }, + { + .core_cfg = 0xF0, + .ccif_meta_data = 0xF4, + .img_addr = 0xF8, + .img_cfg = 0xFC, + .stride = 0x100, + .unpack_cfg = 0x104, + .latency_buf_allocation = 0x118, + .misr_cfg_0 = 0x120, + .misr_cfg_1 = 0x124, + .misr_rd_val = 0x128, + }, + }, +}; + +static struct cam_ope_bus_wr_reg ope_bus_wr_reg = { + .offset = 0x4D90, + .hw_version = 0x0, + .cgc_override = 0x8, + .irq_mask_0 = 0x18, + .irq_mask_1 = 0x1C, + .irq_clear_0 = 0x20, + .irq_clear_1 = 0x24, + .irq_status_0 = 0x28, + .irq_status_1 = 0x2C, + .irq_cmd = 0x30, + .frame_header_cfg_0 = 0x34, + .local_frame_header_cfg_0 = 0x4C, + .irq_set_0 = 0x50, + .irq_set_1 = 0x54, + .iso_cfg = 0x5C, + .violation_status = 0x64, + .image_size_violation_status = 0x70, + .misr_cfg_0 = 0xB8, + .misr_cfg_1 = 0xBC, + .misr_rd_sel = 0xC8, + .misr_reset = 0xCC, + .misr_val = 0xD0, + .num_clients = 0x8, + .wr_clients = { + { + .core_cfg = 0x200, + .img_addr = 0x204, + .img_cfg = 0x20C, + .x_init = 0x210, + .stride = 0x214, + .pack_cfg = 0x218, + .bw_limit = 0x21C, + .frame_header_addr = 0x220, + .subsample_period = 0x230, + .subsample_pattern = 0x234, + }, + { + .core_cfg = 0x300, + .img_addr = 0x304, + .img_cfg = 0x30C, + .x_init = 0x310, + .stride = 0x314, + .pack_cfg = 0x318, + .bw_limit = 0x31C, + .frame_header_addr = 0x320, + .subsample_period = 0x330, + .subsample_pattern = 0x334, + }, + { + .core_cfg = 0x400, + .img_addr = 0x404, + .img_cfg = 0x40C, + .x_init = 0x410, + .stride = 0x414, + .pack_cfg = 0x418, + .bw_limit = 0x41C, + .frame_header_addr = 0x420, + .subsample_period = 0x430, + .subsample_pattern = 0x434, + }, + { + .core_cfg = 0x500, + .img_addr = 0x504, + .img_cfg = 0x50C, + .x_init = 0x510, + .stride = 0x514, + .pack_cfg = 0x518, + .bw_limit = 0x51C, + .frame_header_addr = 0x520, + .subsample_period = 0x530, + .subsample_pattern = 0x534, + }, + { + .core_cfg = 0x600, + .img_addr = 0x604, + .img_cfg = 0x60C, + .x_init = 0x610, + .stride = 0x614, + .pack_cfg = 0x618, + .bw_limit = 0x61C, + .frame_header_addr = 0x620, + .subsample_period = 0x630, + .subsample_pattern = 0x634, + }, + { + .core_cfg = 0x700, + .img_addr = 0x704, + .img_cfg = 0x70C, + .x_init = 0x710, + .stride = 0x714, + .pack_cfg = 0x718, + .bw_limit = 0x71C, + .frame_header_addr = 0x720, + .subsample_period = 0x730, + .subsample_pattern = 0x734, + }, + { + .core_cfg = 0x800, + .img_addr = 0x804, + .img_cfg = 0x80C, + .x_init = 0x810, + .stride = 0x814, + .pack_cfg = 0x818, + .bw_limit = 0x81C, + .frame_header_addr = 0x820, + .subsample_period = 0x830, + .subsample_pattern = 0x834, + }, + { + .core_cfg = 0x900, + .img_addr = 0x904, + .img_cfg = 0x90C, + .x_init = 0x910, + .stride = 0x914, + .pack_cfg = 0x918, + .bw_limit = 0x91C, + .frame_header_addr = 0x920, + .subsample_period = 0x930, + .subsample_pattern = 0x934, + }, + }, +}; + +static struct cam_ope_bus_wr_reg_val ope_bus_wr_reg_val = { + .hw_version = 0x20010000, + .irq_mask_0 = 0xD0000000, + .irq_mask_1 = 0x0, + .irq_set_clear = 0x1, + .comp_rup_done = 0x1, + .comp_buf_done = 0x100, + .cons_violation = 0x10000000, + .violation = 0x40000000, + .img_size_violation = 0x80000000, + .num_clients = 0x8, + .wr_clients = { + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_VIDEO, + .wm_port_id = BUS_WR_VIDEO_Y, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_VIDEO, + .wm_port_id = BUS_WR_VIDEO_C, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_DISP, + .wm_port_id = BUS_WR_DISP_Y, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_DISP, + .wm_port_id = BUS_WR_DISP_C, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_ARGB, + .wm_port_id = BUS_WR_ARGB, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_STATS_RS, + .wm_port_id = BUS_WR_STATS_RS, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_STATS_IHIST, + .wm_port_id = BUS_WR_STATS_IHIST, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + { + .core_cfg_en = 0x1, + .core_cfg_en_mask = 0x1, + .core_cfg_en_shift = 0x0, + .virtual_frame_en_mask = 0x1, + .virtual_frame_en_shift = 0x1, + .frame_header_en_mask = 0x1, + .frame_header_en_shift = 0x2, + .auto_recovery_en_mask = 0x1, + .auto_recovery_en_shift = 0x4, + .mode_mask = 0x3, + .mode_shift = 0x10, + .width_mask = 0xFFFF, + .width_shift = 0x0, + .height_mask = 0xFFFF, + .height_shift = 0x10, + .format_mask = 0xF, + .format_shift = 0x0, + .alignment_mask = 0x1, + .alignment_shift = 0x4, + .output_port_id = OPE_OUT_RES_STATS_LTM, + .wm_port_id = BUS_WR_STATS_LTM, + .format_type = BUS_WR_COMBO_YUV_MASK, + .num_combos_supported = 1, + }, + }, +}; +static struct ope_hw ope_hw_100 = { + .top_reg = &ope_top_reg, + .top_reg_val = &ope_top_reg_val, + .bus_rd_reg = &ope_bus_rd_reg, + .bus_rd_reg_val = &ope_bus_rd_reg_val, + .bus_wr_reg = &ope_bus_wr_reg, + .bus_wr_reg_val = &ope_bus_wr_reg_val, +}; + +#endif /* CAM_OPE_HW_100_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c new file mode 100644 index 000000000000..7f66abfe455c --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "ope_soc.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" + + +static int cam_ope_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct platform_device *pdev = NULL; + struct device_node *of_node = NULL; + struct ope_dev_soc *ope_soc_info; + + if (!soc_info) { + CAM_ERR(CAM_OPE, "soc_info is NULL"); + return -EINVAL; + } + + pdev = soc_info->pdev; + of_node = pdev->dev.of_node; + ope_soc_info = soc_info->soc_private; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) + CAM_ERR(CAM_OPE, "get ope dt prop is failed: %d", rc); + + ope_soc_info->hfi_en = of_property_read_bool(of_node, "hfi_en"); + + return rc; +} + +static int cam_ope_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t ope_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, ope_irq_handler, + irq_data); + + return rc; +} + +int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ope_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_ope_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + rc = cam_ope_request_platform_resource(soc_info, ope_irq_handler, + irq_data); + if (rc < 0) + return rc; + + return rc; +} + +int cam_ope_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, true); + if (rc) { + CAM_ERR(CAM_OPE, "enable platform failed"); + return rc; + } + + return rc; +} + +int cam_ope_disable_soc_resources(struct cam_hw_soc_info *soc_info, + bool disable_clk) +{ + int rc = 0; + + rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk, + true); + if (rc) + CAM_ERR(CAM_OPE, "enable platform failed"); + + return rc; +} + +int cam_ope_update_clk_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_rate) +{ + int32_t src_clk_idx; + + if (!soc_info) { + CAM_ERR(CAM_OPE, "Invalid soc info"); + return -EINVAL; + } + + src_clk_idx = soc_info->src_clk_idx; + + CAM_DBG(CAM_OPE, "clk_rate = %u src_clk_index = %d", + clk_rate, src_clk_idx); + if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) && + (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && + (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { + CAM_DBG(CAM_OPE, "clk_rate %d greater than max, reset to %d", + clk_rate, + soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); + clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; + } + + CAM_DBG(CAM_OPE, "clk_rate = %u src_clk_index = %d", + clk_rate, src_clk_idx); + return cam_soc_util_set_src_clk_rate(soc_info, clk_rate); +} + +int cam_ope_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable) +{ + int rc = 0; + + if (clk_enable) + rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE); + else + cam_soc_util_clk_disable_default(soc_info); + + return rc; +} diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h new file mode 100644 index 000000000000..a6f0b13a3d2e --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_OPE_SOC_H +#define CAM_OPE_SOC_H + +#include "cam_soc_util.h" + +/** + * struct ope_dev_soc + * + * @hfi_en: HFI enable flag + */ +struct ope_dev_soc { + uint32_t hfi_en; +}; + +int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ope_irq_handler, void *irq_data); + + +int cam_ope_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +int cam_ope_disable_soc_resources(struct cam_hw_soc_info *soc_info, + bool disable_clk); + +int cam_ope_update_clk_rate(struct cam_hw_soc_info *soc_info, + uint32_t clk_rate); + +int cam_ope_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable); +#endif /* CAM_OPE_SOC_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c new file mode 100644 index 000000000000..4d8037c88363 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_hw.h" +#include "cam_hw_intf.h" +#include "ope_core.h" +#include "ope_soc.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" +#include "ope_hw.h" +#include "ope_dev_intf.h" +#include "ope_top.h" + +static struct ope_top ope_top_info; + +static int cam_ope_top_reset(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + struct cam_ope_top_reg *top_reg; + struct cam_ope_top_reg_val *top_reg_val; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + top_reg = ope_hw_info->top_reg; + top_reg_val = ope_hw_info->top_reg_val; + + init_completion(&ope_top_info.reset_complete); + + /* enable interrupt mask */ + cam_io_w_mb(top_reg_val->irq_mask, + ope_hw_info->top_reg->base + top_reg->irq_mask); + + /* OPE SW RESET */ + cam_io_w_mb(top_reg_val->sw_reset_cmd, + ope_hw_info->top_reg->base + top_reg->reset_cmd); + + rc = wait_for_completion_timeout( + &ope_top_info.reset_complete, + msecs_to_jiffies(30)); + + if (!rc || rc < 0) { + CAM_ERR(CAM_OPE, "reset error result = %d", rc); + if (!rc) + rc = -ETIMEDOUT; + } else { + rc = 0; + } + + return rc; +} + +static int cam_ope_top_release(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + + if (ctx_id < 0) { + CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id); + return -EINVAL; + } + + ope_top_info.top_ctx[ctx_id].ope_acquire = NULL; + + return rc; +} + +static int cam_ope_top_acquire(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + + if (ctx_id < 0 || !data) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); + return -EINVAL; + } + + ope_top_info.top_ctx[ctx_id].ope_acquire = data; + + return rc; +} + +static int cam_ope_top_init(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + struct cam_ope_top_reg *top_reg; + struct cam_ope_top_reg_val *top_reg_val; + struct cam_ope_dev_init *dev_init = data; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + top_reg = ope_hw_info->top_reg; + top_reg_val = ope_hw_info->top_reg_val; + + top_reg->base = dev_init->core_info->ope_hw_info->ope_top_base; + + /* OPE SW RESET */ + init_completion(&ope_top_info.reset_complete); + + /* enable interrupt mask */ + cam_io_w_mb(top_reg_val->irq_mask, + ope_hw_info->top_reg->base + top_reg->irq_mask); + + cam_io_w_mb(top_reg_val->sw_reset_cmd, + ope_hw_info->top_reg->base + top_reg->reset_cmd); + + rc = wait_for_completion_timeout( + &ope_top_info.reset_complete, + msecs_to_jiffies(30)); + + if (!rc || rc < 0) { + CAM_ERR(CAM_OPE, "reset error result = %d", rc); + if (!rc) + rc = -ETIMEDOUT; + } else { + rc = 0; + } + + return rc; +} + +static int cam_ope_top_probe(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + ope_top_info.ope_hw_info = ope_hw_info; + + return rc; +} + +static int cam_ope_top_isr(struct ope_hw *ope_hw_info, + int32_t ctx_id, void *data) +{ + int rc = 0; + uint32_t irq_status; + uint32_t violation_status; + struct cam_ope_top_reg *top_reg; + struct cam_ope_top_reg_val *top_reg_val; + struct cam_ope_irq_data *irq_data = data; + + if (!ope_hw_info) { + CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); + return -EINVAL; + } + + top_reg = ope_hw_info->top_reg; + top_reg_val = ope_hw_info->top_reg_val; + + /* Read and Clear Top Interrupt status */ + irq_status = cam_io_r_mb(top_reg->base + top_reg->irq_status); + cam_io_w_mb(irq_status, + top_reg->base + top_reg->irq_clear); + + cam_io_w_mb(top_reg_val->irq_set_clear, + top_reg->base + top_reg->irq_cmd); + + if (irq_status & top_reg_val->rst_done) { + CAM_DBG(CAM_OPE, "ope reset done"); + complete(&ope_top_info.reset_complete); + } + + if (irq_status & top_reg_val->ope_violation) { + violation_status = cam_io_r_mb(top_reg->base + + top_reg->violation_status); + irq_data->error = 1; + CAM_ERR(CAM_OPE, "ope violation: %x", violation_status); + } + + return rc; +} + +int cam_ope_top_process(struct ope_hw *ope_hw_info, + int32_t ctx_id, uint32_t cmd_id, void *data) +{ + int rc = 0; + + switch (cmd_id) { + case OPE_HW_PROBE: + CAM_DBG(CAM_OPE, "OPE_HW_PROBE: E"); + rc = cam_ope_top_probe(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_PROBE: X"); + break; + case OPE_HW_INIT: + CAM_DBG(CAM_OPE, "OPE_HW_INIT: E"); + rc = cam_ope_top_init(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_INIT: X"); + break; + case OPE_HW_DEINIT: + break; + case OPE_HW_ACQUIRE: + CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: E"); + rc = cam_ope_top_acquire(ope_hw_info, ctx_id, data); + CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: X"); + break; + case OPE_HW_PREPARE: + break; + case OPE_HW_RELEASE: + rc = cam_ope_top_release(ope_hw_info, ctx_id, data); + break; + case OPE_HW_START: + break; + case OPE_HW_STOP: + break; + case OPE_HW_FLUSH: + break; + case OPE_HW_ISR: + rc = cam_ope_top_isr(ope_hw_info, 0, data); + break; + case OPE_HW_RESET: + rc = cam_ope_top_reset(ope_hw_info, 0, 0); + break; + default: + break; + } + + return rc; +} diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h new file mode 100644 index 000000000000..6fd935c46e78 --- /dev/null +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef OPE_TOP_H +#define OPE_TOP_H + +#include +#include +#include +#include "ope_hw.h" +#include "cam_hw_mgr_intf.h" +#include "cam_hw_intf.h" +#include "cam_soc_util.h" +#include "cam_context.h" +#include "cam_ope_context.h" +#include "cam_ope_hw_mgr.h" + +/** + * struct ope_top_ctx + * + * @ope_acquire: OPE acquire info + */ +struct ope_top_ctx { + struct ope_acquire_dev_info *ope_acquire; +}; + +/** + * struct ope_top + * + * @ope_hw_info: OPE hardware info + * @top_ctx: OPE top context + * @reset_complete: Reset complete flag + */ +struct ope_top { + struct ope_hw *ope_hw_info; + struct ope_top_ctx top_ctx[OPE_CTX_MAX]; + struct completion reset_complete; +}; +#endif /* OPE_TOP_H */ diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index 1cd21b2a971d..c5e1dc7b671f 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundataion. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundataion. All rights reserved. */ #include @@ -93,6 +93,11 @@ const char *cam_get_module_name(unsigned int module_id) break; case CAM_CUSTOM: name = "CAM-CUSTOM"; + case CAM_OPE: + name = "CAM-OPE"; + break; + case CAM_PRESIL: + name = "CAM-PRESIL"; break; default: name = "CAM"; diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 181a1558a904..5537b2d8db5f 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_DEBUG_UTIL_H_ @@ -39,6 +39,8 @@ /* CAM_PERF: Used for performance (clock, BW etc) logs */ #define CAM_PERF (1 << 25) #define CAM_CUSTOM (1 << 26) +#define CAM_OPE (1 << 28) +#define CAM_PRESIL (1 << 27) #define STR_BUFFER_MAX_LENGTH 1024 diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 9286d0631958..b10b1026acb5 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -48,6 +48,8 @@ #include "cam_debug_util.h" +#include "ope_dev_intf.h" + struct camera_submodule_component { int (*init)(void); void (*exit)(void); @@ -101,6 +103,13 @@ static const struct camera_submodule_component camera_icp[] = { #endif }; +static const struct camera_submodule_component camera_ope[] = { +#ifdef CONFIG_SPECTRA_OPE + {&cam_ope_init_module, &cam_ope_exit_module}, + {&cam_ope_subdev_init_module, &cam_ope_subdev_exit_module}, +#endif +}; + static const struct camera_submodule_component camera_jpeg[] = { #ifdef CONFIG_SPECTRA_JPEG {&cam_jpeg_enc_init_module, &cam_jpeg_enc_exit_module}, @@ -152,6 +161,11 @@ static const struct camera_submodule submodule_table[] = { .num_component = ARRAY_SIZE(camera_icp), .component = camera_icp, }, + { + .name = "Camera OPE", + .num_component = ARRAY_SIZE(camera_ope), + .component = camera_ope, + }, { .name = "Camera JPEG", .num_component = ARRAY_SIZE(camera_jpeg), From a46b9bff7ae635250d0d69eed5e06db6f55c666b Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 20 Dec 2019 14:52:45 +0530 Subject: [PATCH 203/790] msm: camera: ope: Add dynamic clock support Dynamic clock and bandwidth support is added to OPE. CRs-Fixed: 2594541 Change-Id: Ib53ec47c7074f01f1bb55e17c97e5dacc550a129 Signed-off-by: Suresh Vankadara Signed-off-by: Trishansh Bhardwaj --- drivers/cam_ope/cam_ope_context.c | 2 +- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 1008 ++++++++++++++++- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 120 ++ drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 17 + .../cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h | 30 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c | 2 +- include/uapi/camera/media/cam_cpas.h | 9 + 7 files changed, 1143 insertions(+), 45 deletions(-) diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index 83dd07be9de8..0ff45243edd3 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -40,7 +40,7 @@ static int cam_ope_context_dump_active_request(void *data, unsigned long iova, mutex_lock(&ctx->ctx_mutex); if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) { - CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d", + CAM_ERR(CAM_OPE, "Invalid state ope ctx %d state %d", ctx->ctx_id, ctx->state); goto end; } diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index bb73190b1438..dfa457adf3a6 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -125,11 +125,30 @@ static int cam_ope_mgr_reset_hw(void) return rc; } +static void cam_ope_device_timer_stop(struct cam_ope_hw_mgr *hw_mgr) +{ + if (hw_mgr->clk_info.watch_dog) { + hw_mgr->clk_info.watch_dog_reset_counter = 0; + crm_timer_exit(&hw_mgr->clk_info.watch_dog); + hw_mgr->clk_info.watch_dog = NULL; + } +} + +static void cam_ope_device_timer_reset(struct cam_ope_hw_mgr *hw_mgr) +{ + + if (hw_mgr->clk_info.watch_dog) { + CAM_DBG(CAM_OPE, "reset timer"); + crm_timer_reset(hw_mgr->clk_info.watch_dog); + hw_mgr->clk_info.watch_dog_reset_counter++; + } +} + static int cam_ope_req_timer_modify(struct cam_ope_ctx *ctx_data, int32_t expires) { if (ctx_data->req_watch_dog) { - CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + CAM_DBG(CAM_OPE, "stop timer : ctx_id = %d", ctx_data->ctx_id); crm_timer_modify(ctx_data->req_watch_dog, expires); } return 0; @@ -138,7 +157,8 @@ static int cam_ope_req_timer_modify(struct cam_ope_ctx *ctx_data, static int cam_ope_req_timer_stop(struct cam_ope_ctx *ctx_data) { if (ctx_data->req_watch_dog) { - CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id); + CAM_DBG(CAM_OPE, "stop timer : ctx_id = %d", ctx_data->ctx_id); + ctx_data->req_watch_dog_reset_counter = 0; crm_timer_exit(&ctx_data->req_watch_dog); ctx_data->req_watch_dog = NULL; } @@ -147,8 +167,13 @@ static int cam_ope_req_timer_stop(struct cam_ope_ctx *ctx_data) static int cam_ope_req_timer_reset(struct cam_ope_ctx *ctx_data) { - if (ctx_data && ctx_data->req_watch_dog) + if (ctx_data && ctx_data->req_watch_dog) { + ctx_data->req_watch_dog_reset_counter++; + CAM_DBG(CAM_OPE, "reset timer : ctx_id = %d, counter=%d", + ctx_data->ctx_id, + ctx_data->req_watch_dog_reset_counter); crm_timer_reset(ctx_data->req_watch_dog); + } return 0; } @@ -192,14 +217,123 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) { struct ope_clk_work_data *task_data = (struct ope_clk_work_data *)data; struct cam_ope_ctx *ctx_data = (struct cam_ope_ctx *)task_data->data; + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; + uint32_t id; + struct cam_hw_intf *dev_intf = NULL; + struct cam_ope_clk_info *clk_info; + struct cam_ope_dev_bw_update clk_update; + int i = 0; + int device_share_ratio = 1; + int path_index; + + if (!ctx_data) { + CAM_ERR(CAM_OPE, "ctx_data is NULL, failed to update clk"); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + if ((ctx_data->ctx_state != OPE_CTX_STATE_ACQUIRED) || + (ctx_data->req_watch_dog_reset_counter == 0)) { + CAM_DBG(CAM_OPE, "state %d counter = %d", ctx_data->ctx_state, + ctx_data->req_watch_dog_reset_counter); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } if (cam_ope_is_pending_request(ctx_data)) { CAM_DBG(CAM_OPE, "pending requests means, issue is with HW"); cam_cdm_handle_error(ctx_data->ope_cdm.cdm_handle); cam_ope_req_timer_reset(ctx_data); - } else { - cam_ope_req_timer_modify(ctx_data, ~0); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; } + + cam_ope_req_timer_modify(ctx_data, ~0); + /* Remove context BW */ + dev_intf = hw_mgr->ope_dev_intf[0]; + if (!dev_intf) { + CAM_ERR(CAM_OPE, "OPE dev intf is NULL"); + mutex_unlock(&ctx_data->ctx_mutex); + return -EINVAL; + } + + clk_info = &hw_mgr->clk_info; + id = OPE_HW_BW_UPDATE; + device_share_ratio = hw_mgr->num_ope; + + clk_update.ahb_vote.type = CAM_VOTE_DYNAMIC; + clk_update.ahb_vote.vote.freq = 0; + clk_update.ahb_vote_valid = false; + + /* + * Remove previous vote of this context from hw mgr first. + * hw_mgr_clk_info has all valid paths, with each path in its + * own index. BW that we wanted to vote now is after removing + * current context's vote from hw mgr consolidated vote + */ + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + path_index = ctx_data->clk_info.axi_path[i] + .path_data_type - + CAM_AXI_PATH_DATA_OPE_START_OFFSET; + + if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_OPE, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i] + .path_data_type, + CAM_AXI_PATH_DATA_OPE_START_OFFSET, + CAM_OPE_MAX_PER_PATH_VOTES); + continue; + } + + clk_info->axi_path[path_index].camnoc_bw -= + ctx_data->clk_info.axi_path[i].camnoc_bw; + clk_info->axi_path[path_index].mnoc_ab_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + clk_info->axi_path[path_index].mnoc_ib_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + clk_info->axi_path[path_index].ddr_ab_bw -= + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + clk_info->axi_path[path_index].ddr_ib_bw -= + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + } + + memset(&ctx_data->clk_info.axi_path[0], 0, + CAM_OPE_MAX_PER_PATH_VOTES * + sizeof(struct cam_axi_per_path_bw_vote)); + ctx_data->clk_info.curr_fc = 0; + ctx_data->clk_info.base_clk = 0; + + clk_update.axi_vote.num_paths = clk_info->num_paths; + memcpy(&clk_update.axi_vote.axi_path[0], + &clk_info->axi_path[0], + clk_update.axi_vote.num_paths * + sizeof(struct cam_axi_per_path_bw_vote)); + + if (device_share_ratio > 1) { + for (i = 0; i < clk_update.axi_vote.num_paths; i++) { + clk_update.axi_vote.axi_path[i].camnoc_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].mnoc_ab_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].mnoc_ib_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].ddr_ab_bw /= + device_share_ratio; + clk_update.axi_vote.axi_path[i].ddr_ib_bw /= + device_share_ratio; + } + } + + clk_update.axi_vote_valid = true; + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + &clk_update, sizeof(clk_update)); + + CAM_DBG(CAM_OPE, "X :ctx_id = %d curr_fc = %u bc = %u", + ctx_data->ctx_id, ctx_data->clk_info.curr_fc, + ctx_data->clk_info.base_clk); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; } @@ -235,7 +369,153 @@ static int cam_ope_start_req_timer(struct cam_ope_ctx *ctx_data) rc = crm_timer_init(&ctx_data->req_watch_dog, 200, ctx_data, &cam_ope_req_timer_cb); if (rc) - CAM_ERR(CAM_ICP, "Failed to start timer"); + CAM_ERR(CAM_OPE, "Failed to start timer"); + + ctx_data->req_watch_dog_reset_counter = 0; + + return rc; +} + +static int cam_ope_supported_clk_rates(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data) +{ + int i; + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *dev_intf = NULL; + struct cam_hw_info *dev = NULL; + + dev_intf = hw_mgr->ope_dev_intf[0]; + if (!dev_intf) { + CAM_ERR(CAM_OPE, "dev_intf is invalid"); + return -EINVAL; + } + + dev = (struct cam_hw_info *)dev_intf->hw_priv; + soc_info = &dev->soc_info; + + for (i = 0; i < CAM_MAX_VOTE; i++) { + ctx_data->clk_info.clk_rate[i] = + soc_info->clk_rate[i][soc_info->src_clk_idx]; + CAM_DBG(CAM_OPE, "clk_info[%d] = %d", + i, ctx_data->clk_info.clk_rate[i]); + } + + return 0; +} + +static int cam_ope_ctx_clk_info_init(struct cam_ope_ctx *ctx_data) +{ + int i; + + ctx_data->clk_info.curr_fc = 0; + ctx_data->clk_info.base_clk = 0; + ctx_data->clk_info.uncompressed_bw = 0; + ctx_data->clk_info.compressed_bw = 0; + + for (i = 0; i < CAM_OPE_MAX_PER_PATH_VOTES; i++) { + ctx_data->clk_info.axi_path[i].camnoc_bw = 0; + ctx_data->clk_info.axi_path[i].mnoc_ab_bw = 0; + ctx_data->clk_info.axi_path[i].mnoc_ib_bw = 0; + } + + cam_ope_supported_clk_rates(ope_hw_mgr, ctx_data); + + return 0; +} + +static int32_t cam_ope_deinit_idle_clk(void *priv, void *data) +{ + struct cam_ope_hw_mgr *hw_mgr = (struct cam_ope_hw_mgr *)priv; + struct ope_clk_work_data *task_data = (struct ope_clk_work_data *)data; + struct cam_ope_clk_info *clk_info = + (struct cam_ope_clk_info *)task_data->data; + uint32_t id; + uint32_t i; + struct cam_ope_ctx *ctx_data; + struct cam_hw_intf *dev_intf = NULL; + int rc = 0; + bool busy = false; + + clk_info->base_clk = 0; + clk_info->curr_clk = 0; + clk_info->over_clked = 0; + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + for (i = 0; i < OPE_CTX_MAX; i++) { + ctx_data = &hw_mgr->ctx[i]; + mutex_lock(&ctx_data->ctx_mutex); + if (ctx_data->ctx_state == OPE_CTX_STATE_ACQUIRED) { + busy = cam_ope_is_pending_request(ctx_data); + if (busy) { + mutex_unlock(&ctx_data->ctx_mutex); + break; + } + cam_ope_ctx_clk_info_init(ctx_data); + } + mutex_unlock(&ctx_data->ctx_mutex); + } + + if (busy) { + cam_ope_device_timer_reset(hw_mgr); + rc = -EBUSY; + goto done; + } + + dev_intf = hw_mgr->ope_dev_intf[0]; + id = OPE_HW_CLK_DISABLE; + + CAM_DBG(CAM_OPE, "Disable %d", clk_info->hw_type); + + dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, NULL, 0); + +done: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static void cam_ope_device_timer_cb(struct timer_list *timer_data) +{ + unsigned long flags; + struct crm_workq_task *task; + struct ope_clk_work_data *task_data; + struct cam_req_mgr_timer *timer = + container_of(timer_data, struct cam_req_mgr_timer, sys_timer); + + spin_lock_irqsave(&ope_hw_mgr->hw_mgr_lock, flags); + task = cam_req_mgr_workq_get_task(ope_hw_mgr->timer_work); + if (!task) { + CAM_ERR(CAM_OPE, "no empty task"); + spin_unlock_irqrestore(&ope_hw_mgr->hw_mgr_lock, flags); + return; + } + + task_data = (struct ope_clk_work_data *)task->payload; + task_data->data = timer->parent; + task_data->type = OPE_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_ope_deinit_idle_clk; + cam_req_mgr_workq_enqueue_task(task, &ope_hw_mgr, + CRM_TASK_PRIORITY_0); + spin_unlock_irqrestore(&ope_hw_mgr->hw_mgr_lock, flags); +} + +static int cam_ope_device_timer_start(struct cam_ope_hw_mgr *hw_mgr) +{ + int rc = 0; + int i; + + for (i = 0; i < CLK_HW_MAX; i++) { + if (!hw_mgr->clk_info.watch_dog) { + rc = crm_timer_init(&hw_mgr->clk_info.watch_dog, + OPE_DEVICE_IDLE_TIMEOUT, &hw_mgr->clk_info, + &cam_ope_device_timer_cb); + + if (rc) + CAM_ERR(CAM_OPE, "Failed to start timer %d", i); + + hw_mgr->clk_info.watch_dog_reset_counter = 0; + } + } return rc; } @@ -245,7 +525,6 @@ static int cam_get_valid_ctx_id(void) struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; int i; - for (i = 0; i < OPE_CTX_MAX; i++) { if (hw_mgr->ctx[i].ctx_state == OPE_CTX_STATE_ACQUIRED) break; @@ -254,6 +533,551 @@ static int cam_get_valid_ctx_id(void) return i; } +static int cam_ope_get_actual_clk_rate_idx( + struct cam_ope_ctx *ctx_data, uint32_t base_clk) +{ + int i; + + for (i = 0; i < CAM_MAX_VOTE; i++) + if (ctx_data->clk_info.clk_rate[i] >= base_clk) + return i; + + /* + * Caller has to ensure returned index is within array + * size bounds while accessing that index. + */ + + return i; +} + +static bool cam_ope_is_over_clk(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_ope_clk_info *hw_mgr_clk_info) +{ + int base_clk_idx; + int curr_clk_idx; + + base_clk_idx = cam_ope_get_actual_clk_rate_idx(ctx_data, + hw_mgr_clk_info->base_clk); + + curr_clk_idx = cam_ope_get_actual_clk_rate_idx(ctx_data, + hw_mgr_clk_info->curr_clk); + + CAM_DBG(CAM_OPE, "bc_idx = %d cc_idx = %d %d %d", + base_clk_idx, curr_clk_idx, hw_mgr_clk_info->base_clk, + hw_mgr_clk_info->curr_clk); + + if (curr_clk_idx > base_clk_idx) + return true; + + return false; +} + + +static int cam_ope_get_lower_clk_rate(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t base_clk) +{ + int i; + + i = cam_ope_get_actual_clk_rate_idx(ctx_data, base_clk); + + if (i > 0) + return ctx_data->clk_info.clk_rate[i - 1]; + + CAM_DBG(CAM_OPE, "Already clk at lower level"); + + return base_clk; +} + +static int cam_ope_get_next_clk_rate(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t base_clk) +{ + int i; + + i = cam_ope_get_actual_clk_rate_idx(ctx_data, base_clk); + + if (i < CAM_MAX_VOTE - 1) + return ctx_data->clk_info.clk_rate[i + 1]; + + CAM_DBG(CAM_OPE, "Already clk at higher level"); + + return base_clk; +} + +static int cam_ope_get_actual_clk_rate(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, uint32_t base_clk) +{ + int i; + + for (i = 0; i < CAM_MAX_VOTE; i++) + if (ctx_data->clk_info.clk_rate[i] >= base_clk) + return ctx_data->clk_info.clk_rate[i]; + + return base_clk; +} + +static int cam_ope_calc_total_clk(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_clk_info *hw_mgr_clk_info, uint32_t dev_type) +{ + int i; + struct cam_ope_ctx *ctx_data; + + hw_mgr_clk_info->base_clk = 0; + for (i = 0; i < OPE_CTX_MAX; i++) { + ctx_data = &hw_mgr->ctx[i]; + if (ctx_data->ctx_state == OPE_CTX_STATE_ACQUIRED && + ctx_data->ope_acquire.dev_type == dev_type) + hw_mgr_clk_info->base_clk += + ctx_data->clk_info.base_clk; + } + + return 0; +} + +static uint32_t cam_ope_mgr_calc_base_clk(uint32_t frame_cycles, + uint64_t budget) +{ + uint64_t base_clk; + uint64_t mul = 1000000000; + + base_clk = (frame_cycles * mul) / budget; + + CAM_DBG(CAM_OPE, "budget = %lld fc = %d ib = %lld base_clk = %lld", + budget, frame_cycles, + (long long)(frame_cycles * mul), base_clk); + + return base_clk; +} + +static bool cam_ope_update_clk_overclk_free(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_ope_clk_info *hw_mgr_clk_info, + struct cam_ope_clk_bw_request *clk_info, + uint32_t base_clk) +{ + int rc = false; + + /* + * In caseof no pending packets case + * 1. In caseof overclk cnt is less than threshold, increase + * overclk count and no update in the clock rate + * 2. In caseof overclk cnt is greater than or equal to threshold + * then lower clock rate by one level and update hw_mgr current + * clock value. + * a. In case of new clock rate greater than sum of clock + * rates, reset overclk count value to zero if it is + * overclock + * b. if it is less than sum of base clocks then go to next + * level of clock and make overclk count to zero + * c. if it is same as sum of base clock rates update overclock + * cnt to 0 + */ + if (hw_mgr_clk_info->over_clked < hw_mgr_clk_info->threshold) { + hw_mgr_clk_info->over_clked++; + rc = false; + } else { + hw_mgr_clk_info->curr_clk = + cam_ope_get_lower_clk_rate(hw_mgr, ctx_data, + hw_mgr_clk_info->curr_clk); + if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk) { + if (cam_ope_is_over_clk(hw_mgr, ctx_data, + hw_mgr_clk_info)) + hw_mgr_clk_info->over_clked = 0; + } else if (hw_mgr_clk_info->curr_clk < + hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->curr_clk = + cam_ope_get_next_clk_rate(hw_mgr, ctx_data, + hw_mgr_clk_info->curr_clk); + hw_mgr_clk_info->over_clked = 0; + } else if (hw_mgr_clk_info->curr_clk == + hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->over_clked = 0; + } + rc = true; + } + + return rc; +} + +static bool cam_ope_update_clk_free(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_ope_clk_info *hw_mgr_clk_info, + struct cam_ope_clk_bw_request *clk_info, + uint32_t base_clk) +{ + int rc = false; + bool over_clocked = false; + + ctx_data->clk_info.curr_fc = clk_info->frame_cycles; + ctx_data->clk_info.base_clk = base_clk; + cam_ope_calc_total_clk(hw_mgr, hw_mgr_clk_info, + ctx_data->ope_acquire.dev_type); + + /* + * Current clock is not always sum of base clocks, due to + * clock scales update to next higher or lower levels, it + * equals to one of discrete clock values supported by hardware. + * So even current clock is higher than sum of base clocks, we + * can not consider it is over clocked. if it is greater than + * discrete clock level then only it is considered as over clock. + * 1. Handle over clock case + * 2. If current clock is less than sum of base clocks + * update current clock + * 3. If current clock is same as sum of base clocks no action + */ + + over_clocked = cam_ope_is_over_clk(hw_mgr, ctx_data, + hw_mgr_clk_info); + + if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk && + over_clocked) { + rc = cam_ope_update_clk_overclk_free(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, base_clk); + } else if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->over_clked = 0; + rc = false; + } else if (hw_mgr_clk_info->curr_clk < hw_mgr_clk_info->base_clk) { + hw_mgr_clk_info->curr_clk = cam_ope_get_actual_clk_rate(hw_mgr, + ctx_data, hw_mgr_clk_info->base_clk); + rc = true; + } + + return rc; +} + +static bool cam_ope_update_clk_busy(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_ope_clk_info *hw_mgr_clk_info, + struct cam_ope_clk_bw_request *clk_info, + uint32_t base_clk) +{ + uint32_t next_clk_level; + uint32_t actual_clk; + bool rc = false; + + /* 1. if current request frame cycles(fc) are more than previous + * frame fc + * Calculate the new base clock. + * if sum of base clocks are more than next available clk level + * Update clock rate, change curr_clk_rate to sum of base clock + * rates and make over_clked to zero + * else + * Update clock rate to next level, update curr_clk_rate and make + * overclked cnt to zero + * 2. if current fc is less than or equal to previous frame fc + * Still Bump up the clock to next available level + * if it is available, then update clock, make overclk cnt to + * zero. If the clock is already at highest clock rate then + * no need to update the clock + */ + ctx_data->clk_info.base_clk = base_clk; + hw_mgr_clk_info->over_clked = 0; + if (clk_info->frame_cycles > ctx_data->clk_info.curr_fc) { + cam_ope_calc_total_clk(hw_mgr, hw_mgr_clk_info, + ctx_data->ope_acquire.dev_type); + actual_clk = cam_ope_get_actual_clk_rate(hw_mgr, + ctx_data, base_clk); + if (hw_mgr_clk_info->base_clk > actual_clk) { + hw_mgr_clk_info->curr_clk = hw_mgr_clk_info->base_clk; + } else { + next_clk_level = cam_ope_get_next_clk_rate(hw_mgr, + ctx_data, hw_mgr_clk_info->curr_clk); + hw_mgr_clk_info->curr_clk = next_clk_level; + } + rc = true; + } else { + next_clk_level = + cam_ope_get_next_clk_rate(hw_mgr, ctx_data, + hw_mgr_clk_info->curr_clk); + if (hw_mgr_clk_info->curr_clk < next_clk_level) { + hw_mgr_clk_info->curr_clk = next_clk_level; + rc = true; + } + } + ctx_data->clk_info.curr_fc = clk_info->frame_cycles; + + return rc; +} + +static bool cam_ope_check_clk_update(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, int idx) +{ + bool busy = false, rc = false; + uint32_t base_clk; + struct cam_ope_clk_bw_request *clk_info; + uint64_t req_id; + struct cam_ope_clk_info *hw_mgr_clk_info; + + /* TODO: Have default clock rates update */ + /* TODO: Add support for debug clock updates */ + cam_ope_req_timer_reset(ctx_data); + cam_ope_device_timer_reset(hw_mgr); + hw_mgr_clk_info = &hw_mgr->clk_info; + req_id = ctx_data->req_list[idx]->request_id; + if (ctx_data->req_cnt > 1) + busy = true; + + CAM_DBG(CAM_OPE, "busy = %d req_id = %lld", busy, req_id); + + clk_info = &ctx_data->req_list[idx]->clk_info; + + /* Calculate base clk rate */ + base_clk = cam_ope_mgr_calc_base_clk( + clk_info->frame_cycles, clk_info->budget_ns); + ctx_data->clk_info.rt_flag = clk_info->rt_flag; + + if (busy) + rc = cam_ope_update_clk_busy(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, base_clk); + else + rc = cam_ope_update_clk_free(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info, base_clk); + + CAM_DBG(CAM_OPE, "bc = %d cc = %d busy = %d overclk = %d uc = %d", + hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk, + busy, hw_mgr_clk_info->over_clked, rc); + + return rc; +} + +static int cam_ope_mgr_update_clk_rate(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data) +{ + struct cam_ope_dev_clk_update clk_upd_cmd; + int i; + + clk_upd_cmd.clk_rate = hw_mgr->clk_info.curr_clk; + + CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d", clk_upd_cmd.clk_rate, + ctx_data->ope_acquire.dev_type); + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_CLK_UPDATE, + &clk_upd_cmd, sizeof(clk_upd_cmd)); + } + + return 0; +} + +static bool cam_ope_update_bw_v2(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, + struct cam_ope_clk_info *hw_mgr_clk_info, + struct cam_ope_clk_bw_req_internal_v2 *clk_info, + bool busy) +{ + int i, path_index; + bool update_required = true; + + /* + * If current request bandwidth is different from previous frames, then + * recalculate bandwidth of all contexts of same hardware and update + * voting of bandwidth + */ + + for (i = 0; i < clk_info->num_paths; i++) + CAM_DBG(CAM_OPE, "clk_info camnoc = %lld busy = %d", + clk_info->axi_path[i].camnoc_bw, busy); + + if (clk_info->num_paths == ctx_data->clk_info.num_paths) { + update_required = false; + for (i = 0; i < clk_info->num_paths; i++) { + if ((clk_info->axi_path[i].transac_type == + ctx_data->clk_info.axi_path[i].transac_type) && + (clk_info->axi_path[i].path_data_type == + ctx_data->clk_info.axi_path[i].path_data_type) && + (clk_info->axi_path[i].camnoc_bw == + ctx_data->clk_info.axi_path[i].camnoc_bw) && + (clk_info->axi_path[i].mnoc_ab_bw == + ctx_data->clk_info.axi_path[i].mnoc_ab_bw)) { + continue; + } else { + update_required = true; + break; + } + } + } + + if (!update_required) { + CAM_DBG(CAM_OPE, + "Incoming BW hasn't changed, no update required"); + return false; + } + + if (busy) { + for (i = 0; i < clk_info->num_paths; i++) { + if (ctx_data->clk_info.axi_path[i].camnoc_bw > + clk_info->axi_path[i].camnoc_bw) + return false; + } + } + + /* + * Remove previous vote of this context from hw mgr first. + * hw_mgr_clk_info has all valid paths, with each path in its own index + */ + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + path_index = + ctx_data->clk_info.axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_OPE_START_OFFSET; + + if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_OPE, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_OPE_START_OFFSET, + CAM_OPE_MAX_PER_PATH_VOTES); + continue; + } + + hw_mgr_clk_info->axi_path[path_index].camnoc_bw -= + ctx_data->clk_info.axi_path[i].camnoc_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ib_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ab_bw -= + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ib_bw -= + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + } + + ctx_data->clk_info.num_paths = clk_info->num_paths; + + memcpy(&ctx_data->clk_info.axi_path[0], + &clk_info->axi_path[0], + clk_info->num_paths * sizeof(struct cam_axi_per_path_bw_vote)); + + /* + * Add new vote of this context in hw mgr. + * hw_mgr_clk_info has all paths, with each path in its own index + */ + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + path_index = + ctx_data->clk_info.axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_OPE_START_OFFSET; + + if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_OPE, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_OPE_START_OFFSET, + CAM_OPE_MAX_PER_PATH_VOTES); + continue; + } + + hw_mgr_clk_info->axi_path[path_index].path_data_type = + ctx_data->clk_info.axi_path[i].path_data_type; + hw_mgr_clk_info->axi_path[path_index].transac_type = + ctx_data->clk_info.axi_path[i].transac_type; + hw_mgr_clk_info->axi_path[path_index].camnoc_bw += + ctx_data->clk_info.axi_path[i].camnoc_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw += + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ib_bw += + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ab_bw += + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ib_bw += + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + CAM_DBG(CAM_OPE, + "Consolidate Path Vote : Dev[%s] i[%d] path_idx[%d] : [%s %s] [%lld %lld]", + ctx_data->ope_acquire.dev_name, + i, path_index, + cam_cpas_axi_util_trans_type_to_string( + hw_mgr_clk_info->axi_path[path_index].transac_type), + cam_cpas_axi_util_path_type_to_string( + hw_mgr_clk_info->axi_path[path_index].path_data_type), + hw_mgr_clk_info->axi_path[path_index].camnoc_bw, + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw); + } + + if (hw_mgr_clk_info->num_paths < ctx_data->clk_info.num_paths) + hw_mgr_clk_info->num_paths = ctx_data->clk_info.num_paths; + + return true; +} + +static bool cam_ope_check_bw_update(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, int idx) +{ + bool busy = false, bw_updated = false; + int i; + struct cam_ope_clk_bw_req_internal_v2 *clk_info_v2; + struct cam_ope_clk_info *hw_mgr_clk_info; + uint64_t req_id; + + hw_mgr_clk_info = &hw_mgr->clk_info; + req_id = ctx_data->req_list[idx]->request_id; + if (ctx_data->req_cnt > 1) + busy = true; + + clk_info_v2 = &ctx_data->req_list[idx]->clk_info_v2; + + bw_updated = cam_ope_update_bw_v2(hw_mgr, ctx_data, + hw_mgr_clk_info, clk_info_v2, busy); + + for (i = 0; i < hw_mgr_clk_info->num_paths; i++) { + CAM_DBG(CAM_OPE, + "Final path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s", + cam_cpas_axi_util_path_type_to_string( + hw_mgr_clk_info->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + hw_mgr_clk_info->axi_path[i].transac_type), + hw_mgr_clk_info->axi_path[i].camnoc_bw, + hw_mgr_clk_info->axi_path[i].mnoc_ab_bw, + hw_mgr_clk_info->axi_path[i].mnoc_ib_bw, + ctx_data->ope_acquire.dev_name); + } + + return bw_updated; +} + +static int cam_ope_update_cpas_vote(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data) +{ + int i = 0; + struct cam_ope_clk_info *clk_info; + struct cam_ope_dev_bw_update bw_update = {{0}, {0}, 0, 0}; + + clk_info = &hw_mgr->clk_info; + + bw_update.ahb_vote.type = CAM_VOTE_DYNAMIC; + bw_update.ahb_vote.vote.freq = 0; + bw_update.ahb_vote_valid = false; + + + bw_update.axi_vote.num_paths = clk_info->num_paths; + memcpy(&bw_update.axi_vote.axi_path[0], + &clk_info->axi_path[0], + bw_update.axi_vote.num_paths * + sizeof(struct cam_axi_per_path_bw_vote)); + + bw_update.axi_vote_valid = true; + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_BW_UPDATE, + &bw_update, sizeof(bw_update)); + } + + return 0; +} + +static int cam_ope_mgr_ope_clk_update(struct cam_ope_hw_mgr *hw_mgr, + struct cam_ope_ctx *ctx_data, int idx) +{ + int rc = 0; + + if (cam_ope_check_clk_update(hw_mgr, ctx_data, idx)) + rc = cam_ope_mgr_update_clk_rate(hw_mgr, ctx_data); + + if (cam_ope_check_bw_update(hw_mgr, ctx_data, idx)) + rc |= cam_ope_update_cpas_vote(hw_mgr, ctx_data); + + return rc; +} static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, enum cam_cdm_cb_status status, uint64_t cookie) @@ -289,6 +1113,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, handle, userdata, status, cookie, ope_req->request_id, ctx->ctx_id); cam_ope_req_timer_reset(ctx); + cam_ope_device_timer_reset(ope_hw_mgr); } else if (status == CAM_CDM_CB_STATUS_HW_RESUBMIT) { CAM_INFO(CAM_OPE, "After reset of CDM and OPE, reapply req"); rc = cam_ope_mgr_reapply_config(ope_hw_mgr, ctx, ope_req); @@ -1344,10 +2169,12 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } cam_ope_start_req_timer(ctx); + cam_ope_device_timer_start(hw_mgr); hw_mgr->ope_ctx_cnt++; ctx->context_priv = args->context_data; args->ctxt_to_hw_map = ctx; ctx->ctxt_event_cb = args->event_cb; + cam_ope_ctx_clk_info_init(ctx); ctx->ctx_state = OPE_CTX_STATE_ACQUIRED; mutex_unlock(&ctx->ctx_mutex); @@ -1502,29 +2329,26 @@ static int cam_ope_mgr_release_hw(void *hw_priv, void *hw_release_args) rc = cam_ope_mgr_release_ctx(hw_mgr, ctx_id); if (!hw_mgr->ope_ctx_cnt) { CAM_DBG(CAM_OPE, "Last Release"); - if (!hw_mgr->ope_ctx_cnt) { - for (i = 0; i < ope_hw_mgr->num_ope; i++) { - dev_intf = hw_mgr->ope_dev_intf[i]; - irq_cb.ope_hw_mgr_cb = NULL; - irq_cb.data = NULL; - rc = dev_intf->hw_ops.process_cmd( - hw_mgr->ope_dev_intf[i]->hw_priv, - OPE_HW_SET_IRQ_CB, - &irq_cb, sizeof(irq_cb)); - if (rc) - CAM_ERR(CAM_OPE, "IRQ dereg failed: %d", - rc); - } - for (i = 0; i < ope_hw_mgr->num_ope; i++) { - dev_intf = hw_mgr->ope_dev_intf[i]; - rc = dev_intf->hw_ops.deinit( - hw_mgr->ope_dev_intf[i]->hw_priv, - NULL, 0); - if (rc) - CAM_ERR(CAM_OPE, "deinit failed: %d", - rc); - } + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + dev_intf = hw_mgr->ope_dev_intf[i]; + irq_cb.ope_hw_mgr_cb = NULL; + irq_cb.data = NULL; + rc = dev_intf->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_SET_IRQ_CB, + &irq_cb, sizeof(irq_cb)); + if (rc) + CAM_ERR(CAM_OPE, "IRQ dereg failed: %d", rc); } + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + dev_intf = hw_mgr->ope_dev_intf[i]; + rc = dev_intf->hw_ops.deinit( + hw_mgr->ope_dev_intf[i]->hw_priv, + NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "deinit failed: %d", rc); + } + cam_ope_device_timer_stop(hw_mgr); } mutex_unlock(&hw_mgr->hw_mgr_mutex); @@ -1533,6 +2357,123 @@ static int cam_ope_mgr_release_hw(void *hw_priv, void *hw_release_args) return rc; } +static int cam_ope_packet_generic_blob_handler(void *user_data, + uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) +{ + struct cam_ope_clk_bw_request *clk_info; + struct ope_clk_bw_request_v2 *soc_req_v2; + struct cam_ope_clk_bw_req_internal_v2 *clk_info_v2; + struct ope_cmd_generic_blob *blob; + struct cam_ope_ctx *ctx_data; + uint32_t index; + size_t clk_update_size; + int rc = 0; + + if (!blob_data || (blob_size == 0)) { + CAM_ERR(CAM_OPE, "Invalid blob info %pK %d", blob_data, + blob_size); + return -EINVAL; + } + + blob = (struct ope_cmd_generic_blob *)user_data; + ctx_data = blob->ctx; + index = blob->req_idx; + + switch (blob_type) { + case OPE_CMD_GENERIC_BLOB_CLK_V2: + if (blob_size < sizeof(struct ope_clk_bw_request_v2)) { + CAM_ERR(CAM_OPE, "Mismatch blob size %d expected %lu", + blob_size, + sizeof(struct ope_clk_bw_request_v2)); + return -EINVAL; + } + + soc_req_v2 = (struct ope_clk_bw_request_v2 *)blob_data; + if (soc_req_v2->num_paths > CAM_OPE_MAX_PER_PATH_VOTES) { + CAM_ERR(CAM_OPE, "Invalid num paths: %d", + soc_req_v2->num_paths); + return -EINVAL; + } + + /* Check for integer overflow */ + if (soc_req_v2->num_paths != 1) { + if (sizeof(struct cam_axi_per_path_bw_vote) > + ((UINT_MAX - + sizeof(struct ope_clk_bw_request_v2)) / + (soc_req_v2->num_paths - 1))) { + CAM_ERR(CAM_OPE, + "Size exceeds limit paths:%u size per path:%lu", + soc_req_v2->num_paths - 1, + sizeof( + struct cam_axi_per_path_bw_vote)); + return -EINVAL; + } + } + + clk_update_size = sizeof(struct ope_clk_bw_request_v2) + + ((soc_req_v2->num_paths - 1) * + sizeof(struct cam_axi_per_path_bw_vote)); + if (blob_size < clk_update_size) { + CAM_ERR(CAM_OPE, "Invalid blob size: %u", + blob_size); + return -EINVAL; + } + + clk_info = &ctx_data->req_list[index]->clk_info; + clk_info_v2 = &ctx_data->req_list[index]->clk_info_v2; + + memcpy(clk_info_v2, soc_req_v2, clk_update_size); + + /* Use v1 structure for clk fields */ + clk_info->budget_ns = clk_info_v2->budget_ns; + clk_info->frame_cycles = clk_info_v2->frame_cycles; + clk_info->rt_flag = clk_info_v2->rt_flag; + + CAM_DBG(CAM_OPE, "budget=%llu, frame_cycle=%llu, rt_flag=%d", + clk_info_v2->budget_ns, clk_info_v2->frame_cycles, + clk_info_v2->rt_flag); + break; + + default: + CAM_WARN(CAM_OPE, "Invalid blob type %d", blob_type); + break; + } + return rc; +} + +static int cam_ope_process_generic_cmd_buffer( + struct cam_packet *packet, + struct cam_ope_ctx *ctx_data, + int32_t index, + uint64_t *io_buf_addr) +{ + int i, rc = 0; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct ope_cmd_generic_blob cmd_generic_blob; + + cmd_generic_blob.ctx = ctx_data; + cmd_generic_blob.req_idx = index; + cmd_generic_blob.io_buf_addr = io_buf_addr; + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + + for (i = 0; i < packet->num_cmd_buf; i++) { + if (!cmd_desc[i].length) + continue; + + if (cmd_desc[i].meta_data != OPE_CMD_META_GENERIC_BLOB) + continue; + + rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[i], + cam_ope_packet_generic_blob_handler, &cmd_generic_blob); + if (rc) + CAM_ERR(CAM_OPE, "Failed in processing blobs %d", rc); + } + + return rc; +} + static int cam_ope_mgr_prepare_hw_update(void *hw_priv, void *hw_prepare_update_args) { @@ -1641,6 +2582,13 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, goto end; } + rc = cam_ope_process_generic_cmd_buffer(packet, ctx_data, + request_idx, NULL); + if (rc) { + mutex_unlock(&ctx_data->ctx_mutex); + CAM_ERR(CAM_OPE, "Failed: %d", rc); + goto end; + } prepare_args->num_hw_update_entries = 1; prepare_args->hw_update_entries[0].addr = (uintptr_t)ctx_data->req_list[request_idx]->cdm_cmd; @@ -1755,6 +2703,8 @@ static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args) config_args->hw_update_entries->addr; cdm_cmd->cookie = ope_req->req_idx; + cam_ope_mgr_ope_clk_update(hw_mgr, ctx_data, ope_req->req_idx); + rc = cam_ope_mgr_enqueue_config(hw_mgr, ctx_data, config_args); if (rc) goto config_err; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index bd88ceb3d764..f062c61706e3 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -52,6 +52,112 @@ #define OPE_MAX_CDM_BLS 16 +#define CAM_OPE_MAX_PER_PATH_VOTES 6 +#define CAM_OPE_BW_CONFIG_UNKNOWN 0 +#define CAM_OPE_BW_CONFIG_V2 2 + +#define CLK_HW_OPE 0x0 +#define CLK_HW_MAX 0x1 + +#define OPE_DEVICE_IDLE_TIMEOUT 400 + + +/** + * struct cam_ope_clk_bw_request_v2 + * @budget_ns: Time required to process frame + * @frame_cycles: Frame cycles needed to process the frame + * @rt_flag: Flag to indicate real time stream + * @num_paths: Number of paths for per path bw vote + * @axi_path: Per path vote info for OPE + */ +struct cam_ope_clk_bw_req_internal_v2 { + uint64_t budget_ns; + uint32_t frame_cycles; + uint32_t rt_flag; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_OPE_MAX_PER_PATH_VOTES]; +}; + +/** + * struct cam_ope_clk_bw_request + * @budget_ns: Time required to process frame + * @frame_cycles: Frame cycles needed to process the frame + * @rt_flag: Flag to indicate real time stream + * @uncompressed_bw: Bandwidth required to process frame + * @compressed_bw: Compressed bandwidth to process frame + */ +struct cam_ope_clk_bw_request { + uint64_t budget_ns; + uint32_t frame_cycles; + uint32_t rt_flag; + uint64_t uncompressed_bw; + uint64_t compressed_bw; +}; + +/** + * struct cam_ctx_clk_info + * @curr_fc: Context latest request frame cycles + * @rt_flag: Flag to indicate real time request + * @base_clk: Base clock to process the request + * @reserved: Reserved field + * @uncompressed_bw: Current bandwidth voting + * @compressed_bw: Current compressed bandwidth voting + * @clk_rate: Supported clock rates for the context + * @num_paths: Number of valid AXI paths + * @axi_path: ctx based per path bw vote + */ +struct cam_ctx_clk_info { + uint32_t curr_fc; + uint32_t rt_flag; + uint32_t base_clk; + uint32_t reserved; + uint64_t uncompressed_bw; + uint64_t compressed_bw; + int32_t clk_rate[CAM_MAX_VOTE]; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_OPE_MAX_PER_PATH_VOTES]; +}; + +/** + * struct ope_cmd_generic_blob + * @ctx: Current context info + * @req_info_idx: Index used for request + * @io_buf_addr: pointer to io buffer address + */ +struct ope_cmd_generic_blob { + struct cam_ope_ctx *ctx; + uint32_t req_idx; + uint64_t *io_buf_addr; +}; + +/** + * struct cam_ope_clk_info + * @base_clk: Base clock to process request + * @curr_clk: Current clock of hadrware + * @threshold: Threshold for overclk count + * @over_clked: Over clock count + * @uncompressed_bw: Current bandwidth voting + * @compressed_bw: Current compressed bandwidth voting + * @num_paths: Number of AXI vote paths + * @axi_path: Current per path bw vote info + * @hw_type: IPE/BPS device type + * @watch_dog: watchdog timer handle + * @watch_dog_reset_counter: Counter for watch dog reset + */ +struct cam_ope_clk_info { + uint32_t base_clk; + uint32_t curr_clk; + uint32_t threshold; + uint32_t over_clked; + uint64_t uncompressed_bw; + uint64_t compressed_bw; + uint32_t num_paths; + struct cam_axi_per_path_bw_vote axi_path[CAM_OPE_MAX_PER_PATH_VOTES]; + uint32_t hw_type; + struct cam_req_mgr_timer *watch_dog; + uint32_t watch_dog_reset_counter; +}; + /** * struct ope_cmd_work_data * @@ -273,6 +379,8 @@ struct ope_io_buf { * @ope_debug_buf: Debug buffer * @io_buf: IO config info of a request * @cdm_cmd: CDM command for OPE CDM + * @clk_info: Clock Info V1 + * @clk_info_v2: Clock Info V2 */ struct cam_ope_request { uint64_t request_id; @@ -290,6 +398,8 @@ struct cam_ope_request { struct ope_debug_buffer ope_debug_buf; struct ope_io_buf io_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_IO_BUFS]; struct cam_cdm_bl_request *cdm_cmd; + struct cam_ope_clk_bw_request clk_info; + struct cam_ope_clk_bw_req_internal_v2 clk_info_v2; }; /** @@ -320,6 +430,10 @@ struct cam_ope_cdm { * @req_list: Request List * @ope_cdm: OPE CDM info * @req_watch_dog: Watchdog for requests + * @req_watch_dog_reset_counter: Request reset counter + * @clk_info: OPE Ctx clock info + * @clk_watch_dog: Clock watchdog + * @clk_watch_dog_reset_counter: Reset counter */ struct cam_ope_ctx { void *context_priv; @@ -336,6 +450,10 @@ struct cam_ope_ctx { struct cam_ope_request *req_list[CAM_CTX_REQ_MAX]; struct cam_ope_cdm ope_cdm; struct cam_req_mgr_timer *req_watch_dog; + uint32_t req_watch_dog_reset_counter; + struct cam_ctx_clk_info clk_info; + struct cam_req_mgr_timer *clk_watch_dog; + uint32_t clk_watch_dog_reset_counter; }; /** @@ -366,6 +484,7 @@ struct cam_ope_ctx { * @timer_work_data: Timer work data * @ope_dev_intf: OPE device interface * @cdm_reg_map: OPE CDM register map + * @clk_info: OPE clock Info for HW manager */ struct cam_ope_hw_mgr { int32_t open_cnt; @@ -394,6 +513,7 @@ struct cam_ope_hw_mgr { struct ope_clk_work_data *timer_work_data; struct cam_hw_intf *ope_dev_intf[OPE_DEV_MAX]; struct cam_soc_reg_map *cdm_reg_map[OPE_DEV_MAX][OPE_BASE_MAX]; + struct cam_ope_clk_info clk_info; }; #endif /* CAM_OPE_HW_MGR_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index d2af4ebd2f1c..bc16bded1f30 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -1711,11 +1711,28 @@ int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type, struct cam_ope_dev_clk_update *clk_upd_cmd = (struct cam_ope_dev_clk_update *)cmd_args; + if (core_info->clk_enable == false) { + rc = cam_soc_util_clk_enable_default(soc_info, + CAM_SVS_VOTE); + if (rc) { + CAM_ERR(CAM_OPE, "Clock enable is failed"); + return rc; + } + core_info->clk_enable = true; + } + rc = cam_ope_update_clk_rate(soc_info, clk_upd_cmd->clk_rate); if (rc) CAM_ERR(CAM_OPE, "Failed to update clk: %d", rc); } break; + case OPE_HW_CLK_DISABLE: { + if (core_info->clk_enable == true) + cam_soc_util_clk_disable_default(soc_info); + + core_info->clk_enable = false; + } + break; case OPE_HW_BW_UPDATE: { struct cam_ope_dev_bw_update *cpas_vote = cmd_args; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h index 462752bd7f3d..9e35fb80613c 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h @@ -12,20 +12,22 @@ #include "cam_cpas_api.h" -#define OPE_HW_INIT 0x1 -#define OPE_HW_DEINIT 0x2 -#define OPE_HW_ACQUIRE 0x3 -#define OPE_HW_RELEASE 0x4 -#define OPE_HW_START 0x5 -#define OPE_HW_STOP 0x6 -#define OPE_HW_FLUSH 0x7 -#define OPE_HW_PREPARE 0x8 -#define OPE_HW_ISR 0x9 -#define OPE_HW_PROBE 0xA -#define OPE_HW_CLK_UPDATE 0xB -#define OPE_HW_BW_UPDATE 0xC -#define OPE_HW_RESET 0xD -#define OPE_HW_SET_IRQ_CB 0xE +#define OPE_HW_INIT 0x1 +#define OPE_HW_DEINIT 0x2 +#define OPE_HW_ACQUIRE 0x3 +#define OPE_HW_RELEASE 0x4 +#define OPE_HW_START 0x5 +#define OPE_HW_STOP 0x6 +#define OPE_HW_FLUSH 0x7 +#define OPE_HW_PREPARE 0x8 +#define OPE_HW_ISR 0x9 +#define OPE_HW_PROBE 0xA +#define OPE_HW_CLK_UPDATE 0xB +#define OPE_HW_BW_UPDATE 0xC +#define OPE_HW_RESET 0xD +#define OPE_HW_SET_IRQ_CB 0xE +#define OPE_HW_CLK_DISABLE 0xF +#define OPE_HW_CLK_ENABLE 0x10 /** * struct cam_ope_dev_probe diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c index 7f66abfe455c..ca83bb31dbe4 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "ope_soc.h" #include "cam_soc_util.h" #include "cam_debug_util.h" diff --git a/include/uapi/camera/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h index 2a44d93497b4..d78b384ce771 100644 --- a/include/uapi/camera/media/cam_cpas.h +++ b/include/uapi/camera/media/cam_cpas.h @@ -52,6 +52,15 @@ #define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) +#define CAM_AXI_PATH_DATA_OPE_START_OFFSET 64 +#define CAM_AXI_PATH_DATA_OPE_RD_IN (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 0) +#define CAM_AXI_PATH_DATA_OPE_RD_REF (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 1) +#define CAM_AXI_PATH_DATA_OPE_WR_VID (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 2) +#define CAM_AXI_PATH_DATA_OPE_WR_DISP (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 3) +#define CAM_AXI_PATH_DATA_OPE_WR_REF (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 4) +#define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ + (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) + #define CAM_AXI_PATH_DATA_ALL 256 /** From 41533c5eb28d8b71dbf204414942220de5c24894 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 20 Dec 2019 14:55:20 +0530 Subject: [PATCH 204/790] msm: camera: ope: Corrected batch mode and stripe for ope Corrected the striping creation for non real time device. Disabled the ope stripe base bus. Corrected the batch mode creation for ope bus read. CRs-Fixed: 2594541 Change-Id: I87adbab25b84d74162a6a8ce2db1412a6d9058d0 Signed-off-by: Rishabh Jain Signed-off-by: Trishansh Bhardwaj --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 2 ++ .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 14 +++++++---- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 23 ++++++++----------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index dfa457adf3a6..13cc29e46b5d 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1504,6 +1504,8 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, stripe_info->pack_format = pack_format; stripe_info->unpack_format = unpack_format; + stripe_info->disable_bus = + in_stripe_info->disable_bus; cam_ope_mgr_print_stripe_info(i, j, k, l, stripe_info, iova_addr); } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index 3deb8ed92212..649f5084c027 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -346,11 +346,15 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, header_size = cdm_ops->cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); - io_port_cdm->go_cmd_addr = kmd_buf; - io_port_cdm->go_cmd_len = - sizeof(temp) * (count + header_size); - io_port_cdm->go_cmd_offset = - prepare->kmd_buf_offset; + for (i = 0; i < ope_request->num_batch; i++) { + io_port_cdm = + &bus_rd_ctx->io_port_cdm_batch.io_port_cdm[i]; + io_port_cdm->go_cmd_addr = kmd_buf; + io_port_cdm->go_cmd_len = + sizeof(temp) * (count + header_size); + io_port_cdm->go_cmd_offset = + prepare->kmd_buf_offset; + } kmd_buf = cdm_ops->cdm_write_regrandom( kmd_buf, count/2, temp_reg); prepare->kmd_buf_offset += diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index bc16bded1f30..25f03f640111 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -772,7 +772,7 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, hw_mgr->iommu_hdl); return NULL; } - iova_addr = iova_addr + frm_proc->cmd_buf[j][i].offset; + iova_addr = iova_addr + frm_proc->cmd_buf[i][j].offset; rc = cam_mem_get_cpu_buf( frm_proc->cmd_buf[i][j].mem_handle, @@ -1123,7 +1123,7 @@ static uint32_t *ope_create_stripes_nrt(struct cam_ope_hw_mgr *hw_mgr, struct cam_ope_ctx *ctx_data, uint32_t req_idx, uint32_t *kmd_buf, struct cam_ope_dev_prepare_req *ope_dev_prepare_req, - uint32_t kmd_buf_offset) + uint32_t *kmd_buf_offset, uint32_t **cdm_kmd_start_addr) { int i, j; struct cam_ope_request *ope_request; @@ -1133,13 +1133,10 @@ static uint32_t *ope_create_stripes_nrt(struct cam_ope_hw_mgr *hw_mgr, uint32_t stripe_idx = 0; struct cam_cdm_utils_ops *cdm_ops; uint32_t len; - uint32_t *cdm_kmd_start_addr; int num_nrt_stripes, num_arb; frm_proc = ope_dev_prepare_req->frame_process; ope_request = ctx_data->req_list[req_idx]; - cdm_kmd_start_addr = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + - (kmd_buf_offset / sizeof(len)); num_nrt_stripes = ctx_data->ope_acquire.nrt_stripes_for_arb; num_arb = ope_request->num_stripes[0] / ctx_data->ope_acquire.nrt_stripes_for_arb; @@ -1162,17 +1159,17 @@ static uint32_t *ope_create_stripes_nrt(struct cam_ope_hw_mgr *hw_mgr, kmd_buf = cdm_ops->cdm_write_wait_comp_event( kmd_buf, OPE_WAIT_COMP_IDLE, 0x0); - len = (kmd_buf - cdm_kmd_start_addr) * + len = (kmd_buf - *cdm_kmd_start_addr) * sizeof(uint32_t); cam_ope_dev_prepare_cdm_request( ope_dev_prepare_req->hw_mgr, ope_dev_prepare_req->prepare_args, ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, - kmd_buf_offset, ope_dev_prepare_req, + *kmd_buf_offset, ope_dev_prepare_req, len, true); - cdm_kmd_start_addr = kmd_buf; - kmd_buf_offset += len; + *cdm_kmd_start_addr = kmd_buf; + *kmd_buf_offset += len; } /* cmd buffer stripes */ kmd_buf = ope_create_stripe_cmd(hw_mgr, ctx_data, @@ -1317,7 +1314,7 @@ static int cam_ope_dev_create_kmd_buf_nrt(struct cam_ope_hw_mgr *hw_mgr, /* Stripes */ kmd_buf = ope_create_stripes_nrt(hw_mgr, ctx_data, req_idx, kmd_buf, - ope_dev_prepare_req, kmd_buf_offset); + ope_dev_prepare_req, &kmd_buf_offset, &cdm_kmd_start_addr); if (!kmd_buf) { rc = -EINVAL; goto end; @@ -1358,7 +1355,7 @@ static int cam_ope_dev_create_kmd_buf_batch(struct cam_ope_hw_mgr *hw_mgr, frm_proc = ope_dev_prepare_req->frame_process; ope_request = ctx_data->req_list[req_idx]; kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + - kmd_buf_offset; + (kmd_buf_offset / sizeof(len)); cdm_kmd_start_addr = kmd_buf; cdm_ops = ctx_data->ope_cdm.cdm_ops; @@ -1436,11 +1433,11 @@ static int cam_ope_dev_create_kmd_buf_batch(struct cam_ope_hw_mgr *hw_mgr, OPE_WAIT_COMP_IDLE, 0x0); /* prepare CDM submit packet */ - len = (cdm_kmd_start_addr - kmd_buf) * sizeof(uint32_t); + len = (kmd_buf - cdm_kmd_start_addr) * sizeof(uint32_t); cam_ope_dev_prepare_cdm_request(ope_dev_prepare_req->hw_mgr, ope_dev_prepare_req->prepare_args, ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, - ope_dev_prepare_req->kmd_buf_offset, ope_dev_prepare_req, + kmd_buf_offset, ope_dev_prepare_req, len, false); end: From 376b7a33514035a114184bf1a9160ca04e050af7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 19 Dec 2019 15:42:18 -0800 Subject: [PATCH 205/790] msm: camera: sync: Enable driver registration with dtsi match Currently sync driver is independent from dtsi matching in order to get it probe. Update the logic to make sure probe is getting invoked if respective dtsi is present. CRs-Fixed: 2590413 Change-Id: I69124e49d68e223d082521a9431cb7e8d846e8d7 Signed-off-by: Jigarkumar Zala --- drivers/cam_sync/cam_sync.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 81b3625c3239..f32cc1c2dbef 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -1107,51 +1107,48 @@ vdev_fail: static int cam_sync_remove(struct platform_device *pdev) { + int i; + v4l2_device_unregister(sync_dev->vdev->v4l2_dev); cam_sync_media_controller_cleanup(sync_dev); video_device_release(sync_dev->vdev); debugfs_remove_recursive(sync_dev->dentry); sync_dev->dentry = NULL; + + for (i = 0; i < CAM_SYNC_MAX_OBJS; i++) + spin_lock_init(&sync_dev->row_spinlocks[i]); kfree(sync_dev); sync_dev = NULL; return 0; } -static struct platform_device cam_sync_device = { - .name = "cam_sync", - .id = -1, +static const struct of_device_id cam_sync_dt_match[] = { + {.compatible = "qcom,cam-sync"}, + {} }; +MODULE_DEVICE_TABLE(of, cam_sync_dt_match); + static struct platform_driver cam_sync_driver = { .probe = cam_sync_probe, .remove = cam_sync_remove, .driver = { .name = "cam_sync", .owner = THIS_MODULE, + .of_match_table = cam_sync_dt_match, .suppress_bind_attrs = true, }, }; int cam_sync_init(void) { - int rc; - rc = platform_device_register(&cam_sync_device); - if (rc) - return -ENODEV; - return platform_driver_register(&cam_sync_driver); } void cam_sync_exit(void) { - int idx; - - for (idx = 0; idx < CAM_SYNC_MAX_OBJS; idx++) - spin_lock_init(&sync_dev->row_spinlocks[idx]); platform_driver_unregister(&cam_sync_driver); - platform_device_unregister(&cam_sync_device); - kfree(sync_dev); } MODULE_DESCRIPTION("Camera sync driver"); From 2c76e695e3b67e7a64a657bf3f6ec160bd2b717b Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 20 Dec 2019 14:59:27 +0530 Subject: [PATCH 206/790] msm: camera: isp: Move the ife hw manager resource to isp hw manager Hardware manager resource is generic. Move the resource definition to isp hw manager so that it can be used by other hw manager. Remove the parent and child graph in the hardware manager resource as it is not used. Use the common isp resource type everywhere. CRs-Fixed: 2594541 Change-Id: I41d49af0855f3bd3768450d850b1284ff1e3fea9 Signed-off-by: Ravikishore Pampana Signed-off-by: Trishansh Bhardwaj --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 319 ++++++++---------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 83 ++--- drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h | 50 ++- .../hw_utils/cam_isp_packet_parser.c | 53 +-- .../hw_utils/include/cam_isp_packet_parser.h | 16 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 6 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 9 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 9 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 10 +- 10 files changed, 254 insertions(+), 302 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 36dbdc17e807..05a166cd01bd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -63,8 +63,8 @@ static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, uint32_t *reg_base_idx) { int rc = 0; - struct cam_ife_hw_mgr_res *hw_mgr_res; - struct cam_ife_hw_mgr_res *hw_mgr_res_temp; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res_temp; struct cam_hw_soc_info *soc_info = NULL; struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *) hw_mgr_ctx; @@ -229,7 +229,7 @@ static int cam_ife_hw_mgr_is_rdi_res(uint32_t res_id) } static int cam_ife_hw_mgr_reset_csid_res( - struct cam_ife_hw_mgr_res *isp_hw_res) + struct cam_isp_hw_mgr_res *isp_hw_res) { int i; int rc = 0; @@ -262,7 +262,7 @@ err: } static int cam_ife_hw_mgr_init_hw_res( - struct cam_ife_hw_mgr_res *isp_hw_res) + struct cam_isp_hw_mgr_res *isp_hw_res) { int i; int rc = -1; @@ -291,7 +291,7 @@ err: } static int cam_ife_hw_mgr_start_hw_res( - struct cam_ife_hw_mgr_res *isp_hw_res, + struct cam_isp_hw_mgr_res *isp_hw_res, struct cam_ife_hw_mgr_ctx *ctx) { int i; @@ -327,7 +327,7 @@ err: } static void cam_ife_hw_mgr_stop_hw_res( - struct cam_ife_hw_mgr_res *isp_hw_res) + struct cam_isp_hw_mgr_res *isp_hw_res) { int i; struct cam_hw_intf *hw_intf; @@ -349,7 +349,7 @@ static void cam_ife_hw_mgr_stop_hw_res( else CAM_ERR(CAM_ISP, "stop null"); if (hw_intf->hw_ops.process_cmd && - isp_hw_res->res_type == CAM_IFE_HW_MGR_RES_IFE_OUT) { + isp_hw_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) { hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ, &dummy_args, sizeof(dummy_args)); @@ -358,7 +358,7 @@ static void cam_ife_hw_mgr_stop_hw_res( } static void cam_ife_hw_mgr_deinit_hw_res( - struct cam_ife_hw_mgr_res *isp_hw_res) + struct cam_isp_hw_mgr_res *isp_hw_res) { int i; struct cam_hw_intf *hw_intf; @@ -377,7 +377,7 @@ static void cam_ife_hw_mgr_deinit_hw_res( static void cam_ife_hw_mgr_deinit_hw( struct cam_ife_hw_mgr_ctx *ctx) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; int i = 0; if (!ctx->init_done) { @@ -417,7 +417,7 @@ static void cam_ife_hw_mgr_deinit_hw( static int cam_ife_hw_mgr_init_hw( struct cam_ife_hw_mgr_ctx *ctx) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; int rc = 0, i; CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", @@ -491,10 +491,10 @@ deinit: static int cam_ife_hw_mgr_put_res( struct list_head *src_list, - struct cam_ife_hw_mgr_res **res) + struct cam_isp_hw_mgr_res **res) { int rc = 0; - struct cam_ife_hw_mgr_res *res_ptr = NULL; + struct cam_isp_hw_mgr_res *res_ptr = NULL; res_ptr = *res; if (res_ptr) @@ -505,14 +505,14 @@ static int cam_ife_hw_mgr_put_res( static int cam_ife_hw_mgr_get_res( struct list_head *src_list, - struct cam_ife_hw_mgr_res **res) + struct cam_isp_hw_mgr_res **res) { int rc = 0; - struct cam_ife_hw_mgr_res *res_ptr = NULL; + struct cam_isp_hw_mgr_res *res_ptr = NULL; if (!list_empty(src_list)) { res_ptr = list_first_entry(src_list, - struct cam_ife_hw_mgr_res, list); + struct cam_isp_hw_mgr_res, list); list_del_init(&res_ptr->list); } else { CAM_ERR(CAM_ISP, "No more free ife hw mgr ctx"); @@ -524,7 +524,7 @@ static int cam_ife_hw_mgr_get_res( } static int cam_ife_hw_mgr_free_hw_res( - struct cam_ife_hw_mgr_res *isp_hw_res) + struct cam_isp_hw_mgr_res *isp_hw_res) { int rc = 0; int i; @@ -625,8 +625,8 @@ static void cam_ife_hw_mgr_dump_src_acq_info( struct cam_ife_hw_mgr_ctx *hwr_mgr_ctx, uint32_t num_pix_port, uint32_t num_rdi_port) { - struct cam_ife_hw_mgr_res *hw_mgr_res = NULL; - struct cam_ife_hw_mgr_res *hw_mgr_res_temp = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res_temp = NULL; struct cam_isp_resource_node *hw_res = NULL; int i = 0; @@ -653,8 +653,8 @@ static void cam_ife_hw_mgr_dump_src_acq_info( static void cam_ife_hw_mgr_dump_acq_data( struct cam_ife_hw_mgr_ctx *hwr_mgr_ctx) { - struct cam_ife_hw_mgr_res *hw_mgr_res = NULL; - struct cam_ife_hw_mgr_res *hw_mgr_res_temp = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res_temp = NULL; struct cam_isp_resource_node *hw_res = NULL; struct timespec64 *ts = NULL; uint64_t ms, tmp, hrs, min, sec; @@ -761,7 +761,7 @@ static int cam_ife_mgr_csid_stop_hw( struct cam_ife_hw_mgr_ctx *ctx, struct list_head *stop_list, uint32_t base_idx, uint32_t stop_cmd) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *isp_res; struct cam_isp_resource_node *stop_res[CAM_IFE_PIX_PATH_RES_MAX - 1]; struct cam_csid_hw_stop_args stop; @@ -801,8 +801,8 @@ static int cam_ife_hw_mgr_release_hw_for_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx) { uint32_t i; - struct cam_ife_hw_mgr_res *hw_mgr_res; - struct cam_ife_hw_mgr_res *hw_mgr_res_temp; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res_temp; /* ife leaf resource */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) @@ -837,7 +837,7 @@ static int cam_ife_hw_mgr_release_hw_for_ctx( } /* ife root node */ - if (ife_ctx->res_list_ife_in.res_type != CAM_IFE_HW_MGR_RES_UNINIT) + if (ife_ctx->res_list_ife_in.res_type != CAM_ISP_RESOURCE_UNINT) cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_in); /* clean up the callback function */ @@ -930,7 +930,7 @@ static void cam_ife_mgr_add_base_info( static int cam_ife_mgr_process_base_info( struct cam_ife_hw_mgr_ctx *ctx) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *res = NULL; uint32_t i; @@ -941,7 +941,7 @@ static int cam_ife_mgr_process_base_info( /* IFE mux in resources */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { - if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) continue; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { @@ -966,9 +966,9 @@ static int cam_ife_hw_mgr_acquire_res_bus_rd( { int rc = -EINVAL; struct cam_vfe_acquire_args vfe_acquire; - struct cam_ife_hw_mgr_res *ife_in_rd_res; + struct cam_isp_hw_mgr_res *ife_in_rd_res; struct cam_hw_intf *hw_intf; - struct cam_ife_hw_mgr_res *ife_src_res; + struct cam_isp_hw_mgr_res *ife_src_res; int i; CAM_DBG(CAM_ISP, "Enter"); @@ -991,7 +991,7 @@ static int cam_ife_hw_mgr_acquire_res_bus_rd( vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops; vfe_acquire.priv = ife_ctx; vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; - vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_vfe; + vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_isp; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!ife_src_res->hw_res[i]) continue; @@ -1000,7 +1000,7 @@ static int cam_ife_hw_mgr_acquire_res_bus_rd( 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) { + if (ife_src_res->is_dual_isp) { /*TBD */ vfe_acquire.vfe_out.is_master = 1; vfe_acquire.vfe_out.dual_slave_core = @@ -1034,9 +1034,8 @@ static int cam_ife_hw_mgr_acquire_res_bus_rd( 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; + ife_in_rd_res->is_dual_isp = in_port->usage_type; + ife_in_rd_res->res_type = CAM_ISP_RESOURCE_VFE_BUS_RD; } return 0; @@ -1047,13 +1046,13 @@ err: 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, - struct cam_isp_in_port_generic_info *in_port) + struct cam_isp_hw_mgr_res *ife_src_res, + struct cam_isp_in_port_generic_info *in_port) { int rc = -EINVAL; struct cam_vfe_acquire_args vfe_acquire; struct cam_isp_out_port_generic_info *out_port = NULL; - struct cam_ife_hw_mgr_res *ife_out_res; + struct cam_isp_hw_mgr_res *ife_out_res; struct cam_hw_intf *hw_intf; uint32_t i, vfe_out_res_id, vfe_in_res_id; @@ -1120,13 +1119,10 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi( } ife_out_res->hw_res[0] = vfe_acquire.vfe_out.rsrc_node; - ife_out_res->is_dual_vfe = 0; + ife_out_res->is_dual_isp = 0; ife_out_res->res_id = vfe_out_res_id; - 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); + ife_out_res->res_type = CAM_ISP_RESOURCE_VFE_OUT; + ife_src_res->num_children++; return 0; err: @@ -1134,16 +1130,16 @@ err: } static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( - struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_ife_hw_mgr_res *ife_src_res, + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_hw_mgr_res *ife_src_res, struct cam_isp_in_port_generic_info *in_port, - bool acquire_lcr) + bool acquire_lcr) { int rc = -1; uint32_t i, j, k; struct cam_vfe_acquire_args vfe_acquire; struct cam_isp_out_port_generic_info *out_port; - struct cam_ife_hw_mgr_res *ife_out_res; + struct cam_isp_hw_mgr_res *ife_out_res; struct cam_hw_intf *hw_intf; for (i = 0; i < in_port->num_out_res; i++) { @@ -1173,14 +1169,14 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( CAM_DBG(CAM_ISP, "res_type 0x%x", out_port->res_type); ife_out_res = &ife_ctx->res_list_ife_out[k]; - ife_out_res->is_dual_vfe = in_port->usage_type; + ife_out_res->is_dual_isp = in_port->usage_type; vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_OUT; vfe_acquire.tasklet = ife_ctx->common.tasklet_info; vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops; vfe_acquire.priv = ife_ctx; vfe_acquire.vfe_out.out_port_info = out_port; - vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_vfe; + vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_isp; vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; @@ -1193,7 +1189,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( if (j == CAM_ISP_HW_SPLIT_LEFT) { vfe_acquire.vfe_out.split_id = CAM_ISP_HW_SPLIT_LEFT; - if (ife_src_res->is_dual_vfe) { + if (ife_src_res->is_dual_isp) { /*TBD */ vfe_acquire.vfe_out.is_master = 1; vfe_acquire.vfe_out.dual_slave_core = @@ -1227,13 +1223,9 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( ife_out_res->hw_res[j]->res_id); } - ife_out_res->res_type = - (enum cam_ife_hw_mgr_res_type)CAM_ISP_RESOURCE_VFE_OUT; + ife_out_res->res_type = CAM_ISP_RESOURCE_VFE_OUT; 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); + ife_src_res->num_children++; } return 0; @@ -1247,7 +1239,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out( struct cam_isp_in_port_generic_info *in_port) { int rc = -EINVAL; - struct cam_ife_hw_mgr_res *ife_src_res; + struct cam_isp_hw_mgr_res *ife_src_res; list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) { if (ife_src_res->num_children) @@ -1291,8 +1283,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_rd_src( struct cam_isp_in_port_generic_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_isp_hw_mgr_res *csid_res; + struct cam_isp_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; @@ -1324,10 +1316,9 @@ static int cam_ife_hw_mgr_acquire_res_ife_rd_src( 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_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; + ife_src_res->is_dual_isp = csid_res->is_dual_isp; hw_intf = ife_hw_mgr->ife_devices[csid_res->hw_res[ @@ -1339,7 +1330,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_rd_src( /* * fill in more acquire information as needed */ - if (ife_src_res->is_dual_vfe) + if (ife_src_res->is_dual_isp) vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, @@ -1359,7 +1350,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_rd_src( 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) + if (!ife_src_res->is_dual_isp) goto acq; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { @@ -1397,13 +1388,7 @@ 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); + csid_res->num_children++; } err: @@ -1505,8 +1490,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( { int rc = -1; int i; - struct cam_ife_hw_mgr_res *csid_res; - struct cam_ife_hw_mgr_res *ife_src_res; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_isp_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; @@ -1544,13 +1529,13 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( else vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_LCR; - if (csid_res->is_dual_vfe) + if (csid_res->is_dual_isp) vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER; else vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; - vfe_acquire.vfe_in.is_dual = csid_res->is_dual_vfe; + vfe_acquire.vfe_in.is_dual = csid_res->is_dual_isp; break; case CAM_IFE_PIX_PATH_RES_PPP: @@ -1579,10 +1564,9 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( CAM_ERR(CAM_ISP, "Wrong IFE CSID Resource Node"); goto err; } - ife_src_res->res_type = - (enum cam_ife_hw_mgr_res_type)vfe_acquire.rsrc_type; + ife_src_res->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; + ife_src_res->is_dual_isp = csid_res->is_dual_isp; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!csid_res->hw_res[i]) @@ -1592,7 +1576,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( csid_res->hw_res[i]->hw_intf->hw_idx]; if (i == CAM_ISP_HW_SPLIT_LEFT && - ife_src_res->is_dual_vfe) { + ife_src_res->is_dual_isp) { vfe_acquire.vfe_in.dual_hw_idx = ife_ctx->slave_hw_idx; } @@ -1600,7 +1584,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( /* fill in more acquire information as needed */ /* slave Camif resource, */ if (i == CAM_ISP_HW_SPLIT_RIGHT && - ife_src_res->is_dual_vfe) { + ife_src_res->is_dual_isp) { vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE; vfe_acquire.vfe_in.dual_hw_idx = @@ -1637,13 +1621,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( ife_src_res->hw_res[i]->res_id); } - - 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); + csid_res->num_children++; } return 0; @@ -1701,16 +1679,16 @@ static int cam_ife_hw_mgr_acquire_csid_hw( } static int cam_ife_mgr_acquire_cid_res( - struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, - struct cam_ife_hw_mgr_res **cid_res, - enum cam_ife_pix_path_res_id path_res_id) + struct cam_isp_hw_mgr_res **cid_res, + enum cam_ife_pix_path_res_id path_res_id) { int rc = -1; int i, j; - struct cam_ife_hw_mgr *ife_hw_mgr; - struct cam_hw_intf *hw_intf; - struct cam_ife_hw_mgr_res *cid_res_temp, *cid_res_iterator; + struct cam_ife_hw_mgr *ife_hw_mgr; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_mgr_res *cid_res_temp, *cid_res_iterator; struct cam_csid_hw_reserve_resource_args csid_acquire; uint32_t acquired_cnt = 0; struct cam_isp_out_port_generic_info *out_port = NULL; @@ -1812,10 +1790,10 @@ acquire_successful: CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d", in_port->usage_type); - cid_res_temp->res_type = CAM_IFE_HW_MGR_RES_CID; + cid_res_temp->res_type = CAM_ISP_RESOURCE_CID; /* CID(DT_ID) value of acquire device, require for path */ cid_res_temp->res_id = csid_acquire.node_res->res_id; - cid_res_temp->is_dual_vfe = in_port->usage_type; + cid_res_temp->is_dual_isp = in_port->usage_type; ife_ctx->is_dual = (bool)in_port->usage_type; if (ife_ctx->is_dual) ife_ctx->master_hw_idx = @@ -1829,7 +1807,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 && path_res_id + if (cid_res_temp->is_dual_isp && 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; @@ -1861,11 +1839,6 @@ acquire_successful: CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d", in_port->usage_type); } - 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: @@ -1886,8 +1859,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( int master_idx = -1; struct cam_ife_hw_mgr *ife_hw_mgr; - struct cam_ife_hw_mgr_res *csid_res; - struct cam_ife_hw_mgr_res *cid_res; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_isp_hw_mgr_res *cid_res; struct cam_hw_intf *hw_intf; struct cam_csid_hw_reserve_resource_args csid_acquire; enum cam_ife_pix_path_res_id path_res_id; @@ -1913,22 +1886,21 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( goto end; } - csid_res->res_type = - (enum cam_ife_hw_mgr_res_type)CAM_ISP_RESOURCE_PIX_PATH; + csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH; csid_res->res_id = path_res_id; if (in_port->usage_type && is_ipp) - csid_res->is_dual_vfe = 1; + csid_res->is_dual_isp = 1; else { - csid_res->is_dual_vfe = 0; + csid_res->is_dual_isp = 0; 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); + for (i = 0; i <= csid_res->is_dual_isp; i++) { + CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_isp); csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; csid_acquire.res_id = path_res_id; @@ -1941,7 +1913,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( hw_intf = cid_res->hw_res[i]->hw_intf; - if (csid_res->is_dual_vfe) { + if (csid_res->is_dual_isp) { if (i == CAM_ISP_HW_SPLIT_LEFT) { master_idx = hw_intf->hw_idx; csid_acquire.sync_mode = @@ -1974,12 +1946,11 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( (is_ipp) ? "IPP" : "PPP"); } cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); - - csid_res->parent = cid_res; - cid_res->child[cid_res->num_children++] = csid_res; + cid_res->num_children++; 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); @@ -2025,11 +1996,11 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( int rc = -EINVAL; int i; - struct cam_ife_hw_mgr *ife_hw_mgr; - struct cam_ife_hw_mgr_res *csid_res; - struct cam_ife_hw_mgr_res *cid_res; - struct cam_hw_intf *hw_intf; - struct cam_isp_out_port_generic_info *out_port; + struct cam_ife_hw_mgr *ife_hw_mgr; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_isp_hw_mgr_res *cid_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_out_port_generic_info *out_port; struct cam_csid_hw_reserve_resource_args csid_acquire; enum cam_ife_pix_path_res_id path_res_id; @@ -2096,19 +2067,13 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( goto put_res; } - csid_res->res_type = (enum cam_ife_hw_mgr_res_type) - CAM_ISP_RESOURCE_PIX_PATH; + csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH; csid_res->res_id = csid_acquire.res_id; - csid_res->is_dual_vfe = 0; + csid_res->is_dual_isp = 0; csid_res->hw_res[0] = csid_acquire.node_res; csid_res->hw_res[1] = NULL; - 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); - + cid_res->num_children++; } return 0; @@ -2124,11 +2089,11 @@ static int cam_ife_hw_mgr_acquire_res_root( { int rc = -1; - if (ife_ctx->res_list_ife_in.res_type == CAM_IFE_HW_MGR_RES_UNINIT) { + if (ife_ctx->res_list_ife_in.res_type == CAM_ISP_RESOURCE_UNINT) { /* first acquire */ - ife_ctx->res_list_ife_in.res_type = CAM_IFE_HW_MGR_RES_ROOT; + ife_ctx->res_list_ife_in.res_type = CAM_ISP_RESOURCE_SRC; 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; + ife_ctx->res_list_ife_in.is_dual_isp = in_port->usage_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"); @@ -2318,7 +2283,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( uint32_t *acquired_hw_id, uint32_t *acquired_hw_path) { int rc = -1; - int is_dual_vfe = 0; + int is_dual_isp = 0; int ipp_count = 0; int rdi_count = 0; int ppp_count = 0; @@ -2326,12 +2291,11 @@ static int cam_ife_mgr_acquire_hw_for_ctx( int lcr_count = 0; bool crop_enable = true; - is_dual_vfe = in_port->usage_type; - + is_dual_isp = in_port->usage_type; /* get root node resource */ rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port); if (rc) { - CAM_ERR(CAM_ISP, "Can not acquire csid rx resource"); + CAM_ERR(CAM_ISP, "Can not acquire root resource"); goto err; } @@ -2444,7 +2408,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, } hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata; - ctx = (struct cam_ife_hw_mgr_ctx *)hw_update_data->ife_mgr_ctx; + ctx = (struct cam_ife_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { complete_all(&ctx->config_done_complete); @@ -3104,7 +3068,7 @@ static const char *cam_isp_util_usage_data_to_string( } static int cam_isp_classify_vote_info( - struct cam_ife_hw_mgr_res *hw_mgr_res, + struct cam_isp_hw_mgr_res *hw_mgr_res, struct cam_isp_bw_config_v2 *bw_config, struct cam_axi_vote *isp_vote, uint32_t split_idx, @@ -3201,7 +3165,7 @@ static int cam_isp_blob_bw_update_v2( struct cam_isp_bw_config_v2 *bw_config, struct cam_ife_hw_mgr_ctx *ctx) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_vfe_bw_update_args_v2 bw_upd_args; int rc = -EINVAL; @@ -3268,7 +3232,7 @@ static int cam_isp_blob_bw_update( struct cam_isp_bw_config *bw_config, struct cam_ife_hw_mgr_ctx *ctx) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_vfe_bw_update_args bw_upd_args; uint64_t cam_bw_bps = 0; @@ -3401,7 +3365,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, } hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; - hw_update_data->ife_mgr_ctx = ctx; + hw_update_data->isp_mgr_ctx = ctx; CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); @@ -3511,7 +3475,7 @@ static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args) { int rc = 0; struct cam_hw_stop_args *stop_args = stop_hw_args; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_ife_hw_mgr_ctx *ctx; uint32_t i, master_base_idx = 0; @@ -3596,7 +3560,7 @@ static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args) static int cam_ife_mgr_bw_control(struct cam_ife_hw_mgr_ctx *ctx, enum cam_vfe_bw_control_action action) { - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_vfe_bw_control_args bw_ctrl_args; int rc = -EINVAL; @@ -3641,7 +3605,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) int rc = 0; struct cam_hw_stop_args *stop_args = stop_hw_args; struct cam_isp_stop_args *stop_isp; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_ife_hw_mgr_ctx *ctx; enum cam_ife_csid_halt_cmd csid_halt_type; uint32_t i, master_base_idx = 0; @@ -3804,7 +3768,7 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args) int rc = -1; struct cam_hw_start_args *start_args = start_hw_args; struct cam_ife_hw_mgr_ctx *ctx; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; uint32_t i; if (!start_hw_args) { @@ -3883,7 +3847,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_hw_stop_args stop_args; struct cam_isp_stop_args stop_isp; struct cam_ife_hw_mgr_ctx *ctx; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *rsrc_node = NULL; uint32_t i, camif_debug; bool res_rdi_context_set = false; @@ -4122,7 +4086,7 @@ static int cam_ife_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_hw_reset_args *reset_args = hw_reset_args; struct cam_ife_hw_mgr_ctx *ctx; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; int rc = 0, i = 0; if (!hw_mgr_priv || !hw_reset_args) { @@ -4223,7 +4187,7 @@ static int cam_isp_blob_fe_update( 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_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; int rc = -EINVAL; uint32_t i; @@ -4297,7 +4261,7 @@ static int cam_isp_blob_ubwc_update( struct cam_ubwc_plane_cfg_v1 *ubwc_plane_cfg; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; @@ -4468,7 +4432,7 @@ static int cam_isp_blob_ubwc_update_v2( struct cam_ubwc_plane_cfg_v2 *ubwc_plane_cfg; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; @@ -4586,7 +4550,7 @@ static int cam_isp_blob_hfr_update( struct cam_isp_port_hfr_config *port_hfr_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; @@ -4682,7 +4646,7 @@ static int cam_isp_blob_csid_clock_update( 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_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_ife_csid_clock_update_args csid_clock_upd_args; uint64_t clk_rate = 0; @@ -4729,7 +4693,7 @@ static int cam_isp_blob_csid_qcfa_update( 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_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_ife_csid_qcfa_update_args csid_qcfa_upd_args; int rc = -EINVAL; @@ -4777,7 +4741,7 @@ static int cam_isp_blob_core_cfg_update( 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_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; uint64_t clk_rate = 0; int rc = 0, i; @@ -4825,7 +4789,7 @@ static int cam_isp_blob_clock_update( 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_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_vfe_clock_update_args clock_upd_args; uint64_t clk_rate = 0; @@ -4937,7 +4901,7 @@ static int cam_isp_blob_vfe_out_update( struct cam_isp_vfe_wm_config *wm_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; - struct cam_ife_hw_mgr_res *ife_out_res; + struct cam_isp_hw_mgr_res *ife_out_res; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; @@ -5677,7 +5641,7 @@ static int cam_ife_mgr_sof_irq_debug( { int rc = 0; uint32_t i = 0; - struct cam_ife_hw_mgr_res *hw_mgr_res = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; struct cam_hw_intf *hw_intf = NULL; struct cam_isp_resource_node *rsrc_node = NULL; @@ -5913,12 +5877,12 @@ static int cam_ife_mgr_cmd_get_sof_timestamp( { int rc = -EINVAL; uint32_t i; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; struct cam_csid_get_time_stamp_args csid_get_time; hw_mgr_res = list_first_entry(&ife_ctx->res_list_ife_csid, - struct cam_ife_hw_mgr_res, list); + struct cam_isp_hw_mgr_res, list); for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) @@ -5966,12 +5930,12 @@ static int cam_ife_mgr_cmd_get_sof_timestamp( static int cam_ife_mgr_process_recovery_cb(void *priv, void *data) { int32_t rc = 0; - struct cam_hw_event_recovery_data *recovery_data = data; - struct cam_hw_start_args start_args; - struct cam_hw_stop_args stop_args; - struct cam_ife_hw_mgr *ife_hw_mgr = priv; - struct cam_ife_hw_mgr_res *hw_mgr_res; - uint32_t i = 0; + struct cam_ife_hw_event_recovery_data *recovery_data = data; + struct cam_hw_start_args start_args; + struct cam_hw_stop_args stop_args; + struct cam_ife_hw_mgr *ife_hw_mgr = priv; + struct cam_isp_hw_mgr_res *hw_mgr_res; + uint32_t i = 0; uint32_t error_type = recovery_data->error_type; struct cam_ife_hw_mgr_ctx *ctx = NULL; @@ -6058,20 +6022,17 @@ static int cam_ife_mgr_process_recovery_cb(void *priv, void *data) } static int cam_ife_hw_mgr_do_error_recovery( - struct cam_hw_event_recovery_data *ife_mgr_recovery_data) + struct cam_ife_hw_event_recovery_data *ife_mgr_recovery_data) { - int32_t rc = 0; - struct crm_workq_task *task = NULL; - struct cam_hw_event_recovery_data *recovery_data = NULL; + int32_t rc = 0; + struct crm_workq_task *task = NULL; + struct cam_ife_hw_event_recovery_data *recovery_data = NULL; - recovery_data = kzalloc(sizeof(struct cam_hw_event_recovery_data), - GFP_ATOMIC); + recovery_data = kmemdup(ife_mgr_recovery_data, + sizeof(struct cam_ife_hw_event_recovery_data), GFP_ATOMIC); if (!recovery_data) return -ENOMEM; - memcpy(recovery_data, ife_mgr_recovery_data, - sizeof(struct cam_hw_event_recovery_data)); - CAM_DBG(CAM_ISP, "Enter: error_type (%d)", recovery_data->error_type); task = cam_req_mgr_workq_get_task(g_ife_hw_mgr.workq); @@ -6143,9 +6104,9 @@ static bool cam_ife_hw_mgr_is_ctx_affected( * b. Notify CTX with fatal error */ static int cam_ife_hw_mgr_find_affected_ctx( - struct cam_isp_hw_error_event_data *error_event_data, - uint32_t curr_core_idx, - struct cam_hw_event_recovery_data *recovery_data) + struct cam_isp_hw_error_event_data *error_event_data, + uint32_t curr_core_idx, + struct cam_ife_hw_event_recovery_data *recovery_data) { uint32_t affected_core[CAM_IFE_HW_NUM_MAX] = {0}; struct cam_ife_hw_mgr_ctx *ife_hwr_mgr_ctx = NULL; @@ -6205,11 +6166,11 @@ static int cam_ife_hw_mgr_find_affected_ctx( static int cam_ife_hw_mgr_handle_hw_err( void *evt_info) { - struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_isp_hw_event_info *event_info = evt_info; uint32_t core_idx; - struct cam_isp_hw_error_event_data error_event_data = {0}; - struct cam_hw_event_recovery_data recovery_data = {0}; - int rc = -EINVAL; + struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_ife_hw_event_recovery_data recovery_data = {0}; + int rc = -EINVAL; if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; @@ -6731,7 +6692,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) int i, j; struct cam_iommu_handle cdm_handles; struct cam_ife_hw_mgr_ctx *ctx_pool; - struct cam_ife_hw_mgr_res *res_list_ife_out; + struct cam_isp_hw_mgr_res *res_list_ife_out; CAM_DBG(CAM_ISP, "Enter"); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 17a9e11834df..7d68b180e5c4 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_HW_MGR_H_ @@ -13,68 +13,11 @@ #include "cam_ife_csid_hw_intf.h" #include "cam_tasklet_util.h" -/* enum cam_ife_hw_mgr_res_type - manager resource node type */ -enum cam_ife_hw_mgr_res_type { - CAM_IFE_HW_MGR_RES_UNINIT, - CAM_IFE_HW_MGR_RES_ROOT, - 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, -}; - /* IFE resource constants */ #define CAM_IFE_HW_IN_RES_MAX (CAM_ISP_IFE_IN_RES_MAX & 0xFF) #define CAM_IFE_HW_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_MAX & 0xFF) #define CAM_IFE_HW_RES_POOL_MAX 64 -/** - * struct cam_vfe_hw_mgr_res- HW resources for the VFE manager - * - * @list: used by the resource list - * @res_type: IFE manager resource type - * @res_id: resource id based on the resource type for root or - * leaf resource, it matches the KMD interface port id. - * For branch resrouce, it is defined by the ISP HW - * layer - * @hw_res: hw layer resource array. For single VFE, only one VFE - * hw resrouce will be acquired. For dual VFE, two hw - * resources from different VFE HW device will be - * acquired - * @parent: point to the parent resource node. - * @children: point to the children resource nodes - * @child_num: numbe of the child resource node. - * @is_secure informs whether the resource is in secure mode or not - * - */ -struct cam_ife_hw_mgr_res { - struct list_head list; - enum cam_ife_hw_mgr_res_type res_type; - uint32_t res_id; - uint32_t is_dual_vfe; - struct cam_isp_resource_node *hw_res[CAM_ISP_HW_SPLIT_MAX]; - - /* graph */ - struct cam_ife_hw_mgr_res *parent; - struct cam_ife_hw_mgr_res *child[CAM_IFE_HW_OUT_RES_MAX]; - uint32_t num_children; - uint32_t is_secure; -}; - - -/** - * struct ctx_base_info - Base hardware information for the context - * - * @idx: Base resource index - * @split_id: Split info for the base resource - * - */ -struct ctx_base_info { - uint32_t idx; - enum cam_isp_hw_split_id split_id; -}; - /** * struct cam_ife_hw_mgr_debug - contain the debug information * @@ -151,20 +94,20 @@ struct cam_ife_hw_mgr_ctx { struct cam_ife_hw_mgr *hw_mgr; uint32_t ctx_in_use; - struct cam_ife_hw_mgr_res res_list_ife_in; + struct cam_isp_hw_mgr_res res_list_ife_in; 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[ + struct cam_isp_hw_mgr_res res_list_ife_out[ CAM_IFE_HW_OUT_RES_MAX]; struct list_head free_res_list; - struct cam_ife_hw_mgr_res res_pool[CAM_IFE_HW_RES_POOL_MAX]; + struct cam_isp_hw_mgr_res res_pool[CAM_IFE_HW_RES_POOL_MAX]; uint32_t irq_status0_mask[CAM_IFE_HW_NUM_MAX]; uint32_t irq_status1_mask[CAM_IFE_HW_NUM_MAX]; - struct ctx_base_info base[CAM_IFE_HW_NUM_MAX]; + struct cam_isp_ctx_base_info base[CAM_IFE_HW_NUM_MAX]; uint32_t num_base; uint32_t cdm_handle; struct cam_cdm_utils_ops *cdm_ops; @@ -225,6 +168,22 @@ struct cam_ife_hw_mgr { struct cam_ife_hw_mgr_debug debug_cfg; }; +/** + * struct cam_ife_hw_event_recovery_data - Payload for the recovery procedure + * + * @error_type: Error type that causes the recovery + * @affected_core: Array of the hardware cores that are affected + * @affected_ctx: Array of the hardware contexts that are affected + * @no_of_context: Actual number of the affected context + * + */ +struct cam_ife_hw_event_recovery_data { + uint32_t error_type; + uint32_t affected_core[CAM_ISP_HW_NUM_MAX]; + struct cam_ife_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX]; + uint32_t no_of_context; +}; + /** * cam_ife_hw_mgr_init() * diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h index 69e24bcc8625..fcb62ff8916c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h @@ -1,13 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_MGR_H_ #define _CAM_ISP_HW_MGR_H_ +#include #include "cam_isp_hw_mgr_intf.h" #include "cam_tasklet_util.h" +#include "cam_isp_hw.h" + #define CAM_ISP_HW_NUM_MAX 7 @@ -50,18 +53,43 @@ struct cam_isp_hw_mgr { }; /** - * struct cam_hw_event_recovery_data - Payload for the recovery procedure + * struct cam_isp_hw_mgr_res- HW resources for the ISP hw manager * - * @error_type: Error type that causes the recovery - * @affected_core: Array of the hardware cores that are affected - * @affected_ctx: Array of the hardware contexts that are affected - * @no_of_context: Actual number of the affected context + * @list: used by the resource list + * @res_type: ISP manager resource type + * @res_id: resource id based on the resource type for root or + * leaf resource, it matches the KMD interface port id. + * For branch resource, it is defined by the ISP HW + * layer + * @is_dual_isp is dual isp hw resource + * @hw_res: hw layer resource array. For single ISP, only one ISP + * hw resource will be acquired. For dual ISP, two hw + * resources from different ISP HW device will be + * acquired + * @is_secure informs whether the resource is in secure mode or not + * @num_children: number of the child resource node. * */ -struct cam_hw_event_recovery_data { - uint32_t error_type; - uint32_t affected_core[CAM_ISP_HW_NUM_MAX]; - struct cam_ife_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX]; - uint32_t no_of_context; +struct cam_isp_hw_mgr_res { + struct list_head list; + enum cam_isp_resource_type res_type; + uint32_t res_id; + uint32_t is_dual_isp; + struct cam_isp_resource_node *hw_res[CAM_ISP_HW_SPLIT_MAX]; + uint32_t is_secure; + uint32_t num_children; +}; + + +/** + * struct cam_isp_ctx_base_info - Base hardware information for the context + * + * @idx: Base resource index + * @split_id: Split info for the base resource + * + */ +struct cam_isp_ctx_base_info { + uint32_t idx; + enum cam_isp_hw_split_id split_id; }; #endif /* _CAM_ISP_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 86a14229915f..67211e60517e 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -18,7 +18,7 @@ int cam_isp_add_change_base( struct cam_kmd_buf_info *kmd_buf_info) { int rc = -EINVAL; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *res; struct cam_isp_hw_get_cmd_update get_base; struct cam_hw_update_entry *hw_entry; @@ -35,7 +35,7 @@ int cam_isp_add_change_base( } list_for_each_entry(hw_mgr_res, res_list_isp_src, list) { - if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) continue; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { @@ -91,12 +91,12 @@ static int cam_isp_update_dual_config( struct cam_cmd_buf_desc *cmd_desc, uint32_t split_id, uint32_t base_idx, - struct cam_ife_hw_mgr_res *res_list_isp_out, + struct cam_isp_hw_mgr_res *res_list_isp_out, uint32_t size_isp_out) { int rc = -EINVAL; struct cam_isp_dual_config *dual_config; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *res; struct cam_isp_hw_dual_isp_update_args dual_isp_update_args; uint32_t outport_id; @@ -180,7 +180,7 @@ end: } int cam_isp_add_cmd_buf_update( - struct cam_ife_hw_mgr_res *hw_mgr_res, + struct cam_isp_hw_mgr_res *hw_mgr_res, uint32_t cmd_type, uint32_t hw_cmd_type, uint32_t base_idx, @@ -195,7 +195,7 @@ int cam_isp_add_cmd_buf_update( uint32_t i; uint32_t total_used_bytes = 0; - if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) { CAM_ERR(CAM_ISP, "io res id:%d not valid", hw_mgr_res->res_type); return -EINVAL; @@ -243,9 +243,9 @@ int cam_isp_add_cmd_buf_update( int cam_isp_add_command_buffers( struct cam_hw_prepare_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, - struct ctx_base_info *base_info, + struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, - struct cam_ife_hw_mgr_res *res_list_isp_out, + struct cam_isp_hw_mgr_res *res_list_isp_out, uint32_t size_isp_out) { int rc = 0; @@ -460,7 +460,7 @@ int cam_isp_add_io_buffers( struct cam_hw_prepare_update_args *prepare, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info, - struct cam_ife_hw_mgr_res *res_list_isp_out, + struct cam_isp_hw_mgr_res *res_list_isp_out, struct list_head *res_list_ife_in_rd, uint32_t size_isp_out, bool fill_fence) @@ -469,7 +469,7 @@ int cam_isp_add_io_buffers( dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; struct cam_buf_io_cfg *io_cfg; struct cam_isp_resource_node *res; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_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; @@ -540,7 +540,7 @@ int cam_isp_add_io_buffers( } hw_mgr_res = &res_list_isp_out[res_id_out]; - if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) { CAM_ERR(CAM_ISP, "io res id:%d not valid", io_cfg[i].resource_type); return -EINVAL; @@ -550,10 +550,15 @@ int cam_isp_add_io_buffers( CAM_DBG(CAM_ISP, "configure input io with fill fence %d", fill_fence); + if (!res_list_ife_in_rd) { + CAM_ERR(CAM_ISP, + "No ISP in Read supported"); + return -EINVAL; + } 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); + struct cam_isp_hw_mgr_res, list); } else { CAM_ERR(CAM_ISP, "No IFE in Read resource"); @@ -606,10 +611,11 @@ int cam_isp_add_io_buffers( break; hdl = io_cfg[i].mem_handle[plane_id]; - if (res->process_cmd(res, - CAM_ISP_HW_CMD_GET_SECURE_MODE, - &mode, - sizeof(bool))) + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_SECURE_MODE, + &mode, sizeof(bool)); + if (rc) return -EINVAL; is_buf_secure = cam_mem_is_secure_buf(hdl); @@ -716,10 +722,11 @@ int cam_isp_add_io_buffers( break; hdl = io_cfg[i].mem_handle[plane_id]; - if (res->process_cmd(res, - CAM_ISP_HW_CMD_GET_SECURE_MODE, - &mode, - sizeof(bool))) + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_SECURE_MODE, + &mode, sizeof(bool)); + if (rc) return -EINVAL; is_buf_secure = cam_mem_is_secure_buf(hdl); @@ -852,7 +859,7 @@ int cam_isp_add_reg_update( { int rc = -EINVAL; struct cam_isp_resource_node *res; - struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_update_entry *hw_entry; struct cam_isp_hw_get_cmd_update get_regup; uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; @@ -869,7 +876,7 @@ int cam_isp_add_reg_update( reg_update_size = 0; list_for_each_entry(hw_mgr_res, res_list_isp_src, list) { - if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) continue; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index c9bd4c4430e9..8948b2a416c5 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_PARSER_H_ @@ -9,7 +9,7 @@ #include #include #include "cam_isp_hw_mgr_intf.h" -#include "cam_ife_hw_mgr.h" +#include "cam_isp_hw_mgr.h" #include "cam_hw_intf.h" #include "cam_packet_util.h" @@ -25,12 +25,12 @@ enum cam_isp_cdm_bl_type { * struct cam_isp_generic_blob_info * * @prepare: Payload for prepare command - * @ctx_base_info: Base hardware information for the context + * @base_info: Base hardware information for the context * @kmd_buf_info: Kmd buffer to store the custom cmd data */ struct cam_isp_generic_blob_info { struct cam_hw_prepare_update_args *prepare; - struct ctx_base_info *base_info; + struct cam_isp_ctx_base_info *base_info; struct cam_kmd_buf_info *kmd_buf_info; }; @@ -77,7 +77,7 @@ int cam_isp_add_change_base( * otherwise returns bytes used */ int cam_isp_add_cmd_buf_update( - struct cam_ife_hw_mgr_res *hw_mgr_res, + struct cam_isp_hw_mgr_res *hw_mgr_res, uint32_t cmd_type, uint32_t hw_cmd_type, uint32_t base_idx, @@ -105,9 +105,9 @@ int cam_isp_add_cmd_buf_update( int cam_isp_add_command_buffers( struct cam_hw_prepare_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, - struct ctx_base_info *base_info, + struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, - struct cam_ife_hw_mgr_res *res_list_isp_out, + struct cam_isp_hw_mgr_res *res_list_isp_out, uint32_t size_isp_out); /* @@ -137,7 +137,7 @@ int cam_isp_add_io_buffers( struct cam_hw_prepare_update_args *prepare, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info, - struct cam_ife_hw_mgr_res *res_list_isp_out, + struct cam_isp_hw_mgr_res *res_list_isp_out, struct list_head *res_list_ife_in_rd, uint32_t size_isp_out, bool fill_fence); diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 6d5d0fd61c88..009975864a45 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_MGR_INTF_H_ @@ -115,7 +115,7 @@ struct cam_isp_bw_config_internal { /** * struct cam_isp_prepare_hw_update_data - hw prepare data * - * @ife_mgr_ctx: IFE HW manager Context for current request + * @isp_mgr_ctx: ISP HW manager Context for current request * @packet_opcode_type: Packet header opcode in the packet header * this opcode defines, packet is init packet or * update packet @@ -129,7 +129,7 @@ struct cam_isp_bw_config_internal { * */ struct cam_isp_prepare_hw_update_data { - struct cam_ife_hw_mgr_ctx *ife_mgr_ctx; + void *isp_mgr_ctx; uint32_t packet_opcode_type; uint32_t bw_config_version; struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 7ac79feb2a9f..b35e495b2410 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_H_ @@ -224,13 +224,6 @@ struct cam_isp_hw_get_cmd_update { 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_vfe_generic_ubwc_config *ubwc_config; - struct cam_isp_vfe_wm_config *wm_config; }; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index ae5713f455dd..34b081a5340e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -606,6 +606,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_UBWC_UPDATE: case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: + case CAM_ISP_HW_CMD_GET_SECURE_MODE: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 9094f1409a66..c5765c8a76a4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -3004,7 +3004,7 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args, } reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; - hfr_cfg = update_hfr->hfr_update; + hfr_cfg = (struct cam_isp_port_hfr_config *)update_hfr->data; for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) { if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { @@ -3116,7 +3116,7 @@ static int cam_vfe_bus_update_ubwc_config(void *cmd_args) goto end; } - ubwc_plane_cfg = update_ubwc->ubwc_update; + ubwc_plane_cfg = (struct cam_ubwc_plane_cfg_v1 *)update_ubwc->data; for (i = 0; i < vfe_out_data->num_wm; i++) { @@ -3226,7 +3226,8 @@ static int cam_vfe_bus_update_ubwc_config_v2(void *cmd_args) goto end; } - ubwc_generic_cfg = update_ubwc->ubwc_config; + ubwc_generic_cfg = (struct cam_vfe_generic_ubwc_config *) + update_ubwc->data; for (i = 0; i < vfe_out_data->num_wm; i++) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 2351afcbf1dc..694dd224a660 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ @@ -3202,7 +3202,7 @@ static int cam_vfe_bus_ver3_update_hfr(void *priv, void *cmd_args, } reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; - hfr_cfg = update_hfr->hfr_update; + hfr_cfg = (struct cam_isp_port_hfr_config *)update_hfr->data; for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) { if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { @@ -3317,7 +3317,8 @@ static int cam_vfe_bus_ver3_update_ubwc_config_v2(void *cmd_args) goto end; } - ubwc_generic_cfg = update_ubwc->ubwc_config; + ubwc_generic_cfg = (struct cam_vfe_generic_ubwc_config *) + update_ubwc->data; for (i = 0; i < vfe_out_data->num_wm; i++) { @@ -3485,7 +3486,8 @@ static int cam_vfe_bus_ver3_update_wm_config( wm_config_update = cmd_args; vfe_out_data = wm_config_update->res->res_priv; - wm_config = wm_config_update->wm_config; + wm_config = (struct cam_isp_vfe_wm_config *) + wm_config_update->data; if (!vfe_out_data || !vfe_out_data->cdm_util_ops || !wm_config) { CAM_ERR(CAM_ISP, "Invalid data"); From 3bbd97274f19d710f925864d57878e42dbc557ad Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 23 Dec 2019 15:34:34 +0530 Subject: [PATCH 207/790] msm: camera: cpas: Add support for Bengal camnoc Bengal has different version of camnoc which requires separate register space and camnoc interface changes. This change adds the same. CRs-Fixed: 2594541 Change-Id: I2a8e6cb8894444cb669ab1c4da5fa706dc6543ad Signed-off-by: Rishabh Jain Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 18 +- drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 6 +- drivers/cam_cpas/cpas_top/cpastop_v540_100.h | 241 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 3 +- 4 files changed, 261 insertions(+), 7 deletions(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v540_100.h diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 9068dd3ebe08..9710050bf09c 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -22,6 +22,7 @@ #include "cpastop_v175_130.h" #include "cpastop_v480_100.h" #include "cpastop_v580_100.h" +#include "cpastop_v540_100.h" struct cam_camnoc_info *camnoc_info; @@ -126,6 +127,10 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, (hw_caps->camera_version.minor == 8) && (hw_caps->camera_version.incr == 0)) { soc_info->hw_version = CAM_CPAS_TITAN_580_V100; + } else if ((hw_caps->camera_version.major == 5) && + (hw_caps->camera_version.minor == 4) && + (hw_caps->camera_version.incr == 0)) { + soc_info->hw_version = CAM_CPAS_TITAN_540_V100; } CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); @@ -521,8 +526,7 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) int i; struct cam_cpas_hw_errata_wa_list *errata_wa_list = camnoc_info->errata_wa_list; - struct cam_cpas_hw_errata_wa *errata_wa = - &errata_wa_list->tcsr_camera_hf_sf_ares_glitch; + struct cam_cpas_hw_errata_wa *errata_wa; cam_cpastop_reset_irq(cpas_hw); for (i = 0; i < camnoc_info->specific_size; i++) { @@ -544,8 +548,10 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) } } - if (errata_wa->enable) { - cam_cpastop_scm_write(errata_wa); + if (errata_wa_list) { + errata_wa = &errata_wa_list->tcsr_camera_hf_sf_ares_glitch; + if (errata_wa->enable) + cam_cpastop_scm_write(errata_wa); } return 0; @@ -628,6 +634,8 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, break; case CAM_CPAS_TITAN_580_V100: camnoc_info = &cam580_cpas100_camnoc_info; + case CAM_CPAS_TITAN_540_V100: + camnoc_info = &cam540_cpas100_camnoc_info; break; default: CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 7dbb5dd8fd38..84c2ea1d724a 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPASTOP_HW_H_ @@ -115,6 +115,8 @@ enum cam_camnoc_hw_irq_type { * @CAM_CAMNOC_JPEG: Indicates JPEG HW connection to camnoc * @CAM_CAMNOC_FD: Indicates FD HW connection to camnoc * @CAM_CAMNOC_ICP: Indicates ICP HW connection to camnoc + * @CAM_CAMNOC_TFE: Indicates TFE HW connection to camnoc + * @CAM_CAMNOC_OPE: Indicates OPE HW connection to camnoc */ enum cam_camnoc_port_type { CAM_CAMNOC_CDM, @@ -139,6 +141,8 @@ enum cam_camnoc_port_type { CAM_CAMNOC_JPEG, CAM_CAMNOC_FD, CAM_CAMNOC_ICP, + CAM_CAMNOC_TFE, + CAM_CAMNOC_OPE, }; /** diff --git a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h new file mode 100644 index 000000000000..2d7e06d5b024 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h @@ -0,0 +1,241 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V540_100_H_ +#define _CPASTOP_V540_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v540_100_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v540_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 = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +// TODO: Need to update cam_cpas_v540_100_camnoc_specific values based on QoS +static struct cam_camnoc_specific + cam_cpas_v540_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 = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x2, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0X10030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xFFAA5500, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0xFF00, + }, + .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_OPE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_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, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam540_cpas100_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam540_cpas100_camnoc_info = { + .specific = &cam_cpas_v540_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v540_100_camnoc_specific), + .irq_sbm = &cam_cpas_v540_100_irq_sbm, + .irq_err = &cam_cpas_v540_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v540_100_irq_err), + .err_logger = &cam540_cpas100_err_logger_offsets, + .errata_wa_list = NULL, +}; + +#endif /* _CPASTOP_V540_100_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index ebfdc70f9d59..6399f76bac50 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_API_H_ @@ -47,6 +47,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_175_V130 = 0x175130, CAM_CPAS_TITAN_480_V100 = 0x480100, CAM_CPAS_TITAN_580_V100 = 0x580100, + CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_MAX }; From 4aad75a2f964fddc2c22c445d9bfc0d9493f78b6 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Thu, 3 Oct 2019 16:13:47 +0530 Subject: [PATCH 208/790] msm: camera: ope: Support 32 bit arch Update datatypes to work with 32 bit kernel. CRs-Fixed: 2594541 Change-Id: I72d628152134770d7e09c3684443e25c47d9d1dc Signed-off-by: Trishansh Bhardwaj --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 6 +++--- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 13cc29e46b5d..d2b4f7d081e5 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1363,7 +1363,7 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, { int rc = 0; int i, j, k, l; - uint64_t iova_addr; + dma_addr_t iova_addr; size_t len; struct ope_frame_process *in_frame_process; struct ope_frame_set *in_frame_set; @@ -1522,8 +1522,8 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr, { int rc = 0; int i, j; - uint64_t iova_addr; - uint64_t iova_cdm_addr; + dma_addr_t iova_addr; + dma_addr_t iova_cdm_addr; uintptr_t cpu_addr; size_t len; struct ope_frame_process *frame_process; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index 25f03f640111..cd5be9ec833a 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -462,7 +462,7 @@ static uint32_t *ope_create_frame_cmd_prefetch_dis( struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; struct ope_frame_process *frm_proc; - uint64_t iova_addr; + dma_addr_t iova_addr; uintptr_t cpu_addr; size_t buf_len; uint32_t print_idx; @@ -574,7 +574,7 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; struct ope_frame_process *frm_proc; - uint64_t iova_addr; + dma_addr_t iova_addr; uintptr_t cpu_addr; size_t buf_len; uint32_t print_idx; @@ -729,7 +729,7 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; struct ope_frame_process *frm_proc; - uint64_t iova_addr; + dma_addr_t iova_addr; uintptr_t cpu_addr; size_t buf_len; uint32_t print_idx; @@ -833,7 +833,7 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, int rc = 0, i, j, k; uint32_t temp[3]; struct cdm_dmi_cmd *dmi_cmd; - uint64_t iova_addr; + dma_addr_t iova_addr; uintptr_t cpu_addr; size_t buf_len; uint32_t print_idx; From d907c2c7cb23d09a3ffe1ed920d89730fbdd27b1 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Thu, 19 Dec 2019 14:56:09 +0530 Subject: [PATCH 209/790] msm: camera: cdm: Add support for different CDM hardware Different CDM hardware have different capability and registers. With old register space, handling new features and operations would have been a complex task. This change takes care of old version of CDM and also changes the regspace to provide every register's access to CDM. This change further adds support for "arbitration" in case of multi-context CDMs. Exports reset functionality to clients, detection of CDM hang. Flushing the CDM requests and dumping the FIFO content for all contexts. It also adds submitting "debug_gen_irq" as BL_done IRQ is only an indication for availability of FIFO's. The AHB operations are completed can only be known if the added "debug_gen_irqs" gets executed and are received by the CDM. CRs-Fixed: 2594541 Change-Id: I9846b1c5320ba652c5d3b7d83d616d2dabc843e1 Signed-off-by: Abhilash Kumar Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm.h | 490 ++++-- drivers/cam_cdm/cam_cdm_core_common.c | 202 ++- drivers/cam_cdm/cam_cdm_core_common.h | 21 +- drivers/cam_cdm/cam_cdm_hw_core.c | 1386 +++++++++++++---- drivers/cam_cdm/cam_cdm_hw_reg_1_0.h | 149 ++ drivers/cam_cdm/cam_cdm_hw_reg_1_1.h | 160 ++ drivers/cam_cdm/cam_cdm_hw_reg_1_2.h | 180 +++ drivers/cam_cdm/cam_cdm_hw_reg_2_0.h | 251 +++ drivers/cam_cdm/cam_cdm_intf.c | 124 +- drivers/cam_cdm/cam_cdm_intf_api.h | 72 +- drivers/cam_cdm/cam_cdm_soc.c | 165 +- drivers/cam_cdm/cam_cdm_soc.h | 14 +- drivers/cam_cdm/cam_cdm_util.c | 172 +- drivers/cam_cdm/cam_cdm_util.h | 80 +- drivers/cam_cdm/cam_hw_cdm170_reg.h | 135 -- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c | 5 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 9 +- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 7 +- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c | 4 +- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c | 3 +- drivers/cam_smmu/cam_smmu_api.c | 171 +- drivers/cam_utils/cam_soc_util.c | 6 +- drivers/cam_utils/cam_soc_util.h | 4 +- 23 files changed, 3057 insertions(+), 753 deletions(-) create mode 100644 drivers/cam_cdm/cam_cdm_hw_reg_1_0.h create mode 100644 drivers/cam_cdm/cam_cdm_hw_reg_1_1.h create mode 100644 drivers/cam_cdm/cam_cdm_hw_reg_1_2.h create mode 100644 drivers/cam_cdm/cam_cdm_hw_reg_2_0.h delete mode 100644 drivers/cam_cdm/cam_hw_cdm170_reg.h diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index ab12ab52f293..525d54d68df3 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_H_ @@ -26,24 +26,341 @@ #define CAM_CDM_INFLIGHT_WORKS 5 #define CAM_CDM_HW_RESET_TIMEOUT 300 +/* + * Macros to get prepare and get information + * from client CDM handles. + */ + #define CAM_CDM_HW_ID_MASK 0xF -#define CAM_CDM_HW_ID_SHIFT 0x5 -#define CAM_CDM_CLIENTS_ID_MASK 0x1F +#define CAM_CDM_HW_ID_SHIFT 0x10 + +#define CAM_CDM_CLIENTS_ID_MASK 0xFF + +#define CAM_CDM_BL_FIFO_ID_MASK 0xF +#define CAM_CDM_BL_FIFO_ID_SHIFT 0x8 #define CAM_CDM_GET_HW_IDX(x) (((x) >> CAM_CDM_HW_ID_SHIFT) & \ CAM_CDM_HW_ID_MASK) -#define CAM_CDM_CREATE_CLIENT_HANDLE(hw_idx, client_idx) \ + +#define CAM_CDM_GET_BLFIFO_IDX(x) (((x) >> CAM_CDM_BL_FIFO_ID_SHIFT) & \ + CAM_CDM_BL_FIFO_ID_MASK) + +#define CAM_CDM_CREATE_CLIENT_HANDLE(hw_idx, priority, client_idx) \ ((((hw_idx) & CAM_CDM_HW_ID_MASK) << CAM_CDM_HW_ID_SHIFT) | \ + (((priority) & CAM_CDM_BL_FIFO_ID_MASK) << CAM_CDM_BL_FIFO_ID_SHIFT)| \ ((client_idx) & CAM_CDM_CLIENTS_ID_MASK)) #define CAM_CDM_GET_CLIENT_IDX(x) ((x) & CAM_CDM_CLIENTS_ID_MASK) #define CAM_PER_CDM_MAX_REGISTERED_CLIENTS (CAM_CDM_CLIENTS_ID_MASK + 1) #define CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM (CAM_CDM_HW_ID_MASK + 1) -/* enum cam_cdm_reg_attr - read, write, read and write permissions.*/ -enum cam_cdm_reg_attr { - CAM_REG_ATTR_READ, - CAM_REG_ATTR_WRITE, - CAM_REG_ATTR_READ_WRITE, +/* Number of FIFO supported on CDM */ +#define CAM_CDM_NUM_BL_FIFO 0x4 + +/* Max number of register set for different CDM */ +#define CAM_CDM_BL_FIFO_REG_NUM 0x4 +#define CAM_CDM_BL_FIFO_IRQ_REG_NUM 0x4 +#define CAM_CDM_BL_FIFO_PENDING_REQ_REG_NUM 0x2 +#define CAM_CDM_SCRATCH_REG_NUM 0xc +#define CAM_CDM_COMP_WAIT_STATUS_REG_NUM 0x2 +#define CAM_CDM_PERF_MON_REG_NUM 0x2 + +/* BL_FIFO configurations*/ +#define CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT 0x40 +#define CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT 0x10 + +#define CAM_CDM_BL_FIFO_REQ_SIZE_MAX 0x00 +#define CAM_CDM_BL_FIFO_REQ_SIZE_MAX_DIV2 0x01 +#define CAM_CDM_BL_FIFO_REQ_SIZE_MAX_DIV4 0x10 +#define CAM_CDM_BL_FIFO_REQ_SIZE_MAX_DIV8 0x11 + +/* CDM core status bitmap */ +#define CAM_CDM_HW_INIT_STATUS 0x0 +#define CAM_CDM_FIFO_0_BLDONE_STATUS 0x0 +#define CAM_CDM_FIFO_1_BLDONE_STATUS 0x1 +#define CAM_CDM_FIFO_2_BLDONE_STATUS 0x2 +#define CAM_CDM_FIFO_3_BLDONE_STATUS 0x3 +#define CAM_CDM_RESET_HW_STATUS 0x4 +#define CAM_CDM_ERROR_HW_STATUS 0x5 +#define CAM_CDM_FLUSH_HW_STATUS 0x6 + +/* Curent BL command masks and shifts */ +#define CAM_CDM_CURRENT_BL_LEN 0xFFFFF +#define CAM_CDM_CURRENT_BL_ARB 0x100000 +#define CAM_CDM_CURRENT_BL_FIFO 0xC00000 +#define CAM_CDM_CURRENT_BL_TAG 0xFF000000 + +#define CAM_CDM_CURRENT_BL_ARB_SHIFT 0x14 +#define CAM_CDM_CURRENT_BL_FIFO_SHIFT 0x16 +#define CAM_CDM_CURRENT_BL_TAG_SHIFT 0x18 + +/* IRQ bit-masks */ +#define CAM_CDM_IRQ_STATUS_RST_DONE_MASK 0x1 +#define CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK 0x2 +#define CAM_CDM_IRQ_STATUS_BL_DONE_MASK 0x4 +#define CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK 0x10000 +#define CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK 0x20000 +#define CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK 0x40000 + +#define CAM_CDM_IRQ_STATUS_ERRORS \ + (CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK | \ + CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK | \ + CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) + +/* Structure to store hw version info */ +struct cam_version_reg { + uint32_t hw_version; +}; + +/** + * struct cam_cdm_irq_regs - CDM IRQ registers + * + * @irq_mask: register offset for irq_mask + * @irq_clear: register offset for irq_clear + * @irq_clear_cmd: register offset to initiate irq clear + * @irq_set: register offset to set irq + * @irq_set_cmd: register offset to issue set_irq from irq_set + * @irq_status: register offset to look which irq is received + */ +struct cam_cdm_irq_regs { + uint32_t irq_mask; + uint32_t irq_clear; + uint32_t irq_clear_cmd; + uint32_t irq_set; + uint32_t irq_set_cmd; + uint32_t irq_status; +}; + +/** + * struct cam_cdm_bl_fifo_regs - BL_FIFO registers + * + * @bl_fifo_base: register offset to write bl_cmd base address + * @bl_fifo_len: register offset to write bl_cmd length + * @bl_fifo_store: register offset to commit the BL cmd + * @bl_fifo_cfg: register offset to config BL_FIFO depth, etc. + */ +struct cam_cdm_bl_fifo_regs { + uint32_t bl_fifo_base; + uint32_t bl_fifo_len; + uint32_t bl_fifo_store; + uint32_t bl_fifo_cfg; +}; + +/** + * struct cam_cdm_bl_pending_req_reg_params - BL_FIFO pending registers + * + * @rb_offset: register offset pending bl request in BL_FIFO + * @rb_mask: mask to get number of pending BLs in BL_FIFO + * @rb_num_fifo: number of BL_FIFO's information in the register + * @rb_next_fifo_shift: shift to get next fifo's pending BLs. + */ +struct cam_cdm_bl_pending_req_reg_params { + uint32_t rb_offset; + uint32_t rb_mask; + uint32_t rb_num_fifo; + uint32_t rb_next_fifo_shift; +}; + +/** + * struct cam_cdm_scratch_reg - scratch register + * + * @scratch_reg: offset of scratch register + */ +struct cam_cdm_scratch_reg { + uint32_t scratch_reg; +}; + +/* struct cam_cdm_perf_mon_regs - perf_mon registers */ +struct cam_cdm_perf_mon_regs { + uint32_t perf_mon_ctrl; + uint32_t perf_mon_0; + uint32_t perf_mon_1; + uint32_t perf_mon_2; +}; + +/** + * struct cam_cdm_perf_mon_regs - perf mon counter's registers + * + * @count_cfg_0: register offset to configure perf measures + * @always_count_val: register offset for always count value + * @busy_count_val: register offset to get busy count + * @stall_axi_count_val: register offset to get axi stall counts + * @count_status: register offset to know if count status finished + * for stall, busy and always. + */ +struct cam_cdm_perf_regs { + uint32_t count_cfg_0; + uint32_t always_count_val; + uint32_t busy_count_val; + uint32_t stall_axi_count_val; + uint32_t count_status; +}; + +/** + * struct cam_cdm_icl_data_regs - CDM icl data registers + * + * @icl_last_data_0: register offset to log last known good command + * @icl_last_data_1: register offset to log last known good command 1 + * @icl_last_data_2: register offset to log last known good command 2 + * @icl_inv_data: register offset to log CDM cmd that triggered + * invalid command. + */ +struct cam_cdm_icl_data_regs { + uint32_t icl_last_data_0; + uint32_t icl_last_data_1; + uint32_t icl_last_data_2; + uint32_t icl_inv_data; +}; + +/** + * struct cam_cdm_icl_misc_regs - CDM icl misc registers + * + * @icl_inv_bl_addr: register offset to give address of bl_cmd that + * gave invalid command + * @icl_status: register offset for context that gave good BL + * command and invalid command. + */ +struct cam_cdm_icl_misc_regs { + uint32_t icl_inv_bl_addr; + uint32_t icl_status; +}; + +/** + * struct cam_cdm_icl_regs - CDM icl registers + * + * @data_regs: structure with registers of all cdm good and invalid + * BL command information. + * @misc_regs: structure with registers for invalid command address + * and context + */ +struct cam_cdm_icl_regs { + struct cam_cdm_icl_data_regs *data_regs; + struct cam_cdm_icl_misc_regs *misc_regs; +}; + +/** + * struct cam_cdm_comp_wait_status - BL_FIFO comp_event status register + * + * @comp_wait_status: register offset to give information on whether the + * CDM is waiting for an event from another module + */ +struct cam_cdm_comp_wait_status { + uint32_t comp_wait_status; +}; + +/** + * struct cam_cdm_common_reg_data - structure for register data + * + * @num_bl_fifo: number of FIFO are there in CDM + * @num_bl_fifo_irq: number of FIFO irqs in CDM + * @num_bl_pending_req_reg: number of pending_requests register in CDM + * @num_scratch_reg: number of scratch registers in CDM + */ +struct cam_cdm_common_reg_data { + uint32_t num_bl_fifo; + uint32_t num_bl_fifo_irq; + uint32_t num_bl_pending_req_reg; + uint32_t num_scratch_reg; +}; + +/** + * struct cam_cdm_common_regs - common structure to get common registers + * of CDM + * + * @cdm_hw_version: offset to read cdm_hw_version + * @cam_version: offset to read the camera Titan architecture version + * @rst_cmd: offset to reset the CDM + * @cgc_cfg: offset to configure CDM CGC logic + * @core_cfg: offset to configure CDM core with ARB_SEL, implicit + * wait, etc. + * @core_en: offset to pause/enable CDM + * @fe_cfg: offset to configure CDM fetch engine + * @bl_fifo_rb: offset to set BL_FIFO read back + * @bl_fifo_base_rb: offset to read back base address on offset set by + * bl_fifo_rb + * @bl_fifo_len_rb: offset to read back base len and tag on offset set by + * bl_fifo_rb + * @usr_data: offset to read user data from GEN_IRQ commands + * @wait_status: offset to read status for last WAIT command + * @last_ahb_addr: offset to read back last AHB address generated by CDM + * @last_ahb_data: offset to read back last AHB data generated by CDM + * @core_debug: offset to configure CDM debug bus and debug features + * @last_ahb_err_addr: offset to read back last AHB Error address generated + * by CDM + * @last_ahb_err_data: offset to read back last AHB Error data generated + * by CDM + * @current_bl_base: offset to read back current command buffer BASE address + * value out of BL_FIFO + * @current_bl_len: offset to read back current command buffer len, TAG, + * context ID ARB value out of BL_FIFO + * @current_used_ahb_base: offset to read back current base address used by + * CDM to access camera register + * @debug_status: offset to read back current CDM status + * @bus_misr_cfg0: offset to enable bus MISR and configure sampling mode + * @bus_misr_cfg1: offset to select from one of the six MISR's for reading + * signature value + * @bus_misr_rd_val: offset to read MISR signature + * @pending_req: registers to read pending request in FIFO + * @comp_wait: registers to read comp_event CDM is waiting for + * @perf_mon: registers to read perf_mon information + * @scratch: registers to read scratch register value + * @perf_reg: registers to read performance counters value + * @icl_reg: registers to read information related to good + * and invalid commands in FIFO + * @spare: spare register + * + */ +struct cam_cdm_common_regs { + uint32_t cdm_hw_version; + const struct cam_version_reg *cam_version; + uint32_t rst_cmd; + uint32_t cgc_cfg; + uint32_t core_cfg; + uint32_t core_en; + uint32_t fe_cfg; + uint32_t bl_fifo_rb; + uint32_t bl_fifo_base_rb; + uint32_t bl_fifo_len_rb; + uint32_t usr_data; + uint32_t wait_status; + uint32_t last_ahb_addr; + uint32_t last_ahb_data; + uint32_t core_debug; + uint32_t last_ahb_err_addr; + uint32_t last_ahb_err_data; + uint32_t current_bl_base; + uint32_t current_bl_len; + uint32_t current_used_ahb_base; + uint32_t debug_status; + uint32_t bus_misr_cfg0; + uint32_t bus_misr_cfg1; + uint32_t bus_misr_rd_val; + const struct cam_cdm_bl_pending_req_reg_params + *pending_req[CAM_CDM_BL_FIFO_PENDING_REQ_REG_NUM]; + const struct cam_cdm_comp_wait_status + *comp_wait[CAM_CDM_COMP_WAIT_STATUS_REG_NUM]; + const struct cam_cdm_perf_mon_regs + *perf_mon[CAM_CDM_PERF_MON_REG_NUM]; + const struct cam_cdm_scratch_reg + *scratch[CAM_CDM_SCRATCH_REG_NUM]; + const struct cam_cdm_perf_regs *perf_reg; + const struct cam_cdm_icl_regs *icl_reg; + uint32_t spare; +}; + +/** + * struct cam_cdm_hw_reg_offset - BL_FIFO comp_event status register + * + * @cmn_reg: pointer to structure to get common registers of a CDM + * @bl_fifo_reg: pointer to structure to get BL_FIFO registers of a CDM + * @irq_reg: pointer to structure to get IRQ registers of a CDM + * @reg_data: pointer to structure to reg_data related to CDM + * registers + */ +struct cam_cdm_hw_reg_offset { + const struct cam_cdm_common_regs *cmn_reg; + const struct cam_cdm_bl_fifo_regs *bl_fifo_reg[CAM_CDM_BL_FIFO_REG_NUM]; + const struct cam_cdm_irq_regs *irq_reg[CAM_CDM_BL_FIFO_IRQ_REG_NUM]; + const struct cam_cdm_common_reg_data *reg_data; }; /* enum cam_cdm_hw_process_intf_cmd - interface commands.*/ @@ -52,83 +369,11 @@ enum cam_cdm_hw_process_intf_cmd { CAM_CDM_HW_INTF_CMD_RELEASE, CAM_CDM_HW_INTF_CMD_SUBMIT_BL, CAM_CDM_HW_INTF_CMD_RESET_HW, + CAM_CDM_HW_INTF_CMD_FLUSH_HW, + CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, CAM_CDM_HW_INTF_CMD_INVALID, }; -/* enum cam_cdm_regs - CDM driver offset enums.*/ -enum cam_cdm_regs { - /*cfg_offsets 0*/ - CDM_CFG_HW_VERSION, - CDM_CFG_TITAN_VERSION, - CDM_CFG_RST_CMD, - CDM_CFG_CGC_CFG, - CDM_CFG_CORE_CFG, - CDM_CFG_CORE_EN, - CDM_CFG_FE_CFG, - /*irq_offsets 7*/ - CDM_IRQ_MASK, - CDM_IRQ_CLEAR, - CDM_IRQ_CLEAR_CMD, - CDM_IRQ_SET, - CDM_IRQ_SET_CMD, - CDM_IRQ_STATUS, - CDM_IRQ_USR_DATA, - /*BL FIFO Registers 14*/ - CDM_BL_FIFO_BASE_REG, - CDM_BL_FIFO_LEN_REG, - CDM_BL_FIFO_STORE_REG, - CDM_BL_FIFO_CFG, - CDM_BL_FIFO_RB, - CDM_BL_FIFO_BASE_RB, - CDM_BL_FIFO_LEN_RB, - CDM_BL_FIFO_PENDING_REQ_RB, - /*CDM System Debug Registers 22*/ - CDM_DBG_WAIT_STATUS, - CDM_DBG_SCRATCH_0_REG, - CDM_DBG_SCRATCH_1_REG, - CDM_DBG_SCRATCH_2_REG, - CDM_DBG_SCRATCH_3_REG, - CDM_DBG_SCRATCH_4_REG, - CDM_DBG_SCRATCH_5_REG, - CDM_DBG_SCRATCH_6_REG, - CDM_DBG_SCRATCH_7_REG, - CDM_DBG_LAST_AHB_ADDR, - CDM_DBG_LAST_AHB_DATA, - CDM_DBG_CORE_DBUG, - CDM_DBG_LAST_AHB_ERR_ADDR, - CDM_DBG_LAST_AHB_ERR_DATA, - CDM_DBG_CURRENT_BL_BASE, - CDM_DBG_CURRENT_BL_LEN, - CDM_DBG_CURRENT_USED_AHB_BASE, - CDM_DBG_DEBUG_STATUS, - /*FE Bus Miser Registers 40*/ - CDM_BUS_MISR_CFG_0, - CDM_BUS_MISR_CFG_1, - CDM_BUS_MISR_RD_VAL, - /*Performance Counter registers 43*/ - CDM_PERF_MON_CTRL, - CDM_PERF_MON_0, - CDM_PERF_MON_1, - CDM_PERF_MON_2, - /*Spare registers 47*/ - CDM_SPARE, -}; - -/* struct cam_cdm_reg_offset - struct for offset with attribute.*/ -struct cam_cdm_reg_offset { - uint32_t offset; - enum cam_cdm_reg_attr attribute; -}; - -/* struct cam_cdm_reg_offset_table - struct for whole offset table.*/ -struct cam_cdm_reg_offset_table { - uint32_t first_offset; - uint32_t last_offset; - uint32_t reg_count; - const struct cam_cdm_reg_offset *offsets; - uint32_t offset_max_size; -}; - /* enum cam_cdm_flags - Bit fields for CDM flags used */ enum cam_cdm_flags { CAM_CDM_FLAG_SHARED_CDM, @@ -147,6 +392,29 @@ enum cam_cdm_mem_base_index { CAM_HW_CDM_MAX_INDEX = CAM_SOC_MAX_BLOCK, }; +/* enum cam_cdm_bl_cb_type - Enum for possible CAM CDM cb request types */ +enum cam_cdm_bl_cb_type { + CAM_HW_CDM_BL_CB_CLIENT = 1, + CAM_HW_CDM_BL_CB_INTERNAL, +}; + +/* enum cam_cdm_arbitration - Enum type of arbitration */ +enum cam_cdm_arbitration { + CAM_CDM_ARBITRATION_NONE, + CAM_CDM_ARBITRATION_ROUND_ROBIN, + CAM_CDM_ARBITRATION_PRIORITY_BASED, + CAM_CDM_ARBITRATION_MAX, +}; + +enum cam_cdm_hw_version { + CAM_CDM_VERSION = 0, + CAM_CDM_VERSION_1_0 = 0x10000000, + CAM_CDM_VERSION_1_1 = 0x10010000, + CAM_CDM_VERSION_1_2 = 0x10020000, + CAM_CDM_VERSION_2_0 = 0x20000000, + CAM_CDM_VERSION_MAX, +}; + /* struct cam_cdm_client - struct for cdm clients data.*/ struct cam_cdm_client { struct cam_cdm_acquire_data data; @@ -162,15 +430,10 @@ struct cam_cdm_work_payload { struct cam_hw_info *hw; uint32_t irq_status; uint32_t irq_data; + int fifo_idx; struct work_struct work; }; -/* enum cam_cdm_bl_cb_type - Enum for possible CAM CDM cb request types */ -enum cam_cdm_bl_cb_type { - CAM_HW_CDM_BL_CB_CLIENT = 1, - CAM_HW_CDM_BL_CB_INTERNAL, -}; - /* struct cam_cdm_bl_cb_request_entry - callback entry for work to process.*/ struct cam_cdm_bl_cb_request_entry { uint8_t bl_tag; @@ -195,28 +458,63 @@ struct cam_cdm_hw_mem { size_t size; }; -/* struct cam_cdm - CDM hw device struct */ +/* struct cam_cdm_bl_fifo - CDM hw memory struct */ +struct cam_cdm_bl_fifo { + struct completion bl_complete; + struct workqueue_struct *work_queue; + struct list_head bl_request_list; + struct mutex fifo_lock; + uint8_t bl_tag; + uint32_t bl_depth; +}; + +/** + * struct cam_cdm - CDM hw device struct + * + * @index: index of CDM hardware + * @name: cdm_name + * @id: enum for possible CDM hardwares + * @flags: enum to tell if CDM is private of shared + * @reset_complete: completion event to make CDM wait for reset + * @work_queue: workqueue to schedule work for virtual CDM + * @bl_request_list: bl_request list for submitted commands in + * virtual CDM + * @version: CDM version with major, minor, incr and reserved + * @hw_version: CDM version as read from the cdm_version register + * @hw_family_version: version of hw family the CDM belongs to + * @iommu_hdl: CDM iommu handle + * @offsets: pointer to structure of CDM registers + * @ops: CDM ops for generating cdm commands + * @clients: CDM clients array currently active on CDM + * @bl_fifo: structure with per fifo related attributes + * @cdm_status: bitfield with bits assigned for different cdm status + * @bl_tag: slot value at which the next bl cmd will be written + * in case of virtual CDM + * @gen_irq: memory region in which gen_irq command will be written + * @cpas_handle: handle for cpas driver + * @arbitration: type of arbitration to be used for the CDM + */ struct cam_cdm { uint32_t index; char name[128]; enum cam_cdm_id id; enum cam_cdm_flags flags; struct completion reset_complete; - struct completion bl_complete; struct workqueue_struct *work_queue; struct list_head bl_request_list; struct cam_hw_version version; uint32_t hw_version; uint32_t hw_family_version; struct cam_iommu_handle iommu_hdl; - struct cam_cdm_reg_offset_table *offset_tbl; + struct cam_cdm_hw_reg_offset *offsets; struct cam_cdm_utils_ops *ops; struct cam_cdm_client *clients[CAM_PER_CDM_MAX_REGISTERED_CLIENTS]; + struct cam_cdm_bl_fifo bl_fifo[CAM_CDM_BL_FIFO_MAX]; + unsigned long cdm_status; uint8_t bl_tag; - atomic_t error; - atomic_t bl_done; - struct cam_cdm_hw_mem gen_irq; + struct cam_cdm_hw_mem gen_irq[CAM_CDM_BL_FIFO_MAX]; uint32_t cpas_handle; + enum cam_cdm_arbitration arbitration; }; /* struct cam_cdm_private_dt_data - CDM hw custom dt data */ @@ -224,6 +522,8 @@ struct cam_cdm_private_dt_data { bool dt_cdm_shared; uint32_t dt_num_supported_clients; const char *dt_cdm_client_name[CAM_PER_CDM_MAX_REGISTERED_CLIENTS]; + bool config_fifo; + uint32_t fifo_depth[CAM_CDM_BL_FIFO_MAX]; }; /* struct cam_cdm_intf_devices - CDM mgr interface devices */ diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index e903dc805ed0..034fdb5fa49d 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -45,9 +45,10 @@ bool cam_cdm_set_cam_hw_version( uint32_t ver, struct cam_hw_version *cam_version) { switch (ver) { - case CAM_CDM170_VERSION: - case CAM_CDM175_VERSION: - case CAM_CDM480_VERSION: + case CAM_CDM100_VERSION: + case CAM_CDM110_VERSION: + case CAM_CDM120_VERSION: + case CAM_CDM200_VERSION: cam_version->major = (ver & 0xF0000000); cam_version->minor = (ver & 0xFFF0000); cam_version->incr = (ver & 0xFFFF); @@ -76,9 +77,10 @@ struct cam_cdm_utils_ops *cam_cdm_get_ops( { if (by_cam_version == false) { switch (ver) { - case CAM_CDM170_VERSION: - case CAM_CDM175_VERSION: - case CAM_CDM480_VERSION: + case CAM_CDM100_VERSION: + case CAM_CDM110_VERSION: + case CAM_CDM120_VERSION: + case CAM_CDM200_VERSION: return &CDM170_ops; default: CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", @@ -183,6 +185,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, return; } cam_cdm_get_client_refcount(client); + mutex_lock(&client->lock); if (client->data.cam_cdm_callback) { CAM_DBG(CAM_CDM, "Calling client=%s cb cookie=%d", client->data.identifier, node->cookie); @@ -195,6 +198,38 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, CAM_ERR(CAM_CDM, "No cb registered for client hdl=%x", node->client_hdl); } + mutex_unlock(&client->lock); + cam_cdm_put_client_refcount(client); + return; + } else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE || + status == CAM_CDM_CB_STATUS_HW_FLUSH || + status == CAM_CDM_CB_STATUS_HW_RESUBMIT || + status == CAM_CDM_CB_STATUS_HW_ERROR) { + int client_idx; + struct cam_cdm_bl_cb_request_entry *node = + (struct cam_cdm_bl_cb_request_entry *)data; + + client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl); + client = core->clients[client_idx]; + if ((!client) || (client->handle != node->client_hdl)) { + CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, + node->client_hdl); + return; + } + cam_cdm_get_client_refcount(client); + mutex_lock(&client->lock); + if (client->data.cam_cdm_callback) { + client->data.cam_cdm_callback( + client->handle, + client->data.userdata, + status, + node->cookie); + } else { + CAM_ERR(CAM_CDM, + "No cb registered for client: name %s, hdl=%x", + client->data.identifier, client->handle); + } + mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); return; } @@ -202,6 +237,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) { if (core->clients[i] != NULL) { client = core->clients[i]; + cam_cdm_get_client_refcount(client); mutex_lock(&client->lock); CAM_DBG(CAM_CDM, "Found client slot %d", i); if (client->data.cam_cdm_callback) { @@ -221,6 +257,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, client->handle); } mutex_unlock(&client->lock); + cam_cdm_put_client_refcount(client); } } } @@ -479,6 +516,27 @@ int cam_cdm_process_cmd(void *hw_priv, data = (struct cam_cdm_acquire_data *)cmd_args; CAM_DBG(CAM_CDM, "Trying to acquire client=%s in hw idx=%d", data->identifier, core->index); + + if (data->priority >= CAM_CDM_BL_FIFO_MAX) { + mutex_unlock(&cdm_hw->hw_mutex); + CAM_ERR(CAM_CDM, + "Invalid priority requested %d", + data->priority); + rc = -EINVAL; + break; + } + + if (core->id != CAM_CDM_VIRTUAL && + core->bl_fifo[data->priority].bl_depth == 0) { + mutex_unlock(&cdm_hw->hw_mutex); + CAM_ERR(CAM_CDM, + "FIFO %d not supported for core %d", + data->priority, + core->id); + rc = -EINVAL; + break; + } + idx = cam_cdm_find_free_client_slot(core); if ((idx < 0) || (core->clients[idx])) { mutex_unlock(&cdm_hw->hw_mutex); @@ -527,6 +585,7 @@ int cam_cdm_process_cmd(void *hw_priv, sizeof(struct cam_cdm_acquire_data)); client->handle = CAM_CDM_CREATE_CLIENT_HANDLE( core->index, + data->priority, idx); client->stream_on = false; data->handle = client->handle; @@ -575,8 +634,133 @@ int cam_cdm_process_cmd(void *hw_priv, break; } case CAM_CDM_HW_INTF_CMD_RESET_HW: { - CAM_ERR(CAM_CDM, "CDM HW reset not supported for handle =%x", - *((uint32_t *)cmd_args)); + uint32_t *handle = cmd_args; + int idx; + struct cam_cdm_client *client; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=%x", + cmd, arg_size, *handle); + return -EINVAL; + } + idx = CAM_CDM_GET_CLIENT_IDX(*handle); + mutex_lock(&cdm_hw->hw_mutex); + client = core->clients[idx]; + if (!client) { + CAM_ERR(CAM_CDM, + "Client not present for handle %d", + *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + if (*handle != client->handle) { + CAM_ERR(CAM_CDM, + "handle mismatch, client handle %d index %d received handle %d", + client->handle, idx, *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + rc = cam_hw_cdm_reset_hw(cdm_hw, *handle); + if (rc) { + CAM_ERR(CAM_CDM, + "CDM HW reset failed for handle 0x%x rc = %d", + *handle, rc); + } else { + CAM_INFO_RATE_LIMIT(CAM_CDM, + "CDM HW reset done for handle 0x%x", + *handle); + } + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + case CAM_CDM_HW_INTF_CMD_FLUSH_HW: { + uint32_t *handle = cmd_args; + int idx; + struct cam_cdm_client *client; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=%x", + cmd, arg_size, *handle); + return -EINVAL; + } + idx = CAM_CDM_GET_CLIENT_IDX(*handle); + mutex_lock(&cdm_hw->hw_mutex); + client = core->clients[idx]; + if (!client) { + CAM_ERR(CAM_CDM, + "Client not present for handle %d", + *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + if (*handle != client->handle) { + CAM_ERR(CAM_CDM, + "handle mismatch, client handle %d index %d received handle %d", + client->handle, idx, *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + rc = cam_hw_cdm_flush_hw(cdm_hw, *handle); + if (rc) { + CAM_ERR(CAM_CDM, + "CDM HW flush failed for handle 0x%x rc = %d", + *handle, rc); + } else { + CAM_INFO_RATE_LIMIT(CAM_CDM, + "CDM HW flush done for handle 0x%x", + *handle); + } + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + case CAM_CDM_HW_INTF_CMD_HANDLE_ERROR: { + uint32_t *handle = cmd_args; + int idx; + struct cam_cdm_client *client; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=%x", + cmd, arg_size, *handle); + return -EINVAL; + } + + idx = CAM_CDM_GET_CLIENT_IDX(*handle); + mutex_lock(&cdm_hw->hw_mutex); + client = core->clients[idx]; + if (!client) { + CAM_ERR(CAM_CDM, + "Client not present for handle %d", + *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + if (*handle != client->handle) { + CAM_ERR(CAM_CDM, + "handle mismatch, client handle %d index %d received handle %d", + client->handle, idx, *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + rc = cam_hw_cdm_handle_error(cdm_hw, *handle); + if (rc) { + CAM_ERR(CAM_CDM, + "CDM HW handle error failed for handle 0x%x rc = %d", + *handle, rc); + } else { + CAM_INFO_RATE_LIMIT(CAM_CDM, + "CDM HW handle error done for handle 0x%x", + *handle); + } + + mutex_unlock(&cdm_hw->hw_mutex); break; } default: diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h index 8dcbe8ed1971..055c7cf1fe9d 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.h +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_CORE_COMMON_H_ @@ -8,9 +8,19 @@ #include "cam_mem_mgr.h" -#define CAM_CDM170_VERSION 0x10000000 -#define CAM_CDM175_VERSION 0x10010000 -#define CAM_CDM480_VERSION 0x10020000 +#define CAM_CDM100_VERSION 0x10000000 +#define CAM_CDM110_VERSION 0x10010000 +#define CAM_CDM120_VERSION 0x10020000 +#define CAM_CDM200_VERSION 0x20000000 + +#define CAM_CDM_AHB_BURST_LEN_1 (BIT(1) - 1) +#define CAM_CDM_AHB_BURST_LEN_4 (BIT(2) - 1) +#define CAM_CDM_AHB_BURST_LEN_8 (BIT(3) - 1) +#define CAM_CDM_AHB_BURST_LEN_16 (BIT(4) - 1) +#define CAM_CDM_AHB_BURST_EN BIT(5) +#define CAM_CDM_AHB_STOP_ON_ERROR BIT(8) +#define CAM_CDM_ARB_SEL_RR BIT(16) +#define CAM_CDM_IMPLICIT_WAIT_EN BIT(17) extern struct cam_cdm_utils_ops CDM170_ops; @@ -37,6 +47,9 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw, int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, struct cam_cdm_hw_intf_cmd_submit_bl *req, struct cam_cdm_client *client); +int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle); +int cam_hw_cdm_flush_hw(struct cam_hw_info *cdm_hw, uint32_t handle); +int cam_hw_cdm_handle_error(struct cam_hw_info *cdm_hw, uint32_t handle); struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( uint32_t tag, struct list_head *bl_list); void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 5a59e4c611df..1142f2776f4f 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -18,14 +18,13 @@ #include "cam_cdm_core_common.h" #include "cam_cdm_soc.h" #include "cam_io_util.h" -#include "cam_hw_cdm170_reg.h" - -#define CAM_HW_CDM_CPAS_0_NAME "qcom,cam170-cpas-cdm0" -#define CAM_HW_CDM_IPE_0_NAME "qcom,cam170-ipe0-cdm" -#define CAM_HW_CDM_IPE_1_NAME "qcom,cam170-ipe1-cdm" -#define CAM_HW_CDM_BPS_NAME "qcom,cam170-bps-cdm" +#include "cam_cdm_hw_reg_1_0.h" +#include "cam_cdm_hw_reg_1_1.h" +#include "cam_cdm_hw_reg_1_2.h" +#include "cam_cdm_hw_reg_2_0.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 +#define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff static void cam_hw_cdm_work(struct work_struct *work); @@ -33,65 +32,96 @@ static void cam_hw_cdm_work(struct work_struct *work); static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { { .compatible = CAM_HW_CDM_CPAS_0_NAME, - .data = &cam170_cpas_cdm_offset_table, + .data = &cam_cdm_1_0_reg_offset, + }, + { + .compatible = CAM_HW_CDM_CPAS_NAME_1_0, + .data = &cam_cdm_1_0_reg_offset, + }, + { + .compatible = CAM_HW_CDM_CPAS_NAME_1_1, + .data = &cam_cdm_1_1_reg_offset, + }, + { + .compatible = CAM_HW_CDM_CPAS_NAME_1_2, + .data = &cam_cdm_1_2_reg_offset, + }, + { + .compatible = CAM_HW_CDM_IFE_NAME_1_2, + .data = &cam_cdm_1_2_reg_offset, + }, + { + .compatible = CAM_HW_CDM_CPAS_NAME_2_0, + .data = &cam_cdm_2_0_reg_offset, + }, + { + .compatible = CAM_HW_CDM_OPE_NAME_2_0, + .data = &cam_cdm_2_0_reg_offset, }, - {} }; static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) { - if (!strcmp(CAM_HW_CDM_CPAS_0_NAME, name)) - return CAM_CDM_CPAS_0; + if (strnstr(name, CAM_HW_CDM_CPAS_0_NAME, + strlen(CAM_HW_CDM_CPAS_0_NAME))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_CPAS_NAME_1_0, + strlen(CAM_HW_CDM_CPAS_NAME_1_0))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_CPAS_NAME_1_1, + strlen(CAM_HW_CDM_CPAS_NAME_1_1))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_CPAS_NAME_1_2, + strlen(CAM_HW_CDM_CPAS_NAME_1_2))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_IFE_NAME_1_2, + strlen(CAM_HW_CDM_CPAS_NAME_1_2))) + return CAM_CDM_IFE; + if (strnstr(name, CAM_HW_CDM_CPAS_NAME_2_0, + strlen(CAM_HW_CDM_CPAS_NAME_2_0))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_0, + strlen(CAM_HW_CDM_CPAS_NAME_2_0))) + return CAM_CDM_OPE; return CAM_CDM_MAX; } -int cam_hw_cdm_bl_fifo_pending_bl_rb(struct cam_hw_info *cdm_hw, - uint32_t *pending_bl) -{ - int rc = 0; - - if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB, - pending_bl)) { - CAM_ERR(CAM_CDM, "Failed to read CDM pending BL's"); - rc = -EIO; - } - - return rc; -} - static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw, - bool enable) + bool enable, uint32_t fifo_idx) { int rc = -EIO; uint32_t irq_mask = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_MASK, - &irq_mask)) { + if (cam_cdm_read_hw_reg(cdm_hw, + core->offsets->irq_reg[fifo_idx]->irq_mask, + &irq_mask)) { CAM_ERR(CAM_CDM, "Failed to read CDM IRQ mask"); return rc; } if (enable == true) { - if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, - (irq_mask | 0x4))) { + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->irq_reg[fifo_idx]->irq_mask, + (irq_mask | 0x4))) { CAM_ERR(CAM_CDM, "Write failed to enable BL done irq"); } else { - atomic_inc(&core->bl_done); + set_bit(fifo_idx, &core->cdm_status); rc = 0; CAM_DBG(CAM_CDM, "BL done irq enabled =%d", - atomic_read(&core->bl_done)); + test_bit(fifo_idx, &core->cdm_status)); } } else { - if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, - (irq_mask & 0x70003))) { + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->irq_reg[fifo_idx]->irq_mask, + (irq_mask & 0x70003))) { CAM_ERR(CAM_CDM, "Write failed to disable BL done irq"); } else { - atomic_dec(&core->bl_done); + clear_bit(fifo_idx, &core->cdm_status); rc = 0; CAM_DBG(CAM_CDM, "BL done irq disable =%d", - atomic_read(&core->bl_done)); + test_bit(fifo_idx, &core->cdm_status)); } } return rc; @@ -100,14 +130,19 @@ static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw, static int cam_hw_cdm_enable_core(struct cam_hw_info *cdm_hw, bool enable) { int rc = 0; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (enable == true) { - if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x01)) { + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_en, + 0x01)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core enable"); rc = -EIO; } } else { - if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x02)) { + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_en, + 0x02)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core disable"); rc = -EIO; } @@ -118,8 +153,11 @@ static int cam_hw_cdm_enable_core(struct cam_hw_info *cdm_hw, bool enable) int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) { int rc = 0; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0x10100)) { + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_debug, + 0x10100)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } @@ -130,8 +168,10 @@ int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) int cam_hw_cdm_disable_core_dbg(struct cam_hw_info *cdm_hw) { int rc = 0; + struct cam_cdm *cdm_core = (struct cam_cdm *)cdm_hw->core_info; - if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0)) { + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->core_debug, 0)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } @@ -142,129 +182,362 @@ int cam_hw_cdm_disable_core_dbg(struct cam_hw_info *cdm_hw) void cam_hw_cdm_dump_scratch_registors(struct cam_hw_info *cdm_hw) { uint32_t dump_reg = 0; + int i; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_en, &dump_reg); CAM_ERR(CAM_CDM, "dump core en=%x", dump_reg); - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_0_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch0=%x", dump_reg); + for (i = 0; i < core->offsets->reg_data->num_scratch_reg; i++) { + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->scratch[i]->scratch_reg, + &dump_reg); + CAM_ERR(CAM_CDM, "dump scratch%d=%x", i, dump_reg); + } +} - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_1_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch1=%x", dump_reg); +int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo( + struct cam_hw_info *cdm_hw, + uint32_t fifo_idx, + uint32_t *pending_bl_req) +{ + int rc = 0; + uint32_t fifo_reg; + uint32_t fifo_id; - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_2_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch2=%x", dump_reg); + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_3_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch3=%x", dump_reg); + if (fifo_idx >= CAM_CDM_BL_FIFO_REG_NUM) { + CAM_ERR(CAM_CDM, + "BL_FIFO index is wrong. fifo_idx %d", + fifo_idx); + rc = -EINVAL; + goto end; + } - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_4_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch4=%x", dump_reg); + fifo_reg = fifo_idx / 2; + fifo_id = fifo_idx % 2; - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_5_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch5=%x", dump_reg); + if (core->offsets->cmn_reg->pending_req[fifo_reg]) { + if (cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->pending_req + [fifo_reg]->rb_offset, + pending_bl_req)) { + CAM_ERR(CAM_CDM, "Error reading CDM register"); + rc = -EIO; + goto end; + } - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_6_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch6=%x", dump_reg); + *pending_bl_req = (*pending_bl_req >> ( + core->offsets->cmn_reg->pending_req + [fifo_reg]->rb_next_fifo_shift * + fifo_id)) & core->offsets->cmn_reg->pending_req + [fifo_reg]->rb_mask; + rc = 0; + } - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_7_REG, &dump_reg); - CAM_ERR(CAM_CDM, "dump scratch7=%x", dump_reg); + CAM_DBG(CAM_CDM, "pending_bl_req %d fifo_reg %d, fifo_id %d", + *pending_bl_req, fifo_reg, fifo_id); +end: + return rc; +} + +int cam_hw_cdm_enable_core_dbg_per_fifo( + struct cam_hw_info *cdm_hw, + uint32_t fifo_idx) +{ + int rc = 0; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_debug, + (0x10100 | fifo_idx << 20))) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); + rc = -EIO; + } + + return rc; +} + +void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) +{ + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + int i, j; + uint32_t num_pending_req = 0, dump_reg; + + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { + cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, + i, &num_pending_req); + + if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) { + CAM_ERR(CAM_CDM, + "Problem in selecting the fifo for readback"); + continue; + } + for (j = 0 ; j < num_pending_req ; j++) { + cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->bl_fifo_rb, j); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->bl_fifo_base_rb, + &dump_reg); + CAM_INFO(CAM_CDM, "BL(%d) base addr =%x", j, dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->bl_fifo_len_rb, + &dump_reg); + CAM_INFO(CAM_CDM, + "CDM HW current BL len=%d ARB %d tag=%d, ", + (dump_reg & CAM_CDM_CURRENT_BL_LEN), + (dump_reg & CAM_CDM_CURRENT_BL_ARB) >> + CAM_CDM_CURRENT_BL_ARB_SHIFT, + (dump_reg & CAM_CDM_CURRENT_BL_TAG) >> + CAM_CDM_CURRENT_BL_TAG_SHIFT); + } + } } void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw) { - uint32_t dump_reg, core_dbg, loop_cnt; + uint32_t dump_reg, core_dbg; + int i; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - mutex_lock(&cdm_hw->hw_mutex); - cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg); + cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); CAM_ERR(CAM_CDM, "CDM HW core status=%x", dump_reg); + /* First pause CDM, If it fails still proceed to dump debug info */ cam_hw_cdm_enable_core(cdm_hw, false); - cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW current pending BL=%x", dump_reg); - loop_cnt = dump_reg; - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_DEBUG_STATUS, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, &core_dbg); + + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->debug_status, + &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_debug, + &core_dbg); if (core_dbg & 0x100) { - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_LAST_AHB_ADDR, &dump_reg); - CAM_ERR(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_LAST_AHB_DATA, &dump_reg); - CAM_ERR(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->last_ahb_addr, + &dump_reg); + CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->last_ahb_data, + &dump_reg); + CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); } else { - CAM_ERR(CAM_CDM, "CDM HW AHB dump not enable"); + CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } - if (core_dbg & 0x10000) { - int i; + cam_hw_cdm_dump_bl_fifo_data(cdm_hw); - CAM_ERR(CAM_CDM, "CDM HW BL FIFO dump with loop count=%d", - loop_cnt); - for (i = 0 ; i < loop_cnt ; i++) { - cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_RB, i); - cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_BASE_RB, - &dump_reg); - CAM_ERR(CAM_CDM, "BL(%d) base addr =%x", i, dump_reg); - cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_LEN_RB, - &dump_reg); - CAM_ERR(CAM_CDM, "BL(%d) len=%d tag=%d", i, - (dump_reg & 0xFFFFF), (dump_reg & 0xFF000000)); - } - } else { - CAM_ERR(CAM_CDM, "CDM HW BL FIFO readback not enable"); + CAM_INFO(CAM_CDM, "CDM HW default dump"); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_cfg, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); + + for (i = 0; i < + core->offsets->reg_data->num_bl_fifo_irq; + i++) { + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->irq_reg[i]->irq_status, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->irq_reg[i]->irq_set, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->irq_reg[i]->irq_mask, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->irq_reg[i]->irq_clear, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg); } - CAM_ERR(CAM_CDM, "CDM HW default dump"); - cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_CFG, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW core cfg=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->current_bl_base, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg); - cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_STATUS, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW irq status=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->current_bl_len, &dump_reg); + CAM_INFO(CAM_CDM, + "CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ", + (dump_reg & CAM_CDM_CURRENT_BL_LEN), + (dump_reg & CAM_CDM_CURRENT_BL_ARB) >> + CAM_CDM_CURRENT_BL_ARB_SHIFT, + (dump_reg & CAM_CDM_CURRENT_BL_FIFO) >> + CAM_CDM_CURRENT_BL_FIFO_SHIFT, + (dump_reg & CAM_CDM_CURRENT_BL_TAG) >> + CAM_CDM_CURRENT_BL_TAG_SHIFT); - cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_SET, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW irq set reg=%x", dump_reg); - - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_BL_BASE, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW current BL base=%x", dump_reg); - - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_BL_LEN, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW current BL len=%d tag=%d", - (dump_reg & 0xFFFFF), (dump_reg & 0xFF000000)); - - cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_USED_AHB_BASE, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); - - cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW current pending BL=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); /* Enable CDM back */ cam_hw_cdm_enable_core(cdm_hw, true); - mutex_unlock(&cdm_hw->hw_mutex); - } -int cam_hw_cdm_wait_for_bl_fifo(struct cam_hw_info *cdm_hw, - uint32_t bl_count) +enum cam_cdm_arbitration cam_cdm_get_arbitration_type( + uint32_t cdm_version, + enum cam_cdm_id id) +{ + enum cam_cdm_arbitration arbitration; + + if (cdm_version < CAM_CDM_VERSION_2_0) { + arbitration = CAM_CDM_ARBITRATION_NONE; + goto end; + } + + switch (id) { + case CAM_CDM_CPAS: + arbitration = CAM_CDM_ARBITRATION_ROUND_ROBIN; + break; + default: + arbitration = CAM_CDM_ARBITRATION_PRIORITY_BASED; + break; + } +end: + return arbitration; +} + +int cam_hw_cdm_set_cdm_blfifo_cfg(struct cam_hw_info *cdm_hw) +{ + uint32_t blfifo_cfg_mask = 0; + int rc = 0, i; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + + blfifo_cfg_mask = blfifo_cfg_mask | + CAM_CDM_BL_FIFO_REQ_SIZE_MAX; + + for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->irq_reg[i]->irq_mask, 0x70003); + if (rc) { + CAM_ERR(CAM_CDM, + "Unable to write to cdm irq mask register"); + rc = -EIO; + goto end; + } + } + + if (core->hw_version >= CAM_CDM_VERSION_2_0) { + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { + blfifo_cfg_mask = blfifo_cfg_mask | + (core->bl_fifo[i].bl_depth + << CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT); + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->bl_fifo_reg[i]->bl_fifo_cfg, + blfifo_cfg_mask); + if (rc) { + CAM_ERR(CAM_CDM, + "Unable to write to cdm irq mask register"); + rc = -EIO; + goto end; + } + } + } else { + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->bl_fifo_reg[i]->bl_fifo_cfg, + blfifo_cfg_mask); + if (rc) { + CAM_ERR(CAM_CDM, + "Unable to write to cdm irq mask register"); + rc = -EIO; + goto end; + } + } + } +end: + return rc; +} + +int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) +{ + uint32_t cdm_version; + uint32_t cfg_mask = 0; + int rc; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + + cfg_mask = cfg_mask | + CAM_CDM_AHB_STOP_ON_ERROR| + CAM_CDM_AHB_BURST_EN| + CAM_CDM_AHB_BURST_LEN_16; + + /* use version from cdm_core structure. */ + if (cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->cdm_hw_version, + &cdm_version)) { + CAM_ERR(CAM_CDM, "Error reading CDM register"); + rc = -EIO; + goto end; + } + + if (cdm_version < CAM_CDM_VERSION_2_0) { + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_cfg, cfg_mask); + if (rc) { + CAM_ERR(CAM_CDM, "Error writing cdm core cfg"); + rc = -EIO; + goto end; + } + } else { + if (core->id != CAM_CDM_CPAS) + cfg_mask = cfg_mask | CAM_CDM_IMPLICIT_WAIT_EN; + + if (core->arbitration == CAM_CDM_ARBITRATION_ROUND_ROBIN) + cfg_mask = cfg_mask | CAM_CDM_ARB_SEL_RR; + + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_cfg, cfg_mask); + if (rc) { + CAM_ERR(CAM_CDM, "Error writing cdm core cfg"); + rc = -EIO; + goto end; + } + } + +end: + return rc; +} + +int cam_hw_cdm_wait_for_bl_fifo( + struct cam_hw_info *cdm_hw, + uint32_t bl_count, + uint32_t fifo_idx) { uint32_t pending_bl = 0; int32_t available_bl_slots = 0; int rc = -EIO; long time_left; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + struct cam_cdm_bl_fifo *bl_fifo = NULL; + + if (fifo_idx >= CAM_CDM_BL_FIFO_MAX) { + rc = -EINVAL; + CAM_ERR(CAM_CDM, + "Invalid fifo index %d rc = %d", + fifo_idx, rc); + goto end; + } + + bl_fifo = &core->bl_fifo[fifo_idx]; do { - if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB, - &pending_bl)) { + if (cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo( + cdm_hw, fifo_idx, &pending_bl)) { CAM_ERR(CAM_CDM, "Failed to read CDM pending BL's"); rc = -EIO; break; } - available_bl_slots = CAM_CDM_HWFIFO_SIZE - pending_bl; + available_bl_slots = bl_fifo->bl_depth - pending_bl; if (available_bl_slots < 0) { CAM_ERR(CAM_CDM, "Invalid available slots %d:%d:%d", - available_bl_slots, CAM_CDM_HWFIFO_SIZE, + available_bl_slots, bl_fifo->bl_depth, pending_bl); break; } @@ -275,25 +548,28 @@ int cam_hw_cdm_wait_for_bl_fifo(struct cam_hw_info *cdm_hw, rc = bl_count; break; } else if (0 == (available_bl_slots - 1)) { - rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, true); + rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, + true, fifo_idx); if (rc) { CAM_ERR(CAM_CDM, "Enable BL done irq failed"); break; } time_left = wait_for_completion_timeout( - &core->bl_complete, msecs_to_jiffies( + &core->bl_fifo[fifo_idx].bl_complete, + msecs_to_jiffies( CAM_CDM_BL_FIFO_WAIT_TIMEOUT)); if (time_left <= 0) { CAM_ERR(CAM_CDM, "CDM HW BL Wait timed out failed"); if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, - false)) + false, fifo_idx)) CAM_ERR(CAM_CDM, "Disable BL done irq failed"); rc = -EIO; break; } - if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, false)) + if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, + false, fifo_idx)) CAM_ERR(CAM_CDM, "Disable BL done irq failed"); rc = 0; CAM_DBG(CAM_CDM, "CDM HW is ready for data"); @@ -303,78 +579,110 @@ int cam_hw_cdm_wait_for_bl_fifo(struct cam_hw_info *cdm_hw, } } while (1); +end: + return rc; } -bool cam_hw_cdm_bl_write(struct cam_hw_info *cdm_hw, uint32_t src, - uint32_t len, uint32_t tag) +bool cam_hw_cdm_bl_write( + struct cam_hw_info *cdm_hw, uint32_t src, + uint32_t len, uint32_t tag, bool set_arb, + uint32_t fifo_idx) { - if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_BASE_REG, src)) { + struct cam_cdm *cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->bl_fifo_reg[fifo_idx]->bl_fifo_base, + src)) { CAM_ERR(CAM_CDM, "Failed to write CDM base to BL base"); return true; } - if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_LEN_REG, - ((len & 0xFFFFF) | ((tag & 0xFF) << 20)))) { + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->bl_fifo_reg[fifo_idx]->bl_fifo_len, + ((len & 0xFFFFF) | ((tag & 0xFF) << 24)) | + ((set_arb) ? (1 << 20) : (0)))) { CAM_ERR(CAM_CDM, "Failed to write CDM BL len"); return true; } return false; } -bool cam_hw_cdm_commit_bl_write(struct cam_hw_info *cdm_hw) +bool cam_hw_cdm_commit_bl_write(struct cam_hw_info *cdm_hw, uint32_t fifo_idx) { - if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_STORE_REG, 1)) { + struct cam_cdm *cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->bl_fifo_reg[fifo_idx]->bl_fifo_store, + 1)) { CAM_ERR(CAM_CDM, "Failed to write CDM commit BL"); return true; } return false; } -int cam_hw_cdm_submit_gen_irq(struct cam_hw_info *cdm_hw, - struct cam_cdm_hw_intf_cmd_submit_bl *req) +int cam_hw_cdm_submit_gen_irq( + struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req, + uint32_t fifo_idx, bool set_arb) { struct cam_cdm_bl_cb_request_entry *node; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; uint32_t len; int rc; + bool bit_wr_enable = false; - if (core->bl_tag > 63) { - CAM_ERR(CAM_CDM, "bl_tag invalid =%d", core->bl_tag); + if (core->bl_fifo[fifo_idx].bl_tag > 63) { + CAM_ERR(CAM_CDM, + "bl_tag invalid =%d", + core->bl_fifo[fifo_idx].bl_tag); rc = -EINVAL; goto end; } CAM_DBG(CAM_CDM, "CDM write BL last cmd tag=%x total=%d cookie=%d", - core->bl_tag, req->data->cmd_arrary_count, req->data->cookie); + core->bl_fifo[fifo_idx].bl_tag, + req->data->cmd_arrary_count, + req->data->cookie); + node = kzalloc(sizeof(struct cam_cdm_bl_cb_request_entry), GFP_KERNEL); if (!node) { rc = -ENOMEM; goto end; } + + if (core->offsets->reg_data->num_bl_fifo > 1) + bit_wr_enable = true; + node->request_type = CAM_HW_CDM_BL_CB_CLIENT; node->client_hdl = req->handle; node->cookie = req->data->cookie; - node->bl_tag = core->bl_tag; + node->bl_tag = core->bl_fifo[fifo_idx].bl_tag; node->userdata = req->data->userdata; - list_add_tail(&node->entry, &core->bl_request_list); - len = core->ops->cdm_required_size_genirq() * core->bl_tag; - core->ops->cdm_write_genirq(((uint32_t *)core->gen_irq.kmdvaddr + len), - core->bl_tag); - rc = cam_hw_cdm_bl_write(cdm_hw, (core->gen_irq.vaddr + (4*len)), + list_add_tail(&node->entry, &core->bl_fifo[fifo_idx].bl_request_list); + len = core->ops->cdm_required_size_genirq() * + core->bl_fifo[fifo_idx].bl_tag; + core->ops->cdm_write_genirq( + ((uint32_t *)core->gen_irq[fifo_idx].kmdvaddr + len), + core->bl_fifo[fifo_idx].bl_tag, + bit_wr_enable, fifo_idx); + rc = cam_hw_cdm_bl_write(cdm_hw, + (core->gen_irq[fifo_idx].vaddr + (4*len)), ((4 * core->ops->cdm_required_size_genirq()) - 1), - core->bl_tag); + core->bl_fifo[fifo_idx].bl_tag, + set_arb, fifo_idx); if (rc) { CAM_ERR(CAM_CDM, "CDM hw bl write failed for gen irq bltag=%d", - core->bl_tag); + core->bl_fifo[fifo_idx].bl_tag); list_del_init(&node->entry); kfree(node); rc = -EIO; goto end; } - if (cam_hw_cdm_commit_bl_write(cdm_hw)) { - CAM_ERR(CAM_CDM, "Cannot commit the genirq BL with tag tag=%d", - core->bl_tag); + if (cam_hw_cdm_commit_bl_write(cdm_hw, fifo_idx)) { + CAM_ERR(CAM_CDM, + "Cannot commit the genirq BL with tag tag=%d", + core->bl_fifo[fifo_idx].bl_tag); list_del_init(&node->entry); kfree(node); rc = -EIO; @@ -384,6 +692,52 @@ end: return rc; } +int cam_hw_cdm_submit_debug_gen_irq( + struct cam_hw_info *cdm_hw, + uint32_t fifo_idx) +{ + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + uint32_t len; + int rc; + bool bit_wr_enable = false; + + CAM_DBG(CAM_CDM, + "CDM write BL last cmd tag=0x%x", + core->bl_fifo[fifo_idx].bl_tag); + + if (core->offsets->reg_data->num_bl_fifo > 1) + bit_wr_enable = true; + + len = core->ops->cdm_required_size_genirq() * + core->bl_fifo[fifo_idx].bl_tag; + core->ops->cdm_write_genirq( + ((uint32_t *)core->gen_irq[fifo_idx].kmdvaddr + len), + CAM_CDM_DBG_GEN_IRQ_USR_DATA, bit_wr_enable, fifo_idx); + rc = cam_hw_cdm_bl_write(cdm_hw, + (core->gen_irq[fifo_idx].vaddr + (4*len)), + ((4 * core->ops->cdm_required_size_genirq()) - 1), + core->bl_fifo[fifo_idx].bl_tag, + false, fifo_idx); + if (rc) { + CAM_ERR(CAM_CDM, + "CDM hw bl write failed for dbggenirq USRdata=%d tag 0x%x", + CAM_CDM_DBG_GEN_IRQ_USR_DATA, + core->bl_fifo[fifo_idx].bl_tag); + rc = -EIO; + goto end; + } + if (cam_hw_cdm_commit_bl_write(cdm_hw, fifo_idx)) { + CAM_ERR(CAM_CDM, + "Cannot commit the dbggenirq BL with tag tag=0x%x", + core->bl_fifo[fifo_idx].bl_tag); + rc = -EIO; + goto end; + } + +end: + return rc; +} + int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, struct cam_cdm_hw_intf_cmd_submit_bl *req, struct cam_cdm_client *client) @@ -391,24 +745,42 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, int i, rc; struct cam_cdm_bl_request *cdm_cmd = req->data; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - uint32_t pending_bl = 0; + struct cam_cdm_bl_fifo *bl_fifo = NULL; + uint32_t pending_bl = 0, fifo_idx = 0; int write_count = 0; - if (req->data->cmd_arrary_count > CAM_CDM_HWFIFO_SIZE) { - pr_info("requested BL more than max size, cnt=%d max=%d", - req->data->cmd_arrary_count, CAM_CDM_HWFIFO_SIZE); + fifo_idx = CAM_CDM_GET_BLFIFO_IDX(client->handle); + + if (fifo_idx >= CAM_CDM_BL_FIFO_MAX) { + rc = -EINVAL; + CAM_ERR(CAM_CDM, "Invalid handle 0x%x, rc = %d", + client->handle, rc); + goto end; } - if (atomic_read(&core->error)) - return -EIO; + bl_fifo = &core->bl_fifo[fifo_idx]; - mutex_lock(&cdm_hw->hw_mutex); + if (req->data->cmd_arrary_count > bl_fifo->bl_depth) { + CAM_INFO(CAM_CDM, + "requested BL more than max size, cnt=%d max=%d", + req->data->cmd_arrary_count, + bl_fifo->bl_depth); + } + + if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || + test_bit(CAM_CDM_RESET_HW_STATUS, &core->cdm_status)) + return -EAGAIN; + + mutex_lock(&core->bl_fifo[fifo_idx].fifo_lock); mutex_lock(&client->lock); - rc = cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &pending_bl); + + rc = cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, + fifo_idx, &pending_bl); + if (rc) { CAM_ERR(CAM_CDM, "Cannot read the current BL depth"); mutex_unlock(&client->lock); - mutex_unlock(&cdm_hw->hw_mutex); + mutex_unlock(&core->bl_fifo[fifo_idx].fifo_lock); return rc; } @@ -425,16 +797,19 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, rc = -EINVAL; break; } - if (atomic_read(&core->error)) { + if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || + test_bit(CAM_CDM_RESET_HW_STATUS, + &core->cdm_status)) { CAM_ERR_RATE_LIMIT(CAM_CDM, - "In error state cnt=%d total cnt=%d\n", - i, req->data->cmd_arrary_count); - rc = -EIO; + "In error/reset state cnt=%d total cnt=%d cdm_status 0x%x", + i, req->data->cmd_arrary_count, + core->cdm_status); + rc = -EAGAIN; break; } if (write_count == 0) { write_count = cam_hw_cdm_wait_for_bl_fifo(cdm_hw, - (req->data->cmd_arrary_count - i)); + (req->data->cmd_arrary_count - i), fifo_idx); if (write_count < 0) { CAM_ERR(CAM_CDM, "wait for bl fifo failed %d:%d", @@ -485,13 +860,16 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, } CAM_DBG(CAM_CDM, "Got the HW VA"); - if (core->bl_tag >= - (CAM_CDM_HWFIFO_SIZE - 1)) - core->bl_tag = 0; + if (core->bl_fifo[fifo_idx].bl_tag >= + (bl_fifo->bl_depth - 1)) + core->bl_fifo[fifo_idx].bl_tag = 0; rc = cam_hw_cdm_bl_write(cdm_hw, ((uint32_t)hw_vaddr_ptr + cdm_cmd->cmd[i].offset), - (cdm_cmd->cmd[i].len - 1), core->bl_tag); + (cdm_cmd->cmd[i].len - 1), + core->bl_fifo[fifo_idx].bl_tag, + cdm_cmd->cmd[i].arbitrate, + fifo_idx); if (rc) { CAM_ERR(CAM_CDM, "Hw bl write failed %d:%d", i, req->data->cmd_arrary_count); @@ -512,40 +890,92 @@ 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 total_cnt=%d", - i, core->bl_tag, req->data->cmd_arrary_count); + i, core->bl_fifo[fifo_idx].bl_tag, + req->data->cmd_arrary_count); CAM_DBG(CAM_CDM, "Now commit the BL"); - if (cam_hw_cdm_commit_bl_write(cdm_hw)) { + if (cam_hw_cdm_commit_bl_write(cdm_hw, fifo_idx)) { CAM_ERR(CAM_CDM, "Cannot commit the BL %d tag=%d", - i, core->bl_tag); + i, core->bl_fifo[fifo_idx].bl_tag); rc = -EIO; break; } CAM_DBG(CAM_CDM, "BL commit success BL %d tag=%d", i, - core->bl_tag); - core->bl_tag++; + core->bl_fifo[fifo_idx].bl_tag); + core->bl_fifo[fifo_idx].bl_tag++; + + if (cdm_cmd->cmd[i].enable_debug_gen_irq) { + rc = cam_hw_cdm_submit_debug_gen_irq(cdm_hw, + fifo_idx); + if (rc == 0) + core->bl_fifo[fifo_idx].bl_tag++; + if (core->bl_fifo[fifo_idx].bl_tag >= + (bl_fifo->bl_depth - + 1)) + core->bl_fifo[fifo_idx].bl_tag = 0; + } + if ((req->data->flag == true) && (i == (req->data->cmd_arrary_count - 1))) { rc = cam_hw_cdm_submit_gen_irq( - cdm_hw, req); + cdm_hw, req, fifo_idx, + cdm_cmd->gen_irq_arb); if (rc == 0) - core->bl_tag++; + core->bl_fifo[fifo_idx].bl_tag++; } } } mutex_unlock(&client->lock); - mutex_unlock(&cdm_hw->hw_mutex); + mutex_unlock(&core->bl_fifo[fifo_idx].fifo_lock); + +end: return rc; } +static void cam_hw_cdm_reset_cleanup( + struct cam_hw_info *cdm_hw, + uint32_t handle) +{ + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + int i; + struct cam_cdm_bl_cb_request_entry *node, *tnode; + bool flush_hw = false; + + if (test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) + flush_hw = true; + + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { + list_for_each_entry_safe(node, tnode, + &core->bl_fifo[i].bl_request_list, entry) { + if (node->request_type == + CAM_HW_CDM_BL_CB_CLIENT) { + if (flush_hw) + cam_cdm_notify_clients(cdm_hw, + (node->client_hdl == handle) ? + CAM_CDM_CB_STATUS_HW_FLUSH : + CAM_CDM_CB_STATUS_HW_RESUBMIT, + (void *)node); + else + cam_cdm_notify_clients(cdm_hw, + CAM_CDM_CB_STATUS_HW_RESET_DONE, + (void *)node); + } + list_del_init(&node->entry); + kfree(node); + } + core->bl_fifo[i].bl_tag = 0; + } +} + static void cam_hw_cdm_work(struct work_struct *work) { struct cam_cdm_work_payload *payload; struct cam_hw_info *cdm_hw; struct cam_cdm *core; + int i; payload = container_of(work, struct cam_cdm_work_payload, work); if (payload) { @@ -554,14 +984,24 @@ static void cam_hw_cdm_work(struct work_struct *work) CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); if (payload->irq_status & - CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) { + CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { struct cam_cdm_bl_cb_request_entry *node, *tnode; CAM_DBG(CAM_CDM, "inline IRQ data=0x%x", payload->irq_data); - mutex_lock(&cdm_hw->hw_mutex); + + if (payload->irq_data == 0xff) { + CAM_INFO(CAM_CDM, "Debug genirq received"); + kfree(payload); + return; + } + + mutex_lock(&core->bl_fifo[payload->fifo_idx] + .fifo_lock); list_for_each_entry_safe(node, tnode, - &core->bl_request_list, entry) { + &core->bl_fifo[payload->fifo_idx] + .bl_request_list, + entry) { if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) { cam_cdm_notify_clients(cdm_hw, @@ -580,41 +1020,42 @@ static void cam_hw_cdm_work(struct work_struct *work) } kfree(node); } - mutex_unlock(&cdm_hw->hw_mutex); + mutex_unlock(&core->bl_fifo[payload->fifo_idx] + .fifo_lock); } if (payload->irq_status & - CAM_CDM_IRQ_STATUS_INFO_RST_DONE_MASK) { + CAM_CDM_IRQ_STATUS_RST_DONE_MASK) { CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); complete(&core->reset_complete); } if (payload->irq_status & - CAM_CDM_IRQ_STATUS_INFO_BL_DONE_MASK) { - if (atomic_read(&core->bl_done)) { + CAM_CDM_IRQ_STATUS_BL_DONE_MASK) { + if (test_bit(payload->fifo_idx, &core->cdm_status)) { CAM_DBG(CAM_CDM, "CDM HW BL done IRQ"); - complete(&core->bl_complete); + complete(&core->bl_fifo[payload->fifo_idx] + .bl_complete); } } if (payload->irq_status & - CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { + CAM_CDM_IRQ_STATUS_ERRORS) { CAM_ERR_RATE_LIMIT(CAM_CDM, - "Invalid command IRQ, Need HW reset\n"); - atomic_inc(&core->error); + "CDM Error IRQ status %d\n", + payload->irq_status); + set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); + mutex_lock(&cdm_hw->hw_mutex); + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; + i++) + mutex_lock(&core->bl_fifo[i].fifo_lock); cam_hw_cdm_dump_core_debug_registers(cdm_hw); - } - if (payload->irq_status & - CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) { - CAM_ERR_RATE_LIMIT(CAM_CDM, "AHB Error IRQ\n"); - atomic_inc(&core->error); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); - atomic_dec(&core->error); - } - if (payload->irq_status & - CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK) { - CAM_ERR_RATE_LIMIT(CAM_CDM, "Overflow Error IRQ\n"); - atomic_inc(&core->error); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); - atomic_dec(&core->error); + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; + i++) + mutex_unlock(&core->bl_fifo[i].fifo_lock); + mutex_unlock(&cdm_hw->hw_mutex); + if (!(payload->irq_status & + CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) + clear_bit(CAM_CDM_ERROR_HW_STATUS, + &core->cdm_status); } kfree(payload); } else { @@ -629,17 +1070,24 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; + int i; if (token) { cdm_hw = (struct cam_hw_info *)token; core = (struct cam_cdm *)cdm_hw->core_info; - atomic_inc(&core->error); + set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); + mutex_lock(&cdm_hw->hw_mutex); + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) + mutex_lock(&core->bl_fifo[i].fifo_lock); cam_hw_cdm_dump_core_debug_registers(cdm_hw); + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) + mutex_unlock(&core->bl_fifo[i].fifo_lock); + mutex_unlock(&cdm_hw->hw_mutex); CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n", (void *)iova); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT, (void *)iova); - atomic_dec(&core->error); + clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "Invalid token"); } @@ -650,46 +1098,88 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) { struct cam_hw_info *cdm_hw = data; struct cam_cdm *cdm_core = cdm_hw->core_info; - struct cam_cdm_work_payload *payload; + struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0}; + uint32_t user_data = 0; + uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0}; bool work_status; + int i; CAM_DBG(CAM_CDM, "Got irq"); - payload = kzalloc(sizeof(struct cam_cdm_work_payload), GFP_ATOMIC); - if (payload) { - if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_STATUS, - &payload->irq_status)) { + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { + if (cam_cdm_read_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_status, + &irq_status[i])) { CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status"); } - if (!payload->irq_status) { - CAM_ERR_RATE_LIMIT(CAM_CDM, "Invalid irq received\n"); - kfree(payload); - return IRQ_HANDLED; + } + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { + if (!irq_status[i]) { + cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_clear, + irq_status[i]); + continue; } - if (payload->irq_status & - CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) { - if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_USR_DATA, - &payload->irq_data)) { + + payload[i] = kzalloc(sizeof(struct cam_cdm_work_payload), + GFP_ATOMIC); + + if (!payload[i]) + continue; + + if (irq_status[i] & + CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { + if (cam_cdm_read_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->usr_data, + &user_data)) { CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ data"); + kfree(payload[i]); + return IRQ_HANDLED; } + + payload[i]->irq_data = user_data >> (i * 0x8); + + if (payload[i]->irq_data == + CAM_CDM_DBG_GEN_IRQ_USR_DATA) + CAM_INFO(CAM_CDM, + "Debug gen_irq received"); } - CAM_DBG(CAM_CDM, "Got payload=%d", payload->irq_status); - payload->hw = cdm_hw; - INIT_WORK((struct work_struct *)&payload->work, + + payload[i]->fifo_idx = i; + payload[i]->irq_status = irq_status[i]; + payload[i]->hw = cdm_hw; + + INIT_WORK((struct work_struct *)&payload[i]->work, cam_hw_cdm_work); - if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_CLEAR, - payload->irq_status)) - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ Clear"); - if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_CLEAR_CMD, 0x01)) - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd"); - work_status = queue_work(cdm_core->work_queue, &payload->work); + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_clear, + payload[i]->irq_status)) { + CAM_ERR(CAM_CDM, + "Failed to Write CDM HW IRQ Clear"); + kfree(payload[i]); + return IRQ_HANDLED; + } + + work_status = queue_work( + cdm_core->bl_fifo[i].work_queue, + &payload[i]->work); + if (work_status == false) { - CAM_ERR(CAM_CDM, "Failed to queue work for irq=0x%x", - payload->irq_status); - kfree(payload); + CAM_ERR(CAM_CDM, + "Failed to queue work for irq=0x%x", + payload[i]->irq_status); + kfree(payload[i]); } } + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[0]->irq_clear_cmd, + 0x01)) + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd 0"); + return IRQ_HANDLED; } @@ -699,27 +1189,32 @@ int cam_hw_cdm_alloc_genirq_mem(void *hw_priv) struct cam_mem_mgr_request_desc genirq_alloc_cmd; struct cam_mem_mgr_memory_desc genirq_alloc_out; struct cam_cdm *cdm_core = NULL; - int rc = -EINVAL; + int rc = -EINVAL, i; if (!hw_priv) return rc; cdm_core = (struct cam_cdm *)cdm_hw->core_info; genirq_alloc_cmd.align = 0; - genirq_alloc_cmd.size = (8 * CAM_CDM_HWFIFO_SIZE); genirq_alloc_cmd.smmu_hdl = cdm_core->iommu_hdl.non_secure; genirq_alloc_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE; - rc = cam_mem_mgr_request_mem(&genirq_alloc_cmd, - &genirq_alloc_out); - if (rc) { - CAM_ERR(CAM_CDM, "Failed to get genirq cmd space rc=%d", rc); - goto end; + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + genirq_alloc_cmd.size = (8 * + cdm_core->bl_fifo[i].bl_depth); + rc = cam_mem_mgr_request_mem(&genirq_alloc_cmd, + &genirq_alloc_out); + if (rc) { + CAM_ERR(CAM_CDM, + "Failed to get genirq cmd space rc=%d", + rc); + goto end; + } + cdm_core->gen_irq[i].handle = genirq_alloc_out.mem_handle; + cdm_core->gen_irq[i].vaddr = (genirq_alloc_out.iova & + 0xFFFFFFFF); + cdm_core->gen_irq[i].kmdvaddr = genirq_alloc_out.kva; + cdm_core->gen_irq[i].size = genirq_alloc_out.len; } - cdm_core->gen_irq.handle = genirq_alloc_out.mem_handle; - cdm_core->gen_irq.vaddr = (genirq_alloc_out.iova & 0xFFFFFFFF); - cdm_core->gen_irq.kmdvaddr = genirq_alloc_out.kva; - cdm_core->gen_irq.size = genirq_alloc_out.len; - end: return rc; } @@ -729,28 +1224,292 @@ int cam_hw_cdm_release_genirq_mem(void *hw_priv) struct cam_hw_info *cdm_hw = hw_priv; struct cam_cdm *cdm_core = NULL; struct cam_mem_mgr_memory_desc genirq_release_cmd; - int rc = -EINVAL; + int rc = -EINVAL, i; if (!hw_priv) return rc; cdm_core = (struct cam_cdm *)cdm_hw->core_info; - genirq_release_cmd.mem_handle = cdm_core->gen_irq.handle; - rc = cam_mem_mgr_release_mem(&genirq_release_cmd); - if (rc) - CAM_ERR(CAM_CDM, "Failed to put genirq cmd space for hw"); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + genirq_release_cmd.mem_handle = cdm_core->gen_irq[i].handle; + rc = cam_mem_mgr_release_mem(&genirq_release_cmd); + if (rc) + CAM_ERR(CAM_CDM, + "Failed to put genirq cmd space for hw rc %d", + rc); + } return rc; } +int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) +{ + struct cam_cdm *cdm_core = NULL; + long time_left; + int i, rc = -EIO; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + reinit_completion(&cdm_core->reset_complete); + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_mask, + 0x70003)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask"); + goto end; + } + } + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->rst_cmd, 0x9)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); + goto end; + } + + CAM_DBG(CAM_CDM, "Waiting for CDM HW reset done"); + time_left = wait_for_completion_timeout(&cdm_core->reset_complete, + msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); + + if (time_left <= 0) { + rc = -ETIMEDOUT; + CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + goto end; + } + + rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to configure CDM rc=%d", rc); + goto end; + } + + rc = cam_hw_cdm_set_cdm_blfifo_cfg(cdm_hw); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to configure CDM fifo rc=%d", rc); + goto end; + } + + cam_hw_cdm_reset_cleanup(cdm_hw, handle); +end: + clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); + + return rc; +} + +int cam_hw_cdm_handle_error_info( + struct cam_hw_info *cdm_hw, + uint32_t handle) +{ + struct cam_cdm *cdm_core = NULL; + struct cam_cdm_bl_cb_request_entry *node = NULL; + long time_left; + int i, rc = -EIO, reset_hw_hdl = 0x0; + uint32_t current_bl_data = 0, current_fifo = 0, current_tag = 0; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + set_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); + reinit_completion(&cdm_core->reset_complete); + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); + + rc = cam_cdm_read_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->current_bl_len, + ¤t_bl_data); + + current_fifo = ((CAM_CDM_CURRENT_BL_FIFO & current_bl_data) + >> CAM_CDM_CURRENT_BL_FIFO_SHIFT); + current_tag = ((CAM_CDM_CURRENT_BL_TAG & current_bl_data) + >> CAM_CDM_CURRENT_BL_TAG_SHIFT); + + if (current_fifo >= CAM_CDM_BL_FIFO_MAX) { + rc = -EFAULT; + goto end; + } + + CAM_ERR(CAM_CDM, "Hang detected for fifo %d with tag 0x%x", + current_fifo, current_tag); + + /* dump cdm registers for further debug */ + cam_hw_cdm_dump_core_debug_registers(cdm_hw); + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_mask, + 0x70003)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask"); + goto end; + } + } + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->rst_cmd, 0x9)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); + goto end; + } + + CAM_DBG(CAM_CDM, "Waiting for CDM HW resetdone"); + time_left = wait_for_completion_timeout(&cdm_core->reset_complete, + msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); + + if (time_left <= 0) { + rc = -ETIMEDOUT; + CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + goto end; + } + + rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); + + if (rc) { + CAM_ERR(CAM_CDM, "Failed to configure CDM rc=%d", rc); + goto end; + } + + rc = cam_hw_cdm_set_cdm_blfifo_cfg(cdm_hw); + + if (rc) { + CAM_ERR(CAM_CDM, "Failed to configure CDM fifo rc=%d", rc); + goto end; + } + + node = list_first_entry_or_null( + &cdm_core->bl_fifo[current_fifo].bl_request_list, + struct cam_cdm_bl_cb_request_entry, entry); + + if (node != NULL) { + if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) { + cam_cdm_notify_clients(cdm_hw, + CAM_CDM_CB_STATUS_HW_ERROR, + (void *)node); + } else if (node->request_type == CAM_HW_CDM_BL_CB_INTERNAL) { + CAM_ERR(CAM_CDM, "Invalid node=%pK %d", node, + node->request_type); + } + list_del_init(&node->entry); + kfree(node); + } + + cam_hw_cdm_reset_cleanup(cdm_hw, reset_hw_hdl); +end: + clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); + clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); + + return rc; +} + +int cam_hw_cdm_flush_hw(struct cam_hw_info *cdm_hw, uint32_t handle) +{ + struct cam_cdm *cdm_core = NULL; + int rc = 0; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + set_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); + rc = cam_hw_cdm_reset_hw(cdm_hw, handle); + clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); + + return rc; +} + +int cam_hw_cdm_handle_error( + struct cam_hw_info *cdm_hw, + uint32_t handle) +{ + struct cam_cdm *cdm_core = NULL; + int rc = 0; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + /* First pause CDM, If it fails still proceed to dump debug info */ + cam_hw_cdm_enable_core(cdm_hw, false); + + rc = cam_hw_cdm_handle_error_info(cdm_hw, handle); + + return rc; +} + +int cam_hw_cdm_get_cdm_config(struct cam_hw_info *cdm_hw) +{ + struct cam_hw_soc_info *soc_info = NULL; + struct cam_cdm *core = NULL; + int rc = 0; + + core = (struct cam_cdm *)cdm_hw->core_info; + soc_info = &cdm_hw->soc_info; + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_SVS_VOTE, true); + if (rc) { + CAM_ERR(CAM_CDM, "Enable platform failed for dev %s", + soc_info->dev_name); + goto end; + } else { + CAM_DBG(CAM_CDM, "CDM init success"); + cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; + } + + if (cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->cdm_hw_version, + &core->hw_version)) { + CAM_ERR(CAM_CDM, "Failed to read CDM HW Version"); + rc = -EIO; + goto disable_platform_resource; + } + + if (core->offsets->cmn_reg->cam_version) { + if (cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->cam_version->hw_version, + &core->hw_family_version)) { + CAM_ERR(CAM_CDM, "Failed to read CDM family Version"); + rc = -EIO; + goto disable_platform_resource; + } + } + + CAM_DBG(CAM_CDM, + "CDM Hw version read success family =%x hw =%x", + core->hw_family_version, core->hw_version); + + core->ops = cam_cdm_get_ops(core->hw_version, NULL, + false); + + if (!core->ops) { + CAM_ERR(CAM_CDM, "Failed to util ops for cdm hw name %s", + core->name); + rc = -EINVAL; + goto disable_platform_resource; + } + +disable_platform_resource: + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + + if (rc) { + CAM_ERR(CAM_CDM, "disable platform failed for dev %s", + soc_info->dev_name); + } else { + CAM_DBG(CAM_CDM, "CDM Deinit success"); + cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + } +end: + return rc; +} + int cam_hw_cdm_init(void *hw_priv, void *init_hw_args, uint32_t arg_size) { struct cam_hw_info *cdm_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_cdm *cdm_core = NULL; - int rc; - long time_left; + int rc, i, reset_hw_hdl = 0x0; if (!hw_priv) return -EINVAL; @@ -768,31 +1527,25 @@ int cam_hw_cdm_init(void *hw_priv, CAM_DBG(CAM_CDM, "Enable soc done"); /* Before triggering the reset to HW, clear the reset complete */ - atomic_set(&cdm_core->error, 0); - atomic_set(&cdm_core->bl_done, 0); - reinit_completion(&cdm_core->reset_complete); - reinit_completion(&cdm_core->bl_complete); + clear_bit(CAM_CDM_ERROR_HW_STATUS, &cdm_core->cdm_status); - if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask"); - goto disable_return; - } - if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_RST_CMD, 0x9)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); - goto disable_return; + for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { + clear_bit(i, &cdm_core->cdm_status); + reinit_completion(&cdm_core->bl_fifo[i].bl_complete); } - CAM_DBG(CAM_CDM, "Waiting for CDM HW resetdone"); - time_left = wait_for_completion_timeout(&cdm_core->reset_complete, - msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); + rc = cam_hw_cdm_reset_hw(cdm_hw, reset_hw_hdl); - if (time_left <= 0) { + if (rc) { CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); goto disable_return; } else { CAM_DBG(CAM_CDM, "CDM Init success"); cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; - cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_mask, + 0x70003); rc = 0; goto end; } @@ -830,7 +1583,7 @@ int cam_hw_cdm_deinit(void *hw_priv, int cam_hw_cdm_probe(struct platform_device *pdev) { - int rc; + int rc, len = 0, i, j; struct cam_hw_info *cdm_hw = NULL; struct cam_hw_intf *cdm_hw_intf = NULL; struct cam_cdm *cdm_core = NULL; @@ -838,6 +1591,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) struct cam_cpas_register_params cpas_parms; struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote = {0}; + char cdm_name[128], work_q_name[128]; cdm_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!cdm_hw_intf) @@ -880,16 +1634,17 @@ int cam_hw_cdm_probe(struct platform_device *pdev) else cdm_core->flags = CAM_CDM_FLAG_PRIVATE_CDM; - cdm_core->bl_tag = 0; cdm_core->id = cam_hw_cdm_get_id_by_name(cdm_core->name); + + CAM_DBG(CAM_CDM, "cdm_name %s", cdm_core->name); + if (cdm_core->id >= CAM_CDM_MAX) { CAM_ERR(CAM_CDM, "Failed to get CDM HW name for %s", cdm_core->name); goto release_private_mem; } - INIT_LIST_HEAD(&cdm_core->bl_request_list); + init_completion(&cdm_core->reset_complete); - init_completion(&cdm_core->bl_complete); cdm_hw_intf->hw_priv = cdm_hw; cdm_hw_intf->hw_ops.get_hw_caps = cam_cdm_get_caps; cdm_hw_intf->hw_ops.init = cam_hw_cdm_init; @@ -906,19 +1661,47 @@ int cam_hw_cdm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cdm_hw_intf); - rc = cam_smmu_get_handle("cpas-cdm0", &cdm_core->iommu_hdl.non_secure); + snprintf(cdm_name, sizeof(cdm_name), "%s%d", + cdm_hw->soc_info.label_name, cdm_hw->soc_info.index); + + rc = cam_smmu_get_handle(cdm_name, &cdm_core->iommu_hdl.non_secure); if (rc < 0) { - CAM_ERR(CAM_CDM, "cpas-cdm get iommu handle failed"); - goto unlock_release_mem; + if (rc != -EALREADY) { + CAM_ERR(CAM_CDM, + "%s get iommu handle failed, rc = %d", + cdm_name, rc); + goto unlock_release_mem; + } + rc = 0; } + cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_hw_cdm_iommu_fault_handler, cdm_hw); cdm_core->iommu_hdl.secure = -1; - cdm_core->work_queue = alloc_workqueue(cdm_core->name, - WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, - CAM_CDM_INFLIGHT_WORKS); + for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { + INIT_LIST_HEAD(&cdm_core->bl_fifo[i].bl_request_list); + + mutex_init(&cdm_core->bl_fifo[i].fifo_lock); + + init_completion(&cdm_core->bl_fifo[i].bl_complete); + + len = strlcpy(work_q_name, cdm_core->name, + sizeof(cdm_core->name)); + snprintf(work_q_name + len, sizeof(work_q_name) - len, "%d", i); + cdm_core->bl_fifo[i].work_queue = alloc_workqueue(work_q_name, + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, + CAM_CDM_INFLIGHT_WORKS); + if (!cdm_core->bl_fifo[i].work_queue) { + CAM_ERR(CAM_CDM, + "Workqueue allocation failed for FIFO %d, cdm %s", + i, cdm_core->name); + goto failed_workq_create; + } + + CAM_DBG(CAM_CDM, "wq %s", work_q_name); + } rc = cam_soc_util_request_platform_resource(&cdm_hw->soc_info, cam_hw_cdm_irq, cdm_hw); @@ -926,12 +1709,12 @@ int cam_hw_cdm_probe(struct platform_device *pdev) CAM_ERR(CAM_CDM, "Failed to request platform resource"); goto destroy_non_secure_hdl; } - cpas_parms.cam_cpas_client_cb = cam_cdm_cpas_cb; cpas_parms.cell_index = cdm_hw->soc_info.index; cpas_parms.dev = &pdev->dev; cpas_parms.userdata = cdm_hw_intf; - strlcpy(cpas_parms.identifier, "cpas-cdm", CAM_HW_IDENTIFIER_LENGTH); + strlcpy(cpas_parms.identifier, cdm_hw->soc_info.label_name, + CAM_HW_IDENTIFIER_LENGTH); rc = cam_cpas_register_client(&cpas_parms); if (rc) { CAM_ERR(CAM_CDM, "Virtual CDM CPAS registration failed"); @@ -956,6 +1739,33 @@ int cam_hw_cdm_probe(struct platform_device *pdev) goto cpas_unregister; } + rc = cam_hw_cdm_get_cdm_config(cdm_hw); + if (rc) { + CAM_ERR(CAM_CDM, "Failed to get cdm configuration rc = %d", rc); + goto cpas_stop; + } + + if (cdm_core->hw_version < CAM_CDM_VERSION_2_0) { + for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { + cdm_core->bl_fifo[i].bl_depth = + CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT; + CAM_DBG(CAM_CDM, "Setting FIFO%d length to %d", + i, cdm_core->bl_fifo[i].bl_depth); + } + } else { + for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { + cdm_core->bl_fifo[i].bl_depth = + soc_private->fifo_depth[i]; + CAM_DBG(CAM_CDM, "Setting FIFO%d length to %d", + i, cdm_core->bl_fifo[i].bl_depth); + } + } + + cdm_core->arbitration = cam_cdm_get_arbitration_type( + cdm_core->hw_version, cdm_core->id); + + cdm_core->cdm_status = CAM_CDM_HW_INIT_STATUS; + rc = cam_hw_cdm_init(cdm_hw, NULL, 0); if (rc) { CAM_ERR(CAM_CDM, "Failed to Init CDM HW"); @@ -963,30 +1773,10 @@ int cam_hw_cdm_probe(struct platform_device *pdev) } cdm_hw->open_count++; - if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_HW_VERSION, - &cdm_core->hw_version)) { - CAM_ERR(CAM_CDM, "Failed to read CDM HW Version"); - goto deinit; - } - - if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_TITAN_VERSION, - &cdm_core->hw_family_version)) { - CAM_ERR(CAM_CDM, "Failed to read CDM family Version"); - goto deinit; - } - - CAM_DBG(CAM_CDM, "CDM Hw version read success family =%x hw =%x", - cdm_core->hw_family_version, cdm_core->hw_version); - cdm_core->ops = cam_cdm_get_ops(cdm_core->hw_version, NULL, - false); - if (!cdm_core->ops) { - CAM_ERR(CAM_CDM, "Failed to util ops for hw"); - goto deinit; - } - if (!cam_cdm_set_cam_hw_version(cdm_core->hw_version, &cdm_core->version)) { - CAM_ERR(CAM_CDM, "Failed to set cam he version for hw"); + CAM_ERR(CAM_CDM, "Failed to set cam hw version for hw"); + rc = -EINVAL; goto deinit; } @@ -1014,7 +1804,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) cdm_hw->open_count--; mutex_unlock(&cdm_hw->hw_mutex); - CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx); + CAM_DBG(CAM_CDM, "%s probe successful", cdm_core->name); return rc; @@ -1031,9 +1821,11 @@ cpas_unregister: release_platform_resource: if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info)) CAM_ERR(CAM_CDM, "Release platform resource failed"); - - flush_workqueue(cdm_core->work_queue); - destroy_workqueue(cdm_core->work_queue); +failed_workq_create: + for (j = 0; j < i; j++) { + flush_workqueue(cdm_core->bl_fifo[j].work_queue); + destroy_workqueue(cdm_core->bl_fifo[j].work_queue); + } destroy_non_secure_hdl: cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, NULL, cdm_hw); @@ -1053,7 +1845,7 @@ release_mem: int cam_hw_cdm_remove(struct platform_device *pdev) { - int rc = -EBUSY; + int rc = -EBUSY, i; struct cam_hw_info *cdm_hw = NULL; struct cam_hw_intf *cdm_hw_intf = NULL; struct cam_cdm *cdm_core = NULL; @@ -1102,8 +1894,10 @@ int cam_hw_cdm_remove(struct platform_device *pdev) if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info)) CAM_ERR(CAM_CDM, "Release platform resource failed"); - flush_workqueue(cdm_core->work_queue); - destroy_workqueue(cdm_core->work_queue); + for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { + flush_workqueue(cdm_core->bl_fifo[i].work_queue); + destroy_workqueue(cdm_core->bl_fifo[i].work_queue); + } if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h b/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h new file mode 100644 index 000000000000..f1564dfafcbd --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "cam_cdm.h" + +static struct cam_version_reg cdm_hw_1_0_titan_version = { + .hw_version = 0x4, +}; + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_1_0_bl_pending_req0 = { + .rb_offset = 0x6c, + .rb_mask = 0x7F, + .rb_num_fifo = 0x1, + .rb_next_fifo_shift = 0x0, +}; + +static struct cam_cdm_irq_regs cdm_hw_1_0_irq0 = { + .irq_mask = 0x30, + .irq_clear = 0x34, + .irq_clear_cmd = 0x38, + .irq_set = 0x3c, + .irq_set_cmd = 0x40, + .irq_status = 0x44, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_1_0_bl_fifo0 = { + .bl_fifo_base = 0x50, + .bl_fifo_len = 0x54, + .bl_fifo_store = 0x58, + .bl_fifo_cfg = 0x5c, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg0 = { + .scratch_reg = 0x90, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg1 = { + .scratch_reg = 0x94, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg2 = { + .scratch_reg = 0x98, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg3 = { + .scratch_reg = 0x9c, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg4 = { + .scratch_reg = 0xa0, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg5 = { + .scratch_reg = 0xa4, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg6 = { + .scratch_reg = 0xa8, +}; + +static struct cam_cdm_scratch_reg cdm_1_0_scratch_reg7 = { + .scratch_reg = 0xac, +}; + +static struct cam_cdm_perf_mon_regs cdm_1_0_perf_mon0 = { + .perf_mon_ctrl = 0x110, + .perf_mon_0 = 0x114, + .perf_mon_1 = 0x118, + .perf_mon_2 = 0x11c, +}; + +static struct cam_cdm_common_regs cdm_hw_1_0_cmn_reg_offset = { + .cdm_hw_version = 0x0, + .cam_version = &cdm_hw_1_0_titan_version, + .rst_cmd = 0x10, + .cgc_cfg = 0x14, + .core_cfg = 0x18, + .core_en = 0x1c, + .fe_cfg = 0x20, + .bl_fifo_rb = 0x60, + .bl_fifo_base_rb = 0x64, + .bl_fifo_len_rb = 0x68, + .usr_data = 0x80, + .wait_status = 0x84, + .last_ahb_addr = 0xd0, + .last_ahb_data = 0xd4, + .core_debug = 0xd8, + .last_ahb_err_addr = 0xe0, + .last_ahb_err_data = 0xe4, + .current_bl_base = 0xe8, + .current_bl_len = 0xec, + .current_used_ahb_base = 0xf0, + .debug_status = 0xf4, + .bus_misr_cfg0 = 0x100, + .bus_misr_cfg1 = 0x104, + .bus_misr_rd_val = 0x108, + .pending_req = { + &cdm_hw_1_0_bl_pending_req0, + NULL, + }, + .comp_wait = { NULL, NULL }, + .perf_mon = { + &cdm_1_0_perf_mon0, + NULL, + }, + .scratch = { + &cdm_1_0_scratch_reg0, + &cdm_1_0_scratch_reg1, + &cdm_1_0_scratch_reg2, + &cdm_1_0_scratch_reg3, + &cdm_1_0_scratch_reg4, + &cdm_1_0_scratch_reg5, + &cdm_1_0_scratch_reg6, + &cdm_1_0_scratch_reg7, + NULL, + NULL, + NULL, + NULL, + }, + .perf_reg = NULL, + .icl_reg = NULL, + .spare = 0x200, +}; + +static struct cam_cdm_common_reg_data cdm_hw_1_0_cmn_reg_data = { + .num_bl_fifo = 0x1, + .num_bl_fifo_irq = 0x1, + .num_bl_pending_req_reg = 0x1, + .num_scratch_reg = 0x8, +}; + +static struct cam_cdm_hw_reg_offset cam_cdm_1_0_reg_offset = { + .cmn_reg = &cdm_hw_1_0_cmn_reg_offset, + .bl_fifo_reg = { + &cdm_hw_1_0_bl_fifo0, + NULL, + NULL, + NULL, + }, + .irq_reg = { + &cdm_hw_1_0_irq0, + NULL, + NULL, + NULL, + }, + .reg_data = &cdm_hw_1_0_cmn_reg_data, +}; diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_1_1.h b/drivers/cam_cdm/cam_cdm_hw_reg_1_1.h new file mode 100644 index 000000000000..d5a0b1063375 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_hw_reg_1_1.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "cam_cdm.h" + +static struct cam_version_reg cdm_hw_1_1_titan_version = { + .hw_version = 0x4, +}; + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_1_1_bl_pending_req0 = { + .rb_offset = 0x6c, + .rb_mask = 0x7f, + .rb_num_fifo = 0x1, + .rb_next_fifo_shift = 0x0, +}; + +static struct cam_cdm_irq_regs cdm_hw_1_1_irq0 = { + .irq_mask = 0x30, + .irq_clear = 0x34, + .irq_clear_cmd = 0x38, + .irq_set = 0x3c, + .irq_set_cmd = 0x40, + .irq_status = 0x44, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_1_1_bl_fifo0 = { + .bl_fifo_base = 0x50, + .bl_fifo_len = 0x54, + .bl_fifo_store = 0x58, + .bl_fifo_cfg = 0x5c, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg0 = { + .scratch_reg = 0x90, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg1 = { + .scratch_reg = 0x94, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg2 = { + .scratch_reg = 0x98, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg3 = { + .scratch_reg = 0x9c, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg4 = { + .scratch_reg = 0xa0, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg5 = { + .scratch_reg = 0xa4, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg6 = { + .scratch_reg = 0xa8, +}; + +static struct cam_cdm_scratch_reg cdm_1_1_scratch_reg7 = { + .scratch_reg = 0xac, +}; + +static struct cam_cdm_perf_mon_regs cdm_1_1_perf_mon0 = { + .perf_mon_ctrl = 0x110, + .perf_mon_0 = 0x114, + .perf_mon_1 = 0x118, + .perf_mon_2 = 0x11c, +}; + +static struct cam_cdm_comp_wait_status cdm_1_1_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_1_1_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + +static struct cam_cdm_common_regs cdm_hw_1_1_cmn_reg_offset = { + .cdm_hw_version = 0x0, + .cam_version = &cdm_hw_1_1_titan_version, + .rst_cmd = 0x10, + .cgc_cfg = 0x14, + .core_cfg = 0x18, + .core_en = 0x1c, + .fe_cfg = 0x20, + .bl_fifo_rb = 0x60, + .bl_fifo_base_rb = 0x64, + .bl_fifo_len_rb = 0x68, + .usr_data = 0x80, + .wait_status = 0x84, + .last_ahb_addr = 0xd0, + .last_ahb_data = 0xd4, + .core_debug = 0xd8, + .last_ahb_err_addr = 0xe0, + .last_ahb_err_data = 0xe4, + .current_bl_base = 0xe8, + .current_bl_len = 0xec, + .current_used_ahb_base = 0xf0, + .debug_status = 0xf4, + .bus_misr_cfg0 = 0x100, + .bus_misr_cfg1 = 0x104, + .bus_misr_rd_val = 0x108, + .pending_req = { + &cdm_hw_1_1_bl_pending_req0, + NULL, + }, + .comp_wait = { + &cdm_1_1_comp_wait_status0, + &cdm_1_1_comp_wait_status1, + }, + .perf_mon = { + &cdm_1_1_perf_mon0, + NULL, + }, + .scratch = { + &cdm_1_1_scratch_reg0, + &cdm_1_1_scratch_reg1, + &cdm_1_1_scratch_reg2, + &cdm_1_1_scratch_reg3, + &cdm_1_1_scratch_reg4, + &cdm_1_1_scratch_reg5, + &cdm_1_1_scratch_reg6, + &cdm_1_1_scratch_reg7, + NULL, + NULL, + NULL, + NULL, + }, + .perf_reg = NULL, + .icl_reg = NULL, + .spare = 0x1fc, +}; + +static struct cam_cdm_common_reg_data cdm_hw_1_1_cmn_reg_data = { + .num_bl_fifo = 0x1, + .num_bl_fifo_irq = 0x1, + .num_bl_pending_req_reg = 0x1, + .num_scratch_reg = 0x8, +}; + +struct cam_cdm_hw_reg_offset cam_cdm_1_1_reg_offset = { + .cmn_reg = &cdm_hw_1_1_cmn_reg_offset, + .bl_fifo_reg = { + &cdm_hw_1_1_bl_fifo0, + NULL, + NULL, + NULL, + }, + .irq_reg = { + &cdm_hw_1_1_irq0, + NULL, + NULL, + NULL, + }, + .reg_data = &cdm_hw_1_1_cmn_reg_data, +}; diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_1_2.h b/drivers/cam_cdm/cam_cdm_hw_reg_1_2.h new file mode 100644 index 000000000000..08949b7dae76 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_hw_reg_1_2.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "cam_cdm.h" + +static struct cam_version_reg cdm_hw_1_2_titan_version = { + .hw_version = 0x4, +}; + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_1_2_bl_pending_req0 = { + .rb_offset = 0x6c, + .rb_mask = 0x7f, + .rb_num_fifo = 0x1, + .rb_next_fifo_shift = 0x0, +}; + +static struct cam_cdm_irq_regs cdm_hw_1_2_irq0 = { + .irq_mask = 0x30, + .irq_clear = 0x34, + .irq_clear_cmd = 0x38, + .irq_set = 0x3c, + .irq_set_cmd = 0x40, + .irq_status = 0x44, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_1_2_bl_fifo0 = { + .bl_fifo_base = 0x50, + .bl_fifo_len = 0x54, + .bl_fifo_store = 0x58, + .bl_fifo_cfg = 0x5c, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg0 = { + .scratch_reg = 0x90, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg1 = { + .scratch_reg = 0x94, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg2 = { + .scratch_reg = 0x98, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg3 = { + .scratch_reg = 0x9c, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg4 = { + .scratch_reg = 0xa0, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg5 = { + .scratch_reg = 0xa4, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg6 = { + .scratch_reg = 0xa8, +}; + +static struct cam_cdm_scratch_reg cdm_1_2_scratch_reg7 = { + .scratch_reg = 0xac, +}; + +static struct cam_cdm_perf_mon_regs cdm_1_2_perf_mon0 = { + .perf_mon_ctrl = 0x110, + .perf_mon_0 = 0x114, + .perf_mon_1 = 0x118, + .perf_mon_2 = 0x11c, +}; + +static struct cam_cdm_comp_wait_status cdm_1_2_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_1_2_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + +static struct cam_cdm_perf_regs cdm_1_2_perf = { + .count_cfg_0 = 0x180, + .always_count_val = 0x184, + .busy_count_val = 0x188, + .stall_axi_count_val = 0x18c, + .count_status = 0x190, +}; + +static struct cam_cdm_icl_data_regs cdm_1_2_icl_data = { + .icl_last_data_0 = 0x1c0, + .icl_last_data_1 = 0x1c4, + .icl_last_data_2 = 0x1c8, + .icl_inv_data = 0x1cc, +}; + +static struct cam_cdm_icl_regs cdm_1_2_icl = { + .data_regs = &cdm_1_2_icl_data, + .misc_regs = NULL, +}; + +static struct cam_cdm_common_regs cdm_hw_1_2_cmn_reg_offset = { + .cdm_hw_version = 0x0, + .cam_version = &cdm_hw_1_2_titan_version, + .rst_cmd = 0x10, + .cgc_cfg = 0x14, + .core_cfg = 0x18, + .core_en = 0x1c, + .fe_cfg = 0x20, + .bl_fifo_rb = 0x60, + .bl_fifo_base_rb = 0x64, + .bl_fifo_len_rb = 0x68, + .usr_data = 0x80, + .wait_status = 0x84, + .last_ahb_addr = 0xd0, + .last_ahb_data = 0xd4, + .core_debug = 0xd8, + .last_ahb_err_addr = 0xe0, + .last_ahb_err_data = 0xe4, + .current_bl_base = 0xe8, + .current_bl_len = 0xec, + .current_used_ahb_base = 0xf0, + .debug_status = 0xf4, + .bus_misr_cfg0 = 0x100, + .bus_misr_cfg1 = 0x104, + .bus_misr_rd_val = 0x108, + .pending_req = { + &cdm_hw_1_2_bl_pending_req0, + NULL, + }, + .comp_wait = { + &cdm_1_2_comp_wait_status0, + &cdm_1_2_comp_wait_status1, + }, + .perf_mon = { + &cdm_1_2_perf_mon0, + NULL, + }, + .scratch = { + &cdm_1_2_scratch_reg0, + &cdm_1_2_scratch_reg1, + &cdm_1_2_scratch_reg2, + &cdm_1_2_scratch_reg3, + &cdm_1_2_scratch_reg4, + &cdm_1_2_scratch_reg5, + &cdm_1_2_scratch_reg6, + &cdm_1_2_scratch_reg7, + NULL, + NULL, + NULL, + NULL, + }, + .perf_reg = &cdm_1_2_perf, + .icl_reg = &cdm_1_2_icl, + .spare = 0x1fc, +}; + +static struct cam_cdm_common_reg_data cdm_hw_1_2_cmn_reg_data = { + .num_bl_fifo = 0x1, + .num_bl_fifo_irq = 0x1, + .num_bl_pending_req_reg = 0x1, + .num_scratch_reg = 0x8, +}; + +struct cam_cdm_hw_reg_offset cam_cdm_1_2_reg_offset = { + .cmn_reg = &cdm_hw_1_2_cmn_reg_offset, + .bl_fifo_reg = { + &cdm_hw_1_2_bl_fifo0, + NULL, + NULL, + NULL, + }, + .irq_reg = { + &cdm_hw_1_2_irq0, + NULL, + NULL, + NULL, + }, + .reg_data = &cdm_hw_1_2_cmn_reg_data, +}; diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_2_0.h b/drivers/cam_cdm/cam_cdm_hw_reg_2_0.h new file mode 100644 index 000000000000..1e224c6d9c0a --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_hw_reg_2_0.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "cam_cdm.h" + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_0_bl_pending_req0 = { + .rb_offset = 0x6c, + .rb_mask = 0x1ff, + .rb_num_fifo = 0x2, + .rb_next_fifo_shift = 0x10, +}; + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_0_bl_pending_req1 = { + .rb_offset = 0x70, + .rb_mask = 0x1ff, + .rb_num_fifo = 0x2, + .rb_next_fifo_shift = 0x10, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_0_irq0 = { + .irq_mask = 0x30, + .irq_clear = 0x34, + .irq_clear_cmd = 0x38, + .irq_set = 0x3c, + .irq_set_cmd = 0x40, + .irq_status = 0x44, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_0_irq1 = { + .irq_mask = 0x130, + .irq_clear = 0x134, + .irq_clear_cmd = 0x138, + .irq_set = 0x13c, + .irq_set_cmd = 0x140, + .irq_status = 0x144, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_0_irq2 = { + .irq_mask = 0x230, + .irq_clear = 0x234, + .irq_clear_cmd = 0x238, + .irq_set = 0x23c, + .irq_set_cmd = 0x240, + .irq_status = 0x244, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_0_irq3 = { + .irq_mask = 0x330, + .irq_clear = 0x334, + .irq_clear_cmd = 0x338, + .irq_set = 0x33c, + .irq_set_cmd = 0x340, + .irq_status = 0x344, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_0_bl_fifo0 = { + .bl_fifo_base = 0x50, + .bl_fifo_len = 0x54, + .bl_fifo_store = 0x58, + .bl_fifo_cfg = 0x5c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_0_bl_fifo1 = { + .bl_fifo_base = 0x150, + .bl_fifo_len = 0x154, + .bl_fifo_store = 0x158, + .bl_fifo_cfg = 0x15c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_0_bl_fifo2 = { + .bl_fifo_base = 0x250, + .bl_fifo_len = 0x254, + .bl_fifo_store = 0x258, + .bl_fifo_cfg = 0x25c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_0_bl_fifo3 = { + .bl_fifo_base = 0x350, + .bl_fifo_len = 0x354, + .bl_fifo_store = 0x358, + .bl_fifo_cfg = 0x35c, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg0 = { + .scratch_reg = 0x90, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg1 = { + .scratch_reg = 0x94, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg2 = { + .scratch_reg = 0x98, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg3 = { + .scratch_reg = 0x9c, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg4 = { + .scratch_reg = 0xa0, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg5 = { + .scratch_reg = 0xa4, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg6 = { + .scratch_reg = 0xa8, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg7 = { + .scratch_reg = 0xac, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg8 = { + .scratch_reg = 0xb0, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg9 = { + .scratch_reg = 0xb4, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg10 = { + .scratch_reg = 0xb8, +}; + +static struct cam_cdm_scratch_reg cdm_2_0_scratch_reg11 = { + .scratch_reg = 0xbc, +}; + +static struct cam_cdm_perf_mon_regs cdm_2_0_perf_mon0 = { + .perf_mon_ctrl = 0x110, + .perf_mon_0 = 0x114, + .perf_mon_1 = 0x118, + .perf_mon_2 = 0x11c, +}; + +static struct cam_cdm_perf_mon_regs cdm_2_0_perf_mon1 = { + .perf_mon_ctrl = 0x120, + .perf_mon_0 = 0x124, + .perf_mon_1 = 0x128, + .perf_mon_2 = 0x12c, +}; + +static struct cam_cdm_comp_wait_status cdm_2_0_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_2_0_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + +static struct cam_cdm_icl_data_regs cdm_2_0_icl_data = { + .icl_last_data_0 = 0x1c0, + .icl_last_data_1 = 0x1c4, + .icl_last_data_2 = 0x1c8, + .icl_inv_data = 0x1cc, +}; + +static struct cam_cdm_icl_misc_regs cdm_2_0_icl_misc = { + .icl_inv_bl_addr = 0x1d0, + .icl_status = 0x1d4, +}; + +static struct cam_cdm_icl_regs cdm_2_0_icl = { + .data_regs = &cdm_2_0_icl_data, + .misc_regs = &cdm_2_0_icl_misc, +}; + +static struct cam_cdm_common_regs cdm_hw_2_0_cmn_reg_offset = { + .cdm_hw_version = 0x0, + .cam_version = NULL, + .rst_cmd = 0x10, + .cgc_cfg = 0x14, + .core_cfg = 0x18, + .core_en = 0x1c, + .fe_cfg = 0x20, + .bl_fifo_rb = 0x60, + .bl_fifo_base_rb = 0x64, + .bl_fifo_len_rb = 0x68, + .usr_data = 0x80, + .wait_status = 0x84, + .last_ahb_addr = 0xd0, + .last_ahb_data = 0xd4, + .core_debug = 0xd8, + .last_ahb_err_addr = 0xe0, + .last_ahb_err_data = 0xe4, + .current_bl_base = 0xe8, + .current_bl_len = 0xec, + .current_used_ahb_base = 0xf0, + .debug_status = 0xf4, + .bus_misr_cfg0 = 0x100, + .bus_misr_cfg1 = 0x104, + .bus_misr_rd_val = 0x108, + .pending_req = { + &cdm_hw_2_0_bl_pending_req0, + &cdm_hw_2_0_bl_pending_req1, + }, + .comp_wait = { + &cdm_2_0_comp_wait_status0, + &cdm_2_0_comp_wait_status1, + }, + .perf_mon = { + &cdm_2_0_perf_mon0, + &cdm_2_0_perf_mon1, + }, + .scratch = { + &cdm_2_0_scratch_reg0, + &cdm_2_0_scratch_reg1, + &cdm_2_0_scratch_reg2, + &cdm_2_0_scratch_reg3, + &cdm_2_0_scratch_reg4, + &cdm_2_0_scratch_reg5, + &cdm_2_0_scratch_reg6, + &cdm_2_0_scratch_reg7, + &cdm_2_0_scratch_reg8, + &cdm_2_0_scratch_reg9, + &cdm_2_0_scratch_reg10, + &cdm_2_0_scratch_reg11, + }, + .perf_reg = NULL, + .icl_reg = &cdm_2_0_icl, + .spare = 0x1fc, +}; + +static struct cam_cdm_common_reg_data cdm_hw_2_0_cmn_reg_data = { + .num_bl_fifo = 0x4, + .num_bl_fifo_irq = 0x4, + .num_bl_pending_req_reg = 0x2, + .num_scratch_reg = 0xc, +}; + +struct cam_cdm_hw_reg_offset cam_cdm_2_0_reg_offset = { + .cmn_reg = &cdm_hw_2_0_cmn_reg_offset, + .bl_fifo_reg = { + &cdm_hw_2_0_bl_fifo0, + &cdm_hw_2_0_bl_fifo1, + &cdm_hw_2_0_bl_fifo2, + &cdm_hw_2_0_bl_fifo3, + }, + .irq_reg = { + &cdm_hw_2_0_irq0, + &cdm_hw_2_0_irq1, + &cdm_hw_2_0_irq2, + &cdm_hw_2_0_irq3, + }, + .reg_data = &cdm_hw_2_0_cmn_reg_data, +}; diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index 990ee39f000c..bbb97d21c123 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -15,6 +15,7 @@ #include "cam_cdm_virtual.h" #include "cam_soc_util.h" #include "cam_cdm_soc.h" +#include "cam_cdm_core_common.h" static struct cam_cdm_intf_mgr cdm_mgr; static DEFINE_MUTEX(cam_cdm_mgr_lock); @@ -77,13 +78,15 @@ static int get_cdm_index_by_id(char *identifier, uint32_t cell_index, uint32_t *hw_index) { int rc = -EPERM, i, j; - char client_name[128]; + char client_name[128], name_index[160]; - CAM_DBG(CAM_CDM, "Looking for HW id of =%s and index=%d", - identifier, cell_index); snprintf(client_name, sizeof(client_name), "%s", identifier); - CAM_DBG(CAM_CDM, "Looking for HW id of %s count:%d", client_name, - cdm_mgr.cdm_count); + snprintf(name_index, sizeof(name_index), "%s%d", + identifier, cell_index); + + CAM_DBG(CAM_CDM, + "Looking for HW id of =%s or %s and index=%d cdm_count %d", + identifier, name_index, cell_index, cdm_mgr.cdm_count); mutex_lock(&cam_cdm_mgr_lock); for (i = 0; i < cdm_mgr.cdm_count; i++) { mutex_lock(&cdm_mgr.nodes[i].lock); @@ -92,11 +95,14 @@ static int get_cdm_index_by_id(char *identifier, for (j = 0; j < cdm_mgr.nodes[i].data->dt_num_supported_clients; j++) { - CAM_DBG(CAM_CDM, "client name:%s", - cdm_mgr.nodes[i].data->dt_cdm_client_name[j]); + CAM_DBG(CAM_CDM, "client name:%s dev Index: %d", + cdm_mgr.nodes[i].data->dt_cdm_client_name[j], + i); if (!strcmp( cdm_mgr.nodes[i].data->dt_cdm_client_name[j], - client_name)) { + client_name) || !strcmp( + cdm_mgr.nodes[i].data->dt_cdm_client_name[j], + name_index)) { rc = 0; *hw_index = i; break; @@ -131,9 +137,14 @@ int cam_cdm_get_iommu_handle(char *identifier, mutex_unlock(&cdm_mgr.nodes[i].lock); continue; } + CAM_DBG(CAM_CDM, "dt_num_supported_clients=%d", + cdm_mgr.nodes[i].data->dt_num_supported_clients); for (j = 0; j < cdm_mgr.nodes[i].data->dt_num_supported_clients; j++) { + CAM_DBG(CAM_CDM, "client name:%s dev Index: %d", + cdm_mgr.nodes[i].data->dt_cdm_client_name[j], + i); if (!strcmp( cdm_mgr.nodes[i].data->dt_cdm_client_name[j], identifier)) { @@ -155,6 +166,8 @@ int cam_cdm_acquire(struct cam_cdm_acquire_data *data) { int rc = -EPERM; struct cam_hw_intf *hw; + struct cam_hw_info *cdm_hw; + struct cam_cdm *core = NULL; uint32_t hw_index = 0; if ((!data) || (!data->base_array_cnt)) @@ -177,12 +190,17 @@ int cam_cdm_acquire(struct cam_cdm_acquire_data *data) CAM_ERR(CAM_CDM, "Failed to identify associated hw id"); goto end; } else { - CAM_DBG(CAM_CDM, "hw_index:%d", hw_index); hw = cdm_mgr.nodes[hw_index].device; if (hw && hw->hw_ops.process_cmd) { + cdm_hw = hw->hw_priv; + core = (struct cam_cdm *)cdm_hw->core_info; + data->id = core->id; + CAM_DBG(CAM_CDM, + "Device = %s, hw_index = %d, CDM id = %d", + data->identifier, hw_index, data->id); rc = hw->hw_ops.process_cmd(hw->hw_priv, - CAM_CDM_HW_INTF_CMD_ACQUIRE, data, - sizeof(struct cam_cdm_acquire_data)); + CAM_CDM_HW_INTF_CMD_ACQUIRE, data, + sizeof(struct cam_cdm_acquire_data)); if (rc < 0) { CAM_ERR(CAM_CDM, "CDM hw acquire failed"); goto end; @@ -203,6 +221,19 @@ end: } EXPORT_SYMBOL(cam_cdm_acquire); +struct cam_cdm_utils_ops *cam_cdm_publish_ops(void) +{ + struct cam_hw_version cdm_version; + + cdm_version.major = 1; + cdm_version.minor = 0; + cdm_version.incr = 0; + cdm_version.reserved = 0; + + return cam_cdm_get_ops(0, &cdm_version, true); +} +EXPORT_SYMBOL(cam_cdm_publish_ops); + int cam_cdm_release(uint32_t handle) { uint32_t hw_index; @@ -379,6 +410,75 @@ int cam_cdm_reset_hw(uint32_t handle) } EXPORT_SYMBOL(cam_cdm_reset_hw); +int cam_cdm_flush_hw(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) { + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_FLUSH_HW, &handle, + sizeof(handle)); + if (rc < 0) + CAM_ERR(CAM_CDM, + "CDM hw release failed for handle=%x", + handle); + } else { + CAM_ERR(CAM_CDM, "hw idx %d doesn't have release ops", + hw_index); + } + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_flush_hw); + +int cam_cdm_handle_error(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) { + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, + &handle, + sizeof(handle)); + if (rc < 0) + CAM_ERR(CAM_CDM, + "CDM hw release failed for handle=%x", + handle); + } else { + CAM_ERR(CAM_CDM, "hw idx %d doesn't have release ops", + hw_index); + } + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_handle_error); + int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, uint32_t *index) diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index 93404353714f..0c9508db41cf 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_API_H_ @@ -14,7 +14,10 @@ enum cam_cdm_id { CAM_CDM_VIRTUAL, CAM_CDM_HW_ANY, - CAM_CDM_CPAS_0, + CAM_CDM_CPAS, + CAM_CDM_IFE, + CAM_CDM_TFE, + CAM_CDM_OPE, CAM_CDM_IPE0, CAM_CDM_IPE1, CAM_CDM_BPS, @@ -29,6 +32,9 @@ enum cam_cdm_cb_status { CAM_CDM_CB_STATUS_PAGEFAULT, CAM_CDM_CB_STATUS_HW_RESET_ONGOING, CAM_CDM_CB_STATUS_HW_RESET_DONE, + CAM_CDM_CB_STATUS_HW_FLUSH, + CAM_CDM_CB_STATUS_HW_RESUBMIT, + CAM_CDM_CB_STATUS_HW_ERROR, CAM_CDM_CB_STATUS_UNKNOWN_ERROR, }; @@ -39,17 +45,26 @@ enum cam_cdm_bl_cmd_addr_type { CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA, }; +/* enum cam_cdm_bl_fifo - interface commands.*/ +enum cam_cdm_bl_fifo_queue { + CAM_CDM_BL_FIFO_0, + CAM_CDM_BL_FIFO_1, + CAM_CDM_BL_FIFO_2, + CAM_CDM_BL_FIFO_3, + CAM_CDM_BL_FIFO_MAX, +}; + /** * struct cam_cdm_acquire_data - Cam CDM acquire data structure * * @identifier : Input identifier string which is the device label from dt - * like vfe, ife, jpeg etc + * like vfe, ife, jpeg etc * @cell_index : Input integer identifier pointing to the cell index from dt * of the device. This can be used to form a unique string * with @identifier like vfe0, ife1, jpeg0 etc * @id : ID of a specific or any CDM HW which needs to be acquired. * @userdata : Input private data which will be returned as part - * of callback. + * of callback. * @cam_cdm_callback : Input callback pointer for triggering the * callbacks from CDM driver * @handle : CDM Client handle @@ -57,12 +72,14 @@ enum cam_cdm_bl_cmd_addr_type { * @status : Callback status * @cookie : Cookie if the callback is gen irq status * @base_array_cnt : Input number of ioremapped address pair pointing - * in base_array, needed only if selected cdm is a virtual. + * in base_array, needed only if selected cdm is a virtual. * @base_array : Input pointer to ioremapped address pair arrary - * needed only if selected cdm is a virtual. + * needed only if selected cdm is a virtual. + * @priority : Priority of the client. * @cdm_version : CDM version is output while acquiring HW cdm and - * it is Input while acquiring virtual cdm, Currently fixing it - * to one version below acquire API. + * it is Input while acquiring virtual cdm. + * Currently fixing it to one version below + * acquire API. * @ops : Output pointer updated by cdm driver to the CDM * util ops for this HW version of CDM acquired. * @handle : Output Unique handle generated for this acquire @@ -77,6 +94,7 @@ struct cam_cdm_acquire_data { enum cam_cdm_cb_status status, uint64_t cookie); uint32_t base_array_cnt; struct cam_soc_reg_map *base_array[CAM_SOC_MAX_BLOCK]; + enum cam_cdm_bl_fifo_queue priority; struct cam_hw_version cdm_version; struct cam_cdm_utils_ops *ops; uint32_t handle; @@ -92,7 +110,8 @@ struct cam_cdm_acquire_data { * @len : Input length of the BL command, Cannot be more than 1MB and * this is will be validated with offset+size of the memory pointed * by mem_handle - * + * @enable_debug_gen_irq : bool flag to submit extra gen_irq afteR bl_command + * @arbitrate : bool flag to arbitrate on submitted BL boundary */ struct cam_cdm_bl_cmd { union { @@ -102,6 +121,8 @@ struct cam_cdm_bl_cmd { } bl_addr; uint32_t offset; uint32_t len; + bool enable_debug_gen_irq; + bool arbitrate; }; /** @@ -114,6 +135,7 @@ struct cam_cdm_bl_cmd { * @cookie : Cookie if the callback is gen irq status * @type : type of the submitted bl cmd address. * @cmd_arrary_count : Input number of BL commands to be submitted to CDM + * @gen_irq_arb : enum for setting arbitration in gen_irq * @bl_cmd_array : Input payload holding the BL cmd's arrary * to be sumbitted. * @@ -124,6 +146,7 @@ struct cam_cdm_bl_request { uint64_t cookie; enum cam_cdm_bl_cmd_addr_type type; uint32_t cmd_arrary_count; + bool gen_irq_arb; struct cam_cdm_bl_cmd cmd[1]; }; @@ -191,7 +214,7 @@ int cam_cdm_stream_off(uint32_t handle); /** * @brief : API to reset previously acquired CDM, - * this can be only performed only the CDM is private. + * this should be only performed only if the CDM is private. * * @handle : Input handle of the CDM to reset * @@ -220,4 +243,33 @@ void cam_cdm_intf_exit_module(void); * @brief : API to remove CDM hw from platform framework. */ void cam_hw_cdm_exit_module(void); + +/** + * @brief : API to flush previously acquired CDM, + * this should be only performed only if the CDM is private. + * + * @handle : Input handle of the CDM to reset + * + * @return 0 on success + */ +int cam_cdm_flush_hw(uint32_t handle); + +/** + * @brief : API to detect culprit bl_tag in previously acquired CDM, + * this should be only performed only if the CDM is private. + * + * @handle : Input handle of the CDM to reset + * + * @return 0 on success + */ +int cam_cdm_handle_error(uint32_t handle); + +/** + * @brief : API get CDM ops + * + * @return : CDM operations + * + */ +struct cam_cdm_utils_ops *cam_cdm_publish_ops(void); + #endif /* _CAM_CDM_API_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_soc.c b/drivers/cam_cdm/cam_cdm_soc.c index 2fb5d5fe97b9..3d81270c1187 100644 --- a/drivers/cam_cdm/cam_cdm_soc.c +++ b/drivers/cam_cdm/cam_cdm_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -15,45 +15,35 @@ #include "cam_cdm.h" #include "cam_soc_util.h" #include "cam_io_util.h" +#include "cam_cdm_soc.h" #define CAM_CDM_OFFSET_FROM_REG(x, y) ((x)->offsets[y].offset) #define CAM_CDM_ATTR_FROM_REG(x, y) ((x)->offsets[y].attribute) bool cam_cdm_read_hw_reg(struct cam_hw_info *cdm_hw, - enum cam_cdm_regs reg, uint32_t *value) + uint32_t reg, uint32_t *value) { void __iomem *reg_addr; - struct cam_cdm *cdm = (struct cam_cdm *)cdm_hw->core_info; void __iomem *base = cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].mem_base; resource_size_t mem_len = cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size; - CAM_DBG(CAM_CDM, "E: b=%pK blen=%d reg=%x off=%x", (void __iomem *)base, - (int)mem_len, reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, - reg))); - CAM_DBG(CAM_CDM, "E: b=%pK reg=%x off=%x", (void __iomem *)base, - reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg))); + CAM_DBG(CAM_CDM, "E: b=%pK blen=%d off=%x", (void __iomem *)base, + (int)mem_len, reg); - if ((reg > cdm->offset_tbl->offset_max_size) || - (reg > cdm->offset_tbl->last_offset)) { - CAM_ERR_RATE_LIMIT(CAM_CDM, "Invalid reg=%d\n", reg); + reg_addr = (base + reg); + if (reg_addr > (base + mem_len)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, + "Invalid mapped region %d", reg); goto permission_error; - } else { - reg_addr = (base + (CAM_CDM_OFFSET_FROM_REG( - cdm->offset_tbl, reg))); - if (reg_addr > (base + mem_len)) { - CAM_ERR_RATE_LIMIT(CAM_CDM, - "Invalid mapped region %d", reg); - goto permission_error; - } - *value = cam_io_r_mb(reg_addr); - CAM_DBG(CAM_CDM, "X b=%pK reg=%x off=%x val=%x", - (void __iomem *)base, reg, - (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)), - *value); - return false; } + *value = cam_io_r_mb(reg_addr); + CAM_DBG(CAM_CDM, "X b=%pK off=%x val=%x", + (void __iomem *)base, reg, + *value); + return false; + permission_error: *value = 0; return true; @@ -61,36 +51,27 @@ permission_error: } bool cam_cdm_write_hw_reg(struct cam_hw_info *cdm_hw, - enum cam_cdm_regs reg, uint32_t value) + uint32_t reg, uint32_t value) { void __iomem *reg_addr; - struct cam_cdm *cdm = (struct cam_cdm *)cdm_hw->core_info; void __iomem *base = cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].mem_base; resource_size_t mem_len = cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size; - CAM_DBG(CAM_CDM, "E: b=%pK reg=%x off=%x val=%x", (void __iomem *)base, - reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)), value); + CAM_DBG(CAM_CDM, "E: b=%pK off=%x val=%x", (void __iomem *)base, + reg, value); - if ((reg > cdm->offset_tbl->offset_max_size) || - (reg > cdm->offset_tbl->last_offset)) { - CAM_ERR_RATE_LIMIT(CAM_CDM, "CDM accessing invalid reg=%d\n", + reg_addr = (base + reg); + if (reg_addr > (base + mem_len)) { + CAM_ERR_RATE_LIMIT(CAM_CDM, + "Accessing invalid region:%d\n", reg); goto permission_error; - } else { - reg_addr = (base + CAM_CDM_OFFSET_FROM_REG( - cdm->offset_tbl, reg)); - if (reg_addr > (base + mem_len)) { - CAM_ERR_RATE_LIMIT(CAM_CDM, - "Accessing invalid region %d:%d\n", - reg, (CAM_CDM_OFFSET_FROM_REG( - cdm->offset_tbl, reg))); - goto permission_error; - } - cam_io_w_mb(value, reg_addr); - return false; } + cam_io_w_mb(value, reg_addr); + return false; + permission_error: return true; @@ -99,7 +80,7 @@ permission_error: int cam_cdm_soc_load_dt_private(struct platform_device *pdev, struct cam_cdm_private_dt_data *ptr) { - int i, rc = -EINVAL; + int i, rc = -EINVAL, num_fifo_entries = 0; ptr->dt_num_supported_clients = of_property_count_strings( pdev->dev.of_node, @@ -111,7 +92,7 @@ int cam_cdm_soc_load_dt_private(struct platform_device *pdev, CAM_ERR(CAM_CDM, "Invalid count of client names count=%d", ptr->dt_num_supported_clients); rc = -EINVAL; - return rc; + goto end; } if (ptr->dt_num_supported_clients < 0) { CAM_DBG(CAM_CDM, "No cdm client names found"); @@ -127,10 +108,43 @@ int cam_cdm_soc_load_dt_private(struct platform_device *pdev, ptr->dt_cdm_client_name[i]); if (rc < 0) { CAM_ERR(CAM_CDM, "Reading cdm-client-names failed"); - break; + goto end; } } + ptr->config_fifo = of_property_read_bool(pdev->dev.of_node, + "config-fifo"); + if (ptr->config_fifo) { + num_fifo_entries = of_property_count_u32_elems( + pdev->dev.of_node, + "fifo-depths"); + if (num_fifo_entries != CAM_CDM_NUM_BL_FIFO) { + CAM_ERR(CAM_CDM, + "Wrong number of configurable FIFOs %d", + num_fifo_entries); + rc = -EINVAL; + goto end; + } + for (i = 0; i < num_fifo_entries; i++) { + rc = of_property_read_u32_index(pdev->dev.of_node, + "fifo-depths", i, &ptr->fifo_depth[i]); + if (rc < 0) { + CAM_ERR(CAM_CDM, + "Unable to read fifo-depth rc %d", + rc); + goto end; + } + CAM_DBG(CAM_CDM, "FIFO%d depth is %d", + i, ptr->fifo_depth[i]); + } + } else { + for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { + ptr->fifo_depth[i] = CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT; + CAM_DBG(CAM_CDM, "FIFO%d depth is %d", + i, ptr->fifo_depth[i]); + } + } +end: return rc; } @@ -140,6 +154,7 @@ int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, int rc; struct cam_hw_soc_info *soc_ptr; const struct of_device_id *id; + struct cam_cdm *cdm_core = cdm_hw->core_info; if (!cdm_hw || (cdm_hw->soc_info.soc_private) || !(cdm_hw->soc_info.pdev)) @@ -150,38 +165,44 @@ int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, rc = cam_soc_util_get_dt_properties(soc_ptr); if (rc != 0) { CAM_ERR(CAM_CDM, "Failed to retrieve the CDM dt properties"); - } else { - soc_ptr->soc_private = kzalloc( - sizeof(struct cam_cdm_private_dt_data), - GFP_KERNEL); - if (!soc_ptr->soc_private) - return -ENOMEM; - - rc = cam_cdm_soc_load_dt_private(soc_ptr->pdev, - soc_ptr->soc_private); - if (rc != 0) { - CAM_ERR(CAM_CDM, "Failed to load CDM dt private data"); - goto error; - } - id = of_match_node(table, soc_ptr->pdev->dev.of_node); - if ((!id) || !(id->data)) { - CAM_ERR(CAM_CDM, "Failed to retrieve the CDM id table"); - goto error; - } - CAM_DBG(CAM_CDM, "CDM Hw Id compatible =%s", id->compatible); - ((struct cam_cdm *)cdm_hw->core_info)->offset_tbl = - (struct cam_cdm_reg_offset_table *)id->data; - strlcpy(((struct cam_cdm *)cdm_hw->core_info)->name, - id->compatible, - sizeof(((struct cam_cdm *)cdm_hw->core_info)->name)); + goto end; } - return rc; + soc_ptr->soc_private = kzalloc( + sizeof(struct cam_cdm_private_dt_data), + GFP_KERNEL); + if (!soc_ptr->soc_private) + return -ENOMEM; + + rc = cam_cdm_soc_load_dt_private(soc_ptr->pdev, + soc_ptr->soc_private); + if (rc != 0) { + CAM_ERR(CAM_CDM, "Failed to load CDM dt private data"); + goto error; + } + + id = of_match_node(table, soc_ptr->pdev->dev.of_node); + if ((!id) || !(id->data)) { + CAM_ERR(CAM_CDM, "Failed to retrieve the CDM id table"); + goto error; + } + cdm_core->offsets = + (struct cam_cdm_hw_reg_offset *)id->data; + + CAM_DBG(CAM_CDM, "name %s", cdm_core->name); + + snprintf(cdm_core->name, sizeof(cdm_core->name) + 1, "%s%d", + id->compatible, soc_ptr->index); + + CAM_DBG(CAM_CDM, "name %s", cdm_core->name); + + goto end; error: rc = -EINVAL; kfree(soc_ptr->soc_private); soc_ptr->soc_private = NULL; +end: return rc; } diff --git a/drivers/cam_cdm/cam_cdm_soc.h b/drivers/cam_cdm/cam_cdm_soc.h index b422b34f244b..25b5a5dc02d6 100644 --- a/drivers/cam_cdm/cam_cdm_soc.h +++ b/drivers/cam_cdm/cam_cdm_soc.h @@ -1,17 +1,25 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_SOC_H_ #define _CAM_CDM_SOC_H_ +#define CAM_HW_CDM_CPAS_0_NAME "qcom,cam170-cpas-cdm0" +#define CAM_HW_CDM_CPAS_NAME_1_0 "qcom,cam-cpas-cdm1_0" +#define CAM_HW_CDM_CPAS_NAME_1_1 "qcom,cam-cpas-cdm1_1" +#define CAM_HW_CDM_CPAS_NAME_1_2 "qcom,cam-cpas-cdm1_2" +#define CAM_HW_CDM_IFE_NAME_1_2 "qcom,cam-ife-cdm1_2" +#define CAM_HW_CDM_CPAS_NAME_2_0 "qcom,cam-cpas-cdm2_0" +#define CAM_HW_CDM_OPE_NAME_2_0 "qcom,cam-ope-cdm2_0" + int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, const struct of_device_id *table); bool cam_cdm_read_hw_reg(struct cam_hw_info *cdm_hw, - enum cam_cdm_regs reg, uint32_t *value); + uint32_t reg, uint32_t *value); bool cam_cdm_write_hw_reg(struct cam_hw_info *cdm_hw, - enum cam_cdm_regs reg, uint32_t value); + uint32_t reg, uint32_t value); int cam_cdm_intf_mgr_soc_get_dt_properties( struct platform_device *pdev, struct cam_cdm_intf_mgr *mgr); diff --git a/drivers/cam_cdm/cam_cdm_util.c b/drivers/cam_cdm/cam_cdm_util.c index 278dadb18db4..89951d24d0ef 100644 --- a/drivers/cam_cdm/cam_cdm_util.c +++ b/drivers/cam_cdm/cam_cdm_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -38,6 +38,9 @@ static unsigned int CDMCmdHeaderSizes[ 1, /* PERF_CONTROL*/ 3, /* DMI32*/ 3, /* DMI64*/ + 3, /* WaitCompEvent*/ + 3, /* ClearCompEvent*/ + 3, /* WaitPrefetchDisable*/ }; /** @@ -156,11 +159,34 @@ struct cdm_perf_ctrl_cmd { unsigned int cmd : 8; } __attribute__((__packed__)); +struct cdm_wait_comp_event_cmd { + unsigned int reserved : 8; + unsigned int id : 8; + unsigned int id_reserved: 8; + unsigned int cmd : 8; + unsigned int mask1; + unsigned int mask2; +} __attribute__((__packed__)); + +struct cdm_prefetch_disable_event_cmd { + unsigned int reserved : 8; + unsigned int id : 8; + unsigned int id_reserved: 8; + unsigned int cmd : 8; + unsigned int mask1; + unsigned int mask2; +} __attribute__((__packed__)); + uint32_t cdm_get_cmd_header_size(unsigned int command) { return CDMCmdHeaderSizes[command]; } +uint32_t cdm_required_size_dmi(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); +} + uint32_t cdm_required_size_reg_continuous(uint32_t numVals) { return cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT) + numVals; @@ -172,9 +198,9 @@ uint32_t cdm_required_size_reg_random(uint32_t numRegVals) (2 * numRegVals); } -uint32_t cdm_required_size_dmi(void) +uint32_t cdm_required_size_indirect(void) { - return cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); + return cdm_get_cmd_header_size(CAM_CDM_CMD_BUFF_INDIRECT); } uint32_t cdm_required_size_genirq(void) @@ -182,9 +208,9 @@ uint32_t cdm_required_size_genirq(void) return cdm_get_cmd_header_size(CAM_CDM_CMD_GEN_IRQ); } -uint32_t cdm_required_size_indirect(void) +uint32_t cdm_required_size_wait_event(void) { - return cdm_get_cmd_header_size(CAM_CDM_CMD_BUFF_INDIRECT); + return cdm_get_cmd_header_size(CAM_CDM_CMD_WAIT_EVENT); } uint32_t cdm_required_size_changebase(void) @@ -192,6 +218,16 @@ uint32_t cdm_required_size_changebase(void) return cdm_get_cmd_header_size(CAM_CDM_CMD_CHANGE_BASE); } +uint32_t cdm_required_size_comp_wait(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_COMP_WAIT); +} + +uint32_t cdm_required_size_prefetch_disable(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_WAIT_PREFETCH_DISABLE); +} + uint32_t cdm_offsetof_dmi_addr(void) { return offsetof(struct cdm_dmi_cmd, addr); @@ -202,6 +238,23 @@ uint32_t cdm_offsetof_indirect_addr(void) return offsetof(struct cdm_indirect_cmd, addr); } +uint32_t *cdm_write_dmi(uint32_t *pCmdBuffer, uint8_t dmiCmd, + uint32_t DMIAddr, uint8_t DMISel, uint32_t dmiBufferAddr, + uint32_t length) +{ + struct cdm_dmi_cmd *pHeader = (struct cdm_dmi_cmd *)pCmdBuffer; + + pHeader->cmd = CAM_CDM_CMD_DMI; + pHeader->addr = dmiBufferAddr; + pHeader->length = length; + pHeader->DMIAddr = DMIAddr; + pHeader->DMISel = DMISel; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); + + return pCmdBuffer; +} + uint32_t *cdm_write_regcontinuous(uint32_t *pCmdBuffer, uint32_t reg, uint32_t numVals, uint32_t *pVals) { @@ -248,23 +301,6 @@ uint32_t *cdm_write_regrandom(uint32_t *pCmdBuffer, uint32_t numRegVals, return dst; } -uint32_t *cdm_write_dmi(uint32_t *pCmdBuffer, uint8_t dmiCmd, - uint32_t DMIAddr, uint8_t DMISel, uint32_t dmiBufferAddr, - uint32_t length) -{ - struct cdm_dmi_cmd *pHeader = (struct cdm_dmi_cmd *)pCmdBuffer; - - pHeader->cmd = dmiCmd; - pHeader->addr = dmiBufferAddr; - pHeader->length = length - 1; - pHeader->DMIAddr = DMIAddr; - pHeader->DMISel = DMISel; - - pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); - - return pCmdBuffer; -} - uint32_t *cdm_write_indirect(uint32_t *pCmdBuffer, uint32_t indirectBufAddr, uint32_t length) { @@ -280,11 +316,50 @@ uint32_t *cdm_write_indirect(uint32_t *pCmdBuffer, uint32_t indirectBufAddr, return pCmdBuffer; } +void cdm_write_genirq(uint32_t *pCmdBuffer, uint32_t userdata, + bool bit_wr_enable, uint32_t fifo_idx) +{ + struct cdm_genirq_cmd *pHeader = (struct cdm_genirq_cmd *)pCmdBuffer; + + CAM_DBG(CAM_CDM, "userdata 0x%x, fifo_idx %d", + userdata, fifo_idx); + + if (bit_wr_enable) + pHeader->reserved = (unsigned int)((fifo_idx << 1) + | (unsigned int)(bit_wr_enable)); + + pHeader->cmd = CAM_CDM_CMD_GEN_IRQ; + pHeader->userdata = (userdata << (8 * fifo_idx)); +} + +uint32_t *cdm_write_wait_event(uint32_t *pcmdbuffer, uint32_t iw, + uint32_t id, uint32_t mask, + uint32_t offset, uint32_t data) +{ + struct cdm_wait_event_cmd *pheader = + (struct cdm_wait_event_cmd *)pcmdbuffer; + + pheader->cmd = CAM_CDM_CMD_WAIT_EVENT; + pheader->mask = mask; + pheader->data = data; + pheader->id = id; + pheader->iw = iw; + pheader->offset = offset; + pheader->iw_reserved = 0; + pheader->offset_reserved = 0; + + pcmdbuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_WAIT_EVENT); + + return pcmdbuffer; +} + uint32_t *cdm_write_changebase(uint32_t *pCmdBuffer, uint32_t base) { struct cdm_changebase_cmd *pHeader = (struct cdm_changebase_cmd *)pCmdBuffer; + CAM_DBG(CAM_CDM, "Change to base 0x%x", base); + pHeader->cmd = CAM_CDM_CMD_CHANGE_BASE; pHeader->base = base; pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_CHANGE_BASE); @@ -292,30 +367,63 @@ uint32_t *cdm_write_changebase(uint32_t *pCmdBuffer, uint32_t base) return pCmdBuffer; } -void cdm_write_genirq(uint32_t *pCmdBuffer, uint32_t userdata) +uint32_t *cdm_write_wait_comp_event( + uint32_t *pCmdBuffer, uint32_t mask1, uint32_t mask2) { - struct cdm_genirq_cmd *pHeader = (struct cdm_genirq_cmd *)pCmdBuffer; + struct cdm_wait_comp_event_cmd *pHeader = + (struct cdm_wait_comp_event_cmd *)pCmdBuffer; - pHeader->cmd = CAM_CDM_CMD_GEN_IRQ; - pHeader->userdata = userdata; + pHeader->cmd = CAM_CDM_COMP_WAIT; + pHeader->mask1 = mask1; + pHeader->mask2 = mask2; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_COMP_WAIT); + + return pCmdBuffer; } +uint32_t *cdm_write_wait_prefetch_disable( + uint32_t *pCmdBuffer, + uint32_t id, + uint32_t mask1, + uint32_t mask2) +{ + struct cdm_prefetch_disable_event_cmd *pHeader = + (struct cdm_prefetch_disable_event_cmd *)pCmdBuffer; + + pHeader->cmd = CAM_CDM_WAIT_PREFETCH_DISABLE; + pHeader->id = id; + pHeader->mask1 = mask1; + pHeader->mask2 = mask2; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_WAIT_PREFETCH_DISABLE); + + return pCmdBuffer; +} + + struct cam_cdm_utils_ops CDM170_ops = { cdm_get_cmd_header_size, + cdm_required_size_dmi, cdm_required_size_reg_continuous, cdm_required_size_reg_random, - cdm_required_size_dmi, - cdm_required_size_genirq, cdm_required_size_indirect, + cdm_required_size_genirq, + cdm_required_size_wait_event, cdm_required_size_changebase, + cdm_required_size_comp_wait, + cdm_required_size_prefetch_disable, cdm_offsetof_dmi_addr, cdm_offsetof_indirect_addr, + cdm_write_dmi, cdm_write_regcontinuous, cdm_write_regrandom, - cdm_write_dmi, cdm_write_indirect, - cdm_write_changebase, cdm_write_genirq, + cdm_write_wait_event, + cdm_write_changebase, + cdm_write_wait_comp_event, + cdm_write_wait_prefetch_disable, }; int cam_cdm_get_ioremap_from_base(uint32_t hw_base, @@ -672,7 +780,7 @@ void cam_cdm_util_dump_cmd_buf( uint32_t cmd = 0; if (!cmd_buf_start || !cmd_buf_end) { - CAM_INFO(CAM_CDM, "Invalid args"); + CAM_ERR(CAM_CDM, "Invalid args"); return; } @@ -708,7 +816,7 @@ void cam_cdm_util_dump_cmd_buf( buf_now += cam_cdm_util_dump_perf_ctrl_cmd(buf_now); break; default: - CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x", + CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x", cmd, *buf_now); buf_now++; break; diff --git a/drivers/cam_cdm/cam_cdm_util.h b/drivers/cam_cdm/cam_cdm_util.h index 663eca92a5fe..4d4095072e99 100644 --- a/drivers/cam_cdm/cam_cdm_util.h +++ b/drivers/cam_cdm/cam_cdm_util.h @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_UTIL_H_ #define _CAM_CDM_UTIL_H_ +#include + enum cam_cdm_command { CAM_CDM_CMD_UNUSED = 0x0, CAM_CDM_CMD_DMI = 0x1, @@ -19,10 +21,13 @@ enum cam_cdm_command { CAM_CDM_CMD_PERF_CTRL = 0x9, CAM_CDM_CMD_DMI_32 = 0xa, CAM_CDM_CMD_DMI_64 = 0xb, - CAM_CDM_CMD_PRIVATE_BASE = 0xc, + CAM_CDM_COMP_WAIT = 0xc, + CAM_CDM_CLEAR_COMP_WAIT = 0xd, + CAM_CDM_WAIT_PREFETCH_DISABLE = 0xe, + CAM_CDM_CMD_PRIVATE_BASE = 0xf, CAM_CDM_CMD_SWD_DMI_32 = (CAM_CDM_CMD_PRIVATE_BASE + 0x64), CAM_CDM_CMD_SWD_DMI_64 = (CAM_CDM_CMD_PRIVATE_BASE + 0x65), - CAM_CDM_CMD_PRIVATE_BASE_MAX = 0x7F + CAM_CDM_CMD_PRIVATE_BASE_MAX = 0x7F, }; /** @@ -53,6 +58,10 @@ enum cam_cdm_command { * in dwords. * @return Size in dwords * + * @cdm_required_size_comp_wait: Calculates the size of a comp-wait command + * in dwords. + * @return Size in dwords + * * @cdm_required_size_changebase: Calculates the size of a change-base command * in dwords. * @return Size in dwords @@ -102,46 +111,73 @@ enum cam_cdm_command { * @base: New base (device) address * @return Pointer in command buffer pointing past the written commands * - * @cdm_write_genirq: Writes a gen irq command into the command buffer. + * @cdm_write_genirq: Writes a gen irq command into the command buffer. * @pCmdBuffer: Pointer to command buffer * @userdata: userdata or cookie return by hardware during irq. + * + * @cdm_write_wait_comp_event: Writes a wait comp event cmd into the + * command buffer. + * @pCmdBuffer: Pointer to command buffer + * @mask1: This value decides which comp events to wait (0 - 31). + * @mask2: This value decides which comp events to wait (32 - 65). */ struct cam_cdm_utils_ops { uint32_t (*cdm_get_cmd_header_size)(unsigned int command); +uint32_t (*cdm_required_size_dmi)(void); uint32_t (*cdm_required_size_reg_continuous)(uint32_t numVals); uint32_t (*cdm_required_size_reg_random)(uint32_t numRegVals); -uint32_t (*cdm_required_size_dmi)(void); -uint32_t (*cdm_required_size_genirq)(void); uint32_t (*cdm_required_size_indirect)(void); +uint32_t (*cdm_required_size_genirq)(void); +uint32_t (*cdm_required_size_wait_event)(void); uint32_t (*cdm_required_size_changebase)(void); +uint32_t (*cdm_required_size_comp_wait)(void); +uint32_t (*cdm_required_size_prefetch_disable)(void); uint32_t (*cdm_offsetof_dmi_addr)(void); uint32_t (*cdm_offsetof_indirect_addr)(void); +uint32_t *(*cdm_write_dmi)( + uint32_t *pCmdBuffer, + uint8_t dmiCmd, + uint32_t DMIAddr, + uint8_t DMISel, + uint32_t dmiBufferAddr, + uint32_t length); uint32_t* (*cdm_write_regcontinuous)( uint32_t *pCmdBuffer, - uint32_t reg, - uint32_t numVals, + uint32_t reg, + uint32_t numVals, uint32_t *pVals); uint32_t *(*cdm_write_regrandom)( uint32_t *pCmdBuffer, - uint32_t numRegVals, + uint32_t numRegVals, uint32_t *pRegVals); -uint32_t *(*cdm_write_dmi)( - uint32_t *pCmdBuffer, - uint8_t dmiCmd, - uint32_t DMIAddr, - uint8_t DMISel, - uint32_t dmiBufferAddr, - uint32_t length); uint32_t *(*cdm_write_indirect)( uint32_t *pCmdBuffer, - uint32_t indirectBufferAddr, - uint32_t length); -uint32_t *(*cdm_write_changebase)( - uint32_t *pCmdBuffer, - uint32_t base); + uint32_t indirectBufferAddr, + uint32_t length); void (*cdm_write_genirq)( uint32_t *pCmdBuffer, - uint32_t userdata); + uint32_t userdata, + bool bit_wr_enable, + uint32_t fifo_idx); +uint32_t *(*cdm_write_wait_event)( + uint32_t *pCmdBuffer, + uint32_t iw, + uint32_t id, + uint32_t mask, + uint32_t offset, + uint32_t data); +uint32_t *(*cdm_write_changebase)( + uint32_t *pCmdBuffer, + uint32_t base); +uint32_t *(*cdm_write_wait_comp_event)( + uint32_t *pCmdBuffer, + uint32_t mask1, + uint32_t mask2); +uint32_t *(*cdm_write_wait_prefetch_disable)( + uint32_t *pCmdBuffer, + uint32_t id, + uint32_t mask1, + uint32_t mask2); }; /** diff --git a/drivers/cam_cdm/cam_hw_cdm170_reg.h b/drivers/cam_cdm/cam_hw_cdm170_reg.h deleted file mode 100644 index 4a0fbda825c5..000000000000 --- a/drivers/cam_cdm/cam_hw_cdm170_reg.h +++ /dev/null @@ -1,135 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef _CAM_HW_CDM170_REG_H_ -#define _CAM_HW_CDM170_REG_H_ - -#define CAM_CDM_REG_OFFSET_FIRST 0x0 -#define CAM_CDM_REG_OFFSET_LAST 0x200 -#define CAM_CDM_REGS_COUNT 0x30 -#define CAM_CDM_HWFIFO_SIZE 0x40 - -#define CAM_CDM_OFFSET_HW_VERSION 0x0 -#define CAM_CDM_OFFSET_TITAN_VERSION 0x4 -#define CAM_CDM_OFFSET_RST_CMD 0x10 -#define CAM_CDM_OFFSET_CGC_CFG 0x14 -#define CAM_CDM_OFFSET_CORE_CFG 0x18 -#define CAM_CDM_OFFSET_CORE_EN 0x1c -#define CAM_CDM_OFFSET_FE_CFG 0x20 -#define CAM_CDM_OFFSET_IRQ_MASK 0x30 -#define CAM_CDM_OFFSET_IRQ_CLEAR 0x34 -#define CAM_CDM_OFFSET_IRQ_CLEAR_CMD 0x38 -#define CAM_CDM_OFFSET_IRQ_SET 0x3c -#define CAM_CDM_OFFSET_IRQ_SET_CMD 0x40 - -#define CAM_CDM_OFFSET_IRQ_STATUS 0x44 -#define CAM_CDM_IRQ_STATUS_INFO_RST_DONE_MASK 0x1 -#define CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK 0x2 -#define CAM_CDM_IRQ_STATUS_INFO_BL_DONE_MASK 0x4 -#define CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK 0x10000 -#define CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK 0x20000 -#define CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK 0x40000 - -#define CAM_CDM_OFFSET_BL_FIFO_BASE_REG 0x50 -#define CAM_CDM_OFFSET_BL_FIFO_LEN_REG 0x54 -#define CAM_CDM_OFFSET_BL_FIFO_STORE_REG 0x58 -#define CAM_CDM_OFFSET_BL_FIFO_CFG 0x5c -#define CAM_CDM_OFFSET_BL_FIFO_RB 0x60 -#define CAM_CDM_OFFSET_BL_FIFO_BASE_RB 0x64 -#define CAM_CDM_OFFSET_BL_FIFO_LEN_RB 0x68 -#define CAM_CDM_OFFSET_BL_FIFO_PENDING_REQ_RB 0x6c -#define CAM_CDM_OFFSET_IRQ_USR_DATA 0x80 -#define CAM_CDM_OFFSET_WAIT_STATUS 0x84 -#define CAM_CDM_OFFSET_SCRATCH_0_REG 0x90 -#define CAM_CDM_OFFSET_SCRATCH_1_REG 0x94 -#define CAM_CDM_OFFSET_SCRATCH_2_REG 0x98 -#define CAM_CDM_OFFSET_SCRATCH_3_REG 0x9c -#define CAM_CDM_OFFSET_SCRATCH_4_REG 0xa0 -#define CAM_CDM_OFFSET_SCRATCH_5_REG 0xa4 -#define CAM_CDM_OFFSET_SCRATCH_6_REG 0xa8 -#define CAM_CDM_OFFSET_SCRATCH_7_REG 0xac -#define CAM_CDM_OFFSET_LAST_AHB_ADDR 0xd0 -#define CAM_CDM_OFFSET_LAST_AHB_DATA 0xd4 -#define CAM_CDM_OFFSET_CORE_DBUG 0xd8 -#define CAM_CDM_OFFSET_LAST_AHB_ERR_ADDR 0xe0 -#define CAM_CDM_OFFSET_LAST_AHB_ERR_DATA 0xe4 -#define CAM_CDM_OFFSET_CURRENT_BL_BASE 0xe8 -#define CAM_CDM_OFFSET_CURRENT_BL_LEN 0xec -#define CAM_CDM_OFFSET_CURRENT_USED_AHB_BASE 0xf0 -#define CAM_CDM_OFFSET_DEBUG_STATUS 0xf4 -#define CAM_CDM_OFFSET_BUS_MISR_CFG_0 0x100 -#define CAM_CDM_OFFSET_BUS_MISR_CFG_1 0x104 -#define CAM_CDM_OFFSET_BUS_MISR_RD_VAL 0x108 -#define CAM_CDM_OFFSET_PERF_MON_CTRL 0x110 -#define CAM_CDM_OFFSET_PERF_MON_0 0x114 -#define CAM_CDM_OFFSET_PERF_MON_1 0x118 -#define CAM_CDM_OFFSET_PERF_MON_2 0x11c -#define CAM_CDM_OFFSET_SPARE 0x200 - -/* - * Always make sure below register offsets are aligned with - * enum cam_cdm_regs offsets - */ -struct cam_cdm_reg_offset cam170_cpas_cdm_register_offsets[] = { - { CAM_CDM_OFFSET_HW_VERSION, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_TITAN_VERSION, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_RST_CMD, CAM_REG_ATTR_WRITE }, - { CAM_CDM_OFFSET_CGC_CFG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_CORE_CFG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_CORE_EN, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_FE_CFG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_IRQ_MASK, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_IRQ_CLEAR, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_IRQ_CLEAR_CMD, CAM_REG_ATTR_WRITE }, - { CAM_CDM_OFFSET_IRQ_SET, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_IRQ_SET_CMD, CAM_REG_ATTR_WRITE }, - { CAM_CDM_OFFSET_IRQ_STATUS, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_IRQ_USR_DATA, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BL_FIFO_BASE_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BL_FIFO_LEN_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BL_FIFO_STORE_REG, CAM_REG_ATTR_WRITE }, - { CAM_CDM_OFFSET_BL_FIFO_CFG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BL_FIFO_RB, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BL_FIFO_BASE_RB, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_BL_FIFO_LEN_RB, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_BL_FIFO_PENDING_REQ_RB, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_WAIT_STATUS, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_SCRATCH_0_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_1_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_2_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_3_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_4_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_5_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_6_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_SCRATCH_7_REG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_LAST_AHB_ADDR, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_LAST_AHB_DATA, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_CORE_DBUG, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_LAST_AHB_ERR_ADDR, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_LAST_AHB_ERR_DATA, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_CURRENT_BL_BASE, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_CURRENT_BL_LEN, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_CURRENT_USED_AHB_BASE, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_DEBUG_STATUS, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_BUS_MISR_CFG_0, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BUS_MISR_CFG_1, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_BUS_MISR_RD_VAL, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_PERF_MON_CTRL, CAM_REG_ATTR_READ_WRITE }, - { CAM_CDM_OFFSET_PERF_MON_0, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_PERF_MON_1, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_PERF_MON_2, CAM_REG_ATTR_READ }, - { CAM_CDM_OFFSET_SPARE, CAM_REG_ATTR_READ_WRITE } -}; - -struct cam_cdm_reg_offset_table cam170_cpas_cdm_offset_table = { - .first_offset = 0x0, - .last_offset = 0x200, - .reg_count = 0x30, - .offsets = cam170_cpas_cdm_register_offsets, - .offset_max_size = (sizeof(cam170_cpas_cdm_register_offsets)/ - sizeof(struct cam_cdm_reg_offset)), -}; - -#endif /* _CAM_HW_CDM170_REG_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c index c28fcdf3efc6..bfb9fdba0af6 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_fd_hw_core.h" @@ -903,12 +903,14 @@ int cam_fd_hw_start(void *hw_priv, void *hw_start_args, uint32_t arg_size) cdm_cmd->flag = false; cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; + cdm_cmd->gen_irq_arb = false; for (i = 0 ; i <= start_args->num_hw_update_entries; i++) { cmd = (start_args->hw_update_entries + i); cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[i].offset = cmd->offset; cdm_cmd->cmd[i].len = cmd->len; + cdm_cmd->cmd[i].arbitrate = false; } rc = cam_cdm_submit_bls(ctx_hw_private->cdm_handle, cdm_cmd); @@ -1032,6 +1034,7 @@ int cam_fd_hw_reserve(void *hw_priv, void *hw_reserve_args, uint32_t arg_size) cdm_acquire.cam_cdm_callback = cam_fd_hw_util_cdm_callback; cdm_acquire.id = CAM_CDM_VIRTUAL; cdm_acquire.base_array_cnt = fd_hw->soc_info.num_reg_map; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; for (i = 0; i < fd_hw->soc_info.num_reg_map; i++) cdm_acquire.base_array[i] = &fd_hw->soc_info.reg_map[i]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 05a166cd01bd..6fdc18b05306 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2697,8 +2697,9 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) cdm_acquire.base_array[j++] = ife_hw_mgr->cdm_reg_map[i]; } - cdm_acquire.base_array_cnt = j; + cdm_acquire.base_array_cnt = j; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; cdm_acquire.id = CAM_CDM_VIRTUAL; cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; rc = cam_cdm_acquire(&cdm_acquire); @@ -2885,9 +2886,9 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) cdm_acquire.base_array[j++] = ife_hw_mgr->cdm_reg_map[i]; } + cdm_acquire.base_array_cnt = j; - - + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; cdm_acquire.id = CAM_CDM_VIRTUAL; cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; rc = cam_cdm_acquire(&cdm_acquire); @@ -3412,6 +3413,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, cdm_cmd->flag = true; cdm_cmd->userdata = hw_update_data; cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; for (i = 0 ; i < cfg->num_hw_update_entries; i++) { cmd = (cfg->hw_update_entries + i); @@ -3430,6 +3432,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[i - skip].offset = cmd->offset; cdm_cmd->cmd[i - skip].len = cmd->len; + cdm_cmd->cmd[i - skip].arbitrate = false; } cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 09b4b8d3e0f6..793415c924a2 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -303,6 +303,7 @@ static int cam_jpeg_insert_cdm_change_base( config_args->hw_update_entries[CAM_JPEG_CHBASE].offset; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = size * sizeof(uint32_t); cdm_cmd->cmd_arrary_count++; + cdm_cmd->gen_irq_arb = false; ch_base_iova_addr += size; *ch_base_iova_addr = 0; @@ -439,6 +440,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; cdm_cmd->cmd_arrary_count = 0; + cdm_cmd->gen_irq_arb = false; rc = cam_jpeg_insert_cdm_change_base(config_args, ctx_data, hw_mgr); @@ -457,6 +459,8 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) cmd->offset; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = cmd->len; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].arbitrate = + false; CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", i, cmd->handle, cmd->offset, cmd->len); cdm_cmd->cmd_arrary_count++; @@ -1186,6 +1190,7 @@ static int cam_jpeg_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) cdm_acquire.base_array_cnt = 1; cdm_acquire.id = CAM_CDM_VIRTUAL; cdm_acquire.cam_cdm_callback = NULL; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; rc = cam_cdm_acquire(&cdm_acquire); if (rc) { diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c index b736708fa99d..7f34de1d2378 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_lrme_hw_core.h" @@ -416,12 +416,14 @@ static int cam_lrme_hw_util_submit_req(struct cam_lrme_core *lrme_core, cdm_cmd->flag = false; cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; + cdm_cmd->gen_irq_arb = false; for (i = 0; i <= frame_req->num_hw_update_entries; i++) { cmd = (frame_req->hw_update_entries + i); cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[i].offset = cmd->offset; cdm_cmd->cmd[i].len = cmd->len; + cdm_cmd->cmd[i].arbitrate = false; } rc = cam_cdm_submit_bls(hw_cdm_info->cdm_handle, cdm_cmd); diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c index 6ea5d343ec4e..e42591dc90d8 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -53,6 +53,7 @@ static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core, cdm_acquire.cam_cdm_callback = NULL; cdm_acquire.id = CAM_CDM_VIRTUAL; cdm_acquire.base_array_cnt = lrme_hw->soc_info.num_reg_map; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; for (i = 0; i < lrme_hw->soc_info.num_reg_map; i++) cdm_acquire.base_array[i] = &lrme_hw->soc_info.reg_map[i]; diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 78d1b2cee91e..ae237c41a0b5 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #include @@ -31,7 +31,8 @@ #define COOKIE_SIZE (BYTE_SIZE*COOKIE_NUM_BYTE) #define COOKIE_MASK ((1<> COOKIE_SIZE) & COOKIE_MASK) @@ -93,7 +94,7 @@ struct cam_context_bank_info { struct iommu_domain *domain; dma_addr_t va_start; size_t va_len; - const char *name; + const char *name[CAM_SMMU_SHARED_HDL_MAX]; bool is_secure; uint8_t scratch_buf_support; uint8_t firmware_support; @@ -128,9 +129,11 @@ struct cam_context_bank_info { int cb_count; int secure_count; int pf_count; - size_t io_mapping_size; size_t shared_mapping_size; + bool is_mul_client; + int device_count; + int num_shared_hdl; }; struct cam_iommu_cb_set { @@ -369,12 +372,16 @@ static void cam_smmu_print_kernel_list(int idx) static void cam_smmu_print_table(void) { - int i; + int i, j; for (i = 0; i < iommu_cb_set.cb_num; i++) { - CAM_ERR(CAM_SMMU, "i= %d, handle= %d, name_addr=%pK", i, - (int)iommu_cb_set.cb_info[i].handle, - (void *)iommu_cb_set.cb_info[i].name); + for (j = 0; j < iommu_cb_set.cb_info[i].num_shared_hdl; j++) { + CAM_ERR(CAM_SMMU, + "i= %d, handle= %d, name_addr=%pK name %s", + i, (int)iommu_cb_set.cb_info[i].handle, + (void *)iommu_cb_set.cb_info[i].name[j], + iommu_cb_set.cb_info[i].name[j]); + } CAM_ERR(CAM_SMMU, "dev = %pK", iommu_cb_set.cb_info[i].dev); } } @@ -399,7 +406,7 @@ static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr) "Found va 0x%lx in:0x%lx-0x%lx, fd %d cb:%s", current_addr, start_addr, end_addr, mapping->ion_fd, - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); goto end; } else { if (start_addr > current_addr) @@ -429,9 +436,9 @@ end: closest_mapping->buf, buf_handle); } else - CAM_INFO(CAM_SMMU, + CAM_ERR(CAM_SMMU, "Cannot find vaddr:%lx in SMMU %s virt address", - current_addr, iommu_cb_set.cb_info[idx].name); + current_addr, iommu_cb_set.cb_info[idx].name[0]); return buf_handle; } @@ -467,7 +474,7 @@ void cam_smmu_set_client_page_fault_handler(int handle, if (iommu_cb_set.cb_info[idx].cb_count == CAM_SMMU_CB_MAX) { CAM_ERR(CAM_SMMU, "%s Should not regiester more handlers", - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); mutex_unlock(&iommu_cb_set.cb_info[idx].lock); return; } @@ -495,7 +502,7 @@ void cam_smmu_set_client_page_fault_handler(int handle, if (i == CAM_SMMU_CB_MAX) CAM_ERR(CAM_SMMU, "Error: hdl %x no matching tokens: %s", - handle, iommu_cb_set.cb_info[idx].name); + handle, iommu_cb_set.cb_info[idx].name[0]); } mutex_unlock(&iommu_cb_set.cb_info[idx].lock); } @@ -537,7 +544,7 @@ void cam_smmu_unset_client_page_fault_handler(int handle, void *token) } if (i == CAM_SMMU_CB_MAX) CAM_ERR(CAM_SMMU, "Error: hdl %x no matching tokens: %s", - handle, iommu_cb_set.cb_info[idx].name); + handle, iommu_cb_set.cb_info[idx].name[0]); mutex_unlock(&iommu_cb_set.cb_info[idx].lock); } @@ -560,7 +567,7 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, cb_name = (char *)token; /* Check whether it is in the table */ for (idx = 0; idx < iommu_cb_set.cb_num; idx++) { - if (!strcmp(iommu_cb_set.cb_info[idx].name, cb_name)) + if (!strcmp(iommu_cb_set.cb_info[idx].name[0], cb_name)) break; } @@ -714,45 +721,69 @@ static int cam_smmu_attach_device(int idx) static int cam_smmu_create_add_handle_in_table(char *name, int *hdl) { - int i; + int i, j; int handle; + bool valid = false; /* create handle and add in the iommu hardware table */ for (i = 0; i < iommu_cb_set.cb_num; i++) { - if (!strcmp(iommu_cb_set.cb_info[i].name, name)) { - mutex_lock(&iommu_cb_set.cb_info[i].lock); - if (iommu_cb_set.cb_info[i].handle != HANDLE_INIT) { - if (iommu_cb_set.cb_info[i].is_secure) - iommu_cb_set.cb_info[i].secure_count++; + for (j = 0; j < iommu_cb_set.cb_info[i].num_shared_hdl; j++) { + if (!strcmp(iommu_cb_set.cb_info[i].name[j], name)) + valid = true; - mutex_unlock(&iommu_cb_set.cb_info[i].lock); + if (iommu_cb_set.cb_info[i].handle != HANDLE_INIT && + valid) { + mutex_lock(&iommu_cb_set.cb_info[i].lock); if (iommu_cb_set.cb_info[i].is_secure) { + iommu_cb_set.cb_info[i].secure_count++; *hdl = iommu_cb_set.cb_info[i].handle; + mutex_unlock( + &iommu_cb_set.cb_info[i].lock); + return 0; + } + + if (iommu_cb_set.cb_info[i].is_mul_client) { + iommu_cb_set.cb_info[i].device_count++; + *hdl = iommu_cb_set.cb_info[i].handle; + mutex_unlock( + &iommu_cb_set.cb_info[i].lock); + CAM_INFO(CAM_SMMU, + "%s already got handle 0x%x", + name, + iommu_cb_set.cb_info[i].handle); return 0; } CAM_ERR(CAM_SMMU, "Error: %s already got handle 0x%x", name, iommu_cb_set.cb_info[i].handle); - - return -EINVAL; + mutex_unlock(&iommu_cb_set.cb_info[i].lock); + return -EALREADY; } - /* make sure handle is unique */ - do { - handle = cam_smmu_create_iommu_handle(i); - } while (cam_smmu_check_handle_unique(handle)); + if (iommu_cb_set.cb_info[i].handle == HANDLE_INIT && + valid) { + /* make sure handle is unique */ + do { + handle = + cam_smmu_create_iommu_handle(i); + } while (cam_smmu_check_handle_unique(handle)); - /* put handle in the table */ - iommu_cb_set.cb_info[i].handle = handle; - iommu_cb_set.cb_info[i].cb_count = 0; - if (iommu_cb_set.cb_info[i].is_secure) - iommu_cb_set.cb_info[i].secure_count++; - *hdl = handle; - CAM_DBG(CAM_SMMU, "%s creates handle 0x%x", - name, handle); - mutex_unlock(&iommu_cb_set.cb_info[i].lock); - return 0; + /* put handle in the table */ + iommu_cb_set.cb_info[i].handle = handle; + iommu_cb_set.cb_info[i].cb_count = 0; + if (iommu_cb_set.cb_info[i].is_secure) + iommu_cb_set.cb_info[i].secure_count++; + + if (iommu_cb_set.cb_info[i].is_mul_client) + iommu_cb_set.cb_info[i].device_count++; + + *hdl = handle; + CAM_DBG(CAM_SMMU, "%s creates handle 0x%x", + name, handle); + mutex_unlock(&iommu_cb_set.cb_info[i].lock); + return 0; + } } } @@ -2038,7 +2069,7 @@ static enum cam_smmu_buf_state cam_smmu_validate_secure_fd_in_list(int idx, int cam_smmu_get_handle(char *identifier, int *handle_ptr) { - int ret = 0; + int rc = 0; if (!identifier) { CAM_ERR(CAM_SMMU, "Error: iommu hardware name is NULL"); @@ -2051,11 +2082,12 @@ int cam_smmu_get_handle(char *identifier, int *handle_ptr) } /* create and put handle in the table */ - ret = cam_smmu_create_add_handle_in_table(identifier, handle_ptr); - if (ret < 0) - CAM_ERR(CAM_SMMU, "Error: %s get handle fail", identifier); + rc = cam_smmu_create_add_handle_in_table(identifier, handle_ptr); + if (rc < 0) + CAM_ERR(CAM_SMMU, "Error: %s get handle fail, rc %d", + identifier, rc); - return ret; + return rc; } EXPORT_SYMBOL(cam_smmu_get_handle); @@ -2328,7 +2360,7 @@ int cam_smmu_get_scratch_iova(int handle, if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) { CAM_ERR(CAM_SMMU, "Err:Dev %s should call SMMU attach before map buffer", - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); rc = -EINVAL; goto error; } @@ -2736,7 +2768,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) { CAM_ERR(CAM_SMMU, "Err:Dev %s should call SMMU attach before map buffer", - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); rc = -EINVAL; goto get_addr_end; } @@ -2800,7 +2832,7 @@ int cam_smmu_map_kernel_iova(int handle, struct dma_buf *buf, if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) { CAM_ERR(CAM_SMMU, "Err:Dev %s should call SMMU attach before map buffer", - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); rc = -EINVAL; goto get_addr_end; } @@ -3139,7 +3171,7 @@ int cam_smmu_destroy_handle(int handle) if (!list_empty_careful(&iommu_cb_set.cb_info[idx].smmu_buf_list)) { CAM_ERR(CAM_SMMU, "UMD %s buffer list is not clean", - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); cam_smmu_print_user_list(idx); cam_smmu_clean_user_buffer_list(idx); } @@ -3147,7 +3179,7 @@ int cam_smmu_destroy_handle(int handle) if (!list_empty_careful( &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list)) { CAM_ERR(CAM_SMMU, "KMD %s buffer list is not clean", - iommu_cb_set.cb_info[idx].name); + iommu_cb_set.cb_info[idx].name[0]); cam_smmu_print_kernel_list(idx); cam_smmu_clean_kernel_buffer_list(idx); } @@ -3168,6 +3200,19 @@ int cam_smmu_destroy_handle(int handle) return 0; } + if (iommu_cb_set.cb_info[idx].is_mul_client && + iommu_cb_set.cb_info[idx].device_count) { + iommu_cb_set.cb_info[idx].device_count--; + + if (!iommu_cb_set.cb_info[idx].device_count) { + iommu_cb_set.cb_info[idx].cb_count = 0; + iommu_cb_set.cb_info[idx].handle = HANDLE_INIT; + } + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return 0; + } + + iommu_cb_set.cb_info[idx].device_count = 0; iommu_cb_set.cb_info[idx].cb_count = 0; iommu_cb_set.cb_info[idx].handle = HANDLE_INIT; mutex_unlock(&iommu_cb_set.cb_info[idx].lock); @@ -3445,7 +3490,7 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, region_id); } - CAM_DBG(CAM_SMMU, "Found label -> %s", cb->name); + CAM_DBG(CAM_SMMU, "Found label -> %s", cb->name[0]); CAM_DBG(CAM_SMMU, "Found region -> %s", region_name); CAM_DBG(CAM_SMMU, "region_start -> %X", region_start); CAM_DBG(CAM_SMMU, "region_len -> %X", region_len); @@ -3468,6 +3513,7 @@ static int cam_populate_smmu_context_banks(struct device *dev, int rc = 0; struct cam_context_bank_info *cb; struct device *ctx = NULL; + int i = 0; if (!dev) { CAM_ERR(CAM_SMMU, "Error: Invalid device"); @@ -3484,8 +3530,24 @@ static int cam_populate_smmu_context_banks(struct device *dev, /* read the context bank from cb set */ cb = &iommu_cb_set.cb_info[iommu_cb_set.cb_init_count]; + cb->is_mul_client = + of_property_read_bool(dev->of_node, "multiple-client-devices"); + + cb->num_shared_hdl = of_property_count_strings(dev->of_node, + "label"); + + if (cb->num_shared_hdl > + CAM_SMMU_SHARED_HDL_MAX) { + CAM_ERR(CAM_CDM, "Invalid count of client names count=%d", + cb->num_shared_hdl); + rc = -EINVAL; + return rc; + } + /* set the name of the context bank */ - rc = of_property_read_string(dev->of_node, "label", &cb->name); + for (i = 0; i < cb->num_shared_hdl; i++) + rc = of_property_read_string_index(dev->of_node, + "label", i, &cb->name[i]); if (rc < 0) { CAM_ERR(CAM_SMMU, "Error: failed to read label from sub device"); @@ -3509,22 +3571,23 @@ static int cam_populate_smmu_context_banks(struct device *dev, /* set up the iommu mapping for the context bank */ if (type == CAM_QSMMU) { CAM_ERR(CAM_SMMU, "Error: QSMMU ctx not supported for : %s", - cb->name); + cb->name[0]); return -ENODEV; } ctx = dev; - CAM_DBG(CAM_SMMU, "getting Arm SMMU ctx : %s", cb->name); + CAM_DBG(CAM_SMMU, "getting Arm SMMU ctx : %s", cb->name[0]); rc = cam_smmu_setup_cb(cb, ctx); if (rc < 0) { - CAM_ERR(CAM_SMMU, "Error: failed to setup cb : %s", cb->name); + CAM_ERR(CAM_SMMU, "Error: failed to setup cb : %s", + cb->name[0]); goto cb_init_fail; } if (cb->io_support && cb->domain) iommu_set_fault_handler(cb->domain, cam_smmu_iommu_fault_handler, - (void *)cb->name); + (void *)cb->name[0]); if (!dev->dma_parms) dev->dma_parms = devm_kzalloc(dev, diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 4e3dacaa822c..a6220d156692 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include @@ -1280,6 +1280,10 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info) } } + rc = of_property_read_string(of_node, "label", &soc_info->label_name); + if (rc) + CAM_DBG(CAM_UTIL, "Label is not available in the node: %d", rc); + if (soc_info->num_mem_block > 0) { rc = of_property_read_u32_array(of_node, "reg-cam-base", soc_info->mem_block_cam_base, soc_info->num_mem_block); diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 25c08fc1890d..5e51fa8f1bf5 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SOC_UTIL_H_ @@ -123,6 +123,7 @@ struct cam_soc_gpio_data { * @index: Instance id for the camera device * @dev_name: Device Name * @irq_name: Name of the irq associated with the device + * @label_name: label name * @irq_line: Irq resource * @irq_data: Private data that is passed when IRQ is requested * @compatible: Compatible string associated with the device @@ -171,6 +172,7 @@ struct cam_hw_soc_info { uint32_t index; const char *dev_name; const char *irq_name; + const char *label_name; struct resource *irq_line; void *irq_data; const char *compatible; From 4fddce3d699d42370ae5a8b27661635f9270a9fe Mon Sep 17 00:00:00 2001 From: Abhilash Kumar Date: Fri, 8 Nov 2019 14:54:03 +0530 Subject: [PATCH 210/790] msm: camera: cdm: Correct bitvalue for burst enable The bit corrresponding to enabling burst is 4th bit. This change fixes its value by assigning the same. CRs-Fixed: 2594541 Change-Id: Ibeec3fd4460f9040255fa77f60fd565aed824c1c Signed-off-by: Abhilash Kumar Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm_core_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h index 055c7cf1fe9d..0f50165c7b15 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.h +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -17,7 +17,7 @@ #define CAM_CDM_AHB_BURST_LEN_4 (BIT(2) - 1) #define CAM_CDM_AHB_BURST_LEN_8 (BIT(3) - 1) #define CAM_CDM_AHB_BURST_LEN_16 (BIT(4) - 1) -#define CAM_CDM_AHB_BURST_EN BIT(5) +#define CAM_CDM_AHB_BURST_EN BIT(4) #define CAM_CDM_AHB_STOP_ON_ERROR BIT(8) #define CAM_CDM_ARB_SEL_RR BIT(16) #define CAM_CDM_IMPLICIT_WAIT_EN BIT(17) From cb2e8943da64f33ca8a150f6a32a7c3cde69a87b Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 23 Dec 2019 16:12:03 +0530 Subject: [PATCH 211/790] msm: camera: tfe: Add support to TFE driver TFE is thin front end hardware that capture and process the real time image. Support is added to enable the TFE hardware. CRs-Fixed: 2594541 Change-Id: I0ab2eff7924e9e01f6a0fcec772d3a7dda229b37 Signed-off-by: Ravikishore Pampana Signed-off-by: Trishansh Bhardwaj --- drivers/Makefile | 16 + drivers/cam_isp/cam_isp_context.c | 71 +- drivers/cam_isp/cam_isp_context.h | 9 +- drivers/cam_isp/cam_isp_dev.c | 27 +- drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c | 15 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 5282 +++++++++++++++++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 196 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 6 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 19 +- .../isp_hw/include/cam_tfe_csid_hw_intf.h | 179 + .../isp_hw/include/cam_tfe_hw_intf.h | 253 + .../isp_hw/include/cam_top_tpg_hw_intf.h | 74 + .../isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile | 15 + .../isp_hw/tfe_csid_hw/cam_tfe_csid530.c | 51 + .../isp_hw/tfe_csid_hw/cam_tfe_csid530.h | 225 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 2824 +++++++++ .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 412 ++ .../isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c | 139 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_dev.h | 16 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c | 209 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h | 119 + .../cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile | 13 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c | 42 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 813 +++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 2149 +++++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h | 240 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 2529 ++++++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h | 272 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c | 197 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h | 38 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h | 31 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c | 240 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h | 117 + .../isp_hw_mgr/isp_hw/top_tpg/Makefile | 15 + .../isp_hw/top_tpg/cam_top_tpg_core.c | 671 +++ .../isp_hw/top_tpg/cam_top_tpg_core.h | 153 + .../isp_hw/top_tpg/cam_top_tpg_dev.c | 140 + .../isp_hw/top_tpg/cam_top_tpg_dev.h | 12 + .../isp_hw/top_tpg/cam_top_tpg_soc.c | 152 + .../isp_hw/top_tpg/cam_top_tpg_soc.h | 78 + .../isp_hw/top_tpg/cam_top_tpg_v1.c | 53 + .../isp_hw/top_tpg/cam_top_tpg_v1.h | 56 + drivers/camera_main.c | 17 + 43 files changed, 18155 insertions(+), 30 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c create mode 100644 drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h diff --git a/drivers/Makefile b/drivers/Makefile index 552ab12e52da..8f4432bf6dfd 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -183,6 +183,22 @@ camera-$(CONFIG_SPECTRA_OPE) += \ cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.o\ cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.o +camera-$(CONFIG_SPECTRA_CAMERA) += \ + cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.o \ + cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.o + camera-y += camera_main.o obj-$(CONFIG_SPECTRA_CAMERA) += camera.o diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 1a66070585e5..79e57b629cdc 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -376,6 +376,38 @@ static const char *__cam_isp_resource_handle_id_to_type( } } +static const char *__cam_isp_tfe_resource_handle_id_to_type( + uint32_t resource_handle) +{ + + switch (resource_handle) { + case CAM_ISP_TFE_OUT_RES_FULL: + return "FULL"; + case CAM_ISP_TFE_OUT_RES_RAW_DUMP: + return "RAW_DUMP"; + case CAM_ISP_TFE_OUT_RES_PDAF: + return "PDAF"; + case CAM_ISP_TFE_OUT_RES_RDI_0: + return "RDI_0"; + case CAM_ISP_TFE_OUT_RES_RDI_1: + return "RDI_1"; + case CAM_ISP_TFE_OUT_RES_RDI_2: + return "RDI_2"; + case CAM_ISP_TFE_OUT_RES_STATS_HDR_BE: + return "STATS_HDR_BE"; + case CAM_ISP_TFE_OUT_RES_STATS_HDR_BHIST: + return "STATS_HDR_BHIST"; + case CAM_ISP_TFE_OUT_RES_STATS_TL_BG: + return "STATS_TL_BG"; + case CAM_ISP_TFE_OUT_RES_STATS_BF: + return "STATS_BF"; + case CAM_ISP_TFE_OUT_RES_STATS_AWB_BG: + return "STATS_AWB_BG"; + default: + return "CAM_ISP_Invalid_Resource_Type"; + } +} + static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data) { uint64_t ts = 0; @@ -471,9 +503,11 @@ static void __cam_isp_ctx_send_sof_timestamp( } static void __cam_isp_ctx_handle_buf_done_fail_log( - uint64_t request_id, struct cam_isp_ctx_req *req_isp) + uint64_t request_id, struct cam_isp_ctx_req *req_isp, + uint32_t isp_device_type) { int i; + const char *handle_type; if (req_isp->num_fence_map_out >= CAM_ISP_CTX_RES_MAX) { CAM_ERR(CAM_ISP, @@ -490,10 +524,18 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( "Resource Handles that fail to generate buf_done in prev frame"); for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) { + if (isp_device_type == CAM_IFE_DEVICE_TYPE) + handle_type = + __cam_isp_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + else + handle_type = + __cam_isp_tfe_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + CAM_WARN(CAM_ISP, "Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]", - __cam_isp_resource_handle_id_to_type( - req_isp->fence_map_out[i].resource_handle), + handle_type, req_isp->fence_map_out[i].resource_handle, req_isp->fence_map_out[i].sync_id); } @@ -512,6 +554,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; uint64_t buf_done_req_id; + const char *handle_type; trace_cam_buf_done("ISP", ctx, req); @@ -541,11 +584,18 @@ static int __cam_isp_ctx_handle_buf_done_for_request( } if (req_isp->fence_map_out[j].sync_id == -1) { + if (ctx_isp->isp_device_type == CAM_IFE_DEVICE_TYPE) + handle_type = + __cam_isp_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + else + handle_type = + __cam_isp_tfe_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + CAM_WARN(CAM_ISP, "Duplicate BUF_DONE for req %lld : i=%d, j=%d, res=%s", - req->request_id, i, j, - __cam_isp_resource_handle_id_to_type( - done->resource_handle[i])); + req->request_id, i, j, handle_type); if (done_next_req) { done_next_req->resource_handle @@ -1967,7 +2017,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state( active_req_isp = (struct cam_isp_ctx_req *) active_req->req_priv; __cam_isp_ctx_handle_buf_done_fail_log( - active_req->request_id, active_req_isp); + active_req->request_id, active_req_isp, + ctx_isp->isp_device_type); } rc = -EFAULT; @@ -4354,7 +4405,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx, struct cam_context *ctx_base, struct cam_req_mgr_kmd_ops *crm_node_intf, struct cam_hw_mgr_intf *hw_intf, - uint32_t ctx_id) + uint32_t ctx_id, + uint32_t isp_device_type) { int rc = -1; @@ -4378,6 +4430,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->substate_machine = cam_isp_ctx_activated_state_machine; ctx->substate_machine_irq = cam_isp_ctx_activated_state_machine_irq; ctx->init_timestamp = jiffies_to_msecs(jiffies); + ctx->isp_device_type = isp_device_type; for (i = 0; i < CAM_CTX_REQ_MAX; i++) { ctx->req_base[i].req_priv = &ctx->req_isp[i]; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 34f899f65b27..dc91ecd9ff5a 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ @@ -10,6 +10,7 @@ #include #include #include +#include #include "cam_context.h" #include "cam_isp_hw_mgr_intf.h" @@ -177,6 +178,7 @@ struct cam_isp_context_state_monitor { * @init_received: Indicate whether init config packet is received * @split_acquire: Indicate whether a separate acquire is expected * @init_timestamp: Timestamp at which this context is initialized + * @isp_device_type ISP device type * */ struct cam_isp_context { @@ -207,6 +209,7 @@ struct cam_isp_context { bool init_received; bool split_acquire; unsigned int init_timestamp; + uint32_t isp_device_type; }; /** @@ -218,13 +221,15 @@ struct cam_isp_context { * @bridge_ops: Bridge call back funciton * @hw_intf: ISP hw manager interface * @ctx_id: ID for this context + * @isp_device_type Isp device type * */ int cam_isp_context_init(struct cam_isp_context *ctx, struct cam_context *ctx_base, struct cam_req_mgr_kmd_ops *bridge_ops, struct cam_hw_mgr_intf *hw_intf, - uint32_t ctx_id); + uint32_t ctx_id, + uint32_t isp_device_type); /** * cam_isp_context_deinit() diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index b2e2b18f8f85..9a3729242b3b 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -117,12 +117,30 @@ static int cam_isp_dev_probe(struct platform_device *pdev) int i; struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; + const char *compat_str = NULL; + uint32_t isp_device_type; + int iommu_hdl = -1; + rc = of_property_read_string_index(pdev->dev.of_node, "arch-compat", 0, + (const char **)&compat_str); + g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; /* Initialize the v4l2 subdevice first. (create cam_node) */ - rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, + if (strnstr(compat_str, "ife", strlen(compat_str))) { + rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, CAM_IFE_DEVICE_TYPE); + isp_device_type = CAM_IFE_DEVICE_TYPE; + } else if (strnstr(compat_str, "tfe", strlen(compat_str))) { + rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, + CAM_TFE_DEVICE_TYPE); + isp_device_type = CAM_TFE_DEVICE_TYPE; + } else { + CAM_ERR(CAM_ISP, "Invalid ISP hw type %s", compat_str); + rc = -EINVAL; + goto err; + } + if (rc) { CAM_ERR(CAM_ISP, "ISP cam_subdev_probe failed!"); goto err; @@ -130,7 +148,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev) node = (struct cam_node *) g_isp_dev.sd.token; memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf)); - rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf, &iommu_hdl); + rc = cam_isp_hw_mgr_init(compat_str, &hw_mgr_intf, &iommu_hdl); if (rc != 0) { CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!"); goto unregister; @@ -141,7 +159,8 @@ static int cam_isp_dev_probe(struct platform_device *pdev) &g_isp_dev.ctx[i], &node->crm_node_intf, &node->hw_mgr_intf, - i); + i, + isp_device_type); if (rc) { CAM_ERR(CAM_ISP, "ISP context init failed!"); goto unregister; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c index b1567d6b9cd8..4c83fa6b9402 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c @@ -1,26 +1,25 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_isp_hw_mgr_intf.h" #include "cam_ife_hw_mgr.h" #include "cam_debug_util.h" +#include "cam_tfe_hw_mgr.h" -int cam_isp_hw_mgr_init(struct device_node *of_node, +int cam_isp_hw_mgr_init(const char *device_name_str, struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl) { int rc = 0; - const char *compat_str = NULL; - rc = of_property_read_string_index(of_node, "arch-compat", 0, - (const char **)&compat_str); - - if (strnstr(compat_str, "ife", strlen(compat_str))) + if (strnstr(device_name_str, "ife", strlen(device_name_str))) rc = cam_ife_hw_mgr_init(hw_mgr, iommu_hdl); + else if (strnstr(device_name_str, "tfe", strlen(device_name_str))) + rc = cam_tfe_hw_mgr_init(hw_mgr, iommu_hdl); else { - CAM_ERR(CAM_ISP, "Invalid ISP hw type"); + CAM_ERR(CAM_ISP, "Invalid ISP hw type :%s", device_name_str); rc = -EINVAL; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c new file mode 100644 index 000000000000..bac81f24363c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -0,0 +1,5282 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "cam_smmu_api.h" +#include "cam_req_mgr_workq.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_isp_hw.h" +#include "cam_tfe_csid_hw_intf.h" +#include "cam_tfe_hw_intf.h" +#include "cam_isp_packet_parser.h" +#include "cam_tfe_hw_mgr.h" +#include "cam_cdm_intf_api.h" +#include "cam_packet_util.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_mem_mgr_api.h" +#include "cam_common_util.h" +#include "cam_compat.h" + +#define CAM_TFE_HW_ENTRIES_MAX 20 +#define CAM_TFE_HW_CONFIG_TIMEOUT 60 + +#define TZ_SVC_SMMU_PROGRAM 0x15 +#define TZ_SAFE_SYSCALL_ID 0x3 +#define CAM_TFE_SAFE_DISABLE 0 +#define CAM_TFE_SAFE_ENABLE 1 +#define SMMU_SE_TFE 0 + + +static struct cam_tfe_hw_mgr g_tfe_hw_mgr; + +static int cam_tfe_hw_mgr_event_handler( + void *priv, + uint32_t evt_id, + void *evt_info); + +static int cam_tfe_mgr_regspace_data_cb(uint32_t reg_base_type, + void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr, + uint32_t *reg_base_idx) +{ + int rc = 0; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_isp_resource_node *res; + struct cam_tfe_hw_mgr_ctx *ctx = + (struct cam_tfe_hw_mgr_ctx *) hw_mgr_ctx; + + *soc_info_ptr = NULL; + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + if (hw_mgr_res->res_id != CAM_ISP_HW_TFE_IN_CAMIF) + continue; + + switch (reg_base_type) { + case CAM_REG_DUMP_BASE_TYPE_CAMNOC: + case CAM_REG_DUMP_BASE_TYPE_ISP_LEFT: + if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]) + continue; + + res = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]; + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, + &soc_info, sizeof(void *)); + + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in regspace data query split idx: %d rc : %d", + CAM_ISP_HW_SPLIT_LEFT, rc); + return rc; + } + + if (reg_base_type == CAM_REG_DUMP_BASE_TYPE_ISP_LEFT) + *reg_base_idx = 0; + else + *reg_base_idx = 1; + + *soc_info_ptr = soc_info; + break; + case CAM_REG_DUMP_BASE_TYPE_ISP_RIGHT: + if (!hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]) + continue; + + + res = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]; + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, + &soc_info, sizeof(void *)); + + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in regspace data query split idx: %d rc : %d", + CAM_ISP_HW_SPLIT_RIGHT, rc); + return rc; + } + + *reg_base_idx = 0; + *soc_info_ptr = soc_info; + break; + default: + CAM_ERR(CAM_ISP, + "Unrecognized reg base type: %d", + reg_base_type); + return -EINVAL; + } + } + + return rc; +} + +static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx, + struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf, + uint32_t meta_type) +{ + int rc = 0, i; + + if (!num_reg_dump_buf || !reg_dump_buf_desc) { + CAM_DBG(CAM_ISP, + "Invalid args for reg dump req_id: [%llu] ctx idx: [%u] meta_type: [%u] num_reg_dump_buf: [%u] reg_dump_buf_desc: [%pK]", + ctx->applied_req_id, ctx->ctx_index, meta_type, + num_reg_dump_buf, reg_dump_buf_desc); + return rc; + } + + if (!atomic_read(&ctx->cdm_done)) + CAM_WARN_RATE_LIMIT(CAM_ISP, + "Reg dump values might be from more than one request"); + + for (i = 0; i < num_reg_dump_buf; i++) { + CAM_DBG(CAM_ISP, "Reg dump cmd meta data: %u req_type: %u", + reg_dump_buf_desc[i].meta_data, meta_type); + if (reg_dump_buf_desc[i].meta_data == meta_type) { + rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, + ®_dump_buf_desc[i], + ctx->applied_req_id, + cam_tfe_mgr_regspace_data_cb); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", + i, rc, ctx->applied_req_id, meta_type); + return rc; + } + } + } + + return 0; +} + +static int cam_tfe_mgr_get_hw_caps(void *hw_mgr_priv, + void *hw_caps_args) +{ + int rc = 0; + int i; + uint32_t num_dev = 0; + struct cam_tfe_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query = hw_caps_args; + struct cam_isp_tfe_query_cap_cmd query_isp; + + CAM_DBG(CAM_ISP, "enter"); + + if (copy_from_user(&query_isp, + u64_to_user_ptr(query->caps_handle), + sizeof(struct cam_isp_tfe_query_cap_cmd))) { + rc = -EFAULT; + return rc; + } + + query_isp.device_iommu.non_secure = hw_mgr->mgr_common.img_iommu_hdl; + query_isp.device_iommu.secure = hw_mgr->mgr_common.img_iommu_hdl_secure; + query_isp.cdm_iommu.non_secure = hw_mgr->mgr_common.cmd_iommu_hdl; + query_isp.cdm_iommu.secure = hw_mgr->mgr_common.cmd_iommu_hdl_secure; + + for (i = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { + if (!hw_mgr->csid_devices[i]) + continue; + + query_isp.dev_caps[i].hw_type = CAM_ISP_TFE_HW_TFE; + query_isp.dev_caps[i].hw_version.major = 5; + query_isp.dev_caps[i].hw_version.minor = 3; + query_isp.dev_caps[i].hw_version.incr = 0; + + /* + * device number is based on number of full tfe + * if pix is not supported, set reserve to 1 + */ + if (hw_mgr->tfe_csid_dev_caps[i].num_pix) { + query_isp.dev_caps[i].hw_version.reserved = 0; + num_dev++; + } else + query_isp.dev_caps[i].hw_version.reserved = 1; + } + + query_isp.num_dev = num_dev; + + if (copy_to_user(u64_to_user_ptr(query->caps_handle), + &query_isp, sizeof(struct cam_isp_tfe_query_cap_cmd))) + rc = -EFAULT; + + CAM_DBG(CAM_ISP, "exit rc :%d", rc); + + return rc; +} + +static int cam_tfe_hw_mgr_is_rdi_res(uint32_t res_id) +{ + int rc = 0; + + switch (res_id) { + case CAM_ISP_TFE_OUT_RES_RDI_0: + case CAM_ISP_TFE_OUT_RES_RDI_1: + case CAM_ISP_TFE_OUT_RES_RDI_2: + rc = 1; + break; + default: + break; + } + + return rc; +} + +static int cam_tfe_hw_mgr_convert_rdi_out_res_id_to_in_res(int res_id) +{ + if (res_id == CAM_ISP_TFE_OUT_RES_RDI_0) + return CAM_ISP_HW_TFE_IN_RDI0; + else if (res_id == CAM_ISP_TFE_OUT_RES_RDI_1) + return CAM_ISP_HW_TFE_IN_RDI1; + else if (res_id == CAM_ISP_TFE_OUT_RES_RDI_2) + return CAM_ISP_HW_TFE_IN_RDI1; + + return CAM_ISP_HW_TFE_IN_MAX; +} + +static int cam_tfe_hw_mgr_reset_csid_res( + struct cam_isp_hw_mgr_res *isp_hw_res) +{ + int i; + int rc = 0; + struct cam_hw_intf *hw_intf; + struct cam_tfe_csid_reset_cfg_args csid_reset_args; + + csid_reset_args.reset_type = CAM_TFE_CSID_RESET_PATH; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + csid_reset_args.node_res = isp_hw_res->hw_res[i]; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "Resetting csid hardware %d", + hw_intf->hw_idx); + if (hw_intf->hw_ops.reset) { + rc = hw_intf->hw_ops.reset(hw_intf->hw_priv, + &csid_reset_args, + sizeof(struct cam_tfe_csid_reset_cfg_args)); + if (rc <= 0) + goto err; + } + } + + return 0; +err: + CAM_ERR(CAM_ISP, "RESET HW res failed: (type:%d, id:%d)", + isp_hw_res->res_type, isp_hw_res->res_id); + return rc; +} + +static int cam_tfe_hw_mgr_init_hw_res( + struct cam_isp_hw_mgr_res *isp_hw_res) +{ + int i; + int rc = -EINVAL; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + if (hw_intf->hw_ops.init) { + rc = hw_intf->hw_ops.init(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + if (rc) + goto err; + } + } + + return 0; +err: + CAM_ERR(CAM_ISP, "INIT HW res failed: (type:%d, id:%d)", + isp_hw_res->res_type, isp_hw_res->res_id); + return rc; +} + +static int cam_tfe_hw_mgr_start_hw_res( + struct cam_isp_hw_mgr_res *isp_hw_res, + struct cam_tfe_hw_mgr_ctx *ctx) +{ + int i; + int rc = -EINVAL; + struct cam_hw_intf *hw_intf; + + /* Start slave (which is right split) first */ + for (i = CAM_ISP_HW_SPLIT_MAX - 1; i >= 0; i--) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.start) { + rc = hw_intf->hw_ops.start(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start HW resources"); + goto err; + } + CAM_DBG(CAM_ISP, "Start hw type:%d HW idx %d Res %d", + hw_intf->hw_type, + hw_intf->hw_idx, + isp_hw_res->hw_res[i]->res_id); + } else { + CAM_ERR(CAM_ISP, "function null"); + goto err; + } + } + + return 0; +err: + CAM_ERR(CAM_ISP, "Start hw res failed (type:%d, id:%d)", + isp_hw_res->res_type, isp_hw_res->res_id); + return rc; +} + +static void cam_tfe_hw_mgr_stop_hw_res( + struct cam_isp_hw_mgr_res *isp_hw_res) +{ + int i; + struct cam_hw_intf *hw_intf; + uint32_t dummy_args; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + + if (isp_hw_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING) + continue; + + if (hw_intf->hw_ops.stop) + hw_intf->hw_ops.stop(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + else + CAM_ERR(CAM_ISP, "stop null"); + if (hw_intf->hw_ops.process_cmd && + isp_hw_res->res_type == CAM_ISP_RESOURCE_TFE_OUT) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ, + &dummy_args, sizeof(dummy_args)); + } + } +} + +static void cam_tfe_hw_mgr_deinit_hw_res( + struct cam_isp_hw_mgr_res *isp_hw_res) +{ + int i; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.deinit) + hw_intf->hw_ops.deinit(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + } +} + +static void cam_tfe_hw_mgr_deinit_hw( + struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + + if (!ctx->init_done) { + CAM_WARN(CAM_ISP, "ctx is not in init state"); + return; + } + + /* Deinit TFE CSID hw */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + CAM_DBG(CAM_ISP, "Going to DeInit TFE CSID"); + cam_tfe_hw_mgr_deinit_hw_res(hw_mgr_res); + } + + /* Deint TFE HW */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + cam_tfe_hw_mgr_deinit_hw_res(hw_mgr_res); + } + + if (ctx->is_tpg) + cam_tfe_hw_mgr_deinit_hw_res(&ctx->res_list_tpg); + + ctx->init_done = false; +} + +static int cam_tfe_hw_mgr_init_hw( + struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + int rc = 0; + + if (ctx->is_tpg) { + CAM_DBG(CAM_ISP, "INIT TPG ... in ctx id:%d", + ctx->ctx_index); + rc = cam_tfe_hw_mgr_init_hw_res(&ctx->res_list_tpg); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT TFE TPG(id :%d)", + ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx); + goto deinit; + } + } + + CAM_DBG(CAM_ISP, "INIT TFE csid ... in ctx id:%d", + ctx->ctx_index); + /* INIT TFE csid */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT TFE CSID(id :%d)", + hw_mgr_res->res_id); + goto deinit; + } + } + + /* INIT TFE IN */ + CAM_DBG(CAM_ISP, "INIT TFE in resource ctx id:%d", + ctx->ctx_index); + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_init_hw_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT TFE SRC (%d)", + hw_mgr_res->res_id); + goto deinit; + } + } + + return rc; +deinit: + ctx->init_done = true; + cam_tfe_hw_mgr_deinit_hw(ctx); + return rc; +} + +static int cam_tfe_hw_mgr_put_res( + struct list_head *src_list, + struct cam_isp_hw_mgr_res **res) +{ + struct cam_isp_hw_mgr_res *res_ptr = NULL; + + res_ptr = *res; + if (res_ptr) + list_add_tail(&res_ptr->list, src_list); + + return 0; +} + +static int cam_tfe_hw_mgr_get_res( + struct list_head *src_list, + struct cam_isp_hw_mgr_res **res) +{ + int rc = 0; + struct cam_isp_hw_mgr_res *res_ptr = NULL; + + if (!list_empty(src_list)) { + res_ptr = list_first_entry(src_list, + struct cam_isp_hw_mgr_res, list); + list_del_init(&res_ptr->list); + } else { + CAM_ERR(CAM_ISP, "No more free tfe hw mgr ctx"); + rc = -EINVAL; + } + *res = res_ptr; + + return rc; +} + +static int cam_tfe_hw_mgr_free_hw_res( + struct cam_isp_hw_mgr_res *isp_hw_res) +{ + int rc = 0; + int i; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.release) { + rc = hw_intf->hw_ops.release(hw_intf->hw_priv, + isp_hw_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + if (rc) + CAM_ERR(CAM_ISP, + "Release hw resource id %d failed", + isp_hw_res->res_id); + isp_hw_res->hw_res[i] = NULL; + } else + CAM_ERR(CAM_ISP, "Release null"); + } + /* caller should make sure the resource is in a list */ + list_del_init(&isp_hw_res->list); + memset(isp_hw_res, 0, sizeof(*isp_hw_res)); + INIT_LIST_HEAD(&isp_hw_res->list); + + return 0; +} + +static int cam_tfe_mgr_csid_stop_hw( + struct cam_tfe_hw_mgr_ctx *ctx, struct list_head *stop_list, + uint32_t base_idx, uint32_t stop_cmd) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_isp_resource_node *stop_res[CAM_TFE_CSID_PATH_RES_MAX]; + struct cam_tfe_csid_hw_stop_args stop; + struct cam_hw_intf *hw_intf; + uint32_t i, cnt; + + cnt = 0; + list_for_each_entry(hw_mgr_res, stop_list, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i] || + (hw_mgr_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING)) + continue; + + isp_res = hw_mgr_res->hw_res[i]; + if (isp_res->hw_intf->hw_idx != base_idx) + continue; + CAM_DBG(CAM_ISP, "base_idx %d res_id %d cnt %u", + base_idx, isp_res->res_id, cnt); + stop_res[cnt] = isp_res; + cnt++; + } + } + + if (cnt) { + hw_intf = stop_res[0]->hw_intf; + stop.num_res = cnt; + stop.node_res = stop_res; + stop.stop_cmd = stop_cmd; + hw_intf->hw_ops.stop(hw_intf->hw_priv, &stop, sizeof(stop)); + } + + return 0; +} + +static int cam_tfe_hw_mgr_release_hw_for_ctx( + struct cam_tfe_hw_mgr_ctx *tfe_ctx) +{ + uint32_t i; + int rc = 0; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res_temp; + struct cam_hw_intf *hw_intf; + + /* tfe out resource */ + for (i = 0; i < CAM_TFE_HW_OUT_RES_MAX; i++) + cam_tfe_hw_mgr_free_hw_res(&tfe_ctx->res_list_tfe_out[i]); + + /* tfe in resource */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &tfe_ctx->res_list_tfe_in, list) { + cam_tfe_hw_mgr_free_hw_res(hw_mgr_res); + cam_tfe_hw_mgr_put_res(&tfe_ctx->free_res_list, &hw_mgr_res); + } + + /* tfe csid resource */ + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &tfe_ctx->res_list_tfe_csid, list) { + cam_tfe_hw_mgr_free_hw_res(hw_mgr_res); + cam_tfe_hw_mgr_put_res(&tfe_ctx->free_res_list, &hw_mgr_res); + } + + /* release tpg resource */ + if (tfe_ctx->is_tpg) { + hw_intf = tfe_ctx->res_list_tpg.hw_res[0]->hw_intf; + if (hw_intf->hw_ops.release) { + rc = hw_intf->hw_ops.release(hw_intf->hw_priv, + tfe_ctx->res_list_tpg.hw_res[0], + sizeof(struct cam_isp_resource_node)); + if (rc) + CAM_ERR(CAM_ISP, + "TPG Release hw failed"); + tfe_ctx->res_list_tpg.hw_res[0] = NULL; + } else + CAM_ERR(CAM_ISP, "TPG resource Release null"); + } + + /* clean up the callback function */ + tfe_ctx->common.cb_priv = NULL; + memset(tfe_ctx->common.event_cb, 0, sizeof(tfe_ctx->common.event_cb)); + + CAM_DBG(CAM_ISP, "release context completed ctx id:%d", + tfe_ctx->ctx_index); + + return 0; +} + + +static int cam_tfe_hw_mgr_put_ctx( + struct list_head *src_list, + struct cam_tfe_hw_mgr_ctx **tfe_ctx) +{ + struct cam_tfe_hw_mgr_ctx *ctx_ptr = NULL; + + mutex_lock(&g_tfe_hw_mgr.ctx_mutex); + ctx_ptr = *tfe_ctx; + if (ctx_ptr) + list_add_tail(&ctx_ptr->list, src_list); + *tfe_ctx = NULL; + mutex_unlock(&g_tfe_hw_mgr.ctx_mutex); + return 0; +} + +static int cam_tfe_hw_mgr_get_ctx( + struct list_head *src_list, + struct cam_tfe_hw_mgr_ctx **tfe_ctx) +{ + int rc = 0; + struct cam_tfe_hw_mgr_ctx *ctx_ptr = NULL; + + mutex_lock(&g_tfe_hw_mgr.ctx_mutex); + if (!list_empty(src_list)) { + ctx_ptr = list_first_entry(src_list, + struct cam_tfe_hw_mgr_ctx, list); + list_del_init(&ctx_ptr->list); + } else { + CAM_ERR(CAM_ISP, "No more free tfe hw mgr ctx"); + rc = -EINVAL; + } + *tfe_ctx = ctx_ptr; + mutex_unlock(&g_tfe_hw_mgr.ctx_mutex); + + return rc; +} + +static void cam_tfe_hw_mgr_dump_all_ctx(void) +{ + uint32_t i; + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_isp_hw_mgr_res *hw_mgr_res; + + mutex_lock(&g_tfe_hw_mgr.ctx_mutex); + list_for_each_entry(ctx, &g_tfe_hw_mgr.used_ctx_list, list) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "ctx id:%d is_dual:%d is_tpg:%d num_base:%d rdi only:%d", + ctx->ctx_index, ctx->is_dual, ctx->is_tpg, + ctx->num_base, ctx->is_rdi_only_context); + + if (ctx->res_list_tpg.res_type == CAM_ISP_RESOURCE_TPG) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "Acquired TPG HW:%d", + ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx); + } + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, + list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (hw_mgr_res->hw_res[i]) + continue; + + CAM_INFO_RATE_LIMIT(CAM_ISP, + "csid:%d res_type:%d res_id:%d res_state:%d", + hw_mgr_res->hw_res[i]->hw_intf->hw_idx, + hw_mgr_res->hw_res[i]->res_type, + hw_mgr_res->hw_res[i]->res_id, + hw_mgr_res->hw_res[i]->res_state); + } + } + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, + list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (hw_mgr_res->hw_res[i]) + continue; + + CAM_INFO_RATE_LIMIT(CAM_ISP, + "TFE IN:%d res_type:%d res_id:%d res_state:%d", + hw_mgr_res->hw_res[i]->hw_intf->hw_idx, + hw_mgr_res->hw_res[i]->res_type, + hw_mgr_res->hw_res[i]->res_id, + hw_mgr_res->hw_res[i]->res_state); + } + } + } + mutex_unlock(&g_tfe_hw_mgr.ctx_mutex); + +} + +static void cam_tfe_mgr_add_base_info( + struct cam_tfe_hw_mgr_ctx *ctx, + enum cam_isp_hw_split_id split_id, + uint32_t base_idx) +{ + uint32_t i; + + if (!ctx->num_base) { + ctx->base[0].split_id = split_id; + ctx->base[0].idx = base_idx; + ctx->num_base++; + CAM_DBG(CAM_ISP, + "Add split id = %d for base idx = %d num_base=%d", + split_id, base_idx, ctx->num_base); + } else { + /*Check if base index already exists in the list */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == base_idx) { + if (split_id != CAM_ISP_HW_SPLIT_MAX && + ctx->base[i].split_id == + CAM_ISP_HW_SPLIT_MAX) + ctx->base[i].split_id = split_id; + + break; + } + } + + if (i == ctx->num_base) { + ctx->base[ctx->num_base].split_id = split_id; + ctx->base[ctx->num_base].idx = base_idx; + ctx->num_base++; + CAM_DBG(CAM_ISP, + "Add split_id=%d for base idx=%d num_base=%d", + split_id, base_idx, ctx->num_base); + } + } +} + +static int cam_tfe_mgr_process_base_info( + struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *res = NULL; + uint32_t i; + + if (list_empty(&ctx->res_list_tfe_in)) { + CAM_ERR(CAM_ISP, "tfe in list empty"); + return -ENODEV; + } + + /* TFE in resources */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) + continue; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + res = hw_mgr_res->hw_res[i]; + cam_tfe_mgr_add_base_info(ctx, i, + res->hw_intf->hw_idx); + CAM_DBG(CAM_ISP, "add base info for hw %d", + res->hw_intf->hw_idx); + } + } + CAM_DBG(CAM_ISP, "ctx base num = %d", ctx->num_base); + + return 0; +} + +static int cam_tfe_hw_mgr_acquire_res_tfe_out_rdi( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_hw_mgr_res *tfe_in_res, + struct cam_isp_tfe_in_port_info *in_port) +{ + int rc = -EINVAL; + struct cam_tfe_acquire_args tfe_acquire; + struct cam_isp_tfe_out_port_info *out_port = NULL; + struct cam_isp_hw_mgr_res *tfe_out_res; + struct cam_hw_intf *hw_intf; + uint32_t i, tfe_out_res_id, tfe_in_res_id; + + /* take left resource */ + tfe_in_res_id = tfe_in_res->hw_res[0]->res_id; + + switch (tfe_in_res_id) { + case CAM_ISP_HW_TFE_IN_RDI0: + tfe_out_res_id = CAM_ISP_TFE_OUT_RES_RDI_0; + break; + case CAM_ISP_HW_TFE_IN_RDI1: + tfe_out_res_id = CAM_ISP_TFE_OUT_RES_RDI_1; + break; + case CAM_ISP_HW_TFE_IN_RDI2: + tfe_out_res_id = CAM_ISP_TFE_OUT_RES_RDI_2; + break; + default: + CAM_ERR(CAM_ISP, "invalid resource type"); + goto err; + } + CAM_DBG(CAM_ISP, "tfe_in_res_id = %d, tfe_out_red_id = %d", + tfe_in_res_id, tfe_out_res_id); + + tfe_acquire.rsrc_type = CAM_ISP_RESOURCE_TFE_OUT; + tfe_acquire.tasklet = tfe_ctx->common.tasklet_info; + + tfe_out_res = &tfe_ctx->res_list_tfe_out[tfe_out_res_id & 0xFF]; + for (i = 0; i < in_port->num_out_res; i++) { + out_port = &in_port->data[i]; + + CAM_DBG(CAM_ISP, "i = %d, tfe_out_res_id = %d, out_port: %d", + i, tfe_out_res_id, out_port->res_id); + + if (tfe_out_res_id != out_port->res_id) + continue; + + tfe_acquire.tfe_out.cdm_ops = tfe_ctx->cdm_ops; + tfe_acquire.priv = tfe_ctx; + tfe_acquire.tfe_out.out_port_info = out_port; + tfe_acquire.tfe_out.split_id = CAM_ISP_HW_SPLIT_LEFT; + tfe_acquire.tfe_out.unique_id = tfe_ctx->ctx_index; + tfe_acquire.tfe_out.is_dual = 0; + tfe_acquire.event_cb = cam_tfe_hw_mgr_event_handler; + hw_intf = tfe_in_res->hw_res[0]->hw_intf; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &tfe_acquire, + sizeof(struct cam_tfe_acquire_args)); + if (rc) { + CAM_ERR(CAM_ISP, "Can not acquire out resource 0x%x", + out_port->res_id); + goto err; + } + break; + } + + if (i == in_port->num_out_res) { + CAM_ERR(CAM_ISP, + "Cannot acquire out resource, i=%d, num_out_res=%d", + i, in_port->num_out_res); + goto err; + } + + tfe_out_res->hw_res[0] = tfe_acquire.tfe_out.rsrc_node; + tfe_out_res->is_dual_isp = 0; + tfe_out_res->res_id = tfe_out_res_id; + tfe_out_res->res_type = CAM_ISP_RESOURCE_TFE_OUT; + tfe_in_res->num_children++; + + return 0; +err: + return rc; +} + +static int cam_tfe_hw_mgr_acquire_res_tfe_out_pixel( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_hw_mgr_res *tfe_in_res, + struct cam_isp_tfe_in_port_info *in_port) +{ + int rc = -EINVAL; + uint32_t i, j, k; + struct cam_tfe_acquire_args tfe_acquire; + struct cam_isp_tfe_out_port_info *out_port; + struct cam_isp_hw_mgr_res *tfe_out_res; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < in_port->num_out_res; i++) { + out_port = &in_port->data[i]; + k = out_port->res_id & 0xFF; + if (k >= CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "invalid output resource type 0x%x", + out_port->res_id); + continue; + } + + if (cam_tfe_hw_mgr_is_rdi_res(out_port->res_id)) + continue; + + CAM_DBG(CAM_ISP, "res_type 0x%x", out_port->res_id); + + tfe_out_res = &tfe_ctx->res_list_tfe_out[k]; + tfe_out_res->is_dual_isp = in_port->usage_type; + + tfe_acquire.rsrc_type = CAM_ISP_RESOURCE_TFE_OUT; + tfe_acquire.tasklet = tfe_ctx->common.tasklet_info; + tfe_acquire.tfe_out.cdm_ops = tfe_ctx->cdm_ops; + tfe_acquire.priv = tfe_ctx; + tfe_acquire.tfe_out.out_port_info = out_port; + tfe_acquire.tfe_out.is_dual = tfe_in_res->is_dual_isp; + tfe_acquire.tfe_out.unique_id = tfe_ctx->ctx_index; + tfe_acquire.event_cb = cam_tfe_hw_mgr_event_handler; + + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { + if (!tfe_in_res->hw_res[j]) + continue; + + hw_intf = tfe_in_res->hw_res[j]->hw_intf; + + if (j == CAM_ISP_HW_SPLIT_LEFT) { + tfe_acquire.tfe_out.split_id = + CAM_ISP_HW_SPLIT_LEFT; + if (tfe_in_res->is_dual_isp) + tfe_acquire.tfe_out.is_master = 1; + else + tfe_acquire.tfe_out.is_master = 0; + } else { + tfe_acquire.tfe_out.split_id = + CAM_ISP_HW_SPLIT_RIGHT; + tfe_acquire.tfe_out.is_master = 0; + } + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &tfe_acquire, + sizeof(struct cam_tfe_acquire_args)); + if (rc) { + CAM_ERR(CAM_ISP, + "Can not acquire out resource 0x%x", + out_port->res_id); + goto err; + } + + tfe_out_res->hw_res[j] = + tfe_acquire.tfe_out.rsrc_node; + CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x", + tfe_out_res->hw_res[j]->res_type, + tfe_out_res->hw_res[j]->res_id); + + } + tfe_out_res->res_type = CAM_ISP_RESOURCE_TFE_OUT; + tfe_out_res->res_id = out_port->res_id; + tfe_in_res->num_children++; + } + + return 0; +err: + /* release resource at the entry function */ + return rc; +} + +static int cam_tfe_hw_mgr_acquire_res_tfe_out( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info *in_port) +{ + int rc = -EINVAL; + struct cam_isp_hw_mgr_res *tfe_in_res; + + list_for_each_entry(tfe_in_res, &tfe_ctx->res_list_tfe_in, list) { + if (tfe_in_res->num_children) + continue; + + switch (tfe_in_res->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + rc = cam_tfe_hw_mgr_acquire_res_tfe_out_pixel(tfe_ctx, + tfe_in_res, in_port); + break; + case CAM_ISP_HW_TFE_IN_RDI0: + case CAM_ISP_HW_TFE_IN_RDI1: + case CAM_ISP_HW_TFE_IN_RDI2: + rc = cam_tfe_hw_mgr_acquire_res_tfe_out_rdi(tfe_ctx, + tfe_in_res, in_port); + break; + default: + CAM_ERR(CAM_ISP, "Unknown TFE SRC resource: %d", + tfe_in_res->res_id); + break; + } + if (rc) + goto err; + } + + return 0; +err: + /* release resource on entry function */ + return rc; +} + +static int cam_tfe_hw_mgr_acquire_res_tfe_in( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info *in_port, + uint32_t *pdaf_enable) +{ + int rc = -EINVAL; + int i; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_isp_hw_mgr_res *tfe_src_res; + struct cam_tfe_acquire_args tfe_acquire; + struct cam_hw_intf *hw_intf; + struct cam_tfe_hw_mgr *tfe_hw_mgr; + + tfe_hw_mgr = tfe_ctx->hw_mgr; + + list_for_each_entry(csid_res, &tfe_ctx->res_list_tfe_csid, list) { + if (csid_res->num_children) + continue; + + rc = cam_tfe_hw_mgr_get_res(&tfe_ctx->free_res_list, + &tfe_src_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto err; + } + cam_tfe_hw_mgr_put_res(&tfe_ctx->res_list_tfe_in, + &tfe_src_res); + tfe_src_res->hw_res[0] = NULL; + tfe_src_res->hw_res[1] = NULL; + + tfe_acquire.rsrc_type = CAM_ISP_RESOURCE_TFE_IN; + tfe_acquire.tasklet = tfe_ctx->common.tasklet_info; + tfe_acquire.tfe_in.cdm_ops = tfe_ctx->cdm_ops; + tfe_acquire.tfe_in.in_port = in_port; + tfe_acquire.tfe_in.camif_pd_enable = *pdaf_enable; + tfe_acquire.priv = tfe_ctx; + tfe_acquire.event_cb = cam_tfe_hw_mgr_event_handler; + + switch (csid_res->res_id) { + case CAM_TFE_CSID_PATH_RES_IPP: + tfe_acquire.tfe_in.res_id = + CAM_ISP_HW_TFE_IN_CAMIF; + + if (csid_res->is_dual_isp) + tfe_acquire.tfe_in.sync_mode = + CAM_ISP_HW_SYNC_MASTER; + else + tfe_acquire.tfe_in.sync_mode = + CAM_ISP_HW_SYNC_NONE; + + break; + case CAM_TFE_CSID_PATH_RES_RDI_0: + tfe_acquire.tfe_in.res_id = CAM_ISP_HW_TFE_IN_RDI0; + tfe_acquire.tfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + case CAM_TFE_CSID_PATH_RES_RDI_1: + tfe_acquire.tfe_in.res_id = CAM_ISP_HW_TFE_IN_RDI1; + tfe_acquire.tfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + case CAM_TFE_CSID_PATH_RES_RDI_2: + tfe_acquire.tfe_in.res_id = CAM_ISP_HW_TFE_IN_RDI2; + tfe_acquire.tfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + break; + default: + CAM_ERR(CAM_ISP, "Wrong TFE CSID Resource Node"); + goto err; + } + tfe_src_res->res_type = tfe_acquire.rsrc_type; + tfe_src_res->res_id = tfe_acquire.tfe_in.res_id; + tfe_src_res->is_dual_isp = csid_res->is_dual_isp; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!csid_res->hw_res[i]) + continue; + + hw_intf = tfe_hw_mgr->tfe_devices[ + csid_res->hw_res[i]->hw_intf->hw_idx]; + + /* fill in more acquire information as needed */ + /* slave Camif resource, */ + if (i == CAM_ISP_HW_SPLIT_RIGHT && + tfe_src_res->is_dual_isp) { + tfe_acquire.tfe_in.sync_mode = + CAM_ISP_HW_SYNC_SLAVE; + tfe_acquire.tfe_in.dual_tfe_sync_sel_idx = + csid_res->hw_res[0]->hw_intf->hw_idx; + } else if (i == CAM_ISP_HW_SPLIT_LEFT && + tfe_src_res->is_dual_isp) + tfe_acquire.tfe_in.dual_tfe_sync_sel_idx = + csid_res->hw_res[1]->hw_intf->hw_idx; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &tfe_acquire, + sizeof(struct cam_tfe_acquire_args)); + if (rc) { + CAM_ERR(CAM_ISP, + "Can not acquire TFE HW res %d", + csid_res->res_id); + goto err; + } + tfe_src_res->hw_res[i] = tfe_acquire.tfe_in.rsrc_node; + CAM_DBG(CAM_ISP, + "acquire success TFE:%d res type :0x%x res id:0x%x", + hw_intf->hw_idx, + tfe_src_res->hw_res[i]->res_type, + tfe_src_res->hw_res[i]->res_id); + + } + csid_res->num_children++; + } + + return 0; +err: + /* release resource at the entry function */ + return rc; +} + +static int cam_tfe_hw_mgr_acquire_res_tfe_csid_pxl( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info *in_port) +{ + int rc = -EINVAL; + int i, j; + uint32_t acquired_cnt = 0; + struct cam_tfe_hw_mgr *tfe_hw_mgr; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_csid_hw_reserve_resource_args csid_acquire; + enum cam_tfe_csid_path_res_id path_res_id; + struct cam_isp_hw_mgr_res *csid_res_temp, *csid_res_iterator; + struct cam_isp_tfe_out_port_info *out_port = NULL; + + tfe_hw_mgr = tfe_ctx->hw_mgr; + /* get csid resource */ + path_res_id = CAM_TFE_CSID_PATH_RES_IPP; + + rc = cam_tfe_hw_mgr_get_res(&tfe_ctx->free_res_list, &csid_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto end; + } + + csid_res_temp = csid_res; + + csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_acquire.res_id = path_res_id; + csid_acquire.in_port = in_port; + csid_acquire.out_port = in_port->data; + csid_acquire.node_res = NULL; + csid_acquire.event_cb_prv = tfe_ctx; + csid_acquire.event_cb = cam_tfe_hw_mgr_event_handler; + if (in_port->num_out_res) + out_port = &(in_port->data[0]); + + if (tfe_ctx->is_tpg) { + if (tfe_ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx == 0) + csid_acquire.phy_sel = CAM_ISP_TFE_IN_RES_PHY_0; + else + csid_acquire.phy_sel = CAM_ISP_TFE_IN_RES_PHY_1; + } + + if (in_port->usage_type) + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_MASTER; + else + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; + + /* Try acquiring CSID resource from previously acquired HW */ + list_for_each_entry(csid_res_iterator, &tfe_ctx->res_list_tfe_csid, + list) { + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!csid_res_iterator->hw_res[i]) + continue; + + if (csid_res_iterator->is_secure == 1 || + (csid_res_iterator->is_secure == 0 && + in_port->num_out_res && + out_port->secure_mode == 1)) + continue; + + hw_intf = csid_res_iterator->hw_res[i]->hw_intf; + csid_acquire.master_idx = hw_intf->hw_idx; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_DBG(CAM_ISP, + "No tfe csid resource from hw %d", + hw_intf->hw_idx); + continue; + } + + csid_res_temp->hw_res[acquired_cnt++] = + csid_acquire.node_res; + + CAM_DBG(CAM_ISP, + "acquired from old csid(%s)=%d CSID rsrc successfully", + (i == 0) ? "left" : "right", + hw_intf->hw_idx); + + if (in_port->usage_type && acquired_cnt == 1 && + path_res_id == CAM_TFE_CSID_PATH_RES_IPP) + /* + * Continue to acquire Right for IPP. + * Dual TFE for RDI is not currently + * supported. + */ + continue; + + if (acquired_cnt) + /* + * If successfully acquired CSID from + * previously acquired HW, skip the next + * part + */ + goto acquire_successful; + } + } + + /* + * If successfully acquired CSID from + * previously acquired HW, skip the next + * part + */ + if (acquired_cnt) + goto acquire_successful; + + /* Acquire Left if not already acquired */ + if (in_port->usage_type) { + for (i = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { + if (!tfe_hw_mgr->csid_devices[i]) + continue; + + hw_intf = tfe_hw_mgr->csid_devices[i]; + csid_acquire.master_idx = hw_intf->hw_idx; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) + continue; + else { + csid_res_temp->hw_res[acquired_cnt++] = + csid_acquire.node_res; + break; + } + } + + if (i == CAM_TFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) { + CAM_ERR(CAM_ISP, + "Can not acquire tfe csid path resource %d", + path_res_id); + goto put_res; + } + } else { + for (i = (CAM_TFE_CSID_HW_NUM_MAX - 1); i >= 0; i--) { + if (!tfe_hw_mgr->csid_devices[i]) + continue; + + hw_intf = tfe_hw_mgr->csid_devices[i]; + csid_acquire.master_idx = hw_intf->hw_idx; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) + continue; + else { + csid_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 tfe csid path resource %d", + path_res_id); + goto put_res; + } + } +acquire_successful: + CAM_DBG(CAM_ISP, "CSID path left acquired success. is_dual %d", + in_port->usage_type); + + csid_res_temp->res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_res_temp->res_id = path_res_id; + + if (in_port->usage_type) { + csid_res_temp->is_dual_isp = 1; + tfe_ctx->is_dual = true; + tfe_ctx->master_hw_idx = + csid_res_temp->hw_res[0]->hw_intf->hw_idx; + } else + csid_res_temp->is_dual_isp = 0; + + if (in_port->num_out_res) + csid_res_temp->is_secure = out_port->secure_mode; + + cam_tfe_hw_mgr_put_res(&tfe_ctx->res_list_tfe_csid, &csid_res); + + /* + * Acquire Right if not already acquired. + * Dual TFE for RDI is not currently supported. + */ + if (in_port->usage_type && (path_res_id == CAM_TFE_CSID_PATH_RES_IPP) + && (acquired_cnt == 1)) { + memset(&csid_acquire, 0, sizeof(csid_acquire)); + csid_acquire.node_res = NULL; + csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_acquire.res_id = path_res_id; + csid_acquire.in_port = in_port; + csid_acquire.master_idx = + csid_res_temp->hw_res[0]->hw_intf->hw_idx; + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_SLAVE; + csid_acquire.node_res = NULL; + csid_acquire.out_port = in_port->data; + csid_acquire.event_cb_prv = tfe_ctx; + csid_acquire.event_cb = cam_tfe_hw_mgr_event_handler; + + if (tfe_ctx->is_tpg) { + if (tfe_ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx + == 0) + csid_acquire.phy_sel = CAM_ISP_TFE_IN_RES_PHY_0; + else + csid_acquire.phy_sel = CAM_ISP_TFE_IN_RES_PHY_1; + } + + for (j = 0; j < CAM_TFE_CSID_HW_NUM_MAX; j++) { + if (!tfe_hw_mgr->csid_devices[j]) + continue; + + if (j == csid_res_temp->hw_res[0]->hw_intf->hw_idx) + continue; + + hw_intf = tfe_hw_mgr->csid_devices[j]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) + continue; + else + break; + } + + if (j == CAM_TFE_CSID_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, + "Can not acquire tfe csid pixel resource"); + goto end; + } + csid_res_temp->hw_res[1] = csid_acquire.node_res; + CAM_DBG(CAM_ISP, "CSID right acquired success is_dual %d", + in_port->usage_type); + } + + return 0; +put_res: + cam_tfe_hw_mgr_put_res(&tfe_ctx->free_res_list, &csid_res); +end: + return rc; +} + +static int cam_tfe_hw_mgr_acquire_tpg( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info **in_port, + uint32_t num_inport) +{ + int rc = -EINVAL; + uint32_t i, j = 0; + struct cam_tfe_hw_mgr *tfe_hw_mgr; + struct cam_hw_intf *hw_intf; + struct cam_top_tpg_hw_reserve_resource_args tpg_reserve; + + tfe_hw_mgr = tfe_ctx->hw_mgr; + + for (i = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) { + if (!tfe_hw_mgr->tpg_devices[i]) + continue; + + hw_intf = tfe_hw_mgr->tpg_devices[i]; + tpg_reserve.num_inport = num_inport; + tpg_reserve.node_res = NULL; + for (j = 0; j < num_inport; j++) + tpg_reserve.in_port[j] = in_port[j]; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &tpg_reserve, sizeof(tpg_reserve)); + if (!rc) + break; + } + + if (i == CAM_TOP_TPG_HW_NUM_MAX || !tpg_reserve.node_res) { + CAM_ERR(CAM_ISP, "Can not acquire tfe TPG"); + rc = -EINVAL; + goto end; + } + + tfe_ctx->res_list_tpg.res_type = CAM_ISP_RESOURCE_TPG; + tfe_ctx->res_list_tpg.hw_res[0] = tpg_reserve.node_res; + +end: + return rc; +} + +static enum cam_tfe_csid_path_res_id + cam_tfe_hw_mgr_get_tfe_csid_rdi_res_type( + uint32_t out_port_type) +{ + enum cam_tfe_csid_path_res_id path_id; + + CAM_DBG(CAM_ISP, "out_port_type %x", out_port_type); + switch (out_port_type) { + case CAM_ISP_TFE_OUT_RES_RDI_0: + path_id = CAM_TFE_CSID_PATH_RES_RDI_0; + break; + case CAM_ISP_TFE_OUT_RES_RDI_1: + path_id = CAM_TFE_CSID_PATH_RES_RDI_1; + break; + case CAM_ISP_TFE_OUT_RES_RDI_2: + path_id = CAM_TFE_CSID_PATH_RES_RDI_2; + break; + default: + path_id = CAM_TFE_CSID_PATH_RES_MAX; + CAM_DBG(CAM_ISP, "maximum rdi type exceeded out_port_type:%d ", + out_port_type); + break; + } + + CAM_DBG(CAM_ISP, "out_port %x path_id %d", out_port_type, path_id); + + return path_id; +} + +static int cam_tfe_hw_mgr_acquire_res_tfe_csid_rdi( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info *in_port) +{ + int rc = -EINVAL; + int i, j; + + struct cam_tfe_hw_mgr *tfe_hw_mgr; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_tfe_out_port_info *out_port; + struct cam_tfe_csid_hw_reserve_resource_args csid_acquire; + struct cam_isp_hw_mgr_res *csid_res_iterator; + enum cam_tfe_csid_path_res_id path_res_id; + + tfe_hw_mgr = tfe_ctx->hw_mgr; + + for (j = 0; j < in_port->num_out_res; j++) { + out_port = &in_port->data[j]; + path_res_id = cam_tfe_hw_mgr_get_tfe_csid_rdi_res_type( + out_port->res_id); + + if (path_res_id == CAM_TFE_CSID_PATH_RES_MAX) + continue; + + rc = cam_tfe_hw_mgr_get_res(&tfe_ctx->free_res_list, &csid_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto end; + } + + memset(&csid_acquire, 0, sizeof(csid_acquire)); + csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_acquire.res_id = path_res_id; + csid_acquire.in_port = in_port; + csid_acquire.out_port = in_port->data; + csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; + csid_acquire.node_res = NULL; + + if (tfe_ctx->is_tpg) { + if (tfe_ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx == + 0) + csid_acquire.phy_sel = CAM_ISP_TFE_IN_RES_PHY_0; + else + csid_acquire.phy_sel = CAM_ISP_TFE_IN_RES_PHY_1; + } + + /* Try acquiring CSID resource from previously acquired HW */ + list_for_each_entry(csid_res_iterator, + &tfe_ctx->res_list_tfe_csid, list) { + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!csid_res_iterator->hw_res[i]) + continue; + + if (csid_res_iterator->is_secure == 1 || + (csid_res_iterator->is_secure == 0 && + in_port->num_out_res && + out_port->secure_mode == 1)) + continue; + + hw_intf = csid_res_iterator->hw_res[i]->hw_intf; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_DBG(CAM_ISP, + "No tfe csid resource from hw %d", + hw_intf->hw_idx); + continue; + } + + if (csid_acquire.node_res == NULL) { + CAM_ERR(CAM_ISP, + "Acquire RDI:%d rsrc failed", + path_res_id); + goto put_res; + } + + csid_res->hw_res[0] = csid_acquire.node_res; + + CAM_DBG(CAM_ISP, + "acquired from old csid(%s)=%d CSID rsrc successfully", + (i == 0) ? "left" : "right", + hw_intf->hw_idx); + /* + * If successfully acquired CSID from + * previously acquired HW, skip the next + * part + */ + goto acquire_successful; + } + } + + /* Acquire if not already acquired */ + if (tfe_ctx->is_dual) { + for (i = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { + if (!tfe_hw_mgr->csid_devices[i]) + continue; + + hw_intf = tfe_hw_mgr->csid_devices[i]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) + continue; + else { + csid_res->hw_res[0] = + csid_acquire.node_res; + break; + } + } + + if (i == CAM_TFE_CSID_HW_NUM_MAX || + !csid_acquire.node_res) { + CAM_ERR(CAM_ISP, + "Can not acquire tfe csid rdi path%d", + path_res_id); + + rc = -EINVAL; + goto put_res; + } + } else { + for (i = CAM_TFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) { + if (!tfe_hw_mgr->csid_devices[i]) + continue; + + hw_intf = tfe_hw_mgr->csid_devices[i]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) + continue; + else { + csid_res->hw_res[0] = + csid_acquire.node_res; + break; + } + } + + if (i == -1 || !csid_acquire.node_res) { + CAM_ERR(CAM_ISP, + "Can not acquire tfe csid rdi path %d", + path_res_id); + + rc = -EINVAL; + goto put_res; + } + } + +acquire_successful: + CAM_DBG(CAM_ISP, "CSID path :%d acquired success", path_res_id); + csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_res->res_id = path_res_id; + csid_res->hw_res[1] = NULL; + csid_res->is_dual_isp = 0; + + if (in_port->num_out_res) + csid_res->is_secure = out_port->secure_mode; + + cam_tfe_hw_mgr_put_res(&tfe_ctx->res_list_tfe_csid, &csid_res); + } + + return 0; +put_res: + cam_tfe_hw_mgr_put_res(&tfe_ctx->free_res_list, &csid_res); +end: + return rc; +} + +static int cam_tfe_hw_mgr_preprocess_port( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info *in_port, + int *ipp_count, + int *rdi_count, + int *pdaf_enable) +{ + int ipp_num = 0; + int rdi_num = 0; + bool rdi2_enable = false; + uint32_t i; + struct cam_isp_tfe_out_port_info *out_port; + struct cam_tfe_hw_mgr *tfe_hw_mgr; + + tfe_hw_mgr = tfe_ctx->hw_mgr; + + + for (i = 0; i < in_port->num_out_res; i++) { + out_port = &in_port->data[i]; + CAM_DBG(CAM_ISP, "out_res id %d", out_port->res_id); + + if (cam_tfe_hw_mgr_is_rdi_res(out_port->res_id)) { + rdi_num++; + if (out_port->res_id == CAM_ISP_TFE_OUT_RES_RDI_2) + rdi2_enable = true; + } else { + ipp_num++; + if (out_port->res_id == CAM_ISP_TFE_OUT_RES_PDAF) + *pdaf_enable = 1; + } + } + + if (*pdaf_enable && rdi2_enable) { + CAM_ERR(CAM_ISP, "invalid outports both RDI2 and PDAF enabled"); + return -EINVAL; + } + + *ipp_count = ipp_num; + *rdi_count = rdi_num; + + CAM_DBG(CAM_ISP, "rdi: %d ipp: %d pdaf:%d", rdi_num, ipp_num, + *pdaf_enable); + + return 0; +} + +static int cam_tfe_mgr_acquire_hw_for_ctx( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_info *in_port, + uint32_t *num_pix_port, uint32_t *num_rdi_port, + uint32_t *pdaf_enable) +{ + int rc = -EINVAL; + int is_dual_isp = 0; + int ipp_count = 0; + int rdi_count = 0; + + is_dual_isp = in_port->usage_type; + + cam_tfe_hw_mgr_preprocess_port(tfe_ctx, in_port, &ipp_count, + &rdi_count, pdaf_enable); + + if (!ipp_count && !rdi_count) { + CAM_ERR(CAM_ISP, + "No PIX or RDI"); + return -EINVAL; + } + + if (ipp_count) { + /* get tfe csid IPP resource */ + rc = cam_tfe_hw_mgr_acquire_res_tfe_csid_pxl(tfe_ctx, + in_port); + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire TFE CSID IPP resource Failed"); + goto err; + } + } + + if (rdi_count) { + /* get tfe csid rdi resource */ + rc = cam_tfe_hw_mgr_acquire_res_tfe_csid_rdi(tfe_ctx, in_port); + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire TFE CSID RDI resource Failed"); + goto err; + } + } + + rc = cam_tfe_hw_mgr_acquire_res_tfe_in(tfe_ctx, in_port, pdaf_enable); + if (rc) { + CAM_ERR(CAM_ISP, + "Acquire TFE IN resource Failed"); + goto err; + } + + CAM_DBG(CAM_ISP, "Acquiring TFE OUT resource..."); + rc = cam_tfe_hw_mgr_acquire_res_tfe_out(tfe_ctx, in_port); + if (rc) { + CAM_ERR(CAM_ISP, "Acquire TFE OUT resource Failed"); + goto err; + } + + *num_pix_port += ipp_count; + *num_rdi_port += rdi_count; + + return 0; +err: + /* release resource at the acquire entry funciton */ + return rc; +} + +void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, + enum cam_cdm_cb_status status, uint64_t cookie) +{ + struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; + struct cam_tfe_hw_mgr_ctx *ctx = NULL; + + if (!userdata) { + CAM_ERR(CAM_ISP, "Invalid args"); + return; + } + + hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata; + ctx = (struct cam_tfe_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; + + if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { + complete_all(&ctx->config_done_complete); + atomic_set(&ctx->cdm_done, 1); + if (g_tfe_hw_mgr.debug_cfg.per_req_reg_dump) + cam_tfe_mgr_handle_reg_dump(ctx, + hw_update_data->reg_dump_buf_desc, + hw_update_data->num_reg_dump_buf, + CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST); + CAM_DBG(CAM_ISP, + "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", + handle, userdata, status, cookie); + } +} + +/* entry function: acquire_hw */ +static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) +{ + struct cam_tfe_hw_mgr *tfe_hw_mgr = hw_mgr_priv; + struct cam_hw_acquire_args *acquire_args = acquire_hw_args; + int rc = -EINVAL; + int i, j; + struct cam_tfe_hw_mgr_ctx *tfe_ctx; + struct cam_isp_tfe_in_port_info *in_port = NULL; + struct cam_cdm_acquire_data cdm_acquire; + uint32_t num_pix_port_per_in = 0; + uint32_t num_rdi_port_per_in = 0; + uint32_t pdaf_enable = 0; + uint32_t total_pix_port = 0; + uint32_t total_rdi_port = 0; + uint32_t in_port_length = 0; + uint32_t total_in_port_length = 0; + struct cam_isp_tfe_acquire_hw_info *acquire_hw_info = NULL; + struct cam_isp_tfe_in_port_info + *tpg_inport[CAM_TOP_TPG_MAX_SUPPORTED_DT] = {0, 0, 0, 0}; + + CAM_DBG(CAM_ISP, "Enter..."); + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error"); + return -EINVAL; + } + + /* get the tfe ctx */ + rc = cam_tfe_hw_mgr_get_ctx(&tfe_hw_mgr->free_ctx_list, &tfe_ctx); + if (rc || !tfe_ctx) { + CAM_ERR(CAM_ISP, "Get tfe hw context failed"); + goto err; + } + + tfe_ctx->common.cb_priv = acquire_args->context_data; + for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) + tfe_ctx->common.event_cb[i] = acquire_args->event_cb; + + tfe_ctx->hw_mgr = tfe_hw_mgr; + + memcpy(cdm_acquire.identifier, "tfe", sizeof("tfe")); + cdm_acquire.cell_index = 0; + cdm_acquire.handle = 0; + cdm_acquire.userdata = tfe_ctx; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; + cdm_acquire.base_array_cnt = CAM_TFE_HW_NUM_MAX; + for (i = 0, j = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (tfe_hw_mgr->cdm_reg_map[i]) + cdm_acquire.base_array[j++] = + tfe_hw_mgr->cdm_reg_map[i]; + } + cdm_acquire.base_array_cnt = j; + + + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_tfe_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_ctx; + } + + CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x", + cdm_acquire.handle); + tfe_ctx->cdm_handle = cdm_acquire.handle; + tfe_ctx->cdm_ops = cdm_acquire.ops; + atomic_set(&tfe_ctx->cdm_done, 1); + + acquire_hw_info = (struct cam_isp_tfe_acquire_hw_info *) + acquire_args->acquire_info; + in_port = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset); + + /* Check any inport has dual tfe usage */ + tfe_ctx->is_dual = false; + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + if (in_port->usage_type) + tfe_ctx->is_dual = true; + + in_port_length = + sizeof(struct cam_isp_tfe_in_port_info) + + (in_port->num_out_res - 1) * + sizeof(struct cam_isp_tfe_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 %d %d", + total_in_port_length, + acquire_hw_info->input_info_size); + rc = -EINVAL; + goto free_cdm; + } + + in_port = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)in_port + in_port_length); + } + + in_port_length = 0; + total_in_port_length = 0; + in_port = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset); + + if (in_port->res_id == CAM_ISP_TFE_IN_RES_TPG) { + if (acquire_hw_info->num_inputs > + CAM_TOP_TPG_MAX_SUPPORTED_DT) { + CAM_ERR(CAM_ISP, "too many number inport:%d for TPG ", + acquire_hw_info->num_inputs); + rc = -EINVAL; + goto free_cdm; + } + + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + if (in_port->res_id != CAM_ISP_TFE_IN_RES_TPG) { + CAM_ERR(CAM_ISP, "Inval :%d inport res id:0x%x", + i, in_port->res_id); + rc = -EINVAL; + goto free_cdm; + } + + tpg_inport[i] = in_port; + in_port_length = + sizeof(struct cam_isp_tfe_in_port_info) + + (in_port->num_out_res - 1) * + sizeof(struct cam_isp_tfe_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 %d %d", + total_in_port_length, + acquire_hw_info->input_info_size); + rc = -EINVAL; + goto free_cdm; + } + + in_port = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)in_port + in_port_length); + } + + rc = cam_tfe_hw_mgr_acquire_tpg(tfe_ctx, tpg_inport, + acquire_hw_info->num_inputs); + if (rc) + goto free_cdm; + + tfe_ctx->is_tpg = true; + } + + in_port = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset); + in_port_length = 0; + total_in_port_length = 0; + + /* acquire HW resources */ + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + + if (in_port->num_out_res > CAM_TFE_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_tfe_in_port_info) + + (in_port->num_out_res - 1) * + sizeof(struct cam_isp_tfe_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"); + rc = -EINVAL; + goto free_res; + } + CAM_DBG(CAM_ISP, "in_res_id %x", in_port->res_id); + rc = cam_tfe_mgr_acquire_hw_for_ctx(tfe_ctx, in_port, + &num_pix_port_per_in, &num_rdi_port_per_in, + &pdaf_enable); + total_pix_port += num_pix_port_per_in; + total_rdi_port += num_rdi_port_per_in; + + if (rc) { + CAM_ERR(CAM_ISP, "can not acquire resource"); + goto free_res; + } + in_port = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)in_port + in_port_length); + } + + /* Check whether context has only RDI resource */ + if (!total_pix_port) { + tfe_ctx->is_rdi_only_context = 1; + CAM_DBG(CAM_ISP, "RDI only context"); + } else + tfe_ctx->is_rdi_only_context = 0; + + /* Process base info */ + rc = cam_tfe_mgr_process_base_info(tfe_ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Process base info failed"); + goto free_res; + } + + acquire_args->ctxt_to_hw_map = tfe_ctx; + tfe_ctx->ctx_in_use = 1; + + cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx); + + CAM_DBG(CAM_ISP, "Exit...(success)"); + + return 0; +free_res: + cam_tfe_hw_mgr_release_hw_for_ctx(tfe_ctx); + tfe_ctx->ctx_in_use = 0; + tfe_ctx->is_rdi_only_context = 0; + tfe_ctx->cdm_handle = 0; + tfe_ctx->cdm_ops = NULL; + tfe_ctx->init_done = false; + tfe_ctx->is_dual = false; + tfe_ctx->is_tpg = false; + tfe_ctx->res_list_tpg.res_type = CAM_ISP_RESOURCE_MAX; +free_cdm: + cam_cdm_release(tfe_ctx->cdm_handle); +free_ctx: + cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->free_ctx_list, &tfe_ctx); +err: + /* Dump all the current acquired HW */ + cam_tfe_hw_mgr_dump_all_ctx(); + + CAM_ERR_RATE_LIMIT(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +/* entry function: acquire_hw */ +static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) +{ + struct cam_tfe_hw_mgr *tfe_hw_mgr = hw_mgr_priv; + struct cam_hw_acquire_args *acquire_args = acquire_hw_args; + int rc = -EINVAL; + int i, j; + struct cam_tfe_hw_mgr_ctx *tfe_ctx; + struct cam_isp_tfe_in_port_info *in_port = NULL; + struct cam_isp_resource *isp_resource = NULL; + struct cam_cdm_acquire_data cdm_acquire; + uint32_t num_pix_port_per_in = 0; + uint32_t num_rdi_port_per_in = 0; + uint32_t pdad_enable = 0; + uint32_t total_pix_port = 0; + uint32_t total_rdi_port = 0; + uint32_t in_port_length = 0; + + CAM_DBG(CAM_ISP, "Enter..."); + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error"); + return -EINVAL; + } + + /* get the tfe ctx */ + rc = cam_tfe_hw_mgr_get_ctx(&tfe_hw_mgr->free_ctx_list, &tfe_ctx); + if (rc || !tfe_ctx) { + CAM_ERR(CAM_ISP, "Get tfe hw context failed"); + goto err; + } + + tfe_ctx->common.cb_priv = acquire_args->context_data; + for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) + tfe_ctx->common.event_cb[i] = acquire_args->event_cb; + + tfe_ctx->hw_mgr = tfe_hw_mgr; + + memcpy(cdm_acquire.identifier, "tfe", sizeof("tfe")); + cdm_acquire.cell_index = 0; + cdm_acquire.handle = 0; + cdm_acquire.userdata = tfe_ctx; + cdm_acquire.base_array_cnt = CAM_TFE_HW_NUM_MAX; + for (i = 0, j = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (tfe_hw_mgr->cdm_reg_map[i]) + cdm_acquire.base_array[j++] = + tfe_hw_mgr->cdm_reg_map[i]; + } + cdm_acquire.base_array_cnt = j; + + + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_tfe_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_ctx; + } + + CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x", + cdm_acquire.handle); + tfe_ctx->cdm_handle = cdm_acquire.handle; + tfe_ctx->cdm_ops = cdm_acquire.ops; + atomic_set(&tfe_ctx->cdm_done, 1); + + isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; + + /* acquire HW resources */ + for (i = 0; i < acquire_args->num_acq; i++) { + 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, + isp_resource[i].length); + + in_port_length = sizeof(struct cam_isp_tfe_in_port_info); + + if (in_port_length > isp_resource[i].length) { + CAM_ERR(CAM_ISP, "buffer size is not enough"); + rc = -EINVAL; + goto free_res; + } + + in_port = memdup_user( + u64_to_user_ptr(isp_resource[i].res_hdl), + isp_resource[i].length); + if (!IS_ERR(in_port)) { + if (in_port->num_out_res > CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "too many output res %d", + in_port->num_out_res); + rc = -EINVAL; + kfree(in_port); + goto free_res; + } + + in_port_length = + sizeof(struct cam_isp_tfe_in_port_info) + + (in_port->num_out_res - 1) * + sizeof(struct cam_isp_tfe_out_port_info); + if (in_port_length > isp_resource[i].length) { + CAM_ERR(CAM_ISP, "buffer size is not enough"); + rc = -EINVAL; + kfree(in_port); + goto free_res; + } + + rc = cam_tfe_mgr_acquire_hw_for_ctx(tfe_ctx, in_port, + &num_pix_port_per_in, &num_rdi_port_per_in, + &pdad_enable); + total_pix_port += num_pix_port_per_in; + total_rdi_port += num_rdi_port_per_in; + + kfree(in_port); + if (rc) { + CAM_ERR(CAM_ISP, "can not acquire resource"); + goto free_res; + } + } else { + CAM_ERR(CAM_ISP, + "Copy from user failed with in_port = %pK", + in_port); + rc = -EFAULT; + goto free_res; + } + } + + /* Check whether context has only RDI resource */ + if (!total_pix_port) { + tfe_ctx->is_rdi_only_context = 1; + CAM_DBG(CAM_ISP, "RDI only context"); + } else + tfe_ctx->is_rdi_only_context = 0; + + /* Process base info */ + rc = cam_tfe_mgr_process_base_info(tfe_ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Process base info failed"); + goto free_res; + } + + acquire_args->ctxt_to_hw_map = tfe_ctx; + tfe_ctx->ctx_in_use = 1; + + cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx); + + CAM_DBG(CAM_ISP, "Exit...(success)"); + + return 0; +free_res: + cam_tfe_hw_mgr_release_hw_for_ctx(tfe_ctx); + cam_cdm_release(tfe_ctx->cdm_handle); +free_ctx: + cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->free_ctx_list, &tfe_ctx); +err: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +/* entry function: acquire_hw */ +static int cam_tfe_mgr_acquire(void *hw_mgr_priv, + void *acquire_hw_args) +{ + struct cam_hw_acquire_args *acquire_args = acquire_hw_args; + int rc = -EINVAL; + + CAM_DBG(CAM_ISP, "Enter..."); + + if (!acquire_args || acquire_args->num_acq <= 0) { + CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error"); + return -EINVAL; + } + + if (acquire_args->num_acq == CAM_API_COMPAT_CONSTANT) + rc = cam_tfe_mgr_acquire_hw(hw_mgr_priv, acquire_hw_args); + else + rc = cam_tfe_mgr_acquire_dev(hw_mgr_priv, acquire_hw_args); + + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +static const char *cam_tfe_util_usage_data_to_string( + uint32_t usage_data) +{ + switch (usage_data) { + case CAM_ISP_TFE_USAGE_LEFT_PX: + return "LEFT_PX"; + case CAM_ISP_TFE_USAGE_RIGHT_PX: + return "RIGHT_PX"; + case CAM_ISP_TFE_USAGE_RDI: + return "RDI"; + default: + return "USAGE_INVALID"; + } +} + +static int cam_tfe_classify_vote_info( + struct cam_isp_hw_mgr_res *hw_mgr_res, + struct cam_isp_bw_config_internal_v2 *bw_config, + struct cam_axi_vote *isp_vote, + uint32_t split_idx, + bool *camif_l_bw_updated, + bool *camif_r_bw_updated) +{ + int rc = 0, i, j = 0; + + if (hw_mgr_res->res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + if (split_idx == CAM_ISP_HW_SPLIT_LEFT) { + if (*camif_l_bw_updated) + return rc; + + for (i = 0; i < bw_config->num_paths; i++) { + if (bw_config->axi_path[i].usage_data == + CAM_ISP_TFE_USAGE_LEFT_PX) { + memcpy(&isp_vote->axi_path[j], + &bw_config->axi_path[i], + sizeof(struct + cam_axi_per_path_bw_vote)); + j++; + } + } + isp_vote->num_paths = j; + + *camif_l_bw_updated = true; + } else { + if (*camif_r_bw_updated) + return rc; + + for (i = 0; i < bw_config->num_paths; i++) { + if (bw_config->axi_path[i].usage_data == + CAM_ISP_TFE_USAGE_RIGHT_PX) { + memcpy(&isp_vote->axi_path[j], + &bw_config->axi_path[i], + sizeof(struct + cam_axi_per_path_bw_vote)); + j++; + } + } + isp_vote->num_paths = j; + + *camif_r_bw_updated = true; + } + } else if ((hw_mgr_res->res_id >= CAM_ISP_HW_TFE_IN_RDI0) + && (hw_mgr_res->res_id <= + CAM_ISP_HW_TFE_IN_RDI2)) { + for (i = 0; i < bw_config->num_paths; i++) { + if ((bw_config->axi_path[i].usage_data == + CAM_ISP_TFE_USAGE_RDI) && + ((bw_config->axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_IFE_RDI0) == + (hw_mgr_res->res_id - + CAM_ISP_HW_TFE_IN_RDI0))) { + memcpy(&isp_vote->axi_path[j], + &bw_config->axi_path[i], + sizeof(struct + cam_axi_per_path_bw_vote)); + j++; + } + } + isp_vote->num_paths = j; + + } else { + if (hw_mgr_res->hw_res[split_idx]) { + CAM_ERR(CAM_ISP, "Invalid res_id %u, split_idx: %u", + hw_mgr_res->res_id, split_idx); + rc = -EINVAL; + return rc; + } + } + + for (i = 0; i < isp_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "CLASSIFY_VOTE [%s] [%s] [%s] [%llu] [%llu] [%llu]", + cam_tfe_util_usage_data_to_string( + isp_vote->axi_path[i].usage_data), + cam_cpas_axi_util_path_type_to_string( + isp_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + isp_vote->axi_path[i].transac_type), + isp_vote->axi_path[i].camnoc_bw, + isp_vote->axi_path[i].mnoc_ab_bw, + isp_vote->axi_path[i].mnoc_ib_bw); + } + + return rc; +} + +static int cam_isp_tfe_blob_bw_update( + struct cam_isp_bw_config_internal_v2 *bw_config, + struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_bw_update_args bw_upd_args; + int rc = -EINVAL; + uint32_t i, split_idx; + bool camif_l_bw_updated = false; + bool camif_r_bw_updated = false; + + for (i = 0; i < bw_config->num_paths; i++) { + CAM_DBG(CAM_PERF, + "ISP_BLOB usage_type=%u [%s] [%s] [%s] [%llu] [%llu] [%llu]", + bw_config->usage_type, + cam_tfe_util_usage_data_to_string( + bw_config->axi_path[i].usage_data), + cam_cpas_axi_util_path_type_to_string( + bw_config->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + bw_config->axi_path[i].transac_type), + bw_config->axi_path[i].camnoc_bw, + bw_config->axi_path[i].mnoc_ab_bw, + bw_config->axi_path[i].mnoc_ib_bw); + } + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + for (split_idx = 0; split_idx < CAM_ISP_HW_SPLIT_MAX; + split_idx++) { + if (!hw_mgr_res->hw_res[split_idx]) + continue; + + memset(&bw_upd_args.isp_vote, 0, + sizeof(struct cam_axi_vote)); + rc = cam_tfe_classify_vote_info(hw_mgr_res, bw_config, + &bw_upd_args.isp_vote, split_idx, + &camif_l_bw_updated, &camif_r_bw_updated); + if (rc) + return rc; + + if (!bw_upd_args.isp_vote.num_paths) + continue; + + hw_intf = hw_mgr_res->hw_res[split_idx]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + bw_upd_args.node_res = + hw_mgr_res->hw_res[split_idx]; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_BW_UPDATE_V2, + &bw_upd_args, + sizeof( + struct cam_tfe_bw_update_args)); + if (rc) + CAM_ERR(CAM_ISP, + "BW Update failed rc: %d", rc); + } else { + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + } + + return rc; +} + +/* entry function: config_hw */ +static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, + void *config_hw_args) +{ + int rc = -EINVAL, i, skip = 0; + struct cam_hw_config_args *cfg; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_isp_prepare_hw_update_data *hw_update_data; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_mgr_priv || !config_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + cfg = config_hw_args; + ctx = (struct cam_tfe_hw_mgr_ctx *)cfg->ctxt_to_hw_map; + if (!ctx) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + if (!ctx->ctx_in_use || !ctx->cdm_cmd) { + CAM_ERR(CAM_ISP, "Invalid context parameters"); + return -EPERM; + } + if (atomic_read(&ctx->overflow_pending)) + return -EINVAL; + + hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; + + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (hw_update_data->bw_config_valid[i] == true) { + + CAM_DBG(CAM_ISP, "idx=%d, bw_config_version=%d", + ctx, ctx->ctx_index, i, + hw_update_data->bw_config_version); + if (hw_update_data->bw_config_version == + CAM_ISP_BW_CONFIG_V2) { + rc = cam_isp_tfe_blob_bw_update( + &hw_update_data->bw_config_v2[i], ctx); + if (rc) + CAM_ERR(CAM_ISP, + "Bandwidth Update Failed rc: %d", rc); + } else { + CAM_ERR(CAM_ISP, + "Invalid bw config version: %d", + hw_update_data->bw_config_version); + } + } + } + + 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; + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; + + for (i = 0 ; i < cfg->num_hw_update_entries; i++) { + cmd = (cfg->hw_update_entries + i); + if (cfg->reapply && cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i - skip].offset = cmd->offset; + cdm_cmd->cmd[i - skip].len = cmd->len; + cdm_cmd->cmd[i - skip].arbitrate = false; + } + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; + + reinit_completion(&ctx->config_done_complete); + ctx->applied_req_id = cfg->request_id; + + CAM_DBG(CAM_ISP, "Submit to CDM"); + atomic_set(&ctx->cdm_done, 0); + rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to apply the configs"); + return rc; + } + + if (cfg->init_packet) { + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(CAM_TFE_HW_CONFIG_TIMEOUT)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, + "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 ctx_index %d", + cfg->request_id, ctx->ctx_index); + } + } + } else { + CAM_ERR(CAM_ISP, "No commands to config"); + } + CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); + + return rc; +} + +static int cam_tfe_mgr_stop_hw_in_overflow(void *stop_hw_args) +{ + int rc = 0; + struct cam_hw_stop_args *stop_args = stop_hw_args; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_tfe_hw_mgr_ctx *ctx; + uint32_t i, master_base_idx = 0; + + if (!stop_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + ctx = (struct cam_tfe_hw_mgr_ctx *)stop_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "Enter...ctx id:%d", + ctx->ctx_index); + + if (!ctx->num_base) { + CAM_ERR(CAM_ISP, "Number of bases are zero"); + return -EINVAL; + } + + /* get master base index first */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT) { + master_base_idx = ctx->base[i].idx; + break; + } + } + + if (i == ctx->num_base) + master_base_idx = ctx->base[0].idx; + + + /* stop the master CSID path first */ + cam_tfe_mgr_csid_stop_hw(ctx, &ctx->res_list_tfe_csid, + master_base_idx, CAM_TFE_CSID_HALT_IMMEDIATELY); + + /* Stop rest of the CSID paths */ + for (i = 0; i < ctx->num_base; i++) { + if (i == master_base_idx) + continue; + + cam_tfe_mgr_csid_stop_hw(ctx, &ctx->res_list_tfe_csid, + ctx->base[i].idx, CAM_TFE_CSID_HALT_IMMEDIATELY); + } + + /* TFE in resources */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + cam_tfe_hw_mgr_stop_hw_res(hw_mgr_res); + } + + /* TFE out resources */ + for (i = 0; i < CAM_TFE_HW_OUT_RES_MAX; i++) + cam_tfe_hw_mgr_stop_hw_res(&ctx->res_list_tfe_out[i]); + + if (ctx->is_tpg) + cam_tfe_hw_mgr_stop_hw_res(&ctx->res_list_tpg); + + /* Stop tasklet for context */ + cam_tasklet_stop(ctx->common.tasklet_info); + CAM_DBG(CAM_ISP, "Exit...ctx id:%d rc :%d", + ctx->ctx_index, rc); + + return rc; +} + +static int cam_tfe_mgr_bw_control(struct cam_tfe_hw_mgr_ctx *ctx, + enum cam_tfe_bw_control_action action) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_bw_control_args bw_ctrl_args; + int rc = -EINVAL; + uint32_t i; + + CAM_DBG(CAM_ISP, "Enter...ctx id:%d", ctx->ctx_index); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, 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) { + bw_ctrl_args.node_res = + hw_mgr_res->hw_res[i]; + bw_ctrl_args.action = action; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_BW_CONTROL, + &bw_ctrl_args, + sizeof(struct cam_tfe_bw_control_args)); + if (rc) + CAM_ERR(CAM_ISP, "BW Update failed"); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + +static int cam_tfe_mgr_pause_hw(struct cam_tfe_hw_mgr_ctx *ctx) +{ + return cam_tfe_mgr_bw_control(ctx, CAM_TFE_BW_CONTROL_EXCLUDE); +} + +/* entry function: stop_hw */ +static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) +{ + int rc = 0; + struct cam_hw_stop_args *stop_args = stop_hw_args; + struct cam_isp_stop_args *stop_isp; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_tfe_hw_mgr_ctx *ctx; + enum cam_tfe_csid_halt_cmd csid_halt_type; + uint32_t i, master_base_idx = 0; + + if (!hw_mgr_priv || !stop_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_tfe_hw_mgr_ctx *)stop_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index); + stop_isp = (struct cam_isp_stop_args *)stop_args->args; + + /* Set the csid halt command */ + if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) + csid_halt_type = CAM_TFE_CSID_HALT_AT_FRAME_BOUNDARY; + else + csid_halt_type = CAM_TFE_CSID_HALT_IMMEDIATELY; + + /* Note:stop resource will remove the irq mask from the hardware */ + + if (!ctx->num_base) { + CAM_ERR(CAM_ISP, "number of bases are zero"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Halting CSIDs"); + + /* get master base index first */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT) { + master_base_idx = ctx->base[i].idx; + break; + } + } + + /* + * If Context does not have PIX resources and has only RDI resource + * then take the first base index. + */ + if (i == ctx->num_base) + master_base_idx = ctx->base[0].idx; + CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); + + /* Stop the master CSID path first */ + cam_tfe_mgr_csid_stop_hw(ctx, &ctx->res_list_tfe_csid, + master_base_idx, csid_halt_type); + + /* stop rest of the CSID paths */ + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == master_base_idx) + continue; + CAM_DBG(CAM_ISP, "Stopping CSID idx %d i %d master %d", + ctx->base[i].idx, i, master_base_idx); + + cam_tfe_mgr_csid_stop_hw(ctx, &ctx->res_list_tfe_csid, + ctx->base[i].idx, csid_halt_type); + } + + CAM_DBG(CAM_ISP, "Going to stop TFE Out"); + + /* TFE out resources */ + for (i = 0; i < CAM_TFE_HW_OUT_RES_MAX; i++) + cam_tfe_hw_mgr_stop_hw_res(&ctx->res_list_tfe_out[i]); + + CAM_DBG(CAM_ISP, "Going to stop TFE IN"); + + /* TFE in resources */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + cam_tfe_hw_mgr_stop_hw_res(hw_mgr_res); + } + + cam_tasklet_stop(ctx->common.tasklet_info); + + cam_tfe_mgr_pause_hw(ctx); + + wait_for_completion(&ctx->config_done_complete); + + if (stop_isp->stop_only) + goto end; + + if (cam_cdm_stream_off(ctx->cdm_handle)) + CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); + + if (ctx->is_tpg) + cam_tfe_hw_mgr_stop_hw_res(&ctx->res_list_tpg); + + cam_tfe_hw_mgr_deinit_hw(ctx); + + CAM_DBG(CAM_ISP, + "Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc); + + mutex_lock(&g_tfe_hw_mgr.ctx_mutex); + atomic_dec_return(&g_tfe_hw_mgr.active_ctx_cnt); + mutex_unlock(&g_tfe_hw_mgr.ctx_mutex); + +end: + return rc; +} + +static int cam_tfe_mgr_reset_tfe_hw(struct cam_tfe_hw_mgr *hw_mgr, + uint32_t hw_idx) +{ + uint32_t i = 0; + struct cam_hw_intf *tfe_hw_intf; + uint32_t tfe_reset_type; + + if (!hw_mgr) { + CAM_DBG(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + /* Reset TFE HW*/ + tfe_reset_type = CAM_TFE_HW_RESET_HW; + + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (hw_idx != hw_mgr->tfe_devices[i]->hw_idx) + continue; + CAM_DBG(CAM_ISP, "TFE (id = %d) reset", hw_idx); + tfe_hw_intf = hw_mgr->tfe_devices[i]; + tfe_hw_intf->hw_ops.reset(tfe_hw_intf->hw_priv, + &tfe_reset_type, sizeof(tfe_reset_type)); + break; + } + + CAM_DBG(CAM_ISP, "Exit Successfully"); + return 0; +} + +static int cam_tfe_mgr_restart_hw(void *start_hw_args) +{ + int rc = -EINVAL; + struct cam_hw_start_args *start_args = start_hw_args; + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_isp_hw_mgr_res *hw_mgr_res; + uint32_t i; + + if (!start_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_tfe_hw_mgr_ctx *)start_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "START TFE OUT ... in ctx id:%d", ctx->ctx_index); + + cam_tasklet_start(ctx->common.tasklet_info); + + /* start the TFE out devices */ + for (i = 0; i < CAM_TFE_HW_OUT_RES_MAX; i++) { + rc = cam_tfe_hw_mgr_start_hw_res( + &ctx->res_list_tfe_out[i], ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE OUT (%d)", i); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START TFE SRC ... in ctx id:%d", ctx->ctx_index); + + /* Start the TFE in devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE IN (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", ctx->ctx_index); + /* Start the TFE CSID HW devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE CSID (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "Exit...(success)"); + return 0; + +err: + cam_tfe_mgr_stop_hw_in_overflow(start_hw_args); + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; +} + +static int cam_tfe_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) +{ + int rc = -EINVAL; + struct cam_isp_start_args *start_isp = start_hw_args; + struct cam_hw_stop_args stop_args; + struct cam_isp_stop_args stop_isp; + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *rsrc_node = NULL; + uint32_t i, camif_debug; + bool res_rdi_context_set = false; + uint32_t primary_rdi_in_res; + uint32_t primary_rdi_out_res; + + primary_rdi_in_res = CAM_ISP_HW_TFE_IN_MAX; + primary_rdi_out_res = CAM_ISP_TFE_OUT_RES_MAX; + + if (!hw_mgr_priv || !start_isp) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_tfe_hw_mgr_ctx *) + start_isp->hw_config.ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + if ((!ctx->init_done) && start_isp->start_only) { + CAM_ERR(CAM_ISP, "Invalid args init_done %d start_only %d", + ctx->init_done, start_isp->start_only); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Enter... ctx id:%d", + ctx->ctx_index); + + /* update Bandwidth should be done at the hw layer */ + + cam_tasklet_start(ctx->common.tasklet_info); + + if (ctx->init_done && start_isp->start_only) + goto start_only; + + /* set current csid debug information to CSID HW */ + for (i = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { + if (g_tfe_hw_mgr.csid_devices[i]) + rc = g_tfe_hw_mgr.csid_devices[i]->hw_ops.process_cmd( + g_tfe_hw_mgr.csid_devices[i]->hw_priv, + CAM_TFE_CSID_SET_CSID_DEBUG, + &g_tfe_hw_mgr.debug_cfg.csid_debug, + sizeof(g_tfe_hw_mgr.debug_cfg.csid_debug)); + } + + camif_debug = g_tfe_hw_mgr.debug_cfg.camif_debug; + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->process_cmd && (rsrc_node->res_id == + CAM_ISP_HW_TFE_IN_CAMIF)) { + rc = hw_mgr_res->hw_res[i]->process_cmd( + hw_mgr_res->hw_res[i], + CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + &camif_debug, + sizeof(camif_debug)); + } + } + } + + rc = cam_tfe_hw_mgr_init_hw(ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Init failed"); + goto tasklet_stop; + } + + ctx->init_done = true; + + mutex_lock(&g_tfe_hw_mgr.ctx_mutex); + atomic_fetch_inc(&g_tfe_hw_mgr.active_ctx_cnt); + mutex_unlock(&g_tfe_hw_mgr.ctx_mutex); + + CAM_DBG(CAM_ISP, "start cdm interface"); + rc = cam_cdm_stream_on(ctx->cdm_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start cdm (%d)", + ctx->cdm_handle); + goto deinit_hw; + } + +start_only: + /* Apply initial configuration */ + CAM_DBG(CAM_ISP, "Config HW"); + rc = cam_tfe_mgr_config_hw(hw_mgr_priv, &start_isp->hw_config); + if (rc) { + CAM_ERR(CAM_ISP, "Config HW failed"); + goto cdm_streamoff; + } + + CAM_DBG(CAM_ISP, "START TFE OUT ... in ctx id:%d", + ctx->ctx_index); + /* start the TFE out devices */ + for (i = 0; i < CAM_TFE_HW_OUT_RES_MAX; i++) { + hw_mgr_res = &ctx->res_list_tfe_out[i]; + switch (hw_mgr_res->res_id) { + case CAM_ISP_TFE_OUT_RES_RDI_0: + case CAM_ISP_TFE_OUT_RES_RDI_1: + case CAM_ISP_TFE_OUT_RES_RDI_2: + if (!res_rdi_context_set && ctx->is_rdi_only_context) { + hw_mgr_res->hw_res[0]->rdi_only_ctx = + ctx->is_rdi_only_context; + res_rdi_context_set = true; + primary_rdi_out_res = hw_mgr_res->res_id; + } + } + + rc = cam_tfe_hw_mgr_start_hw_res( + &ctx->res_list_tfe_out[i], ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE OUT (%d)", + i); + goto err; + } + } + + if (primary_rdi_out_res < CAM_ISP_TFE_OUT_RES_MAX) + primary_rdi_in_res = + cam_tfe_hw_mgr_convert_rdi_out_res_id_to_in_res( + primary_rdi_out_res); + + CAM_DBG(CAM_ISP, "START TFE IN ... in ctx id:%d", + ctx->ctx_index); + /* Start the TFE in resources devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + /* + * if rdi only context has two rdi resources then only one irq + * subscription should be sufficient + */ + if (primary_rdi_in_res == hw_mgr_res->res_id) + hw_mgr_res->hw_res[0]->rdi_only_ctx = + ctx->is_rdi_only_context; + + rc = cam_tfe_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE in resource (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", + ctx->ctx_index); + /* Start the TFE CSID HW devices */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_start_hw_res(hw_mgr_res, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE CSID (%d)", + hw_mgr_res->res_id); + goto err; + } + } + + if (ctx->is_tpg) { + CAM_DBG(CAM_ISP, "START TPG HW ... in ctx id:%d", + ctx->ctx_index); + rc = cam_tfe_hw_mgr_start_hw_res(&ctx->res_list_tpg, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start TFE TPG (%d)", + ctx->res_list_tpg.res_id); + goto err; + } + } + + return 0; + +err: + stop_isp.stop_only = false; + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; + stop_args.ctxt_to_hw_map = start_isp->hw_config.ctxt_to_hw_map; + stop_args.args = (void *)(&stop_isp); + + cam_tfe_mgr_stop_hw(hw_mgr_priv, &stop_args); + CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); + return rc; + +cdm_streamoff: + cam_cdm_stream_off(ctx->cdm_handle); + +deinit_hw: + cam_tfe_hw_mgr_deinit_hw(ctx); + +tasklet_stop: + cam_tasklet_stop(ctx->common.tasklet_info); + + return rc; +} + +static int cam_tfe_mgr_read(void *hw_mgr_priv, void *read_args) +{ + return -EPERM; +} + +static int cam_tfe_mgr_write(void *hw_mgr_priv, void *write_args) +{ + return -EPERM; +} + +static int cam_tfe_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) +{ + struct cam_tfe_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_reset_args *reset_args = hw_reset_args; + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_isp_hw_mgr_res *hw_mgr_res; + int rc = 0, i = 0; + + if (!hw_mgr_priv || !hw_reset_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_tfe_hw_mgr_ctx *)reset_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "Reset CSID and TFE"); + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to reset CSID:%d rc: %d", + hw_mgr_res->res_id, rc); + goto end; + } + } + + for (i = 0; i < ctx->num_base; i++) { + rc = cam_tfe_mgr_reset_tfe_hw(hw_mgr, ctx->base[i].idx); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to reset TFE:%d rc: %d", + ctx->base[i].idx, rc); + goto end; + } + } + +end: + return rc; +} + +static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, + void *release_hw_args) +{ + int rc = 0; + struct cam_hw_release_args *release_args = release_hw_args; + struct cam_tfe_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_tfe_hw_mgr_ctx *ctx; + uint32_t i; + + if (!hw_mgr_priv || !release_hw_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_tfe_hw_mgr_ctx *)release_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "Enter...ctx id:%d", + ctx->ctx_index); + + if (ctx->init_done) + cam_tfe_hw_mgr_deinit_hw(ctx); + + /* we should called the stop hw before this already */ + cam_tfe_hw_mgr_release_hw_for_ctx(ctx); + + /* reset base info */ + ctx->num_base = 0; + memset(ctx->base, 0, sizeof(ctx->base)); + + /* release cdm handle */ + cam_cdm_release(ctx->cdm_handle); + + /* clean context */ + list_del_init(&ctx->list); + ctx->ctx_in_use = 0; + ctx->is_rdi_only_context = 0; + ctx->cdm_handle = 0; + ctx->cdm_ops = NULL; + ctx->init_done = false; + ctx->is_dual = false; + ctx->is_tpg = false; + ctx->res_list_tpg.res_type = CAM_ISP_RESOURCE_MAX; + atomic_set(&ctx->overflow_pending, 0); + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + ctx->sof_cnt[i] = 0; + ctx->eof_cnt[i] = 0; + ctx->epoch_cnt[i] = 0; + } + CAM_DBG(CAM_ISP, "Exit...ctx id:%d", + ctx->ctx_index); + cam_tfe_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx); + return rc; +} + + +static int cam_isp_tfe_blob_hfr_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_tfe_resource_hfr_config *hfr_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_isp_tfe_port_hfr_config *port_hfr_config; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_tfe_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + uint32_t res_id_out, i; + uint32_t total_used_bytes = 0; + uint32_t kmd_buf_remain_size; + uint32_t *cmd_buf_addr; + uint32_t bytes_used = 0; + int num_ent, rc = 0; + + ctx = prepare->ctxt_to_hw_map; + CAM_DBG(CAM_ISP, "num_ports= %d", hfr_config->num_ports); + + /* Max one hw entries required for hfr config update */ + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + kmd_buf_info = blob_info->kmd_buf_info; + for (i = 0; i < hfr_config->num_ports; i++) { + port_hfr_config = &hfr_config->port_hfr_config[i]; + res_id_out = port_hfr_config->resource_type & 0xFF; + + CAM_DBG(CAM_ISP, "hfr config idx %d, type=%d", i, + res_id_out); + + if (res_id_out >= CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "invalid out restype:%x", + port_hfr_config->resource_type); + return -EINVAL; + } + + if ((kmd_buf_info->used_bytes + + total_used_bytes) < kmd_buf_info->size) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + total_used_bytes); + } else { + CAM_ERR(CAM_ISP, + "no free kmd memory for base %d", + blob_info->base_info->idx); + rc = -ENOMEM; + return rc; + } + + cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + total_used_bytes/4; + hw_mgr_res = &ctx->res_list_tfe_out[res_id_out]; + + rc = cam_isp_add_cmd_buf_update( + hw_mgr_res, blob_type, CAM_ISP_HW_CMD_GET_HFR_UPDATE, + blob_info->base_info->idx, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)port_hfr_config, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed cmd_update, base_idx=%d, rc=%d", + blob_info->base_info->idx, bytes_used); + return rc; + } + + total_used_bytes += bytes_used; + } + + if (total_used_bytes) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + num_ent++; + + kmd_buf_info->used_bytes += total_used_bytes; + kmd_buf_info->offset += total_used_bytes; + prepare->num_hw_update_entries = num_ent; + } + + return rc; +} + +static int cam_isp_tfe_blob_csid_clock_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_tfe_csid_clock_config *clock_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_tfe_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_csid_clock_update_args csid_clock_upd_args; + struct cam_top_tpg_clock_update_args tpg_clock_upd_args; + uint64_t clk_rate = 0; + int rc = -EINVAL; + uint32_t i; + + ctx = prepare->ctxt_to_hw_map; + + CAM_DBG(CAM_ISP, "csid clk=%llu", clock_config->csid_clock); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + clk_rate = 0; + if (!hw_mgr_res->hw_res[i]) + continue; + clk_rate = clock_config->csid_clock; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + csid_clock_upd_args.clk_rate = clk_rate; + CAM_DBG(CAM_ISP, "i= %d csid clk=%llu", + i, csid_clock_upd_args.clk_rate); + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE, + &csid_clock_upd_args, + sizeof( + struct cam_tfe_csid_clock_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } + } + + if (ctx->res_list_tpg.res_type == CAM_ISP_RESOURCE_TPG) { + tpg_clock_upd_args.clk_rate = clock_config->phy_clock; + hw_intf = ctx->res_list_tpg.hw_res[0]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + CAM_DBG(CAM_ISP, "i= %d phy clk=%llu", + tpg_clock_upd_args.clk_rate); + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE, + &tpg_clock_upd_args, + sizeof(struct cam_top_tpg_clock_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } + + return rc; +} + +static int cam_isp_tfe_blob_clock_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_tfe_clock_config *clock_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_tfe_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_clock_update_args clock_upd_args; + uint64_t clk_rate = 0; + int rc = -EINVAL; + uint32_t i; + uint32_t j; + bool camif_l_clk_updated = false; + bool camif_r_clk_updated = false; + + ctx = prepare->ctxt_to_hw_map; + + CAM_DBG(CAM_PERF, + "usage=%u left_clk= %lu right_clk=%lu", + clock_config->usage_type, + clock_config->left_pix_hz, + clock_config->right_pix_hz); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + clk_rate = 0; + if (!hw_mgr_res->hw_res[i]) + continue; + + if (hw_mgr_res->res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + if (i == CAM_ISP_HW_SPLIT_LEFT) { + if (camif_l_clk_updated) + continue; + + clk_rate = + clock_config->left_pix_hz; + + camif_l_clk_updated = true; + } else { + if (camif_r_clk_updated) + continue; + + clk_rate = + clock_config->right_pix_hz; + + camif_r_clk_updated = true; + } + } else if ((hw_mgr_res->res_id >= + CAM_ISP_HW_TFE_IN_RDI0) && (hw_mgr_res->res_id + <= CAM_ISP_HW_TFE_IN_RDI2)) { + for (j = 0; j < clock_config->num_rdi; j++) + clk_rate = max(clock_config->rdi_hz[j], + clk_rate); + } else { + CAM_ERR(CAM_ISP, "Invalid res_id %u", + hw_mgr_res->res_id); + rc = -EINVAL; + return rc; + } + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + clock_upd_args.node_res = + hw_mgr_res->hw_res[i]; + CAM_DBG(CAM_ISP, + "res_id=%u i= %d clk=%llu", + hw_mgr_res->res_id, i, clk_rate); + + clock_upd_args.clk_rate = clk_rate; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CLOCK_UPDATE, + &clock_upd_args, + sizeof( + struct cam_tfe_clock_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update failed"); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + +static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, + uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) +{ + int rc = 0; + struct cam_isp_generic_blob_info *blob_info = user_data; + struct cam_hw_prepare_update_args *prepare = NULL; + + if (!blob_data || (blob_size == 0) || !blob_info) { + CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK", + blob_data, blob_size, blob_info); + return -EINVAL; + } + + prepare = blob_info->prepare; + if (!prepare) { + CAM_ERR(CAM_ISP, "Failed. prepare is NULL, blob_type %d", + blob_type); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "BLOB Type: %d", blob_type); + switch (blob_type) { + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_HFR_CONFIG: { + struct cam_isp_tfe_resource_hfr_config *hfr_config = + (struct cam_isp_tfe_resource_hfr_config *)blob_data; + + if (blob_size < + sizeof(struct cam_isp_tfe_resource_hfr_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + if (hfr_config->num_ports > CAM_ISP_TFE_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid num_ports %u in hfr config", + hfr_config->num_ports); + return -EINVAL; + } + + /* Check for integer overflow */ + if (hfr_config->num_ports > 1) { + if (sizeof(struct cam_isp_tfe_resource_hfr_config) > + ((UINT_MAX - + sizeof(struct cam_isp_tfe_resource_hfr_config)) + / (hfr_config->num_ports - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in hfr config num_ports:%u size per port:%lu", + hfr_config->num_ports, + sizeof(struct + cam_isp_tfe_resource_hfr_config)); + return -EINVAL; + } + } + + if ((hfr_config->num_ports != 0) && (blob_size < + (sizeof(struct cam_isp_tfe_resource_hfr_config) + + (hfr_config->num_ports - 1) * + sizeof(struct cam_isp_tfe_resource_hfr_config)))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(struct cam_isp_tfe_resource_hfr_config) + + (hfr_config->num_ports - 1) * + sizeof(struct cam_isp_tfe_resource_hfr_config)); + return -EINVAL; + } + + rc = cam_isp_tfe_blob_hfr_update(blob_type, blob_info, + hfr_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "HFR Update Failed"); + } + break; + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_CLOCK_CONFIG: { + struct cam_isp_tfe_clock_config *clock_config = + (struct cam_isp_tfe_clock_config *)blob_data; + + if (blob_size < sizeof(struct cam_isp_tfe_clock_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + if (clock_config->num_rdi > CAM_TFE_RDI_NUM_MAX) { + CAM_ERR(CAM_ISP, "Invalid num_rdi %u in clock config", + clock_config->num_rdi); + return -EINVAL; + } + /* Check integer overflow */ + if (clock_config->num_rdi > 1) { + if (sizeof(uint64_t) > ((UINT_MAX- + sizeof(struct cam_isp_tfe_clock_config))/ + (clock_config->num_rdi - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in clock config num_rdi:%u size per port:%lu", + clock_config->num_rdi, + sizeof(uint64_t)); + return -EINVAL; + } + } + + if ((clock_config->num_rdi != 0) && (blob_size < + (sizeof(struct cam_isp_tfe_clock_config) + + sizeof(uint64_t) * (clock_config->num_rdi - 1)))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(uint32_t) * 2 + sizeof(uint64_t) * + (clock_config->num_rdi + 2)); + return -EINVAL; + } + + rc = cam_isp_tfe_blob_clock_update(blob_type, blob_info, + clock_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update Failed"); + } + break; + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_CONFIG_V2: { + size_t bw_config_size = 0; + struct cam_isp_tfe_bw_config_v2 *bw_config = + (struct cam_isp_tfe_bw_config_v2 *)blob_data; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + if (blob_size < sizeof(struct cam_isp_tfe_bw_config_v2)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size); + return -EINVAL; + } + + if (bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) { + CAM_ERR(CAM_ISP, "Invalid num paths %d", + bw_config->num_paths); + return -EINVAL; + } + + /* Check for integer overflow */ + if (bw_config->num_paths > 1) { + if (sizeof(struct cam_axi_per_path_bw_vote) > + ((UINT_MAX - + sizeof(struct cam_isp_tfe_bw_config_v2)) / + (bw_config->num_paths - 1))) { + CAM_ERR(CAM_ISP, + "Size exceeds limit paths:%u size per path:%lu", + bw_config->num_paths - 1, + sizeof( + struct cam_axi_per_path_bw_vote)); + return -EINVAL; + } + } + + if ((bw_config->num_paths != 0) && (blob_size < + (sizeof(struct cam_isp_tfe_bw_config_v2) + + ((bw_config->num_paths - 1) * + sizeof(struct cam_axi_per_path_bw_vote))))) { + CAM_ERR(CAM_ISP, + "Invalid blob size: %u, num_paths: %u, bw_config size: %lu, per_path_vote size: %lu", + blob_size, bw_config->num_paths, + sizeof(struct cam_isp_tfe_bw_config_v2), + sizeof(struct cam_axi_per_path_bw_vote)); + return -EINVAL; + } + + if (!prepare || !prepare->priv || + (bw_config->usage_type >= CAM_TFE_HW_NUM_MAX)) { + CAM_ERR(CAM_ISP, "Invalid inputs"); + return -EINVAL; + } + + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + memset(&prepare_hw_data->bw_config_v2[bw_config->usage_type], + 0, sizeof( + prepare_hw_data->bw_config_v2[bw_config->usage_type])); + bw_config_size = sizeof(struct cam_isp_bw_config_internal_v2) + + ((bw_config->num_paths - 1) * + sizeof(struct cam_axi_per_path_bw_vote)); + memcpy(&prepare_hw_data->bw_config_v2[bw_config->usage_type], + bw_config, bw_config_size); + + prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V2; + prepare_hw_data->bw_config_valid[bw_config->usage_type] = true; + } + + break; + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG: { + struct cam_isp_tfe_csid_clock_config *clock_config = + (struct cam_isp_tfe_csid_clock_config *)blob_data; + + if (blob_size < sizeof(struct cam_isp_tfe_csid_clock_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u", + blob_size, + sizeof(struct cam_isp_tfe_csid_clock_config)); + return -EINVAL; + } + rc = cam_isp_tfe_blob_csid_clock_update(blob_type, blob_info, + clock_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update Failed"); + } + break; + default: + CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); + break; + } + + return rc; +} + +static int cam_tfe_update_dual_config( + struct cam_hw_prepare_update_args *prepare, + struct cam_cmd_buf_desc *cmd_desc, + uint32_t split_id, + uint32_t base_idx, + struct cam_isp_hw_mgr_res *res_list_isp_out, + uint32_t size_isp_out) +{ + int rc = -EINVAL; + struct cam_isp_tfe_dual_config *dual_config; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *res; + struct cam_tfe_dual_update_args dual_isp_update_args; + uint32_t outport_id; + size_t len = 0, remain_len = 0; + uint32_t *cpu_addr; + uint32_t i, j, stp_index; + + CAM_DBG(CAM_ISP, "cmd des size %d, length: %d", + cmd_desc->size, cmd_desc->length); + + rc = cam_packet_util_get_cmd_mem_addr( + cmd_desc->mem_handle, &cpu_addr, &len); + if (rc) { + CAM_DBG(CAM_ISP, "unable to get cmd mem addr handle:0x%x", + cmd_desc->mem_handle); + return rc; + } + + if ((len < sizeof(struct cam_isp_tfe_dual_config)) || + (cmd_desc->offset >= + (len - sizeof(struct cam_isp_tfe_dual_config)))) { + CAM_ERR(CAM_ISP, "not enough buffer provided"); + return -EINVAL; + } + + remain_len = len - cmd_desc->offset; + cpu_addr += (cmd_desc->offset / 4); + dual_config = (struct cam_isp_tfe_dual_config *)cpu_addr; + + if ((dual_config->num_ports * + sizeof(struct cam_isp_tfe_dual_stripe_config)) > + (remain_len - + offsetof(struct cam_isp_tfe_dual_config, stripes))) { + CAM_ERR(CAM_ISP, "not enough buffer for all the dual configs"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "num_ports:%d", dual_config->num_ports); + if (dual_config->num_ports >= size_isp_out) { + CAM_ERR(CAM_UTIL, + "inval num ports %d max num tfe ports:%d", + dual_config->num_ports, size_isp_out); + rc = -EINVAL; + goto end; + } + + for (i = 0; i < dual_config->num_ports; i++) { + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { + stp_index = (i * CAM_PACKET_MAX_PLANES) + + (j * (CAM_PACKET_MAX_PLANES * + dual_config->num_ports)); + + if (!dual_config->stripes[stp_index].port_id) + continue; + + outport_id = dual_config->stripes[stp_index].port_id; + if (outport_id >= size_isp_out) { + CAM_ERR(CAM_UTIL, + "inval outport id:%d i:%d j:%d num ports:%d ", + outport_id, i, j, + dual_config->num_ports); + rc = -EINVAL; + goto end; + } + + hw_mgr_res = &res_list_isp_out[outport_id]; + 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]; + + if (res->res_id < CAM_ISP_TFE_OUT_RES_BASE || + res->res_id >= CAM_ISP_TFE_OUT_RES_MAX) { + CAM_DBG(CAM_ISP, "res id :%d", res->res_id); + continue; + } + + dual_isp_update_args.split_id = j; + dual_isp_update_args.res = res; + dual_isp_update_args.stripe_config = + &dual_config->stripes[stp_index]; + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_STRIPE_UPDATE, + &dual_isp_update_args, + sizeof(struct cam_tfe_dual_update_args)); + if (rc) + goto end; + } + } + +end: + return rc; +} + +int cam_tfe_add_command_buffers( + struct cam_hw_prepare_update_args *prepare, + struct cam_kmd_buf_info *kmd_buf_info, + struct cam_isp_ctx_base_info *base_info, + cam_packet_generic_blob_handler blob_handler_cb, + struct cam_isp_hw_mgr_res *res_list_isp_out, + uint32_t size_isp_out) +{ + int rc = 0; + uint32_t cmd_meta_data, num_ent, i; + uint32_t base_idx; + enum cam_isp_hw_split_id split_id; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_hw_update_entry *hw_entry; + + hw_entry = prepare->hw_update_entries; + split_id = base_info->split_id; + base_idx = base_info->idx; + + /* + * set the cmd_desc to point the first command descriptor in the + * packet + */ + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint8_t *)&prepare->packet->payload + + prepare->packet->cmd_buf_offset); + + CAM_DBG(CAM_ISP, "split id = %d, number of command buffers:%d", + split_id, prepare->packet->num_cmd_buf); + + for (i = 0; i < prepare->packet->num_cmd_buf; i++) { + num_ent = prepare->num_hw_update_entries; + if (!cmd_desc[i].length) + continue; + + /* One hw entry space required for left or right or common */ + if (num_ent + 1 >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); + return -EINVAL; + } + + rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); + if (rc) + return rc; + + cmd_meta_data = cmd_desc[i].meta_data; + + CAM_DBG(CAM_ISP, "meta type: %d, split_id: %d", + cmd_meta_data, split_id); + + switch (cmd_meta_data) { + case CAM_ISP_TFE_PACKET_META_BASE: + case CAM_ISP_TFE_PACKET_META_LEFT: + if (split_id == CAM_ISP_HW_SPLIT_LEFT) { + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].handle = + cmd_desc[i].mem_handle; + hw_entry[num_ent].offset = cmd_desc[i].offset; + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; + CAM_DBG(CAM_ISP, + "Meta_Left num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + + num_ent++; + } + break; + case CAM_ISP_TFE_PACKET_META_RIGHT: + if (split_id == CAM_ISP_HW_SPLIT_RIGHT) { + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].handle = + cmd_desc[i].mem_handle; + hw_entry[num_ent].offset = cmd_desc[i].offset; + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; + CAM_DBG(CAM_ISP, + "Meta_Right num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + + num_ent++; + } + break; + case CAM_ISP_TFE_PACKET_META_COMMON: + hw_entry[num_ent].len = cmd_desc[i].length; + hw_entry[num_ent].handle = + cmd_desc[i].mem_handle; + hw_entry[num_ent].offset = cmd_desc[i].offset; + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; + CAM_DBG(CAM_ISP, + "Meta_Common num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + if (cmd_meta_data == CAM_ISP_PACKET_META_DMI_COMMON) + hw_entry[num_ent].flags = 0x1; + + num_ent++; + break; + case CAM_ISP_TFE_PACKET_META_DUAL_CONFIG: + + rc = cam_tfe_update_dual_config(prepare, + &cmd_desc[i], split_id, base_idx, + res_list_isp_out, size_isp_out); + + if (rc) + return rc; + break; + case CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_COMMON: { + struct cam_isp_generic_blob_info blob_info; + + prepare->num_hw_update_entries = num_ent; + blob_info.prepare = prepare; + blob_info.base_info = base_info; + blob_info.kmd_buf_info = kmd_buf_info; + + rc = cam_packet_util_process_generic_cmd_buffer( + &cmd_desc[i], + blob_handler_cb, + &blob_info); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in processing blobs %d", rc); + return rc; + } + hw_entry[num_ent].flags = CAM_ISP_IQ_BL; + num_ent = prepare->num_hw_update_entries; + } + break; + case CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH: + case CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR: + if (split_id == CAM_ISP_HW_SPLIT_LEFT) { + if (prepare->num_reg_dump_buf >= + CAM_REG_DUMP_MAX_BUF_ENTRIES) { + CAM_ERR(CAM_ISP, + "Descriptor count out of bounds: %d", + prepare->num_reg_dump_buf); + return -EINVAL; + } + prepare->reg_dump_buf_desc[ + prepare->num_reg_dump_buf] = + cmd_desc[i]; + prepare->num_reg_dump_buf++; + CAM_DBG(CAM_ISP, + "Added command buffer: %d desc_count: %d", + cmd_desc[i].meta_data, + prepare->num_reg_dump_buf); + } + break; + default: + CAM_ERR(CAM_ISP, "invalid cdm command meta data %d", + cmd_meta_data); + return -EINVAL; + } + prepare->num_hw_update_entries = num_ent; + } + + return rc; +} + +static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, + void *prepare_hw_update_args) +{ + int rc = 0; + struct cam_hw_prepare_update_args *prepare = + (struct cam_hw_prepare_update_args *) prepare_hw_update_args; + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_tfe_hw_mgr *hw_mgr; + struct cam_kmd_buf_info kmd_buf; + uint32_t i; + bool fill_fence = true; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + if (!hw_mgr_priv || !prepare_hw_update_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + CAM_DBG(CAM_REQ, "Enter for req_id %lld", + prepare->packet->header.request_id); + + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + ctx = (struct cam_tfe_hw_mgr_ctx *) prepare->ctxt_to_hw_map; + hw_mgr = (struct cam_tfe_hw_mgr *)hw_mgr_priv; + + rc = cam_packet_util_validate_packet(prepare->packet, + prepare->remain_len); + if (rc) + return rc; + + /* Pre parse the packet*/ + rc = cam_packet_util_get_kmd_buffer(prepare->packet, &kmd_buf); + if (rc) + return rc; + + rc = cam_packet_util_process_patches(prepare->packet, + hw_mgr->mgr_common.cmd_iommu_hdl, + hw_mgr->mgr_common.cmd_iommu_hdl_secure); + if (rc) { + CAM_ERR(CAM_ISP, "Patch ISP packet failed."); + return rc; + } + + prepare->num_hw_update_entries = 0; + prepare->num_in_map_entries = 0; + prepare->num_out_map_entries = 0; + prepare->num_reg_dump_buf = 0; + + memset(&prepare_hw_data->bw_config[0], 0x0, + sizeof(prepare_hw_data->bw_config[0]) * + CAM_TFE_HW_NUM_MAX); + memset(&prepare_hw_data->bw_config_valid[0], 0x0, + sizeof(prepare_hw_data->bw_config_valid[0]) * + CAM_TFE_HW_NUM_MAX); + + for (i = 0; i < ctx->num_base; i++) { + CAM_DBG(CAM_ISP, "process cmd buffer for device %d", i); + + CAM_DBG(CAM_ISP, + "change base i=%d, idx=%d", + i, ctx->base[i].idx); + + /* Add change base */ + rc = cam_isp_add_change_base(prepare, &ctx->res_list_tfe_in, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in change base i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + + + /* get command buffers */ + if (ctx->base[i].split_id != CAM_ISP_HW_SPLIT_MAX) { + rc = cam_tfe_add_command_buffers(prepare, &kmd_buf, + &ctx->base[i], + cam_isp_tfe_packet_generic_blob_handler, + ctx->res_list_tfe_out, CAM_TFE_HW_OUT_RES_MAX); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in add cmdbuf, i=%d, split_id=%d, rc=%d", + i, ctx->base[i].split_id, rc); + goto end; + } + } + + /* get IO buffers */ + rc = cam_isp_add_io_buffers(hw_mgr->mgr_common.img_iommu_hdl, + hw_mgr->mgr_common.img_iommu_hdl_secure, + prepare, ctx->base[i].idx, + &kmd_buf, ctx->res_list_tfe_out, + NULL, + CAM_TFE_HW_OUT_RES_MAX, fill_fence); + + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in io buffers, i=%d, rc=%d", + i, rc); + goto end; + } + + /* fence map table entries need to fill only once in the loop */ + if (fill_fence) + fill_fence = false; + } + + ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; + if ((ctx->num_reg_dump_buf) && (ctx->num_reg_dump_buf < + CAM_REG_DUMP_MAX_BUF_ENTRIES)) { + memcpy(ctx->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare->num_reg_dump_buf); + } + + /* reg update will be done later for the initial configure */ + if (((prepare->packet->header.op_code) & 0xF) == + CAM_ISP_PACKET_INIT_DEV) { + prepare_hw_data->packet_opcode_type = + CAM_ISP_TFE_PACKET_INIT_DEV; + goto end; + } else + prepare_hw_data->packet_opcode_type = + CAM_ISP_TFE_PACKET_CONFIG_DEV; + + /* add reg update commands */ + for (i = 0; i < ctx->num_base; i++) { + /* Add change base */ + rc = cam_isp_add_change_base(prepare, &ctx->res_list_tfe_in, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in change base adding reg_update cmd i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + + /*Add reg update */ + rc = cam_isp_add_reg_update(prepare, &ctx->res_list_tfe_in, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Add Reg_update cmd Failed i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + } + +end: + return rc; +} + +static int cam_tfe_mgr_resume_hw(struct cam_tfe_hw_mgr_ctx *ctx) +{ + return cam_tfe_mgr_bw_control(ctx, CAM_TFE_BW_CONTROL_INCLUDE); +} + +static int cam_tfe_mgr_sof_irq_debug( + struct cam_tfe_hw_mgr_ctx *ctx, + uint32_t sof_irq_enable) +{ + int rc = 0; + uint32_t i = 0; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; + struct cam_hw_intf *hw_intf = NULL; + struct cam_isp_resource_node *rsrc_node = NULL; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, 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_ops.process_cmd) { + rc |= hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_TFE_CSID_SOF_IRQ_DEBUG, + &sof_irq_enable, + sizeof(sof_irq_enable)); + } + } + } + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->process_cmd && (rsrc_node->res_id == + CAM_ISP_HW_TFE_IN_CAMIF)) { + rc |= hw_mgr_res->hw_res[i]->process_cmd( + hw_mgr_res->hw_res[i], + CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, + &sof_irq_enable, + sizeof(sof_irq_enable)); + } + } + } + + return rc; +} + +static void cam_tfe_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + dma_addr_t iova_addr; + size_t src_buf_size; + int i, j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + 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", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "get src buf address fail mem_handle 0x%x", + io_cfg[i].mem_handle[j]); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_ISP, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_ISP, + "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 + + (unsigned int)src_buf_size, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + } + } +} + +static void cam_tfe_mgr_ctx_irq_dump(struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_get_cmd_update cmd_update; + int i = 0; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) + continue; + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + switch (hw_mgr_res->hw_res[i]->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + cmd_update.res = hw_mgr_res->hw_res[i]; + cmd_update.cmd_type = + CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP; + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, + &cmd_update, sizeof(cmd_update)); + break; + default: + break; + } + } + } +} + +static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_tfe_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_tfe_hw_mgr_ctx *ctx = (struct cam_tfe_hw_mgr_ctx *) + hw_cmd_args->ctxt_to_hw_map; + struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Fatal: Invalid context is used"); + return -EPERM; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_INTERNAL: + if (!hw_cmd_args->u.internal_args) { + CAM_ERR(CAM_ISP, "Invalid cmd arguments"); + return -EINVAL; + } + + isp_hw_cmd_args = (struct cam_isp_hw_cmd_args *) + hw_cmd_args->u.internal_args; + + switch (isp_hw_cmd_args->cmd_type) { + case CAM_ISP_HW_MGR_CMD_PAUSE_HW: + cam_tfe_mgr_pause_hw(ctx); + break; + case CAM_ISP_HW_MGR_CMD_RESUME_HW: + cam_tfe_mgr_resume_hw(ctx); + break; + case CAM_ISP_HW_MGR_CMD_SOF_DEBUG: + cam_tfe_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_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); + rc = -EINVAL; + break; + } + break; + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_tfe_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->mgr_common.img_iommu_hdl, + hw_mgr->mgr_common.img_iommu_hdl_secure, + hw_cmd_args->u.pf_args.buf_info, + hw_cmd_args->u.pf_args.mem_found); + break; + case CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH: + if (ctx->last_dump_flush_req_id == ctx->applied_req_id) + return 0; + + ctx->last_dump_flush_req_id = ctx->applied_req_id; + + rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, + CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump on flush failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + return rc; + } + + break; + case CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR: + if (ctx->last_dump_err_req_id == ctx->applied_req_id) + return 0; + + ctx->last_dump_err_req_id = ctx->applied_req_id; + rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, + CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump on error failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + return rc; + } + break; + + default: + CAM_ERR(CAM_ISP, "Invalid cmd"); + } + + return rc; +} + +static int cam_tfe_mgr_cmd_get_sof_timestamp( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + uint64_t *time_stamp, + uint64_t *boot_time_stamp) +{ + int rc = -EINVAL; + uint32_t i; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_csid_get_time_stamp_args csid_get_time; + + list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + /* + * Get the SOF time stamp from left resource only. + * Left resource is master for dual tfe 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 TFE case, Get the time stamp from + * available one csid hw in the context + * Dual TFE 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( + hw_intf->hw_priv, + CAM_TFE_CSID_CMD_GET_TIME_STAMP, + &csid_get_time, + sizeof(struct + cam_tfe_csid_get_time_stamp_args)); + if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { + *time_stamp = + csid_get_time.time_stamp_val; + *boot_time_stamp = + csid_get_time.boot_timestamp; + } + } + } + } + + if (rc) + CAM_ERR_RATE_LIMIT(CAM_ISP, "Getting sof time stamp failed"); + + return rc; +} + +static void cam_tfe_mgr_ctx_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_get_cmd_update cmd_update; + int i = 0; + + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, + list) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) + continue; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + switch (hw_mgr_res->hw_res[i]->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + cmd_update.res = hw_mgr_res->hw_res[i]; + cmd_update.cmd_type = + CAM_ISP_HW_CMD_GET_REG_DUMP; + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_REG_DUMP, + &cmd_update, sizeof(cmd_update)); + break; + default: + break; + } + } + } + + /* Dump the TFE CSID registers */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, + 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_ops.process_cmd) { + hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_TFE_CSID_CMD_GET_REG_DUMP, + hw_mgr_res->hw_res[i], + sizeof(struct cam_isp_resource_node)); + } + } + } +} + +static int cam_tfe_mgr_process_recovery_cb(void *priv, void *data) +{ + int32_t rc = 0; + struct cam_tfe_hw_event_recovery_data *recovery_data = data; + struct cam_hw_start_args start_args; + struct cam_hw_stop_args stop_args; + struct cam_tfe_hw_mgr *tfe_hw_mgr = priv; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx; + uint32_t i = 0; + + uint32_t error_type = recovery_data->error_type; + struct cam_tfe_hw_mgr_ctx *ctx = NULL; + + /* Here recovery is performed */ + CAM_DBG(CAM_ISP, "ErrorType = %d", error_type); + + switch (error_type) { + case CAM_ISP_HW_ERROR_OVERFLOW: + case CAM_ISP_HW_ERROR_BUSIF_OVERFLOW: + if (!recovery_data->affected_ctx[0]) { + CAM_ERR(CAM_ISP, + "No context is affected but recovery called"); + kfree(recovery_data); + return 0; + } + + /* stop resources here */ + CAM_DBG(CAM_ISP, "STOP: Number of affected context: %d", + recovery_data->no_of_context); + for (i = 0; i < recovery_data->no_of_context; i++) { + stop_args.ctxt_to_hw_map = + recovery_data->affected_ctx[i]; + tfe_hw_mgr_ctx = recovery_data->affected_ctx[i]; + + if (g_tfe_hw_mgr.debug_cfg.enable_reg_dump) + cam_tfe_mgr_ctx_reg_dump(tfe_hw_mgr_ctx); + + if (g_tfe_hw_mgr.debug_cfg.enable_recovery) { + rc = cam_tfe_mgr_stop_hw_in_overflow( + &stop_args); + if (rc) { + CAM_ERR(CAM_ISP, + "CTX stop failed(%d)", rc); + return rc; + } + } + } + + if (!g_tfe_hw_mgr.debug_cfg.enable_recovery) { + CAM_INFO(CAM_ISP, "reg dumping is done "); + return 0; + } + + CAM_DBG(CAM_ISP, "RESET: CSID PATH"); + for (i = 0; i < recovery_data->no_of_context; i++) { + ctx = recovery_data->affected_ctx[i]; + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, + list) { + rc = cam_tfe_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed RESET (%d)", + hw_mgr_res->res_id); + return rc; + } + } + } + + CAM_DBG(CAM_ISP, "RESET: Calling TFE reset"); + + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (recovery_data->affected_core[i]) + cam_tfe_mgr_reset_tfe_hw(tfe_hw_mgr, i); + } + + CAM_DBG(CAM_ISP, "START: Number of affected context: %d", + recovery_data->no_of_context); + + for (i = 0; i < recovery_data->no_of_context; i++) { + ctx = recovery_data->affected_ctx[i]; + start_args.ctxt_to_hw_map = ctx; + + atomic_set(&ctx->overflow_pending, 0); + + rc = cam_tfe_mgr_restart_hw(&start_args); + if (rc) { + CAM_ERR(CAM_ISP, "CTX start failed(%d)", rc); + return rc; + } + CAM_DBG(CAM_ISP, "Started resources rc (%d)", rc); + } + CAM_DBG(CAM_ISP, "Recovery Done rc (%d)", rc); + + break; + + case CAM_ISP_HW_ERROR_P2I_ERROR: + break; + + case CAM_ISP_HW_ERROR_VIOLATION: + break; + + default: + CAM_ERR(CAM_ISP, "Invalid Error"); + } + CAM_DBG(CAM_ISP, "Exit: ErrorType = %d", error_type); + + kfree(recovery_data); + return rc; +} + +static int cam_tfe_hw_mgr_do_error_recovery( + struct cam_tfe_hw_event_recovery_data *tfe_mgr_recovery_data) +{ + int32_t rc = 0; + struct crm_workq_task *task = NULL; + struct cam_tfe_hw_event_recovery_data *recovery_data = NULL; + + recovery_data = kmemdup(tfe_mgr_recovery_data, + sizeof(struct cam_tfe_hw_event_recovery_data), GFP_ATOMIC); + + if (!recovery_data) + return -ENOMEM; + + CAM_DBG(CAM_ISP, "Enter: error_type (%d)", recovery_data->error_type); + + task = cam_req_mgr_workq_get_task(g_tfe_hw_mgr.workq); + if (!task) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No empty task frame"); + kfree(recovery_data); + return -ENOMEM; + } + + task->process_cb = &cam_tfe_mgr_process_recovery_cb; + task->payload = recovery_data; + rc = cam_req_mgr_workq_enqueue_task(task, + recovery_data->affected_ctx[0]->hw_mgr, + CRM_TASK_PRIORITY_0); + + return rc; +} + +/* + * This function checks if any of the valid entry in affected_core[] + * is associated with this context. if YES + * a. It fills the other cores associated with this context.in + * affected_core[] + * b. Return true + */ +static bool cam_tfe_hw_mgr_is_ctx_affected( + struct cam_tfe_hw_mgr_ctx *tfe_hwr_mgr_ctx, + uint32_t *affected_core, + uint32_t size) +{ + + bool rc = false; + uint32_t i = 0, j = 0; + uint32_t max_idx = tfe_hwr_mgr_ctx->num_base; + uint32_t ctx_affected_core_idx[CAM_TFE_HW_NUM_MAX] = {0}; + + CAM_DBG(CAM_ISP, "Enter:max_idx = %d", max_idx); + + if ((max_idx >= CAM_TFE_HW_NUM_MAX) || (size > CAM_TFE_HW_NUM_MAX)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "invalid parameter = %d", max_idx); + return rc; + } + + for (i = 0; i < max_idx; i++) { + if (affected_core[tfe_hwr_mgr_ctx->base[i].idx]) + rc = true; + else { + ctx_affected_core_idx[j] = tfe_hwr_mgr_ctx->base[i].idx; + j = j + 1; + } + } + + if (rc) { + while (j) { + if (affected_core[ctx_affected_core_idx[j-1]] != 1) + affected_core[ctx_affected_core_idx[j-1]] = 1; + j = j - 1; + } + } + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +/* + * For any dual TFE context, if non-affected TFE is also serving + * another context, then that context should also be notified with fatal error + * So Loop through each context and - + * a. match core_idx + * b. Notify CTX with fatal error + */ +static int cam_tfe_hw_mgr_find_affected_ctx( + struct cam_isp_hw_error_event_data *error_event_data, + uint32_t curr_core_idx, + struct cam_tfe_hw_event_recovery_data *recovery_data) +{ + uint32_t affected_core[CAM_TFE_HW_NUM_MAX] = {0}; + struct cam_tfe_hw_mgr_ctx *tfe_hwr_mgr_ctx = NULL; + cam_hw_event_cb_func notify_err_cb; + struct cam_tfe_hw_mgr *tfe_hwr_mgr = NULL; + enum cam_isp_hw_event_type event_type = CAM_ISP_HW_EVENT_ERROR; + uint32_t i = 0; + + if (!recovery_data) { + CAM_ERR(CAM_ISP, "recovery_data parameter is NULL"); + return -EINVAL; + } + + recovery_data->no_of_context = 0; + affected_core[curr_core_idx] = 1; + tfe_hwr_mgr = &g_tfe_hw_mgr; + + list_for_each_entry(tfe_hwr_mgr_ctx, + &tfe_hwr_mgr->used_ctx_list, list) { + /* + * Check if current core_idx matches the HW associated + * with this context + */ + if (!cam_tfe_hw_mgr_is_ctx_affected(tfe_hwr_mgr_ctx, + affected_core, CAM_TFE_HW_NUM_MAX)) + continue; + + atomic_set(&tfe_hwr_mgr_ctx->overflow_pending, 1); + notify_err_cb = tfe_hwr_mgr_ctx->common.event_cb[event_type]; + + /* Add affected_context in list of recovery data */ + CAM_DBG(CAM_ISP, "Add affected ctx %d to list", + tfe_hwr_mgr_ctx->ctx_index); + if (recovery_data->no_of_context < CAM_CTX_MAX) + recovery_data->affected_ctx[ + recovery_data->no_of_context++] = + tfe_hwr_mgr_ctx; + + /* + * In the call back function corresponding ISP context + * will update CRM about fatal Error + */ + notify_err_cb(tfe_hwr_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_ERROR, error_event_data); + } + + /* fill the affected_core in recovery data */ + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + recovery_data->affected_core[i] = affected_core[i]; + CAM_DBG(CAM_ISP, "tfe core %d is affected (%d)", + i, recovery_data->affected_core[i]); + } + + return 0; +} + +static int cam_tfe_hw_mgr_handle_hw_err( + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_tfe_hw_event_recovery_data recovery_data = {0}; + int rc = -EINVAL; + uint32_t core_idx; + + if (event_info->err_type == CAM_TFE_IRQ_STATUS_VIOLATION) + error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; + else if (event_info->res_type == CAM_ISP_RESOURCE_TFE_IN || + event_info->res_type == CAM_ISP_RESOURCE_PIX_PATH) + error_event_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; + else if (event_info->res_type == CAM_ISP_RESOURCE_TFE_OUT) + error_event_data.error_type = CAM_ISP_HW_ERROR_BUSIF_OVERFLOW; + + core_idx = event_info->hw_idx; + + if (g_tfe_hw_mgr.debug_cfg.enable_recovery) + error_event_data.recovery_enabled = true; + else + error_event_data.recovery_enabled = false; + + rc = cam_tfe_hw_mgr_find_affected_ctx(&error_event_data, + core_idx, &recovery_data); + + if (event_info->res_type == CAM_ISP_RESOURCE_TFE_OUT) + return rc; + + if (g_tfe_hw_mgr.debug_cfg.enable_recovery) { + /* Trigger for recovery */ + if (event_info->err_type == CAM_TFE_IRQ_STATUS_VIOLATION) + recovery_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; + else + recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; + cam_tfe_hw_mgr_do_error_recovery(&recovery_data); + } else { + CAM_DBG(CAM_ISP, "recovery is not enabled"); + rc = 0; + } + + return rc; +} + +static int cam_tfe_hw_mgr_handle_hw_rup( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; + cam_hw_event_cb_func tfe_hwr_irq_rup_cb; + struct cam_isp_hw_reg_update_event_data rup_event_data; + + tfe_hwr_irq_rup_cb = + tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_REG_UPDATE]; + + switch (event_info->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + if (tfe_hw_mgr_ctx->is_dual) + if (event_info->hw_idx != tfe_hw_mgr_ctx->master_hw_idx) + break; + + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + + tfe_hwr_irq_rup_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + break; + + case CAM_ISP_HW_TFE_IN_RDI0: + case CAM_ISP_HW_TFE_IN_RDI1: + case CAM_ISP_HW_TFE_IN_RDI2: + if (!tfe_hw_mgr_ctx->is_rdi_only_context) + break; + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hwr_irq_rup_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "RUP done for TFE source %d", + event_info->res_id); + + return 0; +} + +static int cam_tfe_hw_mgr_check_irq_for_dual_tfe( + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx, + uint32_t hw_event_type) +{ + int32_t rc = -EINVAL; + uint32_t *event_cnt = NULL; + uint32_t core_idx0 = 0; + uint32_t core_idx1 = 1; + + if (!tfe_hw_mgr_ctx->is_dual) + return 0; + + switch (hw_event_type) { + case CAM_ISP_HW_EVENT_SOF: + event_cnt = tfe_hw_mgr_ctx->sof_cnt; + break; + case CAM_ISP_HW_EVENT_EPOCH: + event_cnt = tfe_hw_mgr_ctx->epoch_cnt; + break; + case CAM_ISP_HW_EVENT_EOF: + event_cnt = tfe_hw_mgr_ctx->eof_cnt; + break; + default: + return 0; + } + + if (event_cnt[core_idx0] == event_cnt[core_idx1]) { + + event_cnt[core_idx0] = 0; + event_cnt[core_idx1] = 0; + + rc = 0; + return rc; + } + + if ((event_cnt[core_idx0] && + (event_cnt[core_idx0] - event_cnt[core_idx1] > 1)) || + (event_cnt[core_idx1] && + (event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) { + + if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt > 10) { + rc = -1; + return rc; + } + + CAM_ERR_RATE_LIMIT(CAM_ISP, + "One TFE could not generate hw event %d id0:%d id1:%d", + hw_event_type, event_cnt[core_idx0], + event_cnt[core_idx1]); + if (event_cnt[core_idx0] >= 2) { + event_cnt[core_idx0]--; + tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; + } + if (event_cnt[core_idx1] >= 2) { + event_cnt[core_idx1]--; + tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; + } + + if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt == 1) + cam_tfe_mgr_ctx_irq_dump(tfe_hw_mgr_ctx); + rc = 0; + } + + CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d", + hw_event_type); + + return rc; +} + +static int cam_tfe_hw_mgr_handle_hw_epoch( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; + cam_hw_event_cb_func tfe_hw_irq_epoch_cb; + struct cam_isp_hw_epoch_event_data epoch_done_event_data; + int rc = 0; + + tfe_hw_irq_epoch_cb = + tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EPOCH]; + + switch (event_info->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + tfe_hw_mgr_ctx->epoch_cnt[event_info->hw_idx]++; + rc = cam_tfe_hw_mgr_check_irq_for_dual_tfe(tfe_hw_mgr_ctx, + CAM_ISP_HW_EVENT_EPOCH); + if (!rc) { + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hw_irq_epoch_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); + } + break; + + case CAM_ISP_HW_TFE_IN_RDI0: + case CAM_ISP_HW_TFE_IN_RDI1: + case CAM_ISP_HW_TFE_IN_RDI2: + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "Epoch for TFE source %d", event_info->res_id); + + return 0; +} + +static int cam_tfe_hw_mgr_handle_hw_sof( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; + cam_hw_event_cb_func tfe_hw_irq_sof_cb; + struct cam_isp_hw_sof_event_data sof_done_event_data; + int rc = 0; + + tfe_hw_irq_sof_cb = + tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF]; + + switch (event_info->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + tfe_hw_mgr_ctx->sof_cnt[event_info->hw_idx]++; + rc = cam_tfe_hw_mgr_check_irq_for_dual_tfe(tfe_hw_mgr_ctx, + CAM_ISP_HW_EVENT_SOF); + if (!rc) { + cam_tfe_mgr_cmd_get_sof_timestamp(tfe_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); + + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + + tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + } + break; + + case CAM_ISP_HW_TFE_IN_RDI0: + case CAM_ISP_HW_TFE_IN_RDI1: + case CAM_ISP_HW_TFE_IN_RDI2: + if (!tfe_hw_mgr_ctx->is_rdi_only_context) + break; + cam_tfe_mgr_cmd_get_sof_timestamp(tfe_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "SOF for TFE source %d", event_info->res_id); + + return 0; +} + +static int cam_tfe_hw_mgr_handle_hw_eof( + void *ctx, + void *evt_info) +{ + struct cam_isp_hw_event_info *event_info = evt_info; + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; + cam_hw_event_cb_func tfe_hw_irq_eof_cb; + struct cam_isp_hw_eof_event_data eof_done_event_data; + int rc = 0; + + tfe_hw_irq_eof_cb = + tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EOF]; + + switch (event_info->res_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + tfe_hw_mgr_ctx->eof_cnt[event_info->hw_idx]++; + rc = cam_tfe_hw_mgr_check_irq_for_dual_tfe(tfe_hw_mgr_ctx, + CAM_ISP_HW_EVENT_EOF); + if (!rc) { + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hw_irq_eof_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + } + break; + + case CAM_ISP_HW_TFE_IN_RDI0: + case CAM_ISP_HW_TFE_IN_RDI1: + case CAM_ISP_HW_TFE_IN_RDI2: + break; + + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", + event_info->res_id); + break; + } + + CAM_DBG(CAM_ISP, "EOF for out_res->res_id: 0x%x", + event_info->res_id); + + return 0; +} + +static int cam_tfe_hw_mgr_handle_hw_buf_done( + void *ctx, + void *evt_info) +{ + cam_hw_event_cb_func tfe_hwr_irq_wm_done_cb; + struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; + struct cam_isp_hw_done_event_data buf_done_event_data = {0}; + struct cam_isp_hw_event_info *event_info = evt_info; + + tfe_hwr_irq_wm_done_cb = + tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_DONE]; + + buf_done_event_data.num_handles = 1; + buf_done_event_data.resource_handle[0] = event_info->res_id; + + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + return 0; + + if (buf_done_event_data.num_handles > 0 && tfe_hwr_irq_wm_done_cb) { + CAM_DBG(CAM_ISP, "Notify ISP context"); + tfe_hwr_irq_wm_done_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); + } + + CAM_DBG(CAM_ISP, "Buf done for out_res->res_id: 0x%x", + event_info->res_id); + + return 0; +} + +static int cam_tfe_hw_mgr_event_handler( + void *priv, + uint32_t evt_id, + void *evt_info) +{ + int rc = 0; + + if (!evt_info) + return -EINVAL; + + if (!priv) + if (evt_id != CAM_ISP_HW_EVENT_ERROR) + return -EINVAL; + + CAM_DBG(CAM_ISP, "Event ID 0x%x", evt_id); + + switch (evt_id) { + case CAM_ISP_HW_EVENT_SOF: + rc = cam_tfe_hw_mgr_handle_hw_sof(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_REG_UPDATE: + rc = cam_tfe_hw_mgr_handle_hw_rup(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_EPOCH: + rc = cam_tfe_hw_mgr_handle_hw_epoch(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_EOF: + rc = cam_tfe_hw_mgr_handle_hw_eof(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_DONE: + rc = cam_tfe_hw_mgr_handle_hw_buf_done(priv, evt_info); + break; + + case CAM_ISP_HW_EVENT_ERROR: + rc = cam_tfe_hw_mgr_handle_hw_err(evt_info); + break; + + default: + CAM_ERR(CAM_ISP, "Invalid event ID %d", evt_id); + break; + } + + return rc; +} + +static int cam_tfe_hw_mgr_sort_dev_with_caps( + struct cam_tfe_hw_mgr *tfe_hw_mgr) +{ + int i; + + /* get caps for csid devices */ + for (i = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { + if (!tfe_hw_mgr->csid_devices[i]) + continue; + if (tfe_hw_mgr->csid_devices[i]->hw_ops.get_hw_caps) { + tfe_hw_mgr->csid_devices[i]->hw_ops.get_hw_caps( + tfe_hw_mgr->csid_devices[i]->hw_priv, + &tfe_hw_mgr->tfe_csid_dev_caps[i], + sizeof(tfe_hw_mgr->tfe_csid_dev_caps[i])); + } + } + + /* get caps for tfe devices */ + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (!tfe_hw_mgr->tfe_devices[i]) + continue; + if (tfe_hw_mgr->tfe_devices[i]->hw_ops.get_hw_caps) { + tfe_hw_mgr->tfe_devices[i]->hw_ops.get_hw_caps( + tfe_hw_mgr->tfe_devices[i]->hw_priv, + &tfe_hw_mgr->tfe_dev_caps[i], + sizeof(tfe_hw_mgr->tfe_dev_caps[i])); + } + } + + return 0; +} + +static int cam_tfe_set_csid_debug(void *data, u64 val) +{ + g_tfe_hw_mgr.debug_cfg.csid_debug = val; + CAM_DBG(CAM_ISP, "Set CSID Debug value :%lld", val); + return 0; +} + +static int cam_tfe_get_csid_debug(void *data, u64 *val) +{ + *val = g_tfe_hw_mgr.debug_cfg.csid_debug; + CAM_DBG(CAM_ISP, "Get CSID Debug value :%lld", + g_tfe_hw_mgr.debug_cfg.csid_debug); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_csid_debug, + cam_tfe_get_csid_debug, + cam_tfe_set_csid_debug, "%16llu"); + +static int cam_tfe_set_camif_debug(void *data, u64 val) +{ + g_tfe_hw_mgr.debug_cfg.camif_debug = val; + CAM_DBG(CAM_ISP, + "Set camif enable_diag_sensor_status value :%lld", val); + return 0; +} + +static int cam_tfe_get_camif_debug(void *data, u64 *val) +{ + *val = g_tfe_hw_mgr.debug_cfg.camif_debug; + CAM_DBG(CAM_ISP, + "Set camif enable_diag_sensor_status value :%lld", + g_tfe_hw_mgr.debug_cfg.csid_debug); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_camif_debug, + cam_tfe_get_camif_debug, + cam_tfe_set_camif_debug, "%16llu"); + +static int cam_tfe_hw_mgr_debug_register(void) +{ + g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", + NULL); + + if (!g_tfe_hw_mgr.debug_cfg.dentry) { + CAM_ERR(CAM_ISP, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_file("tfe_csid_debug", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, + &cam_tfe_csid_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_tfe_csid_debug"); + goto err; + } + + if (!debugfs_create_u32("enable_recovery", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, + &g_tfe_hw_mgr.debug_cfg.enable_recovery)) { + CAM_ERR(CAM_ISP, "failed to create enable_recovery"); + goto err; + } + + if (!debugfs_create_bool("enable_reg_dump", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, + &g_tfe_hw_mgr.debug_cfg.enable_reg_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_reg_dump"); + goto err; + } + + if (!debugfs_create_file("tfe_camif_debug", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, + &cam_tfe_camif_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_tfe_camif_debug"); + goto err; + } + + if (!debugfs_create_bool("per_req_reg_dump", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, + &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump)) { + CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); + goto err; + } + + + g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; + + return 0; + +err: + debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); + return -ENOMEM; +} + +int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) +{ + int rc = -EFAULT; + int i, j; + struct cam_iommu_handle cdm_handles; + struct cam_tfe_hw_mgr_ctx *ctx_pool; + struct cam_isp_hw_mgr_res *res_list_tfe_out; + + CAM_DBG(CAM_ISP, "Enter"); + + memset(&g_tfe_hw_mgr, 0, sizeof(g_tfe_hw_mgr)); + + mutex_init(&g_tfe_hw_mgr.ctx_mutex); + + if (CAM_TFE_HW_NUM_MAX != CAM_TFE_CSID_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, "CSID num is different then TFE num"); + return -EINVAL; + } + + /* fill tfe hw intf information */ + for (i = 0, j = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + rc = cam_tfe_hw_init(&g_tfe_hw_mgr.tfe_devices[i], i); + if (!rc) { + struct cam_hw_info *tfe_hw = (struct cam_hw_info *) + g_tfe_hw_mgr.tfe_devices[i]->hw_priv; + struct cam_hw_soc_info *soc_info = &tfe_hw->soc_info; + + j++; + + g_tfe_hw_mgr.cdm_reg_map[i] = &soc_info->reg_map[0]; + CAM_DBG(CAM_ISP, + "reg_map: mem base = %pK cam_base = 0x%llx", + (void __iomem *)soc_info->reg_map[0].mem_base, + (uint64_t) soc_info->reg_map[0].mem_cam_base); + } else { + g_tfe_hw_mgr.cdm_reg_map[i] = NULL; + } + } + if (j == 0) { + CAM_ERR(CAM_ISP, "no valid TFE HW"); + return -EINVAL; + } + + /* fill csid hw intf information */ + for (i = 0, j = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { + rc = cam_tfe_csid_hw_init(&g_tfe_hw_mgr.csid_devices[i], i); + if (!rc) + j++; + } + if (!j) { + CAM_ERR(CAM_ISP, "no valid TFE CSID HW"); + return -EINVAL; + } + + /* fill tpg hw intf information */ + for (i = 0, j = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) { + rc = cam_top_tpg_hw_init(&g_tfe_hw_mgr.tpg_devices[i], i); + if (!rc) + j++; + } + if (!j) { + CAM_ERR(CAM_ISP, "no valid TFE TPG HW"); + return -EINVAL; + } + + cam_tfe_hw_mgr_sort_dev_with_caps(&g_tfe_hw_mgr); + + /* setup tfe context list */ + INIT_LIST_HEAD(&g_tfe_hw_mgr.free_ctx_list); + INIT_LIST_HEAD(&g_tfe_hw_mgr.used_ctx_list); + + /* + * for now, we only support one iommu handle. later + * we will need to setup more iommu handle for other + * use cases. + * Also, we have to release them once we have the + * deinit support + */ + if (cam_smmu_get_handle("tfe", + &g_tfe_hw_mgr.mgr_common.img_iommu_hdl)) { + CAM_ERR(CAM_ISP, "Can not get iommu handle"); + return -EINVAL; + } + + if (cam_smmu_get_handle("cam-secure", + &g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure)) { + CAM_ERR(CAM_ISP, "Failed to get secure iommu handle"); + goto secure_fail; + } + + CAM_DBG(CAM_ISP, "iommu_handles: non-secure[0x%x], secure[0x%x]", + g_tfe_hw_mgr.mgr_common.img_iommu_hdl, + g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure); + + if (!cam_cdm_get_iommu_handle("tfe0", &cdm_handles)) { + CAM_DBG(CAM_ISP, "Successfully acquired the CDM iommu handles"); + g_tfe_hw_mgr.mgr_common.cmd_iommu_hdl = cdm_handles.non_secure; + g_tfe_hw_mgr.mgr_common.cmd_iommu_hdl_secure = + cdm_handles.secure; + } else { + CAM_DBG(CAM_ISP, "Failed to acquire the CDM iommu handles"); + g_tfe_hw_mgr.mgr_common.cmd_iommu_hdl = -1; + g_tfe_hw_mgr.mgr_common.cmd_iommu_hdl_secure = -1; + } + + atomic_set(&g_tfe_hw_mgr.active_ctx_cnt, 0); + for (i = 0; i < CAM_CTX_MAX; i++) { + memset(&g_tfe_hw_mgr.ctx_pool[i], 0, + sizeof(g_tfe_hw_mgr.ctx_pool[i])); + INIT_LIST_HEAD(&g_tfe_hw_mgr.ctx_pool[i].list); + INIT_LIST_HEAD(&g_tfe_hw_mgr.ctx_pool[i].res_list_tfe_csid); + INIT_LIST_HEAD(&g_tfe_hw_mgr.ctx_pool[i].res_list_tfe_in); + ctx_pool = &g_tfe_hw_mgr.ctx_pool[i]; + for (j = 0; j < CAM_TFE_HW_OUT_RES_MAX; j++) { + res_list_tfe_out = &ctx_pool->res_list_tfe_out[j]; + INIT_LIST_HEAD(&res_list_tfe_out->list); + } + + /* init context pool */ + INIT_LIST_HEAD(&g_tfe_hw_mgr.ctx_pool[i].free_res_list); + for (j = 0; j < CAM_TFE_HW_RES_POOL_MAX; j++) { + INIT_LIST_HEAD( + &g_tfe_hw_mgr.ctx_pool[i].res_pool[j].list); + list_add_tail( + &g_tfe_hw_mgr.ctx_pool[i].res_pool[j].list, + &g_tfe_hw_mgr.ctx_pool[i].free_res_list); + } + + g_tfe_hw_mgr.ctx_pool[i].cdm_cmd = + kzalloc(((sizeof(struct cam_cdm_bl_request)) + + ((CAM_TFE_HW_ENTRIES_MAX - 1) * + sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); + if (!g_tfe_hw_mgr.ctx_pool[i].cdm_cmd) { + rc = -ENOMEM; + CAM_ERR(CAM_ISP, "Allocation Failed for cdm command"); + goto end; + } + + g_tfe_hw_mgr.ctx_pool[i].ctx_index = i; + g_tfe_hw_mgr.ctx_pool[i].hw_mgr = &g_tfe_hw_mgr; + + cam_tasklet_init(&g_tfe_hw_mgr.mgr_common.tasklet_pool[i], + &g_tfe_hw_mgr.ctx_pool[i], i); + g_tfe_hw_mgr.ctx_pool[i].common.tasklet_info = + g_tfe_hw_mgr.mgr_common.tasklet_pool[i]; + + + init_completion(&g_tfe_hw_mgr.ctx_pool[i].config_done_complete); + list_add_tail(&g_tfe_hw_mgr.ctx_pool[i].list, + &g_tfe_hw_mgr.free_ctx_list); + } + + /* Create Worker for tfe_hw_mgr with 10 tasks */ + rc = cam_req_mgr_workq_create("cam_tfe_worker", 10, + &g_tfe_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Unable to create worker"); + goto end; + } + + /* fill return structure */ + hw_mgr_intf->hw_mgr_priv = &g_tfe_hw_mgr; + hw_mgr_intf->hw_get_caps = cam_tfe_mgr_get_hw_caps; + hw_mgr_intf->hw_acquire = cam_tfe_mgr_acquire; + hw_mgr_intf->hw_start = cam_tfe_mgr_start_hw; + hw_mgr_intf->hw_stop = cam_tfe_mgr_stop_hw; + hw_mgr_intf->hw_read = cam_tfe_mgr_read; + hw_mgr_intf->hw_write = cam_tfe_mgr_write; + hw_mgr_intf->hw_release = cam_tfe_mgr_release_hw; + hw_mgr_intf->hw_prepare_update = cam_tfe_mgr_prepare_hw_update; + hw_mgr_intf->hw_config = cam_tfe_mgr_config_hw; + hw_mgr_intf->hw_cmd = cam_tfe_mgr_cmd; + hw_mgr_intf->hw_reset = cam_tfe_mgr_reset; + + if (iommu_hdl) + *iommu_hdl = g_tfe_hw_mgr.mgr_common.img_iommu_hdl; + + cam_tfe_hw_mgr_debug_register(); + CAM_DBG(CAM_ISP, "Exit"); + + return 0; +end: + if (rc) { + for (i = 0; i < CAM_CTX_MAX; i++) { + cam_tasklet_deinit( + &g_tfe_hw_mgr.mgr_common.tasklet_pool[i]); + kfree(g_tfe_hw_mgr.ctx_pool[i].cdm_cmd); + g_tfe_hw_mgr.ctx_pool[i].cdm_cmd = NULL; + g_tfe_hw_mgr.ctx_pool[i].common.tasklet_info = NULL; + } + } + cam_smmu_destroy_handle( + g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure); + g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure = -1; +secure_fail: + cam_smmu_destroy_handle(g_tfe_hw_mgr.mgr_common.img_iommu_hdl); + g_tfe_hw_mgr.mgr_common.img_iommu_hdl = -1; + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h new file mode 100644 index 000000000000..c22eb7862253 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_HW_MGR_H_ +#define _CAM_TFE_HW_MGR_H_ + +#include +#include +#include "cam_isp_hw_mgr.h" +#include "cam_tfe_hw_intf.h" +#include "cam_tfe_csid_hw_intf.h" +#include "cam_top_tpg_hw_intf.h" +#include "cam_tasklet_util.h" + + + +/* TFE resource constants */ +#define CAM_TFE_HW_IN_RES_MAX (CAM_ISP_TFE_IN_RES_MAX & 0xFF) +#define CAM_TFE_HW_OUT_RES_MAX (CAM_ISP_TFE_OUT_RES_MAX & 0xFF) +#define CAM_TFE_HW_RES_POOL_MAX 64 + +/** + * struct cam_tfe_hw_mgr_debug - contain the debug information + * + * @dentry: Debugfs entry + * @csid_debug: csid debug information + * @enable_recovery: enable recovery + * @camif_debug: enable sensor diagnosis status + * @enable_reg_dump: enable reg dump on error; + * @per_req_reg_dump: Enable per request reg dump + * + */ +struct cam_tfe_hw_mgr_debug { + struct dentry *dentry; + uint64_t csid_debug; + uint32_t enable_recovery; + uint32_t camif_debug; + bool enable_reg_dump; + bool per_req_reg_dump; +}; + +/** + * struct cam_tfe_hw_mgr_ctx - TFE HW manager Context object + * + * @list: used by the ctx list. + * @common: common acquired context data + * @ctx_index: acquired context id. + * @hw_mgr: tfe hw mgr which owns this context + * @ctx_in_use: flag to tell whether context is active + * @res_list_csid: csid resource list + * @res_list_tfe_in: tfe input resource list + * @res_list_tfe_out: tfe output resoruces array + * @free_res_list: free resources list for the branch node + * @res_pool: memory storage for the free resource list + * @base device base index array contain the all TFE HW + * instance associated with this context. + * @num_base number of valid base data in the base array + * @cdm_handle cdm hw acquire handle + * @cdm_ops cdm util operation pointer for building + * cdm commands + * @cdm_cmd cdm base and length request pointer + * @config_done_complete indicator for configuration complete + * @sof_cnt sof count value per core, used for dual TFE + * @epoch_cnt epoch count value per core, used for dual TFE + * @eof_cnt eof count value per core, used for dual TFE + * @overflow_pending flat to specify the overflow is pending for the + * context + * @cdm_done flag to indicate cdm has finished writing shadow + * registers + * @is_rdi_only_context flag to specify the context has only rdi resource + * @reg_dump_buf_desc: cmd buffer descriptors for reg dump + * @num_reg_dump_buf: count of descriptors in reg_dump_buf_desc + * @applied_req_id: last request id to be applied + * @last_dump_flush_req_id last req id for which reg dump on flush was called + * @last_dump_err_req_id last req id for which reg dump on error was called + * @init_done indicate whether init hw is done + * @is_dual indicate whether context is in dual TFE mode + * @is_tpg indicate whether context use tpg + * @master_hw_idx master hardware index in dual tfe case + * @dual_tfe_irq_mismatch_cnt irq mismatch count value per core, used for + * dual TFE + */ +struct cam_tfe_hw_mgr_ctx { + struct list_head list; + struct cam_isp_hw_mgr_ctx common; + + uint32_t ctx_index; + struct cam_tfe_hw_mgr *hw_mgr; + uint32_t ctx_in_use; + + struct cam_isp_hw_mgr_res res_list_tpg; + struct list_head res_list_tfe_csid; + struct list_head res_list_tfe_in; + struct cam_isp_hw_mgr_res + res_list_tfe_out[CAM_TFE_HW_OUT_RES_MAX]; + + struct list_head free_res_list; + struct cam_isp_hw_mgr_res res_pool[CAM_TFE_HW_RES_POOL_MAX]; + + struct cam_isp_ctx_base_info base[CAM_TFE_HW_NUM_MAX]; + uint32_t num_base; + uint32_t cdm_handle; + struct cam_cdm_utils_ops *cdm_ops; + struct cam_cdm_bl_request *cdm_cmd; + struct completion config_done_complete; + + uint32_t sof_cnt[CAM_TFE_HW_NUM_MAX]; + uint32_t epoch_cnt[CAM_TFE_HW_NUM_MAX]; + uint32_t eof_cnt[CAM_TFE_HW_NUM_MAX]; + atomic_t overflow_pending; + atomic_t cdm_done; + uint32_t is_rdi_only_context; + struct cam_cmd_buf_desc reg_dump_buf_desc[ + CAM_REG_DUMP_MAX_BUF_ENTRIES]; + uint32_t num_reg_dump_buf; + uint64_t applied_req_id; + uint64_t last_dump_flush_req_id; + uint64_t last_dump_err_req_id; + bool init_done; + bool is_dual; + bool is_tpg; + uint32_t master_hw_idx; + uint32_t dual_tfe_irq_mismatch_cnt; +}; + +/** + * struct cam_tfe_hw_mgr - TFE HW Manager + * + * @mgr_common: common data for all HW managers + * @tpg_devices: tpg devices instacnce array. This will be filled by + * HW manager during the initialization. + * @csid_devices: csid device instances array. This will be filled by + * HW manager during the initialization. + * @tfe_devices: TFE device instances array. This will be filled by + * HW layer during initialization + * @cdm_reg_map commands for register dump + * @ctx_mutex: mutex for the hw context pool + * @active_ctx_cnt active context count number + * @free_ctx_list: free hw context list + * @used_ctx_list: used hw context list + * @ctx_pool: context storage + * @tfe_csid_dev_caps csid device capability stored per core + * @tfe_dev_caps tfe device capability per core + * @work q work queue for TFE hw manager + * @debug_cfg debug configuration + */ +struct cam_tfe_hw_mgr { + struct cam_isp_hw_mgr mgr_common; + struct cam_hw_intf *tpg_devices[CAM_TOP_TPG_HW_NUM_MAX]; + struct cam_hw_intf *csid_devices[CAM_TFE_CSID_HW_NUM_MAX]; + struct cam_hw_intf *tfe_devices[CAM_TFE_HW_NUM_MAX]; + struct cam_soc_reg_map *cdm_reg_map[CAM_TFE_HW_NUM_MAX]; + struct mutex ctx_mutex; + atomic_t active_ctx_cnt; + struct list_head free_ctx_list; + struct list_head used_ctx_list; + struct cam_tfe_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; + + struct cam_tfe_csid_hw_caps tfe_csid_dev_caps[ + CAM_TFE_CSID_HW_NUM_MAX]; + struct cam_tfe_hw_get_hw_cap tfe_dev_caps[CAM_TFE_HW_NUM_MAX]; + struct cam_req_mgr_core_workq *workq; + struct cam_tfe_hw_mgr_debug debug_cfg; +}; + +/** + * struct cam_tfe_hw_event_recovery_data - Payload for the recovery procedure + * + * @error_type: Error type that causes the recovery + * @affected_core: Array of the hardware cores that are affected + * @affected_ctx: Array of the hardware contexts that are affected + * @no_of_context: Actual number of the affected context + * + */ +struct cam_tfe_hw_event_recovery_data { + uint32_t error_type; + uint32_t affected_core[CAM_TFE_HW_NUM_MAX]; + struct cam_tfe_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX]; + uint32_t no_of_context; +}; + +/** + * cam_tfe_hw_mgr_init() + * + * @brief: Initialize the TFE hardware manger. This is the + * etnry functinon for the TFE HW manager. + * + * @hw_mgr_intf: TFE hardware manager object returned + * @iommu_hdl: Iommu handle to be returned + * + */ +int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); + +#endif /* _CAM_TFE_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 009975864a45..5354bfde8331 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -17,6 +17,8 @@ #define CAM_IFE_RDI_NUM_MAX 4 #define CAM_ISP_BW_CONFIG_V1 1 #define CAM_ISP_BW_CONFIG_V2 2 +#define CAM_TFE_HW_NUM_MAX 3 +#define CAM_TFE_RDI_NUM_MAX 3 /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 30 @@ -252,12 +254,12 @@ struct cam_isp_hw_cmd_args { * * @brief: Initialization function for the ISP hardware manager * - * @of_node: Device node input + * @device_name_str: Device name string * @hw_mgr: Input/output structure for the ISP hardware manager * initialization * @iommu_hdl: Iommu handle to be returned */ -int cam_isp_hw_mgr_init(struct device_node *of_node, +int cam_isp_hw_mgr_init(const char *device_name_str, struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl); #endif /* __CAM_ISP_HW_MGR_INTF_H__ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index b35e495b2410..def462459743 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -38,11 +38,14 @@ struct cam_isp_timestamp { void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp); enum cam_isp_hw_type { - CAM_ISP_HW_TYPE_CSID = 0, - CAM_ISP_HW_TYPE_ISPIF = 1, - CAM_ISP_HW_TYPE_VFE = 2, - CAM_ISP_HW_TYPE_IFE_CSID = 3, - CAM_ISP_HW_TYPE_MAX = 4, + CAM_ISP_HW_TYPE_CSID, + CAM_ISP_HW_TYPE_ISPIF, + CAM_ISP_HW_TYPE_VFE, + CAM_ISP_HW_TYPE_IFE_CSID, + CAM_ISP_HW_TYPE_TFE, + CAM_ISP_HW_TYPE_TFE_CSID, + CAM_ISP_HW_TYPE_TPG, + CAM_ISP_HW_TYPE_MAX, }; enum cam_isp_hw_split_id { @@ -74,6 +77,9 @@ enum cam_isp_resource_type { CAM_ISP_RESOURCE_VFE_IN, CAM_ISP_RESOURCE_VFE_OUT, CAM_ISP_RESOURCE_VFE_BUS_RD, + CAM_ISP_RESOURCE_TPG, + CAM_ISP_RESOURCE_TFE_IN, + CAM_ISP_RESOURCE_TFE_OUT, CAM_ISP_RESOURCE_MAX, }; @@ -91,6 +97,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_BW_UPDATE_V2, 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, @@ -102,6 +109,8 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED, CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, + CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE, + CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h new file mode 100644 index 000000000000..a665ac589311 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_HW_INTF_H_ +#define _CAM_TFE_CSID_HW_INTF_H_ + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" + +/* MAX TFE CSID instance */ +#define CAM_TFE_CSID_HW_NUM_MAX 3 +#define CAM_TFE_CSID_RDI_MAX 3 + +/** + * enum cam_tfe_pix_path_res_id - Specify the csid patch + */ +enum cam_tfe_csid_path_res_id { + CAM_TFE_CSID_PATH_RES_RDI_0, + CAM_TFE_CSID_PATH_RES_RDI_1, + CAM_TFE_CSID_PATH_RES_RDI_2, + CAM_TFE_CSID_PATH_RES_IPP, + CAM_TFE_CSID_PATH_RES_MAX, +}; + +/** + * enum cam_tfe_csid_irq_reg + */ +enum cam_tfe_csid_irq_reg { + TFE_CSID_IRQ_REG_RDI0, + TFE_CSID_IRQ_REG_RDI1, + TFE_CSID_IRQ_REG_RDI2, + TFE_CSID_IRQ_REG_TOP, + TFE_CSID_IRQ_REG_RX, + TFE_CSID_IRQ_REG_IPP, + TFE_CSID_IRQ_REG_MAX, +}; + + +/** + * struct cam_tfe_csid_hw_caps- get the CSID hw capability + * @num_rdis: number of rdis supported by CSID HW device + * @num_pix: number of pxl paths supported by CSID HW device + * @major_version : major version + * @minor_version: minor version + * @version_incr: version increment + * + */ +struct cam_tfe_csid_hw_caps { + uint32_t num_rdis; + uint32_t num_pix; + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; +}; + +/** + * struct cam_tfe_csid_hw_reserve_resource_args- hw reserve + * @res_type : Reource type ie PATH + * @res_id : Resource id to be reserved + * @in_port : Input port resource info + * @out_port: Output port resource info, used for RDI path only + * @sync_mode: Sync mode + * Sync mode could be master, slave or none + * @master_idx: Master device index to be configured in the slave path + * for master path, this value is not required. + * only slave need to configure the master index value + * @phy_sel: Phy selection number if tpg is enabled from userspace + * @event_cb_prv: Context data + * @event_cb: Callback function to hw mgr in case of hw events + * @node_res : Reserved resource structure pointer + * + */ +struct cam_tfe_csid_hw_reserve_resource_args { + enum cam_isp_resource_type res_type; + uint32_t res_id; + struct cam_isp_tfe_in_port_info *in_port; + struct cam_isp_tfe_out_port_info *out_port; + enum cam_isp_hw_sync_mode sync_mode; + uint32_t master_idx; + uint32_t phy_sel; + void *event_cb_prv; + cam_hw_mgr_event_cb_func event_cb; + struct cam_isp_resource_node *node_res; +}; + +/** + * enum cam_tfe_csid_halt_cmd - Specify the halt command type + */ +enum cam_tfe_csid_halt_cmd { + CAM_TFE_CSID_HALT_AT_FRAME_BOUNDARY, + CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + CAM_TFE_CSID_HALT_IMMEDIATELY, + CAM_TFE_CSID_HALT_MAX, +}; + +/** + * struct cam_csid_hw_stop- stop all resources + * @stop_cmd : Applicable only for PATH resources + * if stop command set to Halt immediately,driver will stop + * path immediately, manager need to reset the path after HI + * if stop command set to halt at frame boundary, driver will set + * halt at frame boundary and wait for frame boundary + * @num_res : Number of resources to be stopped + * @node_res : Reource pointer array( ie cid or CSID) + * + */ +struct cam_tfe_csid_hw_stop_args { + enum cam_tfe_csid_halt_cmd stop_cmd; + uint32_t num_res; + struct cam_isp_resource_node **node_res; +}; + +/** + * enum cam_tfe_csid_reset_type - Specify the reset type + */ +enum cam_tfe_csid_reset_type { + CAM_TFE_CSID_RESET_GLOBAL, + CAM_TFE_CSID_RESET_PATH, + CAM_TFE_CSID_RESET_MAX, +}; + +/** + * struct cam_tfe_csid_reset_cfg- Csid reset configuration + * @ reset_type : Global reset or path reset + * @res_node : Resource need to be reset + * + */ +struct cam_tfe_csid_reset_cfg_args { + enum cam_tfe_csid_reset_type reset_type; + struct cam_isp_resource_node *node_res; +}; + +/** + * struct cam_csid_get_time_stamp_args- time stamp capture arguments + * @res_node : Resource to get the time stamp + * @time_stamp_val : Captured time stamp + * @boot_timestamp : Boot time stamp + */ +struct cam_tfe_csid_get_time_stamp_args { + struct cam_isp_resource_node *node_res; + uint64_t time_stamp_val; + uint64_t boot_timestamp; +}; + +/** + * enum cam_tfe_csid_cmd_type - Specify the csid command + */ +enum cam_tfe_csid_cmd_type { + CAM_TFE_CSID_CMD_GET_TIME_STAMP, + CAM_TFE_CSID_SET_CSID_DEBUG, + CAM_TFE_CSID_SOF_IRQ_DEBUG, + CAM_TFE_CSID_CMD_GET_REG_DUMP, + CAM_TFE_CSID_CMD_MAX, +}; + +/** + * cam_tfe_csid_hw_init() + * + * @brief: Initialize function for the CSID hardware + * + * @tfe_csid_hw: CSID hardware instance returned + * @hw_idex: CSID hardware instance id + */ +int cam_tfe_csid_hw_init(struct cam_hw_intf **tfe_csid_hw, + uint32_t hw_idx); + +/* + * struct cam_tfe_csid_clock_update_args: + * + * @clk_rate: Clock rate requested + */ +struct cam_tfe_csid_clock_update_args { + uint64_t clk_rate; +}; + + +#endif /* _CAM_TFE_CSID_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h new file mode 100644 index 000000000000..cdbae72678d5 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_HW_INTF_H_ +#define _CAM_TFE_HW_INTF_H_ + +#include "cam_isp_hw.h" +#include "cam_cpas_api.h" + +#define CAM_TFE_HW_NUM_MAX 3 +#define TFE_CORE_BASE_IDX 0 + + +enum cam_isp_hw_tfe_in { + CAM_ISP_HW_TFE_IN_CAMIF = 0, + CAM_ISP_HW_TFE_IN_RDI0 = 1, + CAM_ISP_HW_TFE_IN_RDI1 = 2, + CAM_ISP_HW_TFE_IN_RDI2 = 3, + CAM_ISP_HW_TFE_IN_MAX, +}; + +enum cam_isp_hw_tfe_core { + CAM_ISP_HW_TFE_CORE_0, + CAM_ISP_HW_TFE_CORE_1, + CAM_ISP_HW_TFE_CORE_2, + CAM_ISP_HW_TFE_CORE_MAX, +}; + +enum cam_tfe_hw_irq_status { + CAM_TFE_IRQ_STATUS_SUCCESS, + CAM_TFE_IRQ_STATUS_ERR, + CAM_TFE_IRQ_STATUS_OVERFLOW, + CAM_TFE_IRQ_STATUS_P2I_ERROR, + CAM_TFE_IRQ_STATUS_VIOLATION, + CAM_TFE_IRQ_STATUS_MAX, +}; + +enum cam_tfe_hw_irq_regs { + CAM_TFE_IRQ_CAMIF_REG_STATUS0 = 0, + CAM_TFE_IRQ_CAMIF_REG_STATUS1 = 1, + CAM_TFE_IRQ_CAMIF_REG_STATUS2 = 2, + CAM_TFE_IRQ_REGISTERS_MAX, +}; + +enum cam_tfe_bus_irq_regs { + CAM_TFE_IRQ_BUS_REG_STATUS0 = 0, + CAM_TFE_IRQ_BUS_REG_STATUS1 = 1, + CAM_TFE_BUS_IRQ_REGISTERS_MAX, +}; + +enum cam_tfe_reset_type { + CAM_TFE_HW_RESET_HW_AND_REG, + CAM_TFE_HW_RESET_HW, + CAM_TFE_HW_RESET_MAX, +}; + +enum cam_tfe_bw_control_action { + CAM_TFE_BW_CONTROL_EXCLUDE = 0, + CAM_TFE_BW_CONTROL_INCLUDE = 1 +}; + +/* + * struct cam_tfe_hw_get_hw_cap: + * + * @max_width: Max width supported by HW + * @max_height: Max height supported by HW + * @max_pixel_num: Max Pixel channels available + * @max_rdi_num: Max Raw channels available + */ +struct cam_tfe_hw_get_hw_cap { + uint32_t max_width; + uint32_t max_height; + uint32_t max_pixel_num; + uint32_t max_rdi_num; +}; + +/* + * struct cam_tfe_hw_tfe_out_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @out_port_info: Output Port details to acquire + * @unique_id: Unique Identity of Context to associate with this + * resource. Used for composite grouping of multiple + * resources in the same context + * @is_dual: Dual TFE or not + * @split_id: In case of Dual TFE, this is Left or Right. + * (Default is Left if Single TFE) + * @is_master: In case of Dual TFE, this is Master or Slave. + * (Default is Master in case of Single TFE) + * @cdm_ops: CDM operations + * @ctx: Context data + */ +struct cam_tfe_hw_tfe_out_acquire_args { + struct cam_isp_resource_node *rsrc_node; + struct cam_isp_tfe_out_port_info *out_port_info; + uint32_t unique_id; + uint32_t is_dual; + enum cam_isp_hw_split_id split_id; + uint32_t is_master; + struct cam_cdm_utils_ops *cdm_ops; + void *ctx; +}; + +/* + * struct cam_tfe_hw_tfe_in_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @res_id: Resource ID of resource to acquire if specific, + * else CAM_ISP_HW_TFE_IN_MAX + * @cdm_ops: CDM operations + * @sync_mode: In case of Dual TFE, this is Master or Slave. + * (Default is Master in case of Single TFE) + * @in_port: Input port details to acquire + * @camif_pd_enable Camif pd enable or disable + * @dual_tfe_sync_sel_idx Dual tfe master hardware index + */ +struct cam_tfe_hw_tfe_in_acquire_args { + struct cam_isp_resource_node *rsrc_node; + struct cam_isp_tfe_in_port_info *in_port; + uint32_t res_id; + void *cdm_ops; + enum cam_isp_hw_sync_mode sync_mode; + bool camif_pd_enable; + uint32_t dual_tfe_sync_sel_idx; +}; + +/* + * struct cam_tfe_acquire_args: + * + * @rsrc_type: Type of Resource (OUT/IN) to acquire + * @tasklet: Tasklet to associate with this resource. This is + * used to schedule bottom of IRQ events associated + * with this resource. + * @priv: Context data + * @event_cb: Callback function to hw mgr in case of hw events + * @tfe_out: Acquire args for TFE_OUT + * @tfe_in: Acquire args for TFE_IN + */ +struct cam_tfe_acquire_args { + enum cam_isp_resource_type rsrc_type; + void *tasklet; + void *priv; + cam_hw_mgr_event_cb_func event_cb; + union { + struct cam_tfe_hw_tfe_out_acquire_args tfe_out; + struct cam_tfe_hw_tfe_in_acquire_args tfe_in; + }; +}; + +/* + * struct cam_tfe_clock_update_args: + * + * @node_res: Resource to get the time stamp + * @clk_rate: Clock rate requested + */ +struct cam_tfe_clock_update_args { + struct cam_isp_resource_node *node_res; + uint64_t clk_rate; +}; + +/* + * struct cam_tfe_bw_update_args: + * + * @node_res: Resource to get the BW + * @isp_vote: Vote info according to usage data (left/right/rdi) + */ +struct cam_tfe_bw_update_args { + struct cam_isp_resource_node *node_res; + struct cam_axi_vote isp_vote; +}; + +/* + * struct cam_tfe_dual_update_args: + * + * @Brief: update the dual isp striping configuration. + * + * @ split_id: spilt id to inform left or rifht + * @ res: resource node + * @ stripe_config: stripe configuration for port + * + */ +struct cam_tfe_dual_update_args { + enum cam_isp_hw_split_id split_id; + struct cam_isp_resource_node *res; + struct cam_isp_tfe_dual_stripe_config *stripe_config; +}; + +/* + * struct cam_tfe_bw_control_args: + * + * @node_res: Resource to get the time stamp + * @action: Bandwidth control action + */ +struct cam_tfe_bw_control_args { + struct cam_isp_resource_node *node_res; + enum cam_tfe_bw_control_action action; +}; + +/* + * struct cam_tfe_irq_evt_payload: + * + * @Brief: This structure is used to save payload for IRQ + * related to TFE_TOP resources + * + * @list: list_head node for the payload + * @core_index: Index of TFE HW that generated this IRQ event + * @core_info: Private data of handler in bottom half context + * @evt_id: IRQ event + * @irq_reg_val: IRQ and Error register values, read when IRQ was + * handled + * @bus_irq_val Bus irq register status + * @debug_status_0: Value of debug status_0 register at time of IRQ + * @ccif_violation_status ccif violation status + * @overflow_status bus overflow status + * @image_size_violation_status image size violations status + + * @error_type: Identify different errors + * @enable_reg_dump: enable register dump on error + * @ts: Timestamp + */ +struct cam_tfe_irq_evt_payload { + struct list_head list; + uint32_t core_index; + void *core_info; + uint32_t evt_id; + uint32_t irq_reg_val[CAM_TFE_IRQ_REGISTERS_MAX]; + uint32_t bus_irq_val[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; + uint32_t ccif_violation_status; + uint32_t overflow_status; + uint32_t image_size_violation_status; + uint32_t debug_status_0; + + uint32_t error_type; + bool enable_reg_dump; + struct cam_isp_timestamp ts; +}; + +/* + * cam_tfe_hw_init() + * + * @Brief: Initialize TFE HW device + * + * @tfe_hw: tfe_hw interface to fill in and return on + * successful initialization + * @hw_idx: Index of TFE HW + */ +int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx); + +#endif /* _CAM_TFE_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h new file mode 100644 index 000000000000..17086b50cfc3 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_HW_INTF_H_ +#define _CAM_TOP_TPG_HW_INTF_H_ + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" + +/* Max top tpg instance */ +#define CAM_TOP_TPG_HW_NUM_MAX 2 +/* Max supported number of DT for TPG */ +#define CAM_TOP_TPG_MAX_SUPPORTED_DT 4 + +/** + * enum cam_top_tpg_id - top tpg hw instance id + */ +enum cam_top_tpg_id { + CAM_TOP_TPG_ID_0, + CAM_TOP_TPG_ID_1, + CAM_TFE_TPG_ID_MAX, +}; + +/** + * struct cam_top_tpg_hw_caps- Get the top tpg hw capability + * @major_version : Major version + * @minor_version: Minor version + * @version_incr: Version increment + * + */ +struct cam_top_tpg_hw_caps { + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; +}; + +/** + * struct cam_tfe_csid_hw_reserve_resource_args- hw reserve + * @num_inport: number of inport + * TPG support 4 dt types, each different dt comes in different + * in port. + * @in_port : Input port resource info structure pointer + * @node_res : Reserved resource structure pointer + * + */ +struct cam_top_tpg_hw_reserve_resource_args { + uint32_t num_inport; + struct cam_isp_tfe_in_port_info *in_port[CAM_TOP_TPG_MAX_SUPPORTED_DT]; + struct cam_isp_resource_node *node_res; +}; + +/** + * cam_top_tpg_hw_init() + * + * @brief: Initialize function for the tpg hardware + * + * @top_tpg_hw: TPG hardware instance returned + * @hw_idex: TPG hardware instance id + */ +int cam_top_tpg_hw_init(struct cam_hw_intf **top_tpg_hw, + uint32_t hw_idx); + +/* + * struct cam_top_tpg_clock_update_args: + * + * @clk_rate: phy rate requested + */ +struct cam_top_tpg_clock_update_args { + uint64_t clk_rate; +}; + +#endif /* _CAM_TOP_TPG_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile new file mode 100644 index 000000000000..dcb41c82af58 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_csid_dev.o cam_tfe_csid_soc.o cam_tfe_csid_core.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_csid530.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c new file mode 100644 index 000000000000..419dc5c0cc59 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#include +#include "cam_tfe_csid_core.h" +#include "cam_tfe_csid530.h" +#include "cam_tfe_csid_dev.h" + +#define CAM_TFE_CSID_DRV_NAME "csid_530" +#define CAM_TFE_CSID_VERSION_V530 0x50030000 + +static struct cam_tfe_csid_hw_info cam_tfe_csid530_hw_info = { + .csid_reg = &cam_tfe_csid_530_reg_offset, + .hw_dts_version = CAM_TFE_CSID_VERSION_V530, +}; + +static const struct of_device_id cam_tfe_csid530_dt_match[] = { + { + .compatible = "qcom,csid530", + .data = &cam_tfe_csid530_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_tfe_csid530_dt_match); + +static struct platform_driver cam_tfe_csid530_driver = { + .probe = cam_tfe_csid_probe, + .remove = cam_tfe_csid_remove, + .driver = { + .name = CAM_TFE_CSID_DRV_NAME, + .of_match_table = cam_tfe_csid530_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_tfe_csid530_init_module(void) +{ + return platform_driver_register(&cam_tfe_csid530_driver); +} + +void cam_tfe_csid530_exit_module(void) +{ + platform_driver_unregister(&cam_tfe_csid530_driver); +} + +MODULE_DESCRIPTION("CAM TFE_CSID530 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h new file mode 100644 index 000000000000..4d267bb0868d --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_530_H_ +#define _CAM_TFE_CSID_530_H_ + +#include "cam_tfe_csid_core.h" + +static struct cam_tfe_csid_pxl_reg_offset cam_tfe_csid_530_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_hcrop_addr = 0x21c, + .csid_pxl_vcrop_addr = 0x220, + .csid_pxl_rst_strobes_addr = 0x240, + .csid_pxl_status_addr = 0x254, + .csid_pxl_misr_val_addr = 0x258, + .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, + .csid_pxl_err_recovery_cfg0_addr = 0x2d0, + .csid_pxl_err_recovery_cfg1_addr = 0x2d4, + .csid_pxl_err_recovery_cfg2_addr = 0x2d8, + /* configurations */ + .pix_store_en_shift_val = 7, + .early_eof_en_shift_val = 29, + .halt_master_sel_shift = 4, + .halt_mode_shift = 2, + .halt_master_sel_master_val = 3, + .halt_master_sel_slave_val = 0, +}; + +static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_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_rst_strobes_addr = 0x340, + .csid_rdi_status_addr = 0x350, + .csid_rdi_misr_val0_addr = 0x354, + .csid_rdi_misr_val1_addr = 0x358, + .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_err_recovery_cfg0_addr = 0x3b0, + .csid_rdi_err_recovery_cfg1_addr = 0x3b4, + .csid_rdi_err_recovery_cfg2_addr = 0x3b8, + .csid_rdi_byte_cntr_ping_addr = 0x3e0, + .csid_rdi_byte_cntr_pong_addr = 0x3e4, +}; + +static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_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_rst_strobes_addr = 0x440, + .csid_rdi_status_addr = 0x450, + .csid_rdi_misr_val0_addr = 0x454, + .csid_rdi_misr_val1_addr = 0x458, + .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_err_recovery_cfg0_addr = 0x4b0, + .csid_rdi_err_recovery_cfg1_addr = 0x4b4, + .csid_rdi_err_recovery_cfg2_addr = 0x4b8, + .csid_rdi_byte_cntr_ping_addr = 0x4e0, + .csid_rdi_byte_cntr_pong_addr = 0x4e4, +}; + +static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_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_rst_strobes_addr = 0x540, + .csid_rdi_status_addr = 0x550, + .csid_rdi_misr_val0_addr = 0x554, + .csid_rdi_misr_val1_addr = 0x558, + .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_err_recovery_cfg0_addr = 0x5b0, + .csid_rdi_err_recovery_cfg1_addr = 0x5b4, + .csid_rdi_err_recovery_cfg2_addr = 0x5b8, + .csid_rdi_byte_cntr_ping_addr = 0x5e0, + .csid_rdi_byte_cntr_pong_addr = 0x5e4, +}; + +static struct cam_tfe_csid_csi2_rx_reg_offset + cam_tfe_csid_530_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_total_pkts_rcvd_addr = 0x160, + .csid_csi2_rx_stats_ecc_addr = 0x164, + .csid_csi2_rx_total_crc_err_addr = 0x168, + + .csi2_rst_srb_all = 0x3FFF, + .csi2_rst_done_shift_val = 27, + .csi2_irq_mask_all = 0xFFFFFFF, + .csi2_misr_enable_shift_val = 6, + .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 = 12, + .csi2_capture_cphy_pkt_dt_shift = 14, + .csi2_capture_cphy_pkt_vc_shift = 20, + .csi2_rx_phy_num_mask = 0x3, + .csi2_rx_long_pkt_hdr_rst_stb_shift = 0x1, + .csi2_rx_short_pkt_hdr_rst_stb_shift = 0x2, +}; + +static struct cam_tfe_csid_common_reg_offset + cam_tfe_csid_530_cmn_reg_offset = { + .csid_hw_version_addr = 0x0, + .csid_cfg0_addr = 0x4, + .csid_ctrl_addr = 0x8, + .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 = 5, + .minor_version = 3, + .version_incr = 0, + .num_rdis = 3, + .num_pix = 1, + .csid_reg_rst_stb = 1, + .csid_rst_stb = 0x1e, + .csid_rst_stb_sw_all = 0x1f, + .ipp_path_rst_stb_all = 0x17, + .rdi_path_rst_stb_all = 0x97, + .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 = 0x3FFFF, + .rdi_irq_mask_all = 0x3FFFF, + .top_tfe2_pix_pipe_fuse_reg = 0xFE4, + .top_tfe2_fuse_reg = 0xFE8, +}; + +static struct cam_tfe_csid_reg_offset cam_tfe_csid_530_reg_offset = { + .cmn_reg = &cam_tfe_csid_530_cmn_reg_offset, + .csi2_reg = &cam_tfe_csid_530_csi2_reg_offset, + .ipp_reg = &cam_tfe_csid_530_ipp_reg_offset, + .rdi_reg = { + &cam_tfe_csid_530_rdi_0_reg_offset, + &cam_tfe_csid_530_rdi_1_reg_offset, + &cam_tfe_csid_530_rdi_2_reg_offset, + }, +}; + +int cam_tfe_csid530_init_module(void); +void cam_tfe_csid530_exit_module(void); + +#endif /*_CAM_TFE_CSID_530_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c new file mode 100644 index 000000000000..81c3fe083a56 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -0,0 +1,2824 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_tfe_csid_core.h" +#include "cam_isp_hw.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_isp_hw_mgr_intf.h" + +/* Timeout value in msec */ +#define TFE_CSID_TIMEOUT 1000 + +/* Timeout values in usec */ +#define CAM_TFE_CSID_TIMEOUT_SLEEP_US 1000 +#define CAM_TFE_CSID_TIMEOUT_ALL_US 100000 + +/* + * Constant Factors needed to change QTimer ticks to nanoseconds + * QTimer Freq = 19.2 MHz + * Time(us) = ticks/19.2 + * Time(ns) = ticks/19.2 * 1000 + */ +#define CAM_TFE_CSID_QTIMER_MUL_FACTOR 10000 +#define CAM_TFE_CSID_QTIMER_DIV_FACTOR 192 + +/* Max number of sof irq's triggered in case of SOF freeze */ +#define CAM_TFE_CSID_IRQ_SOF_DEBUG_CNT_MAX 12 + +/* Max CSI Rx irq error count threshold value */ +#define CAM_TFE_CSID_MAX_IRQ_ERROR_COUNT 5 + +static int cam_tfe_csid_is_ipp_format_supported( + uint32_t in_format) +{ + int rc = -EINVAL; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + rc = 0; + break; + default: + break; + } + return rc; +} + +static int cam_tfe_csid_get_format_rdi( + uint32_t in_format, uint32_t out_format, + uint32_t *decode_fmt, uint32_t *plain_fmt) +{ + int rc = 0; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_6: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN8: + *decode_fmt = 0x0; + *plain_fmt = 0x0; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_8: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_PLAIN128: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN8: + *decode_fmt = 0x1; + *plain_fmt = 0x0; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_10: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_PLAIN128: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_10: + *decode_fmt = 0x2; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_12: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_12: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_12: + *decode_fmt = 0x3; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_14: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_14: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_14: + *decode_fmt = 0x4; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + case CAM_FORMAT_MIPI_RAW_16: + switch (out_format) { + case CAM_FORMAT_MIPI_RAW_16: + *decode_fmt = 0xf; + break; + case CAM_FORMAT_PLAIN16_16: + *decode_fmt = 0x5; + *plain_fmt = 0x1; + break; + default: + rc = -EINVAL; + break; + } + break; + default: + rc = -EINVAL; + break; + } + + if (rc) + CAM_ERR(CAM_ISP, "Unsupported format pair in %d out %d", + in_format, out_format); + + return rc; +} + +static int cam_tfe_csid_get_format_ipp( + uint32_t in_format, + uint32_t *decode_fmt, uint32_t *plain_fmt) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "input format:%d", + in_format); + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + *decode_fmt = 0; + *plain_fmt = 0; + break; + case CAM_FORMAT_MIPI_RAW_8: + *decode_fmt = 0x1; + *plain_fmt = 0; + break; + case CAM_FORMAT_MIPI_RAW_10: + *decode_fmt = 0x2; + *plain_fmt = 0x1; + break; + case CAM_FORMAT_MIPI_RAW_12: + *decode_fmt = 0x3; + *plain_fmt = 0x1; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported format %d", + in_format); + rc = -EINVAL; + } + + CAM_DBG(CAM_ISP, "decode_fmt:%d plain_fmt:%d", + *decode_fmt, *plain_fmt); + + return rc; +} + +static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, + int32_t vc, uint32_t dt, uint32_t *cid) +{ + uint32_t i = 0; + + /* Return already reserved CID if the VC/DT matches */ + for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { + if (csid_hw->cid_res[i].cnt >= 1) { + if (csid_hw->cid_res[i].vc == vc && + csid_hw->cid_res[i].dt == dt) { + csid_hw->cid_res[i].cnt++; + *cid = i; + CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated", + csid_hw->hw_intf->hw_idx, i); + return 0; + } + } + } + + for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { + if (!csid_hw->cid_res[i].cnt) { + csid_hw->cid_res[i].vc = vc; + csid_hw->cid_res[i].dt = dt; + csid_hw->cid_res[i].cnt = 1; + *cid = i; + CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated", + csid_hw->hw_intf->hw_idx, i); + return 0; + } + } + + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d Free cid is not available", + csid_hw->hw_intf->hw_idx); + /* Dump CID values */ + for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CID:%d vc:%d dt:%d cnt:%d", + csid_hw->hw_intf->hw_idx, i, csid_hw->cid_res[i].vc, + csid_hw->cid_res[i].dt, csid_hw->cid_res[i].cnt); + } + return -EINVAL; +} + +static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) +{ + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_reg_offset *csid_reg; + int rc = 0; + uint32_t val = 0, i; + uint32_t status; + + soc_info = &csid_hw->hw_info->soc_info; + csid_reg = csid_hw->csid_info->csid_reg; + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid HW State:%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d Csid reset", csid_hw->hw_intf->hw_idx); + + /* Mask all interrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + if (csid_hw->pxl_pipe_enable) + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr); + + /* clear all interrupts */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + + cam_io_w_mb(csid_reg->csi2_reg->csi2_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); + + if (csid_hw->pxl_pipe_enable) + cam_io_w_mb(csid_reg->cmn_reg->ipp_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); + + for (i = 0 ; i < csid_reg->cmn_reg->num_rdis; i++) + cam_io_w_mb(csid_reg->cmn_reg->rdi_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + cam_io_w_mb(0x80, soc_info->reg_map[0].mem_base + + csid_hw->csid_info->csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + + /* 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_TFE_CSID_TIMEOUT_SLEEP_US, CAM_TFE_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 */ + reinit_completion(&csid_hw->csid_top_complete); + 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); + + rc = wait_for_completion_timeout(&csid_hw->csid_top_complete, + msecs_to_jiffies(TFE_CSID_TIMEOUT)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, "CSID:%d soft reg reset fail rc = %d", + csid_hw->hw_intf->hw_idx, rc); + if (rc == 0) + rc = -ETIMEDOUT; + } else + rc = 0; + + 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) + CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d", + csid_hw->hw_intf->hw_idx, val); + csid_hw->error_irq_count = 0; + + return rc; +} + +static int cam_tfe_csid_path_reset(struct cam_tfe_csid_hw *csid_hw, + struct cam_tfe_csid_reset_cfg_args *reset) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *res; + const struct cam_tfe_csid_reg_offset *csid_reg; + uint32_t reset_strb_addr, reset_strb_val, val, id; + struct completion *complete; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + res = reset->node_res; + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid hw state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "CSID:%d resource:%d", + csid_hw->hw_intf->hw_idx, res->res_id); + + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { + if (!csid_reg->ipp_reg) { + CAM_ERR(CAM_ISP, "CSID:%d IPP not supported :%d", + csid_hw->hw_intf->hw_idx, + res->res_id); + return -EINVAL; + } + + reset_strb_addr = csid_reg->ipp_reg->csid_pxl_rst_strobes_addr; + complete = &csid_hw->csid_ipp_complete; + reset_strb_val = csid_reg->cmn_reg->ipp_path_rst_stb_all; + + /* Enable path reset done interrupt */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + val |= TFE_CSID_PATH_INFO_RST_DONE; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + } else { + id = res->res_id; + if (!csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d RDI res not supported :%d", + csid_hw->hw_intf->hw_idx, + res->res_id); + return -EINVAL; + } + + reset_strb_addr = + csid_reg->rdi_reg[id]->csid_rdi_rst_strobes_addr; + complete = + &csid_hw->csid_rdin_complete[id]; + reset_strb_val = csid_reg->cmn_reg->rdi_path_rst_stb_all; + + /* Enable path reset done interrupt */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + val |= TFE_CSID_PATH_INFO_RST_DONE; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + } + + reinit_completion(complete); + + /* Reset the corresponding tfe csid path */ + cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + + reset_strb_addr); + + rc = wait_for_completion_timeout(complete, + msecs_to_jiffies(TFE_CSID_TIMEOUT)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, "CSID:%d Res id %d fail rc = %d", + csid_hw->hw_intf->hw_idx, + res->res_id, rc); + if (rc == 0) + rc = -ETIMEDOUT; + } + +end: + return rc; +} + +static int cam_tfe_csid_cid_reserve(struct cam_tfe_csid_hw *csid_hw, + struct cam_tfe_csid_hw_reserve_resource_args *cid_reserv, + uint32_t *cid_value) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, + "CSID:%d res_id:0x%x Lane type:%d lane_num:%d dt:%d vc:%d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->res_id, + cid_reserv->in_port->lane_type, + cid_reserv->in_port->lane_num, + cid_reserv->in_port->dt, + cid_reserv->in_port->vc); + + if (cid_reserv->in_port->res_id >= CAM_ISP_TFE_IN_RES_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid phy sel %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->res_id); + rc = -EINVAL; + goto end; + } + + if (cid_reserv->in_port->lane_type >= CAM_ISP_LANE_TYPE_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid lane type %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->lane_type); + rc = -EINVAL; + goto end; + } + + if ((cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_DPHY && + cid_reserv->in_port->lane_num > 4)) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid lane num %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->lane_num); + rc = -EINVAL; + goto end; + } + + if (cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_CPHY && + cid_reserv->in_port->lane_num > 3) { + CAM_ERR(CAM_ISP, " CSID:%d Invalid lane type %d & num %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->lane_type, + cid_reserv->in_port->lane_num); + rc = -EINVAL; + goto end; + } + + /* CSID CSI2 v1.1 supports 4 vc */ + if (cid_reserv->in_port->dt > 0x3f || + cid_reserv->in_port->vc > 0x3) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->vc, cid_reserv->in_port->dt); + rc = -EINVAL; + goto end; + } + + if (csid_hw->csi2_reserve_cnt == UINT_MAX) { + CAM_ERR(CAM_ISP, + "CSID%d reserve cnt reached max", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "Reserve_cnt %u", csid_hw->csi2_reserve_cnt); + + if (csid_hw->csi2_reserve_cnt) { + /* current configure res type should match requested res type */ + if (csid_hw->in_res_id != cid_reserv->in_port->res_id) { + rc = -EINVAL; + goto end; + } + + if (csid_hw->csi2_rx_cfg.lane_cfg != + cid_reserv->in_port->lane_cfg || + csid_hw->csi2_rx_cfg.lane_type != + cid_reserv->in_port->lane_type || + csid_hw->csi2_rx_cfg.lane_num != + cid_reserv->in_port->lane_num) { + rc = -EINVAL; + goto end; + } + } + + rc = cam_tfe_csid_cid_get(csid_hw, + cid_reserv->in_port->vc, + cid_reserv->in_port->dt, + cid_value); + if (rc) { + CAM_ERR(CAM_ISP, "CSID:%d CID Reserve failed res_id %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->res_id); + goto end; + } + + if (!csid_hw->csi2_reserve_cnt) { + csid_hw->in_res_id = cid_reserv->in_port->res_id; + + csid_hw->csi2_rx_cfg.lane_cfg = + cid_reserv->in_port->lane_cfg; + csid_hw->csi2_rx_cfg.lane_type = + cid_reserv->in_port->lane_type; + csid_hw->csi2_rx_cfg.lane_num = + cid_reserv->in_port->lane_num; + + if (cid_reserv->in_port->res_id != CAM_ISP_TFE_IN_RES_TPG) + csid_hw->csi2_rx_cfg.phy_sel = + (cid_reserv->in_port->res_id & 0xFF) - 1; + else + csid_hw->csi2_rx_cfg.phy_sel = + (cid_reserv->phy_sel & 0xFF) - 1; + } + + csid_hw->csi2_reserve_cnt++; + CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired reserv cnt:%d", + csid_hw->hw_intf->hw_idx, *cid_value, + csid_hw->csi2_reserve_cnt); + +end: + return rc; +} + +static int cam_tfe_csid_path_reserve(struct cam_tfe_csid_hw *csid_hw, + struct cam_tfe_csid_hw_reserve_resource_args *reserve) +{ + int rc = 0; + struct cam_tfe_csid_path_cfg *path_data; + struct cam_isp_resource_node *res; + uint32_t cid_value; + + /* CSID CSI2 v2.0 supports 4 vc */ + if (reserve->in_port->dt > 0x3f || reserve->in_port->vc > 0x3 || + (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX)) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d mode:%d", + csid_hw->hw_intf->hw_idx, + reserve->in_port->vc, reserve->in_port->dt, + reserve->sync_mode); + rc = -EINVAL; + goto end; + } + + switch (reserve->res_id) { + case CAM_TFE_CSID_PATH_RES_IPP: + if (csid_hw->ipp_res.res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_DBG(CAM_ISP, + "CSID:%d IPP resource not available %d", + csid_hw->hw_intf->hw_idx, + csid_hw->ipp_res.res_state); + rc = -EINVAL; + goto end; + } + + if (cam_tfe_csid_is_ipp_format_supported( + reserve->in_port->format)) { + CAM_ERR(CAM_ISP, + "CSID:%d res id:%d un support format %d", + csid_hw->hw_intf->hw_idx, reserve->res_id, + reserve->in_port->format); + rc = -EINVAL; + goto end; + } + rc = cam_tfe_csid_cid_reserve(csid_hw, reserve, &cid_value); + if (rc) + goto end; + + /* assign the IPP resource */ + res = &csid_hw->ipp_res; + CAM_DBG(CAM_ISP, + "CSID:%d IPP resource:%d acquired successfully", + csid_hw->hw_intf->hw_idx, res->res_id); + + break; + + case CAM_TFE_CSID_PATH_RES_RDI_0: + case CAM_TFE_CSID_PATH_RES_RDI_1: + case CAM_TFE_CSID_PATH_RES_RDI_2: + if (csid_hw->rdi_res[reserve->res_id].res_state != + CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d RDI:%d resource not available %d", + csid_hw->hw_intf->hw_idx, + reserve->res_id, + csid_hw->rdi_res[reserve->res_id].res_state); + rc = -EINVAL; + goto end; + } + + rc = cam_tfe_csid_cid_reserve(csid_hw, reserve, &cid_value); + if (rc) + goto end; + + res = &csid_hw->rdi_res[reserve->res_id]; + CAM_DBG(CAM_ISP, + "CSID:%d RDI resource:%d acquire success", + csid_hw->hw_intf->hw_idx, + res->res_id); + + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id:%d", + csid_hw->hw_intf->hw_idx, reserve->res_id); + rc = -EINVAL; + goto end; + } + + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + path_data = (struct cam_tfe_csid_path_cfg *)res->res_priv; + + CAM_DBG(CAM_ISP, "sensor width:%d height:%d fps:%d vbi:%d hbi:%d", + reserve->in_port->sensor_width, + reserve->in_port->sensor_height, + reserve->in_port->sensor_fps, + reserve->in_port->sensor_vbi, + reserve->in_port->sensor_hbi); + path_data->sensor_width = reserve->in_port->sensor_width; + path_data->sensor_height = reserve->in_port->sensor_height; + path_data->sensor_fps = reserve->in_port->sensor_fps; + path_data->sensor_hbi = reserve->in_port->sensor_vbi; + path_data->sensor_vbi = reserve->in_port->sensor_hbi; + + path_data->cid = cid_value; + path_data->in_format = reserve->in_port->format; + path_data->out_format = reserve->out_port->format; + path_data->sync_mode = reserve->sync_mode; + path_data->height = reserve->in_port->height; + path_data->start_line = reserve->in_port->line_start; + path_data->end_line = reserve->in_port->line_end; + + csid_hw->event_cb = reserve->event_cb; + csid_hw->event_cb_priv = reserve->event_cb_prv; + + /* Enable crop only for ipp */ + if (reserve->res_id == CAM_TFE_CSID_PATH_RES_IPP) + path_data->crop_enable = true; + + CAM_DBG(CAM_ISP, + "Res id: %d height:%d line_start %d line_end %d crop_en %d", + reserve->res_id, reserve->in_port->height, + reserve->in_port->line_start, reserve->in_port->line_end, + path_data->crop_enable); + + path_data->dt = reserve->in_port->dt; + path_data->vc = reserve->in_port->vc; + + if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { + path_data->start_pixel = reserve->in_port->left_start; + path_data->end_pixel = reserve->in_port->left_end; + path_data->width = reserve->in_port->left_width; + CAM_DBG(CAM_ISP, "CSID:%d master:startpixel 0x%x endpixel:0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_pixel, + path_data->end_pixel); + CAM_DBG(CAM_ISP, "CSID:%d master:line start:0x%x line end:0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_line, + path_data->end_line); + } else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { + path_data->master_idx = reserve->master_idx; + CAM_DBG(CAM_ISP, "CSID:%d master_idx=%d", + csid_hw->hw_intf->hw_idx, path_data->master_idx); + path_data->start_pixel = reserve->in_port->right_start; + path_data->end_pixel = reserve->in_port->right_end; + path_data->width = reserve->in_port->right_width; + CAM_DBG(CAM_ISP, "CSID:%d slave:start:0x%x end:0x%x width 0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_pixel, + path_data->end_pixel, path_data->width); + CAM_DBG(CAM_ISP, "CSID:%d slave:line start:0x%x line end:0x%x", + csid_hw->hw_intf->hw_idx, path_data->start_line, + path_data->end_line); + } else { + path_data->width = reserve->in_port->left_width; + path_data->start_pixel = reserve->in_port->left_start; + path_data->end_pixel = reserve->in_port->left_end; + CAM_DBG(CAM_ISP, "Res id: %d left width %d start: %d stop:%d", + reserve->res_id, reserve->in_port->left_width, + reserve->in_port->left_start, + reserve->in_port->left_end); + } + + CAM_DBG(CAM_ISP, "Res %d width %d height %d", reserve->res_id, + path_data->width, path_data->height); + reserve->node_res = res; + +end: + return rc; +} + +static int cam_tfe_csid_enable_csi2( + struct cam_tfe_csid_hw *csid_hw) +{ + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t val = 0; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + CAM_DBG(CAM_ISP, "CSID:%d config csi2 rx", + csid_hw->hw_intf->hw_idx); + + /* 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 & + 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); + + /* rx cfg1 */ + val = (1 << csid_reg->csi2_reg->csi2_misr_enable_shift_val); + + /* enable packet ecc correction */ + val |= 1; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + + /* Enable the CSI2 rx inerrupts */ + val = TFE_CSID_CSI2_RX_INFO_RST_DONE | + TFE_CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW | + TFE_CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW | + TFE_CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW | + TFE_CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW | + TFE_CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION | + TFE_CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION | + TFE_CSID_CSI2_RX_ERROR_CRC | + TFE_CSID_CSI2_RX_ERROR_ECC | + TFE_CSID_CSI2_RX_ERROR_MMAPPED_VC_DT | + TFE_CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW | + TFE_CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME | + TFE_CSID_CSI2_RX_ERROR_CPHY_PH_CRC; + + /* Enable the interrupt based on csid debug info set */ + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOT_IRQ) + val |= TFE_CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED | + TFE_CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED | + TFE_CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED | + TFE_CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED; + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOT_IRQ) + val |= TFE_CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED | + TFE_CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED | + TFE_CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED | + TFE_CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED; + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val |= TFE_CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED; + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= TFE_CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED; + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= TFE_CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + return 0; +} + +static int cam_tfe_csid_disable_csi2( + struct cam_tfe_csid_hw *csid_hw) +{ + const struct cam_tfe_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; + CAM_DBG(CAM_ISP, "CSID:%d Disable csi2 rx", + csid_hw->hw_intf->hw_idx); + + /* Disable the CSI2 rx inerrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + /* Reset the Rx CFG registers */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + + return 0; +} + +static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) +{ + int rc = 0; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t i, val, clk_lvl; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + /* overflow check before increment */ + if (csid_hw->hw_info->open_count == UINT_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Open count reached max", + csid_hw->hw_intf->hw_idx); + return -EINVAL; + } + + /* Increment ref Count */ + csid_hw->hw_info->open_count++; + if (csid_hw->hw_info->open_count > 1) { + CAM_DBG(CAM_ISP, "CSID hw has already been enabled"); + return rc; + } + + CAM_DBG(CAM_ISP, "CSID:%d init CSID HW", + csid_hw->hw_intf->hw_idx); + + rc = cam_soc_util_get_clk_level(soc_info, csid_hw->clk_rate, + soc_info->src_clk_idx, &clk_lvl); + CAM_DBG(CAM_ISP, "CSID clock lvl %u", clk_lvl); + + rc = cam_tfe_csid_enable_soc_resources(soc_info, clk_lvl); + if (rc) { + CAM_ERR(CAM_ISP, "CSID:%d Enable SOC failed", + csid_hw->hw_intf->hw_idx); + goto err; + } + + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP; + /* Disable the top IRQ interrupt */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); + /* Reset CSID top */ + rc = cam_tfe_csid_global_reset(csid_hw); + if (rc) + goto disable_soc; + + /* clear all interrupts */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + + cam_io_w_mb(csid_reg->csi2_reg->csi2_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); + + if (csid_hw->pxl_pipe_enable) + cam_io_w_mb(csid_reg->cmn_reg->ipp_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + cam_io_w_mb(csid_reg->cmn_reg->rdi_irq_mask_all, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_hw_version_addr); + CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + /* enable the csi2 rx */ + rc = cam_tfe_csid_enable_csi2(csid_hw); + if (rc) + goto disable_soc; + + return rc; + +disable_soc: + cam_tfe_csid_disable_soc_resources(soc_info); + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; +err: + csid_hw->hw_info->open_count--; + return rc; +} + +static int cam_tfe_csid_disable_hw(struct cam_tfe_csid_hw *csid_hw) +{ + int rc = -EINVAL; + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_reg_offset *csid_reg; + unsigned long flags; + + /* Check for refcount */ + if (!csid_hw->hw_info->open_count) { + CAM_WARN(CAM_ISP, "Unbalanced disable_hw"); + return rc; + } + + /* Decrement ref Count */ + csid_hw->hw_info->open_count--; + + if (csid_hw->hw_info->open_count) { + rc = 0; + return rc; + } + + soc_info = &csid_hw->hw_info->soc_info; + csid_reg = csid_hw->csid_info->csid_reg; + + /* Disable the csi2 */ + cam_tfe_csid_disable_csi2(csid_hw); + + CAM_DBG(CAM_ISP, "%s:Calling Global Reset", __func__); + cam_tfe_csid_global_reset(csid_hw); + CAM_DBG(CAM_ISP, "%s:Global Reset Done", __func__); + + CAM_DBG(CAM_ISP, "CSID:%d De-init CSID HW", + csid_hw->hw_intf->hw_idx); + + /* Disable the top IRQ interrupt */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); + + rc = cam_tfe_csid_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed", + csid_hw->hw_intf->hw_idx); + + spin_lock_irqsave(&csid_hw->spin_lock, flags); + csid_hw->device_enabled = 0; + spin_unlock_irqrestore(&csid_hw->spin_lock, flags); + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + csid_hw->error_irq_count = 0; + + return rc; +} + +static int cam_tfe_csid_init_config_pxl_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg = NULL; + uint32_t decode_format = 0, plain_format = 0, val = 0; + + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + pxl_reg = csid_reg->ipp_reg; + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d IPP :%d is not supported on HW", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Config IPP Path"); + rc = cam_tfe_csid_get_format_ipp(path_data->in_format, + &decode_format, &plain_format); + if (rc) + return rc; + + /* + * configure Pxl path and enable the time stamp capture. + * enable the HW measrurement blocks + */ + val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | + (decode_format << csid_reg->cmn_reg->fmt_shift_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_h_en_shift_val) | + (path_data->crop_enable << + csid_reg->cmn_reg->crop_v_en_shift_val) | + (1 << 1); + + val |= (1 << pxl_reg->pix_store_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg1_addr); + + /* select the post irq sub sample strobe for time stamp capture */ + val |= TFE_CSID_TIMESTAMP_STB_POST_IRQ; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg1_addr); + + if (path_data->crop_enable) { + val = (((path_data->end_pixel & 0xFFFF) << + csid_reg->cmn_reg->crop_shift) | + (path_data->start_pixel & 0xFFFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_hcrop_addr); + CAM_DBG(CAM_ISP, "CSID:%d Horizontal crop config val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + val = (((path_data->end_line & 0xFFFF) << + csid_reg->cmn_reg->crop_shift) | + (path_data->start_line & 0xFFFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_vcrop_addr); + CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + /* Enable generating early eof strobe based on crop config */ + if (!(csid_hw->csid_debug & TFE_CSID_DEBUG_DISABLE_EARLY_EOF)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + val |= (1 << pxl_reg->early_eof_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + } + } + + /* Enable the Pxl path */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_cfg0_addr); + + /* Enable Error Detection Overflow ctrl mode: 2 -> Detect overflow */ + val = 0x9; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_err_recovery_cfg0_addr); + + /* configure the rx packet capture based on csid debug set */ + val = 0; + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val = ((1 << + csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr); + CAM_DBG(CAM_ISP, "rx capture control value 0x%x", val); + + res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; + + return rc; +} + +static int cam_tfe_csid_deinit_pxl_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg = NULL; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + pxl_reg = csid_reg->ipp_reg; + if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { + CAM_ERR(CAM_ISP, + "CSID:%d IPP Res type %d res_id:%d in wrong state %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + rc = -EINVAL; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d IPP %d is not supported on HW", + csid_hw->hw_intf->hw_idx, res->res_id); + rc = -EINVAL; + goto end; + } + + /* Disable Error Recovery */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_err_recovery_cfg0_addr); + +end: + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_tfe_csid_enable_pxl_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg = NULL; + uint32_t val = 0; + + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + pxl_reg = csid_reg->ipp_reg; + + if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { + CAM_ERR(CAM_ISP, + "CSID:%d IPP path res type:%d res_id:%d Invalid state%d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + return -EINVAL; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d IPP resid: %d not supported on HW", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Enable IPP path"); + + /* Set master or slave path */ + if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) + /* Set halt mode as master */ + val = (TFE_CSID_HALT_MODE_MASTER << + pxl_reg->halt_mode_shift) | + (pxl_reg->halt_master_sel_master_val << + pxl_reg->halt_master_sel_shift); + else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + /* Set halt mode as slave and set master idx */ + val = (TFE_CSID_HALT_MODE_SLAVE << pxl_reg->halt_mode_shift); + else + /* Default is internal halt mode */ + val = 0; + + /* + * Resume at frame boundary if Master or No Sync. + * Slave will get resume command from Master. + */ + if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || + path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) + val |= CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + + CAM_DBG(CAM_ISP, "CSID:%d IPP Ctrl val: 0x%x", + csid_hw->hw_intf->hw_idx, val); + + /* Enable the required pxl path interrupts */ + val = TFE_CSID_PATH_INFO_RST_DONE | + TFE_CSID_PATH_ERROR_FIFO_OVERFLOW | + TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION | + TFE_CSID_PATH_IPP_OVERFLOW_IRQ; + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) + val |= TFE_CSID_PATH_INFO_INPUT_SOF; + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) + val |= TFE_CSID_PATH_INFO_INPUT_EOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + + CAM_DBG(CAM_ISP, "Enable IPP IRQ mask 0x%x", val); + + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + +static int cam_tfe_csid_disable_pxl_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res, + enum cam_tfe_csid_halt_cmd stop_cmd) +{ + int rc = 0; + uint32_t val = 0; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg; + + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return rc; + } + + pxl_reg = csid_reg->ipp_reg; + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_DBG(CAM_ISP, "CSID:%d IPP path Res:%d Invalid state%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return -EINVAL; + } + + if (!pxl_reg) { + CAM_ERR(CAM_ISP, "CSID:%d IPP %d is not supported on HW", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (stop_cmd != CAM_TFE_CSID_HALT_AT_FRAME_BOUNDARY && + stop_cmd != CAM_TFE_CSID_HALT_IMMEDIATELY) { + CAM_ERR(CAM_ISP, + "CSID:%d IPP path un supported stop command:%d", + csid_hw->hw_intf->hw_idx, stop_cmd); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id:%d IPP path", + csid_hw->hw_intf->hw_idx, res->res_id); + + 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; +} + +static int cam_tfe_csid_init_config_rdi_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t path_format = 0, plain_fmt = 0, val = 0, id; + + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + id = res->res_id; + if (!csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d RDI:%d is not supported on HW", + csid_hw->hw_intf->hw_idx, id); + return -EINVAL; + } + + rc = cam_tfe_csid_get_format_rdi(path_data->in_format, + path_data->out_format, &path_format, &plain_fmt); + if (rc) + return rc; + + /* + * RDI path config and enable the time stamp capture + * Enable the measurement blocks + */ + val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | + (path_format << csid_reg->cmn_reg->fmt_shift_val) | + (plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) | + (1 << 2) | 1; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + + /* select the post irq sub sample strobe for time stamp capture */ + cam_io_w_mb(TFE_CSID_TIMESTAMP_STB_POST_IRQ, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr); + + /* Enable Error Detection, Overflow ctrl mode: 2 -> Detect overflow */ + val = 0x9; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_err_recovery_cfg0_addr); + + /* Configure the halt mode */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + + /* Enable the RPP path */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + + /* configure the rx packet capture based on csid debug set */ + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val = ((1 << + csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= ((1 << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | + (path_data->dt << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | + (path_data->vc << + csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; + + return rc; +} + +static int cam_tfe_csid_deinit_rdi_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + int rc = 0; + uint32_t id; + const struct cam_tfe_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; + id = res->res_id; + + if (res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2 || + res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW || + !csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, + res->res_state); + return -EINVAL; + } + + /* Disable Error Recovery */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_err_recovery_cfg0_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_tfe_csid_enable_rdi_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t id, val; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + id = res->res_id; + + if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2 || + !csid_reg->rdi_reg[id]) { + CAM_ERR(CAM_ISP, + "CSID:%d invalid res type:%d res_id:%d state%d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + return -EINVAL; + } + + /* resume at frame boundary */ + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + + /* Enable the required RDI interrupts */ + val = TFE_CSID_PATH_INFO_RST_DONE | TFE_CSID_PATH_ERROR_FIFO_OVERFLOW | + TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION | + TFE_CSID_PATH_RDI_OVERFLOW_IRQ; + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) + val |= TFE_CSID_PATH_INFO_INPUT_SOF; + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) + val |= TFE_CSID_PATH_INFO_INPUT_EOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); + + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + +static int cam_tfe_csid_disable_rdi_path( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res, + enum cam_tfe_csid_halt_cmd stop_cmd) +{ + int rc = 0; + uint32_t id, val = 0; + const struct cam_tfe_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; + id = res->res_id; + + if ((res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2) || + (!csid_reg->rdi_reg[res->res_id])) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d Res:%d already in stopped state:%d", + csid_hw->hw_intf->hw_idx, + res->res_id, res->res_state); + return rc; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d Res:%d Invalid res_state%d", + csid_hw->hw_intf->hw_idx, res->res_id, + res->res_state); + return -EINVAL; + } + + if (stop_cmd != CAM_TFE_CSID_HALT_AT_FRAME_BOUNDARY && + stop_cmd != CAM_TFE_CSID_HALT_IMMEDIATELY) { + CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d", + csid_hw->hw_intf->hw_idx, stop_cmd); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_id); + + 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_tfe_csid_poll_stop_status( + struct cam_tfe_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_tfe_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_TFE_CSID_PATH_RES_MAX; res_id++, res_mask >>= 1) { + if ((res_mask & 0x1) == 0) + continue; + val = 0; + + if (res_id == CAM_TFE_CSID_PATH_RES_IPP) { + csid_status_addr = + csid_reg->ipp_reg->csid_pxl_status_addr; + + if (csid_hw->ipp_res.res_state != + CAM_ISP_RESOURCE_STATE_STREAMING) + continue; + + } else { + csid_status_addr = + csid_reg->rdi_reg[res_id]->csid_rdi_status_addr; + + if (csid_hw->rdi_res[res_id].res_state != + CAM_ISP_RESOURCE_STATE_STREAMING) + continue; + + } + + 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_TFE_CSID_TIMEOUT_SLEEP_US, + CAM_TFE_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; +} + +static int cam_tfe_csid_get_time_stamp( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_tfe_csid_get_time_stamp_args *time_stamp; + struct cam_isp_resource_node *res; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_rdi_reg_offset *rdi_reg; + struct timespec64 ts; + uint32_t time_32, id; + + time_stamp = (struct cam_tfe_csid_get_time_stamp_args *)cmd_args; + res = time_stamp->node_res; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH || + res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_timestamp_curr1_sof_addr); + time_stamp->time_stamp_val = (uint64_t) time_32; + time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_timestamp_curr0_sof_addr); + } else { + id = res->res_id; + rdi_reg = csid_reg->rdi_reg[id]; + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_timestamp_curr1_sof_addr); + time_stamp->time_stamp_val = (uint64_t) time_32; + time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; + + time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_timestamp_curr0_sof_addr); + } + + time_stamp->time_stamp_val |= (uint64_t) time_32; + time_stamp->time_stamp_val = mul_u64_u32_div( + time_stamp->time_stamp_val, + CAM_TFE_CSID_QTIMER_MUL_FACTOR, + CAM_TFE_CSID_QTIMER_DIV_FACTOR); + + ktime_get_boottime_ts64(&ts); + time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + + return 0; +} + +static int cam_tfe_csid_set_csid_debug(struct cam_tfe_csid_hw *csid_hw, + void *cmd_args) +{ + uint32_t *csid_debug; + + csid_debug = (uint32_t *) cmd_args; + csid_hw->csid_debug = *csid_debug; + CAM_DBG(CAM_ISP, "CSID:%d set csid debug value:%d", + csid_hw->hw_intf->hw_idx, csid_hw->csid_debug); + + return 0; +} + +static int cam_tfe_csid_get_hw_caps(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw_caps *hw_caps; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + const struct cam_tfe_csid_reg_offset *csid_reg; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + csid_reg = csid_hw->csid_info->csid_reg; + hw_caps = (struct cam_tfe_csid_hw_caps *) get_hw_cap_args; + + hw_caps->num_rdis = csid_reg->cmn_reg->num_rdis; + hw_caps->num_pix = csid_hw->pxl_pipe_enable; + hw_caps->major_version = csid_reg->cmn_reg->major_version; + hw_caps->minor_version = csid_reg->cmn_reg->minor_version; + hw_caps->version_incr = csid_reg->cmn_reg->version_incr; + + CAM_DBG(CAM_ISP, + "CSID:%d No rdis:%d, no pix:%d, major:%d minor:%d ver :%d", + csid_hw->hw_intf->hw_idx, hw_caps->num_rdis, + hw_caps->num_pix, hw_caps->major_version, + hw_caps->minor_version, hw_caps->version_incr); + + return rc; +} + +static int cam_tfe_csid_reset(void *hw_priv, + void *reset_args, uint32_t arg_size) +{ + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_tfe_csid_reset_cfg_args *reset; + int rc = 0; + + if (!hw_priv || !reset_args || (arg_size != + sizeof(struct cam_tfe_csid_reset_cfg_args))) { + CAM_ERR(CAM_ISP, "CSID:Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + reset = (struct cam_tfe_csid_reset_cfg_args *)reset_args; + + switch (reset->reset_type) { + case CAM_TFE_CSID_RESET_GLOBAL: + rc = cam_tfe_csid_global_reset(csid_hw); + break; + case CAM_TFE_CSID_RESET_PATH: + rc = cam_tfe_csid_path_reset(csid_hw, reset); + break; + default: + CAM_ERR(CAM_ISP, "CSID:Invalid reset type :%d", + reset->reset_type); + rc = -EINVAL; + break; + } + + return rc; +} + +static int cam_tfe_csid_reserve(void *hw_priv, + void *reserve_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_tfe_csid_hw_reserve_resource_args *reserv; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_tfe_csid_hw_reserve_resource_args))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + reserv = (struct cam_tfe_csid_hw_reserve_resource_args *)reserve_args; + + if (reserv->res_type != CAM_ISP_RESOURCE_PIX_PATH) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type :%d", + csid_hw->hw_intf->hw_idx, reserv->res_type); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "res_type %d, CSID: %u", + reserv->res_type, csid_hw->hw_intf->hw_idx); + + mutex_lock(&csid_hw->hw_info->hw_mutex); + rc = cam_tfe_csid_path_reserve(csid_hw, reserv); + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_tfe_csid_release(void *hw_priv, + void *release_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + struct cam_tfe_csid_path_cfg *path_data; + + if (!hw_priv || !release_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + res = (struct cam_isp_resource_node *)release_args; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if ((res->res_type == CAM_ISP_RESOURCE_PIX_PATH && + res->res_id >= CAM_TFE_CSID_PATH_RES_MAX)) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + goto end; + } + + if ((res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE) || + (res->res_state >= CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_WARN(CAM_ISP, + "CSID:%d res type:%d Res %d in state %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, + res->res_state); + goto end; + } + + CAM_DBG(CAM_ISP, "CSID:%d res type :%d Resource id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); + + path_data = (struct cam_tfe_csid_path_cfg *)res->res_priv; + if (csid_hw->cid_res[path_data->cid].cnt) + csid_hw->cid_res[path_data->cid].cnt--; + + if (csid_hw->csi2_reserve_cnt) + csid_hw->csi2_reserve_cnt--; + + if (!csid_hw->csi2_reserve_cnt) + memset(&csid_hw->csi2_rx_cfg, 0, + sizeof(struct cam_tfe_csid_csi2_rx_cfg)); + + CAM_DBG(CAM_ISP, "CSID:%d res id :%d cnt:%d reserv cnt:%d", + csid_hw->hw_intf->hw_idx, + res->res_id, csid_hw->cid_res[path_data->cid].cnt, + csid_hw->csi2_reserve_cnt); + + res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + +end: + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_tfe_csid_reset_retain_sw_reg( + struct cam_tfe_csid_hw *csid_hw) +{ + int rc = 0; + uint32_t status; + const struct cam_tfe_csid_reg_offset *csid_reg = + csid_hw->csid_info->csid_reg; + struct cam_hw_soc_info *soc_info; + + soc_info = &csid_hw->hw_info->soc_info; + /* clear the top interrupt first */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + 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_TFE_CSID_TIMEOUT_SLEEP_US, CAM_TFE_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; + } else { + CAM_DBG(CAM_ISP, "CSID:%d hw reset completed %d", + csid_hw->hw_intf->hw_idx, rc); + rc = 0; + } + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + return rc; +} + +static int cam_tfe_csid_init_hw(void *hw_priv, + void *init_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + const struct cam_tfe_csid_reg_offset *csid_reg; + unsigned long flags; + + if (!hw_priv || !init_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + res = (struct cam_isp_resource_node *)init_args; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type state %d", + csid_hw->hw_intf->hw_idx, + res->res_type); + return -EINVAL; + } + + csid_reg = csid_hw->csid_info->csid_reg; + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && + res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res tpe:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + goto end; + } + + if ((res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && + (res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { + CAM_ERR(CAM_ISP, + "CSID:%d res type:%d res_id:%dInvalid state %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id, res->res_state); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "CSID:%d res type :%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); + + /* Initialize the csid hardware */ + rc = cam_tfe_csid_enable_hw(csid_hw); + if (rc) + goto end; + + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) + rc = cam_tfe_csid_init_config_pxl_path(csid_hw, res); + else + rc = cam_tfe_csid_init_config_rdi_path(csid_hw, res); + + rc = cam_tfe_csid_reset_retain_sw_reg(csid_hw); + if (rc < 0) + CAM_ERR(CAM_ISP, "CSID: Failed in SW reset"); + + if (rc) + cam_tfe_csid_disable_hw(csid_hw); + + spin_lock_irqsave(&csid_hw->spin_lock, flags); + csid_hw->device_enabled = 1; + spin_unlock_irqrestore(&csid_hw->spin_lock, flags); +end: + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_tfe_csid_deinit_hw(void *hw_priv, + void *deinit_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + + if (!hw_priv || !deinit_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID:Invalid arguments"); + return -EINVAL; + } + + res = (struct cam_isp_resource_node *)deinit_args; + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + + if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid Res type %d", + csid_hw->hw_intf->hw_idx, + res->res_type); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "Enter"); + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if (res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in De-init state", + csid_hw->hw_intf->hw_idx, + res->res_id); + goto end; + } + + CAM_DBG(CAM_ISP, "De-Init IPP Path: %d", res->res_id); + + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) + rc = cam_tfe_csid_deinit_pxl_path(csid_hw, res); + else + rc = cam_tfe_csid_deinit_rdi_path(csid_hw, res); + + /* Disable CSID HW */ + CAM_DBG(CAM_ISP, "Disabling CSID Hw"); + cam_tfe_csid_disable_hw(csid_hw); + CAM_DBG(CAM_ISP, "%s: Exit", __func__); + +end: + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_tfe_csid_start(void *hw_priv, void *start_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + const struct cam_tfe_csid_reg_offset *csid_reg; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + res = (struct cam_isp_resource_node *)start_args; + csid_reg = csid_hw->csid_info->csid_reg; + + if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && + res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res tpe:%d res id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + rc = -EINVAL; + goto end; + } + + /* Reset sof irq debug fields */ + csid_hw->sof_irq_triggered = false; + csid_hw->irq_debug_cnt = 0; + + CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d", + csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); + + switch (res->res_type) { + case CAM_ISP_RESOURCE_PIX_PATH: + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) + rc = cam_tfe_csid_enable_pxl_path(csid_hw, res); + else + rc = cam_tfe_csid_enable_rdi_path(csid_hw, res); + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + csid_hw->hw_intf->hw_idx, res->res_type); + break; + } +end: + return rc; +} + +static int cam_tfe_csid_stop(void *hw_priv, + void *stop_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res; + struct cam_tfe_csid_hw_stop_args *csid_stop; + uint32_t i; + uint32_t res_mask = 0; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_tfe_csid_hw_stop_args))) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + csid_stop = (struct cam_tfe_csid_hw_stop_args *) stop_args; + + if (!csid_stop->num_res) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + CAM_DBG(CAM_ISP, "CSID:%d num_res %d", + csid_hw->hw_intf->hw_idx, + csid_stop->num_res); + + /* Stop the resource first */ + for (i = 0; i < csid_stop->num_res; i++) { + res = csid_stop->node_res[i]; + CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id); + switch (res->res_type) { + case CAM_ISP_RESOURCE_PIX_PATH: + res_mask |= (1 << res->res_id); + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) + rc = cam_tfe_csid_disable_pxl_path(csid_hw, + res, csid_stop->stop_cmd); + else + rc = cam_tfe_csid_disable_rdi_path(csid_hw, + res, csid_stop->stop_cmd); + + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + csid_hw->hw_intf->hw_idx, + res->res_type); + break; + } + } + + if (res_mask) + rc = cam_tfe_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; + } + + CAM_DBG(CAM_ISP, "%s: Exit", __func__); + return rc; +} + +static int cam_tfe_csid_read(void *hw_priv, + void *read_args, uint32_t arg_size) +{ + CAM_ERR(CAM_ISP, "CSID: un supported"); + return -EINVAL; +} + +static int cam_tfe_csid_write(void *hw_priv, + void *write_args, uint32_t arg_size) +{ + CAM_ERR(CAM_ISP, "CSID: un supported"); + return -EINVAL; +} + +static int cam_tfe_csid_sof_irq_debug( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + int i = 0; + uint32_t val = 0; + bool sof_irq_enable = false; + const struct cam_tfe_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; + + if (*((uint32_t *)cmd_args) == 1) + sof_irq_enable = true; + + if (csid_hw->hw_info->hw_state == + CAM_HW_STATE_POWER_DOWN) { + CAM_WARN(CAM_ISP, + "CSID powered down unable to %s sof irq", + sof_irq_enable ? "enable" : "disable"); + return 0; + } + + if (csid_reg->ipp_reg) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + + if (val) { + if (sof_irq_enable) + val |= TFE_CSID_PATH_INFO_INPUT_SOF; + else + val &= ~TFE_CSID_PATH_INFO_INPUT_SOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + val = 0; + } + } + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr); + if (val) { + if (sof_irq_enable) + val |= TFE_CSID_PATH_INFO_INPUT_SOF; + else + val &= ~TFE_CSID_PATH_INFO_INPUT_SOF; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr); + val = 0; + } + } + + if (sof_irq_enable) { + csid_hw->csid_debug |= TFE_CSID_DEBUG_ENABLE_SOF_IRQ; + csid_hw->sof_irq_triggered = true; + } else { + csid_hw->csid_debug &= ~TFE_CSID_DEBUG_ENABLE_SOF_IRQ; + csid_hw->sof_irq_triggered = false; + } + + CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s", + sof_irq_enable ? "enabled" : "disabled"); + + return 0; +} + +static int cam_tfe_csid_set_csid_clock( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_tfe_csid_clock_update_args *clk_update = NULL; + + if (!csid_hw) + return -EINVAL; + + clk_update = + (struct cam_tfe_csid_clock_update_args *)cmd_args; + + csid_hw->clk_rate = clk_update->clk_rate; + CAM_DBG(CAM_ISP, "CSID clock rate %llu", csid_hw->clk_rate); + + return 0; +} + +static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, + void *cmd_args) +{ + struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *res; + struct cam_tfe_csid_path_cfg *path_data; + uint32_t id; + int val; + + csid_reg = (struct cam_tfe_csid_reg_offset *) + csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + res = (struct cam_isp_resource_node *)cmd_args; + path_data = (struct cam_tfe_csid_path_cfg *)res->res_priv; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH || + res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_DBG(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { + CAM_INFO(CAM_ISP, "Dumping CSID:%d IPP registers ", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_cfg0_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->ipp_reg->csid_pxl_cfg0_addr, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_cfg1_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->ipp_reg->csid_pxl_cfg1_addr, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_ctrl_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->ipp_reg->csid_pxl_ctrl_addr, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_hcrop_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->ipp_reg->csid_pxl_hcrop_addr, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_vcrop_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->ipp_reg->csid_pxl_vcrop_addr, val); + } else { + id = res->res_id; + CAM_INFO(CAM_ISP, "Dumping CSID:%d RDI:%d registers ", + csid_hw->hw_intf->hw_idx, id); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + CAM_INFO(CAM_ISP, "offset 0x%x=0x08%x", + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr, val); + } + CAM_INFO(CAM_ISP, + "start pix:%d end pix:%d start line:%d end line:%d w:%d h:%d", + path_data->start_pixel, path_data->end_pixel, + path_data->start_line, path_data->end_line, + path_data->width, path_data->height); + CAM_INFO(CAM_ISP, + "clock:%d crop_enable:%d vc:%d dt:%d informat:%d outformat:%d", + path_data->clk_rate, path_data->crop_enable, + path_data->vc, path_data->dt, + path_data->in_format, path_data->out_format); + + return 0; +} + +static int cam_tfe_csid_process_cmd(void *hw_priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_info *csid_hw_info; + + if (!hw_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); + return -EINVAL; + } + + csid_hw_info = (struct cam_hw_info *)hw_priv; + csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; + + switch (cmd_type) { + case CAM_TFE_CSID_CMD_GET_TIME_STAMP: + rc = cam_tfe_csid_get_time_stamp(csid_hw, cmd_args); + break; + case CAM_TFE_CSID_SET_CSID_DEBUG: + rc = cam_tfe_csid_set_csid_debug(csid_hw, cmd_args); + break; + case CAM_TFE_CSID_SOF_IRQ_DEBUG: + rc = cam_tfe_csid_sof_irq_debug(csid_hw, cmd_args); + break; + case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE: + rc = cam_tfe_csid_set_csid_clock(csid_hw, cmd_args); + break; + case CAM_TFE_CSID_CMD_GET_REG_DUMP: + rc = cam_tfe_csid_get_regdump(csid_hw, cmd_args); + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", + csid_hw->hw_intf->hw_idx, cmd_type); + rc = -EINVAL; + break; + } + + return rc; +} + +irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) +{ + struct cam_tfe_csid_hw *csid_hw; + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_reg_offset *csid_reg; + const struct cam_tfe_csid_csi2_rx_reg_offset *csi2_reg; + uint32_t irq_status[TFE_CSID_IRQ_REG_MAX]; + bool fatal_err_detected = false; + uint32_t sof_irq_debug_en = 0; + unsigned long flags; + uint32_t i, val; + + csid_hw = (struct cam_tfe_csid_hw *)data; + + if (!data) { + CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); + return IRQ_HANDLED; + } + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + csi2_reg = csid_reg->csi2_reg; + + /* read */ + irq_status[TFE_CSID_IRQ_REG_TOP] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_status_addr); + + irq_status[TFE_CSID_IRQ_REG_RX] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_status_addr); + + if (csid_hw->pxl_pipe_enable) + irq_status[TFE_CSID_IRQ_REG_IPP] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_status_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) + irq_status[i] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr); + + /* clear */ + cam_io_w_mb(irq_status[TFE_CSID_IRQ_REG_TOP], + soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_clear_addr); + + cam_io_w_mb(irq_status[TFE_CSID_IRQ_REG_RX], + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); + + if (csid_hw->pxl_pipe_enable) + cam_io_w_mb(irq_status[TFE_CSID_IRQ_REG_IPP], + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + cam_io_w_mb(irq_status[i], + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); + } + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_irq_cmd_addr); + + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + csid_hw->hw_intf->hw_idx, irq_status[TFE_CSID_IRQ_REG_TOP], + irq_status[TFE_CSID_IRQ_REG_RX], + irq_status[TFE_CSID_IRQ_REG_IPP], + irq_status[TFE_CSID_IRQ_REG_RDI0], + irq_status[TFE_CSID_IRQ_REG_RDI1], + irq_status[TFE_CSID_IRQ_REG_RDI2]); + + /* Software register reset complete*/ + if (irq_status[TFE_CSID_IRQ_REG_TOP]) + complete(&csid_hw->csid_top_complete); + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) + complete(&csid_hw->csid_csi2_complete); + + spin_lock_irqsave(&csid_hw->spin_lock, flags); + if (csid_hw->device_enabled == 1) { + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) { + fatal_err_detected = true; + } + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) { + fatal_err_detected = true; + } + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) { + fatal_err_detected = true; + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) { + fatal_err_detected = true; + } + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) + csid_hw->error_irq_count++; + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) + csid_hw->error_irq_count++; + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) + csid_hw->error_irq_count++; + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) + csid_hw->error_irq_count++; + + } + spin_unlock_irqrestore(&csid_hw->spin_lock, flags); + + if (csid_hw->error_irq_count > + CAM_TFE_CSID_MAX_IRQ_ERROR_COUNT) { + fatal_err_detected = true; + csid_hw->error_irq_count = 0; + } + + CAM_INFO(CAM_ISP, + "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + csid_hw->hw_intf->hw_idx, + irq_status[TFE_CSID_IRQ_REG_TOP], + irq_status[TFE_CSID_IRQ_REG_RX], + irq_status[TFE_CSID_IRQ_REG_IPP], + irq_status[TFE_CSID_IRQ_REG_RDI0], + irq_status[TFE_CSID_IRQ_REG_RDI1], + irq_status[TFE_CSID_IRQ_REG_RDI2]); + + if (fatal_err_detected) { + /* Reset the Rx CFG registers */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + } + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOT_IRQ) { + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL0_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL1_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL2_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL3_EOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + } + + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOT_IRQ) { + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL0_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL1_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL2_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PHY_DL3_SOT_CAPTURED", + csid_hw->hw_intf->hw_idx); + } + } + + if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) && + (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d LONG_PKT_CAPTURED", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d long packet VC :%d DT:%d WC:%d", + csid_hw->hw_intf->hw_idx, + (val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF)); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_1_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d long packet ECC :%d", + csid_hw->hw_intf->hw_idx, val); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_ftr_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d long pkt cal CRC:%d expected CRC:%d", + csid_hw->hw_intf->hw_idx, (val >> 16), (val & 0xFFFF)); + } + if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) && + (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d SHORT_PKT_CAPTURED", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_short_pkt_0_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d short pkt VC :%d DT:%d LC:%d", + csid_hw->hw_intf->hw_idx, + (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_short_pkt_1_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d short packet ECC :%d", + csid_hw->hw_intf->hw_idx, val); + } + + if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) && + (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PKT_HDR_CAPTURED", + csid_hw->hw_intf->hw_idx); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_cphy_pkt_hdr_addr); + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d cphy packet VC :%d DT:%d WC:%d", + csid_hw->hw_intf->hw_idx, + (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + } + + /* read the IPP errors */ + if (csid_hw->pxl_pipe_enable) { + /* IPP reset done bit */ + if (irq_status[TFE_CSID_IRQ_REG_IPP] & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "CSID IPP reset complete"); + complete(&csid_hw->csid_ipp_complete); + } + + if ((irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_INFO_INPUT_SOF) && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + if (csid_hw->sof_irq_triggered) + csid_hw->irq_debug_cnt++; + } + + if ((irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_INFO_INPUT_EOF) && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP EOF received", + csid_hw->hw_intf->hw_idx); + } + + if (irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_ERROR_FIFO_OVERFLOW) { + /* Stop IPP path immediately */ + cam_io_w_mb(CAM_TFE_CSID_HALT_IMMEDIATELY, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_ctrl_addr); + } + } + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + if (irq_status[i] & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { + CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i); + complete(&csid_hw->csid_rdin_complete[i]); + } + + if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID RDI:%d SOF received", i); + if (csid_hw->sof_irq_triggered) + csid_hw->irq_debug_cnt++; + } + + if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_EOF) && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID RDI:%d EOF received", i); + } + + if (irq_status[i] & TFE_CSID_PATH_ERROR_FIFO_OVERFLOW) { + /* Stop RDI path immediately */ + cam_io_w_mb(CAM_TFE_CSID_HALT_IMMEDIATELY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); + } + } + + if (csid_hw->irq_debug_cnt >= CAM_TFE_CSID_IRQ_SOF_DEBUG_CNT_MAX) { + cam_tfe_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); + csid_hw->irq_debug_cnt = 0; + } + + CAM_DBG(CAM_ISP, "IRQ Handling exit"); + return IRQ_HANDLED; +} + +int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, + uint32_t csid_idx) +{ + int rc = -EINVAL; + uint32_t i, val, clk_lvl; + struct cam_tfe_csid_path_cfg *path_data; + struct cam_hw_info *csid_hw_info; + struct cam_tfe_csid_hw *tfe_csid_hw = NULL; + const struct cam_tfe_csid_reg_offset *csid_reg; + + if (csid_idx >= CAM_TFE_CSID_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, "Invalid csid index:%d", csid_idx); + return rc; + } + + csid_hw_info = (struct cam_hw_info *) csid_hw_intf->hw_priv; + tfe_csid_hw = (struct cam_tfe_csid_hw *) csid_hw_info->core_info; + + tfe_csid_hw->hw_intf = csid_hw_intf; + tfe_csid_hw->hw_info = csid_hw_info; + csid_reg = tfe_csid_hw->csid_info->csid_reg; + + CAM_DBG(CAM_ISP, "type %d index %d", + tfe_csid_hw->hw_intf->hw_type, csid_idx); + + tfe_csid_hw->device_enabled = 0; + tfe_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&tfe_csid_hw->hw_info->hw_mutex); + spin_lock_init(&tfe_csid_hw->hw_info->hw_lock); + spin_lock_init(&tfe_csid_hw->spin_lock); + init_completion(&tfe_csid_hw->hw_info->hw_complete); + + init_completion(&tfe_csid_hw->csid_top_complete); + init_completion(&tfe_csid_hw->csid_csi2_complete); + init_completion(&tfe_csid_hw->csid_ipp_complete); + for (i = 0; i < CAM_TFE_CSID_RDI_MAX; i++) + init_completion(&tfe_csid_hw->csid_rdin_complete[i]); + + rc = cam_tfe_csid_init_soc_resources(&tfe_csid_hw->hw_info->soc_info, + cam_tfe_csid_irq, tfe_csid_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc", csid_idx); + goto err; + } + rc = cam_soc_util_get_clk_level(&tfe_csid_hw->hw_info->soc_info, + tfe_csid_hw->clk_rate, + tfe_csid_hw->hw_info->soc_info.src_clk_idx, &clk_lvl); + CAM_DBG(CAM_ISP, "CSID clock lvl %u", clk_lvl); + + rc = cam_tfe_csid_enable_soc_resources(&tfe_csid_hw->hw_info->soc_info, + clk_lvl); + if (rc) { + CAM_ERR(CAM_ISP, "CSID:%d Enable SOC failed", + tfe_csid_hw->hw_intf->hw_idx); + goto err; + } + + tfe_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_tfe_csid_get_hw_caps; + tfe_csid_hw->hw_intf->hw_ops.init = cam_tfe_csid_init_hw; + tfe_csid_hw->hw_intf->hw_ops.deinit = cam_tfe_csid_deinit_hw; + tfe_csid_hw->hw_intf->hw_ops.reset = cam_tfe_csid_reset; + tfe_csid_hw->hw_intf->hw_ops.reserve = cam_tfe_csid_reserve; + tfe_csid_hw->hw_intf->hw_ops.release = cam_tfe_csid_release; + tfe_csid_hw->hw_intf->hw_ops.start = cam_tfe_csid_start; + tfe_csid_hw->hw_intf->hw_ops.stop = cam_tfe_csid_stop; + tfe_csid_hw->hw_intf->hw_ops.read = cam_tfe_csid_read; + tfe_csid_hw->hw_intf->hw_ops.write = cam_tfe_csid_write; + tfe_csid_hw->hw_intf->hw_ops.process_cmd = cam_tfe_csid_process_cmd; + + /* reset the cid values */ + for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { + tfe_csid_hw->cid_res[i].vc = 0; + tfe_csid_hw->cid_res[i].dt = 0; + tfe_csid_hw->cid_res[i].cnt = 0; + } + + if (tfe_csid_hw->hw_intf->hw_idx == 2) { + val = cam_io_r_mb( + tfe_csid_hw->hw_info->soc_info.reg_map[1].mem_base + + csid_reg->cmn_reg->top_tfe2_fuse_reg); + if (val) { + CAM_INFO(CAM_ISP, "TFE 2 is not supported by hardware"); + rc = -EINVAL; + goto err; + } + } + + val = cam_io_r_mb( + tfe_csid_hw->hw_info->soc_info.reg_map[1].mem_base + + csid_reg->cmn_reg->top_tfe2_pix_pipe_fuse_reg); + + /* Initialize the IPP resources */ + if (!(val && (tfe_csid_hw->hw_intf->hw_idx == 2))) { + CAM_DBG(CAM_ISP, "initializing the pix path"); + + tfe_csid_hw->ipp_res.res_type = CAM_ISP_RESOURCE_PIX_PATH; + tfe_csid_hw->ipp_res.res_id = CAM_TFE_CSID_PATH_RES_IPP; + tfe_csid_hw->ipp_res.res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + tfe_csid_hw->ipp_res.hw_intf = tfe_csid_hw->hw_intf; + path_data = kzalloc(sizeof(*path_data), + GFP_KERNEL); + if (!path_data) { + rc = -ENOMEM; + goto err; + } + tfe_csid_hw->ipp_res.res_priv = path_data; + tfe_csid_hw->pxl_pipe_enable = 1; + } + + /* Initialize the RDI resource */ + for (i = 0; i < tfe_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + i++) { + /* res type is from RDI 0 to RDI2 */ + tfe_csid_hw->rdi_res[i].res_type = + CAM_ISP_RESOURCE_PIX_PATH; + tfe_csid_hw->rdi_res[i].res_id = i; + tfe_csid_hw->rdi_res[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + tfe_csid_hw->rdi_res[i].hw_intf = tfe_csid_hw->hw_intf; + + path_data = kzalloc(sizeof(*path_data), + GFP_KERNEL); + if (!path_data) { + rc = -ENOMEM; + goto err; + } + tfe_csid_hw->rdi_res[i].res_priv = path_data; + } + + tfe_csid_hw->csid_debug = 0; + tfe_csid_hw->error_irq_count = 0; + + rc = cam_tfe_csid_disable_soc_resources( + &tfe_csid_hw->hw_info->soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed", + tfe_csid_hw->hw_intf->hw_idx); + goto err; + } + + return 0; +err: + if (rc) { + kfree(tfe_csid_hw->ipp_res.res_priv); + for (i = 0; i < + tfe_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + i++) + kfree(tfe_csid_hw->rdi_res[i].res_priv); + } + + return rc; +} + + +int cam_tfe_csid_hw_deinit(struct cam_tfe_csid_hw *tfe_csid_hw) +{ + int rc = -EINVAL; + uint32_t i; + + if (!tfe_csid_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return rc; + } + + /* release the privdate data memory from resources */ + kfree(tfe_csid_hw->ipp_res.res_priv); + + for (i = 0; i < + tfe_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis; + i++) { + kfree(tfe_csid_hw->rdi_res[i].res_priv); + } + + cam_tfe_csid_deinit_soc_resources(&tfe_csid_hw->hw_info->soc_info); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h new file mode 100644 index 000000000000..1e23f2aa958c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -0,0 +1,412 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_HW_H_ +#define _CAM_TFE_CSID_HW_H_ + +#include "cam_hw.h" +#include "cam_tfe_csid_hw_intf.h" +#include "cam_tfe_csid_soc.h" + +#define CAM_TFE_CSID_CID_MAX 4 + +#define TFE_CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED BIT(0) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED BIT(1) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED BIT(2) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED BIT(3) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED BIT(4) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED BIT(5) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED BIT(6) +#define TFE_CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED BIT(7) +#define TFE_CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED BIT(8) +#define TFE_CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED BIT(9) +#define TFE_CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED BIT(10) +#define TFE_CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION BIT(11) +#define TFE_CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION BIT(12) +#define TFE_CSID_CSI2_RX_ERROR_CPHY_PH_CRC BIT(13) +#define TFE_CSID_CSI2_RX_WARNING_ECC BIT(14) +#define TFE_CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW BIT(15) +#define TFE_CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW BIT(16) +#define TFE_CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW BIT(17) +#define TFE_CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW BIT(18) +#define TFE_CSID_CSI2_RX_ERROR_CRC BIT(19) +#define TFE_CSID_CSI2_RX_ERROR_ECC BIT(20) +#define TFE_CSID_CSI2_RX_ERROR_MMAPPED_VC_DT BIT(21) +#define TFE_CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT BIT(22) +#define TFE_CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW BIT(23) +#define TFE_CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME BIT(24) +#define TFE_CSID_CSI2_RX_INFO_RST_DONE BIT(27) + +#define TFE_CSID_PATH_INFO_RST_DONE BIT(1) +#define TFE_CSID_PATH_ERROR_FIFO_OVERFLOW BIT(2) +#define TFE_CSID_PATH_INFO_INPUT_EOF BIT(9) +#define TFE_CSID_PATH_INFO_INPUT_EOL BIT(10) +#define TFE_CSID_PATH_INFO_INPUT_SOL BIT(11) +#define TFE_CSID_PATH_INFO_INPUT_SOF BIT(12) +#define TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION BIT(15) +#define TFE_CSID_PATH_IPP_OVERFLOW_IRQ BIT(16) +#define TFE_CSID_PATH_IPP_FRAME_DROP BIT(17) +#define TFE_CSID_PATH_RDI_FRAME_DROP BIT(16) +#define TFE_CSID_PATH_RDI_OVERFLOW_IRQ BIT(17) +#define TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION BIT(18) + +/* + * Debug values enable the corresponding interrupts and debug logs provide + * necessary information + */ +#define TFE_CSID_DEBUG_ENABLE_SOF_IRQ BIT(0) +#define TFE_CSID_DEBUG_ENABLE_EOF_IRQ BIT(1) +#define TFE_CSID_DEBUG_ENABLE_SOT_IRQ BIT(2) +#define TFE_CSID_DEBUG_ENABLE_EOT_IRQ BIT(3) +#define TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE BIT(4) +#define TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE BIT(5) +#define TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6) +#define TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7) +#define TFE_CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) + +/* enum cam_csid_path_halt_mode select the path halt mode control */ +enum cam_tfe_csid_path_halt_mode { + TFE_CSID_HALT_MODE_INTERNAL, + TFE_CSID_HALT_MODE_GLOBAL, + TFE_CSID_HALT_MODE_MASTER, + TFE_CSID_HALT_MODE_SLAVE, +}; + +/** + *enum cam_csid_path_timestamp_stb_sel - select the sof/eof strobes used to + * capture the timestamp + */ +enum cam_tfe_csid_path_timestamp_stb_sel { + TFE_CSID_TIMESTAMP_STB_PRE_HALT, + TFE_CSID_TIMESTAMP_STB_POST_HALT, + TFE_CSID_TIMESTAMP_STB_POST_IRQ, + TFE_CSID_TIMESTAMP_STB_MAX, +}; + +struct cam_tfe_csid_pxl_reg_offset { + /* Pxl path register offsets*/ + uint32_t csid_pxl_irq_status_addr; + uint32_t csid_pxl_irq_mask_addr; + uint32_t csid_pxl_irq_clear_addr; + uint32_t csid_pxl_irq_set_addr; + + uint32_t csid_pxl_cfg0_addr; + uint32_t csid_pxl_cfg1_addr; + uint32_t csid_pxl_ctrl_addr; + uint32_t csid_pxl_hcrop_addr; + uint32_t csid_pxl_vcrop_addr; + uint32_t csid_pxl_rst_strobes_addr; + uint32_t csid_pxl_status_addr; + uint32_t csid_pxl_misr_val_addr; + uint32_t csid_pxl_timestamp_curr0_sof_addr; + uint32_t csid_pxl_timestamp_curr1_sof_addr; + uint32_t csid_pxl_timestamp_perv0_sof_addr; + uint32_t csid_pxl_timestamp_perv1_sof_addr; + uint32_t csid_pxl_timestamp_curr0_eof_addr; + uint32_t csid_pxl_timestamp_curr1_eof_addr; + uint32_t csid_pxl_timestamp_perv0_eof_addr; + uint32_t csid_pxl_timestamp_perv1_eof_addr; + uint32_t csid_pxl_err_recovery_cfg0_addr; + uint32_t csid_pxl_err_recovery_cfg1_addr; + uint32_t csid_pxl_err_recovery_cfg2_addr; + + /* configuration */ + uint32_t pix_store_en_shift_val; + uint32_t early_eof_en_shift_val; + uint32_t halt_master_sel_shift; + uint32_t halt_mode_shift; + uint32_t halt_master_sel_master_val; + uint32_t halt_master_sel_slave_val; +}; + +struct cam_tfe_csid_rdi_reg_offset { + uint32_t csid_rdi_irq_status_addr; + uint32_t csid_rdi_irq_mask_addr; + uint32_t csid_rdi_irq_clear_addr; + uint32_t csid_rdi_irq_set_addr; + + /*RDI N register address */ + uint32_t csid_rdi_cfg0_addr; + uint32_t csid_rdi_cfg1_addr; + uint32_t csid_rdi_ctrl_addr; + uint32_t csid_rdi_rst_strobes_addr; + uint32_t csid_rdi_status_addr; + uint32_t csid_rdi_misr_val0_addr; + uint32_t csid_rdi_misr_val1_addr; + uint32_t csid_rdi_timestamp_curr0_sof_addr; + uint32_t csid_rdi_timestamp_curr1_sof_addr; + uint32_t csid_rdi_timestamp_prev0_sof_addr; + uint32_t csid_rdi_timestamp_prev1_sof_addr; + uint32_t csid_rdi_timestamp_curr0_eof_addr; + uint32_t csid_rdi_timestamp_curr1_eof_addr; + uint32_t csid_rdi_timestamp_prev0_eof_addr; + uint32_t csid_rdi_timestamp_prev1_eof_addr; + uint32_t csid_rdi_err_recovery_cfg0_addr; + uint32_t csid_rdi_err_recovery_cfg1_addr; + uint32_t csid_rdi_err_recovery_cfg2_addr; + uint32_t csid_rdi_byte_cntr_ping_addr; + uint32_t csid_rdi_byte_cntr_pong_addr; + + /* configuration */ + uint32_t packing_format; +}; + +struct cam_tfe_csid_csi2_rx_reg_offset { + uint32_t csid_csi2_rx_irq_status_addr; + uint32_t csid_csi2_rx_irq_mask_addr; + uint32_t csid_csi2_rx_irq_clear_addr; + uint32_t csid_csi2_rx_irq_set_addr; + uint32_t csid_csi2_rx_cfg0_addr; + uint32_t csid_csi2_rx_cfg1_addr; + uint32_t csid_csi2_rx_capture_ctrl_addr; + uint32_t csid_csi2_rx_rst_strobes_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; + uint32_t csid_csi2_rx_captured_short_pkt_1_addr; + uint32_t csid_csi2_rx_captured_long_pkt_0_addr; + uint32_t csid_csi2_rx_captured_long_pkt_1_addr; + uint32_t csid_csi2_rx_captured_long_pkt_ftr_addr; + uint32_t csid_csi2_rx_captured_cphy_pkt_hdr_addr; + uint32_t csid_csi2_rx_total_pkts_rcvd_addr; + uint32_t csid_csi2_rx_stats_ecc_addr; //no + uint32_t csid_csi2_rx_total_crc_err_addr; + + /*configurations */ + uint32_t csi2_rst_srb_all; + uint32_t csi2_rst_done_shift_val; + uint32_t csi2_irq_mask_all; + uint32_t csi2_misr_enable_shift_val; + uint32_t csi2_vc_mode_shift_val; + uint32_t csi2_capture_long_pkt_en_shift; + uint32_t csi2_capture_short_pkt_en_shift; + uint32_t csi2_capture_cphy_pkt_en_shift; + uint32_t csi2_capture_long_pkt_dt_shift; + uint32_t csi2_capture_long_pkt_vc_shift; + 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; + uint32_t csi2_rx_long_pkt_hdr_rst_stb_shift; + uint32_t csi2_rx_short_pkt_hdr_rst_stb_shift; +}; + +struct cam_tfe_csid_common_reg_offset { + /* MIPI CSID registers */ + uint32_t csid_hw_version_addr; + uint32_t csid_cfg0_addr; + uint32_t csid_ctrl_addr; + uint32_t csid_rst_strobes_addr; + + uint32_t csid_test_bus_ctrl_addr; + uint32_t csid_top_irq_status_addr; + uint32_t csid_top_irq_mask_addr; + uint32_t csid_top_irq_clear_addr; + uint32_t csid_top_irq_set_addr; + uint32_t csid_irq_cmd_addr; + + /*configurations */ + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; + uint32_t num_rdis; + uint32_t num_pix; + uint32_t csid_reg_rst_stb; + uint32_t csid_rst_stb; + uint32_t csid_rst_stb_sw_all; + uint32_t ipp_path_rst_stb_all; + uint32_t rdi_path_rst_stb_all; + uint32_t path_rst_done_shift_val; + uint32_t path_en_shift_val; + uint32_t dt_id_shift_val; + uint32_t vc_shift_val; + uint32_t dt_shift_val; + uint32_t fmt_shift_val; + uint32_t plain_fmt_shit_val; + uint32_t crop_v_en_shift_val; + uint32_t crop_h_en_shift_val; + uint32_t crop_shift; + uint32_t ipp_irq_mask_all; + uint32_t rdi_irq_mask_all; + uint32_t top_tfe2_pix_pipe_fuse_reg; + uint32_t top_tfe2_fuse_reg; +}; + +/** + * struct cam_tfe_csid_reg_offset- CSID instance register info + * + * @cmn_reg: csid common registers info + * @ipp_reg: ipp register offset information + * @ppp_reg: ppp register offset information + * @rdi_reg: rdi register offset information + * + */ +struct cam_tfe_csid_reg_offset { + const struct cam_tfe_csid_common_reg_offset *cmn_reg; + const struct cam_tfe_csid_csi2_rx_reg_offset *csi2_reg; + const struct cam_tfe_csid_pxl_reg_offset *ipp_reg; + const struct cam_tfe_csid_rdi_reg_offset *rdi_reg[CAM_TFE_CSID_RDI_MAX]; +}; + +/** + * struct cam_tfe_csid_hw_info- CSID HW info + * + * @csid_reg: csid register offsets + * @hw_dts_version: HW DTS version + * @csid_max_clk: maximim csid clock + * + */ +struct cam_tfe_csid_hw_info { + const struct cam_tfe_csid_reg_offset *csid_reg; + uint32_t hw_dts_version; + uint32_t csid_max_clk; +}; + +/** + * struct cam_tfe_csid_csi2_rx_cfg- csid csi2 rx configuration data + * @phy_sel: input resource type for sensor only + * @lane_type: lane type: c-phy or d-phy + * @lane_num : active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * + */ +struct cam_tfe_csid_csi2_rx_cfg { + uint32_t phy_sel; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; +}; + +/** + * struct cam_tfe_csid_cid_data- cid configuration private data + * + * @vc: Virtual channel + * @dt: Data type + * @cnt: Cid resource reference count. + * + */ +struct cam_tfe_csid_cid_data { + uint32_t vc; + uint32_t dt; + uint32_t cnt; +}; + +/** + * struct cam_tfe_csid_path_cfg- csid path configuration details. It is stored + * as private data for IPP/ RDI paths + * @vc : Virtual channel number + * @dt : Data type number + * @cid cid number, it is same as DT_ID number in HW + * @in_format: input decode format + * @out_format: output format + * @crop_enable: crop is enable or disabled, if enabled + * then remaining parameters are valid. + * @start_pixel: start pixel + * @end_pixel: end_pixel + * @width: width + * @start_line: start line + * @end_line: end_line + * @height: heigth + * @sync_mode: Applicable for IPP/RDI path reservation + * Reserving the path for master IPP or slave IPP + * master (set value 1), Slave ( set value 2) + * for RDI, set mode to none + * @master_idx: For Slave reservation, Give master TFE instance Index. + * Slave will synchronize with master Start and stop operations + * @clk_rate Clock rate + * @sensor_width Sensor width in pixel + * @sensor_height Sensor height in pixel + * @sensor_fps Sensor fps + * @sensor_hbi Sensor horizontal blanking interval + * @sensor_vbi Sensor vertical blanking interval + * + */ +struct cam_tfe_csid_path_cfg { + uint32_t vc; + uint32_t dt; + uint32_t cid; + uint32_t in_format; + uint32_t out_format; + bool crop_enable; + uint32_t start_pixel; + uint32_t end_pixel; + uint32_t width; + uint32_t start_line; + uint32_t end_line; + uint32_t height; + enum cam_isp_hw_sync_mode sync_mode; + uint32_t master_idx; + uint64_t clk_rate; + uint32_t sensor_width; + uint32_t sensor_height; + uint32_t sensor_fps; + uint32_t sensor_hbi; + uint32_t sensor_vbi; +}; + +/** + * struct cam_tfe_csid_hw- csid hw device resources data + * + * @hw_intf: contain the csid hw interface information + * @hw_info: csid hw device information + * @csid_info: csid hw specific information + * @in_res_id: csid in resource type + * @csi2_rx_cfg: csi2 rx decoder configuration for csid + * @csi2_rx_reserve_cnt: csi2 reservations count value + * @ipp_res: image pixel path resource + * @rdi_res: raw dump image path resources + * @cid_res: cid resources values + * @csid_top_reset_complete: csid top reset completion + * @csid_csi2_reset_complete: csi2 reset completion + * @csid_ipp_reset_complete: ipp reset completion + * @csid_ppp_complete: ppp reset completion + * @csid_rdin_reset_complete: rdi n completion + * @csid_debug: csid debug information to enable the SOT, EOT, + * SOF, EOF, measure etc in the csid hw + * @clk_rate Clock rate + * @sof_irq_triggered: Flag is set on receiving event to enable sof irq + * incase of SOF freeze. + * @irq_debug_cnt: Counter to track sof irq's when above flag is set. + * @error_irq_count Error IRQ count, if continuous error irq comes + * need to stop the CSID and mask interrupts. + * @device_enabled Device enabled will set once CSID powered on and + * initial configuration are done. + * @lock_state csid spin lock + * @event_cb: Callback function to hw mgr in case of hw events + * @event_cb_priv: Context data + * + */ +struct cam_tfe_csid_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_tfe_csid_hw_info *csid_info; + uint32_t in_res_id; + struct cam_tfe_csid_csi2_rx_cfg csi2_rx_cfg; + uint32_t csi2_reserve_cnt; + uint32_t pxl_pipe_enable; + struct cam_isp_resource_node ipp_res; + struct cam_isp_resource_node rdi_res[CAM_TFE_CSID_RDI_MAX]; + struct cam_tfe_csid_cid_data cid_res[CAM_TFE_CSID_CID_MAX]; + struct completion csid_top_complete; + struct completion csid_csi2_complete; + struct completion csid_ipp_complete; + struct completion csid_rdin_complete[CAM_TFE_CSID_RDI_MAX]; + uint64_t csid_debug; + uint64_t clk_rate; + bool sof_irq_triggered; + uint32_t irq_debug_cnt; + uint32_t error_irq_count; + uint32_t device_enabled; + spinlock_t spin_lock; + cam_hw_mgr_event_cb_func event_cb; + void *event_cb_priv; +}; + +int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, + uint32_t csid_idx); + +int cam_tfe_csid_hw_deinit(struct cam_tfe_csid_hw *tfe_csid_hw); + +#endif /* _CAM_TFE_CSID_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c new file mode 100644 index 000000000000..cb4a3b9c49d2 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include "cam_tfe_csid_core.h" +#include "cam_tfe_csid_dev.h" +#include "cam_tfe_csid_hw_intf.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_tfe_csid_hw_list[CAM_TFE_CSID_HW_NUM_MAX] = { + 0, 0, 0}; + +static char csid_dev_name[8]; + +int cam_tfe_csid_probe(struct platform_device *pdev) +{ + + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + struct cam_tfe_csid_hw *csid_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_tfe_csid_hw_info *csid_hw_data = NULL; + uint32_t csid_dev_idx; + int rc = 0; + + CAM_DBG(CAM_ISP, "probe called"); + + csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL); + if (!csid_hw_intf) { + rc = -ENOMEM; + goto err; + } + + csid_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!csid_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + csid_dev = kzalloc(sizeof(struct cam_tfe_csid_hw), GFP_KERNEL); + if (!csid_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + /* get tfe csid hw index */ + of_property_read_u32(pdev->dev.of_node, "cell-index", &csid_dev_idx); + /* get tfe csid hw information */ + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the tfe csid hw"); + rc = -EINVAL; + goto free_dev; + } + + memset(csid_dev_name, 0, sizeof(csid_dev_name)); + snprintf(csid_dev_name, sizeof(csid_dev_name), + "csid%1u", csid_dev_idx); + + csid_hw_intf->hw_idx = csid_dev_idx; + csid_hw_intf->hw_type = CAM_ISP_HW_TYPE_TFE_CSID; + csid_hw_intf->hw_priv = csid_hw_info; + + csid_hw_info->core_info = csid_dev; + csid_hw_info->soc_info.pdev = pdev; + csid_hw_info->soc_info.dev = &pdev->dev; + csid_hw_info->soc_info.dev_name = csid_dev_name; + csid_hw_info->soc_info.index = csid_dev_idx; + + csid_hw_data = (struct cam_tfe_csid_hw_info *)match_dev->data; + /* need to setup the pdev before call the tfe hw probe init */ + csid_dev->csid_info = csid_hw_data; + + rc = cam_tfe_csid_hw_probe_init(csid_hw_intf, csid_dev_idx); + if (rc) + goto free_dev; + + platform_set_drvdata(pdev, csid_dev); + CAM_DBG(CAM_ISP, "CSID:%d probe successful", + csid_hw_intf->hw_idx); + + if (csid_hw_intf->hw_idx < CAM_TFE_CSID_HW_NUM_MAX) + cam_tfe_csid_hw_list[csid_hw_intf->hw_idx] = csid_hw_intf; + else + goto free_dev; + + return 0; + +free_dev: + kfree(csid_dev); +free_hw_info: + kfree(csid_hw_info); +free_hw_intf: + kfree(csid_hw_intf); +err: + return rc; +} + +int cam_tfe_csid_remove(struct platform_device *pdev) +{ + struct cam_tfe_csid_hw *csid_dev = NULL; + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + + csid_dev = (struct cam_tfe_csid_hw *)platform_get_drvdata(pdev); + csid_hw_intf = csid_dev->hw_intf; + csid_hw_info = csid_dev->hw_info; + + CAM_DBG(CAM_ISP, "CSID:%d remove", + csid_dev->hw_intf->hw_idx); + + cam_tfe_csid_hw_deinit(csid_dev); + + /*release the csid device memory */ + kfree(csid_dev); + kfree(csid_hw_info); + kfree(csid_hw_intf); + return 0; +} + +int cam_tfe_csid_hw_init(struct cam_hw_intf **tfe_csid_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_tfe_csid_hw_list[hw_idx]) { + *tfe_csid_hw = cam_tfe_csid_hw_list[hw_idx]; + } else { + *tfe_csid_hw = NULL; + rc = -1; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.h new file mode 100644 index 000000000000..3193d64455a7 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_DEV_H_ +#define _CAM_TFE_CSID_DEV_H_ + +#include "cam_isp_hw.h" + +irqreturn_t cam_tfe_csid_irq(int irq_num, void *data); + +int cam_tfe_csid_probe(struct platform_device *pdev); +int cam_tfe_csid_remove(struct platform_device *pdev); + +#endif /*_CAM_TFE_CSID_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c new file mode 100644 index 000000000000..17f3fc7fb5b3 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ +#include +#include "cam_tfe_csid_soc.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + + +int cam_tfe_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t csid_irq_handler, void *irq_data) +{ + int rc = 0; + struct cam_cpas_register_params cpas_register_param; + struct cam_tfe_csid_soc_private *soc_private; + + soc_private = kzalloc(sizeof(struct cam_tfe_csid_soc_private), + GFP_KERNEL); + if (!soc_private) + return -ENOMEM; + + soc_info->soc_private = soc_private; + + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + /* Need to see if we want post process the clock list */ + rc = cam_soc_util_request_platform_resource(soc_info, csid_irq_handler, + irq_data); + + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Error Request platform resources failed rc=%d", rc); + goto free_soc_private; + } + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "csid", + CAM_HW_IDENTIFIER_LENGTH); + cpas_register_param.cell_index = soc_info->index; + cpas_register_param.dev = soc_info->dev; + 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 = cpas_register_param.client_handle; + } + + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); +free_soc_private: + kfree(soc_private); + + return rc; +} + +int cam_tfe_csid_deinit_soc_resources( + struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_tfe_csid_soc_private *soc_private; + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -ENODEV; + } + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + + return rc; +} + +int cam_tfe_csid_enable_soc_resources( + struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level) +{ + int rc = 0; + struct cam_tfe_csid_soc_private *soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + soc_private = soc_info->soc_private; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + CAM_DBG(CAM_ISP, "csid camnoc_bw:%lld mnoc_ab_bw:%lld mnoc_ib_bw:%lld ", + axi_vote.axi_path[0].camnoc_bw, + axi_vote.axi_path[0].mnoc_ab_bw, + axi_vote.axi_path[0].mnoc_ib_bw); + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_ISP, "Error CPAS start failed"); + rc = -EFAULT; + goto end; + } + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + clk_level, true); + if (rc) { + CAM_ERR(CAM_ISP, "enable platform failed"); + goto stop_cpas; + } + + return rc; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); +end: + return rc; +} + +int cam_tfe_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_tfe_csid_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) + CAM_ERR(CAM_ISP, "Disable platform failed"); + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Error CPAS stop failed rc=%d", rc); + return rc; + } + + return rc; +} + +int cam_tfe_csid_enable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_tfe_base_offset) +{ + int rc = 0; + struct cam_tfe_csid_soc_private *soc_private; + uint32_t cpass_tfe_force_clk_offset; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + + soc_private = soc_info->soc_private; + cpass_tfe_force_clk_offset = + cpas_tfe_base_offset + (0x4 * soc_info->index); + rc = cam_cpas_reg_write(soc_private->cpas_handle, CAM_CPAS_REG_CPASTOP, + cpass_tfe_force_clk_offset, 1, 1); + + if (rc) + CAM_ERR(CAM_ISP, "CPASS set TFE:%d Force clock On failed", + soc_info->index); + else + CAM_DBG(CAM_ISP, "CPASS set TFE:%d Force clock On", + soc_info->index); + + return rc; +} + +int cam_tfe_csid_disable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_tfe_base_offset) +{ + int rc = 0; + struct cam_tfe_csid_soc_private *soc_private; + uint32_t cpass_tfe_force_clk_offset; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + + soc_private = soc_info->soc_private; + cpass_tfe_force_clk_offset = + cpas_tfe_base_offset + (0x4 * soc_info->index); + rc = cam_cpas_reg_write(soc_private->cpas_handle, CAM_CPAS_REG_CPASTOP, + cpass_tfe_force_clk_offset, 1, 0); + + if (rc) + CAM_ERR(CAM_ISP, "CPASS set TFE:%d Force clock Off failed", + soc_info->index); + else + CAM_DBG(CAM_ISP, "CPASS set TFE:%d Force clock off", + soc_info->index); + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h new file mode 100644 index 000000000000..98f7a909ee8e --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_SOC_H_ +#define _CAM_TFE_CSID_SOC_H_ + +#include "cam_isp_hw.h" + +/* + * struct cam_csid_soc_private: + * + * @Brief: Private SOC data specific to CSID HW Driver + * + * @cpas_handle: Handle returned on registering with CPAS driver. + * This handle is used for all further interface + * with CPAS. + */ +struct cam_tfe_csid_soc_private { + uint32_t cpas_handle; +}; + +/** + * struct csid_device_soc_info - CSID SOC info object + * + * @csi_vdd_voltage: Csi vdd voltage value + * + */ +struct cam_tfe_csid_device_soc_info { + int csi_vdd_voltage; +}; + +/** + * cam_tfe_csid_init_soc_resources() + * + * @brief: Csid initialization function for the soc info + * + * @soc_info: Soc info structure pointer + * @csid_irq_handler: Irq handler function to be registered + * @irq_data: Irq data for the callback function + * + */ +int cam_tfe_csid_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t csid_irq_handler, void *irq_data); + + +/** + * cam_tfe_csid_deinit_soc_resources() + * + * @brief: Csid de initialization function for the soc info + * + * @soc_info: Soc info structure pointer + * + */ +int cam_tfe_csid_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + +/** + * cam_tfe_csid_enable_soc_resources() + * + * @brief: Csid soc resource enable function + * + * @soc_info: Soc info structure pointer + * @clk_lvl: Vote level to start with + * + */ +int cam_tfe_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info, + uint32_t clk_lvl); + +/** + * cam_tfe_csid_disable_soc_resources() + * + * @brief: Csid soc resource disable function + * + * @soc_info: Soc info structure pointer + * + */ +int cam_tfe_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +/** + * cam_tfe_csid_enable_tfe_force_clock() + * + * @brief: If csid testgen used for dual isp case, before + * starting csid test gen, enable tfe force clock on + * through cpas + * + * @soc_info: Soc info structure pointer + * @cpas_tfe_base_offset: Cpas tfe force clock base reg offset value + * + */ +int cam_tfe_csid_enable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_tfe_base_offset); + +/** + * cam_tfe_csid_disable_tfe_force_clock_on() + * + * @brief: Disable the TFE force clock on after dual ISP + * CSID test gen stop + * + * @soc_info: Soc info structure pointer + * @cpas_tfe_base_offset: Cpas tfe force clock base reg offset value + * + */ +int cam_tfe_csid_disable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info, + uint32_t cpas_tfe_base_offset); + +/** + * cam_tfe_csid_get_vote_level() + * + * @brief: Get the vote level from clock rate + * + * @soc_info: Soc info structure pointer + * @clock_rate Clock rate + * + */ +uint32_t cam_tfe_csid_get_vote_level(struct cam_hw_soc_info *soc_info, + uint64_t clock_rate); + +#endif /* _CAM_TFE_CSID_SOC_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile new file mode 100644 index 000000000000..777b5e7fda6a --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_soc.o cam_tfe_dev.o cam_tfe_core.o cam_tfe_bus.o cam_tfe.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c new file mode 100644 index 000000000000..377b2da2ce33 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_tfe530.h" +#include "cam_tfe_hw_intf.h" +#include "cam_tfe_core.h" +#include "cam_tfe_dev.h" + +static const struct of_device_id cam_tfe_dt_match[] = { + { + .compatible = "qcom,tfe530", + .data = &cam_tfe530, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_tfe_dt_match); + +static struct platform_driver cam_tfe_driver = { + .probe = cam_tfe_probe, + .remove = cam_tfe_remove, + .driver = { + .name = "cam_tfe", + .of_match_table = cam_tfe_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_tfe_init_module(void) +{ + return platform_driver_register(&cam_tfe_driver); +} + +void cam_tfe_exit_module(void) +{ + platform_driver_unregister(&cam_tfe_driver); +} + +MODULE_DESCRIPTION("CAM TFE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h new file mode 100644 index 000000000000..229f7563070c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -0,0 +1,813 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_TFE530_H_ +#define _CAM_TFE530_H_ +#include "cam_tfe_core.h" +#include "cam_tfe_bus.h" + + +static struct cam_tfe_top_reg_offset_common tfe530_top_commong_reg = { + .hw_version = 0x00001000, + .hw_capability = 0x00001004, + .lens_feature = 0x00001008, + .stats_feature = 0x0000100C, + .zoom_feature = 0x00001010, + .global_reset_cmd = 0x00001014, + .core_cgc_ctrl = 0x00001018, + .ahb_cgc_ctrl = 0x0000101C, + .core_cfg_0 = 0x00001024, + .core_cfg_1 = 0x00001028, + .reg_update_cmd = 0x0000102C, + .diag_config = 0x00001060, + .diag_sensor_status_0 = 0x00001064, + .diag_sensor_status_1 = 0x00001068, + .diag_sensor_frame_cnt_status = 0x0000106C, + .violation_status = 0x00001070, + .stats_throttle_cnt_cfg_0 = 0x00001074, + .stats_throttle_cnt_cfg_1 = 0x00001078, + .debug_0 = 0x000010A0, + .debug_1 = 0x000010A4, + .debug_2 = 0x000010A8, + .debug_3 = 0x000010AC, + .debug_cfg = 0x000010DC, + .perf_cnt_cfg = 0x000010E0, + .perf_pixel_count = 0x000010E4, + .perf_line_count = 0x000010E8, + .perf_stall_count = 0x000010EC, + .perf_always_count = 0x000010F0, + .perf_count_status = 0x000010F4, +}; + +static struct cam_tfe_camif_reg tfe530_camif_reg = { + .hw_version = 0x00001200, + .hw_status = 0x00001204, + .module_cfg = 0x00001260, + .pdaf_raw_crop_width_cfg = 0x00001268, + .pdaf_raw_crop_height_cfg = 0x0000126C, + .line_skip_pattern = 0x00001270, + .pixel_skip_pattern = 0x00001274, + .period_cfg = 0x00001278, + .irq_subsample_pattern = 0x0000127C, + .epoch_irq_cfg = 0x00001280, + .debug_1 = 0x000013F0, + .debug_0 = 0x000013F4, + .test_bus_ctrl = 0x000013F8, + .spare = 0x000013F8, + .reg_update_cmd = 0x0000102C, +}; + +static struct cam_tfe_camif_reg_data tfe530_camif_reg_data = { + .extern_reg_update_mask = 0x00000001, + .dual_tfe_pix_en_shift = 0x00000001, + .extern_reg_update_shift = 0x0, + .camif_pd_rdi2_src_sel_shift = 0x2, + .dual_tfe_sync_sel_shift = 18, + .pixel_pattern_shift = 24, + .pixel_pattern_mask = 0x7000000, + .module_enable_shift = 0, + .pix_out_enable_shift = 8, + .pdaf_output_enable_shift = 9, + .dsp_mode_shift = 0, + .dsp_mode_mask = 0, + .dsp_en_shift = 0, + .dsp_en_mask = 0, + .reg_update_cmd_data = 0x1, + .epoch_line_cfg = 0x00140014, + .sof_irq_mask = 0x00000001, + .epoch0_irq_mask = 0x00000004, + .epoch1_irq_mask = 0x00000008, + .eof_irq_mask = 0x00000002, + .reg_update_irq_mask = 0x00000001, + .error_irq_mask0 = 0x00010100, + .error_irq_mask2 = 0x00000023, + .subscribe_irq_mask = { + 0x00000000, + 0x00000007, + 0x00000000, + }, + .enable_diagnostic_hw = 0x1, + .perf_cnt_start_cmd_shift = 0, + .perf_cnt_continuous_shift = 2, + .perf_client_sel_shift = 8, + .perf_window_start_shift = 16, + .perf_window_end_shift = 20, +}; + +static struct cam_tfe_rdi_reg tfe530_rdi0_reg = { + .rdi_hw_version = 0x00001400, + .rdi_hw_status = 0x00001404, + .rdi_module_config = 0x00001460, + .rdi_skip_period = 0x00001468, + .rdi_irq_subsample_pattern = 0x0000146C, + .rdi_epoch_irq = 0x00001470, + .rdi_debug_1 = 0x000015F0, + .rdi_debug_0 = 0x000015F4, + .rdi_test_bus_ctrl = 0x000015F8, + .rdi_spare = 0x000015FC, + .reg_update_cmd = 0x0000102C, +}; + +static struct cam_tfe_rdi_reg_data tfe530_rdi0_reg_data = { + .reg_update_cmd_data = 0x2, + .epoch_line_cfg = 0x00140014, + .pixel_pattern_shift = 24, + .pixel_pattern_mask = 0x07000000, + .rdi_out_enable_shift = 0, + + .sof_irq_mask = 0x00000010, + .epoch0_irq_mask = 0x00000040, + .epoch1_irq_mask = 0x00000080, + .eof_irq_mask = 0x00000020, + .error_irq_mask0 = 0x00020200, + .error_irq_mask2 = 0x00000004, + .subscribe_irq_mask = { + 0x00000000, + 0x00000030, + 0x00000000, + }, + .enable_diagnostic_hw = 0x1, +}; + +static struct cam_tfe_rdi_reg tfe530_rdi1_reg = { + .rdi_hw_version = 0x00001600, + .rdi_hw_status = 0x00001604, + .rdi_module_config = 0x00001660, + .rdi_skip_period = 0x00001668, + .rdi_irq_subsample_pattern = 0x0000166C, + .rdi_epoch_irq = 0x00001670, + .rdi_debug_1 = 0x000017F0, + .rdi_debug_0 = 0x000017F4, + .rdi_test_bus_ctrl = 0x000017F8, + .rdi_spare = 0x000017FC, + .reg_update_cmd = 0x0000102C, +}; + +static struct cam_tfe_rdi_reg_data tfe530_rdi1_reg_data = { + .reg_update_cmd_data = 0x4, + .epoch_line_cfg = 0x00140014, + .pixel_pattern_shift = 24, + .pixel_pattern_mask = 0x07000000, + .rdi_out_enable_shift = 0, + + .sof_irq_mask = 0x00000100, + .epoch0_irq_mask = 0x00000400, + .epoch1_irq_mask = 0x00000800, + .eof_irq_mask = 0x00000200, + .error_irq_mask0 = 0x00040400, + .error_irq_mask2 = 0x00000008, + .subscribe_irq_mask = { + 0x00000000, + 0x00000300, + 0x00000000, + }, + .enable_diagnostic_hw = 0x1, +}; + +static struct cam_tfe_rdi_reg tfe530_rdi2_reg = { + .rdi_hw_version = 0x00001800, + .rdi_hw_status = 0x00001804, + .rdi_module_config = 0x00001860, + .rdi_skip_period = 0x00001868, + .rdi_irq_subsample_pattern = 0x0000186C, + .rdi_epoch_irq = 0x00001870, + .rdi_debug_1 = 0x000019F0, + .rdi_debug_0 = 0x000019F4, + .rdi_test_bus_ctrl = 0x000019F8, + .rdi_spare = 0x000019FC, + .reg_update_cmd = 0x0000102C, +}; + +static struct cam_tfe_rdi_reg_data tfe530_rdi2_reg_data = { + .reg_update_cmd_data = 0x8, + .epoch_line_cfg = 0x00140014, + .pixel_pattern_shift = 24, + .pixel_pattern_mask = 0x07000000, + .rdi_out_enable_shift = 0, + + .sof_irq_mask = 0x00001000, + .epoch0_irq_mask = 0x00004000, + .epoch1_irq_mask = 0x00008000, + .eof_irq_mask = 0x00002000, + .error_irq_mask0 = 0x00080800, + .error_irq_mask2 = 0x00000004, + .subscribe_irq_mask = { + 0x00000000, + 0x00003000, + 0x00000000, + }, + .enable_diagnostic_hw = 0x1, +}; + +static struct cam_tfe_top_hw_info tfe530_top_hw_info = { + .common_reg = &tfe530_top_commong_reg, + .camif_hw_info = { + .camif_reg = &tfe530_camif_reg, + .reg_data = &tfe530_camif_reg_data, + }, + .rdi_hw_info = { + { + .rdi_reg = &tfe530_rdi0_reg, + .reg_data = &tfe530_rdi0_reg_data, + }, + { + .rdi_reg = &tfe530_rdi1_reg, + .reg_data = &tfe530_rdi1_reg_data, + }, + { + .rdi_reg = &tfe530_rdi2_reg, + .reg_data = &tfe530_rdi2_reg_data, + }, + }, + .in_port = { + CAM_TFE_CAMIF_VER_1_0, + CAM_TFE_RDI_VER_1_0, + CAM_TFE_RDI_VER_1_0, + CAM_TFE_RDI_VER_1_0 + }, + .reg_dump_data = { + .num_reg_dump_entries = 19, + .num_lut_dump_entries = 0, + .bus_start_addr = 0x2000, + .bus_write_top_end_addr = 0x2120, + .bus_client_start_addr = 0x2200, + .bus_client_offset = 0x100, + .num_bus_clients = 10, + .reg_entry = { + { + .start_offset = 0x1000, + .end_offset = 0x10F4, + }, + { + .start_offset = 0x1260, + .end_offset = 0x1280, + }, + { + .start_offset = 0x13F0, + .end_offset = 0x13FC, + }, + { + .start_offset = 0x1460, + .end_offset = 0x1470, + }, + { + .start_offset = 0x15F0, + .end_offset = 0x15FC, + }, + { + .start_offset = 0x1660, + .end_offset = 0x1670, + }, + { + .start_offset = 0x17F0, + .end_offset = 0x17FC, + }, + { + .start_offset = 0x1860, + .end_offset = 0x1870, + }, + { + .start_offset = 0x19F0, + .end_offset = 0x19FC, + }, + { + .start_offset = 0x2660, + .end_offset = 0x2694, + }, + { + .start_offset = 0x2860, + .end_offset = 0x2884, + }, + { + .start_offset = 0x2A60, + .end_offset = 0X2B34, + }, + { + .start_offset = 0x2C60, + .end_offset = 0X2C80, + }, + { + .start_offset = 0x2E60, + .end_offset = 0X2E7C, + }, + { + .start_offset = 0x3060, + .end_offset = 0X3110, + }, + { + .start_offset = 0x3260, + .end_offset = 0X3278, + }, + { + .start_offset = 0x3460, + .end_offset = 0X3478, + }, + { + .start_offset = 0x3660, + .end_offset = 0X3684, + }, + { + .start_offset = 0x3860, + .end_offset = 0X3884, + }, + }, + .lut_entry = { + { + .lut_word_size = 1, + .lut_bank_sel = 0x40, + .lut_addr_size = 180, + .dmi_reg_offset = 0x2800, + }, + { + .lut_word_size = 1, + .lut_bank_sel = 0x41, + .lut_addr_size = 180, + .dmi_reg_offset = 0x3000, + }, + }, + }, +}; + +static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { + .common_reg = { + .hw_version = 0x00001A00, + .cgc_ovd = 0x00001A08, + .comp_cfg_0 = 0x00001A0C, + .comp_cfg_1 = 0x00001A10, + .frameheader_cfg = { + 0x00001A34, + 0x00001A38, + 0x00001A3C, + 0x00001A40, + }, + .pwr_iso_cfg = 0x00001A5C, + .overflow_status_clear = 0x00001A60, + .ccif_violation_status = 0x00001A64, + .overflow_status = 0x00001A68, + .image_size_violation_status = 0x00001A70, + .perf_count_cfg = { + 0x00001A74, + 0x00001A78, + 0x00001A7C, + 0x00001A80, + 0x00001A84, + 0x00001A88, + 0x00001A8C, + 0x00001A90, + }, + .perf_count_val = { + 0x00001A94, + 0x00001A98, + 0x00001A9C, + 0x00001AA0, + 0x00001AA4, + 0x00001AA8, + 0x00001AAC, + 0x00001AB0, + }, + .perf_count_status = 0x00001AB4, + .debug_status_top_cfg = 0x00001AD4, + .debug_status_top = 0x00001AD8, + .test_bus_ctrl = 0x00001ADC, + .irq_mask = { + 0x00001A18, + 0x00001A1C, + }, + .irq_clear = { + 0x00001A20, + 0x00001A24, + }, + .irq_status = { + 0x00001A28, + 0x00001A2C, + }, + .irq_cmd = 0x00001A30, + }, + .num_client = CAM_TFE_BUS_MAX_CLIENTS, + .bus_client_reg = { + /* BUS Client 0 BAYER */ + { + .cfg = 0x00001C00, + .image_addr = 0x00001C04, + .frame_incr = 0x00001C08, + .image_cfg_0 = 0x00001C0C, + .image_cfg_1 = 0x00001C10, + .image_cfg_2 = 0x00001C14, + .packer_cfg = 0x00001C18, + .bw_limit = 0x00001C1C, + .frame_header_addr = 0x00001C20, + .frame_header_incr = 0x00001C24, + .frame_header_cfg = 0x00001C28, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00001C30, + .irq_subsample_pattern = 0x00001C34, + .framedrop_period = 0x00001C38, + .framedrop_pattern = 0x00001C3C, + .addr_status_0 = 0x00001C68, + .addr_status_1 = 0x00001C6C, + .addr_status_2 = 0x00001C70, + .addr_status_3 = 0x00001C74, + .debug_status_cfg = 0x00001C78, + .debug_status_0 = 0x00001C7C, + .debug_status_1 = 0x00001C80, + .comp_group = CAM_TFE_BUS_COMP_GRP_0, + }, + /* BUS Client 1 IDEAL RAW*/ + { + .cfg = 0x00001D00, + .image_addr = 0x00001D04, + .frame_incr = 0x00001D08, + .image_cfg_0 = 0x00001D0C, + .image_cfg_1 = 0x00001D10, + .image_cfg_2 = 0x00001D14, + .packer_cfg = 0x00001D18, + .bw_limit = 0x00001D1C, + .frame_header_addr = 0x00001D20, + .frame_header_incr = 0x00001D24, + .frame_header_cfg = 0x00001D28, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00001D30, + .irq_subsample_pattern = 0x00001D34, + .framedrop_period = 0x00001D38, + .framedrop_pattern = 0x00001D3C, + .addr_status_0 = 0x00001D68, + .addr_status_1 = 0x00001D6C, + .addr_status_2 = 0x00001D70, + .addr_status_3 = 0x00001D74, + .debug_status_cfg = 0x00001D78, + .debug_status_0 = 0x00001D7C, + .debug_status_1 = 0x00001D80, + .comp_group = CAM_TFE_BUS_COMP_GRP_1, + }, + /* BUS Client 2 Stats BE Tintless */ + { + .cfg = 0x00001E00, + .image_addr = 0x00001E04, + .frame_incr = 0x00001E08, + .image_cfg_0 = 0x00001E0C, + .image_cfg_1 = 0x00001E10, + .image_cfg_2 = 0x00001E14, + .packer_cfg = 0x00001E18, + .bw_limit = 0x00001E1C, + .frame_header_addr = 0x00001E20, + .frame_header_incr = 0x00001E24, + .frame_header_cfg = 0x00001E28, + .line_done_cfg = 0x00001E00, + .irq_subsample_period = 0x00001E30, + .irq_subsample_pattern = 0x00000E34, + .framedrop_period = 0x00001E38, + .framedrop_pattern = 0x00001E3C, + .addr_status_0 = 0x00001E68, + .addr_status_1 = 0x00001E6C, + .addr_status_2 = 0x00001E70, + .addr_status_3 = 0x00001E74, + .debug_status_cfg = 0x00001E78, + .debug_status_0 = 0x00001E7C, + .debug_status_1 = 0x00001E80, + .comp_group = CAM_TFE_BUS_COMP_GRP_2, + }, + /* BUS Client 3 Stats Bhist */ + { + .cfg = 0x00001F00, + .image_addr = 0x00001F04, + .frame_incr = 0x00001F08, + .image_cfg_0 = 0x00001F0C, + .image_cfg_1 = 0x00001F10, + .image_cfg_2 = 0x00001F14, + .packer_cfg = 0x00001F18, + .bw_limit = 0x00001F1C, + .frame_header_addr = 0x00001F20, + .frame_header_incr = 0x00001F24, + .frame_header_cfg = 0x00001F28, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00001F30, + .irq_subsample_pattern = 0x00001F34, + .framedrop_period = 0x00001F38, + .framedrop_pattern = 0x00001F3C, + .addr_status_0 = 0x00001F68, + .addr_status_1 = 0x00001F6C, + .addr_status_2 = 0x00001F70, + .addr_status_3 = 0x00001F74, + .debug_status_cfg = 0x00001F78, + .debug_status_0 = 0x00001F7C, + .debug_status_1 = 0x00001F80, + .comp_group = CAM_TFE_BUS_COMP_GRP_2, + }, + /* BUS Client 4 Stats AWB BG */ + { + .cfg = 0x00002000, + .image_addr = 0x00002004, + .frame_incr = 0x00002008, + .image_cfg_0 = 0x0000200C, + .image_cfg_1 = 0x00002010, + .image_cfg_2 = 0x00002014, + .packer_cfg = 0x00002018, + .bw_limit = 0x0000201C, + .frame_header_addr = 0x00002020, + .frame_header_incr = 0x00002024, + .frame_header_cfg = 0x00002028, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00002030, + .irq_subsample_pattern = 0x00002034, + .framedrop_period = 0x00002038, + .framedrop_pattern = 0x0000203C, + .addr_status_0 = 0x00002068, + .addr_status_1 = 0x0000206C, + .addr_status_2 = 0x00002070, + .addr_status_3 = 0x00002074, + .debug_status_cfg = 0x00002078, + .debug_status_0 = 0x0000207C, + .debug_status_1 = 0x00002080, + .comp_group = CAM_TFE_BUS_COMP_GRP_3, + }, + /* BUS Client 5 Stats AEC BG */ + { + .cfg = 0x00002100, + .image_addr = 0x00002104, + .frame_incr = 0x00002108, + .image_cfg_0 = 0x0000210C, + .image_cfg_1 = 0x00002110, + .image_cfg_2 = 0x00002114, + .packer_cfg = 0x00002118, + .bw_limit = 0x0000211C, + .frame_header_addr = 0x00002120, + .frame_header_incr = 0x00002124, + .frame_header_cfg = 0x00002128, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00002130, + .irq_subsample_pattern = 0x00002134, + .framedrop_period = 0x00002138, + .framedrop_pattern = 0x0000213C, + .addr_status_0 = 0x00002168, + .addr_status_1 = 0x0000216C, + .addr_status_2 = 0x00002170, + .addr_status_3 = 0x00002174, + .debug_status_cfg = 0x00002178, + .debug_status_0 = 0x0000217C, + .debug_status_1 = 0x00002180, + .comp_group = CAM_TFE_BUS_COMP_GRP_3, + }, + /* BUS Client 6 Stats BAF */ + { + .cfg = 0x00002200, + .image_addr = 0x00002204, + .frame_incr = 0x00002208, + .image_cfg_0 = 0x0000220C, + .image_cfg_1 = 0x00002210, + .image_cfg_2 = 0x00002214, + .packer_cfg = 0x00002218, + .bw_limit = 0x0000221C, + .frame_header_addr = 0x00002220, + .frame_header_incr = 0x00002224, + .frame_header_cfg = 0x00002228, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00002230, + .irq_subsample_pattern = 0x00002234, + .framedrop_period = 0x00002238, + .framedrop_pattern = 0x0000223C, + .addr_status_0 = 0x00002268, + .addr_status_1 = 0x0000226C, + .addr_status_2 = 0x00002270, + .addr_status_3 = 0x00002274, + .debug_status_cfg = 0x00002278, + .debug_status_0 = 0x0000227C, + .debug_status_1 = 0x00002280, + .comp_group = CAM_TFE_BUS_COMP_GRP_4, + }, + /* BUS Client 7 RDI0 */ + { + .cfg = 0x00002300, + .image_addr = 0x00002304, + .frame_incr = 0x00002308, + .image_cfg_0 = 0x0000230C, + .image_cfg_1 = 0x00002310, + .image_cfg_2 = 0x00002314, + .packer_cfg = 0x00002318, + .bw_limit = 0x0000231C, + .frame_header_addr = 0x00002320, + .frame_header_incr = 0x00002324, + .frame_header_cfg = 0x00002328, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00002330, + .irq_subsample_pattern = 0x00002334, + .framedrop_period = 0x00002338, + .framedrop_pattern = 0x0000233C, + .addr_status_0 = 0x00002368, + .addr_status_1 = 0x0000236C, + .addr_status_2 = 0x00002370, + .addr_status_3 = 0x00002374, + .debug_status_cfg = 0x00002378, + .debug_status_0 = 0x0000237C, + .debug_status_1 = 0x00002380, + .comp_group = CAM_TFE_BUS_COMP_GRP_5, + }, + /* BUS Client 8 RDI1 */ + { + .cfg = 0x00002400, + .image_addr = 0x00002404, + .frame_incr = 0x00002408, + .image_cfg_0 = 0x0000240C, + .image_cfg_1 = 0x00002410, + .image_cfg_2 = 0x00002414, + .packer_cfg = 0x00002418, + .bw_limit = 0x0000241C, + .frame_header_addr = 0x00002420, + .frame_header_incr = 0x00002424, + .frame_header_cfg = 0x00002428, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00002430, + .irq_subsample_pattern = 0x00002434, + .framedrop_period = 0x00002438, + .framedrop_pattern = 0x0000243C, + .addr_status_0 = 0x00002468, + .addr_status_1 = 0x0000246C, + .addr_status_2 = 0x00002470, + .addr_status_3 = 0x00002474, + .debug_status_cfg = 0x00002478, + .debug_status_0 = 0x0000247C, + .debug_status_1 = 0x00002480, + .comp_group = CAM_TFE_BUS_COMP_GRP_6, + }, + /* BUS Client 9 PDAF/RDI2*/ + { + .cfg = 0x00002500, + .image_addr = 0x00002504, + .frame_incr = 0x00002508, + .image_cfg_0 = 0x0000250C, + .image_cfg_1 = 0x00002510, + .image_cfg_2 = 0x00002514, + .packer_cfg = 0x00002518, + .bw_limit = 0x0000251C, + .frame_header_addr = 0x00002520, + .frame_header_incr = 0x00002524, + .frame_header_cfg = 0x00002528, + .line_done_cfg = 0x00000000, + .irq_subsample_period = 0x00002530, + .irq_subsample_pattern = 0x00002534, + .framedrop_period = 0x00002538, + .framedrop_pattern = 0x0000253C, + .addr_status_0 = 0x00002568, + .addr_status_1 = 0x0000256C, + .addr_status_2 = 0x00002570, + .addr_status_3 = 0x00002574, + .debug_status_cfg = 0x00002578, + .debug_status_0 = 0x0000257C, + .debug_status_1 = 0x00002580, + .comp_group = CAM_TFE_BUS_COMP_GRP_7, + }, + }, + .num_out = CAM_TFE_BUS_TFE_OUT_MAX, + .tfe_out_hw_info = { + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI0, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_5, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_1, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI1, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_6, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_2, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI2, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_7, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_3, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_FULL, + .max_width = 4096, + .max_height = 4096, + .composite_group = CAM_TFE_BUS_COMP_GRP_0, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RAW_DUMP, + .max_width = 4096, + .max_height = 4096, + .composite_group = CAM_TFE_BUS_COMP_GRP_1, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_PDAF, + .max_width = 4096, + .max_height = 4096, + .composite_group = CAM_TFE_BUS_COMP_GRP_7, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_3, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_3, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_2, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_TL_BG, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_2, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_3, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + { + .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_BF, + .max_width = -1, + .max_height = -1, + .composite_group = CAM_TFE_BUS_COMP_GRP_4, + .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + }, + }, + .comp_done_shift = 8, + .top_bus_wr_irq_shift = 1, + .comp_buf_done_mask = 0xFF00, + .comp_rup_done_mask = 0xF, + .bus_irq_error_mask = { + 0xD0000000, + 0x00000000, + }, +}; + +struct cam_tfe_hw_info cam_tfe530 = { + .top_irq_mask = { + 0x00001034, + 0x00001038, + 0x0000103C, + }, + .top_irq_clear = { + 0x00001040, + 0x00001044, + 0x00001048, + }, + .top_irq_status = { + 0x0000104C, + 0x00001050, + 0x00001054, + }, + .top_irq_cmd = 0x00001030, + .global_clear_bitmask = 0x00000001, + + .bus_irq_mask = { + 0x00001A18, + 0x00001A1C, + }, + .bus_irq_clear = { + 0x00001A20, + 0x00001A24, + }, + .bus_irq_status = { + 0x00001A28, + 0x00001A2C, + }, + .bus_irq_cmd = 0x00001A30, + .bus_violation_reg = 0x00001A64, + .bus_overflow_reg = 0x00001A68, + .bus_image_size_vilation_reg = 0x1A70, + .bus_overflow_clear_cmd = 0x1A60, + .debug_status_top = 0x1AD8, + + .reset_irq_mask = { + 0x00000001, + 0x00000000, + 0x00000000, + }, + .error_irq_mask = { + 0x000F0F00, + 0x00000000, + 0x0000003F, + }, + .bus_reg_irq_mask = { + 0x00000002, + 0x00000000, + 0x00000000, + }, + + .bus_version = CAM_TFE_BUS_1_0, + .bus_hw_info = &tfe530_bus_hw_info, + + .top_version = CAM_TFE_TOP_1_0, + .top_hw_info = &tfe530_top_hw_info, +}; + +#endif /* _CAM_TFE530_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c new file mode 100644 index 000000000000..fc4e465d03cf --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -0,0 +1,2149 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_cdm_util.h" +#include "cam_hw_intf.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_tfe_hw_intf.h" +#include "cam_irq_controller.h" +#include "cam_tasklet_util.h" +#include "cam_tfe_bus.h" +#include "cam_tfe_irq.h" +#include "cam_tfe_soc.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + + +static const char drv_name[] = "tfe_bus"; + +#define CAM_TFE_BUS_IRQ_REG0 0 +#define CAM_TFE_BUS_IRQ_REG1 1 + +#define CAM_TFE_BUS_PAYLOAD_MAX 256 + +#define CAM_TFE_RDI_BUS_DEFAULT_WIDTH 0xFFFF +#define CAM_TFE_RDI_BUS_DEFAULT_STRIDE 0xFFFF + +#define CAM_TFE_MAX_OUT_RES_PER_COMP_GRP 2 + +#define MAX_BUF_UPDATE_REG_NUM \ + (sizeof(struct cam_tfe_bus_reg_offset_bus_client) / 4) +#define MAX_REG_VAL_PAIR_SIZE \ + (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) + +enum cam_tfe_bus_packer_format { + PACKER_FMT_PLAIN_128, + PACKER_FMT_PLAIN_8, + PACKER_FMT_PLAIN_8_ODD_EVEN, + PACKER_FMT_PLAIN_8_LSB_MSB_10, + PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN, + PACKER_FMT_PLAIN_16_10BPP, + PACKER_FMT_PLAIN_16_12BPP, + PACKER_FMT_PLAIN_16_14BPP, + PACKER_FMT_PLAIN_16_16BPP, + PACKER_FMT_PLAIN_32, + PACKER_FMT_PLAIN_64, + PACKER_FMT_TP_10, + PACKET_FMT_MIPI10, + PACKET_FMT_MIPI12, + PACKER_FMT_MAX, +}; + +struct cam_tfe_bus_common_data { + uint32_t core_index; + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + void *tfe_core_data; + struct cam_tfe_bus_reg_offset_common *common_reg; + uint32_t io_buf_update[MAX_REG_VAL_PAIR_SIZE]; + + spinlock_t spin_lock; + struct mutex bus_mutex; + uint32_t secure_mode; + uint32_t num_sec_out; + uint32_t comp_done_shift; + bool is_lite; + cam_hw_mgr_event_cb_func event_cb; + bool rup_irq_enable[CAM_TFE_BUS_RUP_GRP_MAX]; +}; + +struct cam_tfe_bus_wm_resource_data { + uint32_t index; + struct cam_tfe_bus_common_data *common_data; + struct cam_tfe_bus_reg_offset_bus_client *hw_regs; + + uint32_t offset; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; + uint32_t pack_fmt; + uint32_t burst_len; + + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + + uint32_t en_cfg; + uint32_t is_dual; +}; + +struct cam_tfe_bus_comp_grp_data { + enum cam_tfe_bus_comp_grp_id comp_grp_id; + struct cam_tfe_bus_common_data *common_data; + + uint32_t is_master; + uint32_t is_dual; + uint32_t addr_sync_mode; + uint32_t composite_mask; + + uint32_t acquire_dev_cnt; + uint32_t source_grp; + + struct cam_isp_resource_node + *out_rsrc[CAM_TFE_MAX_OUT_RES_PER_COMP_GRP]; +}; + +struct cam_tfe_bus_tfe_out_data { + uint32_t out_id; + uint32_t composite_group; + uint32_t rup_group_id; + uint32_t source_group; + struct cam_tfe_bus_common_data *common_data; + + uint32_t num_wm; + struct cam_isp_resource_node *wm_res[PLANE_MAX]; + + struct cam_isp_resource_node *comp_grp; + struct list_head tfe_out_list; + + uint32_t is_master; + uint32_t is_dual; + + uint32_t format; + uint32_t max_width; + uint32_t max_height; + struct cam_cdm_utils_ops *cdm_util_ops; + uint32_t secure_mode; + void *priv; + cam_hw_mgr_event_cb_func event_cb; +}; + +struct cam_tfe_bus_priv { + struct cam_tfe_bus_common_data common_data; + uint32_t num_client; + uint32_t num_out; + uint32_t top_bus_wr_irq_shift; + + struct cam_isp_resource_node bus_client[CAM_TFE_BUS_MAX_CLIENTS]; + struct cam_isp_resource_node comp_grp[CAM_TFE_BUS_COMP_GRP_MAX]; + struct cam_isp_resource_node tfe_out[CAM_TFE_BUS_TFE_OUT_MAX]; + + struct list_head free_comp_grp; + struct list_head used_comp_grp; + + void *tasklet_info; + uint32_t comp_buf_done_mask; + uint32_t comp_rup_done_mask; + uint32_t bus_irq_error_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; +}; + +static bool cam_tfe_bus_can_be_secure(uint32_t out_id) +{ + switch (out_id) { + case CAM_TFE_BUS_TFE_OUT_FULL: + case CAM_TFE_BUS_TFE_OUT_RAW_DUMP: + case CAM_TFE_BUS_TFE_OUT_RDI0: + case CAM_TFE_BUS_TFE_OUT_RDI1: + case CAM_TFE_BUS_TFE_OUT_RDI2: + return true; + + case CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE: + case CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST: + case CAM_TFE_BUS_TFE_OUT_STATS_TL_BG: + case CAM_TFE_BUS_TFE_OUT_STATS_BF: + case CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG: + default: + return false; + } +} + +static enum cam_tfe_bus_tfe_out_id + cam_tfe_bus_get_out_res_id(uint32_t out_res_id) +{ + switch (out_res_id) { + case CAM_ISP_TFE_OUT_RES_FULL: + return CAM_TFE_BUS_TFE_OUT_FULL; + case CAM_ISP_TFE_OUT_RES_RAW_DUMP: + return CAM_TFE_BUS_TFE_OUT_RAW_DUMP; + case CAM_ISP_TFE_OUT_RES_PDAF: + return CAM_TFE_BUS_TFE_OUT_PDAF; + case CAM_ISP_TFE_OUT_RES_RDI_0: + return CAM_TFE_BUS_TFE_OUT_RDI0; + case CAM_ISP_TFE_OUT_RES_RDI_1: + return CAM_TFE_BUS_TFE_OUT_RDI1; + case CAM_ISP_TFE_OUT_RES_RDI_2: + return CAM_TFE_BUS_TFE_OUT_RDI2; + case CAM_ISP_TFE_OUT_RES_STATS_HDR_BE: + return CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE; + case CAM_ISP_TFE_OUT_RES_STATS_HDR_BHIST: + return CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST; + case CAM_ISP_TFE_OUT_RES_STATS_TL_BG: + return CAM_TFE_BUS_TFE_OUT_STATS_TL_BG; + case CAM_ISP_TFE_OUT_RES_STATS_BF: + return CAM_TFE_BUS_TFE_OUT_STATS_BF; + case CAM_ISP_TFE_OUT_RES_STATS_AWB_BG: + return CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG; + default: + return CAM_TFE_BUS_TFE_OUT_MAX; + } +} + +static int cam_tfe_bus_get_num_wm( + enum cam_tfe_bus_tfe_out_id out_res_id, + uint32_t format) +{ + switch (out_res_id) { + case CAM_TFE_BUS_TFE_OUT_RDI0: + case CAM_TFE_BUS_TFE_OUT_RDI1: + case CAM_TFE_BUS_TFE_OUT_RDI2: + switch (format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + case CAM_FORMAT_PLAIN128: + return 1; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_PDAF: + switch (format) { + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + return 1; + default: + break; + } + break; + + case CAM_TFE_BUS_TFE_OUT_FULL: + switch (format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + return 1; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_RAW_DUMP: + switch (format) { + case CAM_FORMAT_ARGB_14: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + return 1; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE: + case CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST: + case CAM_TFE_BUS_TFE_OUT_STATS_TL_BG: + case CAM_TFE_BUS_TFE_OUT_STATS_BF: + case CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG: + switch (format) { + case CAM_FORMAT_PLAIN64: + return 1; + default: + break; + } + break; + default: + break; + } + + CAM_ERR(CAM_ISP, "Unsupported format %u for resource id %u", + format, out_res_id); + + return -EINVAL; +} + +static int cam_tfe_bus_get_wm_idx( + enum cam_tfe_bus_tfe_out_id tfe_out_res_id, + enum cam_tfe_bus_plane_type plane) +{ + int wm_idx = -1; + + switch (tfe_out_res_id) { + case CAM_TFE_BUS_TFE_OUT_RDI0: + switch (plane) { + case PLANE_Y: + wm_idx = 7; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_RDI1: + switch (plane) { + case PLANE_Y: + wm_idx = 8; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_RDI2: + switch (plane) { + case PLANE_Y: + wm_idx = 9; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_PDAF: + switch (plane) { + case PLANE_Y: + wm_idx = 9; + break; + default: + break; + } + break; + + case CAM_TFE_BUS_TFE_OUT_FULL: + switch (plane) { + case PLANE_Y: + wm_idx = 0; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_RAW_DUMP: + switch (plane) { + case PLANE_Y: + wm_idx = 1; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE: + switch (plane) { + case PLANE_Y: + wm_idx = 5; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST: + switch (plane) { + case PLANE_Y: + wm_idx = 3; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG: + switch (plane) { + case PLANE_Y: + wm_idx = 4; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_STATS_TL_BG: + switch (plane) { + case PLANE_Y: + wm_idx = 2; + break; + default: + break; + } + break; + case CAM_TFE_BUS_TFE_OUT_STATS_BF: + switch (plane) { + case PLANE_Y: + wm_idx = 6; + break; + default: + break; + } + break; + + default: + break; + } + + return wm_idx; +} + +static enum cam_tfe_bus_packer_format + cam_tfe_bus_get_packer_fmt(uint32_t out_fmt, int wm_index) +{ + switch (out_fmt) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PD8: + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_PLAIN8: + return PACKER_FMT_PLAIN_8; + case CAM_FORMAT_Y_ONLY: + return PACKER_FMT_PLAIN_8_LSB_MSB_10; + case CAM_FORMAT_PLAIN16_10: + return PACKER_FMT_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return PACKER_FMT_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return PACKER_FMT_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN16_16: + return PACKER_FMT_PLAIN_16_16BPP; + case CAM_FORMAT_ARGB: + return PACKER_FMT_PLAIN_32; + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_PD10: + return PACKER_FMT_PLAIN_64; + case CAM_FORMAT_TP10: + return PACKER_FMT_TP_10; + default: + return PACKER_FMT_MAX; + } +} + +static int cam_tfe_bus_acquire_wm( + struct cam_tfe_bus_priv *bus_priv, + struct cam_isp_tfe_out_port_info *out_port_info, + struct cam_isp_resource_node **wm_res, + void *tasklet, + enum cam_tfe_bus_tfe_out_id tfe_out_res_id, + enum cam_tfe_bus_plane_type plane, + uint32_t *client_done_mask, + uint32_t is_dual, + enum cam_tfe_bus_comp_grp_id *comp_grp_id) +{ + struct cam_isp_resource_node *wm_res_local = NULL; + struct cam_tfe_bus_wm_resource_data *rsrc_data = NULL; + uint32_t wm_idx = 0; + + *wm_res = NULL; + + /* No need to allocate for BUS TFE OUT to WM is fixed. */ + wm_idx = cam_tfe_bus_get_wm_idx(tfe_out_res_id, plane); + if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { + CAM_ERR(CAM_ISP, "Unsupported TFE out %d plane %d", + tfe_out_res_id, plane); + return -EINVAL; + } + + wm_res_local = &bus_priv->bus_client[wm_idx]; + if (wm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "WM:%d not available state:%d", + wm_idx, wm_res_local->res_state); + return -EALREADY; + } + wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + wm_res_local->tasklet_info = tasklet; + + rsrc_data = wm_res_local->res_priv; + rsrc_data->format = out_port_info->format; + rsrc_data->pack_fmt = cam_tfe_bus_get_packer_fmt(rsrc_data->format, + wm_idx); + + rsrc_data->width = out_port_info->width; + rsrc_data->height = out_port_info->height; + rsrc_data->stride = out_port_info->stride; + rsrc_data->is_dual = is_dual; + /* Set WM offset value to default */ + rsrc_data->offset = 0; + + if (rsrc_data->index > 6) { + /* WM 7-9 refers to RDI 0/ RDI 1/RDI 2 */ + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_PLAIN128: + rsrc_data->width = CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->pack_fmt = 0xA; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + case CAM_FORMAT_PLAIN8: + rsrc_data->en_cfg = 0x1; + rsrc_data->pack_fmt = 0xA; + rsrc_data->stride = rsrc_data->width * 2; + break; + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + rsrc_data->width = CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->pack_fmt = 0xA; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + case CAM_FORMAT_PLAIN64: + rsrc_data->en_cfg = 0x1; + rsrc_data->pack_fmt = 0xA; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported RDI format %d", + rsrc_data->format); + return -EINVAL; + } + } else if (rsrc_data->index == 0) { + /* WM 0 FULL_OUT */ + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_8: + rsrc_data->pack_fmt = 0x1; + break; + case CAM_FORMAT_MIPI_RAW_10: + rsrc_data->pack_fmt = 0xc; + break; + case CAM_FORMAT_MIPI_RAW_12: + rsrc_data->pack_fmt = 0xd; + break; + case CAM_FORMAT_PLAIN8: + rsrc_data->pack_fmt = 0x1; + break; + case CAM_FORMAT_PLAIN16_10: + rsrc_data->pack_fmt = 0x5; + rsrc_data->pack_fmt |= 0x10; + break; + case CAM_FORMAT_PLAIN16_12: + rsrc_data->pack_fmt = 0x6; + rsrc_data->pack_fmt |= 0x10; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d", + rsrc_data->format); + return -EINVAL; + } + + rsrc_data->en_cfg = 0x1; + } else if (rsrc_data->index >= 2 && rsrc_data->index <= 6) { + /* WM 2-6 stats */ + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } else if (rsrc_data->index == 1) { + /* WM 1 Raw dump */ + rsrc_data->stride = rsrc_data->width; + rsrc_data->en_cfg = 0x1; + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x10; + } else { + CAM_ERR(CAM_ISP, "Invalid WM:%d requested", rsrc_data->index); + return -EINVAL; + } + + *wm_res = wm_res_local; + *comp_grp_id = rsrc_data->hw_regs->comp_group; + *client_done_mask |= (1 << wm_idx); + + CAM_DBG(CAM_ISP, + "WM:%d processed width:%d height:%d format:0x%x comp_group:%d packt format:0x%x", + rsrc_data->index, rsrc_data->width, rsrc_data->height, + rsrc_data->format, *comp_grp_id, rsrc_data->pack_fmt); + return 0; +} + +static int cam_tfe_bus_release_wm(void *bus_priv, + struct cam_isp_resource_node *wm_res) +{ + struct cam_tfe_bus_wm_resource_data *rsrc_data = wm_res->res_priv; + + rsrc_data->offset = 0; + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 0; + rsrc_data->format = 0; + rsrc_data->pack_fmt = 0; + rsrc_data->burst_len = 0; + rsrc_data->irq_subsample_period = 0; + rsrc_data->irq_subsample_pattern = 0; + rsrc_data->framedrop_period = 0; + rsrc_data->framedrop_pattern = 0; + rsrc_data->en_cfg = 0; + rsrc_data->is_dual = 0; + + wm_res->tasklet_info = NULL; + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + CAM_DBG(CAM_ISP, "TFE:%dRelease WM:%d", + rsrc_data->common_data->core_index, rsrc_data->index); + + return 0; +} + +static int cam_tfe_bus_start_wm(struct cam_isp_resource_node *wm_res) +{ + struct cam_tfe_bus_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_tfe_bus_common_data *common_data = + rsrc_data->common_data; + + cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->bw_limit); + + cam_io_w((rsrc_data->height << 16) | rsrc_data->width, + common_data->mem_base + rsrc_data->hw_regs->image_cfg_0); + cam_io_w(rsrc_data->pack_fmt, + common_data->mem_base + rsrc_data->hw_regs->packer_cfg); + + /* Configure stride for RDIs on full TFE and TFE lite */ + if (rsrc_data->index > 6) + cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + + rsrc_data->hw_regs->image_cfg_2)); + + /* Enable WM */ + cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + + rsrc_data->hw_regs->cfg); + + CAM_DBG(CAM_ISP, "TFE:%d WM:%d width = %d, height = %d", + common_data->core_index, rsrc_data->index, + rsrc_data->width, rsrc_data->height); + CAM_DBG(CAM_ISP, "WM:%d pk_fmt = %d", rsrc_data->index, + rsrc_data->pack_fmt); + CAM_DBG(CAM_ISP, "WM:%d stride = %d, burst len = %d", + rsrc_data->index, rsrc_data->stride, 0xf); + CAM_DBG(CAM_ISP, "TFE:%d Start WM:%d offset 0x%x val 0x%x", + common_data->core_index, rsrc_data->index, + (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + +static int cam_tfe_bus_stop_wm(struct cam_isp_resource_node *wm_res) +{ + struct cam_tfe_bus_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_tfe_bus_common_data *common_data = + rsrc_data->common_data; + + /* Disable WM */ + cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg); + CAM_DBG(CAM_ISP, "TFE:%d Stop WM:%d", + rsrc_data->common_data->core_index, rsrc_data->index); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + return 0; +} + +static int cam_tfe_bus_init_wm_resource(uint32_t index, + struct cam_tfe_bus_priv *bus_priv, + struct cam_tfe_bus_hw_info *hw_info, + struct cam_isp_resource_node *wm_res) +{ + struct cam_tfe_bus_wm_resource_data *rsrc_data; + + rsrc_data = kzalloc(sizeof(struct cam_tfe_bus_wm_resource_data), + GFP_KERNEL); + if (!rsrc_data) { + CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv"); + return -ENOMEM; + } + wm_res->res_priv = rsrc_data; + + rsrc_data->index = index; + rsrc_data->hw_regs = &hw_info->bus_client_reg[index]; + rsrc_data->common_data = &bus_priv->common_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = cam_tfe_bus_start_wm; + wm_res->stop = cam_tfe_bus_stop_wm; + wm_res->hw_intf = bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_tfe_bus_deinit_wm_resource( + struct cam_isp_resource_node *wm_res) +{ + struct cam_tfe_bus_wm_resource_data *rsrc_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = NULL; + wm_res->stop = NULL; + wm_res->top_half_handler = NULL; + wm_res->bottom_half_handler = NULL; + wm_res->hw_intf = NULL; + + rsrc_data = wm_res->res_priv; + wm_res->res_priv = NULL; + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static void cam_tfe_bus_add_wm_to_comp_grp( + struct cam_isp_resource_node *comp_grp, + uint32_t composite_mask) +{ + struct cam_tfe_bus_comp_grp_data *rsrc_data = comp_grp->res_priv; + + rsrc_data->composite_mask |= composite_mask; +} + +static bool cam_tfe_bus_match_comp_grp( + struct cam_tfe_bus_priv *bus_priv, + struct cam_isp_resource_node **comp_grp, + uint32_t comp_grp_id) +{ + struct cam_tfe_bus_comp_grp_data *rsrc_data = NULL; + struct cam_isp_resource_node *comp_grp_local = NULL; + + list_for_each_entry(comp_grp_local, + &bus_priv->used_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_id == comp_grp_id) { + /* Match found */ + *comp_grp = comp_grp_local; + return true; + } + } + + list_for_each_entry(comp_grp_local, + &bus_priv->free_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_id == comp_grp_id) { + /* Match found */ + *comp_grp = comp_grp_local; + list_del(&comp_grp_local->list); + list_add_tail(&comp_grp_local->list, + &bus_priv->used_comp_grp); + return false; + } + } + + *comp_grp = NULL; + return false; +} + +static int cam_tfe_bus_acquire_comp_grp( + struct cam_tfe_bus_priv *bus_priv, + struct cam_isp_tfe_out_port_info *out_port_info, + void *tasklet, + uint32_t is_dual, + uint32_t is_master, + struct cam_isp_resource_node **comp_grp, + enum cam_tfe_bus_comp_grp_id comp_grp_id, + struct cam_isp_resource_node *out_rsrc, + uint32_t source_group) +{ + int rc = 0; + struct cam_isp_resource_node *comp_grp_local = NULL; + struct cam_tfe_bus_comp_grp_data *rsrc_data = NULL; + bool previously_acquired = false; + + if (comp_grp_id >= CAM_TFE_BUS_COMP_GRP_0 && + comp_grp_id <= CAM_TFE_BUS_COMP_GRP_7) { + /* Check if matching comp_grp has already been acquired */ + previously_acquired = cam_tfe_bus_match_comp_grp( + bus_priv, &comp_grp_local, comp_grp_id); + } + + if (!comp_grp_local) { + CAM_ERR(CAM_ISP, "Invalid comp_grp_id:%d", comp_grp_id); + return -ENODEV; + } + + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->acquire_dev_cnt > CAM_TFE_MAX_OUT_RES_PER_COMP_GRP) { + CAM_ERR(CAM_ISP, "Many acquires comp_grp_id:%d", comp_grp_id); + return -ENODEV; + } + + if (!previously_acquired) { + comp_grp_local->tasklet_info = tasklet; + comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + rsrc_data->is_master = is_master; + rsrc_data->is_dual = is_dual; + + if (is_master) + rsrc_data->addr_sync_mode = 0; + else + rsrc_data->addr_sync_mode = 1; + } else { + rsrc_data = comp_grp_local->res_priv; + /* Do not support runtime change in composite mask */ + if (comp_grp_local->res_state == + CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "Invalid State %d Comp Grp %u", + comp_grp_local->res_state, + rsrc_data->comp_grp_id); + return -EBUSY; + } + } + + CAM_DBG(CAM_ISP, "Acquire comp_grp id:%u", rsrc_data->comp_grp_id); + rsrc_data->source_grp = source_group; + rsrc_data->out_rsrc[rsrc_data->acquire_dev_cnt] = out_rsrc; + rsrc_data->acquire_dev_cnt++; + *comp_grp = comp_grp_local; + + return rc; +} + +static int cam_tfe_bus_release_comp_grp( + struct cam_tfe_bus_priv *bus_priv, + struct cam_isp_resource_node *comp_grp) +{ + struct cam_isp_resource_node *comp_grp_local = NULL; + struct cam_tfe_bus_comp_grp_data *comp_rsrc_data = NULL; + int match_found = 0; + + if (!comp_grp) { + CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", comp_grp); + return -EINVAL; + } + + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "Already released Comp Grp"); + return 0; + } + + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "Invalid State %d", + comp_grp->res_state); + return -EBUSY; + } + + comp_rsrc_data = comp_grp->res_priv; + CAM_DBG(CAM_ISP, "Comp Grp id %u", comp_rsrc_data->comp_grp_id); + + list_for_each_entry(comp_grp_local, &bus_priv->used_comp_grp, list) { + if (comp_grp_local == comp_grp) { + match_found = 1; + break; + } + } + + if (!match_found) { + CAM_ERR(CAM_ISP, "Could not find comp_grp_id:%u", + comp_rsrc_data->comp_grp_id); + return -ENODEV; + } + + comp_rsrc_data->acquire_dev_cnt--; + if (comp_rsrc_data->acquire_dev_cnt == 0) { + list_del(&comp_grp_local->list); + + comp_rsrc_data->addr_sync_mode = 0; + comp_rsrc_data->composite_mask = 0; + + comp_grp_local->tasklet_info = NULL; + comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + list_add_tail(&comp_grp_local->list, &bus_priv->free_comp_grp); + CAM_DBG(CAM_ISP, "Comp Grp id %u released", + comp_rsrc_data->comp_grp_id); + } + + return 0; +} + +static int cam_tfe_bus_start_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + int rc = 0; + uint32_t val; + struct cam_tfe_bus_comp_grp_data *rsrc_data = NULL; + struct cam_tfe_bus_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask_0 = 0; + + rsrc_data = comp_grp->res_priv; + common_data = rsrc_data->common_data; + + CAM_DBG(CAM_ISP, "TFE:%d comp_grp_id:%d streaming state:%d mask:0x%x", + common_data->core_index, rsrc_data->comp_grp_id, + comp_grp->res_state, rsrc_data->composite_mask); + + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + return 0; + + if (rsrc_data->is_dual) { + if (rsrc_data->is_master) { + val = cam_io_r(common_data->mem_base + + common_data->common_reg->comp_cfg_0); + val |= (0x1 << (rsrc_data->comp_grp_id + 16)); + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->comp_cfg_0); + + val = cam_io_r(common_data->mem_base + + common_data->common_reg->comp_cfg_1); + val |= (0x1 << rsrc_data->comp_grp_id); + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->comp_cfg_1); + } else { + val = cam_io_r(common_data->mem_base + + common_data->common_reg->comp_cfg_0); + val |= (0x1 << rsrc_data->comp_grp_id); + cam_io_w(val, common_data->mem_base + + common_data->common_reg->comp_cfg_0); + + val = cam_io_r(common_data->mem_base + + common_data->common_reg->comp_cfg_1); + val |= (0x1 << rsrc_data->comp_grp_id); + cam_io_w(val, common_data->mem_base + + common_data->common_reg->comp_cfg_1); + } + } + + if (rsrc_data->is_dual && !rsrc_data->is_master) + goto end; + + /* Update the composite done mask in bus irq mask*/ + bus_irq_reg_mask_0 = cam_io_r(common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + bus_irq_reg_mask_0 |= (0x1 << (rsrc_data->comp_grp_id + + rsrc_data->common_data->comp_done_shift)); + cam_io_w_mb(bus_irq_reg_mask_0, common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + + CAM_DBG(CAM_ISP, "TFE:%d start COMP_GRP:%d bus_irq_mask_0 0x%x", + common_data->core_index, rsrc_data->comp_grp_id, + bus_irq_reg_mask_0); + +end: + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return rc; +} + +static int cam_tfe_bus_stop_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + struct cam_tfe_bus_comp_grp_data *rsrc_data = NULL; + struct cam_tfe_bus_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask_0 = 0; + + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) + return 0; + + rsrc_data = (struct cam_tfe_bus_comp_grp_data *)comp_grp->res_priv; + common_data = rsrc_data->common_data; + + /* Update the composite done mask in bus irq mask*/ + bus_irq_reg_mask_0 = cam_io_r(common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + bus_irq_reg_mask_0 &= ~(0x1 << (rsrc_data->comp_grp_id + + rsrc_data->common_data->comp_done_shift)); + cam_io_w_mb(bus_irq_reg_mask_0, common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + return 0; +} + +static int cam_tfe_bus_init_comp_grp(uint32_t index, + struct cam_hw_soc_info *soc_info, + struct cam_tfe_bus_priv *bus_priv, + struct cam_tfe_bus_hw_info *hw_info, + struct cam_isp_resource_node *comp_grp) +{ + struct cam_tfe_bus_comp_grp_data *rsrc_data = NULL; + + rsrc_data = kzalloc(sizeof(struct cam_tfe_bus_comp_grp_data), + GFP_KERNEL); + if (!rsrc_data) + return -ENOMEM; + + comp_grp->res_priv = rsrc_data; + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&comp_grp->list); + + comp_grp->res_id = index; + rsrc_data->comp_grp_id = index; + rsrc_data->common_data = &bus_priv->common_data; + + list_add_tail(&comp_grp->list, &bus_priv->free_comp_grp); + + comp_grp->hw_intf = bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_tfe_bus_deinit_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + struct cam_tfe_bus_comp_grp_data *rsrc_data = + comp_grp->res_priv; + + comp_grp->start = NULL; + comp_grp->stop = NULL; + comp_grp->top_half_handler = NULL; + comp_grp->bottom_half_handler = NULL; + comp_grp->hw_intf = NULL; + + list_del_init(&comp_grp->list); + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + + comp_grp->res_priv = NULL; + + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "comp_grp_priv is NULL"); + return -ENODEV; + } + kfree(rsrc_data); + + return 0; +} + +static int cam_tfe_bus_get_secure_mode(void *priv, void *cmd_args, + uint32_t arg_size) +{ + bool *mode = cmd_args; + struct cam_isp_resource_node *res = + (struct cam_isp_resource_node *) priv; + struct cam_tfe_bus_tfe_out_data *rsrc_data = + (struct cam_tfe_bus_tfe_out_data *)res->res_priv; + + *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? + true : false; + + return 0; +} + +static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, + uint32_t args_size) +{ + struct cam_tfe_bus_priv *bus_priv = priv; + struct cam_tfe_acquire_args *acq_args = acquire_args; + struct cam_tfe_hw_tfe_out_acquire_args *out_acquire_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + enum cam_tfe_bus_tfe_out_id tfe_out_res_id; + enum cam_tfe_bus_comp_grp_id comp_grp_id; + int rc = -ENODEV; + uint32_t secure_caps = 0, mode; + uint32_t i, format, num_wm, client_done_mask = 0; + + if (!bus_priv || !acquire_args) { + CAM_ERR(CAM_ISP, "Invalid Param"); + return -EINVAL; + } + + out_acquire_args = &acq_args->tfe_out; + format = out_acquire_args->out_port_info->format; + + CAM_DBG(CAM_ISP, "resid 0x%x fmt:%d, sec mode:%d wm mode:%d", + out_acquire_args->out_port_info->res_id, format, + out_acquire_args->out_port_info->secure_mode, + out_acquire_args->out_port_info->wm_mode); + CAM_DBG(CAM_ISP, "width:%d, height:%d stride:%d", + out_acquire_args->out_port_info->width, + out_acquire_args->out_port_info->height, + out_acquire_args->out_port_info->stride); + + tfe_out_res_id = cam_tfe_bus_get_out_res_id( + out_acquire_args->out_port_info->res_id); + if (tfe_out_res_id == CAM_TFE_BUS_TFE_OUT_MAX) + return -ENODEV; + + num_wm = cam_tfe_bus_get_num_wm(tfe_out_res_id, format); + if (num_wm < 1) + return -EINVAL; + + rsrc_node = &bus_priv->tfe_out[tfe_out_res_id]; + if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d", + tfe_out_res_id, rsrc_node->res_state); + return -EBUSY; + } + + rsrc_data = rsrc_node->res_priv; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + + secure_caps = cam_tfe_bus_can_be_secure(rsrc_data->out_id); + mode = out_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); + + bus_priv->tasklet_info = acq_args->tasklet; + rsrc_data->num_wm = num_wm; + rsrc_node->rdi_only_ctx = 0; + rsrc_node->res_id = out_acquire_args->out_port_info->res_id; + rsrc_node->cdm_ops = out_acquire_args->cdm_ops; + rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops; + + /* Acquire WM and retrieve COMP GRP ID */ + for (i = 0; i < num_wm; i++) { + rc = cam_tfe_bus_acquire_wm(bus_priv, + out_acquire_args->out_port_info, + &rsrc_data->wm_res[i], + acq_args->tasklet, + tfe_out_res_id, + i, + &client_done_mask, + out_acquire_args->is_dual, + &comp_grp_id); + if (rc) { + CAM_ERR(CAM_ISP, + "TFE:%d WM acquire failed for Out %d rc=%d", + rsrc_data->common_data->core_index, + tfe_out_res_id, rc); + goto release_wm; + } + } + + /* Acquire composite group using COMP GRP ID */ + rc = cam_tfe_bus_acquire_comp_grp(bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + out_acquire_args->is_dual, + out_acquire_args->is_master, + &rsrc_data->comp_grp, + comp_grp_id, + rsrc_node, + rsrc_data->source_group); + if (rc) { + CAM_ERR(CAM_ISP, + "TFE%d Comp_Grp acquire fail for Out %d rc=%d", + rsrc_data->common_data->core_index, + tfe_out_res_id, rc); + return rc; + } + + rsrc_data->is_dual = out_acquire_args->is_dual; + rsrc_data->is_master = out_acquire_args->is_master; + + cam_tfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp, + client_done_mask); + + rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + out_acquire_args->rsrc_node = rsrc_node; + + return rc; + +release_wm: + for (i--; i >= 0; i--) + cam_tfe_bus_release_wm(bus_priv, + rsrc_data->wm_res[i]); + + cam_tfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); + + return rc; +} + +static int cam_tfe_bus_release_tfe_out(void *priv, void *release_args, + uint32_t args_size) +{ + struct cam_tfe_bus_priv *bus_priv = priv; + struct cam_isp_resource_node *tfe_out = NULL; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + uint32_t secure_caps = 0; + uint32_t i; + + if (!bus_priv || !release_args) { + CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK", + bus_priv, release_args); + return -EINVAL; + } + + tfe_out = (struct cam_isp_resource_node *)release_args; + rsrc_data = (struct cam_tfe_bus_tfe_out_data *)tfe_out->res_priv; + + if (tfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "Invalid resource state:%d res id:%d", + tfe_out->res_state, tfe_out->res_id); + } + + for (i = 0; i < rsrc_data->num_wm; i++) + cam_tfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]); + + rsrc_data->num_wm = 0; + + if (rsrc_data->comp_grp) + cam_tfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); + + rsrc_data->comp_grp = NULL; + + tfe_out->tasklet_info = NULL; + tfe_out->cdm_ops = NULL; + rsrc_data->cdm_util_ops = NULL; + + secure_caps = cam_tfe_bus_can_be_secure(rsrc_data->out_id); + 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 (tfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) + tfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +static int cam_tfe_bus_start_tfe_out(void *hw_priv, + void *start_hw_args, uint32_t arg_size) +{ + struct cam_isp_resource_node *tfe_out = hw_priv; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + struct cam_tfe_bus_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask_0 = 0; + uint32_t rup_group_id = 0; + int rc = 0, i; + + if (!tfe_out) { + CAM_ERR(CAM_ISP, "Invalid input"); + return -EINVAL; + } + + rsrc_data = tfe_out->res_priv; + common_data = rsrc_data->common_data; + rup_group_id = rsrc_data->rup_group_id; + + CAM_DBG(CAM_ISP, "TFE:%d Start resource index %d", + common_data->core_index, rsrc_data->out_id); + + if (tfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "TFE:%d Invalid resource state:%d", + common_data->core_index, tfe_out->res_state); + return -EACCES; + } + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_tfe_bus_start_wm(rsrc_data->wm_res[i]); + + rc = cam_tfe_bus_start_comp_grp(rsrc_data->comp_grp); + + if (rsrc_data->is_dual && !rsrc_data->is_master && + !tfe_out->rdi_only_ctx) + goto end; + + if (common_data->rup_irq_enable[rup_group_id]) + goto end; + + /* Update the composite regupdate mask in bus irq mask*/ + bus_irq_reg_mask_0 = cam_io_r(common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + bus_irq_reg_mask_0 |= (0x1 << rup_group_id); + cam_io_w_mb(bus_irq_reg_mask_0, common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + common_data->rup_irq_enable[rup_group_id] = true; + +end: + tfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return rc; +} + +static int cam_tfe_bus_stop_tfe_out(void *hw_priv, + void *stop_hw_args, uint32_t arg_size) +{ + struct cam_isp_resource_node *tfe_out = hw_priv; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + struct cam_tfe_bus_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask_0 = 0, rup_group = 0; + int rc = 0, i; + + if (!tfe_out) { + CAM_ERR(CAM_ISP, "Invalid input"); + return -EINVAL; + } + + rsrc_data = tfe_out->res_priv; + common_data = rsrc_data->common_data; + rup_group = rsrc_data->rup_group_id; + + if (tfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE || + tfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_ISP, "tfe_out res_state is %d", tfe_out->res_state); + return rc; + } + + rc = cam_tfe_bus_stop_comp_grp(rsrc_data->comp_grp); + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_tfe_bus_stop_wm(rsrc_data->wm_res[i]); + + + if (!common_data->rup_irq_enable[rup_group]) + goto end; + + /* disable composite regupdate mask in bus irq mask register*/ + bus_irq_reg_mask_0 = cam_io_r(common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + bus_irq_reg_mask_0 &= ~(0x1 << rup_group); + cam_io_w_mb(bus_irq_reg_mask_0, common_data->mem_base + + common_data->common_reg->irq_mask[CAM_TFE_BUS_IRQ_REG0]); + common_data->rup_irq_enable[rup_group] = false; + +end: + tfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_tfe_bus_init_tfe_out_resource(uint32_t index, + struct cam_tfe_bus_priv *bus_priv, + struct cam_tfe_bus_hw_info *hw_info) +{ + struct cam_isp_resource_node *tfe_out = NULL; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + int rc = 0; + int32_t tfe_out_id = hw_info->tfe_out_hw_info[index].tfe_out_id; + + if (tfe_out_id < 0 || + tfe_out_id >= CAM_TFE_BUS_TFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "Init TFE Out failed, Invalid type=%d", + tfe_out_id); + return -EINVAL; + } + + tfe_out = &bus_priv->tfe_out[tfe_out_id]; + if (tfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || + tfe_out->res_priv) { + CAM_ERR(CAM_ISP, "tfe_out_id %d has already been initialized", + tfe_out_id); + return -EFAULT; + } + + rsrc_data = kzalloc(sizeof(struct cam_tfe_bus_tfe_out_data), + GFP_KERNEL); + if (!rsrc_data) { + rc = -ENOMEM; + return rc; + } + + tfe_out->res_priv = rsrc_data; + + tfe_out->res_type = CAM_ISP_RESOURCE_TFE_OUT; + tfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&tfe_out->list); + + rsrc_data->composite_group = + hw_info->tfe_out_hw_info[index].composite_group; + rsrc_data->rup_group_id = + hw_info->tfe_out_hw_info[index].rup_group_id; + rsrc_data->out_id = + hw_info->tfe_out_hw_info[index].tfe_out_id; + rsrc_data->common_data = &bus_priv->common_data; + rsrc_data->max_width = + hw_info->tfe_out_hw_info[index].max_width; + rsrc_data->max_height = + hw_info->tfe_out_hw_info[index].max_height; + rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + + tfe_out->hw_intf = bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_tfe_bus_deinit_tfe_out_resource( + struct cam_isp_resource_node *tfe_out) +{ + struct cam_tfe_bus_tfe_out_data *rsrc_data = tfe_out->res_priv; + + if (tfe_out->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; + } + + tfe_out->start = NULL; + tfe_out->stop = NULL; + tfe_out->top_half_handler = NULL; + tfe_out->bottom_half_handler = NULL; + tfe_out->hw_intf = NULL; + + tfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&tfe_out->list); + tfe_out->res_priv = NULL; + + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static const char *cam_tfe_bus_rup_type( + uint32_t group_id) +{ + switch (group_id) { + case CAM_ISP_HW_TFE_IN_CAMIF: + return "CAMIF RUP"; + case CAM_ISP_HW_TFE_IN_RDI0: + return "RDI0 RUP"; + case CAM_ISP_HW_TFE_IN_RDI1: + return "RDI1 RUP"; + case CAM_ISP_HW_TFE_IN_RDI2: + return "RDI2 RUP"; + default: + return "invalid rup group"; + } +} +static int cam_tfe_bus_rup_bottom_half( + struct cam_tfe_bus_priv *bus_priv, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_bus_common_data *common_data; + struct cam_tfe_bus_tfe_out_data *out_rsrc_data; + struct cam_isp_hw_event_info evt_info; + uint32_t i, j; + + common_data = &bus_priv->common_data; + evt_info.hw_idx = bus_priv->common_data.core_index; + evt_info.res_type = CAM_ISP_RESOURCE_TFE_OUT; + + for (i = 0; i < CAM_TFE_BUS_RUP_GRP_MAX; i++) { + if (!(evt_payload->bus_irq_val[0] & + bus_priv->comp_rup_done_mask)) + break; + + if (evt_payload->bus_irq_val[0] & BIT(i)) { + for (j = 0; j < CAM_TFE_BUS_TFE_OUT_MAX; j++) { + out_rsrc_data = + (struct cam_tfe_bus_tfe_out_data *) + bus_priv->tfe_out[j].res_priv; + if ((out_rsrc_data->rup_group_id == i) && + (bus_priv->tfe_out[j].res_state == + CAM_ISP_RESOURCE_STATE_STREAMING)) + break; + } + + if (j == CAM_TFE_BUS_TFE_OUT_MAX) { + CAM_ERR(CAM_ISP, + "TFE:%d out rsc active status[0]:0x%x", + bus_priv->common_data.core_index, + evt_payload->bus_irq_val[0]); + continue; + } + + CAM_DBG(CAM_ISP, "TFE:%d Received %s", + bus_priv->common_data.core_index, + cam_tfe_bus_rup_type(i)); + evt_info.res_id = i; + if (out_rsrc_data->event_cb) { + out_rsrc_data->event_cb( + out_rsrc_data->priv, + CAM_ISP_HW_EVENT_REG_UPDATE, + (void *)&evt_info); + /* reset the rup bit */ + evt_payload->bus_irq_val[0] &= ~BIT(i); + } else + CAM_ERR(CAM_ISP, + "TFE:%d No event cb id:%lld evt id:%d", + bus_priv->common_data.core_index, + out_rsrc_data->out_id, evt_info.res_id); + } + } + + return 0; +} + +static int cam_tfe_bus_bufdone_bottom_half( + struct cam_tfe_bus_priv *bus_priv, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_bus_common_data *common_data; + struct cam_tfe_bus_tfe_out_data *out_rsrc_data; + struct cam_isp_hw_event_info evt_info; + struct cam_isp_resource_node *out_rsrc = NULL; + struct cam_tfe_bus_comp_grp_data *comp_rsrc_data; + uint32_t i, j; + + common_data = &bus_priv->common_data; + + for (i = 0; i < CAM_TFE_BUS_COMP_GRP_MAX; i++) { + if (!(evt_payload->bus_irq_val[0] & + bus_priv->comp_buf_done_mask)) + break; + + comp_rsrc_data = (struct cam_tfe_bus_comp_grp_data *) + bus_priv->comp_grp[i].res_priv; + + if (evt_payload->bus_irq_val[0] & + BIT(comp_rsrc_data->comp_grp_id + + bus_priv->common_data.comp_done_shift)) { + for (j = 0; j < comp_rsrc_data->acquire_dev_cnt; j++) { + out_rsrc = comp_rsrc_data->out_rsrc[j]; + out_rsrc_data = out_rsrc->res_priv; + evt_info.res_type = out_rsrc->res_type; + evt_info.hw_idx = out_rsrc->hw_intf->hw_idx; + evt_info.res_id = out_rsrc->res_id; + out_rsrc_data->event_cb(out_rsrc_data->priv, + CAM_ISP_HW_EVENT_DONE, + (void *)&evt_info); + } + + evt_payload->bus_irq_val[0] &= + ~BIT(comp_rsrc_data->comp_grp_id + + bus_priv->common_data.comp_done_shift); + } + } + + return 0; +} + +static int cam_tfe_bus_bottom_half(void *priv, + bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_bus_priv *bus_priv; + uint32_t val; + + if (!priv || !evt_payload) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid priv param"); + return -EINVAL; + } + bus_priv = (struct cam_tfe_bus_priv *) priv; + + /* if bus errors are there, mask all bus errors */ + if (evt_payload->bus_irq_val[0] & bus_priv->bus_irq_error_mask[0]) { + val = cam_io_r(bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[0]); + val &= ~bus_priv->bus_irq_error_mask[0]; + cam_io_w(val, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[0]); + } + + if (rup_process) { + if (evt_payload->bus_irq_val[0] & + bus_priv->comp_rup_done_mask) + cam_tfe_bus_rup_bottom_half(bus_priv, evt_payload); + } else { + if (evt_payload->bus_irq_val[0] & + bus_priv->comp_buf_done_mask) + cam_tfe_bus_bufdone_bottom_half(bus_priv, evt_payload); + } + + return 0; + +} + +static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_buf; + struct cam_buf_io_cfg *io_cfg; + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_data = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, size = 0; + uint32_t frame_inc = 0, val; + + bus_priv = (struct cam_tfe_bus_priv *) priv; + update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) + update_buf->res->res_priv; + + if (!tfe_out_data || !tfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + if (update_buf->wm_update->num_buf != tfe_out_data->num_wm) { + CAM_ERR(CAM_ISP, + "Failed! Invalid number buffers:%d required:%d", + update_buf->wm_update->num_buf, tfe_out_data->num_wm); + return -EINVAL; + } + + reg_val_pair = &tfe_out_data->common_data->io_buf_update[0]; + io_cfg = update_buf->wm_update->io_cfg; + + for (i = 0, j = 0; i < tfe_out_data->num_wm; 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 %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = tfe_out_data->wm_res[i]->res_priv; + /* update width register */ + val = cam_io_r_mb(wm_data->common_data->mem_base + + wm_data->hw_regs->image_cfg_0); + /* mask previously written width but preserve height */ + val = val & 0xFFFF0000; + val |= wm_data->width; + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_0, val); + CAM_DBG(CAM_ISP, "WM:%d image height and width 0x%x", + wm_data->index, reg_val_pair[j-1]); + + val = io_cfg->planes[i].plane_stride; + CAM_DBG(CAM_ISP, "before stride %d", val); + val = ALIGNUP(val, 16); + if (val != io_cfg->planes[i].plane_stride && + val != wm_data->stride) + CAM_WARN(CAM_ISP, "Warning stride %u expected %u", + io_cfg->planes[i].plane_stride, val); + + val = wm_data->offset; + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_1, val); + CAM_DBG(CAM_ISP, "WM:%d xinit 0x%x", + wm_data->index, reg_val_pair[j-1]); + + if (wm_data->index < 7) { + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_2, + io_cfg->planes[i].plane_stride); + wm_data->stride = val; + CAM_DBG(CAM_ISP, "WM %d image stride 0x%x", + wm_data->index, reg_val_pair[j-1]); + } + + frame_inc = io_cfg->planes[i].plane_stride * + io_cfg->planes[i].slice_height; + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i]); + CAM_DBG(CAM_ISP, "WM %d image address 0x%x", + wm_data->index, reg_val_pair[j-1]); + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_incr, frame_inc); + CAM_DBG(CAM_ISP, "WM %d frame_inc %d", + wm_data->index, reg_val_pair[j-1]); + + /* enable the WM */ + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->cfg, + wm_data->en_cfg); + } + + size = tfe_out_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; + } + + tfe_out_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_tfe_bus_update_hfr(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_hfr; + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_data = NULL; + struct cam_isp_tfe_port_hfr_config *hfr_cfg = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_tfe_bus_priv *) priv; + update_hfr = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) + update_hfr->res->res_priv; + + if (!tfe_out_data || !tfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + reg_val_pair = &tfe_out_data->common_data->io_buf_update[0]; + hfr_cfg = (struct cam_isp_tfe_port_hfr_config *)update_hfr->data; + + for (i = 0, j = 0; i < tfe_out_data->num_wm; 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 %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = tfe_out_data->wm_res[i]->res_priv; + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_pattern, + hfr_cfg->framedrop_pattern); + wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern; + CAM_DBG(CAM_ISP, "WM:%d framedrop pattern 0x%x", + wm_data->index, wm_data->framedrop_pattern); + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_period, + hfr_cfg->framedrop_period); + wm_data->framedrop_period = hfr_cfg->framedrop_period; + CAM_DBG(CAM_ISP, "WM:%d framedrop period 0x%x", + wm_data->index, wm_data->framedrop_period); + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_period, + hfr_cfg->subsample_period); + wm_data->irq_subsample_period = hfr_cfg->subsample_period; + CAM_DBG(CAM_ISP, "WM:%d irq subsample period 0x%x", + wm_data->index, wm_data->irq_subsample_period); + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_pattern, + hfr_cfg->subsample_pattern); + wm_data->irq_subsample_pattern = hfr_cfg->subsample_pattern; + CAM_DBG(CAM_ISP, "WM:%d irq subsample pattern 0x%x", + wm_data->index, wm_data->irq_subsample_pattern); + } + + size = tfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2); + + /* cdm util returns dwords, need to convert to bytes */ + if ((size * 4) > update_hfr->cmd.size) { + CAM_ERR(CAM_ISP, + "Failed! Buf size:%d insufficient, expected size:%d", + update_hfr->cmd.size, size); + return -ENOMEM; + } + + tfe_out_data->cdm_util_ops->cdm_write_regrandom( + update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + update_hfr->cmd.used_bytes = size * 4; + + return 0; +} + +static int cam_tfe_bus_update_stripe_cfg(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + struct cam_tfe_dual_update_args *stripe_args; + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_data = NULL; + struct cam_isp_tfe_dual_stripe_config *stripe_config; + uint32_t i; + + bus_priv = (struct cam_tfe_bus_priv *) priv; + stripe_args = (struct cam_tfe_dual_update_args *)cmd_args; + + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) + stripe_args->res->res_priv; + + if (!tfe_out_data) { + CAM_ERR(CAM_ISP, "Failed! Invalid data"); + return -EINVAL; + } + + if (stripe_args->res->res_id < CAM_ISP_TFE_OUT_RES_BASE || + stripe_args->res->res_id >= CAM_ISP_TFE_OUT_RES_MAX) + return 0; + + stripe_config = (struct cam_isp_tfe_dual_stripe_config *) + stripe_args->stripe_config; + + for (i = 0; i < tfe_out_data->num_wm; i++) { + stripe_config = &stripe_args->stripe_config[i]; + wm_data = tfe_out_data->wm_res[i]->res_priv; + wm_data->width = stripe_config->width; + wm_data->offset = stripe_config->offset; + CAM_DBG(CAM_ISP, "id:%x WM:%d width:0x%x offset:%x", + stripe_args->res->res_id, wm_data->index, + wm_data->width, wm_data->offset); + } + + return 0; +} + +static int cam_tfe_bus_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv = hw_priv; + uint32_t i, top_irq_reg_mask[3] = {0}; + int rc = -EINVAL; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + top_irq_reg_mask[0] = (1 << bus_priv->top_bus_wr_irq_shift); + + rc = cam_tfe_irq_config(bus_priv->common_data.tfe_core_data, + top_irq_reg_mask, CAM_TFE_TOP_IRQ_REG_NUM, true); + if (rc) + return rc; + + /* configure the error irq */ + for (i = 0; i < CAM_TFE_BUS_IRQ_REGISTERS_MAX; i++) + cam_io_w(bus_priv->bus_irq_error_mask[i], + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[i]); + + return 0; +} + +static int cam_tfe_bus_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv = hw_priv; + uint32_t top_irq_reg_mask[3] = {0}; + int rc = 0; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Error: Invalid args"); + return -EINVAL; + } + top_irq_reg_mask[0] = (1 << bus_priv->top_bus_wr_irq_shift); + rc = cam_tfe_irq_config(bus_priv->common_data.tfe_core_data, + top_irq_reg_mask, CAM_TFE_TOP_IRQ_REG_NUM, false); + if (rc) + return rc; + + /* configure the error irq */ + cam_io_w(0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[0]); + + cam_io_w_mb(0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[1]); + + return rc; +} + +static int cam_tfe_bus_process_cmd(void *priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + int rc = -EINVAL; + uint32_t i, val; + + 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: + rc = cam_tfe_bus_update_wm(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + rc = cam_tfe_bus_update_hfr(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = cam_tfe_bus_get_secure_mode(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + rc = cam_tfe_bus_update_stripe_cfg(priv, + cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: + bus_priv = (struct cam_tfe_bus_priv *) priv; + /* disable the bus error interrupts */ + for (i = 0; i < CAM_TFE_BUS_IRQ_REGISTERS_MAX; i++) { + val = cam_io_r(bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[i]); + val &= ~bus_priv->bus_irq_error_mask[i]; + cam_io_w(val, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->irq_mask[i]); + } + break; + default: + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", + cmd_type); + break; + } + + return rc; +} + +int cam_tfe_bus_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + void *core_data, + struct cam_tfe_bus **tfe_bus) +{ + int i, rc = 0; + struct cam_tfe_bus_priv *bus_priv = NULL; + struct cam_tfe_bus *tfe_bus_local; + struct cam_tfe_bus_hw_info *hw_info = bus_hw_info; + + if (!soc_info || !hw_intf || !bus_hw_info) { + CAM_ERR(CAM_ISP, + "Invalid params soc_info:%pK hw_intf:%pK hw_info%pK", + soc_info, hw_intf, bus_hw_info); + rc = -EINVAL; + goto end; + } + + tfe_bus_local = kzalloc(sizeof(struct cam_tfe_bus), GFP_KERNEL); + if (!tfe_bus_local) { + CAM_DBG(CAM_ISP, "Failed to alloc for tfe_bus"); + rc = -ENOMEM; + goto end; + } + + bus_priv = kzalloc(sizeof(struct cam_tfe_bus_priv), + GFP_KERNEL); + if (!bus_priv) { + CAM_DBG(CAM_ISP, "Failed to alloc for tfe_bus_priv"); + rc = -ENOMEM; + goto free_bus_local; + } + tfe_bus_local->bus_priv = bus_priv; + + bus_priv->num_client = hw_info->num_client; + bus_priv->num_out = hw_info->num_out; + bus_priv->top_bus_wr_irq_shift = hw_info->top_bus_wr_irq_shift; + bus_priv->common_data.comp_done_shift = hw_info->comp_done_shift; + + 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, TFE_CORE_BASE_IDX); + bus_priv->common_data.hw_intf = hw_intf; + bus_priv->common_data.tfe_core_data = core_data; + bus_priv->common_data.common_reg = &hw_info->common_reg; + bus_priv->comp_buf_done_mask = hw_info->comp_buf_done_mask; + bus_priv->comp_rup_done_mask = hw_info->comp_rup_done_mask; + + for (i = 0; i < CAM_TFE_BUS_IRQ_REGISTERS_MAX; i++) + bus_priv->bus_irq_error_mask[i] = + hw_info->bus_irq_error_mask[i]; + + if (strnstr(soc_info->compatible, "lite", + strlen(soc_info->compatible)) != NULL) + bus_priv->common_data.is_lite = true; + else + bus_priv->common_data.is_lite = false; + + for (i = 0; i < CAM_TFE_BUS_RUP_GRP_MAX; i++) + bus_priv->common_data.rup_irq_enable[i] = false; + + mutex_init(&bus_priv->common_data.bus_mutex); + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_tfe_bus_init_wm_resource(i, bus_priv, bus_hw_info, + &bus_priv->bus_client[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Init WM failed rc=%d", rc); + goto deinit_wm; + } + } + + for (i = 0; i < CAM_TFE_BUS_COMP_GRP_MAX; i++) { + rc = cam_tfe_bus_init_comp_grp(i, soc_info, + bus_priv, bus_hw_info, + &bus_priv->comp_grp[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Init Comp Grp failed rc=%d", rc); + goto deinit_comp_grp; + } + } + + for (i = 0; i < bus_priv->num_out; i++) { + rc = cam_tfe_bus_init_tfe_out_resource(i, bus_priv, + bus_hw_info); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Init TFE Out failed rc=%d", rc); + goto deinit_tfe_out; + } + } + + spin_lock_init(&bus_priv->common_data.spin_lock); + + tfe_bus_local->hw_ops.reserve = cam_tfe_bus_acquire_tfe_out; + tfe_bus_local->hw_ops.release = cam_tfe_bus_release_tfe_out; + tfe_bus_local->hw_ops.start = cam_tfe_bus_start_tfe_out; + tfe_bus_local->hw_ops.stop = cam_tfe_bus_stop_tfe_out; + tfe_bus_local->hw_ops.init = cam_tfe_bus_init_hw; + tfe_bus_local->hw_ops.deinit = cam_tfe_bus_deinit_hw; + tfe_bus_local->bottom_half_handler = cam_tfe_bus_bottom_half; + tfe_bus_local->hw_ops.process_cmd = cam_tfe_bus_process_cmd; + + *tfe_bus = tfe_bus_local; + + return rc; + +deinit_tfe_out: + if (i < 0) + i = CAM_TFE_BUS_TFE_OUT_MAX; + for (--i; i >= 0; i--) + cam_tfe_bus_deinit_tfe_out_resource(&bus_priv->tfe_out[i]); + +deinit_comp_grp: + if (i < 0) + i = CAM_TFE_BUS_COMP_GRP_MAX; + for (--i; i >= 0; i--) + cam_tfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]); + +deinit_wm: + if (i < 0) + i = bus_priv->num_client; + for (--i; i >= 0; i--) + cam_tfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]); + + kfree(tfe_bus_local->bus_priv); + +free_bus_local: + kfree(tfe_bus_local); + +end: + return rc; +} + +int cam_tfe_bus_deinit( + struct cam_tfe_bus **tfe_bus) +{ + int i, rc = 0; + struct cam_tfe_bus_priv *bus_priv = NULL; + struct cam_tfe_bus *tfe_bus_local; + + if (!tfe_bus || !*tfe_bus) { + CAM_ERR(CAM_ISP, "Invalid input"); + return -EINVAL; + } + tfe_bus_local = *tfe_bus; + bus_priv = tfe_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_tfe_bus_deinit_wm_resource( + &bus_priv->bus_client[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Deinit WM failed rc=%d", rc); + } + + for (i = 0; i < CAM_TFE_BUS_COMP_GRP_MAX; i++) { + rc = cam_tfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Deinit Comp Grp failed rc=%d", rc); + } + + for (i = 0; i < CAM_TFE_BUS_TFE_OUT_MAX; i++) { + rc = cam_tfe_bus_deinit_tfe_out_resource( + &bus_priv->tfe_out[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Deinit TFE Out failed rc=%d", rc); + } + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + mutex_destroy(&bus_priv->common_data.bus_mutex); + kfree(tfe_bus_local->bus_priv); + +free_bus_local: + kfree(tfe_bus_local); + + *tfe_bus = NULL; + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h new file mode 100644 index 000000000000..3a62806f970f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_TFE_BUS_H_ +#define _CAM_TFE_BUS_H_ + +#include "cam_soc_util.h" +#include "cam_isp_hw.h" +#include "cam_tfe_hw_intf.h" + +#define CAM_TFE_BUS_MAX_CLIENTS 10 +#define CAM_TFE_BUS_MAX_SUB_GRPS 4 +#define CAM_TFE_BUS_MAX_PERF_CNT_REG 8 +#define CAM_TFE_BUS_MAX_IRQ_REGISTERS 2 + +#define CAM_TFE_BUS_1_0 0x1000 + + +#define CAM_TFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \ + do { \ + buf_array[(index)++] = offset; \ + buf_array[(index)++] = val; \ + } while (0) + +#define ALIGNUP(value, alignment) \ + ((value + alignment - 1) / alignment * alignment) + +typedef int (*CAM_BUS_HANDLER_BOTTOM_HALF)(void *bus_priv, + bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload); + +enum cam_tfe_bus_plane_type { + PLANE_Y, + PLANE_C, + PLANE_MAX, +}; + + +enum cam_tfe_bus_tfe_core_id { + CAM_TFE_BUS_TFE_CORE_0, + CAM_TFE_BUS_TFE_CORE_1, + CAM_TFE_BUS_TFE_CORE_2, + CAM_TFE_BUS_TFE_CORE_MAX, +}; + +enum cam_tfe_bus_comp_grp_id { + CAM_TFE_BUS_COMP_GRP_0, + CAM_TFE_BUS_COMP_GRP_1, + CAM_TFE_BUS_COMP_GRP_2, + CAM_TFE_BUS_COMP_GRP_3, + CAM_TFE_BUS_COMP_GRP_4, + CAM_TFE_BUS_COMP_GRP_5, + CAM_TFE_BUS_COMP_GRP_6, + CAM_TFE_BUS_COMP_GRP_7, + CAM_TFE_BUS_COMP_GRP_MAX, +}; + +enum cam_tfe_bus_rup_grp_id { + CAM_TFE_BUS_RUP_GRP_0, + CAM_TFE_BUS_RUP_GRP_1, + CAM_TFE_BUS_RUP_GRP_2, + CAM_TFE_BUS_RUP_GRP_3, + CAM_TFE_BUS_RUP_GRP_MAX, +}; + +enum cam_tfe_bus_tfe_out_id { + CAM_TFE_BUS_TFE_OUT_RDI0, + CAM_TFE_BUS_TFE_OUT_RDI1, + CAM_TFE_BUS_TFE_OUT_RDI2, + CAM_TFE_BUS_TFE_OUT_FULL, + CAM_TFE_BUS_TFE_OUT_RAW_DUMP, + CAM_TFE_BUS_TFE_OUT_PDAF, + CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE, + CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST, + CAM_TFE_BUS_TFE_OUT_STATS_TL_BG, + CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG, + CAM_TFE_BUS_TFE_OUT_STATS_BF, + CAM_TFE_BUS_TFE_OUT_MAX, +}; + +/* + * struct cam_tfe_bus_reg_offset_common: + * + * @Brief: Common registers across all BUS Clients + */ +struct cam_tfe_bus_reg_offset_common { + uint32_t hw_version; + uint32_t cgc_ovd; + uint32_t comp_cfg_0; + uint32_t comp_cfg_1; + uint32_t frameheader_cfg[4]; + uint32_t pwr_iso_cfg; + uint32_t overflow_status_clear; + uint32_t ccif_violation_status; + uint32_t overflow_status; + uint32_t image_size_violation_status; + uint32_t perf_count_cfg[CAM_TFE_BUS_MAX_PERF_CNT_REG]; + uint32_t perf_count_val[CAM_TFE_BUS_MAX_PERF_CNT_REG]; + uint32_t perf_count_status; + uint32_t debug_status_top_cfg; + uint32_t debug_status_top; + uint32_t test_bus_ctrl; + uint32_t irq_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; + uint32_t irq_clear[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; + uint32_t irq_status[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; + uint32_t irq_cmd; +}; + +/* + * struct cam_tfe_bus_reg_offset_bus_client: + * + * @Brief: Register offsets for BUS Clients + */ +struct cam_tfe_bus_reg_offset_bus_client { + uint32_t cfg; + uint32_t image_addr; + uint32_t frame_incr; + uint32_t image_cfg_0; + uint32_t image_cfg_1; + uint32_t image_cfg_2; + uint32_t packer_cfg; + uint32_t bw_limit; + uint32_t frame_header_addr; + uint32_t frame_header_incr; + uint32_t frame_header_cfg; + uint32_t line_done_cfg; + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + uint32_t addr_status_0; + uint32_t addr_status_1; + uint32_t addr_status_2; + uint32_t addr_status_3; + uint32_t debug_status_cfg; + uint32_t debug_status_0; + uint32_t debug_status_1; + uint32_t comp_group; +}; + +/* + * struct cam_tfe_bus_tfe_out_hw_info: + * + * @Brief: HW capability of TFE Bus Client + * tfe_out_id Tfe out port id + * max_width Max width supported by the outport + * max_height Max height supported by outport + * composite_group Out port composite group id + * rup_group_id Reg update group of outport id + */ +struct cam_tfe_bus_tfe_out_hw_info { + enum cam_tfe_bus_tfe_out_id tfe_out_id; + uint32_t max_width; + uint32_t max_height; + uint32_t composite_group; + uint32_t rup_group_id; +}; + +/* + * struct cam_tfe_bus_hw_info: + * + * @Brief: HW register info for entire Bus + * + * @common_reg: Common register details + * @num_client: Total number of write clients + * @bus_client_reg: Bus client register info + * @tfe_out_hw_info: TFE output capability + * @comp_done_shift: Mask shift for comp done mask + * @top_bus_wr_irq_shift: Mask shift for top level BUS WR irq + * @comp_buf_done_mask: Composite buf done bits mask + * @comp_rup_done_mask: Reg update done mask + * @bus_irq_error_mask: Bus irq error mask bits + */ +struct cam_tfe_bus_hw_info { + struct cam_tfe_bus_reg_offset_common common_reg; + uint32_t num_client; + struct cam_tfe_bus_reg_offset_bus_client + bus_client_reg[CAM_TFE_BUS_MAX_CLIENTS]; + uint32_t num_out; + struct cam_tfe_bus_tfe_out_hw_info + tfe_out_hw_info[CAM_TFE_BUS_TFE_OUT_MAX]; + uint32_t comp_done_shift; + uint32_t top_bus_wr_irq_shift; + uint32_t comp_buf_done_mask; + uint32_t comp_rup_done_mask; + uint32_t bus_irq_error_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; +}; + +/* + * struct cam_tfe_bus: + * + * @Brief: Bus interface structure + * + * @bus_priv: Private data of bus + * @hw_ops: Hardware interface functions + * @bottom_half_handler: Bottom Half handler function + */ +struct cam_tfe_bus { + void *bus_priv; + struct cam_hw_ops hw_ops; + CAM_BUS_HANDLER_BOTTOM_HALF bottom_half_handler; +}; + +/* + * cam_tfe_bus_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 + * @core_data: Core data pointer used for top irq config + * @tfe_bus: Pointer to tfe_bus structure which will be filled + * and returned on successful initialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_bus_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + void *core_data, + struct cam_tfe_bus **tfe_bus); + +/* + * cam_tfe_bus_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @tfe_bus: Pointer to tfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_bus_deinit(struct cam_tfe_bus **tfe_bus); + +#endif /* _CAM_TFE_BUS_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c new file mode 100644 index 000000000000..bc60eb05f551 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -0,0 +1,2529 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "cam_cdm_util.h" +#include "cam_tasklet_util.h" +#include "cam_isp_hw_mgr_intf.h" +#include "cam_tfe_soc.h" +#include "cam_tfe_core.h" +#include "cam_tfe_bus.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + +static const char drv_name[] = "tfe"; + +#define CAM_TFE_HW_RESET_HW_AND_REG_VAL 0x1 +#define CAM_TFE_HW_RESET_HW_VAL 0x10000 +#define CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 +#define CAM_TFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX 2 +#define CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 + +struct cam_tfe_top_common_data { + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *hw_intf; + struct cam_tfe_top_reg_offset_common *common_reg; + struct cam_tfe_reg_dump_data *reg_dump_data; +}; + +struct cam_tfe_top_priv { + struct cam_tfe_top_common_data common_data; + struct cam_isp_resource_node in_rsrc[CAM_TFE_TOP_IN_PORT_MAX]; + unsigned long hw_clk_rate; + struct cam_axi_vote applied_axi_vote; + struct cam_axi_vote req_axi_vote[CAM_TFE_TOP_IN_PORT_MAX]; + unsigned long req_clk_rate[CAM_TFE_TOP_IN_PORT_MAX]; + struct cam_axi_vote last_vote[CAM_TFE_TOP_IN_PORT_MAX * + CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES]; + uint32_t last_counter; + uint64_t total_bw_applied; + enum cam_tfe_bw_control_action + axi_vote_control[CAM_TFE_TOP_IN_PORT_MAX]; + uint32_t irq_prepared_mask[3]; + void *tasklet_info; +}; + +struct cam_tfe_camif_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_tfe_top_reg_offset_common *common_reg; + struct cam_tfe_camif_reg *camif_reg; + struct cam_tfe_camif_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; + + + cam_hw_mgr_event_cb_func event_cb; + void *priv; + 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 camif_debug; + uint32_t camif_pd_enable; + uint32_t dual_tfe_sync_sel; +}; + +struct cam_tfe_rdi_data { + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_tfe_top_reg_offset_common *common_reg; + struct cam_tfe_rdi_reg *rdi_reg; + struct cam_tfe_rdi_reg_data *reg_data; + cam_hw_mgr_event_cb_func event_cb; + void *priv; + enum cam_isp_hw_sync_mode sync_mode; + uint32_t pix_pattern; +}; + +static int cam_tfe_validate_pix_pattern(uint32_t pattern) +{ + int rc; + + switch (pattern) { + case CAM_ISP_TFE_PATTERN_BAYER_RGRGRG: + case CAM_ISP_TFE_PATTERN_BAYER_GRGRGR: + case CAM_ISP_TFE_PATTERN_BAYER_BGBGBG: + case CAM_ISP_TFE_PATTERN_BAYER_GBGBGB: + case CAM_ISP_TFE_PATTERN_YUV_YCBYCR: + case CAM_ISP_TFE_PATTERN_YUV_YCRYCB: + case CAM_ISP_TFE_PATTERN_YUV_CBYCRY: + case CAM_ISP_TFE_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_tfe_get_evt_payload(struct cam_tfe_hw_core_info *core_info, + struct cam_tfe_irq_evt_payload **evt_payload) +{ + spin_lock(&core_info->spin_lock); + if (list_empty(&core_info->free_payload_list)) { + *evt_payload = NULL; + spin_unlock(&core_info->spin_lock); + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload, core id 0x%x", + core_info->core_index); + return -ENODEV; + } + + *evt_payload = list_first_entry(&core_info->free_payload_list, + struct cam_tfe_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + spin_unlock(&core_info->spin_lock); + + return 0; +} + +int cam_tfe_put_evt_payload(void *core_info, + struct cam_tfe_irq_evt_payload **evt_payload) +{ + struct cam_tfe_hw_core_info *tfe_core_info = core_info; + unsigned long flags; + + if (!core_info) { + CAM_ERR(CAM_ISP, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_ISP, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&tfe_core_info->spin_lock, flags); + (*evt_payload)->error_type = 0; + list_add_tail(&(*evt_payload)->list, &tfe_core_info->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&tfe_core_info->spin_lock, flags); + + return 0; +} + +int cam_tfe_get_hw_caps(void *hw_priv, void *get_hw_cap_args, + uint32_t arg_size) +{ + return -EPERM; +} + +void cam_tfe_get_timestamp(struct cam_isp_timestamp *time_stamp) +{ + struct timespec ts; + + ts = ktime_to_timespec(ktime_get_boottime()); + time_stamp->mono_time.tv_sec = ts.tv_sec; + time_stamp->mono_time.tv_usec = ts.tv_nsec/1000; +} + +int cam_tfe_irq_config(void *tfe_core_data, + uint32_t *irq_mask, uint32_t num_reg, bool enable) +{ + struct cam_tfe_hw_core_info *core_info; + struct cam_tfe_top_priv *top_priv; + struct cam_hw_soc_info *soc_info; + void __iomem *mem_base; + bool need_lock; + unsigned long flags = 0; + uint32_t i, val; + + if (!tfe_core_data) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Invalid core data"); + return -EINVAL; + } + + core_info = (struct cam_tfe_hw_core_info *)tfe_core_data; + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + soc_info = (struct cam_hw_soc_info *)top_priv->common_data.soc_info; + mem_base = soc_info->reg_map[TFE_CORE_BASE_IDX].mem_base; + + need_lock = !in_irq(); + if (need_lock) + spin_lock_irqsave(&core_info->spin_lock, flags); + + for (i = 0; i < num_reg; i++) { + val = cam_io_r_mb(mem_base + + core_info->tfe_hw_info->top_irq_mask[i]); + if (enable) + val |= irq_mask[i]; + else + val &= ~irq_mask[i]; + cam_io_w_mb(val, mem_base + + core_info->tfe_hw_info->top_irq_mask[i]); + } + if (need_lock) + spin_unlock_irqrestore(&core_info->spin_lock, flags); + + return 0; +} + +static void cam_tfe_log_error_irq_status( + struct cam_tfe_hw_core_info *core_info, + struct cam_tfe_top_priv *top_priv, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_hw_info *hw_info; + void __iomem *mem_base; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_soc_private *soc_private; + struct cam_tfe_camif_data *camif_data; + struct cam_tfe_rdi_data *rdi_data; + uint32_t i, val_0, val_1, val_2, val_3; + + hw_info = core_info->tfe_hw_info; + mem_base = top_priv->common_data.soc_info->reg_map[0].mem_base; + soc_info = top_priv->common_data.soc_info; + soc_private = top_priv->common_data.soc_info->soc_private; + + val_0 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_0); + val_1 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_1); + val_2 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_2); + val_3 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_3); + + CAM_INFO(CAM_ISP, "TOP IRQ[0]:0x%x IRQ[1]:0x%x IRQ[2]:0x%x", + evt_payload->irq_reg_val[0], evt_payload->irq_reg_val[1], + evt_payload->irq_reg_val[2]); + + CAM_INFO(CAM_ISP, "BUS IRQ[0]:0x%x BUS IRQ[1]:0x%x", + evt_payload->bus_irq_val[0], evt_payload->bus_irq_val[1]); + + CAM_INFO(CAM_ISP, "ccif violation:0x%x image size:0x%x overflow:0x%x", + evt_payload->ccif_violation_status, + evt_payload->image_size_violation_status, + evt_payload->overflow_status); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x20, true, &val_0); + CAM_INFO(CAM_ISP, "tfe_niu_MaxWr_Low offset 0x20 val 0x%x", + val_0); + + CAM_INFO(CAM_ISP, "Top debug [0]:0x%x [1]:0x%x [2]:0x%x [3]:0x%x", + val_0, val_1, val_2, val_3); + + val_0 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_pixel_count); + + val_1 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_line_count); + + val_2 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_stall_count); + + val_3 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_always_count); + + CAM_INFO(CAM_ISP, + "Top perf cnt pix:0x%x line:0x%x stall:0x%x always:0x%x", + val_0, val_1, val_2, val_3); + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if ((top_priv->in_rsrc[i].res_state != + CAM_ISP_RESOURCE_STATE_STREAMING)) + continue; + + if (top_priv->in_rsrc[i].res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + camif_data = (struct cam_tfe_camif_data *) + top_priv->in_rsrc[i].res_priv; + val_0 = cam_io_r(mem_base + + camif_data->camif_reg->debug_0); + val_1 = cam_io_r(mem_base + + camif_data->camif_reg->debug_1); + CAM_INFO(CAM_ISP, + "camif debug1:0x%x Height:0x%x, width:0x%x", + val_1, + ((val_0 >> 16) & 0x1FFF), + (val_0 & 0x1FFF)); + } else if ((top_priv->in_rsrc[i].res_id >= + CAM_ISP_HW_TFE_IN_RDI0) || + (top_priv->in_rsrc[i].res_id <= + CAM_ISP_HW_TFE_IN_RDI2)) { + rdi_data = (struct cam_tfe_rdi_data *) + top_priv->in_rsrc[i].res_priv; + val_0 = cam_io_r(mem_base + + rdi_data->rdi_reg->rdi_debug_0); + val_1 = cam_io_r(mem_base + + rdi_data->rdi_reg->rdi_debug_1); + CAM_INFO(CAM_ISP, + "RDI res id:%d debug1:0x%x Height:0x%x, width:0x%x", + top_priv->in_rsrc[i].res_id, + val_1, ((val_0 >> 16) & 0x1FFF), + (val_0 & 0x1FFF)); + } + } + val_0 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_stall_count); + + /* Check the overflow errors */ + if (evt_payload->irq_reg_val[0] & hw_info->error_irq_mask[0]) { + if (evt_payload->irq_reg_val[0] & BIT(8)) + CAM_INFO(CAM_ISP, "PP_FRAME_DROP"); + + if (evt_payload->irq_reg_val[0] & BIT(9)) + CAM_INFO(CAM_ISP, "RDI0_FRAME_DROP"); + + if (evt_payload->irq_reg_val[0] & BIT(10)) + CAM_INFO(CAM_ISP, "RDI1_FRAME_DROP"); + + if (evt_payload->irq_reg_val[0] & BIT(11)) + CAM_INFO(CAM_ISP, "RDI2_FRAME_DROP"); + + if (evt_payload->irq_reg_val[0] & BIT(16)) + CAM_INFO(CAM_ISP, "PP_OVERFLOW"); + + if (evt_payload->irq_reg_val[0] & BIT(17)) + CAM_INFO(CAM_ISP, "RDI0_OVERFLOW"); + + if (evt_payload->irq_reg_val[0] & BIT(18)) + CAM_INFO(CAM_ISP, "RDI1_OVERFLOW"); + + if (evt_payload->irq_reg_val[0] & BIT(19)) + CAM_INFO(CAM_ISP, "RDI2_OVERFLOW"); + } + + /* Check the violation errors */ + if (evt_payload->irq_reg_val[2] & hw_info->error_irq_mask[2]) { + if (evt_payload->irq_reg_val[2] & BIT(0)) + CAM_INFO(CAM_ISP, "PP_CAMIF_VIOLATION"); + + if (evt_payload->irq_reg_val[2] & BIT(1)) + CAM_INFO(CAM_ISP, "PP_VIOLATION"); + + if (evt_payload->irq_reg_val[2] & BIT(2)) + CAM_INFO(CAM_ISP, "RDI0_CAMIF_VIOLATION"); + + if (evt_payload->irq_reg_val[2] & BIT(3)) + CAM_INFO(CAM_ISP, "RDI1_CAMIF_VIOLATION"); + + if (evt_payload->irq_reg_val[2] & BIT(4)) + CAM_INFO(CAM_ISP, "RDI2_CAMIF_VIOLATION"); + + if (evt_payload->irq_reg_val[2] & BIT(5)) + CAM_INFO(CAM_ISP, "DIAG_VIOLATION"); + + val_0 = cam_io_r(mem_base + + top_priv->common_data.common_reg->violation_status); + CAM_INFO(CAM_ISP, "TOP Violation status:0x%x", val_0); + } + + /* Check the bus errors */ + if (evt_payload->bus_irq_val[0] & BIT(29)) + CAM_INFO(CAM_ISP, "CONS_VIOLATION"); + + if (evt_payload->bus_irq_val[0] & BIT(30)) + CAM_INFO(CAM_ISP, "VIOLATION val 0x%x", + evt_payload->ccif_violation_status); + + if (evt_payload->bus_irq_val[0] & BIT(31)) + CAM_INFO(CAM_ISP, "IMAGE_SIZE_VIOLATION val :0x%x", + evt_payload->image_size_violation_status); + + /* clear the bus irq overflow status*/ + if (evt_payload->overflow_status) + cam_io_w_mb(1, mem_base + + core_info->tfe_hw_info->bus_overflow_clear_cmd); + +} + +static int cam_tfe_error_irq_bottom_half( + struct cam_tfe_hw_core_info *core_info, + struct cam_tfe_top_priv *top_priv, + struct cam_tfe_irq_evt_payload *evt_payload, + cam_hw_mgr_event_cb_func event_cb, + void *event_cb_priv) +{ + struct cam_isp_hw_event_info evt_info; + struct cam_tfe_hw_info *hw_info; + + hw_info = core_info->tfe_hw_info; + evt_info.hw_idx = core_info->core_index; + evt_info.res_type = CAM_ISP_RESOURCE_TFE_IN; + + if (evt_payload->irq_reg_val[0] & hw_info->error_irq_mask[0]) { + CAM_ERR(CAM_ISP, "TFE:%d Overflow error irq_status[0]:%x", + core_info->core_index, + evt_payload->irq_reg_val[0]); + + evt_info.err_type = CAM_TFE_IRQ_STATUS_OVERFLOW; + cam_tfe_log_error_irq_status(core_info, top_priv, evt_payload); + if (event_cb) + event_cb(event_cb_priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + else + CAM_ERR(CAM_ISP, "TFE:%d invalid eventcb:", + core_info->core_index); + } + + if (evt_payload->irq_reg_val[2] & hw_info->error_irq_mask[2]) { + CAM_ERR(CAM_ISP, "TFE:%d Violation error irq_status[2]:%x", + core_info->core_index, evt_payload->irq_reg_val[2]); + + evt_info.err_type = CAM_TFE_IRQ_STATUS_VIOLATION; + cam_tfe_log_error_irq_status(core_info, top_priv, evt_payload); + + if (event_cb) + event_cb(event_cb_priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + else + CAM_ERR(CAM_ISP, "TFE:%d invalid eventcb:", + core_info->core_index); + } + + return 0; +} + +static int cam_tfe_rdi_irq_bottom_half( + struct cam_isp_resource_node *rdi_node, + bool epoch_process, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_rdi_data *rdi_priv; + struct cam_isp_hw_event_info evt_info; + struct cam_hw_info *hw_info; + + rdi_priv = (struct cam_tfe_rdi_data *)rdi_node->res_priv; + hw_info = rdi_node->hw_intf->hw_priv; + + evt_info.hw_idx = rdi_node->hw_intf->hw_idx; + evt_info.res_id = rdi_node->res_id; + evt_info.res_type = rdi_node->res_type; + + if ((!epoch_process) && (evt_payload->irq_reg_val[1] & + rdi_priv->reg_data->eof_irq_mask)) { + CAM_DBG(CAM_ISP, "Received EOF"); + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + } + + if ((!epoch_process) && (evt_payload->irq_reg_val[1] & + rdi_priv->reg_data->sof_irq_mask)) { + CAM_DBG(CAM_ISP, "Received SOF"); + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + } + + if (epoch_process && (evt_payload->irq_reg_val[1] & + rdi_priv->reg_data->epoch0_irq_mask)) { + CAM_DBG(CAM_ISP, "Received EPOCH0"); + + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); + } + + return 0; +} + +static int cam_tfe_camif_irq_bottom_half( + struct cam_isp_resource_node *camif_node, + bool epoch_process, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_camif_data *camif_priv; + struct cam_isp_hw_event_info evt_info; + struct cam_hw_info *hw_info; + uint32_t val; + + camif_priv = camif_node->res_priv; + hw_info = camif_node->hw_intf->hw_priv; + evt_info.hw_idx = camif_node->hw_intf->hw_idx; + evt_info.res_id = camif_node->res_id; + evt_info.res_type = camif_node->res_type; + + if ((!epoch_process) && (evt_payload->irq_reg_val[1] & + camif_priv->reg_data->eof_irq_mask)) { + CAM_DBG(CAM_ISP, "Received EOF"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + } + + if ((!epoch_process) && (evt_payload->irq_reg_val[1] & + camif_priv->reg_data->sof_irq_mask)) { + if ((camif_priv->enable_sof_irq_debug) && + (camif_priv->irq_debug_cnt <= + CAM_TFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "Received SOF"); + + camif_priv->irq_debug_cnt++; + if (camif_priv->irq_debug_cnt == + CAM_TFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) { + camif_priv->enable_sof_irq_debug = + false; + camif_priv->irq_debug_cnt = 0; + } + } else + CAM_DBG(CAM_ISP, "Received SOF"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + } + + if (epoch_process && (evt_payload->irq_reg_val[1] & + camif_priv->reg_data->epoch0_irq_mask)) { + CAM_DBG(CAM_ISP, "Received EPOCH"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); + } + + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r(camif_priv->mem_base + + camif_priv->common_reg->diag_sensor_status_0); + CAM_DBG(CAM_ISP, "TFE_DIAG_SENSOR_STATUS: 0x%x", + camif_priv->mem_base, val); + } + + return 0; +} + +static int cam_tfe_irq_bottom_half(void *handler_priv, + void *evt_payload_priv) +{ + struct cam_tfe_hw_core_info *core_info; + struct cam_tfe_top_priv *top_priv; + struct cam_tfe_irq_evt_payload *evt_payload; + struct cam_tfe_camif_data *camif_priv; + struct cam_tfe_rdi_data *rdi_priv; + cam_hw_mgr_event_cb_func event_cb = NULL; + void *event_cb_priv = NULL; + uint32_t i; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, + "Invalid params handle_priv:%pK, evt_payload_priv:%pK", + handler_priv, evt_payload_priv); + return 0; + } + + core_info = (struct cam_tfe_hw_core_info *)handler_priv; + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + evt_payload = evt_payload_priv; + + /* process sof and eof */ + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if ((top_priv->in_rsrc[i].res_id == + CAM_ISP_HW_TFE_IN_CAMIF) && + (top_priv->in_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_STREAMING)) { + camif_priv = (struct cam_tfe_camif_data *) + top_priv->in_rsrc[i].res_priv; + event_cb = camif_priv->event_cb; + event_cb_priv = camif_priv->priv; + + if (camif_priv->reg_data->subscribe_irq_mask[1] & + evt_payload->irq_reg_val[1]) + cam_tfe_camif_irq_bottom_half( + &top_priv->in_rsrc[i], false, + evt_payload); + + } else if ((top_priv->in_rsrc[i].res_id >= + CAM_ISP_HW_TFE_IN_RDI0) && + (top_priv->in_rsrc[i].res_id <= + CAM_ISP_HW_TFE_IN_RDI2) && + (top_priv->in_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_STREAMING)) { + rdi_priv = (struct cam_tfe_rdi_data *) + top_priv->in_rsrc[i].res_priv; + event_cb = rdi_priv->event_cb; + event_cb_priv = rdi_priv->priv; + + if (rdi_priv->reg_data->subscribe_irq_mask[1] & + evt_payload->irq_reg_val[1]) + cam_tfe_rdi_irq_bottom_half( + &top_priv->in_rsrc[i], false, + evt_payload); + } + } + + /* process the irq errors */ + cam_tfe_error_irq_bottom_half(core_info, top_priv, evt_payload, + event_cb, event_cb_priv); + + /* process the reg update in the bus */ + if (evt_payload->irq_reg_val[0] & + core_info->tfe_hw_info->bus_reg_irq_mask[0]) { + core_info->tfe_bus->bottom_half_handler( + core_info->tfe_bus->bus_priv, true, evt_payload); + } + + /* process the epoch */ + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if ((top_priv->in_rsrc[i].res_id == + CAM_ISP_HW_TFE_IN_CAMIF) && + (top_priv->in_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_STREAMING)) { + camif_priv = (struct cam_tfe_camif_data *) + top_priv->in_rsrc[i].res_priv; + if (camif_priv->reg_data->subscribe_irq_mask[1] & + evt_payload->irq_reg_val[1]) + cam_tfe_camif_irq_bottom_half( + &top_priv->in_rsrc[i], true, + evt_payload); + } else if ((top_priv->in_rsrc[i].res_id >= + CAM_ISP_HW_TFE_IN_RDI0) && + (top_priv->in_rsrc[i].res_id <= + CAM_ISP_HW_TFE_IN_RDI2) && + (top_priv->in_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_STREAMING)) { + rdi_priv = (struct cam_tfe_rdi_data *) + top_priv->in_rsrc[i].res_priv; + if (rdi_priv->reg_data->subscribe_irq_mask[1] & + evt_payload->irq_reg_val[1]) + cam_tfe_rdi_irq_bottom_half( + &top_priv->in_rsrc[i], true, + evt_payload); + } + } + + /* process the bufone */ + if (evt_payload->irq_reg_val[0] & + core_info->tfe_hw_info->bus_reg_irq_mask[0]) { + core_info->tfe_bus->bottom_half_handler( + core_info->tfe_bus->bus_priv, false, evt_payload); + } + + cam_tfe_put_evt_payload(core_info, &evt_payload); + + return 0; +} + +static int cam_tfe_irq_err_top_half( + struct cam_tfe_hw_core_info *core_info, + void __iomem *mem_base, + uint32_t *irq_status) +{ + uint32_t i; + + if (irq_status[0] & core_info->tfe_hw_info->error_irq_mask[0] || + irq_status[2] & core_info->tfe_hw_info->error_irq_mask[2]) { + CAM_ERR(CAM_ISP, + "Encountered Error: tfe:%d: Irq_status0=0x%x status2=0x%x", + core_info->core_index, irq_status[0], + irq_status[2]); + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + cam_io_w(0, mem_base + + core_info->tfe_hw_info->top_irq_mask[i]); + + cam_io_w_mb(core_info->tfe_hw_info->global_clear_bitmask, + mem_base + core_info->tfe_hw_info->top_irq_cmd); + } + + return 0; +} + +irqreturn_t cam_tfe_irq(int irq_num, void *data) +{ + struct cam_hw_info *tfe_hw; + struct cam_tfe_hw_core_info *core_info; + struct cam_tfe_top_priv *top_priv; + void __iomem *mem_base; + struct cam_tfe_irq_evt_payload *evt_payload; + uint32_t top_irq_status[CAM_TFE_TOP_IRQ_REG_NUM] = {0}; + uint32_t bus_irq_status[CAM_TFE_BUS_MAX_IRQ_REGISTERS] = {0}; + uint32_t i, ccif_violation = 0, overflow_status = 0; + uint32_t image_sz_violation = 0; + void *bh_cmd = NULL; + int rc = -EINVAL; + + if (!data) + return IRQ_NONE; + + tfe_hw = (struct cam_hw_info *)data; + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + mem_base = top_priv->common_data.soc_info->reg_map[0].mem_base; + + if (tfe_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_ERR(CAM_ISP, "TFE:%d hw is not powered up", + core_info->core_index); + return IRQ_HANDLED; + } + + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + top_irq_status[i] = cam_io_r(mem_base + + core_info->tfe_hw_info->top_irq_status[i]); + + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + cam_io_w(top_irq_status[i], mem_base + + core_info->tfe_hw_info->top_irq_clear[i]); + + CAM_DBG(CAM_ISP, "TFE:%d IRQ status_0:0x%x status_1:0x%x status_2:0x%x", + core_info->core_index, top_irq_status[0], + top_irq_status[1], top_irq_status[2]); + + if (top_irq_status[0] & core_info->tfe_hw_info->bus_reg_irq_mask[0]) { + for (i = 0; i < CAM_TFE_BUS_MAX_IRQ_REGISTERS; i++) + bus_irq_status[i] = cam_io_r(mem_base + + core_info->tfe_hw_info->bus_irq_status[i]); + + for (i = 0; i < CAM_TFE_BUS_MAX_IRQ_REGISTERS; i++) + cam_io_w(bus_irq_status[i], mem_base + + core_info->tfe_hw_info->bus_irq_clear[i]); + + ccif_violation = cam_io_r(mem_base + + core_info->tfe_hw_info->bus_violation_reg); + overflow_status = cam_io_r(mem_base + + core_info->tfe_hw_info->bus_overflow_reg); + image_sz_violation = cam_io_r(mem_base + + core_info->tfe_hw_info->bus_image_size_vilation_reg); + + cam_io_w(core_info->tfe_hw_info->global_clear_bitmask, + mem_base + core_info->tfe_hw_info->bus_irq_cmd); + + CAM_DBG(CAM_ISP, "TFE:%d BUS IRQ status_0:0x%x status_1:0x%x", + core_info->core_index, bus_irq_status[0], + bus_irq_status[1]); + } + + cam_io_w_mb(core_info->tfe_hw_info->global_clear_bitmask, + mem_base + core_info->tfe_hw_info->top_irq_cmd); + + /* check reset */ + if ((top_irq_status[0] & core_info->tfe_hw_info->reset_irq_mask[0]) || + (top_irq_status[1] & + core_info->tfe_hw_info->reset_irq_mask[1]) || + (top_irq_status[2] & + core_info->tfe_hw_info->reset_irq_mask[2])) { + /* Reset ack */ + complete(&core_info->reset_complete); + return IRQ_HANDLED; + } + + /* Check the irq errors */ + cam_tfe_irq_err_top_half(core_info, mem_base, top_irq_status); + + rc = cam_tfe_get_evt_payload(core_info, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No tasklet_cmd is free in queue"); + CAM_ERR_RATE_LIMIT(CAM_ISP, "IRQ status0=0x%x status2=0x%x", + top_irq_status[0], top_irq_status[1]); + goto end; + } + + cam_tfe_get_timestamp(&evt_payload->ts); + + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + evt_payload->irq_reg_val[i] = top_irq_status[i]; + + for (i = 0; i < CAM_TFE_BUS_MAX_IRQ_REGISTERS; i++) + evt_payload->bus_irq_val[i] = bus_irq_status[i]; + + evt_payload->ccif_violation_status = ccif_violation; + evt_payload->overflow_status = overflow_status; + evt_payload->image_size_violation_status = image_sz_violation; + + evt_payload->core_index = core_info->core_index; + evt_payload->core_info = core_info; + + rc = tasklet_bh_api.get_bh_payload_func( + top_priv->tasklet_info, &bh_cmd); + if (rc || !bh_cmd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No payload, IRQ handling frozen"); + cam_tfe_put_evt_payload(core_info, &evt_payload); + goto end; + } + + tasklet_bh_api.bottom_half_enqueue_func( + top_priv->tasklet_info, + bh_cmd, + core_info, + evt_payload, + cam_tfe_irq_bottom_half); + +end: + return IRQ_HANDLED; + +} + +static int cam_tfe_top_set_hw_clk_rate( + struct cam_tfe_top_priv *top_priv) +{ + struct cam_hw_soc_info *soc_info = NULL; + int i, rc = 0; + unsigned long max_clk_rate = 0; + + soc_info = top_priv->common_data.soc_info; + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if (top_priv->req_clk_rate[i] > max_clk_rate) + max_clk_rate = top_priv->req_clk_rate[i]; + } + if (max_clk_rate == top_priv->hw_clk_rate) + return 0; + + CAM_DBG(CAM_ISP, "TFE:%d Clock name=%s idx=%d clk=%llu", + top_priv->common_data.soc_info->index, + soc_info->clk_name[soc_info->src_clk_idx], + soc_info->src_clk_idx, max_clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); + + if (!rc) + top_priv->hw_clk_rate = max_clk_rate; + else + CAM_ERR(CAM_ISP, "TFE:%d set src clock rate:%lld failed, rc=%d", + top_priv->common_data.soc_info->index, max_clk_rate, rc); + + return rc; +} + +static struct cam_axi_vote *cam_tfe_top_delay_bw_reduction( + struct cam_tfe_top_priv *top_priv, + uint64_t *to_be_applied_bw) +{ + uint32_t i, j; + int vote_idx = -1; + uint64_t max_bw = 0; + uint64_t total_bw; + struct cam_axi_vote *curr_l_vote; + + for (i = 0; i < (CAM_TFE_TOP_IN_PORT_MAX * + CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) { + total_bw = 0; + curr_l_vote = &top_priv->last_vote[i]; + for (j = 0; j < curr_l_vote->num_paths; j++) { + if (total_bw > + (U64_MAX - + curr_l_vote->axi_path[j].camnoc_bw)) { + CAM_ERR(CAM_ISP, "Overflow at idx: %d", j); + return NULL; + } + + total_bw += curr_l_vote->axi_path[j].camnoc_bw; + } + + if (total_bw > max_bw) { + vote_idx = i; + max_bw = total_bw; + } + } + + if (vote_idx < 0) + return NULL; + + *to_be_applied_bw = max_bw; + + return &top_priv->last_vote[vote_idx]; +} + +static int cam_tfe_top_set_axi_bw_vote( + struct cam_tfe_top_priv *top_priv, + bool start_stop) +{ + struct cam_axi_vote agg_vote = {0}; + struct cam_axi_vote *to_be_applied_axi_vote = NULL; + struct cam_hw_soc_info *soc_info = top_priv->common_data.soc_info; + struct cam_tfe_soc_private *soc_private = soc_info->soc_private; + int rc = 0; + uint32_t i; + uint32_t num_paths = 0; + uint64_t total_bw_new_vote = 0; + bool bw_unchanged = true; + bool apply_bw_update = false; + + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if (top_priv->axi_vote_control[i] == + CAM_TFE_BW_CONTROL_INCLUDE) { + if (num_paths + + top_priv->req_axi_vote[i].num_paths > + CAM_CPAS_MAX_PATHS_PER_CLIENT) { + CAM_ERR(CAM_ISP, + "Required paths(%d) more than max(%d)", + num_paths + + top_priv->req_axi_vote[i].num_paths, + CAM_CPAS_MAX_PATHS_PER_CLIENT); + return -EINVAL; + } + + memcpy(&agg_vote.axi_path[num_paths], + &top_priv->req_axi_vote[i].axi_path[0], + top_priv->req_axi_vote[i].num_paths * + sizeof( + struct cam_axi_per_path_bw_vote)); + num_paths += top_priv->req_axi_vote[i].num_paths; + } + } + + agg_vote.num_paths = num_paths; + + for (i = 0; i < agg_vote.num_paths; i++) { + CAM_DBG(CAM_PERF, + "tfe[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + top_priv->last_counter, + cam_cpas_axi_util_path_type_to_string( + agg_vote.axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + agg_vote.axi_path[i].transac_type), + agg_vote.axi_path[i].camnoc_bw, + agg_vote.axi_path[i].mnoc_ab_bw, + agg_vote.axi_path[i].mnoc_ib_bw); + + total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; + } + + memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, + sizeof(struct cam_axi_vote)); + top_priv->last_counter = (top_priv->last_counter + 1) % + (CAM_TFE_TOP_IN_PORT_MAX * + CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES); + + if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + bw_unchanged = false; + + CAM_DBG(CAM_PERF, + "tfe[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, + bw_unchanged, start_stop); + + if (bw_unchanged) { + CAM_DBG(CAM_ISP, "BW config unchanged"); + return 0; + } + + if (start_stop) { + /* need to vote current request immediately */ + to_be_applied_axi_vote = &agg_vote; + /* Reset everything, we can start afresh */ + memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * + (CAM_TFE_TOP_IN_PORT_MAX * + CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES)); + top_priv->last_counter = 0; + top_priv->last_vote[top_priv->last_counter] = agg_vote; + top_priv->last_counter = (top_priv->last_counter + 1) % + (CAM_TFE_TOP_IN_PORT_MAX * + CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES); + } else { + /* + * Find max bw request in last few frames. This will the bw + * that we want to vote to CPAS now. + */ + to_be_applied_axi_vote = + cam_tfe_top_delay_bw_reduction(top_priv, + &total_bw_new_vote); + if (!to_be_applied_axi_vote) { + CAM_ERR(CAM_ISP, "to_be_applied_axi_vote is NULL"); + return -EINVAL; + } + } + + for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "tfe[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + cam_cpas_axi_util_path_type_to_string( + to_be_applied_axi_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + to_be_applied_axi_vote->axi_path[i].transac_type), + to_be_applied_axi_vote->axi_path[i].camnoc_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); + } + + if ((to_be_applied_axi_vote->num_paths != + top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + apply_bw_update = true; + + CAM_DBG(CAM_PERF, + "tfe[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, + apply_bw_update, start_stop); + + if (apply_bw_update) { + rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, + to_be_applied_axi_vote); + if (!rc) { + memcpy(&top_priv->applied_axi_vote, + to_be_applied_axi_vote, + sizeof(struct cam_axi_vote)); + top_priv->total_bw_applied = total_bw_new_vote; + } else { + CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc); + } + } + + return rc; +} + +static int cam_tfe_top_get_base(struct cam_tfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + uint32_t size = 0; + uint32_t mem_base = 0; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error 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; + } + + size = cdm_util_ops->cdm_required_size_changebase(); + /* 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; + } + + mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE( + top_priv->common_data.soc_info, TFE_CORE_BASE_IDX); + + cdm_util_ops->cdm_write_changebase( + cdm_args->cmd.cmd_buf_addr, mem_base); + cdm_args->cmd.used_bytes = (size * 4); + + return 0; +} + +static int cam_tfe_top_get_reg_update( + struct cam_tfe_top_priv *top_priv, + 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_tfe_camif_data *camif_rsrc_data = NULL; + struct cam_tfe_rdi_data *rdi_rsrc_data = NULL; + struct cam_isp_resource_node *in_res; + + 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; + } + + in_res = cdm_args->res; + 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; + } + + if (in_res->res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + camif_rsrc_data = in_res->res_priv; + reg_val_pair[0] = camif_rsrc_data->camif_reg->reg_update_cmd; + reg_val_pair[1] = + camif_rsrc_data->reg_data->reg_update_cmd_data; + } else if ((in_res->res_id >= CAM_ISP_HW_TFE_IN_RDI0) && + (in_res->res_id <= CAM_ISP_HW_TFE_IN_RDI2)) { + rdi_rsrc_data = in_res->res_priv; + reg_val_pair[0] = rdi_rsrc_data->rdi_reg->reg_update_cmd; + reg_val_pair[1] = rdi_rsrc_data->reg_data->reg_update_cmd_data; + } + + 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; +} + +static int cam_tfe_top_clock_update( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_clock_update_args *clk_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int i, rc = 0; + + clk_update = + (struct cam_tfe_clock_update_args *)cmd_args; + res = clk_update->node_res; + + if (!res || !res->hw_intf->hw_priv) { + CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + return -EINVAL; + } + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_TFE_IN || + res->res_id >= CAM_ISP_HW_TFE_IN_MAX) { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if (top_priv->in_rsrc[i].res_id == res->res_id) { + top_priv->req_clk_rate[i] = clk_update->clk_rate; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_DBG(CAM_ISP, + "TFE:%d Not ready to set clocks yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else + rc = cam_tfe_top_set_hw_clk_rate(top_priv); + + return rc; +} + +static int cam_tfe_top_bw_update( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_bw_update_args *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_update = (struct cam_tfe_bw_update_args *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_TFE_IN || + res->res_id >= CAM_ISP_HW_TFE_IN_MAX) { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_ISP_HW_TFE_IN_MAX; i++) { + if (top_priv->in_rsrc[i].res_id == res->res_id) { + memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_TFE_BW_CONTROL_INCLUDE; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "TFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_tfe_top_set_axi_bw_vote(top_priv, false); + } + + return rc; +} + +static int cam_tfe_top_bw_control( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_bw_control_args *bw_ctrl = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_ctrl = (struct cam_tfe_bw_control_args *)cmd_args; + res = bw_ctrl->node_res; + + if (!res || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_TFE_IN || + res->res_id >= CAM_ISP_HW_TFE_IN_MAX) { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if (top_priv->in_rsrc[i].res_id == res->res_id) { + top_priv->axi_vote_control[i] = bw_ctrl->action; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "TFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_tfe_top_set_axi_bw_vote(top_priv, true); + } + + return rc; +} + +static int cam_tfe_top_get_reg_dump( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_hw_get_cmd_update *reg_dump_cmd = cmd_args; + struct cam_tfe_soc_private *soc_private; + struct cam_tfe_reg_dump_data *reg_dump_data; + struct cam_hw_soc_info *soc_info; + void __iomem *mem_base; + int i, j, num_reg_dump_entries; + uint32_t val_0, val_1, val_2, val_3, wm_offset, start_offset; + uint32_t end_offset, lut_word_size, lut_size, lut_bank_sel, lut_dmi_reg; + + if (!reg_dump_cmd) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + if ((reg_dump_cmd->res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) || + (reg_dump_cmd->res->res_state == + CAM_ISP_RESOURCE_STATE_AVAILABLE)) + return 0; + + soc_info = top_priv->common_data.soc_info; + soc_private = top_priv->common_data.soc_info->soc_private; + mem_base = soc_info->reg_map[TFE_CORE_BASE_IDX].mem_base; + CAM_INFO(CAM_ISP, "dump tfe:%d registers", + top_priv->common_data.hw_intf->hw_idx); + + reg_dump_data = top_priv->common_data.reg_dump_data; + num_reg_dump_entries = reg_dump_data->num_reg_dump_entries; + for (i = 0; i < num_reg_dump_entries; i++) { + start_offset = reg_dump_data->reg_entry[i].start_offset; + end_offset = reg_dump_data->reg_entry[i].end_offset; + + for (j = start_offset; (j + 0xc) <= end_offset; j += 0x10) { + val_0 = cam_io_r_mb(mem_base + j); + val_1 = cam_io_r_mb(mem_base + j + 4); + val_2 = cam_io_r_mb(mem_base + j + 0x8); + val_3 = cam_io_r_mb(mem_base + j + 0xc); + CAM_INFO(CAM_ISP, "0x%04x=0x%08x 0x%08x 0x%08x 0x%08x", + j, val_0, val_1, val_2, val_3); + } + } + + num_reg_dump_entries = reg_dump_data->num_lut_dump_entries; + for (i = 0; i < num_reg_dump_entries; i++) { + lut_bank_sel = reg_dump_data->lut_entry[i].lut_bank_sel; + lut_size = reg_dump_data->lut_entry[i].lut_addr_size; + lut_word_size = reg_dump_data->lut_entry[i].lut_word_size; + lut_dmi_reg = reg_dump_data->lut_entry[i].dmi_reg_offset; + + cam_io_w_mb(lut_bank_sel, mem_base + lut_dmi_reg + 4); + cam_io_w_mb(0, mem_base + 0xC28); + + for (j = 0; j < lut_size; j++) { + val_0 = cam_io_r_mb(mem_base + 0xC30); + CAM_INFO(CAM_ISP, "Bank%d:0x%x LO: 0x%x", + lut_bank_sel, j, val_0); + } + } + /* No mem selected */ + cam_io_w_mb(0, mem_base + 0xC24); + cam_io_w_mb(0, mem_base + 0xC28); + + start_offset = reg_dump_data->bus_start_addr; + end_offset = reg_dump_data->bus_write_top_end_addr; + + CAM_INFO(CAM_ISP, "bus start addr:0x%x end_offset:0x%x", + start_offset, end_offset); + + for (i = start_offset; (i + 0xc) <= end_offset; i += 0x10) { + val_0 = cam_io_r_mb(mem_base + i); + val_1 = cam_io_r_mb(mem_base + i + 4); + val_2 = cam_io_r_mb(mem_base + i + 0x8); + val_3 = cam_io_r_mb(mem_base + i + 0xc); + CAM_INFO(CAM_ISP, "0x%04x=0x%08x 0x%08x 0x%08x 0x%08x", + i, val_0, val_1, val_2, val_3); + } + + wm_offset = reg_dump_data->bus_client_start_addr; + + CAM_INFO(CAM_ISP, "bus wm offset:0x%x", + wm_offset); + + for (j = 0; j < reg_dump_data->num_bus_clients; j++) { + for (i = 0x0; (i + 0xc) <= 0x3C; i += 0x10) { + val_0 = cam_io_r_mb(mem_base + wm_offset + i); + val_1 = cam_io_r_mb(mem_base + wm_offset + i + 4); + val_2 = cam_io_r_mb(mem_base + wm_offset + i + 0x8); + val_3 = cam_io_r_mb(mem_base + wm_offset + i + 0xc); + CAM_INFO(CAM_ISP, "0x%04x=0x%08x 0x%08x 0x%08x 0x%08x", + (wm_offset + i), val_0, val_1, val_2, val_3); + } + for (i = 0x60; (i + 0xc) <= 0x80; i += 0x10) { + val_0 = cam_io_r_mb(mem_base + wm_offset + i); + val_1 = cam_io_r_mb(mem_base + wm_offset + i + 4); + val_2 = cam_io_r_mb(mem_base + wm_offset + i + 0x8); + val_3 = cam_io_r_mb(mem_base + wm_offset + i + 0xc); + CAM_INFO(CAM_ISP, "0x%04x=0x%08x 0x%08x 0x%08x 0x%08x", + (wm_offset + i), val_0, val_1, val_2, val_3); + } + wm_offset += reg_dump_data->bus_client_offset; + } + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x20, true, &val_0); + CAM_INFO(CAM_ISP, "tfe_niu_MaxWr_Low offset 0x20 val 0x%x", + val_0); + + /* dump the clock votings */ + CAM_INFO(CAM_ISP, "TFE:%d clk=%ld", + top_priv->common_data.hw_intf->hw_idx, + top_priv->hw_clk_rate); + + return 0; +} + +static int cam_tfe_camif_irq_reg_dump( + struct cam_tfe_hw_core_info *core_info, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_top_priv *top_priv; + struct cam_isp_hw_get_cmd_update *cmd_update; + struct cam_isp_resource_node *camif_res = NULL; + void __iomem *mem_base; + uint32_t i; + + int rc = 0; + + if (!cmd_args) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments\n"); + return -EINVAL; + } + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + cmd_update = (struct cam_isp_hw_get_cmd_update *)cmd_args; + camif_res = cmd_update->res; + mem_base = top_priv->common_data.soc_info->reg_map[0].mem_base; + if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) || + (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)) { + CAM_ERR(CAM_ISP, "Error! Invalid state\n"); + return 0; + } + + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) { + CAM_INFO(CAM_ISP, + "Core Id =%d TOP IRQ status[%d ] val 0x%x", + core_info->core_index, i, + cam_io_r_mb(mem_base + + core_info->tfe_hw_info->top_irq_status[i])); + } + + for (i = 0; i < CAM_TFE_BUS_MAX_IRQ_REGISTERS; i++) { + CAM_INFO(CAM_ISP, + "Core Id =%d BUS IRQ status[%d ] val:0x%x", + core_info->core_index, i, + cam_io_r_mb(mem_base + + core_info->tfe_hw_info->bus_irq_status[i])); + } + + return rc; +} + +int cam_tfe_top_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size) +{ + struct cam_tfe_top_priv *top_priv; + struct cam_tfe_acquire_args *args; + struct cam_tfe_hw_tfe_in_acquire_args *acquire_args; + struct cam_tfe_camif_data *camif_data; + struct cam_tfe_rdi_data *rdi_data; + uint32_t i; + int rc = -EINVAL; + + if (!device_priv || !reserve_args) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_tfe_top_priv *)device_priv; + args = (struct cam_tfe_acquire_args *)reserve_args; + acquire_args = &args->tfe_in; + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + CAM_DBG(CAM_ISP, "i :%d res_id:%d state:%d", i, + acquire_args->res_id, top_priv->in_rsrc[i].res_state); + + if ((top_priv->in_rsrc[i].res_id == acquire_args->res_id) && + (top_priv->in_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_AVAILABLE)) { + rc = cam_tfe_validate_pix_pattern( + acquire_args->in_port->pix_pattern); + if (rc) + return rc; + + if (acquire_args->res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + camif_data = (struct cam_tfe_camif_data *) + top_priv->in_rsrc[i].res_priv; + camif_data->pix_pattern = + acquire_args->in_port->pix_pattern; + camif_data->dsp_mode = + acquire_args->in_port->dsp_mode; + camif_data->first_pixel = + acquire_args->in_port->left_start; + camif_data->last_pixel = + acquire_args->in_port->left_end; + camif_data->first_line = + acquire_args->in_port->line_start; + camif_data->last_line = + acquire_args->in_port->line_end; + camif_data->camif_pd_enable = + acquire_args->camif_pd_enable; + camif_data->dual_tfe_sync_sel = + acquire_args->dual_tfe_sync_sel_idx; + camif_data->sync_mode = acquire_args->sync_mode; + camif_data->event_cb = args->event_cb; + camif_data->priv = args->priv; + + CAM_DBG(CAM_ISP, + "TFE:%d pix_pattern:%d dsp_mode=%d", + top_priv->in_rsrc[i].hw_intf->hw_idx, + camif_data->pix_pattern, + camif_data->dsp_mode); + } else { + rdi_data = (struct cam_tfe_rdi_data *) + top_priv->in_rsrc[i].res_priv; + rdi_data->pix_pattern = + acquire_args->in_port->pix_pattern; + rdi_data->sync_mode = acquire_args->sync_mode; + rdi_data->event_cb = args->event_cb; + rdi_data->priv = args->priv; + } + + top_priv->in_rsrc[i].cdm_ops = acquire_args->cdm_ops; + top_priv->in_rsrc[i].tasklet_info = args->tasklet; + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_RESERVED; + top_priv->tasklet_info = args->tasklet; + acquire_args->rsrc_node = + &top_priv->in_rsrc[i]; + rc = 0; + break; + } + } + + return rc; +} + +int cam_tfe_top_release(void *device_priv, + void *release_args, uint32_t arg_size) +{ + struct cam_tfe_top_priv *top_priv; + struct cam_isp_resource_node *in_res; + + if (!device_priv || !release_args) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_tfe_top_priv *)device_priv; + in_res = (struct cam_isp_resource_node *)release_args; + + CAM_DBG(CAM_ISP, "TFE:%d resource id:%d in state %d", + in_res->hw_intf->hw_idx, in_res->res_id, + in_res->res_state); + if (in_res->res_state < CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "TFE:%d Error Resource Invalid res_state :%d", + in_res->hw_intf->hw_idx, in_res->res_state); + return -EINVAL; + } + in_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + in_res->cdm_ops = NULL; + in_res->tasklet_info = NULL; + in_res->rdi_only_ctx = 0; + + return 0; +} + +static int cam_tfe_camif_resource_start( + struct cam_tfe_hw_core_info *core_info, + struct cam_isp_resource_node *camif_res) +{ + struct cam_tfe_camif_data *rsrc_data; + struct cam_tfe_soc_private *soc_private; + uint32_t val = 0; + uint32_t epoch0_irq_mask; + uint32_t epoch1_irq_mask; + uint32_t computed_epoch_line_cfg; + + if (!camif_res || !core_info) { + CAM_ERR(CAM_ISP, "Error Invalid input arguments"); + return -EINVAL; + } + + if (camif_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "TFE:%d Error Invalid camif res res_state:%d", + core_info->core_index, camif_res->res_state); + return -EINVAL; + } + + rsrc_data = (struct cam_tfe_camif_data *)camif_res->res_priv; + soc_private = rsrc_data->soc_info->soc_private; + + if (!soc_private) { + CAM_ERR(CAM_ISP, "TFE:%d Error soc_private NULL", + core_info->core_index); + return -ENODEV; + } + + /* Camif module config */ + val = cam_io_r(rsrc_data->mem_base + + rsrc_data->camif_reg->module_cfg); + val &= ~(rsrc_data->reg_data->pixel_pattern_mask); + val |= (rsrc_data->pix_pattern << + rsrc_data->reg_data->pixel_pattern_shift); + val |= (1 << rsrc_data->reg_data->module_enable_shift); + val |= (1 << rsrc_data->reg_data->pix_out_enable_shift); + if (rsrc_data->camif_pd_enable) + val |= (1 << rsrc_data->reg_data->pdaf_output_enable_shift); + + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->camif_reg->module_cfg); + + CAM_DBG(CAM_ISP, "TFE:%d camif module config val:%d", + core_info->core_index, val); + + /* Config tfe core*/ + val = 0; + if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + val = (1 << rsrc_data->reg_data->extern_reg_update_shift); + + if ((rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) || + (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_MASTER)) { + val |= (1 << rsrc_data->reg_data->dual_tfe_pix_en_shift); + val |= ((rsrc_data->dual_tfe_sync_sel + 1) << + rsrc_data->reg_data->dual_tfe_sync_sel_shift); + } + + if (!rsrc_data->camif_pd_enable) + val |= (1 << rsrc_data->reg_data->camif_pd_rdi2_src_sel_shift); + + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_0); + + CAM_DBG(CAM_ISP, "TFE:%d core_cfg 0 val:0x%x", core_info->core_index, + val); + + val = cam_io_r(rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_1); + val &= ~BIT(0); + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_1); + CAM_DBG(CAM_ISP, "TFE:%d core_cfg 1 val:0x%x", core_info->core_index, + val); + + /* 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->camif_reg->epoch_irq_cfg); + CAM_DBG(CAM_ISP, "TFE:%d first_line: %u\n" + "last_line: %u\n" + "epoch_line_cfg: 0x%x", + core_info->core_index, + rsrc_data->first_line, + rsrc_data->last_line, + computed_epoch_line_cfg); + + camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Reg Update */ + cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, + rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd); + CAM_DBG(CAM_ISP, "hw id:%d RUP val:%d", camif_res->hw_intf->hw_idx, + 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; + + if (rsrc_data->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->common_reg->diag_config); + val |= rsrc_data->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->diag_config); + } + + /* Enable the irq */ + cam_tfe_irq_config(core_info, rsrc_data->reg_data->subscribe_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, true); + + /* Program perf counters */ + val = (1 << rsrc_data->reg_data->perf_cnt_start_cmd_shift) | + (1 << rsrc_data->reg_data->perf_cnt_continuous_shift) | + (1 << rsrc_data->reg_data->perf_client_sel_shift) | + (1 << rsrc_data->reg_data->perf_window_start_shift) | + (2 << rsrc_data->reg_data->perf_window_end_shift); + cam_io_w_mb(val, + rsrc_data->mem_base + rsrc_data->common_reg->perf_cnt_cfg); + CAM_DBG(CAM_ISP, "TFE:%d perf_cfg val:%d", core_info->core_index, + val); + + /* Enable the top debug registers */ + cam_io_w_mb(0x1, + rsrc_data->mem_base + rsrc_data->common_reg->debug_cfg); + + CAM_DBG(CAM_ISP, "Start Camif TFE %d Done", core_info->core_index); + return 0; +} + +int cam_tfe_top_start(struct cam_tfe_hw_core_info *core_info, + void *start_args, uint32_t arg_size) +{ + struct cam_tfe_top_priv *top_priv; + struct cam_isp_resource_node *in_res; + struct cam_hw_info *hw_info = NULL; + struct cam_tfe_rdi_data *rsrc_rdi_data; + uint32_t val; + int rc = 0; + + if (!start_args) { + CAM_ERR(CAM_ISP, "TFE:%d Error Invalid input arguments", + core_info->core_index); + return -EINVAL; + } + + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + in_res = (struct cam_isp_resource_node *)start_args; + hw_info = (struct cam_hw_info *)in_res->hw_intf->hw_priv; + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "TFE:%d HW not powered up", + core_info->core_index); + rc = -EPERM; + goto end; + } + + rc = cam_tfe_top_set_hw_clk_rate(top_priv); + if (rc) { + CAM_ERR(CAM_ISP, "TFE:%d set_hw_clk_rate failed, rc=%d", + hw_info->soc_info.index, rc); + return rc; + } + + rc = cam_tfe_top_set_axi_bw_vote(top_priv, true); + if (rc) { + CAM_ERR(CAM_ISP, "TFE:%d set_axi_bw_vote failed, rc=%d", + core_info->core_index, rc); + return rc; + } + + if (in_res->res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + cam_tfe_camif_resource_start(core_info, in_res); + } else if (in_res->res_id >= CAM_ISP_HW_TFE_IN_RDI0 || + in_res->res_id <= CAM_ISP_HW_TFE_IN_RDI2) { + rsrc_rdi_data = (struct cam_tfe_rdi_data *) in_res->res_priv; + val = (rsrc_rdi_data->pix_pattern << + rsrc_rdi_data->reg_data->pixel_pattern_shift); + + val |= (1 << rsrc_rdi_data->reg_data->rdi_out_enable_shift); + cam_io_w_mb(val, rsrc_rdi_data->mem_base + + rsrc_rdi_data->rdi_reg->rdi_module_config); + + /* Epoch config */ + cam_io_w_mb(rsrc_rdi_data->reg_data->epoch_line_cfg, + rsrc_rdi_data->mem_base + + rsrc_rdi_data->rdi_reg->rdi_epoch_irq); + + /* Reg Update */ + cam_io_w_mb(rsrc_rdi_data->reg_data->reg_update_cmd_data, + rsrc_rdi_data->mem_base + + rsrc_rdi_data->rdi_reg->reg_update_cmd); + in_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + /* Enable the irq */ + if (in_res->rdi_only_ctx) + cam_tfe_irq_config(core_info, + rsrc_rdi_data->reg_data->subscribe_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, true); + + CAM_DBG(CAM_ISP, "TFE:%d Start RDI %d", core_info->core_index, + in_res->res_id - CAM_ISP_HW_TFE_IN_RDI0); + } + + core_info->irq_err_config_cnt++; + if (core_info->irq_err_config_cnt == 1) + cam_tfe_irq_config(core_info, + core_info->tfe_hw_info->error_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, true); + +end: + return rc; +} + +int cam_tfe_top_stop(struct cam_tfe_hw_core_info *core_info, + void *stop_args, uint32_t arg_size) +{ + struct cam_tfe_top_priv *top_priv; + struct cam_isp_resource_node *in_res; + struct cam_hw_info *hw_info = NULL; + struct cam_tfe_camif_data *camif_data; + struct cam_tfe_rdi_data *rsrc_rdi_data; + uint32_t val = 0; + int i, rc = 0; + + if (!stop_args) { + CAM_ERR(CAM_ISP, "TFE:%d Error Invalid input arguments", + core_info->core_index); + return -EINVAL; + } + + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + in_res = (struct cam_isp_resource_node *)stop_args; + hw_info = (struct cam_hw_info *)in_res->hw_intf->hw_priv; + + if (in_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED || + in_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) + return 0; + + if (in_res->res_id == CAM_ISP_HW_TFE_IN_CAMIF) { + camif_data = (struct cam_tfe_camif_data *)in_res->res_priv; + + cam_io_w_mb(0, camif_data->mem_base + + camif_data->camif_reg->module_cfg); + + cam_tfe_irq_config(core_info, + camif_data->reg_data->subscribe_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, false); + + if (in_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + in_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + val = cam_io_r_mb(camif_data->mem_base + + camif_data->common_reg->diag_config); + if (val & camif_data->reg_data->enable_diagnostic_hw) { + val &= ~camif_data->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, camif_data->mem_base + + camif_data->common_reg->diag_config); + } + } else if ((in_res->res_id >= CAM_ISP_HW_TFE_IN_RDI0) && + (in_res->res_id <= CAM_ISP_HW_TFE_IN_RDI2)) { + rsrc_rdi_data = (struct cam_tfe_rdi_data *) in_res->res_priv; + cam_io_w_mb(0x0, rsrc_rdi_data->mem_base + + rsrc_rdi_data->rdi_reg->rdi_module_config); + + if (in_res->rdi_only_ctx) + cam_tfe_irq_config(core_info, + rsrc_rdi_data->reg_data->subscribe_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, false); + + if (in_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + in_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + } else { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res id:%d", + core_info->core_index, in_res->res_id); + return -EINVAL; + } + + if (!rc) { + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + if (top_priv->in_rsrc[i].res_id == in_res->res_id) { + top_priv->req_clk_rate[i] = 0; + memset(&top_priv->req_axi_vote[i], 0, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_TFE_BW_CONTROL_EXCLUDE; + break; + } + } + } + + core_info->irq_err_config_cnt--; + if (!core_info->irq_err_config_cnt) + cam_tfe_irq_config(core_info, + core_info->tfe_hw_info->error_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, false); + + return rc; +} + +int cam_tfe_top_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + struct cam_tfe_hw_core_info *core_info) +{ + struct cam_tfe_top_priv *top_priv = NULL; + struct cam_tfe_top_hw_info *hw_info = top_hw_info; + struct cam_tfe_soc_private *soc_private = NULL; + struct cam_tfe_camif_data *camif_priv = NULL; + struct cam_tfe_rdi_data *rdi_priv = NULL; + int i, j, rc = 0; + + top_priv = kzalloc(sizeof(struct cam_tfe_top_priv), + GFP_KERNEL); + if (!top_priv) { + CAM_DBG(CAM_ISP, "TFE:%DError Failed to alloc for tfe_top_priv", + core_info->core_index); + rc = -ENOMEM; + goto end; + } + core_info->top_priv = top_priv; + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "TFE:%d Error soc_private NULL", + core_info->core_index); + rc = -ENODEV; + goto free_tfe_top_priv; + } + + top_priv->hw_clk_rate = 0; + memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * + (CAM_TFE_TOP_IN_PORT_MAX * + CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES)); + top_priv->last_counter = 0; + + for (i = 0, j = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + top_priv->in_rsrc[i].res_type = CAM_ISP_RESOURCE_TFE_IN; + top_priv->in_rsrc[i].hw_intf = hw_intf; + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + top_priv->req_clk_rate[i] = 0; + memset(&top_priv->req_axi_vote[i], 0, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_TFE_BW_CONTROL_EXCLUDE; + + if (hw_info->in_port[i] == CAM_TFE_CAMIF_VER_1_0) { + top_priv->in_rsrc[i].res_id = + CAM_ISP_HW_TFE_IN_CAMIF; + + camif_priv = kzalloc(sizeof(struct cam_tfe_camif_data), + GFP_KERNEL); + if (!camif_priv) { + CAM_DBG(CAM_ISP, + "TFE:%dError Failed to alloc for camif_priv", + core_info->core_index); + goto free_tfe_top_priv; + } + + top_priv->in_rsrc[i].res_priv = camif_priv; + + camif_priv->mem_base = + soc_info->reg_map[TFE_CORE_BASE_IDX].mem_base; + camif_priv->camif_reg = + hw_info->camif_hw_info.camif_reg; + camif_priv->common_reg = hw_info->common_reg; + camif_priv->reg_data = + hw_info->camif_hw_info.reg_data; + camif_priv->hw_intf = hw_intf; + camif_priv->soc_info = soc_info; + + } else if (hw_info->in_port[i] == + CAM_TFE_RDI_VER_1_0) { + top_priv->in_rsrc[i].res_id = + CAM_ISP_HW_TFE_IN_RDI0 + j; + + rdi_priv = kzalloc(sizeof(struct cam_tfe_rdi_data), + GFP_KERNEL); + if (!rdi_priv) { + CAM_DBG(CAM_ISP, + "TFE:%d Error Failed to alloc for rdi_priv", + core_info->core_index); + goto deinit_resources; + } + + top_priv->in_rsrc[i].res_priv = rdi_priv; + + rdi_priv->mem_base = + soc_info->reg_map[TFE_CORE_BASE_IDX].mem_base; + rdi_priv->hw_intf = hw_intf; + rdi_priv->common_reg = hw_info->common_reg; + rdi_priv->rdi_reg = + hw_info->rdi_hw_info[j].rdi_reg; + rdi_priv->reg_data = + hw_info->rdi_hw_info[j++].reg_data; + } else { + CAM_WARN(CAM_ISP, "TFE:%d Invalid inport type: %u", + core_info->core_index, hw_info->in_port[i]); + } + } + + top_priv->common_data.soc_info = soc_info; + top_priv->common_data.hw_intf = hw_intf; + top_priv->common_data.common_reg = hw_info->common_reg; + top_priv->common_data.reg_dump_data = &hw_info->reg_dump_data; + + return rc; + +deinit_resources: + for (--i; i >= 0; i--) { + + top_priv->in_rsrc[i].start = NULL; + top_priv->in_rsrc[i].stop = NULL; + top_priv->in_rsrc[i].process_cmd = NULL; + top_priv->in_rsrc[i].top_half_handler = NULL; + top_priv->in_rsrc[i].bottom_half_handler = NULL; + + if (!top_priv->in_rsrc[i].res_priv) + continue; + + kfree(top_priv->in_rsrc[i].res_priv); + top_priv->in_rsrc[i].res_priv = NULL; + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + } +free_tfe_top_priv: + kfree(core_info->top_priv); + core_info->top_priv = NULL; +end: + return rc; +} + + +int cam_tfe_top_deinit(struct cam_tfe_top_priv *top_priv) +{ + int i, rc = 0; + + if (!top_priv) { + CAM_ERR(CAM_ISP, "Error Invalid input"); + return -EINVAL; + } + + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + + top_priv->in_rsrc[i].start = NULL; + top_priv->in_rsrc[i].stop = NULL; + top_priv->in_rsrc[i].process_cmd = NULL; + top_priv->in_rsrc[i].top_half_handler = NULL; + top_priv->in_rsrc[i].bottom_half_handler = NULL; + + if (!top_priv->in_rsrc[i].res_priv) { + CAM_ERR(CAM_ISP, "Error res_priv is NULL"); + return -ENODEV; + } + + kfree(top_priv->in_rsrc[i].res_priv); + top_priv->in_rsrc[i].res_priv = NULL; + } + + return rc; +} + +int cam_tfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) +{ + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_tfe_top_priv *top_priv = NULL; + struct cam_tfe_hw_info *hw_info = NULL; + void __iomem *mem_base; + uint32_t *reset_reg_args = reset_core_args; + uint32_t i, reset_reg_val, irq_status[3]; + int rc; + + CAM_DBG(CAM_ISP, "Enter"); + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + soc_info = &tfe_hw->soc_info; + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + top_priv = core_info->top_priv; + hw_info = core_info->tfe_hw_info; + mem_base = tfe_hw->soc_info.reg_map[TFE_CORE_BASE_IDX].mem_base; + + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + irq_status[i] = cam_io_r(mem_base + + core_info->tfe_hw_info->top_irq_status[i]); + + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + cam_io_w(irq_status[i], mem_base + + core_info->tfe_hw_info->top_irq_clear[i]); + + cam_io_w_mb(core_info->tfe_hw_info->global_clear_bitmask, + mem_base + core_info->tfe_hw_info->top_irq_cmd); + + /* Mask all irq registers */ + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) + cam_io_w(0, mem_base + + core_info->tfe_hw_info->top_irq_mask[i]); + + cam_tfe_irq_config(core_info, hw_info->reset_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, true); + + reinit_completion(&core_info->reset_complete); + + CAM_DBG(CAM_ISP, "calling RESET on tfe %d", soc_info->index); + + switch (*reset_reg_args) { + case CAM_TFE_HW_RESET_HW_AND_REG: + reset_reg_val = CAM_TFE_HW_RESET_HW_AND_REG_VAL; + break; + default: + reset_reg_val = CAM_TFE_HW_RESET_HW_VAL; + break; + } + + cam_io_w_mb(reset_reg_val, mem_base + + top_priv->common_data.common_reg->global_reset_cmd); + + CAM_DBG(CAM_ISP, "TFE:%d waiting for tfe reset complete", + core_info->core_index); + /* Wait for Completion or Timeout of 500ms */ + rc = wait_for_completion_timeout(&core_info->reset_complete, 500); + if (rc <= 0) { + CAM_ERR(CAM_ISP, "TFE:%d Error Reset Timeout", + core_info->core_index); + rc = -ETIMEDOUT; + } else { + rc = 0; + CAM_DBG(CAM_ISP, "TFE:%d reset complete done (%d)", + core_info->core_index, rc); + } + + CAM_DBG(CAM_ISP, "TFE:%d reset complete done (%d)", + core_info->core_index, rc); + + cam_tfe_irq_config(core_info, hw_info->reset_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, false); + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +int cam_tfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_tfe_top_priv *top_priv; + void __iomem *mem_base; + int rc = 0; + uint32_t reset_core_args = + CAM_TFE_HW_RESET_HW_AND_REG; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + soc_info = &tfe_hw->soc_info; + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + + mutex_lock(&tfe_hw->hw_mutex); + tfe_hw->open_count++; + if (tfe_hw->open_count > 1) { + mutex_unlock(&tfe_hw->hw_mutex); + CAM_DBG(CAM_ISP, "TFE:%d has already been initialized cnt %d", + core_info->core_index, tfe_hw->open_count); + return 0; + } + mutex_unlock(&tfe_hw->hw_mutex); + + /* Turn ON Regulators, Clocks and other SOC resources */ + rc = cam_tfe_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "Enable SOC failed"); + rc = -EFAULT; + goto decrement_open_cnt; + } + tfe_hw->hw_state = CAM_HW_STATE_POWER_UP; + + mem_base = tfe_hw->soc_info.reg_map[TFE_CORE_BASE_IDX].mem_base; + CAM_DBG(CAM_ISP, "TFE:%d Enable soc done", core_info->core_index); + + /* Do HW Reset */ + rc = cam_tfe_reset(hw_priv, &reset_core_args, sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "TFE:%d Reset Failed rc=%d", + core_info->core_index, rc); + goto disable_soc; + } + + top_priv->hw_clk_rate = 0; + core_info->irq_err_config_cnt = 0; + core_info->irq_err_config = false; + rc = core_info->tfe_bus->hw_ops.init(core_info->tfe_bus->bus_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_ISP, "TFE:%d Top HW init Failed rc=%d", + core_info->core_index, rc); + goto disable_soc; + } + + return rc; + +disable_soc: + cam_tfe_disable_soc_resources(soc_info); + tfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + +decrement_open_cnt: + mutex_lock(&tfe_hw->hw_mutex); + tfe_hw->open_count--; + mutex_unlock(&tfe_hw->hw_mutex); + return rc; +} + +int cam_tfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + int rc = 0; + uint32_t reset_core_args = + CAM_TFE_HW_RESET_HW_AND_REG; + + CAM_DBG(CAM_ISP, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + soc_info = &tfe_hw->soc_info; + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + + mutex_lock(&tfe_hw->hw_mutex); + if (!tfe_hw->open_count) { + mutex_unlock(&tfe_hw->hw_mutex); + CAM_ERR_RATE_LIMIT(CAM_ISP, "TFE:%d Error Unbalanced deinit", + core_info->core_index); + return -EFAULT; + } + tfe_hw->open_count--; + if (tfe_hw->open_count) { + mutex_unlock(&tfe_hw->hw_mutex); + CAM_DBG(CAM_ISP, "TFE:%d open_cnt non-zero =%d", + core_info->core_index, tfe_hw->open_count); + return 0; + } + mutex_unlock(&tfe_hw->hw_mutex); + + rc = core_info->tfe_bus->hw_ops.deinit(core_info->tfe_bus->bus_priv, + NULL, 0); + if (rc) + CAM_ERR(CAM_ISP, "TFE:%d Bus HW deinit Failed rc=%d", + core_info->core_index, rc); + + rc = cam_tfe_reset(hw_priv, &reset_core_args, sizeof(uint32_t)); + + /* Turn OFF Regulators, Clocks and other SOC resources */ + CAM_DBG(CAM_ISP, "TFE:%d Disable SOC resource", core_info->core_index); + rc = cam_tfe_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_ISP, " TFE:%d Disable SOC failed", + core_info->core_index); + + tfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + + CAM_DBG(CAM_ISP, "Exit"); + return rc; +} + +int cam_tfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) +{ + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_tfe_acquire_args *acquire; + int rc = -ENODEV; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_tfe_acquire_args))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + acquire = (struct cam_tfe_acquire_args *)reserve_args; + + CAM_DBG(CAM_ISP, "TFE:%d acquire res type: %d", + core_info->core_index, acquire->rsrc_type); + mutex_lock(&tfe_hw->hw_mutex); + if (acquire->rsrc_type == CAM_ISP_RESOURCE_TFE_IN) { + rc = cam_tfe_top_reserve(core_info->top_priv, + reserve_args, arg_size); + } else if (acquire->rsrc_type == CAM_ISP_RESOURCE_TFE_OUT) { + rc = core_info->tfe_bus->hw_ops.reserve( + core_info->tfe_bus->bus_priv, acquire, + sizeof(*acquire)); + } else { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res type:%d", + core_info->core_index, acquire->rsrc_type); + } + + mutex_unlock(&tfe_hw->hw_mutex); + + return rc; +} + + +int cam_tfe_release(void *hw_priv, void *release_args, uint32_t arg_size) +{ + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_isp_resource_node *isp_res; + int rc = -ENODEV; + + if (!hw_priv || !release_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + isp_res = (struct cam_isp_resource_node *) release_args; + + mutex_lock(&tfe_hw->hw_mutex); + if (isp_res->res_type == CAM_ISP_RESOURCE_TFE_IN) + rc = cam_tfe_top_release(core_info->top_priv, isp_res, + sizeof(*isp_res)); + else if (isp_res->res_type == CAM_ISP_RESOURCE_TFE_OUT) { + rc = core_info->tfe_bus->hw_ops.release( + core_info->tfe_bus->bus_priv, isp_res, + sizeof(*isp_res)); + } else { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res type:%d", + core_info->core_index, isp_res->res_type); + } + + mutex_unlock(&tfe_hw->hw_mutex); + + return rc; +} + +int cam_tfe_start(void *hw_priv, void *start_args, uint32_t arg_size) +{ + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_isp_resource_node *start_res; + + int rc = 0; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + start_res = (struct cam_isp_resource_node *)start_args; + core_info->tasklet_info = start_res->tasklet_info; + + mutex_lock(&tfe_hw->hw_mutex); + if (start_res->res_type == CAM_ISP_RESOURCE_TFE_IN) { + rc = cam_tfe_top_start(core_info, start_args, + arg_size); + if (rc) + CAM_ERR(CAM_ISP, "TFE:%d Start failed. type:%d", + core_info->core_index, start_res->res_type); + + } else if (start_res->res_type == CAM_ISP_RESOURCE_TFE_OUT) { + rc = core_info->tfe_bus->hw_ops.start(start_res, NULL, 0); + } else { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res type:%d", + core_info->core_index, start_res->res_type); + rc = -EFAULT; + } + + mutex_unlock(&tfe_hw->hw_mutex); + + return rc; +} + +int cam_tfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size) +{ + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_isp_resource_node *isp_res; + int rc = -EINVAL; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + isp_res = (struct cam_isp_resource_node *)stop_args; + + mutex_lock(&tfe_hw->hw_mutex); + if (isp_res->res_type == CAM_ISP_RESOURCE_TFE_IN) { + rc = cam_tfe_top_stop(core_info, isp_res, + sizeof(struct cam_isp_resource_node)); + } else if (isp_res->res_type == CAM_ISP_RESOURCE_TFE_OUT) { + rc = core_info->tfe_bus->hw_ops.stop(isp_res, NULL, 0); + } else { + CAM_ERR(CAM_ISP, "TFE:%d Invalid res type:%d", + core_info->core_index, isp_res->res_type); + } + + CAM_DBG(CAM_ISP, "TFE:%d stopped res type:%d res id:%d res_state:%d ", + core_info->core_index, isp_res->res_type, + isp_res->res_id, isp_res->res_state); + + mutex_unlock(&tfe_hw->hw_mutex); + + return rc; +} + +int cam_tfe_read(void *hw_priv, void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_tfe_write(void *hw_priv, void *write_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *tfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_tfe_hw_info *hw_info = NULL; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + soc_info = &tfe_hw->soc_info; + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + hw_info = core_info->tfe_hw_info; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_CHANGE_BASE: + rc = cam_tfe_top_get_base(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + rc = cam_tfe_top_get_reg_update(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_CLOCK_UPDATE: + rc = cam_tfe_top_clock_update(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_BW_UPDATE_V2: + rc = cam_tfe_top_bw_update(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_BW_CONTROL: + rc = cam_tfe_top_bw_control(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_GET_REG_DUMP: + rc = cam_tfe_top_get_reg_dump(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP: + rc = cam_tfe_camif_irq_reg_dump(core_info, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA: + *((struct cam_hw_soc_info **)cmd_args) = soc_info; + break; + case CAM_ISP_HW_CMD_GET_BUF_UPDATE: + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = core_info->tfe_bus->hw_ops.process_cmd( + core_info->tfe_bus->bus_priv, cmd_type, cmd_args, + arg_size); + break; + default: + CAM_ERR(CAM_ISP, "TFE:%d Invalid cmd type:%d", + core_info->core_index, cmd_type); + rc = -EINVAL; + break; + } + return rc; +} + +int cam_tfe_core_init(struct cam_tfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_tfe_hw_info *tfe_hw_info) +{ + int rc = -EINVAL; + int i; + + rc = cam_tfe_top_init(soc_info, hw_intf, tfe_hw_info->top_hw_info, + core_info); + if (rc) { + CAM_ERR(CAM_ISP, "TFE:%d Error cam_tfe_top_init failed", + core_info->core_index); + goto end; + } + + rc = cam_tfe_bus_init(soc_info, hw_intf, + tfe_hw_info->bus_hw_info, core_info, + &core_info->tfe_bus); + if (rc) { + CAM_ERR(CAM_ISP, "TFE:%d Error cam_tfe_bus_init failed", + core_info->core_index); + goto deinit_top; + } + + INIT_LIST_HEAD(&core_info->free_payload_list); + for (i = 0; i < CAM_TFE_EVT_MAX; i++) { + INIT_LIST_HEAD(&core_info->evt_payload[i].list); + list_add_tail(&core_info->evt_payload[i].list, + &core_info->free_payload_list); + } + + core_info->irq_err_config = false; + core_info->irq_err_config_cnt = 0; + spin_lock_init(&core_info->spin_lock); + init_completion(&core_info->reset_complete); + + return rc; + +deinit_top: + cam_tfe_top_deinit(core_info->top_priv); + +end: + return rc; +} + +int cam_tfe_core_deinit(struct cam_tfe_hw_core_info *core_info, + struct cam_tfe_hw_info *tfe_hw_info) +{ + int rc = -EINVAL; + int i; + unsigned long flags; + + spin_lock_irqsave(&core_info->spin_lock, flags); + + INIT_LIST_HEAD(&core_info->free_payload_list); + for (i = 0; i < CAM_TFE_EVT_MAX; i++) + INIT_LIST_HEAD(&core_info->evt_payload[i].list); + + rc = cam_tfe_bus_deinit(&core_info->tfe_bus); + if (rc) + CAM_ERR(CAM_ISP, "TFE:%d Error cam_tfe_bus_deinit failed rc=%d", + core_info->core_index, rc); + + rc = cam_tfe_top_deinit(core_info->top_priv); + kfree(core_info->top_priv); + core_info->top_priv = NULL; + + if (rc) + CAM_ERR(CAM_ISP, "Error cam_tfe_top_deinit failed rc=%d", rc); + + spin_unlock_irqrestore(&core_info->spin_lock, flags); + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h new file mode 100644 index 000000000000..d98a91901149 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_TFE_CORE_H_ +#define _CAM_TFE_CORE_H_ + +#include +#include "cam_hw_intf.h" +#include "cam_tfe_bus.h" +#include "cam_tfe_hw_intf.h" +#include "cam_tfe_irq.h" + +#define CAM_TFE_CAMIF_VER_1_0 0x10 +#define CAM_TFE_RDI_VER_1_0 0x1000 +#define CAM_TFE_TOP_1_0 0x1000 +#define CAM_TFE_TOP_IN_PORT_MAX 4 +#define CAM_TFE_RDI_MAX 4 + +#define CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS BIT(0) +#define CAM_TFE_EVT_MAX 256 + +#define CAM_TFE_MAX_REG_DUMP_ENTRIES 20 +#define CAM_TFE_MAX_LUT_DUMP_ENTRIES 10 + +enum cam_tfe_lut_word_size { + CAM_TFE_LUT_WORD_SIZE_32, + CAM_TFE_LUT_WORD_SIZE_64, + CAM_TFE_LUT_WORD_SIZE_MAX, +}; + +struct cam_tfe_reg_dump_entry { + uint32_t start_offset; + uint32_t end_offset; +}; + +struct cam_tfe_lut_dump_entry { + enum cam_tfe_lut_word_size lut_word_size; + uint32_t lut_bank_sel; + uint32_t lut_addr_size; + uint32_t dmi_reg_offset; +}; +struct cam_tfe_reg_dump_data { + uint32_t num_reg_dump_entries; + uint32_t num_lut_dump_entries; + uint32_t bus_start_addr; + uint32_t bus_write_top_end_addr; + uint32_t bus_client_start_addr; + uint32_t bus_client_offset; + uint32_t num_bus_clients; + struct cam_tfe_reg_dump_entry + reg_entry[CAM_TFE_MAX_REG_DUMP_ENTRIES]; + struct cam_tfe_lut_dump_entry + lut_entry[CAM_TFE_MAX_LUT_DUMP_ENTRIES]; +}; + +struct cam_tfe_top_reg_offset_common { + uint32_t hw_version; + uint32_t hw_capability; + uint32_t lens_feature; + uint32_t stats_feature; + uint32_t zoom_feature; + uint32_t global_reset_cmd; + uint32_t core_cgc_ctrl; + uint32_t ahb_cgc_ctrl; + uint32_t core_cfg_0; + uint32_t core_cfg_1; + uint32_t reg_update_cmd; + uint32_t diag_config; + uint32_t diag_sensor_status_0; + uint32_t diag_sensor_status_1; + uint32_t diag_sensor_frame_cnt_status; + uint32_t violation_status; + uint32_t stats_throttle_cnt_cfg_0; + uint32_t stats_throttle_cnt_cfg_1; + uint32_t debug_0; + uint32_t debug_1; + uint32_t debug_2; + uint32_t debug_3; + uint32_t debug_cfg; + uint32_t perf_cnt_cfg; + uint32_t perf_pixel_count; + uint32_t perf_line_count; + uint32_t perf_stall_count; + uint32_t perf_always_count; + uint32_t perf_count_status; +}; + +struct cam_tfe_camif_reg { + uint32_t hw_version; + uint32_t hw_status; + uint32_t module_cfg; + uint32_t pdaf_raw_crop_width_cfg; + uint32_t pdaf_raw_crop_height_cfg; + uint32_t line_skip_pattern; + uint32_t pixel_skip_pattern; + uint32_t period_cfg; + uint32_t irq_subsample_pattern; + uint32_t epoch_irq_cfg; + uint32_t debug_1; + uint32_t debug_0; + uint32_t test_bus_ctrl; + uint32_t spare; + uint32_t reg_update_cmd; +}; + +struct cam_tfe_camif_reg_data { + uint32_t extern_reg_update_mask; + uint32_t dual_tfe_pix_en_shift; + uint32_t extern_reg_update_shift; + uint32_t camif_pd_rdi2_src_sel_shift; + uint32_t dual_tfe_sync_sel_shift; + + uint32_t pixel_pattern_shift; + uint32_t pixel_pattern_mask; + uint32_t module_enable_shift; + uint32_t pix_out_enable_shift; + uint32_t pdaf_output_enable_shift; + + 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 epoch1_irq_mask; + uint32_t eof_irq_mask; + uint32_t reg_update_irq_mask; + uint32_t error_irq_mask0; + uint32_t error_irq_mask2; + uint32_t subscribe_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + + uint32_t enable_diagnostic_hw; + uint32_t perf_cnt_start_cmd_shift; + uint32_t perf_cnt_continuous_shift; + uint32_t perf_client_sel_shift; + uint32_t perf_window_start_shift; + uint32_t perf_window_end_shift; +}; + +struct cam_tfe_camif_hw_info { + struct cam_tfe_camif_reg *camif_reg; + struct cam_tfe_camif_reg_data *reg_data; +}; + +struct cam_tfe_rdi_reg { + uint32_t rdi_hw_version; + uint32_t rdi_hw_status; + uint32_t rdi_module_config; + uint32_t rdi_skip_period; + uint32_t rdi_irq_subsample_pattern; + uint32_t rdi_epoch_irq; + uint32_t rdi_debug_1; + uint32_t rdi_debug_0; + uint32_t rdi_test_bus_ctrl; + uint32_t rdi_spare; + uint32_t reg_update_cmd; +}; + +struct cam_tfe_rdi_reg_data { + uint32_t reg_update_cmd_data; + uint32_t epoch_line_cfg; + + uint32_t pixel_pattern_shift; + uint32_t pixel_pattern_mask; + uint32_t rdi_out_enable_shift; + + uint32_t sof_irq_mask; + uint32_t epoch0_irq_mask; + uint32_t epoch1_irq_mask; + uint32_t eof_irq_mask; + uint32_t error_irq_mask0; + uint32_t error_irq_mask2; + uint32_t subscribe_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t enable_diagnostic_hw; +}; + +struct cam_tfe_rdi_hw_info { + struct cam_tfe_rdi_reg *rdi_reg; + struct cam_tfe_rdi_reg_data *reg_data; +}; + +struct cam_tfe_top_hw_info { + struct cam_tfe_top_reg_offset_common *common_reg; + struct cam_tfe_camif_hw_info camif_hw_info; + struct cam_tfe_rdi_hw_info rdi_hw_info[CAM_TFE_RDI_MAX]; + uint32_t in_port[CAM_TFE_TOP_IN_PORT_MAX]; + struct cam_tfe_reg_dump_data reg_dump_data; +}; + +struct cam_tfe_hw_info { + uint32_t top_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t top_irq_clear[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t top_irq_status[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t top_irq_cmd; + uint32_t global_clear_bitmask; + + uint32_t bus_irq_mask[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_irq_clear[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_irq_status[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_irq_cmd; + + uint32_t bus_violation_reg; + uint32_t bus_overflow_reg; + uint32_t bus_image_size_vilation_reg; + uint32_t bus_overflow_clear_cmd; + uint32_t debug_status_top; + + uint32_t reset_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t error_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t bus_reg_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + + uint32_t top_version; + void *top_hw_info; + + uint32_t bus_version; + void *bus_hw_info; +}; + +struct cam_tfe_hw_core_info { + uint32_t core_index; + struct cam_tfe_hw_info *tfe_hw_info; + void *top_priv; + struct cam_tfe_bus *tfe_bus; + void *tasklet_info; + struct cam_tfe_irq_evt_payload evt_payload[CAM_TFE_EVT_MAX]; + struct list_head free_payload_list; + bool irq_err_config; + uint32_t irq_err_config_cnt; + spinlock_t spin_lock; + struct completion reset_complete; +}; + +int cam_tfe_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size); +int cam_tfe_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_tfe_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size); +int cam_tfe_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size); +int cam_tfe_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size); +int cam_tfe_release(void *device_priv, + void *reserve_args, uint32_t arg_size); +int cam_tfe_start(void *device_priv, + void *start_args, uint32_t arg_size); +int cam_tfe_stop(void *device_priv, + void *stop_args, uint32_t arg_size); +int cam_tfe_read(void *device_priv, + void *read_args, uint32_t arg_size); +int cam_tfe_write(void *device_priv, + void *write_args, uint32_t arg_size); +int cam_tfe_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); + +irqreturn_t cam_tfe_irq(int irq_num, void *data); + +int cam_tfe_core_init(struct cam_tfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_tfe_hw_info *tfe_hw_info); + +int cam_tfe_core_deinit(struct cam_tfe_hw_core_info *core_info, + struct cam_tfe_hw_info *tfe_hw_info); + +#endif /* _CAM_TFE_CORE_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c new file mode 100644 index 000000000000..112e8c741d86 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include "cam_tfe_dev.h" +#include "cam_tfe_core.h" +#include "cam_tfe_soc.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_tfe_hw_list[CAM_TFE_HW_NUM_MAX] = {0, 0, 0}; + +static char tfe_dev_name[8]; + +int cam_tfe_probe(struct platform_device *pdev) +{ + struct cam_hw_info *tfe_hw = NULL; + struct cam_hw_intf *tfe_hw_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + struct cam_tfe_hw_info *hw_info = NULL; + int rc = 0; + + tfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!tfe_hw_intf) { + rc = -ENOMEM; + goto end; + } + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &tfe_hw_intf->hw_idx); + + tfe_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!tfe_hw) { + rc = -ENOMEM; + goto free_tfe_hw_intf; + } + + memset(tfe_dev_name, 0, sizeof(tfe_dev_name)); + snprintf(tfe_dev_name, sizeof(tfe_dev_name), + "tfe%1u", tfe_hw_intf->hw_idx); + + tfe_hw->soc_info.pdev = pdev; + tfe_hw->soc_info.dev = &pdev->dev; + tfe_hw->soc_info.dev_name = tfe_dev_name; + tfe_hw_intf->hw_priv = tfe_hw; + tfe_hw_intf->hw_ops.get_hw_caps = cam_tfe_get_hw_caps; + tfe_hw_intf->hw_ops.init = cam_tfe_init_hw; + tfe_hw_intf->hw_ops.deinit = cam_tfe_deinit_hw; + tfe_hw_intf->hw_ops.reset = cam_tfe_reset; + tfe_hw_intf->hw_ops.reserve = cam_tfe_reserve; + tfe_hw_intf->hw_ops.release = cam_tfe_release; + tfe_hw_intf->hw_ops.start = cam_tfe_start; + tfe_hw_intf->hw_ops.stop = cam_tfe_stop; + tfe_hw_intf->hw_ops.read = cam_tfe_read; + tfe_hw_intf->hw_ops.write = cam_tfe_write; + tfe_hw_intf->hw_ops.process_cmd = cam_tfe_process_cmd; + tfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_TFE; + + CAM_DBG(CAM_ISP, "type %d index %d", + tfe_hw_intf->hw_type, tfe_hw_intf->hw_idx); + + platform_set_drvdata(pdev, tfe_hw_intf); + + tfe_hw->core_info = kzalloc(sizeof(struct cam_tfe_hw_core_info), + GFP_KERNEL); + if (!tfe_hw->core_info) { + CAM_DBG(CAM_ISP, "Failed to alloc for core"); + rc = -ENOMEM; + goto free_tfe_hw; + } + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "Of_match Failed"); + rc = -EINVAL; + goto free_core_info; + } + hw_info = (struct cam_tfe_hw_info *)match_dev->data; + core_info->tfe_hw_info = hw_info; + core_info->core_index = tfe_hw_intf->hw_idx; + + rc = cam_tfe_init_soc_resources(&tfe_hw->soc_info, cam_tfe_irq, + tfe_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Failed to init soc rc=%d", rc); + goto free_core_info; + } + + rc = cam_tfe_core_init(core_info, &tfe_hw->soc_info, + tfe_hw_intf, hw_info); + if (rc < 0) { + CAM_ERR(CAM_ISP, "Failed to init core rc=%d", rc); + goto deinit_soc; + } + + tfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&tfe_hw->hw_mutex); + spin_lock_init(&tfe_hw->hw_lock); + init_completion(&tfe_hw->hw_complete); + + if (tfe_hw_intf->hw_idx < CAM_TFE_HW_NUM_MAX) + cam_tfe_hw_list[tfe_hw_intf->hw_idx] = tfe_hw_intf; + + cam_tfe_init_hw(tfe_hw, NULL, 0); + cam_tfe_deinit_hw(tfe_hw, NULL, 0); + + CAM_DBG(CAM_ISP, "TFE%d probe successful", tfe_hw_intf->hw_idx); + + return rc; + +deinit_soc: + if (cam_tfe_deinit_soc_resources(&tfe_hw->soc_info)) + CAM_ERR(CAM_ISP, "Failed to deinit soc"); +free_core_info: + kfree(tfe_hw->core_info); +free_tfe_hw: + kfree(tfe_hw); +free_tfe_hw_intf: + kfree(tfe_hw_intf); +end: + return rc; +} + +int cam_tfe_remove(struct platform_device *pdev) +{ + struct cam_hw_info *tfe_hw = NULL; + struct cam_hw_intf *tfe_hw_intf = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + int rc = 0; + + tfe_hw_intf = platform_get_drvdata(pdev); + if (!tfe_hw_intf) { + CAM_ERR(CAM_ISP, "Error! No data in pdev"); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "type %d index %d", + tfe_hw_intf->hw_type, tfe_hw_intf->hw_idx); + + if (tfe_hw_intf->hw_idx < CAM_TFE_HW_NUM_MAX) + cam_tfe_hw_list[tfe_hw_intf->hw_idx] = NULL; + + tfe_hw = tfe_hw_intf->hw_priv; + if (!tfe_hw) { + CAM_ERR(CAM_ISP, "Error! HW data is NULL"); + rc = -ENODEV; + goto free_tfe_hw_intf; + } + + core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; + if (!core_info) { + CAM_ERR(CAM_ISP, "Error! core data NULL"); + rc = -EINVAL; + goto deinit_soc; + } + + rc = cam_tfe_core_deinit(core_info, core_info->tfe_hw_info); + if (rc < 0) + CAM_ERR(CAM_ISP, "Failed to deinit core rc=%d", rc); + + kfree(tfe_hw->core_info); + +deinit_soc: + rc = cam_tfe_deinit_soc_resources(&tfe_hw->soc_info); + if (rc < 0) + CAM_ERR(CAM_ISP, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&tfe_hw->hw_mutex); + kfree(tfe_hw); + + CAM_DBG(CAM_ISP, "TFE%d remove successful", tfe_hw_intf->hw_idx); + +free_tfe_hw_intf: + kfree(tfe_hw_intf); + + return rc; +} + +int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx) +{ + int rc = 0; + + if (cam_tfe_hw_list[hw_idx]) { + *tfe_hw = cam_tfe_hw_list[hw_idx]; + rc = 0; + } else { + *tfe_hw = NULL; + rc = -ENODEV; + } + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h new file mode 100644 index 000000000000..63ae1b17d73c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_DEV_H_ +#define _CAM_TFE_DEV_H_ + +#include + +/* + * cam_tfe_probe() + * + * @brief: Driver probe function called on Boot + * + * @pdev: Platform Device pointer + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_probe(struct platform_device *pdev); + +/* + * cam_tfe_remove() + * + * @brief: Driver remove function + * + * @pdev: Platform Device pointer + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_remove(struct platform_device *pdev); + +int cam_tfe_init_module(void); +void cam_tfe_exit_module(void); + +#endif /* _CAM_TFE_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h new file mode 100644 index 000000000000..dba62d7104de --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_IRQ_H_ +#define _CAM_TFE_IRQ_H_ + +#include + +#define CAM_TFE_TOP_IRQ_REG_NUM 3 + +/* + * cam_tfe_irq_config() + * + * @brief: Tfe hw irq configuration + * + * @tfe_core_data: tfe core pointer + * @irq_mask: Irq mask for enable interrupts or disable + * @num_reg: Number irq mask registers + * @enable: enable = 1, enable the given irq mask interrupts + * enable = 0 disable the given irq mask interrupts + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_irq_config(void *tfe_core_data, + uint32_t *irq_mask, uint32_t num_reg, bool enable); + + +#endif /* _CAM_TFE_IRQ_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c new file mode 100644 index 000000000000..6041c5e3f026 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_cpas_api.h" +#include "cam_tfe_soc.h" +#include "cam_debug_util.h" + +static bool cam_tfe_cpas_cb(uint32_t client_handle, void *userdata, + struct cam_cpas_irq_data *irq_data) +{ + bool error_handled = false; + + if (!irq_data) + return error_handled; + + CAM_DBG(CAM_ISP, "CPSS error type=%d ", + irq_data->irq_type); + + return error_handled; +} + +int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t tfe_irq_handler, void *irq_data) +{ + int rc = 0; + struct cam_tfe_soc_private *soc_private; + struct cam_cpas_register_params cpas_register_param; + + soc_private = kzalloc(sizeof(struct cam_tfe_soc_private), + GFP_KERNEL); + if (!soc_private) { + CAM_DBG(CAM_ISP, "Error! soc_private Alloc Failed"); + return -ENOMEM; + } + soc_info->soc_private = soc_private; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "Error! get DT properties failed rc=%d", rc); + goto free_soc_private; + } + + rc = cam_soc_util_get_option_clk_by_name(soc_info, + CAM_TFE_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 with rc %d", rc); + + rc = cam_soc_util_request_platform_resource(soc_info, tfe_irq_handler, + irq_data); + + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Error! Request platform resources failed rc=%d", rc); + goto free_soc_private; + } + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "tfe", + 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_tfe_cpas_cb; + cpas_register_param.userdata = soc_info; + rc = cam_cpas_register_client(&cpas_register_param); + if (rc) { + CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc); + goto release_soc; + } + + soc_private->cpas_handle = cpas_register_param.client_handle; + + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); +free_soc_private: + kfree(soc_private); + + return rc; +} + +int cam_tfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_tfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error! soc_info NULL"); + return -ENODEV; + } + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error! soc_private NULL"); + return -ENODEV; + } + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_ISP, "CPAS0 unregistration failed rc=%d", rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_ERR(CAM_ISP, + "Error! Release platform resource failed rc=%d", rc); + + + rc = cam_soc_util_clk_put(&soc_private->dsp_clk); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Error Put dsp clk failed rc=%d", rc); + + kfree(soc_private); + + return rc; +} + +int cam_tfe_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_tfe_soc_private *soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error! Invalid params"); + rc = -EINVAL; + goto end; + } + soc_private = soc_info->soc_private; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_IFE_VID; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = 10640000000L; + axi_vote.axi_path[0].mnoc_ab_bw = 10640000000L; + axi_vote.axi_path[0].mnoc_ib_bw = 10640000000L; + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_ISP, "Error! CPAS0 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) { + CAM_ERR(CAM_ISP, "Error! enable platform failed rc=%d", rc); + goto stop_cpas; + } + + return rc; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); +end: + return rc; +} + +int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name) +{ + int rc = 0; + struct cam_tfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) { + rc = cam_soc_util_clk_enable(soc_private->dsp_clk, + CAM_TFE_DSP_CLK_NAME, soc_private->dsp_clk_rate); + if (rc) + CAM_ERR(CAM_ISP, + "Error enable dsp clk failed rc=%d", rc); + } + + return rc; +} + +int cam_tfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name) +{ + int rc = 0; + struct cam_tfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) { + rc = cam_soc_util_clk_disable(soc_private->dsp_clk, + CAM_TFE_DSP_CLK_NAME); + if (rc) + CAM_ERR(CAM_ISP, + "Error enable dsp clk failed rc=%d", rc); + } + + return rc; +} + + +int cam_tfe_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_tfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error! Invalid params"); + rc = -EINVAL; + return rc; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) { + CAM_ERR(CAM_ISP, "Disable platform failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc); + return rc; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h new file mode 100644 index 000000000000..6e08a98fbbfa --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_SOC_H_ +#define _CAM_TFE_SOC_H_ + +#include "cam_soc_util.h" +#include "cam_isp_hw.h" + +#define CAM_TFE_DSP_CLK_NAME "tfe_dsp_clk" + +enum cam_cpas_handle_id { + CAM_CPAS_HANDLE_CAMIF, + CAM_CPAS_HANDLE_RAW, + CAM_CPAS_HANDLE_MAX, +}; + +/* + * struct cam_tfe_soc_private: + * + * @Brief: Private SOC data specific to TFE HW Driver + * + * @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_tfe_soc_private { + uint32_t cpas_handle; + uint32_t cpas_version; + struct clk *dsp_clk; + int32_t dsp_clk_index; + int32_t dsp_clk_rate; +}; + +/* + * cam_tfe_init_soc_resources() + * + * @Brief: Initialize SOC resources including private data + * + * @soc_info: Device soc information + * @handler: Irq handler function pointer + * @irq_data: Irq handler function Callback data + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t tfe_irq_handler, void *irq_data); + +/* + * cam_tfe_deinit_soc_resources() + * + * @Brief: Deinitialize SOC resources including private data + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_tfe_enable_soc_resources() + * + * @brief: Enable regulator, irq resources, start CPAS + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_tfe_disable_soc_resources() + * + * @brief: Disable regulator, irq resources, stop CPAS + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_tfe_soc_enable_clk() + * + * @brief: Enable clock with given name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to enable + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name); + +/* + * cam_tfe_soc_disable_dsp_clk() + * + * @brief: Disable clock with given name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to enable + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_tfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name); + +#endif /* _CAM_TFE_SOC_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile new file mode 100644 index 000000000000..f08acab1e1dc --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_top_tpg_dev.o cam_top_tpg_soc.o cam_top_tpg_core.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_top_tpg_v1.o \ No newline at end of file diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c new file mode 100644 index 000000000000..4ea425df1ea8 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c @@ -0,0 +1,671 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_top_tpg_core.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + + +static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = { + 0, + 3, + 1, + 2 +}; + +static int cam_top_tpg_get_format(uint32_t in_format, + uint32_t *tpg_encode_format) +{ + int rc = 0; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + *tpg_encode_format = 0; + break; + case CAM_FORMAT_MIPI_RAW_8: + *tpg_encode_format = 1; + break; + case CAM_FORMAT_MIPI_RAW_10: + *tpg_encode_format = 2; + break; + case CAM_FORMAT_MIPI_RAW_12: + *tpg_encode_format = 3; + break; + case CAM_FORMAT_MIPI_RAW_14: + *tpg_encode_format = 4; + break; + case CAM_FORMAT_MIPI_RAW_16: + *tpg_encode_format = 4; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported input encode format %d", + in_format); + rc = -EINVAL; + } + return rc; +} + +static int cam_top_tpg_get_hw_caps(void *hw_priv, + void *get_hw_cap_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw_caps *hw_caps; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + hw_caps = (struct cam_top_tpg_hw_caps *) get_hw_cap_args; + + hw_caps->major_version = tpg_hw->tpg_info->tpg_reg->major_version; + hw_caps->minor_version = tpg_hw->tpg_info->tpg_reg->minor_version; + hw_caps->version_incr = tpg_hw->tpg_info->tpg_reg->version_incr; + + CAM_DBG(CAM_ISP, + "TPG:%d major:%d minor:%d ver :%d", + tpg_hw->hw_intf->hw_idx, hw_caps->major_version, + hw_caps->minor_version, hw_caps->version_incr); + + return rc; +} + +static int cam_top_tpg_reserve(void *hw_priv, + void *reserve_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_hw_reserve_resource_args *reserv; + struct cam_top_tpg_cfg *tpg_data; + uint32_t encode_format = 0; + uint32_t i; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_top_tpg_hw_reserve_resource_args))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + reserv = (struct cam_top_tpg_hw_reserve_resource_args *)reserve_args; + + if (reserv->num_inport <= 0 || + reserv->num_inport > CAM_TOP_TPG_MAX_SUPPORTED_DT) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG: %u invalid input num port:%d", + tpg_hw->hw_intf->hw_idx, reserv->num_inport); + return -EINVAL; + } + + mutex_lock(&tpg_hw->hw_info->hw_mutex); + if (tpg_hw->tpg_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return -EINVAL; + } + + if ((reserv->in_port[0]->vc > 0xF) || + (reserv->in_port[0]->lane_num <= 0 || + reserv->in_port[0]->lane_num > 4) || + (reserv->in_port[0]->pix_pattern > 4) || + (reserv->in_port[0]->lane_type >= 2)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d %d %d", + tpg_hw->hw_intf->hw_idx, reserv->in_port[0]->vc, + reserv->in_port[0]->lane_num, + reserv->in_port[0]->pix_pattern, + reserv->in_port[0]->lane_type); + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return -EINVAL; + } + rc = cam_top_tpg_get_format(reserv->in_port[0]->format, + &encode_format); + if (rc) + goto error; + + CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx); + + tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; + tpg_data->vc_num = reserv->in_port[0]->vc; + tpg_data->phy_sel = reserv->in_port[0]->lane_type; + tpg_data->num_active_lanes = reserv->in_port[0]->lane_num; + tpg_data->h_blank_count = reserv->in_port[0]->sensor_hbi; + tpg_data->v_blank_count = reserv->in_port[0]->sensor_vbi; + tpg_data->pix_pattern = reserv->in_port[0]->pix_pattern; + tpg_data->dt_cfg[0].data_type = reserv->in_port[0]->dt; + tpg_data->dt_cfg[0].frame_height = reserv->in_port[0]->height; + if (reserv->in_port[0]->usage_type) + tpg_data->dt_cfg[0].frame_width = + ((reserv->in_port[0]->right_end - + reserv->in_port[0]->left_start) + 1); + else + tpg_data->dt_cfg[0].frame_width = + reserv->in_port[0]->left_width; + tpg_data->dt_cfg[0].encode_format = encode_format; + tpg_data->num_active_dts = 1; + + CAM_DBG(CAM_ISP, + "TPG:%u vc_num:%d dt:%d phy:%d lines:%d pattern:%d format:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->vc_num, tpg_data->dt_cfg[0].data_type, + tpg_data->phy_sel, tpg_data->num_active_lanes, + tpg_data->pix_pattern, + tpg_data->dt_cfg[0].encode_format); + + CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d h blank:%d v blank:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->dt_cfg[0].frame_height, + tpg_data->dt_cfg[0].frame_width, + tpg_data->h_blank_count, + tpg_data->v_blank_count); + + if (reserv->num_inport == 1) + goto end; + + for (i = 1; i < reserv->num_inport; i++) { + if ((tpg_data->vc_num != reserv->in_port[i]->vc) || + (tpg_data->phy_sel != reserv->in_port[i]->lane_type) || + (tpg_data->num_active_lanes != + reserv->in_port[i]->lane_num) || + (tpg_data->pix_pattern != + reserv->in_port[i]->pix_pattern)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "TPG: %u invalid DT config for tpg", + tpg_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto error; + } + rc = cam_top_tpg_get_format(reserv->in_port[0]->format, + &encode_format); + if (rc) + return rc; + + tpg_data->dt_cfg[i].data_type = reserv->in_port[i]->dt; + tpg_data->dt_cfg[i].frame_height = + reserv->in_port[i]->height; + tpg_data->dt_cfg[i].frame_width = + reserv->in_port[i]->left_width; + tpg_data->dt_cfg[i].encode_format = encode_format; + tpg_data->num_active_dts++; + + CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d dt:%d format:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->dt_cfg[i].frame_height, + tpg_data->dt_cfg[i].frame_width, + tpg_data->dt_cfg[i].data_type, + tpg_data->dt_cfg[i].encode_format); + + } +end: + reserv->node_res = &tpg_hw->tpg_res; + tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED; +error: + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + CAM_DBG(CAM_ISP, "exit rc %u", rc); + + return rc; +} + +static int cam_top_tpg_release(void *hw_priv, + void *release_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_cfg *tpg_data; + struct cam_isp_resource_node *tpg_res; + + if (!hw_priv || !release_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_res = (struct cam_isp_resource_node *)release_args; + + mutex_lock(&tpg_hw->hw_info->hw_mutex); + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE)) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, tpg_res->res_type, + tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + CAM_DBG(CAM_ISP, "TPG:%d res type :%d", + tpg_hw->hw_intf->hw_idx, tpg_res->res_type); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv; + memset(tpg_data, 0, sizeof(struct cam_top_tpg_cfg)); + +end: + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_top_tpg_init_hw(void *hw_priv, + void *init_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_isp_resource_node *tpg_res; + const struct cam_top_tpg_reg_offset *tpg_reg; + struct cam_hw_soc_info *soc_info; + uint32_t val, clk_lvl; + + if (!hw_priv || !init_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_res = (struct cam_isp_resource_node *)init_args; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + soc_info = &tpg_hw->hw_info->soc_info; + + if (tpg_res->res_type != CAM_ISP_RESOURCE_TPG) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid res type state %d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type); + return -EINVAL; + } + + CAM_DBG(CAM_ISP, "TPG:%d init HW res type :%d", + tpg_hw->hw_intf->hw_idx, tpg_res->res_type); + mutex_lock(&tpg_hw->hw_info->hw_mutex); + /* overflow check before increment */ + if (tpg_hw->hw_info->open_count == UINT_MAX) { + CAM_ERR(CAM_ISP, "TPG:%d Open count reached max", + tpg_hw->hw_intf->hw_idx); + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return -EINVAL; + } + + /* Increment ref Count */ + tpg_hw->hw_info->open_count++; + if (tpg_hw->hw_info->open_count > 1) { + CAM_DBG(CAM_ISP, "TPG hw has already been enabled"); + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return rc; + } + + rc = cam_soc_util_get_clk_level(soc_info, tpg_hw->clk_rate, + soc_info->src_clk_idx, &clk_lvl); + CAM_DBG(CAM_ISP, "TPG phy clock level %u", clk_lvl); + + rc = cam_top_tpg_enable_soc_resources(soc_info, clk_lvl); + if (rc) { + CAM_ERR(CAM_ISP, "TPG:%d Enable SOC failed", + tpg_hw->hw_intf->hw_idx); + goto err; + } + + tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP; + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + tpg_reg->tpg_hw_version); + CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x", + tpg_hw->hw_intf->hw_idx, val); + + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return rc; + +err: + tpg_hw->hw_info->open_count--; + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_top_tpg_deinit_hw(void *hw_priv, + void *deinit_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_isp_resource_node *tpg_res; + struct cam_hw_soc_info *soc_info; + + if (!hw_priv || !deinit_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG:Invalid arguments"); + return -EINVAL; + } + + tpg_res = (struct cam_isp_resource_node *)deinit_args; + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + + if (tpg_res->res_type != CAM_ISP_RESOURCE_TPG) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type %d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type); + return -EINVAL; + } + + mutex_lock(&tpg_hw->hw_info->hw_mutex); + /* Check for refcount */ + if (!tpg_hw->hw_info->open_count) { + CAM_WARN(CAM_ISP, "Unbalanced disable_hw"); + goto end; + } + + /* Decrement ref Count */ + tpg_hw->hw_info->open_count--; + if (tpg_hw->hw_info->open_count) { + rc = 0; + goto end; + } + + soc_info = &tpg_hw->hw_info->soc_info; + rc = cam_top_tpg_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_ISP, "TPG:%d Disable SOC failed", + tpg_hw->hw_intf->hw_idx); + + tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + CAM_DBG(CAM_ISP, "TPG:%d deint completed", tpg_hw->hw_intf->hw_idx); + +end: + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return rc; +} + +static int cam_top_tpg_start(void *hw_priv, void *start_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + const struct cam_top_tpg_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + uint32_t i, val; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *)start_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_lfsr_seed); + + for (i = 0; i < tpg_data->num_active_dts; i++) { + val = (((tpg_data->dt_cfg[i].frame_width & 0xFFFF) << 16) | + (tpg_data->dt_cfg[i].frame_height & 0x3FFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_0 + 0x10 * i); + cam_io_w_mb(tpg_data->dt_cfg[i].data_type, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_1 + 0x10 * i); + val = ((tpg_data->dt_cfg[i].encode_format & 0xF) << + tpg_reg->tpg_dt_encode_format_shift) | + tpg_reg->tpg_payload_mode_color; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_2 + 0x10 * i); + } + + val = (tpg_num_dt_map[tpg_data->num_active_dts-1] << + tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0); + + /* HBlank count 500 and V blank count is 600 */ + cam_io_w_mb(0x2581F4, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); + + val = (1 << tpg_reg->tpg_split_en_shift); + cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_common_gen_cfg); + cam_io_w_mb(0xAFFF, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); + CAM_DBG(CAM_ISP, "TPG:%d set TPG VBI to 0xAFFF", + tpg_hw->hw_intf->hw_idx); + + /* Set the TOP tpg mux sel*/ + cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx), + soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); + + val = ((tpg_data->num_active_lanes - 1) << + tpg_reg->tpg_num_active_lines_shift) | + (1 << tpg_reg->tpg_fe_pkt_en_shift) | + (1 << tpg_reg->tpg_fs_pkt_en_shift) | + (tpg_data->phy_sel << tpg_reg->tpg_phy_sel_shift_val) | + (1 << tpg_reg->tpg_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + CAM_DBG(CAM_ISP, "TPG:%d started", tpg_hw->hw_intf->hw_idx); + +end: + return rc; +} + +static int cam_top_tpg_stop(void *hw_priv, + void *stop_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + const struct cam_top_tpg_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *) stop_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_state; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_DBG(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_ctrl); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); +end: + return rc; +} + +static int cam_top_tpg_read(void *hw_priv, + void *read_args, uint32_t arg_size) +{ + CAM_ERR(CAM_ISP, "TPG: un supported"); + + return -EINVAL; +} + +static int cam_top_tpg_write(void *hw_priv, + void *write_args, uint32_t arg_size) +{ + CAM_ERR(CAM_ISP, "TPG: un supported"); + return -EINVAL; +} + +static int cam_top_tpg_set_phy_clock( + struct cam_top_tpg_hw *csid_hw, void *cmd_args) +{ + struct cam_top_tpg_clock_update_args *clk_update = NULL; + + if (!csid_hw) + return -EINVAL; + + clk_update = + (struct cam_top_tpg_clock_update_args *)cmd_args; + + csid_hw->clk_rate = clk_update->clk_rate; + CAM_DBG(CAM_ISP, "CSI PHY clock rate %llu", csid_hw->clk_rate); + + return 0; +} + +static int cam_top_tpg_process_cmd(void *hw_priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + + if (!hw_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE: + rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args); + break; + default: + CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d", + tpg_hw->hw_intf->hw_idx, cmd_type); + rc = -EINVAL; + break; + } + + return 0; +} + +int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, + uint32_t tpg_idx) +{ + int rc = -EINVAL; + struct cam_top_tpg_cfg *tpg_data; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_hw *tpg_hw = NULL; + uint32_t val = 0; + + if (tpg_idx >= CAM_TOP_TPG_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, "Invalid tpg index:%d", tpg_idx); + return rc; + } + + tpg_hw_info = (struct cam_hw_info *)tpg_hw_intf->hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + + tpg_hw->hw_intf = tpg_hw_intf; + tpg_hw->hw_info = tpg_hw_info; + + CAM_DBG(CAM_ISP, "type %d index %d", + tpg_hw->hw_intf->hw_type, tpg_idx); + + tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&tpg_hw->hw_info->hw_mutex); + spin_lock_init(&tpg_hw->hw_info->hw_lock); + spin_lock_init(&tpg_hw->lock_state); + init_completion(&tpg_hw->hw_info->hw_complete); + + init_completion(&tpg_hw->tpg_complete); + + rc = cam_top_tpg_init_soc_resources(&tpg_hw->hw_info->soc_info, + tpg_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "TPG:%d Failed to init_soc", tpg_idx); + goto err; + } + + tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_get_hw_caps; + tpg_hw->hw_intf->hw_ops.init = cam_top_tpg_init_hw; + tpg_hw->hw_intf->hw_ops.deinit = cam_top_tpg_deinit_hw; + tpg_hw->hw_intf->hw_ops.reset = NULL; + tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_reserve; + tpg_hw->hw_intf->hw_ops.release = cam_top_tpg_release; + tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_start; + tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_stop; + tpg_hw->hw_intf->hw_ops.read = cam_top_tpg_read; + tpg_hw->hw_intf->hw_ops.write = cam_top_tpg_write; + tpg_hw->hw_intf->hw_ops.process_cmd = cam_top_tpg_process_cmd; + + tpg_hw->tpg_res.res_type = CAM_ISP_RESOURCE_TPG; + tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + tpg_hw->tpg_res.hw_intf = tpg_hw->hw_intf; + tpg_data = kzalloc(sizeof(*tpg_data), GFP_KERNEL); + if (!tpg_data) { + rc = -ENOMEM; + goto err; + } + tpg_hw->tpg_res.res_priv = tpg_data; + + cam_top_tpg_enable_soc_resources(&tpg_hw->hw_info->soc_info, + CAM_SVS_VOTE); + + val = cam_io_r_mb(tpg_hw->hw_info->soc_info.reg_map[0].mem_base + + tpg_hw->tpg_info->tpg_reg->tpg_hw_version); + CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x", + tpg_hw->hw_intf->hw_idx, val); + + cam_top_tpg_disable_soc_resources(&tpg_hw->hw_info->soc_info); +err: + + return rc; +} + +int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw) +{ + int rc = -EINVAL; + + if (!top_tpg_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return rc; + } + + /* release the privdate data memory from resources */ + kfree(top_tpg_hw->tpg_res.res_priv); + cam_top_tpg_deinit_soc_resources(&top_tpg_hw->hw_info->soc_info); + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h new file mode 100644 index 000000000000..12f7cfc85e02 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_HW_H_ +#define _CAM_TOP_TPG_HW_H_ + +#include "cam_hw.h" +#include "cam_top_tpg_hw_intf.h" +#include "cam_top_tpg_soc.h" + +enum cam_top_tpg_encode_format { + CAM_TOP_TPG_ENCODE_FORMAT_RAW6, + CAM_TOP_TPG_ENCODE_FORMAT_RAW8, + CAM_TOP_TPG_ENCODE_FORMAT_RAW10, + CAM_TOP_TPG_ENCODE_FORMAT_RAW12, + CAM_TOP_TPG_ENCODE_FORMAT_RAW14, + CAM_TOP_TPG_ENCODE_FORMAT_RAW16, + CAM_TOP_TPG_ENCODE_FORMAT_MAX, +}; + +struct cam_top_tpg_reg_offset { + uint32_t tpg_hw_version; + uint32_t tpg_hw_status; + uint32_t tpg_ctrl; + uint32_t tpg_vc_cfg0; + uint32_t tpg_vc_cfg1; + uint32_t tpg_lfsr_seed; + uint32_t tpg_dt_0_cfg_0; + uint32_t tpg_dt_1_cfg_0; + uint32_t tpg_dt_2_cfg_0; + uint32_t tpg_dt_3_cfg_0; + uint32_t tpg_dt_0_cfg_1; + uint32_t tpg_dt_1_cfg_1; + uint32_t tpg_dt_2_cfg_1; + uint32_t tpg_dt_3_cfg_1; + uint32_t tpg_dt_0_cfg_2; + uint32_t tpg_dt_1_cfg_2; + uint32_t tpg_dt_2_cfg_2; + uint32_t tpg_dt_3_cfg_2; + uint32_t tpg_color_bar_cfg; + uint32_t tpg_common_gen_cfg; + uint32_t tpg_vbi_cfg; + uint32_t tpg_test_bus_crtl; + uint32_t tpg_spare; + /* configurations */ + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; + uint32_t tpg_en_shift_val; + uint32_t tpg_phy_sel_shift_val; + uint32_t tpg_num_active_lines_shift; + uint32_t tpg_fe_pkt_en_shift; + uint32_t tpg_fs_pkt_en_shift; + uint32_t tpg_line_interleaving_mode_shift; + uint32_t tpg_num_dts_shift_val; + uint32_t tpg_v_blank_cnt_shift; + uint32_t tpg_dt_encode_format_shift; + uint32_t tpg_payload_mode_color; + uint32_t tpg_split_en_shift; + uint32_t top_mux_reg_offset; +}; + +/** + * struct cam_top_tpg_hw_info- tpg hardware info + * + * @tpg_reg: tpg register offsets + * @hw_dts_version: HW DTS version + * @csid_max_clk: maximum csid clock + * @phy_max_clk maximum phy clock + * + */ +struct cam_top_tpg_hw_info { + const struct cam_top_tpg_reg_offset *tpg_reg; + uint32_t hw_dts_version; + uint32_t csid_max_clk; + uint32_t phy_max_clk; +}; + +/** + * struct cam_top_tpg_dt_cfg- tpg data type(dt) configuration + * + * @frame_width: frame width in pixel + * @frame_height: frame height in pixel + * @data_type: data type(dt) value + * @encode_format: encode format for this data type + * @payload_mode payload data, such color bar, color box etc + * + */ + +struct cam_top_tpg_dt_cfg { + uint32_t frame_width; + uint32_t frame_height; + uint32_t data_type; + uint32_t encode_format; + uint32_t payload_mode; +}; + +/** + * struct cam_top_tpg_cfg- tpg congiguration + * @pix_pattern : pixel pattern output of the tpg + * @phy_sel : phy selection 0:dphy or 1:cphy + * @num_active_lanes Number of active lines + * @vc_num: Virtual channel number + * @h_blank_count: horizontal blanking count value + * @h_blank_count: vertical blanking count value + * @vbi_cnt: vbi count + * @num_active_dts: number of active dts need to configure + * @dt_cfg: dt configuration values + * + */ +struct cam_top_tpg_cfg { + uint32_t pix_pattern; + uint32_t phy_sel; + uint32_t num_active_lanes; + uint32_t vc_num; + uint32_t v_blank_count; + uint32_t h_blank_count; + uint32_t vbi_cnt; + uint32_t num_active_dts; + struct cam_top_tpg_dt_cfg dt_cfg[4]; +}; + +/** + * struct cam_top_tpg_hw- tpg hw device resources data + * + * @hw_intf: contain the tpg hw interface information + * @hw_info: tpg hw device information + * @tpg_info: tpg hw specific information + * @tpg_res: tpg resource + * @tpg_cfg: tpg configuration + * @clk_rate clock rate + * @lock_state lock state + * @tpg_complete tpg completion + * + */ +struct cam_top_tpg_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_top_tpg_hw_info *tpg_info; + struct cam_isp_resource_node tpg_res; + uint64_t clk_rate; + spinlock_t lock_state; + struct completion tpg_complete; +}; + +int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, + uint32_t tpg_idx); + +int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw); + +#endif /* _CAM_TOP_TPG_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c new file mode 100644 index 000000000000..98658a7cc5bb --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include "cam_top_tpg_core.h" +#include "cam_top_tpg_dev.h" +#include "cam_top_tpg_hw_intf.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_top_tpg_hw_list[CAM_TOP_TPG_HW_NUM_MAX] = { + 0, 0}; + +static char tpg_dev_name[8]; + +int cam_top_tpg_probe(struct platform_device *pdev) +{ + + struct cam_hw_intf *tpg_hw_intf; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_hw *tpg_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_top_tpg_hw_info *tpg_hw_data = NULL; + uint32_t tpg_dev_idx; + int rc = 0; + + CAM_DBG(CAM_ISP, "probe called"); + + tpg_hw_intf = kzalloc(sizeof(*tpg_hw_intf), GFP_KERNEL); + if (!tpg_hw_intf) { + rc = -ENOMEM; + goto err; + } + + tpg_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!tpg_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + tpg_dev = kzalloc(sizeof(struct cam_top_tpg_hw), GFP_KERNEL); + if (!tpg_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + /* get top tpg hw index */ + of_property_read_u32(pdev->dev.of_node, "cell-index", &tpg_dev_idx); + /* get top tpg hw information */ + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the top tpg hw"); + rc = -EINVAL; + goto free_dev; + } + + memset(tpg_dev_name, 0, sizeof(tpg_dev_name)); + snprintf(tpg_dev_name, sizeof(tpg_dev_name), + "tpg%1u", tpg_dev_idx); + + tpg_hw_intf->hw_idx = tpg_dev_idx; + tpg_hw_intf->hw_type = CAM_ISP_HW_TYPE_TPG; + tpg_hw_intf->hw_priv = tpg_hw_info; + + tpg_hw_info->core_info = tpg_dev; + tpg_hw_info->soc_info.pdev = pdev; + tpg_hw_info->soc_info.dev = &pdev->dev; + tpg_hw_info->soc_info.dev_name = tpg_dev_name; + tpg_hw_info->soc_info.index = tpg_dev_idx; + + tpg_hw_data = (struct cam_top_tpg_hw_info *)match_dev->data; + /* need to setup the pdev before call the tfe hw probe init */ + tpg_dev->tpg_info = tpg_hw_data; + + rc = cam_top_tpg_hw_probe_init(tpg_hw_intf, tpg_dev_idx); + if (rc) + goto free_dev; + + platform_set_drvdata(pdev, tpg_dev); + CAM_DBG(CAM_ISP, "TPG:%d probe successful", + tpg_hw_intf->hw_idx); + + + if (tpg_hw_intf->hw_idx < CAM_TOP_TPG_HW_NUM_MAX) + cam_top_tpg_hw_list[tpg_hw_intf->hw_idx] = tpg_hw_intf; + else + goto free_dev; + + return 0; + +free_dev: + kfree(tpg_dev); +free_hw_info: + kfree(tpg_hw_info); +free_hw_intf: + kfree(tpg_hw_intf); +err: + return rc; +} + +int cam_top_tpg_remove(struct platform_device *pdev) +{ + struct cam_top_tpg_hw *tpg_dev = NULL; + struct cam_hw_intf *tpg_hw_intf; + struct cam_hw_info *tpg_hw_info; + + tpg_dev = (struct cam_top_tpg_hw *)platform_get_drvdata(pdev); + tpg_hw_intf = tpg_dev->hw_intf; + tpg_hw_info = tpg_dev->hw_info; + + CAM_DBG(CAM_ISP, "TPG:%d remove", + tpg_dev->hw_intf->hw_idx); + + cam_top_tpg_hw_deinit(tpg_dev); + + /*release the tpg device memory */ + kfree(tpg_dev); + kfree(tpg_hw_info); + kfree(tpg_hw_intf); + return 0; +} + +int cam_top_tpg_hw_init(struct cam_hw_intf **top_tpg_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_top_tpg_hw_list[hw_idx]) { + *top_tpg_hw = cam_top_tpg_hw_list[hw_idx]; + } else { + *top_tpg_hw = NULL; + rc = -1; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.h new file mode 100644 index 000000000000..2d4ce3614d18 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_DEV_H_ +#define _CAM_TOP_TPG_DEV_H_ + +int cam_top_tpg_probe(struct platform_device *pdev); +int cam_top_tpg_remove(struct platform_device *pdev); + +#endif /*_CAM_TOP_TPG_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c new file mode 100644 index 000000000000..206e91628fc4 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ +#include +#include "cam_top_tpg_soc.h" +#include "cam_cpas_api.h" +#include "cam_debug_util.h" + +int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info, + void *irq_data) +{ + int rc = 0; + struct cam_cpas_register_params cpas_register_param; + struct cam_top_tpg_soc_private *soc_private; + + soc_private = kzalloc(sizeof(struct cam_top_tpg_soc_private), + GFP_KERNEL); + if (!soc_private) + return -ENOMEM; + + soc_info->soc_private = soc_private; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc < 0) + return rc; + + /* Need to see if we want post process the clock list */ + rc = cam_soc_util_request_platform_resource(soc_info, NULL, + irq_data); + + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Error Request platform resources failed rc=%d", rc); + goto free_soc_private; + } + + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "tpg", + CAM_HW_IDENTIFIER_LENGTH); + cpas_register_param.cell_index = soc_info->index; + cpas_register_param.dev = soc_info->dev; + 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 = cpas_register_param.client_handle; + } + + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); +free_soc_private: + kfree(soc_private); + + return rc; +} + +int cam_top_tpg_deinit_soc_resources( + struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_top_tpg_soc_private *soc_private; + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -ENODEV; + } + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc); + + rc = cam_soc_util_release_platform_resource(soc_info); + + return rc; +} + +int cam_top_tpg_enable_soc_resources( + struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level) +{ + int rc = 0; + struct cam_top_tpg_soc_private *soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + + soc_private = soc_info->soc_private; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_SVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + CAM_DBG(CAM_ISP, "csid camnoc_bw:%lld mnoc_ab_bw:%lld mnoc_ib_bw:%lld ", + axi_vote.axi_path[0].camnoc_bw, + axi_vote.axi_path[0].mnoc_ab_bw, + axi_vote.axi_path[0].mnoc_ib_bw); + + rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_ISP, "Error CPAS start failed"); + rc = -EFAULT; + goto end; + } + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + clk_level, false); + if (rc) { + CAM_ERR(CAM_ISP, "enable platform failed"); + goto stop_cpas; + } + + return rc; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); +end: + return rc; +} + +int cam_top_tpg_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + struct cam_top_tpg_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Error Invalid params"); + return -EINVAL; + } + soc_private = soc_info->soc_private; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, false); + if (rc) + CAM_ERR(CAM_ISP, "Disable platform failed"); + + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Error CPAS stop failed rc=%d", rc); + return rc; + } + + return rc; +} + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h new file mode 100644 index 000000000000..9788409c99ad --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_SOC_H_ +#define _CAM_TOP_TPG_SOC_H_ + +#include "cam_isp_hw.h" + +/* + * struct cam_top_tpg_soc_private: + * + * @Brief: Private SOC data specific to TPG HW Driver + * + * @cpas_handle: Handle returned on registering with CPAS driver. + * This handle is used for all further interface + * with CPAS. + */ +struct cam_top_tpg_soc_private { + uint32_t cpas_handle; +}; + +/** + * struct cam_top_tpg_device_soc_info - tpg soc SOC info object + * + * @csi_vdd_voltage: csi vdd voltage value + * + */ +struct cam_top_tpg_device_soc_info { + int csi_vdd_voltage; +}; + +/** + * cam_top_tpg_init_soc_resources() + * + * @brief: csid initialization function for the soc info + * + * @soc_info: soc info structure pointer + * @irq_data: irq data for the callback function + * + */ +int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info, + void *irq_data); + +/** + * cam_top_tpg_deinit_soc_resources() + * + * @brief: tpg de initialization function for the soc info + * + * @soc_info: soc info structure pointer + * + */ +int cam_top_tpg_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + +/** + * cam_top_tpg_enable_soc_resources() + * + * @brief: tpg soc resource enable function + * + * @soc_info: soc info structure pointer + * @clk_lvl: vote level to start with + * + */ +int cam_top_tpg_enable_soc_resources(struct cam_hw_soc_info *soc_info, + uint32_t clk_lvl); + +/** + * cam_top_tpg_disable_soc_resources() + * + * @brief: csid soc resource disable function + * + * @soc_info: soc info structure pointer + * + */ +int cam_top_tpg_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +#endif /* _CAM_TOP_TPG_SOC_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c new file mode 100644 index 000000000000..dde4c1ac0df1 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#include +#include "cam_top_tpg_core.h" +#include "cam_top_tpg_v1.h" +#include "cam_top_tpg_dev.h" + +#define CAM_TOP_TPG_DRV_NAME "tpg_v1" +#define CAM_TOP_TPG_VERSION_V1 0x10000000 + +static struct cam_top_tpg_hw_info cam_top_tpg_v1_hw_info = { + .tpg_reg = &cam_top_tpg_v1_reg_offset, + .hw_dts_version = CAM_TOP_TPG_VERSION_V1, + .csid_max_clk = 426400000, + .phy_max_clk = 384000000, +}; + +static const struct of_device_id cam_top_tpg_v1_dt_match[] = { + { + .compatible = "qcom,tpgv1", + .data = &cam_top_tpg_v1_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_top_tpg_v1_dt_match); + +static struct platform_driver cam_top_tpg_v1_driver = { + .probe = cam_top_tpg_probe, + .remove = cam_top_tpg_remove, + .driver = { + .name = CAM_TOP_TPG_DRV_NAME, + .of_match_table = cam_top_tpg_v1_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_top_tpg_v1_init_module(void) +{ + return platform_driver_register(&cam_top_tpg_v1_driver); +} + +void cam_top_tpg_v1_exit_module(void) +{ + platform_driver_unregister(&cam_top_tpg_v1_driver); +} + +MODULE_DESCRIPTION("CAM TOP TPG driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h new file mode 100644 index 000000000000..2084b811e2ff --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_V1_H_ +#define _CAM_TOP_TPG_V1_H_ + +#include "cam_top_tpg_core.h" + +static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = { + .tpg_hw_version = 0x0, + .tpg_hw_status = 0x4, + .tpg_ctrl = 0x60, + .tpg_vc_cfg0 = 0x64, + .tpg_vc_cfg1 = 0x68, + .tpg_lfsr_seed = 0x6c, + .tpg_dt_0_cfg_0 = 0x70, + .tpg_dt_1_cfg_0 = 0x74, + .tpg_dt_2_cfg_0 = 0x78, + .tpg_dt_3_cfg_0 = 0x7C, + .tpg_dt_0_cfg_1 = 0x80, + .tpg_dt_1_cfg_1 = 0x84, + .tpg_dt_2_cfg_1 = 0x88, + .tpg_dt_3_cfg_1 = 0x8C, + .tpg_dt_0_cfg_2 = 0x90, + .tpg_dt_1_cfg_2 = 0x94, + .tpg_dt_2_cfg_2 = 0x98, + .tpg_dt_3_cfg_2 = 0x9C, + .tpg_color_bar_cfg = 0xA0, + .tpg_common_gen_cfg = 0xA4, + .tpg_vbi_cfg = 0xA8, + .tpg_test_bus_crtl = 0xF8, + .tpg_spare = 0xFC, + /* configurations */ + .major_version = 1, + .minor_version = 0, + .version_incr = 0, + .tpg_en_shift_val = 0, + .tpg_phy_sel_shift_val = 3, + .tpg_num_active_lines_shift = 4, + .tpg_fe_pkt_en_shift = 2, + .tpg_fs_pkt_en_shift = 1, + .tpg_line_interleaving_mode_shift = 10, + .tpg_num_dts_shift_val = 8, + .tpg_v_blank_cnt_shift = 12, + .tpg_dt_encode_format_shift = 16, + .tpg_payload_mode_color = 0x8, + .tpg_split_en_shift = 5, + .top_mux_reg_offset = 0x1C, +}; + +int cam_top_tpg_v1_init_module(void); +void cam_top_tpg_v1_exit_module(void); + +#endif /*_CAM_TOP_TPG_V1_H_ */ diff --git a/drivers/camera_main.c b/drivers/camera_main.c index b10b1026acb5..a109a4312977 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -50,6 +50,10 @@ #include "ope_dev_intf.h" +#include "cam_top_tpg_v1.h" +#include "cam_tfe_dev.h" +#include "cam_tfe_csid530.h" + struct camera_submodule_component { int (*init)(void); void (*exit)(void); @@ -79,6 +83,14 @@ static const struct camera_submodule_component camera_isp[] = { #endif }; +static const struct camera_submodule_component camera_tfe[] = { +#if IS_ENABLED(CONFIG_SPECTRA_TFE) + {&cam_top_tpg_v1_init_module, &cam_top_tpg_v1_exit_module}, + {&cam_tfe_init_module, &cam_tfe_exit_module}, + {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, +#endif +}; + static const struct camera_submodule_component camera_sensor[] = { #ifdef CONFIG_SPECTRA_SENSOR {&cam_res_mgr_init, &cam_res_mgr_exit}, @@ -151,6 +163,11 @@ static const struct camera_submodule submodule_table[] = { .num_component = ARRAY_SIZE(camera_isp), .component = camera_isp, }, + { + .name = "Camera TFE", + .num_component = ARRAY_SIZE(camera_tfe), + .component = camera_tfe, + }, { .name = "Camera SENSOR", .num_component = ARRAY_SIZE(camera_sensor), From d07eb2f941f3ffb1280c1ad33715fd0dd46e3abf Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 23 Dec 2019 16:51:03 +0530 Subject: [PATCH 212/790] msm: camera: cpas: Update the QOS settings for Bengal camera Camera QOS settings are updated for Bengal target as per the Recommendations of hardware team. CRs-Fixed: 2594541 Change-Id: I068683445b0ced92c22a5bfdc56d936ca64385c3 Signed-off-by: Ravikishore Pampana Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cpas/cpas_top/cpastop_v540_100.h | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h index 2d7e06d5b024..65cb1fabc701 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h @@ -88,21 +88,21 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ - .value = 0x22222222, + .value = 0x33333333, }, .priority_lut_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ - .value = 0x22222222, + .value = 0x33333333, }, .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE38, /* CDM_URGENCY_LOW */ - .value = 0x2, + .value = 0x00000003, }, .danger_lut = { .enable = false, @@ -131,7 +131,7 @@ static struct cam_camnoc_specific .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ .offset = 0x30, - .value = 0x66665433, + .value = 0x44443333, }, .priority_lut_high = { .enable = true, @@ -139,26 +139,26 @@ static struct cam_camnoc_specific .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ .offset = 0x34, - .value = 0x66666666, + .value = 0x66665555, }, .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* TFE_URGENCY_LOW */ - .value = 0X10030, + .value = 0x00001030, }, .danger_lut = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x40, /* TFE_DANGERLUT_LOW */ - .value = 0xFFAA5500, + .value = 0xffff0000, }, .safe_lut = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x48, /* TFE_SAFELUT_LOW */ - .value = 0xFF00, + .value = 0x00000003, }, .ubwc_ctl = { /* @@ -177,20 +177,20 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x33333333, }, .priority_lut_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ - .value = 0x66666666, + .value = 0x33333333, }, .urgency = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x438, /* OPE_URGENCY_LOW */ - .value = 0x3, + .value = 0x00000033, }, .danger_lut = { .enable = true, From 50fd3a70d1352210022e66db15ccf9c4accabfac Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 31 Oct 2019 11:36:50 +0530 Subject: [PATCH 213/790] msm: camera: tfe: Configure TPG hbi and vbi User space will send HBI and VBI values for tpg. Configure the TPG HBI and VBI values based on the user space given values. If user space does not send then configure the default values. Assign the isp context variable in the hw update data during the tfe hw config. Update proper comp group id for slave tfe. CRs-Fixed: 2594541 Change-Id: I2771d3c663c0fcb58306952f161c11a473846f8d Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 1 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 1 + .../isp_hw/top_tpg/cam_top_tpg_core.c | 24 ++++++++++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index bac81f24363c..a83f2c5dd61d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -2348,6 +2348,7 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, return -EINVAL; hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; + hw_update_data->isp_mgr_ctx = ctx; for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index fc4e465d03cf..0df57a450ed0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -933,6 +933,7 @@ static int cam_tfe_bus_start_comp_grp( val = cam_io_r(common_data->mem_base + common_data->common_reg->comp_cfg_0); val |= (0x1 << rsrc_data->comp_grp_id); + val |= (0x1 << (rsrc_data->comp_grp_id + 16)); cam_io_w(val, common_data->mem_base + common_data->common_reg->comp_cfg_0); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c index 4ea425df1ea8..6a544faf548f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c @@ -444,17 +444,29 @@ static int cam_top_tpg_start(void *hw_priv, void *start_args, tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0); - /* HBlank count 500 and V blank count is 600 */ - cam_io_w_mb(0x2581F4, + /* + * if hblank is notset configureHBlank count 500 and + * V blank count is 600 + */ + + if (tpg_data->h_blank_count) + cam_io_w_mb(tpg_data->h_blank_count, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); + else + cam_io_w_mb(0x2581F4, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); val = (1 << tpg_reg->tpg_split_en_shift); cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + tpg_reg->tpg_common_gen_cfg); - cam_io_w_mb(0xAFFF, - soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); - CAM_DBG(CAM_ISP, "TPG:%d set TPG VBI to 0xAFFF", - tpg_hw->hw_intf->hw_idx); + + /* if VBI is notset configureVBI to 0xAFF */ + if (tpg_data->v_blank_count) + cam_io_w_mb(tpg_data->v_blank_count, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); + else + cam_io_w_mb(0xAFFF, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); /* Set the TOP tpg mux sel*/ cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx), From 594b0acba567020c62557add7a307228af9b7718 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 12 Nov 2019 18:16:56 +0530 Subject: [PATCH 214/790] msm: camera: common: Remove division on uint64_t Arm arch does not support dividing 64 bit integer, replacing it with do_div call. Fix variable type to work with both 32/64 bit arch. CRs-Fixed: 2594541 Change-Id: I6b30f089bc998e98c7f2e20dc7fc11eedf6e6bc7 Signed-off-by: Chandan Kumar Jha --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 2 +- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 29 ++++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index a83f2c5dd61d..9cae0b8a086f 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -4053,7 +4053,7 @@ static void cam_tfe_mgr_print_io_bufs(struct cam_packet *packet, io_cfg[i].mem_handle[j]); continue; } - if (iova_addr >> 32) { + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { CAM_ERR(CAM_ISP, "Invalid mapped address"); rc = -EINVAL; continue; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index d2b4f7d081e5..d013170d2e0e 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -312,16 +312,21 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) if (device_share_ratio > 1) { for (i = 0; i < clk_update.axi_vote.num_paths; i++) { - clk_update.axi_vote.axi_path[i].camnoc_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].mnoc_ab_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].mnoc_ib_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].ddr_ab_bw /= - device_share_ratio; - clk_update.axi_vote.axi_path[i].ddr_ib_bw /= - device_share_ratio; + do_div( + clk_update.axi_vote.axi_path[i].camnoc_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].mnoc_ab_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].mnoc_ib_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].ddr_ab_bw, + device_share_ratio); + do_div( + clk_update.axi_vote.axi_path[i].ddr_ib_bw, + device_share_ratio); } } @@ -637,10 +642,10 @@ static int cam_ope_calc_total_clk(struct cam_ope_hw_mgr *hw_mgr, static uint32_t cam_ope_mgr_calc_base_clk(uint32_t frame_cycles, uint64_t budget) { - uint64_t base_clk; uint64_t mul = 1000000000; + uint64_t base_clk = frame_cycles * mul; - base_clk = (frame_cycles * mul) / budget; + do_div(base_clk, budget); CAM_DBG(CAM_OPE, "budget = %lld fc = %d ib = %lld base_clk = %lld", budget, frame_cycles, From a90aec6cb4aec22218ec91104911aff2ec8e3585 Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Thu, 14 Nov 2019 16:22:45 +0530 Subject: [PATCH 215/790] msm: camera: ope: Corrected parameter for deiniting idle clock Corrected the parameter needed to be passed in cam_ope_deinit_idle_clk. CRs-Fixed: 2594541 Change-Id: Ibeb8558fd0724fff61f4a6ddadd3b3cf6a6b3ed2 Signed-off-by: Rishabh Jain --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index d013170d2e0e..039ee0f42750 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -499,7 +499,7 @@ static void cam_ope_device_timer_cb(struct timer_list *timer_data) task_data->data = timer->parent; task_data->type = OPE_WORKQ_TASK_MSG_TYPE; task->process_cb = cam_ope_deinit_idle_clk; - cam_req_mgr_workq_enqueue_task(task, &ope_hw_mgr, + cam_req_mgr_workq_enqueue_task(task, ope_hw_mgr, CRM_TASK_PRIORITY_0); spin_unlock_irqrestore(&ope_hw_mgr->hw_mgr_lock, flags); } From 2613767f357b0b0182e8b082f7626d62ff2b58d8 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Mon, 25 Nov 2019 19:02:20 +0530 Subject: [PATCH 216/790] msm: camera: isp: Update bus width properly Do not read the hw register to update the bus width. Update register with stored height and user space given width Update the tfe core irq command register after clear the registers. CRs-Fixed: 2594541 Change-Id: I3fd9e0ce4319cd19b94e9c83fa63aab37f26027e Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 2 +- .../isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 10 +++++++++- drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 6 +----- .../cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 6 +++--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 9cae0b8a086f..ff0b12fd4b35 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1445,7 +1445,7 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_csid_rdi( csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; csid_acquire.res_id = path_res_id; csid_acquire.in_port = in_port; - csid_acquire.out_port = in_port->data; + csid_acquire.out_port = out_port; csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; csid_acquire.node_res = NULL; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 81c3fe083a56..e1925e9d1354 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -315,6 +315,10 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) rc = -ETIMEDOUT; } + status = cam_io_r(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_status_addr); + CAM_DBG(CAM_ISP, "Status reg %d", status); + /* perform the SW registers reset */ reinit_completion(&csid_hw->csid_top_complete); cam_io_w_mb(csid_reg->cmn_reg->csid_reg_rst_stb, @@ -1834,12 +1838,16 @@ static int cam_tfe_csid_reset_retain_sw_reg( if (rc < 0) { CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d", csid_hw->hw_intf->hw_idx, rc); - rc = -ETIMEDOUT; + status = cam_io_r(soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_status_addr); + CAM_DBG(CAM_ISP, "Status reg %d", status); + rc = 0; } else { CAM_DBG(CAM_ISP, "CSID:%d hw reset completed %d", csid_hw->hw_intf->hw_idx, rc); rc = 0; } + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_clear_addr); cam_io_w_mb(1, soc_info->reg_map[0].mem_base + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 0df57a450ed0..1fe75bf15a90 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -1656,11 +1656,7 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, wm_data = tfe_out_data->wm_res[i]->res_priv; /* update width register */ - val = cam_io_r_mb(wm_data->common_data->mem_base + - wm_data->hw_regs->image_cfg_0); - /* mask previously written width but preserve height */ - val = val & 0xFFFF0000; - val |= wm_data->width; + val = ((wm_data->height << 16) | (wm_data->width & 0xFFFF)); CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_0, val); CAM_DBG(CAM_ISP, "WM:%d image height and width 0x%x", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index bc60eb05f551..99fc55b10bc1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -710,6 +710,9 @@ irqreturn_t cam_tfe_irq(int irq_num, void *data) cam_io_w(top_irq_status[i], mem_base + core_info->tfe_hw_info->top_irq_clear[i]); + cam_io_w_mb(core_info->tfe_hw_info->global_clear_bitmask, + mem_base + core_info->tfe_hw_info->top_irq_cmd); + CAM_DBG(CAM_ISP, "TFE:%d IRQ status_0:0x%x status_1:0x%x status_2:0x%x", core_info->core_index, top_irq_status[0], top_irq_status[1], top_irq_status[2]); @@ -738,9 +741,6 @@ irqreturn_t cam_tfe_irq(int irq_num, void *data) bus_irq_status[1]); } - cam_io_w_mb(core_info->tfe_hw_info->global_clear_bitmask, - mem_base + core_info->tfe_hw_info->top_irq_cmd); - /* check reset */ if ((top_irq_status[0] & core_info->tfe_hw_info->reset_irq_mask[0]) || (top_irq_status[1] & From bd1e6c24201b8f8ade5970791df0bd5506ceb5f8 Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Sat, 30 Nov 2019 13:55:01 +0530 Subject: [PATCH 217/790] msm: camera: ope: Add fixes for probe, bus read and req_timer As we are accessing hw version register during probe so calling cpas_start and cpas_stop during probe. Disabling the read clients which are not enabled for the request. Resetting the req_timer when we receive the request from UMD. CRs-Fixed: 2594541 Change-Id: I4a739fedbb498bd0c6b5b1e4cef38de3e4c722ed Signed-off-by: Rishabh Jain --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 3 +- .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 146 +++++++++++++++++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 43 ++++-- 3 files changed, 177 insertions(+), 15 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 039ee0f42750..ebbd7a08ff1a 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -2544,7 +2544,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, return -EINVAL; } set_bit(request_idx, ctx_data->bitmap); - + cam_ope_req_timer_reset(ctx_data); ctx_data->req_list[request_idx] = kzalloc(sizeof(struct cam_ope_request), GFP_KERNEL); if (!ctx_data->req_list[request_idx]) { @@ -2718,7 +2718,6 @@ static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args) CAM_DBG(CAM_OPE, "req_id %llu, io config", ope_req->request_id); - cam_ope_req_timer_modify(ctx_data, 200); mutex_unlock(&ctx_data->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index 649f5084c027..346016d2aae9 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -82,9 +82,42 @@ static int cam_ope_bus_rd_combo_idx(uint32_t format) return rc; } +static int cam_ope_bus_is_rm_enabled( + struct cam_ope_request *ope_request, + uint32_t batch_idx, + uint32_t rm_id) +{ + int i, k; + int32_t combo_idx; + struct ope_io_buf *io_buf; + struct ope_bus_in_port_to_rm *in_port_to_rm; + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx); + return -EINVAL; + } + + for (i = 0; i < ope_request->num_io_bufs[batch_idx]; i++) { + io_buf = &ope_request->io_buf[batch_idx][i]; + if (io_buf->direction != CAM_BUF_INPUT) + continue; + in_port_to_rm = + &bus_rd->in_port_to_rm[io_buf->resource_type - 1]; + combo_idx = cam_ope_bus_rd_combo_idx(io_buf->format); + for (k = 0; k < io_buf->num_planes; k++) { + if (rm_id == + in_port_to_rm->rm_port_id[combo_idx][k]) + return true; + } + } + + return false; +} + static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, int32_t ctx_id, uint32_t *kmd_buf, int batch_idx, - int io_idx, struct cam_ope_dev_prepare_req *prepare) + int io_idx, struct cam_ope_dev_prepare_req *prepare, + int32_t *num_stripes) { int k, l, m; uint32_t idx; @@ -154,6 +187,7 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, for (k = 0; k < io_buf->num_planes; k++) { for (l = 0; l < io_buf->num_stripes[k]; l++) { + *num_stripes = io_buf->num_stripes[k]; stripe_io = &io_buf->s_io[k][l]; rsc_type = io_buf->resource_type - 1; /* frame level info */ @@ -259,6 +293,97 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, return kmd_buf; } +static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info, + int32_t ctx_id, struct cam_ope_dev_prepare_req *prepare, + int batch_idx, int rm_idx, + uint32_t *kmd_buf, uint32_t num_stripes) +{ + int l; + uint32_t idx; + uint32_t req_idx; + uint32_t temp_reg[128]; + uint32_t count = 0; + uint32_t temp = 0; + uint32_t header_size; + struct cam_ope_ctx *ctx_data; + struct ope_bus_rd_ctx *bus_rd_ctx; + struct cam_ope_bus_rd_reg *rd_reg; + struct cam_ope_bus_rd_client_reg *rd_reg_client; + struct ope_bus_rd_io_port_cdm_batch *io_port_cdm_batch; + struct ope_bus_rd_io_port_cdm_info *io_port_cdm; + struct cam_cdm_utils_ops *cdm_ops; + + + if (ctx_id < 0 || !prepare) { + CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare); + return NULL; + } + + if (batch_idx >= OPE_MAX_BATCH_SIZE) { + CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx); + return NULL; + } + + ctx_data = prepare->ctx_data; + req_idx = prepare->req_idx; + cdm_ops = ctx_data->ope_cdm.cdm_ops; + + bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + io_port_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; + rd_reg = ope_hw_info->bus_rd_reg; + + CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d", + kmd_buf, req_idx, prepare->kmd_buf_offset); + + io_port_cdm = + &bus_rd_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; + + for (l = 0; l < num_stripes; l++) { + /* stripe level info */ + rd_reg_client = &rd_reg->rd_clients[rm_idx]; + + /* Core cfg: enable, Mode */ + temp_reg[count++] = rd_reg->offset + + rd_reg_client->core_cfg; + temp_reg[count++] = 0; + + header_size = cdm_ops->cdm_get_cmd_header_size( + CAM_CDM_CMD_REG_RANDOM); + idx = io_port_cdm->num_s_cmd_bufs[l]; + io_port_cdm->s_cdm_info[l][idx].len = + sizeof(temp) * (count + header_size); + io_port_cdm->s_cdm_info[l][idx].offset = + prepare->kmd_buf_offset; + io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf; + io_port_cdm->num_s_cmd_bufs[l]++; + + kmd_buf = cdm_ops->cdm_write_regrandom( + kmd_buf, count/2, temp_reg); + prepare->kmd_buf_offset += ((count + header_size) * + sizeof(temp)); + + CAM_DBG(CAM_OPE, "b:%d s:%d", + batch_idx, l); + CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", + count, temp_reg, header_size); + CAM_DBG(CAM_OPE, "header_size:%d", header_size); + CAM_DBG(CAM_OPE, "RD cmd bufs = %d", + io_port_cdm->num_s_cmd_bufs[l]); + CAM_DBG(CAM_OPE, "off:%d len:%d", + io_port_cdm->s_cdm_info[l][idx].offset, + io_port_cdm->s_cdm_info[l][idx].len); + CAM_DBG(CAM_OPE, "b:%d s:%d", + batch_idx, l); + count = 0; + } + + prepare->rd_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; + + return kmd_buf; +} + static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, int32_t ctx_id, void *data) { @@ -269,6 +394,7 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, uint32_t temp_reg[32] = {0}; uint32_t header_size; uint32_t *kmd_buf; + int is_rm_enabled; struct cam_ope_dev_prepare_req *prepare; struct cam_ope_ctx *ctx_data; struct cam_ope_request *ope_request; @@ -279,6 +405,7 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, struct ope_bus_rd_io_port_cdm_batch *io_port_cdm_batch; struct ope_bus_rd_io_port_cdm_info *io_port_cdm; struct cam_cdm_utils_ops *cdm_ops; + int32_t num_stripes; if (ctx_id < 0 || !data) { CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); @@ -323,7 +450,8 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, } kmd_buf = cam_ope_bus_rd_update(ope_hw_info, - ctx_id, kmd_buf, i, j, prepare); + ctx_id, kmd_buf, i, j, prepare, + &num_stripes); if (!kmd_buf) { rc = -EINVAL; goto end; @@ -336,6 +464,20 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, goto end; } + /* Disable RMs which are not enabled */ + for (i = 0; i < ope_request->num_batch; i++) { + for (j = 0; j < rd_reg_val->num_clients; j++) { + is_rm_enabled = cam_ope_bus_is_rm_enabled( + ope_request, i, j); + if (is_rm_enabled) + continue; + + kmd_buf = cam_ope_bus_rm_disable(ope_hw_info, + ctx_id, prepare, i, j, + kmd_buf, num_stripes); + } + } + /* Go command */ count = 0; temp_reg[count++] = rd_reg->offset + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index 1230fea487af..6435777a4b3e 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -114,6 +114,7 @@ int cam_ope_probe(struct platform_device *pdev) int rc = 0; uint32_t hw_idx; struct cam_ope_dev_probe ope_probe; + struct cam_ope_cpas_vote cpas_vote; of_property_read_u32(pdev->dev.of_node, "cell-index", &hw_idx); @@ -176,17 +177,6 @@ int cam_ope_probe(struct platform_device *pdev) CAM_ERR(CAM_OPE, "failed to init_soc"); goto init_soc_failed; } - - rc = cam_ope_enable_soc_resources(&ope_dev->soc_info); - if (rc < 0) { - CAM_ERR(CAM_OPE, "enable soc resorce failed: %d", rc); - goto enable_soc_failed; - } - - rc = cam_ope_init_hw_version(&ope_dev->soc_info, ope_dev->core_info); - if (rc) - goto init_hw_failure; - core_info->hw_type = OPE_DEV_OPE; core_info->hw_idx = hw_idx; rc = cam_ope_register_cpas(&ope_dev->soc_info, @@ -194,7 +184,38 @@ int cam_ope_probe(struct platform_device *pdev) if (rc < 0) goto register_cpas_failed; + rc = cam_ope_enable_soc_resources(&ope_dev->soc_info); + if (rc < 0) { + CAM_ERR(CAM_OPE, "enable soc resorce failed: %d", rc); + goto enable_soc_failed; + } + cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; + cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote.axi_vote.num_paths = 1; + cpas_vote.axi_vote.axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_OPE_WR_VID; + cpas_vote.axi_vote.axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + cpas_vote.axi_vote.axi_path[0].camnoc_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ab_bw = + CAM_CPAS_DEFAULT_AXI_BW; + cpas_vote.axi_vote.axi_path[0].ddr_ib_bw = + CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(core_info->cpas_handle, + &cpas_vote.ahb_vote, &cpas_vote.axi_vote); + + rc = cam_ope_init_hw_version(&ope_dev->soc_info, ope_dev->core_info); + if (rc) + goto init_hw_failure; + cam_ope_disable_soc_resources(&ope_dev->soc_info, true); + cam_cpas_stop(core_info->cpas_handle); ope_dev->hw_state = CAM_HW_STATE_POWER_DOWN; ope_probe.hfi_en = ope_soc_info.hfi_en; From 130865bbdf39c53825810e891f31148759d0830e Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Mon, 2 Dec 2019 12:11:14 +0530 Subject: [PATCH 218/790] msm: camera: ope: Avoid dead lock during flush During flush OPE driver takes lock on OPE context and calls the CDM flush, in which CDM notifies OPE for all pending requests. If at the same time CDM is notifying OPE for successful request that thread also tries to take lock on OPE context. CDM also tries to takes lock on CDM client in each notify call. Due to which, dead lock is occurring. So taking the lock on OPE context in OPE flush after CDM flush. CRs-Fixed: 2594541 Change-Id: I6ae9105d33a49a638141973cdd6a4a99621dc4c5 Signed-off-by: Rishabh Jain --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index ebbd7a08ff1a..5afdcc1d3f28 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -2804,6 +2804,7 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data, rc = cam_cdm_flush_hw(ctx_data->ope_cdm.cdm_handle); + mutex_lock(&ctx_data->ctx_mutex); for (i = 0; i < hw_mgr->num_ope; i++) { rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RESET, @@ -2823,6 +2824,7 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data, ctx_data->req_list[i] = NULL; clear_bit(i, ctx_data->bitmap); } + mutex_unlock(&ctx_data->ctx_mutex); return rc; } @@ -2855,9 +2857,7 @@ static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args) switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: - mutex_lock(&ctx_data->ctx_mutex); cam_ope_mgr_flush_all(ctx_data, flush_args); - mutex_unlock(&ctx_data->ctx_mutex); break; case CAM_FLUSH_TYPE_REQ: mutex_lock(&ctx_data->ctx_mutex); From eb74ea19e4eac65507783aa67edf70fc18e09294 Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Sat, 16 Nov 2019 19:36:38 +0530 Subject: [PATCH 219/790] msm: camera: ope: Fixed for IRQ mask and log printing Adding fixes to set IRQ mask after reset and strings to print OPE CPAS PATH enums. CRs-Fixed: 2594541 Change-Id: I5873b8b0494623c36ca94edf7a26cc952fbb5e68 Signed-off-by: Rishabh Jain --- drivers/cam_cpas/cam_cpas_intf.c | 14 +++++++++++++- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 2 +- .../cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 8 +------- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 7 ------- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 2 ++ .../cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c | 4 ---- drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 8 ++++++++ 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f2a2e60d636e..bfa017a86442 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -83,6 +83,18 @@ const char *cam_cpas_axi_util_path_type_to_string( case CAM_AXI_PATH_DATA_IPE_WR_REF: return "IPE_WR_REF"; + /* OPE Paths */ + case CAM_AXI_PATH_DATA_OPE_RD_IN: + return "OPE_RD_IN"; + case CAM_AXI_PATH_DATA_OPE_RD_REF: + return "OPE_RD_REF"; + case CAM_AXI_PATH_DATA_OPE_WR_VID: + return "OPE_WR_VID"; + case CAM_AXI_PATH_DATA_OPE_WR_DISP: + return "OPE_WR_DISP"; + case CAM_AXI_PATH_DATA_OPE_WR_REF: + return "OPE_WR_REF"; + /* Common Paths */ case CAM_AXI_PATH_DATA_ALL: return "DATA_ALL"; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index ff0b12fd4b35..c89d6d56479e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -3372,7 +3372,7 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, if ((hfr_config->num_ports != 0) && (blob_size < (sizeof(struct cam_isp_tfe_resource_hfr_config) + (hfr_config->num_ports - 1) * - sizeof(struct cam_isp_tfe_resource_hfr_config)))) { + sizeof(struct cam_isp_tfe_port_hfr_config)))) { CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", blob_size, sizeof(struct cam_isp_tfe_resource_hfr_config) + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 1fe75bf15a90..a4eebd5a6e51 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -535,7 +535,7 @@ static int cam_tfe_bus_acquire_wm( rsrc_data->format); return -EINVAL; } - } else if (rsrc_data->index == 0) { + } else if (rsrc_data->index == 0 || rsrc_data->index == 1) { /* WM 0 FULL_OUT */ switch (rsrc_data->format) { case CAM_FORMAT_MIPI_RAW_8: @@ -571,12 +571,6 @@ static int cam_tfe_bus_acquire_wm( rsrc_data->height = 0; rsrc_data->stride = 1; rsrc_data->en_cfg = (0x1 << 16) | 0x1; - } else if (rsrc_data->index == 1) { - /* WM 1 Raw dump */ - rsrc_data->stride = rsrc_data->width; - rsrc_data->en_cfg = 0x1; - /* LSB aligned */ - rsrc_data->pack_fmt |= 0x10; } else { CAM_ERR(CAM_ISP, "Invalid WM:%d requested", rsrc_data->index); return -EINVAL; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 5afdcc1d3f28..4d369b69193d 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1858,13 +1858,6 @@ static int cam_ope_get_acquire_info(struct cam_ope_hw_mgr *hw_mgr, return -EINVAL; } - if (args->acquire_info_size < - sizeof(struct ope_acquire_dev_info)) { - CAM_ERR(CAM_OPE, "Invalid acquire size = %d", - args->acquire_info_size); - return -EINVAL; - } - if (copy_from_user(&ctx->ope_acquire, (void __user *)args->acquire_info, sizeof(struct ope_acquire_dev_info))) { diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index f062c61706e3..f7dcf9139da0 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -67,6 +67,7 @@ * @budget_ns: Time required to process frame * @frame_cycles: Frame cycles needed to process the frame * @rt_flag: Flag to indicate real time stream + * @reserved: Reserved for future use * @num_paths: Number of paths for per path bw vote * @axi_path: Per path vote info for OPE */ @@ -74,6 +75,7 @@ struct cam_ope_clk_bw_req_internal_v2 { uint64_t budget_ns; uint32_t frame_cycles; uint32_t rt_flag; + uint32_t reserved; uint32_t num_paths; struct cam_axi_per_path_bw_vote axi_path[CAM_OPE_MAX_PER_PATH_VOTES]; }; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c index 7a1a2ca7b9cc..75d7339e0bf4 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c @@ -691,7 +691,6 @@ static int cam_ope_bus_wr_isr(struct ope_hw *ope_hw_info, uint32_t irq_status_0, irq_status_1; struct cam_ope_bus_wr_reg *bus_wr_reg; struct cam_ope_bus_wr_reg_val *bus_wr_reg_val; - struct cam_ope_irq_data *irq_data = data; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -713,17 +712,14 @@ static int cam_ope_bus_wr_isr(struct ope_hw *ope_hw_info, bus_wr_reg->base + bus_wr_reg->irq_cmd); if (irq_status_0 & bus_wr_reg_val->cons_violation) { - irq_data->error = 1; CAM_ERR(CAM_OPE, "ope bus wr cons_violation"); } if (irq_status_0 & bus_wr_reg_val->violation) { - irq_data->error = 1; CAM_ERR(CAM_OPE, "ope bus wr vioalation"); } if (irq_status_0 & bus_wr_reg_val->img_size_violation) { - irq_data->error = 1; CAM_ERR(CAM_OPE, "ope bus wr img_size_violation"); } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index 4d8037c88363..4d1547352cd3 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -66,6 +66,10 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, rc = 0; } + /* enable interrupt mask */ + cam_io_w_mb(top_reg_val->irq_mask, + ope_hw_info->top_reg->base + top_reg->irq_mask); + return rc; } @@ -131,6 +135,10 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, &ope_top_info.reset_complete, msecs_to_jiffies(30)); + /* enable interrupt mask */ + cam_io_w_mb(top_reg_val->irq_mask, + ope_hw_info->top_reg->base + top_reg->irq_mask); + if (!rc || rc < 0) { CAM_ERR(CAM_OPE, "reset error result = %d", rc); if (!rc) From 832ac63b184a33455627e874638515fddee81e2f Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Tue, 3 Dec 2019 14:05:48 +0530 Subject: [PATCH 220/790] msm: camera: cci: Correct the queue size for cci version 1.2 Correct the queue size for cci version 1.2 as below, 1. Queue 0 size = 64. 2. Queue 1 size = 16. CRs-Fixed: 2594541 Change-Id: Ifc9407427fe2bf0996c77dc00c5dfe7e5ba22140 Signed-off-by: Tony Lijo Jose --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 4 +++- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 634a1c54dfe2..c8d424f9afaa 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_DEV_H_ @@ -34,6 +34,8 @@ #define V4L2_IDENT_CCI 50005 #define CCI_I2C_QUEUE_0_SIZE 128 #define CCI_I2C_QUEUE_1_SIZE 32 +#define CCI_I2C_QUEUE_0_SIZE_V_1_2 64 +#define CCI_I2C_QUEUE_1_SIZE_V_1_2 16 #define CYCLES_PER_MICRO_SEC_DEFAULT 4915 #define CCI_MAX_DELAY 1000000 diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 82f1c61cf8fe..b21287cd5028 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" @@ -17,6 +17,7 @@ int cam_cci_init(struct v4l2_subdev *sd, struct cam_axi_vote axi_vote = {0}; struct cam_hw_soc_info *soc_info = NULL; void __iomem *base = NULL; + uint32_t max_queue_0_size = 0, max_queue_1_size = 0; cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { @@ -116,14 +117,23 @@ int cam_cci_init(struct v4l2_subdev *sd, MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; cci_dev->support_seq_write = 1; + if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,cci-v1.2")) { + max_queue_0_size = CCI_I2C_QUEUE_0_SIZE_V_1_2; + max_queue_1_size = CCI_I2C_QUEUE_1_SIZE_V_1_2; + } else { + max_queue_0_size = CCI_I2C_QUEUE_0_SIZE; + max_queue_1_size = CCI_I2C_QUEUE_1_SIZE; + } + for (i = 0; i < NUM_MASTERS; i++) { for (j = 0; j < NUM_QUEUES; j++) { if (j == QUEUE_0) cci_dev->cci_i2c_queue_info[i][j].max_queue_size - = CCI_I2C_QUEUE_0_SIZE; + = max_queue_0_size; else cci_dev->cci_i2c_queue_info[i][j].max_queue_size - = CCI_I2C_QUEUE_1_SIZE; + = max_queue_1_size; CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i, cci_dev->cci_i2c_queue_info[i][j].max_queue_size, From 12548365dfc565cbbed5a2b86662e8aa227f3c8c Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Fri, 15 Nov 2019 09:31:24 +0530 Subject: [PATCH 221/790] msm: camera: common: secure camera fixes Isp bus port secure mode not coming properly. Added proper logic to get the bus port secure mode correctly. Use secure iommu handle to get secure buffer for ope. Add spin lock for tfe irq handler. Use proper bw structure to copy the user send blob data. CRs-Fixed: 2594541 Change-Id: Icb8ecf869681c370efa084991505036f90a35065 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 4 ++-- .../hw_utils/cam_isp_packet_parser.c | 20 ++++++++++++++++--- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 17 ++++++++-------- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 2 ++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 12 ++++++----- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 11 +++++----- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 17 +++++++++++++--- 8 files changed, 58 insertions(+), 27 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 6fdc18b05306..4baf5f37ac38 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5230,7 +5230,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, memset(&prepare_hw_data->bw_config_v2[bw_config->usage_type], 0, sizeof( prepare_hw_data->bw_config_v2[bw_config->usage_type])); - bw_config_size = sizeof(struct cam_isp_bw_config_internal_v2) + + bw_config_size = sizeof(struct cam_isp_bw_config_v2) + ((bw_config->num_paths - 1) * sizeof(struct cam_axi_per_path_bw_vote)); memcpy(&prepare_hw_data->bw_config_v2[bw_config->usage_type], diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index c89d6d56479e..0eaa8df2559e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -2354,7 +2354,7 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, if (hw_update_data->bw_config_valid[i] == true) { CAM_DBG(CAM_ISP, "idx=%d, bw_config_version=%d", - ctx, ctx->ctx_index, i, + ctx->ctx_index, i, hw_update_data->bw_config_version); if (hw_update_data->bw_config_version == CAM_ISP_BW_CONFIG_V2) { @@ -3486,7 +3486,7 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, memset(&prepare_hw_data->bw_config_v2[bw_config->usage_type], 0, sizeof( prepare_hw_data->bw_config_v2[bw_config->usage_type])); - bw_config_size = sizeof(struct cam_isp_bw_config_internal_v2) + + bw_config_size = sizeof(struct cam_isp_tfe_bw_config_v2) + ((bw_config->num_paths - 1) * sizeof(struct cam_axi_per_path_bw_vote)); memcpy(&prepare_hw_data->bw_config_v2[bw_config->usage_type], diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 67211e60517e..ce3f895f4bd8 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -475,6 +475,7 @@ int cam_isp_add_io_buffers( 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; + struct cam_isp_hw_get_cmd_update secure_mode; uint32_t kmd_buf_remain_size; uint32_t i, j, num_out_buf, num_in_buf; uint32_t res_id_out, res_id_in, plane_id; @@ -482,7 +483,8 @@ int cam_isp_add_io_buffers( size_t size; int32_t hdl; int mmu_hdl; - bool mode, is_buf_secure; + bool is_buf_secure; + uint32_t mode; io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) &prepare->packet->payload + @@ -611,10 +613,16 @@ int cam_isp_add_io_buffers( break; hdl = io_cfg[i].mem_handle[plane_id]; + secure_mode.cmd_type = + CAM_ISP_HW_CMD_GET_SECURE_MODE; + secure_mode.res = res; + secure_mode.data = (void *)&mode; rc = res->hw_intf->hw_ops.process_cmd( res->hw_intf->hw_priv, CAM_ISP_HW_CMD_GET_SECURE_MODE, - &mode, sizeof(bool)); + &secure_mode, + sizeof( + struct cam_isp_hw_get_cmd_update)); if (rc) return -EINVAL; @@ -722,10 +730,16 @@ int cam_isp_add_io_buffers( break; hdl = io_cfg[i].mem_handle[plane_id]; + secure_mode.cmd_type = + CAM_ISP_HW_CMD_GET_SECURE_MODE; + secure_mode.res = res; + secure_mode.data = (void *)&mode; rc = res->hw_intf->hw_ops.process_cmd( res->hw_intf->hw_priv, CAM_ISP_HW_CMD_GET_SECURE_MODE, - &mode, sizeof(bool)); + &secure_mode, + sizeof( + struct cam_isp_hw_get_cmd_update)); if (rc) return -EINVAL; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index a4eebd5a6e51..36980990f8af 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -1043,12 +1043,13 @@ static int cam_tfe_bus_deinit_comp_grp( static int cam_tfe_bus_get_secure_mode(void *priv, void *cmd_args, uint32_t arg_size) { - bool *mode = cmd_args; - struct cam_isp_resource_node *res = - (struct cam_isp_resource_node *) priv; - struct cam_tfe_bus_tfe_out_data *rsrc_data = - (struct cam_tfe_bus_tfe_out_data *)res->res_priv; + struct cam_isp_hw_get_cmd_update *secure_mode = cmd_args; + struct cam_tfe_bus_tfe_out_data *rsrc_data; + uint32_t *mode; + rsrc_data = (struct cam_tfe_bus_tfe_out_data *) + secure_mode->res->res_priv; + mode = (uint32_t *)secure_mode->data; *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? true : false; @@ -1657,7 +1658,7 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, wm_data->index, reg_val_pair[j-1]); val = io_cfg->planes[i].plane_stride; - CAM_DBG(CAM_ISP, "before stride %d", val); + CAM_DBG(CAM_ISP, "before stride 0x%x", val); val = ALIGNUP(val, 16); if (val != io_cfg->planes[i].plane_stride && val != wm_data->stride) @@ -1674,7 +1675,7 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_2, io_cfg->planes[i].plane_stride); - wm_data->stride = val; + wm_data->stride = io_cfg->planes[i].plane_stride; CAM_DBG(CAM_ISP, "WM %d image stride 0x%x", wm_data->index, reg_val_pair[j-1]); } @@ -1833,7 +1834,7 @@ static int cam_tfe_bus_update_stripe_cfg(void *priv, void *cmd_args, wm_data = tfe_out_data->wm_res[i]->res_priv; wm_data->width = stripe_config->width; wm_data->offset = stripe_config->offset; - CAM_DBG(CAM_ISP, "id:%x WM:%d width:0x%x offset:%x", + CAM_DBG(CAM_ISP, "id:%x WM:%d width:0x%x offset:0x%x", stripe_args->res->res_id, wm_data->index, wm_data->width, wm_data->offset); } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 99fc55b10bc1..8ebabf1f15c4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -702,6 +702,7 @@ irqreturn_t cam_tfe_irq(int irq_num, void *data) return IRQ_HANDLED; } + spin_lock(&core_info->spin_lock); for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) top_irq_status[i] = cam_io_r(mem_base + core_info->tfe_hw_info->top_irq_status[i]); @@ -740,6 +741,7 @@ irqreturn_t cam_tfe_irq(int irq_num, void *data) core_info->core_index, bus_irq_status[0], bus_irq_status[1]); } + spin_unlock(&core_info->spin_lock); /* check reset */ if ((top_irq_status[0] & core_info->tfe_hw_info->reset_irq_mask[0]) || diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index c5765c8a76a4..9c72e88c6f84 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1980,12 +1980,14 @@ static int cam_vfe_bus_deinit_comp_grp( static int cam_vfe_bus_get_secure_mode(void *priv, void *cmd_args, uint32_t arg_size) { - bool *mode = cmd_args; - struct cam_isp_resource_node *res = - (struct cam_isp_resource_node *) priv; - struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = - (struct cam_vfe_bus_ver2_vfe_out_data *)res->res_priv; + struct cam_isp_hw_get_cmd_update *secure_mode = cmd_args; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data; + uint32_t *mode; + + rsrc_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + secure_mode->res->res_priv; + mode = (uint32_t *)secure_mode->data; *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? true : false; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 694dd224a660..3d8415b0f765 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1865,12 +1865,13 @@ static int cam_vfe_bus_ver3_deinit_comp_grp( static int cam_vfe_bus_ver3_get_secure_mode(void *priv, void *cmd_args, uint32_t arg_size) { - bool *mode = cmd_args; - struct cam_isp_resource_node *res = - (struct cam_isp_resource_node *) priv; - struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = - (struct cam_vfe_bus_ver3_vfe_out_data *)res->res_priv; + struct cam_isp_hw_get_cmd_update *secure_mode = cmd_args; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data; + uint32_t *mode; + rsrc_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + secure_mode->res->res_priv; + mode = (uint32_t *)secure_mode->data; *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? true : false; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 4d369b69193d..3671a008fd48 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1383,6 +1383,7 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, uint32_t unpack_format; struct ope_in_res_info *in_res; struct ope_out_res_info *out_res; + bool is_secure; in_frame_process = (struct ope_frame_process *)frame_process_addr; @@ -1471,9 +1472,19 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, for (k = 0; k < in_io_buf->num_planes; k++) { io_buf->num_stripes[k] = in_io_buf->num_stripes[k]; - rc = cam_mem_get_io_buf( - in_io_buf->mem_handle[k], - hw_mgr->iommu_hdl, &iova_addr, &len); + is_secure = cam_mem_is_secure_buf( + in_io_buf->mem_handle[k]); + if (is_secure) + rc = cam_mem_get_io_buf( + in_io_buf->mem_handle[k], + hw_mgr->iommu_sec_hdl, + &iova_addr, &len); + else + rc = cam_mem_get_io_buf( + in_io_buf->mem_handle[k], + hw_mgr->iommu_hdl, + &iova_addr, &len); + if (rc) { CAM_ERR(CAM_OPE, "get buf failed: %d", rc); From f1f6915ed4bb0797050f34cae2b768daf7ff9777 Mon Sep 17 00:00:00 2001 From: Suresh Vankadara Date: Mon, 9 Dec 2019 15:55:26 +0530 Subject: [PATCH 222/790] msm: camera: ope: Fix OPE AHB voting issue Initialize AHB voting variable in OPE acquire to fix AHB voting issue for OPE. CRs-Fixed: 2594541 Change-Id: I5bf8c0b1315a351abd80341100bdaf42333c4c24 Signed-off-by: Suresh Vankadara --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 3671a008fd48..2671b95ff426 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -2158,6 +2158,7 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } } + bw_update.ahb_vote_valid = false; for (i = 0; i < ope_hw_mgr->num_ope; i++) { bw_update.axi_vote.num_paths = 1; bw_update.axi_vote_valid = true; From 6b1a0dfc660ad67082f6260ae81fa8002ce0eb12 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 21 Nov 2019 22:45:46 +0530 Subject: [PATCH 223/790] msm: camera: isp: prioritize RUP over EPOCH in bottom half When epoch comes along with RUP we report bubble as per current state machine. This was because in camif_bottom_half handler we are handling EPOCH before RUP. This change prioritize RUP over EPOCH and EOF over SOF to handle race. CRs-Fixed: 2567120 Change-Id: I236bcc44b609f8ef7f963f19d33d46a3d95ba0d2 Signed-off-by: Vikram Sharma --- .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 0ed1c6ede3ce..c776888c9871 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -709,6 +709,16 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, CAM_DBG(CAM_ISP, "irq_status_0 = 0x%x irq_status_1 = 0x%x", irq_status0, irq_status1); + if (irq_status0 & camif_priv->reg_data->eof_irq_mask) { + CAM_DBG(CAM_ISP, "Received EOF"); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + + ret = CAM_VFE_IRQ_STATUS_SUCCESS; + } + if (irq_status0 & camif_priv->reg_data->sof_irq_mask) { if ((camif_priv->enable_sof_irq_debug) && (camif_priv->irq_debug_cnt <= @@ -732,16 +742,6 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_SUCCESS; } - if (irq_status0 & camif_priv->reg_data->epoch0_irq_mask) { - CAM_DBG(CAM_ISP, "Received EPOCH"); - - if (camif_priv->event_cb) - camif_priv->event_cb(camif_priv->priv, - CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); - - ret = CAM_VFE_IRQ_STATUS_SUCCESS; - } - if (irq_status0 & camif_priv->reg_data->reg_update_irq_mask) { CAM_DBG(CAM_ISP, "Received REG_UPDATE_ACK"); @@ -752,12 +752,12 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_SUCCESS; } - if (irq_status0 & camif_priv->reg_data->eof_irq_mask) { - CAM_DBG(CAM_ISP, "Received EOF"); + if (irq_status0 & camif_priv->reg_data->epoch0_irq_mask) { + CAM_DBG(CAM_ISP, "Received EPOCH"); if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, - CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); + CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); ret = CAM_VFE_IRQ_STATUS_SUCCESS; } From 65f749c831fa11d1a8db2aa2a06661c23a9736f2 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Fri, 22 Nov 2019 10:35:25 +0530 Subject: [PATCH 224/790] msm: camera: req_mgr: Link state check before process trigger workq Due to scheduling delays, process trigger workq can be delayed. In the meantime, link state can be reset to IDLE. This can cause abnormal behaviour resulting in stability issues. Also, at the time of apply fail for flash, failed_dev is not updated. This causes crash while notifying the error on link. This commit prevents the execution of workq process trigger if the link has been reset to IDLE state. Also, failed_dev is updated if the apply for flash fails. CRs-Fixed: 2572511 Change-Id: Iaea1e0a7a24afc9e408a1530a5875f6b6c41a45b Signed-off-by: Gaurav Jindal --- drivers/cam_req_mgr/cam_req_mgr_core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 0a4af3c097d0..d229f04510d2 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -681,8 +681,10 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.trigger_point = trigger; if (dev->ops && dev->ops->apply_req) { rc = dev->ops->apply_req(&apply_req); - if (rc) + if (rc) { + *failed_dev = dev; return rc; + } CAM_DBG(CAM_REQ, "SEND: link_hdl: %x pd: %d req_id %lld", link->link_hdl, pd, apply_req.request_id); @@ -2456,6 +2458,14 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) link->link_hdl, in_q->rd_idx, in_q->slot[in_q->rd_idx].status); spin_lock_bh(&link->link_state_spin_lock); + + if (link->state < CAM_CRM_LINK_STATE_READY) { + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + spin_unlock_bh(&link->link_state_spin_lock); + rc = -EPERM; + goto release_lock; + } + if (link->state == CAM_CRM_LINK_STATE_ERR) CAM_WARN(CAM_CRM, "Error recovery idx %d status %d", in_q->rd_idx, From bf16c8a8e5a4748da396b7cec614a077e58fa97e Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Mon, 2 Dec 2019 16:36:43 +0530 Subject: [PATCH 225/790] msm: camera: csiphy: Update common sequence for csiphy v1.2 Add a high-to-low transition in the CTRL0 register during the common power-up sequence. CRs-Fixed: 2580437 Change-Id: I66541d3d787fa2f161e5d8e647fb11c8075a1947 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 3bed231e0246..179ccebddc54 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -12,7 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .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_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 18, .csiphy_3ph_config_array_size = 33, @@ -24,6 +24,7 @@ struct csiphy_reg_t csiphy_common_reg_1_2[] = { {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, From 96390653c5a8eea731224f2aed44d00a4b8dc131 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 25 Oct 2019 15:36:03 +0530 Subject: [PATCH 226/790] msm: camera: reqmgr: reset the slot on buf_done Reset the slot with the valid request on receiving the buf_done which is reported on next EPOCH. In case of back to back irqs slot is marked as skip idx it will apply the request and try to reset a slot based on MAX_PD + 1 calculation which might have the request for which we have got a bubble. To make sure this does not happen, reset a slot only on the buf_done for valid request. If STOP ioctl is called from UMD for ISP, it will flush all the lists. But this is not notified to CRM which might have a stale entry of the half applied request, so on STOP ioctl clear all the slots. In case of SAT mode if one of the link has generated bubble, while the sync_link has the sync_request slot reset sync_link will not let the link recover of the bubble. To make sure the recovery sync_mode is set to 0 for two consecutive slots of the link. CRs-Fixed: 2551701 Change-Id: If4b6f8a4a831ffddcef2cae6292d066778c18b04 Signed-off-by: Tejas Prajapati --- drivers/cam_isp/cam_isp_context.c | 36 +++++- drivers/cam_isp/cam_isp_context.h | 14 +++ drivers/cam_req_mgr/cam_req_mgr_core.c | 115 +++++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_core.h | 2 + drivers/cam_req_mgr/cam_req_mgr_interface.h | 17 +++ 5 files changed, 179 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 79e57b629cdc..97b5953f9ca2 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -708,6 +708,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + ctx_isp->req_info.last_bufdone_req_id = req->request_id; } __cam_isp_ctx_update_state_monitor_array(ctx_isp, @@ -907,6 +908,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -1077,7 +1079,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, * If no wait req in epoch, this is an error case. * The recovery is to go back to sof state */ - CAM_ERR(CAM_ISP, "No wait request"); + CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; /* Send SOF event as empty frame*/ @@ -1093,7 +1095,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp->bubble_detected = true; req_isp->reapply = true; - CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); + CAM_INFO(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", + ctx->ctx_id, req_isp->bubble_report, req->request_id); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; @@ -1242,7 +1245,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( * If no pending req in epoch, this is an error case. * Just go back to the bubble state. */ - CAM_ERR(CAM_ISP, "No pending request."); + CAM_ERR(CAM_ISP, "ctx:%d No pending request.", ctx->ctx_id); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); @@ -1254,6 +1257,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; + CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", + ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; if (req_isp->bubble_report && ctx->ctx_crm_intf && @@ -1592,6 +1597,7 @@ static int __cam_isp_ctx_fs2_sof_in_sof_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -1769,6 +1775,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -2457,6 +2464,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -2553,9 +2561,10 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; + CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", + ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; - CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; @@ -2654,6 +2663,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -2726,6 +2736,7 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -2923,6 +2934,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; + ctx_isp->req_info.last_bufdone_req_id = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -2983,6 +2995,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->hw_acquired = false; ctx_isp->init_received = false; ctx_isp->rdi_only_context = false; + ctx_isp->req_info.last_bufdone_req_id = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -3913,6 +3926,18 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); + if (ctx->ctx_crm_intf && + ctx->ctx_crm_intf->notify_stop) { + struct cam_req_mgr_notify_stop notify; + + notify.link_hdl = ctx->link_hdl; + CAM_DBG(CAM_ISP, + "Notify CRM about device stop ctx %u link 0x%x", + ctx->ctx_id, ctx->link_hdl); + ctx->ctx_crm_intf->notify_stop(¬ify); + } else + CAM_ERR(CAM_ISP, "cb not present"); + while (!list_empty(&ctx->pending_req_list)) { req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); @@ -3960,11 +3985,13 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( } list_add_tail(&req->list, &ctx->free_req_list); } + ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->bubble_frame_cnt = 0; ctx_isp->last_applied_req_id = 0; + ctx_isp->req_info.last_bufdone_req_id = 0; atomic_set(&ctx_isp->process_bubble, 0); atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -4424,6 +4451,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->frame_id = 0; ctx->active_req_cnt = 0; ctx->reported_req_id = 0; + ctx->req_info.last_bufdone_req_id = 0; ctx->bubble_frame_cnt = 0; ctx->hw_ctx = NULL; ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index dc91ecd9ff5a..c29a57fc33e4 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -150,6 +150,18 @@ struct cam_isp_context_state_monitor { }; /** + * struct cam_isp_context_req_id_info - ISP context request id + * information for bufdone. + * + *@last_bufdone_req_id: Last bufdone request id + * + */ + +struct cam_isp_context_req_id_info { + int64_t last_bufdone_req_id; +}; +/** + * * struct cam_isp_context - ISP context object * * @base: Common context object pointer @@ -171,6 +183,7 @@ struct cam_isp_context_state_monitor { * will invoke CRM cb at those event. * @last_applied_req_id: Last applied request id * @state_monitor_head: Write index to the state monitoring array + * @req_info Request id information about last buf done * @cam_isp_ctx_state_monitor: State monitoring array * @rdi_only_context: Get context type information. * true, if context is rdi only context @@ -204,6 +217,7 @@ struct cam_isp_context { atomic64_t state_monitor_head; struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; + struct cam_isp_context_req_id_info req_info; bool rdi_only_context; bool hw_acquired; bool init_received; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index d229f04510d2..e7b5994963fe 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -480,7 +480,9 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, CAM_DBG(CAM_CRM, "RESET: idx: %d: slot->status %d", idx, slot->status); /* Check if CSL has already pushed new request*/ - if (slot->status == CRM_SLOT_STATUS_REQ_ADDED) + if (slot->status == CRM_SLOT_STATUS_REQ_ADDED || + in_q->last_applied_idx == idx || + idx < 0) return; /* Reset input queue slot */ @@ -1500,6 +1502,10 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, reset_step = link->sync_link->max_delay; } + + if (slot->req_id > 0) + in_q->last_applied_idx = idx; + __cam_req_mgr_dec_idx( &idx, reset_step + 1, in_q->num_slots); @@ -2403,6 +2409,12 @@ int cam_req_mgr_process_error(void *priv, void *data) __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl); in_q->rd_idx = idx; in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; + if (link->sync_link) { + in_q->slot[idx].sync_mode = 0; + __cam_req_mgr_inc_idx(&idx, 1, + link->req.l_tbl->num_slots); + in_q->slot[idx].sync_mode = 0; + } spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_ERR; spin_unlock_bh(&link->link_state_spin_lock); @@ -2415,6 +2427,31 @@ end: return rc; } +/** + * cam_req_mgr_process_stop() + * + * @brief: This runs in workque thread context. stop notification. + * @priv : link information. + * @data : contains information about frame_id, link etc. + * + * @return: 0 on success. + */ +int cam_req_mgr_process_stop(void *priv, void *data) +{ + int rc = 0; + struct cam_req_mgr_core_link *link = NULL; + + if (!data || !priv) { + CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); + rc = -EINVAL; + goto end; + } + link = (struct cam_req_mgr_core_link *)priv; + __cam_req_mgr_flush_req_slot(link); +end: + return rc; +} + /** * cam_req_mgr_process_trigger() * @@ -2428,6 +2465,7 @@ end: static int cam_req_mgr_process_trigger(void *priv, void *data) { int rc = 0; + int32_t idx = -1; struct cam_req_mgr_trigger_notify *trigger_data = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_req_queue *in_q = NULL; @@ -2450,6 +2488,17 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) in_q = link->req.in_q; mutex_lock(&link->req.lock); + + if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) { + idx = __cam_req_mgr_find_slot_for_req(in_q, + trigger_data->req_id); + if (idx >= 0) { + if (idx == in_q->last_applied_idx) + in_q->last_applied_idx = -1; + __cam_req_mgr_reset_req_slot(link, idx); + } + } + /* * Check if current read index is in applied state, if yes make it free * and increment read index to next slot. @@ -2714,6 +2763,68 @@ end: return rc; } +/* + * cam_req_mgr_cb_notify_stop() + * + * @brief : Stop received from device, resets the morked slots + * @err_info : contains information about error occurred like bubble/overflow + * + * @return : 0 on success, negative in case of failure + * + */ +static int cam_req_mgr_cb_notify_stop( + struct cam_req_mgr_notify_stop *stop_info) +{ + int rc = 0; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_notify_stop *notify_stop; + struct crm_task_payload *task_data; + + if (!stop_info) { + CAM_ERR(CAM_CRM, "stop_info is NULL"); + rc = -EINVAL; + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(stop_info->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", stop_info->link_hdl); + rc = -EINVAL; + goto end; + } + + spin_lock_bh(&link->link_state_spin_lock); + if (link->state != CAM_CRM_LINK_STATE_READY) { + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + spin_unlock_bh(&link->link_state_spin_lock); + rc = -EPERM; + goto end; + } + crm_timer_reset(link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); + + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "no empty task"); + rc = -EBUSY; + goto end; + } + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; + notify_stop = (struct cam_req_mgr_notify_stop *)&task_data->u; + notify_stop->link_hdl = stop_info->link_hdl; + task->process_cb = &cam_req_mgr_process_stop; + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); + +end: + return rc; +} + + + /** * cam_req_mgr_cb_notify_trigger() * @@ -2774,6 +2885,7 @@ static int cam_req_mgr_cb_notify_trigger( notify_trigger->link_hdl = trigger_data->link_hdl; notify_trigger->dev_hdl = trigger_data->dev_hdl; notify_trigger->trigger = trigger_data->trigger; + notify_trigger->req_id = trigger_data->req_id; notify_trigger->sof_timestamp_val = trigger_data->sof_timestamp_val; task->process_cb = &cam_req_mgr_process_trigger; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); @@ -2787,6 +2899,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = { .notify_err = cam_req_mgr_cb_notify_err, .add_req = cam_req_mgr_cb_add_req, .notify_timer = cam_req_mgr_cb_notify_timer, + .notify_stop = cam_req_mgr_cb_notify_stop, }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 0afdc69b0445..14cf4ff06a36 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -253,12 +253,14 @@ struct cam_req_mgr_slot { * @slot : request slot holding incoming request id and bubble info. * @rd_idx : indicates slot index currently in process. * @wr_idx : indicates slot index to hold new upcoming req. + * @last_applied_idx : indicates slot index last applied successfully. */ struct cam_req_mgr_req_queue { int32_t num_slots; struct cam_req_mgr_slot slot[MAX_REQ_SLOTS]; int32_t rd_idx; int32_t wr_idx; + int32_t last_applied_idx; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 5df13b26e215..68ab7917e947 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -15,6 +15,7 @@ struct cam_req_mgr_trigger_notify; struct cam_req_mgr_error_notify; struct cam_req_mgr_add_request; struct cam_req_mgr_timer_notify; +struct cam_req_mgr_notify_stop; struct cam_req_mgr_device_info; struct cam_req_mgr_core_dev_link_setup; struct cam_req_mgr_apply_request; @@ -37,6 +38,7 @@ typedef int (*cam_req_mgr_notify_trigger)( typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *); +typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); /** * @brief: cam req mgr to camera device drivers @@ -61,12 +63,14 @@ typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); * @notify_trigger : payload for trigger indication event * @notify_err : payload for different error occurred at device * @add_req : payload to inform which device and what request is received + * @notify_stop : payload to inform stop event */ struct cam_req_mgr_crm_cb { cam_req_mgr_notify_trigger notify_trigger; cam_req_mgr_notify_err notify_err; cam_req_mgr_add_req add_req; cam_req_mgr_notify_timer notify_timer; + cam_req_mgr_notify_stop notify_stop; }; /** @@ -142,6 +146,7 @@ enum cam_req_mgr_device_error { CRM_KMD_ERR_PAGE_FAULT, CRM_KMD_ERR_OVERFLOW, CRM_KMD_ERR_TIMEOUT, + CRM_KMD_ERR_STOPPED, CRM_KMD_ERR_MAX, }; @@ -200,6 +205,7 @@ enum cam_req_mgr_link_evt_type { * @trigger : trigger point of this notification, CRM will send apply * only to the devices which subscribe to this point. * @sof_timestamp_val: Captured time stamp value at sof hw event + * @req_id : req id which returned buf_done */ struct cam_req_mgr_trigger_notify { int32_t link_hdl; @@ -207,6 +213,7 @@ struct cam_req_mgr_trigger_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; + uint64_t req_id; }; /** @@ -253,6 +260,16 @@ struct cam_req_mgr_add_request { }; +/** + * struct cam_req_mgr_notify_stop + * @link_hdl : link identifier + * + */ +struct cam_req_mgr_notify_stop { + int32_t link_hdl; +}; + + /* CRM to KMD devices */ /** * struct cam_req_mgr_device_info From 2e181b7f9c1ac95345f4c0478d8b28b989d7a0a9 Mon Sep 17 00:00:00 2001 From: Suraj Dongre Date: Wed, 20 Nov 2019 22:23:37 -0800 Subject: [PATCH 227/790] msm: camera: jpeg: Increase number of jpeg contexts Fixed out of memory issue in triple camera usecase by increasing number of logical jpeg contexts. CRs-Fixed: 2587592 Change-Id: I25c99c0be8d3986bc11fbc2894a0dbf27c645d4e Signed-off-by: Suraj Dongre Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_jpeg/cam_jpeg_dev.c | 6 +++--- drivers/cam_jpeg/cam_jpeg_dev.h | 4 ++-- drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h | 3 +-- drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h | 4 +++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 777ec5b4804b..81843d8cf117 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -97,7 +97,7 @@ static int cam_jpeg_dev_remove(struct platform_device *pdev) int rc; int i; - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_JPEG_CTX_MAX; i++) { rc = cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]); if (rc) CAM_ERR(CAM_JPEG, "JPEG context %d deinit failed %d", @@ -135,7 +135,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev) goto unregister; } - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_JPEG_CTX_MAX; i++) { rc = cam_jpeg_context_init(&g_jpeg_dev.ctx_jpeg[i], &g_jpeg_dev.ctx[i], &node->hw_mgr_intf, @@ -147,7 +147,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev) } } - rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_CTX_MAX, + rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_JPEG_CTX_MAX, CAM_JPEG_DEV_NAME); if (rc) { CAM_ERR(CAM_JPEG, "JPEG node init failed %d", rc); diff --git a/drivers/cam_jpeg/cam_jpeg_dev.h b/drivers/cam_jpeg/cam_jpeg_dev.h index f5b83d93422a..d468748d8fa9 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.h +++ b/drivers/cam_jpeg/cam_jpeg_dev.h @@ -24,8 +24,8 @@ struct cam_jpeg_dev { struct cam_subdev sd; struct cam_node *node; - struct cam_context ctx[CAM_CTX_MAX]; - struct cam_jpeg_context ctx_jpeg[CAM_CTX_MAX]; + struct cam_context ctx[CAM_JPEG_CTX_MAX]; + struct cam_jpeg_context ctx_jpeg[CAM_JPEG_CTX_MAX]; struct mutex jpeg_mutex; int32_t open_cnt; }; diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h index 1b93547fdf25..3deb9dd73b32 100644 --- a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_HW_INTF_H @@ -8,7 +8,6 @@ #include "cam_cpas_api.h" -#define CAM_JPEG_CTX_MAX 8 #define CAM_JPEG_DEV_PER_TYPE_MAX 1 #define CAM_JPEG_CMD_BUF_MAX_SIZE 128 diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h index 30c51f7cfcfd..b83a308f7d78 100644 --- a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_HW_MGR_INTF_H @@ -10,6 +10,8 @@ #include #include +#define CAM_JPEG_CTX_MAX 16 + int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl); From 5f5a2f2028e6eb43637d75f1c804258032dc5d89 Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Fri, 13 Dec 2019 09:49:16 +0530 Subject: [PATCH 228/790] msm: camera: cpas: Reorder sequence of cleanup in cpas probe failure if cpas probe fails during initialization of soc resources soc data is being accessed after freeing the memory. This change handling the sequence on failure. CRs-Fixed: 2585085 Change-Id: Ia89b02bce9cfb6512b33f8e7366a552635317ccd Signed-off-by: Alok Pandey --- drivers/cam_cpas/cam_cpas_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 061d2594421a..71a4e4ea953b 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1795,10 +1795,10 @@ ahb_cleanup: cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client); client_cleanup: cam_cpas_util_client_cleanup(cpas_hw); + cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private); deinit_platform_res: cam_cpas_soc_deinit_resources(&cpas_hw->soc_info); release_workq: - cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private); flush_workqueue(cpas_core->work_queue); destroy_workqueue(cpas_core->work_queue); release_mem: From f7943f0f072a632ecc9bfe736ab9173fe9faac02 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 19 Nov 2019 18:26:47 -0800 Subject: [PATCH 229/790] msm: camera: icp: Increase the wait time for abort ACK This change attempts to retry waiting atleast 1 time for a duration of 1 second for the abort ACK from FW. Also adds some debug messages during flush and removes mutex usage during page fault dump. CRs-Fixed: 2588575 Change-Id: I2f273baa3d56ab2dc0368d882470360a3702c53c Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/cam_icp_context.c | 3 - .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 62 +++++++++++++++++-- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 7d2ef39e0aeb..180ea7152a76 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -37,8 +37,6 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova, return -EINVAL; } - mutex_lock(&ctx->ctx_mutex); - if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) { CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d", ctx->ctx_id, ctx->state); @@ -64,7 +62,6 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova, } end: - mutex_unlock(&ctx->ctx_mutex); return rc; } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 67cb42aa1661..65e0f7f66c09 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3031,6 +3031,36 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hw_mgr->a5_jtag_debug); } +static int cam_icp_retry_wait_for_abort( + struct cam_icp_hw_ctx_data *ctx_data) +{ + int retry_cnt = 1; + unsigned long rem_jiffies; + int timeout = 1000; + + CAM_WARN(CAM_ICP, "FW timeout in abort ctx: %u retry_left: %d", + ctx_data->ctx_id, retry_cnt); + while (retry_cnt > 0) { + rem_jiffies = wait_for_completion_timeout( + &ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + if (!rem_jiffies) { + retry_cnt--; + if (retry_cnt > 0) { + CAM_WARN(CAM_ICP, + "FW timeout in abort ctx: %u retry_left: %u", + ctx_data->ctx_id, retry_cnt); + continue; + } + } + + if (retry_cnt > 0) + return 0; + } + + return -ETIMEDOUT; +} + static int cam_icp_mgr_abort_handle( struct cam_icp_hw_ctx_data *ctx_data) { @@ -3074,10 +3104,14 @@ static int cam_icp_mgr_abort_handle( rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, msecs_to_jiffies((timeout))); 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(); + rc = cam_icp_retry_wait_for_abort(ctx_data); + if (rc) { + CAM_ERR(CAM_ICP, + "FW timeout/err in abort handle command ctx: %u", + ctx_data->ctx_id); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_hfi_queue_dump(); + } } kfree(abort_cmd); @@ -4805,6 +4839,24 @@ static int cam_icp_mgr_flush_req(struct cam_icp_hw_ctx_data *ctx_data, return 0; } +static void cam_icp_mgr_flush_info_dump( + struct cam_hw_flush_args *flush_args, uint32_t ctx_id) +{ + int i; + + for (i = 0; i < flush_args->num_req_active; i++) { + CAM_DBG(CAM_ICP, "Flushing active request %lld in ctx %u", + *(int64_t *)flush_args->flush_req_active[i], + ctx_id); + } + + for (i = 0; i < flush_args->num_req_pending; i++) { + CAM_DBG(CAM_ICP, "Flushing pending request %lld in ctx %u", + *(int64_t *)flush_args->flush_req_pending[i], + ctx_id); + } +} + static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; @@ -4838,6 +4890,8 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) if (!atomic_read(&hw_mgr->recovery) && flush_args->num_req_active) { mutex_unlock(&hw_mgr->hw_mgr_mutex); + cam_icp_mgr_flush_info_dump(flush_args, + ctx_data->ctx_id); cam_icp_mgr_abort_handle(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); From 5edf8f04dc024c437842fb211f8ae0975fe5c203 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Sun, 8 Dec 2019 12:56:06 -0800 Subject: [PATCH 230/790] msm: camera: icp: Enqueue the abort cmd in workq The request frame cmds are submitted to the FW in workq context. The abort cmd as part of flush is triggered in user thread context. This change will enqueue the abort as part of flush to FW in workq, thereby ensuring that if there are any pending frames they are submitted prior to the abort cmd. CRs-Fixed: 2588575 Change-Id: I5034ca500cf39dfa0e553c49917fedb8bd084b0b Signed-off-by: Karthik Anantha Ram --- drivers/cam_core/cam_context_utils.c | 1 + drivers/cam_core/cam_hw_mgr_intf.h | 3 + .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 109 +++++++++++++++++- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 + drivers/cam_smmu/cam_smmu_api.c | 4 +- 5 files changed, 113 insertions(+), 6 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index dd5bcd455030..423961aaf2af 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -615,6 +615,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) ctx->dev_name, ctx->ctx_id); flush_args.num_req_pending = 0; + flush_args.last_flush_req = ctx->last_flush_req; while (true) { spin_lock(&ctx->lock); if (list_empty(&temp_list)) { diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 28426b8dc757..fe074734f389 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -258,6 +258,8 @@ struct cam_hw_config_args { * @num_req_active: Num request to flush, valid when flush type is REQ * @flush_req_active: Request active pointers to flush * @flush_type: The flush type + * @last_flush_req: last flush req_id notified to hw_mgr for the + * given stream * */ struct cam_hw_flush_args { @@ -267,6 +269,7 @@ struct cam_hw_flush_args { uint32_t num_req_active; void *flush_req_active[20]; enum flush_type_t flush_type; + uint32_t last_flush_req; }; /** diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 65e0f7f66c09..77e12411f938 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3061,11 +3061,63 @@ static int cam_icp_retry_wait_for_abort( return -ETIMEDOUT; } +static int cam_icp_mgr_abort_handle_wq( + void *priv, void *data) +{ + int rc; + size_t packet_size; + struct hfi_cmd_work_data *task_data = NULL; + struct cam_icp_hw_ctx_data *ctx_data; + struct hfi_cmd_ipebps_async *abort_cmd; + + if (!data || !priv) { + CAM_ERR(CAM_ICP, "Invalid params %pK %pK", data, priv); + return -EINVAL; + } + + task_data = (struct hfi_cmd_work_data *)data; + ctx_data = + (struct cam_icp_hw_ctx_data *)task_data->data; + packet_size = + sizeof(struct hfi_cmd_ipebps_async) + + sizeof(struct hfi_cmd_abort) - + sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct); + abort_cmd = kzalloc(packet_size, GFP_KERNEL); + CAM_DBG(CAM_ICP, "abort pkt size = %d", (int) packet_size); + if (!abort_cmd) { + rc = -ENOMEM; + return rc; + } + + abort_cmd->size = packet_size; + abort_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT; + if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) + abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_ABORT; + else + abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_ABORT; + + abort_cmd->num_fw_handles = 1; + abort_cmd->fw_handles[0] = ctx_data->fw_handle; + abort_cmd->user_data1 = PTR_TO_U64(ctx_data); + abort_cmd->user_data2 = (uint64_t)0x0; + + rc = hfi_write_cmd(abort_cmd); + if (rc) { + kfree(abort_cmd); + return rc; + } + CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK ctx_id %d", + ctx_data->fw_handle, ctx_data, ctx_data->ctx_id); + + kfree(abort_cmd); + return rc; +} + static int cam_icp_mgr_abort_handle( struct cam_icp_hw_ctx_data *ctx_data) { int rc = 0; - unsigned long rem_jiffies; + unsigned long rem_jiffies = 0; size_t packet_size; int timeout = 1000; struct hfi_cmd_ipebps_async *abort_cmd; @@ -3201,6 +3253,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) hw_mgr->ctx_data[ctx_id].fw_handle = 0; hw_mgr->ctx_data[ctx_id].scratch_mem_size = 0; + hw_mgr->ctx_data[ctx_id].last_flush_req = 0; for (i = 0; i < CAM_FRAME_CMD_MAX; i++) clear_bit(i, hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); kfree(hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap); @@ -3808,6 +3861,11 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd"); } + if (req_id <= ctx_data->last_flush_req) + CAM_WARN(CAM_ICP, + "Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u", + req_id, ctx_data->last_flush_req, ctx_data->ctx_id); + rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args); if (rc) goto config_err; @@ -4857,6 +4915,46 @@ static void cam_icp_mgr_flush_info_dump( } } +static int cam_icp_mgr_enqueue_abort( + struct cam_icp_hw_ctx_data *ctx_data) +{ + int timeout = 1000, rc; + unsigned long rem_jiffies = 0; + struct hfi_cmd_work_data *task_data; + struct crm_workq_task *task; + + task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); + if (!task) { + CAM_ERR(CAM_ICP, "no empty task"); + return -ENOMEM; + } + + reinit_completion(&ctx_data->wait_complete); + task_data = (struct hfi_cmd_work_data *)task->payload; + task_data->data = (void *)ctx_data; + task_data->type = ICP_WORKQ_TASK_CMD_TYPE; + task->process_cb = cam_icp_mgr_abort_handle_wq; + cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, + CRM_TASK_PRIORITY_0); + + rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, + msecs_to_jiffies((timeout))); + if (!rem_jiffies) { + rc = cam_icp_retry_wait_for_abort(ctx_data); + if (rc) { + CAM_ERR(CAM_ICP, + "FW timeout/err in abort handle command ctx: %u", + ctx_data->ctx_id); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_hfi_queue_dump(); + return rc; + } + } + + CAM_DBG(CAM_ICP, "Abort after flush is success"); + return 0; +} + static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; @@ -4881,9 +4979,10 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) return -EINVAL; } - CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d", - ctx_data->ctx_id, flush_args->flush_type); - + ctx_data->last_flush_req = flush_args->last_flush_req; + CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d last_flush_req %u", + ctx_data->ctx_id, flush_args->flush_type, + ctx_data->last_flush_req); switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: mutex_lock(&hw_mgr->hw_mgr_mutex); @@ -4892,7 +4991,7 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) mutex_unlock(&hw_mgr->hw_mgr_mutex); cam_icp_mgr_flush_info_dump(flush_args, ctx_data->ctx_id); - cam_icp_mgr_abort_handle(ctx_data); + cam_icp_mgr_enqueue_abort(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 7ca32efd9318..8cab9a80cd30 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -232,6 +232,7 @@ struct cam_ctx_clk_info { * @watch_dog: watchdog timer handle * @watch_dog_reset_counter: Counter for watch dog reset * @icp_dev_io_info: io config resource + * @last_flush_req: last flush req for this ctx */ struct cam_icp_hw_ctx_data { void *context_priv; @@ -253,6 +254,7 @@ struct cam_icp_hw_ctx_data { struct cam_req_mgr_timer *watch_dog; uint32_t watch_dog_reset_counter; struct cam_icp_acquire_dev_info icp_dev_io_info; + uint64_t last_flush_req; }; /** diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index ae237c41a0b5..8a21e0b2ae7d 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -293,6 +293,7 @@ static void cam_smmu_page_fault_work(struct work_struct *work) buf_info); } } + cam_smmu_dump_cb_info(idx); kfree(payload); } @@ -429,8 +430,9 @@ end: if (closest_mapping) { buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd); CAM_INFO(CAM_SMMU, - "Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x", + "Closest map fd %d 0x%lx %llu-%llu 0x%lx-0x%lx buf=%pK mem %0x", closest_mapping->ion_fd, current_addr, + mapping->len, closest_mapping->len, (unsigned long)closest_mapping->paddr, (unsigned long)closest_mapping->paddr + mapping->len, closest_mapping->buf, From 4f8e2cdeffedc065c9b6fb798dea3ed29f36305a Mon Sep 17 00:00:00 2001 From: Prakasha Nayak Date: Thu, 12 Dec 2019 15:18:36 +0530 Subject: [PATCH 231/790] msm: camera: icp: Mapping fw error numbers with error names This change will print ICP error names based on error type. CRs-Fixed: 2456658 Change-Id: I975598a7404f7520912d7b3211b6baa249e7f238 Signed-off-by: Prakasha Nayak --- drivers/cam_icp/fw_inc/hfi_sys_defs.h | 6 ++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 95 +++++++++++++++++-- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/cam_icp/fw_inc/hfi_sys_defs.h index 905b85a53633..f62e8cc99430 100644 --- a/drivers/cam_icp/fw_inc/hfi_sys_defs.h +++ b/drivers/cam_icp/fw_inc/hfi_sys_defs.h @@ -82,6 +82,12 @@ #define CAMERAICP_EHWVIOLATION 11 #define CAMERAICP_ECDMERROR 12 +/* HFI Specific errors. */ +#define CAMERAICP_HFI_ERR_COMMAND_SIZE 1000 +#define CAMERAICP_HFI_ERR_MESSAGE_SIZE 1001 +#define CAMERAICP_HFI_QUEUE_EMPTY 1002 +#define CAMERAICP_HFI_QUEUE_FULL 1003 + /* Core level commands */ /* IPE/BPS core Commands */ #define HFI_CMD_IPE_BPS_COMMON_START \ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 67cb42aa1661..f3a7a1019e0e 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1955,6 +1955,70 @@ static int cam_icp_mgr_cleanup_ctx(struct cam_icp_hw_ctx_data *ctx_data) return 0; } +static const char *cam_icp_error_handle_id_to_type( + uint32_t error_handle) +{ + const char *name = NULL; + + switch (error_handle) { + case CAMERAICP_SUCCESS: + name = "SUCCESS"; + break; + case CAMERAICP_EFAILED: + name = "EFAILED"; + break; + case CAMERAICP_ENOMEMORY: + name = "ENOMEMORY"; + break; + case CAMERAICP_EBADSTATE: + name = "EBADSTATE"; + break; + case CAMERAICP_EBADPARM: + name = "EBADPARM"; + break; + case CAMERAICP_EBADITEM: + name = "EBADITEM"; + break; + case CAMERAICP_EINVALIDFORMAT: + name = "EINVALIDFORMAT"; + break; + case CAMERAICP_EUNSUPPORTED: + name = "EUNSUPPORTED"; + break; + case CAMERAICP_EOUTOFBOUND: + name = "EOUTOFBOUND"; + break; + case CAMERAICP_ETIMEDOUT: + name = "ETIMEDOUT"; + break; + case CAMERAICP_EABORTED: + name = "EABORTED"; + break; + case CAMERAICP_EHWVIOLATION: + name = "EHWVIOLATION"; + break; + case CAMERAICP_ECDMERROR: + name = "ECDMERROR"; + break; + case CAMERAICP_HFI_ERR_COMMAND_SIZE: + name = "HFI_ERR_COMMAND_SIZE"; + break; + case CAMERAICP_HFI_ERR_MESSAGE_SIZE: + name = "HFI_ERR_MESSAGE_SIZE"; + break; + case CAMERAICP_HFI_QUEUE_EMPTY: + name = "HFI_QUEUE_EMPTY"; + break; + case CAMERAICP_HFI_QUEUE_FULL: + name = "HFI_QUEUE_FULL"; + break; + default: + name = NULL; + break; + } + return name; +} + static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) { int i; @@ -2014,8 +2078,10 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) ctx_data->icp_dev_acquire_info->dev_type); else CAM_ERR(CAM_ICP, - "Done with error: %u on ctx_id %d dev %d for req %llu", + "Done with error: %u err_type= [%s] on ctx_id %d dev %d for req %llu", ioconfig_ack->err_type, + cam_icp_error_handle_id_to_type( + ioconfig_ack->err_type), ctx_data->ctx_id, ctx_data->icp_dev_acquire_info->dev_type, request_id); @@ -2088,8 +2154,13 @@ static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr) ipe_config_ack = (struct hfi_msg_ipe_config *)(ioconfig_ack->msg_data); if (ipe_config_ack->rc) { - CAM_ERR(CAM_ICP, "rc = %d err = %u", - ipe_config_ack->rc, ioconfig_ack->err_type); + CAM_ERR(CAM_ICP, "rc = %d failed with\n" + "err_no = [%u] err_type = [%s]", + ipe_config_ack->rc, + ioconfig_ack->err_type, + cam_icp_error_handle_id_to_type( + ioconfig_ack->err_type)); + return -EIO; } ctx_data = (struct cam_icp_hw_ctx_data *) @@ -2254,9 +2325,13 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr) (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; if (ctx_data->state != CAM_ICP_CTX_STATE_FREE) complete(&ctx_data->wait_complete); - CAM_DBG(CAM_ICP, - "received IPE/BPS MAP ACK:ctx_state =%d err_status =%u", - ctx_data->state, ioconfig_ack->err_type); + CAM_DBG(CAM_ICP, "received IPE/BPS\n" + "MAP ACK:ctx_state =%d\n" + "failed with err_no = [%u] err_type = [%s]", + ctx_data->state, + ioconfig_ack->err_type, + cam_icp_error_handle_id_to_type( + ioconfig_ack->err_type)); break; case HFI_IPEBPS_CMD_OPCODE_MEM_UNMAP: ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; @@ -2265,8 +2340,12 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr) if (ctx_data->state != CAM_ICP_CTX_STATE_FREE) complete(&ctx_data->wait_complete); CAM_DBG(CAM_ICP, - "received IPE/BPS UNMAP ACK:ctx_state =%d err_status =%u", - ctx_data->state, ioconfig_ack->err_type); + "received IPE/BPS UNMAP ACK:ctx_state =%d\n" + "failed with err_no = [%u] err_type = [%s]", + ctx_data->state, + ioconfig_ack->err_type, + cam_icp_error_handle_id_to_type( + ioconfig_ack->err_type)); break; default: CAM_ERR(CAM_ICP, "Invalid opcode : %u", From a29622aedc280786a4387e10ee6a39e58d2480cf Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Tue, 3 Dec 2019 18:10:44 +0530 Subject: [PATCH 232/790] msm: camera: jpeg: Add mutex lock to protect jpeg list corruption Due to race conditions, situation can arise where the process_irq and flush for jpeg are being handled in parallel. This will cause the jpeg list corruption. This commit protects the code of adding back to free list in process_irq with the mutex. CRs-Fixed: 2578247 Change-Id: I28ee48bc0d5cfcf3ae4a936b2eb2976226ad88d5 Signed-off-by: Gaurav Jindal --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 793415c924a2..a59a2581410e 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -177,7 +177,9 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) PTR_TO_U64(p_cfg_req->hw_cfg_args.priv); ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); + mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex); list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list); + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); return rc; } From 9fdce6ca87e86261d6e623a9b115c2636b0f5db8 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Tue, 3 Dec 2019 21:39:28 +0530 Subject: [PATCH 233/790] msm: camera: sensor: Add null check for read buffer Add proper null checks for function arguments, including read buffer, before dereferencing them. CRs-Fixed: 2581538 Change-Id: I8c49bbc419e2ac5579341c7dc789da0ed1c4d123 Signed-off-by: Shravan Nevatia --- .../cam_sensor_module/cam_sensor_utils/cam_sensor_util.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 4b2b7781207e..5903bc1ff5fd 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -241,6 +241,12 @@ static int32_t cam_sensor_get_io_buffer( size_t buf_size = 0; int32_t rc = 0; + if (io_cfg == NULL || i2c_settings == NULL) { + CAM_ERR(CAM_SENSOR, + "Invalid args, io buf or i2c settings is NULL"); + return -EINVAL; + } + if (io_cfg->direction == CAM_BUF_OUTPUT) { rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0], &buf_addr, &buf_size); From 080bb2339a921f83648908137775623547b0ec13 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 7 Nov 2019 18:54:27 -0800 Subject: [PATCH 234/790] msm: camera: icp: Enable hang dump on failure In case user does not set any dump lvl, KMD will set to dump on failure as default. CRs-Fixed: 2579908 Change-Id: I036e91f5daceedf575815e7569c0e90c04f8de52 Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 67cb42aa1661..c61779dd6d5d 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1890,6 +1890,8 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void) goto err; } + /* Set default hang dump lvl */ + icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; return rc; err: debugfs_remove_recursive(icp_hw_mgr.dentry); From b2e69c4df04eccb577f332a320c9691599edea2b Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 8 Nov 2019 17:45:22 -0800 Subject: [PATCH 235/790] msm: camera: icp: Dump patching info in case of page faults Currently as part of the page fault handler we only dump the io_bufs. This change dumps all the patched addresses for this request as well. CRs-Fixed: 2579908 Change-Id: If5deec0ad3a8aec82824ef55366084c31a037515 Signed-off-by: Karthik Anantha Ram --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 2 + drivers/cam_utils/cam_packet_util.c | 55 ++++++++++++++++++- drivers/cam_utils/cam_packet_util.h | 16 +++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index c61779dd6d5d..06e3f9b7ed90 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4519,6 +4519,8 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, } } + cam_packet_dump_patch_info(packet, icp_hw_mgr.iommu_hdl, + icp_hw_mgr.iommu_sec_hdl); } static int cam_icp_mgr_config_stream_settings( diff --git a/drivers/cam_utils/cam_packet_util.c b/drivers/cam_utils/cam_packet_util.c index 4eadee666219..1569d5dbafa6 100644 --- a/drivers/cam_utils/cam_packet_util.c +++ b/drivers/cam_utils/cam_packet_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -154,6 +154,59 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet, return rc; } +void cam_packet_dump_patch_info(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl) +{ + struct cam_patch_desc *patch_desc = NULL; + dma_addr_t iova_addr; + size_t dst_buf_len; + size_t src_buf_size; + int i, rc = 0; + int32_t hdl; + uintptr_t cpu_addr = 0; + uint32_t *dst_cpu_addr; + uint64_t value = 0; + + patch_desc = (struct cam_patch_desc *) + ((uint32_t *) &packet->payload + + packet->patch_offset/4); + + 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, + hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, + "unable to get src buf address for hdl 0x%x", + hdl); + return; + } + + rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl, + &cpu_addr, &dst_buf_len); + if (rc < 0 || !cpu_addr || (dst_buf_len == 0)) { + CAM_ERR(CAM_UTIL, "unable to get dst buf address"); + return; + } + + dst_cpu_addr = (uint32_t *)cpu_addr; + dst_cpu_addr = (uint32_t *)((uint8_t *)dst_cpu_addr + + patch_desc[i].dst_offset); + value = *((uint64_t *)dst_cpu_addr); + CAM_INFO(CAM_UTIL, + "i = %d src_buf 0x%llx src_hdl 0x%x src_buf_with_offset 0x%llx size 0x%llx dst %p dst_offset %u dst_hdl 0x%x value 0x%llx", + i, iova_addr, patch_desc[i].src_buf_hdl, + (iova_addr + patch_desc[i].src_offset), + src_buf_size, dst_cpu_addr, + patch_desc[i].dst_offset, + patch_desc[i].dst_buf_hdl, value); + + if (!(*dst_cpu_addr)) + CAM_ERR(CAM_ICP, "Null at dst addr %p", dst_cpu_addr); + } +} + int cam_packet_util_process_patches(struct cam_packet *packet, int32_t iommu_hdl, int32_t sec_mmu_hdl) { diff --git a/drivers/cam_utils/cam_packet_util.h b/drivers/cam_utils/cam_packet_util.h index d5fc8f70ec07..62866a962cc6 100644 --- a/drivers/cam_utils/cam_packet_util.h +++ b/drivers/cam_utils/cam_packet_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_PACKET_UTIL_H_ @@ -86,6 +86,20 @@ int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc); int cam_packet_util_get_kmd_buffer(struct cam_packet *packet, struct cam_kmd_buf_info *kmd_buf_info); +/** + * cam_packet_dump_patch_info() + * + * @brief: Dump patch info in case of page fault + * + * @packet: Input packet containing Command Buffers and Patches + * @iommu_hdl: IOMMU handle of the HW Device that received the packet + * @sec_iommu_hdl: Secure IOMMU handle of the HW Device that + * received the packet + * + */ +void cam_packet_dump_patch_info(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl); + /** * cam_packet_util_process_patches() * From 42e7f5c6d809f1eb8d0ef2bfe0e59f9d165dc4c4 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 6 Jan 2020 15:11:49 -0800 Subject: [PATCH 236/790] msm: camera: custom: Disable overflow recovery This change disables overflow recovery/detection for custom CSID. Currently for QCOM CSID we enable overflow detection and freeze on overflow. But for custom HW the CSID needs to be free running, custom HW will take care of handling any backpressure from IFE pipeline/DDR. There is no need to backpressure to CSID in case of custom HW. CRs-Fixed: 2524308 Change-Id: I5de62eea0e87674d7ac24bb5ad2f11ff2a5a6b7c Signed-off-by: Karthik Anantha Ram --- .../cam_custom_csid/cam_custom_csid480.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h index a55bb002ffc2..da98ebf104c7 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid480.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CUSTOM_CSID_480_H_ @@ -56,7 +56,7 @@ static struct cam_ife_csid_udi_reg_offset .csid_udi_byte_cntr_pong_addr = 0x2e4, /* configurations */ .ccif_violation_en = 1, - .overflow_ctrl_en = 1, + .overflow_ctrl_en = 0, }; static struct cam_ife_csid_udi_reg_offset @@ -105,7 +105,7 @@ static struct cam_ife_csid_udi_reg_offset .csid_udi_byte_cntr_pong_addr = 0x3e4, /* configurations */ .ccif_violation_en = 1, - .overflow_ctrl_en = 1, + .overflow_ctrl_en = 0, }; static struct cam_ife_csid_udi_reg_offset @@ -155,7 +155,7 @@ static struct cam_ife_csid_udi_reg_offset .csid_udi_byte_cntr_pong_addr = 0x4e4, /* configurations */ .ccif_violation_en = 1, - .overflow_ctrl_en = 1, + .overflow_ctrl_en = 0, }; static struct cam_ife_csid_csi2_rx_reg_offset From 287b7b22d7c0a262d83f117692980e65226a3cff Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 9 Jan 2020 12:18:17 -0800 Subject: [PATCH 237/790] msm: camera: isp: Change data type for error handling Use unsigned long to capture the return value of wait_for_completion APIs as part of CSID path reset. CRs-Fixed: 2600604 Change-Id: Ic21ddf283180a177b2c2d9e9a33fec4ec68bdd98 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4baf5f37ac38..72c2a5ab3792 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -249,7 +249,7 @@ static int cam_ife_hw_mgr_reset_csid_res( rc = hw_intf->hw_ops.reset(hw_intf->hw_priv, &csid_reset_args, sizeof(struct cam_csid_reset_cfg_args)); - if (rc <= 0) + if (rc) goto err; } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 3682823a496b..0ee18c2787a9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -529,6 +529,7 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, struct cam_csid_reset_cfg_args *reset) { int rc = 0; + unsigned long rem_jiffies; struct cam_hw_soc_info *soc_info; struct cam_isp_resource_node *res; const struct cam_ife_csid_reg_offset *csid_reg; @@ -648,14 +649,13 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + reset_strb_addr); - rc = wait_for_completion_timeout(complete, + rem_jiffies = wait_for_completion_timeout(complete, msecs_to_jiffies(IFE_CSID_TIMEOUT)); - if (rc <= 0) { + if (!rem_jiffies) { + rc = -ETIMEDOUT; CAM_ERR(CAM_ISP, "CSID:%d Res id %d fail rc = %d", csid_hw->hw_intf->hw_idx, res->res_id, rc); - if (rc == 0) - rc = -ETIMEDOUT; } end: From 118b93f5ddc2b9e1c828dcc1788f0fb29c15a52f Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 8 Jan 2020 19:04:51 -0800 Subject: [PATCH 238/790] msm: camera: custom: Add support for immediate stop Add support for immediate stop and reset during flush for custom HW. CRs-Fixed: 2585745 Change-Id: I542ac02f8d99c194efa498bc07dffae7879a6c8a Signed-off-by: Karthik Anantha Ram --- drivers/cam_cust/cam_custom_context.c | 225 +++++++++++++----- .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 99 +++++++- 2 files changed, 267 insertions(+), 57 deletions(-) diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 3e69ebd15109..25e092841cef 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -24,6 +24,10 @@ static const char custom_dev_name[] = "cam-custom"; static int __cam_custom_ctx_handle_irq_in_activated( void *context, uint32_t evt_id, void *evt_data); +static int __cam_custom_ctx_start_dev_in_ready( + struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); + + static int __cam_custom_ctx_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) { @@ -131,22 +135,104 @@ static int __cam_custom_ctx_flush_req(struct cam_context *ctx, return 0; } +static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + ctx->link_hdl = -1; + ctx->ctx_crm_intf = NULL; + + return 0; +} + +static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, + struct cam_req_mgr_core_dev_link_setup *unlink) +{ + ctx->link_hdl = -1; + ctx->ctx_crm_intf = NULL; + ctx->state = CAM_CTX_ACQUIRED; + + return 0; +} + +static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, + struct cam_req_mgr_device_info *dev_info) +{ + dev_info->dev_hdl = ctx->dev_hdl; + strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); + dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; + dev_info->p_delay = 1; + dev_info->trigger = CAM_TRIGGER_POINT_SOF; + + return 0; +} + static int __cam_custom_ctx_flush_req_in_top_state( struct cam_context *ctx, struct cam_req_mgr_flush_request *flush_req) { int rc = 0; + struct cam_custom_context *custom_ctx; + struct cam_hw_reset_args reset_args; + struct cam_hw_stop_args stop_args; + struct cam_custom_stop_args custom_stop; + + custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + CAM_DBG(CAM_CUSTOM, "Flushing pending list"); + spin_lock_bh(&ctx->lock); + __cam_custom_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 (ctx->state <= CAM_CTX_READY) { + ctx->state = CAM_CTX_ACQUIRED; + goto end; + } + + spin_lock_bh(&ctx->lock); + ctx->state = CAM_CTX_FLUSHED; + spin_unlock_bh(&ctx->lock); + CAM_INFO(CAM_CUSTOM, "Last request id to flush is %lld", flush_req->req_id); ctx->last_flush_req = flush_req->req_id; + + /* stop hw first */ + if (ctx->hw_mgr_intf->hw_stop) { + custom_stop.stop_only = true; + stop_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + stop_args.args = (void *) &custom_stop; + rc = ctx->hw_mgr_intf->hw_stop( + ctx->hw_mgr_intf->hw_mgr_priv, &stop_args); + if (rc) + CAM_ERR(CAM_CUSTOM, + "HW stop failed in flush rc %d", rc); + } + + spin_lock_bh(&ctx->lock); + if (!list_empty(&ctx->wait_req_list)) + __cam_custom_ctx_flush_req(ctx, &ctx->wait_req_list, + flush_req); + + if (!list_empty(&ctx->active_req_list)) + __cam_custom_ctx_flush_req(ctx, &ctx->active_req_list, + flush_req); + + custom_ctx->active_req_cnt = 0; + spin_unlock_bh(&ctx->lock); + + reset_args.ctxt_to_hw_map = custom_ctx->hw_ctx; + rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, + &reset_args); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Reset HW failed in flush rc %d", rc); + + custom_ctx->init_received = false; } - spin_lock_bh(&ctx->lock); - rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); - spin_unlock_bh(&ctx->lock); - +end: return rc; } @@ -170,34 +256,27 @@ static int __cam_custom_ctx_flush_req_in_ready( return rc; } -static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, - struct cam_req_mgr_core_dev_link_setup *unlink) -{ - ctx->link_hdl = -1; - ctx->ctx_crm_intf = NULL; - ctx->state = CAM_CTX_ACQUIRED; - - return 0; -} - static int __cam_custom_stop_dev_core( struct cam_context *ctx, struct cam_start_stop_dev_cmd *stop_cmd) { int rc = 0; uint32_t i; struct cam_custom_context *ctx_custom = - (struct cam_custom_context *) ctx->ctx_priv; - struct cam_ctx_request *req; - struct cam_custom_dev_ctx_req *req_custom; - struct cam_hw_stop_args stop; + (struct cam_custom_context *) ctx->ctx_priv; + struct cam_ctx_request *req; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_hw_stop_args stop; + struct cam_custom_stop_args custom_stop; - if (ctx_custom->hw_ctx) { + if ((ctx->state != CAM_CTX_FLUSHED) && (ctx_custom->hw_ctx) && + (ctx->hw_mgr_intf->hw_stop)) { + custom_stop.stop_only = false; stop.ctxt_to_hw_map = ctx_custom->hw_ctx; - - stop.args = NULL; - if (ctx->hw_mgr_intf->hw_stop) - ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + stop.args = (void *) &custom_stop; + rc = ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop); + if (rc) + CAM_ERR(CAM_CUSTOM, "HW stop failed rc %d", rc); } while (!list_empty(&ctx->pending_req_list)) { @@ -752,7 +831,9 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, CAM_ERR(CAM_CUSTOM, "Recevied INIT pkt in wrong state"); } } else { - if (ctx->state >= CAM_CTX_READY && ctx->ctx_crm_intf->add_req) { + if ((ctx->state != CAM_CTX_FLUSHED) && + (ctx->state >= CAM_CTX_READY) && + (ctx->ctx_crm_intf->add_req)) { add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; @@ -796,6 +877,44 @@ free_req: } +static int __cam_custom_ctx_config_dev_in_flushed(struct cam_context *ctx, + struct cam_config_dev_cmd *cmd) +{ + int rc = 0; + struct cam_start_stop_dev_cmd start_cmd; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + if (!custom_ctx->hw_acquired) { + CAM_ERR(CAM_CUSTOM, "HW is not acquired, reject packet"); + rc = -EINVAL; + goto end; + } + + rc = __cam_custom_ctx_config_dev(ctx, cmd); + if (rc) + goto end; + + if (!custom_ctx->init_received) { + CAM_WARN(CAM_CUSTOM, + "Received update packet in flushed state, skip start"); + goto end; + } + + start_cmd.dev_handle = cmd->dev_handle; + start_cmd.session_handle = cmd->session_handle; + rc = __cam_custom_ctx_start_dev_in_ready(ctx, &start_cmd); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Failed to re-start HW after flush rc: %d", rc); + else + CAM_INFO(CAM_CUSTOM, + "Received init after flush. Re-start HW complete."); + +end: + return rc; +} + static int __cam_custom_ctx_config_dev_in_acquired(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { @@ -835,32 +954,11 @@ static int __cam_custom_ctx_link_in_acquired(struct cam_context *ctx, return 0; } -static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, - struct cam_req_mgr_core_dev_link_setup *unlink) -{ - ctx->link_hdl = -1; - ctx->ctx_crm_intf = NULL; - - return 0; -} - -static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, - struct cam_req_mgr_device_info *dev_info) -{ - dev_info->dev_hdl = ctx->dev_hdl; - strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); - dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; - dev_info->p_delay = 1; - dev_info->trigger = CAM_TRIGGER_POINT_SOF; - - return 0; -} - static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; - struct cam_hw_config_args hw_config; + struct cam_custom_start_args custom_start; struct cam_ctx_request *req; struct cam_custom_dev_ctx_req *req_custom; struct cam_custom_context *ctx_custom = @@ -889,16 +987,20 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } - hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; - hw_config.request_id = req->request_id; - hw_config.hw_update_entries = req_custom->cfg; - hw_config.num_hw_update_entries = req_custom->num_cfg; - hw_config.priv = &req_custom->hw_update_data; - hw_config.init_packet = 1; + custom_start.hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; + custom_start.hw_config.request_id = req->request_id; + custom_start.hw_config.hw_update_entries = req_custom->cfg; + custom_start.hw_config.num_hw_update_entries = req_custom->num_cfg; + custom_start.hw_config.priv = &req_custom->hw_update_data; + custom_start.hw_config.init_packet = 1; + if (ctx->state == CAM_CTX_FLUSHED) + custom_start.start_only = true; + else + custom_start.start_only = false; ctx->state = CAM_CTX_ACTIVATED; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, - &hw_config); + &custom_start); if (rc) { /* HW failure. User need to clean up the resource */ CAM_ERR(CAM_CUSTOM, "Start HW failed"); @@ -1064,7 +1166,20 @@ static struct cam_ctx_ops .pagefault_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .stop_dev = __cam_custom_stop_dev_in_activated, + .release_dev = + __cam_custom_ctx_release_dev_in_activated, + .config_dev = __cam_custom_ctx_config_dev_in_flushed, + .release_hw = + __cam_custom_ctx_release_hw_in_activated_state, + }, + .crm_ops = { + .unlink = __cam_custom_ctx_unlink_in_ready, + }, + .irq_ops = NULL, + }, /* Activated */ { .ioctl_ops = { diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index 78226a5f32ac..7587e41aa6f7 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -222,6 +222,7 @@ err: static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { int rc = 0; + struct cam_custom_stop_args *custom_args; struct cam_hw_stop_args *stop_args = stop_hw_args; struct cam_custom_hw_mgr_res *hw_mgr_res; struct cam_custom_hw_mgr_ctx *ctx; @@ -231,6 +232,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) return -EINVAL; } + custom_args = (struct cam_custom_stop_args *)stop_args->args; ctx = (struct cam_custom_hw_mgr_ctx *) stop_args->ctxt_to_hw_map; @@ -263,6 +265,9 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* stop custom hw here */ + if (custom_args->stop_only) + goto end; + /* Deinit custom cid here */ list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_cid, list) { @@ -284,6 +289,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* deinit custom rsrc */ +end: return rc; } @@ -359,13 +365,19 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, struct cam_hw_stop_args stop_args; struct cam_custom_hw_mgr_res *hw_mgr_res; struct cam_custom_hw_mgr_ctx *ctx; + struct cam_custom_stop_args custom_stop_args; + struct cam_custom_start_args *custom_args; if (!hw_mgr_priv || !start_hw_args) { CAM_ERR(CAM_CUSTOM, "Invalid arguments"); return -EINVAL; } - hw_config = (struct cam_hw_config_args *)start_hw_args; + custom_args = + (struct cam_custom_start_args *)start_hw_args; + + hw_config = (struct cam_hw_config_args *) + &custom_args->hw_config; ctx = (struct cam_custom_hw_mgr_ctx *) hw_config->ctxt_to_hw_map; @@ -377,6 +389,9 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, CAM_DBG(CAM_CUSTOM, "Enter... ctx id:%d", ctx->ctx_index); + if (custom_args->start_only) + goto start_only; + /* Init custom cid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_cid, list) { @@ -404,6 +419,8 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, /* Apply init config */ +start_only: + /* Start custom HW first */ if (rc < 0) goto err; @@ -434,6 +451,8 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, return 0; err: + custom_stop_args.stop_only = false; + stop_args.args = (void *) &custom_stop_args; stop_args.ctxt_to_hw_map = hw_config->ctxt_to_hw_map; cam_custom_mgr_stop_hw(hw_mgr_priv, &stop_args); deinit_hw: @@ -1115,6 +1134,81 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, return 0; } +static int cam_custom_hw_mgr_reset_csid_res( + struct cam_custom_hw_mgr_res *hw_mgr_res) +{ + int rc = -1; + struct cam_csid_reset_cfg_args csid_reset_args; + struct cam_isp_resource_node *custom_rsrc_node = NULL; + struct cam_hw_intf *hw_intf = NULL; + + custom_rsrc_node = + (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; + if (!custom_rsrc_node) { + CAM_ERR(CAM_CUSTOM, "Invalid args"); + return -EINVAL; + } + + csid_reset_args.reset_type = CAM_IFE_CSID_RESET_PATH; + csid_reset_args.node_res = custom_rsrc_node; + hw_intf = custom_rsrc_node->hw_intf; + if (hw_intf->hw_ops.reset) { + CAM_DBG(CAM_CUSTOM, "RESET HW for res_id:%u", + hw_mgr_res->res_id); + rc = hw_intf->hw_ops.reset(hw_intf->hw_priv, + &csid_reset_args, + sizeof(struct cam_csid_reset_cfg_args)); + if (rc) + goto err; + } + + return 0; + +err: + CAM_ERR(CAM_CUSTOM, + "RESET HW failed for res_id:%u", + hw_mgr_res->res_id); + return rc; +} + +static int cam_custom_hw_mgr_reset( + void *hw_mgr_priv, void *hw_reset_args) +{ + struct cam_hw_reset_args *reset_args = + hw_reset_args; + struct cam_custom_hw_mgr_ctx *ctx; + struct cam_custom_hw_mgr_res *hw_mgr_res; + int rc = 0; + + if (!hw_mgr_priv || !hw_reset_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_custom_hw_mgr_ctx *) + reset_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_CUSTOM, "Reset SBI CSID and SBI core"); + list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_csid, list) { + rc = cam_custom_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_CUSTOM, + "Failed to reset CSID:%d rc: %d", + hw_mgr_res->res_id, rc); + goto end; + } + } + + /* Reset SBI HW */ + +end: + return rc; +} + static int cam_custom_mgr_config_hw(void *hw_mgr_priv, void *hw_config_args) { @@ -1281,6 +1375,7 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_release = cam_custom_mgr_release_hw; hw_mgr_intf->hw_prepare_update = cam_custom_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_custom_mgr_config_hw; + hw_mgr_intf->hw_reset = cam_custom_hw_mgr_reset; if (iommu_hdl) *iommu_hdl = g_custom_hw_mgr.img_iommu_hdl; From fbfa512811363025da5fae0dc2bbc418103b9b00 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 11 Oct 2019 15:39:42 -0700 Subject: [PATCH 239/790] msm: camera: reqmgr: Reduce delay by one frame during bubble recovery The EPOCH at which bubble is detected no setting is applied to any device. This change will trigger applying the bubbled setting to the device with highest pipeline delay. CRs-Fixed: 2564669 Change-Id: I180b4a1d2d29267f330546b8860a099baf1688e9 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 15 +++++++++++ drivers/cam_req_mgr/cam_req_mgr_core.c | 30 +++++++++++++++++++++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 6 +++++ 3 files changed, 51 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 79e57b629cdc..c3cb14ea3832 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1102,6 +1102,11 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; notify.error = CRM_KMD_ERR_BUBBLE; + notify.trigger = 0; + if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) + notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.frame_id = ctx_isp->frame_id; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; CAM_WARN(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); @@ -1264,6 +1269,11 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; notify.error = CRM_KMD_ERR_BUBBLE; + notify.trigger = 0; + if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) + notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.frame_id = ctx_isp->frame_id; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; CAM_WARN(CAM_REQ, "Notify CRM about Bubble req_id %llu frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); @@ -2564,6 +2574,11 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; notify.error = CRM_KMD_ERR_BUBBLE; + notify.trigger = 0; + if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) + notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.frame_id = ctx_isp->frame_id; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; CAM_WARN(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld ctx %u", req->request_id, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 0a4af3c097d0..e67a8050f574 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2321,6 +2321,35 @@ end: return rc; } +/** + * __cam_req_mgr_apply_on_bubble() + * + * @brief : This API tries to apply settings to the device + * with highest pd on the bubbled frame + * @link : link information. + * @err_info : contains information about frame_id, trigger etc. + * + */ +void __cam_req_mgr_apply_on_bubble( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_error_notify *err_info) +{ + int rc = 0; + struct cam_req_mgr_trigger_notify trigger_data; + + trigger_data.dev_hdl = err_info->dev_hdl; + trigger_data.frame_id = err_info->frame_id; + trigger_data.link_hdl = err_info->link_hdl; + trigger_data.sof_timestamp_val = + err_info->sof_timestamp_val; + trigger_data.trigger = err_info->trigger; + + rc = __cam_req_mgr_process_req(link, &trigger_data); + if (rc) + CAM_ERR(CAM_CRM, + "Failed to apply request on bubbled frame"); +} + /** * cam_req_mgr_process_error() * @@ -2405,6 +2434,7 @@ int cam_req_mgr_process_error(void *priv, void *data) link->state = CAM_CRM_LINK_STATE_ERR; spin_unlock_bh(&link->link_state_spin_lock); link->open_req_cnt++; + __cam_req_mgr_apply_on_bubble(link, err_info); } } mutex_unlock(&link->req.lock); diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 5df13b26e215..2294ff27f50b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -227,12 +227,18 @@ struct cam_req_mgr_timer_notify { * @link_hdl : link identifier * @dev_hdl : device handle which has sent this req id * @req_id : req id which hit error + * @frame_id : frame id for internal tracking + * @trigger : trigger point of this notification, CRM will send apply + * @sof_timestamp_val : Captured time stamp value at sof hw event * @error : what error device hit while processing this req */ struct cam_req_mgr_error_notify { int32_t link_hdl; int32_t dev_hdl; uint64_t req_id; + int64_t frame_id; + uint32_t trigger; + uint64_t sof_timestamp_val; enum cam_req_mgr_device_error error; }; From 10d42b7f6c53bed14c9740f3c8b180b2ef5fc66f Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Tue, 17 Dec 2019 15:21:45 +0530 Subject: [PATCH 240/790] msm: camera: isp: Mask unused rdi interrupts Enable rdi interrupts from the required sources only, other unused interrupts from rdi sources should be masked. Also in the case where multiple rdi has been acquired in same context interrupts from only one of them should be enabled. CRs-Fixed: 2590476 Change-Id: Icd074d1566db0b758d25c7b127402b424e48efd9 Signed-off-by: Tejas Prajapati --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index 7aaacde775f4..a0e7741e5505 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -212,7 +212,7 @@ static int cam_vfe_rdi_resource_start( struct cam_vfe_mux_rdi_data *rsrc_data; int rc = 0; uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; - uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t rdi_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; if (!rdi_res) { CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); @@ -230,10 +230,6 @@ static int cam_vfe_rdi_resource_start( rsrc_data->rdi_common_reg_data->error_irq_mask0; err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = rsrc_data->rdi_common_reg_data->error_irq_mask1; - irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = - rsrc_data->rdi_common_reg_data->subscribe_irq_mask0; - irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = - rsrc_data->rdi_common_reg_data->subscribe_irq_mask1; rdi_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; @@ -261,11 +257,19 @@ static int cam_vfe_rdi_resource_start( if (!rdi_res->rdi_only_ctx) goto end; + rdi_irq_mask[0] = + (rsrc_data->reg_data->reg_update_irq_mask | + rsrc_data->reg_data->sof_irq_mask); + + CAM_DBG(CAM_ISP, "RDI%d irq_mask 0x%x", + rdi_res->res_id - CAM_ISP_HW_VFE_IN_RDI0, + rdi_irq_mask[0]); + if (!rsrc_data->irq_handle) { rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, CAM_IRQ_PRIORITY_1, - irq_mask, + rdi_irq_mask, rdi_res, rdi_res->top_half_handler, rdi_res->bottom_half_handler, From 7d3a0f3abb9e5c0c5a318abd0ab6328df9aaf5e4 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 19 Dec 2019 12:55:45 +0530 Subject: [PATCH 241/790] msm: camera: isp: Update unlink handling to avoid race Expire timer after destroying workqueues so that we do not refer to watchdog timer while the link is getting unlinked from session handle. CRs-Fixed: 2585098 Change-Id: Ife2450ae66bd52ec704ac7d593b2daaeb20ba54d Signed-off-by: Vikram Sharma --- drivers/cam_req_mgr/cam_req_mgr_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 0a4af3c097d0..2d5e12c09522 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3026,12 +3026,13 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) } mutex_lock(&link->lock); - /* Destroy timer of link */ - crm_timer_exit(&link->watchdog); /* Destroy workq of link */ cam_req_mgr_workq_destroy(&link->workq); + /* Destroy timer of link */ + crm_timer_exit(&link->watchdog); + /* Cleanup request tables and unlink devices */ __cam_req_mgr_destroy_link_info(link); From cc79abb0a512cc58a7764bfcbf8eb17c00e086b6 Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Tue, 17 Dec 2019 12:44:44 +0530 Subject: [PATCH 242/790] msm: camera: sync: correcting atomic read operation This change rectifies the reading of atomic variable. CRs-Fixed: 2591537 Change-Id: I13c289bc00a07d5c2289e2e3f13245bbc521d4ee Signed-off-by: Alok Pandey --- drivers/cam_sync/cam_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index f32cc1c2dbef..b431ef0a0bd9 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -38,7 +38,7 @@ static void cam_sync_print_fence_table(void) sync_dev->sync_table[idx].name, sync_dev->sync_table[idx].type, sync_dev->sync_table[idx].state, - sync_dev->sync_table[idx].ref_cnt); + atomic_read(&sync_dev->sync_table[idx].ref_cnt)); spin_unlock_bh(&sync_dev->row_spinlocks[idx]); } } From 9303d3ae02022efc25d8683b1a769a20fad646cc Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 23 Dec 2019 11:42:09 +0800 Subject: [PATCH 243/790] msm: camera: sensor: Fix an operator error - Fix an operator error in cam_sensor_flush_request CRs-Fixed: 2591694 Change-Id: I39a8b29f83db55d2a930dd5ccd2b765517e2c1d6 Signed-off-by: Depeng Shao --- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 6902122b3f66..37f62fe95246 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -1319,8 +1319,8 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) } mutex_lock(&(s_ctrl->cam_sensor_mutex)); - if (s_ctrl->sensor_state != CAM_SENSOR_START || - s_ctrl->sensor_state != CAM_SENSOR_CONFIG) { + if ((s_ctrl->sensor_state != CAM_SENSOR_START) && + (s_ctrl->sensor_state != CAM_SENSOR_CONFIG)) { mutex_unlock(&(s_ctrl->cam_sensor_mutex)); return rc; } From 043c37f2b49038578873cb3a85532a39bd974a1b Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 18 Dec 2019 15:53:50 -0800 Subject: [PATCH 244/790] msm: camera: sensor: Add Init setting retry in case cci is resetting If any subdev is reporting Nack, cci hardware gets into resetting. During resetting if sensor tries to apply Init setting, it fails. This change adds retry for INIT setting to reapply after sometime. CRs-Fixed: 2598605 Change-Id: Iff13014d74abe6aebaec6cd428811de9d865f090 Signed-off-by: Jigarkumar Zala --- .../cam_actuator/cam_actuator_core.c | 15 +++++++++++--- .../cam_flash/cam_flash_core.c | 12 ++++++++++- .../cam_sensor_module/cam_ois/cam_ois_core.c | 14 +++++++++++-- .../cam_sensor/cam_sensor_core.c | 20 ++++++++++++++++--- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index d886d8ebaecb..0b6e25572e90 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -957,10 +957,19 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, ACT_APPLY_SETTINGS_NOW) { rc = cam_actuator_apply_settings(a_ctrl, &a_ctrl->i2c_data.init_settings); + if ((rc == -EAGAIN) && + (a_ctrl->io_master_info.master_type == CCI_MASTER)) { + CAM_WARN(CAM_ACTUATOR, + "CCI HW is in resetting mode:: Reapplying Init settings"); + usleep_range(1000, 1010); + rc = cam_actuator_apply_settings(a_ctrl, + &a_ctrl->i2c_data.init_settings); + } + if (rc < 0) CAM_ERR(CAM_ACTUATOR, - "Cannot apply Update settings"); - + "Failed to apply Init settings: rc = %d", + rc); /* Delete the request even if the apply is failed */ rc = delete_request(&a_ctrl->i2c_data.init_settings); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 063848104f63..2d8df8a0ac41 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -662,6 +662,16 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, list) { rc = cam_sensor_util_i2c_apply_setting (&(fctrl->io_master_info), i2c_list); + if ((rc == -EAGAIN) && + (fctrl->io_master_info.master_type == + CCI_MASTER)) { + CAM_WARN(CAM_FLASH, + "CCI HW is in reset mode: Reapplying Init settings"); + usleep_range(1000, 1010); + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + } + if (rc) { CAM_ERR(CAM_FLASH, "Failed to apply init settings: %d", diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 4a3cd853e22b..3ee402e2661d 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -583,8 +583,18 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data); + if ((rc == -EAGAIN) && + (o_ctrl->io_master_info.master_type == CCI_MASTER)) { + CAM_WARN(CAM_OIS, + "CCI HW is restting: Reapplying INIT settings"); + usleep_range(1000, 1010); + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_init_data); + } if (rc < 0) { - CAM_ERR(CAM_OIS, "Cannot apply Init settings"); + CAM_ERR(CAM_OIS, + "Cannot apply Init settings: rc = %d", + rc); goto pwr_dwn; } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 6902122b3f66..b9862cbc3dc4 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -644,7 +644,7 @@ int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl) int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, void *arg) { - int rc = 0; + int rc = 0, pkt_opcode = 0; struct cam_control *cmd = (struct cam_control *)arg; struct cam_sensor_power_ctrl_t *power_info = &s_ctrl->sensordata->power_info; @@ -932,14 +932,28 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, if (s_ctrl->i2c_data.init_settings.is_settings_valid && (s_ctrl->i2c_data.init_settings.request_id == 0)) { + pkt_opcode = + CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG; rc = cam_sensor_apply_settings(s_ctrl, 0, - CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG); + pkt_opcode); + if ((rc == -EAGAIN) && + (s_ctrl->io_master_info.master_type == CCI_MASTER)) { + /* If CCI hardware is resetting we need to wait + * for sometime before reapply + */ + CAM_WARN(CAM_SENSOR, + "Reapplying the Init settings due to cci hw reset"); + usleep_range(1000, 1010); + rc = cam_sensor_apply_settings(s_ctrl, 0, + pkt_opcode); + } s_ctrl->i2c_data.init_settings.request_id = -1; if (rc < 0) { CAM_ERR(CAM_SENSOR, - "cannot apply init settings"); + "cannot apply init settings rc= %d", + rc); delete_request(&s_ctrl->i2c_data.init_settings); goto release_mutex; } From f01052856673a969a5e9fe3bcd8e8ee6291a1136 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 11 Dec 2019 13:20:01 -0800 Subject: [PATCH 245/790] msm: camera: req_mgr: Increase watchdog timeout This change increases the watchdog timeout value from one second to five. CRs-Fixed: 2606911 Change-Id: I353f78369c31a513dfd94dd1988bc42c2f75b167 Signed-off-by: Venkat Chinta --- drivers/cam_req_mgr/cam_req_mgr_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 0afdc69b0445..9bc7e9b4bb2e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_CORE_H_ #define _CAM_REQ_MGR_CORE_H_ @@ -13,7 +13,7 @@ #define CAM_REQ_MGR_MAX_LINKED_DEV 16 #define MAX_REQ_SLOTS 48 -#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 1000 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 #define CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX 50000 #define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 #define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 From 5fec859ec63c08095870c5ed88ffe36e037eea3b Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 19 Dec 2019 16:00:05 -0800 Subject: [PATCH 246/790] msm: camera: ife: Disable clock gating at top Clock gating must be disabled at top level initialize hardware routine as VFE is reset after resource level initialize hardware routine. CRs-Fixed: 2590331 Change-Id: I5c51c402a3a6076f056368493b774daa199228aa Signed-off-by: Venkat Chinta --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 14 -------------- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 5b79b90cb827..e558e9087fe8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -298,20 +298,6 @@ static int cam_vfe_camif_ver3_resource_init( "failed to enable dsp clk, rc = %d", rc); } - /* All auto clock gating disabled by default */ - CAM_INFO(CAM_ISP, "overriding clock gating"); - cam_io_w_mb(0xFFFFFFFF, camif_data->mem_base + - camif_data->common_reg->core_cgc_ovd_0); - - cam_io_w_mb(0xFF, camif_data->mem_base + - camif_data->common_reg->core_cgc_ovd_1); - - cam_io_w_mb(0x1, camif_data->mem_base + - camif_data->common_reg->ahb_cgc_ovd); - - cam_io_w_mb(0x1, camif_data->mem_base + - camif_data->common_reg->noc_cgc_ovd); - return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 743950bd01bc..2bd393fc97a8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -222,9 +222,24 @@ int cam_vfe_top_ver3_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { struct cam_vfe_top_ver3_priv *top_priv = device_priv; + struct cam_vfe_top_ver3_common_data common_data = top_priv->common_data; top_priv->hw_clk_rate = 0; + /* Disable clock gating at IFE top */ + CAM_INFO(CAM_ISP, "Disable clock gating at IFE top"); + cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, + common_data.common_reg->core_cgc_ovd_0, 0xFFFFFFFF); + + cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, + common_data.common_reg->core_cgc_ovd_1, 0xFF); + + cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, + common_data.common_reg->ahb_cgc_ovd, 0x1); + + cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, + common_data.common_reg->noc_cgc_ovd, 0x1); + return 0; } From 0fb8f447c145330c5666d343c39fdd577781b6f4 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 14 Jan 2020 15:53:54 -0800 Subject: [PATCH 247/790] msm: camera: req_mgr: Reduce maximum attempts to apply request This change reduces the maximum attempts to apply a particular request from three to two. After two failed attempts to apply to ISP device, IRQs for ISP device will be overlapped from two requests. Thereafter apply request at every alternate frame will fail without a chance of recovery. Therefore we must notify userspace to trigger recover on the link. CRs-Fixed: 2606911 Change-Id: I526bb837a496fe1e67786b854c5afb062dddb918 Signed-off-by: Venkat Chinta --- drivers/cam_req_mgr/cam_req_mgr_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 9bc7e9b4bb2e..fd5f3a751a39 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -33,7 +33,7 @@ #define MAXIMUM_LINKS_PER_SESSION 4 -#define MAXIMUM_RETRY_ATTEMPTS 3 +#define MAXIMUM_RETRY_ATTEMPTS 2 #define VERSION_1 1 #define VERSION_2 2 From 0f1162d0996482ef34016e9ae46c81b20d84f641 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 11 Dec 2019 13:12:58 -0800 Subject: [PATCH 248/790] msm: camera: ife: Stop hardware in error This change adds logic to stop IFE hardware in case of hardware errors. CRs-Fixed: 2590331 Change-Id: I86773cc44ce890cea47f19f0482761e686b0cd00 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 23 +++++++-------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4baf5f37ac38..09b803ac650d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5968,6 +5968,9 @@ static int cam_ife_mgr_process_recovery_cb(void *priv, void *data) } } + if (!g_ife_hw_mgr.debug_cfg.enable_recovery) + break; + CAM_DBG(CAM_ISP, "RESET: CSID PATH"); for (i = 0; i < recovery_data->no_of_context; i++) { ctx = recovery_data->affected_ctx[i]; @@ -6193,22 +6196,12 @@ static int cam_ife_hw_mgr_handle_hw_err( rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, core_idx, &recovery_data); - if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) - return rc; + if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) + recovery_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; + else + recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; - if (g_ife_hw_mgr.debug_cfg.enable_recovery) { - CAM_DBG(CAM_ISP, "IFE Mgr recovery is enabled"); - - /* Trigger for recovery */ - if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) - recovery_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; - else - recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; - cam_ife_hw_mgr_do_error_recovery(&recovery_data); - } else { - CAM_DBG(CAM_ISP, "recovery is not enabled"); - rc = 0; - } + cam_ife_hw_mgr_do_error_recovery(&recovery_data); return rc; } From 4e30068212a544d79568ab84b0e2a31e42f83192 Mon Sep 17 00:00:00 2001 From: Abhilash Kumar Date: Wed, 18 Dec 2019 16:27:40 +0530 Subject: [PATCH 249/790] msm: camera: cdm: Clear IRQ before reading userdata CDM driver read the user_data reg to inform CDM's clients about the request status being served. If before clearing the IRQ, the value of userdata register gets updated, then CDM will not receive another INLINE_IRQ for the updated userdata. This change will make sure that another interrupt is fired by clearing the IRQ first and reading the userdata later. CRs-Fixed: 2581559 Change-Id: I74edf1b8439ae2f88f30b6c2fdbf9ac9f3742503 Signed-off-by: Abhilash Kumar Signed-off-by: Venkat Chinta --- drivers/cam_cdm/cam_cdm_hw_core.c | 50 +++++++++------------ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 15 ++++++- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 1142f2776f4f..8145b3293216 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1108,19 +1108,25 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { if (cam_cdm_read_hw_reg(cdm_hw, - cdm_core->offsets->irq_reg[i]->irq_status, - &irq_status[i])) { + cdm_core->offsets->irq_reg[i]->irq_status, + &irq_status[i])) { CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status"); } + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_clear, + irq_status[i])) { + CAM_ERR(CAM_CDM, + "Failed to Write CDM HW IRQ Clear"); + } } + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[0]->irq_clear_cmd, 0x01)) + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd 0"); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { - if (!irq_status[i]) { - cam_cdm_write_hw_reg(cdm_hw, - cdm_core->offsets->irq_reg[i]->irq_clear, - irq_status[i]); + if (!irq_status[i]) continue; - } payload[i] = kzalloc(sizeof(struct cam_cdm_work_payload), GFP_ATOMIC); @@ -1128,11 +1134,10 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) if (!payload[i]) continue; - if (irq_status[i] & - CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { + if (irq_status[i] & CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { if (cam_cdm_read_hw_reg(cdm_hw, - cdm_core->offsets->cmn_reg->usr_data, - &user_data)) { + cdm_core->offsets->cmn_reg->usr_data, + &user_data)) { CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ data"); kfree(payload[i]); @@ -1142,9 +1147,8 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) payload[i]->irq_data = user_data >> (i * 0x8); if (payload[i]->irq_data == - CAM_CDM_DBG_GEN_IRQ_USR_DATA) - CAM_INFO(CAM_CDM, - "Debug gen_irq received"); + CAM_CDM_DBG_GEN_IRQ_USR_DATA) + CAM_INFO(CAM_CDM, "Debug gen_irq received"); } payload[i]->fifo_idx = i; @@ -1154,18 +1158,9 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) INIT_WORK((struct work_struct *)&payload[i]->work, cam_hw_cdm_work); - if (cam_cdm_write_hw_reg(cdm_hw, - cdm_core->offsets->irq_reg[i]->irq_clear, - payload[i]->irq_status)) { - CAM_ERR(CAM_CDM, - "Failed to Write CDM HW IRQ Clear"); - kfree(payload[i]); - return IRQ_HANDLED; - } - work_status = queue_work( - cdm_core->bl_fifo[i].work_queue, - &payload[i]->work); + cdm_core->bl_fifo[i].work_queue, + &payload[i]->work); if (work_status == false) { CAM_ERR(CAM_CDM, @@ -1175,11 +1170,6 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) } } - if (cam_cdm_write_hw_reg(cdm_hw, - cdm_core->offsets->irq_reg[0]->irq_clear_cmd, - 0x01)) - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd 0"); - return IRQ_HANDLED; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4baf5f37ac38..379a33c71d34 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3711,7 +3711,20 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_pause_hw(ctx); - wait_for_completion(&ctx->config_done_complete); + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(300)); + if (rc <= 0) { + CAM_WARN(CAM_ISP, + "config done completion timeout for last applied req_id=%llu rc=%d ctx_index %d", + ctx->applied_req_id, rc, ctx->ctx_index); + rc = -ETIMEDOUT; + } else { + CAM_DBG(CAM_ISP, + "config done Success for req_id=%llu ctx_index %d", + ctx->applied_req_id, ctx->ctx_index); + rc = 0; + } if (stop_isp->stop_only) goto end; From 89c75af320d6be16f11b6bdf034347b90bf44ef1 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 16 Jan 2020 12:14:03 -0800 Subject: [PATCH 250/790] msm: camera: ife: Reduce config done timeout during stop This change reduces the duration of wait for config done during stop and flush. We perform wait for completion once for reg dump during flush so there is no need for a long wait during stop. CRs-Fixed: 2606911 Change-Id: Ib1c2d7655d8a213495618a140acea2391b262082 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 379a33c71d34..ed0099f0acae 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3711,19 +3711,13 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_pause_hw(ctx); - rc = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies(300)); - if (rc <= 0) { + rc = wait_for_completion_timeout(&ctx->config_done_complete, + msecs_to_jiffies(10)); + if (rc == 0) { CAM_WARN(CAM_ISP, "config done completion timeout for last applied req_id=%llu rc=%d ctx_index %d", ctx->applied_req_id, rc, ctx->ctx_index); rc = -ETIMEDOUT; - } else { - CAM_DBG(CAM_ISP, - "config done Success for req_id=%llu ctx_index %d", - ctx->applied_req_id, ctx->ctx_index); - rc = 0; } if (stop_isp->stop_only) From e03b67bb2f69d7c67e890c43500bb31ba3d726db Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Sat, 9 Nov 2019 00:59:33 +0530 Subject: [PATCH 251/790] msm: camera: cpas: Add cpas support for camera v170_200 platform Add register information. Initial QoS settings info to program camera static settings for chipsets having camera v170_200. Also change the logic to get the camera and cpas versions. Added the map table corresponding to camera and cpas versions. For any new CPAS version support, just need to add the entries to the map. This removes the complexity of if-else cases while fetching the cpas hw information. CRs-Fixed: 2571273 Change-Id: I7d54b8bc038aa90ecb39f5048e7809ac10c4476f Signed-off-by: Gaurav Jindal Signed-off-by: Chandan Kumar Jha Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 203 ++++--- drivers/cam_cpas/cpas_top/cpastop_v170_200.h | 538 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 55 ++ 3 files changed, 734 insertions(+), 62 deletions(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v170_200.h diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 9710050bf09c..5bd654f44258 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -15,6 +15,7 @@ #include "cam_cpas_soc.h" #include "cpastop100.h" #include "cpastop_v150_100.h" +#include "cpastop_v170_200.h" #include "cpastop_v170_110.h" #include "cpastop_v175_100.h" #include "cpastop_v175_101.h" @@ -38,6 +39,123 @@ static const char * const camnoc_salve_err_code[] = { "Unknown Error", /* unknown err code */ }; +static const uint32_t cam_cpas_hw_version_map + [CAM_CPAS_CAMERA_VERSION_ID_MAX][CAM_CPAS_VERSION_ID_MAX] = { + /* for camera_150 */ + { + CAM_CPAS_TITAN_150_V100, + 0, + 0, + 0, + 0, + 0, + }, + /* for camera_170 */ + { + CAM_CPAS_TITAN_170_V100, + 0, + CAM_CPAS_TITAN_170_V110, + CAM_CPAS_TITAN_170_V120, + 0, + CAM_CPAS_TITAN_170_V200, + }, + /* for camera_175 */ + { + CAM_CPAS_TITAN_175_V100, + CAM_CPAS_TITAN_175_V101, + 0, + CAM_CPAS_TITAN_175_V120, + CAM_CPAS_TITAN_175_V130, + 0, + }, + /* for camera_480 */ + { + CAM_CPAS_TITAN_480_V100, + 0, + 0, + 0, + 0, + 0, + }, + /* for camera_580 */ + { + CAM_CPAS_TITAN_580_V100, + 0, + 0, + 0, + 0, + 0, + }, +}; + +static int cam_cpas_translate_camera_cpas_version_id( + uint32_t cam_version, + uint32_t cpas_version, + uint32_t *cam_version_id, + uint32_t *cpas_version_id) +{ + + switch (cam_version) { + + case CAM_CPAS_CAMERA_VERSION_150: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_150; + break; + + case CAM_CPAS_CAMERA_VERSION_170: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_170; + break; + + case CAM_CPAS_CAMERA_VERSION_175: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_175; + break; + + case CAM_CPAS_CAMERA_VERSION_480: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_480; + break; + + case CAM_CPAS_CAMERA_VERSION_580: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_580; + break; + + default: + CAM_ERR(CAM_CPAS, "Invalid cam version %u", + cam_version); + return -EINVAL; + } + + switch (cpas_version) { + + case CAM_CPAS_VERSION_100: + *cpas_version_id = CAM_CPAS_VERSION_ID_100; + break; + + case CAM_CPAS_VERSION_101: + *cpas_version_id = CAM_CPAS_VERSION_ID_101; + break; + case CAM_CPAS_VERSION_110: + *cpas_version_id = CAM_CPAS_VERSION_ID_110; + break; + + case CAM_CPAS_VERSION_120: + *cpas_version_id = CAM_CPAS_VERSION_ID_120; + break; + + case CAM_CPAS_VERSION_130: + *cpas_version_id = CAM_CPAS_VERSION_ID_130; + break; + + case CAM_CPAS_VERSION_200: + *cpas_version_id = CAM_CPAS_VERSION_ID_200; + break; + + default: + CAM_ERR(CAM_CPAS, "Invalid cpas version %u", + cpas_version); + return -EINVAL; + } + return 0; +} + static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, struct cam_cpas_hw_caps *hw_caps) { @@ -45,27 +163,30 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CPASTOP]; uint32_t reg_value; + uint32_t cam_version, cpas_version; + uint32_t cam_version_id, cpas_version_id; + int rc; if (reg_indx == -1) return -EINVAL; hw_caps->camera_family = CAM_FAMILY_CPAS_SS; - reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x0); + cam_version = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x0); hw_caps->camera_version.major = - CAM_BITS_MASK_SHIFT(reg_value, 0xff0000, 0x10); + CAM_BITS_MASK_SHIFT(cam_version, 0xff0000, 0x10); hw_caps->camera_version.minor = - CAM_BITS_MASK_SHIFT(reg_value, 0xff00, 0x8); + CAM_BITS_MASK_SHIFT(cam_version, 0xff00, 0x8); hw_caps->camera_version.incr = - CAM_BITS_MASK_SHIFT(reg_value, 0xff, 0x0); + CAM_BITS_MASK_SHIFT(cam_version, 0xff, 0x0); - reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x4); + cpas_version = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x4); hw_caps->cpas_version.major = - CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c); + CAM_BITS_MASK_SHIFT(cpas_version, 0xf0000000, 0x1c); hw_caps->cpas_version.minor = - CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10); + CAM_BITS_MASK_SHIFT(cpas_version, 0xfff0000, 0x10); hw_caps->cpas_version.incr = - CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0); + CAM_BITS_MASK_SHIFT(cpas_version, 0xffff, 0x0); reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x8); hw_caps->camera_capability = reg_value; @@ -77,62 +198,16 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, hw_caps->cpas_version.incr, hw_caps->camera_capability); soc_info->hw_version = CAM_CPAS_TITAN_NONE; - - if ((hw_caps->camera_version.major == 1) && - (hw_caps->camera_version.minor == 7) && - (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_170_V100; - else if ((hw_caps->cpas_version.major == 1) && - (hw_caps->cpas_version.minor == 1) && - (hw_caps->cpas_version.incr == 0)) - soc_info->hw_version = CAM_CPAS_TITAN_170_V110; - 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_170_V120; - } else if ((hw_caps->camera_version.major == 1) && - (hw_caps->camera_version.minor == 7) && - (hw_caps->camera_version.incr == 5)) { - 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_175_V100; - else if ((hw_caps->cpas_version.major == 1) && - (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->cpas_version.major == 1) && - (hw_caps->cpas_version.minor == 3) && - (hw_caps->cpas_version.incr == 0)) - soc_info->hw_version = CAM_CPAS_TITAN_175_V130; - } 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; - } else if ((hw_caps->camera_version.major == 4) && - (hw_caps->camera_version.minor == 8) && - (hw_caps->camera_version.incr == 0)) { - soc_info->hw_version = CAM_CPAS_TITAN_480_V100; - } else if ((hw_caps->camera_version.major == 5) && - (hw_caps->camera_version.minor == 8) && - (hw_caps->camera_version.incr == 0)) { - soc_info->hw_version = CAM_CPAS_TITAN_580_V100; - } else if ((hw_caps->camera_version.major == 5) && - (hw_caps->camera_version.minor == 4) && - (hw_caps->camera_version.incr == 0)) { - soc_info->hw_version = CAM_CPAS_TITAN_540_V100; + rc = cam_cpas_translate_camera_cpas_version_id(cam_version, + cpas_version, &cam_version_id, &cpas_version_id); + if (rc) { + CAM_ERR(CAM_CPAS, "Invalid Version, Camera: 0x%x CPAS: 0x%x", + cam_version, cpas_version); + return -EINVAL; } + soc_info->hw_version = + cam_cpas_hw_version_map[cam_version_id][cpas_version_id]; CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); return 0; @@ -614,6 +689,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_170_V110: camnoc_info = &cam170_cpas110_camnoc_info; break; + case CAM_CPAS_TITAN_170_V200: + camnoc_info = &cam170_cpas200_camnoc_info; + break; case CAM_CPAS_TITAN_175_V100: camnoc_info = &cam175_cpas100_camnoc_info; break; @@ -634,6 +712,7 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, break; case CAM_CPAS_TITAN_580_V100: camnoc_info = &cam580_cpas100_camnoc_info; + break; case CAM_CPAS_TITAN_540_V100: camnoc_info = &cam540_cpas100_camnoc_info; break; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v170_200.h b/drivers/cam_cpas/cpas_top/cpastop_v170_200.h new file mode 100644 index 000000000000..98aabc984c87 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v170_200.h @@ -0,0 +1,538 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V170_200_H_ +#define _CPASTOP_V170_200_H_ + +#define TEST_IRQ_ENABLE 0 +#define TCSR_CONN_RESET 0x0 +#define TCSR_CONN_SET 0x3 + +static struct cam_camnoc_irq_sbm cam_cpas_v170_200_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_v170_200_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_v170_200_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 = 0x66666543, + }, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .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 = 0x66666543, + }, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x988, /* SPECIFIC_IFE13_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 = 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 = true, + .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 = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1188, /* 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 = 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 cam170_cpas200_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 cam170_cpas200_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 cam170_cpas200_camnoc_info = { + .specific = &cam_cpas_v170_200_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v170_200_camnoc_specific), + .irq_sbm = &cam_cpas_v170_200_irq_sbm, + .irq_err = &cam_cpas_v170_200_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v170_200_irq_err), + .err_logger = &cam170_cpas200_err_logger_offsets, + .errata_wa_list = &cam170_cpas200_errata_wa_list, +}; + +#endif /* _CPASTOP_V170_200_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 6399f76bac50..8423bc511d31 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -32,6 +32,60 @@ enum cam_cpas_reg_base { CAM_CPAS_REG_MAX }; +/** + * enum cam_cpas_camera_version Enum for Titan Camera Versions + */ +enum cam_cpas_camera_version { + CAM_CPAS_CAMERA_VERSION_NONE = 0, + CAM_CPAS_CAMERA_VERSION_150 = 0x00010500, + CAM_CPAS_CAMERA_VERSION_170 = 0x00010700, + CAM_CPAS_CAMERA_VERSION_175 = 0x00010705, + CAM_CPAS_CAMERA_VERSION_480 = 0x00040800, + CAM_CPAS_CAMERA_VERSION_580 = 0x00050800, + CAM_CPAS_CAMERA_VERSION_MAX +}; + +/** + * enum cam_cpas_version Enum for Titan CPAS Versions + */ +enum cam_cpas_version { + CAM_CPAS_VERSION_NONE = 0, + CAM_CPAS_VERSION_100 = 0x10000000, + CAM_CPAS_VERSION_101 = 0x10000001, + CAM_CPAS_VERSION_110 = 0x10010000, + CAM_CPAS_VERSION_120 = 0x10020000, + CAM_CPAS_VERSION_130 = 0x10030000, + CAM_CPAS_VERSION_200 = 0x20000000, + CAM_CPAS_VERSION_MAX +}; + +/** + * enum cam_cpas_camera_version_map_id Enum for camera version map id + * This enum is mapped with cam_cpas_camera_version + */ +enum cam_cpas_camera_version_map_id { + CAM_CPAS_CAMERA_VERSION_ID_150 = 0x0, + CAM_CPAS_CAMERA_VERSION_ID_170 = 0x1, + CAM_CPAS_CAMERA_VERSION_ID_175 = 0x2, + CAM_CPAS_CAMERA_VERSION_ID_480 = 0x3, + CAM_CPAS_CAMERA_VERSION_ID_580 = 0x4, + CAM_CPAS_CAMERA_VERSION_ID_MAX +}; + +/** + * enum cam_cpas_version_map_id Enum for cpas version map id + * This enum is mapped with cam_cpas_version + */ +enum cam_cpas_version_map_id { + CAM_CPAS_VERSION_ID_100 = 0x0, + CAM_CPAS_VERSION_ID_101 = 0x1, + CAM_CPAS_VERSION_ID_110 = 0x2, + CAM_CPAS_VERSION_ID_120 = 0x3, + CAM_CPAS_VERSION_ID_130 = 0x4, + CAM_CPAS_VERSION_ID_200 = 0x5, + CAM_CPAS_VERSION_ID_MAX +}; + /** * enum cam_cpas_hw_version - Enum for Titan CPAS HW Versions */ @@ -41,6 +95,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_170_V100 = 0x170100, CAM_CPAS_TITAN_170_V110 = 0x170110, CAM_CPAS_TITAN_170_V120 = 0x170120, + CAM_CPAS_TITAN_170_V200 = 0x170200, CAM_CPAS_TITAN_175_V100 = 0x175100, CAM_CPAS_TITAN_175_V101 = 0x175101, CAM_CPAS_TITAN_175_V120 = 0x175120, From 3f5125ebb1cb6f4b16f608e79f1746fe04331cc8 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 22 Jan 2020 15:47:27 -0800 Subject: [PATCH 252/790] msm: camera: ife: Remove reset type override This change removes the VFE reset type override that was introduced to a hardware limitation that has since been rectified. CRs-Fixed: 2590331 Change-Id: I2232ab69a9c66e9e14dd849755d8b4eba63fe136 Signed-off-by: Venkat Chinta --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 743950bd01bc..f85cab5cb832 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -12,10 +12,10 @@ #include "cam_debug_util.h" #include "cam_vfe_soc.h" -#define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00000003 -#define CAM_VFE_HW_RESET_HW_VAL 0x007F0000 +#define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00000001 +#define CAM_VFE_HW_RESET_HW_VAL 0x00010000 #define CAM_VFE_LITE_HW_RESET_AND_REG_VAL 0x00000002 -#define CAM_VFE_LITE_HW_RESET_HW_VAL 0x0000003D +#define CAM_VFE_LITE_HW_RESET_HW_VAL 0x00000001 struct cam_vfe_top_ver3_common_data { struct cam_hw_soc_info *soc_info; @@ -266,11 +266,6 @@ int cam_vfe_top_ver3_reset(void *device_priv, reset_reg_val = CAM_VFE_LITE_HW_RESET_HW_VAL; break; } - /* override due to hw limitation */ - if (!soc_private->is_ife_lite) - reset_reg_val = CAM_VFE_HW_RESET_HW_AND_REG_VAL; - else - reset_reg_val = CAM_VFE_LITE_HW_RESET_AND_REG_VAL; CAM_DBG(CAM_ISP, "reset reg value: 0x%x", reset_reg_val); From 54440e3bb13edc1c9c2a2431eebac3904ae54090 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 19 Nov 2019 13:40:02 -0800 Subject: [PATCH 253/790] msm: camera: reqmgr: Add uapi for new v4l2 event type Add event type to be notify custom events from the custom driver. Also adds a new custom message definition. CRs-Fixed: 2569823 Change-Id: I2ff701e79949ac3a467cbfe0c704065dbf0dc759 Signed-off-by: Karthik Anantha Ram --- include/uapi/camera/media/cam_req_mgr.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index b1170004281c..16e495127b28 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_LINUX_CAM_REQ_MGR_H @@ -53,6 +53,7 @@ #define V4L_EVENT_CAM_REQ_MGR_SOF 0 #define V4L_EVENT_CAM_REQ_MGR_ERROR 1 #define V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS 2 +#define V4L_EVENT_CAM_REQ_MGR_CUSTOM_EVT 3 /* SOF Event status */ #define CAM_REQ_MGR_SOF_EVENT_SUCCESS 0 @@ -461,11 +462,29 @@ struct cam_req_mgr_frame_msg { uint32_t reserved; }; +/** + * struct cam_req_mgr_custom_msg + * @custom_type: custom type + * @request_id: request id of the frame + * @frame_id: frame id of the frame + * @timestamp: timestamp of the frame + * @link_hdl: link handle associated with this message + * @custom_data: custom data + */ +struct cam_req_mgr_custom_msg { + uint32_t custom_type; + uint64_t request_id; + uint64_t frame_id; + uint64_t timestamp; + int32_t link_hdl; + uint64_t custom_data; +}; + /** * struct cam_req_mgr_message * @session_hdl: session to which the frame belongs to * @reserved: reserved field - * @u: union which can either be error or frame message + * @u: union which can either be error/frame/custom message */ struct cam_req_mgr_message { int32_t session_hdl; @@ -473,6 +492,7 @@ struct cam_req_mgr_message { union { struct cam_req_mgr_error_msg err_msg; struct cam_req_mgr_frame_msg frame_msg; + struct cam_req_mgr_custom_msg custom_msg; } u; }; #endif /* __UAPI_LINUX_CAM_REQ_MGR_H */ From d7c20bce6749ddf94370014832cf5711610f45d9 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 9 Sep 2019 23:05:15 -0700 Subject: [PATCH 254/790] msm: camera: isp: Add check for cid acquire This change adds a check to validate the cid being acquired, when custom HW is in the pipeline. CRs-Fixed: 2524308 Change-Id: I32913e74bc946a4333f77f5e10757c4bd51eab67 Signed-off-by: Karthik Anantha Ram --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 3682823a496b..af096b9ff123 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -773,17 +773,39 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, break; case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: - if (cid_reserv->in_port->cust_node == 1) { - if (cid_reserv->in_port->usage_type == 1) { - CAM_ERR(CAM_ISP, "Dual IFE is not supported"); + /* + * Assigning existing two IFEs for custom in KONA, + * this needs to be addressed accordingly for + * upcoming targets + */ + if (cid_reserv->in_port->cust_node) { + if (cid_reserv->in_port->usage_type == + CAM_ISP_RES_USAGE_DUAL) { + CAM_ERR(CAM_ISP, + "Dual IFE is not supported for cust_node %u", + cid_reserv->in_port->cust_node); rc = -EINVAL; goto end; } - if (csid_hw->hw_intf->hw_idx != 0) { - CAM_DBG(CAM_ISP, "CSID%d not eligible", - csid_hw->hw_intf->hw_idx); - rc = -EINVAL; - goto end; + + if (cid_reserv->in_port->cust_node == + CAM_ISP_ACQ_CUSTOM_PRIMARY) { + if (csid_hw->hw_intf->hw_idx != 0) { + CAM_ERR(CAM_ISP, "CSID%d not eligible", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } + } + + if (cid_reserv->in_port->cust_node == + CAM_ISP_ACQ_CUSTOM_SECONDARY) { + if (csid_hw->hw_intf->hw_idx != 1) { + CAM_ERR(CAM_ISP, "CSID%d not eligible", + csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto end; + } } } break; @@ -828,7 +850,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_IPP: if (csid_hw->ipp_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_DBG(CAM_ISP, + CAM_ERR(CAM_ISP, "CSID:%d IPP resource not available", csid_hw->hw_intf->hw_idx); rc = -EINVAL; From 88aeb5cd042ec1b6b5670115251e545483a79419 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Tue, 14 Jan 2020 14:44:43 +0530 Subject: [PATCH 255/790] msm: camera: req_mgr: Update link activate/deactivate to avoid race When cam request manager gets a request to deactivate a link, we do pause for each of the device for that link. There is a race here in current scenario that workqueues can be scheduled even after the link has been deactivated. This can lead to unexpected behavior. This change has updated the activate and deactivate handling to take care of the race. CRs-Fixed: 2601863 Change-Id: I7ff03c74c240fc3250618db518d586531d87369f Signed-off-by: Vikram Sharma --- drivers/cam_req_mgr/cam_req_mgr_core.c | 96 +++++++++++++++----------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 2d5e12c09522..8071261e6bcb 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -533,32 +533,40 @@ static void __cam_req_mgr_validate_crm_wd_timer( CAM_DBG(CAM_CRM, "rd_idx: %d idx: %d current_frame_timeout: %d ms", in_q->rd_idx, idx, current_frame_timeout); - - if ((next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT) > - link->watchdog->expires) { - CAM_DBG(CAM_CRM, - "Modifying wd timer expiry from %d ms to %d ms", - link->watchdog->expires, - (next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); - crm_timer_modify(link->watchdog, - next_frame_timeout + - CAM_REQ_MGR_WATCHDOG_TIMEOUT); - } else if (current_frame_timeout) { - CAM_DBG(CAM_CRM, - "Reset wd timer to current frame from %d ms to %d ms", - link->watchdog->expires, - (current_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); - crm_timer_modify(link->watchdog, - current_frame_timeout + - CAM_REQ_MGR_WATCHDOG_TIMEOUT); - } else if (link->watchdog->expires > - CAM_REQ_MGR_WATCHDOG_TIMEOUT) { - CAM_DBG(CAM_CRM, - "Reset wd timer to default from %d ms to %d ms", - link->watchdog->expires, CAM_REQ_MGR_WATCHDOG_TIMEOUT); - crm_timer_modify(link->watchdog, - CAM_REQ_MGR_WATCHDOG_TIMEOUT); + spin_lock_bh(&link->link_state_spin_lock); + if (link->watchdog) { + if ((next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT) > + link->watchdog->expires) { + CAM_DBG(CAM_CRM, + "Modifying wd timer expiry from %d ms to %d ms", + link->watchdog->expires, + (next_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); + crm_timer_modify(link->watchdog, + next_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } else if (current_frame_timeout) { + CAM_DBG(CAM_CRM, + "Reset wd timer to frame from %d ms to %d ms", + link->watchdog->expires, + (current_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); + crm_timer_modify(link->watchdog, + current_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } else if (link->watchdog->expires > + CAM_REQ_MGR_WATCHDOG_TIMEOUT) { + CAM_DBG(CAM_CRM, + "Reset wd timer to default from %d ms to %d ms", + link->watchdog->expires, + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + crm_timer_modify(link->watchdog, + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } + } else { + CAM_WARN(CAM_CRM, "Watchdog timer exited already"); } + spin_unlock_bh(&link->link_state_spin_lock); } /** @@ -1712,6 +1720,14 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) link = (struct cam_req_mgr_core_link *)priv; session = (struct cam_req_mgr_core_session *)link->parent; + spin_lock_bh(&link->link_state_spin_lock); + if ((link->watchdog) && (link->watchdog->pause_timer)) { + CAM_INFO(CAM_CRM, "Watchdog Paused"); + spin_unlock_bh(&link->link_state_spin_lock); + return rc; + } + spin_unlock_bh(&link->link_state_spin_lock); + CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x", session->session_hdl, link->link_hdl); @@ -1756,9 +1772,6 @@ static void __cam_req_mgr_sof_freeze(struct timer_list *timer_data) link = (struct cam_req_mgr_core_link *)timer->parent; - if (link->watchdog->pause_timer) - return; - task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR(CAM_CRM, "No empty task"); @@ -2694,11 +2707,9 @@ static int cam_req_mgr_cb_notify_timer( rc = -EPERM; goto end; } - spin_unlock_bh(&link->link_state_spin_lock); - - - if (!timer_data->state) + if ((link->watchdog) && (!timer_data->state)) link->watchdog->pause_timer = true; + spin_unlock_bh(&link->link_state_spin_lock); end: return rc; @@ -2744,7 +2755,7 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } - if (link->watchdog->pause_timer) + if ((link->watchdog) && (link->watchdog->pause_timer)) link->watchdog->pause_timer = false; crm_timer_reset(link->watchdog); @@ -3029,14 +3040,15 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) /* Destroy workq of link */ cam_req_mgr_workq_destroy(&link->workq); - + spin_lock_bh(&link->link_state_spin_lock); /* Destroy timer of link */ crm_timer_exit(&link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); /* Cleanup request tables and unlink devices */ __cam_req_mgr_destroy_link_info(link); - /* Free memory holding data of linked devs */ + __cam_req_mgr_destroy_subdev(link->l_dev); /* Destroy the link handle */ @@ -3664,6 +3676,9 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) mutex_lock(&link->lock); if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) { + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_READY; + spin_unlock_bh(&link->link_state_spin_lock); /* Start SOF watchdog timer */ rc = crm_timer_init(&link->watchdog, CAM_REQ_MGR_WATCHDOG_TIMEOUT, link, @@ -3685,10 +3700,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) dev->ops->process_evt(&evt_data); } } else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) { - /* Destroy SOF watchdog timer */ - spin_lock_bh(&link->link_state_spin_lock); - crm_timer_exit(&link->watchdog); - spin_unlock_bh(&link->link_state_spin_lock); /* notify nodes */ for (j = 0; j < link->num_devs; j++) { dev = &link->l_dev[j]; @@ -3699,6 +3710,11 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (dev->ops && dev->ops->process_evt) dev->ops->process_evt(&evt_data); } + /* Destroy SOF watchdog timer */ + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_IDLE; + crm_timer_exit(&link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); } else { CAM_ERR(CAM_CRM, "Invalid link control command"); rc = -EINVAL; From 0eaa2bd1520157a4b6dc81bd5928034db46d46ca Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 27 Jan 2020 13:53:04 -0800 Subject: [PATCH 256/790] msm: camera: req_mgr: Header file comment fixes Update header files to reflect changes in functions that are being documented. CRs-Fixed: 2584631 Change-Id: I45e2c7830a685b43f25bfc1fb4db6800a2de6150 Signed-off-by: Karthik Jayakumar --- drivers/cam_req_mgr/cam_mem_mgr_api.h | 7 ++-- drivers/cam_req_mgr/cam_req_mgr_core.h | 18 ++++------- drivers/cam_req_mgr/cam_req_mgr_dev.h | 4 +-- drivers/cam_req_mgr/cam_req_mgr_interface.h | 36 +++++++++------------ drivers/cam_req_mgr/cam_req_mgr_timer.h | 7 ++-- drivers/cam_req_mgr/cam_req_mgr_workq.h | 24 +++++++------- drivers/cam_req_mgr/cam_subdev.h | 3 +- 7 files changed, 46 insertions(+), 53 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr_api.h b/drivers/cam_req_mgr/cam_mem_mgr_api.h index e216a46a3a6f..e3f741e80828 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr_api.h +++ b/drivers/cam_req_mgr/cam_mem_mgr_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_MEM_MGR_API_H_ @@ -15,8 +15,7 @@ * @size : Size of memory requested for allocation * @align : Alignment of requested memory * @smmu_hdl: SMMU handle to identify context bank where memory will be mapped - * @flags : Flags to indicate cached/uncached property - * @region : Region where memory should be allocated + * @flags: Flags to indicate cached/uncached property */ struct cam_mem_mgr_request_desc { uint64_t size; @@ -83,7 +82,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, * * @buf_handle: Handle for the buffer * @vaddr_ptr : pointer to kernel virtual address - * @len_ptr : Length of the buffer + * @len : Length of the buffer * * @return Status of operation. Negative in case of error. Zero otherwise. */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 14cf4ff06a36..56669d9569e3 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_CORE_H_ #define _CAM_REQ_MGR_CORE_H_ @@ -63,7 +63,6 @@ enum crm_workq_task_type { * @flush_info : contains info of cancelled reqest * @dev_req : contains tracking info of available req id at device * @send_req : contains info of apply settings to be sent to devs in link - * @apply_req : contains info of which request is applied at device * @notify_trigger : contains notification from IFE to CRM about trigger * @notify_err : contains error info happened while processing request * - @@ -100,8 +99,8 @@ enum crm_req_state { * State machine for life cycle of request in input queue * NO_REQ : empty slot * REQ_ADDED : new entry in slot - * PENDING : waiting for next trigger to apply - * APPLIED : req is sent to all devices + * REQ_PENDING : waiting for next trigger to apply + * REQ_APPLIED : req is sent to all devices * INVALID : invalid state */ enum crm_slot_status { @@ -206,7 +205,7 @@ struct cam_req_mgr_tbl_slot { * @dev_count : num of devices having same pipeline delay * @dev_mask : mask to track which devices are linked * @skip_traverse : to indicate how many traverses need to be dropped - * by this table especially in the beginning or bubble recovery + * by this table especially in the beginning or bubble recovery * @next : pointer to next pipeline delay request table * @pd_delta : differnce between this table's pipeline delay and next * @num_slots : number of request slots present in the table @@ -268,7 +267,7 @@ struct cam_req_mgr_req_queue { * @in_q : Poiner to Input request queue * @l_tbl : unique pd request tables. * @num_tbl : how many unique pd value devices are present - * @apply_data : Holds information about request id for a request + * @apply_data : Holds information about request id for a request * @lock : mutex lock protecting request data ops. */ struct cam_req_mgr_req_data { @@ -384,7 +383,6 @@ struct cam_req_mgr_core_link { * @num_links : num of active links for current session * - Links of this session * @links : pointer to array of links within session - * @in_q : Input request queue one per session * - Session private data * @entry : pvt data - entry in the list of sessions * @lock : pvt data - spin lock to guard session data @@ -462,8 +460,7 @@ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info); * @brief: Request is scheduled * @sched_req: request id, session and link id info, bubble recovery info */ -int cam_req_mgr_schedule_request( - struct cam_req_mgr_sched_request *sched_req); +int cam_req_mgr_schedule_request(struct cam_req_mgr_sched_request *sched_req); /** * cam_req_mgr_sync_mode_setup() @@ -477,8 +474,7 @@ int cam_req_mgr_sync_config(struct cam_req_mgr_sync_mode *sync_info); * @brief: flush all requests * @flush_info: requests related to link and session */ -int cam_req_mgr_flush_requests( - struct cam_req_mgr_flush_info *flush_info); +int cam_req_mgr_flush_requests(struct cam_req_mgr_flush_info *flush_info); /** * cam_req_mgr_core_device_init() diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 86381d90080b..464720efb0a2 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_DEV_H_ @@ -28,7 +28,7 @@ struct cam_req_mgr_device { bool state; int32_t open_cnt; struct mutex cam_lock; - struct v4l2_fh *cam_eventq; + struct v4l2_fh *cam_eventq; spinlock_t cam_eventq_lock; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index a932d1e52920..383d79c0871b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_INTERFACE_H @@ -30,11 +30,11 @@ struct cam_req_mgr_link_evt_data; * * @cam_req_mgr_notify_trigger: for device which generates trigger to inform CRM * @cam_req_mgr_notify_err : device use this to inform about different errors - * @cam_req_mgr_add_req : to info CRm about new rqeuest received from + * @cam_req_mgr_add_req : to info CRM about new rqeuest received from * userspace + * @cam_req_mgr_notify_timer : start the timer */ -typedef int (*cam_req_mgr_notify_trigger)( - struct cam_req_mgr_trigger_notify *); +typedef int (*cam_req_mgr_notify_trigger)(struct cam_req_mgr_trigger_notify *); typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *); @@ -45,14 +45,12 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); * * @cam_req_mgr_get_dev_info: to fetch details about device linked * @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_apply_req : CRM asks device to apply certain request id * @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 *); -typedef int (*cam_req_mgr_link_setup)( - struct cam_req_mgr_core_dev_link_setup *); +typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); @@ -63,6 +61,7 @@ typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); * @notify_trigger : payload for trigger indication event * @notify_err : payload for different error occurred at device * @add_req : payload to inform which device and what request is received + * @notify_timer : payload for timer start event * @notify_stop : payload to inform stop event */ struct cam_req_mgr_crm_cb { @@ -107,8 +106,8 @@ enum cam_pipeline_delay { }; /** - * @CAM_TRIGGER_POINT_SOF : Trigger point for SOF - * @CAM_TRIGGER_POINT_EOF : Trigger point for EOF + * @CAM_TRIGGER_POINT_SOF : Trigger point for Start Of Frame + * @CAM_TRIGGER_POINT_EOF : Trigger point for End Of Frame */ #define CAM_TRIGGER_POINT_SOF (1 << 0) #define CAM_TRIGGER_POINT_EOF (1 << 1) @@ -203,7 +202,7 @@ enum cam_req_mgr_link_evt_type { * @dev_hdl : device handle which has sent this req id * @frame_id : frame id for internal tracking * @trigger : trigger point of this notification, CRM will send apply - * only to the devices which subscribe to this point. + * only to the devices which subscribe to this point. * @sof_timestamp_val: Captured time stamp value at sof hw event * @req_id : req id which returned buf_done */ @@ -220,7 +219,6 @@ struct cam_req_mgr_trigger_notify { * struct cam_req_mgr_timer_notify * @link_hdl : link identifier * @dev_hdl : device handle which has sent this req id - * @frame_id : frame id for internal tracking * @state : timer state i.e ON or OFF */ struct cam_req_mgr_timer_notify { @@ -255,8 +253,7 @@ struct cam_req_mgr_error_notify { * @dev_hdl : device handle which has sent this req id * @req_id : req id which device is ready to process * @skip_before_applying : before applying req mgr introduce bubble - * by not sending request to device/s. - * ex: IFE and Flash + * by not sending request to devices. ex: IFE and Flash */ struct cam_req_mgr_add_request { int32_t link_hdl; @@ -284,7 +281,6 @@ struct cam_req_mgr_notify_stop { * @dev_id : device id info * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client - * */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -296,13 +292,12 @@ struct cam_req_mgr_device_info { /** * struct cam_req_mgr_core_dev_link_setup - * @link_enable : link link or unlink + * @link_enable : link or unlink * @link_hdl : link identifier * @dev_hdl : device handle for reference * @max_delay : max pipeline delay on this link * @crm_cb : callback funcs to communicate with req mgr * @subscribe_event : the mask of trigger points this link subscribes - * */ struct cam_req_mgr_core_dev_link_setup { int32_t link_enable; @@ -335,7 +330,7 @@ struct cam_req_mgr_apply_request { * @link_hdl : link identifier * @dev_hdl : device handle for cross check * @type : cancel request type flush all or a request - * @request_id : request id to cancel + * @req_id : request id to cancel * */ struct cam_req_mgr_flush_request { @@ -349,7 +344,7 @@ struct cam_req_mgr_flush_request { * struct cam_req_mgr_event_data * @link_hdl : link handle * @req_id : request id - * + * @evt_type : link event */ struct cam_req_mgr_link_evt_data { int32_t link_hdl; @@ -365,8 +360,7 @@ struct cam_req_mgr_link_evt_data { /** * struct cam_req_mgr_send_request * @link_hdl : link identifier - * @idx : slot idx - * + * @in_q : input request queue pointer */ struct cam_req_mgr_send_request { int32_t link_hdl; diff --git a/drivers/cam_req_mgr/cam_req_mgr_timer.h b/drivers/cam_req_mgr/cam_req_mgr_timer.h index d2e20498df9a..5517a57d447e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_timer.h +++ b/drivers/cam_req_mgr/cam_req_mgr_timer.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_TIMER_H_ @@ -11,7 +11,8 @@ #include "cam_req_mgr_core_defs.h" -/** struct cam_req_mgr_timer +/** + * struct cam_req_mgr_timer * @expires : timeout value for timer * @sys_timer : system timer variable * @parent : priv data - link pointer @@ -28,7 +29,7 @@ struct cam_req_mgr_timer { /** * crm_timer_modify() - * @brief : allows ser to modify expiry time. + * @brief : modify expiry time. * @timer : timer which will be reset to expires values */ void crm_timer_modify(struct cam_req_mgr_timer *crm_timer, diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.h b/drivers/cam_req_mgr/cam_req_mgr_workq.h index f938710b69ae..c09cb5eb64d8 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.h +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_WORKQ_H_ @@ -65,17 +65,19 @@ struct crm_workq_task { }; /** struct cam_req_mgr_core_workq - * @work : work token used by workqueue - * @job : workqueue internal job struct + * @work : work token used by workqueue + * @job : workqueue internal job struct + * @lock_bh : lock for task structs + * @in_irq : set true if workque can be used in irq context * task - - * @lock_bh : lock for task structs - * @in_irq : set true if workque can be used in irq context - * @free_cnt : num of free/available tasks - * @empty_head : list head of available taska which can be used - * or acquired in order to enqueue a task to workq - * @pool : pool of tasks used for handling events in workq context - * @num_task : size of tasks pool - * - + * @lock : Current task's lock handle + * @pending_cnt : # of tasks left in queue + * @free_cnt : # of free/available tasks + * @process_head: + * @empty_head : list head of available taska which can be used + * or acquired in order to enqueue a task to workq + * @pool : pool of tasks used for handling events in workq context + * @num_task : size of tasks pool */ struct cam_req_mgr_core_workq { struct work_struct work; diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index ef8e9fbac794..08d02a1b0fab 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SUBDEV_H_ @@ -34,6 +34,7 @@ * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. + * @subdev_node_created: Enabled sub-device * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be From c1eedf8be519865adb07710d976d3ed5b036a8dd Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Tue, 4 Feb 2020 13:43:52 -0800 Subject: [PATCH 257/790] msm: camera: isp: Update IRQ controller names Fixes debug log printing of IRQ controller names from within interrupt. CRs-Fixed: 2584631 Change-Id: I0df94603f31fa2fb56464938e1a28fda470e4a27 Signed-off-by: Karthik Jayakumar --- .../hw_utils/irq_controller/cam_irq_controller.c | 12 +++++++----- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 6 +----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index cc1fe18e05fd..1e138bac5f92 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -695,8 +695,9 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv) if (!controller) return IRQ_NONE; - CAM_DBG(CAM_IRQ_CTRL, "locking controller %pK name %s lock %pK", - controller, controller->name, &controller->lock); + CAM_DBG(CAM_IRQ_CTRL, + "Locking: %s IRQ Controller: [%pK], lock handle: %pK", + controller->name, controller, &controller->lock); spin_lock(&controller->lock); for (i = 0; i < controller->num_registers; i++) { irq_register = &controller->irq_register_arr[i]; @@ -743,8 +744,9 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv) } } spin_unlock(&controller->lock); - CAM_DBG(CAM_IRQ_CTRL, "unlocked controller %pK name %s lock %pK", - controller, controller->name, &controller->lock); + CAM_DBG(CAM_IRQ_CTRL, + "Unlocked: %s IRQ Controller: %pK, lock handle: %pK", + controller->name, controller, &controller->lock); return IRQ_HANDLED; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 3d8415b0f765..ebe2e1d4e9e6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3727,7 +3727,6 @@ int cam_vfe_bus_ver3_init( struct cam_vfe_bus *vfe_bus_local; struct cam_vfe_bus_ver3_hw_info *ver3_hw_info = bus_hw_info; struct cam_vfe_soc_private *soc_private = NULL; - char rup_controller_name[12] = ""; CAM_DBG(CAM_ISP, "Enter"); @@ -3793,10 +3792,7 @@ int cam_vfe_bus_ver3_init( goto free_bus_priv; } - strlcat(rup_controller_name, drv_name, sizeof(rup_controller_name)); - strlcat(rup_controller_name, "_rup", sizeof(rup_controller_name)); - - rc = cam_irq_controller_init(rup_controller_name, + rc = cam_irq_controller_init("vfe_bus_rup", bus_priv->common_data.mem_base, &ver3_hw_info->common_reg.irq_reg_info, &bus_priv->common_data.rup_irq_controller, false); From 14b75bff2def91798302812e89971c5ce1c3ba7d Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 16 Dec 2019 13:57:57 +0530 Subject: [PATCH 258/790] msm: camera: isp: Add support for IFE2 Add support for IFE2 hardware in ife hw manager, bus files. CRs-Fixed: 2571273 Change-Id: I6193b70707b15282b8d819e8dda5eb2e5fc4c345 Signed-off-by: Gaurav Jindal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 10 ++++++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 15 +++++++++++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 70da17532160..a652bc1e6069 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1439,6 +1439,16 @@ static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) else if (hw_idx == 4) return CAM_ISP_IFE1_LITE_HW; break; + case CAM_CPAS_TITAN_170_V200: + if (hw_idx == 0) + return CAM_ISP_IFE0_HW; + else if (hw_idx == 1) + return CAM_ISP_IFE1_HW; + else if (hw_idx == 2) + return CAM_ISP_IFE2_HW; + else if (hw_idx == 3) + return CAM_ISP_IFE0_LITE_HW; + break; default: CAM_ERR(CAM_ISP, "Invalid hw_version: 0x%X", hw_version); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 9c72e88c6f84..401b49b6f073 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -319,6 +319,7 @@ static int cam_vfe_bus_ver2_get_intra_client_mask( case CAM_VFE_BUS_VER2_VFE_CORE_0: switch (dual_slave_core) { case CAM_VFE_BUS_VER2_VFE_CORE_1: + case CAM_VFE_BUS_VER2_VFE_CORE_2: *intra_client_mask = version_based_intra_client_mask; break; default: @@ -331,6 +332,20 @@ static int cam_vfe_bus_ver2_get_intra_client_mask( case CAM_VFE_BUS_VER2_VFE_CORE_1: switch (dual_slave_core) { case CAM_VFE_BUS_VER2_VFE_CORE_0: + case CAM_VFE_BUS_VER2_VFE_CORE_2: + *intra_client_mask = version_based_intra_client_mask; + break; + default: + CAM_ERR(CAM_ISP, "Invalid value for slave core %u", + dual_slave_core); + rc = -EINVAL; + break; + } + break; + case CAM_VFE_BUS_VER2_VFE_CORE_2: + switch (dual_slave_core) { + case CAM_VFE_BUS_VER2_VFE_CORE_0: + case CAM_VFE_BUS_VER2_VFE_CORE_1: *intra_client_mask = version_based_intra_client_mask; break; default: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index cac3adf65a93..fc1608315330 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_BUS_VER2_H_ @@ -14,6 +14,7 @@ enum cam_vfe_bus_ver2_vfe_core_id { CAM_VFE_BUS_VER2_VFE_CORE_0, CAM_VFE_BUS_VER2_VFE_CORE_1, + CAM_VFE_BUS_VER2_VFE_CORE_2, CAM_VFE_BUS_VER2_VFE_CORE_MAX, }; From d95d140d40b674b5b476c52db28ef8eb7c36c83d Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 14 Oct 2019 15:08:23 +0530 Subject: [PATCH 259/790] msm: camera: req_mgr: LDAR Debug framework implementation When user space detects an error or does not receive response for a request, Lets do a reset(LDAR) is triggered. Before LDAR, user space sends flush command to the kernel space. To debug the cause for this situation and to dump the information, user space sends a dump command to the kernel space before sending flush. As a part of this command, it passes the culprit request id and the buffer into which the information can be dumped. Kernel space traverses across the drivers and find the culprit hw and dumps the relevant information in the buffer. This data is written to a file for offline processing. This commit implements the framework for traversal across the RT and NRT devices. CRs-Fixed: 2602180 Change-Id: I7e24006c20c23bfab163a2ad13b4ac6e2913bb9e Signed-off-by: Gaurav Jindal --- drivers/cam_core/cam_context.c | 65 ++++++++++ drivers/cam_core/cam_context.h | 49 ++++++++ drivers/cam_core/cam_context_utils.c | 127 ++++++++++++++++++++ drivers/cam_core/cam_context_utils.h | 3 +- drivers/cam_core/cam_hw_mgr_intf.h | 19 +++ drivers/cam_core/cam_node.c | 77 ++++++++++++ drivers/cam_req_mgr/cam_req_mgr_core.c | 60 +++++++++ drivers/cam_req_mgr/cam_req_mgr_core.h | 6 + drivers/cam_req_mgr/cam_req_mgr_dev.c | 24 ++++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 24 ++++ include/uapi/camera/media/cam_defs.h | 22 ++++ include/uapi/camera/media/cam_req_mgr.h | 2 + 12 files changed, 477 insertions(+), 1 deletion(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 1c17422d01d0..267b23dafa72 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -230,6 +230,34 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, return rc; } +int cam_context_handle_crm_dump_req(struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump) +{ + int rc = 0; + + if (!ctx) { + CAM_ERR(CAM_CORE, "Invalid Context"); + return -EINVAL; + } + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context %s ctx_id %d is not ready", + ctx->dev_name, ctx->ctx_id); + return -EINVAL; + } + mutex_lock(&ctx->ctx_mutex); + + if (ctx->state_machine[ctx->state].crm_ops.dump_req) + rc = ctx->state_machine[ctx->state].crm_ops.dump_req(ctx, + dump); + else + CAM_ERR(CAM_CORE, "No crm dump req for %s dev %d, state %d", + ctx->dev_name, ctx->dev_hdl, ctx->state); + + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, uint32_t buf_info) { @@ -524,6 +552,43 @@ int cam_context_handle_info_dump(void *context, return rc; } +int cam_context_handle_dump_dev(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc = 0; + + if (!ctx) { + CAM_ERR(CAM_CORE, "Invalid Context"); + return -EINVAL; + } + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context %s ctx_id %d is not ready", + ctx->dev_name, ctx->ctx_id); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, + "Context %s ctx_id %d Invalid dump command payload", + ctx->dev_name, ctx->ctx_id); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + CAM_DBG(CAM_CORE, "dump device in dev %d, name %s state %d", + ctx->dev_hdl, ctx->dev_name, ctx->state); + if (ctx->state_machine[ctx->state].ioctl_ops.dump_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.dump_dev( + ctx, cmd); + else + CAM_WARN(CAM_CORE, "No dump device in dev %d, name %s state %d", + ctx->dev_hdl, ctx->dev_name, ctx->state); + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + int cam_context_init(struct cam_context *ctx, const char *dev_name, uint64_t dev_id, diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 2c1c685e76b8..770451faadf2 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -23,6 +23,12 @@ struct cam_context; #define CAM_CTX_CFG_MAX 20 #define CAM_CTX_RES_MAX 20 +/* max tag dump header string length*/ +#define CAM_CTXT_DUMP_TAG_MAX_LEN 32 + +/* Number of words to be dumped for context*/ +#define CAM_CTXT_DUMP_NUM_WORDS 10 + /** * enum cam_ctx_state - context top level states * @@ -86,6 +92,7 @@ struct cam_ctx_request { * @flush_dev: Function pointer for flush device * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw + * @dump_dev: Function pointer for dump dev * */ struct cam_ctx_ioctl_ops { @@ -103,6 +110,8 @@ struct cam_ctx_ioctl_ops { struct cam_flush_dev_cmd *cmd); int (*acquire_hw)(struct cam_context *ctx, void *args); int (*release_hw)(struct cam_context *ctx, void *args); + int (*dump_dev)(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd); }; /** @@ -114,6 +123,7 @@ struct cam_ctx_ioctl_ops { * @apply_req: Apply setting for the context * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) + * @dump_req: Dump information for the issue request * */ struct cam_ctx_crm_ops { @@ -129,6 +139,8 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_flush_request *flush); int (*process_evt)(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *evt_data); + int (*dump_req)(struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump); }; @@ -219,6 +231,19 @@ struct cam_context { uint32_t last_flush_req; }; +/** + * struct cam_context_dump_header - Function for context dump header + * + * @tag : Tag for context dump header + * @size : Size of data + * @word_size : Word size of data + */ +struct cam_context_dump_header { + uint8_t tag[CAM_CTXT_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + /** * cam_context_shutdown() * @@ -301,6 +326,18 @@ int cam_context_handle_crm_flush_req(struct cam_context *ctx, int cam_context_handle_crm_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *process_evt); +/** + * cam_context_handle_crm_dump_req() + * + * @brief: Handle CRM dump request + * + * @ctx: Object pointer for cam_context + * @dump: Dump request command payload + * + */ +int cam_context_handle_crm_dump_req(struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump); + /** * cam_context_dump_pf_info() * @@ -410,6 +447,18 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +/** + * cam_context_handle_dump_dev() + * + * @brief: Handle dump device command + * + * @ctx: Object pointer for cam_context + * @cmd: Dump device command payload + * + */ +int cam_context_handle_dump_dev(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd); + /** * cam_context_handle_info_dump() * diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 423961aaf2af..87abebabaf00 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -1046,3 +1046,130 @@ int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx) end: return rc; } + +static int cam_context_dump_context(struct cam_context *ctx, + struct cam_hw_dump_args *dump_args) +{ + int rc; + int i; + size_t buf_len; + size_t remain_len; + uint8_t *dst; + uint64_t *addr, *start; + uint32_t min_len; + uintptr_t cpu_addr; + struct cam_ctx_request *req; + struct cam_context_dump_header *hdr; + + if (!ctx || !dump_args) { + CAM_ERR(CAM_CORE, "Invalid parameters %pK %pK", + ctx, dump_args); + return -EINVAL; + } + + spin_lock_bh(&ctx->lock); + if (list_empty(&ctx->active_req_list)) { + CAM_ERR(CAM_CTXT, "[%s][%d] no active request", + ctx->dev_name, ctx->ctx_id); + spin_unlock_bh(&ctx->lock); + return -EIO; + } + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + spin_unlock_bh(&ctx->lock); + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &cpu_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_CTXT, "Invalid hdl %u rc %d", + dump_args->buf_handle, rc); + return rc; + } + if (dump_args->offset >= buf_len) { + CAM_WARN(CAM_CTXT, "dump buffer overshoot offset %zu len %zu", + dump_args->offset, buf_len); + return -ENOSPC; + } + + remain_len = buf_len - dump_args->offset; + min_len = sizeof(struct cam_context_dump_header) + + (CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries + + (req->num_out_map_entries * 2)) * sizeof(uint64_t); + + if (remain_len < min_len) { + CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + dst = (uint8_t *)cpu_addr + dump_args->offset; + hdr = (struct cam_context_dump_header *)dst; + scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN, + "%s_CTXT_DUMP:", ctx->dev_name); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header)); + start = addr; + *addr++ = ctx->ctx_id; + *addr++ = refcount_read(&(ctx->refcount.refcount)); + *addr++ = ctx->last_flush_req; + *addr++ = ctx->state; + *addr++ = req->num_out_map_entries; + for (i = 0; i < req->num_out_map_entries; i++) { + *addr++ = req->out_map_entries[i].resource_handle; + *addr++ = req->out_map_entries[i].sync_id; + } + *addr++ = req->num_in_map_entries; + for (i = 0; i < req->num_in_map_entries; i++) + *addr++ = req->in_map_entries[i].sync_id; + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_context_dump_header); + return rc; +} + +int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc = 0; + struct cam_hw_dump_args dump_args; + + if (!ctx || !cmd) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + return -EINVAL; + } + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + return -EFAULT; + } + memset(&dump_args, 0, sizeof(dump_args)); + if (ctx->hw_mgr_intf->hw_dump) { + dump_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + dump_args.buf_handle = cmd->buf_handle; + dump_args.offset = cmd->offset; + dump_args.request_id = cmd->issue_req_id; + dump_args.error_type = cmd->error_type; + rc = ctx->hw_mgr_intf->hw_dump( + ctx->hw_mgr_intf->hw_mgr_priv, + &dump_args); + if (rc) { + CAM_ERR(CAM_CTXT, "[%s][%d] handle[%u] failed", + ctx->dev_name, ctx->ctx_id, dump_args.buf_handle); + return rc; + } + /* Offset will change if the issue request id is found with + * the hw and has been lying with it beyond threshold time. + * If offset does not change, do not dump the context + * information as the current context has no problem with + * the provided request id. + */ + if (dump_args.offset > cmd->offset) { + cam_context_dump_context(ctx, &dump_args); + CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %u", + ctx->dev_name, ctx->ctx_id, + dump_args.offset - cmd->offset); + cmd->offset = dump_args.offset; + } + } else { + CAM_DBG(CAM_CTXT, "%s hw dump not registered", ctx->dev_name); + } + return rc; +} diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h index 087fdbf36544..79dec3142e8a 100644 --- a/drivers/cam_core/cam_context_utils.h +++ b/drivers/cam_core/cam_context_utils.h @@ -30,5 +30,6 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, struct cam_packet *packet, unsigned long iova, uint32_t buf_info, bool *mem_found); int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx); - +int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd); #endif /* _CAM_CONTEXT_UTILS_H_ */ diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index fe074734f389..1e2c1f7a7008 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -300,6 +300,23 @@ struct cam_hw_reset_args { void *ctxt_to_hw_map; }; +/** + * struct cam_hw_dump_args - Dump arguments + * + * @request_id: request_id + * @offset: Buffer offset. This is updated by the drivers. + * @buf_handle: Buffer handle + * @error_type: Error type, to be used to extend dump information + * @ctxt_to_hw_map: HW context from the acquire + */ +struct cam_hw_dump_args { + uint64_t request_id; + size_t offset; + uint32_t buf_handle; + uint32_t error_type; + void *ctxt_to_hw_map; +}; + /* enum cam_hw_mgr_command - Hardware manager command type */ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, @@ -355,6 +372,7 @@ struct cam_hw_cmd_args { * @hw_close: Function pointer for HW deinit * @hw_flush: Function pointer for HW flush * @hw_reset: Function pointer for HW reset + * @hw_dump: Function pointer for HW dump * */ struct cam_hw_mgr_intf { @@ -376,6 +394,7 @@ struct cam_hw_mgr_intf { int (*hw_close)(void *hw_priv, void *hw_close_args); int (*hw_flush)(void *hw_priv, void *hw_flush_args); int (*hw_reset)(void *hw_priv, void *hw_reset_args); + int (*hw_dump)(void *hw_priv, void *hw_dump_args); }; #endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 4fefa2f35db3..672ae35b6226 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -435,6 +435,39 @@ destroy_dev_hdl: return rc; } +static int __cam_node_handle_dump_dev(struct cam_node *node, + struct cam_dump_req_cmd *dump) +{ + int rc; + struct cam_context *ctx = NULL; + + if (!dump) + return -EINVAL; + + if (dump->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (dump->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(dump->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + dump->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_dump_dev(ctx, dump); + if (rc) + CAM_ERR(CAM_CORE, "Dump failure for node %s", node->name); + + return rc; +} + static int __cam_node_handle_release_hw_v1(struct cam_node *node, struct cam_release_hw_cmd_v1 *release) { @@ -575,6 +608,25 @@ static int __cam_node_crm_process_evt( return cam_context_handle_crm_process_evt(ctx, evt_data); } +static int __cam_node_crm_dump_req(struct cam_req_mgr_dump_info *dump) +{ + struct cam_context *ctx = NULL; + + if (!dump) { + CAM_ERR(CAM_CORE, "Invalid dump request payload"); + return -EINVAL; + } + + ctx = (struct cam_context *) cam_get_device_priv(dump->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + dump->dev_hdl); + return -EINVAL; + } + + return cam_context_handle_crm_dump_req(ctx, dump); +} + int cam_node_deinit(struct cam_node *node) { if (node) @@ -630,6 +682,7 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.link_setup = __cam_node_crm_link_setup; node->crm_node_intf.flush_req = __cam_node_crm_flush_req; node->crm_node_intf.process_evt = __cam_node_crm_process_evt; + node->crm_node_intf.dump_req = __cam_node_crm_dump_req; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); @@ -877,6 +930,30 @@ release_kfree: } break; } + case CAM_DUMP_REQ: { + struct cam_dump_req_cmd dump; + + if (copy_from_user(&dump, u64_to_user_ptr(cmd->handle), + sizeof(dump))) { + rc = -EFAULT; + break; + } + rc = __cam_node_handle_dump_dev(node, &dump); + if (rc) { + CAM_ERR(CAM_CORE, + "Dump device %s failed(rc = %d) ", + node->name, rc); + break; + } + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &dump, sizeof(dump))) { + CAM_ERR(CAM_CORE, + "Dump device %s copy_to_user fail", + node->name); + rc = -EFAULT; + } + break; + } default: CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code); rc = -EINVAL; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 2b0916eca67e..be693f9ea3ff 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3863,6 +3863,66 @@ end: return rc; } +int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req) +{ + int rc = 0; + int i; + struct cam_req_mgr_dump_info info; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_core_session *session = NULL; + struct cam_req_mgr_connected_device *device = NULL; + + if (!dump_req) { + CAM_ERR(CAM_CRM, "dump req is NULL"); + return -EFAULT; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + /* session hdl's priv data is cam session struct */ + session = (struct cam_req_mgr_core_session *) + cam_get_device_priv(dump_req->session_handle); + if (!session) { + CAM_ERR(CAM_CRM, "Invalid session %x", + dump_req->session_handle); + rc = -EINVAL; + goto end; + } + if (session->num_links <= 0) { + CAM_WARN(CAM_CRM, "No active links in session %x", + dump_req->session_handle); + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(dump_req->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", dump_req->link_hdl); + rc = -EINVAL; + goto end; + } + info.offset = dump_req->offset; + for (i = 0; i < link->num_devs; i++) { + device = &link->l_dev[i]; + info.link_hdl = dump_req->link_hdl; + info.dev_hdl = device->dev_hdl; + info.req_id = dump_req->issue_req_id; + info.buf_handle = dump_req->buf_handle; + info.error_type = dump_req->error_type; + if (device->ops && device->ops->dump_req) { + rc = device->ops->dump_req(&info); + if (rc) + CAM_ERR(CAM_REQ, + "Fail dump req %llu dev %d rc %d", + info.req_id, device->dev_hdl, rc); + } + } + dump_req->offset = info.offset; + CAM_INFO(CAM_REQ, "req %llu, offset %zu", + dump_req->issue_req_id, dump_req->offset); +end: + mutex_unlock(&g_crm_core_dev->crm_lock); + return 0; +} int cam_req_mgr_core_device_init(void) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index e093e2211a5a..b037c4364790 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -505,4 +505,10 @@ void cam_req_mgr_handle_core_shutdown(void); */ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control); +/** + * cam_req_mgr_dump_request() + * @brief: Dumps the request information + * @dump_req: Dump request + */ +int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req); #endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 4c4bb5afacae..186ea75f88d8 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -523,6 +523,30 @@ static long cam_private_ioctl(struct file *file, void *fh, rc = -EINVAL; } break; + case CAM_REQ_MGR_REQUEST_DUMP: { + struct cam_dump_req_cmd cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_dump_req_cmd))) { + rc = -EFAULT; + break; + } + rc = cam_req_mgr_dump_request(&cmd); + if (rc) { + CAM_ERR(CAM_CORE, "dump fail for dev %d req %llu rc %d", + cmd.dev_handle, cmd.issue_req_id, rc); + break; + } + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &cmd, sizeof(struct cam_dump_req_cmd))) + rc = -EFAULT; + } + break; default: return -ENOIOCTLCMD; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index a932d1e52920..7c184d675c6f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -21,6 +21,7 @@ struct cam_req_mgr_core_dev_link_setup; struct cam_req_mgr_apply_request; struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; +struct cam_req_mgr_dump_info; #define SKIP_NEXT_FRAME 0x100 @@ -49,6 +50,7 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); * @cam_req_mgr_apply_req : CRM asks device to apply certain request id. * @cam_req_mgr_flush_req : Flush or cancel request * cam_req_mgr_process_evt : generic events + * @cam_req_mgr_dump_req : dump request */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)( @@ -56,6 +58,7 @@ typedef int (*cam_req_mgr_link_setup)( typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); +typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); /** * @brief : cam_req_mgr_crm_cb - func table @@ -81,6 +84,7 @@ struct cam_req_mgr_crm_cb { * @apply_req : payload to apply request id on a device linked * @flush_req : payload to flush request * @process_evt : payload to generic event + * @dump_req : payload to dump request */ struct cam_req_mgr_kmd_ops { cam_req_mgr_get_dev_info get_dev_info; @@ -88,6 +92,7 @@ struct cam_req_mgr_kmd_ops { cam_req_mgr_apply_req apply_req; cam_req_mgr_flush_req flush_req; cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; }; /** @@ -372,4 +377,23 @@ struct cam_req_mgr_send_request { int32_t link_hdl; struct cam_req_mgr_req_queue *in_q; }; + +/** + * struct cam_req_mgr_dump_info + * @req_id : request id to dump + * @offset : offset of buffer + * @error_type : error type + * @buf_handle : buf handle + * @link_hdl : link identifier + * @dev_hdl : device handle for cross check + * + */ +struct cam_req_mgr_dump_info { + uint64_t req_id; + size_t offset; + uint32_t error_type; + uint32_t buf_handle; + int32_t link_hdl; + int32_t dev_hdl; +}; #endif diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index 23b4ba98f92a..52d14a2d3fb3 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -26,6 +26,7 @@ #define CAM_COMMON_OPCODE_BASE_v2 0x150 #define CAM_ACQUIRE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x1) #define CAM_RELEASE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x2) +#define CAM_DUMP_REQ (CAM_COMMON_OPCODE_BASE_v2 + 0x3) #define CAM_EXT_OPCODE_BASE 0x200 #define CAM_CONFIG_DEV_EXTERNAL (CAM_EXT_OPCODE_BASE + 0x1) @@ -868,5 +869,26 @@ struct cam_reg_dump_input_info { uint32_t dump_set_offsets[1]; }; +/** + * struct cam_dump_req_cmd - + * Dump the information of issue req id + * + * @issue_req_id : Issue Request Id + * @offset : Offset for the buffer + * @buf_handle : Buffer Handle + * @error_type : Error type, using it, dumping information can be extended + * @session_handle : Session Handle + * @link_hdl : link handle + * @dev_handle : Device Handle + */ +struct cam_dump_req_cmd { + uint64_t issue_req_id; + size_t offset; + uint32_t buf_handle; + uint32_t error_type; + int32_t session_handle; + int32_t link_hdl; + int32_t dev_handle; +}; #endif /* __UAPI_CAM_DEFS_H__ */ diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 16e495127b28..d876f21575bb 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -262,6 +262,8 @@ struct cam_req_mgr_link_control { #define CAM_REQ_MGR_CACHE_OPS (CAM_COMMON_OPCODE_MAX + 12) #define CAM_REQ_MGR_LINK_CONTROL (CAM_COMMON_OPCODE_MAX + 13) #define CAM_REQ_MGR_LINK_V2 (CAM_COMMON_OPCODE_MAX + 14) +#define CAM_REQ_MGR_REQUEST_DUMP (CAM_COMMON_OPCODE_MAX + 15) + /* end of cam_req_mgr opcodes */ #define CAM_MEM_FLAG_HW_READ_WRITE (1<<0) From b68a69b788264594a0ab5c2910f9fb6ce0e14b8e Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Fri, 20 Dec 2019 12:51:16 +0530 Subject: [PATCH 260/790] msm: camera: csiphy: Add combo phy settings for csiphy v1.2.2.2 As per HPG revision L, there's a difference in the DPHY combo-mode sequence settings between lito v1 and v2. This change adds a separate sequence for lito v2, csiphy version 1.2.2.2. CRs-Fixed: 2591712 Change-Id: Ic535bd2c98f47c33aa689d0e1bfe07d7dac8d9a2 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/cam_csiphy_soc.c | 22 ++++ .../include/cam_csiphy_1_2_2_hwreg.h | 115 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index cc07b5eed5ab..6b6b67b3d73d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -9,6 +9,7 @@ #include "include/cam_csiphy_1_0_hwreg.h" #include "include/cam_csiphy_1_2_hwreg.h" #include "include/cam_csiphy_1_2_1_hwreg.h" +#include "include/cam_csiphy_1_2_2_hwreg.h" #include "include/cam_csiphy_1_2_3_hwreg.h" #include "include/cam_csiphy_2_0_hwreg.h" @@ -311,6 +312,27 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_1_2; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.2.2")) { + /* settings for lito v2 */ + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_2_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->hw_version = CSIPHY_VERSION_V12; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v1.2.3")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_3_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h new file mode 100644 index 000000000000..dd88ba7cca38 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_2_2_HWREG_H_ +#define _CAM_CSIPHY_1_2_2_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_t +csiphy_2ph_v1_2_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DNP_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, +}; + +#endif /* _CAM_CSIPHY_1_2_2_HWREG_H_ */ From fdb9ade9a8e711b162e1054cc14300af25b649a3 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 5 Dec 2019 16:30:26 -0800 Subject: [PATCH 261/790] msm: camera: sensor: Notify completion in error case There is no need to wait till timeout in case of NACK or underflow error irq is raised, so notify thread for rd_done completion. Also, correct the error mask to catch the NACK error for Master 1. CRs-Fixed: 2598605 Change-Id: Ib8a16ee119dd81f1384283ac7e9f82d3ac2588bb Signed-off-by: Jigarkumar Zala Signed-off-by: Depeng Shao --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 75 +++++++++++++++++-- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 48 +++++++++--- .../cam_sensor_module/cam_cci/cam_cci_hwreg.h | 8 +- .../cam_sensor_module/cam_cci/cam_cci_soc.c | 3 + 4 files changed, 113 insertions(+), 21 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index a0d1cbe058d9..4a2a643a7408 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -42,6 +42,9 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev, void __iomem *base = soc_info->reg_map[0].mem_base; cam_io_w_mb(1 << master, base + CCI_HALT_REQ_ADDR); + if (!cci_dev->cci_master_info[master].status) + reinit_completion(&cci_dev->cci_master_info[master] + .reset_complete); rc = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); if (rc < 0) { @@ -51,6 +54,7 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev, /* Set reset pending flag to true */ cci_dev->cci_master_info[master].reset_pending = true; + cci_dev->cci_master_info[master].status = 0; /* Set proper mask to RESET CMD address based on MASTER */ if (master == MASTER_0) @@ -66,6 +70,7 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev, CCI_TIMEOUT); if (rc <= 0) CAM_ERR(CAM_CCI, "wait failed %d", rc); + cci_dev->cci_master_info[master].status = 0; } } @@ -127,8 +132,10 @@ static int32_t cam_cci_validate_queue(struct cci_device *cci_dev, return rc; } rc = cci_dev->cci_master_info[master].status; - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_CCI, "Failed rc %d", rc); + cci_dev->cci_master_info[master].status = 0; + } } return rc; @@ -246,14 +253,16 @@ static uint32_t cam_cci_wait(struct cci_device *cci_dev, cam_cci_dump_registers(cci_dev, master, queue); #endif CAM_ERR(CAM_CCI, "wait for queue: %d", queue); - if (rc == 0) + if (rc == 0) { rc = -ETIMEDOUT; - cam_cci_flush_queue(cci_dev, master); - return rc; + cam_cci_flush_queue(cci_dev, master); + return rc; + } } rc = cci_dev->cci_master_info[master].status; if (rc < 0) { CAM_ERR(CAM_CCI, "failed rc %d", rc); + cci_dev->cci_master_info[master].status = 0; return rc; } @@ -851,7 +860,8 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev, rc = cam_cci_transfer_end(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, "Slave: 0x%x failed rc %d", + (c_ctrl->cci_info->sid << 1), rc); return rc; } @@ -918,6 +928,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, mutex_unlock(&cci_dev->cci_master_info[master].mutex); mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + reinit_completion(&cci_dev->cci_master_info[master].report_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 @@ -1024,6 +1035,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, goto rel_mutex_q; } + if (cci_dev->cci_master_info[master].status) { + CAM_ERR(CAM_CCI, "Error with Salve: 0x%x", + (c_ctrl->cci_info->sid << 1)); + rc = -EINVAL; + cci_dev->cci_master_info[master].status = 0; + goto rel_mutex_q; + } + read_words = cam_io_r_mb(base + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); if (read_words <= 0) { @@ -1104,6 +1123,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, cam_cci_flush_queue(cci_dev, master); goto rel_mutex_q; } + + if (cci_dev->cci_master_info[master].status) { + CAM_ERR(CAM_CCI, "Error with Slave 0x%x", + (c_ctrl->cci_info->sid << 1)); + rc = -EINVAL; + cci_dev->cci_master_info[master].status = 0; + goto rel_mutex_q; + } break; } } @@ -1183,6 +1210,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, mutex_unlock(&cci_dev->cci_master_info[master].mutex); mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + reinit_completion(&cci_dev->cci_master_info[master].report_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 @@ -1290,6 +1318,14 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, rc = 0; } + if (cci_dev->cci_master_info[master].status) { + CAM_ERR(CAM_CCI, "ERROR with Slave 0x%x:", + (c_ctrl->cci_info->sid << 1)); + rc = -EINVAL; + cci_dev->cci_master_info[master].status = 0; + goto rel_mutex_q; + } + read_words = cam_io_r_mb(base + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); exp_words = ((read_cfg->num_byte / 4) + 1); @@ -1384,6 +1420,8 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd, goto ERROR; } mutex_unlock(&cci_dev->cci_master_info[master].mutex); + + reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); /* * 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 @@ -1546,6 +1584,7 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, * THRESHOLD irq's, we reinit the threshold wait before * we load the burst read cmd. */ + reinit_completion(&cci_dev->cci_master_info[master].rd_done); reinit_completion(&cci_dev->cci_master_info[master].th_complete); CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes); @@ -1687,7 +1726,29 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, { int32_t rc = 0; struct cci_device *cci_dev = v4l2_get_subdevdata(sd); - CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); + enum cci_i2c_master_t master = MASTER_MAX; + + if (!cci_dev) { + CAM_ERR(CAM_CCI, "CCI_DEV IS NULL"); + return -EINVAL; + } + + if (!cci_ctrl) { + CAM_ERR(CAM_CCI, "CCI_CTRL IS NULL"); + return -EINVAL; + } + + master = cci_ctrl->cci_info->cci_i2c_master; + if (master >= MASTER_MAX) { + CAM_ERR(CAM_CCI, "INVALID MASTER: %d", master); + return -EINVAL; + } + + if (cci_dev->cci_master_info[master].status < 0) { + CAM_WARN(CAM_CCI, "CCI hardware is resetting"); + return -EAGAIN; + } + CAM_DBG(CAM_CCI, "master = %d, cmd = %d", master, cci_ctrl->cmd); switch (cci_ctrl->cmd) { case MSM_CCI_INIT: diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 48552c82239b..4a235c8de287 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" @@ -82,7 +82,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) false; if (!cci_master_info->status) complete(&cci_master_info->reset_complete); - cci_master_info->status = 0; + + complete_all(&cci_master_info->rd_done); + complete_all(&cci_master_info->th_complete); } if (cci_dev->cci_master_info[MASTER_1].reset_pending == true) { cci_master_info = &cci_dev->cci_master_info[MASTER_1]; @@ -90,7 +92,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) false; if (!cci_master_info->status) complete(&cci_master_info->reset_complete); - cci_master_info->status = 0; + + complete_all(&cci_master_info->rd_done); + complete_all(&cci_master_info->th_complete); } } @@ -223,9 +227,18 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_0].status = -EINVAL; - if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) - CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x", + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK) { + CAM_ERR(CAM_CCI, "Base:%pK, M0_Q0 NACK ERROR: 0x%x", base, irq_status0); + complete_all(&cci_dev->cci_master_info[MASTER_0] + .report_q[QUEUE_0]); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK) { + CAM_ERR(CAM_CCI, "Base:%pK, M0_Q1 NACK ERROR: 0x%x", + base, irq_status0); + complete_all(&cci_dev->cci_master_info[MASTER_0] + .report_q[QUEUE_1]); + } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x", @@ -234,22 +247,35 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x", base, irq_status0); - cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); + + cci_dev->cci_master_info[MASTER_0].reset_pending = true; + cam_io_w_mb(CCI_M0_RESET_RMSK, base + CCI_RESET_CMD_ADDR); } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_1].status = -EINVAL; - if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) - CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x", + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK) { + CAM_ERR(CAM_CCI, "Base:%pK, M1_Q0 NACK ERROR: 0x%x", base, irq_status0); - if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) + complete_all(&cci_dev->cci_master_info[MASTER_1] + .report_q[QUEUE_0]); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK) { + CAM_ERR(CAM_CCI, "Base:%pK, M1_Q1 NACK ERROR: 0x%x", + base, irq_status0); + complete_all(&cci_dev->cci_master_info[MASTER_1] + .report_q[QUEUE_1]); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x", base, irq_status0); - if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x", base, irq_status0); - cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); + + cci_dev->cci_master_info[MASTER_1].reset_pending = true; + cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR); } cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h b/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h index f00b854e9533..73756a301f7a 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015, 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_HWREG_ @@ -54,8 +54,10 @@ #define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10 #define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6 #define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000 -#define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK 0x18000000 -#define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK 0x60000000 +#define CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK 0x8000000 +#define CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK 0x10000000 +#define CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK 0x20000000 +#define CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK 0x40000000 #define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK 0xEE0 #define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK 0xEE0000 #define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK 0x6 diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index b21287cd5028..9790055c8a87 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -55,6 +55,7 @@ int cam_cci_init(struct v4l2_subdev *sd, &cci_dev->cci_master_info[master].report_q[i]); /* Set reset pending flag to true */ cci_dev->cci_master_info[master].reset_pending = true; + cci_dev->cci_master_info[master].status = 0; /* Set proper mask to RESET CMD address */ if (master == MASTER_0) cam_io_w_mb(CCI_M0_RESET_RMSK, @@ -68,6 +69,7 @@ int cam_cci_init(struct v4l2_subdev *sd, CCI_TIMEOUT); if (rc <= 0) CAM_ERR(CAM_CCI, "wait failed %d", rc); + cci_dev->cci_master_info[master].status = 0; mutex_unlock(&cci_dev->cci_master_info[master].mutex); } return 0; @@ -142,6 +144,7 @@ int cam_cci_init(struct v4l2_subdev *sd, } cci_dev->cci_master_info[master].reset_pending = true; + cci_dev->cci_master_info[master].status = 0; cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); From 8dc1774e8b4df31ef3184758eb1e8e6e7aeead0b Mon Sep 17 00:00:00 2001 From: Prakasha Nayak Date: Wed, 6 Nov 2019 17:02:50 +0530 Subject: [PATCH 262/790] msm: camera: isp: Add epd Blob support This change adds blob support to disable CSID EOT IRQ in case of high data rate sensors which sends EPD instead of EOT. CRs-Fixed: 2566158 Change-Id: I8ac6d2281a6510d3702f3b651e2c7ca2391afe6c Signed-off-by: Prakasha Nayak --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 67 +++++++++++++++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 29 +++++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 3 +- .../isp_hw/include/cam_ife_csid_hw_intf.h | 9 +++ include/uapi/camera/media/cam_isp.h | 10 +++ 5 files changed, 110 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 70da17532160..b30c6087c610 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4997,6 +4997,51 @@ static int cam_isp_blob_vfe_out_update( return rc; } +static int cam_isp_blob_csid_config_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_csid_epd_config *epd_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_csid_epd_update_args epd_update_args; + int rc = -EINVAL; + uint32_t i = 0; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, 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) { + epd_update_args.epd_supported = + epd_config->is_epd_supported; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_SET_CONFIG, + &epd_update_args, + sizeof( + struct cam_ife_csid_epd_update_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Failed to epd config:%d", + epd_config->is_epd_supported); + } else { + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + + } + } + + return rc; +} static int cam_isp_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { @@ -5011,12 +5056,6 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, return -EINVAL; } - if (blob_type >= CAM_ISP_GENERIC_BLOB_TYPE_MAX) { - CAM_ERR(CAM_ISP, "Invalid Blob Type %d Max %d", blob_type, - CAM_ISP_GENERIC_BLOB_TYPE_MAX); - return -EINVAL; - } - prepare = blob_info->prepare; if (!prepare || !prepare->ctxt_to_hw_map) { CAM_ERR(CAM_ISP, "Failed. prepare is NULL, blob_type %d", @@ -5466,7 +5505,23 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "VFE out update failed rc: %d", rc); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG: { + struct cam_isp_csid_epd_config *epd_config; + if (blob_size < sizeof(struct cam_isp_csid_epd_config)) { + CAM_ERR(CAM_ISP, + "Invalid epd config blob size %u expected %u", + blob_size, + sizeof(struct cam_isp_csid_epd_config)); + return -EINVAL; + } + epd_config = (struct cam_isp_csid_epd_config *)blob_data; + rc = cam_isp_blob_csid_config_update(blob_type, blob_info, + epd_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "CSID Config failed rc: %d", rc); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 02c5746c1805..150e40050999 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -520,6 +520,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) csid_hw->hw_intf->hw_idx, val); csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; + csid_hw->epd_supported = 0; end: return rc; @@ -1349,6 +1350,7 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; + csid_hw->epd_supported = 0; return rc; } @@ -1584,7 +1586,6 @@ static int cam_ife_csid_enable_csi2( CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW | CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW | CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW | - CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION | CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION | CSID_CSI2_RX_ERROR_CRC | CSID_CSI2_RX_ERROR_ECC | @@ -1593,6 +1594,12 @@ static int cam_ife_csid_enable_csi2( CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME | CSID_CSI2_RX_ERROR_CPHY_PH_CRC; + if (csid_hw->epd_supported == 1) + CAM_INFO(CAM_ISP, + "Disable CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION for EPD"); + else + val = val | CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION; + /* Enable the interrupt based on csid debug info set */ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOT_IRQ) val |= CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED | @@ -3788,6 +3795,23 @@ static int cam_ife_csid_set_csid_qcfa( return 0; } +static int cam_ife_csid_set_epd_config( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_csid_epd_update_args *epd_update = NULL; + + if ((!csid_hw) || (!cmd_args)) + return -EINVAL; + + epd_update = + (struct cam_ife_csid_epd_update_args *)cmd_args; + + csid_hw->epd_supported = epd_update->epd_supported; + CAM_DBG(CAM_ISP, "CSID EPD supported %d", csid_hw->epd_supported); + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -3825,6 +3849,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED: rc = cam_ife_csid_set_csid_qcfa(csid_hw, cmd_args); break; + case CAM_IFE_CSID_SET_CONFIG: + rc = cam_ife_csid_set_epd_config(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 4c2ac18089af..ab2ea20a045f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -550,9 +550,9 @@ struct cam_ife_csid_path_cfg { * need to stop the CSID and mask interrupts. * @binning_enable Flag is set if hardware supports QCFA binning * @binning_supported Flag is set if sensor supports QCFA binning - * * @first_sof_ts first bootime stamp at the start * @prev_qtimer_ts stores csid timestamp + * @epd_supported Flag is set if sensor supports EPD */ struct cam_ife_csid_hw { struct cam_hw_intf *hw_intf; @@ -586,6 +586,7 @@ struct cam_ife_csid_hw { uint32_t binning_supported; uint64_t prev_boot_timestamp; uint64_t prev_qtimer_ts; + uint32_t epd_supported; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 56ce59636dda..b7f2692b61a0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -204,6 +204,7 @@ enum cam_ife_csid_cmd_type { CAM_IFE_CSID_CMD_GET_TIME_STAMP, CAM_IFE_CSID_SET_CSID_DEBUG, CAM_IFE_CSID_SOF_IRQ_DEBUG, + CAM_IFE_CSID_SET_CONFIG, CAM_IFE_CSID_CMD_MAX, }; @@ -236,5 +237,13 @@ struct cam_ife_csid_qcfa_update_args { uint32_t qcfa_binning; }; +/* + * struct cam_ife_csid_epd_update_args: + * + * @epd_supported: flag to check epd supported or not + */ +struct cam_ife_csid_epd_update_args { + uint32_t epd_supported; +}; #endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index 22e898b55cfc..0acb0f98ca0d 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -102,6 +102,7 @@ #define CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG 7 #define CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG 8 #define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 9 +#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG 10 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG 12 #define CAM_ISP_VC_DT_CFG 4 @@ -699,6 +700,15 @@ struct cam_isp_vfe_out_config { struct cam_isp_vfe_wm_config wm_config[1]; }; +/** + * struct cam_isp_csid_epd_config - Support for EPD Packet config + * + * @is_epd_sensor : flag to check if epd supported + */ +struct cam_isp_csid_epd_config { + uint32_t is_epd_supported; +}; + #define CAM_ISP_ACQUIRE_COMMON_VER0 0x1000 #define CAM_ISP_ACQUIRE_COMMON_SIZE_VER0 0x0 From 1ed310412a6cc983e14a0877c728462ccd74134c Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Fri, 3 Jan 2020 18:37:51 +0530 Subject: [PATCH 263/790] msm: camera: cpas: Add support for camnoc based voting For some targets, it is needed to vote for camnoc clock as there is no CAMNOC AXI clock source in camera domain. Voting is done with the bus drivers and it calcultates the clock rate. This change adds support for camnoc based voting. CRs-Fixed: 2571273 Change-Id: I38a4fa8d40892b6dfe7e925b6368eb259132615d Signed-off-by: Gaurav Jindal --- drivers/cam_cpas/cam_cpas_hw.c | 166 +++++++++++++++++++++++++++----- drivers/cam_cpas/cam_cpas_hw.h | 10 +- drivers/cam_cpas/cam_cpas_soc.c | 56 ++++++++++- drivers/cam_cpas/cam_cpas_soc.h | 4 +- 4 files changed, 208 insertions(+), 28 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 71a4e4ea953b..0486a0c2fccd 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -177,6 +177,12 @@ static int cam_cpas_util_axi_cleanup(struct cam_cpas *cpas_core, return -EINVAL; } + if (cpas_core->num_camnoc_axi_ports > CAM_CPAS_MAX_AXI_PORTS) { + CAM_ERR(CAM_CPAS, "Invalid num_camnoc_axi_ports: %d", + cpas_core->num_camnoc_axi_ports); + return -EINVAL; + } + for (i = 0; i < cpas_core->num_axi_ports; i++) { cam_cpas_util_unregister_bus_client( &cpas_core->axi_port[i].bus_client); @@ -184,6 +190,13 @@ static int cam_cpas_util_axi_cleanup(struct cam_cpas *cpas_core, cpas_core->axi_port[i].axi_port_node = NULL; } + for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { + cam_cpas_util_unregister_bus_client( + &cpas_core->camnoc_axi_port[i].bus_client); + of_node_put(cpas_core->camnoc_axi_port[i].axi_port_node); + cpas_core->camnoc_axi_port[i].axi_port_node = NULL; + } + return 0; } @@ -192,6 +205,7 @@ static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core, { int i = 0, rc = 0; struct device_node *axi_port_mnoc_node = NULL; + struct device_node *axi_port_camnoc_node = NULL; if (cpas_core->num_axi_ports > CAM_CPAS_MAX_AXI_PORTS) { CAM_ERR(CAM_CPAS, "Invalid num_axi_ports: %d", @@ -206,6 +220,15 @@ static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core, if (rc) goto bus_register_fail; } + for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { + axi_port_camnoc_node = + cpas_core->camnoc_axi_port[i].axi_port_node; + rc = cam_cpas_util_register_bus_client(soc_info, + axi_port_camnoc_node, + &cpas_core->camnoc_axi_port[i].bus_client); + if (rc) + goto bus_register_fail; + } return 0; bus_register_fail: @@ -543,6 +566,99 @@ static int cam_cpas_axi_consolidate_path_votes( return rc; } +static int cam_cpas_update_axi_vote_bw( + struct cam_hw_info *cpas_hw, + struct cam_cpas_tree_node *cpas_tree_node, + bool *mnoc_axi_port_updated, + bool *camnoc_axi_port_updated) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + + if (cpas_tree_node->axi_port_idx >= CAM_CPAS_MAX_AXI_PORTS) { + CAM_ERR(CAM_CPAS, "Invalid axi_port_idx: %d", + cpas_tree_node->axi_port_idx); + return -EINVAL; + } + + cpas_core->axi_port[cpas_tree_node->axi_port_idx].ab_bw = + cpas_tree_node->mnoc_ab_bw; + cpas_core->axi_port[cpas_tree_node->axi_port_idx].ib_bw = + cpas_tree_node->mnoc_ib_bw; + mnoc_axi_port_updated[cpas_tree_node->axi_port_idx] = true; + + if (soc_private->control_camnoc_axi_clk) + return 0; + + cpas_core->camnoc_axi_port[cpas_tree_node->axi_port_idx].camnoc_bw = + cpas_tree_node->camnoc_bw; + camnoc_axi_port_updated[cpas_tree_node->camnoc_axi_port_idx] = true; + return 0; +} + +static int cam_cpas_camnoc_set_vote_axi_clk_rate( + struct cam_hw_info *cpas_hw, + bool *camnoc_axi_port_updated) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + int i; + int rc = 0; + struct cam_cpas_axi_port *camnoc_axi_port = NULL; + uint64_t camnoc_bw; + + if (soc_private->control_camnoc_axi_clk) { + rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); + if (rc) + CAM_ERR(CAM_CPAS, + "Failed in setting axi clk rate rc=%d", rc); + return rc; + } + + /* Below code is executed if we just vote and do not set the clk rate + * for camnoc + */ + + if (cpas_core->num_camnoc_axi_ports > CAM_CPAS_MAX_AXI_PORTS) { + CAM_ERR(CAM_CPAS, "Invalid num_camnoc_axi_ports: %d", + cpas_core->num_camnoc_axi_ports); + return -EINVAL; + } + + for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { + if (camnoc_axi_port_updated[i]) + camnoc_axi_port = &cpas_core->camnoc_axi_port[i]; + else + continue; + + CAM_DBG(CAM_PERF, "Port[%s] : camnoc_bw=%lld", + camnoc_axi_port->axi_port_name, + camnoc_axi_port->camnoc_bw); + + if (camnoc_axi_port->camnoc_bw) + camnoc_bw = camnoc_axi_port->camnoc_bw; + else + camnoc_bw = camnoc_axi_port->additional_bw; + + rc = cam_cpas_util_vote_bus_client_bw( + &camnoc_axi_port->bus_client, + 0, camnoc_bw, true); + + CAM_DBG(CAM_CPAS, + "camnoc vote camnoc_bw[%llu] rc=%d %s", + camnoc_bw, rc, camnoc_axi_port->axi_port_name); + if (rc) { + CAM_ERR(CAM_CPAS, + "Failed in camnoc vote camnoc_bw[%llu] rc=%d", + camnoc_bw, rc); + break; + } + } + return rc; +} + static int cam_cpas_util_apply_client_axi_vote( struct cam_hw_info *cpas_hw, struct cam_cpas_client *cpas_client, @@ -550,12 +666,13 @@ static int cam_cpas_util_apply_client_axi_vote( { struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_axi_vote *con_axi_vote = NULL; - struct cam_cpas_axi_port *axi_port = NULL; + struct cam_cpas_axi_port *mnoc_axi_port = NULL; struct cam_cpas_tree_node *curr_tree_node = NULL; struct cam_cpas_tree_node *par_tree_node = NULL; uint32_t transac_type; uint32_t path_data_type; - bool axi_port_updated[CAM_CPAS_MAX_AXI_PORTS] = {false}; + bool mnoc_axi_port_updated[CAM_CPAS_MAX_AXI_PORTS] = {false}; + bool camnoc_axi_port_updated[CAM_CPAS_MAX_AXI_PORTS] = {false}; uint64_t mnoc_ab_bw = 0, mnoc_ib_bw = 0, curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0, par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0; @@ -578,7 +695,7 @@ static int cam_cpas_util_apply_client_axi_vote( cpas_core->axi_port[i].additional_bw -= CAM_CPAS_DEFAULT_AXI_BW; } - axi_port_updated[i] = true; + mnoc_axi_port_updated[i] = true; } goto vote_start_clients; } @@ -668,15 +785,15 @@ static int cam_cpas_util_apply_client_axi_vote( rc = -EINVAL; goto unlock_tree; } - - cpas_core->axi_port - [par_tree_node->axi_port_idx].ab_bw = - par_tree_node->mnoc_ab_bw; - cpas_core->axi_port - [par_tree_node->axi_port_idx].ib_bw = - par_tree_node->mnoc_ib_bw; - axi_port_updated[par_tree_node->axi_port_idx] = - true; + rc = cam_cpas_update_axi_vote_bw(cpas_hw, + par_tree_node, + mnoc_axi_port_updated, + camnoc_axi_port_updated); + if (rc) { + CAM_ERR(CAM_CPAS, + "Update Vote failed"); + goto unlock_tree; + } } curr_tree_node = par_tree_node; @@ -694,26 +811,27 @@ static int cam_cpas_util_apply_client_axi_vote( vote_start_clients: for (i = 0; i < cpas_core->num_axi_ports; i++) { - if (axi_port_updated[i]) - axi_port = &cpas_core->axi_port[i]; + if (mnoc_axi_port_updated[i]) + mnoc_axi_port = &cpas_core->axi_port[i]; else continue; CAM_DBG(CAM_PERF, "Port[%s] : ab=%lld ib=%lld additional=%lld", - axi_port->bus_client.common_data.name, axi_port->ab_bw, - axi_port->ib_bw, axi_port->additional_bw); + mnoc_axi_port->axi_port_name, mnoc_axi_port->ab_bw, + mnoc_axi_port->ib_bw, mnoc_axi_port->additional_bw); - if (axi_port->ab_bw) - mnoc_ab_bw = axi_port->ab_bw; + if (mnoc_axi_port->ab_bw) + mnoc_ab_bw = mnoc_axi_port->ab_bw; else - mnoc_ab_bw = axi_port->additional_bw; + mnoc_ab_bw = mnoc_axi_port->additional_bw; if (cpas_core->axi_port[i].ib_bw_voting_needed) - mnoc_ib_bw = axi_port->ib_bw; + mnoc_ib_bw = mnoc_axi_port->ib_bw; else mnoc_ib_bw = 0; - rc = cam_cpas_util_vote_bus_client_bw(&axi_port->bus_client, + rc = cam_cpas_util_vote_bus_client_bw( + &mnoc_axi_port->bus_client, mnoc_ab_bw, mnoc_ib_bw, false); if (rc) { CAM_ERR(CAM_CPAS, @@ -722,8 +840,8 @@ vote_start_clients: goto unlock_tree; } } - - rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); + rc = cam_cpas_camnoc_set_vote_axi_clk_rate( + cpas_hw, camnoc_axi_port_updated); if (rc) CAM_ERR(CAM_CPAS, "Failed in setting axi clk rate rc=%d", rc); diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index 2b207a090a02..ac692d9ff559 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_H_ @@ -136,19 +136,23 @@ struct cam_cpas_bus_client { /** * struct cam_cpas_axi_port : AXI port information * + * @axi_port_name: Name of this AXI port * @bus_client: bus client info for this port * @ib_bw_voting_needed: if this port can update ib bw dynamically * @axi_port_node: Node representing AXI Port info in device tree * @ab_bw: AB bw value for this port * @ib_bw: IB bw value for this port + * @camnoc_bw: CAMNOC bw value for this port * @additional_bw: Additional bandwidth to cover non-hw cpas clients */ struct cam_cpas_axi_port { + const char *axi_port_name; struct cam_cpas_bus_client bus_client; bool ib_bw_voting_needed; struct device_node *axi_port_node; uint64_t ab_bw; uint64_t ib_bw; + uint64_t camnoc_bw; uint64_t additional_bw; }; @@ -161,11 +165,13 @@ struct cam_cpas_axi_port { * @tree_lock: Mutex lock for accessing CPAS node tree * @num_clients: Total number of clients that CPAS supports * @num_axi_ports: Total number of axi ports found in device tree + * @num_camnoc_axi_ports: Total number of camnoc axi ports found in device tree * @registered_clients: Number of Clients registered currently * @streamon_clients: Number of Clients that are in start state currently * @regbase_index: Register base indices for CPAS register base IDs * @ahb_bus_client: AHB Bus client info * @axi_port: AXI port info for a specific axi index + * @camnoc_axi_port: CAMNOC AXI port info for a specific camnoc axi index * @internal_ops: CPAS HW internal ops * @work_queue: Work queue handle * @irq_count: atomic irq count @@ -180,11 +186,13 @@ struct cam_cpas { struct mutex tree_lock; uint32_t num_clients; uint32_t num_axi_ports; + uint32_t num_camnoc_axi_ports; uint32_t registered_clients; uint32_t streamon_clients; int32_t regbase_index[CAM_CPAS_REG_MAX]; struct cam_cpas_bus_client ahb_bus_client; struct cam_cpas_axi_port axi_port[CAM_CPAS_MAX_AXI_PORTS]; + struct cam_cpas_axi_port camnoc_axi_port[CAM_CPAS_MAX_AXI_PORTS]; struct cam_cpas_internal_ops internal_ops; struct workqueue_struct *work_queue; atomic_t irq_count; diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index a55f4a97813f..1a34b2409f11 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -134,6 +134,47 @@ static int cam_cpas_util_path_type_to_idx(uint32_t *path_data_type) return 0; } +static int cam_cpas_update_camnoc_node(struct cam_cpas *cpas_core, + struct device_node *curr_node, + struct cam_cpas_tree_node *cpas_node_ptr, + int *camnoc_idx) + +{ + struct device_node *camnoc_node; + int rc; + + camnoc_node = of_find_node_by_name(curr_node, + "qcom,axi-port-camnoc"); + if (camnoc_node) { + + if (*camnoc_idx >= + CAM_CPAS_MAX_AXI_PORTS) { + CAM_ERR(CAM_CPAS, "CAMNOC axi index overshoot %d", + *camnoc_idx); + return -EINVAL; + } + + cpas_core->camnoc_axi_port[*camnoc_idx] + .axi_port_node = camnoc_node; + rc = of_property_read_string( + curr_node, + "qcom,axi-port-name", + &cpas_core->camnoc_axi_port[*camnoc_idx] + .axi_port_name); + + if (rc) { + CAM_ERR(CAM_CPAS, + "fail to read camnoc-port-name rc=%d", + rc); + return rc; + } + cpas_node_ptr->camnoc_axi_port_idx = *camnoc_idx; + cpas_core->num_camnoc_axi_ports++; + (*camnoc_idx)++; + } + return 0; +} + static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, struct device_node *of_node, struct cam_cpas_private_soc *soc_private) { @@ -142,7 +183,7 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, struct device_node *curr_node; struct device_node *parent_node; struct device_node *mnoc_node; - int mnoc_idx = 0; + int mnoc_idx = 0, camnoc_idx = 0; uint32_t path_idx; bool camnoc_max_needed = false; struct cam_cpas_tree_node *curr_node_ptr = NULL; @@ -311,6 +352,17 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, cpas_core->num_axi_ports++; } + if (!soc_private->control_camnoc_axi_clk) { + rc = cam_cpas_update_camnoc_node( + cpas_core, curr_node, curr_node_ptr, + &camnoc_idx); + if (rc) { + CAM_ERR(CAM_CPAS, + "Parse Camnoc port fail"); + return rc; + } + } + rc = of_property_read_string(curr_node, "client-name", &client_name); if (!rc) { diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index ef5eb32337e6..45a045ef6f55 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_SOC_H_ @@ -30,6 +30,7 @@ struct cam_cpas_vdd_ahb_mapping { * @cell_idx: Index to identify node from device tree and its parent * @level_idx: Index to identify at what level the node is present * @axi_port_idx: Index to identify which axi port to vote the consolidated bw + * @camnoc_axi_port_idx: Index to find which axi port to vote consolidated bw * @path_data_type: Traffic type info from device tree (ife-vid, ife-disp etc) * @path_trans_type: Transaction type info from device tree (rd, wr) * @merge_type: Traffic merge type (calculation info) from device tree @@ -53,6 +54,7 @@ struct cam_cpas_tree_node { uint32_t cell_idx; uint32_t level_idx; int axi_port_idx; + int camnoc_axi_port_idx; const char *node_name; uint32_t path_data_type; uint32_t path_trans_type; From 5cb000ee7f9d678e40a4ed07df145c0f1a3bc75b Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sat, 25 Jan 2020 21:15:38 -0800 Subject: [PATCH 264/790] msm: camera: common: Add component helper support in camera Due to the asynchronous nature of platform probes, inter dependency between drivers needs to be taken care during kernel boot up. Component helper provides the facility of adding matching drivers in a list ordered in the way we want to bind those drivers. The CRM driver acts as component master to make sure all slave drivers are bound before it returns from its own bind call. Add support for serializing platform probes through component framework. CRs-Fixed: 2584631 Change-Id: I345da1d2b9cccf6021ac6fc899143013b7714ec4 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cdm/cam_cdm_hw_core.c | 46 +++- drivers/cam_cdm/cam_cdm_intf.c | 40 +++- drivers/cam_cpas/cam_cpas_intf.c | 39 +++- drivers/cam_cust/cam_custom_dev.c | 77 ++++--- .../cam_custom_csid/cam_custom_csid_dev.c | 52 ++++- .../cam_custom_hw1/cam_custom_sub_mod_dev.c | 42 +++- drivers/cam_fd/cam_fd_dev.c | 37 ++- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c | 41 +++- drivers/cam_icp/cam_icp_subdev.c | 43 +++- drivers/cam_icp/icp_hw/a5_hw/a5_dev.c | 37 ++- drivers/cam_icp/icp_hw/bps_hw/bps_dev.c | 36 ++- drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c | 39 +++- drivers/cam_isp/cam_isp_dev.c | 73 ++++-- .../isp_hw/ife_csid_hw/cam_ife_csid17x.c | 3 +- .../isp_hw/ife_csid_hw/cam_ife_csid_dev.c | 40 +++- .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c | 3 +- .../isp_hw/tfe_csid_hw/cam_tfe_csid530.c | 3 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c | 3 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c | 50 ++-- .../isp_hw/top_tpg/cam_top_tpg_dev.c | 41 +++- .../isp_hw/top_tpg/cam_top_tpg_v1.c | 3 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c | 55 +++-- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c | 5 +- drivers/cam_jpeg/cam_jpeg_dev.c | 72 ++++-- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 131 ++++++----- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 127 +++++++---- drivers/cam_lrme/cam_lrme_dev.c | 37 ++- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c | 38 +++- drivers/cam_ope/cam_ope_subdev.c | 47 +++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 35 ++- drivers/cam_req_mgr/cam_req_mgr_dev.c | 91 ++++++-- .../cam_actuator/cam_actuator_dev.c | 189 +++++++++------- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 39 +++- .../cam_sensor_module/cam_cci/cam_cci_soc.c | 4 - .../cam_csiphy/cam_csiphy_dev.c | 51 ++++- .../cam_eeprom/cam_eeprom_dev.c | 39 +++- .../cam_flash/cam_flash_dev.c | 80 ++++--- .../cam_sensor_module/cam_ois/cam_ois_dev.c | 40 +++- .../cam_res_mgr/cam_res_mgr.c | 34 ++- .../cam_sensor/cam_sensor_dev.c | 157 +++++++------ drivers/cam_smmu/cam_smmu_api.c | 213 +++++++++++++----- drivers/cam_sync/cam_sync.c | 33 ++- drivers/camera_main.c | 105 +++++++++ drivers/camera_main.h | 71 ++++++ 44 files changed, 1826 insertions(+), 615 deletions(-) create mode 100644 drivers/camera_main.h diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 8145b3293216..a78156243e3c 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -22,6 +22,7 @@ #include "cam_cdm_hw_reg_1_1.h" #include "cam_cdm_hw_reg_1_2.h" #include "cam_cdm_hw_reg_2_0.h" +#include "camera_main.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 #define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff @@ -1571,7 +1572,8 @@ int cam_hw_cdm_deinit(void *hw_priv, return rc; } -int cam_hw_cdm_probe(struct platform_device *pdev) +static int cam_hw_cdm_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc, len = 0, i, j; struct cam_hw_info *cdm_hw = NULL; @@ -1582,6 +1584,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote = {0}; char cdm_name[128], work_q_name[128]; + struct platform_device *pdev = to_platform_device(dev); cdm_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!cdm_hw_intf) @@ -1794,7 +1797,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) cdm_hw->open_count--; mutex_unlock(&cdm_hw->hw_mutex); - CAM_DBG(CAM_CDM, "%s probe successful", cdm_core->name); + CAM_DBG(CAM_CDM, "%s component bound successfully", cdm_core->name); return rc; @@ -1833,17 +1836,19 @@ release_mem: return rc; } -int cam_hw_cdm_remove(struct platform_device *pdev) +static void cam_hw_cdm_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int rc = -EBUSY, i; struct cam_hw_info *cdm_hw = NULL; struct cam_hw_intf *cdm_hw_intf = NULL; struct cam_cdm *cdm_core = NULL; + struct platform_device *pdev = to_platform_device(dev); cdm_hw_intf = platform_get_drvdata(pdev); if (!cdm_hw_intf) { CAM_ERR(CAM_CDM, "Failed to get dev private data"); - return rc; + return; } cdm_hw = cdm_hw_intf->hw_priv; @@ -1851,7 +1856,7 @@ int cam_hw_cdm_remove(struct platform_device *pdev) CAM_ERR(CAM_CDM, "Failed to get hw private data for type=%d idx=%d", cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx); - return rc; + return; } cdm_core = cdm_hw->core_info; @@ -1859,26 +1864,26 @@ int cam_hw_cdm_remove(struct platform_device *pdev) CAM_ERR(CAM_CDM, "Failed to get hw core data for type=%d idx=%d", cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx); - return rc; + return; } if (cdm_hw->open_count != 0) { CAM_ERR(CAM_CDM, "Hw open count invalid type=%d idx=%d cnt=%d", cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx, cdm_hw->open_count); - return rc; + return; } rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); if (rc) { CAM_ERR(CAM_CDM, "Deinit failed for hw"); - return rc; + return; } rc = cam_cpas_unregister_client(cdm_core->cpas_handle); if (rc) { CAM_ERR(CAM_CDM, "CPAS unregister failed"); - return rc; + return; } if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info)) @@ -1899,11 +1904,32 @@ int cam_hw_cdm_remove(struct platform_device *pdev) kfree(cdm_hw_intf); kfree(cdm_hw->core_info); kfree(cdm_hw); +} +const static struct component_ops cam_hw_cdm_component_ops = { + .bind = cam_hw_cdm_component_bind, + .unbind = cam_hw_cdm_component_unbind, +}; + +int cam_hw_cdm_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CDM, "Adding HW CDM component"); + rc = component_add(&pdev->dev, &cam_hw_cdm_component_ops); + if (rc) + CAM_ERR(CAM_CDM, "failed to add component rc: %d", rc); + + return rc; +} + +int cam_hw_cdm_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_hw_cdm_component_ops); return 0; } -static struct platform_driver cam_hw_cdm_driver = { +struct platform_driver cam_hw_cdm_driver = { .probe = cam_hw_cdm_probe, .remove = cam_hw_cdm_remove, .driver = { diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index bbb97d21c123..dcdbc667f832 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -16,6 +16,7 @@ #include "cam_soc_util.h" #include "cam_cdm_soc.h" #include "cam_cdm_core_common.h" +#include "camera_main.h" static struct cam_cdm_intf_mgr cdm_mgr; static DEFINE_MUTEX(cam_cdm_mgr_lock); @@ -563,9 +564,11 @@ int cam_cdm_intf_deregister_hw_cdm(struct cam_hw_intf *hw, return rc; } -static int cam_cdm_intf_probe(struct platform_device *pdev) +static int cam_cdm_intf_component_bind(struct device *dev, + struct device *master_dev, void *data) { int i, rc; + struct platform_device *pdev = to_platform_device(dev); rc = cam_cdm_intf_mgr_soc_get_dt_properties(pdev, &cdm_mgr); if (rc) { @@ -599,18 +602,20 @@ static int cam_cdm_intf_probe(struct platform_device *pdev) mutex_unlock(&cam_cdm_mgr_lock); } - CAM_DBG(CAM_CDM, "CDM Intf probe done"); + CAM_DBG(CAM_CDM, "CDM Intf component bound successfully"); return rc; } -static int cam_cdm_intf_remove(struct platform_device *pdev) +static void cam_cdm_intf_component_unbind(struct device *dev, + struct device *master_dev, void *data) { - int i, rc = -EBUSY; + int i; + struct platform_device *pdev = to_platform_device(dev); if (get_cdm_mgr_refcount()) { CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); - return rc; + return; } if (cam_virtual_cdm_remove(pdev)) { @@ -639,14 +644,35 @@ static int cam_cdm_intf_remove(struct platform_device *pdev) cdm_mgr.nodes[i].refcount = 0; } cdm_mgr.probe_done = false; - rc = 0; end: mutex_unlock(&cam_cdm_mgr_lock); +} + +const static struct component_ops cam_cdm_intf_component_ops = { + .bind = cam_cdm_intf_component_bind, + .unbind = cam_cdm_intf_component_unbind, +}; + +static int cam_cdm_intf_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CDM, "Adding CDM INTF component"); + rc = component_add(&pdev->dev, &cam_cdm_intf_component_ops); + if (rc) + CAM_ERR(CAM_CDM, "failed to add component rc: %d", rc); + return rc; } -static struct platform_driver cam_cdm_intf_driver = { +static int cam_cdm_intf_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_cdm_intf_component_ops); + return 0; +} + +struct platform_driver cam_cdm_intf_driver = { .probe = cam_cdm_intf_probe, .remove = cam_cdm_intf_remove, .driver = { diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index bfa017a86442..f96da1779c2a 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -17,6 +17,7 @@ #include "cam_subdev.h" #include "cam_cpas_hw_intf.h" #include "cam_cpas_soc.h" +#include "camera_main.h" #define CAM_CPAS_DEV_NAME "cam-cpas" #define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done) @@ -651,14 +652,16 @@ static int cam_cpas_subdev_register(struct platform_device *pdev) return rc; } -static int cam_cpas_dev_probe(struct platform_device *pdev) +static int cam_cpas_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_cpas_hw_caps *hw_caps; struct cam_hw_intf *hw_intf; int rc; + struct platform_device *pdev = to_platform_device(dev); if (g_cpas_intf) { - CAM_ERR(CAM_CPAS, "cpas dev proble already done"); + CAM_ERR(CAM_CPAS, "cpas component already binded"); return -EALREADY; } @@ -695,7 +698,7 @@ static int cam_cpas_dev_probe(struct platform_device *pdev) g_cpas_intf->probe_done = true; CAM_DBG(CAM_CPAS, - "CPAS INTF Probe success %d, %d.%d.%d, %d.%d.%d, 0x%x", + "Component bound successfully %d, %d.%d.%d, %d.%d.%d, 0x%x", hw_caps->camera_family, hw_caps->camera_version.major, hw_caps->camera_version.minor, hw_caps->camera_version.incr, hw_caps->cpas_version.major, hw_caps->cpas_version.minor, @@ -709,15 +712,16 @@ error_destroy_mem: mutex_destroy(&g_cpas_intf->intf_lock); kfree(g_cpas_intf); g_cpas_intf = NULL; - CAM_ERR(CAM_CPAS, "CPAS probe failed"); + CAM_ERR(CAM_CPAS, "CPAS component bind failed"); return rc; } -static int cam_cpas_dev_remove(struct platform_device *dev) +static void cam_cpas_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) { if (!CAM_CPAS_INTF_INITIALIZED()) { CAM_ERR(CAM_CPAS, "cpas intf not initialized"); - return -ENODEV; + return; } mutex_lock(&g_cpas_intf->intf_lock); @@ -728,7 +732,28 @@ static int cam_cpas_dev_remove(struct platform_device *dev) mutex_destroy(&g_cpas_intf->intf_lock); kfree(g_cpas_intf); g_cpas_intf = NULL; +} +const static struct component_ops cam_cpas_dev_component_ops = { + .bind = cam_cpas_dev_component_bind, + .unbind = cam_cpas_dev_component_unbind, +}; + +static int cam_cpas_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CPAS, "Adding CPAS INTF component"); + rc = component_add(&pdev->dev, &cam_cpas_dev_component_ops); + if (rc) + CAM_ERR(CAM_CPAS, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_cpas_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_cpas_dev_component_ops); return 0; } @@ -737,7 +762,7 @@ static const struct of_device_id cam_cpas_dt_match[] = { {} }; -static struct platform_driver cam_cpas_driver = { +struct platform_driver cam_cpas_driver = { .probe = cam_cpas_dev_probe, .remove = cam_cpas_dev_remove, .driver = { diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index f36e5ad27cf2..af3c7b907af5 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -20,6 +20,7 @@ #include "cam_node.h" #include "cam_debug_util.h" #include "cam_smmu_api.h" +#include "camera_main.h" static struct cam_custom_dev g_custom_dev; @@ -92,34 +93,15 @@ static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { .open = cam_custom_subdev_open, }; -static int cam_custom_dev_remove(struct platform_device *pdev) -{ - int rc = 0; - int i; - - /* clean up resources */ - for (i = 0; i < CAM_CUSTOM_HW_MAX_INSTANCES; i++) { - rc = cam_custom_dev_context_deinit(&g_custom_dev.ctx_custom[i]); - if (rc) - CAM_ERR(CAM_CUSTOM, - "Custom context %d deinit failed", i); - } - - rc = cam_subdev_remove(&g_custom_dev.sd); - if (rc) - CAM_ERR(CAM_CUSTOM, "Unregister failed"); - - memset(&g_custom_dev, 0, sizeof(g_custom_dev)); - return 0; -} - -static int cam_custom_dev_probe(struct platform_device *pdev) +static int cam_custom_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc = -EINVAL; int i; struct cam_hw_mgr_intf hw_mgr_intf; - struct cam_node *node; + struct cam_node *node; int iommu_hdl = -1; + struct platform_device *pdev = to_platform_device(dev); g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; @@ -163,7 +145,7 @@ static int cam_custom_dev_probe(struct platform_device *pdev) mutex_init(&g_custom_dev.custom_dev_mutex); - CAM_DBG(CAM_CUSTOM, "Camera custom HW probe complete"); + CAM_DBG(CAM_CUSTOM, "%s component bound successfully", pdev->name); return 0; unregister: @@ -172,8 +154,51 @@ err: return rc; } +static void cam_custom_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + int rc = 0; + int i; -static struct platform_driver custom_driver = { + /* clean up resources */ + for (i = 0; i < CAM_CUSTOM_HW_MAX_INSTANCES; i++) { + rc = cam_custom_dev_context_deinit(&g_custom_dev.ctx_custom[i]); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Custom context %d deinit failed", i); + } + + rc = cam_subdev_remove(&g_custom_dev.sd); + if (rc) + CAM_ERR(CAM_CUSTOM, "Unregister failed"); + + memset(&g_custom_dev, 0, sizeof(g_custom_dev)); +} + +const static struct component_ops cam_custom_component_ops = { + .bind = cam_custom_component_bind, + .unbind = cam_custom_component_unbind, +}; + +static int cam_custom_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_custom_component_ops); + return 0; +} + +static int cam_custom_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CUSTOM, "Adding Custom HW component"); + rc = component_add(&pdev->dev, &cam_custom_component_ops); + if (rc) + CAM_ERR(CAM_CUSTOM, "failed to add component rc: %d", rc); + + return rc; +} + +struct platform_driver custom_driver = { .probe = cam_custom_dev_probe, .remove = cam_custom_dev_remove, .driver = { diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c index ca592a60fcb0..724d047fa0de 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -14,6 +14,7 @@ #include "cam_hw_intf.h" #include "cam_custom_csid480.h" #include "cam_debug_util.h" +#include "camera_main.h" #define CAM_CUSTOM_CSID_DRV_NAME "custom_csid" @@ -27,16 +28,18 @@ static struct cam_ife_csid_hw_info cam_custom_csid480_hw_info = { .hw_dts_version = CAM_CSID_VERSION_V480, }; -static int cam_custom_csid_probe(struct platform_device *pdev) +static int cam_custom_csid_component_bind(struct device *dev, + struct device *master_dev, void *data) { - struct cam_hw_intf *csid_hw_intf; - struct cam_hw_info *csid_hw_info; - struct cam_ife_csid_hw *csid_dev = NULL; + struct cam_hw_intf *csid_hw_intf; + struct cam_hw_info *csid_hw_info; + struct cam_ife_csid_hw *csid_dev = NULL; const struct of_device_id *match_dev = NULL; struct cam_ife_csid_hw_info *csid_hw_data = NULL; - uint32_t csid_dev_idx; - int rc = 0; + uint32_t csid_dev_idx; + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL); if (!csid_hw_intf) { @@ -90,14 +93,15 @@ static int cam_custom_csid_probe(struct platform_device *pdev) goto free_dev; platform_set_drvdata(pdev, csid_dev); - CAM_DBG(CAM_CUSTOM, "CSID:%d probe successful for dev %s", - csid_hw_intf->hw_idx, csid_dev_name); if (csid_hw_intf->hw_idx < CAM_IFE_CSID_HW_NUM_MAX) cam_custom_csid_hw_list[csid_hw_intf->hw_idx] = csid_hw_intf; else goto free_dev; + CAM_DBG(CAM_CUSTOM, "CSID:%d component bound successfully", + csid_hw_intf->hw_idx); + return 0; free_dev: @@ -110,17 +114,19 @@ err: return rc; } -static int cam_custom_csid_remove(struct platform_device *pdev) +static void cam_custom_csid_component_unbind(struct device *dev, + struct device *master_dev, void *data) { struct cam_ife_csid_hw *csid_dev = NULL; struct cam_hw_intf *csid_hw_intf; struct cam_hw_info *csid_hw_info; + struct platform_device *pdev = to_platform_device(dev); csid_dev = (struct cam_ife_csid_hw *)platform_get_drvdata(pdev); csid_hw_intf = csid_dev->hw_intf; csid_hw_info = csid_dev->hw_info; - CAM_DBG(CAM_CUSTOM, "CSID:%d remove", + CAM_DBG(CAM_CUSTOM, "CSID:%d component unbind", csid_dev->hw_intf->hw_idx); cam_ife_csid_hw_deinit(csid_dev); @@ -129,6 +135,28 @@ static int cam_custom_csid_remove(struct platform_device *pdev) kfree(csid_dev); kfree(csid_hw_info); kfree(csid_hw_intf); +} + +const static struct component_ops cam_custom_csid_component_ops = { + .bind = cam_custom_csid_component_bind, + .unbind = cam_custom_csid_component_unbind, +}; + +static int cam_custom_csid_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CUSTOM, "Adding Custom CSID component"); + rc = component_add(&pdev->dev, &cam_custom_csid_component_ops); + if (rc) + CAM_ERR(CAM_CUSTOM, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_custom_csid_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_custom_csid_component_ops); return 0; } @@ -142,7 +170,7 @@ static const struct of_device_id cam_custom_csid_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_custom_csid_dt_match); -static struct platform_driver cam_custom_csid_driver = { +struct platform_driver cam_custom_csid_driver = { .probe = cam_custom_csid_probe, .driver = { .name = "qcom,custom-csid", diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c index 2a13e4979c15..d06b0ac2d38b 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -11,6 +11,7 @@ #include "cam_custom_sub_mod_core.h" #include "cam_custom_sub_mod_soc.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_hw_intf *cam_custom_hw_sub_mod_list [CAM_CUSTOM_SUB_MOD_MAX_INSTANCES] = {0, 0}; @@ -39,12 +40,14 @@ int cam_custom_hw_sub_mod_init(struct cam_hw_intf **custom_hw, uint32_t hw_idx) return 0; } -int cam_custom_hw_sub_mod_probe(struct platform_device *pdev) +static int cam_custom_hw_sub_mod_component_bind(struct device *dev, + struct device *master_dev, void *data) { - struct cam_hw_info *hw = NULL; - struct cam_hw_intf *hw_intf = NULL; + struct cam_hw_info *hw = NULL; + struct cam_hw_intf *hw_intf = NULL; struct cam_custom_sub_mod_core_info *core_info = NULL; - int rc = 0; + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!hw_intf) @@ -114,7 +117,7 @@ int cam_custom_hw_sub_mod_probe(struct platform_device *pdev) /* needs to be invoked when custom hw is in place */ //cam_custom_hw_sub_mod_init_hw(hw, NULL, 0); - CAM_DBG(CAM_CUSTOM, "Custom hw_idx[%d] probe successful", + CAM_DBG(CAM_CUSTOM, "HW idx:%d component bound successfully"); hw_intf->hw_idx); return rc; @@ -127,6 +130,31 @@ free_hw_intf: return rc; } +static void cam_custom_hw_sub_mod_component_unbind( + struct device *dev, struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_CUSTOM, "Unbinding component: %s", pdev->name); +} + +const static struct component_ops cam_custom_hw_sub_mod_component_ops = { + .bind = cam_custom_hw_sub_mod_component_bind, + .unbind = cam_custom_hw_sub_mod_component_unbind, +}; + +int cam_custom_hw_sub_mod_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CUSTOM, "Adding Custom HW sub module component"); + rc = component_add(&pdev->dev, &cam_custom_hw_sub_mod_component_ops); + if (rc) + CAM_ERR(CAM_CUSTOM, "failed to add component rc: %d", rc); + + return rc; +} + static const struct of_device_id cam_custom_hw_sub_mod_dt_match[] = { { .compatible = "qcom,cam_custom_hw_sub_mod", @@ -137,7 +165,7 @@ static const struct of_device_id cam_custom_hw_sub_mod_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_custom_hw_sub_mod_dt_match); -static struct platform_driver cam_custom_hw_sub_mod_driver = { +struct platform_driver cam_custom_hw_sub_mod_driver = { .probe = cam_custom_hw_sub_mod_probe, .driver = { .name = CAM_CUSTOM_SUB_MOD_NAME, diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index 1fa9e78d42a3..e4285e2bf066 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -14,6 +14,7 @@ #include "cam_fd_context.h" #include "cam_fd_hw_mgr.h" #include "cam_fd_hw_mgr_intf.h" +#include "camera_main.h" #define CAM_FD_DEV_NAME "cam-fd" @@ -87,12 +88,14 @@ static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { .close = cam_fd_dev_close, }; -static int cam_fd_dev_probe(struct platform_device *pdev) +static int cam_fd_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc; int i; struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; + struct platform_device *pdev = to_platform_device(dev); g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; @@ -131,8 +134,7 @@ static int cam_fd_dev_probe(struct platform_device *pdev) mutex_init(&g_fd_dev.lock); g_fd_dev.probe_done = true; - - CAM_DBG(CAM_FD, "Camera FD probe complete"); + CAM_DBG(CAM_FD, "Component bound successfully"); return 0; @@ -148,9 +150,11 @@ unregister_subdev: return rc; } -static int cam_fd_dev_remove(struct platform_device *pdev) +static void cam_fd_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i, rc; + struct platform_device *pdev = to_platform_device(dev); for (i = 0; i < CAM_CTX_MAX; i++) { rc = cam_fd_context_deinit(&g_fd_dev.fd_ctx[i]); @@ -169,10 +173,31 @@ static int cam_fd_dev_remove(struct platform_device *pdev) mutex_destroy(&g_fd_dev.lock); g_fd_dev.probe_done = false; +} + +const static struct component_ops cam_fd_dev_component_ops = { + .bind = cam_fd_dev_component_bind, + .unbind = cam_fd_dev_component_unbind, +}; + +static int cam_fd_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_FD, "Adding FD dev component"); + rc = component_add(&pdev->dev, &cam_fd_dev_component_ops); + if (rc) + CAM_ERR(CAM_FD, "failed to add component rc: %d", rc); return rc; } +static int cam_fd_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_fd_dev_component_ops); + return 0; +} + static const struct of_device_id cam_fd_dt_match[] = { { .compatible = "qcom,cam-fd" @@ -180,7 +205,7 @@ static const struct of_device_id cam_fd_dt_match[] = { {} }; -static struct platform_driver cam_fd_driver = { +struct platform_driver cam_fd_driver = { .probe = cam_fd_dev_probe, .remove = cam_fd_dev_remove, .driver = { diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c index 7668dd622b90..daa46c091fe7 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -17,10 +17,12 @@ #include "cam_fd_hw_v41.h" #include "cam_fd_hw_v501.h" #include "cam_fd_hw_v600.h" +#include "camera_main.h" static char fd_dev_name[8]; -static int cam_fd_hw_dev_probe(struct platform_device *pdev) +static int cam_fd_hw_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *fd_hw; struct cam_hw_intf *fd_hw_intf; @@ -31,6 +33,7 @@ static int cam_fd_hw_dev_probe(struct platform_device *pdev) uint32_t hw_idx; struct cam_fd_hw_init_args init_args; struct cam_fd_hw_deinit_args deinit_args; + struct platform_device *pdev = to_platform_device(dev); fd_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!fd_hw_intf) @@ -129,7 +132,8 @@ static int cam_fd_hw_dev_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, fd_hw_intf); - CAM_DBG(CAM_FD, "FD-%d probe successful", fd_hw_intf->hw_idx); + CAM_DBG(CAM_FD, "FD:%d component bound successfully", + fd_hw_intf->hw_idx); return rc; @@ -148,30 +152,30 @@ free_memory: return rc; } -static int cam_fd_hw_dev_remove(struct platform_device *pdev) +static void cam_fd_hw_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int rc = 0; struct cam_hw_intf *fd_hw_intf; struct cam_hw_info *fd_hw; struct cam_fd_core *fd_core; + struct platform_device *pdev = to_platform_device(dev); fd_hw_intf = platform_get_drvdata(pdev); if (!fd_hw_intf) { CAM_ERR(CAM_FD, "Invalid fd_hw_intf from pdev"); - return -EINVAL; + return; } fd_hw = fd_hw_intf->hw_priv; if (!fd_hw) { CAM_ERR(CAM_FD, "Invalid fd_hw from fd_hw_intf"); - rc = -ENODEV; goto free_fd_hw_intf; } fd_core = (struct cam_fd_core *)fd_hw->core_info; if (!fd_core) { CAM_ERR(CAM_FD, "Invalid fd_core from fd_hw"); - rc = -EINVAL; goto deinit_platform_res; } @@ -187,10 +191,31 @@ deinit_platform_res: free_fd_hw_intf: kfree(fd_hw_intf); +} + +const static struct component_ops cam_fd_hw_dev_component_ops = { + .bind = cam_fd_hw_dev_component_bind, + .unbind = cam_fd_hw_dev_component_unbind, +}; + +static int cam_fd_hw_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_FD, "Adding FD HW dev component"); + rc = component_add(&pdev->dev, &cam_fd_hw_dev_component_ops); + if (rc) + CAM_ERR(CAM_FD, "failed to add component rc: %d", rc); return rc; } +static int cam_fd_hw_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_fd_hw_dev_component_ops); + return 0; +} + static const struct of_device_id cam_fd_hw_dt_match[] = { { .compatible = "qcom,fd41", @@ -208,7 +233,7 @@ static const struct of_device_id cam_fd_hw_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_fd_hw_dt_match); -static struct platform_driver cam_fd_hw_driver = { +struct platform_driver cam_fd_hw_driver = { .probe = cam_fd_hw_dev_probe, .remove = cam_fd_hw_dev_remove, .driver = { diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 62cfc96ab999..d4c7e025afbd 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -29,6 +29,7 @@ #include "cam_icp_hw_mgr_intf.h" #include "cam_debug_util.h" #include "cam_smmu_api.h" +#include "camera_main.h" #define CAM_ICP_DEV_NAME "cam-icp" @@ -143,12 +144,14 @@ const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { .close = cam_icp_subdev_close, }; -static int cam_icp_probe(struct platform_device *pdev) +static int cam_icp_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc = 0, i = 0; struct cam_node *node; struct cam_hw_mgr_intf *hw_mgr_intf; int iommu_hdl = -1; + struct platform_device *pdev = to_platform_device(dev); if (!pdev) { CAM_ERR(CAM_ICP, "pdev is NULL"); @@ -202,7 +205,7 @@ static int cam_icp_probe(struct platform_device *pdev) g_icp_dev.open_cnt = 0; mutex_init(&g_icp_dev.icp_lock); - CAM_DBG(CAM_ICP, "ICP probe complete"); + CAM_DBG(CAM_ICP, "Component bound successfully"); return rc; @@ -217,39 +220,63 @@ probe_fail: return rc; } -static int cam_icp_remove(struct platform_device *pdev) +static void cam_icp_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i; struct v4l2_subdev *sd; struct cam_subdev *subdev; + struct platform_device *pdev = to_platform_device(dev); if (!pdev) { CAM_ERR(CAM_ICP, "pdev is NULL"); - return -ENODEV; + return; } sd = platform_get_drvdata(pdev); if (!sd) { CAM_ERR(CAM_ICP, "V4l2 subdev is NULL"); - return -ENODEV; + return; } subdev = v4l2_get_subdevdata(sd); if (!subdev) { CAM_ERR(CAM_ICP, "cam subdev is NULL"); - return -ENODEV; + return; } for (i = 0; i < CAM_ICP_CTX_MAX; i++) cam_icp_context_deinit(&g_icp_dev.ctx_icp[i]); + cam_node_deinit(g_icp_dev.node); cam_subdev_remove(&g_icp_dev.sd); mutex_destroy(&g_icp_dev.icp_lock); +} +const static struct component_ops cam_icp_component_ops = { + .bind = cam_icp_component_bind, + .unbind = cam_icp_component_unbind, +}; + +static int cam_icp_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ICP, "Adding ICP component"); + rc = component_add(&pdev->dev, &cam_icp_component_ops); + if (rc) + CAM_ERR(CAM_ICP, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_icp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_icp_component_ops); return 0; } -static struct platform_driver cam_icp_driver = { +struct platform_driver cam_icp_driver = { .probe = cam_icp_probe, .remove = cam_icp_remove, .driver = { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c index ea1a8bb91e13..ef5ec1119d33 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -17,6 +17,7 @@ #include "cam_icp_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" +#include "camera_main.h" struct a5_soc_info cam_a5_soc_info; EXPORT_SYMBOL(cam_a5_soc_info); @@ -100,7 +101,8 @@ int cam_a5_register_cpas(struct cam_hw_soc_info *soc_info, return rc; } -int cam_a5_probe(struct platform_device *pdev) +static int cam_a5_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc = 0; struct cam_hw_info *a5_dev = NULL; @@ -108,6 +110,7 @@ int cam_a5_probe(struct platform_device *pdev) const struct of_device_id *match_dev = NULL; struct cam_a5_device_core_info *core_info = NULL; struct cam_a5_device_hw_info *hw_info = NULL; + struct platform_device *pdev = to_platform_device(dev); a5_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!a5_dev_intf) @@ -177,7 +180,7 @@ int cam_a5_probe(struct platform_device *pdev) spin_lock_init(&a5_dev->hw_lock); init_completion(&a5_dev->hw_complete); - CAM_DBG(CAM_ICP, "A5%d probe successful", + CAM_DBG(CAM_ICP, "A5:%d component bound successfully", a5_dev_intf->hw_idx); return 0; @@ -191,6 +194,32 @@ a5_dev_alloc_failure: kfree(a5_dev_intf); return rc; + +} + +static void cam_a5_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_ICP, "Unbinding component: %s", pdev->name); +} + +const static struct component_ops cam_a5_component_ops = { + .bind = cam_a5_component_bind, + .unbind = cam_a5_component_unbind, +}; + +int cam_a5_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ICP, "Adding A5 component"); + rc = component_add(&pdev->dev, &cam_a5_component_ops); + if (rc) + CAM_ERR(CAM_ICP, "failed to add component rc: %d", rc); + + return rc; } static const struct of_device_id cam_a5_dt_match[] = { @@ -202,7 +231,7 @@ static const struct of_device_id cam_a5_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_a5_dt_match); -static struct platform_driver cam_a5_driver = { +struct platform_driver cam_a5_driver = { .probe = cam_a5_probe, .driver = { .name = "cam-a5", diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c index e2ebd76b502a..b70b2f187d6a 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -17,6 +17,7 @@ #include "cam_icp_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_bps_device_hw_info cam_bps_hw_info = { .hw_idx = 0, @@ -84,7 +85,8 @@ int cam_bps_register_cpas(struct cam_hw_soc_info *soc_info, return rc; } -int cam_bps_probe(struct platform_device *pdev) +static int cam_bps_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *bps_dev = NULL; struct cam_hw_intf *bps_dev_intf = NULL; @@ -92,6 +94,7 @@ int cam_bps_probe(struct platform_device *pdev) struct cam_bps_device_core_info *core_info = NULL; struct cam_bps_device_hw_info *hw_info = NULL; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); bps_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!bps_dev_intf) @@ -165,12 +168,37 @@ int cam_bps_probe(struct platform_device *pdev) mutex_init(&bps_dev->hw_mutex); spin_lock_init(&bps_dev->hw_lock); init_completion(&bps_dev->hw_complete); - CAM_DBG(CAM_ICP, "BPS%d probe successful", + CAM_DBG(CAM_ICP, "BPS:%d component bound successfully", bps_dev_intf->hw_idx); return rc; } +static void cam_bps_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_ICP, "Unbinding component: %s", pdev->name); +} + +const static struct component_ops cam_bps_component_ops = { + .bind = cam_bps_component_bind, + .unbind = cam_bps_component_unbind, +}; + +int cam_bps_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ICP, "Adding BPS component"); + rc = component_add(&pdev->dev, &cam_bps_component_ops); + if (rc) + CAM_ERR(CAM_ICP, "failed to add component rc: %d", rc); + + return rc; +} + static const struct of_device_id cam_bps_dt_match[] = { { .compatible = "qcom,cam-bps", @@ -180,7 +208,7 @@ static const struct of_device_id cam_bps_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_bps_dt_match); -static struct platform_driver cam_bps_driver = { +struct platform_driver cam_bps_driver = { .probe = cam_bps_probe, .driver = { .name = "cam-bps", diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c index c6c34f27c034..c4b75711ce40 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -17,6 +17,7 @@ #include "cam_icp_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_ipe_device_hw_info cam_ipe_hw_info[] = { { @@ -58,7 +59,8 @@ int cam_ipe_register_cpas(struct cam_hw_soc_info *soc_info, return rc; } -int cam_ipe_probe(struct platform_device *pdev) +static int cam_ipe_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *ipe_dev = NULL; struct cam_hw_intf *ipe_dev_intf = NULL; @@ -69,6 +71,7 @@ int cam_ipe_probe(struct platform_device *pdev) struct cam_cpas_query_cap query; uint32_t cam_caps; uint32_t hw_idx; + struct platform_device *pdev = to_platform_device(dev); of_property_read_u32(pdev->dev.of_node, "cell-index", &hw_idx); @@ -104,7 +107,7 @@ int cam_ipe_probe(struct platform_device *pdev) ipe_dev_intf->hw_ops.process_cmd = cam_ipe_process_cmd; ipe_dev_intf->hw_type = CAM_ICP_DEV_IPE; - CAM_DBG(CAM_ICP, "type %d index %d", + CAM_DBG(CAM_ICP, "IPE component bind type %d index %d", ipe_dev_intf->hw_type, ipe_dev_intf->hw_idx); @@ -157,12 +160,38 @@ int cam_ipe_probe(struct platform_device *pdev) spin_lock_init(&ipe_dev->hw_lock); init_completion(&ipe_dev->hw_complete); - CAM_DBG(CAM_ICP, "IPE%d probe successful", + CAM_DBG(CAM_ICP, "IPE:%d component bound successfully", ipe_dev_intf->hw_idx); return rc; } +static void cam_ipe_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_ICP, "Unbinding component: %s", pdev->name); +} + + +const static struct component_ops cam_ipe_component_ops = { + .bind = cam_ipe_component_bind, + .unbind = cam_ipe_component_unbind, +}; + +int cam_ipe_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ICP, "Adding IPE component"); + rc = component_add(&pdev->dev, &cam_ipe_component_ops); + if (rc) + CAM_ERR(CAM_ICP, "failed to add component rc: %d", rc); + + return rc; +} + static const struct of_device_id cam_ipe_dt_match[] = { { .compatible = "qcom,cam-ipe", @@ -172,7 +201,7 @@ static const struct of_device_id cam_ipe_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_ipe_dt_match); -static struct platform_driver cam_ipe_driver = { +struct platform_driver cam_ipe_driver = { .probe = cam_ipe_probe, .driver = { .name = "cam-ipe", diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 9a3729242b3b..f5bbf89d292b 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -18,6 +18,7 @@ #include "cam_node.h" #include "cam_debug_util.h" #include "cam_smmu_api.h" +#include "camera_main.h" static struct cam_isp_dev g_isp_dev; @@ -90,28 +91,8 @@ static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .open = cam_isp_subdev_open, }; -static int cam_isp_dev_remove(struct platform_device *pdev) -{ - int rc = 0; - int i; - - /* clean up resources */ - for (i = 0; i < CAM_CTX_MAX; i++) { - rc = cam_isp_context_deinit(&g_isp_dev.ctx_isp[i]); - if (rc) - CAM_ERR(CAM_ISP, "ISP context %d deinit failed", - i); - } - - rc = cam_subdev_remove(&g_isp_dev.sd); - if (rc) - CAM_ERR(CAM_ISP, "Unregister failed"); - - memset(&g_isp_dev, 0, sizeof(g_isp_dev)); - return 0; -} - -static int cam_isp_dev_probe(struct platform_device *pdev) +static int cam_isp_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc = -1; int i; @@ -119,6 +100,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev) struct cam_node *node; const char *compat_str = NULL; uint32_t isp_device_type; + struct platform_device *pdev = to_platform_device(dev); int iommu_hdl = -1; @@ -179,7 +161,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev) mutex_init(&g_isp_dev.isp_mutex); - CAM_INFO(CAM_ISP, "Camera ISP probe complete"); + CAM_INFO(CAM_ISP, "ISP HW component bound successfully"); return 0; unregister: @@ -188,8 +170,51 @@ err: return rc; } +static void cam_isp_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + int rc = 0; + int i; -static struct platform_driver isp_driver = { + /* clean up resources */ + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_isp_context_deinit(&g_isp_dev.ctx_isp[i]); + if (rc) + CAM_ERR(CAM_ISP, "ISP context %d deinit failed", + i); + } + + rc = cam_subdev_remove(&g_isp_dev.sd); + if (rc) + CAM_ERR(CAM_ISP, "Unregister failed rc: %d", rc); + + memset(&g_isp_dev, 0, sizeof(g_isp_dev)); +} + +const static struct component_ops cam_isp_dev_component_ops = { + .bind = cam_isp_dev_component_bind, + .unbind = cam_isp_dev_component_unbind, +}; + +static int cam_isp_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_isp_dev_component_ops); + return 0; +} + +static int cam_isp_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "Adding ISP dev component"); + rc = component_add(&pdev->dev, &cam_isp_dev_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); + + return rc; +} + +struct platform_driver isp_driver = { .probe = cam_isp_dev_probe, .remove = cam_isp_dev_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c index 98155a08c036..972994f53e8c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c @@ -11,6 +11,7 @@ #include "cam_ife_csid175_200.h" #include "cam_ife_csid480.h" #include "cam_ife_csid_dev.h" +#include "camera_main.h" #define CAM_CSID_DRV_NAME "csid_17x" #define CAM_CSID_VERSION_V170 0x10070000 @@ -63,7 +64,7 @@ static const struct of_device_id cam_ife_csid17x_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_ife_csid17x_dt_match); -static struct platform_driver cam_ife_csid17x_driver = { +struct platform_driver cam_ife_csid17x_driver = { .probe = cam_ife_csid_probe, .remove = cam_ife_csid_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c index eca0e43a9b5e..55c8cd4274df 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -10,15 +10,16 @@ #include "cam_ife_csid_dev.h" #include "cam_ife_csid_hw_intf.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_hw_intf *cam_ife_csid_hw_list[CAM_IFE_CSID_HW_NUM_MAX] = { 0, 0, 0, 0}; static char csid_dev_name[8]; -int cam_ife_csid_probe(struct platform_device *pdev) +static int cam_ife_csid_component_bind(struct device *dev, + struct device *master_dev, void *data) { - struct cam_hw_intf *csid_hw_intf; struct cam_hw_info *csid_hw_info; struct cam_ife_csid_hw *csid_dev = NULL; @@ -26,8 +27,9 @@ int cam_ife_csid_probe(struct platform_device *pdev) struct cam_ife_csid_hw_info *csid_hw_data = NULL; uint32_t csid_dev_idx; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); - CAM_DBG(CAM_ISP, "probe called"); + CAM_DBG(CAM_ISP, "Binding IFE CSID component"); csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL); if (!csid_hw_intf) { @@ -81,7 +83,7 @@ int cam_ife_csid_probe(struct platform_device *pdev) goto free_dev; platform_set_drvdata(pdev, csid_dev); - CAM_DBG(CAM_ISP, "CSID:%d probe successful", + CAM_DBG(CAM_ISP, "CSID:%d component bound successfully", csid_hw_intf->hw_idx); @@ -102,17 +104,19 @@ err: return rc; } -int cam_ife_csid_remove(struct platform_device *pdev) +static void cam_ife_csid_component_unbind(struct device *dev, + struct device *master_dev, void *data) { struct cam_ife_csid_hw *csid_dev = NULL; struct cam_hw_intf *csid_hw_intf; struct cam_hw_info *csid_hw_info; + struct platform_device *pdev = to_platform_device(dev); csid_dev = (struct cam_ife_csid_hw *)platform_get_drvdata(pdev); csid_hw_intf = csid_dev->hw_intf; csid_hw_info = csid_dev->hw_info; - CAM_DBG(CAM_ISP, "CSID:%d remove", + CAM_DBG(CAM_ISP, "CSID:%d component unbind", csid_dev->hw_intf->hw_idx); cam_ife_csid_hw_deinit(csid_dev); @@ -121,6 +125,28 @@ int cam_ife_csid_remove(struct platform_device *pdev) kfree(csid_dev); kfree(csid_hw_info); kfree(csid_hw_intf); +} + +const static struct component_ops cam_ife_csid_component_ops = { + .bind = cam_ife_csid_component_bind, + .unbind = cam_ife_csid_component_unbind, +}; + +int cam_ife_csid_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "Adding IFE CSID component"); + rc = component_add(&pdev->dev, &cam_ife_csid_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); + + return rc; +} + +int cam_ife_csid_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_ife_csid_component_ops); return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c index 421218a0ee06..cf0174d6b60a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c @@ -8,6 +8,7 @@ #include "cam_ife_csid_lite480.h" #include "cam_ife_csid_core.h" #include "cam_ife_csid_dev.h" +#include "camera_main.h" #define CAM_CSID_LITE_DRV_NAME "csid_lite" @@ -40,7 +41,7 @@ static const struct of_device_id cam_ife_csid_lite_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_ife_csid_lite_dt_match); -static struct platform_driver cam_ife_csid_lite_driver = { +struct platform_driver cam_ife_csid_lite_driver = { .probe = cam_ife_csid_probe, .remove = cam_ife_csid_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c index 419dc5c0cc59..420ac8ff930e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c @@ -8,6 +8,7 @@ #include "cam_tfe_csid_core.h" #include "cam_tfe_csid530.h" #include "cam_tfe_csid_dev.h" +#include "camera_main.h" #define CAM_TFE_CSID_DRV_NAME "csid_530" #define CAM_TFE_CSID_VERSION_V530 0x50030000 @@ -27,7 +28,7 @@ static const struct of_device_id cam_tfe_csid530_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_tfe_csid530_dt_match); -static struct platform_driver cam_tfe_csid530_driver = { +struct platform_driver cam_tfe_csid530_driver = { .probe = cam_tfe_csid_probe, .remove = cam_tfe_csid_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c index 377b2da2ce33..74f61bbae857 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c @@ -8,6 +8,7 @@ #include "cam_tfe_hw_intf.h" #include "cam_tfe_core.h" #include "cam_tfe_dev.h" +#include "camera_main.h" static const struct of_device_id cam_tfe_dt_match[] = { { @@ -18,7 +19,7 @@ static const struct of_device_id cam_tfe_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_tfe_dt_match); -static struct platform_driver cam_tfe_driver = { +struct platform_driver cam_tfe_driver = { .probe = cam_tfe_probe, .remove = cam_tfe_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c index 112e8c741d86..0f8c057b7bb4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c @@ -10,12 +10,14 @@ #include "cam_tfe_core.h" #include "cam_tfe_soc.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_hw_intf *cam_tfe_hw_list[CAM_TFE_HW_NUM_MAX] = {0, 0, 0}; static char tfe_dev_name[8]; -int cam_tfe_probe(struct platform_device *pdev) +static int cam_tfe_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *tfe_hw = NULL; struct cam_hw_intf *tfe_hw_intf = NULL; @@ -23,6 +25,7 @@ int cam_tfe_probe(struct platform_device *pdev) struct cam_tfe_hw_core_info *core_info = NULL; struct cam_tfe_hw_info *hw_info = NULL; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); tfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!tfe_hw_intf) { @@ -60,7 +63,7 @@ int cam_tfe_probe(struct platform_device *pdev) tfe_hw_intf->hw_ops.process_cmd = cam_tfe_process_cmd; tfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_TFE; - CAM_DBG(CAM_ISP, "type %d index %d", + CAM_DBG(CAM_ISP, "TFE component bind,type %d index %d", tfe_hw_intf->hw_type, tfe_hw_intf->hw_idx); platform_set_drvdata(pdev, tfe_hw_intf); @@ -110,8 +113,8 @@ int cam_tfe_probe(struct platform_device *pdev) cam_tfe_init_hw(tfe_hw, NULL, 0); cam_tfe_deinit_hw(tfe_hw, NULL, 0); - CAM_DBG(CAM_ISP, "TFE%d probe successful", tfe_hw_intf->hw_idx); - + CAM_DBG(CAM_ISP, "TFE:%d component bound successfully", + tfe_hw_intf->hw_idx); return rc; deinit_soc: @@ -127,17 +130,19 @@ end: return rc; } -int cam_tfe_remove(struct platform_device *pdev) +static void cam_tfe_component_unbind(struct device *dev, + struct device *master_dev, void *data) { - struct cam_hw_info *tfe_hw = NULL; - struct cam_hw_intf *tfe_hw_intf = NULL; - struct cam_tfe_hw_core_info *core_info = NULL; - int rc = 0; + struct cam_hw_info *tfe_hw = NULL; + struct cam_hw_intf *tfe_hw_intf = NULL; + struct cam_tfe_hw_core_info *core_info = NULL; + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); tfe_hw_intf = platform_get_drvdata(pdev); if (!tfe_hw_intf) { CAM_ERR(CAM_ISP, "Error! No data in pdev"); - return -EINVAL; + return; } CAM_DBG(CAM_ISP, "type %d index %d", @@ -149,14 +154,12 @@ int cam_tfe_remove(struct platform_device *pdev) tfe_hw = tfe_hw_intf->hw_priv; if (!tfe_hw) { CAM_ERR(CAM_ISP, "Error! HW data is NULL"); - rc = -ENODEV; goto free_tfe_hw_intf; } core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info; if (!core_info) { CAM_ERR(CAM_ISP, "Error! core data NULL"); - rc = -EINVAL; goto deinit_soc; } @@ -174,14 +177,35 @@ deinit_soc: mutex_destroy(&tfe_hw->hw_mutex); kfree(tfe_hw); - CAM_DBG(CAM_ISP, "TFE%d remove successful", tfe_hw_intf->hw_idx); + CAM_DBG(CAM_ISP, "TFE%d component unbound", tfe_hw_intf->hw_idx); free_tfe_hw_intf: kfree(tfe_hw_intf); +} + +const static struct component_ops cam_tfe_component_ops = { + .bind = cam_tfe_component_bind, + .unbind = cam_tfe_component_unbind, +}; + +int cam_tfe_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "Adding TFE component"); + rc = component_add(&pdev->dev, &cam_tfe_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); return rc; } +int cam_tfe_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_tfe_component_ops); + return 0; +} + int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx) { int rc = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c index 98658a7cc5bb..ebb355a29d4b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c @@ -10,15 +10,16 @@ #include "cam_top_tpg_dev.h" #include "cam_top_tpg_hw_intf.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_hw_intf *cam_top_tpg_hw_list[CAM_TOP_TPG_HW_NUM_MAX] = { 0, 0}; static char tpg_dev_name[8]; -int cam_top_tpg_probe(struct platform_device *pdev) +static int cam_top_tpg_component_bind(struct device *dev, + struct device *master_dev, void *data) { - struct cam_hw_intf *tpg_hw_intf; struct cam_hw_info *tpg_hw_info; struct cam_top_tpg_hw *tpg_dev = NULL; @@ -26,8 +27,9 @@ int cam_top_tpg_probe(struct platform_device *pdev) struct cam_top_tpg_hw_info *tpg_hw_data = NULL; uint32_t tpg_dev_idx; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); - CAM_DBG(CAM_ISP, "probe called"); + CAM_DBG(CAM_ISP, "Binding TPG component"); tpg_hw_intf = kzalloc(sizeof(*tpg_hw_intf), GFP_KERNEL); if (!tpg_hw_intf) { @@ -81,10 +83,9 @@ int cam_top_tpg_probe(struct platform_device *pdev) goto free_dev; platform_set_drvdata(pdev, tpg_dev); - CAM_DBG(CAM_ISP, "TPG:%d probe successful", + CAM_DBG(CAM_ISP, "TPG: %d component binded successfully", tpg_hw_intf->hw_idx); - if (tpg_hw_intf->hw_idx < CAM_TOP_TPG_HW_NUM_MAX) cam_top_tpg_hw_list[tpg_hw_intf->hw_idx] = tpg_hw_intf; else @@ -102,25 +103,47 @@ err: return rc; } -int cam_top_tpg_remove(struct platform_device *pdev) +static void cam_top_tpg_component_unbind(struct device *dev, + struct device *master_dev, void *data) { struct cam_top_tpg_hw *tpg_dev = NULL; struct cam_hw_intf *tpg_hw_intf; struct cam_hw_info *tpg_hw_info; + struct platform_device *pdev = to_platform_device(dev); tpg_dev = (struct cam_top_tpg_hw *)platform_get_drvdata(pdev); tpg_hw_intf = tpg_dev->hw_intf; tpg_hw_info = tpg_dev->hw_info; - CAM_DBG(CAM_ISP, "TPG:%d remove", - tpg_dev->hw_intf->hw_idx); - + CAM_DBG(CAM_ISP, "TPG:%d component unbound", tpg_dev->hw_intf->hw_idx); cam_top_tpg_hw_deinit(tpg_dev); /*release the tpg device memory */ kfree(tpg_dev); kfree(tpg_hw_info); kfree(tpg_hw_intf); +} + +const static struct component_ops cam_top_tpg_component_ops = { + .bind = cam_top_tpg_component_bind, + .unbind = cam_top_tpg_component_unbind, +}; + +int cam_top_tpg_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "Adding TPG component"); + rc = component_add(&pdev->dev, &cam_top_tpg_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); + + return rc; +} + +int cam_top_tpg_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_top_tpg_component_ops); return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c index dde4c1ac0df1..8564a30339c2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c @@ -8,6 +8,7 @@ #include "cam_top_tpg_core.h" #include "cam_top_tpg_v1.h" #include "cam_top_tpg_dev.h" +#include "camera_main.h" #define CAM_TOP_TPG_DRV_NAME "tpg_v1" #define CAM_TOP_TPG_VERSION_V1 0x10000000 @@ -29,7 +30,7 @@ static const struct of_device_id cam_top_tpg_v1_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_top_tpg_v1_dt_match); -static struct platform_driver cam_top_tpg_v1_driver = { +struct platform_driver cam_top_tpg_v1_driver = { .probe = cam_top_tpg_probe, .remove = cam_top_tpg_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c index 362d513c6a8f..3f1376311cdb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include #include #include +#include + #include "cam_vfe_dev.h" #include "cam_vfe_core.h" #include "cam_vfe_soc.h" @@ -16,7 +18,8 @@ static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX] = {0, 0, 0, 0}; static char vfe_dev_name[8]; -int cam_vfe_probe(struct platform_device *pdev) +static int cam_vfe_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *vfe_hw = NULL; struct cam_hw_intf *vfe_hw_intf = NULL; @@ -24,6 +27,7 @@ int cam_vfe_probe(struct platform_device *pdev) struct cam_vfe_hw_core_info *core_info = NULL; struct cam_vfe_hw_info *hw_info = NULL; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); vfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!vfe_hw_intf) { @@ -61,7 +65,7 @@ int cam_vfe_probe(struct platform_device *pdev) vfe_hw_intf->hw_ops.process_cmd = cam_vfe_process_cmd; vfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_VFE; - CAM_DBG(CAM_ISP, "type %d index %d", + CAM_DBG(CAM_ISP, "VFE component bind, type %d index %d", vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx); platform_set_drvdata(pdev, vfe_hw_intf); @@ -110,8 +114,8 @@ int cam_vfe_probe(struct platform_device *pdev) cam_vfe_init_hw(vfe_hw, NULL, 0); cam_vfe_deinit_hw(vfe_hw, NULL, 0); - CAM_DBG(CAM_ISP, "VFE%d probe successful", vfe_hw_intf->hw_idx); - + CAM_DBG(CAM_ISP, "VFE:%d component bound successfully", + vfe_hw_intf->hw_idx); return rc; deinit_soc: @@ -127,20 +131,22 @@ end: return rc; } -int cam_vfe_remove(struct platform_device *pdev) +static void cam_vfe_component_unbind(struct device *dev, + struct device *master_dev, void *data) { - struct cam_hw_info *vfe_hw = NULL; - struct cam_hw_intf *vfe_hw_intf = NULL; - struct cam_vfe_hw_core_info *core_info = NULL; - int rc = 0; + struct cam_hw_info *vfe_hw = NULL; + struct cam_hw_intf *vfe_hw_intf = NULL; + struct cam_vfe_hw_core_info *core_info = NULL; + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); vfe_hw_intf = platform_get_drvdata(pdev); if (!vfe_hw_intf) { CAM_ERR(CAM_ISP, "Error! No data in pdev"); - return -EINVAL; + return; } - CAM_DBG(CAM_ISP, "type %d index %d", + CAM_DBG(CAM_ISP, "VFE component unbind, type %d index %d", vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx); if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) @@ -149,14 +155,12 @@ int cam_vfe_remove(struct platform_device *pdev) vfe_hw = vfe_hw_intf->hw_priv; if (!vfe_hw) { CAM_ERR(CAM_ISP, "Error! HW data is NULL"); - rc = -ENODEV; goto free_vfe_hw_intf; } core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info; if (!core_info) { CAM_ERR(CAM_ISP, "Error! core data NULL"); - rc = -EINVAL; goto deinit_soc; } @@ -174,14 +178,35 @@ deinit_soc: mutex_destroy(&vfe_hw->hw_mutex); kfree(vfe_hw); - CAM_DBG(CAM_ISP, "VFE%d remove successful", vfe_hw_intf->hw_idx); + CAM_DBG(CAM_ISP, "VFE%d component unbound", vfe_hw_intf->hw_idx); free_vfe_hw_intf: kfree(vfe_hw_intf); +} + +const static struct component_ops cam_vfe_component_ops = { + .bind = cam_vfe_component_bind, + .unbind = cam_vfe_component_unbind, +}; + +int cam_vfe_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "Adding VFE component"); + rc = component_add(&pdev->dev, &cam_vfe_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); return rc; } +int cam_vfe_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_vfe_component_ops); + return 0; +} + int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx) { int rc = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c index e6f339e51825..461b66cd081e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -14,6 +14,7 @@ #include "cam_vfe_hw_intf.h" #include "cam_vfe_core.h" #include "cam_vfe_dev.h" +#include "camera_main.h" static const struct of_device_id cam_vfe_dt_match[] = { { @@ -56,7 +57,7 @@ static const struct of_device_id cam_vfe_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_vfe_dt_match); -static struct platform_driver cam_vfe_driver = { +struct platform_driver cam_vfe_driver = { .probe = cam_vfe_probe, .remove = cam_vfe_remove, .driver = { diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 81843d8cf117..d78d889e8844 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -15,6 +15,7 @@ #include "cam_jpeg_dev.h" #include "cam_debug_util.h" #include "cam_smmu_api.h" +#include "camera_main.h" #define CAM_JPEG_DEV_NAME "cam-jpeg" @@ -92,32 +93,15 @@ static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .open = cam_jpeg_subdev_open, }; -static int cam_jpeg_dev_remove(struct platform_device *pdev) -{ - int rc; - int i; - - for (i = 0; i < CAM_JPEG_CTX_MAX; i++) { - rc = cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]); - if (rc) - CAM_ERR(CAM_JPEG, "JPEG context %d deinit failed %d", - i, rc); - } - - rc = cam_subdev_remove(&g_jpeg_dev.sd); - if (rc) - CAM_ERR(CAM_JPEG, "Unregister failed %d", rc); - - return rc; -} - -static int cam_jpeg_dev_probe(struct platform_device *pdev) +static int cam_jpeg_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc; int i; struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; int iommu_hdl = -1; + struct platform_device *pdev = to_platform_device(dev); g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, @@ -159,7 +143,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev) mutex_init(&g_jpeg_dev.jpeg_mutex); - CAM_INFO(CAM_JPEG, "Camera JPEG probe complete"); + CAM_INFO(CAM_JPEG, "Component bound successfully"); return rc; @@ -174,7 +158,49 @@ err: return rc; } -static struct platform_driver jpeg_driver = { +static void cam_jpeg_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + int rc; + int i; + + for (i = 0; i < CAM_CTX_MAX; i++) { + rc = cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]); + if (rc) + CAM_ERR(CAM_JPEG, "JPEG context %d deinit failed %d", + i, rc); + } + + rc = cam_subdev_remove(&g_jpeg_dev.sd); + if (rc) + CAM_ERR(CAM_JPEG, "Unregister failed %d", rc); +} + +const static struct component_ops cam_jpeg_dev_component_ops = { + .bind = cam_jpeg_dev_component_bind, + .unbind = cam_jpeg_dev_component_unbind, +}; + +static int cam_jpeg_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_jpeg_dev_component_ops); + return 0; +} + +static int cam_jpeg_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_JPEG, "Adding JPEG component"); + rc = component_add(&pdev->dev, &cam_jpeg_dev_component_ops); + if (rc) + CAM_ERR(CAM_JPEG, "failed to add component rc: %d", rc); + + return rc; + +} + +struct platform_driver jpeg_driver = { .probe = cam_jpeg_dev_probe, .remove = cam_jpeg_dev_remove, .driver = { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index f717d68c8eed..0bbe7ddfba8f 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -18,6 +18,7 @@ #include "cam_jpeg_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { .reserved = 0, @@ -60,54 +61,8 @@ static int cam_jpeg_dma_unregister_cpas( return rc; } -static int cam_jpeg_dma_remove(struct platform_device *pdev) -{ - struct cam_hw_info *jpeg_dma_dev = NULL; - struct cam_hw_intf *jpeg_dma_dev_intf = NULL; - struct cam_jpeg_dma_device_core_info *core_info = NULL; - int rc; - - jpeg_dma_dev_intf = platform_get_drvdata(pdev); - if (!jpeg_dma_dev_intf) { - CAM_ERR(CAM_JPEG, "error No data in pdev"); - return -EINVAL; - } - - jpeg_dma_dev = jpeg_dma_dev_intf->hw_priv; - if (!jpeg_dma_dev) { - CAM_ERR(CAM_JPEG, "error HW data is NULL"); - rc = -ENODEV; - goto free_jpeg_hw_intf; - } - - core_info = (struct cam_jpeg_dma_device_core_info *) - jpeg_dma_dev->core_info; - if (!core_info) { - CAM_ERR(CAM_JPEG, "error core data NULL"); - goto deinit_soc; - } - - rc = cam_jpeg_dma_unregister_cpas(core_info); - if (rc) - CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); - - mutex_destroy(&core_info->core_mutex); - kfree(core_info); - -deinit_soc: - rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); - if (rc) - CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); - - mutex_destroy(&jpeg_dma_dev->hw_mutex); - kfree(jpeg_dma_dev); - -free_jpeg_hw_intf: - kfree(jpeg_dma_dev_intf); - return rc; -} - -static int cam_jpeg_dma_probe(struct platform_device *pdev) +static int cam_jpeg_dma_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *jpeg_dma_dev = NULL; struct cam_hw_intf *jpeg_dma_dev_intf = NULL; @@ -115,6 +70,7 @@ static int cam_jpeg_dma_probe(struct platform_device *pdev) struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; int rc; + struct platform_device *pdev = to_platform_device(dev); jpeg_dma_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!jpeg_dma_dev_intf) @@ -179,7 +135,8 @@ static int cam_jpeg_dma_probe(struct platform_device *pdev) spin_lock_init(&jpeg_dma_dev->hw_lock); init_completion(&jpeg_dma_dev->hw_complete); - CAM_DBG(CAM_JPEG, " hwidx %d", jpeg_dma_dev_intf->hw_idx); + CAM_DBG(CAM_JPEG, "JPEG:%d component bound successfully", + jpeg_dma_dev_intf->hw_idx); return rc; @@ -196,6 +153,78 @@ error_alloc_dev: return rc; } +static void cam_jpeg_dma_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct cam_hw_info *jpeg_dma_dev = NULL; + struct cam_hw_intf *jpeg_dma_dev_intf = NULL; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + int rc; + struct platform_device *pdev = to_platform_device(dev); + + jpeg_dma_dev_intf = platform_get_drvdata(pdev); + if (!jpeg_dma_dev_intf) { + CAM_ERR(CAM_JPEG, "error No data in pdev"); + return; + } + + jpeg_dma_dev = jpeg_dma_dev_intf->hw_priv; + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "error HW data is NULL"); + goto free_jpeg_hw_intf; + } + + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + if (!core_info) { + CAM_ERR(CAM_JPEG, "error core data NULL"); + goto deinit_soc; + } + + rc = cam_jpeg_dma_unregister_cpas(core_info); + if (rc) + CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); + + mutex_destroy(&core_info->core_mutex); + kfree(core_info); + +deinit_soc: + rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&jpeg_dma_dev->hw_mutex); + kfree(jpeg_dma_dev); + +free_jpeg_hw_intf: + kfree(jpeg_dma_dev_intf); + return; + +} + +const static struct component_ops cam_jpeg_dma_component_ops = { + .bind = cam_jpeg_dma_component_bind, + .unbind = cam_jpeg_dma_component_unbind, +}; + +static int cam_jpeg_dma_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_jpeg_dma_component_ops); + return 0; +} + +static int cam_jpeg_dma_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_JPEG, "Adding JPEG dma component"); + rc = component_add(&pdev->dev, &cam_jpeg_dma_component_ops); + if (rc) + CAM_ERR(CAM_JPEG, "failed to add component rc: %d", rc); + + return rc; +} + static const struct of_device_id cam_jpeg_dma_dt_match[] = { { .compatible = "qcom,cam_jpeg_dma", @@ -205,7 +234,7 @@ static const struct of_device_id cam_jpeg_dma_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_jpeg_dma_dt_match); -static struct platform_driver cam_jpeg_dma_driver = { +struct platform_driver cam_jpeg_dma_driver = { .probe = cam_jpeg_dma_probe, .remove = cam_jpeg_dma_remove, .driver = { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index b6ab52f377c5..130111e54119 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -19,6 +19,7 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" #include "cam_jpeg_enc_hw_info_ver_4_2_0.h" +#include "camera_main.h" static int cam_jpeg_enc_register_cpas(struct cam_hw_soc_info *soc_info, struct cam_jpeg_enc_device_core_info *core_info, @@ -57,54 +58,8 @@ static int cam_jpeg_enc_unregister_cpas( return rc; } -static int cam_jpeg_enc_remove(struct platform_device *pdev) -{ - struct cam_hw_info *jpeg_enc_dev = NULL; - struct cam_hw_intf *jpeg_enc_dev_intf = NULL; - struct cam_jpeg_enc_device_core_info *core_info = NULL; - int rc; - - jpeg_enc_dev_intf = platform_get_drvdata(pdev); - if (!jpeg_enc_dev_intf) { - CAM_ERR(CAM_JPEG, "error No data in pdev"); - return -EINVAL; - } - - jpeg_enc_dev = jpeg_enc_dev_intf->hw_priv; - if (!jpeg_enc_dev) { - CAM_ERR(CAM_JPEG, "error HW data is NULL"); - rc = -ENODEV; - goto free_jpeg_hw_intf; - } - - core_info = (struct cam_jpeg_enc_device_core_info *) - jpeg_enc_dev->core_info; - if (!core_info) { - CAM_ERR(CAM_JPEG, "error core data NULL"); - goto deinit_soc; - } - - rc = cam_jpeg_enc_unregister_cpas(core_info); - if (rc) - CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); - - mutex_destroy(&core_info->core_mutex); - kfree(core_info); - -deinit_soc: - rc = cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info); - if (rc) - CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); - - mutex_destroy(&jpeg_enc_dev->hw_mutex); - kfree(jpeg_enc_dev); - -free_jpeg_hw_intf: - kfree(jpeg_enc_dev_intf); - return rc; -} - -static int cam_jpeg_enc_probe(struct platform_device *pdev) +static int cam_jpeg_enc_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *jpeg_enc_dev = NULL; struct cam_hw_intf *jpeg_enc_dev_intf = NULL; @@ -112,6 +67,7 @@ static int cam_jpeg_enc_probe(struct platform_device *pdev) struct cam_jpeg_enc_device_core_info *core_info = NULL; struct cam_jpeg_enc_device_hw_info *hw_info = NULL; int rc; + struct platform_device *pdev = to_platform_device(dev); jpeg_enc_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!jpeg_enc_dev_intf) @@ -178,6 +134,7 @@ static int cam_jpeg_enc_probe(struct platform_device *pdev) mutex_init(&jpeg_enc_dev->hw_mutex); spin_lock_init(&jpeg_enc_dev->hw_lock); init_completion(&jpeg_enc_dev->hw_complete); + CAM_DBG(CAM_JPEG, "Encoder component bound successfully"); return rc; @@ -195,6 +152,76 @@ error_alloc_dev: return rc; } +static void cam_jpeg_enc_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct cam_hw_info *jpeg_enc_dev = NULL; + struct cam_hw_intf *jpeg_enc_dev_intf = NULL; + struct cam_jpeg_enc_device_core_info *core_info = NULL; + int rc; + struct platform_device *pdev = to_platform_device(dev); + + jpeg_enc_dev_intf = platform_get_drvdata(pdev); + if (!jpeg_enc_dev_intf) { + CAM_ERR(CAM_JPEG, "error No data in pdev"); + return; + } + + jpeg_enc_dev = jpeg_enc_dev_intf->hw_priv; + if (!jpeg_enc_dev) { + CAM_ERR(CAM_JPEG, "error HW data is NULL"); + goto free_jpeg_hw_intf; + } + + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + if (!core_info) { + CAM_ERR(CAM_JPEG, "error core data NULL"); + goto deinit_soc; + } + + rc = cam_jpeg_enc_unregister_cpas(core_info); + if (rc) + CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); + + mutex_destroy(&core_info->core_mutex); + kfree(core_info); + +deinit_soc: + rc = cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&jpeg_enc_dev->hw_mutex); + kfree(jpeg_enc_dev); + +free_jpeg_hw_intf: + kfree(jpeg_enc_dev_intf); +} + +const static struct component_ops cam_jpeg_enc_component_ops = { + .bind = cam_jpeg_enc_component_bind, + .unbind = cam_jpeg_enc_component_unbind, +}; + +static int cam_jpeg_enc_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_jpeg_enc_component_ops); + return 0; +} + +static int cam_jpeg_enc_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_JPEG, "Adding JPEG component"); + rc = component_add(&pdev->dev, &cam_jpeg_enc_component_ops); + if (rc) + CAM_ERR(CAM_JPEG, "failed to add component rc: %d", rc); + + return rc; +} + static const struct of_device_id cam_jpeg_enc_dt_match[] = { { .compatible = "qcom,cam_jpeg_enc", @@ -204,7 +231,7 @@ static const struct of_device_id cam_jpeg_enc_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_jpeg_enc_dt_match); -static struct platform_driver cam_jpeg_enc_driver = { +struct platform_driver cam_jpeg_enc_driver = { .probe = cam_jpeg_enc_probe, .remove = cam_jpeg_enc_remove, .driver = { diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 0670132fc8d5..28d11305223a 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -14,6 +14,7 @@ #include "cam_lrme_context.h" #include "cam_lrme_hw_mgr.h" #include "cam_lrme_hw_mgr_intf.h" +#include "camera_main.h" #define CAM_LRME_DEV_NAME "cam-lrme" @@ -110,12 +111,14 @@ static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { .close = cam_lrme_dev_close, }; -static int cam_lrme_dev_probe(struct platform_device *pdev) +static int cam_lrme_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc; int i; struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; + struct platform_device *pdev = to_platform_device(dev); g_lrme_dev = kzalloc(sizeof(struct cam_lrme_dev), GFP_KERNEL); if (!g_lrme_dev) { @@ -157,7 +160,7 @@ static int cam_lrme_dev_probe(struct platform_device *pdev) goto deinit_ctx; } - CAM_DBG(CAM_LRME, "%s probe complete", g_lrme_dev->sd.name); + CAM_DBG(CAM_LRME, "Component bound successfully"); return 0; @@ -175,7 +178,8 @@ free_mem: return rc; } -static int cam_lrme_dev_remove(struct platform_device *pdev) +static void cam_lrme_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i; int rc = 0; @@ -192,15 +196,36 @@ static int cam_lrme_dev_remove(struct platform_device *pdev) rc = cam_subdev_remove(&g_lrme_dev->sd); if (rc) - CAM_ERR(CAM_LRME, "Unregister failed"); + CAM_ERR(CAM_LRME, "Unregister failed rc: %d", rc); mutex_destroy(&g_lrme_dev->lock); kfree(g_lrme_dev); g_lrme_dev = NULL; +} + +const static struct component_ops cam_lrme_component_ops = { + .bind = cam_lrme_component_bind, + .unbind = cam_lrme_component_unbind, +}; + +static int cam_lrme_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Adding LRME component"); + rc = component_add(&pdev->dev, &cam_lrme_component_ops); + if (rc) + CAM_ERR(CAM_LRME, "failed to add component rc: %d", rc); return rc; } +static int cam_lrme_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_lrme_component_ops); + return 0; +} + static const struct of_device_id cam_lrme_dt_match[] = { { .compatible = "qcom,cam-lrme" @@ -208,7 +233,7 @@ static const struct of_device_id cam_lrme_dt_match[] = { {} }; -static struct platform_driver cam_lrme_driver = { +struct platform_driver cam_lrme_driver = { .probe = cam_lrme_dev_probe, .remove = cam_lrme_dev_remove, .driver = { diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c index e42591dc90d8..3c5aab0b36a7 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c @@ -20,6 +20,7 @@ #include "cam_lrme_hw_mgr.h" #include "cam_mem_mgr_api.h" #include "cam_smmu_api.h" +#include "camera_main.h" static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core, struct cam_hw_info *lrme_hw) @@ -77,7 +78,8 @@ error: return rc; } -static int cam_lrme_hw_dev_probe(struct platform_device *pdev) +static int cam_lrme_hw_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_info *lrme_hw; struct cam_hw_intf lrme_hw_intf; @@ -85,6 +87,7 @@ static int cam_lrme_hw_dev_probe(struct platform_device *pdev) const struct of_device_id *match_dev = NULL; struct cam_lrme_hw_info *hw_info; int rc, i; + struct platform_device *pdev = to_platform_device(dev); lrme_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); if (!lrme_hw) { @@ -205,7 +208,8 @@ static int cam_lrme_hw_dev_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, lrme_hw); - CAM_DBG(CAM_LRME, "LRME-%d probe successful", lrme_hw_intf.hw_idx); + CAM_DBG(CAM_LRME, "HW:%d component bound successfully", + lrme_hw_intf.hw_idx); return rc; @@ -229,22 +233,23 @@ free_memory: return rc; } -static int cam_lrme_hw_dev_remove(struct platform_device *pdev) +static void cam_lrme_hw_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int rc = 0; struct cam_hw_info *lrme_hw; struct cam_lrme_core *lrme_core; + struct platform_device *pdev = to_platform_device(dev); lrme_hw = platform_get_drvdata(pdev); if (!lrme_hw) { CAM_ERR(CAM_LRME, "Invalid lrme_hw from fd_hw_intf"); - return -ENODEV; + return; } lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; if (!lrme_core) { CAM_ERR(CAM_LRME, "Invalid lrme_core from fd_hw"); - rc = -EINVAL; goto deinit_platform_res; } @@ -263,10 +268,31 @@ deinit_platform_res: mutex_destroy(&lrme_hw->hw_mutex); kfree(lrme_hw); +} + +const static struct component_ops cam_lrme_hw_dev_component_ops = { + .bind = cam_lrme_hw_dev_component_bind, + .unbind = cam_lrme_hw_dev_component_unbind, +}; + +static int cam_lrme_hw_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Adding LRME HW component"); + rc = component_add(&pdev->dev, &cam_lrme_hw_dev_component_ops); + if (rc) + CAM_ERR(CAM_LRME, "failed to add component rc: %d", rc); return rc; } +static int cam_lrme_hw_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_lrme_hw_dev_component_ops); + return 0; +} + static const struct of_device_id cam_lrme_hw_dt_match[] = { { .compatible = "qcom,lrme", @@ -277,7 +303,7 @@ static const struct of_device_id cam_lrme_hw_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_lrme_hw_dt_match); -static struct platform_driver cam_lrme_hw_driver = { +struct platform_driver cam_lrme_hw_driver = { .probe = cam_lrme_hw_dev_probe, .remove = cam_lrme_hw_dev_remove, .driver = { diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index 18ed0518992a..3ac839a47407 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -29,6 +29,7 @@ #include "cam_hw_mgr_intf.h" #include "cam_debug_util.h" #include "cam_smmu_api.h" +#include "camera_main.h" #define OPE_DEV_NAME "cam-ope" @@ -140,14 +141,16 @@ const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { .close = cam_ope_subdev_close, }; -static int cam_ope_subdev_probe(struct platform_device *pdev) +static int cam_ope_subdev_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc = 0, i = 0; struct cam_node *node; struct cam_hw_mgr_intf *hw_mgr_intf; int iommu_hdl = -1; + struct platform_device *pdev = to_platform_device(dev); - CAM_DBG(CAM_OPE, "OPE subdev probe start"); + CAM_DBG(CAM_OPE, "Binding OPE subdev component"); if (!pdev) { CAM_ERR(CAM_OPE, "pdev is NULL"); return -EINVAL; @@ -200,7 +203,7 @@ static int cam_ope_subdev_probe(struct platform_device *pdev) g_ope_dev.open_cnt = 0; mutex_init(&g_ope_dev.ope_lock); - CAM_DBG(CAM_OPE, "OPE subdev probe complete"); + CAM_DBG(CAM_OPE, "Subdev component bound successfully"); return rc; @@ -214,35 +217,59 @@ hw_alloc_fail: return rc; } -static int cam_ope_subdev_remove(struct platform_device *pdev) +static void cam_ope_subdev_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i; struct v4l2_subdev *sd; struct cam_subdev *subdev; + struct platform_device *pdev = to_platform_device(dev); if (!pdev) { CAM_ERR(CAM_OPE, "pdev is NULL"); - return -ENODEV; + return; } sd = platform_get_drvdata(pdev); if (!sd) { CAM_ERR(CAM_OPE, "V4l2 subdev is NULL"); - return -ENODEV; + return; } subdev = v4l2_get_subdevdata(sd); if (!subdev) { CAM_ERR(CAM_OPE, "cam subdev is NULL"); - return -ENODEV; + return; } for (i = 0; i < OPE_CTX_MAX; i++) cam_ope_context_deinit(&g_ope_dev.ctx_ope[i]); + cam_node_deinit(g_ope_dev.node); cam_subdev_remove(&g_ope_dev.sd); mutex_destroy(&g_ope_dev.ope_lock); +} +const static struct component_ops cam_ope_subdev_component_ops = { + .bind = cam_ope_subdev_component_bind, + .unbind = cam_ope_subdev_component_unbind, +}; + +static int cam_ope_subdev_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_OPE, "Adding OPE subdev component"); + rc = component_add(&pdev->dev, &cam_ope_subdev_component_ops); + if (rc) + CAM_ERR(CAM_OPE, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_ope_subdev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_ope_subdev_component_ops); return 0; } @@ -252,7 +279,7 @@ static const struct of_device_id cam_ope_dt_match[] = { }; -static struct platform_driver cam_ope_driver = { +struct platform_driver cam_ope_subdev_driver = { .probe = cam_ope_subdev_probe, .remove = cam_ope_subdev_remove, .driver = { @@ -264,12 +291,12 @@ static struct platform_driver cam_ope_driver = { int cam_ope_subdev_init_module(void) { - return platform_driver_register(&cam_ope_driver); + return platform_driver_register(&cam_ope_subdev_driver); } void cam_ope_subdev_exit_module(void) { - platform_driver_unregister(&cam_ope_driver); + platform_driver_unregister(&cam_ope_subdev_driver); } MODULE_DESCRIPTION("MSM OPE driver"); diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index 6435777a4b3e..fd6c0aaf54da 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -19,6 +19,7 @@ #include "cam_debug_util.h" #include "ope_hw_100.h" #include "ope_dev_intf.h" +#include "camera_main.h" static struct cam_ope_device_hw_info ope_hw_info; static struct ope_dev_soc ope_soc_info; @@ -105,7 +106,8 @@ int cam_ope_register_cpas(struct cam_hw_soc_info *soc_info, return rc; } -int cam_ope_probe(struct platform_device *pdev) +static int cam_ope_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_intf *ope_dev_intf = NULL; struct cam_hw_info *ope_dev = NULL; @@ -115,6 +117,7 @@ int cam_ope_probe(struct platform_device *pdev) uint32_t hw_idx; struct cam_ope_dev_probe ope_probe; struct cam_ope_cpas_vote cpas_vote; + struct platform_device *pdev = to_platform_device(dev); of_property_read_u32(pdev->dev.of_node, "cell-index", &hw_idx); @@ -225,7 +228,7 @@ int cam_ope_probe(struct platform_device *pdev) spin_lock_init(&ope_dev->hw_lock); init_completion(&ope_dev->hw_complete); - CAM_DBG(CAM_OPE, "OPE%d probe successful", + CAM_DBG(CAM_OPE, "OPE:%d component bound successfully" ope_dev_intf->hw_idx); return rc; @@ -242,6 +245,32 @@ ope_dev_alloc_failed: return rc; } +static void cam_ope_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_OPE, "Unbinding component: %s", pdev->name); +} + + +const static struct component_ops cam_ope_component_ops = { + .bind = cam_ope_component_bind, + .unbind = cam_ope_component_unbind, +}; + +int cam_ope_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_OPE, "Adding OPE component"); + rc = component_add(&pdev->dev, &cam_vfe_component_ops); + if (rc) + CAM_ERR(CAM_OPE, "failed to add component rc: %d", rc); + + return rc; +} + static const struct of_device_id cam_ope_dt_match[] = { { .compatible = "qcom,ope", @@ -251,7 +280,7 @@ static const struct of_device_id cam_ope_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_ope_dt_match); -static struct platform_driver cam_ope_driver = { +struct platform_driver cam_ope_driver = { .probe = cam_ope_probe, .driver = { .name = "ope", diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 4c4bb5afacae..6a49809af520 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -24,6 +24,7 @@ #include "cam_mem_mgr.h" #include "cam_debug_util.h" #include "cam_common_util.h" +#include "camera_main.h" #define CAM_REQ_MGR_EVENT_MAX 30 @@ -689,28 +690,16 @@ int cam_unregister_subdev(struct cam_subdev *csd) } EXPORT_SYMBOL(cam_unregister_subdev); -static int cam_req_mgr_remove(struct platform_device *pdev) +static int cam_req_mgr_component_master_bind(struct device *dev) { - cam_req_mgr_core_device_deinit(); - cam_req_mgr_util_deinit(); - cam_media_device_cleanup(); - cam_video_device_cleanup(); - cam_v4l2_device_cleanup(); - mutex_destroy(&g_dev.dev_lock); - g_dev.state = false; + int rc = 0; - return 0; -} - -static int cam_req_mgr_probe(struct platform_device *pdev) -{ - int rc; - - rc = cam_v4l2_device_setup(&pdev->dev); + CAM_DBG(CAM_CRM, "Master bind called"); + rc = cam_v4l2_device_setup(dev); if (rc) return rc; - rc = cam_media_device_setup(&pdev->dev); + rc = cam_media_device_setup(dev); if (rc) goto media_setup_fail; @@ -749,6 +738,16 @@ static int cam_req_mgr_probe(struct platform_device *pdev) } g_dev.state = true; + + CAM_DBG(CAM_CRM, "Binding all slave components"); + rc = component_bind_all(dev, NULL); + if (rc) { + CAM_ERR(CAM_CRM, + "Error in binding all components rc: %d, Camera initialization failed!", + rc); + goto req_mgr_core_fail; + } + return rc; req_mgr_core_fail: @@ -764,13 +763,67 @@ media_setup_fail: return rc; } +static void cam_req_mgr_component_master_unbind(struct device *dev) +{ + /* Unbinding all slave components first */ + component_unbind_all(dev, NULL); + + /* Now proceed with unbinding master */ + cam_req_mgr_core_device_deinit(); + cam_req_mgr_util_deinit(); + cam_media_device_cleanup(); + cam_video_device_cleanup(); + cam_v4l2_device_cleanup(); + mutex_destroy(&g_dev.dev_lock); + g_dev.state = false; +} + +static const struct component_master_ops cam_req_mgr_component_master_ops = { + .bind = cam_req_mgr_component_master_bind, + .unbind = cam_req_mgr_component_master_unbind, +}; + +static int cam_req_mgr_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &cam_req_mgr_component_master_ops); + return 0; +} + +static int cam_req_mgr_probe(struct platform_device *pdev) +{ + int rc = 0; + struct component_match *match_list = NULL; + struct device *dev = &pdev->dev; + + rc = camera_component_match_add_drivers(dev, &match_list); + if (rc) { + CAM_ERR(CAM_CRM, + "Unable to match components, probe failed rc: %d", + rc); + goto end; + } + + /* Supply match_list to master for handing over control */ + rc = component_master_add_with_match(dev, + &cam_req_mgr_component_master_ops, match_list); + if (rc) { + CAM_ERR(CAM_CRM, + "Unable to add master, probe failed rc: %d", + rc); + goto end; + } + +end: + return rc; +} + static const struct of_device_id cam_req_mgr_dt_match[] = { {.compatible = "qcom,cam-req-mgr"}, {} }; MODULE_DEVICE_TABLE(of, cam_req_mgr_dt_match); -static struct platform_driver cam_req_mgr_driver = { +struct platform_driver cam_req_mgr_driver = { .probe = cam_req_mgr_probe, .remove = cam_req_mgr_remove, .driver = { diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 92c9e6591012..e0df270b80cb 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_actuator_dev.h" @@ -8,6 +8,7 @@ #include "cam_actuator_soc.h" #include "cam_actuator_core.h" #include "cam_trace.h" +#include "camera_main.h" static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -222,86 +223,14 @@ free_ctrl: return rc; } -static int32_t cam_actuator_platform_remove(struct platform_device *pdev) +static int cam_actuator_component_bind(struct device *dev, + struct device *master_dev, void *data) { - int32_t rc = 0; - struct cam_actuator_ctrl_t *a_ctrl; - struct cam_actuator_soc_private *soc_private; - struct cam_sensor_power_ctrl_t *power_info; - - a_ctrl = platform_get_drvdata(pdev); - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL"); - 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(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; -} - -static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client) -{ - struct cam_actuator_ctrl_t *a_ctrl = - i2c_get_clientdata(client); - struct cam_actuator_soc_private *soc_private; - struct cam_sensor_power_ctrl_t *power_info; - - /* Handle I2C Devices */ - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL"); - 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; - - /*Free Allocated Mem */ - kfree(a_ctrl->i2c_data.per_frame); - a_ctrl->i2c_data.per_frame = NULL; - a_ctrl->soc_info.soc_private = NULL; - v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL); - kfree(a_ctrl); - - return 0; -} - -static const struct of_device_id cam_actuator_driver_dt_match[] = { - {.compatible = "qcom,actuator"}, - {} -}; - -static int32_t cam_actuator_driver_platform_probe( - struct platform_device *pdev) -{ - int32_t rc = 0; - int32_t i = 0; - struct cam_actuator_ctrl_t *a_ctrl = NULL; - struct cam_actuator_soc_private *soc_private = NULL; + int32_t rc = 0; + int32_t i = 0; + struct cam_actuator_ctrl_t *a_ctrl = NULL; + struct cam_actuator_soc_private *soc_private = NULL; + struct platform_device *pdev = to_platform_device(dev); /* Create actuator control structure */ a_ctrl = devm_kzalloc(&pdev->dev, @@ -372,6 +301,7 @@ static int32_t cam_actuator_driver_platform_probe( platform_set_drvdata(pdev, a_ctrl); a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; + CAM_DBG(CAM_ACTUATOR, "Component bound successfully"); return rc; @@ -386,9 +316,106 @@ free_ctrl: return rc; } +static void cam_actuator_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct cam_actuator_ctrl_t *a_ctrl; + struct cam_actuator_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + struct platform_device *pdev = to_platform_device(dev); + + a_ctrl = platform_get_drvdata(pdev); + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL"); + return; + } + + 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(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); + CAM_INFO(CAM_ACTUATOR, "Actuator component unbinded"); +} + +const static struct component_ops cam_actuator_component_ops = { + .bind = cam_actuator_component_bind, + .unbind = cam_actuator_component_unbind, +}; + +static int32_t cam_actuator_platform_remove( + struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_actuator_component_ops); + return 0; +} + +static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client) +{ + struct cam_actuator_ctrl_t *a_ctrl = + i2c_get_clientdata(client); + struct cam_actuator_soc_private *soc_private; + struct cam_sensor_power_ctrl_t *power_info; + + /* Handle I2C Devices */ + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL"); + 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; + + /*Free Allocated Mem */ + kfree(a_ctrl->i2c_data.per_frame); + a_ctrl->i2c_data.per_frame = NULL; + a_ctrl->soc_info.soc_private = NULL; + v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL); + kfree(a_ctrl); + + return 0; +} + +static const struct of_device_id cam_actuator_driver_dt_match[] = { + {.compatible = "qcom,actuator"}, + {} +}; + +static int32_t cam_actuator_driver_platform_probe( + struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ACTUATOR, "Adding sensor actuator component"); + rc = component_add(&pdev->dev, &cam_actuator_component_ops); + if (rc) + CAM_ERR(CAM_ICP, "failed to add component rc: %d", rc); + + return rc; +} + MODULE_DEVICE_TABLE(of, cam_actuator_driver_dt_match); -static struct platform_driver cam_actuator_platform_driver = { +struct platform_driver cam_actuator_platform_driver = { .probe = cam_actuator_driver_platform_probe, .driver = { .name = "qcom,actuator", diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 48552c82239b..3459b3a5d53c 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" #include "cam_req_mgr_dev.h" #include "cam_cci_soc.h" #include "cam_cci_core.h" +#include "camera_main.h" #define CCI_MAX_DELAY 1000000 @@ -340,12 +341,14 @@ static const struct v4l2_subdev_ops cci_subdev_ops = { static const struct v4l2_subdev_internal_ops cci_subdev_intern_ops; -static int cam_cci_platform_probe(struct platform_device *pdev) +static int cam_cci_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_cpas_register_params cpas_parms; struct cci_device *new_cci_dev; struct cam_hw_soc_info *soc_info = NULL; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); new_cci_dev = kzalloc(sizeof(struct cci_device), GFP_KERNEL); @@ -409,18 +412,22 @@ static int cam_cci_platform_probe(struct platform_device *pdev) CAM_ERR(CAM_CCI, "CPAS registration failed"); goto cci_no_resource; } + CAM_DBG(CAM_CCI, "CPAS registration successful handle=%d", cpas_parms.client_handle); new_cci_dev->cpas_handle = cpas_parms.client_handle; - + CAM_DBG(CAM_CCI, "Component bound successfully"); return rc; cci_no_resource: kfree(new_cci_dev); return rc; } -static int cam_cci_device_remove(struct platform_device *pdev) +static void cam_cci_component_unbind(struct device *dev, + struct device *master_dev, void *data) { + struct platform_device *pdev = to_platform_device(dev); + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); struct cci_device *cci_dev = v4l2_get_subdevdata(subdev); @@ -428,6 +435,28 @@ static int cam_cci_device_remove(struct platform_device *pdev) cam_cpas_unregister_client(cci_dev->cpas_handle); cam_cci_soc_remove(pdev, cci_dev); devm_kfree(&pdev->dev, cci_dev); +} + +const static struct component_ops cam_cci_component_ops = { + .bind = cam_cci_component_bind, + .unbind = cam_cci_component_unbind, +}; + +static int cam_cci_platform_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CCI, "Adding CCI component"); + rc = component_add(&pdev->dev, &cam_cci_component_ops); + if (rc) + CAM_ERR(CAM_CCI, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_cci_device_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_cci_component_ops); return 0; } @@ -438,7 +467,7 @@ static const struct of_device_id cam_cci_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_cci_dt_match); -static struct platform_driver cci_driver = { +struct platform_driver cci_driver = { .probe = cam_cci_platform_probe, .remove = cam_cci_device_remove, .driver = { diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index b21287cd5028..61869c384957 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -375,10 +375,6 @@ int cam_cci_parse_dt_info(struct platform_device *pdev, cam_cci_init_cci_params(new_cci_dev); cam_cci_init_clk_params(new_cci_dev); - rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - if (rc) - CAM_ERR(CAM_CCI, "failed to add child nodes, rc=%d", rc); - for (i = 0; i < MASTER_MAX; i++) { new_cci_dev->write_wq[i] = create_singlethread_workqueue( "cam_cci_wq"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 0e15bcf9d2a5..2a6abfc30665 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_csiphy_dev.h" @@ -8,6 +8,7 @@ #include "cam_csiphy_soc.h" #include "cam_csiphy_core.h" #include +#include "camera_main.h" static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -104,11 +105,13 @@ static const struct v4l2_subdev_internal_ops csiphy_subdev_intern_ops = { .close = cam_csiphy_subdev_close, }; -static int32_t cam_csiphy_platform_probe(struct platform_device *pdev) +static int cam_csiphy_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_cpas_register_params cpas_parms; struct csiphy_device *new_csiphy_dev; - int32_t rc = 0; + int32_t rc = 0; + struct platform_device *pdev = to_platform_device(dev); new_csiphy_dev = devm_kzalloc(&pdev->dev, sizeof(struct csiphy_device), GFP_KERNEL); @@ -183,10 +186,12 @@ static int32_t cam_csiphy_platform_probe(struct platform_device *pdev) CAM_ERR(CAM_CSIPHY, "CPAS registration failed rc: %d", rc); goto csiphy_no_resource; } + CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d", cpas_parms.client_handle); new_csiphy_dev->cpas_handle = cpas_parms.client_handle; - + CAM_DBG(CAM_CSIPHY, "%s component bound successfully", + pdev->name); return rc; csiphy_no_resource: mutex_destroy(&new_csiphy_dev->mutex); @@ -195,15 +200,15 @@ csiphy_no_resource: return rc; } - -static int32_t cam_csiphy_device_remove(struct platform_device *pdev) +static void cam_csiphy_component_unbind(struct device *dev, + struct device *master_dev, void *data) { - struct v4l2_subdev *subdev = - platform_get_drvdata(pdev); - struct csiphy_device *csiphy_dev = - v4l2_get_subdevdata(subdev); + struct platform_device *pdev = to_platform_device(dev); - CAM_INFO(CAM_CSIPHY, "device remove invoked"); + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(subdev); + + CAM_INFO(CAM_CSIPHY, "Unbind CSIPHY component"); cam_cpas_unregister_client(csiphy_dev->cpas_handle); cam_csiphy_soc_release(csiphy_dev); mutex_lock(&csiphy_dev->mutex); @@ -215,7 +220,29 @@ static int32_t cam_csiphy_device_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&(csiphy_dev->v4l2_dev_str.sd), NULL); devm_kfree(&pdev->dev, csiphy_dev); +} +const static struct component_ops cam_csiphy_component_ops = { + .bind = cam_csiphy_component_bind, + .unbind = cam_csiphy_component_unbind, +}; + +static int32_t cam_csiphy_platform_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_CSIPHY, "Adding CSIPHY component"); + rc = component_add(&pdev->dev, &cam_csiphy_component_ops); + if (rc) + CAM_ERR(CAM_CSIPHY, "failed to add component rc: %d", rc); + + return rc; +} + + +static int32_t cam_csiphy_device_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_csiphy_component_ops); return 0; } @@ -226,7 +253,7 @@ static const struct of_device_id cam_csiphy_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_csiphy_dt_match); -static struct platform_driver csiphy_driver = { +struct platform_driver csiphy_driver = { .probe = cam_csiphy_platform_probe, .remove = cam_csiphy_device_remove, .driver = { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 5fedbed5aa12..a0d4b5a45f30 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_eeprom_dev.h" @@ -8,6 +8,7 @@ #include "cam_eeprom_soc.h" #include "cam_eeprom_core.h" #include "cam_debug_util.h" +#include "camera_main.h" static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -409,12 +410,13 @@ static int cam_eeprom_spi_driver_remove(struct spi_device *sdev) return 0; } -static int32_t cam_eeprom_platform_driver_probe( - struct platform_device *pdev) +static int cam_eeprom_component_bind(struct device *dev, + struct device *master_dev, void *data) { int32_t rc = 0; struct cam_eeprom_ctrl_t *e_ctrl = NULL; struct cam_eeprom_soc_private *soc_private = NULL; + struct platform_device *pdev = to_platform_device(dev); e_ctrl = kzalloc(sizeof(struct cam_eeprom_ctrl_t), GFP_KERNEL); if (!e_ctrl) @@ -469,6 +471,7 @@ static int32_t cam_eeprom_platform_driver_probe( e_ctrl->bridge_intf.ops.apply_req = NULL; platform_set_drvdata(pdev, e_ctrl); e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT; + CAM_DBG(CAM_EEPROM, "Component bound successfully"); return rc; free_soc: @@ -481,16 +484,18 @@ free_e_ctrl: return rc; } -static int cam_eeprom_platform_driver_remove(struct platform_device *pdev) +static void cam_eeprom_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i; struct cam_eeprom_ctrl_t *e_ctrl; struct cam_hw_soc_info *soc_info; + struct platform_device *pdev = to_platform_device(dev); e_ctrl = platform_get_drvdata(pdev); if (!e_ctrl) { CAM_ERR(CAM_EEPROM, "eeprom device is NULL"); - return -EINVAL; + return; } CAM_INFO(CAM_EEPROM, "Platform driver remove invoked"); @@ -509,7 +514,29 @@ static int cam_eeprom_platform_driver_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL); kfree(e_ctrl); +} +const static struct component_ops cam_eeprom_component_ops = { + .bind = cam_eeprom_component_bind, + .unbind = cam_eeprom_component_unbind, +}; + +static int32_t cam_eeprom_platform_driver_probe( + struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_EEPROM, "Adding EEPROM Sensor component"); + rc = component_add(&pdev->dev, &cam_eeprom_component_ops); + if (rc) + CAM_ERR(CAM_EEPROM, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_eeprom_platform_driver_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_eeprom_component_ops); return 0; } @@ -521,7 +548,7 @@ static const struct of_device_id cam_eeprom_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_eeprom_dt_match); -static struct platform_driver cam_eeprom_platform_driver = { +struct platform_driver cam_eeprom_platform_driver = { .driver = { .name = "qcom,eeprom", .owner = THIS_MODULE, diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 868d30a85900..6b872be656af 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -8,6 +8,7 @@ #include "cam_flash_soc.h" #include "cam_flash_core.h" #include "cam_common_util.h" +#include "camera_main.h" static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, void *arg, struct cam_flash_private_soc *soc_private) @@ -302,28 +303,6 @@ static long cam_flash_subdev_do_ioctl(struct v4l2_subdev *sd, } #endif -static int cam_flash_platform_remove(struct platform_device *pdev) -{ - struct cam_flash_ctrl *fctrl; - - fctrl = platform_get_drvdata(pdev); - if (!fctrl) { - CAM_ERR(CAM_FLASH, "Flash device is NULL"); - return 0; - } - - 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; -} - static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) { int32_t rc = 0; @@ -397,13 +376,15 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) return rc; } -static int32_t cam_flash_platform_probe(struct platform_device *pdev) +static int cam_flash_component_bind(struct device *dev, + struct device *master_dev, void *data) { int32_t rc = 0, i = 0; struct cam_flash_ctrl *fctrl = NULL; struct device_node *of_parent = NULL; + struct platform_device *pdev = to_platform_device(dev); - CAM_DBG(CAM_FLASH, "Enter"); + CAM_DBG(CAM_FLASH, "Binding flash component"); if (!pdev->dev.of_node) { CAM_ERR(CAM_FLASH, "of_node NULL"); return -EINVAL; @@ -503,7 +484,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) mutex_init(&(fctrl->flash_mutex)); fctrl->flash_state = CAM_FLASH_STATE_INIT; - CAM_DBG(CAM_FLASH, "Probe success"); + CAM_DBG(CAM_FLASH, "Component bound successfully"); return rc; free_cci_resource: @@ -520,6 +501,51 @@ free_resource: return rc; } +static void cam_flash_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct cam_flash_ctrl *fctrl; + struct platform_device *pdev = to_platform_device(dev); + + fctrl = platform_get_drvdata(pdev); + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash device is NULL"); + return; + } + + 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); + CAM_INFO(CAM_FLASH, "Flash Sensor component unbind"); +} + +const static struct component_ops cam_flash_component_ops = { + .bind = cam_flash_component_bind, + .unbind = cam_flash_component_unbind, +}; + +static int cam_flash_platform_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_flash_component_ops); + return 0; +} + +static int32_t cam_flash_platform_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_FLASH, "Adding Flash Sensor component"); + rc = component_add(&pdev->dev, &cam_flash_component_ops); + if (rc) + CAM_ERR(CAM_FLASH, "failed to add component rc: %d", rc); + + return rc; +} + static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -601,7 +627,7 @@ free_ctrl: MODULE_DEVICE_TABLE(of, cam_flash_dt_match); -static struct platform_driver cam_flash_platform_driver = { +struct platform_driver cam_flash_platform_driver = { .probe = cam_flash_platform_probe, .remove = cam_flash_platform_remove, .driver = { diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 667cbb44eef8..8797252ab7b6 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_ois_dev.h" @@ -8,6 +8,7 @@ #include "cam_ois_soc.h" #include "cam_ois_core.h" #include "cam_debug_util.h" +#include "camera_main.h" static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -244,12 +245,13 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client) return 0; } -static int32_t cam_ois_platform_driver_probe( - struct platform_device *pdev) +static int cam_ois_component_bind(struct device *dev, + struct device *master_dev, void *data) { int32_t rc = 0; struct cam_ois_ctrl_t *o_ctrl = NULL; struct cam_ois_soc_private *soc_private = NULL; + struct platform_device *pdev = to_platform_device(dev); o_ctrl = kzalloc(sizeof(struct cam_ois_ctrl_t), GFP_KERNEL); if (!o_ctrl) @@ -300,7 +302,7 @@ static int32_t cam_ois_platform_driver_probe( platform_set_drvdata(pdev, o_ctrl); o_ctrl->cam_ois_state = CAM_OIS_INIT; - + CAM_DBG(CAM_OIS, "Component bound successfully"); return rc; unreg_subdev: cam_unregister_subdev(&(o_ctrl->v4l2_dev_str)); @@ -313,18 +315,20 @@ free_o_ctrl: return rc; } -static int cam_ois_platform_driver_remove(struct platform_device *pdev) +static void cam_ois_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i; struct cam_ois_ctrl_t *o_ctrl; struct cam_ois_soc_private *soc_private; struct cam_sensor_power_ctrl_t *power_info; struct cam_hw_soc_info *soc_info; + struct platform_device *pdev = to_platform_device(dev); o_ctrl = platform_get_drvdata(pdev); if (!o_ctrl) { CAM_ERR(CAM_OIS, "ois device is NULL"); - return -EINVAL; + return; } CAM_INFO(CAM_OIS, "platform driver remove invoked"); @@ -346,7 +350,29 @@ static int cam_ois_platform_driver_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL); kfree(o_ctrl); +} +const static struct component_ops cam_ois_component_ops = { + .bind = cam_ois_component_bind, + .unbind = cam_ois_component_unbind, +}; + +static int32_t cam_ois_platform_driver_probe( + struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_OIS, "Adding OIS Sensor component"); + rc = component_add(&pdev->dev, &cam_ois_component_ops); + if (rc) + CAM_ERR(CAM_OIS, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_ois_platform_driver_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_ois_component_ops); return 0; } @@ -358,7 +384,7 @@ static const struct of_device_id cam_ois_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_ois_dt_match); -static struct platform_driver cam_ois_platform_driver = { +struct platform_driver cam_ois_platform_driver = { .driver = { .name = "qcom,ois", .owner = THIS_MODULE, diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 009043acbc29..3a944abff778 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -12,6 +12,7 @@ #include "cam_debug_util.h" #include "cam_res_mgr_api.h" #include "cam_res_mgr_private.h" +#include "camera_main.h" static struct cam_res_mgr *cam_res; @@ -664,9 +665,11 @@ static int cam_res_mgr_parse_dt(struct device *dev) return rc; } -static int cam_res_mgr_probe(struct platform_device *pdev) +static int cam_res_mgr_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc = 0; + struct platform_device *pdev = to_platform_device(dev); cam_res = kzalloc(sizeof(*cam_res), GFP_KERNEL); if (!cam_res) @@ -692,17 +695,40 @@ static int cam_res_mgr_probe(struct platform_device *pdev) INIT_LIST_HEAD(&cam_res->gpio_res_list); INIT_LIST_HEAD(&cam_res->flash_res_list); + CAM_DBG(CAM_RES, "Component bound successfully"); return 0; } -static int cam_res_mgr_remove(struct platform_device *pdev) +static void cam_res_mgr_component_unbind(struct device *dev, + struct device *master_dev, void *data) { if (cam_res) { cam_res_mgr_free_res(); kfree(cam_res); cam_res = NULL; } +} +const static struct component_ops cam_res_mgr_component_ops = { + .bind = cam_res_mgr_component_bind, + .unbind = cam_res_mgr_component_unbind, +}; + +static int cam_res_mgr_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_RES, "Adding Res mgr component"); + rc = component_add(&pdev->dev, &cam_res_mgr_component_ops); + if (rc) + CAM_ERR(CAM_RES, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_res_mgr_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_res_mgr_component_ops); return 0; } @@ -712,7 +738,7 @@ static const struct of_device_id cam_res_mgr_dt_match[] = { }; MODULE_DEVICE_TABLE(of, cam_res_mgr_dt_match); -static struct platform_driver cam_res_mgr_driver = { +struct platform_driver cam_res_mgr_driver = { .probe = cam_res_mgr_probe, .remove = cam_res_mgr_remove, .driver = { diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 848234196e3f..564cae097934 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_sensor_dev.h" #include "cam_req_mgr_dev.h" #include "cam_sensor_soc.h" #include "cam_sensor_core.h" +#include "camera_main.h" static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -201,73 +202,13 @@ free_s_ctrl: return rc; } -static int cam_sensor_platform_remove(struct platform_device *pdev) -{ - int i; - struct cam_sensor_ctrl_t *s_ctrl; - struct cam_hw_soc_info *soc_info; - - s_ctrl = platform_get_drvdata(pdev); - if (!s_ctrl) { - CAM_ERR(CAM_SENSOR, "sensor device is NULL"); - 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; -} - -static int cam_sensor_driver_i2c_remove(struct i2c_client *client) -{ - int i; - struct cam_sensor_ctrl_t *s_ctrl = i2c_get_clientdata(client); - struct cam_hw_soc_info *soc_info; - - if (!s_ctrl) { - CAM_ERR(CAM_SENSOR, "sensor device is NULL"); - 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; -} - -static const struct of_device_id cam_sensor_driver_dt_match[] = { - {.compatible = "qcom,cam-sensor"}, - {} -}; - -static int32_t cam_sensor_driver_platform_probe( - struct platform_device *pdev) +static int cam_sensor_component_bind(struct device *dev, + struct device *master_dev, void *data) { int32_t rc = 0, i = 0; struct cam_sensor_ctrl_t *s_ctrl = NULL; struct cam_hw_soc_info *soc_info = NULL; + struct platform_device *pdev = to_platform_device(dev); /* Create sensor control structure */ s_ctrl = devm_kzalloc(&pdev->dev, @@ -330,6 +271,7 @@ static int32_t cam_sensor_driver_platform_probe( s_ctrl->sensordata->power_info.dev = &pdev->dev; platform_set_drvdata(pdev, s_ctrl); s_ctrl->sensor_state = CAM_SENSOR_INIT; + CAM_DBG(CAM_SENSOR, "Component bound successfully"); return rc; unreg_subdev: @@ -339,9 +281,94 @@ free_s_ctrl: return rc; } +static void cam_sensor_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + int i; + struct cam_sensor_ctrl_t *s_ctrl; + struct cam_hw_soc_info *soc_info; + struct platform_device *pdev = to_platform_device(dev); + + s_ctrl = platform_get_drvdata(pdev); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "sensor device is NULL"); + return; + } + + 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); +} + +const static struct component_ops cam_sensor_component_ops = { + .bind = cam_sensor_component_bind, + .unbind = cam_sensor_component_unbind, +}; + +static int cam_sensor_platform_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_sensor_component_ops); + return 0; +} + +static int cam_sensor_driver_i2c_remove(struct i2c_client *client) +{ + int i; + struct cam_sensor_ctrl_t *s_ctrl = i2c_get_clientdata(client); + struct cam_hw_soc_info *soc_info; + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "sensor device is NULL"); + return 0; + } + + CAM_DBG(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; +} + +static const struct of_device_id cam_sensor_driver_dt_match[] = { + {.compatible = "qcom,cam-sensor"}, + {} +}; + +static int32_t cam_sensor_driver_platform_probe( + struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_SENSOR, "Adding Sensor component"); + rc = component_add(&pdev->dev, &cam_sensor_component_ops); + if (rc) + CAM_ERR(CAM_SENSOR, "failed to add component rc: %d", rc); + + return rc; +} + MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match); -static struct platform_driver cam_sensor_platform_driver = { +struct platform_driver cam_sensor_platform_driver = { .probe = cam_sensor_driver_platform_probe, .driver = { .name = "qcom,camera", diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 8a21e0b2ae7d..336c5c039ae0 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -22,6 +22,7 @@ #include "cam_compat.h" #include "cam_smmu_api.h" #include "cam_debug_util.h" +#include "camera_main.h" #define SHARED_MEM_POOL_GRANULARITY 16 @@ -3639,62 +3640,106 @@ err: return -ENOMEM; } -static int cam_smmu_probe(struct platform_device *pdev) +static int cam_smmu_fw_dev_component_bind(struct device *dev, + struct device *master_dev, void *data) { - int rc = 0; - struct device *dev = &pdev->dev; + struct platform_device *pdev = to_platform_device(dev); - dev->dma_parms = NULL; - if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu")) { - rc = cam_alloc_smmu_context_banks(dev); - if (rc < 0) { - CAM_ERR(CAM_SMMU, "Error: allocating context banks"); - return -ENOMEM; - } - } - if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu-cb")) { - rc = cam_populate_smmu_context_banks(dev, CAM_ARM_SMMU); - if (rc < 0) { - CAM_ERR(CAM_SMMU, "Error: populating context banks"); - cam_smmu_release_cb(pdev); - return -ENOMEM; - } - return rc; - } - if (of_device_is_compatible(dev->of_node, "qcom,qsmmu-cam-cb")) { - rc = cam_populate_smmu_context_banks(dev, CAM_QSMMU); - if (rc < 0) { - CAM_ERR(CAM_SMMU, "Error: populating context banks"); - return -ENOMEM; - } - return rc; - } + icp_fw.fw_dev = &pdev->dev; + icp_fw.fw_kva = NULL; + icp_fw.fw_hdl = 0; - if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu-fw-dev")) { - icp_fw.fw_dev = &pdev->dev; - icp_fw.fw_kva = NULL; - icp_fw.fw_hdl = 0; - return rc; - } - - /* probe through all the subdevices */ - rc = of_platform_populate(pdev->dev.of_node, msm_cam_smmu_dt_match, - NULL, &pdev->dev); - if (rc < 0) { - CAM_ERR(CAM_SMMU, "Error: populating devices"); - } else { - INIT_WORK(&iommu_cb_set.smmu_work, cam_smmu_page_fault_work); - mutex_init(&iommu_cb_set.payload_list_lock); - INIT_LIST_HEAD(&iommu_cb_set.payload_list); - } - - cam_smmu_create_debug_fs(); - return rc; + CAM_DBG(CAM_SMMU, "FW dev component bound successfully"); + return 0; } -static int cam_smmu_remove(struct platform_device *pdev) +static void cam_smmu_fw_dev_component_unbind(struct device *dev, + struct device *master_dev, void *data) { - struct device *dev = &pdev->dev; + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_SMMU, "Unbinding component: %s", pdev->name); +} + +const static struct component_ops cam_smmu_fw_dev_component_ops = { + .bind = cam_smmu_fw_dev_component_bind, + .unbind = cam_smmu_fw_dev_component_unbind, +}; + +static int cam_smmu_cb_component_bind(struct device *dev, + struct device *master_dev, void *data) +{ + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); + + rc = cam_populate_smmu_context_banks(dev, CAM_ARM_SMMU); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Error: populating context banks"); + cam_smmu_release_cb(pdev); + return -ENOMEM; + } + + CAM_DBG(CAM_SMMU, "CB component bound successfully"); + return 0; +} + +static void cam_smmu_cb_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_SMMU, "Unbinding component: %s", pdev->name); +} + +const static struct component_ops cam_smmu_cb_component_ops = { + .bind = cam_smmu_cb_component_bind, + .unbind = cam_smmu_cb_component_unbind, +}; + +static int cam_smmu_cb_qsmmu_component_bind(struct device *dev, + struct device *master_dev, void *data) +{ + int rc = 0; + + rc = cam_populate_smmu_context_banks(dev, CAM_QSMMU); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Failed in populating context banks"); + return -ENOMEM; + } + + CAM_DBG(CAM_SMMU, "QSMMU CB component bound successfully"); + return 0; +} + +static void cam_smmu_cb_qsmmu_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_SMMU, "Unbinding component: %s", pdev->name); +} + +const static struct component_ops cam_smmu_cb_qsmmu_component_ops = { + .bind = cam_smmu_cb_qsmmu_component_bind, + .unbind = cam_smmu_cb_qsmmu_component_unbind, +}; + +static int cam_smmu_component_bind(struct device *dev, + struct device *master_dev, void *data) +{ + INIT_WORK(&iommu_cb_set.smmu_work, cam_smmu_page_fault_work); + mutex_init(&iommu_cb_set.payload_list_lock); + INIT_LIST_HEAD(&iommu_cb_set.payload_list); + cam_smmu_create_debug_fs(); + + CAM_DBG(CAM_SMMU, "Main component bound successfully"); + return 0; +} + +static void cam_smmu_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); /* release all the context banks and memory allocated */ cam_smmu_reset_iommu_table(CAM_SMMU_TABLE_DEINIT); @@ -3703,15 +3748,75 @@ static int cam_smmu_remove(struct platform_device *pdev) dev->dma_parms = NULL; } - if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-cam-smmu")) - cam_smmu_release_cb(pdev); - + cam_smmu_release_cb(pdev); debugfs_remove_recursive(iommu_cb_set.dentry); iommu_cb_set.dentry = NULL; +} + +const static struct component_ops cam_smmu_component_ops = { + .bind = cam_smmu_component_bind, + .unbind = cam_smmu_component_unbind, +}; + +static int cam_smmu_probe(struct platform_device *pdev) +{ + int rc = 0; + struct device *dev = &pdev->dev; + + dev->dma_parms = NULL; + CAM_DBG(CAM_SMMU, "Adding SMMU component: %s", pdev->name); + if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu")) { + rc = cam_alloc_smmu_context_banks(dev); + if (rc < 0) { + CAM_ERR(CAM_SMMU, "Failed in allocating context banks"); + return -ENOMEM; + } + + rc = component_add(&pdev->dev, &cam_smmu_component_ops); + } else if (of_device_is_compatible(dev->of_node, + "qcom,msm-cam-smmu-cb")) { + rc = component_add(&pdev->dev, &cam_smmu_cb_component_ops); + } else if (of_device_is_compatible(dev->of_node, "qcom,qsmmu-cam-cb")) { + rc = component_add(&pdev->dev, + &cam_smmu_cb_qsmmu_component_ops); + } else if (of_device_is_compatible(dev->of_node, + "qcom,msm-cam-smmu-fw-dev")) { + rc = component_add(&pdev->dev, &cam_smmu_fw_dev_component_ops); + } else { + CAM_ERR(CAM_SMMU, "Unrecognized child device: %s", pdev->name); + rc = -ENODEV; + } + + if (rc < 0) + CAM_ERR(CAM_SMMU, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_smmu_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + CAM_DBG(CAM_SMMU, "Removing SMMU component: %s", pdev->name); + if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu")) { + component_del(&pdev->dev, &cam_smmu_component_ops); + } else if (of_device_is_compatible(dev->of_node, + "qcom,msm-cam-smmu-cb")) { + component_del(&pdev->dev, &cam_smmu_cb_component_ops); + } else if (of_device_is_compatible(dev->of_node, "qcom,qsmmu-cam-cb")) { + component_del(&pdev->dev, &cam_smmu_cb_qsmmu_component_ops); + } else if (of_device_is_compatible(dev->of_node, + "qcom,msm-cam-smmu-fw-dev")) { + component_del(&pdev->dev, &cam_smmu_fw_dev_component_ops); + } else { + CAM_ERR(CAM_SMMU, "Unrecognized child device: %s", pdev->name); + return -ENODEV; + } + return 0; } -static struct platform_driver cam_smmu_driver = { +struct platform_driver cam_smmu_driver = { .probe = cam_smmu_probe, .remove = cam_smmu_remove, .driver = { diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index b431ef0a0bd9..d5529c2055e9 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -12,6 +12,7 @@ #include "cam_sync_util.h" #include "cam_debug_util.h" #include "cam_common_util.h" +#include "camera_main.h" #ifdef CONFIG_MSM_GLOBAL_SYNX #include @@ -1016,10 +1017,12 @@ static void cam_sync_register_synx_bind_ops(void) } #endif -static int cam_sync_probe(struct platform_device *pdev) +static int cam_sync_component_bind(struct device *dev, + struct device *master_dev, void *data) { int rc; int idx; + struct platform_device *pdev = to_platform_device(dev); sync_dev = kzalloc(sizeof(*sync_dev), GFP_KERNEL); if (!sync_dev) @@ -1091,6 +1094,7 @@ static int cam_sync_probe(struct platform_device *pdev) #ifdef CONFIG_MSM_GLOBAL_SYNX cam_sync_register_synx_bind_ops(); #endif + CAM_DBG(CAM_SYNC, "Component bound successfully"); return rc; v4l2_fail: @@ -1105,7 +1109,8 @@ vdev_fail: return rc; } -static int cam_sync_remove(struct platform_device *pdev) +static void cam_sync_component_unbind(struct device *dev, + struct device *master_dev, void *data) { int i; @@ -1117,9 +1122,31 @@ static int cam_sync_remove(struct platform_device *pdev) for (i = 0; i < CAM_SYNC_MAX_OBJS; i++) spin_lock_init(&sync_dev->row_spinlocks[i]); + kfree(sync_dev); sync_dev = NULL; +} +const static struct component_ops cam_sync_component_ops = { + .bind = cam_sync_component_bind, + .unbind = cam_sync_component_unbind, +}; + +static int cam_sync_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_SYNC, "Adding Sync component"); + rc = component_add(&pdev->dev, &cam_sync_component_ops); + if (rc) + CAM_ERR(CAM_SYNC, "failed to add component rc: %d", rc); + + return rc; +} + +static int cam_sync_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_sync_component_ops); return 0; } @@ -1130,7 +1157,7 @@ static const struct of_device_id cam_sync_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_sync_dt_match); -static struct platform_driver cam_sync_driver = { +struct platform_driver cam_sync_driver = { .probe = cam_sync_probe, .remove = cam_sync_remove, .driver = { diff --git a/drivers/camera_main.c b/drivers/camera_main.c index a109a4312977..1dfe51a7ada7 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -53,6 +53,7 @@ #include "cam_top_tpg_v1.h" #include "cam_tfe_dev.h" #include "cam_tfe_csid530.h" +#include "camera_main.h" struct camera_submodule_component { int (*init)(void); @@ -205,6 +206,110 @@ static const struct camera_submodule submodule_table[] = { } }; +/* + * Drivers to be bound by component framework in this order with + * CRM as master + */ +static struct platform_driver *const cam_component_drivers[] = { +/* BASE */ + &cam_sync_driver, + &cam_smmu_driver, + &cam_cpas_driver, + &cam_cdm_intf_driver, + &cam_hw_cdm_driver, +#ifdef CONFIG_SPECTRA_ISP + &cam_ife_csid17x_driver, + &cam_ife_csid_lite_driver, + &cam_vfe_driver, + &isp_driver, +#endif +#ifdef CONFIG_SPECTRA_TFE + &cam_top_tpg_v1_driver, + &cam_tfe_driver, + &cam_tfe_csid530_driver, +#endif +#ifdef CONFIG_SPECTRA_SENSOR + &cam_res_mgr_driver, + &cci_driver, + &csiphy_driver, + &cam_actuator_platform_driver, + &cam_sensor_platform_driver, + &cam_eeprom_platform_driver, + &cam_ois_platform_driver, +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) + &cam_flash_platform_driver, +#endif +#endif +#ifdef CONFIG_SPECTRA_ICP + &cam_a5_driver, + &cam_ipe_driver, + &cam_bps_driver, + &cam_icp_driver, +#endif +#ifdef CONFIG_SPECTRA_OPE + &cam_ope_driver, + &cam_ope_subdev_driver, +#endif +#ifdef CONFIG_SPECTRA_JPEG + &cam_jpeg_enc_driver, + &cam_jpeg_dma_driver, + &jpeg_driver, +#endif +#ifdef CONFIG_SPECTRA_FD + &cam_fd_hw_driver, + &cam_fd_driver, +#endif +#ifdef CONFIG_SPECTRA_LRME + &cam_lrme_hw_driver, + &cam_lrme_driver, +#endif +#ifdef CONFIG_SPECTRA_CUSTOM + &cam_custom_hw_sub_mod_driver, + &cam_custom_csid_driver, + &custom_driver, +#endif +}; + +/* Callback to compare device from match list before adding as component */ +static int camera_component_compare_dev(struct device *dev, void *data) +{ + return dev == data; +} + +/* Add component matches to list for master of aggregate driver */ +int camera_component_match_add_drivers(struct device *master_dev, + struct component_match **match_list) +{ + int i, rc = 0; + struct platform_device *pdev = NULL; + + if (!master_dev || !match_list) { + CAM_ERR(CAM_UTIL, "Invalid parameters for component match add"); + rc = -EINVAL; + goto end; + } + + for (i = 0; i < ARRAY_SIZE(cam_component_drivers); i++) { + struct device_driver *drv = &cam_component_drivers[i]->driver; + struct device *start_dev = NULL, *match_dev; + + while ((match_dev = bus_find_device(&platform_bus_type, + start_dev, drv, (void *)platform_bus_type.match))) { + put_device(start_dev); + pdev = to_platform_device(match_dev); + CAM_DBG(CAM_UTIL, "Adding matched component:%s", + pdev->name); + component_match_add(master_dev, match_list, + camera_component_compare_dev, match_dev); + start_dev = match_dev; + } + put_device(start_dev); + } + +end: + return rc; +} + static int camera_verify_submodules(void) { int rc = 0; diff --git a/drivers/camera_main.h b/drivers/camera_main.h new file mode 100644 index 000000000000..8787c8786c6d --- /dev/null +++ b/drivers/camera_main.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAMERA_MAIN_H +#define CAMERA_MAIN_H + +#include +#include + +extern struct platform_driver cam_sync_driver; +extern struct platform_driver cam_smmu_driver; +extern struct platform_driver cam_cpas_driver; +extern struct platform_driver cam_cdm_intf_driver; +extern struct platform_driver cam_hw_cdm_driver; +#ifdef CONFIG_SPECTRA_ISP +extern struct platform_driver cam_ife_csid17x_driver; +extern struct platform_driver cam_ife_csid_lite_driver; +extern struct platform_driver cam_vfe_driver; +extern struct platform_driver isp_driver; +#endif +#ifdef CONFIG_SPECTRA_TFE +extern struct platform_driver cam_top_tpg_v1_driver; +extern struct platform_driver cam_tfe_driver; +extern struct platform_driver cam_tfe_csid530_driver; +#endif +#ifdef CONFIG_SPECTRA_SENSOR +extern struct platform_driver cam_res_mgr_driver; +extern struct platform_driver cci_driver; +extern struct platform_driver csiphy_driver; +extern struct platform_driver cam_actuator_platform_driver; +extern struct platform_driver cam_sensor_platform_driver; +extern struct platform_driver cam_eeprom_platform_driver; +extern struct platform_driver cam_ois_platform_driver; +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +extern struct platform_driver cam_flash_platform_driver; +#endif +#endif +#ifdef CONFIG_SPECTRA_ICP +extern struct platform_driver cam_a5_driver; +extern struct platform_driver cam_ipe_driver; +extern struct platform_driver cam_bps_driver; +extern struct platform_driver cam_icp_driver; +#endif +#ifdef CONFIG_SPECTRA_OPE +extern struct platform_driver cam_ope_driver; +extern struct platform_driver cam_ope_subdev_driver; +#endif +#ifdef CONFIG_SPECTRA_JPEG +extern struct platform_driver cam_jpeg_enc_driver; +extern struct platform_driver cam_jpeg_dma_driver; +extern struct platform_driver jpeg_driver; +#endif +#ifdef CONFIG_SPECTRA_FD +extern struct platform_driver cam_fd_hw_driver; +extern struct platform_driver cam_fd_driver; +#endif +#ifdef CONFIG_SPECTRA_LRME +extern struct platform_driver cam_lrme_hw_driver; +extern struct platform_driver cam_lrme_driver; +#endif +#ifdef CONFIG_SPECTRA_CUSTOM +extern struct platform_driver cam_custom_hw_sub_mod_driver; +extern struct platform_driver cam_custom_csid_driver; +extern struct platform_driver custom_driver; +#endif + +int camera_component_match_add_drivers(struct device *dev, + struct component_match **match_list); +#endif /* CAMERA_MAIN_H */ From 05378eff2572e8d68c09b7fa7152e5134437114e Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 2 Jan 2020 12:30:45 +0530 Subject: [PATCH 265/790] msm: camera: isp: Register dump for first request id First request id not getting dump if early pcr is on. If early pcr is on need to store the parsed register dump descriptor for first request id which comes as init packet. CRs-Fixed: 2595702 Change-Id: Icbf94d65b5c35cdf47044d770c7db7093001d506 Signed-off-by: Ravikishore Pampana Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/cam_isp_context.c | 19 ++++++++++++++++--- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index dbf7dab9b505..7a9b10cbeca4 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -248,9 +248,11 @@ static int __cam_isp_ctx_enqueue_init_request( struct cam_context *ctx, struct cam_ctx_request *req) { int rc = 0; - struct cam_ctx_request *req_old; - struct cam_isp_ctx_req *req_isp_old; - struct cam_isp_ctx_req *req_isp_new; + struct cam_ctx_request *req_old; + struct cam_isp_ctx_req *req_isp_old; + struct cam_isp_ctx_req *req_isp_new; + struct cam_isp_prepare_hw_update_data *req_update_old; + struct cam_isp_prepare_hw_update_data *req_update_new; spin_lock_bh(&ctx->lock); if (list_empty(&ctx->pending_req_list)) { @@ -302,6 +304,17 @@ static int __cam_isp_ctx_enqueue_init_request( memcpy(&req_old->pf_data, &req->pf_data, sizeof(struct cam_hw_mgr_dump_pf_data)); + if (req_isp_new->hw_update_data.num_reg_dump_buf) { + req_update_new = &req_isp_new->hw_update_data; + req_update_old = &req_isp_old->hw_update_data; + memcpy(&req_update_old->reg_dump_buf_desc, + &req_update_new->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + req_update_new->num_reg_dump_buf); + req_update_old->num_reg_dump_buf = + req_update_new->num_reg_dump_buf; + } + req_old->request_id = req->request_id; list_add_tail(&req->list, &ctx->free_req_list); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 70da17532160..43678af93761 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2768,6 +2768,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->ctxt_to_hw_map = ife_ctx; ife_ctx->ctx_in_use = 1; + ife_ctx->num_reg_dump_buf = 0; acquire_args->valid_acquired_hw = acquire_hw_info->num_inputs; @@ -3011,6 +3012,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->ctxt_to_hw_map = ife_ctx; ife_ctx->ctx_in_use = 1; + ife_ctx->num_reg_dump_buf = 0; CAM_INFO(CAM_ISP, "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", @@ -4175,6 +4177,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->is_rdi_only_context = 0; ctx->cdm_handle = 0; ctx->cdm_ops = NULL; + ctx->num_reg_dump_buf = 0; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; @@ -5590,13 +5593,24 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, if (((prepare->packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_INIT_DEV) { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV; - if ((prepare->num_reg_dump_buf) && (prepare->num_reg_dump_buf < - CAM_REG_DUMP_MAX_BUF_ENTRIES)) { + + if ((!prepare->num_reg_dump_buf) || (prepare->num_reg_dump_buf > + CAM_REG_DUMP_MAX_BUF_ENTRIES)) + goto end; + + if (!ctx->num_reg_dump_buf) { ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; memcpy(ctx->reg_dump_buf_desc, prepare->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * prepare->num_reg_dump_buf); + } else { + prepare_hw_data->num_reg_dump_buf = + prepare->num_reg_dump_buf; + memcpy(prepare_hw_data->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare_hw_data->num_reg_dump_buf); } goto end; From 9ea8b7319440782b60fb8d974ebe657097576c47 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Tue, 7 Jan 2020 16:06:46 +0530 Subject: [PATCH 266/790] msm: camera: fd: skip halt and reset for session start Halt and reset can be applied only at probe time and flush time to clean up the MSF interface. CRs-Fixed: 2593760 Change-Id: I8a19a5a5f4a3b25ef5fe9c18a1e754529418c53c Signed-off-by: Tejas Prajapati --- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 12 +++++++++++- drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c | 10 ++++++---- drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h | 4 +++- drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c | 3 ++- drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h | 4 +++- drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h | 3 ++- 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index b33dfa699647..5799fbdc0cd6 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -1243,6 +1243,8 @@ static int cam_fd_mgr_hw_start(void *hw_mgr_priv, void *mgr_start_args) struct cam_fd_hw_mgr_ctx *hw_ctx; struct cam_fd_device *hw_device; struct cam_fd_hw_init_args hw_init_args; + struct cam_hw_info *fd_hw; + struct cam_fd_core *fd_core; if (!hw_mgr_priv || !hw_mgr_start_args) { CAM_ERR(CAM_FD, "Invalid arguments %pK %pK", @@ -1265,9 +1267,17 @@ static int cam_fd_mgr_hw_start(void *hw_mgr_priv, void *mgr_start_args) return rc; } + fd_hw = (struct cam_hw_info *)hw_device->hw_intf->hw_priv; + fd_core = (struct cam_fd_core *)fd_hw->core_info; + if (hw_device->hw_intf->hw_ops.init) { hw_init_args.hw_ctx = hw_ctx; hw_init_args.ctx_hw_private = hw_ctx->ctx_hw_private; + if (fd_core->hw_static_info->enable_errata_wa.skip_reset) + hw_init_args.reset_required = false; + else + hw_init_args.reset_required = true; + rc = hw_device->hw_intf->hw_ops.init( hw_device->hw_intf->hw_priv, &hw_init_args, sizeof(hw_init_args)); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c index bfb9fdba0af6..78e9ac568381 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -673,10 +673,12 @@ int cam_fd_hw_init(void *hw_priv, void *init_hw_args, uint32_t arg_size) fd_core->core_state = CAM_FD_CORE_STATE_IDLE; spin_unlock_irqrestore(&fd_core->spin_lock, flags); - rc = cam_fd_hw_reset(hw_priv, NULL, 0); - if (rc) { - CAM_ERR(CAM_FD, "Reset Failed, rc=%d", rc); - goto disable_soc; + if (init_args->reset_required) { + rc = cam_fd_hw_reset(hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_FD, "Reset Failed, rc=%d", rc); + goto disable_soc; + } } cam_fd_hw_util_enable_power_on_settings(fd_hw); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h index 1f8815e72f20..22bcdf6fc733 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_CORE_H_ @@ -135,11 +135,13 @@ struct cam_fd_wrapper_regs { * @ro_mode_enable_always : Whether to enable ro mode always * @ro_mode_results_invalid : Whether results written directly into output * memory by HW are valid or not + * @skip_reset : Whether to skip reset during init */ struct cam_fd_hw_errata_wa { bool single_irq_only; bool ro_mode_enable_always; bool ro_mode_results_invalid; + bool skip_reset; }; /** diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c index 7668dd622b90..37db17e5afa8 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -110,6 +110,7 @@ static int cam_fd_hw_dev_probe(struct platform_device *pdev) memset(&init_args, 0x0, sizeof(init_args)); memset(&deinit_args, 0x0, sizeof(deinit_args)); + init_args.reset_required = true; rc = cam_fd_hw_init(fd_hw, &init_args, sizeof(init_args)); if (rc) { CAM_ERR(CAM_FD, "Failed to hw init, rc=%d", rc); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h index 7dd7d94f783a..0dc4593d96da 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_INTF_H_ @@ -158,10 +158,12 @@ struct cam_fd_hw_release_args { * * @hw_ctx : HW context for which init is requested * @ctx_hw_private : HW layer's private information specific to this hw context + * @reset_required : Indicates if the reset is required during init or not */ struct cam_fd_hw_init_args { void *hw_ctx; void *ctx_hw_private; + bool reset_required; }; /** diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h index f3eedeb3b811..d8b78d6e4414 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_V501_H_ @@ -50,6 +50,7 @@ static struct cam_fd_hw_static_info cam_fd_wrapper200_core501_info = { .single_irq_only = true, .ro_mode_enable_always = true, .ro_mode_results_invalid = true, + .skip_reset = true, }, .irq_mask = CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE) | CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE) | From 4f1ba0f292afb3891d6a19dc158d906762175f99 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Mon, 6 Jan 2020 11:41:06 +0530 Subject: [PATCH 267/790] msm: camera: isp: Get packet opcode from hw manager While processing the user space submitted isp packet, isp context need to know the packet opcode. Get the opcode from the hw manager than the direct accessing the opcode from packet. Ife umd sends different opcodes then tfe umd. Both ife and tfe kernel packet opcodes are same. So hw manager can consume this differences. CRs-Fixed: 2585713 Change-Id: I54813af233cd8bfa640f2688c1334510a5b85f1c Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/cam_isp_context.c | 21 ++++++++++++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 12 +++++++++++ .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 5 +++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index dbf7dab9b505..1024f69d8900 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3052,6 +3052,9 @@ static int __cam_isp_ctx_config_dev_in_top_state( struct cam_req_mgr_add_request add_req; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + uint32_t packet_opcode = 0; CAM_DBG(CAM_ISP, "get free request object......"); @@ -3100,7 +3103,23 @@ 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.op_code + 1) & 0xF) == CAM_ISP_PACKET_UPDATE_DEV) + /* Query the packet opcode */ + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_GET_PACKET_OPCODE; + isp_hw_cmd_args.cmd_data = (void *)packet; + 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); + if (rc) { + CAM_ERR(CAM_ISP, "HW command failed"); + goto free_req; + } + + packet_opcode = isp_hw_cmd_args.u.packet_op_code; + CAM_DBG(CAM_ISP, "packet op %d", packet_opcode); + + if ((packet_opcode == CAM_ISP_PACKET_UPDATE_DEV) && (packet->header.request_id <= ctx->last_flush_req)) { CAM_INFO(CAM_ISP, "request %lld has been flushed, reject packet", diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index a652bc1e6069..9a35ec91e07c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5783,6 +5783,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *) hw_cmd_args->ctxt_to_hw_map; struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; + struct cam_packet *packet; if (!hw_mgr_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -5823,6 +5824,17 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) else isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_PIX; break; + case CAM_ISP_HW_MGR_GET_PACKET_OPCODE: + packet = (struct cam_packet *) + isp_hw_cmd_args->cmd_data; + if (((packet->header.op_code + 1) & 0xF) == + CAM_ISP_PACKET_INIT_DEV) + isp_hw_cmd_args->u.packet_op_code = + CAM_ISP_PACKET_INIT_DEV; + else + isp_hw_cmd_args->u.packet_op_code = + CAM_ISP_PACKET_UPDATE_DEV; + break; default: CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", hw_cmd_args->cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 5354bfde8331..a0c0e60a30a4 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -224,6 +224,7 @@ enum cam_isp_hw_mgr_command { 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_GET_PACKET_OPCODE, CAM_ISP_HW_MGR_CMD_MAX, }; @@ -237,14 +238,18 @@ enum cam_isp_ctx_type { * struct cam_isp_hw_cmd_args - Payload for hw manager command * * @cmd_type HW command type + * @cmd_data command data * @sof_irq_enable To debug if SOF irq is enabled * @ctx_type RDI_ONLY, PIX and RDI, or FS2 + * @packet_op_code packet opcode */ struct cam_isp_hw_cmd_args { uint32_t cmd_type; + void *cmd_data; union { uint32_t sof_irq_enable; uint32_t ctx_type; + uint32_t packet_op_code; } u; }; From dbc2111c4f5c0d41e5d017add3ebe9f622bbfe9d Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 28 Oct 2019 19:54:39 +0530 Subject: [PATCH 268/790] msm: camera: common: LDAR dump NRT devices information When user space detects an error or does not receive response for a request, Lets do a reset(LDAR) is triggered. Before LDAR, user space sends flush command to the kernel space. In order to debug the cause for this situation and to dump the information, user space sends a dump command to the kernel space before sending flush. As a part of this command, it passes the culprit request id and the buffer into which the information can be dumped. Kernel space traverses across the drivers and find the culprit hw and dumps the relevant information in the buffer. This data is written to a file for offline processing. This commit dumps the information for NRT devices; JPEG, LRME, FD and ICP. For LRME, FD, JPEG context information is dumped. FOR ICP, fw image is dumped. Change-Id: I123e9b8289521a40d88156ba9bd0003ad9602f01 CRs-Fixed: 2602180 Signed-off-by: Gaurav Jindal --- drivers/cam_fd/cam_fd_context.c | 16 +- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 135 ++++++++++++++- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h | 10 +- .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c | 79 +++++++++ .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h | 35 +++- drivers/cam_icp/cam_icp_context.c | 17 +- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 55 +++++- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 111 ++++++++++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 10 +- .../icp_hw_mgr/include/cam_a5_hw_intf.h | 3 +- .../icp_hw/include/cam_icp_hw_mgr_intf.h | 29 +++- drivers/cam_jpeg/cam_jpeg_context.c | 16 +- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 139 +++++++++++++++ drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 10 +- .../jpeg_hw/include/cam_jpeg_hw_intf.h | 19 +- .../cam_jpeg_enc_hw_info_ver_4_2_0.h | 6 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 83 ++++++++- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h | 8 +- drivers/cam_lrme/cam_lrme_context.c | 18 +- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 47 ++++- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c | 162 ++++++++++++++++++ .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h | 20 ++- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h | 23 ++- 23 files changed, 1032 insertions(+), 19 deletions(-) diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index ec6468f85dc0..99887d30242d 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -117,6 +117,19 @@ static int __cam_fd_ctx_release_dev_in_activated(struct cam_context *ctx, return rc; } +static int __cam_fd_ctx_dump_dev_in_activated( + struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc; + + rc = cam_context_dump_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_FD, "Failed to dump device, rc=%d", rc); + + return rc; +} + static int __cam_fd_ctx_flush_dev_in_activated(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { @@ -198,6 +211,7 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_activated, .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, + .dump_dev = __cam_fd_ctx_dump_dev_in_activated, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index b33dfa699647..cfbb8840eb63 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -883,6 +883,7 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) hw_device->cur_hw_ctx = hw_ctx; hw_device->req_id = frame_req->request_id; mutex_unlock(&hw_device->lock); + frame_req->submit_timestamp = ktime_get(); rc = cam_fd_mgr_util_put_frame_req( &hw_mgr->frame_processing_list, &frame_req); @@ -1504,6 +1505,137 @@ static int cam_fd_mgr_hw_flush(void *hw_mgr_priv, return rc; } +static int cam_fd_mgr_hw_dump( + void *hw_mgr_priv, + void *hw_dump_args) +{ + int rc; + uint8_t *dst; + ktime_t cur_time; + size_t remain_len; + uint32_t min_len; + uint64_t diff; + uint64_t *addr, *start; + struct timespec64 cur_ts; + struct timespec64 req_ts; + struct cam_fd_hw_mgr *hw_mgr; + struct cam_hw_dump_args *dump_args; + struct cam_fd_hw_mgr_ctx *hw_ctx; + struct cam_fd_device *hw_device; + struct cam_fd_hw_dump_args fd_dump_args; + struct cam_fd_hw_dump_header *hdr; + struct cam_fd_mgr_frame_request *frame_req, *req_temp; + + hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; + dump_args = (struct cam_hw_dump_args *)hw_dump_args; + if (!hw_mgr || !dump_args) { + CAM_ERR(CAM_FD, "Invalid args %pK %pK", + hw_mgr, dump_args); + return -EINVAL; + } + + hw_ctx = (struct cam_fd_hw_mgr_ctx *)dump_args->ctxt_to_hw_map; + + if (!hw_ctx) { + CAM_ERR(CAM_FD, "Invalid ctx"); + return -EINVAL; + } + + rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); + + if (rc) { + CAM_ERR(CAM_FD, "Error in getting device %d", rc); + return rc; + } + + list_for_each_entry_safe(frame_req, req_temp, + &hw_mgr->frame_processing_list, list) { + if (frame_req->request_id == dump_args->request_id) + goto hw_dump; + } + + CAM_DBG(CAM_FD, "fd dump cannot find req %llu", + dump_args->request_id); + return rc; +hw_dump: + cur_time = ktime_get(); + diff = ktime_us_delta(frame_req->submit_timestamp, cur_time); + cur_ts = ktime_to_timespec64(cur_time); + req_ts = ktime_to_timespec64(frame_req->submit_timestamp); + if (diff < CAM_FD_RESPONSE_TIME_THRESHOLD) { + CAM_INFO(CAM_FD, "No Error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + return 0; + } + CAM_INFO(CAM_FD, "Error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &fd_dump_args.cpu_addr, &fd_dump_args.buf_len); + if (rc) { + CAM_ERR(CAM_FD, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + return rc; + } + if (fd_dump_args.buf_len <= dump_args->offset) { + CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu", + fd_dump_args.buf_len, dump_args->offset); + return -ENOSPC; + } + remain_len = fd_dump_args.buf_len - dump_args->offset; + min_len = sizeof(struct cam_fd_hw_dump_header) + + (CAM_FD_HW_DUMP_NUM_WORDS * sizeof(uint64_t)); + + if (remain_len < min_len) { + CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + + dst = (uint8_t *)fd_dump_args.cpu_addr + dump_args->offset; + hdr = (struct cam_fd_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN, + "FD_REQ:"); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + sizeof(struct cam_fd_hw_dump_header)); + start = addr; + *addr++ = frame_req->request_id; + *addr++ = req_ts.tv_sec; + *addr++ = req_ts.tv_nsec/NSEC_PER_USEC; + *addr++ = cur_ts.tv_sec; + *addr++ = cur_ts.tv_nsec/NSEC_PER_USEC; + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_fd_hw_dump_header); + + fd_dump_args.request_id = dump_args->request_id; + fd_dump_args.offset = dump_args->offset; + if (hw_device->hw_intf->hw_ops.process_cmd) { + rc = hw_device->hw_intf->hw_ops.process_cmd( + hw_device->hw_intf->hw_priv, + CAM_FD_HW_CMD_HW_DUMP, + &fd_dump_args, + sizeof(struct + cam_fd_hw_dump_args)); + if (rc) { + CAM_ERR(CAM_FD, "Hw Dump cmd fails req %lld rc %d", + frame_req->request_id, rc); + return rc; + } + } + CAM_DBG(CAM_FD, "Offset before %zu after %zu", + dump_args->offset, fd_dump_args.offset); + dump_args->offset = fd_dump_args.offset; + return rc; +} + static int cam_fd_mgr_hw_stop(void *hw_mgr_priv, void *mgr_stop_args) { struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; @@ -1944,6 +2076,7 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_write = NULL; hw_mgr_intf->hw_close = NULL; hw_mgr_intf->hw_flush = cam_fd_mgr_hw_flush; + hw_mgr_intf->hw_dump = cam_fd_mgr_hw_dump; return rc; diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h index 49bc5bbc1b07..bbbc77bef6a3 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_MGR_H_ @@ -21,6 +21,12 @@ #define CAM_FD_HW_MAX 1 #define CAM_FD_WORKQ_NUM_TASK 10 +/* + * Response time threshold in ms beyond which a request is not expected to be + * with FD hw + */ +#define CAM_FD_RESPONSE_TIME_THRESHOLD 100000 + struct cam_fd_hw_mgr; /** @@ -100,6 +106,7 @@ struct cam_fd_device { * @hw_update_entries : HW update entries corresponding to this request * which needs to be submitted to HW through CDM * @num_hw_update_entries : Number of HW update entries + * @submit_timestamp : Time stamp for submit req with hw */ struct cam_fd_mgr_frame_request { struct list_head list; @@ -108,6 +115,7 @@ struct cam_fd_mgr_frame_request { struct cam_fd_hw_req_private hw_req_private; struct cam_hw_update_entry hw_update_entries[CAM_FD_MAX_HW_ENTRIES]; uint32_t num_hw_update_entries; + ktime_t submit_timestamp; }; /** diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c index bfb9fdba0af6..16a66c2a41ce 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -516,6 +516,80 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw, return 0; } +static int cam_fd_hw_util_processcmd_hw_dump( + struct cam_hw_info *fd_hw, + void *args) +{ + int i, j; + uint8_t *dst; + uint32_t *addr, *start; + uint32_t num_reg, min_len; + uint64_t remain_len; + struct cam_hw_soc_info *soc_info; + struct cam_fd_hw_dump_header *hdr; + struct cam_fd_hw_dump_args *dump_args; + + if (!fd_hw || !args) { + CAM_ERR(CAM_FD, "Invalid args %pK %pK", + fd_hw, args); + return -EINVAL; + } + + mutex_lock(&fd_hw->hw_mutex); + + if (fd_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_INFO(CAM_FD, "power off state"); + mutex_unlock(&fd_hw->hw_mutex); + return 0; + } + + dump_args = (struct cam_fd_hw_dump_args *)args; + soc_info = &fd_hw->soc_info; + + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu", + dump_args->buf_len, dump_args->offset); + mutex_unlock(&fd_hw->hw_mutex); + return -ENOSPC; + } + + remain_len = dump_args->buf_len - dump_args->offset; + min_len = sizeof(struct cam_fd_hw_dump_header) + + soc_info->reg_map[0].size + sizeof(uint32_t); + + if (remain_len < min_len) { + CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + mutex_unlock(&fd_hw->hw_mutex); + return -ENOSPC; + } + + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_fd_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN, + "FD_REG:"); + hdr->word_size = sizeof(uint32_t); + addr = (uint32_t *)(dst + sizeof(struct cam_fd_hw_dump_header)); + start = addr; + *addr++ = soc_info->index; + + for (j = 0; j < soc_info->num_reg_map; j++) { + num_reg = soc_info->reg_map[j].size/4; + for (i = 0; i < num_reg; i++) { + *addr++ = soc_info->mem_block[j]->start + i*4; + *addr++ = cam_io_r(soc_info->reg_map[j].mem_base + + (i*4)); + } + } + + mutex_unlock(&fd_hw->hw_mutex); + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_fd_hw_dump_header); + CAM_DBG(CAM_FD, "%zu", dump_args->offset); + return 0; +} + irqreturn_t cam_fd_hw_irq(int irq_num, void *data) { struct cam_hw_info *fd_hw = (struct cam_hw_info *)data; @@ -1159,6 +1233,11 @@ int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type, cmd_frame_results); break; } + case CAM_FD_HW_CMD_HW_DUMP: { + rc = cam_fd_hw_util_processcmd_hw_dump(fd_hw, + cmd_args); + break; + } default: break; } diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h index 7dd7d94f783a..6d6f33e739e4 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_INTF_H_ @@ -24,6 +24,8 @@ #define CAM_FD_MAX_IO_BUFFERS 5 #define CAM_FD_MAX_HW_ENTRIES 5 +#define CAM_FD_HW_DUMP_TAG_MAX_LEN 32 +#define CAM_FD_HW_DUMP_NUM_WORDS 5 /** * enum cam_fd_hw_type - Enum for FD HW type @@ -81,12 +83,14 @@ enum cam_fd_hw_irq_type { * @CAM_FD_HW_CMD_UPDATE_SOC : Command to process soc update * @CAM_FD_HW_CMD_REGISTER_CALLBACK : Command to set hw mgr callback * @CAM_FD_HW_CMD_MAX : Indicates max cmd + * @CAM_FD_HW_CMD_HW_DUMP : Command to dump fd hw information */ enum cam_fd_hw_cmd_type { CAM_FD_HW_CMD_PRESTART, CAM_FD_HW_CMD_FRAME_DONE, CAM_FD_HW_CMD_UPDATE_SOC, CAM_FD_HW_CMD_REGISTER_CALLBACK, + CAM_FD_HW_CMD_HW_DUMP, CAM_FD_HW_CMD_MAX, }; @@ -279,6 +283,34 @@ struct cam_fd_hw_cmd_set_irq_cb { void *data; }; +/** + * struct cam_fd_hw_dump_args : Args for dump request + * + * @request_id : Issue request id + * @offset : offset of the buffer + * @buf_len : Length of target buffer + * @cpu_addr : start address of the target buffer + */ +struct cam_fd_hw_dump_args { + uint64_t request_id; + size_t offset; + size_t buf_len; + uintptr_t cpu_addr; +}; + +/** + * struct cam_fd_hw_dump_header : fd hw dump header + * + * @tag : fd hw dump header tag + * @size : Size of data + * @word_size : size of each word + */ +struct cam_fd_hw_dump_header { + uint8_t tag[CAM_FD_HW_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + /** * @brief : API to register FD Hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. @@ -291,3 +323,4 @@ int cam_fd_hw_init_module(void); void cam_fd_hw_exit_module(void); #endif /* _CAM_FD_HW_INTF_H_ */ + diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 180ea7152a76..6a9f57b65f68 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -107,6 +107,19 @@ static int __cam_icp_start_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_icp_dump_dev_in_ready( + struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc; + + rc = cam_context_dump_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_ICP, "Failed to dump device"); + + return rc; +} + static int __cam_icp_flush_dev_in_ready(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { @@ -230,6 +243,7 @@ static struct cam_ctx_ops .start_dev = __cam_icp_start_dev_in_acquired, .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, + .dump_dev = __cam_icp_dump_dev_in_ready, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, @@ -242,6 +256,7 @@ static struct cam_ctx_ops .release_dev = __cam_icp_release_dev_in_ready, .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, + .dump_dev = __cam_icp_dump_dev_in_ready, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index e4cb645b7af0..1ac27511f7ac 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -235,6 +235,53 @@ fw_download_failed: return rc; } +static int cam_a5_fw_dump( + struct cam_icp_hw_dump_args *dump_args, + struct cam_a5_device_core_info *core_info) +{ + u8 *dest; + u8 *src; + uint64_t size_required; + struct cam_icp_dump_header *hdr; + + if (!core_info || !dump_args) { + CAM_ERR(CAM_ICP, "invalid params %pK %pK", + core_info, dump_args); + return -EINVAL; + } + if (!core_info->fw_kva_addr || !dump_args->cpu_addr) { + CAM_ERR(CAM_ICP, "invalid params %pK, 0x%zx", + core_info->fw_kva_addr, dump_args->cpu_addr); + return -EINVAL; + } + + size_required = core_info->fw_buf_len + + sizeof(struct cam_icp_dump_header); + + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_ICP, "Dump offset overshoot len %zu offset %zu", + dump_args->buf_len, dump_args->offset); + return -ENOSPC; + } + + if ((dump_args->buf_len - dump_args->offset) < size_required) { + CAM_WARN(CAM_ICP, "Dump buffer exhaust required %llu len %llu", + size_required, core_info->fw_buf_len); + return -ENOSPC; + } + + dest = (u8 *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_icp_dump_header *)dest; + scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_FW:"); + hdr->word_size = sizeof(u8); + hdr->size = core_info->fw_buf_len; + src = (u8 *)core_info->fw_kva_addr; + dest = (u8 *)dest + sizeof(struct cam_icp_dump_header); + memcpy_fromio(dest, src, core_info->fw_buf_len); + dump_args->offset += hdr->size + sizeof(struct cam_icp_dump_header); + return 0; +} + int cam_a5_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { @@ -543,6 +590,12 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, core_info->cpas_handle, &ahb_vote); break; } + case CAM_ICP_A5_CMD_HW_DUMP: { + struct cam_icp_hw_dump_args *dump_args = cmd_args; + + rc = cam_a5_fw_dump(dump_args, core_info); + break; + } default: break; } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 040d302f6603..3f30bb6819d4 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3930,6 +3930,7 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx); ctx_data->hfi_frame_process.fw_process_flag[idx] = true; + ctx_data->hfi_frame_process.submit_timestamp[idx] = ktime_get(); CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id, frame_info->io_config); @@ -5038,6 +5039,115 @@ static int cam_icp_mgr_enqueue_abort( return 0; } +static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args) +{ + int rc; + int i; + size_t remain_len; + uint8_t *dst; + uint32_t min_len; + uint64_t diff; + uint64_t *addr, *start; + struct timespec64 cur_ts; + struct timespec64 req_ts; + ktime_t cur_time; + struct cam_hw_intf *a5_dev_intf; + struct cam_icp_hw_mgr *hw_mgr; + struct cam_hw_dump_args *dump_args; + struct cam_icp_hw_ctx_data *ctx_data; + struct cam_icp_dump_header *hdr; + struct cam_icp_hw_dump_args icp_dump_args; + struct hfi_frame_process_info *frm_process; + + if ((!hw_priv) || (!hw_dump_args)) { + CAM_ERR(CAM_ICP, "Invalid params %pK %pK", + hw_priv, hw_dump_args); + return -EINVAL; + } + + dump_args = (struct cam_hw_dump_args *)hw_dump_args; + hw_mgr = hw_priv; + ctx_data = dump_args->ctxt_to_hw_map; + CAM_DBG(CAM_ICP, "Req %lld", dump_args->request_id); + frm_process = &ctx_data->hfi_frame_process; + for (i = 0; i < CAM_FRAME_CMD_MAX; i++) { + if ((frm_process->request_id[i] == + dump_args->request_id) && + frm_process->fw_process_flag[i]) + goto hw_dump; + } + return 0; +hw_dump: + cur_time = ktime_get(); + diff = ktime_us_delta(frm_process->submit_timestamp[i], cur_time); + cur_ts = ktime_to_timespec64(cur_time); + req_ts = ktime_to_timespec64(frm_process->submit_timestamp[i]); + + if (diff < CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD) { + CAM_INFO(CAM_ICP, "No Error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + return 0; + } + + CAM_INFO(CAM_ICP, "Error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &icp_dump_args.cpu_addr, &icp_dump_args.buf_len); + if (rc) { + CAM_ERR(CAM_ICP, "Invalid addr %u rc %d", + dump_args->buf_handle, rc); + return rc; + } + if (icp_dump_args.buf_len <= dump_args->offset) { + CAM_WARN(CAM_ICP, "dump buffer overshoot len %zu offset %zu", + icp_dump_args.buf_len, dump_args->offset); + return -ENOSPC; + } + + remain_len = icp_dump_args.buf_len - dump_args->offset; + min_len = sizeof(struct cam_icp_dump_header) + + (CAM_ICP_DUMP_NUM_WORDS * sizeof(uint64_t)); + + if (remain_len < min_len) { + CAM_WARN(CAM_ICP, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + + dst = (uint8_t *)icp_dump_args.cpu_addr + dump_args->offset; + hdr = (struct cam_icp_dump_header *)dst; + scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_REQ:"); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + sizeof(struct cam_icp_dump_header)); + start = addr; + *addr++ = frm_process->request_id[i]; + *addr++ = req_ts.tv_sec; + *addr++ = req_ts.tv_nsec/NSEC_PER_USEC; + *addr++ = cur_ts.tv_sec; + *addr++ = cur_ts.tv_nsec/NSEC_PER_USEC; + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += (hdr->size + sizeof(struct cam_icp_dump_header)); + /* Dumping the fw image*/ + icp_dump_args.offset = dump_args->offset; + a5_dev_intf = hw_mgr->a5_dev_intf; + rc = a5_dev_intf->hw_ops.process_cmd( + a5_dev_intf->hw_priv, + CAM_ICP_A5_CMD_HW_DUMP, &icp_dump_args, + sizeof(struct cam_icp_hw_dump_args)); + CAM_DBG(CAM_ICP, "Offset before %zu after %zu", + dump_args->offset, icp_dump_args.offset); + dump_args->offset = icp_dump_args.offset; + return rc; +} + static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; @@ -5850,6 +5960,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, hw_mgr_intf->hw_close = cam_icp_mgr_hw_close_u; hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush; hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd; + hw_mgr_intf->hw_dump = cam_icp_mgr_hw_dump; icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE; mutex_init(&icp_hw_mgr.hw_mgr_mutex); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 8cab9a80cd30..c438d438e892 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_ICP_HW_MGR_H @@ -67,6 +67,12 @@ /* Current appliacble vote paths, based on number of UAPI definitions */ #define CAM_ICP_MAX_PER_PATH_VOTES 6 +/* + * Response time threshold in ms beyond which a request is not expected + * to be with ICP hw + */ +#define CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD 300000 + /** * struct icp_hfi_mem_info * @qtbl: Memory info of queue table @@ -171,6 +177,7 @@ struct cam_icp_clk_bw_req_internal_v2 { * @clk_info: Clock information for a request * @clk_info_v2: Clock info for AXI bw voting v2 * @frame_info: information needed to process request + * @submit_timestamp: Submit timestamp to hw */ struct hfi_frame_process_info { struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX]; @@ -186,6 +193,7 @@ struct hfi_frame_process_info { struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX]; struct cam_icp_clk_bw_req_internal_v2 clk_info_v2[CAM_FRAME_CMD_MAX]; struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX]; + ktime_t submit_timestamp[CAM_FRAME_CMD_MAX]; }; /** diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h index af80a2eac15d..c3fefdc09ba9 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_A5_HW_INTF_H @@ -27,6 +27,7 @@ enum cam_icp_a5_cmd_type { CAM_ICP_A5_CMD_UBWC_CFG, CAM_ICP_A5_CMD_PC_PREP, CAM_ICP_A5_CMD_CLK_UPDATE, + CAM_ICP_A5_CMD_HW_DUMP, CAM_ICP_A5_CMD_MAX, }; diff --git a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h index d87c7ef238df..84129cba7e19 100644 --- a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h +++ b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_ICP_HW_MGR_INTF_H @@ -27,6 +27,9 @@ #define CAM_ICP_DEFAULT_AXI_PATH CAM_AXI_PATH_DATA_ALL #define CAM_ICP_DEFAULT_AXI_TRANSAC CAM_AXI_TRANSACTION_READ +#define CAM_ICP_DUMP_TAG_MAX_LEN 32 +#define CAM_ICP_DUMP_NUM_WORDS 5 + int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl); @@ -44,4 +47,28 @@ struct cam_icp_cpas_vote { uint32_t axi_vote_valid; }; +/** + * struct cam_icp_hw_dump_args + * @cpu_addr: kernel vaddr + * @buf_len: buffer length + * @offset: offset + */ +struct cam_icp_hw_dump_args { + uintptr_t cpu_addr; + size_t buf_len; + size_t offset; +}; + +/** + * struct cam_icp_dump_header + * @tag: tag of the packet + * @size: size of data in packet + * @word_size: size of each word in packet + */ +struct cam_icp_dump_header { + uint8_t tag[CAM_ICP_DUMP_TAG_MAX_LEN]; + uint64_t size; + int32_t word_size; +}; + #endif /* CAM_ICP_HW_MGR_INTF_H */ diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index b16a9dfed011..b28f8b667239 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -83,6 +83,19 @@ static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_jpeg_ctx_dump_dev_in_acquired( + struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc; + + rc = cam_context_dump_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to dump device, rc=%d", rc); + + return rc; +} + static int __cam_jpeg_ctx_flush_dev_in_acquired(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { @@ -145,6 +158,7 @@ static struct cam_ctx_ops .config_dev = __cam_jpeg_ctx_config_dev_in_acquired, .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, + .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired, }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index a59a2581410e..24511b904da0 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -488,6 +488,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) rc); goto end_callcb; } + p_cfg_req->submit_timestamp = ktime_get(); mutex_unlock(&hw_mgr->hw_mgr_mutex); return rc; @@ -1491,6 +1492,143 @@ num_dev_failed: return rc; } +static int cam_jpeg_mgr_hw_dump(void *hw_mgr_priv, void *dump_hw_args) +{ + int rc; + uint8_t *dst; + ktime_t cur_time; + size_t remain_len; + uint32_t min_len; + uint32_t dev_type; + uint64_t diff; + uint64_t *addr, *start; + struct timespec64 cur_ts; + struct timespec64 req_ts; + struct cam_jpeg_hw_mgr *hw_mgr; + struct cam_hw_dump_args *dump_args; + struct cam_jpeg_hw_cfg_req *p_cfg_req; + struct cam_jpeg_hw_ctx_data *ctx_data; + struct cam_jpeg_hw_dump_args jpeg_dump_args; + struct cam_jpeg_hw_dump_header *hdr; + + if (!hw_mgr_priv || !dump_hw_args) { + CAM_ERR(CAM_JPEG, "Invalid args %pK %pK", + hw_mgr_priv, dump_hw_args); + return -EINVAL; + } + + hw_mgr = hw_mgr_priv; + dump_args = (struct cam_hw_dump_args *)dump_hw_args; + ctx_data = (struct cam_jpeg_hw_ctx_data *)dump_args->ctxt_to_hw_map; + + if (!ctx_data) { + CAM_ERR(CAM_JPEG, "Invalid context"); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + if (!ctx_data->in_use) { + CAM_ERR(CAM_JPEG, "ctx is not in use"); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + if (true == hw_mgr->device_in_use[dev_type][0]) { + p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; + if (p_cfg_req && p_cfg_req->req_id == + (uintptr_t)dump_args->request_id) + goto hw_dump; + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; + +hw_dump: + cur_time = ktime_get(); + diff = ktime_us_delta(p_cfg_req->submit_timestamp, cur_time); + cur_ts = ktime_to_timespec64(cur_time); + req_ts = ktime_to_timespec64(p_cfg_req->submit_timestamp); + + if (diff < CAM_JPEG_RESPONSE_TIME_THRESHOLD) { + CAM_INFO(CAM_JPEG, + "No error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; + } + + CAM_INFO(CAM_JPEG, + "Error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &jpeg_dump_args.cpu_addr, &jpeg_dump_args.buf_len); + if (rc) { + CAM_ERR(CAM_JPEG, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -rc; + } + + if (jpeg_dump_args.buf_len <= dump_args->offset) { + CAM_WARN(CAM_JPEG, "dump offset overshoot len %zu offset %zu", + jpeg_dump_args.buf_len, dump_args->offset); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -ENOSPC; + } + + remain_len = jpeg_dump_args.buf_len - dump_args->offset; + min_len = sizeof(struct cam_jpeg_hw_dump_header) + + (CAM_JPEG_HW_DUMP_NUM_WORDS * sizeof(uint64_t)); + if (remain_len < min_len) { + CAM_WARN(CAM_JPEG, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -ENOSPC; + } + + dst = (uint8_t *)jpeg_dump_args.cpu_addr + dump_args->offset; + hdr = (struct cam_jpeg_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_JPEG_HW_DUMP_TAG_MAX_LEN, + "JPEG_REQ:"); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + sizeof(struct cam_jpeg_hw_dump_header)); + start = addr; + *addr++ = dump_args->request_id; + *addr++ = req_ts.tv_sec; + *addr++ = req_ts.tv_nsec/NSEC_PER_USEC; + *addr++ = cur_ts.tv_sec; + *addr++ = cur_ts.tv_nsec/NSEC_PER_USEC; + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_jpeg_hw_dump_header); + jpeg_dump_args.request_id = dump_args->request_id; + jpeg_dump_args.offset = dump_args->offset; + + if (hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) { + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_HW_DUMP, + &jpeg_dump_args, sizeof(jpeg_dump_args)); + } + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_DBG(CAM_JPEG, "Offset before %u after %u", + dump_args->offset, jpeg_dump_args.offset); + dump_args->offset = jpeg_dump_args.offset; + return rc; +} + static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -1544,6 +1682,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, hw_mgr_intf->hw_flush = cam_jpeg_mgr_hw_flush; hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop; hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd; + hw_mgr_intf->hw_dump = cam_jpeg_mgr_hw_dump; mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex); spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index e482c11a82bd..3a00e424ebc9 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_HW_MGR_H @@ -21,6 +21,12 @@ #define CAM_JPEG_WORKQ_TASK_MSG_TYPE 2 #define CAM_JPEG_HW_CFG_Q_MAX 50 +/* + * Response time threshold in ms beyond which a request is not expected + * to be with JPEG hw + */ +#define CAM_JPEG_RESPONSE_TIME_THRESHOLD 100000 + /** * struct cam_jpeg_process_frame_work_data_t * @@ -69,12 +75,14 @@ struct cam_jpeg_hw_cdm_info_t { * @hw_cfg_args: Hw config args * @dev_type: Dev type for cfg request * @req_id: Request Id + * @submit_timestamp: Timestamp of submitting request */ struct cam_jpeg_hw_cfg_req { struct list_head list; struct cam_hw_config_args hw_cfg_args; uint32_t dev_type; uintptr_t req_id; + ktime_t submit_timestamp; }; /** diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h index 3deb9dd73b32..df552c4d04cf 100644 --- a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_HW_INTF_H @@ -15,6 +15,9 @@ #define JPEG_VOTE 640000000 +#define CAM_JPEG_HW_DUMP_TAG_MAX_LEN 32 +#define CAM_JPEG_HW_DUMP_NUM_WORDS 5 + enum cam_jpeg_hw_type { CAM_JPEG_DEV_ENC, CAM_JPEG_DEV_DMA, @@ -27,9 +30,23 @@ struct cam_jpeg_set_irq_cb { uint32_t b_set_cb; }; +struct cam_jpeg_hw_dump_args { + uint64_t request_id; + uintptr_t cpu_addr; + size_t offset; + size_t buf_len; +}; + +struct cam_jpeg_hw_dump_header { + uint8_t tag[CAM_JPEG_HW_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + enum cam_jpeg_cmd_type { CAM_JPEG_CMD_CDM_CFG, CAM_JPEG_CMD_SET_IRQ_CB, + CAM_JPEG_CMD_HW_DUMP, CAM_JPEG_CMD_MAX, }; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h index e610a9e7ee03..b75998bc586c 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_ENC_HW_INFO_TITAN170_H @@ -66,6 +66,10 @@ static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = { .resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK, .iserror = CAM_JPEG_HW_MASK_COMP_ERR, .stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK, + }, + .reg_dump = { + .start_offset = 0x0, + .end_offset = 0x33C, } }; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index 4830bf58e89e..b9329a8173e5 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -378,6 +378,81 @@ int cam_jpeg_enc_stop_hw(void *data, return 0; } +int cam_jpeg_enc_hw_dump( + struct cam_hw_info *jpeg_enc_dev, + struct cam_jpeg_hw_dump_args *dump_args) +{ + + int i; + uint8_t *dst; + uint32_t *addr, *start; + uint32_t num_reg, min_len; + uint32_t reg_start_offset; + size_t remain_len; + struct cam_hw_soc_info *soc_info; + struct cam_jpeg_hw_dump_header *hdr; + struct cam_jpeg_enc_device_hw_info *hw_info; + struct cam_jpeg_enc_device_core_info *core_info; + + soc_info = &jpeg_enc_dev->soc_info; + core_info = (struct cam_jpeg_enc_device_core_info *) + jpeg_enc_dev->core_info; + hw_info = core_info->jpeg_enc_hw_info; + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_enc_dev->hw_lock); + + if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_ERR(CAM_JPEG, "JPEG HW is in off state"); + spin_unlock(&jpeg_enc_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return -EINVAL; + } + + spin_unlock(&jpeg_enc_dev->hw_lock); + + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_JPEG, "dump buffer overshoot %zu %zu", + dump_args->buf_len, dump_args->offset); + mutex_unlock(&core_info->core_mutex); + return -ENOSPC; + } + + remain_len = dump_args->buf_len - dump_args->offset; + min_len = sizeof(struct cam_jpeg_hw_dump_header) + + soc_info->reg_map[0].size + sizeof(uint32_t); + if (remain_len < min_len) { + CAM_WARN(CAM_JPEG, "dump buffer exhaust %zu %u", + remain_len, min_len); + mutex_unlock(&core_info->core_mutex); + return -ENOSPC; + } + + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_jpeg_hw_dump_header *)dst; + snprintf(hdr->tag, CAM_JPEG_HW_DUMP_TAG_MAX_LEN, + "JPEG_REG:"); + hdr->word_size = sizeof(uint32_t); + addr = (uint32_t *)(dst + sizeof(struct cam_jpeg_hw_dump_header)); + start = addr; + *addr++ = soc_info->index; + num_reg = (hw_info->reg_dump.end_offset - + hw_info->reg_dump.start_offset)/4; + reg_start_offset = hw_info->reg_dump.start_offset; + for (i = 0; i < num_reg; i++) { + *addr++ = soc_info->mem_block[0]->start + + reg_start_offset + i*4; + *addr++ = cam_io_r(soc_info->reg_map[0].mem_base + (i*4)); + } + + mutex_unlock(&core_info->core_mutex); + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_jpeg_hw_dump_header); + CAM_DBG(CAM_JPEG, "offset %zu", dump_args->offset); + + return 0; +} + int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -418,6 +493,12 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, rc = 0; break; } + case CAM_JPEG_CMD_HW_DUMP: + { + rc = cam_jpeg_enc_hw_dump(jpeg_enc_dev, + cmd_args); + break; + } default: rc = -EINVAL; break; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h index 598158ad1e1f..db505bf5bab7 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_ENC_CORE_H @@ -39,10 +39,16 @@ struct cam_jpeg_enc_int_status { uint32_t stopdone; }; +struct cam_jpeg_enc_reg_dump { + uint32_t start_offset; + uint32_t end_offset; +}; + struct cam_jpeg_enc_device_hw_info { struct cam_jpeg_enc_reg_offsets reg_offset; struct cam_jpeg_enc_regval reg_val; struct cam_jpeg_enc_int_status int_status; + struct cam_jpeg_enc_reg_dump reg_dump; }; enum cam_jpeg_enc_core_state { diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index fa544c7a089e..857aab9dd476 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -86,6 +86,21 @@ static int __cam_lrme_ctx_config_dev_in_activated(struct cam_context *ctx, return rc; } +static int __cam_lrme_ctx_dump_dev_in_activated( + struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc = 0; + + CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); + + rc = cam_context_dump_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_LRME, "Failed to dump device"); + + return rc; +} + static int __cam_lrme_ctx_flush_dev_in_activated(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { @@ -199,6 +214,7 @@ static struct cam_ctx_ops .release_dev = __cam_lrme_ctx_release_dev_in_activated, .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, + .dump_dev = __cam_lrme_ctx_dump_dev_in_activated, }, .crm_ops = {}, .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 40700bbce9e0..537fc48a619e 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -649,6 +649,50 @@ static int cam_lrme_mgr_hw_release(void *hw_mgr_priv, void *hw_release_args) return rc; } +static int cam_lrme_mgr_hw_dump(void *hw_mgr_priv, void *hw_dump_args) +{ + struct cam_hw_dump_args *dump_args = hw_dump_args; + struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_lrme_device *hw_device; + int rc = 0; + uint32_t device_index; + struct cam_lrme_hw_dump_args lrme_dump_args; + + device_index = CAM_LRME_DECODE_DEVICE_INDEX(dump_args->ctxt_to_hw_map); + if (device_index >= hw_mgr->device_count) { + CAM_ERR(CAM_LRME, "Invalid device index %d", device_index); + return -EPERM; + } + + CAM_DBG(CAM_LRME, "Start device index %d", device_index); + + rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device); + if (rc) { + CAM_ERR(CAM_LRME, "Failed to get hw device"); + return rc; + } + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &lrme_dump_args.cpu_addr, + &lrme_dump_args.buf_len); + if (rc) { + CAM_ERR(CAM_LRME, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + return rc; + } + lrme_dump_args.offset = dump_args->offset; + lrme_dump_args.request_id = dump_args->request_id; + + rc = hw_device->hw_intf.hw_ops.process_cmd( + hw_device->hw_intf.hw_priv, + CAM_LRME_HW_CMD_DUMP, + &lrme_dump_args, + sizeof(struct cam_lrme_hw_dump_args)); + CAM_DBG(CAM_LRME, "Offset before %zu after %zu", + dump_args->offset, lrme_dump_args.offset); + dump_args->offset = lrme_dump_args.offset; + return rc; +} + static int cam_lrme_mgr_hw_flush(void *hw_mgr_priv, void *hw_flush_args) { int rc = 0, i; struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv; @@ -1147,6 +1191,7 @@ int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, hw_mgr_intf->hw_flush = cam_lrme_mgr_hw_flush; g_lrme_hw_mgr.event_cb = cam_lrme_dev_buf_done_cb; + hw_mgr_intf->hw_dump = cam_lrme_mgr_hw_dump; cam_lrme_mgr_create_debugfs_entry(); diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c index 7f34de1d2378..dc4df1c57931 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c @@ -3,6 +3,7 @@ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ +#include #include "cam_lrme_hw_core.h" #include "cam_lrme_hw_soc.h" #include "cam_smmu_api.h" @@ -21,6 +22,159 @@ static void cam_lrme_dump_registers(void __iomem *base) cam_io_dump(base, 0x900, (0x928 - 0x900) / 0x4); } +static int cam_lrme_dump_regs_to_buf( + struct cam_lrme_frame_request *req, + struct cam_hw_info *lrme_hw, + struct cam_lrme_hw_dump_args *dump_args) +{ + int i; + uint8_t *dst; + uint32_t *addr, *start; + uint32_t num_reg, min_len; + size_t remain_len; + struct cam_hw_soc_info *soc_info; + struct cam_lrme_hw_dump_header *hdr; + + if (!lrme_hw || !req || !dump_args) { + CAM_ERR(CAM_LRME, "Invalid params %pK, %pK, %pK", + lrme_hw, req, dump_args); + return -EINVAL; + } + soc_info = &lrme_hw->soc_info; + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_LRME, "dump buffer overshoot len %zu offset %zu", + dump_args->buf_len, dump_args->offset); + return -ENOSPC; + } + remain_len = dump_args->buf_len - dump_args->offset; + min_len = sizeof(struct cam_lrme_hw_dump_header) + + soc_info->reg_map[0].size + sizeof(uint32_t); + + if (remain_len < min_len) { + CAM_WARN(CAM_LRME, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_lrme_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_LRME_HW_DUMP_TAG_MAX_LEN, + "LRME_REG:"); + hdr->word_size = sizeof(uint32_t); + addr = (uint32_t *)(dst + sizeof(struct cam_lrme_hw_dump_header)); + start = addr; + *addr++ = soc_info->index; + num_reg = soc_info->reg_map[0].size/4; + for (i = 0; i < num_reg; i++) { + *addr++ = soc_info->mem_block[0]->start + (i*4); + *addr++ = cam_io_r(soc_info->reg_map[0].mem_base + (i*4)); + } + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_lrme_hw_dump_header); + CAM_DBG(CAM_LRME, "offset %zu", dump_args->offset); + return 0; +} + +static int cam_lrme_hw_dump( + struct cam_hw_info *lrme_hw, + struct cam_lrme_hw_dump_args *dump_args) +{ + uint8_t *dst; + ktime_t cur_time; + size_t remain_len; + uint32_t min_len; + uint64_t diff; + uint64_t *addr, *start; + struct timespec64 cur_ts; + struct timespec64 req_ts; + struct cam_lrme_core *lrme_core; + struct cam_lrme_frame_request *req = NULL; + struct cam_lrme_hw_dump_header *hdr; + + 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"); + mutex_unlock(&lrme_hw->hw_mutex); + return 0; + } + + lrme_core = (struct cam_lrme_core *)lrme_hw->core_info; + + if (lrme_core->req_submit && + lrme_core->req_submit->req_id == dump_args->request_id) + req = lrme_core->req_submit; + else if (lrme_core->req_proc && + lrme_core->req_proc->req_id == dump_args->request_id) + req = lrme_core->req_proc; + + if (!req) { + CAM_DBG(CAM_LRME, "LRME req %lld not with hw", + dump_args->request_id); + mutex_unlock(&lrme_hw->hw_mutex); + return 0; + } + + cur_time = ktime_get(); + diff = ktime_us_delta(req->submit_timestamp, cur_time); + cur_ts = ktime_to_timespec64(cur_time); + req_ts = ktime_to_timespec64(req->submit_timestamp); + + if (diff < CAM_LRME_RESPONSE_TIME_THRESHOLD) { + CAM_INFO(CAM_LRME, "No error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + mutex_unlock(&lrme_hw->hw_mutex); + return 0; + } + + CAM_INFO(CAM_LRME, "Error req %lld %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_LRME, "dump buffer overshoot len %zu offset %zu", + dump_args->buf_len, dump_args->offset); + mutex_unlock(&lrme_hw->hw_mutex); + return 0; + } + + remain_len = dump_args->buf_len - dump_args->offset; + min_len = sizeof(struct cam_lrme_hw_dump_header) + + (CAM_LRME_HW_DUMP_NUM_WORDS * sizeof(uint64_t)); + + if (remain_len < min_len) { + CAM_WARN(CAM_LRME, "dump buffer exhaust remain %zu min %u", + remain_len, min_len); + mutex_unlock(&lrme_hw->hw_mutex); + return 0; + } + + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_lrme_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_LRME_HW_DUMP_TAG_MAX_LEN, + "LRME_REQ:"); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + sizeof(struct cam_lrme_hw_dump_header)); + start = addr; + *addr++ = req->req_id; + *addr++ = req_ts.tv_sec; + *addr++ = req_ts.tv_nsec/NSEC_PER_USEC; + *addr++ = cur_ts.tv_sec; + *addr++ = cur_ts.tv_nsec/NSEC_PER_USEC; + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_lrme_hw_dump_header); + cam_lrme_dump_regs_to_buf(req, lrme_hw, dump_args); + mutex_unlock(&lrme_hw->hw_mutex); + return 0; +} + static void cam_lrme_cdm_write_reg_val_pair(uint32_t *buffer, uint32_t *index, uint32_t reg_offset, uint32_t reg_value) { @@ -959,6 +1113,8 @@ int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args, goto error; } + frame_req->submit_timestamp = ktime_get(); + switch (lrme_core->state) { case CAM_LRME_CORE_STATE_PROCESSING: lrme_core->state = CAM_LRME_CORE_STATE_REQ_PROC_PEND; @@ -1268,6 +1424,12 @@ int cam_lrme_hw_process_cmd(void *hw_priv, uint32_t cmd_type, break; } + case CAM_LRME_HW_CMD_DUMP: { + struct cam_lrme_hw_dump_args *dump_args = + (struct cam_lrme_hw_dump_args *)cmd_args; + rc = cam_lrme_hw_dump(lrme_hw, dump_args); + break; + } default: break; } diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h index accb5a8b5827..4c9386c9f046 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_LRME_HW_CORE_H_ @@ -35,6 +35,10 @@ #define CAM_LRME_MAX_REG_PAIR_NUM 60 +#define CAM_LRME_RESPONSE_TIME_THRESHOLD 100000 +#define CAM_LRME_HW_DUMP_TAG_MAX_LEN 32 +#define CAM_LRME_HW_DUMP_NUM_WORDS 5 + /** * enum cam_lrme_irq_set * @@ -432,6 +436,20 @@ struct cam_lrme_hw_info { struct cam_lrme_titan_reg titan_reg; }; +/** + * struct cam_lrme_hw_dump_header : LRME hw dump header + * + * @tag : LRME hw dump header tag + * @size : Size of data + * @word_size : size of each word + */ + +struct cam_lrme_hw_dump_header { + uint8_t tag[CAM_LRME_HW_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + int cam_lrme_hw_process_irq(void *priv, void *data); int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args, uint32_t arg_size); diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h index 161b9b017597..64eb9c11232f 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_LRME_HW_INTF_H_ @@ -59,12 +59,14 @@ enum cam_lrme_cb_type { * @CAM_LRME_HW_CMD_REGISTER_CB : register HW manager callback * @CAM_LRME_HW_CMD_SUBMIT : Submit frame to HW * @CAM_LRME_HW_CMD_DUMP_REGISTER : dump register values + * @CAM_LRME_HW_CMD_DUMP : dump register values to buffer */ enum cam_lrme_hw_cmd_type { CAM_LRME_HW_CMD_PREPARE_HW_UPDATE, CAM_LRME_HW_CMD_REGISTER_CB, CAM_LRME_HW_CMD_SUBMIT, CAM_LRME_HW_CMD_DUMP_REGISTER, + CAM_LRME_HW_CMD_DUMP, }; /** @@ -87,6 +89,7 @@ enum cam_lrme_hw_reset_type { * @hw_device : Pointer to HW device * @hw_update_entries : List of hw_update_entries * @num_hw_update_entries : number of hw_update_entries + * @submit_timestamp : timestamp of submitting request with hw */ struct cam_lrme_frame_request { struct list_head frame_list; @@ -95,6 +98,7 @@ struct cam_lrme_frame_request { struct cam_lrme_device *hw_device; struct cam_hw_update_entry hw_update_entries[CAM_LRME_MAX_HW_ENTRIES]; uint32_t num_hw_update_entries; + ktime_t submit_timestamp; }; /** @@ -192,6 +196,21 @@ struct cam_lrme_hw_submit_args { struct cam_lrme_frame_request *frame_req; }; +/** + * struct cam_lrme_hw_dump_args : Args for dump request + * + * @request_id : Issue request id + * @cpu_addr : start address of the target buffer + * @offset : offset of the buffer + * @buf_len : Length of target buffer + */ +struct cam_lrme_hw_dump_args { + uint64_t request_id; + uintptr_t cpu_addr; + size_t offset; + size_t buf_len; +}; + /** * @brief : API to register LRME hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. @@ -202,4 +221,6 @@ int cam_lrme_hw_init_module(void); * @brief : API to remove LRME Hw from platform framework. */ void cam_lrme_hw_exit_module(void); + #endif /* _CAM_LRME_HW_INTF_H_ */ + From 5ddf0a5cfbcb3f5aec90aebee521d2768b39bf26 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 9 Sep 2019 22:54:06 -0700 Subject: [PATCH 269/790] msm: camera: isp: Add support to obtain frame index This change captures the frame index as part of the IFE top register space at every epoch event. The index is then notified to userspace as part of shutter notification. CRs-Fixed: 2524308 Change-Id: Iac510c452f9ceda86e9f7d69528f22f81e614974 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 44 +++++++++++++---- drivers/cam_isp/cam_isp_context.h | 39 ++++++++------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 48 +++++++++++-------- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 3 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 + .../isp_hw/include/cam_vfe_hw_intf.h | 4 ++ .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 5 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 26 ++++++++++ .../vfe_hw/vfe_top/cam_vfe_camif_ver3.h | 1 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h | 4 +- 10 files changed, 126 insertions(+), 50 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f69e0fc914df..8141d75bc9ca 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -470,6 +470,7 @@ static void __cam_isp_ctx_send_sof_boot_timestamp( req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp; req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; req_msg.u.frame_msg.sof_status = sof_event_status; + req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, "request id:%lld frame number:%lld boot time stamp:0x%llx", @@ -497,6 +498,7 @@ static void __cam_isp_ctx_send_sof_timestamp( req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val; req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; req_msg.u.frame_msg.sof_status = sof_event_status; + req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, "request id:%lld frame number:%lld SOF time stamp:0x%llx", @@ -863,11 +865,20 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( struct cam_isp_context *ctx_isp, void *evt_data) { int rc = 0; + uint64_t request_id = 0; struct cam_req_mgr_trigger_notify notify; struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; - uint64_t request_id = 0; + struct cam_isp_hw_epoch_event_data *epoch_done_event_data = + (struct cam_isp_hw_epoch_event_data *)evt_data; + + if (!evt_data) { + CAM_ERR(CAM_ISP, "invalid event data"); + return -EINVAL; + } + + ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; /* * notify reqmgr with sof signal. Note, due to scheduling delay @@ -1082,11 +1093,19 @@ end: static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { - struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; - struct cam_context *ctx = ctx_isp->base; - uint64_t request_id = 0; + uint64_t request_id = 0; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_epoch_event_data *epoch_done_event_data = + (struct cam_isp_hw_epoch_event_data *)evt_data; + if (!evt_data) { + CAM_ERR(CAM_ISP, "invalid event data"); + return -EINVAL; + } + + ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; if (list_empty(&ctx->wait_req_list)) { /* * If no wait req in epoch, this is an error case. @@ -1248,10 +1267,19 @@ static int __cam_isp_ctx_buf_done_in_bubble( static int __cam_isp_ctx_epoch_in_bubble_applied( struct cam_isp_context *ctx_isp, void *evt_data) { - struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; - struct cam_context *ctx = ctx_isp->base; uint64_t request_id = 0; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_epoch_event_data *epoch_done_event_data = + (struct cam_isp_hw_epoch_event_data *)evt_data; + + if (!evt_data) { + CAM_ERR(CAM_ISP, "invalid event data"); + return -EINVAL; + } + + ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; /* * This means we missed the reg upd ack. So we need to diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index c29a57fc33e4..3e4e601b9bfe 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -166,6 +166,8 @@ struct cam_isp_context_req_id_info { * * @base: Common context object pointer * @frame_id: Frame id tracking for the isp context + * @frame_id_meta: Frame id read every epoch for the ctx + * meta from the sensor * @substate_actiavted: Current substate for the activated state. * @process_bubble: Atomic variable to check if ctx is still * processing bubble. @@ -195,27 +197,28 @@ struct cam_isp_context_req_id_info { * */ struct cam_isp_context { - struct cam_context *base; + struct cam_context *base; - int64_t frame_id; - enum cam_isp_ctx_activated_substate substate_activated; - atomic_t process_bubble; - uint32_t bubble_frame_cnt; - struct cam_ctx_ops *substate_machine; - struct cam_isp_ctx_irq_ops *substate_machine_irq; + int64_t frame_id; + uint32_t frame_id_meta; + uint32_t substate_activated; + atomic_t process_bubble; + uint32_t bubble_frame_cnt; + struct cam_ctx_ops *substate_machine; + struct cam_isp_ctx_irq_ops *substate_machine_irq; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; - struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; - void *hw_ctx; - uint64_t sof_timestamp_val; - uint64_t boot_timestamp; - int32_t active_req_cnt; - int64_t reported_req_id; - uint32_t subscribe_event; - int64_t last_applied_req_id; - atomic64_t state_monitor_head; - struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ + void *hw_ctx; + uint64_t sof_timestamp_val; + uint64_t boot_timestamp; + int32_t active_req_cnt; + int64_t reported_req_id; + uint32_t subscribe_event; + int64_t last_applied_req_id; + atomic64_t state_monitor_head; + struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; struct cam_isp_context_req_id_info req_info; bool rdi_only_context; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7bf3c518cbb7..44c42e2e71c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4775,29 +4775,36 @@ static int cam_isp_blob_core_cfg_update( list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { clk_rate = 0; - if (!hw_mgr_res->hw_res[i] || - hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF) + 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) { - vfe_core_config.node_res = - hw_mgr_res->hw_res[i]; + if ((hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_CAMIF) || + (hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_PDLIB)) { + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + vfe_core_config.node_res = + hw_mgr_res->hw_res[i]; - memcpy(&vfe_core_config.core_config, - core_config, - sizeof(struct cam_isp_core_config)); + memcpy(&vfe_core_config.core_config, + core_config, + sizeof( + struct cam_isp_core_config)); - rc = hw_intf->hw_ops.process_cmd( - hw_intf->hw_priv, - CAM_ISP_HW_CMD_CORE_CONFIG, - &vfe_core_config, - sizeof( - struct cam_vfe_core_config_args)); - if (rc) - CAM_ERR(CAM_ISP, "Core cfg parse fail"); - } else { - CAM_WARN(CAM_ISP, "NULL hw_intf!"); + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CORE_CONFIG, + &vfe_core_config, + sizeof( + struct cam_vfe_core_config_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Core cfg parse fail"); + } else { + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } } } } @@ -6434,6 +6441,9 @@ static int cam_ife_hw_mgr_handle_hw_epoch( if (!rc) { if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; + + epoch_done_event_data.frame_id_meta = + event_info->th_reg_val; ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); } diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index a0c0e60a30a4..86b47da0b313 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -170,10 +170,11 @@ struct cam_isp_hw_reg_update_event_data { * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH * * @timestamp: Time stamp for the epoch event - * + * @frame_id_meta: Frame id value corresponding to this frame */ struct cam_isp_hw_epoch_event_data { uint64_t timestamp; + uint32_t frame_id_meta; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index def462459743..22b2bf1f534f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -174,6 +174,7 @@ struct cam_isp_resource_node { * @res_id: Unique resource ID * @hw_idx: IFE hw index * @err_type: Error type if any + * @th_reg_val: Any critical register value captured during th * */ struct cam_isp_hw_event_info { @@ -181,6 +182,7 @@ struct cam_isp_hw_event_info { uint32_t res_id; uint32_t hw_idx; uint32_t err_type; + uint32_t th_reg_val; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 24ae56de5014..c3f2aabf5656 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -263,11 +263,15 @@ struct cam_vfe_bw_control_args { * @list: list_head node for the payload * @irq_reg_val: IRQ and Error register values, read when IRQ was * handled + * @th_reg_val: Value of any critical register that needs to be + * read at th to avoid any latencies in bh processing + * * @ts: Timestamp */ struct cam_vfe_top_irq_evt_payload { struct list_head list; uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t th_reg_val; struct cam_isp_timestamp ts; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index ae65df7c1126..0cd59de02f46 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ @@ -77,6 +77,7 @@ static struct cam_vfe_camif_ver3_reg_data vfe_480_camif_reg_data = { .error_irq_mask0 = 0x82000200, .error_irq_mask2 = 0x30301F80, .subscribe_irq_mask1 = 0x00000007, + .frame_id_irq_mask = 0x400, .enable_diagnostic_hw = 0x1, .pp_camif_cfg_en_shift = 0, .pp_camif_cfg_ife_out_en_shift = 8, @@ -101,7 +102,7 @@ static struct cam_vfe_top_ver3_reg_offset_common vfe480_top_common_reg = { .ahb_cgc_ovd = 0x00000024, .noc_cgc_ovd = 0x00000028, .trigger_cdm_events = 0x00000090, - .sbi_frame_idx = 0x00000110, + .custom_frame_idx = 0x00000110, .dsp_status = 0x0000007C, .diag_config = 0x00000064, .diag_sensor_status_0 = 0x00000068, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index e558e9087fe8..d9fe166d3981 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -507,6 +507,9 @@ static int cam_vfe_camif_ver3_resource_start( irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = rsrc_data->reg_data->sof_irq_mask; + if (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->frame_id_irq_mask; if (!rsrc_data->sof_irq_handle) { rsrc_data->sof_irq_handle = cam_irq_controller_subscribe_irq( @@ -1191,10 +1194,21 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, } cam_isp_hw_get_timestamp(&evt_payload->ts); + evt_payload->th_reg_val = 0; for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + /* Read frame_id meta at every epoch if custom hw is enabled */ + if (evt_payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->epoch0_irq_mask) { + if ((camif_priv->common_reg->custom_frame_idx) && + (camif_priv->cam_common_cfg.input_mux_sel_pp & 0x3)) + evt_payload->th_reg_val = cam_io_r_mb( + camif_priv->mem_base + + camif_priv->common_reg->custom_frame_idx); + } + th_payload->evt_payload_priv = evt_payload; CAM_DBG(CAM_ISP, "Exit"); @@ -1210,6 +1224,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; + uint32_t val = 0; int i = 0; if (!handler_priv || !evt_payload_priv) { @@ -1229,6 +1244,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, evt_info.hw_idx = camif_node->hw_intf->hw_idx; evt_info.res_id = camif_node->res_id; evt_info.res_type = camif_node->res_type; + evt_info.th_reg_val = 0; if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->sof_irq_mask) { @@ -1259,6 +1275,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); + evt_info.th_reg_val = payload->th_reg_val; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1294,6 +1311,15 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, cam_vfe_camif_ver3_reg_dump(camif_node); } + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + & camif_priv->reg_data->frame_id_irq_mask) { + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->common_reg->custom_frame_idx); + CAM_DBG(CAM_ISP, + "VFE:%d Frame id change to: %u", evt_info.hw_idx, + val); + } + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h index e611d1ac62f2..6e02c58ee63b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -53,6 +53,7 @@ struct cam_vfe_camif_ver3_reg_data { uint32_t error_irq_mask0; uint32_t error_irq_mask2; uint32_t subscribe_irq_mask1; + uint32_t frame_id_irq_mask; uint32_t enable_diagnostic_hw; uint32_t pp_camif_cfg_en_shift; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h index 14c96097cdf6..4a24ba6ddf76 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_TOP_VER3_H_ @@ -41,7 +41,7 @@ struct cam_vfe_top_ver3_reg_offset_common { uint32_t reg_update_cmd; uint32_t trigger_cdm_events; uint32_t violation_status; - uint32_t sbi_frame_idx; + uint32_t custom_frame_idx; uint32_t dsp_status; uint32_t diag_config; uint32_t diag_sensor_status_0; From e3f5738e43d814ab9b66a586dd4fd175cbf1ce13 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 14 Oct 2019 17:09:54 +0530 Subject: [PATCH 270/790] msm: camera: isp: LDAR Dump ISP information When user space detects an error or does not receive response for a request, Lets do a reset(LDAR) is triggered. Before LDAR, user space sends flush command to the kernel space. In order to debug the cause for this situation and to dump the information, user space sends a dump command to kernel space before sending flush. As a part of this command, it passes the culprit request id and the buffer into which the information can be dumped. Kernel space traverses across the drivers and find the culprit hw and dumps the relevant information in the buffer. This data is written to a file for offline processing. This commit dumps the IFE, CSID registers, LUT tables and context information, cmd buffers, timestamps information for submit, apply, RUP, epoch and buffdones of the last 20 requests. CRs-Fixed: 2612116 Change-Id: If83db59458c1e5ad778f3fa90cbc730122491c54 Signed-off-by: Gaurav Jindal --- drivers/cam_cdm/cam_cdm_util.c | 168 +++++++ drivers/cam_cdm/cam_cdm_util.h | 43 ++ drivers/cam_isp/cam_isp_context.c | 448 +++++++++++++++++- drivers/cam_isp/cam_isp_context.h | 71 +++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 165 ++++++- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 4 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 66 +++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 39 ++ .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 29 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 29 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 29 +- .../vfe_hw/vfe_top/cam_vfe_top_common.h | 30 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 142 +++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h | 3 +- drivers/cam_utils/cam_soc_util.c | 292 +++++++++++- drivers/cam_utils/cam_soc_util.h | 55 ++- 17 files changed, 1568 insertions(+), 46 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_util.c b/drivers/cam_cdm/cam_cdm_util.c index 89951d24d0ef..c9eee75f1c43 100644 --- a/drivers/cam_cdm/cam_cdm_util.c +++ b/drivers/cam_cdm/cam_cdm_util.c @@ -823,3 +823,171 @@ void cam_cdm_util_dump_cmd_buf( } } while (buf_now <= cmd_buf_end); } + +static uint32_t cam_cdm_util_dump_reg_cont_cmd_v2( + uint32_t *cmd_buf_addr, + struct cam_cdm_cmd_buf_dump_info *dump_info) +{ + int i; + long ret; + uint8_t *dst; + size_t remain_len; + uint32_t *temp_ptr = cmd_buf_addr; + uint32_t *addr, *start; + uint32_t min_len; + struct cdm_regcontinuous_cmd *p_regcont_cmd; + struct cam_cdm_cmd_dump_header *hdr; + + p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr; + temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); + ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT); + + min_len = (sizeof(uint32_t) * p_regcont_cmd->count) + + sizeof(struct cam_cdm_cmd_dump_header) + + (2 * sizeof(uint32_t)); + remain_len = dump_info->dst_max_size - dump_info->dst_offset; + + if (remain_len < min_len) { + CAM_WARN_RATE_LIMIT(CAM_CDM, + "Dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return ret; + } + + dst = (char *)dump_info->dst_start + dump_info->dst_offset; + hdr = (struct cam_cdm_cmd_dump_header *)dst; + scnprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_CONT:"); + hdr->word_size = sizeof(uint32_t); + addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header)); + start = addr; + *addr++ = p_regcont_cmd->offset; + *addr++ = p_regcont_cmd->count; + for (i = 0; i < p_regcont_cmd->count; i++) { + *addr = *temp_ptr; + temp_ptr++; + addr++; + ret++; + } + hdr->size = hdr->word_size * (addr - start); + dump_info->dst_offset += hdr->size + + sizeof(struct cam_cdm_cmd_dump_header); + + return ret; +} + +static uint32_t cam_cdm_util_dump_reg_random_cmd_v2( + uint32_t *cmd_buf_addr, + struct cam_cdm_cmd_buf_dump_info *dump_info) +{ + int i; + long ret; + uint8_t *dst; + uint32_t *temp_ptr = cmd_buf_addr; + uint32_t *addr, *start; + size_t remain_len; + uint32_t min_len; + struct cdm_regrandom_cmd *p_regrand_cmd; + struct cam_cdm_cmd_dump_header *hdr; + + p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr; + temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); + ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM); + + min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) + + sizeof(struct cam_cdm_cmd_dump_header) + sizeof(uint32_t); + remain_len = dump_info->dst_max_size - dump_info->dst_offset; + + if (remain_len < min_len) { + CAM_WARN_RATE_LIMIT(CAM_CDM, + "Dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return ret; + } + + dst = (char *)dump_info->dst_start + dump_info->dst_offset; + hdr = (struct cam_cdm_cmd_dump_header *)dst; + scnprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_RANDOM:"); + hdr->word_size = sizeof(uint32_t); + addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header)); + start = addr; + *addr++ = p_regrand_cmd->count; + for (i = 0; i < p_regrand_cmd->count; i++) { + addr[0] = temp_ptr[0] & CAM_CDM_REG_OFFSET_MASK; + addr[1] = temp_ptr[1]; + temp_ptr += 2; + addr += 2; + ret += 2; + } + hdr->size = hdr->word_size * (addr - start); + dump_info->dst_offset += hdr->size + + sizeof(struct cam_cdm_cmd_dump_header); + return ret; +} + +int cam_cdm_util_dump_cmd_bufs_v2( + struct cam_cdm_cmd_buf_dump_info *dump_info) +{ + uint32_t cmd; + uint32_t *buf_now; + int rc = 0; + + if (!dump_info || !dump_info->src_start || !dump_info->src_end || + !dump_info->dst_start) { + CAM_INFO(CAM_CDM, "Invalid args"); + return -EINVAL; + } + + buf_now = dump_info->src_start; + do { + if (dump_info->dst_offset >= dump_info->dst_max_size) { + CAM_WARN(CAM_CDM, + "Dump overshoot offset %zu size %zu", + dump_info->dst_offset, + dump_info->dst_max_size); + return -ENOSPC; + } + cmd = *buf_now; + cmd = cmd >> CAM_CDM_COMMAND_OFFSET; + + switch (cmd) { + case CAM_CDM_CMD_DMI: + case CAM_CDM_CMD_DMI_32: + case CAM_CDM_CMD_DMI_64: + buf_now += cdm_get_cmd_header_size(CAM_CDM_CMD_DMI); + break; + case CAM_CDM_CMD_REG_CONT: + buf_now += cam_cdm_util_dump_reg_cont_cmd_v2(buf_now, + dump_info); + break; + case CAM_CDM_CMD_REG_RANDOM: + buf_now += cam_cdm_util_dump_reg_random_cmd_v2(buf_now, + dump_info); + break; + case CAM_CDM_CMD_BUFF_INDIRECT: + buf_now += cdm_get_cmd_header_size( + CAM_CDM_CMD_BUFF_INDIRECT); + break; + case CAM_CDM_CMD_GEN_IRQ: + buf_now += cdm_get_cmd_header_size( + CAM_CDM_CMD_GEN_IRQ); + break; + case CAM_CDM_CMD_WAIT_EVENT: + buf_now += cdm_get_cmd_header_size( + CAM_CDM_CMD_WAIT_EVENT); + break; + case CAM_CDM_CMD_CHANGE_BASE: + buf_now += cdm_get_cmd_header_size( + CAM_CDM_CMD_CHANGE_BASE); + break; + case CAM_CDM_CMD_PERF_CTRL: + buf_now += cdm_get_cmd_header_size( + CAM_CDM_CMD_PERF_CTRL); + break; + default: + CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x", cmd); + buf_now++; + break; + } + } while (buf_now <= dump_info->src_end); + return rc; +} diff --git a/drivers/cam_cdm/cam_cdm_util.h b/drivers/cam_cdm/cam_cdm_util.h index 4d4095072e99..875c9215e6f8 100644 --- a/drivers/cam_cdm/cam_cdm_util.h +++ b/drivers/cam_cdm/cam_cdm_util.h @@ -6,6 +6,9 @@ #ifndef _CAM_CDM_UTIL_H_ #define _CAM_CDM_UTIL_H_ +/* Max len for tag name for header while dumping cmd buffer*/ +#define CAM_CDM_CMD_TAG_MAX_LEN 32 + #include enum cam_cdm_command { @@ -180,6 +183,34 @@ uint32_t *(*cdm_write_wait_prefetch_disable)( uint32_t mask2); }; +/** + * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info + * @dst_offset: dst offset + * @dst_max_size max size of destination buffer + * @src_start: source start address + * @src_end: source end address + * @dst_start: dst start address + */ +struct cam_cdm_cmd_buf_dump_info { + size_t dst_offset; + size_t dst_max_size; + uint32_t *src_start; + uint32_t *src_end; + uintptr_t dst_start; +}; + +/** + * struct cam_cdm_cmd_dump_header- Camera CDM dump header + * @tag: tag name for header + * @size: size of data + * @word_size: size of each word + */ +struct cam_cdm_cmd_dump_header { + uint8_t tag[CAM_CDM_CMD_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + /** * cam_cdm_util_log_cmd_bufs() * @@ -192,6 +223,18 @@ uint32_t *(*cdm_write_wait_prefetch_disable)( void cam_cdm_util_dump_cmd_buf( uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end); +/** + * cam_cdm_util_dump_cmd_bufs_v2() + * + * @brief: Util function to cdm command buffers + * to a buffer + * + * @dump_info: Information about source and destination buffers + * + * return SUCCESS/FAILURE + */ +int cam_cdm_util_dump_cmd_bufs_v2( + struct cam_cdm_cmd_buf_dump_info *dump_info); #endif /* _CAM_CDM_UTIL_H_ */ diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 8141d75bc9ca..3f991dc7b136 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -24,9 +24,9 @@ static const char isp_dev_name[] = "cam-isp"; static struct cam_isp_ctx_debug isp_ctx_debug; -#define INC_STATE_MONITOR_HEAD(head, ret) \ +#define INC_HEAD(head, max_entries, ret) \ div_u64_rem(atomic64_add_return(1, head),\ - CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, (ret)) + max_entries, (ret)) static int cam_isp_context_dump_active_request(void *data, unsigned long iova, uint32_t buf_info); @@ -34,6 +34,150 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +static const char *__cam_isp_evt_val_to_type( + uint32_t evt_id) +{ + switch (evt_id) { + case CAM_ISP_CTX_EVENT_SUBMIT: + return "SUBMIT"; + case CAM_ISP_CTX_EVENT_APPLY: + return "APPLY"; + case CAM_ISP_CTX_EVENT_EPOCH: + return "EPOCH"; + case CAM_ISP_CTX_EVENT_RUP: + return "RUP"; + case CAM_ISP_CTX_EVENT_BUFDONE: + return "BUFDONE"; + default: + return "CAM_ISP_EVENT_INVALID"; + } +} + +static void __cam_isp_ctx_update_event_record( + struct cam_isp_context *ctx_isp, + enum cam_isp_ctx_event event, + struct cam_ctx_request *req) +{ + int iterator = 0; + ktime_t cur_time; + struct cam_isp_ctx_req *req_isp; + + if (!ctx_isp) { + CAM_ERR(CAM_ISP, "Invalid Args"); + return; + } + switch (event) { + case CAM_ISP_CTX_EVENT_EPOCH: + case CAM_ISP_CTX_EVENT_RUP: + case CAM_ISP_CTX_EVENT_BUFDONE: + break; + case CAM_ISP_CTX_EVENT_SUBMIT: + case CAM_ISP_CTX_EVENT_APPLY: + if (!req) { + CAM_ERR(CAM_ISP, "Invalid arg for event %d", event); + return; + } + break; + default: + break; + } + + INC_HEAD(&ctx_isp->event_record_head[event], + CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES, &iterator); + cur_time = ktime_get(); + if (req) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + ctx_isp->event_record[event][iterator].req_id = + req->request_id; + req_isp->event_timestamp[event] = cur_time; + } else { + ctx_isp->event_record[event][iterator].req_id = 0; + } + ctx_isp->event_record[event][iterator].timestamp = cur_time; +} + +static int __cam_isp_ctx_dump_event_record( + struct cam_isp_context *ctx_isp, + uintptr_t cpu_addr, + size_t buf_len, + size_t *offset) +{ + int i, j; + int index; + size_t remain_len; + uint8_t *dst; + uint32_t oldest_entry, num_entries; + uint32_t min_len; + uint64_t *addr, *start; + uint64_t state_head; + struct timespec64 ts; + struct cam_isp_context_dump_header *hdr; + struct cam_isp_context_event_record *record; + + if (!cpu_addr || !buf_len || !offset || !ctx_isp) { + CAM_ERR(CAM_ISP, "Invalid args %pK %zu %pK %pK", + cpu_addr, buf_len, offset, ctx_isp); + return -EINVAL; + } + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) { + state_head = atomic64_read(&ctx_isp->event_record_head[i]); + + if (state_head == -1) { + return 0; + } else if (state_head < CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) { + num_entries = state_head + 1; + oldest_entry = 0; + } else { + num_entries = CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES; + div_u64_rem(state_head + 1, + CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES, + &oldest_entry); + } + index = oldest_entry; + + if (buf_len <= *offset) { + CAM_WARN(CAM_ISP, + "Dump buffer overshoot len %zu offset %zu", + buf_len, *offset); + return -ENOSPC; + } + + min_len = sizeof(struct cam_isp_context_dump_header) + + ((num_entries * CAM_ISP_CTX_DUMP_EVENT_NUM_WORDS) * + sizeof(uint64_t)); + remain_len = buf_len - *offset; + + if (remain_len < min_len) { + CAM_WARN(CAM_ISP, + "Dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + dst = (uint8_t *)cpu_addr + *offset; + hdr = (struct cam_isp_context_dump_header *)dst; + scnprintf(hdr->tag, + CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_EVT_%s:", + __cam_isp_evt_val_to_type(i)); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + + sizeof(struct cam_isp_context_dump_header)); + start = addr; + for (j = 0; j < num_entries; j++) { + record = &ctx_isp->event_record[i][index]; + ts = ktime_to_timespec64(record->timestamp); + *addr++ = record->req_id; + *addr++ = ts.tv_sec; + *addr++ = ts.tv_nsec/NSEC_PER_USEC; + index = (index + 1) % + CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES; + } + hdr->size = hdr->word_size * (addr - start); + *offset += hdr->size + + sizeof(struct cam_isp_context_dump_header); + } + return 0; +} + static void __cam_isp_ctx_update_state_monitor_array( struct cam_isp_context *ctx_isp, enum cam_isp_state_change_trigger trigger_type, @@ -41,7 +185,8 @@ static void __cam_isp_ctx_update_state_monitor_array( { int iterator; - INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head, &iterator); + INC_HEAD(&ctx_isp->state_monitor_head, + CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES, &iterator); ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state = ctx_isp->substate_activated; @@ -162,13 +307,19 @@ static int cam_isp_context_info_dump(void *context, return 0; } -static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) +static int cam_isp_ctx_dump_req( + struct cam_isp_ctx_req *req_isp, + uintptr_t cpu_addr, + size_t buf_len, + size_t *offset, + bool dump_to_buff) { int i = 0, rc = 0; size_t len = 0; uint32_t *buf_addr; uint32_t *buf_start, *buf_end; size_t remain_len = 0; + struct cam_cdm_cmd_buf_dump_info dump_info; for (i = 0; i < req_isp->num_cfg; i++) { rc = cam_packet_util_get_cmd_mem_addr( @@ -182,7 +333,7 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) CAM_ERR(CAM_ISP, "Invalid offset exp %u actual %u", req_isp->cfg[i].offset, (uint32_t)len); - return; + return rc; } remain_len = len - req_isp->cfg[i].offset; @@ -192,16 +343,33 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) "Invalid len exp %u remain_len %u", req_isp->cfg[i].len, (uint32_t)remain_len); - return; + return rc; } 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); - cam_cdm_util_dump_cmd_buf(buf_start, buf_end); + if (dump_to_buff) { + if (!cpu_addr || !offset || !buf_len) { + CAM_ERR(CAM_ISP, "Invalid args"); + break; + } + dump_info.src_start = buf_start; + dump_info.src_end = buf_end; + dump_info.dst_start = cpu_addr; + dump_info.dst_offset = *offset; + dump_info.dst_max_size = buf_len; + rc = cam_cdm_util_dump_cmd_bufs_v2(&dump_info); + *offset = dump_info.dst_offset; + if (rc) + return rc; + } else { + cam_cdm_util_dump_cmd_buf(buf_start, buf_end); + } } } + return rc; } static int __cam_isp_ctx_enqueue_request_in_order( @@ -210,6 +378,7 @@ static int __cam_isp_ctx_enqueue_request_in_order( struct cam_ctx_request *req_current; struct cam_ctx_request *req_prev; struct list_head temp_list; + struct cam_isp_context *ctx_isp; INIT_LIST_HEAD(&temp_list); spin_lock_bh(&ctx->lock); @@ -240,6 +409,9 @@ static int __cam_isp_ctx_enqueue_request_in_order( } } } + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_SUBMIT, req); spin_unlock_bh(&ctx->lock); return 0; } @@ -729,6 +901,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_BUFDONE, req); return rc; } @@ -837,6 +1011,8 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( 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); + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_RUP, req); } else { /* no io config, so the request is completed. */ list_add_tail(&req->list, &ctx->free_req_list); @@ -944,6 +1120,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( if (req->request_id > ctx_isp->reported_req_id) { request_id = req->request_id; ctx_isp->reported_req_id = request_id; + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, req); break; } } @@ -1117,7 +1295,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, /* Send SOF event as empty frame*/ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); - + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, NULL); goto end; } @@ -1167,7 +1346,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, } __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_ERROR); - + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, req); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( @@ -1294,6 +1474,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( CAM_ERR(CAM_ISP, "ctx:%d No pending request.", ctx->ctx_id); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, NULL); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; goto end; @@ -1345,13 +1527,21 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( ctx_isp->reported_req_id = request_id; __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_ERROR); - } else + + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, req); + } else { __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); - } else + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, NULL); + } + } else { __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); - + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_EPOCH, NULL); + } ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( @@ -1441,7 +1631,7 @@ 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; if (error_event_data->enable_req_dump) - cam_isp_ctx_dump_req(req_isp); + rc = cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false); __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req_to_dump->request_id); @@ -2109,6 +2299,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state( __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, req->request_id); + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_APPLY, req); } end: return rc; @@ -2186,6 +2378,200 @@ static int __cam_isp_ctx_apply_req_in_bubble( return rc; } +static int __cam_isp_ctx_dump_req_info( + struct cam_context *ctx, + struct cam_ctx_request *req, + uintptr_t cpu_addr, + size_t buf_len, + size_t *offset) +{ + int i, rc; + uint8_t *dst; + int32_t *addr, *start; + uint32_t min_len; + size_t remain_len; + struct cam_isp_ctx_req *req_isp; + struct cam_isp_context *ctx_isp; + struct cam_isp_context_dump_header *hdr; + + if (!req || !ctx || !offset || !cpu_addr || !buf_len) { + CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK %pK %zu", + req, ctx, offset, buf_len); + return -EINVAL; + } + req_isp = (struct cam_isp_ctx_req *)req->req_priv; + ctx_isp = (struct cam_isp_context *)ctx->ctx_priv; + + if (buf_len <= *offset) { + CAM_WARN(CAM_ISP, "Dump buffer overshoot len %zu offset %zu", + buf_len, *offset); + return -ENOSPC; + } + + remain_len = buf_len - *offset; + min_len = sizeof(struct cam_isp_context_dump_header) + + (CAM_ISP_CTX_DUMP_REQUEST_NUM_WORDS * + req_isp->num_fence_map_out * + sizeof(int32_t)); + + if (remain_len < min_len) { + CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + + dst = (uint8_t *)cpu_addr + *offset; + hdr = (struct cam_isp_context_dump_header *)dst; + hdr->word_size = sizeof(int32_t); + scnprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, + "ISP_OUT_FENCE:"); + addr = (int32_t *)(dst + sizeof(struct cam_isp_context_dump_header)); + start = addr; + for (i = 0; i < req_isp->num_fence_map_out; i++) { + *addr++ = req_isp->fence_map_out[i].resource_handle; + *addr++ = req_isp->fence_map_out[i].sync_id; + } + hdr->size = hdr->word_size * (addr - start); + *offset += hdr->size + sizeof(struct cam_isp_context_dump_header); + rc = cam_isp_ctx_dump_req(req_isp, cpu_addr, buf_len, + offset, true); + return rc; +} + +static int __cam_isp_ctx_dump_in_top_state( + struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump_info) +{ + int rc = 0; + bool dump_only_event_record = false; + size_t buf_len; + size_t remain_len; + uint8_t *dst; + ktime_t cur_time; + uint32_t min_len; + uint64_t diff; + uint64_t *addr, *start; + uintptr_t cpu_addr; + struct timespec64 ts; + struct cam_isp_context *ctx_isp; + struct cam_ctx_request *req = NULL; + struct cam_isp_ctx_req *req_isp; + struct cam_ctx_request *req_temp; + struct cam_hw_dump_args dump_args; + struct cam_isp_context_dump_header *hdr; + + spin_lock_bh(&ctx->lock); + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + if (req->request_id == dump_info->req_id) { + CAM_INFO(CAM_ISP, "isp dump active list req: %lld", + dump_info->req_id); + goto hw_dump; + } + } + list_for_each_entry_safe(req, req_temp, + &ctx->wait_req_list, list) { + if (req->request_id == dump_info->req_id) { + CAM_INFO(CAM_ISP, "isp dump wait list req: %lld", + dump_info->req_id); + goto hw_dump; + } + } + spin_unlock_bh(&ctx->lock); + return rc; +hw_dump: + rc = cam_mem_get_cpu_buf(dump_info->buf_handle, + &cpu_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_ISP, "Invalid handle %u rc %d", + dump_info->buf_handle, rc); + spin_unlock_bh(&ctx->lock); + return rc; + } + if (buf_len <= dump_info->offset) { + spin_unlock_bh(&ctx->lock); + CAM_WARN(CAM_ISP, "Dump buffer overshoot len %zu offset %zu", + buf_len, dump_info->offset); + return -ENOSPC; + } + + remain_len = buf_len - dump_info->offset; + min_len = sizeof(struct cam_isp_context_dump_header) + + (CAM_ISP_CTX_DUMP_NUM_WORDS * sizeof(uint64_t)); + + if (remain_len < min_len) { + spin_unlock_bh(&ctx->lock); + CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu min %u", + remain_len, min_len); + return -ENOSPC; + } + + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + cur_time = ktime_get(); + diff = ktime_us_delta( + req_isp->event_timestamp[CAM_ISP_CTX_EVENT_APPLY], + cur_time); + if (diff < CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD) { + CAM_INFO(CAM_ISP, "req %lld found no error", + req->request_id); + dump_only_event_record = true; + } + dst = (uint8_t *)cpu_addr + dump_info->offset; + hdr = (struct cam_isp_context_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, + "ISP_CTX_DUMP:"); + hdr->word_size = sizeof(uint64_t); + addr = (uint64_t *)(dst + + sizeof(struct cam_isp_context_dump_header)); + start = addr; + *addr++ = req->request_id; + ts = ktime_to_timespec64( + req_isp->event_timestamp[CAM_ISP_CTX_EVENT_APPLY]); + *addr++ = ts.tv_sec; + *addr++ = ts.tv_nsec/NSEC_PER_USEC; + ts = ktime_to_timespec64(cur_time); + *addr++ = ts.tv_sec; + *addr++ = ts.tv_nsec/NSEC_PER_USEC; + hdr->size = hdr->word_size * (addr - start); + dump_info->offset += hdr->size + + sizeof(struct cam_isp_context_dump_header); + + rc = __cam_isp_ctx_dump_event_record(ctx_isp, cpu_addr, + buf_len, &dump_info->offset); + if (rc) { + CAM_ERR(CAM_ISP, "Dump event fail %lld", + req->request_id); + spin_unlock_bh(&ctx->lock); + return rc; + } + if (dump_only_event_record) { + spin_unlock_bh(&ctx->lock); + return rc; + } + rc = __cam_isp_ctx_dump_req_info(ctx, req, cpu_addr, + buf_len, &dump_info->offset); + if (rc) { + CAM_ERR(CAM_ISP, "Dump Req info fail %lld", + req->request_id); + spin_unlock_bh(&ctx->lock); + return rc; + } + spin_unlock_bh(&ctx->lock); + + if (ctx->hw_mgr_intf->hw_dump) { + dump_args.offset = dump_info->offset; + dump_args.request_id = dump_info->req_id; + dump_args.buf_handle = dump_info->buf_handle; + dump_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + rc = ctx->hw_mgr_intf->hw_dump( + ctx->hw_mgr_intf->hw_mgr_priv, + &dump_args); + dump_info->offset = dump_args.offset; + } + return rc; +} + static int __cam_isp_ctx_flush_req(struct cam_context *ctx, struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req) { @@ -2749,7 +3135,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( struct cam_isp_context *ctx_isp, void *evt_data) { - struct cam_ctx_request *req; + 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; @@ -2809,12 +3195,15 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); - + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_RUP, req); return 0; error: /* Send SOF event as idle frame*/ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_RUP, NULL); /* * There is no request in the pending list, move the sub state machine @@ -2974,6 +3363,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; + int i; if (ctx_isp->hw_ctx) { rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx; @@ -2994,6 +3384,8 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, atomic64_set(&ctx_isp->state_monitor_head, -1); + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx_isp->event_record_head[i], -1); /* * Ideally, we should never have any active request here. * But we still add some sanity check code here to help the debug @@ -3023,6 +3415,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, struct cam_release_dev_cmd *cmd) { int rc = 0; + int i; struct cam_hw_release_args rel_arg; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; @@ -3054,7 +3447,8 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->req_info.last_bufdone_req_id = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); - + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx_isp->event_record_head[i], -1); /* * Ideally, we should never have any active request here. * But we still add some sanity check code here to help the debug @@ -3279,6 +3673,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { int rc = 0; + int i; struct cam_hw_acquire_args param; struct cam_isp_resource *isp_res = NULL; struct cam_create_dev_hdl req_hdl_param; @@ -3391,6 +3786,8 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; atomic64_set(&ctx_isp->state_monitor_head, -1); + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx_isp->event_record_head[i], -1); kfree(isp_res); isp_res = NULL; @@ -3441,6 +3838,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, void *args) { int rc = 0; + int i; struct cam_acquire_hw_cmd_v1 *cmd = (struct cam_acquire_hw_cmd_v1 *)args; struct cam_hw_acquire_args param; @@ -3546,6 +3944,9 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, atomic64_set(&ctx_isp->state_monitor_head, -1); + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx_isp->event_record_head[i], -1); + trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Acquire success on session_hdl 0x%xs ctx_type %d ctx_id %u", @@ -3855,6 +4256,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; + int i; struct cam_isp_start_args start_isp; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; @@ -3911,6 +4313,9 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, atomic64_set(&ctx_isp->state_monitor_head, -1); + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx_isp->event_record_head[i], -1); + /* * In case of CSID TPG we might receive SOF and RUP IRQs * before hw_mgr_intf->hw_start has returned. So move @@ -3941,7 +4346,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, ctx->state = CAM_CTX_READY; trace_cam_context_state("ISP", ctx); if (rc == -ETIMEDOUT) - cam_isp_ctx_dump_req(req_isp); + rc = cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false); list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); goto end; @@ -4070,6 +4475,9 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( atomic_set(&ctx_isp->process_bubble, 0); atomic64_set(&ctx_isp->state_monitor_head, -1); + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx_isp->event_record_head[i], -1); + CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u", ctx->state, ctx->ctx_id); @@ -4326,6 +4734,7 @@ static struct cam_ctx_ops .unlink = __cam_isp_ctx_unlink_in_acquired, .get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired, .flush_req = __cam_isp_ctx_flush_req_in_top_state, + .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, @@ -4342,6 +4751,7 @@ static struct cam_ctx_ops .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, .flush_req = __cam_isp_ctx_flush_req_in_ready, + .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_active_request, @@ -4376,6 +4786,7 @@ static struct cam_ctx_ops .apply_req = __cam_isp_ctx_apply_req, .flush_req = __cam_isp_ctx_flush_req_in_top_state, .process_evt = __cam_isp_ctx_process_evt, + .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_active_request, @@ -4559,6 +4970,9 @@ int cam_isp_context_init(struct cam_isp_context *ctx, } atomic64_set(&ctx->state_monitor_head, -1); + for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) + atomic64_set(&ctx->event_record_head[i], -1); + cam_isp_context_debug_register(); err: return rc; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 3e4e601b9bfe..78e2db92f0b1 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -33,6 +33,27 @@ */ #define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 40 +/* + * Threshold response time in us beyond which a request is not expected + * to be with IFE hw + */ +#define CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD 100000 + +/* Number of words for dumping isp context */ +#define CAM_ISP_CTX_DUMP_NUM_WORDS 5 + +/* Number of words for dumping isp context events*/ +#define CAM_ISP_CTX_DUMP_EVENT_NUM_WORDS 3 + +/* Number of words for dumping request info*/ +#define CAM_ISP_CTX_DUMP_REQUEST_NUM_WORDS 2 + +/* Maximum entries in event record */ +#define CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES 20 + +/* Maximum length of tag while dumping */ +#define CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN 32 + /* forward declaration */ struct cam_isp_context; @@ -55,6 +76,19 @@ enum cam_isp_ctx_activated_substate { CAM_ISP_CTX_ACTIVATED_MAX, }; +/** + * enum cam_isp_ctx_event_type - events for a request + * + */ +enum cam_isp_ctx_event { + CAM_ISP_CTX_EVENT_SUBMIT, + CAM_ISP_CTX_EVENT_APPLY, + CAM_ISP_CTX_EVENT_EPOCH, + CAM_ISP_CTX_EVENT_RUP, + CAM_ISP_CTX_EVENT_BUFDONE, + CAM_ISP_CTX_EVENT_MAX +}; + /** * enum cam_isp_state_change_trigger - Different types of ISP events * @@ -109,6 +143,7 @@ struct cam_isp_ctx_irq_ops { * @bubble_report: Flag to track if bubble report is active on * current request * @hw_update_data: HW update data for this request + * @event_timestamp: Timestamp for different stage of request * @reapply: True if reapplying after bubble * */ @@ -125,6 +160,8 @@ struct cam_isp_ctx_req { uint32_t num_acked; int32_t bubble_report; struct cam_isp_prepare_hw_update_data hw_update_data; + ktime_t event_timestamp + [CAM_ISP_CTX_EVENT_MAX]; bool bubble_detected; bool reapply; }; @@ -160,8 +197,23 @@ struct cam_isp_context_state_monitor { struct cam_isp_context_req_id_info { int64_t last_bufdone_req_id; }; + /** * + * + * struct cam_isp_context_event_record - Information for last 20 Events + * for a request; Submit, Apply, EPOCH, RUP, Buf done. + * + * @req_id: Last applied request id + * @timestamp: Timestamp for the event + * + */ +struct cam_isp_context_event_record { + uint64_t req_id; + ktime_t timestamp; +}; + +/** * struct cam_isp_context - ISP context object * * @base: Common context object pointer @@ -187,6 +239,8 @@ struct cam_isp_context_req_id_info { * @state_monitor_head: Write index to the state monitoring array * @req_info Request id information about last buf done * @cam_isp_ctx_state_monitor: State monitoring array + * @event_record_head: Write index to the state monitoring array + * @event_record: Event record array * @rdi_only_context: Get context type information. * true, if context is rdi only context * @hw_acquired: Indicate whether HW resources are acquired @@ -221,6 +275,10 @@ struct cam_isp_context { struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; struct cam_isp_context_req_id_info req_info; + atomic64_t event_record_head[ + CAM_ISP_CTX_EVENT_MAX]; + struct cam_isp_context_event_record event_record[ + CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES]; bool rdi_only_context; bool hw_acquired; bool init_received; @@ -229,6 +287,19 @@ struct cam_isp_context { uint32_t isp_device_type; }; +/** + * struct cam_isp_context_dump_header - ISP context dump header + * @tag: Tag name for the header + * @word_size: Size of word + * @size: Size of data + * + */ +struct cam_isp_context_dump_header { + uint8_t tag[CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + /** * cam_isp_context_init() * diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 44c42e2e71c3..af626cbbfb0b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -134,7 +134,9 @@ static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type, static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf, - uint32_t meta_type) + uint32_t meta_type, + void *soc_dump_args, + bool user_triggered_dump) { int rc = 0, i; @@ -157,7 +159,9 @@ static int cam_ife_mgr_handle_reg_dump(struct cam_ife_hw_mgr_ctx *ctx, rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, ®_dump_buf_desc[i], ctx->applied_req_id, - cam_ife_mgr_regspace_data_cb); + cam_ife_mgr_regspace_data_cb, + soc_dump_args, + user_triggered_dump); if (rc) { CAM_ERR(CAM_ISP, "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", @@ -2427,7 +2431,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, hw_update_data->num_reg_dump_buf, - CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST); + CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST, + NULL, false); CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", @@ -5943,7 +5948,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, - CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH); + CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH, NULL, false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump on flush failed req id: %llu rc: %d", @@ -5959,7 +5964,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_err_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, - CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR); + CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, NULL, false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump on error failed req id: %llu rc: %d", @@ -5978,6 +5983,155 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } +static int cam_ife_mgr_user_dump_hw( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_hw_dump_args *dump_args) +{ + int rc = 0; + struct cam_hw_soc_dump_args soc_dump_args; + + if (!ife_ctx || !dump_args) { + CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK", + ife_ctx, dump_args); + rc = -EINVAL; + goto end; + } + soc_dump_args.buf_handle = dump_args->buf_handle; + soc_dump_args.request_id = dump_args->request_id; + soc_dump_args.offset = dump_args->offset; + + rc = cam_ife_mgr_handle_reg_dump(ife_ctx, + ife_ctx->reg_dump_buf_desc, + ife_ctx->num_reg_dump_buf, + CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, + &soc_dump_args, + true); + if (rc) { + CAM_ERR(CAM_ISP, + "Dump failed req: %lld handle %u offset %u", + dump_args->request_id, + dump_args->buf_handle, + dump_args->offset); + goto end; + } + dump_args->offset = soc_dump_args.offset; +end: + return rc; +} + +static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args) +{ + struct cam_isp_hw_dump_args isp_hw_dump_args; + struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_hw_mgr_ctx *ife_ctx = (struct cam_ife_hw_mgr_ctx *) + dump_args->ctxt_to_hw_map; + int i; + int rc = 0; + + /* for some targets, information about the IFE registers to be dumped + * is already submitted with the hw manager. In this case, we + * can dump just the related registers and skip going to core files. + */ + if (ife_ctx->num_reg_dump_buf) { + cam_ife_mgr_user_dump_hw(ife_ctx, dump_args); + goto end; + } + + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &isp_hw_dump_args.cpu_addr, + &isp_hw_dump_args.buf_len); + if (rc) { + CAM_ERR(CAM_ISP, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + return rc; + } + + isp_hw_dump_args.offset = dump_args->offset; + isp_hw_dump_args.req_id = dump_args->request_id; + + 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]) + continue; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + switch (hw_mgr_res->hw_res[i]->res_id) { + case CAM_IFE_PIX_PATH_RES_RDI_0: + case CAM_IFE_PIX_PATH_RES_RDI_1: + case CAM_IFE_PIX_PATH_RES_RDI_2: + case CAM_IFE_PIX_PATH_RES_RDI_3: + if (ife_ctx->is_rdi_only_context && + hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + case CAM_IFE_PIX_PATH_RES_IPP: + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + default: + CAM_DBG(CAM_ISP, "not a valid res %d", + hw_mgr_res->res_id); + break; + } + } + } + + list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_src, 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; + switch (hw_mgr_res->res_id) { + case CAM_ISP_HW_VFE_IN_RDI0: + case CAM_ISP_HW_VFE_IN_RDI1: + case CAM_ISP_HW_VFE_IN_RDI2: + case CAM_ISP_HW_VFE_IN_RDI3: + if (ife_ctx->is_rdi_only_context && + hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + case CAM_ISP_HW_VFE_IN_CAMIF: + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + default: + CAM_DBG(CAM_ISP, "not a valid res %d", + hw_mgr_res->res_id); + break; + } + } + } + dump_args->offset = isp_hw_dump_args.offset; +end: + CAM_DBG(CAM_ISP, "offset %u", dump_args->offset); + return rc; +} + static int cam_ife_mgr_cmd_get_sof_timestamp( struct cam_ife_hw_mgr_ctx *ife_ctx, uint64_t *time_stamp, @@ -6957,6 +7111,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; hw_mgr_intf->hw_reset = cam_ife_mgr_reset; + hw_mgr_intf->hw_dump = cam_ife_mgr_dump; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 0eaa8df2559e..1eaa695d362e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -140,7 +140,9 @@ static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx, rc = cam_soc_util_reg_dump_to_cmd_buf(ctx, ®_dump_buf_desc[i], ctx->applied_req_id, - cam_tfe_mgr_regspace_data_cb); + cam_tfe_mgr_regspace_data_cb, + NULL, + false); if (rc) { CAM_ERR(CAM_ISP, "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 150e40050999..d2b04752e2e2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3808,7 +3808,70 @@ static int cam_ife_csid_set_epd_config( csid_hw->epd_supported = epd_update->epd_supported; CAM_DBG(CAM_ISP, "CSID EPD supported %d", csid_hw->epd_supported); + return 0; +} +static int cam_ife_csid_dump_hw( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + int i; + uint8_t *dst; + uint32_t *addr, *start; + uint32_t min_len; + uint32_t num_reg; + size_t remain_len; + struct cam_isp_hw_dump_header *hdr; + struct cam_isp_hw_dump_args *dump_args = + (struct cam_isp_hw_dump_args *)cmd_args; + struct cam_hw_soc_info *soc_info; + + if (!dump_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + if (!dump_args->cpu_addr || !dump_args->buf_len) { + CAM_ERR(CAM_ISP, + "Invalid params %pK %zu", + (void *)dump_args->cpu_addr, + dump_args->buf_len); + return -EINVAL; + } + soc_info = &csid_hw->hw_info->soc_info; + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_ISP, + "Dump offset overshoot offset %zu buf_len %zu", + dump_args->offset, dump_args->buf_len); + return -ENOSPC; + } + min_len = soc_info->reg_map[0].size + + sizeof(struct cam_isp_hw_dump_header) + + sizeof(uint32_t); + remain_len = dump_args->buf_len - dump_args->offset; + if (remain_len < min_len) { + CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu, min %u", + remain_len, min_len); + return -ENOSPC; + } + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "CSID_REG:"); + addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header)); + + start = addr; + num_reg = soc_info->reg_map[0].size/4; + hdr->word_size = sizeof(uint32_t); + *addr = soc_info->index; + addr++; + for (i = 0; i < num_reg; i++) { + addr[0] = soc_info->mem_block[0]->start + (i*4); + addr[1] = cam_io_r(soc_info->reg_map[0].mem_base + + (i*4)); + addr += 2; + } + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + CAM_DBG(CAM_ISP, "offset %zu", dump_args->offset); return 0; } @@ -3852,6 +3915,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_SET_CONFIG: rc = cam_ife_csid_set_epd_config(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_DUMP_HW: + rc = cam_ife_csid_dump_hw(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 22b2bf1f534f..5fd1172a4033 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -13,6 +13,8 @@ #include "cam_irq_controller.h" #include "cam_hw_intf.h" +/* Maximum length of tag while dumping */ +#define CAM_ISP_HW_DUMP_TAG_MAX_LEN 32 /* * struct cam_isp_timestamp: * @@ -111,6 +113,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, + CAM_ISP_HW_CMD_DUMP_HW, CAM_ISP_HW_CMD_MAX, }; @@ -253,4 +256,40 @@ struct cam_isp_hw_dual_isp_update_args { struct cam_isp_resource_node *res; struct cam_isp_dual_config *dual_cfg; }; + +/* + * struct cam_isp_hw_dump_args: + * + * @Brief: isp hw dump args + * + * @ req_id: request id + * @ cpu_addr: cpu address + * @ buf_len: buf len + * @ offset: offset of buffer + * @ ctxt_to_hw_map: ctx to hw map + */ +struct cam_isp_hw_dump_args { + uint64_t req_id; + uintptr_t cpu_addr; + size_t buf_len; + size_t offset; + void *ctxt_to_hw_map; +}; + +/** + * struct cam_isp_hw_dump_header - ISP context dump header + * + * @Brief: isp hw dump header + * + * @tag: Tag name for the header + * @word_size: Size of word + * @size: Size of data + * + */ +struct cam_isp_hw_dump_header { + uint8_t tag[CAM_ISP_HW_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + #endif /* _CAM_ISP_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 34b081a5340e..7281e98ba94c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -595,6 +595,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_BW_CONTROL: case CAM_ISP_HW_CMD_CORE_CONFIG: case CAM_ISP_HW_CMD_BW_UPDATE_V2: + case CAM_ISP_HW_CMD_DUMP_HW: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index 663bc247b27f..63df625221cc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE170_H_ @@ -144,6 +144,32 @@ static struct cam_vfe_rdi_reg_data vfe_170_rdi_2_data = { .reg_update_irq_mask = 0x80, }; +struct cam_vfe_top_dump_data vfe170_dump_data = { + .num_reg_dump_entries = 2, + .num_lut_dump_entries = 1, + .dmi_cfg = 0xc24, + .dmi_addr = 0xc28, + .dmi_data_path_hi = 0xc2C, + .dmi_data_path_lo = 0xc30, + .reg_entry = { + { + .reg_dump_start = 0x0, + .reg_dump_end = 0x1164, + }, + { + .reg_dump_start = 0x2000, + .reg_dump_end = 0x397C, + }, + }, + .lut_entry = { + { + .lut_word_size = 64, + .lut_bank_sel = 0x40, + .lut_addr_size = 180, + }, + }, +}; + static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { .common_reg = &vfe170_top_common_reg, .camif_hw_info = { @@ -173,6 +199,7 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { CAM_VFE_RDI_VER_1_0, CAM_VFE_RDI_VER_1_0, }, + .dump_data = &vfe170_dump_data, }; static struct cam_irq_register_set vfe170_bus_irq_reg[3] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index 6823b6386b91..4e9a1e232860 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE175_H_ @@ -178,6 +178,32 @@ static struct cam_vfe_rdi_reg_data vfe_175_rdi_2_data = { .reg_update_irq_mask = 0x80, }; +struct cam_vfe_top_dump_data vfe175_dump_data = { + .num_reg_dump_entries = 2, + .num_lut_dump_entries = 1, + .dmi_cfg = 0xc24, + .dmi_addr = 0xc28, + .dmi_data_path_hi = 0xc2C, + .dmi_data_path_lo = 0xc30, + .reg_entry = { + { + .reg_dump_start = 0x0, + .reg_dump_end = 0x1164, + }, + { + .reg_dump_start = 0x2000, + .reg_dump_end = 0x397C, + }, + }, + .lut_entry = { + { + .lut_word_size = 64, + .lut_bank_sel = 0x40, + .lut_addr_size = 180, + }, + }, +}; + static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = { .common_reg = &vfe175_top_common_reg, .camif_hw_info = { @@ -209,6 +235,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = { CAM_VFE_RDI_VER_1_0, CAM_VFE_CAMIF_LITE_VER_2_0, }, + .dump_data = &vfe175_dump_data, }; static struct cam_irq_register_set vfe175_bus_irq_reg[3] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 8acd77d1f1e2..1a80dc7f8f2e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE175_130_H_ @@ -226,6 +226,32 @@ static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_2_data = { .reg_update_irq_mask = 0x80, }; +struct cam_vfe_top_dump_data vfe175_130_dump_data = { + .num_reg_dump_entries = 2, + .num_lut_dump_entries = 1, + .dmi_cfg = 0xc24, + .dmi_addr = 0xc28, + .dmi_data_path_hi = 0xc2C, + .dmi_data_path_lo = 0xc30, + .reg_entry = { + { + .reg_dump_start = 0x0, + .reg_dump_end = 0x1164, + }, + { + .reg_dump_start = 0x2000, + .reg_dump_end = 0x397C, + }, + }, + .lut_entry = { + { + .lut_word_size = 64, + .lut_bank_sel = 0x40, + .lut_addr_size = 180, + }, + }, +}; + static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = { .common_reg = &vfe175_130_top_common_reg, .camif_hw_info = { @@ -263,6 +289,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = { CAM_VFE_CAMIF_LITE_VER_2_0, CAM_VFE_IN_RD_VER_1_0, }, + .dump_data = &vfe175_130_dump_data, }; static struct cam_irq_register_set vfe175_130_bus_rd_irq_reg[1] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h index 03be713e6068..55607b6d886f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_TOP_COMMON_H_ @@ -13,6 +13,10 @@ #include "cam_vfe_hw_intf.h" #include "cam_vfe_soc.h" +#define CAM_VFE_TOP_MAX_REG_DUMP_ENTRIES 70 + +#define CAM_VFE_TOP_MAX_LUT_DUMP_ENTRIES 6 + struct cam_vfe_top_priv_common { struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_MUX_MAX]; uint32_t num_mux; @@ -26,6 +30,30 @@ struct cam_vfe_top_priv_common { enum cam_vfe_bw_control_action axi_vote_control[CAM_VFE_TOP_MUX_MAX]; }; +struct cam_vfe_top_reg_dump_entry { + uint32_t reg_dump_start; + uint32_t reg_dump_end; +}; + +struct cam_vfe_top_lut_dump_entry { + uint32_t lut_word_size; + uint32_t lut_bank_sel; + uint32_t lut_addr_size; +}; + +struct cam_vfe_top_dump_data { + uint32_t num_reg_dump_entries; + uint32_t num_lut_dump_entries; + uint32_t dmi_cfg; + uint32_t dmi_addr; + uint32_t dmi_data_path_hi; + uint32_t dmi_data_path_lo; + struct cam_vfe_top_reg_dump_entry + reg_entry[CAM_VFE_TOP_MAX_REG_DUMP_ENTRIES]; + struct cam_vfe_top_lut_dump_entry + lut_entry[CAM_VFE_TOP_MAX_LUT_DUMP_ENTRIES]; +}; + int cam_vfe_top_set_axi_bw_vote(struct cam_vfe_soc_private *soc_private, struct cam_vfe_top_priv_common *top_common, bool start_stop); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index c5225c540722..6774be8cda3d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -19,6 +19,7 @@ struct cam_vfe_top_ver2_common_data { struct cam_hw_soc_info *soc_info; struct cam_hw_intf *hw_intf; struct cam_vfe_top_ver2_reg_offset_common *common_reg; + struct cam_vfe_top_dump_data *dump_data; }; struct cam_vfe_top_ver2_priv { @@ -184,6 +185,140 @@ int cam_vfe_top_get_hw_caps(void *device_priv, return -EPERM; } +static int cam_vfe_hw_dump( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, + uint32_t arg_size) +{ + int i, j; + uint8_t *dst; + uint32_t reg_start_offset; + uint32_t reg_dump_size = 0; + uint32_t lut_dump_size = 0; + uint32_t val; + uint32_t num_reg; + void __iomem *reg_base; + uint32_t *addr, *start; + size_t remain_len; + uint32_t min_len; + struct cam_hw_soc_info *soc_info; + struct cam_vfe_top_dump_data *dump_data; + struct cam_isp_hw_dump_header *hdr; + struct cam_isp_hw_dump_args *dump_args = + (struct cam_isp_hw_dump_args *)cmd_args; + + if (!dump_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + if (!dump_args->cpu_addr || !dump_args->buf_len) { + CAM_ERR(CAM_ISP, + "Invalid params %pK %zu", + (void *)dump_args->cpu_addr, + dump_args->buf_len); + return -EINVAL; + } + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_ISP, + "Dump offset overshoot offset %zu buf_len %zu", + dump_args->offset, dump_args->buf_len); + return -ENOSPC; + } + dump_data = top_priv->common_data.dump_data; + soc_info = top_priv->common_data.soc_info; + + /*Dump registers */ + for (i = 0; i < dump_data->num_reg_dump_entries; i++) + reg_dump_size += (dump_data->reg_entry[i].reg_dump_end - + dump_data->reg_entry[i].reg_dump_start); + /* + * We dump the offset as well, so the total size dumped becomes + * multiplied by 2 + */ + reg_dump_size *= 2; + for (i = 0; i < dump_data->num_lut_dump_entries; i++) + lut_dump_size += ((dump_data->lut_entry[i].lut_addr_size) * + (dump_data->lut_entry[i].lut_word_size/8)); + + /*Minimum len comprises of: + * soc_index + * lut_dump_size + reg_dump_size + sizeof dump_header + + * (num_lut_dump_entries--> represents number of banks) + */ + min_len = sizeof(uint32_t) + lut_dump_size + reg_dump_size + + sizeof(struct cam_isp_hw_dump_header) + + (dump_data->num_lut_dump_entries * sizeof(uint32_t)); + remain_len = dump_args->buf_len - dump_args->offset; + if (remain_len < min_len) { + CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu, min %u", + remain_len, min_len); + return -ENOSPC; + } + + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + hdr->word_size = sizeof(uint32_t); + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "VFE_REG:"); + addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header)); + start = addr; + *addr++ = soc_info->index; + for (i = 0; i < dump_data->num_reg_dump_entries; i++) { + num_reg = (dump_data->reg_entry[i].reg_dump_end - + dump_data->reg_entry[i].reg_dump_start)/4; + reg_start_offset = dump_data->reg_entry[i].reg_dump_start; + reg_base = soc_info->reg_map[0].mem_base + reg_start_offset; + for (j = 0; j < num_reg; j++) { + addr[0] = soc_info->mem_block[0]->start + + reg_start_offset + (j*4); + addr[1] = cam_io_r(reg_base + (j*4)); + addr += 2; + } + } + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + + /*dump LUT*/ + for (i = 0; i < dump_data->num_lut_dump_entries; i++) { + + dst = (char *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "LUT_REG:"); + hdr->word_size = dump_data->lut_entry[i].lut_word_size/8; + addr = (uint32_t *)(dst + + sizeof(struct cam_isp_hw_dump_header)); + start = addr; + *addr++ = dump_data->lut_entry[i].lut_bank_sel; + val = 0x100 | dump_data->lut_entry[i].lut_bank_sel; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + dump_data->dmi_cfg); + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + dump_data->dmi_addr); + for (j = 0; j < dump_data->lut_entry[i].lut_addr_size; + j++) { + if (dump_data->lut_entry[i].lut_word_size == 64) { + addr[0] = cam_io_r( + soc_info->reg_map[0].mem_base + + dump_data->dmi_data_path_lo); + addr[1] = cam_io_r( + soc_info->reg_map[0].mem_base + + dump_data->dmi_data_path_hi); + addr += 2; + } else { + *addr = cam_io_r( + soc_info->reg_map[0].mem_base + + dump_data->dmi_data_path_lo); + addr++; + } + } + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + } + CAM_DBG(CAM_ISP, "offset %zu", dump_args->offset); + return 0; +} + int cam_vfe_top_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { @@ -505,6 +640,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_top_bw_control(soc_private, &top_priv->top_common, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_DUMP_HW: + rc = cam_vfe_hw_dump(top_priv, + cmd_args, arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type); @@ -627,6 +766,7 @@ int cam_vfe_top_ver2_init( top_priv->common_data.hw_intf = hw_intf; top_priv->top_common.hw_idx = hw_intf->hw_idx; top_priv->common_data.common_reg = ver2_hw_info->common_reg; + top_priv->common_data.dump_data = ver2_hw_info->dump_data; return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h index 961bf954aaa1..65d01da159ec 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_TOP_VER2_H_ @@ -49,6 +49,7 @@ struct cam_vfe_top_ver2_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; + struct cam_vfe_top_dump_data *dump_data; uint32_t num_mux; uint32_t mux_type[CAM_VFE_TOP_MUX_MAX]; }; diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index a6220d156692..ce80569ab0f9 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -2002,9 +2002,268 @@ end: return rc; } +static int cam_soc_util_dump_dmi_reg_range_user_buf( + struct cam_hw_soc_info *soc_info, + struct cam_dmi_read_desc *dmi_read, uint32_t base_idx, + struct cam_hw_soc_dump_args *dump_args) +{ + int i; + int rc; + size_t buf_len = 0; + uint8_t *dst; + size_t remain_len; + uint32_t min_len; + uint32_t *waddr, *start; + uintptr_t cpu_addr; + struct cam_hw_soc_dump_header *hdr; + + if (!soc_info || !dump_args || !dmi_read) { + CAM_ERR(CAM_UTIL, + "Invalid input args soc_info: %pK, dump_args: %pK", + soc_info, dump_args); + rc = -EINVAL; + goto end; + } + + if (dmi_read->num_pre_writes > CAM_REG_DUMP_DMI_CONFIG_MAX || + dmi_read->num_post_writes > CAM_REG_DUMP_DMI_CONFIG_MAX) { + CAM_ERR(CAM_UTIL, + "Invalid number of requested writes, pre: %d post: %d", + dmi_read->num_pre_writes, dmi_read->num_post_writes); + rc = -EINVAL; + goto end; + } + + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &cpu_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_UTIL, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + goto end; + } + + if (buf_len <= dump_args->offset) { + CAM_WARN(CAM_UTIL, "Dump offset overshoot offset %zu len %zu", + dump_args->offset, buf_len); + rc = -ENOSPC; + goto end; + } + remain_len = buf_len - dump_args->offset; + min_len = (dmi_read->num_pre_writes * 2 * sizeof(uint32_t)) + + (dmi_read->dmi_data_read.num_values * 2 * sizeof(uint32_t)) + + sizeof(uint32_t); + if (remain_len < min_len) { + CAM_WARN(CAM_UTIL, + "Dump Buffer exhaust read %d write %d remain %zu min %u", + dmi_read->dmi_data_read.num_values, + dmi_read->num_pre_writes, remain_len, + min_len); + rc = -ENOSPC; + goto end; + } + + dst = (uint8_t *)cpu_addr + dump_args->offset; + hdr = (struct cam_hw_soc_dump_header *)dst; + memset(hdr, 0, sizeof(struct cam_hw_soc_dump_header)); + scnprintf(hdr->tag, CAM_SOC_HW_DUMP_TAG_MAX_LEN, + "DMI_DUMP:"); + waddr = (uint32_t *)(dst + sizeof(struct cam_hw_soc_dump_header)); + start = waddr; + hdr->word_size = sizeof(uint32_t); + *waddr = soc_info->index; + waddr++; + for (i = 0; i < dmi_read->num_pre_writes; i++) { + if (dmi_read->pre_read_config[i].offset > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + dmi_read->pre_read_config[i].offset, + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + + cam_soc_util_w_mb(soc_info, base_idx, + dmi_read->pre_read_config[i].offset, + dmi_read->pre_read_config[i].value); + *waddr++ = dmi_read->pre_read_config[i].offset; + *waddr++ = dmi_read->pre_read_config[i].value; + } + + if (dmi_read->dmi_data_read.offset > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + dmi_read->dmi_data_read.offset, + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + + for (i = 0; i < dmi_read->dmi_data_read.num_values; i++) { + *waddr++ = dmi_read->dmi_data_read.offset; + *waddr++ = cam_soc_util_r_mb(soc_info, base_idx, + dmi_read->dmi_data_read.offset); + } + + for (i = 0; i < dmi_read->num_post_writes; i++) { + if (dmi_read->post_read_config[i].offset > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + dmi_read->post_read_config[i].offset, + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + cam_soc_util_w_mb(soc_info, base_idx, + dmi_read->post_read_config[i].offset, + dmi_read->post_read_config[i].value); + } + hdr->size = (waddr - start) * hdr->word_size; + dump_args->offset += hdr->size + + sizeof(struct cam_hw_soc_dump_header); + +end: + return rc; +} + +static int cam_soc_util_dump_cont_reg_range_user_buf( + struct cam_hw_soc_info *soc_info, + struct cam_reg_range_read_desc *reg_read, + uint32_t base_idx, + struct cam_hw_soc_dump_args *dump_args) +{ + int i; + int rc = 0; + size_t buf_len; + uint8_t *dst; + size_t remain_len; + uint32_t min_len; + uint32_t *waddr, *start; + uintptr_t cpu_addr; + struct cam_hw_soc_dump_header *hdr; + + if (!soc_info || !dump_args || !reg_read) { + CAM_ERR(CAM_UTIL, + "Invalid input args soc_info: %pK, dump_out_buffer: %pK reg_read: %pK", + soc_info, dump_args, reg_read); + rc = -EINVAL; + goto end; + } + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &cpu_addr, &buf_len); + if (rc) { + CAM_ERR(CAM_UTIL, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + goto end; + } + if (buf_len <= dump_args->offset) { + CAM_WARN(CAM_UTIL, "Dump offset overshoot %zu %zu", + dump_args->offset, buf_len); + rc = -ENOSPC; + goto end; + } + remain_len = buf_len - dump_args->offset; + min_len = (reg_read->num_values * 2 * sizeof(uint32_t)) + + sizeof(struct cam_hw_soc_dump_header) + sizeof(uint32_t); + if (remain_len < min_len) { + CAM_WARN(CAM_UTIL, + "Dump Buffer exhaust read_values %d remain %zu min %u", + reg_read->num_values, + remain_len, + min_len); + rc = -ENOSPC; + goto end; + } + dst = (uint8_t *)cpu_addr + dump_args->offset; + hdr = (struct cam_hw_soc_dump_header *)dst; + memset(hdr, 0, sizeof(struct cam_hw_soc_dump_header)); + scnprintf(hdr->tag, CAM_SOC_HW_DUMP_TAG_MAX_LEN, "%s_REG:", + soc_info->dev_name); + waddr = (uint32_t *)(dst + sizeof(struct cam_hw_soc_dump_header)); + start = waddr; + hdr->word_size = sizeof(uint32_t); + *waddr = soc_info->index; + waddr++; + for (i = 0; i < reg_read->num_values; i++) { + if ((reg_read->offset + (i * sizeof(uint32_t))) > + (uint32_t)soc_info->reg_map[base_idx].size) { + CAM_ERR(CAM_UTIL, + "Reg offset out of range, offset: 0x%X reg_map size: 0x%X", + (reg_read->offset + (i * sizeof(uint32_t))), + (uint32_t)soc_info->reg_map[base_idx].size); + rc = -EINVAL; + goto end; + } + + waddr[0] = reg_read->offset + (i * sizeof(uint32_t)); + waddr[1] = cam_soc_util_r(soc_info, base_idx, + (reg_read->offset + (i * sizeof(uint32_t)))); + waddr += 2; + } + hdr->size = (waddr - start) * hdr->word_size; + dump_args->offset += hdr->size + + sizeof(struct cam_hw_soc_dump_header); +end: + return rc; +} + +static int cam_soc_util_user_reg_dump( + struct cam_reg_dump_desc *reg_dump_desc, + struct cam_hw_soc_dump_args *dump_args, + struct cam_hw_soc_info *soc_info, + uint32_t reg_base_idx) +{ + int rc = 0; + int i; + struct cam_reg_read_info *reg_read_info = NULL; + + if (!dump_args || !reg_dump_desc || !soc_info) { + CAM_ERR(CAM_UTIL, + "Invalid input parameters %pK %pK %pK", + dump_args, reg_dump_desc, soc_info); + return -EINVAL; + } + for (i = 0; i < reg_dump_desc->num_read_range; i++) { + + reg_read_info = ®_dump_desc->read_range[i]; + if (reg_read_info->type == + CAM_REG_DUMP_READ_TYPE_CONT_RANGE) { + rc = cam_soc_util_dump_cont_reg_range_user_buf( + soc_info, + ®_read_info->reg_read, + reg_base_idx, + dump_args); + } else if (reg_read_info->type == + CAM_REG_DUMP_READ_TYPE_DMI) { + rc = cam_soc_util_dump_dmi_reg_range_user_buf( + soc_info, + ®_read_info->dmi_read, + reg_base_idx, + dump_args); + } else { + CAM_ERR(CAM_UTIL, + "Invalid Reg dump read type: %d", + reg_read_info->type); + rc = -EINVAL; + goto end; + } + + if (rc) { + CAM_ERR(CAM_UTIL, + "Reg range read failed rc: %d reg_base_idx: %d", + rc, reg_base_idx); + goto end; + } + } +end: + return rc; +} + int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, struct cam_cmd_buf_desc *cmd_desc, uint64_t req_id, - cam_soc_util_regspace_data_cb reg_data_cb) + cam_soc_util_regspace_data_cb reg_data_cb, + struct cam_hw_soc_dump_args *soc_dump_args, + bool user_triggered_dump) { int rc = 0, i, j; uintptr_t cpu_addr = 0; @@ -2148,12 +2407,6 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, goto end; } - dump_out_buf = (struct cam_reg_dump_out_buffer *) - (cmd_buf_start + - (uintptr_t)reg_dump_desc->dump_buffer_offset); - dump_out_buf->req_id = req_id; - dump_out_buf->bytes_written = 0; - reg_base_type = reg_dump_desc->reg_base_type; if (reg_base_type == 0 || reg_base_type > CAM_REG_DUMP_BASE_TYPE_CAMNOC) { @@ -2185,6 +2438,31 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, "Reg data callback success req_id: %llu base_type: %d base_idx: %d num_read_range: %d", req_id, reg_base_type, reg_base_idx, reg_dump_desc->num_read_range); + + /* If the dump request is triggered by user space + * buffer will be different from the buffer which is received + * in init packet. In this case, dump the data to the + * user provided buffer and exit. + */ + if (user_triggered_dump) { + rc = cam_soc_util_user_reg_dump(reg_dump_desc, + soc_dump_args, soc_info, reg_base_idx); + CAM_INFO(CAM_UTIL, + "%s reg_base_idx %d dumped offset %u", + soc_info->dev_name, reg_base_idx, + soc_dump_args->offset); + goto end; + } + + /* Below code is executed when data is dumped to the + * out buffer received in init packet + */ + dump_out_buf = (struct cam_reg_dump_out_buffer *) + (cmd_buf_start + + (uintptr_t)reg_dump_desc->dump_buffer_offset); + dump_out_buf->req_id = req_id; + dump_out_buf->bytes_written = 0; + for (j = 0; j < reg_dump_desc->num_read_range; j++) { CAM_DBG(CAM_UTIL, "Number of bytes written to cmd buffer: %u req_id: %llu", diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 5e51fa8f1bf5..1f795b07e9e4 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -41,6 +41,9 @@ #define DDR_TYPE_LPDDR5 8 #define DDR_TYPE_LPDDR5X 9 +/* Maximum length of tag while dumping */ +#define CAM_SOC_HW_DUMP_TAG_MAX_LEN 32 + /** * enum cam_vote_level - Enum for voting level * @@ -218,6 +221,34 @@ struct cam_hw_soc_info { void *soc_private; }; +/** + * struct cam_hw_soc_dump_header - SOC dump header + * + * @Brief: soc hw dump header + * + * @tag: Tag name for the header + * @word_size: Size of each word + * @size: Total size of dumped data + */ +struct cam_hw_soc_dump_header { + uint8_t tag[CAM_SOC_HW_DUMP_TAG_MAX_LEN]; + uint64_t size; + uint32_t word_size; +}; + +/** + * struct cam_hw_soc_dump_args: SOC Dump args + * + * @request_id: Issue request id + * @offset: Buffer offset, updated as the informaton is dumped + * @buf_handle: Buffer handle of the out buffer + */ +struct cam_hw_soc_dump_args { + uint64_t request_id; + size_t offset; + uint32_t buf_handle; +}; + /* * CAM_SOC_GET_REG_MAP_START * @@ -636,19 +667,23 @@ typedef int (*cam_soc_util_regspace_data_cb)(uint32_t reg_base_type, /** * cam_soc_util_reg_dump_to_cmd_buf() * - * @brief: Camera SOC util for dumping sets of register ranges to - * to command buffer + * @brief: Camera SOC util for dumping sets of register ranges + * command buffer * - * @ctx: Context info from specific hardware manager - * @cmd_desc: Command buffer descriptor - * @req_id: Last applied req id for which reg dump is required - * @reg_data_cb: Callback function to get reg space info based on type - * in command buffer - * - * @return: Success or Failure + * @ctx: Context info from specific hardware manager + * @cmd_desc: Command buffer descriptor + * @req_id: Last applied req id for which reg dump is required + * @reg_data_cb: Callback function to get reg space info based on type + * in command buffer + * @soc_dump_args: Dump buffer args to dump the soc information. + * @user_triggered_dump: Flag to indicate if the dump request is issued by + * user. + * @return: Success or Failure */ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, struct cam_cmd_buf_desc *cmd_desc, uint64_t req_id, - cam_soc_util_regspace_data_cb reg_data_cb); + cam_soc_util_regspace_data_cb reg_data_cb, + struct cam_hw_soc_dump_args *soc_dump_args, + bool user_triggered_dump); #endif /* _CAM_SOC_UTIL_H_ */ From 381bb12c680b7cba4891b33a985a03e08e1788f6 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 13 Sep 2019 11:08:05 -0700 Subject: [PATCH 271/790] msm: camera: isp: Obtain timestamp as part of frame header In use-cases that involve custom HW retrieve the timestamp for shutter from frame header as opposed to csid registers. CRs-Fixed: 2524308 Change-Id: I5de789cf939546affbfe6d537d8090982f39189d Signed-off-by: Karthik Anantha Ram --- drivers/cam_core/cam_hw_mgr_intf.h | 6 +- drivers/cam_isp/cam_isp_context.c | 90 +++++++++++++-- drivers/cam_isp/cam_isp_context.h | 8 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 107 +++++++++++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 4 + drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 8 +- .../hw_utils/cam_isp_packet_parser.c | 19 +++- .../hw_utils/include/cam_isp_packet_parser.h | 18 ++- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 8 +- .../isp_hw/include/cam_ife_csid_hw_intf.h | 8 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 4 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 22 ++++ 12 files changed, 278 insertions(+), 24 deletions(-) diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 1e2c1f7a7008..422a47bf354a 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HW_MGR_INTF_H_ @@ -101,6 +101,8 @@ struct cam_hw_done_event_data { * @num_acq: Total number of acquire in the payload * @acquire_info: Acquired resource array pointer * @ctxt_to_hw_map: HW context (returned) + * @custom_enabled: ctx has custom enabled + * @use_frame_header_ts: Use frame header for qtimer ts * @acquired_hw_id: Acquired hardware mask * @acquired_hw_path: Acquired path mask for an input * if input splits into multiple paths, @@ -115,6 +117,8 @@ struct cam_hw_acquire_args { uint32_t acquire_info_size; uintptr_t acquire_info; void *ctxt_to_hw_map; + bool custom_enabled; + bool use_frame_header_ts; uint32_t acquired_hw_id[CAM_MAX_ACQ_RES]; uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 3f991dc7b136..02f51ff13cb6 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -425,6 +425,7 @@ static int __cam_isp_ctx_enqueue_init_request( struct cam_isp_ctx_req *req_isp_new; struct cam_isp_prepare_hw_update_data *req_update_old; struct cam_isp_prepare_hw_update_data *req_update_new; + struct cam_isp_prepare_hw_update_data *hw_update_data; spin_lock_bh(&ctx->lock); if (list_empty(&ctx->pending_req_list)) { @@ -487,6 +488,13 @@ static int __cam_isp_ctx_enqueue_init_request( req_update_new->num_reg_dump_buf; } + /* Update frame header params for EPCR */ + hw_update_data = &req_isp_new->hw_update_data; + req_isp_old->hw_update_data.frame_header_res_id = + req_isp_new->hw_update_data.frame_header_res_id; + req_isp_old->hw_update_data.frame_header_cpu_addr = + hw_update_data->frame_header_cpu_addr; + req_old->request_id = req->request_id; list_add_tail(&req->list, &ctx->free_req_list); @@ -645,9 +653,9 @@ static void __cam_isp_ctx_send_sof_boot_timestamp( req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld boot time stamp:0x%llx", + "request id:%lld frame number:%lld boot time stamp:0x%llx status:%u", request_id, ctx_isp->frame_id, - ctx_isp->boot_timestamp); + ctx_isp->boot_timestamp, sof_event_status); if (cam_req_mgr_notify_message(&req_msg, V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS, @@ -657,6 +665,41 @@ static void __cam_isp_ctx_send_sof_boot_timestamp( request_id); } +static void __cam_isp_ctx_send_sof_timestamp_frame_header( + struct cam_isp_context *ctx_isp, uint32_t *frame_header_cpu_addr, + uint64_t request_id, uint32_t sof_event_status) +{ + uint32_t *time32 = NULL; + uint64_t timestamp = 0; + struct cam_req_mgr_message req_msg; + + time32 = frame_header_cpu_addr; + timestamp = (uint64_t) time32[1]; + timestamp = timestamp << 24; + timestamp |= (uint64_t)(time32[0] >> 8); + timestamp = mul_u64_u32_div(timestamp, + CAM_IFE_QTIMER_MUL_FACTOR, + CAM_IFE_QTIMER_DIV_FACTOR); + + ctx_isp->sof_timestamp_val = timestamp; + req_msg.session_hdl = ctx_isp->base->session_hdl; + req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; + req_msg.u.frame_msg.request_id = request_id; + req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val; + req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; + req_msg.u.frame_msg.sof_status = sof_event_status; + + CAM_DBG(CAM_ISP, + "request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u", + request_id, ctx_isp->frame_id, + ctx_isp->sof_timestamp_val, sof_event_status); + + if (cam_req_mgr_notify_message(&req_msg, + V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT)) + CAM_ERR(CAM_ISP, + "Error in notifying the sof time for req id:%lld", + request_id); +} static void __cam_isp_ctx_send_sof_timestamp( struct cam_isp_context *ctx_isp, uint64_t request_id, @@ -664,6 +707,10 @@ static void __cam_isp_ctx_send_sof_timestamp( { struct cam_req_mgr_message req_msg; + if ((ctx_isp->use_frame_header_ts) && (request_id) && + (sof_event_status == CAM_REQ_MGR_SOF_EVENT_SUCCESS)) + goto end; + req_msg.session_hdl = ctx_isp->base->session_hdl; req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; req_msg.u.frame_msg.request_id = request_id; @@ -673,10 +720,9 @@ static void __cam_isp_ctx_send_sof_timestamp( req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld SOF time stamp:0x%llx", + "request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u", request_id, ctx_isp->frame_id, - ctx_isp->sof_timestamp_val); - CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status); + ctx_isp->sof_timestamp_val, sof_event_status); if (cam_req_mgr_notify_message(&req_msg, V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT)) @@ -684,9 +730,9 @@ static void __cam_isp_ctx_send_sof_timestamp( "Error in notifying the sof time for req id:%lld", request_id); +end: __cam_isp_ctx_send_sof_boot_timestamp(ctx_isp, request_id, sof_event_status); - } static void __cam_isp_ctx_handle_buf_done_fail_log( @@ -738,7 +784,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( { int rc = 0; int i, j; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; uint64_t buf_done_req_id; const char *handle_type; @@ -840,6 +886,14 @@ static int __cam_isp_ctx_handle_buf_done_for_request( req_isp->num_acked++; req_isp->fence_map_out[j].sync_id = -1; } + + if ((ctx_isp->use_frame_header_ts) && + (req_isp->hw_update_data.frame_header_res_id == + req_isp->fence_map_out[j].resource_handle)) + __cam_isp_ctx_send_sof_timestamp_frame_header( + ctx_isp, + req_isp->hw_update_data.frame_header_cpu_addr, + req->request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); } if (req_isp->num_acked > req_isp->num_fence_map_out) { @@ -883,10 +937,14 @@ static int __cam_isp_ctx_handle_buf_done_for_request( ctx->ctx_id); } } else { - if (ctx_isp->reported_req_id < buf_done_req_id) { - ctx_isp->reported_req_id = buf_done_req_id; - __cam_isp_ctx_send_sof_timestamp(ctx_isp, - buf_done_req_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + if (!ctx_isp->use_frame_header_ts) { + if (ctx_isp->reported_req_id < buf_done_req_id) { + ctx_isp->reported_req_id = buf_done_req_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, + buf_done_req_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } } list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); @@ -3375,6 +3433,8 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, } ctx->last_flush_req = 0; + ctx_isp->custom_enabled = false; + ctx_isp->use_frame_header_ts = false; ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; @@ -4030,6 +4090,12 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, goto free_res; } + /* Set custom flag if applicable + * custom hw is supported only on v2 + */ + ctx_isp->custom_enabled = param.custom_enabled; + ctx_isp->use_frame_header_ts = param.use_frame_header_ts; + /* 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; @@ -4935,6 +5001,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->base = ctx_base; ctx->frame_id = 0; + ctx->custom_enabled = false; + ctx->use_frame_header_ts = false; ctx->active_req_cnt = 0; ctx->reported_req_id = 0; ctx->req_info.last_bufdone_req_id = 0; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 78e2db92f0b1..94c61af5e0e7 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -15,6 +15,10 @@ #include "cam_context.h" #include "cam_isp_hw_mgr_intf.h" + +#define CAM_IFE_QTIMER_MUL_FACTOR 10000 +#define CAM_IFE_QTIMER_DIV_FACTOR 192 + /* * Maximum hw resource - This number is based on the maximum * output port resource. The current maximum resource number @@ -246,6 +250,8 @@ struct cam_isp_context_event_record { * @hw_acquired: Indicate whether HW resources are acquired * @init_received: Indicate whether init config packet is received * @split_acquire: Indicate whether a separate acquire is expected + * @custom_enabled: Custom HW enabled for this ctx + * @use_frame_header_ts: Use frame header for qtimer ts * @init_timestamp: Timestamp at which this context is initialized * @isp_device_type ISP device type * @@ -283,6 +289,8 @@ struct cam_isp_context { bool hw_acquired; bool init_received; bool split_acquire; + bool custom_enabled; + bool use_frame_header_ts; unsigned int init_timestamp; uint32_t isp_device_type; }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index af626cbbfb0b..e2a2cecf7235 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2695,6 +2695,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto err; } + ife_ctx->custom_enabled = false; ife_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) ife_ctx->common.event_cb[i] = acquire_args->event_cb; @@ -2748,6 +2749,12 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type); + if ((in_port->cust_node) && (!ife_ctx->custom_enabled)) { + ife_ctx->custom_enabled = true; + /* This can be obtained from uapi */ + ife_ctx->use_frame_header_ts = true; + } + rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, &num_pix_port_per_in, &num_rdi_port_per_in, &acquire_args->acquired_hw_id[i], @@ -2782,6 +2789,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } acquire_args->ctxt_to_hw_map = ife_ctx; + acquire_args->custom_enabled = ife_ctx->custom_enabled; + acquire_args->use_frame_header_ts = ife_ctx->use_frame_header_ts; ife_ctx->ctx_in_use = 1; ife_ctx->num_reg_dump_buf = 0; @@ -4193,6 +4202,8 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->cdm_handle = 0; ctx->cdm_ops = NULL; ctx->num_reg_dump_buf = 0; + ctx->custom_enabled = false; + ctx->use_frame_header_ts = false; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; @@ -5555,6 +5566,58 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, return rc; } +static int cam_ife_mgr_util_insert_frame_header( + struct cam_kmd_buf_info *kmd_buf, + struct cam_isp_prepare_hw_update_data *prepare_hw_data) +{ + int mmu_hdl = -1, rc = 0; + dma_addr_t iova_addr; + uint32_t frame_header_iova, padded_bytes = 0; + size_t len; + struct cam_ife_hw_mgr *hw_mgr = &g_ife_hw_mgr; + + mmu_hdl = cam_mem_is_secure_buf( + kmd_buf->handle) ? + hw_mgr->mgr_common.img_iommu_hdl_secure : + hw_mgr->mgr_common.img_iommu_hdl; + + rc = cam_mem_get_io_buf(kmd_buf->handle, mmu_hdl, + &iova_addr, &len); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to get io addr for handle = %d for mmu_hdl = %u", + kmd_buf->handle, mmu_hdl); + return rc; + } + + frame_header_iova = (uint32_t)iova_addr; + frame_header_iova += kmd_buf->offset; + + /* frame header address needs to be 16 byte aligned */ + if (frame_header_iova % 16) { + padded_bytes = (uint32_t)(16 - (frame_header_iova % 16)); + iova_addr += padded_bytes; + } + + prepare_hw_data->frame_header_iova = frame_header_iova; + + /* update the padding if any for the cpu addr as well */ + prepare_hw_data->frame_header_cpu_addr = kmd_buf->cpu_addr + + (padded_bytes / 4); + + CAM_DBG(CAM_ISP, + "Frame Header iova_addr: %pK cpu_addr: %pK padded_bytes: %llu", + prepare_hw_data->frame_header_iova, + prepare_hw_data->frame_header_cpu_addr, + padded_bytes); + + /* Reserve memory for frame header */ + kmd_buf->used_bytes += 128; + kmd_buf->offset += kmd_buf->used_bytes; + + return rc; +} + static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { @@ -5566,7 +5629,9 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, struct cam_kmd_buf_info kmd_buf; uint32_t i; bool fill_fence = true; + bool frame_header_enable = false; struct cam_isp_prepare_hw_update_data *prepare_hw_data; + struct cam_isp_frame_header_info frame_header_info; if (!hw_mgr_priv || !prepare_hw_update_args) { CAM_ERR(CAM_ISP, "Invalid args"); @@ -5593,6 +5658,15 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, if (rc) return rc; + if (ctx->use_frame_header_ts) { + rc = cam_ife_mgr_util_insert_frame_header(&kmd_buf, + prepare_hw_data); + if (rc) + return rc; + + frame_header_enable = true; + } + rc = cam_packet_util_process_patches(prepare->packet, hw_mgr->mgr_common.cmd_iommu_hdl, hw_mgr->mgr_common.cmd_iommu_hdl_secure); @@ -5641,13 +5715,23 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } + memset(&frame_header_info, 0, + sizeof(struct cam_isp_frame_header_info)); + if (frame_header_enable) { + frame_header_info.frame_header_enable = true; + frame_header_info.frame_header_iova_addr = + prepare_hw_data->frame_header_iova; + } + /* get IO buffers */ - rc = cam_isp_add_io_buffers(hw_mgr->mgr_common.img_iommu_hdl, + rc = cam_isp_add_io_buffers( + hw_mgr->mgr_common.img_iommu_hdl, hw_mgr->mgr_common.img_iommu_hdl_secure, prepare, ctx->base[i].idx, &kmd_buf, ctx->res_list_ife_out, &ctx->res_list_ife_in_rd, - CAM_IFE_HW_OUT_RES_MAX, fill_fence); + CAM_IFE_HW_OUT_RES_MAX, fill_fence, + &frame_header_info); if (rc) { CAM_ERR(CAM_ISP, @@ -5659,6 +5743,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, /* fence map table entries need to fill only once in the loop */ if (fill_fence) fill_fence = false; + + if (frame_header_info.frame_header_res_id && + frame_header_enable) { + frame_header_enable = false; + prepare_hw_data->frame_header_res_id = + frame_header_info.frame_header_res_id; + + CAM_DBG(CAM_ISP, + "Frame header enabled for res_id 0x%x cpu_addr %pK", + prepare_hw_data->frame_header_res_id, + prepare_hw_data->frame_header_cpu_addr); + } } /* @@ -6643,10 +6739,15 @@ static int cam_ife_hw_mgr_handle_hw_sof( rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, CAM_ISP_HW_EVENT_SOF); if (!rc) { - cam_ife_mgr_cmd_get_sof_timestamp(ife_hw_mgr_ctx, + cam_ife_mgr_cmd_get_sof_timestamp( + ife_hw_mgr_ctx, &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); + /* if frame header is enabled reset qtimer ts */ + if (ife_hw_mgr_ctx->use_frame_header_ts) + sof_done_event_data.timestamp = 0x0; + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 7d68b180e5c4..79033e3458d7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -82,6 +82,8 @@ struct cam_ife_hw_mgr_debug { * @init_done indicate whether init hw is done * @is_fe_enable indicate whether fetch engine\read path is enabled * @is_dual indicate whether context is in dual VFE mode + * @custom_enabled update the flag if context is connected to custom HW + * @use_frame_header_ts obtain qtimer ts using frame header * @ts captured timestamp when the ctx is acquired */ struct cam_ife_hw_mgr_ctx { @@ -129,6 +131,8 @@ struct cam_ife_hw_mgr_ctx { bool init_done; bool is_fe_enable; bool is_dual; + bool custom_enabled; + bool use_frame_header_ts; struct timespec64 ts; }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 1eaa695d362e..a3e946e802a8 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -3809,6 +3809,7 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, uint32_t i; bool fill_fence = true; struct cam_isp_prepare_hw_update_data *prepare_hw_data; + struct cam_isp_frame_header_info frame_header_info; if (!hw_mgr_priv || !prepare_hw_update_args) { CAM_ERR(CAM_ISP, "Invalid args"); @@ -3886,13 +3887,18 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, } } + memset(&frame_header_info, 0, + sizeof(struct cam_isp_frame_header_info)); + frame_header_info.frame_header_enable = false; + /* get IO buffers */ rc = cam_isp_add_io_buffers(hw_mgr->mgr_common.img_iommu_hdl, hw_mgr->mgr_common.img_iommu_hdl_secure, prepare, ctx->base[i].idx, &kmd_buf, ctx->res_list_tfe_out, NULL, - CAM_TFE_HW_OUT_RES_MAX, fill_fence); + CAM_TFE_HW_OUT_RES_MAX, fill_fence, + &frame_header_info); if (rc) { CAM_ERR(CAM_ISP, diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index ce3f895f4bd8..b6027db649fb 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -463,7 +463,8 @@ int cam_isp_add_io_buffers( struct cam_isp_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, + struct cam_isp_frame_header_info *frame_header_info) { int rc = 0; dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; @@ -480,6 +481,7 @@ int cam_isp_add_io_buffers( uint32_t i, j, num_out_buf, num_in_buf; uint32_t res_id_out, res_id_in, plane_id; uint32_t io_cfg_used_bytes, num_ent; + uint64_t iova_addr; size_t size; int32_t hdl; int mmu_hdl; @@ -693,6 +695,21 @@ int cam_isp_add_io_buffers( wm_update.image_buf = io_addr; wm_update.num_buf = plane_id; wm_update.io_cfg = &io_cfg[i]; + wm_update.frame_header = 0; + iova_addr = frame_header_info->frame_header_iova_addr; + if ((frame_header_info->frame_header_enable) && + !(frame_header_info->frame_header_res_id)) { + wm_update.frame_header = iova_addr; + frame_header_info->frame_header_res_id = + res->res_id; + wm_update.local_id = + prepare->packet->header.request_id; + CAM_DBG(CAM_ISP, + "Frame header enabled for res: 0x%x iova: %pK", + frame_header_info->frame_header_res_id, + wm_update.frame_header); + } + update_buf.cmd.size = kmd_buf_remain_size; update_buf.wm_update = &wm_update; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index 8948b2a416c5..ca56b155e9ba 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -34,6 +34,19 @@ struct cam_isp_generic_blob_info { struct cam_kmd_buf_info *kmd_buf_info; }; +/* + * struct cam_isp_frame_header_info + * + * @frame_header_enable: Enable frame header + * @frame_header_iova_addr: frame header iova + * @frame_header_res_id: res id for which frame header is enabled + */ +struct cam_isp_frame_header_info { + bool frame_header_enable; + uint64_t frame_header_iova_addr; + uint32_t frame_header_res_id; +}; + /* * cam_isp_add_change_base() * @@ -127,7 +140,7 @@ int cam_isp_add_command_buffers( * @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 - * + * @frame_header_info: Frame header related params * @return: 0 for success * -EINVAL for Fail */ @@ -140,7 +153,8 @@ int cam_isp_add_io_buffers( struct cam_isp_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, + struct cam_isp_frame_header_info *frame_header_info); /* * cam_isp_add_reg_update() diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 86b47da0b313..f68a6ec3a84e 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -121,6 +121,9 @@ struct cam_isp_bw_config_internal { * @packet_opcode_type: Packet header opcode in the packet header * this opcode defines, packet is init packet or * update packet + * @frame_header_cpu_addr: Frame header cpu addr + * @frame_header_iova: Frame header iova + * @frame_header_res_id: Out port res_id corresponding to frame header * @bw_config_version: BW config version indicator * @bw_config: BW config information * @bw_config_v2: BW config info for AXI bw voting v2 @@ -133,10 +136,13 @@ struct cam_isp_bw_config_internal { struct cam_isp_prepare_hw_update_data { void *isp_mgr_ctx; uint32_t packet_opcode_type; + uint32_t *frame_header_cpu_addr; + uint64_t frame_header_iova; + uint32_t frame_header_res_id; uint32_t bw_config_version; struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; struct cam_isp_bw_config_internal_v2 bw_config_v2[CAM_IFE_HW_NUM_MAX]; - bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; + bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; struct cam_cmd_buf_desc reg_dump_buf_desc[ CAM_REG_DUMP_MAX_BUF_ENTRIES]; uint32_t num_reg_dump_buf; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index b7f2692b61a0..c242bdaa174c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSID_HW_INTF_H_ @@ -187,9 +187,9 @@ struct cam_csid_reset_cfg_args { /** * struct cam_csid_get_time_stamp_args- time stamp capture arguments - * @res_node : resource to get the time stamp - * @time_stamp_val : captured time stamp - * @boot_timestamp : boot time stamp + * @node_res : resource to get the time stamp + * @time_stamp_val : captured time stamp + * @boot_timestamp : boot time stamp */ struct cam_csid_get_time_stamp_args { struct cam_isp_resource_node *node_res; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 5fd1172a4033..02c1948e90a2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -211,12 +211,16 @@ struct cam_isp_hw_cmd_buf_update { * * @ image_buf: image buffer address array * @ num_buf: Number of buffers in the image_buf array + * @ frame_header: frame header iova + * @ local_id: local id for the wm * @ io_cfg: IO buffer config information sent from UMD * */ struct cam_isp_hw_get_wm_update { dma_addr_t *image_buf; uint32_t num_buf; + uint64_t frame_header; + uint32_t local_id; struct cam_buf_io_cfg *io_cfg; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index ebe2e1d4e9e6..d6f66dffb6f5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3010,6 +3010,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, uint32_t i, j, k, size = 0; uint32_t frame_inc = 0, val; uint32_t loop_size = 0; + bool frame_header_enable = false; bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; @@ -3043,6 +3044,27 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, wm_data = vfe_out_data->wm_res[i]->res_priv; ubwc_client = wm_data->hw_regs->ubwc_regs; + /* Disable frame header in case it was previously enabled */ + if ((wm_data->en_cfg) & (1 << 2)) + wm_data->en_cfg &= ~(1 << 2); + + if (update_buf->wm_update->frame_header && + !frame_header_enable) { + wm_data->en_cfg |= 1 << 2; + frame_header_enable = true; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_header_addr, + update_buf->wm_update->frame_header); + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_header_cfg, + update_buf->wm_update->local_id); + CAM_DBG(CAM_ISP, + "WM: %d en_cfg 0x%x frame_header %pK local_id %u", + wm_data->index, wm_data->en_cfg, + update_buf->wm_update->frame_header, + update_buf->wm_update->local_id); + } + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->cfg, wm_data->en_cfg); CAM_DBG(CAM_ISP, "WM:%d en_cfg 0x%X", From 131b4115d56367bd8482378bcdae6879ac116b74 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 30 Jan 2020 12:43:55 -0800 Subject: [PATCH 272/790] msm: camera: isp: Add support for PHY TPG This change adds support for PHY TPG version 102 hardware. CRs-Fixed: 2608550 Change-Id: I92387b08e8a91bb0c6a77b5301ebc30c7cb6f252 Signed-off-by: Vishalsingh Hajeri Signed-off-by: Venkat Chinta Signed-off-by: Mukund Madhusudan Atre --- drivers/Makefile | 9 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 92 +++++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 6 + drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 2 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 18 +- .../isp_hw/include/cam_top_tpg_hw_intf.h | 19 +- .../isp_hw_mgr/isp_hw/top_tpg/Makefile | 15 - .../isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c | 48 +++ .../isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h | 12 + .../{cam_top_tpg_v1.h => cam_top_tpg101.h} | 17 +- .../isp_hw/top_tpg/cam_top_tpg102.h | 50 +++ .../isp_hw/top_tpg/cam_top_tpg_core.c | 383 +---------------- .../isp_hw/top_tpg/cam_top_tpg_core.h | 70 +--- .../isp_hw/top_tpg/cam_top_tpg_dev.c | 46 +-- .../isp_hw/top_tpg/cam_top_tpg_v1.c | 54 --- .../isp_hw/top_tpg/cam_top_tpg_ver1.c | 385 ++++++++++++++++++ .../isp_hw/top_tpg/cam_top_tpg_ver1.h | 55 +++ .../isp_hw/top_tpg/cam_top_tpg_ver2.c | 242 +++++++++++ .../isp_hw/top_tpg/cam_top_tpg_ver2.h | 44 ++ drivers/camera_main.c | 8 +- drivers/camera_main.h | 3 +- include/uapi/camera/media/cam_isp_ife.h | 6 +- 22 files changed, 1055 insertions(+), 529 deletions(-) delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h rename drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/{cam_top_tpg_v1.h => cam_top_tpg101.h} (76%) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.h diff --git a/drivers/Makefile b/drivers/Makefile index 8f4432bf6dfd..2ab203025f31 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -85,6 +85,11 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.o \ cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.o \ cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o \ cam_isp/isp_hw_mgr/cam_isp_hw_mgr.o \ cam_isp/isp_hw_mgr/cam_ife_hw_mgr.o \ cam_isp/cam_isp_dev.o \ @@ -197,7 +202,9 @@ camera-$(CONFIG_SPECTRA_CAMERA) += \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ - cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.o + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o + camera-y += camera_main.o diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index e2a2cecf7235..c6e5e9d75223 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -424,6 +424,17 @@ static int cam_ife_hw_mgr_init_hw( struct cam_isp_hw_mgr_res *hw_mgr_res; int rc = 0, i; + if (ctx->is_tpg) { + CAM_DBG(CAM_ISP, "INIT TPG ... in ctx id:%d", + ctx->ctx_index); + rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_tpg); + if (rc) { + CAM_ERR(CAM_ISP, "Can not INIT TFE TPG(id :%d)", + ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx); + goto deinit; + } + } + CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", ctx->ctx_index); /* INIT IFE CID */ @@ -840,6 +851,10 @@ static int cam_ife_hw_mgr_release_hw_for_ctx( cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &hw_mgr_res); } + /* ife phy tpg resource */ + if (ife_ctx->is_tpg) + cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_tpg); + /* ife root node */ if (ife_ctx->res_list_ife_in.res_type != CAM_ISP_RESOURCE_UNINT) cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_in); @@ -1862,6 +1877,48 @@ end: } +static int cam_ife_hw_mgr_acquire_tpg( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + uint32_t num_inport) +{ + int rc = -EINVAL; + uint32_t i; + struct cam_ife_hw_mgr *ife_hw_mgr; + struct cam_hw_intf *hw_intf; + struct cam_top_tpg_ver2_reserve_args tpg_reserve; + + ife_hw_mgr = ife_ctx->hw_mgr; + + for (i = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) { + if (!ife_hw_mgr->tpg_devices[i]) + continue; + + hw_intf = ife_hw_mgr->tpg_devices[i]; + tpg_reserve.num_inport = num_inport; + tpg_reserve.node_res = NULL; + tpg_reserve.in_port = in_port; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &tpg_reserve, sizeof(tpg_reserve)); + if (!rc) + break; + } + + if (i == CAM_TOP_TPG_HW_NUM_MAX || !tpg_reserve.node_res) { + CAM_ERR(CAM_ISP, "Can not acquire IFE TPG"); + rc = -EINVAL; + goto end; + } + + ife_ctx->res_list_tpg.res_type = in_port->res_type; + ife_ctx->res_list_tpg.hw_res[0] = tpg_reserve.node_res; + ife_ctx->is_tpg = true; + +end: + return rc; +} + static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, @@ -2755,6 +2812,16 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->use_frame_header_ts = true; } + if ((in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || + (in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) + rc = cam_ife_hw_mgr_acquire_tpg(ife_ctx, in_port, + acquire_hw_info->num_inputs); + + if (rc) { + CAM_ERR(CAM_ISP, "can not acquire TPG resource"); + goto free_mem; + } + rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, &num_pix_port_per_in, &num_rdi_port_per_in, &acquire_args->acquired_hw_id[i], @@ -3752,6 +3819,9 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) if (cam_cdm_stream_off(ctx->cdm_handle)) CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); + if (ctx->is_tpg) + cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_tpg); + cam_ife_hw_mgr_deinit_hw(ctx); CAM_DBG(CAM_ISP, "Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc); @@ -4077,6 +4147,17 @@ start_only: } } + if (ctx->is_tpg) { + CAM_DBG(CAM_ISP, "START TPG HW ... in ctx id:%d", + ctx->ctx_index); + rc = cam_ife_hw_mgr_start_hw_res(&ctx->res_list_tpg, ctx); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start IFE TPG (%d)", + ctx->res_list_tpg.res_id); + goto err; + } + } + /* Start IFE root node: do nothing */ CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index); @@ -7100,6 +7181,16 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return -EINVAL; } + /* fill tpg hw intf information */ + for (i = 0, j = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) { + rc = cam_top_tpg_hw_init(&g_ife_hw_mgr.tpg_devices[i], i); + if (!rc) + j++; + } + if (!j) + CAM_ERR(CAM_ISP, "no valid IFE TPG HW"); + + cam_ife_hw_mgr_sort_dev_with_caps(&g_ife_hw_mgr); /* setup ife context list */ @@ -7146,6 +7237,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) sizeof(g_ife_hw_mgr.ctx_pool[i])); INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].list); + INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_tpg.list); INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_in.list); 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); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 79033e3458d7..91caeb314f41 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -11,6 +11,7 @@ #include "cam_isp_hw_mgr.h" #include "cam_vfe_hw_intf.h" #include "cam_ife_csid_hw_intf.h" +#include "cam_top_tpg_hw_intf.h" #include "cam_tasklet_util.h" /* IFE resource constants */ @@ -48,6 +49,7 @@ struct cam_ife_hw_mgr_debug { * @slave_hw_idx: hw index for slave core * @hw_mgr: IFE hw mgr which owns this context * @ctx_in_use: flag to tell whether context is active + * @res_list_tpg: TPG resource list * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be * one. * @res_list_csid: CSID resource list @@ -85,6 +87,7 @@ struct cam_ife_hw_mgr_debug { * @custom_enabled update the flag if context is connected to custom HW * @use_frame_header_ts obtain qtimer ts using frame header * @ts captured timestamp when the ctx is acquired + * @is_tpg indicate whether context is using PHY TPG */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -97,6 +100,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t ctx_in_use; struct cam_isp_hw_mgr_res res_list_ife_in; + struct cam_isp_hw_mgr_res res_list_tpg; struct list_head res_list_ife_cid; struct list_head res_list_ife_csid; struct list_head res_list_ife_src; @@ -134,6 +138,7 @@ struct cam_ife_hw_mgr_ctx { bool custom_enabled; bool use_frame_header_ts; struct timespec64 ts; + bool is_tpg; }; /** @@ -155,6 +160,7 @@ struct cam_ife_hw_mgr_ctx { */ struct cam_ife_hw_mgr { struct cam_isp_hw_mgr mgr_common; + struct cam_hw_intf *tpg_devices[CAM_TOP_TPG_HW_NUM_MAX]; struct cam_hw_intf *csid_devices[CAM_IFE_CSID_HW_NUM_MAX]; struct cam_hw_intf *ife_devices[CAM_IFE_HW_NUM_MAX]; struct cam_soc_reg_map *cdm_reg_map[CAM_IFE_HW_NUM_MAX]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index a3e946e802a8..fc4051011585 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1350,7 +1350,7 @@ static int cam_tfe_hw_mgr_acquire_tpg( uint32_t i, j = 0; struct cam_tfe_hw_mgr *tfe_hw_mgr; struct cam_hw_intf *hw_intf; - struct cam_top_tpg_hw_reserve_resource_args tpg_reserve; + struct cam_top_tpg_ver1_reserve_args tpg_reserve; tfe_hw_mgr = tfe_ctx->hw_mgr; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index d2b04752e2e2..b7787a32ff97 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -25,6 +25,10 @@ #define CAM_IFE_CSID_TPG_VC_VAL 0xA #define CAM_IFE_CSID_TPG_DT_VAL 0x2B +/* CSIPHY TPG VC/DT values */ +#define CAM_IFE_CSI_TPG_VC_VAL 0x0 +#define CAM_IFE_CSI_TPG_DT_VAL 0x2B + /* Timeout values in usec */ #define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000 #define CAM_IFE_CSID_TIMEOUT_ALL_US 100000 @@ -957,6 +961,12 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->tpg_cfg.height); cid_data->tpg_set = 1; + } else if (cid_reserv->in_port->res_type == + CAM_ISP_IFE_IN_RES_CPHY_TPG_0) { + csid_hw->csi2_rx_cfg.phy_sel = 0; + } else if (cid_reserv->in_port->res_type == + CAM_ISP_IFE_IN_RES_CPHY_TPG_1) { + csid_hw->csi2_rx_cfg.phy_sel = 1; } else { csid_hw->csi2_rx_cfg.phy_sel = (cid_reserv->in_port->res_type & 0xFF) - 1; @@ -1129,9 +1139,10 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, reserve->in_port->line_start, reserve->in_port->line_stop, path_data->crop_enable); - if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { - path_data->dt = CAM_IFE_CSID_TPG_DT_VAL; - path_data->vc = CAM_IFE_CSID_TPG_VC_VAL; + if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || + (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) { + path_data->dt = CAM_IFE_CSI_TPG_DT_VAL; + path_data->vc = CAM_IFE_CSI_TPG_VC_VAL; } else { path_data->dt = reserve->in_port->dt[0]; path_data->vc = reserve->in_port->vc[0]; @@ -4459,6 +4470,7 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->num_pix + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis + ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis; + /* Initialize the CID resource */ for (i = 0; i < num_paths; i++) { ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h index 17086b50cfc3..fdbc6639bd87 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h @@ -8,6 +8,7 @@ #include "cam_isp_hw.h" #include "cam_hw_intf.h" +#include "cam_ife_csid_hw_intf.h" /* Max top tpg instance */ #define CAM_TOP_TPG_HW_NUM_MAX 2 @@ -37,7 +38,7 @@ struct cam_top_tpg_hw_caps { }; /** - * struct cam_tfe_csid_hw_reserve_resource_args- hw reserve + * struct cam_top_tpg_ver1_reserve_args- hw reserve * @num_inport: number of inport * TPG support 4 dt types, each different dt comes in different * in port. @@ -45,12 +46,26 @@ struct cam_top_tpg_hw_caps { * @node_res : Reserved resource structure pointer * */ -struct cam_top_tpg_hw_reserve_resource_args { +struct cam_top_tpg_ver1_reserve_args { uint32_t num_inport; struct cam_isp_tfe_in_port_info *in_port[CAM_TOP_TPG_MAX_SUPPORTED_DT]; struct cam_isp_resource_node *node_res; }; +/** + * struct cam_top_tpg_ver2_reserve_args + * @num_inport: number of inport + * TPG supports 1 VC/DT + * @in_port : Input port resource info structure pointer + * @node_res : Reserved resource structure pointer + * + */ +struct cam_top_tpg_ver2_reserve_args { + uint32_t num_inport; + struct cam_isp_in_port_generic_info *in_port; + struct cam_isp_resource_node *node_res; +}; + /** * cam_top_tpg_hw_init() * diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile deleted file mode 100644 index f08acab1e1dc..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_top_tpg_dev.o cam_top_tpg_soc.o cam_top_tpg_core.o -obj-$(CONFIG_SPECTRA_CAMERA) += cam_top_tpg_v1.o \ No newline at end of file diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c new file mode 100644 index 000000000000..9eafcf4da636 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_top_tpg101.h" +#include "cam_top_tpg102.h" +#include "cam_top_tpg_core.h" +#include "cam_top_tpg_dev.h" +#include "camera_main.h" + +static const struct of_device_id cam_top_tpg_dt_match[] = { + { + .compatible = "qcom,tpg101", + .data = &cam_top_tpg101_hw_info, + }, + { + .compatible = "qcom,tpg102", + .data = &cam_top_tpg102_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_top_tpg_dt_match); + +struct platform_driver cam_top_tpg_driver = { + .probe = cam_top_tpg_probe, + .remove = cam_top_tpg_remove, + .driver = { + .name = "cam_top_tpg", + .of_match_table = cam_top_tpg_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_top_tpg_init_module(void) +{ + return platform_driver_register(&cam_top_tpg_driver); +} + +void cam_top_tpg_exit_module(void) +{ + platform_driver_unregister(&cam_top_tpg_driver); +} + +MODULE_DESCRIPTION("CAM TOP TPG driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h new file mode 100644 index 000000000000..6332469056f0 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_H_ +#define _CAM_TOP_TPG_H_ + +int cam_top_tpg_init_module(void); +void cam_top_tpg_exit_module(void); + +#endif /*_CAM_TOP_TPG_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h similarity index 76% rename from drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h rename to drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h index 2084b811e2ff..0b99a3f6d1ba 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h @@ -3,12 +3,13 @@ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ -#ifndef _CAM_TOP_TPG_V1_H_ -#define _CAM_TOP_TPG_V1_H_ +#ifndef _CAM_TOP_TPG101_H_ +#define _CAM_TOP_TPG101_H_ +#include "cam_top_tpg_ver1.h" #include "cam_top_tpg_core.h" -static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = { +static struct cam_top_tpg_ver1_reg_offset cam_top_tpg101_reg = { .tpg_hw_version = 0x0, .tpg_hw_status = 0x4, .tpg_ctrl = 0x60, @@ -50,7 +51,11 @@ static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = { .top_mux_reg_offset = 0x1C, }; -int cam_top_tpg_v1_init_module(void); -void cam_top_tpg_v1_exit_module(void); +struct cam_top_tpg_hw_info cam_top_tpg101_hw_info = { + .tpg_reg = &cam_top_tpg101_reg, + .hw_dts_version = CAM_TOP_TPG_VERSION_1, + .csid_max_clk = 426400000, + .phy_max_clk = 384000000, +}; -#endif /*_CAM_TOP_TPG_V1_H_ */ +#endif /* _CAM_TOP_TPG101_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h new file mode 100644 index 000000000000..ce2f2c73a070 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG102_H_ +#define _CAM_TOP_TPG102_H_ + +#include "cam_top_tpg_ver2.h" +#include "cam_top_tpg_core.h" + +static struct cam_top_tpg_ver2_reg_offset cam_top_tpg102_reg = { + .tpg_hw_version = 0x0, + .tpg_hw_status = 0x4, + .tpg_module_cfg = 0x60, + .tpg_cfg_0 = 0x68, + .tpg_cfg_1 = 0x6C, + .tpg_cfg_2 = 0x70, + .tpg_cfg_3 = 0x74, + .tpg_spare = 0xFC, + .top_mux_sel = 0x90, + /* configurations */ + .major_version = 1, + .minor_version = 0, + .version_incr = 0, + .tpg_module_en = 1, + .tpg_mux_sel_en = 1, + .tpg_mux_sel_tpg_0_shift = 0, + .tpg_mux_sel_tpg_1_shift = 8, + .tpg_en_shift_val = 0, + .tpg_phy_sel_shift_val = 3, + .tpg_num_active_lines_shift = 4, + .tpg_fe_pkt_en_shift = 2, + .tpg_fs_pkt_en_shift = 1, + .tpg_line_interleaving_mode_shift = 10, + .tpg_num_dts_shift_val = 8, + .tpg_v_blank_cnt_shift = 12, + .tpg_dt_encode_format_shift = 16, + .tpg_payload_mode_color = 0x8, + .tpg_split_en_shift = 5, +}; + +struct cam_top_tpg_hw_info cam_top_tpg102_hw_info = { + .tpg_reg = &cam_top_tpg102_reg, + .hw_dts_version = CAM_TOP_TPG_VERSION_2, + .csid_max_clk = 426400000, + .phy_max_clk = 384000000, +}; + +#endif /* _CAM_TOP_TPG102_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c index 6a544faf548f..64b776623d72 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c @@ -13,210 +13,8 @@ #include "cam_io_util.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" - - -static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = { - 0, - 3, - 1, - 2 -}; - -static int cam_top_tpg_get_format(uint32_t in_format, - uint32_t *tpg_encode_format) -{ - int rc = 0; - - switch (in_format) { - case CAM_FORMAT_MIPI_RAW_6: - *tpg_encode_format = 0; - break; - case CAM_FORMAT_MIPI_RAW_8: - *tpg_encode_format = 1; - break; - case CAM_FORMAT_MIPI_RAW_10: - *tpg_encode_format = 2; - break; - case CAM_FORMAT_MIPI_RAW_12: - *tpg_encode_format = 3; - break; - case CAM_FORMAT_MIPI_RAW_14: - *tpg_encode_format = 4; - break; - case CAM_FORMAT_MIPI_RAW_16: - *tpg_encode_format = 4; - break; - default: - CAM_ERR(CAM_ISP, "Unsupported input encode format %d", - in_format); - rc = -EINVAL; - } - return rc; -} - -static int cam_top_tpg_get_hw_caps(void *hw_priv, - void *get_hw_cap_args, uint32_t arg_size) -{ - int rc = 0; - struct cam_top_tpg_hw_caps *hw_caps; - struct cam_top_tpg_hw *tpg_hw; - struct cam_hw_info *tpg_hw_info; - - if (!hw_priv || !get_hw_cap_args) { - CAM_ERR(CAM_ISP, "TPG: Invalid args"); - return -EINVAL; - } - - tpg_hw_info = (struct cam_hw_info *)hw_priv; - tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; - hw_caps = (struct cam_top_tpg_hw_caps *) get_hw_cap_args; - - hw_caps->major_version = tpg_hw->tpg_info->tpg_reg->major_version; - hw_caps->minor_version = tpg_hw->tpg_info->tpg_reg->minor_version; - hw_caps->version_incr = tpg_hw->tpg_info->tpg_reg->version_incr; - - CAM_DBG(CAM_ISP, - "TPG:%d major:%d minor:%d ver :%d", - tpg_hw->hw_intf->hw_idx, hw_caps->major_version, - hw_caps->minor_version, hw_caps->version_incr); - - return rc; -} - -static int cam_top_tpg_reserve(void *hw_priv, - void *reserve_args, uint32_t arg_size) -{ - int rc = 0; - struct cam_top_tpg_hw *tpg_hw; - struct cam_hw_info *tpg_hw_info; - struct cam_top_tpg_hw_reserve_resource_args *reserv; - struct cam_top_tpg_cfg *tpg_data; - uint32_t encode_format = 0; - uint32_t i; - - if (!hw_priv || !reserve_args || (arg_size != - sizeof(struct cam_top_tpg_hw_reserve_resource_args))) { - CAM_ERR(CAM_ISP, "TPG: Invalid args"); - return -EINVAL; - } - - tpg_hw_info = (struct cam_hw_info *)hw_priv; - tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; - reserv = (struct cam_top_tpg_hw_reserve_resource_args *)reserve_args; - - if (reserv->num_inport <= 0 || - reserv->num_inport > CAM_TOP_TPG_MAX_SUPPORTED_DT) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG: %u invalid input num port:%d", - tpg_hw->hw_intf->hw_idx, reserv->num_inport); - return -EINVAL; - } - - mutex_lock(&tpg_hw->hw_info->hw_mutex); - if (tpg_hw->tpg_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - mutex_unlock(&tpg_hw->hw_info->hw_mutex); - return -EINVAL; - } - - if ((reserv->in_port[0]->vc > 0xF) || - (reserv->in_port[0]->lane_num <= 0 || - reserv->in_port[0]->lane_num > 4) || - (reserv->in_port[0]->pix_pattern > 4) || - (reserv->in_port[0]->lane_type >= 2)) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d %d %d", - tpg_hw->hw_intf->hw_idx, reserv->in_port[0]->vc, - reserv->in_port[0]->lane_num, - reserv->in_port[0]->pix_pattern, - reserv->in_port[0]->lane_type); - mutex_unlock(&tpg_hw->hw_info->hw_mutex); - return -EINVAL; - } - rc = cam_top_tpg_get_format(reserv->in_port[0]->format, - &encode_format); - if (rc) - goto error; - - CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx); - - tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; - tpg_data->vc_num = reserv->in_port[0]->vc; - tpg_data->phy_sel = reserv->in_port[0]->lane_type; - tpg_data->num_active_lanes = reserv->in_port[0]->lane_num; - tpg_data->h_blank_count = reserv->in_port[0]->sensor_hbi; - tpg_data->v_blank_count = reserv->in_port[0]->sensor_vbi; - tpg_data->pix_pattern = reserv->in_port[0]->pix_pattern; - tpg_data->dt_cfg[0].data_type = reserv->in_port[0]->dt; - tpg_data->dt_cfg[0].frame_height = reserv->in_port[0]->height; - if (reserv->in_port[0]->usage_type) - tpg_data->dt_cfg[0].frame_width = - ((reserv->in_port[0]->right_end - - reserv->in_port[0]->left_start) + 1); - else - tpg_data->dt_cfg[0].frame_width = - reserv->in_port[0]->left_width; - tpg_data->dt_cfg[0].encode_format = encode_format; - tpg_data->num_active_dts = 1; - - CAM_DBG(CAM_ISP, - "TPG:%u vc_num:%d dt:%d phy:%d lines:%d pattern:%d format:%d", - tpg_hw->hw_intf->hw_idx, - tpg_data->vc_num, tpg_data->dt_cfg[0].data_type, - tpg_data->phy_sel, tpg_data->num_active_lanes, - tpg_data->pix_pattern, - tpg_data->dt_cfg[0].encode_format); - - CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d h blank:%d v blank:%d", - tpg_hw->hw_intf->hw_idx, - tpg_data->dt_cfg[0].frame_height, - tpg_data->dt_cfg[0].frame_width, - tpg_data->h_blank_count, - tpg_data->v_blank_count); - - if (reserv->num_inport == 1) - goto end; - - for (i = 1; i < reserv->num_inport; i++) { - if ((tpg_data->vc_num != reserv->in_port[i]->vc) || - (tpg_data->phy_sel != reserv->in_port[i]->lane_type) || - (tpg_data->num_active_lanes != - reserv->in_port[i]->lane_num) || - (tpg_data->pix_pattern != - reserv->in_port[i]->pix_pattern)) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "TPG: %u invalid DT config for tpg", - tpg_hw->hw_intf->hw_idx); - rc = -EINVAL; - goto error; - } - rc = cam_top_tpg_get_format(reserv->in_port[0]->format, - &encode_format); - if (rc) - return rc; - - tpg_data->dt_cfg[i].data_type = reserv->in_port[i]->dt; - tpg_data->dt_cfg[i].frame_height = - reserv->in_port[i]->height; - tpg_data->dt_cfg[i].frame_width = - reserv->in_port[i]->left_width; - tpg_data->dt_cfg[i].encode_format = encode_format; - tpg_data->num_active_dts++; - - CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d dt:%d format:%d", - tpg_hw->hw_intf->hw_idx, - tpg_data->dt_cfg[i].frame_height, - tpg_data->dt_cfg[i].frame_width, - tpg_data->dt_cfg[i].data_type, - tpg_data->dt_cfg[i].encode_format); - - } -end: - reserv->node_res = &tpg_hw->tpg_res; - tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED; -error: - mutex_unlock(&tpg_hw->hw_info->hw_mutex); - CAM_DBG(CAM_ISP, "exit rc %u", rc); - - return rc; -} +#include "cam_top_tpg_ver1.h" +#include "cam_top_tpg_ver2.h" static int cam_top_tpg_release(void *hw_priv, void *release_args, uint32_t arg_size) @@ -266,9 +64,8 @@ static int cam_top_tpg_init_hw(void *hw_priv, struct cam_top_tpg_hw *tpg_hw; struct cam_hw_info *tpg_hw_info; struct cam_isp_resource_node *tpg_res; - const struct cam_top_tpg_reg_offset *tpg_reg; struct cam_hw_soc_info *soc_info; - uint32_t val, clk_lvl; + uint32_t clk_lvl; if (!hw_priv || !init_args || (arg_size != sizeof(struct cam_isp_resource_node))) { @@ -278,8 +75,7 @@ static int cam_top_tpg_init_hw(void *hw_priv, tpg_hw_info = (struct cam_hw_info *)hw_priv; tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; - tpg_res = (struct cam_isp_resource_node *)init_args; - tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *)init_args; soc_info = &tpg_hw->hw_info->soc_info; if (tpg_res->res_type != CAM_ISP_RESOURCE_TPG) { @@ -321,11 +117,6 @@ static int cam_top_tpg_init_hw(void *hw_priv, tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP; - val = cam_io_r_mb(soc_info->reg_map[0].mem_base + - tpg_reg->tpg_hw_version); - CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x", - tpg_hw->hw_intf->hw_idx, val); - mutex_unlock(&tpg_hw->hw_info->hw_mutex); return rc; @@ -389,148 +180,6 @@ end: return rc; } -static int cam_top_tpg_start(void *hw_priv, void *start_args, - uint32_t arg_size) -{ - int rc = 0; - struct cam_top_tpg_hw *tpg_hw; - struct cam_hw_info *tpg_hw_info; - struct cam_hw_soc_info *soc_info; - struct cam_isp_resource_node *tpg_res; - const struct cam_top_tpg_reg_offset *tpg_reg; - struct cam_top_tpg_cfg *tpg_data; - uint32_t i, val; - - if (!hw_priv || !start_args || - (arg_size != sizeof(struct cam_isp_resource_node))) { - CAM_ERR(CAM_ISP, "TPG: Invalid args"); - return -EINVAL; - } - - tpg_hw_info = (struct cam_hw_info *)hw_priv; - tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; - tpg_reg = tpg_hw->tpg_info->tpg_reg; - tpg_res = (struct cam_isp_resource_node *)start_args; - tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv; - soc_info = &tpg_hw->hw_info->soc_info; - - if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || - (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { - CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", - tpg_hw->hw_intf->hw_idx, - tpg_res->res_type, tpg_res->res_state); - rc = -EINVAL; - goto end; - } - cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base + - tpg_reg->tpg_lfsr_seed); - - for (i = 0; i < tpg_data->num_active_dts; i++) { - val = (((tpg_data->dt_cfg[i].frame_width & 0xFFFF) << 16) | - (tpg_data->dt_cfg[i].frame_height & 0x3FFF)); - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + - tpg_reg->tpg_dt_0_cfg_0 + 0x10 * i); - cam_io_w_mb(tpg_data->dt_cfg[i].data_type, - soc_info->reg_map[0].mem_base + - tpg_reg->tpg_dt_0_cfg_1 + 0x10 * i); - val = ((tpg_data->dt_cfg[i].encode_format & 0xF) << - tpg_reg->tpg_dt_encode_format_shift) | - tpg_reg->tpg_payload_mode_color; - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + - tpg_reg->tpg_dt_0_cfg_2 + 0x10 * i); - } - - val = (tpg_num_dt_map[tpg_data->num_active_dts-1] << - tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num; - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0); - - /* - * if hblank is notset configureHBlank count 500 and - * V blank count is 600 - */ - - if (tpg_data->h_blank_count) - cam_io_w_mb(tpg_data->h_blank_count, - soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); - else - cam_io_w_mb(0x2581F4, - soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); - - val = (1 << tpg_reg->tpg_split_en_shift); - cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + - tpg_reg->tpg_common_gen_cfg); - - /* if VBI is notset configureVBI to 0xAFF */ - if (tpg_data->v_blank_count) - cam_io_w_mb(tpg_data->v_blank_count, - soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); - else - cam_io_w_mb(0xAFFF, - soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); - - /* Set the TOP tpg mux sel*/ - cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx), - soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); - - val = ((tpg_data->num_active_lanes - 1) << - tpg_reg->tpg_num_active_lines_shift) | - (1 << tpg_reg->tpg_fe_pkt_en_shift) | - (1 << tpg_reg->tpg_fs_pkt_en_shift) | - (tpg_data->phy_sel << tpg_reg->tpg_phy_sel_shift_val) | - (1 << tpg_reg->tpg_en_shift_val); - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); - - tpg_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; - - CAM_DBG(CAM_ISP, "TPG:%d started", tpg_hw->hw_intf->hw_idx); - -end: - return rc; -} - -static int cam_top_tpg_stop(void *hw_priv, - void *stop_args, uint32_t arg_size) -{ - int rc = 0; - struct cam_top_tpg_hw *tpg_hw; - struct cam_hw_info *tpg_hw_info; - struct cam_hw_soc_info *soc_info; - struct cam_isp_resource_node *tpg_res; - const struct cam_top_tpg_reg_offset *tpg_reg; - struct cam_top_tpg_cfg *tpg_data; - - if (!hw_priv || !stop_args || - (arg_size != sizeof(struct cam_isp_resource_node))) { - CAM_ERR(CAM_ISP, "TPG: Invalid args"); - return -EINVAL; - } - - tpg_hw_info = (struct cam_hw_info *)hw_priv; - tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; - tpg_reg = tpg_hw->tpg_info->tpg_reg; - tpg_res = (struct cam_isp_resource_node *) stop_args; - tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_state; - soc_info = &tpg_hw->hw_info->soc_info; - - if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || - (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) { - CAM_DBG(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", - tpg_hw->hw_intf->hw_idx, - tpg_res->res_type, tpg_res->res_state); - rc = -EINVAL; - goto end; - } - - cam_io_w_mb(0, soc_info->reg_map[0].mem_base + - tpg_reg->tpg_ctrl); - - tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; - - CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); -end: - return rc; -} - static int cam_top_tpg_read(void *hw_priv, void *read_args, uint32_t arg_size) { @@ -592,14 +241,14 @@ static int cam_top_tpg_process_cmd(void *hw_priv, return 0; } -int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, +int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf, uint32_t tpg_idx) { int rc = -EINVAL; struct cam_top_tpg_cfg *tpg_data; struct cam_hw_info *tpg_hw_info; struct cam_top_tpg_hw *tpg_hw = NULL; - uint32_t val = 0; + uint32_t hw_version = 0; if (tpg_idx >= CAM_TOP_TPG_HW_NUM_MAX) { CAM_ERR(CAM_ISP, "Invalid tpg index:%d", tpg_idx); @@ -620,7 +269,6 @@ int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, spin_lock_init(&tpg_hw->hw_info->hw_lock); spin_lock_init(&tpg_hw->lock_state); init_completion(&tpg_hw->hw_info->hw_complete); - init_completion(&tpg_hw->tpg_complete); rc = cam_top_tpg_init_soc_resources(&tpg_hw->hw_info->soc_info, @@ -630,18 +278,20 @@ int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, goto err; } - tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_get_hw_caps; tpg_hw->hw_intf->hw_ops.init = cam_top_tpg_init_hw; tpg_hw->hw_intf->hw_ops.deinit = cam_top_tpg_deinit_hw; tpg_hw->hw_intf->hw_ops.reset = NULL; - tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_reserve; tpg_hw->hw_intf->hw_ops.release = cam_top_tpg_release; - tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_start; - tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_stop; tpg_hw->hw_intf->hw_ops.read = cam_top_tpg_read; tpg_hw->hw_intf->hw_ops.write = cam_top_tpg_write; tpg_hw->hw_intf->hw_ops.process_cmd = cam_top_tpg_process_cmd; + hw_version = tpg_hw->tpg_info->hw_dts_version; + if (hw_version == CAM_TOP_TPG_VERSION_1) + cam_top_tpg_ver1_init(tpg_hw); + else if (hw_version == CAM_TOP_TPG_VERSION_2) + cam_top_tpg_ver2_init(tpg_hw); + tpg_hw->tpg_res.res_type = CAM_ISP_RESOURCE_TPG; tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; tpg_hw->tpg_res.hw_intf = tpg_hw->hw_intf; @@ -655,18 +305,13 @@ int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, cam_top_tpg_enable_soc_resources(&tpg_hw->hw_info->soc_info, CAM_SVS_VOTE); - val = cam_io_r_mb(tpg_hw->hw_info->soc_info.reg_map[0].mem_base + - tpg_hw->tpg_info->tpg_reg->tpg_hw_version); - CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x", - tpg_hw->hw_intf->hw_idx, val); - cam_top_tpg_disable_soc_resources(&tpg_hw->hw_info->soc_info); -err: +err: return rc; } -int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw) +int cam_top_tpg_deinit(struct cam_top_tpg_hw *top_tpg_hw) { int rc = -EINVAL; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h index 12f7cfc85e02..3dce37d94f9d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h @@ -3,13 +3,16 @@ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ -#ifndef _CAM_TOP_TPG_HW_H_ -#define _CAM_TOP_TPG_HW_H_ +#ifndef _CAM_TOP_TPG_CORE_H_ +#define _CAM_TOP_TPG_CORE_H_ #include "cam_hw.h" #include "cam_top_tpg_hw_intf.h" #include "cam_top_tpg_soc.h" +#define CAM_TOP_TPG_VERSION_1 0x10000001 +#define CAM_TOP_TPG_VERSION_2 0x10000002 + enum cam_top_tpg_encode_format { CAM_TOP_TPG_ENCODE_FORMAT_RAW6, CAM_TOP_TPG_ENCODE_FORMAT_RAW8, @@ -20,48 +23,6 @@ enum cam_top_tpg_encode_format { CAM_TOP_TPG_ENCODE_FORMAT_MAX, }; -struct cam_top_tpg_reg_offset { - uint32_t tpg_hw_version; - uint32_t tpg_hw_status; - uint32_t tpg_ctrl; - uint32_t tpg_vc_cfg0; - uint32_t tpg_vc_cfg1; - uint32_t tpg_lfsr_seed; - uint32_t tpg_dt_0_cfg_0; - uint32_t tpg_dt_1_cfg_0; - uint32_t tpg_dt_2_cfg_0; - uint32_t tpg_dt_3_cfg_0; - uint32_t tpg_dt_0_cfg_1; - uint32_t tpg_dt_1_cfg_1; - uint32_t tpg_dt_2_cfg_1; - uint32_t tpg_dt_3_cfg_1; - uint32_t tpg_dt_0_cfg_2; - uint32_t tpg_dt_1_cfg_2; - uint32_t tpg_dt_2_cfg_2; - uint32_t tpg_dt_3_cfg_2; - uint32_t tpg_color_bar_cfg; - uint32_t tpg_common_gen_cfg; - uint32_t tpg_vbi_cfg; - uint32_t tpg_test_bus_crtl; - uint32_t tpg_spare; - /* configurations */ - uint32_t major_version; - uint32_t minor_version; - uint32_t version_incr; - uint32_t tpg_en_shift_val; - uint32_t tpg_phy_sel_shift_val; - uint32_t tpg_num_active_lines_shift; - uint32_t tpg_fe_pkt_en_shift; - uint32_t tpg_fs_pkt_en_shift; - uint32_t tpg_line_interleaving_mode_shift; - uint32_t tpg_num_dts_shift_val; - uint32_t tpg_v_blank_cnt_shift; - uint32_t tpg_dt_encode_format_shift; - uint32_t tpg_payload_mode_color; - uint32_t tpg_split_en_shift; - uint32_t top_mux_reg_offset; -}; - /** * struct cam_top_tpg_hw_info- tpg hardware info * @@ -72,7 +33,7 @@ struct cam_top_tpg_reg_offset { * */ struct cam_top_tpg_hw_info { - const struct cam_top_tpg_reg_offset *tpg_reg; + void *tpg_reg; uint32_t hw_dts_version; uint32_t csid_max_clk; uint32_t phy_max_clk; @@ -86,15 +47,24 @@ struct cam_top_tpg_hw_info { * @data_type: data type(dt) value * @encode_format: encode format for this data type * @payload_mode payload data, such color bar, color box etc + * @bayer_pattern: Bayer patter information + * @rotate_period: period value for repeating color, 0 for no rotate + * @split_en: enables split mode + * @unicolor_en: enables unicolor value + * @unicolor_sel: select color used in unicolor mode * */ - struct cam_top_tpg_dt_cfg { uint32_t frame_width; uint32_t frame_height; uint32_t data_type; uint32_t encode_format; uint32_t payload_mode; + uint32_t bayer_pattern; + uint32_t rotate_period; + uint32_t split_en; + uint32_t unicolor_en; + uint32_t unicolor_sel; }; /** @@ -107,6 +77,7 @@ struct cam_top_tpg_dt_cfg { * @h_blank_count: vertical blanking count value * @vbi_cnt: vbi count * @num_active_dts: number of active dts need to configure + * @num_frames: number of output frames * @dt_cfg: dt configuration values * */ @@ -119,6 +90,7 @@ struct cam_top_tpg_cfg { uint32_t h_blank_count; uint32_t vbi_cnt; uint32_t num_active_dts; + uint32_t num_frames; struct cam_top_tpg_dt_cfg dt_cfg[4]; }; @@ -145,9 +117,9 @@ struct cam_top_tpg_hw { struct completion tpg_complete; }; -int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf, +int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf, uint32_t tpg_idx); -int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw); +int cam_top_tpg_deinit(struct cam_top_tpg_hw *top_tpg_hw); -#endif /* _CAM_TOP_TPG_HW_H_ */ +#endif /* _CAM_TOP_TPG_CORE_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c index ebb355a29d4b..fa4828c5bc3b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c @@ -21,10 +21,10 @@ static int cam_top_tpg_component_bind(struct device *dev, struct device *master_dev, void *data) { struct cam_hw_intf *tpg_hw_intf; - struct cam_hw_info *tpg_hw_info; - struct cam_top_tpg_hw *tpg_dev = NULL; + struct cam_hw_info *hw_info; + struct cam_top_tpg_hw *tpg_hw = NULL; const struct of_device_id *match_dev = NULL; - struct cam_top_tpg_hw_info *tpg_hw_data = NULL; + struct cam_top_tpg_hw_info *tpg_hw_info = NULL; uint32_t tpg_dev_idx; int rc = 0; struct platform_device *pdev = to_platform_device(dev); @@ -37,14 +37,14 @@ static int cam_top_tpg_component_bind(struct device *dev, goto err; } - tpg_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); - if (!tpg_hw_info) { + hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!hw_info) { rc = -ENOMEM; goto free_hw_intf; } - tpg_dev = kzalloc(sizeof(struct cam_top_tpg_hw), GFP_KERNEL); - if (!tpg_dev) { + tpg_hw = kzalloc(sizeof(struct cam_top_tpg_hw), GFP_KERNEL); + if (!tpg_hw) { rc = -ENOMEM; goto free_hw_info; } @@ -66,23 +66,23 @@ static int cam_top_tpg_component_bind(struct device *dev, tpg_hw_intf->hw_idx = tpg_dev_idx; tpg_hw_intf->hw_type = CAM_ISP_HW_TYPE_TPG; - tpg_hw_intf->hw_priv = tpg_hw_info; + tpg_hw_intf->hw_priv = hw_info; - tpg_hw_info->core_info = tpg_dev; - tpg_hw_info->soc_info.pdev = pdev; - tpg_hw_info->soc_info.dev = &pdev->dev; - tpg_hw_info->soc_info.dev_name = tpg_dev_name; - tpg_hw_info->soc_info.index = tpg_dev_idx; + hw_info->core_info = tpg_hw; + hw_info->soc_info.pdev = pdev; + hw_info->soc_info.dev = &pdev->dev; + hw_info->soc_info.dev_name = tpg_dev_name; + hw_info->soc_info.index = tpg_dev_idx; - tpg_hw_data = (struct cam_top_tpg_hw_info *)match_dev->data; + tpg_hw_info = (struct cam_top_tpg_hw_info *)match_dev->data; /* need to setup the pdev before call the tfe hw probe init */ - tpg_dev->tpg_info = tpg_hw_data; + tpg_hw->tpg_info = tpg_hw_info; - rc = cam_top_tpg_hw_probe_init(tpg_hw_intf, tpg_dev_idx); + rc = cam_top_tpg_probe_init(tpg_hw_intf, tpg_dev_idx); if (rc) goto free_dev; - platform_set_drvdata(pdev, tpg_dev); + platform_set_drvdata(pdev, tpg_hw); CAM_DBG(CAM_ISP, "TPG: %d component binded successfully", tpg_hw_intf->hw_idx); @@ -94,9 +94,9 @@ static int cam_top_tpg_component_bind(struct device *dev, return 0; free_dev: - kfree(tpg_dev); + kfree(tpg_hw); free_hw_info: - kfree(tpg_hw_info); + kfree(hw_info); free_hw_intf: kfree(tpg_hw_intf); err: @@ -108,19 +108,19 @@ static void cam_top_tpg_component_unbind(struct device *dev, { struct cam_top_tpg_hw *tpg_dev = NULL; struct cam_hw_intf *tpg_hw_intf; - struct cam_hw_info *tpg_hw_info; struct platform_device *pdev = to_platform_device(dev); + struct cam_hw_info *hw_info; tpg_dev = (struct cam_top_tpg_hw *)platform_get_drvdata(pdev); tpg_hw_intf = tpg_dev->hw_intf; - tpg_hw_info = tpg_dev->hw_info; + hw_info = tpg_dev->hw_info; CAM_DBG(CAM_ISP, "TPG:%d component unbound", tpg_dev->hw_intf->hw_idx); - cam_top_tpg_hw_deinit(tpg_dev); + cam_top_tpg_deinit(tpg_dev); /*release the tpg device memory */ kfree(tpg_dev); - kfree(tpg_hw_info); + kfree(hw_info); kfree(tpg_hw_intf); } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c deleted file mode 100644 index 8564a30339c2..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. - */ - - -#include -#include "cam_top_tpg_core.h" -#include "cam_top_tpg_v1.h" -#include "cam_top_tpg_dev.h" -#include "camera_main.h" - -#define CAM_TOP_TPG_DRV_NAME "tpg_v1" -#define CAM_TOP_TPG_VERSION_V1 0x10000000 - -static struct cam_top_tpg_hw_info cam_top_tpg_v1_hw_info = { - .tpg_reg = &cam_top_tpg_v1_reg_offset, - .hw_dts_version = CAM_TOP_TPG_VERSION_V1, - .csid_max_clk = 426400000, - .phy_max_clk = 384000000, -}; - -static const struct of_device_id cam_top_tpg_v1_dt_match[] = { - { - .compatible = "qcom,tpgv1", - .data = &cam_top_tpg_v1_hw_info, - }, - {} -}; - -MODULE_DEVICE_TABLE(of, cam_top_tpg_v1_dt_match); - -struct platform_driver cam_top_tpg_v1_driver = { - .probe = cam_top_tpg_probe, - .remove = cam_top_tpg_remove, - .driver = { - .name = CAM_TOP_TPG_DRV_NAME, - .of_match_table = cam_top_tpg_v1_dt_match, - .suppress_bind_attrs = true, - }, -}; - -int cam_top_tpg_v1_init_module(void) -{ - return platform_driver_register(&cam_top_tpg_v1_driver); -} - -void cam_top_tpg_v1_exit_module(void) -{ - platform_driver_unregister(&cam_top_tpg_v1_driver); -} - -MODULE_DESCRIPTION("CAM TOP TPG driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c new file mode 100644 index 000000000000..24c930f12556 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_top_tpg_core.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_top_tpg_ver1.h" + +static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = { + 0, + 3, + 1, + 2 +}; + +static int cam_top_tpg_ver1_get_format( + uint32_t in_format, + uint32_t *tpg_encode_format) +{ + int rc = 0; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + *tpg_encode_format = 0; + break; + case CAM_FORMAT_MIPI_RAW_8: + *tpg_encode_format = 1; + break; + case CAM_FORMAT_MIPI_RAW_10: + *tpg_encode_format = 2; + break; + case CAM_FORMAT_MIPI_RAW_12: + *tpg_encode_format = 3; + break; + case CAM_FORMAT_MIPI_RAW_14: + *tpg_encode_format = 4; + break; + case CAM_FORMAT_MIPI_RAW_16: + *tpg_encode_format = 4; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported input encode format %d", + in_format); + rc = -EINVAL; + } + return rc; +} + +static int cam_top_tpg_ver1_get_hw_caps( + void *hw_priv, + void *get_hw_cap_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw_caps *hw_caps; + struct cam_top_tpg_hw *tpg_hw; + const struct cam_top_tpg_ver1_reg_offset *tpg_reg; + struct cam_hw_info *tpg_hw_info; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + hw_caps = (struct cam_top_tpg_hw_caps *) get_hw_cap_args; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + + hw_caps->major_version = tpg_reg->major_version; + hw_caps->minor_version = tpg_reg->minor_version; + hw_caps->version_incr = tpg_reg->version_incr; + + CAM_DBG(CAM_ISP, + "TPG:%d major:%d minor:%d ver :%d", + tpg_hw->hw_intf->hw_idx, hw_caps->major_version, + hw_caps->minor_version, hw_caps->version_incr); + + return rc; +} + +static int cam_top_tpg_ver1_reserve( + void *hw_priv, + void *reserve_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_ver1_reserve_args *reserv; + struct cam_top_tpg_cfg *tpg_data; + uint32_t encode_format = 0; + uint32_t i; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_top_tpg_ver1_reserve_args))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + reserv = (struct cam_top_tpg_ver1_reserve_args *)reserve_args; + + if (reserv->num_inport <= 0 || + reserv->num_inport > CAM_TOP_TPG_MAX_SUPPORTED_DT) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG: %u invalid input num port:%d", + tpg_hw->hw_intf->hw_idx, reserv->num_inport); + return -EINVAL; + } + + mutex_lock(&tpg_hw->hw_info->hw_mutex); + if (tpg_hw->tpg_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return -EINVAL; + } + + if ((reserv->in_port[0]->vc > 0xF) || + (reserv->in_port[0]->lane_num <= 0 || + reserv->in_port[0]->lane_num > 4) || + (reserv->in_port[0]->pix_pattern > 4) || + (reserv->in_port[0]->lane_type >= 2)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d %d %d", + tpg_hw->hw_intf->hw_idx, reserv->in_port[0]->vc, + reserv->in_port[0]->lane_num, + reserv->in_port[0]->pix_pattern, + reserv->in_port[0]->lane_type); + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return -EINVAL; + } + rc = cam_top_tpg_ver1_get_format(reserv->in_port[0]->format, + &encode_format); + if (rc) + goto error; + + CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx); + + tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; + tpg_data->vc_num = reserv->in_port[0]->vc; + tpg_data->phy_sel = reserv->in_port[0]->lane_type; + tpg_data->num_active_lanes = reserv->in_port[0]->lane_num; + tpg_data->h_blank_count = reserv->in_port[0]->sensor_hbi; + tpg_data->v_blank_count = reserv->in_port[0]->sensor_vbi; + tpg_data->pix_pattern = reserv->in_port[0]->pix_pattern; + tpg_data->dt_cfg[0].data_type = reserv->in_port[0]->dt; + tpg_data->dt_cfg[0].frame_height = reserv->in_port[0]->height; + if (reserv->in_port[0]->usage_type) + tpg_data->dt_cfg[0].frame_width = + ((reserv->in_port[0]->right_end - + reserv->in_port[0]->left_start) + 1); + else + tpg_data->dt_cfg[0].frame_width = + reserv->in_port[0]->left_width; + tpg_data->dt_cfg[0].encode_format = encode_format; + tpg_data->num_active_dts = 1; + + CAM_DBG(CAM_ISP, + "TPG:%u vc_num:%d dt:%d phy:%d lines:%d pattern:%d format:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->vc_num, tpg_data->dt_cfg[0].data_type, + tpg_data->phy_sel, tpg_data->num_active_lanes, + tpg_data->pix_pattern, + tpg_data->dt_cfg[0].encode_format); + + CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d h blank:%d v blank:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->dt_cfg[0].frame_height, + tpg_data->dt_cfg[0].frame_width, + tpg_data->h_blank_count, + tpg_data->v_blank_count); + + if (reserv->num_inport == 1) + goto end; + + for (i = 1; i < reserv->num_inport; i++) { + if ((tpg_data->vc_num != reserv->in_port[i]->vc) || + (tpg_data->phy_sel != reserv->in_port[i]->lane_type) || + (tpg_data->num_active_lanes != + reserv->in_port[i]->lane_num) || + (tpg_data->pix_pattern != + reserv->in_port[i]->pix_pattern)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "TPG: %u invalid DT config for tpg", + tpg_hw->hw_intf->hw_idx); + rc = -EINVAL; + goto error; + } + rc = cam_top_tpg_ver1_get_format(reserv->in_port[0]->format, + &encode_format); + if (rc) + return rc; + + tpg_data->dt_cfg[i].data_type = reserv->in_port[i]->dt; + tpg_data->dt_cfg[i].frame_height = + reserv->in_port[i]->height; + tpg_data->dt_cfg[i].frame_width = + reserv->in_port[i]->left_width; + tpg_data->dt_cfg[i].encode_format = encode_format; + tpg_data->num_active_dts++; + + CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d dt:%d format:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->dt_cfg[i].frame_height, + tpg_data->dt_cfg[i].frame_width, + tpg_data->dt_cfg[i].data_type, + tpg_data->dt_cfg[i].encode_format); + + } +end: + reserv->node_res = &tpg_hw->tpg_res; + tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED; +error: + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + CAM_DBG(CAM_ISP, "exit rc %u", rc); + + return rc; +} + +static int cam_top_tpg_ver1_start( + void *hw_priv, + void *start_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + struct cam_top_tpg_ver1_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + uint32_t i, val; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *)start_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_lfsr_seed); + + for (i = 0; i < tpg_data->num_active_dts; i++) { + val = (((tpg_data->dt_cfg[i].frame_width & 0xFFFF) << 16) | + (tpg_data->dt_cfg[i].frame_height & 0x3FFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_0 + 0x10 * i); + cam_io_w_mb(tpg_data->dt_cfg[i].data_type, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_1 + 0x10 * i); + val = ((tpg_data->dt_cfg[i].encode_format & 0xF) << + tpg_reg->tpg_dt_encode_format_shift) | + tpg_reg->tpg_payload_mode_color; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_2 + 0x10 * i); + } + + val = (tpg_num_dt_map[tpg_data->num_active_dts-1] << + tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0); + + /* + * if hblank is notset configureHBlank count 500 and + * V blank count is 600 + */ + + if (tpg_data->h_blank_count) + cam_io_w_mb(tpg_data->h_blank_count, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); + else + cam_io_w_mb(0x2581F4, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); + + val = (1 << tpg_reg->tpg_split_en_shift); + cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_common_gen_cfg); + + /* if VBI is notset configureVBI to 0xAFF */ + if (tpg_data->v_blank_count) + cam_io_w_mb(tpg_data->v_blank_count, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); + else + cam_io_w_mb(0xAFFF, + soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); + + /* Set the TOP tpg mux sel*/ + cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx), + soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); + + val = ((tpg_data->num_active_lanes - 1) << + tpg_reg->tpg_num_active_lines_shift) | + (1 << tpg_reg->tpg_fe_pkt_en_shift) | + (1 << tpg_reg->tpg_fs_pkt_en_shift) | + (tpg_data->phy_sel << tpg_reg->tpg_phy_sel_shift_val) | + (1 << tpg_reg->tpg_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + tpg_reg->tpg_hw_version); + CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x started", + tpg_hw->hw_intf->hw_idx, val); + +end: + return rc; +} + +static int cam_top_tpg_ver1_stop( + void *hw_priv, + void *stop_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + const struct cam_top_tpg_ver1_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *) stop_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_state; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_DBG(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_ctrl); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); +end: + return rc; +} + +int cam_top_tpg_ver1_init( + struct cam_top_tpg_hw *tpg_hw) +{ + tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_ver1_get_hw_caps; + tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver1_reserve; + tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver1_start; + tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver1_stop; + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h new file mode 100644 index 000000000000..b0c5d68f04f1 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_VER1_H_ +#define _CAM_TOP_TPG_VER1_H_ + +#include "cam_top_tpg_core.h" + +struct cam_top_tpg_ver1_reg_offset { + uint32_t tpg_hw_version; + uint32_t tpg_hw_status; + uint32_t tpg_ctrl; + uint32_t tpg_vc_cfg0; + uint32_t tpg_vc_cfg1; + uint32_t tpg_lfsr_seed; + uint32_t tpg_dt_0_cfg_0; + uint32_t tpg_dt_1_cfg_0; + uint32_t tpg_dt_2_cfg_0; + uint32_t tpg_dt_3_cfg_0; + uint32_t tpg_dt_0_cfg_1; + uint32_t tpg_dt_1_cfg_1; + uint32_t tpg_dt_2_cfg_1; + uint32_t tpg_dt_3_cfg_1; + uint32_t tpg_dt_0_cfg_2; + uint32_t tpg_dt_1_cfg_2; + uint32_t tpg_dt_2_cfg_2; + uint32_t tpg_dt_3_cfg_2; + uint32_t tpg_color_bar_cfg; + uint32_t tpg_common_gen_cfg; + uint32_t tpg_vbi_cfg; + uint32_t tpg_test_bus_crtl; + uint32_t tpg_spare; + /* configurations */ + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; + uint32_t tpg_en_shift_val; + uint32_t tpg_phy_sel_shift_val; + uint32_t tpg_num_active_lines_shift; + uint32_t tpg_fe_pkt_en_shift; + uint32_t tpg_fs_pkt_en_shift; + uint32_t tpg_line_interleaving_mode_shift; + uint32_t tpg_num_dts_shift_val; + uint32_t tpg_v_blank_cnt_shift; + uint32_t tpg_dt_encode_format_shift; + uint32_t tpg_payload_mode_color; + uint32_t tpg_split_en_shift; + uint32_t top_mux_reg_offset; +}; + +int cam_top_tpg_ver1_init(struct cam_top_tpg_hw *tpg_hw); + +#endif /* _CAM_TOP_TPG_VER1_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c new file mode 100644 index 000000000000..555cebf79f8f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_top_tpg_core.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_top_tpg_ver2.h" + +#define CAM_TOP_TPG_VER2_MAX_SUPPORTED_DT 1 + +static int cam_top_tpg_ver2_get_hw_caps( + void *hw_priv, + void *get_hw_cap_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw_caps *hw_caps; + struct cam_top_tpg_hw *tpg_hw; + const struct cam_top_tpg_ver2_reg_offset *tpg_reg; + struct cam_hw_info *tpg_hw_info; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + hw_caps = (struct cam_top_tpg_hw_caps *) get_hw_cap_args; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + + hw_caps->major_version = tpg_reg->major_version; + hw_caps->minor_version = tpg_reg->minor_version; + hw_caps->version_incr = tpg_reg->version_incr; + + CAM_DBG(CAM_ISP, + "TPG:%d major:%d minor:%d ver :%d", + tpg_hw->hw_intf->hw_idx, hw_caps->major_version, + hw_caps->minor_version, hw_caps->version_incr); + + return rc; +} + +static int cam_top_tpg_ver2_reserve( + void *hw_priv, + void *reserve_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_ver2_reserve_args *reserv; + struct cam_top_tpg_cfg *tpg_data; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_top_tpg_ver2_reserve_args))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + reserv = (struct cam_top_tpg_ver2_reserve_args *)reserve_args; + + if (reserv->num_inport <= 0 || + reserv->num_inport > CAM_TOP_TPG_VER2_MAX_SUPPORTED_DT) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG: %u invalid input num port:%d", + tpg_hw->hw_intf->hw_idx, reserv->num_inport); + return -EINVAL; + } + + mutex_lock(&tpg_hw->hw_info->hw_mutex); + if (tpg_hw->tpg_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, "TPG:%d resource not available state:%d", + tpg_hw->hw_intf->hw_idx, tpg_hw->tpg_res.res_state); + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + return -EINVAL; + } + + tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; + tpg_data->h_blank_count = reserv->in_port->hbi_cnt; + tpg_data->v_blank_count = 600; + tpg_data->dt_cfg[0].data_type = reserv->in_port->dt[0]; + tpg_data->dt_cfg[0].frame_height = reserv->in_port->height; + if (reserv->in_port->usage_type) + tpg_data->dt_cfg[0].frame_width = + ((reserv->in_port->right_stop - + reserv->in_port->left_start) + 1); + else + tpg_data->dt_cfg[0].frame_width = + reserv->in_port->left_width; + tpg_data->num_active_dts = 1; + + CAM_DBG(CAM_ISP, "TPG:%u dt:0x%x h:%d w:%d hbi:%d vbi:%d reserved", + tpg_hw->hw_intf->hw_idx, + tpg_data->dt_cfg[0].data_type, + tpg_data->dt_cfg[0].frame_height, + tpg_data->dt_cfg[0].frame_width, + tpg_data->h_blank_count, + tpg_data->v_blank_count); + + reserv->node_res = &tpg_hw->tpg_res; + tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + + return rc; +} + +static int cam_top_tpg_ver2_start( + void *hw_priv, + void *start_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + struct cam_top_tpg_ver2_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + uint32_t val; + uint32_t mux_sel_shift = 0; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *)start_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + if (tpg_hw->hw_intf->hw_idx == CAM_TOP_TPG_ID_0) + mux_sel_shift = tpg_reg->tpg_mux_sel_tpg_0_shift; + else if (tpg_hw->hw_intf->hw_idx == CAM_TOP_TPG_ID_1) + mux_sel_shift = tpg_reg->tpg_mux_sel_tpg_1_shift; + + cam_io_w_mb((tpg_reg->tpg_mux_sel_en << mux_sel_shift), + soc_info->reg_map[1].mem_base + tpg_reg->top_mux_sel); + + val = (((tpg_data->dt_cfg[0].frame_width & 0x3FFF) << 16) | + (tpg_data->dt_cfg[0].frame_height & 0x3FFF)); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_0); + + val = (tpg_data->h_blank_count & 0x7FF) << 20; + val |= (tpg_data->v_blank_count & 0x3FFFF); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_1); + + val = tpg_data->dt_cfg[0].data_type << 11; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_2); + + /* program number of frames */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_3); + + cam_io_w_mb(tpg_reg->tpg_module_en, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_module_cfg); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + CAM_DBG(CAM_ISP, "TPG:%d started", tpg_hw->hw_intf->hw_idx); + +end: + return rc; +} + +static int cam_top_tpg_ver2_stop( + void *hw_priv, + void *stop_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + const struct cam_top_tpg_ver2_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *) stop_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_state; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_DBG(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_module_cfg); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); +end: + return rc; +} + +int cam_top_tpg_ver2_init( + struct cam_top_tpg_hw *tpg_hw) +{ + tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_ver2_get_hw_caps; + tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver2_reserve; + tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver2_start; + tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver2_stop; + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.h new file mode 100644 index 000000000000..698ebf9e3fde --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_VER2_H_ +#define _CAM_TOP_TPG_VER2_H_ + +#include "cam_top_tpg_core.h" + +struct cam_top_tpg_ver2_reg_offset { + uint32_t tpg_hw_version; + uint32_t tpg_hw_status; + uint32_t tpg_module_cfg; + uint32_t tpg_cfg_0; + uint32_t tpg_cfg_1; + uint32_t tpg_cfg_2; + uint32_t tpg_cfg_3; + uint32_t tpg_spare; + uint32_t top_mux_sel; + /* configurations */ + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; + uint32_t tpg_module_en; + uint32_t tpg_mux_sel_en; + uint32_t tpg_mux_sel_tpg_0_shift; + uint32_t tpg_mux_sel_tpg_1_shift; + uint32_t tpg_en_shift_val; + uint32_t tpg_phy_sel_shift_val; + uint32_t tpg_num_active_lines_shift; + uint32_t tpg_fe_pkt_en_shift; + uint32_t tpg_fs_pkt_en_shift; + uint32_t tpg_line_interleaving_mode_shift; + uint32_t tpg_num_dts_shift_val; + uint32_t tpg_v_blank_cnt_shift; + uint32_t tpg_dt_encode_format_shift; + uint32_t tpg_payload_mode_color; + uint32_t tpg_split_en_shift; +}; + +int cam_top_tpg_ver2_init(struct cam_top_tpg_hw *tpg_hw); + +#endif /* _CAM_TOP_TPG_VER2_H_ */ diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 1dfe51a7ada7..35bd853f4412 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -50,7 +50,7 @@ #include "ope_dev_intf.h" -#include "cam_top_tpg_v1.h" +#include "cam_top_tpg.h" #include "cam_tfe_dev.h" #include "cam_tfe_csid530.h" #include "camera_main.h" @@ -77,6 +77,7 @@ static const struct camera_submodule_component camera_base[] = { static const struct camera_submodule_component camera_isp[] = { #ifdef CONFIG_SPECTRA_ISP + {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, {&cam_ife_csid17x_init_module, &cam_ife_csid17x_exit_module}, {&cam_ife_csid_lite_init_module, &cam_ife_csid_lite_exit_module}, {&cam_vfe_init_module, &cam_vfe_exit_module}, @@ -86,7 +87,7 @@ static const struct camera_submodule_component camera_isp[] = { static const struct camera_submodule_component camera_tfe[] = { #if IS_ENABLED(CONFIG_SPECTRA_TFE) - {&cam_top_tpg_v1_init_module, &cam_top_tpg_v1_exit_module}, + {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, {&cam_tfe_init_module, &cam_tfe_exit_module}, {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, #endif @@ -218,13 +219,14 @@ static struct platform_driver *const cam_component_drivers[] = { &cam_cdm_intf_driver, &cam_hw_cdm_driver, #ifdef CONFIG_SPECTRA_ISP + &cam_top_tpg_driver, &cam_ife_csid17x_driver, &cam_ife_csid_lite_driver, &cam_vfe_driver, &isp_driver, #endif #ifdef CONFIG_SPECTRA_TFE - &cam_top_tpg_v1_driver, + &cam_top_tpg_driver, &cam_tfe_driver, &cam_tfe_csid530_driver, #endif diff --git a/drivers/camera_main.h b/drivers/camera_main.h index 8787c8786c6d..3de446d08b7c 100644 --- a/drivers/camera_main.h +++ b/drivers/camera_main.h @@ -15,13 +15,14 @@ extern struct platform_driver cam_cpas_driver; extern struct platform_driver cam_cdm_intf_driver; extern struct platform_driver cam_hw_cdm_driver; #ifdef CONFIG_SPECTRA_ISP +extern struct platform_driver cam_top_tpg_driver; extern struct platform_driver cam_ife_csid17x_driver; extern struct platform_driver cam_ife_csid_lite_driver; extern struct platform_driver cam_vfe_driver; extern struct platform_driver isp_driver; #endif #ifdef CONFIG_SPECTRA_TFE -extern struct platform_driver cam_top_tpg_v1_driver; +extern struct platform_driver cam_top_tpg_driver; extern struct platform_driver cam_tfe_driver; extern struct platform_driver cam_tfe_csid530_driver; #endif diff --git a/include/uapi/camera/media/cam_isp_ife.h b/include/uapi/camera/media/cam_isp_ife.h index 34c1b3bd2bfe..f18a474bc7b9 100644 --- a/include/uapi/camera/media/cam_isp_ife.h +++ b/include/uapi/camera/media/cam_isp_ife.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_ISP_IFE_H__ @@ -49,6 +49,8 @@ #define CAM_ISP_IFE_IN_RES_PHY_4 (CAM_ISP_IFE_IN_RES_BASE + 5) #define CAM_ISP_IFE_IN_RES_PHY_5 (CAM_ISP_IFE_IN_RES_BASE + 6) #define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 7) -#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 8) +#define CAM_ISP_IFE_IN_RES_CPHY_TPG_0 (CAM_ISP_IFE_IN_RES_BASE + 8) +#define CAM_ISP_IFE_IN_RES_CPHY_TPG_1 (CAM_ISP_IFE_IN_RES_BASE + 9) +#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 10) #endif /* __UAPI_CAM_ISP_IFE_H__ */ From 8e79606ada4db8702cda603dc15561cb2e895e91 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 4 Feb 2020 16:18:46 -0800 Subject: [PATCH 273/790] msm: camera: isp: Add support for offline IFE This change adds new IRQ state machine and updates the acquire logic to enable offline IFE. This change also adds the fixes necessary to enable bus read for various buffer formats and append go command at the end of each packet for offline context. CRs-Fixed: 2513939 Change-Id: Ie068670ed11aa6713e8f0cb817e4b5d4c209e696 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 206 +++++- drivers/cam_isp/cam_isp_context.h | 7 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 700 +++++++++++------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 6 +- .../hw_utils/cam_isp_packet_parser.c | 99 ++- .../hw_utils/include/cam_isp_packet_parser.h | 19 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 1 + .../isp_hw/include/cam_ife_csid_hw_intf.h | 1 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 3 +- .../isp_hw/include/cam_vfe_hw_intf.h | 31 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c | 652 +++++++++------- .../vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h | 3 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 58 +- 15 files changed, 1210 insertions(+), 578 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 02f51ff13cb6..0e9918f80f91 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1028,6 +1028,96 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( return rc; } +static int __cam_isp_ctx_apply_req_offline( + struct cam_context *ctx, uint32_t next_state, + struct cam_isp_context *ctx_isp) +{ + int rc = 0; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_hw_config_args cfg; + + if (list_empty(&ctx->pending_req_list)) { + CAM_DBG(CAM_ISP, "No pending requests to apply"); + rc = -EFAULT; + goto end; + } + + if (ctx->state != CAM_CTX_ACTIVATED) + goto end; + + if (ctx_isp->active_req_cnt >= 2) + goto end; + + req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, + list); + + 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; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; + cfg.request_id = req->request_id; + cfg.hw_update_entries = req_isp->cfg; + cfg.num_hw_update_entries = req_isp->num_cfg; + cfg.priv = &req_isp->hw_update_data; + cfg.init_packet = 0; + + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); + } else { + atomic_set(&ctx_isp->rxd_epoch, 0); + ctx_isp->substate_activated = next_state; + ctx_isp->last_applied_req_id = req->request_id; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->wait_req_list); + CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld", + next_state, ctx_isp->last_applied_req_id); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, + req->request_id); + } +end: + return rc; +} + +static int __cam_isp_ctx_offline_epoch_in_activated_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_context *ctx = ctx_isp->base; + struct cam_ctx_request *req, *req_temp; + uint64_t request_id = 0; + + atomic_set(&ctx_isp->rxd_epoch, 1); + + CAM_DBG(CAM_ISP, "SOF frame %lld ctx %u", ctx_isp->frame_id, + ctx->ctx_id); + + list_for_each_entry_safe(req, req_temp, &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_apply_req_offline(ctx, CAM_ISP_CTX_ACTIVATED_APPLIED, + ctx_isp); + + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, + request_id); + + return 0; +} + static int __cam_isp_ctx_reg_upd_in_epoch_bubble_state( struct cam_isp_context *ctx_isp, void *evt_data) { @@ -1811,6 +1901,9 @@ end: } while (req->request_id < ctx_isp->last_applied_req_id); + if (ctx_isp->offline_context) + goto exit; + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { notify.link_hdl = ctx->link_hdl; notify.dev_hdl = ctx->dev_hdl; @@ -1861,6 +1954,7 @@ end: CAM_DBG(CAM_ISP, "Exit"); +exit: return rc; } @@ -2244,6 +2338,63 @@ static struct cam_isp_ctx_irq_ops }, }; +static struct cam_isp_ctx_irq_ops + cam_isp_ctx_offline_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + NULL, + NULL, + NULL, + NULL, + NULL, + }, + }, + /* APPLIED */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + __cam_isp_ctx_sof_in_activated_state, + __cam_isp_ctx_reg_upd_in_applied_state, + NULL, + NULL, + __cam_isp_ctx_buf_done_in_applied, + }, + }, + /* EPOCH */ + { + .irq_ops = { + __cam_isp_ctx_handle_error, + NULL, + NULL, + __cam_isp_ctx_offline_epoch_in_activated_state, + NULL, + __cam_isp_ctx_buf_done_in_epoch, + }, + }, + /* BUBBLE */ + { + }, + /* 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, enum cam_isp_ctx_activated_substate next_state) @@ -2796,6 +2947,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( end: ctx_isp->bubble_frame_cnt = 0; atomic_set(&ctx_isp->process_bubble, 0); + atomic_set(&ctx_isp->rxd_epoch, 0); return rc; } @@ -3685,8 +3837,11 @@ static int __cam_isp_ctx_config_dev_in_top_state( ctx->state); } } else { - if (ctx->state != CAM_CTX_FLUSHED && ctx->state >= CAM_CTX_READY - && ctx->ctx_crm_intf->add_req) { + if (ctx_isp->offline_context) { + __cam_isp_ctx_enqueue_request_in_order(ctx, req); + } else if ((ctx->state != CAM_CTX_FLUSHED) && + (ctx->state >= CAM_CTX_READY) && + ctx->ctx_crm_intf->add_req) { add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; @@ -3713,6 +3868,13 @@ static int __cam_isp_ctx_config_dev_in_top_state( "Preprocessing Config req_id %lld successful on ctx %u", req->request_id, ctx->ctx_id); + if (ctx_isp->offline_context && atomic_read(&ctx_isp->rxd_epoch)) { + spin_lock_bh(&ctx->lock); + __cam_isp_ctx_apply_req_offline(ctx, + CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp); + spin_unlock_bh(&ctx->lock); + } + return rc; put_ref: @@ -3827,11 +3989,15 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, 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"); + 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 if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) { + CAM_DBG(CAM_ISP, "offline Session has PIX and RD resources"); + ctx_isp->substate_machine_irq = + cam_isp_ctx_offline_state_machine_irq; } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = @@ -3985,11 +4151,16 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, 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"); + 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 if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) { + CAM_DBG(CAM_ISP, "Offline session has PIX and RD resources"); + ctx_isp->substate_machine_irq = + cam_isp_ctx_offline_state_machine_irq; + ctx_isp->substate_machine = NULL; } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = @@ -4136,11 +4307,17 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, 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"); + 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 if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) { + CAM_DBG(CAM_ISP, "Offline Session has PIX and RD resources"); + ctx_isp->substate_machine_irq = + cam_isp_ctx_offline_state_machine_irq; + ctx_isp->substate_machine = NULL; + ctx_isp->offline_context = true; } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = @@ -4207,7 +4384,7 @@ static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx, rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd); - if (!rc && (ctx->link_hdl >= 0)) { + if (!rc && ((ctx->link_hdl >= 0) || ctx_isp->offline_context)) { ctx->state = CAM_CTX_READY; trace_cam_context_state("ISP", ctx); } @@ -4368,6 +4545,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.start_only = false; atomic_set(&ctx_isp->process_bubble, 0); + atomic_set(&ctx_isp->rxd_epoch, 0); ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; @@ -4390,11 +4568,24 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, */ list_del_init(&req->list); - if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) { + if (ctx_isp->offline_context && !req_isp->num_fence_map_out) { + list_add_tail(&req->list, &ctx->free_req_list); + atomic_set(&ctx_isp->rxd_epoch, 1); + CAM_DBG(CAM_REQ, + "Move pending req: %lld to free list(cnt: %d) offline ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); + } else if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) { list_add_tail(&req->list, &ctx->wait_req_list); + CAM_DBG(CAM_REQ, + "Move pending req: %lld to wait list(cnt: %d) ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } else { list_add_tail(&req->list, &ctx->active_req_list); ctx_isp->active_req_cnt++; + CAM_DBG(CAM_REQ, + "Move pending req: %lld to active list(cnt: %d) ctx %u offline %d", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id, + ctx_isp->offline_context); } /* @@ -4539,6 +4730,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->last_applied_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0; atomic_set(&ctx_isp->process_bubble, 0); + atomic_set(&ctx_isp->rxd_epoch, 0); atomic64_set(&ctx_isp->state_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 94c61af5e0e7..beec13e3ff13 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -247,13 +247,16 @@ struct cam_isp_context_event_record { * @event_record: Event record array * @rdi_only_context: Get context type information. * true, if context is rdi only context + * @offline_context: Indicate whether context is for offline IFE * @hw_acquired: Indicate whether HW resources are acquired * @init_received: Indicate whether init config packet is received * @split_acquire: Indicate whether a separate acquire is expected * @custom_enabled: Custom HW enabled for this ctx * @use_frame_header_ts: Use frame header for qtimer ts * @init_timestamp: Timestamp at which this context is initialized - * @isp_device_type ISP device type + * @isp_device_type: ISP device type + * @rxd_epoch: Indicate whether epoch has been received. Used to + * decide whether to apply request in offline ctx * */ struct cam_isp_context { @@ -286,6 +289,7 @@ struct cam_isp_context { struct cam_isp_context_event_record event_record[ CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES]; bool rdi_only_context; + bool offline_context; bool hw_acquired; bool init_received; bool split_acquire; @@ -293,6 +297,7 @@ struct cam_isp_context { bool use_frame_header_ts; unsigned int init_timestamp; uint32_t isp_device_type; + atomic_t rxd_epoch; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c6e5e9d75223..d12a375daf01 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -979,90 +979,6 @@ 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_generic_info *in_port) -{ - int rc = -EINVAL; - struct cam_vfe_acquire_args vfe_acquire; - struct cam_isp_hw_mgr_res *ife_in_rd_res; - struct cam_hw_intf *hw_intf; - struct cam_isp_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.priv = ife_ctx; - vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; - vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_isp; - 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_isp) { - /*TBD */ - vfe_acquire.vfe_out.is_master = 1; - vfe_acquire.vfe_out.dual_slave_core = - ife_ctx->slave_hw_idx; - } 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 = - ife_ctx->master_hw_idx; - } - 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_isp = in_port->usage_type; - ife_in_rd_res->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_isp_hw_mgr_res *ife_src_res, @@ -1297,125 +1213,6 @@ 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_generic_info *in_port) -{ - int rc = -1; - struct cam_isp_hw_mgr_res *csid_res; - struct cam_isp_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 = vfe_acquire.rsrc_type; - ife_src_res->res_id = vfe_acquire.vfe_in.res_id; - ife_src_res->is_dual_isp = csid_res->is_dual_isp; - - 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_isp) - 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_isp) - 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->num_children++; - } - -err: - /* release resource at the entry function */ - CAM_DBG(CAM_ISP, "Exit rc %d", rc); - return rc; -} - static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) { uint32_t hw_version, rc = 0; @@ -1547,6 +1344,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( 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.is_fe_enabled = ife_ctx->is_fe_enabled; + vfe_acquire.vfe_in.is_offline = ife_ctx->is_offline; vfe_acquire.priv = ife_ctx; vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; @@ -1800,7 +1599,7 @@ static int cam_ife_mgr_acquire_cid_res( /* Acquire Left if not already acquired */ /* For dual IFE cases, start acquiring the lower idx first */ - if (ife_ctx->is_fe_enable || in_port->usage_type) + if (ife_ctx->is_fe_enabled || in_port->usage_type) rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr, &csid_acquire, true); else @@ -2166,7 +1965,7 @@ static int cam_ife_hw_mgr_acquire_res_root( ife_ctx->res_list_ife_in.res_id = in_port->res_type; ife_ctx->res_list_ife_in.is_dual_isp = in_port->usage_type; } else if ((ife_ctx->res_list_ife_in.res_id != - in_port->res_type) && (!ife_ctx->is_fe_enable)) { + in_port->res_type) && (!ife_ctx->is_fe_enabled)) { CAM_ERR(CAM_ISP, "No Free resource for this context"); goto err; } else { @@ -2211,14 +2010,14 @@ static int cam_ife_mgr_check_and_update_fe_v0( 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; + ife_ctx->is_fe_enabled = 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); + CAM_DBG(CAM_ISP, "is_fe_enabled %d", ife_ctx->is_fe_enabled); return 0; } @@ -2256,14 +2055,17 @@ static int cam_ife_mgr_check_and_update_fe_v2( 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; + ife_ctx->is_fe_enabled = true; + if (in_port->offline_mode) + ife_ctx->is_offline = true; break; } in_port = (struct cam_isp_in_port_info_v2 *) ((uint8_t *)in_port + in_port_length); } - CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable); + CAM_DBG(CAM_ISP, "is_fe_enabled %d is_offline %d", + ife_ctx->is_fe_enabled, ife_ctx->is_offline); return 0; } @@ -2316,22 +2118,21 @@ static int cam_ife_hw_mgr_preprocess_port( ife_hw_mgr = ife_ctx->hw_mgr; - if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) { + 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 if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR) - lcr_num++; - else { - CAM_DBG(CAM_ISP, "out_res_type %d", - out_port->res_type); - ipp_num++; - } + + 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 if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR) + lcr_num++; + else { + CAM_DBG(CAM_ISP, "out_res_type %d", + out_port->res_type); + ipp_num++; } } @@ -2347,6 +2148,290 @@ static int cam_ife_hw_mgr_preprocess_port( return 0; } +static int cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port) +{ + int rc = -EINVAL, j; + int i = CAM_ISP_HW_SPLIT_LEFT; + struct cam_vfe_acquire_args vfe_acquire; + struct cam_isp_hw_mgr_res *ife_bus_rd_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_hw_mgr *ife_hw_mgr; + + ife_hw_mgr = ife_ctx->hw_mgr; + + rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &ife_bus_rd_res); + if (rc) { + CAM_ERR(CAM_ISP, "No more free hw mgr resource"); + goto end; + } + + vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD; + vfe_acquire.tasklet = ife_ctx->common.tasklet_info; + vfe_acquire.priv = ife_ctx; + vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; + + vfe_acquire.vfe_bus_rd.cdm_ops = ife_ctx->cdm_ops; + vfe_acquire.vfe_bus_rd.is_dual = (uint32_t)ife_ctx->is_dual; + vfe_acquire.vfe_bus_rd.is_offline = ife_ctx->is_offline; + vfe_acquire.vfe_bus_rd.res_id = CAM_ISP_HW_VFE_IN_RD; + vfe_acquire.vfe_bus_rd.unpacker_fmt = in_port->fe_unpacker_fmt; + + for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) { + if (!ife_hw_mgr->ife_devices[j]) + continue; + + hw_intf = ife_hw_mgr->ife_devices[j]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); + + if (!rc) { + ife_bus_rd_res->hw_res[i] = + vfe_acquire.vfe_bus_rd.rsrc_node; + + CAM_DBG(CAM_ISP, "Acquired VFE:%d BUS RD for LEFT", j); + break; + } + } + + if (j == CAM_IFE_HW_NUM_MAX || !vfe_acquire.vfe_bus_rd.rsrc_node) { + CAM_ERR(CAM_ISP, "Failed to acquire BUS RD for LEFT", i); + goto put_res; + } + + ife_bus_rd_res->res_type = vfe_acquire.rsrc_type; + ife_bus_rd_res->res_id = vfe_acquire.vfe_in.res_id; + ife_bus_rd_res->is_dual_isp = (uint32_t)ife_ctx->is_dual; + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd, &ife_bus_rd_res); + + if (ife_ctx->is_dual) { + for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) { + if (!ife_hw_mgr->ife_devices[j]) + continue; + + if (j == ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx) + continue; + + hw_intf = ife_hw_mgr->ife_devices[j]; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &vfe_acquire, + sizeof(struct cam_vfe_acquire_args)); + + if (!rc) { + ife_bus_rd_res->hw_res[++i] = + vfe_acquire.vfe_bus_rd.rsrc_node; + + CAM_DBG(CAM_ISP, + "Acquired VFE:%d BUS RD for RIGHT", j); + break; + } + } + + if (j == CAM_IFE_HW_NUM_MAX || + !vfe_acquire.vfe_bus_rd.rsrc_node) { + CAM_ERR(CAM_ISP, "Failed to acquire BUS RD for RIGHT"); + goto end; + } + } + + return 0; + +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &ife_bus_rd_res); + +end: + return rc; +} + +static int cam_ife_hw_mgr_acquire_offline_res_ife_camif( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + bool acquire_lcr, + uint32_t *acquired_hw_id, + uint32_t *acquired_hw_path) +{ + int rc = -1; + int i = CAM_ISP_HW_SPLIT_LEFT; + struct cam_isp_hw_mgr_res *ife_src_res; + struct cam_isp_hw_mgr_res *ife_bus_rd_res; + struct cam_vfe_acquire_args vfe_acquire; + struct cam_hw_intf *hw_intf; + struct cam_ife_hw_mgr *ife_hw_mgr; + + ife_hw_mgr = ife_ctx->hw_mgr; + + ife_bus_rd_res = list_first_entry(&ife_ctx->res_list_ife_in_rd, + struct cam_isp_hw_mgr_res, list); + + if (!ife_bus_rd_res) { + CAM_ERR(CAM_ISP, "BUS RD resource has not been acquired"); + rc = -EINVAL; + goto end; + } + + rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &ife_src_res); + if (rc) { + CAM_ERR(CAM_ISP, "No free resource"); + goto end; + } + + vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN; + vfe_acquire.tasklet = ife_ctx->common.tasklet_info; + vfe_acquire.priv = ife_ctx; + vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; + + vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops; + vfe_acquire.vfe_in.in_port = in_port; + vfe_acquire.vfe_in.is_fe_enabled = ife_ctx->is_fe_enabled; + vfe_acquire.vfe_in.is_offline = ife_ctx->is_offline; + + if (!acquire_lcr) + vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_CAMIF; + else + vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_LCR; + + if (ife_ctx->is_dual) + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER; + else + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; + + hw_intf = ife_hw_mgr->ife_devices[ + ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx]; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, + sizeof(struct cam_vfe_acquire_args)); + + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire CAMIF for LEFT"); + goto put_res; + } + + ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node; + + *acquired_hw_id |= cam_convert_hw_idx_to_ife_hw_num( + hw_intf->hw_idx); + + acquired_hw_path[i] |= cam_convert_res_id_to_hw_path( + ife_src_res->hw_res[i]->res_id); + + CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF for LEFT", + ife_src_res->hw_res[i]->hw_intf->hw_idx); + + ife_src_res->res_type = vfe_acquire.rsrc_type; + ife_src_res->res_id = vfe_acquire.vfe_in.res_id; + ife_src_res->is_dual_isp = (uint32_t)ife_ctx->is_dual; + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src, &ife_src_res); + + if (ife_ctx->is_dual) { + vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE; + + hw_intf = ife_hw_mgr->ife_devices[ + ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx]; + + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, + sizeof(struct cam_vfe_acquire_args)); + + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire CAMIF for RIGHT"); + goto end; + } + + ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node; + + *acquired_hw_id |= cam_convert_hw_idx_to_ife_hw_num( + hw_intf->hw_idx); + + acquired_hw_path[i] |= cam_convert_res_id_to_hw_path( + ife_src_res->hw_res[i]->res_id); + + CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF for RIGHT", + ife_src_res->hw_res[i]->hw_intf->hw_idx); + } + + ife_bus_rd_res->num_children++; + + return rc; + +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &ife_src_res); + +end: + return rc; +} + +static int cam_ife_mgr_acquire_hw_for_fe_ctx( + struct cam_ife_hw_mgr_ctx *ife_ctx, + struct cam_isp_in_port_generic_info *in_port, + uint32_t *num_pix_port, + uint32_t *acquired_hw_id, + uint32_t *acquired_hw_path) +{ + int rc = -1; + int ipp_count = 0; + int rdi_count = 0; + int ppp_count = 0; + int ife_rd_count = 0; + int lcr_count = 0; + + ife_ctx->is_dual = (bool)in_port->usage_type; + + cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, + &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); + + if ((!ipp_count && !lcr_count) || !ife_rd_count) { + CAM_ERR(CAM_ISP, + "Invalid %d BUS RD %d PIX %d LCR ports for FE ctx"); + return -EINVAL; + } + + if (rdi_count || ppp_count) { + CAM_ERR(CAM_ISP, + "%d RDI %d PPP ports invalid for FE ctx", + rdi_count, ppp_count); + return -EINVAL; + } + + rc = cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(ife_ctx, in_port); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed"); + goto err; + } + + if (ipp_count) + rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx, + in_port, false, acquired_hw_id, acquired_hw_path); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE IPP SRC resource Failed"); + goto err; + } + + if (lcr_count) + rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx, + in_port, true, acquired_hw_id, acquired_hw_path); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE LCR SRC resource Failed"); + goto err; + } + + 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 + lcr_count; + + return 0; + +err: + return rc; +} + + static int cam_ife_mgr_acquire_hw_for_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, @@ -2373,10 +2458,14 @@ static int cam_ife_mgr_acquire_hw_for_ctx( cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); - if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count - && !lcr_count) { + if (ife_rd_count) { + CAM_ERR(CAM_ISP, "Invalid BUS RD port for non-FE ctx"); + return -EINVAL; + } + + if (!ipp_count && !rdi_count && !ppp_count && !lcr_count) { CAM_ERR(CAM_ISP, - "No PIX or RDI or PPP or IFE RD or LCR resource"); + "No PIX or RDI or PPP or LCR resource"); return -EINVAL; } @@ -2421,15 +2510,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( } /* get ife src resource */ - 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); - - if (rc) { - CAM_ERR(CAM_ISP, "Acquire IFE RD SRC resource Failed"); - goto err; - } - } else if (ipp_count || ppp_count || rdi_count) { + if (ipp_count || ppp_count || rdi_count) { rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port, false, acquired_hw_id, acquired_hw_path); @@ -2633,10 +2714,12 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2( if (port_info->num_valid_vc_dt == 0 || port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) { - CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d", - in->num_valid_vc_dt); - rc = -EINVAL; - goto release_mem; + if (in->res_type != CAM_ISP_IFE_IN_RES_RD) { + CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d", + in->num_valid_vc_dt); + rc = -EINVAL; + goto release_mem; + } } for (i = 0; i < port_info->num_valid_vc_dt; i++) { @@ -2644,26 +2727,27 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2( port_info->dt[i] = in->dt[i]; } - port_info->format = in->format; - port_info->test_pattern = in->test_pattern; - port_info->usage_type = in->usage_type; - port_info->left_start = in->left_start; - port_info->left_stop = in->left_stop; - port_info->left_width = in->left_width; - port_info->right_start = in->right_start; - port_info->right_stop = in->right_stop; - port_info->right_width = in->right_width; - port_info->line_start = in->line_start; - port_info->line_stop = in->line_stop; - port_info->height = in->height; - port_info->pixel_clk = in->pixel_clk; - port_info->batch_size = in->batch_size; - port_info->dsp_mode = in->dsp_mode; - port_info->hbi_cnt = in->hbi_cnt; - port_info->cust_node = in->cust_node; - port_info->horizontal_bin = in->horizontal_bin; - port_info->qcfa_bin = in->qcfa_bin; - port_info->num_out_res = in->num_out_res; + port_info->format = in->format; + port_info->test_pattern = in->test_pattern; + port_info->usage_type = in->usage_type; + port_info->left_start = in->left_start; + port_info->left_stop = in->left_stop; + port_info->left_width = in->left_width; + port_info->right_start = in->right_start; + port_info->right_stop = in->right_stop; + port_info->right_width = in->right_width; + port_info->line_start = in->line_start; + port_info->line_stop = in->line_stop; + port_info->height = in->height; + port_info->pixel_clk = in->pixel_clk; + port_info->batch_size = in->batch_size; + port_info->dsp_mode = in->dsp_mode; + port_info->fe_unpacker_fmt = in->format; + port_info->hbi_cnt = in->hbi_cnt; + port_info->cust_node = in->cust_node; + port_info->horizontal_bin = in->horizontal_bin; + port_info->qcfa_bin = in->qcfa_bin; + port_info->num_out_res = in->num_out_res; port_info->data = kcalloc(in->num_out_res, sizeof(struct cam_isp_out_port_generic_info), @@ -2822,10 +2906,17 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto free_mem; } - rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, - &num_pix_port_per_in, &num_rdi_port_per_in, - &acquire_args->acquired_hw_id[i], - acquire_args->acquired_hw_path[i]); + if (ife_ctx->is_fe_enabled) + rc = cam_ife_mgr_acquire_hw_for_fe_ctx( + ife_ctx, in_port, + &num_pix_port_per_in, + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + else + rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, + &num_pix_port_per_in, &num_rdi_port_per_in, + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); total_pix_port += num_pix_port_per_in; total_rdi_port += num_rdi_port_per_in; @@ -2915,6 +3006,7 @@ void cam_ife_mgr_acquire_get_unified_dev_str(struct cam_isp_in_port_info *in, gen_port_info->batch_size = in->batch_size; gen_port_info->dsp_mode = in->dsp_mode; gen_port_info->hbi_cnt = in->hbi_cnt; + gen_port_info->fe_unpacker_fmt = in->format; gen_port_info->cust_node = 0; gen_port_info->num_out_res = in->num_out_res; @@ -3788,11 +3880,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) 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 */ @@ -3800,6 +3887,11 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, 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); + } + cam_tasklet_stop(ctx->common.tasklet_info); cam_ife_mgr_pause_hw(ctx); @@ -4090,18 +4182,6 @@ 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; - } - } - if (primary_rdi_out_res < CAM_ISP_IFE_OUT_RES_MAX) primary_rdi_src_res = cam_convert_rdi_out_res_id_to_src(primary_rdi_out_res); @@ -4114,15 +4194,25 @@ start_only: hw_mgr_res->hw_res[0]->rdi_only_ctx = ctx->is_rdi_only_context; } - rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); if (rc) { - CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)", + CAM_ERR(CAM_ISP, "Can not start IFE Mux (%d)", hw_mgr_res->res_id); goto err; } } + CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d", ctx->ctx_index); + /* Start IFE Bus RD 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 CSID HW ... in ctx id:%d", ctx->ctx_index); /* Start the IFE CSID HW devices */ @@ -5838,6 +5928,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } + + /* add go_cmd for offline context */ + if (prepare->num_out_map_entries && prepare->num_in_map_entries && + ctx->is_offline) { + rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd, + ctx->base[i].idx, &kmd_buf); + if (rc) + CAM_ERR(CAM_ISP, + "Add GO_CMD faled i: %d, idx: %d, rc: %d", + i, ctx->base[i].idx, rc); + } + /* * reg update will be done later for the initial configure. * need to plus one to the op_code and only take the lower @@ -6075,7 +6177,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) isp_hw_cmd_args->u.sof_irq_enable); break; case CAM_ISP_HW_MGR_CMD_CTX_TYPE: - if (ctx->is_fe_enable) + if (ctx->is_fe_enabled && ctx->is_offline) + isp_hw_cmd_args->u.ctx_type = + CAM_ISP_CTX_OFFLINE; + else if (ctx->is_fe_enabled && !ctx->is_offline) 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; @@ -6309,6 +6414,17 @@ end: return rc; } +static inline void cam_ife_hw_mgr_get_offline_sof_timestamp( + uint64_t *timestamp, + uint64_t *boot_time) +{ + struct timespec64 ts; + + ktime_get_boottime_ts64(&ts); + *timestamp = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec); + *boot_time = *timestamp; +} + static int cam_ife_mgr_cmd_get_sof_timestamp( struct cam_ife_hw_mgr_ctx *ife_ctx, uint64_t *time_stamp, @@ -6681,6 +6797,7 @@ static int cam_ife_hw_mgr_handle_hw_rup( case CAM_ISP_HW_VFE_IN_PDLIB: case CAM_ISP_HW_VFE_IN_LCR: + case CAM_ISP_HW_VFE_IN_RD: break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", @@ -6810,6 +6927,8 @@ static int cam_ife_hw_mgr_handle_hw_sof( struct cam_isp_hw_sof_event_data sof_done_event_data; int rc = 0; + memset(&sof_done_event_data, 0, sizeof(sof_done_event_data)); + ife_hw_irq_sof_cb = ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF]; @@ -6820,10 +6939,15 @@ static int cam_ife_hw_mgr_handle_hw_sof( rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, CAM_ISP_HW_EVENT_SOF); if (!rc) { - cam_ife_mgr_cmd_get_sof_timestamp( - ife_hw_mgr_ctx, - &sof_done_event_data.timestamp, - &sof_done_event_data.boot_time); + if (ife_hw_mgr_ctx->is_offline) + cam_ife_hw_mgr_get_offline_sof_timestamp( + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); + else + cam_ife_mgr_cmd_get_sof_timestamp( + ife_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); /* if frame header is enabled reset qtimer ts */ if (ife_hw_mgr_ctx->use_frame_header_ts) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 91caeb314f41..627c7fc780dd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -82,12 +82,13 @@ struct cam_ife_hw_mgr_debug { * @last_dump_flush_req_id Last req id for which reg dump on flush was called * @last_dump_err_req_id Last req id for which reg dump on error was called * @init_done indicate whether init hw is done - * @is_fe_enable indicate whether fetch engine\read path is enabled + * @is_fe_enabled Indicate whether fetch engine\read path is enabled * @is_dual indicate whether context is in dual VFE mode * @custom_enabled update the flag if context is connected to custom HW * @use_frame_header_ts obtain qtimer ts using frame header * @ts captured timestamp when the ctx is acquired * @is_tpg indicate whether context is using PHY TPG + * @is_offline Indicate whether context is for offline IFE */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -133,12 +134,13 @@ struct cam_ife_hw_mgr_ctx { uint64_t last_dump_flush_req_id; uint64_t last_dump_err_req_id; bool init_done; - bool is_fe_enable; + bool is_fe_enabled; bool is_dual; bool custom_enabled; bool use_frame_header_ts; struct timespec64 ts; bool is_tpg; + bool is_offline; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index b6027db649fb..15b01a35581f 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -947,7 +947,7 @@ int cam_isp_add_reg_update( return rc; CAM_DBG(CAM_ISP, "Reg update added for res %d hw_id %d", - res->res_id, res->hw_intf->hw_idx); + res->res_type, res->hw_intf->hw_idx); reg_update_size += get_regup.cmd.used_bytes; } } @@ -981,3 +981,100 @@ int cam_isp_add_reg_update( return rc; } + +int cam_isp_add_go_cmd( + struct cam_hw_prepare_update_args *prepare, + struct list_head *res_list_isp_rd, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info) +{ + int rc = -EINVAL; + struct cam_isp_resource_node *res; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_update_entry *hw_entry; + struct cam_isp_hw_get_cmd_update get_regup; + uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; + + hw_entry = prepare->hw_update_entries; + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries current: %d max: %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + reg_update_size = 0; + list_for_each_entry(hw_mgr_res, res_list_isp_rd, list) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) + continue; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + res = hw_mgr_res->hw_res[i]; + if (res->hw_intf->hw_idx != base_idx) + continue; + + if (kmd_buf_info->size > (kmd_buf_info->used_bytes + + reg_update_size)) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + reg_update_size); + } else { + CAM_ERR(CAM_ISP, "no free mem %d %d %d", + base_idx, kmd_buf_info->size, + kmd_buf_info->used_bytes + + reg_update_size); + rc = -EINVAL; + return rc; + } + + get_regup.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + reg_update_size/4; + get_regup.cmd.size = kmd_buf_remain_size; + get_regup.cmd_type = CAM_ISP_HW_CMD_FE_TRIGGER_CMD; + get_regup.res = res; + + rc = res->process_cmd(res->res_priv, + CAM_ISP_HW_CMD_FE_TRIGGER_CMD, &get_regup, + sizeof(struct cam_isp_hw_get_cmd_update)); + if (rc) + return rc; + + CAM_DBG(CAM_ISP, "GO_CMD added for RD res %d hw_id %d", + res->res_type, res->hw_intf->hw_idx); + reg_update_size += get_regup.cmd.used_bytes; + } + } + + if (reg_update_size) { + /* Update the HW entries */ + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = reg_update_size; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + + prepare->hw_update_entries[num_ent].flags = + CAM_ISP_IOCFG_BL; + CAM_DBG(CAM_ISP, + "num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); + num_ent++; + + kmd_buf_info->used_bytes += reg_update_size; + kmd_buf_info->offset += reg_update_size; + prepare->num_hw_update_entries = num_ent; + rc = 0; + } + + return rc; +} + diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index ca56b155e9ba..92632b689a40 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -176,4 +176,23 @@ int cam_isp_add_reg_update( uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info); +/* + * cam_isp_add_go_cmd() + * + * @brief Add go_cmd in the hw entries list for each rd source + * + * @prepare: Contain the packet and HW update variables + * @res_list_isp_rd: Resource list for BUS RD ports + * @base_idx: Base or dev index of the IFE/VFE HW instance + * @kmd_buf_info: Kmd buffer to store the change base command + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_isp_add_go_cmd( + struct cam_hw_prepare_update_args *prepare, + struct list_head *res_list_isp_rd, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info); + + #endif /*_CAM_ISP_HW_PARSER_H */ diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index f68a6ec3a84e..9ee05756c306 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -239,6 +239,7 @@ enum cam_isp_ctx_type { CAM_ISP_CTX_FS2 = 1, CAM_ISP_CTX_RDI, CAM_ISP_CTX_PIX, + CAM_ISP_CTX_OFFLINE, CAM_ISP_CTX_MAX, }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index c242bdaa174c..78c457b6a7cb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -97,6 +97,7 @@ struct cam_isp_in_port_generic_info { uint32_t batch_size; uint32_t dsp_mode; uint32_t hbi_cnt; + uint32_t fe_unpacker_fmt; uint32_t cust_node; uint32_t num_out_res; uint32_t horizontal_bin; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 02c1948e90a2..2f00b1476986 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -77,8 +77,8 @@ enum cam_isp_resource_type { CAM_ISP_RESOURCE_CID, CAM_ISP_RESOURCE_PIX_PATH, CAM_ISP_RESOURCE_VFE_IN, - CAM_ISP_RESOURCE_VFE_OUT, CAM_ISP_RESOURCE_VFE_BUS_RD, + CAM_ISP_RESOURCE_VFE_OUT, CAM_ISP_RESOURCE_TPG, CAM_ISP_RESOURCE_TFE_IN, CAM_ISP_RESOURCE_TFE_OUT, @@ -114,6 +114,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, CAM_ISP_HW_CMD_DUMP_HW, + CAM_ISP_HW_CMD_FE_TRIGGER_CMD, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index c3f2aabf5656..531e695583a0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -102,6 +102,27 @@ struct cam_vfe_hw_get_hw_cap { uint32_t max_rdi_num; }; +/* + * struct cam_vfe_hw_vfe_bus_rd_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @res_id: Unique Identity of port to associate with this + * resource. + * @is_dual: Flag to indicate dual VFE usecase + * @cdm_ops: CDM operations + * @unpacket_fmt: Unpacker format for read engine + * @is_offline: Flag to indicate offline usecase + */ +struct cam_vfe_hw_vfe_bus_rd_acquire_args { + struct cam_isp_resource_node *rsrc_node; + uint32_t res_id; + uint32_t is_dual; + struct cam_cdm_utils_ops *cdm_ops; + uint32_t unpacker_fmt; + bool is_offline; +}; + /* * struct cam_vfe_hw_vfe_out_acquire_args: * @@ -143,6 +164,8 @@ struct cam_vfe_hw_vfe_out_acquire_args { * @sync_mode: In case of Dual VFE, this is Master or Slave. * (Default is Master in case of Single VFE) * @in_port: Input port details to acquire + * @is_fe_enabled: Flag to indicate if FE is enabled + * @is_offline: Flag to indicate Offline IFE */ struct cam_vfe_hw_vfe_in_acquire_args { struct cam_isp_resource_node *rsrc_node; @@ -152,6 +175,8 @@ struct cam_vfe_hw_vfe_in_acquire_args { void *cdm_ops; enum cam_isp_hw_sync_mode sync_mode; struct cam_isp_in_port_generic_info *in_port; + bool is_fe_enabled; + bool is_offline; }; /* @@ -173,9 +198,9 @@ struct cam_vfe_acquire_args { void *priv; cam_hw_mgr_event_cb_func event_cb; 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; + struct cam_vfe_hw_vfe_out_acquire_args vfe_out; + struct cam_vfe_hw_vfe_bus_rd_acquire_args vfe_bus_rd; + struct cam_vfe_hw_vfe_in_acquire_args vfe_in; }; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 1a80dc7f8f2e..946ac2267d95 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -407,6 +407,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = { .max_height = -1, }, }, + .top_irq_shift = 23, }; static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 0cd59de02f46..18a0071bf0b0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1360,6 +1360,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe480_bus_rd_hw_info = { .max_height = -1, }, }, + .top_irq_shift = 8, }; struct cam_vfe_hw_info cam_vfe480_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c index 28e4218a7bd3..3f7ce6a4a55c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -39,24 +39,29 @@ static const char drv_name[] = "vfe_bus_rd"; buf_array[(index)++] = val; \ } while (0) +#define BUS_RD_VER1_DEFAULT_LATENCY_BUF_ALLOC 512 + 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, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_128 = 0x0, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_8 = 0x1, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_10BPP = 0x2, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_12BPP = 0x3, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_14BPP = 0x4, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_32_20BPP = 0x5, + BUS_RD_VER1_UNPACKER_FMT_ARGB_10 = 0x6, + BUS_RD_VER1_UNPACKER_FMT_ARGB_12 = 0x7, + BUS_RD_VER1_UNPACKER_FMT_ARGB_14 = 0x8, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_32 = 0x9, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_64 = 0xA, + BUS_RD_VER1_UNPACKER_FMT_TP_10 = 0xB, + BUS_RD_VER1_UNPACKER_FMT_MIPI8 = 0xC, + BUS_RD_VER1_UNPACKER_FMT_MIPI10 = 0xD, + BUS_RD_VER1_UNPACKER_FMT_MIPI12 = 0xE, + BUS_RD_VER1_UNPACKER_FMT_MIPI14 = 0xF, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_16BPP = 0x10, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_128_ODD_EVEN = 0x11, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_8_ODD_EVEN = 0x12, + BUS_RD_VER1_UNPACKER_FMT_MAX = 0x13, }; struct cam_vfe_bus_rd_ver1_common_data { @@ -76,6 +81,7 @@ struct cam_vfe_bus_rd_ver1_common_data { uint32_t num_sec_out; uint32_t fs_sync_enable; uint32_t go_cmd_sel; + cam_hw_mgr_event_cb_func event_cb; }; struct cam_vfe_bus_rd_ver1_rm_resource_data { @@ -85,7 +91,6 @@ struct cam_vfe_bus_rd_ver1_rm_resource_data { void *ctx; bool init_cfg_done; - bool hfr_cfg_done; uint32_t offset; @@ -127,12 +132,16 @@ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data { uint32_t max_height; struct cam_cdm_utils_ops *cdm_util_ops; uint32_t secure_mode; + int irq_handle; + void *priv; + uint32_t status; + bool is_offline; }; 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; + uint32_t num_client; + uint32_t num_bus_rd_resc; struct cam_isp_resource_node bus_client[ CAM_VFE_BUS_RD_VER1_MAX_CLIENTS]; @@ -140,32 +149,105 @@ struct cam_vfe_bus_rd_ver1_priv { CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX]; int irq_handle; - int error_irq_handle; + void *tasklet_info; + uint32_t top_irq_shift; }; -static int cam_vfe_bus_process_cmd( +static int cam_vfe_bus_rd_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); +static void cam_vfe_bus_rd_pxls_to_bytes(uint32_t pxls, uint32_t fmt, + uint32_t *bytes) +{ + switch (fmt) { + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_128: + *bytes = pxls * 16; + break; + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_8: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_8_ODD_EVEN: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_10BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_12BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_14BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_16BPP: + case BUS_RD_VER1_UNPACKER_FMT_ARGB_10: + case BUS_RD_VER1_UNPACKER_FMT_ARGB_12: + case BUS_RD_VER1_UNPACKER_FMT_ARGB_14: + *bytes = pxls * 2; + break; + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_32_20BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_32: + *bytes = pxls * 4; + break; + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_64: + *bytes = pxls * 8; + break; + case BUS_RD_VER1_UNPACKER_FMT_TP_10: + *bytes = ALIGNUP(pxls, 3) * 4 / 3; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI8: + *bytes = pxls; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI10: + *bytes = ALIGNUP(pxls * 5, 4) / 4; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI12: + *bytes = ALIGNUP(pxls * 3, 2) / 2; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI14: + *bytes = ALIGNUP(pxls * 7, 4) / 4; + break; + default: + CAM_ERR(CAM_ISP, "Invalid unpacker_fmt:%d", fmt); + break; + } +} + 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_PLAIN128: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_128; + case CAM_FORMAT_PLAIN8: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_8; + case CAM_FORMAT_PLAIN16_10: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN32_20: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_32_20BPP; + case CAM_FORMAT_ARGB_10: + return BUS_RD_VER1_UNPACKER_FMT_ARGB_10; + case CAM_FORMAT_ARGB_12: + return BUS_RD_VER1_UNPACKER_FMT_ARGB_12; + case CAM_FORMAT_ARGB_14: + return BUS_RD_VER1_UNPACKER_FMT_ARGB_14; + case CAM_FORMAT_PLAIN32: + case CAM_FORMAT_ARGB: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_32; + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_ARGB_16: + case CAM_FORMAT_PD10: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_64; + case CAM_FORMAT_TP10: + return BUS_RD_VER1_UNPACKER_FMT_TP_10; + case CAM_FORMAT_MIPI_RAW_8: + return BUS_RD_VER1_UNPACKER_FMT_MIPI8; case CAM_FORMAT_MIPI_RAW_10: - return BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN; + return BUS_RD_VER1_UNPACKER_FMT_MIPI10; + case CAM_FORMAT_MIPI_RAW_12: + return BUS_RD_VER1_UNPACKER_FMT_MIPI12; + case CAM_FORMAT_MIPI_RAW_14: + return BUS_RD_VER1_UNPACKER_FMT_MIPI14; + case CAM_FORMAT_PLAIN16_16: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_16BPP; + case CAM_FORMAT_PLAIN8_SWAP: + return BUS_RD_VER1_UNPACKER_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; + return BUS_RD_VER1_UNPACKER_FMT_MAX; } } @@ -187,12 +269,58 @@ static int cam_vfe_bus_get_num_rm( 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_rd_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_isp_resource_node *bus_rd = NULL; + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; + + bus_rd = th_payload->handler_priv; + if (!bus_rd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + rsrc_data = bus_rd->res_priv; + rsrc_data->status = th_payload->evt_status_arr[0]; + + CAM_DBG(CAM_ISP, "VFE:%d Bus RD IRQ status_0: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0]); + + return 0; +} + +static int cam_vfe_bus_rd_handle_irq_bottom_half( + void *handler_priv, void *evt_payload_priv) +{ + struct cam_isp_resource_node *bus_rd = NULL; + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; + + bus_rd = (struct cam_isp_resource_node *)handler_priv; + if (!bus_rd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + rsrc_data = bus_rd->res_priv; + + if (rsrc_data->status & 0x2) + CAM_DBG(CAM_ISP, "Received VFE:%d BUS RD RUP", + rsrc_data->common_data->core_index); + else if (rsrc_data->status & 0x4) + CAM_DBG(CAM_ISP, "Received VFE:%d BUS RD BUF DONE", + rsrc_data->common_data->core_index); + else if (rsrc_data->status & 0x10000) { + CAM_ERR(CAM_ISP, "Received VFE:%d BUS RD CCIF Violation", + rsrc_data->common_data->core_index); + return CAM_VFE_IRQ_STATUS_VIOLATION; } - CAM_ERR(CAM_ISP, "Unsupported resource_type %u", - res_type); - return -EINVAL; + return CAM_VFE_IRQ_STATUS_SUCCESS; } static int cam_vfe_bus_get_rm_idx( @@ -219,19 +347,18 @@ static int cam_vfe_bus_get_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_generic_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) + struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv, + 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, + struct cam_isp_resource_node **rm_res, + uint32_t *client_done_mask, + uint32_t is_dual, + uint32_t unpacker_fmt) { - uint32_t rm_idx = 0; - struct cam_isp_resource_node *rm_res_local = NULL; + 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; @@ -240,14 +367,15 @@ static int cam_vfe_bus_acquire_rm( /* 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", + CAM_ERR(CAM_ISP, "Unsupported VFE RM:%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", + CAM_ERR(CAM_ISP, "VFE:%d RM:%d res not available state:%d", + ver1_bus_rd_priv->common_data.core_index, rm_idx, rm_res_local->res_state); return -EALREADY; } @@ -257,18 +385,22 @@ static int cam_vfe_bus_acquire_rm( rsrc_data = rm_res_local->res_priv; rsrc_data->ctx = ctx; rsrc_data->is_dual = is_dual; + rsrc_data->unpacker_cfg = cam_vfe_bus_get_unpacker_fmt(unpacker_fmt); + rsrc_data->latency_buf_allocation = + BUS_RD_VER1_DEFAULT_LATENCY_BUF_ALLOC; /* Set RM offset value to default */ rsrc_data->offset = 0; - *client_done_mask = (1 << rm_idx); + *client_done_mask = (1 << (rm_idx + 2)); *rm_res = rm_res_local; - CAM_DBG(CAM_ISP, "RM %d: Acquired"); + CAM_DBG(CAM_ISP, "VFE:%d RM:%d Acquired", + rsrc_data->common_data->core_index, rsrc_data->index); return 0; } -static int cam_vfe_bus_release_rm(void *bus_priv, - struct cam_isp_resource_node *rm_res) +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; @@ -281,68 +413,49 @@ static int cam_vfe_bus_release_rm(void *bus_priv, 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; + CAM_DBG(CAM_ISP, "VFE:%d RM:%d released", + rsrc_data->common_data->core_index, rsrc_data->index); 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; + struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data; + struct cam_vfe_bus_rd_ver1_common_data *common_data; + uint32_t buf_size; - 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); + rm_data = rm_res->res_priv; + common_data = rm_data->common_data; - /* Write All the values*/ - offset = rm_data->hw_regs->buf_size; 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); + cam_io_w_mb(buf_size, common_data->mem_base + + rm_data->hw_regs->buf_size); + cam_io_w_mb(rm_data->width, common_data->mem_base + + rm_data->hw_regs->stride); + cam_io_w_mb(rm_data->unpacker_cfg, common_data->mem_base + + rm_data->hw_regs->unpacker_cfg); + cam_io_w_mb(rm_data->latency_buf_allocation, common_data->mem_base + + rm_data->hw_regs->latency_buf_allocation); + cam_io_w_mb(0x1, common_data->mem_base + rm_data->hw_regs->cfg); - 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); + rm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; - 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); + CAM_DBG(CAM_ISP, + "Start VFE:%d RM:%d offset:0x%X en_cfg:0x%X width:%d height:%d", + rm_data->common_data->core_index, rm_data->index, + (uint32_t) rm_data->hw_regs->cfg, rm_data->en_cfg, + rm_data->width, rm_data->height); + CAM_DBG(CAM_ISP, "RM:%d pk_fmt:%d stride:%d", rm_data->index, + rm_data->unpacker_cfg, rm_data->stride); - 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; + return 0; } static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res) @@ -354,12 +467,13 @@ static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res) rsrc_data->common_data; /* Disable RM */ - cam_io_w_mb(0x0, - common_data->mem_base + rsrc_data->hw_regs->cfg); + 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; + + CAM_DBG(CAM_ISP, "VFE:%d RM:%d stopped", + rsrc_data->common_data->core_index, rsrc_data->index); return rc; } @@ -374,7 +488,8 @@ static int cam_vfe_bus_init_rm_resource(uint32_t index, 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"); + CAM_DBG(CAM_ISP, "Failed to alloc VFE:%d RM res priv", + ver1_bus_rd_priv->common_data.core_index); return -ENOMEM; } rm_res->res_priv = rsrc_data; @@ -390,7 +505,6 @@ static int cam_vfe_bus_init_rm_resource(uint32_t index, rm_res->stop = cam_vfe_bus_stop_rm; rm_res->hw_intf = ver1_bus_rd_priv->common_data.hw_intf; - return 0; } @@ -430,15 +544,13 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, 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_vfe_hw_vfe_bus_rd_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"); @@ -447,9 +559,6 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, 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) @@ -461,61 +570,40 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, 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); + CAM_ERR(CAM_ISP, "VFE:%d RM:0x%x not available state:%d", + ver1_bus_rd_priv->common_data.core_index, + acq_args->rsrc_type, rsrc_node->res_state); return -EBUSY; } + rsrc_node->res_id = acq_args->rsrc_type; 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); + CAM_DBG(CAM_ISP, "VFE:%d acquire RD type:0x%x", + rsrc_data->common_data->core_index, acq_args->rsrc_type); rsrc_data->num_rm = num_rm; rsrc_node->tasklet_info = acq_args->tasklet; + ver1_bus_rd_priv->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; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + rsrc_data->is_offline = bus_rd_acquire_args->is_offline; 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, acq_args->priv, bus_rd_res_id, i, - subscribe_irq, &rsrc_data->rm_res[i], &client_done_mask, - bus_rd_acquire_args->is_dual); + bus_rd_acquire_args->is_dual, + bus_rd_acquire_args->unpacker_fmt); if (rc) { CAM_ERR(CAM_ISP, - "VFE%d RM acquire failed for Out %d rc=%d", + "VFE:%d RM:%d acquire failed rc:%d", rsrc_data->common_data->core_index, bus_rd_res_id, rc); goto release_rm; @@ -525,7 +613,8 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; bus_rd_acquire_args->rsrc_node = rsrc_node; - CAM_DBG(CAM_ISP, "Acquire successful"); + CAM_DBG(CAM_ISP, "VFE:%d acquire RD 0x%x successful", + rsrc_data->common_data->core_index, acq_args->rsrc_type); return rc; release_rm: @@ -540,7 +629,6 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, 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", @@ -552,8 +640,10 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *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); + CAM_ERR(CAM_ISP, + "VFE:%d RD type:0x%x invalid resource state:%d", + rsrc_data->common_data->core_index, + vfe_bus_rd->res_id, vfe_bus_rd->res_state); } for (i = 0; i < rsrc_data->num_rm; i++) @@ -564,32 +654,6 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, 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; @@ -597,31 +661,56 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, } static int cam_vfe_bus_start_vfe_bus_rd( - struct cam_isp_resource_node *vfe_out) + 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; - struct cam_vfe_bus_rd_ver1_common_data *common_data = NULL; + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; + struct cam_vfe_bus_rd_ver1_common_data *common_data = NULL; + uint32_t irq_reg_mask[1] = {0x6}, val = 0; - if (!vfe_out) { + if (!vfe_bus_rd) { CAM_ERR(CAM_ISP, "Invalid input"); return -EINVAL; } - rsrc_data = vfe_out->res_priv; + rsrc_data = vfe_bus_rd->res_priv; common_data = rsrc_data->common_data; - CAM_DBG(CAM_ISP, "Start resource type: %x", rsrc_data->bus_rd_type); + CAM_DBG(CAM_ISP, "VFE:%d start RD type:0x%x", vfe_bus_rd->res_id); - if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { CAM_ERR(CAM_ISP, "Invalid resource state:%d", - vfe_out->res_state); + vfe_bus_rd->res_state); return -EACCES; } + if (!rsrc_data->is_offline) { + val = (common_data->fs_sync_enable << 5) | + (common_data->go_cmd_sel << 4); + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->input_if_cmd); + } + 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; + + rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( + common_data->bus_irq_controller, + CAM_IRQ_PRIORITY_1, + irq_reg_mask, + vfe_bus_rd, + cam_vfe_bus_rd_handle_irq_top_half, + cam_vfe_bus_rd_handle_irq_bottom_half, + vfe_bus_rd->tasklet_info, + &tasklet_bh_api); + + if (rsrc_data->irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS RD IRQ"); + rsrc_data->irq_handle = 0; + return -EFAULT; + } + + vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; return rc; } @@ -631,7 +720,6 @@ static int cam_vfe_bus_stop_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; @@ -641,14 +729,26 @@ static int cam_vfe_bus_stop_vfe_bus_rd( 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", + CAM_DBG(CAM_ISP, "VFE:%d Bus RD 0x%x state: %d", + rsrc_data->common_data->core_index, vfe_bus_rd->res_id, 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]); + if (rsrc_data->irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + rsrc_data->common_data->bus_irq_controller, + rsrc_data->irq_handle); + rsrc_data->irq_handle = 0; + } + vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + CAM_DBG(CAM_ISP, "VFE:%d stopped Bus RD:0x%x", + rsrc_data->common_data->core_index, + vfe_bus_rd->res_id); return rc; } @@ -663,7 +763,7 @@ static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t index, 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) { + vfe_bus_rd_resc_type >= CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX) { CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d", vfe_bus_rd_resc_type); return -EINVAL; @@ -701,7 +801,7 @@ static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t index, 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->process_cmd = cam_vfe_bus_rd_process_cmd; vfe_bus_rd->hw_intf = bus_rd_priv->common_data.hw_intf; return 0; @@ -740,13 +840,18 @@ static int cam_vfe_bus_deinit_vfe_bus_rd_resource( } static int cam_vfe_bus_rd_ver1_handle_irq(uint32_t evt_id, - struct cam_irq_th_payload *th_payload) + struct cam_irq_th_payload *th_payload) { - struct cam_vfe_bus_rd_ver1_priv *bus_priv; + struct cam_vfe_bus_rd_ver1_priv *bus_priv; + int rc = 0; - bus_priv = th_payload->handler_priv; - CAM_DBG(CAM_ISP, "BUS READ IRQ Received"); - return 0; + bus_priv = th_payload->handler_priv; + CAM_DBG(CAM_ISP, "Top Bus RD IRQ Received"); + + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.bus_irq_controller); + + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; } static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args, @@ -759,7 +864,6 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args, 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; @@ -796,39 +900,32 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args, rm_data = vfe_bus_rd_data->rm_res[i]->res_priv; /* update size register */ - rm_data->width = io_cfg->planes[i].width; + cam_vfe_bus_rd_pxls_to_bytes(io_cfg->planes[i].width, + rm_data->unpacker_cfg, &rm_data->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->buf_size, buf_size); - CAM_DBG(CAM_ISP, "RM %d image size 0x%x", + CAM_DBG(CAM_ISP, "VFE:%d RM:%d image_size:0x%X", + rm_data->common_data->core_index, rm_data->index, reg_val_pair[j-1]); - val = rm_data->width; - CAM_DBG(CAM_ISP, "io_cfg stride 0x%x", val); + rm_data->stride = io_cfg->planes[i].plane_stride; 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->hw_regs->stride, rm_data->stride); + CAM_DBG(CAM_ISP, "VFE:%d RM:%d image_stride:0x%X", + rm_data->common_data->core_index, 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", + CAM_DBG(CAM_ISP, "VFE:%d RM:%d image_address:0x%X", + rm_data->common_data->core_index, rm_data->index, reg_val_pair[j-1]); rm_data->img_addr = reg_val_pair[j-1]; @@ -889,43 +986,93 @@ static int cam_vfe_bus_rd_update_fs_cfg(void *priv, void *cmd_args, 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); + + CAM_DBG(CAM_ISP, + "VFE:%d RM:%d format:0x%x unpacker_cfg:0x%x", + rm_data->format, rm_data->unpacker_cfg); + CAM_DBG(CAM_ISP, + "latency_buf_alloc:0x%x stride:0x%x go_cmd_sel:0x%x", + rm_data->latency_buf_allocation, rm_data->stride, + rm_data->go_cmd_sel); + CAM_DBG(CAM_ISP, + "fs_sync_en:%d hbi_cnt:0x%x fs_mode:0x%x min_vbi:0x%x", + rm_data->fs_sync_enable, rm_data->hbi_count, + rm_data->fs_mode, 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_rd_add_go_cmd(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rd_data; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + uint32_t reg_val_pair[2 * CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX]; + struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data; + int i = 0; + uint32_t val = 0, size = 0, offset = 0; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "invalid ars size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *) priv; + + 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; + } + + for (i = 0; i < rd_data->num_rm; i++) { + 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 = rd_data->rm_res[i]->res_priv; + offset = rsrc_data->common_data->common_reg->input_if_cmd; + val = cam_io_r_mb(rsrc_data->common_data->mem_base + offset); + val |= 0x1; + reg_val_pair[i * 2] = offset; + reg_val_pair[i * 2 + 1] = val; + CAM_DBG(CAM_ISP, "VFE:%d Bus RD go_cmd: 0x%x offset 0x%x", + rd_data->common_data->core_index, + reg_val_pair[i * 2 + 1], reg_val_pair[i * 2]); + } + + 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; + +} + static int cam_vfe_bus_start_hw(void *hw_priv, void *start_hw_args, uint32_t arg_size) { @@ -943,7 +1090,7 @@ static int cam_vfe_bus_init_hw(void *hw_priv, { struct cam_vfe_bus_rd_ver1_priv *bus_priv = hw_priv; uint32_t top_irq_reg_mask[3] = {0}; - uint32_t offset = 0, val = 0; + uint32_t offset = 0; struct cam_vfe_bus_rd_ver1_reg_offset_common *common_reg; if (!bus_priv) { @@ -951,7 +1098,7 @@ static int cam_vfe_bus_init_hw(void *hw_priv, return -EINVAL; } common_reg = bus_priv->common_data.common_reg; - top_irq_reg_mask[0] = (1 << 23); + top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift); bus_priv->irq_handle = cam_irq_controller_subscribe_irq( bus_priv->common_data.vfe_irq_controller, @@ -968,23 +1115,15 @@ static int cam_vfe_bus_init_hw(void *hw_priv, bus_priv->irq_handle = 0; 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); + cam_io_w_mb(0x1, 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; } @@ -999,13 +1138,6 @@ static int cam_vfe_bus_deinit_hw(void *hw_priv, 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); - bus_priv->error_irq_handle = 0; - } - if (bus_priv->irq_handle) { rc = cam_irq_controller_unsubscribe_irq( bus_priv->common_data.vfe_irq_controller, @@ -1016,13 +1148,13 @@ static int cam_vfe_bus_deinit_hw(void *hw_priv, return rc; } -static int __cam_vfe_bus_process_cmd(void *priv, +static int __cam_vfe_bus_rd_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); + return cam_vfe_bus_rd_process_cmd(priv, cmd_type, cmd_args, arg_size); } -static int cam_vfe_bus_process_cmd( +static int cam_vfe_bus_rd_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -1046,6 +1178,9 @@ static int cam_vfe_bus_process_cmd( case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD: rc = cam_vfe_bus_rd_update_fs_cfg(priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_FE_TRIGGER_CMD: + rc = cam_vfe_bus_rd_add_go_cmd(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -1104,6 +1239,7 @@ int cam_vfe_bus_rd_ver1_init( 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; + bus_priv->top_irq_shift = bus_rd_hw_info->top_irq_shift; mutex_init(&bus_priv->common_data.bus_mutex); @@ -1143,7 +1279,7 @@ int cam_vfe_bus_rd_ver1_init( 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_local->hw_ops.process_cmd = __cam_vfe_bus_rd_process_cmd; *vfe_bus = vfe_bus_local; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h index 19cc86496371..90229b179c0d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_BUS_R_VER1_H_ @@ -88,6 +88,7 @@ struct cam_vfe_bus_rd_ver1_hw_info { 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]; + uint32_t top_irq_shift; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index d9fe166d3981..ca0cf15ba200 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -54,6 +54,8 @@ struct cam_vfe_mux_camif_ver3_data { uint32_t qcfa_bin; uint32_t dual_hw_idx; uint32_t is_dual; + bool is_fe_enabled; + bool is_offline; }; static int cam_vfe_camif_ver3_get_evt_payload( @@ -248,19 +250,20 @@ int cam_vfe_camif_ver3_acquire_resource( return rc; } - camif_data->sync_mode = acquire_data->vfe_in.sync_mode; - camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern; - camif_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode; - camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start; - camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop; - camif_data->first_line = acquire_data->vfe_in.in_port->line_start; - camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; + camif_data->sync_mode = acquire_data->vfe_in.sync_mode; + camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern; + camif_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode; + camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start; + camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop; + camif_data->first_line = acquire_data->vfe_in.in_port->line_start; + camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; + camif_data->is_fe_enabled = acquire_data->vfe_in.is_fe_enabled; + camif_data->is_offline = acquire_data->vfe_in.is_offline; + camif_data->event_cb = acquire_data->event_cb; + camif_data->priv = acquire_data->priv; + camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin; camif_data->horizontal_bin = acquire_data->vfe_in.in_port->horizontal_bin; - camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin; - camif_data->event_cb = acquire_data->event_cb; - camif_data->priv = acquire_data->priv; - camif_data->is_dual = acquire_data->vfe_in.is_dual; if (acquire_data->vfe_in.is_dual) camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx; @@ -417,12 +420,20 @@ static int cam_vfe_camif_ver3_resource_start( val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) << CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP; + if (rsrc_data->is_fe_enabled && !rsrc_data->is_offline) + val |= 0x2 << rsrc_data->reg_data->operating_mode_shift; + else + val |= 0x1 << rsrc_data->reg_data->operating_mode_shift; + if (rsrc_data->is_dual && rsrc_data->reg_data->dual_vfe_sync_mask) { val |= (((rsrc_data->dual_hw_idx & rsrc_data->reg_data->dual_vfe_sync_mask) + 1) << rsrc_data->reg_data->dual_ife_sync_sel_shift); } + CAM_DBG(CAM_ISP, "VFE:%d TOP core_cfg: 0x%X", + camif_res->hw_intf->hw_idx, val); + cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg_0); @@ -459,11 +470,14 @@ static int cam_vfe_camif_ver3_resource_start( camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; /* Reg Update */ - cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, - rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd); - CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X", - camif_res->hw_intf->hw_idx, - rsrc_data->reg_data->reg_update_cmd_data); + if (!rsrc_data->is_offline) { + cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, + rsrc_data->mem_base + + rsrc_data->camif_reg->reg_update_cmd); + CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X", + camif_res->hw_intf->hw_idx, + rsrc_data->reg_data->reg_update_cmd_data); + } /* disable sof irq debug flag */ rsrc_data->enable_sof_irq_debug = false; @@ -606,6 +620,18 @@ static int cam_vfe_camif_ver3_reg_dump( CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val); } + CAM_INFO(CAM_ISP, "IFE:%d BUS RD", camif_res->hw_intf->hw_idx); + for (offset = 0xA800; offset <= 0xA89C; 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); + if (offset == 0xA838) + offset = 0xA844; + if (offset == 0xA864) + offset = 0xA874; + if (offset == 0xA878) + offset = 0xA87C; + } + CAM_INFO(CAM_ISP, "IFE:%d BUS WR", camif_res->hw_intf->hw_idx); for (offset = 0xAA00; offset <= 0xAADC; offset += 0x4) { val = cam_soc_util_r(camif_priv->soc_info, 0, offset); From 7c25b49bef5e27f6fe6d7ba0cff916d7e6fd9205 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Sat, 8 Feb 2020 17:18:50 -0800 Subject: [PATCH 274/790] msm: camera: ife: Reduce CSID reset timeout This change reduces CSID reset timeout from one second to hundred milliseconds. CRs-Fixed: 2619894 Change-Id: I1593b033356fc17c2fc35e962dd193a5537b23b7 Signed-off-by: Venkat Chinta --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index b7787a32ff97..cd9a71e30435 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -33,6 +33,8 @@ #define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000 #define CAM_IFE_CSID_TIMEOUT_ALL_US 100000 +#define CAM_IFE_CSID_RESET_TIMEOUT_MS 100 + /* * Constant Factors needed to change QTimer ticks to nanoseconds * QTimer Freq = 19.2 MHz @@ -655,7 +657,7 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, reset_strb_addr); rem_jiffies = wait_for_completion_timeout(complete, - msecs_to_jiffies(IFE_CSID_TIMEOUT)); + msecs_to_jiffies(CAM_IFE_CSID_RESET_TIMEOUT_MS)); if (!rem_jiffies) { rc = -ETIMEDOUT; CAM_ERR(CAM_ISP, "CSID:%d Res id %d fail rc = %d", @@ -3321,7 +3323,7 @@ static int cam_ife_csid_reset_regs( spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); CAM_DBG(CAM_ISP, "CSID reset start"); rc = wait_for_completion_timeout(&csid_hw->csid_top_complete, - msecs_to_jiffies(IFE_CSID_TIMEOUT)); + msecs_to_jiffies(CAM_IFE_CSID_RESET_TIMEOUT_MS)); if (rc <= 0) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_status_addr); From 704dc07b7b419fba17f15ed27488b60fb3b74b5c Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Fri, 7 Feb 2020 15:13:18 +0530 Subject: [PATCH 275/790] msm: camera: ope: Clear comp events before each request If there is a stale entry of any event in the CDM, it will end the wait of same event in next request. So, clearing the comp events before each request. CRs-Fixed: 2611231 Change-Id: I252ee5edaea1cda34dc48343dd6bc865b490e977 Signed-off-by: Rishabh Jain --- drivers/cam_cdm/cam_cdm_util.c | 31 ++++++++++++++++++++ drivers/cam_cdm/cam_cdm_util.h | 15 ++++++++++ drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 7 +++++ 3 files changed, 53 insertions(+) diff --git a/drivers/cam_cdm/cam_cdm_util.c b/drivers/cam_cdm/cam_cdm_util.c index c9eee75f1c43..117680a5f8a0 100644 --- a/drivers/cam_cdm/cam_cdm_util.c +++ b/drivers/cam_cdm/cam_cdm_util.c @@ -168,6 +168,15 @@ struct cdm_wait_comp_event_cmd { unsigned int mask2; } __attribute__((__packed__)); +struct cdm_clear_comp_event_cmd { + unsigned int reserved : 8; + unsigned int id : 8; + unsigned int id_reserved: 8; + unsigned int cmd : 8; + unsigned int mask1; + unsigned int mask2; +} __attribute__((__packed__)); + struct cdm_prefetch_disable_event_cmd { unsigned int reserved : 8; unsigned int id : 8; @@ -223,6 +232,11 @@ uint32_t cdm_required_size_comp_wait(void) return cdm_get_cmd_header_size(CAM_CDM_COMP_WAIT); } +uint32_t cdm_required_size_clear_comp_event(void) +{ + return cdm_get_cmd_header_size(CAM_CDM_CLEAR_COMP_WAIT); +} + uint32_t cdm_required_size_prefetch_disable(void) { return cdm_get_cmd_header_size(CAM_CDM_WAIT_PREFETCH_DISABLE); @@ -382,6 +396,21 @@ uint32_t *cdm_write_wait_comp_event( return pCmdBuffer; } +uint32_t *cdm_write_clear_comp_event( + uint32_t *pCmdBuffer, uint32_t mask1, uint32_t mask2) +{ + struct cdm_clear_comp_event_cmd *pHeader = + (struct cdm_clear_comp_event_cmd *)pCmdBuffer; + + pHeader->cmd = CAM_CDM_CLEAR_COMP_WAIT; + pHeader->mask1 = mask1; + pHeader->mask2 = mask2; + + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CLEAR_COMP_WAIT); + + return pCmdBuffer; +} + uint32_t *cdm_write_wait_prefetch_disable( uint32_t *pCmdBuffer, uint32_t id, @@ -412,6 +441,7 @@ struct cam_cdm_utils_ops CDM170_ops = { cdm_required_size_wait_event, cdm_required_size_changebase, cdm_required_size_comp_wait, + cdm_required_size_clear_comp_event, cdm_required_size_prefetch_disable, cdm_offsetof_dmi_addr, cdm_offsetof_indirect_addr, @@ -423,6 +453,7 @@ struct cam_cdm_utils_ops CDM170_ops = { cdm_write_wait_event, cdm_write_changebase, cdm_write_wait_comp_event, + cdm_write_clear_comp_event, cdm_write_wait_prefetch_disable, }; diff --git a/drivers/cam_cdm/cam_cdm_util.h b/drivers/cam_cdm/cam_cdm_util.h index 875c9215e6f8..ff613c44f8c3 100644 --- a/drivers/cam_cdm/cam_cdm_util.h +++ b/drivers/cam_cdm/cam_cdm_util.h @@ -65,6 +65,10 @@ enum cam_cdm_command { * in dwords. * @return Size in dwords * + * @cdm_required_size_clear_comp_event: Calculates the size of clear-comp-event + * command in dwords. + * @return Size in dwords + * * @cdm_required_size_changebase: Calculates the size of a change-base command * in dwords. * @return Size in dwords @@ -123,6 +127,12 @@ enum cam_cdm_command { * @pCmdBuffer: Pointer to command buffer * @mask1: This value decides which comp events to wait (0 - 31). * @mask2: This value decides which comp events to wait (32 - 65). + * + * @cdm_write_clear_comp_event: Writes a clear comp event cmd into the + * command buffer. + * @pCmdBuffer: Pointer to command buffer + * @mask1: This value decides which comp events to clear (0 - 31). + * @mask2: This value decides which comp events to clear (32 - 65). */ struct cam_cdm_utils_ops { uint32_t (*cdm_get_cmd_header_size)(unsigned int command); @@ -134,6 +144,7 @@ uint32_t (*cdm_required_size_genirq)(void); uint32_t (*cdm_required_size_wait_event)(void); uint32_t (*cdm_required_size_changebase)(void); uint32_t (*cdm_required_size_comp_wait)(void); +uint32_t (*cdm_required_size_clear_comp_event)(void); uint32_t (*cdm_required_size_prefetch_disable)(void); uint32_t (*cdm_offsetof_dmi_addr)(void); uint32_t (*cdm_offsetof_indirect_addr)(void); @@ -176,6 +187,10 @@ uint32_t *(*cdm_write_wait_comp_event)( uint32_t *pCmdBuffer, uint32_t mask1, uint32_t mask2); +uint32_t *(*cdm_write_clear_comp_event)( + uint32_t *pCmdBuffer, + uint32_t mask1, + uint32_t mask2); uint32_t *(*cdm_write_wait_prefetch_disable)( uint32_t *pCmdBuffer, uint32_t id, diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index cd5be9ec833a..1fc49cebbb09 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -1276,6 +1276,9 @@ static int cam_ope_dev_create_kmd_buf_nrt(struct cam_ope_hw_mgr *hw_mgr, cdm_ops = ctx_data->ope_cdm.cdm_ops; + kmd_buf = cdm_ops->cdm_write_clear_comp_event(kmd_buf, + OPE_WAIT_COMP_IDLE|OPE_WAIT_COMP_RUP, 0x0); + /* Frame 0 DB */ kmd_buf = ope_create_frame_cmd(hw_mgr, ctx_data, req_idx, @@ -1358,6 +1361,8 @@ static int cam_ope_dev_create_kmd_buf_batch(struct cam_ope_hw_mgr *hw_mgr, (kmd_buf_offset / sizeof(len)); cdm_kmd_start_addr = kmd_buf; cdm_ops = ctx_data->ope_cdm.cdm_ops; + kmd_buf = cdm_ops->cdm_write_clear_comp_event(kmd_buf, + OPE_WAIT_COMP_IDLE|OPE_WAIT_COMP_RUP, 0x0); for (i = 0; i < frm_proc->batch_size; i++) { wr_cdm_info = @@ -1494,6 +1499,8 @@ static int cam_ope_dev_create_kmd_buf(struct cam_ope_hw_mgr *hw_mgr, CAM_DBG(CAM_OPE, "kmd_buf:%x req_idx:%d req_id:%lld offset:%d", kmd_buf, req_idx, ope_request->request_id, kmd_buf_offset); + kmd_buf = cdm_ops->cdm_write_clear_comp_event(kmd_buf, + OPE_WAIT_COMP_IDLE|OPE_WAIT_COMP_RUP, 0x0); /* Frame 0 DB */ kmd_buf = ope_create_frame_cmd(hw_mgr, ctx_data, req_idx, From 37b7384396442087b89fc064f6b1ec1f3b880bb8 Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Mon, 3 Feb 2020 12:42:03 +0530 Subject: [PATCH 276/790] msm: camera: csiphy: Update phy sequence for bengal Toggle reset register in common and reset programming sequence. CRs-Fixed: 2615460 Change-Id: Iba17fa3b2014be0bc27236169cf8456a7f8ededd Signed-off-by: Tony Lijo Jose --- .../cam_csiphy/include/cam_csiphy_2_0_hwreg.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h index cbd0dc582b32..9549919e2ea7 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_2_0_HWREG_H_ @@ -12,8 +12,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, @@ -24,6 +24,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}, @@ -33,6 +35,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[] = { From a753fd0f4ddf25dba030ce6167e59b4a49713dd8 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Tue, 11 Feb 2020 12:18:05 -0800 Subject: [PATCH 277/790] msm: camera: ife: Assign VC/DT values for CSID TPG This change adds check for CSID TPG to assign VC/DT values for CSID path. CRs-Fixed: 2619894 Change-Id: I94b3661e45285cd83b572353a6bcd3f2b04d31c7 Signed-off-by: Venkat Chinta --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index b7787a32ff97..7ee973bc08ed 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1140,7 +1140,8 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->crop_enable); if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || - (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) { + (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || + (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG)) { path_data->dt = CAM_IFE_CSI_TPG_DT_VAL; path_data->vc = CAM_IFE_CSI_TPG_VC_VAL; } else { From a44cb8d722a809e183425015100d6a60b2a12044 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 9 Jan 2020 12:01:18 -0800 Subject: [PATCH 278/790] msm: camera: ife: Look into next request if res not found In cases where IRQ delays or overlap happens, the IRQ we get for the resource may belong to the 2nd request in the queue. If the IRQ resource is not found in top request, look into the second request as well. CRs-Fixed: 2600457 Change-Id: Ida2665a00169463e2f146de1cfa6be076d8c7d72 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_isp/cam_isp_context.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 0e9918f80f91..9e28d2eeb612 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -809,10 +809,28 @@ static int __cam_isp_ctx_handle_buf_done_for_request( } if (j == req_isp->num_fence_map_out) { - CAM_ERR(CAM_ISP, - "Can not find matching lane handle 0x%x!", - done->resource_handle[i]); - rc = -EINVAL; + if (done_next_req) { + /* + * If not found in current request, it could be + * belonging to next request, This can happen if + * IRQ delay happens. + */ + CAM_WARN(CAM_ISP, + "BUF_DONE for res 0x%x not found in Req %lld ", + __cam_isp_resource_handle_id_to_type( + done->resource_handle[i]), + req->request_id); + + done_next_req->resource_handle + [done_next_req->num_handles++] = + done->resource_handle[i]; + } else { + CAM_ERR(CAM_ISP, + "Can not find matching lane handle 0x%x! in Req %lld", + done->resource_handle[i], + req->request_id); + rc = -EINVAL; + } continue; } From 4e5ffd3ce0f136ff5e7ef785c5c5d434646a1fa8 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 16 Feb 2020 22:47:44 -0800 Subject: [PATCH 279/790] msm: camera: cci: Add device managed alloc to balance free in remove The devm_kfree call in remove is unbalanced without a devm_kzalloc. Add required kzalloc and free during probe to balance it. CRs-Fixed: 2584631 Change-Id: I14164405e62036f7918b858d978afe454e4feb4a Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 85cc359ec996..cd937016298c 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -376,7 +376,7 @@ static int cam_cci_component_bind(struct device *dev, int rc = 0; struct platform_device *pdev = to_platform_device(dev); - new_cci_dev = kzalloc(sizeof(struct cci_device), + new_cci_dev = devm_kzalloc(&pdev->dev, sizeof(struct cci_device), GFP_KERNEL); if (!new_cci_dev) return -ENOMEM; @@ -445,7 +445,7 @@ static int cam_cci_component_bind(struct device *dev, CAM_DBG(CAM_CCI, "Component bound successfully"); return rc; cci_no_resource: - kfree(new_cci_dev); + devm_kfree(&pdev->dev, new_cci_dev); return rc; } From afb504ab340b4e357a2982c99fde0a96f33382b1 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 16 Feb 2020 23:29:27 -0800 Subject: [PATCH 280/790] msm: camera: cdm: Fix component unbind failures in cdm hw In cdm hw unbind, smmu handle is destroyed before handler is unset. Also, mutex unlock is unbalanced during error case. Fix invalid unset handler call and unbalanced mutex in component unbind for hw cdm. CRs-Fixed: 2584631 Change-Id: I8e117ce9623ba631d9457ef851b8f271591091b6 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cdm/cam_cdm_hw_core.c | 4 ++-- drivers/cam_cdm/cam_cdm_intf.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index a78156243e3c..e5a8efeb6e70 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1894,10 +1894,10 @@ static void cam_hw_cdm_component_unbind(struct device *dev, destroy_workqueue(cdm_core->bl_fifo[i].work_queue); } - if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) - CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); cam_smmu_unset_client_page_fault_handler( cdm_core->iommu_hdl.non_secure, cdm_hw); + if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) + CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); mutex_destroy(&cdm_hw->hw_mutex); kfree(cdm_hw->soc_info.soc_private); diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index dcdbc667f832..8f9c9ce0ecb4 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -620,7 +620,7 @@ static void cam_cdm_intf_component_unbind(struct device *dev, if (cam_virtual_cdm_remove(pdev)) { CAM_ERR(CAM_CDM, "Virtual CDM remove failed"); - goto end; + return; } put_cdm_mgr_refcount(); @@ -635,7 +635,6 @@ static void cam_cdm_intf_component_unbind(struct device *dev, if (cdm_mgr.nodes[i].device || cdm_mgr.nodes[i].data || (cdm_mgr.nodes[i].refcount != 0)) { CAM_ERR(CAM_CDM, "Valid node present in index=%d", i); - mutex_unlock(&cam_cdm_mgr_lock); goto end; } mutex_destroy(&cdm_mgr.nodes[i].lock); From 3abdf420b1ad418454506df1dadfdfccb2d6e449 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 17 Feb 2020 19:22:28 -0800 Subject: [PATCH 281/790] msm: camera: isp: Fix failure due to dereference of invalid ife device During reset of vfe hw, we are referencing an ife device which might not be available. Add condition to check ife device validity before reset. CRs-Fixed: 2584631 Change-Id: Ibf9e3e0a3696cf006977af60360a964748e8ef38 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 ++- drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d12a375daf01..033b201338a6 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3948,7 +3948,8 @@ static int cam_ife_mgr_reset_vfe_hw(struct cam_ife_hw_mgr *hw_mgr, vfe_reset_type = CAM_VFE_HW_RESET_HW; for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) { - if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + if ((!hw_mgr->ife_devices[i]) || + (hw_idx != hw_mgr->ife_devices[i]->hw_idx)) continue; CAM_DBG(CAM_ISP, "VFE (id = %d) reset", hw_idx); vfe_hw_intf = hw_mgr->ife_devices[i]; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c index 3f1376311cdb..1dfa48cbfbf4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c @@ -14,7 +14,7 @@ #include "cam_vfe_soc.h" #include "cam_debug_util.h" -static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX] = {0, 0, 0, 0}; +static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX]; static char vfe_dev_name[8]; From dbdab7dbb0742a6fc2969974888295d309bdb993 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 31 Jan 2020 15:05:23 -0800 Subject: [PATCH 282/790] msm: camera: ife: Change data type for timeout This commit changes the data type used to capture wait for completion timeout return value from integer type to the more appropriate unsigned long type. CRs-Fixed: 2620807 Change-Id: Ifcf54bdee133df5277ce56f0ba85442d32046eac Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 34 ++++++++----------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 20 +++++------ 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d12a375daf01..ae4944b342ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3521,6 +3521,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, struct cam_cdm_bl_request *cdm_cmd; struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; + unsigned long rem_jiffies = 0; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, @@ -3635,21 +3636,18 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, } if (cfg->init_packet) { - rc = wait_for_completion_timeout( + rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete, msecs_to_jiffies(30)); - if (rc <= 0) { + if (rem_jiffies == 0) { CAM_ERR(CAM_ISP, - "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; + "config done completion timeout for req_id=%llu ctx_index %d", + cfg->request_id, ctx->ctx_index); + rc = -ETIMEDOUT; + } else CAM_DBG(CAM_ISP, "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"); @@ -3797,6 +3795,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) struct cam_ife_hw_mgr_ctx *ctx; enum cam_ife_csid_halt_cmd csid_halt_type; uint32_t i, master_base_idx = 0; + unsigned long rem_jiffies = 0; if (!hw_mgr_priv || !stop_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -3896,14 +3895,12 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_pause_hw(ctx); - rc = wait_for_completion_timeout(&ctx->config_done_complete, + rem_jiffies = wait_for_completion_timeout(&ctx->config_done_complete, msecs_to_jiffies(10)); - if (rc == 0) { + if (rem_jiffies == 0) CAM_WARN(CAM_ISP, "config done completion timeout for last applied req_id=%llu rc=%d ctx_index %d", ctx->applied_req_id, rc, ctx->ctx_index); - rc = -ETIMEDOUT; - } if (stop_isp->stop_only) goto end; @@ -6144,6 +6141,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) hw_cmd_args->ctxt_to_hw_map; struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; struct cam_packet *packet; + unsigned long rem_jiffies = 0; if (!hw_mgr_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -6217,15 +6215,13 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) if (ctx->last_dump_flush_req_id == ctx->applied_req_id) return 0; - rc = wait_for_completion_timeout( + rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete, msecs_to_jiffies(30)); - if (rc <= 0) { + if (rem_jiffies == 0) CAM_ERR(CAM_ISP, - "config done completion timeout, Reg dump will be unreliable rc=%d ctx_index %d", - rc, ctx->ctx_index); - rc = 0; - } + "config done completion timeout, Reg dump will be unreliable ctx_index %d", + ctx->ctx_index); ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index bef045e79af7..07ea4a8154cf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3280,7 +3280,7 @@ static int cam_ife_csid_reset_regs( csid_hw->csid_info->csid_reg; struct cam_hw_soc_info *soc_info; uint32_t val = 0; - unsigned long flags; + unsigned long flags, rem_jiffies = 0; soc_info = &csid_hw->hw_info->soc_info; @@ -3323,9 +3323,10 @@ static int cam_ife_csid_reset_regs( spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); CAM_DBG(CAM_ISP, "CSID reset start"); - rc = wait_for_completion_timeout(&csid_hw->csid_top_complete, + + rem_jiffies = wait_for_completion_timeout(&csid_hw->csid_top_complete, msecs_to_jiffies(CAM_IFE_CSID_RESET_TIMEOUT_MS)); - if (rc <= 0) { + if (rem_jiffies == 0) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_status_addr); if (val & 0x1) { @@ -3337,19 +3338,18 @@ static int cam_ife_csid_reset_regs( CAM_DBG(CAM_ISP, "CSID:%d %s reset completed %d", csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", - rc); - rc = 0; + rem_jiffies); goto end; } CAM_ERR(CAM_ISP, "CSID:%d csid_reset %s fail rc = %d", - csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", rc); + csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", + rem_jiffies); rc = -ETIMEDOUT; goto end; - } else { + } else CAM_DBG(CAM_ISP, "CSID:%d %s reset completed %d", - csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", rc); - rc = 0; - } + csid_hw->hw_intf->hw_idx, reset_hw ? "hw" : "sw", + rem_jiffies); end: return rc; From cf19384de76ea74a01e15f6c04a6bfe313c42cb8 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 5 Feb 2020 16:50:54 -0800 Subject: [PATCH 283/790] msm: camera: ife: Change halt type This commit changes halt type when HVX streamer is enabled as halting immediately will lead to HVX hang. CRs-Fixed: 2620821 Change-Id: Iab28cb91018899acec1eb671a87aec05b872391e Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 10 +++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index ae4944b342ca..8ae4fc517fef 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2448,6 +2448,8 @@ static int cam_ife_mgr_acquire_hw_for_ctx( bool crop_enable = true; is_dual_isp = in_port->usage_type; + ife_ctx->dsp_enabled = (bool)in_port->dsp_mode; + /* get root node resource */ rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port); if (rc) { @@ -3812,7 +3814,8 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) stop_isp = (struct cam_isp_stop_args *)stop_args->args; /* Set the csid halt command */ - if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) + if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) || + ctx->dsp_enabled) csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY; else csid_halt_type = CAM_CSID_HALT_IMMEDIATELY; @@ -4372,6 +4375,11 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->num_reg_dump_buf = 0; ctx->custom_enabled = false; ctx->use_frame_header_ts = false; + ctx->num_reg_dump_buf = 0; + ctx->is_dual = false; + ctx->dsp_enabled = false; + ctx->is_fe_enabled = false; + ctx->is_offline = false; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 627c7fc780dd..bd83f8937257 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -89,6 +89,7 @@ struct cam_ife_hw_mgr_debug { * @ts captured timestamp when the ctx is acquired * @is_tpg indicate whether context is using PHY TPG * @is_offline Indicate whether context is for offline IFE + * @dsp_enabled Indicate whether dsp is enabled in this context */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -141,6 +142,7 @@ struct cam_ife_hw_mgr_ctx { struct timespec64 ts; bool is_tpg; bool is_offline; + bool dsp_enabled; }; /** From f1a54282cc02e77765f938d41764f29511ebe1e3 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 15 Jan 2020 18:29:00 -0800 Subject: [PATCH 284/790] msm: camera: ife: Improve logs This change adds more information to existing acquire and hfr update logs. CRs-Fixed: 2606911 Change-Id: I1ff4e1cbdd52be6b5c434438772084c4fdb2e80e Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 94 +++++++++++++------ .../hw_utils/cam_isp_packet_parser.c | 4 +- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 8ae4fc517fef..6434a4abe922 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -636,25 +636,50 @@ static const char *cam_ife_hw_mgr_get_src_res_id( } } -static void cam_ife_hw_mgr_dump_src_acq_info( - struct cam_ife_hw_mgr_ctx *hwr_mgr_ctx, - uint32_t num_pix_port, uint32_t num_rdi_port) +static void cam_ife_hw_mgr_print_acquire_info( + struct cam_ife_hw_mgr_ctx *hw_mgr_ctx, uint32_t num_pix_port, + uint32_t num_pd_port, uint32_t num_rdi_port, int acquire_failed) { struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res_temp = NULL; struct cam_isp_resource_node *hw_res = NULL; + int hw_idx[CAM_ISP_HW_SPLIT_MAX] = {-1, -1}; int i = 0; + hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_csid, + struct cam_isp_hw_mgr_res, list); + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) + hw_idx[i] = hw_res->hw_intf->hw_idx; + } + + if (acquire_failed) + goto fail; + CAM_INFO(CAM_ISP, - "Acquired HW for ctx: %u with pix_port: %u rdi_port: %u", - hwr_mgr_ctx->ctx_index, num_pix_port, num_rdi_port); + "Acquired %s IFE[%d %d] with [%u pix] [%u pd] [%u rdi] ports for ctx:%u", + (hw_mgr_ctx->is_dual) ? "dual" : "single", + hw_idx[CAM_ISP_HW_SPLIT_LEFT], hw_idx[CAM_ISP_HW_SPLIT_RIGHT], + num_pix_port, num_pd_port, num_rdi_port, hw_mgr_ctx->ctx_index); + + return; + +fail: + CAM_ERR(CAM_ISP, "Acquire HW failed for ctx:%u", hw_mgr_ctx->ctx_index); + CAM_INFO(CAM_ISP, + "Previously acquired %s IFE[%d %d] with [%u pix] [%u pd] [%u rdi] ports for ctx:%u", + (hw_mgr_ctx->is_dual) ? "dual" : "single", + hw_idx[CAM_ISP_HW_SPLIT_LEFT], hw_idx[CAM_ISP_HW_SPLIT_RIGHT], + num_pix_port, num_pd_port, num_rdi_port, hw_mgr_ctx->ctx_index); + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, - &hwr_mgr_ctx->res_list_ife_src, list) { + &hw_mgr_ctx->res_list_ife_src, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { hw_res = hw_mgr_res->hw_res[i]; if (hw_res && hw_res->hw_intf) CAM_INFO(CAM_ISP, - "IFE src split_id: %d res_id: %s hw_idx: %u state: %s", + "IFE src split_id:%d res_id:%s hw_idx:%u state:%s", i, cam_ife_hw_mgr_get_src_res_id( hw_res->res_id), @@ -2435,8 +2460,9 @@ err: static int cam_ife_mgr_acquire_hw_for_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, - uint32_t *num_pix_port, uint32_t *num_rdi_port, - uint32_t *acquired_hw_id, uint32_t *acquired_hw_path) + uint32_t *num_pix_port, uint32_t *num_rdi_port, + uint32_t *num_pd_port, uint32_t *acquired_hw_id, + uint32_t *acquired_hw_path) { int rc = -1; int is_dual_isp = 0; @@ -2541,7 +2567,8 @@ static int cam_ife_mgr_acquire_hw_for_ctx( goto err; } - *num_pix_port = ipp_count + ppp_count + ife_rd_count + lcr_count; + *num_pix_port = ipp_count + ife_rd_count + lcr_count; + *num_pd_port = ppp_count; *num_rdi_port = rdi_count; return 0; @@ -2819,8 +2846,10 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) struct cam_cdm_acquire_data cdm_acquire; uint32_t num_pix_port_per_in = 0; uint32_t num_rdi_port_per_in = 0; + uint32_t num_pd_port_per_in = 0; uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; + uint32_t total_pd_port = 0; struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; uint32_t input_size = 0; @@ -2917,16 +2946,18 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) else rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, &num_pix_port_per_in, &num_rdi_port_per_in, + &num_pd_port_per_in, &acquire_args->acquired_hw_id[i], acquire_args->acquired_hw_path[i]); total_pix_port += num_pix_port_per_in; total_rdi_port += num_rdi_port_per_in; + total_pd_port += num_pd_port_per_in; if (rc) { - CAM_ERR(CAM_ISP, "can not acquire resource"); - cam_ife_hw_mgr_dump_src_acq_info(ife_ctx, - total_pix_port, total_rdi_port); + cam_ife_hw_mgr_print_acquire_info(ife_ctx, + total_pix_port, total_pd_port, + total_rdi_port, rc); goto free_mem; } @@ -2936,7 +2967,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } /* Check whether context has only RDI resource */ - if (!total_pix_port) { + if (!total_pix_port && !total_pd_port) { ife_ctx->is_rdi_only_context = 1; CAM_DBG(CAM_ISP, "RDI only context"); } @@ -2958,10 +2989,9 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_hw_info->num_inputs; ktime_get_real_ts64(&ife_ctx->ts); - CAM_INFO(CAM_ISP, - "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", - total_pix_port, total_rdi_port, - ife_ctx->is_dual, ife_ctx->ctx_index); + + cam_ife_hw_mgr_print_acquire_info(ife_ctx, total_pix_port, + total_pd_port, total_rdi_port, rc); cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); @@ -3037,6 +3067,8 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) struct cam_isp_in_port_generic_info *gen_port_info = NULL; uint32_t num_pix_port_per_in = 0; uint32_t num_rdi_port_per_in = 0; + uint32_t num_pd_port_per_in = 0; + uint32_t total_pd_port = 0; uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; uint32_t in_port_length = 0; @@ -3156,12 +3188,13 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, gen_port_info, &num_pix_port_per_in, - &num_rdi_port_per_in, + &num_rdi_port_per_in, &num_pd_port_per_in, &acquire_args->acquired_hw_id[i], acquire_args->acquired_hw_path[i]); total_pix_port += num_pix_port_per_in; total_rdi_port += num_rdi_port_per_in; + total_pd_port += num_pd_port_per_in; kfree(in_port); if (gen_port_info != NULL) { @@ -3170,7 +3203,9 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) gen_port_info = NULL; } if (rc) { - CAM_ERR(CAM_ISP, "can not acquire resource"); + cam_ife_hw_mgr_print_acquire_info(ife_ctx, + total_pix_port, total_pd_port, + total_rdi_port, rc); goto free_res; } } else { @@ -3199,10 +3234,8 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->ctx_in_use = 1; ife_ctx->num_reg_dump_buf = 0; - CAM_INFO(CAM_ISP, - "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", - total_pix_port, total_rdi_port, - ife_ctx->is_dual, ife_ctx->ctx_index); + cam_ife_hw_mgr_print_acquire_info(ife_ctx, total_pix_port, + total_pd_port, total_rdi_port, rc); cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); @@ -4554,10 +4587,10 @@ static int cam_isp_blob_ubwc_update( &bytes_used); if (rc < 0) { CAM_ERR(CAM_ISP, - "Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%x", + "Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%X", blob_info->base_info->idx, bytes_used, - res_id_out); + ubwc_plane_cfg->port_type); goto end; } @@ -4727,10 +4760,10 @@ static int cam_isp_blob_ubwc_update_v2( &bytes_used); if (rc < 0) { CAM_ERR(CAM_ISP, - "Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%x", + "Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%X", blob_info->base_info->idx, bytes_used, - res_id_out); + ubwc_plane_cfg->port_type); goto end; } @@ -4828,8 +4861,9 @@ static int cam_isp_blob_hfr_update( &bytes_used); if (rc < 0) { CAM_ERR(CAM_ISP, - "Failed cmd_update, base_idx=%d, rc=%d", - blob_info->base_info->idx, bytes_used); + "Failed cmd_update, base_idx=%d, rc=%d, res_id_out:0x%X", + blob_info->base_info->idx, bytes_used, + port_hfr_config->resource_type); return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 15b01a35581f..282c458d1b25 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -196,8 +196,8 @@ int cam_isp_add_cmd_buf_update( uint32_t total_used_bytes = 0; if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) { - CAM_ERR(CAM_ISP, "io res id:%d not valid", - hw_mgr_res->res_type); + CAM_ERR(CAM_ISP, "VFE out resource:0x%X type:%d not valid", + hw_mgr_res->res_id, hw_mgr_res->res_type); return -EINVAL; } From 32eade687afb54c1ea0c79c8f607b88bb0689dfc Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Mon, 20 Jan 2020 14:37:51 -0800 Subject: [PATCH 285/790] msm: camera: isp: Config hardware in work queue Currently requests for offline IFE are applied from tasklet context or from an ioctl thread within a critical section protected by a spinlock. In both of these cases, preemtion is disabled but CDM requires mutex locks during this operation. Therefore a work queue is added in this change to handle apply request for offline IFE. CRs-Fixed: 2606911 Change-Id: Ie893a626bc274d026fb878f1f19830e990be6dc6 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 68 +++++++++++++++++---- drivers/cam_isp/cam_isp_context.h | 4 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 29 ++++++--- 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9e28d2eeb612..5843b6be1042 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1047,13 +1047,21 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( } static int __cam_isp_ctx_apply_req_offline( - struct cam_context *ctx, uint32_t next_state, - struct cam_isp_context *ctx_isp) + void *priv, void *data) { int rc = 0; - struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; - struct cam_hw_config_args cfg; + struct cam_context *ctx = NULL; + struct cam_isp_context *ctx_isp = priv; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_hw_config_args cfg; + + if (!ctx_isp) { + CAM_ERR(CAM_ISP, "Invalid ctx_isp:%pK", ctx); + rc = -EINVAL; + goto end; + } + ctx = ctx_isp->base; if (list_empty(&ctx->pending_req_list)) { CAM_DBG(CAM_ISP, "No pending requests to apply"); @@ -1067,8 +1075,10 @@ static int __cam_isp_ctx_apply_req_offline( if (ctx_isp->active_req_cnt >= 2) goto end; + spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); + spin_unlock_bh(&ctx->lock); CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u", req->request_id, ctx_isp->substate_activated, ctx->ctx_id); @@ -1087,13 +1097,21 @@ static int __cam_isp_ctx_apply_req_offline( if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); } else { + spin_lock_bh(&ctx->lock); + atomic_set(&ctx_isp->rxd_epoch, 0); - ctx_isp->substate_activated = next_state; + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_APPLIED; ctx_isp->last_applied_req_id = req->request_id; + list_del_init(&req->list); list_add_tail(&req->list, &ctx->wait_req_list); + + spin_unlock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld", - next_state, ctx_isp->last_applied_req_id); + CAM_ISP_CTX_ACTIVATED_APPLIED, + ctx_isp->last_applied_req_id); __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, @@ -1103,6 +1121,26 @@ end: return rc; } +static int __cam_isp_ctx_schedule_apply_req_offline( + struct cam_isp_context *ctx_isp) +{ + int rc = 0; + struct crm_workq_task *task; + + task = cam_req_mgr_workq_get_task(ctx_isp->workq); + if (!task) { + CAM_ERR(CAM_ISP, "No task for worker"); + return -ENOMEM; + } + + task->process_cb = __cam_isp_ctx_apply_req_offline; + rc = cam_req_mgr_workq_enqueue_task(task, ctx_isp, CRM_TASK_PRIORITY_0); + if (rc) + CAM_ERR(CAM_ISP, "Failed to schedule task rc:%d", rc); + + return rc; +} + static int __cam_isp_ctx_offline_epoch_in_activated_state( struct cam_isp_context *ctx_isp, void *evt_data) { @@ -1123,8 +1161,7 @@ static int __cam_isp_ctx_offline_epoch_in_activated_state( } } - __cam_isp_ctx_apply_req_offline(ctx, CAM_ISP_CTX_ACTIVATED_APPLIED, - ctx_isp); + __cam_isp_ctx_schedule_apply_req_offline(ctx_isp); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); @@ -3887,10 +3924,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req->request_id, ctx->ctx_id); if (ctx_isp->offline_context && atomic_read(&ctx_isp->rxd_epoch)) { - spin_lock_bh(&ctx->lock); - __cam_isp_ctx_apply_req_offline(ctx, - CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp); - spin_unlock_bh(&ctx->lock); + __cam_isp_ctx_schedule_apply_req_offline(ctx_isp); } return rc; @@ -4336,6 +4370,13 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, cam_isp_ctx_offline_state_machine_irq; ctx_isp->substate_machine = NULL; ctx_isp->offline_context = true; + + rc = cam_req_mgr_workq_create("offline_ife", 20, + &ctx_isp->workq, CRM_WORKQ_USAGE_IRQ, 0); + if (rc) + CAM_ERR(CAM_ISP, + "Failed to create workq for offline IFE rc:%d", + rc); } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = @@ -5252,6 +5293,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, atomic64_set(&ctx->event_record_head[i], -1); cam_isp_context_debug_register(); + err: return rc; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index beec13e3ff13..ba49f534e071 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -14,7 +14,7 @@ #include "cam_context.h" #include "cam_isp_hw_mgr_intf.h" - +#include "cam_req_mgr_workq.h" #define CAM_IFE_QTIMER_MUL_FACTOR 10000 #define CAM_IFE_QTIMER_DIV_FACTOR 192 @@ -257,6 +257,7 @@ struct cam_isp_context_event_record { * @isp_device_type: ISP device type * @rxd_epoch: Indicate whether epoch has been received. Used to * decide whether to apply request in offline ctx + * @workq: Worker thread for offline ife * */ struct cam_isp_context { @@ -298,6 +299,7 @@ struct cam_isp_context { unsigned int init_timestamp; uint32_t isp_device_type; atomic_t rxd_epoch; + struct cam_req_mgr_core_workq *workq; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 6434a4abe922..1e5154fb5c03 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -648,6 +648,11 @@ static void cam_ife_hw_mgr_print_acquire_info( hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_csid, struct cam_isp_hw_mgr_res, list); + + if (hw_mgr_ctx->is_offline) + hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_src, + struct cam_isp_hw_mgr_res, list); + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { hw_res = hw_mgr_res->hw_res[i]; if (hw_res && hw_res->hw_intf) @@ -2173,7 +2178,7 @@ static int cam_ife_hw_mgr_preprocess_port( return 0; } -static int cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd( +static int cam_ife_hw_mgr_acquire_res_ife_bus_rd( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port) { @@ -2385,7 +2390,7 @@ end: return rc; } -static int cam_ife_mgr_acquire_hw_for_fe_ctx( +static int cam_ife_mgr_acquire_hw_for_offline_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, uint32_t *num_pix_port, @@ -2417,7 +2422,7 @@ static int cam_ife_mgr_acquire_hw_for_fe_ctx( return -EINVAL; } - rc = cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(ife_ctx, in_port); + rc = cam_ife_hw_mgr_acquire_res_ife_bus_rd(ife_ctx, in_port); if (rc) { CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed"); @@ -2486,17 +2491,21 @@ static int cam_ife_mgr_acquire_hw_for_ctx( cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); - if (ife_rd_count) { - CAM_ERR(CAM_ISP, "Invalid BUS RD port for non-FE ctx"); - return -EINVAL; - } - if (!ipp_count && !rdi_count && !ppp_count && !lcr_count) { CAM_ERR(CAM_ISP, "No PIX or RDI or PPP or LCR resource"); return -EINVAL; } + if (ife_rd_count) { + rc = cam_ife_hw_mgr_acquire_res_ife_bus_rd(ife_ctx, in_port); + + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed"); + goto err; + } + } + if (ipp_count || lcr_count) { /* get ife csid IPP resource */ rc = cam_ife_hw_mgr_acquire_res_ife_csid_pxl(ife_ctx, @@ -2937,8 +2946,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto free_mem; } - if (ife_ctx->is_fe_enabled) - rc = cam_ife_mgr_acquire_hw_for_fe_ctx( + if (ife_ctx->is_offline) + rc = cam_ife_mgr_acquire_hw_for_offline_ctx( ife_ctx, in_port, &num_pix_port_per_in, &acquire_args->acquired_hw_id[i], From 0e57ffd0a0e65c4a770690e82e5de8c98f12b2fd Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 17 Feb 2020 00:49:22 -0800 Subject: [PATCH 286/790] msm: camera: isp: Avoid dereference for unavailable port in ife out During deinit, we are dereferencing resource data even for unavailable out resource. Avoid dereferencing NULL pointer during vfe deinit out resource. CRs-Fixed: 2584631 Change-Id: I8488ccf73f62c551fc9d6ce3d636b10d8b0c7b8c Signed-off-by: Mukund Madhusudan Atre --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index d6f66dffb6f5..ab84616885fd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2400,9 +2400,6 @@ static int cam_vfe_bus_ver3_deinit_vfe_out_resource( * This is not error. It can happen if the resource is * never supported in the HW. */ - CAM_DBG(CAM_ISP, "VFE:%d out_type:%d already deinitialized", - rsrc_data->common_data->core_index, - rsrc_data->out_type); return 0; } From c5539d1d13e588a68318342e3df02da54c478415 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 16 Feb 2020 23:20:02 -0800 Subject: [PATCH 287/790] msm: camera: smmu: Fix unbalanced mutex unlock in camera smmmu When smmu get handle is called, mutex unlock is called on a lock that was not acquired. Add mutex lock condition to balance it. Also, re-organize the conditions for handle types to be mutually exclusive. CRs-Fixed: 2584631 Change-Id: I057b8812c8f76e157503eb5c76aa1de174563f3a Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_smmu/cam_smmu_api.c | 63 ++++++++++++++++----------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 336c5c039ae0..3f86b8c5e3be 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -724,18 +724,39 @@ static int cam_smmu_attach_device(int idx) static int cam_smmu_create_add_handle_in_table(char *name, int *hdl) { - int i, j; + int i, j, rc = -EINVAL; int handle; - bool valid = false; /* create handle and add in the iommu hardware table */ for (i = 0; i < iommu_cb_set.cb_num; i++) { for (j = 0; j < iommu_cb_set.cb_info[i].num_shared_hdl; j++) { - if (!strcmp(iommu_cb_set.cb_info[i].name[j], name)) - valid = true; + if (strcmp(iommu_cb_set.cb_info[i].name[j], name)) + continue; - if (iommu_cb_set.cb_info[i].handle != HANDLE_INIT && - valid) { + if (iommu_cb_set.cb_info[i].handle == HANDLE_INIT) { + mutex_lock(&iommu_cb_set.cb_info[i].lock); + /* make sure handle is unique */ + do { + handle = + cam_smmu_create_iommu_handle(i); + } while (cam_smmu_check_handle_unique(handle)); + + /* put handle in the table */ + iommu_cb_set.cb_info[i].handle = handle; + iommu_cb_set.cb_info[i].cb_count = 0; + if (iommu_cb_set.cb_info[i].is_secure) + iommu_cb_set.cb_info[i].secure_count++; + + if (iommu_cb_set.cb_info[i].is_mul_client) + iommu_cb_set.cb_info[i].device_count++; + + *hdl = handle; + CAM_DBG(CAM_SMMU, "%s creates handle 0x%x", + name, handle); + mutex_unlock(&iommu_cb_set.cb_info[i].lock); + rc = 0; + goto end; + } else { mutex_lock(&iommu_cb_set.cb_info[i].lock); if (iommu_cb_set.cb_info[i].is_secure) { iommu_cb_set.cb_info[i].secure_count++; @@ -761,31 +782,8 @@ static int cam_smmu_create_add_handle_in_table(char *name, "Error: %s already got handle 0x%x", name, iommu_cb_set.cb_info[i].handle); mutex_unlock(&iommu_cb_set.cb_info[i].lock); - return -EALREADY; - } - - if (iommu_cb_set.cb_info[i].handle == HANDLE_INIT && - valid) { - /* make sure handle is unique */ - do { - handle = - cam_smmu_create_iommu_handle(i); - } while (cam_smmu_check_handle_unique(handle)); - - /* put handle in the table */ - iommu_cb_set.cb_info[i].handle = handle; - iommu_cb_set.cb_info[i].cb_count = 0; - if (iommu_cb_set.cb_info[i].is_secure) - iommu_cb_set.cb_info[i].secure_count++; - - if (iommu_cb_set.cb_info[i].is_mul_client) - iommu_cb_set.cb_info[i].device_count++; - - *hdl = handle; - CAM_DBG(CAM_SMMU, "%s creates handle 0x%x", - name, handle); - mutex_unlock(&iommu_cb_set.cb_info[i].lock); - return 0; + rc = -EALREADY; + goto end; } } } @@ -793,7 +791,8 @@ static int cam_smmu_create_add_handle_in_table(char *name, CAM_ERR(CAM_SMMU, "Error: Cannot find name %s or all handle exist", name); cam_smmu_print_table(); - return -EINVAL; +end: + return rc; } static int cam_smmu_init_scratch_map(struct scratch_mapping *scratch_map, From a16202752fff7eaaa21a367500fb2b826b89f1e2 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 21 Feb 2020 11:30:53 -0800 Subject: [PATCH 288/790] msm: camera: ife: Assign half the height value for cbcr plane This change adds a check for plane ID when updating write master height value in per frame blob. Plane C must be programmed with half the height. CRs-Fixed: 2626999 Change-Id: I44b4d69d9d330342c444bbe435c6a54ad9f3bd6f Signed-off-by: Venkat Chinta --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index d6f66dffb6f5..81ed5c0b40d5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3527,9 +3527,13 @@ static int cam_vfe_bus_ver3_update_wm_config( } wm_data->en_cfg = (wm_config->wm_mode << 16) | 0x1; - wm_data->height = wm_config->height; wm_data->width = wm_config->width; + if (i == PLANE_C) + wm_data->height = wm_config->height / 2; + else + wm_data->height = wm_config->height; + CAM_DBG(CAM_ISP, "WM:%d en_cfg:0x%X height:%d width:%d", wm_data->index, wm_data->en_cfg, wm_data->height, From 85aae7fa2c4bb7e76cd3d1db48483f7f3dc4b2e2 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 26 Feb 2020 16:51:56 -0800 Subject: [PATCH 289/790] msm: camera: fd: Add balanced dynamic allocation for free in init The work data passed as payload to workq is statically allocated, which has kfree call during destroy, this fails during component unbind. Change allocation of work data to dynamic in fd hw manager. CRs-Fixed: 2584631 Change-Id: I0cd2a152d39793ce620e9a9fc2950ee91cefe6bf Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 3 +++ drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index a293770542ec..f90ffc4eb7c4 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -2053,6 +2053,9 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, goto detach_smmu; } + g_fd_hw_mgr.work_data = kcalloc(CAM_FD_WORKQ_NUM_TASK, + sizeof(struct cam_fd_mgr_work_data), GFP_KERNEL); + for (i = 0; i < CAM_FD_WORKQ_NUM_TASK; i++) g_fd_hw_mgr.work->task.pool[i].payload = &g_fd_hw_mgr.work_data[i]; diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h index bbbc77bef6a3..61b3ae3b40a5 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h @@ -180,7 +180,7 @@ struct cam_fd_hw_mgr { struct cam_fd_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; struct cam_fd_mgr_frame_request frame_req[CAM_CTX_REQ_MAX]; struct cam_req_mgr_core_workq *work; - struct cam_fd_mgr_work_data work_data[CAM_FD_WORKQ_NUM_TASK]; + struct cam_fd_mgr_work_data *work_data; struct cam_fd_query_cap_cmd fd_caps; }; From ac6f8eeb6d70ab21bafbe36936508c6bc3433ced Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Fri, 7 Feb 2020 17:27:09 -0800 Subject: [PATCH 290/790] msm: camera: flash: Add qti flash support in camera Add support for qti flash along with updated max current DT property. Remove support for enable/disable regulator as it is no-op since a long time. CRs-Fixed: 2584631 Change-Id: I3305e7b6e4d6ef34d90d38f5f25cfa5b8b817f8b Signed-off-by: Mukund Madhusudan Atre --- drivers/Makefile | 7 + .../cam_flash/cam_flash_core.c | 148 ++++-------------- .../cam_flash/cam_flash_core.h | 4 +- .../cam_flash/cam_flash_dev.c | 8 +- .../cam_flash/cam_flash_dev.h | 10 +- .../cam_flash/cam_flash_soc.c | 22 ++- drivers/camera_main.c | 9 +- drivers/camera_main.h | 3 +- 8 files changed, 77 insertions(+), 134 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index 2ab203025f31..ed3cbb527506 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -168,6 +168,13 @@ camera-$(CONFIG_LEDS_QPNP_FLASH_V2) += \ cam_sensor_module/cam_flash/cam_flash_core.o \ cam_sensor_module/cam_flash/cam_flash_soc.o +ifneq (,$(filter $(CONFIG_LEDS_QTI_FLASH),y m)) +camera-y += \ + cam_sensor_module/cam_flash/cam_flash_dev.o \ + cam_sensor_module/cam_flash/cam_flash_core.o \ + cam_sensor_module/cam_flash/cam_flash_soc.o +endif + camera-$(CONFIG_SPECTRA_CUSTOM) += \ cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.o \ cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.o \ diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 2d8df8a0ac41..fa8943fc8e94 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -11,76 +11,35 @@ #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 cam_flash_led_prepare(struct led_trigger *trigger, int options, + int *max_current, bool is_wled) { 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 (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; + if (is_wled) { +#ifdef CONFIG_BACKLIGHT_QCOM_SPMI_WLED + rc = wled_flash_led_prepare(trigger, options, max_current); + if (rc) { + CAM_ERR(CAM_FLASH, "enable reg failed: rc: %d", + rc); + return rc; } +#else + return -EPERM; +#endif } else { - 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; +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) + rc = qpnp_flash_led_prepare(trigger, options, max_current); +#elif IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) + rc = qti_flash_led_prepare(trigger, options, max_current); +#endif + if (rc) { + CAM_ERR(CAM_FLASH, + "Regulator enable failed rc = %d", rc); + return rc; } } + return rc; } @@ -180,39 +139,6 @@ free_power_settings: return rc; } -int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl, - bool regulator_enable) -{ - int rc = 0; - - if (!(fctrl->switch_trigger)) { - CAM_ERR(CAM_FLASH, "Invalid argument"); - return -EINVAL; - } - - if (regulator_enable) { - rc = cam_flash_prepare(fctrl, true); - if (rc) { - CAM_ERR(CAM_FLASH, - "Enable Regulator Failed rc = %d", rc); - return rc; - } - fctrl->last_flush_req = 0; - } - - if (!regulator_enable) { - if ((fctrl->flash_state == CAM_FLASH_STATE_START) && - (fctrl->is_regulator_enabled == true)) { - rc = cam_flash_prepare(fctrl, false); - if (rc) - CAM_ERR(CAM_FLASH, - "Disable Regulator Failed rc: %d", rc); - } - } - - return rc; -} - int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl, bool regulator_enable) { @@ -1366,13 +1292,6 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) fctrl->nrt_info.cmn_attr.cmd_type = CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO; - rc = fctrl->func_tbl.power_ops(fctrl, true); - if (rc) { - CAM_ERR(CAM_FLASH, - "Enable Regulator Failed rc = %d", rc); - return rc; - } - fctrl->flash_state = CAM_FLASH_STATE_CONFIG; break; @@ -1599,16 +1518,9 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) flash_query_info = (struct cam_flash_query_curr *)cmd_buf; - 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); + rc = cam_flash_led_prepare(fctrl->switch_trigger, + QUERY_MAX_AVAIL_CURRENT, &query_curr_ma, + soc_private->is_wled_flash); CAM_DBG(CAM_FLASH, "query_curr_ma = %d", query_curr_ma); @@ -1784,10 +1696,12 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || (fctrl->flash_state == CAM_FLASH_STATE_START)) { fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); - rc = fctrl->func_tbl.power_ops(fctrl, false); - if (rc) - CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", - rc); + if (fctrl->func_tbl.power_ops) { + rc = fctrl->func_tbl.power_ops(fctrl, false); + if (rc) + CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", + rc); + } } rc = cam_flash_release_dev(fctrl); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/cam_sensor_module/cam_flash/cam_flash_core.h index c382809dbb92..f4e451c1efd8 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FLASH_CORE_H_ @@ -14,6 +14,8 @@ 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); +int cam_flash_led_prepare(struct led_trigger *trigger, int options, + int *max_current, bool is_wled); #endif /*_CAM_FLASH_CORE_H_*/ diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 6b872be656af..320caa6d9cfe 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -120,8 +120,10 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, CAM_WARN(CAM_FLASH, "Failed in destroying the device Handle"); - if (fctrl->func_tbl.power_ops(fctrl, false)) - CAM_WARN(CAM_FLASH, "Power Down Failed"); + if (fctrl->func_tbl.power_ops) { + if (fctrl->func_tbl.power_ops(fctrl, false)) + CAM_WARN(CAM_FLASH, "Power Down Failed"); + } fctrl->flash_state = CAM_FLASH_STATE_INIT; break; @@ -461,7 +463,7 @@ static int cam_flash_component_bind(struct device *dev, /* PMIC Flash */ fctrl->func_tbl.parser = cam_flash_pmic_pkt_parser; fctrl->func_tbl.apply_setting = cam_flash_pmic_apply_setting; - fctrl->func_tbl.power_ops = cam_flash_pmic_power_ops; + fctrl->func_tbl.power_ops = NULL; fctrl->func_tbl.flush_req = cam_flash_pmic_flush_request; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 59911a5fb3a8..64bb25308d41 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FLASH_DEV_H_ @@ -13,12 +13,18 @@ #include #include #include -#include #include #include #include #include #include + +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +#include +#elif IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) +#include +#endif + #include "cam_req_mgr_util.h" #include "cam_req_mgr_interface.h" #include "cam_subdev.h" diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 762977f4b968..dc56aebfe739 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -78,10 +78,11 @@ static int32_t cam_get_source_node_info( &fctrl->flash_trigger[i]); if (soc_private->is_wled_flash) { - rc = wled_flash_led_prepare( + rc = cam_flash_led_prepare( fctrl->flash_trigger[i], - QUERY_MAX_CURRENT, - &soc_private->flash_max_current[i]); + QUERY_MAX_AVAIL_CURRENT, + &soc_private->flash_max_current[i], + true); if (rc) { CAM_ERR(CAM_FLASH, "WLED FLASH max_current read fail: %d", @@ -94,6 +95,9 @@ static int32_t cam_get_source_node_info( rc = of_property_read_u32(flash_src_node, "qcom,max-current", &soc_private->flash_max_current[i]); + rc &= of_property_read_u32(flash_src_node, + "qcom,max-current-ma", + &soc_private->flash_max_current[i]); if (rc < 0) { CAM_WARN(CAM_FLASH, "LED FLASH max-current read fail: %d", @@ -165,10 +169,11 @@ static int32_t cam_get_source_node_info( &fctrl->torch_trigger[i]); if (soc_private->is_wled_flash) { - rc = wled_flash_led_prepare( + rc = cam_flash_led_prepare( fctrl->torch_trigger[i], - QUERY_MAX_CURRENT, - &soc_private->torch_max_current[i]); + QUERY_MAX_AVAIL_CURRENT, + &soc_private->torch_max_current[i], + true); if (rc) { CAM_ERR(CAM_FLASH, "WLED TORCH max_current read fail: %d", @@ -180,6 +185,9 @@ static int32_t cam_get_source_node_info( rc = of_property_read_u32(torch_src_node, "qcom,max-current", &soc_private->torch_max_current[i]); + rc &= of_property_read_u32(torch_src_node, + "qcom,max-current-ma", + &soc_private->torch_max_current[i]); if (rc < 0) { CAM_WARN(CAM_FLASH, "LED-TORCH max-current read failed: %d", diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 35bd853f4412..6583c922a115 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -23,7 +23,8 @@ #include "cam_eeprom_dev.h" #include "cam_ois_dev.h" -#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ + IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) #include "cam_flash_dev.h" #endif @@ -102,7 +103,8 @@ static const struct camera_submodule_component camera_sensor[] = { {&cam_sensor_driver_init, &cam_sensor_driver_exit}, {&cam_eeprom_driver_init, &cam_eeprom_driver_exit}, {&cam_ois_driver_init, &cam_ois_driver_exit}, -#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ + IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) {&cam_flash_init_module, &cam_flash_exit_module}, #endif #endif @@ -238,7 +240,8 @@ static struct platform_driver *const cam_component_drivers[] = { &cam_sensor_platform_driver, &cam_eeprom_platform_driver, &cam_ois_platform_driver, -#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ + IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) &cam_flash_platform_driver, #endif #endif diff --git a/drivers/camera_main.h b/drivers/camera_main.h index 3de446d08b7c..af832ee60f10 100644 --- a/drivers/camera_main.h +++ b/drivers/camera_main.h @@ -34,7 +34,8 @@ extern struct platform_driver cam_actuator_platform_driver; extern struct platform_driver cam_sensor_platform_driver; extern struct platform_driver cam_eeprom_platform_driver; extern struct platform_driver cam_ois_platform_driver; -#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ + IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) extern struct platform_driver cam_flash_platform_driver; #endif #endif From 88406b50a83b7a45917913c946a5c0961dfc110f Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 26 Feb 2020 19:00:01 -0800 Subject: [PATCH 291/790] msm: camera: ife: Save dual IFE flag This change saves the dual IFE flag during CAMIF acquire. This line was misplaced during rebase of commit 8e79606ada4d ("msm: camera: isp: Add support for offline IFE"). CRs-Fixed: 2630545 Change-Id: I321898aa6550b15240ca4308b1ceda1fbad14963 Signed-off-by: Venkat Chinta --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index ca0cf15ba200..a8533c11f60a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -259,18 +259,21 @@ int cam_vfe_camif_ver3_acquire_resource( camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; camif_data->is_fe_enabled = acquire_data->vfe_in.is_fe_enabled; camif_data->is_offline = acquire_data->vfe_in.is_offline; + camif_data->is_dual = acquire_data->vfe_in.is_dual; camif_data->event_cb = acquire_data->event_cb; camif_data->priv = acquire_data->priv; camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin; camif_data->horizontal_bin = acquire_data->vfe_in.in_port->horizontal_bin; - if (acquire_data->vfe_in.is_dual) + if (camif_data->is_dual) camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx; - CAM_DBG(CAM_ISP, "VFE:%d CAMIF pix_pattern:%d dsp_mode=%d", + CAM_DBG(CAM_ISP, + "VFE:%d CAMIF pix_pattern:%d dsp_mode=%d is_dual:%d dual_hw_idx:%d", camif_res->hw_intf->hw_idx, - camif_data->pix_pattern, camif_data->dsp_mode); + camif_data->pix_pattern, camif_data->dsp_mode, + camif_data->is_dual, camif_data->dual_hw_idx); return rc; } From fce521db947e7de29a636b87d7f452098eb6e8f2 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 23 Jan 2020 18:18:16 -0800 Subject: [PATCH 292/790] msm: camera: cci: Add hardware index in dumps This change adds hardware index to register dump. CRs-Fixed: 2632034 Change-Id: Ibdd96d4f9f7a99c71118950fc0ee0b8aec9a7340 Signed-off-by: Venkat Chinta --- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 4a2a643a7408..6efa77a8d55d 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -192,6 +192,9 @@ static void cam_cci_dump_registers(struct cci_device *cci_dev, uint32_t reg_offset = 0; void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base; + CAM_INFO(CAM_CCI, "**** CCI:%d register dump ****", + cci_dev->soc_info->index); + /* CCI Top Registers */ CAM_INFO(CAM_CCI, "****CCI TOP Registers ****"); for (i = 0; i < DEBUG_TOP_REG_COUNT; i++) { @@ -205,6 +208,9 @@ static void cam_cci_dump_registers(struct cci_device *cci_dev, CAM_INFO(CAM_CCI, "****CCI MASTER %d Registers ****", master); for (i = 0; i < DEBUG_MASTER_REG_COUNT; i++) { + if ((i * 4) == 0x18) + continue; + reg_offset = DEBUG_MASTER_REG_START + master*0x100 + i * 4; read_val = cam_io_r_mb(base + reg_offset); CAM_INFO(CAM_CCI, "offset = 0x%X value = 0x%X", From 4682501c822adbe94d2782ce05ecc1e7824427c4 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 28 Feb 2020 14:43:03 -0800 Subject: [PATCH 293/790] msm: camera: ife: Add check for DSP enabled in acquire This change adds a check if DSP is enabled to ensure lower index IFE cores are acquired since only they support DSP mode. CRs-Fixed: 2632139 Change-Id: Ib1be26be9d5afd83f565ddf5adb989ef463d8b8d Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index e9d69122b080..556c24784b63 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1629,7 +1629,8 @@ static int cam_ife_mgr_acquire_cid_res( /* Acquire Left if not already acquired */ /* For dual IFE cases, start acquiring the lower idx first */ - if (ife_ctx->is_fe_enabled || in_port->usage_type) + if (ife_ctx->is_fe_enabled || in_port->usage_type || + ife_ctx->dsp_enabled) rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr, &csid_acquire, true); else From c5086bcea344a52c00b9790c75d6eda7dacd40ba Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 28 Feb 2020 15:22:13 -0800 Subject: [PATCH 294/790] msm: camera: csid: Rename TPG vd/dt macros CSID TPG and PHY TPG require different values for VC/DT. This change renames the macros to more distinct identifiers and assigns the appropriate values based on input TPG type. CRs-Fixed: 2632165 Change-Id: I136eb88a7cec338898cab8537cb080a0f26c2f77 Signed-off-by: Venkat Chinta --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 07ea4a8154cf..84c9b1702d88 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -26,8 +26,8 @@ #define CAM_IFE_CSID_TPG_DT_VAL 0x2B /* CSIPHY TPG VC/DT values */ -#define CAM_IFE_CSI_TPG_VC_VAL 0x0 -#define CAM_IFE_CSI_TPG_DT_VAL 0x2B +#define CAM_IFE_CPHY_TPG_VC_VAL 0x0 +#define CAM_IFE_CPHY_TPG_DT_VAL 0x2B /* Timeout values in usec */ #define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000 @@ -1142,10 +1142,12 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->crop_enable); if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || - (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || - (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG)) { - path_data->dt = CAM_IFE_CSI_TPG_DT_VAL; - path_data->vc = CAM_IFE_CSI_TPG_VC_VAL; + (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) { + path_data->dt = CAM_IFE_CPHY_TPG_DT_VAL; + path_data->vc = CAM_IFE_CPHY_TPG_VC_VAL; + } else if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { + path_data->dt = CAM_IFE_CSID_TPG_DT_VAL; + path_data->vc = CAM_IFE_CSID_TPG_VC_VAL; } else { path_data->dt = reserve->in_port->dt[0]; path_data->vc = reserve->in_port->vc[0]; From 3ba88cc32fa704b7cf30bc3c83e02664eef55f1a Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 27 Feb 2020 15:46:37 -0800 Subject: [PATCH 295/790] msm: camera: sensor: Update maximum supported camera id Updates maximum number of supported camera id to 9 CRs-Fixed: 2584631 Change-Id: I00a595d784b38030a7996a8da930ecdeaf05835c Signed-off-by: Karthik Jayakumar --- .../cam_sensor_utils/cam_sensor_cmn_header.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index bd0cb25c88a2..09d100c8f0a8 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_CMN_HEADER_ @@ -338,6 +338,9 @@ enum msm_sensor_camera_id_t { CAMERA_4, CAMERA_5, CAMERA_6, + CAMERA_7, + CAMERA_8, + CAMERA_9, MAX_CAMERAS, }; From 0a649b30634a396bd74462414877cbe6d564c1dd Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 17 Feb 2020 00:29:44 -0800 Subject: [PATCH 296/790] msm: camera: common: Fix failures in v4l2 unregister during error Missing video unregister was causing list delete corruption. Also, there were double free errors in Sync and CRM driver. Fix v4l2 issues by adding the missing unregister calls and changing release callback to empty, because we are freeing it during cleanup. Improve logging during bind/unbind to better reflect what is happening. CRs-Fixed: 2584631 Change-Id: Idc5db655d22df54e8bdb470d29896e10f6987796 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_icp/cam_icp_subdev.c | 2 +- drivers/cam_isp/cam_isp_dev.c | 2 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 103 +++++++++++++----- drivers/cam_req_mgr/cam_req_mgr_dev.h | 2 + drivers/cam_req_mgr/cam_subdev.h | 2 - .../cam_sensor_module/cam_cci/cam_cci_dev.c | 5 + .../cam_eeprom/cam_eeprom_dev.c | 2 +- .../cam_sensor/cam_sensor_dev.c | 2 +- drivers/cam_sync/cam_sync.c | 4 +- drivers/camera_main.c | 4 +- 10 files changed, 89 insertions(+), 39 deletions(-) diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index d4c7e025afbd..801c88591436 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -205,7 +205,7 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.open_cnt = 0; mutex_init(&g_icp_dev.icp_lock); - CAM_DBG(CAM_ICP, "Component bound successfully"); + CAM_INFO(CAM_ICP, "Component bound successfully"); return rc; diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index f5bbf89d292b..322ee3d85449 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -161,7 +161,7 @@ static int cam_isp_dev_component_bind(struct device *dev, mutex_init(&g_isp_dev.isp_mutex); - CAM_INFO(CAM_ISP, "ISP HW component bound successfully"); + CAM_INFO(CAM_ISP, "Component bound successfully"); return 0; unregister: diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 0ac8178b47f8..038d3c28e49f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -62,8 +62,8 @@ mdev_fail: static void cam_media_device_cleanup(void) { - media_entity_cleanup(&g_dev.video->entity); media_device_unregister(g_dev.v4l2_dev->mdev); + media_device_cleanup(g_dev.v4l2_dev->mdev); kfree(g_dev.v4l2_dev->mdev); g_dev.v4l2_dev->mdev = NULL; } @@ -575,7 +575,7 @@ static int cam_video_device_setup(void) strlcpy(g_dev.video->name, "cam-req-mgr", sizeof(g_dev.video->name)); - g_dev.video->release = video_device_release; + g_dev.video->release = video_device_release_empty; g_dev.video->fops = &g_cam_fops; g_dev.video->ioctl_ops = &g_cam_ioctl_ops; g_dev.video->minor = -1; @@ -630,6 +630,7 @@ EXPORT_SYMBOL(cam_req_mgr_notify_message); void cam_video_device_cleanup(void) { + media_entity_cleanup(&g_dev.video->entity); video_unregister_device(g_dev.video); video_device_release(g_dev.video); g_dev.video = NULL; @@ -640,7 +641,7 @@ int cam_register_subdev(struct cam_subdev *csd) struct v4l2_subdev *sd; int rc; - if (g_dev.state != true) { + if (!g_dev.state) { CAM_ERR(CAM_CRM, "camera root device not ready yet"); return -ENODEV; } @@ -651,6 +652,15 @@ int cam_register_subdev(struct cam_subdev *csd) } mutex_lock(&g_dev.dev_lock); + if ((g_dev.subdev_nodes_created) && + (csd->sd_flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) { + CAM_ERR(CAM_CRM, + "dynamic node is not allowed, name: %s, type :%d", + csd->name, csd->ent_function); + rc = -EINVAL; + goto reg_fail; + } + sd = &csd->sd; v4l2_subdev_init(sd, csd->ops); sd->internal_ops = csd->internal_ops; @@ -662,34 +672,12 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; - if (csd->subdev_node_created) { - CAM_ERR(CAM_CRM, - "Dynamic Node is not allowed, name: %s, type: %d", - csd->name, csd->ent_function); - rc = -EINVAL; - goto reg_fail; - } - rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); goto reg_fail; } - rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); - if (rc) { - CAM_ERR(CAM_CRM, - "Device Register subdev node failed: rc = %d", rc); - goto reg_fail; - - } - - if ((sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) { - sd->entity.name = video_device_node_name(sd->devnode); - CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); - } - - csd->subdev_node_created = true; g_dev.count++; reg_fail: @@ -700,7 +688,7 @@ EXPORT_SYMBOL(cam_register_subdev); int cam_unregister_subdev(struct cam_subdev *csd) { - if (g_dev.state != true) { + if (!g_dev.state) { CAM_ERR(CAM_CRM, "camera root device not ready yet"); return -ENODEV; } @@ -714,6 +702,47 @@ int cam_unregister_subdev(struct cam_subdev *csd) } EXPORT_SYMBOL(cam_unregister_subdev); +static int cam_dev_mgr_create_subdev_nodes(void) +{ + int rc; + struct v4l2_subdev *sd; + + if (!g_dev.v4l2_dev) { + CAM_ERR(CAM_CRM, "V4L2 device not initialized"); + return -EINVAL; + } + + if (!g_dev.state) { + CAM_ERR(CAM_CRM, "camera root device not ready"); + return -ENODEV; + } + + mutex_lock(&g_dev.dev_lock); + if (g_dev.subdev_nodes_created) { + rc = -EEXIST; + goto create_fail; + } + + rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); + if (rc) { + CAM_ERR(CAM_CRM, "failed to register the sub devices"); + goto create_fail; + } + + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) + continue; + sd->entity.name = video_device_node_name(sd->devnode); + CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); + } + + g_dev.subdev_nodes_created = true; + +create_fail: + mutex_unlock(&g_dev.dev_lock); + return rc; +} + static int cam_req_mgr_component_master_bind(struct device *dev) { int rc = 0; @@ -734,6 +763,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) g_dev.open_cnt = 0; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); + g_dev.subdev_nodes_created = false; mutex_init(&g_dev.dev_lock); rc = cam_req_mgr_util_init(); @@ -748,6 +778,8 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto req_mgr_core_fail; } + g_dev.state = true; + if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", sizeof(struct cam_req_mgr_timer), 64, @@ -761,19 +793,28 @@ static int cam_req_mgr_component_master_bind(struct device *dev) g_cam_req_mgr_timer_cachep->name); } - g_dev.state = true; - - CAM_DBG(CAM_CRM, "Binding all slave components"); + CAM_INFO(CAM_CRM, "All probes done, binding slave components"); rc = component_bind_all(dev, NULL); if (rc) { CAM_ERR(CAM_CRM, "Error in binding all components rc: %d, Camera initialization failed!", rc); - goto req_mgr_core_fail; + goto req_mgr_device_deinit; } + rc = cam_dev_mgr_create_subdev_nodes(); + if (rc) { + CAM_ERR(CAM_CRM, "failed in creating devices for subdevs %d", + rc); + goto req_mgr_device_deinit; + } + + CAM_INFO(CAM_CRM, "All camera components bound successfully"); + return rc; +req_mgr_device_deinit: + cam_req_mgr_core_device_deinit(); req_mgr_core_fail: cam_req_mgr_util_deinit(); req_mgr_util_fail: @@ -784,6 +825,7 @@ video_setup_fail: cam_media_device_cleanup(); media_setup_fail: cam_v4l2_device_cleanup(); + g_dev.state = false; return rc; } @@ -800,6 +842,7 @@ static void cam_req_mgr_component_master_unbind(struct device *dev) cam_v4l2_device_cleanup(); mutex_destroy(&g_dev.dev_lock); g_dev.state = false; + g_dev.subdev_nodes_created = false; } static const struct component_master_ops cam_req_mgr_component_master_ops = { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 464720efb0a2..9b241e6f0a46 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -12,6 +12,7 @@ * * @video: pointer to struct video device. * @v4l2_dev: pointer to struct v4l2 device. + * @subdev_nodes_created: all subdev nodes are created for this device * @count: number of subdevices registered. * @dev_lock: lock for the subdevice count. * @state: state of the root device. @@ -23,6 +24,7 @@ struct cam_req_mgr_device { struct video_device *video; struct v4l2_device *v4l2_dev; + bool subdev_nodes_created; int count; struct mutex dev_lock; bool state; diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index 08d02a1b0fab..1b2d146fa2fe 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -34,7 +34,6 @@ * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. - * @subdev_node_created: Enabled sub-device * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be @@ -50,7 +49,6 @@ struct cam_subdev { u32 sd_flags; void *token; u32 ent_function; - bool subdev_node_created; }; /** diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index cd937016298c..804bee34c2df 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -452,6 +452,7 @@ cci_no_resource: static void cam_cci_component_unbind(struct device *dev, struct device *master_dev, void *data) { + int rc = 0; struct platform_device *pdev = to_platform_device(dev); struct v4l2_subdev *subdev = platform_get_drvdata(pdev); @@ -460,6 +461,10 @@ static void cam_cci_component_unbind(struct device *dev, cam_cpas_unregister_client(cci_dev->cpas_handle); cam_cci_soc_remove(pdev, cci_dev); + rc = cam_unregister_subdev(&(cci_dev->v4l2_dev_str)); + if (rc < 0) + CAM_ERR(CAM_CCI, "Fail with cam_unregister_subdev"); + devm_kfree(&pdev->dev, cci_dev); } diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index a0d4b5a45f30..486632399e60 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -498,7 +498,7 @@ static void cam_eeprom_component_unbind(struct device *dev, return; } - CAM_INFO(CAM_EEPROM, "Platform driver remove invoked"); + CAM_DBG(CAM_EEPROM, "Component unbind called for: %s", pdev->name); soc_info = &e_ctrl->soc_info; for (i = 0; i < soc_info->num_clk; i++) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 564cae097934..9d85f3f9c10f 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -295,7 +295,7 @@ static void cam_sensor_component_unbind(struct device *dev, return; } - CAM_INFO(CAM_SENSOR, "platform remove invoked"); + CAM_DBG(CAM_SENSOR, "Component unbind called for: %s", pdev->name); mutex_lock(&(s_ctrl->cam_sensor_mutex)); cam_sensor_shutdown(s_ctrl); mutex_unlock(&(s_ctrl->cam_sensor_mutex)); diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index d5529c2055e9..8f7d9d838970 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1052,7 +1052,7 @@ static int cam_sync_component_bind(struct device *dev, strlcpy(sync_dev->vdev->name, CAM_SYNC_NAME, sizeof(sync_dev->vdev->name)); - sync_dev->vdev->release = video_device_release; + sync_dev->vdev->release = video_device_release_empty; sync_dev->vdev->fops = &cam_sync_v4l2_fops; sync_dev->vdev->ioctl_ops = &g_cam_sync_ioctl_ops; sync_dev->vdev->minor = -1; @@ -1102,6 +1102,7 @@ v4l2_fail: register_fail: cam_sync_media_controller_cleanup(sync_dev); mcinit_fail: + video_unregister_device(sync_dev->vdev); video_device_release(sync_dev->vdev); vdev_fail: mutex_destroy(&sync_dev->table_lock); @@ -1116,6 +1117,7 @@ static void cam_sync_component_unbind(struct device *dev, v4l2_device_unregister(sync_dev->vdev->v4l2_dev); cam_sync_media_controller_cleanup(sync_dev); + video_unregister_device(sync_dev->vdev); video_device_release(sync_dev->vdev); debugfs_remove_recursive(sync_dev->dentry); sync_dev->dentry = NULL; diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 35bd853f4412..f90aa0652c59 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -86,7 +86,7 @@ static const struct camera_submodule_component camera_isp[] = { }; static const struct camera_submodule_component camera_tfe[] = { -#if IS_ENABLED(CONFIG_SPECTRA_TFE) +#ifdef CONFIG_SPECTRA_TFE {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, {&cam_tfe_init_module, &cam_tfe_exit_module}, {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, @@ -381,7 +381,7 @@ static int camera_init(void) } } - CAM_INFO(CAM_UTIL, "Spectra camera driver initialized!"); + CAM_INFO(CAM_UTIL, "Spectra camera driver initcalls done"); end_init: return rc; From a6a80b5c2b806d73bb01b1a3d4c16bf17d513808 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 27 Feb 2020 15:30:46 -0800 Subject: [PATCH 297/790] msm: camera: sensor: Update I2C read/write size Update I2C read and write capability to 10kb. CRs-Fixed: 2584631 Change-Id: Iffffb18ad79a5492df2ca0aa0f1411ae67cb92cc Signed-off-by: Karthik Jayakumar --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 4 ++-- drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h | 4 ++-- drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index c8d424f9afaa..5ac6441df53a 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -58,8 +58,8 @@ /* Max bytes that can be read per CCI read transaction */ #define CCI_READ_MAX 256 #define CCI_I2C_READ_MAX_RETRIES 3 -#define CCI_I2C_MAX_READ 8192 -#define CCI_I2C_MAX_WRITE 8192 +#define CCI_I2C_MAX_READ 10240 +#define CCI_I2C_MAX_WRITE 10240 #define CCI_I2C_MAX_BYTE_COUNT 65535 #define CAMX_CCI_DEV_NAME "cam-cci-driver" diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h index def8be55bc8b..e37314a46571 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_I2C_H_ @@ -18,7 +18,7 @@ #define I2C_COMPARE_MATCH 0 #define I2C_COMPARE_MISMATCH 1 -#define I2C_REG_DATA_MAX (8*1024) +#define I2C_REG_DATA_MAX (10*1024) /** * @client: CCI client structure diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c index a9fd0881aabf..38af4f74bedb 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c @@ -1,13 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_sensor_cmn_header.h" #include "cam_sensor_i2c.h" #include "cam_sensor_io.h" -#define I2C_REG_DATA_MAX (8*1024) #define I2C_REG_MAX_BUF_SIZE 8 static int32_t cam_qup_i2c_rxdata( From 5619d4e93e494efe57361e433d0cc3a6ea647f5c Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Thu, 19 Dec 2019 15:46:17 -0800 Subject: [PATCH 298/790] msm: camera: ife: Unmask top level bus write IRQ bit During VFE reset we mask all bits apart from reset done. Since the top level bus write IRQ bit is common to all output ports it is set during the initialize hardware sequence. However since initialize hardware is not invoked in start only case that follows flush, we must set it again. CRs-Fixed: 2590331 Change-Id: I73f09e552779bd65f472178c1025594be03025fb Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 42 ++++++++++++++++++- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 2 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 2 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 2 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 2 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 1 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 13 +++++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 5 ++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 12 +++++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 3 +- 13 files changed, 82 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 556c24784b63..69713cc8fd6a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4005,6 +4005,36 @@ static int cam_ife_mgr_reset_vfe_hw(struct cam_ife_hw_mgr *hw_mgr, return 0; } +static int cam_ife_mgr_unmask_bus_wr_irq(struct cam_ife_hw_mgr *hw_mgr, + uint32_t hw_idx) +{ + uint32_t i = 0, dummy_args = 0; + struct cam_hw_intf *vfe_hw_intf; + + if (!hw_mgr) { + CAM_DBG(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) { + if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + continue; + + CAM_DBG(CAM_ISP, "Unmask VFE:%d BUS_WR IRQ", hw_idx); + + vfe_hw_intf = hw_mgr->ife_devices[i]; + + vfe_hw_intf->hw_ops.process_cmd(vfe_hw_intf->hw_priv, + CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, + &dummy_args, + sizeof(dummy_args)); + + break; + } + + return 0; +} + static int cam_ife_mgr_restart_hw(void *start_hw_args) { int rc = -1; @@ -4124,8 +4154,18 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) cam_tasklet_start(ctx->common.tasklet_info); - if (ctx->init_done && start_isp->start_only) + if (ctx->init_done && start_isp->start_only) { + /* Unmask BUS_WR bit in VFE top */ + for (i = 0; i < ctx->num_base; i++) { + rc = cam_ife_mgr_unmask_bus_wr_irq(hw_mgr_priv, + ctx->base[i].idx); + if (rc) + CAM_ERR(CAM_ISP, + "Failed to unmask VFE:%d BUS_WR IRQ rc:%d", + ctx->base[i].idx, rc); + } goto start_only; + } /* set current csid debug information to CSID HW */ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 2f00b1476986..b55af3ec2ef0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -115,6 +115,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, CAM_ISP_HW_CMD_DUMP_HW, CAM_ISP_HW_CMD_FE_TRIGGER_CMD, + CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 7281e98ba94c..13e3263ff26b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -608,6 +608,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: case CAM_ISP_HW_CMD_GET_SECURE_MODE: + case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index 63df625221cc..07d821871b5e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -265,6 +265,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { .addr_sync_no_sync = 0x00002084, .debug_status_cfg = 0x0000226C, .debug_status_0 = 0x00002270, + .top_irq_mask_0 = 0x0000005C, }, .num_client = 20, .bus_client_reg = { @@ -849,6 +850,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { .max_height = -1, }, }, + .top_irq_shift = 9, }; struct cam_vfe_hw_info cam_vfe170_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index 4e9a1e232860..ccc771c993c2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -331,6 +331,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { .addr_sync_no_sync = 0x00002084, .debug_status_cfg = 0x0000226C, .debug_status_0 = 0x00002270, + .top_irq_mask_0 = 0x0000005C, }, .num_client = 24, .bus_client_reg = { @@ -1019,6 +1020,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { .max_height = 1080, }, }, + .top_irq_shift = 9, }; struct cam_vfe_hw_info cam_vfe175_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 946ac2267d95..7573407af078 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -433,6 +433,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { .addr_sync_no_sync = 0x00002084, .debug_status_cfg = 0x0000226C, .debug_status_0 = 0x00002270, + .top_irq_mask_0 = 0x0000005C, }, .num_client = 24, .bus_client_reg = { @@ -1125,6 +1126,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { .max_height = 1080, }, }, + .top_irq_shift = 9, }; struct cam_vfe_hw_info cam_vfe175_130_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 18a0071bf0b0..359c43ae0c6f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -404,6 +404,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .debug_status_top_cfg = 0x0000AAD4, .debug_status_top = 0x0000AAD8, .test_bus_ctrl = 0x0000AADC, + .top_irq_mask_0 = 0x0000003C, .irq_reg_info = { .num_registers = 2, .irq_reg_set = vfe480_bus_irq_reg, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index aab38c791637..be6d1ada950d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -153,6 +153,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe17x_bus_hw_info = { .addr_sync_cfg = 0x0000207C, .addr_sync_frame_hdr = 0x00002080, .addr_sync_no_sync = 0x00002084, + .top_irq_mask_0 = 0x0000005C, }, .num_client = 4, .bus_client_reg = { @@ -322,6 +323,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe17x_bus_hw_info = { .max_height = -1, }, }, + .top_irq_shift = 9, }; static struct cam_vfe_hw_info cam_vfe_lite17x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index c19ade50bec9..09da6810fd4b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -239,6 +239,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .debug_status_top_cfg = 0x00001AD4, .debug_status_top = 0x00001AD8, .test_bus_ctrl = 0x00001ADC, + .top_irq_mask_0 = 0x00000028, .irq_reg_info = { .num_registers = 2, .irq_reg_set = vfe48x_bus_irq_reg, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 401b49b6f073..aeb154482d17 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -183,6 +183,7 @@ struct cam_vfe_bus_ver2_priv { struct cam_vfe_bus_ver2_common_data common_data; uint32_t num_client; uint32_t num_out; + uint32_t top_irq_shift; struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS]; struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX]; @@ -3424,7 +3425,7 @@ static int cam_vfe_bus_init_hw(void *hw_priv, if (bus_priv->common_data.hw_init) return 0; - top_irq_reg_mask[0] = (1 << 9); + top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift); bus_priv->irq_handle = cam_irq_controller_subscribe_irq( bus_priv->common_data.vfe_irq_controller, @@ -3539,6 +3540,7 @@ static int cam_vfe_bus_process_cmd( { int rc = -EINVAL; struct cam_vfe_bus_ver2_priv *bus_priv; + uint32_t top_mask_0 = 0; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3574,6 +3576,14 @@ static int cam_vfe_bus_process_cmd( case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: rc = cam_vfe_bus_update_ubwc_config_v2(cmd_args); break; + case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + top_mask_0 = cam_io_r_mb(bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->top_irq_mask_0); + top_mask_0 |= (1 << bus_priv->top_irq_shift); + cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->top_irq_mask_0); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3624,6 +3634,7 @@ int cam_vfe_bus_ver2_init( bus_priv->num_client = ver2_hw_info->num_client; bus_priv->num_out = ver2_hw_info->num_out; + bus_priv->top_irq_shift = ver2_hw_info->top_irq_shift; 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; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index fc1608315330..e611113bedd2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_BUS_VER2_H_ @@ -83,6 +83,7 @@ struct cam_vfe_bus_ver2_reg_offset_common { uint32_t addr_sync_no_sync; uint32_t debug_status_cfg; uint32_t debug_status_0; + uint32_t top_irq_mask_0; }; /* @@ -177,6 +178,7 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info { * @bus_client_reg: Bus client register info * @comp_reg_grp: Composite group register info * @vfe_out_hw_info: VFE output capability + * @top_irq_shift: Mask shift for top level BUS WR irq */ struct cam_vfe_bus_ver2_hw_info { struct cam_vfe_bus_ver2_reg_offset_common common_reg; @@ -188,6 +190,7 @@ struct cam_vfe_bus_ver2_hw_info { uint32_t num_out; struct cam_vfe_bus_ver2_vfe_out_hw_info vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; + uint32_t top_irq_shift; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index eecd6926cced..87a0b72f1dfc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3693,6 +3693,7 @@ static int cam_vfe_bus_ver3_process_cmd( { int rc = -EINVAL; struct cam_vfe_bus_ver3_priv *bus_priv; + uint32_t top_mask_0 = 0; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3729,6 +3730,14 @@ static int cam_vfe_bus_ver3_process_cmd( case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: rc = cam_vfe_bus_ver3_update_wm_config(cmd_args); break; + case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + top_mask_0 = cam_io_r_mb(bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->top_irq_mask_0); + top_mask_0 |= (1 << bus_priv->top_irq_shift); + cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->top_irq_mask_0); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3750,6 +3759,7 @@ int cam_vfe_bus_ver3_init( struct cam_vfe_bus *vfe_bus_local; struct cam_vfe_bus_ver3_hw_info *ver3_hw_info = bus_hw_info; struct cam_vfe_soc_private *soc_private = NULL; + static const char rup_controller_name[] = "vfe_bus_rup"; CAM_DBG(CAM_ISP, "Enter"); @@ -3815,7 +3825,7 @@ int cam_vfe_bus_ver3_init( goto free_bus_priv; } - rc = cam_irq_controller_init("vfe_bus_rup", + rc = cam_irq_controller_init(rup_controller_name, bus_priv->common_data.mem_base, &ver3_hw_info->common_reg.irq_reg_info, &bus_priv->common_data.rup_irq_controller, false); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index c5b4ab69fa9f..f2430c5f2f8e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ @@ -95,6 +95,7 @@ struct cam_vfe_bus_ver3_reg_offset_common { uint32_t debug_status_top_cfg; uint32_t debug_status_top; uint32_t test_bus_ctrl; + uint32_t top_irq_mask_0; struct cam_irq_controller_reg_info irq_reg_info; }; From 75740a1ced2844f039f0b467cc92332bddbc69a9 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 27 Feb 2020 09:55:01 -0800 Subject: [PATCH 299/790] msm: camera: common: Fix types for comparison function Creates a function to match expectant types for platform device comparisons during component registration. CRs-Fixed: 2584631 Change-Id: Ib07160b8d8f1a370ba535ffdbbc6adbe391c68d5 Signed-off-by: Karthik Jayakumar --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 2 +- drivers/cam_utils/cam_compat.c | 60 ++++++++++++++- drivers/cam_utils/cam_compat.h | 6 +- drivers/camera_main.c | 106 -------------------------- drivers/camera_main.h | 68 ++++++++++++++++- 5 files changed, 131 insertions(+), 111 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 038d3c28e49f..ad85d89953c8 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -24,7 +24,7 @@ #include "cam_mem_mgr.h" #include "cam_debug_util.h" #include "cam_common_util.h" -#include "camera_main.h" +#include "cam_compat.h" #define CAM_REQ_MGR_EVENT_MAX 30 diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index aa3c02bafb41..e0b70865c885 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #include @@ -9,6 +9,7 @@ #include "cam_compat.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include "camera_main.h" #if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) @@ -96,6 +97,11 @@ void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) reg_val |= errata_wa->data.reg_info.value; qcom_scm_io_writel(errata_wa->data.reg_info.offset, reg_val); } + +static int camera_platform_compare_dev(struct device *dev, const void *data) +{ + return platform_bus_type.match(dev, (struct device_driver *) data); +} #else int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) { @@ -174,4 +180,56 @@ void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) reg_val |= errata_wa->data.reg_info.value; scm_io_write(errata_wa->data.reg_info.offset, reg_val); } + +static int camera_platform_compare_dev(struct device *dev, void *data) +{ + return platform_bus_type.match(dev, (struct device_driver *) data); +} #endif + +/* Callback to compare device from match list before adding as component */ +static inline int camera_component_compare_dev(struct device *dev, void *data) +{ + return dev == data; +} + +/* Add component matches to list for master of aggregate driver */ +int camera_component_match_add_drivers(struct device *master_dev, + struct component_match **match_list) +{ + int i, rc = 0; + struct platform_device *pdev = NULL; + + if (!master_dev || !match_list) { + CAM_ERR(CAM_UTIL, "Invalid parameters for component match add"); + rc = -EINVAL; + goto end; + } + + for (i = 0; i < ARRAY_SIZE(cam_component_drivers); i++) { +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + struct device_driver const *drv = + &cam_component_drivers[i]->driver; + const void *drv_ptr = (const void *)drv; +#else + struct device_driver *drv = &cam_component_drivers[i]->driver; + void *drv_ptr = (void *)drv; +#endif + struct device *start_dev = NULL, *match_dev; + + while ((match_dev = bus_find_device(&platform_bus_type, + start_dev, drv_ptr, &camera_platform_compare_dev))) { + put_device(start_dev); + pdev = to_platform_device(match_dev); + CAM_DBG(CAM_UTIL, "Adding matched component:%s", + pdev->name); + component_match_add(master_dev, match_list, + camera_component_compare_dev, match_dev); + start_dev = match_dev; + } + put_device(start_dev); + } + +end: + return rc; +} diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h index 3e7bec620c53..ae3cd2a3d388 100644 --- a/drivers/cam_utils/cam_compat.h +++ b/drivers/cam_utils/cam_compat.h @@ -1,12 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_COMPAT_H_ #define _CAM_COMPAT_H_ #include +#include +#include #include "cam_csiphy_dev.h" #include "cam_cpastop_hw.h" @@ -37,5 +39,7 @@ void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa); int cam_ife_notify_safe_lut_scm(bool safe_trigger); int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, bool protect, int32_t offset); +int camera_component_match_add_drivers(struct device *master_dev, + struct component_match **match_list); #endif /* _CAM_COMPAT_H_ */ diff --git a/drivers/camera_main.c b/drivers/camera_main.c index ec29cfd707a8..621f5c3dbe74 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -209,112 +209,6 @@ static const struct camera_submodule submodule_table[] = { } }; -/* - * Drivers to be bound by component framework in this order with - * CRM as master - */ -static struct platform_driver *const cam_component_drivers[] = { -/* BASE */ - &cam_sync_driver, - &cam_smmu_driver, - &cam_cpas_driver, - &cam_cdm_intf_driver, - &cam_hw_cdm_driver, -#ifdef CONFIG_SPECTRA_ISP - &cam_top_tpg_driver, - &cam_ife_csid17x_driver, - &cam_ife_csid_lite_driver, - &cam_vfe_driver, - &isp_driver, -#endif -#ifdef CONFIG_SPECTRA_TFE - &cam_top_tpg_driver, - &cam_tfe_driver, - &cam_tfe_csid530_driver, -#endif -#ifdef CONFIG_SPECTRA_SENSOR - &cam_res_mgr_driver, - &cci_driver, - &csiphy_driver, - &cam_actuator_platform_driver, - &cam_sensor_platform_driver, - &cam_eeprom_platform_driver, - &cam_ois_platform_driver, -#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ - IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) - &cam_flash_platform_driver, -#endif -#endif -#ifdef CONFIG_SPECTRA_ICP - &cam_a5_driver, - &cam_ipe_driver, - &cam_bps_driver, - &cam_icp_driver, -#endif -#ifdef CONFIG_SPECTRA_OPE - &cam_ope_driver, - &cam_ope_subdev_driver, -#endif -#ifdef CONFIG_SPECTRA_JPEG - &cam_jpeg_enc_driver, - &cam_jpeg_dma_driver, - &jpeg_driver, -#endif -#ifdef CONFIG_SPECTRA_FD - &cam_fd_hw_driver, - &cam_fd_driver, -#endif -#ifdef CONFIG_SPECTRA_LRME - &cam_lrme_hw_driver, - &cam_lrme_driver, -#endif -#ifdef CONFIG_SPECTRA_CUSTOM - &cam_custom_hw_sub_mod_driver, - &cam_custom_csid_driver, - &custom_driver, -#endif -}; - -/* Callback to compare device from match list before adding as component */ -static int camera_component_compare_dev(struct device *dev, void *data) -{ - return dev == data; -} - -/* Add component matches to list for master of aggregate driver */ -int camera_component_match_add_drivers(struct device *master_dev, - struct component_match **match_list) -{ - int i, rc = 0; - struct platform_device *pdev = NULL; - - if (!master_dev || !match_list) { - CAM_ERR(CAM_UTIL, "Invalid parameters for component match add"); - rc = -EINVAL; - goto end; - } - - for (i = 0; i < ARRAY_SIZE(cam_component_drivers); i++) { - struct device_driver *drv = &cam_component_drivers[i]->driver; - struct device *start_dev = NULL, *match_dev; - - while ((match_dev = bus_find_device(&platform_bus_type, - start_dev, drv, (void *)platform_bus_type.match))) { - put_device(start_dev); - pdev = to_platform_device(match_dev); - CAM_DBG(CAM_UTIL, "Adding matched component:%s", - pdev->name); - component_match_add(master_dev, match_list, - camera_component_compare_dev, match_dev); - start_dev = match_dev; - } - put_device(start_dev); - } - -end: - return rc; -} - static int camera_verify_submodules(void) { int rc = 0; diff --git a/drivers/camera_main.h b/drivers/camera_main.h index af832ee60f10..e802d64b7510 100644 --- a/drivers/camera_main.h +++ b/drivers/camera_main.h @@ -68,6 +68,70 @@ extern struct platform_driver cam_custom_csid_driver; extern struct platform_driver custom_driver; #endif -int camera_component_match_add_drivers(struct device *dev, - struct component_match **match_list); +/* + * Drivers to be bound by component framework in this order with + * CRM as master + */ +static struct platform_driver *const cam_component_drivers[] = { +/* BASE */ + &cam_sync_driver, + &cam_smmu_driver, + &cam_cpas_driver, + &cam_cdm_intf_driver, + &cam_hw_cdm_driver, +#ifdef CONFIG_SPECTRA_ISP + &cam_top_tpg_driver, + &cam_ife_csid17x_driver, + &cam_ife_csid_lite_driver, + &cam_vfe_driver, + &isp_driver, +#endif +#ifdef CONFIG_SPECTRA_TFE + &cam_top_tpg_driver, + &cam_tfe_driver, + &cam_tfe_csid530_driver, +#endif +#ifdef CONFIG_SPECTRA_SENSOR + &cam_res_mgr_driver, + &cci_driver, + &csiphy_driver, + &cam_actuator_platform_driver, + &cam_sensor_platform_driver, + &cam_eeprom_platform_driver, + &cam_ois_platform_driver, +#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ + IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) + &cam_flash_platform_driver, +#endif +#endif +#ifdef CONFIG_SPECTRA_ICP + &cam_a5_driver, + &cam_ipe_driver, + &cam_bps_driver, + &cam_icp_driver, +#endif +#ifdef CONFIG_SPECTRA_OPE + &cam_ope_driver, + &cam_ope_subdev_driver, +#endif +#ifdef CONFIG_SPECTRA_JPEG + &cam_jpeg_enc_driver, + &cam_jpeg_dma_driver, + &jpeg_driver, +#endif +#ifdef CONFIG_SPECTRA_FD + &cam_fd_hw_driver, + &cam_fd_driver, +#endif +#ifdef CONFIG_SPECTRA_LRME + &cam_lrme_hw_driver, + &cam_lrme_driver, +#endif +#ifdef CONFIG_SPECTRA_CUSTOM + &cam_custom_hw_sub_mod_driver, + &cam_custom_csid_driver, + &custom_driver, +#endif +}; + #endif /* CAMERA_MAIN_H */ From 6eded6217da181a367c10485d52dec90705e09ea Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 9 Jan 2020 15:37:13 -0800 Subject: [PATCH 300/790] msm: camera: uapi: Add support for precise flash on duration Precise flash needs the data for time on duration from UMD. Add the attribute to fill in by UMD. Also, updating the Macro for the max led trigger from 3 to 2 as there are only two physical LED channel is available. CRs-Fixed: 2633194 Change-Id: I641e1ab42e59bc251d33a1e1dd0dff83afb5b7fb Signed-off-by: Jigarkumar Zala --- include/uapi/camera/media/cam_sensor.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index cc86f2706c63..9732502f074c 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_SENSOR_H__ @@ -11,7 +11,7 @@ #include #define CAM_SENSOR_PROBE_CMD (CAM_COMMON_OPCODE_MAX + 1) -#define CAM_FLASH_MAX_LED_TRIGGERS 3 +#define CAM_FLASH_MAX_LED_TRIGGERS 2 #define MAX_OIS_NAME_SIZE 32 #define CAM_CSIPHY_SECURE_MODE_ENABLED 1 /** @@ -434,13 +434,14 @@ struct cam_flash_set_rer { /** * struct cam_flash_set_on_off : led turn on/off command buffer * - * @count : Number of Flash leds - * @opcode : command buffer opcodes - * CAM_FLASH_FIRE_LOW - * CAM_FLASH_FIRE_HIGH - * CAM_FLASH_OFF - * @cmd_type : command buffer operation type - * @led_current_ma : flash led current in ma + * @count : Number of Flash leds + * @opcode : Command buffer opcodes + * CAM_FLASH_FIRE_LOW + * CAM_FLASH_FIRE_HIGH + * CAM_FLASH_OFF + * @cmd_type : Command buffer operation type + * @led_current_ma : Flash led current in ma + * @time_on_duration_ms : Flash time on duration in ns * */ struct cam_flash_set_on_off { @@ -449,6 +450,7 @@ struct cam_flash_set_on_off { uint8_t cmd_type; uint16_t reserved; uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; + uint64_t time_on_duration_ns; } __attribute__((packed)); /** From b7a494a1309b645beed787ce054cebe5ff0d1f6f Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 11 Mar 2020 15:44:46 -0700 Subject: [PATCH 301/790] msm: camera: reqmgr: Add support for dual trigger Currently CRM waits for a single trigger to apply settings for all the devices on a given link. This change provides provision for CRM to wait on two triggers prior to applying a given setting. CRs-Fixed: 2627065 Change-Id: If6e4c9281cfd1bf1a8ffa369daee060d79f3c39e Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 6 ++ drivers/cam_isp/cam_isp_context.h | 2 + drivers/cam_req_mgr/cam_req_mgr_core.c | 77 ++++++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_core.h | 7 ++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 6 ++ 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5843b6be1042..596a4f30719c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1313,6 +1313,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( notify.trigger = CAM_TRIGGER_POINT_SOF; notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; + notify.trigger_id = ctx_isp->trigger_id; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld ctx %u", @@ -4517,6 +4518,7 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx, ctx->link_hdl = link->link_hdl; ctx->ctx_crm_intf = link->crm_cb; ctx_isp->subscribe_event = link->subscribe_event; + ctx_isp->trigger_id = link->trigger_id; /* change state only if we had the init config */ if (ctx_isp->init_received) { @@ -4533,9 +4535,12 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { int rc = 0; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; + ctx_isp->trigger_id = -1; return rc; } @@ -4550,6 +4555,7 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_IFE; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; + dev_info->trigger_on = true; return rc; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index ba49f534e071..2baabe8b2412 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -258,6 +258,7 @@ struct cam_isp_context_event_record { * @rxd_epoch: Indicate whether epoch has been received. Used to * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife + * @trigger_id: ID provided by CRM for each ctx on the link * */ struct cam_isp_context { @@ -300,6 +301,7 @@ struct cam_isp_context { uint32_t isp_device_type; atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; + int32_t trigger_id; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index b5f10a232b89..bc4ed3864802 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -40,6 +40,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->open_req_cnt = 0; link->last_flush_id = 0; link->initial_sync_req = -1; + link->dual_trigger = false; + link->trigger_cnt[0] = 0; + link->trigger_cnt[1] = 0; link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; @@ -2760,6 +2763,33 @@ end: return rc; } +static int __cam_req_mgr_check_for_dual_trigger( + struct cam_req_mgr_core_link *link) +{ + int rc = -EAGAIN; + + if (link->trigger_cnt[0] == link->trigger_cnt[1]) { + link->trigger_cnt[0] = 0; + link->trigger_cnt[1] = 0; + rc = 0; + return rc; + } + + if ((link->trigger_cnt[0] && + (link->trigger_cnt[0] - link->trigger_cnt[1] > 1)) || + (link->trigger_cnt[1] && + (link->trigger_cnt[1] - link->trigger_cnt[0] > 1))) { + + CAM_ERR(CAM_CRM, + "One of the devices could not generate trigger"); + return rc; + } + + CAM_DBG(CAM_CRM, "Only one device has generated trigger"); + + return rc; +} + /** * cam_req_mgr_cb_notify_timer() * @@ -2878,7 +2908,7 @@ end: static int cam_req_mgr_cb_notify_trigger( struct cam_req_mgr_trigger_notify *trigger_data) { - int rc = 0; + int32_t rc = 0, trigger_id = 0; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_trigger_notify *notify_trigger; @@ -2898,6 +2928,8 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } + trigger_id = trigger_data->trigger_id; + spin_lock_bh(&link->link_state_spin_lock); if (link->state < CAM_CRM_LINK_STATE_READY) { CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); @@ -2909,6 +2941,23 @@ static int cam_req_mgr_cb_notify_trigger( if ((link->watchdog) && (link->watchdog->pause_timer)) link->watchdog->pause_timer = false; + if (link->dual_trigger) { + if ((trigger_id >= 0) && (trigger_id < + CAM_REQ_MGR_MAX_TRIGGERS)) { + link->trigger_cnt[trigger_id]++; + rc = __cam_req_mgr_check_for_dual_trigger(link); + if (rc) { + spin_unlock_bh(&link->link_state_spin_lock); + goto end; + } + } else { + CAM_ERR(CAM_CRM, "trigger_id invalid %d", trigger_id); + rc = -EINVAL; + spin_unlock_bh(&link->link_state_spin_lock); + goto end; + } + } + crm_timer_reset(link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); @@ -2963,16 +3012,18 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, struct cam_req_mgr_req_tbl *pd_tbl; enum cam_pipeline_delay max_delay; uint32_t subscribe_event = 0; + uint32_t num_trigger_devices = 0; if (link_info->version == VERSION_1) { if (link_info->u.link_info_v1.num_devices > CAM_REQ_MGR_MAX_HANDLES) return -EPERM; - } + } else if (link_info->version == VERSION_2) { if (link_info->u.link_info_v2.num_devices > CAM_REQ_MGR_MAX_HANDLES_V2) return -EPERM; - } + } + mutex_init(&link->req.lock); CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock); link->req.num_tbl = 0; @@ -3052,6 +3103,17 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, subscribe_event |= (uint32_t)dev->dev_info.trigger; } + + if (dev->dev_info.trigger_on) + num_trigger_devices++; + } + + if (num_trigger_devices > CAM_REQ_MGR_MAX_TRIGGERS) { + CAM_ERR(CAM_CRM, + "Unsupported number of trigger devices %u", + num_trigger_devices); + rc = -EINVAL; + goto error; } link->subscribe_event = subscribe_event; @@ -3060,7 +3122,10 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, link_data.crm_cb = &cam_req_mgr_ops; link_data.max_delay = max_delay; link_data.subscribe_event = subscribe_event; + if (num_trigger_devices == CAM_REQ_MGR_MAX_TRIGGERS) + link->dual_trigger = true; + num_trigger_devices = 0; for (i = 0; i < num_devices; i++) { dev = &link->l_dev[i]; @@ -3100,6 +3165,12 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, CAM_DBG(CAM_CRM, "dev_bit %u name %s pd %u mask %d", dev->dev_bit, dev->dev_info.name, pd_tbl->pd, pd_tbl->dev_mask); + link_data.trigger_id = -1; + if ((dev->dev_info.trigger_on) && (link->dual_trigger)) { + link_data.trigger_id = num_trigger_devices; + num_trigger_devices++; + } + /* Communicate with dev to establish the link */ dev->ops->link_setup(&link_data); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 8324e706cbe5..c364128e6093 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -37,6 +37,7 @@ #define VERSION_1 1 #define VERSION_2 2 +#define CAM_REQ_MGR_MAX_TRIGGERS 2 /** * enum crm_workq_task_type @@ -344,6 +345,9 @@ struct cam_req_mgr_connected_device { * as part of shutdown. * @sof_timestamp_value : SOF timestamp value * @prev_sof_timestamp : Previous SOF timestamp value + * @dual_trigger : Links needs to wait for two triggers prior to + * applying the settings + * @trigger_cnt : trigger count value per device initiating the trigger */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -374,6 +378,9 @@ struct cam_req_mgr_core_link { bool is_shutdown; uint64_t sof_timestamp; uint64_t prev_sof_timestamp; + bool dual_trigger; + uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; + }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index e2e69c3cd2f7..01e3f7abf0fa 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -210,6 +210,7 @@ enum cam_req_mgr_link_evt_type { * only to the devices which subscribe to this point. * @sof_timestamp_val: Captured time stamp value at sof hw event * @req_id : req id which returned buf_done + * @trigger_id: ID to differentiate between the trigger devices */ struct cam_req_mgr_trigger_notify { int32_t link_hdl; @@ -218,6 +219,7 @@ struct cam_req_mgr_trigger_notify { uint32_t trigger; uint64_t sof_timestamp_val; uint64_t req_id; + int32_t trigger_id; }; /** @@ -286,6 +288,7 @@ struct cam_req_mgr_notify_stop { * @dev_id : device id info * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client + * @trigger_on : This device provides trigger */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -293,6 +296,7 @@ struct cam_req_mgr_device_info { enum cam_req_mgr_device_id dev_id; enum cam_pipeline_delay p_delay; uint32_t trigger; + bool trigger_on; }; /** @@ -303,6 +307,7 @@ struct cam_req_mgr_device_info { * @max_delay : max pipeline delay on this link * @crm_cb : callback funcs to communicate with req mgr * @subscribe_event : the mask of trigger points this link subscribes + * @trigger_id : Unique ID provided to the triggering device */ struct cam_req_mgr_core_dev_link_setup { int32_t link_enable; @@ -311,6 +316,7 @@ struct cam_req_mgr_core_dev_link_setup { enum cam_pipeline_delay max_delay; struct cam_req_mgr_crm_cb *crm_cb; uint32_t subscribe_event; + int32_t trigger_id; }; /** From d500bda747b1f88944e98ecd02dbe63f4ac1f5e1 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 3 Dec 2019 20:18:07 +0800 Subject: [PATCH 302/790] msm: camera: sensor: Turn off the flash while flushing Turn off the flash while flushing if the flushed request turns off the flash. CRs-Fixed: 2576732 Change-Id: I546fc6b6ee79f492af905d163515eb19eed78f41 Signed-off-by: Depeng Shao --- .../cam_flash/cam_flash_core.c | 61 ++++++++++++++++--- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index fa8943fc8e94..da32761b5488 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -213,6 +213,8 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, int rc = 0; int i = 0, j = 0; int frame_offset = 0; + bool is_off_needed = false; + struct cam_flash_frame_setting *flash_data = NULL; if (!fctrl) { CAM_ERR(CAM_FLASH, "Device data is NULL"); @@ -222,23 +224,47 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, if (type == FLUSH_ALL) { /* flush all requests*/ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { - fctrl->per_frame[i].cmn_attr.request_id = 0; - fctrl->per_frame[i].cmn_attr.is_settings_valid = false; - fctrl->per_frame[i].cmn_attr.count = 0; + flash_data = + &fctrl->per_frame[i]; + if ((flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_OFF) && + (flash_data->cmn_attr.request_id > 0) && + (flash_data->cmn_attr.request_id <= req_id) && + flash_data->cmn_attr.is_settings_valid) { + is_off_needed = true; + CAM_DBG(CAM_FLASH, + "FLASH_ALL: Turn off the flash for req %llu", + flash_data->cmn_attr.request_id); + } + + flash_data->cmn_attr.request_id = 0; + flash_data->cmn_attr.is_settings_valid = false; + flash_data->cmn_attr.count = 0; for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++) - fctrl->per_frame[i].led_current_ma[j] = 0; + flash_data->led_current_ma[j] = 0; } cam_flash_pmic_flush_nrt(fctrl); } else if ((type == FLUSH_REQ) && (req_id != 0)) { /* flush request with req_id*/ frame_offset = req_id % MAX_PER_FRAME_ARRAY; - fctrl->per_frame[frame_offset].cmn_attr.request_id = 0; - fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid = + flash_data = + &fctrl->per_frame[frame_offset]; + + if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_OFF) { + is_off_needed = true; + CAM_DBG(CAM_FLASH, + "FLASH_REQ: Turn off the flash for req %llu", + flash_data->cmn_attr.request_id); + } + + flash_data->cmn_attr.request_id = 0; + flash_data->cmn_attr.is_settings_valid = false; - fctrl->per_frame[frame_offset].cmn_attr.count = 0; + flash_data->cmn_attr.count = 0; for (i = 0; i < CAM_FLASH_MAX_LED_TRIGGERS; i++) - fctrl->per_frame[frame_offset].led_current_ma[i] = 0; + flash_data->led_current_ma[i] = 0; } else if ((type == FLUSH_REQ) && (req_id == 0)) { /* Handels NonRealTime usecase */ cam_flash_pmic_flush_nrt(fctrl); @@ -247,6 +273,9 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, return -EINVAL; } + if (is_off_needed) + cam_flash_off(fctrl); + return rc; } @@ -493,7 +522,9 @@ static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl, CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", top, del_req_id); } - fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id); + + cam_flash_i2c_flush_nrt(fctrl); + return 0; } @@ -503,6 +534,7 @@ static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl, int i = 0; struct cam_flash_frame_setting *flash_data = NULL; uint64_t top = 0, del_req_id = 0; + int frame_offset = 0; if (req_id != 0) { for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { @@ -538,7 +570,16 @@ static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl, top, del_req_id); } - fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id); + /* delete the request */ + frame_offset = del_req_id % MAX_PER_FRAME_ARRAY; + flash_data = &fctrl->per_frame[frame_offset]; + flash_data->cmn_attr.request_id = 0; + flash_data->cmn_attr.is_settings_valid = false; + flash_data->cmn_attr.count = 0; + + for (i = 0; i < CAM_FLASH_MAX_LED_TRIGGERS; i++) + flash_data->led_current_ma[i] = 0; + return 0; } From 624a05a1029c5f87240a1e0308f253d987d2bb8a Mon Sep 17 00:00:00 2001 From: Shankar Ravi Date: Mon, 10 Feb 2020 14:50:18 +0530 Subject: [PATCH 303/790] msm: camera: eeprom: Correct EEPROM Read return EEPROM Read using QUP I2C returns the number of bytes read from the EEPROM, While CCI/SPI returns zero value. Return Error only when if the value is less than zero. CRs-Fixed: 2617882 External Impact: No Change-Id: I9a9674366c10de4efce779f75dd36b293838c47b Signed-off-by: Shankar Ravi --- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index c50230309c57..caf5132b3df2 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -108,7 +108,7 @@ static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl, emap[j].mem.addr_type, emap[j].mem.data_type, emap[j].mem.valid_size); - if (rc) { + if (rc < 0) { CAM_ERR(CAM_EEPROM, "read failed rc %d", rc); return rc; From 3e463c33ea05e60c2deed74f2b8a7e0eba72f594 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 6 Feb 2020 13:58:09 -0800 Subject: [PATCH 304/790] msm: camera: icp: Remove bw vote of context in Release Do not rely on timer expiry to remove bw of current context if it is getting released. If context release is coming before timer expiry (from last request submit), we are not removing current context's vote from hw mgr and thus from cpas. This will accumulate the bandwidth and causes clocks to go to turbo and also into overflow issues if the bw variables in cpas are wrapping around in long hours testing. CRs-Fixed: 2617278 Change-Id: I11d837bf7224ac4573fee32518f7f57ad9bf49f0 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 25 ++- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 189 ++++++++++++------ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 + 3 files changed, 149 insertions(+), 67 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 0486a0c2fccd..134b1638b2e2 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -403,6 +403,13 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( do_div(intermediate_result, 100); required_camnoc_bw += intermediate_result; + if (cpas_core->streamon_clients && (required_camnoc_bw == 0)) { + CAM_DBG(CAM_CPAS, + "Set min vote if streamon_clients is non-zero : streamon_clients=%d", + cpas_core->streamon_clients); + required_camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + } + if ((required_camnoc_bw > 0) && (required_camnoc_bw < soc_private->camnoc_axi_min_ib_bw)) @@ -639,8 +646,12 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( if (camnoc_axi_port->camnoc_bw) camnoc_bw = camnoc_axi_port->camnoc_bw; - else + else if (camnoc_axi_port->additional_bw) camnoc_bw = camnoc_axi_port->additional_bw; + else if (cpas_core->streamon_clients) + camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + else + camnoc_bw = 0; rc = cam_cpas_util_vote_bus_client_bw( &camnoc_axi_port->bus_client, @@ -816,14 +827,20 @@ vote_start_clients: else continue; - CAM_DBG(CAM_PERF, "Port[%s] : ab=%lld ib=%lld additional=%lld", + CAM_DBG(CAM_PERF, + "Port[%s] : ab=%lld ib=%lld additional=%lld, streamon_clients=%d", mnoc_axi_port->axi_port_name, mnoc_axi_port->ab_bw, - mnoc_axi_port->ib_bw, mnoc_axi_port->additional_bw); + mnoc_axi_port->ib_bw, mnoc_axi_port->additional_bw, + cpas_core->streamon_clients); if (mnoc_axi_port->ab_bw) mnoc_ab_bw = mnoc_axi_port->ab_bw; - else + else if (mnoc_axi_port->additional_bw) mnoc_ab_bw = mnoc_axi_port->additional_bw; + else if (cpas_core->streamon_clients) + mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + else + mnoc_ab_bw = 0; if (cpas_core->axi_port[i].ib_bw_voting_needed) mnoc_ib_bw = mnoc_axi_port->ib_bw; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 3f30bb6819d4..425cebafae75 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -415,73 +415,48 @@ done: return rc; } -static int32_t cam_icp_ctx_timer(void *priv, void *data) +static int cam_icp_remove_ctx_bw(struct cam_icp_hw_mgr *hw_mgr, + struct cam_icp_hw_ctx_data *ctx_data) { - struct clk_work_data *task_data = (struct clk_work_data *)data; - struct cam_icp_hw_ctx_data *ctx_data = - (struct cam_icp_hw_ctx_data *)task_data->data; - struct cam_icp_hw_mgr *hw_mgr = &icp_hw_mgr; + int rc = 0; + struct cam_hw_intf *dev_intf = NULL; uint32_t id; uint64_t temp; - struct cam_hw_intf *ipe0_dev_intf = NULL; - struct cam_hw_intf *ipe1_dev_intf = NULL; - struct cam_hw_intf *bps_dev_intf = NULL; - struct cam_hw_intf *dev_intf = NULL; struct cam_icp_clk_info *clk_info; struct cam_icp_cpas_vote clk_update; int i = 0; int device_share_ratio = 1; uint64_t total_ab_bw = 0; - if (!ctx_data) { - CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk"); + if (!ctx_data->icp_dev_acquire_info) { + CAM_WARN(CAM_ICP, "NULL acquire info"); return -EINVAL; } - mutex_lock(&ctx_data->ctx_mutex); - if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) || - (ctx_data->watch_dog_reset_counter == 0)) { - CAM_DBG(CAM_PERF, "state %d, counter=%d", - ctx_data->state, ctx_data->watch_dog_reset_counter); - mutex_unlock(&ctx_data->ctx_mutex); - return 0; - } - - if (cam_icp_frame_pending(ctx_data)) { - cam_icp_ctx_timer_reset(ctx_data); - mutex_unlock(&ctx_data->ctx_mutex); - return -EBUSY; + if ((!hw_mgr->ipe0_dev_intf) || (!hw_mgr->bps_dev_intf)) { + CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk"); + return -EINVAL; } CAM_DBG(CAM_PERF, - "E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u", + "ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u", ctx_data->ctx_id, ctx_data->clk_info.uncompressed_bw, ctx_data->clk_info.compressed_bw, ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk); - ipe0_dev_intf = hw_mgr->ipe0_dev_intf; - ipe1_dev_intf = hw_mgr->ipe1_dev_intf; - bps_dev_intf = hw_mgr->bps_dev_intf; - - if ((!ipe0_dev_intf) || (!bps_dev_intf)) { - CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk"); - mutex_unlock(&ctx_data->ctx_mutex); - return -EINVAL; - } - - if (!ctx_data->icp_dev_acquire_info) { - CAM_WARN(CAM_ICP, "NULL acquire info"); - mutex_unlock(&ctx_data->ctx_mutex); - return -EINVAL; + if (!ctx_data->clk_info.bw_included) { + CAM_DBG(CAM_PERF, "ctx_id = %d BW vote already removed", + ctx_data->ctx_id); + return 0; } if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) { - dev_intf = bps_dev_intf; + dev_intf = hw_mgr->bps_dev_intf; clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS]; id = CAM_ICP_BPS_CMD_VOTE_CPAS; } else { - dev_intf = ipe0_dev_intf; + dev_intf = hw_mgr->ipe0_dev_intf; clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE]; id = CAM_ICP_IPE_CMD_VOTE_CPAS; } @@ -492,7 +467,7 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) * to vote on each device */ if ((ctx_data->icp_dev_acquire_info->dev_type != - CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) + CAM_ICP_RES_TYPE_BPS) && (hw_mgr->ipe1_dev_intf)) device_share_ratio = 2; if (ctx_data->bw_config_version == CAM_ICP_BW_CONFIG_V1) { @@ -549,23 +524,20 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) * votes only. */ path_index = - ctx_data->clk_info.axi_path[i] - .transac_type - - CAM_AXI_TRANSACTION_READ; + ctx_data->clk_info.axi_path[i].transac_type - + CAM_AXI_TRANSACTION_READ; } else { path_index = - ctx_data->clk_info.axi_path[i] - .path_data_type - - CAM_AXI_PATH_DATA_IPE_START_OFFSET; + ctx_data->clk_info.axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_IPE_START_OFFSET; } if (path_index >= CAM_ICP_MAX_PER_PATH_VOTES) { CAM_WARN(CAM_PERF, - "Invalid path %d, start offset=%d, max=%d", - ctx_data->clk_info.axi_path[i] - .path_data_type, - CAM_AXI_PATH_DATA_IPE_START_OFFSET, - CAM_ICP_MAX_PER_PATH_VOTES); + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_IPE_START_OFFSET, + CAM_ICP_MAX_PER_PATH_VOTES); continue; } @@ -582,6 +554,30 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) total_ab_bw += clk_info->axi_path[path_index].mnoc_ab_bw; + + CAM_DBG(CAM_PERF, + "Removing ctx bw from path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s", + cam_cpas_axi_util_path_type_to_string( + ctx_data->clk_info.axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + ctx_data->clk_info.axi_path[i].transac_type), + ctx_data->clk_info.axi_path[i].camnoc_bw, + ctx_data->clk_info.axi_path[i].mnoc_ab_bw, + ctx_data->clk_info.axi_path[i].mnoc_ib_bw, + cam_icp_dev_type_to_name( + ctx_data->icp_dev_acquire_info->dev_type)); + + CAM_DBG(CAM_PERF, + "Final HW bw for path_type: %s, transac_type: %s, camnoc_bw = %lld mnoc_ab_bw = %lld, mnoc_ib_bw = %lld, device: %s", + cam_cpas_axi_util_path_type_to_string( + clk_info->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + clk_info->axi_path[i].transac_type), + clk_info->axi_path[i].camnoc_bw, + clk_info->axi_path[i].mnoc_ab_bw, + clk_info->axi_path[i].mnoc_ib_bw, + cam_icp_dev_type_to_name( + ctx_data->icp_dev_acquire_info->dev_type)); } memset(&ctx_data->clk_info.axi_path[0], 0, @@ -628,22 +624,76 @@ static int32_t cam_icp_ctx_timer(void *priv, void *data) clk_update.ahb_vote_valid = false; } - dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + rc = dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, &clk_update, sizeof(clk_update)); + if (rc) + CAM_ERR(CAM_PERF, "Failed in updating cpas vote, rc=%d", rc); /* * Vote half bandwidth each on both devices. * Total bw at mnoc - CPAS will take care of adding up. * camnoc clk calculate is more accurate this way. */ - if ((ctx_data->icp_dev_acquire_info->dev_type != - CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) - ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id, - &clk_update, sizeof(clk_update)); + if ((!rc) && (hw_mgr->ipe1_dev_intf) && + (ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS)) { + dev_intf = hw_mgr->ipe1_dev_intf; + rc = dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, + id, &clk_update, sizeof(clk_update)); + if (rc) + CAM_ERR(CAM_PERF, + "Failed in updating cpas vote for ipe 2, rc=%d", + rc); + } + + ctx_data->clk_info.bw_included = false; CAM_DBG(CAM_PERF, "X :ctx_id = %d curr_fc = %u bc = %u", ctx_data->ctx_id, ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk); + + return rc; + +} + + +static int32_t cam_icp_ctx_timer(void *priv, void *data) +{ + struct clk_work_data *task_data = (struct clk_work_data *)data; + struct cam_icp_hw_ctx_data *ctx_data = + (struct cam_icp_hw_ctx_data *)task_data->data; + + if (!ctx_data) { + CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk"); + return -EINVAL; + } + + mutex_lock(&ctx_data->ctx_mutex); + + CAM_DBG(CAM_PERF, + "ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u", + ctx_data->ctx_id, + ctx_data->clk_info.uncompressed_bw, + ctx_data->clk_info.compressed_bw, + ctx_data->clk_info.curr_fc, + ctx_data->clk_info.base_clk); + + if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) || + (ctx_data->watch_dog_reset_counter == 0)) { + CAM_DBG(CAM_PERF, "state %d, counter=%d", + ctx_data->state, ctx_data->watch_dog_reset_counter); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + if (cam_icp_frame_pending(ctx_data)) { + cam_icp_ctx_timer_reset(ctx_data); + mutex_unlock(&ctx_data->ctx_mutex); + return -EBUSY; + } + + cam_icp_remove_ctx_bw(&icp_hw_mgr, ctx_data); + mutex_unlock(&ctx_data->ctx_mutex); return 0; @@ -1184,6 +1234,8 @@ static bool cam_icp_update_bw_v2(struct cam_icp_hw_mgr *hw_mgr, hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw); } + ctx_data->clk_info.bw_included = true; + if (hw_mgr_clk_info->num_paths < ctx_data->clk_info.num_paths) hw_mgr_clk_info->num_paths = ctx_data->clk_info.num_paths; @@ -1250,6 +1302,8 @@ static bool cam_icp_update_bw(struct cam_icp_hw_mgr *hw_mgr, } } + ctx_data->clk_info.bw_included = true; + return true; } @@ -1432,6 +1486,7 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, struct cam_icp_hw_ctx_data *ctx_data) { + int rc = 0; uint32_t id; uint64_t temp; int i = 0; @@ -1529,8 +1584,10 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, } clk_update.axi_vote_valid = true; - dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, + rc = dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, &clk_update, sizeof(clk_update)); + if (rc) + CAM_ERR(CAM_PERF, "Failed in updating cpas vote, rc=%d", rc); /* * Vote half bandwidth each on both devices. @@ -1538,11 +1595,16 @@ static int cam_icp_update_cpas_vote(struct cam_icp_hw_mgr *hw_mgr, * camnoc clk calculate is more accurate this way. */ if ((ctx_data->icp_dev_acquire_info->dev_type != - CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) - ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, id, - &clk_update, sizeof(clk_update)); + CAM_ICP_RES_TYPE_BPS) && (ipe1_dev_intf)) { + rc = ipe1_dev_intf->hw_ops.process_cmd(ipe1_dev_intf->hw_priv, + id, &clk_update, sizeof(clk_update)); + if (rc) + CAM_ERR(CAM_PERF, + "Failed in updating cpas vote for ipe 2, rc=%d", + rc); + } - return 0; + return rc; } static int cam_icp_mgr_ipe_bps_clk_update(struct cam_icp_hw_mgr *hw_mgr, @@ -3315,6 +3377,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) } mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); + cam_icp_remove_ctx_bw(hw_mgr, &hw_mgr->ctx_data[ctx_id]); if (hw_mgr->ctx_data[ctx_id].state != CAM_ICP_CTX_STATE_ACQUIRED) { mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index c438d438e892..a4b3817680e8 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -207,6 +207,7 @@ struct hfi_frame_process_info { * @clk_rate: Supported clock rates for the context * @num_paths: Number of valid AXI paths * @axi_path: ctx based per path bw vote + * @bw_included: Whether bw of this context is included in overal voting */ struct cam_ctx_clk_info { uint32_t curr_fc; @@ -218,6 +219,7 @@ struct cam_ctx_clk_info { int32_t clk_rate[CAM_MAX_VOTE]; uint32_t num_paths; struct cam_axi_per_path_bw_vote axi_path[CAM_ICP_MAX_PER_PATH_VOTES]; + bool bw_included; }; /** * struct cam_icp_hw_ctx_data From 1f40c7a4673f5dcd47fb7dedde1a84c9aa39b057 Mon Sep 17 00:00:00 2001 From: Mangalaram ARCHANA Date: Thu, 5 Dec 2019 15:32:46 +0530 Subject: [PATCH 305/790] msm: camera: reqmgr: skip re_apply of ISP for buf_done request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crm applied both sensor and isp packets,sensor packet failed to apply due to CCI timeout error. In the meantime ISP packet applied and that request of ISP moved to free_list.In the next epoch crm trying to reapply both the packets of sensor and isp again.In this case ISP always reporting an apply failure because its pending queue doesn’t have that request.To handle this we are skipping to re-apply the ISP successful buf_done request and trying to apply only sensor packet in this scenario. CRs-Fixed: 2599186 Change-Id: Id7e72fc016a75782b57f05558c615b069b416ffe Signed-off-by: Mangalaram ARCHANA --- drivers/cam_isp/cam_isp_context.c | 8 ++++++++ drivers/cam_req_mgr/cam_req_mgr_core.c | 5 +++++ drivers/cam_req_mgr/cam_req_mgr_core.h | 2 ++ drivers/cam_req_mgr/cam_req_mgr_debug.c | 9 ++++++++- drivers/cam_req_mgr/cam_req_mgr_interface.h | 2 ++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5843b6be1042..6a02b4acd10f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2485,6 +2485,14 @@ static int __cam_isp_ctx_apply_req_in_activated_state( goto end; } + if (apply->re_apply) + if (apply->request_id <= ctx_isp->last_applied_req_id) { + CAM_INFO(CAM_ISP, + "Trying to reapply the same request %llu again", + apply->request_id); + return 0; + } + spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index b5f10a232b89..af27858834b9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -659,6 +659,11 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.link_hdl = link->link_hdl; apply_req.report_if_bubble = 0; + apply_req.re_apply = false; + if (link->retry_cnt > 0) { + if (g_crm_core_dev->recovery_on_apply_fail) + apply_req.re_apply = true; + } for (i = 0; i < link->num_devs; i++) { dev = &link->l_dev[i]; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 8324e706cbe5..991eaf9f3344 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -406,10 +406,12 @@ struct cam_req_mgr_core_session { * - Core camera request manager data struct * @session_head : list head holding sessions * @crm_lock : mutex lock to protect session creation & destruction + * @recovery_on_apply_fail : Recovery on apply failure using debugfs. */ struct cam_req_mgr_core_device { struct list_head session_head; struct mutex crm_lock; + bool recovery_on_apply_fail; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index 6b428c41c1b0..db6bec704370 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_debug.h" @@ -128,5 +128,12 @@ int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) debugfs_root, core_dev, &bubble_recovery)) return -ENOMEM; + if (!debugfs_create_bool("recovery_on_apply_fail", + 0644, + debugfs_root, + &core_dev->recovery_on_apply_fail)) { + return -ENOMEM; + } + return 0; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index e2e69c3cd2f7..12b3e63c3764 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -320,6 +320,7 @@ struct cam_req_mgr_core_dev_link_setup { * @request_id : request id settings to apply * @report_if_bubble : report to crm if failure in applying * @trigger_point : the trigger point of this apply + * @re_apply : to skip re_apply for buf_done request * */ struct cam_req_mgr_apply_request { @@ -328,6 +329,7 @@ struct cam_req_mgr_apply_request { uint64_t request_id; int32_t report_if_bubble; uint32_t trigger_point; + bool re_apply; }; /** From f77d546937657cad7b6e2218f86aa1501292a021 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Tue, 10 Dec 2019 14:11:48 -0800 Subject: [PATCH 306/790] msm: camera: cpas: Remove votes on enable_soc failure If enabling soc resources has failed, remove the votes that were voted for this client. CRs-Fixed: 2585080 Change-Id: I05f460e93a1bf7b96a99dd32f3fd03dbde5b094f Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 44 +++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 0486a0c2fccd..14a8de79afe0 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1115,6 +1115,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, struct cam_cpas_hw_cmd_start *cmd_hw_start; struct cam_cpas_client *cpas_client; struct cam_ahb_vote *ahb_vote; + struct cam_ahb_vote remove_ahb; struct cam_axi_vote axi_vote = {0}; enum cam_vote_level applied_level = CAM_SVS_VOTE; int rc, i = 0; @@ -1176,7 +1177,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, CAM_ERR(CAM_CPAS, "client=[%d] is not registered", client_indx); rc = -EPERM; - goto done; + goto error; } if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { @@ -1184,7 +1185,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, client_indx, cpas_client->data.identifier, cpas_client->data.cell_index); rc = -EPERM; - goto done; + goto error; } CAM_DBG(CAM_CPAS, @@ -1195,7 +1196,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client, ahb_vote, &applied_level); if (rc) - goto done; + goto error; cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start Vote", &axi_vote); @@ -1216,7 +1217,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, if (rc) { CAM_ERR(CAM_CPAS, "Unable to create or translate paths rc: %d", rc); - goto done; + goto remove_ahb_vote; } cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start Translated Vote", @@ -1225,7 +1226,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, cpas_client, &axi_vote); if (rc) - goto done; + goto remove_ahb_vote; if (cpas_core->streamon_clients == 0) { atomic_set(&cpas_core->irq_count, 1); @@ -1234,7 +1235,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, if (rc) { atomic_set(&cpas_core->irq_count, 0); CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc); - goto done; + goto remove_axi_vote; } if (cpas_core->internal_ops.power_on) { @@ -1246,7 +1247,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, CAM_ERR(CAM_CPAS, "failed in power_on settings rc=%d", rc); - goto done; + goto remove_axi_vote; } } CAM_DBG(CAM_CPAS, "irq_count=%d\n", @@ -1260,7 +1261,34 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, CAM_DBG(CAM_CPAS, "client=[%d][%s][%d] streamon_clients=%d", client_indx, cpas_client->data.identifier, cpas_client->data.cell_index, cpas_core->streamon_clients); -done: + + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return rc; + +remove_axi_vote: + memset(&axi_vote, 0x0, sizeof(struct cam_axi_vote)); + rc = cam_cpas_util_create_vote_all_paths(cpas_client, &axi_vote); + if (rc) + CAM_ERR(CAM_CPAS, "Unable to create per path votes rc: %d", rc); + + cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start fail Vote", + &axi_vote); + + rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, + cpas_client, &axi_vote); + if (rc) + CAM_ERR(CAM_CPAS, "Unable remove votes rc: %d", rc); + +remove_ahb_vote: + remove_ahb.type = CAM_VOTE_ABSOLUTE; + remove_ahb.vote.level = CAM_SUSPEND_VOTE; + rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client, + &remove_ahb, NULL); + if (rc) + CAM_ERR(CAM_CPAS, "Removing AHB vote failed, rc=%d", rc); + +error: mutex_unlock(&cpas_core->client_mutex[client_indx]); mutex_unlock(&cpas_hw->hw_mutex); return rc; From 09e14ad7e8dc2b9393da5ac1d404036a6ef6f8ea Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 23 Jan 2020 12:10:52 -0800 Subject: [PATCH 307/790] msm: camera: fd: Fix race condition in resetting ready_to_process Do not unlock frame_req_mutex until the request is added into processing list after submitting the frame to hw. This can cause a race condition where Flush comes before adding the frame into processing list and thinks there is no frame with HW. And there is a possibility that FrameDone IRQ thread can get the mutex and thinks no frame in processing list - causing never to reset the flag ready_to_process. This will cause all subsequent camera usage to fail as requests will never be submitted to hw. CRs-Fixed: 2600443 Change-Id: Icd12e155192fccd9adbc7b774b073ca623f1d7ba Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 82 +++++++++++++------ drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h | 3 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c | 1 + .../cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h | 2 + 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index f90ffc4eb7c4..644767d9e513 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -240,6 +240,15 @@ static int cam_fd_mgr_util_release_device(struct cam_fd_hw_mgr *hw_mgr, mutex_lock(&hw_mgr->hw_mgr_mutex); hw_device->num_ctxts--; + + if (!hw_device->num_ctxts) { + mutex_lock(&hw_device->lock); + hw_device->ready_to_process = true; + hw_device->req_id = -1; + hw_device->cur_hw_ctx = NULL; + mutex_unlock(&hw_device->lock); + } + mutex_unlock(&hw_mgr->hw_mgr_mutex); hw_ctx->device_index = -1; @@ -277,6 +286,11 @@ static int cam_fd_mgr_util_select_device(struct cam_fd_hw_mgr *hw_mgr, (!fd_acquire_args->get_raw_results || hw_device->hw_caps.raw_results_available)) { CAM_DBG(CAM_FD, "Found dedicated HW Index=%d", i); + mutex_lock(&hw_device->lock); + hw_device->ready_to_process = true; + hw_device->req_id = -1; + hw_device->cur_hw_ctx = NULL; + mutex_unlock(&hw_device->lock); hw_device->num_ctxts++; break; } @@ -294,7 +308,9 @@ static int cam_fd_mgr_util_select_device(struct cam_fd_hw_mgr *hw_mgr, (!fd_acquire_args->get_raw_results || hw_device->hw_caps.raw_results_available)) { hw_device->num_ctxts++; - CAM_DBG(CAM_FD, "Found sharing HW Index=%d", i); + CAM_DBG(CAM_FD, + "Found sharing HW Index=%d, num_ctxts=%d", + i, hw_device->num_ctxts); break; } } @@ -846,6 +862,11 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) mutex_lock(&hw_device->lock); if (hw_device->ready_to_process == false) { + if (hw_mgr->num_pending_frames > 6) { + CAM_WARN(CAM_FD, + "Device busy for longer time with cur_hw_ctx=%pK, ReqId=%lld", + hw_device->cur_hw_ctx, hw_device->req_id); + } mutex_unlock(&hw_device->lock); mutex_unlock(&hw_mgr->frame_req_mutex); return -EBUSY; @@ -854,7 +875,8 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) trace_cam_submit_to_hw("FD", frame_req->request_id); list_del_init(&frame_req->list); - mutex_unlock(&hw_mgr->frame_req_mutex); + hw_mgr->num_pending_frames--; + list_add_tail(&frame_req->list, &hw_mgr->frame_processing_list); if (hw_device->hw_intf->hw_ops.start) { start_args.hw_ctx = hw_ctx; @@ -869,12 +891,16 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) sizeof(start_args)); if (rc) { CAM_ERR(CAM_FD, "Failed in HW Start %d", rc); + list_del_init(&frame_req->list); mutex_unlock(&hw_device->lock); + mutex_unlock(&hw_mgr->frame_req_mutex); goto put_req_into_free_list; } } else { CAM_ERR(CAM_FD, "Invalid hw_ops.start"); + list_del_init(&frame_req->list); mutex_unlock(&hw_device->lock); + mutex_unlock(&hw_mgr->frame_req_mutex); rc = -EPERM; goto put_req_into_free_list; } @@ -883,30 +909,9 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) hw_device->cur_hw_ctx = hw_ctx; hw_device->req_id = frame_req->request_id; mutex_unlock(&hw_device->lock); - frame_req->submit_timestamp = ktime_get(); - - rc = cam_fd_mgr_util_put_frame_req( - &hw_mgr->frame_processing_list, &frame_req); - if (rc) { - CAM_ERR(CAM_FD, - "Failed in putting frame req in processing list"); - goto stop_unlock; - } + mutex_unlock(&hw_mgr->frame_req_mutex); return rc; - -stop_unlock: - if (hw_device->hw_intf->hw_ops.stop) { - struct cam_fd_hw_stop_args stop_args; - - stop_args.hw_ctx = hw_ctx; - stop_args.ctx_hw_private = hw_ctx->ctx_hw_private; - stop_args.hw_req_private = &frame_req->hw_req_private; - if (hw_device->hw_intf->hw_ops.stop( - hw_device->hw_intf->hw_priv, &stop_args, - sizeof(stop_args))) - CAM_ERR(CAM_FD, "Failed in HW Stop %d", rc); - } put_req_into_free_list: cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list, &frame_req); @@ -1274,6 +1279,7 @@ static int cam_fd_mgr_hw_start(void *hw_mgr_priv, void *mgr_start_args) if (hw_device->hw_intf->hw_ops.init) { hw_init_args.hw_ctx = hw_ctx; hw_init_args.ctx_hw_private = hw_ctx->ctx_hw_private; + hw_init_args.is_hw_reset = false; if (fd_core->hw_static_info->enable_errata_wa.skip_reset) hw_init_args.reset_required = false; else @@ -1286,6 +1292,14 @@ static int cam_fd_mgr_hw_start(void *hw_mgr_priv, void *mgr_start_args) CAM_ERR(CAM_FD, "Failed in HW Init %d", rc); return rc; } + + if (hw_init_args.is_hw_reset) { + mutex_lock(&hw_device->lock); + hw_device->ready_to_process = true; + hw_device->req_id = -1; + hw_device->cur_hw_ctx = NULL; + mutex_unlock(&hw_device->lock); + } } else { CAM_ERR(CAM_FD, "Invalid init function"); return -EINVAL; @@ -1333,6 +1347,7 @@ static int cam_fd_mgr_hw_flush_req(void *hw_mgr_priv, if (frame_req->request_id != flush_req->request_id) continue; + hw_mgr->num_pending_frames--; list_del_init(&frame_req->list); break; } @@ -1345,6 +1360,7 @@ static int cam_fd_mgr_hw_flush_req(void *hw_mgr_priv, if (frame_req->request_id != flush_req->request_id) continue; + hw_mgr->num_pending_frames--; list_del_init(&frame_req->list); break; } @@ -1427,6 +1443,7 @@ static int cam_fd_mgr_hw_flush_ctx(void *hw_mgr_priv, if (frame_req->hw_ctx != hw_ctx) continue; + hw_mgr->num_pending_frames--; list_del_init(&frame_req->list); } @@ -1435,6 +1452,7 @@ static int cam_fd_mgr_hw_flush_ctx(void *hw_mgr_priv, if (frame_req->hw_ctx != hw_ctx) continue; + hw_mgr->num_pending_frames--; list_del_init(&frame_req->list); } @@ -1816,6 +1834,7 @@ static int cam_fd_mgr_hw_config(void *hw_mgr_priv, void *hw_config_args) struct cam_fd_mgr_frame_request *frame_req; int rc; int i; + uint64_t req_id; if (!hw_mgr || !config) { CAM_ERR(CAM_FD, "Invalid arguments %pK %pK", hw_mgr, config); @@ -1834,6 +1853,7 @@ static int cam_fd_mgr_hw_config(void *hw_mgr_priv, void *hw_config_args) } frame_req = config->priv; + req_id = frame_req->request_id; trace_cam_apply_req("FD", frame_req->request_id); CAM_DBG(CAM_FD, "FrameHWConfig : Frame[%lld]", frame_req->request_id); @@ -1863,6 +1883,13 @@ static int cam_fd_mgr_hw_config(void *hw_mgr_priv, void *hw_config_args) goto put_free_list; } + mutex_lock(&g_fd_hw_mgr.frame_req_mutex); + hw_mgr->num_pending_frames++; + CAM_DBG(CAM_FD, + "Adding ctx[%pK] Req[%llu] : Total number of pending frames %d", + hw_ctx, req_id, hw_mgr->num_pending_frames); + mutex_unlock(&g_fd_hw_mgr.frame_req_mutex); + rc = cam_fd_mgr_util_schedule_frame_worker_task(hw_mgr); if (rc) { CAM_ERR(CAM_FD, "Worker task scheduling failed %d", rc); @@ -1882,6 +1909,10 @@ remove_and_put_free_list: cam_fd_mgr_util_get_frame_req( &hw_mgr->frame_pending_list_normal, &frame_req); } + + mutex_lock(&g_fd_hw_mgr.frame_req_mutex); + hw_mgr->num_pending_frames--; + mutex_unlock(&g_fd_hw_mgr.frame_req_mutex); put_free_list: cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list, &frame_req); @@ -1952,6 +1983,8 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, hw_device->valid = true; hw_device->hw_intf = hw_intf; hw_device->ready_to_process = true; + hw_device->req_id = -1; + hw_device->cur_hw_ctx = NULL; if (hw_device->hw_intf->hw_ops.process_cmd) { struct cam_fd_hw_cmd_set_irq_cb irq_cb_args; @@ -2004,6 +2037,7 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, g_fd_hw_mgr.device_iommu.secure = -1; g_fd_hw_mgr.cdm_iommu.non_secure = -1; g_fd_hw_mgr.cdm_iommu.secure = -1; + g_fd_hw_mgr.num_pending_frames = 0; rc = cam_smmu_get_handle("fd", &g_fd_hw_mgr.device_iommu.non_secure); diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h index 61b3ae3b40a5..d453923b09de 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h @@ -159,6 +159,8 @@ struct cam_fd_mgr_work_data { * @work : Worker handle * @work_data : Worker data * @fd_caps : FD driver capabilities + * @num_pending_frames : Number of total frames pending for processing + * across contexts */ struct cam_fd_hw_mgr { struct list_head free_ctx_list; @@ -182,6 +184,7 @@ struct cam_fd_hw_mgr { struct cam_req_mgr_core_workq *work; struct cam_fd_mgr_work_data *work_data; struct cam_fd_query_cap_cmd fd_caps; + uint32_t num_pending_frames; }; #endif /* _CAM_FD_HW_MGR_H_ */ diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c index 80e30ad6c64e..49cee7922f9c 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -753,6 +753,7 @@ int cam_fd_hw_init(void *hw_priv, void *init_hw_args, uint32_t arg_size) CAM_ERR(CAM_FD, "Reset Failed, rc=%d", rc); goto disable_soc; } + init_args->is_hw_reset = true; } cam_fd_hw_util_enable_power_on_settings(fd_hw); diff --git a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h index fd8720856583..9a600b91ca15 100644 --- a/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +++ b/drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -163,11 +163,13 @@ struct cam_fd_hw_release_args { * @hw_ctx : HW context for which init is requested * @ctx_hw_private : HW layer's private information specific to this hw context * @reset_required : Indicates if the reset is required during init or not + * @is_hw_reset : Output from hw layer, whether hw is reset on this init */ struct cam_fd_hw_init_args { void *hw_ctx; void *ctx_hw_private; bool reset_required; + bool is_hw_reset; }; /** From 320ae57bb915e0e91be7546bb13fd0458a48f210 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 4 Feb 2020 11:33:11 +0530 Subject: [PATCH 308/790] msm: camera: core: Fix context release timing issue When sync object is invalid and num_in_map > 1, it will lead to context ref leak. Check sync object first, then register sync call back. CRs-Fixed: 2594185 Change-Id: I2d39ce3ea43bbe7bc05420b86b37fdfba4aa795a Signed-off-by: Ayush Kumar --- drivers/cam_core/cam_context_utils.c | 19 +++++++++++----- drivers/cam_sync/cam_sync.c | 33 ++++++++++++++++++++++++++++ drivers/cam_sync/cam_sync_api.h | 12 +++++++++- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 87abebabaf00..09f164561d69 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -451,6 +451,17 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, "[%s][%d] : Moving req[%llu] from free_list to pending_list", ctx->dev_name, ctx->ctx_id, req->request_id); + for (j = 0; j < req->num_in_map_entries; j++) { + rc = cam_sync_check_valid( + req->in_map_entries[j].sync_id); + if (rc) { + CAM_ERR(CAM_CTXT, + "invalid in map sync object %d", + req->in_map_entries[j].sync_id); + goto put_ref; + } + } + for (j = 0; j < req->num_in_map_entries; j++) { cam_context_getref(ctx); rc = cam_sync_register_callback( @@ -472,7 +483,8 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, ctx->dev_name, ctx->ctx_id, req->request_id); - goto put_ctx_ref; + cam_context_putref(ctx); + goto put_ref; } CAM_DBG(CAM_CTXT, "register in fence cb: %d ret = %d", req->in_map_entries[j].sync_id, rc); @@ -480,9 +492,6 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, } return rc; -put_ctx_ref: - for (; j >= 0; j--) - cam_context_putref(ctx); put_ref: for (--i; i >= 0; i--) { if (cam_sync_put_obj_ref(req->out_map_entries[i].sync_id)) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 8f7d9d838970..7f6a38a283f4 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -287,6 +287,7 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj) int rc; long idx = 0; bool bit; + int i = 0; if (!sync_obj || !merged_obj) { CAM_ERR(CAM_SYNC, "Invalid pointer(s)"); @@ -304,6 +305,14 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj) return -EINVAL; } + for (i = 0; i < num_objs; i++) { + rc = cam_sync_check_valid(sync_obj[i]); + if (rc) { + CAM_ERR(CAM_SYNC, "Sync_obj[%d] %d valid check fail", + i, sync_obj[i]); + return rc; + } + } do { idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS); if (idx >= CAM_SYNC_MAX_OBJS) @@ -375,6 +384,30 @@ int cam_sync_destroy(int32_t sync_obj) return cam_sync_deinit_object(sync_dev->sync_table, sync_obj); } +int cam_sync_check_valid(int32_t sync_obj) +{ + struct sync_table_row *row = NULL; + + if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) + return -EINVAL; + + row = sync_dev->sync_table + sync_obj; + + if (!test_bit(sync_obj, sync_dev->bitmap)) { + CAM_ERR(CAM_SYNC, "Error: Released sync obj received %d", + sync_obj); + return -EINVAL; + } + + if (row->state == CAM_SYNC_STATE_INVALID) { + CAM_ERR(CAM_SYNC, + "Error: accessing an uninitialized sync obj = %d", + sync_obj); + return -EINVAL; + } + return 0; +} + int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms) { unsigned long timeleft; diff --git a/drivers/cam_sync/cam_sync_api.h b/drivers/cam_sync/cam_sync_api.h index bce22226f7c2..a46e37b31b10 100644 --- a/drivers/cam_sync/cam_sync_api.h +++ b/drivers/cam_sync/cam_sync_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __CAM_SYNC_API_H__ @@ -140,6 +140,16 @@ int cam_sync_destroy(int32_t sync_obj); */ int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms); +/** + * @brief: Check if sync object is valid + * + * @param sync_obj: int referencing the sync object to be checked + * + * @return 0 upon success, -EINVAL if sync object is in bad state or arguments + * are invalid + */ +int cam_sync_check_valid(int32_t sync_obj); + /** * @brief : API to register SYNC to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. From 2b9a25929a77ddd01e7f61548f487110a75a5b07 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 11 Mar 2020 15:55:05 -0700 Subject: [PATCH 309/790] msm: camera: ife: Subscribe to error IRQs only on slave core This change adds a check for slave core in dual IFE usecases to avoid subscribing to SOF/EOF/EPOCH IRQs. We can use IRQs from single core to drive our state machine. Error IRQs must still be subscribed to as earlier. CRs-Fixed: 2639855 Change-Id: I6aa6ab5b7e1049cd12f702da560b9b4a6ba9562b Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 130 ++++-------------- .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 9 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 5 + 3 files changed, 42 insertions(+), 102 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 69713cc8fd6a..7ee21351e581 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6900,63 +6900,6 @@ static int cam_ife_hw_mgr_handle_hw_rup( return 0; } -static int cam_ife_hw_mgr_check_irq_for_dual_vfe( - struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx, - uint32_t hw_event_type) -{ - int32_t rc = -1; - uint32_t *event_cnt = NULL; - uint32_t master_hw_idx; - uint32_t slave_hw_idx; - - if (!ife_hw_mgr_ctx->is_dual) - return 0; - - switch (hw_event_type) { - case CAM_ISP_HW_EVENT_SOF: - event_cnt = ife_hw_mgr_ctx->sof_cnt; - break; - case CAM_ISP_HW_EVENT_EPOCH: - event_cnt = ife_hw_mgr_ctx->epoch_cnt; - break; - case CAM_ISP_HW_EVENT_EOF: - event_cnt = ife_hw_mgr_ctx->eof_cnt; - break; - default: - return 0; - } - - master_hw_idx = ife_hw_mgr_ctx->master_hw_idx; - slave_hw_idx = ife_hw_mgr_ctx->slave_hw_idx; - - if (event_cnt[master_hw_idx] == event_cnt[slave_hw_idx]) { - - event_cnt[master_hw_idx] = 0; - event_cnt[slave_hw_idx] = 0; - - rc = 0; - return rc; - } - - if ((event_cnt[master_hw_idx] && - (event_cnt[master_hw_idx] - event_cnt[slave_hw_idx] > 1)) || - (event_cnt[slave_hw_idx] && - (event_cnt[slave_hw_idx] - event_cnt[master_hw_idx] > 1))) { - - CAM_ERR_RATE_LIMIT(CAM_ISP, - "One of the VFE could not generate hw event %d master[%d] core_cnt %d slave[%d] core_cnt %d", - hw_event_type, master_hw_idx, event_cnt[master_hw_idx], - slave_hw_idx, event_cnt[slave_hw_idx]); - rc = -1; - return rc; - } - - CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d", - hw_event_type); - - return rc; -} - static int cam_ife_hw_mgr_handle_hw_epoch( void *ctx, void *evt_info) @@ -6965,25 +6908,19 @@ static int cam_ife_hw_mgr_handle_hw_epoch( struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; cam_hw_event_cb_func ife_hw_irq_epoch_cb; struct cam_isp_hw_epoch_event_data epoch_done_event_data; - int rc = 0; ife_hw_irq_epoch_cb = ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EPOCH]; switch (event_info->res_id) { case CAM_ISP_HW_VFE_IN_CAMIF: - ife_hw_mgr_ctx->epoch_cnt[event_info->hw_idx]++; - rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, - CAM_ISP_HW_EVENT_EPOCH); - if (!rc) { - if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) - break; + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + + epoch_done_event_data.frame_id_meta = event_info->th_reg_val; + ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); - epoch_done_event_data.frame_id_meta = - event_info->th_reg_val; - ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); - } break; case CAM_ISP_HW_VFE_IN_RDI0: @@ -7014,7 +6951,6 @@ static int cam_ife_hw_mgr_handle_hw_sof( struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; cam_hw_event_cb_func ife_hw_irq_sof_cb; struct cam_isp_hw_sof_event_data sof_done_event_data; - int rc = 0; memset(&sof_done_event_data, 0, sizeof(sof_done_event_data)); @@ -7024,30 +6960,26 @@ static int cam_ife_hw_mgr_handle_hw_sof( switch (event_info->res_id) { case CAM_ISP_HW_VFE_IN_CAMIF: case CAM_ISP_HW_VFE_IN_RD: - ife_hw_mgr_ctx->sof_cnt[event_info->hw_idx]++; - rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, - CAM_ISP_HW_EVENT_SOF); - if (!rc) { - if (ife_hw_mgr_ctx->is_offline) - cam_ife_hw_mgr_get_offline_sof_timestamp( - &sof_done_event_data.timestamp, - &sof_done_event_data.boot_time); - else - cam_ife_mgr_cmd_get_sof_timestamp( - ife_hw_mgr_ctx, - &sof_done_event_data.timestamp, - &sof_done_event_data.boot_time); + if (ife_hw_mgr_ctx->is_offline) + cam_ife_hw_mgr_get_offline_sof_timestamp( + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); + else + cam_ife_mgr_cmd_get_sof_timestamp( + ife_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); - /* if frame header is enabled reset qtimer ts */ - if (ife_hw_mgr_ctx->use_frame_header_ts) - sof_done_event_data.timestamp = 0x0; + /* if frame header is enabled reset qtimer ts */ + if (ife_hw_mgr_ctx->use_frame_header_ts) + sof_done_event_data.timestamp = 0x0; - if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) - break; + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + + ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); - ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); - } break; case CAM_ISP_HW_VFE_IN_RDI0: @@ -7089,22 +7021,18 @@ static int cam_ife_hw_mgr_handle_hw_eof( struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; cam_hw_event_cb_func ife_hw_irq_eof_cb; struct cam_isp_hw_eof_event_data eof_done_event_data; - int rc = 0; ife_hw_irq_eof_cb = ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EOF]; switch (event_info->res_id) { case CAM_ISP_HW_VFE_IN_CAMIF: - ife_hw_mgr_ctx->eof_cnt[event_info->hw_idx]++; - rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx, - CAM_ISP_HW_EVENT_EOF); - if (!rc) { - if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) - break; - ife_hw_irq_eof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); - } + if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) + break; + + ife_hw_irq_eof_cb(ife_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + break; case CAM_ISP_HW_VFE_IN_RDI0: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index c776888c9871..bcc67aad48d2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -48,6 +48,7 @@ struct cam_vfe_mux_camif_data { bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; + uint32_t is_dual; }; static int cam_vfe_camif_get_evt_payload( @@ -256,6 +257,7 @@ int cam_vfe_camif_ver2_acquire_resource( camif_data->last_line = acquire_data->vfe_in.in_port->line_stop; camif_data->event_cb = acquire_data->event_cb; camif_data->priv = acquire_data->priv; + camif_data->is_dual = acquire_data->vfe_in.is_dual; CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d", camif_res->hw_intf->hw_idx, @@ -433,6 +435,10 @@ static int cam_vfe_camif_resource_start( rsrc_data->camif_reg->vfe_diag_config); } + if ((rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) && + rsrc_data->is_dual) + goto subscribe_err; + if (!rsrc_data->irq_handle) { rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, @@ -450,6 +456,7 @@ static int cam_vfe_camif_resource_start( } } +subscribe_err: if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index a8533c11f60a..b335b9e1e4c7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -500,6 +500,10 @@ static int cam_vfe_camif_ver3_resource_start( err_irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS2] = rsrc_data->reg_data->error_irq_mask2; + if ((rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) && + rsrc_data->is_dual) + goto subscribe_err; + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = rsrc_data->reg_data->epoch0_irq_mask | rsrc_data->reg_data->eof_irq_mask; @@ -546,6 +550,7 @@ static int cam_vfe_camif_ver3_resource_start( } } +subscribe_err: if (!rsrc_data->irq_err_handle) { rsrc_data->irq_err_handle = cam_irq_controller_subscribe_irq( rsrc_data->vfe_irq_controller, From 89feb6b2ae3248e9ea242869903cf37545094a59 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 13 Mar 2020 13:31:58 -0700 Subject: [PATCH 310/790] msm: camera: ife: Remove check for intra-client mask Intra-client mask is unused in Bus version 2.0 hardware and can be removed. CRs-Fixed: 2641529 Change-Id: I89b3620496995dbef8a6b09718f20a419ccf632c Signed-off-by: Venkat Chinta --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 62 +------------------ 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 87a0b72f1dfc..7ccc462756e2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -34,7 +34,6 @@ static const char drv_name[] = "vfe_bus"; #define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFFFF #define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFFFF -#define CAM_VFE_BUS_VER3_INTRA_CLIENT_MASK 0x3 #define MAX_BUF_UPDATE_REG_NUM \ ((sizeof(struct cam_vfe_bus_ver3_reg_offset_bus_client) + \ @@ -253,57 +252,6 @@ static int cam_vfe_bus_ver3_put_evt_payload( return 0; } -static int cam_vfe_bus_ver3_get_intra_client_mask( - enum cam_vfe_bus_ver3_vfe_core_id dual_slave_core, - enum cam_vfe_bus_ver3_vfe_core_id current_core, - uint32_t *intra_client_mask) -{ - int rc = 0; - uint32_t version_based_intra_client_mask = 0x1; - - *intra_client_mask = 0; - - if (dual_slave_core == current_core) { - CAM_ERR(CAM_ISP, - "Invalid params. Same core as Master and Slave"); - return -EINVAL; - } - - switch (current_core) { - case CAM_VFE_BUS_VER3_VFE_CORE_0: - switch (dual_slave_core) { - case CAM_VFE_BUS_VER3_VFE_CORE_1: - *intra_client_mask = version_based_intra_client_mask; - break; - default: - CAM_ERR(CAM_ISP, "Invalid value for slave core %u", - dual_slave_core); - rc = -EINVAL; - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_CORE_1: - switch (dual_slave_core) { - case CAM_VFE_BUS_VER3_VFE_CORE_0: - *intra_client_mask = version_based_intra_client_mask; - break; - default: - CAM_ERR(CAM_ISP, "Invalid value for slave core %u", - dual_slave_core); - rc = -EINVAL; - break; - } - break; - default: - CAM_ERR(CAM_ISP, - "Invalid value for master core %u", current_core); - rc = -EINVAL; - break; - } - - return rc; -} - static bool cam_vfe_bus_ver3_can_be_secure(uint32_t out_type) { switch (out_type) { @@ -1558,15 +1506,7 @@ static int cam_vfe_bus_ver3_acquire_comp_grp( rsrc_data = comp_grp_local->res_priv; if (!previously_acquired) { - if (is_dual) { - rc = cam_vfe_bus_ver3_get_intra_client_mask( - dual_slave_core, - comp_grp_local->hw_intf->hw_idx, - &rsrc_data->intra_client_mask); - if (rc) - return rc; - } - + rsrc_data->intra_client_mask = 0x1; comp_grp_local->tasklet_info = tasklet; comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; From a913f342a065c6eaf5a9aa654b629818e6b7e112 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Thu, 29 Aug 2019 12:35:25 -0700 Subject: [PATCH 311/790] msm: camera: isp: Add trace events across ISP Add trace events for IRQ's on IFE top side and IFE BUS side in top half. These traces when enabled will help to gather relative timing information of the IRQ's with systrace. CRs-Fixed: 2538876 Change-Id: I856a9df1978f90e260da7c62cadf02fa2fe53202 Signed-off-by: Vishalsingh Hajeri Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cdm/cam_cdm_hw_core.c | 18 ++++++++++++- drivers/cam_isp/cam_isp_context.c | 20 +++++++++++++-- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 25 +++++++++++++++++-- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 22 ++++++++++++++++ drivers/cam_utils/cam_trace.h | 23 +++++++++++++++++ 5 files changed, 103 insertions(+), 5 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index e5a8efeb6e70..d815408ca5be 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -23,6 +23,7 @@ #include "cam_cdm_hw_reg_1_2.h" #include "cam_cdm_hw_reg_2_0.h" #include "camera_main.h" +#include "cam_trace.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 #define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff @@ -689,6 +690,8 @@ int cam_hw_cdm_submit_gen_irq( rc = -EIO; } + trace_cam_log_event("CDM_START", "CDM_START_IRQ", req->data->cookie, 0); + end: return rc; } @@ -1159,7 +1162,20 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) INIT_WORK((struct work_struct *)&payload[i]->work, cam_hw_cdm_work); - work_status = queue_work( + trace_cam_log_event("CDM_DONE", "CDM_DONE_IRQ", + payload[i]->irq_status, + cdm_hw->soc_info.index); + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_clear, + payload[i]->irq_status)) { + CAM_ERR(CAM_CDM, + "Failed to Write CDM HW IRQ Clear"); + kfree(payload[i]); + return IRQ_HANDLED; + } + + work_status = queue_work( cdm_core->bl_fifo[i].work_queue, &payload[i]->work); diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5f05139af252..fce96b55f6a8 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -757,15 +757,26 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( "Resource Handles that fail to generate buf_done in prev frame"); for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) { - if (isp_device_type == CAM_IFE_DEVICE_TYPE) + if (isp_device_type == CAM_IFE_DEVICE_TYPE) { handle_type = __cam_isp_resource_handle_id_to_type( req_isp->fence_map_out[i].resource_handle); - else + + trace_cam_log_event("Buf_done Congestion", + __cam_isp_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle), + request_id, req_isp->fence_map_out[i].sync_id); + } else { handle_type = __cam_isp_tfe_resource_handle_id_to_type( req_isp->fence_map_out[i].resource_handle); + trace_cam_log_event("Buf_done Congestion", + __cam_isp_tfe_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle), + request_id, req_isp->fence_map_out[i].sync_id); + } + CAM_WARN(CAM_ISP, "Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]", handle_type, @@ -848,6 +859,9 @@ static int __cam_isp_ctx_handle_buf_done_for_request( "Duplicate BUF_DONE for req %lld : i=%d, j=%d, res=%s", req->request_id, i, j, handle_type); + trace_cam_log_event("Duplicate BufDone", + handle_type, req->request_id, ctx->ctx_id); + if (done_next_req) { done_next_req->resource_handle [done_next_req->num_handles++] = @@ -1528,6 +1542,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, CAM_WARN(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); + trace_cam_log_event("Bubble", "Rcvd epoch in applied state", + req->request_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 87a0b72f1dfc..64ee54816ab8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -23,6 +23,7 @@ #include "cam_vfe_soc.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include "cam_trace.h" static const char drv_name[] = "vfe_bus"; @@ -918,6 +919,7 @@ static int cam_vfe_bus_ver3_handle_rup_top_half(uint32_t evt_id, struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_irq_evt_payload *evt_payload; + uint32_t irq_status; vfe_out = th_payload->handler_priv; if (!vfe_out) { @@ -946,6 +948,12 @@ static int cam_vfe_bus_ver3_handle_rup_top_half(uint32_t evt_id, evt_payload->evt_id = evt_id; for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + irq_status = + th_payload->evt_status_arr[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; + + trace_cam_log_event("RUP", "RUP_IRQ", irq_status, 0); + th_payload->evt_payload_priv = evt_payload; return rc; @@ -2240,6 +2248,8 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_irq_evt_payload *evt_payload; + struct cam_vfe_bus_ver3_comp_grp_data *resource_data; + uint32_t status_0; vfe_out = th_payload->handler_priv; if (!vfe_out) { @@ -2248,6 +2258,7 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, } rsrc_data = vfe_out->res_priv; + resource_data = rsrc_data->comp_grp->res_priv; CAM_DBG(CAM_ISP, "VFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", rsrc_data->common_data->core_index, @@ -2276,6 +2287,17 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, th_payload->evt_payload_priv = evt_payload; + status_0 = th_payload->evt_status_arr[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; + + if (status_0 & BIT(resource_data->comp_grp_type + + rsrc_data->common_data->comp_done_shift)) { + trace_cam_log_event("bufdone", "bufdone_IRQ", + status_0, resource_data->comp_grp_type); + } + + if (status_0 & 0x1) + trace_cam_log_event("UnexpectedRUP", "RUP_IRQ", status_0, 40); + CAM_DBG(CAM_ISP, "Exit"); return rc; } @@ -3759,7 +3781,6 @@ int cam_vfe_bus_ver3_init( struct cam_vfe_bus *vfe_bus_local; struct cam_vfe_bus_ver3_hw_info *ver3_hw_info = bus_hw_info; struct cam_vfe_soc_private *soc_private = NULL; - static const char rup_controller_name[] = "vfe_bus_rup"; CAM_DBG(CAM_ISP, "Enter"); @@ -3825,7 +3846,7 @@ int cam_vfe_bus_ver3_init( goto free_bus_priv; } - rc = cam_irq_controller_init(rup_controller_name, + rc = cam_irq_controller_init("vfe_bus_rup", bus_priv->common_data.mem_base, &ver3_hw_info->common_reg.irq_reg_info, &bus_priv->common_data.rup_irq_controller, false); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index a8533c11f60a..afa7cb36d3f1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -18,6 +18,7 @@ #include "cam_debug_util.h" #include "cam_cdm_util.h" #include "cam_cpas_api.h" +#include "cam_trace.h" #define CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX 2 @@ -1240,6 +1241,27 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, th_payload->evt_payload_priv = evt_payload; + if (th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->sof_irq_mask) { + trace_cam_log_event("SOF", "TOP_HALF", + th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1], + camif_node->hw_intf->hw_idx); + } + + if (th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->epoch0_irq_mask) { + trace_cam_log_event("EPOCH0", "TOP_HALF", + th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1], + camif_node->hw_intf->hw_idx); + } + + if (th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->eof_irq_mask) { + trace_cam_log_event("EOF", "TOP_HALF", + th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1], + camif_node->hw_intf->hw_idx); + } + CAM_DBG(CAM_ISP, "Exit"); return rc; } diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h index 838997590771..c564b1582a3a 100644 --- a/drivers/cam_utils/cam_trace.h +++ b/drivers/cam_utils/cam_trace.h @@ -63,6 +63,29 @@ TRACE_EVENT(cam_isp_activated_irq, ) ); +TRACE_EVENT(cam_log_event, + TP_PROTO(const char *string1, const char *string2, + uint64_t val1, uint64_t val2), + TP_ARGS(string1, string2, val1, val2), + TP_STRUCT__entry( + __string(string1, string1) + __string(string2, string2) + __field(uint64_t, val1) + __field(uint64_t, val2) + ), + TP_fast_assign( + __assign_str(string1, string1); + __assign_str(string2, string2); + __entry->val1 = val1; + __entry->val2 = val2; + ), + TP_printk( + "%s: %s val1=%llu val2=%llu", + __get_str(string1), __get_str(string2), + __entry->val1, __entry->val2 + ) +); + TRACE_EVENT(cam_icp_fw_dbg, TP_PROTO(char *dbg_message, uint64_t timestamp), TP_ARGS(dbg_message, timestamp), From 3009b33966474039ee444c53c6b86277d208a8f0 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 18 Mar 2020 17:52:57 -0700 Subject: [PATCH 312/790] msm: camera: cpas: Add missing axi port name info During apply vote axi port name is coming as null. Add missing axi port name info in cpas layer also for more descriptive log during apply. CRs-Fixed: 2584631 Change-Id: Ibf99b542101a39c415157797e36b5605962873cb Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_soc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index 1a34b2409f11..a7550a397405 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -343,6 +343,9 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, } } + cpas_core->axi_port[mnoc_idx].axi_port_name = + cpas_core->axi_port[mnoc_idx] + .bus_client.common_data.name; cpas_core->axi_port [mnoc_idx].ib_bw_voting_needed = of_property_read_bool(curr_node, From 438fc6a8771c1b79bdacd6d6fd461b40f8083673 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Sat, 14 Mar 2020 12:55:38 -0700 Subject: [PATCH 313/790] msm: camera: common: Enabling EOF support for flash New usecase for flash driver requires to be trigger at EOF. This change adds the new operation code support in flash driver along with EOF enable support in crm and across other drivers. Also to improve the performance, this change adds the logic to dynamically update the subscribe event to CRM, so that CRM can enqueue EOF events when Flash or any other device add the request for EOF. CRs-Fixed: 2633194 Change-Id: I2f68ac7fc6a4699debd39b64319728cdf17bbcfa Signed-off-by: Jigarkumar Zala --- drivers/cam_isp/cam_isp_context.c | 4 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 169 +++++++++++++++--- drivers/cam_req_mgr/cam_req_mgr_core.h | 40 +++-- drivers/cam_req_mgr/cam_req_mgr_interface.h | 23 +-- .../cam_actuator/cam_actuator_core.c | 1 + .../cam_flash/cam_flash_core.c | 105 ++++++++++- .../cam_flash/cam_flash_dev.h | 15 +- .../cam_sensor/cam_sensor_core.c | 1 + .../cam_sensor_utils/cam_sensor_cmn_header.h | 1 + 9 files changed, 295 insertions(+), 64 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5f05139af252..f7dda7d2029b 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3910,6 +3910,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; add_req.skip_before_applying = 0; + add_req.trigger_eof = false; rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_ISP, "Add req failed: req id=%llu", @@ -4525,7 +4526,8 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx, ctx->link_hdl = link->link_hdl; ctx->ctx_crm_intf = link->crm_cb; - ctx_isp->subscribe_event = link->subscribe_event; + ctx_isp->subscribe_event = + CAM_TRIGGER_POINT_SOF | CAM_TRIGGER_POINT_EOF; ctx_isp->trigger_id = link->trigger_id; /* change state only if we had the init config */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 51604fda6a1f..c78e8e39879b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -49,6 +49,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->initial_skip = true; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; + atomic_set(&link->eof_event_cnt, 0); } void cam_req_mgr_handle_core_shutdown(void) @@ -456,10 +457,15 @@ static void __cam_req_mgr_flush_req_slot( tbl->pd, idx, tbl->slot[idx].state); tbl->slot[idx].req_ready_map = 0; tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; + tbl->slot[idx].ops.apply_at_eof = false; + tbl->slot[idx].ops.skip_next_frame = false; + tbl->slot[idx].ops.dev_hdl = -1; + tbl->slot[idx].ops.is_applied = false; tbl = tbl->next; } } + atomic_set(&link->eof_event_cnt, 0); in_q->wr_idx = 0; in_q->rd_idx = 0; } @@ -502,6 +508,10 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, tbl->pd, idx, tbl->slot[idx].state); tbl->slot[idx].req_ready_map = 0; tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; + tbl->slot[idx].ops.apply_at_eof = false; + tbl->slot[idx].ops.skip_next_frame = false; + tbl->slot[idx].ops.dev_hdl = -1; + tbl->slot[idx].ops.is_applied = false; tbl = tbl->next; } } @@ -668,6 +678,10 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.re_apply = true; } + /* + * This For loop is to address the special operation requested + * by device + */ for (i = 0; i < link->num_devs; i++) { dev = &link->l_dev[i]; if (!dev) @@ -681,37 +695,76 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, idx = link->req.apply_data[pd].idx; slot = &dev->pd_tbl->slot[idx]; - /* - * Just let flash go for this request and other - * device get restricted - */ - if ((slot->skip_next_frame != true) || - (slot->dev_hdl != dev->dev_hdl)) + if (slot->ops.dev_hdl < 0) { + CAM_DBG(CAM_CRM, + "No special ops detected for this table slot"); continue; + } - if (!(dev->dev_info.trigger & trigger)) + if (slot->ops.apply_at_eof && slot->ops.skip_next_frame) { + CAM_ERR(CAM_CRM, + "Both EOF and SOF trigger is not supported"); + return -EINVAL; + } + + if (dev->dev_hdl != slot->ops.dev_hdl) { + CAM_DBG(CAM_CRM, + "Dev_hdl : %d Not matched:: Expected dev_hdl: %d", + dev->dev_hdl, slot->ops.dev_hdl); continue; + } + + /* This one is to prevent EOF request to apply on SOF*/ + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (slot->ops.apply_at_eof)) { + CAM_DBG(CAM_CRM, "EOF event cannot be applied at SOF"); + break; + } + + if ((trigger == CAM_TRIGGER_POINT_EOF) && + (!slot->ops.apply_at_eof)) { + CAM_DBG(CAM_CRM, "NO EOF DATA FOR REQ: %llu", + link->req.apply_data[pd].req_id); + break; + } apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = link->req.apply_data[pd].req_id; apply_req.trigger_point = trigger; - if (dev->ops && dev->ops->apply_req) { + if ((dev->ops) && (dev->ops->apply_req) && + (!slot->ops.is_applied)) { rc = dev->ops->apply_req(&apply_req); if (rc) { *failed_dev = dev; return rc; } - CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd: %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); - slot->skip_next_frame = false; - slot->is_applied = true; + } + + CAM_DBG(CAM_REQ, + "SEND: link_hdl: %x pd: %d req_id %lld", + link->link_hdl, pd, apply_req.request_id); + + if (trigger == CAM_TRIGGER_POINT_SOF && + slot->ops.skip_next_frame) { + slot->ops.skip_next_frame = false; + slot->ops.is_applied = true; return -EAGAIN; + } else if ((trigger == CAM_TRIGGER_POINT_EOF) && + (slot->ops.apply_at_eof)) { + slot->ops.apply_at_eof = false; + if (atomic_read(&link->eof_event_cnt) > 0) + atomic_dec(&link->eof_event_cnt); + CAM_DBG(CAM_REQ, + "Req_id: %llu eof_event_cnt : %d", + link->req.apply_data[pd].req_id, + link->eof_event_cnt); + return 0; } } + /* For regular send requests */ for (i = 0; i < link->num_devs; i++) { dev = &link->l_dev[i]; if (dev) { @@ -739,12 +792,29 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.report_if_bubble = in_q->slot[idx].recover; - if ((slot->dev_hdl == dev->dev_hdl) && - (slot->is_applied == true)) { - slot->is_applied = false; + if ((slot->ops.dev_hdl == dev->dev_hdl) && + (slot->ops.is_applied)) { + slot->ops.is_applied = false; continue; } + /* + * If apply_at_eof is enabled do not apply at SOF + * e.x. Flash device + */ + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (dev->dev_hdl == slot->ops.dev_hdl) && + (slot->ops.apply_at_eof)) + continue; + + /* + * If apply_at_eof is not enabled ignore EOF + */ + if ((trigger == CAM_TRIGGER_POINT_EOF) && + (dev->dev_hdl == slot->ops.dev_hdl) && + (!slot->ops.apply_at_eof)) + continue; + apply_req.trigger_point = trigger; CAM_DBG(CAM_REQ, "SEND: link_hdl: %x pd %d req_id %lld", @@ -1507,6 +1577,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->trigger_mask == link->subscribe_event) { slot->status = CRM_SLOT_STATUS_REQ_APPLIED; link->trigger_mask = 0; + if (!(atomic_read(&link->eof_event_cnt)) && + (trigger == CAM_TRIGGER_POINT_EOF)) { + link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF; + CAM_DBG(CAM_CRM, + "Update link subscribe_event: %d", + link->subscribe_event); + } CAM_DBG(CAM_CRM, "req %d is applied on link %x", slot->req_id, link->link_hdl); @@ -1591,11 +1668,19 @@ static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl, */ static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay) { + int i = 0; + struct cam_req_mgr_req_tbl *tbl = kzalloc(sizeof(struct cam_req_mgr_req_tbl), GFP_KERNEL); if (tbl != NULL) { tbl->num_slots = MAX_REQ_SLOTS; CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots); + for (i = 0; i < MAX_REQ_SLOTS; i++) { + tbl->slot[i].ops.apply_at_eof = false; + tbl->slot[i].ops.skip_next_frame = false; + tbl->slot[i].ops.dev_hdl = -1; + tbl->slot[i].ops.is_applied = false; + } } return tbl; @@ -2310,17 +2395,27 @@ int cam_req_mgr_process_add_req(void *priv, void *data) } slot = &tbl->slot[idx]; - slot->is_applied = false; + slot->ops.is_applied = false; if ((add_req->skip_before_applying & 0xFF) > slot->inject_delay) { slot->inject_delay = (add_req->skip_before_applying & 0xFF); - slot->dev_hdl = add_req->dev_hdl; - if (add_req->skip_before_applying & SKIP_NEXT_FRAME) - slot->skip_next_frame = true; + if (add_req->skip_before_applying & SKIP_NEXT_FRAME) { + slot->ops.skip_next_frame = true; + slot->ops.dev_hdl = add_req->dev_hdl; + } CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %llu", add_req->req_id, (add_req->skip_before_applying & 0xFF)); } + /* Used when Precise Flash is enabled */ + if ((add_req->trigger_eof) && (!add_req->skip_before_applying)) { + slot->ops.apply_at_eof = true; + slot->ops.dev_hdl = add_req->dev_hdl; + CAM_DBG(CAM_REQ, + "Req_id %llu added for EOF tigger for Device: %s", + add_req->req_id, device->dev_info.name); + } + if (slot->state != CRM_REQ_STATE_PENDING && slot->state != CRM_REQ_STATE_EMPTY) { CAM_WARN(CAM_CRM, @@ -2658,9 +2753,10 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) return -EINVAL; } - CAM_DBG(CAM_REQ, "dev name %s dev_hdl %d dev req %lld", + CAM_DBG(CAM_REQ, + "dev name %s dev_hdl %d dev req %lld, trigger_eof: %d", __cam_req_mgr_dev_handle_to_name(add_req->dev_hdl, link), - add_req->dev_hdl, add_req->req_id); + add_req->dev_hdl, add_req->req_id, add_req->trigger_eof); mutex_lock(&link->lock); spin_lock_bh(&link->link_state_spin_lock); @@ -2695,6 +2791,16 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) dev_req->link_hdl = add_req->link_hdl; dev_req->dev_hdl = add_req->dev_hdl; dev_req->skip_before_applying = add_req->skip_before_applying; + dev_req->trigger_eof = add_req->trigger_eof; + if (dev_req->trigger_eof) { + link->subscribe_event |= CAM_TRIGGER_POINT_EOF; + atomic_inc(&link->eof_event_cnt); + CAM_DBG(CAM_REQ, + "Req_id: %llu, eof_event_cnt: %d, link subscribe event: %d", + dev_req->req_id, link->eof_event_cnt, + link->subscribe_event); + } + task->process_cb = &cam_req_mgr_process_add_req; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); CAM_DBG(CAM_CRM, "X: dev %x dev req %lld", @@ -2935,6 +3041,12 @@ static int cam_req_mgr_cb_notify_trigger( trigger_id = trigger_data->trigger_id; + if ((!atomic_read(&link->eof_event_cnt)) && + (trigger_data->trigger == CAM_TRIGGER_POINT_EOF)) { + CAM_DBG(CAM_CRM, "Not any request to schedule at EOF"); + goto end; + } + spin_lock_bh(&link->link_state_spin_lock); if (link->state < CAM_CRM_LINK_STATE_READY) { CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); @@ -2943,7 +3055,8 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } - if ((link->watchdog) && (link->watchdog->pause_timer)) + if ((link->watchdog) && (link->watchdog->pause_timer) && + (trigger_data->trigger == CAM_TRIGGER_POINT_SOF)) link->watchdog->pause_timer = false; if (link->dual_trigger) { @@ -2963,7 +3076,9 @@ static int cam_req_mgr_cb_notify_trigger( } } - crm_timer_reset(link->watchdog); + if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) + crm_timer_reset(link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); task = cam_req_mgr_workq_get_task(link->workq); @@ -2974,7 +3089,8 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } task_data = (struct crm_task_payload *)task->payload; - task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF; + task_data->type = (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) ? + CRM_WORKQ_TASK_NOTIFY_SOF : CRM_WORKQ_TASK_NOTIFY_EOF; notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u; notify_trigger->frame_id = trigger_data->frame_id; notify_trigger->link_hdl = trigger_data->link_hdl; @@ -3022,8 +3138,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, if (link_info->u.link_info_v1.num_devices > CAM_REQ_MGR_MAX_HANDLES) return -EPERM; - } - else if (link_info->version == VERSION_2) { + } else if (link_info->version == VERSION_2) { if (link_info->u.link_info_v2.num_devices > CAM_REQ_MGR_MAX_HANDLES_V2) return -EPERM; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index df2d921e7c19..e406590c9499 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -49,6 +49,7 @@ enum crm_workq_task_type { CRM_WORKQ_TASK_DEV_ADD_REQ, CRM_WORKQ_TASK_APPLY_REQ, CRM_WORKQ_TASK_NOTIFY_SOF, + CRM_WORKQ_TASK_NOTIFY_EOF, CRM_WORKQ_TASK_NOTIFY_ERR, CRM_WORKQ_TASK_NOTIFY_FREEZE, CRM_WORKQ_TASK_SCHED_REQ, @@ -178,25 +179,39 @@ struct cam_req_mgr_apply { int32_t skip_idx; }; +/** + * struct crm_tbl_slot_special_ops + * @dev_hdl : Device handle who requested for special ops + * @apply_at_eof : Boolean Identifier for request to be applied at EOF + * @skip_next_frame : Flag to drop the frame after skip_before_apply frame + * @is_applied : Flag to identify if request is already applied to device + * in previous frame + */ +struct crm_tbl_slot_special_ops { + int32_t dev_hdl; + bool apply_at_eof; + bool skip_next_frame; + bool is_applied; +}; + /** * struct cam_req_mgr_tbl_slot * @idx : slot index * @req_ready_map : mask tracking which all devices have request ready * @state : state machine for life cycle of a slot * @inject_delay : insert extra bubbling for flash type of use cases - * @dev_hdl : stores the dev_hdl, who is having higher inject delay - * @skip_next_frame : flag to drop the frame after skip_before_apply frame - * @is_applied : flag to identify if request is already applied to - * device. + * @ops : special operation for the table slot + * e.g. + * skip_next frame: in case of applying one device + * and skip others + * apply_at_eof: device that needs to apply at EOF */ struct cam_req_mgr_tbl_slot { - int32_t idx; - uint32_t req_ready_map; - enum crm_req_state state; - uint32_t inject_delay; - int32_t dev_hdl; - bool skip_next_frame; - bool is_applied; + int32_t idx; + uint32_t req_ready_map; + enum crm_req_state state; + uint32_t inject_delay; + struct crm_tbl_slot_special_ops ops; }; /** @@ -348,6 +363,7 @@ struct cam_req_mgr_connected_device { * @dual_trigger : Links needs to wait for two triggers prior to * applying the settings * @trigger_cnt : trigger count value per device initiating the trigger + * @eof_event_cnt : Atomic variable to track the number of EOF requests */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -380,7 +396,7 @@ struct cam_req_mgr_core_link { uint64_t prev_sof_timestamp; bool dual_trigger; uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; - + atomic_t eof_event_cnt; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 4957bda64865..c40a479419e7 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -186,12 +186,13 @@ enum cam_req_mgr_device_id { /** * enum cam_req_mgr_link_evt_type - * @CAM_REQ_MGR_LINK_EVT_ERR : error on the link from any of the - * connected devices - * @CAM_REQ_MGR_LINK_EVT_PAUSE : to pause the link - * @CAM_REQ_MGR_LINK_EVT_RESUME : resumes the link which was paused - * @CAM_REQ_MGR_LINK_EVT_SOF_FREEZE : request manager has detected an sof freeze - * @CAM_REQ_MGR_LINK_EVT_MAX : invalid event type + * @CAM_REQ_MGR_LINK_EVT_ERR : error on the link from any of the + * connected devices + * @CAM_REQ_MGR_LINK_EVT_PAUSE : to pause the link + * @CAM_REQ_MGR_LINK_EVT_RESUME : resumes the link which was paused + * @CAM_REQ_MGR_LINK_EVT_SOF_FREEZE : request manager has detected an + * sof freeze + * @CAM_REQ_MGR_LINK_EVT_MAX : invalid event type */ enum cam_req_mgr_link_evt_type { CAM_REQ_MGR_LINK_EVT_ERR, @@ -261,12 +262,15 @@ struct cam_req_mgr_error_notify { * @req_id : req id which device is ready to process * @skip_before_applying : before applying req mgr introduce bubble * by not sending request to devices. ex: IFE and Flash + * @trigger_eof : to identify that one of the device at this slot needs + * to be apply at EOF */ struct cam_req_mgr_add_request { int32_t link_hdl; int32_t dev_hdl; uint64_t req_id; uint32_t skip_before_applying; + bool trigger_eof; }; @@ -355,15 +359,14 @@ struct cam_req_mgr_flush_request { /** * struct cam_req_mgr_event_data - * @link_hdl : link handle - * @req_id : request id - * @evt_type : link event + * @link_hdl : link handle + * @req_id : request id + * @evt_type : link event */ struct cam_req_mgr_link_evt_data { int32_t link_hdl; int32_t dev_hdl; uint64_t req_id; - enum cam_req_mgr_link_evt_type evt_type; union { enum cam_req_mgr_device_error error; diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 0b6e25572e90..06f98a01d1df 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -370,6 +370,7 @@ static void cam_actuator_update_req_mgr( add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl; add_req.skip_before_applying = 0; + add_req.trigger_eof = false; if (a_ctrl->bridge_intf.crm_cb && a_ctrl->bridge_intf.crm_cb->add_req) { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index da32761b5488..0e60442c4a75 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -11,6 +11,9 @@ #include "cam_common_util.h" #include "cam_packet_util.h" +static uint default_on_timer = 2; +module_param(default_on_timer, uint, 0644); + int cam_flash_led_prepare(struct led_trigger *trigger, int options, int *max_current, bool is_wled) { @@ -396,7 +399,8 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, cam_res_mgr_led_trigger_event( flash_ctrl->torch_trigger[i], curr); } - } else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) { + } else if ((op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) || + (op == CAMERA_SENSOR_FLASH_OP_FIREDURATION)) { for (i = 0; i < flash_ctrl->flash_num_sources; i++) { if (flash_ctrl->flash_trigger[i]) { max_current = soc_private->flash_max_current[i]; @@ -416,10 +420,39 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, return -EINVAL; } - if (flash_ctrl->switch_trigger) + if (flash_ctrl->switch_trigger) { +#if IS_ENABLED(CONFIG_LEDS_QTI_FLASH) + int rc = 0; + + if (op == CAMERA_SENSOR_FLASH_OP_FIREDURATION) { + struct flash_led_param param; + + param.off_time_ms = + flash_data->flash_active_time_ms; + /* This is to dynamically change the turn on time */ + param.on_time_ms = default_on_timer; + CAM_DBG(CAM_FLASH, + "Precise flash_on time: %u, Precise flash_off time: %u", + param.on_time_ms, param.off_time_ms); + rc = qti_flash_led_set_param( + flash_ctrl->switch_trigger, + param); + if (rc) { + CAM_ERR(CAM_FLASH, + "LED set param fail rc= %d", rc); + return rc; + } + } +#else + if (op == CAMERA_SENSOR_FLASH_OP_FIREDURATION) { + CAM_ERR(CAM_FLASH, "FIREDURATION op not supported"); + return -EINVAL; + } +#endif cam_res_mgr_led_trigger_event( flash_ctrl->switch_trigger, (enum led_brightness)LED_SWITCH_ON); + } return 0; } @@ -489,6 +522,30 @@ static int cam_flash_high( return rc; } +static int cam_flash_duration(struct cam_flash_ctrl *fctrl, + struct cam_flash_frame_setting *flash_data) +{ + int i = 0, rc = 0; + + if (!flash_data) { + CAM_ERR(CAM_FLASH, "Flash Data NULL"); + return -EINVAL; + } + + for (i = 0; i < fctrl->torch_num_sources; i++) + if (fctrl->torch_trigger[i]) + cam_res_mgr_led_trigger_event( + fctrl->torch_trigger[i], + LED_OFF); + + rc = cam_flash_ops(fctrl, flash_data, + CAMERA_SENSOR_FLASH_OP_FIREDURATION); + if (rc) + CAM_ERR(CAM_FLASH, "Fire PreciseFlash Failed: %d", rc); + + return rc; +} + static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl, uint64_t req_id) { @@ -850,6 +907,19 @@ int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, "Flash off failed %d", rc); goto apply_setting_err; } + } else if ((flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIREDURATION) && + (flash_data->cmn_attr.is_settings_valid) && + (flash_data->cmn_attr.request_id == req_id)) { + if (fctrl->flash_state == CAM_FLASH_STATE_START) { + rc = cam_flash_duration(fctrl, flash_data); + if (rc) { + CAM_ERR(CAM_FLASH, + "PreciaseFlash op failed:%d", + rc); + goto apply_setting_err; + } + } } else if (flash_data->opcode == CAM_PKT_NOP_OPCODE) { CAM_DBG(CAM_FLASH, "NOP Packet"); } else { @@ -1473,6 +1543,18 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) add_req.skip_before_applying |= SKIP_NEXT_FRAME; + + if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIREDURATION) { + add_req.trigger_eof = true; + /* Active time for the preflash */ + flash_data->flash_active_time_ms = + (flash_operation_info->time_on_duration_ns) + / 1000000; + CAM_DBG(CAM_FLASH, + "PRECISE FLASH: active_time: %llu", + flash_data->flash_active_time_ms); + } } break; default: @@ -1660,15 +1742,24 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) add_req.dev_hdl = fctrl->bridge_intf.device_hdl; if ((csl_packet->header.op_code & 0xFFFFF) == - CAM_FLASH_PACKET_OPCODE_SET_OPS) - add_req.skip_before_applying |= 1; - else + CAM_FLASH_PACKET_OPCODE_SET_OPS) { + if ((flash_data->opcode != + CAMERA_SENSOR_FLASH_OP_FIREDURATION)) + add_req.skip_before_applying |= 1; + else if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIREDURATION) + add_req.trigger_eof = true; + else + add_req.skip_before_applying = 0; + } else { add_req.skip_before_applying = 0; - + } + CAM_DBG(CAM_FLASH, + "add req to req_mgr= %lld:: trigger_eof: %d", + add_req.req_id, add_req.trigger_eof); if (fctrl->bridge_intf.crm_cb && fctrl->bridge_intf.crm_cb->add_req) fctrl->bridge_intf.crm_cb->add_req(&add_req); - CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); } return rc; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 64bb25308d41..b8416cd15d8b 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -108,13 +108,13 @@ struct cam_flash_init_packet { /** * struct flash_frame_setting - * @cmn_attr : Provides common attributes - * @num_iterations : Iterations used to perform RER - * @led_on_delay_ms : LED on time in milisec - * @led_off_delay_ms : LED off time in milisec - * @opcode : Command buffer opcode - * @led_current_ma[] : LED current array in miliamps - * + * @cmn_attr : Provides common attributes + * @num_iterations : Iterations used to perform RER + * @led_on_delay_ms : LED on time in milisec + * @led_off_delay_ms : LED off time in milisec + * @opcode : Command buffer opcode + * @led_current_ma[] : LED current array in miliamps + * @flash_active_time_ms : Flash_On time with precise flash */ struct cam_flash_frame_setting { struct cam_flash_common_attr cmn_attr; @@ -123,6 +123,7 @@ struct cam_flash_frame_setting { uint16_t led_off_delay_ms; int8_t opcode; uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; + uint64_t flash_active_time_ms; }; /** diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 696bbd3b90cb..762b0a65e0c2 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -25,6 +25,7 @@ static void cam_sensor_update_req_mgr( csl_packet->header.request_id); add_req.dev_hdl = s_ctrl->bridge_intf.device_hdl; add_req.skip_before_applying = 0; + add_req.trigger_eof = false; if (s_ctrl->bridge_intf.crm_cb && s_ctrl->bridge_intf.crm_cb->add_req) s_ctrl->bridge_intf.crm_cb->add_req(&add_req); diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 09d100c8f0a8..5889243dd38e 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -77,6 +77,7 @@ enum camera_flash_opcode { CAMERA_SENSOR_FLASH_OP_OFF, CAMERA_SENSOR_FLASH_OP_FIRELOW, CAMERA_SENSOR_FLASH_OP_FIREHIGH, + CAMERA_SENSOR_FLASH_OP_FIREDURATION, CAMERA_SENSOR_FLASH_OP_MAX, }; From ca48923671053821deb6d7d38b8bda83e5c7c4a0 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Fri, 28 Feb 2020 19:09:34 -0800 Subject: [PATCH 314/790] msm: camera: cdm: Enable internal CDM Add support to acquire IFE CDM instead of CPAS CDM. CRs-Fixed: 2571273 Change-Id: Iea3bcf236d00d39bf19e0997e6d21efcd5406a61 Signed-off-by: Jigar Agrawal Signed-off-by: Vishalsingh Hajeri --- drivers/cam_cdm/cam_cdm_hw_core.c | 12 +- drivers/cam_cdm/cam_cdm_intf_api.h | 8 + drivers/cam_isp/cam_isp_context.c | 230 +++-- drivers/cam_isp/cam_isp_context.h | 15 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 852 ++++++++++++------ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 19 +- drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h | 3 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 194 ++-- .../hw_utils/cam_isp_packet_parser.c | 356 ++++++-- .../hw_utils/include/cam_isp_packet_parser.h | 59 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 120 ++- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 3 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 2 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 92 ++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 103 +++ 15 files changed, 1519 insertions(+), 549 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index e5a8efeb6e70..762cb4090afd 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1654,8 +1654,7 @@ static int cam_hw_cdm_component_bind(struct device *dev, platform_set_drvdata(pdev, cdm_hw_intf); - snprintf(cdm_name, sizeof(cdm_name), "%s%d", - cdm_hw->soc_info.label_name, cdm_hw->soc_info.index); + snprintf(cdm_name, sizeof(cdm_name), "%s", cdm_hw->soc_info.label_name); rc = cam_smmu_get_handle(cdm_name, &cdm_core->iommu_hdl.non_secure); if (rc < 0) { @@ -1766,6 +1765,15 @@ static int cam_hw_cdm_component_bind(struct device *dev, } cdm_hw->open_count++; + cdm_core->ops = cam_cdm_get_ops(cdm_core->hw_version, NULL, + false); + + if (!cdm_core->ops) { + CAM_ERR(CAM_CDM, "Failed to util ops for hw"); + rc = -EINVAL; + goto deinit; + } + if (!cam_cdm_set_cam_hw_version(cdm_core->hw_version, &cdm_core->version)) { CAM_ERR(CAM_CDM, "Failed to set cam hw version for hw"); diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index 0c9508db41cf..37f1f1503ccd 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -222,6 +222,14 @@ int cam_cdm_stream_off(uint32_t handle); */ int cam_cdm_reset_hw(uint32_t handle); +/** + * @brief : API to publish CDM ops to HW blocks like IFE + * + * @return : CDM operations + * + */ +struct cam_cdm_utils_ops *cam_cdm_publish_ops(void); + /** * @brief : API to register CDM hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5f05139af252..cb9e6814b7f9 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -314,61 +314,71 @@ static int cam_isp_ctx_dump_req( size_t *offset, bool dump_to_buff) { - int i = 0, rc = 0; + int i, j, rc = 0; size_t len = 0; uint32_t *buf_addr; uint32_t *buf_start, *buf_end; - size_t remain_len = 0; + size_t remain_len = 0; struct cam_cdm_cmd_buf_dump_info dump_info; + uint32_t num_cfg; + struct cam_hw_update_entry *cfg; - for (i = 0; i < req_isp->num_cfg; i++) { - rc = cam_packet_util_get_cmd_mem_addr( - req_isp->cfg[i].handle, &buf_addr, &len); - if (rc) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "Failed to get_cmd_mem_addr, rc=%d", - rc); - } else { - if (req_isp->cfg[i].offset >= ((uint32_t)len)) { - CAM_ERR(CAM_ISP, - "Invalid offset exp %u actual %u", - req_isp->cfg[i].offset, (uint32_t)len); - return rc; - } - remain_len = len - req_isp->cfg[i].offset; - - if (req_isp->cfg[i].len > - ((uint32_t)remain_len)) { - CAM_ERR(CAM_ISP, - "Invalid len exp %u remain_len %u", - req_isp->cfg[i].len, - (uint32_t)remain_len); - return rc; - } - - 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 (dump_to_buff) { - if (!cpu_addr || !offset || !buf_len) { - CAM_ERR(CAM_ISP, "Invalid args"); - break; - } - dump_info.src_start = buf_start; - dump_info.src_end = buf_end; - dump_info.dst_start = cpu_addr; - dump_info.dst_offset = *offset; - dump_info.dst_max_size = buf_len; - rc = cam_cdm_util_dump_cmd_bufs_v2(&dump_info); - *offset = dump_info.dst_offset; - if (rc) - return rc; + for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) { + num_cfg = req_isp->cfg_info[j].num_hw_entries; + cfg = req_isp->cfg_info[j].hw_entries; + for (i = 0; i < num_cfg; i++) { + rc = cam_packet_util_get_cmd_mem_addr( + cfg[i].handle, &buf_addr, &len); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Failed to get_cmd_mem_addr, rc=%d", + rc); } else { - cam_cdm_util_dump_cmd_buf(buf_start, buf_end); + if (cfg[i].offset >= ((uint32_t)len)) { + CAM_ERR(CAM_ISP, + "Invalid offset exp %u actual %u", + cfg[i].offset, (uint32_t)len); + return -EINVAL; + } + remain_len = len - cfg[i].offset; + + if (req_isp->cfg_info[j].hw_entries[i].len > + ((uint32_t)remain_len)) { + CAM_ERR(CAM_ISP, + "Invalid len exp %u remain_len %u", + cfg[i].len, + (uint32_t)remain_len); + return -EINVAL; + } + + buf_start = (uint32_t *)((uint8_t *) buf_addr + + cfg[i].offset); + buf_end = (uint32_t *)((uint8_t *) buf_start + + cfg[i].len - 1); + + if (dump_to_buff) { + if (!cpu_addr || !offset || !buf_len) { + CAM_ERR(CAM_ISP, + "Invalid args"); + break; + } + dump_info.src_start = buf_start; + dump_info.src_end = buf_end; + dump_info.dst_start = cpu_addr; + dump_info.dst_offset = *offset; + dump_info.dst_max_size = buf_len; + rc = cam_cdm_util_dump_cmd_bufs_v2( + &dump_info); + *offset = dump_info.dst_offset; + if (rc) + return rc; + } else + cam_cdm_util_dump_cmd_buf(buf_start, + buf_end); } } } + return rc; } @@ -419,13 +429,17 @@ static int __cam_isp_ctx_enqueue_request_in_order( static int __cam_isp_ctx_enqueue_init_request( struct cam_context *ctx, struct cam_ctx_request *req) { - int rc = 0; + int rc = 0, i = 0; struct cam_ctx_request *req_old; struct cam_isp_ctx_req *req_isp_old; struct cam_isp_ctx_req *req_isp_new; struct cam_isp_prepare_hw_update_data *req_update_old; struct cam_isp_prepare_hw_update_data *req_update_new; struct cam_isp_prepare_hw_update_data *hw_update_data; + struct cam_hw_update_entry *cfg_old; + struct cam_hw_update_entry *cfg_new; + uint32_t num_cfg_old; + uint32_t num_cfg_new; spin_lock_bh(&ctx->lock); if (list_empty(&ctx->pending_req_list)) { @@ -441,9 +455,12 @@ static int __cam_isp_ctx_enqueue_init_request( req_isp_new = (struct cam_isp_ctx_req *) req->req_priv; if (req_isp_old->hw_update_data.packet_opcode_type == CAM_ISP_PACKET_INIT_DEV) { - if ((req_isp_old->num_cfg + req_isp_new->num_cfg) >= + if ((req_isp_old->total_num_cfg + req_isp_new->total_num_cfg) >= CAM_ISP_CTX_CFG_MAX) { - CAM_WARN(CAM_ISP, "Can not merge INIT pkt"); + CAM_WARN(CAM_ISP, + "Can not merge INIT pkt total_num_cfgs = %d", + (req_isp_old->total_num_cfg + + req_isp_new->total_num_cfg)); rc = -ENOMEM; } @@ -468,11 +485,19 @@ static int __cam_isp_ctx_enqueue_init_request( req_isp_old->num_fence_map_in = req_isp_new->num_fence_map_in; - memcpy(&req_isp_old->cfg[req_isp_old->num_cfg], - req_isp_new->cfg, - sizeof(req_isp_new->cfg[0])* - req_isp_new->num_cfg); - req_isp_old->num_cfg += req_isp_new->num_cfg; + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + cfg_old = req_isp_old->cfg_info[i].hw_entries; + cfg_new = req_isp_new->cfg_info[i].hw_entries; + num_cfg_old = + req_isp_old->cfg_info[i].num_hw_entries; + num_cfg_new = + req_isp_old->cfg_info[i].num_hw_entries; + memcpy(&cfg_old[num_cfg_old], + cfg_new, + sizeof(cfg_new[0]) * num_cfg_new); + req_isp_old->cfg_info[i].num_hw_entries + += num_cfg_new; + } memcpy(&req_old->pf_data, &req->pf_data, sizeof(struct cam_hw_mgr_dump_pf_data)); @@ -1049,12 +1074,12 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( static int __cam_isp_ctx_apply_req_offline( void *priv, void *data) { - int rc = 0; + int rc = 0, i = 0; struct cam_context *ctx = NULL; struct cam_isp_context *ctx_isp = priv; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; - struct cam_hw_config_args cfg; + struct cam_isp_hw_config_args cfg; if (!ctx_isp) { CAM_ERR(CAM_ISP, "Invalid ctx_isp:%pK", ctx); @@ -1088,8 +1113,12 @@ static int __cam_isp_ctx_apply_req_offline( cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; cfg.request_id = req->request_id; - cfg.hw_update_entries = req_isp->cfg; - cfg.num_hw_update_entries = req_isp->num_cfg; + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + cfg.hw_update_info[i].num_hw_entries = + req_isp->cfg_info[i].num_hw_entries; + cfg.hw_update_info[i].hw_entries = + req_isp->cfg_info[i].hw_entries; + } cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; @@ -2455,13 +2484,13 @@ static int __cam_isp_ctx_apply_req_in_activated_state( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, enum cam_isp_ctx_activated_substate next_state) { - int rc = 0; + int rc = 0, i; struct cam_ctx_request *req; struct cam_ctx_request *active_req = NULL; struct cam_isp_ctx_req *req_isp; struct cam_isp_ctx_req *active_req_isp; struct cam_isp_context *ctx_isp = NULL; - struct cam_hw_config_args cfg; + struct cam_isp_hw_config_args isp_cfg; if (list_empty(&ctx->pending_req_list)) { CAM_ERR(CAM_ISP, "No available request for Apply id %lld", @@ -2547,15 +2576,22 @@ static int __cam_isp_ctx_apply_req_in_activated_state( } req_isp->bubble_report = apply->report_if_bubble; - cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; - cfg.request_id = req->request_id; - cfg.hw_update_entries = req_isp->cfg; - cfg.num_hw_update_entries = req_isp->num_cfg; - cfg.priv = &req_isp->hw_update_data; - cfg.init_packet = 0; - cfg.reapply = req_isp->reapply; + memset(&isp_cfg, 0, sizeof(isp_cfg)); - rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + isp_cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; + isp_cfg.request_id = req->request_id; + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + isp_cfg.hw_update_info[i].num_hw_entries = + req_isp->cfg_info[i].num_hw_entries; + isp_cfg.hw_update_info[i].hw_entries = + req_isp->cfg_info[i].hw_entries; + } + isp_cfg.priv = &req_isp->hw_update_data; + isp_cfg.init_packet = 0; + isp_cfg.reapply = req_isp->reapply; + + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, + &isp_cfg); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); } else { @@ -3759,7 +3795,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( struct cam_packet *packet; size_t len = 0; size_t remain_len = 0; - struct cam_hw_prepare_update_args cfg; + struct cam_isp_hw_update_args isp_cfg; struct cam_req_mgr_add_request add_req; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; @@ -3840,31 +3876,43 @@ static int __cam_isp_ctx_config_dev_in_top_state( } /* 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; - cfg.max_out_map_entries = CAM_ISP_CTX_RES_MAX; - cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX; - cfg.out_map_entries = req_isp->fence_map_out; - cfg.in_map_entries = req_isp->fence_map_in; - cfg.priv = &req_isp->hw_update_data; - cfg.pf_data = &(req->pf_data); + memset(&isp_cfg, 0, sizeof(isp_cfg)); + + isp_cfg.packet = packet; + isp_cfg.remain_len = remain_len; + isp_cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; + isp_cfg.max_hw_update_entries = CAM_ISP_CTX_CFG_MAX; + isp_cfg.max_out_map_entries = CAM_ISP_CTX_RES_MAX; + isp_cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX; + isp_cfg.out_map_entries = req_isp->fence_map_out; + isp_cfg.in_map_entries = req_isp->fence_map_in; + isp_cfg.priv = &req_isp->hw_update_data; + isp_cfg.pf_data = &(req->pf_data); + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) + isp_cfg.hw_update_info[i].hw_entries + = req_isp->cfg_info[i].hw_entries; CAM_DBG(CAM_ISP, "try to prepare config packet......"); rc = ctx->hw_mgr_intf->hw_prepare_update( - ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + ctx->hw_mgr_intf->hw_mgr_priv, &isp_cfg); if (rc != 0) { CAM_ERR(CAM_ISP, "Prepare config packet failed in HW layer"); rc = -EFAULT; goto free_req; } - req_isp->num_cfg = cfg.num_hw_update_entries; - req_isp->num_fence_map_out = cfg.num_out_map_entries; - req_isp->num_fence_map_in = cfg.num_in_map_entries; + + req_isp->total_num_cfg = 0; + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + req_isp->cfg_info[i].num_hw_entries + = isp_cfg.hw_update_info[i].num_hw_entries; + req_isp->total_num_cfg += + req_isp->cfg_info[i].num_hw_entries; + } + + req_isp->num_fence_map_out = isp_cfg.num_out_map_entries; + req_isp->num_fence_map_in = isp_cfg.num_in_map_entries; req_isp->num_acked = 0; req_isp->bubble_detected = false; @@ -3878,7 +3926,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( } CAM_DBG(CAM_ISP, "num_entry: %d, num fence out: %d, num fence in: %d", - req_isp->num_cfg, req_isp->num_fence_map_out, + req_isp->total_num_cfg, req_isp->num_fence_map_out, req_isp->num_fence_map_in); req->request_id = packet->header.request_id; @@ -4604,8 +4652,14 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.hw_config.request_id = req->request_id; - start_isp.hw_config.hw_update_entries = req_isp->cfg; - start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg; + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + start_isp.hw_config.hw_update_info[i].hw_entries + = req_isp->cfg_info[i].hw_entries; + start_isp.hw_config.hw_update_info[i].num_hw_entries = + req_isp->cfg_info[i].num_hw_entries; + } + start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 2baabe8b2412..a05e44221af8 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -26,12 +26,6 @@ */ #define CAM_ISP_CTX_RES_MAX 24 -/* - * Maximum configuration entry size - This is based on the - * worst case DUAL IFE use case plus some margin. - */ -#define CAM_ISP_CTX_CFG_MAX 22 - /* * Maximum entries in state monitoring array for error logging */ @@ -135,8 +129,8 @@ struct cam_isp_ctx_irq_ops { * struct cam_isp_ctx_req - ISP context request object * * @base: Common request object ponter - * @cfg: ISP hardware configuration array - * @num_cfg: Number of ISP hardware configuration entries + * @cfg_info: ISP hardware configuration array + * @total_num_cfg: Number of ISP hardware configuration entries * @fence_map_out: Output fence mapping array * @num_fence_map_out: Number of the output fence map * @fence_map_in: Input fence mapping array @@ -153,9 +147,8 @@ struct cam_isp_ctx_irq_ops { */ struct cam_isp_ctx_req { struct cam_ctx_request *base; - - struct cam_hw_update_entry cfg[CAM_ISP_CTX_CFG_MAX]; - uint32_t num_cfg; + struct cam_isp_hw_update_info cfg_info[CAM_IFE_HW_NUM_MAX]; + uint32_t total_num_cfg; struct cam_hw_fence_map_entry fence_map_out [CAM_ISP_CTX_RES_MAX]; uint32_t num_fence_map_out; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7ee21351e581..d1cf9fd3eb50 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1419,7 +1419,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; break; default: - CAM_ERR(CAM_ISP, "Wrong IFE CSID Resource Node"); + CAM_ERR(CAM_ISP, "Wrong IFE CSID Path Resource ID : %d", + csid_res->res_id); goto err; } ife_src_res->res_type = vfe_acquire.rsrc_type; @@ -1473,7 +1474,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( ife_src_res->hw_res[i]->res_id); CAM_DBG(CAM_ISP, - "acquire success IFE:%d res type :0x%x res id:0x%x", + "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); @@ -1849,6 +1850,17 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); cid_res->num_children++; + if (is_ipp) { + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (master_idx == i) + ife_ctx->master_slave[i] = CAM_IFE_RES_MASTER; + else + ife_ctx->master_slave[i] = CAM_IFE_RES_SLAVE; + CAM_DBG(CAM_ISP, "hw %d, slave/master %d", + i, ife_ctx->master_slave[i]); + } + } + CAM_DBG(CAM_ISP, "acquire res %d CID children = %d", csid_acquire.res_id, cid_res->num_children); @@ -2590,8 +2602,10 @@ err: void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, enum cam_cdm_cb_status status, uint64_t cookie) { - struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; - struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + int i; + uint32_t idx = 0; if (!userdata) { CAM_ERR(CAM_ISP, "Invalid args"); @@ -2601,10 +2615,27 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata; ctx = (struct cam_ife_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; + if (!ctx->internal_cdm) + idx = 0; + else { + for (i = 0; i < ctx->num_base; i++) { + if (ctx->cdm_handle[ctx->base[i].idx] == handle) { + idx = ctx->base[i].idx; + break; + } + } + + if (i == ctx->num_base) { + CAM_ERR(CAM_ISP, "Incorrect CDM handle=0x%x", handle); + return; + } + } + if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { - complete_all(&ctx->config_done_complete); + complete_all(&ctx->config_done_complete[idx]); atomic_set(&ctx->cdm_done, 1); - if (g_ife_hw_mgr.debug_cfg.per_req_reg_dump) + if ((g_ife_hw_mgr.debug_cfg.per_req_reg_dump) && + (idx == ctx->master_hw_idx)) cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, hw_update_data->num_reg_dump_buf, @@ -2612,11 +2643,11 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, NULL, false); CAM_DBG(CAM_ISP, - "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", + "Called by CDM hdl=0x%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", + "Called by CDM hdl=0x%x, udata=%pK, status=%d, cookie=%llu", handle, userdata, status, cookie); } } @@ -2850,7 +2881,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) struct cam_ife_hw_mgr *ife_hw_mgr = hw_mgr_priv; struct cam_hw_acquire_args *acquire_args = acquire_hw_args; int rc = -1; - int i, j; + int i, j = 0, k; struct cam_ife_hw_mgr_ctx *ife_ctx; struct cam_isp_in_port_generic_info *in_port = NULL; struct cam_cdm_acquire_data cdm_acquire; @@ -2862,6 +2893,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) uint32_t total_pd_port = 0; struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; uint32_t input_size = 0; + uint32_t hw_version, idx; CAM_DBG(CAM_ISP, "Enter..."); @@ -2878,39 +2910,15 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } ife_ctx->custom_enabled = false; + memset(ife_ctx->cdm_handle, 0, sizeof(ife_ctx->cdm_handle)); + ife_ctx->common.cb_priv = acquire_args->context_data; + ife_ctx->internal_cdm = false; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) ife_ctx->common.event_cb[i] = acquire_args->event_cb; ife_ctx->hw_mgr = ife_hw_mgr; - - - memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); - cdm_acquire.cell_index = 0; - cdm_acquire.handle = 0; - cdm_acquire.userdata = ife_ctx; - cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; - for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - if (ife_hw_mgr->cdm_reg_map[i]) - cdm_acquire.base_array[j++] = - ife_hw_mgr->cdm_reg_map[i]; - } - - cdm_acquire.base_array_cnt = j; - cdm_acquire.priority = CAM_CDM_BL_FIFO_0; - cdm_acquire.id = CAM_CDM_VIRTUAL; - cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; - rc = cam_cdm_acquire(&cdm_acquire); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); - goto free_ctx; - } - - CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x", - cdm_acquire.handle); - ife_ctx->cdm_handle = cdm_acquire.handle; - ife_ctx->cdm_ops = cdm_acquire.ops; - atomic_set(&ife_ctx->cdm_done, 1); + ife_ctx->cdm_ops = cam_cdm_publish_ops(); acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; @@ -2986,9 +2994,44 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) rc = cam_ife_mgr_process_base_info(ife_ctx); if (rc) { CAM_ERR(CAM_ISP, "Process base info failed"); - goto free_res; + goto free_cdm; } + cam_cpas_get_cpas_hw_version(&hw_version); + ife_ctx->hw_version = hw_version; + + for (k = 0; k < ife_ctx->num_base; k++) { + CAM_DBG(CAM_ISP, "Acquire cdm for ife_hw_idx %d", + ife_ctx->base[k].idx); + + memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); + cdm_acquire.cell_index = ife_ctx->base[k].idx; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ife_ctx; + if (ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]) + cdm_acquire.base_array[j++] = + ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]; + cdm_acquire.base_array_cnt = j; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_cdm; + } + + CAM_DBG(CAM_ISP, + "Successfully acquired CDM id=0%d, handle :0x%x", + cdm_acquire.id, cdm_acquire.handle); + if (cdm_acquire.id == CAM_CDM_IFE) + ife_ctx->internal_cdm = true; + ife_ctx->cdm_handle[ife_ctx->base[k].idx] = cdm_acquire.handle; + ife_ctx->base[k].cdm_id = cdm_acquire.id; + } + + atomic_set(&ife_ctx->cdm_done, 1); + acquire_args->ctxt_to_hw_map = ife_ctx; acquire_args->custom_enabled = ife_ctx->custom_enabled; acquire_args->use_frame_header_ts = ife_ctx->use_frame_header_ts; @@ -3009,11 +3052,14 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) free_mem: kfree(in_port->data); kfree(in_port); +free_cdm: + for (i = 0; i < ife_ctx->num_base; i++) { + idx = ife_ctx->base[i].idx; + if (ife_ctx->cdm_handle[idx] != 0) + cam_cdm_release(ife_ctx->cdm_handle[idx]); + } free_res: cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); -free_cdm: - cam_cdm_release(ife_ctx->cdm_handle); -free_ctx: cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); err: CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); @@ -3069,7 +3115,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) struct cam_ife_hw_mgr *ife_hw_mgr = hw_mgr_priv; struct cam_hw_acquire_args *acquire_args = acquire_hw_args; int rc = -1; - int i, j; + int i, j = 0, k; struct cam_ife_hw_mgr_ctx *ife_ctx; struct cam_isp_in_port_info *in_port = NULL; struct cam_isp_resource *isp_resource = NULL; @@ -3082,6 +3128,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; uint32_t in_port_length = 0; + uint32_t hw_version, idx; CAM_DBG(CAM_ISP, "Enter..."); @@ -3097,39 +3144,15 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto err; } + memset(ife_ctx->cdm_handle, 0, sizeof(ife_ctx->cdm_handle)); + ife_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) ife_ctx->common.event_cb[i] = acquire_args->event_cb; ife_ctx->hw_mgr = ife_hw_mgr; - - memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); - cdm_acquire.cell_index = 0; - cdm_acquire.handle = 0; - cdm_acquire.userdata = ife_ctx; - cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; - for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - if (ife_hw_mgr->cdm_reg_map[i]) - cdm_acquire.base_array[j++] = - ife_hw_mgr->cdm_reg_map[i]; - } - - cdm_acquire.base_array_cnt = j; - cdm_acquire.priority = CAM_CDM_BL_FIFO_0; - cdm_acquire.id = CAM_CDM_VIRTUAL; - cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; - rc = cam_cdm_acquire(&cdm_acquire); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); - goto free_ctx; - } - - CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x", - cdm_acquire.handle); - ife_ctx->cdm_handle = cdm_acquire.handle; - ife_ctx->cdm_ops = cdm_acquire.ops; - atomic_set(&ife_ctx->cdm_done, 1); + ife_ctx->cdm_ops = cam_cdm_publish_ops(); isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; @@ -3240,6 +3263,40 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto free_res; } + cam_cpas_get_cpas_hw_version(&hw_version); + + ife_ctx->hw_version = hw_version; + + for (k = 0; k < ife_ctx->num_base; k++) { + CAM_DBG(CAM_ISP, "Acquire cdm for ife_hw_idx %d", k); + + memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); + cdm_acquire.cell_index = ife_ctx->base[k].idx; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ife_ctx; + if (ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]) + cdm_acquire.base_array[j++] = + ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]; + cdm_acquire.base_array_cnt = j; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_res; + } + + CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=0x%x", + cdm_acquire.handle); + + if (cdm_acquire.id == CAM_CDM_IFE) + ife_ctx->internal_cdm = true; + ife_ctx->cdm_handle[ife_ctx->base[k].idx] = cdm_acquire.handle; + } + + atomic_set(&ife_ctx->cdm_done, 1); + acquire_args->ctxt_to_hw_map = ife_ctx; ife_ctx->ctx_in_use = 1; ife_ctx->num_reg_dump_buf = 0; @@ -3252,8 +3309,11 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) return 0; free_res: cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); - cam_cdm_release(ife_ctx->cdm_handle); -free_ctx: + for (i = 0; i < ife_ctx->num_base; i++) { + idx = ife_ctx->base[i].idx; + if (ife_ctx->cdm_handle[idx] != 0) + cam_cdm_release(ife_ctx->cdm_handle[idx]); + } cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); err: CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); @@ -3556,17 +3616,197 @@ static int cam_isp_blob_bw_update( return rc; } +static int cam_ife_config_hw_internal_cdm(struct cam_ife_hw_mgr_ctx *ctx, + struct cam_isp_hw_config_args *cfg, + struct cam_isp_prepare_hw_update_data *hw_update_data) +{ + int rc = -1, i, j, skip = 0; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + uint32_t num_ent; + struct cam_hw_update_entry *cfg_info; + unsigned long rem_jiffies = 0; + uint32_t idx; + + if (ctx->num_base >= CAM_IFE_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, + "Invalid number of IFE acquired = %d", + ctx->num_base); + return -EINVAL; + } + + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + num_ent = cfg->hw_update_info[idx].num_hw_entries; + cfg_info = cfg->hw_update_info[idx].hw_entries; + if (num_ent > 0) { + cdm_cmd = ctx->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; + skip = 0; + + for (j = 0 ; j < num_ent; j++) { + cmd = (cfg_info + j); + + if (cfg->reapply && + cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, + "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[j - skip].bl_addr.mem_handle = + cmd->handle; + cdm_cmd->cmd[j - skip].offset = cmd->offset; + cdm_cmd->cmd[j - skip].len = cmd->len; + cdm_cmd->cmd[j - skip].arbitrate = false; + } + cdm_cmd->cmd_arrary_count = num_ent - skip; + + reinit_completion(&ctx->config_done_complete[idx]); + ctx->applied_req_id = cfg->request_id; + + CAM_DBG(CAM_ISP, "Submit to CDM for IFE idx = %d", + ctx->base[i].idx); + atomic_set(&ctx->cdm_done, 0); + rc = cam_cdm_submit_bls(ctx->cdm_handle[idx], cdm_cmd); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to apply the configs for req %llu, rc %d", + cfg->request_id, rc); + return rc; + } + } + } + + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + if (cfg->init_packet) { + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete[idx], + msecs_to_jiffies(30)); + if (rem_jiffies == 0) { + CAM_ERR(CAM_ISP, + "config done completion timeout for req_id=%llu ctx_index %d IFE:%d", + cfg->request_id, + ctx->ctx_index, idx); + rc = -ETIMEDOUT; + } else + CAM_DBG(CAM_ISP, + "config done Success for req_id=%llu ctx_index %d IFE:%d", + cfg->request_id, + ctx->ctx_index, idx); + } + } + + return rc; +} + +static int cam_ife_config_hw_external_cdm(struct cam_ife_hw_mgr_ctx *ctx, + struct cam_isp_hw_config_args *cfg, + struct cam_isp_prepare_hw_update_data *hw_update_data) +{ + int rc = -1, i, j, k = 0, skip = 0; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + uint32_t num_ent; + struct cam_hw_update_entry *cfg_info; + unsigned long rem_jiffies = 0; + + if (ctx->num_base >= CAM_IFE_HW_NUM_MAX) { + CAM_ERR(CAM_ISP, + "Invalid number of IFE acquired = %d", + ctx->num_base); + return -EINVAL; + } + + cdm_cmd = ctx->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; + cdm_cmd->cmd_arrary_count = 0; + + for (i = 0; i < ctx->num_base; i++) { + num_ent = cfg->hw_update_info[ctx->base[i].idx].num_hw_entries; + cfg_info = cfg->hw_update_info[ctx->base[i].idx].hw_entries; + if (num_ent > 0) { + for (j = 0 ; j < num_ent; j++) { + cmd = (cfg_info + j); + + if (cfg->reapply && + cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, + "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[j - skip + k].bl_addr.mem_handle = + cmd->handle; + cdm_cmd->cmd[j - skip + k].offset = cmd->offset; + cdm_cmd->cmd[j - skip + k].len = cmd->len; + cdm_cmd->cmd[j - skip + k].arbitrate = false; + } + cdm_cmd->cmd_arrary_count += num_ent - skip; + k = cdm_cmd->cmd_arrary_count; + } + } + + ctx->applied_req_id = cfg->request_id; + CAM_DBG(CAM_ISP, "Submit to CDM for IFE idx = %d", + ctx->base[i].idx); + atomic_set(&ctx->cdm_done, 0); + reinit_completion(&ctx->config_done_complete[0]); + rc = cam_cdm_submit_bls(ctx->cdm_handle[ctx->base[0].idx], cdm_cmd); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to apply the configs for req %llu, rc %d", + cfg->request_id, rc); + return rc; + } + + if (cfg->init_packet) { + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete[0], + msecs_to_jiffies(30)); + if (rem_jiffies == 0) { + CAM_ERR(CAM_ISP, + "config done completion timeout for req_id=%llu ctx_index %d IFE:%d", + cfg->request_id, + ctx->ctx_index, ctx->base[0].idx); + rc = -ETIMEDOUT; + } else + CAM_DBG(CAM_ISP, + "config done Success for req_id=%llu ctx_index %d IFE:%d", + cfg->request_id, + ctx->ctx_index, ctx->base[0].idx); + } + + return rc; +} + /* entry function: config_hw */ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) { - int rc = -1, i, skip = 0; - struct cam_hw_config_args *cfg; - struct cam_hw_update_entry *cmd; - struct cam_cdm_bl_request *cdm_cmd; + int rc = -1, i, idx; + struct cam_isp_hw_config_args *cfg; struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; - unsigned long rem_jiffies = 0; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, @@ -3602,18 +3842,18 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - if (hw_update_data->bw_config_valid[i] == true) { + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + if (hw_update_data->bw_config_valid[idx] == true) { CAM_DBG(CAM_PERF, "idx=%d, bw_config_version=%d", - ctx, ctx->ctx_index, i, - hw_update_data->bw_config_version); + idx, hw_update_data->bw_config_version); if (hw_update_data->bw_config_version == CAM_ISP_BW_CONFIG_V1) { rc = cam_isp_blob_bw_update( (struct cam_isp_bw_config *) - &hw_update_data->bw_config[i], ctx); + &hw_update_data->bw_config[idx], ctx); if (rc) CAM_ERR(CAM_PERF, "Bandwidth Update Failed rc: %d", rc); @@ -3621,7 +3861,8 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_ISP_BW_CONFIG_V2) { rc = cam_isp_blob_bw_update_v2( (struct cam_isp_bw_config_v2 *) - &hw_update_data->bw_config_v2[i], ctx); + &hw_update_data->bw_config_v2[idx], + ctx); if (rc) CAM_ERR(CAM_PERF, "Bandwidth Update Failed rc: %d", rc); @@ -3635,68 +3876,19 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, } 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); + "Enter ctx id:%d request id: %llu", ctx->ctx_index, + cfg->request_id); - if (cfg->num_hw_update_entries > 0) { - cdm_cmd = ctx->cdm_cmd; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = true; - cdm_cmd->userdata = hw_update_data; - cdm_cmd->cookie = cfg->request_id; - cdm_cmd->gen_irq_arb = false; + if (ctx->internal_cdm) + rc = cam_ife_config_hw_internal_cdm(ctx, cfg, hw_update_data); + else + rc = cam_ife_config_hw_external_cdm(ctx, cfg, hw_update_data); - for (i = 0 ; i < cfg->num_hw_update_entries; i++) { - cmd = (cfg->hw_update_entries + i); - - if (cfg->reapply && - cmd->flags == CAM_ISP_IQ_BL) { - skip++; - continue; - } - - if (cmd->flags == CAM_ISP_UNUSED_BL || - cmd->flags >= CAM_ISP_BL_MAX) - CAM_ERR(CAM_ISP, "Unexpected BL type %d", - cmd->flags); - - cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; - cdm_cmd->cmd[i - skip].offset = cmd->offset; - cdm_cmd->cmd[i - skip].len = cmd->len; - cdm_cmd->cmd[i - skip].arbitrate = false; - } - cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; - - reinit_completion(&ctx->config_done_complete); - ctx->applied_req_id = cfg->request_id; - - CAM_DBG(CAM_ISP, "Submit to CDM"); - atomic_set(&ctx->cdm_done, 0); - rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed to apply the configs for req %llu, rc %d", - cfg->request_id, rc); - return rc; - } - - if (cfg->init_packet) { - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies(30)); - if (rem_jiffies == 0) { - CAM_ERR(CAM_ISP, - "config done completion timeout for req_id=%llu ctx_index %d", - cfg->request_id, ctx->ctx_index); - rc = -ETIMEDOUT; - } else - CAM_DBG(CAM_ISP, - "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"); + if (rc) { + CAM_ERR(CAM_ISP, "Config HW failure"); + return rc; } + CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); return rc; @@ -3841,6 +4033,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) enum cam_ife_csid_halt_cmd csid_halt_type; uint32_t i, master_base_idx = 0; unsigned long rem_jiffies = 0; + uint32_t idx; if (!hw_mgr_priv || !stop_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -3941,18 +4134,40 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_pause_hw(ctx); - rem_jiffies = wait_for_completion_timeout(&ctx->config_done_complete, - msecs_to_jiffies(10)); - if (rem_jiffies == 0) - CAM_WARN(CAM_ISP, - "config done completion timeout for last applied req_id=%llu rc=%d ctx_index %d", - ctx->applied_req_id, rc, ctx->ctx_index); + if (ctx->internal_cdm) { + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete[idx], + msecs_to_jiffies(5)); + if (rem_jiffies == 0) + CAM_WARN(CAM_ISP, + "config done completion timeout for last applied req_id=%llu ctx_index %d IFE:%d", + ctx->applied_req_id, ctx->ctx_index, + idx); + } + } else { + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete[0], + msecs_to_jiffies(5)); + if (rem_jiffies == 0) + CAM_WARN(CAM_ISP, + "config done completion timeout for last applied req_id=%llu ctx_index %d IFE:%d", + ctx->applied_req_id, ctx->ctx_index, + ctx->master_hw_idx); + } if (stop_isp->stop_only) goto end; - if (cam_cdm_stream_off(ctx->cdm_handle)) - CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + if (ctx->cdm_handle[idx] != 0) { + if (cam_cdm_stream_off(ctx->cdm_handle[idx])) + CAM_ERR(CAM_ISP, "CDM stream off failed %d", + ctx->cdm_handle[i]); + } + } if (ctx->is_tpg) cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_tpg); @@ -4121,7 +4336,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *rsrc_node = NULL; - uint32_t i, camif_debug; + uint32_t i, camif_debug, idx; bool res_rdi_context_set = false; uint32_t primary_rdi_src_res; uint32_t primary_rdi_out_res; @@ -4215,12 +4430,16 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } mutex_unlock(&g_ife_hw_mgr.ctx_mutex); - CAM_DBG(CAM_ISP, "start cdm interface"); - rc = cam_cdm_stream_on(ctx->cdm_handle); - if (rc) { - CAM_ERR(CAM_ISP, "Can not start cdm (%d)", - ctx->cdm_handle); - goto safe_disable; + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + if (ctx->cdm_handle[idx] != 0) { + rc = cam_cdm_stream_on(ctx->cdm_handle[idx]); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start cdm (%d)", + ctx->cdm_handle); + goto safe_disable; + } + } } start_only: @@ -4348,8 +4567,10 @@ err: return rc; cdm_streamoff: - cam_cdm_stream_off(ctx->cdm_handle); - + for (i = 0; i < ctx->num_base; i++) { + if (ctx->cdm_handle[ctx->base[i].idx] != 0) + cam_cdm_stream_off(ctx->cdm_handle[ctx->base[i].idx]); + } safe_disable: cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE); @@ -4448,13 +4669,16 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, memset(ctx->base, 0, sizeof(ctx->base)); /* release cdm handle */ - cam_cdm_release(ctx->cdm_handle); + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (ctx->cdm_handle[i] != 0) + cam_cdm_release(ctx->cdm_handle[i]); + ctx->cdm_handle[i] = 0; + } /* clean context */ list_del_init(&ctx->list); ctx->ctx_in_use = 0; ctx->is_rdi_only_context = 0; - ctx->cdm_handle = 0; ctx->cdm_ops = NULL; ctx->num_reg_dump_buf = 0; ctx->custom_enabled = false; @@ -4483,7 +4707,7 @@ 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_isp_hw_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -4555,13 +4779,14 @@ static int cam_isp_blob_ubwc_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_ubwc_config *ubwc_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ubwc_plane_cfg_v1 *ubwc_plane_cfg; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - uint32_t res_id_out, i; + struct cam_hw_update_entry *hw_entry; + uint32_t res_id_out, i, slot_idx = 0; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; @@ -4575,10 +4800,14 @@ static int cam_isp_blob_ubwc_update( goto end; } - if ((prepare->num_hw_update_entries + 1) >= + slot_idx = blob_info->base_info->idx; + hw_entry = prepare->hw_update_info[slot_idx].hw_entries; + num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; + + if ((num_ent + 1) >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d", - prepare->num_hw_update_entries, + num_ent, prepare->max_hw_update_entries); rc = -EINVAL; goto end; @@ -4650,18 +4879,18 @@ static int cam_isp_blob_ubwc_update( if (total_used_bytes) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = + hw_entry[num_ent].handle = kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = + hw_entry[num_ent].len = total_used_bytes; - prepare->hw_update_entries[num_ent].offset = + hw_entry[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[slot_idx].num_hw_entries + = num_ent; } break; default: @@ -4726,12 +4955,13 @@ static int cam_isp_blob_ubwc_update_v2( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_ubwc_config_v2 *ubwc_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ubwc_plane_cfg_v2 *ubwc_plane_cfg; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_update_entry *hw_entry; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; @@ -4739,6 +4969,7 @@ static int cam_isp_blob_ubwc_update_v2( uint32_t bytes_used = 0; int num_ent, rc = 0; struct cam_vfe_generic_ubwc_config generic_ubwc_cfg; + uint32_t slot_idx; ctx = prepare->ctxt_to_hw_map; if (!ctx) { @@ -4747,10 +4978,14 @@ static int cam_isp_blob_ubwc_update_v2( goto end; } - if (prepare->num_hw_update_entries + 1 >= + slot_idx = blob_info->base_info->idx; + hw_entry = prepare->hw_update_info[slot_idx].hw_entries; + num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; + + if (num_ent + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d", - prepare->num_hw_update_entries, + prepare->hw_update_info[slot_idx].num_hw_entries, prepare->max_hw_update_entries); rc = -EINVAL; goto end; @@ -4823,18 +5058,18 @@ static int cam_isp_blob_ubwc_update_v2( if (total_used_bytes) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = + hw_entry[num_ent].handle = kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = + hw_entry[num_ent].len = total_used_bytes; - prepare->hw_update_entries[num_ent].offset = + hw_entry[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[slot_idx].num_hw_entries + = num_ent; } end: return rc; @@ -4844,13 +5079,14 @@ static int cam_isp_blob_hfr_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_resource_hfr_config *hfr_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_isp_port_hfr_config *port_hfr_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - uint32_t res_id_out, i; + struct cam_hw_update_entry *hw_entry; + uint32_t res_id_out, i, slot_idx = 0; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; @@ -4861,11 +5097,15 @@ static int cam_isp_blob_hfr_update( CAM_DBG(CAM_ISP, "num_ports= %d", hfr_config->num_ports); + slot_idx = blob_info->base_info->idx; + hw_entry = prepare->hw_update_info[slot_idx].hw_entries; + num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; + /* Max one hw entries required for hfr config update */ - if (prepare->num_hw_update_entries + 1 >= + if (prepare->hw_update_info[slot_idx].num_hw_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->num_hw_update_entries, + prepare->hw_update_info[slot_idx].num_hw_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -4923,17 +5163,17 @@ static int cam_isp_blob_hfr_update( if (total_used_bytes) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = + hw_entry[num_ent].handle = kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = total_used_bytes; - prepare->hw_update_entries[num_ent].offset = + hw_entry[num_ent].len = + total_used_bytes; + hw_entry[num_ent].offset = kmd_buf_info->offset; num_ent++; - kmd_buf_info->used_bytes += total_used_bytes; - kmd_buf_info->offset += total_used_bytes; - prepare->num_hw_update_entries = num_ent; + kmd_buf_info->offset += total_used_bytes; + prepare->hw_update_info[slot_idx].num_hw_entries + = num_ent; } return rc; @@ -4943,7 +5183,7 @@ static int cam_isp_blob_csid_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_csid_clock_config *clock_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -4990,7 +5230,7 @@ static int cam_isp_blob_csid_qcfa_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_csid_qcfa_config *qcfa_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5038,7 +5278,7 @@ static int cam_isp_blob_core_cfg_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_core_config *core_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5093,7 +5333,7 @@ static int cam_isp_blob_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_clock_config *clock_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5203,26 +5443,30 @@ static int cam_isp_blob_vfe_out_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_vfe_out_config *vfe_out_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_isp_vfe_wm_config *wm_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *ife_out_res; + struct cam_hw_update_entry *hw_entry; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; uint32_t bytes_used = 0; + uint32_t slot_idx = 0; int num_ent, rc = 0; ctx = prepare->ctxt_to_hw_map; + slot_idx = blob_info->base_info->idx; + hw_entry = prepare->hw_update_info[slot_idx].hw_entries; + num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; - if (prepare->num_hw_update_entries + 1 >= + if (num_ent + 1 >= prepare->max_hw_update_entries) { - CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->num_hw_update_entries, - prepare->max_hw_update_entries); + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d", + num_ent); return -EINVAL; } @@ -5278,17 +5522,17 @@ static int cam_isp_blob_vfe_out_update( } if (total_used_bytes) { - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = + hw_entry[num_ent].handle = kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = total_used_bytes; - prepare->hw_update_entries[num_ent].offset = + hw_entry[num_ent].len = + total_used_bytes; + hw_entry[num_ent].offset = kmd_buf_info->offset; num_ent++; - kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[slot_idx].num_hw_entries + = num_ent; } return rc; @@ -5298,7 +5542,7 @@ static int cam_isp_blob_csid_config_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_csid_epd_config *epd_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5343,9 +5587,9 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { int rc = 0; - struct cam_isp_generic_blob_info *blob_info = user_data; - struct cam_hw_prepare_update_args *prepare = NULL; - struct cam_ife_hw_mgr_ctx *ife_mgr_ctx = NULL; + struct cam_isp_generic_blob_info *blob_info = user_data; + struct cam_ife_hw_mgr_ctx *ife_mgr_ctx = NULL; + struct cam_isp_hw_update_args *prepare = NULL; if (!blob_data || (blob_size == 0) || !blob_info) { CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK", @@ -5883,12 +6127,13 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { int rc = 0; - struct cam_hw_prepare_update_args *prepare = - (struct cam_hw_prepare_update_args *) prepare_hw_update_args; + struct cam_isp_hw_update_args *ife_cfg = + (struct cam_isp_hw_update_args *) prepare_hw_update_args; + struct cam_ife_hw_mgr_ctx *ctx; struct cam_ife_hw_mgr *hw_mgr; struct cam_kmd_buf_info kmd_buf; - uint32_t i; + uint32_t i, idx; bool fill_fence = true; bool frame_header_enable = false; struct cam_isp_prepare_hw_update_data *prepare_hw_data; @@ -5900,22 +6145,22 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) - prepare->priv; + ife_cfg->priv; - ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map; + ctx = (struct cam_ife_hw_mgr_ctx *) ife_cfg->ctxt_to_hw_map; hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv; CAM_DBG(CAM_REQ, "ctx[%pK][%d] Enter for req_id %lld", - ctx, ctx->ctx_index, prepare->packet->header.request_id); + ctx, ctx->ctx_index, ife_cfg->packet->header.request_id); - rc = cam_packet_util_validate_packet(prepare->packet, - prepare->remain_len); + rc = cam_packet_util_validate_packet(ife_cfg->packet, + ife_cfg->remain_len); if (rc) return rc; /* Pre parse the packet*/ - rc = cam_packet_util_get_kmd_buffer(prepare->packet, &kmd_buf); + rc = cam_packet_util_get_kmd_buffer(ife_cfg->packet, &kmd_buf); if (rc) return rc; @@ -5928,18 +6173,28 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, frame_header_enable = true; } - rc = cam_packet_util_process_patches(prepare->packet, - hw_mgr->mgr_common.cmd_iommu_hdl, - hw_mgr->mgr_common.cmd_iommu_hdl_secure); + if (ctx->internal_cdm) + rc = cam_packet_util_process_patches(ife_cfg->packet, + hw_mgr->mgr_common.img_iommu_hdl, + hw_mgr->mgr_common.img_iommu_hdl_secure); + else + rc = cam_packet_util_process_patches(ife_cfg->packet, + hw_mgr->mgr_common.cmd_iommu_hdl, + hw_mgr->mgr_common.cmd_iommu_hdl_secure); + if (rc) { CAM_ERR(CAM_ISP, "Patch ISP packet failed."); return rc; } - prepare->num_hw_update_entries = 0; - prepare->num_in_map_entries = 0; - prepare->num_out_map_entries = 0; - prepare->num_reg_dump_buf = 0; + + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + ife_cfg->hw_update_info[idx].num_hw_entries = 0; + } + ife_cfg->num_in_map_entries = 0; + ife_cfg->num_out_map_entries = 0; + ife_cfg->num_reg_dump_buf = 0; memset(&prepare_hw_data->bw_config[0], 0x0, sizeof(prepare_hw_data->bw_config[0]) * @@ -5948,23 +6203,42 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, sizeof(prepare_hw_data->bw_config_valid[0]) * CAM_IFE_HW_NUM_MAX); + /* Add reset trigger_cdm_event */ + if ((ctx->hw_version >= CAM_CPAS_TITAN_480_V100) && ctx->is_dual + && ctx->internal_cdm) { + for (i = 0; i < ctx->num_base; i++) { + if (ctx->master_slave[ctx->base[i].idx] + == CAM_IFE_RES_SLAVE && + ctx->base[i].cdm_id == CAM_CDM_IFE) + rc = cam_isp_add_wait_trigger(ife_cfg, + &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf, false); + } + } + for (i = 0; i < ctx->num_base; i++) { CAM_DBG(CAM_ISP, "process cmd buffer for device %d", i); + CAM_DBG(CAM_ISP, + "change base i=%d, idx=%d, ctx->internal_cdm = %d cdm_id = %d", + i, ctx->base[i].idx, ctx->internal_cdm, + ctx->base[i].cdm_id); + /* Add change base */ - rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf); - if (rc) { - CAM_ERR(CAM_ISP, + if (!ctx->internal_cdm || ctx->base[i].cdm_id == CAM_CDM_CPAS) { + rc = cam_isp_add_change_base(ife_cfg, + &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, "Failed in change base i=%d, idx=%d, rc=%d", i, ctx->base[i].idx, rc); - goto end; + goto end; + } } - - /* get command buffers */ if (ctx->base[i].split_id != CAM_ISP_HW_SPLIT_MAX) { - rc = cam_isp_add_command_buffers(prepare, &kmd_buf, + rc = cam_isp_add_command_buffers(ife_cfg, &kmd_buf, &ctx->base[i], cam_isp_packet_generic_blob_handler, ctx->res_list_ife_out, CAM_IFE_HW_OUT_RES_MAX); @@ -5988,7 +6262,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, rc = cam_isp_add_io_buffers( hw_mgr->mgr_common.img_iommu_hdl, hw_mgr->mgr_common.img_iommu_hdl_secure, - prepare, ctx->base[i].idx, + ife_cfg, ctx->base[i].idx, &kmd_buf, ctx->res_list_ife_out, &ctx->res_list_ife_in_rd, CAM_IFE_HW_OUT_RES_MAX, fill_fence, @@ -6018,11 +6292,10 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } - /* add go_cmd for offline context */ - if (prepare->num_out_map_entries && prepare->num_in_map_entries && + if (ife_cfg->num_out_map_entries && ife_cfg->num_in_map_entries && ctx->is_offline) { - rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd, + rc = cam_isp_add_go_cmd(ife_cfg, &ctx->res_list_ife_in_rd, ctx->base[i].idx, &kmd_buf); if (rc) CAM_ERR(CAM_ISP, @@ -6036,25 +6309,26 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, * bits to get the type of operation since UMD definition * of op_code has some difference from KMD. */ - if (((prepare->packet->header.op_code + 1) & 0xF) == + if (((ife_cfg->packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_INIT_DEV) { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV; - if ((!prepare->num_reg_dump_buf) || (prepare->num_reg_dump_buf > + if ((!ife_cfg->num_reg_dump_buf) || (ife_cfg->num_reg_dump_buf > CAM_REG_DUMP_MAX_BUF_ENTRIES)) goto end; if (!ctx->num_reg_dump_buf) { - ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; + ctx->num_reg_dump_buf = ife_cfg->num_reg_dump_buf; + memcpy(ctx->reg_dump_buf_desc, - prepare->reg_dump_buf_desc, + ife_cfg->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * - prepare->num_reg_dump_buf); + ife_cfg->num_reg_dump_buf); } else { prepare_hw_data->num_reg_dump_buf = - prepare->num_reg_dump_buf; + ife_cfg->num_reg_dump_buf; memcpy(prepare_hw_data->reg_dump_buf_desc, - prepare->reg_dump_buf_desc, + ife_cfg->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * prepare_hw_data->num_reg_dump_buf); } @@ -6062,32 +6336,49 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, goto end; } else { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV; - prepare_hw_data->num_reg_dump_buf = prepare->num_reg_dump_buf; + prepare_hw_data->num_reg_dump_buf = ife_cfg->num_reg_dump_buf; if ((prepare_hw_data->num_reg_dump_buf) && (prepare_hw_data->num_reg_dump_buf < CAM_REG_DUMP_MAX_BUF_ENTRIES)) { memcpy(prepare_hw_data->reg_dump_buf_desc, - prepare->reg_dump_buf_desc, + ife_cfg->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * prepare_hw_data->num_reg_dump_buf); } } + /* Add wait for comp event */ + if ((ctx->hw_version >= CAM_CPAS_TITAN_480_V100) && ctx->is_dual + && ctx->internal_cdm) { + for (i = 0; i < ctx->num_base; i++) { + if (ctx->master_slave[ctx->base[i].idx] == + CAM_IFE_RES_MASTER && + ctx->base[i].cdm_id == CAM_CDM_IFE) + rc = cam_isp_add_comp_wait(ife_cfg, + &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf); + } + } + /* add reg update commands */ for (i = 0; i < ctx->num_base; i++) { /* Add change base */ - rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed in change base adding reg_update cmd i=%d, idx=%d, rc=%d", - i, ctx->base[i].idx, rc); - goto end; - } + if (!ctx->internal_cdm || ctx->base[i].cdm_id == CAM_CDM_CPAS) { + rc = cam_isp_add_change_base(ife_cfg, + &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed in change base adding reg_update cmd i=%d, idx=%d, rc=%d", + i, ctx->base[i].idx, rc); + goto end; + } + } /*Add reg update */ - rc = cam_isp_add_reg_update(prepare, &ctx->res_list_ife_src, + rc = cam_isp_add_reg_update(ife_cfg, &ctx->res_list_ife_src, ctx->base[i].idx, &kmd_buf); + if (rc) { CAM_ERR(CAM_ISP, "Add Reg_update cmd Failed i=%d, idx=%d, rc=%d", @@ -6096,6 +6387,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } + /* Add trigger_cdm_event */ + if ((ctx->hw_version >= CAM_CPAS_TITAN_480_V100) && ctx->is_dual + && ctx->internal_cdm) { + for (i = 0; i < ctx->num_base; i++) { + if (ctx->master_slave[ctx->base[i].idx] + == CAM_IFE_RES_SLAVE) + rc = cam_isp_add_wait_trigger(ife_cfg, + &ctx->res_list_ife_src, + ctx->base[i].idx, &kmd_buf, true); + } + } + end: return rc; } @@ -6227,7 +6530,7 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { - int rc = 0; + int rc = 0, i = 0; struct cam_hw_cmd_args *hw_cmd_args = cmd_args; struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *) @@ -6235,6 +6538,7 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; struct cam_packet *packet; unsigned long rem_jiffies = 0; + uint32_t idx; if (!hw_mgr_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -6308,13 +6612,17 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) if (ctx->last_dump_flush_req_id == ctx->applied_req_id) return 0; - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies(30)); - if (rem_jiffies == 0) - CAM_ERR(CAM_ISP, - "config done completion timeout, Reg dump will be unreliable ctx_index %d", - ctx->ctx_index); + for (i = 0; i < ctx->num_base; i++) { + idx = ctx->base[i].idx; + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete[idx], + msecs_to_jiffies(5)); + if (rem_jiffies == 0) + CAM_ERR(CAM_ISP, + "config done completion timeout, Reg dump will be unreliable rc=%d ctx_index %d", + rc, ctx->ctx_index); + rc = 0; + } ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, @@ -7345,8 +7653,10 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) * Also, we have to release them once we have the * deinit support */ - if (cam_smmu_get_handle("ife", - &g_ife_hw_mgr.mgr_common.img_iommu_hdl)) { + rc = cam_smmu_get_handle("ife", + &g_ife_hw_mgr.mgr_common.img_iommu_hdl); + + if (rc && rc != -EALREADY) { CAM_ERR(CAM_ISP, "Can not get iommu handle"); return -EINVAL; } @@ -7361,13 +7671,15 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) g_ife_hw_mgr.mgr_common.img_iommu_hdl, g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure); - if (!cam_cdm_get_iommu_handle("ife", &cdm_handles)) { - CAM_DBG(CAM_ISP, "Successfully acquired the CDM iommu handles"); + if (!cam_cdm_get_iommu_handle("ife3", &cdm_handles)) { + CAM_DBG(CAM_ISP, + "Successfully acquired CDM iommu handles 0x%x, 0x%x", + cdm_handles.non_secure, cdm_handles.secure); g_ife_hw_mgr.mgr_common.cmd_iommu_hdl = cdm_handles.non_secure; g_ife_hw_mgr.mgr_common.cmd_iommu_hdl_secure = cdm_handles.secure; } else { - CAM_DBG(CAM_ISP, "Failed to acquire the CDM iommu handles"); + CAM_ERR(CAM_ISP, "Failed to acquire CDM iommu handle"); g_ife_hw_mgr.mgr_common.cmd_iommu_hdl = -1; g_ife_hw_mgr.mgr_common.cmd_iommu_hdl_secure = -1; } @@ -7418,8 +7730,10 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = g_ife_hw_mgr.mgr_common.tasklet_pool[i]; - - init_completion(&g_ife_hw_mgr.ctx_pool[i].config_done_complete); + for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) + init_completion( + &g_ife_hw_mgr.ctx_pool[i] + .config_done_complete[j]); list_add_tail(&g_ife_hw_mgr.ctx_pool[i].list, &g_ife_hw_mgr.free_ctx_list); } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index bd83f8937257..b6124ba566c7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -13,6 +13,15 @@ #include "cam_ife_csid_hw_intf.h" #include "cam_top_tpg_hw_intf.h" #include "cam_tasklet_util.h" +#include "cam_cdm_intf_api.h" + +/* enum cam_ife_res_master_slave - HW resource master/slave */ +enum cam_ife_res_master_slave { + CAM_IFE_RES_NONE, + CAM_IFE_RES_MASTER, + CAM_IFE_RES_SLAVE, + CAM_IFE_RES_MAX, +}; /* IFE resource constants */ #define CAM_IFE_HW_IN_RES_MAX (CAM_ISP_IFE_IN_RES_MAX & 0xFF) @@ -90,6 +99,8 @@ struct cam_ife_hw_mgr_debug { * @is_tpg indicate whether context is using PHY TPG * @is_offline Indicate whether context is for offline IFE * @dsp_enabled Indicate whether dsp is enabled in this context + * @hw_enabled Array to indicate active HW + * @internal_cdm Indicate whether context uses internal CDM */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -117,7 +128,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t irq_status1_mask[CAM_IFE_HW_NUM_MAX]; struct cam_isp_ctx_base_info base[CAM_IFE_HW_NUM_MAX]; uint32_t num_base; - uint32_t cdm_handle; + uint32_t cdm_handle[CAM_IFE_HW_NUM_MAX]; struct cam_cdm_utils_ops *cdm_ops; struct cam_cdm_bl_request *cdm_cmd; @@ -127,7 +138,10 @@ struct cam_ife_hw_mgr_ctx { atomic_t overflow_pending; atomic_t cdm_done; uint32_t is_rdi_only_context; - struct completion config_done_complete; + struct completion config_done_complete[ + CAM_IFE_HW_NUM_MAX]; + enum cam_ife_res_master_slave master_slave[CAM_IFE_HW_NUM_MAX]; + uint32_t hw_version; struct cam_cmd_buf_desc reg_dump_buf_desc[ CAM_REG_DUMP_MAX_BUF_ENTRIES]; uint32_t num_reg_dump_buf; @@ -143,6 +157,7 @@ struct cam_ife_hw_mgr_ctx { bool is_tpg; bool is_offline; bool dsp_enabled; + bool internal_cdm; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h index fcb62ff8916c..edd1d33be8f0 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h @@ -10,7 +10,7 @@ #include "cam_isp_hw_mgr_intf.h" #include "cam_tasklet_util.h" #include "cam_isp_hw.h" - +#include "cam_cdm_intf_api.h" #define CAM_ISP_HW_NUM_MAX 7 @@ -91,5 +91,6 @@ struct cam_isp_hw_mgr_res { struct cam_isp_ctx_base_info { uint32_t idx; enum cam_isp_hw_split_id split_id; + enum cam_cdm_id cdm_id; }; #endif /* _CAM_ISP_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index fc4051011585..02ca27f7f499 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1759,6 +1759,8 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto err; } + memset(&tfe_ctx->cdm_handle, 0, sizeof(tfe_ctx->cdm_handle)); + tfe_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) tfe_ctx->common.event_cb[i] = acquire_args->event_cb; @@ -1778,7 +1780,6 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } cdm_acquire.base_array_cnt = j; - cdm_acquire.id = CAM_CDM_VIRTUAL; cdm_acquire.cam_cdm_callback = cam_tfe_cam_cdm_callback; rc = cam_cdm_acquire(&cdm_acquire); @@ -1992,6 +1993,8 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto err; } + memset(&tfe_ctx->cdm_handle, 0, sizeof(tfe_ctx->cdm_handle)); + tfe_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) tfe_ctx->common.event_cb[i] = acquire_args->event_cb; @@ -2322,14 +2325,15 @@ static int cam_isp_tfe_blob_bw_update( static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) { - int rc = -EINVAL, i, skip = 0; - struct cam_hw_config_args *cfg; + int rc = -EINVAL, i, j, k = 0, skip = 0; + struct cam_isp_hw_config_args *cfg; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; struct cam_tfe_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; + uint32_t num_ent; + struct cam_hw_update_entry *cfg_info; - CAM_DBG(CAM_ISP, "Enter"); if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); return -EINVAL; @@ -2373,68 +2377,79 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, } } - 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); + CAM_DBG(CAM_ISP, "Enter ctx id:%d request id: %llu", + ctx->ctx_index, cfg->request_id); - if (cfg->num_hw_update_entries > 0) { - cdm_cmd = ctx->cdm_cmd; - cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = true; - cdm_cmd->userdata = hw_update_data; - cdm_cmd->cookie = cfg->request_id; - cdm_cmd->gen_irq_arb = false; + cdm_cmd = ctx->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; + cdm_cmd->cmd_arrary_count = 0; - for (i = 0 ; i < cfg->num_hw_update_entries; i++) { - cmd = (cfg->hw_update_entries + i); - if (cfg->reapply && cmd->flags == CAM_ISP_IQ_BL) { - skip++; - continue; + for (i = 0; i < ctx->num_base; i++) { + num_ent = cfg->hw_update_info[ctx->base[i].idx].num_hw_entries; + cfg_info = cfg->hw_update_info[ctx->base[i].idx].hw_entries; + if (num_ent > 0) { + for (j = 0 ; j < num_ent; j++) { + cmd = (cfg_info + j); + + if (cfg->reapply && + cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, + "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[j - skip + k].bl_addr.mem_handle = + cmd->handle; + cdm_cmd->cmd[j - skip + k].offset = cmd->offset; + cdm_cmd->cmd[j - skip + k].len = cmd->len; + cdm_cmd->cmd[j - skip + k].arbitrate = false; } - - if (cmd->flags == CAM_ISP_UNUSED_BL || - cmd->flags >= CAM_ISP_BL_MAX) - CAM_ERR(CAM_ISP, "Unexpected BL type %d", - cmd->flags); - - cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; - cdm_cmd->cmd[i - skip].offset = cmd->offset; - cdm_cmd->cmd[i - skip].len = cmd->len; - cdm_cmd->cmd[i - skip].arbitrate = false; + cdm_cmd->cmd_arrary_count += num_ent - skip; + k = cdm_cmd->cmd_arrary_count; } - cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; + } - reinit_completion(&ctx->config_done_complete); - ctx->applied_req_id = cfg->request_id; + ctx->applied_req_id = cfg->request_id; + CAM_DBG(CAM_ISP, "Submit to CDM"); - CAM_DBG(CAM_ISP, "Submit to CDM"); - atomic_set(&ctx->cdm_done, 0); - rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to apply the configs"); - return rc; + atomic_set(&ctx->cdm_done, 0); + reinit_completion(&ctx->config_done_complete); + rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to apply the configs for req %llu, rc %d", + cfg->request_id, rc); + return rc; + } + + if (cfg->init_packet) { + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies( + CAM_TFE_HW_CONFIG_TIMEOUT)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, + "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 ctx_index %d", + cfg->request_id, + ctx->ctx_index); } - - if (cfg->init_packet) { - rc = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies(CAM_TFE_HW_CONFIG_TIMEOUT)); - if (rc <= 0) { - CAM_ERR(CAM_ISP, - "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 ctx_index %d", - cfg->request_id, ctx->ctx_index); - } - } - } else { - CAM_ERR(CAM_ISP, "No commands to config"); } CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); @@ -2642,7 +2657,8 @@ static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_tfe_mgr_pause_hw(ctx); - wait_for_completion(&ctx->config_done_complete); + wait_for_completion_timeout(&ctx->config_done_complete, + msecs_to_jiffies(5)); if (stop_isp->stop_only) goto end; @@ -3069,18 +3085,18 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, return rc; } - static int cam_isp_tfe_blob_hfr_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_tfe_resource_hfr_config *hfr_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_isp_tfe_port_hfr_config *port_hfr_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_tfe_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - uint32_t res_id_out, i; + struct cam_hw_update_entry *hw_entry; + uint32_t res_id_out, i, slot_idx = 0; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; @@ -3090,11 +3106,15 @@ static int cam_isp_tfe_blob_hfr_update( ctx = prepare->ctxt_to_hw_map; CAM_DBG(CAM_ISP, "num_ports= %d", hfr_config->num_ports); + slot_idx = blob_info->base_info->idx; + hw_entry = prepare->hw_update_info[slot_idx].hw_entries; + num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; + /* Max one hw entries required for hfr config update */ - if (prepare->num_hw_update_entries + 1 >= + if (prepare->hw_update_info[slot_idx].num_hw_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->num_hw_update_entries, + prepare->hw_update_info[slot_idx].num_hw_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -3150,17 +3170,17 @@ static int cam_isp_tfe_blob_hfr_update( if (total_used_bytes) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = + hw_entry[num_ent].handle = kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = total_used_bytes; - prepare->hw_update_entries[num_ent].offset = + hw_entry[num_ent].len = + total_used_bytes; + hw_entry[num_ent].offset = kmd_buf_info->offset; num_ent++; - kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[slot_idx].num_hw_entries + = num_ent; } return rc; @@ -3170,7 +3190,7 @@ static int cam_isp_tfe_blob_csid_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_tfe_csid_clock_config *clock_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_tfe_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -3234,7 +3254,7 @@ static int cam_isp_tfe_blob_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_tfe_clock_config *clock_config, - struct cam_hw_prepare_update_args *prepare) + struct cam_isp_hw_update_args *prepare) { struct cam_tfe_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -3323,7 +3343,7 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, { int rc = 0; struct cam_isp_generic_blob_info *blob_info = user_data; - struct cam_hw_prepare_update_args *prepare = NULL; + struct cam_isp_hw_update_args *prepare = NULL; if (!blob_data || (blob_size == 0) || !blob_info) { CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK", @@ -3524,7 +3544,7 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, } static int cam_tfe_update_dual_config( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct cam_cmd_buf_desc *cmd_desc, uint32_t split_id, uint32_t base_idx, @@ -3633,7 +3653,7 @@ end: } int cam_tfe_add_command_buffers( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, @@ -3645,12 +3665,13 @@ int cam_tfe_add_command_buffers( uint32_t base_idx; enum cam_isp_hw_split_id split_id; struct cam_cmd_buf_desc *cmd_desc = NULL; - struct cam_hw_update_entry *hw_entry; + struct cam_hw_update_entry *hw_entry = NULL; + struct cam_isp_hw_update_entry_info *hw_info; - hw_entry = prepare->hw_update_entries; split_id = base_info->split_id; base_idx = base_info->idx; - + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + hw_info = prepare->hw_update_info; /* * set the cmd_desc to point the first command descriptor in the * packet @@ -3663,7 +3684,7 @@ int cam_tfe_add_command_buffers( split_id, prepare->packet->num_cmd_buf); for (i = 0; i < prepare->packet->num_cmd_buf; i++) { - num_ent = prepare->num_hw_update_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; if (!cmd_desc[i].length) continue; @@ -3748,7 +3769,8 @@ int cam_tfe_add_command_buffers( case CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_COMMON: { struct cam_isp_generic_blob_info blob_info; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries = + num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -3763,7 +3785,7 @@ int cam_tfe_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = prepare->num_hw_update_entries; + num_ent = hw_info[base_idx].num_hw_entries; } break; case CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH: @@ -3791,7 +3813,8 @@ int cam_tfe_add_command_buffers( cmd_meta_data); return -EINVAL; } - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; } return rc; @@ -3801,8 +3824,8 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { int rc = 0; - struct cam_hw_prepare_update_args *prepare = - (struct cam_hw_prepare_update_args *) prepare_hw_update_args; + struct cam_isp_hw_update_args *prepare = + (struct cam_isp_hw_update_args *) prepare_hw_update_args; struct cam_tfe_hw_mgr_ctx *ctx; struct cam_tfe_hw_mgr *hw_mgr; struct cam_kmd_buf_info kmd_buf; @@ -3843,7 +3866,6 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, return rc; } - prepare->num_hw_update_entries = 0; prepare->num_in_map_entries = 0; prepare->num_out_map_entries = 0; prepare->num_reg_dump_buf = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 282c458d1b25..c4931d85e7da 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -10,9 +10,10 @@ #include "cam_vfe_hw_intf.h" #include "cam_isp_packet_parser.h" #include "cam_debug_util.h" +#include "cam_isp_hw_mgr_intf.h" int cam_isp_add_change_base( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct list_head *res_list_isp_src, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info) @@ -24,8 +25,8 @@ int cam_isp_add_change_base( struct cam_hw_update_entry *hw_entry; uint32_t num_ent, i; - hw_entry = prepare->hw_update_entries; - num_ent = prepare->num_hw_update_entries; + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; /* Max one hw entries required for each base */ if (num_ent + 1 >= prepare->max_hw_update_entries) { @@ -76,7 +77,8 @@ int cam_isp_add_change_base( kmd_buf_info->used_bytes += get_base.cmd.used_bytes; kmd_buf_info->offset += get_base.cmd.used_bytes; num_ent++; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; /* return success */ return 0; @@ -87,7 +89,7 @@ int cam_isp_add_change_base( } static int cam_isp_update_dual_config( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct cam_cmd_buf_desc *cmd_desc, uint32_t split_id, uint32_t base_idx, @@ -241,7 +243,7 @@ int cam_isp_add_cmd_buf_update( } int cam_isp_add_command_buffers( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, @@ -253,12 +255,13 @@ int cam_isp_add_command_buffers( uint32_t base_idx; enum cam_isp_hw_split_id split_id; struct cam_cmd_buf_desc *cmd_desc = NULL; - struct cam_hw_update_entry *hw_entry; + struct cam_hw_update_entry *hw_entry = NULL; + struct cam_isp_hw_update_entry_info *hw_info; - hw_entry = prepare->hw_update_entries; split_id = base_info->split_id; base_idx = base_info->idx; - + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + hw_info = prepare->hw_update_info; /* * set the cmd_desc to point the first command descriptor in the * packet @@ -271,7 +274,8 @@ int cam_isp_add_command_buffers( split_id, prepare->packet->num_cmd_buf); for (i = 0; i < prepare->packet->num_cmd_buf; i++) { - num_ent = prepare->num_hw_update_entries; + num_ent = + prepare->hw_update_info[base_idx].num_hw_entries; if (!cmd_desc[i].length) continue; @@ -358,7 +362,8 @@ int cam_isp_add_command_buffers( if (split_id == CAM_ISP_HW_SPLIT_LEFT) { struct cam_isp_generic_blob_info blob_info; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -374,14 +379,15 @@ int cam_isp_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = prepare->num_hw_update_entries; + num_ent = hw_info[base_idx].num_hw_entries; } break; case CAM_ISP_PACKET_META_GENERIC_BLOB_RIGHT: if (split_id == CAM_ISP_HW_SPLIT_RIGHT) { struct cam_isp_generic_blob_info blob_info; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -397,13 +403,14 @@ int cam_isp_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = prepare->num_hw_update_entries; + num_ent = hw_info[base_idx].num_hw_entries; } break; case CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON: { struct cam_isp_generic_blob_info blob_info; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries = + num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -418,7 +425,7 @@ int cam_isp_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = prepare->num_hw_update_entries; + num_ent = hw_info[base_idx].num_hw_entries; } break; case CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH: @@ -448,7 +455,8 @@ int cam_isp_add_command_buffers( cmd_meta_data); return -EINVAL; } - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; } return rc; @@ -457,7 +465,7 @@ int cam_isp_add_command_buffers( int cam_isp_add_io_buffers( int iommu_hdl, int sec_iommu_hdl, - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_hw_mgr_res *res_list_isp_out, @@ -473,6 +481,7 @@ int cam_isp_add_io_buffers( struct cam_isp_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_hw_update_entry *hw_entry; 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; @@ -495,12 +504,14 @@ int cam_isp_add_io_buffers( num_in_buf = 0; io_cfg_used_bytes = 0; prepare->pf_data->packet = prepare->packet; + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; /* Max one hw entries required for each base */ - if (prepare->num_hw_update_entries + 1 >= + if (num_ent + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->num_hw_update_entries, + prepare->hw_update_info[base_idx].num_hw_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -852,25 +863,21 @@ int cam_isp_add_io_buffers( io_cfg_used_bytes, fill_fence); if (io_cfg_used_bytes) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = - kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = io_cfg_used_bytes; - prepare->hw_update_entries[num_ent].offset = - kmd_buf_info->offset; - prepare->hw_update_entries[num_ent].flags = - CAM_ISP_IOCFG_BL; + hw_entry[num_ent].handle = kmd_buf_info->handle; + hw_entry[num_ent].len = io_cfg_used_bytes; + hw_entry[num_ent].offset = kmd_buf_info->offset; + hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - prepare->hw_update_entries[num_ent].handle, - prepare->hw_update_entries[num_ent].len, - prepare->hw_update_entries[num_ent].offset); + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += io_cfg_used_bytes; kmd_buf_info->offset += io_cfg_used_bytes; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries = num_ent; } if (fill_fence) { @@ -881,9 +888,8 @@ int cam_isp_add_io_buffers( return rc; } - int cam_isp_add_reg_update( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct list_head *res_list_isp_src, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info) @@ -895,12 +901,13 @@ int cam_isp_add_reg_update( struct cam_isp_hw_get_cmd_update get_regup; uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; - hw_entry = prepare->hw_update_entries; + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; + /* Max one hw entries required for each base */ - if (prepare->num_hw_update_entries + 1 >= - prepare->max_hw_update_entries) { + if (num_ent + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->num_hw_update_entries, + num_ent, prepare->max_hw_update_entries); return -EINVAL; } @@ -946,35 +953,32 @@ int cam_isp_add_reg_update( if (rc) return rc; - CAM_DBG(CAM_ISP, "Reg update added for res %d hw_id %d", - res->res_type, res->hw_intf->hw_idx); + CAM_DBG(CAM_ISP, + "Reg update added for res %d hw_id %d cdm_idx %d", + res->res_id, res->hw_intf->hw_idx, base_idx); reg_update_size += get_regup.cmd.used_bytes; } } if (reg_update_size) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = - kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = reg_update_size; - prepare->hw_update_entries[num_ent].offset = - kmd_buf_info->offset; + hw_entry[num_ent].handle = kmd_buf_info->handle; + hw_entry[num_ent].len = reg_update_size; + hw_entry[num_ent].offset = kmd_buf_info->offset; /* Marking reg update as IOCFG to reapply on bubble */ - prepare->hw_update_entries[num_ent].flags = - CAM_ISP_IOCFG_BL; + hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - prepare->hw_update_entries[num_ent].handle, - prepare->hw_update_entries[num_ent].len, - prepare->hw_update_entries[num_ent].offset); + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += reg_update_size; kmd_buf_info->offset += reg_update_size; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries = num_ent; /* reg update is success return status 0 */ rc = 0; } @@ -983,7 +987,7 @@ int cam_isp_add_reg_update( } int cam_isp_add_go_cmd( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct list_head *res_list_isp_rd, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info) @@ -995,11 +999,13 @@ int cam_isp_add_go_cmd( struct cam_isp_hw_get_cmd_update get_regup; uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; - hw_entry = prepare->hw_update_entries; - if (prepare->num_hw_update_entries + 1 >= - prepare->max_hw_update_entries) { - CAM_ERR(CAM_ISP, "Insufficient HW entries current: %d max: %d", - prepare->num_hw_update_entries, + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; + + /* Max one hw entries required for each base */ + if (num_ent + 1 >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", + num_ent, prepare->max_hw_update_entries); return -EINVAL; } @@ -1052,26 +1058,236 @@ int cam_isp_add_go_cmd( if (reg_update_size) { /* Update the HW entries */ - num_ent = prepare->num_hw_update_entries; - prepare->hw_update_entries[num_ent].handle = - kmd_buf_info->handle; - prepare->hw_update_entries[num_ent].len = reg_update_size; - prepare->hw_update_entries[num_ent].offset = - kmd_buf_info->offset; + hw_entry[num_ent].handle = kmd_buf_info->handle; + hw_entry[num_ent].len = reg_update_size; + hw_entry[num_ent].offset = kmd_buf_info->offset; - prepare->hw_update_entries[num_ent].flags = - CAM_ISP_IOCFG_BL; + hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - prepare->hw_update_entries[num_ent].handle, - prepare->hw_update_entries[num_ent].len, - prepare->hw_update_entries[num_ent].offset); + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += reg_update_size; kmd_buf_info->offset += reg_update_size; - prepare->num_hw_update_entries = num_ent; + prepare->hw_update_info[base_idx].num_hw_entries = num_ent; + + rc = 0; + } + + return rc; +} + +int cam_isp_add_comp_wait( + struct cam_isp_hw_update_args *prepare, + struct list_head *res_list_isp_src, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info) +{ + int rc = -EINVAL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_update_entry *hw_entry; + struct cam_isp_hw_get_cmd_update add_wait; + struct cam_hw_intf *hw_intf; + bool hw_res_valid = false; + uint32_t kmd_buf_remain_size, num_ent, add_wait_size; + + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; + + /* Max one hw entries required for each base */ + if (num_ent >= prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries"); + return -EINVAL; + } + + add_wait_size = 0; + list_for_each_entry(hw_mgr_res, res_list_isp_src, list) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) + continue; + if (hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] && + hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]) { + hw_res_valid = true; + break; + } + } + + if (!hw_mgr_res || !hw_res_valid) { + CAM_ERR(CAM_ISP, "No src with multi_vfe config"); + return -EINVAL; + } + + hw_intf = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->hw_intf; + + if (kmd_buf_info->size > (kmd_buf_info->used_bytes + + add_wait_size)) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + add_wait_size); + } else { + CAM_ERR(CAM_ISP, "no free mem %d %d %d", + base_idx, kmd_buf_info->size, + kmd_buf_info->used_bytes + + add_wait_size); + rc = -EINVAL; + return rc; + } + + add_wait.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + add_wait_size/4; + add_wait.cmd.size = kmd_buf_remain_size; + add_wait.cmd_type = CAM_ISP_HW_CMD_ADD_WAIT; + add_wait.res = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_ADD_WAIT, + &add_wait, + sizeof(struct cam_isp_hw_get_cmd_update)); + + if (rc) { + CAM_ERR(CAM_ISP, + "wait_comp_event addition failed for dual vfe"); + return rc; + } + + add_wait_size += add_wait.cmd.used_bytes; + if (add_wait_size) { + /* Update the HW entries */ + hw_entry[num_ent].handle = + kmd_buf_info->handle; + hw_entry[num_ent].len = + add_wait_size; + hw_entry[num_ent].offset = + kmd_buf_info->offset; + hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + CAM_DBG(CAM_ISP, + "num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + num_ent++; + + kmd_buf_info->used_bytes += add_wait_size; + kmd_buf_info->offset += add_wait_size; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; + /* add wait_comp_event is success return status 0 */ + rc = 0; + } + + return rc; +} + +int cam_isp_add_wait_trigger( + struct cam_isp_hw_update_args *prepare, + struct list_head *res_list_isp_src, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info, + bool trigger_cdm_en) +{ + int rc = -EINVAL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_update_entry *hw_entry; + struct cam_isp_hw_get_cmd_update add_trigger; + struct cam_hw_intf *hw_intf; + bool hw_res_valid = false; + uint32_t kmd_buf_remain_size, num_ent, add_trigger_size; + + hw_entry = prepare->hw_update_info[base_idx].hw_entries; + num_ent = prepare->hw_update_info[base_idx].num_hw_entries; + + /* Max one hw entries required for each base */ + if (num_ent + 1 >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d"); + return -EINVAL; + } + + add_trigger_size = 0; + + list_for_each_entry(hw_mgr_res, res_list_isp_src, list) { + if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) + continue; + if (hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] && + hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]) { + hw_res_valid = true; + break; + } + } + + if (!hw_mgr_res || !hw_res_valid) { + CAM_ERR(CAM_ISP, "No src with multi_vfe config"); + return -EINVAL; + } + + hw_intf = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]->hw_intf; + + if (kmd_buf_info->size > (kmd_buf_info->used_bytes + + add_trigger_size)) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + add_trigger_size); + } else { + CAM_ERR(CAM_ISP, "no free mem %d %d %d", + base_idx, kmd_buf_info->size, + kmd_buf_info->used_bytes + + add_trigger_size); + rc = -EINVAL; + return rc; + } + + add_trigger.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + + add_trigger_size/4; + add_trigger.cmd.size = kmd_buf_remain_size; + add_trigger.cmd_type = CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER; + add_trigger.res = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]; + + if (trigger_cdm_en) + add_trigger.trigger_cdm_en = true; + else + add_trigger.trigger_cdm_en = false; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER, + &add_trigger, + sizeof(struct cam_isp_hw_get_cmd_update)); + + if (rc) { + CAM_ERR(CAM_ISP, + "wait_trigger_event addition failed for dual vfe"); + return rc; + } + + add_trigger_size += add_trigger.cmd.used_bytes; + + if (add_trigger_size) { + /* Update the HW entries */ + hw_entry[num_ent].handle = + kmd_buf_info->handle; + hw_entry[num_ent].len = + add_trigger_size; + hw_entry[num_ent].offset = + kmd_buf_info->offset; + hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + CAM_DBG(CAM_ISP, + "num_ent=%d handle=0x%x, len=%u, offset=%u", + num_ent, + hw_entry[num_ent].handle, + hw_entry[num_ent].len, + hw_entry[num_ent].offset); + num_ent++; + + kmd_buf_info->used_bytes += add_trigger_size; + kmd_buf_info->offset += add_trigger_size; + prepare->hw_update_info[base_idx].num_hw_entries + = num_ent; + /* add wait trigger is success return status 0 */ rc = 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index 92632b689a40..3c13ee52ae0d 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -29,7 +29,7 @@ enum cam_isp_cdm_bl_type { * @kmd_buf_info: Kmd buffer to store the custom cmd data */ struct cam_isp_generic_blob_info { - struct cam_hw_prepare_update_args *prepare; + struct cam_isp_hw_update_args *prepare; struct cam_isp_ctx_base_info *base_info; struct cam_kmd_buf_info *kmd_buf_info; }; @@ -59,12 +59,11 @@ struct cam_isp_frame_header_info { * @base_idx: Base or dev index of the IFE/VFE HW instance for * which change change base need to be added * @kmd_buf_info: Kmd buffer to store the change base command - * * @return: 0 for success * -EINVAL for Fail */ int cam_isp_add_change_base( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct list_head *res_list_isp_src, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info); @@ -116,7 +115,7 @@ int cam_isp_add_cmd_buf_update( * Negative for Failure */ int cam_isp_add_command_buffers( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, @@ -147,7 +146,7 @@ int cam_isp_add_command_buffers( int cam_isp_add_io_buffers( int iommu_hdl, int sec_iommu_hdl, - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_hw_mgr_res *res_list_isp_out, @@ -171,11 +170,56 @@ int cam_isp_add_io_buffers( * -EINVAL for Fail */ int cam_isp_add_reg_update( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct list_head *res_list_isp_src, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info); +/* + * cam_isp_add_comp_wait() + * + * @brief Add reg update in the hw entries list + * processe the isp source list get the reg update from + * ISP HW instance + * + * @prepare: Contain the packet and HW update variables + * @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 + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_isp_add_comp_wait( + struct cam_isp_hw_update_args *prepare, + struct list_head *res_list_isp_src, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info); + +/* + * cam_isp_add_wait_trigger() + * + * @brief Add reg update in the hw entries list + * processe the isp source list get the reg update from + * ISP HW instance + * + * @prepare: Contain the packet and HW update variables + * @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 + * @trigger_cdm_en Used to reset and set trigger_cdm_events register + * + * @return: 0 for success + * -EINVAL for Fail + */ +int cam_isp_add_wait_trigger( + struct cam_isp_hw_update_args *prepare, + struct list_head *res_list_isp_src, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info, + bool trigger_cdm_en); + + /* * cam_isp_add_go_cmd() * @@ -189,10 +233,9 @@ int cam_isp_add_reg_update( * -EINVAL for Fail */ int cam_isp_add_go_cmd( - struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_update_args *prepare, struct list_head *res_list_isp_rd, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info); - #endif /*_CAM_ISP_HW_PARSER_H */ diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 9ee05756c306..32f38d81b515 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -22,6 +22,13 @@ /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 30 + +/* + * Maximum configuration entry size - This is based on the + * worst case DUAL IFE use case plus some margin. + */ + #define CAM_ISP_CTX_CFG_MAX 25 + /** * enum cam_isp_hw_event_type - Collection of the ISP hardware events */ @@ -71,18 +78,7 @@ struct cam_isp_stop_args { bool stop_only; }; -/** - * struct cam_isp_start_args - isp hardware start arguments - * - * @config_args: Hardware configuration commands. - * @start_only Send start only to hw drivers. No init to - * be done. - * - */ -struct cam_isp_start_args { - struct cam_hw_config_args hw_config; - bool start_only; -}; + /** * struct cam_isp_bw_config_internal_v2 - Bandwidth configuration @@ -261,6 +257,106 @@ struct cam_isp_hw_cmd_args { } u; }; +/** + * struct cam_isp_hw_update_entry_info - hardware config info + * + * @hw_update_entries Entry for hardware config + * @num_hw_update_entries: Number of IFE hw + * + */ +struct cam_isp_hw_update_entry_info { + struct cam_hw_update_entry *hw_entries; + uint32_t num_hw_entries; +}; + +/** + * struct cam_isp_hw_update_info - hardware config info + * + * @hw_update_entries Entry for hardware config + * @num_hw_update_entries: number of IFE hw + * + */ + +struct cam_isp_hw_update_info { + struct cam_hw_update_entry hw_entries[CAM_ISP_CTX_CFG_MAX]; + uint32_t num_hw_entries; +}; + +/** + * struct cam_isp_hw_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_info: Actual hardware update configuration (returned) + * @max_out_map_entries: Maximum output fence mapping supported + * @out_map_entries: Actual output fence mapping list (returned) + * @num_out_map_entries: Number of actual output fence mapping (returned) + * @max_in_map_entries: Maximum input fence mapping supported + * @in_map_entries: Actual input fence mapping list (returned) + * @num_in_map_entries: Number of acutal input fence mapping (returned) + * @priv: Private pointer of hw update + * @pf_data: Debug data for page fault + * + */ + +struct cam_isp_hw_update_args { + struct cam_packet *packet; + uint32_t remain_len; + void *ctxt_to_hw_map; + uint32_t max_hw_update_entries; + struct cam_isp_hw_update_entry_info hw_update_info[CAM_IFE_HW_NUM_MAX]; + uint32_t max_out_map_entries; + struct cam_hw_fence_map_entry *out_map_entries; + uint32_t num_out_map_entries; + uint32_t max_in_map_entries; + struct cam_hw_fence_map_entry *in_map_entries; + uint32_t num_in_map_entries; + void *priv; + struct cam_hw_mgr_dump_pf_data *pf_data; + struct cam_cmd_buf_desc reg_dump_buf_desc[ + CAM_REG_DUMP_MAX_BUF_ENTRIES]; + uint32_t num_reg_dump_buf; +}; + +/** + * struct cam_isp_hw_config_args - Payload for config command + * + * @ctxt_to_hw_map: HW context from the acquire + * @hw_update_info: Hardware update info for every IFE + * @out_map_entries: Out map info + * @num_out_map_entries: Number of out map entries + * @priv: Private pointer + * @request_id: Request ID + * @init_packet: check init packet or update packet + * @reapply: check if current req is reapplied + * + */ + +struct cam_isp_hw_config_args { + void *ctxt_to_hw_map; + struct cam_isp_hw_update_entry_info hw_update_info[CAM_IFE_HW_NUM_MAX]; + struct cam_hw_fence_map_entry *out_map_entries; + uint32_t num_out_map_entries; + void *priv; + uint64_t request_id; + bool init_packet; + bool reapply; +}; + +/** + * struct cam_isp_start_args - isp hardware start arguments + * + * @config_args: Hardware configuration commands. + * @start_only Send start only to hw drivers. No init to + * be done. + * + */ +struct cam_isp_start_args { + struct cam_isp_hw_config_args hw_config; + bool start_only; +}; /** * cam_isp_hw_mgr_init() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index b55af3ec2ef0..b48416c35587 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -110,6 +110,8 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CORE_CONFIG, CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED, + CAM_ISP_HW_CMD_ADD_WAIT, + CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER, CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA, CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, @@ -245,6 +247,7 @@ struct cam_isp_hw_get_cmd_update { struct cam_isp_hw_get_wm_update *wm_update; struct cam_isp_hw_get_wm_update *rm_update; }; + bool trigger_cdm_en; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 13e3263ff26b..7b991a316824 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -596,6 +596,8 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_CORE_CONFIG: case CAM_ISP_HW_CMD_BW_UPDATE_V2: case CAM_ISP_HW_CMD_DUMP_HW: + case CAM_ISP_HW_CMD_ADD_WAIT: + case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 6774be8cda3d..b174c21d8bf2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -179,6 +179,92 @@ static int cam_vfe_top_mux_get_reg_update( return -EINVAL; } +static int cam_vfe_top_wait_comp_event(struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + uint32_t size = 0; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error! Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error! 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; + } + + size = cdm_util_ops->cdm_required_size_comp_wait(); + /* 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; + } + + cdm_util_ops->cdm_write_wait_comp_event(cdm_args->cmd.cmd_buf_addr, + 0, 0x2); + cdm_args->cmd.used_bytes = (size * 4); + + return 0; +} + +static int cam_vfe_top_add_wait_trigger(struct cam_vfe_top_ver2_priv *top_priv, + 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; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error! Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error! 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; + } + + 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; + } + + reg_val_pair[0] = 0x90; + reg_val_pair[1] = 0x1; + + 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_top_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size) { @@ -644,6 +730,12 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_hw_dump(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_ADD_WAIT: + rc = cam_vfe_top_wait_comp_event(top_priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: + rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index dc15cab5e2f4..a750e7d2ee99 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -16,6 +16,7 @@ #define CAM_VFE_HW_RESET_HW_VAL 0x00010000 #define CAM_VFE_LITE_HW_RESET_AND_REG_VAL 0x00000002 #define CAM_VFE_LITE_HW_RESET_HW_VAL 0x00000001 +#define CAM_CDM_WAIT_COMP_EVENT_BIT 0x2 struct cam_vfe_top_ver3_common_data { struct cam_hw_soc_info *soc_info; @@ -212,6 +213,102 @@ static int cam_vfe_top_ver3_mux_get_reg_update( return -EINVAL; } +static int cam_vfe_top_wait_comp_event(struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + uint32_t size = 0; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error, Invalid arg size = %d expected = %d", + arg_size, sizeof(struct cam_isp_hw_get_cmd_update)); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error, 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; + } + + size = cdm_util_ops->cdm_required_size_comp_wait(); + /* 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; + } + + cdm_util_ops->cdm_write_wait_comp_event(cdm_args->cmd.cmd_buf_addr, + 0, CAM_CDM_WAIT_COMP_EVENT_BIT); + cdm_args->cmd.used_bytes = (size * 4); + + return 0; +} + +static int cam_vfe_top_add_wait_trigger(struct cam_vfe_top_ver3_priv *top_priv, + 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_top_ver3_reg_offset_common *reg_common = NULL; + uint32_t set_cdm_trigger_event; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "Error, Invalid arg size = %d expected = %d", + arg_size, sizeof(struct cam_isp_hw_get_cmd_update)); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "Error, 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; + } + + 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; + } + + if (cdm_args->trigger_cdm_en == true) + set_cdm_trigger_event = 1; + else + set_cdm_trigger_event = 0; + + reg_common = top_priv->common_data.common_reg; + reg_val_pair[0] = reg_common->trigger_cdm_events; + reg_val_pair[1] = set_cdm_trigger_event; + + 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_top_ver3_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size) { @@ -561,6 +658,12 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_CORE_CONFIG: rc = cam_vfe_core_config_control(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_ADD_WAIT: + rc = cam_vfe_top_wait_comp_event(top_priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: + rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type); From 1befcf3a1a4d364cc47a3d4defe2a30a7eee2b27 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Tue, 10 Dec 2019 18:45:03 +0530 Subject: [PATCH 315/790] msm: camera: isp: Add header files and hardware updates For lagoon, few changes in CSID and IFE to handle the dual vfe sync and halt. For CSID, while handling the halt, external and internal core configuration is changed. For VFE, 3 IFE support is possible with the combinations: 0-1, 1-2, 0-2. This requires changes in dual vfe sync handling. Also, CSID and IFE versions are updated. This commit adds the driver header files for the version and handles the hardware changes in the driver. CRs-Fixed: 2571273 Change-Id: I48fd3319692cc1044beb20c278cc2fe5676cb668 Signed-off-by: Gaurav Jindal Signed-off-by: Vishalsingh Hajeri --- .../isp_hw/ife_csid_hw/cam_ife_csid170_200.h | 368 ++++++++ .../isp_hw/ife_csid_hw/cam_ife_csid17x.c | 10 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 140 +-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 +- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c | 5 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h | 850 ++++++++++++++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 2 + .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 13 + .../vfe_hw/vfe_top/cam_vfe_camif_ver2.h | 4 +- 9 files changed, 1330 insertions(+), 66 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h new file mode 100644 index 000000000000..47cb02492412 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_IFE_CSID_170_200_H_ +#define _CAM_IFE_CSID_170_200_H_ + +#include "cam_ife_csid_core.h" + +static struct cam_ife_csid_pxl_reg_offset + cam_ife_csid_170_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, + .quad_cfa_bin_en_shift_val = 30, + .ccif_violation_en = 1, + .halt_master_sel_en = 1, + .halt_sel_internal_master_val = 3, +}; + +static struct cam_ife_csid_pxl_reg_offset + cam_ife_csid_170_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, + .halt_master_sel_en = 1, + .halt_sel_internal_master_val = 3, +}; + + +static struct cam_ife_csid_rdi_reg_offset + cam_ife_csid_170_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_170_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_170_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_170_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_170_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_170_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 = 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, + .path_rst_done_shift_val = 1, + .path_en_shift_val = 31, + .packing_fmt_shift_val = 30, + .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_170_200_reg_offset = { + .cmn_reg = &cam_ife_csid_170_200_cmn_reg_offset, + .csi2_reg = &cam_ife_csid_170_200_csi2_reg_offset, + .ipp_reg = &cam_ife_csid_170_200_ipp_reg_offset, + .ppp_reg = &cam_ife_csid_170_200_ppp_reg_offset, + .rdi_reg = { + &cam_ife_csid_170_200_rdi_0_reg_offset, + &cam_ife_csid_170_200_rdi_1_reg_offset, + &cam_ife_csid_170_200_rdi_2_reg_offset, + NULL, + }, + .tpg_reg = &cam_ife_csid_170_200_tpg_reg_offset, +}; + +#endif /*_CAM_IFE_CSID_170_200_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c index 972994f53e8c..a59903040257 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c @@ -7,6 +7,7 @@ #include #include "cam_ife_csid_core.h" #include "cam_ife_csid170.h" +#include "cam_ife_csid170_200.h" #include "cam_ife_csid175.h" #include "cam_ife_csid175_200.h" #include "cam_ife_csid480.h" @@ -23,6 +24,11 @@ static struct cam_ife_csid_hw_info cam_ife_csid170_hw_info = { .hw_dts_version = CAM_CSID_VERSION_V170, }; +static struct cam_ife_csid_hw_info cam_ife_csid170_200_hw_info = { + .csid_reg = &cam_ife_csid_170_200_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, @@ -43,6 +49,10 @@ static const struct of_device_id cam_ife_csid17x_dt_match[] = { .compatible = "qcom,csid170", .data = &cam_ife_csid170_hw_info, }, + { + .compatible = "qcom,csid170_200", + .data = &cam_ife_csid170_200_hw_info, + }, { .compatible = "qcom,csid175", .data = &cam_ife_csid175_hw_info, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 84c9b1702d88..19c29da3c2ec 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -772,6 +772,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_CPAS_TITAN_170_V100: case CAM_CPAS_TITAN_170_V110: case CAM_CPAS_TITAN_170_V120: + case CAM_CPAS_TITAN_170_V200: if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_PHY_3 && csid_hw->hw_intf->hw_idx != 2) { rc = -EINVAL; @@ -828,28 +829,31 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, goto end; } - if (cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { - if (csid_hw->csi2_rx_cfg.lane_cfg != - cid_reserv->in_port->lane_cfg || - csid_hw->csi2_rx_cfg.lane_type != - cid_reserv->in_port->lane_type || - csid_hw->csi2_rx_cfg.lane_num != - cid_reserv->in_port->lane_num) { - rc = -EINVAL; - goto end; - } - } else { - if (csid_hw->tpg_cfg.in_format != - cid_reserv->in_port->format || - csid_hw->tpg_cfg.width != - cid_reserv->in_port->left_width || - csid_hw->tpg_cfg.height != - cid_reserv->in_port->height || - csid_hw->tpg_cfg.test_pattern != - cid_reserv->in_port->test_pattern) { - rc = -EINVAL; - goto end; - } + if ((cid_reserv->in_port->res_type != + CAM_ISP_IFE_IN_RES_TPG) && + (csid_hw->csi2_rx_cfg.lane_cfg != + cid_reserv->in_port->lane_cfg || + csid_hw->csi2_rx_cfg.lane_type != + cid_reserv->in_port->lane_type || + csid_hw->csi2_rx_cfg.lane_num != + cid_reserv->in_port->lane_num)) { + + rc = -EINVAL; + goto end; + } + if ((cid_reserv->in_port->res_type == + CAM_ISP_IFE_IN_RES_TPG) && + (csid_hw->tpg_cfg.in_format != + cid_reserv->in_port->format || + csid_hw->tpg_cfg.width != + cid_reserv->in_port->left_width || + csid_hw->tpg_cfg.height != + cid_reserv->in_port->height || + csid_hw->tpg_cfg.test_pattern != + cid_reserv->in_port->test_pattern)) { + + rc = -EINVAL; + goto end; } } @@ -934,45 +938,45 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->csi2_rx_cfg.lane_num = cid_reserv->in_port->lane_num; - if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { - csid_hw->csi2_rx_cfg.phy_sel = 0; - if (cid_reserv->in_port->format > - CAM_FORMAT_MIPI_RAW_16) { - CAM_ERR(CAM_ISP, " Wrong TPG format"); - rc = -EINVAL; - goto end; - } - csid_hw->tpg_cfg.in_format = - cid_reserv->in_port->format; - csid_hw->tpg_cfg.usage_type = - cid_reserv->in_port->usage_type; - if (cid_reserv->in_port->usage_type) - csid_hw->tpg_cfg.width = - (cid_reserv->in_port->right_stop + 1); - else - csid_hw->tpg_cfg.width = - cid_reserv->in_port->left_width; - - csid_hw->tpg_cfg.height = cid_reserv->in_port->height; - csid_hw->tpg_cfg.test_pattern = - cid_reserv->in_port->test_pattern; - - CAM_DBG(CAM_ISP, "CSID:%d TPG width:%d height:%d", - csid_hw->hw_intf->hw_idx, - csid_hw->tpg_cfg.width, - csid_hw->tpg_cfg.height); - - cid_data->tpg_set = 1; - } else if (cid_reserv->in_port->res_type == - CAM_ISP_IFE_IN_RES_CPHY_TPG_0) { - csid_hw->csi2_rx_cfg.phy_sel = 0; - } else if (cid_reserv->in_port->res_type == - CAM_ISP_IFE_IN_RES_CPHY_TPG_1) { - csid_hw->csi2_rx_cfg.phy_sel = 1; - } else { + if (cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { csid_hw->csi2_rx_cfg.phy_sel = (cid_reserv->in_port->res_type & 0xFF) - 1; + csid_hw->csi2_reserve_cnt++; + CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired", + csid_hw->hw_intf->hw_idx, + cid_reserv->node_res->res_id); + goto end; } + + /* Below code is executed only for TPG in_res type */ + csid_hw->csi2_rx_cfg.phy_sel = 0; + if (cid_reserv->in_port->format > + CAM_FORMAT_MIPI_RAW_16) { + CAM_ERR(CAM_ISP, " Wrong TPG format"); + rc = -EINVAL; + goto end; + } + csid_hw->tpg_cfg.in_format = + cid_reserv->in_port->format; + csid_hw->tpg_cfg.usage_type = + cid_reserv->in_port->usage_type; + if (cid_reserv->in_port->usage_type) + csid_hw->tpg_cfg.width = + (cid_reserv->in_port->right_stop + 1); + else + csid_hw->tpg_cfg.width = + cid_reserv->in_port->left_width; + + csid_hw->tpg_cfg.height = cid_reserv->in_port->height; + csid_hw->tpg_cfg.test_pattern = + cid_reserv->in_port->test_pattern; + + CAM_DBG(CAM_ISP, "CSID:%d TPG width:%d height:%d", + csid_hw->hw_intf->hw_idx, + csid_hw->tpg_cfg.width, + csid_hw->tpg_cfg.height); + + cid_data->tpg_set = 1; } csid_hw->csi2_reserve_cnt++; @@ -2023,16 +2027,24 @@ static int cam_ife_csid_enable_pxl_path( CAM_DBG(CAM_ISP, "Enable %s path", (is_ipp) ? "IPP" : "PPP"); /* Set master or slave path */ - if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) + if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) { /*Set halt mode as master */ - val = CSID_HALT_MODE_MASTER << 2; - else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + if (pxl_reg->halt_master_sel_en) + val = pxl_reg->halt_sel_internal_master_val << 4 | + CSID_HALT_MODE_MASTER << 2; + else + val = CSID_HALT_MODE_MASTER << 2; + } else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { /*Set halt mode as slave and set master idx */ - val = path_data->master_idx << 4 | CSID_HALT_MODE_SLAVE << 2; - else + if (pxl_reg->halt_master_sel_en) + val = CSID_HALT_MODE_SLAVE << 2; + else + val = path_data->master_idx << 4 | + CSID_HALT_MODE_SLAVE << 2; + } else { /* Default is internal halt mode */ val = 0; - + } /* * Resume at frame boundary if Master or No Sync. * Slave will get resume command from Master. diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index ab2ea20a045f..71a451b89198 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_HW_H_ @@ -139,6 +139,8 @@ struct cam_ife_csid_pxl_reg_offset { uint32_t quad_cfa_bin_en_shift_val; uint32_t ccif_violation_en; uint32_t overflow_ctrl_en; + uint32_t halt_master_sel_en; + uint32_t halt_sel_internal_master_val; }; struct cam_ife_csid_rdi_reg_offset { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c index 461b66cd081e..7bc27a1b63bc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c @@ -5,6 +5,7 @@ #include #include "cam_vfe170.h" +#include "cam_vfe170_150.h" #include "cam_vfe175.h" #include "cam_vfe175_130.h" #include "cam_vfe480.h" @@ -21,6 +22,10 @@ static const struct of_device_id cam_vfe_dt_match[] = { .compatible = "qcom,vfe170", .data = &cam_vfe170_hw_info, }, + { + .compatible = "qcom,vfe170_150", + .data = &cam_vfe170_150_hw_info, + }, { .compatible = "qcom,vfe175", .data = &cam_vfe175_hw_info, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h new file mode 100644 index 000000000000..df5cc3594b98 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h @@ -0,0 +1,850 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE170_150_H_ +#define _CAM_VFE170_150_H_ + +#include "cam_vfe_camif_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_150_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_150_top_irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe170_150_top_irq_reg_set, + .global_clear_offset = 0x00000058, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_camif_ver2_reg vfe170_150_camif_reg = { + .dual_vfe_sync = 0x00000100, + .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_170_150_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 = 0x0FFF7E80, + .enable_diagnostic_hw = 0x1, + .dual_vfe_sync_mask = 0x3, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_150_reg = { + .reset = 0x0000001C, + .cgc_ovd = 0x0000002C, + .enable = 0x00000040, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_150_reg = { + .reset = 0x00000020, + .cgc_ovd = 0x00000030, + .enable = 0x00000044, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_150_reg = { + .reset = 0x00000024, + .cgc_ovd = 0x00000034, + .enable = 0x00000048, +}; + +struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_150_reg = { + .reset = 0x00000028, + .cgc_ovd = 0x00000038, + .enable = 0x0000004C, +}; + +static struct cam_vfe_top_ver2_reg_offset_common vfe170_150_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_170_150_reg, + &stats_170_150_reg, + &color_170_150_reg, + &zoom_170_150_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 vfe170_150_rdi_reg = { + .reg_update_cmd = 0x000004AC, +}; + +static struct cam_vfe_rdi_reg_data vfe_170_150_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_150_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_150_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_150_top_hw_info = { + .common_reg = &vfe170_150_top_common_reg, + .camif_hw_info = { + .common_reg = &vfe170_150_top_common_reg, + .camif_reg = &vfe170_150_camif_reg, + .reg_data = &vfe_170_150_camif_reg_data, + }, + .camif_lite_hw_info = { + .common_reg = NULL, + .camif_lite_reg = NULL, + .reg_data = NULL, + }, + .rdi_hw_info = { + .common_reg = &vfe170_150_top_common_reg, + .rdi_reg = &vfe170_150_rdi_reg, + .reg_data = { + &vfe_170_150_rdi_0_data, + &vfe_170_150_rdi_1_data, + &vfe_170_150_rdi_2_data, + NULL, + }, + }, + .num_mux = 4, + .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, + }, +}; + +static struct cam_irq_register_set vfe170_150_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_client + vfe_170_150_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, + .bw_limit = 0x000025A0, +}; + +static struct cam_vfe_bus_ver2_reg_offset_ubwc_client + vfe_170_150_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, + .bw_limit = 0x000026A0, +}; + +static struct cam_vfe_bus_ver2_hw_info vfe170_150_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_150_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, + .debug_status_cfg = 0x0000226C, + .debug_status_0 = 0x00002270, + }, + .num_client = 20, + .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 = + &vfe_170_150_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 = + &vfe_170_150_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, + }, + }, + .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 = 18, + .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, + }, + }, +}; + +struct cam_vfe_hw_info cam_vfe170_150_hw_info = { + .irq_reg_info = &vfe170_150_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_2_0, + .bus_hw_info = &vfe170_150_bus_hw_info, + + .top_version = CAM_VFE_TOP_VER_2_0, + .top_hw_info = &vfe170_150_top_hw_info, + + .camif_version = CAM_VFE_CAMIF_VER_2_0, + .camif_reg = &vfe170_150_camif_reg, + + .camif_lite_version = 0, + .camif_lite_reg = NULL, + +}; + +#endif /* _CAM_vfe170_150_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index aeb154482d17..ae705f265af1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -2594,6 +2594,7 @@ static void cam_vfe_bus_update_ubwc_meta_addr( case CAM_CPAS_TITAN_170_V100: case CAM_CPAS_TITAN_170_V110: case CAM_CPAS_TITAN_170_V120: + case CAM_CPAS_TITAN_170_V200: ubwc_regs = (struct cam_vfe_bus_ver2_reg_offset_ubwc_client *)regs; CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, @@ -2811,6 +2812,7 @@ static int cam_vfe_bus_update_ubwc_regs( case CAM_CPAS_TITAN_170_V100: case CAM_CPAS_TITAN_170_V110: case CAM_CPAS_TITAN_170_V120: + case CAM_CPAS_TITAN_170_V200: rc = cam_vfe_bus_update_ubwc_legacy_regs( wm_data, camera_hw_version, reg_val_pair, i, j); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index bcc67aad48d2..55a94c843dfb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -48,6 +48,7 @@ struct cam_vfe_mux_camif_data { bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; + uint32_t dual_hw_idx; uint32_t is_dual; }; @@ -259,6 +260,10 @@ int cam_vfe_camif_ver2_acquire_resource( camif_data->priv = acquire_data->priv; camif_data->is_dual = acquire_data->vfe_in.is_dual; + if (acquire_data->vfe_in.is_dual) + camif_data->dual_hw_idx = + acquire_data->vfe_in.dual_hw_idx; + CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d", camif_res->hw_intf->hw_idx, camif_data->pix_pattern, camif_data->dsp_mode); @@ -330,6 +335,7 @@ static int cam_vfe_camif_resource_start( int rc = 0; uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t dual_vfe_sync_val; struct cam_vfe_soc_private *soc_private; if (!camif_res) { @@ -390,6 +396,7 @@ static int cam_vfe_camif_resource_start( case CAM_CPAS_TITAN_170_V100: case CAM_CPAS_TITAN_170_V110: case CAM_CPAS_TITAN_170_V120: + case CAM_CPAS_TITAN_170_V200: cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg, rsrc_data->mem_base + rsrc_data->camif_reg->epoch_irq); @@ -414,6 +421,12 @@ static int cam_vfe_camif_resource_start( break; } + if (rsrc_data->is_dual && rsrc_data->reg_data->dual_vfe_sync_mask) { + dual_vfe_sync_val = (rsrc_data->dual_hw_idx & + rsrc_data->reg_data->dual_vfe_sync_mask) + 1; + cam_io_w_mb(dual_vfe_sync_val, rsrc_data->mem_base + + rsrc_data->camif_reg->dual_vfe_sync); + } camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; /* Reg Update */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h index f071a0627bbc..26522594b97b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_CAMIF_VER2_H_ @@ -22,6 +22,7 @@ struct cam_vfe_camif_ver2_reg { uint32_t reg_update_cmd; uint32_t vfe_diag_config; uint32_t vfe_diag_sensor_status; + uint32_t dual_vfe_sync; }; struct cam_vfe_camif_reg_data { @@ -62,6 +63,7 @@ struct cam_vfe_camif_reg_data { uint32_t subscribe_irq_mask1; uint32_t enable_diagnostic_hw; + uint32_t dual_vfe_sync_mask; }; struct cam_vfe_camif_ver2_hw_info { From ede10a204811616bec4ef877a5af8aa1a1926d93 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 21 Feb 2020 16:22:27 +0530 Subject: [PATCH 316/790] msm: camera: reqmgr: increase the rd idx if no lower pd device For link with maximum pipeline delay of 1 e.g., TPG use case or sensors with pipeline delay of 1, if the request is not submitted before 2 consecutive triggers we do not get chance to increment rd idx, in the mean time the slot which was last applied will be reset and we will not be able to apply request even if new requests are scheduled. This will cause the camera to not apply any request further, hence increasing the rd idx if no lower pd devices are pending will fix the issue. CRs-Fixed: 2622845 Change-Id: I012e242c7fca22abecc171ef4d7063d851bb5748 Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_req_mgr_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index c78e8e39879b..5359cf1e7f8d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2683,6 +2683,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) CAM_DBG(CAM_REQ, "No pending req to apply to lower pd devices"); rc = 0; + __cam_req_mgr_inc_idx(&in_q->rd_idx, + 1, in_q->num_slots); goto release_lock; } __cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots); From 4f1388a7b0f41a4e3b87a2e9e6702cf4f44b951f Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 16 Mar 2020 21:24:05 +0530 Subject: [PATCH 317/790] msm: camera: cpas: Update camnoc axi port vote during cpas start/stop For some cpas clients like csiphy, cci voting is applied and removed during their respective start and stop flow. Such clients do no call for vote update explicitly. For such cases, camnoc axi ports were not updated. This can result in camnoc_sf vote to be present. This commit updates the camnoc ports as well for the clients for who the voting is applied and removed during the start and stop only. CRs-Fixed: 2571273 Change-Id: I2997e5abad904532dc0d582edbf6d6078ac732d7 Signed-off-by: Gaurav Jindal --- drivers/cam_cpas/cam_cpas_hw.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 23c045bd1044..8fd153169d89 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -708,6 +708,20 @@ static int cam_cpas_util_apply_client_axi_vote( } mnoc_axi_port_updated[i] = true; } + + for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { + if (axi_vote->axi_path[0].camnoc_bw) { + /* start case */ + cpas_core->camnoc_axi_port[i].additional_bw += + CAM_CPAS_DEFAULT_AXI_BW; + } else { + /* stop case */ + cpas_core->camnoc_axi_port[i].additional_bw -= + CAM_CPAS_DEFAULT_AXI_BW; + } + camnoc_axi_port_updated[i] = true; + } + goto vote_start_clients; } From ae5d1857a3e24f2634853b32b5ec12aa8b15ca50 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 19 Mar 2020 11:03:04 +0530 Subject: [PATCH 318/790] msm: camera: isp: variable should be accessed only if match is found There is a possibility that the priority variable would be accessed even for the HEAD node which would result in out of bound errors, so access the elements of the structure only if the handler is found. CRs-Fixed: 2646173 Change-Id: I0540658b9c9487f6e3a4601a488a1add1e790dda Signed-off-by: Tejas Prajapati --- .../isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index 1e138bac5f92..83d4a61a2682 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -515,8 +515,8 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller, } } - priority = evt_handler->priority; if (found) { + priority = evt_handler->priority; for (i = 0; i < controller->num_registers; i++) { irq_register = &controller->irq_register_arr[i]; irq_register->top_half_enable_mask[priority] &= From 2b5f77663052d77f82e109e8d4649cf7ad996977 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Fri, 3 Apr 2020 16:26:06 -0700 Subject: [PATCH 319/790] msm: camera: ife: Re-enable auto clock gating Auto clock gating was disabled to aid in certain debug scenarios. However, for normal operation the expectation is for auto clock gating to be enabled. The writes could be removed as enabled is the default, but no harm in being explicit. CRs-Fixed: 2584631 Change-Id: I63336d12b94f270c4962281e14e879a6207ea386 Signed-off-by: Fernando Pacheco --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index a750e7d2ee99..e632596991bb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -323,19 +323,23 @@ int cam_vfe_top_ver3_init_hw(void *device_priv, top_priv->hw_clk_rate = 0; - /* Disable clock gating at IFE top */ - CAM_INFO(CAM_ISP, "Disable clock gating at IFE top"); - cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->core_cgc_ovd_0, 0xFFFFFFFF); + /** + * Auto clock gating is enabled by default, but no harm + * in setting the value we expect. + */ + CAM_INFO(CAM_ISP, "Enabling clock gating at IFE top"); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->core_cgc_ovd_1, 0xFF); + common_data.common_reg->core_cgc_ovd_0, 0x0); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->ahb_cgc_ovd, 0x1); + common_data.common_reg->core_cgc_ovd_1, 0x0); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->noc_cgc_ovd, 0x1); + common_data.common_reg->ahb_cgc_ovd, 0x0); + + cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, + common_data.common_reg->noc_cgc_ovd, 0x0); return 0; } From eb919ee4dce39ac5bc0f531d5e854669836f0d81 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Tue, 18 Feb 2020 11:49:52 +0530 Subject: [PATCH 320/790] msm: camera: csiphy: Secure cam usecase not working Secure CP control register always assume that it contains 7 bit mask for each PHY. But this register format is different based on target. Update secure CP control bitmask generation logic for each PHY index based on phy_version. So we have below 3 combinations to handle at SW. 1.Old Titan Targets : 7 bits for each PHY. 2.PHY 1_2_1 : for 4 pHYS 7 bits and for remaining 2 PHYs 8 bits are reserved. 3.Mimas (PHY 2_0_1): 8 bits for each PHY. CRs-Fixed: 2624698 Change-Id: Iac4c3c718fc96a51592e07b45458fb045c52366d Signed-off-by: Anil Kumar Kanakanti --- .../cam_csiphy/cam_csiphy_core.c | 60 ++++++++++++++++--- .../cam_csiphy/cam_csiphy_soc.c | 17 ++++++ .../cam_csiphy/cam_csiphy_soc.h | 1 + 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index ec8dd1ae685b..69ebbda53dee 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -19,6 +19,9 @@ #define LANE_MASK_2PH 0x1F #define LANE_MASK_3PH 0x7 +#define SEC_LANE_CP_REG_LEN 32 +#define MAX_PHY_MSK_PER_REG 4 + static int csiphy_dump; module_param(csiphy_dump, int, 0644); @@ -80,7 +83,7 @@ int32_t cam_csiphy_update_secure_info( struct cam_csiphy_info *cam_cmd_csiphy_info, struct cam_config_dev_cmd *cfg_dev) { - uint32_t clock_lane, adj_lane_mask, temp; + uint32_t clock_lane, adj_lane_mask, temp, phy_mask_len; int32_t offset; if (csiphy_dev->acquire_count >= @@ -114,12 +117,37 @@ int32_t cam_csiphy_update_secure_info( csiphy_dev->csiphy_info.secure_mode[offset] = 1; - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = - adj_lane_mask << (csiphy_dev->soc_info.index * - (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) + - (!cam_cmd_csiphy_info->csiphy_3phase) * - (CAM_CSIPHY_MAX_CPHY_LANES)); + if (csiphy_dev->hw_version == CSIPHY_VERSION_V201) { + phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + + CAM_CSIPHY_MAX_CPHY_LANES + 1; + } else if (csiphy_dev->hw_version == CSIPHY_VERSION_V121) { + phy_mask_len = + (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) ? + CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES : + CAM_CSIPHY_MAX_DPHY_LANES + + CAM_CSIPHY_MAX_CPHY_LANES + 1; + } else { + phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + + CAM_CSIPHY_MAX_CPHY_LANES; + } + if (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) { + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = + ((uint64_t)adj_lane_mask) << + (csiphy_dev->soc_info.index * phy_mask_len + + (!cam_cmd_csiphy_info->csiphy_3phase) * + (CAM_CSIPHY_MAX_CPHY_LANES)); + } else { + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = + ((uint64_t)adj_lane_mask) << + ((csiphy_dev->soc_info.index - MAX_PHY_MSK_PER_REG) * + phy_mask_len + SEC_LANE_CP_REG_LEN + + (!cam_cmd_csiphy_info->csiphy_3phase) * + (CAM_CSIPHY_MAX_CPHY_LANES)); + } + CAM_DBG(CAM_CSIPHY, "csi phy idx:%d, cp_reg_mask:0x%lx", + csiphy_dev->soc_info.index, + csiphy_dev->csiphy_cpas_cp_reg_mask[offset]); return 0; } @@ -216,6 +244,24 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, cam_csiphy_update_secure_info(csiphy_dev, cam_cmd_csiphy_info, cfg_dev); + CAM_DBG(CAM_CSIPHY, + "phy version_%d, lane count:%d, mask:0x%x", + csiphy_dev->hw_version, + csiphy_dev->csiphy_info.lane_cnt, + csiphy_dev->csiphy_info.lane_mask + ); + CAM_DBG(CAM_CSIPHY, + "3phase:%d, combo mode:%d, secure mode:%d", + csiphy_dev->csiphy_info.csiphy_3phase, + csiphy_dev->csiphy_info.combo_mode, + cam_cmd_csiphy_info->secure_mode + ); + CAM_DBG(CAM_CSIPHY, + "phy idx:%d, settle time:%d, datarate:%d", + csiphy_dev->soc_info.index, + csiphy_dev->csiphy_info.settle_time, + csiphy_dev->csiphy_info.data_rate); + return rc; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 6b6b67b3d73d..781baa499c1f 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -370,6 +370,23 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->is_divisor_32_comp = false; csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v2.0.1")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v2_0_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v2_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_2_0; + csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_2_0; + csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_2_0; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v2_0; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->hw_version = CSIPHY_VERSION_V201; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; } else { CAM_ERR(CAM_CSIPHY, "invalid hw version : 0x%x", csiphy_dev->hw_version); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index e68ec2a58de0..1f08193de2a6 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -32,6 +32,7 @@ #define CSIPHY_VERSION_V121 0x121 #define CSIPHY_VERSION_V123 0x123 #define CSIPHY_VERSION_V20 0x20 +#define CSIPHY_VERSION_V201 0x201 /** * @csiphy_dev: CSIPhy device structure From 54bddb9d741788db0ce05497b20218a8411d08ff Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Fri, 10 Apr 2020 15:22:15 -0700 Subject: [PATCH 321/790] msm: camera: isp: change variables declaration to static Static variables are initialized only once and the compiler persists with the variable till the end of the program hence declaring some of the varaibles in header files as static. CRs-Fixed: 2663712 Change-Id: I55265f5ac1d144ae5b5c62a9984c08d242be157d Signed-off-by: Vishalsingh Hajeri --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 12 ++++++------ .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h | 10 +++++----- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 10 +++++----- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 10 +++++----- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 2 +- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index 07d821871b5e..a16c9d510f40 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -77,25 +77,25 @@ static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = { .enable_diagnostic_hw = 0x1, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = { .reset = 0x0000001C, .cgc_ovd = 0x0000002C, .enable = 0x00000040, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_reg = { .reset = 0x00000020, .cgc_ovd = 0x00000030, .enable = 0x00000044, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_reg = { .reset = 0x00000024, .cgc_ovd = 0x00000034, .enable = 0x00000048, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_reg = { .reset = 0x00000028, .cgc_ovd = 0x00000038, .enable = 0x0000004C, @@ -853,7 +853,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { .top_irq_shift = 9, }; -struct cam_vfe_hw_info cam_vfe170_hw_info = { +static struct cam_vfe_hw_info cam_vfe170_hw_info = { .irq_reg_info = &vfe170_top_irq_reg_info, .bus_version = CAM_VFE_BUS_VER_2_0, @@ -866,7 +866,7 @@ struct cam_vfe_hw_info cam_vfe170_hw_info = { .camif_reg = &vfe170_camif_reg, .camif_lite_version = 0, - .camif_reg = NULL, + .camif_lite_reg = NULL, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h index df5cc3594b98..9aa1c05c1904 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h @@ -79,25 +79,25 @@ static struct cam_vfe_camif_reg_data vfe_170_150_camif_reg_data = { .dual_vfe_sync_mask = 0x3, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_150_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_150_reg = { .reset = 0x0000001C, .cgc_ovd = 0x0000002C, .enable = 0x00000040, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_150_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_150_reg = { .reset = 0x00000020, .cgc_ovd = 0x00000030, .enable = 0x00000044, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_150_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_150_reg = { .reset = 0x00000024, .cgc_ovd = 0x00000034, .enable = 0x00000048, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_150_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_150_reg = { .reset = 0x00000028, .cgc_ovd = 0x00000038, .enable = 0x0000004C, @@ -830,7 +830,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_150_bus_hw_info = { }, }; -struct cam_vfe_hw_info cam_vfe170_150_hw_info = { +static struct cam_vfe_hw_info cam_vfe170_150_hw_info = { .irq_reg_info = &vfe170_150_top_irq_reg_info, .bus_version = CAM_VFE_BUS_VER_2_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index ccc771c993c2..111eb486d592 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -104,25 +104,25 @@ static struct cam_vfe_camif_lite_ver2_reg_data vfe175_camif_lite_reg_data = { .dual_pd_path_sel_shift = 24, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_reg = { +static 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_175_reg = { +static 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_175_reg = { +static 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_175_reg = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_reg = { .reset = 0x00000028, .cgc_ovd = 0x00000038, .enable = 0x0000004C, @@ -1023,7 +1023,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { .top_irq_shift = 9, }; -struct cam_vfe_hw_info cam_vfe175_hw_info = { +static 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, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 7573407af078..a1df85c12388 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -152,25 +152,25 @@ static struct cam_vfe_camif_lite_ver2_reg_data .dual_pd_path_sel_shift = 24, }; -struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_130_reg = { +static 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 = { +static 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 = { +static 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 = { +static struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_130_reg = { .reset = 0x00000028, .cgc_ovd = 0x00000038, .enable = 0x0000004C, @@ -1129,7 +1129,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { .top_irq_shift = 9, }; -struct cam_vfe_hw_info cam_vfe175_130_hw_info = { +static 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, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 359c43ae0c6f..1d9173a0c73b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1364,7 +1364,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe480_bus_rd_hw_info = { .top_irq_shift = 8, }; -struct cam_vfe_hw_info cam_vfe480_hw_info = { +static struct cam_vfe_hw_info cam_vfe480_hw_info = { .irq_reg_info = &vfe480_top_irq_reg_info, .bus_version = CAM_VFE_BUS_VER_3_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h index 8bb01532e807..8c854a5f5482 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe580.h @@ -105,7 +105,7 @@ static struct cam_vfe_top_ver3_hw_info vfe580_top_hw_info = { }, }; -struct cam_vfe_hw_info cam_vfe580_hw_info = { +static struct cam_vfe_hw_info cam_vfe580_hw_info = { .irq_reg_info = &vfe480_top_irq_reg_info, .bus_version = CAM_VFE_BUS_VER_3_0, From b318b39465793328819400479081e914217f0c46 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Wed, 25 Mar 2020 18:12:08 -0700 Subject: [PATCH 322/790] msm: camera: config: Do not compile camera sources for VM image Do not compile camera sources for VM image for lahaina. Guard the source path against CONFIG_QTI_VM to decide to compile it are not. CRs-Fixed: 2663712 Change-Id: I4a624cf8d9824b545c8fb70c134a3b7011c4d2ca Signed-off-by: Vishalsingh Hajeri --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index c24393bede31..3e82a6fc6ccd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only # auto-detect subdirs +ifneq ($(CONFIG_ARCH_QTI_VM), y) ifeq ($(CONFIG_ARCH_KONA), y) include $(srctree)/techpack/camera/config/konacamera.conf endif @@ -36,6 +37,7 @@ ifeq ($(CONFIG_ARCH_LAHAINA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/lahainacameraconf.h endif +endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) # Use USERINCLUDE when you must reference the UAPI directories only. From b7235bc92c9d028cf27fc69db4a50381f7127c4b Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 3 Feb 2020 17:45:14 +0530 Subject: [PATCH 323/790] msm: camera: ife: IFE debug enhancement for overflow debugging In many error cases it is required to know the bandwidth applied on axi ports and camnoc axi clock rate values. Added cpas api to print the current axi bus votes, camnoc axi clock and ahb vote level.This api can be called for isp errors such as bus overflow, pxl overflow cases. On RDI overflow printing last applied IFE clock, dumping the CAMNOC fill-level registers to know the pending and queued transactions, SOF EPOCH and EOF timing to know exactly at what time the RDI overflow came, Width and height of specific Write master. CRs-Fixed: 2623885 Change-Id: I92a9097efe9f6726748ec27ca39dd51c8c6de1b6 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_hw.c | 69 ++++++++++- drivers/cam_cpas/cam_cpas_hw.h | 6 + drivers/cam_cpas/cam_cpas_hw_intf.h | 3 +- drivers/cam_cpas/cam_cpas_intf.c | 24 ++++ drivers/cam_cpas/include/cam_cpas_api.h | 10 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 82 ++++++++++++- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 2 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h | 4 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 13 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 9 ++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 43 +++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 95 +++++++-------- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c | 72 ++++++++++- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 68 ++++++++++- .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 67 +++++++++- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 68 ++++++++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 115 +++++++++++++++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h | 11 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 28 ++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 17 +++ 21 files changed, 732 insertions(+), 76 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 8fd153169d89..e45145090bd9 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -81,7 +81,7 @@ end: static int cam_cpas_util_vote_bus_client_bw( struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib, - bool camnoc_bw) + bool camnoc_bw, uint64_t *applied_ab, uint64_t *applied_ib) { int rc = 0; uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; @@ -124,6 +124,11 @@ static int cam_cpas_util_vote_bus_client_bw( goto unlock_client; } + if (applied_ab) + *applied_ab = ab; + if (applied_ib) + *applied_ib = ib; + unlock_client: mutex_unlock(&bus_client->lock); end: @@ -242,6 +247,7 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, int rc, i = 0; struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info; uint64_t ab_bw, ib_bw; + uint64_t applied_ab_bw = 0, applied_ib_bw = 0; rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client, (enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE); @@ -262,13 +268,15 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, for (i = 0; i < cpas_core->num_axi_ports; i++) { rc = cam_cpas_util_vote_bus_client_bw( &cpas_core->axi_port[i].bus_client, - ab_bw, ib_bw, false); + ab_bw, ib_bw, false, &applied_ab_bw, &applied_ib_bw); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote, enable=%d, rc=%d", enable, rc); goto remove_ahb_vote; } + cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw; + cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw; } return 0; @@ -434,6 +442,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( CAM_ERR(CAM_CPAS, "Failed in setting camnoc axi clk %llu %d %d", required_camnoc_bw, clk_rate, rc); + + cpas_core->applied_camnoc_axi_rate = clk_rate; } } @@ -615,6 +625,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( int rc = 0; struct cam_cpas_axi_port *camnoc_axi_port = NULL; uint64_t camnoc_bw; + uint64_t applied_ab = 0, applied_ib = 0; if (soc_private->control_camnoc_axi_clk) { rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); @@ -655,7 +666,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( rc = cam_cpas_util_vote_bus_client_bw( &camnoc_axi_port->bus_client, - 0, camnoc_bw, true); + 0, camnoc_bw, true, &applied_ab, &applied_ib); CAM_DBG(CAM_CPAS, "camnoc vote camnoc_bw[%llu] rc=%d %s", @@ -666,6 +677,8 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( camnoc_bw, rc); break; } + camnoc_axi_port->applied_ab_bw = applied_ab; + camnoc_axi_port->applied_ib_bw = applied_ib; } return rc; } @@ -688,6 +701,7 @@ static int cam_cpas_util_apply_client_axi_vote( curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0, par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0; int rc = 0, i = 0; + uint64_t applied_ab = 0, applied_ib = 0; mutex_lock(&cpas_core->tree_lock); if (!cpas_client->tree_node_valid) { @@ -863,13 +877,16 @@ vote_start_clients: rc = cam_cpas_util_vote_bus_client_bw( &mnoc_axi_port->bus_client, - mnoc_ab_bw, mnoc_ib_bw, false); + mnoc_ab_bw, mnoc_ib_bw, false, &applied_ab, + &applied_ib); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d", mnoc_ab_bw, mnoc_ib_bw, rc); goto unlock_tree; } + mnoc_axi_port->applied_ab_bw = applied_ab; + mnoc_axi_port->applied_ib_bw = applied_ib; } rc = cam_cpas_camnoc_set_vote_axi_clk_rate( cpas_hw, camnoc_axi_port_updated); @@ -1616,6 +1633,46 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, return 0; } +static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + int rc = 0; + uint32_t i; + + for (i = 0; i < cpas_core->num_axi_ports; i++) { + CAM_INFO(CAM_CPAS, + "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", + cpas_core->axi_port[i].axi_port_name, + cpas_core->axi_port[i].ab_bw, + cpas_core->axi_port[i].ib_bw, + cpas_core->axi_port[i].additional_bw, + cpas_core->axi_port[i].applied_ab_bw, + cpas_core->axi_port[i].applied_ib_bw); + } + + if (soc_private->control_camnoc_axi_clk) { + CAM_INFO(CAM_CPAS, "applied camnoc axi clk[%lld]", + cpas_core->applied_camnoc_axi_rate); + } else { + for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { + CAM_INFO(CAM_CPAS, + "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", + cpas_core->camnoc_axi_port[i].axi_port_name, + cpas_core->camnoc_axi_port[i].ab_bw, + cpas_core->camnoc_axi_port[i].ib_bw, + cpas_core->camnoc_axi_port[i].additional_bw, + cpas_core->camnoc_axi_port[i].applied_ab_bw, + cpas_core->camnoc_axi_port[i].applied_ib_bw); + } + } + + CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]", + cpas_core->ahb_bus_client.curr_vote_level); + + return rc; +} static int cam_cpas_hw_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -1719,6 +1776,10 @@ static int cam_cpas_hw_process_cmd(void *hw_priv, cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote); break; } + case CAM_CPAS_HW_CMD_LOG_VOTE: { + rc = cam_cpas_log_vote(hw_priv); + break; + } default: CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type); break; diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index ac692d9ff559..ca44666dd40f 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -144,6 +144,8 @@ struct cam_cpas_bus_client { * @ib_bw: IB bw value for this port * @camnoc_bw: CAMNOC bw value for this port * @additional_bw: Additional bandwidth to cover non-hw cpas clients + * @applied_ab_bw: applied ab bw for this port + * @applied_ib_bw: applied ib bw for this port */ struct cam_cpas_axi_port { const char *axi_port_name; @@ -154,6 +156,8 @@ struct cam_cpas_axi_port { uint64_t ib_bw; uint64_t camnoc_bw; uint64_t additional_bw; + uint64_t applied_ab_bw; + uint64_t applied_ib_bw; }; /** @@ -178,6 +182,7 @@ struct cam_cpas_axi_port { * @irq_count_wq: wait variable to ensure all irq's are handled * @dentry: debugfs file entry * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus + * @applied_camnoc_axi_rate: applied camnoc axi clock rate */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; @@ -199,6 +204,7 @@ struct cam_cpas { wait_queue_head_t irq_count_wq; struct dentry *dentry; bool ahb_bus_scaling_disable; + uint64_t applied_camnoc_axi_rate; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index 1c3c146e24e7..3e6ac167f478 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_INTF_H_ @@ -38,6 +38,7 @@ enum cam_cpas_hw_cmd_process { CAM_CPAS_HW_CMD_REG_READ, CAM_CPAS_HW_CMD_AHB_VOTE, CAM_CPAS_HW_CMD_AXI_VOTE, + CAM_CPAS_HW_CMD_LOG_VOTE, CAM_CPAS_HW_CMD_INVALID, }; diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f96da1779c2a..cc72cbf985b1 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -405,6 +405,30 @@ int cam_cpas_start(uint32_t client_handle, } EXPORT_SYMBOL(cam_cpas_start); +void cam_cpas_log_votes(void) +{ + uint32_t dummy_args; + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_LOG_VOTE, &dummy_args, + sizeof(dummy_args)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + } + +} +EXPORT_SYMBOL(cam_cpas_log_votes); + int cam_cpas_unregister_client(uint32_t client_handle) { int rc; diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 8423bc511d31..c13ac20e7b7b 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -622,5 +622,15 @@ const char *cam_cpas_axi_util_path_type_to_string( const char *cam_cpas_axi_util_trans_type_to_string( uint32_t path_data_type); +/** + * cam_cpas_log_votes() + * + * @brief: API to print the all bw votes of axi client. It also print the + * applied camnoc axi clock vote value and ahb vote value + * + * @return 0 on success. + * + */ +void cam_cpas_log_votes(void); #endif /* _CAM_CPAS_API_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d1cf9fd3eb50..045097aa2a7e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7118,14 +7118,86 @@ static int cam_ife_hw_mgr_find_affected_ctx( return 0; } +static int cam_ife_hw_mgr_handle_hw_dump_info( + void *ctx, + void *evt_info) +{ + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = + (struct cam_ife_hw_mgr_ctx *)ctx; + struct cam_isp_hw_event_info *event_info = + (struct cam_isp_hw_event_info *)evt_info; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_hw_intf *hw_intf; + uint32_t i, out_port_id; + int rc = 0; + + list_for_each_entry(hw_mgr_res, + &ife_hw_mgr_ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->res_id == + CAM_ISP_HW_VFE_IN_CAMIF) { + hw_intf = rsrc_node->hw_intf; + if (hw_intf && + hw_intf->hw_ops.process_cmd) + rc = + hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CAMIF_DATA, + rsrc_node, + sizeof( + struct + cam_isp_resource_node)); + } + } + } + + + out_port_id = event_info->res_id & 0xFF; + hw_mgr_res = + &ife_hw_mgr_ctx->res_list_ife_out[out_port_id]; + 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_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)event_info, + sizeof(struct cam_isp_hw_event_info)); + } + } + + return rc; +} + static int cam_ife_hw_mgr_handle_hw_err( + void *ctx, void *evt_info) { - struct cam_isp_hw_event_info *event_info = evt_info; - uint32_t core_idx; - struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx; + struct cam_isp_hw_event_info *event_info = evt_info; + uint32_t core_idx; + struct cam_isp_hw_error_event_data error_event_data = {0}; struct cam_ife_hw_event_recovery_data recovery_data = {0}; - int rc = -EINVAL; + int rc = -EINVAL; + + if (ctx) { + ife_hw_mgr_ctx = + (struct cam_ife_hw_mgr_ctx *)ctx; + if (event_info->res_type == + CAM_ISP_RESOURCE_VFE_IN && + !ife_hw_mgr_ctx->is_rdi_only_context && + event_info->res_id != + CAM_ISP_HW_VFE_IN_CAMIF) + cam_ife_hw_mgr_handle_hw_dump_info( + ife_hw_mgr_ctx, event_info); + } if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; @@ -7431,7 +7503,7 @@ static int cam_ife_hw_mgr_event_handler( break; case CAM_ISP_HW_EVENT_ERROR: - rc = cam_ife_hw_mgr_handle_hw_err(evt_info); + rc = cam_ife_hw_mgr_handle_hw_err(priv, evt_info); break; default: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index b48416c35587..25697c9d64f3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -101,8 +101,10 @@ enum cam_isp_hw_cmd_type { 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_DUMP_BUS_INFO, CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + CAM_ISP_HW_CMD_CAMIF_DATA, CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE, CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 7b991a316824..bd1a84e86042 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -598,6 +598,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_DUMP_HW: case CAM_ISP_HW_CMD_ADD_WAIT: case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: + case CAM_ISP_HW_CMD_CAMIF_DATA: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); @@ -611,6 +612,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h index 64d9de084ec1..eef02079628a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_SOC_H_ @@ -24,6 +24,7 @@ * @cpas_version: Has cpas version read from Hardware * @ubwc_static_ctrl: UBWC static control configuration * @is_ife_lite: Flag to indicate full vs lite IFE + * @ife_clk_src: IFE source clock */ struct cam_vfe_soc_private { uint32_t cpas_handle; @@ -33,6 +34,7 @@ struct cam_vfe_soc_private { int32_t dsp_clk_rate; uint32_t ubwc_static_ctrl[UBWC_STATIC_CONFIG_MAX]; bool is_ife_lite; + uint64_t ife_clk_src; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index a16c9d510f40..d0f85565a968 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -170,6 +170,14 @@ struct cam_vfe_top_dump_data vfe170_dump_data = { }, }; +static struct cam_vfe_rdi_overflow_status vfe170_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { .common_reg = &vfe170_top_common_reg, .camif_hw_info = { @@ -183,8 +191,9 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { .reg_data = NULL, }, .rdi_hw_info = { - .common_reg = &vfe170_top_common_reg, - .rdi_reg = &vfe170_rdi_reg, + .common_reg = &vfe170_top_common_reg, + .rdi_reg = &vfe170_rdi_reg, + .rdi_irq_status = &vfe170_rdi_irq_status, .reg_data = { &vfe_170_rdi_0_data, &vfe_170_rdi_1_data, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index a1df85c12388..ce0739d386cd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -27,6 +27,14 @@ static struct cam_irq_register_set vfe175_130_top_irq_reg_set[2] = { }, }; +static struct cam_vfe_rdi_overflow_status vfe175_130_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + 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, @@ -268,6 +276,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = { .common_reg = &vfe175_130_top_common_reg, .rdi_reg = &vfe175_130_rdi_reg, .common_reg_data = &vfe175_130_rdi_reg_data, + .rdi_irq_status = &vfe175_130_rdi_irq_status, .reg_data = { &vfe_175_130_rdi_0_data, &vfe_175_130_rdi_1_data, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index ae705f265af1..1771ed7d529b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -140,6 +140,8 @@ struct cam_vfe_bus_ver2_wm_resource_data { uint32_t ubwc_lossy_threshold_0; uint32_t ubwc_lossy_threshold_1; uint32_t ubwc_bandwidth_limit; + uint32_t acquired_width; + uint32_t acquired_height; }; struct cam_vfe_bus_ver2_comp_grp_data { @@ -984,6 +986,8 @@ static int cam_vfe_bus_acquire_wm( rsrc_data->width = out_port_info->width; rsrc_data->height = out_port_info->height; + rsrc_data->acquired_width = out_port_info->width; + rsrc_data->acquired_height = out_port_info->height; rsrc_data->is_dual = is_dual; /* Set WM offset value to default */ rsrc_data->offset = 0; @@ -3536,6 +3540,42 @@ static int __cam_vfe_bus_process_cmd(void *priv, return cam_vfe_bus_process_cmd(priv, cmd_type, cmd_args, arg_size); } +int cam_vfe_bus_dump_wm_data(void *priv, void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv = + (struct cam_vfe_bus_ver2_priv *) priv; + struct cam_isp_hw_event_info *event_info = + (struct cam_isp_hw_event_info *)cmd_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + int i, wm_idx; + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id; + + vfe_out_res_id = cam_vfe_bus_get_out_res_id(event_info->res_id); + rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; + rsrc_data = rsrc_node->res_priv; + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, i); + if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { + CAM_ERR(CAM_ISP, "Unsupported VFE out %d", + vfe_out_res_id); + return -EINVAL; + } + wm_data = bus_priv->bus_client[wm_idx].res_priv; + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_idx, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); + } + return 0; +} + static int cam_vfe_bus_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -3575,6 +3615,9 @@ static int cam_vfe_bus_process_cmd( case CAM_ISP_HW_CMD_UBWC_UPDATE: rc = cam_vfe_bus_update_ubwc_config(cmd_args); break; + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: + rc = cam_vfe_bus_dump_wm_data(priv, cmd_args, arg_size); + break; case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: rc = cam_vfe_bus_update_ubwc_config_v2(cmd_args); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 67c59bc0e205..425a041ba912 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -128,6 +128,8 @@ struct cam_vfe_bus_ver3_wm_resource_data { uint32_t ubwc_lossy_threshold_1; uint32_t ubwc_offset_lossy_variance; uint32_t ubwc_bandwidth_limit; + uint32_t acquired_width; + uint32_t acquired_height; }; struct cam_vfe_bus_ver3_comp_grp_data { @@ -1079,6 +1081,8 @@ static int cam_vfe_bus_ver3_acquire_wm( rsrc_data->width = out_port_info->width; rsrc_data->height = out_port_info->height; + rsrc_data->acquired_width = out_port_info->width; + rsrc_data->acquired_height = out_port_info->height; rsrc_data->is_dual = is_dual; /* Set WM offset value to default */ rsrc_data->offset = 0; @@ -2383,34 +2387,37 @@ static int cam_vfe_bus_ver3_deinit_vfe_out_resource( return 0; } -static void cam_vfe_bus_ver3_print_dimensions( +static int cam_vfe_bus_ver3_print_dimensions( enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, - enum cam_vfe_bus_plane_type plane, struct cam_vfe_bus_ver3_priv *bus_priv) { - struct cam_isp_resource_node *wm_res = NULL; - struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; - int wm_idx = 0; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + int i, wm_idx; - wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, plane, - bus_priv->common_data.is_lite); - - if (wm_idx < 0 || wm_idx >= bus_priv->num_client || plane > PLANE_C) { - CAM_ERR(CAM_ISP, - "Unsupported VFE out_type:0x%X plane:%d wm_idx:%d max_idx:%d", - vfe_out_res_id, plane, wm_idx, - bus_priv->num_client - 1); - return; + rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; + rsrc_data = rsrc_node->res_priv; + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, i, + bus_priv->common_data.is_lite); + if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { + CAM_ERR(CAM_ISP, "Unsupported VFE out %d", + vfe_out_res_id); + return -EINVAL; + } + wm_data = bus_priv->bus_client[wm_idx].res_priv; + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_idx, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); } - - wm_res = &bus_priv->bus_client[wm_idx]; - wm_data = wm_res->res_priv; - - CAM_INFO(CAM_ISP, - "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u", - wm_data->common_data->core_index, wm_idx, wm_data->width, - wm_data->height, wm_data->stride, wm_data->h_init, - wm_data->en_cfg); + return 0; } static int cam_vfe_bus_ver3_handle_bus_irq(uint32_t evt_id, @@ -2516,7 +2523,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 0 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI0, - PLANE_Y, bus_priv); } @@ -2525,7 +2531,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI1, - PLANE_Y, bus_priv); } @@ -2534,7 +2539,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 2 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI2, - PLANE_Y, bus_priv); } @@ -2543,7 +2547,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 3 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI3, - PLANE_Y, bus_priv); } } @@ -2578,7 +2581,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID Y 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL, - PLANE_Y, bus_priv); } @@ -2586,7 +2588,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID C 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL, - PLANE_C, bus_priv); } @@ -2594,7 +2595,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID YC 4:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS4, - PLANE_Y, bus_priv); } @@ -2602,7 +2602,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID YC 16:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS16, - PLANE_Y, bus_priv); } @@ -2610,7 +2609,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP Y 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, - PLANE_Y, bus_priv); } @@ -2618,7 +2616,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP C 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, - PLANE_C, bus_priv); } @@ -2626,7 +2623,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP YC 4:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, - PLANE_Y, bus_priv); } @@ -2634,7 +2630,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP YC 16:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, - PLANE_Y, bus_priv); } @@ -2642,7 +2637,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "FD Y image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FD, - PLANE_Y, bus_priv); } @@ -2650,7 +2644,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "FD C image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FD, - PLANE_C, bus_priv); } @@ -2659,7 +2652,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "PIXEL RAW DUMP image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, - PLANE_Y, bus_priv); } @@ -2667,7 +2659,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS HDR BE image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, - PLANE_Y, bus_priv); } @@ -2676,7 +2667,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "STATS HDR BHIST image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, - PLANE_Y, bus_priv); } @@ -2685,7 +2675,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "STATS TINTLESS BG image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, - PLANE_Y, bus_priv); } @@ -2693,7 +2682,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS AWB BG image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, - PLANE_Y, bus_priv); } @@ -2701,7 +2689,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS BHIST image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, - PLANE_Y, bus_priv); } @@ -2709,7 +2696,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS RS image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, - PLANE_Y, bus_priv); } @@ -2717,7 +2703,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS CS image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, - PLANE_Y, bus_priv); } @@ -2725,7 +2710,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS IHIST image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, - PLANE_Y, bus_priv); } @@ -2733,7 +2717,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS BAF image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, - PLANE_Y, bus_priv); } @@ -2741,7 +2724,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "PD image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_2PD, - PLANE_Y, bus_priv); } @@ -2749,7 +2731,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "LCR image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_LCR, - PLANE_Y, bus_priv); } @@ -2757,7 +2738,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "RDI 0 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI0, - PLANE_Y, bus_priv); } @@ -2765,7 +2745,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "RDI 1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI1, - PLANE_Y, bus_priv); } @@ -2773,7 +2752,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "RDI 2 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI2, - PLANE_Y, bus_priv); } @@ -3686,6 +3664,19 @@ static int cam_vfe_bus_ver3_process_cmd( bus_priv->error_irq_handle = 0; } break; + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: { + struct cam_isp_hw_event_info *event_info; + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id; + + event_info = + (struct cam_isp_hw_event_info *)cmd_args; + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + vfe_out_res_id = + cam_vfe_bus_ver3_get_out_res_id(event_info->res_id); + rc = cam_vfe_bus_ver3_print_dimensions( + vfe_out_res_id, bus_priv); + break; + } case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: rc = cam_vfe_bus_ver3_update_ubwc_config_v2(cmd_args); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c index 9ea8d74a35ca..e4ff7255df5b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -36,6 +36,7 @@ struct cam_vfe_mux_camif_lite_data { evt_payload[CAM_VFE_CAMIF_LITE_EVT_MAX]; struct list_head free_payload_list; spinlock_t spin_lock; + struct timeval error_ts; }; static int cam_vfe_camif_lite_get_evt_payload( @@ -133,6 +134,12 @@ static int cam_vfe_camif_lite_err_irq_top_half( } cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_lite_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_lite_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -301,6 +308,9 @@ static int cam_vfe_camif_lite_resource_start( } } + rsrc_data->error_ts.tv_sec = 0; + rsrc_data->error_ts.tv_usec = 0; + CAM_DBG(CAM_ISP, "Start Camif Lite IFE %d Done", camif_lite_res->hw_intf->hw_idx); return rc; @@ -405,6 +415,44 @@ static int cam_vfe_camif_lite_handle_irq_top_half(uint32_t evt_id, return rc; } +static int cam_vfe_camif_lite_cpas_fifo_levels_reg_dump( + struct cam_vfe_mux_camif_lite_data *camif_lite_priv) +{ + struct cam_vfe_soc_private *soc_private = + camif_lite_priv->soc_info->soc_private; + uint32_t val; + + if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + CAM_INFO(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); + + } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { + 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); + + 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); + } + + return 0; + +} + static int cam_vfe_camif_lite_handle_irq_bottom_half( void *handler_priv, void *evt_payload_priv) @@ -416,6 +464,9 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( struct cam_isp_hw_event_info evt_info; uint32_t irq_status0; uint32_t irq_status1; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -427,6 +478,9 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( 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]; + soc_info = camif_lite_priv->soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; evt_info.hw_idx = camif_lite_node->hw_intf->hw_idx; evt_info.res_id = camif_lite_node->res_id; @@ -464,11 +518,27 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE Received ERROR", evt_info.hw_idx); + cam_vfe_camif_lite_cpas_fifo_levels_reg_dump(camif_lite_priv); + + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld", + camif_lite_priv->error_ts.tv_sec, + camif_lite_priv->error_ts.tv_usec); + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + + cam_cpas_log_votes(); + } cam_vfe_camif_lite_put_evt_payload(camif_lite_priv, &payload); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index bfb17d2145f8..b54c43a145bc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -40,6 +40,10 @@ struct cam_vfe_mux_camif_lite_data { uint32_t camif_debug; struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_CAMIF_LITE_EVT_MAX]; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; static int cam_vfe_camif_lite_get_evt_payload( @@ -137,6 +141,12 @@ static int cam_vfe_camif_lite_err_irq_top_half( return rc; cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_lite_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_lite_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -293,6 +303,15 @@ static int cam_vfe_camif_lite_resource_start( rsrc_data->mem_base + rsrc_data->camif_lite_reg->lite_epoch_irq); + rsrc_data->error_ts.tv_sec = 0; + rsrc_data->error_ts.tv_usec = 0; + rsrc_data->sof_ts.tv_sec = 0; + rsrc_data->sof_ts.tv_usec = 0; + rsrc_data->epoch_ts.tv_sec = 0; + rsrc_data->epoch_ts.tv_usec = 0; + rsrc_data->eof_ts.tv_sec = 0; + rsrc_data->eof_ts.tv_usec = 0; + skip_core_cfg: camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; @@ -888,6 +907,7 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, CAM_INFO(CAM_ISP, "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", val0, val1, val2); + cam_cpas_log_votes(); } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { @@ -1062,6 +1082,8 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( struct cam_vfe_soc_private *soc_private = NULL; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; int i = 0; + uint32_t status_0 = 0; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -1097,6 +1119,10 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received SOF", evt_info.hw_idx, evt_info.res_id); ret = CAM_VFE_IRQ_STATUS_SUCCESS; + camif_lite_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_lite_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, @@ -1108,6 +1134,10 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received EPOCH", evt_info.hw_idx, evt_info.res_id); ret = CAM_VFE_IRQ_STATUS_SUCCESS; + camif_lite_priv->epoch_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_lite_priv->epoch_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, @@ -1119,18 +1149,50 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received EOF", evt_info.hw_idx, evt_info.res_id); ret = CAM_VFE_IRQ_STATUS_SUCCESS; + camif_lite_priv->eof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_lite_priv->eof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); } - if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] - & camif_lite_priv->reg_data->error_irq_mask0) { + status_0 = irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + & camif_lite_priv->reg_data->error_irq_mask0; + if (status_0) { CAM_ERR(CAM_ISP, "VFE:%d Overflow", camif_lite_node->hw_intf->hw_idx); evt_info.err_type = CAM_VFE_IRQ_STATUS_OVERFLOW; + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld", + camif_lite_priv->error_ts.tv_sec, + camif_lite_priv->error_ts.tv_usec); + + if (camif_lite_node->rdi_only_ctx) + CAM_INFO(CAM_ISP, + "SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_lite_priv->sof_ts.tv_sec, + camif_lite_priv->sof_ts.tv_usec, + camif_lite_priv->epoch_ts.tv_sec, + camif_lite_priv->epoch_ts.tv_usec, + camif_lite_priv->eof_ts.tv_sec, + camif_lite_priv->eof_ts.tv_usec); + + if (status_0 & 0x8000000) + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_2; + + if (status_0 & 0x10000000) + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_1; + + if (status_0 & 0x20000000) + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_0; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 55a94c843dfb..1f7824763cfe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -50,6 +50,10 @@ struct cam_vfe_mux_camif_data { uint32_t camif_debug; uint32_t dual_hw_idx; uint32_t is_dual; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; static int cam_vfe_camif_get_evt_payload( @@ -144,6 +148,12 @@ static int cam_vfe_camif_err_irq_top_half( } cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -293,6 +303,14 @@ static int cam_vfe_camif_resource_init( if (rc) CAM_ERR(CAM_ISP, "failed to enable dsp clk"); } + camif_data->sof_ts.tv_sec = 0; + camif_data->sof_ts.tv_usec = 0; + camif_data->epoch_ts.tv_sec = 0; + camif_data->epoch_ts.tv_usec = 0; + camif_data->eof_ts.tv_sec = 0; + camif_data->eof_ts.tv_usec = 0; + camif_data->error_ts.tv_sec = 0; + camif_data->error_ts.tv_usec = 0; return rc; } @@ -631,6 +649,26 @@ static int cam_vfe_camif_sof_irq_debug( return 0; } +int cam_vfe_camif_dump_timestamps( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_data *camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + + CAM_INFO(CAM_ISP, + "CAMIF ERROR time %lld:%lld SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->error_ts.tv_sec, + camif_priv->error_ts.tv_usec, + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); + + return 0; +} + static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -655,6 +693,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; camif_priv->camif_debug = *((uint32_t *)cmd_args); break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_camif_dump_timestamps(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); @@ -710,6 +751,7 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, uint32_t irq_status0; uint32_t irq_status1; uint32_t val; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -731,6 +773,10 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & camif_priv->reg_data->eof_irq_mask) { CAM_DBG(CAM_ISP, "Received EOF"); + camif_priv->eof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->eof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -752,8 +798,13 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, false; camif_priv->irq_debug_cnt = 0; } - } else + } else { CAM_DBG(CAM_ISP, "Received SOF"); + camif_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; + } if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -774,6 +825,10 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "Received EPOCH"); + camif_priv->epoch_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->epoch_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -785,6 +840,11 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & camif_priv->reg_data->error_irq_mask0) { CAM_DBG(CAM_ISP, "Received ERROR"); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); @@ -800,6 +860,11 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status1 & camif_priv->reg_data->error_irq_mask1) { CAM_DBG(CAM_ISP, "Received ERROR"); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index b5e2a429dab1..543dcbb358bf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -57,6 +57,10 @@ struct cam_vfe_mux_camif_ver3_data { uint32_t is_dual; bool is_fe_enabled; bool is_offline; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; static int cam_vfe_camif_ver3_get_evt_payload( @@ -142,6 +146,12 @@ static int cam_vfe_camif_ver3_err_irq_top_half( return rc; cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -304,6 +314,14 @@ static int cam_vfe_camif_ver3_resource_init( CAM_ERR(CAM_ISP, "failed to enable dsp clk, rc = %d", rc); } + camif_data->sof_ts.tv_sec = 0; + camif_data->sof_ts.tv_usec = 0; + camif_data->epoch_ts.tv_sec = 0; + camif_data->epoch_ts.tv_usec = 0; + camif_data->eof_ts.tv_sec = 0; + camif_data->eof_ts.tv_usec = 0; + camif_data->error_ts.tv_sec = 0; + camif_data->error_ts.tv_usec = 0; return rc; } @@ -772,6 +790,26 @@ static int cam_vfe_camif_ver3_sof_irq_debug( return 0; } +int cam_vfe_camif_ver3_dump_timestamps( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv = + (struct cam_vfe_mux_camif_ver3_data *)rsrc_node->res_priv; + + CAM_INFO(CAM_ISP, + "CAMIF ERROR time %lld:%lld SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->error_ts.tv_sec, + camif_priv->error_ts.tv_usec, + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); + + return 0; +} + static int cam_vfe_camif_ver3_process_cmd( struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -808,6 +846,9 @@ static int cam_vfe_camif_ver3_process_cmd( *((struct cam_hw_soc_info **)cmd_args) = camif_priv->soc_info; rc = 0; break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_camif_ver3_dump_timestamps(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); @@ -969,6 +1010,7 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, CAM_INFO(CAM_ISP, "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", val0, val1, val2); + cam_cpas_log_votes(); return; } @@ -1280,6 +1322,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; + struct timespec64 ts; uint32_t val = 0; int i = 0; @@ -1317,9 +1360,14 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, false; camif_priv->irq_debug_cnt = 0; } - } else + } else { CAM_DBG(CAM_ISP, "VFE:%d Received SOF", evt_info.hw_idx); + camif_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; + } if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1332,6 +1380,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); evt_info.th_reg_val = payload->th_reg_val; + camif_priv->epoch_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->epoch_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1343,6 +1395,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->eof_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EOF", evt_info.hw_idx); + camif_priv->eof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->eof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1355,6 +1411,11 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, & camif_priv->reg_data->error_irq_mask0) { CAM_ERR(CAM_ISP, "VFE:%d Overflow", evt_info.hw_idx); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); @@ -1379,6 +1440,11 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index a0e7741e5505..b766c1ee844b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -21,7 +21,9 @@ struct cam_vfe_mux_rdi_data { struct cam_vfe_top_ver2_reg_offset_common *common_reg; struct cam_vfe_rdi_ver2_reg *rdi_reg; struct cam_vfe_rdi_common_reg_data *rdi_common_reg_data; + struct cam_vfe_rdi_overflow_status *rdi_irq_status; struct cam_vfe_rdi_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; cam_hw_mgr_event_cb_func event_cb; void *priv; @@ -33,6 +35,8 @@ struct cam_vfe_mux_rdi_data { spinlock_t spin_lock; enum cam_isp_hw_sync_mode sync_mode; + struct timeval sof_ts; + struct timeval error_ts; }; static int cam_vfe_rdi_get_evt_payload( @@ -81,6 +85,44 @@ static int cam_vfe_rdi_put_evt_payload( return 0; } +static int cam_vfe_rdi_cpas_reg_dump( +struct cam_vfe_mux_rdi_data *rdi_priv) +{ + struct cam_vfe_soc_private *soc_private = + rdi_priv->soc_info->soc_private; + uint32_t val; + + if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + CAM_INFO(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); + + } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { + 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); + + 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); + } + + return 0; + +} + static int cam_vfe_rdi_err_irq_top_half( uint32_t evt_id, struct cam_irq_th_payload *th_payload) @@ -124,6 +166,12 @@ static int cam_vfe_rdi_err_irq_top_half( } cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + rdi_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + rdi_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -282,6 +330,11 @@ static int cam_vfe_rdi_resource_start( } } + rsrc_data->sof_ts.tv_sec = 0; + rsrc_data->sof_ts.tv_usec = 0; + rsrc_data->error_ts.tv_sec = 0; + rsrc_data->error_ts.tv_usec = 0; + CAM_DBG(CAM_ISP, "Start RDI %d", rdi_res->res_id - CAM_ISP_HW_VFE_IN_RDI0); end: @@ -392,6 +445,11 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; uint32_t irq_status0; + uint32_t irq_status1; + uint32_t irq_rdi_status; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -401,8 +459,12 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, rdi_node = handler_priv; rdi_priv = rdi_node->res_priv; payload = evt_payload_priv; + soc_info = rdi_priv->soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; + irq_status1 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1]; evt_info.hw_idx = rdi_node->hw_intf->hw_idx; evt_info.res_id = rdi_node->res_id; @@ -412,7 +474,10 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & rdi_priv->reg_data->sof_irq_mask) { CAM_DBG(CAM_ISP, "Received SOF"); - + rdi_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + rdi_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (rdi_priv->event_cb) rdi_priv->event_cb(rdi_priv->priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); @@ -430,6 +495,50 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_SUCCESS; } + irq_rdi_status = + (irq_status1 & + rdi_priv->rdi_irq_status->rdi_overflow_mask); + if (irq_rdi_status) { + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + + cam_vfe_rdi_cpas_reg_dump(rdi_priv); + + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld SOF %lld:%lld", + rdi_priv->error_ts.tv_sec, + rdi_priv->error_ts.tv_usec, + rdi_priv->sof_ts.tv_sec, + rdi_priv->sof_ts.tv_usec); + + if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi0_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_0; + } + else if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi1_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_1; + } + else if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi2_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_2; + } + else if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi3_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_3; + } + + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_ERROR, + (void *)&evt_info); + cam_cpas_log_votes(); + } + cam_vfe_rdi_put_evt_payload(rdi_priv, &payload); CAM_DBG(CAM_ISP, "returing status = %d", ret); return ret; @@ -461,6 +570,8 @@ int cam_vfe_rdi_ver2_init( rdi_priv->rdi_reg = rdi_info->rdi_reg; rdi_priv->vfe_irq_controller = vfe_irq_controller; rdi_priv->rdi_common_reg_data = rdi_info->common_reg_data; + rdi_priv->soc_info = soc_info; + rdi_priv->rdi_irq_status = rdi_info->rdi_irq_status; switch (rdi_node->res_id) { case CAM_ISP_HW_VFE_IN_RDI0: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h index c570e84a011c..70a2cb756cea 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_RDI_H_ @@ -17,6 +17,14 @@ struct cam_vfe_rdi_ver2_reg { uint32_t reg_update_cmd; }; +struct cam_vfe_rdi_overflow_status { + uint32_t rdi0_overflow_mask; + uint32_t rdi1_overflow_mask; + uint32_t rdi2_overflow_mask; + uint32_t rdi3_overflow_mask; + uint32_t rdi_overflow_mask; +}; + struct cam_vfe_rdi_common_reg_data { uint32_t subscribe_irq_mask0; uint32_t subscribe_irq_mask1; @@ -35,6 +43,7 @@ struct cam_vfe_rdi_ver2_hw_info { struct cam_vfe_top_ver2_reg_offset_common *common_reg; struct cam_vfe_rdi_ver2_reg *rdi_reg; struct cam_vfe_rdi_common_reg_data *common_reg_data; + struct cam_vfe_rdi_overflow_status *rdi_irq_status; struct cam_vfe_rdi_reg_data *reg_data[CAM_VFE_RDI_VER2_MAX]; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index b174c21d8bf2..044a02468072 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -83,8 +83,11 @@ static int cam_vfe_top_set_hw_clk_rate( struct cam_hw_soc_info *soc_info = NULL; int i, rc = 0; unsigned long max_clk_rate = 0; + struct cam_vfe_soc_private *soc_private = NULL; soc_info = top_priv->common_data.soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) @@ -96,7 +99,7 @@ static int cam_vfe_top_set_hw_clk_rate( CAM_DBG(CAM_PERF, "VFE: Clock name=%s idx=%d clk=%llu", soc_info->clk_name[soc_info->src_clk_idx], soc_info->src_clk_idx, max_clk_rate); - + soc_private->ife_clk_src = max_clk_rate; rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); if (!rc) @@ -265,6 +268,19 @@ static int cam_vfe_top_add_wait_trigger(struct cam_vfe_top_ver2_priv *top_priv, return 0; } +static int cam_vfe_top_get_data( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_resource_node *res = cmd_args; + + if (res->process_cmd) + return res->process_cmd(res, + CAM_ISP_HW_CMD_CAMIF_DATA, cmd_args, arg_size); + + return -EINVAL; +} + int cam_vfe_top_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size) { @@ -622,6 +638,8 @@ int cam_vfe_top_stop(void *device_priv, struct cam_vfe_top_ver2_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int i, rc = 0; if (!device_priv || !stop_args) { @@ -632,6 +650,8 @@ int cam_vfe_top_stop(void *device_priv, top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; mux_res = (struct cam_isp_resource_node *)stop_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; if ((mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) || (mux_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || @@ -662,7 +682,7 @@ int cam_vfe_top_stop(void *device_priv, } } } - + soc_private->ife_clk_src = 0; return rc; } @@ -706,6 +726,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_top_mux_get_reg_update(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_top_get_data(top_priv, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_CLOCK_UPDATE: rc = cam_vfe_top_clock_update(top_priv, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index e632596991bb..763b8f4afdaa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -309,6 +309,19 @@ static int cam_vfe_top_add_wait_trigger(struct cam_vfe_top_ver3_priv *top_priv, return 0; } +static int cam_vfe_top_ver3_get_data( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_resource_node *res = cmd_args; + + if (res->process_cmd) + return res->process_cmd(res, + CAM_ISP_HW_CMD_CAMIF_DATA, cmd_args, arg_size); + + return -EINVAL; +} + int cam_vfe_top_ver3_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size) { @@ -639,6 +652,10 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_top_ver3_mux_get_reg_update(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_top_ver3_get_data(top_priv, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_CLOCK_UPDATE: rc = cam_vfe_top_ver3_clock_update(top_priv, cmd_args, arg_size); From a085cf0e51360ccd82c75c3581c8a7913422cc18 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Thu, 16 Apr 2020 22:05:26 -0700 Subject: [PATCH 324/790] msm: camera: isp: Fix per req reg dump for Single IFE usecase In dual ife usecase we get two cdm callbacks from respective internal cdm's. This change makes sure per req reg dump function is called only once when two cdm callbacks are received. CRs-Fixed: 2666317 Change-Id: I766dbe471cbee0fd2d26e7618ebc06a9f185a873 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d1cf9fd3eb50..72010cb5d024 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2606,6 +2606,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, struct cam_ife_hw_mgr_ctx *ctx = NULL; int i; uint32_t idx = 0; + int reg_dump_done; if (!userdata) { CAM_ERR(CAM_ISP, "Invalid args"); @@ -2633,9 +2634,10 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { complete_all(&ctx->config_done_complete[idx]); + reg_dump_done = atomic_read(&ctx->cdm_done); atomic_set(&ctx->cdm_done, 1); if ((g_ife_hw_mgr.debug_cfg.per_req_reg_dump) && - (idx == ctx->master_hw_idx)) + (!reg_dump_done)) cam_ife_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, hw_update_data->num_reg_dump_buf, From 28be26b7404db834f175a13b094cd731bf349c67 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Fri, 17 Apr 2020 14:21:01 -0700 Subject: [PATCH 325/790] msm: camera: sync: Fix kbuild config checks for synx driver External configs should be checked by using IS_REACHABLE/IS_ENABLED macro's to check if the config option is set for the build target. CRs-Fixed: 2584631 Change-Id: I07a0d95391a83a2264f826e2935d67686d295317 Signed-off-by: Karthik Jayakumar --- .../cam_flash/cam_flash_core.c | 2 +- drivers/cam_sync/cam_sync.c | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 0e60442c4a75..46245d72942c 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -20,7 +20,7 @@ int cam_flash_led_prepare(struct led_trigger *trigger, int options, int rc = 0; if (is_wled) { -#ifdef CONFIG_BACKLIGHT_QCOM_SPMI_WLED +#if IS_REACHABLE(CONFIG_BACKLIGHT_QCOM_SPMI_WLED) rc = wled_flash_led_prepare(trigger, options, max_current); if (rc) { CAM_ERR(CAM_FLASH, "enable reg failed: rc: %d", diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 7f6a38a283f4..8f38bcca160b 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -9,14 +9,15 @@ #include #include #include +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#include +#endif + #include "cam_sync_util.h" #include "cam_debug_util.h" #include "cam_common_util.h" #include "camera_main.h" -#ifdef CONFIG_MSM_GLOBAL_SYNX -#include -#endif struct sync_device *sync_dev; /* @@ -948,7 +949,7 @@ static struct v4l2_file_operations cam_sync_v4l2_fops = { #endif }; -#if defined(CONFIG_MEDIA_CONTROLLER) +#if IS_REACHABLE(CONFIG_MEDIA_CONTROLLER) static int cam_sync_media_controller_init(struct sync_device *sync_dev, struct platform_device *pdev) { @@ -1031,8 +1032,8 @@ static int cam_sync_create_debugfs(void) return 0; } -#ifdef CONFIG_MSM_GLOBAL_SYNX -static void cam_sync_register_synx_bind_ops(void) +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +static int cam_sync_register_synx_bind_ops(void) { int rc = 0; struct synx_register_params params; @@ -1046,7 +1047,9 @@ static void cam_sync_register_synx_bind_ops(void) rc = synx_register_ops(¶ms); if (rc) - CAM_ERR(CAM_SYNC, "synx registration fail with %d", rc); + CAM_ERR(CAM_SYNC, "synx registration fail with rc=%d", rc); + + return rc; } #endif @@ -1124,8 +1127,11 @@ static int cam_sync_component_bind(struct device *dev, trigger_cb_without_switch = false; cam_sync_create_debugfs(); -#ifdef CONFIG_MSM_GLOBAL_SYNX - cam_sync_register_synx_bind_ops(); +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) + CAM_INFO(CAM_SYNC, "Registering with synx driver"); + rc = cam_sync_register_synx_bind_ops(); + if (rc) + goto v4l2_fail; #endif CAM_DBG(CAM_SYNC, "Component bound successfully"); return rc; From df4da1d8dd0dd33f6e384fac1e687ff2f7616cc0 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 17 Apr 2020 13:33:56 -0700 Subject: [PATCH 326/790] msm: camera: ife: Change log level To acquire a CSID path we loop through all available CSIDs. Therefore the log that indicates that a specific CSID does not have a path available is not a error by itself. This commit changes that log level to debug. CRs-Fixed: 2671273 Change-Id: I52750975a739faa5a4015d20cebb5f7f0442fb58 Signed-off-by: Venkat Chinta --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 4 +--- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d1cf9fd3eb50..e2bea21986a0 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1639,9 +1639,7 @@ static int cam_ife_mgr_acquire_cid_res( &csid_acquire, false); if (rc || !csid_acquire.node_res) { - CAM_ERR(CAM_ISP, - "Can not acquire ife cid resource for path %d", - path_res_id); + CAM_ERR(CAM_ISP, "No %d paths available", path_res_id); goto put_res; } cid_res_temp->hw_res[acquired_cnt++] = csid_acquire.node_res; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 19c29da3c2ec..34a5affdab0f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1018,7 +1018,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_IPP: if (csid_hw->ipp_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, + CAM_DBG(CAM_ISP, "CSID:%d IPP resource not available %d", csid_hw->hw_intf->hw_idx, csid_hw->ipp_res.res_state); @@ -1046,7 +1046,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_PPP: if (csid_hw->ppp_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, + CAM_DBG(CAM_ISP, "CSID:%d PPP resource not available %d", csid_hw->hw_intf->hw_idx, csid_hw->ppp_res.res_state); @@ -1077,7 +1077,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_RDI_3: if (csid_hw->rdi_res[reserve->res_id].res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, + CAM_DBG(CAM_ISP, "CSID:%d RDI:%d resource not available %d", csid_hw->hw_intf->hw_idx, reserve->res_id, @@ -1100,7 +1100,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, id = reserve->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; if (csid_hw->udi_res[id].res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, + CAM_DBG(CAM_ISP, "CSID:%d UDI:%d resource not available %d", csid_hw->hw_intf->hw_idx, reserve->res_id, From 758e751074b035bc53a720840613a3b0f301e469 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Fri, 10 Apr 2020 13:53:34 -0700 Subject: [PATCH 327/790] msm: camera: isp: Remove request ID in bubble sof notification This change removes valid request ID from sof notification when bubble is detected. The sof notification for this request will be sent after the state machine moves out of bubble applied state. This is to avoid duplication of timestamps in case of bubble due to IRQ delays. CRs-Fixed: 2671273 Change-Id: I5334fab41ae5bce8a42e421747b35f9bfd32aff3 Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 32ab5c7977a9..7fd06d214c9e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1589,7 +1589,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, 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); - if (req->request_id > ctx_isp->reported_req_id) { + if ((req->request_id > ctx_isp->reported_req_id) + && !req_isp->bubble_report) { request_id = req->request_id; ctx_isp->reported_req_id = request_id; } From 85ac759b1eb24150e810391c6ec2a86a8c691fc3 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 22 Apr 2020 16:16:36 -0700 Subject: [PATCH 328/790] msm: camera: cpas: Set AHB clock rate only if a client is streamed on Currently the ahb clock rate is set as part of cpas_start for a given client. In order to set this rate, any camera gdsc needs to be enabled. This change adds a check to allow setting the clk rate only if the gdsc regulator has been enabled to avoid NoC timeouts. CRs-Fixed: 2671048 Change-Id: I6551c8c648ae298dca97f0e35ba7c9ca83b5a2cd Signed-off-by: Karthik Anantha Ram --- drivers/cam_cpas/cam_cpas_hw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 8fd153169d89..b042dc0e8ab6 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1030,12 +1030,15 @@ static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw, } } - rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info, highest_level); - if (rc) { - CAM_ERR(CAM_CPAS, - "Failed in scaling clock rate level %d for AHB", + if (cpas_core->streamon_clients) { + rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info, highest_level); - goto unlock_bus_client; + if (rc) { + CAM_ERR(CAM_CPAS, + "Failed in scaling clock rate level %d for AHB", + highest_level); + goto unlock_bus_client; + } } if (applied_level) From e990f992763ec7a4e6b6948548b2ec8cb2d295c4 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 24 Dec 2019 16:54:55 +0530 Subject: [PATCH 329/790] msm: camera: isp: Ignore other csid irq errors during csid top reset During global reset, csi rx irq bits are set since sensor/phy was not reset properly in last closure and sending some data. This can lead to csid fatal or non-fatal errors. To avoid this condition, ignore other csid irq errors during csid top reset and during csid stop sequence. CRs-Fixed: 2585726 Change-Id: I5e09caf3b374407ece8ff1b871c2cf7e0f1837ac Signed-off-by: Chandan Kumar Jha Signed-off-by: Depeng Shao Signed-off-by: Vishalsingh Hajeri --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 22 +++++++++++++++++++ .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 19c29da3c2ec..2d3b59cc7f9e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3302,6 +3302,8 @@ static int cam_ife_csid_reset_regs( spin_lock_irqsave(&csid_hw->hw_info->hw_lock, flags); + csid_hw->is_resetting = true; + /* clear the top interrupt first */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_clear_addr); @@ -3366,6 +3368,7 @@ static int cam_ife_csid_reset_regs( rem_jiffies); end: + csid_hw->is_resetting = false; return rc; } @@ -3540,6 +3543,7 @@ int cam_ife_csid_start(void *hw_priv, void *start_args, 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 || !start_args || (arg_size != sizeof(struct cam_isp_resource_node))) { @@ -3567,6 +3571,10 @@ int cam_ife_csid_start(void *hw_priv, void *start_args, csid_hw->sof_irq_triggered = false; csid_hw->irq_debug_cnt = 0; + spin_lock_irqsave(&csid_hw->lock_state, flags); + csid_hw->device_enabled = 1; + spin_unlock_irqrestore(&csid_hw->lock_state, flags); + CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d", csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); @@ -3615,6 +3623,7 @@ int cam_ife_csid_stop(void *hw_priv, struct cam_csid_hw_stop_args *csid_stop; uint32_t i; uint32_t res_mask = 0; + unsigned long flags; if (!hw_priv || !stop_args || (arg_size != sizeof(struct cam_csid_hw_stop_args))) { @@ -3677,6 +3686,10 @@ int cam_ife_csid_stop(void *hw_priv, } } + spin_lock_irqsave(&csid_hw->lock_state, flags); + csid_hw->device_enabled = 0; + spin_unlock_irqrestore(&csid_hw->lock_state, flags); + if (res_mask) rc = cam_ife_csid_poll_stop_status(csid_hw, res_mask); @@ -4065,6 +4078,14 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if (irq_status_top & CSID_TOP_IRQ_DONE) { CAM_DBG(CAM_ISP, "csid top reset complete"); complete(&csid_hw->csid_top_complete); + csid_hw->is_resetting = false; + return IRQ_HANDLED; + } + + if (csid_hw->is_resetting) { + CAM_DBG(CAM_ISP, "CSID:%d is resetting, IRQ Handling exit", + csid_hw->hw_intf->hw_idx); + return IRQ_HANDLED; } if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) { @@ -4446,6 +4467,7 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->device_enabled = 0; + ife_csid_hw->is_resetting = false; 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); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 71a451b89198..f75b97224e60 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -547,6 +547,7 @@ struct cam_ife_csid_path_cfg { * @clk_rate Clock rate * @sof_irq_triggered: Flag is set on receiving event to enable sof irq * incase of SOF freeze. + * @is_resetting: informs whether reset is started or not. * @irq_debug_cnt: Counter to track sof irq's when above flag is set. * @error_irq_count Error IRQ count, if continuous error irq comes * need to stop the CSID and mask interrupts. @@ -580,6 +581,7 @@ struct cam_ife_csid_hw { uint64_t csid_debug; uint64_t clk_rate; bool sof_irq_triggered; + bool is_resetting; uint32_t irq_debug_cnt; uint32_t error_irq_count; uint32_t device_enabled; From 2e6a2419b48aa05c31d58680df1bb370d25aa99d Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 6 Apr 2020 12:52:45 -0700 Subject: [PATCH 330/790] msm: camera: common: Add sysfs support for bw override To simulate bus overflow recovery in camera, cpas needs sysfs to take input from shell and vote the final value as given, instead of consolidated values from cpas clients. Add initial support for sysfs to add nodes for all drivers. Add sysfs based debug node to maintain and update all settings. Add cpas settings to override final bw voted to camnoc and mnoc ports. Usage: adb shell "echo #= > /sys/devices/platform/soc/soc:qcom,cam-req-mgr/debug_node" Example:i adb shell "echo cpas#camnoc_bw=100 > /sys/devices/platform/soc/soc:qcom,cam-req-mgr/debug_node" Input format for updating settings is strict. CRs-Fixed: 2646825 Change-Id: I8d6063240f9685474bf4b2899e8dfb3f74cbdb75 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_hw.c | 84 +++++++++++++++++++++ drivers/cam_req_mgr/cam_req_mgr_dev.c | 13 ++++ drivers/cam_utils/cam_debug_util.c | 103 ++++++++++++++++++++++++++ drivers/cam_utils/cam_debug_util.h | 41 ++++++++++ 4 files changed, 241 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 8fd153169d89..49ebdb3f9324 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -13,10 +13,63 @@ #include "cam_cpas_hw.h" #include "cam_cpas_hw_intf.h" #include "cam_cpas_soc.h" +#include "cam_req_mgr_dev.h" static uint cam_min_camnoc_ib_bw; module_param(cam_min_camnoc_ib_bw, uint, 0644); +static void cam_cpas_process_bw_overrides( + struct cam_cpas_bus_client *bus_client, uint64_t *ab, uint64_t *ib, + const struct cam_cpas_debug_settings *cpas_settings) +{ + uint64_t curr_ab = *ab; + uint64_t curr_ib = *ib; + size_t name_len = strlen(bus_client->common_data.name); + + if (!cpas_settings) { + CAM_ERR(CAM_CPAS, "Invalid cpas debug settings"); + return; + } + + if (strnstr(bus_client->common_data.name, "cam_hf_0", name_len)) { + if (cpas_settings->mnoc_hf_0_ab_bw) + *ab = cpas_settings->mnoc_hf_0_ab_bw; + if (cpas_settings->mnoc_hf_0_ib_bw) + *ib = cpas_settings->mnoc_hf_0_ib_bw; + } else if (strnstr(bus_client->common_data.name, "cam_hf_1", + name_len)) { + if (cpas_settings->mnoc_hf_1_ab_bw) + *ab = cpas_settings->mnoc_hf_1_ab_bw; + if (cpas_settings->mnoc_hf_0_ib_bw) + *ib = cpas_settings->mnoc_hf_1_ib_bw; + } else if (strnstr(bus_client->common_data.name, "cam_sf_0", + name_len)) { + if (cpas_settings->mnoc_sf_0_ab_bw) + *ab = cpas_settings->mnoc_sf_0_ab_bw; + if (cpas_settings->mnoc_sf_0_ib_bw) + *ib = cpas_settings->mnoc_sf_0_ib_bw; + } else if (strnstr(bus_client->common_data.name, "cam_sf_1", + name_len)) { + if (cpas_settings->mnoc_sf_1_ab_bw) + *ab = cpas_settings->mnoc_sf_1_ab_bw; + if (cpas_settings->mnoc_sf_1_ib_bw) + *ib = cpas_settings->mnoc_sf_1_ib_bw; + } else if (strnstr(bus_client->common_data.name, "cam_sf_icp", + name_len)) { + if (cpas_settings->mnoc_sf_icp_ab_bw) + *ab = cpas_settings->mnoc_sf_icp_ab_bw; + if (cpas_settings->mnoc_sf_icp_ib_bw) + *ib = cpas_settings->mnoc_sf_icp_ib_bw; + } else { + CAM_ERR(CAM_CPAS, "unknown mnoc port: %s, bw override failed", + bus_client->common_data.name); + return; + } + + CAM_INFO(CAM_CPAS, + "Overriding mnoc bw for: %s with ab: %llu, ib: %llu, curr_ab: %llu, curr_ib: %llu", + bus_client->common_data.name, *ab, *ib, curr_ab, curr_ib); +} int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info) @@ -85,6 +138,7 @@ static int cam_cpas_util_vote_bus_client_bw( { int rc = 0; uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; + const struct camera_debug_settings *cam_debug = NULL; if (!bus_client->valid) { CAM_ERR(CAM_CPAS, "bus client: %s not valid", @@ -116,6 +170,21 @@ static int cam_cpas_util_vote_bus_client_bw( ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW; } + cam_debug = cam_debug_get_settings(); + + if (cam_debug && (cam_debug->cpas_settings.mnoc_hf_0_ab_bw || + cam_debug->cpas_settings.mnoc_hf_0_ib_bw || + cam_debug->cpas_settings.mnoc_hf_1_ab_bw || + cam_debug->cpas_settings.mnoc_hf_1_ib_bw || + cam_debug->cpas_settings.mnoc_sf_0_ab_bw || + cam_debug->cpas_settings.mnoc_sf_0_ib_bw || + cam_debug->cpas_settings.mnoc_sf_1_ab_bw || + cam_debug->cpas_settings.mnoc_sf_1_ib_bw || + cam_debug->cpas_settings.mnoc_sf_icp_ab_bw || + cam_debug->cpas_settings.mnoc_sf_icp_ib_bw)) + cam_cpas_process_bw_overrides(bus_client, &ab, &ib, + &cam_debug->cpas_settings); + rc = cam_soc_bus_client_update_bw(bus_client->soc_bus_client, ab, ib); if (rc) { CAM_ERR(CAM_CPAS, @@ -376,6 +445,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_cpas_tree_node *tree_node = NULL; int rc = 0, i = 0; + const struct camera_debug_settings *cam_debug = NULL; + CAM_DBG(CAM_CPAS, "control_camnoc_axi_clk=%d", soc_private->control_camnoc_axi_clk); @@ -415,6 +486,19 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( soc_private->camnoc_axi_min_ib_bw)) required_camnoc_bw = soc_private->camnoc_axi_min_ib_bw; + cam_debug = cam_debug_get_settings(); + if (cam_debug && cam_debug->cpas_settings.camnoc_bw) { + if (cam_debug->cpas_settings.camnoc_bw < + soc_private->camnoc_bus_width) + required_camnoc_bw = + soc_private->camnoc_bus_width; + else + required_camnoc_bw = + cam_debug->cpas_settings.camnoc_bw; + CAM_INFO(CAM_CPAS, "Overriding camnoc bw: %llu", + required_camnoc_bw); + } + intermediate_result = required_camnoc_bw; do_div(intermediate_result, soc_private->camnoc_bus_width); clk_rate = intermediate_result; diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index ad85d89953c8..55d08da9ffd7 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -25,12 +25,16 @@ #include "cam_debug_util.h" #include "cam_common_util.h" #include "cam_compat.h" +#include "cam_cpas_hw.h" #define CAM_REQ_MGR_EVENT_MAX 30 static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; +static struct device_attribute camera_debug_sysfs_attr = + __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); + static int cam_media_device_setup(struct device *dev) { int rc; @@ -810,9 +814,17 @@ static int cam_req_mgr_component_master_bind(struct device *dev) } CAM_INFO(CAM_CRM, "All camera components bound successfully"); + rc = sysfs_create_file(&dev->kobj, &camera_debug_sysfs_attr.attr); + if (rc < 0) { + CAM_ERR(CAM_CPAS, + "Failed to create debug attribute, rc=%d\n", rc); + goto sysfs_fail; + } return rc; +sysfs_fail: + sysfs_remove_file(&dev->kobj, &camera_debug_sysfs_attr.attr); req_mgr_device_deinit: cam_req_mgr_core_device_deinit(); req_mgr_core_fail: @@ -835,6 +847,7 @@ static void cam_req_mgr_component_master_unbind(struct device *dev) component_unbind_all(dev, NULL); /* Now proceed with unbinding master */ + sysfs_remove_file(&dev->kobj, &camera_debug_sysfs_attr.attr); cam_req_mgr_core_device_deinit(); cam_req_mgr_util_deinit(); cam_media_device_cleanup(); diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index c5e1dc7b671f..96d466008cf2 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -4,12 +4,115 @@ */ #include +#include #include #include "cam_debug_util.h" static uint debug_mdl; module_param(debug_mdl, uint, 0644); +struct camera_debug_settings cam_debug; + +const struct camera_debug_settings *cam_debug_get_settings() +{ + return &cam_debug; +} + +static int cam_debug_parse_cpas_settings(const char *setting, u64 value) +{ + if (!strcmp(setting, "camnoc_bw")) { + cam_debug.cpas_settings.camnoc_bw = value; + } else if (!strcmp(setting, "mnoc_hf_0_ab_bw")) { + cam_debug.cpas_settings.mnoc_hf_0_ab_bw = value; + } else if (!strcmp(setting, "mnoc_hf_0_ib_bw")) { + cam_debug.cpas_settings.mnoc_hf_0_ib_bw = value; + } else if (!strcmp(setting, "mnoc_hf_1_ab_bw")) { + cam_debug.cpas_settings.mnoc_hf_1_ab_bw = value; + } else if (!strcmp(setting, "mnoc_hf_1_ib_bw")) { + cam_debug.cpas_settings.mnoc_hf_1_ib_bw = value; + } else if (!strcmp(setting, "mnoc_sf_0_ab_bw")) { + cam_debug.cpas_settings.mnoc_sf_0_ab_bw = value; + } else if (!strcmp(setting, "mnoc_sf_0_ib_bw")) { + cam_debug.cpas_settings.mnoc_sf_0_ib_bw = value; + } else if (!strcmp(setting, "mnoc_sf_1_ab_bw")) { + cam_debug.cpas_settings.mnoc_sf_1_ab_bw = value; + } else if (!strcmp(setting, "mnoc_sf_1_ib_bw")) { + cam_debug.cpas_settings.mnoc_sf_1_ib_bw = value; + } else if (!strcmp(setting, "mnoc_sf_icp_ab_bw")) { + cam_debug.cpas_settings.mnoc_sf_icp_ab_bw = value; + } else if (!strcmp(setting, "mnoc_sf_icp_ib_bw")) { + cam_debug.cpas_settings.mnoc_sf_icp_ib_bw = value; + } else { + CAM_ERR(CAM_UTIL, "Unsupported cpas sysfs entry"); + return -EINVAL; + } + + return 0; +} + +ssize_t cam_debug_sysfs_node_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc = 0; + char *local_buf = NULL, *local_buf_temp = NULL; + char *driver; + char *setting = NULL; + char *value_str = NULL; + u64 value; + + CAM_INFO(CAM_UTIL, "Sysfs debug attr name:[%s] buf:[%s] bytes:[%d]", + attr->attr.name, buf, count); + local_buf = kmemdup(buf, (count + sizeof(char)), GFP_KERNEL); + local_buf_temp = local_buf; + driver = strsep(&local_buf, "#"); + if (!driver) { + CAM_ERR(CAM_UTIL, + "Invalid input driver name buf:[%s], count:%d", + buf, count); + goto error; + } + + setting = strsep(&local_buf, "="); + if (!setting) { + CAM_ERR(CAM_UTIL, "Invalid input setting buf:[%s], count:%d", + buf, count); + goto error; + } + + value_str = strsep(&local_buf, "="); + if (!value_str) { + CAM_ERR(CAM_UTIL, "Invalid input value buf:[%s], count:%d", + buf, count); + goto error; + } + + rc = kstrtou64(value_str, 0, &value); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "Error converting value:[%s], buf:[%s]", + value_str, buf); + goto error; + } + + CAM_INFO(CAM_UTIL, + "Processing sysfs store for driver:[%s], setting:[%s], value:[%llu]", + driver, setting, value); + + if (!strcmp(driver, "cpas")) { + rc = cam_debug_parse_cpas_settings(setting, value); + if (rc) + goto error; + } else { + CAM_ERR(CAM_UTIL, "Unsupported driver in camera debug node"); + goto error; + } + + kfree(local_buf_temp); + return count; + +error: + kfree(local_buf_temp); + return -EPERM; +} const char *cam_get_module_name(unsigned int module_id) { diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 5537b2d8db5f..3a53aa9ce566 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -6,6 +6,8 @@ #ifndef _CAM_DEBUG_UTIL_H_ #define _CAM_DEBUG_UTIL_H_ +#include + #define CAM_CDM (1 << 0) #define CAM_CORE (1 << 1) #define CAM_CPAS (1 << 2) @@ -44,6 +46,32 @@ #define STR_BUFFER_MAX_LENGTH 1024 +/** + * struct cam_cpas_debug_settings - Sysfs debug settings for cpas driver + */ +struct cam_cpas_debug_settings { + uint64_t mnoc_hf_0_ab_bw; + uint64_t mnoc_hf_0_ib_bw; + uint64_t mnoc_hf_1_ab_bw; + uint64_t mnoc_hf_1_ib_bw; + uint64_t mnoc_sf_0_ab_bw; + uint64_t mnoc_sf_0_ib_bw; + uint64_t mnoc_sf_1_ab_bw; + uint64_t mnoc_sf_1_ib_bw; + uint64_t mnoc_sf_icp_ab_bw; + uint64_t mnoc_sf_icp_ib_bw; + uint64_t camnoc_bw; +}; + +/** + * struct camera_debug_settings - Sysfs debug settings for camera + * + * @cpas_settings: Debug settings for cpas driver. + */ +struct camera_debug_settings { + struct cam_cpas_debug_settings cpas_settings; +}; + /* * cam_debug_log() * @@ -211,4 +239,17 @@ const char *cam_get_module_name(unsigned int module_id); __LINE__, ##args); \ }) +/** + * @brief : API to get camera debug settings + * @return const struct camera_debug_settings pointer. + */ +const struct camera_debug_settings *cam_debug_get_settings(void); + +/** + * @brief : API to parse and store input from sysfs debug node + * @return Number of bytes read from buffer on success, or -EPERM on error. + */ +ssize_t cam_debug_sysfs_node_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + #endif /* _CAM_DEBUG_UTIL_H_ */ From 1b644126dd5ec143b28ff501abeef031729fed56 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 16 Apr 2020 20:28:26 -0700 Subject: [PATCH 331/790] msm: camera: smmu: Profile time taken for map, unmap Add debugging capability to profile ion alloc, smmu map and unmap calls. Enable below debugfs settings to get the traces with corresponding latencies. Alloc : echo 1 > /sys/kernel/debug/camera_memmgr/alloc_profile_enable Map, Unmap : echo 1 > /sys/kernel/debug/camera_smmu/map_profile_enable Capture the profiling numbers in traces. CRs-Fixed: 2538876 Change-Id: I92dc58416a9febc77a7836b8f7b1523b547c128f Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_req_mgr/cam_mem_mgr.c | 47 +++++++++++++++++++++++++++-- drivers/cam_req_mgr/cam_mem_mgr.h | 6 +++- drivers/cam_smmu/cam_smmu_api.c | 40 +++++++++++++++++++++++- drivers/cam_utils/cam_common_util.h | 21 ++++++++++++- 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 84bc7ce95bad..97a6c8b1b094 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -9,12 +9,15 @@ #include #include #include +#include #include "cam_compat.h" #include "cam_req_mgr_util.h" #include "cam_mem_mgr.h" #include "cam_smmu_api.h" #include "cam_debug_util.h" +#include "cam_trace.h" +#include "cam_common_util.h" static struct cam_mem_table tbl; static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED); @@ -116,6 +119,29 @@ static int cam_mem_util_unmap_cpu_va(struct dma_buf *dmabuf, return rc; } +static int cam_mem_mgr_create_debug_fs(void) +{ + tbl.dentry = debugfs_create_dir("camera_memmgr", NULL); + if (!tbl.dentry) { + CAM_ERR(CAM_MEM, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_bool("alloc_profile_enable", + 0644, + tbl.dentry, + &tbl.alloc_profile_enable)) { + CAM_ERR(CAM_MEM, + "failed to create alloc_profile_enable"); + goto err; + } + + return 0; +err: + debugfs_remove_recursive(tbl.dentry); + return -ENOMEM; +} + int cam_mem_mgr_init(void) { int i; @@ -141,6 +167,8 @@ int cam_mem_mgr_init(void) atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED); + cam_mem_mgr_create_debug_fs(); + return 0; } @@ -375,12 +403,17 @@ static int cam_mem_util_get_dma_buf_fd(size_t len, { struct dma_buf *dmabuf = NULL; int rc = 0; + struct timespec64 ts1, ts2; + long microsec = 0; if (!buf || !fd) { CAM_ERR(CAM_MEM, "Invalid params, buf=%pK, fd=%pK", buf, fd); return -EINVAL; } + if (tbl.alloc_profile_enable) + CAM_GET_TIMESTAMP(ts1); + *buf = ion_alloc(len, heap_id_mask, flags); if (IS_ERR_OR_NULL(*buf)) return -ENOMEM; @@ -403,6 +436,13 @@ static int cam_mem_util_get_dma_buf_fd(size_t len, rc = -EINVAL; } + if (tbl.alloc_profile_enable) { + CAM_GET_TIMESTAMP(ts2); + CAM_GET_TIMESTAMP_DIFF_IN_MICRO(ts1, ts2, microsec); + trace_cam_log_event("IONAllocProfile", "size and time in micro", + len, microsec); + } + return rc; get_fd_fail: @@ -639,8 +679,9 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) if (rc) { CAM_ERR(CAM_MEM, - "Failed in map_hw_va, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", - cmd->flags, fd, region, cmd->num_hdl, rc); + "Failed in map_hw_va, len=%llu, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", + cmd->len, cmd->flags, fd, region, + cmd->num_hdl, rc); goto map_hw_fail; } } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index 6ce30db66fe3..b9e42b62d52f 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_MEM_MGR_H_ @@ -65,12 +65,16 @@ struct cam_mem_buf_queue { * @bitmap: bitmap of the mem mgr utility * @bits: max bits of the utility * @bufq: array of buffers + * @dentry: Debugfs entry + * @alloc_profile_enable: Whether to enable alloc profiling */ struct cam_mem_table { struct mutex m_lock; void *bitmap; size_t bits; struct cam_mem_buf_queue bufq[CAM_MEM_BUFQ_MAX]; + struct dentry *dentry; + bool alloc_profile_enable; }; /** diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 3f86b8c5e3be..1cc957803f4c 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -23,6 +23,8 @@ #include "cam_smmu_api.h" #include "cam_debug_util.h" #include "camera_main.h" +#include "cam_trace.h" +#include "cam_common_util.h" #define SHARED_MEM_POOL_GRANULARITY 16 @@ -147,6 +149,7 @@ struct cam_iommu_cb_set { u32 non_fatal_fault; struct dentry *dentry; bool cb_dump_enable; + bool map_profile_enable; }; static const struct of_device_id msm_cam_smmu_dt_match[] = { @@ -1718,6 +1721,8 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, size_t size = 0; uint32_t iova = 0; int rc = 0; + struct timespec64 ts1, ts2; + long microsec = 0; if (IS_ERR_OR_NULL(buf)) { rc = PTR_ERR(buf); @@ -1732,6 +1737,9 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, goto err_out; } + if (iommu_cb_set.map_profile_enable) + CAM_GET_TIMESTAMP(ts1); + attach = dma_buf_attach(buf, iommu_cb_set.cb_info[idx].dev); if (IS_ERR_OR_NULL(attach)) { rc = PTR_ERR(attach); @@ -1791,7 +1799,9 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, table = dma_buf_map_attachment(attach, dma_dir); if (IS_ERR_OR_NULL(table)) { rc = PTR_ERR(table); - CAM_ERR(CAM_SMMU, "Error: dma map attachment failed"); + CAM_ERR(CAM_SMMU, + "Error: dma map attachment failed, size=%zu", + buf->size); goto err_detach; } @@ -1808,6 +1818,13 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, "iova=%pK, region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d", iova, region_id, *paddr_ptr, *len_ptr, attach->dma_map_attrs); + if (iommu_cb_set.map_profile_enable) { + CAM_GET_TIMESTAMP(ts2); + CAM_GET_TIMESTAMP_DIFF_IN_MICRO(ts1, ts2, microsec); + trace_cam_log_event("SMMUMapProfile", "size and time in micro", + *len_ptr, microsec); + } + if (table->sgl) { CAM_DBG(CAM_SMMU, "DMA buf: %pK, device: %pK, attach: %pK, table: %pK", @@ -1934,6 +1951,8 @@ static int cam_smmu_unmap_buf_and_remove_from_list( int rc; size_t size; struct iommu_domain *domain; + struct timespec64 ts1, ts2; + long microsec = 0; if ((!mapping_info->buf) || (!mapping_info->table) || (!mapping_info->attach)) { @@ -1952,6 +1971,9 @@ static int cam_smmu_unmap_buf_and_remove_from_list( mapping_info->region_id, mapping_info->paddr, mapping_info->len, mapping_info->attach->dma_map_attrs); + if (iommu_cb_set.map_profile_enable) + CAM_GET_TIMESTAMP(ts1); + if (mapping_info->region_id == CAM_SMMU_REGION_SHARED) { CAM_DBG(CAM_SMMU, "Removing SHARED buffer paddr = %pK, len = %zu", @@ -1988,6 +2010,13 @@ static int cam_smmu_unmap_buf_and_remove_from_list( dma_buf_detach(mapping_info->buf, mapping_info->attach); dma_buf_put(mapping_info->buf); + if (iommu_cb_set.map_profile_enable) { + CAM_GET_TIMESTAMP(ts2); + CAM_GET_TIMESTAMP_DIFF_IN_MICRO(ts1, ts2, microsec); + trace_cam_log_event("SMMUUnmapProfile", + "size and time in micro", mapping_info->len, microsec); + } + mapping_info->buf = NULL; list_del_init(&mapping_info->list); @@ -3633,6 +3662,15 @@ static int cam_smmu_create_debug_fs(void) goto err; } + if (!debugfs_create_bool("map_profile_enable", + 0644, + iommu_cb_set.dentry, + &iommu_cb_set.map_profile_enable)) { + CAM_ERR(CAM_SMMU, + "failed to create map_profile_enable"); + goto err; + } + return 0; err: debugfs_remove_recursive(iommu_cb_set.dentry); diff --git a/drivers/cam_utils/cam_common_util.h b/drivers/cam_utils/cam_common_util.h index e202bae5b761..5bf20501af2e 100644 --- a/drivers/cam_utils/cam_common_util.h +++ b/drivers/cam_utils/cam_common_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_COMMON_UTIL_H_ @@ -14,6 +14,25 @@ #define PTR_TO_U64(ptr) ((uint64_t)(uintptr_t)ptr) #define U64_TO_PTR(ptr) ((void *)(uintptr_t)ptr) +#define CAM_GET_TIMESTAMP(timestamp) ktime_get_real_ts64(&(timestamp)) +#define CAM_GET_TIMESTAMP_DIFF_IN_MICRO(ts_start, ts_end, diff_microsec) \ +({ \ + diff_microsec = 0; \ + if (ts_end.tv_nsec >= ts_start.tv_nsec) { \ + diff_microsec = \ + (ts_end.tv_nsec - ts_start.tv_nsec) / 1000; \ + diff_microsec += \ + (ts_end.tv_sec - ts_start.tv_sec) * 1000 * 1000; \ + } else { \ + diff_microsec = \ + (ts_end.tv_nsec + \ + (1000*1000*1000 - ts_start.tv_nsec)) / 1000; \ + diff_microsec += \ + (ts_end.tv_sec - ts_start.tv_sec - 1) * 1000 * 1000; \ + } \ +}) + + /** * cam_common_util_get_string_index() * From efc0528e8a21d6f1270212f0f9835c001a58be5d Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 19 Dec 2019 22:26:37 -0800 Subject: [PATCH 332/790] msm: camera: smmu: Add support for non-contiguous mermory region Add support to discard a memory region inside the full dma map virtual address space region. CRs-Fixed: 2580128 Change-Id: I76cc778f2437a01a4efabec836ce92c47d983d61 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_icp/fw_inc/hfi_intf.h | 2 + drivers/cam_icp/fw_inc/hfi_reg.h | 2 + drivers/cam_icp/hfi.c | 17 +++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 74 ++++++++-- drivers/cam_smmu/cam_smmu_api.c | 136 +++++++++++++++++- drivers/cam_smmu/cam_smmu_api.h | 13 +- 6 files changed, 226 insertions(+), 18 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 1dcf4ee3668a..afd42d23b9fb 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -32,6 +32,7 @@ struct hfi_mem { * @sec_heap: secondary heap hfi memory for firmware * @qdss: qdss mapped memory for fw * @io_mem: io memory info + * @io_mem2: 2nd io memory info * @icp_base: icp base address */ struct hfi_mem_info { @@ -44,6 +45,7 @@ struct hfi_mem_info { struct hfi_mem shmem; struct hfi_mem qdss; struct hfi_mem io_mem; + struct hfi_mem io_mem2; void __iomem *icp_base; }; diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index 2a30c1451201..df4ae01d7ef2 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -39,6 +39,8 @@ #define HFI_REG_QDSS_IOVA_SIZE 0x70 #define HFI_REG_IO_REGION_IOVA 0x74 #define HFI_REG_IO_REGION_SIZE 0x78 +#define HFI_REG_IO2_REGION_IOVA 0x7C +#define HFI_REG_IO2_REGION_SIZE 0x80 /* end of ICP CSR registers */ diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index b5d340cb424a..89a95aca62e1 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -669,6 +669,15 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, icp_base + HFI_REG_IO_REGION_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova, + icp_base + HFI_REG_IO2_REGION_IOVA); + cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, + icp_base + HFI_REG_IO2_REGION_SIZE); + + CAM_INFO(CAM_HFI, "Resume IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", + hfi_mem->io_mem.iova, hfi_mem->io_mem.len, + hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); + return rc; } @@ -859,6 +868,14 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, icp_base + HFI_REG_IO_REGION_IOVA); cam_io_w_mb((uint32_t)hfi_mem->io_mem.len, icp_base + HFI_REG_IO_REGION_SIZE); + cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova, + icp_base + HFI_REG_IO2_REGION_IOVA); + cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, + icp_base + HFI_REG_IO2_REGION_SIZE); + + CAM_INFO(CAM_HFI, "Init IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", + hfi_mem->io_mem.iova, hfi_mem->io_mem.len, + hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 425cebafae75..1c804d5df6a5 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -2858,18 +2858,21 @@ static int cam_icp_allocate_qdss_mem(void) static int cam_icp_get_io_mem_info(void) { int rc; - size_t len; - dma_addr_t iova; + size_t len, discard_iova_len; + dma_addr_t iova, discard_iova_start; rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl, - &iova, &len); + &iova, &len, &discard_iova_start, &discard_iova_len); if (rc) return rc; icp_hw_mgr.hfi_mem.io_mem.iova_len = len; icp_hw_mgr.hfi_mem.io_mem.iova_start = iova; + icp_hw_mgr.hfi_mem.io_mem.discard_iova_start = discard_iova_start; + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len = discard_iova_len; - CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len); + CAM_DBG(CAM_ICP, "iova: %llx, len: %zu discard iova %llx len %llx", + iova, len, discard_iova_start, discard_iova_len); return rc; } @@ -3162,12 +3165,38 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; - hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; - hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; + if (icp_hw_mgr.hfi_mem.io_mem.discard_iova_start && + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len) { + /* IO Region 1 */ + hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; + hfi_mem.io_mem.len = + icp_hw_mgr.hfi_mem.io_mem.discard_iova_start - + icp_hw_mgr.hfi_mem.io_mem.iova_start; - CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld", - hfi_mem.io_mem.iova, - hfi_mem.io_mem.len); + /* IO Region 2 */ + hfi_mem.io_mem2.iova = + icp_hw_mgr.hfi_mem.io_mem.discard_iova_start + + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len; + hfi_mem.io_mem2.len = + icp_hw_mgr.hfi_mem.io_mem.iova_start + + icp_hw_mgr.hfi_mem.io_mem.iova_len - + hfi_mem.io_mem2.iova; + } else { + /* IO Region 1 */ + hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; + hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; + + /* IO Region 2 */ + hfi_mem.io_mem2.iova = 0x0; + hfi_mem.io_mem2.len = 0x0; + } + + CAM_DBG(CAM_ICP, + "IO region1 IOVA = %X length = %lld, IO region2 IOVA = %X length = %lld", + hfi_mem.io_mem.iova, + hfi_mem.io_mem.len, + hfi_mem.io_mem2.iova, + hfi_mem.io_mem2.len); return cam_hfi_resume(&hfi_mem, a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, @@ -3637,8 +3666,31 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova; hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len; - hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; - hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; + if (icp_hw_mgr.hfi_mem.io_mem.discard_iova_start && + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len) { + /* IO Region 1 */ + hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; + hfi_mem.io_mem.len = + icp_hw_mgr.hfi_mem.io_mem.discard_iova_start - + icp_hw_mgr.hfi_mem.io_mem.iova_start; + + /* IO Region 2 */ + hfi_mem.io_mem2.iova = + icp_hw_mgr.hfi_mem.io_mem.discard_iova_start + + icp_hw_mgr.hfi_mem.io_mem.discard_iova_len; + hfi_mem.io_mem2.len = + icp_hw_mgr.hfi_mem.io_mem.iova_start + + icp_hw_mgr.hfi_mem.io_mem.iova_len - + hfi_mem.io_mem2.iova; + } else { + /* IO Region 1 */ + hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start; + hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len; + + /* IO Region 2 */ + hfi_mem.io_mem2.iova = 0x0; + hfi_mem.io_mem2.len = 0x0; + } return cam_hfi_init(0, &hfi_mem, a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 1cc957803f4c..440e0320a03b 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -15,6 +15,8 @@ #include #include #include +#include + #include #include @@ -137,6 +139,10 @@ struct cam_context_bank_info { bool is_mul_client; int device_count; int num_shared_hdl; + + /* discard iova - non-zero values are valid */ + dma_addr_t discard_iova_start; + size_t discard_iova_len; }; struct cam_iommu_cb_set { @@ -1440,11 +1446,13 @@ end: EXPORT_SYMBOL(cam_smmu_dealloc_qdss); int cam_smmu_get_io_region_info(int32_t smmu_hdl, - dma_addr_t *iova, size_t *len) + dma_addr_t *iova, size_t *len, + dma_addr_t *discard_iova_start, size_t *discard_iova_len) { int32_t idx; - if (!iova || !len || (smmu_hdl == HANDLE_INIT)) { + if (!iova || !len || !discard_iova_start || !discard_iova_len || + (smmu_hdl == HANDLE_INIT)) { CAM_ERR(CAM_SMMU, "Error: Input args are invalid"); return -EINVAL; } @@ -1466,10 +1474,15 @@ int cam_smmu_get_io_region_info(int32_t smmu_hdl, mutex_lock(&iommu_cb_set.cb_info[idx].lock); *iova = iommu_cb_set.cb_info[idx].io_info.iova_start; *len = iommu_cb_set.cb_info[idx].io_info.iova_len; + *discard_iova_start = + iommu_cb_set.cb_info[idx].io_info.discard_iova_start; + *discard_iova_len = + iommu_cb_set.cb_info[idx].io_info.discard_iova_len; CAM_DBG(CAM_SMMU, - "I/O area for hdl = %x start addr = %pK len = %zu", - smmu_hdl, *iova, *len); + "I/O area for hdl = %x Region:[%pK %zu] Discard:[%pK %zu]", + smmu_hdl, *iova, *len, + *discard_iova_start, *discard_iova_len); mutex_unlock(&iommu_cb_set.cb_info[idx].lock); return 0; @@ -3339,6 +3352,11 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, rc = -ENODEV; goto end; } + + if (cb->discard_iova_start) + iommu_dma_reserve_iova(dev, cb->discard_iova_start, + cb->discard_iova_len); + cb->state = CAM_SMMU_ATTACH; } else { CAM_ERR(CAM_SMMU, "Context bank does not have IO region"); @@ -3405,6 +3423,52 @@ static int cam_alloc_smmu_context_banks(struct device *dev) return 0; } +static int cam_smmu_get_discard_memory_regions(struct device_node *of_node, + dma_addr_t *discard_iova_start, size_t *discard_iova_len) +{ + uint32_t discard_iova[2] = { 0 }; + int num_values = 0; + int rc = 0; + + if (!discard_iova_start || !discard_iova_len) + return -EINVAL; + + *discard_iova_start = 0; + *discard_iova_len = 0; + + num_values = of_property_count_u32_elems(of_node, + "iova-region-discard"); + if (num_values <= 0) { + CAM_DBG(CAM_UTIL, "No discard region specified"); + return 0; + } else if (num_values != 2) { + CAM_ERR(CAM_UTIL, "Invalid discard region specified %d", + num_values); + return -EINVAL; + } + + rc = of_property_read_u32_array(of_node, + "iova-region-discard", + discard_iova, num_values); + if (rc) { + CAM_ERR(CAM_UTIL, "Can not read discard region %d", num_values); + return rc; + } else if (!discard_iova[0] || !discard_iova[1]) { + CAM_ERR(CAM_UTIL, + "Incorrect Discard region specified [0x%x 0x%x]", + discard_iova[0], discard_iova[1]); + return -EINVAL; + } + + CAM_DBG(CAM_UTIL, "Discard region [0x%x 0x%x]", + discard_iova[0], discard_iova[0] + discard_iova[1]); + + *discard_iova_start = discard_iova[0]; + *discard_iova_len = discard_iova[1]; + + return 0; +} + static int cam_smmu_get_memory_regions_info(struct device_node *of_node, struct cam_context_bank_info *cb) { @@ -3503,6 +3567,16 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, cb->io_support = 1; cb->io_info.iova_start = region_start; cb->io_info.iova_len = region_len; + rc = cam_smmu_get_discard_memory_regions(child_node, + &cb->io_info.discard_iova_start, + &cb->io_info.discard_iova_len); + if (rc) { + CAM_ERR(CAM_SMMU, + "Invalid Discard region specified in IO region, rc=%d", + rc); + of_node_put(mem_map_node); + return -EINVAL; + } break; case CAM_SMMU_REGION_SECHEAP: cb->secheap_support = 1; @@ -3527,6 +3601,60 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, CAM_DBG(CAM_SMMU, "region_len -> %X", region_len); CAM_DBG(CAM_SMMU, "region_id -> %X", region_id); } + + if (cb->io_support) { + rc = cam_smmu_get_discard_memory_regions(of_node, + &cb->discard_iova_start, + &cb->discard_iova_len); + if (rc) { + CAM_ERR(CAM_SMMU, + "Invalid Discard region specified in CB, rc=%d", + rc); + of_node_put(mem_map_node); + return -EINVAL; + } + + /* Make sure Discard region is properly specified */ + if ((cb->discard_iova_start != + cb->io_info.discard_iova_start) || + (cb->discard_iova_len != + cb->io_info.discard_iova_len)) { + CAM_ERR(CAM_SMMU, + "Mismatch Discard region specified, [0x%x 0x%x] [0x%x 0x%x]", + cb->discard_iova_start, + cb->discard_iova_len, + cb->io_info.discard_iova_start, + cb->io_info.discard_iova_len); + of_node_put(mem_map_node); + return -EINVAL; + } else if (cb->discard_iova_start && cb->discard_iova_len) { + if ((cb->discard_iova_start <= + cb->io_info.iova_start) || + (cb->discard_iova_start >= + cb->io_info.iova_start + cb->io_info.iova_len) || + (cb->discard_iova_start + cb->discard_iova_len >= + cb->io_info.iova_start + cb->io_info.iova_len)) { + CAM_ERR(CAM_SMMU, + "[%s] : Incorrect Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", + cb->name, + cb->discard_iova_start, + cb->discard_iova_start + cb->discard_iova_len, + cb->io_info.iova_start, + cb->io_info.iova_start + cb->io_info.iova_len); + of_node_put(mem_map_node); + return -EINVAL; + } + + CAM_INFO(CAM_SMMU, + "[%s] : Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", + cb->name, + cb->discard_iova_start, + cb->discard_iova_start + cb->discard_iova_len, + cb->io_info.iova_start, + cb->io_info.iova_start + cb->io_info.iova_len); + } + } + of_node_put(mem_map_node); if (!num_regions) { diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index 4c2a6a426ee3..d89cba1510dc 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -60,12 +60,16 @@ typedef void (*cam_smmu_client_page_fault_handler)(struct iommu_domain *domain, /** * @brief : Structure to store region information * - * @param iova_start : Start address of region - * @param iova_len : length of region + * @param iova_start : Start address of region + * @param iova_len : length of region + * @param discard_iova_start : iova addr start from where should not be used + * @param discard_iova_len : length of discard iova region */ struct cam_smmu_region_info { dma_addr_t iova_start; size_t iova_len; + dma_addr_t discard_iova_start; + size_t discard_iova_len; }; /** @@ -387,11 +391,14 @@ int cam_smmu_dealloc_qdss(int32_t smmu_hdl); * @param smmu_hdl: SMMU handle identifying the context bank * @param iova: IOVA address of allocated I/O region * @param len: Length of allocated I/O memory + * @param discard_iova_start: Start address of io space to discard + * @param discard_iova_len: Length of io space to discard * * @return Status of operation. Negative in case of error. Zero otherwise. */ int cam_smmu_get_io_region_info(int32_t smmu_hdl, - dma_addr_t *iova, size_t *len); + dma_addr_t *iova, size_t *len, + dma_addr_t *discard_iova_start, size_t *discard_iova_len); /** * @brief : API to register SMMU hw to platform framework. From 5b396d14110520a03fac6d3366777458a571385e Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 19 Dec 2019 22:25:37 -0800 Subject: [PATCH 333/790] msm: camera: smmu: Use iommu best match algo for camera Use best fit match algo for smmu map instead of first match algo to avoid fragmentation in smmu virtual space. CRs-Fixed: 2580128 Change-Id: I434e6e4396bc713e6e12e3da7ae4b78cc2da6a42 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_smmu/cam_smmu_api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 440e0320a03b..7d531bdd4283 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3353,6 +3353,8 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, goto end; } + iommu_dma_enable_best_fit_algo(dev); + if (cb->discard_iova_start) iommu_dma_reserve_iova(dev, cb->discard_iova_start, cb->discard_iova_len); From 122039844c59379bb2b8a9374d7b77fab57506f8 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Wed, 29 Jan 2020 14:10:55 -0800 Subject: [PATCH 334/790] msm: camera: smmu: Add map and unmap monitor Add map and unmap events in monitor array for each context bank and dump the last set of events whenever some smmu related issue happens. CRs-Fixed: 2538876 Change-Id: I18941e9a64ebd6828419e13471938bb32438122c Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_smmu/cam_smmu_api.c | 109 +++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 7d531bdd4283..dffdf13b2824 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -42,6 +42,11 @@ #define GET_SMMU_HDL(x, y) (((x) << COOKIE_SIZE) | ((y) & COOKIE_MASK)) #define GET_SMMU_TABLE_IDX(x) (((x) >> COOKIE_SIZE) & COOKIE_MASK) +#define CAM_SMMU_MONITOR_MAX_ENTRIES 100 +#define CAM_SMMU_INC_MONITOR_HEAD(head, ret) \ + div_u64_rem(atomic64_add_return(1, head),\ + CAM_SMMU_MONITOR_MAX_ENTRIES, (ret)) + static int g_num_pf_handled = 4; module_param(g_num_pf_handled, int, 0644); @@ -94,6 +99,17 @@ struct secheap_buf_info { struct sg_table *table; }; +struct cam_smmu_monitor { + struct timespec64 timestamp; + bool is_map; + + /* map-unmap info */ + int ion_fd; + dma_addr_t paddr; + size_t len; + enum cam_smmu_region_id region_id; +}; + struct cam_context_bank_info { struct device *dev; struct iommu_domain *domain; @@ -143,6 +159,9 @@ struct cam_context_bank_info { /* discard iova - non-zero values are valid */ dma_addr_t discard_iova_start; size_t discard_iova_len; + + atomic64_t monitor_head; + struct cam_smmu_monitor monitor_entries[CAM_SMMU_MONITOR_MAX_ENTRIES]; }; struct cam_iommu_cb_set { @@ -266,6 +285,76 @@ static int cam_smmu_probe(struct platform_device *pdev); static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr); +static void cam_smmu_update_monitor_array( + struct cam_context_bank_info *cb_info, + bool is_map, + struct cam_dma_buff_info *mapping_info) +{ + int iterator; + + CAM_SMMU_INC_MONITOR_HEAD(&cb_info->monitor_head, &iterator); + + ktime_get_real_ts64(&cb_info->monitor_entries[iterator].timestamp); + + cb_info->monitor_entries[iterator].is_map = is_map; + cb_info->monitor_entries[iterator].ion_fd = mapping_info->ion_fd; + cb_info->monitor_entries[iterator].paddr = mapping_info->paddr; + cb_info->monitor_entries[iterator].len = mapping_info->len; + cb_info->monitor_entries[iterator].region_id = mapping_info->region_id; +} + +static void cam_smmu_dump_monitor_array( + struct cam_context_bank_info *cb_info) +{ + int i = 0; + int64_t state_head = 0; + uint32_t index, num_entries, oldest_entry; + uint64_t ms, tmp, hrs, min, sec; + struct timespec64 *ts = NULL; + + state_head = atomic64_read(&cb_info->monitor_head); + + if (state_head == -1) { + return; + } else if (state_head < CAM_SMMU_MONITOR_MAX_ENTRIES) { + num_entries = state_head; + oldest_entry = 0; + } else { + num_entries = CAM_SMMU_MONITOR_MAX_ENTRIES; + div_u64_rem(state_head + 1, + CAM_SMMU_MONITOR_MAX_ENTRIES, &oldest_entry); + } + + CAM_INFO(CAM_SMMU, + "========Dumping monitor information for cb %s===========", + cb_info->name[0]); + + index = oldest_entry; + + for (i = 0; i < num_entries; i++) { + ts = &cb_info->monitor_entries[index].timestamp; + tmp = ts->tv_sec; + ms = (ts->tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); + + CAM_INFO(CAM_SMMU, + "**** %llu:%llu:%llu.%llu : Index[%d] [%s] : ion_fd=%d start=0x%x end=0x%x len=%u region=%d", + hrs, min, sec, ms, + index, + cb_info->monitor_entries[index].is_map ? "MAP" : "UNMAP", + cb_info->monitor_entries[index].ion_fd, + (void *)cb_info->monitor_entries[index].paddr, + ((uint64_t)cb_info->monitor_entries[index].paddr + + (uint64_t)cb_info->monitor_entries[index].len), + (unsigned int)cb_info->monitor_entries[index].len, + cb_info->monitor_entries[index].region_id); + + index = (index + 1) % CAM_SMMU_MONITOR_MAX_ENTRIES; + } +} + static void cam_smmu_page_fault_work(struct work_struct *work) { int j; @@ -328,7 +417,7 @@ static void cam_smmu_dump_cb_info(int idx) CAM_ERR(CAM_SMMU, "********** Context bank dump for %s **********", - cb_info->name); + cb_info->name[0]); CAM_ERR(CAM_SMMU, "Usage: shared_usage=%u io_usage=%u shared_free=%u io_free=%u", (unsigned int)cb_info->shared_mapping_size, @@ -348,6 +437,8 @@ static void cam_smmu_dump_cb_info(int idx) (unsigned int)mapping->len, mapping->region_id); } + + cam_smmu_dump_monitor_array(&iommu_cb_set.cb_info[idx]); } } @@ -1928,6 +2019,9 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list); + cam_smmu_update_monitor_array(&iommu_cb_set.cb_info[idx], true, + mapping_info); + return 0; } @@ -1953,6 +2047,9 @@ static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list); + cam_smmu_update_monitor_array(&iommu_cb_set.cb_info[idx], true, + mapping_info); + return 0; } @@ -1979,6 +2076,9 @@ static int cam_smmu_unmap_buf_and_remove_from_list( return -EINVAL; } + cam_smmu_update_monitor_array(&iommu_cb_set.cb_info[idx], false, + mapping_info); + CAM_DBG(CAM_SMMU, "region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d", mapping_info->region_id, mapping_info->paddr, mapping_info->len, @@ -2948,6 +3048,7 @@ int cam_smmu_get_iova(int handle, int ion_fd, if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) { CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd); rc = -EINVAL; + cam_smmu_dump_cb_info(idx); goto get_addr_end; } @@ -3305,6 +3406,8 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, cb->is_fw_allocated = false; cb->is_secheap_allocated = false; + atomic64_set(&cb->monitor_head, -1); + /* Create a pool with 64K granularity for supporting shared memory */ if (cb->shared_support) { cb->shared_mem_pool = gen_pool_create( @@ -3638,7 +3741,7 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, cb->io_info.iova_start + cb->io_info.iova_len)) { CAM_ERR(CAM_SMMU, "[%s] : Incorrect Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", - cb->name, + cb->name[0], cb->discard_iova_start, cb->discard_iova_start + cb->discard_iova_len, cb->io_info.iova_start, @@ -3649,7 +3752,7 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, CAM_INFO(CAM_SMMU, "[%s] : Discard region specified [0x%x 0x%x] in [0x%x 0x%x]", - cb->name, + cb->name[0], cb->discard_iova_start, cb->discard_iova_start + cb->discard_iova_len, cb->io_info.iova_start, From 43e3ea9bf3b03c44a73fa99b3343377c60c3b697 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Apr 2020 11:36:31 -0700 Subject: [PATCH 335/790] msm: camera: csiphy: Update bringUp sequence Update 2phase and 3phase bring up sequence for different data rate to reflect latest hpg change. CRs-Fixed: 2671221 Change-Id: Idd7445a523486a5fb4ec5d43bcf8987c54c089b0 Signed-off-by: Jigarkumar Zala --- .../include/cam_csiphy_1_2_3_hwreg.h | 102 +++++++++--------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 74a3c564ea45..e70940e80a80 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -12,10 +12,10 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, - .csiphy_common_array_size = 7, + .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 16, - .csiphy_3ph_config_array_size = 30, + .csiphy_3ph_config_array_size = 28, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -23,7 +23,8 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x081C, 0x5A, 0x00, CSIPHY_2PH_REGS}, + {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, {0x081C, 0x5A, 0x00, CSIPHY_3PH_REGS}, {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, @@ -57,9 +58,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x000c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -93,9 +94,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x020c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -111,9 +112,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0428, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x040c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -129,9 +130,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0628, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x060c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -151,9 +152,9 @@ struct csiphy_reg_t { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x000c, 0xFF, 0x00, CSIPHY_DNP_PARAMS}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -171,7 +172,7 @@ struct csiphy_reg_t {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -187,7 +188,7 @@ struct csiphy_reg_t { {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -222,7 +223,7 @@ struct csiphy_reg_t }, { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -246,8 +247,8 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -269,17 +270,15 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -301,8 +300,6 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -310,8 +307,8 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -333,8 +330,6 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -348,44 +343,51 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { .bandwidth = 5700000000, .data_rate_reg_array_size = 6, .csiphy_data_rate_regs = { + {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + } }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 9, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { - {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 9, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { - {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, }, } } From 49dfccf2601c2e0c331fc89be19653e26f6efbfe Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 20 Apr 2020 20:34:46 -0700 Subject: [PATCH 336/790] msm: camera: csiphy: Remove unnecessary delay from reset sequence Lane enable register reset is not required any delay to reflect the change. This change removes the unnecesaary delay from lane_enable register. Also, adding 1us of delay between back to back write in SW reset register along with condition based refelction of delay. CRs-Fixed: 2671221 Change-Id: I010570045a97fc1489a84d22ebd39df6f6f14f0a Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 24 ++++++++----------- .../cam_csiphy/cam_csiphy_dev.h | 4 ++-- .../include/cam_csiphy_1_2_3_hwreg.h | 18 +++++++------- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 69ebbda53dee..60ebe5172673 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -71,10 +71,11 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev) csiphy_dev->ctrl_reg->csiphy_reset_reg[i].reg_data, base + csiphy_dev->ctrl_reg->csiphy_reset_reg[i].reg_addr); - - usleep_range(csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay - * 1000, csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay - * 1000 + 10); + if (csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay > 0) + usleep_range( + csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay, + csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay + + 5); } } @@ -465,22 +466,16 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) case CSIPHY_LANE_ENABLE: cam_io_w_mb(lane_enable, csiphybase + csiphy_common_reg->reg_addr); - usleep_range(csiphy_common_reg->delay * 1000, - csiphy_common_reg->delay * 1000 + 10); break; case CSIPHY_DEFAULT_PARAMS: cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); - usleep_range(csiphy_common_reg->delay * 1000, - csiphy_common_reg->delay * 1000 + 10); break; case CSIPHY_2PH_REGS: if (!csiphy_dev->csiphy_info.csiphy_3phase) { cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); - usleep_range(csiphy_common_reg->delay * 1000, - csiphy_common_reg->delay * 1000 + 10); } break; case CSIPHY_3PH_REGS: @@ -488,13 +483,14 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); - usleep_range(csiphy_common_reg->delay * 1000, - csiphy_common_reg->delay * 1000 + 10); } break; default: break; } + if (csiphy_common_reg->delay > 0) + usleep_range(csiphy_common_reg->delay, + csiphy_common_reg->delay + 5); } while (lane_mask) { @@ -541,8 +537,8 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) break; } if (reg_array[lane_pos][i].delay > 0) { - usleep_range(reg_array[lane_pos][i].delay*1000, - reg_array[lane_pos][i].delay*1000 + 10); + usleep_range(reg_array[lane_pos][i].delay, + reg_array[lane_pos][i].delay + 5); } } lane_mask >>= 1; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index e1c0910b37c7..c88b109a5db4 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_DEV_H_ @@ -137,7 +137,7 @@ struct csiphy_intf_params { * struct csiphy_reg_t * @reg_addr: Register address * @reg_data: Register data - * @delay: Delay + * @delay: Delay in us * @csiphy_param_type: CSIPhy parameter type */ struct csiphy_reg_t { diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index e70940e80a80..a9290d6e6cc5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -26,16 +26,16 @@ struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { {0x081C, 0x5A, 0x00, CSIPHY_2PH_REGS}, {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, {0x081C, 0x5A, 0x00, CSIPHY_3PH_REGS}, - {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, }; struct csiphy_reg_t csiphy_reset_reg_1_2_3[] = { - {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE}, + {0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE}, {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }; @@ -247,7 +247,7 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x098C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x64, CSIPHY_DEFAULT_PARAMS}, {0x0168, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -277,7 +277,7 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x64, CSIPHY_DEFAULT_PARAMS}, {0x0368, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -307,7 +307,7 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x64, CSIPHY_DEFAULT_PARAMS}, {0x0568, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -348,7 +348,7 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x0A, CSIPHY_DEFAULT_PARAMS}, } }, @@ -368,7 +368,7 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { @@ -387,7 +387,7 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, } } From a5c3abfd09c0d3c6de2dd2d9877c75c7b657a1e4 Mon Sep 17 00:00:00 2001 From: ANIL KUMAR KANAKANTI Date: Wed, 26 Feb 2020 12:06:33 +0530 Subject: [PATCH 337/790] msm: camera: csiphy: Fixed CSID overflow errors Fix: Updated PHY settings as per latest PHY HPG to avoid possible CSID overflow errors. CRs-Fixed: 2567045 Change-Id: I7a508cb8ef31b642b2afbeb1adb1508b1d8ee205 Signed-off-by: ANIL KUMAR KANAKANTI Signed-off-by: Jigarkumar Zala --- .../include/cam_csiphy_1_2_1_hwreg.h | 157 +++++++----------- 1 file changed, 64 insertions(+), 93 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 32fbf47eabd9..c9fb93f7e9bd 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_1_HWREG_H_ @@ -12,10 +12,10 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .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_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 20, - .csiphy_3ph_config_array_size = 34, + .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -25,6 +25,7 @@ struct csiphy_reg_t csiphy_common_reg_1_2_1[] = { {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, + {0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, }; @@ -33,7 +34,7 @@ struct csiphy_reg_t csiphy_reset_reg_1_2_1[] = { {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE}, {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }; @@ -58,7 +59,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0900, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -80,7 +81,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0C80, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -102,7 +103,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0A00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -124,7 +125,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -146,7 +147,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0C00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -288,10 +289,11 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -306,28 +308,27 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09AC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -342,16 +343,14 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -360,10 +359,11 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -378,16 +378,14 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -397,82 +395,55 @@ struct data_rate_settings_t data_rate_delta_table_1_2_1 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 12, + .data_rate_reg_array_size = 9, .csiphy_data_rate_regs = { - {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, } }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 24, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { - {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 24, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { - {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, }, } } From 655736ee0b6e2e82d086b1583354595e42187610 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Wed, 29 Apr 2020 15:39:53 -0700 Subject: [PATCH 338/790] msm: camera: common: Remove extra CAM_INFO logs Changes extraneous CAM_INFO logs into CAM_DBG logs in order to help de-clutter serial boot logs. CRs-Fixed: 2669269 Change-Id: I7589bd64363aa122c46e1193c68bbf49d78a4a9a Signed-off-by: Karthik Jayakumar --- drivers/cam_icp/cam_icp_subdev.c | 2 +- drivers/cam_isp/cam_isp_dev.c | 2 +- drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 2 +- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 2 +- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 2 +- drivers/cam_jpeg/cam_jpeg_dev.c | 2 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 2 +- drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c | 6 +++--- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 2 +- drivers/cam_sensor_module/cam_flash/cam_flash_soc.c | 4 ++-- drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c | 4 ++-- drivers/cam_smmu/cam_smmu_api.c | 2 +- drivers/cam_utils/cam_debug_util.c | 3 +++ drivers/cam_utils/cam_soc_util.c | 2 +- drivers/camera_main.c | 2 +- 15 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 801c88591436..d4c7e025afbd 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -205,7 +205,7 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.open_cnt = 0; mutex_init(&g_icp_dev.icp_lock); - CAM_INFO(CAM_ICP, "Component bound successfully"); + CAM_DBG(CAM_ICP, "Component bound successfully"); return rc; diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 322ee3d85449..a8c56ae19229 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -161,7 +161,7 @@ static int cam_isp_dev_component_bind(struct device *dev, mutex_init(&g_isp_dev.isp_mutex); - CAM_INFO(CAM_ISP, "Component bound successfully"); + CAM_DBG(CAM_ISP, "Component bound successfully"); return 0; unregister: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index c0b555d37090..6f4152671f5a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -149,7 +149,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 with rc %d", rc); + CAM_DBG(CAM_ISP, "Option clk get failed with rc %d", rc); rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler, irq_data); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 67c59bc0e205..a7ee65edb32a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3581,7 +3581,7 @@ static int cam_vfe_bus_ver3_init_hw(void *hw_priv, } /* no clock gating at bus input */ - CAM_INFO(CAM_ISP, "Overriding clock gating at bus input"); + CAM_DBG(CAM_ISP, "Overriding clock gating at bus input"); cam_io_w_mb(0x3FFFFFF, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->cgc_ovd); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index e632596991bb..d114de1d0e6d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -327,7 +327,7 @@ int cam_vfe_top_ver3_init_hw(void *device_priv, * Auto clock gating is enabled by default, but no harm * in setting the value we expect. */ - CAM_INFO(CAM_ISP, "Enabling clock gating at IFE top"); + CAM_DBG(CAM_ISP, "Enabling clock gating at IFE top"); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, common_data.common_reg->core_cgc_ovd_0, 0x0); diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index d78d889e8844..76a055b89149 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -143,7 +143,7 @@ static int cam_jpeg_dev_component_bind(struct device *dev, mutex_init(&g_jpeg_dev.jpeg_mutex); - CAM_INFO(CAM_JPEG, "Component bound successfully"); + CAM_DBG(CAM_JPEG, "Component bound successfully"); return rc; diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 55d08da9ffd7..ba45dbd7b63f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -813,7 +813,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto req_mgr_device_deinit; } - CAM_INFO(CAM_CRM, "All camera components bound successfully"); + CAM_DBG(CAM_CRM, "All camera components bound successfully"); rc = sysfs_create_file(&dev->kobj, &camera_debug_sysfs_attr.attr); if (rc < 0) { CAM_ERR(CAM_CPAS, diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c index 3ee629e3f1ca..0248effdfbe4 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -57,13 +57,13 @@ int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl, } if (!soc_info->gpio_data) { - CAM_INFO(CAM_ACTUATOR, "No GPIO found"); + CAM_DBG(CAM_ACTUATOR, "No GPIO found"); rc = 0; return rc; } if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { - CAM_INFO(CAM_ACTUATOR, "No GPIO found"); + CAM_DBG(CAM_ACTUATOR, "No GPIO found"); return -EINVAL; } diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 804bee34c2df..d78d4c7fb8c2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -426,7 +426,7 @@ static int cam_cci_component_bind(struct device *dev, g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; mutex_init(&(new_cci_dev->init_mutex)); - CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); + CAM_DBG(CAM_CCI, "Device Type :%d", soc_info->index); cpas_parms.cam_cpas_client_cb = NULL; cpas_parms.cell_index = soc_info->index; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index dc56aebfe739..abd2355403c6 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -112,7 +112,7 @@ static int32_t cam_get_source_node_info( "qcom,current-ma", &soc_private->flash_op_current[i]); if (rc) { - CAM_INFO(CAM_FLASH, "op-current: read failed"); + CAM_DBG(CAM_FLASH, "op-current: read failed"); rc = 0; } @@ -121,7 +121,7 @@ static int32_t cam_get_source_node_info( "qcom,duration-ms", &soc_private->flash_max_duration[i]); if (rc) { - CAM_INFO(CAM_FLASH, + CAM_DBG(CAM_FLASH, "max-duration prop unavailable: %d", rc); rc = 0; diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 3a944abff778..abe1b2c7a0fd 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -682,10 +682,10 @@ static int cam_res_mgr_component_bind(struct device *dev, rc = cam_res_mgr_parse_dt(&pdev->dev); if (rc) { - CAM_INFO(CAM_RES, "Disable shared gpio support."); + CAM_DBG(CAM_RES, "Disable shared gpio support."); cam_res->shared_gpio_enabled = false; } else { - CAM_INFO(CAM_RES, "Enable shared gpio support."); + CAM_DBG(CAM_RES, "Enable shared gpio support."); cam_res->shared_gpio_enabled = true; } diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 3f86b8c5e3be..719f98cc5f9c 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -771,7 +771,7 @@ static int cam_smmu_create_add_handle_in_table(char *name, *hdl = iommu_cb_set.cb_info[i].handle; mutex_unlock( &iommu_cb_set.cb_info[i].lock); - CAM_INFO(CAM_SMMU, + CAM_DBG(CAM_SMMU, "%s already got handle 0x%x", name, iommu_cb_set.cb_info[i].handle); diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index 96d466008cf2..882b9ea678cc 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -202,6 +202,9 @@ const char *cam_get_module_name(unsigned int module_id) case CAM_PRESIL: name = "CAM-PRESIL"; break; + case CAM_RES: + name = "CAM-RES"; + break; default: name = "CAM"; break; diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index ce80569ab0f9..73077a799da7 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -556,7 +556,7 @@ int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info, clk_name); if (index < 0) { - CAM_INFO(CAM_UTIL, "No clk data for %s", clk_name); + CAM_DBG(CAM_UTIL, "No clk data for %s", clk_name); *clk_index = -1; *clk = ERR_PTR(-EINVAL); return -EINVAL; diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 621f5c3dbe74..b73c9992f093 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -278,7 +278,7 @@ static int camera_init(void) } } - CAM_INFO(CAM_UTIL, "Spectra camera driver initcalls done"); + CAM_INFO(CAM_UTIL, "Spectra camera driver initialized"); end_init: return rc; From bac9cf4a20ff04087c666b3d2fe261c0faae2312 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Tue, 14 Apr 2020 13:09:51 -0700 Subject: [PATCH 339/790] msm: camera: cpas: Fix bw voting units for interconnect In bw voting for ahb and axi, interconnect API requires bw values in KBps. Add conversion to icc compatible units before voting to interconnect framework. CRs-Fixed: 2664087 Change-Id: If64c2bcbd20a3e2ad9f738e18955d5a8256d715c Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_utils/cam_soc_icc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index b9d507eea165..7cf14a2c4044 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -37,7 +37,8 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) CAM_DBG(CAM_UTIL, "Bus client=[%s] index[%d]", bus_client->common_data->name, idx); - rc = icc_set_bw(bus_client_data->icc_data, ab, ib); + rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), + Bps_to_icc(ib)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s], idx: %d", @@ -59,7 +60,8 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) CAM_DBG(CAM_UTIL, "Bus client=[%s] :ab[%llu] ib[%llu]", bus_client->common_data->name, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, ab, ib); + rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), + Bps_to_icc(ib)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s]", bus_client->common_data->name); From 7429211dfcea83fed5ad5b339d7f395bef3e343c Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Tue, 21 Apr 2020 21:22:55 -0700 Subject: [PATCH 340/790] msm: camera: isp: Fix checking for valid bw vote The BW config coming from user space functions based on usage type as single or dual. Checking the validity of bw vote based on hw index caused bw updates to be ignored from isp side. Fix checking for valid bw vote by falling back to walking through all indices. CRs-Fixed: 2669422 Change-Id: I5762fb06c8b69ade286d890146e91844fbde5ce7 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 253361b608f8..5d8f1b2c6860 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3805,7 +3805,7 @@ static int cam_ife_config_hw_external_cdm(struct cam_ife_hw_mgr_ctx *ctx, static int cam_ife_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) { - int rc = -1, i, idx; + int rc = -1, i; struct cam_isp_hw_config_args *cfg; struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; @@ -3844,18 +3844,17 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - if (hw_update_data->bw_config_valid[idx] == true) { + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (hw_update_data->bw_config_valid[i]) { CAM_DBG(CAM_PERF, "idx=%d, bw_config_version=%d", - idx, hw_update_data->bw_config_version); + i, hw_update_data->bw_config_version); if (hw_update_data->bw_config_version == CAM_ISP_BW_CONFIG_V1) { rc = cam_isp_blob_bw_update( (struct cam_isp_bw_config *) - &hw_update_data->bw_config[idx], ctx); + &hw_update_data->bw_config[i], ctx); if (rc) CAM_ERR(CAM_PERF, "Bandwidth Update Failed rc: %d", rc); @@ -3863,7 +3862,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_ISP_BW_CONFIG_V2) { rc = cam_isp_blob_bw_update_v2( (struct cam_isp_bw_config_v2 *) - &hw_update_data->bw_config_v2[idx], + &hw_update_data->bw_config_v2[i], ctx); if (rc) CAM_ERR(CAM_PERF, From 538accf58ebd5da4f03e9ce4aed9ac90176e5d7b Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Fri, 17 Apr 2020 22:52:58 +0530 Subject: [PATCH 341/790] msm: camera: sensor: Turn off the flash while flushing Turn off the flash while flushing if the flushed request is flash off and removed flush request ID validation in flush_all scenario. CRs-Fixed: 2667472 Change-Id: Iaf123f2f56117d7b7d1ef6d2291b0cde8c232d44 Signed-off-by: Anil Kumar Kanakanti --- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 0e60442c4a75..ed2afb3e89f2 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -232,7 +232,6 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, if ((flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) && (flash_data->cmn_attr.request_id > 0) && - (flash_data->cmn_attr.request_id <= req_id) && flash_data->cmn_attr.is_settings_valid) { is_off_needed = true; CAM_DBG(CAM_FLASH, @@ -463,7 +462,7 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) CAM_ERR(CAM_FLASH, "Flash control Null"); return -EINVAL; } - + CAM_DBG(CAM_FLASH, "Flash OFF Triggered"); if (flash_ctrl->switch_trigger) cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger, (enum led_brightness)LED_SWITCH_OFF); @@ -1541,6 +1540,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) flash_data->led_current_ma[i] = flash_operation_info->led_current_ma[i]; + CAM_DBG(CAM_FLASH, + "FLASH_CMD_TYPE op:%d", flash_data->opcode); if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) add_req.skip_before_applying |= SKIP_NEXT_FRAME; From bfdaaba4eb92cb5884038fa77e0407bf116ceb02 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 11 May 2020 13:12:40 -0700 Subject: [PATCH 342/790] msm: camera: sync: Increase number of fences in sync Some mfhdr usecases require more than 1024 fences because of delayed request processing and bypass. Increase maximum number of fences or sync objects to 2048. CRs-Fixed: 2598592 Change-Id: If11fa2986fce0cd97c14370d29a117230134d6f5 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_sync/cam_sync_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index a8612fdcd7c5..2cd8917758ee 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __CAM_SYNC_PRIVATE_H__ @@ -24,7 +24,7 @@ #endif #define CAM_SYNC_OBJ_NAME_LEN 64 -#define CAM_SYNC_MAX_OBJS 1024 +#define CAM_SYNC_MAX_OBJS 2048 #define CAM_SYNC_MAX_V4L2_EVENTS 100 #define CAM_SYNC_DEBUG_FILENAME "cam_debug" #define CAM_SYNC_DEBUG_BASEDIR "cam" From 0bede4b524330002d51952aa15a46b9ed4463595 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 12 May 2020 17:26:39 -0700 Subject: [PATCH 343/790] msm: camera: util: Correct the return code For secure mode, csiphy driver ask for secure stream. Currently this call always return success. This change return the appropriate result of failure/success. CRs-Fixed: 2673418 Change-Id: Ib425ad77e6481888acefdaf843256602aa759cf3 Signed-off-by: Jigarkumar Zala --- drivers/cam_utils/cam_compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index e0b70865c885..27c84b0ecac2 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -86,7 +86,7 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, rc = -EINVAL; } - return 0; + return rc; } void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) @@ -169,7 +169,7 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, rc = -EINVAL; } - return 0; + return rc; } void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) From 26ef750076c4bb3224318b48404b4bc77a32df5c Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 13 May 2020 14:38:59 -0700 Subject: [PATCH 344/790] msm: camera: isp: Update last reported request ID correctly The last reported request ID indicates the request ID for which the shutter was sent last. Only update this field for requests that have not bubbled in a given IFE ctx. CRs-Fixed: 2680502 Change-Id: I9ee4b479fe95800efa40ea1ff8d840fc79ef6528 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 7fd06d214c9e..13cd4ae74d94 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1364,7 +1364,9 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( } list_for_each_entry(req, &ctx->active_req_list, list) { - if (req->request_id > ctx_isp->reported_req_id) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if ((!req_isp->bubble_detected) && + (req->request_id > ctx_isp->reported_req_id)) { request_id = req->request_id; ctx_isp->reported_req_id = request_id; __cam_isp_ctx_update_event_record(ctx_isp, From 0ec65e7c742b6747559fc3c3a7f788131a091954 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 24 Jan 2020 17:51:50 +0530 Subject: [PATCH 345/790] msm: camera: cpas: Add mandatory bw option for axi ports clocks Bw voting is mandatory to enable rt_axi and nrt_axi clocks. Adding support for the same. CRs-Fixed: 2585073, 2685467 Change-Id: I236b3940faea3925e668e0e5ddbf61e8e569b2f7 Signed-off-by: Rishabh Jain Signed-off-by: Alok Chauhan Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_cpas/cam_cpas_hw.c | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index aedd05861174..936a5f7177ec 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -982,6 +982,46 @@ unlock_tree: return rc; } +static int cam_cpas_util_apply_default_axi_vote( + struct cam_hw_info *cpas_hw, bool enable) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_axi_port *axi_port = NULL; + uint64_t mnoc_ab_bw = 0, mnoc_ib_bw = 0; + int rc = 0, i = 0; + + mutex_lock(&cpas_core->tree_lock); + for (i = 0; i < cpas_core->num_axi_ports; i++) { + if (!cpas_core->axi_port[i].ab_bw || + !cpas_core->axi_port[i].ib_bw) + axi_port = &cpas_core->axi_port[i]; + else + continue; + + if (enable) + mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + else + mnoc_ib_bw = 0; + + CAM_DBG(CAM_CPAS, "Port=[%s] :ab[%llu] ib[%llu]", + axi_port->axi_port_name, mnoc_ab_bw, mnoc_ib_bw); + + rc = cam_cpas_util_vote_bus_client_bw(&axi_port->bus_client, + mnoc_ab_bw, mnoc_ib_bw, false, &axi_port->applied_ab_bw, + &axi_port->applied_ib_bw); + if (rc) { + CAM_ERR(CAM_CPAS, + "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d", + mnoc_ab_bw, mnoc_ib_bw, rc); + goto unlock_tree; + } + } + +unlock_tree: + mutex_unlock(&cpas_core->tree_lock); + return rc; +} + static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, uint32_t client_handle, struct cam_axi_vote *client_axi_vote) { @@ -1364,6 +1404,10 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, goto remove_ahb_vote; if (cpas_core->streamon_clients == 0) { + rc = cam_cpas_util_apply_default_axi_vote(cpas_hw, true); + if (rc) + goto remove_ahb_vote; + atomic_set(&cpas_core->irq_count, 1); rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, applied_level); @@ -1543,6 +1587,11 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, cpas_client, &axi_vote); + if (rc) + goto done; + + if (cpas_core->streamon_clients == 0) + rc = cam_cpas_util_apply_default_axi_vote(cpas_hw, false); done: mutex_unlock(&cpas_core->client_mutex[client_indx]); mutex_unlock(&cpas_hw->hw_mutex); From 74410fea6b7a382b4bead7c5fe73f6847721e293 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 27 Apr 2020 20:59:07 -0700 Subject: [PATCH 346/790] msm: camera: sync: Add SYNC_CANCEL support in sync driver Add SYNC_CANCEL definition and signal CANCEL instead of ERROR in flush cases. CRs-Fixed: 2673810 Change-Id: I1bd83e382f9b38f5f020a5af3b883083e211e3d2 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_core/cam_context_utils.c | 12 +++--- drivers/cam_cust/cam_custom_context.c | 8 ++-- drivers/cam_isp/cam_isp_context.c | 8 ++-- drivers/cam_sync/cam_sync.c | 53 +++++++++++++++++++++++---- drivers/cam_sync/cam_sync_util.c | 11 ++++-- include/uapi/camera/media/cam_sync.h | 3 +- 6 files changed, 70 insertions(+), 25 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 09f164561d69..5b09d1183d7a 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -201,8 +201,10 @@ static void cam_context_sync_callback(int32_t sync_obj, int status, void *data) * in a critical section which is provided by this * mutex. */ - if (status == CAM_SYNC_STATE_SIGNALED_ERROR) { - CAM_DBG(CAM_CTXT, "fence error: %d", sync_obj); + if ((status == CAM_SYNC_STATE_SIGNALED_ERROR) || + (status == CAM_SYNC_STATE_SIGNALED_CANCEL)) { + CAM_DBG(CAM_CTXT, "fence error: %d on obj %d", + status, sync_obj); flush_cmd.req_id = req->request_id; cam_context_flush_req_to_hw(ctx, &flush_cmd); } @@ -660,7 +662,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) if (req->out_map_entries[i].sync_id != -1) { rc = cam_sync_signal( req->out_map_entries[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled, sync_id:%d", @@ -732,7 +734,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) if (req->out_map_entries[i].sync_id != -1) { rc = cam_sync_signal( req->out_map_entries[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled ctx: %pK dev_name: %s dev_handle: %d ctx_state: %d", @@ -845,7 +847,7 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, req->out_map_entries[i].sync_id; if (sync_id != -1) { rc = cam_sync_signal(sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled, sync_id:%d", diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 25e092841cef..0fff3f079242 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -116,7 +116,7 @@ static int __cam_custom_ctx_flush_req(struct cam_context *ctx, req_custom->fence_map_out[i].sync_id); rc = cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); if (rc) CAM_ERR_RATE_LIMIT(CAM_CUSTOM, "signal fence failed\n"); @@ -291,7 +291,7 @@ static int __cam_custom_stop_dev_core( if (req_custom->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -307,7 +307,7 @@ static int __cam_custom_stop_dev_core( if (req_custom->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -323,7 +323,7 @@ static int __cam_custom_stop_dev_core( if (req_custom->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); } list_add_tail(&req->list, &ctx->free_req_list); } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 7fd06d214c9e..093e7793684f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2953,7 +2953,7 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, req_isp->fence_map_out[i].sync_id); rc = cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); if (rc) { tmp = req_isp->fence_map_out[i].sync_id; CAM_ERR_RATE_LIMIT(CAM_ISP, @@ -4832,7 +4832,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -4848,7 +4848,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -4864,7 +4864,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_CANCEL); } list_add_tail(&req->list, &ctx->free_req_list); } diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 8f38bcca160b..a984a7be8ffa 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -110,8 +110,9 @@ int cam_sync_register_callback(sync_callback cb_func, } /* Trigger callback if sync object is already in SIGNALED state */ - if ((row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS || - row->state == CAM_SYNC_STATE_SIGNALED_ERROR) && + if (((row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS) || + (row->state == CAM_SYNC_STATE_SIGNALED_ERROR) || + (row->state == CAM_SYNC_STATE_SIGNALED_CANCEL)) && (!row->remaining)) { if (trigger_cb_without_switch) { CAM_DBG(CAM_SYNC, "Invoke callback for sync object:%d", @@ -222,8 +223,9 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status) return -EALREADY; } - if (status != CAM_SYNC_STATE_SIGNALED_SUCCESS && - status != CAM_SYNC_STATE_SIGNALED_ERROR) { + if ((status != CAM_SYNC_STATE_SIGNALED_SUCCESS) && + (status != CAM_SYNC_STATE_SIGNALED_ERROR) && + (status != CAM_SYNC_STATE_SIGNALED_CANCEL)) { spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); CAM_ERR(CAM_SYNC, "Error: signaling with undefined status = %d", @@ -439,6 +441,7 @@ int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms) case CAM_SYNC_STATE_INVALID: case CAM_SYNC_STATE_ACTIVE: case CAM_SYNC_STATE_SIGNALED_ERROR: + case CAM_SYNC_STATE_SIGNALED_CANCEL: CAM_ERR(CAM_SYNC, "Error: Wait on invalid state = %d, obj = %d", row->state, sync_obj); @@ -653,8 +656,9 @@ static int cam_sync_handle_register_user_payload( return -EINVAL; } - if (row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS || - row->state == CAM_SYNC_STATE_SIGNALED_ERROR) { + if ((row->state == CAM_SYNC_STATE_SIGNALED_SUCCESS) || + (row->state == CAM_SYNC_STATE_SIGNALED_ERROR) || + (row->state == CAM_SYNC_STATE_SIGNALED_CANCEL)) { cam_sync_util_send_v4l2_event(CAM_SYNC_V4L_EVENT_ID_CB_TRIG, sync_obj, @@ -1033,6 +1037,41 @@ static int cam_sync_create_debugfs(void) } #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +int cam_synx_sync_signal(int32_t sync_obj, uint32_t synx_status) +{ + int rc = 0; + uint32_t sync_status = synx_status; + + switch (synx_status) { + case SYNX_STATE_ACTIVE: + sync_status = CAM_SYNC_STATE_ACTIVE; + break; + case SYNX_STATE_SIGNALED_SUCCESS: + sync_status = CAM_SYNC_STATE_SIGNALED_SUCCESS; + break; + case SYNX_STATE_SIGNALED_ERROR: + sync_status = CAM_SYNC_STATE_SIGNALED_ERROR; + break; + case 4: /* SYNX_STATE_SIGNALED_CANCEL: */ + sync_status = CAM_SYNC_STATE_SIGNALED_CANCEL; + break; + default: + CAM_ERR(CAM_SYNC, "Invalid synx status %d for obj %d", + synx_status, sync_obj); + sync_status = CAM_SYNC_STATE_SIGNALED_ERROR; + break; + } + + rc = cam_sync_signal(sync_obj, sync_status); + if (rc) { + CAM_ERR(CAM_SYNC, + "synx signal failed with %d, sync_obj=%d, synx_status=%d, sync_status=%d", + sync_obj, synx_status, sync_status, rc); + } + + return rc; +} + static int cam_sync_register_synx_bind_ops(void) { int rc = 0; @@ -1043,7 +1082,7 @@ static int cam_sync_register_synx_bind_ops(void) params.ops.register_callback = cam_sync_register_callback; params.ops.deregister_callback = cam_sync_deregister_callback; params.ops.enable_signaling = cam_sync_get_obj_ref; - params.ops.signal = cam_sync_signal; + params.ops.signal = cam_synx_sync_signal; rc = synx_register_ops(¶ms); if (rc) diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c index d7e0f4125290..44a7bd4d0574 100644 --- a/drivers/cam_sync/cam_sync_util.c +++ b/drivers/cam_sync/cam_sync_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. */ #include "cam_sync_util.h" @@ -88,8 +88,9 @@ int cam_sync_init_group_object(struct sync_table_row *table, } /* check for child's state */ - if (child_row->state == CAM_SYNC_STATE_SIGNALED_ERROR) { - row->state = CAM_SYNC_STATE_SIGNALED_ERROR; + if ((child_row->state == CAM_SYNC_STATE_SIGNALED_ERROR) || + (child_row->state == CAM_SYNC_STATE_SIGNALED_CANCEL)) { + row->state = child_row->state; spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); continue; } @@ -123,7 +124,8 @@ int cam_sync_init_group_object(struct sync_table_row *table, } if (!row->remaining) { - if (row->state != CAM_SYNC_STATE_SIGNALED_ERROR) + if ((row->state != CAM_SYNC_STATE_SIGNALED_ERROR) && + (row->state != CAM_SYNC_STATE_SIGNALED_CANCEL)) row->state = CAM_SYNC_STATE_SIGNALED_SUCCESS; complete_all(&row->signaled); } @@ -392,6 +394,7 @@ int cam_sync_util_update_parent_state(struct sync_table_row *parent_row, break; case CAM_SYNC_STATE_SIGNALED_ERROR: + case CAM_SYNC_STATE_SIGNALED_CANCEL: break; case CAM_SYNC_STATE_INVALID: diff --git a/include/uapi/camera/media/cam_sync.h b/include/uapi/camera/media/cam_sync.h index d1ab63fd4294..86d987585ae7 100644 --- a/include/uapi/camera/media/cam_sync.h +++ b/include/uapi/camera/media/cam_sync.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_SYNC_H__ @@ -35,6 +35,7 @@ #define CAM_SYNC_STATE_ACTIVE 1 #define CAM_SYNC_STATE_SIGNALED_SUCCESS 2 #define CAM_SYNC_STATE_SIGNALED_ERROR 3 +#define CAM_SYNC_STATE_SIGNALED_CANCEL 4 /** * struct cam_sync_ev_header - Event header for sync event notification From a1f635192b0e05b851431b6a3270a1c9d0cfd436 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 14 May 2020 16:10:54 -0700 Subject: [PATCH 347/790] msm: camera: cci: Correct the check and return code Update the master status data type, as it expects the negative value and do the operation accordingly. Also, correct the return code and update the validation check. CRs-Fixed: 2686717 Change-Id: I8ecae74de2995a08e532a7f0ef078d48d45a928e Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 8 +++++--- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 4 ++-- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 6efa77a8d55d..fcdee4e50c60 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -148,15 +148,17 @@ static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev, { int32_t rc = 0; uint32_t reg_offset = master * 0x200 + queue * 0x100; - struct cam_hw_soc_info *soc_info = - &cci_dev->soc_info; - void __iomem *base = soc_info->reg_map[0].mem_base; + struct cam_hw_soc_info *soc_info = NULL; + void __iomem *base = NULL; if (!cci_dev) { CAM_ERR(CAM_CCI, "Failed"); return -EINVAL; } + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + rc = cam_cci_validate_queue(cci_dev, 1, master, queue); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed %d", rc); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index d78d4c7fb8c2..269a2fd28a61 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -33,8 +33,8 @@ static long cam_cci_subdev_ioctl(struct v4l2_subdev *sd, int32_t rc = 0; if (arg == NULL) { - CAM_ERR(CAM_CCI, "Invalid Args"); - return rc; + CAM_ERR(CAM_CCI, "Args is Null"); + return -EINVAL; } switch (cmd) { diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 5ac6441df53a..fbf1834d6074 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -124,7 +124,7 @@ struct cam_cci_i2c_queue_info { }; struct cam_cci_master_info { - uint32_t status; + int32_t status; atomic_t q_free[NUM_QUEUES]; uint8_t q_lock[NUM_QUEUES]; uint8_t reset_pending; From f54a60cc9e6fd8d77120d58249a8210ff17885f5 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Thu, 14 May 2020 16:37:10 -0700 Subject: [PATCH 348/790] msm: camera: reqmgr: Add subdev node at the time of register Some driver probes do not have a real dependency on other driver probes. Still, they are blocked from creating subdev nodes if that driver's probe comes after all nodes were created in master component bind. Add subdev node at the time of subdev register itself, to lift this requirement. CRs-Fixed: 2686729 Change-Id: I3505071a79296dd7d5665b13d533a9a022aa1a85 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 70 +++++---------------------- drivers/cam_req_mgr/cam_req_mgr_dev.h | 2 - 2 files changed, 12 insertions(+), 60 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index ba45dbd7b63f..555ad537b830 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -656,14 +656,6 @@ int cam_register_subdev(struct cam_subdev *csd) } mutex_lock(&g_dev.dev_lock); - if ((g_dev.subdev_nodes_created) && - (csd->sd_flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) { - CAM_ERR(CAM_CRM, - "dynamic node is not allowed, name: %s, type :%d", - csd->name, csd->ent_function); - rc = -EINVAL; - goto reg_fail; - } sd = &csd->sd; v4l2_subdev_init(sd, csd->ops); @@ -682,6 +674,18 @@ int cam_register_subdev(struct cam_subdev *csd) goto reg_fail; } + rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); + if (rc) { + CAM_ERR(CAM_CRM, "Failed to register subdev node: %s, rc: %d", + sd->name, rc); + goto reg_fail; + } + + if (sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) { + sd->entity.name = video_device_node_name(sd->devnode); + CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); + } + g_dev.count++; reg_fail: @@ -706,47 +710,6 @@ int cam_unregister_subdev(struct cam_subdev *csd) } EXPORT_SYMBOL(cam_unregister_subdev); -static int cam_dev_mgr_create_subdev_nodes(void) -{ - int rc; - struct v4l2_subdev *sd; - - if (!g_dev.v4l2_dev) { - CAM_ERR(CAM_CRM, "V4L2 device not initialized"); - return -EINVAL; - } - - if (!g_dev.state) { - CAM_ERR(CAM_CRM, "camera root device not ready"); - return -ENODEV; - } - - mutex_lock(&g_dev.dev_lock); - if (g_dev.subdev_nodes_created) { - rc = -EEXIST; - goto create_fail; - } - - rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev); - if (rc) { - CAM_ERR(CAM_CRM, "failed to register the sub devices"); - goto create_fail; - } - - list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { - if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) - continue; - sd->entity.name = video_device_node_name(sd->devnode); - CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name); - } - - g_dev.subdev_nodes_created = true; - -create_fail: - mutex_unlock(&g_dev.dev_lock); - return rc; -} - static int cam_req_mgr_component_master_bind(struct device *dev) { int rc = 0; @@ -767,7 +730,6 @@ static int cam_req_mgr_component_master_bind(struct device *dev) g_dev.open_cnt = 0; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); - g_dev.subdev_nodes_created = false; mutex_init(&g_dev.dev_lock); rc = cam_req_mgr_util_init(); @@ -806,13 +768,6 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto req_mgr_device_deinit; } - rc = cam_dev_mgr_create_subdev_nodes(); - if (rc) { - CAM_ERR(CAM_CRM, "failed in creating devices for subdevs %d", - rc); - goto req_mgr_device_deinit; - } - CAM_DBG(CAM_CRM, "All camera components bound successfully"); rc = sysfs_create_file(&dev->kobj, &camera_debug_sysfs_attr.attr); if (rc < 0) { @@ -855,7 +810,6 @@ static void cam_req_mgr_component_master_unbind(struct device *dev) cam_v4l2_device_cleanup(); mutex_destroy(&g_dev.dev_lock); g_dev.state = false; - g_dev.subdev_nodes_created = false; } static const struct component_master_ops cam_req_mgr_component_master_ops = { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 9b241e6f0a46..464720efb0a2 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -12,7 +12,6 @@ * * @video: pointer to struct video device. * @v4l2_dev: pointer to struct v4l2 device. - * @subdev_nodes_created: all subdev nodes are created for this device * @count: number of subdevices registered. * @dev_lock: lock for the subdevice count. * @state: state of the root device. @@ -24,7 +23,6 @@ struct cam_req_mgr_device { struct video_device *video; struct v4l2_device *v4l2_dev; - bool subdev_nodes_created; int count; struct mutex dev_lock; bool state; From c6096c4e35da67cdb24d28b03e1ca88a74382a83 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Tue, 5 May 2020 12:55:22 -0700 Subject: [PATCH 349/790] msm: camera: uapi: Support for UAPI_HEADER_TEST config Aligns the uapi header types and includes to be in-line with upstream kernel formatting. The errors are given by enabling the UAPI_HEADER_TEST config, which is now enabled in GKI builds. CRs-Fixed: 2679250 Change-Id: I195fb2aab9251043fc63d79dd31f2db53b1228f5 Signed-off-by: Karthik Jayakumar --- include/uapi/camera/media/cam_cpas.h | 30 +- include/uapi/camera/media/cam_custom.h | 110 +++---- include/uapi/camera/media/cam_defs.h | 356 +++++++++++------------ include/uapi/camera/media/cam_fd.h | 50 ++-- include/uapi/camera/media/cam_icp.h | 72 ++--- include/uapi/camera/media/cam_isp.h | 362 ++++++++++++------------ include/uapi/camera/media/cam_jpeg.h | 28 +- include/uapi/camera/media/cam_lrme.h | 18 +- include/uapi/camera/media/cam_ope.h | 152 +++++----- include/uapi/camera/media/cam_req_mgr.h | 168 +++++------ include/uapi/camera/media/cam_sensor.h | 254 ++++++++--------- include/uapi/camera/media/cam_sync.h | 26 +- include/uapi/camera/media/cam_tfe.h | 172 +++++------ 13 files changed, 899 insertions(+), 899 deletions(-) diff --git a/include/uapi/camera/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h index d78b384ce771..71d1f131cbbf 100644 --- a/include/uapi/camera/media/cam_cpas.h +++ b/include/uapi/camera/media/cam_cpas.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_CPAS_H__ #define __UAPI_CAM_CPAS_H__ -#include +#include #define CAM_FAMILY_CAMERA_SS 1 #define CAM_FAMILY_CPAS_SS 2 @@ -73,10 +73,10 @@ * */ struct cam_cpas_query_cap { - uint32_t camera_family; - uint32_t reserved; - struct cam_hw_version camera_version; - struct cam_hw_version cpas_version; + __u32 camera_family; + __u32 reserved; + struct cam_hw_version camera_version; + struct cam_hw_version cpas_version; }; /** @@ -93,15 +93,15 @@ struct cam_cpas_query_cap { * @ddr_ib_bw DDR IB bw for this path */ struct cam_axi_per_path_bw_vote { - uint32_t usage_data; - uint32_t transac_type; - uint32_t path_data_type; - uint32_t reserved; - uint64_t camnoc_bw; - uint64_t mnoc_ab_bw; - uint64_t mnoc_ib_bw; - uint64_t ddr_ab_bw; - uint64_t ddr_ib_bw; + __u32 usage_data; + __u32 transac_type; + __u32 path_data_type; + __u32 reserved; + __u64 camnoc_bw; + __u64 mnoc_ab_bw; + __u64 mnoc_ib_bw; + __u64 ddr_ab_bw; + __u64 ddr_ib_bw; }; #endif /* __UAPI_CAM_CPAS_H__ */ diff --git a/include/uapi/camera/media/cam_custom.h b/include/uapi/camera/media/cam_custom.h index 37edce171e4b..87ca4274217c 100644 --- a/include/uapi/camera/media/cam_custom.h +++ b/include/uapi/camera/media/cam_custom.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_CUSTOM_H__ #define __UAPI_CAM_CUSTOM_H__ -#include "cam_defs.h" +#include /* Custom driver name */ #define CAM_CUSTOM_DEV_NAME "cam-custom" @@ -53,8 +53,8 @@ * */ struct cam_custom_dev_cap_info { - uint32_t hw_type; - uint32_t hw_version; + __u32 hw_type; + __u32 hw_version; }; /** @@ -68,11 +68,11 @@ struct cam_custom_dev_cap_info { * */ struct cam_custom_query_cap_cmd { - struct cam_iommu_handle device_iommu; - struct cam_iommu_handle cdm_iommu; - int32_t num_dev; - uint32_t reserved; - struct cam_custom_dev_cap_info dev_caps[CAM_CUSTOM_NUM_SUB_DEVICES]; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + __s32 num_dev; + __u32 reserved; + struct cam_custom_dev_cap_info dev_caps[CAM_CUSTOM_NUM_SUB_DEVICES]; }; /* Acquire Device */ @@ -86,12 +86,12 @@ struct cam_custom_query_cap_cmd { * */ struct cam_custom_out_port_info { - uint32_t res_type; - uint32_t format; - uint32_t custom_info1; - uint32_t custom_info2; - uint32_t custom_info3; - uint32_t reserved; + __u32 res_type; + __u32 format; + __u32 custom_info1; + __u32 custom_info2; + __u32 custom_info3; + __u32 reserved; }; /** @@ -125,30 +125,30 @@ struct cam_custom_out_port_info { * */ struct cam_custom_in_port_info { - uint32_t res_type; - uint32_t lane_type; - uint32_t lane_num; - uint32_t lane_cfg; - uint32_t vc[CAM_CUSTOM_VC_DT_CFG_MAX]; - uint32_t dt[CAM_CUSTOM_VC_DT_CFG_MAX]; - uint32_t num_valid_vc_dt; - uint32_t format; - uint32_t test_pattern; - uint32_t usage_type; - uint32_t left_start; - uint32_t left_stop; - uint32_t left_width; - uint32_t right_start; - uint32_t right_stop; - uint32_t right_width; - uint32_t line_start; - uint32_t line_stop; - uint32_t height; - uint32_t pixel_clk; - uint32_t num_bytes_out; - uint32_t custom_info1; - uint32_t custom_info2; - uint32_t num_out_res; + __u32 res_type; + __u32 lane_type; + __u32 lane_num; + __u32 lane_cfg; + __u32 vc[CAM_CUSTOM_VC_DT_CFG_MAX]; + __u32 dt[CAM_CUSTOM_VC_DT_CFG_MAX]; + __u32 num_valid_vc_dt; + __u32 format; + __u32 test_pattern; + __u32 usage_type; + __u32 left_start; + __u32 left_stop; + __u32 left_width; + __u32 right_start; + __u32 right_stop; + __u32 right_width; + __u32 line_start; + __u32 line_stop; + __u32 height; + __u32 pixel_clk; + __u32 num_bytes_out; + __u32 custom_info1; + __u32 custom_info2; + __u32 num_out_res; struct cam_custom_out_port_info data[1]; }; @@ -163,11 +163,11 @@ struct cam_custom_in_port_info { * resource array; */ struct cam_custom_resource { - uint32_t resource_id; - uint32_t length; - uint32_t handle_type; - uint32_t reserved; - uint64_t res_hdl; + __u32 resource_id; + __u32 length; + __u32 handle_type; + __u32 reserved; + __u64 res_hdl; }; /** @@ -180,11 +180,11 @@ struct cam_custom_resource { * @data : Start of data region */ struct cam_custom_acquire_hw_info { - uint32_t num_inputs; - uint32_t input_info_size; - uint32_t input_info_offset; - uint32_t reserved; - uint64_t data; + __u32 num_inputs; + __u32 input_info_size; + __u32 input_info_offset; + __u32 reserved; + __u64 data; }; /** @@ -194,8 +194,8 @@ struct cam_custom_acquire_hw_info { * @reserved: reserved */ struct cam_custom_cmd_buf_type_1 { - uint32_t custom_info; - uint32_t reserved; + __u32 custom_info; + __u32 reserved; }; /** @@ -207,9 +207,9 @@ struct cam_custom_cmd_buf_type_1 { * @reserved: reserved */ struct cam_custom_cmd_buf_type_2 { - uint32_t custom_info1; - uint32_t custom_info2; - uint32_t custom_info3; - uint32_t reserved; + __u32 custom_info1; + __u32 custom_info2; + __u32 custom_info3; + __u32 reserved; }; #endif /* __UAPI_CAM_CUSTOM_H__ */ diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index 52d14a2d3fb3..4c132a8a2fe6 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_DEFS_H__ @@ -85,11 +85,11 @@ enum flush_type_t { * @handle: Control command payload */ struct cam_control { - uint32_t op_code; - uint32_t size; - uint32_t handle_type; - uint32_t reserved; - uint64_t handle; + __u32 op_code; + __u32 size; + __u32 handle_type; + __u32 reserved; + __u64 handle; }; /* camera IOCTL */ @@ -105,10 +105,10 @@ struct cam_control { * @reserved : Reserved for 64 bit aligngment */ struct cam_hw_version { - uint32_t major; - uint32_t minor; - uint32_t incr; - uint32_t reserved; + __u32 major; + __u32 minor; + __u32 incr; + __u32 reserved; }; /** @@ -119,8 +119,8 @@ struct cam_hw_version { * */ struct cam_iommu_handle { - int32_t non_secure; - int32_t secure; + __s32 non_secure; + __s32 secure; }; /* camera secure mode */ @@ -266,18 +266,18 @@ struct cam_iommu_handle { * */ struct cam_plane_cfg { - uint32_t width; - uint32_t height; - uint32_t plane_stride; - uint32_t slice_height; - uint32_t meta_stride; - uint32_t meta_size; - uint32_t meta_offset; - uint32_t packer_config; - uint32_t mode_config; - uint32_t tile_config; - uint32_t h_init; - uint32_t v_init; + __u32 width; + __u32 height; + __u32 plane_stride; + __u32 slice_height; + __u32 meta_stride; + __u32 meta_size; + __u32 meta_offset; + __u32 packer_config; + __u32 mode_config; + __u32 tile_config; + __u32 h_init; + __u32 v_init; }; /** @@ -296,16 +296,16 @@ struct cam_plane_cfg { * */ struct cam_ubwc_plane_cfg_v1 { - uint32_t port_type; - uint32_t meta_stride; - uint32_t meta_size; - uint32_t meta_offset; - uint32_t packer_config; - uint32_t mode_config_0; - uint32_t mode_config_1; - uint32_t tile_config; - uint32_t h_init; - uint32_t v_init; + __u32 port_type; + __u32 meta_stride; + __u32 meta_size; + __u32 meta_offset; + __u32 packer_config; + __u32 mode_config_0; + __u32 mode_config_1; + __u32 tile_config; + __u32 h_init; + __u32 v_init; }; /** @@ -329,24 +329,24 @@ struct cam_ubwc_plane_cfg_v1 { * */ struct cam_ubwc_plane_cfg_v2 { - uint32_t port_type; - uint32_t meta_stride; - uint32_t meta_size; - uint32_t meta_offset; - uint32_t packer_config; - uint32_t mode_config_0; - uint32_t mode_config_1; - uint32_t tile_config; - uint32_t h_init; - uint32_t v_init; - uint32_t static_ctrl; - uint32_t ctrl_2; - uint32_t stats_ctrl_2; - uint32_t lossy_threshold_0; - uint32_t lossy_threshold_1; - uint32_t lossy_var_offset; - uint32_t bandwidth_limit; - uint32_t reserved[3]; + __u32 port_type; + __u32 meta_stride; + __u32 meta_size; + __u32 meta_offset; + __u32 packer_config; + __u32 mode_config_0; + __u32 mode_config_1; + __u32 tile_config; + __u32 h_init; + __u32 v_init; + __u32 static_ctrl; + __u32 ctrl_2; + __u32 stats_ctrl_2; + __u32 lossy_threshold_0; + __u32 lossy_threshold_1; + __u32 lossy_var_offset; + __u32 bandwidth_limit; + __u32 reserved[3]; }; /** * struct cam_cmd_buf_desc - Command buffer descriptor @@ -361,12 +361,12 @@ struct cam_ubwc_plane_cfg_v2 { * */ struct cam_cmd_buf_desc { - int32_t mem_handle; - uint32_t offset; - uint32_t size; - uint32_t length; - uint32_t type; - uint32_t meta_data; + __s32 mem_handle; + __u32 offset; + __u32 size; + __u32 length; + __u32 type; + __u32 meta_data; }; /** @@ -403,26 +403,26 @@ struct cam_cmd_buf_desc { * */ struct cam_buf_io_cfg { - int32_t mem_handle[CAM_PACKET_MAX_PLANES]; - uint32_t offsets[CAM_PACKET_MAX_PLANES]; - struct cam_plane_cfg planes[CAM_PACKET_MAX_PLANES]; - uint32_t format; - uint32_t color_space; - uint32_t color_pattern; - uint32_t bpp; - uint32_t rotation; - uint32_t resource_type; - int32_t fence; - int32_t early_fence; - struct cam_cmd_buf_desc aux_cmd_buf; - uint32_t direction; - uint32_t batch_size; - uint32_t subsample_pattern; - uint32_t subsample_period; - uint32_t framedrop_pattern; - uint32_t framedrop_period; - uint32_t flag; - uint32_t padding; + __s32 mem_handle[CAM_PACKET_MAX_PLANES]; + __u32 offsets[CAM_PACKET_MAX_PLANES]; + struct cam_plane_cfg planes[CAM_PACKET_MAX_PLANES]; + __u32 format; + __u32 color_space; + __u32 color_pattern; + __u32 bpp; + __u32 rotation; + __u32 resource_type; + __s32 fence; + __s32 early_fence; + struct cam_cmd_buf_desc aux_cmd_buf; + __u32 direction; + __u32 batch_size; + __u32 subsample_pattern; + __u32 subsample_period; + __u32 framedrop_pattern; + __u32 framedrop_period; + __u32 flag; + __u32 padding; }; /** @@ -436,11 +436,11 @@ struct cam_buf_io_cfg { * */ struct cam_packet_header { - uint32_t op_code; - uint32_t size; - uint64_t request_id; - uint32_t flags; - uint32_t padding; + __u32 op_code; + __u32 size; + __u64 request_id; + __u32 flags; + __u32 padding; }; /** @@ -453,10 +453,10 @@ struct cam_packet_header { * */ struct cam_patch_desc { - int32_t dst_buf_hdl; - uint32_t dst_offset; - int32_t src_buf_hdl; - uint32_t src_offset; + __s32 dst_buf_hdl; + __u32 dst_offset; + __s32 src_buf_hdl; + __u32 src_offset; }; /** @@ -477,16 +477,16 @@ struct cam_patch_desc { * */ struct cam_packet { - struct cam_packet_header header; - uint32_t cmd_buf_offset; - uint32_t num_cmd_buf; - uint32_t io_configs_offset; - uint32_t num_io_configs; - uint32_t patch_offset; - uint32_t num_patches; - uint32_t kmd_cmd_buf_index; - uint32_t kmd_cmd_buf_offset; - uint64_t payload[1]; + struct cam_packet_header header; + __u32 cmd_buf_offset; + __u32 num_cmd_buf; + __u32 io_configs_offset; + __u32 num_io_configs; + __u32 patch_offset; + __u32 num_patches; + __u32 kmd_cmd_buf_index; + __u32 kmd_cmd_buf_offset; + __u64 payload[1]; }; @@ -497,8 +497,8 @@ struct cam_packet { * @dev_handle: Device handle for the release */ struct cam_release_dev_cmd { - int32_t session_handle; - int32_t dev_handle; + __s32 session_handle; + __s32 dev_handle; }; /** @@ -509,8 +509,8 @@ struct cam_release_dev_cmd { * */ struct cam_start_stop_dev_cmd { - int32_t session_handle; - int32_t dev_handle; + __s32 session_handle; + __s32 dev_handle; }; /** @@ -524,10 +524,10 @@ struct cam_start_stop_dev_cmd { * */ struct cam_config_dev_cmd { - int32_t session_handle; - int32_t dev_handle; - uint64_t offset; - uint64_t packet_handle; + __s32 session_handle; + __s32 dev_handle; + __u64 offset; + __u64 packet_handle; }; /** @@ -539,9 +539,9 @@ struct cam_config_dev_cmd { * */ struct cam_query_cap_cmd { - uint32_t size; - uint32_t handle_type; - uint64_t caps_handle; + __u32 size; + __u32 handle_type; + __u64 caps_handle; }; /** @@ -558,11 +558,11 @@ struct cam_query_cap_cmd { * */ struct cam_acquire_dev_cmd { - int32_t session_handle; - int32_t dev_handle; - uint32_t handle_type; - uint32_t num_resources; - uint64_t resource_hdl; + __s32 session_handle; + __s32 dev_handle; + __u32 handle_type; + __u32 num_resources; + __u64 resource_hdl; }; /* @@ -575,7 +575,7 @@ struct cam_acquire_dev_cmd { * ACQUIRE_HW IOCTL after ACQUIRE_DEV and that is when the HW * is associated with the dev_handle. * - * (Data type): uint32_t + * (Data type): __u32 */ #define CAM_API_COMPAT_CONSTANT 0xFEFEFEFE @@ -602,13 +602,13 @@ struct cam_acquire_dev_cmd { * resource data. */ struct cam_acquire_hw_cmd_v1 { - uint32_t struct_version; - uint32_t reserved; - int32_t session_handle; - int32_t dev_handle; - uint32_t handle_type; - uint32_t data_size; - uint64_t resource_hdl; + __u32 struct_version; + __u32 reserved; + __s32 session_handle; + __s32 dev_handle; + __u32 handle_type; + __u32 data_size; + __u64 resource_hdl; }; /** @@ -621,9 +621,9 @@ struct cam_acquire_hw_cmd_v1 { * valid_acquired_hw: Valid num of acquired hardware */ struct cam_acquired_hw_info { - uint32_t acquired_hw_id[CAM_MAX_ACQ_RES]; - uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; - uint32_t valid_acquired_hw; + __u32 acquired_hw_id[CAM_MAX_ACQ_RES]; + __u32 acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; + __u32 valid_acquired_hw; }; /** @@ -646,13 +646,13 @@ struct cam_acquired_hw_info { * resource data. */ struct cam_acquire_hw_cmd_v2 { - uint32_t struct_version; - uint32_t reserved; - int32_t session_handle; - int32_t dev_handle; - uint32_t handle_type; - uint32_t data_size; - uint64_t resource_hdl; + __u32 struct_version; + __u32 reserved; + __s32 session_handle; + __s32 dev_handle; + __u32 handle_type; + __u32 data_size; + __u64 resource_hdl; struct cam_acquired_hw_info hw_info; }; @@ -672,10 +672,10 @@ struct cam_acquire_hw_cmd_v2 { * @dev_handle: Device handle for the release */ struct cam_release_hw_cmd_v1 { - uint32_t struct_version; - uint32_t reserved; - int32_t session_handle; - int32_t dev_handle; + __u32 struct_version; + __u32 reserved; + __s32 session_handle; + __s32 dev_handle; }; /** @@ -692,12 +692,12 @@ struct cam_release_hw_cmd_v1 { * */ struct cam_flush_dev_cmd { - uint64_t version; - int32_t session_handle; - int32_t dev_handle; - uint32_t flush_type; - uint32_t reserved; - int64_t req_id; + __u64 version; + __s32 session_handle; + __s32 dev_handle; + __u32 flush_type; + __u32 reserved; + __s64 req_id; }; /** @@ -712,8 +712,8 @@ struct cam_flush_dev_cmd { * */ struct cam_ubwc_config { - uint32_t api_version; - uint32_t num_ports; + __u32 api_version; + __u32 num_ports; struct cam_ubwc_plane_cfg_v1 ubwc_plane_cfg[1][CAM_PACKET_MAX_PLANES - 1]; }; @@ -730,8 +730,8 @@ struct cam_ubwc_config { * */ struct cam_ubwc_config_v2 { - uint32_t api_version; - uint32_t num_ports; + __u32 api_version; + __u32 num_ports; struct cam_ubwc_plane_cfg_v2 ubwc_plane_cfg[1][CAM_PACKET_MAX_PLANES - 1]; }; @@ -746,10 +746,10 @@ struct cam_ubwc_config_v2 { * @flags : Flags if any */ struct cam_cmd_mem_region_info { - int32_t mem_handle; - uint32_t offset; - uint32_t size; - uint32_t flags; + __s32 mem_handle; + __u32 offset; + __u32 size; + __u32 flags; }; /** @@ -762,8 +762,8 @@ struct cam_cmd_mem_region_info { * @map_info_array : Array of all the regions */ struct cam_cmd_mem_regions { - uint32_t version; - uint32_t num_regions; + __u32 version; + __u32 num_regions; struct cam_cmd_mem_region_info map_info_array[1]; }; @@ -774,8 +774,8 @@ struct cam_cmd_mem_regions { * @value : Register value to write */ struct cam_reg_write_desc { - uint32_t offset; - uint32_t value; + __u32 offset; + __u32 value; }; /** @@ -785,8 +785,8 @@ struct cam_reg_write_desc { * @num_values : Number of values to read */ struct cam_reg_range_read_desc { - uint32_t offset; - uint32_t num_values; + __u32 offset; + __u32 num_values; }; /** @@ -800,8 +800,8 @@ struct cam_reg_range_read_desc { * @post_read_config : Registers to write after reading DMI data */ struct cam_dmi_read_desc { - uint32_t num_pre_writes; - uint32_t num_post_writes; + __u32 num_pre_writes; + __u32 num_post_writes; struct cam_reg_write_desc pre_read_config[ CAM_REG_DUMP_DMI_CONFIG_MAX]; struct cam_reg_range_read_desc dmi_data_read; @@ -818,11 +818,11 @@ struct cam_dmi_read_desc { * @dmi_read : DMI data to read */ struct cam_reg_read_info { - uint32_t type; - uint32_t reserved; + __u32 type; + __u32 reserved; union { - struct cam_reg_range_read_desc reg_read; - struct cam_dmi_read_desc dmi_read; + struct cam_reg_range_read_desc reg_read; + struct cam_dmi_read_desc dmi_read; }; }; @@ -834,9 +834,9 @@ struct cam_reg_read_info { * @dump_data : Register dump data */ struct cam_reg_dump_out_buffer { - uint64_t req_id; - uint32_t bytes_written; - uint32_t dump_data[1]; + __u64 req_id; + __u32 bytes_written; + __u32 dump_data[1]; }; /** @@ -850,11 +850,11 @@ struct cam_reg_dump_out_buffer { * @read_range : Read range info */ struct cam_reg_dump_desc { - uint32_t reg_base_type; - uint32_t dump_buffer_offset; - uint32_t dump_buffer_size; - uint32_t num_read_range; - struct cam_reg_read_info read_range[1]; + __u32 reg_base_type; + __u32 dump_buffer_offset; + __u32 dump_buffer_size; + __u32 num_read_range; + struct cam_reg_read_info read_range[1]; }; /** @@ -865,8 +865,8 @@ struct cam_reg_dump_desc { * (cam_reg_dump_desc) */ struct cam_reg_dump_input_info { - uint32_t num_dump_sets; - uint32_t dump_set_offsets[1]; + __u32 num_dump_sets; + __u32 dump_set_offsets[1]; }; /** @@ -882,13 +882,13 @@ struct cam_reg_dump_input_info { * @dev_handle : Device Handle */ struct cam_dump_req_cmd { - uint64_t issue_req_id; - size_t offset; - uint32_t buf_handle; - uint32_t error_type; - int32_t session_handle; - int32_t link_hdl; - int32_t dev_handle; + __u64 issue_req_id; + __kernel_size_t offset; + __u32 buf_handle; + __u32 error_type; + __s32 session_handle; + __s32 link_hdl; + __s32 dev_handle; }; #endif /* __UAPI_CAM_DEFS_H__ */ diff --git a/include/uapi/camera/media/cam_fd.h b/include/uapi/camera/media/cam_fd.h index 126be4555f69..da24ec78efaa 100644 --- a/include/uapi/camera/media/cam_fd.h +++ b/include/uapi/camera/media/cam_fd.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_FD_H__ #define __UAPI_CAM_FD_H__ -#include +#include #define CAM_FD_MAX_FACES 35 #define CAM_FD_RAW_RESULT_ENTRIES 512 @@ -40,9 +40,9 @@ * @reserved : Reserved for future use */ struct cam_fd_soc_clock_bw_request { - uint64_t clock_rate; - uint64_t bandwidth; - uint64_t reserved[4]; + __u64 clock_rate; + __u64 bandwidth; + __u64 reserved[4]; }; /** @@ -57,10 +57,10 @@ struct cam_fd_soc_clock_bw_request { * these values directly when the buffer is programmed to HW */ struct cam_fd_face { - uint32_t prop1; - uint32_t prop2; - uint32_t prop3; - uint32_t prop4; + __u32 prop1; + __u32 prop2; + __u32 prop3; + __u32 prop4; }; /** @@ -74,9 +74,9 @@ struct cam_fd_face { * these values directly when the buffer is programmed to HW */ struct cam_fd_results { - struct cam_fd_face faces[CAM_FD_MAX_FACES]; - uint32_t face_count; - uint32_t reserved[3]; + struct cam_fd_face faces[CAM_FD_MAX_FACES]; + __u32 face_count; + __u32 reserved[3]; }; /** @@ -89,11 +89,11 @@ struct cam_fd_results { * @reserved : Reserved for future use */ struct cam_fd_hw_caps { - struct cam_hw_version core_version; - struct cam_hw_version wrapper_version; - uint32_t raw_results_available; - uint32_t supported_modes; - uint64_t reserved; + struct cam_hw_version core_version; + struct cam_hw_version wrapper_version; + __u32 raw_results_available; + __u32 supported_modes; + __u64 reserved; }; /** @@ -105,10 +105,10 @@ struct cam_fd_hw_caps { * @reserved : Reserved for alignment */ struct cam_fd_query_cap_cmd { - struct cam_iommu_handle device_iommu; - struct cam_iommu_handle cdm_iommu; - struct cam_fd_hw_caps hw_caps; - uint64_t reserved; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + struct cam_fd_hw_caps hw_caps; + __u64 reserved; }; /** @@ -123,10 +123,10 @@ struct cam_fd_query_cap_cmd { */ struct cam_fd_acquire_dev_info { struct cam_fd_soc_clock_bw_request clk_bw_request; - uint32_t priority; - uint32_t mode; - uint32_t get_raw_results; - uint32_t reserved[13]; + __u32 priority; + __u32 mode; + __u32 get_raw_results; + __u32 reserved[13]; }; #endif /* __UAPI_CAM_FD_H__ */ diff --git a/include/uapi/camera/media/cam_icp.h b/include/uapi/camera/media/cam_icp.h index 4b5419d2f21d..1139ee473695 100644 --- a/include/uapi/camera/media/cam_icp.h +++ b/include/uapi/camera/media/cam_icp.h @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_ICP_H__ #define __UAPI_CAM_ICP_H__ -#include -#include +#include +#include /* icp, ipe, bps, cdm(ipe/bps) are used in querycap */ #define CAM_ICP_DEV_TYPE_A5 1 @@ -89,12 +89,12 @@ * @axi_path: Per path vote info for IPE/BPS */ struct cam_icp_clk_bw_request_v2 { - uint64_t budget_ns; - uint32_t frame_cycles; - uint32_t rt_flag; - uint32_t reserved; - uint32_t num_paths; - struct cam_axi_per_path_bw_vote axi_path[1]; + __u64 budget_ns; + __u32 frame_cycles; + __u32 rt_flag; + __u32 reserved; + __u32 num_paths; + struct cam_axi_per_path_bw_vote axi_path[1]; }; /** @@ -107,11 +107,11 @@ struct cam_icp_clk_bw_request_v2 { * @compressed_bw: Compressed bandwidth to process frame */ struct cam_icp_clk_bw_request { - uint64_t budget_ns; - uint32_t frame_cycles; - uint32_t rt_flag; - uint64_t uncompressed_bw; - uint64_t compressed_bw; + __u64 budget_ns; + __u32 frame_cycles; + __u32 rt_flag; + __u64 uncompressed_bw; + __u64 compressed_bw; }; /** @@ -126,8 +126,8 @@ struct cam_icp_clk_bw_request { * @hw_ver: major, minor and incr values of a device version */ struct cam_icp_dev_ver { - uint32_t dev_type; - uint32_t reserved; + __u32 dev_type; + __u32 reserved; struct cam_hw_version hw_ver; }; @@ -143,10 +143,10 @@ struct cam_icp_dev_ver { * @revision: FW version increment */ struct cam_icp_ver { - uint32_t major; - uint32_t minor; - uint32_t revision; - uint32_t reserved; + __u32 major; + __u32 minor; + __u32 revision; + __u32 reserved; }; /** @@ -163,11 +163,11 @@ struct cam_icp_ver { struct cam_icp_query_cap_cmd { struct cam_iommu_handle dev_iommu_handle; struct cam_iommu_handle cdm_iommu_handle; - struct cam_icp_ver fw_version; - struct cam_icp_ver api_version; - uint32_t num_ipe; - uint32_t num_bps; - struct cam_icp_dev_ver dev_ver[CAM_ICP_DEV_TYPE_MAX]; + struct cam_icp_ver fw_version; + struct cam_icp_ver api_version; + __u32 num_ipe; + __u32 num_bps; + struct cam_icp_dev_ver dev_ver[CAM_ICP_DEV_TYPE_MAX]; }; /** @@ -179,10 +179,10 @@ struct cam_icp_query_cap_cmd { * @fps: fps */ struct cam_icp_res_info { - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t fps; + __u32 format; + __u32 width; + __u32 height; + __u32 fps; }; /** @@ -199,14 +199,14 @@ struct cam_icp_res_info { * @out_res: output resource */ struct cam_icp_acquire_dev_info { - uint32_t scratch_mem_size; - uint32_t dev_type; - uint32_t io_config_cmd_size; - int32_t io_config_cmd_handle; - uint32_t secure_mode; - int32_t chain_info; + __u32 scratch_mem_size; + __u32 dev_type; + __u32 io_config_cmd_size; + __s32 io_config_cmd_handle; + __u32 secure_mode; + __s32 chain_info; struct cam_icp_res_info in_res; - uint32_t num_out_res; + __u32 num_out_res; struct cam_icp_res_info out_res[1]; } __attribute__((__packed__)); diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index 0acb0f98ca0d..c3126dac8eee 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -6,10 +6,10 @@ #ifndef __UAPI_CAM_ISP_H__ #define __UAPI_CAM_ISP_H__ -#include -#include -#include -#include +#include +#include +#include +#include /* ISP driver name */ #define CAM_ISP_DEV_NAME "cam-isp" @@ -145,8 +145,8 @@ * */ struct cam_isp_dev_cap_info { - uint32_t hw_type; - uint32_t reserved; + __u32 hw_type; + __u32 reserved; struct cam_hw_version hw_version; }; @@ -161,11 +161,11 @@ struct cam_isp_dev_cap_info { * */ struct cam_isp_query_cap_cmd { - struct cam_iommu_handle device_iommu; - struct cam_iommu_handle cdm_iommu; - int32_t num_dev; - uint32_t reserved; - struct cam_isp_dev_cap_info dev_caps[CAM_ISP_HW_MAX]; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + __s32 num_dev; + __u32 reserved; + struct cam_isp_dev_cap_info dev_caps[CAM_ISP_HW_MAX]; }; /* Acquire Device */ @@ -185,14 +185,14 @@ struct cam_isp_query_cap_cmd { * */ struct cam_isp_out_port_info { - uint32_t res_type; - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t comp_grp_id; - uint32_t split_point; - uint32_t secure_mode; - uint32_t reserved; + __u32 res_type; + __u32 format; + __u32 width; + __u32 height; + __u32 comp_grp_id; + __u32 split_point; + __u32 secure_mode; + __u32 reserved; }; /** @@ -213,16 +213,16 @@ struct cam_isp_out_port_info { * */ struct cam_isp_out_port_info_v2 { - uint32_t res_type; - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t comp_grp_id; - uint32_t split_point; - uint32_t secure_mode; - uint32_t wm_mode; - uint32_t out_port_res1; - uint32_t out_port_res2; + __u32 res_type; + __u32 format; + __u32 width; + __u32 height; + __u32 comp_grp_id; + __u32 split_point; + __u32 secure_mode; + __u32 wm_mode; + __u32 out_port_res1; + __u32 out_port_res2; }; /** @@ -260,31 +260,31 @@ struct cam_isp_out_port_info_v2 { * */ struct cam_isp_in_port_info { - uint32_t res_type; - uint32_t lane_type; - uint32_t lane_num; - uint32_t lane_cfg; - uint32_t vc; - uint32_t dt; - uint32_t format; - uint32_t test_pattern; - uint32_t usage_type; - uint32_t left_start; - uint32_t left_stop; - uint32_t left_width; - uint32_t right_start; - uint32_t right_stop; - uint32_t right_width; - uint32_t line_start; - uint32_t line_stop; - uint32_t height; - uint32_t pixel_clk; - uint32_t batch_size; - uint32_t dsp_mode; - uint32_t hbi_cnt; - uint32_t reserved; - uint32_t num_out_res; - struct cam_isp_out_port_info data[1]; + __u32 res_type; + __u32 lane_type; + __u32 lane_num; + __u32 lane_cfg; + __u32 vc; + __u32 dt; + __u32 format; + __u32 test_pattern; + __u32 usage_type; + __u32 left_start; + __u32 left_stop; + __u32 left_width; + __u32 right_start; + __u32 right_stop; + __u32 right_width; + __u32 line_start; + __u32 line_stop; + __u32 height; + __u32 pixel_clk; + __u32 batch_size; + __u32 dsp_mode; + __u32 hbi_cnt; + __u32 reserved; + __u32 num_out_res; + struct cam_isp_out_port_info data[1]; }; /** @@ -329,38 +329,38 @@ struct cam_isp_in_port_info { * */ struct cam_isp_in_port_info_v2 { - uint32_t res_type; - uint32_t lane_type; - uint32_t lane_num; - uint32_t lane_cfg; - uint32_t vc[CAM_ISP_VC_DT_CFG]; - uint32_t dt[CAM_ISP_VC_DT_CFG]; - uint32_t num_valid_vc_dt; - uint32_t format; - uint32_t test_pattern; - uint32_t usage_type; - uint32_t left_start; - uint32_t left_stop; - uint32_t left_width; - uint32_t right_start; - uint32_t right_stop; - uint32_t right_width; - uint32_t line_start; - uint32_t line_stop; - uint32_t height; - uint32_t pixel_clk; - uint32_t batch_size; - uint32_t dsp_mode; - uint32_t hbi_cnt; - uint32_t cust_node; - uint32_t num_out_res; - uint32_t offline_mode; - uint32_t horizontal_bin; - uint32_t qcfa_bin; - uint32_t csid_res_1; - uint32_t csid_res_2; - uint32_t ife_res_1; - uint32_t ife_res_2; + __u32 res_type; + __u32 lane_type; + __u32 lane_num; + __u32 lane_cfg; + __u32 vc[CAM_ISP_VC_DT_CFG]; + __u32 dt[CAM_ISP_VC_DT_CFG]; + __u32 num_valid_vc_dt; + __u32 format; + __u32 test_pattern; + __u32 usage_type; + __u32 left_start; + __u32 left_stop; + __u32 left_width; + __u32 right_start; + __u32 right_stop; + __u32 right_width; + __u32 line_start; + __u32 line_stop; + __u32 height; + __u32 pixel_clk; + __u32 batch_size; + __u32 dsp_mode; + __u32 hbi_cnt; + __u32 cust_node; + __u32 num_out_res; + __u32 offline_mode; + __u32 horizontal_bin; + __u32 qcfa_bin; + __u32 csid_res_1; + __u32 csid_res_2; + __u32 ife_res_1; + __u32 ife_res_2; struct cam_isp_out_port_info_v2 data[1]; }; @@ -376,11 +376,11 @@ struct cam_isp_in_port_info_v2 { * */ struct cam_isp_resource { - uint32_t resource_id; - uint32_t length; - uint32_t handle_type; - uint32_t reserved; - uint64_t res_hdl; + __u32 resource_id; + __u32 length; + __u32 handle_type; + __u32 reserved; + __u64 res_hdl; }; /** @@ -398,12 +398,12 @@ struct cam_isp_resource { * @reserved: Reserved for alignment */ struct cam_isp_port_hfr_config { - uint32_t resource_type; - uint32_t subsample_pattern; - uint32_t subsample_period; - uint32_t framedrop_pattern; - uint32_t framedrop_period; - uint32_t reserved; + __u32 resource_type; + __u32 subsample_pattern; + __u32 subsample_period; + __u32 framedrop_pattern; + __u32 framedrop_period; + __u32 reserved; } __attribute__((packed)); /** @@ -414,8 +414,8 @@ struct cam_isp_port_hfr_config { * @port_hfr_config: HFR configuration for each IO port */ struct cam_isp_resource_hfr_config { - uint32_t num_ports; - uint32_t reserved; + __u32 num_ports; + __u32 reserved; struct cam_isp_port_hfr_config port_hfr_config[1]; } __attribute__((packed)); @@ -433,10 +433,10 @@ struct cam_isp_resource_hfr_config { * */ struct cam_isp_dual_split_params { - uint32_t split_point; - uint32_t right_padding; - uint32_t left_padding; - uint32_t reserved; + __u32 split_point; + __u32 right_padding; + __u32 left_padding; + __u32 reserved; }; /** @@ -453,10 +453,10 @@ struct cam_isp_dual_split_params { * */ struct cam_isp_dual_stripe_config { - uint32_t offset; - uint32_t width; - uint32_t tileconfig; - uint32_t port_id; + __u32 offset; + __u32 width; + __u32 tileconfig; + __u32 port_id; }; /** @@ -469,10 +469,10 @@ struct cam_isp_dual_stripe_config { * */ struct cam_isp_dual_config { - uint32_t num_ports; - uint32_t reserved; - struct cam_isp_dual_split_params split_params; - struct cam_isp_dual_stripe_config stripes[1]; + __u32 num_ports; + __u32 reserved; + struct cam_isp_dual_split_params split_params; + struct cam_isp_dual_stripe_config stripes[1]; } __attribute__((packed)); /** @@ -488,11 +488,11 @@ struct cam_isp_dual_config { * Hence pass the clock and let KMD decide. */ struct cam_isp_clock_config { - uint32_t usage_type; - uint32_t num_rdi; - uint64_t left_pix_hz; - uint64_t right_pix_hz; - uint64_t rdi_hz[1]; + __u32 usage_type; + __u32 num_rdi; + __u64 left_pix_hz; + __u64 right_pix_hz; + __u64 rdi_hz[1]; } __attribute__((packed)); /** @@ -501,7 +501,7 @@ struct cam_isp_clock_config { * @csid_clock CSID clock */ struct cam_isp_csid_clock_config { - uint64_t csid_clock; + __u64 csid_clock; } __attribute__((packed)); /** @@ -510,7 +510,7 @@ struct cam_isp_csid_clock_config { * @csid_binning CSID binning */ struct cam_isp_csid_qcfa_config { - uint32_t csid_binning; + __u32 csid_binning; } __attribute__((packed)); /** @@ -522,10 +522,10 @@ struct cam_isp_csid_qcfa_config { * @ext_bw_bps: Bandwidth vote for path-to-DDR after CAMNOC */ struct cam_isp_bw_vote { - uint32_t resource_id; - uint32_t reserved; - uint64_t cam_bw_bps; - uint64_t ext_bw_bps; + __u32 resource_id; + __u32 reserved; + __u64 cam_bw_bps; + __u64 ext_bw_bps; } __attribute__((packed)); /** @@ -538,11 +538,11 @@ struct cam_isp_bw_vote { * @rdi_vote: RDI bandwidth requirements */ struct cam_isp_bw_config { - uint32_t usage_type; - uint32_t num_rdi; - struct cam_isp_bw_vote left_pix_vote; - struct cam_isp_bw_vote right_pix_vote; - struct cam_isp_bw_vote rdi_vote[1]; + __u32 usage_type; + __u32 num_rdi; + struct cam_isp_bw_vote left_pix_vote; + struct cam_isp_bw_vote right_pix_vote; + struct cam_isp_bw_vote rdi_vote[1]; } __attribute__((packed)); /** @@ -553,9 +553,9 @@ struct cam_isp_bw_config { * @axi_path Per path vote info */ struct cam_isp_bw_config_v2 { - uint32_t usage_type; - uint32_t num_paths; - struct cam_axi_per_path_bw_vote axi_path[1]; + __u32 usage_type; + __u32 num_paths; + struct cam_axi_per_path_bw_vote axi_path[1]; } __attribute__((packed)); /** @@ -580,21 +580,21 @@ struct cam_isp_bw_config_v2 { * @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; + __u64 version; + __u32 min_vbi; + __u32 fs_mode; + __u32 fs_line_sync_en; + __u32 hbi_count; + __u32 fs_sync_enable; + __u32 go_cmd_sel; + __u32 client_enable; + __u32 source_addr; + __u32 width; + __u32 height; + __u32 stride; + __u32 format; + __u32 unpacker_cfg; + __u32 latency_buf_size; } __attribute__((packed)); /** @@ -614,18 +614,18 @@ struct cam_fe_config { * @reserved: Reserved */ struct cam_isp_core_config { - uint32_t version; - uint32_t vid_ds16_r2pd; - uint32_t vid_ds4_r2pd; - uint32_t disp_ds16_r2pd; - uint32_t disp_ds4_r2pd; - uint32_t dsp_streaming_tap_point; - uint32_t ihist_src_sel; - uint32_t hdr_be_src_sel; - uint32_t hdr_bhist_src_sel; - uint32_t input_mux_sel_pdaf; - uint32_t input_mux_sel_pp; - uint32_t reserved; + __u32 version; + __u32 vid_ds16_r2pd; + __u32 vid_ds4_r2pd; + __u32 disp_ds16_r2pd; + __u32 disp_ds4_r2pd; + __u32 dsp_streaming_tap_point; + __u32 ihist_src_sel; + __u32 hdr_be_src_sel; + __u32 hdr_bhist_src_sel; + __u32 input_mux_sel_pdaf; + __u32 input_mux_sel_pp; + __u32 reserved; } __attribute__((packed)); /** @@ -641,14 +641,14 @@ struct cam_isp_core_config { * @data : Start of data region */ struct cam_isp_acquire_hw_info { - uint16_t common_info_version; - uint16_t common_info_size; - uint32_t common_info_offset; - uint32_t num_inputs; - uint32_t input_info_version; - uint32_t input_info_size; - uint32_t input_info_offset; - uint64_t data; + __u16 common_info_version; + __u16 common_info_size; + __u32 common_info_offset; + __u32 num_inputs; + __u32 input_info_version; + __u32 input_info_size; + __u32 input_info_offset; + __u64 data; }; /** @@ -673,18 +673,18 @@ struct cam_isp_acquire_hw_info { * @reserved_4 : Reserved field for Write master config */ struct cam_isp_vfe_wm_config { - uint32_t port_type; - uint32_t wm_mode; - uint32_t h_init; - uint32_t height; - uint32_t width; - uint32_t virtual_frame_en; - uint32_t stride; - uint32_t offset; - uint32_t reserved_1; - uint32_t reserved_2; - uint32_t reserved_3; - uint32_t reserved_4; + __u32 port_type; + __u32 wm_mode; + __u32 h_init; + __u32 height; + __u32 width; + __u32 virtual_frame_en; + __u32 stride; + __u32 offset; + __u32 reserved_1; + __u32 reserved_2; + __u32 reserved_3; + __u32 reserved_4; }; /** @@ -695,9 +695,9 @@ struct cam_isp_vfe_wm_config { * @wm_config : VFE out config */ struct cam_isp_vfe_out_config { - uint32_t num_ports; - uint32_t reserved; - struct cam_isp_vfe_wm_config wm_config[1]; + __u32 num_ports; + __u32 reserved; + struct cam_isp_vfe_wm_config wm_config[1]; }; /** @@ -706,7 +706,7 @@ struct cam_isp_vfe_out_config { * @is_epd_sensor : flag to check if epd supported */ struct cam_isp_csid_epd_config { - uint32_t is_epd_supported; + __u32 is_epd_supported; }; #define CAM_ISP_ACQUIRE_COMMON_VER0 0x1000 diff --git a/include/uapi/camera/media/cam_jpeg.h b/include/uapi/camera/media/cam_jpeg.h index fd0ed2a2cfdb..a1e63a3e2bc8 100644 --- a/include/uapi/camera/media/cam_jpeg.h +++ b/include/uapi/camera/media/cam_jpeg.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_JPEG_H__ #define __UAPI_CAM_JPEG_H__ -#include +#include /* enc, dma, cdm(enc/dma) are used in querycap */ #define CAM_JPEG_DEV_TYPE_ENC 0 @@ -53,8 +53,8 @@ * @hw_ver: Major, minor and incr values of a device version */ struct cam_jpeg_dev_ver { - uint32_t size; - uint32_t dev_type; + __u32 size; + __u32 dev_type; struct cam_hw_version hw_ver; }; @@ -71,8 +71,8 @@ struct cam_jpeg_dev_ver { struct cam_jpeg_query_cap_cmd { struct cam_iommu_handle dev_iommu_handle; struct cam_iommu_handle cdm_iommu_handle; - uint32_t num_enc; - uint32_t num_dma; + __u32 num_enc; + __u32 num_dma; struct cam_jpeg_dev_ver dev_ver[CAM_JPEG_DEV_TYPE_MAX]; }; @@ -85,10 +85,10 @@ struct cam_jpeg_query_cap_cmd { * @fps: Fps */ struct cam_jpeg_res_info { - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t fps; + __u32 format; + __u32 width; + __u32 height; + __u32 fps; }; /** @@ -100,8 +100,8 @@ struct cam_jpeg_res_info { * @in_res: Iut resource info */ struct cam_jpeg_acquire_dev_info { - uint32_t dev_type; - uint32_t reserved; + __u32 dev_type; + __u32 reserved; struct cam_jpeg_res_info in_res; struct cam_jpeg_res_info out_res; }; @@ -115,8 +115,8 @@ struct cam_jpeg_acquire_dev_info { * bytes */ struct cam_jpeg_config_inout_param_info { - int32_t clk_index; - int32_t output_size; + __s32 clk_index; + __s32 output_size; }; #endif /* __UAPI_CAM_JPEG_H__ */ diff --git a/include/uapi/camera/media/cam_lrme.h b/include/uapi/camera/media/cam_lrme.h index e3bd9449f7ef..0ee5225f2fbb 100644 --- a/include/uapi/camera/media/cam_lrme.h +++ b/include/uapi/camera/media/cam_lrme.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_LRME_H__ #define __UAPI_CAM_LRME_H__ -#include +#include /* LRME Resource Types */ @@ -27,9 +27,9 @@ enum CAM_LRME_IO_TYPE { struct cam_lrme_hw_version { - uint32_t gen; - uint32_t rev; - uint32_t step; + __u32 gen; + __u32 rev; + __u32 step; }; struct cam_lrme_dev_cap { @@ -52,14 +52,14 @@ struct cam_lrme_dev_cap { struct cam_lrme_query_cap_cmd { struct cam_iommu_handle device_iommu; struct cam_iommu_handle cdm_iommu; - uint32_t num_devices; + __u32 num_devices; struct cam_lrme_dev_cap dev_caps[CAM_LRME_DEV_MAX]; }; struct cam_lrme_soc_info { - uint64_t clock_rate; - uint64_t bandwidth; - uint64_t reserved[4]; + __u64 clock_rate; + __u64 bandwidth; + __u64 reserved[4]; }; struct cam_lrme_acquire_args { diff --git a/include/uapi/camera/media/cam_ope.h b/include/uapi/camera/media/cam_ope.h index 7b4ed57b778e..9ddf3c8004a6 100644 --- a/include/uapi/camera/media/cam_ope.h +++ b/include/uapi/camera/media/cam_ope.h @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_OPE_H__ #define __UAPI_OPE_H__ -#include "cam_defs.h" -#include "cam_cpas.h" +#include +#include #define OPE_DEV_NAME_SIZE 128 @@ -88,12 +88,12 @@ * */ struct ope_stripe_info { - uint32_t offset; - uint32_t x_init; - uint32_t stripe_location; - uint32_t width; - uint32_t disable_bus; - uint32_t reserved; + __u32 offset; + __u32 x_init; + __u32 stripe_location; + __u32 width; + __u32 disable_bus; + __u32 reserved; }; /** @@ -115,18 +115,18 @@ struct ope_stripe_info { * */ struct ope_io_buf_info { - uint32_t direction; - uint32_t resource_type; - uint32_t num_planes; - uint32_t reserved; - uint32_t num_stripes[OPE_MAX_PLANES]; - uint32_t mem_handle[OPE_MAX_PLANES]; - uint32_t plane_offset[OPE_MAX_PLANES]; - uint32_t length[OPE_MAX_PLANES]; - uint32_t plane_stride[OPE_MAX_PLANES]; - uint32_t height[OPE_MAX_PLANES]; - uint32_t format; - uint32_t fence; + __u32 direction; + __u32 resource_type; + __u32 num_planes; + __u32 reserved; + __u32 num_stripes[OPE_MAX_PLANES]; + __u32 mem_handle[OPE_MAX_PLANES]; + __u32 plane_offset[OPE_MAX_PLANES]; + __u32 length[OPE_MAX_PLANES]; + __u32 plane_stride[OPE_MAX_PLANES]; + __u32 height[OPE_MAX_PLANES]; + __u32 format; + __u32 fence; struct ope_stripe_info stripe_info[OPE_MAX_PLANES][OPE_MAX_STRIPES]; }; @@ -139,8 +139,8 @@ struct ope_io_buf_info { * */ struct ope_frame_set { - uint32_t num_io_bufs; - uint32_t reserved; + __u32 num_io_bufs; + __u32 reserved; struct ope_io_buf_info io_buf[OPE_MAX_IO_BUFS]; }; @@ -161,17 +161,17 @@ struct ope_frame_set { */ struct ope_cmd_buf_info { - uint32_t mem_handle; - uint32_t offset; - uint32_t size; - uint32_t length; - uint32_t cmd_buf_scope; - uint32_t type; - uint32_t cmd_buf_usage; - uint32_t cmd_buf_buffered; - uint32_t stripe_idx; - uint32_t cmd_buf_pass_idx; - uint32_t prefetch_disable; + __u32 mem_handle; + __u32 offset; + __u32 size; + __u32 length; + __u32 cmd_buf_scope; + __u32 type; + __u32 cmd_buf_usage; + __u32 cmd_buf_buffered; + __u32 stripe_idx; + __u32 cmd_buf_pass_idx; + __u32 prefetch_disable; }; /** @@ -184,8 +184,8 @@ struct ope_cmd_buf_info { * */ struct ope_frame_process { - uint32_t num_cmd_bufs[OPE_MAX_BATCH_SIZE]; - uint32_t batch_size; + __u32 num_cmd_bufs[OPE_MAX_BATCH_SIZE]; + __u32 batch_size; struct ope_cmd_buf_info cmd_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_CMD_BUFS]; struct ope_frame_set frame_set[OPE_MAX_BATCH_SIZE]; }; @@ -201,11 +201,11 @@ struct ope_frame_process { * */ struct ope_clk_bw_request_v2 { - uint64_t budget_ns; - uint32_t frame_cycles; - uint32_t rt_flag; - uint32_t reserved; - uint32_t num_paths; + __u64 budget_ns; + __u32 frame_cycles; + __u32 rt_flag; + __u32 reserved; + __u32 num_paths; struct cam_axi_per_path_bw_vote axi_path[1]; }; @@ -221,8 +221,8 @@ struct ope_clk_bw_request_v2 { * */ struct ope_hw_ver { - uint32_t hw_type; - uint32_t reserved; + __u32 hw_type; + __u32 reserved; struct cam_hw_version hw_ver; }; @@ -238,8 +238,8 @@ struct ope_hw_ver { struct ope_query_cap_cmd { struct cam_iommu_handle dev_iommu_handle; struct cam_iommu_handle cdm_iommu_handle; - uint32_t num_ope; - uint32_t reserved; + __u32 num_ope; + __u32 reserved; struct ope_hw_ver hw_ver[OPE_DEV_TYPE_MAX]; }; @@ -259,16 +259,16 @@ struct ope_query_cap_cmd { * */ struct ope_out_res_info { - uint32_t res_id; - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t alignment; - uint32_t packer_format; - uint32_t subsample_period; - uint32_t subsample_pattern; - uint32_t pixel_pattern; - uint32_t reserved; + __u32 res_id; + __u32 format; + __u32 width; + __u32 height; + __u32 alignment; + __u32 packer_format; + __u32 subsample_period; + __u32 subsample_pattern; + __u32 pixel_pattern; + __u32 reserved; }; /** @@ -287,16 +287,16 @@ struct ope_out_res_info { * */ struct ope_in_res_info { - uint32_t res_id; - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t pixel_pattern; - uint32_t alignment; - uint32_t unpacker_format; - uint32_t max_stripe_size; - uint32_t fps; - uint32_t reserved; + __u32 res_id; + __u32 format; + __u32 width; + __u32 height; + __u32 pixel_pattern; + __u32 alignment; + __u32 unpacker_format; + __u32 max_stripe_size; + __u32 fps; + __u32 reserved; }; /** @@ -317,17 +317,17 @@ struct ope_in_res_info { * */ struct ope_acquire_dev_info { - uint32_t hw_type; - uint32_t dev_type; - char dev_name[OPE_DEV_NAME_SIZE]; - uint32_t nrt_stripes_for_arb; - uint32_t secure_mode; - uint32_t batch_size; - uint32_t num_in_res; - struct ope_in_res_info in_res[OPE_IN_RES_MAX]; - uint32_t num_out_res; - uint32_t reserved; - struct ope_out_res_info out_res[OPE_OUT_RES_MAX]; + __u32 hw_type; + __u32 dev_type; + char dev_name[OPE_DEV_NAME_SIZE]; + __u32 nrt_stripes_for_arb; + __u32 secure_mode; + __u32 batch_size; + __u32 num_in_res; + struct ope_in_res_info in_res[OPE_IN_RES_MAX]; + __u32 num_out_res; + __u32 reserved; + struct ope_out_res_info out_res[OPE_OUT_RES_MAX]; } __attribute__((__packed__)); #endif /* __UAPI_OPE_H__ */ diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index d876f21575bb..80a52fb01504 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #define CAM_REQ_MGR_VNODE_NAME "cam-req-mgr-devnode" @@ -96,13 +96,13 @@ * @tv_usec: timestamp in micro seconds */ struct cam_req_mgr_event_data { - int32_t session_hdl; - int32_t link_hdl; - int32_t frame_id; - int32_t reserved; - int64_t req_id; - uint64_t tv_sec; - uint64_t tv_usec; + __s32 session_hdl; + __s32 link_hdl; + __s32 frame_id; + __s32 reserved; + __s64 req_id; + __u64 tv_sec; + __u64 tv_usec; }; /** @@ -112,8 +112,8 @@ struct cam_req_mgr_event_data { * @opcode2: CAM_REQ_MGR_DESTROY_SESSION */ struct cam_req_mgr_session_info { - int32_t session_hdl; - int32_t reserved; + __s32 session_hdl; + __s32 reserved; }; /** @@ -125,21 +125,21 @@ struct cam_req_mgr_session_info { * @opcode: CAM_REQ_MGR_LINK */ struct cam_req_mgr_link_info { - int32_t session_hdl; - uint32_t num_devices; - int32_t dev_hdls[CAM_REQ_MGR_MAX_HANDLES]; - int32_t link_hdl; + __s32 session_hdl; + __u32 num_devices; + __s32 dev_hdls[CAM_REQ_MGR_MAX_HANDLES]; + __s32 link_hdl; }; struct cam_req_mgr_link_info_v2 { - int32_t session_hdl; - uint32_t num_devices; - int32_t dev_hdls[CAM_REQ_MGR_MAX_HANDLES_V2]; - int32_t link_hdl; + __s32 session_hdl; + __u32 num_devices; + __s32 dev_hdls[CAM_REQ_MGR_MAX_HANDLES_V2]; + __s32 link_hdl; }; struct cam_req_mgr_ver_info { - uint32_t version; + __u32 version; union { struct cam_req_mgr_link_info link_info_v1; struct cam_req_mgr_link_info_v2 link_info_v2; @@ -152,8 +152,8 @@ struct cam_req_mgr_ver_info { * @opcode: CAM_REQ_MGR_UNLINK */ struct cam_req_mgr_unlink_info { - int32_t session_hdl; - int32_t link_hdl; + __s32 session_hdl; + __s32 link_hdl; }; /** @@ -172,11 +172,11 @@ struct cam_req_mgr_unlink_info { * @opcode: CAM_REQ_MGR_FLUSH_REQ */ struct cam_req_mgr_flush_info { - int32_t session_hdl; - int32_t link_hdl; - uint32_t flush_type; - uint32_t reserved; - int64_t req_id; + __s32 session_hdl; + __s32 link_hdl; + __u32 flush_type; + __u32 reserved; + __s64 req_id; }; /** struct cam_req_mgr_sched_info @@ -194,13 +194,13 @@ struct cam_req_mgr_flush_info { * @req_id: Input Param - Request Id from which all requests will be flushed */ struct cam_req_mgr_sched_request { - int32_t session_hdl; - int32_t link_hdl; - int32_t bubble_enable; - int32_t sync_mode; - int32_t additional_timeout; - int32_t reserved; - int64_t req_id; + __s32 session_hdl; + __s32 link_hdl; + __s32 bubble_enable; + __s32 sync_mode; + __s32 additional_timeout; + __s32 reserved; + __s64 req_id; }; /** @@ -219,12 +219,12 @@ struct cam_req_mgr_sched_request { * @opcode: CAM_REQ_MGR_SYNC_MODE */ struct cam_req_mgr_sync_mode { - int32_t session_hdl; - int32_t sync_mode; - int32_t num_links; - int32_t link_hdls[MAX_LINKS_PER_SESSION]; - int32_t master_link_hdl; - int32_t reserved; + __s32 session_hdl; + __s32 sync_mode; + __s32 num_links; + __s32 link_hdls[MAX_LINKS_PER_SESSION]; + __s32 master_link_hdl; + __s32 reserved; }; /** @@ -238,11 +238,11 @@ struct cam_req_mgr_sync_mode { * @opcode: CAM_REQ_MGR_LINK_CONTROL */ struct cam_req_mgr_link_control { - int32_t ops; - int32_t session_hdl; - int32_t num_links; - int32_t reserved; - int32_t link_hdls[MAX_LINKS_PER_SESSION]; + __s32 ops; + __s32 session_hdl; + __s32 num_links; + __s32 reserved; + __s32 link_hdls[MAX_LINKS_PER_SESSION]; }; /** @@ -335,9 +335,9 @@ struct cam_req_mgr_link_control { * @vaddr: virtual address pointer */ struct cam_mem_alloc_out_params { - uint32_t buf_handle; - int32_t fd; - uint64_t vaddr; + __u32 buf_handle; + __s32 fd; + __u64 vaddr; }; /** @@ -347,9 +347,9 @@ struct cam_mem_alloc_out_params { * @vaddr: virtual address pointer */ struct cam_mem_map_out_params { - uint32_t buf_handle; - uint32_t reserved; - uint64_t vaddr; + __u32 buf_handle; + __u32 reserved; + __u64 vaddr; }; /** @@ -363,11 +363,11 @@ struct cam_mem_map_out_params { */ /* CAM_REQ_MGR_ALLOC_BUF */ struct cam_mem_mgr_alloc_cmd { - uint64_t len; - uint64_t align; - int32_t mmu_hdls[CAM_MEM_MMU_MAX_HANDLE]; - uint32_t num_hdl; - uint32_t flags; + __u64 len; + __u64 align; + __s32 mmu_hdls[CAM_MEM_MMU_MAX_HANDLE]; + __u32 num_hdl; + __u32 flags; struct cam_mem_alloc_out_params out; }; @@ -383,11 +383,11 @@ struct cam_mem_mgr_alloc_cmd { /* CAM_REQ_MGR_MAP_BUF */ struct cam_mem_mgr_map_cmd { - int32_t mmu_hdls[CAM_MEM_MMU_MAX_HANDLE]; - uint32_t num_hdl; - uint32_t flags; - int32_t fd; - uint32_t reserved; + __s32 mmu_hdls[CAM_MEM_MMU_MAX_HANDLE]; + __u32 num_hdl; + __u32 flags; + __s32 fd; + __u32 reserved; struct cam_mem_map_out_params out; }; @@ -398,8 +398,8 @@ struct cam_mem_mgr_map_cmd { */ /* CAM_REQ_MGR_RELEASE_BUF */ struct cam_mem_mgr_release_cmd { - int32_t buf_handle; - uint32_t reserved; + __s32 buf_handle; + __u32 reserved; }; /** @@ -409,8 +409,8 @@ struct cam_mem_mgr_release_cmd { */ /* CAM_REQ_MGR_CACHE_OPS */ struct cam_mem_cache_ops_cmd { - int32_t buf_handle; - uint32_t mem_cache_ops; + __s32 buf_handle; + __u32 mem_cache_ops; }; /** @@ -436,11 +436,11 @@ struct cam_mem_cache_ops_cmd { * @resource_size: size of the resource */ struct cam_req_mgr_error_msg { - uint32_t error_type; - uint32_t request_id; - int32_t device_hdl; - int32_t link_hdl; - uint64_t resource_size; + __u32 error_type; + __u32 request_id; + __s32 device_hdl; + __s32 link_hdl; + __u64 resource_size; }; /** @@ -455,13 +455,13 @@ struct cam_req_mgr_error_msg { * @reserved: reserved */ struct cam_req_mgr_frame_msg { - uint64_t request_id; - uint64_t frame_id; - uint64_t timestamp; - int32_t link_hdl; - uint32_t sof_status; - uint32_t frame_id_meta; - uint32_t reserved; + __u64 request_id; + __u64 frame_id; + __u64 timestamp; + __s32 link_hdl; + __u32 sof_status; + __u32 frame_id_meta; + __u32 reserved; }; /** @@ -474,12 +474,12 @@ struct cam_req_mgr_frame_msg { * @custom_data: custom data */ struct cam_req_mgr_custom_msg { - uint32_t custom_type; - uint64_t request_id; - uint64_t frame_id; - uint64_t timestamp; - int32_t link_hdl; - uint64_t custom_data; + __u32 custom_type; + __u64 request_id; + __u64 frame_id; + __u64 timestamp; + __s32 link_hdl; + __u64 custom_data; }; /** @@ -489,8 +489,8 @@ struct cam_req_mgr_custom_msg { * @u: union which can either be error/frame/custom message */ struct cam_req_mgr_message { - int32_t session_hdl; - int32_t reserved; + __s32 session_hdl; + __s32 reserved; union { struct cam_req_mgr_error_msg err_msg; struct cam_req_mgr_frame_msg frame_msg; diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index 9732502f074c..bc9498ea6101 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -8,7 +8,7 @@ #include #include -#include +#include #define CAM_SENSOR_PROBE_CMD (CAM_COMMON_OPCODE_MAX + 1) #define CAM_FLASH_MAX_LED_TRIGGERS 2 @@ -30,16 +30,16 @@ * */ struct cam_sensor_query_cap { - uint32_t slot_info; - uint32_t secure_camera; - uint32_t pos_pitch; - uint32_t pos_roll; - uint32_t pos_yaw; - uint32_t actuator_slot_id; - uint32_t eeprom_slot_id; - uint32_t ois_slot_id; - uint32_t flash_slot_id; - uint32_t csiphy_slot_id; + __u32 slot_info; + __u32 secure_camera; + __u32 pos_pitch; + __u32 pos_roll; + __u32 pos_yaw; + __u32 actuator_slot_id; + __u32 eeprom_slot_id; + __u32 ois_slot_id; + __u32 flash_slot_id; + __u32 csiphy_slot_id; } __attribute__((packed)); /** @@ -52,10 +52,10 @@ struct cam_sensor_query_cap { * @reserved */ struct cam_csiphy_query_cap { - uint32_t slot_info; - uint32_t version; - uint32_t clk_lane; - uint32_t reserved; + __u32 slot_info; + __u32 version; + __u32 clk_lane; + __u32 reserved; } __attribute__((packed)); /** @@ -65,8 +65,8 @@ struct cam_csiphy_query_cap { * @reserved */ struct cam_actuator_query_cap { - uint32_t slot_info; - uint32_t reserved; + __u32 slot_info; + __u32 reserved; } __attribute__((packed)); /** @@ -76,9 +76,9 @@ struct cam_actuator_query_cap { * @eeprom_kernel_probe : Indicates about the kernel or userspace probe */ struct cam_eeprom_query_cap_t { - uint32_t slot_info; - uint16_t eeprom_kernel_probe; - uint16_t is_multimodule_mode; + __u32 slot_info; + __u16 eeprom_kernel_probe; + __u16 is_multimodule_mode; } __attribute__((packed)); /** @@ -87,8 +87,8 @@ struct cam_eeprom_query_cap_t { * @slot_info : Indicates about the slotId or cell Index */ struct cam_ois_query_cap_t { - uint32_t slot_info; - uint16_t reserved; + __u32 slot_info; + __u16 reserved; } __attribute__((packed)); /** @@ -99,10 +99,10 @@ struct cam_ois_query_cap_t { * @cmd_type : Explains type of command */ struct cam_cmd_i2c_info { - uint32_t slave_addr; - uint8_t i2c_freq_mode; - uint8_t cmd_type; - uint16_t reserved; + __u32 slave_addr; + __u8 i2c_freq_mode; + __u8 cmd_type; + __u16 reserved; } __attribute__((packed)); /** @@ -114,10 +114,10 @@ struct cam_cmd_i2c_info { * @memory : OIS memory */ struct cam_ois_opcode { - uint32_t prog; - uint32_t coeff; - uint32_t pheripheral; - uint32_t memory; + __u32 prog; + __u32 coeff; + __u32 pheripheral; + __u32 memory; } __attribute__((packed)); /** @@ -132,11 +132,11 @@ struct cam_ois_opcode { * @opcode : opcode */ struct cam_cmd_ois_info { - uint32_t slave_addr; - uint8_t i2c_freq_mode; - uint8_t cmd_type; - uint8_t ois_fw_flag; - uint8_t is_ois_calib; + __u32 slave_addr; + __u8 i2c_freq_mode; + __u8 cmd_type; + __u8 ois_fw_flag; + __u8 is_ois_calib; char ois_name[MAX_OIS_NAME_SIZE]; struct cam_ois_opcode opcode; } __attribute__((packed)); @@ -156,15 +156,15 @@ struct cam_cmd_ois_info { * @reserved */ struct cam_cmd_probe { - uint8_t data_type; - uint8_t addr_type; - uint8_t op_code; - uint8_t cmd_type; - uint32_t reg_addr; - uint32_t expected_data; - uint32_t data_mask; - uint16_t camera_id; - uint16_t reserved; + __u8 data_type; + __u8 addr_type; + __u8 op_code; + __u8 cmd_type; + __u32 reg_addr; + __u32 expected_data; + __u32 data_mask; + __u16 camera_id; + __u16 reserved; } __attribute__((packed)); /** @@ -177,10 +177,10 @@ struct cam_cmd_probe { * */ struct cam_power_settings { - uint16_t power_seq_type; - uint16_t reserved; - uint32_t config_val_low; - uint32_t config_val_high; + __u16 power_seq_type; + __u16 reserved; + __u32 config_val_low; + __u32 config_val_high; } __attribute__((packed)); /** @@ -192,10 +192,10 @@ struct cam_power_settings { * @power_settings : Contains power setting info */ struct cam_cmd_power { - uint32_t count; - uint8_t reserved; - uint8_t cmd_type; - uint16_t more_reserved; + __u32 count; + __u8 reserved; + __u8 cmd_type; + __u16 more_reserved; struct cam_power_settings power_settings[1]; } __attribute__((packed)); @@ -210,11 +210,11 @@ struct cam_cmd_power { * @ reserved */ struct i2c_rdwr_header { - uint32_t count; - uint8_t op_code; - uint8_t cmd_type; - uint8_t data_type; - uint8_t addr_type; + __u32 count; + __u8 op_code; + __u8 cmd_type; + __u8 data_type; + __u8 addr_type; } __attribute__((packed)); /** @@ -225,8 +225,8 @@ struct i2c_rdwr_header { * */ struct i2c_random_wr_payload { - uint32_t reg_addr; - uint32_t reg_data; + __u32 reg_addr; + __u32 reg_data; } __attribute__((packed)); /** @@ -245,8 +245,8 @@ struct cam_cmd_i2c_random_wr { * @ reserved */ struct cam_cmd_read { - uint32_t reg_data; - uint32_t reserved; + __u32 reg_data; + __u32 reserved; } __attribute__((packed)); /** @@ -256,9 +256,9 @@ struct cam_cmd_read { * @ data_read : I2C read command */ struct cam_cmd_i2c_continuous_wr { - struct i2c_rdwr_header header; - uint32_t reg_addr; - struct cam_cmd_read data_read[1]; + struct i2c_rdwr_header header; + __u32 reg_addr; + struct cam_cmd_read data_read[1]; } __attribute__((packed)); /** @@ -267,8 +267,8 @@ struct cam_cmd_i2c_continuous_wr { * @ data_read : I2C read command */ struct cam_cmd_i2c_random_rd { - struct i2c_rdwr_header header; - struct cam_cmd_read data_read[1]; + struct i2c_rdwr_header header; + struct cam_cmd_read data_read[1]; } __attribute__((packed)); /** @@ -278,8 +278,8 @@ struct cam_cmd_i2c_random_rd { * */ struct cam_cmd_i2c_continuous_rd { - struct i2c_rdwr_header header; - uint32_t reg_addr; + struct i2c_rdwr_header header; + __u32 reg_addr; } __attribute__((packed)); /** @@ -298,15 +298,15 @@ struct cam_cmd_i2c_continuous_rd { * */ struct cam_cmd_conditional_wait { - uint8_t data_type; - uint8_t addr_type; - uint16_t reserved; - uint8_t op_code; - uint8_t cmd_type; - uint16_t timeout; - uint32_t reg_addr; - uint32_t reg_data; - uint32_t data_mask; + __u8 data_type; + __u8 addr_type; + __u16 reserved; + __u8 op_code; + __u8 cmd_type; + __u16 timeout; + __u32 reg_addr; + __u32 reg_data; + __u32 data_mask; } __attribute__((packed)); /** @@ -316,11 +316,11 @@ struct cam_cmd_conditional_wait { * @cmd_type : Explains type of command */ struct cam_cmd_unconditional_wait { - int16_t delay; - int16_t reserved; - uint8_t op_code; - uint8_t cmd_type; - uint16_t reserved1; + __s16 delay; + __s16 reserved; + __u8 op_code; + __u8 cmd_type; + __u16 reserved1; } __attribute__((packed)); /** @@ -337,14 +337,14 @@ struct cam_cmd_unconditional_wait { * */ struct cam_csiphy_info { - uint16_t lane_mask; - uint16_t lane_assign; - uint8_t csiphy_3phase; - uint8_t combo_mode; - uint8_t lane_cnt; - uint8_t secure_mode; - uint64_t settle_time; - uint64_t data_rate; + __u16 lane_mask; + __u16 lane_assign; + __u8 csiphy_3phase; + __u8 combo_mode; + __u8 lane_cnt; + __u8 secure_mode; + __u64 settle_time; + __u64 data_rate; } __attribute__((packed)); /** @@ -355,8 +355,8 @@ struct cam_csiphy_info { * */ struct cam_csiphy_acquire_dev_info { - uint32_t combo_mode; - uint32_t reserved; + __u32 combo_mode; + __u32 reserved; } __attribute__((packed)); /** @@ -370,11 +370,11 @@ struct cam_csiphy_acquire_dev_info { * */ struct cam_sensor_acquire_dev { - uint32_t session_handle; - uint32_t device_handle; - uint32_t handle_type; - uint32_t reserved; - uint64_t info_handle; + __u32 session_handle; + __u32 device_handle; + __u32 handle_type; + __u32 reserved; + __u64 info_handle; } __attribute__((packed)); /** @@ -387,11 +387,11 @@ struct cam_sensor_acquire_dev { * */ struct cam_sensor_streamon_dev { - uint32_t session_handle; - uint32_t device_handle; - uint32_t handle_type; - uint32_t reserved; - uint64_t info_handle; + __u32 session_handle; + __u32 device_handle; + __u32 handle_type; + __u32 reserved; + __u64 info_handle; } __attribute__((packed)); /** @@ -401,10 +401,10 @@ struct cam_sensor_streamon_dev { * @cmd_type : command buffer type */ struct cam_flash_init { - uint32_t flash_type; - uint8_t reserved; - uint8_t cmd_type; - uint16_t reserved1; + __u32 flash_type; + __u8 reserved; + __u8 cmd_type; + __u16 reserved1; } __attribute__((packed)); /** @@ -422,13 +422,13 @@ struct cam_flash_init { * */ struct cam_flash_set_rer { - uint32_t count; - uint8_t opcode; - uint8_t cmd_type; - uint16_t num_iteration; - uint32_t led_on_delay_ms; - uint32_t led_off_delay_ms; - uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; + __u32 count; + __u8 opcode; + __u8 cmd_type; + __u16 num_iteration; + __u32 led_on_delay_ms; + __u32 led_off_delay_ms; + __u32 led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; } __attribute__((packed)); /** @@ -445,12 +445,12 @@ struct cam_flash_set_rer { * */ struct cam_flash_set_on_off { - uint32_t count; - uint8_t opcode; - uint8_t cmd_type; - uint16_t reserved; - uint32_t led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; - uint64_t time_on_duration_ns; + __u32 count; + __u8 opcode; + __u8 cmd_type; + __u16 reserved; + __u32 led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS]; + __u64 time_on_duration_ns; } __attribute__((packed)); /** @@ -463,10 +463,10 @@ struct cam_flash_set_on_off { * */ struct cam_flash_query_curr { - uint16_t reserved; - uint8_t opcode; - uint8_t cmd_type; - uint32_t query_current_ma; + __u16 reserved; + __u8 opcode; + __u8 cmd_type; + __u32 query_current_ma; } __attribute__ ((packed)); /** @@ -479,10 +479,10 @@ struct cam_flash_query_curr { * */ struct cam_flash_query_cap_info { - uint32_t slot_info; - uint32_t max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS]; - uint32_t max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; - uint32_t max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; + __u32 slot_info; + __u32 max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS]; + __u32 max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; + __u32 max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; } __attribute__ ((packed)); #endif diff --git a/include/uapi/camera/media/cam_sync.h b/include/uapi/camera/media/cam_sync.h index d1ab63fd4294..0c97982c983e 100644 --- a/include/uapi/camera/media/cam_sync.h +++ b/include/uapi/camera/media/cam_sync.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_SYNC_H__ @@ -43,8 +43,8 @@ * @status: Status of the object */ struct cam_sync_ev_header { - int32_t sync_obj; - int32_t status; + __s32 sync_obj; + __s32 status; }; /** @@ -54,8 +54,8 @@ struct cam_sync_ev_header { * @sync_obj: Sync object returned after creation in kernel */ struct cam_sync_info { - char name[64]; - int32_t sync_obj; + char name[64]; + __s32 sync_obj; }; /** @@ -65,8 +65,8 @@ struct cam_sync_info { * @sync_state: State of the sync object to which it should be signaled */ struct cam_sync_signal { - int32_t sync_obj; - uint32_t sync_state; + __s32 sync_obj; + __u32 sync_state; }; /** @@ -78,8 +78,8 @@ struct cam_sync_signal { */ struct cam_sync_merge { __u64 sync_objs; - uint32_t num_objs; - int32_t merged; + __u32 num_objs; + __s32 merged; }; /** @@ -90,8 +90,8 @@ struct cam_sync_merge { * @payload: Pointer to user payload */ struct cam_sync_userpayload_info { - int32_t sync_obj; - uint32_t reserved; + __s32 sync_obj; + __u32 reserved; __u64 payload[CAM_SYNC_USER_PAYLOAD_SIZE]; }; @@ -103,8 +103,8 @@ struct cam_sync_userpayload_info { * @timeout_ms: Timeout in milliseconds */ struct cam_sync_wait { - int32_t sync_obj; - uint32_t reserved; + __s32 sync_obj; + __u32 reserved; uint64_t timeout_ms; }; diff --git a/include/uapi/camera/media/cam_tfe.h b/include/uapi/camera/media/cam_tfe.h index 9055f7fbe55c..26573c33a40d 100644 --- a/include/uapi/camera/media/cam_tfe.h +++ b/include/uapi/camera/media/cam_tfe.h @@ -1,14 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_TFE_H__ #define __UAPI_CAM_TFE_H__ -#include "cam_defs.h" -#include "cam_isp_tfe.h" -#include "cam_cpas.h" +#include +#include +#include /* ISP TFE driver name */ @@ -93,8 +93,8 @@ * */ struct cam_isp_tfe_dev_cap_info { - uint32_t hw_type; - uint32_t reserved; + __u32 hw_type; + __u32 reserved; struct cam_hw_version hw_version; }; @@ -110,11 +110,11 @@ struct cam_isp_tfe_dev_cap_info { * */ struct cam_isp_tfe_query_cap_cmd { - struct cam_iommu_handle device_iommu; - struct cam_iommu_handle cdm_iommu; - int32_t num_dev; - uint32_t reserved; - struct cam_isp_tfe_dev_cap_info dev_caps[CAM_ISP_TFE_HW_MAX]; + struct cam_iommu_handle device_iommu; + struct cam_iommu_handle cdm_iommu; + __s32 num_dev; + __u32 reserved; + struct cam_isp_tfe_dev_cap_info dev_caps[CAM_ISP_TFE_HW_MAX]; }; /* Acquire Device */ @@ -135,15 +135,15 @@ struct cam_isp_tfe_query_cap_cmd { * */ struct cam_isp_tfe_out_port_info { - uint32_t res_id; - uint32_t format; - uint32_t width; - uint32_t height; - uint32_t stride; - uint32_t comp_grp_id; - uint32_t secure_mode; - uint32_t wm_mode; - uint32_t reserved; + __u32 res_id; + __u32 format; + __u32 width; + __u32 height; + __u32 stride; + __u32 comp_grp_id; + __u32 secure_mode; + __u32 wm_mode; + __u32 reserved; }; /** @@ -185,34 +185,34 @@ struct cam_isp_tfe_out_port_info { * */ struct cam_isp_tfe_in_port_info { - uint32_t res_id; - uint32_t lane_type; - uint32_t lane_num; - uint32_t lane_cfg; - uint32_t vc; - uint32_t dt; - uint32_t format; - uint32_t pix_pattern; - uint32_t usage_type; - uint32_t left_start; - uint32_t left_end; - uint32_t left_width; - uint32_t right_start; - uint32_t right_end; - uint32_t right_width; - uint32_t line_start; - uint32_t line_end; - uint32_t height; - uint32_t batch_size; - uint32_t dsp_mode; - uint32_t sensor_width; - uint32_t sensor_height; - uint32_t sensor_hbi; - uint32_t sensor_vbi; - uint32_t sensor_fps; - uint32_t init_frame_drop; - uint32_t num_out_res; - struct cam_isp_tfe_out_port_info data[1]; + __u32 res_id; + __u32 lane_type; + __u32 lane_num; + __u32 lane_cfg; + __u32 vc; + __u32 dt; + __u32 format; + __u32 pix_pattern; + __u32 usage_type; + __u32 left_start; + __u32 left_end; + __u32 left_width; + __u32 right_start; + __u32 right_end; + __u32 right_width; + __u32 line_start; + __u32 line_end; + __u32 height; + __u32 batch_size; + __u32 dsp_mode; + __u32 sensor_width; + __u32 sensor_height; + __u32 sensor_hbi; + __u32 sensor_vbi; + __u32 sensor_fps; + __u32 init_frame_drop; + __u32 num_out_res; + struct cam_isp_tfe_out_port_info data[1]; }; /** @@ -227,11 +227,11 @@ struct cam_isp_tfe_in_port_info { * */ struct cam_isp_tfe_resource { - uint32_t resource_id; - uint32_t length; - uint32_t handle_type; - uint32_t reserved; - uint64_t res_hdl; + __u32 resource_id; + __u32 length; + __u32 handle_type; + __u32 reserved; + __u64 res_hdl; }; /** @@ -250,12 +250,12 @@ struct cam_isp_tfe_resource { * @reserved: Reserved for alignment */ struct cam_isp_tfe_port_hfr_config { - uint32_t resource_type; - uint32_t subsample_pattern; - uint32_t subsample_period; - uint32_t framedrop_pattern; - uint32_t framedrop_period; - uint32_t reserved; + __u32 resource_type; + __u32 subsample_pattern; + __u32 subsample_period; + __u32 framedrop_pattern; + __u32 framedrop_period; + __u32 reserved; } __attribute__((packed)); /** @@ -267,8 +267,8 @@ struct cam_isp_tfe_port_hfr_config { * @port_hfr_config: HFR configuration for each IO port */ struct cam_isp_tfe_resource_hfr_config { - uint32_t num_ports; - uint32_t reserved; + __u32 num_ports; + __u32 reserved; struct cam_isp_tfe_port_hfr_config port_hfr_config[1]; } __attribute__((packed)); @@ -284,10 +284,10 @@ struct cam_isp_tfe_resource_hfr_config { * */ struct cam_isp_tfe_dual_stripe_config { - uint32_t offset; - uint32_t width; - uint32_t port_id; - uint32_t reserved; + __u32 offset; + __u32 width; + __u32 port_id; + __u32 reserved; }; /** @@ -299,9 +299,9 @@ struct cam_isp_tfe_dual_stripe_config { * */ struct cam_isp_tfe_dual_config { - uint32_t num_ports; - uint32_t reserved; - struct cam_isp_tfe_dual_stripe_config stripes[1]; + __u32 num_ports; + __u32 reserved; + struct cam_isp_tfe_dual_stripe_config stripes[1]; } __attribute__((packed)); /** @@ -320,11 +320,11 @@ struct cam_isp_tfe_dual_config { * clock and let KMD decide. */ struct cam_isp_tfe_clock_config { - uint32_t usage_type; - uint32_t num_rdi; - uint64_t left_pix_hz; - uint64_t right_pix_hz; - uint64_t rdi_hz[1]; + __u32 usage_type; + __u32 num_rdi; + __u64 left_pix_hz; + __u64 right_pix_hz; + __u64 rdi_hz[1]; } __attribute__((packed)); /** @@ -335,8 +335,8 @@ struct cam_isp_tfe_clock_config { * @csi_phy_clock Phy clock valid if tpg is selected */ struct cam_isp_tfe_csid_clock_config { - uint64_t csid_clock; - uint64_t phy_clock; + __u64 csid_clock; + __u64 phy_clock; } __attribute__((packed)); /** @@ -347,9 +347,9 @@ struct cam_isp_tfe_csid_clock_config { * @axi_path Per path vote info */ struct cam_isp_tfe_bw_config_v2 { - uint32_t usage_type; - uint32_t num_paths; - struct cam_axi_per_path_bw_vote axi_path[1]; + __u32 usage_type; + __u32 num_paths; + struct cam_axi_per_path_bw_vote axi_path[1]; } __attribute__((packed)); /** @@ -366,14 +366,14 @@ struct cam_isp_tfe_bw_config_v2 { * structure */ struct cam_isp_tfe_acquire_hw_info { - uint16_t common_info_version; - uint16_t common_info_size; - uint32_t common_info_offset; - uint32_t num_inputs; - uint32_t input_info_version; - uint32_t input_info_size; - uint32_t input_info_offset; - uint64_t data; + __u16 common_info_version; + __u16 common_info_size; + __u32 common_info_offset; + __u32 num_inputs; + __u32 input_info_version; + __u32 input_info_size; + __u32 input_info_offset; + __u64 data; }; #define CAM_TFE_ACQUIRE_COMMON_VER0 0x1000 From be34fb7086ade233e38c56cbd6874ef7c9ca4e11 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 12 May 2020 17:26:39 -0700 Subject: [PATCH 350/790] msm: camera: util: Correct the return code For secure mode, csiphy driver ask for secure stream. Currently this call always return success. This change return the appropriate result of failure/success. CRs-Fixed: 2673418 Change-Id: Ib425ad77e6481888acefdaf843256602aa759cf3 Signed-off-by: Jigarkumar Zala --- drivers/cam_utils/cam_compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index e0b70865c885..27c84b0ecac2 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -86,7 +86,7 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, rc = -EINVAL; } - return 0; + return rc; } void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) @@ -169,7 +169,7 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, rc = -EINVAL; } - return 0; + return rc; } void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) From 4a7fda98ae2a840eee7d508a64068115eb4731c0 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 13 May 2020 14:38:59 -0700 Subject: [PATCH 351/790] msm: camera: isp: Update last reported request ID correctly The last reported request ID indicates the request ID for which the shutter was sent last. Only update this field for requests that have not bubbled in a given IFE ctx. CRs-Fixed: 2680502 Change-Id: I9ee4b479fe95800efa40ea1ff8d840fc79ef6528 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 7fd06d214c9e..13cd4ae74d94 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1364,7 +1364,9 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( } list_for_each_entry(req, &ctx->active_req_list, list) { - if (req->request_id > ctx_isp->reported_req_id) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if ((!req_isp->bubble_detected) && + (req->request_id > ctx_isp->reported_req_id)) { request_id = req->request_id; ctx_isp->reported_req_id = request_id; __cam_isp_ctx_update_event_record(ctx_isp, From a4f5f1e5126c1c9aceba6bf82c0d817732033097 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 28 May 2020 14:52:33 -0700 Subject: [PATCH 352/790] msm: camera: flash: Add flash off operation in shutdown There is high chances, when camera server crash flash may not have flash off request scheduled with CRM. In case of torch on, followed by shutdown sequence, if flash off request is not scheduled, flash remains turned on. This change adds flash off operation, in case of shutdown. CRs-Fixed: 2691916 Change-Id: I472f2b204b93d0cdc3d8a1f14fff29ab479e4588 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 3 +-- drivers/cam_sensor_module/cam_flash/cam_flash_dev.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index c9a0d611e69c..adc7f0d86c0e 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -466,8 +466,6 @@ 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, (enum led_brightness)LED_SWITCH_OFF); - - flash_ctrl->flash_state = CAM_FLASH_STATE_START; return 0; } @@ -1829,6 +1827,7 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || (fctrl->flash_state == CAM_FLASH_STATE_START)) { fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + cam_flash_off(fctrl); if (fctrl->func_tbl.power_ops) { rc = fctrl->func_tbl.power_ops(fctrl, false); if (rc) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 320caa6d9cfe..3d2ef84a2a87 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -176,9 +176,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; + cam_flash_off(fctrl); fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE; break; } From 8f54a5073210093b6616f94f982fcd8cebfc1bad Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 28 Apr 2020 13:29:12 -0700 Subject: [PATCH 353/790] msm: camera: isp: Wait for cdm submit incase of custom HW If IFE is connected to custom HW in the pipeline, make the cdm submit a blocking call to ensure settings are programmed to IFE on time. CRs-Fixed: 2687917 Change-Id: Ib7a3c44f3f99a30805c1cbf49669dabc27d20431 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 24 ++++++++++++++------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 8 +++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7e62810609fa..f6a8632b11ae 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2910,6 +2910,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } ife_ctx->custom_enabled = false; + ife_ctx->custom_config = 0; memset(ife_ctx->cdm_handle, 0, sizeof(ife_ctx->cdm_handle)); ife_ctx->common.cb_priv = acquire_args->context_data; @@ -2941,8 +2942,11 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) if ((in_port->cust_node) && (!ife_ctx->custom_enabled)) { ife_ctx->custom_enabled = true; - /* This can be obtained from uapi */ - ife_ctx->use_frame_header_ts = true; + /* These can be obtained from uapi */ + ife_ctx->custom_config |= + CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS; + ife_ctx->custom_config |= + CAM_IFE_CUSTOM_CFG_SW_SYNC_ON; } if ((in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || @@ -3034,7 +3038,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->ctxt_to_hw_map = ife_ctx; acquire_args->custom_enabled = ife_ctx->custom_enabled; - acquire_args->use_frame_header_ts = ife_ctx->use_frame_header_ts; + acquire_args->use_frame_header_ts = + (ife_ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS); ife_ctx->ctx_in_use = 1; ife_ctx->num_reg_dump_buf = 0; @@ -3689,7 +3694,8 @@ static int cam_ife_config_hw_internal_cdm(struct cam_ife_hw_mgr_ctx *ctx, for (i = 0; i < ctx->num_base; i++) { idx = ctx->base[i].idx; - if (cfg->init_packet) { + if ((cfg->init_packet) || + (ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) { rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete[idx], msecs_to_jiffies(30)); @@ -3779,7 +3785,8 @@ static int cam_ife_config_hw_external_cdm(struct cam_ife_hw_mgr_ctx *ctx, return rc; } - if (cfg->init_packet) { + if ((cfg->init_packet) || + (ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) { rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete[0], msecs_to_jiffies(30)); @@ -4681,7 +4688,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->cdm_ops = NULL; ctx->num_reg_dump_buf = 0; ctx->custom_enabled = false; - ctx->use_frame_header_ts = false; + ctx->custom_config = 0; ctx->num_reg_dump_buf = 0; ctx->is_dual = false; ctx->dsp_enabled = false; @@ -6163,7 +6170,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, if (rc) return rc; - if (ctx->use_frame_header_ts) { + if (ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) { rc = cam_ife_mgr_util_insert_frame_header(&kmd_buf, prepare_hw_data); if (rc) @@ -7350,7 +7357,8 @@ static int cam_ife_hw_mgr_handle_hw_sof( &sof_done_event_data.boot_time); /* if frame header is enabled reset qtimer ts */ - if (ife_hw_mgr_ctx->use_frame_header_ts) + if (ife_hw_mgr_ctx->custom_config & + CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) sof_done_event_data.timestamp = 0x0; if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index b6124ba566c7..9ff4c05d0e5b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -28,6 +28,10 @@ enum cam_ife_res_master_slave { #define CAM_IFE_HW_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_MAX & 0xFF) #define CAM_IFE_HW_RES_POOL_MAX 64 +/* IFE_HW_MGR custom config */ +#define CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS BIT(0) +#define CAM_IFE_CUSTOM_CFG_SW_SYNC_ON BIT(1) + /** * struct cam_ife_hw_mgr_debug - contain the debug information * @@ -94,7 +98,7 @@ struct cam_ife_hw_mgr_debug { * @is_fe_enabled Indicate whether fetch engine\read path is enabled * @is_dual indicate whether context is in dual VFE mode * @custom_enabled update the flag if context is connected to custom HW - * @use_frame_header_ts obtain qtimer ts using frame header + * @custom_config ife ctx config if custom is enabled [bit field] * @ts captured timestamp when the ctx is acquired * @is_tpg indicate whether context is using PHY TPG * @is_offline Indicate whether context is for offline IFE @@ -152,7 +156,7 @@ struct cam_ife_hw_mgr_ctx { bool is_fe_enabled; bool is_dual; bool custom_enabled; - bool use_frame_header_ts; + uint32_t custom_config; struct timespec64 ts; bool is_tpg; bool is_offline; From 5c24b7d2d6cf0fa8ea25b145cc0c87aa9e3a7c58 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 6 Apr 2020 14:28:07 -0700 Subject: [PATCH 354/790] msm: camera: common: Correct compilation flag for TFE hw TFE hardware compilation needs to be enable with correct flag. Correct tfe compilation flag along with necessary base Makefile change. Also, remove unnecessary makefiles from tfe hw module. CRs-Fixed: 2675526 Change-Id: Ibd8b8f5acc4f843bf373e14a9c8e3bc41cb58839 Signed-off-by: Jigarkumar Zala --- drivers/Makefile | 10 +++------- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 8 ++++++++ .../isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile | 15 --------------- drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile | 13 ------------- 4 files changed, 11 insertions(+), 35 deletions(-) delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile delete mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile diff --git a/drivers/Makefile b/drivers/Makefile index ed3cbb527506..dc5da5116010 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -88,6 +88,7 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o \ cam_isp/isp_hw_mgr/cam_isp_hw_mgr.o \ @@ -195,8 +196,7 @@ camera-$(CONFIG_SPECTRA_OPE) += \ cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.o\ cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.o -camera-$(CONFIG_SPECTRA_CAMERA) += \ - cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.o \ +camera-$(CONFIG_SPECTRA_TFE) += \ cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.o \ @@ -206,11 +206,7 @@ camera-$(CONFIG_SPECTRA_CAMERA) += \ cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.o \ - cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \ - cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \ - cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ - cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.o \ - cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o + cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.o camera-y += camera_main.o diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index c22eb7862253..8aefaa7acf3b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -191,6 +191,14 @@ struct cam_tfe_hw_event_recovery_data { * @iommu_hdl: Iommu handle to be returned * */ +#ifdef CONFIG_SPECTRA_TFE int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); +#else +static inline int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, + int *iommu_hdl) { + return -EINVAL; +} +#endif + #endif /* _CAM_TFE_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile deleted file mode 100644 index dcb41c82af58..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_csid_dev.o cam_tfe_csid_soc.o cam_tfe_csid_core.o -obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_csid530.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile deleted file mode 100644 index 777b5e7fda6a..000000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/ -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include -ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller - -obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_soc.o cam_tfe_dev.o cam_tfe_core.o cam_tfe_bus.o cam_tfe.o From cb7abacaf603d92a5c7001eb7e24e0cccbbe8c3d Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Fri, 29 May 2020 11:38:09 -0700 Subject: [PATCH 355/790] msm: camera: cci: Correct logging for better debug Correct and Update logs for better debugging purpose. CRs-Fixed: 2686717 Change-Id: I2f7720e32aaf44764e6341813bb35c1717125a67 Signed-off-by: Jigar Agrawal Signed-off-by: Jigarkumar Zala --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 248 +++++++++++------- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 50 ++-- .../cam_sensor_module/cam_cci/cam_cci_soc.c | 45 ++-- 3 files changed, 210 insertions(+), 133 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index fcdee4e50c60..87ae98094968 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -26,7 +26,7 @@ static int32_t cam_cci_convert_type_to_num_bytes( num_bytes = 4; break; default: - CAM_ERR(CAM_CCI, "failed: %d", type); + CAM_ERR(CAM_CCI, "Wrong Sensor I2c Type: %d", type); num_bytes = 0; break; } @@ -45,12 +45,12 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev, if (!cci_dev->cci_master_info[master].status) reinit_completion(&cci_dev->cci_master_info[master] .reset_complete); - rc = wait_for_completion_timeout( - &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc < 0) { - CAM_ERR(CAM_CCI, "wait failed"); - } else if (rc == 0) { - CAM_ERR(CAM_CCI, "wait timeout"); + if (!wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT)) { + CAM_DBG(CAM_CCI, + "wait timeout for reset complete for cci:%d master: %d", + cci_dev->soc_info.index, master); /* Set reset pending flag to true */ cci_dev->cci_master_info[master].reset_pending = true; @@ -65,13 +65,21 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev, base + CCI_RESET_CMD_ADDR); /* wait for reset done irq */ - rc = wait_for_completion_timeout( + if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT); - if (rc <= 0) - CAM_ERR(CAM_CCI, "wait failed %d", rc); + CCI_TIMEOUT)) { + rc = -EINVAL; + CAM_ERR(CAM_CCI, + "Retry:: wait timeout for reset complete for cci: %d master: %d", + cci_dev->soc_info.index, master); + } cci_dev->cci_master_info[master].status = 0; } + + if (!rc) + CAM_DBG(CAM_CCI, + "Success: Reset complete: for cci: %d master: %d", + cci_dev->soc_info.index, master); } static int32_t cam_cci_validate_queue(struct cci_device *cci_dev, @@ -114,26 +122,23 @@ static int32_t cam_cci_validate_queue(struct cci_device *cci_dev, atomic_set( &cci_dev->cci_master_info[master].done_pending[queue], 1); - cam_io_w_mb(reg_val, base + - CCI_QUEUE_START_ADDR); - CAM_DBG(CAM_CCI, "wait_for_completion_timeout"); + cam_io_w_mb(reg_val, base + CCI_QUEUE_START_ADDR); atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1); spin_unlock_irqrestore( &cci_dev->cci_master_info[master].lock_q[queue], flags); - rc = wait_for_completion_timeout( + if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].report_q[queue], - CCI_TIMEOUT); - if (rc <= 0) { - CAM_ERR(CAM_CCI, "Wait_for_completion_timeout: rc: %d", - rc); - if (rc == 0) - rc = -ETIMEDOUT; + CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "Wait timeout cci: %d, Master:%d, report_q: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); cam_cci_flush_queue(cci_dev, master); - return rc; + return -EINVAL; } rc = cci_dev->cci_master_info[master].status; if (rc < 0) { - CAM_ERR(CAM_CCI, "Failed rc %d", rc); + CAM_ERR(CAM_CCI, "cci: %d is in error state", + cci_dev->soc_info.index); cci_dev->cci_master_info[master].status = 0; } } @@ -152,7 +157,7 @@ static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev, void __iomem *base = NULL; if (!cci_dev) { - CAM_ERR(CAM_CCI, "Failed"); + CAM_ERR(CAM_CCI, "cci_dev NULL"); return -EINVAL; } @@ -161,7 +166,9 @@ static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev, rc = cam_cci_validate_queue(cci_dev, 1, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "Failed %d", rc); + CAM_ERR(CAM_CCI, + "Failed to validate:: cci: %d, Master: %d, Queue:%d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", @@ -169,6 +176,7 @@ static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev, reg_offset, val); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); + return rc; } @@ -248,28 +256,28 @@ static uint32_t cam_cci_wait(struct cci_device *cci_dev, int32_t rc = 0; if (!cci_dev) { - CAM_ERR(CAM_CCI, "failed"); + CAM_ERR(CAM_CCI, "cci_dev pointer is NULL"); return -EINVAL; } - rc = wait_for_completion_timeout( - &cci_dev->cci_master_info[master].report_q[queue], CCI_TIMEOUT); - CAM_DBG(CAM_CCI, "wait DONE_for_completion_timeout"); - - if (rc <= 0) { + if (!wait_for_completion_timeout( + &cci_dev->cci_master_info[master].report_q[queue], + CCI_TIMEOUT)) { #ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); #endif - CAM_ERR(CAM_CCI, "wait for queue: %d", queue); - if (rc == 0) { - rc = -ETIMEDOUT; - cam_cci_flush_queue(cci_dev, master); - return rc; - } + CAM_ERR(CAM_CCI, + "wait timeout for cci:%d, Maser:%d, Queue:%d, rc=%d", + cci_dev->soc_info.index, master, queue, rc); + rc = -ETIMEDOUT; + cam_cci_flush_queue(cci_dev, master); + return rc; } + rc = cci_dev->cci_master_info[master].status; if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, "cci: %d is in error state", + cci_dev->soc_info.index); cci_dev->cci_master_info[master].status = 0; return rc; } @@ -319,8 +327,7 @@ static int32_t cam_cci_wait_report_cmd(struct cci_device *cci_dev, atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1); spin_unlock_irqrestore( &cci_dev->cci_master_info[master].lock_q[queue], flags); - cam_io_w_mb(reg_val, base + - CCI_QUEUE_START_ADDR); + cam_io_w_mb(reg_val, base + CCI_QUEUE_START_ADDR); return cam_cci_wait(cci_dev, master, queue); } @@ -339,12 +346,16 @@ static int32_t cam_cci_transfer_end(struct cci_device *cci_dev, &cci_dev->cci_master_info[master].lock_q[queue], flags); rc = cam_cci_lock_queue(cci_dev, master, queue, 0); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc: %d", rc); + CAM_ERR(CAM_CCI, + "Failed to lock for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } rc = cam_cci_wait_report_cmd(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, + "Failed for wait_report_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } } else { @@ -355,17 +366,23 @@ static int32_t cam_cci_transfer_end(struct cci_device *cci_dev, &cci_dev->cci_master_info[master].lock_q[queue], flags); rc = cam_cci_wait(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, + "Failed with cci_wait for cci: %d, master: %d, queue: %d, rc %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } rc = cam_cci_lock_queue(cci_dev, master, queue, 0); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, + "Failed to lock_queue for cci: %d, master: %d, queue: %d, rc %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } rc = cam_cci_wait_report_cmd(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "Failed rc %d", rc); + CAM_ERR(CAM_CCI, + "Failed in wait_report_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } } @@ -431,7 +448,9 @@ static int32_t cam_cci_process_full_q(struct cci_device *cci_dev, &cci_dev->cci_master_info[master].lock_q[queue], flags); rc = cam_cci_wait(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, + "cci_wait failed for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } } else { @@ -439,7 +458,9 @@ static int32_t cam_cci_process_full_q(struct cci_device *cci_dev, &cci_dev->cci_master_info[master].lock_q[queue], flags); rc = cam_cci_wait_report_cmd(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc %d", rc); + CAM_ERR(CAM_CCI, + "Failed in wait_report for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } } @@ -460,7 +481,8 @@ static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev, uint32_t size = cmd_size; if (!cci_dev || !c_ctrl) { - CAM_ERR(CAM_CCI, "failed"); + CAM_ERR(CAM_CCI, "Invalid arguments cci_dev:%p, c_ctrl:%p", + cci_dev, c_ctrl); return -EINVAL; } @@ -498,7 +520,8 @@ static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev, } if (len > cci_dev->payload_size) { - CAM_ERR(CAM_CCI, "Len error: %d", len); + CAM_ERR(CAM_CCI, "Len error: len: %u expected_len: %u", + len, cci_dev->payload_size); return -EINVAL; } @@ -515,7 +538,7 @@ static uint32_t cam_cci_cycles_per_ms(unsigned long clk) if (clk) { cycles_per_us = ((clk/1000)*256)/1000; } else { - CAM_ERR(CAM_CCI, "failed: Can use default: %d", + CAM_ERR(CAM_CCI, "Failed: Can use default: %d", CYCLES_PER_MICRO_SEC_DEFAULT); cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT; } @@ -712,7 +735,9 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev, rc = cam_cci_lock_queue(cci_dev, master, queue, 1); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed line %d", rc); + CAM_ERR(CAM_CCI, + "Failed to lock_queue for cci: %d, Master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); return rc; } @@ -722,7 +747,8 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev, len = cam_cci_calc_cmd_len(cci_dev, c_ctrl, cmd_size, i2c_cmd, &pack); if (len <= 0) { - CAM_ERR(CAM_CCI, "failed"); + CAM_ERR(CAM_CCI, + "Calculate comamnd len failed, len:%d", len); return -EINVAL; } @@ -736,7 +762,9 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev, rc = cam_cci_process_full_q(cci_dev, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "failed rc: %d", rc); + CAM_ERR(CAM_CCI, + "Failed to process full queue rc: %d", + rc); return rc; } continue; @@ -946,12 +974,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1, master, queue); if (rc < 0) { - CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc); + CAM_ERR(CAM_CCI, "Initial validataion failed rc:%d", rc); goto rel_mutex_q; } if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { - CAM_ERR(CAM_CCI, "More than max retries"); + CAM_ERR(CAM_CCI, + "Invalid read retries info retries from slave: %d, max retries : %d", + c_ctrl->cci_info->retries, CCI_I2C_READ_MAX_RETRIES); goto rel_mutex_q; } @@ -975,14 +1005,18 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, c_ctrl->cci_info->id_map << 18; rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue); if (rc < 0) { - CAM_DBG(CAM_CCI, "failed rc: %d", rc); + CAM_DBG(CAM_CCI, + "Failed to write param_cmd for cci: %d, master:%d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); 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); + CAM_DBG(CAM_CCI, + "failed to write lock_cmd for cci: %d, master:%d, queue:%d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); goto rel_mutex_q; } @@ -994,21 +1028,27 @@ 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); + CAM_DBG(CAM_CCI, + "Failed to write disable cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); 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); + CAM_DBG(CAM_CCI, + "Failed to write read_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); 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); + CAM_DBG(CAM_CCI, + "Failed to write unlock_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); goto rel_mutex_q; } @@ -1034,8 +1074,8 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); CAM_ERR(CAM_CCI, - "wait_for_completion_timeout rc = %d FIFO buf_lvl:0x%x", - rc, val); + "wait timeout for th_complete cci: %d, master: %d, FIFO buf_lvl:0x%x, rc: %d", + cci_dev->soc_info.index, master, val, rc); #ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); #endif @@ -1044,8 +1084,10 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, } if (cci_dev->cci_master_info[master].status) { - CAM_ERR(CAM_CCI, "Error with Salve: 0x%x", - (c_ctrl->cci_info->sid << 1)); + CAM_ERR(CAM_CCI, + "Error with Slave: 0x%x on cci_dev: %d, master: %d", + (c_ctrl->cci_info->sid << 1), + cci_dev->soc_info.index, master); rc = -EINVAL; cci_dev->cci_master_info[master].status = 0; goto rel_mutex_q; @@ -1122,8 +1164,9 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); CAM_ERR(CAM_CCI, - "Failed to receive RD_DONE irq rc = %d FIFO buf_lvl:0x%x", - rc, val); + "wait timeout for RD_DONE irq for cci: %d, master: %d, rc = %d FIFO buf_lvl:0x%x, rc: %d", + cci_dev->soc_info.index, master, + val, rc); #ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); @@ -1179,7 +1222,8 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX || c_ctrl->cci_info->cci_i2c_master < 0) { - CAM_ERR(CAM_CCI, "Invalid I2C master addr"); + CAM_ERR(CAM_CCI, "Invalid I2C master addr:%d", + c_ctrl->cci_info->cci_i2c_master); return -EINVAL; } @@ -1233,7 +1277,9 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, } if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { - CAM_ERR(CAM_CCI, "More than max retries"); + CAM_ERR(CAM_CCI, + "Invalid read retries info retries from slave: %d, max retries : %d", + c_ctrl->cci_info->retries, CCI_I2C_READ_MAX_RETRIES); goto rel_mutex_q; } @@ -1251,19 +1297,23 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, c_ctrl->cci_info->id_map << 18; rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue); if (rc < 0) { - CAM_DBG(CAM_CCI, "failed rc: %d", rc); + CAM_DBG(CAM_CCI, + "Failed to write param_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); 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); + CAM_DBG(CAM_CCI, + "Failed to write lock_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); goto rel_mutex_q; } if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { - CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u", + CAM_ERR(CAM_CCI, "Failed : Invalid addr type: %u", read_cfg->addr_type); rc = -EINVAL; goto rel_mutex_q; @@ -1277,21 +1327,27 @@ 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); + CAM_DBG(CAM_CCI, + "Failed to write disable_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); 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); + CAM_DBG(CAM_CCI, + "Failed to write read_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); 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); + CAM_DBG(CAM_CCI, + "Failed to write unlock_cmd for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); goto rel_mutex_q; } @@ -1303,27 +1359,22 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, val = 1 << ((master * 2) + queue); cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); - CAM_DBG(CAM_CCI, - "waiting_for_rd_done [exp_words: %d]", + CAM_DBG(CAM_CCI, "exp_words to be read: %d", ((read_cfg->num_byte / 4) + 1)); - rc = wait_for_completion_timeout( - &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT); - if (rc <= 0) { + if (!wait_for_completion_timeout( + &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT)) { #ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); #endif - if (rc == 0) - rc = -ETIMEDOUT; + rc = -ETIMEDOUT; val = cam_io_r_mb(base + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); CAM_ERR(CAM_CCI, - "wait_for_completion_timeout rc = %d FIFO buf_lvl: 0x%x", - rc, val); + "wait timeout rd_done for cci: %d, master: %d, queue: %d, FIFO buf_lvl: 0x%x, rc: %d", + cci_dev->soc_info.index, master, queue, val, rc); cam_cci_flush_queue(cci_dev, master); goto rel_mutex_q; - } else { - rc = 0; } if (cci_dev->cci_master_info[master].status) { @@ -1444,12 +1495,16 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd, goto ERROR; } if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { - CAM_ERR(CAM_CCI, "More than max retries"); + CAM_ERR(CAM_CCI, + "Invalid read retries info retries from slave: %d, max retries : %d", + c_ctrl->cci_info->retries, CCI_I2C_READ_MAX_RETRIES); 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); + CAM_ERR(CAM_CCI, + "Failed in queueing the data for cci: %d, master: %d, queue: %d, rc: %d", + cci_dev->soc_info.index, master, queue, rc); goto ERROR; } @@ -1483,7 +1538,7 @@ static void cam_cci_write_async_helper(struct work_struct *work) &write_async->c_ctrl, write_async->queue, write_async->sync_en); mutex_unlock(&cci_master_info->mutex_q[write_async->queue]); if (rc < 0) - CAM_ERR(CAM_CCI, "failed rc: %d", rc); + CAM_ERR(CAM_CCI, "Failed rc: %d", rc); kfree(write_async->c_ctrl.cfg.cci_i2c_write_cfg.reg_setting); kfree(write_async); @@ -1502,8 +1557,10 @@ static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); write_async = kzalloc(sizeof(*write_async), GFP_KERNEL); - if (!write_async) + if (!write_async) { + CAM_ERR(CAM_CCI, "Memory allocation failed for write_async"); return -ENOMEM; + } INIT_WORK(&write_async->work, cam_cci_write_async_helper); @@ -1524,7 +1581,7 @@ static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, kzalloc(sizeof(struct cam_sensor_i2c_reg_array)* cci_i2c_write_cfg->size, GFP_KERNEL); if (!cci_i2c_write_cfg_w->reg_setting) { - CAM_ERR(CAM_CCI, "Couldn't allocate memory"); + CAM_ERR(CAM_CCI, "Couldn't allocate memory for reg_setting"); kfree(write_async); return -ENOMEM; } @@ -1554,7 +1611,7 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, uint16_t read_bytes = 0; if (!sd || !c_ctrl) { - CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl); + CAM_ERR(CAM_CCI, "Invalid arg sd %pK c_ctrl %pK", sd, c_ctrl); return -EINVAL; } if (!c_ctrl->cci_info) { @@ -1610,7 +1667,7 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, rc = cam_cci_read(sd, c_ctrl); } if (rc) { - CAM_ERR(CAM_CCI, "failed to read rc:%d", rc); + CAM_ERR(CAM_CCI, "Failed to read rc:%d", rc); goto ERROR; } @@ -1637,7 +1694,8 @@ static int32_t cam_cci_i2c_set_sync_prms(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { - CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + CAM_ERR(CAM_CCI, + "Failed: invalid params cci_dev:%pK, c_ctrl:%pK", cci_dev, c_ctrl); rc = -EINVAL; return rc; @@ -1675,7 +1733,8 @@ static int32_t cam_cci_write(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { - CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + CAM_ERR(CAM_CCI, + "Failed: invalid params cci_dev:%pK, c_ctrl:%pK", cci_dev, c_ctrl); rc = -EINVAL; return rc; @@ -1692,6 +1751,7 @@ static int32_t cam_cci_write(struct v4l2_subdev *sd, cci_master_info = &cci_dev->cci_master_info[master]; switch (c_ctrl->cmd) { + CAM_DBG(CAM_CCI, "ctrl_cmd = %d", c_ctrl->cmd); case MSM_CCI_I2C_WRITE_SYNC_BLOCK: mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]); rc = cam_cci_i2c_write(sd, c_ctrl, diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 269a2fd28a61..1281691df5b6 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -72,8 +72,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR); irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR); - CAM_DBG(CAM_CCI, "BASE: %pK", base); - CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1); + CAM_DBG(CAM_CCI, + "BASE: %pK, irq0:%x irq1:%x", + base, irq_status0, irq_status1); if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { struct cam_cci_master_info *cci_master_info; @@ -229,21 +230,23 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_0].status = -EINVAL; if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK) { - CAM_ERR(CAM_CCI, "Base:%pK, M0_Q0 NACK ERROR: 0x%x", - base, irq_status0); + CAM_ERR(CAM_CCI, + "Base:%pK,cci: %d, M0_Q0 NACK ERROR: 0x%x", + base, cci_dev->soc_info.index, irq_status0); complete_all(&cci_dev->cci_master_info[MASTER_0] .report_q[QUEUE_0]); } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK) { - CAM_ERR(CAM_CCI, "Base:%pK, M0_Q1 NACK ERROR: 0x%x", - base, irq_status0); + CAM_ERR(CAM_CCI, + "Base:%pK,cci: %d, M0_Q1 NACK ERROR: 0x%x", + base, cci_dev->soc_info.index, irq_status0); complete_all(&cci_dev->cci_master_info[MASTER_0] .report_q[QUEUE_1]); } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, - "Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x", - base, irq_status0); + "Base:%pK, cci: %d, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x", + base, cci_dev->soc_info.index, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x", @@ -255,25 +258,27 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_1].status = -EINVAL; if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK) { - CAM_ERR(CAM_CCI, "Base:%pK, M1_Q0 NACK ERROR: 0x%x", - base, irq_status0); + CAM_ERR(CAM_CCI, + "Base:%pK, cci: %d, M1_Q0 NACK ERROR: 0x%x", + base, cci_dev->soc_info.index, irq_status0); complete_all(&cci_dev->cci_master_info[MASTER_1] .report_q[QUEUE_0]); } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK) { - CAM_ERR(CAM_CCI, "Base:%pK, M1_Q1 NACK ERROR: 0x%x", - base, irq_status0); + CAM_ERR(CAM_CCI, + "Base:%pK, cci: %d, M1_Q1 NACK ERROR: 0x%x", + base, cci_dev->soc_info.index, irq_status0); complete_all(&cci_dev->cci_master_info[MASTER_1] .report_q[QUEUE_1]); } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, - "Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x", - base, irq_status0); + "Base:%pK, cci: %d, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x", + base, cci_dev->soc_info.index, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, - "Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x", - base, irq_status0); + "Base:%pK, cci: %d, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x", + base, cci_dev->soc_info.index, irq_status0); cci_dev->cci_master_info[MASTER_1].reset_pending = true; cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR); @@ -378,9 +383,10 @@ static int cam_cci_component_bind(struct device *dev, new_cci_dev = devm_kzalloc(&pdev->dev, sizeof(struct cci_device), GFP_KERNEL); - if (!new_cci_dev) + if (!new_cci_dev) { + CAM_ERR(CAM_CCI, "Memory allocation failed for cci_dev"); return -ENOMEM; - + } soc_info = &new_cci_dev->soc_info; new_cci_dev->v4l2_dev_str.pdev = pdev; @@ -391,7 +397,7 @@ static int cam_cci_component_bind(struct device *dev, rc = cam_cci_parse_dt_info(pdev, new_cci_dev); if (rc < 0) { - CAM_ERR(CAM_CCI, "Resource get Failed: %d", rc); + CAM_ERR(CAM_CCI, "Resource get Failed rc:%d", rc); goto cci_no_resource; } @@ -412,7 +418,7 @@ static int cam_cci_component_bind(struct device *dev, rc = cam_register_subdev(&(new_cci_dev->v4l2_dev_str)); if (rc < 0) { - CAM_ERR(CAM_CCI, "Fail with cam_register_subdev"); + CAM_ERR(CAM_CCI, "Fail with cam_register_subdev rc: %d", rc); goto cci_no_resource; } @@ -435,7 +441,7 @@ static int cam_cci_component_bind(struct device *dev, strlcpy(cpas_parms.identifier, "cci", CAM_HW_IDENTIFIER_LENGTH); rc = cam_cpas_register_client(&cpas_parms); if (rc) { - CAM_ERR(CAM_CCI, "CPAS registration failed"); + CAM_ERR(CAM_CCI, "CPAS registration failed rc:%d", rc); goto cci_no_resource; } @@ -463,7 +469,7 @@ static void cam_cci_component_unbind(struct device *dev, cam_cci_soc_remove(pdev, cci_dev); rc = cam_unregister_subdev(&(cci_dev->v4l2_dev_str)); if (rc < 0) - CAM_ERR(CAM_CCI, "Fail with cam_unregister_subdev"); + CAM_ERR(CAM_CCI, "Fail with cam_unregister_subdev. rc:%d", rc); devm_kfree(&pdev->dev, cci_dev); } diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 66fe66b00501..03208616459d 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -21,7 +21,8 @@ int cam_cci_init(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { - CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + CAM_ERR(CAM_CCI, + "failed: invalid params cci_dev:%pK, c_ctrl:%pK", cci_dev, c_ctrl); rc = -EINVAL; return rc; @@ -31,7 +32,8 @@ int cam_cci_init(struct v4l2_subdev *sd, base = soc_info->reg_map[0].mem_base; if (!soc_info || !base) { - CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK", + CAM_ERR(CAM_CCI, + "failed: invalid params soc_info:%pK, base:%pK", soc_info, base); rc = -EINVAL; return rc; @@ -40,8 +42,9 @@ int cam_cci_init(struct v4l2_subdev *sd, CAM_DBG(CAM_CCI, "Base address %pK", base); if (cci_dev->ref_count++) { - CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count); - CAM_DBG(CAM_CCI, "master %d", master); + CAM_DBG(CAM_CCI, + "ref_count:%d, master:%d", + cci_dev->ref_count, master); if (master < MASTER_MAX && master >= 0) { mutex_lock(&cci_dev->cci_master_info[master].mutex); flush_workqueue(cci_dev->write_wq[master]); @@ -64,15 +67,21 @@ int cam_cci_init(struct v4l2_subdev *sd, cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR); /* wait for reset done irq */ - rc = wait_for_completion_timeout( + if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT); - if (rc <= 0) - CAM_ERR(CAM_CCI, "wait failed %d", rc); + CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "wait timeout for reset_complete for master: %d", + master); + reinit_completion( + &cci_dev->cci_master_info[master].reset_complete + ); + rc = -EINVAL; + } cci_dev->cci_master_info[master].status = 0; mutex_unlock(&cci_dev->cci_master_info[master].mutex); } - return 0; + return rc; } ahb_vote.type = CAM_VOTE_ABSOLUTE; @@ -92,7 +101,7 @@ int cam_cci_init(struct v4l2_subdev *sd, rc = cam_cpas_start(cci_dev->cpas_handle, &ahb_vote, &axi_vote); if (rc != 0) - CAM_ERR(CAM_CCI, "CPAS start failed"); + CAM_ERR(CAM_CCI, "CPAS start failed, rc: %d", rc); cam_cci_get_clk_rates(cci_dev, c_ctrl); @@ -107,7 +116,8 @@ int cam_cci_init(struct v4l2_subdev *sd, rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_LOWSVS_VOTE, true); if (rc < 0) { - CAM_DBG(CAM_CCI, "request platform resources failed"); + CAM_DBG(CAM_CCI, "request platform resources failed, rc: %d", + rc); goto platform_enable_failed; } @@ -148,13 +158,14 @@ int cam_cci_init(struct v4l2_subdev *sd, cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); - rc = wait_for_completion_timeout( + if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT); - if (rc <= 0) { - CAM_ERR(CAM_CCI, "wait_for_completion_timeout"); - if (rc == 0) - rc = -ETIMEDOUT; + CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "wait timeout for reset_complete for master: %d", + master); + + rc = -ETIMEDOUT; goto reset_complete_failed; } for (i = 0; i < MASTER_MAX; i++) From 68846d255520ee8e915862d13868e79016288762 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Wed, 22 Apr 2020 15:46:09 -0700 Subject: [PATCH 356/790] msm: camera: isp: Fix num_entries value assigned to variable num_cfg_new temp variable should be assigned the value of num_hw_entries from new isp request instead of old isp request. CRs-Fixed: 2673657 Change-Id: Ie4d29949e2c992560b6635f7e0b5db88c2dafd48 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/cam_isp_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 2091399a6d0a..4b9c4a671f80 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -491,7 +491,7 @@ static int __cam_isp_ctx_enqueue_init_request( num_cfg_old = req_isp_old->cfg_info[i].num_hw_entries; num_cfg_new = - req_isp_old->cfg_info[i].num_hw_entries; + req_isp_new->cfg_info[i].num_hw_entries; memcpy(&cfg_old[num_cfg_old], cfg_new, sizeof(cfg_new[0]) * num_cfg_new); From 4544e11ed91e56a5a5ceb55a5889919c5ddfe126 Mon Sep 17 00:00:00 2001 From: Venkat Chinta Date: Wed, 27 May 2020 11:22:24 -0700 Subject: [PATCH 357/790] msm: camera: isp: Check for epoch before applying When there is a delay in offline ife workqueue scheduling it is possible that two requests are applied back to back. This could lead to requests lost. Therefore we must check for epoch flag before applying any request. CRs-Fixed: 2686281 Change-Id: I323710a61301d79e78db22dc1f66a6a0f141389a Signed-off-by: Venkat Chinta --- drivers/cam_isp/cam_isp_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 2091399a6d0a..fafd09f8c4da 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1108,7 +1108,9 @@ static int __cam_isp_ctx_apply_req_offline( goto end; } - if (ctx->state != CAM_CTX_ACTIVATED) + if ((ctx->state != CAM_CTX_ACTIVATED) || + (!atomic_read(&ctx_isp->rxd_epoch)) || + (ctx_isp->substate_activated == CAM_ISP_CTX_ACTIVATED_APPLIED)) goto end; if (ctx_isp->active_req_cnt >= 2) From 172d34b6f7f81a88b96ee13c3d48015ddccd6bc5 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 21 Apr 2020 12:11:13 +0530 Subject: [PATCH 358/790] msm: camera: common: Merge camera-kernel.3.1 changes in camera-kernel.4.0 msm: camera: tfe: Fix variable initialization issues msm: camera: isp: Dual tfe event check with proper hw idx msm: camera: smmu: Add support for non-contiguous mermory region msm: camera: smmu: Use iommu best match algo for camera msm: camera: ope: Optimize allocation of IO configuration msm: camera: ope: Fix for KW Issues msm: camera: ope: Add support for stripe level height configuration msm: camera: tfe: Enable the delay line clc msm: camera: ope: Fix false alarm for OPE HW timeout msm: camera: tfe: Support register dump per request msm: camera: ope: Increase max number of stripes msm: camera: ope: Change packer and unpacker format in case NV12 msm: camera: tfe: Add packet code get command for tfe msm: camera: ope: Trigger recovery in case of violation on write bus msm: camera: ope: Protect ope hw reset with mutex msm: camera: ope: Add a check for valid request in cdm callback msm: camera: ope: Remove the BW & clock vote in release context msm: camera: ope: Reduce OPE BUS memory msm: camera: ope: Fix return value for ope acquire msm: camera: ope: Fix false alarm for OPE request timeout msm: camera: ope: Avoid deadlock during recovery after HW hang msm: camera: tfe: tfe debug enhancement msm: camera: cdm: Fix irq_data value in case of inline irq msm: camera: flash: Switch off flash on provider crash msm: camera: ope: Initialize ope hw mutex structure msm: camera: cdm: Flush all available FIFOs during reset msm: camera: cpas: Add mandatory bw option for axi ports clocks msm: camera: ope: Use vzalloc to allocate the write bus ctx structure msm: camera: ope: Fix handling of init hw failure msm: camera: tfe: Enable per frame register dump for rdi only context msm: camera: cdm: Protect cdm core status bits with mutex msm: camera: cdm: correct the error check in cmd submit irq msm: camera: ope: Fix unclock access during HW reset msm: camera: ope: Program frame level settings after idle event msm: camera: ope: Delay releasing of resources for last context msm: camera: isp: Increase default SOF freeze timeout msm: camera: smmu: Add map and unmap monitor msm: camera: isp: Add trace events across ISP msm: camera: smmu: Profile time taken for map, unmap msm: camera: ope: Start context timer on receiving new request msm: camera: tfe: Reduce stack size during set axi bw msm: camera: cdm: Check for HW state before dumping registers msm: camera: ope: Reduce stack footprint during acquire msm: camera: tfe: Disable clock if tfe2 is not supported msm: camera: cdm: Avoid cdm pause incase of BL submit msm: camera: tfe: Optimize CSID IRQ logging msm: camera: ope: Move request id validity check outside of lock msm: camera: tfe: Correct the tfe hw manager dump logic msm: camera: ope: Synchronize flush and submit BLs msm: camera: cdm: Protect cdm reset status msm: camera: cdm: Handle cdm deinit sequence properly msm: camera: tfe: Reduce reset timeout to 100ms msm: camera: ope: Fix hang detection msm: camera: ope: Make non-fatal logs as debug and info logs msm: camera: tfe: set overflow pending bit to zero after HW reset msm: camera: ope: Do not disable CDM during error handling msm: camera: ope: Add support for OPE Replay msm: camera: ope: Stop OPE in case of init failure msm: camera: ope: Synchronize process cmd and flush request msm: camera: cdm: Fix CDM IRQ handling msm: camera: tfe: LDAR dump for TFE msm: camera: ope: Fix the length check for debug buffer msm: camera: cdm: Fix CDM reset logic msm: camera: ope: Dump debug registers in case of HW hang msm: camera: tfe: Support the RDI bus port for line based mode msm: camera: cdm: Handle out of order reset done events msm: camera: ope: Consider other contexts during timeout msm: camera: ope: Put GenIRQ in last stripe BL msm: camera: tfe: Process the rdi interrupts for rdi only resource msm: camera: jpeg: Check the HW state before accessing register msm: camera: csiphy: Update csiphy power-up sequence for lito v2 msm: camera: cdm: Secure freeing of request lists using locks msm: camera: cpas: Add support for Scuba camnoc msm: camera: csiphy: Clear secure phy flags on release msm: camera: tfe: validate the tfe bw num paths msm: camera: ope: Reorder the reset order in ope acquire msm: camera: ope: Dump debug registers in case of reset failure msm: camera: ope: Add logic to detect hang in CDM msm: camera: isp: Increase max count of cfg to support more init packets msm: camera: core: Fix cpas axi clk rate overflow. CRs-Fixed: 2668666 Change-Id: I882ca4bd117bebc7d1c62bc82299d69d7b5c9388 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm.h | 7 + drivers/cam_cdm/cam_cdm_core_common.c | 103 +- drivers/cam_cdm/cam_cdm_core_common.h | 1 + drivers/cam_cdm/cam_cdm_hw_core.c | 493 +++++++--- drivers/cam_cdm/cam_cdm_intf.c | 27 + drivers/cam_cdm/cam_cdm_intf_api.h | 9 + drivers/cam_cpas/cam_cpas_hw.c | 6 +- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 31 + drivers/cam_cpas/cpas_top/cpastop_v520_100.h | 240 +++++ drivers/cam_cpas/include/cam_cpas_api.h | 5 + drivers/cam_icp/fw_inc/hfi_intf.h | 2 +- drivers/cam_icp/fw_inc/hfi_reg.h | 2 +- drivers/cam_icp/hfi.c | 2 +- drivers/cam_isp/cam_isp_context.h | 6 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 6 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 314 +++++- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 6 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 220 ++++- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 7 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 78 ++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 318 ++++++- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h | 18 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 615 +++++++++--- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h | 63 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 54 +- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 896 +++++++++++++++--- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 79 +- .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 60 +- .../ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c | 94 +- .../ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h | 2 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 256 ++--- .../cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h | 1 + drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 10 + .../cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h | 34 + .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 56 +- .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h | 2 + drivers/cam_req_mgr/cam_req_mgr_core.c | 2 +- drivers/cam_req_mgr/cam_req_mgr_core.h | 9 +- .../cam_sensor_module/cam_cci/cam_cci_core.c | 81 +- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 2 + .../cam_sensor_module/cam_cci/cam_cci_soc.c | 13 +- .../cam_csiphy/cam_csiphy_core.c | 23 + .../cam_csiphy/cam_csiphy_soc.c | 4 +- .../include/cam_csiphy_1_2_2_hwreg.h | 25 +- .../cam_flash/cam_flash_core.c | 6 +- drivers/cam_smmu/cam_smmu_api.h | 2 +- drivers/cam_utils/cam_compat.h | 4 +- drivers/cam_utils/cam_soc_util.c | 18 +- drivers/cam_utils/cam_soc_util.h | 4 +- include/uapi/camera/media/cam_ope.h | 3 +- include/uapi/camera/media/cam_tfe.h | 5 + 52 files changed, 3504 insertions(+), 822 deletions(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v520_100.h diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 525d54d68df3..cc808fe2c508 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -67,6 +67,7 @@ /* BL_FIFO configurations*/ #define CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT 0x40 #define CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT 0x10 +#define CAM_CDM_BL_FIFO_FLUSH_SHIFT 0x3 #define CAM_CDM_BL_FIFO_REQ_SIZE_MAX 0x00 #define CAM_CDM_BL_FIFO_REQ_SIZE_MAX_DIV2 0x01 @@ -100,6 +101,7 @@ #define CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK 0x10000 #define CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK 0x20000 #define CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK 0x40000 +#define CAM_CDM_IRQ_STATUS_USR_DATA_MASK 0xFF #define CAM_CDM_IRQ_STATUS_ERRORS \ (CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK | \ @@ -371,6 +373,7 @@ enum cam_cdm_hw_process_intf_cmd { CAM_CDM_HW_INTF_CMD_RESET_HW, CAM_CDM_HW_INTF_CMD_FLUSH_HW, CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, + CAM_CDM_HW_INTF_CMD_HANG_DETECT, CAM_CDM_HW_INTF_CMD_INVALID, }; @@ -466,6 +469,8 @@ struct cam_cdm_bl_fifo { struct mutex fifo_lock; uint8_t bl_tag; uint32_t bl_depth; + uint8_t last_bl_tag_done; + uint32_t work_record; }; /** @@ -493,6 +498,7 @@ struct cam_cdm_bl_fifo { * @gen_irq: memory region in which gen_irq command will be written * @cpas_handle: handle for cpas driver * @arbitration: type of arbitration to be used for the CDM + * @rst_done_cnt: CMD reset done count */ struct cam_cdm { uint32_t index; @@ -515,6 +521,7 @@ struct cam_cdm { struct cam_cdm_hw_mem gen_irq[CAM_CDM_BL_FIFO_MAX]; uint32_t cpas_handle; enum cam_cdm_arbitration arbitration; + uint32_t rst_done_cnt; }; /* struct cam_cdm_private_dt_data - CDM hw custom dt data */ diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index 034fdb5fa49d..e93e54f0335e 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -262,6 +262,47 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } } +static int cam_cdm_stream_handle_init(void *hw_priv, bool init) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_cdm *core = NULL; + int rc = -EPERM; + + core = (struct cam_cdm *)cdm_hw->core_info; + + if (init) { + rc = cam_hw_cdm_init(hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "CDM HW init failed"); + return rc; + } + + if (core->arbitration != + CAM_CDM_ARBITRATION_PRIORITY_BASED) { + rc = cam_hw_cdm_alloc_genirq_mem( + hw_priv); + if (rc) { + CAM_ERR(CAM_CDM, + "Genirqalloc failed"); + cam_hw_cdm_deinit(hw_priv, + NULL, 0); + } + } + } else { + rc = cam_hw_cdm_deinit(hw_priv, NULL, 0); + if (rc) + CAM_ERR(CAM_CDM, "Deinit failed in streamoff"); + + if (core->arbitration != + CAM_CDM_ARBITRATION_PRIORITY_BASED) { + if (cam_hw_cdm_release_genirq_mem(hw_priv)) + CAM_ERR(CAM_CDM, "Genirq release fail"); + } + } + + return rc; +} + int cam_cdm_stream_ops_internal(void *hw_priv, void *start_args, bool operation) { @@ -337,19 +378,7 @@ int cam_cdm_stream_ops_internal(void *hw_priv, rc = 0; } else { CAM_DBG(CAM_CDM, "CDM HW init first time"); - rc = cam_hw_cdm_init(hw_priv, NULL, 0); - if (rc == 0) { - rc = cam_hw_cdm_alloc_genirq_mem( - hw_priv); - if (rc != 0) { - CAM_ERR(CAM_CDM, - "Genirqalloc failed"); - cam_hw_cdm_deinit(hw_priv, - NULL, 0); - } - } else { - CAM_ERR(CAM_CDM, "CDM HW init failed"); - } + rc = cam_cdm_stream_handle_init(hw_priv, true); } if (rc == 0) { cdm_hw->open_count++; @@ -378,17 +407,10 @@ int cam_cdm_stream_ops_internal(void *hw_priv, rc = 0; } else { CAM_DBG(CAM_CDM, "CDM HW Deinit now"); - rc = cam_hw_cdm_deinit( - hw_priv, NULL, 0); - if (cam_hw_cdm_release_genirq_mem( - hw_priv)) - CAM_ERR(CAM_CDM, - "Genirq release fail"); + rc = cam_cdm_stream_handle_init(hw_priv, + false); } - if (rc) { - CAM_ERR(CAM_CDM, - "Deinit failed in streamoff"); - } else { + if (rc == 0) { client->stream_on = false; rc = cam_cpas_stop(core->cpas_handle); if (rc) @@ -763,6 +785,41 @@ int cam_cdm_process_cmd(void *hw_priv, mutex_unlock(&cdm_hw->hw_mutex); break; } + case CAM_CDM_HW_INTF_CMD_HANG_DETECT: { + uint32_t *handle = cmd_args; + int idx; + struct cam_cdm_client *client; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=%x", + cmd, arg_size, *handle); + return -EINVAL; + } + + idx = CAM_CDM_GET_CLIENT_IDX(*handle); + mutex_lock(&cdm_hw->hw_mutex); + client = core->clients[idx]; + if (!client) { + CAM_ERR(CAM_CDM, + "Client not present for handle %d", + *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + if (*handle != client->handle) { + CAM_ERR(CAM_CDM, + "handle mismatch, client handle %d index %d received handle %d", + client->handle, idx, *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } + + rc = cam_hw_cdm_hang_detect(cdm_hw, *handle); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } default: CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); break; diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h index 0f50165c7b15..5545f15903e0 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.h +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -50,6 +50,7 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle); int cam_hw_cdm_flush_hw(struct cam_hw_info *cdm_hw, uint32_t handle); int cam_hw_cdm_handle_error(struct cam_hw_info *cdm_hw, uint32_t handle); +int cam_hw_cdm_hang_detect(struct cam_hw_info *cdm_hw, uint32_t handle); struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( uint32_t tag, struct list_head *bl_list); void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 998d3f6dc625..0ce4380bdd8e 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -129,26 +129,21 @@ static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw, return rc; } -static int cam_hw_cdm_enable_core(struct cam_hw_info *cdm_hw, bool enable) +static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + uint32_t val = 0x1; - if (enable == true) { - if (cam_cdm_write_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_en, - 0x01)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW core enable"); - rc = -EIO; - } - } else { - if (cam_cdm_write_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_en, - 0x02)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW core disable"); - rc = -EIO; - } + if (pause) + val |= 0x2; + + if (cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_en, val)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW core_en"); + rc = -EIO; } + return rc; } @@ -307,10 +302,13 @@ void cam_hw_cdm_dump_core_debug_registers( struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); - CAM_ERR(CAM_CDM, "CDM HW core status=%x", dump_reg); + CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg); - /* First pause CDM, If it fails still proceed to dump debug info */ - cam_hw_cdm_enable_core(cdm_hw, false); + cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, + &dump_reg); + CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg); + + usleep_range(1000, 1010); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, @@ -379,8 +377,6 @@ void cam_hw_cdm_dump_core_debug_registers( core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); - /* Enable CDM back */ - cam_hw_cdm_enable_core(cdm_hw, true); } enum cam_cdm_arbitration cam_cdm_get_arbitration_type( @@ -633,10 +629,13 @@ int cam_hw_cdm_submit_gen_irq( int rc; bool bit_wr_enable = false; - if (core->bl_fifo[fifo_idx].bl_tag > 63) { + if (core->bl_fifo[fifo_idx].bl_tag > + (core->bl_fifo[fifo_idx].bl_depth - 1)) { CAM_ERR(CAM_CDM, - "bl_tag invalid =%d", - core->bl_fifo[fifo_idx].bl_tag); + "Invalid bl_tag=%d bl_depth=%d fifo_idx=%d", + core->bl_fifo[fifo_idx].bl_tag, + core->bl_fifo[fifo_idx].bl_depth, + fifo_idx); rc = -EINVAL; goto end; } @@ -742,6 +741,78 @@ end: return rc; } +static int cam_hw_cdm_arb_submit_bl(struct cam_hw_info *cdm_hw, + struct cam_cdm_hw_intf_cmd_submit_bl *req, int i, + uint32_t fifo_idx, dma_addr_t hw_vaddr_ptr) +{ + struct cam_cdm_bl_request *cdm_cmd = req->data; + struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + uintptr_t cpu_addr; + struct cam_cdm_bl_cb_request_entry *node; + int rc = 0; + size_t len = 0; + + node = kzalloc(sizeof( + struct cam_cdm_bl_cb_request_entry), + GFP_KERNEL); + if (!node) + return -ENOMEM; + + node->request_type = CAM_HW_CDM_BL_CB_CLIENT; + node->client_hdl = req->handle; + node->cookie = req->data->cookie; + node->bl_tag = core->bl_fifo[fifo_idx].bl_tag - + 1; + node->userdata = req->data->userdata; + list_add_tail(&node->entry, + &core->bl_fifo[fifo_idx] + .bl_request_list); + cdm_cmd->cmd[i].arbitrate = true; + rc = cam_mem_get_cpu_buf( + cdm_cmd->cmd[i].bl_addr.mem_handle, + &cpu_addr, &len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buffailed %x", + cdm_cmd->cmd[i].bl_addr + .mem_handle); + return rc; + } + core->ops->cdm_write_genirq( + ((uint32_t *)cpu_addr + + cdm_cmd->cmd[i].offset / 4 + + cdm_cmd->cmd[i].len / 4), + core->bl_fifo[fifo_idx].bl_tag - 1, + 1, fifo_idx); + rc = cam_hw_cdm_bl_write(cdm_hw, + (uint32_t)hw_vaddr_ptr + + cdm_cmd->cmd[i].offset, + cdm_cmd->cmd[i].len + 7, + core->bl_fifo[fifo_idx].bl_tag - 1, + 1, fifo_idx); + if (rc) { + CAM_ERR(CAM_CDM, + "CDM hw bl write failed tag=%d", + core->bl_fifo[fifo_idx].bl_tag - + 1); + list_del_init(&node->entry); + kfree(node); + return -EIO; + } + rc = cam_hw_cdm_commit_bl_write(cdm_hw, + fifo_idx); + if (rc) { + CAM_ERR(CAM_CDM, + "CDM hw commit failed tag=%d", + core->bl_fifo[fifo_idx].bl_tag - + 1); + list_del_init(&node->entry); + kfree(node); + return -EIO; + } + + return 0; +} + int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, struct cam_cdm_hw_intf_cmd_submit_bl *req, struct cam_cdm_client *client) @@ -771,13 +842,17 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, bl_fifo->bl_depth); } - if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || - test_bit(CAM_CDM_RESET_HW_STATUS, &core->cdm_status)) - return -EAGAIN; mutex_lock(&core->bl_fifo[fifo_idx].fifo_lock); mutex_lock(&client->lock); + if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || + test_bit(CAM_CDM_RESET_HW_STATUS, &core->cdm_status)) { + mutex_unlock(&client->lock); + mutex_unlock(&core->bl_fifo[fifo_idx].fifo_lock); + return -EAGAIN; + } + rc = cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, fifo_idx, &pending_bl); @@ -867,18 +942,28 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, if (core->bl_fifo[fifo_idx].bl_tag >= (bl_fifo->bl_depth - 1)) core->bl_fifo[fifo_idx].bl_tag = 0; - rc = cam_hw_cdm_bl_write(cdm_hw, - ((uint32_t)hw_vaddr_ptr + - cdm_cmd->cmd[i].offset), - (cdm_cmd->cmd[i].len - 1), - core->bl_fifo[fifo_idx].bl_tag, - cdm_cmd->cmd[i].arbitrate, - fifo_idx); - if (rc) { - CAM_ERR(CAM_CDM, "Hw bl write failed %d:%d", - i, req->data->cmd_arrary_count); - rc = -EIO; - break; + if (core->arbitration == + CAM_CDM_ARBITRATION_PRIORITY_BASED && + (req->data->flag == true) && + (i == (req->data->cmd_arrary_count - + 1))) { + CAM_DBG(CAM_CDM, + "GenIRQ in same bl, will sumbit later"); + } else { + rc = cam_hw_cdm_bl_write(cdm_hw, + ((uint32_t)hw_vaddr_ptr + + cdm_cmd->cmd[i].offset), + (cdm_cmd->cmd[i].len - 1), + core->bl_fifo[fifo_idx].bl_tag, + cdm_cmd->cmd[i].arbitrate, + fifo_idx); + if (rc) { + CAM_ERR(CAM_CDM, + "Hw bl write failed %d:%d", + i, req->data->cmd_arrary_count); + rc = -EIO; + break; + } } } else { CAM_ERR(CAM_CDM, @@ -893,20 +978,31 @@ 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 total_cnt=%d", + "write BL done cnt=%d with tag=%d total_cnt=%d", i, core->bl_fifo[fifo_idx].bl_tag, req->data->cmd_arrary_count); - CAM_DBG(CAM_CDM, "Now commit the BL"); - if (cam_hw_cdm_commit_bl_write(cdm_hw, fifo_idx)) { - CAM_ERR(CAM_CDM, - "Cannot commit the BL %d tag=%d", + if (core->arbitration == + CAM_CDM_ARBITRATION_PRIORITY_BASED && + (req->data->flag == true) && + (i == (req->data->cmd_arrary_count - + 1))) { + CAM_DBG(CAM_CDM, + "GenIRQ in same blcommit later"); + } else { + CAM_DBG(CAM_CDM, "Now commit the BL"); + if (cam_hw_cdm_commit_bl_write(cdm_hw, + fifo_idx)) { + CAM_ERR(CAM_CDM, + "commit failed BL %d tag=%d", + i, core->bl_fifo[fifo_idx] + .bl_tag); + rc = -EIO; + break; + } + CAM_DBG(CAM_CDM, "commit success BL %d tag=%d", i, core->bl_fifo[fifo_idx].bl_tag); - rc = -EIO; - break; } - CAM_DBG(CAM_CDM, "BL commit success BL %d tag=%d", i, - core->bl_fifo[fifo_idx].bl_tag); core->bl_fifo[fifo_idx].bl_tag++; if (cdm_cmd->cmd[i].enable_debug_gen_irq) { @@ -923,11 +1019,21 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, if ((req->data->flag == true) && (i == (req->data->cmd_arrary_count - 1))) { - rc = cam_hw_cdm_submit_gen_irq( - cdm_hw, req, fifo_idx, - cdm_cmd->gen_irq_arb); - if (rc == 0) - core->bl_fifo[fifo_idx].bl_tag++; + if (core->arbitration != + CAM_CDM_ARBITRATION_PRIORITY_BASED) { + rc = cam_hw_cdm_submit_gen_irq( + cdm_hw, req, fifo_idx, + cdm_cmd->gen_irq_arb); + if (rc == 0) + core->bl_fifo[fifo_idx] + .bl_tag++; + break; + } + + rc = cam_hw_cdm_arb_submit_bl(cdm_hw, req, i, + fifo_idx, hw_vaddr_ptr); + if (rc) + break; } } } @@ -971,6 +1077,8 @@ static void cam_hw_cdm_reset_cleanup( kfree(node); } core->bl_fifo[i].bl_tag = 0; + core->bl_fifo[i].last_bl_tag_done = -1; + core->bl_fifo[i].work_record = 0; } } @@ -985,14 +1093,22 @@ static void cam_hw_cdm_work(struct work_struct *work) if (payload) { cdm_hw = payload->hw; core = (struct cam_cdm *)cdm_hw->core_info; + if (payload->fifo_idx >= core->offsets->reg_data->num_bl_fifo) { + CAM_ERR(CAM_CDM, "Invalid fifo idx %d", + payload->fifo_idx); + kfree(payload); + return; + } CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); if (payload->irq_status & CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { struct cam_cdm_bl_cb_request_entry *node, *tnode; - CAM_DBG(CAM_CDM, "inline IRQ data=0x%x", - payload->irq_data); + CAM_DBG(CAM_CDM, "inline IRQ data=0x%x last tag: 0x%x", + payload->irq_data, + core->bl_fifo[payload->fifo_idx] + .last_bl_tag_done); if (payload->irq_data == 0xff) { CAM_INFO(CAM_CDM, "Debug genirq received"); @@ -1002,37 +1118,47 @@ static void cam_hw_cdm_work(struct work_struct *work) mutex_lock(&core->bl_fifo[payload->fifo_idx] .fifo_lock); - list_for_each_entry_safe(node, tnode, + + if (core->bl_fifo[payload->fifo_idx].work_record) + core->bl_fifo[payload->fifo_idx].work_record--; + + if (core->bl_fifo[payload->fifo_idx] + .last_bl_tag_done != + payload->irq_data) { + core->bl_fifo[payload->fifo_idx] + .last_bl_tag_done = + payload->irq_data; + list_for_each_entry_safe(node, tnode, &core->bl_fifo[payload->fifo_idx] .bl_request_list, entry) { - if (node->request_type == - CAM_HW_CDM_BL_CB_CLIENT) { - cam_cdm_notify_clients(cdm_hw, + 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_ERR(CAM_CDM, - "Invalid node=%pK %d", node, - node->request_type); + } else if (node->request_type == + 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; + } } - list_del_init(&node->entry); - if (node->bl_tag == payload->irq_data) { - kfree(node); - break; - } - kfree(node); + } else { + CAM_DBG(CAM_CDM, + "Skip GenIRQ, tag 0x%x fifo %d", + payload->irq_data, payload->fifo_idx); } mutex_unlock(&core->bl_fifo[payload->fifo_idx] .fifo_lock); } - if (payload->irq_status & - CAM_CDM_IRQ_STATUS_RST_DONE_MASK) { - CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); - complete(&core->reset_complete); - } if (payload->irq_status & CAM_CDM_IRQ_STATUS_BL_DONE_MASK) { if (test_bit(payload->fifo_idx, &core->cdm_status)) { @@ -1051,7 +1177,14 @@ static void cam_hw_cdm_work(struct work_struct *work) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); + /* + * First pause CDM, If it fails still proceed + * to dump debug info + */ + cam_hw_cdm_pause_core(cdm_hw, true); cam_hw_cdm_dump_core_debug_registers(cdm_hw); + /* Resume CDM back */ + cam_hw_cdm_pause_core(cdm_hw, false); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); @@ -1083,7 +1216,17 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, mutex_lock(&cdm_hw->hw_mutex); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); + if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { + /* + * First pause CDM, If it fails still proceed + * to dump debug info + */ + cam_hw_cdm_pause_core(cdm_hw, true); + cam_hw_cdm_dump_core_debug_registers(cdm_hw); + /* Resume CDM back */ + cam_hw_cdm_pause_core(cdm_hw, false); + } else + CAM_INFO(CAM_CDM, "CDM hw is power in off state"); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); mutex_unlock(&cdm_hw->hw_mutex); @@ -1109,7 +1252,12 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) int i; CAM_DBG(CAM_CDM, "Got irq"); - + spin_lock(&cdm_hw->hw_lock); + if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_DBG(CAM_CDM, "CDM is in power down state"); + spin_unlock(&cdm_hw->hw_lock); + return IRQ_HANDLED; + } for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { if (cam_cdm_read_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_status, @@ -1126,35 +1274,46 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[0]->irq_clear_cmd, 0x01)) - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd 0"); + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ clr cmd"); + if (cam_cdm_read_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->usr_data, + &user_data)) + CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ data"); + spin_unlock(&cdm_hw->hw_lock); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { if (!irq_status[i]) continue; + if (irq_status[i] & CAM_CDM_IRQ_STATUS_RST_DONE_MASK) { + cdm_core->rst_done_cnt++; + continue; + } + payload[i] = kzalloc(sizeof(struct cam_cdm_work_payload), GFP_ATOMIC); - if (!payload[i]) + if (!payload[i]) { + CAM_ERR(CAM_CDM, + "failed to allocate memory for fifo %d payload", + i); continue; + } if (irq_status[i] & CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { - if (cam_cdm_read_hw_reg(cdm_hw, - cdm_core->offsets->cmn_reg->usr_data, - &user_data)) { - CAM_ERR(CAM_CDM, - "Failed to read CDM HW IRQ data"); - kfree(payload[i]); - return IRQ_HANDLED; - } - payload[i]->irq_data = user_data >> (i * 0x8); + payload[i]->irq_data = (user_data >> (i * 0x8)) & + CAM_CDM_IRQ_STATUS_USR_DATA_MASK; if (payload[i]->irq_data == CAM_CDM_DBG_GEN_IRQ_USR_DATA) CAM_INFO(CAM_CDM, "Debug gen_irq received"); } + CAM_DBG(CAM_CDM, + "Rcvd of fifo %d userdata 0x%x tag 0x%x irq_stat 0x%x", + i, user_data, payload[i]->irq_data, irq_status[i]); + payload[i]->fifo_idx = i; payload[i]->irq_status = irq_status[i]; payload[i]->hw = cdm_hw; @@ -1162,10 +1321,9 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) INIT_WORK((struct work_struct *)&payload[i]->work, cam_hw_cdm_work); - trace_cam_log_event("CDM_DONE", "CDM_DONE_IRQ", + trace_cam_log_event("CDM_DONE", "CDM_DONE_IRQ", payload[i]->irq_status, cdm_hw->soc_info.index); - if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_clear, payload[i]->irq_status)) { @@ -1175,18 +1333,30 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) return IRQ_HANDLED; } - work_status = queue_work( + cdm_core->bl_fifo[i].work_record++; + work_status = queue_work( cdm_core->bl_fifo[i].work_queue, &payload[i]->work); if (work_status == false) { CAM_ERR(CAM_CDM, - "Failed to queue work for irq=0x%x", - payload[i]->irq_status); + "Failed to queue work for FIFO: %d irq=0x%x", + i, payload[i]->irq_status); kfree(payload[i]); } } - + if (cdm_core->rst_done_cnt == + cdm_core->offsets->reg_data->num_bl_fifo_irq) { + CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); + complete(&cdm_core->reset_complete); + } + if (cdm_core->rst_done_cnt && + cdm_core->rst_done_cnt != + cdm_core->offsets->reg_data->num_bl_fifo_irq) + CAM_INFO(CAM_CDM, + "Reset IRQ received for %d fifos instead of %d", + cdm_core->rst_done_cnt, + cdm_core->offsets->reg_data->num_bl_fifo_irq); return IRQ_HANDLED; } @@ -1254,16 +1424,24 @@ int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) struct cam_cdm *cdm_core = NULL; long time_left; int i, rc = -EIO; + int reset_val = 1; cdm_core = (struct cam_cdm *)cdm_hw->core_info; - set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); - reinit_completion(&cdm_core->reset_complete); - for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); + set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + cdm_core->rst_done_cnt = 0; + reinit_completion(&cdm_core->reset_complete); + + /* First pause CDM, If it fails still proceed to reset CDM HW */ + cam_hw_cdm_pause_core(cdm_hw, true); + usleep_range(1000, 1010); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + reset_val = reset_val | + (1 << (i + CAM_CDM_BL_FIFO_FLUSH_SHIFT)); if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_mask, 0x70003)) { @@ -1273,7 +1451,7 @@ int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) } if (cam_cdm_write_hw_reg(cdm_hw, - cdm_core->offsets->cmn_reg->rst_cmd, 0x9)) { + cdm_core->offsets->cmn_reg->rst_cmd, reset_val)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); goto end; } @@ -1318,16 +1496,21 @@ int cam_hw_cdm_handle_error_info( long time_left; int i, rc = -EIO, reset_hw_hdl = 0x0; uint32_t current_bl_data = 0, current_fifo = 0, current_tag = 0; + int reset_val = 1; cdm_core = (struct cam_cdm *)cdm_hw->core_info; - set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); - set_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); - reinit_completion(&cdm_core->reset_complete); - for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); + cdm_core->rst_done_cnt = 0; + reinit_completion(&cdm_core->reset_complete); + set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + set_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); + + /* First pause CDM, If it fails still proceed to dump debug info */ + cam_hw_cdm_pause_core(cdm_hw, true); + rc = cam_cdm_read_hw_reg(cdm_hw, cdm_core->offsets->cmn_reg->current_bl_len, ¤t_bl_data); @@ -1349,6 +1532,8 @@ int cam_hw_cdm_handle_error_info( cam_hw_cdm_dump_core_debug_registers(cdm_hw); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + reset_val = reset_val | + (1 << (i + CAM_CDM_BL_FIFO_FLUSH_SHIFT)); if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_mask, 0x70003)) { @@ -1358,7 +1543,7 @@ int cam_hw_cdm_handle_error_info( } if (cam_cdm_write_hw_reg(cdm_hw, - cdm_core->offsets->cmn_reg->rst_cmd, 0x9)) { + cdm_core->offsets->cmn_reg->rst_cmd, reset_val)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); goto end; } @@ -1437,14 +1622,38 @@ int cam_hw_cdm_handle_error( cdm_core = (struct cam_cdm *)cdm_hw->core_info; - /* First pause CDM, If it fails still proceed to dump debug info */ - cam_hw_cdm_enable_core(cdm_hw, false); - rc = cam_hw_cdm_handle_error_info(cdm_hw, handle); return rc; } +int cam_hw_cdm_hang_detect( + struct cam_hw_info *cdm_hw, + uint32_t handle) +{ + struct cam_cdm *cdm_core = NULL; + int i, rc = -1; + + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + if (cdm_core->bl_fifo[i].work_record) { + CAM_WARN(CAM_CDM, + "workqueue got delayed, work_record :%u", + cdm_core->bl_fifo[i].work_record); + rc = 0; + break; + } + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); + + return rc; +} + int cam_hw_cdm_get_cdm_config(struct cam_hw_info *cdm_hw) { struct cam_hw_soc_info *soc_info = NULL; @@ -1517,6 +1726,7 @@ int cam_hw_cdm_init(void *hw_priv, struct cam_hw_soc_info *soc_info = NULL; struct cam_cdm *cdm_core = NULL; int rc, i, reset_hw_hdl = 0x0; + unsigned long flags; if (!hw_priv) return -EINVAL; @@ -1530,6 +1740,9 @@ int cam_hw_cdm_init(void *hw_priv, CAM_ERR(CAM_CDM, "Enable platform failed"); goto end; } + spin_lock_irqsave(&cdm_hw->hw_lock, flags); + cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; + spin_unlock_irqrestore(&cdm_hw->hw_lock, flags); CAM_DBG(CAM_CDM, "Enable soc done"); @@ -1540,6 +1753,10 @@ int cam_hw_cdm_init(void *hw_priv, clear_bit(i, &cdm_core->cdm_status); reinit_completion(&cdm_core->bl_fifo[i].bl_complete); } + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + cdm_core->bl_fifo[i].last_bl_tag_done = -1; + cdm_core->bl_fifo[i].work_record = 0; + } rc = cam_hw_cdm_reset_hw(cdm_hw, reset_hw_hdl); @@ -1548,7 +1765,6 @@ int cam_hw_cdm_init(void *hw_priv, goto disable_return; } else { CAM_DBG(CAM_CDM, "CDM Init success"); - cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_mask, @@ -1559,6 +1775,9 @@ int cam_hw_cdm_init(void *hw_priv, disable_return: rc = -EIO; + spin_lock_irqsave(&cdm_hw->hw_lock, flags); + cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + spin_unlock_irqrestore(&cdm_hw->hw_lock, flags); cam_soc_util_disable_platform_resource(soc_info, true, true); end: return rc; @@ -1570,19 +1789,74 @@ int cam_hw_cdm_deinit(void *hw_priv, struct cam_hw_info *cdm_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_cdm *cdm_core = NULL; - int rc = 0; + struct cam_cdm_bl_cb_request_entry *node, *tnode; + int rc = 0, i; + uint32_t reset_val = 1; + long time_left; + unsigned long flags; if (!hw_priv) return -EINVAL; soc_info = &cdm_hw->soc_info; - cdm_core = cdm_hw->core_info; + cdm_core = (struct cam_cdm *)cdm_hw->core_info; + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); + + /*clear bl request */ + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + list_for_each_entry_safe(node, tnode, + &cdm_core->bl_fifo[i].bl_request_list, entry) { + list_del_init(&node->entry); + kfree(node); + } + } + + set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + cdm_core->rst_done_cnt = 0; + reinit_completion(&cdm_core->reset_complete); + + /* First pause CDM, If it fails still proceed to reset CDM HW */ + cam_hw_cdm_pause_core(cdm_hw, true); + usleep_range(1000, 1010); + + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + reset_val = reset_val | + (1 << (i + CAM_CDM_BL_FIFO_FLUSH_SHIFT)); + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->irq_reg[i]->irq_mask, + 0x70003)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask"); + } + } + + if (cam_cdm_write_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->rst_cmd, reset_val)) { + CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); + } + + CAM_DBG(CAM_CDM, "Waiting for CDM HW reset done"); + time_left = wait_for_completion_timeout(&cdm_core->reset_complete, + msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); + + if (time_left <= 0) { + rc = -ETIMEDOUT; + CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + } + + clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); + + spin_lock_irqsave(&cdm_hw->hw_lock, flags); + cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + spin_unlock_irqrestore(&cdm_hw->hw_lock, flags); rc = cam_soc_util_disable_platform_resource(soc_info, true, true); if (rc) { CAM_ERR(CAM_CDM, "disable platform failed"); } else { CAM_DBG(CAM_CDM, "CDM Deinit success"); - cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; } return rc; @@ -1653,6 +1927,7 @@ static int cam_hw_cdm_component_bind(struct device *dev, goto release_private_mem; } + cdm_core->rst_done_cnt = 0; init_completion(&cdm_core->reset_complete); cdm_hw_intf->hw_priv = cdm_hw; cdm_hw_intf->hw_ops.get_hw_caps = cam_cdm_get_caps; diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index 8f9c9ce0ecb4..8c7fcadc91e4 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -480,6 +480,33 @@ int cam_cdm_handle_error(uint32_t handle) } EXPORT_SYMBOL(cam_cdm_handle_error); +int cam_cdm_detect_hang_error(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_CMD_HANG_DETECT, + &handle, + sizeof(handle)); + } + put_cdm_mgr_refcount(); + + return rc; +} +EXPORT_SYMBOL(cam_cdm_detect_hang_error); + int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, uint32_t *index) diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index 37f1f1503ccd..58ffd4f8a0f9 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -280,4 +280,13 @@ int cam_cdm_handle_error(uint32_t handle); */ struct cam_cdm_utils_ops *cam_cdm_publish_ops(void); +/** + * @brief : API to detect hang in previously acquired CDM, + * this should be only performed only if the CDM is private. + * + * @handle : Input handle of the CDM to detect hang + * + * @return 0 on success + */ +int cam_cdm_detect_hang_error(uint32_t handle); #endif /* _CAM_CDM_API_H_ */ diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 936a5f7177ec..c7fa0c4fd60b 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -462,7 +462,7 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( if (soc_private->control_camnoc_axi_clk) { struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; uint64_t required_camnoc_bw = 0, intermediate_result = 0; - int32_t clk_rate = 0; + int64_t clk_rate = 0; for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) { tree_node = soc_private->tree_node[i]; @@ -511,7 +511,7 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( do_div(intermediate_result, soc_private->camnoc_bus_width); clk_rate = intermediate_result; - CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %d", + CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %lld", required_camnoc_bw, clk_rate); /* @@ -524,7 +524,7 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( rc = cam_soc_util_set_src_clk_rate(soc_info, clk_rate); if (rc) CAM_ERR(CAM_CPAS, - "Failed in setting camnoc axi clk %llu %d %d", + "Failed in setting camnoc axi clk %llu %lld %d", required_camnoc_bw, clk_rate, rc); cpas_core->applied_camnoc_axi_rate = clk_rate; diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 5bd654f44258..3cb820036408 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -24,6 +24,7 @@ #include "cpastop_v480_100.h" #include "cpastop_v580_100.h" #include "cpastop_v540_100.h" +#include "cpastop_v520_100.h" struct cam_camnoc_info *camnoc_info; @@ -86,6 +87,25 @@ static const uint32_t cam_cpas_hw_version_map 0, 0, }, + /* for camera_520 */ + { + CAM_CPAS_TITAN_520_V100, + 0, + 0, + 0, + 0, + 0, + + }, + /* for camera_540 */ + { + CAM_CPAS_TITAN_540_V100, + 0, + 0, + 0, + 0, + 0, + }, }; static int cam_cpas_translate_camera_cpas_version_id( @@ -113,6 +133,14 @@ static int cam_cpas_translate_camera_cpas_version_id( *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_480; break; + case CAM_CPAS_CAMERA_VERSION_520: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_520; + break; + + case CAM_CPAS_CAMERA_VERSION_540: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_540; + break; + case CAM_CPAS_CAMERA_VERSION_580: *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_580; break; @@ -716,6 +744,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_540_V100: camnoc_info = &cam540_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_520_V100: + camnoc_info = &cam520_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/cam_cpas/cpas_top/cpastop_v520_100.h b/drivers/cam_cpas/cpas_top/cpastop_v520_100.h new file mode 100644 index 000000000000..ec99574ebf10 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v520_100.h @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V520_100_H_ +#define _CPASTOP_V520_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v520_100_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v520_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 = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +static struct cam_camnoc_specific + cam_cpas_v520_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 = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x00000003, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x44443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66665555, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + .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_OPE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x00000033, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_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, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam520_cpas100_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam520_cpas100_camnoc_info = { + .specific = &cam_cpas_v520_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v520_100_camnoc_specific), + .irq_sbm = &cam_cpas_v520_100_irq_sbm, + .irq_err = &cam_cpas_v520_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v520_100_irq_err), + .err_logger = &cam520_cpas100_err_logger_offsets, + .errata_wa_list = NULL, +}; + +#endif /* _CPASTOP_V520_100_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index c13ac20e7b7b..9601166c2afe 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -41,6 +41,8 @@ enum cam_cpas_camera_version { CAM_CPAS_CAMERA_VERSION_170 = 0x00010700, CAM_CPAS_CAMERA_VERSION_175 = 0x00010705, CAM_CPAS_CAMERA_VERSION_480 = 0x00040800, + CAM_CPAS_CAMERA_VERSION_520 = 0x00050200, + CAM_CPAS_CAMERA_VERSION_540 = 0x00050400, CAM_CPAS_CAMERA_VERSION_580 = 0x00050800, CAM_CPAS_CAMERA_VERSION_MAX }; @@ -69,6 +71,8 @@ enum cam_cpas_camera_version_map_id { CAM_CPAS_CAMERA_VERSION_ID_175 = 0x2, CAM_CPAS_CAMERA_VERSION_ID_480 = 0x3, CAM_CPAS_CAMERA_VERSION_ID_580 = 0x4, + CAM_CPAS_CAMERA_VERSION_ID_520 = 0x5, + CAM_CPAS_CAMERA_VERSION_ID_540 = 0x6, CAM_CPAS_CAMERA_VERSION_ID_MAX }; @@ -103,6 +107,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_480_V100 = 0x480100, CAM_CPAS_TITAN_580_V100 = 0x580100, CAM_CPAS_TITAN_540_V100 = 0x540100, + CAM_CPAS_TITAN_520_V100 = 0x520100, CAM_CPAS_TITAN_MAX }; diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index afd42d23b9fb..6a5ec8482457 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _HFI_INTF_H_ diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index df4ae01d7ef2..200bfe6bc2b1 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HFI_REG_H_ diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 89a95aca62e1..b015d19d1e55 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index a05e44221af8..fd5c59fb47f1 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -26,6 +26,12 @@ */ #define CAM_ISP_CTX_RES_MAX 24 +/* + * Maximum configuration entry size - This is based on the + * worst case DUAL IFE use case plus some margin. + */ +#define CAM_ISP_CTX_CFG_MAX 25 + /* * Maximum entries in state monitoring array for error logging */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7e62810609fa..bfdc76f930d8 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4205,8 +4205,10 @@ static int cam_ife_mgr_reset_vfe_hw(struct cam_ife_hw_mgr *hw_mgr, vfe_reset_type = CAM_VFE_HW_RESET_HW; for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) { - if ((!hw_mgr->ife_devices[i]) || - (hw_idx != hw_mgr->ife_devices[i]->hw_idx)) + if (!hw_mgr->ife_devices[i]) + continue; + + if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) continue; CAM_DBG(CAM_ISP, "VFE (id = %d) reset", hw_idx); vfe_hw_intf = hw_mgr->ife_devices[i]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 02ca27f7f499..9d7ec3e03852 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -54,7 +54,8 @@ static int cam_tfe_mgr_regspace_data_cb(uint32_t reg_base_type, *soc_info_ptr = NULL; list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { - if (hw_mgr_res->res_id != CAM_ISP_HW_TFE_IN_CAMIF) + if ((hw_mgr_res->res_id != CAM_ISP_HW_TFE_IN_CAMIF) && + !ctx->is_rdi_only_context) continue; switch (reg_base_type) { @@ -117,9 +118,11 @@ static int cam_tfe_mgr_regspace_data_cb(uint32_t reg_base_type, static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx, struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf, - uint32_t meta_type) + uint32_t meta_type, + void *soc_dump_args, + bool user_triggered_dump) { - int rc = 0, i; + int rc = -EINVAL, i; if (!num_reg_dump_buf || !reg_dump_buf_desc) { CAM_DBG(CAM_ISP, @@ -141,8 +144,8 @@ static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx, ®_dump_buf_desc[i], ctx->applied_req_id, cam_tfe_mgr_regspace_data_cb, - NULL, - false); + soc_dump_args, + user_triggered_dump); if (rc) { CAM_ERR(CAM_ISP, "Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u", @@ -152,7 +155,7 @@ static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx, } } - return 0; + return rc; } static int cam_tfe_mgr_get_hw_caps(void *hw_mgr_priv, @@ -678,7 +681,7 @@ static void cam_tfe_hw_mgr_dump_all_ctx(void) list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (hw_mgr_res->hw_res[i]) + if (!hw_mgr_res->hw_res[i]) continue; CAM_INFO_RATE_LIMIT(CAM_ISP, @@ -693,7 +696,7 @@ static void cam_tfe_hw_mgr_dump_all_ctx(void) list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (hw_mgr_res->hw_res[i]) + if (!hw_mgr_res->hw_res[i]) continue; CAM_INFO_RATE_LIMIT(CAM_ISP, @@ -1232,7 +1235,7 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_csid_pxl( if (i == CAM_TFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) { CAM_ERR(CAM_ISP, - "Can not acquire tfe csid path resource %d", + "Can not acquire left tfe csid path resource %d", path_res_id); goto put_res; } @@ -1330,6 +1333,8 @@ acquire_successful: goto end; } csid_res_temp->hw_res[1] = csid_acquire.node_res; + tfe_ctx->slave_hw_idx = + csid_res_temp->hw_res[1]->hw_intf->hw_idx; CAM_DBG(CAM_ISP, "CSID right acquired success is_dual %d", in_port->usage_type); } @@ -1654,7 +1659,8 @@ static int cam_tfe_mgr_acquire_hw_for_ctx( in_port); if (rc) { CAM_ERR(CAM_ISP, - "Acquire TFE CSID IPP resource Failed"); + "Acquire TFE CSID IPP resource Failed dual:%d", + in_port->usage_type); goto err; } } @@ -1664,7 +1670,8 @@ static int cam_tfe_mgr_acquire_hw_for_ctx( rc = cam_tfe_hw_mgr_acquire_res_tfe_csid_rdi(tfe_ctx, in_port); if (rc) { CAM_ERR(CAM_ISP, - "Acquire TFE CSID RDI resource Failed"); + "Acquire TFE CSID RDI resource Failed dual:%d", + in_port->usage_type); goto err; } } @@ -1672,14 +1679,15 @@ static int cam_tfe_mgr_acquire_hw_for_ctx( rc = cam_tfe_hw_mgr_acquire_res_tfe_in(tfe_ctx, in_port, pdaf_enable); if (rc) { CAM_ERR(CAM_ISP, - "Acquire TFE IN resource Failed"); + "Acquire TFE IN resource Failed dual:%d", in_port->usage_type); goto err; } CAM_DBG(CAM_ISP, "Acquiring TFE OUT resource..."); rc = cam_tfe_hw_mgr_acquire_res_tfe_out(tfe_ctx, in_port); if (rc) { - CAM_ERR(CAM_ISP, "Acquire TFE OUT resource Failed"); + CAM_ERR(CAM_ISP, "Acquire TFE OUT resource Failed dual:%d", + in_port->usage_type); goto err; } @@ -1713,7 +1721,8 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, cam_tfe_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, hw_update_data->num_reg_dump_buf, - CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST); + CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST, + NULL, false); CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", handle, userdata, status, cookie, ctx->ctx_index); @@ -1933,6 +1942,7 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->ctxt_to_hw_map = tfe_ctx; tfe_ctx->ctx_in_use = 1; + tfe_ctx->num_reg_dump_buf = 0; cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx); @@ -2697,6 +2707,9 @@ static int cam_tfe_mgr_reset_tfe_hw(struct cam_tfe_hw_mgr *hw_mgr, tfe_reset_type = CAM_TFE_HW_RESET_HW; for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (!hw_mgr->tfe_devices[i]) + continue; + if (hw_idx != hw_mgr->tfe_devices[i]->hw_idx) continue; CAM_DBG(CAM_ISP, "TFE (id = %d) reset", hw_idx); @@ -2985,6 +2998,159 @@ static int cam_tfe_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_tfe_mgr_user_dump_hw( + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_hw_dump_args *dump_args) +{ + int rc = 0; + struct cam_hw_soc_dump_args soc_dump_args; + + if (!tfe_ctx || !dump_args) { + CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK", + tfe_ctx, dump_args); + return -EINVAL; + } + soc_dump_args.buf_handle = dump_args->buf_handle; + soc_dump_args.request_id = dump_args->request_id; + soc_dump_args.offset = dump_args->offset; + + rc = cam_tfe_mgr_handle_reg_dump(tfe_ctx, + tfe_ctx->reg_dump_buf_desc, + tfe_ctx->num_reg_dump_buf, + CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, + &soc_dump_args, + true); + if (rc) { + CAM_DBG(CAM_ISP, + "Dump failed req: %lld handle %u offset %u rc %d", + dump_args->request_id, + dump_args->buf_handle, + dump_args->offset, + rc); + return rc; + } + dump_args->offset = soc_dump_args.offset; + return rc; +} + +static int cam_tfe_mgr_dump(void *hw_mgr_priv, void *args) +{ + + struct cam_isp_hw_dump_args isp_hw_dump_args; + struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_tfe_hw_mgr_ctx *tfe_ctx = (struct cam_tfe_hw_mgr_ctx *) + dump_args->ctxt_to_hw_map; + int i; + int rc = 0; + + /* for some targets, information about the TFE registers to be dumped + * is already submitted with the hw manager. In this case, we + * can dump just the related registers and skip going to core files. + * If dump to this buffer falis due to any reason, fallback to dump + * to the LDAR buffer + */ + isp_hw_dump_args.is_dump_all = true; + if (tfe_ctx->num_reg_dump_buf) { + rc = cam_tfe_mgr_user_dump_hw(tfe_ctx, dump_args); + if (!rc) + isp_hw_dump_args.is_dump_all = false; + } + + rc = cam_mem_get_cpu_buf(dump_args->buf_handle, + &isp_hw_dump_args.cpu_addr, + &isp_hw_dump_args.buf_len); + + if (rc) { + CAM_ERR(CAM_ISP, "Invalid handle %u rc %d", + dump_args->buf_handle, rc); + return rc; + } + + isp_hw_dump_args.offset = dump_args->offset; + isp_hw_dump_args.req_id = dump_args->request_id; + + list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_csid, 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; + switch (hw_mgr_res->hw_res[i]->res_id) { + case CAM_TFE_CSID_PATH_RES_RDI_0: + case CAM_TFE_CSID_PATH_RES_RDI_1: + case CAM_TFE_CSID_PATH_RES_RDI_2: + if (tfe_ctx->is_rdi_only_context && + hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + + case CAM_TFE_CSID_PATH_RES_IPP: + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + default: + CAM_DBG(CAM_ISP, "not a valid res %d", + hw_mgr_res->res_id); + break; + } + } + } + + list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_in, 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; + switch (hw_mgr_res->hw_res[i]->res_id) { + case CAM_ISP_HW_TFE_IN_RDI0: + case CAM_ISP_HW_TFE_IN_RDI1: + case CAM_ISP_HW_TFE_IN_RDI2: + if (tfe_ctx->is_rdi_only_context && + hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + + case CAM_ISP_HW_TFE_IN_CAMIF: + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_HW, + &isp_hw_dump_args, + sizeof(struct + cam_isp_hw_dump_args)); + } + break; + default: + CAM_DBG(CAM_ISP, "not a valid res %d", + hw_mgr_res->res_id); + break; + } + } + } + dump_args->offset = isp_hw_dump_args.offset; + CAM_DBG(CAM_ISP, "offset %u", dump_args->offset); + return rc; +} + static int cam_tfe_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) { struct cam_tfe_hw_mgr *hw_mgr = hw_mgr_priv; @@ -3023,6 +3189,7 @@ static int cam_tfe_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) } } + atomic_set(&ctx->overflow_pending, 0); end: return rc; } @@ -3072,6 +3239,7 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, ctx->init_done = false; ctx->is_dual = false; ctx->is_tpg = false; + ctx->num_reg_dump_buf = 0; ctx->res_list_tpg.res_type = CAM_ISP_RESOURCE_MAX; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { @@ -3463,7 +3631,8 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, return -EINVAL; } - if (bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) { + if ((bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) || + !bw_config->num_paths) { CAM_ERR(CAM_ISP, "Invalid num paths %d", bw_config->num_paths); return -EINVAL; @@ -3790,6 +3959,7 @@ int cam_tfe_add_command_buffers( break; case CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH: case CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR: + case CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST: if (split_id == CAM_ISP_HW_SPLIT_LEFT) { if (prepare->num_reg_dump_buf >= CAM_REG_DUMP_MAX_BUF_ENTRIES) { @@ -3934,24 +4104,50 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, fill_fence = false; } - ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; - if ((ctx->num_reg_dump_buf) && (ctx->num_reg_dump_buf < - CAM_REG_DUMP_MAX_BUF_ENTRIES)) { - memcpy(ctx->reg_dump_buf_desc, - prepare->reg_dump_buf_desc, - sizeof(struct cam_cmd_buf_desc) * - prepare->num_reg_dump_buf); - } + CAM_DBG(CAM_ISP, + "num_reg_dump_buf=%d ope code:%d", + prepare->num_reg_dump_buf, prepare->packet->header.op_code); /* reg update will be done later for the initial configure */ if (((prepare->packet->header.op_code) & 0xF) == CAM_ISP_PACKET_INIT_DEV) { prepare_hw_data->packet_opcode_type = CAM_ISP_TFE_PACKET_INIT_DEV; + + if ((!prepare->num_reg_dump_buf) || (prepare->num_reg_dump_buf > + CAM_REG_DUMP_MAX_BUF_ENTRIES)) + goto end; + + if (!ctx->num_reg_dump_buf) { + ctx->num_reg_dump_buf = + prepare->num_reg_dump_buf; + memcpy(ctx->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare->num_reg_dump_buf); + } else { + prepare_hw_data->num_reg_dump_buf = + prepare->num_reg_dump_buf; + memcpy(prepare_hw_data->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare_hw_data->num_reg_dump_buf); + } + goto end; - } else + } else { prepare_hw_data->packet_opcode_type = CAM_ISP_TFE_PACKET_CONFIG_DEV; + prepare_hw_data->num_reg_dump_buf = prepare->num_reg_dump_buf; + if ((prepare_hw_data->num_reg_dump_buf) && + (prepare_hw_data->num_reg_dump_buf < + CAM_REG_DUMP_MAX_BUF_ENTRIES)) { + memcpy(prepare_hw_data->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, + sizeof(struct cam_cmd_buf_desc) * + prepare_hw_data->num_reg_dump_buf); + } + } /* add reg update commands */ for (i = 0; i < ctx->num_base; i++) { @@ -4142,6 +4338,7 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) struct cam_tfe_hw_mgr_ctx *ctx = (struct cam_tfe_hw_mgr_ctx *) hw_cmd_args->ctxt_to_hw_map; struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; + struct cam_packet *packet; if (!hw_mgr_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -4180,6 +4377,17 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) else isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_PIX; break; + case CAM_ISP_HW_MGR_GET_PACKET_OPCODE: + packet = (struct cam_packet *) + isp_hw_cmd_args->cmd_data; + if ((packet->header.op_code & 0xF) == + CAM_ISP_TFE_PACKET_INIT_DEV) + isp_hw_cmd_args->u.packet_op_code = + CAM_ISP_TFE_PACKET_INIT_DEV; + else + isp_hw_cmd_args->u.packet_op_code = + CAM_ISP_TFE_PACKET_CONFIG_DEV; + break; default: CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", hw_cmd_args->cmd_type); @@ -4203,11 +4411,12 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, - CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH); + CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH, + NULL, false); if (rc) { CAM_ERR(CAM_ISP, - "Reg dump on flush failed req id: %llu rc: %d", - ctx->applied_req_id, rc); + "Reg dump on flush failed req id: %llu num_reg_dump:0x%x rc: %d", + ctx->applied_req_id, ctx->num_reg_dump_buf, rc); return rc; } @@ -4219,15 +4428,15 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) ctx->last_dump_err_req_id = ctx->applied_req_id; rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, ctx->num_reg_dump_buf, - CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR); + CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR, + NULL, false); if (rc) { CAM_ERR(CAM_ISP, - "Reg dump on error failed req id: %llu rc: %d", - ctx->applied_req_id, rc); + "Reg dump on error failed req id:%llu num_reg_dump:0x%x rc: %d", + ctx->applied_req_id, ctx->num_reg_dump_buf, rc); return rc; } break; - default: CAM_ERR(CAM_ISP, "Invalid cmd"); } @@ -4695,12 +4904,15 @@ static int cam_tfe_hw_mgr_check_irq_for_dual_tfe( { int32_t rc = -EINVAL; uint32_t *event_cnt = NULL; - uint32_t core_idx0 = 0; - uint32_t core_idx1 = 1; + uint32_t master_hw_idx; + uint32_t slave_hw_idx; if (!tfe_hw_mgr_ctx->is_dual) return 0; + master_hw_idx = tfe_hw_mgr_ctx->master_hw_idx; + slave_hw_idx = tfe_hw_mgr_ctx->slave_hw_idx; + switch (hw_event_type) { case CAM_ISP_HW_EVENT_SOF: event_cnt = tfe_hw_mgr_ctx->sof_cnt; @@ -4715,19 +4927,18 @@ static int cam_tfe_hw_mgr_check_irq_for_dual_tfe( return 0; } - if (event_cnt[core_idx0] == event_cnt[core_idx1]) { + if (event_cnt[master_hw_idx] == event_cnt[slave_hw_idx]) { - event_cnt[core_idx0] = 0; - event_cnt[core_idx1] = 0; + event_cnt[master_hw_idx] = 0; + event_cnt[slave_hw_idx] = 0; - rc = 0; - return rc; + return 0; } - if ((event_cnt[core_idx0] && - (event_cnt[core_idx0] - event_cnt[core_idx1] > 1)) || - (event_cnt[core_idx1] && - (event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) { + if ((event_cnt[master_hw_idx] && + (event_cnt[master_hw_idx] - event_cnt[slave_hw_idx] > 1)) || + (event_cnt[slave_hw_idx] && + (event_cnt[slave_hw_idx] - event_cnt[master_hw_idx] > 1))) { if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt > 10) { rc = -1; @@ -4735,15 +4946,15 @@ static int cam_tfe_hw_mgr_check_irq_for_dual_tfe( } CAM_ERR_RATE_LIMIT(CAM_ISP, - "One TFE could not generate hw event %d id0:%d id1:%d", - hw_event_type, event_cnt[core_idx0], - event_cnt[core_idx1]); - if (event_cnt[core_idx0] >= 2) { - event_cnt[core_idx0]--; + "One TFE could not generate hw event %d master id :%d slave id:%d", + hw_event_type, event_cnt[master_hw_idx], + event_cnt[slave_hw_idx]); + if (event_cnt[master_hw_idx] >= 2) { + event_cnt[master_hw_idx]--; tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; } - if (event_cnt[core_idx1] >= 2) { - event_cnt[core_idx1]--; + if (event_cnt[slave_hw_idx] >= 2) { + event_cnt[slave_hw_idx]--; tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; } @@ -5078,7 +5289,7 @@ static int cam_tfe_hw_mgr_debug_register(void) goto err; } - if (!debugfs_create_bool("enable_reg_dump", + if (!debugfs_create_u32("enable_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, &g_tfe_hw_mgr.debug_cfg.enable_reg_dump)) { @@ -5094,7 +5305,7 @@ static int cam_tfe_hw_mgr_debug_register(void) goto err; } - if (!debugfs_create_bool("per_req_reg_dump", + if (!debugfs_create_u32("per_req_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump)) { @@ -5285,6 +5496,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_config = cam_tfe_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_tfe_mgr_cmd; hw_mgr_intf->hw_reset = cam_tfe_mgr_reset; + hw_mgr_intf->hw_dump = cam_tfe_mgr_dump; if (iommu_hdl) *iommu_hdl = g_tfe_hw_mgr.mgr_common.img_iommu_hdl; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 8aefaa7acf3b..5b9ca51365a7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -37,8 +37,8 @@ struct cam_tfe_hw_mgr_debug { uint64_t csid_debug; uint32_t enable_recovery; uint32_t camif_debug; - bool enable_reg_dump; - bool per_req_reg_dump; + uint32_t enable_reg_dump; + uint32_t per_req_reg_dump; }; /** @@ -79,6 +79,7 @@ struct cam_tfe_hw_mgr_debug { * @is_dual indicate whether context is in dual TFE mode * @is_tpg indicate whether context use tpg * @master_hw_idx master hardware index in dual tfe case + * @slave_hw_idx slave hardware index in dual tfe case * @dual_tfe_irq_mismatch_cnt irq mismatch count value per core, used for * dual TFE */ @@ -122,6 +123,7 @@ struct cam_tfe_hw_mgr_ctx { bool is_dual; bool is_tpg; uint32_t master_hw_idx; + uint32_t slave_hw_idx; uint32_t dual_tfe_irq_mismatch_cnt; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 25697c9d64f3..22a75b91203a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -278,6 +278,7 @@ struct cam_isp_hw_dual_isp_update_args { * @ buf_len: buf len * @ offset: offset of buffer * @ ctxt_to_hw_map: ctx to hw map + * @ is_dump_all: flag to indicate if all information or just bw/clk rate */ struct cam_isp_hw_dump_args { uint64_t req_id; @@ -285,6 +286,7 @@ struct cam_isp_hw_dump_args { size_t buf_len; size_t offset; void *ctxt_to_hw_map; + bool is_dump_all; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index e1925e9d1354..ddad24cd23df 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1275,6 +1275,18 @@ static int cam_tfe_csid_disable_pxl_path( pxl_reg->csid_pxl_ctrl_addr); } + if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE && + stop_cmd == CAM_TFE_CSID_HALT_IMMEDIATELY) { + /* configure Halt for slave */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val &= ~0xF; + val |= stop_cmd; + val |= (TFE_CSID_HALT_MODE_MASTER << 2); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + } + return rc; } @@ -1822,6 +1834,10 @@ static int cam_tfe_csid_reset_retain_sw_reg( struct cam_hw_soc_info *soc_info; soc_info = &csid_hw->hw_info->soc_info; + + /* Mask top interrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->cmn_reg->csid_top_irq_mask_addr); /* clear the top interrupt first */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_clear_addr); @@ -1841,7 +1857,6 @@ static int cam_tfe_csid_reset_retain_sw_reg( status = cam_io_r(soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_status_addr); CAM_DBG(CAM_ISP, "Status reg %d", status); - rc = 0; } else { CAM_DBG(CAM_ISP, "CSID:%d hw reset completed %d", csid_hw->hw_intf->hw_idx, rc); @@ -1875,6 +1890,7 @@ static int cam_tfe_csid_init_hw(void *hw_priv, csid_hw_info = (struct cam_hw_info *)hw_priv; csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; res = (struct cam_isp_resource_node *)init_args; + csid_reg = csid_hw->csid_info->csid_reg; if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) { CAM_ERR(CAM_ISP, "CSID:%d Invalid res type state %d", @@ -1883,8 +1899,6 @@ static int cam_tfe_csid_init_hw(void *hw_priv, return -EINVAL; } - csid_reg = csid_hw->csid_info->csid_reg; - mutex_lock(&csid_hw->hw_info->hw_mutex); if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { @@ -1947,19 +1961,18 @@ static int cam_tfe_csid_deinit_hw(void *hw_priv, return -EINVAL; } + CAM_DBG(CAM_ISP, "Enter"); res = (struct cam_isp_resource_node *)deinit_args; csid_hw_info = (struct cam_hw_info *)hw_priv; csid_hw = (struct cam_tfe_csid_hw *)csid_hw_info->core_info; - if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH) { + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) { CAM_ERR(CAM_ISP, "CSID:%d Invalid Res type %d", csid_hw->hw_intf->hw_idx, res->res_type); return -EINVAL; } - CAM_DBG(CAM_ISP, "Enter"); - mutex_lock(&csid_hw->hw_info->hw_mutex); if (res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in De-init state", @@ -2287,6 +2300,106 @@ static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, return 0; } +static int cam_tfe_csid_dump_hw( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + int i; + uint8_t *dst; + uint32_t *addr, *start; + uint64_t *clk_addr, *clk_start; + uint32_t min_len; + uint32_t num_reg; + uint32_t reg_size = 0; + size_t remain_len; + struct cam_isp_hw_dump_header *hdr; + struct cam_isp_hw_dump_args *dump_args = + (struct cam_isp_hw_dump_args *)cmd_args; + struct cam_hw_soc_info *soc_info; + + if (!dump_args) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + if (!dump_args->cpu_addr || !dump_args->buf_len) { + CAM_ERR(CAM_ISP, + "Invalid params %pK %zu", + (void *)dump_args->cpu_addr, + dump_args->buf_len); + return -EINVAL; + } + + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_ISP, + "Dump offset overshoot offset %zu buf_len %zu", + dump_args->offset, dump_args->buf_len); + return -ENOSPC; + } + + soc_info = &csid_hw->hw_info->soc_info; + if (dump_args->is_dump_all) + reg_size = soc_info->reg_map[0].size; + + min_len = reg_size + + sizeof(struct cam_isp_hw_dump_header) + + (sizeof(uint32_t) * CAM_TFE_CSID_DUMP_MISC_NUM_WORDS); + remain_len = dump_args->buf_len - dump_args->offset; + + if (remain_len < min_len) { + CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu, min %u", + remain_len, min_len); + return -ENOSPC; + } + + mutex_lock(&csid_hw->hw_info->hw_mutex); + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid HW State:%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return -EINVAL; + } + + if (!dump_args->is_dump_all) + goto dump_bw; + + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "CSID_REG:"); + addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header)); + start = addr; + num_reg = soc_info->reg_map[0].size/4; + hdr->word_size = sizeof(uint32_t); + *addr = soc_info->index; + addr++; + + for (i = 0; i < num_reg; i++) { + addr[0] = soc_info->mem_block[0]->start + (i*4); + addr[1] = cam_io_r(soc_info->reg_map[0].mem_base + + (i*4)); + addr += 2; + } + + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); +dump_bw: + dst = (char *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "CSID_CLK_RATE:"); + clk_addr = (uint64_t *)(dst + + sizeof(struct cam_isp_hw_dump_header)); + clk_start = clk_addr; + hdr->word_size = sizeof(uint64_t); + *clk_addr++ = csid_hw->clk_rate; + hdr->size = hdr->word_size * (clk_addr - clk_start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + CAM_DBG(CAM_ISP, "offset %zu", dump_args->offset); + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return 0; +} + static int cam_tfe_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -2318,6 +2431,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_TFE_CSID_CMD_GET_REG_DUMP: rc = cam_tfe_csid_get_regdump(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_DUMP_HW: + rc = cam_tfe_csid_dump_hw(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -2335,7 +2451,7 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) const struct cam_tfe_csid_reg_offset *csid_reg; const struct cam_tfe_csid_csi2_rx_reg_offset *csi2_reg; uint32_t irq_status[TFE_CSID_IRQ_REG_MAX]; - bool fatal_err_detected = false; + bool fatal_err_detected = false, is_error_irq = false; uint32_t sof_irq_debug_en = 0; unsigned long flags; uint32_t i, val; @@ -2392,14 +2508,6 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); - CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", - csid_hw->hw_intf->hw_idx, irq_status[TFE_CSID_IRQ_REG_TOP], - irq_status[TFE_CSID_IRQ_REG_RX], - irq_status[TFE_CSID_IRQ_REG_IPP], - irq_status[TFE_CSID_IRQ_REG_RDI0], - irq_status[TFE_CSID_IRQ_REG_RDI1], - irq_status[TFE_CSID_IRQ_REG_RDI2]); /* Software register reset complete*/ if (irq_status[TFE_CSID_IRQ_REG_TOP]) @@ -2446,25 +2554,29 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) TFE_CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) csid_hw->error_irq_count++; + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_CRC) + is_error_irq = true; + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_ECC) + is_error_irq = true; + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + TFE_CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) + is_error_irq = true; } spin_unlock_irqrestore(&csid_hw->spin_lock, flags); + if (csid_hw->error_irq_count || fatal_err_detected) + is_error_irq = true; + if (csid_hw->error_irq_count > CAM_TFE_CSID_MAX_IRQ_ERROR_COUNT) { fatal_err_detected = true; csid_hw->error_irq_count = 0; } - CAM_INFO(CAM_ISP, - "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", - csid_hw->hw_intf->hw_idx, - irq_status[TFE_CSID_IRQ_REG_TOP], - irq_status[TFE_CSID_IRQ_REG_RX], - irq_status[TFE_CSID_IRQ_REG_IPP], - irq_status[TFE_CSID_IRQ_REG_RDI0], - irq_status[TFE_CSID_IRQ_REG_RDI1], - irq_status[TFE_CSID_IRQ_REG_RDI2]); - if (fatal_err_detected) { /* Reset the Rx CFG registers */ cam_io_w_mb(0, soc_info->reg_map[0].mem_base + @@ -2580,6 +2692,23 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); } + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_RST_IRQ_LOG) { + + if (irq_status[TFE_CSID_IRQ_REG_IPP] & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID IPP reset complete"); + + if (irq_status[TFE_CSID_IRQ_REG_TOP]) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID TOP reset complete"); + + if (irq_status[TFE_CSID_IRQ_REG_RX] & + BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID RX reset complete"); + } + /* read the IPP errors */ if (csid_hw->pxl_pipe_enable) { /* IPP reset done bit */ @@ -2611,10 +2740,24 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) cam_io_w_mb(CAM_TFE_CSID_HALT_IMMEDIATELY, soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_ctrl_addr); + is_error_irq = true; } + + if (irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION) + is_error_irq = true; + } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + + if ((irq_status[i] & + BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) && + (csid_hw->csid_debug & + TFE_CSID_DEBUG_ENABLE_RST_IRQ_LOG)) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID RDI%d reset complete", i); + if (irq_status[i] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i); @@ -2637,12 +2780,29 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) if (irq_status[i] & TFE_CSID_PATH_ERROR_FIFO_OVERFLOW) { /* Stop RDI path immediately */ + is_error_irq = true; cam_io_w_mb(CAM_TFE_CSID_HALT_IMMEDIATELY, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); } + + if ((irq_status[i] & TFE_CSID_PATH_RDI_OVERFLOW_IRQ) || + (irq_status[i] & + TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION)) + is_error_irq = true; } + if (is_error_irq) + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x", + csid_hw->hw_intf->hw_idx, + irq_status[TFE_CSID_IRQ_REG_TOP], + irq_status[TFE_CSID_IRQ_REG_RX], + irq_status[TFE_CSID_IRQ_REG_IPP], + irq_status[TFE_CSID_IRQ_REG_RDI0], + irq_status[TFE_CSID_IRQ_REG_RDI1], + irq_status[TFE_CSID_IRQ_REG_RDI2]); + if (csid_hw->irq_debug_cnt >= CAM_TFE_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_tfe_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); csid_hw->irq_debug_cnt = 0; @@ -2734,7 +2894,15 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, csid_reg->cmn_reg->top_tfe2_fuse_reg); if (val) { CAM_INFO(CAM_ISP, "TFE 2 is not supported by hardware"); - rc = -EINVAL; + + rc = cam_tfe_csid_disable_soc_resources( + &tfe_csid_hw->hw_info->soc_info); + if (rc) + CAM_ERR(CAM_ISP, + "CSID:%d Disable CSID SOC failed", + tfe_csid_hw->hw_intf->hw_idx); + else + rc = -EINVAL; goto err; } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index 1e23f2aa958c..fc0b72677a58 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -12,6 +12,12 @@ #define CAM_TFE_CSID_CID_MAX 4 +/* Each word is taken as uint32_t, for dumping uint64_t count as 2 words + * 1. soc_index + * 2. clk_rate --> uint64_t -> 2 words + */ +#define CAM_TFE_CSID_DUMP_MISC_NUM_WORDS 3 + #define TFE_CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED BIT(0) #define TFE_CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED BIT(1) #define TFE_CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED BIT(2) @@ -65,6 +71,7 @@ #define TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6) #define TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7) #define TFE_CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) +#define TFE_CSID_DEBUG_ENABLE_RST_IRQ_LOG BIT(9) /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_tfe_csid_path_halt_mode { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index 229f7563070c..d22836edc951 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -66,6 +66,7 @@ static struct cam_tfe_camif_reg_data tfe530_camif_reg_data = { .extern_reg_update_shift = 0x0, .camif_pd_rdi2_src_sel_shift = 0x2, .dual_tfe_sync_sel_shift = 18, + .delay_line_en_shift = 8, .pixel_pattern_shift = 24, .pixel_pattern_mask = 0x7000000, .module_enable_shift = 0, @@ -202,6 +203,65 @@ static struct cam_tfe_rdi_reg_data tfe530_rdi2_reg_data = { .enable_diagnostic_hw = 0x1, }; +static struct cam_tfe_clc_hw_status tfe530_clc_hw_info[CAM_TFE_MAX_CLC] = { + { + .name = "CLC_CAMIF", + .hw_status_reg = 0x1204, + }, + { + .name = "CLC_RDI0_CAMIF", + .hw_status_reg = 0x1404, + }, + { + .name = "CLC_RDI1_CAMIF", + .hw_status_reg = 0x1604, + }, + { + .name = "CLC_RDI2_CAMIF", + .hw_status_reg = 0x1804, + }, + { + .name = "CLC_CHANNEL_GAIN", + .hw_status_reg = 0x2604, + }, + { + .name = "CLC_LENS_ROLL_OFF", + .hw_status_reg = 0x2804, + }, + { + .name = "CLC_WB_BDS", + .hw_status_reg = 0x2A04, + }, + { + .name = "CLC_STATS_BHIST", + .hw_status_reg = 0x2C04, + }, + { + .name = "CLC_STATS_TINTLESS_BG", + .hw_status_reg = 0x2E04, + }, + { + .name = "CLC_STATS_BAF", + .hw_status_reg = 0x3004, + }, + { + .name = "CLC_STATS_AWB_BG", + .hw_status_reg = 0x3204, + }, + { + .name = "CLC_STATS_AEC_BG", + .hw_status_reg = 0x3404, + }, + { + .name = "CLC_STATS_RAW_OUT", + .hw_status_reg = 0x3604, + }, + { + .name = "CLC_STATS_CROP_POST_BDS", + .hw_status_reg = 0x3804, + }, +}; + static struct cam_tfe_top_hw_info tfe530_top_hw_info = { .common_reg = &tfe530_top_commong_reg, .camif_hw_info = { @@ -385,6 +445,9 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { 0x00001A2C, }, .irq_cmd = 0x00001A30, + .cons_violation_shift = 28, + .violation_shift = 30, + .image_size_violation = 31, }, .num_client = CAM_TFE_BUS_MAX_CLIENTS, .bus_client_reg = { @@ -414,6 +477,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x00001C7C, .debug_status_1 = 0x00001C80, .comp_group = CAM_TFE_BUS_COMP_GRP_0, + .client_name = "BAYER", }, /* BUS Client 1 IDEAL RAW*/ { @@ -441,6 +505,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x00001D7C, .debug_status_1 = 0x00001D80, .comp_group = CAM_TFE_BUS_COMP_GRP_1, + .client_name = "IDEAL_RAW", }, /* BUS Client 2 Stats BE Tintless */ { @@ -468,6 +533,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x00001E7C, .debug_status_1 = 0x00001E80, .comp_group = CAM_TFE_BUS_COMP_GRP_2, + .client_name = "STATS BE TINTLESS", }, /* BUS Client 3 Stats Bhist */ { @@ -495,6 +561,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x00001F7C, .debug_status_1 = 0x00001F80, .comp_group = CAM_TFE_BUS_COMP_GRP_2, + .client_name = "STATS BHIST", }, /* BUS Client 4 Stats AWB BG */ { @@ -522,6 +589,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x0000207C, .debug_status_1 = 0x00002080, .comp_group = CAM_TFE_BUS_COMP_GRP_3, + .client_name = "STATS AWB BG", }, /* BUS Client 5 Stats AEC BG */ { @@ -549,6 +617,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x0000217C, .debug_status_1 = 0x00002180, .comp_group = CAM_TFE_BUS_COMP_GRP_3, + .client_name = "STATS AEC BG", }, /* BUS Client 6 Stats BAF */ { @@ -576,6 +645,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x0000227C, .debug_status_1 = 0x00002280, .comp_group = CAM_TFE_BUS_COMP_GRP_4, + .client_name = "STATS BAF", }, /* BUS Client 7 RDI0 */ { @@ -603,6 +673,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x0000237C, .debug_status_1 = 0x00002380, .comp_group = CAM_TFE_BUS_COMP_GRP_5, + .client_name = "RDI0", }, /* BUS Client 8 RDI1 */ { @@ -630,6 +701,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x0000247C, .debug_status_1 = 0x00002480, .comp_group = CAM_TFE_BUS_COMP_GRP_6, + .client_name = "RDI1", }, /* BUS Client 9 PDAF/RDI2*/ { @@ -657,6 +729,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .debug_status_0 = 0x0000257C, .debug_status_1 = 0x00002580, .comp_group = CAM_TFE_BUS_COMP_GRP_7, + .client_name = "RDI2/PADF", }, }, .num_out = CAM_TFE_BUS_TFE_OUT_MAX, @@ -800,9 +873,14 @@ struct cam_tfe_hw_info cam_tfe530 = { .bus_reg_irq_mask = { 0x00000002, 0x00000000, + }, + .bus_error_irq_mask = { + 0xC0000000, 0x00000000, }, + .num_clc = 14, + .clc_hw_status_info = tfe530_clc_hw_info, .bus_version = CAM_TFE_BUS_1_0, .bus_hw_info = &tfe530_bus_hw_info, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 36980990f8af..01ffb90d7461 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -87,6 +87,7 @@ struct cam_tfe_bus_wm_resource_data { uint32_t format; uint32_t pack_fmt; uint32_t burst_len; + uint32_t mode; uint32_t irq_subsample_period; uint32_t irq_subsample_pattern; @@ -95,6 +96,10 @@ struct cam_tfe_bus_wm_resource_data { uint32_t en_cfg; uint32_t is_dual; + + uint32_t acquired_width; + uint32_t acquired_height; + uint32_t acquired_stride; }; struct cam_tfe_bus_comp_grp_data { @@ -449,6 +454,137 @@ static enum cam_tfe_bus_packer_format } } +static int cam_tfe_bus_acquire_rdi_wm( + struct cam_tfe_bus_wm_resource_data *rsrc_data) +{ + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_6: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 6, 64) / 64; + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_PLAIN8: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 8, 64) / 64; + + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + case CAM_FORMAT_MIPI_RAW_10: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 10, 64) / 64; + + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + case CAM_FORMAT_MIPI_RAW_12: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 12, 64) / 64; + + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + case CAM_FORMAT_MIPI_RAW_14: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 14, 64) / 64; + + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_PLAIN16_16: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 16, 64) / 64; + + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + + case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PLAIN64: + rsrc_data->pack_fmt = 0xA; + if (rsrc_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE) { + rsrc_data->width = + ALIGNUP(rsrc_data->width * 64, 64) / 64; + + rsrc_data->en_cfg = 0x1; + } else { + rsrc_data->width = + CAM_TFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = + CAM_TFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } + break; + default: + CAM_ERR(CAM_ISP, "Unsupported RDI:%d format %d", + rsrc_data->index, rsrc_data->format); + return -EINVAL; + } + + return 0; +} + static int cam_tfe_bus_acquire_wm( struct cam_tfe_bus_priv *bus_priv, struct cam_isp_tfe_out_port_info *out_port_info, @@ -463,9 +599,9 @@ static int cam_tfe_bus_acquire_wm( struct cam_isp_resource_node *wm_res_local = NULL; struct cam_tfe_bus_wm_resource_data *rsrc_data = NULL; uint32_t wm_idx = 0; + int rc = 0; *wm_res = NULL; - /* No need to allocate for BUS TFE OUT to WM is fixed. */ wm_idx = cam_tfe_bus_get_wm_idx(tfe_out_res_id, plane); if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { @@ -491,50 +627,26 @@ static int cam_tfe_bus_acquire_wm( rsrc_data->width = out_port_info->width; rsrc_data->height = out_port_info->height; rsrc_data->stride = out_port_info->stride; + rsrc_data->mode = out_port_info->wm_mode; + + /* + * Store the acquire width, height separately. For frame based ports + * width and height modified again + */ + rsrc_data->acquired_width = out_port_info->width; + rsrc_data->acquired_height = out_port_info->height; + rsrc_data->acquired_stride = out_port_info->stride; + rsrc_data->is_dual = is_dual; /* Set WM offset value to default */ rsrc_data->offset = 0; if (rsrc_data->index > 6) { /* WM 7-9 refers to RDI 0/ RDI 1/RDI 2 */ - switch (rsrc_data->format) { - case CAM_FORMAT_MIPI_RAW_6: - case CAM_FORMAT_MIPI_RAW_8: - case CAM_FORMAT_MIPI_RAW_10: - case CAM_FORMAT_MIPI_RAW_12: - case CAM_FORMAT_MIPI_RAW_14: - case CAM_FORMAT_MIPI_RAW_16: - case CAM_FORMAT_PLAIN128: - rsrc_data->width = CAM_TFE_RDI_BUS_DEFAULT_WIDTH; - rsrc_data->height = 0; - rsrc_data->stride = CAM_TFE_RDI_BUS_DEFAULT_STRIDE; - rsrc_data->pack_fmt = 0xA; - rsrc_data->en_cfg = (0x1 << 16) | 0x1; - break; - case CAM_FORMAT_PLAIN8: - rsrc_data->en_cfg = 0x1; - rsrc_data->pack_fmt = 0xA; - rsrc_data->stride = rsrc_data->width * 2; - break; - case CAM_FORMAT_PLAIN16_10: - case CAM_FORMAT_PLAIN16_12: - case CAM_FORMAT_PLAIN16_14: - case CAM_FORMAT_PLAIN16_16: - rsrc_data->width = CAM_TFE_RDI_BUS_DEFAULT_WIDTH; - rsrc_data->height = 0; - rsrc_data->stride = CAM_TFE_RDI_BUS_DEFAULT_STRIDE; - rsrc_data->pack_fmt = 0xA; - rsrc_data->en_cfg = (0x1 << 16) | 0x1; - break; - case CAM_FORMAT_PLAIN64: - rsrc_data->en_cfg = 0x1; - rsrc_data->pack_fmt = 0xA; - break; - default: - CAM_ERR(CAM_ISP, "Unsupported RDI format %d", - rsrc_data->format); - return -EINVAL; - } + rc = cam_tfe_bus_acquire_rdi_wm(rsrc_data); + if (rc) + return rc; + } else if (rsrc_data->index == 0 || rsrc_data->index == 1) { /* WM 0 FULL_OUT */ switch (rsrc_data->format) { @@ -581,9 +693,10 @@ static int cam_tfe_bus_acquire_wm( *client_done_mask |= (1 << wm_idx); CAM_DBG(CAM_ISP, - "WM:%d processed width:%d height:%d format:0x%x comp_group:%d packt format:0x%x", + "WM:%d processed width:%d height:%d format:0x%x comp_group:%d packt format:0x%x wm mode:%d", rsrc_data->index, rsrc_data->width, rsrc_data->height, - rsrc_data->format, *comp_grp_id, rsrc_data->pack_fmt); + rsrc_data->format, *comp_grp_id, rsrc_data->pack_fmt, + rsrc_data->mode); return 0; } @@ -630,7 +743,8 @@ static int cam_tfe_bus_start_wm(struct cam_isp_resource_node *wm_res) common_data->mem_base + rsrc_data->hw_regs->packer_cfg); /* Configure stride for RDIs on full TFE and TFE lite */ - if (rsrc_data->index > 6) + if ((rsrc_data->index > 6) && + (rsrc_data->mode != CAM_ISP_TFE_WM_LINE_BASED_MODE)) cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + rsrc_data->hw_regs->image_cfg_2)); @@ -1573,8 +1687,108 @@ static int cam_tfe_bus_bufdone_bottom_half( return 0; } +static void cam_tfe_bus_error_bottom_half( + struct cam_tfe_bus_priv *bus_priv, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_bus_wm_resource_data *rsrc_data; + struct cam_tfe_bus_reg_offset_common *common_reg; + uint32_t i, overflow_status, image_size_violation_status; + uint32_t ccif_violation_status; + + common_reg = bus_priv->common_data.common_reg; + + CAM_INFO(CAM_ISP, "BUS IRQ[0]:0x%x BUS IRQ[1]:0x%x", + evt_payload->bus_irq_val[0], evt_payload->bus_irq_val[1]); + + overflow_status = cam_io_r_mb(bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->overflow_status); + + image_size_violation_status = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->image_size_violation_status); + + ccif_violation_status = cam_io_r_mb(bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->ccif_violation_status); + + CAM_INFO(CAM_ISP, + "ccif violation status:0x%x image size violation:0x%x overflow status:0x%x", + ccif_violation_status, + image_size_violation_status, + overflow_status); + + /* Check the bus errors */ + if (evt_payload->bus_irq_val[0] & BIT(common_reg->cons_violation_shift)) + CAM_INFO(CAM_ISP, "CONS_VIOLATION"); + + if (evt_payload->bus_irq_val[0] & BIT(common_reg->violation_shift)) + CAM_INFO(CAM_ISP, "VIOLATION"); + + if (evt_payload->bus_irq_val[0] & + BIT(common_reg->image_size_violation)) { + CAM_INFO(CAM_ISP, "IMAGE_SIZE_VIOLATION val :0x%x", + evt_payload->image_size_violation_status); + + for (i = 0; i < CAM_TFE_BUS_MAX_CLIENTS; i++) { + if (!(evt_payload->image_size_violation_status >> i)) + break; + + if (evt_payload->image_size_violation_status & BIT(i)) { + rsrc_data = bus_priv->bus_client[i].res_priv; + CAM_INFO(CAM_ISP, + "WM:%d width 0x%x height:0x%x format:%d stride:0x%x offset:0x%x encfg:0x%x", + i, + rsrc_data->acquired_width, + rsrc_data->acquired_height, + rsrc_data->format, + rsrc_data->acquired_stride, + rsrc_data->offset, + rsrc_data->en_cfg); + + CAM_INFO(CAM_ISP, + "WM:%d current width 0x%x height:0x%x stride:0x%x", + i, + rsrc_data->width, + rsrc_data->height, + rsrc_data->stride); + + } + } + } + + if (overflow_status) { + for (i = 0; i < CAM_TFE_BUS_MAX_CLIENTS; i++) { + + if (!(evt_payload->overflow_status >> i)) + break; + + if (evt_payload->overflow_status & BIT(i)) { + rsrc_data = bus_priv->bus_client[i].res_priv; + CAM_INFO(CAM_ISP, + "WM:%d %s BUS OVERFLOW width0x%x height:0x%x format:%d stride:0x%x offset:0x%x encfg:%x", + i, + rsrc_data->hw_regs->client_name, + rsrc_data->acquired_width, + rsrc_data->acquired_height, + rsrc_data->format, + rsrc_data->acquired_stride, + rsrc_data->offset, + rsrc_data->en_cfg); + + CAM_INFO(CAM_ISP, + "WM:%d current width:0x%x height:0x%x stride:0x%x", + i, + rsrc_data->width, + rsrc_data->height, + rsrc_data->stride); + } + } + } +} + static int cam_tfe_bus_bottom_half(void *priv, - bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload) + bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload, + bool error_process) { struct cam_tfe_bus_priv *bus_priv; uint32_t val; @@ -1585,6 +1799,11 @@ static int cam_tfe_bus_bottom_half(void *priv, } bus_priv = (struct cam_tfe_bus_priv *) priv; + if (error_process) { + cam_tfe_bus_error_bottom_half(bus_priv, evt_payload); + goto end; + } + /* if bus errors are there, mask all bus errors */ if (evt_payload->bus_irq_val[0] & bus_priv->bus_irq_error_mask[0]) { val = cam_io_r(bus_priv->common_data.mem_base + @@ -1592,6 +1811,7 @@ static int cam_tfe_bus_bottom_half(void *priv, val &= ~bus_priv->bus_irq_error_mask[0]; cam_io_w(val, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->irq_mask[0]); + } if (rup_process) { @@ -1604,6 +1824,7 @@ static int cam_tfe_bus_bottom_half(void *priv, cam_tfe_bus_bufdone_bottom_half(bus_priv, evt_payload); } +end: return 0; } @@ -1657,21 +1878,14 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, CAM_DBG(CAM_ISP, "WM:%d image height and width 0x%x", wm_data->index, reg_val_pair[j-1]); - val = io_cfg->planes[i].plane_stride; - CAM_DBG(CAM_ISP, "before stride 0x%x", val); - val = ALIGNUP(val, 16); - if (val != io_cfg->planes[i].plane_stride && - val != wm_data->stride) - CAM_WARN(CAM_ISP, "Warning stride %u expected %u", - io_cfg->planes[i].plane_stride, val); - val = wm_data->offset; CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_1, val); CAM_DBG(CAM_ISP, "WM:%d xinit 0x%x", wm_data->index, reg_val_pair[j-1]); - if (wm_data->index < 7) { + if ((wm_data->index < 7) || ((wm_data->index >= 7) && + (wm_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE))) { CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_2, io_cfg->planes[i].plane_stride); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h index 3a62806f970f..db34083ede00 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h @@ -11,10 +11,11 @@ #include "cam_isp_hw.h" #include "cam_tfe_hw_intf.h" -#define CAM_TFE_BUS_MAX_CLIENTS 10 -#define CAM_TFE_BUS_MAX_SUB_GRPS 4 -#define CAM_TFE_BUS_MAX_PERF_CNT_REG 8 -#define CAM_TFE_BUS_MAX_IRQ_REGISTERS 2 +#define CAM_TFE_BUS_MAX_CLIENTS 10 +#define CAM_TFE_BUS_MAX_SUB_GRPS 4 +#define CAM_TFE_BUS_MAX_PERF_CNT_REG 8 +#define CAM_TFE_BUS_MAX_IRQ_REGISTERS 2 +#define CAM_TFE_BUS_CLIENT_NAME_MAX_LENGTH 32 #define CAM_TFE_BUS_1_0 0x1000 @@ -29,7 +30,8 @@ ((value + alignment - 1) / alignment * alignment) typedef int (*CAM_BUS_HANDLER_BOTTOM_HALF)(void *bus_priv, - bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload); + bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload, + bool error_process); enum cam_tfe_bus_plane_type { PLANE_Y, @@ -106,6 +108,10 @@ struct cam_tfe_bus_reg_offset_common { uint32_t irq_clear[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; uint32_t irq_status[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; uint32_t irq_cmd; + /* common register data */ + uint32_t cons_violation_shift; + uint32_t violation_shift; + uint32_t image_size_violation; }; /* @@ -138,6 +144,8 @@ struct cam_tfe_bus_reg_offset_bus_client { uint32_t debug_status_0; uint32_t debug_status_1; uint32_t comp_group; + /*bus data */ + uint8_t client_name[CAM_TFE_BUS_CLIENT_NAME_MAX_LENGTH]; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 8ebabf1f15c4..9c82d7cbca88 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -48,6 +48,10 @@ struct cam_tfe_top_priv { axi_vote_control[CAM_TFE_TOP_IN_PORT_MAX]; uint32_t irq_prepared_mask[3]; void *tasklet_info; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; struct cam_tfe_camif_data { @@ -64,9 +68,11 @@ struct cam_tfe_camif_data { enum cam_isp_hw_sync_mode sync_mode; uint32_t dsp_mode; uint32_t pix_pattern; - uint32_t first_pixel; + uint32_t left_first_pixel; + uint32_t left_last_pixel; + uint32_t right_first_pixel; + uint32_t right_last_pixel; uint32_t first_line; - uint32_t last_pixel; uint32_t last_line; bool enable_sof_irq_debug; uint32_t irq_debug_cnt; @@ -85,6 +91,10 @@ struct cam_tfe_rdi_data { void *priv; enum cam_isp_hw_sync_mode sync_mode; uint32_t pix_pattern; + uint32_t left_first_pixel; + uint32_t left_last_pixel; + uint32_t first_line; + uint32_t last_line; }; static int cam_tfe_validate_pix_pattern(uint32_t pattern) @@ -211,68 +221,15 @@ int cam_tfe_irq_config(void *tfe_core_data, return 0; } -static void cam_tfe_log_error_irq_status( - struct cam_tfe_hw_core_info *core_info, - struct cam_tfe_top_priv *top_priv, - struct cam_tfe_irq_evt_payload *evt_payload) +static void cam_tfe_log_tfe_in_debug_status( + struct cam_tfe_top_priv *top_priv) { - struct cam_tfe_hw_info *hw_info; void __iomem *mem_base; - struct cam_hw_soc_info *soc_info; - struct cam_tfe_soc_private *soc_private; struct cam_tfe_camif_data *camif_data; struct cam_tfe_rdi_data *rdi_data; - uint32_t i, val_0, val_1, val_2, val_3; + uint32_t i, val_0, val_1; - hw_info = core_info->tfe_hw_info; mem_base = top_priv->common_data.soc_info->reg_map[0].mem_base; - soc_info = top_priv->common_data.soc_info; - soc_private = top_priv->common_data.soc_info->soc_private; - - val_0 = cam_io_r(mem_base + - top_priv->common_data.common_reg->debug_0); - val_1 = cam_io_r(mem_base + - top_priv->common_data.common_reg->debug_1); - val_2 = cam_io_r(mem_base + - top_priv->common_data.common_reg->debug_2); - val_3 = cam_io_r(mem_base + - top_priv->common_data.common_reg->debug_3); - - CAM_INFO(CAM_ISP, "TOP IRQ[0]:0x%x IRQ[1]:0x%x IRQ[2]:0x%x", - evt_payload->irq_reg_val[0], evt_payload->irq_reg_val[1], - evt_payload->irq_reg_val[2]); - - CAM_INFO(CAM_ISP, "BUS IRQ[0]:0x%x BUS IRQ[1]:0x%x", - evt_payload->bus_irq_val[0], evt_payload->bus_irq_val[1]); - - CAM_INFO(CAM_ISP, "ccif violation:0x%x image size:0x%x overflow:0x%x", - evt_payload->ccif_violation_status, - evt_payload->image_size_violation_status, - evt_payload->overflow_status); - - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x20, true, &val_0); - CAM_INFO(CAM_ISP, "tfe_niu_MaxWr_Low offset 0x20 val 0x%x", - val_0); - - CAM_INFO(CAM_ISP, "Top debug [0]:0x%x [1]:0x%x [2]:0x%x [3]:0x%x", - val_0, val_1, val_2, val_3); - - val_0 = cam_io_r(mem_base + - top_priv->common_data.common_reg->perf_pixel_count); - - val_1 = cam_io_r(mem_base + - top_priv->common_data.common_reg->perf_line_count); - - val_2 = cam_io_r(mem_base + - top_priv->common_data.common_reg->perf_stall_count); - - val_3 = cam_io_r(mem_base + - top_priv->common_data.common_reg->perf_always_count); - - CAM_INFO(CAM_ISP, - "Top perf cnt pix:0x%x line:0x%x stall:0x%x always:0x%x", - val_0, val_1, val_2, val_3); for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { if ((top_priv->in_rsrc[i].res_state != @@ -291,6 +248,23 @@ static void cam_tfe_log_error_irq_status( val_1, ((val_0 >> 16) & 0x1FFF), (val_0 & 0x1FFF)); + CAM_INFO(CAM_ISP, + "Acquired sync mode:%d left start pxl:0x%x end_pixel:0x%x", + camif_data->sync_mode, + camif_data->left_first_pixel, + camif_data->left_last_pixel); + + if (camif_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) + CAM_INFO(CAM_ISP, + "sync mode:%d right start pxl:0x%x end_pixel:0x%x", + camif_data->sync_mode, + camif_data->right_first_pixel, + camif_data->right_last_pixel); + + CAM_INFO(CAM_ISP, + "Acquired line start:0x%x line end:0x%x", + camif_data->first_line, + camif_data->last_line); } else if ((top_priv->in_rsrc[i].res_id >= CAM_ISP_HW_TFE_IN_RDI0) || (top_priv->in_rsrc[i].res_id <= @@ -306,11 +280,104 @@ static void cam_tfe_log_error_irq_status( top_priv->in_rsrc[i].res_id, val_1, ((val_0 >> 16) & 0x1FFF), (val_0 & 0x1FFF)); + CAM_INFO(CAM_ISP, + "sync mode:%d left start pxl:0x%x end_pixel:0x%x", + rdi_data->sync_mode, + rdi_data->left_first_pixel, + rdi_data->left_last_pixel); + CAM_INFO(CAM_ISP, + "sync mode:%d line start:0x%x line end:0x%x", + rdi_data->sync_mode, + rdi_data->first_line, + rdi_data->last_line); } } +} +static void cam_tfe_log_error_irq_status( + struct cam_tfe_hw_core_info *core_info, + struct cam_tfe_top_priv *top_priv, + struct cam_tfe_irq_evt_payload *evt_payload) +{ + struct cam_tfe_hw_info *hw_info; + void __iomem *mem_base; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_soc_private *soc_private; + + struct cam_tfe_clc_hw_status *clc_hw_status; + struct timespec64 ts; + uint32_t i, val_0, val_1, val_2, val_3; + + + ktime_get_boottime_ts64(&ts); + hw_info = core_info->tfe_hw_info; + mem_base = top_priv->common_data.soc_info->reg_map[0].mem_base; + soc_info = top_priv->common_data.soc_info; + soc_private = top_priv->common_data.soc_info->soc_private; + + CAM_INFO(CAM_ISP, "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + top_priv->error_ts.tv_sec, + top_priv->error_ts.tv_usec, + top_priv->sof_ts.tv_sec, + top_priv->sof_ts.tv_usec, + top_priv->epoch_ts.tv_sec, + top_priv->epoch_ts.tv_usec, + top_priv->eof_ts.tv_sec, + top_priv->eof_ts.tv_usec); + val_0 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_0); + val_1 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_1); + val_2 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_2); + val_3 = cam_io_r(mem_base + + top_priv->common_data.common_reg->debug_3); + + CAM_INFO(CAM_ISP, "TOP IRQ[0]:0x%x IRQ[1]:0x%x IRQ[2]:0x%x", + evt_payload->irq_reg_val[0], evt_payload->irq_reg_val[1], + evt_payload->irq_reg_val[2]); + + CAM_INFO(CAM_ISP, "Top debug [0]:0x%x [1]:0x%x [2]:0x%x [3]:0x%x", + val_0, val_1, val_2, val_3); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x20, true, &val_0); + CAM_INFO(CAM_ISP, "tfe_niu_MaxWr_Low offset 0x20 val 0x%x", + val_0); + + val_0 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_pixel_count); + + val_1 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_line_count); + + val_2 = cam_io_r(mem_base + top_priv->common_data.common_reg->perf_stall_count); + val_3 = cam_io_r(mem_base + + top_priv->common_data.common_reg->perf_always_count); + + CAM_INFO(CAM_ISP, + "Top perf cnt pix:0x%x line:0x%x stall:0x%x always:0x%x", + val_0, val_1, val_2, val_3); + + clc_hw_status = hw_info->clc_hw_status_info; + for (i = 0; i < hw_info->num_clc; i++) { + val_0 = cam_io_r(mem_base + + clc_hw_status[i].hw_status_reg); + if (val_0) + CAM_INFO(CAM_ISP, + "CLC HW status :name:%s offset:0x%x value:0x%x", + clc_hw_status[i].name, + clc_hw_status[i].hw_status_reg, + val_0); + } + + cam_tfe_log_tfe_in_debug_status(top_priv); + /* Check the overflow errors */ if (evt_payload->irq_reg_val[0] & hw_info->error_irq_mask[0]) { if (evt_payload->irq_reg_val[0] & BIT(8)) @@ -363,22 +430,13 @@ static void cam_tfe_log_error_irq_status( CAM_INFO(CAM_ISP, "TOP Violation status:0x%x", val_0); } - /* Check the bus errors */ - if (evt_payload->bus_irq_val[0] & BIT(29)) - CAM_INFO(CAM_ISP, "CONS_VIOLATION"); + core_info->tfe_bus->bottom_half_handler( + core_info->tfe_bus->bus_priv, false, evt_payload, true); - if (evt_payload->bus_irq_val[0] & BIT(30)) - CAM_INFO(CAM_ISP, "VIOLATION val 0x%x", - evt_payload->ccif_violation_status); - - if (evt_payload->bus_irq_val[0] & BIT(31)) - CAM_INFO(CAM_ISP, "IMAGE_SIZE_VIOLATION val :0x%x", - evt_payload->image_size_violation_status); - - /* clear the bus irq overflow status*/ - if (evt_payload->overflow_status) - cam_io_w_mb(1, mem_base + - core_info->tfe_hw_info->bus_overflow_clear_cmd); + CAM_INFO(CAM_ISP, + "TFE clock rate:%d TFE total bw applied:%lld", + top_priv->hw_clk_rate, + top_priv->total_bw_applied); } @@ -391,33 +449,31 @@ static int cam_tfe_error_irq_bottom_half( { struct cam_isp_hw_event_info evt_info; struct cam_tfe_hw_info *hw_info; + uint32_t error_detected = 0; hw_info = core_info->tfe_hw_info; evt_info.hw_idx = core_info->core_index; evt_info.res_type = CAM_ISP_RESOURCE_TFE_IN; if (evt_payload->irq_reg_val[0] & hw_info->error_irq_mask[0]) { - CAM_ERR(CAM_ISP, "TFE:%d Overflow error irq_status[0]:%x", - core_info->core_index, - evt_payload->irq_reg_val[0]); - evt_info.err_type = CAM_TFE_IRQ_STATUS_OVERFLOW; - cam_tfe_log_error_irq_status(core_info, top_priv, evt_payload); - if (event_cb) - event_cb(event_cb_priv, - CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); - else - CAM_ERR(CAM_ISP, "TFE:%d invalid eventcb:", - core_info->core_index); + error_detected = 1; } - if (evt_payload->irq_reg_val[2] & hw_info->error_irq_mask[2]) { - CAM_ERR(CAM_ISP, "TFE:%d Violation error irq_status[2]:%x", - core_info->core_index, evt_payload->irq_reg_val[2]); - + if ((evt_payload->bus_irq_val[0] & hw_info->bus_error_irq_mask[0]) || + (evt_payload->irq_reg_val[2] & hw_info->error_irq_mask[2])) { evt_info.err_type = CAM_TFE_IRQ_STATUS_VIOLATION; - cam_tfe_log_error_irq_status(core_info, top_priv, evt_payload); + error_detected = 1; + } + if (error_detected) { + evt_info.err_type = CAM_TFE_IRQ_STATUS_OVERFLOW; + top_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + + cam_tfe_log_error_irq_status(core_info, top_priv, evt_payload); if (event_cb) event_cb(event_cb_priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); @@ -430,6 +486,7 @@ static int cam_tfe_error_irq_bottom_half( } static int cam_tfe_rdi_irq_bottom_half( + struct cam_tfe_top_priv *top_priv, struct cam_isp_resource_node *rdi_node, bool epoch_process, struct cam_tfe_irq_evt_payload *evt_payload) @@ -448,6 +505,11 @@ static int cam_tfe_rdi_irq_bottom_half( if ((!epoch_process) && (evt_payload->irq_reg_val[1] & rdi_priv->reg_data->eof_irq_mask)) { CAM_DBG(CAM_ISP, "Received EOF"); + top_priv->eof_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->eof_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + if (rdi_priv->event_cb) rdi_priv->event_cb(rdi_priv->priv, CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); @@ -456,6 +518,11 @@ static int cam_tfe_rdi_irq_bottom_half( if ((!epoch_process) && (evt_payload->irq_reg_val[1] & rdi_priv->reg_data->sof_irq_mask)) { CAM_DBG(CAM_ISP, "Received SOF"); + top_priv->sof_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->sof_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + if (rdi_priv->event_cb) rdi_priv->event_cb(rdi_priv->priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); @@ -464,6 +531,10 @@ static int cam_tfe_rdi_irq_bottom_half( if (epoch_process && (evt_payload->irq_reg_val[1] & rdi_priv->reg_data->epoch0_irq_mask)) { CAM_DBG(CAM_ISP, "Received EPOCH0"); + top_priv->epoch_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->epoch_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; if (rdi_priv->event_cb) rdi_priv->event_cb(rdi_priv->priv, @@ -474,6 +545,7 @@ static int cam_tfe_rdi_irq_bottom_half( } static int cam_tfe_camif_irq_bottom_half( + struct cam_tfe_top_priv *top_priv, struct cam_isp_resource_node *camif_node, bool epoch_process, struct cam_tfe_irq_evt_payload *evt_payload) @@ -493,6 +565,11 @@ static int cam_tfe_camif_irq_bottom_half( camif_priv->reg_data->eof_irq_mask)) { CAM_DBG(CAM_ISP, "Received EOF"); + top_priv->eof_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->eof_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); @@ -515,6 +592,11 @@ static int cam_tfe_camif_irq_bottom_half( } else CAM_DBG(CAM_ISP, "Received SOF"); + top_priv->sof_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->sof_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); @@ -524,6 +606,11 @@ static int cam_tfe_camif_irq_bottom_half( camif_priv->reg_data->epoch0_irq_mask)) { CAM_DBG(CAM_ISP, "Received EPOCH"); + top_priv->epoch_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + top_priv->epoch_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); @@ -575,7 +662,7 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, if (camif_priv->reg_data->subscribe_irq_mask[1] & evt_payload->irq_reg_val[1]) - cam_tfe_camif_irq_bottom_half( + cam_tfe_camif_irq_bottom_half(top_priv, &top_priv->in_rsrc[i], false, evt_payload); @@ -584,7 +671,8 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, (top_priv->in_rsrc[i].res_id <= CAM_ISP_HW_TFE_IN_RDI2) && (top_priv->in_rsrc[i].res_state == - CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_ISP_RESOURCE_STATE_STREAMING) && + top_priv->in_rsrc[i].rdi_only_ctx) { rdi_priv = (struct cam_tfe_rdi_data *) top_priv->in_rsrc[i].res_priv; event_cb = rdi_priv->event_cb; @@ -592,7 +680,7 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, if (rdi_priv->reg_data->subscribe_irq_mask[1] & evt_payload->irq_reg_val[1]) - cam_tfe_rdi_irq_bottom_half( + cam_tfe_rdi_irq_bottom_half(top_priv, &top_priv->in_rsrc[i], false, evt_payload); } @@ -606,7 +694,7 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, if (evt_payload->irq_reg_val[0] & core_info->tfe_hw_info->bus_reg_irq_mask[0]) { core_info->tfe_bus->bottom_half_handler( - core_info->tfe_bus->bus_priv, true, evt_payload); + core_info->tfe_bus->bus_priv, true, evt_payload, false); } /* process the epoch */ @@ -619,7 +707,7 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, top_priv->in_rsrc[i].res_priv; if (camif_priv->reg_data->subscribe_irq_mask[1] & evt_payload->irq_reg_val[1]) - cam_tfe_camif_irq_bottom_half( + cam_tfe_camif_irq_bottom_half(top_priv, &top_priv->in_rsrc[i], true, evt_payload); } else if ((top_priv->in_rsrc[i].res_id >= @@ -632,7 +720,7 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, top_priv->in_rsrc[i].res_priv; if (rdi_priv->reg_data->subscribe_irq_mask[1] & evt_payload->irq_reg_val[1]) - cam_tfe_rdi_irq_bottom_half( + cam_tfe_rdi_irq_bottom_half(top_priv, &top_priv->in_rsrc[i], true, evt_payload); } @@ -642,7 +730,8 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, if (evt_payload->irq_reg_val[0] & core_info->tfe_hw_info->bus_reg_irq_mask[0]) { core_info->tfe_bus->bottom_half_handler( - core_info->tfe_bus->bus_priv, false, evt_payload); + core_info->tfe_bus->bus_priv, false, evt_payload, + false); } cam_tfe_put_evt_payload(core_info, &evt_payload); @@ -653,16 +742,24 @@ static int cam_tfe_irq_bottom_half(void *handler_priv, static int cam_tfe_irq_err_top_half( struct cam_tfe_hw_core_info *core_info, void __iomem *mem_base, - uint32_t *irq_status) + uint32_t *top_irq_status, + uint32_t *bus_irq_status) { uint32_t i; - if (irq_status[0] & core_info->tfe_hw_info->error_irq_mask[0] || - irq_status[2] & core_info->tfe_hw_info->error_irq_mask[2]) { + if ((top_irq_status[0] & core_info->tfe_hw_info->error_irq_mask[0]) || + (top_irq_status[2] & + core_info->tfe_hw_info->error_irq_mask[2]) || + (bus_irq_status[0] & + core_info->tfe_hw_info->bus_error_irq_mask[0])) { CAM_ERR(CAM_ISP, "Encountered Error: tfe:%d: Irq_status0=0x%x status2=0x%x", - core_info->core_index, irq_status[0], - irq_status[2]); + core_info->core_index, top_irq_status[0], + top_irq_status[2]); + CAM_ERR(CAM_ISP, + "Encountered Error: tfe:%d:BUS Irq_status0=0x%x", + core_info->core_index, bus_irq_status[0]); + for (i = 0; i < CAM_TFE_TOP_IRQ_REG_NUM; i++) cam_io_w(0, mem_base + core_info->tfe_hw_info->top_irq_mask[i]); @@ -755,7 +852,8 @@ irqreturn_t cam_tfe_irq(int irq_num, void *data) } /* Check the irq errors */ - cam_tfe_irq_err_top_half(core_info, mem_base, top_irq_status); + cam_tfe_irq_err_top_half(core_info, mem_base, top_irq_status, + bus_irq_status); rc = cam_tfe_get_evt_payload(core_info, &evt_payload); if (rc) { @@ -877,7 +975,7 @@ static int cam_tfe_top_set_axi_bw_vote( struct cam_tfe_top_priv *top_priv, bool start_stop) { - struct cam_axi_vote agg_vote = {0}; + struct cam_axi_vote *agg_vote = NULL; struct cam_axi_vote *to_be_applied_axi_vote = NULL; struct cam_hw_soc_info *soc_info = top_priv->common_data.soc_info; struct cam_tfe_soc_private *soc_private = soc_info->soc_private; @@ -893,6 +991,12 @@ static int cam_tfe_top_set_axi_bw_vote( return -EINVAL; } + agg_vote = kzalloc(sizeof(struct cam_axi_vote), GFP_KERNEL); + if (!agg_vote) { + CAM_ERR(CAM_ISP, "Out of memory"); + return -ENOMEM; + } + for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) { if (top_priv->axi_vote_control[i] == CAM_TFE_BW_CONTROL_INCLUDE) { @@ -904,10 +1008,11 @@ static int cam_tfe_top_set_axi_bw_vote( num_paths + top_priv->req_axi_vote[i].num_paths, CAM_CPAS_MAX_PATHS_PER_CLIENT); - return -EINVAL; + rc = -EINVAL; + goto free_mem; } - memcpy(&agg_vote.axi_path[num_paths], + memcpy(&agg_vote->axi_path[num_paths], &top_priv->req_axi_vote[i].axi_path[0], top_priv->req_axi_vote[i].num_paths * sizeof( @@ -916,31 +1021,31 @@ static int cam_tfe_top_set_axi_bw_vote( } } - agg_vote.num_paths = num_paths; + agg_vote->num_paths = num_paths; - for (i = 0; i < agg_vote.num_paths; i++) { + for (i = 0; i < agg_vote->num_paths; i++) { CAM_DBG(CAM_PERF, "tfe[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", top_priv->common_data.hw_intf->hw_idx, top_priv->last_counter, cam_cpas_axi_util_path_type_to_string( - agg_vote.axi_path[i].path_data_type), + agg_vote->axi_path[i].path_data_type), cam_cpas_axi_util_trans_type_to_string( - agg_vote.axi_path[i].transac_type), - agg_vote.axi_path[i].camnoc_bw, - agg_vote.axi_path[i].mnoc_ab_bw, - agg_vote.axi_path[i].mnoc_ib_bw); + agg_vote->axi_path[i].transac_type), + agg_vote->axi_path[i].camnoc_bw, + agg_vote->axi_path[i].mnoc_ab_bw, + agg_vote->axi_path[i].mnoc_ib_bw); - total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; + total_bw_new_vote += agg_vote->axi_path[i].camnoc_bw; } - memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, + memcpy(&top_priv->last_vote[top_priv->last_counter], agg_vote, sizeof(struct cam_axi_vote)); top_priv->last_counter = (top_priv->last_counter + 1) % (CAM_TFE_TOP_IN_PORT_MAX * CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES); - if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || + if ((agg_vote->num_paths != top_priv->applied_axi_vote.num_paths) || (total_bw_new_vote != top_priv->total_bw_applied)) bw_unchanged = false; @@ -952,18 +1057,19 @@ static int cam_tfe_top_set_axi_bw_vote( if (bw_unchanged) { CAM_DBG(CAM_ISP, "BW config unchanged"); - return 0; + rc = 0; + goto free_mem; } if (start_stop) { /* need to vote current request immediately */ - to_be_applied_axi_vote = &agg_vote; + to_be_applied_axi_vote = agg_vote; /* Reset everything, we can start afresh */ memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * (CAM_TFE_TOP_IN_PORT_MAX * CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES)); top_priv->last_counter = 0; - top_priv->last_vote[top_priv->last_counter] = agg_vote; + top_priv->last_vote[top_priv->last_counter] = *agg_vote; top_priv->last_counter = (top_priv->last_counter + 1) % (CAM_TFE_TOP_IN_PORT_MAX * CAM_TFE_DELAY_BW_REDUCTION_NUM_FRAMES); @@ -977,7 +1083,8 @@ static int cam_tfe_top_set_axi_bw_vote( &total_bw_new_vote); if (!to_be_applied_axi_vote) { CAM_ERR(CAM_ISP, "to_be_applied_axi_vote is NULL"); - return -EINVAL; + rc = -EINVAL; + goto free_mem; } } @@ -1018,6 +1125,9 @@ static int cam_tfe_top_set_axi_bw_vote( } } +free_mem: + kzfree(agg_vote); + agg_vote = NULL; return rc; } @@ -1381,6 +1491,234 @@ static int cam_tfe_top_get_reg_dump( return 0; } +static int cam_tfe_hw_dump( + struct cam_tfe_hw_core_info *core_info, + void *cmd_args, + uint32_t arg_size) +{ + int i, j; + uint8_t *dst; + uint32_t reg_start_offset; + uint32_t reg_dump_size = 0; + uint32_t lut_dump_size = 0; + uint32_t num_lut_dump_entries = 0; + uint32_t num_reg; + uint32_t lut_word_size, lut_size; + uint32_t lut_bank_sel, lut_dmi_reg; + uint32_t val; + void __iomem *reg_base; + void __iomem *mem_base; + uint32_t *addr, *start; + uint64_t *clk_waddr, *clk_wstart; + size_t remain_len; + uint32_t min_len; + struct cam_hw_info *tfe_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_top_priv *top_priv; + struct cam_tfe_soc_private *soc_private; + struct cam_tfe_reg_dump_data *reg_dump_data; + struct cam_isp_hw_dump_header *hdr; + struct cam_isp_hw_dump_args *dump_args = + (struct cam_isp_hw_dump_args *)cmd_args; + + if (!dump_args || !core_info) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + if (!dump_args->cpu_addr || !dump_args->buf_len) { + CAM_ERR(CAM_ISP, + "Invalid params %pK %zu", + (void *)dump_args->cpu_addr, + dump_args->buf_len); + return -EINVAL; + } + + if (dump_args->buf_len <= dump_args->offset) { + CAM_WARN(CAM_ISP, + "Dump offset overshoot offset %zu buf_len %zu", + dump_args->offset, dump_args->buf_len); + return -ENOSPC; + } + + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + tfe_hw_info = + (struct cam_hw_info *)(top_priv->common_data.hw_intf->hw_priv); + reg_dump_data = top_priv->common_data.reg_dump_data; + soc_info = top_priv->common_data.soc_info; + soc_private = top_priv->common_data.soc_info->soc_private; + mem_base = soc_info->reg_map[TFE_CORE_BASE_IDX].mem_base; + + if (dump_args->is_dump_all) { + + /*Dump registers size*/ + for (i = 0; i < reg_dump_data->num_reg_dump_entries; i++) + reg_dump_size += + (reg_dump_data->reg_entry[i].end_offset - + reg_dump_data->reg_entry[i].start_offset); + + /* + * We dump the offset as well, so the total size dumped becomes + * multiplied by 2 + */ + reg_dump_size *= 2; + + /* LUT dump size */ + for (i = 0; i < reg_dump_data->num_lut_dump_entries; i++) + lut_dump_size += + ((reg_dump_data->lut_entry[i].lut_addr_size) * + (reg_dump_data->lut_entry[i].lut_word_size/8)); + + num_lut_dump_entries = reg_dump_data->num_lut_dump_entries; + } + + /*Minimum len comprises of: + * lut_dump_size + reg_dump_size + sizeof dump_header + + * (num_lut_dump_entries--> represents number of banks) + + * (misc number of words) * sizeof(uint32_t) + */ + min_len = lut_dump_size + reg_dump_size + + sizeof(struct cam_isp_hw_dump_header) + + (num_lut_dump_entries * sizeof(uint32_t)) + + (sizeof(uint32_t) * CAM_TFE_CORE_DUMP_MISC_NUM_WORDS); + + remain_len = dump_args->buf_len - dump_args->offset; + if (remain_len < min_len) { + CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu, min %u", + remain_len, min_len); + return -ENOSPC; + } + + mutex_lock(&tfe_hw_info->hw_mutex); + if (tfe_hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "TFE:%d HW not powered up", + core_info->core_index); + mutex_unlock(&tfe_hw_info->hw_mutex); + return -EPERM; + } + + if (!dump_args->is_dump_all) + goto dump_bw; + + dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + hdr->word_size = sizeof(uint32_t); + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "TFE_REG:"); + addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header)); + start = addr; + *addr++ = soc_info->index; + for (i = 0; i < reg_dump_data->num_reg_dump_entries; i++) { + num_reg = (reg_dump_data->reg_entry[i].end_offset - + reg_dump_data->reg_entry[i].start_offset)/4; + reg_start_offset = reg_dump_data->reg_entry[i].start_offset; + reg_base = mem_base + reg_start_offset; + for (j = 0; j < num_reg; j++) { + addr[0] = + soc_info->mem_block[TFE_CORE_BASE_IDX]->start + + reg_start_offset + (j*4); + addr[1] = cam_io_r(reg_base + (j*4)); + addr += 2; + } + } + + /*Dump bus top registers*/ + num_reg = (reg_dump_data->bus_write_top_end_addr - + reg_dump_data->bus_start_addr)/4; + reg_base = mem_base + reg_dump_data->bus_start_addr; + reg_start_offset = soc_info->mem_block[TFE_CORE_BASE_IDX]->start + + reg_dump_data->bus_start_addr; + for (i = 0; i < num_reg; i++) { + addr[0] = reg_start_offset + (i*4); + addr[1] = cam_io_r(reg_base + (i*4)); + addr += 2; + } + + /* Dump bus clients */ + reg_base = mem_base + reg_dump_data->bus_client_start_addr; + reg_start_offset = soc_info->mem_block[TFE_CORE_BASE_IDX]->start + + reg_dump_data->bus_client_start_addr; + for (j = 0; j < reg_dump_data->num_bus_clients; j++) { + + for (i = 0; i <= 0x3c; i += 4) { + addr[0] = reg_start_offset + i; + addr[1] = cam_io_r(reg_base + i); + addr += 2; + } + for (i = 0x60; i <= 0x80; i += 4) { + addr[0] = reg_start_offset + (i*4); + addr[1] = cam_io_r(reg_base + (i*4)); + addr += 2; + } + reg_base += reg_dump_data->bus_client_offset; + reg_start_offset += reg_dump_data->bus_client_offset; + } + + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + + /* Dump LUT entries */ + for (i = 0; i < reg_dump_data->num_lut_dump_entries; i++) { + + lut_bank_sel = reg_dump_data->lut_entry[i].lut_bank_sel; + lut_size = reg_dump_data->lut_entry[i].lut_addr_size; + lut_word_size = reg_dump_data->lut_entry[i].lut_word_size; + lut_dmi_reg = reg_dump_data->lut_entry[i].dmi_reg_offset; + dst = (char *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "LUT_REG:"); + hdr->word_size = lut_word_size/8; + addr = (uint32_t *)(dst + + sizeof(struct cam_isp_hw_dump_header)); + start = addr; + *addr++ = lut_bank_sel; + cam_io_w_mb(lut_bank_sel, mem_base + lut_dmi_reg + 4); + cam_io_w_mb(0, mem_base + 0xC28); + for (j = 0; j < lut_size; j++) { + *addr = cam_io_r_mb(mem_base + 0xc30); + addr++; + } + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + } + cam_io_w_mb(0, mem_base + 0xC24); + cam_io_w_mb(0, mem_base + 0xC28); + +dump_bw: + dst = (char *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "TFE_CLK_RATE_BW:"); + clk_waddr = (uint64_t *)(dst + + sizeof(struct cam_isp_hw_dump_header)); + clk_wstart = clk_waddr; + hdr->word_size = sizeof(uint64_t); + *clk_waddr++ = top_priv->hw_clk_rate; + *clk_waddr++ = top_priv->total_bw_applied; + + hdr->size = hdr->word_size * (clk_waddr - clk_wstart); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + + dst = (char *)dump_args->cpu_addr + dump_args->offset; + hdr = (struct cam_isp_hw_dump_header *)dst; + scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "TFE_NIU_MAXWR:"); + addr = (uint32_t *)(dst + + sizeof(struct cam_isp_hw_dump_header)); + start = addr; + hdr->word_size = sizeof(uint32_t); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x20, true, &val); + *addr++ = val; + hdr->size = hdr->word_size * (addr - start); + dump_args->offset += hdr->size + + sizeof(struct cam_isp_hw_dump_header); + mutex_unlock(&tfe_hw_info->hw_mutex); + + CAM_DBG(CAM_ISP, "offset %zu", dump_args->offset); + return 0; +} + static int cam_tfe_camif_irq_reg_dump( struct cam_tfe_hw_core_info *core_info, void *cmd_args, uint32_t arg_size) @@ -1465,10 +1803,14 @@ int cam_tfe_top_reserve(void *device_priv, acquire_args->in_port->pix_pattern; camif_data->dsp_mode = acquire_args->in_port->dsp_mode; - camif_data->first_pixel = + camif_data->left_first_pixel = acquire_args->in_port->left_start; - camif_data->last_pixel = + camif_data->left_last_pixel = acquire_args->in_port->left_end; + camif_data->right_first_pixel = + acquire_args->in_port->right_start; + camif_data->right_last_pixel = + acquire_args->in_port->right_end; camif_data->first_line = acquire_args->in_port->line_start; camif_data->last_line = @@ -1494,6 +1836,14 @@ int cam_tfe_top_reserve(void *device_priv, rdi_data->sync_mode = acquire_args->sync_mode; rdi_data->event_cb = args->event_cb; rdi_data->priv = args->priv; + rdi_data->left_first_pixel = + acquire_args->in_port->left_start; + rdi_data->left_last_pixel = + acquire_args->in_port->left_end; + rdi_data->first_line = + acquire_args->in_port->line_start; + rdi_data->last_line = + acquire_args->in_port->line_end; } top_priv->in_rsrc[i].cdm_ops = acquire_args->cdm_ops; @@ -1604,6 +1954,9 @@ static int cam_tfe_camif_resource_start( if (!rsrc_data->camif_pd_enable) val |= (1 << rsrc_data->reg_data->camif_pd_rdi2_src_sel_shift); + /* enables the Delay Line CLC in the pixel pipeline */ + val |= BIT(rsrc_data->reg_data->delay_line_en_shift); + cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg_0); @@ -1755,10 +2108,19 @@ int cam_tfe_top_start(struct cam_tfe_hw_core_info *core_info, } core_info->irq_err_config_cnt++; - if (core_info->irq_err_config_cnt == 1) + if (core_info->irq_err_config_cnt == 1) { cam_tfe_irq_config(core_info, core_info->tfe_hw_info->error_irq_mask, CAM_TFE_TOP_IRQ_REG_NUM, true); + top_priv->error_ts.tv_sec = 0; + top_priv->error_ts.tv_usec = 0; + top_priv->sof_ts.tv_sec = 0; + top_priv->sof_ts.tv_usec = 0; + top_priv->epoch_ts.tv_sec = 0; + top_priv->epoch_ts.tv_usec = 0; + top_priv->eof_ts.tv_sec = 0; + top_priv->eof_ts.tv_usec = 0; + } end: return rc; @@ -2079,8 +2441,9 @@ int cam_tfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) CAM_DBG(CAM_ISP, "TFE:%d waiting for tfe reset complete", core_info->core_index); - /* Wait for Completion or Timeout of 500ms */ - rc = wait_for_completion_timeout(&core_info->reset_complete, 500); + /* Wait for Completion or Timeout of 100ms */ + rc = wait_for_completion_timeout(&core_info->reset_complete, + msecs_to_jiffies(100)); if (rc <= 0) { CAM_ERR(CAM_ISP, "TFE:%d Error Reset Timeout", core_info->core_index); @@ -2436,6 +2799,10 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA: *((struct cam_hw_soc_info **)cmd_args) = soc_info; break; + case CAM_ISP_HW_CMD_DUMP_HW: + rc = cam_tfe_hw_dump(core_info, + cmd_args, arg_size); + break; case CAM_ISP_HW_CMD_GET_BUF_UPDATE: case CAM_ISP_HW_CMD_GET_HFR_UPDATE: case CAM_ISP_HW_CMD_STRIPE_UPDATE: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h index d98a91901149..2418831d00c1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h @@ -25,6 +25,17 @@ #define CAM_TFE_MAX_REG_DUMP_ENTRIES 20 #define CAM_TFE_MAX_LUT_DUMP_ENTRIES 10 +#define CAM_TFE_MAX_CLC 30 +#define CAM_TFE_CLC_NAME_LENGTH_MAX 32 + +/*we take each word as uint32_t, for dumping uint64_t count as 2 words + * soc index + * clk_rate--> uint64_t--> count as 2 words + * BW--> uint64_t --> count as 2 words + * MAX_NIU + */ +#define CAM_TFE_CORE_DUMP_MISC_NUM_WORDS 4 + enum cam_tfe_lut_word_size { CAM_TFE_LUT_WORD_SIZE_32, CAM_TFE_LUT_WORD_SIZE_64, @@ -112,6 +123,7 @@ struct cam_tfe_camif_reg_data { uint32_t extern_reg_update_shift; uint32_t camif_pd_rdi2_src_sel_shift; uint32_t dual_tfe_sync_sel_shift; + uint32_t delay_line_en_shift; uint32_t pixel_pattern_shift; uint32_t pixel_pattern_mask; @@ -180,6 +192,11 @@ struct cam_tfe_rdi_reg_data { uint32_t enable_diagnostic_hw; }; +struct cam_tfe_clc_hw_status { + uint8_t name[CAM_TFE_CLC_NAME_LENGTH_MAX]; + uint32_t hw_status_reg; +}; + struct cam_tfe_rdi_hw_info { struct cam_tfe_rdi_reg *rdi_reg; struct cam_tfe_rdi_reg_data *reg_data; @@ -194,32 +211,36 @@ struct cam_tfe_top_hw_info { }; struct cam_tfe_hw_info { - uint32_t top_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; - uint32_t top_irq_clear[CAM_TFE_TOP_IRQ_REG_NUM]; - uint32_t top_irq_status[CAM_TFE_TOP_IRQ_REG_NUM]; - uint32_t top_irq_cmd; - uint32_t global_clear_bitmask; + uint32_t top_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t top_irq_clear[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t top_irq_status[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t top_irq_cmd; + uint32_t global_clear_bitmask; - uint32_t bus_irq_mask[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; - uint32_t bus_irq_clear[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; - uint32_t bus_irq_status[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; - uint32_t bus_irq_cmd; + uint32_t bus_irq_mask[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_irq_clear[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_irq_status[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_irq_cmd; - uint32_t bus_violation_reg; - uint32_t bus_overflow_reg; - uint32_t bus_image_size_vilation_reg; - uint32_t bus_overflow_clear_cmd; - uint32_t debug_status_top; + uint32_t bus_violation_reg; + uint32_t bus_overflow_reg; + uint32_t bus_image_size_vilation_reg; + uint32_t bus_overflow_clear_cmd; + uint32_t debug_status_top; - uint32_t reset_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; - uint32_t error_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; - uint32_t bus_reg_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t reset_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t error_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; + uint32_t bus_reg_irq_mask[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; + uint32_t bus_error_irq_mask[CAM_TFE_BUS_MAX_IRQ_REGISTERS]; - uint32_t top_version; - void *top_hw_info; + uint32_t num_clc; + struct cam_tfe_clc_hw_status *clc_hw_status_info; - uint32_t bus_version; - void *bus_hw_info; + uint32_t top_version; + void *top_hw_info; + + uint32_t bus_version; + void *bus_hw_info; }; struct cam_tfe_hw_core_info { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index b9329a8173e5..c0cfbe7a76e4 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -42,6 +42,7 @@ int cam_jpeg_enc_init_hw(void *device_priv, struct cam_jpeg_enc_device_core_info *core_info = NULL; struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote = {0}; + unsigned long flags; int rc; if (!device_priv) { @@ -92,6 +93,9 @@ int cam_jpeg_enc_init_hw(void *device_priv, CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc); goto soc_failed; } + spin_lock_irqsave(&jpeg_enc_dev->hw_lock, flags); + jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_UP; + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); mutex_unlock(&core_info->core_mutex); @@ -112,6 +116,7 @@ int cam_jpeg_enc_deinit_hw(void *device_priv, struct cam_hw_info *jpeg_enc_dev = device_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_enc_device_core_info *core_info = NULL; + unsigned long flags; int rc; if (!device_priv) { @@ -141,6 +146,9 @@ int cam_jpeg_enc_deinit_hw(void *device_priv, return -EFAULT; } + spin_lock_irqsave(&jpeg_enc_dev->hw_lock, flags); + jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); rc = cam_jpeg_enc_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_JPEG, "soc disable failed %d", rc); @@ -174,12 +182,19 @@ irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data) hw_info = core_info->jpeg_enc_hw_info; mem_base = soc_info->reg_map[0].mem_base; + spin_lock(&jpeg_enc_dev->hw_lock); + if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_ERR(CAM_JPEG, "JPEG HW is in off state"); + spin_unlock(&jpeg_enc_dev->hw_lock); + return IRQ_HANDLED; + } irq_status = cam_io_r_mb(mem_base + core_info->jpeg_enc_hw_info->reg_offset.int_status); cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + core_info->jpeg_enc_hw_info->reg_offset.int_clr); + spin_unlock(&jpeg_enc_dev->hw_lock); CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d", irq_num, irq_status, core_info->core_state); @@ -255,6 +270,7 @@ int cam_jpeg_enc_reset_hw(void *data, struct cam_jpeg_enc_device_hw_info *hw_info = NULL; void __iomem *mem_base; unsigned long rem_jiffies; + unsigned long flags; if (!jpeg_enc_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); @@ -268,17 +284,23 @@ int cam_jpeg_enc_reset_hw(void *data, mem_base = soc_info->reg_map[0].mem_base; mutex_lock(&core_info->core_mutex); - spin_lock(&jpeg_enc_dev->hw_lock); + spin_lock_irqsave(&jpeg_enc_dev->hw_lock, flags); + if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_ERR(CAM_JPEG, "JPEG HW is in off state"); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); + mutex_unlock(&core_info->core_mutex); + return -EINVAL; + } if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) { CAM_ERR(CAM_JPEG, "alrady resetting"); - spin_unlock(&jpeg_enc_dev->hw_lock); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); mutex_unlock(&core_info->core_mutex); return 0; } reinit_completion(&jpeg_enc_dev->hw_complete); core_info->core_state = CAM_JPEG_ENC_CORE_RESETTING; - spin_unlock(&jpeg_enc_dev->hw_lock); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); cam_io_w_mb(hw_info->reg_val.int_mask_disable_all, mem_base + hw_info->reg_offset.int_mask); @@ -308,6 +330,7 @@ int cam_jpeg_enc_start_hw(void *data, struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_enc_device_hw_info *hw_info = NULL; void __iomem *mem_base; + unsigned long flags; if (!jpeg_enc_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); @@ -320,10 +343,18 @@ int cam_jpeg_enc_start_hw(void *data, hw_info = core_info->jpeg_enc_hw_info; mem_base = soc_info->reg_map[0].mem_base; - if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) { - CAM_ERR(CAM_JPEG, "Error not ready"); + spin_lock_irqsave(&jpeg_enc_dev->hw_lock, flags); + if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_ERR(CAM_JPEG, "JPEG HW is in off state"); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); return -EINVAL; } + if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) { + CAM_ERR(CAM_JPEG, "Error not ready: %d", core_info->core_state); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); + return -EINVAL; + } + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); cam_io_w_mb(hw_info->reg_val.hw_cmd_start, mem_base + hw_info->reg_offset.hw_cmd); @@ -340,6 +371,7 @@ int cam_jpeg_enc_stop_hw(void *data, struct cam_jpeg_enc_device_hw_info *hw_info = NULL; void __iomem *mem_base; unsigned long rem_jiffies; + unsigned long flags; if (!jpeg_enc_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); @@ -352,17 +384,23 @@ int cam_jpeg_enc_stop_hw(void *data, mem_base = soc_info->reg_map[0].mem_base; mutex_lock(&core_info->core_mutex); - spin_lock(&jpeg_enc_dev->hw_lock); + spin_lock_irqsave(&jpeg_enc_dev->hw_lock, flags); + if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_ERR(CAM_JPEG, "JPEG HW is in off state"); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); + mutex_unlock(&core_info->core_mutex); + return -EINVAL; + } if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) { CAM_ERR(CAM_JPEG, "alrady stopping"); - spin_unlock(&jpeg_enc_dev->hw_lock); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); mutex_unlock(&core_info->core_mutex); return 0; } reinit_completion(&jpeg_enc_dev->hw_complete); core_info->core_state = CAM_JPEG_ENC_CORE_ABORTING; - spin_unlock(&jpeg_enc_dev->hw_lock); + spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); cam_io_w_mb(hw_info->reg_val.hw_cmd_stop, mem_base + hw_info->reg_offset.hw_cmd); diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 2671b95ff426..45ba114cc17a 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -85,6 +85,7 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) struct ope_cmd_work_data *task_data = NULL; struct cam_ope_ctx *ctx_data; struct cam_cdm_bl_request *cdm_cmd; + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; if (!data || !priv) { CAM_ERR(CAM_OPE, "Invalid params%pK %pK", data, priv); @@ -95,8 +96,23 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) task_data = (struct ope_cmd_work_data *)data; cdm_cmd = task_data->data; - CAM_DBG(CAM_OPE, "cam_cdm_submit_bls: handle = %u", - ctx_data->ope_cdm.cdm_handle); + CAM_DBG(CAM_OPE, + "cam_cdm_submit_bls: handle 0x%x, ctx_id %d req %d cookie %d", + ctx_data->ope_cdm.cdm_handle, ctx_data->ctx_id, + task_data->req_id, cdm_cmd->cookie); + + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (task_data->req_id <= ctx_data->last_flush_req) { + CAM_WARN(CAM_OPE, + "request %lld has been flushed, reject packet", + task_data->req_id, ctx_data->last_flush_req); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + + if (task_data->req_id > ctx_data->last_flush_req) + ctx_data->last_flush_req = 0; + rc = cam_cdm_submit_bls(ctx_data->ope_cdm.cdm_handle, cdm_cmd); if (!rc) @@ -104,6 +120,8 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) else CAM_ERR(CAM_OPE, "submit failed for %lld", cdm_cmd->cookie); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; } @@ -125,6 +143,20 @@ static int cam_ope_mgr_reset_hw(void) return rc; } +static void cam_ope_free_io_config(struct cam_ope_request *req) +{ + int i, j; + + for (i = 0; i < OPE_MAX_BATCH_SIZE; i++) { + for (j = 0; j < OPE_MAX_IO_BUFS; j++) { + if (req->io_buf[i][j]) { + kzfree(req->io_buf[i][j]); + req->io_buf[i][j] = NULL; + } + } + } +} + static void cam_ope_device_timer_stop(struct cam_ope_hw_mgr *hw_mgr) { if (hw_mgr->clk_info.watch_dog) { @@ -213,10 +245,363 @@ static bool cam_ope_is_pending_request(struct cam_ope_ctx *ctx_data) return !bitmap_empty(ctx_data->bitmap, CAM_CTX_REQ_MAX); } +static int cam_get_valid_ctx_id(void) +{ + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; + int i; + + for (i = 0; i < OPE_CTX_MAX; i++) { + if (hw_mgr->ctx[i].ctx_state == OPE_CTX_STATE_ACQUIRED) + break; + } + + if (i == OPE_CTX_MAX) + return -EINVAL; + + return i; +} + +static int32_t cam_ope_mgr_process_msg(void *priv, void *data) +{ + struct ope_msg_work_data *task_data; + struct cam_ope_hw_mgr *hw_mgr; + struct cam_ope_ctx *ctx; + uint32_t irq_status; + int32_t ctx_id; + int rc = 0, i; + + if (!data || !priv) { + CAM_ERR(CAM_OPE, "Invalid data"); + return -EINVAL; + } + + task_data = data; + hw_mgr = priv; + irq_status = task_data->irq_status; + ctx_id = cam_get_valid_ctx_id(); + if (ctx_id < 0) { + CAM_ERR(CAM_OPE, "No valid context to handle error"); + return ctx_id; + } + + ctx = &hw_mgr->ctx[ctx_id]; + + /* Indicate about this error to CDM and reset OPE*/ + rc = cam_cdm_handle_error(ctx->ope_cdm.cdm_handle); + + mutex_lock(&ctx->ctx_mutex); + if (ctx->ctx_state != OPE_CTX_STATE_ACQUIRED) { + CAM_DBG(CAM_OPE, "ctx id: %d not in right state: %d", + ctx_id, ctx->ctx_state); + mutex_unlock(&ctx->ctx_mutex); + return -EINVAL; + } + + for (i = 0; i < hw_mgr->num_ope; i++) { + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RESET, + NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "OPE Dev acquire failed: %d", rc); + } + + mutex_unlock(&ctx->ctx_mutex); + return rc; +} + +static int cam_ope_dump_hang_patches(struct cam_packet *packet, + struct cam_ope_hang_dump *dump) +{ + struct cam_patch_desc *patch_desc = NULL; + dma_addr_t iova_addr; + size_t src_buf_size; + int i, rc = 0; + int32_t iommu_hdl = ope_hw_mgr->iommu_hdl; + + /* process patch descriptor */ + patch_desc = (struct cam_patch_desc *) + ((uint32_t *) &packet->payload + + packet->patch_offset/4); + + for (i = 0; i < packet->num_patches; i++) { + rc = cam_mem_get_io_buf(patch_desc[i].src_buf_hdl, + iommu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, + "get src buf address failed for handle 0x%x", + patch_desc[i].src_buf_hdl); + return rc; + } + dump->entries[dump->num_bufs].memhdl = + patch_desc[i].src_buf_hdl; + dump->entries[dump->num_bufs].iova = iova_addr; + dump->entries[dump->num_bufs].offset = patch_desc[i].src_offset; + dump->entries[dump->num_bufs].len = 0; + dump->entries[dump->num_bufs].size = src_buf_size; + dump->num_bufs++; + } + return rc; +} + +static int cam_ope_dump_direct(struct ope_cmd_buf_info *cmd_buf_info, + struct cam_ope_hang_dump *dump) +{ + dma_addr_t iova_addr; + size_t size; + int rc = 0; + + rc = cam_mem_get_io_buf(cmd_buf_info->mem_handle, + ope_hw_mgr->iommu_hdl, &iova_addr, &size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get cmd buf addressfailed for handle 0x%x", + cmd_buf_info->mem_handle); + return rc; + } + dump->entries[dump->num_bufs].memhdl = cmd_buf_info->mem_handle; + dump->entries[dump->num_bufs].iova = iova_addr; + dump->entries[dump->num_bufs].offset = cmd_buf_info->offset; + dump->entries[dump->num_bufs].len = cmd_buf_info->length; + dump->entries[dump->num_bufs].size = size; + dump->num_bufs++; + return 0; +} + +static void cam_ope_dump_dmi(struct cam_ope_hang_dump *dump, uint32_t addr, + uint32_t length) +{ + int i; + uint32_t memhdl = 0, iova = 0, size; + + for (i = 0; i < dump->num_bufs; i++) { + if (dump->entries[i].iova + dump->entries[i].offset == addr) { + if (dump->entries[i].len == length) + goto end; + else if (dump->entries[i].len == 0) { + dump->entries[i].len = length; + goto end; + } else { + iova = dump->entries[i].iova; + memhdl = dump->entries[i].memhdl; + size = dump->entries[i].size; + } + } + } + if (memhdl && iova) { + dump->entries[dump->num_bufs].memhdl = memhdl; + dump->entries[dump->num_bufs].iova = iova; + dump->entries[dump->num_bufs].offset = addr - iova; + dump->entries[dump->num_bufs].len = length; + dump->entries[dump->num_bufs].size = size; + dump->num_bufs++; + } +end: + return; +} + +static int cam_ope_dump_indirect(struct ope_cmd_buf_info *cmd_buf_info, + struct cam_ope_hang_dump *dump) +{ + int rc = 0; + uintptr_t cpu_addr; + size_t buf_len; + uint32_t num_dmi; + struct cdm_dmi_cmd dmi_cmd; + uint32_t *print_ptr, print_idx; + + rc = cam_mem_get_cpu_buf(cmd_buf_info->mem_handle, + &cpu_addr, &buf_len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buf fail 0x%x", + cmd_buf_info->mem_handle); + return rc; + } + cpu_addr = cpu_addr + cmd_buf_info->offset; + + num_dmi = cmd_buf_info->length / + sizeof(struct cdm_dmi_cmd); + print_ptr = (uint32_t *)cpu_addr; + for (print_idx = 0; print_idx < num_dmi; print_idx++) { + memcpy(&dmi_cmd, (const void *)print_ptr, + sizeof(struct cdm_dmi_cmd)); + cam_ope_dump_dmi(dump, dmi_cmd.addr, dmi_cmd.length+1); + print_ptr += sizeof(struct cdm_dmi_cmd) / + sizeof(uint32_t); + } + return rc; +} + +static int cam_ope_mgr_dump_cmd_buf(uintptr_t frame_process_addr, + struct cam_ope_hang_dump *dump) +{ + int rc = 0; + int i, j; + struct ope_frame_process *frame_process; + struct ope_cmd_buf_info *cmd_buf; + + frame_process = (struct ope_frame_process *)frame_process_addr; + for (i = 0; i < frame_process->batch_size; i++) { + for (j = 0; j < frame_process->num_cmd_bufs[i]; j++) { + cmd_buf = &frame_process->cmd_buf[i][j]; + if (cmd_buf->type == OPE_CMD_BUF_TYPE_DIRECT) { + if (cmd_buf->cmd_buf_usage == OPE_CMD_BUF_DEBUG) + continue; + cam_ope_dump_direct(cmd_buf, dump); + } else if (cmd_buf->type == OPE_CMD_BUF_TYPE_INDIRECT) + cam_ope_dump_indirect(cmd_buf, dump); + } + } + return rc; +} + +static int cam_ope_mgr_dump_frame_set(uintptr_t frame_process_addr, + struct cam_ope_hang_dump *dump) +{ + int i, j, rc = 0; + dma_addr_t iova_addr; + size_t size; + struct ope_frame_process *frame_process; + struct ope_io_buf_info *io_buf; + struct cam_ope_buf_entry *buf_entry; + struct cam_ope_output_info *output_info; + + frame_process = (struct ope_frame_process *)frame_process_addr; + for (j = 0; j < frame_process->batch_size; j++) { + for (i = 0; i < frame_process->frame_set[j].num_io_bufs; i++) { + io_buf = &frame_process->frame_set[j].io_buf[i]; + rc = cam_mem_get_io_buf(io_buf->mem_handle[0], + ope_hw_mgr->iommu_hdl, &iova_addr, &size); + if (rc) { + CAM_ERR(CAM_OPE, "get io buf fail 0x%x", + io_buf->mem_handle[0]); + return rc; + } + buf_entry = &dump->entries[dump->num_bufs]; + buf_entry->memhdl = io_buf->mem_handle[0]; + buf_entry->iova = iova_addr; + buf_entry->offset = io_buf->plane_offset[0]; + buf_entry->len = size - io_buf->plane_offset[0]; + buf_entry->size = size; + dump->num_bufs++; + if (io_buf->direction == 2) { + output_info = + &dump->outputs[dump->num_outputs]; + output_info->iova = iova_addr; + output_info->offset = io_buf->plane_offset[0]; + output_info->len = size - + io_buf->plane_offset[0]; + dump->num_outputs++; + } + } + } + return rc; +} + +static int cam_ope_dump_frame_process(struct cam_packet *packet, + struct cam_ope_hang_dump *dump) +{ + int rc = 0; + int i; + size_t len; + struct cam_cmd_buf_desc *cmd_desc = NULL; + uintptr_t cpu_addr = 0; + + cmd_desc = (struct cam_cmd_buf_desc *) + ((uint32_t *) &packet->payload + packet->cmd_buf_offset/4); + for (i = 0; i < packet->num_cmd_buf; i++) { + if (cmd_desc[i].type != CAM_CMD_BUF_GENERIC || + cmd_desc[i].meta_data == OPE_CMD_META_GENERIC_BLOB) + continue; + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &cpu_addr, &len); + if (rc || !cpu_addr) { + CAM_ERR(CAM_OPE, "get cmd buf failed %x", + cmd_desc[i].mem_handle); + return rc; + } + cpu_addr = cpu_addr + cmd_desc[i].offset; + break; + } + + if (!cpu_addr) { + CAM_ERR(CAM_OPE, "invalid number of cmd buf"); + return -EINVAL; + } + + cam_ope_mgr_dump_cmd_buf(cpu_addr, dump); + cam_ope_mgr_dump_frame_set(cpu_addr, dump); + return rc; +} + +static int cam_ope_dump_bls(struct cam_ope_request *ope_req, + struct cam_ope_hang_dump *dump) +{ + struct cam_cdm_bl_request *cdm_cmd; + int i; + + cdm_cmd = ope_req->cdm_cmd; + for (i = 0; i < cdm_cmd->cmd_arrary_count; i++) { + dump->bl_entries[dump->num_bls].base = + (uint32_t)cdm_cmd->cmd[i].bl_addr.hw_iova + + cdm_cmd->cmd[i].offset; + dump->bl_entries[dump->num_bls].len = cdm_cmd->cmd[i].len; + dump->bl_entries[dump->num_bls].arbitration = + cdm_cmd->cmd[i].arbitrate; + dump->num_bls++; + } + return 0; +} + +static void cam_ope_dump_req_data(struct cam_ope_request *ope_req) +{ + struct cam_ope_hang_dump *dump; + struct cam_packet *packet = + (struct cam_packet *)ope_req->hang_data.packet; + + if (!ope_req->ope_debug_buf.cpu_addr || + ope_req->ope_debug_buf.len < sizeof(struct cam_ope_hang_dump) || + (ope_req->ope_debug_buf.offset + ope_req->ope_debug_buf.len) + > ope_req->ope_debug_buf.size) { + CAM_ERR(CAM_OPE, "Invalid debug buf, size %d %d len %d off %d", + sizeof(struct cam_ope_hang_dump), + ope_req->ope_debug_buf.size, + ope_req->ope_debug_buf.len, + ope_req->ope_debug_buf.offset); + return; + } + dump = (struct cam_ope_hang_dump *)ope_req->ope_debug_buf.cpu_addr; + memset(dump, 0, sizeof(struct cam_ope_hang_dump)); + dump->num_bufs = 0; + cam_ope_dump_hang_patches(packet, dump); + cam_ope_dump_frame_process(packet, dump); + cam_ope_dump_bls(ope_req, dump); +} + +static bool cam_ope_check_req_delay(struct cam_ope_ctx *ctx_data, + uint64_t req_time) +{ + struct timespec64 ts; + uint64_t ts_ns; + + get_monotonic_boottime64(&ts); + ts_ns = (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + + if (ts_ns - req_time < + ((OPE_REQUEST_TIMEOUT - + OPE_REQUEST_TIMEOUT / 10) * 1000000)) { + CAM_INFO(CAM_OPE, "ctx: %d, ts_ns : %llu", + ctx_data->ctx_id, ts_ns); + cam_ope_req_timer_reset(ctx_data); + return true; + } + + return false; +} + static int32_t cam_ope_process_request_timer(void *priv, void *data) { - struct ope_clk_work_data *task_data = (struct ope_clk_work_data *)data; - struct cam_ope_ctx *ctx_data = (struct cam_ope_ctx *)task_data->data; + struct ope_clk_work_data *clk_data = (struct ope_clk_work_data *)data; + struct cam_ope_ctx *ctx_data = (struct cam_ope_ctx *)clk_data->data; struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; uint32_t id; struct cam_hw_intf *dev_intf = NULL; @@ -225,6 +610,8 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) int i = 0; int device_share_ratio = 1; int path_index; + struct crm_workq_task *task; + struct ope_msg_work_data *task_data; if (!ctx_data) { CAM_ERR(CAM_OPE, "ctx_data is NULL, failed to update clk"); @@ -241,8 +628,61 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) } if (cam_ope_is_pending_request(ctx_data)) { - CAM_DBG(CAM_OPE, "pending requests means, issue is with HW"); - cam_cdm_handle_error(ctx_data->ope_cdm.cdm_handle); + + if (cam_ope_check_req_delay(ctx_data, + ctx_data->last_req_time)) { + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + if (cam_ope_check_req_delay(ctx_data, + ope_hw_mgr->last_callback_time)) { + CAM_WARN(CAM_OPE, + "ope ctx: %d stuck due to other contexts", + ctx_data->ctx_id); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + if (!cam_cdm_detect_hang_error(ctx_data->ope_cdm.cdm_handle)) { + cam_ope_req_timer_reset(ctx_data); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + /* Try checking ctx struck again */ + if (cam_ope_check_req_delay(ctx_data, + ope_hw_mgr->last_callback_time)) { + CAM_WARN(CAM_OPE, + "ope ctx: %d stuck due to other contexts", + ctx_data->ctx_id); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + + CAM_ERR(CAM_OPE, + "pending requests means, issue is with HW for ctx %d", + ctx_data->ctx_id); + CAM_ERR(CAM_OPE, "ctx: %d, lrt: %llu, lct: %llu", + ctx_data->ctx_id, ctx_data->last_req_time, + ope_hw_mgr->last_callback_time); + hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + hw_mgr->ope_dev_intf[i]->hw_priv, + OPE_HW_DUMP_DEBUG, + NULL, 0); + task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work); + if (!task) { + CAM_ERR(CAM_OPE, "no empty task"); + mutex_unlock(&ctx_data->ctx_mutex); + return 0; + } + task_data = (struct ope_msg_work_data *)task->payload; + task_data->data = hw_mgr; + task_data->irq_status = 1; + task_data->type = OPE_WORKQ_TASK_MSG_TYPE; + task->process_cb = cam_ope_mgr_process_msg; + cam_req_mgr_workq_enqueue_task(task, ope_hw_mgr, + CRM_TASK_PRIORITY_0); cam_ope_req_timer_reset(ctx_data); mutex_unlock(&ctx_data->ctx_mutex); return 0; @@ -372,7 +812,7 @@ static int cam_ope_start_req_timer(struct cam_ope_ctx *ctx_data) int rc = 0; rc = crm_timer_init(&ctx_data->req_watch_dog, - 200, ctx_data, &cam_ope_req_timer_cb); + OPE_REQUEST_TIMEOUT, ctx_data, &cam_ope_req_timer_cb); if (rc) CAM_ERR(CAM_OPE, "Failed to start timer"); @@ -525,19 +965,6 @@ static int cam_ope_device_timer_start(struct cam_ope_hw_mgr *hw_mgr) return rc; } -static int cam_get_valid_ctx_id(void) -{ - struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; - int i; - - for (i = 0; i < OPE_CTX_MAX; i++) { - if (hw_mgr->ctx[i].ctx_state == OPE_CTX_STATE_ACQUIRED) - break; - } - - return i; -} - static int cam_ope_get_actual_clk_rate_idx( struct cam_ope_ctx *ctx_data, uint32_t base_clk) { @@ -1091,6 +1518,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, struct cam_ope_ctx *ctx; struct cam_ope_request *ope_req; struct cam_hw_done_event_data buf_data; + struct timespec64 ts; bool flag = false; if (!userdata) { @@ -1098,15 +1526,35 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, return; } - CAM_DBG(CAM_FD, "CDM hdl=%x, udata=%pK, status=%d, cookie=%llu", - handle, userdata, status, cookie); + if (cookie >= CAM_CTX_REQ_MAX) { + CAM_ERR(CAM_OPE, "Invalid reqIdx = %llu", cookie); + return; + } ctx = userdata; + mutex_lock(&ctx->ctx_mutex); + + if (!test_bit(cookie, ctx->bitmap)) { + CAM_ERR(CAM_OPE, "Req not present reqIdx = %d for ctx_id = %d", + cookie, ctx->ctx_id); + goto end; + } + ope_req = ctx->req_list[cookie]; - mutex_lock(&ctx->ctx_mutex); + get_monotonic_boottime64(&ts); + ope_hw_mgr->last_callback_time = (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + + CAM_DBG(CAM_REQ, + "hdl=%x, udata=%pK, status=%d, cookie=%d", + handle, userdata, status, cookie); + CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lcb=%llu", + ope_req->request_id, ctx->ctx_id, + ope_hw_mgr->last_callback_time); + if (ctx->ctx_state != OPE_CTX_STATE_ACQUIRED) { - CAM_DBG(CAM_OPE, "ctx %u is in %d state", + CAM_ERR(CAM_OPE, "ctx %u is in %d state", ctx->ctx_id, ctx->ctx_state); mutex_unlock(&ctx->ctx_mutex); return; @@ -1126,10 +1574,13 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, goto end; } else { CAM_ERR(CAM_OPE, - "CDM hdl=%x, udata=%pK, status=%d, cookie=%d req_id = %llu", - handle, userdata, status, cookie, ope_req->request_id); + "CDM hdl=%x, udata=%pK, status=%d, cookie=%d req_id = %llu ctx_id=%d", + handle, userdata, status, cookie, + ope_req->request_id, ctx->ctx_id); CAM_ERR(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", ope_req->request_id); + if (status != CAM_CDM_CB_STATUS_HW_FLUSH) + cam_ope_dump_req_data(ope_req); rc = cam_ope_mgr_reset_hw(); flag = true; } @@ -1140,6 +1591,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id = 0; kzfree(ctx->req_list[cookie]->cdm_cmd); ctx->req_list[cookie]->cdm_cmd = NULL; + cam_ope_free_io_config(ctx->req_list[cookie]); kzfree(ctx->req_list[cookie]); ctx->req_list[cookie] = NULL; clear_bit(cookie, ctx->bitmap); @@ -1149,45 +1601,6 @@ end: mutex_unlock(&ctx->ctx_mutex); } -static int32_t cam_ope_mgr_process_msg(void *priv, void *data) -{ - struct ope_msg_work_data *task_data; - struct cam_ope_hw_mgr *hw_mgr; - struct cam_ope_ctx *ctx; - uint32_t irq_status; - int32_t ctx_id; - int rc = 0, i; - - if (!data || !priv) { - CAM_ERR(CAM_OPE, "Invalid data"); - return -EINVAL; - } - - task_data = data; - hw_mgr = priv; - irq_status = task_data->irq_status; - ctx_id = cam_get_valid_ctx_id(); - if (ctx_id < 0) { - CAM_ERR(CAM_OPE, "No valid context to handle error"); - return ctx_id; - } - - ctx = &hw_mgr->ctx[ctx_id]; - - /* Indicate about this error to CDM and reset OPE*/ - rc = cam_cdm_handle_error(ctx->ope_cdm.cdm_handle); - - for (i = 0; i < hw_mgr->num_ope; i++) { - rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( - hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RESET, - NULL, 0); - if (rc) - CAM_ERR(CAM_OPE, "OPE Dev acquire failed: %d", rc); - } - - return rc; -} - int32_t cam_ope_hw_mgr_cb(uint32_t irq_status, void *data) { int32_t rc = 0; @@ -1273,7 +1686,7 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, for (i = 0; i < ope_request->num_batch; i++) { for (l = 0; l < ope_request->num_io_bufs[i]; l++) { - io_buf = &ope_request->io_buf[i][l]; + io_buf = ope_request->io_buf[i][l]; if (io_buf->direction == CAM_BUF_INPUT) { if (io_buf->fence != -1) { sync_in_obj[j++] = io_buf->fence; @@ -1290,9 +1703,13 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, k++; prep_args->num_out_map_entries++; } else { - CAM_ERR(CAM_OPE, "Invalid fence %d %d", + if (io_buf->resource_type + != OPE_OUT_RES_STATS_LTM) { + CAM_ERR(CAM_OPE, + "Invalid fence %d %d", io_buf->resource_type, ope_request->request_id); + } } } CAM_DBG(CAM_REQ, @@ -1305,12 +1722,14 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, } } - if (prep_args->num_in_map_entries > 1) + if (prep_args->num_in_map_entries > 1 && + prep_args->num_in_map_entries <= CAM_MAX_IN_RES) prep_args->num_in_map_entries = cam_common_util_remove_duplicate_arr( sync_in_obj, prep_args->num_in_map_entries); - if (prep_args->num_in_map_entries > 1) { + if (prep_args->num_in_map_entries > 1 && + prep_args->num_in_map_entries <= CAM_MAX_IN_RES) { rc = cam_sync_merge(&sync_in_obj[0], prep_args->num_in_map_entries, &merged_sync_in_obj); if (rc) { @@ -1332,7 +1751,8 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, ope_request->in_resource = 0; CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]); } else { - CAM_DBG(CAM_OPE, "No input fences"); + CAM_DBG(CAM_OPE, "Invalid count of input fences, count: %d", + prep_args->num_in_map_entries); prep_args->num_in_map_entries = 0; ope_request->in_resource = 0; rc = -EINVAL; @@ -1433,7 +1853,15 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, for (j = 0; j < in_frame_set->num_io_bufs; j++) { in_io_buf = &in_frame_set->io_buf[j]; - io_buf = &ope_request->io_buf[i][j]; + ope_request->io_buf[i][j] = + kzalloc(sizeof(struct ope_io_buf), GFP_KERNEL); + if (!ope_request->io_buf[i][j]) { + CAM_ERR(CAM_OPE, + "IO config allocation failure"); + cam_ope_free_io_config(ope_request); + return -ENOMEM; + } + io_buf = ope_request->io_buf[i][j]; if (in_io_buf->num_planes > OPE_MAX_PLANES) { CAM_ERR(CAM_OPE, "wrong number of planes: %u", in_io_buf->num_planes); @@ -1510,7 +1938,7 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, stripe_info->width = in_stripe_info->width; stripe_info->height = - in_io_buf->height[k]; + in_stripe_info->height; stripe_info->stride = in_io_buf->plane_stride[k]; stripe_info->x_init = @@ -1634,6 +2062,8 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr, ope_request->ope_kmd_buf.iova_cdm_addr = iova_cdm_addr; ope_request->ope_kmd_buf.len = len; + ope_request->ope_kmd_buf.offset = + cmd_buf->offset; ope_request->ope_kmd_buf.size = cmd_buf->size; is_kmd_buf_valid = true; @@ -1649,9 +2079,11 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr, ope_request->ope_debug_buf.iova_addr = iova_addr; ope_request->ope_debug_buf.len = - len; + cmd_buf->length; ope_request->ope_debug_buf.size = - cmd_buf->size; + len; + ope_request->ope_debug_buf.offset = + cmd_buf->offset; CAM_DBG(CAM_OPE, "dbg buf = %x", ope_request->ope_debug_buf.cpu_addr); break; @@ -2043,10 +2475,10 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) struct cam_hw_acquire_args *args = hw_acquire_args; struct cam_ope_dev_acquire ope_dev_acquire; struct cam_ope_dev_release ope_dev_release; - struct cam_cdm_acquire_data cdm_acquire; + struct cam_cdm_acquire_data *cdm_acquire; struct cam_ope_dev_init init; struct cam_ope_dev_clk_update clk_update; - struct cam_ope_dev_bw_update bw_update; + struct cam_ope_dev_bw_update *bw_update; struct cam_ope_set_irq_cb irq_cb; if ((!hw_priv) || (!hw_acquire_args)) { @@ -2072,6 +2504,42 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) goto end; } + cdm_acquire = kzalloc(sizeof(struct cam_cdm_acquire_data), GFP_KERNEL); + if (!cdm_acquire) { + CAM_ERR(CAM_ISP, "Out of memory"); + goto end; + } + strlcpy(cdm_acquire->identifier, "ope", sizeof("ope")); + if (ctx->ope_acquire.dev_type == OPE_DEV_TYPE_OPE_RT) + cdm_acquire->priority = CAM_CDM_BL_FIFO_3; + else if (ctx->ope_acquire.dev_type == + OPE_DEV_TYPE_OPE_NRT) + cdm_acquire->priority = CAM_CDM_BL_FIFO_0; + else + goto free_cdm_acquire; + + cdm_acquire->cell_index = 0; + cdm_acquire->handle = 0; + cdm_acquire->userdata = ctx; + cdm_acquire->cam_cdm_callback = cam_ope_ctx_cdm_callback; + cdm_acquire->id = CAM_CDM_VIRTUAL; + cdm_acquire->base_array_cnt = 1; + cdm_acquire->base_array[0] = hw_mgr->cdm_reg_map[OPE_DEV_OPE][0]; + + rc = cam_cdm_acquire(cdm_acquire); + if (rc) { + CAM_ERR(CAM_OPE, "cdm_acquire is failed: %d", rc); + goto cdm_acquire_failed; + } + + ctx->ope_cdm.cdm_ops = cdm_acquire->ops; + ctx->ope_cdm.cdm_handle = cdm_acquire->handle; + + rc = cam_cdm_stream_on(cdm_acquire->handle); + if (rc) { + CAM_ERR(CAM_OPE, "cdm stream on failure: %d", rc); + goto cdm_stream_on_failure; + } if (!hw_mgr->ope_ctx_cnt) { for (i = 0; i < ope_hw_mgr->num_ope; i++) { @@ -2081,7 +2549,7 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) sizeof(init)); if (rc) { CAM_ERR(CAM_OPE, "OPE Dev init failed: %d", rc); - goto end; + goto ope_dev_init_failure; } } @@ -2099,6 +2567,19 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) goto ope_irq_set_failed; } } + + hw_mgr->clk_info.base_clk = 600000000; + hw_mgr->clk_info.curr_clk = 600000000; + hw_mgr->clk_info.threshold = 5; + hw_mgr->clk_info.over_clked = 0; + + for (i = 0; i < CAM_OPE_MAX_PER_PATH_VOTES; i++) { + hw_mgr->clk_info.axi_path[i].camnoc_bw = 0; + hw_mgr->clk_info.axi_path[i].mnoc_ab_bw = 0; + hw_mgr->clk_info.axi_path[i].mnoc_ib_bw = 0; + hw_mgr->clk_info.axi_path[i].ddr_ab_bw = 0; + hw_mgr->clk_info.axi_path[i].ddr_ib_bw = 0; + } } ope_dev_acquire.ctx_id = ctx_id; @@ -2114,39 +2595,6 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } } - memset(&cdm_acquire, 0, sizeof(cdm_acquire)); - strlcpy(cdm_acquire.identifier, "ope", sizeof("ope")); - if (ctx->ope_acquire.dev_type == OPE_DEV_TYPE_OPE_RT) - cdm_acquire.priority = CAM_CDM_BL_FIFO_3; - else if (ctx->ope_acquire.dev_type == - OPE_DEV_TYPE_OPE_NRT) - cdm_acquire.priority = CAM_CDM_BL_FIFO_0; - else - goto ope_dev_acquire_failed; - - cdm_acquire.cell_index = 0; - cdm_acquire.handle = 0; - cdm_acquire.userdata = ctx; - cdm_acquire.cam_cdm_callback = cam_ope_ctx_cdm_callback; - cdm_acquire.id = CAM_CDM_VIRTUAL; - cdm_acquire.base_array_cnt = 1; - cdm_acquire.base_array[0] = hw_mgr->cdm_reg_map[OPE_DEV_OPE][0]; - - rc = cam_cdm_acquire(&cdm_acquire); - if (rc) { - CAM_ERR(CAM_OPE, "cdm_acquire is failed: %d", rc); - goto cdm_acquire_failed; - } - - ctx->ope_cdm.cdm_ops = cdm_acquire.ops; - ctx->ope_cdm.cdm_handle = cdm_acquire.handle; - - rc = cam_cdm_stream_on(cdm_acquire.handle); - if (rc) { - CAM_ERR(CAM_OPE, "cdm stream on failure: %d", rc); - goto cdm_stream_on_failure; - } - for (i = 0; i < ope_hw_mgr->num_ope; i++) { clk_update.clk_rate = 600000000; rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( @@ -2158,25 +2606,30 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } } - bw_update.ahb_vote_valid = false; + bw_update = kzalloc(sizeof(struct cam_ope_dev_bw_update), GFP_KERNEL); + if (!bw_update) { + CAM_ERR(CAM_ISP, "Out of memory"); + goto ope_clk_update_failed; + } + bw_update->ahb_vote_valid = false; for (i = 0; i < ope_hw_mgr->num_ope; i++) { - bw_update.axi_vote.num_paths = 1; - bw_update.axi_vote_valid = true; - bw_update.axi_vote.axi_path[0].camnoc_bw = 600000000; - bw_update.axi_vote.axi_path[0].mnoc_ab_bw = 600000000; - bw_update.axi_vote.axi_path[0].mnoc_ib_bw = 600000000; - bw_update.axi_vote.axi_path[0].ddr_ab_bw = 600000000; - bw_update.axi_vote.axi_path[0].ddr_ib_bw = 600000000; - bw_update.axi_vote.axi_path[0].transac_type = + bw_update->axi_vote.num_paths = 1; + bw_update->axi_vote_valid = true; + bw_update->axi_vote.axi_path[0].camnoc_bw = 600000000; + bw_update->axi_vote.axi_path[0].mnoc_ab_bw = 600000000; + bw_update->axi_vote.axi_path[0].mnoc_ib_bw = 600000000; + bw_update->axi_vote.axi_path[0].ddr_ab_bw = 600000000; + bw_update->axi_vote.axi_path[0].ddr_ib_bw = 600000000; + bw_update->axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; - bw_update.axi_vote.axi_path[0].path_data_type = + bw_update->axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_BW_UPDATE, - &bw_update, sizeof(bw_update)); + bw_update, sizeof(*bw_update)); if (rc) { CAM_ERR(CAM_OPE, "OPE Dev clk update failed: %d", rc); - goto ope_bw_update_failed; + goto free_bw_update; } } @@ -2192,53 +2645,122 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) mutex_unlock(&ctx->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_INFO(CAM_OPE, "OPE: %d acquire succesfull rc %d", ctx_id, rc); return rc; +free_bw_update: + kzfree(bw_update); + bw_update = NULL; ope_clk_update_failed: -ope_bw_update_failed: -cdm_stream_on_failure: - cam_cdm_release(cdm_acquire.handle); - ctx->ope_cdm.cdm_ops = NULL; - ctx->ope_cdm.cdm_handle = 0; -cdm_acquire_failed: ope_dev_release.ctx_id = ctx_id; for (i = 0; i < ope_hw_mgr->num_ope; i++) { - rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + if (hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_RELEASE, - &ope_dev_release, sizeof(ope_dev_release)); - if (rc) - CAM_ERR(CAM_OPE, "OPE Dev release failed: %d", rc); + &ope_dev_release, sizeof(ope_dev_release))) + CAM_ERR(CAM_OPE, "OPE Dev release failed"); } - ope_dev_acquire_failed: if (!hw_mgr->ope_ctx_cnt) { irq_cb.ope_hw_mgr_cb = NULL; irq_cb.data = hw_mgr; for (i = 0; i < ope_hw_mgr->num_ope; i++) { init.hfi_en = ope_hw_mgr->hfi_en; - rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( + if (hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_SET_IRQ_CB, - &irq_cb, sizeof(irq_cb)); - CAM_ERR(CAM_OPE, "OPE IRQ de register failed"); + &irq_cb, sizeof(irq_cb))) + CAM_ERR(CAM_OPE, + "OPE IRQ de register failed"); } } ope_irq_set_failed: if (!hw_mgr->ope_ctx_cnt) { for (i = 0; i < ope_hw_mgr->num_ope; i++) { - rc = hw_mgr->ope_dev_intf[i]->hw_ops.deinit( - hw_mgr->ope_dev_intf[i]->hw_priv, NULL, 0); - if (rc) - CAM_ERR(CAM_OPE, "OPE deinit fail: %d", rc); + if (hw_mgr->ope_dev_intf[i]->hw_ops.deinit( + hw_mgr->ope_dev_intf[i]->hw_priv, NULL, 0)) + CAM_ERR(CAM_OPE, "OPE deinit fail"); + if (hw_mgr->ope_dev_intf[i]->hw_ops.stop( + hw_mgr->ope_dev_intf[i]->hw_priv, + NULL, 0)) + CAM_ERR(CAM_OPE, "OPE stop fail"); } } +ope_dev_init_failure: +cdm_stream_on_failure: + cam_cdm_release(cdm_acquire->handle); + ctx->ope_cdm.cdm_ops = NULL; + ctx->ope_cdm.cdm_handle = 0; + +cdm_acquire_failed: +free_cdm_acquire: + kzfree(cdm_acquire); + cdm_acquire = NULL; end: + args->ctxt_to_hw_map = NULL; cam_ope_put_free_ctx(hw_mgr, ctx_id); mutex_unlock(&ctx->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); return rc; } +static int cam_ope_mgr_remove_bw(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) +{ + int i, path_index, rc = 0; + struct cam_ope_ctx *ctx_data = NULL; + struct cam_ope_clk_info *hw_mgr_clk_info; + + ctx_data = &hw_mgr->ctx[ctx_id]; + hw_mgr_clk_info = &hw_mgr->clk_info; + + for (i = 0; i < ctx_data->clk_info.num_paths; i++) { + path_index = + ctx_data->clk_info.axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_OPE_START_OFFSET; + + if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + CAM_WARN(CAM_OPE, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_OPE_START_OFFSET, + CAM_OPE_MAX_PER_PATH_VOTES); + continue; + } + + hw_mgr_clk_info->axi_path[path_index].camnoc_bw -= + ctx_data->clk_info.axi_path[i].camnoc_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ab_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ab_bw; + hw_mgr_clk_info->axi_path[path_index].mnoc_ib_bw -= + ctx_data->clk_info.axi_path[i].mnoc_ib_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ab_bw -= + ctx_data->clk_info.axi_path[i].ddr_ab_bw; + hw_mgr_clk_info->axi_path[path_index].ddr_ib_bw -= + ctx_data->clk_info.axi_path[i].ddr_ib_bw; + } + + rc = cam_ope_update_cpas_vote(hw_mgr, ctx_data); + + return rc; +} + +static int cam_ope_mgr_ope_clk_remove(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) +{ + struct cam_ope_ctx *ctx_data = NULL; + struct cam_ope_clk_info *hw_mgr_clk_info; + + ctx_data = &hw_mgr->ctx[ctx_id]; + hw_mgr_clk_info = &hw_mgr->clk_info; + + if (hw_mgr_clk_info->base_clk >= ctx_data->clk_info.base_clk) + hw_mgr_clk_info->base_clk -= ctx_data->clk_info.base_clk; + + /* reset clock info */ + ctx_data->clk_info.curr_fc = 0; + ctx_data->clk_info.base_clk = 0; + + return 0; +} + static int cam_ope_mgr_release_ctx(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) { int i = 0, rc = 0; @@ -2286,6 +2808,7 @@ static int cam_ope_mgr_release_ctx(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) kzfree(hw_mgr->ctx[ctx_id].req_list[i]->cdm_cmd); hw_mgr->ctx[ctx_id].req_list[i]->cdm_cmd = NULL; } + cam_ope_free_io_config(hw_mgr->ctx[ctx_id].req_list[i]); kzfree(hw_mgr->ctx[ctx_id].req_list[i]); hw_mgr->ctx[ctx_id].req_list[i] = NULL; clear_bit(i, hw_mgr->ctx[ctx_id].bitmap); @@ -2294,7 +2817,13 @@ static int cam_ope_mgr_release_ctx(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) cam_ope_req_timer_stop(&hw_mgr->ctx[ctx_id]); hw_mgr->ctx[ctx_id].ope_cdm.cdm_handle = 0; hw_mgr->ctx[ctx_id].req_cnt = 0; + hw_mgr->ctx[ctx_id].last_flush_req = 0; cam_ope_put_free_ctx(hw_mgr, ctx_id); + + rc = cam_ope_mgr_ope_clk_remove(hw_mgr, ctx_id); + if (rc) + CAM_ERR(CAM_OPE, "OPE clk update failed: %d", rc); + hw_mgr->ope_ctx_cnt--; mutex_unlock(&hw_mgr->ctx[ctx_id].ctx_mutex); CAM_DBG(CAM_OPE, "X: ctx_id = %d", ctx_id); @@ -2363,6 +2892,21 @@ static int cam_ope_mgr_release_hw(void *hw_priv, void *hw_release_args) cam_ope_device_timer_stop(hw_mgr); } + rc = cam_ope_mgr_remove_bw(hw_mgr, ctx_id); + if (rc) + CAM_ERR(CAM_OPE, "OPE remove bw failed: %d", rc); + + if (!hw_mgr->ope_ctx_cnt) { + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + dev_intf = hw_mgr->ope_dev_intf[i]; + rc = dev_intf->hw_ops.stop( + hw_mgr->ope_dev_intf[i]->hw_priv, + NULL, 0); + if (rc) + CAM_ERR(CAM_OPE, "stop failed: %d", rc); + } + } + mutex_unlock(&hw_mgr->hw_mgr_mutex); CAM_DBG(CAM_OPE, "Release done for ctx_id %d", ctx_id); @@ -2498,6 +3042,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, uintptr_t ope_cmd_buf_addr; uint32_t request_idx = 0; struct cam_ope_request *ope_req; + struct timespec64 ts; if ((!prepare_args) || (!hw_mgr) || (!prepare_args->packet)) { CAM_ERR(CAM_OPE, "Invalid args: %x %x", @@ -2523,14 +3068,18 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, rc = cam_packet_util_validate_packet(packet, prepare_args->remain_len); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "packet validation is failed: %d", rc); + CAM_ERR(CAM_OPE, + "packet validation failed: %d req_id: %d ctx: %d", + rc, packet->header.request_id, ctx_data->ctx_id); return rc; } rc = cam_ope_mgr_pkt_validation(packet); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "ope packet validation is failed"); + CAM_ERR(CAM_OPE, + "ope packet validation failed: %d req_id: %d ctx: %d", + rc, packet->header.request_id, ctx_data->ctx_id); return -EINVAL; } @@ -2538,7 +3087,8 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, hw_mgr->iommu_sec_cdm_hdl); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "Patching is failed: %d", rc); + CAM_ERR(CAM_OPE, "Patching failed: %d req_id: %d ctx: %d", + rc, packet->header.request_id, ctx_data->ctx_id); return -EINVAL; } @@ -2548,11 +3098,19 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, CAM_ERR(CAM_OPE, "Invalid ctx req slot = %d", request_idx); return -EINVAL; } + get_monotonic_boottime64(&ts); + ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lrt=%llu", + packet->header.request_id, ctx_data->ctx_id, + ctx_data->last_req_time); + cam_ope_req_timer_modify(ctx_data, OPE_REQUEST_TIMEOUT); set_bit(request_idx, ctx_data->bitmap); - cam_ope_req_timer_reset(ctx_data); ctx_data->req_list[request_idx] = kzalloc(sizeof(struct cam_ope_request), GFP_KERNEL); if (!ctx_data->req_list[request_idx]) { + CAM_ERR(CAM_OPE, "mem allocation failed ctx:%d req_idx:%d", + ctx_data->ctx_id, request_idx); rc = -ENOMEM; mutex_unlock(&ctx_data->ctx_mutex); goto req_mem_alloc_failed; @@ -2565,6 +3123,8 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); if (!ope_req->cdm_cmd) { + CAM_ERR(CAM_OPE, "Cdm mem alloc failed ctx:%d req_idx:%d", + ctx_data->ctx_id, request_idx); rc = -ENOMEM; mutex_unlock(&ctx_data->ctx_mutex); goto req_cdm_mem_alloc_failed; @@ -2574,7 +3134,9 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, ctx_data, &ope_cmd_buf_addr, request_idx); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "cmd desc processing failed: %d", rc); + CAM_ERR(CAM_OPE, + "cmd desc processing failed :%d ctx: %d req_id:%d", + rc, ctx_data->ctx_id, packet->header.request_id); goto end; } @@ -2582,7 +3144,9 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, ctx_data, request_idx); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "IO cfg processing failed: %d", rc); + CAM_ERR(CAM_OPE, + "IO cfg processing failed: %d ctx: %d req_id:%d", + rc, ctx_data->ctx_id, packet->header.request_id); goto end; } @@ -2590,7 +3154,9 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, ctx_data, request_idx, ope_cmd_buf_addr); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "cam_ope_mgr_create_kmd_buf failed: %d", rc); + CAM_ERR(CAM_OPE, + "create kmd buf failed: %d ctx: %d request_id:%d", + rc, ctx_data->ctx_id, packet->header.request_id); goto end; } @@ -2598,16 +3164,21 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, request_idx, NULL); if (rc) { mutex_unlock(&ctx_data->ctx_mutex); - CAM_ERR(CAM_OPE, "Failed: %d", rc); + CAM_ERR(CAM_OPE, "Failed: %d ctx: %d req_id: %d req_idx: %d", + rc, ctx_data->ctx_id, packet->header.request_id, + request_idx); goto end; } prepare_args->num_hw_update_entries = 1; prepare_args->hw_update_entries[0].addr = (uintptr_t)ctx_data->req_list[request_idx]->cdm_cmd; prepare_args->priv = ctx_data->req_list[request_idx]; - + prepare_args->pf_data->packet = packet; + ope_req->hang_data.packet = packet; mutex_unlock(&ctx_data->ctx_mutex); + CAM_DBG(CAM_REQ, "Prepare Hw update Successful request_id: %d ctx: %d", + packet->header.request_id, ctx_data->ctx_id); return rc; end: @@ -2638,6 +3209,7 @@ static int cam_ope_mgr_handle_config_err( ope_req->request_id = 0; kzfree(ctx_data->req_list[req_idx]->cdm_cmd); ctx_data->req_list[req_idx]->cdm_cmd = NULL; + cam_ope_free_io_config(ctx_data->req_list[req_idx]); kzfree(ctx_data->req_list[req_idx]); ctx_data->req_list[req_idx] = NULL; clear_bit(req_idx, ctx_data->bitmap); @@ -2657,8 +3229,9 @@ static int cam_ope_mgr_enqueue_config(struct cam_ope_hw_mgr *hw_mgr, struct cam_ope_request *ope_req = NULL; ope_req = config_args->priv; - request_id = ope_req->request_id; + request_id = config_args->request_id; hw_update_entries = config_args->hw_update_entries; + CAM_DBG(CAM_OPE, "req_id = %lld %pK", request_id, config_args->priv); task = cam_req_mgr_workq_get_task(ope_hw_mgr->cmd_work); @@ -2717,11 +3290,18 @@ static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args) cam_ope_mgr_ope_clk_update(hw_mgr, ctx_data, ope_req->req_idx); + if (ope_req->request_id <= ctx_data->last_flush_req) + CAM_WARN(CAM_OPE, + "Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u", + ope_req->request_id, ctx_data->last_flush_req, + ctx_data->ctx_id); + rc = cam_ope_mgr_enqueue_config(hw_mgr, ctx_data, config_args); if (rc) goto config_err; - CAM_DBG(CAM_OPE, "req_id %llu, io config", ope_req->request_id); + CAM_DBG(CAM_REQ, "req_id %llu, ctx_id %u io config", + ope_req->request_id, ctx_data->ctx_id); mutex_unlock(&ctx_data->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); @@ -2793,6 +3373,7 @@ static int cam_ope_mgr_flush_req(struct cam_ope_ctx *ctx_data, ctx_data->req_list[idx]->request_id = 0; kzfree(ctx_data->req_list[idx]->cdm_cmd); ctx_data->req_list[idx]->cdm_cmd = NULL; + cam_ope_free_io_config(ctx_data->req_list[idx]); kzfree(ctx_data->req_list[idx]); ctx_data->req_list[idx] = NULL; clear_bit(idx, ctx_data->bitmap); @@ -2825,6 +3406,7 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data, ctx_data->req_list[i]->request_id = 0; kzfree(ctx_data->req_list[i]->cdm_cmd); ctx_data->req_list[i]->cdm_cmd = NULL; + cam_ope_free_io_config(ctx_data->req_list[i]); kzfree(ctx_data->req_list[i]); ctx_data->req_list[i] = NULL; clear_bit(i, ctx_data->bitmap); @@ -2838,6 +3420,7 @@ static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; struct cam_ope_ctx *ctx_data; + struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; if ((!hw_priv) || (!hw_flush_args)) { CAM_ERR(CAM_OPE, "Input params are Null"); @@ -2857,12 +3440,17 @@ static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args) return -EINVAL; } - CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d", - ctx_data->ctx_id, flush_args->flush_type); - switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: + mutex_lock(&hw_mgr->hw_mgr_mutex); + ctx_data->last_flush_req = flush_args->last_flush_req; + + CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d last_flush_req %u", + ctx_data->ctx_id, flush_args->flush_type, + ctx_data->last_flush_req); + cam_ope_mgr_flush_all(ctx_data, flush_args); + mutex_unlock(&hw_mgr->hw_mgr_mutex); break; case CAM_FLUSH_TYPE_REQ: mutex_lock(&ctx_data->ctx_mutex); diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index f7dcf9139da0..07ef8203bbef 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -60,6 +60,8 @@ #define CLK_HW_MAX 0x1 #define OPE_DEVICE_IDLE_TIMEOUT 400 +#define OPE_REQUEST_TIMEOUT 200 + /** @@ -223,12 +225,14 @@ struct cdm_dmi_cmd { * @iova_addr: IOVA address * @len: Buffer length * @size: Buffer Size + * @offset: buffer offset */ struct ope_debug_buffer { uintptr_t cpu_addr; dma_addr_t iova_addr; size_t len; uint32_t size; + uint32_t offset; }; /** @@ -238,6 +242,7 @@ struct ope_debug_buffer { * @cpu_addr: CPU address * @iova_addr: IOVA address * @iova_cdm_addr: CDM IOVA address + * @offset: Offset of buffer * @len: Buffer length * @size: Buffer Size */ @@ -246,6 +251,7 @@ struct ope_kmd_buffer { uintptr_t cpu_addr; dma_addr_t iova_addr; dma_addr_t iova_cdm_addr; + uint32_t offset; size_t len; uint32_t size; }; @@ -383,6 +389,7 @@ struct ope_io_buf { * @cdm_cmd: CDM command for OPE CDM * @clk_info: Clock Info V1 * @clk_info_v2: Clock Info V2 + * @hang_data: Debug data for HW error */ struct cam_ope_request { uint64_t request_id; @@ -398,10 +405,11 @@ struct cam_ope_request { uint8_t num_stripe_cmd_bufs[OPE_MAX_BATCH_SIZE][OPE_MAX_STRIPES]; struct ope_kmd_buffer ope_kmd_buf; struct ope_debug_buffer ope_debug_buf; - struct ope_io_buf io_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_IO_BUFS]; + struct ope_io_buf *io_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_IO_BUFS]; struct cam_cdm_bl_request *cdm_cmd; struct cam_ope_clk_bw_request clk_info; struct cam_ope_clk_bw_req_internal_v2 clk_info_v2; + struct cam_hw_mgr_dump_pf_data hang_data; }; /** @@ -431,11 +439,13 @@ struct cam_ope_cdm { * @ctxt_event_cb: Callback of a context * @req_list: Request List * @ope_cdm: OPE CDM info + * @last_req_time: Timestamp of last request * @req_watch_dog: Watchdog for requests * @req_watch_dog_reset_counter: Request reset counter * @clk_info: OPE Ctx clock info * @clk_watch_dog: Clock watchdog * @clk_watch_dog_reset_counter: Reset counter + * @last_flush_req: last flush req for this ctx */ struct cam_ope_ctx { void *context_priv; @@ -451,11 +461,13 @@ struct cam_ope_ctx { cam_hw_event_cb_func ctxt_event_cb; struct cam_ope_request *req_list[CAM_CTX_REQ_MAX]; struct cam_ope_cdm ope_cdm; + uint64_t last_req_time; struct cam_req_mgr_timer *req_watch_dog; uint32_t req_watch_dog_reset_counter; struct cam_ctx_clk_info clk_info; struct cam_req_mgr_timer *clk_watch_dog; uint32_t clk_watch_dog_reset_counter; + uint64_t last_flush_req; }; /** @@ -506,6 +518,7 @@ struct cam_ope_hw_mgr { struct cam_ope_ctx ctx[OPE_CTX_MAX]; struct cam_hw_intf **devices[OPE_DEV_MAX]; struct ope_query_cap_cmd ope_caps; + uint64_t last_callback_time; struct cam_req_mgr_core_workq *cmd_work; struct cam_req_mgr_core_workq *msg_work; @@ -518,4 +531,68 @@ struct cam_ope_hw_mgr { struct cam_ope_clk_info clk_info; }; +/** + * struct cam_ope_buf_entry + * + * @fd: FD of cmd buffer + * @memhdl: Memhandle of cmd buffer + * @iova: IOVA address of cmd buffer + * @offset: Offset of cmd buffer + * @len: Length of cmd buffer + * @size: Size of cmd buffer + */ +struct cam_ope_buf_entry { + uint32_t fd; + uint64_t memhdl; + uint64_t iova; + uint64_t offset; + uint64_t len; + uint64_t size; +}; + +/** + * struct cam_ope_bl_entry + * + * @base: Base IOVA address of BL + * @len: Length of BL + * @arbitration: Arbitration bit + */ +struct cam_ope_bl_entry { + uint32_t base; + uint32_t len; + uint32_t arbitration; +}; + +/** + * struct cam_ope_output_info + * + * @iova: IOVA address of output buffer + * @offset: Offset of buffer + * @len: Length of buffer + */ +struct cam_ope_output_info { + uint64_t iova; + uint64_t offset; + uint64_t len; +}; + +/** + * struct cam_ope_hang_dump + * + * @num_bls: count of BLs for request + * @num_bufs: Count of buffer related to request + * @num_outputs: Count of output beffers + * @entries: Buffers info + * @bl_entries: BLs info + * @outputs: Output info + */ +struct cam_ope_hang_dump { + uint32_t num_bls; + uint32_t num_bufs; + uint64_t num_outputs; + struct cam_ope_buf_entry entries[OPE_MAX_BATCH_SIZE * OPE_MAX_CMD_BUFS]; + struct cam_ope_bl_entry bl_entries[OPE_MAX_CDM_BLS]; + struct cam_ope_output_info outputs + [OPE_MAX_BATCH_SIZE * OPE_OUT_RES_MAX]; +}; #endif /* CAM_OPE_HW_MGR_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index 346016d2aae9..d58d4dd5e94a 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -29,6 +29,29 @@ static struct ope_bus_rd *bus_rd; +enum cam_ope_bus_unpacker_format { + UNPACKER_FMT_PLAIN_128 = 0x0, + UNPACKER_FMT_PLAIN_8 = 0x1, + UNPACKER_FMT_PLAIN_16_10BPP = 0x2, + UNPACKER_FMT_PLAIN_16_12BPP = 0x3, + UNPACKER_FMT_PLAIN_16_14BPP = 0x4, + UNPACKER_FMT_PLAIN_32_20BPP = 0x5, + UNPACKER_FMT_ARGB_16_10BPP = 0x6, + UNPACKER_FMT_ARGB_16_12BPP = 0x7, + UNPACKER_FMT_ARGB_16_14BPP = 0x8, + UNPACKER_FMT_PLAIN_32 = 0x9, + UNPACKER_FMT_PLAIN_64 = 0xA, + UNPACKER_FMT_TP_10 = 0xB, + UNPACKER_FMT_MIPI_8 = 0xC, + UNPACKER_FMT_MIPI_10 = 0xD, + UNPACKER_FMT_MIPI_12 = 0xE, + UNPACKER_FMT_MIPI_14 = 0xF, + UNPACKER_FMT_PLAIN_16_16BPP = 0x10, + UNPACKER_FMT_PLAIN_128_ODD_EVEN = 0x11, + UNPACKER_FMT_PLAIN_8_ODD_EVEN = 0x12, + UNPACKER_FMT_MAX = 0x13, +}; + static int cam_ope_bus_rd_in_port_idx(uint32_t input_port_id) { int i; @@ -98,12 +121,16 @@ static int cam_ope_bus_is_rm_enabled( } for (i = 0; i < ope_request->num_io_bufs[batch_idx]; i++) { - io_buf = &ope_request->io_buf[batch_idx][i]; + io_buf = ope_request->io_buf[batch_idx][i]; if (io_buf->direction != CAM_BUF_INPUT) continue; in_port_to_rm = &bus_rd->in_port_to_rm[io_buf->resource_type - 1]; combo_idx = cam_ope_bus_rd_combo_idx(io_buf->format); + if (combo_idx < 0) { + CAM_ERR(CAM_OPE, "Invalid combo_idx"); + return -EINVAL; + } for (k = 0; k < io_buf->num_planes; k++) { if (rm_id == in_port_to_rm->rm_port_id[combo_idx][k]) @@ -171,7 +198,7 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, rd_reg = ope_hw_info->bus_rd_reg; rd_reg_val = ope_hw_info->bus_rd_reg_val; - io_buf = &ope_request->io_buf[batch_idx][io_idx]; + io_buf = ope_request->io_buf[batch_idx][io_idx]; CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d", batch_idx, io_idx, io_buf->direction); @@ -239,6 +266,14 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, rd_reg_client->stride; temp_reg[count++] = stripe_io->stride; + /* + * In case of NV12, change the unpacker format of + * chroma plane to odd even byte swapped format. + */ + if (k == 1 && stripe_io->format == CAM_FORMAT_NV12) + stripe_io->unpack_format = + UNPACKER_FMT_PLAIN_8_ODD_EVEN; + /* Unpack cfg : Mode and alignment */ temp_reg[count++] = rd_reg->offset + rd_reg_client->unpack_cfg; @@ -324,6 +359,11 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info, return NULL; } + if (rm_idx >= MAX_RD_CLIENTS) { + CAM_ERR(CAM_OPE, "Invalid read client: %d", rm_idx); + return NULL; + } + ctx_data = prepare->ctx_data; req_idx = prepare->req_idx; cdm_ops = ctx_data->ope_cdm.cdm_ops; @@ -403,9 +443,9 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, struct cam_ope_bus_rd_reg *rd_reg; struct cam_ope_bus_rd_reg_val *rd_reg_val; struct ope_bus_rd_io_port_cdm_batch *io_port_cdm_batch; - struct ope_bus_rd_io_port_cdm_info *io_port_cdm; + struct ope_bus_rd_io_port_cdm_info *io_port_cdm = NULL; struct cam_cdm_utils_ops *cdm_ops; - int32_t num_stripes; + int32_t num_stripes = 0; if (ctx_id < 0 || !data) { CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); @@ -434,7 +474,7 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, for (i = 0; i < ope_request->num_batch; i++) { for (j = 0; j < ope_request->num_io_bufs[i]; j++) { - io_buf = &ope_request->io_buf[i][j]; + io_buf = ope_request->io_buf[i][j]; if (io_buf->direction != CAM_BUF_INPUT) continue; @@ -469,12 +509,20 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, for (j = 0; j < rd_reg_val->num_clients; j++) { is_rm_enabled = cam_ope_bus_is_rm_enabled( ope_request, i, j); + if (is_rm_enabled < 0) { + rc = -EINVAL; + goto end; + } if (is_rm_enabled) continue; kmd_buf = cam_ope_bus_rm_disable(ope_hw_info, ctx_id, prepare, i, j, kmd_buf, num_stripes); + if (!kmd_buf) { + rc = -EINVAL; + goto end; + } } } @@ -772,7 +820,7 @@ static int cam_ope_bus_rd_isr(struct ope_hw *ope_hw_info, if (irq_status & bus_rd_reg_val->rst_done) { complete(&bus_rd->reset_complete); - CAM_ERR(CAM_OPE, "ope bus rd reset done"); + CAM_DBG(CAM_OPE, "ope bus rd reset done"); } if ((irq_status & bus_rd_reg_val->violation) == diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c index 75d7339e0bf4..bade41972a26 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c @@ -29,6 +29,24 @@ static struct ope_bus_wr *wr_info; +enum cam_ope_bus_packer_format { + PACKER_FMT_PLAIN_128 = 0x0, + PACKER_FMT_PLAIN_8 = 0x1, + PACKER_FMT_PLAIN_8_ODD_EVEN = 0x2, + PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0x3, + PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0x4, + PACKER_FMT_PLAIN_16_10BPP = 0x5, + PACKER_FMT_PLAIN_16_12BPP = 0x6, + PACKER_FMT_PLAIN_16_14BPP = 0x7, + PACKER_FMT_PLAIN_16_16BPP = 0x8, + PACKER_FMT_PLAIN_32 = 0x9, + PACKER_FMT_PLAIN_64 = 0xA, + PACKER_FMT_TP_10 = 0xB, + PACKER_FMT_MIPI_10 = 0xC, + PACKER_FMT_MIPI_12 = 0xD, + PACKER_FMT_MAX = 0xE, +}; + static int cam_ope_bus_en_port_idx( struct cam_ope_request *ope_request, uint32_t batch_idx, @@ -43,7 +61,7 @@ static int cam_ope_bus_en_port_idx( } for (i = 0; i < ope_request->num_io_bufs[batch_idx]; i++) { - io_buf = &ope_request->io_buf[batch_idx][i]; + io_buf = ope_request->io_buf[batch_idx][i]; if (io_buf->direction != CAM_BUF_OUTPUT) continue; if (io_buf->resource_type == output_port_id) @@ -133,25 +151,15 @@ static int cam_ope_bus_wr_subsample( static int cam_ope_bus_wr_release(struct ope_hw *ope_hw_info, int32_t ctx_id, void *data) { - int rc = 0, i; - struct ope_acquire_dev_info *in_acquire; - struct ope_bus_wr_ctx *bus_wr_ctx; + int rc = 0; - if (ctx_id < 0) { + if (ctx_id < 0 || ctx_id >= OPE_CTX_MAX) { CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id); return -EINVAL; } - in_acquire = wr_info->bus_wr_ctx[ctx_id].ope_acquire; - wr_info->bus_wr_ctx[ctx_id].ope_acquire = NULL; - bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; - bus_wr_ctx->num_out_ports = 0; - - for (i = 0; i < bus_wr_ctx->num_out_ports; i++) { - bus_wr_ctx->io_port_info.output_port_id[i] = 0; - bus_wr_ctx->io_port_info.output_format_type[i - 1] = 0; - bus_wr_ctx->io_port_info.pixel_pattern[i - 1] = 0; - } + vfree(wr_info->bus_wr_ctx[ctx_id]); + wr_info->bus_wr_ctx[ctx_id] = NULL; return rc; } @@ -208,7 +216,7 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, cdm_ops = ctx_data->ope_cdm.cdm_ops; ope_request = ctx_data->req_list[req_idx]; - bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id]; io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; wr_reg = ope_hw_info->bus_wr_reg; wr_reg_val = ope_hw_info->bus_wr_reg_val; @@ -217,7 +225,7 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, kmd_buf, req_idx, ope_request->request_id, prepare->kmd_buf_offset); - io_buf = &ope_request->io_buf[batch_idx][io_idx]; + io_buf = ope_request->io_buf[batch_idx][io_idx]; CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d", batch_idx, io_idx, io_buf->direction); @@ -286,6 +294,16 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, temp_reg[count++] = wr_reg->offset + wr_reg_client->pack_cfg; temp = 0; + + /* + * In case of NV12, change the packer format of chroma + * plane to odd even byte swapped format + */ + + if (k == 1 && stripe_io->format == CAM_FORMAT_NV12) + stripe_io->pack_format = + PACKER_FMT_PLAIN_8_ODD_EVEN; + temp |= ((stripe_io->pack_format & wr_res_val_client->format_mask) << wr_res_val_client->format_shift); @@ -376,7 +394,7 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, req_idx = prepare->req_idx; cdm_ops = ctx_data->ope_cdm.cdm_ops; - bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id]; io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; wr_reg = ope_hw_info->bus_wr_reg; @@ -466,7 +484,7 @@ static int cam_ope_bus_wr_prepare(struct ope_hw *ope_hw_info, prepare = data; ctx_data = prepare->ctx_data; req_idx = prepare->req_idx; - bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id]; ope_request = ctx_data->req_list[req_idx]; kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + @@ -477,13 +495,13 @@ static int cam_ope_bus_wr_prepare(struct ope_hw *ope_hw_info, kmd_buf, req_idx, ope_request->request_id, prepare->kmd_buf_offset); - io_port_cdm_batch = &wr_info->bus_wr_ctx[ctx_id].io_port_cdm_batch; + io_port_cdm_batch = &wr_info->bus_wr_ctx[ctx_id]->io_port_cdm_batch; memset(io_port_cdm_batch, 0, sizeof(struct ope_bus_wr_io_port_cdm_batch)); for (i = 0; i < ope_request->num_batch; i++) { for (j = 0; j < ope_request->num_io_bufs[i]; j++) { - io_buf = &ope_request->io_buf[i][j]; + io_buf = ope_request->io_buf[i][j]; CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d", i, j, io_buf->direction); if (io_buf->direction != CAM_BUF_OUTPUT) @@ -533,14 +551,20 @@ static int cam_ope_bus_wr_acquire(struct ope_hw *ope_hw_info, int combo_idx; int out_port_idx; - if (ctx_id < 0 || !data) { + if (ctx_id < 0 || !data || ctx_id >= OPE_CTX_MAX) { CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data); return -EINVAL; } - wr_info->bus_wr_ctx[ctx_id].ope_acquire = data; + wr_info->bus_wr_ctx[ctx_id] = vzalloc(sizeof(struct ope_bus_wr_ctx)); + if (!wr_info->bus_wr_ctx[ctx_id]) { + CAM_ERR(CAM_OPE, "Out of memory"); + return -ENOMEM; + } + + wr_info->bus_wr_ctx[ctx_id]->ope_acquire = data; in_acquire = data; - bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id]; + bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id]; bus_wr_ctx->num_out_ports = in_acquire->num_out_res; bus_wr_ctx->security_flag = in_acquire->secure_mode; @@ -688,11 +712,12 @@ static int cam_ope_bus_wr_isr(struct ope_hw *ope_hw_info, int32_t ctx_id, void *data) { int rc = 0; - uint32_t irq_status_0, irq_status_1; + uint32_t irq_status_0, irq_status_1, violation_status; struct cam_ope_bus_wr_reg *bus_wr_reg; struct cam_ope_bus_wr_reg_val *bus_wr_reg_val; + struct cam_ope_irq_data *irq_data = data; - if (!ope_hw_info) { + if (!ope_hw_info || !irq_data) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); return -EINVAL; } @@ -712,15 +737,26 @@ static int cam_ope_bus_wr_isr(struct ope_hw *ope_hw_info, bus_wr_reg->base + bus_wr_reg->irq_cmd); if (irq_status_0 & bus_wr_reg_val->cons_violation) { + irq_data->error = 1; CAM_ERR(CAM_OPE, "ope bus wr cons_violation"); } if (irq_status_0 & bus_wr_reg_val->violation) { - CAM_ERR(CAM_OPE, "ope bus wr vioalation"); + irq_data->error = 1; + violation_status = cam_io_r_mb(bus_wr_reg->base + + bus_wr_reg->violation_status); + CAM_ERR(CAM_OPE, + "ope bus wr violation, violation_status 0x%x", + violation_status); } if (irq_status_0 & bus_wr_reg_val->img_size_violation) { - CAM_ERR(CAM_OPE, "ope bus wr img_size_violation"); + irq_data->error = 1; + violation_status = cam_io_r_mb(bus_wr_reg->base + + bus_wr_reg->image_size_violation_status); + CAM_ERR(CAM_OPE, + "ope bus wr img_size_violation, violation_status 0x%x", + violation_status); } return rc; @@ -769,7 +805,7 @@ int cam_ope_bus_wr_process(struct ope_hw *ope_hw_info, CAM_DBG(CAM_OPE, "Unhandled cmds: %d", cmd_id); break; case OPE_HW_ISR: - rc = cam_ope_bus_wr_isr(ope_hw_info, 0, NULL); + rc = cam_ope_bus_wr_isr(ope_hw_info, 0, data); break; default: CAM_ERR(CAM_OPE, "Unsupported cmd: %d", cmd_id); diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h index 0eb052b1687b..ed9b8cca68df 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h @@ -130,7 +130,7 @@ struct ope_bus_wr_ctx { struct ope_bus_wr { struct ope_hw *ope_hw_info; struct ope_bus_out_port_to_wm out_port_to_wm[OPE_OUT_RES_MAX]; - struct ope_bus_wr_ctx bus_wr_ctx[OPE_CTX_MAX]; + struct ope_bus_wr_ctx *bus_wr_ctx[OPE_CTX_MAX]; }; #endif /* OPE_BUS_WR_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index 1fc49cebbb09..8a46b71241d6 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -96,7 +96,29 @@ int cam_ope_start(void *hw_priv, void *start_args, uint32_t arg_size) int cam_ope_stop(void *hw_priv, void *start_args, uint32_t arg_size) { - return 0; + struct cam_hw_info *ope_dev = hw_priv; + struct cam_ope_device_core_info *core_info = NULL; + int rc = 0; + + if (!hw_priv) { + CAM_ERR(CAM_OPE, "Invalid cam_dev_info"); + return -EINVAL; + } + + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + if (!core_info) { + CAM_ERR(CAM_OPE, "core_info = %pK", core_info); + return -EINVAL; + } + + if (core_info->cpas_start) { + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_OPE, "cpas stop is failed"); + else + core_info->cpas_start = false; + } + + return rc; } int cam_ope_flush(void *hw_priv, void *flush_args, uint32_t arg_size) @@ -149,14 +171,15 @@ int cam_ope_init_hw(void *device_priv, struct cam_hw_info *ope_dev = device_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_ope_device_core_info *core_info = NULL; - struct cam_ope_cpas_vote cpas_vote; + struct cam_ope_cpas_vote *cpas_vote; int rc = 0; struct cam_ope_dev_init *init; struct ope_hw *ope_hw; if (!device_priv) { CAM_ERR(CAM_OPE, "Invalid cam_dev_info"); - return -EINVAL; + rc = -EINVAL; + goto end; } soc_info = &ope_dev->soc_info; @@ -164,55 +187,72 @@ int cam_ope_init_hw(void *device_priv, if ((!soc_info) || (!core_info)) { CAM_ERR(CAM_OPE, "soc_info = %pK core_info = %pK", soc_info, core_info); - return -EINVAL; + rc = -EINVAL; + goto end; } ope_hw = core_info->ope_hw_info->ope_hw; + cpas_vote = kzalloc(sizeof(struct cam_ope_cpas_vote), GFP_KERNEL); + if (!cpas_vote) { + CAM_ERR(CAM_ISP, "Out of memory"); + rc = -ENOMEM; + goto end; + } - cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE; - cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE; - cpas_vote.axi_vote.num_paths = 1; - cpas_vote.axi_vote.axi_path[0].path_data_type = + cpas_vote->ahb_vote.type = CAM_VOTE_ABSOLUTE; + cpas_vote->ahb_vote.vote.level = CAM_SVS_VOTE; + cpas_vote->axi_vote.num_paths = 1; + cpas_vote->axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; - cpas_vote.axi_vote.axi_path[0].transac_type = + cpas_vote->axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; - cpas_vote.axi_vote.axi_path[0].camnoc_bw = + cpas_vote->axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; - cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw = + cpas_vote->axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; - cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw = + cpas_vote->axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; - cpas_vote.axi_vote.axi_path[0].ddr_ab_bw = + cpas_vote->axi_vote.axi_path[0].ddr_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; - cpas_vote.axi_vote.axi_path[0].ddr_ib_bw = + cpas_vote->axi_vote.axi_path[0].ddr_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; rc = cam_cpas_start(core_info->cpas_handle, - &cpas_vote.ahb_vote, &cpas_vote.axi_vote); + &cpas_vote->ahb_vote, &cpas_vote->axi_vote); if (rc) { CAM_ERR(CAM_OPE, "cpass start failed: %d", rc); - return rc; + goto free_cpas_vote; } core_info->cpas_start = true; rc = cam_ope_enable_soc_resources(soc_info); - if (rc) { - CAM_ERR(CAM_OPE, "soc enable is failed : %d", rc); - if (cam_cpas_stop(core_info->cpas_handle)) - CAM_ERR(CAM_OPE, "cpas stop is failed"); - else - core_info->cpas_start = false; - } else { + if (rc) + goto enable_soc_resource_failed; + else core_info->clk_enable = true; - } init = init_hw_args; core_info->ope_hw_info->hfi_en = init->hfi_en; init->core_info = core_info; - rc = cam_ope_process_init(ope_hw, init_hw_args, init->hfi_en); + if (rc) + goto process_init_failed; + else + goto free_cpas_vote; +process_init_failed: + if (cam_ope_disable_soc_resources(soc_info, core_info->clk_enable)) + CAM_ERR(CAM_OPE, "disable soc resource failed"); +enable_soc_resource_failed: + if (cam_cpas_stop(core_info->cpas_handle)) + CAM_ERR(CAM_OPE, "cpas stop is failed"); + else + core_info->cpas_start = false; +free_cpas_vote: + kzfree(cpas_vote); + cpas_vote = NULL; +end: return rc; } @@ -242,12 +282,15 @@ int cam_ope_deinit_hw(void *device_priv, CAM_ERR(CAM_OPE, "soc disable is failed : %d", rc); core_info->clk_enable = false; - if (core_info->cpas_start) { - if (cam_cpas_stop(core_info->cpas_handle)) - CAM_ERR(CAM_OPE, "cpas stop is failed"); - else - core_info->cpas_start = false; - } + return rc; +} + +static int cam_ope_dev_process_dump_debug_reg(struct ope_hw *ope_hw) +{ + int rc = 0; + + rc = cam_ope_top_process(ope_hw, -1, + OPE_HW_DUMP_DEBUG, NULL); return rc; } @@ -310,14 +353,11 @@ static int cam_ope_dev_process_acquire(struct ope_hw *ope_hw, void *cmd_args) return 0; bus_wr_acquire_fail: - rc = cam_ope_bus_rd_process(ope_hw, ope_dev_acquire->ctx_id, + cam_ope_bus_rd_process(ope_hw, ope_dev_acquire->ctx_id, OPE_HW_RELEASE, ope_dev_acquire->ope_acquire); bus_rd_acquire_fail: - rc = cam_ope_top_process(ope_hw, ope_dev_acquire->ctx_id, + cam_ope_top_process(ope_hw, ope_dev_acquire->ctx_id, OPE_HW_RELEASE, ope_dev_acquire->ope_acquire); - if (rc) - goto top_acquire_fail; - top_acquire_fail: return rc; } @@ -340,16 +380,17 @@ static int cam_ope_dev_prepare_cdm_request( kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr + kmd_buf_offset; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_HW_IOVA; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = true; cdm_cmd->userdata = ctx_data; cdm_cmd->cookie = req_idx; cdm_cmd->gen_irq_arb = true; i = cdm_cmd->cmd_arrary_count; - cdm_cmd->cmd[i].bl_addr.hw_iova = - (uint32_t *)ope_request->ope_kmd_buf.iova_cdm_addr; - cdm_cmd->cmd[i].offset = kmd_buf_offset; + cdm_cmd->cmd[i].bl_addr.mem_handle = + ope_request->ope_kmd_buf.mem_handle; + cdm_cmd->cmd[i].offset = kmd_buf_offset + + ope_request->ope_kmd_buf.offset; cdm_cmd->cmd[i].len = len; cdm_cmd->cmd[i].arbitrate = arbitrate; @@ -365,6 +406,7 @@ static int cam_ope_dev_prepare_cdm_request( return 0; } + static int dump_dmi_cmd(uint32_t print_idx, uint32_t *print_ptr, struct cdm_dmi_cmd *dmi_cmd, uint32_t *temp) @@ -449,119 +491,6 @@ static int dump_stripe_cmd(struct ope_frame_process *frm_proc, return 0; } -static uint32_t *ope_create_frame_cmd_prefetch_dis( - struct cam_ope_hw_mgr *hw_mgr, - struct cam_ope_ctx *ctx_data, uint32_t req_idx, - uint32_t *kmd_buf, uint32_t buffered, int batch_idx, - struct cam_ope_dev_prepare_req *ope_dev_prepare_req) -{ - int rc = 0, i, j; - uint32_t temp[3]; - struct cam_ope_request *ope_request; - struct cdm_dmi_cmd *dmi_cmd; - struct ope_bus_wr_io_port_cdm_info *wr_cdm_info; - struct ope_bus_rd_io_port_cdm_info *rd_cdm_info; - struct ope_frame_process *frm_proc; - dma_addr_t iova_addr; - uintptr_t cpu_addr; - size_t buf_len; - uint32_t print_idx; - uint32_t *print_ptr; - int num_dmi = 0; - struct cam_cdm_utils_ops *cdm_ops; - - frm_proc = ope_dev_prepare_req->frame_process; - ope_request = ctx_data->req_list[req_idx]; - cdm_ops = ctx_data->ope_cdm.cdm_ops; - wr_cdm_info = - &ope_dev_prepare_req->wr_cdm_batch->io_port_cdm[0]; - rd_cdm_info = - &ope_dev_prepare_req->rd_cdm_batch->io_port_cdm[0]; - - if (batch_idx >= OPE_MAX_BATCH_SIZE) { - CAM_ERR(CAM_OPE, "Invalid input: %d", batch_idx); - return NULL; - } - - i = batch_idx; - - for (j = 0; j < frm_proc->num_cmd_bufs[i]; j++) { - if (frm_proc->cmd_buf[i][j].cmd_buf_scope != - OPE_CMD_BUF_SCOPE_FRAME) - continue; - - if (frm_proc->cmd_buf[i][j].cmd_buf_usage == - OPE_CMD_BUF_KMD || - frm_proc->cmd_buf[i][j].cmd_buf_usage == - OPE_CMD_BUF_DEBUG) - continue; - - if (frm_proc->cmd_buf[i][j].prefetch_disable && - frm_proc->cmd_buf[i][j].cmd_buf_buffered != - buffered) - continue; - - if (!frm_proc->cmd_buf[i][j].mem_handle) - continue; - - rc = cam_mem_get_io_buf( - frm_proc->cmd_buf[i][j].mem_handle, - hw_mgr->iommu_cdm_hdl, &iova_addr, &buf_len); - if (rc) { - CAM_ERR(CAM_OPE, "get cmd buf failed %x", - hw_mgr->iommu_hdl); - return NULL; - } - iova_addr = iova_addr + frm_proc->cmd_buf[i][j].offset; - - rc = cam_mem_get_cpu_buf( - frm_proc->cmd_buf[i][j].mem_handle, - &cpu_addr, &buf_len); - if (rc || !cpu_addr) { - CAM_ERR(CAM_OPE, "get cmd buf failed %x", - hw_mgr->iommu_hdl); - return NULL; - } - - cpu_addr = cpu_addr + frm_proc->cmd_buf[i][j].offset; - if (frm_proc->cmd_buf[i][j].type == - OPE_CMD_BUF_TYPE_DIRECT) { - kmd_buf = cdm_ops->cdm_write_indirect(kmd_buf, - iova_addr, - frm_proc->cmd_buf[i][j].length); - print_ptr = (uint32_t *)cpu_addr; - dump_frame_direct(print_idx, print_ptr, - frm_proc, i, j); - } else { - num_dmi = frm_proc->cmd_buf[i][j].length / - sizeof(struct cdm_dmi_cmd); - CAM_DBG(CAM_OPE, "Frame DB : In direct: E"); - print_ptr = (uint32_t *)cpu_addr; - for (print_idx = 0; - print_idx < num_dmi; print_idx++) { - memcpy(temp, (const void *)print_ptr, - sizeof(struct cdm_dmi_cmd)); - dmi_cmd = (struct cdm_dmi_cmd *)temp; - kmd_buf = cdm_ops->cdm_write_dmi( - kmd_buf, - 0, dmi_cmd->DMIAddr, - dmi_cmd->DMISel, dmi_cmd->addr, - dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); - print_ptr += - sizeof(struct cdm_dmi_cmd) / - sizeof(uint32_t); - } - CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); - } - dump_frame_cmd(frm_proc, i, j, - iova_addr, kmd_buf, buf_len); - } - return kmd_buf; - -} - static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, struct cam_ope_ctx *ctx_data, uint32_t req_idx, uint32_t *kmd_buf, uint32_t buffered, int batch_idx, @@ -1372,15 +1301,6 @@ static int cam_ope_dev_create_kmd_buf_batch(struct cam_ope_hw_mgr *hw_mgr, /* After second batch DB programming add prefecth dis */ if (i) { - /* program db buffered prefecth disable cmds */ - kmd_buf = ope_create_frame_cmd_prefetch_dis(hw_mgr, - ctx_data, req_idx, - kmd_buf, OPE_CMD_BUF_DOUBLE_BUFFERED, i, - ope_dev_prepare_req); - if (!kmd_buf) { - rc = -EINVAL; - goto end; - } kmd_buf = cdm_ops->cdm_write_wait_prefetch_disable( kmd_buf, 0x0, @@ -1621,6 +1541,15 @@ static int cam_ope_process_probe(struct ope_hw *ope_hw, return -EINVAL; } +static int cam_ope_process_dump_debug_reg(struct ope_hw *ope_hw, + bool hfi_en) +{ + if (!hfi_en) + return cam_ope_dev_process_dump_debug_reg(ope_hw); + + return -EINVAL; +} + static int cam_ope_process_reset(struct ope_hw *ope_hw, void *cmd_args, bool hfi_en) { @@ -1762,6 +1691,9 @@ int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type, spin_unlock_irqrestore(&ope_dev->hw_lock, flags); } break; + case OPE_HW_DUMP_DEBUG: + rc = cam_ope_process_dump_debug_reg(ope_hw, hfi_en); + break; default: break; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h index 9e35fb80613c..1e191961b5d4 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h @@ -28,6 +28,7 @@ #define OPE_HW_SET_IRQ_CB 0xE #define OPE_HW_CLK_DISABLE 0xF #define OPE_HW_CLK_ENABLE 0x10 +#define OPE_HW_DUMP_DEBUG 0x11 /** * struct cam_ope_dev_probe diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index 28c1a4d5e2ed..2890f1579e67 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -49,6 +49,8 @@ #define OPE_WAIT_COMP_IDLE 0x4 #define OPE_WAIT_COMP_GEN_IRQ 0x8 +#define OPE_MAX_DEBUG_REGISTER 30 + struct cam_ope_common { uint32_t mode[CAM_FORMAT_MAX]; }; @@ -68,6 +70,9 @@ struct cam_ope_top_reg { uint32_t irq_cmd; uint32_t violation_status; uint32_t throttle_cnt_cfg; + uint32_t debug_cfg; + uint32_t num_debug_registers; + struct cam_ope_debug_register *debug_regs; }; struct cam_ope_top_reg_val { @@ -103,6 +108,7 @@ struct cam_ope_top_reg_val { uint32_t fe_done; uint32_t ope_violation; uint32_t idle; + uint32_t debug_cfg_val; }; struct cam_ope_qos_reg { @@ -375,6 +381,10 @@ struct cam_ope_bus_wr_reg_val { struct cam_ope_bus_wr_client_reg_val wr_clients[MAX_WR_CLIENTS]; }; +struct cam_ope_debug_register { + uint32_t offset; +}; + struct ope_hw { struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index 0970fc3816e6..95ae384161af 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -42,6 +42,36 @@ enum cam_ope_bus_rd_unpacker_format { BUS_RD_VER1_PACKER_FMT_MAX = 0x13, }; +static struct cam_ope_debug_register ope_debug_regs[OPE_MAX_DEBUG_REGISTER] = { + { + .offset = 0xA0, + }, + { + .offset = 0xA4 + }, + { + .offset = 0xA8, + }, + { + .offset = 0xAC, + }, + { + .offset = 0xB0, + }, + { + .offset = 0xB4, + }, + { + .offset = 0xB8, + }, + { + .offset = 0xBC, + }, + { + .offset = 0xD0, + }, +}; + static struct cam_ope_top_reg ope_top_reg = { .offset = 0x400, .hw_version = 0x0, @@ -56,6 +86,9 @@ static struct cam_ope_top_reg ope_top_reg = { .irq_cmd = 0x24, .violation_status = 0x28, .throttle_cnt_cfg = 0x2C, + .debug_cfg = 0xDC, + .num_debug_registers = 9, + .debug_regs = ope_debug_regs, }; static struct cam_ope_top_reg_val ope_top_reg_val = { @@ -75,6 +108,7 @@ static struct cam_ope_top_reg_val ope_top_reg_val = { .fe_done = 0x4, .ope_violation = 0x8, .idle = 0x10, + .debug_cfg_val = 0x1, }; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index 4d1547352cd3..becfa63540ed 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -29,12 +29,27 @@ static struct ope_top ope_top_info; +static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info) +{ + uint32_t i, val; + struct cam_ope_top_reg *top_reg; + + top_reg = ope_hw_info->top_reg; + for (i = 0; i < top_reg->num_debug_registers; i++) { + val = cam_io_r_mb(top_reg->base + + top_reg->debug_regs[i].offset); + CAM_INFO(CAM_OPE, "Debug_status_%d val: 0x%x", i, val); + } + return 0; +} + static int cam_ope_top_reset(struct ope_hw *ope_hw_info, int32_t ctx_id, void *data) { int rc = 0; struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; + uint32_t irq_mask, irq_status; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -44,7 +59,8 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, top_reg = ope_hw_info->top_reg; top_reg_val = ope_hw_info->top_reg_val; - init_completion(&ope_top_info.reset_complete); + mutex_lock(&ope_top_info.ope_hw_mutex); + reinit_completion(&ope_top_info.reset_complete); /* enable interrupt mask */ cam_io_w_mb(top_reg_val->irq_mask, @@ -58,10 +74,19 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, &ope_top_info.reset_complete, msecs_to_jiffies(30)); + cam_io_w_mb(top_reg_val->debug_cfg_val, + top_reg->base + top_reg->debug_cfg); + if (!rc || rc < 0) { CAM_ERR(CAM_OPE, "reset error result = %d", rc); - if (!rc) - rc = -ETIMEDOUT; + irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_mask); + irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_status); + CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x", + irq_mask, irq_status); + cam_ope_top_dump_debug_reg(ope_hw_info); + rc = -ETIMEDOUT; } else { rc = 0; } @@ -70,6 +95,7 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, cam_io_w_mb(top_reg_val->irq_mask, ope_hw_info->top_reg->base + top_reg->irq_mask); + mutex_unlock(&ope_top_info.ope_hw_mutex); return rc; } @@ -110,6 +136,7 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; struct cam_ope_dev_init *dev_init = data; + uint32_t irq_mask, irq_status; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -121,13 +148,13 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, top_reg->base = dev_init->core_info->ope_hw_info->ope_top_base; + mutex_init(&ope_top_info.ope_hw_mutex); /* OPE SW RESET */ init_completion(&ope_top_info.reset_complete); /* enable interrupt mask */ cam_io_w_mb(top_reg_val->irq_mask, ope_hw_info->top_reg->base + top_reg->irq_mask); - cam_io_w_mb(top_reg_val->sw_reset_cmd, ope_hw_info->top_reg->base + top_reg->reset_cmd); @@ -135,18 +162,27 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, &ope_top_info.reset_complete, msecs_to_jiffies(30)); - /* enable interrupt mask */ - cam_io_w_mb(top_reg_val->irq_mask, - ope_hw_info->top_reg->base + top_reg->irq_mask); + cam_io_w_mb(top_reg_val->debug_cfg_val, + top_reg->base + top_reg->debug_cfg); if (!rc || rc < 0) { CAM_ERR(CAM_OPE, "reset error result = %d", rc); - if (!rc) - rc = -ETIMEDOUT; + irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_mask); + irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_status); + CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x", + irq_mask, irq_status); + cam_ope_top_dump_debug_reg(ope_hw_info); + rc = -ETIMEDOUT; } else { rc = 0; } + /* enable interrupt mask */ + cam_io_w_mb(top_reg_val->irq_mask, + ope_hw_info->top_reg->base + top_reg->irq_mask); + return rc; } @@ -246,6 +282,8 @@ int cam_ope_top_process(struct ope_hw *ope_hw_info, case OPE_HW_RESET: rc = cam_ope_top_reset(ope_hw_info, 0, 0); break; + case OPE_HW_DUMP_DEBUG: + rc - cam_ope_top_dump_debug_reg(ope_hw_info); default: break; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h index 6fd935c46e78..428d66f7e9b8 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h @@ -32,10 +32,12 @@ struct ope_top_ctx { * @ope_hw_info: OPE hardware info * @top_ctx: OPE top context * @reset_complete: Reset complete flag + * @ope_mutex: OPE hardware mutex */ struct ope_top { struct ope_hw *ope_hw_info; struct ope_top_ctx top_ctx[OPE_CTX_MAX]; struct completion reset_complete; + struct mutex ope_hw_mutex; }; #endif /* OPE_TOP_H */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 5359cf1e7f8d..63294dfb2cca 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -4027,7 +4027,7 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) spin_unlock_bh(&link->link_state_spin_lock); /* Start SOF watchdog timer */ rc = crm_timer_init(&link->watchdog, - CAM_REQ_MGR_WATCHDOG_TIMEOUT, link, + CAM_REQ_MGR_WATCHDOG_TIMEOUT_DEFAULT, link, &__cam_req_mgr_sof_freeze); if (rc < 0) { CAM_ERR(CAM_CRM, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index e406590c9499..9b7724c4c174 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -13,10 +13,11 @@ #define CAM_REQ_MGR_MAX_LINKED_DEV 16 #define MAX_REQ_SLOTS 48 -#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 -#define CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX 50000 -#define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 -#define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 1000 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT_DEFAULT 5000 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX 50000 +#define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 +#define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 #define FORCE_DISABLE_RECOVERY 2 #define FORCE_ENABLE_RECOVERY 1 diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index fcdee4e50c60..84fe16cca481 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1544,6 +1544,76 @@ static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, return rc; } +static int32_t cam_cci_read_bytes_v_1_2(struct v4l2_subdev *sd, + struct cam_cci_ctrl *c_ctrl) +{ + int32_t rc = 0; + struct cci_device *cci_dev = NULL; + enum cci_i2c_master_t master; + struct cam_cci_read_cfg *read_cfg = NULL; + uint16_t read_bytes = 0; + + if (!sd || !c_ctrl) { + CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl); + return -EINVAL; + } + if (!c_ctrl->cci_info) { + CAM_ERR(CAM_CCI, "cci_info NULL"); + return -EINVAL; + } + cci_dev = v4l2_get_subdevdata(sd); + if (!cci_dev) { + CAM_ERR(CAM_CCI, "cci_dev NULL"); + return -EINVAL; + } + if (cci_dev->cci_state != CCI_STATE_ENABLED) { + CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state); + return -EINVAL; + } + + if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX + || c_ctrl->cci_info->cci_i2c_master < 0) { + CAM_ERR(CAM_CCI, "Invalid I2C master addr"); + return -EINVAL; + } + + master = c_ctrl->cci_info->cci_i2c_master; + read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; + if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) { + CAM_ERR(CAM_CCI, "read num bytes 0"); + rc = -EINVAL; + goto ERROR; + } + + read_bytes = read_cfg->num_byte; + CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes); + do { + if (read_bytes >= CCI_READ_MAX_V_1_2) + read_cfg->num_byte = CCI_READ_MAX_V_1_2; + else + read_cfg->num_byte = read_bytes; + + cci_dev->is_burst_read = false; + rc = cam_cci_read(sd, c_ctrl); + if (rc) { + CAM_ERR(CAM_CCI, "failed to read rc:%d", rc); + goto ERROR; + } + + if (read_bytes >= CCI_READ_MAX_V_1_2) { + read_cfg->addr += CCI_READ_MAX_V_1_2; + read_cfg->data += CCI_READ_MAX_V_1_2; + read_bytes -= CCI_READ_MAX_V_1_2; + } else { + read_bytes = 0; + } + } while (read_bytes); + +ERROR: + cci_dev->is_burst_read = false; + return rc; +} + static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl) { @@ -1770,7 +1840,16 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, mutex_unlock(&cci_dev->init_mutex); break; case MSM_CCI_I2C_READ: - rc = cam_cci_read_bytes(sd, cci_ctrl); + /* + * CCI version 1.2 does not support burst read + * due to the absence of the read threshold register + */ + if (cci_dev->hw_version == CCI_VERSION_1_2_9) { + CAM_DBG(CAM_CCI, "cci-v1.2 no burst read"); + rc = cam_cci_read_bytes_v_1_2(sd, cci_ctrl); + } else { + rc = cam_cci_read_bytes(sd, cci_ctrl); + } break; case MSM_CCI_I2C_WRITE: case MSM_CCI_I2C_WRITE_SEQ: diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index fbf1834d6074..8dd50aa408ca 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -57,6 +57,7 @@ /* Max bytes that can be read per CCI read transaction */ #define CCI_READ_MAX 256 +#define CCI_READ_MAX_V_1_2 0xE #define CCI_I2C_READ_MAX_RETRIES 3 #define CCI_I2C_MAX_READ 10240 #define CCI_I2C_MAX_WRITE 10240 @@ -69,6 +70,7 @@ #define PRIORITY_QUEUE (QUEUE_0) #define SYNC_QUEUE (QUEUE_1) +#define CCI_VERSION_1_2_9 0x10020009 enum cci_i2c_sync { MSM_SYNC_DISABLE, MSM_SYNC_ENABLE, diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 66fe66b00501..ac37cb2a9f2b 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -119,8 +119,7 @@ int cam_cci_init(struct v4l2_subdev *sd, MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; cci_dev->support_seq_write = 1; - if (of_device_is_compatible(soc_info->dev->of_node, - "qcom,cci-v1.2")) { + if (cci_dev->hw_version == CCI_VERSION_1_2_9) { max_queue_0_size = CCI_I2C_QUEUE_0_SIZE_V_1_2; max_queue_1_size = CCI_I2C_QUEUE_1_SIZE_V_1_2; } else { @@ -180,10 +179,12 @@ int cam_cci_init(struct v4l2_subdev *sd, } /* Set RD FIFO threshold for M0 & M1 */ - cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, - base + CCI_I2C_M0_RD_THRESHOLD_ADDR); - cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, - base + CCI_I2C_M1_RD_THRESHOLD_ADDR); + if (cci_dev->hw_version != CCI_VERSION_1_2_9) { + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M0_RD_THRESHOLD_ADDR); + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M1_RD_THRESHOLD_ADDR); + } cci_dev->cci_state = CCI_STATE_ENABLED; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 60ebe5172673..01c54cdd6cd5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -15,6 +15,11 @@ #include "cam_packet_util.h" #include "cam_mem_mgr.h" #include "cam_cpas_api.h" +#include "cam_compat.h" + +#define SCM_SVC_CAMERASS 0x18 +#define SECURE_SYSCALL_ID 0x6 +#define SECURE_SYSCALL_ID_2 0x7 #define LANE_MASK_2PH 0x1F #define LANE_MASK_3PH 0x7 @@ -834,6 +839,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } break; case CAM_RELEASE_DEV: { + int32_t offset; struct cam_release_dev_cmd release; if (!csiphy_dev->acquire_count) { @@ -849,6 +855,23 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } + offset = cam_csiphy_get_instance_offset(csiphy_dev, + release.dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + goto release_mutex; + } + + if (csiphy_dev->csiphy_info.secure_mode[offset]) + cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, offset); + + csiphy_dev->csiphy_info.secure_mode[offset] = + CAM_SECURE_MODE_NON_SECURE; + + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; + rc = cam_destroy_device_hdl(release.dev_handle); if (rc < 0) CAM_ERR(CAM_CSIPHY, "destroying the device hdl"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 781baa499c1f..89686a3b0088 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -322,11 +322,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2; csiphy_dev->ctrl_reg->csiphy_common_reg = - csiphy_common_reg_1_2; + csiphy_common_reg_1_2_2; csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_2; csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; - csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_2; csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; csiphy_dev->is_divisor_32_comp = false; csiphy_dev->hw_version = CSIPHY_VERSION_V12; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h index dd88ba7cca38..119b6b575b60 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_2_HWREG_H_ @@ -8,6 +8,29 @@ #include "../cam_csiphy_dev.h" +struct csiphy_reg_parms_t csiphy_v1_2_2 = { + .mipi_csiphy_interrupt_status0_addr = 0x8B0, + .mipi_csiphy_interrupt_clear0_addr = 0x858, + .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_common_array_size = 8, + .csiphy_reset_array_size = 5, + .csiphy_2ph_config_array_size = 18, + .csiphy_3ph_config_array_size = 33, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_2_2[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x088C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, +}; + struct csiphy_reg_t csiphy_2ph_v1_2_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index adc7f0d86c0e..3212c795473e 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1827,7 +1827,11 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || (fctrl->flash_state == CAM_FLASH_STATE_START)) { fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); - cam_flash_off(fctrl); + rc = cam_flash_off(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "LED OFF FAILED: %d", rc); + } if (fctrl->func_tbl.power_ops) { rc = fctrl->func_tbl.power_ops(fctrl, false); if (rc) diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index d89cba1510dc..472d95c4432f 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SMMU_API_H_ diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h index ae3cd2a3d388..f4299e0826a2 100644 --- a/drivers/cam_utils/cam_compat.h +++ b/drivers/cam_utils/cam_compat.h @@ -37,9 +37,9 @@ int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa); int cam_ife_notify_safe_lut_scm(bool safe_trigger); -int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, - bool protect, int32_t offset); int camera_component_match_add_drivers(struct device *master_dev, struct component_match **match_list); +int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, + bool protect, int32_t offset); #endif /* _CAM_COMPAT_H_ */ diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 73077a799da7..39da1d20e3d9 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -17,7 +17,7 @@ static char supported_clk_info[256]; static char debugfs_dir_name[64]; int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, - int32_t clk_rate, int clk_idx, int32_t *clk_lvl) + int64_t clk_rate, int clk_idx, int32_t *clk_lvl) { int i; long clk_rate_round; @@ -41,9 +41,9 @@ int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, (soc_info->clk_rate[i][clk_idx] >= clk_rate_round)) { CAM_DBG(CAM_UTIL, - "soc = %d round rate = %ld actual = %d", + "soc = %d round rate = %ld actual = %lld", soc_info->clk_rate[i][clk_idx], - clk_rate_round, clk_rate); + clk_rate_round, clk_rate); *clk_lvl = i; return 0; } @@ -380,7 +380,7 @@ long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, * @return: Success or failure */ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, - int32_t clk_rate) + int64_t clk_rate) { int rc = 0; long clk_rate_round; @@ -388,7 +388,7 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, if (!clk || !clk_name) return -EINVAL; - CAM_DBG(CAM_UTIL, "set %s, rate %d", clk_name, clk_rate); + CAM_DBG(CAM_UTIL, "set %s, rate %lld", clk_name, clk_rate); if (clk_rate > 0) { clk_rate_round = clk_round_rate(clk, clk_rate); CAM_DBG(CAM_UTIL, "new_rate %ld", clk_rate_round); @@ -424,7 +424,7 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, } int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, - int32_t clk_rate) + int64_t clk_rate) { int rc = 0; int i = 0; @@ -452,13 +452,13 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, &apply_level); if (rc || (apply_level < 0) || (apply_level >= CAM_MAX_VOTE)) { CAM_ERR(CAM_UTIL, - "set %s, rate %d dev_name = %s apply level = %d", + "set %s, rate %lld dev_name = %s apply level = %d", soc_info->clk_name[src_clk_idx], clk_rate, soc_info->dev_name, apply_level); return -EINVAL; } - CAM_DBG(CAM_UTIL, "set %s, rate %d dev_name = %s apply level = %d", + CAM_DBG(CAM_UTIL, "set %s, rate %lld dev_name = %s apply level = %d", soc_info->clk_name[src_clk_idx], clk_rate, soc_info->dev_name, apply_level); @@ -471,7 +471,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, soc_info->clk_name[src_clk_idx], clk_rate); if (rc) { CAM_ERR(CAM_UTIL, - "SET_RATE Failed: src clk: %s, rate %d, dev_name = %s rc: %d", + "SET_RATE Failed: src clk: %s, rate %lld, dev_name = %s rc: %d", soc_info->clk_name[src_clk_idx], clk_rate, soc_info->dev_name, rc); return rc; diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 1f795b07e9e4..1e4d1bbce4bd 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -415,7 +415,7 @@ long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, * @return: success or failure */ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, - int32_t clk_rate); + int64_t clk_rate); /** * cam_soc_util_get_option_clk_by_name() @@ -657,7 +657,7 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level); int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, - int32_t clk_rate, int clk_idx, int32_t *clk_lvl); + int64_t clk_rate, int clk_idx, int32_t *clk_lvl); /* Callback to get reg space data for specific HW */ typedef int (*cam_soc_util_regspace_data_cb)(uint32_t reg_base_type, diff --git a/include/uapi/camera/media/cam_ope.h b/include/uapi/camera/media/cam_ope.h index 9ddf3c8004a6..fd6e30ca30da 100644 --- a/include/uapi/camera/media/cam_ope.h +++ b/include/uapi/camera/media/cam_ope.h @@ -73,7 +73,7 @@ #define OPE_MAX_IO_BUFS (OPE_OUT_RES_MAX + OPE_IN_RES_MAX) #define OPE_MAX_PASS 1 #define OPE_MAX_PLANES 2 -#define OPE_MAX_STRIPES 32 +#define OPE_MAX_STRIPES 48 #define OPE_MAX_BATCH_SIZE 16 /** @@ -83,6 +83,7 @@ * @x_init: X_init * @stripe_location: Stripe location (OPE_STRIPE_XXX) * @width: Width of a stripe + * @height: Height of a stripe * @disable_bus: Flag to disable BUS master * @reserved: Reserved * diff --git a/include/uapi/camera/media/cam_tfe.h b/include/uapi/camera/media/cam_tfe.h index 26573c33a40d..dcb254c86e35 100644 --- a/include/uapi/camera/media/cam_tfe.h +++ b/include/uapi/camera/media/cam_tfe.h @@ -83,6 +83,11 @@ #define CAM_ISP_TFE_USAGE_RIGHT_PX 2 #define CAM_ISP_TFE_USAGE_RDI 3 +/* Bus write master modes */ +#define CAM_ISP_TFE_WM_FRAME_BASED_MODE 0 +#define CAM_ISP_TFE_WM_LINE_BASED_MODE 1 +#define CAM_ISP_TFE_WM_INDEX_BASED_MODE 2 + /* Query devices */ /** * struct cam_isp_tfe_dev_cap_info - A cap info for particular hw type From f81a46003b6fefc08fbc9adbb2d0f6046cf293b3 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 21 Oct 2019 16:13:12 -0700 Subject: [PATCH 359/790] msm: camera: reqmgr: Invoke custom device at every frame If there is a valid request CRM will apply that request to the custom device, in scenerios during which there is no setting to be applied to a custom device at a given epoch CRM needs to invoke the custom device to program default settings for the next frame. CRs-Fixed: 2524308 Change-Id: I4701c602ab68b9f64266f03a9b200d15a808165e Signed-off-by: Karthik Anantha Ram --- drivers/cam_core/cam_context.c | 28 ++++++++ drivers/cam_core/cam_context.h | 15 +++++ drivers/cam_core/cam_node.c | 21 ++++++ drivers/cam_cust/cam_custom_context.c | 29 +++++++++ .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 52 +++++++++++++++ .../include/cam_custom_hw_mgr_intf.h | 16 +++++ drivers/cam_req_mgr/cam_req_mgr_core.c | 65 +++++++++++++++++-- drivers/cam_req_mgr/cam_req_mgr_core.h | 5 ++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 7 ++ 9 files changed, 231 insertions(+), 7 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 267b23dafa72..d3ca4f2e1aeb 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -182,6 +182,34 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } +int cam_context_handle_crm_apply_default_req( + struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!apply) { + CAM_ERR(CAM_CORE, "Invalid apply request payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.apply_default) + rc = ctx->state_machine[ctx->state].crm_ops.apply_default(ctx, + apply); + else + CAM_DBG(CAM_CORE, "No crm apply_default in dev %d, state %d", + ctx->dev_hdl, ctx->state); + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + int cam_context_handle_crm_flush_req(struct cam_context *ctx, struct cam_req_mgr_flush_request *flush) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 770451faadf2..e2fd6c2cce39 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -121,6 +121,7 @@ struct cam_ctx_ioctl_ops { * @link: Link the context * @unlink: Unlink the context * @apply_req: Apply setting for the context + * @apply_default: Apply default settings for the context * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request @@ -135,6 +136,8 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_core_dev_link_setup *unlink); int (*apply_req)(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); + int (*apply_default)(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply); int (*flush_req)(struct cam_context *ctx, struct cam_req_mgr_flush_request *flush); int (*process_evt)(struct cam_context *ctx, @@ -302,6 +305,18 @@ int cam_context_handle_crm_unlink(struct cam_context *ctx, int cam_context_handle_crm_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); +/** + * cam_context_handle_crm_apply_default_req() + * + * @brief: Handle apply default request command + * + * @ctx: Object pointer for cam_context + * @apply: Apply default request command payload + * + */ +int cam_context_handle_crm_apply_default_req( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); + /** * cam_context_handle_crm_flush_req() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 672ae35b6226..23a440a3e07f 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -570,6 +570,26 @@ static int __cam_node_crm_apply_req(struct cam_req_mgr_apply_request *apply) return cam_context_handle_crm_apply_req(ctx, apply); } +static int __cam_node_crm_apply_default_req( + struct cam_req_mgr_apply_request *apply) +{ + struct cam_context *ctx = NULL; + + if (!apply) + return -EINVAL; + + ctx = (struct cam_context *) cam_get_device_priv(apply->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + apply->dev_hdl); + return -EINVAL; + } + + trace_cam_apply_req("Node", apply->request_id); + + return cam_context_handle_crm_apply_default_req(ctx, apply); +} + static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) { struct cam_context *ctx = NULL; @@ -683,6 +703,7 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.flush_req = __cam_node_crm_flush_req; node->crm_node_intf.process_evt = __cam_node_crm_process_evt; node->crm_node_intf.dump_req = __cam_node_crm_dump_req; + node->crm_node_intf.apply_default = __cam_node_crm_apply_default_req; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 0fff3f079242..b38b08750c8b 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -162,6 +162,7 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; + dev_info->enable_apply_default = true; return 0; } @@ -456,6 +457,32 @@ static int __cam_custom_release_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_custom_ctx_apply_default_settings( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_custom_hw_cmd_args custom_hw_cmd_args; + + hw_cmd_args.ctxt_to_hw_map = custom_ctx->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + custom_hw_cmd_args.cmd_type = + CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG; + hw_cmd_args.u.internal_args = (void *)&custom_hw_cmd_args; + + rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_cmd_args); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Failed to apply default settings rc %d", rc); + else + CAM_DBG(CAM_CUSTOM, "Applied default settings rc %d", rc); + + return rc; +} + static int __cam_custom_ctx_apply_req_in_activated_state( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -1194,6 +1221,8 @@ static struct cam_ctx_ops .unlink = __cam_custom_ctx_unlink_in_activated, .apply_req = __cam_custom_ctx_apply_req_in_activated_state, + .apply_default = + __cam_custom_ctx_apply_default_settings, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, }, diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index 7587e41aa6f7..eb42913ea4b9 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -1281,6 +1281,57 @@ static int cam_custom_hw_mgr_irq_cb(void *data, return 0; } +static int cam_custom_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_custom_hw_cmd_args *custom_hw_cmd_args; + struct cam_custom_hw_mgr_ctx *custom_ctx = NULL; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + custom_ctx = + (struct cam_custom_hw_mgr_ctx *) + hw_cmd_args->ctxt_to_hw_map; + + if (!custom_ctx || !custom_ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Fatal: Invalid context is used"); + return -EPERM; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_INTERNAL: + if (!hw_cmd_args->u.internal_args) { + CAM_ERR(CAM_CUSTOM, "Invalid cmd arguments"); + return -EINVAL; + } + + custom_hw_cmd_args = (struct cam_custom_hw_cmd_args *) + hw_cmd_args->u.internal_args; + + switch (custom_hw_cmd_args->cmd_type) { + case CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG: + CAM_DBG(CAM_CUSTOM, "configure RUP and scratch buffer"); + /* Handle event accordingly */ + break; + default: + CAM_ERR(CAM_CUSTOM, "Invalid HW mgr command:0x%x", + hw_cmd_args->cmd_type); + rc = -EINVAL; + break; + } + break; + default: + rc = -EINVAL; + break; + } + + return rc; +} + int cam_custom_hw_mgr_init(struct device_node *of_node, struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { @@ -1376,6 +1427,7 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_prepare_update = cam_custom_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_custom_mgr_config_hw; hw_mgr_intf->hw_reset = cam_custom_hw_mgr_reset; + hw_mgr_intf->hw_cmd = cam_custom_mgr_cmd; if (iommu_hdl) *iommu_hdl = g_custom_hw_mgr.img_iommu_hdl; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h index 0577cd6ef9cb..b47ebb5f7824 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -32,6 +32,22 @@ enum cam_custom_cmd_types { CAM_CUSTOM_SUBMIT_REQ, }; +enum cam_custom_hw_mgr_cmd { + CAM_CUSTOM_HW_MGR_CMD_NONE, + CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG, +}; + +/** + * struct cam_custom_hw_cmd_args - Payload for hw manager command + * + * @cmd_type HW command type + * @reserved any other required data + */ +struct cam_custom_hw_cmd_args { + uint32_t cmd_type; + uint32_t reserved; +}; + /** * struct cam_custom_stop_args - hardware stop arguments * diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 5359cf1e7f8d..701757d00d16 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -49,6 +49,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->initial_skip = true; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; + link->enable_apply_default = false; atomic_set(&link->eof_event_cnt, 0); } @@ -209,6 +210,35 @@ static void __cam_req_mgr_find_dev_name( } } +/** + * __cam_req_mgr_apply_default() + * + * @brief : Apply default settings to all devices + * @link : link on which we are applying these settings + * + */ +static void __cam_req_mgr_apply_default( + struct cam_req_mgr_core_link *link) +{ + int i; + struct cam_req_mgr_apply_request apply_req; + struct cam_req_mgr_connected_device *dev = NULL; + + if (!link->enable_apply_default) + return; + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + apply_req.request_id = 0; + apply_req.dev_hdl = dev->dev_hdl; + apply_req.link_hdl = link->link_hdl; + apply_req.trigger_point = 0; + apply_req.report_if_bubble = 0; + if (dev->ops && dev->ops->apply_default) + dev->ops->apply_default(&apply_req); + } +} + /** * __cam_req_mgr_notify_error_on_link() * @@ -738,6 +768,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, rc = dev->ops->apply_req(&apply_req); if (rc) { *failed_dev = dev; + __cam_req_mgr_apply_default(link); return rc; } } @@ -750,6 +781,10 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, slot->ops.skip_next_frame) { slot->ops.skip_next_frame = false; slot->ops.is_applied = true; + CAM_DBG(CAM_REQ, + "SEND: link_hdl: %x pd: %d req_id %lld", + link->link_hdl, pd, apply_req.request_id); + __cam_req_mgr_apply_default(link); return -EAGAIN; } else if ((trigger == CAM_TRIGGER_POINT_EOF) && (slot->ops.apply_at_eof)) { @@ -774,16 +809,27 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, pd); continue; } - if (link->req.apply_data[pd].skip_idx || - link->req.apply_data[pd].req_id < 0) { - CAM_DBG(CAM_CRM, "skip %d req_id %lld", - link->req.apply_data[pd].skip_idx, - link->req.apply_data[pd].req_id); - continue; - } + if (!(dev->dev_info.trigger & trigger)) continue; + if (link->req.apply_data[pd].skip_idx || + (link->req.apply_data[pd].req_id < 0)) { + CAM_DBG(CAM_CRM, + "dev %s skip %d req_id %lld", + dev->dev_info.name, + link->req.apply_data[pd].skip_idx, + link->req.apply_data[pd].req_id); + apply_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = 0; + apply_req.trigger_point = 0; + apply_req.report_if_bubble = 0; + if ((link->enable_apply_default) && + (dev->ops) && (dev->ops->apply_default)) + dev->ops->apply_default(&apply_req); + continue; + } + apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = link->req.apply_data[pd].req_id; @@ -843,6 +889,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (dev->ops && dev->ops->process_evt) dev->ops->process_evt(&evt_data); } + __cam_req_mgr_apply_default(link); } return rc; } @@ -1534,6 +1581,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, rc = -EPERM; } spin_unlock_bh(&link->link_state_spin_lock); + __cam_req_mgr_apply_default(link); goto error; } } @@ -3223,6 +3271,9 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, if (dev->dev_info.p_delay > max_delay) max_delay = dev->dev_info.p_delay; + if (dev->dev_info.enable_apply_default) + link->enable_apply_default = true; + subscribe_event |= (uint32_t)dev->dev_info.trigger; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index e406590c9499..3f1102b8d5a3 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -364,6 +364,10 @@ struct cam_req_mgr_connected_device { * applying the settings * @trigger_cnt : trigger count value per device initiating the trigger * @eof_event_cnt : Atomic variable to track the number of EOF requests + * @enable_apply_default : Link will apply a default settings to devices on + * frames where actual settings are not available. + * This will account for all devices irrespective of + * pipeline delay */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -397,6 +401,7 @@ struct cam_req_mgr_core_link { bool dual_trigger; uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; atomic_t eof_event_cnt; + bool enable_apply_default; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index c40a479419e7..b832f3a46ed3 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -54,6 +54,7 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); +typedef int (*cam_req_mgr_apply_default)(struct cam_req_mgr_apply_request *); typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); @@ -81,6 +82,7 @@ struct cam_req_mgr_crm_cb { * @get_dev_info : payload to fetch device details * @link_setup : payload to establish link with device * @apply_req : payload to apply request id on a device linked + * @apply_default: payload to trigger default apply settings * @flush_req : payload to flush request * @process_evt : payload to generic event * @dump_req : payload to dump request @@ -89,6 +91,7 @@ struct cam_req_mgr_kmd_ops { cam_req_mgr_get_dev_info get_dev_info; cam_req_mgr_link_setup link_setup; cam_req_mgr_apply_req apply_req; + cam_req_mgr_apply_default apply_default; cam_req_mgr_flush_req flush_req; cam_req_mgr_process_evt process_evt; cam_req_mgr_dump_req dump_req; @@ -293,6 +296,9 @@ struct cam_req_mgr_notify_stop { * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client * @trigger_on : This device provides trigger + * @enable_apply_default : Device requests CRM to apply default + * settings for devices on a link if actual + * settings for a given frame is not available */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -301,6 +307,7 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; + bool enable_apply_default; }; /** From 24bb90e6ea8a9dbbd4cf5a3f3ca7fda19a5d138c Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 29 Apr 2020 13:40:18 +0530 Subject: [PATCH 360/790] msm: camera: utils: add spacing between register values when using the cam_io_dump function to dump the register values we are getting 4 register values without spacing which makes is difficult to read, so adding space between two specific register values. CRs-Fixed: 2675959 Change-Id: I7e5db59398e406c30aa9729eb38331aa85736175 Signed-off-by: Tejas Prajapati --- drivers/cam_utils/cam_io_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_utils/cam_io_util.c b/drivers/cam_utils/cam_io_util.c index d35320e7e487..fcbc4b5e00f5 100644 --- a/drivers/cam_utils/cam_io_util.c +++ b/drivers/cam_utils/cam_io_util.c @@ -265,8 +265,8 @@ int cam_io_dump(void __iomem *base_addr, uint32_t start_offset, int size) p_str += 11; } data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i)); - snprintf(p_str, 9, "%08x ", data); - p_str += 8; + snprintf(p_str, 10, "%08x ", data); + p_str += 9; if ((i + 1) % NUM_REGISTER_PER_LINE == 0) { CAM_ERR(CAM_UTIL, "%s", line_str); line_str[0] = '\0'; From 02af3487fa6bfa41863342822abdcf31fb826e23 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 22 Oct 2019 14:54:38 -0700 Subject: [PATCH 361/790] msm: camera: custom: Add support for SW sync & snapshot Add support to handle SW sync & ZSLSnapshot. Add substate machine and mechanism to handle the lifecycle of requests based on irqs accordingly. CRs-Fixed: 2524308 Change-Id: Ie5ba97d4ae1b38f4b44c2d3935d2882df59fcac6 Signed-off-by: Karthik Anantha Ram --- drivers/cam_cust/cam_custom_context.c | 388 ++++++++++++++++-- drivers/cam_cust/cam_custom_context.h | 56 ++- .../cam_custom_hw1/cam_custom_sub_mod_core.c | 4 +- .../cam_custom_hw1/cam_custom_sub_mod_core.h | 2 + .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 235 ++++++++--- .../cam_custom_hw_mgr/cam_custom_hw_mgr.h | 4 + .../cam_custom_hw_mgr/include/cam_custom_hw.h | 22 + .../include/cam_custom_hw_mgr_intf.h | 66 ++- 8 files changed, 667 insertions(+), 110 deletions(-) diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index b38b08750c8b..de9777a8b14b 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -27,6 +27,258 @@ static int __cam_custom_ctx_handle_irq_in_activated( static int __cam_custom_ctx_start_dev_in_ready( struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +static int __cam_custom_ctx_apply_req_in_activated_state( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, + uint32_t next_state); + +static int __cam_custom_ctx_apply_default_settings( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); + +static int __cam_custom_ctx_apply_req_in_activated( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + rc = __cam_custom_ctx_apply_req_in_activated_state( + ctx, apply, CAM_CUSTOM_CTX_ACTIVATED_APPLIED); + CAM_DBG(CAM_CUSTOM, "new substate %d", custom_ctx->substate_activated); + + if (rc) + CAM_ERR(CAM_CUSTOM, "Apply failed in state %d rc %d", + custom_ctx->substate_activated, rc); + + return rc; +} + +static int __cam_custom_ctx_handle_error( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + /* + * Handle any HW error scenerios here, all the + * requests in all the lists can be signaled error. + * Notify UMD about this error if needed. + */ + + return 0; +} + +static int __cam_custom_ctx_reg_upd_in_sof( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + struct cam_ctx_request *req = NULL; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_context *ctx = custom_ctx->base; + + custom_ctx->frame_id++; + + /* + * This is for the first update before streamon. + * 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_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + if (req_custom->num_fence_map_out == req_custom->num_acked) { + list_add_tail(&req->list, &ctx->free_req_list); + } else { + list_add_tail(&req->list, &ctx->active_req_list); + custom_ctx->active_req_cnt++; + CAM_DBG(CAM_REQ, + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, custom_ctx->active_req_cnt, + ctx->ctx_id); + } + } + + return 0; +} + +static int __cam_custom_ctx_reg_upd_in_applied_state( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + struct cam_ctx_request *req; + struct cam_context *ctx = custom_ctx->base; + struct cam_custom_dev_ctx_req *req_custom; + + custom_ctx->frame_id++; + if (list_empty(&ctx->wait_req_list)) { + CAM_ERR(CAM_CUSTOM, + "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_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + if (req_custom->num_fence_map_out != 0) { + list_add_tail(&req->list, &ctx->active_req_list); + custom_ctx->active_req_cnt++; + CAM_DBG(CAM_REQ, + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, custom_ctx->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), ctx %u", + req->request_id, custom_ctx->active_req_cnt, + ctx->ctx_id); + } + + custom_ctx->substate_activated = CAM_CUSTOM_CTX_ACTIVATED_SOF; + CAM_DBG(CAM_CUSTOM, "next substate %d", custom_ctx->substate_activated); + +end: + return 0; +} + +static int __cam_custom_ctx_frame_done( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + int rc = 0, i, j; + uint64_t frame_done_req_id; + struct cam_ctx_request *req; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_context *ctx = custom_ctx->base; + struct cam_custom_hw_done_event_data *done_data = + (struct cam_custom_hw_done_event_data *)evt_data; + + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_CUSTOM, "Frame done with no active request"); + return 0; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_custom = req->req_priv; + + for (i = 0; i < done_data->num_handles; i++) { + for (j = 0; j < req_custom->num_fence_map_out; j++) { + if (done_data->resource_handle[i] == + req_custom->fence_map_out[j].resource_handle) + break; + } + + if (j == req_custom->num_fence_map_out) { + CAM_ERR(CAM_CUSTOM, + "Can not find matching rsrc handle 0x%x!", + done_data->resource_handle[i]); + rc = -EINVAL; + continue; + } + + if (req_custom->fence_map_out[j].sync_id == -1) { + CAM_WARN(CAM_CUSTOM, + "Duplicate frame done for req %lld", + req->request_id); + continue; + } + + rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS); + if (rc) + CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); + + req_custom->num_acked++; + req_custom->fence_map_out[j].sync_id = -1; + } + + if (req_custom->num_acked > req_custom->num_fence_map_out) { + CAM_ERR(CAM_CUSTOM, + "WARNING: req_id %lld num_acked %d > map_out %d, ctx %u", + req->request_id, req_custom->num_acked, + req_custom->num_fence_map_out, ctx->ctx_id); + } + + if (req_custom->num_acked != req_custom->num_fence_map_out) + return rc; + + custom_ctx->active_req_cnt--; + frame_done_req_id = req->request_id; + 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], ctx %u", + frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); + + return rc; +} + +static struct cam_ctx_ops + cam_custom_ctx_activated_state_machine + [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .ioctl_ops = {}, + .crm_ops = { + .apply_req = __cam_custom_ctx_apply_req_in_activated, + .apply_default = + __cam_custom_ctx_apply_default_settings, + }, + .irq_ops = NULL, + }, + /* APPLIED */ + { + .ioctl_ops = {}, + .crm_ops = { + .apply_req = __cam_custom_ctx_apply_req_in_activated, + .apply_default = + __cam_custom_ctx_apply_default_settings, + }, + .irq_ops = NULL, + }, + /* HW ERROR */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* HALT */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, +}; + +static struct cam_custom_ctx_irq_ops + cam_custom_ctx_activated_state_machine_irq + [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .irq_ops = { + __cam_custom_ctx_handle_error, + __cam_custom_ctx_reg_upd_in_sof, + __cam_custom_ctx_frame_done, + }, + }, + /* APPLIED */ + { + .irq_ops = { + __cam_custom_ctx_handle_error, + __cam_custom_ctx_reg_upd_in_applied_state, + __cam_custom_ctx_frame_done, + }, + }, + /* HW ERROR */ + { + .irq_ops = { + NULL, + NULL, + NULL, + }, + }, + /* HALT */ + { + }, +}; static int __cam_custom_ctx_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) @@ -484,7 +736,8 @@ static int __cam_custom_ctx_apply_default_settings( } static int __cam_custom_ctx_apply_req_in_activated_state( - struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, + uint32_t next_state) { int rc = 0; struct cam_ctx_request *req; @@ -499,6 +752,9 @@ static int __cam_custom_ctx_apply_req_in_activated_state( goto end; } + if (!list_empty(&ctx->wait_req_list)) + CAM_WARN(CAM_CUSTOM, "Apply invoked with a req in wait list"); + custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, @@ -531,19 +787,10 @@ static int __cam_custom_ctx_apply_req_in_activated_state( "Can not apply the configuration"); } else { spin_lock_bh(&ctx->lock); + custom_ctx->substate_activated = next_state; list_del_init(&req->list); - if (!req->num_out_map_entries) { - list_add_tail(&req->list, &ctx->free_req_list); - spin_unlock_bh(&ctx->lock); - } else { - list_add_tail(&req->list, &ctx->active_req_list); - spin_unlock_bh(&ctx->lock); - /* - * for test purposes only-this should be - * triggered based on irq - */ - __cam_custom_ctx_handle_irq_in_activated(ctx, 0, NULL); - } + list_add_tail(&req->list, &ctx->wait_req_list); + spin_unlock_bh(&ctx->lock); } end: @@ -610,6 +857,10 @@ static int __cam_custom_ctx_acquire_hw_v1( goto free_res; } + ctx_custom->substate_machine_irq = + cam_custom_ctx_activated_state_machine_irq; + ctx_custom->substate_machine = + cam_custom_ctx_activated_state_machine; ctx_custom->hw_ctx = param.ctxt_to_hw_map; ctx_custom->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; @@ -808,7 +1059,9 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, cfg.packet = packet; cfg.ctxt_to_hw_map = ctx_custom->hw_ctx; cfg.out_map_entries = req_custom->fence_map_out; + cfg.max_out_map_entries = CAM_CUSTOM_DEV_CTX_RES_MAX; cfg.in_map_entries = req_custom->fence_map_in; + cfg.max_in_map_entries = CAM_CUSTOM_DEV_CTX_RES_MAX; cfg.priv = &req_custom->hw_update_data; cfg.pf_data = &(req->pf_data); @@ -824,6 +1077,7 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, req_custom->num_fence_map_out = cfg.num_out_map_entries; req_custom->num_fence_map_in = cfg.num_in_map_entries; req_custom->num_acked = 0; + req_custom->hw_update_data.num_cfg = cfg.num_out_map_entries; for (i = 0; i < req_custom->num_fence_map_out; i++) { rc = cam_sync_get_obj_ref(req_custom->fence_map_out[i].sync_id); @@ -1025,6 +1279,13 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, else custom_start.start_only = false; + ctx_custom->frame_id = 0; + ctx_custom->active_req_cnt = 0; + ctx_custom->substate_activated = + (req_custom->num_fence_map_out) ? + CAM_CUSTOM_CTX_ACTIVATED_APPLIED : + CAM_CUSTOM_CTX_ACTIVATED_SOF; + ctx->state = CAM_CTX_ACTIVATED; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &custom_start); @@ -1040,10 +1301,7 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, spin_lock_bh(&ctx->lock); list_del_init(&req->list); - if (req_custom->num_fence_map_out) - list_add_tail(&req->list, &ctx->active_req_list); - else - list_add_tail(&req->list, &ctx->free_req_list); + list_add_tail(&req->list, &ctx->wait_req_list); spin_unlock_bh(&ctx->lock); end: @@ -1103,20 +1361,28 @@ static int __cam_custom_ctx_process_evt(struct cam_context *ctx, static int __cam_custom_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { - int rc; - struct cam_context *ctx = - (struct cam_context *)context; + int rc = 0; + struct cam_custom_ctx_irq_ops *custom_irq_ops = NULL; + struct cam_context *ctx = (struct cam_context *)context; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *)ctx->ctx_priv; - CAM_DBG(CAM_CUSTOM, "Enter %d", ctx->ctx_id); + spin_lock(&ctx->lock); + CAM_DBG(CAM_CUSTOM, "Enter: State %d, Substate %d, evt id %d", + ctx->state, ctx_custom->substate_activated, evt_id); + custom_irq_ops = &ctx_custom->substate_machine_irq[ + ctx_custom->substate_activated]; + if (custom_irq_ops->irq_ops[evt_id]) + rc = custom_irq_ops->irq_ops[evt_id](ctx_custom, + evt_data); + else + CAM_DBG(CAM_CUSTOM, "No handle function for substate %d", + ctx_custom->substate_activated); - /* - * handle based on different irq's currently - * triggering only buf done if there are fences - */ - rc = cam_context_buf_done_from_hw(ctx, evt_data, 0); - if (rc) - CAM_ERR(CAM_CUSTOM, "Failed in buf done, rc=%d", rc); + CAM_DBG(CAM_CUSTOM, "Exit: State %d Substate %d", + ctx->state, ctx_custom->substate_activated); + spin_unlock(&ctx->lock); return rc; } @@ -1141,6 +1407,67 @@ static int __cam_custom_ctx_acquire_hw_in_acquired( return rc; } +static int __cam_custom_ctx_apply_req(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_ctx_ops *ctx_ops = NULL; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + CAM_DBG(CAM_CUSTOM, + "Enter: apply req in Substate %d request _id:%lld", + custom_ctx->substate_activated, apply->request_id); + + ctx_ops = &custom_ctx->substate_machine[ + custom_ctx->substate_activated]; + if (ctx_ops->crm_ops.apply_req) { + rc = ctx_ops->crm_ops.apply_req(ctx, apply); + } else { + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "No handle function in activated substate %d", + custom_ctx->substate_activated); + rc = -EFAULT; + } + + if (rc) + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "Apply failed in active substate %d rc %d", + custom_ctx->substate_activated, rc); + return rc; +} + +static int __cam_custom_ctx_apply_default_req( + struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_ctx_ops *ctx_ops = NULL; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + CAM_DBG(CAM_CUSTOM, + "Enter: apply req in Substate %d request _id:%lld", + custom_ctx->substate_activated, apply->request_id); + + ctx_ops = &custom_ctx->substate_machine[ + custom_ctx->substate_activated]; + if (ctx_ops->crm_ops.apply_default) { + rc = ctx_ops->crm_ops.apply_default(ctx, apply); + } else { + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "No handle function in activated substate %d", + custom_ctx->substate_activated); + rc = -EFAULT; + } + + if (rc) + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "Apply default failed in active substate %d rc %d", + custom_ctx->substate_activated, rc); + return rc; +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1219,10 +1546,9 @@ static struct cam_ctx_ops }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, - .apply_req = - __cam_custom_ctx_apply_req_in_activated_state, + .apply_req = __cam_custom_ctx_apply_req, .apply_default = - __cam_custom_ctx_apply_default_settings, + __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, }, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index 723644f7e876..d2bf069b47f2 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -19,13 +19,39 @@ * output port resource. The current maximum resource number * is 2. */ -#define CAM_CUSTOM_DEV_CTX_RES_MAX 2 +#define CAM_CUSTOM_DEV_CTX_RES_MAX 1 #define CAM_CUSTOM_CTX_CFG_MAX 8 /* forward declaration */ struct cam_custom_context; +/* cam custom context irq handling function type */ +typedef int (*cam_custom_hw_event_cb_func)( + struct cam_custom_context *custom_ctx, void *evt_data); + +/** + * enum cam_custom_ctx_activated_substate - sub states for activated + * + */ +enum cam_custom_ctx_activated_substate { + CAM_CUSTOM_CTX_ACTIVATED_SOF, + CAM_CUSTOM_CTX_ACTIVATED_APPLIED, + CAM_CUSTOM_CTX_ACTIVATED_HW_ERROR, + CAM_CUSTOM_CTX_ACTIVATED_HALT, + CAM_CUSTOM_CTX_ACTIVATED_MAX, +}; + +/** + * struct cam_custom_ctx_irq_ops - Function table for handling IRQ callbacks + * + * @irq_ops: Array of handle function pointers. + * + */ +struct cam_custom_ctx_irq_ops { + cam_custom_hw_event_cb_func irq_ops[CAM_CUSTOM_HW_EVENT_MAX]; +}; + /** * struct cam_custom_dev_ctx_req - Custom context request object * @@ -69,22 +95,28 @@ struct cam_custom_dev_ctx_req { * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context * @hw_acquired: Flag to indicate if HW is acquired for this context + * @substate_actiavted: Current substate for the activated state. + * @substate_machine: Custom substate machine for external interface + * @substate_machine_irq: Custom substate machine for irq handling * @req_base: common request structure * @req_custom: custom request structure * */ struct cam_custom_context { - struct cam_context *base; - struct cam_ctx_ops *state_machine; - uint32_t state; - void *hw_ctx; - bool init_received; - uint32_t subscribe_event; - uint32_t active_req_cnt; - int64_t frame_id; - bool hw_acquired; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; - struct cam_custom_dev_ctx_req req_custom[CAM_CTX_REQ_MAX]; + struct cam_context *base; + struct cam_ctx_ops *state_machine; + uint32_t state; + void *hw_ctx; + bool init_received; + uint32_t subscribe_event; + uint32_t active_req_cnt; + int64_t frame_id; + bool hw_acquired; + uint32_t substate_activated; + struct cam_ctx_ops *substate_machine; + struct cam_custom_ctx_irq_ops *substate_machine_irq; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_custom_dev_ctx_req req_custom[CAM_CTX_REQ_MAX]; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c index 9ac5da25571e..96e1d00c924c 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c @@ -283,8 +283,6 @@ irqreturn_t cam_custom_hw_sub_mod_irq(int irq_num, void *data) core_info->device_hw_info->irq_clear); spin_lock(&custom_dev->hw_lock); - cb_args.irq_status = irq_status; - cb_args.req_info = core_info->curr_req; core_info->curr_req = NULL; if (core_info->irq_cb.custom_hw_mgr_cb) core_info->irq_cb.custom_hw_mgr_cb( @@ -315,7 +313,7 @@ int cam_custom_hw_sub_mod_process_cmd(void *hw_priv, uint32_t cmd_type, switch (cmd_type) { case CAM_CUSTOM_SET_IRQ_CB: { struct cam_custom_sub_mod_set_irq_cb *irq_cb = cmd_args; - + /* This can be deprecated */ CAM_DBG(CAM_CUSTOM, "Setting irq cb"); spin_lock_irqsave(&hw->hw_lock, flag); core_info->irq_cb.custom_hw_mgr_cb = irq_cb->custom_hw_mgr_cb; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h index d27d578f6c8d..88a5ad661937 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h @@ -49,6 +49,8 @@ enum cam_custom_hw_resource_type { struct cam_custom_sub_mod_acq { enum cam_custom_hw_resource_type rsrc_type; int32_t acq; + cam_hw_mgr_event_cb_func event_cb; + void *priv; struct cam_custom_resource_node *rsrc_node; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index eb42913ea4b9..91fc1730b083 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -471,6 +471,88 @@ static int cam_custom_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_custom_hw_mgr_notify( + uint32_t evt_id, + struct cam_custom_hw_mgr_ctx *custom_ctx, + struct cam_custom_hw_event_info *evt_info) +{ + int rc = 0; + struct cam_custom_hw_reg_update_event_data reg_upd_data; + struct cam_custom_hw_done_event_data done_evt_data; + struct cam_custom_hw_error_event_data err_evt_data; + + switch (evt_id) { + case CAM_CUSTOM_HW_EVENT_RUP_DONE: + CAM_DBG(CAM_CUSTOM, "Notify RUP for ctx %u", + custom_ctx->ctx_index); + /* fill the evt data struct */ + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_HW_EVENT_RUP_DONE, ®_upd_data); + break; + case CAM_CUSTOM_HW_EVENT_RUP_DONE: + CAM_DBG(CAM_CUSTOM, "Notify FRAME DONE for ctx %u", + custom_ctx->ctx_index); + /* fill the evt data struct */ + done_evt_data.num_handles = 1; + done_evt_data.resource_handle = 0; + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_HW_EVENT_RUP_DONE, &done_evt_data); + break; + case CAM_CUSTOM_HW_EVENT_RUP_DONE: + CAM_DBG(CAM_CUSTOM, "Notify ERROR for ctx %u", + custom_ctx->ctx_index); + /* fill the evt data struct */ + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_HW_EVENT_RUP_DONE, &err_evt_data); + break; + default: + CAM_ERR(CAM_CUSTOM, "Invalid evt_id %u", evt_id); + rc = -EINVAL; + break; + } + + return rc; +} + +static int cam_custom_hw_mgr_evt_handler( + void *priv, uint32_t evt_id, void *hw_evt_info) +{ + int rc = 0; + struct cam_custom_hw_mgr_ctx *custom_ctx = NULL; + struct cam_custom_hw_mgr_ctx *custom_ctx_tmp = NULL; + struct cam_custom_hw_event_info *evt_info = NULL; + struct cam_custom_hw_mgr *hw_mgr = &g_custom_hw_mgr; + bool ctx_found = false; + + if (!hw_evt_info) { + CAM_ERR(CAM_CUSTOM, "invalid evt info"); + return -EINVAL; + } + + CAM_DBG(CAM_CUSTOM, "Invoked for HW Event ID 0x%x", + evt_id); + evt_info = (struct cam_custom_hw_event_info *)hw_evt_info; + + list_for_each_entry_safe(custom_ctx, custom_ctx_tmp, + &hw_mgr->used_ctx_list, list) { + if (custom_ctx->task_type == evt_info->task_type) { + ctx_found = true; + rc = cam_custom_hw_mgr_notify(evt_id, custom_ctx, + evt_info); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Failed to notify"); + return rc; + } + break; + } + } + + if (!ctx_found) + CAM_DBG(CAM_CUSTOM, "Failed to find affected ctx"); + + return rc; +} + static int cam_custom_hw_mgr_put_ctx( struct list_head *src_list, struct cam_custom_hw_mgr_ctx **custom_ctx) @@ -541,7 +623,8 @@ static int cam_custom_hw_mgr_get_res( static enum cam_ife_pix_path_res_id cam_custom_hw_mgr_get_csid_res_type( - uint32_t out_port_type) + uint32_t out_port_type, + struct cam_custom_hw_mgr_ctx *custom_ctx) { enum cam_ife_pix_path_res_id path_id; @@ -553,9 +636,11 @@ static enum cam_ife_pix_path_res_id break; case CAM_CUSTOM_OUT_RES_UDI_1: path_id = CAM_IFE_PIX_PATH_RES_UDI_1; + custom_ctx->task_type = CAM_CUSTOM_EVENT_TASK2; break; case CAM_CUSTOM_OUT_RES_UDI_2: path_id = CAM_IFE_PIX_PATH_RES_UDI_2; + custom_ctx->task_type = CAM_CUSTOM_EVENT_TASK3; break; default: path_id = CAM_IFE_PIX_PATH_RES_MAX; @@ -668,7 +753,7 @@ static int cam_custom_hw_mgr_acquire_csid_res( for (i = 0; i < in_port_info->num_out_res; i++) { out_port = &in_port_info->data[i]; path_res_id = cam_custom_hw_mgr_get_csid_res_type( - out_port->res_type); + out_port->res_type, custom_ctx); if (path_res_id == CAM_IFE_PIX_PATH_RES_MAX) { CAM_WARN(CAM_CUSTOM, "Invalid out port res_type %u", @@ -826,7 +911,9 @@ static int cam_custom_mgr_release_hw(void *hw_mgr_priv, cam_custom_hw_mgr_release_hw_for_ctx(custom_ctx); list_del_init(&custom_ctx->list); + custom_ctx->scratch_buffer_addr = 0; custom_ctx->ctx_in_use = 0; + custom_ctx->task_type = CAM_CUSTOM_EVENT_INVALID; cam_custom_hw_mgr_put_ctx(&g_custom_hw_mgr.free_ctx_list, &custom_ctx); CAM_DBG(CAM_CUSTOM, "Release Exit.."); return rc; @@ -935,6 +1022,8 @@ static int cam_custom_mgr_acquire_hw_for_ctx( if (!hw_intf) continue; + acq.event_cb = cam_custom_hw_mgr_evt_handler; + acq.priv = custom_ctx; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &acq, sizeof(acq)); if (rc) { @@ -1014,6 +1103,7 @@ static int cam_custom_mgr_acquire_hw( } custom_ctx->ctx_in_use = 1; + custom_ctx->scratch_buffer_addr = 0; acquire_args->ctxt_to_hw_map = custom_ctx; cam_custom_hw_mgr_put_ctx(&custom_hw_mgr->used_ctx_list, &custom_ctx); CAM_DBG(CAM_CUSTOM, "Exit...(success)"); @@ -1034,17 +1124,23 @@ static int cam_custom_add_io_buffers( int iommu_hdl, struct cam_hw_prepare_update_args *prepare) { - int rc = 0, i = 0; + int rc = 0, i = 0, num_out_buf = 0; int32_t hdl; uint32_t plane_id; + size_t size; struct cam_buf_io_cfg *io_cfg; + struct cam_hw_fence_map_entry *out_map_entries; + struct cam_custom_prepare_hw_update_data *prepare_hw_data; + bool is_buf_secure; io_cfg = (struct cam_buf_io_cfg *)((uint8_t *) &prepare->packet->payload + prepare->packet->io_configs_offset); + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *) + prepare->priv; /* Validate hw update entries */ - for (i = 0; i < prepare->packet->num_io_configs; i++) { CAM_DBG(CAM_CUSTOM, "======= io config idx %d ============", i); CAM_DBG(CAM_CUSTOM, @@ -1058,29 +1154,69 @@ static int cam_custom_add_io_buffers( if (io_cfg[i].direction == CAM_BUF_OUTPUT) { CAM_DBG(CAM_CUSTOM, "output fence 0x%x", io_cfg[i].fence); + out_map_entries = + &prepare->out_map_entries[num_out_buf]; + if (num_out_buf < prepare->max_out_map_entries) { + out_map_entries->resource_handle = + io_cfg[i].resource_type; + out_map_entries->sync_id = + io_cfg[i].fence; + num_out_buf++; + } else { + CAM_ERR(CAM_CUSTOM, "out: %d max: %d", + num_out_buf, + prepare->max_out_map_entries); + return -EINVAL; + } } else if (io_cfg[i].direction == CAM_BUF_INPUT) { CAM_DBG(CAM_CUSTOM, "input fence 0x%x", io_cfg[i].fence); + return -EINVAL; } else { CAM_ERR(CAM_CUSTOM, "Invalid io config direction :%d", io_cfg[i].direction); return -EINVAL; } - for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; - plane_id++) { - if (!io_cfg[i].mem_handle[plane_id]) - continue; + if (io_cfg[i].direction == CAM_BUF_OUTPUT) { + for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) { + /* for custom HW it's one plane only */ + if (!io_cfg[i].mem_handle[plane_id]) + continue; - hdl = io_cfg[i].mem_handle[plane_id]; - CAM_DBG(CAM_CUSTOM, "handle 0x%x for plane %d", - hdl, plane_id); - /* Use cam_mem_get_io_buf() to retrieve iova */ + hdl = io_cfg[i].mem_handle[plane_id]; + is_buf_secure = cam_mem_is_secure_buf(hdl); + if (is_buf_secure) { + CAM_ERR(CAM_CUSTOM, + "secure buffer not supported"); + return -EINVAL; + } + + rc = cam_mem_get_io_buf( + io_cfg[i].mem_handle[plane_id], + iommu_hdl, + &prepare_hw_data->io_addr[plane_id], + &size); + if (rc) { + CAM_ERR(CAM_CUSTOM, + "No io addr for plane: %d", + plane_id); + return -EINVAL; + } + + prepare_hw_data->io_addr[plane_id] += + io_cfg[i].offsets[plane_id]; + CAM_DBG(CAM_CUSTOM, + "handle 0x%x for plane %d addr %pK", + hdl, plane_id, + prepare_hw_data->io_addr[plane_id]); + } } - - /* Do other I/O config operations */ } + prepare->num_out_map_entries = num_out_buf; + prepare->num_in_map_entries = 0; return rc; } @@ -1116,6 +1252,10 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, (prepare->packet->header.op_code & 0xFFF); ctx = (struct cam_custom_hw_mgr_ctx *) prepare->ctxt_to_hw_map; + prepare->num_hw_update_entries = 0; + prepare->num_in_map_entries = 0; + prepare->num_out_map_entries = 0; + /* Test purposes-check the data in cmd buffer */ cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)&prepare->packet->payload + @@ -1130,6 +1270,11 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, custom_buf_type1->custom_info); } + /* + * Populate scratch buffer addr here based on INIT + */ + ctx->scratch_buffer_addr = 0x0; + prepare_hw_data->num_cfg = 0; cam_custom_add_io_buffers(hw_mgr->img_iommu_hdl, prepare); return 0; } @@ -1218,6 +1363,7 @@ static int cam_custom_mgr_config_hw(void *hw_mgr_priv, struct cam_custom_hw_mgr_res *res; struct cam_hw_config_args *cfg; struct cam_hw_intf *hw_intf = NULL; + struct cam_custom_prepare_hw_update_data *prepare_hw_data; CAM_DBG(CAM_CUSTOM, "Enter"); if (!hw_mgr_priv || !hw_config_args) { @@ -1234,6 +1380,23 @@ static int cam_custom_mgr_config_hw(void *hw_mgr_priv, return -EPERM; } + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *) + cfg->priv; + for (i = 0; i < prepare_hw_data->num_cfg; i++) { + CAM_DBG(CAM_CUSTOM, "plane %d io_addr %pK", + i, prepare_hw_data->io_addr[i]); + } + + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *)cfg->priv; + for (i = 0; i < prepare_hw_data->num_cfg; i++) { + CAM_DBG(CAM_CUSTOM, "plane %d io_addr %p cfg %u", i, + prepare_hw_data->io_addr[i], + prepare_hw_data->num_cfg); + /* this will be ZSLBuffer addr */ + } + for (i = 0; i < CAM_CUSTOM_HW_SUB_MOD_MAX; i++) { res = &custom_ctx->sub_hw_list[i]; if (res->hw_res) { @@ -1255,32 +1418,6 @@ static int cam_custom_mgr_config_hw(void *hw_mgr_priv, return rc; } -static int cam_custom_hw_mgr_irq_cb(void *data, - struct cam_custom_hw_cb_args *cb_args) -{ - struct cam_custom_sub_mod_req_to_dev *proc_req; - struct cam_hw_done_event_data evt_data; - struct cam_custom_hw_mgr_ctx *custom_ctx; - uint32_t ctx_idx; - - proc_req = cb_args->req_info; - ctx_idx = proc_req->ctx_idx; - custom_ctx = &g_custom_hw_mgr.ctx_pool[ctx_idx]; - - if (!custom_ctx->ctx_in_use) { - CAM_ERR(CAM_CUSTOM, "ctx %u not in use", ctx_idx); - return 0; - } - - /* Based on irq status notify success/failure */ - - evt_data.request_id = proc_req->req_id; - custom_ctx->event_cb(custom_ctx->cb_priv, - CAM_CUSTOM_EVENT_BUF_DONE, &evt_data); - - return 0; -} - static int cam_custom_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -1315,7 +1452,7 @@ static int cam_custom_mgr_cmd(void *hw_mgr_priv, void *cmd_args) switch (custom_hw_cmd_args->cmd_type) { case CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG: CAM_DBG(CAM_CUSTOM, "configure RUP and scratch buffer"); - /* Handle event accordingly */ + //use custom_ctx->scratch_buffer_addr break; default: CAM_ERR(CAM_CUSTOM, "Invalid HW mgr command:0x%x", @@ -1338,8 +1475,6 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, int rc = 0; int i, j; struct cam_custom_hw_mgr_ctx *ctx_pool; - struct cam_custom_sub_mod_set_irq_cb irq_cb_args; - struct cam_hw_intf *hw_intf = NULL; memset(&g_custom_hw_mgr, 0, sizeof(g_custom_hw_mgr)); mutex_init(&g_custom_hw_mgr.ctx_mutex); @@ -1349,20 +1484,6 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, /* Initialize sub modules */ rc = cam_custom_hw_sub_mod_init( &g_custom_hw_mgr.custom_hw[i], i); - - /* handle in case init fails */ - if (g_custom_hw_mgr.custom_hw[i]) { - hw_intf = g_custom_hw_mgr.custom_hw[i]; - if (hw_intf->hw_ops.process_cmd) { - irq_cb_args.custom_hw_mgr_cb = - cam_custom_hw_mgr_irq_cb; - irq_cb_args.data = - g_custom_hw_mgr.custom_hw[i]->hw_priv; - hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, - CAM_CUSTOM_SET_IRQ_CB, &irq_cb_args, - sizeof(irq_cb_args)); - } - } } for (i = 0; i < CAM_CUSTOM_CSID_HW_MAX; i++) { diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h index 4a9b27be7467..bd8a119f25b1 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h @@ -75,6 +75,8 @@ struct ctx_base_info { * @num_base: number of valid base data in the base array * @init_done: indicate whether init hw is done * @event_cb: event_cb to ctx + * @scratch_buffer_addr: scratch buffer address + * @task_type: Custom HW task type * @cb_priv: data sent back with event_cb * */ @@ -96,6 +98,8 @@ struct cam_custom_hw_mgr_ctx { uint32_t num_base; bool init_done; cam_hw_event_cb_func event_cb; + uint64_t scratch_buffer_addr; + enum cam_custom_hw_task_type task_type; void *cb_priv; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h index c1d6a258cc55..33c0ebff773d 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h @@ -20,6 +20,28 @@ enum cam_custom_hw_resource_state { CAM_CUSTOM_HW_RESOURCE_STATE_STREAMING = 4, }; +enum cam_custom_hw_task_type { + CAM_CUSTOM_EVENT_INVALID, + CAM_CUSTOM_EVENT_TASK1, + CAM_CUSTOM_EVENT_TASK2, + CAM_CUSTOM_EVENT_TASK3, + CAM_CUSTOM_EVENT_MAX, +}; + +/* + * struct cam_custom_hw_event_info: + * + * @Brief: Structure to pass event details to hw mgr + * + * @task_type: Type of CUSTOM HW Task + * @err_type: Error type if any + * + */ +struct cam_custom_hw_event_info { + enum cam_custom_hw_task_type task_type; + uint32_t err_type; +}; + /* * struct cam_custom_resource_node: * diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h index b47ebb5f7824..673735d52381 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -13,6 +13,7 @@ #include "cam_hw.h" #include "cam_hw_mgr_intf.h" #include "cam_hw_intf.h" +#include "cam_custom_hw.h" #define CAM_CUSTOM_HW_TYPE_1 1 @@ -22,8 +23,10 @@ #define CAM_CUSTOM_CSID_HW_MAX 1 enum cam_custom_hw_event_type { - CAM_CUSTOM_EVENT_TYPE_ERROR, - CAM_CUSTOM_EVENT_BUF_DONE, + CAM_CUSTOM_HW_EVENT_ERROR, + CAM_CUSTOM_HW_EVENT_RUP_DONE, + CAM_CUSTOM_HW_EVENT_FRAME_DONE, + CAM_CUSTOM_HW_EVENT_MAX }; enum cam_custom_cmd_types { @@ -48,6 +51,52 @@ struct cam_custom_hw_cmd_args { uint32_t reserved; }; +/** + * struct cam_custom_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF + * + * @timestamp: Time stamp for the sof event + * @boot_time: Boot time stamp for the sof event + * + */ +struct cam_custom_hw_sof_event_data { + uint64_t timestamp; + uint64_t boot_time; +}; + +/** + * struct cam_custom_hw_reg_update_event_data - Event payload for + * CAM_HW_EVENT_REG_UPDATE + * + * @timestamp: Time stamp for the reg update event + * + */ +struct cam_custom_hw_reg_update_event_data { + uint64_t timestamp; +}; + +/** + * struct cam_custom_hw_done_event_data - Event payload for CAM_HW_EVENT_DONE + * + * @num_handles: Number of resource handeles + * @resource_handle: Resource handle array + * + */ +struct cam_custom_hw_done_event_data { + uint32_t num_handles; + uint32_t resource_handle[CAM_NUM_OUT_PER_COMP_IRQ_MAX]; +}; + +/** + * struct cam_custom_hw_error_event_data - Event payload for CAM_HW_EVENT_ERROR + * + * @error_type: Error type for the error event + * @timestamp: Timestamp for the error event + */ +struct cam_custom_hw_error_event_data { + uint32_t error_type; + uint64_t timestamp; +}; + /** * struct cam_custom_stop_args - hardware stop arguments * @@ -77,21 +126,24 @@ struct cam_custom_start_args { * @packet_opcode_type: Packet header opcode in the packet header * this opcode defines, packet is init packet or * update packet + * @buffer_addr: IO Buffer address * */ struct cam_custom_prepare_hw_update_data { - uint32_t packet_opcode_type; + uint32_t packet_opcode_type; + uint32_t num_cfg; + uint64_t io_addr[CAM_PACKET_MAX_PLANES]; }; /** * struct cam_custom_hw_cb_args : HW manager callback args * - * @irq_status : irq status - * @req_info : Pointer to the request info associated with the cb + * @res_type : resource type + * @err_type : error type */ struct cam_custom_hw_cb_args { - uint32_t irq_status; - struct cam_custom_sub_mod_req_to_dev *req_info; + uint32_t res_type; + uint32_t err_type; }; /** From 159ea8087f127ed8ea2ca80f0800d0e9cc605d4f Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 5 May 2020 20:17:08 +0530 Subject: [PATCH 362/790] msm: camera: cdm: Add support for CDM 2.1 This change adds CDM 2.1 support. CRs-Fixed: 2682747 Change-Id: I9e0782a5e7d8e22706048469669772c21d883d89 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm.h | 3 + drivers/cam_cdm/cam_cdm_core_common.c | 2 + drivers/cam_cdm/cam_cdm_core_common.h | 1 + drivers/cam_cdm/cam_cdm_hw_core.c | 39 +++- drivers/cam_cdm/cam_cdm_hw_reg_2_1.h | 252 ++++++++++++++++++++++++++ drivers/cam_cdm/cam_cdm_soc.h | 3 + 6 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 drivers/cam_cdm/cam_cdm_hw_reg_2_1.h diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index cc808fe2c508..99ea396dc79a 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -276,6 +276,7 @@ struct cam_cdm_common_reg_data { * wait, etc. * @core_en: offset to pause/enable CDM * @fe_cfg: offset to configure CDM fetch engine + * @irq_context_status offset to read back irq context status * @bl_fifo_rb: offset to set BL_FIFO read back * @bl_fifo_base_rb: offset to read back base address on offset set by * bl_fifo_rb @@ -319,6 +320,7 @@ struct cam_cdm_common_regs { uint32_t core_cfg; uint32_t core_en; uint32_t fe_cfg; + uint32_t irq_context_status; uint32_t bl_fifo_rb; uint32_t bl_fifo_base_rb; uint32_t bl_fifo_len_rb; @@ -415,6 +417,7 @@ enum cam_cdm_hw_version { CAM_CDM_VERSION_1_1 = 0x10010000, CAM_CDM_VERSION_1_2 = 0x10020000, CAM_CDM_VERSION_2_0 = 0x20000000, + CAM_CDM_VERSION_2_1 = 0x20010000, CAM_CDM_VERSION_MAX, }; diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index e93e54f0335e..9e08c08b6d5d 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -49,6 +49,7 @@ bool cam_cdm_set_cam_hw_version( case CAM_CDM110_VERSION: case CAM_CDM120_VERSION: case CAM_CDM200_VERSION: + case CAM_CDM210_VERSION: cam_version->major = (ver & 0xF0000000); cam_version->minor = (ver & 0xFFF0000); cam_version->incr = (ver & 0xFFFF); @@ -81,6 +82,7 @@ struct cam_cdm_utils_ops *cam_cdm_get_ops( case CAM_CDM110_VERSION: case CAM_CDM120_VERSION: case CAM_CDM200_VERSION: + case CAM_CDM210_VERSION: return &CDM170_ops; default: CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h index 5545f15903e0..1dd43b678dfe 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.h +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -12,6 +12,7 @@ #define CAM_CDM110_VERSION 0x10010000 #define CAM_CDM120_VERSION 0x10020000 #define CAM_CDM200_VERSION 0x20000000 +#define CAM_CDM210_VERSION 0x20010000 #define CAM_CDM_AHB_BURST_LEN_1 (BIT(1) - 1) #define CAM_CDM_AHB_BURST_LEN_4 (BIT(2) - 1) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 0ce4380bdd8e..ed3498308b7c 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -22,6 +22,7 @@ #include "cam_cdm_hw_reg_1_1.h" #include "cam_cdm_hw_reg_1_2.h" #include "cam_cdm_hw_reg_2_0.h" +#include "cam_cdm_hw_reg_2_1.h" #include "camera_main.h" #include "cam_trace.h" @@ -60,6 +61,18 @@ static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { .compatible = CAM_HW_CDM_OPE_NAME_2_0, .data = &cam_cdm_2_0_reg_offset, }, + { + .compatible = CAM_HW_CDM_CPAS_NAME_2_1, + .data = &cam_cdm_2_1_reg_offset, + }, + { + .compatible = CAM_HW_CDM_OPE_NAME_2_1, + .data = &cam_cdm_2_1_reg_offset, + }, + { + .compatible = CAM_HW_CDM_IFE_NAME_2_1, + .data = &cam_cdm_2_1_reg_offset, + }, }; static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) @@ -77,14 +90,23 @@ static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) strlen(CAM_HW_CDM_CPAS_NAME_1_2))) return CAM_CDM_CPAS; if (strnstr(name, CAM_HW_CDM_IFE_NAME_1_2, - strlen(CAM_HW_CDM_CPAS_NAME_1_2))) + strlen(CAM_HW_CDM_IFE_NAME_1_2))) return CAM_CDM_IFE; if (strnstr(name, CAM_HW_CDM_CPAS_NAME_2_0, strlen(CAM_HW_CDM_CPAS_NAME_2_0))) return CAM_CDM_CPAS; if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_0, - strlen(CAM_HW_CDM_CPAS_NAME_2_0))) + strlen(CAM_HW_CDM_OPE_NAME_2_0))) return CAM_CDM_OPE; + if (strnstr(name, CAM_HW_CDM_CPAS_NAME_2_1, + strlen(CAM_HW_CDM_CPAS_NAME_2_1))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_1, + strlen(CAM_HW_CDM_OPE_NAME_2_1))) + return CAM_CDM_OPE; + if (strnstr(name, CAM_HW_CDM_IFE_NAME_2_1, + strlen(CAM_HW_CDM_IFE_NAME_2_1))) + return CAM_CDM_IFE; return CAM_CDM_MAX; } @@ -1248,17 +1270,28 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0}; uint32_t user_data = 0; uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0}; + uint32_t irq_context_summary = 0xF; bool work_status; int i; - CAM_DBG(CAM_CDM, "Got irq"); + CAM_DBG(CAM_CDM, "Got irq hw_version 0x%x", cdm_core->hw_version); spin_lock(&cdm_hw->hw_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_DBG(CAM_CDM, "CDM is in power down state"); spin_unlock(&cdm_hw->hw_lock); return IRQ_HANDLED; } + if (cdm_core->hw_version >= CAM_CDM_VERSION_2_1) { + if (cam_cdm_read_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->irq_context_status, + &irq_context_summary)) { + CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status"); + } + } for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { + if (!(BIT(i) & irq_context_summary)) { + continue; + } if (cam_cdm_read_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_status, &irq_status[i])) { diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h b/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h new file mode 100644 index 000000000000..0d6f85165651 --- /dev/null +++ b/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "cam_cdm.h" + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_1_bl_pending_req0 = { + .rb_offset = 0x6c, + .rb_mask = 0x1ff, + .rb_num_fifo = 0x2, + .rb_next_fifo_shift = 0x10, +}; + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_1_bl_pending_req1 = { + .rb_offset = 0x70, + .rb_mask = 0x1ff, + .rb_num_fifo = 0x2, + .rb_next_fifo_shift = 0x10, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq0 = { + .irq_mask = 0x30, + .irq_clear = 0x34, + .irq_clear_cmd = 0x38, + .irq_set = 0x3c, + .irq_set_cmd = 0x40, + .irq_status = 0x44, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq1 = { + .irq_mask = 0x130, + .irq_clear = 0x134, + .irq_clear_cmd = 0x138, + .irq_set = 0x13c, + .irq_set_cmd = 0x140, + .irq_status = 0x144, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq2 = { + .irq_mask = 0x230, + .irq_clear = 0x234, + .irq_clear_cmd = 0x238, + .irq_set = 0x23c, + .irq_set_cmd = 0x240, + .irq_status = 0x244, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq3 = { + .irq_mask = 0x330, + .irq_clear = 0x334, + .irq_clear_cmd = 0x338, + .irq_set = 0x33c, + .irq_set_cmd = 0x340, + .irq_status = 0x344, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo0 = { + .bl_fifo_base = 0x50, + .bl_fifo_len = 0x54, + .bl_fifo_store = 0x58, + .bl_fifo_cfg = 0x5c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo1 = { + .bl_fifo_base = 0x150, + .bl_fifo_len = 0x154, + .bl_fifo_store = 0x158, + .bl_fifo_cfg = 0x15c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo2 = { + .bl_fifo_base = 0x250, + .bl_fifo_len = 0x254, + .bl_fifo_store = 0x258, + .bl_fifo_cfg = 0x25c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo3 = { + .bl_fifo_base = 0x350, + .bl_fifo_len = 0x354, + .bl_fifo_store = 0x358, + .bl_fifo_cfg = 0x35c, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg0 = { + .scratch_reg = 0x90, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg1 = { + .scratch_reg = 0x94, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg2 = { + .scratch_reg = 0x98, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg3 = { + .scratch_reg = 0x9c, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg4 = { + .scratch_reg = 0xa0, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg5 = { + .scratch_reg = 0xa4, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg6 = { + .scratch_reg = 0xa8, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg7 = { + .scratch_reg = 0xac, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg8 = { + .scratch_reg = 0xb0, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg9 = { + .scratch_reg = 0xb4, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg10 = { + .scratch_reg = 0xb8, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg11 = { + .scratch_reg = 0xbc, +}; + +static struct cam_cdm_perf_mon_regs cdm_2_1_perf_mon0 = { + .perf_mon_ctrl = 0x110, + .perf_mon_0 = 0x114, + .perf_mon_1 = 0x118, + .perf_mon_2 = 0x11c, +}; + +static struct cam_cdm_perf_mon_regs cdm_2_1_perf_mon1 = { + .perf_mon_ctrl = 0x120, + .perf_mon_0 = 0x124, + .perf_mon_1 = 0x128, + .perf_mon_2 = 0x12c, +}; + +static struct cam_cdm_comp_wait_status cdm_2_1_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_2_1_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + +static struct cam_cdm_icl_data_regs cdm_2_1_icl_data = { + .icl_last_data_0 = 0x1c0, + .icl_last_data_1 = 0x1c4, + .icl_last_data_2 = 0x1c8, + .icl_inv_data = 0x1cc, +}; + +static struct cam_cdm_icl_misc_regs cdm_2_1_icl_misc = { + .icl_inv_bl_addr = 0x1d0, + .icl_status = 0x1d8, +}; + +static struct cam_cdm_icl_regs cdm_2_1_icl = { + .data_regs = &cdm_2_1_icl_data, + .misc_regs = &cdm_2_1_icl_misc, +}; + +static struct cam_cdm_common_regs cdm_hw_2_1_cmn_reg_offset = { + .cdm_hw_version = 0x0, + .cam_version = NULL, + .rst_cmd = 0x10, + .cgc_cfg = 0x14, + .core_cfg = 0x18, + .core_en = 0x1c, + .fe_cfg = 0x20, + .irq_context_status = 0x2c, + .bl_fifo_rb = 0x60, + .bl_fifo_base_rb = 0x64, + .bl_fifo_len_rb = 0x68, + .usr_data = 0x80, + .wait_status = 0x84, + .last_ahb_addr = 0xd0, + .last_ahb_data = 0xd4, + .core_debug = 0xd8, + .last_ahb_err_addr = 0xe0, + .last_ahb_err_data = 0xe4, + .current_bl_base = 0xe8, + .current_bl_len = 0xec, + .current_used_ahb_base = 0xf0, + .debug_status = 0xf4, + .bus_misr_cfg0 = 0x100, + .bus_misr_cfg1 = 0x104, + .bus_misr_rd_val = 0x108, + .pending_req = { + &cdm_hw_2_1_bl_pending_req0, + &cdm_hw_2_1_bl_pending_req1, + }, + .comp_wait = { + &cdm_2_1_comp_wait_status0, + &cdm_2_1_comp_wait_status1, + }, + .perf_mon = { + &cdm_2_1_perf_mon0, + &cdm_2_1_perf_mon1, + }, + .scratch = { + &cdm_2_1_scratch_reg0, + &cdm_2_1_scratch_reg1, + &cdm_2_1_scratch_reg2, + &cdm_2_1_scratch_reg3, + &cdm_2_1_scratch_reg4, + &cdm_2_1_scratch_reg5, + &cdm_2_1_scratch_reg6, + &cdm_2_1_scratch_reg7, + &cdm_2_1_scratch_reg8, + &cdm_2_1_scratch_reg9, + &cdm_2_1_scratch_reg10, + &cdm_2_1_scratch_reg11, + }, + .perf_reg = NULL, + .icl_reg = &cdm_2_1_icl, + .spare = 0x3fc, +}; + +static struct cam_cdm_common_reg_data cdm_hw_2_1_cmn_reg_data = { + .num_bl_fifo = 0x4, + .num_bl_fifo_irq = 0x4, + .num_bl_pending_req_reg = 0x2, + .num_scratch_reg = 0xc, +}; + +struct cam_cdm_hw_reg_offset cam_cdm_2_1_reg_offset = { + .cmn_reg = &cdm_hw_2_1_cmn_reg_offset, + .bl_fifo_reg = { + &cdm_hw_2_1_bl_fifo0, + &cdm_hw_2_1_bl_fifo1, + &cdm_hw_2_1_bl_fifo2, + &cdm_hw_2_1_bl_fifo3, + }, + .irq_reg = { + &cdm_hw_2_1_irq0, + &cdm_hw_2_1_irq1, + &cdm_hw_2_1_irq2, + &cdm_hw_2_1_irq3, + }, + .reg_data = &cdm_hw_2_1_cmn_reg_data, +}; diff --git a/drivers/cam_cdm/cam_cdm_soc.h b/drivers/cam_cdm/cam_cdm_soc.h index 25b5a5dc02d6..59129c7031c7 100644 --- a/drivers/cam_cdm/cam_cdm_soc.h +++ b/drivers/cam_cdm/cam_cdm_soc.h @@ -13,6 +13,9 @@ #define CAM_HW_CDM_IFE_NAME_1_2 "qcom,cam-ife-cdm1_2" #define CAM_HW_CDM_CPAS_NAME_2_0 "qcom,cam-cpas-cdm2_0" #define CAM_HW_CDM_OPE_NAME_2_0 "qcom,cam-ope-cdm2_0" +#define CAM_HW_CDM_CPAS_NAME_2_1 "qcom,cam-cpas-cdm2_1" +#define CAM_HW_CDM_OPE_NAME_2_1 "qcom,cam-ope-cdm2_1" +#define CAM_HW_CDM_IFE_NAME_2_1 "qcom,cam-ife-cdm2_1" int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, const struct of_device_id *table); From 7eb3653915f20b46ef61e2aa81413d4c088d5252 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 7 May 2020 00:34:12 +0530 Subject: [PATCH 363/790] msm: camera: reqmgr: Work queue names added Added wrapper functions for each workq to enable workq names in log. CRs-Fixed: 2684378 Change-Id: If5b3671fbf20777cc891cba4b27cad6ed3a0d146 Signed-off-by: Wyes Karny --- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 8 +++++- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 25 ++++++++++++++++--- drivers/cam_isp/cam_isp_context.c | 8 +++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 8 +++++- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 16 ++++++++++-- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 9 +++++-- .../lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c | 8 +++++- drivers/cam_req_mgr/cam_req_mgr_core.c | 11 ++++++-- drivers/cam_req_mgr/cam_req_mgr_workq.c | 8 +++--- drivers/cam_req_mgr/cam_req_mgr_workq.h | 9 ++++++- 10 files changed, 91 insertions(+), 19 deletions(-) diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index 644767d9e513..041fad4ed7fe 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -1936,6 +1936,11 @@ int cam_fd_hw_mgr_deinit(struct device_node *of_node) return 0; } +static void cam_req_mgr_process_workq_cam_fd_worker(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + int cam_fd_hw_mgr_init(struct device_node *of_node, struct cam_hw_mgr_intf *hw_mgr_intf) { @@ -2081,7 +2086,8 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, } rc = cam_req_mgr_workq_create("cam_fd_worker", CAM_FD_WORKQ_NUM_TASK, - &g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ, 0); + &g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_workq_cam_fd_worker); if (rc) { CAM_ERR(CAM_FD, "Unable to create a worker, rc=%d", rc); goto detach_smmu; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 1c804d5df6a5..c976ae7b4858 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -5942,28 +5942,45 @@ compat_hw_name_failed: return rc; } +static void cam_req_mgr_process_workq_icp_command_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + +static void cam_req_mgr_process_workq_icp_message_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + +static void cam_req_mgr_process_workq_icp_timer_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + static int cam_icp_mgr_create_wq(void) { int rc; int i; rc = cam_req_mgr_workq_create("icp_command_queue", ICP_WORKQ_NUM_TASK, - &icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ, - 0); + &icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ, 0, + cam_req_mgr_process_workq_icp_command_queue); if (rc) { CAM_ERR(CAM_ICP, "unable to create a command worker"); goto cmd_work_failed; } rc = cam_req_mgr_workq_create("icp_message_queue", ICP_WORKQ_NUM_TASK, - &icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ, 0); + &icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_workq_icp_message_queue); if (rc) { CAM_ERR(CAM_ICP, "unable to create a message worker"); goto msg_work_failed; } rc = cam_req_mgr_workq_create("icp_timer_queue", ICP_WORKQ_NUM_TASK, - &icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ, 0); + &icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_workq_icp_timer_queue); if (rc) { CAM_ERR(CAM_ICP, "unable to create a timer worker"); goto timer_work_failed; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 4b9c4a671f80..ffb69adbb485 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4325,6 +4325,11 @@ end: return rc; } +static void cam_req_mgr_process_workq_offline_ife_worker(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, void *args) { @@ -4449,7 +4454,8 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, ctx_isp->offline_context = true; rc = cam_req_mgr_workq_create("offline_ife", 20, - &ctx_isp->workq, CRM_WORKQ_USAGE_IRQ, 0); + &ctx_isp->workq, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_workq_offline_ife_worker); if (rc) CAM_ERR(CAM_ISP, "Failed to create workq for offline IFE rc:%d", diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index bfdc76f930d8..4717768f79d5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7648,6 +7648,11 @@ err: return -ENOMEM; } +static void cam_req_mgr_process_workq_cam_ife_worker(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { int rc = -EFAULT; @@ -7813,7 +7818,8 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) /* Create Worker for ife_hw_mgr with 10 tasks */ rc = cam_req_mgr_workq_create("cam_ife_worker", 10, - &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0); + &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0, + cam_req_mgr_process_workq_cam_ife_worker); if (rc < 0) { CAM_ERR(CAM_ISP, "Unable to create worker"); goto end; diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 24511b904da0..e89c28146e43 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1290,6 +1290,16 @@ copy_error: return rc; } +static void cam_req_mgr_process_workq_jpeg_command_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + +static void cam_req_mgr_process_workq_jpeg_message_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + static int cam_jpeg_setup_workqs(void) { int rc, i; @@ -1298,7 +1308,8 @@ static int cam_jpeg_setup_workqs(void) "jpeg_command_queue", CAM_JPEG_WORKQ_NUM_TASK, &g_jpeg_hw_mgr.work_process_frame, - CRM_WORKQ_USAGE_NON_IRQ, 0); + CRM_WORKQ_USAGE_NON_IRQ, 0, + cam_req_mgr_process_workq_jpeg_command_queue); if (rc) { CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc); goto work_process_frame_failed; @@ -1308,7 +1319,8 @@ static int cam_jpeg_setup_workqs(void) "jpeg_message_queue", CAM_JPEG_WORKQ_NUM_TASK, &g_jpeg_hw_mgr.work_process_irq_cb, - CRM_WORKQ_USAGE_IRQ, 0); + CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_workq_jpeg_message_queue); if (rc) { CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc); goto work_process_irq_cb_failed; diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 537fc48a619e..5cf8c55c0e37 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -1041,6 +1041,11 @@ err: return rc; } +static void cam_req_mgr_process_workq_cam_lrme_device_submit_worker( + struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} int cam_lrme_mgr_register_device( struct cam_hw_intf *lrme_hw_intf, @@ -1068,8 +1073,8 @@ int cam_lrme_mgr_register_device( CAM_DBG(CAM_LRME, "Create submit workq for %s", buf); rc = cam_req_mgr_workq_create(buf, CAM_LRME_WORKQ_NUM_TASK, - &hw_device->work, CRM_WORKQ_USAGE_NON_IRQ, - 0); + &hw_device->work, CRM_WORKQ_USAGE_NON_IRQ, 0, + cam_req_mgr_process_workq_cam_lrme_device_submit_worker); if (rc) { CAM_ERR(CAM_LRME, "Unable to create a worker, rc=%d", rc); diff --git a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c index 3c5aab0b36a7..ecf4d38ffb61 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c +++ b/drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c @@ -78,6 +78,11 @@ error: return rc; } +static void cam_req_mgr_process_workq_cam_lrme_hw_worker(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + static int cam_lrme_hw_dev_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -117,7 +122,8 @@ static int cam_lrme_hw_dev_component_bind(struct device *dev, rc = cam_req_mgr_workq_create("cam_lrme_hw_worker", CAM_LRME_HW_WORKQ_NUM_TASK, - &lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0); + &lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_workq_cam_lrme_hw_worker); if (rc) { CAM_ERR(CAM_LRME, "Unable to create a workq, rc=%d", rc); goto free_memory; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 63294dfb2cca..ef8b04ff7645 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3463,6 +3463,11 @@ end: return rc; } +static void cam_req_mgr_process_workq_link_worker(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info) { int rc = 0; @@ -3541,7 +3546,8 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info) link_info->u.link_info_v1.session_hdl, link->link_hdl); wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL; rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS, - &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag); + &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag, + cam_req_mgr_process_workq_link_worker); if (rc < 0) { CAM_ERR(CAM_CRM, "FATAL: unable to create worker"); __cam_req_mgr_destroy_link_info(link); @@ -3650,7 +3656,8 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) link_info->u.link_info_v2.session_hdl, link->link_hdl); wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL; rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS, - &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag); + &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag, + cam_req_mgr_process_workq_link_worker); if (rc < 0) { CAM_ERR(CAM_CRM, "FATAL: unable to create worker"); __cam_req_mgr_destroy_link_info(link); diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.c b/drivers/cam_req_mgr/cam_req_mgr_workq.c index 29d98503f305..0c9ff7c419ca 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.c +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_workq.h" @@ -88,7 +88,7 @@ static int cam_req_mgr_process_task(struct crm_workq_task *task) * cam_req_mgr_process_workq() - main loop handling * @w: workqueue task pointer */ -static void cam_req_mgr_process_workq(struct work_struct *w) +void cam_req_mgr_process_workq(struct work_struct *w) { struct cam_req_mgr_core_workq *workq = NULL; struct crm_workq_task *task; @@ -172,7 +172,7 @@ end: int cam_req_mgr_workq_create(char *name, int32_t num_tasks, struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq, - int flags) + int flags, void (*func)(struct work_struct *w)) { int32_t i, wq_flags = 0, max_active_tasks = 0; struct crm_workq_task *task; @@ -202,7 +202,7 @@ int cam_req_mgr_workq_create(char *name, int32_t num_tasks, } /* Workq attributes initialization */ - INIT_WORK(&crm_workq->work, cam_req_mgr_process_workq); + INIT_WORK(&crm_workq->work, func); spin_lock_init(&crm_workq->lock_bh); CAM_DBG(CAM_CRM, "LOCK_DBG workq %s lock %pK", name, &crm_workq->lock_bh); diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.h b/drivers/cam_req_mgr/cam_req_mgr_workq.h index c09cb5eb64d8..95c435ced9ed 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.h +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.h @@ -98,6 +98,12 @@ struct cam_req_mgr_core_workq { } task; }; +/** + * cam_req_mgr_process_workq() - main loop handling + * @w: workqueue task pointer + */ +void cam_req_mgr_process_workq(struct work_struct *w); + /** * cam_req_mgr_workq_create() * @brief : create a workqueue @@ -108,12 +114,13 @@ struct cam_req_mgr_core_workq { * @in_irq : Set to one if workq might be used in irq context * @flags : Bitwise OR of Flags for workq behavior. * e.g. CAM_REQ_MGR_WORKQ_HIGH_PRIORITY | CAM_REQ_MGR_WORKQ_SERIAL + * @func : function pointer for cam_req_mgr_process_workq wrapper function * This function will allocate and create workqueue and pass * the workq pointer to caller. */ int cam_req_mgr_workq_create(char *name, int32_t num_tasks, struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq, - int flags); + int flags, void (*func)(struct work_struct *w)); /** * cam_req_mgr_workq_destroy() From 685eb68649cdc60702ad9e3fd91b4863d393fa4e Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 5 May 2020 11:23:44 +0530 Subject: [PATCH 364/790] msm: camera: cdm: Add priority group support This change adds priority group support for CDM 2.1. CRs-Fixed: 2682747 Change-Id: I4e97e12d916a72d41f2cf8e92cf71d15ede91da5 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm.h | 7 ++++-- drivers/cam_cdm/cam_cdm_hw_core.c | 32 ++++++++++++++-------------- drivers/cam_cdm/cam_cdm_hw_reg_2_1.h | 1 + drivers/cam_cdm/cam_cdm_soc.c | 13 +++++++++-- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 99ea396dc79a..714bff32c399 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -310,6 +310,7 @@ struct cam_cdm_common_reg_data { * @icl_reg: registers to read information related to good * and invalid commands in FIFO * @spare: spare register + * @priority_group_bit_offset offset of priority group bits * */ struct cam_cdm_common_regs { @@ -349,6 +350,7 @@ struct cam_cdm_common_regs { const struct cam_cdm_perf_regs *perf_reg; const struct cam_cdm_icl_regs *icl_reg; uint32_t spare; + uint32_t priority_group_bit_offset; }; /** @@ -530,10 +532,11 @@ struct cam_cdm { /* struct cam_cdm_private_dt_data - CDM hw custom dt data */ struct cam_cdm_private_dt_data { bool dt_cdm_shared; + bool config_fifo; + uint8_t priority_group; + uint32_t fifo_depth[CAM_CDM_BL_FIFO_MAX]; uint32_t dt_num_supported_clients; const char *dt_cdm_client_name[CAM_PER_CDM_MAX_REGISTERED_CLIENTS]; - bool config_fifo; - uint32_t fifo_depth[CAM_CDM_BL_FIFO_MAX]; }; /* struct cam_cdm_intf_devices - CDM mgr interface devices */ diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index ed3498308b7c..d1d402285560 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -482,6 +482,8 @@ int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) uint32_t cfg_mask = 0; int rc; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + struct cam_cdm_private_dt_data *pvt_data = + pvt_data = cdm_hw->soc_info.soc_private; cfg_mask = cfg_mask | CAM_CDM_AHB_STOP_ON_ERROR| @@ -497,28 +499,26 @@ int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) goto end; } - if (cdm_version < CAM_CDM_VERSION_2_0) { - rc = cam_cdm_write_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_cfg, cfg_mask); - if (rc) { - CAM_ERR(CAM_CDM, "Error writing cdm core cfg"); - rc = -EIO; - goto end; - } - } else { + if (cdm_version >= CAM_CDM_VERSION_2_0) { if (core->id != CAM_CDM_CPAS) cfg_mask = cfg_mask | CAM_CDM_IMPLICIT_WAIT_EN; if (core->arbitration == CAM_CDM_ARBITRATION_ROUND_ROBIN) cfg_mask = cfg_mask | CAM_CDM_ARB_SEL_RR; - rc = cam_cdm_write_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_cfg, cfg_mask); - if (rc) { - CAM_ERR(CAM_CDM, "Error writing cdm core cfg"); - rc = -EIO; - goto end; - } + } + + if (cdm_version >= CAM_CDM_VERSION_2_1) { + cfg_mask = cfg_mask | ((uint32_t)pvt_data->priority_group << + core->offsets->cmn_reg->priority_group_bit_offset); + } + + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_cfg, cfg_mask); + if (rc) { + CAM_ERR(CAM_CDM, "Error writing cdm core cfg"); + rc = -EIO; + goto end; } end: diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h b/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h index 0d6f85165651..b9c8e1df7bb8 100644 --- a/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h +++ b/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h @@ -225,6 +225,7 @@ static struct cam_cdm_common_regs cdm_hw_2_1_cmn_reg_offset = { .perf_reg = NULL, .icl_reg = &cdm_2_1_icl, .spare = 0x3fc, + .priority_group_bit_offset = 20, }; static struct cam_cdm_common_reg_data cdm_hw_2_1_cmn_reg_data = { diff --git a/drivers/cam_cdm/cam_cdm_soc.c b/drivers/cam_cdm/cam_cdm_soc.c index 3d81270c1187..ec8a9e096a7b 100644 --- a/drivers/cam_cdm/cam_cdm_soc.c +++ b/drivers/cam_cdm/cam_cdm_soc.c @@ -110,6 +110,14 @@ int cam_cdm_soc_load_dt_private(struct platform_device *pdev, CAM_ERR(CAM_CDM, "Reading cdm-client-names failed"); goto end; } + + } + + rc = of_property_read_u8(pdev->dev.of_node, "cdm-priority-group", + &ptr->priority_group); + if (rc < 0) { + ptr->priority_group = 0; + rc = 0; } ptr->config_fifo = of_property_read_bool(pdev->dev.of_node, @@ -154,12 +162,13 @@ int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, int rc; struct cam_hw_soc_info *soc_ptr; const struct of_device_id *id; - struct cam_cdm *cdm_core = cdm_hw->core_info; + struct cam_cdm *cdm_core = NULL; if (!cdm_hw || (cdm_hw->soc_info.soc_private) || !(cdm_hw->soc_info.pdev)) return -EINVAL; + cdm_core = cdm_hw->core_info; soc_ptr = &cdm_hw->soc_info; rc = cam_soc_util_get_dt_properties(soc_ptr); @@ -191,7 +200,7 @@ int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, CAM_DBG(CAM_CDM, "name %s", cdm_core->name); - snprintf(cdm_core->name, sizeof(cdm_core->name) + 1, "%s%d", + snprintf(cdm_core->name, sizeof(cdm_core->name), "%s%d", id->compatible, soc_ptr->index); CAM_DBG(CAM_CDM, "name %s", cdm_core->name); From a68684d77c9d8a7bb172c488af460be87bd9e4f2 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Fri, 21 Feb 2020 13:39:59 -0800 Subject: [PATCH 365/790] msm: camera: mem_mgr: Cache invalidation optimization During unmap these internal buffers will be freed immediately afterwards, therefore there is no need to do cache operation. CRs-Fixed: 2627074 Change-Id: Ica4ebb93eb212604268c3450a92d075197783537 Signed-off-by: Karthik Jayakumar --- drivers/cam_req_mgr/cam_mem_mgr.c | 37 ++++++++++++++++++++++++--- drivers/cam_req_mgr/cam_mem_mgr.h | 2 ++ drivers/cam_req_mgr/cam_req_mgr_dev.c | 1 + drivers/cam_smmu/cam_smmu_api.c | 15 ++++++++--- drivers/cam_smmu/cam_smmu_api.h | 7 +++-- 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 97a6c8b1b094..af6bd0160e1a 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -196,6 +196,7 @@ static void cam_mem_put_slot(int32_t idx) mutex_lock(&tbl.m_lock); mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].active = false; + tbl.bufq[idx].is_internal = false; mutex_unlock(&tbl.bufq[idx].q_lock); mutex_destroy(&tbl.bufq[idx].q_lock); clear_bit(idx, tbl.bitmap); @@ -540,7 +541,8 @@ static int cam_mem_util_map_hw_va(uint32_t flags, int fd, dma_addr_t *hw_vaddr, size_t *len, - enum cam_smmu_region_id region) + enum cam_smmu_region_id region, + bool is_internal) { int i; int rc = -1; @@ -582,7 +584,8 @@ static int cam_mem_util_map_hw_va(uint32_t flags, dir, (dma_addr_t *)hw_vaddr, len, - region); + region, + is_internal); if (rc < 0) { CAM_ERR(CAM_MEM, @@ -675,7 +678,8 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) fd, &hw_vaddr, &len, - region); + region, + true); if (rc) { CAM_ERR(CAM_MEM, @@ -691,6 +695,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) tbl.bufq[idx].dma_buf = NULL; tbl.bufq[idx].flags = cmd->flags; tbl.bufq[idx].buf_handle = GET_MEM_HANDLE(idx, fd); + tbl.bufq[idx].is_internal = true; if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) CAM_MEM_MGR_SET_SECURE_HDL(tbl.bufq[idx].buf_handle, true); @@ -733,6 +738,23 @@ slot_fail: return rc; } +static bool cam_mem_util_is_map_internal(int32_t fd) +{ + uint32_t i; + bool is_internal = false; + + mutex_lock(&tbl.m_lock); + for_each_set_bit(i, tbl.bitmap, tbl.bits) { + if (tbl.bufq[i].fd == fd) { + is_internal = tbl.bufq[i].is_internal; + break; + } + } + mutex_unlock(&tbl.m_lock); + + return is_internal; +} + int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) { int32_t idx; @@ -740,6 +762,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) struct dma_buf *dmabuf; dma_addr_t hw_vaddr = 0; size_t len = 0; + bool is_internal = false; if (!atomic_read(&cam_mem_mgr_state)) { CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized"); @@ -769,6 +792,8 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) return -EINVAL; } + is_internal = cam_mem_util_is_map_internal(cmd->fd); + if ((cmd->flags & CAM_MEM_FLAG_HW_READ_WRITE) || (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE)) { rc = cam_mem_util_map_hw_va(cmd->flags, @@ -777,7 +802,8 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) cmd->fd, &hw_vaddr, &len, - CAM_SMMU_REGION_IO); + CAM_SMMU_REGION_IO, + is_internal); if (rc) { CAM_ERR(CAM_MEM, "Failed in map_hw_va, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", @@ -813,6 +839,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) memcpy(tbl.bufq[idx].hdls, cmd->mmu_hdls, sizeof(int32_t) * cmd->num_hdl); tbl.bufq[idx].is_imported = true; + tbl.bufq[idx].is_internal = is_internal; mutex_unlock(&tbl.bufq[idx].q_lock); cmd->out.buf_handle = tbl.bufq[idx].buf_handle; @@ -939,6 +966,7 @@ static int cam_mem_mgr_cleanup_table(void) tbl.bufq[i].num_hdl = 0; tbl.bufq[i].dma_buf = NULL; tbl.bufq[i].active = false; + tbl.bufq[i].is_internal = false; mutex_unlock(&tbl.bufq[i].q_lock); mutex_destroy(&tbl.bufq[i].q_lock); } @@ -1034,6 +1062,7 @@ static int cam_mem_util_unmap(int32_t idx, tbl.bufq[idx].fd = -1; tbl.bufq[idx].dma_buf = NULL; tbl.bufq[idx].is_imported = false; + tbl.bufq[idx].is_internal = false; tbl.bufq[idx].len = 0; tbl.bufq[idx].num_hdl = 0; tbl.bufq[idx].active = false; diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index b9e42b62d52f..16bb4bdf7094 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -41,6 +41,7 @@ enum cam_smmu_mapping_client { * @kmdvaddr: Kernel virtual address * @active: state of the buffer * @is_imported: Flag indicating if buffer is imported from an FD in user space + * @is_internal: Flag indicating kernel allocated buffer */ struct cam_mem_buf_queue { struct dma_buf *dma_buf; @@ -56,6 +57,7 @@ struct cam_mem_buf_queue { uintptr_t kmdvaddr; bool active; bool is_imported; + bool is_internal; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 555ad537b830..348cab5603eb 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -7,6 +7,7 @@ #include #include #include +#include #include diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 61c1ee44a2e9..74bd0e6689fd 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -197,6 +197,7 @@ struct cam_dma_buff_info { int ion_fd; size_t len; size_t phys_len; + bool is_internal; }; struct cam_sec_buff_info { @@ -249,7 +250,7 @@ static struct cam_dma_buff_info *cam_smmu_find_mapping_by_virt_address(int idx, static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, bool dis_delayed_unmap, enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, size_t *len_ptr, - enum cam_smmu_region_id region_id); + enum cam_smmu_region_id region_id, bool is_internal); static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, struct dma_buf *buf, enum dma_data_direction dma_dir, @@ -1997,7 +1998,7 @@ err_out: static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, bool dis_delayed_unmap, enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr, size_t *len_ptr, - enum cam_smmu_region_id region_id) + enum cam_smmu_region_id region_id, bool is_internal) { int rc = -1; struct cam_dma_buff_info *mapping_info = NULL; @@ -2015,6 +2016,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, } mapping_info->ion_fd = ion_fd; + mapping_info->is_internal = is_internal; /* add to the list */ list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list); @@ -2118,6 +2120,9 @@ static int cam_smmu_unmap_buf_and_remove_from_list( iommu_cb_set.cb_info[idx].io_mapping_size -= mapping_info->len; } + if (mapping_info->is_internal) + mapping_info->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; + dma_buf_unmap_attachment(mapping_info->attach, mapping_info->table, mapping_info->dir); dma_buf_detach(mapping_info->buf, mapping_info->attach); @@ -2877,7 +2882,8 @@ static int cam_smmu_map_iova_validate_params(int handle, int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, enum cam_smmu_map_dir dir, dma_addr_t *paddr_ptr, - size_t *len_ptr, enum cam_smmu_region_id region_id) + size_t *len_ptr, enum cam_smmu_region_id region_id, + bool is_internal) { int idx, rc = 0; enum cam_smmu_buf_state buf_state; @@ -2927,7 +2933,8 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, } rc = cam_smmu_map_buffer_and_add_to_list(idx, ion_fd, - dis_delayed_unmap, dma_dir, paddr_ptr, len_ptr, region_id); + dis_delayed_unmap, dma_dir, paddr_ptr, len_ptr, + region_id, is_internal); if (rc < 0) { CAM_ERR(CAM_SMMU, "mapping or add list fail, idx=%d, fd=%d, region=%d, rc=%d", diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index d89cba1510dc..19d96e4e242b 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SMMU_API_H_ @@ -111,11 +111,13 @@ int cam_smmu_ops(int handle, enum cam_smmu_ops_param op); * CAM_SMMU_REGION_SHARED, dma_addr is used as an input parameter * which specifies the cpu virtual address to map. * @len_ptr : Length of buffer mapped returned by CAM SMMU driver. + * @region_id : Memory region identifier + * @is_internal: Specifies if this buffer is kernel allocated. * @return Status of operation. Negative in case of error. Zero otherwise. */ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, enum cam_smmu_map_dir dir, dma_addr_t *dma_addr, size_t *len_ptr, - enum cam_smmu_region_id region_id); + enum cam_smmu_region_id region_id, bool is_internal); /** * @brief : Maps kernel space IOVA for calling driver @@ -129,6 +131,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, * CAM_SMMU_REGION_SHARED, dma_addr is used as an input * parameter which specifies the cpu virtual address to map. * @len_ptr : Length of buffer mapped returned by CAM SMMU driver. + * @region_id : Memory region identifier * @return Status of operation. Negative in case of error. Zero otherwise. */ int cam_smmu_map_kernel_iova(int handle, From 083b98cdb338a9977cb10a87049abbbadc9f02fd Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 14 Oct 2019 14:45:04 -0700 Subject: [PATCH 366/790] msm: camera: ife: check for constraint violation Add support for debugging constraint violations within the VFE Bus. CRs-Fixed: 2545323 Change-Id: Ib8805b6b61284ac869218cab4d6689ded23bf98a Signed-off-by: Karthik Jayakumar --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 673 +++++++++--------- 1 file changed, 350 insertions(+), 323 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index e6f62b361cd1..9c0f86799058 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -6,7 +6,6 @@ #include #include - #include #include "cam_io_util.h" @@ -63,6 +62,12 @@ enum cam_vfe_bus_ver3_packer_format { PACKER_FMT_VER3_MAX, }; +struct cam_vfe_bus_error_info { + uint32_t bitmask; + uint32_t vfe_output; + char *error_description; +}; + struct cam_vfe_bus_ver3_common_data { uint32_t core_index; void __iomem *mem_base; @@ -191,6 +196,265 @@ struct cam_vfe_bus_ver3_priv { void *tasklet_info; }; +static const struct cam_vfe_bus_error_info vfe_error_list[] = { + { + .bitmask = 0x0000001, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_FULL, + .error_description = "VID Y 1:1" + }, + { + .bitmask = 0x0000002, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_FULL, + .error_description = "VID C 1:1" + }, + { + .bitmask = 0x0000004, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_DS4, + .error_description = "VID YC 4:1" + }, + { + .bitmask = 0x0000008, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_DS16, + .error_description = "VID YC 16:1" + }, + { + .bitmask = 0x0000010, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + .error_description = "DISP Y 1:1" + }, + { + .bitmask = 0x0000020, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + .error_description = "DISP C 1:1" + }, + { + .bitmask = 0x0000040, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, + .error_description = "DISP YC 4:1" + }, + { + .bitmask = 0x0000080, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, + .error_description = "DISP YC 16:1" + }, + { + .bitmask = 0x0000100, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_FD, + .error_description = "FD Y" + }, + { + .bitmask = 0x0000200, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_FD, + .error_description = "FD C" + }, + { + .bitmask = 0x0000400, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, + .error_description = "PIXEL RAW DUMP" + }, + { + .bitmask = 0x0001000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, + .error_description = "STATS HDR BE" + }, + { + .bitmask = 0x0002000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, + .error_description = "STATS HDR BHIST" + }, + { + .bitmask = 0x0004000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, + .error_description = "STATS TINTLESS BG" + }, + { + .bitmask = 0x0008000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, + .error_description = "STATS AWB BG" + }, + { + .bitmask = 0x0010000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, + .error_description = "STATS BHIST" + }, + { + .bitmask = 0x0020000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, + .error_description = "STATS RS" + }, + { + .bitmask = 0x0040000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, + .error_description = "STATS CS" + }, + { + .bitmask = 0x0080000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, + .error_description = "STATS IHIST" + }, + { + .bitmask = 0x0100000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, + .error_description = "STATS BAF" + }, + { + .bitmask = 0x0200000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_2PD, + .error_description = "PD" + }, + { + .bitmask = 0x0400000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_LCR, + .error_description = "LCR" + }, + { + .bitmask = 0x0800000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + .error_description = "Full RDI 0" + }, + { + .bitmask = 0x1000000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + .error_description = "Full RDI 1" + }, + { + .bitmask = 0x2000000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + .error_description = "Full RDI 2" + }, +}; + +static const struct cam_vfe_bus_error_info vfe_constraint_error_list[] = { + { + .bitmask = 0x000001, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "PPC 1x1 illegal" + }, + { + .bitmask = 0x000002, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "PPC 1x2 illegal" + }, + { + .bitmask = 0x000004, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "PPC 2x1 illegal" + }, + { + .bitmask = 0x000008, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "PPC 2x2 illegal" + }, + { + .bitmask = 0x000010, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Pack 8 BPP illegal" + }, + { + .bitmask = 0x000020, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Pack 16 BPP illegal" + }, + { + .bitmask = 0x000040, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Pack 32 BPP illegal" + }, + { + .bitmask = 0x000080, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Pack 64 BPP illegal" + }, + { + .bitmask = 0x000100, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Pack 128 BPP illegal" + }, + { + .bitmask = 0x000200, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "UBWC NV12 illegal" + }, + { + .bitmask = 0x000400, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "UBWC NV12 4R illegal" + }, + { + .bitmask = 0x000800, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "UBWC TP10 illegal" + }, + { + .bitmask = 0x001000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Frame based illegal" + }, + { + .bitmask = 0x002000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Index based illegal" + }, + { + .bitmask = 0x004000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Image address unalign" + }, + { + .bitmask = 0x008000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "UBWC address unalign" + }, + { + .bitmask = 0x010000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Frame Header address unalign" + }, + { + .bitmask = 0x020000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "X Initialization unalign" + }, + { + .bitmask = 0x040000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Image Width unalign" + }, + { + .bitmask = 0x080000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Image Height unalign" + }, + { + .bitmask = 0x100000, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_MAX, + .error_description = "Meta Stride unalign" + }, +}; + +static const struct cam_vfe_bus_error_info vfe_lite_error_list[] = { + { + .bitmask = 0x01, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + .error_description = "Lite RDI 0" + }, + { + .bitmask = 0x02, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + .error_description = "Lite RDI 1" + }, + { + .bitmask = 0x04, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + .error_description = "Lite RDI 2" + }, + { + .bitmask = 0x08, + .vfe_output = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, + .error_description = "Lite RDI 3" + } +}; + static int cam_vfe_bus_ver3_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); @@ -909,6 +1173,42 @@ static int cam_vfe_bus_ver3_handle_rup_top_half(uint32_t evt_id, return rc; } +static void cam_vfe_bus_ver3_print_constraint_errors( + uint32_t wm_idx, + uint32_t constraint_errors) +{ + uint32_t i; + + CAM_INFO(CAM_ISP, "Constraint violation bitflags: %u", + constraint_errors); + + for (i = 0; i < ARRAY_SIZE(vfe_constraint_error_list); i++) { + if (vfe_constraint_error_list[i].bitmask & constraint_errors) { + CAM_INFO(CAM_ISP, "WM:%u %s programming", + wm_idx, + vfe_constraint_error_list[i].error_description); + } + } +} + +static void cam_vfe_bus_ver3_get_constraint_errors( + struct cam_vfe_bus_ver3_priv *bus_priv) +{ + uint32_t i, constraint_errors; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data; + + for (i = 0; i < bus_priv->num_client; i++) { + wm_data = bus_priv->bus_client[i].res_priv; + if (wm_data) { + constraint_errors = cam_io_r_mb( + bus_priv->common_data.mem_base + + wm_data->hw_regs->debug_status_1); + cam_vfe_bus_ver3_print_constraint_errors(i, + constraint_errors); + } + } +} + static int cam_vfe_bus_ver3_handle_rup_bottom_half(void *handler_priv, void *evt_payload_priv) { @@ -1315,6 +1615,7 @@ static int cam_vfe_bus_ver3_release_wm(void *bus_priv, static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) { + const uint32_t enable_debug_status_1 = 11 << 8; int val = 0; struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data = wm_res->res_priv; @@ -1343,6 +1644,11 @@ static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + rsrc_data->hw_regs->cfg); + /* Enable constraint error detection */ + cam_io_w_mb(enable_debug_status_1, + common_data->mem_base + + rsrc_data->hw_regs->debug_status_cfg); + CAM_DBG(CAM_ISP, "Start VFE:%d WM:%d offset:0x%X en_cfg:0x%X width:%d height:%d", rsrc_data->common_data->core_index, rsrc_data->index, @@ -2487,6 +2793,28 @@ static int cam_vfe_bus_ver3_err_irq_top_half(uint32_t evt_id, return rc; } +static void cam_vfe_print_violations( + char *error_type, + const struct cam_vfe_bus_error_info *error_list, + uint32_t num_errors, + uint32_t status, + struct cam_vfe_bus_ver3_priv *bus_priv) +{ + int i; + + for (i = 0; i < num_errors; i++) { + if (status & error_list[i].bitmask) { + CAM_INFO(CAM_ISP, "%s: %s violation", + error_list[i].error_description, + error_type); + if (bus_priv != NULL) + cam_vfe_bus_ver3_print_dimensions( + error_list[i].vfe_output, + bus_priv); + } + } +} + static int cam_vfe_bus_ver3_err_irq_bottom_half( void *handler_priv, void *evt_payload_priv) { @@ -2494,350 +2822,49 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( struct cam_vfe_bus_ver3_priv *bus_priv = handler_priv; struct cam_vfe_bus_ver3_common_data *common_data; struct cam_isp_hw_event_info evt_info; - uint32_t val = 0, image_size_violation = 0, ccif_violation = 0; + const struct cam_vfe_bus_error_info *error_list = NULL; + uint32_t error_list_size = 0; + uint32_t status = 0, image_size_violation = 0, ccif_violation = 0; if (!handler_priv || !evt_payload_priv) return -EINVAL; common_data = &bus_priv->common_data; - val = evt_payload->irq_reg_val[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; - image_size_violation = (val >> 31) & 0x1; - ccif_violation = (val >> 30) & 0x1; + status = evt_payload->irq_reg_val[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; + image_size_violation = (status >> 31) & 0x1; + ccif_violation = (status >> 30) & 0x1; CAM_ERR(CAM_ISP, - "VFE:%d BUS Violation image_size_violation %d ccif_violation %d", + "VFE:%d BUS error image size violation %d CCIF violation %d", bus_priv->common_data.core_index, image_size_violation, ccif_violation); CAM_INFO(CAM_ISP, - "image_size_violation_status 0x%X ccif_violation_status 0x%X", + "Image Size violation status 0x%X CCIF violation status 0x%X", evt_payload->image_size_violation_status, evt_payload->ccif_violation_status); - if (common_data->is_lite) { - if (image_size_violation) { - val = evt_payload->image_size_violation_status; - - if (val & 0x01) { - CAM_INFO(CAM_ISP, - "RDI 0 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI0, - bus_priv); - } - - if (val & 0x02) { - CAM_INFO(CAM_ISP, - "RDI 1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI1, - bus_priv); - } - - if (val & 0x04) { - CAM_INFO(CAM_ISP, - "RDI 2 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI2, - bus_priv); - } - - if (val & 0x08) { - CAM_INFO(CAM_ISP, - "RDI 3 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI3, - bus_priv); - } - } - - if (ccif_violation) { - val = evt_payload->ccif_violation_status; - - if (val & 0x01) - CAM_INFO(CAM_ISP, - "RDI 0 ccif violation"); - - if (val & 0x02) - CAM_INFO(CAM_ISP, - "RDI 1 ccif violation"); - - if (val & 0x04) - CAM_INFO(CAM_ISP, - "RDI 2 ccif violation"); - - if (val & 0x08) - CAM_INFO(CAM_ISP, - "RDI 3 ccif violation"); - } - - goto end; - } + error_list = common_data->is_lite ? + vfe_lite_error_list : vfe_error_list; + error_list_size = common_data->is_lite ? + ARRAY_SIZE(vfe_lite_error_list) : ARRAY_SIZE(vfe_error_list); if (image_size_violation) { - val = evt_payload->image_size_violation_status; - - if (val & 0x01) { - CAM_INFO(CAM_ISP, "VID Y 1:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_FULL, - bus_priv); + status = evt_payload->image_size_violation_status; + if (!status) + cam_vfe_bus_ver3_get_constraint_errors(bus_priv); + else { + cam_vfe_print_violations("Image Size", error_list, + error_list_size, status, bus_priv); } - - if (val & 0x02) { - CAM_INFO(CAM_ISP, "VID C 1:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_FULL, - bus_priv); - } - - if (val & 0x04) { - CAM_INFO(CAM_ISP, "VID YC 4:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_DS4, - bus_priv); - } - - if (val & 0x08) { - CAM_INFO(CAM_ISP, "VID YC 16:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_DS16, - bus_priv); - } - - if (val & 0x010) { - CAM_INFO(CAM_ISP, "DISP Y 1:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, - bus_priv); - } - - if (val & 0x020) { - CAM_INFO(CAM_ISP, "DISP C 1:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, - bus_priv); - } - - if (val & 0x040) { - CAM_INFO(CAM_ISP, "DISP YC 4:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, - bus_priv); - } - - if (val & 0x080) { - CAM_INFO(CAM_ISP, "DISP YC 16:1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, - bus_priv); - } - - if (val & 0x0100) { - CAM_INFO(CAM_ISP, "FD Y image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_FD, - bus_priv); - } - - if (val & 0x0200) { - CAM_INFO(CAM_ISP, "FD C image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_FD, - bus_priv); - } - - if (val & 0x0400) { - CAM_INFO(CAM_ISP, - "PIXEL RAW DUMP image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, - bus_priv); - } - - if (val & 0x01000) { - CAM_INFO(CAM_ISP, "STATS HDR BE image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, - bus_priv); - } - - if (val & 0x02000) { - CAM_INFO(CAM_ISP, - "STATS HDR BHIST image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, - bus_priv); - } - - if (val & 0x04000) { - CAM_INFO(CAM_ISP, - "STATS TINTLESS BG image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, - bus_priv); - } - - if (val & 0x08000) { - CAM_INFO(CAM_ISP, "STATS AWB BG image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, - bus_priv); - } - - if (val & 0x010000) { - CAM_INFO(CAM_ISP, "STATS BHIST image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, - bus_priv); - } - - if (val & 0x020000) { - CAM_INFO(CAM_ISP, "STATS RS image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, - bus_priv); - } - - if (val & 0x040000) { - CAM_INFO(CAM_ISP, "STATS CS image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, - bus_priv); - } - - if (val & 0x080000) { - CAM_INFO(CAM_ISP, "STATS IHIST image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, - bus_priv); - } - - if (val & 0x0100000) { - CAM_INFO(CAM_ISP, "STATS BAF image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, - bus_priv); - } - - if (val & 0x0200000) { - CAM_INFO(CAM_ISP, "PD image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_2PD, - bus_priv); - } - - if (val & 0x0400000) { - CAM_INFO(CAM_ISP, "LCR image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_LCR, - bus_priv); - } - - if (val & 0x0800000) { - CAM_INFO(CAM_ISP, "RDI 0 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI0, - bus_priv); - } - - if (val & 0x01000000) { - CAM_INFO(CAM_ISP, "RDI 1 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI1, - bus_priv); - } - - if (val & 0x02000000) { - CAM_INFO(CAM_ISP, "RDI 2 image size violation"); - cam_vfe_bus_ver3_print_dimensions( - CAM_VFE_BUS_VER3_VFE_OUT_RDI2, - bus_priv); - } - } if (ccif_violation) { - val = evt_payload->ccif_violation_status; - - if (val & 0x01) - CAM_INFO(CAM_ISP, "VID Y 1:1 ccif violation"); - - if (val & 0x02) - CAM_INFO(CAM_ISP, "VID C 1:1 ccif violation"); - - if (val & 0x04) - CAM_INFO(CAM_ISP, "VID YC 4:1 ccif violation"); - - if (val & 0x08) - CAM_INFO(CAM_ISP, "VID YC 16:1 ccif violation"); - - if (val & 0x010) - CAM_INFO(CAM_ISP, "DISP Y 1:1 ccif violation"); - - if (val & 0x020) - CAM_INFO(CAM_ISP, "DISP C 1:1 ccif violation"); - - if (val & 0x040) - CAM_INFO(CAM_ISP, "DISP YC 4:1 ccif violation"); - - if (val & 0x080) - CAM_INFO(CAM_ISP, "DISP YC 16:1 ccif violation"); - - if (val & 0x0100) - CAM_INFO(CAM_ISP, "FD Y ccif violation"); - - if (val & 0x0200) - CAM_INFO(CAM_ISP, "FD C ccif violation"); - - if (val & 0x0400) - CAM_INFO(CAM_ISP, "PIXEL RAW DUMP ccif violation"); - - if (val & 0x01000) - CAM_INFO(CAM_ISP, "STATS HDR BE ccif violation"); - - if (val & 0x02000) - CAM_INFO(CAM_ISP, "STATS HDR BHIST ccif violation"); - - if (val & 0x04000) - CAM_INFO(CAM_ISP, "STATS TINTLESS BG ccif violation"); - - if (val & 0x08000) - CAM_INFO(CAM_ISP, "STATS AWB BG ccif violation"); - - if (val & 0x010000) - CAM_INFO(CAM_ISP, "STATS BHIST ccif violation"); - - if (val & 0x020000) - CAM_INFO(CAM_ISP, "STATS RS ccif violation"); - - if (val & 0x040000) - CAM_INFO(CAM_ISP, "STATS CS ccif violation"); - - if (val & 0x080000) - CAM_INFO(CAM_ISP, "STATS IHIST ccif violation"); - - if (val & 0x0100000) - CAM_INFO(CAM_ISP, "STATS BAF ccif violation"); - - if (val & 0x0200000) - CAM_INFO(CAM_ISP, "PD ccif violation"); - - if (val & 0x0400000) - CAM_INFO(CAM_ISP, "LCR ccif violation"); - - if (val & 0x0800000) - CAM_INFO(CAM_ISP, "RDI 0 ccif violation"); - - if (val & 0x01000000) - CAM_INFO(CAM_ISP, "RDI 1 ccif violation"); - - if (val & 0x02000000) - CAM_INFO(CAM_ISP, "RDI 2 ccif violation"); - + status = evt_payload->ccif_violation_status; + cam_vfe_print_violations("CCIF", error_list, + error_list_size, status, NULL); } -end: cam_vfe_bus_ver3_put_evt_payload(common_data, &evt_payload); evt_info.hw_idx = common_data->core_index; From ec23ff584a62b89b4fa940c8dfa5d60b77590b01 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 10 Mar 2020 15:37:33 -0700 Subject: [PATCH 367/790] msm: camera: smmu: Enhance debug capability for camera memmgr Improve debugging infrastructure and logging for memory related issues. There are scenarios where the fd returned after ion_alloc exists in camera smmu table as being mapped [stale entry]. On such scenarios, this change will return a specific error code to userspace. The change also propagates the mapped size back to user space. CRs-Fixed: 2663114 Change-Id: Ia797b65d1e8ded58dec5b01df07d73262c4cfa95 Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_mem_mgr.c | 62 ++++++++++++++++++++++--- drivers/cam_req_mgr/cam_mem_mgr.h | 2 + drivers/cam_smmu/cam_smmu_api.c | 60 +++++++++++++++++++----- include/uapi/camera/media/cam_req_mgr.h | 4 +- 4 files changed, 107 insertions(+), 21 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index af6bd0160e1a..19a1ebbd30ee 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -22,6 +22,39 @@ static struct cam_mem_table tbl; static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED); +static void cam_mem_mgr_print_tbl(void) +{ + int i; + uint64_t ms, tmp, hrs, min, sec; + struct timespec64 *ts = NULL; + struct timespec64 current_ts; + + ktime_get_real_ts64(&(current_ts)); + tmp = current_ts.tv_sec; + ms = (current_ts.tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); + + CAM_INFO(CAM_MEM, "***%llu:%llu:%llu:%llu Mem mgr table dump***", + hrs, min, sec, ms); + for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) { + if (tbl.bufq[i].active) { + ts = &tbl.bufq[i].timestamp; + tmp = ts->tv_sec; + ms = (ts->tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); + CAM_INFO(CAM_MEM, + "%llu:%llu:%llu:%llu idx %d fd %d size %llu", + hrs, min, sec, ms, i, tbl.bufq[i].fd, + tbl.bufq[i].len); + } + } + +} + static int cam_mem_util_get_dma_dir(uint32_t flags) { int rc = -EINVAL; @@ -185,6 +218,7 @@ static int32_t cam_mem_get_slot(void) set_bit(idx, tbl.bitmap); tbl.bufq[idx].active = true; + ktime_get_real_ts64(&(tbl.bufq[idx].timestamp)); mutex_init(&tbl.bufq[idx].q_lock); mutex_unlock(&tbl.m_lock); @@ -197,6 +231,7 @@ static void cam_mem_put_slot(int32_t idx) mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].active = false; tbl.bufq[idx].is_internal = false; + memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64)); mutex_unlock(&tbl.bufq[idx].q_lock); mutex_destroy(&tbl.bufq[idx].q_lock); clear_bit(idx, tbl.bitmap); @@ -646,6 +681,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) CAM_ERR(CAM_MEM, "Ion Alloc failed, len=%llu, align=%llu, flags=0x%x, num_hdl=%d", cmd->len, cmd->align, cmd->flags, cmd->num_hdl); + cam_mem_mgr_print_tbl(); return rc; } @@ -683,9 +719,14 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) if (rc) { CAM_ERR(CAM_MEM, - "Failed in map_hw_va, len=%llu, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", - cmd->len, cmd->flags, fd, region, - cmd->num_hdl, rc); + "Failed in map_hw_va len=%llu, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", + len, cmd->flags, + fd, region, cmd->num_hdl, rc); + if (rc == -EALREADY) { + if ((size_t)dmabuf->size != len) + rc = -EBADR; + cam_mem_mgr_print_tbl(); + } goto map_hw_fail; } } @@ -806,9 +847,15 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) is_internal); if (rc) { CAM_ERR(CAM_MEM, - "Failed in map_hw_va, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d", - cmd->flags, cmd->fd, CAM_SMMU_REGION_IO, - cmd->num_hdl, rc); + "Failed in map_hw_va, flags=0x%x, fd=%d, len=%llu, region=%d, num_hdl=%d, rc=%d", + cmd->flags, cmd->fd, len, + CAM_SMMU_REGION_IO, cmd->num_hdl, rc); + if (rc == -EALREADY) { + if ((size_t)dmabuf->size != len) { + rc = -EBADR; + cam_mem_mgr_print_tbl(); + } + } goto map_fail; } } @@ -844,7 +891,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) cmd->out.buf_handle = tbl.bufq[idx].buf_handle; cmd->out.vaddr = 0; - + cmd->out.size = (uint32_t)len; CAM_DBG(CAM_MEM, "fd=%d, flags=0x%x, num_hdl=%d, idx=%d, buf handle=%x, len=%zu", cmd->fd, cmd->flags, cmd->num_hdl, idx, cmd->out.buf_handle, @@ -1066,6 +1113,7 @@ static int cam_mem_util_unmap(int32_t idx, tbl.bufq[idx].len = 0; tbl.bufq[idx].num_hdl = 0; tbl.bufq[idx].active = false; + memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64)); mutex_unlock(&tbl.bufq[idx].q_lock); mutex_destroy(&tbl.bufq[idx].q_lock); clear_bit(idx, tbl.bitmap); diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index 16bb4bdf7094..69637ba1dc8e 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -42,6 +42,7 @@ enum cam_smmu_mapping_client { * @active: state of the buffer * @is_imported: Flag indicating if buffer is imported from an FD in user space * @is_internal: Flag indicating kernel allocated buffer + * @timestamp: Timestamp at which this entry in tbl was made */ struct cam_mem_buf_queue { struct dma_buf *dma_buf; @@ -58,6 +59,7 @@ struct cam_mem_buf_queue { bool active; bool is_imported; bool is_internal; + struct timespec64 timestamp; }; /** diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 74bd0e6689fd..b87972840021 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -198,6 +198,7 @@ struct cam_dma_buff_info { size_t len; size_t phys_len; bool is_internal; + struct timespec64 ts; }; struct cam_sec_buff_info { @@ -403,6 +404,9 @@ static void cam_smmu_dump_cb_info(int idx) size_t shared_reg_len = 0, io_reg_len = 0; size_t shared_free_len = 0, io_free_len = 0; uint32_t i = 0; + uint64_t ms, tmp, hrs, min, sec; + struct timespec64 *ts = NULL; + struct timespec64 current_ts; struct cam_context_bank_info *cb_info = &iommu_cb_set.cb_info[idx]; @@ -416,9 +420,15 @@ static void cam_smmu_dump_cb_info(int idx) io_free_len = io_reg_len - cb_info->io_mapping_size; } + ktime_get_real_ts64(&(current_ts)); + tmp = current_ts.tv_sec; + ms = (current_ts.tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); CAM_ERR(CAM_SMMU, - "********** Context bank dump for %s **********", - cb_info->name[0]); + "********** %llu:%llu:%llu:%llu Context bank dump for %s **********", + hrs, min, sec, ms, cb_info->name[0]); CAM_ERR(CAM_SMMU, "Usage: shared_usage=%u io_usage=%u shared_free=%u io_free=%u", (unsigned int)cb_info->shared_mapping_size, @@ -430,9 +440,16 @@ static void cam_smmu_dump_cb_info(int idx) list_for_each_entry_safe(mapping, mapping_temp, &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { i++; + ts = &mapping->ts; + tmp = ts->tv_sec; + ms = (ts->tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); CAM_ERR(CAM_SMMU, - "%u. ion_fd=%d start=0x%x end=0x%x len=%u region=%d", - i, mapping->ion_fd, (void *)mapping->paddr, + "%llu:%llu:%llu:%llu: %u ion_fd=%d start=0x%x end=0x%x len=%u region=%d", + hrs, min, sec, ms, i, mapping->ion_fd, + (void *)mapping->paddr, ((uint64_t)mapping->paddr + (uint64_t)mapping->len), (unsigned int)mapping->len, @@ -2017,6 +2034,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, mapping_info->ion_fd = ion_fd; mapping_info->is_internal = is_internal; + ktime_get_real_ts64(&mapping_info->ts); /* add to the list */ list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list); @@ -2044,7 +2062,7 @@ static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx, } mapping_info->ion_fd = -1; - + ktime_get_real_ts64(&mapping_info->ts); /* add to the list */ list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_kernel_list); @@ -2145,7 +2163,8 @@ static int cam_smmu_unmap_buf_and_remove_from_list( } static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx, - int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr) + int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr, + struct timespec64 **ts_mapping) { struct cam_dma_buff_info *mapping; @@ -2154,6 +2173,7 @@ static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx, if (mapping->ion_fd == ion_fd) { *paddr_ptr = mapping->paddr; *len_ptr = mapping->len; + *ts_mapping = &mapping->ts; return CAM_SMMU_BUFF_EXIST; } } @@ -2886,6 +2906,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, bool is_internal) { int idx, rc = 0; + struct timespec64 *ts = NULL; enum cam_smmu_buf_state buf_state; enum dma_data_direction dma_dir; @@ -2923,11 +2944,23 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, goto get_addr_end; } - buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr); + buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, + len_ptr, &ts); if (buf_state == CAM_SMMU_BUFF_EXIST) { + uint64_t ms = 0, tmp = 0, hrs = 0, min = 0, sec = 0; + + if (ts) { + tmp = ts->tv_sec; + ms = (ts->tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); + } CAM_ERR(CAM_SMMU, - "fd:%d already in list idx:%d, handle=%d, give same addr back", - ion_fd, idx, handle); + "fd=%d already in list [%llu:%llu:%lu:%llu] cb=%s idx=%d handle=%d len=%llu,give same addr back", + ion_fd, hrs, min, sec, ms, + iommu_cb_set.cb_info[idx].name[0], + idx, handle, *len_ptr); rc = -EALREADY; goto get_addr_end; } @@ -2937,8 +2970,9 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, region_id, is_internal); if (rc < 0) { CAM_ERR(CAM_SMMU, - "mapping or add list fail, idx=%d, fd=%d, region=%d, rc=%d", - idx, ion_fd, region_id, rc); + "mapping or add list fail cb:%s idx=%d, fd=%d, region=%d, rc=%d", + iommu_cb_set.cb_info[idx].name[0], idx, + ion_fd, region_id, rc); cam_smmu_dump_cb_info(idx); } @@ -3012,6 +3046,7 @@ int cam_smmu_get_iova(int handle, int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr) { int idx, rc = 0; + struct timespec64 *ts = NULL; enum cam_smmu_buf_state buf_state; if (!paddr_ptr || !len_ptr) { @@ -3051,7 +3086,8 @@ int cam_smmu_get_iova(int handle, int ion_fd, goto get_addr_end; } - buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr); + buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, + len_ptr, &ts); if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) { CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd); rc = -EINVAL; diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 80a52fb01504..fc6924920616 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -343,12 +343,12 @@ struct cam_mem_alloc_out_params { /** * struct cam_mem_map_out_params * @buf_handle: buffer handle - * @reserved: reserved for future + * @size: size of the buffer being mapped * @vaddr: virtual address pointer */ struct cam_mem_map_out_params { __u32 buf_handle; - __u32 reserved; + __u32 size; __u64 vaddr; }; From 0816d56047cd6843b63f4f700fef98268b8b800c Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 27 Apr 2020 08:46:18 +0530 Subject: [PATCH 368/790] msm: camera: isp: Correct the bitmask for packet header Bitmask for printing the CSI short packet and CPHY packet is configured wrong. Change the bitmask to print the correct values. CRs-Fixed: 2672724 Change-Id: I716ea7f6e1dacc9669498d01550009a290374237 Signed-off-by: Gaurav Jindal --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 66803e43100d..c144d4213a07 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4246,7 +4246,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d short pkt VC :%d DT:%d LC:%d", csid_hw->hw_intf->hw_idx, - (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + (val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF)); val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csi2_reg->csid_csi2_rx_captured_short_pkt_1_addr); CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d short packet ECC :%d", @@ -4262,7 +4262,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d cphy packet VC :%d DT:%d WC:%d", csid_hw->hw_intf->hw_idx, - (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + (val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF)); } /*read the IPP errors */ From 346084f00ad1cb02a0c9dbcb2e77d32478483fa7 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Thu, 26 Mar 2020 17:35:01 -0700 Subject: [PATCH 369/790] msm: camera: ife: Add support for csitpg 1.3 Add version_3 files to support next revision of CPHY TPG. Extended capability for Multi-VC mode of operation. Add support to handle IRQ. CRs-Fixed: 2663712 Change-Id: I91864af6e9415e74104a6bce266dd78d5c021dc7 Signed-off-by: Vishalsingh Hajeri --- drivers/Makefile | 1 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 +- .../isp_hw/include/cam_top_tpg_hw_intf.h | 19 +- .../isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c | 5 + .../isp_hw/top_tpg/cam_top_tpg102.h | 4 +- .../isp_hw/top_tpg/cam_top_tpg103.h | 124 +++++++ .../isp_hw/top_tpg/cam_top_tpg_core.c | 74 +++- .../isp_hw/top_tpg/cam_top_tpg_core.h | 7 +- .../isp_hw/top_tpg/cam_top_tpg_soc.c | 4 +- .../isp_hw/top_tpg/cam_top_tpg_soc.h | 3 +- .../isp_hw/top_tpg/cam_top_tpg_ver1.c | 45 +-- .../isp_hw/top_tpg/cam_top_tpg_ver3.c | 345 ++++++++++++++++++ .../isp_hw/top_tpg/cam_top_tpg_ver3.h | 118 ++++++ include/uapi/camera/media/cam_isp_ife.h | 3 +- 15 files changed, 707 insertions(+), 51 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h diff --git a/drivers/Makefile b/drivers/Makefile index dc5da5116010..57e2929ab37f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -90,6 +90,7 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.o \ + cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o \ cam_isp/isp_hw_mgr/cam_isp_hw_mgr.o \ cam_isp/isp_hw_mgr/cam_ife_hw_mgr.o \ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index bfdc76f930d8..87e947c93ae9 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2946,7 +2946,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) } if ((in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || - (in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) + (in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || + (in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) rc = cam_ife_hw_mgr_acquire_tpg(ife_ctx, in_port, acquire_hw_info->num_inputs); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 66803e43100d..b885cd17baf7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1146,7 +1146,8 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->crop_enable); if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || - (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) { + (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || + (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) { path_data->dt = CAM_IFE_CPHY_TPG_DT_VAL; path_data->vc = CAM_IFE_CPHY_TPG_VC_VAL; } else if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h index fdbc6639bd87..1aa9d26e11c1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h @@ -11,7 +11,7 @@ #include "cam_ife_csid_hw_intf.h" /* Max top tpg instance */ -#define CAM_TOP_TPG_HW_NUM_MAX 2 +#define CAM_TOP_TPG_HW_NUM_MAX 3 /* Max supported number of DT for TPG */ #define CAM_TOP_TPG_MAX_SUPPORTED_DT 4 @@ -21,6 +21,7 @@ enum cam_top_tpg_id { CAM_TOP_TPG_ID_0, CAM_TOP_TPG_ID_1, + CAM_TOP_TPG_ID_2, CAM_TFE_TPG_ID_MAX, }; @@ -55,7 +56,7 @@ struct cam_top_tpg_ver1_reserve_args { /** * struct cam_top_tpg_ver2_reserve_args * @num_inport: number of inport - * TPG supports 1 VC/DT + * TPG supports 1 VC/DT combo * @in_port : Input port resource info structure pointer * @node_res : Reserved resource structure pointer * @@ -66,6 +67,20 @@ struct cam_top_tpg_ver2_reserve_args { struct cam_isp_resource_node *node_res; }; +/** + * struct cam_top_tpg_ver2_reserve_args + * @num_inport: number of inport + * TPG supports 4 VC's and 4 DT's per VC + * @in_port : Input port resource info structure pointer + * @node_res : Reserved resource structure pointer + * + */ +struct cam_top_tpg_ver3_reserve_args { + uint32_t num_inport; + struct cam_isp_in_port_generic_info *in_port; + struct cam_isp_resource_node *node_res; +}; + /** * cam_top_tpg_hw_init() * diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c index 9eafcf4da636..6d86970457e4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c @@ -6,6 +6,7 @@ #include #include "cam_top_tpg101.h" #include "cam_top_tpg102.h" +#include "cam_top_tpg103.h" #include "cam_top_tpg_core.h" #include "cam_top_tpg_dev.h" #include "camera_main.h" @@ -19,6 +20,10 @@ static const struct of_device_id cam_top_tpg_dt_match[] = { .compatible = "qcom,tpg102", .data = &cam_top_tpg102_hw_info, }, + { + .compatible = "qcom,tpg103", + .data = &cam_top_tpg103_hw_info, + }, {} }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h index ce2f2c73a070..0a3a54bf612f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h @@ -43,8 +43,8 @@ static struct cam_top_tpg_ver2_reg_offset cam_top_tpg102_reg = { struct cam_top_tpg_hw_info cam_top_tpg102_hw_info = { .tpg_reg = &cam_top_tpg102_reg, .hw_dts_version = CAM_TOP_TPG_VERSION_2, - .csid_max_clk = 426400000, - .phy_max_clk = 384000000, + .csid_max_clk = 400000000, + .phy_max_clk = 400000000, }; #endif /* _CAM_TOP_TPG102_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h new file mode 100644 index 000000000000..396671852799 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG103_H_ +#define _CAM_TOP_TPG103_H_ + +#include "cam_top_tpg_ver3.h" +#include "cam_top_tpg_core.h" + +static struct cam_top_tpg_ver3_reg_offset cam_top_tpg103_reg = { + .tpg_hw_version = 0x0, + .tpg_hw_status = 0x4, + .tpg_ctrl = 0x64, + .tpg_vc0_cfg0 = 0x68, + .tpg_vc0_lfsr_seed = 0x6C, + .tpg_vc0_hbi_cfg = 0x70, + .tpg_vc0_vbi_cfg = 0x74, + .tpg_vc0_color_bar_cfg = 0x78, + .tpg_vc0_dt_0_cfg_0 = 0x7C, + .tpg_vc0_dt_0_cfg_1 = 0x80, + .tpg_vc0_dt_0_cfg_2 = 0x84, + .tpg_vc0_dt_1_cfg_0 = 0x88, + .tpg_vc0_dt_1_cfg_1 = 0x8C, + .tpg_vc0_dt_1_cfg_2 = 0x90, + .tpg_vc0_dt_2_cfg_0 = 0x94, + .tpg_vc0_dt_2_cfg_1 = 0x98, + .tpg_vc0_dt_2_cfg_2 = 0x9C, + .tpg_vc0_dt_3_cfg_0 = 0xA0, + .tpg_vc0_dt_3_cfg_1 = 0xA4, + .tpg_vc0_dt_3_cfg_2 = 0xA8, + + .tpg_vc1_cfg0 = 0xC8, + .tpg_vc1_lfsr_seed = 0xCC, + .tpg_vc1_hbi_cfg = 0xD0, + .tpg_vc1_vbi_cfg = 0xD4, + .tpg_vc1_color_bar_cfg = 0xD8, + .tpg_vc1_dt_0_cfg_0 = 0xDC, + .tpg_vc1_dt_0_cfg_1 = 0xE0, + .tpg_vc1_dt_0_cfg_2 = 0xE4, + .tpg_vc1_dt_1_cfg_0 = 0xE8, + .tpg_vc1_dt_1_cfg_1 = 0xEC, + .tpg_vc1_dt_1_cfg_2 = 0xF0, + .tpg_vc1_dt_2_cfg_0 = 0xF4, + .tpg_vc1_dt_2_cfg_1 = 0xF8, + .tpg_vc1_dt_2_cfg_2 = 0xFC, + .tpg_vc1_dt_3_cfg_0 = 0x100, + .tpg_vc1_dt_3_cfg_1 = 0x104, + .tpg_vc1_dt_3_cfg_2 = 0x108, + + .tpg_vc2_cfg0 = 0x128, + .tpg_vc2_lfsr_seed = 0x12C, + .tpg_vc2_hbi_cfg = 0x130, + .tpg_vc2_vbi_cfg = 0x134, + .tpg_vc2_color_bar_cfg = 0x138, + .tpg_vc2_dt_0_cfg_0 = 0x13C, + .tpg_vc2_dt_0_cfg_1 = 0x140, + .tpg_vc2_dt_0_cfg_2 = 0x144, + .tpg_vc2_dt_1_cfg_0 = 0x148, + .tpg_vc2_dt_1_cfg_1 = 0x14C, + .tpg_vc2_dt_1_cfg_2 = 0x150, + .tpg_vc2_dt_2_cfg_0 = 0x154, + .tpg_vc2_dt_2_cfg_1 = 0x158, + .tpg_vc2_dt_2_cfg_2 = 0x15C, + .tpg_vc2_dt_3_cfg_0 = 0x160, + .tpg_vc2_dt_3_cfg_1 = 0x164, + .tpg_vc2_dt_3_cfg_2 = 0x168, + + .tpg_vc3_cfg0 = 0x188, + .tpg_vc3_lfsr_seed = 0x18C, + .tpg_vc3_hbi_cfg = 0x190, + .tpg_vc3_vbi_cfg = 0x194, + .tpg_vc3_color_bar_cfg = 0x198, + .tpg_vc3_dt_0_cfg_0 = 0x19C, + .tpg_vc3_dt_0_cfg_1 = 0x1A0, + .tpg_vc3_dt_0_cfg_2 = 0x1A4, + .tpg_vc3_dt_1_cfg_0 = 0x1A8, + .tpg_vc3_dt_1_cfg_1 = 0x1AC, + .tpg_vc3_dt_1_cfg_2 = 0x1B0, + .tpg_vc3_dt_2_cfg_0 = 0x1B4, + .tpg_vc3_dt_2_cfg_1 = 0x1B8, + .tpg_vc3_dt_2_cfg_2 = 0x1BC, + .tpg_vc3_dt_3_cfg_0 = 0x1C0, + .tpg_vc3_dt_3_cfg_1 = 0x1C4, + .tpg_vc3_dt_3_cfg_2 = 0x1C8, + .tpg_throttle = 0x1CC, + .tpg_top_irq_status = 0x1E0, + .tpg_top_irq_mask = 0x1E4, + .tpg_top_irq_clear = 0x1E8, + .tpg_top_irq_set = 0x1EC, + .tpg_top_irq_cmd = 0x1F0, + .tpg_top_clear = 0x1F4, + .tpg_test_bus_crtl = 0x1F8, + .tpg_spare = 0x1FC, + + /* configurations */ + .major_version = 2, + .minor_version = 0, + .version_incr = 0, + .tpg_en_shift_val = 0, + .tpg_cphy_dphy_sel_shift_val = 3, + .tpg_num_active_lanes_shift = 4, + .tpg_fe_pkt_en_shift = 2, + .tpg_fs_pkt_en_shift = 1, + .tpg_line_interleaving_mode_shift = 10, + .tpg_num_dts_shift_val = 8, + .tpg_v_blank_cnt_shift = 12, + .tpg_dt_encode_format_shift = 20, + .tpg_payload_mode_color = 0x8, + .tpg_split_en_shift = 4, + .top_mux_reg_offset = 0x1C, + .tpg_vc_dt_pattern_id_shift = 6, + .tpg_num_active_vcs_shift = 30, +}; + +struct cam_top_tpg_hw_info cam_top_tpg103_hw_info = { + .tpg_reg = &cam_top_tpg103_reg, + .hw_dts_version = CAM_TOP_TPG_VERSION_3, + .csid_max_clk = 480000000, + .phy_max_clk = 480000000, +}; + +#endif /* _CAM_TOP_TPG103_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c index 64b776623d72..23b62f6fdb85 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c @@ -15,6 +15,40 @@ #include "cam_cpas_api.h" #include "cam_top_tpg_ver1.h" #include "cam_top_tpg_ver2.h" +#include "cam_top_tpg_ver3.h" + +int cam_top_tpg_get_format( + uint32_t in_format, + uint32_t *tpg_encode_format) +{ + int rc = 0; + + switch (in_format) { + case CAM_FORMAT_MIPI_RAW_6: + *tpg_encode_format = 0; + break; + case CAM_FORMAT_MIPI_RAW_8: + *tpg_encode_format = 1; + break; + case CAM_FORMAT_MIPI_RAW_10: + *tpg_encode_format = 2; + break; + case CAM_FORMAT_MIPI_RAW_12: + *tpg_encode_format = 3; + break; + case CAM_FORMAT_MIPI_RAW_14: + *tpg_encode_format = 4; + break; + case CAM_FORMAT_MIPI_RAW_16: + *tpg_encode_format = 5; + break; + default: + CAM_ERR(CAM_ISP, "Unsupported input encode format %d", + in_format); + rc = -EINVAL; + } + return rc; +} static int cam_top_tpg_release(void *hw_priv, void *release_args, uint32_t arg_size) @@ -212,6 +246,42 @@ static int cam_top_tpg_set_phy_clock( return 0; } +irqreturn_t cam_top_tpg_irq(int irq_num, void *data) +{ + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_soc_info *soc_info; + struct cam_top_tpg_ver3_reg_offset *tpg_reg; + uint32_t irq_status_top; + unsigned long flags; + + if (!data) { + CAM_ERR(CAM_ISP, "TPG: Invalid arguments"); + return IRQ_HANDLED; + } + + + tpg_hw = (struct cam_top_tpg_hw *) data; + CAM_DBG(CAM_ISP, "CPHY TPG %d IRQ Handling", tpg_hw->hw_intf->hw_idx); + + soc_info = &tpg_hw->hw_info->soc_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + + irq_status_top = cam_io_r_mb(soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_status); + + spin_lock_irqsave(&tpg_hw->hw_info->hw_lock, flags); + /* clear */ + cam_io_w_mb(irq_status_top, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_clear); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_cmd); + + spin_unlock_irqrestore(&tpg_hw->hw_info->hw_lock, flags); + + CAM_DBG(CAM_ISP, "TPG: irq_status_top = 0x%x", irq_status_top); + return IRQ_HANDLED; +} + static int cam_top_tpg_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -272,7 +342,7 @@ int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf, init_completion(&tpg_hw->tpg_complete); rc = cam_top_tpg_init_soc_resources(&tpg_hw->hw_info->soc_info, - tpg_hw); + cam_top_tpg_irq, tpg_hw); if (rc < 0) { CAM_ERR(CAM_ISP, "TPG:%d Failed to init_soc", tpg_idx); goto err; @@ -291,6 +361,8 @@ int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf, cam_top_tpg_ver1_init(tpg_hw); else if (hw_version == CAM_TOP_TPG_VERSION_2) cam_top_tpg_ver2_init(tpg_hw); + else if (hw_version == CAM_TOP_TPG_VERSION_3) + cam_top_tpg_ver3_init(tpg_hw); tpg_hw->tpg_res.res_type = CAM_ISP_RESOURCE_TPG; tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h index 3dce37d94f9d..eb6e03a36cce 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h @@ -12,6 +12,8 @@ #define CAM_TOP_TPG_VERSION_1 0x10000001 #define CAM_TOP_TPG_VERSION_2 0x10000002 +#define CAM_TOP_TPG_VERSION_3 0x20000000 + enum cam_top_tpg_encode_format { CAM_TOP_TPG_ENCODE_FORMAT_RAW6, @@ -85,12 +87,13 @@ struct cam_top_tpg_cfg { uint32_t pix_pattern; uint32_t phy_sel; uint32_t num_active_lanes; - uint32_t vc_num; + uint32_t vc_num[4]; uint32_t v_blank_count; uint32_t h_blank_count; uint32_t vbi_cnt; uint32_t num_active_dts; uint32_t num_frames; + uint32_t vc_dt_pattern_id; struct cam_top_tpg_dt_cfg dt_cfg[4]; }; @@ -117,6 +120,8 @@ struct cam_top_tpg_hw { struct completion tpg_complete; }; +int cam_top_tpg_get_format(uint32_t in_format, uint32_t *tpg_encode_format); + int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf, uint32_t tpg_idx); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c index 206e91628fc4..255145879397 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c @@ -8,7 +8,7 @@ #include "cam_debug_util.h" int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info, - void *irq_data) + irq_handler_t tpg_irq_handler, void *irq_data) { int rc = 0; struct cam_cpas_register_params cpas_register_param; @@ -26,7 +26,7 @@ int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info, return rc; /* Need to see if we want post process the clock list */ - rc = cam_soc_util_request_platform_resource(soc_info, NULL, + rc = cam_soc_util_request_platform_resource(soc_info, tpg_irq_handler, irq_data); if (rc < 0) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h index 9788409c99ad..faefb81eb0f9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h @@ -37,11 +37,12 @@ struct cam_top_tpg_device_soc_info { * @brief: csid initialization function for the soc info * * @soc_info: soc info structure pointer + * @tpg_irq_handler: irq handler function to be registered * @irq_data: irq data for the callback function * */ int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info, - void *irq_data); + irq_handler_t tpg_irq_handler, void *irq_data); /** * cam_top_tpg_deinit_soc_resources() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c index 24c930f12556..8a657e753509 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c @@ -21,39 +21,6 @@ static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = { 2 }; -static int cam_top_tpg_ver1_get_format( - uint32_t in_format, - uint32_t *tpg_encode_format) -{ - int rc = 0; - - switch (in_format) { - case CAM_FORMAT_MIPI_RAW_6: - *tpg_encode_format = 0; - break; - case CAM_FORMAT_MIPI_RAW_8: - *tpg_encode_format = 1; - break; - case CAM_FORMAT_MIPI_RAW_10: - *tpg_encode_format = 2; - break; - case CAM_FORMAT_MIPI_RAW_12: - *tpg_encode_format = 3; - break; - case CAM_FORMAT_MIPI_RAW_14: - *tpg_encode_format = 4; - break; - case CAM_FORMAT_MIPI_RAW_16: - *tpg_encode_format = 4; - break; - default: - CAM_ERR(CAM_ISP, "Unsupported input encode format %d", - in_format); - rc = -EINVAL; - } - return rc; -} - static int cam_top_tpg_ver1_get_hw_caps( void *hw_priv, void *get_hw_cap_args, @@ -136,7 +103,7 @@ static int cam_top_tpg_ver1_reserve( mutex_unlock(&tpg_hw->hw_info->hw_mutex); return -EINVAL; } - rc = cam_top_tpg_ver1_get_format(reserv->in_port[0]->format, + rc = cam_top_tpg_get_format(reserv->in_port[0]->format, &encode_format); if (rc) goto error; @@ -144,7 +111,7 @@ static int cam_top_tpg_ver1_reserve( CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx); tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; - tpg_data->vc_num = reserv->in_port[0]->vc; + tpg_data->vc_num[0] = reserv->in_port[0]->vc; tpg_data->phy_sel = reserv->in_port[0]->lane_type; tpg_data->num_active_lanes = reserv->in_port[0]->lane_num; tpg_data->h_blank_count = reserv->in_port[0]->sensor_hbi; @@ -165,7 +132,7 @@ static int cam_top_tpg_ver1_reserve( CAM_DBG(CAM_ISP, "TPG:%u vc_num:%d dt:%d phy:%d lines:%d pattern:%d format:%d", tpg_hw->hw_intf->hw_idx, - tpg_data->vc_num, tpg_data->dt_cfg[0].data_type, + tpg_data->vc_num[0], tpg_data->dt_cfg[0].data_type, tpg_data->phy_sel, tpg_data->num_active_lanes, tpg_data->pix_pattern, tpg_data->dt_cfg[0].encode_format); @@ -181,7 +148,7 @@ static int cam_top_tpg_ver1_reserve( goto end; for (i = 1; i < reserv->num_inport; i++) { - if ((tpg_data->vc_num != reserv->in_port[i]->vc) || + if ((tpg_data->vc_num[0] != reserv->in_port[i]->vc) || (tpg_data->phy_sel != reserv->in_port[i]->lane_type) || (tpg_data->num_active_lanes != reserv->in_port[i]->lane_num) || @@ -193,7 +160,7 @@ static int cam_top_tpg_ver1_reserve( rc = -EINVAL; goto error; } - rc = cam_top_tpg_ver1_get_format(reserv->in_port[0]->format, + rc = cam_top_tpg_get_format(reserv->in_port[0]->format, &encode_format); if (rc) return rc; @@ -278,7 +245,7 @@ static int cam_top_tpg_ver1_start( } val = (tpg_num_dt_map[tpg_data->num_active_dts-1] << - tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num; + tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num[0]; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0); /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c new file mode 100644 index 000000000000..ee862e3db199 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_top_tpg_core.h" +#include "cam_soc_util.h" +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_top_tpg_ver3.h" + +static int cam_top_tpg_ver3_get_hw_caps( + void *hw_priv, + void *get_hw_cap_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw_caps *hw_caps; + struct cam_top_tpg_hw *tpg_hw; + const struct cam_top_tpg_ver3_reg_offset *tpg_reg; + struct cam_hw_info *tpg_hw_info; + + if (!hw_priv || !get_hw_cap_args) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + hw_caps = (struct cam_top_tpg_hw_caps *) get_hw_cap_args; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + + hw_caps->major_version = tpg_reg->major_version; + hw_caps->minor_version = tpg_reg->minor_version; + hw_caps->version_incr = tpg_reg->version_incr; + + CAM_DBG(CAM_ISP, + "TPG:%d major:%d minor:%d ver :%d", + tpg_hw->hw_intf->hw_idx, hw_caps->major_version, + hw_caps->minor_version, hw_caps->version_incr); + + return rc; +} + +static int cam_top_tpg_ver3_reserve( + void *hw_priv, + void *reserve_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_top_tpg_ver3_reserve_args *reserv; + struct cam_top_tpg_cfg *tpg_data; + uint32_t encode_format = 0; + uint32_t i; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_top_tpg_ver3_reserve_args))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + reserv = (struct cam_top_tpg_ver3_reserve_args *)reserve_args; + + if (reserv->num_inport <= 0 || + reserv->num_inport > CAM_TOP_TPG_MAX_SUPPORTED_DT) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG: %u invalid input num port:%d", + tpg_hw->hw_intf->hw_idx, reserv->num_inport); + return -EINVAL; + } + + mutex_lock(&tpg_hw->hw_info->hw_mutex); + if (tpg_hw->tpg_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + rc = -EINVAL; + goto error; + } + + if ((reserv->in_port->lane_num <= 0 || + reserv->in_port->lane_num > 4) || + (reserv->in_port->lane_type >= 2)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d", + tpg_hw->hw_intf->hw_idx, + reserv->in_port->lane_num, + reserv->in_port->lane_type); + rc = -EINVAL; + goto error; + } + + tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; + + for (i = 0; i < reserv->in_port->num_valid_vc_dt; i++) { + if (reserv->in_port->dt[i] > 0x3f || + reserv->in_port->vc[i] > 0x1f) { + CAM_ERR(CAM_ISP, "TPG:%u Invalid vc:%d dt %d", + tpg_hw->hw_intf->hw_idx, + reserv->in_port->vc[i], + reserv->in_port->dt[i]); + rc = -EINVAL; + goto error; + } + tpg_data->vc_num[i] = reserv->in_port->vc[i]; + tpg_data->dt_cfg[i].data_type = reserv->in_port->dt[i]; + } + + rc = cam_top_tpg_get_format(reserv->in_port->format, + &encode_format); + if (rc) + goto error; + + + CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx); + + tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; + tpg_data->phy_sel = reserv->in_port->lane_type; + tpg_data->num_active_lanes = reserv->in_port->lane_num; + tpg_data->h_blank_count = reserv->in_port->hbi_cnt; + tpg_data->v_blank_count = 600; + tpg_data->num_active_dts = reserv->in_port->num_valid_vc_dt; + + for (i = 0; i < reserv->in_port->num_valid_vc_dt; i++) { + tpg_data->dt_cfg[i].encode_format = encode_format; + tpg_data->dt_cfg[i].frame_height = reserv->in_port->height; + + if (reserv->in_port->usage_type) + tpg_data->dt_cfg[i].frame_width = + ((reserv->in_port->right_stop - + reserv->in_port->left_start) + 1); + else + tpg_data->dt_cfg[i].frame_width = + reserv->in_port->left_width; + } + + CAM_DBG(CAM_ISP, + "TPG:%u vc_num:%d dt:%d phy:%d lines:%d pattern:%d format:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->vc_num, tpg_data->dt_cfg[0].data_type, + tpg_data->phy_sel, tpg_data->num_active_lanes, + tpg_data->pix_pattern, + tpg_data->dt_cfg[0].encode_format); + + CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d h blank:%d v blank:%d", + tpg_hw->hw_intf->hw_idx, + tpg_data->dt_cfg[0].frame_height, + tpg_data->dt_cfg[0].frame_width, + tpg_data->h_blank_count, + tpg_data->v_blank_count); + + reserv->node_res = &tpg_hw->tpg_res; + tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED; +error: + mutex_unlock(&tpg_hw->hw_info->hw_mutex); + CAM_DBG(CAM_ISP, "exit rc %u", rc); + + return rc; +} + +static int cam_top_tpg_ver3_start( + void *hw_priv, + void *start_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + struct cam_top_tpg_ver3_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + uint32_t i, val; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *)start_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) { + CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_top_clear); + + for (i = 0; i < tpg_data->num_active_dts; i++) { + val = (((tpg_data->dt_cfg[i].frame_width & 0xFFFF) << 16) | + (tpg_data->dt_cfg[i].frame_height & 0xFFFF)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_dt_0_cfg_0 + 0x60 * i); + + cam_io_w_mb(tpg_data->dt_cfg[i].data_type, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_dt_0_cfg_1 + 0x60 * i); + val = ((tpg_data->dt_cfg[i].encode_format & 0xF) << + tpg_reg->tpg_dt_encode_format_shift) | + tpg_reg->tpg_payload_mode_color; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_dt_0_cfg_2 + 0x60 * i); + + val = (1 << tpg_reg->tpg_split_en_shift); + val |= tpg_data->pix_pattern; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_color_bar_cfg + 0x60 * i); + + /* + * if hblank is notset configureHBlank count 500 and + * V blank count is 600 + */ + + if (tpg_data->h_blank_count) + cam_io_w_mb(tpg_data->h_blank_count, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_hbi_cfg + 0x60 * i); + else + cam_io_w_mb(0x1F4, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_hbi_cfg + 0x60 * i); + + if (tpg_data->v_blank_count) + cam_io_w_mb(tpg_data->h_blank_count, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_vbi_cfg + 0x60 * i); + else + cam_io_w_mb(0x258, + soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_vbi_cfg + 0x60 * i); + + cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_lfsr_seed + 0x60 * i); + + val = (((tpg_data->num_active_dts-1) << + tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num[i]); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_vc0_cfg0 + 0x60 * i); + } + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_mask); + + val = ((tpg_data->num_active_dts - 1) << + (tpg_reg->tpg_num_active_vcs_shift) | + (tpg_data->num_active_lanes - 1) << + tpg_reg->tpg_num_active_lanes_shift) | + (tpg_data->vc_dt_pattern_id) << + (tpg_reg->tpg_vc_dt_pattern_id_shift) | + (tpg_data->phy_sel << tpg_reg->tpg_cphy_dphy_sel_shift_val) | + (1 << tpg_reg->tpg_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); + + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + tpg_reg->tpg_hw_version); + CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x started", + tpg_hw->hw_intf->hw_idx, val); + +end: + return rc; +} + +static int cam_top_tpg_ver3_stop( + void *hw_priv, + void *stop_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *tpg_res; + const struct cam_top_tpg_ver3_reg_offset *tpg_reg; + struct cam_top_tpg_cfg *tpg_data; + + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_reg = tpg_hw->tpg_info->tpg_reg; + tpg_res = (struct cam_isp_resource_node *) stop_args; + tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_state; + soc_info = &tpg_hw->hw_info->soc_info; + + if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) || + (tpg_res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) { + CAM_DBG(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d", + tpg_hw->hw_intf->hw_idx, + tpg_res->res_type, tpg_res->res_state); + rc = -EINVAL; + goto end; + } + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_mask); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_clear); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_top_irq_cmd); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_top_clear); + + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); +end: + return rc; +} + +int cam_top_tpg_ver3_init( + struct cam_top_tpg_hw *tpg_hw) +{ + tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_ver3_get_hw_caps; + tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver3_reserve; + tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver3_start; + tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver3_stop; + + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h new file mode 100644 index 000000000000..b8853d6215a2 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TOP_TPG_VER3_H_ +#define _CAM_TOP_TPG_VER3_H_ + +#include "cam_top_tpg_core.h" + +struct cam_top_tpg_ver3_reg_offset { + uint32_t tpg_hw_version; + uint32_t tpg_hw_status; + uint32_t tpg_ctrl; + uint32_t tpg_vc0_cfg0; + uint32_t tpg_vc0_lfsr_seed; + uint32_t tpg_vc0_hbi_cfg; + uint32_t tpg_vc0_vbi_cfg; + uint32_t tpg_vc0_color_bar_cfg; + uint32_t tpg_vc0_dt_0_cfg_0; + uint32_t tpg_vc0_dt_0_cfg_1; + uint32_t tpg_vc0_dt_0_cfg_2; + uint32_t tpg_vc0_dt_1_cfg_0; + uint32_t tpg_vc0_dt_1_cfg_1; + uint32_t tpg_vc0_dt_1_cfg_2; + uint32_t tpg_vc0_dt_2_cfg_0; + uint32_t tpg_vc0_dt_2_cfg_1; + uint32_t tpg_vc0_dt_2_cfg_2; + uint32_t tpg_vc0_dt_3_cfg_0; + uint32_t tpg_vc0_dt_3_cfg_1; + uint32_t tpg_vc0_dt_3_cfg_2; + + uint32_t tpg_vc1_cfg0; + uint32_t tpg_vc1_lfsr_seed; + uint32_t tpg_vc1_hbi_cfg; + uint32_t tpg_vc1_vbi_cfg; + uint32_t tpg_vc1_color_bar_cfg; + uint32_t tpg_vc1_dt_0_cfg_0; + uint32_t tpg_vc1_dt_0_cfg_1; + uint32_t tpg_vc1_dt_0_cfg_2; + uint32_t tpg_vc1_dt_1_cfg_0; + uint32_t tpg_vc1_dt_1_cfg_1; + uint32_t tpg_vc1_dt_1_cfg_2; + uint32_t tpg_vc1_dt_2_cfg_0; + uint32_t tpg_vc1_dt_2_cfg_1; + uint32_t tpg_vc1_dt_2_cfg_2; + uint32_t tpg_vc1_dt_3_cfg_0; + uint32_t tpg_vc1_dt_3_cfg_1; + uint32_t tpg_vc1_dt_3_cfg_2; + + uint32_t tpg_vc2_cfg0; + uint32_t tpg_vc2_lfsr_seed; + uint32_t tpg_vc2_hbi_cfg; + uint32_t tpg_vc2_vbi_cfg; + uint32_t tpg_vc2_color_bar_cfg; + uint32_t tpg_vc2_dt_0_cfg_0; + uint32_t tpg_vc2_dt_0_cfg_1; + uint32_t tpg_vc2_dt_0_cfg_2; + uint32_t tpg_vc2_dt_1_cfg_0; + uint32_t tpg_vc2_dt_1_cfg_1; + uint32_t tpg_vc2_dt_1_cfg_2; + uint32_t tpg_vc2_dt_2_cfg_0; + uint32_t tpg_vc2_dt_2_cfg_1; + uint32_t tpg_vc2_dt_2_cfg_2; + uint32_t tpg_vc2_dt_3_cfg_0; + uint32_t tpg_vc2_dt_3_cfg_1; + uint32_t tpg_vc2_dt_3_cfg_2; + + uint32_t tpg_vc3_cfg0; + uint32_t tpg_vc3_lfsr_seed; + uint32_t tpg_vc3_hbi_cfg; + uint32_t tpg_vc3_vbi_cfg; + uint32_t tpg_vc3_color_bar_cfg; + uint32_t tpg_vc3_dt_0_cfg_0; + uint32_t tpg_vc3_dt_0_cfg_1; + uint32_t tpg_vc3_dt_0_cfg_2; + uint32_t tpg_vc3_dt_1_cfg_0; + uint32_t tpg_vc3_dt_1_cfg_1; + uint32_t tpg_vc3_dt_1_cfg_2; + uint32_t tpg_vc3_dt_2_cfg_0; + uint32_t tpg_vc3_dt_2_cfg_1; + uint32_t tpg_vc3_dt_2_cfg_2; + uint32_t tpg_vc3_dt_3_cfg_0; + uint32_t tpg_vc3_dt_3_cfg_1; + uint32_t tpg_vc3_dt_3_cfg_2; + uint32_t tpg_throttle; + uint32_t tpg_top_irq_status; + uint32_t tpg_top_irq_mask; + uint32_t tpg_top_irq_clear; + uint32_t tpg_top_irq_set; + uint32_t tpg_top_irq_cmd; + uint32_t tpg_top_clear; + uint32_t tpg_test_bus_crtl; + uint32_t tpg_spare; + + /* configurations */ + uint32_t major_version; + uint32_t minor_version; + uint32_t version_incr; + uint32_t tpg_en_shift_val; + uint32_t tpg_cphy_dphy_sel_shift_val; + uint32_t tpg_num_active_lanes_shift; + uint32_t tpg_fe_pkt_en_shift; + uint32_t tpg_fs_pkt_en_shift; + uint32_t tpg_line_interleaving_mode_shift; + uint32_t tpg_num_dts_shift_val; + uint32_t tpg_v_blank_cnt_shift; + uint32_t tpg_dt_encode_format_shift; + uint32_t tpg_payload_mode_color; + uint32_t tpg_split_en_shift; + uint32_t top_mux_reg_offset; + uint32_t tpg_vc_dt_pattern_id_shift; + uint32_t tpg_num_active_vcs_shift; +}; + +int cam_top_tpg_ver3_init(struct cam_top_tpg_hw *tpg_hw); + +#endif /* _CAM_TOP_TPG_VER3_H_ */ diff --git a/include/uapi/camera/media/cam_isp_ife.h b/include/uapi/camera/media/cam_isp_ife.h index f18a474bc7b9..28a21140d87b 100644 --- a/include/uapi/camera/media/cam_isp_ife.h +++ b/include/uapi/camera/media/cam_isp_ife.h @@ -51,6 +51,7 @@ #define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 7) #define CAM_ISP_IFE_IN_RES_CPHY_TPG_0 (CAM_ISP_IFE_IN_RES_BASE + 8) #define CAM_ISP_IFE_IN_RES_CPHY_TPG_1 (CAM_ISP_IFE_IN_RES_BASE + 9) -#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 10) +#define CAM_ISP_IFE_IN_RES_CPHY_TPG_2 (CAM_ISP_IFE_IN_RES_BASE + 10) +#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 11) #endif /* __UAPI_CAM_ISP_IFE_H__ */ From 6de4fa2ed806e919cd4aea103d1a758dbb3ddf0c Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 8 Jun 2020 14:15:12 -0700 Subject: [PATCH 370/790] msm: camera: ife: Add support to provide IFE count in Query caps IFE Query cap currently gives only IFE Full Information. Update the code to return IFE Full, IFE lite, full IFE-CSID and IFE-CSID lite information in return of the IFE Query cap command. CRs-Fixed: 2647995 Change-Id: I84cf5b766ce191aacad4a1de478c6eebafe917b3 Signed-off-by: Jigar Agrawal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 104 ++++++++++++++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 28 ++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 2 + .../isp_hw/ife_csid_hw/cam_ife_csid_soc.c | 13 ++- .../isp_hw/ife_csid_hw/cam_ife_csid_soc.h | 4 +- .../isp_hw/include/cam_ife_csid_hw_intf.h | 3 +- .../isp_hw/include/cam_vfe_hw_intf.h | 17 +-- .../vfe_hw/vfe_top/cam_vfe_top_common.h | 1 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 39 ++++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 38 ++++++- include/uapi/camera/media/cam_isp.h | 10 +- 11 files changed, 225 insertions(+), 34 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 17aa1ff4f217..dfe8a9ceafdd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -182,6 +182,11 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv, struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_query_cap_cmd *query = hw_caps_args; struct cam_isp_query_cap_cmd query_isp; + struct cam_isp_dev_cap_info *ife_full_hw_info = NULL; + struct cam_isp_dev_cap_info *ife_lite_hw_info = NULL; + struct cam_isp_dev_cap_info *csid_full_hw_info = NULL; + struct cam_isp_dev_cap_info *csid_lite_hw_info = NULL; + struct cam_ife_csid_hw_caps *ife_csid_caps = {0}; CAM_DBG(CAM_ISP, "enter"); @@ -196,13 +201,98 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv, query_isp.device_iommu.secure = hw_mgr->mgr_common.img_iommu_hdl_secure; query_isp.cdm_iommu.non_secure = hw_mgr->mgr_common.cmd_iommu_hdl; query_isp.cdm_iommu.secure = hw_mgr->mgr_common.cmd_iommu_hdl_secure; - query_isp.num_dev = 2; - for (i = 0; i < query_isp.num_dev; i++) { - query_isp.dev_caps[i].hw_type = CAM_ISP_HW_IFE; - query_isp.dev_caps[i].hw_version.major = 1; - query_isp.dev_caps[i].hw_version.minor = 7; - query_isp.dev_caps[i].hw_version.incr = 0; - query_isp.dev_caps[i].hw_version.reserved = 0; + query_isp.num_dev = 0; + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (!hw_mgr->ife_devices[i]) + continue; + + if (hw_mgr->ife_dev_caps[i].is_lite) { + if (ife_lite_hw_info == NULL) { + ife_lite_hw_info = + &query_isp.dev_caps[query_isp.num_dev]; + query_isp.num_dev++; + + ife_lite_hw_info->hw_type = CAM_ISP_HW_IFE_LITE; + ife_lite_hw_info->hw_version.major = + hw_mgr->ife_dev_caps[i].major; + ife_lite_hw_info->hw_version.minor = + hw_mgr->ife_dev_caps[i].minor; + ife_lite_hw_info->hw_version.incr = + hw_mgr->ife_dev_caps[i].incr; + ife_lite_hw_info->hw_version.reserved = 0; + ife_lite_hw_info->num_hw = 0; + } + + ife_lite_hw_info->num_hw++; + + } else { + if (ife_full_hw_info == NULL) { + ife_full_hw_info = + &query_isp.dev_caps[query_isp.num_dev]; + query_isp.num_dev++; + + ife_full_hw_info->hw_type = CAM_ISP_HW_IFE; + ife_full_hw_info->hw_version.major = + hw_mgr->ife_dev_caps[i].major; + ife_full_hw_info->hw_version.minor = + hw_mgr->ife_dev_caps[i].minor; + ife_full_hw_info->hw_version.incr = + hw_mgr->ife_dev_caps[i].incr; + ife_full_hw_info->hw_version.reserved = 0; + ife_full_hw_info->num_hw = 0; + } + + ife_full_hw_info->num_hw++; + } + } + + for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { + if (!hw_mgr->csid_devices[i]) + continue; + + ife_csid_caps = (struct cam_ife_csid_hw_caps *) + &hw_mgr->ife_csid_dev_caps[i]; + + if (ife_csid_caps->is_lite) { + if (csid_lite_hw_info == NULL) { + csid_lite_hw_info = + &query_isp.dev_caps[query_isp.num_dev]; + query_isp.num_dev++; + + csid_lite_hw_info->hw_type = + CAM_ISP_HW_CSID_LITE; + csid_lite_hw_info->hw_version.major = + ife_csid_caps->major_version; + csid_lite_hw_info->hw_version.minor = + ife_csid_caps->minor_version; + csid_lite_hw_info->hw_version.incr = + ife_csid_caps->version_incr; + csid_lite_hw_info->hw_version.reserved = 0; + csid_lite_hw_info->num_hw = 0; + } + + csid_lite_hw_info->num_hw++; + + } else { + if (csid_full_hw_info == NULL) { + csid_full_hw_info = + &query_isp.dev_caps[query_isp.num_dev]; + query_isp.num_dev++; + + csid_full_hw_info->hw_type = CAM_ISP_HW_CSID; + csid_full_hw_info->hw_version.major = + ife_csid_caps->major_version; + csid_full_hw_info->hw_version.minor = + ife_csid_caps->minor_version; + csid_full_hw_info->hw_version.incr = + ife_csid_caps->version_incr; + csid_full_hw_info->hw_version.reserved = 0; + csid_full_hw_info->num_hw = 0; + } + + csid_full_hw_info->num_hw++; + } } if (copy_to_user(u64_to_user_ptr(query->caps_handle), diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 66803e43100d..54b441424ca1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1223,7 +1223,7 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) int rc = 0; const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; - uint32_t i, val; + uint32_t i; int clk_lvl; unsigned long flags; @@ -1305,10 +1305,12 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); - val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_hw->csid_info->hw_reg_version = + cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_hw_version_addr); CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x", - csid_hw->hw_intf->hw_idx, val); + csid_hw->hw_intf->hw_idx, + csid_hw->csid_info->hw_reg_version); spin_lock_irqsave(&csid_hw->lock_state, flags); csid_hw->device_enabled = 1; @@ -3102,6 +3104,7 @@ int cam_ife_csid_get_hw_caps(void *hw_priv, struct cam_ife_csid_hw *csid_hw; struct cam_hw_info *csid_hw_info; const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_csid_soc_private *soc_priv = NULL; if (!hw_priv || !get_hw_cap_args) { CAM_ERR(CAM_ISP, "CSID: Invalid args"); @@ -3116,9 +3119,22 @@ int cam_ife_csid_get_hw_caps(void *hw_priv, hw_caps->num_rdis = csid_reg->cmn_reg->num_rdis; hw_caps->num_pix = csid_reg->cmn_reg->num_pix; hw_caps->num_ppp = csid_reg->cmn_reg->num_ppp; - hw_caps->major_version = csid_reg->cmn_reg->major_version; - hw_caps->minor_version = csid_reg->cmn_reg->minor_version; - hw_caps->version_incr = csid_reg->cmn_reg->version_incr; + + /* NOTE: HW version is not correct since we dont enable + * the soc resources in the probe for CSID, instead we + * when the camera actually runs + */ + hw_caps->version_incr = + csid_hw->csid_info->hw_reg_version & 0x00ffff; + hw_caps->minor_version = + (csid_hw->csid_info->hw_reg_version >> 16) & 0x0fff; + hw_caps->major_version = + (csid_hw->csid_info->hw_reg_version >> 28) & 0x000f; + + soc_priv = (struct cam_csid_soc_private *) + (csid_hw_info->soc_info.soc_private); + + hw_caps->is_lite = soc_priv->is_ife_csid_lite; CAM_DBG(CAM_ISP, "CSID:%d No rdis:%d, no pix:%d, major:%d minor:%d ver :%d", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index f75b97224e60..819e91bc0b2a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -402,12 +402,14 @@ struct cam_ife_csid_reg_offset { * * @csid_reg: csid register offsets * @hw_dts_version: HW DTS version + * @hw_reg_version: HW Version read from register * @csid_max_clk: maximim csid clock * */ struct cam_ife_csid_hw_info { const struct cam_ife_csid_reg_offset *csid_reg; uint32_t hw_dts_version; + uint32_t hw_reg_version; uint32_t csid_max_clk; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c index 7abcc64068ee..49c81fd30317 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include #include "cam_ife_csid_soc.h" @@ -10,16 +10,23 @@ static int cam_ife_csid_get_dt_properties(struct cam_hw_soc_info *soc_info) { struct device_node *of_node = NULL; - struct csid_device_soc_info *csid_soc_info = NULL; + struct cam_csid_soc_private *soc_private = NULL; int rc = 0; of_node = soc_info->pdev->dev.of_node; - csid_soc_info = (struct csid_device_soc_info *)soc_info->soc_private; rc = cam_soc_util_get_dt_properties(soc_info); if (rc) return rc; + soc_private = (struct cam_csid_soc_private *)soc_info->soc_private; + + soc_private->is_ife_csid_lite = false; + if (strnstr(soc_info->compatible, "lite", + strlen(soc_info->compatible)) != NULL) { + soc_private->is_ife_csid_lite = true; + } + return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h index 4f76d084fba3..3391bcaf463f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_SOC_H_ @@ -16,9 +16,11 @@ * @cpas_handle: Handle returned on registering with CPAS driver. * This handle is used for all further interface * with CPAS. + * @is_ife_csid_lite: Flag to indicate Whether a full csid or a Lite csid */ struct cam_csid_soc_private { uint32_t cpas_handle; + bool is_ife_csid_lite; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 78c457b6a7cb..9d15a8bbedf2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -49,7 +49,7 @@ enum cam_ife_cid_res_id { * @major_version : major version * @minor_version: minor version * @version_incr: version increment - * + * @is_lite: is the ife_csid lite */ struct cam_ife_csid_hw_caps { uint32_t num_rdis; @@ -58,6 +58,7 @@ struct cam_ife_csid_hw_caps { uint32_t major_version; uint32_t minor_version; uint32_t version_incr; + bool is_lite; }; struct cam_isp_out_port_generic_info { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 531e695583a0..41c4564eb390 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -90,16 +90,17 @@ enum cam_vfe_reset_type { /* * struct cam_vfe_hw_get_hw_cap: * - * @max_width: Max width supported by HW - * @max_height: Max height supported by HW - * @max_pixel_num: Max Pixel channels available - * @max_rdi_num: Max Raw channels available + * @Brief: Argument type for fetching the hw information for Query caps + * @major: Major revision number + * @minor: Minor revision number + * @incr: Increment revision number + * @is_lite: Flag to indicate Whether a full vfe or a Lite vfe */ struct cam_vfe_hw_get_hw_cap { - uint32_t max_width; - uint32_t max_height; - uint32_t max_pixel_num; - uint32_t max_rdi_num; + uint32_t major; + uint32_t minor; + uint32_t incr; + bool is_lite; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h index 55607b6d886f..9078ec9995c6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h @@ -27,6 +27,7 @@ struct cam_vfe_top_priv_common { CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; uint32_t last_counter; uint64_t total_bw_applied; + uint32_t hw_version; enum cam_vfe_bw_control_action axi_vote_control[CAM_VFE_TOP_MUX_MAX]; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 044a02468072..6e1ae838bca3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -282,9 +282,39 @@ static int cam_vfe_top_get_data( } int cam_vfe_top_get_hw_caps(void *device_priv, - void *get_hw_cap_args, uint32_t arg_size) + void *args, uint32_t arg_size) { - return -EPERM; + struct cam_vfe_hw_get_hw_cap *vfe_cap_info = NULL; + struct cam_vfe_top_ver2_priv *vfe_top_prv = NULL; + struct cam_vfe_soc_private *vfe_soc_private = NULL; + + if (!device_priv || !args) { + CAM_ERR(CAM_ISP, + "Invalid arguments device_priv:%p, args:%p", + device_priv, args); + return -EINVAL; + } + + vfe_cap_info = (struct cam_vfe_hw_get_hw_cap *)args; + vfe_top_prv = (struct cam_vfe_top_ver2_priv *)device_priv; + + if (!vfe_top_prv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "soc_info is null"); + return -EFAULT; + } + + vfe_soc_private = (struct cam_vfe_soc_private *) + vfe_top_prv->common_data.soc_info->soc_private; + + vfe_cap_info->is_lite = (vfe_soc_private->is_ife_lite) ? true : false; + vfe_cap_info->incr = + (vfe_top_prv->top_common.hw_version) & 0x00ffff; + vfe_cap_info->minor = + ((vfe_top_prv->top_common.hw_version) >> 16) & 0x0fff; + vfe_cap_info->major = + ((vfe_top_prv->top_common.hw_version) >> 28) & 0x000f; + + return 0; } static int cam_vfe_hw_dump( @@ -425,9 +455,14 @@ int cam_vfe_top_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { struct cam_vfe_top_ver2_priv *top_priv = device_priv; + struct cam_vfe_top_ver2_common_data common_data = top_priv->common_data; top_priv->hw_clk_rate = 0; + top_priv->top_common.hw_version = + cam_io_r_mb(common_data.soc_info->reg_map[0].mem_base + + common_data.common_reg->hw_version); + return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 087a6bbf2296..6a66955ed280 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -323,9 +323,39 @@ static int cam_vfe_top_ver3_get_data( } int cam_vfe_top_ver3_get_hw_caps(void *device_priv, - void *get_hw_cap_args, uint32_t arg_size) + void *args, uint32_t arg_size) { - return -EPERM; + struct cam_vfe_hw_get_hw_cap *vfe_cap_info = NULL; + struct cam_vfe_top_ver3_priv *vfe_top_prv = NULL; + struct cam_vfe_soc_private *vfe_soc_private = NULL; + + if (!device_priv || !args) { + CAM_ERR(CAM_ISP, + "Invalid arguments device_priv:%p, args:%p", + device_priv, args); + return -EINVAL; + } + + vfe_cap_info = (struct cam_vfe_hw_get_hw_cap *)args; + vfe_top_prv = (struct cam_vfe_top_ver3_priv *)device_priv; + + if (!vfe_top_prv->common_data.soc_info) { + CAM_ERR(CAM_ISP, "soc_info is null"); + return -EFAULT; + } + + vfe_soc_private = (struct cam_vfe_soc_private *) + vfe_top_prv->common_data.soc_info->soc_private; + + vfe_cap_info->is_lite = (vfe_soc_private->is_ife_lite) ? true : false; + vfe_cap_info->incr = + (vfe_top_prv->top_common.hw_version) & 0x00ffff; + vfe_cap_info->minor = + ((vfe_top_prv->top_common.hw_version) >> 16) & 0x0fff; + vfe_cap_info->major = + ((vfe_top_prv->top_common.hw_version) >> 28) & 0x000f; + + return 0; } int cam_vfe_top_ver3_init_hw(void *device_priv, @@ -354,6 +384,10 @@ int cam_vfe_top_ver3_init_hw(void *device_priv, cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, common_data.common_reg->noc_cgc_ovd, 0x0); + top_priv->top_common.hw_version = + cam_io_r_mb(common_data.soc_info->reg_map[0].mem_base + + common_data.common_reg->hw_version); + return 0; } diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index c3126dac8eee..82e5ebe81460 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -20,7 +20,9 @@ #define CAM_ISP_HW_VFE 2 #define CAM_ISP_HW_IFE 3 #define CAM_ISP_HW_ISPIF 4 -#define CAM_ISP_HW_MAX 5 +#define CAM_ISP_HW_IFE_LITE 5 +#define CAM_ISP_HW_CSID_LITE 6 +#define CAM_ISP_HW_MAX 7 /* Color Pattern */ #define CAM_ISP_PATTERN_BAYER_RGRGRG 0 @@ -140,13 +142,13 @@ * struct cam_isp_dev_cap_info - A cap info for particular hw type * * @hw_type: Hardware type for the cap info - * @reserved: reserved field for alignment + * @num_hw: Number of HW of type @hw_type * @hw_version: Hardware version * */ struct cam_isp_dev_cap_info { - __u32 hw_type; - __u32 reserved; + __u32 hw_type; + __u32 num_hw; struct cam_hw_version hw_version; }; From 56199228546a8041d893671225e31ec10627bc9d Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 2 Jan 2020 10:24:53 +0530 Subject: [PATCH 371/790] msm: camera: isp: Enable format measurement in CSID Enabling format measure helps to find mismatch between the expected sensor width and height with actual sensor width and height. In case of metadata, width is more than 16 bit, hence skip format measure check for it. In case of mismatch CSID will give CSID_PATH_ERROR_PIX_COUNT and CSID_PATH_ERROR_LINE_COUNT. CRs-Fixed: 2634468 Change-Id: Ic57a18ee5217982d36116060371bdc99405ea759 Signed-off-by: Ayush Kumar Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 92 +++++++- .../isp_hw/ife_csid_hw/cam_ife_csid170.h | 6 +- .../isp_hw/ife_csid_hw/cam_ife_csid170_200.h | 4 + .../isp_hw/ife_csid_hw/cam_ife_csid175.h | 6 +- .../isp_hw/ife_csid_hw/cam_ife_csid175_200.h | 6 +- .../isp_hw/ife_csid_hw/cam_ife_csid480.h | 6 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 218 +++++++++++++++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 9 + .../isp_hw/include/cam_ife_csid_hw_intf.h | 14 ++ include/uapi/camera/media/cam_isp.h | 58 ++++- 10 files changed, 396 insertions(+), 23 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index bfdc76f930d8..0abb6f8653f1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -36,7 +36,7 @@ (CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1) #define CAM_ISP_GENERIC_BLOB_TYPE_MAX \ - (CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 + 1) + (CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG + 1) static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = { CAM_ISP_HW_CMD_GET_HFR_UPDATE, @@ -5440,6 +5440,76 @@ static int cam_isp_blob_clock_update( return rc; } +static int cam_isp_blob_sensor_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_sensor_config *dim_config, + struct cam_isp_hw_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_sensor_dimension_update_args update_args; + int rc = -EINVAL, found = 0; + uint32_t i, j; + struct cam_isp_sensor_dimension *path_config; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + found = 1; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + path_config = &(dim_config->ipp_path); + update_args.ipp_path.width = + path_config->width; + update_args.ipp_path.height = + path_config->height; + update_args.ipp_path.measure_enabled = + path_config->measure_enabled; + path_config = &(dim_config->ppp_path); + update_args.ppp_path.width = + path_config->width; + update_args.ppp_path.height = + path_config->height; + update_args.ppp_path.measure_enabled = + path_config->measure_enabled; + for (j = 0; j < CAM_IFE_RDI_NUM_MAX; j++) { + path_config = + &(dim_config->rdi_path[j]); + update_args.rdi_path[j].width = + path_config->width; + update_args.rdi_path[j].height = + path_config->height; + update_args.rdi_path[j].measure_enabled = + path_config->measure_enabled; + } + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, + &update_args, + sizeof( + struct + cam_ife_sensor_dimension_update_args) + ); + if (rc) { + CAM_ERR(CAM_ISP, + "Dimension Update failed"); + break; + } + } else + CAM_ERR(CAM_ISP, "hw_intf is NULL"); + } + if (found) + break; + } + + return rc; +} + static int cam_isp_blob_vfe_out_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, @@ -6064,6 +6134,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "CSID Config failed rc: %d", rc); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG: { + struct cam_isp_sensor_config *csid_dim_config; + + if (blob_size < sizeof(struct cam_isp_sensor_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %zu expected %zu", + blob_size, + sizeof(struct cam_isp_sensor_config)); + return -EINVAL; + } + + csid_dim_config = + (struct cam_isp_sensor_config *)blob_data; + + rc = cam_isp_blob_sensor_config(blob_type, blob_info, + csid_dim_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, + "Sensor Dimension Update Failed rc: %d", rc); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h index 714fa8ef2b31..bc564b2e1f77 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_170_H_ @@ -286,6 +286,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0x0, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_170_reg_offset = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h index 47cb02492412..f7608a73fad6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170_200.h @@ -349,6 +349,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_170_200_reg_offset = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h index 70f96ea416d8..734218bf5144 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_175_H_ @@ -327,6 +327,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_175_reg_offset = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h index 612379ec4bdd..1794a860b84e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_175_200_H_ @@ -345,6 +345,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_175_200_reg_offset = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h index 66c1b32d51b0..316c3e2ab629 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_480_H_ @@ -365,6 +365,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_480_reg_offset = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 66803e43100d..ec7b77238ce4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -82,7 +82,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported( static int cam_ife_csid_get_format_rdi( uint32_t in_format, uint32_t out_format, uint32_t *decode_fmt, - uint32_t *plain_fmt, uint32_t *packing_fmt, bool rpp) + uint32_t *plain_fmt, uint32_t *packing_fmt, bool rpp, uint32_t *in_bpp) { int rc = 0; @@ -104,6 +104,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 6; break; case CAM_FORMAT_MIPI_RAW_8: switch (out_format) { @@ -123,6 +124,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 8; break; case CAM_FORMAT_MIPI_RAW_10: switch (out_format) { @@ -142,6 +144,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 10; break; case CAM_FORMAT_MIPI_RAW_12: switch (out_format) { @@ -160,6 +163,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 12; break; case CAM_FORMAT_MIPI_RAW_14: switch (out_format) { @@ -178,6 +182,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 14; break; case CAM_FORMAT_MIPI_RAW_16: switch (out_format) { @@ -196,6 +201,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 16; break; case CAM_FORMAT_MIPI_RAW_20: switch (out_format) { @@ -214,6 +220,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 20; break; case CAM_FORMAT_DPCM_10_6_10: *decode_fmt = 0x7; @@ -1327,6 +1334,7 @@ err: static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) { int rc = -EINVAL; + uint32_t i; struct cam_hw_soc_info *soc_info; const struct cam_ife_csid_reg_offset *csid_reg; unsigned long flags; @@ -1367,6 +1375,12 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) spin_lock_irqsave(&csid_hw->lock_state, flags); csid_hw->device_enabled = 0; spin_unlock_irqrestore(&csid_hw->lock_state, flags); + + csid_hw->ipp_path_config.measure_enabled = 0; + csid_hw->ppp_path_config.measure_enabled = 0; + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) + csid_hw->rdi_path_config[i].measure_enabled = 0; + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; @@ -1720,6 +1734,7 @@ static int cam_ife_csid_init_config_pxl_path( bool is_ipp; uint32_t decode_format = 0, plain_format = 0, val = 0; uint32_t camera_hw_version; + struct cam_isp_sensor_dimension *path_config; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -1728,9 +1743,11 @@ static int cam_ife_csid_init_config_pxl_path( if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { is_ipp = true; pxl_reg = csid_reg->ipp_reg; + path_config = &(csid_hw->ipp_path_config); } else { is_ipp = false; pxl_reg = csid_reg->ppp_reg; + path_config = &(csid_hw->ppp_path_config); } if (!pxl_reg) { @@ -1846,6 +1863,25 @@ static int cam_ife_csid_init_config_pxl_path( pxl_reg->csid_pxl_irq_subsample_period_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_subsample_pattern_addr); + + /* configure pixel format measure */ + if (path_config->measure_enabled) { + val = (((path_config->height & + csid_reg->cmn_reg->format_measure_height_mask_val) << + csid_reg->cmn_reg->format_measure_height_shift_val) | + (path_config->width & + csid_reg->cmn_reg->format_measure_width_mask_val)); + CAM_DBG(CAM_ISP, "CSID:%d format measure cfg1 value : 0x%x", + csid_hw->hw_intf->hw_idx, val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg1_addr); + + /* enable pixel and line counter */ + cam_io_w_mb(3, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + } + /* set pxl drop pattern to 0 and period to 1 */ cam_io_w_mb(0, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_pix_drop_pattern_addr); @@ -1995,6 +2031,7 @@ static int cam_ife_csid_enable_pxl_path( const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; bool is_ipp; uint32_t val = 0; + struct cam_isp_sensor_dimension *path_config; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2003,9 +2040,11 @@ static int cam_ife_csid_enable_pxl_path( if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { is_ipp = true; pxl_reg = csid_reg->ipp_reg; + path_config = &(csid_hw->ipp_path_config); } else { is_ipp = false; pxl_reg = csid_reg->ppp_reg; + path_config = &(csid_hw->ppp_path_config); } if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { @@ -2074,6 +2113,10 @@ static int cam_ife_csid_enable_pxl_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; + if (path_config->measure_enabled) + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_mask_addr); @@ -2187,7 +2230,8 @@ static int cam_ife_csid_init_config_rdi_path( const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t path_format = 0, plain_fmt = 0, val = 0, id; - uint32_t format_measure_addr, camera_hw_version, packing_fmt = 0; + uint32_t format_measure_addr, camera_hw_version; + uint32_t packing_fmt = 0, in_bpp = 0; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2202,7 +2246,7 @@ static int cam_ife_csid_init_config_rdi_path( rc = cam_ife_csid_get_format_rdi(path_data->in_format, path_data->out_format, &path_format, &plain_fmt, &packing_fmt, - path_data->crop_enable || path_data->drop_enable); + path_data->crop_enable || path_data->drop_enable, &in_bpp); if (rc) return rc; @@ -2284,6 +2328,35 @@ static int cam_ife_csid_init_config_rdi_path( csid_reg->rdi_reg[id]->csid_rdi_err_recovery_cfg0_addr); } + /* configure pixel format measure */ + if (csid_hw->rdi_path_config[id].measure_enabled) { + val = ((csid_hw->rdi_path_config[id].height & + csid_reg->cmn_reg->format_measure_height_mask_val) << + csid_reg->cmn_reg->format_measure_height_shift_val); + + if (path_format == 0xF) + val |= (__KERNEL_DIV_ROUND_UP( + (csid_hw->rdi_path_config[id].width * + in_bpp), 8) & + csid_reg->cmn_reg->format_measure_width_mask_val); + else + val |= (csid_hw->rdi_path_config[id].width & + csid_reg->cmn_reg->format_measure_width_mask_val); + + CAM_DBG(CAM_ISP, "CSID:%d format measure cfg1 value : 0x%x", + csid_hw->hw_intf->hw_idx, val); + CAM_DBG(CAM_ISP, "format measure width : 0x%x height : 0x%x", + csid_hw->rdi_path_config[id].width, + csid_hw->rdi_path_config[id].height); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg1_addr); + + /* enable pixel and line counter */ + cam_io_w_mb(3, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr); + } + /* set frame drop pattern to 0 and period to 1 */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_frm_drop_period_addr); @@ -2381,7 +2454,7 @@ static int cam_ife_csid_init_config_udi_path( const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t path_format = 0, plain_fmt = 0, val = 0, val1, id; - uint32_t format_measure_addr, packing_fmt = 0; + uint32_t format_measure_addr, packing_fmt = 0, in_bpp = 0; path_data = (struct cam_ife_csid_path_cfg *)res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2396,7 +2469,7 @@ static int cam_ife_csid_init_config_udi_path( rc = cam_ife_csid_get_format_rdi(path_data->in_format, path_data->out_format, &path_format, &plain_fmt, &packing_fmt, - path_data->crop_enable || path_data->drop_enable); + path_data->crop_enable || path_data->drop_enable, &in_bpp); if (rc) { CAM_ERR(CAM_ISP, "Failed to get format in_format: %u out_format: %u rc: %d", @@ -2660,9 +2733,14 @@ static int cam_ife_csid_enable_rdi_path( 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) val |= CSID_PATH_INFO_INPUT_EOF; + if (csid_hw->rdi_path_config[id].measure_enabled) + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); @@ -3272,6 +3350,13 @@ int cam_ife_csid_release(void *hw_priv, break; case CAM_ISP_RESOURCE_PIX_PATH: res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) + csid_hw->ipp_path_config.measure_enabled = 0; + else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + csid_hw->ppp_path_config.measure_enabled = 0; + else + csid_hw->rdi_path_config[res->res_id].measure_enabled + = 0; break; default: CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", @@ -3819,6 +3904,58 @@ static int cam_ife_csid_set_csid_clock( return 0; } +static int cam_ife_csid_set_sensor_dimension( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_sensor_dimension_update_args *dimension_update = NULL; + uint32_t i; + + if (!csid_hw) + return -EINVAL; + + dimension_update = + (struct cam_ife_sensor_dimension_update_args *)cmd_args; + csid_hw->ipp_path_config.measure_enabled = + dimension_update->ipp_path.measure_enabled; + if (dimension_update->ipp_path.measure_enabled) { + csid_hw->ipp_path_config.width = + dimension_update->ipp_path.width; + csid_hw->ipp_path_config.height = + dimension_update->ipp_path.height; + CAM_DBG(CAM_ISP, "CSID ipp path width %d height %d", + csid_hw->ipp_path_config.width, + csid_hw->ipp_path_config.height); + } + csid_hw->ppp_path_config.measure_enabled = + dimension_update->ppp_path.measure_enabled; + if (dimension_update->ppp_path.measure_enabled) { + csid_hw->ppp_path_config.width = + dimension_update->ppp_path.width; + csid_hw->ppp_path_config.height = + dimension_update->ppp_path.height; + CAM_DBG(CAM_ISP, "CSID ppp path width %d height %d", + csid_hw->ppp_path_config.width, + csid_hw->ppp_path_config.height); + } + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) { + csid_hw->rdi_path_config[i].measure_enabled + = dimension_update->rdi_path[i].measure_enabled; + if (csid_hw->rdi_path_config[i].measure_enabled) { + csid_hw->rdi_path_config[i].width = + dimension_update->rdi_path[i].width; + csid_hw->rdi_path_config[i].height = + dimension_update->rdi_path[i].height; + if (csid_hw->rdi_path_config[i].height == 1) + csid_hw->rdi_path_config[i].measure_enabled = 0; + CAM_DBG(CAM_ISP, + "CSID rdi path[%d] width %d height %d", + i, csid_hw->rdi_path_config[i].width, + csid_hw->rdi_path_config[i].height); + } + } + return 0; +} + static int cam_ife_csid_set_csid_qcfa( struct cam_ife_csid_hw *csid_hw, void *cmd_args) { @@ -3959,6 +4096,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_DUMP_HW: rc = cam_ife_csid_dump_hw(csid_hw, cmd_args); break; + case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG: + rc = cam_ife_csid_set_sensor_dimension(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -3979,7 +4119,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0; uint32_t irq_status_rdi[CAM_IFE_CSID_RDI_MAX] = {0, 0, 0, 0}; uint32_t irq_status_udi[CAM_IFE_CSID_UDI_MAX] = {0, 0, 0}; - uint32_t val, irq_status_ppp = 0; + uint32_t val, val2, irq_status_ppp = 0; bool fatal_err_detected = false; uint32_t sof_irq_debug_en = 0; unsigned long flags; @@ -4306,6 +4446,25 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_ctrl_addr); } + + if ((irq_status_ipp & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_ipp & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_format_measure0_addr); + + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_ipp:0x%x", + csid_hw->hw_intf->hw_idx, irq_status_ipp); + CAM_ERR(CAM_ISP, + "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", + csid_hw->ipp_path_config.height, + csid_hw->ipp_path_config.width, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } /*read PPP errors */ @@ -4349,6 +4508,25 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_ctrl_addr); } + + if ((irq_status_ppp & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_ppp & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_format_measure0_addr); + + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_ppp:0x%x", + csid_hw->hw_intf->hw_idx, irq_status_ppp); + CAM_ERR(CAM_ISP, + "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", + csid_hw->ppp_path_config.height, + csid_hw->ppp_path_config.width, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { @@ -4389,6 +4567,30 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); } + + if ((irq_status_rdi[i] & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_rdi[i] & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_format_measure0_addr); + val2 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_format_measure_cfg1_addr + ); + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_rdi[%d]:0x%x", + csid_hw->hw_intf->hw_idx, i, irq_status_rdi[i]); + CAM_ERR(CAM_ISP, + "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", + ((val2 >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val2 & + csid_reg->cmn_reg->format_measure_width_mask_val, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { @@ -4602,6 +4804,10 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->csid_debug = 0; ife_csid_hw->error_irq_count = 0; + ife_csid_hw->ipp_path_config.measure_enabled = 0; + ife_csid_hw->ppp_path_config.measure_enabled = 0; + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) + ife_csid_hw->rdi_path_config[i].measure_enabled = 0; return 0; err: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index f75b97224e60..a3f34947a253 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -373,6 +373,10 @@ struct cam_ife_csid_common_reg_offset { uint32_t measure_en_hbi_vbi_cnt_mask; uint32_t format_measure_en_val; uint32_t num_bytes_out_shift_val; + uint32_t format_measure_width_shift_val; + uint32_t format_measure_width_mask_val; + uint32_t format_measure_height_shift_val; + uint32_t format_measure_height_mask_val; }; /** @@ -580,6 +584,11 @@ struct cam_ife_csid_hw { struct completion csid_udin_complete[CAM_IFE_CSID_UDI_MAX]; uint64_t csid_debug; uint64_t clk_rate; + struct cam_isp_sensor_dimension ipp_path_config; + struct cam_isp_sensor_dimension ppp_path_config; + struct cam_isp_sensor_dimension rdi_path_config[CAM_IFE_CSID_RDI_MAX]; + uint32_t hbi; + uint32_t vbi; bool sof_irq_triggered; bool is_resetting; uint32_t irq_debug_cnt; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 78c457b6a7cb..1998f19b7918 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -206,6 +206,7 @@ enum cam_ife_csid_cmd_type { CAM_IFE_CSID_SET_CSID_DEBUG, CAM_IFE_CSID_SOF_IRQ_DEBUG, CAM_IFE_CSID_SET_CONFIG, + CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, CAM_IFE_CSID_CMD_MAX, }; @@ -247,4 +248,17 @@ struct cam_ife_csid_epd_update_args { uint32_t epd_supported; }; +/* + * struct cam_ife_sensor_dim_update_args: + * + * @ppp_path: expected ppp path configuration + * @ipp_path: expected ipp path configuration + * @rdi_path: expected rdi path configuration + */ +struct cam_ife_sensor_dimension_update_args { + struct cam_isp_sensor_dimension ppp_path; + struct cam_isp_sensor_dimension ipp_path; + struct cam_isp_sensor_dimension rdi_path[CAM_IFE_CSID_RDI_MAX]; +}; + #endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index c3126dac8eee..ce9bdde64210 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -92,18 +92,19 @@ #define CAM_ISP_DSP_MODE_ROUND 2 /* ISP Generic Cmd Buffer Blob types */ -#define CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG 0 -#define CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 -#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 -#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2 6 -#define CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG 7 -#define CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG 8 -#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 9 -#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG 10 -#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG 12 +#define CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG 0 +#define CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 +#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 +#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2 6 +#define CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG 7 +#define CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG 8 +#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 9 +#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG 10 +#define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG 11 +#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG 12 #define CAM_ISP_VC_DT_CFG 4 @@ -135,6 +136,8 @@ #define CAM_ISP_ACQ_CUSTOM_PRIMARY 1 #define CAM_ISP_ACQ_CUSTOM_SECONDARY 2 +#define CAM_IFE_CSID_RDI_MAX 4 + /* Query devices */ /** * struct cam_isp_dev_cap_info - A cap info for particular hw type @@ -597,6 +600,37 @@ struct cam_fe_config { __u32 latency_buf_size; } __attribute__((packed)); + +/** + * struct cam_isp_sensor_path_dimension + * + * @width expected width + * @height expected height + * @measure_enabled flag to indicate if pixel measurement is to be enabled + */ +struct cam_isp_sensor_dimension { + __u32 width; + __u32 height; + __u32 measure_enabled; +} __attribute__((packed)); + +/** + * struct cam_isp_sensor_config - Sensor Dimension configuration + * + * @ppp_path: expected ppp path configuration + * @ipp_path: expected ipp path configuration + * @rdi_path: expected rdi path configuration + * @hbi: HBI value + * @vbi: VBI value + */ +struct cam_isp_sensor_config { + struct cam_isp_sensor_dimension ppp_path; + struct cam_isp_sensor_dimension ipp_path; + struct cam_isp_sensor_dimension rdi_path[CAM_IFE_CSID_RDI_MAX]; + __u32 hbi; + __u32 vbi; +} __attribute__((packed)); + /** * struct cam_isp_core_config - ISP core registers configuration * From 09295759164b475f8332a9d68aba327e3d330474 Mon Sep 17 00:00:00 2001 From: Suresh Vankadara Date: Sat, 30 May 2020 15:49:40 +0530 Subject: [PATCH 372/790] msm: camera: cpas: Add support for holi camnoc Holi has different version of camnoc and CPAS version which requires separate register space and camnoc interface changes and CPAS version change. This change adds the same. CRs-Fixed: 2701462 Change-Id: I9fbfab592278ba7804809872b4b4b235895477f2 Signed-off-by: Suresh Vankadara --- Makefile | 10 + config/holicamera.conf | 17 + config/holicameraconf.h | 10 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 17 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 6 +- drivers/cam_cpas/cpas_top/cpastop_v545_100.h | 318 ++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 3 + drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 6 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 4 +- .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 3 +- include/uapi/camera/media/cam_ope.h | 1 + 11 files changed, 388 insertions(+), 7 deletions(-) create mode 100644 config/holicamera.conf create mode 100644 config/holicameraconf.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v545_100.h diff --git a/Makefile b/Makefile index 3e82a6fc6ccd..6e69c3b02f1b 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,10 @@ ifeq ($(CONFIG_ARCH_LAHAINA), y) include $(srctree)/techpack/camera/config/lahainacamera.conf endif +ifeq ($(CONFIG_ARCH_HOLI), y) +include $(srctree)/techpack/camera/config/holicamera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h @@ -37,6 +41,12 @@ ifeq ($(CONFIG_ARCH_LAHAINA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/lahainacameraconf.h endif + +ifeq ($(CONFIG_ARCH_HOLI), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/holicameraconf.h +endif + endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) diff --git a/config/holicamera.conf b/config/holicamera.conf new file mode 100644 index 000000000000..bfc74856aa7d --- /dev/null +++ b/config/holicamera.conf @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2020, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=y +$(info "SPECTRA_CAMERA IS STATIC") +else +$(info "SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_OPE=y +export CONFIG_SPECTRA_TFE=y +export CONFIG_SPECTRA_SENSOR=y +endif diff --git a/config/holicameraconf.h b/config/holicameraconf.h new file mode 100644 index 000000000000..958fe154c124 --- /dev/null +++ b/config/holicameraconf.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_OPE 1 +#define CONFIG_SPECTRA_TFE 1 +#define CONFIG_SPECTRA_SENSOR 1 diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 3cb820036408..632226fe5dfa 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -25,6 +25,7 @@ #include "cpastop_v580_100.h" #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" +#include "cpastop_v545_100.h" struct cam_camnoc_info *camnoc_info; @@ -106,6 +107,15 @@ static const uint32_t cam_cpas_hw_version_map 0, 0, }, + /* for camera_545 */ + { + CAM_CPAS_TITAN_545_V100, + 0, + 0, + 0, + 0, + 0, + }, }; static int cam_cpas_translate_camera_cpas_version_id( @@ -145,6 +155,10 @@ static int cam_cpas_translate_camera_cpas_version_id( *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_580; break; + case CAM_CPAS_CAMERA_VERSION_545: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_545; + break; + default: CAM_ERR(CAM_CPAS, "Invalid cam version %u", cam_version); @@ -747,6 +761,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_520_V100: camnoc_info = &cam520_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_545_V100: + camnoc_info = &cam545_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/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 84c2ea1d724a..f12010116bec 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -115,7 +115,9 @@ enum cam_camnoc_hw_irq_type { * @CAM_CAMNOC_JPEG: Indicates JPEG HW connection to camnoc * @CAM_CAMNOC_FD: Indicates FD HW connection to camnoc * @CAM_CAMNOC_ICP: Indicates ICP HW connection to camnoc - * @CAM_CAMNOC_TFE: Indicates TFE HW connection to camnoc + * @CAM_CAMNOC_TFE: Indicates TFE0 HW connection to camnoc + * @CAM_CAMNOC_TFE_1: Indicates TFE1 HW connection to camnoc + * @CAM_CAMNOC_TFE_2: Indicates TFE2 HW connection to camnoc * @CAM_CAMNOC_OPE: Indicates OPE HW connection to camnoc */ enum cam_camnoc_port_type { @@ -142,6 +144,8 @@ enum cam_camnoc_port_type { CAM_CAMNOC_FD, CAM_CAMNOC_ICP, CAM_CAMNOC_TFE, + CAM_CAMNOC_TFE_1, + CAM_CAMNOC_TFE_2, CAM_CAMNOC_OPE, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h new file mode 100644 index 000000000000..79e4910dea28 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V545_100_H_ +#define _CPASTOP_V545_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v545_100_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v545_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 = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +static struct cam_camnoc_specific + cam_cpas_v545_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 = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x00000003, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x55443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + .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_TFE_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x4030, + .value = 0x55443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x4034, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4040, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_TFE_2, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x5030, + .value = 0x55443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x5034, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5040, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_OPE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x00000033, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_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, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam545_cpas100_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam545_cpas100_camnoc_info = { + .specific = &cam_cpas_v545_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v545_100_camnoc_specific), + .irq_sbm = &cam_cpas_v545_100_irq_sbm, + .irq_err = &cam_cpas_v545_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v545_100_irq_err), + .err_logger = &cam545_cpas100_err_logger_offsets, + .errata_wa_list = NULL, +}; + +#endif /* _CPASTOP_V545_100_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 9601166c2afe..fa69ba4ab1d5 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -44,6 +44,7 @@ enum cam_cpas_camera_version { CAM_CPAS_CAMERA_VERSION_520 = 0x00050200, CAM_CPAS_CAMERA_VERSION_540 = 0x00050400, CAM_CPAS_CAMERA_VERSION_580 = 0x00050800, + CAM_CPAS_CAMERA_VERSION_545 = 0x00050405, CAM_CPAS_CAMERA_VERSION_MAX }; @@ -73,6 +74,7 @@ enum cam_cpas_camera_version_map_id { CAM_CPAS_CAMERA_VERSION_ID_580 = 0x4, CAM_CPAS_CAMERA_VERSION_ID_520 = 0x5, CAM_CPAS_CAMERA_VERSION_ID_540 = 0x6, + CAM_CPAS_CAMERA_VERSION_ID_545 = 0x7, CAM_CPAS_CAMERA_VERSION_ID_MAX }; @@ -108,6 +110,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_580_V100 = 0x580100, CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_520_V100 = 0x520100, + CAM_CPAS_TITAN_545_V100 = 0x545100, CAM_CPAS_TITAN_MAX }; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 45ba114cc17a..5b459dd4f366 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -582,7 +582,7 @@ static bool cam_ope_check_req_delay(struct cam_ope_ctx *ctx_data, struct timespec64 ts; uint64_t ts_ns; - get_monotonic_boottime64(&ts); + ktime_get_boottime_ts64(&ts); ts_ns = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec); @@ -1542,7 +1542,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req = ctx->req_list[cookie]; - get_monotonic_boottime64(&ts); + ktime_get_boottime_ts64(&ts); ope_hw_mgr->last_callback_time = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec); @@ -3098,7 +3098,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, CAM_ERR(CAM_OPE, "Invalid ctx req slot = %d", request_idx); return -EINVAL; } - get_monotonic_boottime64(&ts); + ktime_get_boottime_ts64(&ts); ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec); CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lrt=%llu", diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index fd6c0aaf54da..0d3472d2bffb 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -228,7 +228,7 @@ static int cam_ope_component_bind(struct device *dev, spin_lock_init(&ope_dev->hw_lock); init_completion(&ope_dev->hw_complete); - CAM_DBG(CAM_OPE, "OPE:%d component bound successfully" + CAM_DBG(CAM_OPE, "OPE:%d component bound successfully", ope_dev_intf->hw_idx); return rc; @@ -264,7 +264,7 @@ int cam_ope_probe(struct platform_device *pdev) int rc = 0; CAM_DBG(CAM_OPE, "Adding OPE component"); - rc = component_add(&pdev->dev, &cam_vfe_component_ops); + rc = component_add(&pdev->dev, &cam_ope_component_ops); if (rc) CAM_ERR(CAM_OPE, "failed to add component rc: %d", rc); diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index becfa63540ed..1034e55febc2 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -283,7 +283,8 @@ int cam_ope_top_process(struct ope_hw *ope_hw_info, rc = cam_ope_top_reset(ope_hw_info, 0, 0); break; case OPE_HW_DUMP_DEBUG: - rc - cam_ope_top_dump_debug_reg(ope_hw_info); + rc = cam_ope_top_dump_debug_reg(ope_hw_info); + break; default: break; } diff --git a/include/uapi/camera/media/cam_ope.h b/include/uapi/camera/media/cam_ope.h index fd6e30ca30da..cfd153cccd6e 100644 --- a/include/uapi/camera/media/cam_ope.h +++ b/include/uapi/camera/media/cam_ope.h @@ -93,6 +93,7 @@ struct ope_stripe_info { __u32 x_init; __u32 stripe_location; __u32 width; + __u32 height; __u32 disable_bus; __u32 reserved; }; From ebb82d948cba30f26cf7ec2360a06496ffa5a29b Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 19 May 2020 18:28:16 -0700 Subject: [PATCH 373/790] msm: camera: config: Enable camera as dlkm for lahaina Enable camera as dlkm for all flavor of compilation. CRs-Fixed: 2701988 Change-Id: Ic1bdd64cd612636613d3b1419c7bebc136023948 Signed-off-by: Jigarkumar Zala --- config/lahainacamera.conf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/lahainacamera.conf b/config/lahainacamera.conf index 32abf9dbba5f..af13af07e534 100644 --- a/config/lahainacamera.conf +++ b/config/lahainacamera.conf @@ -1,12 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only -# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. ifeq ($(CONFIG_QGKI),y) -export CONFIG_SPECTRA_CAMERA=y -$(info "SPECTRA_CAMERA IS STATIC") -else -$(info "SPECTRA_CAMERA IS MODULAR") export CONFIG_SPECTRA_CAMERA=m +$(info "QGKI Spectra Camera Building as DLKM") +else +export CONFIG_SPECTRA_CAMERA=m +$(info "GKI Spectra Camera Building as DLKM") endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) From 279dfebf8c2ed47404f4be7dd9081da4eeb0ad7f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 7 Apr 2020 14:26:03 -0700 Subject: [PATCH 374/790] msm: camera: common: Fixes the exit module code flow Fixes exit call flow as a part of rmmod. CRs-Fixed: 2675526 Change-Id: I47111a737cb06d9bb3d0a417a471c5c9fb545999 Signed-off-by: Jigarkumar Zala --- drivers/cam_cdm/cam_cdm_hw_core.c | 15 ++++- drivers/cam_icp/cam_icp_subdev.c | 11 +--- drivers/cam_icp/icp_hw/a5_hw/a5_dev.c | 24 ++++++- drivers/cam_icp/icp_hw/a5_hw/a5_soc.c | 11 +++- drivers/cam_icp/icp_hw/a5_hw/a5_soc.h | 4 +- drivers/cam_icp/icp_hw/bps_hw/bps_dev.c | 19 ++++++ drivers/cam_icp/icp_hw/bps_hw/bps_soc.c | 11 +++- drivers/cam_icp/icp_hw/bps_hw/bps_soc.h | 3 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 62 +++++++++++++++---- .../icp_hw/include/cam_icp_hw_mgr_intf.h | 2 + drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c | 18 ++++++ drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c | 11 +++- drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h | 3 +- drivers/cam_isp/cam_isp_context.c | 12 ++-- drivers/cam_isp/cam_isp_dev.c | 6 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 24 +++++++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 1 + drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c | 10 +++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 24 +++++++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 9 ++- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 2 + .../isp_hw/ife_csid_hw/cam_ife_csid_soc.c | 5 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 11 ++-- drivers/cam_req_mgr/cam_req_mgr_core.c | 1 + drivers/cam_req_mgr/cam_req_mgr_debug.c | 43 +++++++------ drivers/cam_req_mgr/cam_req_mgr_debug.h | 4 +- .../cam_flash/cam_flash_dev.c | 7 ++- .../cam_flash/cam_flash_soc.c | 51 +++++++++++++++ .../cam_flash/cam_flash_soc.h | 3 +- drivers/cam_sync/cam_sync.c | 43 +++++++++---- drivers/cam_sync/cam_sync_private.h | 8 +++ drivers/cam_utils/cam_soc_util.c | 22 ++++--- 32 files changed, 391 insertions(+), 89 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index ed3498308b7c..e8a4b6b7ac03 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -2206,10 +2206,19 @@ static void cam_hw_cdm_component_unbind(struct device *dev, return; } - rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); + if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { + rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "Deinit failed for hw"); + return; + } + } + + rc = cam_cdm_intf_deregister_hw_cdm(cdm_hw_intf, + cdm_hw->soc_info.soc_private, CAM_HW_CDM, cdm_core->index); if (rc) { - CAM_ERR(CAM_CDM, "Deinit failed for hw"); - return; + CAM_ERR(CAM_CDM, + "HW_CDM interface deregistration failed: rd: %d", rc); } rc = cam_cpas_unregister_client(cdm_core->cpas_handle); diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index d4c7e025afbd..ee7fe5132d6c 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -171,7 +171,8 @@ static int cam_icp_component_bind(struct device *dev, hw_mgr_intf = kzalloc(sizeof(*hw_mgr_intf), GFP_KERNEL); if (!hw_mgr_intf) { - rc = -EINVAL; + rc = -ENOMEM; + CAM_ERR(CAM_ICP, "Memory allocation fail"); goto hw_alloc_fail; } @@ -225,7 +226,6 @@ static void cam_icp_component_unbind(struct device *dev, { int i; struct v4l2_subdev *sd; - struct cam_subdev *subdev; struct platform_device *pdev = to_platform_device(dev); if (!pdev) { @@ -239,15 +239,10 @@ static void cam_icp_component_unbind(struct device *dev, return; } - subdev = v4l2_get_subdevdata(sd); - if (!subdev) { - CAM_ERR(CAM_ICP, "cam subdev is NULL"); - return; - } - for (i = 0; i < CAM_ICP_CTX_MAX; i++) cam_icp_context_deinit(&g_icp_dev.ctx_icp[i]); + cam_icp_hw_mgr_deinit(); cam_node_deinit(g_icp_dev.node); cam_subdev_remove(&g_icp_dev.sd); mutex_destroy(&g_icp_dev.icp_lock); diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c index ef5ec1119d33..64d02a7d5b9e 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_dev.c @@ -168,7 +168,7 @@ static int cam_a5_component_bind(struct device *dev, } CAM_DBG(CAM_ICP, "soc info : %pK", - (void *)&a5_dev->soc_info); + (void *)&a5_dev->soc_info); rc = cam_a5_register_cpas(&a5_dev->soc_info, core_info, a5_dev_intf->hw_idx); if (rc < 0) { @@ -185,6 +185,7 @@ static int cam_a5_component_bind(struct device *dev, return 0; cpas_reg_failed: + cam_a5_deinit_soc_resources(&a5_dev->soc_info); init_soc_failure: match_err: kfree(a5_dev->core_info); @@ -200,9 +201,21 @@ a5_dev_alloc_failure: static void cam_a5_component_unbind(struct device *dev, struct device *master_dev, void *data) { + struct cam_hw_info *a5_dev = NULL; + struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_a5_device_core_info *core_info = NULL; struct platform_device *pdev = to_platform_device(dev); - CAM_DBG(CAM_ICP, "Unbinding component: %s", pdev->name); + a5_dev_intf = platform_get_drvdata(pdev); + a5_dev = a5_dev_intf->hw_priv; + core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; + cam_cpas_unregister_client(core_info->cpas_handle); + cam_a5_deinit_soc_resources(&a5_dev->soc_info); + memset(&cam_a5_soc_info, 0, sizeof(struct a5_soc_info)); + kfree(a5_dev->core_info); + a5_dev->core_info = NULL; + kfree(a5_dev); + kfree(a5_dev_intf); } const static struct component_ops cam_a5_component_ops = { @@ -222,6 +235,12 @@ int cam_a5_probe(struct platform_device *pdev) return rc; } +static int cam_a5_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_a5_component_ops); + return 0; +} + static const struct of_device_id cam_a5_dt_match[] = { { .compatible = "qcom,cam-a5", @@ -233,6 +252,7 @@ MODULE_DEVICE_TABLE(of, cam_a5_dt_match); struct platform_driver cam_a5_driver = { .probe = cam_a5_probe, + .remove = cam_a5_remove, .driver = { .name = "cam-a5", .owner = THIS_MODULE, diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c index d0629612193a..6e9bace10ca4 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -174,6 +174,15 @@ int cam_a5_init_soc_resources(struct cam_hw_soc_info *soc_info, return rc; } +void cam_a5_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_WARN(CAM_ICP, "release platform resources fail"); +} + int cam_a5_enable_soc_resources(struct cam_hw_soc_info *soc_info) { int rc = 0; diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h index 480364df1fd6..8b5bc1c23c26 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_A5_SOC_H @@ -30,6 +30,8 @@ struct a5_soc_info { int cam_a5_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t a5_irq_handler, void *irq_data); +void cam_a5_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + int cam_a5_enable_soc_resources(struct cam_hw_soc_info *soc_info); int cam_a5_disable_soc_resources(struct cam_hw_soc_info *soc_info); diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c index b70b2f187d6a..7dab07468d26 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_dev.c @@ -177,9 +177,21 @@ static int cam_bps_component_bind(struct device *dev, static void cam_bps_component_unbind(struct device *dev, struct device *master_dev, void *data) { + struct cam_hw_info *bps_dev = NULL; + struct cam_hw_intf *bps_dev_intf = NULL; + struct cam_bps_device_core_info *core_info = NULL; struct platform_device *pdev = to_platform_device(dev); CAM_DBG(CAM_ICP, "Unbinding component: %s", pdev->name); + bps_dev_intf = platform_get_drvdata(pdev); + bps_dev = bps_dev_intf->hw_priv; + core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; + cam_cpas_unregister_client(core_info->cpas_handle); + cam_bps_deinit_soc_resources(&bps_dev->soc_info); + + kfree(bps_dev->core_info); + kfree(bps_dev); + kfree(bps_dev_intf); } const static struct component_ops cam_bps_component_ops = { @@ -199,6 +211,12 @@ int cam_bps_probe(struct platform_device *pdev) return rc; } +static int cam_bps_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_bps_component_ops); + return 0; +} + static const struct of_device_id cam_bps_dt_match[] = { { .compatible = "qcom,cam-bps", @@ -210,6 +228,7 @@ MODULE_DEVICE_TABLE(of, cam_bps_dt_match); struct platform_driver cam_bps_driver = { .probe = cam_bps_probe, + .remove = cam_bps_remove, .driver = { .name = "cam-bps", .owner = THIS_MODULE, diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c index 481eeafdb0b2..d1a97de5c026 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -52,6 +52,15 @@ int cam_bps_init_soc_resources(struct cam_hw_soc_info *soc_info, return rc; } +void cam_bps_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_WARN(CAM_ICP, "release platform resources fail"); +} + int cam_bps_enable_soc_resources(struct cam_hw_soc_info *soc_info) { int rc = 0; diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h index da4feac909e4..b7657bf671a7 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_BPS_SOC_H_ @@ -23,4 +23,5 @@ int cam_bps_transfer_gdsc_control(struct cam_hw_soc_info *soc_info); int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_rate); int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable); +void cam_bps_deinit_soc_resources(struct cam_hw_soc_info *soc_info); #endif /* _CAM_BPS_SOC_H_*/ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 1c804d5df6a5..268256d8a438 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1887,8 +1887,11 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void) int rc = 0; icp_hw_mgr.dentry = debugfs_create_dir("camera_icp", NULL); - if (!icp_hw_mgr.dentry) + if (IS_ERR_OR_NULL(icp_hw_mgr.dentry)) { + CAM_ERR(CAM_ICP, "Debugfs entry dir: %s failed", + "camrea_icp"); return -ENOMEM; + } if (!debugfs_create_bool("icp_pc", 0644, @@ -5818,6 +5821,7 @@ static int cam_icp_mgr_alloc_devs(struct device_node *of_node) sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL); if (!icp_hw_mgr.devices[CAM_ICP_DEV_A5]) { rc = -ENOMEM; + CAM_ERR(CAM_ICP, "a5 allocation fail: rc = %d", rc); goto num_a5_failed; } @@ -5834,6 +5838,7 @@ static int cam_icp_mgr_alloc_devs(struct device_node *of_node) sizeof(struct cam_hw_intf *), GFP_KERNEL); if (!icp_hw_mgr.devices[CAM_ICP_DEV_IPE]) { rc = -ENOMEM; + CAM_ERR(CAM_ICP, "ipe device allocation fail : rc= %d", rc); goto num_ipe_failed; } @@ -5846,6 +5851,7 @@ static int cam_icp_mgr_alloc_devs(struct device_node *of_node) sizeof(struct cam_hw_intf *), GFP_KERNEL); if (!icp_hw_mgr.devices[CAM_ICP_DEV_BPS]) { rc = -ENOMEM; + CAM_ERR(CAM_ICP, "bps device allocation fail : rc= %d", rc); goto num_bps_failed; } @@ -5874,9 +5880,10 @@ static int cam_icp_mgr_init_devs(struct device_node *of_node) struct cam_hw_intf *child_dev_intf = NULL; rc = cam_icp_mgr_alloc_devs(of_node); - if (rc) + if (rc) { + CAM_ERR(CAM_ICP, "alloc_devs fail : rc = %d", rc); return rc; - + } count = of_property_count_strings(of_node, "compat-hw-name"); if (!count) { CAM_ERR(CAM_ICP, "no compat hw found in dev tree, cnt = %d", @@ -5972,25 +5979,31 @@ static int cam_icp_mgr_create_wq(void) icp_hw_mgr.cmd_work_data = kzalloc(sizeof(struct hfi_cmd_work_data) * ICP_WORKQ_NUM_TASK, GFP_KERNEL); - if (!icp_hw_mgr.cmd_work_data) + if (!icp_hw_mgr.cmd_work_data) { + CAM_ERR(CAM_ICP, "Mem reservation fail for cmd_work_data"); goto cmd_work_data_failed; - + } icp_hw_mgr.msg_work_data = kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, GFP_KERNEL); - if (!icp_hw_mgr.msg_work_data) + if (!icp_hw_mgr.msg_work_data) { + CAM_ERR(CAM_ICP, "Mem reservation fail for msg_work_data"); goto msg_work_data_failed; + } icp_hw_mgr.timer_work_data = kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK, GFP_KERNEL); - if (!icp_hw_mgr.timer_work_data) + if (!icp_hw_mgr.timer_work_data) { + CAM_ERR(CAM_ICP, "Mem reservation fail for timer_work_data"); goto timer_work_data_failed; + } rc = cam_icp_hw_mgr_create_debugfs_entry(); - if (rc) + if (rc) { + CAM_ERR(CAM_ICP, "create_debugfs_entry fail= rc: %d", rc); goto debugfs_create_failed; - + } for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) icp_hw_mgr.msg_work->task.pool[i].payload = &icp_hw_mgr.msg_work_data[i]; @@ -6020,6 +6033,13 @@ cmd_work_failed: return rc; } +void cam_icp_mgr_destroy_wq(void) +{ + cam_req_mgr_workq_destroy(&icp_hw_mgr.timer_work); + cam_req_mgr_workq_destroy(&icp_hw_mgr.msg_work); + cam_req_mgr_workq_destroy(&icp_hw_mgr.cmd_work); +} + static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -6104,9 +6124,10 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, } rc = cam_icp_mgr_init_devs(of_node); - if (rc) + if (rc) { + CAM_ERR(CAM_ICP, "cam_icp_mgr_init_devs fail: rc: %d", rc); goto dev_init_failed; - + } rc = cam_smmu_get_handle("icp", &icp_hw_mgr.iommu_hdl); if (rc) { CAM_ERR(CAM_ICP, "get mmu handle failed: %d", rc); @@ -6120,8 +6141,10 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, } rc = cam_icp_mgr_create_wq(); - if (rc) + if (rc) { + CAM_ERR(CAM_ICP, "cam_icp_mgr_create_wq fail: rc=%d", rc); goto icp_wq_create_failed; + } if (iommu_hdl) *iommu_hdl = icp_hw_mgr.iommu_hdl; @@ -6146,3 +6169,18 @@ dev_init_failed: return rc; } + +void cam_icp_hw_mgr_deinit(void) +{ + int i = 0; + + debugfs_remove_recursive(icp_hw_mgr.dentry); + icp_hw_mgr.dentry = NULL; + cam_icp_mgr_destroy_wq(); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_BPS]); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_IPE]); + kfree(icp_hw_mgr.devices[CAM_ICP_DEV_A5]); + mutex_destroy(&icp_hw_mgr.hw_mgr_mutex); + for (i = 0; i < CAM_ICP_CTX_MAX; i++) + mutex_destroy(&icp_hw_mgr.ctx_data[i].ctx_mutex); +} diff --git a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h index 84129cba7e19..c18e4053bc82 100644 --- a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h +++ b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h @@ -33,6 +33,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl); +void cam_icp_hw_mgr_deinit(void); + /** * struct cam_icp_cpas_vote * @ahb_vote: AHB vote info diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c index c4b75711ce40..70957a40686d 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -169,9 +169,20 @@ static int cam_ipe_component_bind(struct device *dev, static void cam_ipe_component_unbind(struct device *dev, struct device *master_dev, void *data) { + struct cam_hw_info *ipe_dev = NULL; + struct cam_hw_intf *ipe_dev_intf = NULL; + struct cam_ipe_device_core_info *core_info = NULL; struct platform_device *pdev = to_platform_device(dev); CAM_DBG(CAM_ICP, "Unbinding component: %s", pdev->name); + ipe_dev_intf = platform_get_drvdata(pdev); + ipe_dev = ipe_dev_intf->hw_priv; + core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; + cam_cpas_unregister_client(core_info->cpas_handle); + cam_ipe_deinit_soc_resources(&ipe_dev->soc_info); + kfree(ipe_dev->core_info); + kfree(ipe_dev); + kfree(ipe_dev_intf); } @@ -192,6 +203,12 @@ int cam_ipe_probe(struct platform_device *pdev) return rc; } +static int cam_ipe_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_ipe_component_ops); + return 0; +} + static const struct of_device_id cam_ipe_dt_match[] = { { .compatible = "qcom,cam-ipe", @@ -203,6 +220,7 @@ MODULE_DEVICE_TABLE(of, cam_ipe_dt_match); struct platform_driver cam_ipe_driver = { .probe = cam_ipe_probe, + .remove = cam_ipe_remove, .driver = { .name = "cam-ipe", .owner = THIS_MODULE, diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c index 11cc7f7a3317..92d3390a9a74 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -103,6 +103,15 @@ int cam_ipe_init_soc_resources(struct cam_hw_soc_info *soc_info, return rc; } +void cam_ipe_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_WARN(CAM_ICP, "release platform resources fail"); +} + int cam_ipe_enable_soc_resources(struct cam_hw_soc_info *soc_info) { int rc = 0; diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h index 8981b18823ad..c7e11506251a 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_IPE_SOC_H @@ -23,4 +23,5 @@ int cam_ipe_transfer_gdsc_control(struct cam_hw_soc_info *soc_info); int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_rate); int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable); +void cam_ipe_deinit_soc_resources(struct cam_hw_soc_info *soc_info); #endif /* CAM_IPE_SOC_H */ diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 0e95661bc60d..71bac56daa40 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5302,7 +5302,7 @@ static int cam_isp_context_debug_register(void) isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", NULL); - if (!isp_ctx_debug.dentry) { + if (IS_ERR_OR_NULL(isp_ctx_debug.dentry)) { CAM_ERR(CAM_ISP, "failed to create dentry"); return -ENOMEM; } @@ -5383,7 +5383,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx, for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) atomic64_set(&ctx->event_record_head[i], -1); - cam_isp_context_debug_register(); + if (!isp_ctx_debug.dentry) + cam_isp_context_debug_register(); err: return rc; @@ -5391,8 +5392,6 @@ err: int cam_isp_context_deinit(struct cam_isp_context *ctx) { - int rc = 0; - if (ctx->base) cam_context_deinit(ctx->base); @@ -5401,6 +5400,9 @@ int cam_isp_context_deinit(struct cam_isp_context *ctx) __cam_isp_ctx_substate_val_to_type( ctx->substate_activated)); + debugfs_remove_recursive(isp_ctx_debug.dentry); + isp_ctx_debug.dentry = NULL; memset(ctx, 0, sizeof(*ctx)); - return rc; + + return 0; } diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index a8c56ae19229..778621bcdb40 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -175,7 +175,13 @@ static void cam_isp_dev_component_unbind(struct device *dev, { int rc = 0; int i; + const char *compat_str = NULL; + struct platform_device *pdev = to_platform_device(dev); + rc = of_property_read_string_index(pdev->dev.of_node, "arch-compat", 0, + (const char **)&compat_str); + + cam_isp_hw_mgr_deinit(compat_str); /* clean up resources */ for (i = 0; i < CAM_CTX_MAX; i++) { rc = cam_isp_context_deinit(&g_isp_dev.ctx_isp[i]); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 17aa1ff4f217..0772711710c1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7867,3 +7867,27 @@ secure_fail: g_ife_hw_mgr.mgr_common.img_iommu_hdl = -1; return rc; } + +void cam_ife_hw_mgr_deinit(void) +{ + int i = 0; + + cam_req_mgr_workq_destroy(&g_ife_hw_mgr.workq); + debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); + g_ife_hw_mgr.debug_cfg.dentry = NULL; + + for (i = 0; i < CAM_CTX_MAX; i++) { + cam_tasklet_deinit( + &g_ife_hw_mgr.mgr_common.tasklet_pool[i]); + kfree(g_ife_hw_mgr.ctx_pool[i].cdm_cmd); + g_ife_hw_mgr.ctx_pool[i].cdm_cmd = NULL; + g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = NULL; + } + + cam_smmu_destroy_handle( + g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure); + g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure = -1; + + cam_smmu_destroy_handle(g_ife_hw_mgr.mgr_common.img_iommu_hdl); + g_ife_hw_mgr.mgr_common.img_iommu_hdl = -1; +} diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 9ff4c05d0e5b..ca1648d616c5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -228,5 +228,6 @@ struct cam_ife_hw_event_recovery_data { * */ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); +void cam_ife_hw_mgr_deinit(void); #endif /* _CAM_IFE_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c index 4c83fa6b9402..e68fd557a394 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c @@ -25,3 +25,13 @@ int cam_isp_hw_mgr_init(const char *device_name_str, return rc; } + +void cam_isp_hw_mgr_deinit(const char *device_name_str) +{ + if (strnstr(device_name_str, "ife", strlen(device_name_str))) + cam_ife_hw_mgr_deinit(); + else if (strnstr(device_name_str, "tfe", strlen(device_name_str))) + cam_tfe_hw_mgr_deinit(); + else + CAM_ERR(CAM_ISP, "Invalid ISP hw type :%s", device_name_str); +} diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 9d7ec3e03852..6425088a462c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5523,3 +5523,27 @@ secure_fail: g_tfe_hw_mgr.mgr_common.img_iommu_hdl = -1; return rc; } + +void cam_tfe_hw_mgr_deinit(void) +{ + int i = 0; + + cam_req_mgr_workq_destroy(&g_tfe_hw_mgr.workq); + debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); + g_tfe_hw_mgr.debug_cfg.dentry = NULL; + + for (i = 0; i < CAM_CTX_MAX; i++) { + cam_tasklet_deinit( + &g_tfe_hw_mgr.mgr_common.tasklet_pool[i]); + kfree(g_tfe_hw_mgr.ctx_pool[i].cdm_cmd); + g_tfe_hw_mgr.ctx_pool[i].cdm_cmd = NULL; + g_tfe_hw_mgr.ctx_pool[i].common.tasklet_info = NULL; + } + + cam_smmu_destroy_handle( + g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure); + g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure = -1; + + cam_smmu_destroy_handle(g_tfe_hw_mgr.mgr_common.img_iommu_hdl); + g_tfe_hw_mgr.mgr_common.img_iommu_hdl = -1; +} diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 5b9ca51365a7..971863d5b5b6 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -195,12 +195,17 @@ struct cam_tfe_hw_event_recovery_data { */ #ifdef CONFIG_SPECTRA_TFE int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); - +void cam_tfe_hw_mgr_deinit(void); #else static inline int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, - int *iommu_hdl) { + int *iommu_hdl) +{ return -EINVAL; } + +static inline void cam_tfe_hw_mgr_deinit(void) +{ +} #endif #endif /* _CAM_TFE_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 32f38d81b515..2ed1f8b211c1 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -371,4 +371,6 @@ struct cam_isp_start_args { int cam_isp_hw_mgr_init(const char *device_name_str, struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl); +void cam_isp_hw_mgr_deinit(const char *device_name_str); + #endif /* __CAM_ISP_HW_MGR_INTF_H__ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c index 7abcc64068ee..2065a3aeb459 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include #include "cam_ife_csid_soc.h" @@ -110,6 +110,9 @@ int cam_ife_csid_deinit_soc_resources( CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc); rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_WARN(CAM_ISP, + "soc release platform resource fail rc: %d", rc); return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 6f4152671f5a..3179362f7cac 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -208,11 +208,12 @@ int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info) CAM_ERR(CAM_ISP, "Error! Release platform resources failed rc=%d", rc); - rc = cam_soc_util_clk_put(&soc_private->dsp_clk); - if (rc < 0) - CAM_ERR(CAM_ISP, - "Error Put dsp clk failed rc=%d", rc); - + if (soc_private->dsp_clk_index != -1) { + rc = cam_soc_util_clk_put(&soc_private->dsp_clk); + if (rc < 0) + CAM_ERR(CAM_ISP, + "Error Put dsp clk failed rc=%d", rc); + } kfree(soc_private); return rc; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index bd403c93b29d..aaa10827fba6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -4220,6 +4220,7 @@ int cam_req_mgr_core_device_deinit(void) } CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev); + cam_req_mgr_debug_unregister(); mutex_destroy(&g_crm_core_dev->crm_lock); kfree(g_crm_core_dev); g_crm_core_dev = NULL; diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index db6bec704370..6b6a91b6303b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_debug.h" @@ -8,6 +8,7 @@ #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; +static struct dentry *debugfs_root; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { @@ -112,28 +113,34 @@ static const struct file_operations session_info = { int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) { - struct dentry *debugfs_root; char dirname[32] = {0}; - snprintf(dirname, sizeof(dirname), "cam_req_mgr"); debugfs_root = debugfs_create_dir(dirname, NULL); - if (!debugfs_root) - return -ENOMEM; - - if (!debugfs_create_file("sessions_info", 0644, - debugfs_root, core_dev, &session_info)) - return -ENOMEM; - - if (!debugfs_create_file("bubble_recovery", 0644, - debugfs_root, core_dev, &bubble_recovery)) - return -ENOMEM; - - if (!debugfs_create_bool("recovery_on_apply_fail", - 0644, - debugfs_root, - &core_dev->recovery_on_apply_fail)) { + if (IS_ERR_OR_NULL(debugfs_root)) { + CAM_ERR(CAM_CRM, "Failed to create cam_req_mgr debugfs dir"); return -ENOMEM; } + if (!debugfs_create_file("sessions_info", 0644, + debugfs_root, core_dev, &session_info)) + CAM_WARN(CAM_CRM, + "Failed to create sessions_info debugfs file"); + + if (!debugfs_create_file("bubble_recovery", 0644, + debugfs_root, core_dev, &bubble_recovery)) + CAM_WARN(CAM_CRM, + "Failed to create bubble_recovery debugfs file"); + + if (!debugfs_create_bool("recovery_on_apply_fail", + 0644, debugfs_root, + &core_dev->recovery_on_apply_fail)) + CAM_WARN(CAM_CRM, + "Failed to create recovery_on_apply_fail debugfs bool"); return 0; } + +void cam_req_mgr_debug_unregister(void) +{ + if (!debugfs_root) + debugfs_remove_recursive(debugfs_root); +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.h b/drivers/cam_req_mgr/cam_req_mgr_debug.h index dc72c522d140..defe55a731e7 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.h +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_DEBUG_H_ @@ -8,7 +8,9 @@ #include #include "cam_req_mgr_core.h" +#include "cam_debug_util.h" int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev); +void cam_req_mgr_debug_unregister(void); #endif diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 3d2ef84a2a87..ae6620017d62 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -519,6 +519,7 @@ static void cam_flash_component_unbind(struct device *dev, cam_flash_shutdown(fctrl); mutex_unlock(&fctrl->flash_mutex); cam_unregister_subdev(&(fctrl->v4l2_dev_str)); + cam_flash_put_source_node_data(fctrl); platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&fctrl->v4l2_dev_str.sd, NULL); kfree(fctrl); @@ -659,9 +660,9 @@ int32_t cam_flash_init_module(void) int32_t rc = 0; rc = platform_driver_register(&cam_flash_platform_driver); - if (rc == 0) { - CAM_DBG(CAM_FLASH, "platform probe success"); - return 0; + if (rc < 0) { + CAM_ERR(CAM_FLASH, "platform probe failed rc: %d", rc); + return rc; } rc = i2c_add_driver(&cam_flash_i2c_driver); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index abd2355403c6..17b7c7e0aec8 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -8,6 +8,57 @@ #include "cam_flash_soc.h" #include "cam_res_mgr_api.h" +void cam_flash_put_source_node_data(struct cam_flash_ctrl *fctrl) +{ + uint32_t count = 0, i = 0; + struct cam_flash_private_soc *soc_private = NULL; + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "NULL flash control structure"); + return; + } + + soc_private = fctrl->soc_info.soc_private; + + if (fctrl->switch_trigger) { + CAM_DBG(CAM_FLASH, "switch trigger: %s", + soc_private->switch_trigger_name); + cam_res_mgr_led_trigger_unregister(fctrl->switch_trigger); + } + + if (fctrl->flash_num_sources) { + if (fctrl->flash_num_sources > CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "Invalid LED count: %d", count); + return; + } + + count = fctrl->flash_num_sources; + + for (i = 0; i < count; i++) { + CAM_DBG(CAM_FLASH, "Flash default trigger %s", + soc_private->flash_trigger_name[i]); + cam_res_mgr_led_trigger_unregister( + fctrl->flash_trigger[i]); + } + } + + if (fctrl->torch_num_sources) { + if (fctrl->torch_num_sources > CAM_FLASH_MAX_LED_TRIGGERS) { + CAM_ERR(CAM_FLASH, "Invalid LED count: %d", count); + return; + } + + count = fctrl->torch_num_sources; + + for (i = 0; i < count; i++) { + CAM_DBG(CAM_FLASH, "Flash default trigger %s", + soc_private->flash_trigger_name[i]); + cam_res_mgr_led_trigger_unregister( + fctrl->torch_trigger[i]); + } + } +} + static int32_t cam_get_source_node_info( struct device_node *of_node, struct cam_flash_ctrl *fctrl, diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h index cfe7c3464f64..466fbeef1928 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FLASH_SOC_H_ @@ -11,4 +11,5 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, struct cam_hw_soc_info *soc_info); +void cam_flash_put_source_node_data(struct cam_flash_ctrl *fctrl); #endif /*_CAM_FLASH_SOC_H_*/ diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index a984a7be8ffa..37461c27d8c0 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1072,24 +1072,39 @@ int cam_synx_sync_signal(int32_t sync_obj, uint32_t synx_status) return rc; } -static int cam_sync_register_synx_bind_ops(void) +static int cam_sync_register_synx_bind_ops( + struct synx_register_params *object) { int rc = 0; - struct synx_register_params params; - params.name = CAM_SYNC_NAME; - params.type = SYNX_TYPE_CSL; - params.ops.register_callback = cam_sync_register_callback; - params.ops.deregister_callback = cam_sync_deregister_callback; - params.ops.enable_signaling = cam_sync_get_obj_ref; - params.ops.signal = cam_synx_sync_signal; - - rc = synx_register_ops(¶ms); + rc = synx_register_ops(object); if (rc) CAM_ERR(CAM_SYNC, "synx registration fail with rc=%d", rc); return rc; } + +static void cam_sync_unregister_synx_bind_ops( + struct synx_register_params *object) +{ + int rc = 0; + + rc = synx_deregister_ops(object); + if (rc) + CAM_ERR(CAM_SYNC, "sync unregistration fail with %d", rc); +} + +static void cam_sync_configure_synx_obj(struct synx_register_params *object) +{ + struct synx_register_params *params = object; + + params->name = CAM_SYNC_NAME; + params->type = SYNX_TYPE_CSL; + params->ops.register_callback = cam_sync_register_callback; + params->ops.deregister_callback = cam_sync_deregister_callback; + params->ops.enable_signaling = cam_sync_get_obj_ref; + params->ops.signal = cam_synx_sync_signal; +} #endif static int cam_sync_component_bind(struct device *dev, @@ -1167,8 +1182,9 @@ static int cam_sync_component_bind(struct device *dev, trigger_cb_without_switch = false; cam_sync_create_debugfs(); #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) - CAM_INFO(CAM_SYNC, "Registering with synx driver"); - rc = cam_sync_register_synx_bind_ops(); + CAM_DBG(CAM_SYNC, "Registering with synx driver"); + cam_sync_configure_synx_obj(&sync_dev->params); + rc = cam_sync_register_synx_bind_ops(&sync_dev->params); if (rc) goto v4l2_fail; #endif @@ -1195,6 +1211,9 @@ static void cam_sync_component_unbind(struct device *dev, v4l2_device_unregister(sync_dev->vdev->v4l2_dev); cam_sync_media_controller_cleanup(sync_dev); +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) + cam_sync_unregister_synx_bind_ops(&sync_dev->params); +#endif video_unregister_device(sync_dev->vdev); video_device_release(sync_dev->vdev); debugfs_remove_recursive(sync_dev->dentry); diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index 2cd8917758ee..8d95efe2cf88 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -17,6 +17,10 @@ #include #include +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) +#include +#endif + #ifdef CONFIG_CAM_SYNC_DBG #define CDBG(fmt, args...) pr_err(fmt, ##args) #else @@ -177,6 +181,7 @@ struct cam_signalable_info { * @work_queue : Work queue used for dispatching kernel callbacks * @cam_sync_eventq : Event queue used to dispatch user payloads to user space * @bitmap : Bitmap representation of all sync objects + * @params : Parameters for synx call back registration */ struct sync_device { struct video_device *vdev; @@ -190,6 +195,9 @@ struct sync_device { struct v4l2_fh *cam_sync_eventq; spinlock_t cam_sync_eventq_lock; DECLARE_BITMAP(bitmap, CAM_SYNC_MAX_OBJS); +#if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) + struct synx_register_params params; +#endif }; diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 39da1d20e3d9..5ea63757526b 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -184,35 +184,35 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control, static int cam_soc_util_create_clk_lvl_debugfs( struct cam_hw_soc_info *soc_info) { - struct dentry *dentry = NULL; - if (!soc_info) { CAM_ERR(CAM_UTIL, "soc info is NULL"); return -EINVAL; } - if (soc_info->dentry) + if (soc_info->dentry) { + CAM_DBG(CAM_UTIL, "Debubfs entry for %s already exist", + soc_info->dev_name); return 0; + } memset(debugfs_dir_name, 0, sizeof(debugfs_dir_name)); strlcat(debugfs_dir_name, "clk_dir_", sizeof(debugfs_dir_name)); strlcat(debugfs_dir_name, soc_info->dev_name, sizeof(debugfs_dir_name)); - dentry = soc_info->dentry; - dentry = debugfs_create_dir(debugfs_dir_name, NULL); - if (!dentry) { + soc_info->dentry = debugfs_create_dir(debugfs_dir_name, NULL); + if (IS_ERR_OR_NULL(soc_info->dentry)) { CAM_ERR(CAM_UTIL, "failed to create debug directory"); return -ENOMEM; } if (!debugfs_create_file("clk_lvl_options", 0444, - dentry, soc_info, &cam_soc_util_clk_lvl_options)) { + soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_options)) { CAM_ERR(CAM_UTIL, "failed to create clk_lvl_options"); goto err; } if (!debugfs_create_file("clk_lvl_control", 0644, - dentry, soc_info, &cam_soc_util_clk_lvl_control)) { + soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control)) { CAM_ERR(CAM_UTIL, "failed to create clk_lvl_control"); goto err; } @@ -223,8 +223,10 @@ static int cam_soc_util_create_clk_lvl_debugfs( return 0; err: - debugfs_remove_recursive(dentry); - dentry = NULL; + CAM_ERR(CAM_UTIL, "Error in creating Debugfs Entry: %s", + soc_info->dev_name); + debugfs_remove_recursive(soc_info->dentry); + soc_info->dentry = NULL; return -ENOMEM; } From 5cb16c01edb44f88c532b7cfcecaa7e335740040 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 18 May 2020 16:19:59 -0700 Subject: [PATCH 375/790] msm: camera: cpas: Add support for custom QoS selection Add cpas interface to allow clients or usecase to select different QoS settings based on requirement. Selection API must be called before camera hw powers up. CRs-Fixed: 2687917 Change-Id: Ie524fcd6131d7c42288d0d734a7cdf6b9fcb92b7 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 43 + drivers/cam_cpas/cam_cpas_hw.h | 3 + drivers/cam_cpas/cam_cpas_hw_intf.h | 1 + drivers/cam_cpas/cam_cpas_intf.c | 25 + drivers/cam_cpas/camss_top/cam_camsstop_hw.c | 3 +- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 44 + .../cam_cpas/cpas_top/cpastop_v480_custom.h | 711 ++++++++++++++++ .../cam_cpas/cpas_top/cpastop_v580_custom.h | 791 ++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 14 + .../cam_custom_hw1/cam_custom_sub_mod_soc.c | 15 +- 10 files changed, 1647 insertions(+), 3 deletions(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v480_custom.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v580_custom.h diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index c7fa0c4fd60b..c864a7fb286a 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1810,6 +1810,35 @@ static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) return rc; } +static int cam_cpas_select_qos(struct cam_hw_info *cpas_hw, + uint32_t selection_mask) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + int rc = 0; + + mutex_lock(&cpas_hw->hw_mutex); + + if (cpas_hw->hw_state == CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_CPAS, + "Hw already in power up state, can't change QoS settings"); + rc = -EINVAL; + goto done; + } + + if (cpas_core->internal_ops.setup_qos_settings) { + rc = cpas_core->internal_ops.setup_qos_settings(cpas_hw, + selection_mask); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in changing QoS %d", rc); + } else { + CAM_WARN(CAM_CPAS, "No ops for qos_settings"); + } + +done: + mutex_unlock(&cpas_hw->hw_mutex); + return rc; +} + static int cam_cpas_hw_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -1916,6 +1945,20 @@ static int cam_cpas_hw_process_cmd(void *hw_priv, rc = cam_cpas_log_vote(hw_priv); break; } + + case CAM_CPAS_HW_CMD_SELECT_QOS: { + uint32_t *selection_mask; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + selection_mask = (uint32_t *)cmd_args; + rc = cam_cpas_select_qos(hw_priv, *selection_mask); + break; + } default: CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type); break; diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index ca44666dd40f..4d76b80fa7d1 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -55,6 +55,7 @@ enum cam_cpas_access_type { * @setup_regbase: Function pointer for setup rebase indices * @power_on: Function pointer for hw core specific power on settings * @power_off: Function pointer for hw core specific power off settings + * @setup_qos_settings: Function pointer for hw to select a specific qos header * */ struct cam_cpas_internal_ops { @@ -67,6 +68,8 @@ struct cam_cpas_internal_ops { int32_t regbase_index[], int32_t num_reg_map); int (*power_on)(struct cam_hw_info *cpas_hw); int (*power_off)(struct cam_hw_info *cpas_hw); + int (*setup_qos_settings)(struct cam_hw_info *cpas_hw, + uint32_t selection_mask); }; /** diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index 3e6ac167f478..096437408043 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -39,6 +39,7 @@ enum cam_cpas_hw_cmd_process { CAM_CPAS_HW_CMD_AHB_VOTE, CAM_CPAS_HW_CMD_AXI_VOTE, CAM_CPAS_HW_CMD_LOG_VOTE, + CAM_CPAS_HW_CMD_SELECT_QOS, CAM_CPAS_HW_CMD_INVALID, }; diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index cc72cbf985b1..ddbb3bb2efb9 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -429,6 +429,31 @@ void cam_cpas_log_votes(void) } EXPORT_SYMBOL(cam_cpas_log_votes); +int cam_cpas_select_qos_settings(uint32_t selection_mask) +{ + int rc = 0; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -EBADR; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_SELECT_QOS, &selection_mask, + sizeof(selection_mask)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EBADR; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_select_qos_settings); + int cam_cpas_unregister_client(uint32_t client_handle) { int rc; diff --git a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c index b7f3550bc632..32415b0baf5d 100644 --- a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c +++ b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. */ #include "cam_cpas_hw_intf.h" @@ -77,6 +77,7 @@ int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->setup_regbase = cam_camsstop_setup_regbase_indices; internal_ops->power_on = NULL; internal_ops->power_off = NULL; + internal_ops->setup_qos_settings = NULL; return 0; } diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 3cb820036408..ebeb048838a0 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -22,7 +22,9 @@ #include "cpastop_v175_120.h" #include "cpastop_v175_130.h" #include "cpastop_v480_100.h" +#include "cpastop_v480_custom.h" #include "cpastop_v580_100.h" +#include "cpastop_v580_custom.h" #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" @@ -759,6 +761,47 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, return 0; } +static int cam_cpastop_setup_qos_settings(struct cam_hw_info *cpas_hw, + uint32_t selection_mask) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + + CAM_DBG(CAM_CPAS, + "QoS selection : hw_version=0x%x selection_mask 0x%x", + soc_info->hw_version, + selection_mask); + + switch (soc_info->hw_version) { + case CAM_CPAS_TITAN_480_V100: + if (selection_mask & CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK) + camnoc_info = &cam480_custom_camnoc_info; + else if (selection_mask & CAM_CPAS_QOS_DEFAULT_SETTINGS_MASK) + camnoc_info = &cam480_cpas100_camnoc_info; + else + CAM_ERR(CAM_CPAS, "Invalid selection mask 0x%x", + selection_mask); + break; + case CAM_CPAS_TITAN_580_V100: + if (selection_mask & CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK) + camnoc_info = &cam580_custom_camnoc_info; + else if (selection_mask & CAM_CPAS_QOS_DEFAULT_SETTINGS_MASK) + camnoc_info = &cam580_cpas100_camnoc_info; + else + CAM_ERR(CAM_CPAS, + "Invalid selection mask 0x%x for hw 0x%x", + selection_mask, soc_info->hw_version); + break; + default: + CAM_WARN(CAM_CPAS, "QoS selection not supported for 0x%x", + soc_info->hw_version); + rc = -EINVAL; + break; + } + + return rc; +} + int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) { if (!internal_ops) { @@ -772,6 +815,7 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->setup_regbase = cam_cpastop_setup_regbase_indices; internal_ops->power_on = cam_cpastop_poweron; internal_ops->power_off = cam_cpastop_poweroff; + internal_ops->setup_qos_settings = cam_cpastop_setup_qos_settings; return 0; } diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h new file mode 100644 index 000000000000..1b2767b3232c --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h @@ -0,0 +1,711 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V480_CUSTOM_H_ +#define _CPASTOP_V480_CUSTOM_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v480_custom_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3840, /* SBM_FAULTINEN0_LOW */ + .value = 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + (TEST_IRQ_ENABLE ? + 0x40 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3848, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x3880, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x5 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v480_custom_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = false, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x7008, /* ERL_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x7010, /* ERL_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x7018, /* ERL_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x1BA0, /* IFE_UBWC_STATS_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1B90, /* IFE_UBWC_STATS_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1B98, /* IFE_UBWC_STATS_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2520, /* IPE1_BPS_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2510, /* IPE1_BPS_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2518, /* IPE1_BPS_RD_DECERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE0_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 = 0x1F20, /* IPE0_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1F10, /* IPE0_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1F18, /* IPE0_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 = 0x29A0, /* IPE_BPS_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2990, + /* IPE_BPS_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2998, /* IPE_BPS_WR_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = false, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* 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 = 0x40, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v480_custom_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* CDM_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_FD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x630, /* FD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x634, /* FD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x638, /* FD_URGENCY_LOW */ + .value = 0x33, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x640, /* FD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x648, /* FD_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_RDI_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1048, /* IFE_RDI_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, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_RDI_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* IFE_RDI_WR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* IFE_RDI_WR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1438, /* IFE_RDI_WR_URGENCY_LOW */ + .value = 0x1070, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1440, /* IFE_RDI_WR_DANGERLUT_LOW */ + .value = 0xFFFFFFF0, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1448, /* IFE_RDI_WR_SAFELUT_LOW */ + .value = 0x1, + }, + .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_IFE_UBWC_STATS, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A30, /* IFE_UBWC_STATS_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A34, /* IFE_UBWC_STATS_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A38, /* IFE_UBWC_STATS_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A40, /* IFE_UBWC_STATS_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A48, /* IFE_UBWC_STATS_SAFELUT_LOW */ + .value = 0x000F, + }, + .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 = 0x1B88, /* IFE_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE0_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E48, /* IPE0_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 = 0x1F08, /* IPE0_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE1_BPS_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2448, /* IPE1_BPS_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 = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2848, /* IPE_BPS_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 = 0x2988, /* IPE_BPS_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 = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E38, /* JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .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 cam480_custom_err_logger_offsets = { + .mainctrl = 0x7008, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x7010, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x7020, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x7024, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x7028, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x702c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x7030, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x7034, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x7038, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x703c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam480_custom_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 cam480_custom_camnoc_info = { + .specific = &cam_cpas_v480_custom_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v480_custom_camnoc_specific), + .irq_sbm = &cam_cpas_v480_custom_irq_sbm, + .irq_err = &cam_cpas_v480_custom_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v480_custom_irq_err), + .err_logger = &cam480_custom_err_logger_offsets, + .errata_wa_list = &cam480_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP_V480_CUSTOM_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h new file mode 100644 index 000000000000..4b97ee206ed2 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h @@ -0,0 +1,791 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V580_CUSTOM_H_ +#define _CPASTOP_V580_CUSTOM_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v580_custom_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3840, /* SBM_FAULTINEN0_LOW */ + .value = 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + 0x1000 | /* SBM_FAULTINEN0_LOW_PORT12_MASK */ + (TEST_IRQ_ENABLE ? + 0x40 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3848, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x3880, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x5 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v580_custom_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = false, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x7008, /* ERL_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x7010, /* ERL_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x7018, /* ERL_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x1BA0, /* IFE_UBWC_STATS_0_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1B90, + /* IFE_UBWC_STATS_0_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1B98, /* IFE_UBWC_STATS_0_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2520, /* IPE1_BPS_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2510, /* IPE1_BPS_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2518, /* IPE1_BPS_RD_DECERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE0_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 = 0x1F20, /* IPE0_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1F10, /* IPE0_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1F18, /* IPE0_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 = 0x29A0, /* IPE_BPS_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2990, + /* IPE_BPS_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2998, /* IPE_BPS_WR_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = false, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* 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 = 0x40, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x1000, /* SBM_FAULTINSTATUS0_LOW_PORT12_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x77A0, /* IFE_UBWC_STATS_1_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x7790, + /* IFE_UBWC_STATS_1_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x7798, /* IFE_UBWC_STATS_1_ENCERRCLR_LOW */ + .value = 1, + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v580_custom_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* CDM_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_RDI_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1048, /* IFE_RDI_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, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_RDI_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* IFE_RDI_WR_0_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1438, /* IFE_RDI_WR_0_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1440, /* IFE_RDI_WR_0_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_RDI_WR_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7430, /* IFE_RDI_WR_1_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7434, /* IFE_RDI_WR_1_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7438, /* IFE_RDI_WR_1_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7440, /* IFE_RDI_WR_1_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7448, /* IFE_RDI_WR_1_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_UBWC_STATS, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A34, + /* IFE_UBWC_STATS_0_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A38, /* IFE_UBWC_STATS_0_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A40, /* IFE_UBWC_STATS_0_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A48, /* IFE_UBWC_STATS_0_SAFELUT_LOW */ + .value = 0x000F, + }, + .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 = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_UBWC_STATS_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7630, /* IFE_UBWC_STATS_1_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7634, + /* IFE_UBWC_STATS_1_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7638, /* IFE_UBWC_STATS_1_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7640, /* IFE_UBWC_STATS_1_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x7648, /* IFE_UBWC_STATS_1_SAFELUT_LOW */ + .value = 0x000F, + }, + .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 = 0x7788, /* IFE_UBWC_STATS_1_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE0_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E48, /* IPE0_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 = 0x1F08, /* IPE0_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE1_BPS_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2448, /* IPE1_BPS_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 = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2848, /* IPE_BPS_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 = 0x2988, /* IPE_BPS_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 = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E38, /* JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .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 = 0x3888, + .value = 0x100000, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam580_custom_err_logger_offsets = { + .mainctrl = 0x7008, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x7010, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x7020, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x7024, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x7028, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x702c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x7030, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x7034, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x7038, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x703c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam580_custom_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x3900, /* sbm_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam580_custom_camnoc_info = { + .specific = &cam_cpas_v580_custom_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v580_custom_camnoc_specific), + .irq_sbm = &cam_cpas_v580_custom_irq_sbm, + .irq_err = &cam_cpas_v580_custom_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v580_custom_irq_err), + .err_logger = &cam580_custom_err_logger_offsets, + .errata_wa_list = &cam580_custom_errata_wa_list, +}; + +#endif /* _CPASTOP_V580_CUSTOM_H_ */ + diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 9601166c2afe..dd8f4db577f4 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -20,6 +20,10 @@ #define CAM_CPAS_MAX_PATHS_PER_CLIENT 15 #define CAM_CPAS_API_PATH_DATA_STD_START 512 +/* Qos Selection mask */ +#define CAM_CPAS_QOS_DEFAULT_SETTINGS_MASK 0x1 +#define CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK 0x2 + /** * enum cam_cpas_reg_base - Enum for register base identifier. These * are the identifiers used in generic register @@ -638,4 +642,14 @@ const char *cam_cpas_axi_util_trans_type_to_string( */ void cam_cpas_log_votes(void); +/** + * cam_cpas_select_qos_settings() + * + * @brief: API to select specific qos settings based on usecase requirements + * + * @return 0 on success. + * + */ +int cam_cpas_select_qos_settings(uint32_t selection_mask); + #endif /* _CAM_CPAS_API_H_ */ diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c index 9011ac9d5291..b7322b2af66d 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -55,10 +55,21 @@ int cam_custom_hw_sub_mod_init_soc_resources(struct cam_hw_soc_info *soc_info, soc_private->cpas_handle = cpas_register_param.client_handle; + rc = cam_cpas_select_qos_settings(CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK); + if (rc) { + CAM_ERR(CAM_CPAS, "Custom QoS selection failed %d", rc); + goto unregister_cpas; + } + return rc; +unregister_cpas: + if (cam_cpas_unregister_client(soc_private->cpas_handle)) + CAM_ERR(CAM_CUSTOM, "CPAS0 unregistration failed"); release_soc: - cam_soc_util_release_platform_resource(soc_info); + if (cam_soc_util_release_platform_resource(soc_info)) + CAM_ERR(CAM_CUSTOM, "CPAS0 release resource failed"); + return rc; } From 54f5035aa7f30e8eb0dd250ea867880e73162a5b Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Sun, 24 May 2020 17:06:42 -0700 Subject: [PATCH 376/790] msm: camera: custom: Add dt matching string for spectra580 csid Add dt matching string to probe spectra580 custom csid device. CRs-Fixed: 2687917 Change-Id: Ibf220dd88dfad76742b71e7550f6b50ff6b2f57e Signed-off-by: Pavan Kumar Chilamkurthi --- .../cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c index 724d047fa0de..a4cee0f200d2 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_csid/cam_custom_csid_dev.c @@ -165,6 +165,10 @@ static const struct of_device_id cam_custom_csid_dt_match[] = { .compatible = "qcom,csid-custom480", .data = &cam_custom_csid480_hw_info }, + { + .compatible = "qcom,csid-custom580", + .data = &cam_custom_csid480_hw_info + }, {} }; From bb88411486df12ede86124dc27da8876169407bd Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 26 Mar 2020 13:24:42 +0530 Subject: [PATCH 377/790] msm: camera: isp: validate in_port before accessing in_port information we are getting from the UMD and accessing it directly without validation which might lead to corruption and device failure. CRs-Fixed: 2629969 Change-Id: I0a1c57db9b94f9657427872ae6797635c6aed668 Signed-off-by: Tejas Prajapati --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 50 ++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index df5c9a2e2c85..ca621c9d99bd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2110,18 +2110,36 @@ err: static int cam_ife_mgr_check_and_update_fe_v0( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_acquire_hw_info *acquire_hw_info) + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t acquire_info_size) { int i; struct cam_isp_in_port_info *in_port = NULL; uint32_t in_port_length = 0; uint32_t total_in_port_length = 0; + if (acquire_hw_info->input_info_offset >= + acquire_hw_info->input_info_size) { + CAM_ERR(CAM_ISP, + "Invalid size offset 0x%x is greater then size 0x%x", + acquire_hw_info->input_info_offset, + acquire_hw_info->input_info_size); + return -EINVAL; + } + 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++) { + if (((uint8_t *)in_port + + sizeof(struct cam_isp_in_port_info)) > + ((uint8_t *)acquire_hw_info + + acquire_info_size)) { + CAM_ERR(CAM_ISP, "Invalid size"); + return -EINVAL; + } + if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", @@ -2155,18 +2173,36 @@ static int cam_ife_mgr_check_and_update_fe_v0( static int cam_ife_mgr_check_and_update_fe_v2( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_acquire_hw_info *acquire_hw_info) + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t acquire_info_size) { int i; struct cam_isp_in_port_info_v2 *in_port = NULL; uint32_t in_port_length = 0; uint32_t total_in_port_length = 0; + if (acquire_hw_info->input_info_offset >= + acquire_hw_info->input_info_size) { + CAM_ERR(CAM_ISP, + "Invalid size offset 0x%x is greater then size 0x%x", + acquire_hw_info->input_info_offset, + acquire_hw_info->input_info_size); + return -EINVAL; + } + in_port = (struct cam_isp_in_port_info_v2 *) ((uint8_t *)&acquire_hw_info->data + acquire_hw_info->input_info_offset); for (i = 0; i < acquire_hw_info->num_inputs; i++) { + if (((uint8_t *)in_port + + sizeof(struct cam_isp_in_port_info)) > + ((uint8_t *)acquire_hw_info + + acquire_info_size)) { + CAM_ERR(CAM_ISP, "Invalid size"); + return -EINVAL; + } + if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", @@ -2203,7 +2239,8 @@ static int cam_ife_mgr_check_and_update_fe_v2( 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) + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t acquire_info_size) { uint32_t major_ver = 0, minor_ver = 0; @@ -2216,10 +2253,10 @@ static int cam_ife_mgr_check_and_update_fe( switch (major_ver) { case 1: return cam_ife_mgr_check_and_update_fe_v0( - ife_ctx, acquire_hw_info); + ife_ctx, acquire_hw_info, acquire_info_size); case 2: return cam_ife_mgr_check_and_update_fe_v2( - ife_ctx, acquire_hw_info); + ife_ctx, acquire_hw_info, acquire_info_size); break; default: CAM_ERR(CAM_ISP, "Invalid ver of common info from user"); @@ -3014,7 +3051,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; - rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info); + rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info, + acquire_args->acquire_info_size); if (rc) { CAM_ERR(CAM_ISP, "buffer size is not enough"); goto free_cdm; From 9f3787106469efcbe15f0a6ee80321ed1cd46360 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 11 May 2020 11:37:23 -0700 Subject: [PATCH 378/790] msm: camera: reqmgr: Add provision in UAPI for INIT exp timeout Add provision in CRM link control to accept any long exposure timeout value so that CRM can modify it's internal WD timer during link activate. CRs-Fixed: 2706105 Change-Id: Icedeeef32dcc5c881277f28dc2c0fbb40fa1e7f1 Signed-off-by: Karthik Anantha Ram --- include/uapi/camera/media/cam_req_mgr.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 80a52fb01504..23ced4dbcb48 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -233,6 +233,9 @@ struct cam_req_mgr_sync_mode { * @session_hdl: Input param - Identifier for CSL session * @num_links: Input Param - Num of links * @reserved: reserved field + * @init_timeout: To account for INIT exposure settings (ms) + * If there is no change in exp settings + * field needs to assigned to 0ms. * @link_hdls: Input Param - Links to be activated/deactivated * * @opcode: CAM_REQ_MGR_LINK_CONTROL @@ -242,6 +245,7 @@ struct cam_req_mgr_link_control { __s32 session_hdl; __s32 num_links; __s32 reserved; + __s32 init_timeout[MAX_LINKS_PER_SESSION]; __s32 link_hdls[MAX_LINKS_PER_SESSION]; }; From 6addc5d8b5eb164aa52c239b14fb7b933e2d7cae Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 8 Jun 2020 18:48:14 -0700 Subject: [PATCH 379/790] msm: camera: isp: Unmask CSI RX IRQs In stop immediate currently only the CSID path is reset, the RX is still capable of listening to IRQs. Unmask this in stop and enable them again at start. CRs-Fixed: 2698391 Change-Id: Iacdc9d241192e976b61728314a83d445534234c6 Signed-off-by: Karthik Anantha Ram Signed-off-by: Vishalsingh Hajeri --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 126 ++++++++++-------- 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 54b441424ca1..2271210f948e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1541,6 +1541,71 @@ static int cam_ife_csid_config_tpg(struct cam_ife_csid_hw *csid_hw, return 0; } +static int cam_ife_csid_csi2_irq_ctrl( + struct cam_ife_csid_hw *csid_hw, + bool irq_enable) +{ + uint32_t val = 0; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (irq_enable) { + /*Enable the CSI2 rx interrupts */ + val = CSID_CSI2_RX_INFO_RST_DONE | + CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW | + CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION | + CSID_CSI2_RX_ERROR_CRC | + CSID_CSI2_RX_ERROR_ECC | + CSID_CSI2_RX_ERROR_MMAPPED_VC_DT | + CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW | + CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME | + CSID_CSI2_RX_ERROR_CPHY_PH_CRC; + + if (csid_hw->epd_supported == 1) + CAM_INFO(CAM_ISP, + "Disable CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION for EPD"); + else + val = val | CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION; + + /* Enable the interrupt based on csid debug info set */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOT_IRQ) + val |= CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) + val |= CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED | + CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) + val |= CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) + val |= CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED; + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) + val |= CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED; + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + } else { + /* Disable the CSI2 rx inerrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + } + + return 0; +} + static int cam_ife_csid_enable_csi2( struct cam_ife_csid_hw *csid_hw, struct cam_isp_resource_node *res) @@ -1601,51 +1666,7 @@ static int cam_ife_csid_enable_csi2( } } - /*Enable the CSI2 rx interrupts */ - val = CSID_CSI2_RX_INFO_RST_DONE | - CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW | - CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW | - CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW | - CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW | - CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW | - CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION | - CSID_CSI2_RX_ERROR_CRC | - CSID_CSI2_RX_ERROR_ECC | - CSID_CSI2_RX_ERROR_MMAPPED_VC_DT | - CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW | - CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME | - CSID_CSI2_RX_ERROR_CPHY_PH_CRC; - - if (csid_hw->epd_supported == 1) - CAM_INFO(CAM_ISP, - "Disable CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION for EPD"); - else - val = val | CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION; - - /* Enable the interrupt based on csid debug info set */ - if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOT_IRQ) - val |= CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED | - CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED | - CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED | - CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED; - - if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) - val |= CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED | - CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED | - CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED | - CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED; - - if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) - val |= CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED; - - if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) - val |= CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED; - if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) - val |= CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED; - - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + - csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); - + cam_ife_csid_csi2_irq_ctrl(csid_hw, true); return 0; } @@ -1673,9 +1694,7 @@ static int cam_ife_csid_disable_csi2( if (csid_hw->csi2_cfg_cnt) return 0; - /* Disable the CSI2 rx inerrupts */ - cam_io_w_mb(0, soc_info->reg_map[0].mem_base + - csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + cam_ife_csid_csi2_irq_ctrl(csid_hw, false); /* Reset the Rx CFG registers */ cam_io_w_mb(0, soc_info->reg_map[0].mem_base + @@ -3588,6 +3607,8 @@ int cam_ife_csid_start(void *hw_priv, void *start_args, csid_hw->irq_debug_cnt = 0; spin_lock_irqsave(&csid_hw->lock_state, flags); + if (!csid_hw->device_enabled) + cam_ife_csid_csi2_irq_ctrl(csid_hw, true); csid_hw->device_enabled = 1; spin_unlock_irqrestore(&csid_hw->lock_state, flags); @@ -3659,6 +3680,11 @@ int cam_ife_csid_stop(void *hw_priv, csid_hw->hw_intf->hw_idx, csid_stop->num_res); + spin_lock_irqsave(&csid_hw->lock_state, flags); + csid_hw->device_enabled = 0; + cam_ife_csid_csi2_irq_ctrl(csid_hw, false); + spin_unlock_irqrestore(&csid_hw->lock_state, flags); + /* Stop the resource first */ for (i = 0; i < csid_stop->num_res; i++) { res = csid_stop->node_res[i]; @@ -3702,10 +3728,6 @@ int cam_ife_csid_stop(void *hw_priv, } } - spin_lock_irqsave(&csid_hw->lock_state, flags); - csid_hw->device_enabled = 0; - spin_unlock_irqrestore(&csid_hw->lock_state, flags); - if (res_mask) rc = cam_ife_csid_poll_stop_status(csid_hw, res_mask); From 24e6de881cbbb46ae3aef5794fb8fb4d77a3364b Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 29 Apr 2020 11:52:35 +0530 Subject: [PATCH 380/790] msm: camera: reqmgr: Modify SOF watchlog timer for INIT exposure In case of long exposure shots, watchdog timer needs to be modified for init exposure seeting also to avoid trigger. CRs-Fixed: 2706105 Change-Id: Ife8b3ec32103aff71d281e11b68e0d48f4ef79e1 Signed-off-by: Chandan Kumar Jha --- drivers/cam_req_mgr/cam_req_mgr_core.c | 21 +++++++++++++++++---- drivers/cam_req_mgr/cam_req_mgr_core.h | 3 +++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index aaa10827fba6..a236bc57b275 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -50,6 +50,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->sof_timestamp = 0; link->prev_sof_timestamp = 0; link->enable_apply_default = false; + link->skip_init_frame = false; atomic_set(&link->eof_event_cnt, 0); } @@ -561,6 +562,13 @@ static void __cam_req_mgr_validate_crm_wd_timer( int next_frame_timeout = 0, current_frame_timeout = 0; struct cam_req_mgr_req_queue *in_q = link->req.in_q; + if (link->skip_init_frame) { + CAM_DBG(CAM_CRM, + "skipping modifying wd timer for first frame after streamon"); + link->skip_init_frame = false; + return; + } + idx = in_q->rd_idx; __cam_req_mgr_dec_idx( &idx, (link->max_delay - 1), @@ -599,8 +607,8 @@ static void __cam_req_mgr_validate_crm_wd_timer( crm_timer_modify(link->watchdog, current_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT); - } else if (link->watchdog->expires > - CAM_REQ_MGR_WATCHDOG_TIMEOUT) { + } else if (!next_frame_timeout && (link->watchdog->expires > + CAM_REQ_MGR_WATCHDOG_TIMEOUT)) { CAM_DBG(CAM_CRM, "Reset wd timer to default from %d ms to %d ms", link->watchdog->expires, @@ -4045,6 +4053,7 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) struct cam_req_mgr_connected_device *dev = NULL; struct cam_req_mgr_link_evt_data evt_data; + int init_timeout = 0; if (!control) { CAM_ERR(CAM_CRM, "Control command is NULL"); @@ -4076,10 +4085,13 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_READY; spin_unlock_bh(&link->link_state_spin_lock); + if (control->init_timeout[i]) + link->skip_init_frame = true; + init_timeout = (2 * control->init_timeout[i]); /* Start SOF watchdog timer */ rc = crm_timer_init(&link->watchdog, - CAM_REQ_MGR_WATCHDOG_TIMEOUT_DEFAULT, link, - &__cam_req_mgr_sof_freeze); + (init_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT), + link, &__cam_req_mgr_sof_freeze); if (rc < 0) { CAM_ERR(CAM_CRM, "SOF timer start fails: link=0x%x", @@ -4110,6 +4122,7 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) /* Destroy SOF watchdog timer */ spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_IDLE; + link->skip_init_frame = false; crm_timer_exit(&link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); } else { diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index b21fc00f6bd0..6a806f192542 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -369,6 +369,8 @@ struct cam_req_mgr_connected_device { * frames where actual settings are not available. * This will account for all devices irrespective of * pipeline delay + * @skip_init_frame : skip initial frames crm_wd_timer validation in the + * case of long exposure use case */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -403,6 +405,7 @@ struct cam_req_mgr_core_link { uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; atomic_t eof_event_cnt; bool enable_apply_default; + bool skip_init_frame; }; /** From 7d3f7b71b65d4aa54c7b5190c8c51a33b115a399 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Wed, 6 May 2020 02:03:55 -0700 Subject: [PATCH 381/790] msm: camera: cdm: Add CDM cmd_type WAIT in dump util CDM comp_wait is the new cmd_type used by IFE Master to wait for trigger from slave. Add this type to the dump command buffer routine. CRs-Fixed: 2679783 Change-Id: I142cbd849141725cc05f3276c20ea1c0d59f7c3c Signed-off-by: Vishalsingh Hajeri --- drivers/cam_cdm/cam_cdm_util.c | 25 ++++++++++++++++++++++--- drivers/cam_cdm/cam_cdm_util.h | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_util.c b/drivers/cam_cdm/cam_cdm_util.c index 117680a5f8a0..67b584066a08 100644 --- a/drivers/cam_cdm/cam_cdm_util.c +++ b/drivers/cam_cdm/cam_cdm_util.c @@ -229,7 +229,7 @@ uint32_t cdm_required_size_changebase(void) uint32_t cdm_required_size_comp_wait(void) { - return cdm_get_cmd_header_size(CAM_CDM_COMP_WAIT); + return cdm_get_cmd_header_size(CAM_CDM_CMD_COMP_WAIT); } uint32_t cdm_required_size_clear_comp_event(void) @@ -387,11 +387,11 @@ uint32_t *cdm_write_wait_comp_event( struct cdm_wait_comp_event_cmd *pHeader = (struct cdm_wait_comp_event_cmd *)pCmdBuffer; - pHeader->cmd = CAM_CDM_COMP_WAIT; + pHeader->cmd = CAM_CDM_CMD_COMP_WAIT; pHeader->mask1 = mask1; pHeader->mask2 = mask2; - pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_COMP_WAIT); + pCmdBuffer += cdm_get_cmd_header_size(CAM_CDM_CMD_COMP_WAIT); return pCmdBuffer; } @@ -793,6 +793,17 @@ static long cam_cdm_util_dump_change_base_cmd(uint32_t *cmd_buf_addr) return ret; } +static long cam_cdm_util_dump_comp_wait_event_cmd(uint32_t *cmd_buf_addr) +{ + long ret = 0; + + ret += CDMCmdHeaderSizes[CAM_CDM_CMD_COMP_WAIT]; + + CAM_INFO(CAM_CDM, "WAIT_EVENT"); + + return ret; +} + static long cam_cdm_util_dump_perf_ctrl_cmd(uint32_t *cmd_buf_addr) { long ret = 0; @@ -846,6 +857,10 @@ void cam_cdm_util_dump_cmd_buf( case CAM_CDM_CMD_PERF_CTRL: buf_now += cam_cdm_util_dump_perf_ctrl_cmd(buf_now); break; + case CAM_CDM_CMD_COMP_WAIT: + buf_now += + cam_cdm_util_dump_comp_wait_event_cmd(buf_now); + break; default: CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x", cmd, *buf_now); @@ -1014,6 +1029,10 @@ int cam_cdm_util_dump_cmd_bufs_v2( buf_now += cdm_get_cmd_header_size( CAM_CDM_CMD_PERF_CTRL); break; + case CAM_CDM_CMD_COMP_WAIT: + buf_now += cdm_get_cmd_header_size( + CAM_CDM_CMD_COMP_WAIT); + break; default: CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x", cmd); buf_now++; diff --git a/drivers/cam_cdm/cam_cdm_util.h b/drivers/cam_cdm/cam_cdm_util.h index ff613c44f8c3..7e5f9d7edd11 100644 --- a/drivers/cam_cdm/cam_cdm_util.h +++ b/drivers/cam_cdm/cam_cdm_util.h @@ -24,7 +24,7 @@ enum cam_cdm_command { CAM_CDM_CMD_PERF_CTRL = 0x9, CAM_CDM_CMD_DMI_32 = 0xa, CAM_CDM_CMD_DMI_64 = 0xb, - CAM_CDM_COMP_WAIT = 0xc, + CAM_CDM_CMD_COMP_WAIT = 0xc, CAM_CDM_CLEAR_COMP_WAIT = 0xd, CAM_CDM_WAIT_PREFETCH_DISABLE = 0xe, CAM_CDM_CMD_PRIVATE_BASE = 0xf, From 0181a16f13a02f9beaf3cca35b63c33a5a365d82 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 11 Jun 2020 16:39:32 -0700 Subject: [PATCH 382/790] msm: camera: isp: Disable clk gating in IFE top Disable auto clk gating for all core clocks, ahb & NOC. CRs-Fixed: 2705869 Change-Id: I74ad58e1c8308edcd19ac6414a25a0f7fafce3cd Signed-off-by: Karthik Anantha Ram --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 6a66955ed280..adbd880eabc8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -366,23 +366,20 @@ int cam_vfe_top_ver3_init_hw(void *device_priv, top_priv->hw_clk_rate = 0; - /** - * Auto clock gating is enabled by default, but no harm - * in setting the value we expect. - */ - CAM_DBG(CAM_ISP, "Enabling clock gating at IFE top"); + /* Disable clock gating at IFE top */ + CAM_DBG(CAM_ISP, "Disable clock gating at IFE top"); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->core_cgc_ovd_0, 0x0); + common_data.common_reg->core_cgc_ovd_0, 0xFFFFFFFF); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->core_cgc_ovd_1, 0x0); + common_data.common_reg->core_cgc_ovd_1, 0xFF); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->ahb_cgc_ovd, 0x0); + common_data.common_reg->ahb_cgc_ovd, 0x1); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->noc_cgc_ovd, 0x0); + common_data.common_reg->noc_cgc_ovd, 0x1); top_priv->top_common.hw_version = cam_io_r_mb(common_data.soc_info->reg_map[0].mem_base + From 1435a8a68b24fe0c45f23a44ac1fce10fc463957 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Thu, 2 Apr 2020 20:43:26 +0530 Subject: [PATCH 383/790] msm: camera: sensor: Dump phy registers on error Dump csiphy registers on following fatal errors: 1. lane overflow error 2. unbounded frame error 3. SOT ans EOT reception error 4. stream underflow error These errors irqs are set at csid end, Currently there is no interface to send message from one subdevice to other if the subdev is not a real time device. This change adds an interface to notify the no real time subdev. CRs-Fixed: 2696744 Change-Id: I522167d1639ac298bc739a8a5a380a01356f0776 Signed-off-by: Vishal Verma Signed-off-by: Jigar Agrawal --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 5 ++ .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 8 ++++ drivers/cam_req_mgr/cam_req_mgr_dev.c | 20 +++++++- drivers/cam_req_mgr/cam_subdev.h | 22 +++++++++ .../cam_csiphy/cam_csiphy_dev.c | 21 ++++++++ .../cam_csiphy/cam_csiphy_dev.h | 1 + .../cam_csiphy/cam_csiphy_soc.c | 48 +++++++++++++++++++ .../cam_csiphy/cam_csiphy_soc.h | 6 +++ .../cam_csiphy/include/cam_csiphy_1_0_hwreg.h | 3 +- .../cam_csiphy/include/cam_csiphy_1_1_hwreg.h | 3 +- .../include/cam_csiphy_1_2_1_hwreg.h | 1 + .../include/cam_csiphy_1_2_2_hwreg.h | 1 + .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 3 +- .../cam_csiphy/include/cam_csiphy_2_0_hwreg.h | 1 + 14 files changed, 139 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 54b441424ca1..ac6c2a5d543b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -9,6 +9,7 @@ #include #include +#include #include #include "cam_ife_csid_core.h" @@ -17,6 +18,7 @@ #include "cam_io_util.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include "cam_subdev.h" /* Timeout value in msec */ #define IFE_CSID_TIMEOUT 1000 @@ -1708,6 +1710,9 @@ static void cam_ife_csid_halt_csi2( csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + csid_hw->csi2_rx_cfg.phy_sel); } static int cam_ife_csid_init_config_pxl_path( diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index ddad24cd23df..6b896a0beb84 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "cam_tfe_csid_core.h" #include "cam_isp_hw.h" @@ -15,6 +16,7 @@ #include "cam_debug_util.h" #include "cam_cpas_api.h" #include "cam_isp_hw_mgr_intf.h" +#include "cam_subdev.h" /* Timeout value in msec */ #define TFE_CSID_TIMEOUT 1000 @@ -2585,6 +2587,12 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + /* phy_sel starts from 1 and should never be zero*/ + if (csid_hw->csi2_rx_cfg.phy_sel > 0) { + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + (csid_hw->csi2_rx_cfg.phy_sel - 1)); + } } if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOT_IRQ) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 555ad537b830..cc9139e289b0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -640,6 +640,24 @@ void cam_video_device_cleanup(void) g_dev.video = NULL; } +void cam_subdev_notify_message(u32 subdev_type, + enum cam_subdev_message_type_t message_type, + uint32_t data) +{ + struct v4l2_subdev *sd = NULL; + struct cam_subdev *csd = NULL; + + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + sd->entity.name = video_device_node_name(sd->devnode); + if (sd->entity.function == subdev_type) { + csd = container_of(sd, struct cam_subdev, sd); + if (csd->msg_cb != NULL) + csd->msg_cb(sd, message_type, data); + } + } +} +EXPORT_SYMBOL(cam_subdev_notify_message); + int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -660,7 +678,7 @@ int cam_register_subdev(struct cam_subdev *csd) sd = &csd->sd; v4l2_subdev_init(sd, csd->ops); sd->internal_ops = csd->internal_ops; - snprintf(sd->name, ARRAY_SIZE(sd->name), csd->name); + snprintf(sd->name, V4L2_SUBDEV_NAME_SIZE, "%s", csd->name); v4l2_set_subdevdata(sd, csd->token); sd->flags = csd->sd_flags; diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index 1b2d146fa2fe..c2ded0c9103e 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -16,6 +16,10 @@ #define CAM_SUBDEVICE_EVENT_MAX 30 +enum cam_subdev_message_type_t { + CAM_SUBDEV_MESSAGE_IRQ_ERR = 0x1 +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -49,8 +53,26 @@ struct cam_subdev { u32 sd_flags; void *token; u32 ent_function; + void (*msg_cb)( + struct v4l2_subdev *sd, + enum cam_subdev_message_type_t msg_type, + uint32_t data); }; +/** + * cam_subdev_notify_message() + * + * @brief: Notify message to a subdevs of specific type + * + * @subdev_type: Subdev type + * @message_type: message type + * @data: data to be delivered. + * + */ +void cam_subdev_notify_message(u32 subdev_type, + enum cam_subdev_message_type_t message_type, + uint32_t data); + /** * cam_subdev_probe() * diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 2a6abfc30665..ebfd041d13bf 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -10,6 +10,25 @@ #include #include "camera_main.h" +static void cam_csiphy_subdev_handle_message( + struct v4l2_subdev *sd, + enum cam_subdev_message_type_t message_type, + uint32_t data) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + + switch (message_type) { + case CAM_SUBDEV_MESSAGE_IRQ_ERR: + CAM_INFO(CAM_CSIPHY, "subdev index : %d CSIPHY index: %d", + csiphy_dev->soc_info.index, data); + if (data == csiphy_dev->soc_info.index) + cam_csiphy_status_dmp(csiphy_dev); + break; + default: + break; + } +} + static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -151,6 +170,8 @@ static int cam_csiphy_component_bind(struct device *dev, (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); new_csiphy_dev->v4l2_dev_str.ent_function = CAM_CSIPHY_DEVICE_TYPE; + new_csiphy_dev->v4l2_dev_str.msg_cb = + cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index c88b109a5db4..ac5a017b151e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -106,6 +106,7 @@ struct csiphy_reg_parms_t { uint32_t mipi_csiphy_interrupt_mask_addr; uint32_t mipi_csiphy_interrupt_clear0_addr; uint32_t csiphy_version; + uint32_t csiphy_interrupt_status_size; uint32_t csiphy_common_array_size; uint32_t csiphy_reset_array_size; uint32_t csiphy_2ph_config_array_size; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 89686a3b0088..bedd0570b4e0 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -78,6 +78,54 @@ int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info) return rc; } +int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) +{ + struct csiphy_reg_parms_t *csiphy_reg = NULL; + int32_t rc = 0; + resource_size_t size = 0; + void __iomem *phy_base = NULL; + int reg_id = 0; + uint32_t irq, status_reg, clear_reg; + + if (!csiphy_dev) { + rc = -EINVAL; + CAM_ERR(CAM_CSIPHY, "invalid input %d", rc); + return rc; + } + + csiphy_reg = &csiphy_dev->ctrl_reg->csiphy_reg; + phy_base = csiphy_dev->soc_info.reg_map[0].mem_base; + status_reg = csiphy_reg->mipi_csiphy_interrupt_status0_addr; + clear_reg = csiphy_reg->mipi_csiphy_interrupt_clear0_addr; + size = csiphy_reg->csiphy_interrupt_status_size; + + CAM_INFO(CAM_CSIPHY, "PHY base addr=%pK offset=0x%x size=%d", + phy_base, status_reg, size); + + if (phy_base != NULL) { + for (reg_id = 0; reg_id < size; reg_id++) { + uint32_t offset; + + offset = status_reg + (0x4 * reg_id); + irq = cam_io_r(phy_base + offset); + offset = clear_reg + (0x4 * reg_id); + cam_io_w_mb(irq, phy_base + offset); + cam_io_w_mb(0, phy_base + offset); + + CAM_INFO(CAM_CSIPHY, + "CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x", + csiphy_dev->soc_info.index, reg_id, irq); + } + } else { + rc = -EINVAL; + CAM_ERR(CAM_CSIPHY, "phy base is NULL %d", rc); + return rc; + } + return rc; +} + + + enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev) { CAM_DBG(CAM_CSIPHY, "voting for SVS"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 1f08193de2a6..0416d8cda66d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -72,4 +72,10 @@ int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev); */ int cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info); +/** + * @csiphy_dev: CSIPhy device structure + * + * This API dumps memory for the entire status region + */ +int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev); #endif /* _CAM_CSIPHY_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h index e910162858b3..eaedc7b672a8 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_0_HWREG_H_ @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_0 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 5, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 14, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h index 30b61067a792..e1db638da5f0 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_1_HWREG_H_ @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_1 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 5, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 14, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index c9fb93f7e9bd..8bf373677a51 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 20, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h index 119b6b575b60..00e6bb30392b 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 18, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 179ccebddc54..446c8197df8a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_HWREG_H_ @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 18, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h index 9549919e2ea7..f7be2b60a4b5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h @@ -12,6 +12,7 @@ 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_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 15, From 1268c5ae4059bf85d9ac4572f0c2e92a4b7882a2 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 15 Jun 2020 11:09:29 -0700 Subject: [PATCH 384/790] msm: camera: csid: Add CSID Number in CSID ISR Logs Add CSID Number for RDI and UDI paths in CSID ISR for better debugging purpose. CRs-Fixed: 2709537 Change-Id: Ie8e70addaa282a07feb38597dba9a3abdec77707 Signed-off-by: Jigar Agrawal --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 2271210f948e..eadaf2e99f34 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -861,9 +861,10 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_IPP: if (csid_hw->ipp_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, - "CSID:%d IPP resource not available", - csid_hw->hw_intf->hw_idx); + CAM_DBG(CAM_ISP, + "CSID:%d IPP resource not available state %d", + csid_hw->hw_intf->hw_idx, + csid_hw->ipp_res.res_state); rc = -EINVAL; goto end; } @@ -871,7 +872,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_PPP: if (csid_hw->ppp_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, + CAM_DBG(CAM_ISP, "CSID:%d PPP resource not available state %d", csid_hw->hw_intf->hw_idx, csid_hw->ppp_res.res_state); @@ -885,10 +886,11 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, case CAM_IFE_PIX_PATH_RES_RDI_3: if (csid_hw->rdi_res[cid_reserv->res_id].res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, - "CSID:%d RDI:%d resource not available", + CAM_DBG(CAM_ISP, + "CSID:%d RDI:%d resource not available state:%d", csid_hw->hw_intf->hw_idx, - cid_reserv->res_id); + cid_reserv->res_id, + csid_hw->rdi_res[cid_reserv->res_id].res_state); rc = -EINVAL; goto end; } @@ -899,10 +901,11 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, id = cid_reserv->res_id - CAM_IFE_PIX_PATH_RES_UDI_0; if (csid_hw->udi_res[id].res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, - "CSID:%d UDI:%d resource not available", + CAM_DBG(CAM_ISP, + "CSID:%d UDI:%d resource not available state:%d", csid_hw->hw_intf->hw_idx, - cid_reserv->res_id); + cid_reserv->res_id, + csid_hw->udi_res[id].res_state); rc = -EINVAL; goto end; } @@ -4308,7 +4311,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) /* IPP reset done bit */ if (irq_status_ipp & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { - CAM_DBG(CAM_ISP, "CSID IPP reset complete"); + CAM_DBG(CAM_ISP, "CSID:%d IPP reset complete", + csid_hw->hw_intf->hw_idx); complete(&csid_hw->csid_ipp_complete); } @@ -4351,7 +4355,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) /* PPP reset done bit */ if (irq_status_ppp & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { - CAM_DBG(CAM_ISP, "CSID PPP reset complete"); + CAM_DBG(CAM_ISP, "CSID:%d PPP reset complete", + csid_hw->hw_intf->hw_idx); complete(&csid_hw->csid_ppp_complete); } @@ -4392,14 +4397,16 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { if (irq_status_rdi[i] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { - CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i); + CAM_DBG(CAM_ISP, "CSID:%d RDI%d reset complete", + csid_hw->hw_intf->hw_idx, i); complete(&csid_hw->csid_rdin_complete[i]); } if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI:%d SOF received", i); + "CSID:%d RDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -4407,16 +4414,18 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI:%d EOF received", i); + "CSID:%d RDI:%d EOF received", + csid_hw->hw_intf->hw_idx, i); if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI :%d CCIF violation", i); + "CSID:%d RDI :%d CCIF violation", + csid_hw->hw_intf->hw_idx, i); if ((irq_status_rdi[i] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI :%d Overflow due to back pressure", - i); + "CSID:%d RDI :%d Overflow due to back pressure", + csid_hw->hw_intf->hw_idx, i); if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, @@ -4432,14 +4441,16 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { if (irq_status_udi[i] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { - CAM_DBG(CAM_ISP, "CSID UDI%d reset complete", i); + CAM_DBG(CAM_ISP, "CSID:%d UDI%d reset complete", + csid_hw->hw_intf->hw_idx, i); complete(&csid_hw->csid_udin_complete[i]); } if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID UDI:%d SOF received", i); + "CSID:%d UDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -4447,16 +4458,18 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID UDI:%d EOF received", i); + "CSID:%d UDI:%d EOF received", + csid_hw->hw_intf->hw_idx, i); if ((irq_status_udi[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_WARN_RATE_LIMIT(CAM_ISP, - "CSID UDI :%d CCIF violation", i); + "CSID:%d UDI :%d CCIF violation", + csid_hw->hw_intf->hw_idx, i); if ((irq_status_udi[i] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_WARN_RATE_LIMIT(CAM_ISP, - "CSID UDI :%d Overflow due to back pressure", - i); + "CSID:%d UDI :%d Overflow due to back pressure", + csid_hw->hw_intf->hw_idx, i); if (irq_status_udi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, From 968d954b756528a351baf1486f98ea3d688ddd77 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 7 May 2020 15:00:01 -0700 Subject: [PATCH 385/790] msm: camera: utils: Add logic to maintain unique buffer handle for patch Currently smmu_get_iova is called for every patch, regardless of the same source handle. This change avoids this by checking if io virtual address is already being quried with earlier patch. This can reduce the call and mutex operation from smmu prospective. CRs-Fixed: 2711810 Change-Id: I681589cd1328389e0828a3318edad1a2a91d8547 Signed-off-by: Jigarkumar Zala --- drivers/cam_utils/cam_packet_util.c | 97 +++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 11 deletions(-) diff --git a/drivers/cam_utils/cam_packet_util.c b/drivers/cam_utils/cam_packet_util.c index 1569d5dbafa6..a462fb970e92 100644 --- a/drivers/cam_utils/cam_packet_util.c +++ b/drivers/cam_utils/cam_packet_util.c @@ -10,6 +10,14 @@ #include "cam_packet_util.h" #include "cam_debug_util.h" +#define CAM_UNIQUE_SRC_HDL_MAX 50 + +struct cam_patch_unique_src_buf_tbl { + int32_t hdl; + dma_addr_t iova; + size_t buf_size; +}; + int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr, size_t *len) { @@ -207,6 +215,63 @@ void cam_packet_dump_patch_info(struct cam_packet *packet, } } +static int cam_packet_util_get_patch_iova( + struct cam_patch_unique_src_buf_tbl *tbl, + int32_t hdl, uint32_t buf_hdl, dma_addr_t *iova, size_t *buf_size) +{ + int idx = 0; + int rc = 0; + size_t src_buf_size; + dma_addr_t iova_addr; + bool is_found = false; + + for (idx = 0; idx < CAM_UNIQUE_SRC_HDL_MAX; idx++) { + if (buf_hdl == tbl[idx].hdl) { + CAM_DBG(CAM_UTIL, + "Matched entry for src_buf_hdl: 0x%x with src_hdl[%d]: 0x%x", + buf_hdl, idx, tbl[idx].hdl); + *iova = tbl[idx].iova; + *buf_size = tbl[idx].buf_size; + is_found = true; + break; + } else if ((tbl[idx].hdl == 0) || (tbl[idx].iova == 0)) { + CAM_DBG(CAM_UTIL, "New src handle detected 0x%x", + buf_hdl); + is_found = false; + break; + } + CAM_DBG(CAM_UTIL, + "Index: %d is filled with differnt src_hdl: 0x%x", + idx, buf_hdl); + } + + if (!is_found) { + CAM_DBG(CAM_UTIL, "src_hdl 0x%x not found in table entries", + buf_hdl); + rc = cam_mem_get_io_buf(buf_hdl, hdl, + &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, + "unable to get iova for src_hdl: 0x%x", + buf_hdl); + return rc; + } + /* Update the table entry with unique src buf handle */ + if (idx < CAM_UNIQUE_SRC_HDL_MAX && tbl[idx].hdl == 0) { + tbl[idx].buf_size = src_buf_size; + tbl[idx].iova = iova_addr; + tbl[idx].hdl = buf_hdl; + CAM_DBG(CAM_UTIL, + "Updated table index: %d with src_buf_hdl: 0x%x", + idx, tbl[idx].hdl); + } + *iova = iova_addr; + *buf_size = src_buf_size; + } + + return rc; +} + int cam_packet_util_process_patches(struct cam_packet *packet, int32_t iommu_hdl, int32_t sec_mmu_hdl) { @@ -218,9 +283,14 @@ int cam_packet_util_process_patches(struct cam_packet *packet, uint32_t *src_buf_iova_addr; size_t dst_buf_len; size_t src_buf_size; - int i; + int i = 0; int rc = 0; int32_t hdl; + struct cam_patch_unique_src_buf_tbl + tbl[CAM_UNIQUE_SRC_HDL_MAX]; + + memset(tbl, 0, CAM_UNIQUE_SRC_HDL_MAX * + sizeof(struct cam_patch_unique_src_buf_tbl)); /* process patch descriptor */ patch_desc = (struct cam_patch_desc *) @@ -233,12 +303,23 @@ int cam_packet_util_process_patches(struct cam_packet *packet, 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, - hdl, &iova_addr, &src_buf_size); - if (rc < 0) { - CAM_ERR(CAM_UTIL, "unable to get src buf address"); + + rc = cam_packet_util_get_patch_iova(&tbl[0], hdl, + patch_desc[i].src_buf_hdl, &iova_addr, &src_buf_size); + if (rc) { + CAM_ERR(CAM_UTIL, + "get_iova failed for patch[%d], src_buf_hdl: 0x%x: rc: %d", + i, patch_desc[i].src_buf_hdl, rc); return rc; } + + if ((size_t)patch_desc[i].src_offset >= src_buf_size) { + CAM_ERR(CAM_UTIL, + "Invalid src buf patch offset: patch:src_offset: 0x%x, src_buf_size: %zu", + patch_desc[i].src_offset, src_buf_size); + return -EINVAL; + } + src_buf_iova_addr = (uint32_t *)iova_addr; temp = iova_addr; @@ -254,12 +335,6 @@ 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)) { From 2c32ced295d860cb08784a4855c0f8874cfe8468 Mon Sep 17 00:00:00 2001 From: Divya Sharma Date: Tue, 16 Jun 2020 17:46:40 -0700 Subject: [PATCH 386/790] Revert "msm: camera: isp: Update last reported request ID correctly" This reverts commit 4a7fda98ae2a840eee7d508a64068115eb4731c0. Change-Id: I3a841e7be736bc15307d60739bf8f6130c233254 Signed-off-by: Divya Sharma --- drivers/cam_isp/cam_isp_context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 13cd4ae74d94..7fd06d214c9e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1364,9 +1364,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( } list_for_each_entry(req, &ctx->active_req_list, list) { - req_isp = (struct cam_isp_ctx_req *) req->req_priv; - if ((!req_isp->bubble_detected) && - (req->request_id > ctx_isp->reported_req_id)) { + if (req->request_id > ctx_isp->reported_req_id) { request_id = req->request_id; ctx_isp->reported_req_id = request_id; __cam_isp_ctx_update_event_record(ctx_isp, From d37a16ddff6c6cd805b2c2ff150d6bd9ae136a27 Mon Sep 17 00:00:00 2001 From: Divya Sharma Date: Tue, 16 Jun 2020 17:50:44 -0700 Subject: [PATCH 387/790] Revert "msm: camera: util: Correct the return code" This reverts commit be34fb7086ade233e38c56cbd6874ef7c9ca4e11. Change-Id: Ifafefd3ee56bf8add5d54a9e8383706cc0d24e46 Signed-off-by: Divya Sharma --- drivers/cam_utils/cam_compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 27c84b0ecac2..e0b70865c885 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -86,7 +86,7 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, rc = -EINVAL; } - return rc; + return 0; } void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) @@ -169,7 +169,7 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, rc = -EINVAL; } - return rc; + return 0; } void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa) From becd9f4f111b15d20530b98e0e9c4efdeaef89e0 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 13 May 2020 12:52:42 -0700 Subject: [PATCH 388/790] msm: camera: cci: Add check for the cci master initialization Multiple Sensor submodules can stream on same CCI master. Currently, there is not any knowledge, whether requested master is already initialized by other submodules. This can result in operation slave in error, while other submodule tries to init the same master. This change adds the boolean variable to notify cci hardware, whether master is already initialized, and do the operations accordingly. CRs-Fixed: 2686487 Change-Id: I8b5d01fc9fd06176e9fbd9a69d56424d4ef79a73 Signed-off-by: Jigarkumar Zala --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 7 +- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 11 +- .../cam_sensor_module/cam_cci/cam_cci_soc.c | 257 +++++++++--------- .../cam_sensor_module/cam_cci/cam_cci_soc.h | 5 +- 4 files changed, 139 insertions(+), 141 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 08422719b1fb..647edaf34256 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1776,14 +1776,15 @@ static int32_t cam_cci_i2c_set_sync_prms(struct v4l2_subdev *sd, return rc; } -static int32_t cam_cci_release(struct v4l2_subdev *sd) +static int32_t cam_cci_release(struct v4l2_subdev *sd, + enum cci_i2c_master_t master) { uint8_t rc = 0; struct cci_device *cci_dev; cci_dev = v4l2_get_subdevdata(sd); - rc = cam_cci_soc_release(cci_dev); + rc = cam_cci_soc_release(cci_dev, master); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed in releasing the cci: %d", rc); return rc; @@ -1896,7 +1897,7 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, break; case MSM_CCI_RELEASE: mutex_lock(&cci_dev->init_mutex); - rc = cam_cci_release(sd); + rc = cam_cci_release(sd, master); mutex_unlock(&cci_dev->init_mutex); break; case MSM_CCI_I2C_READ: diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 8dd50aa408ca..ee8c313eff2c 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -40,8 +40,6 @@ #define CCI_MAX_DELAY 1000000 #define CCI_TIMEOUT msecs_to_jiffies(1500) - -#define NUM_MASTERS 2 #define NUM_QUEUES 2 #define CCI_PINCTRL_STATE_DEFAULT "cci_default" @@ -142,6 +140,7 @@ struct cam_cci_master_info { struct semaphore master_sem; bool is_first_req; uint16_t freq_ref_cnt; + bool is_initilized; }; struct cam_cci_clk_params_t { @@ -176,6 +175,7 @@ enum cam_cci_state_t { * @cci_clk_info: CCI clock information * @cam_cci_i2c_queue_info: CCI queue information * @i2c_freq_mode: I2C frequency of operations + * @master_active_slave: Number of active/connected slaves for master * @cci_clk_params: CCI hw clk params * @cci_gpio_tbl: CCI GPIO table * @cci_gpio_tbl_size: GPIO table size @@ -208,9 +208,10 @@ struct cci_device { uint8_t ref_count; enum cam_cci_state_t cci_state; struct cam_cci_i2c_queue_info - cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES]; - struct cam_cci_master_info cci_master_info[NUM_MASTERS]; - enum i2c_freq_mode i2c_freq_mode[NUM_MASTERS]; + cci_i2c_queue_info[MASTER_MAX][NUM_QUEUES]; + struct cam_cci_master_info cci_master_info[MASTER_MAX]; + enum i2c_freq_mode i2c_freq_mode[MASTER_MAX]; + uint8_t master_active_slave[MASTER_MAX]; struct cam_cci_clk_params_t cci_clk_params[I2C_MAX_MODES]; struct msm_pinctrl_info cci_pinctrl; uint8_t cci_pinctrl_status; diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 87603d069387..5f35a6449a07 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -6,10 +6,78 @@ #include "cam_cci_dev.h" #include "cam_cci_core.h" +static int cam_cci_init_master(struct cci_device *cci_dev, + enum cci_i2c_master_t master) +{ + int i = 0, rc = 0; + void __iomem *base = NULL; + struct cam_hw_soc_info *soc_info = NULL; + uint32_t max_queue_0_size = 0, max_queue_1_size = 0; + + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + + if (cci_dev->hw_version != CCI_VERSION_1_2_9) { + max_queue_0_size = CCI_I2C_QUEUE_0_SIZE_V_1_2; + max_queue_1_size = CCI_I2C_QUEUE_1_SIZE_V_1_2; + } else { + max_queue_0_size = CCI_I2C_QUEUE_0_SIZE; + max_queue_1_size = CCI_I2C_QUEUE_1_SIZE; + } + + cci_dev->master_active_slave[master]++; + if (!cci_dev->cci_master_info[master].is_initilized) { + /* Re-initialize the completion */ + reinit_completion( + &cci_dev->cci_master_info[master].reset_complete); + reinit_completion(&cci_dev->cci_master_info[master].rd_done); + + /* reinit the reports for the queue */ + for (i = 0; i < NUM_QUEUES; i++) + reinit_completion( + &cci_dev->cci_master_info[master].report_q[i]); + + /* Set reset pending flag to true */ + cci_dev->cci_master_info[master].reset_pending = true; + cam_io_w_mb((master == MASTER_0) ? + CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + if (!wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "Failed: reset complete timeout for master: %d", + master); + rc = -ETIMEDOUT; + cci_dev->master_active_slave[master]--; + return rc; + } + + flush_workqueue(cci_dev->write_wq[master]); + + /* Setting up the queue size for master */ + cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size + = max_queue_0_size; + cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size + = max_queue_1_size; + + CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0: %d Q1: %d", master, + cci_dev->cci_i2c_queue_info[master][QUEUE_0] + .max_queue_size, + cci_dev->cci_i2c_queue_info[master][QUEUE_1] + .max_queue_size); + + cci_dev->cci_master_info[master].status = 0; + cci_dev->cci_master_info[master].is_initilized = true; + } + + return 0; +} + int cam_cci_init(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl) { - uint8_t i = 0, j = 0; + uint8_t i = 0; int32_t rc = 0; struct cci_device *cci_dev; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; @@ -17,7 +85,6 @@ int cam_cci_init(struct v4l2_subdev *sd, struct cam_axi_vote axi_vote = {0}; struct cam_hw_soc_info *soc_info = NULL; void __iomem *base = NULL; - uint32_t max_queue_0_size = 0, max_queue_1_size = 0; cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { @@ -39,79 +106,46 @@ int cam_cci_init(struct v4l2_subdev *sd, return rc; } - CAM_DBG(CAM_CCI, "Base address %pK", base); + if (master >= MASTER_MAX || master < 0) { + CAM_ERR(CAM_CCI, "Incorrect Master: %d", master); + return -EINVAL; + } + + if (!cci_dev->write_wq[master]) { + CAM_ERR(CAM_CCI, "Null memory for write wq[:%d]", master); + rc = -ENOMEM; + return rc; + } if (cci_dev->ref_count++) { - CAM_DBG(CAM_CCI, - "ref_count:%d, master:%d", - cci_dev->ref_count, master); - if (master < MASTER_MAX && master >= 0) { - mutex_lock(&cci_dev->cci_master_info[master].mutex); - flush_workqueue(cci_dev->write_wq[master]); - /* Re-initialize the completion */ - reinit_completion( - &cci_dev->cci_master_info[master].reset_complete); - reinit_completion( - &cci_dev->cci_master_info[master].rd_done); - for (i = 0; i < NUM_QUEUES; i++) - reinit_completion( - &cci_dev->cci_master_info[master].report_q[i]); - /* Set reset pending flag to true */ - cci_dev->cci_master_info[master].reset_pending = true; - cci_dev->cci_master_info[master].status = 0; - /* Set proper mask to RESET CMD address */ - if (master == MASTER_0) - cam_io_w_mb(CCI_M0_RESET_RMSK, - base + CCI_RESET_CMD_ADDR); - else - cam_io_w_mb(CCI_M1_RESET_RMSK, - base + CCI_RESET_CMD_ADDR); - /* wait for reset done irq */ - if (!wait_for_completion_timeout( - &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT)) { - CAM_ERR(CAM_CCI, - "wait timeout for reset_complete for master: %d", - master); - reinit_completion( - &cci_dev->cci_master_info[master].reset_complete - ); - rc = -EINVAL; - } - cci_dev->cci_master_info[master].status = 0; - mutex_unlock(&cci_dev->cci_master_info[master].mutex); + rc = cam_cci_init_master(cci_dev, master); + if (rc) { + CAM_ERR(CAM_CCI, "Failed to init: Master: %d: rc: %d", + master, rc); + cci_dev->ref_count--; } + CAM_DBG(CAM_CCI, "ref_count %d, master: %d", + cci_dev->ref_count, master); return rc; } ahb_vote.type = CAM_VOTE_ABSOLUTE; ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; - axi_vote.axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_ALL; - axi_vote.axi_path[0].transac_type = - CAM_AXI_TRANSACTION_WRITE; - axi_vote.axi_path[0].camnoc_bw = - CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ab_bw = - CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ib_bw = - CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; - rc = cam_cpas_start(cci_dev->cpas_handle, - &ahb_vote, &axi_vote); - if (rc != 0) - CAM_ERR(CAM_CCI, "CPAS start failed, rc: %d", rc); + rc = cam_cpas_start(cci_dev->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_CCI, "CPAS start failed rc= %d", rc); + return rc; + } cam_cci_get_clk_rates(cci_dev, c_ctrl); - /* Re-initialize the completion */ - reinit_completion(&cci_dev->cci_master_info[master].reset_complete); - reinit_completion(&cci_dev->cci_master_info[master].rd_done); - for (i = 0; i < NUM_QUEUES; i++) - reinit_completion( - &cci_dev->cci_master_info[master].report_q[i]); - /* Enable Regulators and IRQ*/ rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_LOWSVS_VOTE, true); @@ -121,73 +155,27 @@ int cam_cci_init(struct v4l2_subdev *sd, goto platform_enable_failed; } - cci_dev->hw_version = cam_io_r_mb(base + - CCI_HW_VERSION_ADDR); + cci_dev->hw_version = cam_io_r_mb(base + CCI_HW_VERSION_ADDR); CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version); - cci_dev->payload_size = - MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; + cci_dev->payload_size = MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; cci_dev->support_seq_write = 1; - if (cci_dev->hw_version == CCI_VERSION_1_2_9) { - max_queue_0_size = CCI_I2C_QUEUE_0_SIZE_V_1_2; - max_queue_1_size = CCI_I2C_QUEUE_1_SIZE_V_1_2; - } else { - max_queue_0_size = CCI_I2C_QUEUE_0_SIZE; - max_queue_1_size = CCI_I2C_QUEUE_1_SIZE; - } - - for (i = 0; i < NUM_MASTERS; i++) { - for (j = 0; j < NUM_QUEUES; j++) { - if (j == QUEUE_0) - cci_dev->cci_i2c_queue_info[i][j].max_queue_size - = max_queue_0_size; - else - cci_dev->cci_i2c_queue_info[i][j].max_queue_size - = max_queue_1_size; - - CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i, - cci_dev->cci_i2c_queue_info[i][j].max_queue_size, - cci_dev->cci_i2c_queue_info[i][j].max_queue_size); - } - } - - cci_dev->cci_master_info[master].reset_pending = true; - cci_dev->cci_master_info[master].status = 0; - cam_io_w_mb(CCI_RESET_CMD_RMSK, base + - CCI_RESET_CMD_ADDR); - cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); - if (!wait_for_completion_timeout( - &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT)) { - CAM_ERR(CAM_CCI, - "wait timeout for reset_complete for master: %d", - master); - - rc = -ETIMEDOUT; + rc = cam_cci_init_master(cci_dev, master); + if (rc) { + CAM_ERR(CAM_CCI, "Failed to init: Master: %d, rc: %d", + master, rc); goto reset_complete_failed; } + for (i = 0; i < MASTER_MAX; i++) cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; - cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, - base + CCI_IRQ_MASK_0_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, - base + CCI_IRQ_CLEAR_0_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, - base + CCI_IRQ_MASK_1_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, - base + CCI_IRQ_CLEAR_1_ADDR); - cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); - for (i = 0; i < MASTER_MAX; i++) { - if (!cci_dev->write_wq[i]) { - CAM_ERR(CAM_CCI, "Failed to flush write wq"); - rc = -ENOMEM; - goto reset_complete_failed; - } else { - flush_workqueue(cci_dev->write_wq[i]); - } - } + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_MASK_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_CLEAR_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_CLEAR_1_ADDR); + cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); /* Set RD FIFO threshold for M0 & M1 */ if (cci_dev->hw_version != CCI_VERSION_1_2_9) { @@ -203,7 +191,6 @@ int cam_cci_init(struct v4l2_subdev *sd, reset_complete_failed: cam_soc_util_disable_platform_resource(soc_info, 1, 1); - platform_enable_failed: cci_dev->ref_count--; cam_cpas_stop(cci_dev->cpas_handle); @@ -223,9 +210,10 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) { uint8_t i = 0, j = 0; - for (i = 0; i < NUM_MASTERS; i++) { + for (i = 0; i < MASTER_MAX; i++) { new_cci_dev->cci_master_info[i].status = 0; new_cci_dev->cci_master_info[i].is_first_req = true; + new_cci_dev->cci_master_info[i].is_initilized = false; 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); @@ -400,27 +388,34 @@ int cam_cci_parse_dt_info(struct platform_device *pdev, return 0; } -int cam_cci_soc_release(struct cci_device *cci_dev) +int cam_cci_soc_release(struct cci_device *cci_dev, + enum cci_i2c_master_t master) { uint8_t i = 0, rc = 0; - struct cam_hw_soc_info *soc_info = - &cci_dev->soc_info; + struct cam_hw_soc_info *soc_info = &cci_dev->soc_info; - if (!cci_dev->ref_count || cci_dev->cci_state != CCI_STATE_ENABLED) { - CAM_ERR(CAM_CCI, "invalid ref count %d / cci state %d", - cci_dev->ref_count, cci_dev->cci_state); + if (!cci_dev->ref_count || cci_dev->cci_state != CCI_STATE_ENABLED || + !cci_dev->master_active_slave[master]) { + CAM_ERR(CAM_CCI, + "invalid cci_dev_ref count %u | cci state %d | master_ref_count %u", + cci_dev->ref_count, cci_dev->cci_state, + cci_dev->master_active_slave[master]); return -EINVAL; } + + if (--cci_dev->master_active_slave[master]) + cci_dev->cci_master_info[master].is_initilized = false; + if (--cci_dev->ref_count) { CAM_DBG(CAM_CCI, "ref_count Exit %d", cci_dev->ref_count); return 0; } - for (i = 0; i < MASTER_MAX; i++) + + for (i = 0; i < MASTER_MAX; i++) { if (cci_dev->write_wq[i]) flush_workqueue(cci_dev->write_wq[i]); - - for (i = 0; i < MASTER_MAX; i++) cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; + } rc = cam_soc_util_disable_platform_resource(soc_info, true, true); if (rc) { diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h index f0cdfe822cd3..e78d9918ff45 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_SOC_H_ @@ -23,7 +23,8 @@ int cam_cci_init(struct v4l2_subdev *sd, * * This API releases the CCI and its SOC resources */ -int cam_cci_soc_release(struct cci_device *cci_dev); +int cam_cci_soc_release(struct cci_device *cci_dev, + enum cci_i2c_master_t master); /** * @pdev: Platform device From 5a5fb4e8f011b8f12ef5d9439413c4ce60049a45 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 10 Jun 2020 17:33:50 -0700 Subject: [PATCH 389/790] msm: camera: req_mgr: Clean up debugfs entry At the time of unbind, all debugfs entry needs to be properly clean up. This change adds debugfs directory removal alongwith entries under debugfs root entry. CRs-Fixed: 2675526 Change-Id: I3eba11db032dbafe5f7d444e8c5a823639ba0e74 Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_mem_mgr.c | 1 + drivers/cam_req_mgr/cam_req_mgr_debug.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 97a6c8b1b094..e0ce16a794c0 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -955,6 +955,7 @@ void cam_mem_mgr_deinit(void) { atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED); cam_mem_mgr_cleanup_table(); + debugfs_remove_recursive(tbl.dentry); mutex_lock(&tbl.m_lock); bitmap_zero(tbl.bitmap, tbl.bits); kfree(tbl.bitmap); diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index 6b6a91b6303b..89b55d937667 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -141,6 +141,5 @@ int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) void cam_req_mgr_debug_unregister(void) { - if (!debugfs_root) - debugfs_remove_recursive(debugfs_root); + debugfs_remove_recursive(debugfs_root); } From e625f33cffefb5e145c72974b91e02df4603eb44 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 16 Jun 2020 14:13:59 +0530 Subject: [PATCH 390/790] msm: camera: isp: Bring PPI driver in camera techpack This change bring PPI driver from msm-4.14 to camera-kernel.lnx.4.0. msm: camera: isp: Added PPI driver functionality msm: camera: ppi: Change PPI reset sequence msm: camera: isp: Do not enable the ppi hw twice. CRs-Fixed: 2682747 Change-Id: I7cde3aeed1dbcef95f25441c2482f5bc8c1534de Signed-off-by: Trishansh Bhardwaj --- drivers/Makefile | 3 + .../isp_hw/ppi_hw/cam_csid_ppi100.c | 49 +++ .../isp_hw/ppi_hw/cam_csid_ppi100.h | 35 ++ .../isp_hw/ppi_hw/cam_csid_ppi_core.c | 391 ++++++++++++++++++ .../isp_hw/ppi_hw/cam_csid_ppi_core.h | 95 +++++ .../isp_hw/ppi_hw/cam_csid_ppi_dev.c | 164 ++++++++ .../isp_hw/ppi_hw/cam_csid_ppi_dev.h | 15 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 58 ++- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 6 + drivers/camera_main.c | 28 +- 10 files changed, 829 insertions(+), 15 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h diff --git a/drivers/Makefile b/drivers/Makefile index dc5da5116010..7f633970dd07 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -197,6 +197,9 @@ camera-$(CONFIG_SPECTRA_OPE) += \ cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.o camera-$(CONFIG_SPECTRA_TFE) += \ + cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.o \ + cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.o \ cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.o \ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c new file mode 100644 index 000000000000..3ad3bd9b6a78 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi100.h" +#include "cam_csid_ppi_dev.h" + +#define CAM_PPI_DRV_NAME "ppi_100" +#define CAM_PPI_VERSION_V100 0x10000000 + +static struct cam_csid_ppi_hw_info cam_csid_ppi100_hw_info = { + .ppi_reg = &cam_csid_ppi_100_reg_offset, +}; + +static const struct of_device_id cam_csid_ppi100_dt_match[] = { + { + .compatible = "qcom,ppi100", + .data = &cam_csid_ppi100_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_csid_ppi100_dt_match); + +static struct platform_driver cam_csid_ppi100_driver = { + .probe = cam_csid_ppi_probe, + .remove = cam_csid_ppi_remove, + .driver = { + .name = CAM_PPI_DRV_NAME, + .of_match_table = cam_csid_ppi100_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_csid_ppi100_init_module(void) +{ + return platform_driver_register(&cam_csid_ppi100_driver); +} + +void cam_csid_ppi100_exit_module(void) +{ + platform_driver_unregister(&cam_csid_ppi100_driver); +} + +MODULE_DESCRIPTION("CAM CSID_PPI100 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h new file mode 100644 index 000000000000..eacf87f4e936 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_PPI_100_H_ +#define _CAM_CSID_PPI_100_H_ + +#include "cam_csid_ppi_core.h" + +static struct cam_csid_ppi_reg_offset cam_csid_ppi_100_reg_offset = { + .ppi_hw_version_addr = 0, + .ppi_module_cfg_addr = 0x60, + .ppi_irq_status_addr = 0x68, + .ppi_irq_mask_addr = 0x6c, + .ppi_irq_set_addr = 0x70, + .ppi_irq_clear_addr = 0x74, + .ppi_irq_cmd_addr = 0x78, + .ppi_rst_cmd_addr = 0x7c, + .ppi_test_bus_ctrl_addr = 0x1f4, + .ppi_debug_addr = 0x1f8, + .ppi_spare_addr = 0x1fc, +}; + +/** + * @brief : API to register PPI Dev to platform framework. + * @return struct platform_device pointer on on success, or ERR_PTR() on error. + */ +int cam_csid_ppi100_init_module(void); + +/** + * @brief : API to remove PPI Dev from platform framework. + */ +void cam_csid_ppi100_exit_module(void); +#endif /*_CAM_CSID_PPI_100_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c new file mode 100644 index 000000000000..21316b09f29f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_io_util.h" + +static int cam_csid_ppi_reset(struct cam_csid_ppi_hw *ppi_hw) +{ + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + int rc = 0; + uint32_t status; + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "PPI:%d reset", ppi_hw->hw_intf->hw_idx); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_set_addr); + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_rst_cmd_addr); + cam_io_w_mb(PPI_IRQ_CMD_SET, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + rc = readl_poll_timeout(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr, status, + (status & 0x1) == 0x1, 1000, 500000); + CAM_DBG(CAM_ISP, "PPI:%d reset status %d", ppi_hw->hw_intf->hw_idx, + status); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d ppi_reset fail rc = %d status = %d", + ppi_hw->hw_intf->hw_idx, rc, status); + return rc; + } + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + return 0; +} + +static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + int32_t i; + uint64_t val; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + uint32_t err_irq_mask; + + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + CAM_DBG(CAM_ISP, "PPI:%d init PPI HW", ppi_hw->hw_intf->hw_idx); + + ppi_hw->hw_info->open_count++; + if (ppi_hw->hw_info->open_count > 1) { + CAM_DBG(CAM_ISP, "PPI:%d dual vfe already enabled", + ppi_hw->hw_intf->hw_idx); + return 0; + } + + for (i = 0; i < soc_info->num_clk; i++) { + rc = cam_soc_util_clk_enable(soc_info->clk[i], + soc_info->clk_name[i], 0); + if (rc) + goto clk_disable; + } + + rc = cam_csid_ppi_reset(ppi_hw); + if (rc) + goto clk_disable; + + err_irq_mask = PPI_IRQ_FIFO0_OVERFLOW | PPI_IRQ_FIFO1_OVERFLOW | + PPI_IRQ_FIFO2_OVERFLOW; + cam_io_w_mb(err_irq_mask, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + rc = cam_soc_util_irq_enable(soc_info); + if (rc) + goto clk_disable; + + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_hw_version_addr); + CAM_DBG(CAM_ISP, "PPI:%d PPI HW version: 0x%x", + ppi_hw->hw_intf->hw_idx, val); + ppi_hw->device_enabled = 1; + + return 0; +clk_disable: + for (--i; i >= 0; i--) + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + ppi_hw->hw_info->open_count--; + return rc; +} + +static int cam_csid_ppi_disable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + int i; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + uint64_t ppi_cfg_val = 0; + + CAM_DBG(CAM_ISP, "PPI:%d De-init PPI HW", + ppi_hw->hw_intf->hw_idx); + + if (!ppi_hw->hw_info->open_count) { + CAM_WARN(CAM_ISP, "ppi[%d] unbalanced disable hw", + ppi_hw->hw_intf->hw_idx); + return -EINVAL; + } + ppi_hw->hw_info->open_count--; + + if (ppi_hw->hw_info->open_count) + return rc; + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "Calling PPI Reset"); + cam_csid_ppi_reset(ppi_hw); + CAM_DBG(CAM_ISP, "PPI Reset Done"); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_soc_util_irq_disable(soc_info); + + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + ppi_hw->device_enabled = 0; + + for (i = 0; i < soc_info->num_clk; i++) + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + + return rc; +} + +static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, + uint32_t arg_size) +{ + int i, rc = 0; + uint32_t num_lanes; + uint32_t lanes[CAM_CSID_PPI_HW_MAX] = {0, 0, 0, 0}; + uint32_t cphy; + bool dl0, dl1; + uint32_t ppi_cfg_val = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + struct cam_csid_ppi_cfg ppi_cfg; + + if (!hw_priv || !init_args || + (arg_size != sizeof(struct cam_csid_ppi_cfg))) { + CAM_ERR(CAM_ISP, "PPI: Invalid args"); + rc = -EINVAL; + goto end; + } + + dl0 = dl1 = false; + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + ppi_cfg = *((struct cam_csid_ppi_cfg *)init_args); + + rc = cam_csid_ppi_enable_hw(ppi_hw); + if (rc) + goto end; + + num_lanes = ppi_cfg.lane_num; + cphy = ppi_cfg.lane_type; + CAM_DBG(CAM_ISP, "lane_cfg 0x%x | num_lanes 0x%x | lane_type 0x%x", + ppi_cfg.lane_cfg, num_lanes, cphy); + + for (i = 0; i < num_lanes; i++) { + lanes[i] = ppi_cfg.lane_cfg & (0x3 << (4 * i)); + (lanes[i] < 2) ? (dl0 = true) : (dl1 = true); + CAM_DBG(CAM_ISP, "lanes[%d] %d", i, lanes[i]); + } + + if (num_lanes) { + if (cphy) { + for (i = 0; i < num_lanes; i++) { + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(lanes[i]); + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(lanes[i]); + } + } else { + if (dl0) + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(0); + if (dl1) + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(1); + } + } else { + CAM_ERR(CAM_ISP, + "Number of lanes to enable is cannot be zero"); + rc = -1; + goto end; + } + + CAM_DBG(CAM_ISP, "ppi_cfg_val 0x%x", ppi_cfg_val); + soc_info = &ppi_hw->hw_info->soc_info; + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + CAM_DBG(CAM_ISP, "ppi cfg 0x%x", + cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr)); +end: + return rc; +} + +static int cam_csid_ppi_deinit_hw(void *hw_priv, void *deinit_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + + CAM_DBG(CAM_ISP, "Enter"); + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "PPI:Invalid arguments"); + rc = -EINVAL; + goto end; + } + + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + + CAM_DBG(CAM_ISP, "Disabling PPI Hw"); + rc = cam_csid_ppi_disable_hw(ppi_hw); + if (rc < 0) + CAM_DBG(CAM_ISP, "Exit with %d", rc); +end: + return rc; +} + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx) +{ + int rc = -EINVAL; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *csid_ppi_hw = NULL; + + if (ppi_idx >= CAM_CSID_PPI_HW_MAX) { + CAM_ERR(CAM_ISP, "Invalid ppi index:%d", ppi_idx); + goto err; + } + + ppi_hw_info = (struct cam_hw_info *) ppi_hw_intf->hw_priv; + csid_ppi_hw = (struct cam_csid_ppi_hw *) ppi_hw_info->core_info; + + csid_ppi_hw->hw_intf = ppi_hw_intf; + csid_ppi_hw->hw_info = ppi_hw_info; + + CAM_DBG(CAM_ISP, "type %d index %d", + csid_ppi_hw->hw_intf->hw_type, ppi_idx); + + rc = cam_csid_ppi_init_soc_resources(&csid_ppi_hw->hw_info->soc_info, + cam_csid_ppi_irq, csid_ppi_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Failed to init_soc", ppi_idx); + goto err; + } + + csid_ppi_hw->hw_intf->hw_ops.init = cam_csid_ppi_init_hw; + csid_ppi_hw->hw_intf->hw_ops.deinit = cam_csid_ppi_deinit_hw; + return 0; +err: + return rc; +} + +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Failed to get dt properties"); + goto end; + } + + rc = cam_soc_util_request_platform_resource(soc_info, ppi_irq_handler, + irq_data); + if (rc) { + CAM_ERR(CAM_ISP, + "PPI: Error Request platform resources failed rc=%d", + rc); + goto err; + } +end: + return rc; +err: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data) +{ + uint32_t irq_status = 0; + uint32_t i, ppi_cfg_val = 0; + bool fatal_err_detected = false; + + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + + if (!data) { + CAM_ERR(CAM_ISP, "PPI: Invalid arguments"); + return IRQ_HANDLED; + } + + ppi_hw = (struct cam_csid_ppi_hw *)data; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + if (ppi_hw->device_enabled != 1) + goto ret; + + irq_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr); + + cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + CAM_DBG(CAM_ISP, "PPI %d irq status 0x%x", ppi_hw->hw_intf->hw_idx, + irq_status); + + if (irq_status & PPI_IRQ_RST_DONE) { + CAM_DBG(CAM_ISP, "PPI Reset Done"); + goto ret; + } + if ((irq_status & PPI_IRQ_FIFO0_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO1_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO2_OVERFLOW)) { + fatal_err_detected = true; + goto handle_fatal_error; + } + +handle_fatal_error: + if (fatal_err_detected) { + CAM_ERR(CAM_ISP, "PPI: %d irq_status:0x%x", + ppi_hw->hw_intf->hw_idx, irq_status); + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + } +ret: + CAM_DBG(CAM_ISP, "IRQ Handling exit"); + return IRQ_HANDLED; +} + +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw) +{ + if (!csid_ppi_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return -EINVAL; + } + return cam_soc_util_release_platform_resource( + &csid_ppi_hw->hw_info->soc_info); +} + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h new file mode 100644 index 000000000000..dc0edf7e50ce --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_PPI_HW_H_ +#define _CAM_CSID_PPI_HW_H_ + +#include "cam_hw.h" +#include "cam_hw_intf.h" + +#define CAM_CSID_PPI_HW_MAX 6 +#define CAM_CSID_PPI_LANES_MAX 3 + +#define PPI_IRQ_RST_DONE BIT(0) +#define PPI_IRQ_FIFO0_OVERFLOW BIT(1) +#define PPI_IRQ_FIFO1_OVERFLOW BIT(2) +#define PPI_IRQ_FIFO2_OVERFLOW BIT(3) + +#define PPI_IRQ_CMD_SET BIT(1) + +#define PPI_IRQ_CMD_CLEAR BIT(0) + +#define PPI_RST_CONTROL BIT(0) +/* + * Select the PHY (CPHY set '1' or DPHY set '0') + */ +#define PPI_CFG_CPHY_DLX_SEL(X) ((X < 2) ? BIT(X) : 0) + +#define PPI_CFG_CPHY_DLX_EN(X) BIT(4+X) + +struct cam_csid_ppi_reg_offset { + uint32_t ppi_hw_version_addr; + uint32_t ppi_module_cfg_addr; + + uint32_t ppi_irq_status_addr; + uint32_t ppi_irq_mask_addr; + uint32_t ppi_irq_set_addr; + uint32_t ppi_irq_clear_addr; + uint32_t ppi_irq_cmd_addr; + uint32_t ppi_rst_cmd_addr; + uint32_t ppi_test_bus_ctrl_addr; + uint32_t ppi_debug_addr; + uint32_t ppi_spare_addr; +}; + +/** + * struct cam_csid_ppi_hw_info- ppi HW info + * + * @ppi_reg: ppi register offsets + * + */ +struct cam_csid_ppi_hw_info { + const struct cam_csid_ppi_reg_offset *ppi_reg; +}; + +/** + * struct cam_csid_ppi_hw- ppi hw device resources data + * + * @hw_intf: contain the ppi hw interface information + * @hw_info: ppi hw device information + * @ppi_info: ppi hw specific information + * @device_enabled Device enabled will set once ppi powered on and + * initial configuration are done. + * + */ +struct cam_csid_ppi_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_csid_ppi_hw_info *ppi_info; + uint32_t device_enabled; +}; + +/** + * struct cam_csid_ppi_cfg - ppi lane configuration data + * @lane_type: lane type: c-phy or d-phy + * @lane_num : active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * + */ +struct cam_csid_ppi_cfg { + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; +}; + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx); +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw); +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data); +int cam_csid_ppi_deinit_soc_resources(struct cam_hw_soc_info *soc_info); +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx); +#endif /* _CAM_CSID_PPI_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c new file mode 100644 index 000000000000..28b39d74bee5 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_csid_ppi_hw_list[CAM_CSID_PPI_HW_MAX] = { + NULL, NULL, NULL, NULL}; +static char ppi_dev_name[8]; + +static int cam_ppi_component_bind(struct device *dev, + struct device *master_dev, void *data) +{ + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *ppi_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_csid_ppi_hw_info *ppi_hw_data = NULL; + uint32_t ppi_dev_idx; + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); + + CAM_DBG(CAM_ISP, "PPI probe called"); + + ppi_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!ppi_hw_intf) { + rc = -ENOMEM; + goto err; + } + + ppi_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!ppi_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + ppi_dev = kzalloc(sizeof(struct cam_csid_ppi_hw), GFP_KERNEL); + if (!ppi_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + of_property_read_u32(pdev->dev.of_node, "cell-index", &ppi_dev_idx); + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the CSID PPI HW!"); + rc = -EINVAL; + goto free_dev; + } + + memset(ppi_dev_name, 0, sizeof(ppi_dev_name)); + snprintf(ppi_dev_name, sizeof(ppi_dev_name), "ppi%1u", ppi_dev_idx); + + ppi_hw_intf->hw_idx = ppi_dev_idx; + ppi_hw_intf->hw_priv = ppi_hw_info; + + if (ppi_hw_intf->hw_idx < CAM_CSID_PPI_HW_MAX) + cam_csid_ppi_hw_list[ppi_hw_intf->hw_idx] = ppi_hw_intf; + else { + rc = -EINVAL; + goto free_dev; + } + + ppi_hw_info->core_info = ppi_dev; + ppi_hw_info->soc_info.pdev = pdev; + ppi_hw_info->soc_info.dev = &pdev->dev; + ppi_hw_info->soc_info.dev_name = ppi_dev_name; + ppi_hw_info->soc_info.index = ppi_dev_idx; + + ppi_hw_data = (struct cam_csid_ppi_hw_info *)match_dev->data; + ppi_dev->ppi_info = ppi_hw_data; + + rc = cam_csid_ppi_hw_probe_init(ppi_hw_intf, ppi_dev_idx); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Probe init failed!"); + goto free_dev; + } + + platform_set_drvdata(pdev, ppi_dev); + CAM_DBG(CAM_ISP, "PPI:%d probe successful", + ppi_hw_intf->hw_idx); + + return 0; +free_dev: + kfree(ppi_dev); +free_hw_info: + kfree(ppi_hw_info); +free_hw_intf: + kfree(ppi_hw_intf); +err: + return rc; +} + +static void cam_ppi_component_unbind(struct device *dev, + struct device *master_dev, void *data) +{ + struct cam_csid_ppi_hw *ppi_dev = NULL; + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + struct platform_device *pdev = to_platform_device(dev); + + ppi_dev = (struct cam_csid_ppi_hw *)platform_get_drvdata(pdev); + ppi_hw_intf = ppi_dev->hw_intf; + ppi_hw_info = ppi_dev->hw_info; + + CAM_DBG(CAM_ISP, "PPI:%d remove", ppi_dev->hw_intf->hw_idx); + + cam_csid_ppi_hw_deinit(ppi_dev); + + kfree(ppi_dev); + kfree(ppi_hw_info); + kfree(ppi_hw_intf); +} + +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_csid_ppi_hw_list[hw_idx]) { + *csid_ppi_hw = cam_csid_ppi_hw_list[hw_idx]; + } else { + *csid_ppi_hw = NULL; + rc = -1; + } + + return rc; +} +EXPORT_SYMBOL(cam_csid_ppi_hw_init); + +const static struct component_ops cam_ppi_component_ops = { + .bind = cam_ppi_component_bind, + .unbind = cam_ppi_component_unbind, +}; + +int cam_csid_ppi_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_ISP, "Adding PPI component"); + rc = component_add(&pdev->dev, &cam_ppi_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); + + return rc; +} + +int cam_csid_ppi_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_ppi_component_ops); + return 0; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h new file mode 100644 index 000000000000..d8995f811b1f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_PPI_DEV_H_ +#define _CAM_CSID_PPI_DEV_H_ + +#include "cam_isp_hw.h" + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data); +int cam_csid_ppi_probe(struct platform_device *pdev); +int cam_csid_ppi_remove(struct platform_device *pdev); + +#endif /*_CAM_CSID_PPI_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index ddad24cd23df..7e75cc264a55 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -9,6 +9,7 @@ #include #include "cam_tfe_csid_core.h" +#include "cam_csid_ppi_core.h" #include "cam_isp_hw.h" #include "cam_soc_util.h" #include "cam_io_util.h" @@ -733,7 +734,9 @@ static int cam_tfe_csid_enable_csi2( { const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_csid_ppi_cfg ppi_lane_cfg; uint32_t val = 0; + uint32_t ppi_index = 0, rc; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -797,6 +800,25 @@ static int cam_tfe_csid_enable_csi2( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + ppi_lane_cfg.lane_type = csid_hw->csi2_rx_cfg.lane_type; + ppi_lane_cfg.lane_num = csid_hw->csi2_rx_cfg.lane_num; + ppi_lane_cfg.lane_cfg = csid_hw->csi2_rx_cfg.lane_cfg; + + CAM_DBG(CAM_ISP, "ppi_index to init %d", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.init( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + &ppi_lane_cfg, + sizeof(struct cam_csid_ppi_cfg)); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Init Failed", + ppi_index); + return rc; + } + } + + return 0; } @@ -805,6 +827,7 @@ static int cam_tfe_csid_disable_csi2( { const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + uint32_t ppi_index = 0, rc; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -821,6 +844,19 @@ static int cam_tfe_csid_disable_csi2( cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + /* De-Initialize the PPI bridge */ + CAM_DBG(CAM_ISP, "ppi_index to de-init %d\n", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.deinit( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + NULL, 0); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d De-Init Failed", ppi_index); + return rc; + } + } + return 0; } @@ -2456,13 +2492,14 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) unsigned long flags; uint32_t i, val; - csid_hw = (struct cam_tfe_csid_hw *)data; - if (!data) { CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); return IRQ_HANDLED; } + csid_hw = (struct cam_tfe_csid_hw *)data; + CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); + csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; csi2_reg = csid_reg->csi2_reg; @@ -2961,6 +2998,23 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, goto err; } + /* Check if ppi bridge is present or not? */ + tfe_csid_hw->ppi_enable = of_property_read_bool( + csid_hw_info->soc_info.pdev->dev.of_node, + "ppi-enable"); + + if (!tfe_csid_hw->ppi_enable) + return 0; + + /* Initialize the PPI bridge */ + for (i = 0; i < CAM_CSID_PPI_HW_MAX; i++) { + rc = cam_csid_ppi_hw_init(&tfe_csid_hw->ppi_hw_intf[i], i); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI init failed for PPI %d", i); + break; + } + } + return 0; err: if (rc) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index fc0b72677a58..d211a70c56bc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -9,6 +9,7 @@ #include "cam_hw.h" #include "cam_tfe_csid_hw_intf.h" #include "cam_tfe_csid_soc.h" +#include "cam_csid_ppi_core.h" #define CAM_TFE_CSID_CID_MAX 4 @@ -383,6 +384,9 @@ struct cam_tfe_csid_path_cfg { * @lock_state csid spin lock * @event_cb: Callback function to hw mgr in case of hw events * @event_cb_priv: Context data + * @ppi_hw_intf interface to ppi hardware + * @ppi_enabled flag to specify if the hardware has ppi bridge + * or not * */ struct cam_tfe_csid_hw { @@ -409,6 +413,8 @@ struct cam_tfe_csid_hw { spinlock_t spin_lock; cam_hw_mgr_event_cb_func event_cb; void *event_cb_priv; + struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX]; + bool ppi_enable; }; int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/camera_main.c b/drivers/camera_main.c index b73c9992f093..ebc9559d51ab 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -54,6 +54,7 @@ #include "cam_top_tpg.h" #include "cam_tfe_dev.h" #include "cam_tfe_csid530.h" +#include "cam_csid_ppi100.h" #include "camera_main.h" struct camera_submodule_component { @@ -76,6 +77,15 @@ static const struct camera_submodule_component camera_base[] = { {&cam_hw_cdm_init_module, &cam_hw_cdm_exit_module}, }; +static const struct camera_submodule_component camera_tfe[] = { +#ifdef CONFIG_SPECTRA_TFE + {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, + {&cam_csid_ppi100_init_module, &cam_csid_ppi100_exit_module}, + {&cam_tfe_init_module, &cam_tfe_exit_module}, + {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, +#endif +}; + static const struct camera_submodule_component camera_isp[] = { #ifdef CONFIG_SPECTRA_ISP {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, @@ -86,14 +96,6 @@ static const struct camera_submodule_component camera_isp[] = { #endif }; -static const struct camera_submodule_component camera_tfe[] = { -#ifdef CONFIG_SPECTRA_TFE - {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, - {&cam_tfe_init_module, &cam_tfe_exit_module}, - {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, -#endif -}; - static const struct camera_submodule_component camera_sensor[] = { #ifdef CONFIG_SPECTRA_SENSOR {&cam_res_mgr_init, &cam_res_mgr_exit}, @@ -162,16 +164,16 @@ static const struct camera_submodule submodule_table[] = { .num_component = ARRAY_SIZE(camera_base), .component = camera_base, }, - { - .name = "Camera ISP", - .num_component = ARRAY_SIZE(camera_isp), - .component = camera_isp, - }, { .name = "Camera TFE", .num_component = ARRAY_SIZE(camera_tfe), .component = camera_tfe, }, + { + .name = "Camera ISP", + .num_component = ARRAY_SIZE(camera_isp), + .component = camera_isp, + }, { .name = "Camera SENSOR", .num_component = ARRAY_SIZE(camera_sensor), From 23a77b634299c1468f39b003621b63a45d3897d9 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 26 Mar 2020 13:24:42 +0530 Subject: [PATCH 391/790] msm: camera: isp: validate in_port before accessing in_port information we are getting from the UMD and accessing it directly without validation which might lead to corruption and device failure. CRs-Fixed: 2629969 Change-Id: I0a1c57db9b94f9657427872ae6797635c6aed668 Signed-off-by: Tejas Prajapati --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 50 ++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index df5c9a2e2c85..ca621c9d99bd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2110,18 +2110,36 @@ err: static int cam_ife_mgr_check_and_update_fe_v0( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_acquire_hw_info *acquire_hw_info) + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t acquire_info_size) { int i; struct cam_isp_in_port_info *in_port = NULL; uint32_t in_port_length = 0; uint32_t total_in_port_length = 0; + if (acquire_hw_info->input_info_offset >= + acquire_hw_info->input_info_size) { + CAM_ERR(CAM_ISP, + "Invalid size offset 0x%x is greater then size 0x%x", + acquire_hw_info->input_info_offset, + acquire_hw_info->input_info_size); + return -EINVAL; + } + 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++) { + if (((uint8_t *)in_port + + sizeof(struct cam_isp_in_port_info)) > + ((uint8_t *)acquire_hw_info + + acquire_info_size)) { + CAM_ERR(CAM_ISP, "Invalid size"); + return -EINVAL; + } + if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", @@ -2155,18 +2173,36 @@ static int cam_ife_mgr_check_and_update_fe_v0( static int cam_ife_mgr_check_and_update_fe_v2( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_acquire_hw_info *acquire_hw_info) + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t acquire_info_size) { int i; struct cam_isp_in_port_info_v2 *in_port = NULL; uint32_t in_port_length = 0; uint32_t total_in_port_length = 0; + if (acquire_hw_info->input_info_offset >= + acquire_hw_info->input_info_size) { + CAM_ERR(CAM_ISP, + "Invalid size offset 0x%x is greater then size 0x%x", + acquire_hw_info->input_info_offset, + acquire_hw_info->input_info_size); + return -EINVAL; + } + in_port = (struct cam_isp_in_port_info_v2 *) ((uint8_t *)&acquire_hw_info->data + acquire_hw_info->input_info_offset); for (i = 0; i < acquire_hw_info->num_inputs; i++) { + if (((uint8_t *)in_port + + sizeof(struct cam_isp_in_port_info)) > + ((uint8_t *)acquire_hw_info + + acquire_info_size)) { + CAM_ERR(CAM_ISP, "Invalid size"); + return -EINVAL; + } + if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", @@ -2203,7 +2239,8 @@ static int cam_ife_mgr_check_and_update_fe_v2( 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) + struct cam_isp_acquire_hw_info *acquire_hw_info, + uint32_t acquire_info_size) { uint32_t major_ver = 0, minor_ver = 0; @@ -2216,10 +2253,10 @@ static int cam_ife_mgr_check_and_update_fe( switch (major_ver) { case 1: return cam_ife_mgr_check_and_update_fe_v0( - ife_ctx, acquire_hw_info); + ife_ctx, acquire_hw_info, acquire_info_size); case 2: return cam_ife_mgr_check_and_update_fe_v2( - ife_ctx, acquire_hw_info); + ife_ctx, acquire_hw_info, acquire_info_size); break; default: CAM_ERR(CAM_ISP, "Invalid ver of common info from user"); @@ -3014,7 +3051,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; - rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info); + rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info, + acquire_args->acquire_info_size); if (rc) { CAM_ERR(CAM_ISP, "buffer size is not enough"); goto free_cdm; From 139ced0c94395a1521ccf45f9d0b0578178c4212 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 17 Jun 2020 21:17:29 -0700 Subject: [PATCH 392/790] msm: camera: custom: Enable driver compilation & minor fixes Enable custom driver compilation on lahaina and few minor fixes in custom HW driver. CRs-Fixed: 2716300 Change-Id: I6f9ead5d2d67d91c14daf200ba12e95a1afec61d Signed-off-by: Karthik Anantha Ram --- config/lahainacamera.conf | 1 + config/lahainacameraconf.h | 3 ++- .../cam_custom_hw1/cam_custom_sub_mod_dev.c | 2 +- drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c | 5 ++--- drivers/cam_utils/cam_debug_util.c | 1 + 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config/lahainacamera.conf b/config/lahainacamera.conf index af13af07e534..3e3d0744ca0b 100644 --- a/config/lahainacamera.conf +++ b/config/lahainacamera.conf @@ -14,4 +14,5 @@ export CONFIG_SPECTRA_ISP=y export CONFIG_SPECTRA_SENSOR=y export CONFIG_SPECTRA_ICP=y export CONFIG_SPECTRA_JPEG=y +export CONFIG_SPECTRA_CUSTOM=y endif diff --git a/config/lahainacameraconf.h b/config/lahainacameraconf.h index 58a006d2e4cd..a780c96bfddb 100644 --- a/config/lahainacameraconf.h +++ b/config/lahainacameraconf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ @@ -9,3 +9,4 @@ #define CONFIG_SPECTRA_SENSOR 1 #define CONFIG_SPECTRA_ICP 1 #define CONFIG_SPECTRA_JPEG 1 +#define CONFIG_SPECTRA_CUSTOM 1 diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c index d06b0ac2d38b..9f1eb99562d9 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_dev.c @@ -117,7 +117,7 @@ static int cam_custom_hw_sub_mod_component_bind(struct device *dev, /* needs to be invoked when custom hw is in place */ //cam_custom_hw_sub_mod_init_hw(hw, NULL, 0); - CAM_DBG(CAM_CUSTOM, "HW idx:%d component bound successfully"); + CAM_DBG(CAM_CUSTOM, "HW idx:%d component bound successfully", hw_intf->hw_idx); return rc; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index 91fc1730b083..91a4e2ef26b6 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -489,16 +489,15 @@ static int cam_custom_hw_mgr_notify( custom_ctx->event_cb(custom_ctx->cb_priv, CAM_CUSTOM_HW_EVENT_RUP_DONE, ®_upd_data); break; - case CAM_CUSTOM_HW_EVENT_RUP_DONE: + case CAM_CUSTOM_HW_EVENT_FRAME_DONE: CAM_DBG(CAM_CUSTOM, "Notify FRAME DONE for ctx %u", custom_ctx->ctx_index); /* fill the evt data struct */ done_evt_data.num_handles = 1; - done_evt_data.resource_handle = 0; custom_ctx->event_cb(custom_ctx->cb_priv, CAM_CUSTOM_HW_EVENT_RUP_DONE, &done_evt_data); break; - case CAM_CUSTOM_HW_EVENT_RUP_DONE: + case CAM_CUSTOM_HW_EVENT_ERROR: CAM_DBG(CAM_CUSTOM, "Notify ERROR for ctx %u", custom_ctx->ctx_index); /* fill the evt data struct */ diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index 882b9ea678cc..a655b084d35e 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -196,6 +196,7 @@ const char *cam_get_module_name(unsigned int module_id) break; case CAM_CUSTOM: name = "CAM-CUSTOM"; + break; case CAM_OPE: name = "CAM-OPE"; break; From c92348064f2c20a8707be031e629130d2f83168c Mon Sep 17 00:00:00 2001 From: Suresh Vankadara Date: Mon, 22 Jun 2020 15:23:00 +0530 Subject: [PATCH 393/790] msm: camera: common: Update holi camera workq wrapper Update OPE and TFE drivers to use new camera workq wrapper functions. CRs-Fixed: 2716498 Change-Id: I05ecefb191a544c2953ac7e71a7c9a95d1f1fb10 Signed-off-by: Suresh Vankadara --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 8 ++++++- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 23 ++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 6425088a462c..a28b9773dfd2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5323,6 +5323,11 @@ err: return -ENOMEM; } +static void cam_req_mgr_process_tfe_worker(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { int rc = -EFAULT; @@ -5477,7 +5482,8 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) /* Create Worker for tfe_hw_mgr with 10 tasks */ rc = cam_req_mgr_workq_create("cam_tfe_worker", 10, - &g_tfe_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0); + &g_tfe_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0, + cam_req_mgr_process_tfe_worker); if (rc < 0) { CAM_ERR(CAM_ISP, "Unable to create worker"); goto end; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 5b459dd4f366..6016652717c5 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -3573,6 +3573,21 @@ compat_hw_name_failed: return rc; } +static void cam_req_mgr_process_ope_command_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + +static void cam_req_mgr_process_ope_msg_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + +static void cam_req_mgr_process_ope_timer_queue(struct work_struct *w) +{ + cam_req_mgr_process_workq(w); +} + static int cam_ope_mgr_create_wq(void) { @@ -3581,21 +3596,23 @@ static int cam_ope_mgr_create_wq(void) rc = cam_req_mgr_workq_create("ope_command_queue", OPE_WORKQ_NUM_TASK, &ope_hw_mgr->cmd_work, CRM_WORKQ_USAGE_NON_IRQ, - 0); + 0, cam_req_mgr_process_ope_command_queue); if (rc) { CAM_ERR(CAM_OPE, "unable to create a command worker"); goto cmd_work_failed; } rc = cam_req_mgr_workq_create("ope_message_queue", OPE_WORKQ_NUM_TASK, - &ope_hw_mgr->msg_work, CRM_WORKQ_USAGE_IRQ, 0); + &ope_hw_mgr->msg_work, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_ope_msg_queue); if (rc) { CAM_ERR(CAM_OPE, "unable to create a message worker"); goto msg_work_failed; } rc = cam_req_mgr_workq_create("ope_timer_queue", OPE_WORKQ_NUM_TASK, - &ope_hw_mgr->timer_work, CRM_WORKQ_USAGE_IRQ, 0); + &ope_hw_mgr->timer_work, CRM_WORKQ_USAGE_IRQ, 0, + cam_req_mgr_process_ope_timer_queue); if (rc) { CAM_ERR(CAM_OPE, "unable to create a timer worker"); goto timer_work_failed; From 124ac14bf92ae092a23b6514b95cf45aa301fb7a Mon Sep 17 00:00:00 2001 From: zhuo Date: Fri, 19 Jun 2020 16:19:04 +0800 Subject: [PATCH 394/790] msm: camera: isp: Reset offline context flag This change resets the offline context flag, otherwise the packet may be applied to HW immediately if this context is offline context last time. CRs-Fixed: 2696977 Change-Id: I2fc836f7ba2889ec62273c3b12cc4050736f587b Signed-off-by: zhuo --- drivers/cam_isp/cam_isp_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 7a189faeeda1..d9abaff11f82 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3776,6 +3776,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; + ctx_isp->offline_context = false; ctx_isp->rdi_only_context = false; ctx_isp->req_info.last_bufdone_req_id = 0; From 14ed8a149e4015841bda88eaca32b2db70ecfe28 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Tue, 2 Jun 2020 13:49:15 +0530 Subject: [PATCH 395/790] msm: camera: csiphy: Enable CSIPHY v1.2.4 in PHY driver Add support for CSIPHY v1.2.4 in the PHY driver. CRs-Fixed: 2709344 Change-Id: Ic0eeabe2e978e6f2513e61a063e8b354c8466954 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/cam_csiphy_soc.c | 20 +++++++++++++++++++ .../cam_csiphy/cam_csiphy_soc.h | 1 + 2 files changed, 21 insertions(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index bedd0570b4e0..dc3bda4d33e5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -401,6 +401,26 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_1_2_3; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.4")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_3_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_3_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_3_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2_3; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2_3; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2_3; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_3; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->hw_version = CSIPHY_VERSION_V124; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2_3; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 0416d8cda66d..9d3113fb9edf 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -31,6 +31,7 @@ #define CSIPHY_VERSION_V12 0x12 #define CSIPHY_VERSION_V121 0x121 #define CSIPHY_VERSION_V123 0x123 +#define CSIPHY_VERSION_V124 0x124 #define CSIPHY_VERSION_V20 0x20 #define CSIPHY_VERSION_V201 0x201 From cf8074099294d9e80be43d7a6278004d2fe11e7c Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 18 Jun 2020 19:03:40 -0700 Subject: [PATCH 396/790] msm: camera: common: Enable debugfs compile check. Guards debugfs features in camera driver to only be compiled when CONFIG_DEBUG_FS is enabled. CRs-Fixed: 2717236 Change-Id: I0de77741301d259cbec64e8a2e27830981b2b69d Signed-off-by: Karthik Jayakumar --- drivers/cam_cpas/cam_cpas_hw.c | 37 ++++--- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 99 ++++++------------- drivers/cam_isp/cam_isp_context.c | 36 +++---- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 79 ++++++--------- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 77 ++++++--------- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 31 +++--- drivers/cam_req_mgr/cam_mem_mgr.c | 36 ++++--- drivers/cam_req_mgr/cam_req_mgr_debug.c | 49 ++++----- drivers/cam_smmu/cam_smmu_api.c | 47 ++++----- drivers/cam_sync/cam_sync.c | 29 +++--- drivers/cam_utils/cam_soc_util.c | 60 +++++------ 11 files changed, 251 insertions(+), 329 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index c864a7fb286a..2aa68d52d6fe 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -2025,32 +2025,31 @@ static int cam_cpas_util_get_internal_ops(struct platform_device *pdev, return rc; } +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_cpas_util_create_debugfs( struct cam_cpas *cpas_core) { int rc = 0; cpas_core->dentry = debugfs_create_dir("camera_cpas", NULL); - if (!cpas_core->dentry) - return -ENOMEM; - - if (!debugfs_create_bool("ahb_bus_scaling_disable", - 0644, - cpas_core->dentry, - &cpas_core->ahb_bus_scaling_disable)) { - CAM_ERR(CAM_CPAS, - "failed to create ahb_bus_scaling_disable entry"); - rc = -ENOMEM; - goto err; + if (IS_ERR(cpas_core->dentry)) { + rc = PTR_ERR(cpas_core->dentry); + goto end; } + + debugfs_create_bool("ahb_bus_scaling_disable", 0644, cpas_core->dentry, + &cpas_core->ahb_bus_scaling_disable); - return 0; - -err: - debugfs_remove_recursive(cpas_core->dentry); - cpas_core->dentry = NULL; +end: return rc; } +#else +static inline int cam_cpas_util_create_debugfs(struct cam_cpas *cpas_core) +{ + CAM_WARN(CAM_CPAS, "DebugFS not enabled in kernel"); + return 0; +} +#endif int cam_cpas_hw_probe(struct platform_device *pdev, struct cam_hw_intf **hw_intf) @@ -2195,9 +2194,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, if (rc) goto axi_cleanup; - rc = cam_cpas_util_create_debugfs(cpas_core); - if (rc) - CAM_WARN(CAM_CPAS, "Failed to create dentry"); + rc = cam_cpas_util_create_debugfs(cpas_core); *hw_intf = cpas_hw_intf; return 0; @@ -2250,7 +2247,9 @@ int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf) cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client); cam_cpas_util_client_cleanup(cpas_hw); cam_cpas_soc_deinit_resources(&cpas_hw->soc_info); +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(cpas_core->dentry); +#endif cpas_core->dentry = NULL; flush_workqueue(cpas_core->work_queue); destroy_workqueue(cpas_core->work_queue); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 268256d8a438..1a233ef10e65 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1882,87 +1882,51 @@ static int cam_icp_get_a5_fw_dump_lvl(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_a5_fw_dump_lvl, cam_icp_set_a5_fw_dump_lvl, "%08llu"); +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_icp_hw_mgr_create_debugfs_entry(void) { int rc = 0; icp_hw_mgr.dentry = debugfs_create_dir("camera_icp", NULL); - if (IS_ERR_OR_NULL(icp_hw_mgr.dentry)) { - CAM_ERR(CAM_ICP, "Debugfs entry dir: %s failed", - "camrea_icp"); - return -ENOMEM; + if (IS_ERR(icp_hw_mgr.dentry)) { + rc = PTR_ERR(icp_hw_mgr.dentry); + goto end; } - if (!debugfs_create_bool("icp_pc", - 0644, - icp_hw_mgr.dentry, - &icp_hw_mgr.icp_pc_flag)) { - CAM_ERR(CAM_ICP, "failed to create icp_pc entry"); - rc = -ENOMEM; - goto err; - } + debugfs_create_bool("icp_pc", 0644, icp_hw_mgr.dentry, + &icp_hw_mgr.icp_pc_flag); - if (!debugfs_create_bool("ipe_bps_pc", - 0644, - icp_hw_mgr.dentry, - &icp_hw_mgr.ipe_bps_pc_flag)) { - CAM_ERR(CAM_ICP, "failed to create ipe_bps_pc entry"); - rc = -ENOMEM; - goto err; - } + debugfs_create_bool("ipe_bps_pc", 0644, icp_hw_mgr.dentry, + &icp_hw_mgr.ipe_bps_pc_flag); - if (!debugfs_create_file("icp_debug_clk", - 0644, - icp_hw_mgr.dentry, NULL, - &cam_icp_debug_default_clk)) { - CAM_ERR(CAM_ICP, "failed to create icp_debug_clk entry"); - rc = -ENOMEM; - goto err; - } + debugfs_create_file("icp_debug_clk", 0644, icp_hw_mgr.dentry, NULL, + &cam_icp_debug_default_clk); - if (!debugfs_create_bool("a5_jtag_debug", - 0644, - icp_hw_mgr.dentry, - &icp_hw_mgr.a5_jtag_debug)) { - rc = -ENOMEM; - goto err; - } + debugfs_create_bool("a5_jtag_debug", 0644, icp_hw_mgr.dentry, + &icp_hw_mgr.a5_jtag_debug); - if (!debugfs_create_file("a5_debug_type", - 0644, - icp_hw_mgr.dentry, - NULL, &cam_icp_debug_type_fs)) { - CAM_ERR(CAM_ICP, "failed to create a5_debug_type"); - rc = -ENOMEM; - goto err; - } + debugfs_create_file("a5_debug_type", 0644, icp_hw_mgr.dentry, NULL, + &cam_icp_debug_type_fs); - if (!debugfs_create_file("a5_debug_lvl", - 0644, - icp_hw_mgr.dentry, - NULL, &cam_icp_debug_fs)) { - CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl"); - rc = -ENOMEM; - goto err; - } - - if (!debugfs_create_file("a5_fw_dump_lvl", - 0644, - icp_hw_mgr.dentry, - NULL, &cam_icp_debug_fw_dump)) { - CAM_ERR(CAM_ICP, "failed to create a5_fw_dump_lvl"); - rc = -ENOMEM; - goto err; - } + debugfs_create_file("a5_debug_lvl", 0644, icp_hw_mgr.dentry, NULL, + &cam_icp_debug_fs); + debugfs_create_file("a5_fw_dump_lvl", 0644, icp_hw_mgr.dentry, NULL, + &cam_icp_debug_fw_dump); +end: /* Set default hang dump lvl */ icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; return rc; -err: - debugfs_remove_recursive(icp_hw_mgr.dentry); - icp_hw_mgr.dentry = NULL; - return rc; } +#else +static inline int cam_icp_hw_mgr_create_debugfs_entry(void) +{ + /* Set default hang dump lvl */ + icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; + CAM_WARN(CAM_ICP, "DebugFS not enabled in kernel"); + return 0; +} +#endif static int cam_icp_mgr_process_cmd(void *priv, void *data) { @@ -6000,10 +5964,9 @@ static int cam_icp_mgr_create_wq(void) } rc = cam_icp_hw_mgr_create_debugfs_entry(); - if (rc) { - CAM_ERR(CAM_ICP, "create_debugfs_entry fail= rc: %d", rc); + if (rc) goto debugfs_create_failed; - } + for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) icp_hw_mgr.msg_work->task.pool[i].payload = &icp_hw_mgr.msg_work_data[i]; @@ -6174,7 +6137,9 @@ void cam_icp_hw_mgr_deinit(void) { int i = 0; +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(icp_hw_mgr.dentry); +#endif icp_hw_mgr.dentry = NULL; cam_icp_mgr_destroy_wq(); kfree(icp_hw_mgr.devices[CAM_ICP_DEV_BPS]); diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 71bac56daa40..5f54e438421a 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5297,30 +5297,30 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, return rc; } +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_isp_context_debug_register(void) { - isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", - NULL); + int rc = 0; - if (IS_ERR_OR_NULL(isp_ctx_debug.dentry)) { - CAM_ERR(CAM_ISP, "failed to create dentry"); - return -ENOMEM; + isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", NULL); + if (IS_ERR(isp_ctx_debug.dentry)) { + rc = PTR_ERR(isp_ctx_debug.dentry); + goto end; } - if (!debugfs_create_u32("enable_state_monitor_dump", - 0644, - isp_ctx_debug.dentry, - &isp_ctx_debug.enable_state_monitor_dump)) { - CAM_ERR(CAM_ISP, "failed to create enable_state_monitor_dump"); - goto err; - } + debugfs_create_u32("enable_state_monitor_dump", 0644, + isp_ctx_debug.dentry, &isp_ctx_debug.enable_state_monitor_dump); - return 0; - -err: - debugfs_remove_recursive(isp_ctx_debug.dentry); - return -ENOMEM; +end: + return rc; } +#else +static inline int cam_isp_context_debug_register(void) +{ + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); + return 0; +} +#endif int cam_isp_context_init(struct cam_isp_context *ctx, struct cam_context *ctx_base, @@ -5400,7 +5400,9 @@ int cam_isp_context_deinit(struct cam_isp_context *ctx) __cam_isp_ctx_substate_val_to_type( ctx->substate_activated)); +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(isp_ctx_debug.dentry); +#endif isp_ctx_debug.dentry = NULL; memset(ctx, 0, sizeof(*ctx)); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index ca621c9d99bd..9bd34db7f216 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7725,64 +7725,43 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug, cam_ife_get_camif_debug, cam_ife_set_camif_debug, "%16llu"); +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_ife_hw_mgr_debug_register(void) { - g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", - NULL); + int rc = 0; - if (!g_ife_hw_mgr.debug_cfg.dentry) { - CAM_ERR(CAM_ISP, "failed to create dentry"); - return -ENOMEM; + g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", NULL); + if (IS_ERR(g_ife_hw_mgr.debug_cfg.dentry)) + { + rc = PTR_ERR(g_ife_hw_mgr.debug_cfg.dentry); + goto end; } - if (!debugfs_create_file("ife_csid_debug", - 0644, - g_ife_hw_mgr.debug_cfg.dentry, NULL, - &cam_ife_csid_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_ife_csid_debug"); - goto err; - } - - if (!debugfs_create_u32("enable_recovery", - 0644, + debugfs_create_file("ife_csid_debug", 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_csid_debug); + debugfs_create_u32("enable_recovery", 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.enable_recovery)) { - CAM_ERR(CAM_ISP, "failed to create enable_recovery"); - goto err; - } - - if (!debugfs_create_bool("enable_req_dump", - 0644, + &g_ife_hw_mgr.debug_cfg.enable_recovery); + debugfs_create_bool("enable_req_dump", 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.enable_req_dump)) { - CAM_ERR(CAM_ISP, "failed to create enable_req_dump"); - goto err; - } - - if (!debugfs_create_file("ife_camif_debug", - 0644, - g_ife_hw_mgr.debug_cfg.dentry, NULL, - &cam_ife_camif_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug"); - goto err; - } - - if (!debugfs_create_bool("per_req_reg_dump", - 0644, + &g_ife_hw_mgr.debug_cfg.enable_req_dump); + debugfs_create_file("ife_camif_debug", 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_camif_debug); + debugfs_create_bool("per_req_reg_dump", 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.per_req_reg_dump)) { - CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); - goto err; - } - + &g_ife_hw_mgr.debug_cfg.per_req_reg_dump); +end: g_ife_hw_mgr.debug_cfg.enable_recovery = 0; - - return 0; - -err: - debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); - return -ENOMEM; + return rc; } +#else +static inline int cam_ife_hw_mgr_debug_register(void) +{ + g_ife_hw_mgr.debug_cfg.enable_recovery = 0; + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); + return 0; +} +#endif int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { @@ -7792,8 +7771,6 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) struct cam_ife_hw_mgr_ctx *ctx_pool; struct cam_isp_hw_mgr_res *res_list_ife_out; - CAM_DBG(CAM_ISP, "Enter"); - memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr)); mutex_init(&g_ife_hw_mgr.ctx_mutex); @@ -8001,7 +7978,9 @@ void cam_ife_hw_mgr_deinit(void) int i = 0; cam_req_mgr_workq_destroy(&g_ife_hw_mgr.workq); +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); +#endif g_ife_hw_mgr.debug_cfg.dentry = NULL; for (i = 0; i < CAM_CTX_MAX; i++) { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 6425088a462c..a2697eb15a21 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5263,65 +5263,42 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_camif_debug, cam_tfe_get_camif_debug, cam_tfe_set_camif_debug, "%16llu"); +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_tfe_hw_mgr_debug_register(void) { - g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", - NULL); + int rc = 0; - if (!g_tfe_hw_mgr.debug_cfg.dentry) { - CAM_ERR(CAM_ISP, "failed to create dentry"); - return -ENOMEM; + g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", NULL); + if (IS_ERR(g_tfe_hw_mgr.debug_cfg.dentry)) { + rc = PTR_ERR(g_tfe_hw_mgr.debug_cfg.dentry); + goto end; } - if (!debugfs_create_file("tfe_csid_debug", - 0644, - g_tfe_hw_mgr.debug_cfg.dentry, NULL, - &cam_tfe_csid_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_tfe_csid_debug"); - goto err; - } - - if (!debugfs_create_u32("enable_recovery", - 0644, + debugfs_create_file("tfe_csid_debug", 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_csid_debug); + debugfs_create_u32("enable_recovery", 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.enable_recovery)) { - CAM_ERR(CAM_ISP, "failed to create enable_recovery"); - goto err; - } - - if (!debugfs_create_u32("enable_reg_dump", - 0644, + &g_tfe_hw_mgr.debug_cfg.enable_recovery); + debugfs_create_u32("enable_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.enable_reg_dump)) { - CAM_ERR(CAM_ISP, "failed to create enable_reg_dump"); - goto err; - } - - if (!debugfs_create_file("tfe_camif_debug", - 0644, - g_tfe_hw_mgr.debug_cfg.dentry, NULL, - &cam_tfe_camif_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_tfe_camif_debug"); - goto err; - } - - if (!debugfs_create_u32("per_req_reg_dump", - 0644, + &g_tfe_hw_mgr.debug_cfg.enable_reg_dump); + debugfs_create_file("tfe_camif_debug", 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_camif_debug); + debugfs_create_u32("per_req_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump)) { - CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); - goto err; - } - - + &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump); +end: g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; - - return 0; - -err: - debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); - return -ENOMEM; + return rc; } +#else +static inline int cam_tfe_hw_mgr_debug_register(void) +{ + g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); + return 0; +} +#endif int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { @@ -5529,7 +5506,9 @@ void cam_tfe_hw_mgr_deinit(void) int i = 0; cam_req_mgr_workq_destroy(&g_tfe_hw_mgr.workq); +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); +#endif g_tfe_hw_mgr.debug_cfg.dentry = NULL; for (i = 0; i < CAM_CTX_MAX; i++) { diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 537fc48a619e..a777458966ad 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -1013,33 +1013,32 @@ static int cam_lrme_mgr_hw_config(void *hw_mgr_priv, return rc; } +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_lrme_mgr_create_debugfs_entry(void) { int rc = 0; g_lrme_hw_mgr.debugfs_entry.dentry = debugfs_create_dir("camera_lrme", NULL); - if (!g_lrme_hw_mgr.debugfs_entry.dentry) { - CAM_ERR(CAM_LRME, "failed to create dentry"); - return -ENOMEM; + if (IS_ERR(g_lrme_hw_mgr.debugfs_entry.dentry)) { + rc = PTR_ERR(g_lrme_hw_mgr.debugfs_entry.dentry); + goto end; } - if (!debugfs_create_bool("dump_register", - 0644, + debugfs_create_bool("dump_register", 0644, g_lrme_hw_mgr.debugfs_entry.dentry, - &g_lrme_hw_mgr.debugfs_entry.dump_register)) { - CAM_ERR(CAM_LRME, "failed to create dump register entry"); - rc = -ENOMEM; - goto err; - } - - return rc; + &g_lrme_hw_mgr.debugfs_entry.dump_register); err: - debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); - g_lrme_hw_mgr.debugfs_entry.dentry = NULL; return rc; } +#else +static inline int cam_lrme_mgr_create_debugfs_entry(void) +{ + CAM_WARN(CAM_LRME, "DebugFS not enabled in kernel"); + return 0; +} +#endif int cam_lrme_mgr_register_device( @@ -1140,6 +1139,9 @@ int cam_lrme_mgr_deregister_device(int device_index) int cam_lrme_hw_mgr_deinit(void) { mutex_destroy(&g_lrme_hw_mgr.hw_mgr_mutex); +#if IS_ENABLED(CONFIG_DEBUG_FS) + debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); +#endif memset(&g_lrme_hw_mgr, 0x0, sizeof(g_lrme_hw_mgr)); return 0; @@ -1194,7 +1196,6 @@ int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, hw_mgr_intf->hw_dump = cam_lrme_mgr_hw_dump; cam_lrme_mgr_create_debugfs_entry(); - CAM_DBG(CAM_LRME, "Hw mgr init done"); return rc; } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 97a6c8b1b094..e386aac308f3 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -119,28 +119,29 @@ static int cam_mem_util_unmap_cpu_va(struct dma_buf *dmabuf, return rc; } +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_mem_mgr_create_debug_fs(void) { + int rc = 0; + tbl.dentry = debugfs_create_dir("camera_memmgr", NULL); - if (!tbl.dentry) { - CAM_ERR(CAM_MEM, "failed to create dentry"); - return -ENOMEM; + if (IS_ERR(tbl.dentry)) { + rc = PTR_ERR(tbl.dentry); + goto end; } - if (!debugfs_create_bool("alloc_profile_enable", - 0644, - tbl.dentry, - &tbl.alloc_profile_enable)) { - CAM_ERR(CAM_MEM, - "failed to create alloc_profile_enable"); - goto err; - } - - return 0; -err: - debugfs_remove_recursive(tbl.dentry); - return -ENOMEM; + debugfs_create_bool("alloc_profile_enable", 0644, tbl.dentry, + &tbl.alloc_profile_enable); +end: + return rc; } +#else +static inline int cam_mem_mgr_create_debug_fs(void) +{ + CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel"); + return 0; +} +#endif int cam_mem_mgr_init(void) { @@ -953,6 +954,9 @@ static int cam_mem_mgr_cleanup_table(void) void cam_mem_mgr_deinit(void) { +#if IS_ENABLED(CONFIG_DEBUG_FS) + debugfs_remove_recursive(tbl.dentry); +#endif atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED); cam_mem_mgr_cleanup_table(); mutex_lock(&tbl.m_lock); diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index 6b6a91b6303b..eced0037d8fa 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -8,7 +8,6 @@ #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; -static struct dentry *debugfs_root; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { @@ -111,32 +110,27 @@ static const struct file_operations session_info = { .write = session_info_write, }; +#if IS_ENABLED(CONFIG_DEBUG_FS) +static struct dentry *debugfs_root; int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) { - char dirname[32] = {0}; - snprintf(dirname, sizeof(dirname), "cam_req_mgr"); - debugfs_root = debugfs_create_dir(dirname, NULL); - if (IS_ERR_OR_NULL(debugfs_root)) { - CAM_ERR(CAM_CRM, "Failed to create cam_req_mgr debugfs dir"); - return -ENOMEM; + int rc = 0; + + debugfs_root = debugfs_create_dir("cam_req_mgr", NULL); + if (IS_ERR(debugfs_root)) { + rc = PTR_ERR(debugfs_root); + goto end; } + + debugfs_create_file("sessions_info", 0644, debugfs_root, core_dev, + &session_info); + debugfs_create_file("bubble_recovery", 0644, debugfs_root, core_dev, + &bubble_recovery); + debugfs_create_bool("recovery_on_apply_fail", 0644, debugfs_root, + &core_dev->recovery_on_apply_fail); - if (!debugfs_create_file("sessions_info", 0644, - debugfs_root, core_dev, &session_info)) - CAM_WARN(CAM_CRM, - "Failed to create sessions_info debugfs file"); - - if (!debugfs_create_file("bubble_recovery", 0644, - debugfs_root, core_dev, &bubble_recovery)) - CAM_WARN(CAM_CRM, - "Failed to create bubble_recovery debugfs file"); - - if (!debugfs_create_bool("recovery_on_apply_fail", - 0644, debugfs_root, - &core_dev->recovery_on_apply_fail)) - CAM_WARN(CAM_CRM, - "Failed to create recovery_on_apply_fail debugfs bool"); - return 0; +end: + return rc; } void cam_req_mgr_debug_unregister(void) @@ -144,3 +138,12 @@ void cam_req_mgr_debug_unregister(void) if (!debugfs_root) debugfs_remove_recursive(debugfs_root); } +#else +int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) +{ + CAM_WARN(CAM_CRM, "DebugFS not enabled in kernel"); + return 0; +} + +void cam_req_mgr_debug_unregister(void) { }; +#endif diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 61c1ee44a2e9..1c512aab76ce 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3876,39 +3876,32 @@ cb_init_fail: return rc; } +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_smmu_create_debug_fs(void) { - iommu_cb_set.dentry = debugfs_create_dir("camera_smmu", - NULL); + int rc = 0; - if (!iommu_cb_set.dentry) { - CAM_ERR(CAM_SMMU, "failed to create dentry"); - return -ENOMEM; + iommu_cb_set.dentry = debugfs_create_dir("camera_smmu", NULL); + if (IS_ERR(iommu_cb_set.dentry)) { + rc = PTR_ERR(iommu_cb_set.dentry); + goto end; } - if (!debugfs_create_bool("cb_dump_enable", - 0644, - iommu_cb_set.dentry, - &iommu_cb_set.cb_dump_enable)) { - CAM_ERR(CAM_SMMU, - "failed to create dump_enable_debug"); - goto err; - } + debugfs_create_bool("cb_dump_enable", 0644, iommu_cb_set.dentry, + &iommu_cb_set.cb_dump_enable); + debugfs_create_bool("map_profile_enable", 0644, iommu_cb_set.dentry, + &iommu_cb_set.map_profile_enable); - if (!debugfs_create_bool("map_profile_enable", - 0644, - iommu_cb_set.dentry, - &iommu_cb_set.map_profile_enable)) { - CAM_ERR(CAM_SMMU, - "failed to create map_profile_enable"); - goto err; - } - - return 0; -err: - debugfs_remove_recursive(iommu_cb_set.dentry); - return -ENOMEM; +end: + return rc; } +#else +static inline int cam_smmu_create_debug_fs(void) +{ + CAM_WARN(CAM_SMMU, "DebugFS not enabled in kernel"); + return 0; +} +#endif static int cam_smmu_fw_dev_component_bind(struct device *dev, struct device *master_dev, void *data) @@ -4019,7 +4012,9 @@ static void cam_smmu_component_unbind(struct device *dev, } cam_smmu_release_cb(pdev); +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(iommu_cb_set.dentry); +#endif iommu_cb_set.dentry = NULL; } diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 37461c27d8c0..02be2e7b1455 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1016,25 +1016,30 @@ static void cam_sync_init_entity(struct sync_device *sync_dev) } #endif +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_sync_create_debugfs(void) { + int rc = 0; + sync_dev->dentry = debugfs_create_dir("camera_sync", NULL); - - if (!sync_dev->dentry) { - CAM_ERR(CAM_SYNC, "Failed to create sync dir"); - return -ENOMEM; + if (IS_ERR(sync_dev->dentry)) { + rc = PTR_ERR(sync_dev->dentry); + goto end; } - if (!debugfs_create_bool("trigger_cb_without_switch", - 0644, sync_dev->dentry, - &trigger_cb_without_switch)) { - CAM_ERR(CAM_SYNC, - "failed to create trigger_cb_without_switch entry"); - return -ENOMEM; - } + debugfs_create_bool("trigger_cb_without_switch", 0644, + sync_dev->dentry, &trigger_cb_without_switch); +end: + return rc; +} +#else +static inline int cam_sync_create_debugfs(void) +{ + CAM_WARN(CAM_SYNC, "DebugFS not enabled in kernel"); return 0; } +#endif #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) int cam_synx_sync_signal(int32_t sync_obj, uint32_t synx_status) @@ -1216,7 +1221,9 @@ static void cam_sync_component_unbind(struct device *dev, #endif video_unregister_device(sync_dev->vdev); video_device_release(sync_dev->vdev); +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(sync_dev->dentry); +#endif sync_dev->dentry = NULL; for (i = 0; i < CAM_SYNC_MAX_OBJS; i++) diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 5ea63757526b..aab96d3782c3 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -14,7 +14,6 @@ #include "cam_mem_mgr.h" static char supported_clk_info[256]; -static char debugfs_dir_name[64]; int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, int64_t clk_rate, int clk_idx, int32_t *clk_lvl) @@ -181,18 +180,16 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control, * * @return: Success or failure */ -static int cam_soc_util_create_clk_lvl_debugfs( - struct cam_hw_soc_info *soc_info) +#if IS_ENABLED(CONFIG_DEBUG_FS) +static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) { - if (!soc_info) { - CAM_ERR(CAM_UTIL, "soc info is NULL"); - return -EINVAL; - } + char debugfs_dir_name[64]; + int rc = 0; if (soc_info->dentry) { - CAM_DBG(CAM_UTIL, "Debubfs entry for %s already exist", + CAM_DBG(CAM_UTIL, "Debugfs entry for %s already exist", soc_info->dev_name); - return 0; + goto end; } memset(debugfs_dir_name, 0, sizeof(debugfs_dir_name)); @@ -200,36 +197,26 @@ static int cam_soc_util_create_clk_lvl_debugfs( strlcat(debugfs_dir_name, soc_info->dev_name, sizeof(debugfs_dir_name)); soc_info->dentry = debugfs_create_dir(debugfs_dir_name, NULL); - if (IS_ERR_OR_NULL(soc_info->dentry)) { - CAM_ERR(CAM_UTIL, "failed to create debug directory"); - return -ENOMEM; + if (IS_ERR(soc_info->dentry)) { + rc = PTR_ERR(soc_info->dentry); + goto end; } - if (!debugfs_create_file("clk_lvl_options", 0444, - soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_options)) { - CAM_ERR(CAM_UTIL, "failed to create clk_lvl_options"); - goto err; - } + debugfs_create_file("clk_lvl_options", 0444, soc_info->dentry, soc_info, + &cam_soc_util_clk_lvl_options); + debugfs_create_file("clk_lvl_control", 0644, soc_info->dentry, soc_info, + &cam_soc_util_clk_lvl_control); - if (!debugfs_create_file("clk_lvl_control", 0644, - soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control)) { - CAM_ERR(CAM_UTIL, "failed to create clk_lvl_control"); - goto err; - } - - CAM_DBG(CAM_UTIL, "clk lvl debugfs for %s successfully created", - soc_info->dev_name); - - return 0; - -err: - CAM_ERR(CAM_UTIL, "Error in creating Debugfs Entry: %s", - soc_info->dev_name); - debugfs_remove_recursive(soc_info->dentry); - soc_info->dentry = NULL; - return -ENOMEM; +end: + return rc; } - +#else +static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) +{ + CAM_WARN(CAM_UTIL, "DebugFS not enabled in kernel"); + return 0; +} +#endif /** * cam_soc_util_remove_clk_lvl_debugfs() * @@ -242,8 +229,9 @@ err: static void cam_soc_util_remove_clk_lvl_debugfs( struct cam_hw_soc_info *soc_info) { +#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(soc_info->dentry); - soc_info->dentry = NULL; +#endif } int cam_soc_util_get_level_from_string(const char *string, From 7a99d64ebf61a90659b306809f1434fbefe91022 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 24 Jun 2020 09:53:18 -0700 Subject: [PATCH 397/790] msm: camera: reqmgr: Skip wd timer update if there is no valid request At a given point if there is no request to apply, carry forward the same timeout value for the wd timer. Modify timer only in cases where we apply a valid request. CRs-Fixed: 2698225 Change-Id: I92a1f1c6d0154349e19fdc1582d9d8836a7db1f4 Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_core.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 9b2f458fa44f..fc5495cc6f2e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -560,6 +560,7 @@ static void __cam_req_mgr_validate_crm_wd_timer( { int idx = 0; int next_frame_timeout = 0, current_frame_timeout = 0; + int64_t current_req_id, next_req_id; struct cam_req_mgr_req_queue *in_q = link->req.in_q; if (link->skip_init_frame) { @@ -574,18 +575,26 @@ static void __cam_req_mgr_validate_crm_wd_timer( &idx, (link->max_delay - 1), in_q->num_slots); next_frame_timeout = in_q->slot[idx].additional_timeout; + next_req_id = in_q->slot[idx].req_id; CAM_DBG(CAM_CRM, - "rd_idx: %d idx: %d next_frame_timeout: %d ms", - in_q->rd_idx, idx, next_frame_timeout); + "rd_idx: %d idx: %d next_req_id: %lld next_frame_timeout: %d ms", + in_q->rd_idx, idx, next_req_id, next_frame_timeout); idx = in_q->rd_idx; __cam_req_mgr_dec_idx( &idx, link->max_delay, in_q->num_slots); current_frame_timeout = in_q->slot[idx].additional_timeout; + current_req_id = in_q->slot[idx].req_id; CAM_DBG(CAM_CRM, - "rd_idx: %d idx: %d current_frame_timeout: %d ms", - in_q->rd_idx, idx, current_frame_timeout); + "rd_idx: %d idx: %d curr_req_id: %lld current_frame_timeout: %d ms", + in_q->rd_idx, idx, current_req_id, current_frame_timeout); + + if ((current_req_id == -1) && (next_req_id == -1)) { + CAM_DBG(CAM_CRM, + "Skip modifying wd timer, continue with same timeout"); + return; + } spin_lock_bh(&link->link_state_spin_lock); if (link->watchdog) { if ((next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT) > @@ -4095,6 +4104,9 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (control->init_timeout[i]) link->skip_init_frame = true; init_timeout = (2 * control->init_timeout[i]); + CAM_DBG(CAM_CRM, + "Activate link: 0x%x init_timeout: %d ms", + link->link_hdl, control->init_timeout[i]); /* Start SOF watchdog timer */ rc = crm_timer_init(&link->watchdog, (init_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT), @@ -4132,6 +4144,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->skip_init_frame = false; crm_timer_exit(&link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); + CAM_DBG(CAM_CRM, + "De-activate link: 0x%x", link->link_hdl); } else { CAM_ERR(CAM_CRM, "Invalid link control command"); rc = -EINVAL; From aaf3059502ed08d464f35829fd19c02c11455c1d Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Wed, 17 Jun 2020 12:37:39 -0700 Subject: [PATCH 398/790] msm: camera: cci: Fix incorrect use of cci config ioctl The cci configuration will be transitioned to a new API that does not require routing through the v4l layer. This is work-in-progrss so in the mean time prevent the device from being exposed as configurable from userspace. The ioctl will still be exposed to kernel users so fix the arg size as well. We want size of struct not pointer. CRs-Fixed: 2702760 Change-Id: I9c7bd8f76980603dbf27e1c5bc9b19f8a3b8a39a Signed-off-by: Fernando Pacheco --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 3 +-- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 1281691df5b6..baaa37ced39b 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -409,8 +409,7 @@ static int cam_cci_component_bind(struct device *dev, sizeof(new_cci_dev->device_name)); new_cci_dev->v4l2_dev_str.name = new_cci_dev->device_name; - new_cci_dev->v4l2_dev_str.sd_flags = - (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + new_cci_dev->v4l2_dev_str.sd_flags = V4L2_SUBDEV_FL_HAS_EVENTS; new_cci_dev->v4l2_dev_str.ent_function = CAM_CCI_DEVICE_TYPE; new_cci_dev->v4l2_dev_str.token = diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index ee8c313eff2c..62652c0397e4 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -313,6 +313,6 @@ int cam_cci_init_module(void); */ void cam_cci_exit_module(void); #define VIDIOC_MSM_CCI_CFG \ - _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl *) + _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct cam_cci_ctrl) #endif /* _CAM_CCI_DEV_H_ */ From e618f72d9f904398ef0396933bf68c5cb29b9e9d Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Tue, 16 Jun 2020 18:07:33 -0700 Subject: [PATCH 399/790] msm: camera: core: Handle request abort and signal fence CANCEL Handle request abort cases from underlying hw mgr, hw layers. This will handle in differentiating ERROR vs ABORT returned from firmware in case of ICP and signal the fence accordingly. By the time flush is issued to firmware, if a request is not yet processed, firmware signals with Abort, which needs to be propogated as CANCEL instead of ERROR to core context layer so that context layer signals the fence accordingly as ERROR or CANCEL. CRs-Fixed: 2702771 Change-Id: I8fe6bd1c8f5cf09b99196a1caac1283032418f8c Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_core/cam_context_utils.c | 23 +++++++++---------- drivers/cam_core/cam_context_utils.h | 4 ++-- drivers/cam_core/cam_hw_mgr_intf.h | 4 ++++ drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 7 +++--- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 20 +++++++++++----- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 6 +++-- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 12 +++++----- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 9 ++++---- 8 files changed, 49 insertions(+), 36 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 5b09d1183d7a..d69ab63bfa52 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -32,7 +32,7 @@ static inline int cam_context_validate_thread(void) } int cam_context_buf_done_from_hw(struct cam_context *ctx, - void *done_event_data, uint32_t bubble_state) + void *done_event_data, uint32_t evt_id) { int j; int result; @@ -84,21 +84,20 @@ int cam_context_buf_done_from_hw(struct cam_context *ctx, */ list_del_init(&req->list); spin_unlock(&ctx->lock); - if (!bubble_state) { + if (evt_id == CAM_CTX_EVT_ID_SUCCESS) result = CAM_SYNC_STATE_SIGNALED_SUCCESS; - } else { - CAM_DBG(CAM_REQ, - "[%s][ctx_id %d] : req[%llu] is done with error", - ctx->dev_name, ctx->ctx_id, req->request_id); - - for (j = 0; j < req->num_out_map_entries; j++) - CAM_DBG(CAM_REQ, "fence %d signaled with error", - req->out_map_entries[j].sync_id); - + else if (evt_id == CAM_CTX_EVT_ID_CANCEL) + result = CAM_SYNC_STATE_SIGNALED_CANCEL; + else result = CAM_SYNC_STATE_SIGNALED_ERROR; - } + + CAM_DBG(CAM_REQ, + "[%s][ctx_id %d] : req[%llu] : Signaling %d", + ctx->dev_name, ctx->ctx_id, req->request_id, result); for (j = 0; j < req->num_out_map_entries; j++) { + CAM_DBG(CAM_REQ, "fence %d signal with %d", + req->out_map_entries[j].sync_id, result); cam_sync_signal(req->out_map_entries[j].sync_id, result); req->out_map_entries[j].sync_id = -1; } diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h index 79dec3142e8a..4aeb7dd338ba 100644 --- a/drivers/cam_core/cam_context_utils.h +++ b/drivers/cam_core/cam_context_utils.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_UTILS_H_ @@ -9,7 +9,7 @@ #include int cam_context_buf_done_from_hw(struct cam_context *ctx, - void *done_event_data, uint32_t bubble_state); + void *done_event_data, uint32_t evt_id); int32_t cam_context_release_dev_to_hw(struct cam_context *ctx, struct cam_release_dev_cmd *cmd); int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 422a47bf354a..12b01ab688eb 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -35,6 +35,10 @@ enum cam_context_dump_id { CAM_CTX_DUMP_TYPE_MAX, }; +#define CAM_CTX_EVT_ID_SUCCESS 0 +#define CAM_CTX_EVT_ID_ERROR 1 +#define CAM_CTX_EVT_ID_CANCEL 2 + /* hardware event callback function type */ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, void *evt_data); diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index 041fad4ed7fe..079047c51e84 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -947,7 +947,7 @@ static int32_t cam_fd_mgr_workq_irq_cb(void *priv, void *data) struct cam_fd_mgr_work_data *work_data; struct cam_fd_mgr_frame_request *frame_req = NULL; enum cam_fd_hw_irq_type irq_type; - bool frame_abort = true; + uint32_t evt_id = CAM_CTX_EVT_ID_ERROR; int rc; if (!data || !priv) { @@ -1013,12 +1013,11 @@ static int32_t cam_fd_mgr_workq_irq_cb(void *priv, void *data) if (rc) { CAM_ERR(CAM_FD, "Failed in CMD_PRESTART %d", rc); - frame_abort = true; goto notify_context; } } - frame_abort = false; + evt_id = CAM_CTX_EVT_ID_SUCCESS; } trace_cam_irq_handled("FD", irq_type); @@ -1035,7 +1034,7 @@ notify_context: buf_data.request_id = frame_req->request_id; rc = frame_req->hw_ctx->event_cb(frame_req->hw_ctx->cb_priv, - frame_abort, &buf_data); + evt_id, &buf_data); if (rc) CAM_ERR(CAM_FD, "Error in event cb handling %d", rc); } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a2b2666329aa..07c471da9500 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1995,7 +1995,7 @@ static int cam_icp_mgr_cleanup_ctx(struct cam_icp_hw_ctx_data *ctx_data) continue; buf_data.request_id = hfi_frame_process->request_id[i]; ctx_data->ctxt_event_cb(ctx_data->context_priv, - false, &buf_data); + CAM_CTX_EVT_ID_SUCCESS, &buf_data); hfi_frame_process->request_id[i] = 0; if (ctx_data->hfi_frame_process.in_resource[i] > 0) { CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", @@ -2096,6 +2096,7 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) struct hfi_frame_process_info *hfi_frame_process; struct cam_hw_done_event_data buf_data; uint32_t clk_type; + uint32_t event_id; ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; request_id = ioconfig_ack->user_data2; @@ -2138,12 +2139,13 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) idx = i; if (flag == ICP_FRAME_PROCESS_FAILURE) { - if (ioconfig_ack->err_type == CAMERAICP_EABORTED) + if (ioconfig_ack->err_type == CAMERAICP_EABORTED) { CAM_WARN(CAM_ICP, "ctx_id %d req %llu dev %d has been aborted[flushed]", ctx_data->ctx_id, request_id, ctx_data->icp_dev_acquire_info->dev_type); - else + event_id = CAM_CTX_EVT_ID_CANCEL; + } else { CAM_ERR(CAM_ICP, "Done with error: %u err_type= [%s] on ctx_id %d dev %d for req %llu", ioconfig_ack->err_type, @@ -2152,10 +2154,14 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) ctx_data->ctx_id, ctx_data->icp_dev_acquire_info->dev_type, request_id); + event_id = CAM_CTX_EVT_ID_ERROR; + } + } else { + event_id = CAM_CTX_EVT_ID_SUCCESS; } buf_data.request_id = hfi_frame_process->request_id[idx]; - ctx_data->ctxt_event_cb(ctx_data->context_priv, flag, &buf_data); + ctx_data->ctxt_event_cb(ctx_data->context_priv, event_id, &buf_data); hfi_frame_process->request_id[idx] = 0; if (ctx_data->hfi_frame_process.in_resource[idx] > 0) { CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", @@ -3890,7 +3896,8 @@ static int cam_icp_mgr_handle_config_err( struct cam_hw_done_event_data buf_data; buf_data.request_id = *(uint64_t *)config_args->priv; - ctx_data->ctxt_event_cb(ctx_data->context_priv, false, &buf_data); + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_SUCCESS, + &buf_data); ctx_data->hfi_frame_process.request_id[idx] = 0; ctx_data->hfi_frame_process.fw_process_flag[idx] = false; @@ -4962,7 +4969,8 @@ static int cam_icp_mgr_send_abort_status(struct cam_icp_hw_ctx_data *ctx_data) if (!hfi_frame_process->request_id[idx]) continue; - ctx_data->ctxt_event_cb(ctx_data->context_priv, true, + ctx_data->ctxt_event_cb(ctx_data->context_priv, + CAM_CTX_EVT_ID_CANCEL, &hfi_frame_process->request_id[idx]); /* now release memory for hfi frame process command */ diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index e89c28146e43..3f7c179711af 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -175,7 +175,8 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) } buf_data.request_id = PTR_TO_U64(p_cfg_req->hw_cfg_args.priv); - ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_SUCCESS, + &buf_data); mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex); list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list); @@ -505,7 +506,8 @@ end_callcb: } buf_data.request_id = (uintptr_t)p_cfg_req->hw_cfg_args.priv; - ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); + ctx_data->ctxt_event_cb(ctx_data->context_priv, + CAM_CTX_EVT_ID_ERROR, &buf_data); } end_unusedev: mutex_lock(&hw_mgr->hw_mgr_mutex); diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 5cf8c55c0e37..d84028cac11e 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -498,7 +498,7 @@ static int cam_lrme_mgr_cb(void *data, { struct cam_lrme_hw_mgr *hw_mgr = &g_lrme_hw_mgr; int rc = 0; - bool frame_abort = true; + uint32_t evt_id = CAM_CTX_EVT_ID_ERROR; struct cam_lrme_frame_request *frame_req; struct cam_lrme_device *hw_device; @@ -530,10 +530,10 @@ static int cam_lrme_mgr_cb(void *data, if (cb_args->cb_type & CAM_LRME_CB_BUF_DONE) { cb_args->cb_type &= ~CAM_LRME_CB_BUF_DONE; - frame_abort = false; + evt_id = CAM_CTX_EVT_ID_SUCCESS; } else if (cb_args->cb_type & CAM_LRME_CB_ERROR) { cb_args->cb_type &= ~CAM_LRME_CB_ERROR; - frame_abort = true; + evt_id = CAM_CTX_EVT_ID_ERROR; } else { CAM_ERR(CAM_LRME, "Wrong cb type %d, req %lld", cb_args->cb_type, frame_req->req_id); @@ -544,10 +544,10 @@ static int cam_lrme_mgr_cb(void *data, struct cam_hw_done_event_data buf_data; buf_data.request_id = frame_req->req_id; - CAM_DBG(CAM_LRME, "frame req %llu, frame_abort %d", - frame_req->req_id, frame_abort); + CAM_DBG(CAM_LRME, "frame req %llu, evt_id %d", + frame_req->req_id, evt_id); rc = hw_mgr->event_cb(frame_req->ctxt_to_hw_map, - frame_abort, &buf_data); + evt_id, &buf_data); } else { CAM_ERR(CAM_LRME, "No cb function"); } diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 6016652717c5..bb1972c513b3 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1519,7 +1519,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, struct cam_ope_request *ope_req; struct cam_hw_done_event_data buf_data; struct timespec64 ts; - bool flag = false; + uint32_t evt_id = CAM_CTX_EVT_ID_SUCCESS; if (!userdata) { CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); @@ -1582,7 +1582,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, if (status != CAM_CDM_CB_STATUS_HW_FLUSH) cam_ope_dump_req_data(ope_req); rc = cam_ope_mgr_reset_hw(); - flag = true; + evt_id = CAM_CTX_EVT_ID_ERROR; } ctx->req_cnt--; @@ -1595,7 +1595,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, kzfree(ctx->req_list[cookie]); ctx->req_list[cookie] = NULL; clear_bit(cookie, ctx->bitmap); - ctx->ctxt_event_cb(ctx->context_priv, flag, &buf_data); + ctx->ctxt_event_cb(ctx->context_priv, evt_id, &buf_data); end: mutex_unlock(&ctx->ctx_mutex); @@ -3203,7 +3203,8 @@ static int cam_ope_mgr_handle_config_err( ope_req = config_args->priv; buf_data.request_id = ope_req->request_id; - ctx_data->ctxt_event_cb(ctx_data->context_priv, false, &buf_data); + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_ERROR, + &buf_data); req_idx = ope_req->req_idx; ope_req->request_id = 0; From 899a6b0d505b679d5daaa42b9aeaef20f7fc2d4f Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 10 Jun 2020 18:48:23 +0530 Subject: [PATCH 400/790] msm: camera: cpas: Add support for shima camnoc Add register information. Initial QoS settings info to program camera static settings for chipsets having camera V570_200. CRs-Fixed: 2707213 Change-Id: Ic9af3c4ff1cc69c6b70e1489e4634afe7b71390a Signed-off-by: Chandan Kumar Jha --- Makefile | 9 + config/shimacamera.conf | 17 + config/shimacameraconf.h | 11 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 17 + drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 672 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 3 + 6 files changed, 729 insertions(+) create mode 100644 config/shimacamera.conf create mode 100644 config/shimacameraconf.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v570_200.h diff --git a/Makefile b/Makefile index 6e69c3b02f1b..dd08f9f140d6 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,10 @@ ifeq ($(CONFIG_ARCH_HOLI), y) include $(srctree)/techpack/camera/config/holicamera.conf endif +ifeq ($(CONFIG_ARCH_SHIMA), y) +include $(srctree)/techpack/camera/config/shimacamera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h @@ -47,6 +51,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/holicameraconf.h endif +ifeq ($(CONFIG_ARCH_SHIMA), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/shimacameraconf.h +endif + endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) diff --git a/config/shimacamera.conf b/config/shimacamera.conf new file mode 100644 index 000000000000..3b32dc7c49b2 --- /dev/null +++ b/config/shimacamera.conf @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2020, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=m +$(info "SPECTRA_CAMERA IS STATIC") +else +$(info "SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +endif diff --git a/config/shimacameraconf.h b/config/shimacameraconf.h new file mode 100644 index 000000000000..f75988567853 --- /dev/null +++ b/config/shimacameraconf.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 396355cefb70..2605de78b238 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -28,6 +28,7 @@ #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" #include "cpastop_v545_100.h" +#include "cpastop_v570_200.h" struct cam_camnoc_info *camnoc_info; @@ -118,6 +119,15 @@ static const uint32_t cam_cpas_hw_version_map 0, 0, }, + /* for camera_570 */ + { + 0, + 0, + 0, + 0, + 0, + CAM_CPAS_TITAN_570_V200, + }, }; static int cam_cpas_translate_camera_cpas_version_id( @@ -161,6 +171,10 @@ static int cam_cpas_translate_camera_cpas_version_id( *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_545; break; + case CAM_CPAS_CAMERA_VERSION_570: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_570; + break; + default: CAM_ERR(CAM_CPAS, "Invalid cam version %u", cam_version); @@ -766,6 +780,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_545_V100: camnoc_info = &cam545_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_570_V200: + camnoc_info = &cam570_cpas200_camnoc_info; + break; default: CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", hw_caps->camera_version.major, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h new file mode 100644 index 000000000000..a8bd3112f226 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -0,0 +1,672 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V570_200_H_ +#define _CPASTOP_V570_200_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v570_200_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3840, /* SBM_FAULTINEN0_LOW */ + .value = 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + 0x1000 | /* SBM_FAULTINEN0_LOW_PORT12_MASK */ + (TEST_IRQ_ENABLE ? + 0x40 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3848, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x3880, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x5 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v570_200_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = false, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x7008, /* ERL_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x7010, /* ERL_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x7018, /* ERL_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x1BA0, /* IFE_UBWC_STATS_0_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1B90, + /* IFE_UBWC_STATS_0_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1B98, /* IFE_UBWC_STATS_0_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2520, /* IPE1_BPS_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2510, /* IPE1_BPS_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2518, /* IPE1_BPS_RD_DECERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE0_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 = 0x1F20, /* IPE0_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1F10, /* IPE0_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1F18, /* IPE0_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 = 0x29A0, /* IPE_BPS_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2990, + /* IPE_BPS_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2998, /* IPE_BPS_WR_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = false, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* 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 = 0x40, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x3888, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3890, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v570_200_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* CDM_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_RDI_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1048, /* IFE_RDI_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, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_RDI_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* IFE_RDI_WR_0_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1438, /* IFE_RDI_WR_0_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1440, /* IFE_RDI_WR_0_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE_UBWC_STATS, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A34, + /* IFE_UBWC_STATS_0_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1A38, /* IFE_UBWC_STATS_0_URGENCY_LOW */ + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A40, /* IFE_UBWC_STATS_0_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x1A48, /* IFE_UBWC_STATS_0_SAFELUT_LOW */ + .value = 0x000F, + }, + .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 = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE0_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1E48, /* IPE0_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 = 0x1F08, /* IPE0_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE1_BPS_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2448, /* IPE1_BPS_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 = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2848, /* IPE_BPS_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 = 0x2988, /* IPE_BPS_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 = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E38, /* JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .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 = 0x3888, + .value = 0x100000, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam570_cpas200_err_logger_offsets = { + .mainctrl = 0x7008, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x7010, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x7020, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x7024, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x7028, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x702c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x7030, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x7034, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x7038, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x703c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam570_cpas200_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x3900, /* sbm_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam570_cpas200_camnoc_info = { + .specific = &cam_cpas_v570_200_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v570_200_camnoc_specific), + .irq_sbm = &cam_cpas_v570_200_irq_sbm, + .irq_err = &cam_cpas_v570_200_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v570_200_irq_err), + .err_logger = &cam570_cpas200_err_logger_offsets, + .errata_wa_list = &cam570_cpas200_errata_wa_list, +}; + +#endif /* _CPASTOP_V570_200_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 1c46c964f6a9..1b08b427ddb9 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -49,6 +49,7 @@ enum cam_cpas_camera_version { CAM_CPAS_CAMERA_VERSION_540 = 0x00050400, CAM_CPAS_CAMERA_VERSION_580 = 0x00050800, CAM_CPAS_CAMERA_VERSION_545 = 0x00050405, + CAM_CPAS_CAMERA_VERSION_570 = 0x00050700, CAM_CPAS_CAMERA_VERSION_MAX }; @@ -79,6 +80,7 @@ enum cam_cpas_camera_version_map_id { CAM_CPAS_CAMERA_VERSION_ID_520 = 0x5, CAM_CPAS_CAMERA_VERSION_ID_540 = 0x6, CAM_CPAS_CAMERA_VERSION_ID_545 = 0x7, + CAM_CPAS_CAMERA_VERSION_ID_570 = 0x8, CAM_CPAS_CAMERA_VERSION_ID_MAX }; @@ -115,6 +117,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_520_V100 = 0x520100, CAM_CPAS_TITAN_545_V100 = 0x545100, + CAM_CPAS_TITAN_570_V200 = 0x570200, CAM_CPAS_TITAN_MAX }; From 25e54e279c96712ebaf14bc5c8501804ddc9b10b Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 12 Jun 2020 01:51:45 +0530 Subject: [PATCH 401/790] msm: camera: common: Add hw version checks for shima camera Add hw version checks in csid, vfe and ICP driver. CRs-Fixed: 2707213 Change-Id: I9a698479b5a86b279a4a58cceb908ed7a7e93f11 Signed-off-by: Chandan Kumar Jha --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 3 ++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 1 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 20 ++++++++++++------- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 2 ++ .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 1 + .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 1 + 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a2b2666329aa..810c02a197fc 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -6126,7 +6126,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, cam_cpas_get_cpas_hw_version(&camera_hw_version); if ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || - (camera_hw_version == CAM_CPAS_TITAN_580_V100)) { + (camera_hw_version == CAM_CPAS_TITAN_580_V100) || + (camera_hw_version == CAM_CPAS_TITAN_570_V200)) { if (cam_caps & CPAS_TITAN_480_IPE0_BIT) icp_hw_mgr.ipe0_enable = true; if (cam_caps & CPAS_BPS_BIT) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 2a7218f0fa34..431580186e2c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1364,6 +1364,7 @@ static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) return CAM_ISP_IFE4_LITE_HW; break; case CAM_CPAS_TITAN_580_V100: + case CAM_CPAS_TITAN_570_V200: if (hw_idx == 0) return CAM_ISP_IFE0_HW; else if (hw_idx == 1) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 41decd3ffec8..2e5f7e5d9b99 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -354,8 +354,9 @@ static int cam_ife_match_vc_dt_pair(int32_t *vc, uint32_t *dt, return -EINVAL; } - if ((camera_hw_version != CAM_CPAS_TITAN_480_V100) && - (camera_hw_version != CAM_CPAS_TITAN_580_V100)) + if ((camera_hw_version != CAM_CPAS_TITAN_480_V100) || + (camera_hw_version != CAM_CPAS_TITAN_580_V100) || + (camera_hw_version != CAM_CPAS_TITAN_570_V200)) num_valid_vc_dt = 1; switch (num_valid_vc_dt) { @@ -1815,7 +1816,8 @@ static int cam_ife_csid_init_config_pxl_path( CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version); if ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || - (camera_hw_version == CAM_CPAS_TITAN_580_V100)) + (camera_hw_version == CAM_CPAS_TITAN_580_V100) || + (camera_hw_version == CAM_CPAS_TITAN_570_V200)) val |= (path_data->drop_enable << csid_reg->cmn_reg->drop_h_en_shift_val) | (path_data->drop_enable << @@ -1837,7 +1839,8 @@ static int cam_ife_csid_init_config_pxl_path( if (path_data->is_valid_vc1_dt1 && ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || - (camera_hw_version == CAM_CPAS_TITAN_580_V100))) { + (camera_hw_version == CAM_CPAS_TITAN_580_V100) || + (camera_hw_version == CAM_CPAS_TITAN_570_V200))) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_multi_vcdt_cfg0_addr); val |= ((path_data->vc1 << 2) | @@ -2304,7 +2307,8 @@ static int cam_ife_csid_init_config_rdi_path( if (camera_hw_version == CAM_CPAS_TITAN_480_V100 || camera_hw_version == CAM_CPAS_TITAN_175_V130 || - camera_hw_version == CAM_CPAS_TITAN_580_V100) { + camera_hw_version == CAM_CPAS_TITAN_580_V100 || + camera_hw_version == CAM_CPAS_TITAN_570_V200) { val |= (path_data->drop_enable << csid_reg->cmn_reg->drop_h_en_shift_val) | (path_data->drop_enable << @@ -2318,7 +2322,8 @@ static int cam_ife_csid_init_config_rdi_path( if (path_data->is_valid_vc1_dt1 && ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || - (camera_hw_version == CAM_CPAS_TITAN_580_V100))) { + (camera_hw_version == CAM_CPAS_TITAN_580_V100) || + (camera_hw_version == CAM_CPAS_TITAN_570_V200))) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_multi_vcdt_cfg0_addr); val |= ((path_data->vc1 << 2) | @@ -2404,7 +2409,8 @@ static int cam_ife_csid_init_config_rdi_path( /* Write max value to pixel drop period due to a bug in ver 480 HW */ if (((camera_hw_version == CAM_CPAS_TITAN_480_V100) || - (camera_hw_version == CAM_CPAS_TITAN_580_V100)) && + (camera_hw_version == CAM_CPAS_TITAN_580_V100) || + (camera_hw_version == CAM_CPAS_TITAN_570_V200)) && path_data->drop_enable) cam_io_w_mb(0x1F, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_period_addr); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index bd1a84e86042..bcb926324621 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -91,6 +91,7 @@ int cam_vfe_reset_irq_top_half(uint32_t evt_id, switch (soc_info->hw_version) { case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: + case CAM_CPAS_TITAN_570_V200: if (!soc_private->is_ife_lite) { if (th_payload->evt_status_arr[0] & 0x1) { cam_io_w(0xFFFFFFFF, mem_base + @@ -332,6 +333,7 @@ int cam_vfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) switch (soc_info->hw_version) { case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: + case CAM_CPAS_TITAN_570_V200: if (!soc_private->is_ife_lite) top_reset_irq_reg_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = CAM_VFE_48X_TOP_RESET_MASK; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 3179362f7cac..61b7efe5bfa3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -61,6 +61,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) switch (soc_info->hw_version) { case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: + case CAM_CPAS_TITAN_570_V200: num_ubwc_cfg = of_property_count_u32_elems(of_node, "ubwc-static-cfg"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 543dcbb358bf..1f1e12ea57c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -463,6 +463,7 @@ static int cam_vfe_camif_ver3_resource_start( switch (soc_private->cpas_version) { case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: + case CAM_CPAS_TITAN_570_V200: epoch0_line_cfg = (rsrc_data->last_line - rsrc_data->first_line) / 4; /* epoch line cfg will still be configured at midpoint of the From c8ac83dc3e22714a38f99d9eeede62bcba3368d0 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 22 Jun 2020 09:32:47 -0700 Subject: [PATCH 402/790] msm: camera: cci: Correct the condition check Submodules per master uninitialize check needs to be set to false when all submodules are released for that master. Correct the refcount check for the appropriate operation. CRs-Fixed: 2686487 Change-Id: Iaea94e4d1ad83bef99d40cec4e96de3993783ec1 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 5f35a6449a07..ce0b8de81316 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -403,11 +403,15 @@ int cam_cci_soc_release(struct cci_device *cci_dev, return -EINVAL; } - if (--cci_dev->master_active_slave[master]) + if (!(--cci_dev->master_active_slave[master])) { cci_dev->cci_master_info[master].is_initilized = false; + CAM_DBG(CAM_CCI, + "All submodules are released for master: %d", master); + } if (--cci_dev->ref_count) { - CAM_DBG(CAM_CCI, "ref_count Exit %d", cci_dev->ref_count); + CAM_DBG(CAM_CCI, "Submodule release: Ref_count: %d", + cci_dev->ref_count); return 0; } From fa080688013d21e43352bf1925fba2f2f30c137e Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 16 Mar 2020 12:20:57 -0700 Subject: [PATCH 403/790] msm: camera: csiphy: Update logic for lane enablement Currently lane enablement is happening as a part of lanemask field, which is send by UMD. Lane enablement should be purely depends on laneCnt and laneAssign attributes. Also, combo mode sensors needs to come with combo mode flag set from the UMD. This change updates the logic for lane enablement with respect to laneAssign and laneCnt, and also covers all combomode selection as per the request. This change also enables the sensors to acquire and streamon/streamoff at anytime in session. CRs-Fixed: 2677450 Change-Id: I4f0d3ffd7245a931c273611c9c4b7e503c038664 Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 806 ++++++++++++------ .../cam_csiphy/cam_csiphy_dev.c | 24 +- .../cam_csiphy/cam_csiphy_dev.h | 154 ++-- .../cam_csiphy/cam_csiphy_soc.c | 33 +- .../cam_csiphy/cam_csiphy_soc.h | 5 +- .../include/cam_csiphy_1_2_3_hwreg.h | 1 + drivers/cam_utils/cam_compat.c | 10 +- include/uapi/camera/media/cam_sensor.h | 33 +- 8 files changed, 679 insertions(+), 387 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 01c54cdd6cd5..f4d60b937c58 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -34,17 +34,21 @@ int32_t cam_csiphy_get_instance_offset( struct csiphy_device *csiphy_dev, int32_t dev_handle) { - int32_t i; + int32_t i = 0; - if (csiphy_dev->acquire_count > - CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); + if ((csiphy_dev->acquire_count > + csiphy_dev->session_max_device_support) || + (csiphy_dev->acquire_count < 0)) { + CAM_ERR(CAM_CSIPHY, + "Invalid acquire count: %d, Max supported device for session: %u", + csiphy_dev->acquire_count, + csiphy_dev->session_max_device_support); return -EINVAL; } for (i = 0; i < csiphy_dev->acquire_count; i++) { if (dev_handle == - csiphy_dev->bridge_intf.device_hdl[i]) + csiphy_dev->csiphy_info[i].hdl_data.device_hdl) break; } @@ -84,83 +88,138 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev) } } -int32_t cam_csiphy_update_secure_info( - struct csiphy_device *csiphy_dev, - struct cam_csiphy_info *cam_cmd_csiphy_info, - struct cam_config_dev_cmd *cfg_dev) +static int32_t cam_csiphy_update_secure_info( + struct csiphy_device *csiphy_dev, int32_t index) { - uint32_t clock_lane, adj_lane_mask, temp, phy_mask_len; - int32_t offset; + uint32_t adj_lane_mask = 0; + uint16_t lane_assign = 0; + uint32_t phy_mask_len = 0; + uint8_t lane_cnt = 0; - if (csiphy_dev->acquire_count >= - CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); - return -EINVAL; + lane_assign = csiphy_dev->csiphy_info[index].lane_assign; + lane_cnt = csiphy_dev->csiphy_info[index].lane_cnt; + + while (lane_cnt--) { + if ((lane_assign & 0xF) == 0x0) + adj_lane_mask |= 0x1; + else + adj_lane_mask |= (1 << (lane_assign & 0xF)); + + lane_assign >>= 4; } - offset = cam_csiphy_get_instance_offset(csiphy_dev, - cfg_dev->dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); - return -EINVAL; - } - - if (cam_cmd_csiphy_info->combo_mode) - clock_lane = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_combo_ck_ln; - else - clock_lane = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_clock_lane; - - adj_lane_mask = cam_cmd_csiphy_info->lane_mask & LANE_MASK_2PH & - ~clock_lane; - temp = adj_lane_mask & (clock_lane - 1); - adj_lane_mask = - ((adj_lane_mask & (~(clock_lane - 1))) >> 1) | temp; - - if (cam_cmd_csiphy_info->csiphy_3phase) - adj_lane_mask = cam_cmd_csiphy_info->lane_mask & LANE_MASK_3PH; - - csiphy_dev->csiphy_info.secure_mode[offset] = 1; - if (csiphy_dev->hw_version == CSIPHY_VERSION_V201) { phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES + 1; } else if (csiphy_dev->hw_version == CSIPHY_VERSION_V121) { phy_mask_len = (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) ? - CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES : - CAM_CSIPHY_MAX_DPHY_LANES + - CAM_CSIPHY_MAX_CPHY_LANES + 1; + (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) + : (CAM_CSIPHY_MAX_DPHY_LANES + + CAM_CSIPHY_MAX_CPHY_LANES + 1); } else { phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES; } if (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) { - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = - ((uint64_t)adj_lane_mask) << - (csiphy_dev->soc_info.index * phy_mask_len + - (!cam_cmd_csiphy_info->csiphy_3phase) * + csiphy_dev->csiphy_info[index].csiphy_cpas_cp_reg_mask = + adj_lane_mask << + ((csiphy_dev->soc_info.index * phy_mask_len) + + (!csiphy_dev->csiphy_info[index].csiphy_3phase) * (CAM_CSIPHY_MAX_CPHY_LANES)); } else { - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = + csiphy_dev->csiphy_info[index].csiphy_cpas_cp_reg_mask = ((uint64_t)adj_lane_mask) << ((csiphy_dev->soc_info.index - MAX_PHY_MSK_PER_REG) * phy_mask_len + SEC_LANE_CP_REG_LEN + - (!cam_cmd_csiphy_info->csiphy_3phase) * + (!csiphy_dev->csiphy_info[index].csiphy_3phase) * (CAM_CSIPHY_MAX_CPHY_LANES)); } + CAM_DBG(CAM_CSIPHY, "csi phy idx:%d, cp_reg_mask:0x%lx", csiphy_dev->soc_info.index, - csiphy_dev->csiphy_cpas_cp_reg_mask[offset]); + csiphy_dev->csiphy_info[index].csiphy_cpas_cp_reg_mask); + return 0; } +static int cam_csiphy_get_lane_enable( + struct csiphy_device *csiphy, int index, uint32_t *lane_enable) +{ + uint32_t lane_select = 0; + uint16_t lane_assign = csiphy->csiphy_info[index].lane_assign; + uint8_t lane_cnt = csiphy->csiphy_info[index].lane_cnt; + int rc = 0; + + while (lane_cnt--) { + if (csiphy->csiphy_info[index].csiphy_3phase) { + switch (lane_assign & 0xF) { + case 0x0: + lane_select |= CPHY_LANE_0; + break; + case 0x1: + lane_select |= CPHY_LANE_1; + break; + case 0x2: + lane_select |= CPHY_LANE_2; + break; + default: + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for CPHY : %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + } else { + switch (lane_assign & 0xF) { + case 0x0: + lane_select |= DPHY_LANE_0; + lane_select |= DPHY_CLK_LN; + break; + case 0x1: + lane_select |= DPHY_LANE_1; + lane_select |= DPHY_CLK_LN; + break; + case 0x2: + lane_select |= DPHY_LANE_2; + if (csiphy->combo_mode) + lane_select |= DPHY_LANE_3; + else + lane_select |= DPHY_CLK_LN; + break; + case 0x3: + if (csiphy->combo_mode) { + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for DPHYCombo: %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + lane_select |= DPHY_LANE_3; + lane_select |= DPHY_CLK_LN; + break; + default: + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for DPHY: %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + } + lane_assign >>= 4; + } + + CAM_DBG(CAM_CSIPHY, "Lane_enable: 0x%x", lane_enable); + *lane_enable = lane_select; + + return rc; +} + int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, struct cam_config_dev_cmd *cfg_dev) { - int32_t rc = 0; + int rc = 0; uintptr_t generic_ptr; uintptr_t generic_pkt_ptr; struct cam_packet *csl_packet = NULL; @@ -169,6 +228,8 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, struct cam_csiphy_info *cam_cmd_csiphy_info = NULL; size_t len; size_t remain_len; + int index; + uint32_t lane_enable = 0; if (!cfg_dev || !csiphy_dev) { CAM_ERR(CAM_CSIPHY, "Invalid Args"); @@ -227,46 +288,73 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, cmd_buf += cmd_desc->offset / 4; cam_cmd_csiphy_info = (struct cam_csiphy_info *)cmd_buf; - csiphy_dev->config_count++; - csiphy_dev->csiphy_info.lane_cnt += cam_cmd_csiphy_info->lane_cnt; - csiphy_dev->csiphy_info.lane_mask |= cam_cmd_csiphy_info->lane_mask; - csiphy_dev->csiphy_info.csiphy_3phase = - cam_cmd_csiphy_info->csiphy_3phase; - csiphy_dev->csiphy_info.combo_mode |= cam_cmd_csiphy_info->combo_mode; - if (cam_cmd_csiphy_info->combo_mode == 1) { - csiphy_dev->csiphy_info.settle_time_combo_sensor = - cam_cmd_csiphy_info->settle_time; - csiphy_dev->csiphy_info.data_rate_combo_sensor = - cam_cmd_csiphy_info->data_rate; - } else { - csiphy_dev->csiphy_info.settle_time = - cam_cmd_csiphy_info->settle_time; - csiphy_dev->csiphy_info.data_rate = - cam_cmd_csiphy_info->data_rate; + index = cam_csiphy_get_instance_offset(csiphy_dev, cfg_dev->dev_handle); + if (index < 0 || index >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index in invalid: %d", index); + return -EINVAL; } + csiphy_dev->csiphy_info[index].lane_cnt = cam_cmd_csiphy_info->lane_cnt; + csiphy_dev->csiphy_info[index].lane_assign = + cam_cmd_csiphy_info->lane_assign; + + csiphy_dev->csiphy_info[index].settle_time = + cam_cmd_csiphy_info->settle_time; + csiphy_dev->csiphy_info[index].data_rate = + cam_cmd_csiphy_info->data_rate; + csiphy_dev->csiphy_info[index].secure_mode = + cam_cmd_csiphy_info->secure_mode; + + rc = cam_csiphy_get_lane_enable(csiphy_dev, index, &lane_enable); + if (rc) { + CAM_ERR(CAM_CSIPHY, "Wrong lane configuration: %d", + csiphy_dev->csiphy_info[index].lane_assign); + if ((csiphy_dev->combo_mode) || + (csiphy_dev->cphy_dphy_combo_mode)) { + CAM_DBG(CAM_CSIPHY, + "Resetting error to zero for other devices to configure"); + rc = 0; + } + lane_enable = 0; + csiphy_dev->csiphy_info[index].lane_enable = lane_enable; + goto reset_settings; + } + + csiphy_dev->csiphy_info[index].lane_enable = lane_enable; if (cam_cmd_csiphy_info->secure_mode == 1) cam_csiphy_update_secure_info(csiphy_dev, - cam_cmd_csiphy_info, cfg_dev); + index); + + csiphy_dev->config_count++; CAM_DBG(CAM_CSIPHY, - "phy version_%d, lane count:%d, mask:0x%x", + "phy version:%d, phy_idx: %d", csiphy_dev->hw_version, - csiphy_dev->csiphy_info.lane_cnt, - csiphy_dev->csiphy_info.lane_mask - ); + csiphy_dev->soc_info.index); CAM_DBG(CAM_CSIPHY, "3phase:%d, combo mode:%d, secure mode:%d", - csiphy_dev->csiphy_info.csiphy_3phase, - csiphy_dev->csiphy_info.combo_mode, - cam_cmd_csiphy_info->secure_mode - ); + csiphy_dev->csiphy_info[index].csiphy_3phase, + csiphy_dev->combo_mode, + cam_cmd_csiphy_info->secure_mode); CAM_DBG(CAM_CSIPHY, - "phy idx:%d, settle time:%d, datarate:%d", - csiphy_dev->soc_info.index, - csiphy_dev->csiphy_info.settle_time, - csiphy_dev->csiphy_info.data_rate); + "lane_cnt: 0x%x, lane_assign: 0x%x, lane_enable: 0x%x, settle time:%llu, datarate:%llu", + csiphy_dev->csiphy_info[index].lane_cnt, + csiphy_dev->csiphy_info[index].lane_assign, + csiphy_dev->csiphy_info[index].lane_enable, + csiphy_dev->csiphy_info[index].settle_time, + csiphy_dev->csiphy_info[index].data_rate); + + return rc; + +reset_settings: + csiphy_dev->csiphy_info[index].lane_cnt = 0; + csiphy_dev->csiphy_info[index].lane_assign = 0; + csiphy_dev->csiphy_info[index].lane_enable = 0; + csiphy_dev->csiphy_info[index].settle_time = 0; + csiphy_dev->csiphy_info[index].data_rate = 0; + csiphy_dev->csiphy_info[index].secure_mode = 0; + csiphy_dev->csiphy_info[index].hdl_data.device_hdl = -1; return rc; } @@ -284,7 +372,8 @@ void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev) csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr); } -void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) +static void cam_csiphy_cphy_data_rate_config( + struct csiphy_device *csiphy_device, int32_t idx) { int i = 0, j = 0; uint64_t phy_data_rate = 0; @@ -300,7 +389,7 @@ void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) return; } - phy_data_rate = csiphy_device->csiphy_info.data_rate; + phy_data_rate = csiphy_device->csiphy_info[idx].data_rate; csiphybase = csiphy_device->soc_info.reg_map[0].mem_base; settings_table = @@ -319,8 +408,8 @@ void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) if (phy_data_rate > bandwidth) { CAM_DBG(CAM_CSIPHY, - "Skipping table [%d] %llu required: %llu", - i, bandwidth, phy_data_rate); + "Skipping table [%d] %llu required: %llu", + i, bandwidth, phy_data_rate); continue; } @@ -393,82 +482,124 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data) return IRQ_HANDLED; } -int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) +int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, + int32_t dev_handle) { int32_t rc = 0; - uint32_t lane_enable = 0, mask = 1, size = 0; - uint16_t lane_mask = 0, i = 0, cfg_size = 0, temp = 0; - uint8_t lane_cnt, lane_pos = 0; + uint32_t lane_enable = 0; + uint32_t size = 0; + uint16_t i = 0, cfg_size = 0; + uint16_t lane_assign = 0; + uint8_t lane_cnt; + int max_lanes = 0; uint16_t settle_cnt = 0; uint64_t intermediate_var; + uint8_t lane_pos = 0; + int index; void __iomem *csiphybase; struct csiphy_reg_t *csiphy_common_reg = NULL; struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE]; - - lane_cnt = csiphy_dev->csiphy_info.lane_cnt; + bool is_3phase = false; csiphybase = csiphy_dev->soc_info.reg_map[0].mem_base; + CAM_DBG(CAM_CSIPHY, "ENTER"); if (!csiphybase) { CAM_ERR(CAM_CSIPHY, "csiphybase NULL"); return -EINVAL; } - if (!csiphy_dev->csiphy_info.csiphy_3phase) { - if (csiphy_dev->csiphy_info.combo_mode == 1) - reg_array = - csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg; - else - reg_array = - csiphy_dev->ctrl_reg->csiphy_2ph_reg; - csiphy_dev->num_irq_registers = 11; - cfg_size = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_config_array_size; + index = cam_csiphy_get_instance_offset(csiphy_dev, dev_handle); + if (index < 0 || index >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", index); + return -EINVAL; + } - lane_mask = csiphy_dev->csiphy_info.lane_mask & LANE_MASK_2PH; - for (i = 0; i < MAX_DPHY_DATA_LN; i++) { - if (mask == 0x2) { - if (lane_mask & mask) - lane_enable |= 0x80; - i--; - } else if (lane_mask & mask) { - lane_enable |= 0x1 << (i<<1); - } - mask <<= 1; - } - } else { - if (csiphy_dev->csiphy_info.combo_mode == 1) { - if (csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg) - reg_array = - csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg; - else { + CAM_DBG(CAM_CSIPHY, + "Index: %d: expected dev_hdl: 0x%x : derived dev_hdl: 0x%x", + index, dev_handle, + csiphy_dev->csiphy_info[index].hdl_data.device_hdl); + csiphy_dev->num_irq_registers = 11; + + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + is_3phase = true; + + if (csiphy_dev->combo_mode) { + /* for CPHY(3Phase) or DPHY(2Phase) combo mode selection */ + if (is_3phase) { + /* CPHY combo mode */ + if (csiphy_dev->ctrl_reg->csiphy_3ph_combo_reg) { + reg_array = csiphy_dev->ctrl_reg + ->csiphy_3ph_combo_reg; + } else { + CAM_WARN(CAM_CSIPHY, + "CPHY combo mode reg settings not found"); reg_array = csiphy_dev->ctrl_reg->csiphy_3ph_reg; - CAM_ERR(CAM_CSIPHY, - "Unsupported configuration, Falling back to CPHY mode"); } - } else - reg_array = - csiphy_dev->ctrl_reg->csiphy_3ph_reg; - csiphy_dev->num_irq_registers = 11; - cfg_size = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_3ph_config_array_size; - - lane_mask = csiphy_dev->csiphy_info.lane_mask & LANE_MASK_3PH; - mask = lane_mask; - while (mask != 0) { - temp = (i << 1)+1; - lane_enable |= ((mask & 0x1) << temp); - mask >>= 1; - i++; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_3ph_config_array_size; + max_lanes = CAM_CSIPHY_MAX_CPHY_LANES; + } else { + /* DPHY combo mode*/ + if (csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg) { + reg_array = csiphy_dev + ->ctrl_reg->csiphy_2ph_combo_mode_reg; + } else { + CAM_WARN(CAM_CSIPHY, + "DPHY combo mode reg settings not found"); + reg_array = csiphy_dev + ->ctrl_reg->csiphy_2ph_reg; + } + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_2ph_config_array_size; + max_lanes = MAX_LANES; + } + } else if (csiphy_dev->cphy_dphy_combo_mode) { + /* for CPHY and DPHY combo mode selection */ + if (csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg) { + reg_array = csiphy_dev + ->ctrl_reg->csiphy_2ph_3ph_mode_reg; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_2ph_3ph_config_array_size; + max_lanes = CAM_CSIPHY_MAX_CPHY_DPHY_COMBO_LN; + } else { + reg_array = csiphy_dev->ctrl_reg->csiphy_3ph_reg; + cfg_size = + csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_3ph_config_array_size; + CAM_WARN(CAM_CSIPHY, + "Unsupported configuration, Falling back to CPHY mission mode"); + max_lanes = CAM_CSIPHY_MAX_CPHY_LANES; + } + } else { + /* for CPHY(3Phase) or DPHY(2Phase) Non combe mode selection */ + if (is_3phase) { + CAM_DBG(CAM_CSIPHY, + "3phase Non combo mode reg array selected"); + reg_array = csiphy_dev->ctrl_reg->csiphy_3ph_reg; + max_lanes = CAM_CSIPHY_MAX_CPHY_LANES; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_3ph_config_array_size; + } else { + CAM_DBG(CAM_CSIPHY, + "2PHASE Non combo mode reg array selected"); + reg_array = csiphy_dev->ctrl_reg->csiphy_2ph_reg; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_2ph_config_array_size; + max_lanes = MAX_LANES; } } - size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; + lane_cnt = csiphy_dev->csiphy_info[index].lane_cnt; + lane_assign = csiphy_dev->csiphy_info[index].lane_assign; + lane_enable = csiphy_dev->csiphy_info[index].lane_enable; + size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; for (i = 0; i < size; i++) { csiphy_common_reg = &csiphy_dev->ctrl_reg->csiphy_common_reg[i]; switch (csiphy_common_reg->csiphy_param_type) { case CSIPHY_LANE_ENABLE: + CAM_DBG(CAM_CSIPHY, "LANE_ENABLE: 0x%x", lane_enable); cam_io_w_mb(lane_enable, csiphybase + csiphy_common_reg->reg_addr); break; @@ -477,14 +608,14 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) csiphybase + csiphy_common_reg->reg_addr); break; case CSIPHY_2PH_REGS: - if (!csiphy_dev->csiphy_info.csiphy_3phase) { + if (!is_3phase) { cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); } break; case CSIPHY_3PH_REGS: - if (csiphy_dev->csiphy_info.csiphy_3phase) { + if (is_3phase) { cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); @@ -498,23 +629,12 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) csiphy_common_reg->delay + 5); } - while (lane_mask) { - if (!(lane_mask & 0x1)) { - lane_pos++; - lane_mask >>= 1; - continue; - } + intermediate_var = csiphy_dev->csiphy_info[index].settle_time; + do_div(intermediate_var, 200000000); + settle_cnt = intermediate_var; - intermediate_var = csiphy_dev->csiphy_info.settle_time; - do_div(intermediate_var, 200000000); - settle_cnt = intermediate_var; - if (csiphy_dev->csiphy_info.combo_mode == 1 && - (lane_pos >= 3)) { - intermediate_var = - csiphy_dev->csiphy_info.settle_time_combo_sensor; - do_div(intermediate_var, 200000000); - settle_cnt = intermediate_var; - } + for (lane_pos = 0; lane_pos < max_lanes; lane_pos++) { + CAM_DBG(CAM_CSIPHY, "lane_pos: %d is configuring", lane_pos); for (i = 0; i < cfg_size; i++) { switch (reg_array[lane_pos][i].csiphy_param_type) { case CSIPHY_LANE_ENABLE: @@ -546,15 +666,14 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) reg_array[lane_pos][i].delay + 5); } } - lane_mask >>= 1; - lane_pos++; } - if (csiphy_dev->csiphy_info.csiphy_3phase) - cam_csiphy_cphy_data_rate_config(csiphy_dev); + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + cam_csiphy_cphy_data_rate_config(csiphy_dev, index); cam_csiphy_cphy_irq_config(csiphy_dev); + CAM_DBG(CAM_CSIPHY, "EXIT"); return rc; } @@ -566,19 +685,31 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) return; + if (!csiphy_dev->acquire_count) + return; + + if (csiphy_dev->acquire_count >= CSIPHY_MAX_INSTANCES_PER_PHY) { + CAM_WARN(CAM_CSIPHY, "acquire count is invalid: %u", + csiphy_dev->acquire_count); + csiphy_dev->acquire_count = + CSIPHY_MAX_INSTANCES_PER_PHY; + } + if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { soc_info = &csiphy_dev->soc_info; for (i = 0; i < csiphy_dev->acquire_count; i++) { - if (csiphy_dev->csiphy_info.secure_mode[i]) + if (csiphy_dev->csiphy_info[i].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, i); - csiphy_dev->csiphy_info.secure_mode[i] = + csiphy_dev->csiphy_info[i].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_cpas_cp_reg_mask[i] = 0; + csiphy_dev->csiphy_info[i].csiphy_cpas_cp_reg_mask = 0; + csiphy_dev->csiphy_info[i].settle_time = 0; + csiphy_dev->csiphy_info[i].data_rate = 0; } cam_csiphy_reset(csiphy_dev); @@ -589,22 +720,18 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) } if (csiphy_dev->csiphy_state == CAM_CSIPHY_ACQUIRE) { - if (csiphy_dev->bridge_intf.device_hdl[0] != -1) - cam_destroy_device_hdl( - csiphy_dev->bridge_intf.device_hdl[0]); - if (csiphy_dev->bridge_intf.device_hdl[1] != -1) - cam_destroy_device_hdl( - csiphy_dev->bridge_intf.device_hdl[1]); - csiphy_dev->bridge_intf.device_hdl[0] = -1; - csiphy_dev->bridge_intf.device_hdl[1] = -1; - csiphy_dev->bridge_intf.link_hdl[0] = -1; - csiphy_dev->bridge_intf.link_hdl[1] = -1; - csiphy_dev->bridge_intf.session_hdl[0] = -1; - csiphy_dev->bridge_intf.session_hdl[1] = -1; + for (i = 0; i < csiphy_dev->acquire_count; i++) { + if (csiphy_dev->csiphy_info[i].hdl_data.device_hdl + != -1) + cam_destroy_device_hdl( + csiphy_dev->csiphy_info[i] + .hdl_data.device_hdl); + csiphy_dev->csiphy_info[i].hdl_data.device_hdl = -1; + csiphy_dev->csiphy_info[i].hdl_data.session_hdl = -1; + } } csiphy_dev->ref_count = 0; - csiphy_dev->is_acquired_dev_combo_mode = 0; csiphy_dev->acquire_count = 0; csiphy_dev->start_dev_count = 0; csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; @@ -615,6 +742,7 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev, { struct cam_csiphy_info cam_cmd_csiphy_info; int32_t rc = 0; + int32_t index = -1; if (copy_from_user(&cam_cmd_csiphy_info, u64_to_user_ptr(p_submit_cmd->packet_handle), @@ -622,37 +750,87 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev, CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n"); rc = -EFAULT; } else { - csiphy_dev->csiphy_info.lane_cnt = + index = cam_csiphy_get_instance_offset(csiphy_dev, + p_submit_cmd->dev_handle); + if (index < 0 || + index >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", index); + return -EINVAL; + } + + csiphy_dev->csiphy_info[index].lane_cnt = cam_cmd_csiphy_info.lane_cnt; - csiphy_dev->csiphy_info.lane_cnt = - cam_cmd_csiphy_info.lane_cnt; - csiphy_dev->csiphy_info.lane_mask = - cam_cmd_csiphy_info.lane_mask; - csiphy_dev->csiphy_info.csiphy_3phase = - cam_cmd_csiphy_info.csiphy_3phase; - csiphy_dev->csiphy_info.combo_mode = - cam_cmd_csiphy_info.combo_mode; - csiphy_dev->csiphy_info.settle_time = + csiphy_dev->csiphy_info[index].lane_assign = + cam_cmd_csiphy_info.lane_assign; + csiphy_dev->csiphy_info[index].settle_time = cam_cmd_csiphy_info.settle_time; - csiphy_dev->csiphy_info.data_rate = + csiphy_dev->csiphy_info[index].data_rate = cam_cmd_csiphy_info.data_rate; CAM_DBG(CAM_CSIPHY, - "%s CONFIG_DEV_EXT settle_time= %lld lane_cnt=%d lane_mask=0x%x", + "%s CONFIG_DEV_EXT settle_time= %lld lane_cnt=%d", __func__, - csiphy_dev->csiphy_info.settle_time, - csiphy_dev->csiphy_info.lane_cnt, - csiphy_dev->csiphy_info.lane_mask); + csiphy_dev->csiphy_info[index].settle_time, + csiphy_dev->csiphy_info[index].lane_cnt); } return rc; } +static int cam_csiphy_update_lane( + struct csiphy_device *csiphy, int index, bool enable) +{ + int i = 0; + uint32_t lane_enable = 0; + uint32_t size = 0; + uint16_t lane_assign; + void __iomem *base_address; + struct csiphy_reg_t *csiphy_common_reg = NULL; + + base_address = csiphy->soc_info.reg_map[0].mem_base; + size = csiphy->ctrl_reg->csiphy_reg.csiphy_common_array_size; + + for (i = 0; i < size; i++) { + csiphy_common_reg = &csiphy->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_LANE_ENABLE: + CAM_DBG(CAM_CSIPHY, "LANE_ENABLE: %d", lane_enable); + lane_enable = cam_io_r(base_address + + csiphy_common_reg->reg_addr); + break; + } + } + + lane_assign = csiphy->csiphy_info[index].lane_assign; + + if (enable) + lane_enable |= csiphy->csiphy_info[index].lane_enable; + else + lane_enable &= ~csiphy->csiphy_info[index].lane_enable; + + CAM_DBG(CAM_CSIPHY, "lane_assign: 0x%x, lane_enable: 0x%x", + lane_assign, lane_enable); + for (i = 0; i < size; i++) { + csiphy_common_reg = &csiphy->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_LANE_ENABLE: + CAM_DBG(CAM_CSIPHY, "LANE_ENABLE: %d", lane_enable); + cam_io_w_mb(lane_enable, + base_address + csiphy_common_reg->reg_addr); + if (csiphy_common_reg->delay) + usleep_range(csiphy_common_reg->delay, + csiphy_common_reg->delay + 5); + break; + } + } + + return 0; +} + int32_t cam_csiphy_core_cfg(void *phy_dev, void *arg) { struct csiphy_device *csiphy_dev = (struct csiphy_device *)phy_dev; - struct csiphy_intf_params *bridge_intf = NULL; struct cam_control *cmd = (struct cam_control *)arg; int32_t rc = 0; @@ -673,13 +851,28 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, case CAM_ACQUIRE_DEV: { struct cam_sensor_acquire_dev csiphy_acq_dev; struct cam_csiphy_acquire_dev_info csiphy_acq_params; - + int index; struct cam_create_dev_hdl bridge_params; - if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { + CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d COMBO_MODE: %d", + csiphy_dev->acquire_count, + csiphy_dev->combo_mode); + if ((csiphy_dev->csiphy_state == CAM_CSIPHY_START) && + (csiphy_dev->combo_mode == 0) && + (csiphy_dev->acquire_count > 0)) { CAM_ERR(CAM_CSIPHY, - "Not in right state to acquire : %d", - csiphy_dev->csiphy_state); + "NonComboMode does not support multiple acquire: Acquire_count: %d", + csiphy_dev->acquire_count); + rc = -EINVAL; + goto release_mutex; + } + + if ((csiphy_dev->acquire_count) && + (csiphy_dev->acquire_count >= + csiphy_dev->session_max_device_support)) { + CAM_ERR(CAM_CSIPHY, + "Max acquires are allowed in combo mode: %d", + csiphy_dev->session_max_device_support); rc = -EINVAL; goto release_mutex; } @@ -702,32 +895,37 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->acquire_count == 2) { + if (csiphy_acq_params.combo_mode && + csiphy_acq_params.cphy_dphy_combo_mode) { CAM_ERR(CAM_CSIPHY, - "CSIPHY device do not allow more than 2 acquires"); + "Cannot support both Combo_mode and cphy_dphy_combo_mode"); rc = -EINVAL; goto release_mutex; } - if ((csiphy_acq_params.combo_mode == 1) && - (csiphy_dev->is_acquired_dev_combo_mode == 1)) { - CAM_ERR(CAM_CSIPHY, - "Multiple Combo Acq are not allowed: cm: %d, acm: %d", - csiphy_acq_params.combo_mode, - csiphy_dev->is_acquired_dev_combo_mode); - rc = -EINVAL; - goto release_mutex; + if (csiphy_acq_params.combo_mode == 1) { + CAM_DBG(CAM_CSIPHY, "combo mode stream detected"); + csiphy_dev->combo_mode = 1; + if (csiphy_acq_params.csiphy_3phase) + csiphy_dev->session_max_device_support = + CSIPHY_MAX_INSTANCES_PER_PHY; + else + csiphy_dev->session_max_device_support = + CSIPHY_MAX_INSTANCES_PER_PHY - 1; } - if ((csiphy_acq_params.combo_mode != 1) && - (csiphy_dev->is_acquired_dev_combo_mode != 1) && - (csiphy_dev->acquire_count == 1)) { - CAM_ERR(CAM_CSIPHY, - "Multiple Acquires are not allowed cm: %d acm: %d", - csiphy_acq_params.combo_mode, - csiphy_dev->is_acquired_dev_combo_mode); - rc = -EINVAL; - goto release_mutex; + if (csiphy_acq_params.cphy_dphy_combo_mode == 1) { + CAM_DBG(CAM_CSIPHY, + "cphy_dphy_combo_mode stream detected"); + csiphy_dev->cphy_dphy_combo_mode = 1; + csiphy_dev->session_max_device_support = + CSIPHY_MAX_INSTANCES_PER_PHY - 1; + } + + if (!csiphy_acq_params.combo_mode && + !csiphy_acq_params.cphy_dphy_combo_mode) { + CAM_DBG(CAM_CSIPHY, "Non Combo Mode stream"); + csiphy_dev->session_max_device_support = 1; } bridge_params.ops = NULL; @@ -735,22 +933,19 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = csiphy_dev; - - if (csiphy_acq_params.combo_mode >= 2) { - CAM_ERR(CAM_CSIPHY, "Invalid combo_mode %d", - csiphy_acq_params.combo_mode); - rc = -EINVAL; - goto release_mutex; - } - + index = csiphy_dev->acquire_count; csiphy_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); - bridge_intf = &csiphy_dev->bridge_intf; - bridge_intf->device_hdl[csiphy_acq_params.combo_mode] - = csiphy_acq_dev.device_handle; - bridge_intf->session_hdl[csiphy_acq_params.combo_mode] = + csiphy_dev->csiphy_info[index].hdl_data.device_hdl = + csiphy_acq_dev.device_handle; + csiphy_dev->csiphy_info[index].hdl_data.session_hdl = csiphy_acq_dev.session_handle; + csiphy_dev->csiphy_info[index].csiphy_3phase = + csiphy_acq_params.csiphy_3phase; + CAM_DBG(CAM_CSIPHY, "Add dev_handle:0x%x at index: %d ", + csiphy_dev->csiphy_info[index].hdl_data.device_hdl, + index); if (copy_to_user(u64_to_user_ptr(cmd->handle), &csiphy_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { @@ -758,11 +953,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = -EINVAL; goto release_mutex; } - if (csiphy_acq_params.combo_mode == 1) - csiphy_dev->is_acquired_dev_combo_mode = 1; csiphy_dev->acquire_count++; - csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; + CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d", + csiphy_dev->acquire_count); + if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) + csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; } break; case CAM_QUERY_CAP: { @@ -788,8 +984,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if ((csiphy_dev->csiphy_state != CAM_CSIPHY_START) || - !csiphy_dev->start_dev_count) { + if (csiphy_dev->csiphy_state != CAM_CSIPHY_START) { CAM_ERR(CAM_CSIPHY, "Not in right state to stop : %d", csiphy_dev->csiphy_state); goto release_mutex; @@ -797,35 +992,44 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, offset = cam_csiphy_get_instance_offset(csiphy_dev, config.dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); + if (offset < 0 || + offset >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "Index is invalid: %d", offset); goto release_mutex; } + CAM_INFO(CAM_CSIPHY, + "STOP_DEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", + csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].data_rate, + csiphy_dev->csiphy_info[offset].settle_time); + if (--csiphy_dev->start_dev_count) { CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d", csiphy_dev->start_dev_count); - if (csiphy_dev->csiphy_info.secure_mode[offset]) + if (csiphy_dev->csiphy_info[offset].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0; + csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask + = 0; + cam_csiphy_update_lane(csiphy_dev, offset, false); goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode[offset]) + if (csiphy_dev->csiphy_info[offset].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; + csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0; rc = cam_csiphy_disable_hw(csiphy_dev); if (rc < 0) @@ -835,6 +1039,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, if (rc < 0) CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc); + CAM_DBG(CAM_CSIPHY, "All PHY devices stopped"); csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; } break; @@ -857,17 +1062,18 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, offset = cam_csiphy_get_instance_offset(csiphy_dev, release.dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); + if (offset < 0 || + offset >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", offset); goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode[offset]) + if (csiphy_dev->csiphy_info[offset].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; @@ -875,32 +1081,29 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = cam_destroy_device_hdl(release.dev_handle); if (rc < 0) CAM_ERR(CAM_CSIPHY, "destroying the device hdl"); - if (release.dev_handle == - csiphy_dev->bridge_intf.device_hdl[0]) { - csiphy_dev->bridge_intf.device_hdl[0] = -1; - csiphy_dev->bridge_intf.link_hdl[0] = -1; - csiphy_dev->bridge_intf.session_hdl[0] = -1; - } else { - csiphy_dev->bridge_intf.device_hdl[1] = -1; - csiphy_dev->bridge_intf.link_hdl[1] = -1; - csiphy_dev->bridge_intf.session_hdl[1] = -1; - csiphy_dev->is_acquired_dev_combo_mode = 0; - } + csiphy_dev->csiphy_info[offset].hdl_data.device_hdl = -1; + csiphy_dev->csiphy_info[offset].hdl_data.session_hdl = -1; csiphy_dev->config_count--; - csiphy_dev->acquire_count--; + if (csiphy_dev->acquire_count) { + csiphy_dev->acquire_count--; + CAM_DBG(CAM_CSIPHY, "Acquire_cnt: %d", + csiphy_dev->acquire_count); + } - if (csiphy_dev->acquire_count == 0) + if (csiphy_dev->start_dev_count == 0) { + CAM_DBG(CAM_CSIPHY, "All PHY devices released"); csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; - + } if (csiphy_dev->config_count == 0) { CAM_DBG(CAM_CSIPHY, "reset csiphy_info"); - csiphy_dev->csiphy_info.lane_mask = 0; - csiphy_dev->csiphy_info.lane_cnt = 0; - csiphy_dev->csiphy_info.combo_mode = 0; + csiphy_dev->csiphy_info[offset].lane_cnt = 0; + csiphy_dev->csiphy_info[offset].lane_assign = 0; + csiphy_dev->csiphy_info[offset].csiphy_3phase = -1; + csiphy_dev->combo_mode = 0; } - } break; + } case CAM_CONFIG_DEV: { struct cam_config_dev_cmd config; @@ -922,6 +1125,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, struct cam_axi_vote axi_vote = {0}; struct cam_start_stop_dev_cmd config; int32_t offset; + int clk_vote_level = -1; rc = copy_from_user(&config, (void __user *)cmd->handle, sizeof(config)); @@ -930,18 +1134,86 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { - csiphy_dev->start_dev_count++; + if ((csiphy_dev->csiphy_state == CAM_CSIPHY_START) && + (csiphy_dev->start_dev_count > + csiphy_dev->session_max_device_support)) { + CAM_ERR(CAM_CSIPHY, + "Invalid start count: %d, Max supported devices: %u", + csiphy_dev->start_dev_count, + csiphy_dev->session_max_device_support); + rc = -EINVAL; goto release_mutex; } offset = cam_csiphy_get_instance_offset(csiphy_dev, config.dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); + if (offset < 0 || + offset >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", offset); goto release_mutex; } + CAM_INFO(CAM_CSIPHY, + "START_DEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", + csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].data_rate, + csiphy_dev->csiphy_info[offset].settle_time); + + if (csiphy_dev->start_dev_count) { + clk_vote_level = + csiphy_dev->ctrl_reg->getclockvoting( + csiphy_dev, offset); + rc = cam_soc_util_set_clk_rate_level( + &csiphy_dev->soc_info, clk_vote_level); + if (rc) { + CAM_WARN(CAM_CSIPHY, + "Failed to set the clk_rate level: %d", + clk_vote_level); + rc = 0; + } + + if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { + if (cam_cpas_is_feature_supported( + CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { + CAM_WARN(CAM_CSIPHY, + "sec_cam: camera fuse bit not set"); + rc = 0; + goto release_mutex; + } + + rc = cam_csiphy_notify_secure_mode(csiphy_dev, + CAM_SECURE_MODE_SECURE, offset); + if (rc < 0) { + csiphy_dev->csiphy_info[offset] + .secure_mode = + CAM_SECURE_MODE_NON_SECURE; + CAM_WARN(CAM_CSIPHY, + "sec_cam: notify failed: rc: %d", + rc); + rc = 0; + goto release_mutex; + } + } + if (csiphy_dev->csiphy_info[offset].csiphy_3phase) + cam_csiphy_cphy_data_rate_config( + csiphy_dev, offset); + + rc = cam_csiphy_update_lane(csiphy_dev, offset, true); + if (csiphy_dump == 1) + cam_csiphy_mem_dmp(&csiphy_dev->soc_info); + if (rc) { + CAM_WARN(CAM_CSIPHY, + "csiphy_config_dev failed"); + goto release_mutex; + } + + csiphy_dev->start_dev_count++; + goto release_mutex; + } + + CAM_DBG(CAM_CSIPHY, "Start_dev_cnt: %d", + csiphy_dev->start_dev_count); + ahb_vote.type = CAM_VOTE_ABSOLUTE; ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; @@ -958,7 +1230,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) { + if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { if (cam_cpas_is_feature_supported( CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { CAM_ERR(CAM_CSIPHY, @@ -972,20 +1244,20 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev, CAM_SECURE_MODE_SECURE, offset); if (rc < 0) { - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; cam_cpas_stop(csiphy_dev->cpas_handle); goto release_mutex; } } - rc = cam_csiphy_enable_hw(csiphy_dev); + rc = cam_csiphy_enable_hw(csiphy_dev, offset); if (rc != 0) { CAM_ERR(CAM_CSIPHY, "cam_csiphy_enable_hw failed"); cam_cpas_stop(csiphy_dev->cpas_handle); goto release_mutex; } - rc = cam_csiphy_config_dev(csiphy_dev); + rc = cam_csiphy_config_dev(csiphy_dev, config.dev_handle); if (csiphy_dump == 1) cam_csiphy_mem_dmp(&csiphy_dev->soc_info); @@ -996,6 +1268,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } csiphy_dev->start_dev_count++; + CAM_DBG(CAM_CSIPHY, "START DEV CNT: %d", + csiphy_dev->start_dev_count); csiphy_dev->csiphy_state = CAM_CSIPHY_START; } break; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index ebfd041d13bf..9150125fe53a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -131,6 +131,7 @@ static int cam_csiphy_component_bind(struct device *dev, struct csiphy_device *new_csiphy_dev; int32_t rc = 0; struct platform_device *pdev = to_platform_device(dev); + int i; new_csiphy_dev = devm_kzalloc(&pdev->dev, sizeof(struct csiphy_device), GFP_KERNEL); @@ -183,18 +184,23 @@ static int cam_csiphy_component_bind(struct device *dev, platform_set_drvdata(pdev, &(new_csiphy_dev->v4l2_dev_str.sd)); - new_csiphy_dev->bridge_intf.device_hdl[0] = -1; - new_csiphy_dev->bridge_intf.device_hdl[1] = -1; - new_csiphy_dev->bridge_intf.ops.get_dev_info = - NULL; - new_csiphy_dev->bridge_intf.ops.link_setup = - NULL; - new_csiphy_dev->bridge_intf.ops.apply_req = - NULL; + for (i = 0; i < CSIPHY_MAX_INSTANCES_PER_PHY; i++) { + new_csiphy_dev->csiphy_info[i].hdl_data.device_hdl = -1; + new_csiphy_dev->csiphy_info[i].hdl_data.session_hdl = -1; + new_csiphy_dev->csiphy_info[i].csiphy_3phase = -1; + new_csiphy_dev->csiphy_info[i].data_rate = 0; + new_csiphy_dev->csiphy_info[i].settle_time = 0; + new_csiphy_dev->csiphy_info[i].lane_cnt = 0; + new_csiphy_dev->csiphy_info[i].lane_assign = 0; + new_csiphy_dev->csiphy_info[i].lane_enable = 0; + } + + new_csiphy_dev->ops.get_dev_info = NULL; + new_csiphy_dev->ops.link_setup = NULL; + new_csiphy_dev->ops.apply_req = NULL; new_csiphy_dev->acquire_count = 0; new_csiphy_dev->start_dev_count = 0; - new_csiphy_dev->is_acquired_dev_combo_mode = 0; cpas_parms.cam_cpas_client_cb = NULL; cpas_parms.cell_index = new_csiphy_dev->soc_info.index; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index ac5a017b151e..35c2f585deb7 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -29,7 +29,7 @@ #include "cam_context.h" #define MAX_CSIPHY 6 -#define MAX_DPHY_DATA_LN 4 + #define MAX_LRME_V4l2_EVENTS 30 #define CSIPHY_NUM_CLK_MAX 16 #define MAX_CSIPHY_REG_ARRAY 70 @@ -41,6 +41,7 @@ #define MAX_DATA_RATE_REGS 30 #define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver" +#define CAM_CSIPHY_RX_CLK_SRC "cphy_rx_src_clk" #define CSIPHY_POWER_UP 0 #define CSIPHY_POWER_DOWN 1 @@ -53,20 +54,25 @@ #define CSIPHY_2PH_REGS 5 #define CSIPHY_3PH_REGS 6 -#define CSIPHY_MAX_INSTANCES 2 +#define CSIPHY_MAX_INSTANCES_PER_PHY 3 #define CAM_CSIPHY_MAX_DPHY_LANES 4 #define CAM_CSIPHY_MAX_CPHY_LANES 3 +#define CAM_CSIPHY_MAX_CPHY_DPHY_COMBO_LN 3 +#define CAM_CSIPHY_MAX_CPHY_COMBO_LN 3 + + +#define DPHY_LANE_0 BIT(0) +#define CPHY_LANE_0 BIT(1) +#define DPHY_LANE_1 BIT(2) +#define CPHY_LANE_1 BIT(3) +#define DPHY_LANE_2 BIT(4) +#define CPHY_LANE_2 BIT(5) +#define DPHY_LANE_3 BIT(6) +#define DPHY_CLK_LN BIT(7) #define ENABLE_IRQ false -#undef CDBG -#ifdef CAM_CSIPHY_CORE_DEBUG -#define CDBG(fmt, args...) pr_err(fmt, ##args) -#else -#define CDBG(fmt, args...) pr_debug(fmt, ##args) -#endif - enum cam_csiphy_state { CAM_CSIPHY_INIT, CAM_CSIPHY_ACQUIRE, @@ -111,6 +117,7 @@ struct csiphy_reg_parms_t { uint32_t csiphy_reset_array_size; uint32_t csiphy_2ph_config_array_size; uint32_t csiphy_3ph_config_array_size; + uint32_t csiphy_2ph_3ph_config_array_size; uint32_t csiphy_cpas_cp_bits_per_phy; uint32_t csiphy_cpas_cp_is_interleaved; uint32_t csiphy_cpas_cp_2ph_offset; @@ -123,22 +130,17 @@ struct csiphy_reg_parms_t { * struct csiphy_intf_params * @device_hdl: Device Handle * @session_hdl: Session Handle - * @ops: KMD operations - * @crm_cb: Callback API pointers */ -struct csiphy_intf_params { - int32_t device_hdl[CSIPHY_MAX_INSTANCES]; - int32_t session_hdl[CSIPHY_MAX_INSTANCES]; - int32_t link_hdl[CSIPHY_MAX_INSTANCES]; - struct cam_req_mgr_kmd_ops ops; - struct cam_req_mgr_crm_cb *crm_cb; +struct csiphy_hdl_tbl { + int32_t device_hdl; + int32_t session_hdl; }; /** * struct csiphy_reg_t - * @reg_addr: Register address - * @reg_data: Register data - * @delay: Delay in us + * @reg_addr: Register address + * @reg_data: Register data + * @delay: Delay in us * @csiphy_param_type: CSIPhy parameter type */ struct csiphy_reg_t { @@ -200,38 +202,35 @@ struct csiphy_ctrl_t { struct csiphy_reg_t (*csiphy_2ph_reg)[MAX_SETTINGS_PER_LANE]; struct csiphy_reg_t (*csiphy_2ph_combo_mode_reg)[MAX_SETTINGS_PER_LANE]; struct csiphy_reg_t (*csiphy_3ph_reg)[MAX_SETTINGS_PER_LANE]; + struct csiphy_reg_t (*csiphy_3ph_combo_reg)[MAX_SETTINGS_PER_LANE]; struct csiphy_reg_t (*csiphy_2ph_3ph_mode_reg)[MAX_SETTINGS_PER_LANE]; - enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev); + enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev, + int32_t index); struct data_rate_settings_t *data_rates_settings_table; }; /** - * cam_csiphy_param: Provides cmdbuffer structre - * @lane_mask : Lane mask details - * @lane_assign : Lane sensor will be using - * @csiphy_3phase : Mentions DPHY or CPHY - * @combo_mode : Info regarding combo_mode is enable / disable - * @lane_cnt : Total number of lanes - * @reserved - * @3phase : Details whether 3Phase / 2Phase operation - * @settle_time : Settling time in ms - * @settle_time_combo_sensor : Settling time in ms - * @data_rate : Data rate in mbps - * @data_rate_combo_sensor: data rate of combo sensor - * in the the same phy - * + * cam_csiphy_param : Provides cmdbuffer structure + * @lane_assign : Lane sensor will be using + * @lane_cnt : Total number of lanes + * @secure_mode : To identify whether stream is secure/nonsecure + * @lane_enable : Data Lane selection + * @settle_time : Settling time in ms + * @data_rate : Data rate in mbps + * @csiphy_3phase : To identify DPHY or CPHY + * @csiphy_cpas_cp_reg_mask : CP reg mask for phy instance + * @hdl_data : CSIPHY handle table */ struct cam_csiphy_param { - uint16_t lane_mask; - uint16_t lane_assign; - uint8_t csiphy_3phase; - uint8_t combo_mode; - uint8_t lane_cnt; - uint8_t secure_mode[CSIPHY_MAX_INSTANCES]; - uint64_t settle_time; - uint64_t settle_time_combo_sensor; - uint64_t data_rate; - uint64_t data_rate_combo_sensor; + uint16_t lane_assign; + uint8_t lane_cnt; + uint8_t secure_mode; + uint32_t lane_enable; + uint64_t settle_time; + uint64_t data_rate; + int csiphy_3phase; + uint64_t csiphy_cpas_cp_reg_mask; + struct csiphy_hdl_tbl hdl_data; }; /** @@ -255,41 +254,50 @@ struct cam_csiphy_param { * @csi_3phase: Is it a 3Phase mode * @ref_count: Reference count * @clk_lane: Clock lane + * @rx_clk_src_idx: Phy src clk index * @acquire_count: Acquire device count * @start_dev_count: Start count - * @is_acquired_dev_combo_mode: Flag that mentions whether already acquired - * device is for combo mode * @soc_info: SOC information * @cpas_handle: CPAS handle * @config_count: Config reg count - * @csiphy_cpas_cp_reg_mask: CP reg mask for phy instance + * @current_data_rate: Data rate in mbps + * @csiphy_3phase: To identify DPHY or CPHY at top level + * @combo_mode: Info regarding combo_mode is enable / disable + * @ops: KMD operations + * @crm_cb: Callback API pointers */ struct csiphy_device { - char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; - struct mutex mutex; - uint32_t hw_version; - enum cam_csiphy_state csiphy_state; - struct csiphy_ctrl_t *ctrl_reg; - uint32_t csiphy_max_clk; - struct msm_cam_clk_info csiphy_3p_clk_info[2]; - struct clk *csiphy_3p_clk[2]; - unsigned char csi_3phase; - int32_t ref_count; - uint16_t lane_mask[MAX_CSIPHY]; - uint8_t is_csiphy_3phase_hw; - uint8_t is_divisor_32_comp; - uint8_t num_irq_registers; - struct cam_subdev v4l2_dev_str; - struct cam_csiphy_param csiphy_info; - struct csiphy_intf_params bridge_intf; - uint32_t clk_lane; - uint32_t acquire_count; - uint32_t start_dev_count; - uint32_t is_acquired_dev_combo_mode; - struct cam_hw_soc_info soc_info; - uint32_t cpas_handle; - uint32_t config_count; - uint64_t csiphy_cpas_cp_reg_mask[CSIPHY_MAX_INSTANCES]; + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; + struct mutex mutex; + uint32_t hw_version; + enum cam_csiphy_state csiphy_state; + struct csiphy_ctrl_t *ctrl_reg; + uint32_t csiphy_max_clk; + struct msm_cam_clk_info csiphy_3p_clk_info[2]; + struct clk *csiphy_3p_clk[2]; + int32_t ref_count; + uint16_t lane_mask[MAX_CSIPHY]; + uint8_t is_csiphy_3phase_hw; + uint8_t is_divisor_32_comp; + uint8_t num_irq_registers; + struct cam_subdev v4l2_dev_str; + struct cam_csiphy_param csiphy_info[ + CSIPHY_MAX_INSTANCES_PER_PHY]; + uint32_t clk_lane; + uint8_t rx_clk_src_idx; + uint32_t acquire_count; + uint32_t start_dev_count; + struct cam_hw_soc_info soc_info; + uint32_t cpas_handle; + uint32_t config_count; + uint64_t current_data_rate; + uint64_t csiphy_cpas_cp_reg_mask[ + CSIPHY_MAX_INSTANCES_PER_PHY]; + uint8_t session_max_device_support; + uint8_t combo_mode; + uint8_t cphy_dphy_combo_mode; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index bedd0570b4e0..5143f2ab0abb 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -126,26 +126,25 @@ int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) -enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev) +enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev, + int32_t index) { CAM_DBG(CAM_CSIPHY, "voting for SVS"); return CAM_SVS_VOTE; } -enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) +enum cam_vote_level get_clk_voting_dynamic( + struct csiphy_device *csiphy_dev, int32_t index) { uint32_t cam_vote_level = 0; uint32_t last_valid_vote = 0; struct cam_hw_soc_info *soc_info; - uint64_t phy_data_rate = csiphy_dev->csiphy_info.data_rate; + uint64_t phy_data_rate = csiphy_dev->csiphy_info[index].data_rate; soc_info = &csiphy_dev->soc_info; + phy_data_rate = max(phy_data_rate, csiphy_dev->current_data_rate); - if (csiphy_dev->is_acquired_dev_combo_mode) - phy_data_rate = max(phy_data_rate, - csiphy_dev->csiphy_info.data_rate_combo_sensor); - - if (csiphy_dev->csiphy_info.csiphy_3phase) { + if (csiphy_dev->csiphy_info[index].csiphy_3phase) { if (csiphy_dev->is_divisor_32_comp) do_div(phy_data_rate, CSIPHY_DIVISOR_32); else @@ -156,19 +155,21 @@ enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) /* round off to next integer */ phy_data_rate += 1; + csiphy_dev->current_data_rate = phy_data_rate; for (cam_vote_level = 0; cam_vote_level < CAM_MAX_VOTE; cam_vote_level++) { if (soc_info->clk_level_valid[cam_vote_level] != true) continue; - if (soc_info->clk_rate[cam_vote_level][0] > - phy_data_rate) { + if (soc_info->clk_rate[cam_vote_level] + [csiphy_dev->rx_clk_src_idx] > phy_data_rate) { CAM_DBG(CAM_CSIPHY, "match detected %s : %llu:%d level : %d", - soc_info->clk_name[0], + soc_info->clk_name[csiphy_dev->rx_clk_src_idx], phy_data_rate, - soc_info->clk_rate[cam_vote_level][0], + soc_info->clk_rate[cam_vote_level] + [csiphy_dev->rx_clk_src_idx], cam_vote_level); return cam_vote_level; } @@ -177,7 +178,7 @@ enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) return last_valid_vote; } -int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev) +int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index) { int32_t rc = 0; struct cam_hw_soc_info *soc_info; @@ -191,7 +192,7 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev) return rc; } - vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev); + vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, index); rc = cam_soc_util_enable_platform_resource(soc_info, true, vote_level, ENABLE_IRQ); if (rc < 0) { @@ -466,6 +467,10 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->csiphy_3p_clk[1] = soc_info->clk[i]; continue; + } else if (!strcmp(soc_info->clk_name[i], + CAM_CSIPHY_RX_CLK_SRC)) { + csiphy_dev->rx_clk_src_idx = i; + continue; } CAM_DBG(CAM_CSIPHY, "clk_rate[%d] = %d", clk_cnt, diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 0416d8cda66d..2ae08006fa8a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -21,9 +21,6 @@ #include "cam_csiphy_dev.h" #include "cam_csiphy_core.h" -#undef CDBG -#define CDBG(fmt, args...) pr_debug(fmt, ##args) - #define CSI_3PHASE_HW 1 #define CSIPHY_VERSION_V35 0x35 #define CSIPHY_VERSION_V10 0x10 @@ -55,7 +52,7 @@ int cam_csiphy_parse_dt_info(struct platform_device *pdev, * * This API enables SOC related parameters */ -int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev); +int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index); /** * @csiphy_dev: CSIPhy device structure diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index a9290d6e6cc5..bddd49432d9a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -16,6 +16,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 16, .csiphy_3ph_config_array_size = 28, + .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 27c84b0ecac2..21ebc95ab35e 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -77,11 +77,12 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, { int rc = 0; - if (offset >= CSIPHY_MAX_INSTANCES) { + if (offset >= CSIPHY_MAX_INSTANCES_PER_PHY) { CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); rc = -EINVAL; } else if (qcom_scm_camera_protect_phy_lanes(protect, - csiphy_dev->csiphy_cpas_cp_reg_mask[offset])) { + csiphy_dev->csiphy_info[offset] + .csiphy_cpas_cp_reg_mask)) { CAM_ERR(CAM_CSIPHY, "SCM call to hypervisor failed"); rc = -EINVAL; } @@ -158,10 +159,11 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, struct scm_desc description = { .arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL), .args[0] = protect, - .args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset], + .args[1] = csiphy_dev->csiphy_info[offset] + .csiphy_cpas_cp_reg_mask, }; - if (offset >= CSIPHY_MAX_INSTANCES) { + if (offset >= CSIPHY_MAX_INSTANCES_PER_PHY) { CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); rc = -EINVAL; } else if (scm_call2(SCM_SIP_FNID(0x18, 0x7), &description)) { diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index bc9498ea6101..4ff9ecc7c3a1 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -324,23 +324,18 @@ struct cam_cmd_unconditional_wait { } __attribute__((packed)); /** - * cam_csiphy_info: Provides cmdbuffer structre - * @lane_mask : Lane mask details - * @lane_assign : Lane sensor will be using - * @csiphy_3phase : Total number of lanes - * @combo_mode : Info regarding combo_mode is enable / disable - * @lane_cnt : Total number of lanes - * @secure_mode : Secure mode flag to enable / disable - * @3phase : Details whether 3Phase / 2Phase operation - * @settle_time : Settling time in ms - * @data_rate : Data rate + * cam_csiphy_info : Provides cmdbuffer structre + * @lane_assign : Lane sensor will be using + * @lane_cnt : Total number of lanes + * @secure_mode : Secure mode flag to enable / disable + * @settle_time : Settling time in ms + * @data_rate : Data rate * */ struct cam_csiphy_info { - __u16 lane_mask; + __u16 reserved; __u16 lane_assign; - __u8 csiphy_3phase; - __u8 combo_mode; + __u16 reserved1; __u8 lane_cnt; __u8 secure_mode; __u64 settle_time; @@ -349,14 +344,18 @@ struct cam_csiphy_info { /** * cam_csiphy_acquire_dev_info : Information needed for - * csiphy at the time of acquire - * @combo_mode : Indicates the device mode of operation - * @reserved + * csiphy at the time of acquire + * @combo_mode : Indicates the device mode of operation + * @cphy_dphy_combo_mode : Info regarding cphy_dphy_combo mode + * @csiphy_3phase : Details whether 3Phase / 2Phase operation + * @reserve * */ struct cam_csiphy_acquire_dev_info { __u32 combo_mode; - __u32 reserved; + __u16 cphy_dphy_combo_mode; + __u8 csiphy_3phase; + __u8 reserve; } __attribute__((packed)); /** From d543187b79bcdc53be3705f8c90c604bd6589d3e Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Tue, 16 Jun 2020 17:30:19 -0700 Subject: [PATCH 404/790] msm: camera: utils: Add final BW vote logs as perf logs AHB and AXI BW voting path requires all key logs to be perf. Change BW voting logs in utils to perf for easier debugging. CRs-Fixed: 2584631 Change-Id: I41ef094f6633101bb7b636ea310aca81de0101c7 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_utils/cam_soc_bus.c | 8 ++++---- drivers/cam_utils/cam_soc_icc.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/cam_utils/cam_soc_bus.c b/drivers/cam_utils/cam_soc_bus.c index 1cef2610b805..465a7da4ffbf 100644 --- a/drivers/cam_utils/cam_soc_bus.c +++ b/drivers/cam_utils/cam_soc_bus.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -48,7 +48,7 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) goto end; } - CAM_DBG(CAM_UTIL, "Bus client=[%d][%s] index[%d]", + CAM_DBG(CAM_PERF, "Bus client=[%d][%s] index[%d]", bus_client_data->client_id, bus_client->common_data->name, idx); rc = msm_bus_scale_client_update_request(bus_client_data->client_id, @@ -99,7 +99,7 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) path->vectors[0].ab = ab; path->vectors[0].ib = ib; - CAM_DBG(CAM_UTIL, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", + CAM_DBG(CAM_PERF, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", bus_client_data->client_id, bus_client->common_data->name, ab, ib, idx); rc = msm_bus_scale_client_update_request(bus_client_data->client_id, @@ -194,7 +194,7 @@ int cam_soc_bus_client_register(struct platform_device *pdev, bus_client_data->num_paths = pdata->usecase[0].num_paths; bus_client->common_data->name = pdata->name; - CAM_DBG(CAM_UTIL, "Bus Client=[%d][%s] : src=%d, dst=%d", + CAM_DBG(CAM_PERF, "Register Bus Client=[%d][%s] : src=%d, dst=%d", bus_client_data->client_id, bus_client->common_data->name, bus_client->common_data->src_id, bus_client->common_data->dst_id); diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index 7cf14a2c4044..a30e0f153b1b 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -34,8 +34,8 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) ab = bus_client->common_data->bw_pair[idx].ab; ib = bus_client->common_data->bw_pair[idx].ib; - CAM_DBG(CAM_UTIL, "Bus client=[%s] index[%d]", - bus_client->common_data->name, idx); + CAM_DBG(CAM_PERF, "Bus client=[%s] index[%d] ab[%llu] ib[%llu]", + bus_client->common_data->name, idx, ab, ib); rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), Bps_to_icc(ib)); @@ -58,7 +58,7 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) (struct cam_soc_bus_client_data *) bus_client->client_data; int rc = 0; - CAM_DBG(CAM_UTIL, "Bus client=[%s] :ab[%llu] ib[%llu]", + CAM_DBG(CAM_PERF, "Bus client=[%s] :ab[%llu] ib[%llu]", bus_client->common_data->name, ab, ib); rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), Bps_to_icc(ib)); @@ -116,7 +116,7 @@ int cam_soc_bus_client_register(struct platform_device *pdev, goto fail_unregister_client; } - CAM_DBG(CAM_UTIL, "Bus Client=[%s] : src=%d, dst=%d", + CAM_DBG(CAM_PERF, "Register Bus Client=[%s] : src=%d, dst=%d", bus_client->common_data->name, bus_client->common_data->src_id, bus_client->common_data->dst_id); From 7c8204a42dd251e0d37233cae1d918862f8c44b2 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Thu, 18 Jun 2020 19:03:40 -0700 Subject: [PATCH 405/790] msm: camera: common: Enable debugfs compile check Guards debugfs features in camera driver to only be compiled when CONFIG_DEBUG_FS is enabled. CRs-Fixed: 2717236 Change-Id: I0de77741301d259cbec64e8a2e27830981b2b69d Signed-off-by: Karthik Jayakumar --- drivers/cam_cpas/cam_cpas_hw.c | 41 +++---- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 109 ++++++------------ drivers/cam_isp/cam_isp_context.c | 35 +++--- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 75 +++++------- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 83 ++++++------- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 32 ++--- drivers/cam_req_mgr/cam_mem_mgr.c | 35 +++--- drivers/cam_req_mgr/cam_req_mgr_debug.c | 48 ++++---- drivers/cam_smmu/cam_smmu_api.c | 46 ++++---- drivers/cam_sync/cam_sync.c | 30 +++-- drivers/cam_utils/cam_soc_util.c | 62 ++++------ 11 files changed, 257 insertions(+), 339 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index c864a7fb286a..5b509ad51c3f 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -2025,30 +2025,29 @@ static int cam_cpas_util_get_internal_ops(struct platform_device *pdev, return rc; } -static int cam_cpas_util_create_debugfs( - struct cam_cpas *cpas_core) +static int cam_cpas_util_create_debugfs(struct cam_cpas *cpas_core) { int rc = 0; + struct dentry *dbgfileptr = NULL; - cpas_core->dentry = debugfs_create_dir("camera_cpas", NULL); - if (!cpas_core->dentry) - return -ENOMEM; - - if (!debugfs_create_bool("ahb_bus_scaling_disable", - 0644, - cpas_core->dentry, - &cpas_core->ahb_bus_scaling_disable)) { - CAM_ERR(CAM_CPAS, - "failed to create ahb_bus_scaling_disable entry"); - rc = -ENOMEM; - goto err; + dbgfileptr = debugfs_create_dir("camera_cpas", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_CPAS,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + cpas_core->dentry = dbgfileptr; - return 0; - -err: - debugfs_remove_recursive(cpas_core->dentry); - cpas_core->dentry = NULL; + dbgfileptr = debugfs_create_bool("ahb_bus_scaling_disable", 0644, + cpas_core->dentry, &cpas_core->ahb_bus_scaling_disable); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_CPAS, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); + } +end: return rc; } @@ -2195,9 +2194,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, if (rc) goto axi_cleanup; - rc = cam_cpas_util_create_debugfs(cpas_core); - if (rc) - CAM_WARN(CAM_CPAS, "Failed to create dentry"); + rc = cam_cpas_util_create_debugfs(cpas_core); *hw_intf = cpas_hw_intf; return 0; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index a2b2666329aa..57dc8586e614 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1885,83 +1885,47 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_a5_fw_dump_lvl, static int cam_icp_hw_mgr_create_debugfs_entry(void) { int rc = 0; + struct dentry *dbgfileptr = NULL; - icp_hw_mgr.dentry = debugfs_create_dir("camera_icp", NULL); - if (IS_ERR_OR_NULL(icp_hw_mgr.dentry)) { - CAM_ERR(CAM_ICP, "Debugfs entry dir: %s failed", - "camrea_icp"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_icp", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_ICP,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + icp_hw_mgr.dentry = dbgfileptr; - if (!debugfs_create_bool("icp_pc", - 0644, - icp_hw_mgr.dentry, - &icp_hw_mgr.icp_pc_flag)) { - CAM_ERR(CAM_ICP, "failed to create icp_pc entry"); - rc = -ENOMEM; - goto err; + dbgfileptr = debugfs_create_bool("icp_pc", 0644, icp_hw_mgr.dentry, + &icp_hw_mgr.icp_pc_flag); + + dbgfileptr = debugfs_create_bool("ipe_bps_pc", 0644, icp_hw_mgr.dentry, + &icp_hw_mgr.ipe_bps_pc_flag); + + dbgfileptr = debugfs_create_file("icp_debug_clk", 0644, + icp_hw_mgr.dentry, NULL, &cam_icp_debug_default_clk); + + dbgfileptr = debugfs_create_bool("a5_jtag_debug", 0644, + icp_hw_mgr.dentry, &icp_hw_mgr.a5_jtag_debug); + + dbgfileptr = debugfs_create_file("a5_debug_type", 0644, + icp_hw_mgr.dentry, NULL, &cam_icp_debug_type_fs); + + dbgfileptr = debugfs_create_file("a5_debug_lvl", 0644, + icp_hw_mgr.dentry, NULL, &cam_icp_debug_fs); + + dbgfileptr = debugfs_create_file("a5_fw_dump_lvl", 0644, + icp_hw_mgr.dentry, NULL, &cam_icp_debug_fw_dump); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_ICP, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - - if (!debugfs_create_bool("ipe_bps_pc", - 0644, - icp_hw_mgr.dentry, - &icp_hw_mgr.ipe_bps_pc_flag)) { - CAM_ERR(CAM_ICP, "failed to create ipe_bps_pc entry"); - rc = -ENOMEM; - goto err; - } - - if (!debugfs_create_file("icp_debug_clk", - 0644, - icp_hw_mgr.dentry, NULL, - &cam_icp_debug_default_clk)) { - CAM_ERR(CAM_ICP, "failed to create icp_debug_clk entry"); - rc = -ENOMEM; - goto err; - } - - if (!debugfs_create_bool("a5_jtag_debug", - 0644, - icp_hw_mgr.dentry, - &icp_hw_mgr.a5_jtag_debug)) { - rc = -ENOMEM; - goto err; - } - - if (!debugfs_create_file("a5_debug_type", - 0644, - icp_hw_mgr.dentry, - NULL, &cam_icp_debug_type_fs)) { - CAM_ERR(CAM_ICP, "failed to create a5_debug_type"); - rc = -ENOMEM; - goto err; - } - - if (!debugfs_create_file("a5_debug_lvl", - 0644, - icp_hw_mgr.dentry, - NULL, &cam_icp_debug_fs)) { - CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl"); - rc = -ENOMEM; - goto err; - } - - if (!debugfs_create_file("a5_fw_dump_lvl", - 0644, - icp_hw_mgr.dentry, - NULL, &cam_icp_debug_fw_dump)) { - CAM_ERR(CAM_ICP, "failed to create a5_fw_dump_lvl"); - rc = -ENOMEM; - goto err; - } - +end: /* Set default hang dump lvl */ icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; return rc; -err: - debugfs_remove_recursive(icp_hw_mgr.dentry); - icp_hw_mgr.dentry = NULL; - return rc; } static int cam_icp_mgr_process_cmd(void *priv, void *data) @@ -6017,10 +5981,9 @@ static int cam_icp_mgr_create_wq(void) } rc = cam_icp_hw_mgr_create_debugfs_entry(); - if (rc) { - CAM_ERR(CAM_ICP, "create_debugfs_entry fail= rc: %d", rc); + if (rc) goto debugfs_create_failed; - } + for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) icp_hw_mgr.msg_work->task.pool[i].payload = &icp_hw_mgr.msg_work_data[i]; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d9abaff11f82..9fa3a6e304a5 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5306,27 +5306,28 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, static int cam_isp_context_debug_register(void) { - isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", - NULL); + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (IS_ERR_OR_NULL(isp_ctx_debug.dentry)) { - CAM_ERR(CAM_ISP, "failed to create dentry"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_isp_ctx", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_ICP,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + isp_ctx_debug.dentry = dbgfileptr; - if (!debugfs_create_u32("enable_state_monitor_dump", - 0644, - isp_ctx_debug.dentry, - &isp_ctx_debug.enable_state_monitor_dump)) { - CAM_ERR(CAM_ISP, "failed to create enable_state_monitor_dump"); - goto err; + dbgfileptr = debugfs_create_u32("enable_state_monitor_dump", 0644, + isp_ctx_debug.dentry, &isp_ctx_debug.enable_state_monitor_dump); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_ICP, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - - return 0; - -err: - debugfs_remove_recursive(isp_ctx_debug.dentry); - return -ENOMEM; +end: + return rc; } int cam_isp_context_init(struct cam_isp_context *ctx, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 2a7218f0fa34..8282f1282780 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7818,61 +7818,40 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug, static int cam_ife_hw_mgr_debug_register(void) { - g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", - NULL); + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (!g_ife_hw_mgr.debug_cfg.dentry) { - CAM_ERR(CAM_ISP, "failed to create dentry"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_ife", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_ISP,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + g_ife_hw_mgr.debug_cfg.dentry = dbgfileptr; - if (!debugfs_create_file("ife_csid_debug", - 0644, - g_ife_hw_mgr.debug_cfg.dentry, NULL, - &cam_ife_csid_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_ife_csid_debug"); - goto err; - } - - if (!debugfs_create_u32("enable_recovery", - 0644, + dbgfileptr = debugfs_create_file("ife_csid_debug", 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_csid_debug); + dbgfileptr = debugfs_create_u32("enable_recovery", 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.enable_recovery)) { - CAM_ERR(CAM_ISP, "failed to create enable_recovery"); - goto err; - } - - if (!debugfs_create_bool("enable_req_dump", - 0644, + &g_ife_hw_mgr.debug_cfg.enable_recovery); + dbgfileptr = debugfs_create_bool("enable_req_dump", 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.enable_req_dump)) { - CAM_ERR(CAM_ISP, "failed to create enable_req_dump"); - goto err; - } - - if (!debugfs_create_file("ife_camif_debug", - 0644, - g_ife_hw_mgr.debug_cfg.dentry, NULL, - &cam_ife_camif_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug"); - goto err; - } - - if (!debugfs_create_bool("per_req_reg_dump", - 0644, + &g_ife_hw_mgr.debug_cfg.enable_req_dump); + dbgfileptr = debugfs_create_file("ife_camif_debug", 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_camif_debug); + dbgfileptr = debugfs_create_bool("per_req_reg_dump", 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.per_req_reg_dump)) { - CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); - goto err; + &g_ife_hw_mgr.debug_cfg.per_req_reg_dump); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - +end: g_ife_hw_mgr.debug_cfg.enable_recovery = 0; - - return 0; - -err: - debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); - return -ENOMEM; + return rc; } static void cam_req_mgr_process_workq_cam_ife_worker(struct work_struct *w) @@ -7888,8 +7867,6 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) struct cam_ife_hw_mgr_ctx *ctx_pool; struct cam_isp_hw_mgr_res *res_list_ife_out; - CAM_DBG(CAM_ISP, "Enter"); - memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr)); mutex_init(&g_ife_hw_mgr.ctx_mutex); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index a28b9773dfd2..41f267633205 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5263,65 +5263,52 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_camif_debug, cam_tfe_get_camif_debug, cam_tfe_set_camif_debug, "%16llu"); +#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_tfe_hw_mgr_debug_register(void) { - g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", - NULL); + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (!g_tfe_hw_mgr.debug_cfg.dentry) { - CAM_ERR(CAM_ISP, "failed to create dentry"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_ife", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_ISP,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + g_tfe_hw_mgr.debug_cfg.dentry = dbgfileptr; - if (!debugfs_create_file("tfe_csid_debug", - 0644, - g_tfe_hw_mgr.debug_cfg.dentry, NULL, - &cam_tfe_csid_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_tfe_csid_debug"); - goto err; - } - - if (!debugfs_create_u32("enable_recovery", - 0644, + dbgfileptr = debugfs_create_file("tfe_csid_debug", 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_csid_debug); + dbgfileptr = debugfs_create_u32("enable_recovery", 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.enable_recovery)) { - CAM_ERR(CAM_ISP, "failed to create enable_recovery"); - goto err; - } - - if (!debugfs_create_u32("enable_reg_dump", - 0644, + &g_tfe_hw_mgr.debug_cfg.enable_recovery); + dbgfileptr = debugfs_create_u32("enable_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.enable_reg_dump)) { - CAM_ERR(CAM_ISP, "failed to create enable_reg_dump"); - goto err; - } - - if (!debugfs_create_file("tfe_camif_debug", - 0644, - g_tfe_hw_mgr.debug_cfg.dentry, NULL, - &cam_tfe_camif_debug)) { - CAM_ERR(CAM_ISP, "failed to create cam_tfe_camif_debug"); - goto err; - } - - if (!debugfs_create_u32("per_req_reg_dump", - 0644, + &g_tfe_hw_mgr.debug_cfg.enable_reg_dump); + dbgfileptr = debugfs_create_file("tfe_camif_debug", 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_camif_debug); + dbgfileptr = debugfs_create_u32("per_req_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump)) { - CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); - goto err; + &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - - +end: g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; - - return 0; - -err: - debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); - return -ENOMEM; + return rc; } +#else +static inline int cam_tfe_hw_mgr_debug_register(void) +{ + g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); + return 0; +} +#endif static void cam_req_mgr_process_tfe_worker(struct work_struct *w) { diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 5cf8c55c0e37..71ff238d0775 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -1016,28 +1016,28 @@ static int cam_lrme_mgr_hw_config(void *hw_mgr_priv, static int cam_lrme_mgr_create_debugfs_entry(void) { int rc = 0; + struct dentry *dbgfileptr = NULL; - g_lrme_hw_mgr.debugfs_entry.dentry = - debugfs_create_dir("camera_lrme", NULL); - if (!g_lrme_hw_mgr.debugfs_entry.dentry) { - CAM_ERR(CAM_LRME, "failed to create dentry"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_lrme", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_ISP,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + g_lrme_hw_mgr.debugfs_entry.dentry = dbgfileptr; - if (!debugfs_create_bool("dump_register", - 0644, + dbgfileptr = debugfs_create_bool("dump_register", 0644, g_lrme_hw_mgr.debugfs_entry.dentry, - &g_lrme_hw_mgr.debugfs_entry.dump_register)) { - CAM_ERR(CAM_LRME, "failed to create dump register entry"); - rc = -ENOMEM; - goto err; + &g_lrme_hw_mgr.debugfs_entry.dump_register); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_LRME, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - return rc; - err: - debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); - g_lrme_hw_mgr.debugfs_entry.dentry = NULL; return rc; } @@ -1145,6 +1145,7 @@ int cam_lrme_mgr_deregister_device(int device_index) int cam_lrme_hw_mgr_deinit(void) { mutex_destroy(&g_lrme_hw_mgr.hw_mgr_mutex); + debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); memset(&g_lrme_hw_mgr, 0x0, sizeof(g_lrme_hw_mgr)); return 0; @@ -1199,7 +1200,6 @@ int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, hw_mgr_intf->hw_dump = cam_lrme_mgr_hw_dump; cam_lrme_mgr_create_debugfs_entry(); - CAM_DBG(CAM_LRME, "Hw mgr init done"); return rc; } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index ca6d671f46f2..3d89aff97e28 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -154,25 +154,28 @@ static int cam_mem_util_unmap_cpu_va(struct dma_buf *dmabuf, static int cam_mem_mgr_create_debug_fs(void) { - tbl.dentry = debugfs_create_dir("camera_memmgr", NULL); - if (!tbl.dentry) { - CAM_ERR(CAM_MEM, "failed to create dentry"); - return -ENOMEM; - } + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (!debugfs_create_bool("alloc_profile_enable", - 0644, - tbl.dentry, - &tbl.alloc_profile_enable)) { - CAM_ERR(CAM_MEM, - "failed to create alloc_profile_enable"); - goto err; + dbgfileptr = debugfs_create_dir("camera_memmgr", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_MEM,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + tbl.dentry = dbgfileptr; - return 0; -err: - debugfs_remove_recursive(tbl.dentry); - return -ENOMEM; + dbgfileptr = debugfs_create_bool("alloc_profile_enable", 0644, + tbl.dentry, &tbl.alloc_profile_enable); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); + } +end: + return rc; } int cam_mem_mgr_init(void) diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index 89b55d937667..41d9258e9a7f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -8,7 +8,6 @@ #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; -static struct dentry *debugfs_root; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { @@ -111,32 +110,35 @@ static const struct file_operations session_info = { .write = session_info_write, }; +static struct dentry *debugfs_root; int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) { - char dirname[32] = {0}; - snprintf(dirname, sizeof(dirname), "cam_req_mgr"); - debugfs_root = debugfs_create_dir(dirname, NULL); - if (IS_ERR_OR_NULL(debugfs_root)) { - CAM_ERR(CAM_CRM, "Failed to create cam_req_mgr debugfs dir"); - return -ENOMEM; + int rc = 0; + struct dentry *dbgfileptr = NULL; + + dbgfileptr = debugfs_create_dir("cam_req_mgr", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_MEM,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + debugfs_root = dbgfileptr; - if (!debugfs_create_file("sessions_info", 0644, - debugfs_root, core_dev, &session_info)) - CAM_WARN(CAM_CRM, - "Failed to create sessions_info debugfs file"); - - if (!debugfs_create_file("bubble_recovery", 0644, - debugfs_root, core_dev, &bubble_recovery)) - CAM_WARN(CAM_CRM, - "Failed to create bubble_recovery debugfs file"); - - if (!debugfs_create_bool("recovery_on_apply_fail", - 0644, debugfs_root, - &core_dev->recovery_on_apply_fail)) - CAM_WARN(CAM_CRM, - "Failed to create recovery_on_apply_fail debugfs bool"); - return 0; + dbgfileptr = debugfs_create_file("sessions_info", 0644, debugfs_root, + core_dev, &session_info); + dbgfileptr = debugfs_create_file("bubble_recovery", 0644, + debugfs_root, core_dev, &bubble_recovery); + dbgfileptr = debugfs_create_bool("recovery_on_apply_fail", 0644, + debugfs_root, &core_dev->recovery_on_apply_fail); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); + } +end: + return rc; } void cam_req_mgr_debug_unregister(void) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index b87972840021..7376c2964f83 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3921,36 +3921,30 @@ cb_init_fail: static int cam_smmu_create_debug_fs(void) { - iommu_cb_set.dentry = debugfs_create_dir("camera_smmu", - NULL); + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (!iommu_cb_set.dentry) { - CAM_ERR(CAM_SMMU, "failed to create dentry"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_smmu", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_SMMU,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + iommu_cb_set.dentry = dbgfileptr; - if (!debugfs_create_bool("cb_dump_enable", - 0644, - iommu_cb_set.dentry, - &iommu_cb_set.cb_dump_enable)) { - CAM_ERR(CAM_SMMU, - "failed to create dump_enable_debug"); - goto err; + dbgfileptr = debugfs_create_bool("cb_dump_enable", 0644, + iommu_cb_set.dentry, &iommu_cb_set.cb_dump_enable); + dbgfileptr = debugfs_create_bool("map_profile_enable", 0644, + iommu_cb_set.dentry, &iommu_cb_set.map_profile_enable); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - - if (!debugfs_create_bool("map_profile_enable", - 0644, - iommu_cb_set.dentry, - &iommu_cb_set.map_profile_enable)) { - CAM_ERR(CAM_SMMU, - "failed to create map_profile_enable"); - goto err; - } - - return 0; -err: - debugfs_remove_recursive(iommu_cb_set.dentry); - return -ENOMEM; +end: + return rc; } static int cam_smmu_fw_dev_component_bind(struct device *dev, diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 37461c27d8c0..68fea1904ffe 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1018,22 +1018,28 @@ static void cam_sync_init_entity(struct sync_device *sync_dev) static int cam_sync_create_debugfs(void) { - sync_dev->dentry = debugfs_create_dir("camera_sync", NULL); + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (!sync_dev->dentry) { - CAM_ERR(CAM_SYNC, "Failed to create sync dir"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir("camera_sync", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_SYNC,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + sync_dev->dentry = dbgfileptr; - if (!debugfs_create_bool("trigger_cb_without_switch", - 0644, sync_dev->dentry, - &trigger_cb_without_switch)) { - CAM_ERR(CAM_SYNC, - "failed to create trigger_cb_without_switch entry"); - return -ENOMEM; + dbgfileptr = debugfs_create_bool("trigger_cb_without_switch", 0644, + sync_dev->dentry, &trigger_cb_without_switch); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_SYNC, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - - return 0; +end: + return rc; } #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 5ea63757526b..764002d2ac31 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -14,7 +14,6 @@ #include "cam_mem_mgr.h" static char supported_clk_info[256]; -static char debugfs_dir_name[64]; int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, int64_t clk_rate, int clk_idx, int32_t *clk_lvl) @@ -181,53 +180,43 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control, * * @return: Success or failure */ -static int cam_soc_util_create_clk_lvl_debugfs( - struct cam_hw_soc_info *soc_info) +static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) { - if (!soc_info) { - CAM_ERR(CAM_UTIL, "soc info is NULL"); - return -EINVAL; - } + char debugfs_dir_name[64]; + int rc = 0; + struct dentry *dbgfileptr = NULL; - if (soc_info->dentry) { - CAM_DBG(CAM_UTIL, "Debubfs entry for %s already exist", + if (!soc_info->dentry) { + CAM_DBG(CAM_UTIL, "Debugfs entry for %s already exist", soc_info->dev_name); - return 0; + goto end; } memset(debugfs_dir_name, 0, sizeof(debugfs_dir_name)); strlcat(debugfs_dir_name, "clk_dir_", sizeof(debugfs_dir_name)); strlcat(debugfs_dir_name, soc_info->dev_name, sizeof(debugfs_dir_name)); - soc_info->dentry = debugfs_create_dir(debugfs_dir_name, NULL); - if (IS_ERR_OR_NULL(soc_info->dentry)) { - CAM_ERR(CAM_UTIL, "failed to create debug directory"); - return -ENOMEM; + dbgfileptr = debugfs_create_dir(debugfs_dir_name, NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_UTIL,"DebugFS could not create directory!"); + rc = -ENOENT; + goto end; } + /* Store parent inode for cleanup in caller */ + soc_info->dentry = dbgfileptr; - if (!debugfs_create_file("clk_lvl_options", 0444, - soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_options)) { - CAM_ERR(CAM_UTIL, "failed to create clk_lvl_options"); - goto err; + dbgfileptr = debugfs_create_file("clk_lvl_options", 0444, + soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_options); + dbgfileptr = debugfs_create_file("clk_lvl_control", 0644, + soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_UTIL, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); } - - if (!debugfs_create_file("clk_lvl_control", 0644, - soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control)) { - CAM_ERR(CAM_UTIL, "failed to create clk_lvl_control"); - goto err; - } - - CAM_DBG(CAM_UTIL, "clk lvl debugfs for %s successfully created", - soc_info->dev_name); - - return 0; - -err: - CAM_ERR(CAM_UTIL, "Error in creating Debugfs Entry: %s", - soc_info->dev_name); - debugfs_remove_recursive(soc_info->dentry); - soc_info->dentry = NULL; - return -ENOMEM; +end: + return rc; } /** @@ -243,7 +232,6 @@ static void cam_soc_util_remove_clk_lvl_debugfs( struct cam_hw_soc_info *soc_info) { debugfs_remove_recursive(soc_info->dentry); - soc_info->dentry = NULL; } int cam_soc_util_get_level_from_string(const char *string, From f3435b0efda654ce13dc9fa112efa209426aa8f7 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 15 Jun 2020 16:59:19 -0700 Subject: [PATCH 406/790] msm: camera: ife: Improve IFE logs for better debugging Add HW index in Release, Acquire, Flush and confiqure IFE Logs to Improve the debugging. CRs-Fixed: 2709537 Change-Id: Ia540f1498d889f1e744e6ab20e07d17e27b07731 Signed-off-by: Jigar Agrawal --- drivers/cam_isp/cam_isp_context.c | 27 ++++++++++--------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 24 ++++++++++++----- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 5 ++-- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d9abaff11f82..be8cf4d9d32a 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -28,7 +28,7 @@ static struct cam_isp_ctx_debug isp_ctx_debug; div_u64_rem(atomic64_add_return(1, head),\ max_entries, (ret)) -static int cam_isp_context_dump_active_request(void *data, unsigned long iova, +static int cam_isp_context_dump_requests(void *data, unsigned long iova, uint32_t buf_info); static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, @@ -3010,8 +3010,8 @@ static int __cam_isp_ctx_flush_req_in_top_state( ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; spin_unlock_bh(&ctx->lock); - CAM_INFO(CAM_ISP, "Last request id to flush is %lld", - flush_req->req_id); + CAM_INFO(CAM_ISP, "Last request id to flush is %lld, ctx_id:%d", + flush_req->req_id, ctx->ctx_id); ctx->last_flush_req = flush_req->req_id; memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); @@ -4583,7 +4583,8 @@ static int __cam_isp_ctx_config_dev_in_flushed(struct cam_context *ctx, "Failed to re-start HW after flush rc: %d", rc); else CAM_INFO(CAM_ISP, - "Received init after flush. Re-start HW complete."); + "Received init after flush. Re-start HW complete in ctx:%d", + ctx->ctx_id); end: CAM_DBG(CAM_ISP, "next state %d sub_state:%d", ctx->state, @@ -5152,7 +5153,7 @@ static struct cam_ctx_ops .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, - .pagefault_ops = cam_isp_context_dump_active_request, + .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, }, /* Ready */ @@ -5169,7 +5170,7 @@ static struct cam_ctx_ops .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = NULL, - .pagefault_ops = cam_isp_context_dump_active_request, + .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, }, /* Flushed */ @@ -5185,7 +5186,7 @@ static struct cam_ctx_ops .process_evt = __cam_isp_ctx_process_evt, }, .irq_ops = NULL, - .pagefault_ops = cam_isp_context_dump_active_request, + .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, }, /* Activated */ @@ -5204,13 +5205,13 @@ static struct cam_ctx_ops .dump_req = __cam_isp_ctx_dump_in_top_state, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, - .pagefault_ops = cam_isp_context_dump_active_request, + .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, }, }; -static int cam_isp_context_dump_active_request(void *data, unsigned long iova, +static int cam_isp_context_dump_requests(void *data, unsigned long iova, uint32_t buf_info) { @@ -5239,7 +5240,8 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, req_isp = (struct cam_isp_ctx_req *) req->req_priv; hw_update_data = &req_isp->hw_update_data; pf_dbg_entry = &(req->pf_data); - CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + CAM_INFO(CAM_ISP, "Active List: req_id : %lld ", + req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, iova, buf_info, &mem_found); @@ -5259,7 +5261,7 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, req_isp = (struct cam_isp_ctx_req *) req->req_priv; hw_update_data = &req_isp->hw_update_data; pf_dbg_entry = &(req->pf_data); - CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + CAM_INFO(CAM_ISP, "Wait List: req_id : %lld ", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, iova, buf_info, &mem_found); @@ -5289,7 +5291,8 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, req_isp = (struct cam_isp_ctx_req *) req->req_priv; hw_update_data = &req_isp->hw_update_data; pf_dbg_entry = &(req->pf_data); - CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + CAM_INFO(CAM_ISP, "Pending List: req_id : %lld ", + req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, iova, buf_info, &mem_found); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 2a7218f0fa34..1a7767e73ab9 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -402,11 +402,13 @@ static int cam_ife_hw_mgr_start_hw_res( isp_hw_res->hw_res[i], sizeof(struct cam_isp_resource_node)); if (rc) { - CAM_ERR(CAM_ISP, "Can not start HW resources"); + CAM_ERR(CAM_ISP, + "Can not start HW:%d resources", + hw_intf->hw_idx); goto err; - } - CAM_DBG(CAM_ISP, "Start HW %d Res %d", hw_intf->hw_idx, - isp_hw_res->hw_res[i]->res_id); + } else + CAM_INFO(CAM_ISP, "Started HW:%d", + hw_intf->hw_idx); } else { CAM_ERR(CAM_ISP, "function null"); goto err; @@ -436,10 +438,13 @@ static void cam_ife_hw_mgr_stop_hw_res( CAM_ISP_RESOURCE_STATE_STREAMING) continue; - if (hw_intf->hw_ops.stop) + if (hw_intf->hw_ops.stop) { hw_intf->hw_ops.stop(hw_intf->hw_priv, isp_hw_res->hw_res[i], sizeof(struct cam_isp_resource_node)); + + CAM_INFO(CAM_ISP, "Stopped Hw:%d", hw_intf->hw_idx); + } else CAM_ERR(CAM_ISP, "stop null"); if (hw_intf->hw_ops.process_cmd && @@ -645,8 +650,13 @@ static int cam_ife_hw_mgr_free_hw_res( sizeof(struct cam_isp_resource_node)); if (rc) CAM_ERR(CAM_ISP, - "Release hw resource id %d failed", - isp_hw_res->res_id); + "Release HW:%d resource id %d failed", + hw_intf->hw_idx, isp_hw_res->res_id); + else + CAM_INFO(CAM_ISP, + "Released HW:%d resource id %d", + hw_intf->hw_idx, isp_hw_res->res_id); + isp_hw_res->hw_res[i] = NULL; } else CAM_ERR(CAM_ISP, "Release null"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 41decd3ffec8..c123ffbd8d18 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3928,8 +3928,9 @@ static int cam_ife_csid_sof_irq_debug( csid_hw->sof_irq_triggered = false; } - CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s", - (sof_irq_enable == true) ? "enabled" : "disabled"); + CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s, CSID HW:%d", + (sof_irq_enable) ? "enabled" : "disabled", + csid_hw->hw_intf->hw_idx); return 0; } From 006e454f569dd58cdb0a9f4145cb0f6bb9133710 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Wed, 1 Jul 2020 15:35:04 +0800 Subject: [PATCH 407/790] msm: camera: isp: Only RDI path can access RDI resource Only RDI path can access RDI resource. CRs-Fixed: 2721399 Change-Id: Iad15b72a12cf825f150605f110bee04880a65852 Signed-off-by: Depeng Shao --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 41decd3ffec8..26c077ff7baf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3398,7 +3398,8 @@ int cam_ife_csid_release(void *hw_priv, csid_hw->ipp_path_config.measure_enabled = 0; else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) csid_hw->ppp_path_config.measure_enabled = 0; - else + else if (res->res_id >= CAM_IFE_PIX_PATH_RES_RDI_0 && + res->res_id <= CAM_IFE_PIX_PATH_RES_RDI_3) csid_hw->rdi_path_config[res->res_id].measure_enabled = 0; break; From cb24ba9b7972d6b7105a43bb489b0edd3c0847a5 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 1 Jul 2020 12:38:18 -0700 Subject: [PATCH 408/790] msm: camera: common: Return appropriate error code for cancelled requests If a request is submitted post flush and the request ID of that request is <= last flush req ID return an appropriate error code to indicate the same. CRs-Fixed: 2720555 Change-Id: Ic26c4fc5f0ba490ed277b3bb301cc02d1fa027d6 Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_core/cam_context_utils.c | 2 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 5b09d1183d7a..28d7827391db 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -396,7 +396,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, CAM_ERR(CAM_CORE, "request %lld has been flushed, reject packet", packet->header.request_id); - rc = -EINVAL; + rc = -EBADR; goto free_req; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 9b2f458fa44f..665f67816a21 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2829,8 +2829,17 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) /* Validate if req id is present in input queue */ idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id); if (idx < 0) { - CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id); - rc = -ENOENT; + if (((uint32_t)add_req->req_id) <= (link->last_flush_id)) { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q; it has been flushed [last_flush_req %u]", + add_req->req_id, link->last_flush_id); + rc = -EBADR; + } else { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q", + add_req->req_id); + rc = -ENOENT; + } goto end; } From 891c47b17e3fd2d734e4fb50ff68b18a4fc7c0a4 Mon Sep 17 00:00:00 2001 From: Haibin Liu Date: Fri, 27 Sep 2019 20:05:04 +0800 Subject: [PATCH 409/790] msm: camera: memmgr: reduce mutex lock duration Allow concurrent calls to unmap buffer by reducing the mutex lock duration, and allow same fd for mapping user iova, use book keeping for user smmu. CRs-Fixed: 2559879 Change-Id: Ic3c92d4fa0ca7d1c29e621172e0b058420e1501d Signed-off-by: Haibin Liu --- drivers/cam_req_mgr/cam_mem_mgr.c | 22 ++++++++++++++++---- drivers/cam_smmu/cam_smmu_api.c | 34 +++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index ca6d671f46f2..5efd66b9eb82 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -254,8 +254,11 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) return -ENOENT; - if (!tbl.bufq[idx].active) + if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); return -EAGAIN; + } mutex_lock(&tbl.bufq[idx].q_lock); if (buf_handle != tbl.bufq[idx].buf_handle) { @@ -310,8 +313,11 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) return -EINVAL; - if (!tbl.bufq[idx].active) + if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); return -EPERM; + } if (buf_handle != tbl.bufq[idx].buf_handle) return -EINVAL; @@ -353,6 +359,8 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) mutex_lock(&tbl.bufq[idx].q_lock); if (!tbl.bufq[idx].active) { + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); rc = -EINVAL; goto end; } @@ -1061,6 +1069,13 @@ static int cam_mem_util_unmap(int32_t idx, return 0; } + /* Deactivate the buffer queue to prevent multiple unmap */ + mutex_lock(&tbl.bufq[idx].q_lock); + tbl.bufq[idx].active = false; + tbl.bufq[idx].vaddr = 0; + mutex_unlock(&tbl.bufq[idx].q_lock); + mutex_unlock(&tbl.m_lock); + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS) { if (tbl.bufq[idx].dma_buf && tbl.bufq[idx].kmdvaddr) { rc = cam_mem_util_unmap_cpu_va(tbl.bufq[idx].dma_buf, @@ -1091,10 +1106,10 @@ static int cam_mem_util_unmap(int32_t idx, tbl.bufq[idx].dma_buf = NULL; } + mutex_lock(&tbl.m_lock); mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].flags = 0; tbl.bufq[idx].buf_handle = -1; - tbl.bufq[idx].vaddr = 0; memset(tbl.bufq[idx].hdls, 0, sizeof(int32_t) * CAM_MEM_MMU_MAX_HANDLE); @@ -1113,7 +1128,6 @@ static int cam_mem_util_unmap(int32_t idx, tbl.bufq[idx].is_internal = false; tbl.bufq[idx].len = 0; tbl.bufq[idx].num_hdl = 0; - tbl.bufq[idx].active = false; memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64)); mutex_unlock(&tbl.bufq[idx].q_lock); mutex_destroy(&tbl.bufq[idx].q_lock); diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index b87972840021..6ff1775c3f63 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -2181,6 +2181,26 @@ static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx, return CAM_SMMU_BUFF_NOT_EXIST; } +static enum cam_smmu_buf_state cam_smmu_user_reuse_fd_in_list(int idx, + int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr, + struct timespec64 **ts_mapping) +{ + struct cam_dma_buff_info *mapping; + + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { + if (mapping->ion_fd == ion_fd) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + *ts_mapping = &mapping->ts; + mapping->ref_count++; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + static enum cam_smmu_buf_state cam_smmu_check_dma_buf_in_list(int idx, struct dma_buf *buf, dma_addr_t *paddr_ptr, size_t *len_ptr) { @@ -2944,7 +2964,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, goto get_addr_end; } - buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, + buf_state = cam_smmu_user_reuse_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr, &ts); if (buf_state == CAM_SMMU_BUFF_EXIST) { uint64_t ms = 0, tmp = 0, hrs = 0, min = 0, sec = 0; @@ -2961,7 +2981,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap, ion_fd, hrs, min, sec, ms, iommu_cb_set.cb_info[idx].name[0], idx, handle, *len_ptr); - rc = -EALREADY; + rc = 0; goto get_addr_end; } @@ -3222,6 +3242,16 @@ int cam_smmu_unmap_user_iova(int handle, goto unmap_end; } + mapping_info->ref_count--; + if (mapping_info->ref_count > 0) { + CAM_DBG(CAM_SMMU, + "idx: %d fd = %d ref_count: %d", + idx, ion_fd, mapping_info->ref_count); + rc = 0; + goto unmap_end; + } + mapping_info->ref_count = 0; + /* Unmapping one buffer from device */ CAM_DBG(CAM_SMMU, "SMMU: removing buffer idx = %d", idx); rc = cam_smmu_unmap_buf_and_remove_from_list(mapping_info, idx); From cd675940d79642695e9fb97712a0bb76187a715b Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 22 Jun 2020 19:03:18 -0700 Subject: [PATCH 410/790] msm: camera: csiphy: Add support for CSIPHY 2.1.0 Add support for new CSIPHY version 2.1.0. Add hw register file for CSIPHY 2.1.0. CRs-Fixed: 2724449 Change-Id: Id3f21b4f60e807ca6fef762f0c6da193ae78e099 Signed-off-by: Jigar Agrawal --- .../cam_csiphy/cam_csiphy_soc.c | 20 + .../cam_csiphy/cam_csiphy_soc.h | 1 + .../include/cam_csiphy_2_1_0_hwreg.h | 442 ++++++++++++++++++ 3 files changed, 463 insertions(+) create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index f4eab97db4a1..9e15249774da 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -12,6 +12,7 @@ #include "include/cam_csiphy_1_2_2_hwreg.h" #include "include/cam_csiphy_1_2_3_hwreg.h" #include "include/cam_csiphy_2_0_hwreg.h" +#include "include/cam_csiphy_2_1_0_hwreg.h" #define CSIPHY_DIVISOR_16 16 #define CSIPHY_DIVISOR_32 32 @@ -456,6 +457,25 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->is_divisor_32_comp = false; csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v2.1.0")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_1_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v2_1_0_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v2_1_0_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_2_1_0; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_2_1_0; + csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_2_1_0; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v2_1_0; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->hw_version = CSIPHY_VERSION_V210; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_2_1_0; } else { CAM_ERR(CAM_CSIPHY, "invalid hw version : 0x%x", csiphy_dev->hw_version); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 02176211b676..62e50349c892 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -31,6 +31,7 @@ #define CSIPHY_VERSION_V124 0x124 #define CSIPHY_VERSION_V20 0x20 #define CSIPHY_VERSION_V201 0x201 +#define CSIPHY_VERSION_V210 0x210 /** * @csiphy_dev: CSIPhy device structure diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h new file mode 100644 index 000000000000..cdeffc9bf754 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h @@ -0,0 +1,442 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_2_1_0_HWREG_H_ +#define _CAM_CSIPHY_2_1_0_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v2_1_0 = { + .mipi_csiphy_interrupt_status0_addr = 0x10B0, + .mipi_csiphy_interrupt_clear0_addr = 0x1058, + .mipi_csiphy_glbl_irq_cmd_addr = 0x1028, + .csiphy_common_array_size = 6, + .csiphy_reset_array_size = 5, + .csiphy_2ph_config_array_size = 19, + .csiphy_3ph_config_array_size = 28, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_2_1_0[] = { + {0x1014, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x1018, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x101C, 0x5a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x1000, 0x0E, 0x00, CSIPHY_3PH_REGS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_2_1_0[] = { + {0x1014, 0x00, 0x00, CSIPHY_LANE_ENABLE}, + {0x1018, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x101C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_irq_reg_2_1_0[] = { + {0x102c, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1030, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1034, 0xfb, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1038, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x103c, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1040, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1044, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1048, 0xef, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x104c, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1050, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1054, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_2ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0094, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0090, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0098, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0EA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E90, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E94, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0E30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E00, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0490, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0498, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x08A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0890, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0898, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0828, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0800, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x080C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0838, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x082C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0814, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0804, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0808, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0CA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C28, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0C00, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C0C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0C38, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v2_1_0_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0094, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0090, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0098, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0EA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E90, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E94, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0E30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E00, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0E2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0490, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0498, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x08A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0890, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0898, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0828, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0800, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x080C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0838, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0828, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x082C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0814, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0804, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0808, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0CA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x0f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0x07, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C28, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t csiphy_3ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0294, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02F4, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02F8, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02FC, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02F0, 0xEF, 0x03, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0294, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0278, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0268, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x026C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0240, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02E4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02E8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02EC, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0218, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0224, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0244, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0310, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0694, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06F4, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06F8, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06FC, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06F0, 0xEF, 0x03, CSIPHY_DEFAULT_PARAMS}, + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0694, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0678, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0668, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x066C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0640, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06E4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06E8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06EC, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0618, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0644, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AF4, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AF8, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AFC, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AF0, 0xEF, 0x03, CSIPHY_DEFAULT_PARAMS}, + {0x0B24, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A78, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A68, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A6C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A14, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A60, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A40, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AE4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AE8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AEC, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A18, 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A1C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A20, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A24, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A28, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A2C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A64, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A44, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A5C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x1000, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct data_rate_settings_t data_rate_delta_table_2_1_0 = { + .num_data_rate_settings = 3, + .data_rate_settings = { + { + /* (2.5 * 10**3 * 2.28) rounded value*/ + .bandwidth = 5700000000, + .data_rate_reg_array_size = 9, + .csiphy_data_rate_regs = { + {0x0290, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0690, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0208, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x060C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0608, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0A0C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0A08, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + + } + }, + { + /* (4.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 10260000000, + .data_rate_reg_array_size = 9, + .csiphy_data_rate_regs = { + {0x0290, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0690, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0208, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x060C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0608, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0A0C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0A08, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + }, + }, + { + /* (6.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 14820000000, + .data_rate_reg_array_size = 9, + .csiphy_data_rate_regs = { + {0x0290, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0690, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x020C, 0x07, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0208, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x060C, 0x07, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0608, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0A0C, 0x07, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0A08, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + }, + } + } +}; + +#endif /* _CAM_CSIPHY_2_1_0_HWREG_H_ */ From 402c0a500b9f727d102fe3571d043840b504e4cf Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 8 Jul 2020 16:06:40 -0700 Subject: [PATCH 411/790] msm: camera: req_mgr: Remove unwanted v4l2 operation CCI hardware is no longer register as device node with v4l2 layer. At time of notify message, there is missing check to read subdev name, which cause the null pointer issue. This change removes the sudbev node reading operation with devnode pointer as it is not being use anywhere in functionality. CRs-Fixed: 2702760, 2727771 Change-Id: Id362bd2edf4eea35f05115ae3a5b6c1d761bb437 Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index c7f21854878f..6f4c0e6baa08 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -649,7 +649,6 @@ void cam_subdev_notify_message(u32 subdev_type, struct cam_subdev *csd = NULL; list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { - sd->entity.name = video_device_node_name(sd->devnode); if (sd->entity.function == subdev_type) { csd = container_of(sd, struct cam_subdev, sd); if (csd->msg_cb != NULL) From 3adf5ea68e610a1c1f37f428401d6da3d8ddac15 Mon Sep 17 00:00:00 2001 From: Vishalsingh Hajeri Date: Fri, 19 Jun 2020 11:59:21 -0700 Subject: [PATCH 412/790] msm: camera: isp: Add handle function for RUP in bubble When we wait on Bufdone for Bubble Request in Bubble state, We don't know whether the CDM is hung or Bufdone is delayed. This change prints more information for bubble request to ascertain CDM is in good state. CRs-Fixed: 2705745 Change-Id: I98215904b5665281808e775c97c6747a38eb1081 Signed-off-by: Vishalsingh Hajeri --- drivers/cam_isp/cam_isp_context.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9d0db9845666..5d2c46aa6ab5 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3463,6 +3463,21 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( return 0; } + +static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_state( + struct cam_isp_context *ctx_isp, void *evt_data) +{ + struct cam_ctx_request *req = NULL; + struct cam_context *ctx = ctx_isp->base; + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + + CAM_INFO(CAM_ISP, "Received RUP for Bubble Request", req->request_id); + + return 0; +} + static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( struct cam_isp_context *ctx_isp, void *evt_data) { @@ -3586,7 +3601,7 @@ static struct cam_isp_ctx_irq_ops .irq_ops = { __cam_isp_ctx_handle_error, __cam_isp_ctx_rdi_only_sof_in_bubble_state, - NULL, + __cam_isp_ctx_rdi_only_reg_upd_in_bubble_state, NULL, NULL, __cam_isp_ctx_buf_done_in_bubble, From dcb4ee83be5d38950c5bf428963547944b0989a8 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Wed, 10 Jun 2020 16:11:17 -0700 Subject: [PATCH 413/790] msm: camera: icp: Poll HFI init response using readl variant The extra read seems to have been added due to an incorrect use of readw_poll_timeout. The readw_poll_timeout was effectively acting as a long delay before attempting the second read. Replacing the readw with a readl results in correctly polling the register. We can safely remove the extra read and simplify the polling logic. CRs-Fixed: 2722486 Change-Id: I07269d601e64059ce7654563c379b5dc956895b3 Signed-off-by: Fernando Pacheco --- drivers/cam_icp/hfi.c | 75 +++++++++---------------------------------- 1 file changed, 15 insertions(+), 60 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index b015d19d1e55..b62cdf1fa9f7 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -31,7 +31,8 @@ #define HFI_VERSION_INFO_STEP_BMSK 0xFF #define HFI_VERSION_INFO_STEP_SHFT 0 -#define HFI_MAX_POLL_TRY 5 +#define HFI_POLL_DELAY_US 100 +#define HFI_POLL_TIMEOUT_US 10000 #define HFI_MAX_PC_POLL_TRY 150 #define HFI_POLL_TRY_SLEEP 1 @@ -588,7 +589,6 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, int rc = 0; uint32_t data; uint32_t fw_version, status = 0; - uint32_t retry_cnt = 0; cam_hfi_enable_cpu(icp_base); g_hfi->csr_base = icp_base; @@ -611,33 +611,12 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, icp_base + HFI_REG_A5_CSR_A5_CONTROL); } - while (retry_cnt < HFI_MAX_POLL_TRY) { - readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), - status, (status == ICP_INIT_RESP_SUCCESS), 100, 10000); - - CAM_DBG(CAM_HFI, "1: status = %u", status); - status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); - CAM_DBG(CAM_HFI, "2: status = %u", status); - if (status == ICP_INIT_RESP_SUCCESS) - break; - - if (status == ICP_INIT_RESP_FAILED) { - CAM_ERR(CAM_HFI, "ICP Init Failed. status = %u", - status); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); - return -EINVAL; - } - retry_cnt++; - } - - if ((retry_cnt == HFI_MAX_POLL_TRY) && - (status == ICP_INIT_RESP_RESET)) { - CAM_ERR(CAM_HFI, "Reached Max retries. status = %u", - status); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); - return -EINVAL; + if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, + status, status == ICP_INIT_RESP_SUCCESS, + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { + CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", + status); + return -ETIMEDOUT; } cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), @@ -689,7 +668,6 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; uint32_t hw_version, fw_version, status = 0; - uint32_t retry_cnt = 0; struct sfr_buf *sfr_buffer; mutex_lock(&hfi_cmd_q_mutex); @@ -877,39 +855,16 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); - hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); - - while (retry_cnt < HFI_MAX_POLL_TRY) { - readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), - status, (status == ICP_INIT_RESP_SUCCESS), 100, 10000); - - CAM_DBG(CAM_HFI, "1: status = %u rc = %d", status, rc); - status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); - CAM_DBG(CAM_HFI, "2: status = %u rc = %d", status, rc); - if (status == ICP_INIT_RESP_SUCCESS) - break; - - if (status == ICP_INIT_RESP_FAILED) { - CAM_ERR(CAM_HFI, "ICP Init Failed. status = %u", - status); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); - goto regions_fail; - } - retry_cnt++; - } - - if ((retry_cnt == HFI_MAX_POLL_TRY) && - (status == ICP_INIT_RESP_RESET)) { - CAM_ERR(CAM_HFI, "Reached Max retries. status = %u", - status); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_ERR(CAM_HFI, - "hw version : : [%x], fw version : [%x]", - hw_version, fw_version); + if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, + status, status == ICP_INIT_RESP_SUCCESS, + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { + CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", + status); + rc = -ETIMEDOUT; goto regions_fail; } + hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]", hw_version, fw_version); From 41ffa1f4f93568ca32d22d36d73cc3647f8bcdd2 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 13 Jul 2020 21:57:26 +0800 Subject: [PATCH 414/790] msm: camera: cdm: Fix out of bounds issue The dt match table needs end up with null. CRs-Fixed: 2730795 Change-Id: I75bdf20d74d9a83d9a0de28a2ad4d95412a51f0c Signed-off-by: Depeng Shao --- drivers/cam_cdm/cam_cdm_hw_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index d4e4c50a5b6c..fd903f336414 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -73,6 +73,7 @@ static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { .compatible = CAM_HW_CDM_IFE_NAME_2_1, .data = &cam_cdm_2_1_reg_offset, }, + {} }; static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) From c782e8c3ab3178419a9c8a23e343021e2385b5e0 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 21 May 2020 10:55:37 +0800 Subject: [PATCH 415/790] msm: camera: reqmgr: Add notify frame skip interface This change adds support to notify frame skip when CRM not ready to apply a normal setting. Sensor and custom device also want to update the HW settings in some conditions even if a frame is skipped. CRs-Fixed: 2691642 Change-Id: Ibd2b22655d0f6b6c90663df75a0f5fad8565e918 Signed-off-by: Depeng Shao --- drivers/cam_core/cam_context.c | 13 +- drivers/cam_core/cam_context.h | 14 +- drivers/cam_core/cam_node.c | 9 +- drivers/cam_cust/cam_custom_context.c | 11 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 173 +++++++++++------- drivers/cam_req_mgr/cam_req_mgr_core.h | 18 +- drivers/cam_req_mgr/cam_req_mgr_interface.h | 49 +++-- .../cam_sensor/cam_sensor_core.c | 130 +++++++++++-- .../cam_sensor/cam_sensor_core.h | 9 +- .../cam_sensor/cam_sensor_dev.c | 35 +++- .../cam_sensor_utils/cam_sensor_cmn_header.h | 2 + drivers/cam_utils/cam_trace.h | 19 +- 12 files changed, 335 insertions(+), 147 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index d3ca4f2e1aeb..4b3078ad79e5 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -182,7 +182,7 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } -int cam_context_handle_crm_apply_default_req( +int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -199,11 +199,12 @@ int cam_context_handle_crm_apply_default_req( } mutex_lock(&ctx->ctx_mutex); - if (ctx->state_machine[ctx->state].crm_ops.apply_default) - rc = ctx->state_machine[ctx->state].crm_ops.apply_default(ctx, - apply); + if (ctx->state_machine[ctx->state].crm_ops.notify_frame_skip) + rc = ctx->state_machine[ctx->state].crm_ops.notify_frame_skip( + ctx, apply); else - CAM_DBG(CAM_CORE, "No crm apply_default in dev %d, state %d", + CAM_DBG(CAM_CORE, + "No crm notify_frame_skip in dev %d, state %d", ctx->dev_hdl, ctx->state); mutex_unlock(&ctx->ctx_mutex); diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index e2fd6c2cce39..1f2f8154ae99 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -121,7 +121,7 @@ struct cam_ctx_ioctl_ops { * @link: Link the context * @unlink: Unlink the context * @apply_req: Apply setting for the context - * @apply_default: Apply default settings for the context + * @notify_frame_skip: Notify device that a frame is skipped * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request @@ -136,7 +136,7 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_core_dev_link_setup *unlink); int (*apply_req)(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); - int (*apply_default)(struct cam_context *ctx, + int (*notify_frame_skip)(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); int (*flush_req)(struct cam_context *ctx, struct cam_req_mgr_flush_request *flush); @@ -306,15 +306,15 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); /** - * cam_context_handle_crm_apply_default_req() + * cam_context_handle_crm_notify_frame_skip() * - * @brief: Handle apply default request command + * @brief: Handle notify frame skip command * * @ctx: Object pointer for cam_context - * @apply: Apply default request command payload + * @apply: Notify frame skip command payload * */ -int cam_context_handle_crm_apply_default_req( +int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); /** diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 23a440a3e07f..6b24bde92a8c 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -570,7 +570,7 @@ static int __cam_node_crm_apply_req(struct cam_req_mgr_apply_request *apply) return cam_context_handle_crm_apply_req(ctx, apply); } -static int __cam_node_crm_apply_default_req( +static int __cam_node_crm_notify_frame_skip( struct cam_req_mgr_apply_request *apply) { struct cam_context *ctx = NULL; @@ -587,7 +587,7 @@ static int __cam_node_crm_apply_default_req( trace_cam_apply_req("Node", apply->request_id); - return cam_context_handle_crm_apply_default_req(ctx, apply); + return cam_context_handle_crm_notify_frame_skip(ctx, apply); } static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) @@ -703,7 +703,8 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.flush_req = __cam_node_crm_flush_req; node->crm_node_intf.process_evt = __cam_node_crm_process_evt; node->crm_node_intf.dump_req = __cam_node_crm_dump_req; - node->crm_node_intf.apply_default = __cam_node_crm_apply_default_req; + node->crm_node_intf.notify_frame_skip = + __cam_node_crm_notify_frame_skip; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index de9777a8b14b..f0b782c0971d 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -219,7 +219,7 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_custom_ctx_apply_req_in_activated, - .apply_default = + .notify_frame_skip = __cam_custom_ctx_apply_default_settings, }, .irq_ops = NULL, @@ -229,7 +229,7 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_custom_ctx_apply_req_in_activated, - .apply_default = + .notify_frame_skip = __cam_custom_ctx_apply_default_settings, }, .irq_ops = NULL, @@ -414,7 +414,6 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; - dev_info->enable_apply_default = true; return 0; } @@ -1452,8 +1451,8 @@ static int __cam_custom_ctx_apply_default_req( ctx_ops = &custom_ctx->substate_machine[ custom_ctx->substate_activated]; - if (ctx_ops->crm_ops.apply_default) { - rc = ctx_ops->crm_ops.apply_default(ctx, apply); + if (ctx_ops->crm_ops.notify_frame_skip) { + rc = ctx_ops->crm_ops.notify_frame_skip(ctx, apply); } else { CAM_WARN_RATE_LIMIT(CAM_CUSTOM, "No handle function in activated substate %d", @@ -1547,7 +1546,7 @@ static struct cam_ctx_ops .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, .apply_req = __cam_custom_ctx_apply_req, - .apply_default = + .notify_frame_skip = __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index ae9a90caed04..57ef31ee552b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -21,6 +21,8 @@ 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) { + uint32_t pd = 0; + link->link_hdl = 0; link->num_devs = 0; link->max_delay = CAM_PIPELINE_DELAY_0; @@ -49,9 +51,13 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->initial_skip = true; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; - link->enable_apply_default = false; link->skip_init_frame = false; atomic_set(&link->eof_event_cnt, 0); + + for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { + link->req.apply_data[pd].req_id = -1; + link->req.prev_apply_data[pd].req_id = -1; + } } void cam_req_mgr_handle_core_shutdown(void) @@ -212,32 +218,77 @@ static void __cam_req_mgr_find_dev_name( } /** - * __cam_req_mgr_apply_default() + * __cam_req_mgr_notify_frame_skip() * - * @brief : Apply default settings to all devices + * @brief : Notify all devices of frame skipping * @link : link on which we are applying these settings * */ -static void __cam_req_mgr_apply_default( - struct cam_req_mgr_core_link *link) +static int __cam_req_mgr_notify_frame_skip( + struct cam_req_mgr_core_link *link, + uint32_t trigger) { - int i; - struct cam_req_mgr_apply_request apply_req; + int rc = 0, i, pd, idx; + struct cam_req_mgr_apply_request frame_skip; + struct cam_req_mgr_apply *apply_data = NULL; struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_tbl_slot *slot = NULL; - if (!link->enable_apply_default) - return; + apply_data = link->req.prev_apply_data; for (i = 0; i < link->num_devs; i++) { dev = &link->l_dev[i]; - apply_req.request_id = 0; - apply_req.dev_hdl = dev->dev_hdl; - apply_req.link_hdl = link->link_hdl; - apply_req.trigger_point = 0; - apply_req.report_if_bubble = 0; - if (dev->ops && dev->ops->apply_default) - dev->ops->apply_default(&apply_req); + if (!dev) + continue; + + pd = dev->dev_info.p_delay; + if (pd >= CAM_PIPELINE_DELAY_MAX) { + CAM_WARN(CAM_CRM, "pd %d greater than max", + pd); + continue; + } + + idx = apply_data[pd].idx; + slot = &dev->pd_tbl->slot[idx]; + + if ((slot->ops.dev_hdl == dev->dev_hdl) && + (slot->ops.is_applied)) { + slot->ops.is_applied = false; + continue; + } + + /* + * If apply_at_eof is enabled do not apply at SOF + * e.x. Flash device + */ + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (dev->dev_hdl == slot->ops.dev_hdl) && + (slot->ops.apply_at_eof)) + continue; + + /* + * If apply_at_eof is not enabled ignore EOF + */ + if ((trigger == CAM_TRIGGER_POINT_EOF) && + (dev->dev_hdl == slot->ops.dev_hdl) && + (!slot->ops.apply_at_eof)) + continue; + + frame_skip.dev_hdl = dev->dev_hdl; + frame_skip.link_hdl = link->link_hdl; + frame_skip.request_id = + apply_data[pd].req_id; + frame_skip.trigger_point = trigger; + frame_skip.report_if_bubble = 0; + + CAM_DBG(CAM_REQ, + "Notify_frame_skip: pd %d req_id %lld", + link->link_hdl, pd, apply_data[pd].req_id); + if ((dev->ops) && (dev->ops->notify_frame_skip)) + dev->ops->notify_frame_skip(&frame_skip); } + + return rc; } /** @@ -716,6 +767,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_apply_request apply_req; struct cam_req_mgr_link_evt_data evt_data; struct cam_req_mgr_tbl_slot *slot = NULL; + struct cam_req_mgr_apply *apply_data = NULL; apply_req.link_hdl = link->link_hdl; apply_req.report_if_bubble = 0; @@ -725,6 +777,8 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.re_apply = true; } + apply_data = link->req.apply_data; + /* * This For loop is to address the special operation requested * by device @@ -740,7 +794,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, continue; } - idx = link->req.apply_data[pd].idx; + idx = apply_data[pd].idx; slot = &dev->pd_tbl->slot[idx]; if (slot->ops.dev_hdl < 0) { @@ -772,20 +826,21 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if ((trigger == CAM_TRIGGER_POINT_EOF) && (!slot->ops.apply_at_eof)) { CAM_DBG(CAM_CRM, "NO EOF DATA FOR REQ: %llu", - link->req.apply_data[pd].req_id); + apply_data[pd].req_id); break; } apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = - link->req.apply_data[pd].req_id; + apply_data[pd].req_id; apply_req.trigger_point = trigger; if ((dev->ops) && (dev->ops->apply_req) && (!slot->ops.is_applied)) { rc = dev->ops->apply_req(&apply_req); if (rc) { *failed_dev = dev; - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, + trigger); return rc; } } @@ -801,7 +856,8 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, CAM_DBG(CAM_REQ, "SEND: link_hdl: %x pd: %d req_id %lld", link->link_hdl, pd, apply_req.request_id); - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, + trigger); return -EAGAIN; } else if ((trigger == CAM_TRIGGER_POINT_EOF) && (slot->ops.apply_at_eof)) { @@ -810,7 +866,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, atomic_dec(&link->eof_event_cnt); CAM_DBG(CAM_REQ, "Req_id: %llu eof_event_cnt : %d", - link->req.apply_data[pd].req_id, + apply_data[pd].req_id, link->eof_event_cnt); return 0; } @@ -830,27 +886,27 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (!(dev->dev_info.trigger & trigger)) continue; - if (link->req.apply_data[pd].skip_idx || - (link->req.apply_data[pd].req_id < 0)) { + if (apply_data[pd].skip_idx || + (apply_data[pd].req_id < 0)) { CAM_DBG(CAM_CRM, "dev %s skip %d req_id %lld", dev->dev_info.name, - link->req.apply_data[pd].skip_idx, - link->req.apply_data[pd].req_id); + apply_data[pd].skip_idx, + apply_data[pd].req_id); apply_req.dev_hdl = dev->dev_hdl; - apply_req.request_id = 0; + apply_req.request_id = + link->req.prev_apply_data[pd].req_id; apply_req.trigger_point = 0; apply_req.report_if_bubble = 0; - if ((link->enable_apply_default) && - (dev->ops) && (dev->ops->apply_default)) - dev->ops->apply_default(&apply_req); + if ((dev->ops) && (dev->ops->notify_frame_skip)) + dev->ops->notify_frame_skip(&apply_req); continue; } apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = - link->req.apply_data[pd].req_id; - idx = link->req.apply_data[pd].idx; + apply_data[pd].req_id; + idx = apply_data[pd].idx; slot = &dev->pd_tbl->slot[idx]; apply_req.report_if_bubble = in_q->slot[idx].recover; @@ -880,7 +936,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.trigger_point = trigger; CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd %d req_id %lld", + "SEND: %d link_hdl: %x pd %d req_id %lld", link->link_hdl, pd, apply_req.request_id); if (dev->ops && dev->ops->apply_req) { rc = dev->ops->apply_req(&apply_req); @@ -906,8 +962,13 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (dev->ops && dev->ops->process_evt) dev->ops->process_evt(&evt_data); } - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, trigger); + } else { + memcpy(link->req.prev_apply_data, link->req.apply_data, + CAM_PIPELINE_DELAY_MAX * + sizeof(struct cam_req_mgr_apply)); } + return rc; } @@ -1598,7 +1659,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, rc = -EPERM; } spin_unlock_bh(&link->link_state_spin_lock); - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, trigger); goto error; } } @@ -2197,38 +2258,6 @@ static void __cam_req_mgr_unreserve_link( /* Workqueue context processing section */ -/** - * cam_req_mgr_process_send_req() - * - * @brief: This runs in workque thread context. Call core funcs to send - * apply request id to drivers. - * @priv : link information. - * @data : contains information about frame_id, link etc. - * - * @return: 0 on success. - */ -int cam_req_mgr_process_send_req(void *priv, void *data) -{ - int rc = 0; - struct cam_req_mgr_core_link *link = NULL; - struct cam_req_mgr_send_request *send_req = NULL; - struct cam_req_mgr_req_queue *in_q = NULL; - struct cam_req_mgr_connected_device *dev; - - if (!data || !priv) { - CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); - rc = -EINVAL; - goto end; - } - link = (struct cam_req_mgr_core_link *)priv; - send_req = (struct cam_req_mgr_send_request *)data; - in_q = send_req->in_q; - - rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF, &dev); -end: - return rc; -} - /** * cam_req_mgr_process_flush_req() * @@ -2242,6 +2271,7 @@ end: int cam_req_mgr_process_flush_req(void *priv, void *data) { int rc = 0, i = 0, idx = -1; + uint32_t pd = 0; struct cam_req_mgr_flush_info *flush_info = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_req_queue *in_q = NULL; @@ -2306,6 +2336,12 @@ int cam_req_mgr_process_flush_req(void *priv, void *data) if (device->ops && device->ops->flush_req) rc = device->ops->flush_req(&flush_req); } + + for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { + link->req.apply_data[pd].req_id = -1; + link->req.prev_apply_data[pd].req_id = -1; + } + complete(&link->workq_comp); mutex_unlock(&link->req.lock); @@ -3297,9 +3333,6 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, if (dev->dev_info.p_delay > max_delay) max_delay = dev->dev_info.p_delay; - if (dev->dev_info.enable_apply_default) - link->enable_apply_default = true; - subscribe_event |= (uint32_t)dev->dev_info.trigger; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 6a806f192542..cc135d716dd3 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -281,17 +281,20 @@ struct cam_req_mgr_req_queue { /** * struct cam_req_mgr_req_data - * @in_q : Poiner to Input request queue - * @l_tbl : unique pd request tables. - * @num_tbl : how many unique pd value devices are present - * @apply_data : Holds information about request id for a request - * @lock : mutex lock protecting request data ops. + * @in_q : Poiner to Input request queue + * @l_tbl : unique pd request tables. + * @num_tbl : how many unique pd value devices are present + * @apply_data : Holds information about request id for a request + * @prev_apply_data : Holds information about request id for a previous + * applied request + * @lock : mutex lock protecting request data ops. */ struct cam_req_mgr_req_data { struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_req_tbl *l_tbl; int32_t num_tbl; struct cam_req_mgr_apply apply_data[CAM_PIPELINE_DELAY_MAX]; + struct cam_req_mgr_apply prev_apply_data[CAM_PIPELINE_DELAY_MAX]; struct mutex lock; }; @@ -365,10 +368,6 @@ struct cam_req_mgr_connected_device { * applying the settings * @trigger_cnt : trigger count value per device initiating the trigger * @eof_event_cnt : Atomic variable to track the number of EOF requests - * @enable_apply_default : Link will apply a default settings to devices on - * frames where actual settings are not available. - * This will account for all devices irrespective of - * pipeline delay * @skip_init_frame : skip initial frames crm_wd_timer validation in the * case of long exposure use case */ @@ -404,7 +403,6 @@ struct cam_req_mgr_core_link { bool dual_trigger; uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; atomic_t eof_event_cnt; - bool enable_apply_default; bool skip_init_frame; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index b832f3a46ed3..231cf397f3d8 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -44,17 +44,20 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); /** * @brief: cam req mgr to camera device drivers * - * @cam_req_mgr_get_dev_info: to fetch details about device linked - * @cam_req_mgr_link_setup : to establish link with device for a session - * @cam_req_mgr_apply_req : CRM asks device to apply certain request id - * @cam_req_mgr_flush_req : Flush or cancel request - * cam_req_mgr_process_evt : generic events - * @cam_req_mgr_dump_req : dump request + * @cam_req_mgr_get_dev_info : to fetch details about device linked + * @cam_req_mgr_link_setup : to establish link with device for a session + * @cam_req_mgr_apply_req : CRM asks device to apply certain request id + * @cam_req_mgr_notify_frame_skip: CRM asks device to apply setting for + * frame skip + * @cam_req_mgr_flush_req : Flush or cancel request + * cam_req_mgr_process_evt : generic events + * @cam_req_mgr_dump_req : dump request */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); -typedef int (*cam_req_mgr_apply_default)(struct cam_req_mgr_apply_request *); +typedef int (*cam_req_mgr_notify_frame_skip)( + struct cam_req_mgr_apply_request *); typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); @@ -79,22 +82,22 @@ struct cam_req_mgr_crm_cb { /** * @brief : cam_req_mgr_kmd_ops - func table * - * @get_dev_info : payload to fetch device details - * @link_setup : payload to establish link with device - * @apply_req : payload to apply request id on a device linked - * @apply_default: payload to trigger default apply settings - * @flush_req : payload to flush request - * @process_evt : payload to generic event - * @dump_req : payload to dump request + * @get_dev_info : payload to fetch device details + * @link_setup : payload to establish link with device + * @apply_req : payload to apply request id on a device linked + * @notify_frame_skip: payload to notify frame skip + * @flush_req : payload to flush request + * @process_evt : payload to generic event + * @dump_req : payload to dump request */ struct cam_req_mgr_kmd_ops { - cam_req_mgr_get_dev_info get_dev_info; - cam_req_mgr_link_setup link_setup; - cam_req_mgr_apply_req apply_req; - cam_req_mgr_apply_default apply_default; - cam_req_mgr_flush_req flush_req; - cam_req_mgr_process_evt process_evt; - cam_req_mgr_dump_req dump_req; + cam_req_mgr_get_dev_info get_dev_info; + cam_req_mgr_link_setup link_setup; + cam_req_mgr_apply_req apply_req; + cam_req_mgr_notify_frame_skip notify_frame_skip; + cam_req_mgr_flush_req flush_req; + cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; }; /** @@ -296,9 +299,6 @@ struct cam_req_mgr_notify_stop { * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client * @trigger_on : This device provides trigger - * @enable_apply_default : Device requests CRM to apply default - * settings for devices on a link if actual - * settings for a given frame is not available */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -307,7 +307,6 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; - bool enable_apply_default; }; /** diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 762b0a65e0c2..42f92279f0af 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -78,6 +78,20 @@ static void cam_sensor_release_per_frame_resource( } } } + + if (s_ctrl->i2c_data.frame_skip != NULL) { + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(s_ctrl->i2c_data.frame_skip[i]); + if (i2c_set->is_settings_valid == 1) { + i2c_set->is_settings_valid = -1; + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + } + } + } } static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, @@ -137,7 +151,6 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, CAM_ERR(CAM_SENSOR, "Invalid packet params"); rc = -EINVAL; goto end; - } if ((csl_packet->header.op_code & 0xFFFFFF) != @@ -240,6 +253,22 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, } break; } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE: { + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || + (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { + CAM_WARN(CAM_SENSOR, + "Rxed Update packets without linking"); + goto end; + } + + i2c_reg_settings = + &i2c_data->frame_skip[csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY]; + CAM_DBG(CAM_SENSOR, "Received not ready packet: %lld req: %lld", + csl_packet->header.request_id % MAX_PER_FRAME_ARRAY, + csl_packet->header.request_id); + break; + } case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: { if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { @@ -275,6 +304,12 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, cam_sensor_update_req_mgr(s_ctrl, csl_packet); } + if ((csl_packet->header.op_code & 0xFFFFFF) == + CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE) { + i2c_reg_settings->request_id = + csl_packet->header.request_id; + } + end: return rc; } @@ -1207,6 +1242,7 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, break; } case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: + case CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE: case CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE: default: return 0; @@ -1227,11 +1263,16 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, } } else { offset = req_id % MAX_PER_FRAME_ARRAY; - i2c_set = &(s_ctrl->i2c_data.per_frame[offset]); - if (i2c_set->is_settings_valid == 1 && - i2c_set->request_id == req_id) { + + if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE) + i2c_set = s_ctrl->i2c_data.frame_skip; + else + i2c_set = s_ctrl->i2c_data.per_frame; + + if (i2c_set[offset].is_settings_valid == 1 && + i2c_set[offset].request_id == req_id) { list_for_each_entry(i2c_list, - &(i2c_set->list_head), list) { + &(i2c_set[offset].list_head), list) { rc = cam_sensor_i2c_modes_util( &(s_ctrl->io_master_info), i2c_list); @@ -1250,13 +1291,13 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, /* Change the logic dynamically */ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { if ((req_id >= - s_ctrl->i2c_data.per_frame[i].request_id) && + i2c_set[i].request_id) && (top < - s_ctrl->i2c_data.per_frame[i].request_id) && - (s_ctrl->i2c_data.per_frame[i].is_settings_valid + i2c_set[i].request_id) && + (i2c_set[i].is_settings_valid == 1)) { del_req_id = top; - top = s_ctrl->i2c_data.per_frame[i].request_id; + top = i2c_set[i].request_id; } } @@ -1276,12 +1317,12 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { if ((del_req_id > - s_ctrl->i2c_data.per_frame[i].request_id) && ( - s_ctrl->i2c_data.per_frame[i].is_settings_valid + i2c_set[i].request_id) && ( + i2c_set[i].is_settings_valid == 1)) { - s_ctrl->i2c_data.per_frame[i].request_id = 0; + i2c_set[i].request_id = 0; rc = delete_request( - &(s_ctrl->i2c_data.per_frame[i])); + &(i2c_set[i])); if (rc < 0) CAM_ERR(CAM_SENSOR, "Delete request Fail:%lld rc:%d", @@ -1297,6 +1338,8 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply) { int32_t rc = 0; struct cam_sensor_ctrl_t *s_ctrl = NULL; + enum cam_sensor_packet_opcodes opcode = + CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE; if (!apply) return -EINVAL; @@ -1307,11 +1350,40 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply) CAM_ERR(CAM_SENSOR, "Device data is NULL"); return -EINVAL; } - CAM_DBG(CAM_REQ, " Sensor update req id: %lld", apply->request_id); + + CAM_DBG(CAM_REQ, " Sensor[%d] update req id: %lld", + s_ctrl->soc_info.index, apply->request_id); trace_cam_apply_req("Sensor", apply->request_id); mutex_lock(&(s_ctrl->cam_sensor_mutex)); rc = cam_sensor_apply_settings(s_ctrl, apply->request_id, - CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE); + opcode); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return rc; +} + +int32_t cam_sensor_notify_frame_skip(struct cam_req_mgr_apply_request *apply) +{ + int32_t rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + enum cam_sensor_packet_opcodes opcode = + CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE; + + if (!apply) + return -EINVAL; + + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(apply->dev_hdl); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + return -EINVAL; + } + + CAM_DBG(CAM_REQ, " Sensor[%d] handle frame skip for req id: %lld", + s_ctrl->soc_info.index, apply->request_id); + trace_cam_notify_frame_skip("Sensor", apply->request_id); + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + rc = cam_sensor_apply_settings(s_ctrl, apply->request_id, + opcode); mutex_unlock(&(s_ctrl->cam_sensor_mutex)); return rc; } @@ -1346,6 +1418,12 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) return -EINVAL; } + if (s_ctrl->i2c_data.frame_skip == NULL) { + CAM_ERR(CAM_SENSOR, "i2c not ready data is NULL"); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return -EINVAL; + } + 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", @@ -1374,6 +1452,28 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) } } + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(s_ctrl->i2c_data.frame_skip[i]); + + if ((flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) + && (i2c_set->request_id != flush_req->req_id)) + continue; + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request for not ready packet: %lld rc: %d", + i2c_set->request_id, rc); + + if (flush_req->type == + CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + cancel_req_id_found = 1; + break; + } + } + } + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && !cancel_req_id_found) CAM_DBG(CAM_SENSOR, diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h index b7a5923a6a70..507776843add 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_CORE_H_ @@ -47,6 +47,13 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, int64_t req_id, */ int cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply); +/** + * @apply: Req mgr structure for notifying frame skip + * + * This API notifies a frame is skipped + */ +int cam_sensor_notify_frame_skip(struct cam_req_mgr_apply_request *apply); + /** * @flush: Req mgr structure for flushing request * diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 9d85f3f9c10f..fd529205cdf7 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -176,25 +176,39 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, goto unreg_subdev; } + s_ctrl->i2c_data.frame_skip = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (s_ctrl->i2c_data.frame_skip == NULL) { + rc = -ENOMEM; + goto free_perframe; + } + INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); - for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.frame_skip[i].list_head)); + } s_ctrl->bridge_intf.device_hdl = -1; s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; + s_ctrl->bridge_intf.ops.notify_frame_skip = + cam_sensor_notify_frame_skip; s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request; s_ctrl->sensordata->power_info.dev = soc_info->dev; return rc; +free_perframe: + kfree(s_ctrl->i2c_data.per_frame); unreg_subdev: cam_unregister_subdev(&(s_ctrl->v4l2_dev_str)); free_s_ctrl: @@ -252,20 +266,32 @@ static int cam_sensor_component_bind(struct device *dev, goto unreg_subdev; } + s_ctrl->i2c_data.frame_skip = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (s_ctrl->i2c_data.frame_skip == NULL) { + rc = -ENOMEM; + goto free_perframe; + } + INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); - for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.frame_skip[i].list_head)); + } s_ctrl->bridge_intf.device_hdl = -1; s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; + s_ctrl->bridge_intf.ops.notify_frame_skip = + cam_sensor_notify_frame_skip; s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request; s_ctrl->sensordata->power_info.dev = &pdev->dev; @@ -274,6 +300,9 @@ static int cam_sensor_component_bind(struct device *dev, CAM_DBG(CAM_SENSOR, "Component bound successfully"); return rc; + +free_perframe: + kfree(s_ctrl->i2c_data.per_frame); unreg_subdev: cam_unregister_subdev(&(s_ctrl->v4l2_dev_str)); free_s_ctrl: @@ -305,6 +334,7 @@ static void cam_sensor_component_unbind(struct device *dev, devm_clk_put(soc_info->dev, soc_info->clk[i]); kfree(s_ctrl->i2c_data.per_frame); + kfree(s_ctrl->i2c_data.frame_skip); platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL); devm_kfree(&pdev->dev, s_ctrl); @@ -342,6 +372,7 @@ static int cam_sensor_driver_i2c_remove(struct i2c_client *client) devm_clk_put(soc_info->dev, soc_info->clk[i]); kfree(s_ctrl->i2c_data.per_frame); + kfree(s_ctrl->i2c_data.frame_skip); v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL); kfree(s_ctrl); diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 5889243dd38e..e18b4bb1c8d8 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -154,6 +154,7 @@ enum cam_sensor_packet_opcodes { CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF, CAM_SENSOR_PACKET_OPCODE_SENSOR_READ, + CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE, CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127 }; @@ -306,6 +307,7 @@ struct i2c_data_settings { struct i2c_settings_array streamoff_settings; struct i2c_settings_array read_settings; struct i2c_settings_array *per_frame; + struct i2c_settings_array *frame_skip; }; struct cam_sensor_power_ctrl_t { diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h index c564b1582a3a..8868c430684b 100644 --- a/drivers/cam_utils/cam_trace.h +++ b/drivers/cam_utils/cam_trace.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #if !defined(_CAM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) @@ -140,6 +140,23 @@ TRACE_EVENT(cam_apply_req, ) ); +TRACE_EVENT(cam_notify_frame_skip, + TP_PROTO(const char *entity, uint64_t req_id), + TP_ARGS(entity, req_id), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint64_t, req_id) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->req_id = req_id; + ), + TP_printk( + "%8s: NotifyFrameSkip request=%llu", + __get_str(entity), __entry->req_id + ) +); + TRACE_EVENT(cam_flush_req, TP_PROTO(struct cam_req_mgr_core_link *link, struct cam_req_mgr_flush_info *info), From 093fcb7ceb7661ffbf72871e475b027e638b0766 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 1 Jul 2020 13:13:22 -0700 Subject: [PATCH 416/790] msm: camera: reqmgr: Update the dma_buf api usage dma_buf_kmap/kunmap is replaced with dma_buf_vmap/vunmap api, to accommodate upstream driver. CRs-Fixed: 2732008 Change-Id: Id6551d84ea09d91a18c64fbbca3a796f4eab0bb1 Signed-off-by: Jigarkumar Zala --- drivers/cam_req_mgr/cam_mem_mgr.c | 45 +++++++++++-------------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 3d89aff97e28..650bfa0ab216 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -75,7 +75,7 @@ static int cam_mem_util_map_cpu_va(struct dma_buf *dmabuf, uintptr_t *vaddr, size_t *len) { - int i, j, rc; + int rc = 0; void *addr; /* @@ -88,30 +88,16 @@ static int cam_mem_util_map_cpu_va(struct dma_buf *dmabuf, return rc; } - /* - * Code could be simplified if ION support of dma_buf_vmap is - * available. This workaround takes the avandaage that ion_alloc - * returns a virtually contiguous memory region, so we just need - * to _kmap each individual page and then only use the virtual - * address returned from the first call to _kmap. - */ - for (i = 0; i < PAGE_ALIGN(dmabuf->size) / PAGE_SIZE; i++) { - addr = dma_buf_kmap(dmabuf, i); - if (IS_ERR_OR_NULL(addr)) { - CAM_ERR(CAM_MEM, "kernel map fail"); - for (j = 0; j < i; j++) - dma_buf_kunmap(dmabuf, - j, - (void *)(*vaddr + (j * PAGE_SIZE))); - *vaddr = 0; - *len = 0; - rc = -ENOSPC; - goto fail; - } - if (i == 0) - *vaddr = (uint64_t)addr; + addr = dma_buf_vmap(dmabuf); + if (!addr) { + CAM_ERR(CAM_MEM, "kernel map fail"); + *vaddr = 0; + *len = 0; + rc = -ENOSPC; + goto fail; } + *vaddr = (uint64_t)addr; *len = dmabuf->size; return 0; @@ -123,19 +109,14 @@ fail: static int cam_mem_util_unmap_cpu_va(struct dma_buf *dmabuf, uint64_t vaddr) { - int i, rc = 0, page_num; + int rc = 0; if (!dmabuf || !vaddr) { CAM_ERR(CAM_MEM, "Invalid input args %pK %llX", dmabuf, vaddr); return -EINVAL; } - page_num = PAGE_ALIGN(dmabuf->size) / PAGE_SIZE; - - for (i = 0; i < page_num; i++) { - dma_buf_kunmap(dmabuf, i, - (void *)(vaddr + (i * PAGE_SIZE))); - } + dma_buf_vunmap(dmabuf, (void *)vaddr); /* * dma_buf_begin_cpu_access() and @@ -982,6 +963,10 @@ static void cam_mem_mgr_unmap_active_buf(int idx) region = CAM_SMMU_REGION_IO; cam_mem_util_unmap_hw_va(idx, region, CAM_SMMU_MAPPING_USER); + + if (tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS) + cam_mem_util_unmap_cpu_va(tbl.bufq[idx].dma_buf, + tbl.bufq[idx].kmdvaddr); } static int cam_mem_mgr_cleanup_table(void) From af762bc692c2ca647bee0e95346a38ca92ae4575 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 3 Jun 2020 16:30:55 -0700 Subject: [PATCH 417/790] msm: camera: csiphy: Add support for CPHY dynamic lane configuration Add logic to dynamically lane configuration for the CPHY combo mode, where individual sensor can configure with different datarate by configuring the respective lanes at the time of configuration. CRs-Fixed: 2729624 Change-Id: Ie3714f9fd5d24c6cea8824f3a9dd9dc7f6f6d976 Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 408 +++++++++++------- .../cam_csiphy/cam_csiphy_dev.h | 8 +- .../include/cam_csiphy_1_2_1_hwreg.h | 163 +++++-- .../include/cam_csiphy_1_2_3_hwreg.h | 154 +++++-- .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 162 +++++-- .../include/cam_csiphy_2_1_0_hwreg.h | 152 ++++--- 6 files changed, 718 insertions(+), 329 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index f4d60b937c58..cd046c4eacc5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -145,75 +145,105 @@ static int32_t cam_csiphy_update_secure_info( } static int cam_csiphy_get_lane_enable( - struct csiphy_device *csiphy, int index, uint32_t *lane_enable) + struct csiphy_device *csiphy, int index, + uint16_t lane_assign, uint32_t *lane_enable) { uint32_t lane_select = 0; - uint16_t lane_assign = csiphy->csiphy_info[index].lane_assign; - uint8_t lane_cnt = csiphy->csiphy_info[index].lane_cnt; - int rc = 0; - while (lane_cnt--) { - if (csiphy->csiphy_info[index].csiphy_3phase) { - switch (lane_assign & 0xF) { - case 0x0: - lane_select |= CPHY_LANE_0; - break; - case 0x1: - lane_select |= CPHY_LANE_1; - break; - case 0x2: - lane_select |= CPHY_LANE_2; - break; - default: - CAM_ERR(CAM_CSIPHY, - "Wrong lane configuration for CPHY : %d", - lane_assign); - *lane_enable = 0; - return -EINVAL; - } - } else { - switch (lane_assign & 0xF) { - case 0x0: - lane_select |= DPHY_LANE_0; - lane_select |= DPHY_CLK_LN; - break; - case 0x1: - lane_select |= DPHY_LANE_1; - lane_select |= DPHY_CLK_LN; - break; - case 0x2: - lane_select |= DPHY_LANE_2; - if (csiphy->combo_mode) - lane_select |= DPHY_LANE_3; - else - lane_select |= DPHY_CLK_LN; - break; - case 0x3: - if (csiphy->combo_mode) { - CAM_ERR(CAM_CSIPHY, - "Wrong lane configuration for DPHYCombo: %d", - lane_assign); - *lane_enable = 0; - return -EINVAL; - } - lane_select |= DPHY_LANE_3; - lane_select |= DPHY_CLK_LN; - break; - default: - CAM_ERR(CAM_CSIPHY, - "Wrong lane configuration for DPHY: %d", - lane_assign); - *lane_enable = 0; - return -EINVAL; - } + if (csiphy->csiphy_info[index].csiphy_3phase) { + switch (lane_assign & 0xF) { + case 0x0: + lane_select |= CPHY_LANE_0; + break; + case 0x1: + lane_select |= CPHY_LANE_1; + break; + case 0x2: + lane_select |= CPHY_LANE_2; + break; + default: + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for CPHY : %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + } else { + switch (lane_assign & 0xF) { + case 0x0: + lane_select |= DPHY_LANE_0; + lane_select |= DPHY_CLK_LN; + break; + case 0x1: + lane_select |= DPHY_LANE_1; + lane_select |= DPHY_CLK_LN; + break; + case 0x2: + lane_select |= DPHY_LANE_2; + if (csiphy->combo_mode) + lane_select |= DPHY_LANE_3; + else + lane_select |= DPHY_CLK_LN; + break; + case 0x3: + if (csiphy->combo_mode) { + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for DPHYCombo: %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + lane_select |= DPHY_LANE_3; + lane_select |= DPHY_CLK_LN; + break; + default: + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for DPHY: %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; } - lane_assign >>= 4; } CAM_DBG(CAM_CSIPHY, "Lane_enable: 0x%x", lane_enable); *lane_enable = lane_select; - return rc; + return 0; +} + +static int cam_csiphy_sanitize_lane_cnt( + struct csiphy_device *csiphy_dev, + int32_t index, uint8_t lane_cnt) +{ + uint8_t max_supported_lanes = 0; + + if (csiphy_dev->combo_mode) { + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + max_supported_lanes = 1; + else + max_supported_lanes = 2; + } else if (csiphy_dev->cphy_dphy_combo_mode) { + /* 2DPHY + 1CPHY or 2CPHY + 1DPHY */ + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + max_supported_lanes = 2; + else + max_supported_lanes = 2; + } else { + /* Mission Mode */ + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + max_supported_lanes = 3; + else + max_supported_lanes = 4; + } + + if (lane_cnt <= 0 || lane_cnt > max_supported_lanes) { + CAM_ERR(CAM_CSIPHY, + "wrong lane_cnt configuration: expected max lane_cnt: %u received lane_cnt: %u", + max_supported_lanes, lane_cnt); + return -EINVAL; + } + + return 0; } int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, @@ -230,6 +260,8 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, size_t remain_len; int index; uint32_t lane_enable = 0; + uint16_t lane_assign = 0; + uint8_t lane_cnt = 0; if (!cfg_dev || !csiphy_dev) { CAM_ERR(CAM_CSIPHY, "Invalid Args"); @@ -294,6 +326,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, return -EINVAL; } + rc = cam_csiphy_sanitize_lane_cnt(csiphy_dev, index, + cam_cmd_csiphy_info->lane_cnt); + if (rc) { + CAM_ERR(CAM_CSIPHY, + "Wrong configuration lane_cnt: %u", + cam_cmd_csiphy_info->lane_cnt); + return rc; + } + csiphy_dev->csiphy_info[index].lane_cnt = cam_cmd_csiphy_info->lane_cnt; csiphy_dev->csiphy_info[index].lane_assign = cam_cmd_csiphy_info->lane_assign; @@ -305,22 +346,28 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, csiphy_dev->csiphy_info[index].secure_mode = cam_cmd_csiphy_info->secure_mode; - rc = cam_csiphy_get_lane_enable(csiphy_dev, index, &lane_enable); - if (rc) { - CAM_ERR(CAM_CSIPHY, "Wrong lane configuration: %d", - csiphy_dev->csiphy_info[index].lane_assign); - if ((csiphy_dev->combo_mode) || - (csiphy_dev->cphy_dphy_combo_mode)) { - CAM_DBG(CAM_CSIPHY, - "Resetting error to zero for other devices to configure"); - rc = 0; - } - lane_enable = 0; - csiphy_dev->csiphy_info[index].lane_enable = lane_enable; - goto reset_settings; - } + lane_assign = csiphy_dev->csiphy_info[index].lane_assign; + lane_cnt = csiphy_dev->csiphy_info[index].lane_cnt; - csiphy_dev->csiphy_info[index].lane_enable = lane_enable; + while (lane_cnt--) { + rc = cam_csiphy_get_lane_enable(csiphy_dev, index, + (lane_assign & 0xF), &lane_enable); + if (rc) { + CAM_ERR(CAM_CSIPHY, "Wrong lane configuration: %d", + csiphy_dev->csiphy_info[index].lane_assign); + if ((csiphy_dev->combo_mode) || + (csiphy_dev->cphy_dphy_combo_mode)) { + CAM_DBG(CAM_CSIPHY, + "Resetting error to zero for other devices to configure"); + rc = 0; + } + lane_enable = 0; + csiphy_dev->csiphy_info[index].lane_enable = lane_enable; + goto reset_settings; + } + csiphy_dev->csiphy_info[index].lane_enable |= lane_enable; + lane_assign >>= 4; + } if (cam_cmd_csiphy_info->secure_mode == 1) cam_csiphy_update_secure_info(csiphy_dev, @@ -372,66 +419,6 @@ void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev) csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr); } -static void cam_csiphy_cphy_data_rate_config( - struct csiphy_device *csiphy_device, int32_t idx) -{ - int i = 0, j = 0; - uint64_t phy_data_rate = 0; - void __iomem *csiphybase = NULL; - ssize_t num_table_entries = 0; - struct data_rate_settings_t *settings_table = NULL; - - if ((csiphy_device == NULL) || - (csiphy_device->ctrl_reg == NULL) || - (csiphy_device->ctrl_reg->data_rates_settings_table == NULL)) { - CAM_DBG(CAM_CSIPHY, - "Data rate specific register table not found"); - return; - } - - phy_data_rate = csiphy_device->csiphy_info[idx].data_rate; - csiphybase = - csiphy_device->soc_info.reg_map[0].mem_base; - settings_table = - csiphy_device->ctrl_reg->data_rates_settings_table; - num_table_entries = - settings_table->num_data_rate_settings; - - CAM_DBG(CAM_CSIPHY, "required data rate : %llu", phy_data_rate); - for (i = 0; i < num_table_entries; i++) { - struct data_rate_reg_info_t *drate_settings = - settings_table->data_rate_settings; - uint64_t bandwidth = - drate_settings[i].bandwidth; - ssize_t num_reg_entries = - drate_settings[i].data_rate_reg_array_size; - - if (phy_data_rate > bandwidth) { - CAM_DBG(CAM_CSIPHY, - "Skipping table [%d] %llu required: %llu", - i, bandwidth, phy_data_rate); - continue; - } - - CAM_DBG(CAM_CSIPHY, - "table[%d] BW : %llu Selected", i, bandwidth); - for (j = 0; j < num_reg_entries; j++) { - uint32_t reg_addr = - drate_settings[i].csiphy_data_rate_regs[j].reg_addr; - - uint32_t reg_data = - drate_settings[i].csiphy_data_rate_regs[j].reg_data; - - CAM_DBG(CAM_CSIPHY, - "writing reg : %x val : %x", - reg_addr, reg_data); - cam_io_w_mb(reg_data, - csiphybase + reg_addr); - } - break; - } -} - void cam_csiphy_cphy_irq_disable(struct csiphy_device *csiphy_dev) { int32_t i; @@ -482,6 +469,122 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data) return IRQ_HANDLED; } +static int cam_csiphy_cphy_get_data_rate_lane_idx( + struct csiphy_device *csiphy_dev, int32_t index, + uint16_t lane_assign, + struct data_rate_reg_info_t *drate_settings) +{ + int rc = 0; + int idx = -1; + uint32_t lane_enable; + + rc = cam_csiphy_get_lane_enable(csiphy_dev, index, + lane_assign, &lane_enable); + if (rc) { + CAM_ERR(CAM_CSIPHY, + "Wrong configuration for lane_assign: %u", lane_assign); + return rc; + } + + for (idx = 0; idx < CAM_CSIPHY_MAX_CPHY_LANES; idx++) { + if (lane_enable & drate_settings->per_lane_info[idx].lane_identifier) + return idx; + } + + if (idx == CAM_CSIPHY_MAX_CPHY_LANES) { + CAM_ERR(CAM_CSIPHY, + "Lane not found in datarate table"); + rc = -EINVAL; + } + + return rc; +} + +static int cam_csiphy_cphy_data_rate_config( + struct csiphy_device *csiphy_device, int32_t idx) +{ + int i = 0; + int lane_idx = -1; + int data_rate_idx = -1; + uint64_t phy_data_rate = 0; + void __iomem *csiphybase = NULL; + ssize_t num_table_entries = 0; + struct data_rate_settings_t *settings_table = NULL; + struct csiphy_cphy_per_lane_info *per_lane = NULL; + uint32_t lane_enable = 0; + uint8_t lane_cnt = 0; + uint16_t lane_assign = 0; + + if ((csiphy_device == NULL) || + (csiphy_device->ctrl_reg == NULL) || + (csiphy_device->ctrl_reg->data_rates_settings_table == NULL)) { + CAM_DBG(CAM_CSIPHY, + "Data rate specific register table not found"); + return -EINVAL; + } + + phy_data_rate = csiphy_device->csiphy_info[idx].data_rate; + csiphybase = + csiphy_device->soc_info.reg_map[0].mem_base; + settings_table = + csiphy_device->ctrl_reg->data_rates_settings_table; + num_table_entries = + settings_table->num_data_rate_settings; + lane_cnt = csiphy_device->csiphy_info[idx].lane_cnt; + + CAM_DBG(CAM_CSIPHY, "required data rate : %llu", phy_data_rate); + for (data_rate_idx = 0; data_rate_idx < num_table_entries; + data_rate_idx++) { + struct data_rate_reg_info_t *drate_settings = + settings_table->data_rate_settings; + uint64_t bandwidth = drate_settings[data_rate_idx].bandwidth; + ssize_t num_reg_entries = + drate_settings[data_rate_idx].data_rate_reg_array_size; + if (phy_data_rate > bandwidth) { + CAM_DBG(CAM_CSIPHY, + "Skipping table [%d] with BW: %llu, Required data_rate: %llu", + data_rate_idx, bandwidth, phy_data_rate); + continue; + } + + CAM_DBG(CAM_CSIPHY, "table[%d] BW : %llu Selected", + data_rate_idx, bandwidth); + lane_enable = csiphy_device->csiphy_info[idx].lane_enable; + lane_assign = csiphy_device->csiphy_info[idx].lane_assign; + lane_idx = -1; + + while (lane_cnt--) { + lane_idx = cam_csiphy_cphy_get_data_rate_lane_idx( + csiphy_device, idx, (lane_assign & 0xF), + &drate_settings[data_rate_idx]); + if (lane_idx < 0) { + CAM_ERR(CAM_CSIPHY, + "Lane_assign %u failed to find the lane for datarate_idx: %d", + lane_assign, data_rate_idx); + return -EINVAL; + } + + lane_assign >>= 4; + per_lane = &drate_settings[data_rate_idx].per_lane_info[lane_idx]; + + for (i = 0; i < num_reg_entries; i++) { + uint32_t reg_addr = + per_lane->csiphy_data_rate_regs[i].reg_addr; + + uint32_t reg_data = + per_lane->csiphy_data_rate_regs[i].reg_data; + + CAM_DBG(CAM_CSIPHY, "writing reg : %x val : %x", + reg_addr, reg_data); + cam_io_w_mb(reg_data, csiphybase + reg_addr); + } + } + break; + } + + return 0; +} + int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, int32_t dev_handle) { @@ -668,8 +771,15 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, } } - if (csiphy_dev->csiphy_info[index].csiphy_3phase) - cam_csiphy_cphy_data_rate_config(csiphy_dev, index); + if (csiphy_dev->csiphy_info[index].csiphy_3phase) { + rc = cam_csiphy_cphy_data_rate_config(csiphy_dev, index); + if (rc) { + CAM_ERR(CAM_CSIPHY, + "Date rate specific configuration failed rc: %d", + rc); + return rc; + } + } cam_csiphy_cphy_irq_config(csiphy_dev); @@ -1175,9 +1285,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { if (cam_cpas_is_feature_supported( CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { - CAM_WARN(CAM_CSIPHY, + CAM_ERR(CAM_CSIPHY, "sec_cam: camera fuse bit not set"); - rc = 0; goto release_mutex; } @@ -1187,23 +1296,30 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev->csiphy_info[offset] .secure_mode = CAM_SECURE_MODE_NON_SECURE; - CAM_WARN(CAM_CSIPHY, + CAM_ERR(CAM_CSIPHY, "sec_cam: notify failed: rc: %d", rc); - rc = 0; goto release_mutex; } } - if (csiphy_dev->csiphy_info[offset].csiphy_3phase) - cam_csiphy_cphy_data_rate_config( + + if (csiphy_dev->csiphy_info[offset].csiphy_3phase) { + rc = cam_csiphy_cphy_data_rate_config( csiphy_dev, offset); + if (rc) { + CAM_ERR(CAM_CSIPHY, + "Data rate specific configuration failed rc: %d", + rc); + goto release_mutex; + } + } rc = cam_csiphy_update_lane(csiphy_dev, offset, true); if (csiphy_dump == 1) cam_csiphy_mem_dmp(&csiphy_dev->soc_info); if (rc) { - CAM_WARN(CAM_CSIPHY, - "csiphy_config_dev failed"); + CAM_ERR(CAM_CSIPHY, + "Update enable lane failed, rc: %d", rc); goto release_mutex; } @@ -1236,7 +1352,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, CAM_ERR(CAM_CSIPHY, "sec_cam: camera fuse bit not set"); cam_cpas_stop(csiphy_dev->cpas_handle); - rc = -1; + rc = -EINVAL; goto release_mutex; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 35c2f585deb7..39e3c62f5678 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -152,6 +152,11 @@ struct csiphy_reg_t { struct csiphy_device; +struct csiphy_cphy_per_lane_info { + uint8_t lane_identifier; + struct csiphy_reg_t csiphy_data_rate_regs[MAX_DATA_RATE_REGS]; +}; + /* * struct data_rate_reg_info_t * @bandwidth: max bandwidth supported by this reg settings @@ -161,7 +166,8 @@ struct csiphy_device; struct data_rate_reg_info_t { uint64_t bandwidth; ssize_t data_rate_reg_array_size; - struct csiphy_reg_t csiphy_data_rate_regs[MAX_DATA_RATE_REGS]; + struct csiphy_cphy_per_lane_info per_lane_info[ + CAM_CSIPHY_MAX_CPHY_LANES]; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 8bf373677a51..4d8a32940299 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -396,58 +396,135 @@ struct data_rate_settings_t data_rate_delta_table_1_2_1 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 9, - .csiphy_data_rate_regs = { - {0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - } + .data_rate_reg_array_size = 3, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0x32, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x0B, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0x32, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x0B, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x544, 0x32, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x0B, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 12, - .csiphy_data_rate_regs = { - {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + .data_rate_reg_array_size = 4, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x01, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x01, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x544, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x01, + CSIPHY_DEFAULT_PARAMS}, + }, + }, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 12, - .csiphy_data_rate_regs = { - {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + .data_rate_reg_array_size = 4, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x01, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x01, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x544, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x01, + CSIPHY_DEFAULT_PARAMS}, + }, + }, }, - } - } + }, + }, }; - #endif /* _CAM_CSIPHY_1_2_1_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index bddd49432d9a..ec6a5499d6fc 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -342,56 +342,130 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 6, - .csiphy_data_rate_regs = { - {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x0A, CSIPHY_DEFAULT_PARAMS}, - - } + .data_rate_reg_array_size = 2, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x544, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 12, - .csiphy_data_rate_regs = { - {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x0A, CSIPHY_DEFAULT_PARAMS}, + .data_rate_reg_array_size = 4, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 12, - .csiphy_data_rate_regs = { - {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x0A, CSIPHY_DEFAULT_PARAMS}, + .data_rate_reg_array_size = 4, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x01, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x01, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, }, - } - } + }, + }, }; #endif /* _CAM_CSIPHY_1_2_3_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 446c8197df8a..80821fa1c5fe 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -376,57 +376,135 @@ struct data_rate_settings_t data_rate_delta_table_1_2 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 3, - .csiphy_data_rate_regs = { - {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - } + .data_rate_reg_array_size = 1, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x544, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 15, - .csiphy_data_rate_regs = { - {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + .data_rate_reg_array_size = 5, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x9B4, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x10C, 0x08, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0xAB4, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x08, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0xBB4, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x08, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 15, - .csiphy_data_rate_regs = { - {0x9B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xA80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xB80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x10C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x30C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x50C, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + .data_rate_reg_array_size = 5, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x9B4, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x10C, 0x08, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0xAB4, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x30C, 0x08, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0xBB4, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x50C, 0x08, 0x00, + CSIPHY_DEFAULT_PARAMS}, + }, + }, }, - } - } + }, + }, }; #endif /* _CAM_CSIPHY_1_2_HWREG_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h index cdeffc9bf754..9cd115be221d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h @@ -15,7 +15,7 @@ struct csiphy_reg_parms_t csiphy_v2_1_0 = { .csiphy_common_array_size = 6, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 19, - .csiphy_3ph_config_array_size = 28, + .csiphy_3ph_config_array_size = 29, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -286,6 +286,7 @@ struct csiphy_reg_t csiphy_3ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0268, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x026C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0214, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0260, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0240, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -316,6 +317,7 @@ struct csiphy_reg_t csiphy_3ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0668, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x066C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0614, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0660, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0640, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -346,6 +348,7 @@ struct csiphy_reg_t csiphy_3ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0A68, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A6C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0A14, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A60, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A40, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -372,71 +375,106 @@ struct data_rate_settings_t data_rate_delta_table_2_1_0 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 9, - .csiphy_data_rate_regs = { - {0x0290, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0690, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A90, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x020C, 0x03, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0208, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x060C, 0x03, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0608, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x0A0C, 0x03, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0A08, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - - } + .data_rate_reg_array_size = 2, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x0290, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x020C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x0690, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x060C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x0A90, 0x02, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x0A0C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 9, - .csiphy_data_rate_regs = { - {0x0290, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0690, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A90, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x020C, 0x03, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0208, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x060C, 0x03, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0608, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x0A0C, 0x03, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0A08, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + .data_rate_reg_array_size = 2, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x0290, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x020C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x0690, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x060C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x0A90, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x0A0C, 0x03, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, }, }, { /* (6.5 * 10**3 * 2.28) rounded value */ .bandwidth = 14820000000, - .data_rate_reg_array_size = 9, - .csiphy_data_rate_regs = { - {0x0290, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0690, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A90, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x020C, 0x07, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0208, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x060C, 0x07, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0608, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x0A0C, 0x07, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0A08, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + .data_rate_reg_array_size = 2, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x0290, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x020C, 0x07, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x0690, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x060C, 0x07, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x0A90, 0x03, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x0A0C, 0x07, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + }, + }, }, - } - } + }, + }, }; -#endif /* _CAM_CSIPHY_2_1_0_HWREG_H_ */ +#endif /* _CAM_CSIPHY_2_1_0_HWREG_H_ */ \ No newline at end of file From 61575d2c08d571aa70b24c69687754bd4a21f8f5 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Wed, 15 Jul 2020 22:44:25 +0800 Subject: [PATCH 418/790] msm: camera: sensor: Fix misleading indentation issue Fix misleading indentation issue. CRs-Fixed: 2732403 Change-Id: I1f04f0de14ef7c18d669f17842c712f340d093ed Signed-off-by: Depeng Shao --- drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c index 3d09a4ea7eb3..b41626704509 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -171,12 +171,14 @@ static int32_t cam_spi_tx_helper(struct camera_io_master *client, memcpy(data, crx + hlen, num_byte); out: - if (!tx) + if (!tx) { vfree(vaddr_tx); vaddr_tx = NULL; - if (!rx) + } + if (!rx) { vfree(vaddr_rx); vaddr_rx = NULL; + } return rc; } From a358e14888731a449d604e6907538a592b330c74 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 10 Jul 2020 15:13:05 -0700 Subject: [PATCH 419/790] msm: camera: reqmgr: Allow requests to be submitted in IDLE state Allow requests to be submitted by UMD and added by devices on the link, irrespective of the link state. CRs-Fixed: 2718108 Change-Id: Ie6a6f3576bc6aeb1657ee751dc72779cafec7ffe Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_core.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 57ef31ee552b..e0a145e53630 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2857,20 +2857,12 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) } CAM_DBG(CAM_REQ, - "dev name %s dev_hdl %d dev req %lld, trigger_eof: %d", + "dev name %s dev_hdl %d dev req %lld, trigger_eof %d link_state %d", __cam_req_mgr_dev_handle_to_name(add_req->dev_hdl, link), - add_req->dev_hdl, add_req->req_id, add_req->trigger_eof); + add_req->dev_hdl, add_req->req_id, add_req->trigger_eof, + link->state); mutex_lock(&link->lock); - spin_lock_bh(&link->link_state_spin_lock); - if (link->state < CAM_CRM_LINK_STATE_READY) { - CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); - rc = -EPERM; - spin_unlock_bh(&link->link_state_spin_lock); - goto end; - } - spin_unlock_bh(&link->link_state_spin_lock); - /* Validate if req id is present in input queue */ idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id); if (idx < 0) { From 8210c9c2167bc38b4d22153b4595351a3a0b6f0f Mon Sep 17 00:00:00 2001 From: Suraj Dongre Date: Mon, 10 Feb 2020 20:01:39 -0800 Subject: [PATCH 420/790] msm: camera: jpeg: Add dma driver implementation Add code to fill register settings and irq handler code for JPEG DMA. CRs-Fixed: 2716356 Change-Id: Ib48c5b27e6b29bf935fff3b68a6c74b483ea572c Signed-off-by: Suraj Dongre --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 193 +++++++++----- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 2 + .../cam_jpeg_dma_hw_info_ver_4_2_0.h | 46 ++++ .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 241 +++++++++++++++++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 42 ++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 18 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 1 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 2 +- 8 files changed, 459 insertions(+), 86 deletions(-) create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 3f7c179711af..b270ce955285 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -38,6 +38,112 @@ static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr; static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status, int32_t result_size, void *data); static int cam_jpeg_mgr_process_cmd(void *priv, void *data); +static int cam_jpeg_insert_cdm_change_base( + struct cam_hw_config_args *config_args, + struct cam_jpeg_hw_ctx_data *ctx_data, + struct cam_jpeg_hw_mgr *hw_mgr); + +static int cam_jpeg_process_next_hw_update(void *priv, void *data) +{ + int rc; + int i = 0; + struct cam_jpeg_hw_mgr *hw_mgr = priv; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; + struct cam_hw_config_args *config_args = NULL; + struct cam_jpeg_hw_ctx_data *ctx_data = NULL; + uint32_t dev_type; + struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; + uint32_t cdm_cfg_to_insert = 0; + + if (!data || !priv) { + CAM_ERR(CAM_JPEG, "Invalid data"); + return -EINVAL; + } + + ctx_data = (struct cam_jpeg_hw_ctx_data *)data; + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; + config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args; + + if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { + CAM_ERR(CAM_JPEG, "op reset null "); + rc = -EFAULT; + goto end_error; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( + hw_mgr->devices[dev_type][0]->hw_priv, + NULL, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + goto end_error; + } + + cdm_cmd = ctx_data->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = false; + cdm_cmd->userdata = NULL; + cdm_cmd->cookie = 0; + cdm_cmd->cmd_arrary_count = 0; + + /* insert cdm chage base cmd */ + rc = cam_jpeg_insert_cdm_change_base(config_args, + ctx_data, hw_mgr); + if (rc) { + CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); + goto end_error; + } + + /* insert next cdm payload at index */ + /* for enc or dma 1st pass at index 1 */ + /* for dma 2nd pass at index 2, for 3rd at 4 */ + if (p_cfg_req->num_hw_entry_processed == 0) + cdm_cfg_to_insert = CAM_JPEG_CFG; + else + cdm_cfg_to_insert = p_cfg_req->num_hw_entry_processed + 2; + + CAM_DBG(CAM_JPEG, "processed %d total %d using cfg entry %d for %pK", + p_cfg_req->num_hw_entry_processed, + config_args->num_hw_update_entries, + cdm_cfg_to_insert, + p_cfg_req); + + cmd = (config_args->hw_update_entries + cdm_cfg_to_insert); + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = + cmd->handle; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = + cmd->offset; + cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = + cmd->len; + CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", + i, cmd->handle, cmd->offset, cmd->len); + cdm_cmd->cmd_arrary_count++; + + rc = cam_cdm_submit_bls( + hw_mgr->cdm_info[dev_type][0].cdm_handle, + cdm_cmd); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); + goto end_error; + } + + if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { + CAM_ERR(CAM_JPEG, "op start null "); + rc = -EINVAL; + goto end_error; + } + rc = hw_mgr->devices[dev_type][0]->hw_ops.start( + hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", + rc); + goto end_error; + } + + return 0; +end_error: + return rc; +} static int cam_jpeg_mgr_process_irq(void *priv, void *data) { @@ -85,6 +191,21 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) return -EINVAL; } + p_cfg_req->num_hw_entry_processed++; + CAM_DBG(CAM_JPEG, "hw entry processed %d", + p_cfg_req->num_hw_entry_processed); + + if ((task_data->result_size > 0) && + (p_cfg_req->num_hw_entry_processed < + p_cfg_req->hw_cfg_args.num_hw_update_entries - 2)) { + /* start processing next entry before marking device free */ + rc = cam_jpeg_process_next_hw_update(priv, ctx_data); + if (!rc) { + mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); + return 0; + } + } + irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; irq_cb.data = NULL; irq_cb.b_set_cb = false; @@ -281,7 +402,9 @@ static int cam_jpeg_insert_cdm_change_base( if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >= ch_base_len) { - CAM_ERR(CAM_JPEG, "Not enough buf"); + CAM_ERR(CAM_JPEG, "Not enough buf offset %d len %d", + config_args->hw_update_entries[CAM_JPEG_CHBASE].offset, + ch_base_len); return -EINVAL; } CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d", @@ -321,8 +444,6 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) int rc; int i = 0; struct cam_jpeg_hw_mgr *hw_mgr = priv; - struct cam_hw_update_entry *cmd; - struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; uintptr_t request_id = 0; @@ -424,71 +545,13 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) goto end_callcb; } - if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { - CAM_ERR(CAM_JPEG, "op reset null "); - rc = -EFAULT; - goto end_callcb; - } - rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( - hw_mgr->devices[dev_type][0]->hw_priv, - NULL, 0); + /* insert one of the cdm payloads */ + rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (rc) { - CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + CAM_ERR(CAM_JPEG, "next hw update failed %d", rc); goto end_callcb; } - cdm_cmd = ctx_data->cdm_cmd; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = false; - cdm_cmd->userdata = NULL; - cdm_cmd->cookie = 0; - cdm_cmd->cmd_arrary_count = 0; - cdm_cmd->gen_irq_arb = false; - - rc = cam_jpeg_insert_cdm_change_base(config_args, - ctx_data, hw_mgr); - if (rc) { - CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); - goto end_callcb; - } - - CAM_DBG(CAM_JPEG, "num hw up %d", config_args->num_hw_update_entries); - for (i = CAM_JPEG_CFG; i < (config_args->num_hw_update_entries - 1); - i++) { - cmd = (config_args->hw_update_entries + i); - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle - = cmd->handle; - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = - cmd->offset; - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = - cmd->len; - cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].arbitrate = - false; - CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", - i, cmd->handle, cmd->offset, cmd->len); - cdm_cmd->cmd_arrary_count++; - } - - rc = cam_cdm_submit_bls( - hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); - if (rc) { - CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); - goto end_callcb; - } - - if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { - CAM_ERR(CAM_JPEG, "op start null "); - rc = -EINVAL; - goto end_callcb; - } - rc = hw_mgr->devices[dev_type][0]->hw_ops.start( - hw_mgr->devices[dev_type][0]->hw_priv, - NULL, 0); - if (rc) { - CAM_ERR(CAM_JPEG, "Failed to start hw %d", - rc); - goto end_callcb; - } p_cfg_req->submit_timestamp = ktime_get(); mutex_unlock(&hw_mgr->hw_mgr_mutex); @@ -567,6 +630,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) request_id = (uintptr_t)config_args->priv; p_cfg_req->req_id = request_id; + p_cfg_req->num_hw_entry_processed = 0; hw_update_entries = config_args->hw_update_entries; CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd", ctx_data, request_id, (uintptr_t)config_args->priv); @@ -781,6 +845,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence); } + CAM_DBG(CAM_JPEG, "received num cmd buf %d", packet->num_cmd_buf); j = prepare_args->num_hw_update_entries; rc = cam_packet_util_get_kmd_buffer(packet, &kmd_buf); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 3a00e424ebc9..9de5f2950d3a 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -76,6 +76,7 @@ struct cam_jpeg_hw_cdm_info_t { * @dev_type: Dev type for cfg request * @req_id: Request Id * @submit_timestamp: Timestamp of submitting request + * @num_hw_entry_processed: Cdm payloads already processed */ struct cam_jpeg_hw_cfg_req { struct list_head list; @@ -83,6 +84,7 @@ struct cam_jpeg_hw_cfg_req { uint32_t dev_type; uintptr_t req_id; ktime_t submit_timestamp; + uint32_t num_hw_entry_processed; }; /** diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..d4c62f381851 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H +#define CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H + +#define CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE (1 << 0) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RD_BUF_DONE (1 << 1) +#define CAM_JPEGDMA_HW_IRQ_STATUS_WR_BUF_DONE (1 << 5) +#define CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT (1 << 9) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE (1 << 10) + +#define CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE +#define CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK \ + CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE + +static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x14, + .int_status = 0x10, + .int_mask = 0x0C, + .hw_cmd = 0x1C, + .reset_cmd = 0x08, + .encode_size = 0x180, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x32083, + .hw_cmd_stop = 0x00000004, + }, + .int_status = { + .framedone = CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK, + .iserror = 0x0, + .stopdone = CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT, + } +}; + +#endif /* CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c index 1304bbc71d38..87431897d4b1 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -23,6 +23,15 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" +#define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.framedone) +#define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.resetdone) +#define CAM_JPEG_HW_IRQ_IS_STOP_DONE(jpeg_irq_status, hi) \ + ((jpeg_irq_status) & (hi)->int_status.stopdone) + +#define CAM_JPEG_DMA_RESET_TIMEOUT msecs_to_jiffies(500) + int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { @@ -132,7 +141,7 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, rc = cam_jpeg_dma_disable_soc_resources(soc_info); if (rc) - CAM_ERR(CAM_JPEG, "soc enable failed %d", rc); + CAM_ERR(CAM_JPEG, "soc disable failed %d", rc); rc = cam_cpas_stop(core_info->cpas_handle); if (rc) @@ -143,6 +152,226 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, return 0; } +irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + uint32_t irq_status = 0; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return IRQ_HANDLED; + } + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + irq_status = cam_io_r_mb(mem_base + + core_info->jpeg_dma_hw_info->reg_offset.int_status); + cam_io_w_mb(irq_status, + soc_info->reg_map[0].mem_base + + core_info->jpeg_dma_hw_info->reg_offset.int_clr); + CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d", + irq_num, irq_status, core_info->core_state); + if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) { + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_READY) { + core_info->result_size = 1; + CAM_DBG(CAM_JPEG, "result_size %d", + core_info->result_size); + core_info->core_state = + CAM_JPEG_DMA_CORE_RESETTING_ON_DONE; + cam_io_w_mb(hw_info->reg_val.reset_cmd, + mem_base + hw_info->reg_offset.reset_cmd); + } else { + CAM_WARN(CAM_JPEG, "unexpected frame done "); + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } + spin_unlock(&jpeg_dma_dev->hw_lock); + } + + if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status, hw_info)) { + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { + core_info->core_state = CAM_JPEG_DMA_CORE_READY; + core_info->result_size = -1; + complete(&jpeg_dma_dev->hw_complete); + } else if (core_info->core_state == + CAM_JPEG_DMA_CORE_RESETTING_ON_DONE) { + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + core_info->result_size, + core_info->irq_cb.data); + } else { + CAM_WARN(CAM_JPEG, "unexpected frame done"); + } + core_info->result_size = -1; + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } else { + CAM_ERR(CAM_JPEG, "unexpected reset irq"); + } + spin_unlock(&jpeg_dma_dev->hw_lock); + } + if (CAM_JPEG_HW_IRQ_IS_STOP_DONE(irq_status, hw_info)) { + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + complete(&jpeg_dma_dev->hw_complete); + if (core_info->irq_cb.jpeg_hw_mgr_cb) { + core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, + -1, + core_info->irq_cb.data); + } + } else { + CAM_ERR(CAM_JPEG, "unexpected abort irq"); + } + spin_unlock(&jpeg_dma_dev->hw_lock); + } + + return IRQ_HANDLED; +} + +int cam_jpeg_dma_reset_hw(void *data, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + unsigned long rem_jiffies; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + /* maskdisable.clrirq.maskenable.resetcmd */ + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { + CAM_ERR(CAM_JPEG, "dma alrady resetting"); + spin_unlock(&jpeg_dma_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return 0; + } + + reinit_completion(&jpeg_dma_dev->hw_complete); + + core_info->core_state = CAM_JPEG_DMA_CORE_RESETTING; + spin_unlock(&jpeg_dma_dev->hw_lock); + + cam_io_w_mb(hw_info->reg_val.int_mask_disable_all, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.int_clr_clearall, + mem_base + hw_info->reg_offset.int_clr); + cam_io_w_mb(hw_info->reg_val.int_mask_enable_all, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.reset_cmd, + mem_base + hw_info->reg_offset.reset_cmd); + + rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, + CAM_JPEG_DMA_RESET_TIMEOUT); + if (!rem_jiffies) { + CAM_ERR(CAM_JPEG, "dma error Reset Timeout"); + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } + + mutex_unlock(&core_info->core_mutex); + return 0; +} + +int cam_jpeg_dma_start_hw(void *data, + void *start_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + if (core_info->core_state != CAM_JPEG_DMA_CORE_READY) { + CAM_ERR(CAM_JPEG, "Error not ready"); + return -EINVAL; + } + + CAM_DBG(CAM_JPEG, "Starting DMA"); + cam_io_w_mb(0x00000601, + mem_base + hw_info->reg_offset.int_mask); + cam_io_w_mb(hw_info->reg_val.hw_cmd_start, + mem_base + hw_info->reg_offset.hw_cmd); + + return 0; +} + +int cam_jpeg_dma_stop_hw(void *data, + void *stop_args, uint32_t arg_size) +{ + struct cam_hw_info *jpeg_dma_dev = data; + struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; + void __iomem *mem_base; + unsigned long rem_jiffies; + + if (!jpeg_dma_dev) { + CAM_ERR(CAM_JPEG, "Invalid args"); + return -EINVAL; + } + soc_info = &jpeg_dma_dev->soc_info; + core_info = (struct cam_jpeg_dma_device_core_info *) + jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + mem_base = soc_info->reg_map[0].mem_base; + + mutex_lock(&core_info->core_mutex); + spin_lock(&jpeg_dma_dev->hw_lock); + if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { + CAM_ERR(CAM_JPEG, "alrady stopping"); + spin_unlock(&jpeg_dma_dev->hw_lock); + mutex_unlock(&core_info->core_mutex); + return 0; + } + + reinit_completion(&jpeg_dma_dev->hw_complete); + core_info->core_state = CAM_JPEG_DMA_CORE_ABORTING; + spin_unlock(&jpeg_dma_dev->hw_lock); + + cam_io_w_mb(hw_info->reg_val.hw_cmd_stop, + mem_base + hw_info->reg_offset.hw_cmd); + + rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, + CAM_JPEG_DMA_RESET_TIMEOUT); + if (!rem_jiffies) { + CAM_ERR(CAM_JPEG, "error Reset Timeout"); + core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; + } + + mutex_unlock(&core_info->core_mutex); + return 0; +} + int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -187,11 +416,7 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, rc = -EINVAL; break; } - + if (rc) + CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc); return rc; } - -irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) -{ - return IRQ_HANDLED; -} diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h index 6b7c8344a292..94085814b472 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_DMA_CORE_H @@ -10,17 +10,48 @@ #include #include #include +#include #include "cam_jpeg_hw_intf.h" +struct cam_jpeg_dma_reg_offsets { + uint32_t hw_version; + uint32_t int_status; + uint32_t int_clr; + uint32_t int_mask; + uint32_t hw_cmd; + uint32_t reset_cmd; + uint32_t encode_size; +}; + +struct cam_jpeg_dma_regval { + uint32_t int_clr_clearall; + uint32_t int_mask_disable_all; + uint32_t int_mask_enable_all; + uint32_t hw_cmd_start; + uint32_t reset_cmd; + uint32_t hw_cmd_stop; +}; + +struct cam_jpeg_dma_int_status { + uint32_t framedone; + uint32_t resetdone; + uint32_t iserror; + uint32_t stopdone; +}; + struct cam_jpeg_dma_device_hw_info { - uint32_t reserved; + struct cam_jpeg_dma_reg_offsets reg_offset; + struct cam_jpeg_dma_regval reg_val; + struct cam_jpeg_dma_int_status int_status; }; enum cam_jpeg_dma_core_state { CAM_JPEG_DMA_CORE_NOT_READY, CAM_JPEG_DMA_CORE_READY, CAM_JPEG_DMA_CORE_RESETTING, + CAM_JPEG_DMA_CORE_ABORTING, + CAM_JPEG_DMA_CORE_RESETTING_ON_DONE, CAM_JPEG_DMA_CORE_STATE_MAX, }; @@ -31,12 +62,19 @@ struct cam_jpeg_dma_device_core_info { struct cam_jpeg_set_irq_cb irq_cb; int32_t ref_count; struct mutex core_mutex; + int32_t result_size; }; int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_jpeg_dma_deinit_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); +int cam_jpeg_dma_start_hw(void *device_priv, + void *start_hw_args, uint32_t arg_size); +int cam_jpeg_dma_stop_hw(void *device_priv, + void *stop_hw_args, uint32_t arg_size); +int cam_jpeg_dma_reset_hw(void *device_priv, + void *reset_hw_args, uint32_t arg_size); int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index 0bbe7ddfba8f..214bde71bcb6 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -18,12 +18,9 @@ #include "cam_jpeg_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" +#include "cam_jpeg_dma_hw_info_ver_4_2_0.h" #include "camera_main.h" -static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { - .reserved = 0, -}; - static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, struct cam_jpeg_dma_device_core_info *core_info, uint32_t hw_idx) @@ -90,6 +87,9 @@ static int cam_jpeg_dma_component_bind(struct device *dev, jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev; jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw; jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw; + jpeg_dma_dev_intf->hw_ops.start = cam_jpeg_dma_start_hw; + jpeg_dma_dev_intf->hw_ops.stop = cam_jpeg_dma_stop_hw; + jpeg_dma_dev_intf->hw_ops.reset = cam_jpeg_dma_reset_hw; jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd; jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA; @@ -134,14 +134,11 @@ static int cam_jpeg_dma_component_bind(struct device *dev, mutex_init(&jpeg_dma_dev->hw_mutex); spin_lock_init(&jpeg_dma_dev->hw_lock); init_completion(&jpeg_dma_dev->hw_complete); - - CAM_DBG(CAM_JPEG, "JPEG:%d component bound successfully", - jpeg_dma_dev_intf->hw_idx); - + CAM_DBG(CAM_JPEG, "JPEG-DMA component bound successfully"); return rc; error_reg_cpas: - rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); + cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); error_init_soc: mutex_destroy(&core_info->core_mutex); error_match_dev: @@ -150,6 +147,7 @@ error_alloc_core: kfree(jpeg_dma_dev); error_alloc_dev: kfree(jpeg_dma_dev_intf); + return rc; } @@ -198,8 +196,6 @@ deinit_soc: free_jpeg_hw_intf: kfree(jpeg_dma_dev_intf); - return; - } const static struct component_ops cam_jpeg_dma_component_ops = { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index c0cfbe7a76e4..62d0cb562aa5 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -356,6 +356,7 @@ int cam_jpeg_enc_start_hw(void *data, } spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); + CAM_DBG(CAM_JPEG, "Starting JPEG ENC"); cam_io_w_mb(hw_info->reg_val.hw_cmd_start, mem_base + hw_info->reg_offset.hw_cmd); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index 130111e54119..e9c9ebd6e193 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -134,7 +134,7 @@ static int cam_jpeg_enc_component_bind(struct device *dev, mutex_init(&jpeg_enc_dev->hw_mutex); spin_lock_init(&jpeg_enc_dev->hw_lock); init_completion(&jpeg_enc_dev->hw_complete); - CAM_DBG(CAM_JPEG, "Encoder component bound successfully"); + CAM_DBG(CAM_JPEG, "JPEG-Encoder component bound successfully"); return rc; From db30227d1795f85a6e77fe9407962386455c9da7 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Tue, 7 Jul 2020 17:56:09 -0700 Subject: [PATCH 421/790] Revert "msm: camera: isp: Disable clk gating in IFE top" This reverts commit 0181a16f13a02f9beaf3cca35b63c33a5a365d82. The control for disabling clock gating is with cpas. So, this change has no effect. CRs-Fixed: 2726688 Change-Id: I74f7d06680d039f8df4e28e8b58d4bd6ad0f650b Signed-off-by: Mukund Madhusudan Atre --- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index adbd880eabc8..6a66955ed280 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -366,20 +366,23 @@ int cam_vfe_top_ver3_init_hw(void *device_priv, top_priv->hw_clk_rate = 0; - /* Disable clock gating at IFE top */ - CAM_DBG(CAM_ISP, "Disable clock gating at IFE top"); + /** + * Auto clock gating is enabled by default, but no harm + * in setting the value we expect. + */ + CAM_DBG(CAM_ISP, "Enabling clock gating at IFE top"); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->core_cgc_ovd_0, 0xFFFFFFFF); + common_data.common_reg->core_cgc_ovd_0, 0x0); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->core_cgc_ovd_1, 0xFF); + common_data.common_reg->core_cgc_ovd_1, 0x0); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->ahb_cgc_ovd, 0x1); + common_data.common_reg->ahb_cgc_ovd, 0x0); cam_soc_util_w_mb(common_data.soc_info, VFE_CORE_BASE_IDX, - common_data.common_reg->noc_cgc_ovd, 0x1); + common_data.common_reg->noc_cgc_ovd, 0x0); top_priv->top_common.hw_version = cam_io_r_mb(common_data.soc_info->reg_map[0].mem_base + From 5f7b7386cf1e35e7d0869b13d6de59f8cf58b730 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Fri, 28 Feb 2020 14:32:54 +0530 Subject: [PATCH 422/790] msm: camera: isp: Added CSID recovery mechanism CSID is not able to recover from the fatal errors like lane overflows, continuous unbound frames or ESD errors. To recover from such errors, it is necessary to restart the sensor as just starting the ISP hw do not make any change as the sensor can still be in bad state. This commit implements tasklet based CSID recovery mechanism. On detecting an error in CSID interrupt, tasklet is scheduled which in turn will call the ISP hw manager to notify the ISP context, from here a notification is sent to CRM to send a message to trigger full recovery. This full recovery includes the sensor release and start. This feature is debugfs based. Based on need this can be turned on. CRs-Fixed: 2642216 Change-Id: Iecf9916d3672d71a1367886cc934b5a2b148f918 Signed-off-by: Gaurav Jindal Signed-off-by: Vishalsingh Hajeri Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/cam_isp_context.c | 10 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 64 ++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 3 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 1 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 472 ++++++++++++++---- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 48 ++ .../isp_hw/include/cam_ife_csid_hw_intf.h | 4 + include/uapi/camera/media/cam_req_mgr.h | 2 + 8 files changed, 505 insertions(+), 99 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5d2c46aa6ab5..9e876f08d425 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2036,8 +2036,14 @@ end: if (notify.error == CRM_KMD_ERR_FATAL) { 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; + + if (error_type == CAM_ISP_HW_ERROR_CSID_FATAL) + req_msg.u.err_msg.error_type = + CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + else + 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; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4f07a3a2841e..dbe8366d00c9 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1909,6 +1909,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( csid_acquire.in_port = in_port; csid_acquire.out_port = in_port->data; csid_acquire.node_res = NULL; + csid_acquire.event_cb = cam_ife_hw_mgr_event_handler; + csid_acquire.priv = ife_ctx; csid_acquire.crop_enable = crop_enable; csid_acquire.drop_enable = false; @@ -2048,6 +2050,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( csid_acquire.in_port = in_port; csid_acquire.out_port = out_port; csid_acquire.node_res = NULL; + csid_acquire.event_cb = cam_ife_hw_mgr_event_handler; + csid_acquire.priv = ife_ctx; /* * Enable RDI pixel drop by default. CSID will enable only for @@ -7327,6 +7331,12 @@ static int cam_ife_hw_mgr_find_affected_ctx( affected_core, CAM_IFE_HW_NUM_MAX)) continue; + if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) { + CAM_INFO(CAM_ISP, "CTX:%d already error reported", + ife_hwr_mgr_ctx->ctx_index); + continue; + } + atomic_set(&ife_hwr_mgr_ctx->overflow_pending, 1); notify_err_cb = ife_hwr_mgr_ctx->common.event_cb[event_type]; @@ -7342,8 +7352,13 @@ static int cam_ife_hw_mgr_find_affected_ctx( * In the call back function corresponding ISP context * will update CRM about fatal Error */ - notify_err_cb(ife_hwr_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_ERROR, error_event_data); + if (notify_err_cb) + notify_err_cb(ife_hwr_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_ERROR, error_event_data); + else { + CAM_WARN(CAM_ISP, "Error call back is not set"); + goto end; + } } /* fill the affected_core in recovery data */ @@ -7352,7 +7367,7 @@ static int cam_ife_hw_mgr_find_affected_ctx( CAM_DBG(CAM_ISP, "Vfe core %d is affected (%d)", i, recovery_data->affected_core[i]); } - +end: return 0; } @@ -7414,6 +7429,33 @@ static int cam_ife_hw_mgr_handle_hw_dump_info( return rc; } +static int cam_ife_hw_mgr_handle_csid_event( + struct cam_isp_hw_event_info *event_info) +{ + struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_ife_hw_event_recovery_data recovery_data = {0}; + + /* this can be extended based on the types of error + * received from CSID + */ + switch (event_info->err_type) { + case CAM_ISP_HW_ERROR_CSID_FATAL: { + + if (!g_ife_hw_mgr.debug_cfg.enable_csid_recovery) + break; + + error_event_data.error_type = event_info->err_type; + cam_ife_hw_mgr_find_affected_ctx(&error_event_data, + event_info->hw_idx, + &recovery_data); + break; + } + default: + break; + } + return 0; +} + static int cam_ife_hw_mgr_handle_hw_err( void *ctx, void *evt_info) @@ -7444,6 +7486,13 @@ static int cam_ife_hw_mgr_handle_hw_err( else if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) error_event_data.error_type = CAM_ISP_HW_ERROR_BUSIF_OVERFLOW; + spin_lock(&g_ife_hw_mgr.ctx_lock); + if (event_info->err_type == CAM_ISP_HW_ERROR_CSID_FATAL) { + rc = cam_ife_hw_mgr_handle_csid_event(event_info); + spin_unlock(&g_ife_hw_mgr.ctx_lock); + return rc; + } + core_idx = event_info->hw_idx; if (g_ife_hw_mgr.debug_cfg.enable_recovery) @@ -7454,6 +7503,8 @@ static int cam_ife_hw_mgr_handle_hw_err( rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, core_idx, &recovery_data); + if ((rc != 0) || !(recovery_data.no_of_context)) + goto end; if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) recovery_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; @@ -7461,7 +7512,8 @@ static int cam_ife_hw_mgr_handle_hw_err( recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; cam_ife_hw_mgr_do_error_recovery(&recovery_data); - +end: + spin_unlock(&g_ife_hw_mgr.ctx_lock); return rc; } @@ -7849,6 +7901,9 @@ static int cam_ife_hw_mgr_debug_register(void) dbgfileptr = debugfs_create_bool("enable_req_dump", 0644, g_ife_hw_mgr.debug_cfg.dentry, &g_ife_hw_mgr.debug_cfg.enable_req_dump); + dbgfileptr = debugfs_create_u32("enable_csid_recovery", 0644, + g_ife_hw_mgr.debug_cfg.dentry, + &g_ife_hw_mgr.debug_cfg.enable_csid_recovery); dbgfileptr = debugfs_create_file("ife_camif_debug", 0644, g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_camif_debug); dbgfileptr = debugfs_create_bool("per_req_reg_dump", 0644, @@ -7881,6 +7936,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr)); mutex_init(&g_ife_hw_mgr.ctx_mutex); + spin_lock_init(&g_ife_hw_mgr.ctx_lock); if (CAM_IFE_HW_NUM_MAX != CAM_IFE_CSID_HW_NUM_MAX) { CAM_ERR(CAM_ISP, "CSID num is different then IFE num"); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index ca1648d616c5..5fd66dbb069d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -38,6 +38,7 @@ enum cam_ife_res_master_slave { * @dentry: Debugfs entry * @csid_debug: csid debug information * @enable_recovery: enable recovery + * @enable_csid_recovery: enable csid recovery * @enable_diag_sensor_status: enable sensor diagnosis status * @enable_req_dump: Enable request dump on HW errors * @per_req_reg_dump: Enable per request reg dump @@ -47,6 +48,7 @@ struct cam_ife_hw_mgr_debug { struct dentry *dentry; uint64_t csid_debug; uint32_t enable_recovery; + uint32_t enable_csid_recovery; uint32_t camif_debug; bool enable_req_dump; bool per_req_reg_dump; @@ -199,6 +201,7 @@ struct cam_ife_hw_mgr { struct cam_vfe_hw_get_hw_cap ife_dev_caps[CAM_IFE_HW_NUM_MAX]; struct cam_req_mgr_core_workq *workq; struct cam_ife_hw_mgr_debug debug_cfg; + spinlock_t ctx_lock; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 2ed1f8b211c1..216b84b70698 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -53,6 +53,7 @@ enum cam_isp_hw_err_type { CAM_ISP_HW_ERROR_P2I_ERROR, CAM_ISP_HW_ERROR_VIOLATION, CAM_ISP_HW_ERROR_BUSIF_OVERFLOW, + CAM_ISP_HW_ERROR_CSID_FATAL, CAM_ISP_HW_ERROR_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 9be459f8ee74..9f0779c0ee99 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -12,6 +12,7 @@ #include #include +#include "cam_isp_hw_mgr_intf.h" #include "cam_ife_csid_core.h" #include "cam_isp_hw.h" #include "cam_soc_util.h" @@ -19,6 +20,7 @@ #include "cam_debug_util.h" #include "cam_cpas_api.h" #include "cam_subdev.h" +#include "cam_tasklet_util.h" /* Timeout value in msec */ #define IFE_CSID_TIMEOUT 1000 @@ -1227,6 +1229,8 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, reserve->res_id, path_data->width, path_data->height); reserve->node_res = res; + csid_hw->event_cb = reserve->event_cb; + csid_hw->priv = reserve->priv; end: return rc; @@ -1327,8 +1331,10 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) csid_hw->csid_info->hw_reg_version); spin_lock_irqsave(&csid_hw->lock_state, flags); + csid_hw->fatal_err_detected = false; csid_hw->device_enabled = 1; spin_unlock_irqrestore(&csid_hw->lock_state, flags); + cam_tasklet_start(csid_hw->tasklet); return 0; @@ -1381,6 +1387,7 @@ 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); + cam_tasklet_stop(csid_hw->tasklet); spin_lock_irqsave(&csid_hw->lock_state, flags); csid_hw->device_enabled = 0; spin_unlock_irqrestore(&csid_hw->lock_state, flags); @@ -3353,6 +3360,8 @@ int cam_ife_csid_release(void *hw_priv, res = (struct cam_isp_resource_node *)release_args; mutex_lock(&csid_hw->hw_info->hw_mutex); + csid_hw->event_cb = NULL; + csid_hw->priv = NULL; if ((res->res_type == CAM_ISP_RESOURCE_CID && res->res_id >= CAM_IFE_CSID_CID_MAX) || (res->res_type == CAM_ISP_RESOURCE_PIX_PATH && @@ -4165,16 +4174,208 @@ static int cam_ife_csid_process_cmd(void *hw_priv, } +static int cam_csid_get_evt_payload( + struct cam_ife_csid_hw *csid_hw, + struct cam_csid_evt_payload **evt_payload) +{ + + spin_lock(&csid_hw->lock_state); + + if (list_empty(&csid_hw->free_payload_list)) { + *evt_payload = NULL; + spin_unlock(&csid_hw->lock_state); + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload core %d", + csid_hw->hw_intf->hw_idx); + return -ENOMEM; + } + + *evt_payload = list_first_entry(&csid_hw->free_payload_list, + struct cam_csid_evt_payload, list); + list_del_init(&(*evt_payload)->list); + spin_unlock(&csid_hw->lock_state); + + return 0; +} + +static int cam_csid_put_evt_payload( + struct cam_ife_csid_hw *csid_hw, + struct cam_csid_evt_payload **evt_payload) +{ + unsigned long flags; + + if (*evt_payload == NULL) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid payload core %d", + csid_hw->hw_intf->hw_idx); + return -EINVAL; + } + spin_lock_irqsave(&csid_hw->lock_state, flags); + list_add_tail(&(*evt_payload)->list, + &csid_hw->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&csid_hw->lock_state, flags); + + return 0; +} +static char *cam_csid_status_to_str(uint32_t status) +{ + switch (status) { + case CAM_IFE_CSID_IRQ_REG_TOP: + return "TOP"; + case CAM_IFE_CSID_IRQ_REG_RX: + return "RX"; + case CAM_IFE_CSID_IRQ_REG_IPP: + return "IPP"; + case CAM_IFE_CSID_IRQ_REG_PPP: + return "PPP"; + case CAM_IFE_CSID_IRQ_REG_RDI_0: + return "RDI0"; + case CAM_IFE_CSID_IRQ_REG_RDI_1: + return "RDI1"; + case CAM_IFE_CSID_IRQ_REG_RDI_2: + return "RDI2"; + case CAM_IFE_CSID_IRQ_REG_RDI_3: + return "RDI3"; + case CAM_IFE_CSID_IRQ_REG_UDI_0: + return "UDI0"; + case CAM_IFE_CSID_IRQ_REG_UDI_1: + return "UDI1"; + case CAM_IFE_CSID_IRQ_REG_UDI_2: + return "UDI2"; + default: + return "Invalid IRQ"; + } +} + +static int cam_csid_evt_bottom_half_handler( + void *handler_priv, + void *evt_payload_priv) +{ + struct cam_ife_csid_hw *csid_hw; + struct cam_csid_evt_payload *evt_payload; + int i; + int rc = 0; + struct cam_isp_hw_event_info event_info; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, + "Invalid Param handler_priv %pK evt_payload_priv %pK", + handler_priv, evt_payload_priv); + return 0; + } + + csid_hw = (struct cam_ife_csid_hw *)handler_priv; + evt_payload = (struct cam_csid_evt_payload *)evt_payload_priv; + + if (!csid_hw->event_cb || !csid_hw->priv) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "hw_idx %d Invalid args %pK %pK", + csid_hw->hw_intf->hw_idx, + csid_hw->event_cb, + csid_hw->priv); + goto end; + } + + if (csid_hw->priv != evt_payload->priv) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "hw_idx %d priv mismatch %pK, %pK", + csid_hw->hw_intf->hw_idx, + csid_hw->priv, + evt_payload->priv); + goto end; + } + + CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d cnt %d", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type, + csid_hw->csi2_rx_cfg.phy_sel, + csid_hw->csi2_cfg_cnt); + + for (i = 0; i < CAM_IFE_CSID_IRQ_REG_MAX; i++) + CAM_ERR_RATE_LIMIT(CAM_ISP, "status %s: %x", + cam_csid_status_to_str(i), + evt_payload->irq_status[i]); + + /* this hunk can be extended to handle more cases + * which we want to offload to bottom half from + * irq handlers + */ + event_info.err_type = evt_payload->evt_type; + event_info.hw_idx = evt_payload->hw_idx; + + switch (evt_payload->evt_type) { + case CAM_ISP_HW_ERROR_CSID_FATAL: + if (csid_hw->fatal_err_detected) + break; + csid_hw->fatal_err_detected = true; + rc = csid_hw->event_cb(NULL, + CAM_ISP_HW_EVENT_ERROR, (void *)&event_info); + break; + + default: + CAM_DBG(CAM_ISP, "CSID[%d] invalid error type %d", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type); + break; + } +end: + cam_csid_put_evt_payload(csid_hw, &evt_payload); + return 0; +} + +static int cam_csid_handle_hw_err_irq( + struct cam_ife_csid_hw *csid_hw, + int evt_type, + uint32_t *irq_status) +{ + int rc = 0; + int i; + void *bh_cmd = NULL; + struct cam_csid_evt_payload *evt_payload; + + CAM_DBG(CAM_ISP, "CSID[%d] error %d", + csid_hw->hw_intf->hw_idx, evt_type); + + rc = cam_csid_get_evt_payload(csid_hw, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No free payload core %d", + csid_hw->hw_intf->hw_idx); + return rc; + } + + rc = tasklet_bh_api.get_bh_payload_func(csid_hw->tasklet, &bh_cmd); + if (rc || !bh_cmd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID[%d] Can not get cmd for tasklet, evt_type %d", + csid_hw->hw_intf->hw_idx, + evt_type); + return rc; + } + + evt_payload->evt_type = evt_type; + evt_payload->priv = csid_hw->priv; + evt_payload->hw_idx = csid_hw->hw_intf->hw_idx; + + for (i = 0; i < CAM_IFE_CSID_IRQ_REG_MAX; i++) + evt_payload->irq_status[i] = irq_status[i]; + + tasklet_bh_api.bottom_half_enqueue_func(csid_hw->tasklet, + bh_cmd, + csid_hw, + evt_payload, + cam_csid_evt_bottom_half_handler); + + return rc; +} + irqreturn_t cam_ife_csid_irq(int irq_num, void *data) { struct cam_ife_csid_hw *csid_hw; struct cam_hw_soc_info *soc_info; const struct cam_ife_csid_reg_offset *csid_reg; const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg; - uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0; - uint32_t irq_status_rdi[CAM_IFE_CSID_RDI_MAX] = {0, 0, 0, 0}; - uint32_t irq_status_udi[CAM_IFE_CSID_UDI_MAX] = {0, 0, 0}; - uint32_t val, val2, irq_status_ppp = 0; + uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX] = {0}; + uint32_t i, val, val2; bool fatal_err_detected = false; uint32_t sof_irq_debug_en = 0; unsigned long flags; @@ -4193,23 +4394,27 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csi2_reg = csid_reg->csi2_reg; /* read */ - irq_status_top = cam_io_r_mb(soc_info->reg_map[0].mem_base + + irq_status[CAM_IFE_CSID_IRQ_REG_TOP] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_status_addr); - irq_status_rx = cam_io_r_mb(soc_info->reg_map[0].mem_base + + irq_status[CAM_IFE_CSID_IRQ_REG_RX] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_status_addr); if (csid_reg->cmn_reg->num_pix) - irq_status_ipp = cam_io_r_mb(soc_info->reg_map[0].mem_base + + irq_status[CAM_IFE_CSID_IRQ_REG_IPP] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_irq_status_addr); if (csid_reg->cmn_reg->num_ppp) - irq_status_ppp = cam_io_r_mb(soc_info->reg_map[0].mem_base + + irq_status[CAM_IFE_CSID_IRQ_REG_PPP] = + cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_irq_status_addr); if (csid_reg->cmn_reg->num_rdis <= CAM_IFE_CSID_RDI_MAX) { for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { - irq_status_rdi[i] = + irq_status[i] = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr); } @@ -4217,7 +4422,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if (csid_reg->cmn_reg->num_udis <= CAM_IFE_CSID_UDI_MAX) { for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { - irq_status_udi[i] = + irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->udi_reg[i]->csid_udi_irq_status_addr); } @@ -4225,22 +4430,26 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) spin_lock_irqsave(&csid_hw->hw_info->hw_lock, flags); /* clear */ - cam_io_w_mb(irq_status_top, soc_info->reg_map[0].mem_base + + cam_io_w_mb(irq_status[CAM_IFE_CSID_IRQ_REG_TOP], + soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_clear_addr); - cam_io_w_mb(irq_status_rx, soc_info->reg_map[0].mem_base + + cam_io_w_mb(irq_status[CAM_IFE_CSID_IRQ_REG_RX], + soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr); if (csid_reg->cmn_reg->num_pix) - cam_io_w_mb(irq_status_ipp, soc_info->reg_map[0].mem_base + + cam_io_w_mb(irq_status[CAM_IFE_CSID_IRQ_REG_IPP], + soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_irq_clear_addr); if (csid_reg->cmn_reg->num_ppp) - cam_io_w_mb(irq_status_ppp, soc_info->reg_map[0].mem_base + + cam_io_w_mb(irq_status[CAM_IFE_CSID_IRQ_REG_PPP], + soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_irq_clear_addr); if (csid_reg->cmn_reg->num_rdis <= CAM_IFE_CSID_RDI_MAX) { for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { - cam_io_w_mb(irq_status_rdi[i], + cam_io_w_mb(irq_status[i], soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr); } @@ -4248,7 +4457,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if (csid_reg->cmn_reg->num_udis <= CAM_IFE_CSID_UDI_MAX) { for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { - cam_io_w_mb(irq_status_udi[i], + cam_io_w_mb(irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i], soc_info->reg_map[0].mem_base + csid_reg->udi_reg[i]->csid_udi_irq_clear_addr); } @@ -4259,18 +4468,24 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) spin_unlock_irqrestore(&csid_hw->hw_info->hw_lock, flags); - CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", irq_status_top); - CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx); - CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp); - CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", irq_status_ppp); + CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", + irq_status[CAM_IFE_CSID_IRQ_REG_TOP]); + CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", + irq_status[CAM_IFE_CSID_IRQ_REG_RX]); + CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", + irq_status[CAM_IFE_CSID_IRQ_REG_IPP]); + CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", + irq_status[CAM_IFE_CSID_IRQ_REG_PPP]); CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x irq_status_rdi1= 0x%x irq_status_rdi2= 0x%x", - irq_status_rdi[0], irq_status_rdi[1], irq_status_rdi[2]); + irq_status[0], irq_status[1], irq_status[2]); CAM_DBG(CAM_ISP, "irq_status_udi0= 0x%x irq_status_udi1= 0x%x irq_status_udi2= 0x%x", - irq_status_udi[0], irq_status_udi[1], irq_status_udi[2]); + irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0], + irq_status[CAM_IFE_CSID_IRQ_REG_UDI_1], + irq_status[CAM_IFE_CSID_IRQ_REG_UDI_2]); - if (irq_status_top & CSID_TOP_IRQ_DONE) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_TOP] & CSID_TOP_IRQ_DONE) { CAM_DBG(CAM_ISP, "csid top reset complete"); complete(&csid_hw->csid_top_complete); csid_hw->is_resetting = false; @@ -4283,78 +4498,99 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) return IRQ_HANDLED; } - if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "csi rx reset complete"); complete(&csid_hw->csid_csi2_complete); } 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) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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; + goto handle_fatal_error; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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; + goto handle_fatal_error; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + csid_hw->hw_intf->hw_idx); fatal_err_detected = true; + goto handle_fatal_error; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + csid_hw->hw_intf->hw_idx); fatal_err_detected = true; + goto handle_fatal_error; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + csid_hw->hw_intf->hw_idx); fatal_err_detected = true; + goto handle_fatal_error; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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->hw_intf->hw_idx); csid_hw->error_irq_count++; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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->hw_intf->hw_idx); csid_hw->error_irq_count++; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_ERROR_CRC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC", - csid_hw->hw_intf->hw_idx); + csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_ERROR_ECC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC", - csid_hw->hw_intf->hw_idx); + csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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->hw_intf->hw_idx); csid_hw->error_irq_count++; } - if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_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->hw_intf->hw_idx); csid_hw->error_irq_count++; } } + +handle_fatal_error: spin_unlock_irqrestore(&csid_hw->lock_state, flags); if (csid_hw->error_irq_count > @@ -4363,26 +4599,33 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->error_irq_count = 0; } - if (fatal_err_detected) + if (fatal_err_detected) { cam_ife_csid_halt_csi2(csid_hw); + cam_csid_handle_hw_err_irq(csid_hw, + CAM_ISP_HW_ERROR_CSID_FATAL, irq_status); + } if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) { - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL0_EOT_CAPTURED", csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL1_EOT_CAPTURED", csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL2_EOT_CAPTURED", csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL3_EOT_CAPTURED", csid_hw->hw_intf->hw_idx); @@ -4390,22 +4633,26 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOT_IRQ) { - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL0_SOT_CAPTURED", csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL1_SOT_CAPTURED", csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL2_SOT_CAPTURED", csid_hw->hw_intf->hw_idx); } - if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PHY_DL3_SOT_CAPTURED", csid_hw->hw_intf->hw_idx); @@ -4413,7 +4660,9 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) && - (irq_status_rx & CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED)) { + (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d LONG_PKT_CAPTURED", csid_hw->hw_intf->hw_idx); val = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -4433,7 +4682,9 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->hw_intf->hw_idx, (val >> 16), (val & 0xFFFF)); } if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) && - (irq_status_rx & CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED)) { + (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED)) { + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d SHORT_PKT_CAPTURED", csid_hw->hw_intf->hw_idx); val = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -4449,7 +4700,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) && - (irq_status_rx & CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED)) { + (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED)) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PKT_HDR_CAPTURED", csid_hw->hw_intf->hw_idx); val = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -4463,14 +4715,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) /*read the IPP errors */ if (csid_reg->cmn_reg->num_pix) { /* IPP reset done bit */ - if (irq_status_ipp & + if (irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "CSID:%d IPP reset complete", csid_hw->hw_intf->hw_idx); complete(&csid_hw->csid_ipp_complete); } - if ((irq_status_ipp & CSID_PATH_INFO_INPUT_SOF) && + if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP SOF received", csid_hw->hw_intf->hw_idx); @@ -4478,22 +4731,26 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->irq_debug_cnt++; } - if ((irq_status_ipp & CSID_PATH_INFO_INPUT_EOF) && + if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) 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)) + if ((irq_status[CAM_IFE_CSID_IRQ_REG_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_OVERFLOW_RECOVERY)) + if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP Overflow due to back pressure", csid_hw->hw_intf->hw_idx); - if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_ERROR_FIFO_OVERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d IPP fifo over flow", csid_hw->hw_intf->hw_idx); @@ -4503,14 +4760,17 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_reg->ipp_reg->csid_pxl_ctrl_addr); } - if ((irq_status_ipp & CSID_PATH_ERROR_PIX_COUNT) || - (irq_status_ipp & CSID_PATH_ERROR_LINE_COUNT)) { + if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_ERROR_PIX_COUNT) || + (irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_ERROR_LINE_COUNT)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_format_measure0_addr); CAM_ERR(CAM_ISP, "CSID:%d irq_status_ipp:0x%x", - csid_hw->hw_intf->hw_idx, irq_status_ipp); + csid_hw->hw_intf->hw_idx, + irq_status[CAM_IFE_CSID_IRQ_REG_IPP]); CAM_ERR(CAM_ISP, "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", csid_hw->ipp_path_config.height, @@ -4526,14 +4786,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) /*read PPP errors */ if (csid_reg->cmn_reg->num_ppp) { /* PPP reset done bit */ - if (irq_status_ppp & + if (irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "CSID:%d PPP reset complete", csid_hw->hw_intf->hw_idx); complete(&csid_hw->csid_ppp_complete); } - if ((irq_status_ppp & CSID_PATH_INFO_INPUT_SOF) && + if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP SOF received", csid_hw->hw_intf->hw_idx); @@ -4541,22 +4802,26 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->irq_debug_cnt++; } - if ((irq_status_ppp & CSID_PATH_INFO_INPUT_EOF) && + if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received", csid_hw->hw_intf->hw_idx); - if ((irq_status_ppp & CSID_PATH_ERROR_CCIF_VIOLATION)) + if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + 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_OVERFLOW_RECOVERY)) + if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP Overflow due to back pressure", csid_hw->hw_intf->hw_idx); - if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_ERROR_FIFO_OVERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d PPP fifo over flow", csid_hw->hw_intf->hw_idx); @@ -4566,14 +4831,17 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_reg->ppp_reg->csid_pxl_ctrl_addr); } - if ((irq_status_ppp & CSID_PATH_ERROR_PIX_COUNT) || - (irq_status_ppp & CSID_PATH_ERROR_LINE_COUNT)) { + if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_ERROR_PIX_COUNT) || + (irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_ERROR_LINE_COUNT)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_format_measure0_addr); CAM_ERR(CAM_ISP, "CSID:%d irq_status_ppp:0x%x", - csid_hw->hw_intf->hw_idx, irq_status_ppp); + csid_hw->hw_intf->hw_idx, + irq_status[CAM_IFE_CSID_IRQ_REG_PPP]); CAM_ERR(CAM_ISP, "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", csid_hw->ppp_path_config.height, @@ -4587,14 +4855,14 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { - if (irq_status_rdi[i] & + if (irq_status[i] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "CSID:%d RDI%d reset complete", csid_hw->hw_intf->hw_idx, i); complete(&csid_hw->csid_rdin_complete[i]); } - if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_SOF) && + if ((irq_status[i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d RDI:%d SOF received", @@ -4603,23 +4871,23 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->irq_debug_cnt++; } - if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF) && + if ((irq_status[i] & CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d RDI:%d EOF received", csid_hw->hw_intf->hw_idx, i); - if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) + if ((irq_status[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d RDI :%d CCIF violation", csid_hw->hw_intf->hw_idx, i); - if ((irq_status_rdi[i] & CSID_PATH_OVERFLOW_RECOVERY)) + if ((irq_status[i] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d RDI :%d Overflow due to back pressure", csid_hw->hw_intf->hw_idx, i); - if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { + if (irq_status[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d RDI fifo over flow", csid_hw->hw_intf->hw_idx); @@ -4629,8 +4897,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); } - if ((irq_status_rdi[i] & CSID_PATH_ERROR_PIX_COUNT) || - (irq_status_rdi[i] & CSID_PATH_ERROR_LINE_COUNT)) { + if ((irq_status[i] & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status[i] & CSID_PATH_ERROR_LINE_COUNT)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_format_measure0_addr); val2 = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -4638,7 +4906,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) ); CAM_ERR(CAM_ISP, "CSID:%d irq_status_rdi[%d]:0x%x", - csid_hw->hw_intf->hw_idx, i, irq_status_rdi[i]); + csid_hw->hw_intf->hw_idx, i, irq_status[i]); CAM_ERR(CAM_ISP, "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", ((val2 >> @@ -4655,14 +4923,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) } for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { - if (irq_status_udi[i] & + if (irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { CAM_DBG(CAM_ISP, "CSID:%d UDI%d reset complete", csid_hw->hw_intf->hw_idx, i); complete(&csid_hw->csid_udin_complete[i]); } - if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_SOF) && + if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & + CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d UDI:%d SOF received", @@ -4671,23 +4940,27 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->irq_debug_cnt++; } - if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_EOF) && + if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & + CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)) CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d UDI:%d EOF received", csid_hw->hw_intf->hw_idx, i); - if ((irq_status_udi[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) + if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & + CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_WARN_RATE_LIMIT(CAM_ISP, "CSID:%d UDI :%d CCIF violation", csid_hw->hw_intf->hw_idx, i); - if ((irq_status_udi[i] & CSID_PATH_OVERFLOW_RECOVERY)) + if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & + CSID_PATH_OVERFLOW_RECOVERY)) CAM_WARN_RATE_LIMIT(CAM_ISP, "CSID:%d UDI :%d Overflow due to back pressure", csid_hw->hw_intf->hw_idx, i); - if (irq_status_udi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { + if (irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & + CSID_PATH_ERROR_FIFO_OVERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UDI fifo over flow", csid_hw->hw_intf->hw_idx); @@ -4867,6 +5140,19 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->udi_res[i].res_priv = path_data; } + rc = cam_tasklet_init(&ife_csid_hw->tasklet, ife_csid_hw, csid_idx); + if (rc) { + CAM_ERR(CAM_ISP, "Unable to create CSID tasklet rc %d", rc); + goto err; + } + + INIT_LIST_HEAD(&ife_csid_hw->free_payload_list); + for (i = 0; i < CAM_CSID_EVT_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&ife_csid_hw->evt_payload[i].list); + list_add_tail(&ife_csid_hw->evt_payload[i].list, + &ife_csid_hw->free_payload_list); + } + ife_csid_hw->csid_debug = 0; ife_csid_hw->error_irq_count = 0; ife_csid_hw->ipp_path_config.measure_enabled = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 793e2217ffdb..6854e9767917 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -72,6 +72,8 @@ #define CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7) #define CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) +#define CAM_CSID_EVT_PAYLOAD_MAX 10 + /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_csid_path_halt_mode { CSID_HALT_MODE_INTERNAL, @@ -91,6 +93,24 @@ enum cam_csid_path_timestamp_stb_sel { CSID_TIMESTAMP_STB_MAX, }; +/** + * enum cam_ife_pix_path_res_id - Specify the csid patch + */ +enum cam_ife_csid_irq_reg { + CAM_IFE_CSID_IRQ_REG_RDI_0, + CAM_IFE_CSID_IRQ_REG_RDI_1, + CAM_IFE_CSID_IRQ_REG_RDI_2, + CAM_IFE_CSID_IRQ_REG_RDI_3, + CAM_IFE_CSID_IRQ_REG_TOP, + CAM_IFE_CSID_IRQ_REG_RX, + CAM_IFE_CSID_IRQ_REG_IPP, + CAM_IFE_CSID_IRQ_REG_PPP, + CAM_IFE_CSID_IRQ_REG_UDI_0, + CAM_IFE_CSID_IRQ_REG_UDI_1, + CAM_IFE_CSID_IRQ_REG_UDI_2, + CAM_IFE_CSID_IRQ_REG_MAX, +}; + struct cam_ife_csid_pxl_reg_offset { /* Pxl path register offsets*/ uint32_t csid_pxl_irq_status_addr; @@ -525,12 +545,32 @@ struct cam_ife_csid_path_cfg { uint32_t num_bytes_out; }; +/** + * struct cam_csid_evt_payload- payload for csid hw event + * @list : list head + * @evt_type : Event type from CSID + * @irq_status : IRQ Status register + * @hw_idx : Hw index + * @priv : Private data of payload + */ +struct cam_csid_evt_payload { + struct list_head list; + uint32_t evt_type; + uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX]; + uint32_t hw_idx; + void *priv; +}; + /** * struct cam_ife_csid_hw- csid hw device resources data * * @hw_intf: contain the csid hw interface information * @hw_info: csid hw device information * @csid_info: csid hw specific information + * @tasklet: tasklet to handle csid errors + * @priv: private data to be sent with callback + * @free_payload_list: list head for payload + * @evt_payload: Event payload to be passed to tasklet * @res_type: CSID in resource type * @csi2_rx_cfg: Csi2 rx decoder configuration for csid * @tpg_cfg: TPG configuration @@ -562,11 +602,17 @@ struct cam_ife_csid_path_cfg { * @first_sof_ts first bootime stamp at the start * @prev_qtimer_ts stores csid timestamp * @epd_supported Flag is set if sensor supports EPD + * @fatal_err_detected flag to indicate fatal errror is reported + * @event_cb Callback to hw manager if CSID event reported */ struct cam_ife_csid_hw { struct cam_hw_intf *hw_intf; struct cam_hw_info *hw_info; struct cam_ife_csid_hw_info *csid_info; + void *tasklet; + void *priv; + struct list_head free_payload_list; + struct cam_csid_evt_payload evt_payload[CAM_CSID_EVT_PAYLOAD_MAX]; uint32_t res_type; struct cam_ife_csid_csi2_rx_cfg csi2_rx_cfg; struct cam_ife_csid_tpg_cfg tpg_cfg; @@ -602,6 +648,8 @@ struct cam_ife_csid_hw { uint64_t prev_boot_timestamp; uint64_t prev_qtimer_ts; uint32_t epd_supported; + bool fatal_err_detected; + cam_hw_mgr_event_cb_func event_cb; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 2d821ee42836..a399d2fdc479 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -125,6 +125,8 @@ struct cam_isp_in_port_generic_info { * @node_res : Reserved resource structure pointer * @crop_enable : Flag to indicate CSID crop enable * @drop_enable : Flag to indicate CSID drop enable + * @priv: private data to be sent in callback + * @event_cb: CSID event callback to hw manager * */ struct cam_csid_hw_reserve_resource_args { @@ -138,6 +140,8 @@ struct cam_csid_hw_reserve_resource_args { struct cam_isp_resource_node *node_res; bool crop_enable; bool drop_enable; + void *priv; + cam_hw_mgr_event_cb_func event_cb; }; /** diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 241fd671f624..58071bc3419e 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -430,6 +430,8 @@ struct cam_mem_cache_ops_cmd { #define CAM_REQ_MGR_ERROR_TYPE_BUFFER 2 #define CAM_REQ_MGR_ERROR_TYPE_RECOVERY 3 #define CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE 4 +#define CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY 5 + /** * struct cam_req_mgr_error_msg From c515d1506d39da0c578710f95b986106fee9d2b4 Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Tue, 14 Jul 2020 15:59:26 +0530 Subject: [PATCH 423/790] msm: camera: cci: Fix invalid queue size for cci The queue size of cci hw version 1.2.9 is 64 and 16. Due to wrong conditional check the cci queue size is assigned wrongly for cci version 1.2.9. This change corrects the cci queue size for cci version 1.2.9. CRs-Fixed: 2736884 Change-Id: I60508fadec89831f3b877d64631b7da6304c030d Signed-off-by: Tony Lijo Jose --- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index ce0b8de81316..302983958780 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -17,7 +17,7 @@ static int cam_cci_init_master(struct cci_device *cci_dev, soc_info = &cci_dev->soc_info; base = soc_info->reg_map[0].mem_base; - if (cci_dev->hw_version != CCI_VERSION_1_2_9) { + if (cci_dev->hw_version == CCI_VERSION_1_2_9) { max_queue_0_size = CCI_I2C_QUEUE_0_SIZE_V_1_2; max_queue_1_size = CCI_I2C_QUEUE_1_SIZE_V_1_2; } else { From a6321e50af4632fa3e9dd093affdb0beacb957c9 Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Tue, 30 Jun 2020 14:50:43 +0530 Subject: [PATCH 424/790] msm: camera: cci: reset reinit completion on read Reinit completion rd_done completion variable before each read so that the rd_done completion variable state will be clean . CRs-Fixed: 2736884 Change-Id: I2cd7350da8e8270c1cd9238dec0eec9f84360899 Signed-off-by: Tony Lijo Jose --- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 647edaf34256..af1cd28144ff 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1642,6 +1642,7 @@ static int32_t cam_cci_read_bytes_v_1_2(struct v4l2_subdev *sd, goto ERROR; } + reinit_completion(&cci_dev->cci_master_info[master].rd_done); read_bytes = read_cfg->num_byte; CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes); do { From a7b73974d0d30ac923191d54b2718c657b090c3f Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 15 Jul 2020 15:09:09 -0700 Subject: [PATCH 425/790] msm: camera: reqmgr: Defer probe when master is not ready Some sensor drivers that are not slaves to CRM, can probe earlier than the master bind call. Return EPROBE_DEFER when camera v4l2 root device is not ready. CRs-Fixed: 2734061 Change-Id: I5a1162f38526fc7f95127b4163183aa66f213d8f Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_req_mgr/cam_req_mgr_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 6f4c0e6baa08..6043f2999323 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -664,8 +664,8 @@ int cam_register_subdev(struct cam_subdev *csd) int rc; if (!g_dev.state) { - CAM_ERR(CAM_CRM, "camera root device not ready yet"); - return -ENODEV; + CAM_DBG(CAM_CRM, "camera root device not ready yet"); + return -EPROBE_DEFER; } if (!csd || !csd->name) { From 2ed641f535c3838c979c4b5a6b83698eac25c0f2 Mon Sep 17 00:00:00 2001 From: Divya Sharma Date: Tue, 21 Jul 2020 12:34:42 -0700 Subject: [PATCH 426/790] Revert "msm: camera: common: Enable debugfs compile check." This reverts commit cf8074099294d9e80be43d7a6278004d2fe11e7c. Change-Id: Ib8d6808ed0072ce5c8ff14cd5b3ae3a597a51008 Signed-off-by: Divya Sharma --- drivers/cam_cpas/cam_cpas_hw.c | 39 ++++---- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 99 +++++++++++++------ drivers/cam_isp/cam_isp_context.c | 34 +++---- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 77 +++++++++------ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 75 +++++++++----- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 31 +++--- drivers/cam_req_mgr/cam_mem_mgr.c | 34 +++---- drivers/cam_req_mgr/cam_req_mgr_debug.c | 49 +++++---- drivers/cam_smmu/cam_smmu_api.c | 45 +++++---- drivers/cam_sync/cam_sync.c | 29 +++--- drivers/cam_utils/cam_soc_util.c | 58 ++++++----- 11 files changed, 324 insertions(+), 246 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 2aa68d52d6fe..c864a7fb286a 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -2025,31 +2025,32 @@ static int cam_cpas_util_get_internal_ops(struct platform_device *pdev, return rc; } -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_cpas_util_create_debugfs( struct cam_cpas *cpas_core) { int rc = 0; cpas_core->dentry = debugfs_create_dir("camera_cpas", NULL); - if (IS_ERR(cpas_core->dentry)) { - rc = PTR_ERR(cpas_core->dentry); - goto end; - } - - debugfs_create_bool("ahb_bus_scaling_disable", 0644, cpas_core->dentry, - &cpas_core->ahb_bus_scaling_disable); + if (!cpas_core->dentry) + return -ENOMEM; -end: + if (!debugfs_create_bool("ahb_bus_scaling_disable", + 0644, + cpas_core->dentry, + &cpas_core->ahb_bus_scaling_disable)) { + CAM_ERR(CAM_CPAS, + "failed to create ahb_bus_scaling_disable entry"); + rc = -ENOMEM; + goto err; + } + + return 0; + +err: + debugfs_remove_recursive(cpas_core->dentry); + cpas_core->dentry = NULL; return rc; } -#else -static inline int cam_cpas_util_create_debugfs(struct cam_cpas *cpas_core) -{ - CAM_WARN(CAM_CPAS, "DebugFS not enabled in kernel"); - return 0; -} -#endif int cam_cpas_hw_probe(struct platform_device *pdev, struct cam_hw_intf **hw_intf) @@ -2194,7 +2195,9 @@ int cam_cpas_hw_probe(struct platform_device *pdev, if (rc) goto axi_cleanup; - rc = cam_cpas_util_create_debugfs(cpas_core); + rc = cam_cpas_util_create_debugfs(cpas_core); + if (rc) + CAM_WARN(CAM_CPAS, "Failed to create dentry"); *hw_intf = cpas_hw_intf; return 0; @@ -2247,9 +2250,7 @@ int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf) cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client); cam_cpas_util_client_cleanup(cpas_hw); cam_cpas_soc_deinit_resources(&cpas_hw->soc_info); -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(cpas_core->dentry); -#endif cpas_core->dentry = NULL; flush_workqueue(cpas_core->work_queue); destroy_workqueue(cpas_core->work_queue); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 1a233ef10e65..268256d8a438 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1882,51 +1882,87 @@ static int cam_icp_get_a5_fw_dump_lvl(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_a5_fw_dump_lvl, cam_icp_set_a5_fw_dump_lvl, "%08llu"); -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_icp_hw_mgr_create_debugfs_entry(void) { int rc = 0; icp_hw_mgr.dentry = debugfs_create_dir("camera_icp", NULL); - if (IS_ERR(icp_hw_mgr.dentry)) { - rc = PTR_ERR(icp_hw_mgr.dentry); - goto end; + if (IS_ERR_OR_NULL(icp_hw_mgr.dentry)) { + CAM_ERR(CAM_ICP, "Debugfs entry dir: %s failed", + "camrea_icp"); + return -ENOMEM; } - debugfs_create_bool("icp_pc", 0644, icp_hw_mgr.dentry, - &icp_hw_mgr.icp_pc_flag); + if (!debugfs_create_bool("icp_pc", + 0644, + icp_hw_mgr.dentry, + &icp_hw_mgr.icp_pc_flag)) { + CAM_ERR(CAM_ICP, "failed to create icp_pc entry"); + rc = -ENOMEM; + goto err; + } - debugfs_create_bool("ipe_bps_pc", 0644, icp_hw_mgr.dentry, - &icp_hw_mgr.ipe_bps_pc_flag); + if (!debugfs_create_bool("ipe_bps_pc", + 0644, + icp_hw_mgr.dentry, + &icp_hw_mgr.ipe_bps_pc_flag)) { + CAM_ERR(CAM_ICP, "failed to create ipe_bps_pc entry"); + rc = -ENOMEM; + goto err; + } - debugfs_create_file("icp_debug_clk", 0644, icp_hw_mgr.dentry, NULL, - &cam_icp_debug_default_clk); + if (!debugfs_create_file("icp_debug_clk", + 0644, + icp_hw_mgr.dentry, NULL, + &cam_icp_debug_default_clk)) { + CAM_ERR(CAM_ICP, "failed to create icp_debug_clk entry"); + rc = -ENOMEM; + goto err; + } - debugfs_create_bool("a5_jtag_debug", 0644, icp_hw_mgr.dentry, - &icp_hw_mgr.a5_jtag_debug); + if (!debugfs_create_bool("a5_jtag_debug", + 0644, + icp_hw_mgr.dentry, + &icp_hw_mgr.a5_jtag_debug)) { + rc = -ENOMEM; + goto err; + } - debugfs_create_file("a5_debug_type", 0644, icp_hw_mgr.dentry, NULL, - &cam_icp_debug_type_fs); + if (!debugfs_create_file("a5_debug_type", + 0644, + icp_hw_mgr.dentry, + NULL, &cam_icp_debug_type_fs)) { + CAM_ERR(CAM_ICP, "failed to create a5_debug_type"); + rc = -ENOMEM; + goto err; + } - debugfs_create_file("a5_debug_lvl", 0644, icp_hw_mgr.dentry, NULL, - &cam_icp_debug_fs); + if (!debugfs_create_file("a5_debug_lvl", + 0644, + icp_hw_mgr.dentry, + NULL, &cam_icp_debug_fs)) { + CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl"); + rc = -ENOMEM; + goto err; + } + + if (!debugfs_create_file("a5_fw_dump_lvl", + 0644, + icp_hw_mgr.dentry, + NULL, &cam_icp_debug_fw_dump)) { + CAM_ERR(CAM_ICP, "failed to create a5_fw_dump_lvl"); + rc = -ENOMEM; + goto err; + } - debugfs_create_file("a5_fw_dump_lvl", 0644, icp_hw_mgr.dentry, NULL, - &cam_icp_debug_fw_dump); -end: /* Set default hang dump lvl */ icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; return rc; +err: + debugfs_remove_recursive(icp_hw_mgr.dentry); + icp_hw_mgr.dentry = NULL; + return rc; } -#else -static inline int cam_icp_hw_mgr_create_debugfs_entry(void) -{ - /* Set default hang dump lvl */ - icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; - CAM_WARN(CAM_ICP, "DebugFS not enabled in kernel"); - return 0; -} -#endif static int cam_icp_mgr_process_cmd(void *priv, void *data) { @@ -5964,9 +6000,10 @@ static int cam_icp_mgr_create_wq(void) } rc = cam_icp_hw_mgr_create_debugfs_entry(); - if (rc) + if (rc) { + CAM_ERR(CAM_ICP, "create_debugfs_entry fail= rc: %d", rc); goto debugfs_create_failed; - + } for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) icp_hw_mgr.msg_work->task.pool[i].payload = &icp_hw_mgr.msg_work_data[i]; @@ -6137,9 +6174,7 @@ void cam_icp_hw_mgr_deinit(void) { int i = 0; -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(icp_hw_mgr.dentry); -#endif icp_hw_mgr.dentry = NULL; cam_icp_mgr_destroy_wq(); kfree(icp_hw_mgr.devices[CAM_ICP_DEV_BPS]); diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5f54e438421a..71bac56daa40 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5297,30 +5297,30 @@ static int cam_isp_context_dump_active_request(void *data, unsigned long iova, return rc; } -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_isp_context_debug_register(void) { - int rc = 0; + isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", + NULL); - isp_ctx_debug.dentry = debugfs_create_dir("camera_isp_ctx", NULL); - if (IS_ERR(isp_ctx_debug.dentry)) { - rc = PTR_ERR(isp_ctx_debug.dentry); - goto end; + if (IS_ERR_OR_NULL(isp_ctx_debug.dentry)) { + CAM_ERR(CAM_ISP, "failed to create dentry"); + return -ENOMEM; } - debugfs_create_u32("enable_state_monitor_dump", 0644, - isp_ctx_debug.dentry, &isp_ctx_debug.enable_state_monitor_dump); + if (!debugfs_create_u32("enable_state_monitor_dump", + 0644, + isp_ctx_debug.dentry, + &isp_ctx_debug.enable_state_monitor_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_state_monitor_dump"); + goto err; + } -end: - return rc; -} -#else -static inline int cam_isp_context_debug_register(void) -{ - CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); return 0; + +err: + debugfs_remove_recursive(isp_ctx_debug.dentry); + return -ENOMEM; } -#endif int cam_isp_context_init(struct cam_isp_context *ctx, struct cam_context *ctx_base, @@ -5400,9 +5400,7 @@ int cam_isp_context_deinit(struct cam_isp_context *ctx) __cam_isp_ctx_substate_val_to_type( ctx->substate_activated)); -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(isp_ctx_debug.dentry); -#endif isp_ctx_debug.dentry = NULL; memset(ctx, 0, sizeof(*ctx)); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 9bd34db7f216..ca621c9d99bd 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7725,43 +7725,64 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug, cam_ife_get_camif_debug, cam_ife_set_camif_debug, "%16llu"); -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_ife_hw_mgr_debug_register(void) { - int rc = 0; + g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", + NULL); - g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", NULL); - if (IS_ERR(g_ife_hw_mgr.debug_cfg.dentry)) - { - rc = PTR_ERR(g_ife_hw_mgr.debug_cfg.dentry); - goto end; + if (!g_ife_hw_mgr.debug_cfg.dentry) { + CAM_ERR(CAM_ISP, "failed to create dentry"); + return -ENOMEM; } - debugfs_create_file("ife_csid_debug", 0644, - g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_csid_debug); - debugfs_create_u32("enable_recovery", 0644, + if (!debugfs_create_file("ife_csid_debug", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, + &cam_ife_csid_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_ife_csid_debug"); + goto err; + } + + if (!debugfs_create_u32("enable_recovery", + 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.enable_recovery); - debugfs_create_bool("enable_req_dump", 0644, + &g_ife_hw_mgr.debug_cfg.enable_recovery)) { + CAM_ERR(CAM_ISP, "failed to create enable_recovery"); + goto err; + } + + if (!debugfs_create_bool("enable_req_dump", + 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.enable_req_dump); - debugfs_create_file("ife_camif_debug", 0644, - g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_camif_debug); - debugfs_create_bool("per_req_reg_dump", 0644, + &g_ife_hw_mgr.debug_cfg.enable_req_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_req_dump"); + goto err; + } + + if (!debugfs_create_file("ife_camif_debug", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, + &cam_ife_camif_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug"); + goto err; + } + + if (!debugfs_create_bool("per_req_reg_dump", + 0644, g_ife_hw_mgr.debug_cfg.dentry, - &g_ife_hw_mgr.debug_cfg.per_req_reg_dump); -end: + &g_ife_hw_mgr.debug_cfg.per_req_reg_dump)) { + CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); + goto err; + } + g_ife_hw_mgr.debug_cfg.enable_recovery = 0; - return rc; -} -#else -static inline int cam_ife_hw_mgr_debug_register(void) -{ - g_ife_hw_mgr.debug_cfg.enable_recovery = 0; - CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); + return 0; + +err: + debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); + return -ENOMEM; } -#endif int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { @@ -7771,6 +7792,8 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) struct cam_ife_hw_mgr_ctx *ctx_pool; struct cam_isp_hw_mgr_res *res_list_ife_out; + CAM_DBG(CAM_ISP, "Enter"); + memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr)); mutex_init(&g_ife_hw_mgr.ctx_mutex); @@ -7978,9 +8001,7 @@ void cam_ife_hw_mgr_deinit(void) int i = 0; cam_req_mgr_workq_destroy(&g_ife_hw_mgr.workq); -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); -#endif g_ife_hw_mgr.debug_cfg.dentry = NULL; for (i = 0; i < CAM_CTX_MAX; i++) { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index a2697eb15a21..6425088a462c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5263,42 +5263,65 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_camif_debug, cam_tfe_get_camif_debug, cam_tfe_set_camif_debug, "%16llu"); -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_tfe_hw_mgr_debug_register(void) { - int rc = 0; + g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", + NULL); - g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", NULL); - if (IS_ERR(g_tfe_hw_mgr.debug_cfg.dentry)) { - rc = PTR_ERR(g_tfe_hw_mgr.debug_cfg.dentry); - goto end; + if (!g_tfe_hw_mgr.debug_cfg.dentry) { + CAM_ERR(CAM_ISP, "failed to create dentry"); + return -ENOMEM; } - debugfs_create_file("tfe_csid_debug", 0644, - g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_csid_debug); - debugfs_create_u32("enable_recovery", 0644, + if (!debugfs_create_file("tfe_csid_debug", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, + &cam_tfe_csid_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_tfe_csid_debug"); + goto err; + } + + if (!debugfs_create_u32("enable_recovery", + 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.enable_recovery); - debugfs_create_u32("enable_reg_dump", 0644, + &g_tfe_hw_mgr.debug_cfg.enable_recovery)) { + CAM_ERR(CAM_ISP, "failed to create enable_recovery"); + goto err; + } + + if (!debugfs_create_u32("enable_reg_dump", + 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.enable_reg_dump); - debugfs_create_file("tfe_camif_debug", 0644, - g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_camif_debug); - debugfs_create_u32("per_req_reg_dump", 0644, + &g_tfe_hw_mgr.debug_cfg.enable_reg_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_reg_dump"); + goto err; + } + + if (!debugfs_create_file("tfe_camif_debug", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, NULL, + &cam_tfe_camif_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_tfe_camif_debug"); + goto err; + } + + if (!debugfs_create_u32("per_req_reg_dump", + 0644, g_tfe_hw_mgr.debug_cfg.dentry, - &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump); -end: + &g_tfe_hw_mgr.debug_cfg.per_req_reg_dump)) { + CAM_ERR(CAM_ISP, "failed to create per_req_reg_dump entry"); + goto err; + } + + g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; - return rc; -} -#else -static inline int cam_tfe_hw_mgr_debug_register(void) -{ - g_tfe_hw_mgr.debug_cfg.enable_recovery = 0; - CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel"); + return 0; + +err: + debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); + return -ENOMEM; } -#endif int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { @@ -5506,9 +5529,7 @@ void cam_tfe_hw_mgr_deinit(void) int i = 0; cam_req_mgr_workq_destroy(&g_tfe_hw_mgr.workq); -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); -#endif g_tfe_hw_mgr.debug_cfg.dentry = NULL; for (i = 0; i < CAM_CTX_MAX; i++) { diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index a777458966ad..537fc48a619e 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -1013,32 +1013,33 @@ static int cam_lrme_mgr_hw_config(void *hw_mgr_priv, return rc; } -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_lrme_mgr_create_debugfs_entry(void) { int rc = 0; g_lrme_hw_mgr.debugfs_entry.dentry = debugfs_create_dir("camera_lrme", NULL); - if (IS_ERR(g_lrme_hw_mgr.debugfs_entry.dentry)) { - rc = PTR_ERR(g_lrme_hw_mgr.debugfs_entry.dentry); - goto end; + if (!g_lrme_hw_mgr.debugfs_entry.dentry) { + CAM_ERR(CAM_LRME, "failed to create dentry"); + return -ENOMEM; } - debugfs_create_bool("dump_register", 0644, + if (!debugfs_create_bool("dump_register", + 0644, g_lrme_hw_mgr.debugfs_entry.dentry, - &g_lrme_hw_mgr.debugfs_entry.dump_register); + &g_lrme_hw_mgr.debugfs_entry.dump_register)) { + CAM_ERR(CAM_LRME, "failed to create dump register entry"); + rc = -ENOMEM; + goto err; + } + + return rc; err: + debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); + g_lrme_hw_mgr.debugfs_entry.dentry = NULL; return rc; } -#else -static inline int cam_lrme_mgr_create_debugfs_entry(void) -{ - CAM_WARN(CAM_LRME, "DebugFS not enabled in kernel"); - return 0; -} -#endif int cam_lrme_mgr_register_device( @@ -1139,9 +1140,6 @@ int cam_lrme_mgr_deregister_device(int device_index) int cam_lrme_hw_mgr_deinit(void) { mutex_destroy(&g_lrme_hw_mgr.hw_mgr_mutex); -#if IS_ENABLED(CONFIG_DEBUG_FS) - debugfs_remove_recursive(g_lrme_hw_mgr.debugfs_entry.dentry); -#endif memset(&g_lrme_hw_mgr, 0x0, sizeof(g_lrme_hw_mgr)); return 0; @@ -1196,6 +1194,7 @@ int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, hw_mgr_intf->hw_dump = cam_lrme_mgr_hw_dump; cam_lrme_mgr_create_debugfs_entry(); + CAM_DBG(CAM_LRME, "Hw mgr init done"); return rc; } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index e386aac308f3..97a6c8b1b094 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -119,29 +119,28 @@ static int cam_mem_util_unmap_cpu_va(struct dma_buf *dmabuf, return rc; } -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_mem_mgr_create_debug_fs(void) { - int rc = 0; - tbl.dentry = debugfs_create_dir("camera_memmgr", NULL); - if (IS_ERR(tbl.dentry)) { - rc = PTR_ERR(tbl.dentry); - goto end; + if (!tbl.dentry) { + CAM_ERR(CAM_MEM, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_bool("alloc_profile_enable", + 0644, + tbl.dentry, + &tbl.alloc_profile_enable)) { + CAM_ERR(CAM_MEM, + "failed to create alloc_profile_enable"); + goto err; } - debugfs_create_bool("alloc_profile_enable", 0644, tbl.dentry, - &tbl.alloc_profile_enable); -end: - return rc; -} -#else -static inline int cam_mem_mgr_create_debug_fs(void) -{ - CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel"); return 0; +err: + debugfs_remove_recursive(tbl.dentry); + return -ENOMEM; } -#endif int cam_mem_mgr_init(void) { @@ -954,9 +953,6 @@ static int cam_mem_mgr_cleanup_table(void) void cam_mem_mgr_deinit(void) { -#if IS_ENABLED(CONFIG_DEBUG_FS) - debugfs_remove_recursive(tbl.dentry); -#endif atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED); cam_mem_mgr_cleanup_table(); mutex_lock(&tbl.m_lock); diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index eced0037d8fa..6b6a91b6303b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -8,6 +8,7 @@ #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; +static struct dentry *debugfs_root; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { @@ -110,27 +111,32 @@ static const struct file_operations session_info = { .write = session_info_write, }; -#if IS_ENABLED(CONFIG_DEBUG_FS) -static struct dentry *debugfs_root; int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) { - int rc = 0; - - debugfs_root = debugfs_create_dir("cam_req_mgr", NULL); - if (IS_ERR(debugfs_root)) { - rc = PTR_ERR(debugfs_root); - goto end; + char dirname[32] = {0}; + snprintf(dirname, sizeof(dirname), "cam_req_mgr"); + debugfs_root = debugfs_create_dir(dirname, NULL); + if (IS_ERR_OR_NULL(debugfs_root)) { + CAM_ERR(CAM_CRM, "Failed to create cam_req_mgr debugfs dir"); + return -ENOMEM; } - - debugfs_create_file("sessions_info", 0644, debugfs_root, core_dev, - &session_info); - debugfs_create_file("bubble_recovery", 0644, debugfs_root, core_dev, - &bubble_recovery); - debugfs_create_bool("recovery_on_apply_fail", 0644, debugfs_root, - &core_dev->recovery_on_apply_fail); -end: - return rc; + if (!debugfs_create_file("sessions_info", 0644, + debugfs_root, core_dev, &session_info)) + CAM_WARN(CAM_CRM, + "Failed to create sessions_info debugfs file"); + + if (!debugfs_create_file("bubble_recovery", 0644, + debugfs_root, core_dev, &bubble_recovery)) + CAM_WARN(CAM_CRM, + "Failed to create bubble_recovery debugfs file"); + + if (!debugfs_create_bool("recovery_on_apply_fail", + 0644, debugfs_root, + &core_dev->recovery_on_apply_fail)) + CAM_WARN(CAM_CRM, + "Failed to create recovery_on_apply_fail debugfs bool"); + return 0; } void cam_req_mgr_debug_unregister(void) @@ -138,12 +144,3 @@ void cam_req_mgr_debug_unregister(void) if (!debugfs_root) debugfs_remove_recursive(debugfs_root); } -#else -int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) -{ - CAM_WARN(CAM_CRM, "DebugFS not enabled in kernel"); - return 0; -} - -void cam_req_mgr_debug_unregister(void) { }; -#endif diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 1c512aab76ce..61c1ee44a2e9 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3876,32 +3876,39 @@ cb_init_fail: return rc; } -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_smmu_create_debug_fs(void) { - int rc = 0; + iommu_cb_set.dentry = debugfs_create_dir("camera_smmu", + NULL); - iommu_cb_set.dentry = debugfs_create_dir("camera_smmu", NULL); - if (IS_ERR(iommu_cb_set.dentry)) { - rc = PTR_ERR(iommu_cb_set.dentry); - goto end; + if (!iommu_cb_set.dentry) { + CAM_ERR(CAM_SMMU, "failed to create dentry"); + return -ENOMEM; } - debugfs_create_bool("cb_dump_enable", 0644, iommu_cb_set.dentry, - &iommu_cb_set.cb_dump_enable); - debugfs_create_bool("map_profile_enable", 0644, iommu_cb_set.dentry, - &iommu_cb_set.map_profile_enable); + if (!debugfs_create_bool("cb_dump_enable", + 0644, + iommu_cb_set.dentry, + &iommu_cb_set.cb_dump_enable)) { + CAM_ERR(CAM_SMMU, + "failed to create dump_enable_debug"); + goto err; + } + + if (!debugfs_create_bool("map_profile_enable", + 0644, + iommu_cb_set.dentry, + &iommu_cb_set.map_profile_enable)) { + CAM_ERR(CAM_SMMU, + "failed to create map_profile_enable"); + goto err; + } -end: - return rc; -} -#else -static inline int cam_smmu_create_debug_fs(void) -{ - CAM_WARN(CAM_SMMU, "DebugFS not enabled in kernel"); return 0; +err: + debugfs_remove_recursive(iommu_cb_set.dentry); + return -ENOMEM; } -#endif static int cam_smmu_fw_dev_component_bind(struct device *dev, struct device *master_dev, void *data) @@ -4012,9 +4019,7 @@ static void cam_smmu_component_unbind(struct device *dev, } cam_smmu_release_cb(pdev); -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(iommu_cb_set.dentry); -#endif iommu_cb_set.dentry = NULL; } diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 02be2e7b1455..37461c27d8c0 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1016,30 +1016,25 @@ static void cam_sync_init_entity(struct sync_device *sync_dev) } #endif -#if IS_ENABLED(CONFIG_DEBUG_FS) static int cam_sync_create_debugfs(void) { - int rc = 0; - sync_dev->dentry = debugfs_create_dir("camera_sync", NULL); - if (IS_ERR(sync_dev->dentry)) { - rc = PTR_ERR(sync_dev->dentry); - goto end; + + if (!sync_dev->dentry) { + CAM_ERR(CAM_SYNC, "Failed to create sync dir"); + return -ENOMEM; } - debugfs_create_bool("trigger_cb_without_switch", 0644, - sync_dev->dentry, &trigger_cb_without_switch); + if (!debugfs_create_bool("trigger_cb_without_switch", + 0644, sync_dev->dentry, + &trigger_cb_without_switch)) { + CAM_ERR(CAM_SYNC, + "failed to create trigger_cb_without_switch entry"); + return -ENOMEM; + } -end: - return rc; -} -#else -static inline int cam_sync_create_debugfs(void) -{ - CAM_WARN(CAM_SYNC, "DebugFS not enabled in kernel"); return 0; } -#endif #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) int cam_synx_sync_signal(int32_t sync_obj, uint32_t synx_status) @@ -1221,9 +1216,7 @@ static void cam_sync_component_unbind(struct device *dev, #endif video_unregister_device(sync_dev->vdev); video_device_release(sync_dev->vdev); -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(sync_dev->dentry); -#endif sync_dev->dentry = NULL; for (i = 0; i < CAM_SYNC_MAX_OBJS; i++) diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index aab96d3782c3..5ea63757526b 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -14,6 +14,7 @@ #include "cam_mem_mgr.h" static char supported_clk_info[256]; +static char debugfs_dir_name[64]; int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, int64_t clk_rate, int clk_idx, int32_t *clk_lvl) @@ -180,16 +181,18 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control, * * @return: Success or failure */ -#if IS_ENABLED(CONFIG_DEBUG_FS) -static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) +static int cam_soc_util_create_clk_lvl_debugfs( + struct cam_hw_soc_info *soc_info) { - char debugfs_dir_name[64]; - int rc = 0; + if (!soc_info) { + CAM_ERR(CAM_UTIL, "soc info is NULL"); + return -EINVAL; + } if (soc_info->dentry) { - CAM_DBG(CAM_UTIL, "Debugfs entry for %s already exist", + CAM_DBG(CAM_UTIL, "Debubfs entry for %s already exist", soc_info->dev_name); - goto end; + return 0; } memset(debugfs_dir_name, 0, sizeof(debugfs_dir_name)); @@ -197,26 +200,36 @@ static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) strlcat(debugfs_dir_name, soc_info->dev_name, sizeof(debugfs_dir_name)); soc_info->dentry = debugfs_create_dir(debugfs_dir_name, NULL); - if (IS_ERR(soc_info->dentry)) { - rc = PTR_ERR(soc_info->dentry); - goto end; + if (IS_ERR_OR_NULL(soc_info->dentry)) { + CAM_ERR(CAM_UTIL, "failed to create debug directory"); + return -ENOMEM; } - debugfs_create_file("clk_lvl_options", 0444, soc_info->dentry, soc_info, - &cam_soc_util_clk_lvl_options); - debugfs_create_file("clk_lvl_control", 0644, soc_info->dentry, soc_info, - &cam_soc_util_clk_lvl_control); + if (!debugfs_create_file("clk_lvl_options", 0444, + soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_options)) { + CAM_ERR(CAM_UTIL, "failed to create clk_lvl_options"); + goto err; + } + + if (!debugfs_create_file("clk_lvl_control", 0644, + soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control)) { + CAM_ERR(CAM_UTIL, "failed to create clk_lvl_control"); + goto err; + } + + CAM_DBG(CAM_UTIL, "clk lvl debugfs for %s successfully created", + soc_info->dev_name); -end: - return rc; -} -#else -static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) -{ - CAM_WARN(CAM_UTIL, "DebugFS not enabled in kernel"); return 0; + +err: + CAM_ERR(CAM_UTIL, "Error in creating Debugfs Entry: %s", + soc_info->dev_name); + debugfs_remove_recursive(soc_info->dentry); + soc_info->dentry = NULL; + return -ENOMEM; } -#endif + /** * cam_soc_util_remove_clk_lvl_debugfs() * @@ -229,9 +242,8 @@ static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info) static void cam_soc_util_remove_clk_lvl_debugfs( struct cam_hw_soc_info *soc_info) { -#if IS_ENABLED(CONFIG_DEBUG_FS) debugfs_remove_recursive(soc_info->dentry); -#endif + soc_info->dentry = NULL; } int cam_soc_util_get_level_from_string(const char *string, From f115d3e484e1f87c863ec408e1e468b2e753eac9 Mon Sep 17 00:00:00 2001 From: Divya Sharma Date: Tue, 21 Jul 2020 12:34:58 -0700 Subject: [PATCH 427/790] Revert "msm: camera: isp: validate in_port before accessing" This reverts commit 23a77b634299c1468f39b003621b63a45d3897d9. Change-Id: I74b4f396d8c85b7c5de9996e87cc76e0fc7c0178 Signed-off-by: Divya Sharma --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 50 +++------------------ 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index ca621c9d99bd..df5c9a2e2c85 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2110,36 +2110,18 @@ err: static int cam_ife_mgr_check_and_update_fe_v0( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_acquire_hw_info *acquire_hw_info, - uint32_t acquire_info_size) + 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; - if (acquire_hw_info->input_info_offset >= - acquire_hw_info->input_info_size) { - CAM_ERR(CAM_ISP, - "Invalid size offset 0x%x is greater then size 0x%x", - acquire_hw_info->input_info_offset, - acquire_hw_info->input_info_size); - return -EINVAL; - } - 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++) { - if (((uint8_t *)in_port + - sizeof(struct cam_isp_in_port_info)) > - ((uint8_t *)acquire_hw_info + - acquire_info_size)) { - CAM_ERR(CAM_ISP, "Invalid size"); - return -EINVAL; - } - if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", @@ -2173,36 +2155,18 @@ static int cam_ife_mgr_check_and_update_fe_v0( static int cam_ife_mgr_check_and_update_fe_v2( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_acquire_hw_info *acquire_hw_info, - uint32_t acquire_info_size) + struct cam_isp_acquire_hw_info *acquire_hw_info) { int i; struct cam_isp_in_port_info_v2 *in_port = NULL; uint32_t in_port_length = 0; uint32_t total_in_port_length = 0; - if (acquire_hw_info->input_info_offset >= - acquire_hw_info->input_info_size) { - CAM_ERR(CAM_ISP, - "Invalid size offset 0x%x is greater then size 0x%x", - acquire_hw_info->input_info_offset, - acquire_hw_info->input_info_size); - return -EINVAL; - } - in_port = (struct cam_isp_in_port_info_v2 *) ((uint8_t *)&acquire_hw_info->data + acquire_hw_info->input_info_offset); for (i = 0; i < acquire_hw_info->num_inputs; i++) { - if (((uint8_t *)in_port + - sizeof(struct cam_isp_in_port_info)) > - ((uint8_t *)acquire_hw_info + - acquire_info_size)) { - CAM_ERR(CAM_ISP, "Invalid size"); - return -EINVAL; - } - if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", @@ -2239,8 +2203,7 @@ static int cam_ife_mgr_check_and_update_fe_v2( 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, - uint32_t acquire_info_size) + struct cam_isp_acquire_hw_info *acquire_hw_info) { uint32_t major_ver = 0, minor_ver = 0; @@ -2253,10 +2216,10 @@ static int cam_ife_mgr_check_and_update_fe( switch (major_ver) { case 1: return cam_ife_mgr_check_and_update_fe_v0( - ife_ctx, acquire_hw_info, acquire_info_size); + ife_ctx, acquire_hw_info); case 2: return cam_ife_mgr_check_and_update_fe_v2( - ife_ctx, acquire_hw_info, acquire_info_size); + ife_ctx, acquire_hw_info); break; default: CAM_ERR(CAM_ISP, "Invalid ver of common info from user"); @@ -3051,8 +3014,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; - rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info, - acquire_args->acquire_info_size); + 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_cdm; From 92ebf5ad23ff4dbf89b2ec404583ccc2907dbf38 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 30 Jun 2020 14:14:00 -0700 Subject: [PATCH 428/790] msm: camera: csiphy: Fill interrupt size variable As a part of interrupt status dump, it needs details for number of register to be read. This change fill the interrupt size variable to do the correct operation. CRs-Fixed: 2729624 Change-Id: I9ee97e5a6c495062753fbd0ed44a178908c5109b Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index ec6a5499d6fc..2c6617574263 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 16, From 3f8fc789d9688f4a2b22deddf163a28284696d0a Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Fri, 26 Jun 2020 07:47:32 -0700 Subject: [PATCH 429/790] msm: camera: ife: Optimize the IFE CDM Acquire Optimize IFE configuration process by making IFE hw update entries independent of the hw type (IFE or SFE). Use CPAS-CDM for dualIFE configuration. CRs-Fixed: 2704472 Change-Id: I1ecba0312c83f0ab1b88c158430650bb9e28666c Signed-off-by: Jigar Agrawal --- drivers/cam_isp/cam_isp_context.c | 230 +++--- drivers/cam_isp/cam_isp_context.h | 8 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 749 ++++++------------ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 14 +- drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h | 2 - drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 191 ++--- .../hw_utils/cam_isp_packet_parser.c | 193 ++--- .../hw_utils/include/cam_isp_packet_parser.h | 16 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 98 +-- 9 files changed, 509 insertions(+), 992 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5d2c46aa6ab5..00993e35d48a 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -314,71 +314,62 @@ static int cam_isp_ctx_dump_req( size_t *offset, bool dump_to_buff) { - int i, j, rc = 0; + int i, rc = 0; size_t len = 0; uint32_t *buf_addr; uint32_t *buf_start, *buf_end; size_t remain_len = 0; struct cam_cdm_cmd_buf_dump_info dump_info; - uint32_t num_cfg; - struct cam_hw_update_entry *cfg; - for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) { - num_cfg = req_isp->cfg_info[j].num_hw_entries; - cfg = req_isp->cfg_info[j].hw_entries; - for (i = 0; i < num_cfg; i++) { - rc = cam_packet_util_get_cmd_mem_addr( - cfg[i].handle, &buf_addr, &len); - if (rc) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "Failed to get_cmd_mem_addr, rc=%d", - rc); - } else { - if (cfg[i].offset >= ((uint32_t)len)) { - CAM_ERR(CAM_ISP, - "Invalid offset exp %u actual %u", - cfg[i].offset, (uint32_t)len); - return -EINVAL; - } - remain_len = len - cfg[i].offset; - - if (req_isp->cfg_info[j].hw_entries[i].len > - ((uint32_t)remain_len)) { - CAM_ERR(CAM_ISP, - "Invalid len exp %u remain_len %u", - cfg[i].len, - (uint32_t)remain_len); - return -EINVAL; - } - - buf_start = (uint32_t *)((uint8_t *) buf_addr + - cfg[i].offset); - buf_end = (uint32_t *)((uint8_t *) buf_start + - cfg[i].len - 1); - - if (dump_to_buff) { - if (!cpu_addr || !offset || !buf_len) { - CAM_ERR(CAM_ISP, - "Invalid args"); - break; - } - dump_info.src_start = buf_start; - dump_info.src_end = buf_end; - dump_info.dst_start = cpu_addr; - dump_info.dst_offset = *offset; - dump_info.dst_max_size = buf_len; - rc = cam_cdm_util_dump_cmd_bufs_v2( - &dump_info); - *offset = dump_info.dst_offset; - if (rc) - return rc; - } else - cam_cdm_util_dump_cmd_buf(buf_start, - buf_end); + for (i = 0; i < req_isp->num_cfg; i++) { + rc = cam_packet_util_get_cmd_mem_addr( + req_isp->cfg[i].handle, &buf_addr, &len); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Failed to get_cmd_mem_addr, rc=%d", + rc); + } else { + if (req_isp->cfg[i].offset >= ((uint32_t)len)) { + CAM_ERR(CAM_ISP, + "Invalid offset exp %u actual %u", + req_isp->cfg[i].offset, (uint32_t)len); + return -EINVAL; } + remain_len = len - req_isp->cfg[i].offset; + + if (req_isp->cfg[i].len > + ((uint32_t)remain_len)) { + CAM_ERR(CAM_ISP, + "Invalid len exp %u remain_len %u", + req_isp->cfg[i].len, + (uint32_t)remain_len); + return -EINVAL; + } + + 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 (dump_to_buff) { + if (!cpu_addr || !offset || !buf_len) { + CAM_ERR(CAM_ISP, "Invalid args"); + break; + } + dump_info.src_start = buf_start; + dump_info.src_end = buf_end; + dump_info.dst_start = cpu_addr; + dump_info.dst_offset = *offset; + dump_info.dst_max_size = buf_len; + rc = cam_cdm_util_dump_cmd_bufs_v2( + &dump_info); + *offset = dump_info.dst_offset; + if (rc) + return rc; + } else + cam_cdm_util_dump_cmd_buf(buf_start, buf_end); } } - return rc; } @@ -429,17 +420,13 @@ static int __cam_isp_ctx_enqueue_request_in_order( static int __cam_isp_ctx_enqueue_init_request( struct cam_context *ctx, struct cam_ctx_request *req) { - int rc = 0, i = 0; + int rc = 0; struct cam_ctx_request *req_old; struct cam_isp_ctx_req *req_isp_old; struct cam_isp_ctx_req *req_isp_new; struct cam_isp_prepare_hw_update_data *req_update_old; struct cam_isp_prepare_hw_update_data *req_update_new; struct cam_isp_prepare_hw_update_data *hw_update_data; - struct cam_hw_update_entry *cfg_old; - struct cam_hw_update_entry *cfg_new; - uint32_t num_cfg_old; - uint32_t num_cfg_new; spin_lock_bh(&ctx->lock); if (list_empty(&ctx->pending_req_list)) { @@ -455,12 +442,12 @@ static int __cam_isp_ctx_enqueue_init_request( req_isp_new = (struct cam_isp_ctx_req *) req->req_priv; if (req_isp_old->hw_update_data.packet_opcode_type == CAM_ISP_PACKET_INIT_DEV) { - if ((req_isp_old->total_num_cfg + req_isp_new->total_num_cfg) >= + if ((req_isp_old->num_cfg + req_isp_new->num_cfg) >= CAM_ISP_CTX_CFG_MAX) { CAM_WARN(CAM_ISP, - "Can not merge INIT pkt total_num_cfgs = %d", - (req_isp_old->total_num_cfg + - req_isp_new->total_num_cfg)); + "Can not merge INIT pkt num_cfgs = %d", + (req_isp_old->num_cfg + + req_isp_new->num_cfg)); rc = -ENOMEM; } @@ -485,19 +472,11 @@ static int __cam_isp_ctx_enqueue_init_request( req_isp_old->num_fence_map_in = req_isp_new->num_fence_map_in; - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - cfg_old = req_isp_old->cfg_info[i].hw_entries; - cfg_new = req_isp_new->cfg_info[i].hw_entries; - num_cfg_old = - req_isp_old->cfg_info[i].num_hw_entries; - num_cfg_new = - req_isp_new->cfg_info[i].num_hw_entries; - memcpy(&cfg_old[num_cfg_old], - cfg_new, - sizeof(cfg_new[0]) * num_cfg_new); - req_isp_old->cfg_info[i].num_hw_entries - += num_cfg_new; - } + memcpy(&req_isp_old->cfg[req_isp_old->num_cfg], + req_isp_new->cfg, + sizeof(req_isp_new->cfg[0]) * + req_isp_new->num_cfg); + req_isp_old->num_cfg += req_isp_new->num_cfg; memcpy(&req_old->pf_data, &req->pf_data, sizeof(struct cam_hw_mgr_dump_pf_data)); @@ -1088,12 +1067,12 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( static int __cam_isp_ctx_apply_req_offline( void *priv, void *data) { - int rc = 0, i = 0; + int rc = 0; struct cam_context *ctx = NULL; struct cam_isp_context *ctx_isp = priv; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; - struct cam_isp_hw_config_args cfg; + struct cam_hw_config_args cfg; if (!ctx_isp) { CAM_ERR(CAM_ISP, "Invalid ctx_isp:%pK", ctx); @@ -1129,12 +1108,8 @@ static int __cam_isp_ctx_apply_req_offline( cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; cfg.request_id = req->request_id; - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - cfg.hw_update_info[i].num_hw_entries = - req_isp->cfg_info[i].num_hw_entries; - cfg.hw_update_info[i].hw_entries = - req_isp->cfg_info[i].hw_entries; - } + cfg.hw_update_entries = req_isp->cfg; + cfg.num_hw_update_entries = req_isp->num_cfg; cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; @@ -2505,13 +2480,13 @@ static int __cam_isp_ctx_apply_req_in_activated_state( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, enum cam_isp_ctx_activated_substate next_state) { - int rc = 0, i; + int rc = 0; struct cam_ctx_request *req; struct cam_ctx_request *active_req = NULL; struct cam_isp_ctx_req *req_isp; struct cam_isp_ctx_req *active_req_isp; struct cam_isp_context *ctx_isp = NULL; - struct cam_isp_hw_config_args isp_cfg; + struct cam_hw_config_args cfg = {0}; if (list_empty(&ctx->pending_req_list)) { CAM_ERR(CAM_ISP, "No available request for Apply id %lld", @@ -2597,22 +2572,16 @@ static int __cam_isp_ctx_apply_req_in_activated_state( } req_isp->bubble_report = apply->report_if_bubble; - memset(&isp_cfg, 0, sizeof(isp_cfg)); - - isp_cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; - isp_cfg.request_id = req->request_id; - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - isp_cfg.hw_update_info[i].num_hw_entries = - req_isp->cfg_info[i].num_hw_entries; - isp_cfg.hw_update_info[i].hw_entries = - req_isp->cfg_info[i].hw_entries; - } - isp_cfg.priv = &req_isp->hw_update_data; - isp_cfg.init_packet = 0; - isp_cfg.reapply = req_isp->reapply; + cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; + cfg.request_id = req->request_id; + cfg.hw_update_entries = req_isp->cfg; + cfg.num_hw_update_entries = req_isp->num_cfg; + cfg.priv = &req_isp->hw_update_data; + cfg.init_packet = 0; + cfg.reapply = req_isp->reapply; rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, - &isp_cfg); + &cfg); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); } else { @@ -3832,7 +3801,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( struct cam_packet *packet; size_t len = 0; size_t remain_len = 0; - struct cam_isp_hw_update_args isp_cfg; + struct cam_hw_prepare_update_args cfg = {0}; struct cam_req_mgr_add_request add_req; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; @@ -3912,44 +3881,31 @@ static int __cam_isp_ctx_config_dev_in_top_state( goto free_req; } - /* preprocess the configuration */ - memset(&isp_cfg, 0, sizeof(isp_cfg)); - - isp_cfg.packet = packet; - isp_cfg.remain_len = remain_len; - isp_cfg.ctxt_to_hw_map = ctx_isp->hw_ctx; - isp_cfg.max_hw_update_entries = CAM_ISP_CTX_CFG_MAX; - isp_cfg.max_out_map_entries = CAM_ISP_CTX_RES_MAX; - isp_cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX; - isp_cfg.out_map_entries = req_isp->fence_map_out; - isp_cfg.in_map_entries = req_isp->fence_map_in; - isp_cfg.priv = &req_isp->hw_update_data; - isp_cfg.pf_data = &(req->pf_data); - - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) - isp_cfg.hw_update_info[i].hw_entries - = req_isp->cfg_info[i].hw_entries; + 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; + cfg.max_out_map_entries = CAM_ISP_CTX_RES_MAX; + cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX; + cfg.out_map_entries = req_isp->fence_map_out; + cfg.in_map_entries = req_isp->fence_map_in; + cfg.priv = &req_isp->hw_update_data; + cfg.pf_data = &(req->pf_data); CAM_DBG(CAM_ISP, "try to prepare config packet......"); rc = ctx->hw_mgr_intf->hw_prepare_update( - ctx->hw_mgr_intf->hw_mgr_priv, &isp_cfg); + ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (rc != 0) { CAM_ERR(CAM_ISP, "Prepare config packet failed in HW layer"); rc = -EFAULT; goto free_req; } - req_isp->total_num_cfg = 0; - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - req_isp->cfg_info[i].num_hw_entries - = isp_cfg.hw_update_info[i].num_hw_entries; - req_isp->total_num_cfg += - req_isp->cfg_info[i].num_hw_entries; - } - - req_isp->num_fence_map_out = isp_cfg.num_out_map_entries; - req_isp->num_fence_map_in = isp_cfg.num_in_map_entries; + req_isp->num_cfg = cfg.num_hw_update_entries; + req_isp->num_fence_map_out = cfg.num_out_map_entries; + req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; req_isp->bubble_detected = false; @@ -3963,7 +3919,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( } CAM_DBG(CAM_ISP, "num_entry: %d, num fence out: %d, num fence in: %d", - req_isp->total_num_cfg, req_isp->num_fence_map_out, + req_isp->num_cfg, req_isp->num_fence_map_out, req_isp->num_fence_map_in); req->request_id = packet->header.request_id; @@ -4698,14 +4654,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.hw_config.request_id = req->request_id; - - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - start_isp.hw_config.hw_update_info[i].hw_entries - = req_isp->cfg_info[i].hw_entries; - start_isp.hw_config.hw_update_info[i].num_hw_entries = - req_isp->cfg_info[i].num_hw_entries; - } - + start_isp.hw_config.hw_update_entries = req_isp->cfg; + start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg; start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index fd5c59fb47f1..c6f5aa31882e 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -135,8 +135,8 @@ struct cam_isp_ctx_irq_ops { * struct cam_isp_ctx_req - ISP context request object * * @base: Common request object ponter - * @cfg_info: ISP hardware configuration array - * @total_num_cfg: Number of ISP hardware configuration entries + * @cfg: ISP hardware configuration array + * @num_cfg: Number of ISP hardware configuration entries * @fence_map_out: Output fence mapping array * @num_fence_map_out: Number of the output fence map * @fence_map_in: Input fence mapping array @@ -153,8 +153,8 @@ struct cam_isp_ctx_irq_ops { */ struct cam_isp_ctx_req { struct cam_ctx_request *base; - struct cam_isp_hw_update_info cfg_info[CAM_IFE_HW_NUM_MAX]; - uint32_t total_num_cfg; + struct cam_hw_update_entry cfg[CAM_ISP_CTX_CFG_MAX]; + uint32_t num_cfg; struct cam_hw_fence_map_entry fence_map_out [CAM_ISP_CTX_RES_MAX]; uint32_t num_fence_map_out; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4f07a3a2841e..9945190e339d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -653,7 +653,7 @@ static int cam_ife_hw_mgr_free_hw_res( "Release HW:%d resource id %d failed", hw_intf->hw_idx, isp_hw_res->res_id); else - CAM_INFO(CAM_ISP, + CAM_DBG(CAM_ISP, "Released HW:%d resource id %d", hw_intf->hw_idx, isp_hw_res->res_id); @@ -1949,17 +1949,6 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); cid_res->num_children++; - if (is_ipp) { - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - if (master_idx == i) - ife_ctx->master_slave[i] = CAM_IFE_RES_MASTER; - else - ife_ctx->master_slave[i] = CAM_IFE_RES_SLAVE; - CAM_DBG(CAM_ISP, "hw %d, slave/master %d", - i, ife_ctx->master_slave[i]); - } - } - CAM_DBG(CAM_ISP, "acquire res %d CID children = %d", csid_acquire.res_id, cid_res->num_children); @@ -2740,8 +2729,6 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, { struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; struct cam_ife_hw_mgr_ctx *ctx = NULL; - int i; - uint32_t idx = 0; int reg_dump_done; if (!userdata) { @@ -2752,24 +2739,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata; ctx = (struct cam_ife_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; - if (!ctx->internal_cdm) - idx = 0; - else { - for (i = 0; i < ctx->num_base; i++) { - if (ctx->cdm_handle[ctx->base[i].idx] == handle) { - idx = ctx->base[i].idx; - break; - } - } - - if (i == ctx->num_base) { - CAM_ERR(CAM_ISP, "Incorrect CDM handle=0x%x", handle); - return; - } - } - if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { - complete_all(&ctx->config_done_complete[idx]); + complete_all(&ctx->config_done_complete); reg_dump_done = atomic_read(&ctx->cdm_done); atomic_set(&ctx->cdm_done, 1); if ((g_ife_hw_mgr.debug_cfg.per_req_reg_dump) && @@ -3019,7 +2990,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) struct cam_ife_hw_mgr *ife_hw_mgr = hw_mgr_priv; struct cam_hw_acquire_args *acquire_args = acquire_hw_args; int rc = -1; - int i, j = 0, k; + int i, j; struct cam_ife_hw_mgr_ctx *ife_ctx; struct cam_isp_in_port_generic_info *in_port = NULL; struct cam_cdm_acquire_data cdm_acquire; @@ -3031,7 +3002,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) uint32_t total_pd_port = 0; struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; uint32_t input_size = 0; - uint32_t hw_version, idx; + uint32_t hw_version; CAM_DBG(CAM_ISP, "Enter..."); @@ -3049,15 +3020,14 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->custom_enabled = false; ife_ctx->custom_config = 0; - memset(ife_ctx->cdm_handle, 0, sizeof(ife_ctx->cdm_handle)); - + ife_ctx->cdm_handle = 0; ife_ctx->common.cb_priv = acquire_args->context_data; ife_ctx->internal_cdm = false; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) ife_ctx->common.event_cb[i] = acquire_args->event_cb; ife_ctx->hw_mgr = ife_hw_mgr; - ife_ctx->cdm_ops = cam_cdm_publish_ops(); + ife_ctx->cdm_ops = cam_cdm_publish_ops(); acquire_hw_info = (struct cam_isp_acquire_hw_info *)acquire_args->acquire_info; @@ -3144,36 +3114,36 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) cam_cpas_get_cpas_hw_version(&hw_version); ife_ctx->hw_version = hw_version; - for (k = 0; k < ife_ctx->num_base; k++) { - CAM_DBG(CAM_ISP, "Acquire cdm for ife_hw_idx %d", - ife_ctx->base[k].idx); - + if (ife_ctx->is_dual) + memcpy(cdm_acquire.identifier, "dualife", sizeof("dualife")); + else memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); - cdm_acquire.cell_index = ife_ctx->base[k].idx; - cdm_acquire.handle = 0; - cdm_acquire.userdata = ife_ctx; - if (ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]) - cdm_acquire.base_array[j++] = - ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]; - cdm_acquire.base_array_cnt = j; - cdm_acquire.priority = CAM_CDM_BL_FIFO_0; - cdm_acquire.id = CAM_CDM_VIRTUAL; - cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; - rc = cam_cdm_acquire(&cdm_acquire); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); - goto free_cdm; - } - CAM_DBG(CAM_ISP, - "Successfully acquired CDM id=0%d, handle :0x%x", - cdm_acquire.id, cdm_acquire.handle); - if (cdm_acquire.id == CAM_CDM_IFE) - ife_ctx->internal_cdm = true; - ife_ctx->cdm_handle[ife_ctx->base[k].idx] = cdm_acquire.handle; - ife_ctx->base[k].cdm_id = cdm_acquire.id; + cdm_acquire.cell_index = ife_ctx->base[0].idx; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ife_ctx; + cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; + for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (ife_hw_mgr->cdm_reg_map[i]) + cdm_acquire.base_array[j++] = + ife_hw_mgr->cdm_reg_map[i]; + } + cdm_acquire.base_array_cnt = j; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_ctx; } + CAM_DBG(CAM_ISP, + "Successfully acquired CDM Id: %d, CDM HW hdl=%x, is_dual=%d", + cdm_acquire.id, cdm_acquire.handle, ife_ctx->is_dual); + ife_ctx->cdm_handle = cdm_acquire.handle; + if (cdm_acquire.id == CAM_CDM_IFE) + ife_ctx->internal_cdm = true; atomic_set(&ife_ctx->cdm_done, 1); acquire_args->ctxt_to_hw_map = ife_ctx; @@ -3198,13 +3168,10 @@ free_mem: kfree(in_port->data); kfree(in_port); free_cdm: - for (i = 0; i < ife_ctx->num_base; i++) { - idx = ife_ctx->base[i].idx; - if (ife_ctx->cdm_handle[idx] != 0) - cam_cdm_release(ife_ctx->cdm_handle[idx]); - } + cam_cdm_release(ife_ctx->cdm_handle); free_res: cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); +free_ctx: cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); err: CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); @@ -3260,7 +3227,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) struct cam_ife_hw_mgr *ife_hw_mgr = hw_mgr_priv; struct cam_hw_acquire_args *acquire_args = acquire_hw_args; int rc = -1; - int i, j = 0, k; + int i, j; struct cam_ife_hw_mgr_ctx *ife_ctx; struct cam_isp_in_port_info *in_port = NULL; struct cam_isp_resource *isp_resource = NULL; @@ -3273,7 +3240,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; uint32_t in_port_length = 0; - uint32_t hw_version, idx; + uint32_t hw_version; CAM_DBG(CAM_ISP, "Enter..."); @@ -3289,14 +3256,12 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto err; } - memset(ife_ctx->cdm_handle, 0, sizeof(ife_ctx->cdm_handle)); - + ife_ctx->cdm_handle = 0; ife_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) ife_ctx->common.event_cb[i] = acquire_args->event_cb; ife_ctx->hw_mgr = ife_hw_mgr; - ife_ctx->cdm_ops = cam_cdm_publish_ops(); isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; @@ -3409,37 +3374,38 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) } cam_cpas_get_cpas_hw_version(&hw_version); - ife_ctx->hw_version = hw_version; + ife_ctx->internal_cdm = false; - for (k = 0; k < ife_ctx->num_base; k++) { - CAM_DBG(CAM_ISP, "Acquire cdm for ife_hw_idx %d", k); - + if (ife_ctx->is_dual) + memcpy(cdm_acquire.identifier, "dualife", sizeof("dualife")); + else memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); - cdm_acquire.cell_index = ife_ctx->base[k].idx; - cdm_acquire.handle = 0; - cdm_acquire.userdata = ife_ctx; - if (ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]) + cdm_acquire.cell_index = ife_ctx->base[0].idx; + cdm_acquire.handle = 0; + cdm_acquire.userdata = ife_ctx; + cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; + for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (ife_hw_mgr->cdm_reg_map[i]) cdm_acquire.base_array[j++] = - ife_hw_mgr->cdm_reg_map[ife_ctx->base[k].idx]; - cdm_acquire.base_array_cnt = j; - cdm_acquire.priority = CAM_CDM_BL_FIFO_0; - cdm_acquire.id = CAM_CDM_VIRTUAL; - cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; - rc = cam_cdm_acquire(&cdm_acquire); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); - goto free_res; - } - - CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=0x%x", - cdm_acquire.handle); - - if (cdm_acquire.id == CAM_CDM_IFE) - ife_ctx->internal_cdm = true; - ife_ctx->cdm_handle[ife_ctx->base[k].idx] = cdm_acquire.handle; + ife_hw_mgr->cdm_reg_map[i]; + } + cdm_acquire.base_array_cnt = j; + cdm_acquire.priority = CAM_CDM_BL_FIFO_0; + cdm_acquire.id = CAM_CDM_VIRTUAL; + cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback; + rc = cam_cdm_acquire(&cdm_acquire); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); + goto free_res; } + CAM_DBG(CAM_ISP, "Successfully acquired CDM ID:%d, CDM HW hdl=%x", + cdm_acquire.id, cdm_acquire.handle); + + if (cdm_acquire.id == CAM_CDM_IFE) + ife_ctx->internal_cdm = true; + ife_ctx->cdm_handle = cdm_acquire.handle; atomic_set(&ife_ctx->cdm_done, 1); acquire_args->ctxt_to_hw_map = ife_ctx; @@ -3454,11 +3420,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) return 0; free_res: cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); - for (i = 0; i < ife_ctx->num_base; i++) { - idx = ife_ctx->base[i].idx; - if (ife_ctx->cdm_handle[idx] != 0) - cam_cdm_release(ife_ctx->cdm_handle[idx]); - } + cam_cdm_release(ife_ctx->cdm_handle); cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); err: CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); @@ -3761,199 +3723,17 @@ static int cam_isp_blob_bw_update( return rc; } -static int cam_ife_config_hw_internal_cdm(struct cam_ife_hw_mgr_ctx *ctx, - struct cam_isp_hw_config_args *cfg, - struct cam_isp_prepare_hw_update_data *hw_update_data) -{ - int rc = -1, i, j, skip = 0; - struct cam_hw_update_entry *cmd; - struct cam_cdm_bl_request *cdm_cmd; - uint32_t num_ent; - struct cam_hw_update_entry *cfg_info; - unsigned long rem_jiffies = 0; - uint32_t idx; - - if (ctx->num_base >= CAM_IFE_HW_NUM_MAX) { - CAM_ERR(CAM_ISP, - "Invalid number of IFE acquired = %d", - ctx->num_base); - return -EINVAL; - } - - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - num_ent = cfg->hw_update_info[idx].num_hw_entries; - cfg_info = cfg->hw_update_info[idx].hw_entries; - if (num_ent > 0) { - cdm_cmd = ctx->cdm_cmd; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = true; - cdm_cmd->userdata = hw_update_data; - cdm_cmd->cookie = cfg->request_id; - cdm_cmd->gen_irq_arb = false; - skip = 0; - - for (j = 0 ; j < num_ent; j++) { - cmd = (cfg_info + j); - - if (cfg->reapply && - cmd->flags == CAM_ISP_IQ_BL) { - skip++; - continue; - } - - if (cmd->flags == CAM_ISP_UNUSED_BL || - cmd->flags >= CAM_ISP_BL_MAX) - CAM_ERR(CAM_ISP, - "Unexpected BL type %d", - cmd->flags); - - cdm_cmd->cmd[j - skip].bl_addr.mem_handle = - cmd->handle; - cdm_cmd->cmd[j - skip].offset = cmd->offset; - cdm_cmd->cmd[j - skip].len = cmd->len; - cdm_cmd->cmd[j - skip].arbitrate = false; - } - cdm_cmd->cmd_arrary_count = num_ent - skip; - - reinit_completion(&ctx->config_done_complete[idx]); - ctx->applied_req_id = cfg->request_id; - - CAM_DBG(CAM_ISP, "Submit to CDM for IFE idx = %d", - ctx->base[i].idx); - atomic_set(&ctx->cdm_done, 0); - rc = cam_cdm_submit_bls(ctx->cdm_handle[idx], cdm_cmd); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed to apply the configs for req %llu, rc %d", - cfg->request_id, rc); - return rc; - } - } - } - - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - if ((cfg->init_packet) || - (ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) { - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete[idx], - msecs_to_jiffies(30)); - if (rem_jiffies == 0) { - CAM_ERR(CAM_ISP, - "config done completion timeout for req_id=%llu ctx_index %d IFE:%d", - cfg->request_id, - ctx->ctx_index, idx); - rc = -ETIMEDOUT; - } else - CAM_DBG(CAM_ISP, - "config done Success for req_id=%llu ctx_index %d IFE:%d", - cfg->request_id, - ctx->ctx_index, idx); - } - } - - return rc; -} - -static int cam_ife_config_hw_external_cdm(struct cam_ife_hw_mgr_ctx *ctx, - struct cam_isp_hw_config_args *cfg, - struct cam_isp_prepare_hw_update_data *hw_update_data) -{ - int rc = -1, i, j, k = 0, skip = 0; - struct cam_hw_update_entry *cmd; - struct cam_cdm_bl_request *cdm_cmd; - uint32_t num_ent; - struct cam_hw_update_entry *cfg_info; - unsigned long rem_jiffies = 0; - - if (ctx->num_base >= CAM_IFE_HW_NUM_MAX) { - CAM_ERR(CAM_ISP, - "Invalid number of IFE acquired = %d", - ctx->num_base); - return -EINVAL; - } - - cdm_cmd = ctx->cdm_cmd; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = true; - cdm_cmd->userdata = hw_update_data; - cdm_cmd->cookie = cfg->request_id; - cdm_cmd->gen_irq_arb = false; - cdm_cmd->cmd_arrary_count = 0; - - for (i = 0; i < ctx->num_base; i++) { - num_ent = cfg->hw_update_info[ctx->base[i].idx].num_hw_entries; - cfg_info = cfg->hw_update_info[ctx->base[i].idx].hw_entries; - if (num_ent > 0) { - for (j = 0 ; j < num_ent; j++) { - cmd = (cfg_info + j); - - if (cfg->reapply && - cmd->flags == CAM_ISP_IQ_BL) { - skip++; - continue; - } - - if (cmd->flags == CAM_ISP_UNUSED_BL || - cmd->flags >= CAM_ISP_BL_MAX) - CAM_ERR(CAM_ISP, - "Unexpected BL type %d", - cmd->flags); - - cdm_cmd->cmd[j - skip + k].bl_addr.mem_handle = - cmd->handle; - cdm_cmd->cmd[j - skip + k].offset = cmd->offset; - cdm_cmd->cmd[j - skip + k].len = cmd->len; - cdm_cmd->cmd[j - skip + k].arbitrate = false; - } - cdm_cmd->cmd_arrary_count += num_ent - skip; - k = cdm_cmd->cmd_arrary_count; - } - } - - ctx->applied_req_id = cfg->request_id; - CAM_DBG(CAM_ISP, "Submit to CDM for IFE idx = %d", - ctx->base[i].idx); - atomic_set(&ctx->cdm_done, 0); - reinit_completion(&ctx->config_done_complete[0]); - rc = cam_cdm_submit_bls(ctx->cdm_handle[ctx->base[0].idx], cdm_cmd); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed to apply the configs for req %llu, rc %d", - cfg->request_id, rc); - return rc; - } - - if ((cfg->init_packet) || - (ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) { - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete[0], - msecs_to_jiffies(30)); - if (rem_jiffies == 0) { - CAM_ERR(CAM_ISP, - "config done completion timeout for req_id=%llu ctx_index %d IFE:%d", - cfg->request_id, - ctx->ctx_index, ctx->base[0].idx); - rc = -ETIMEDOUT; - } else - CAM_DBG(CAM_ISP, - "config done Success for req_id=%llu ctx_index %d IFE:%d", - cfg->request_id, - ctx->ctx_index, ctx->base[0].idx); - } - - return rc; -} - /* entry function: config_hw */ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) { - int rc = -1, i; - struct cam_isp_hw_config_args *cfg; + int rc = -1, i, skip = 0; + struct cam_hw_config_args *cfg; + struct cam_hw_update_entry *cmd; + struct cam_cdm_bl_request *cdm_cmd; struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; + unsigned long rem_jiffies = 0; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, @@ -3990,10 +3770,11 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - if (hw_update_data->bw_config_valid[i]) { + if (hw_update_data->bw_config_valid[i] == true) { CAM_DBG(CAM_PERF, "idx=%d, bw_config_version=%d", - i, hw_update_data->bw_config_version); + ctx, ctx->ctx_index, i, + hw_update_data->bw_config_version); if (hw_update_data->bw_config_version == CAM_ISP_BW_CONFIG_V1) { @@ -4007,8 +3788,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_ISP_BW_CONFIG_V2) { rc = cam_isp_blob_bw_update_v2( (struct cam_isp_bw_config_v2 *) - &hw_update_data->bw_config_v2[i], - ctx); + &hw_update_data->bw_config_v2[i], ctx); if (rc) CAM_ERR(CAM_PERF, "Bandwidth Update Failed rc: %d", rc); @@ -4022,19 +3802,68 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, } CAM_DBG(CAM_ISP, - "Enter ctx id:%d request id: %llu", ctx->ctx_index, - cfg->request_id); + "Enter ctx id:%d num_hw_upd_entries %d request id: %llu", + ctx->ctx_index, cfg->num_hw_update_entries, cfg->request_id); - if (ctx->internal_cdm) - rc = cam_ife_config_hw_internal_cdm(ctx, cfg, hw_update_data); - else - rc = cam_ife_config_hw_external_cdm(ctx, cfg, hw_update_data); + if (cfg->num_hw_update_entries > 0) { + cdm_cmd = ctx->cdm_cmd; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; - if (rc) { - CAM_ERR(CAM_ISP, "Config HW failure"); - return rc; + for (i = 0 ; i < cfg->num_hw_update_entries; i++) { + cmd = (cfg->hw_update_entries + i); + + if (cfg->reapply && + cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i - skip].offset = cmd->offset; + cdm_cmd->cmd[i - skip].len = cmd->len; + cdm_cmd->cmd[i - skip].arbitrate = false; + } + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; + + reinit_completion(&ctx->config_done_complete); + ctx->applied_req_id = cfg->request_id; + + CAM_DBG(CAM_ISP, "Submit to CDM"); + atomic_set(&ctx->cdm_done, 0); + rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); + if (rc) { + CAM_ERR(CAM_ISP, + "Failed to apply the configs for req %llu, rc %d", + cfg->request_id, rc); + return rc; + } + + if (cfg->init_packet) { + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(30)); + if (rem_jiffies == 0) { + CAM_ERR(CAM_ISP, + "config done completion timeout for req_id=%llu ctx_index %d", + cfg->request_id, ctx->ctx_index); + rc = -ETIMEDOUT; + } else + CAM_DBG(CAM_ISP, + "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: Config Done: %llu", cfg->request_id); return rc; @@ -4179,7 +4008,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) enum cam_ife_csid_halt_cmd csid_halt_type; uint32_t i, master_base_idx = 0; unsigned long rem_jiffies = 0; - uint32_t idx; if (!hw_mgr_priv || !stop_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -4280,40 +4108,19 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_pause_hw(ctx); - if (ctx->internal_cdm) { - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete[idx], - msecs_to_jiffies(5)); - if (rem_jiffies == 0) - CAM_WARN(CAM_ISP, - "config done completion timeout for last applied req_id=%llu ctx_index %d IFE:%d", - ctx->applied_req_id, ctx->ctx_index, - idx); - } - } else { - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete[0], - msecs_to_jiffies(5)); - if (rem_jiffies == 0) - CAM_WARN(CAM_ISP, - "config done completion timeout for last applied req_id=%llu ctx_index %d IFE:%d", - ctx->applied_req_id, ctx->ctx_index, - ctx->master_hw_idx); - } + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(10)); + if (rem_jiffies == 0) + CAM_WARN(CAM_ISP, + "config done completion timeout for last applied req_id=%llu ctx_index %", + ctx->applied_req_id, ctx->ctx_index); if (stop_isp->stop_only) goto end; - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - if (ctx->cdm_handle[idx] != 0) { - if (cam_cdm_stream_off(ctx->cdm_handle[idx])) - CAM_ERR(CAM_ISP, "CDM stream off failed %d", - ctx->cdm_handle[i]); - } - } + if (cam_cdm_stream_off(ctx->cdm_handle)) + CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); if (ctx->is_tpg) cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_tpg); @@ -4484,7 +4291,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *rsrc_node = NULL; - uint32_t i, camif_debug, idx; + uint32_t i, camif_debug; bool res_rdi_context_set = false; uint32_t primary_rdi_src_res; uint32_t primary_rdi_out_res; @@ -4578,16 +4385,10 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } mutex_unlock(&g_ife_hw_mgr.ctx_mutex); - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - if (ctx->cdm_handle[idx] != 0) { - rc = cam_cdm_stream_on(ctx->cdm_handle[idx]); - if (rc) { - CAM_ERR(CAM_ISP, "Can not start cdm (%d)", - ctx->cdm_handle); - goto safe_disable; - } - } + rc = cam_cdm_stream_on(ctx->cdm_handle); + if (rc) { + CAM_ERR(CAM_ISP, "Can not start cdm (%d)", ctx->cdm_handle); + goto safe_disable; } start_only: @@ -4715,10 +4516,7 @@ err: return rc; cdm_streamoff: - for (i = 0; i < ctx->num_base; i++) { - if (ctx->cdm_handle[ctx->base[i].idx] != 0) - cam_cdm_stream_off(ctx->cdm_handle[ctx->base[i].idx]); - } + cam_cdm_stream_off(ctx->cdm_handle); safe_disable: cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE); @@ -4817,16 +4615,13 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, memset(ctx->base, 0, sizeof(ctx->base)); /* release cdm handle */ - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { - if (ctx->cdm_handle[i] != 0) - cam_cdm_release(ctx->cdm_handle[i]); - ctx->cdm_handle[i] = 0; - } + cam_cdm_release(ctx->cdm_handle); /* clean context */ list_del_init(&ctx->list); ctx->ctx_in_use = 0; ctx->is_rdi_only_context = 0; + ctx->cdm_handle = 0; ctx->cdm_ops = NULL; ctx->num_reg_dump_buf = 0; ctx->custom_enabled = false; @@ -4855,7 +4650,7 @@ 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_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -4927,14 +4722,13 @@ static int cam_isp_blob_ubwc_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_ubwc_config *ubwc_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ubwc_plane_cfg_v1 *ubwc_plane_cfg; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; - uint32_t res_id_out, i, slot_idx = 0; + uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; @@ -4948,14 +4742,10 @@ static int cam_isp_blob_ubwc_update( goto end; } - slot_idx = blob_info->base_info->idx; - hw_entry = prepare->hw_update_info[slot_idx].hw_entries; - num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; - - if ((num_ent + 1) >= + if ((prepare->num_hw_update_entries + 1) >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d", - num_ent, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); rc = -EINVAL; goto end; @@ -5027,18 +4817,18 @@ static int cam_isp_blob_ubwc_update( if (total_used_bytes) { /* Update the HW entries */ - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = + prepare->hw_update_entries[num_ent].len = total_used_bytes; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->hw_update_info[slot_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } break; default: @@ -5103,13 +4893,12 @@ static int cam_isp_blob_ubwc_update_v2( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_ubwc_config_v2 *ubwc_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ubwc_plane_cfg_v2 *ubwc_plane_cfg; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; @@ -5117,7 +4906,6 @@ static int cam_isp_blob_ubwc_update_v2( uint32_t bytes_used = 0; int num_ent, rc = 0; struct cam_vfe_generic_ubwc_config generic_ubwc_cfg; - uint32_t slot_idx; ctx = prepare->ctxt_to_hw_map; if (!ctx) { @@ -5126,14 +4914,10 @@ static int cam_isp_blob_ubwc_update_v2( goto end; } - slot_idx = blob_info->base_info->idx; - hw_entry = prepare->hw_update_info[slot_idx].hw_entries; - num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; - - if (num_ent + 1 >= + if (prepare->num_hw_update_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d", - prepare->hw_update_info[slot_idx].num_hw_entries, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); rc = -EINVAL; goto end; @@ -5206,18 +4990,17 @@ static int cam_isp_blob_ubwc_update_v2( if (total_used_bytes) { /* Update the HW entries */ - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = - total_used_bytes; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->hw_update_info[slot_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } end: return rc; @@ -5227,14 +5010,13 @@ static int cam_isp_blob_hfr_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_resource_hfr_config *hfr_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_isp_port_hfr_config *port_hfr_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; - uint32_t res_id_out, i, slot_idx = 0; + uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; @@ -5245,15 +5027,11 @@ static int cam_isp_blob_hfr_update( CAM_DBG(CAM_ISP, "num_ports= %d", hfr_config->num_ports); - slot_idx = blob_info->base_info->idx; - hw_entry = prepare->hw_update_info[slot_idx].hw_entries; - num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; - /* Max one hw entries required for hfr config update */ - if (prepare->hw_update_info[slot_idx].num_hw_entries + 1 >= + if (prepare->num_hw_update_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->hw_update_info[slot_idx].num_hw_entries, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -5311,17 +5089,16 @@ static int cam_isp_blob_hfr_update( if (total_used_bytes) { /* Update the HW entries */ - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = - total_used_bytes; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->hw_update_info[slot_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } return rc; @@ -5331,7 +5108,7 @@ static int cam_isp_blob_csid_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_csid_clock_config *clock_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5378,7 +5155,7 @@ static int cam_isp_blob_csid_qcfa_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_csid_qcfa_config *qcfa_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5426,7 +5203,7 @@ static int cam_isp_blob_core_cfg_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_core_config *core_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5481,7 +5258,7 @@ static int cam_isp_blob_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_clock_config *clock_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5591,7 +5368,7 @@ static int cam_isp_blob_sensor_config( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_sensor_config *dim_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5661,30 +5438,25 @@ static int cam_isp_blob_vfe_out_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_vfe_out_config *vfe_out_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_isp_vfe_wm_config *wm_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *ife_out_res; - struct cam_hw_update_entry *hw_entry; uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; uint32_t bytes_used = 0; - uint32_t slot_idx = 0; int num_ent, rc = 0; ctx = prepare->ctxt_to_hw_map; - slot_idx = blob_info->base_info->idx; - hw_entry = prepare->hw_update_info[slot_idx].hw_entries; - num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; - if (num_ent + 1 >= + if (prepare->num_hw_update_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d", - num_ent); + prepare->num_hw_update_entries); return -EINVAL; } @@ -5740,17 +5512,16 @@ static int cam_isp_blob_vfe_out_update( } if (total_used_bytes) { - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = - total_used_bytes; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->hw_update_info[slot_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } return rc; @@ -5760,7 +5531,7 @@ static int cam_isp_blob_csid_config_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_csid_epd_config *epd_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_ife_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -5807,7 +5578,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, int rc = 0; struct cam_isp_generic_blob_info *blob_info = user_data; struct cam_ife_hw_mgr_ctx *ife_mgr_ctx = NULL; - struct cam_isp_hw_update_args *prepare = NULL; + struct cam_hw_prepare_update_args *prepare = NULL; if (!blob_data || (blob_size == 0) || !blob_info) { CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK", @@ -6365,13 +6136,13 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { int rc = 0; - struct cam_isp_hw_update_args *ife_cfg = - (struct cam_isp_hw_update_args *) prepare_hw_update_args; + struct cam_hw_prepare_update_args *prepare = + (struct cam_hw_prepare_update_args *) prepare_hw_update_args; struct cam_ife_hw_mgr_ctx *ctx; struct cam_ife_hw_mgr *hw_mgr; struct cam_kmd_buf_info kmd_buf; - uint32_t i, idx; + uint32_t i; bool fill_fence = true; bool frame_header_enable = false; struct cam_isp_prepare_hw_update_data *prepare_hw_data; @@ -6383,22 +6154,22 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) - ife_cfg->priv; + prepare->priv; - ctx = (struct cam_ife_hw_mgr_ctx *) ife_cfg->ctxt_to_hw_map; + ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map; hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv; CAM_DBG(CAM_REQ, "ctx[%pK][%d] Enter for req_id %lld", - ctx, ctx->ctx_index, ife_cfg->packet->header.request_id); + ctx, ctx->ctx_index, prepare->packet->header.request_id); - rc = cam_packet_util_validate_packet(ife_cfg->packet, - ife_cfg->remain_len); + rc = cam_packet_util_validate_packet(prepare->packet, + prepare->remain_len); if (rc) return rc; /* Pre parse the packet*/ - rc = cam_packet_util_get_kmd_buffer(ife_cfg->packet, &kmd_buf); + rc = cam_packet_util_get_kmd_buffer(prepare->packet, &kmd_buf); if (rc) return rc; @@ -6412,11 +6183,11 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } if (ctx->internal_cdm) - rc = cam_packet_util_process_patches(ife_cfg->packet, + rc = cam_packet_util_process_patches(prepare->packet, hw_mgr->mgr_common.img_iommu_hdl, hw_mgr->mgr_common.img_iommu_hdl_secure); else - rc = cam_packet_util_process_patches(ife_cfg->packet, + rc = cam_packet_util_process_patches(prepare->packet, hw_mgr->mgr_common.cmd_iommu_hdl, hw_mgr->mgr_common.cmd_iommu_hdl_secure); @@ -6425,14 +6196,10 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, return rc; } - - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - ife_cfg->hw_update_info[idx].num_hw_entries = 0; - } - ife_cfg->num_in_map_entries = 0; - ife_cfg->num_out_map_entries = 0; - ife_cfg->num_reg_dump_buf = 0; + prepare->num_hw_update_entries = 0; + prepare->num_in_map_entries = 0; + prepare->num_out_map_entries = 0; + prepare->num_reg_dump_buf = 0; memset(&prepare_hw_data->bw_config[0], 0x0, sizeof(prepare_hw_data->bw_config[0]) * @@ -6441,30 +6208,16 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, sizeof(prepare_hw_data->bw_config_valid[0]) * CAM_IFE_HW_NUM_MAX); - /* Add reset trigger_cdm_event */ - if ((ctx->hw_version >= CAM_CPAS_TITAN_480_V100) && ctx->is_dual - && ctx->internal_cdm) { - for (i = 0; i < ctx->num_base; i++) { - if (ctx->master_slave[ctx->base[i].idx] - == CAM_IFE_RES_SLAVE && - ctx->base[i].cdm_id == CAM_CDM_IFE) - rc = cam_isp_add_wait_trigger(ife_cfg, - &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf, false); - } - } - for (i = 0; i < ctx->num_base; i++) { CAM_DBG(CAM_ISP, "process cmd buffer for device %d", i); CAM_DBG(CAM_ISP, - "change base i=%d, idx=%d, ctx->internal_cdm = %d cdm_id = %d", - i, ctx->base[i].idx, ctx->internal_cdm, - ctx->base[i].cdm_id); + "change base i=%d, idx=%d, ctx->internal_cdm = %d", + i, ctx->base[i].idx, ctx->internal_cdm); /* Add change base */ - if (!ctx->internal_cdm || ctx->base[i].cdm_id == CAM_CDM_CPAS) { - rc = cam_isp_add_change_base(ife_cfg, + if (!ctx->internal_cdm) { + rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, ctx->base[i].idx, &kmd_buf); if (rc) { @@ -6476,7 +6229,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } /* get command buffers */ if (ctx->base[i].split_id != CAM_ISP_HW_SPLIT_MAX) { - rc = cam_isp_add_command_buffers(ife_cfg, &kmd_buf, + rc = cam_isp_add_command_buffers(prepare, &kmd_buf, &ctx->base[i], cam_isp_packet_generic_blob_handler, ctx->res_list_ife_out, CAM_IFE_HW_OUT_RES_MAX); @@ -6500,7 +6253,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, rc = cam_isp_add_io_buffers( hw_mgr->mgr_common.img_iommu_hdl, hw_mgr->mgr_common.img_iommu_hdl_secure, - ife_cfg, ctx->base[i].idx, + prepare, ctx->base[i].idx, &kmd_buf, ctx->res_list_ife_out, &ctx->res_list_ife_in_rd, CAM_IFE_HW_OUT_RES_MAX, fill_fence, @@ -6531,9 +6284,9 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } /* add go_cmd for offline context */ - if (ife_cfg->num_out_map_entries && ife_cfg->num_in_map_entries && + if (prepare->num_out_map_entries && prepare->num_in_map_entries && ctx->is_offline) { - rc = cam_isp_add_go_cmd(ife_cfg, &ctx->res_list_ife_in_rd, + rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd, ctx->base[i].idx, &kmd_buf); if (rc) CAM_ERR(CAM_ISP, @@ -6547,26 +6300,26 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, * bits to get the type of operation since UMD definition * of op_code has some difference from KMD. */ - if (((ife_cfg->packet->header.op_code + 1) & 0xF) == + if (((prepare->packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_INIT_DEV) { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV; - if ((!ife_cfg->num_reg_dump_buf) || (ife_cfg->num_reg_dump_buf > + if ((!prepare->num_reg_dump_buf) || (prepare->num_reg_dump_buf > CAM_REG_DUMP_MAX_BUF_ENTRIES)) goto end; if (!ctx->num_reg_dump_buf) { - ctx->num_reg_dump_buf = ife_cfg->num_reg_dump_buf; + ctx->num_reg_dump_buf = prepare->num_reg_dump_buf; memcpy(ctx->reg_dump_buf_desc, - ife_cfg->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * - ife_cfg->num_reg_dump_buf); + prepare->num_reg_dump_buf); } else { prepare_hw_data->num_reg_dump_buf = - ife_cfg->num_reg_dump_buf; + prepare->num_reg_dump_buf; memcpy(prepare_hw_data->reg_dump_buf_desc, - ife_cfg->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * prepare_hw_data->num_reg_dump_buf); } @@ -6574,35 +6327,22 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, goto end; } else { prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_UPDATE_DEV; - prepare_hw_data->num_reg_dump_buf = ife_cfg->num_reg_dump_buf; + prepare_hw_data->num_reg_dump_buf = prepare->num_reg_dump_buf; if ((prepare_hw_data->num_reg_dump_buf) && (prepare_hw_data->num_reg_dump_buf < CAM_REG_DUMP_MAX_BUF_ENTRIES)) { memcpy(prepare_hw_data->reg_dump_buf_desc, - ife_cfg->reg_dump_buf_desc, + prepare->reg_dump_buf_desc, sizeof(struct cam_cmd_buf_desc) * prepare_hw_data->num_reg_dump_buf); } } - /* Add wait for comp event */ - if ((ctx->hw_version >= CAM_CPAS_TITAN_480_V100) && ctx->is_dual - && ctx->internal_cdm) { - for (i = 0; i < ctx->num_base; i++) { - if (ctx->master_slave[ctx->base[i].idx] == - CAM_IFE_RES_MASTER && - ctx->base[i].cdm_id == CAM_CDM_IFE) - rc = cam_isp_add_comp_wait(ife_cfg, - &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf); - } - } - /* add reg update commands */ for (i = 0; i < ctx->num_base; i++) { /* Add change base */ - if (!ctx->internal_cdm || ctx->base[i].cdm_id == CAM_CDM_CPAS) { - rc = cam_isp_add_change_base(ife_cfg, + if (!ctx->internal_cdm) { + rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, ctx->base[i].idx, &kmd_buf); @@ -6614,7 +6354,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } /*Add reg update */ - rc = cam_isp_add_reg_update(ife_cfg, &ctx->res_list_ife_src, + rc = cam_isp_add_reg_update(prepare, &ctx->res_list_ife_src, ctx->base[i].idx, &kmd_buf); if (rc) { @@ -6625,18 +6365,6 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } - /* Add trigger_cdm_event */ - if ((ctx->hw_version >= CAM_CPAS_TITAN_480_V100) && ctx->is_dual - && ctx->internal_cdm) { - for (i = 0; i < ctx->num_base; i++) { - if (ctx->master_slave[ctx->base[i].idx] - == CAM_IFE_RES_SLAVE) - rc = cam_isp_add_wait_trigger(ife_cfg, - &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf, true); - } - } - end: return rc; } @@ -6768,7 +6496,7 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { - int rc = 0, i = 0; + int rc = 0; struct cam_hw_cmd_args *hw_cmd_args = cmd_args; struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *) @@ -6776,7 +6504,6 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) struct cam_isp_hw_cmd_args *isp_hw_cmd_args = NULL; struct cam_packet *packet; unsigned long rem_jiffies = 0; - uint32_t idx; if (!hw_mgr_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -6850,17 +6577,12 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) if (ctx->last_dump_flush_req_id == ctx->applied_req_id) return 0; - for (i = 0; i < ctx->num_base; i++) { - idx = ctx->base[i].idx; - rem_jiffies = wait_for_completion_timeout( - &ctx->config_done_complete[idx], - msecs_to_jiffies(5)); - if (rem_jiffies == 0) - CAM_ERR(CAM_ISP, - "config done completion timeout, Reg dump will be unreliable rc=%d ctx_index %d", - rc, ctx->ctx_index); - rc = 0; - } + rem_jiffies = wait_for_completion_timeout( + &ctx->config_done_complete, msecs_to_jiffies(30)); + if (rem_jiffies == 0) + CAM_ERR(CAM_ISP, + "config done completion timeout, Reg dump will be unreliable rc=%d ctx_index %d", + rc, ctx->ctx_index); ctx->last_dump_flush_req_id = ctx->applied_req_id; rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, @@ -8023,10 +7745,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = g_ife_hw_mgr.mgr_common.tasklet_pool[i]; - for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) - init_completion( - &g_ife_hw_mgr.ctx_pool[i] - .config_done_complete[j]); + init_completion(&g_ife_hw_mgr.ctx_pool[i].config_done_complete); list_add_tail(&g_ife_hw_mgr.ctx_pool[i].list, &g_ife_hw_mgr.free_ctx_list); } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index ca1648d616c5..6afc982ce402 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -15,14 +15,6 @@ #include "cam_tasklet_util.h" #include "cam_cdm_intf_api.h" -/* enum cam_ife_res_master_slave - HW resource master/slave */ -enum cam_ife_res_master_slave { - CAM_IFE_RES_NONE, - CAM_IFE_RES_MASTER, - CAM_IFE_RES_SLAVE, - CAM_IFE_RES_MAX, -}; - /* IFE resource constants */ #define CAM_IFE_HW_IN_RES_MAX (CAM_ISP_IFE_IN_RES_MAX & 0xFF) #define CAM_IFE_HW_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_MAX & 0xFF) @@ -132,7 +124,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t irq_status1_mask[CAM_IFE_HW_NUM_MAX]; struct cam_isp_ctx_base_info base[CAM_IFE_HW_NUM_MAX]; uint32_t num_base; - uint32_t cdm_handle[CAM_IFE_HW_NUM_MAX]; + uint32_t cdm_handle; struct cam_cdm_utils_ops *cdm_ops; struct cam_cdm_bl_request *cdm_cmd; @@ -142,9 +134,7 @@ struct cam_ife_hw_mgr_ctx { atomic_t overflow_pending; atomic_t cdm_done; uint32_t is_rdi_only_context; - struct completion config_done_complete[ - CAM_IFE_HW_NUM_MAX]; - enum cam_ife_res_master_slave master_slave[CAM_IFE_HW_NUM_MAX]; + struct completion config_done_complete; uint32_t hw_version; struct cam_cmd_buf_desc reg_dump_buf_desc[ CAM_REG_DUMP_MAX_BUF_ENTRIES]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h index edd1d33be8f0..021ff7072450 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h @@ -10,7 +10,6 @@ #include "cam_isp_hw_mgr_intf.h" #include "cam_tasklet_util.h" #include "cam_isp_hw.h" -#include "cam_cdm_intf_api.h" #define CAM_ISP_HW_NUM_MAX 7 @@ -91,6 +90,5 @@ struct cam_isp_hw_mgr_res { struct cam_isp_ctx_base_info { uint32_t idx; enum cam_isp_hw_split_id split_id; - enum cam_cdm_id cdm_id; }; #endif /* _CAM_ISP_HW_MGR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 41f267633205..7523c699613f 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1768,8 +1768,6 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto err; } - memset(&tfe_ctx->cdm_handle, 0, sizeof(tfe_ctx->cdm_handle)); - tfe_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) tfe_ctx->common.event_cb[i] = acquire_args->event_cb; @@ -2003,8 +2001,6 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto err; } - memset(&tfe_ctx->cdm_handle, 0, sizeof(tfe_ctx->cdm_handle)); - tfe_ctx->common.cb_priv = acquire_args->context_data; for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++) tfe_ctx->common.event_cb[i] = acquire_args->event_cb; @@ -2335,14 +2331,12 @@ static int cam_isp_tfe_blob_bw_update( static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) { - int rc = -EINVAL, i, j, k = 0, skip = 0; - struct cam_isp_hw_config_args *cfg; + int rc = -EINVAL, i, skip = 0; + struct cam_hw_config_args *cfg; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; struct cam_tfe_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; - uint32_t num_ent; - struct cam_hw_update_entry *cfg_info; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -2387,80 +2381,74 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, } } - CAM_DBG(CAM_ISP, "Enter ctx id:%d request id: %llu", - ctx->ctx_index, cfg->request_id); + 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); - cdm_cmd = ctx->cdm_cmd; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = true; - cdm_cmd->userdata = hw_update_data; - cdm_cmd->cookie = cfg->request_id; - cdm_cmd->gen_irq_arb = false; - cdm_cmd->cmd_arrary_count = 0; + if (cfg->num_hw_update_entries > 0) { + cdm_cmd = ctx->cdm_cmd; + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; - for (i = 0; i < ctx->num_base; i++) { - num_ent = cfg->hw_update_info[ctx->base[i].idx].num_hw_entries; - cfg_info = cfg->hw_update_info[ctx->base[i].idx].hw_entries; - if (num_ent > 0) { - for (j = 0 ; j < num_ent; j++) { - cmd = (cfg_info + j); - - if (cfg->reapply && - cmd->flags == CAM_ISP_IQ_BL) { - skip++; - continue; - } - - if (cmd->flags == CAM_ISP_UNUSED_BL || - cmd->flags >= CAM_ISP_BL_MAX) - CAM_ERR(CAM_ISP, - "Unexpected BL type %d", - cmd->flags); - - cdm_cmd->cmd[j - skip + k].bl_addr.mem_handle = - cmd->handle; - cdm_cmd->cmd[j - skip + k].offset = cmd->offset; - cdm_cmd->cmd[j - skip + k].len = cmd->len; - cdm_cmd->cmd[j - skip + k].arbitrate = false; + for (i = 0; i < cfg->num_hw_update_entries; i++) { + cmd = cfg->hw_update_entries + i; + if (cfg->reapply && cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; } - cdm_cmd->cmd_arrary_count += num_ent - skip; - k = cdm_cmd->cmd_arrary_count; + + if (cmd->flags == CAM_ISP_UNUSED_BL || + cmd->flags >= CAM_ISP_BL_MAX) + CAM_ERR(CAM_ISP, "Unexpected BL type %d", + cmd->flags); + + cdm_cmd->cmd[i - skip].bl_addr.mem_handle = cmd->handle; + cdm_cmd->cmd[i - skip].offset = cmd->offset; + cdm_cmd->cmd[i - skip].len = cmd->len; + cdm_cmd->cmd[i - skip].arbitrate = false; } - } + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries - skip; + reinit_completion(&ctx->config_done_complete); + ctx->applied_req_id = cfg->request_id; + CAM_DBG(CAM_ISP, "Submit to CDM"); - ctx->applied_req_id = cfg->request_id; - CAM_DBG(CAM_ISP, "Submit to CDM"); + atomic_set(&ctx->cdm_done, 0); - atomic_set(&ctx->cdm_done, 0); - reinit_completion(&ctx->config_done_complete); - rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); - if (rc) { - CAM_ERR(CAM_ISP, - "Failed to apply the configs for req %llu, rc %d", - cfg->request_id, rc); - return rc; - } - - if (cfg->init_packet) { - rc = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies( - CAM_TFE_HW_CONFIG_TIMEOUT)); - if (rc <= 0) { + rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd); + if (rc) { CAM_ERR(CAM_ISP, - "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 ctx_index %d", - cfg->request_id, - ctx->ctx_index); + "Failed to apply the configs for req %llu, rc %d", + cfg->request_id, rc); + return rc; } + + if (cfg->init_packet) { + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies(CAM_TFE_HW_CONFIG_TIMEOUT)); + if (rc <= 0) { + CAM_ERR(CAM_ISP, + "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 ctx_index %d", + cfg->request_id, + ctx->ctx_index); + } + } + } else { + CAM_ERR(CAM_ISP, "No commands to config"); } + CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); return rc; @@ -3257,14 +3245,13 @@ static int cam_isp_tfe_blob_hfr_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_tfe_resource_hfr_config *hfr_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_isp_tfe_port_hfr_config *port_hfr_config; struct cam_kmd_buf_info *kmd_buf_info; struct cam_tfe_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; - uint32_t res_id_out, i, slot_idx = 0; + uint32_t res_id_out, i; uint32_t total_used_bytes = 0; uint32_t kmd_buf_remain_size; uint32_t *cmd_buf_addr; @@ -3274,15 +3261,11 @@ static int cam_isp_tfe_blob_hfr_update( ctx = prepare->ctxt_to_hw_map; CAM_DBG(CAM_ISP, "num_ports= %d", hfr_config->num_ports); - slot_idx = blob_info->base_info->idx; - hw_entry = prepare->hw_update_info[slot_idx].hw_entries; - num_ent = prepare->hw_update_info[slot_idx].num_hw_entries; - /* Max one hw entries required for hfr config update */ - if (prepare->hw_update_info[slot_idx].num_hw_entries + 1 >= + if (prepare->num_hw_update_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->hw_update_info[slot_idx].num_hw_entries, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -3338,17 +3321,16 @@ static int cam_isp_tfe_blob_hfr_update( if (total_used_bytes) { /* Update the HW entries */ - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = - total_used_bytes; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; num_ent++; kmd_buf_info->used_bytes += total_used_bytes; kmd_buf_info->offset += total_used_bytes; - prepare->hw_update_info[slot_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } return rc; @@ -3358,7 +3340,7 @@ static int cam_isp_tfe_blob_csid_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_tfe_csid_clock_config *clock_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_tfe_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -3422,7 +3404,7 @@ static int cam_isp_tfe_blob_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, struct cam_isp_tfe_clock_config *clock_config, - struct cam_isp_hw_update_args *prepare) + struct cam_hw_prepare_update_args *prepare) { struct cam_tfe_hw_mgr_ctx *ctx = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res; @@ -3511,7 +3493,7 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, { int rc = 0; struct cam_isp_generic_blob_info *blob_info = user_data; - struct cam_isp_hw_update_args *prepare = NULL; + struct cam_hw_prepare_update_args *prepare = NULL; if (!blob_data || (blob_size == 0) || !blob_info) { CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK", @@ -3713,7 +3695,6 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, } static int cam_tfe_update_dual_config( - struct cam_isp_hw_update_args *prepare, struct cam_cmd_buf_desc *cmd_desc, uint32_t split_id, uint32_t base_idx, @@ -3822,7 +3803,7 @@ end: } int cam_tfe_add_command_buffers( - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, @@ -3835,12 +3816,10 @@ int cam_tfe_add_command_buffers( enum cam_isp_hw_split_id split_id; struct cam_cmd_buf_desc *cmd_desc = NULL; struct cam_hw_update_entry *hw_entry = NULL; - struct cam_isp_hw_update_entry_info *hw_info; split_id = base_info->split_id; base_idx = base_info->idx; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - hw_info = prepare->hw_update_info; + hw_entry = prepare->hw_update_entries; /* * set the cmd_desc to point the first command descriptor in the * packet @@ -3853,7 +3832,7 @@ int cam_tfe_add_command_buffers( split_id, prepare->packet->num_cmd_buf); for (i = 0; i < prepare->packet->num_cmd_buf; i++) { - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; + num_ent = prepare->num_hw_update_entries; if (!cmd_desc[i].length) continue; @@ -3928,9 +3907,8 @@ int cam_tfe_add_command_buffers( break; case CAM_ISP_TFE_PACKET_META_DUAL_CONFIG: - rc = cam_tfe_update_dual_config(prepare, - &cmd_desc[i], split_id, base_idx, - res_list_isp_out, size_isp_out); + rc = cam_tfe_update_dual_config(&cmd_desc[i], split_id, + base_idx, res_list_isp_out, size_isp_out); if (rc) return rc; @@ -3938,8 +3916,7 @@ int cam_tfe_add_command_buffers( case CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_COMMON: { struct cam_isp_generic_blob_info blob_info; - prepare->hw_update_info[base_idx].num_hw_entries = - num_ent; + prepare->num_hw_update_entries = num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -3954,7 +3931,7 @@ int cam_tfe_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = hw_info[base_idx].num_hw_entries; + num_ent = prepare->num_hw_update_entries; } break; case CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH: @@ -3983,8 +3960,7 @@ int cam_tfe_add_command_buffers( cmd_meta_data); return -EINVAL; } - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } return rc; @@ -3994,8 +3970,8 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { int rc = 0; - struct cam_isp_hw_update_args *prepare = - (struct cam_isp_hw_update_args *) prepare_hw_update_args; + struct cam_hw_prepare_update_args *prepare = + (struct cam_hw_prepare_update_args *) prepare_hw_update_args; struct cam_tfe_hw_mgr_ctx *ctx; struct cam_tfe_hw_mgr *hw_mgr; struct cam_kmd_buf_info kmd_buf; @@ -4036,6 +4012,7 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, return rc; } + prepare->num_hw_update_entries = 0; prepare->num_in_map_entries = 0; prepare->num_out_map_entries = 0; prepare->num_reg_dump_buf = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index c4931d85e7da..c498233f48e8 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -13,7 +13,7 @@ #include "cam_isp_hw_mgr_intf.h" int cam_isp_add_change_base( - struct cam_isp_hw_update_args *prepare, + 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) @@ -25,8 +25,8 @@ int cam_isp_add_change_base( struct cam_hw_update_entry *hw_entry; uint32_t num_ent, i; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; + hw_entry = prepare->hw_update_entries; + num_ent = prepare->num_hw_update_entries; /* Max one hw entries required for each base */ if (num_ent + 1 >= prepare->max_hw_update_entries) { @@ -77,8 +77,7 @@ int cam_isp_add_change_base( kmd_buf_info->used_bytes += get_base.cmd.used_bytes; kmd_buf_info->offset += get_base.cmd.used_bytes; num_ent++; - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; /* return success */ return 0; @@ -89,7 +88,6 @@ int cam_isp_add_change_base( } static int cam_isp_update_dual_config( - struct cam_isp_hw_update_args *prepare, struct cam_cmd_buf_desc *cmd_desc, uint32_t split_id, uint32_t base_idx, @@ -243,7 +241,7 @@ int cam_isp_add_cmd_buf_update( } int cam_isp_add_command_buffers( - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, @@ -256,12 +254,11 @@ int cam_isp_add_command_buffers( enum cam_isp_hw_split_id split_id; struct cam_cmd_buf_desc *cmd_desc = NULL; struct cam_hw_update_entry *hw_entry = NULL; - struct cam_isp_hw_update_entry_info *hw_info; split_id = base_info->split_id; base_idx = base_info->idx; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - hw_info = prepare->hw_update_info; + hw_entry = prepare->hw_update_entries; + /* * set the cmd_desc to point the first command descriptor in the * packet @@ -274,8 +271,7 @@ int cam_isp_add_command_buffers( split_id, prepare->packet->num_cmd_buf); for (i = 0; i < prepare->packet->num_cmd_buf; i++) { - num_ent = - prepare->hw_update_info[base_idx].num_hw_entries; + num_ent = prepare->num_hw_update_entries; if (!cmd_desc[i].length) continue; @@ -351,8 +347,8 @@ int cam_isp_add_command_buffers( num_ent++; break; case CAM_ISP_PACKET_META_DUAL_CONFIG: - rc = cam_isp_update_dual_config(prepare, - &cmd_desc[i], split_id, base_idx, + rc = cam_isp_update_dual_config(&cmd_desc[i], + split_id, base_idx, res_list_isp_out, size_isp_out); if (rc) @@ -362,8 +358,7 @@ int cam_isp_add_command_buffers( if (split_id == CAM_ISP_HW_SPLIT_LEFT) { struct cam_isp_generic_blob_info blob_info; - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -379,15 +374,14 @@ int cam_isp_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = hw_info[base_idx].num_hw_entries; + num_ent = prepare->num_hw_update_entries; } break; case CAM_ISP_PACKET_META_GENERIC_BLOB_RIGHT: if (split_id == CAM_ISP_HW_SPLIT_RIGHT) { struct cam_isp_generic_blob_info blob_info; - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -403,14 +397,13 @@ int cam_isp_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = hw_info[base_idx].num_hw_entries; + num_ent = prepare->num_hw_update_entries; } break; case CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON: { struct cam_isp_generic_blob_info blob_info; - prepare->hw_update_info[base_idx].num_hw_entries = - num_ent; + prepare->num_hw_update_entries = num_ent; blob_info.prepare = prepare; blob_info.base_info = base_info; blob_info.kmd_buf_info = kmd_buf_info; @@ -425,7 +418,7 @@ int cam_isp_add_command_buffers( return rc; } hw_entry[num_ent].flags = CAM_ISP_IQ_BL; - num_ent = hw_info[base_idx].num_hw_entries; + num_ent = prepare->num_hw_update_entries; } break; case CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH: @@ -455,8 +448,7 @@ int cam_isp_add_command_buffers( cmd_meta_data); return -EINVAL; } - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; } return rc; @@ -465,7 +457,7 @@ int cam_isp_add_command_buffers( int cam_isp_add_io_buffers( int iommu_hdl, int sec_iommu_hdl, - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_hw_mgr_res *res_list_isp_out, @@ -481,7 +473,6 @@ int cam_isp_add_io_buffers( struct cam_isp_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_hw_update_entry *hw_entry; 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; @@ -504,14 +495,12 @@ int cam_isp_add_io_buffers( num_in_buf = 0; io_cfg_used_bytes = 0; prepare->pf_data->packet = prepare->packet; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; /* Max one hw entries required for each base */ - if (num_ent + 1 >= + if (prepare->num_hw_update_entries + 1 >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - prepare->hw_update_info[base_idx].num_hw_entries, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -863,21 +852,25 @@ int cam_isp_add_io_buffers( io_cfg_used_bytes, fill_fence); if (io_cfg_used_bytes) { /* Update the HW entries */ - hw_entry[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = io_cfg_used_bytes; - hw_entry[num_ent].offset = kmd_buf_info->offset; - hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = + io_cfg_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + prepare->hw_update_entries[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - hw_entry[num_ent].handle, - hw_entry[num_ent].len, - hw_entry[num_ent].offset); + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += io_cfg_used_bytes; kmd_buf_info->offset += io_cfg_used_bytes; - prepare->hw_update_info[base_idx].num_hw_entries = num_ent; + prepare->num_hw_update_entries = num_ent; } if (fill_fence) { @@ -889,7 +882,7 @@ int cam_isp_add_io_buffers( } int cam_isp_add_reg_update( - struct cam_isp_hw_update_args *prepare, + 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) @@ -897,17 +890,14 @@ int cam_isp_add_reg_update( int rc = -EINVAL; struct cam_isp_resource_node *res; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; struct cam_isp_hw_get_cmd_update get_regup; uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; - /* Max one hw entries required for each base */ - if (num_ent + 1 >= prepare->max_hw_update_entries) { + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - num_ent, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -962,23 +952,26 @@ int cam_isp_add_reg_update( if (reg_update_size) { /* Update the HW entries */ - hw_entry[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = reg_update_size; - hw_entry[num_ent].offset = kmd_buf_info->offset; + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = reg_update_size; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; /* Marking reg update as IOCFG to reapply on bubble */ - hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + prepare->hw_update_entries[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - hw_entry[num_ent].handle, - hw_entry[num_ent].len, - hw_entry[num_ent].offset); + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += reg_update_size; kmd_buf_info->offset += reg_update_size; - prepare->hw_update_info[base_idx].num_hw_entries = num_ent; + prepare->num_hw_update_entries = num_ent; /* reg update is success return status 0 */ rc = 0; } @@ -987,7 +980,7 @@ int cam_isp_add_reg_update( } int cam_isp_add_go_cmd( - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, struct list_head *res_list_isp_rd, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info) @@ -995,17 +988,14 @@ int cam_isp_add_go_cmd( int rc = -EINVAL; struct cam_isp_resource_node *res; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; struct cam_isp_hw_get_cmd_update get_regup; uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; - /* Max one hw entries required for each base */ - if (num_ent + 1 >= prepare->max_hw_update_entries) { + if (prepare->num_hw_update_entries + 1 >= + prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d", - num_ent, + prepare->num_hw_update_entries, prepare->max_hw_update_entries); return -EINVAL; } @@ -1058,22 +1048,24 @@ int cam_isp_add_go_cmd( if (reg_update_size) { /* Update the HW entries */ - hw_entry[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = reg_update_size; - hw_entry[num_ent].offset = kmd_buf_info->offset; - - hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = reg_update_size; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + prepare->hw_update_entries[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - hw_entry[num_ent].handle, - hw_entry[num_ent].len, - hw_entry[num_ent].offset); + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += reg_update_size; kmd_buf_info->offset += reg_update_size; - prepare->hw_update_info[base_idx].num_hw_entries = num_ent; + prepare->num_hw_update_entries = num_ent; rc = 0; } @@ -1082,24 +1074,20 @@ int cam_isp_add_go_cmd( } int cam_isp_add_comp_wait( - struct cam_isp_hw_update_args *prepare, + 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) { int rc = -EINVAL; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; struct cam_isp_hw_get_cmd_update add_wait; struct cam_hw_intf *hw_intf; bool hw_res_valid = false; uint32_t kmd_buf_remain_size, num_ent, add_wait_size; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; - /* Max one hw entries required for each base */ - if (num_ent >= prepare->max_hw_update_entries) { + if (prepare->num_hw_update_entries >= prepare->max_hw_update_entries) { CAM_ERR(CAM_ISP, "Insufficient HW entries"); return -EINVAL; } @@ -1157,25 +1145,24 @@ int cam_isp_add_comp_wait( add_wait_size += add_wait.cmd.used_bytes; if (add_wait_size) { /* Update the HW entries */ - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = - add_wait_size; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].len = add_wait_size; + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; - hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + prepare->hw_update_entries[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - hw_entry[num_ent].handle, - hw_entry[num_ent].len, - hw_entry[num_ent].offset); + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += add_wait_size; kmd_buf_info->offset += add_wait_size; - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; /* add wait_comp_event is success return status 0 */ rc = 0; } @@ -1184,7 +1171,7 @@ int cam_isp_add_comp_wait( } int cam_isp_add_wait_trigger( - struct cam_isp_hw_update_args *prepare, + 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, @@ -1192,19 +1179,15 @@ int cam_isp_add_wait_trigger( { int rc = -EINVAL; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_update_entry *hw_entry; struct cam_isp_hw_get_cmd_update add_trigger; struct cam_hw_intf *hw_intf; bool hw_res_valid = false; uint32_t kmd_buf_remain_size, num_ent, add_trigger_size; - hw_entry = prepare->hw_update_info[base_idx].hw_entries; - num_ent = prepare->hw_update_info[base_idx].num_hw_entries; - /* Max one hw entries required for each base */ - if (num_ent + 1 >= + if (prepare->num_hw_update_entries + 1 >= prepare->max_hw_update_entries) { - CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d"); + CAM_ERR(CAM_ISP, "Insufficient HW entries"); return -EINVAL; } @@ -1247,11 +1230,6 @@ int cam_isp_add_wait_trigger( add_trigger.cmd_type = CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER; add_trigger.res = hw_mgr_res->hw_res[CAM_ISP_HW_SPLIT_RIGHT]; - if (trigger_cdm_en) - add_trigger.trigger_cdm_en = true; - else - add_trigger.trigger_cdm_en = false; - rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER, @@ -1268,25 +1246,24 @@ int cam_isp_add_wait_trigger( if (add_trigger_size) { /* Update the HW entries */ - hw_entry[num_ent].handle = + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = kmd_buf_info->handle; - hw_entry[num_ent].len = - add_trigger_size; - hw_entry[num_ent].offset = + prepare->hw_update_entries[num_ent].len = add_trigger_size; + prepare->hw_update_entries[num_ent].offset = kmd_buf_info->offset; - hw_entry[num_ent].flags = CAM_ISP_IOCFG_BL; + prepare->hw_update_entries[num_ent].flags = CAM_ISP_IOCFG_BL; CAM_DBG(CAM_ISP, "num_ent=%d handle=0x%x, len=%u, offset=%u", num_ent, - hw_entry[num_ent].handle, - hw_entry[num_ent].len, - hw_entry[num_ent].offset); + prepare->hw_update_entries[num_ent].handle, + prepare->hw_update_entries[num_ent].len, + prepare->hw_update_entries[num_ent].offset); num_ent++; kmd_buf_info->used_bytes += add_trigger_size; kmd_buf_info->offset += add_trigger_size; - prepare->hw_update_info[base_idx].num_hw_entries - = num_ent; + prepare->num_hw_update_entries = num_ent; /* add wait trigger is success return status 0 */ rc = 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index 3c13ee52ae0d..1be8507e20f0 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -29,7 +29,7 @@ enum cam_isp_cdm_bl_type { * @kmd_buf_info: Kmd buffer to store the custom cmd data */ struct cam_isp_generic_blob_info { - struct cam_isp_hw_update_args *prepare; + struct cam_hw_prepare_update_args *prepare; struct cam_isp_ctx_base_info *base_info; struct cam_kmd_buf_info *kmd_buf_info; }; @@ -63,7 +63,7 @@ struct cam_isp_frame_header_info { * -EINVAL for Fail */ int cam_isp_add_change_base( - struct cam_isp_hw_update_args *prepare, + 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); @@ -115,7 +115,7 @@ int cam_isp_add_cmd_buf_update( * Negative for Failure */ int cam_isp_add_command_buffers( - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_ctx_base_info *base_info, cam_packet_generic_blob_handler blob_handler_cb, @@ -146,7 +146,7 @@ int cam_isp_add_command_buffers( int cam_isp_add_io_buffers( int iommu_hdl, int sec_iommu_hdl, - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info, struct cam_isp_hw_mgr_res *res_list_isp_out, @@ -170,7 +170,7 @@ int cam_isp_add_io_buffers( * -EINVAL for Fail */ int cam_isp_add_reg_update( - struct cam_isp_hw_update_args *prepare, + 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); @@ -191,7 +191,7 @@ int cam_isp_add_reg_update( * -EINVAL for Fail */ int cam_isp_add_comp_wait( - struct cam_isp_hw_update_args *prepare, + 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); @@ -213,7 +213,7 @@ int cam_isp_add_comp_wait( * -EINVAL for Fail */ int cam_isp_add_wait_trigger( - struct cam_isp_hw_update_args *prepare, + 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, @@ -233,7 +233,7 @@ int cam_isp_add_wait_trigger( * -EINVAL for Fail */ int cam_isp_add_go_cmd( - struct cam_isp_hw_update_args *prepare, + struct cam_hw_prepare_update_args *prepare, struct list_head *res_list_isp_rd, uint32_t base_idx, struct cam_kmd_buf_info *kmd_buf_info); diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 2ed1f8b211c1..36e0b7e1bee4 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -23,12 +23,6 @@ /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 30 -/* - * Maximum configuration entry size - This is based on the - * worst case DUAL IFE use case plus some margin. - */ - #define CAM_ISP_CTX_CFG_MAX 25 - /** * enum cam_isp_hw_event_type - Collection of the ISP hardware events */ @@ -257,94 +251,6 @@ struct cam_isp_hw_cmd_args { } u; }; -/** - * struct cam_isp_hw_update_entry_info - hardware config info - * - * @hw_update_entries Entry for hardware config - * @num_hw_update_entries: Number of IFE hw - * - */ -struct cam_isp_hw_update_entry_info { - struct cam_hw_update_entry *hw_entries; - uint32_t num_hw_entries; -}; - -/** - * struct cam_isp_hw_update_info - hardware config info - * - * @hw_update_entries Entry for hardware config - * @num_hw_update_entries: number of IFE hw - * - */ - -struct cam_isp_hw_update_info { - struct cam_hw_update_entry hw_entries[CAM_ISP_CTX_CFG_MAX]; - uint32_t num_hw_entries; -}; - -/** - * struct cam_isp_hw_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_info: Actual hardware update configuration (returned) - * @max_out_map_entries: Maximum output fence mapping supported - * @out_map_entries: Actual output fence mapping list (returned) - * @num_out_map_entries: Number of actual output fence mapping (returned) - * @max_in_map_entries: Maximum input fence mapping supported - * @in_map_entries: Actual input fence mapping list (returned) - * @num_in_map_entries: Number of acutal input fence mapping (returned) - * @priv: Private pointer of hw update - * @pf_data: Debug data for page fault - * - */ - -struct cam_isp_hw_update_args { - struct cam_packet *packet; - uint32_t remain_len; - void *ctxt_to_hw_map; - uint32_t max_hw_update_entries; - struct cam_isp_hw_update_entry_info hw_update_info[CAM_IFE_HW_NUM_MAX]; - uint32_t max_out_map_entries; - struct cam_hw_fence_map_entry *out_map_entries; - uint32_t num_out_map_entries; - uint32_t max_in_map_entries; - struct cam_hw_fence_map_entry *in_map_entries; - uint32_t num_in_map_entries; - void *priv; - struct cam_hw_mgr_dump_pf_data *pf_data; - struct cam_cmd_buf_desc reg_dump_buf_desc[ - CAM_REG_DUMP_MAX_BUF_ENTRIES]; - uint32_t num_reg_dump_buf; -}; - -/** - * struct cam_isp_hw_config_args - Payload for config command - * - * @ctxt_to_hw_map: HW context from the acquire - * @hw_update_info: Hardware update info for every IFE - * @out_map_entries: Out map info - * @num_out_map_entries: Number of out map entries - * @priv: Private pointer - * @request_id: Request ID - * @init_packet: check init packet or update packet - * @reapply: check if current req is reapplied - * - */ - -struct cam_isp_hw_config_args { - void *ctxt_to_hw_map; - struct cam_isp_hw_update_entry_info hw_update_info[CAM_IFE_HW_NUM_MAX]; - struct cam_hw_fence_map_entry *out_map_entries; - uint32_t num_out_map_entries; - void *priv; - uint64_t request_id; - bool init_packet; - bool reapply; -}; - /** * struct cam_isp_start_args - isp hardware start arguments * @@ -354,8 +260,8 @@ struct cam_isp_hw_config_args { * */ struct cam_isp_start_args { - struct cam_isp_hw_config_args hw_config; - bool start_only; + struct cam_hw_config_args hw_config; + bool start_only; }; /** From c1b6545f004a8a29ef10b3094d8ef065c568aaa4 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 8 Jul 2020 11:09:52 -0700 Subject: [PATCH 430/790] msm: camera: sensor: Add error handling when adding request Currently proper error handling is not present in case of failure in adding request to request manager. This change adding proper result send out to UMD. CRs-Fixed: 2738448 Change-Id: I7fb54c085ac670c197523e4d7cb416eeb414a2ed Signed-off-by: Jigarkumar Zala --- .../cam_actuator/cam_actuator_core.c | 35 +++++++++++++++--- .../cam_flash/cam_flash_core.c | 8 ++++- .../cam_sensor/cam_sensor_core.c | 36 ++++++++++++++----- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 06f98a01d1df..a3fc2d7756ad 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -360,10 +360,11 @@ int32_t cam_actuator_establish_link( return 0; } -static void cam_actuator_update_req_mgr( +static int cam_actuator_update_req_mgr( struct cam_actuator_ctrl_t *a_ctrl, struct cam_packet *csl_packet) { + int rc = 0; struct cam_req_mgr_add_request add_req; add_req.link_hdl = a_ctrl->bridge_intf.link_hdl; @@ -374,13 +375,22 @@ static void cam_actuator_update_req_mgr( if (a_ctrl->bridge_intf.crm_cb && a_ctrl->bridge_intf.crm_cb->add_req) { - a_ctrl->bridge_intf.crm_cb->add_req(&add_req); + rc = a_ctrl->bridge_intf.crm_cb->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "Adding request: %llu failed: rc: %d", + csl_packet->header.request_id, rc); + return rc; + } CAM_DBG(CAM_ACTUATOR, "Request Id: %lld added to CRM", add_req.req_id); } else { CAM_ERR(CAM_ACTUATOR, "Can't add Request ID: %lld to CRM", csl_packet->header.request_id); + rc = -EINVAL; } + + return rc; } int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info) @@ -619,7 +629,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, "Auto move lens parsing failed: %d", rc); goto end; } - cam_actuator_update_req_mgr(a_ctrl, csl_packet); + rc = cam_actuator_update_req_mgr(a_ctrl, csl_packet); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "Failed in adding request to request manager"); + goto end; + } break; case CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS: if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) { @@ -651,7 +666,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, goto end; } - cam_actuator_update_req_mgr(a_ctrl, csl_packet); + rc = cam_actuator_update_req_mgr(a_ctrl, csl_packet); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "Failed in adding request to request manager"); + goto end; + } break; case CAM_PKT_NOP_OPCODE: if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) { @@ -661,7 +681,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = -EINVAL; goto end; } - cam_actuator_update_req_mgr(a_ctrl, csl_packet); + rc = cam_actuator_update_req_mgr(a_ctrl, csl_packet); + if (rc) { + CAM_ERR(CAM_ACTUATOR, + "Failed in adding request to request manager"); + goto end; + } break; case CAM_ACTUATOR_PACKET_OPCODE_READ: { struct cam_buf_io_cfg *io_cfg; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 3212c795473e..15def761af55 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1275,7 +1275,13 @@ update_req_mgr: if (fctrl->bridge_intf.crm_cb && fctrl->bridge_intf.crm_cb->add_req) - fctrl->bridge_intf.crm_cb->add_req(&add_req); + rc = fctrl->bridge_intf.crm_cb->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in adding request: %llu to request manager", + csl_packet->header.request_id); + return rc; + } CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); } return rc; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 42f92279f0af..55779be0dac0 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -13,25 +13,34 @@ #include "cam_packet_util.h" -static void cam_sensor_update_req_mgr( +static int cam_sensor_update_req_mgr( struct cam_sensor_ctrl_t *s_ctrl, struct cam_packet *csl_packet) { + int rc = 0; struct cam_req_mgr_add_request add_req; add_req.link_hdl = s_ctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; - CAM_DBG(CAM_SENSOR, " Rxed Req Id: %lld", + CAM_DBG(CAM_SENSOR, " Rxed Req Id: %llu", csl_packet->header.request_id); add_req.dev_hdl = s_ctrl->bridge_intf.device_hdl; add_req.skip_before_applying = 0; add_req.trigger_eof = false; if (s_ctrl->bridge_intf.crm_cb && - s_ctrl->bridge_intf.crm_cb->add_req) - s_ctrl->bridge_intf.crm_cb->add_req(&add_req); + s_ctrl->bridge_intf.crm_cb->add_req) { + rc = s_ctrl->bridge_intf.crm_cb->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Adding request: %llu failed with request manager rc: %d", + csl_packet->header.request_id, rc); + return rc; + } + } - CAM_DBG(CAM_SENSOR, " add req to req mgr: %lld", + CAM_DBG(CAM_SENSOR, "Successfully add req: %llu to req mgr", add_req.req_id); + return rc; } static void cam_sensor_release_stream_rsc( @@ -248,7 +257,10 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, * and freeze. If this log is triggered then * fix it. */ - cam_sensor_update_req_mgr(s_ctrl, csl_packet); + rc = cam_sensor_update_req_mgr(s_ctrl, csl_packet); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in adding request to req_mgr"); goto end; } break; @@ -277,7 +289,10 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, goto end; } - cam_sensor_update_req_mgr(s_ctrl, csl_packet); + rc = cam_sensor_update_req_mgr(s_ctrl, csl_packet); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in adding request to req_mgr"); goto end; } default: @@ -301,7 +316,12 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE) { i2c_reg_settings->request_id = csl_packet->header.request_id; - cam_sensor_update_req_mgr(s_ctrl, csl_packet); + rc = cam_sensor_update_req_mgr(s_ctrl, csl_packet); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Failed in adding request to req_mgr"); + goto end; + } } if ((csl_packet->header.op_code & 0xFFFFFF) == From bef2e958a1602de10e5234119ac98f472438865b Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Sun, 21 Jun 2020 03:04:47 +0530 Subject: [PATCH 431/790] msm: camera: req_mgr: Support for 3 links in CRM Add third link to support 3 concurrent camera in sync. This change contain support same max pipeline delay and different max pipeline delay as well. CRs-Fixed: 2723787 Change-Id: I25e50e8e9a19c4c306a01dd3b700f8a990f3eb66 Signed-off-by: Ayush Kumar --- drivers/cam_req_mgr/cam_req_mgr_core.c | 265 +++++++++++++------------ drivers/cam_req_mgr/cam_req_mgr_core.h | 7 +- 2 files changed, 145 insertions(+), 127 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 57ef31ee552b..198be50b024e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -22,6 +22,7 @@ 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) { uint32_t pd = 0; + int i = 0; link->link_hdl = 0; link->num_devs = 0; @@ -37,7 +38,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) 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; @@ -52,12 +52,16 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->sof_timestamp = 0; link->prev_sof_timestamp = 0; link->skip_init_frame = false; + link->num_sync_links = 0; atomic_set(&link->eof_event_cnt, 0); for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { link->req.apply_data[pd].req_id = -1; link->req.prev_apply_data[pd].req_id = -1; } + + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++) + link->sync_link[i] = NULL; } void cam_req_mgr_handle_core_shutdown(void) @@ -1100,20 +1104,19 @@ static int32_t __cam_req_mgr_find_slot_for_req( */ static int __cam_req_mgr_check_sync_for_mslave( struct cam_req_mgr_core_link *link, + struct cam_req_mgr_core_link *sync_link, struct cam_req_mgr_slot *slot) { - 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; int32_t sync_num_slots = 0; - if (!link->sync_link) { + if (!sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } - sync_link = link->sync_link; req_id = slot->req_id; sync_num_slots = sync_link->req.in_q->num_slots; sync_rd_idx = sync_link->req.in_q->rd_idx; @@ -1288,15 +1291,6 @@ static int __cam_req_mgr_check_sync_for_mslave( "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; } @@ -1313,9 +1307,9 @@ static int __cam_req_mgr_check_sync_for_mslave( */ static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_core_link *link, + struct cam_req_mgr_core_link *sync_link, struct cam_req_mgr_slot *slot) { - struct cam_req_mgr_core_link *sync_link = NULL; struct cam_req_mgr_slot *sync_rd_slot = NULL; int64_t req_id = 0, sync_req_id = 0; int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; @@ -1325,12 +1319,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( uint64_t master_slave_diff = 0; bool ready = true, sync_ready = true; - if (!link->sync_link) { + if (!sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } - sync_link = link->sync_link; req_id = slot->req_id; sync_num_slots = sync_link->req.in_q->num_slots; sync_rd_idx = sync_link->req.in_q->rd_idx; @@ -1520,6 +1513,50 @@ static int __cam_req_mgr_check_sync_req_is_ready( "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); + return 0; +} + +static int __cam_req_mgr_check_multi_sync_link_ready( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_slot *slot) +{ + int i, rc = 0; + + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if (link->max_delay == link->sync_link[i]->max_delay) { + rc = __cam_req_mgr_check_sync_req_is_ready( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link %x not ready", + link->link_hdl); + return rc; + } + } else if (link->max_delay > + link->sync_link[i]->max_delay) { + link->is_master = true; + link->sync_link[i]->is_master = false; + rc = __cam_req_mgr_check_sync_for_mslave( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link%x not ready", + link->link_hdl); + return rc; + } + } else { + link->is_master = false; + link->sync_link[i]->is_master = true; + rc = __cam_req_mgr_check_sync_for_mslave( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link %x not ready", + link->link_hdl); + return rc; + } + } + } + } + /* * At this point all validation is successfully done * and we can proceed to apply the given request. @@ -1545,13 +1582,14 @@ static int __cam_req_mgr_check_sync_req_is_ready( static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_trigger_notify *trigger_data) { - int rc = 0, idx; + int rc = 0, idx, i; int reset_step = 0; uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_core_session *session; struct cam_req_mgr_connected_device *dev; + struct cam_req_mgr_core_link *tmp_link = NULL; in_q = link->req.in_q; session = (struct cam_req_mgr_core_session *)link->parent; @@ -1602,22 +1640,9 @@ 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) && - (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); - } + if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + rc = __cam_req_mgr_check_multi_sync_link_ready( + link, slot); } else { if (link->in_msync_mode) { CAM_DBG(CAM_CRM, @@ -1625,9 +1650,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, 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; + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + tmp_link = link->sync_link[i]; + tmp_link->initial_sync_req = -1; + tmp_link->in_msync_mode = false; + } } } @@ -1715,11 +1743,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); idx = in_q->rd_idx; reset_step = link->max_delay; - if (link->sync_link) { - if ((link->in_msync_mode) && - (link->sync_link->is_master)) - reset_step = - link->sync_link->max_delay; + + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if ((link->in_msync_mode) && + (link->sync_link[i]->max_delay > + reset_step)) + reset_step = + link->sync_link[i]->max_delay; + } } if (slot->req_id > 0) @@ -2160,7 +2192,10 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( in_q->num_slots = 0; link->state = CAM_CRM_LINK_STATE_IDLE; link->parent = (void *)session; - link->sync_link = NULL; + + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++) + link->sync_link[i] = NULL; + mutex_unlock(&link->lock); mutex_lock(&session->lock); @@ -2223,7 +2258,7 @@ static void __cam_req_mgr_unreserve_link( struct cam_req_mgr_core_session *session, struct cam_req_mgr_core_link *link) { - int i; + int i, j; if (!session || !link) { CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK", @@ -2242,14 +2277,16 @@ 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 (link->sync_link) { - if (link->sync_link == session->links[i]) - session->links[i]->sync_link = NULL; + for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) { + if (link->sync_link[j]) { + if (link->sync_link[j] == session->links[i]) + session->links[i]->sync_link[j] = NULL; + } } } - link->sync_link = NULL; + for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) + link->sync_link[j] = NULL; session->num_links--; CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); mutex_unlock(&session->lock); @@ -2361,7 +2398,7 @@ end: */ int cam_req_mgr_process_sched_req(void *priv, void *data) { - int rc = 0; + int rc = 0, i; struct cam_req_mgr_sched_request *sched_req = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_req_queue *in_q = NULL; @@ -2421,8 +2458,10 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) link->initial_sync_req = slot->req_id; } else { link->initial_sync_req = -1; - if (link->sync_link) - link->sync_link->initial_sync_req = -1; + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) + link->sync_link[i]->initial_sync_req = -1; + } } mutex_unlock(&link->req.lock); @@ -2655,7 +2694,7 @@ int cam_req_mgr_process_error(void *priv, void *data) __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl); in_q->rd_idx = idx; in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; - if (link->sync_link) { + if (link->sync_link[0]) { in_q->slot[idx].sync_mode = 0; __cam_req_mgr_inc_idx(&idx, 1, link->req.l_tbl->num_slots); @@ -3905,40 +3944,13 @@ 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) { - int rc = 0; + int i, j, rc = 0; + int sync_idx = 0; struct cam_req_mgr_core_session *cam_session; - struct cam_req_mgr_core_link *link1 = NULL; - struct cam_req_mgr_core_link *link2 = NULL; + struct cam_req_mgr_core_link *link[MAX_LINKS_PER_SESSION]; if (!sync_info) { CAM_ERR(CAM_CRM, "NULL pointer"); @@ -3976,58 +3988,61 @@ int cam_req_mgr_sync_config( mutex_lock(&cam_session->lock); - CAM_DBG(CAM_CRM, "link handles %x %x", - sync_info->link_hdls[0], sync_info->link_hdls[1]); + for (i = 0; i < sync_info->num_links; i++) { - /* only two links existing per session in dual cam use case*/ - link1 = cam_get_device_priv(sync_info->link_hdls[0]); - if (!link1) { - CAM_ERR(CAM_CRM, "link1 NULL pointer"); - rc = -EINVAL; - goto done; + if (!sync_info->link_hdls[i]) { + CAM_ERR(CAM_CRM, "link handle %d is null", i); + rc = -EINVAL; + goto done; + } + + link[i] = cam_get_device_priv(sync_info->link_hdls[i]); + if (!link[i]) { + CAM_ERR(CAM_CRM, "link%d NULL pointer", i); + rc = -EINVAL; + goto done; + } + + link[i]->sync_link_sof_skip = false; + link[i]->is_master = false; + link[i]->in_msync_mode = false; + link[i]->initial_sync_req = -1; + + for (j = 0; j < sync_info->num_links-1; j++) + link[i]->sync_link[j] = NULL; } - link2 = cam_get_device_priv(sync_info->link_hdls[1]); - if (!link2) { - CAM_ERR(CAM_CRM, "link2 NULL pointer"); - rc = -EINVAL; - goto done; - } - - link1->sync_link_sof_skip = false; - link1->sync_link = NULL; - - link2->sync_link_sof_skip = false; - link2->sync_link = NULL; - - link1->is_master = false; - link2->is_master = 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); + for (i = 0; i < sync_info->num_links; i++) { + j = 0; + sync_idx = 0; + CAM_DBG(CAM_REQ, "link %x adds sync link:", + link[i]->link_hdl); + while (j < sync_info->num_links) { + if (i != j) { + link[i]->sync_link[sync_idx++] = + link[j]; + link[i]->num_sync_links++; + CAM_DBG(CAM_REQ, "sync_link[%d] : %x", + sync_idx-1, link[j]->link_hdl); + } + j++; + } + link[i]->initial_skip = true; + link[i]->sof_timestamp = 0; + } } else { - /* - * Reset below info after the mode is configured - * to NO-SYNC mode since they may be overridden - * if the sync config is invoked after SOF comes. - */ - link1->initial_skip = true; - link2->initial_skip = true; - link1->sof_timestamp = 0; - link2->sof_timestamp = 0; + for (j = 0; j < sync_info->num_links; j++) { + link[j]->initial_skip = true; + link[j]->sof_timestamp = 0; + link[j]->num_sync_links = 0; + } } cam_session->sync_mode = sync_info->sync_mode; CAM_DBG(CAM_REQ, - "Sync config on link1 0x%x & link2 0x%x with sync_mode %d", - link1->link_hdl, link2->link_hdl, cam_session->sync_mode); + "Sync config completed on %d links with sync_mode %d", + sync_info->num_links, sync_info->sync_mode); done: mutex_unlock(&cam_session->lock); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index cc135d716dd3..ebe440828ecf 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -343,7 +343,8 @@ struct cam_req_mgr_connected_device { * @subscribe_event : irqs that link subscribes, IFE should send * 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 + * @sync_link : array of pointer to the sync link for synchronization + * @num_sync_links : num of links sync associated with this link * @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. @@ -387,7 +388,9 @@ struct cam_req_mgr_core_link { spinlock_t link_state_spin_lock; uint32_t subscribe_event; uint32_t trigger_mask; - struct cam_req_mgr_core_link *sync_link; + struct cam_req_mgr_core_link + *sync_link[MAXIMUM_LINKS_PER_SESSION - 1]; + int32_t num_sync_links; bool sync_link_sof_skip; int32_t open_req_cnt; uint32_t last_flush_id; From 4b9521408ed9ab1072ce23239c1369496afcf20f Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Tue, 21 Jul 2020 03:17:49 +0530 Subject: [PATCH 432/790] msm: camera: csiphy: add 1.2.5 version phy for holi camera as per hpg Implement PHY settings as per HPG version File name CRs-Fixed: 2736884 Change-Id: I01949090448d9f8ff691e40ca38a800dbc15f9d5 Signed-off-by: Tony Lijo Jose --- .../cam_csiphy/cam_csiphy_soc.c | 20 + .../cam_csiphy/cam_csiphy_soc.h | 1 + .../include/cam_csiphy_1_2_5_hwreg.h | 413 ++++++++++++++++++ 3 files changed, 434 insertions(+) create mode 100644 drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 9e15249774da..0d73d3925795 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -11,6 +11,7 @@ #include "include/cam_csiphy_1_2_1_hwreg.h" #include "include/cam_csiphy_1_2_2_hwreg.h" #include "include/cam_csiphy_1_2_3_hwreg.h" +#include "include/cam_csiphy_1_2_5_hwreg.h" #include "include/cam_csiphy_2_0_hwreg.h" #include "include/cam_csiphy_2_1_0_hwreg.h" @@ -423,6 +424,25 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_1_2_3; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.5")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_5_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_5_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_5_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2_5; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2_5; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2_5; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_5; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->hw_version = CSIPHY_VERSION_V125; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 62e50349c892..e41464a35c20 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -29,6 +29,7 @@ #define CSIPHY_VERSION_V121 0x121 #define CSIPHY_VERSION_V123 0x123 #define CSIPHY_VERSION_V124 0x124 +#define CSIPHY_VERSION_V125 0x125 #define CSIPHY_VERSION_V20 0x20 #define CSIPHY_VERSION_V201 0x201 #define CSIPHY_VERSION_V210 0x210 diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h new file mode 100644 index 000000000000..0a680857b048 --- /dev/null +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h @@ -0,0 +1,413 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSIPHY_1_2_5_HWREG_H_ +#define _CAM_CSIPHY_1_2_5_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_2_5 = { + .mipi_csiphy_interrupt_status0_addr = 0x8B0, + .mipi_csiphy_interrupt_clear0_addr = 0x858, + .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, + .csiphy_common_array_size = 6, + .csiphy_reset_array_size = 5, + .csiphy_2ph_config_array_size = 23, + .csiphy_3ph_config_array_size = 30, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_2_5[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, + {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_1_2_5[] = { + {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_1_2_5[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct +csiphy_reg_t csiphy_2ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_2_5_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x075C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct +csiphy_reg_t csiphy_3ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0984, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A84, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B84, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB4, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +#endif /* _CAM_CSIPHY_1_2_5_HWREG_H_ */ From 97eeefea15bf0591553a934cc1e487bbfc424f30 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Wed, 1 Jul 2020 12:53:59 +0530 Subject: [PATCH 433/790] msm: camera: tfe: Enable TFE and OPE for bengal Enable TFE and OPE compilation for bengal target. CRs-Fixed: 2729996 Change-Id: I648cae32f39a5bf7225c8be545f1c310e24db8e6 Signed-off-by: Trishansh Bhardwaj --- config/bengalcamera.conf | 6 ++-- config/bengalcameraconf.h | 8 ++--- drivers/cam_cdm/cam_cdm_intf.c | 8 ++--- drivers/cam_cpas/cam_cpas_hw.c | 2 +- .../isp_hw/ppi_hw/cam_csid_ppi100.c | 2 +- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 3 +- .../isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c | 30 +++++++++++++++++-- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 1 + drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 1 + drivers/camera_main.c | 1 - drivers/camera_main.h | 12 ++++---- 11 files changed, 49 insertions(+), 25 deletions(-) diff --git a/config/bengalcamera.conf b/config/bengalcamera.conf index 051268ee0ff1..38e163af7ebd 100644 --- a/config/bengalcamera.conf +++ b/config/bengalcamera.conf @@ -2,9 +2,7 @@ # Copyright (c) 2019, The Linux Foundation. All rights reserved. export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_TFE=y export CONFIG_SPECTRA_ISP=y export CONFIG_SPECTRA_SENSOR=y -export CONFIG_SPECTRA_ICP=y -export CONFIG_SPECTRA_JPEG=y -export CONFIG_SPECTRA_LRME=y -export CONFIG_SPECTRA_FD=y +export CONFIG_SPECTRA_OPE=y diff --git a/config/bengalcameraconf.h b/config/bengalcameraconf.h index 6d3b10779651..bb1f8be4012f 100644 --- a/config/bengalcameraconf.h +++ b/config/bengalcameraconf.h @@ -1,13 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_TFE 1 #define CONFIG_SPECTRA_ISP 1 #define CONFIG_SPECTRA_SENSOR 1 -#define CONFIG_SPECTRA_ICP 1 -#define CONFIG_SPECTRA_JPEG 1 -#define CONFIG_SPECTRA_LRME 1 -#define CONFIG_SPECTRA_FD 1 +#define CONFIG_SPECTRA_OPE 1 diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index 8c7fcadc91e4..04b2a7393546 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -702,10 +702,10 @@ struct platform_driver cam_cdm_intf_driver = { .probe = cam_cdm_intf_probe, .remove = cam_cdm_intf_remove, .driver = { - .name = "msm_cam_cdm_intf", - .owner = THIS_MODULE, - .of_match_table = msm_cam_cdm_intf_dt_match, - .suppress_bind_attrs = true, + .name = "msm_cam_cdm_intf", + .owner = THIS_MODULE, + .of_match_table = msm_cam_cdm_intf_dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 5b509ad51c3f..edfc42a4f2e9 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1565,7 +1565,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc); goto done; } - CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d\n", + CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d", atomic_read(&cpas_core->irq_count)); cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c index 3ad3bd9b6a78..4d7fcb537284 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c @@ -25,7 +25,7 @@ static const struct of_device_id cam_csid_ppi100_dt_match[] = { MODULE_DEVICE_TABLE(of, cam_csid_ppi100_dt_match); -static struct platform_driver cam_csid_ppi100_driver = { +struct platform_driver cam_csid_ppi100_driver = { .probe = cam_csid_ppi_probe, .remove = cam_csid_ppi_remove, .driver = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index a490088fb914..f9325204ba72 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -3018,7 +3018,8 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, for (i = 0; i < CAM_CSID_PPI_HW_MAX; i++) { rc = cam_csid_ppi_hw_init(&tfe_csid_hw->ppi_hw_intf[i], i); if (rc < 0) { - CAM_ERR(CAM_ISP, "PPI init failed for PPI %d", i); + CAM_INFO(CAM_ISP, "PPI init failed for PPI %d", i); + rc = 0; break; } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c index cb4a3b9c49d2..790ddf1a5a11 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c @@ -10,13 +10,15 @@ #include "cam_tfe_csid_dev.h" #include "cam_tfe_csid_hw_intf.h" #include "cam_debug_util.h" +#include "camera_main.h" static struct cam_hw_intf *cam_tfe_csid_hw_list[CAM_TFE_CSID_HW_NUM_MAX] = { 0, 0, 0}; static char csid_dev_name[8]; -int cam_tfe_csid_probe(struct platform_device *pdev) +static int cam_tfe_csid_component_bind(struct device *dev, + struct device *master_dev, void *data) { struct cam_hw_intf *csid_hw_intf; @@ -26,6 +28,7 @@ int cam_tfe_csid_probe(struct platform_device *pdev) struct cam_tfe_csid_hw_info *csid_hw_data = NULL; uint32_t csid_dev_idx; int rc = 0; + struct platform_device *pdev = to_platform_device(dev); CAM_DBG(CAM_ISP, "probe called"); @@ -101,11 +104,13 @@ err: return rc; } -int cam_tfe_csid_remove(struct platform_device *pdev) +void cam_tfe_csid_component_unbind(struct device *dev, + struct device *master_dev, void *data) { struct cam_tfe_csid_hw *csid_dev = NULL; struct cam_hw_intf *csid_hw_intf; struct cam_hw_info *csid_hw_info; + struct platform_device *pdev = to_platform_device(dev); csid_dev = (struct cam_tfe_csid_hw *)platform_get_drvdata(pdev); csid_hw_intf = csid_dev->hw_intf; @@ -120,6 +125,27 @@ int cam_tfe_csid_remove(struct platform_device *pdev) kfree(csid_dev); kfree(csid_hw_info); kfree(csid_hw_intf); +} + +const static struct component_ops cam_tfe_csid_component_ops = { + .bind = cam_tfe_csid_component_bind, + .unbind = cam_tfe_csid_component_unbind, +}; + +int cam_tfe_csid_probe(struct platform_device *pdev) +{ + int rc = 0; + + rc = component_add(&pdev->dev, &cam_tfe_csid_component_ops); + if (rc) + CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc); + + return rc; +} + +int cam_tfe_csid_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_tfe_csid_component_ops); return 0; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index 0d3472d2bffb..e3c7cedafff3 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -67,6 +67,7 @@ static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info, switch (core_info->hw_version) { case OPE_HW_VER_1_0_0: + case OPE_HW_VER_1_1_0: core_info->ope_hw_info->ope_hw = &ope_hw_100; break; default: diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index 2890f1579e67..ecff57eeb96b 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -7,6 +7,7 @@ #define CAM_OPE_HW_H #define OPE_HW_VER_1_0_0 0x10000000 +#define OPE_HW_VER_1_1_0 0x10010000 #define OPE_DEV_OPE 0 #define OPE_DEV_MAX 1 diff --git a/drivers/camera_main.c b/drivers/camera_main.c index ebc9559d51ab..db91401f13dc 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -79,7 +79,6 @@ static const struct camera_submodule_component camera_base[] = { static const struct camera_submodule_component camera_tfe[] = { #ifdef CONFIG_SPECTRA_TFE - {&cam_top_tpg_init_module, &cam_top_tpg_exit_module}, {&cam_csid_ppi100_init_module, &cam_csid_ppi100_exit_module}, {&cam_tfe_init_module, &cam_tfe_exit_module}, {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, diff --git a/drivers/camera_main.h b/drivers/camera_main.h index e802d64b7510..255985fc8c09 100644 --- a/drivers/camera_main.h +++ b/drivers/camera_main.h @@ -22,7 +22,7 @@ extern struct platform_driver cam_vfe_driver; extern struct platform_driver isp_driver; #endif #ifdef CONFIG_SPECTRA_TFE -extern struct platform_driver cam_top_tpg_driver; +extern struct platform_driver cam_csid_ppi100_driver; extern struct platform_driver cam_tfe_driver; extern struct platform_driver cam_tfe_csid530_driver; #endif @@ -79,6 +79,11 @@ static struct platform_driver *const cam_component_drivers[] = { &cam_cpas_driver, &cam_cdm_intf_driver, &cam_hw_cdm_driver, +#ifdef CONFIG_SPECTRA_TFE + &cam_csid_ppi100_driver, + &cam_tfe_driver, + &cam_tfe_csid530_driver, +#endif #ifdef CONFIG_SPECTRA_ISP &cam_top_tpg_driver, &cam_ife_csid17x_driver, @@ -86,11 +91,6 @@ static struct platform_driver *const cam_component_drivers[] = { &cam_vfe_driver, &isp_driver, #endif -#ifdef CONFIG_SPECTRA_TFE - &cam_top_tpg_driver, - &cam_tfe_driver, - &cam_tfe_csid530_driver, -#endif #ifdef CONFIG_SPECTRA_SENSOR &cam_res_mgr_driver, &cci_driver, From ab936609b86501ccfd03fd8c5464919aa706480e Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 23 Jul 2020 22:56:35 +0800 Subject: [PATCH 434/790] msm: camera: sensor: Only handle the valid request CRM may give an invalid request id to sensor when the first req isn't ready, since we don't have chance to update prev_apply_data in CRM. This change adds a protection in sensor side to only handle the valid request for per frame update. CRs-Fixed: 2738404 Change-Id: Ic43d68a69c10b7b063b40a0cef17e55e748b8b2a Signed-off-by: Depeng Shao --- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 42f92279f0af..6080d6075a94 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1261,7 +1261,7 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, } } } - } else { + } else if (req_id > 0) { offset = req_id % MAX_PER_FRAME_ARRAY; if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE) From bfa65377f8eb805199e4bad13c27808d436e8d0c Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 20 Jul 2020 16:41:18 +0530 Subject: [PATCH 435/790] msm: camera: common: Add support of PHY TPG deinitialization Add support of phy tpg deinit in ife HW manager. Change print statement in shima camera config. CRs-Fixed: 2732941 Change-Id: I572b19b76afdb89bda4bb1cbad7fd94bb5aa8097 Signed-off-by: Chandan Kumar Jha --- config/shimacamera.conf | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 +++ .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config/shimacamera.conf b/config/shimacamera.conf index 3b32dc7c49b2..ddc74389ec1f 100644 --- a/config/shimacamera.conf +++ b/config/shimacamera.conf @@ -3,7 +3,7 @@ ifeq ($(CONFIG_QGKI),y) export CONFIG_SPECTRA_CAMERA=m -$(info "SPECTRA_CAMERA IS STATIC") +$(info "SPECTRA_CAMERA IS MODULAR") else $(info "SPECTRA_CAMERA IS MODULAR") export CONFIG_SPECTRA_CAMERA=m diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4f07a3a2841e..697c511bcb47 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -484,6 +484,9 @@ static void cam_ife_hw_mgr_deinit_hw( return; } + if (ctx->is_tpg) + cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_tpg); + /* Deinit IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 9be459f8ee74..37d29cc03a78 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1877,7 +1877,8 @@ static int cam_ife_csid_init_config_pxl_path( */ if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF) && (camera_hw_version != CAM_CPAS_TITAN_480_V100) && - (camera_hw_version != CAM_CPAS_TITAN_580_V100)) { + (camera_hw_version != CAM_CPAS_TITAN_580_V100) && + (camera_hw_version != CAM_CPAS_TITAN_570_V200)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); val |= (1 << pxl_reg->early_eof_en_shift_val); From 151c4266836f56d2c8bea1fa86130cb515bf6400 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 12 Jun 2020 16:18:05 +0530 Subject: [PATCH 436/790] msm: camera: sensor: unregister subdev if cpas registration fails In case if the CPAS registration is failed before freeing the memory of the subdev, subdev need to be unregistered so that subdev list entry will not become NULL and other subdev can be added. CRs-Fixed: 2708016 Change-Id: I464c73411596fc562fc7a190ddfa130f23ee487a Signed-off-by: Tejas Prajapati --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 5 ++++- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index baaa37ced39b..68bd320d89a8 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -441,7 +441,7 @@ static int cam_cci_component_bind(struct device *dev, rc = cam_cpas_register_client(&cpas_parms); if (rc) { CAM_ERR(CAM_CCI, "CPAS registration failed rc:%d", rc); - goto cci_no_resource; + goto cci_unregister_subdev; } CAM_DBG(CAM_CCI, "CPAS registration successful handle=%d", @@ -449,6 +449,9 @@ static int cam_cci_component_bind(struct device *dev, new_cci_dev->cpas_handle = cpas_parms.client_handle; CAM_DBG(CAM_CCI, "Component bound successfully"); return rc; + +cci_unregister_subdev: + cam_unregister_subdev(&(new_cci_dev->v4l2_dev_str)); cci_no_resource: devm_kfree(&pdev->dev, new_cci_dev); return rc; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 9150125fe53a..1d8dc2af07c9 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -211,7 +211,7 @@ static int cam_csiphy_component_bind(struct device *dev, rc = cam_cpas_register_client(&cpas_parms); if (rc) { CAM_ERR(CAM_CSIPHY, "CPAS registration failed rc: %d", rc); - goto csiphy_no_resource; + goto csiphy_unregister_subdev; } CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d", @@ -220,6 +220,9 @@ static int cam_csiphy_component_bind(struct device *dev, CAM_DBG(CAM_CSIPHY, "%s component bound successfully", pdev->name); return rc; + +csiphy_unregister_subdev: + cam_unregister_subdev(&(new_csiphy_dev->v4l2_dev_str)); csiphy_no_resource: mutex_destroy(&new_csiphy_dev->mutex); kfree(new_csiphy_dev->ctrl_reg); From 986223aab6b9700d76df4fa3e5cfb5230f623fdd Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 17 Jul 2020 15:55:06 -0700 Subject: [PATCH 437/790] msm: camera: isp: Remove bubble re-apply recovery mechanism If a request has been applied the buffer addresses have been configured, and if a frame bubbles buf done is expected on the same frame or in the worse case on the next frame. SW should not try adding a bubbled request back to pending list without a buf done for that request. CRs-Fixed: 2729789 Change-Id: I9a2f45c58d39b659cd7a12747dc738c43cf5e0ad Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 44 +------------------------------ drivers/cam_isp/cam_isp_context.h | 2 -- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9e876f08d425..1d349f5cb74c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -987,7 +987,6 @@ static int __cam_isp_ctx_handle_buf_done_for_request( ctx->ctx_id); } else { list_add(&req->list, &ctx->pending_req_list); - ctx_isp->bubble_frame_cnt = 0; CAM_DBG(CAM_REQ, "Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u", req->request_id, ctx_isp->active_req_cnt, @@ -1311,44 +1310,6 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( * In this case, we need to skip the current notification. This * helps the state machine to catch up the delay. */ - - if (atomic_read(&ctx_isp->process_bubble)) { - - if (list_empty(&ctx->active_req_list)) { - CAM_ERR(CAM_ISP, - "No available active req in bubble"); - atomic_set(&ctx_isp->process_bubble, 0); - rc = -EINVAL; - return rc; - } - - req = list_first_entry(&ctx->active_req_list, - struct cam_ctx_request, list); - req_isp = (struct cam_isp_ctx_req *) req->req_priv; - - if (ctx_isp->bubble_frame_cnt >= 1 && - req_isp->bubble_detected) { - req_isp->num_acked = 0; - ctx_isp->bubble_frame_cnt = 0; - 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); - ctx_isp->active_req_cnt--; - CAM_DBG(CAM_REQ, - "Move active req: %lld to pending list(cnt = %d) [bubble re-apply], ctx %u", - req->request_id, - ctx_isp->active_req_cnt, ctx->ctx_id); - } else if (req_isp->bubble_detected) { - ctx_isp->bubble_frame_cnt++; - CAM_DBG(CAM_ISP, - "Waiting on bufdone for bubble req: %lld, since frame_cnt = %lld", - req->request_id, ctx_isp->bubble_frame_cnt); - } else - CAM_DBG(CAM_ISP, "Delayed bufdone for req: %lld", - req->request_id); - } - 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) { @@ -3072,7 +3033,6 @@ static int __cam_isp_ctx_flush_req_in_top_state( } end: - ctx_isp->bubble_frame_cnt = 0; atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); return rc; @@ -4728,7 +4688,6 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; - ctx_isp->bubble_frame_cnt = 0; ctx_isp->substate_activated = ctx_isp->rdi_only_context ? CAM_ISP_CTX_ACTIVATED_APPLIED : (req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH : @@ -4905,7 +4864,6 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; - ctx_isp->bubble_frame_cnt = 0; ctx_isp->last_applied_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0; atomic_set(&ctx_isp->process_bubble, 0); @@ -5380,7 +5338,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->active_req_cnt = 0; ctx->reported_req_id = 0; ctx->req_info.last_bufdone_req_id = 0; - ctx->bubble_frame_cnt = 0; + ctx->hw_ctx = NULL; ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; ctx->substate_machine = cam_isp_ctx_activated_state_machine; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index fd5c59fb47f1..9d9a71904f68 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -226,7 +226,6 @@ struct cam_isp_context_event_record { * @substate_actiavted: Current substate for the activated state. * @process_bubble: Atomic variable to check if ctx is still * processing bubble. - * @bubble_frame_cnt: Count number of frames since the req is in bubble * @substate_machine: ISP substate machine for external interface * @substate_machine_irq: ISP substate machine for irq handling * @req_base: Common request object storage @@ -267,7 +266,6 @@ struct cam_isp_context { uint32_t frame_id_meta; uint32_t substate_activated; atomic_t process_bubble; - uint32_t bubble_frame_cnt; struct cam_ctx_ops *substate_machine; struct cam_isp_ctx_irq_ops *substate_machine_irq; From 934bb3ea14dbee3310b7b8e6022f40f8e4624e9a Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 22 Jul 2020 11:03:17 -0700 Subject: [PATCH 438/790] msm: camera: ope: Fix unsequenced clang warning Address unsequenced operations to avoid any undefined behavior. CRs-Fixed: 2738394 Change-Id: Ieac88c20d1411771d8b722ccb4c417b47570f7ca Signed-off-by: Karthik Anantha Ram --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index bb1972c513b3..f16b329aaadd 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -2155,8 +2155,6 @@ static int cam_ope_mgr_process_cmd_desc(struct cam_ope_hw_mgr *hw_mgr, if (rc || !cpu_addr) { CAM_ERR(CAM_OPE, "get cmd buf failed %x", hw_mgr->iommu_hdl); - num_cmd_buf = (num_cmd_buf > 0) ? - num_cmd_buf-- : 0; goto end; } if ((len <= cmd_desc[i].offset) || From 17f1383e33401f72e9e5df9f795725abeb770cc0 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Thu, 23 Jul 2020 12:22:44 -0700 Subject: [PATCH 439/790] msm: camera: common: Improve IFE and CSIPhy logging Remove unnecessary logs from ife start, stop and release routines. Add secure mode to CSIPHY logging. CRs-Fixed: 2709537 Change-Id: Ib58d008cff5fef3d75f19c88aab76a85b5dc2e89 Signed-off-by: Jigar Agrawal Signed-off-by: Jeyaprakash Soundrapandian --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 11 +---------- .../cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 3 ++- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 233a9392a6e1..b673368258ac 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -406,9 +406,7 @@ static int cam_ife_hw_mgr_start_hw_res( "Can not start HW:%d resources", hw_intf->hw_idx); goto err; - } else - CAM_INFO(CAM_ISP, "Started HW:%d", - hw_intf->hw_idx); + } } else { CAM_ERR(CAM_ISP, "function null"); goto err; @@ -442,8 +440,6 @@ static void cam_ife_hw_mgr_stop_hw_res( hw_intf->hw_ops.stop(hw_intf->hw_priv, isp_hw_res->hw_res[i], sizeof(struct cam_isp_resource_node)); - - CAM_INFO(CAM_ISP, "Stopped Hw:%d", hw_intf->hw_idx); } else CAM_ERR(CAM_ISP, "stop null"); @@ -652,11 +648,6 @@ static int cam_ife_hw_mgr_free_hw_res( CAM_ERR(CAM_ISP, "Release HW:%d resource id %d failed", hw_intf->hw_idx, isp_hw_res->res_id); - else - CAM_DBG(CAM_ISP, - "Released HW:%d resource id %d", - hw_intf->hw_idx, isp_hw_res->res_id); - isp_hw_res->hw_res[i] = NULL; } else CAM_ERR(CAM_ISP, "Release null"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index cd046c4eacc5..b3ff2435b08b 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1264,8 +1264,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } CAM_INFO(CAM_CSIPHY, - "START_DEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", + "CAM_START_PHYDEV: CSIPHY_IDX: %d, Device_slot: %d, cp_mode: %d, Datarate: %llu, Settletime: %llu", csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].secure_mode, csiphy_dev->csiphy_info[offset].data_rate, csiphy_dev->csiphy_info[offset].settle_time); From 7ccae419d38bdb647e6dd03b1f1b2b9a781c726e Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 28 Jul 2020 15:33:46 +0800 Subject: [PATCH 440/790] msm: camera: isp: Update ife substate before apply setting Offline mode may receive the SOF and REG_UPD irq event earlier than CMD processing return back, then the event will be dropped. This change updates ife substate to APPLIED state before apply setting and move the req to wait list. CRs-Fixed: 2736862 Change-Id: I052c618ef64aae0e30232609a209a0dc43b53f8c Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index be3b123bd6a7..794c88a16c1d 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1067,6 +1067,7 @@ static int __cam_isp_ctx_apply_req_offline( void *priv, void *data) { int rc = 0; + int64_t prev_applied_req; struct cam_context *ctx = NULL; struct cam_isp_context *ctx_isp = priv; struct cam_ctx_request *req; @@ -1112,22 +1113,36 @@ static int __cam_isp_ctx_apply_req_offline( cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; + /* + * Offline mode may receive the SOF and REG_UPD earlier than + * CDM processing return back, so we set the substate before + * apply setting. + */ + spin_lock_bh(&ctx->lock); + + atomic_set(&ctx_isp->rxd_epoch, 0); + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_APPLIED; + prev_applied_req = ctx_isp->last_applied_req_id; + ctx_isp->last_applied_req_id = req->request_id; + + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->wait_req_list); + + spin_unlock_bh(&ctx->lock); + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); - } else { spin_lock_bh(&ctx->lock); - atomic_set(&ctx_isp->rxd_epoch, 0); - - ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_APPLIED; - ctx_isp->last_applied_req_id = req->request_id; + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; + ctx_isp->last_applied_req_id = prev_applied_req; list_del_init(&req->list); - list_add_tail(&req->list, &ctx->wait_req_list); + list_add(&req->list, &ctx->pending_req_list); spin_unlock_bh(&ctx->lock); - + } else { CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld", CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp->last_applied_req_id); @@ -1136,6 +1151,7 @@ static int __cam_isp_ctx_apply_req_offline( CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED, req->request_id); } + end: return rc; } From 893a5afdbfcb8028d712da02f07b17d28261b63a Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Wed, 15 Jul 2020 14:22:58 -0700 Subject: [PATCH 441/790] msm: camera: sensor: OIS lens position data infrastructure Add support to read OIS lens position data and current Qtimer value. Add support to write qtimer time stamp to OIS FW. CRs-Fixed: 2721489 Change-Id: I7a4f4d342ff41c72db892ea706d0cfd6d667d96d Signed-off-by: Sureshnaidu Laveti --- .../cam_sensor_module/cam_ois/cam_ois_core.c | 110 +++++++++++++++++- .../cam_sensor_module/cam_ois/cam_ois_dev.h | 4 +- .../cam_sensor_utils/cam_sensor_cmn_header.h | 3 +- .../cam_sensor_utils/cam_sensor_util.c | 84 ++++++++++++- .../cam_sensor_utils/cam_sensor_util.h | 16 ++- 5 files changed, 212 insertions(+), 5 deletions(-) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 3ee402e2661d..fcd7a0e7938f 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -198,6 +198,49 @@ static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl) return rc; } +static int cam_ois_update_time(struct i2c_settings_array *i2c_set) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0; + uint32_t size = 0; + uint32_t i = 0; + uint64_t qtime_ns = 0; + + if (i2c_set == NULL) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed to get current qtimer value: %d", + rc); + return rc; + } + + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + size = i2c_list->i2c_settings.size; + /* qtimer is 8 bytes so validate here*/ + if (size < 8) { + CAM_ERR(CAM_OIS, "Invalid write time settings"); + return -EINVAL; + } + for (i = 0; i < size; i++) { + CAM_DBG(CAM_OIS, "time: reg_data[%d]: 0x%x", + i, (qtime_ns & 0xFF)); + i2c_list->i2c_settings.reg_setting[i].reg_data = + (qtime_ns & 0xFF); + qtime_ns >>= 8; + } + } + } + + return rc; +} + static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, struct i2c_settings_array *i2c_set) { @@ -225,6 +268,17 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, "Failed in Applying i2c wrt settings"); return rc; } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + rc = camera_io_dev_write_continuous( + &(o_ctrl->io_master_info), + &(i2c_list->i2c_settings), + 0); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed to seq write I2C settings: %d", + rc); + return rc; + } } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { size = i2c_list->i2c_settings.size; for (i = 0; i < size; i++) { @@ -680,6 +734,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) &csl_packet->payload + csl_packet->io_configs_offset); + /* validate read data io config */ if (io_cfg == NULL) { CAM_ERR(CAM_OIS, "I/O config is invalid(NULL)"); rc = -EINVAL; @@ -693,7 +748,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) i2c_read_settings.request_id = 0; rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, &i2c_read_settings, - cmd_desc, 1, io_cfg); + cmd_desc, 1, &io_cfg[0]); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS read pkt parsing failed: %d", rc); return rc; @@ -708,6 +763,17 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) return rc; } + if (csl_packet->num_io_configs > 1) { + rc = cam_sensor_util_write_qtimer_to_io_buffer( + &io_cfg[1]); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "write qtimer failed rc: %d", rc); + delete_request(&i2c_read_settings); + return rc; + } + } + rc = delete_request(&i2c_read_settings); if (rc < 0) { CAM_ERR(CAM_OIS, @@ -716,6 +782,48 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } break; } + case CAM_OIS_PACKET_OPCODE_WRITE_TIME: { + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { + rc = -EINVAL; + CAM_ERR(CAM_OIS, + "Not in right state to write time to OIS: %d", + o_ctrl->cam_ois_state); + return rc; + } + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + i2c_reg_settings = &(o_ctrl->i2c_time_data); + i2c_reg_settings->is_settings_valid = 1; + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1, NULL); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); + return rc; + } + + rc = cam_ois_update_time(i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, "Cannot update time"); + return rc; + } + + rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, "Cannot apply mode settings"); + return rc; + } + + rc = delete_request(i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Fail deleting Mode data: rc: %d", rc); + return rc; + } + break; + } default: CAM_ERR(CAM_OIS, "Invalid Opcode: %d", (csl_packet->header.op_code & 0xFFFFFF)); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index eb0a69d11278..ddb585bc4f2b 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_OIS_DEV_H_ #define _CAM_OIS_DEV_H_ @@ -94,6 +94,7 @@ struct cam_ois_intf_params { * @bridge_intf : bridge interface params * @i2c_init_data : ois i2c init settings * @i2c_mode_data : ois i2c mode settings + * @i2c_time_data : ois i2c time write settings * @i2c_calib_data : ois i2c calib settings * @ois_device_type : ois device type * @cam_ois_state : ois_device_state @@ -116,6 +117,7 @@ struct cam_ois_ctrl_t { struct i2c_settings_array i2c_init_data; struct i2c_settings_array i2c_calib_data; struct i2c_settings_array i2c_mode_data; + struct i2c_settings_array i2c_time_data; enum msm_camera_device_type_t ois_device_type; enum cam_ois_state cam_ois_state; char ois_name[32]; diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index e18b4bb1c8d8..25ab72ae6069 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -173,7 +173,8 @@ enum cam_eeprom_packet_opcodes { enum cam_ois_packet_opcodes { CAM_OIS_PACKET_OPCODE_INIT, CAM_OIS_PACKET_OPCODE_OIS_CONTROL, - CAM_OIS_PACKET_OPCODE_READ + CAM_OIS_PACKET_OPCODE_READ, + CAM_OIS_PACKET_OPCODE_WRITE_TIME }; enum msm_bus_perf_setting { diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 5903bc1ff5fd..7334c9accbb2 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include +#include #include "cam_sensor_util.h" #include "cam_mem_mgr.h" #include "cam_res_mgr_api.h" @@ -40,6 +41,29 @@ static struct i2c_settings_list* return tmp; } +int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns) +{ + uint64_t ticks = 0; + int32_t rc = 0; + + ticks = arch_timer_read_counter(); + if (ticks == 0) { + CAM_ERR(CAM_SENSOR, "qtimer returned 0, rc:%d", rc); + return -EINVAL; + } + + if (qtime_ns != NULL) { + *qtime_ns = mul_u64_u32_div(ticks, + QTIMER_MUL_FACTOR, QTIMER_DIV_FACTOR); + CAM_DBG(CAM_SENSOR, "Qtimer time: 0x%x", *qtime_ns); + } else { + CAM_ERR(CAM_SENSOR, "NULL pointer passed"); + return -EINVAL; + } + + return rc; +} + int32_t delete_request(struct i2c_settings_array *i2c_array) { struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL; @@ -277,6 +301,64 @@ static int32_t cam_sensor_get_io_buffer( return rc; } +int32_t cam_sensor_util_write_qtimer_to_io_buffer( + struct cam_buf_io_cfg *io_cfg) +{ + uintptr_t buf_addr = 0x0, target_buf = 0x0; + size_t buf_size = 0, target_size = 0; + int32_t rc = 0; + uint64_t qtime_ns = 0; + + if (io_cfg == NULL) { + CAM_ERR(CAM_SENSOR, + "Invalid args, io buf is NULL"); + return -EINVAL; + } + + if (io_cfg->direction == CAM_BUF_OUTPUT) { + rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0], + &buf_addr, &buf_size); + if ((rc < 0) || (!buf_addr)) { + CAM_ERR(CAM_SENSOR, + "invalid buffer, rc: %d, buf_addr: %pK", + rc, buf_addr); + return -EINVAL; + } + CAM_DBG(CAM_SENSOR, + "buf_addr: %pK, buf_size: %zu, offsetsize: %d", + (void *)buf_addr, buf_size, io_cfg->offsets[0]); + if (io_cfg->offsets[0] >= buf_size) { + CAM_ERR(CAM_SENSOR, + "invalid size:io_cfg->offsets[0]: %d, buf_size: %d", + io_cfg->offsets[0], buf_size); + return -EINVAL; + } + + target_buf = buf_addr + io_cfg->offsets[0]; + target_size = buf_size - io_cfg->offsets[0]; + + if (target_size < sizeof(uint64_t)) { + CAM_ERR(CAM_SENSOR, + "not enough size for qtimer, target_size:%d", + target_size); + return -EINVAL; + } + + rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed to get qtimer rc:%d"); + return rc; + } + + memcpy((void *)target_buf, &qtime_ns, sizeof(uint64_t)); + } else { + CAM_ERR(CAM_SENSOR, "Invalid direction: %d", + io_cfg->direction); + rc = -EINVAL; + } + return rc; +} + static int32_t cam_sensor_handle_random_read( struct cam_cmd_i2c_random_rd *cmd_i2c_random_rd, struct i2c_settings_array *i2c_reg_settings, diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 3600b5636cab..690b7189e7c7 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_UTIL_H_ @@ -21,6 +21,15 @@ #define INVALID_VREG 100 +/* + * Constant Factors needed to change QTimer ticks to nanoseconds + * QTimer Freq = 19.2 MHz + * Time(us) = ticks/19.2 + * Time(ns) = ticks/19.2 * 1000 + */ +#define QTIMER_MUL_FACTOR 10000 +#define QTIMER_DIV_FACTOR 192 + int cam_get_dt_power_setting_data(struct device_node *of_node, struct cam_hw_soc_info *soc_info, struct cam_sensor_power_ctrl_t *power_info); @@ -28,6 +37,11 @@ int cam_get_dt_power_setting_data(struct device_node *of_node, int msm_camera_pinctrl_init (struct msm_pinctrl_info *sensor_pctrl, struct device *dev); +int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns); + +int32_t cam_sensor_util_write_qtimer_to_io_buffer( + struct cam_buf_io_cfg *io_cfg); + int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers, From 86f144a267ddf56c767c097c21328c6db8ddeb10 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 23 Jun 2020 22:17:18 +0800 Subject: [PATCH 442/790] msm: camera: isp: Handling IRQ delays Checking the BUS write client last consumed address, if it matches with next request port io buffer address, then irq delay detected. We can signal port fence for both active request. CRs-Fixed: 2684890 Change-Id: I8265c06a2284897d43e9a24511ad2c13c9690186 Signed-off-by: Depeng Shao --- drivers/cam_core/cam_hw_mgr_intf.h | 4 + drivers/cam_isp/cam_isp_context.c | 419 ++++++++++++++---- drivers/cam_isp/cam_isp_context.h | 2 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 38 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 29 ++ .../hw_utils/cam_isp_packet_parser.c | 21 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 3 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 19 +- .../isp_hw/include/cam_vfe_hw_intf.h | 6 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 1 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 42 ++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h | 2 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 3 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 3 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 10 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 12 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 56 ++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 14 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 8 +- 26 files changed, 579 insertions(+), 120 deletions(-) diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 12b01ab688eb..626b3be1489e 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -74,11 +74,13 @@ struct cam_hw_update_entry { * * @resrouce_handle: Resource port id for the buffer * @sync_id: Sync id + * @image_buf_addr: Image buffer address array * */ struct cam_hw_fence_map_entry { uint32_t resource_handle; int32_t sync_id; + int32_t image_buf_addr[CAM_PACKET_MAX_PLANES]; }; /** @@ -107,6 +109,7 @@ struct cam_hw_done_event_data { * @ctxt_to_hw_map: HW context (returned) * @custom_enabled: ctx has custom enabled * @use_frame_header_ts: Use frame header for qtimer ts + * @support_consumed_addr: The platform has last consumed addr register * @acquired_hw_id: Acquired hardware mask * @acquired_hw_path: Acquired path mask for an input * if input splits into multiple paths, @@ -123,6 +126,7 @@ struct cam_hw_acquire_args { void *ctxt_to_hw_map; bool custom_enabled; bool use_frame_header_ts; + bool support_consumed_addr; uint32_t acquired_hw_id[CAM_MAX_ACQ_RES]; uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index be3b123bd6a7..811d38a5891c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -790,6 +790,70 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( } } +static int __cam_isp_ctx_handle_buf_done_for_req_list( + struct cam_isp_context *ctx_isp, + struct cam_ctx_request *req) +{ + int rc = 0, i; + uint64_t buf_done_req_id; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + ctx_isp->active_req_cnt--; + buf_done_req_id = req->request_id; + + if (req_isp->bubble_detected && req_isp->bubble_report) { + req_isp->num_acked = 0; + req_isp->bubble_detected = false; + list_del_init(&req->list); + atomic_set(&ctx_isp->process_bubble, 0); + + if (buf_done_req_id <= ctx->last_flush_req) { + for (i = 0; i < req_isp->num_fence_map_out; i++) + rc = cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + + list_add_tail(&req->list, &ctx->free_req_list); + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", + buf_done_req_id, ctx_isp->active_req_cnt, + ctx->ctx_id); + } else { + list_add(&req->list, &ctx->pending_req_list); + CAM_DBG(CAM_REQ, + "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 { + if (!ctx_isp->use_frame_header_ts) { + if (ctx_isp->reported_req_id < buf_done_req_id) { + ctx_isp->reported_req_id = buf_done_req_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, + buf_done_req_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + req_isp->reapply = false; + + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", + buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + ctx_isp->req_info.last_bufdone_req_id = req->request_id; + } + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); + + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_BUFDONE, req); + return rc; +} + static int __cam_isp_ctx_handle_buf_done_for_request( struct cam_isp_context *ctx_isp, struct cam_ctx_request *req, @@ -801,7 +865,6 @@ static int __cam_isp_ctx_handle_buf_done_for_request( int i, j; struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; - uint64_t buf_done_req_id; const char *handle_type; trace_cam_buf_done("ISP", ctx, req); @@ -811,10 +874,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", bubble_state, req_isp->bubble_detected); - if (done_next_req) { - done_next_req->num_handles = 0; - done_next_req->timestamp = done->timestamp; - } + done_next_req->num_handles = 0; + done_next_req->timestamp = done->timestamp; for (i = 0; i < done->num_handles; i++) { for (j = 0; j < req_isp->num_fence_map_out; j++) { @@ -824,28 +885,21 @@ static int __cam_isp_ctx_handle_buf_done_for_request( } if (j == req_isp->num_fence_map_out) { - if (done_next_req) { - /* - * If not found in current request, it could be - * belonging to next request, This can happen if - * IRQ delay happens. - */ - CAM_WARN(CAM_ISP, - "BUF_DONE for res 0x%x not found in Req %lld ", - __cam_isp_resource_handle_id_to_type( - done->resource_handle[i]), - req->request_id); + /* + * If not found in current request, it could be + * belonging to next request, this can happen if + * IRQ delay happens. It is only valid when the + * platform doesn't have last consumed address. + */ + CAM_WARN(CAM_ISP, + "BUF_DONE for res %s not found in Req %lld ", + __cam_isp_resource_handle_id_to_type( + done->resource_handle[i]), + req->request_id); - done_next_req->resource_handle - [done_next_req->num_handles++] = - done->resource_handle[i]; - } else { - CAM_ERR(CAM_ISP, - "Can not find matching lane handle 0x%x! in Req %lld", - done->resource_handle[i], - req->request_id); - rc = -EINVAL; - } + done_next_req->resource_handle + [done_next_req->num_handles++] = + done->resource_handle[i]; continue; } @@ -866,12 +920,9 @@ static int __cam_isp_ctx_handle_buf_done_for_request( trace_cam_log_event("Duplicate BufDone", handle_type, req->request_id, ctx->ctx_id); - if (done_next_req) { - done_next_req->resource_handle - [done_next_req->num_handles++] = - done->resource_handle[i]; - } - + done_next_req->resource_handle + [done_next_req->num_handles++] = + done->resource_handle[i]; continue; } @@ -944,68 +995,156 @@ static int __cam_isp_ctx_handle_buf_done_for_request( if (req_isp->num_acked != req_isp->num_fence_map_out) return rc; - ctx_isp->active_req_cnt--; - buf_done_req_id = req->request_id; - - if (req_isp->bubble_detected && req_isp->bubble_report) { - req_isp->num_acked = 0; - req_isp->bubble_detected = false; - list_del_init(&req->list); - atomic_set(&ctx_isp->process_bubble, 0); - - if (buf_done_req_id <= ctx->last_flush_req) { - for (i = 0; i < req_isp->num_fence_map_out; i++) - cam_sync_signal( - req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); - - list_add_tail(&req->list, &ctx->free_req_list); - CAM_DBG(CAM_REQ, - "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", - buf_done_req_id, ctx_isp->active_req_cnt, - ctx->ctx_id); - } else { - list_add(&req->list, &ctx->pending_req_list); - CAM_DBG(CAM_REQ, - "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 { - - if (!ctx_isp->use_frame_header_ts) { - if (ctx_isp->reported_req_id < buf_done_req_id) { - ctx_isp->reported_req_id = buf_done_req_id; - __cam_isp_ctx_send_sof_timestamp(ctx_isp, - buf_done_req_id, - CAM_REQ_MGR_SOF_EVENT_SUCCESS); - } - } - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->free_req_list); - req_isp->reapply = false; - - CAM_DBG(CAM_REQ, - "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", - buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); - ctx_isp->req_info.last_bufdone_req_id = req->request_id; - } - - __cam_isp_ctx_update_state_monitor_array(ctx_isp, - CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); - - __cam_isp_ctx_update_event_record(ctx_isp, - CAM_ISP_CTX_EVENT_BUFDONE, req); + rc = __cam_isp_ctx_handle_buf_done_for_req_list(ctx_isp, req); return rc; } -static int __cam_isp_ctx_handle_buf_done_in_activated_state( +static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + struct cam_isp_context *ctx_isp, + struct cam_ctx_request *req, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state, + bool verify_consumed_addr) +{ + int rc = 0; + int i, j; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + const char *handle_type; + + trace_cam_buf_done("ISP", ctx, req); + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", + bubble_state, req_isp->bubble_detected); + + for (i = 0; i < done->num_handles; i++) { + for (j = 0; j < req_isp->num_fence_map_out; j++) { + if (verify_consumed_addr && + (done->last_consumed_addr[i] != + req_isp->fence_map_out[j].image_buf_addr[0])) + continue; + + if (done->resource_handle[i] == + req_isp->fence_map_out[j].resource_handle) + break; + } + + if (j == req_isp->num_fence_map_out) { + /* + * If not found in current request, it could be + * belonging to next request, this can happen if + * IRQ delay happens. It is only valid when the + * platform doesn't have last consumed address. + */ + CAM_DBG(CAM_ISP, + "BUF_DONE for res %s not found in Req %lld ", + __cam_isp_resource_handle_id_to_type( + done->resource_handle[i]), + req->request_id); + continue; + } + + if (req_isp->fence_map_out[j].sync_id == -1) { + if (ctx_isp->isp_device_type == CAM_IFE_DEVICE_TYPE) + handle_type = + __cam_isp_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + else + handle_type = + __cam_isp_tfe_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + + CAM_WARN(CAM_ISP, + "Duplicate BUF_DONE for req %lld : i=%d, j=%d, res=%s", + req->request_id, i, j, handle_type); + + trace_cam_log_event("Duplicate BufDone", + handle_type, req->request_id, ctx->ctx_id); + continue; + } + + if (!req_isp->bubble_detected) { + 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, + ctx->ctx_id); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS); + if (rc) + CAM_DBG(CAM_ISP, "Sync failed with rc = %d", + rc); + } else if (!req_isp->bubble_report) { + 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, + ctx->ctx_id); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) + CAM_ERR(CAM_ISP, "Sync failed with rc = %d", + rc); + } else { + /* + * Ignore the buffer done if bubble detect is on + * Increment the ack number here, and queue the + * request back to pending list whenever all the + * buffers are done. + */ + req_isp->num_acked++; + CAM_DBG(CAM_ISP, + "buf done with bubble state %d recovery %d", + bubble_state, req_isp->bubble_report); + continue; + } + + CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x ctx %u", + req->request_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; + } + + if ((ctx_isp->use_frame_header_ts) && + (req_isp->hw_update_data.frame_header_res_id == + req_isp->fence_map_out[j].resource_handle)) + __cam_isp_ctx_send_sof_timestamp_frame_header( + ctx_isp, + req_isp->hw_update_data.frame_header_cpu_addr, + req->request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } + + 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, ctx %u", + req->request_id, req_isp->num_acked, + req_isp->num_fence_map_out, ctx->ctx_id); + WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out); + } + + if (req_isp->num_acked != req_isp->num_fence_map_out) + return rc; + + rc = __cam_isp_ctx_handle_buf_done_for_req_list(ctx_isp, req); + return rc; +} + +static int __cam_isp_ctx_handle_buf_done( struct cam_isp_context *ctx_isp, struct cam_isp_hw_done_event_data *done, uint32_t bubble_state) { int rc = 0; - struct cam_ctx_request *req; + struct cam_ctx_request *req; struct cam_context *ctx = ctx_isp->base; struct cam_isp_hw_done_event_data done_next_req; @@ -1063,6 +1202,111 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( return rc; } +static void __cam_isp_ctx_buf_done_match_req( + struct cam_ctx_request *req, + struct cam_isp_hw_done_event_data *done, + bool *irq_delay_detected) +{ + int i, j; + uint32_t match_count = 0; + struct cam_isp_ctx_req *req_isp; + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + for (i = 0; i < done->num_handles; i++) { + for (j = 0; j < req_isp->num_fence_map_out; j++) { + if ((done->resource_handle[i] == + req_isp->fence_map_out[j].resource_handle) && + (done->last_consumed_addr[i] == + req_isp->fence_map_out[j].image_buf_addr[0])) { + match_count++; + break; + } + } + } + + if (match_count > 0) + *irq_delay_detected = true; + else + *irq_delay_detected = false; + + CAM_DBG(CAM_ISP, + "buf done num handles %d match count %d for next req:%lld", + done->num_handles, match_count, req->request_id); +} + +static int __cam_isp_ctx_handle_buf_done_verify_addr( + struct cam_isp_context *ctx_isp, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state) +{ + int rc = 0; + bool irq_delay_detected = false; + struct cam_ctx_request *req; + struct cam_ctx_request *next_req = NULL; + struct cam_context *ctx = ctx_isp->base; + + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_ISP, "Buf done with no active request"); + return 0; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + + if (ctx_isp->active_req_cnt > 1) { + next_req = list_last_entry( + &ctx->active_req_list, + struct cam_ctx_request, list); + + if (next_req->request_id != req->request_id) + __cam_isp_ctx_buf_done_match_req(next_req, done, + &irq_delay_detected); + else + CAM_WARN(CAM_ISP, + "Req %lld only active request, spurious buf_done rxd", + req->request_id); + } + + /* + * If irq delay isn't detected, then we need to verify + * the consumed address for current req, otherwise, we + * can't verify the consumed address. + */ + rc = __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + ctx_isp, req, done, bubble_state, + !irq_delay_detected); + + /* + * Verify the consumed address for next req all the time, + * since the reported buf done event may belong to current + * req, then we can't signal this event for next req. + */ + if (!rc && irq_delay_detected) + rc = __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + ctx_isp, next_req, done, + bubble_state, true); + + return rc; +} + +static int __cam_isp_ctx_handle_buf_done_in_activated_state( + struct cam_isp_context *ctx_isp, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state) +{ + int rc = 0; + + if (ctx_isp->support_consumed_addr) + rc = __cam_isp_ctx_handle_buf_done_verify_addr( + ctx_isp, done, bubble_state); + else + rc = __cam_isp_ctx_handle_buf_done( + ctx_isp, done, bubble_state); + + return rc; +} + static int __cam_isp_ctx_apply_req_offline( void *priv, void *data) { @@ -3663,6 +3907,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; + ctx_isp->support_consumed_addr = false; ctx_isp->req_info.last_bufdone_req_id = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -4340,6 +4585,8 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, */ ctx_isp->custom_enabled = param.custom_enabled; ctx_isp->use_frame_header_ts = param.use_frame_header_ts; + ctx_isp->support_consumed_addr = + param.support_consumed_addr; /* Query the context has rdi only resource */ hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 0847a1d7c9b0..26cc377c608f 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -251,6 +251,7 @@ struct cam_isp_context_event_record { * @split_acquire: Indicate whether a separate acquire is expected * @custom_enabled: Custom HW enabled for this ctx * @use_frame_header_ts: Use frame header for qtimer ts + * @support_consumed_addr: Indicate whether HW has last consumed addr reg * @init_timestamp: Timestamp at which this context is initialized * @isp_device_type: ISP device type * @rxd_epoch: Indicate whether epoch has been received. Used to @@ -294,6 +295,7 @@ struct cam_isp_context { bool split_acquire; bool custom_enabled; bool use_frame_header_ts; + bool support_consumed_addr; unsigned int init_timestamp; uint32_t isp_device_type; atomic_t rxd_epoch; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index edc6d34cfc9d..c67c5754cccb 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2982,6 +2982,32 @@ static int cam_ife_mgr_acquire_get_unified_structure( return 0; } +static bool cam_ife_mgr_is_consumed_addr_supported( + struct cam_ife_hw_mgr_ctx *ctx) +{ + bool support_consumed_addr = false; + struct cam_isp_hw_mgr_res *isp_hw_res = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_hw_res = &ctx->res_list_ife_out[0]; + + if (!isp_hw_res || !isp_hw_res->hw_res[0]) { + CAM_ERR(CAM_ISP, "Invalid ife out res."); + goto end; + } + + hw_intf = isp_hw_res->hw_res[0]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + &support_consumed_addr, + sizeof(support_consumed_addr)); + } + +end: + return support_consumed_addr; +} + /* entry function: acquire_hw */ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -3144,6 +3170,9 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->internal_cdm = true; atomic_set(&ife_ctx->cdm_done, 1); + acquire_args->support_consumed_addr = + cam_ife_mgr_is_consumed_addr_supported(ife_ctx); + acquire_args->ctxt_to_hw_map = ife_ctx; acquire_args->custom_enabled = ife_ctx->custom_enabled; acquire_args->use_frame_header_ts = @@ -7303,7 +7332,7 @@ static int cam_ife_hw_mgr_handle_hw_epoch( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; - epoch_done_event_data.frame_id_meta = event_info->th_reg_val; + epoch_done_event_data.frame_id_meta = event_info->reg_val; ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); @@ -7456,6 +7485,8 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( buf_done_event_data.num_handles = 1; buf_done_event_data.resource_handle[0] = event_info->res_id; + buf_done_event_data.last_consumed_addr[0] = + event_info->reg_val; if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) return 0; @@ -7466,8 +7497,9 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); } - CAM_DBG(CAM_ISP, "Buf done for VFE:%d out_res->res_id: 0x%x", - event_info->hw_idx, event_info->res_id); + CAM_DBG(CAM_ISP, + "Buf done for VFE:%d res_id: 0x%x last consumed addr: 0x%x", + event_info->hw_idx, event_info->res_id, event_info->reg_val); return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 7523c699613f..8a26c06e7cd0 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1733,6 +1733,32 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, } } +static bool cam_tfe_mgr_is_consumed_addr_supported( + struct cam_tfe_hw_mgr_ctx *ctx) +{ + bool support_consumed_addr = false; + struct cam_isp_hw_mgr_res *isp_hw_res = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_hw_res = &ctx->res_list_tfe_out[0]; + + if (!isp_hw_res || !isp_hw_res->hw_res[0]) { + CAM_ERR(CAM_ISP, "Invalid ife out res."); + goto end; + } + + hw_intf = isp_hw_res->hw_res[0]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + &support_consumed_addr, + sizeof(support_consumed_addr)); + } + +end: + return support_consumed_addr; +} + /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -1942,6 +1968,9 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->ctx_in_use = 1; tfe_ctx->num_reg_dump_buf = 0; + acquire_args->support_consumed_addr = + cam_tfe_mgr_is_consumed_addr_supported(tfe_ctx); + cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx); CAM_DBG(CAM_ISP, "Exit...(success)"); diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index c498233f48e8..6cad5f6e73ed 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -481,6 +481,8 @@ int cam_isp_add_io_buffers( uint32_t i, j, num_out_buf, num_in_buf; uint32_t res_id_out, res_id_in, plane_id; uint32_t io_cfg_used_bytes, num_ent; + uint32_t *image_buf_addr; + uint32_t *image_buf_offset; uint64_t iova_addr; size_t size; int32_t hdl; @@ -696,6 +698,11 @@ int cam_isp_add_io_buffers( wm_update.num_buf = plane_id; wm_update.io_cfg = &io_cfg[i]; wm_update.frame_header = 0; + + for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) + wm_update.image_buf_offset[plane_id] = 0; + iova_addr = frame_header_info->frame_header_iova_addr; if ((frame_header_info->frame_header_enable) && !(frame_header_info->frame_header_res_id)) { @@ -728,6 +735,20 @@ int cam_isp_add_io_buffers( return rc; } io_cfg_used_bytes += update_buf.cmd.used_bytes; + + + image_buf_addr = + out_map_entries->image_buf_addr; + image_buf_offset = + wm_update.image_buf_offset; + if (j == CAM_ISP_HW_SPLIT_LEFT) { + for (plane_id = 0; + plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) + image_buf_addr[plane_id] = + io_addr[plane_id] + + image_buf_offset[plane_id]; + } } for (j = 0; j < CAM_ISP_HW_SPLIT_MAX && io_cfg[i].direction == CAM_BUF_INPUT; j++) { diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 61b646a1e4aa..4243f1acebfc 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -179,6 +179,7 @@ struct cam_isp_hw_epoch_event_data { * * @num_handles: Number of resource handeles * @resource_handle: Resource handle array + * @last_consumed_addr: Last consumed addr * @timestamp: Timestamp for the buf done event * */ @@ -186,6 +187,8 @@ struct cam_isp_hw_done_event_data { uint32_t num_handles; uint32_t resource_handle[ CAM_NUM_OUT_PER_COMP_IRQ_MAX]; + uint32_t last_consumed_addr[ + CAM_NUM_OUT_PER_COMP_IRQ_MAX]; uint64_t timestamp; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 22a75b91203a..9181fdc2eb40 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -120,6 +120,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_DUMP_HW, CAM_ISP_HW_CMD_FE_TRIGGER_CMD, CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, CAM_ISP_HW_CMD_MAX, }; @@ -183,7 +184,7 @@ struct cam_isp_resource_node { * @res_id: Unique resource ID * @hw_idx: IFE hw index * @err_type: Error type if any - * @th_reg_val: Any critical register value captured during th + * @reg_val: Any critical register value captured during irq handling * */ struct cam_isp_hw_event_info { @@ -191,7 +192,7 @@ struct cam_isp_hw_event_info { uint32_t res_id; uint32_t hw_idx; uint32_t err_type; - uint32_t th_reg_val; + uint32_t reg_val; }; /* @@ -213,17 +214,19 @@ struct cam_isp_hw_cmd_buf_update { /* * struct cam_isp_hw_get_wm_update: * - * @Brief: Get cmd buffer for WM updates. + * @Brief: Get cmd buffer for WM updates. * - * @ image_buf: image buffer address array - * @ num_buf: Number of buffers in the image_buf array - * @ frame_header: frame header iova - * @ local_id: local id for the wm - * @ io_cfg: IO buffer config information sent from UMD + * @ image_buf: image buffer address array + * @ image_buf_offset: image buffer address offset array + * @ num_buf: Number of buffers in the image_buf array + * @ frame_header: frame header iova + * @ local_id: local id for the wm + * @ io_cfg: IO buffer config information sent from UMD * */ struct cam_isp_hw_get_wm_update { dma_addr_t *image_buf; + uint32_t image_buf_offset[CAM_PACKET_MAX_PLANES]; uint32_t num_buf; uint64_t frame_header; uint32_t local_id; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 41c4564eb390..adb33444cf8c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -289,15 +289,15 @@ struct cam_vfe_bw_control_args { * @list: list_head node for the payload * @irq_reg_val: IRQ and Error register values, read when IRQ was * handled - * @th_reg_val: Value of any critical register that needs to be - * read at th to avoid any latencies in bh processing + * @reg_val: Value of any critical register that needs to be + * read at during irq handling * * @ts: Timestamp */ struct cam_vfe_top_irq_evt_payload { struct list_head list; uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX]; - uint32_t th_reg_val; + uint32_t reg_val; struct cam_isp_timestamp ts; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index d22836edc951..6be379a393ac 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -820,6 +820,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { 0xD0000000, 0x00000000, }, + .support_consumed_addr = true, }; struct cam_tfe_hw_info cam_tfe530 = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 01ffb90d7461..afa5464afd63 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -71,6 +71,7 @@ struct cam_tfe_bus_common_data { uint32_t num_sec_out; uint32_t comp_done_shift; bool is_lite; + bool support_consumed_addr; cam_hw_mgr_event_cb_func event_cb; bool rup_irq_enable[CAM_TFE_BUS_RUP_GRP_MAX]; }; @@ -95,6 +96,7 @@ struct cam_tfe_bus_wm_resource_data { uint32_t framedrop_pattern; uint32_t en_cfg; + uint32_t image_addr_offset; uint32_t is_dual; uint32_t acquired_width; @@ -124,6 +126,7 @@ struct cam_tfe_bus_tfe_out_data { uint32_t rup_group_id; uint32_t source_group; struct cam_tfe_bus_common_data *common_data; + struct cam_tfe_bus_priv *bus_priv; uint32_t num_wm; struct cam_isp_resource_node *wm_res[PLANE_MAX]; @@ -1221,6 +1224,7 @@ static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, rsrc_data->common_data->event_cb = acq_args->event_cb; rsrc_data->event_cb = acq_args->event_cb; rsrc_data->priv = acq_args->priv; + rsrc_data->bus_priv = bus_priv; secure_caps = cam_tfe_bus_can_be_secure(rsrc_data->out_id); mode = out_acquire_args->out_port_info->secure_mode; @@ -1643,6 +1647,31 @@ static int cam_tfe_bus_rup_bottom_half( return 0; } +static uint32_t cam_tfe_bus_get_last_consumed_addr( + struct cam_tfe_bus_priv *bus_priv, + uint32_t res_id) +{ + uint32_t val = 0; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_rsrc_data = NULL; + + if (res_id >= CAM_TFE_BUS_TFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "invalid res id:%u", res_id); + return 0; + } + + rsrc_node = &bus_priv->tfe_out[res_id]; + rsrc_data = rsrc_node->res_priv; + wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv; + + val = cam_io_r_mb( + wm_rsrc_data->common_data->mem_base + + wm_rsrc_data->hw_regs->addr_status_0); + + return val; +} + static int cam_tfe_bus_bufdone_bottom_half( struct cam_tfe_bus_priv *bus_priv, struct cam_tfe_irq_evt_payload *evt_payload) @@ -1673,6 +1702,10 @@ static int cam_tfe_bus_bufdone_bottom_half( evt_info.res_type = out_rsrc->res_type; evt_info.hw_idx = out_rsrc->hw_intf->hw_idx; evt_info.res_id = out_rsrc->res_id; + evt_info.reg_val = + cam_tfe_bus_get_last_consumed_addr( + out_rsrc_data->bus_priv, + evt_info.res_id); out_rsrc_data->event_cb(out_rsrc_data->priv, CAM_ISP_HW_EVENT_DONE, (void *)&evt_info); @@ -2117,6 +2150,7 @@ static int cam_tfe_bus_process_cmd(void *priv, struct cam_tfe_bus_priv *bus_priv; int rc = -EINVAL; uint32_t i, val; + bool *support_consumed_addr; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -2148,6 +2182,12 @@ static int cam_tfe_bus_process_cmd(void *priv, bus_priv->common_data.common_reg->irq_mask[i]); } break; + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + bus_priv = (struct cam_tfe_bus_priv *) priv; + support_consumed_addr = (bool *)cmd_args; + *support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -2208,6 +2248,8 @@ int cam_tfe_bus_init( bus_priv->common_data.common_reg = &hw_info->common_reg; bus_priv->comp_buf_done_mask = hw_info->comp_buf_done_mask; bus_priv->comp_rup_done_mask = hw_info->comp_rup_done_mask; + bus_priv->common_data.support_consumed_addr = + hw_info->support_consumed_addr; for (i = 0; i < CAM_TFE_BUS_IRQ_REGISTERS_MAX; i++) bus_priv->bus_irq_error_mask[i] = diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h index db34083ede00..2b2ca16ab1d5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h @@ -180,6 +180,7 @@ struct cam_tfe_bus_tfe_out_hw_info { * @comp_buf_done_mask: Composite buf done bits mask * @comp_rup_done_mask: Reg update done mask * @bus_irq_error_mask: Bus irq error mask bits + * @support_consumed_addr: Indicate if bus support consumed address */ struct cam_tfe_bus_hw_info { struct cam_tfe_bus_reg_offset_common common_reg; @@ -194,6 +195,7 @@ struct cam_tfe_bus_hw_info { uint32_t comp_buf_done_mask; uint32_t comp_rup_done_mask; uint32_t bus_irq_error_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; + bool support_consumed_addr; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 9c82d7cbca88..36a87fe3101b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -2808,6 +2808,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_STRIPE_UPDATE: case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: case CAM_ISP_HW_CMD_GET_SECURE_MODE: + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: rc = core_info->tfe_bus->hw_ops.process_cmd( core_info->tfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index bcb926324621..8eaca71f1e38 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -615,6 +615,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index d0f85565a968..aa42c874e40f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -860,6 +860,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe170_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h index 9aa1c05c1904..670316b85c95 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h @@ -828,6 +828,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_150_bus_hw_info = { .max_height = -1, }, }, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe170_150_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index 111eb486d592..7b7dee78b9f8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -1021,6 +1021,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe175_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index ce0739d386cd..dd74b028f934 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -1136,6 +1136,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe175_130_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 1d9173a0c73b..bda439a4c959 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1314,6 +1314,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { }, .comp_done_shift = 6, .top_irq_shift = 7, + .support_consumed_addr = true, }; static struct cam_irq_register_set vfe480_bus_rd_irq_reg[1] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index be6d1ada950d..8139744ce84a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE17X_H_ @@ -324,6 +324,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe17x_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe_lite17x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 09da6810fd4b..730af4c945c2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE48x_H_ @@ -395,6 +395,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { }, .comp_done_shift = 4, .top_irq_shift = 4, + .support_consumed_addr = true, }; static struct cam_vfe_hw_info cam_vfe_lite48x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 1771ed7d529b..82d0f555faba 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -100,6 +100,7 @@ struct cam_vfe_bus_ver2_common_data { uint32_t addr_no_sync; cam_hw_mgr_event_cb_func event_cb; bool hw_init; + bool support_consumed_addr; }; struct cam_vfe_bus_ver2_wm_resource_data { @@ -3583,6 +3584,7 @@ static int cam_vfe_bus_process_cmd( int rc = -EINVAL; struct cam_vfe_bus_ver2_priv *bus_priv; uint32_t top_mask_0 = 0; + bool *support_consumed_addr; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3629,6 +3631,12 @@ static int cam_vfe_bus_process_cmd( cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->top_irq_mask_0); break; + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + support_consumed_addr = (bool *)cmd_args; + *support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3691,6 +3699,8 @@ int cam_vfe_bus_ver2_init( bus_priv->common_data.addr_no_sync = CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL; bus_priv->common_data.hw_init = false; + bus_priv->common_data.support_consumed_addr = + ver2_hw_info->support_consumed_addr; mutex_init(&bus_priv->common_data.bus_mutex); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index e611113bedd2..cfb8dda17d9f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -174,11 +174,12 @@ struct cam_vfe_bus_ver2_vfe_out_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 - * @top_irq_shift: Mask shift for top level BUS WR irq + * @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 + * @top_irq_shift: Mask shift for top level BUS WR irq + * @support_consumed_addr: Indicate if bus support consumed address */ struct cam_vfe_bus_ver2_hw_info { struct cam_vfe_bus_ver2_reg_offset_common common_reg; @@ -191,6 +192,7 @@ struct cam_vfe_bus_ver2_hw_info { struct cam_vfe_bus_ver2_vfe_out_hw_info vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; uint32_t top_irq_shift; + bool support_consumed_addr; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 9c0f86799058..727febe397ba 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -90,6 +90,7 @@ struct cam_vfe_bus_ver3_common_data { uint32_t comp_done_shift; bool is_lite; bool hw_init; + bool support_consumed_addr; cam_hw_mgr_event_cb_func event_cb; int rup_irq_handle[CAM_VFE_BUS_VER3_SRC_GRP_MAX]; }; @@ -157,6 +158,7 @@ struct cam_vfe_bus_ver3_vfe_out_data { uint32_t out_type; uint32_t source_group; struct cam_vfe_bus_ver3_common_data *common_data; + struct cam_vfe_bus_ver3_priv *bus_priv; uint32_t num_wm; struct cam_isp_resource_node *wm_res[PLANE_MAX]; @@ -2186,6 +2188,7 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, rsrc_data = rsrc_node->res_priv; rsrc_data->common_data->event_cb = acq_args->event_cb; rsrc_data->priv = acq_args->priv; + rsrc_data->bus_priv = ver3_bus_priv; secure_caps = cam_vfe_bus_ver3_can_be_secure( rsrc_data->out_type); @@ -2552,6 +2555,34 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, return rc; } +static uint32_t cam_vfe_bus_ver3_get_last_consumed_addr( + struct cam_vfe_bus_ver3_priv *bus_priv, + uint32_t res_type) +{ + uint32_t val = 0; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_rsrc_data = NULL; + enum cam_vfe_bus_ver3_vfe_out_type res_id; + + res_id = cam_vfe_bus_ver3_get_out_res_id(res_type); + + if (res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "invalid res id:%u", res_id); + return 0; + } + + rsrc_node = &bus_priv->vfe_out[res_id]; + rsrc_data = rsrc_node->res_priv; + wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv; + + val = cam_io_r_mb( + wm_rsrc_data->common_data->mem_base + + wm_rsrc_data->hw_regs->addr_status_0); + + return val; +} + static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( void *handler_priv, void *evt_payload_priv) @@ -2586,6 +2617,10 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( rsrc_data->common_data->is_lite); for (i = 0; i < num_out; i++) { evt_info.res_id = out_list[i]; + evt_info.reg_val = + cam_vfe_bus_ver3_get_last_consumed_addr( + rsrc_data->bus_priv, + evt_info.res_id); if (rsrc_data->common_data->event_cb) rsrc_data->common_data->event_cb(ctx, evt_id, (void *)&evt_info); @@ -3110,22 +3145,28 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, /* WM Image address */ for (k = 0; k < loop_size; k++) { - if (wm_data->en_ubwc) + if (wm_data->en_ubwc) { CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_addr, update_buf->wm_update->image_buf[i] + io_cfg->planes[i].meta_size + k * frame_inc); - else if (wm_data->en_cfg & (0x3 << 16)) + update_buf->wm_update->image_buf_offset[i] = + io_cfg->planes[i].meta_size; + } else if (wm_data->en_cfg & (0x3 << 16)) { CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_addr, (update_buf->wm_update->image_buf[i] + wm_data->offset + k * frame_inc)); - else + update_buf->wm_update->image_buf_offset[i] = + wm_data->offset; + } else { CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_addr, (update_buf->wm_update->image_buf[i] + k * frame_inc)); + update_buf->wm_update->image_buf_offset[i] = 0; + } CAM_DBG(CAM_ISP, "WM:%d image address 0x%X", wm_data->index, reg_val_pair[j-1]); @@ -3661,6 +3702,7 @@ static int cam_vfe_bus_ver3_process_cmd( int rc = -EINVAL; struct cam_vfe_bus_ver3_priv *bus_priv; uint32_t top_mask_0 = 0; + bool *support_consumed_addr; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3718,6 +3760,12 @@ static int cam_vfe_bus_ver3_process_cmd( cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->top_irq_mask_0); break; + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + support_consumed_addr = (bool *)cmd_args; + *support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3790,6 +3838,8 @@ int cam_vfe_bus_ver3_init( bus_priv->common_data.hw_init = false; bus_priv->common_data.is_lite = soc_private->is_ife_lite; + bus_priv->common_data.support_consumed_addr = + ver3_hw_info->support_consumed_addr; for (i = 0; i < CAM_VFE_BUS_VER3_SRC_GRP_MAX; i++) bus_priv->common_data.rup_irq_handle[i] = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index f2430c5f2f8e..7b39c97f4510 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -167,12 +167,13 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { * * @Brief: HW register info for entire Bus * - * @common_reg: Common register details - * @num_client: Total number of write clients - * @bus_client_reg: Bus client register info - * @vfe_out_hw_info: VFE output capability - * @comp_done_shift: Mask shift for comp done mask - * @top_irq_shift: Mask shift for top level BUS WR irq + * @common_reg: Common register details + * @num_client: Total number of write clients + * @bus_client_reg: Bus client register info + * @vfe_out_hw_info: VFE output capability + * @comp_done_shift: Mask shift for comp done mask + * @top_irq_shift: Mask shift for top level BUS WR irq + * @support_consumed_addr: Indicate if bus support consumed address */ struct cam_vfe_bus_ver3_hw_info { struct cam_vfe_bus_ver3_reg_offset_common common_reg; @@ -184,6 +185,7 @@ struct cam_vfe_bus_ver3_hw_info { vfe_out_hw_info[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; uint32_t comp_done_shift; uint32_t top_irq_shift; + bool support_consumed_addr; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 1f1e12ea57c3..27fdde7718c0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1272,7 +1272,7 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, } cam_isp_hw_get_timestamp(&evt_payload->ts); - evt_payload->th_reg_val = 0; + evt_payload->reg_val = 0; for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -1282,7 +1282,7 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, & camif_priv->reg_data->epoch0_irq_mask) { if ((camif_priv->common_reg->custom_frame_idx) && (camif_priv->cam_common_cfg.input_mux_sel_pp & 0x3)) - evt_payload->th_reg_val = cam_io_r_mb( + evt_payload->reg_val = cam_io_r_mb( camif_priv->mem_base + camif_priv->common_reg->custom_frame_idx); } @@ -1344,7 +1344,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, evt_info.hw_idx = camif_node->hw_intf->hw_idx; evt_info.res_id = camif_node->res_id; evt_info.res_type = camif_node->res_type; - evt_info.th_reg_val = 0; + evt_info.reg_val = 0; if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->sof_irq_mask) { @@ -1380,7 +1380,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); - evt_info.th_reg_val = payload->th_reg_val; + evt_info.reg_val = payload->reg_val; camif_priv->epoch_ts.tv_sec = payload->ts.mono_time.tv_sec; camif_priv->epoch_ts.tv_usec = From 812fe415ad33d9d32678fad3dfc0a7d21dea28b6 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 4 Aug 2020 11:21:19 +0530 Subject: [PATCH 443/790] msm: camera: cpas: Correct QoS setting for holi Correct PRIORITYLUT_LOW for holi tfe. CRs-Fixed: 2747287 Change-Id: I5799f56ac93891b00578d63f64c23a0e4a2f69da Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cpas/cpas_top/cpastop_v545_100.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h index 79e4910dea28..d7cbe7794f6e 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h @@ -130,7 +130,7 @@ static struct cam_camnoc_specific .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ .offset = 0x30, - .value = 0x55443333, + .value = 0x55554433, }, .priority_lut_high = { .enable = true, @@ -177,7 +177,7 @@ static struct cam_camnoc_specific .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ .offset = 0x4030, - .value = 0x55443333, + .value = 0x55554433, }, .priority_lut_high = { .enable = true, @@ -216,7 +216,7 @@ static struct cam_camnoc_specific .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ .offset = 0x5030, - .value = 0x55443333, + .value = 0x55554433, }, .priority_lut_high = { .enable = true, From 8d1b53b0225ba16782cf147c9fa91f1c20504e93 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Fri, 24 Jul 2020 17:29:04 -0700 Subject: [PATCH 444/790] msm: camera: icp: Increase request queue depth for ICP contexts Some usecases need more than the original max depth of 20 for ICP contexts. Accommodate these usecases by increasing the max request depth only for ICP. CRs-Fixed: 2739277 Change-Id: Ibeda16aa439b49815cbefc3a76580092351c3572 Signed-off-by: Fernando Pacheco --- drivers/cam_core/cam_context.h | 1 + drivers/cam_icp/cam_icp_context.c | 2 +- drivers/cam_icp/cam_icp_context.h | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 1f2f8154ae99..c959edb8a2cf 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -20,6 +20,7 @@ struct cam_context; /* max request number */ #define CAM_CTX_REQ_MAX 20 +#define CAM_CTX_ICP_REQ_MAX 36 #define CAM_CTX_CFG_MAX 20 #define CAM_CTX_RES_MAX 20 diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 6a9f57b65f68..c2edab7d3fd5 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -285,7 +285,7 @@ int cam_icp_context_init(struct cam_icp_context *ctx, } rc = cam_context_init(ctx->base, icp_dev_name, CAM_ICP, ctx_id, - NULL, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + NULL, hw_intf, ctx->req_base, CAM_CTX_ICP_REQ_MAX); if (rc) { CAM_ERR(CAM_ICP, "Camera Context Base init failed"); goto err; diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h index edd8bd5617c9..1062e8f005ff 100644 --- a/drivers/cam_icp/cam_icp_context.h +++ b/drivers/cam_icp/cam_icp_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ICP_CONTEXT_H_ @@ -19,7 +19,7 @@ struct cam_icp_context { struct cam_context *base; struct cam_ctx_ops *state_machine; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_ctx_request req_base[CAM_CTX_ICP_REQ_MAX]; uint32_t state; void *ctxt_to_hw_map; }; From 397fcc6f55cea327eaed76668e05617ce97087c3 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Tue, 28 Jul 2020 18:37:28 -0700 Subject: [PATCH 445/790] msm: camera: utils: Add CAM_IO_ACCESS log category Currently, CAM_UTIL debug logs when enabled, flood the logcat with io read/write access logs, which are not necessary when debugging clocks, interrupts and other parameters. Add separate entry for IO access in debug util. CRs-Fixed: 2743063 Change-Id: Id13393211bcc6fdc620aaffe8f8ab27a6b7c6986 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_utils/cam_debug_util.c | 3 +++ drivers/cam_utils/cam_debug_util.h | 3 +++ drivers/cam_utils/cam_io_util.c | 42 ++++++++++++++++-------------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index a655b084d35e..a345947dee58 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -206,6 +206,9 @@ const char *cam_get_module_name(unsigned int module_id) case CAM_RES: name = "CAM-RES"; break; + case CAM_IO_ACCESS: + name = "CAM-IO-ACCESS"; + break; default: name = "CAM"; break; diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 3a53aa9ce566..fdeb3e758b66 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -44,6 +44,9 @@ #define CAM_OPE (1 << 28) #define CAM_PRESIL (1 << 27) +/* CAM_IO_ACCESS: Tracks IO read/write */ +#define CAM_IO_ACCESS (1 << 29) + #define STR_BUFFER_MAX_LENGTH 1024 /** diff --git a/drivers/cam_utils/cam_io_util.c b/drivers/cam_utils/cam_io_util.c index fcbc4b5e00f5..0d78f5f43e0f 100644 --- a/drivers/cam_utils/cam_io_util.c +++ b/drivers/cam_utils/cam_io_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2011-2014, 2017-2018, The Linux Foundation. + * Copyright (c) 2011-2014, 2017-2018, 2020, The Linux Foundation. * All rights reserved. */ @@ -15,7 +15,7 @@ int cam_io_w(uint32_t data, void __iomem *addr) if (!addr) return -EINVAL; - CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + CAM_DBG(CAM_IO_ACCESS, "0x%pK %08x", addr, data); writel_relaxed_no_log(data, addr); return 0; @@ -26,7 +26,7 @@ int cam_io_w_mb(uint32_t data, void __iomem *addr) if (!addr) return -EINVAL; - CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + CAM_DBG(CAM_IO_ACCESS, "0x%pK %08x", addr, data); /* Ensure previous writes are done */ wmb(); writel_relaxed_no_log(data, addr); @@ -41,12 +41,12 @@ uint32_t cam_io_r(void __iomem *addr) uint32_t data; if (!addr) { - CAM_ERR(CAM_UTIL, "Invalid args"); + CAM_ERR(CAM_IO_ACCESS, "Invalid args"); return 0; } data = readl_relaxed(addr); - CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + CAM_DBG(CAM_IO_ACCESS, "0x%pK %08x", addr, data); return data; } @@ -56,14 +56,14 @@ uint32_t cam_io_r_mb(void __iomem *addr) uint32_t data; if (!addr) { - CAM_ERR(CAM_UTIL, "Invalid args"); + CAM_ERR(CAM_IO_ACCESS, "Invalid args"); return 0; } /* Ensure previous read is done */ rmb(); data = readl_relaxed(addr); - CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data); + CAM_DBG(CAM_IO_ACCESS, "0x%pK %08x", addr, data); /* Ensure previous read is done */ rmb(); @@ -80,10 +80,10 @@ int cam_io_memcpy(void __iomem *dest_addr, if (!dest_addr || !src_addr) return -EINVAL; - CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len); + CAM_DBG(CAM_IO_ACCESS, "%pK %pK %d", dest_addr, src_addr, len); for (i = 0; i < len/4; i++) { - CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s); + CAM_DBG(CAM_IO_ACCESS, "0x%pK %08x", d, *s); writel_relaxed(*s++, d++); } @@ -100,7 +100,7 @@ int cam_io_memcpy_mb(void __iomem *dest_addr, if (!dest_addr || !src_addr) return -EINVAL; - CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len); + CAM_DBG(CAM_IO_ACCESS, "%pK %pK %d", dest_addr, src_addr, len); /* * Do not use cam_io_w_mb to avoid double wmb() after a write @@ -108,7 +108,7 @@ int cam_io_memcpy_mb(void __iomem *dest_addr, */ wmb(); for (i = 0; i < (len / 4); i++) { - CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s); + CAM_DBG(CAM_IO_ACCESS, "0x%pK %08x", d, *s); writel_relaxed(*s++, d++); } /* Ensure previous writes are done */ @@ -134,7 +134,7 @@ int cam_io_poll_value(void __iomem *addr, uint32_t wait_data, uint32_t retry, } if (cnt > retry) { - CAM_DBG(CAM_UTIL, "Poll failed by value"); + CAM_DBG(CAM_IO_ACCESS, "Poll failed by value"); rc = -EINVAL; } @@ -159,7 +159,7 @@ int cam_io_poll_value_wmask(void __iomem *addr, uint32_t wait_data, } if (cnt > retry) { - CAM_DBG(CAM_UTIL, "Poll failed with mask"); + CAM_DBG(CAM_IO_ACCESS, "Poll failed with mask"); rc = -EINVAL; } @@ -175,7 +175,7 @@ int cam_io_w_same_offset_block(const uint32_t *data, void __iomem *addr, return -EINVAL; for (i = 0; i < len; i++) { - CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK", + CAM_DBG(CAM_IO_ACCESS, "i= %d len =%d val=%x addr =%pK", i, len, data[i], addr); writel_relaxed(data[i], addr); } @@ -192,7 +192,7 @@ int cam_io_w_mb_same_offset_block(const uint32_t *data, void __iomem *addr, return -EINVAL; for (i = 0; i < len; i++) { - CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK", + CAM_DBG(CAM_IO_ACCESS, "i= %d len =%d val=%x addr =%pK", i, len, data[i], addr); /* Ensure previous writes are done */ wmb(); @@ -213,7 +213,8 @@ int cam_io_w_offset_val_block(const uint32_t data[][2], return -EINVAL; for (i = 0; i < len; i++) { - CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x", + CAM_DBG(CAM_IO_ACCESS, + "i= %d len =%d val=%x addr_base =%pK reg=%x", i, len, __VAL(i), addr_base, __OFFSET(i)); writel_relaxed(__VAL(i), addr_base + __OFFSET(i)); } @@ -232,7 +233,8 @@ int cam_io_w_mb_offset_val_block(const uint32_t data[][2], /* Ensure write is done */ wmb(); for (i = 0; i < len; i++) { - CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x", + CAM_DBG(CAM_IO_ACCESS, + "i= %d len =%d val=%x addr_base =%pK reg=%x", i, len, __VAL(i), addr_base, __OFFSET(i)); writel_relaxed(__VAL(i), addr_base + __OFFSET(i)); } @@ -250,7 +252,7 @@ int cam_io_dump(void __iomem *base_addr, uint32_t start_offset, int size) int i; uint32_t data; - CAM_DBG(CAM_UTIL, "addr=%pK offset=0x%x size=%d", + CAM_DBG(CAM_IO_ACCESS, "addr=%pK offset=0x%x size=%d", base_addr, start_offset, size); if (!base_addr || (size <= 0)) @@ -268,13 +270,13 @@ int cam_io_dump(void __iomem *base_addr, uint32_t start_offset, int size) snprintf(p_str, 10, "%08x ", data); p_str += 9; if ((i + 1) % NUM_REGISTER_PER_LINE == 0) { - CAM_ERR(CAM_UTIL, "%s", line_str); + CAM_ERR(CAM_IO_ACCESS, "%s", line_str); line_str[0] = '\0'; p_str = line_str; } } if (line_str[0] != '\0') - CAM_ERR(CAM_UTIL, "%s", line_str); + CAM_ERR(CAM_IO_ACCESS, "%s", line_str); return 0; } From 00b8521d2a7de5aa11c148b74fb749580b41260f Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 4 Aug 2020 22:57:30 +0800 Subject: [PATCH 446/790] msm: camera: isp: Reset CSID sw register before reset clock domain Reset CSID SW register firstly to cut off potential input source before reset the HW logic, then HW logic won't get junk data. CRs-Fixed: 2731158 Change-Id: I9c8e1f3776229bf96c0c712de8c083b1334702ef Signed-off-by: Depeng Shao --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index e91cdb437a1e..dd85eb45d4ab 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -523,11 +523,11 @@ 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); - /* reset HW regs first, then SW */ - rc = cam_ife_csid_reset_regs(csid_hw, true); + /* reset SW regs first, then HW */ + rc = cam_ife_csid_reset_regs(csid_hw, false); if (rc < 0) goto end; - rc = cam_ife_csid_reset_regs(csid_hw, false); + rc = cam_ife_csid_reset_regs(csid_hw, true); if (rc < 0) goto end; From 0d784286a97e8d84e6b00e851e8d2f908a40b913 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Tue, 28 Jul 2020 17:02:09 -0700 Subject: [PATCH 447/790] msm: camera: common: Avoid uninitialized accesses Improve the error-handling code paths to prevent accesses to uninitialized variables. This is done by either picking a sane default for the variable or skipping accesses altogether after an unsuccessful attempt to initialize. CRs-Fixed: 2748220 Change-Id: Ibe383e56ec4e3f45f76f619c7d6b62c3d7dfcadb Signed-off-by: Fernando Pacheco --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 6 ++ drivers/cam_cust/cam_custom_context.c | 2 + drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 95 +++++++++++++----- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 19 +++- drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 98 ++++++++++++++----- drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c | 9 +- drivers/cam_isp/cam_isp_context.c | 2 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 3 +- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c | 50 +++++++--- .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 50 +++++++--- 10 files changed, 253 insertions(+), 81 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 2605de78b238..ea1a076ca7de 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -292,6 +292,9 @@ static int cam_cpastop_setup_regbase_indices(struct cam_hw_soc_info *soc_info, soc_info->num_mem_block, "cam_cpas_top", &index); if ((rc == 0) && (index < num_reg_map)) { regbase_index[CAM_CPAS_REG_CPASTOP] = index; + } else if (rc) { + CAM_ERR(CAM_CPAS, "failed to get index for CPASTOP rc=%d", rc); + return rc; } else { CAM_ERR(CAM_CPAS, "regbase not found for CPASTOP, rc=%d, %d %d", rc, index, num_reg_map); @@ -302,6 +305,9 @@ static int cam_cpastop_setup_regbase_indices(struct cam_hw_soc_info *soc_info, soc_info->num_mem_block, "cam_camnoc", &index); if ((rc == 0) && (index < num_reg_map)) { regbase_index[CAM_CPAS_REG_CAMNOC] = index; + } else if (rc) { + CAM_ERR(CAM_CPAS, "failed to get index for CAMNOC rc=%d", rc); + return rc; } else { CAM_ERR(CAM_CPAS, "regbase not found for CAMNOC, rc=%d, %d %d", rc, index, num_reg_map); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index f0b782c0971d..62b138633454 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -637,6 +637,7 @@ static int __cam_custom_ctx_release_hw_in_top_state( flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; flush_req.link_hdl = ctx->link_hdl; flush_req.dev_hdl = ctx->dev_hdl; + flush_req.req_id = 0; CAM_DBG(CAM_CUSTOM, "try to flush pending list"); spin_lock_bh(&ctx->lock); @@ -694,6 +695,7 @@ static int __cam_custom_release_dev_in_acquired(struct cam_context *ctx, flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; flush_req.link_hdl = ctx->link_hdl; flush_req.dev_hdl = ctx->dev_hdl; + flush_req.req_id = 0; CAM_DBG(CAM_CUSTOM, "try to flush pending list"); spin_lock_bh(&ctx->lock); diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index 8a079bd14202..eea5ac24d82c 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -151,6 +151,7 @@ static int cam_bps_handle_pc(struct cam_hw_info *bps_dev) struct cam_hw_soc_info *soc_info = NULL; struct cam_bps_device_core_info *core_info = NULL; struct cam_bps_device_hw_info *hw_info = NULL; + int rc = 0; int pwr_ctrl; int pwr_status; @@ -158,13 +159,22 @@ static int cam_bps_handle_pc(struct cam_hw_info *bps_dev) core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; hw_info = core_info->bps_hw_info; - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, - true, &pwr_ctrl); + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + if (!(pwr_ctrl & BPS_COLLAPSE_MASK)) { - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, - true, &pwr_status); + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "power status read failed rc=%d", rc); + return rc; + } cam_cpas_reg_write(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, @@ -174,15 +184,30 @@ static int cam_bps_handle_pc(struct cam_hw_info *bps_dev) CAM_WARN(CAM_PERF, "BPS: pwr_status(%x):pwr_ctrl(%x)", pwr_status, pwr_ctrl); } - cam_bps_get_gdsc_control(soc_info); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, - &pwr_ctrl); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, - true, &pwr_status); - CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", - pwr_ctrl, pwr_status); + + rc = cam_bps_get_gdsc_control(soc_info); + if (rc) { + CAM_ERR(CAM_ICP, "failed to get gdsc control rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "power status read failed rc=%d", rc); + return rc; + } + + CAM_DBG(CAM_PERF, "pwr_ctrl=%x pwr_status=%x", pwr_ctrl, pwr_status); return 0; } @@ -200,8 +225,14 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) core_info = (struct cam_bps_device_core_info *)bps_dev->core_info; hw_info = core_info->bps_hw_info; - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + if (pwr_ctrl & BPS_COLLAPSE_MASK) { CAM_DBG(CAM_PERF, "BPS: pwr_ctrl set(%x)", pwr_ctrl); cam_cpas_reg_write(core_info->cpas_handle, @@ -210,12 +241,28 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) } rc = cam_bps_transfer_gdsc_control(soc_info); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status); - CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", - pwr_ctrl, pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "failed to transfer gdsc control rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "power status read failed rc=%d", rc); + return rc; + } + + CAM_DBG(CAM_PERF, "pwr_ctrl=%x pwr_status=%x", pwr_ctrl, pwr_status); return rc; } diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index c85f001d1540..9ca55f30db5f 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -6092,9 +6092,18 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, for (i = 0; i < CAM_ICP_CTX_MAX; i++) mutex_init(&icp_hw_mgr.ctx_data[i].ctx_mutex); - cam_cpas_get_hw_info(&query.camera_family, - &query.camera_version, &query.cpas_version, &cam_caps); - cam_cpas_get_cpas_hw_version(&camera_hw_version); + rc = cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, &cam_caps); + if (rc) { + CAM_ERR(CAM_ICP, "failed to get hw info rc=%d", rc); + goto destroy_mutex; + } + + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ICP, "failed to get hw version rc=%d", rc); + goto destroy_mutex; + } if ((camera_hw_version == CAM_CPAS_TITAN_480_V100) || (camera_hw_version == CAM_CPAS_TITAN_580_V100) || @@ -6115,7 +6124,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, rc = cam_icp_mgr_init_devs(of_node); if (rc) { CAM_ERR(CAM_ICP, "cam_icp_mgr_init_devs fail: rc: %d", rc); - goto dev_init_failed; + goto destroy_mutex; } rc = cam_smmu_get_handle("icp", &icp_hw_mgr.iommu_hdl); if (rc) { @@ -6151,7 +6160,7 @@ icp_get_hdl_failed: kfree(icp_hw_mgr.devices[CAM_ICP_DEV_BPS]); kfree(icp_hw_mgr.devices[CAM_ICP_DEV_IPE]); kfree(icp_hw_mgr.devices[CAM_ICP_DEV_A5]); -dev_init_failed: +destroy_mutex: mutex_destroy(&icp_hw_mgr.hw_mgr_mutex); for (i = 0; i < CAM_ICP_CTX_MAX; i++) mutex_destroy(&icp_hw_mgr.ctx_data[i].ctx_mutex); diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 4263cf7ea669..2c82b1a5ac9a 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -149,6 +149,7 @@ static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev) struct cam_hw_soc_info *soc_info = NULL; struct cam_ipe_device_core_info *core_info = NULL; struct cam_ipe_device_hw_info *hw_info = NULL; + int rc = 0; int pwr_ctrl; int pwr_status; @@ -156,13 +157,23 @@ static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev) core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; hw_info = core_info->ipe_hw_info; - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, - true, &pwr_ctrl); + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + if (!(pwr_ctrl & IPE_COLLAPSE_MASK)) { - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, - true, &pwr_status); + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "power status read failed rc=%d", rc); + return rc; + } + cam_cpas_reg_write(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, 0x1); @@ -172,15 +183,30 @@ static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev) pwr_status, pwr_ctrl); } - cam_ipe_get_gdsc_control(soc_info); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, - true, &pwr_ctrl); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, - true, &pwr_status); - CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", - pwr_ctrl, pwr_status); + + rc = cam_ipe_get_gdsc_control(soc_info); + if (rc) { + CAM_ERR(CAM_ICP, "failed to get gdsc control rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "power status read failed rc=%d", rc); + return rc; + } + + CAM_DBG(CAM_PERF, "pwr_ctrl=%x pwr_status=%x", pwr_ctrl, pwr_status); return 0; } @@ -198,9 +224,14 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info; hw_info = core_info->ipe_hw_info; - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, - true, &pwr_ctrl); + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + if (pwr_ctrl & IPE_COLLAPSE_MASK) { CAM_DBG(CAM_PERF, "IPE pwr_ctrl set(%x)", pwr_ctrl); cam_cpas_reg_write(core_info->cpas_handle, @@ -209,13 +240,28 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) } rc = cam_ipe_transfer_gdsc_control(soc_info); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); - cam_cpas_reg_read(core_info->cpas_handle, - CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, - true, &pwr_status); - CAM_DBG(CAM_PERF, "pwr_ctrl = %x pwr_status = %x", - pwr_ctrl, pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "failed to transfer gdsc control rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, + true, &pwr_ctrl); + if (rc) { + CAM_ERR(CAM_ICP, "power ctrl read failed rc=%d", rc); + return rc; + } + + rc = cam_cpas_reg_read(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, + true, &pwr_status); + if (rc) { + CAM_ERR(CAM_ICP, "power status read failed rc=%d", rc); + return rc; + } + + CAM_DBG(CAM_PERF, "pwr_ctrl=%x pwr_status=%x", pwr_ctrl, pwr_status); return rc; } diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c index 70957a40686d..d7eee64a37b5 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -76,8 +76,13 @@ static int cam_ipe_component_bind(struct device *dev, of_property_read_u32(pdev->dev.of_node, "cell-index", &hw_idx); - cam_cpas_get_hw_info(&query.camera_family, - &query.camera_version, &query.cpas_version, &cam_caps); + rc = cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, &cam_caps); + if (rc) { + CAM_ERR(CAM_ICP, "failed to get hw info rc=%d", rc); + return rc; + } + if ((!(cam_caps & CPAS_IPE1_BIT)) && (hw_idx)) { CAM_ERR(CAM_ICP, "IPE1 hw idx = %d\n", hw_idx); return -EINVAL; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 811d38a5891c..4ad7d6202194 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3925,6 +3925,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; flush_req.link_hdl = ctx->link_hdl; flush_req.dev_hdl = ctx->dev_hdl; + flush_req.req_id = 0; CAM_DBG(CAM_ISP, "try to flush pending list"); spin_lock_bh(&ctx->lock); @@ -3989,6 +3990,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; flush_req.link_hdl = ctx->link_hdl; flush_req.dev_hdl = ctx->dev_hdl; + flush_req.req_id = 0; CAM_DBG(CAM_ISP, "try to flush pending list"); spin_lock_bh(&ctx->lock); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 82d0f555faba..a5bb5b86213b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1243,8 +1243,7 @@ static int cam_vfe_bus_start_wm( if (rsrc_data->en_ubwc) { rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); if (rc) { - CAM_ERR(CAM_ISP, "Failed to get HW version:%d rc:%d", - camera_hw_version, rc); + CAM_ERR(CAM_ISP, "failed to get HW version rc=%d", rc); return rc; } if ((camera_hw_version > CAM_CPAS_TITAN_NONE) && diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c index e4ff7255df5b..ad4e7eca7186 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -418,39 +418,67 @@ static int cam_vfe_camif_lite_handle_irq_top_half(uint32_t evt_id, static int cam_vfe_camif_lite_cpas_fifo_levels_reg_dump( struct cam_vfe_mux_camif_lite_data *camif_lite_priv) { + int rc = 0; struct cam_vfe_soc_private *soc_private = camif_lite_priv->soc_info->soc_private; uint32_t val; if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, + "IFE0_nRDI_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", val); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, + "IFE1_nRDI_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", val); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, "IFE02_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x820, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x820, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, "IFE13_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val); } return 0; - } static int cam_vfe_camif_lite_handle_irq_bottom_half( diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index b766c1ee844b..f9c6d8f4dc1d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -88,39 +88,67 @@ static int cam_vfe_rdi_put_evt_payload( static int cam_vfe_rdi_cpas_reg_dump( struct cam_vfe_mux_rdi_data *rdi_priv) { + int rc = 0; struct cam_vfe_soc_private *soc_private = rdi_priv->soc_info->soc_private; uint32_t val; if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, + "IFE0_nRDI_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", val); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, + "IFE1_nRDI_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", val); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, "IFE02_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x820, true, &val); + rc = cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x820, true, &val); + if (rc) { + CAM_ERR(CAM_ISP, "IFE13_MAXWR_LOW read failed rc=%d", + rc); + return rc; + } CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val); } return 0; - } static int cam_vfe_rdi_err_irq_top_half( From a58f2a9d27e5b55dda6128263909ad2dace32f28 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Tue, 26 May 2020 04:20:39 +0530 Subject: [PATCH 448/790] msm: camera: csiphy: Add mipi flags to phy config -Add mipi flags mask to phy cmd buffer. -Enable skew calibration settings only if the corresponding flag is set. CRs-fixed: 2697576 Change-Id: I0353e57daf49ce15d7573b57dbaa9363dbc59635 Signed-off-by: Shravan Nevatia --- .../cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 14 ++++++++++++++ .../cam_sensor_module/cam_csiphy/cam_csiphy_dev.h | 3 +++ include/uapi/camera/media/cam_sensor.h | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index b3ff2435b08b..d9cd5f647f25 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -27,6 +27,9 @@ #define SEC_LANE_CP_REG_LEN 32 #define MAX_PHY_MSK_PER_REG 4 +/* Mask to enable skew calibration registers */ +#define SKEW_CAL_MASK 0x2 + static int csiphy_dump; module_param(csiphy_dump, int, 0644); @@ -345,6 +348,8 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, cam_cmd_csiphy_info->data_rate; csiphy_dev->csiphy_info[index].secure_mode = cam_cmd_csiphy_info->secure_mode; + csiphy_dev->csiphy_info[index].mipi_flags = + cam_cmd_csiphy_info->mipi_flags; lane_assign = csiphy_dev->csiphy_info[index].lane_assign; lane_cnt = csiphy_dev->csiphy_info[index].lane_cnt; @@ -596,6 +601,7 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, uint8_t lane_cnt; int max_lanes = 0; uint16_t settle_cnt = 0; + uint8_t skew_cal_enable = 0; uint64_t intermediate_var; uint8_t lane_pos = 0; int index; @@ -735,6 +741,8 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, intermediate_var = csiphy_dev->csiphy_info[index].settle_time; do_div(intermediate_var, 200000000); settle_cnt = intermediate_var; + skew_cal_enable = + csiphy_dev->csiphy_info[index].mipi_flags & SKEW_CAL_MASK; for (lane_pos = 0; lane_pos < max_lanes; lane_pos++) { CAM_DBG(CAM_CSIPHY, "lane_pos: %d is configuring", lane_pos); @@ -760,6 +768,12 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, csiphybase + reg_array[lane_pos][i].reg_addr); break; + case CSIPHY_SKEW_CAL: + if (skew_cal_enable) + cam_io_w_mb(reg_array[lane_pos][i].reg_data, + csiphybase + + reg_array[lane_pos][i].reg_addr); + break; default: CAM_DBG(CAM_CSIPHY, "Do Nothing"); break; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 39e3c62f5678..3d467375d1e4 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -53,6 +53,7 @@ #define CSIPHY_DNP_PARAMS 4 #define CSIPHY_2PH_REGS 5 #define CSIPHY_3PH_REGS 6 +#define CSIPHY_SKEW_CAL 7 #define CSIPHY_MAX_INSTANCES_PER_PHY 3 @@ -224,6 +225,7 @@ struct csiphy_ctrl_t { * @settle_time : Settling time in ms * @data_rate : Data rate in mbps * @csiphy_3phase : To identify DPHY or CPHY + * @mipi_flags : MIPI phy flags * @csiphy_cpas_cp_reg_mask : CP reg mask for phy instance * @hdl_data : CSIPHY handle table */ @@ -235,6 +237,7 @@ struct cam_csiphy_param { uint64_t settle_time; uint64_t data_rate; int csiphy_3phase; + uint16_t mipi_flags; uint64_t csiphy_cpas_cp_reg_mask; struct csiphy_hdl_tbl hdl_data; }; diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index 4ff9ecc7c3a1..cff997346943 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -326,6 +326,7 @@ struct cam_cmd_unconditional_wait { /** * cam_csiphy_info : Provides cmdbuffer structre * @lane_assign : Lane sensor will be using + * @mipi_flags : MIPI phy flags * @lane_cnt : Total number of lanes * @secure_mode : Secure mode flag to enable / disable * @settle_time : Settling time in ms @@ -335,7 +336,7 @@ struct cam_cmd_unconditional_wait { struct cam_csiphy_info { __u16 reserved; __u16 lane_assign; - __u16 reserved1; + __u16 mipi_flags; __u8 lane_cnt; __u8 secure_mode; __u64 settle_time; From ea7b6b2312b37d6eae998ed35f877cb106198e3c Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Fri, 24 Jul 2020 17:55:27 -0700 Subject: [PATCH 449/790] msm: camera: csiphy: Add Skew calibration in DPHY Programming Sequence Update register pragramming sequence to account for signal skew calibration for DPHY single and combo mode for per lane data rates higher than 1.5 Gbps for CSIPHY1.2.3 and CSIPHY 2.1.0. Also, move settle time register update in data specific table, as settle time is pre calculated based on datarate and need to configure accordingly. CRs-fixed: 2697576 Change-Id: I428d8d14887aa54ff22d727f80ee4a395be76baf Signed-off-by: Jigar Agrawal --- .../include/cam_csiphy_1_2_3_hwreg.h | 90 +++++++++++++++---- .../include/cam_csiphy_2_1_0_hwreg.h | 42 ++++++++- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 2c6617574263..e626c13a70f5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -15,8 +15,8 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 16, - .csiphy_3ph_config_array_size = 28, + .csiphy_2ph_config_array_size = 19, + .csiphy_3ph_config_array_size = 26, .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -73,6 +73,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x005C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -91,6 +94,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x075C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0764, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -109,6 +115,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x025C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0260, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0264, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -127,6 +136,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x045C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -145,6 +157,9 @@ csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x065C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0660, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0664, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -167,6 +182,9 @@ struct csiphy_reg_t {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x005C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -185,6 +203,9 @@ struct csiphy_reg_t {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x075C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0764, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -203,6 +224,9 @@ struct csiphy_reg_t {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x025C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0260, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0264, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -221,6 +245,9 @@ struct csiphy_reg_t {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x045C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0x0D, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -239,6 +266,9 @@ struct csiphy_reg_t {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x065C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0664, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -254,8 +284,6 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -284,8 +312,6 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -314,8 +340,6 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -343,29 +367,41 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 2, + .data_rate_reg_array_size = 4, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { + {0x010C, 0x12, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, + {0x9B4, 0x03, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { + {0x030C, 0x12, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, + {0xAB4, 0x03, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { + {0x050C, 0x12, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x03, 0x0A, @@ -377,11 +413,15 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 4, + .data_rate_reg_array_size = 6, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { + {0x010C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x988, 0x05, 0x00, @@ -395,6 +435,10 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { + {0x030C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA88, 0x05, 0x00, @@ -408,7 +452,11 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { - {0x344, 0xB2, 0x00, + {0x050C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -423,11 +471,15 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 4, + .data_rate_reg_array_size = 6, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { + {0x010C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x988, 0x05, 0x00, @@ -441,6 +493,10 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { + {0x030C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xA88, 0x05, 0x00, @@ -454,7 +510,11 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { - {0x344, 0xB2, 0x00, + {0x050C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xB88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h index 9cd115be221d..841b91c5ff71 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_1_0_hwreg.h @@ -14,7 +14,7 @@ struct csiphy_reg_parms_t csiphy_v2_1_0 = { .mipi_csiphy_glbl_irq_cmd_addr = 0x1028, .csiphy_common_array_size = 6, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 19, + .csiphy_2ph_config_array_size = 23, .csiphy_3ph_config_array_size = 29, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -72,6 +72,10 @@ struct csiphy_reg_t csiphy_2ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -93,6 +97,10 @@ struct csiphy_reg_t csiphy_2ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0E08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E5C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0E60, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0E64, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x1000, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -114,6 +122,10 @@ struct csiphy_reg_t csiphy_2ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -135,6 +147,10 @@ struct csiphy_reg_t csiphy_2ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0808, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x085C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0860, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -156,6 +172,10 @@ struct csiphy_reg_t csiphy_2ph_v2_1_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C5C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0C60, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -182,6 +202,10 @@ struct csiphy_reg_t {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -204,6 +228,10 @@ struct csiphy_reg_t {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0E08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E5C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0E60, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0E64, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x1000, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -226,6 +254,10 @@ struct csiphy_reg_t {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -248,6 +280,10 @@ struct csiphy_reg_t {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0808, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x085C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0860, 0xF1, 0x00, CSIPHY_SKEW_CAL}, + {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + {0x1000, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -270,6 +306,10 @@ struct csiphy_reg_t {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C08, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C5C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0C60, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0C64, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x1000, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; From 494ace8da7350cffe3f3a9239d32ed6dc459fb28 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Fri, 7 Aug 2020 14:54:24 +0800 Subject: [PATCH 450/790] msm: camera: ife: Get consumed address info during hw_mgr init This change checks whether the context supports last consumed address during hw_mgr init. CRs-Fixed: 2749254 Change-Id: I238893eb2d661014a2a51758bcf71c3e4d00f2d5 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 2 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 41 +++++++-------------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 2 + 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 811d38a5891c..a7942f6665f8 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1233,6 +1233,8 @@ static void __cam_isp_ctx_buf_done_match_req( CAM_DBG(CAM_ISP, "buf done num handles %d match count %d for next req:%lld", done->num_handles, match_count, req->request_id); + CAM_DBG(CAM_ISP, + "irq_delay_detected %d", *irq_delay_detected); } static int __cam_isp_ctx_handle_buf_done_verify_addr( diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c67c5754cccb..c41af53f91e6 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2982,32 +2982,6 @@ static int cam_ife_mgr_acquire_get_unified_structure( return 0; } -static bool cam_ife_mgr_is_consumed_addr_supported( - struct cam_ife_hw_mgr_ctx *ctx) -{ - bool support_consumed_addr = false; - struct cam_isp_hw_mgr_res *isp_hw_res = NULL; - struct cam_hw_intf *hw_intf = NULL; - - isp_hw_res = &ctx->res_list_ife_out[0]; - - if (!isp_hw_res || !isp_hw_res->hw_res[0]) { - CAM_ERR(CAM_ISP, "Invalid ife out res."); - goto end; - } - - hw_intf = isp_hw_res->hw_res[0]->hw_intf; - if (hw_intf && hw_intf->hw_ops.process_cmd) { - hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, - CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, - &support_consumed_addr, - sizeof(support_consumed_addr)); - } - -end: - return support_consumed_addr; -} - /* entry function: acquire_hw */ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -3171,7 +3145,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) atomic_set(&ife_ctx->cdm_done, 1); acquire_args->support_consumed_addr = - cam_ife_mgr_is_consumed_addr_supported(ife_ctx); + g_ife_hw_mgr.support_consumed_addr; acquire_args->ctxt_to_hw_map = ife_ctx; acquire_args->custom_enabled = ife_ctx->custom_enabled; @@ -7677,6 +7651,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { int rc = -EFAULT; int i, j; + bool support_consumed_addr = false; struct cam_iommu_handle cdm_handles; struct cam_ife_hw_mgr_ctx *ctx_pool; struct cam_isp_hw_mgr_res *res_list_ife_out; @@ -7695,11 +7670,19 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) for (i = 0, j = 0; i < CAM_IFE_HW_NUM_MAX; i++) { rc = cam_vfe_hw_init(&g_ife_hw_mgr.ife_devices[i], i); if (!rc) { + struct cam_hw_intf *ife_device = + g_ife_hw_mgr.ife_devices[i]; struct cam_hw_info *vfe_hw = (struct cam_hw_info *) - g_ife_hw_mgr.ife_devices[i]->hw_priv; + ife_device->hw_priv; struct cam_hw_soc_info *soc_info = &vfe_hw->soc_info; + if (j == 0) + ife_device->hw_ops.process_cmd( + vfe_hw, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + &support_consumed_addr, + sizeof(support_consumed_addr)); j++; g_ife_hw_mgr.cdm_reg_map[i] = &soc_info->reg_map[0]; @@ -7716,6 +7699,8 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return -EINVAL; } + g_ife_hw_mgr.support_consumed_addr = support_consumed_addr; + /* fill csid hw intf information */ for (i = 0, j = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { rc = cam_ife_csid_hw_init(&g_ife_hw_mgr.csid_devices[i], i); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 32743e0b6bb7..15adc1713c74 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -172,6 +172,7 @@ struct cam_ife_hw_mgr_ctx { * @ife_dev_caps ife device capability per core * @work q work queue for IFE hw manager * @debug_cfg debug configuration + * @support_consumed_addr indicate whether hw supports last consumed address */ struct cam_ife_hw_mgr { struct cam_isp_hw_mgr mgr_common; @@ -192,6 +193,7 @@ struct cam_ife_hw_mgr { struct cam_req_mgr_core_workq *workq; struct cam_ife_hw_mgr_debug debug_cfg; spinlock_t ctx_lock; + bool support_consumed_addr; }; /** From 329870a0135926e3c6864344a0aac81c12c89396 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 7 Aug 2020 18:03:22 +0530 Subject: [PATCH 451/790] msm: camera: tfe: confine hw errata for bengal Confine bengal specific HW errata CRs-Fixed: 2752895 Change-Id: I896b1f2e16adf917085e7056f08e87b212485dbb Signed-off-by: Trishansh Bhardwaj --- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 20 ++++++++++++------- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 36a87fe3101b..f4b7d669e800 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -1901,6 +1901,7 @@ static int cam_tfe_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; if (!camif_res || !core_info) { CAM_ERR(CAM_ISP, "Error Invalid input arguments"); @@ -1963,13 +1964,18 @@ static int cam_tfe_camif_resource_start( CAM_DBG(CAM_ISP, "TFE:%d core_cfg 0 val:0x%x", core_info->core_index, val); - val = cam_io_r(rsrc_data->mem_base + - rsrc_data->common_reg->core_cfg_1); - val &= ~BIT(0); - cam_io_w_mb(val, rsrc_data->mem_base + - rsrc_data->common_reg->core_cfg_1); - CAM_DBG(CAM_ISP, "TFE:%d core_cfg 1 val:0x%x", core_info->core_index, - val); + if (cam_cpas_get_cpas_hw_version(&camera_hw_version)) + CAM_ERR(CAM_ISP, "Failed to get HW version"); + + if (camera_hw_version == CAM_CPAS_TITAN_540_V100) { + val = cam_io_r(rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_1); + val &= ~BIT(0); + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_1); + CAM_DBG(CAM_ISP, "TFE:%d core_cfg 1 val:0x%x", + core_info->core_index, val); + } /* Epoch config */ epoch0_irq_mask = ((rsrc_data->last_line - diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 121339e28161..df5b61eb916d 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -1022,7 +1022,7 @@ static int cam_lrme_mgr_create_debugfs_entry(void) if (!dbgfileptr) { CAM_ERR(CAM_ISP,"DebugFS could not create directory!"); rc = -ENOENT; - goto end; + goto err; } /* Store parent inode for cleanup in caller */ g_lrme_hw_mgr.debugfs_entry.dentry = dbgfileptr; From 24c71ea45d029ae6f9e5695a0937ff1a0a9dbddf Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 7 Aug 2020 10:09:49 -0700 Subject: [PATCH 452/790] msm: camera: isp: Fix frame header alignment issue Update frame header iova correctly so that it's 16 byte aligned. CRs-Fixed: 2751309 Change-Id: I4af0eb5f12bcd92ba40077d9d62a9e308fa06f8d Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c41af53f91e6..ec4f65aee4e7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6111,7 +6111,7 @@ static int cam_ife_mgr_util_insert_frame_header( /* frame header address needs to be 16 byte aligned */ if (frame_header_iova % 16) { padded_bytes = (uint32_t)(16 - (frame_header_iova % 16)); - iova_addr += padded_bytes; + frame_header_iova += padded_bytes; } prepare_hw_data->frame_header_iova = frame_header_iova; From dc64ec28dd5444c5097bb1e8eefde72f75f25db3 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 12 Aug 2020 09:44:58 -0700 Subject: [PATCH 453/790] msm: camera: isp: Fix boot ts when custom is enabled When custom is enabled, we can generate boot time independent of qtimer update from CSID. CRs-Fixed: 2753196 Change-Id: I39255ddcc419d9a89981e57e8d3a9f466c62e7e6 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 26 ++++++++++++------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 4 ++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c41af53f91e6..344b8263a8ff 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7340,6 +7340,7 @@ static int cam_ife_hw_mgr_handle_hw_sof( struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = ctx; cam_hw_event_cb_func ife_hw_irq_sof_cb; struct cam_isp_hw_sof_event_data sof_done_event_data; + struct timespec64 ts; memset(&sof_done_event_data, 0, sizeof(sof_done_event_data)); @@ -7349,20 +7350,27 @@ static int cam_ife_hw_mgr_handle_hw_sof( switch (event_info->res_id) { case CAM_ISP_HW_VFE_IN_CAMIF: case CAM_ISP_HW_VFE_IN_RD: - if (ife_hw_mgr_ctx->is_offline) - cam_ife_hw_mgr_get_offline_sof_timestamp( + /* if frame header is enabled reset qtimer ts */ + if (ife_hw_mgr_ctx->custom_config & + CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) { + sof_done_event_data.timestamp = 0x0; + ktime_get_boottime_ts64(&ts); + sof_done_event_data.boot_time = + (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + CAM_DBG(CAM_ISP, "boot_time 0x%llx", + sof_done_event_data.boot_time); + } else { + if (ife_hw_mgr_ctx->is_offline) + cam_ife_hw_mgr_get_offline_sof_timestamp( &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); - else - cam_ife_mgr_cmd_get_sof_timestamp( + else + cam_ife_mgr_cmd_get_sof_timestamp( ife_hw_mgr_ctx, &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); - - /* if frame header is enabled reset qtimer ts */ - if (ife_hw_mgr_ctx->custom_config & - CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) - sof_done_event_data.timestamp = 0x0; + } if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index dd85eb45d4ab..0566a3fb05eb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3111,7 +3111,7 @@ static int cam_ife_csid_get_time_stamp( const struct cam_ife_csid_udi_reg_offset *udi_reg; struct timespec64 ts; uint32_t time_32, id; - uint64_t time_delta; + uint64_t time_delta = 0; time_stamp = (struct cam_csid_get_time_stamp_args *)cmd_args; res = time_stamp->node_res; @@ -3196,6 +3196,8 @@ static int cam_ife_csid_get_time_stamp( csid_hw->prev_qtimer_ts; time_stamp->boot_timestamp = csid_hw->prev_boot_timestamp + time_delta; + if (time_delta == 0) + CAM_WARN(CAM_ISP, "No qtimer update"); } csid_hw->prev_qtimer_ts = time_stamp->time_stamp_val; csid_hw->prev_boot_timestamp = time_stamp->boot_timestamp; From a677b40a4ab3b95a8cb48d8e44927d4ce517924d Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Fri, 14 Aug 2020 16:47:43 +0530 Subject: [PATCH 454/790] msm: camera: csiphy: Protect phy lanes for holi target Holi target uses 8 bit per phy register format for secure camera usecases. This change takes care of the secure phy bit mask formation specific to holi target. CRs-Fixed: 2757195 Change-Id: Ibe33b7619b484fd6e64d958ce01cba8fb0e72d3b Signed-off-by: Tony Lijo Jose --- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index d9cd5f647f25..4230a12fc0c7 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -111,7 +111,8 @@ static int32_t cam_csiphy_update_secure_info( lane_assign >>= 4; } - if (csiphy_dev->hw_version == CSIPHY_VERSION_V201) { + if ((csiphy_dev->hw_version == CSIPHY_VERSION_V201) || + (csiphy_dev->hw_version == CSIPHY_VERSION_V125)) { phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES + 1; } else if (csiphy_dev->hw_version == CSIPHY_VERSION_V121) { From 3da4eff78a34b3df19c26e3ee1653cf1deab9851 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Sat, 15 Aug 2020 11:45:39 +0530 Subject: [PATCH 455/790] msm: camera: tfe: Fix NULL ptr dereference Fixes NULL ptr deref caused by incorrectly passing res_id in place of res_type. CRs-Fixed: 2755471 Change-Id: I55ccb6a5fec6e61f79ed0b2cd9fc0cdc62f65b0e Signed-off-by: Trishansh Bhardwaj --- drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 10 +++++----- drivers/cam_utils/cam_soc_util.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index afa5464afd63..05b5924003d3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -1649,19 +1649,19 @@ static int cam_tfe_bus_rup_bottom_half( static uint32_t cam_tfe_bus_get_last_consumed_addr( struct cam_tfe_bus_priv *bus_priv, - uint32_t res_id) + uint32_t out_id) { uint32_t val = 0; struct cam_isp_resource_node *rsrc_node = NULL; struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; struct cam_tfe_bus_wm_resource_data *wm_rsrc_data = NULL; - if (res_id >= CAM_TFE_BUS_TFE_OUT_MAX) { - CAM_ERR(CAM_ISP, "invalid res id:%u", res_id); + if (out_id >= CAM_TFE_BUS_TFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "invalid out_id:%u", out_id); return 0; } - rsrc_node = &bus_priv->tfe_out[res_id]; + rsrc_node = &bus_priv->tfe_out[out_id]; rsrc_data = rsrc_node->res_priv; wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv; @@ -1705,7 +1705,7 @@ static int cam_tfe_bus_bufdone_bottom_half( evt_info.reg_val = cam_tfe_bus_get_last_consumed_addr( out_rsrc_data->bus_priv, - evt_info.res_id); + out_rsrc_data->out_id); out_rsrc_data->event_cb(out_rsrc_data->priv, CAM_ISP_HW_EVENT_DONE, (void *)&evt_info); diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 1e4d1bbce4bd..a71820a0759e 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -6,6 +6,7 @@ #ifndef _CAM_SOC_UTIL_H_ #define _CAM_SOC_UTIL_H_ +#include #include #include #include From 1d1edb7030867aecb55d6214ac8d6a5ff00474eb Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Tue, 28 Jul 2020 21:42:02 +0530 Subject: [PATCH 456/790] msm: camera: sync: Add SYNC_V4L_EVENT_V2 support in sync driver Add SYNC_V4L_EVENT_V2 support in sync driver. As part of this change, added the reason code field as part of sync event header. This failure reason code is filled by camera kernel driver and propagate to userspace. CRs-Fixed: 2750553 Change-Id: I206d0d51c38cfe4214814b89d241f51c1f50605b Signed-off-by: Alok Chauhan --- drivers/cam_core/cam_context_utils.c | 12 ++-- drivers/cam_core/cam_hw_mgr_intf.h | 2 + drivers/cam_cust/cam_custom_context.c | 15 ++-- drivers/cam_isp/cam_isp_context.c | 59 +++++++++++---- drivers/cam_sync/cam_sync.c | 57 +++++++++++---- drivers/cam_sync/cam_sync_api.h | 3 +- drivers/cam_sync/cam_sync_private.h | 2 + drivers/cam_sync/cam_sync_util.c | 41 +++++++---- drivers/cam_sync/cam_sync_util.h | 13 ++-- include/uapi/camera/media/cam_sync.h | 100 ++++++++++++++++++++++++++ 10 files changed, 251 insertions(+), 53 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 99a51ad193bb..beb28f89d800 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -98,7 +98,8 @@ int cam_context_buf_done_from_hw(struct cam_context *ctx, for (j = 0; j < req->num_out_map_entries; j++) { CAM_DBG(CAM_REQ, "fence %d signal with %d", req->out_map_entries[j].sync_id, result); - cam_sync_signal(req->out_map_entries[j].sync_id, result); + cam_sync_signal(req->out_map_entries[j].sync_id, result, + done->evt_param); req->out_map_entries[j].sync_id = -1; } @@ -661,7 +662,8 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) if (req->out_map_entries[i].sync_id != -1) { rc = cam_sync_signal( req->out_map_entries[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_FLUSH); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled, sync_id:%d", @@ -733,7 +735,8 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) if (req->out_map_entries[i].sync_id != -1) { rc = cam_sync_signal( req->out_map_entries[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_FLUSH); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled ctx: %pK dev_name: %s dev_handle: %d ctx_state: %d", @@ -846,7 +849,8 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, req->out_map_entries[i].sync_id; if (sync_id != -1) { rc = cam_sync_signal(sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_FLUSH); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled, sync_id:%d", diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 626b3be1489e..9c243f19a872 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -90,6 +90,7 @@ struct cam_hw_fence_map_entry { * @resrouce_handle: list of the resource handle * @timestamp: time stamp * @request_id: request identifier + * @evt_param: event parameter * */ struct cam_hw_done_event_data { @@ -97,6 +98,7 @@ struct cam_hw_done_event_data { uint32_t resource_handle[CAM_NUM_OUT_PER_COMP_IRQ_MAX]; struct timeval timestamp; uint64_t request_id; + uint32_t evt_param; }; /** diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 62b138633454..7126f6ba7e7c 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -182,7 +182,8 @@ static int __cam_custom_ctx_frame_done( } rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, - CAM_SYNC_STATE_SIGNALED_SUCCESS); + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_EVENT_SUCCESS); if (rc) CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); @@ -368,7 +369,8 @@ static int __cam_custom_ctx_flush_req(struct cam_context *ctx, req_custom->fence_map_out[i].sync_id); rc = cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_FLUSH); if (rc) CAM_ERR_RATE_LIMIT(CAM_CUSTOM, "signal fence failed\n"); @@ -543,7 +545,8 @@ static int __cam_custom_stop_dev_core( if (req_custom->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -559,7 +562,8 @@ static int __cam_custom_stop_dev_core( if (req_custom->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -575,7 +579,8 @@ static int __cam_custom_stop_dev_core( if (req_custom->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_custom->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_EVENT_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 21c1f9416583..c1e9b968cd93 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -813,7 +813,8 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( for (i = 0; i < req_isp->num_fence_map_out; i++) rc = cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); list_add_tail(&req->list, &ctx->free_req_list); CAM_DBG(CAM_REQ, @@ -935,7 +936,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( ctx->ctx_id); rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, - CAM_SYNC_STATE_SIGNALED_SUCCESS); + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_EVENT_SUCCESS); if (rc) CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); @@ -948,7 +950,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( ctx->ctx_id); rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); if (rc) CAM_ERR(CAM_ISP, "Sync failed with rc = %d", rc); @@ -1074,7 +1077,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx->ctx_id); rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, - CAM_SYNC_STATE_SIGNALED_SUCCESS); + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_EVENT_SUCCESS); if (rc) CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); @@ -1087,7 +1091,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx->ctx_id); rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); if (rc) CAM_ERR(CAM_ISP, "Sync failed with rc = %d", rc); @@ -2003,6 +2008,22 @@ static int __cam_isp_ctx_buf_done_in_bubble_applied( return rc; } +static uint32_t get_evt_param(uint32_t error_type) +{ + switch (error_type) { + case CAM_ISP_HW_ERROR_OVERFLOW: + return CAM_SYNC_ISP_EVENT_OVERFLOW; + case CAM_ISP_HW_ERROR_P2I_ERROR: + return CAM_SYNC_ISP_EVENT_P2I_ERROR; + case CAM_ISP_HW_ERROR_VIOLATION: + return CAM_SYNC_ISP_EVENT_VIOLATION; + case CAM_ISP_HW_ERROR_BUSIF_OVERFLOW: + return CAM_SYNC_ISP_EVENT_BUSIF_OVERFLOW; + default: + return CAM_SYNC_ISP_EVENT_UNKNOWN; + } +} + static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, void *evt_data) { @@ -2019,6 +2040,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, uint64_t error_request_id; struct cam_hw_fence_map_entry *fence_map_out = NULL; struct cam_req_mgr_message req_msg; + uint32_t evt_param; struct cam_context *ctx = ctx_isp->base; struct cam_isp_hw_error_event_data *error_event_data = @@ -2043,6 +2065,9 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, rc = 0; } } + + evt_param = get_evt_param(error_type); + /* * The error is likely caused by first request on the active list. * If active list is empty check wait list (maybe error hit as soon @@ -2087,7 +2112,8 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, if (req_isp->fence_map_out[i].sync_id != -1) { rc = cam_sync_signal( fence_map_out->sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + evt_param); fence_map_out->sync_id = -1; } } @@ -2118,7 +2144,8 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, if (req_isp->fence_map_out[i].sync_id != -1) { rc = cam_sync_signal( fence_map_out->sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + evt_param); fence_map_out->sync_id = -1; } } @@ -2181,7 +2208,8 @@ end: if (req_isp->fence_map_out[i].sync_id != -1) rc = cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + evt_param); req_isp->fence_map_out[i].sync_id = -1; } list_del_init(&req->list); @@ -3139,7 +3167,8 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, req_isp->fence_map_out[i].sync_id); rc = cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_ISP_EVENT_FLUSH); if (rc) { tmp = req_isp->fence_map_out[i].sync_id; CAM_ERR_RATE_LIMIT(CAM_ISP, @@ -3605,7 +3634,8 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); } list_add_tail(&req->list, &ctx->free_req_list); ctx_isp->active_req_cnt--; @@ -5025,7 +5055,8 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_ISP_EVENT_HW_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -5041,7 +5072,8 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_ISP_EVENT_HW_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -5057,7 +5089,8 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (req_isp->fence_map_out[i].sync_id != -1) { cam_sync_signal( req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_CANCEL); + CAM_SYNC_STATE_SIGNALED_CANCEL, + CAM_SYNC_ISP_EVENT_HW_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 68fea1904ffe..748878e94478 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -184,7 +184,7 @@ int cam_sync_deregister_callback(sync_callback cb_func, return found ? 0 : -ENOENT; } -int cam_sync_signal(int32_t sync_obj, uint32_t status) +int cam_sync_signal(int32_t sync_obj, uint32_t status, uint32_t event_cause) { struct sync_table_row *row = NULL; struct sync_table_row *parent_row = NULL; @@ -228,8 +228,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status) (status != CAM_SYNC_STATE_SIGNALED_CANCEL)) { spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); CAM_ERR(CAM_SYNC, - "Error: signaling with undefined status = %d", - status); + "Error: signaling with undefined status = %d event reason = %u", + status, event_cause); return -EINVAL; } @@ -239,7 +239,7 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status) } row->state = status; - cam_sync_util_dispatch_signaled_cb(sync_obj, status); + cam_sync_util_dispatch_signaled_cb(sync_obj, status, event_cause); /* copy parent list to local and release child lock */ INIT_LIST_HEAD(&parents_list); @@ -275,7 +275,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status) if (!parent_row->remaining) cam_sync_util_dispatch_signaled_cb( - parent_info->sync_id, parent_row->state); + parent_info->sync_id, parent_row->state, + event_cause); spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); list_del_init(&parent_info->list); @@ -514,7 +515,8 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl) } return cam_sync_signal(sync_signal.sync_obj, - sync_signal.sync_state); + sync_signal.sync_state, + CAM_SYNC_CAM_SYNC_SIGNAL_EVENT); } static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl) @@ -664,7 +666,8 @@ static int cam_sync_handle_register_user_payload( sync_obj, row->state, user_payload_kernel->payload_data, - CAM_SYNC_USER_PAYLOAD_SIZE * sizeof(__u64)); + CAM_SYNC_USER_PAYLOAD_SIZE * sizeof(__u64), + CAM_SYNC_REGISTER_PAYLOAD_EVENT); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); kfree(user_payload_kernel); @@ -869,7 +872,8 @@ static int cam_sync_close(struct file *filep) */ if (row->state == CAM_SYNC_STATE_ACTIVE) { rc = cam_sync_signal(i, - CAM_SYNC_STATE_SIGNALED_ERROR); + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_v4l2_RELEASE_EVENT); if (rc < 0) CAM_ERR(CAM_SYNC, "Cleanup signal fail idx:%d\n", @@ -912,11 +916,24 @@ static int cam_sync_close(struct file *filep) static void cam_sync_event_queue_notify_error(const struct v4l2_event *old, struct v4l2_event *new) { - struct cam_sync_ev_header *ev_header; + if (sync_dev->version == CAM_SYNC_V4L_EVENT_V2) { + struct cam_sync_ev_header_v2 *ev_header; - ev_header = CAM_SYNC_GET_HEADER_PTR((*old)); - CAM_ERR(CAM_CRM, "Failed to notify event id %d fence %d statue %d", - old->id, ev_header->sync_obj, ev_header->status); + ev_header = CAM_SYNC_GET_HEADER_PTR_V2((*old)); + CAM_ERR(CAM_CRM, + "Failed to notify event id %d fence %d statue %d reason %u %u %u %u", + old->id, ev_header->sync_obj, ev_header->status, + ev_header->evt_param[0], ev_header->evt_param[1], + ev_header->evt_param[2], ev_header->evt_param[3]); + + } else { + struct cam_sync_ev_header *ev_header; + + ev_header = CAM_SYNC_GET_HEADER_PTR((*old)); + CAM_ERR(CAM_CRM, + "Failed to notify event id %d fence %d statue %d", + old->id, ev_header->sync_obj, ev_header->status); + } } static struct v4l2_subscribed_event_ops cam_sync_v4l2_ops = { @@ -926,6 +943,14 @@ static struct v4l2_subscribed_event_ops cam_sync_v4l2_ops = { int cam_sync_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { + if (!((sub->type == CAM_SYNC_V4L_EVENT) || + (sub->type == CAM_SYNC_V4L_EVENT_V2))) { + CAM_ERR(CAM_SYNC, "Non supported event type 0x%x", sub->type); + return -EINVAL; + } + + sync_dev->version = sub->type; + CAM_DBG(CAM_SYNC, "Sync event verion type 0x%x", sync_dev->version); return v4l2_event_subscribe(fh, sub, CAM_SYNC_MAX_V4L2_EVENTS, &cam_sync_v4l2_ops); } @@ -933,6 +958,12 @@ int cam_sync_subscribe_event(struct v4l2_fh *fh, int cam_sync_unsubscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { + if (!((sub->type == CAM_SYNC_V4L_EVENT) || + (sub->type == CAM_SYNC_V4L_EVENT_V2))) { + CAM_ERR(CAM_SYNC, "Non supported event type 0x%x", sub->type); + return -EINVAL; + } + return v4l2_event_unsubscribe(fh, sub); } @@ -1068,7 +1099,7 @@ int cam_synx_sync_signal(int32_t sync_obj, uint32_t synx_status) break; } - rc = cam_sync_signal(sync_obj, sync_status); + rc = cam_sync_signal(sync_obj, sync_status, CAM_SYNC_EVENT_SYNX); if (rc) { CAM_ERR(CAM_SYNC, "synx signal failed with %d, sync_obj=%d, synx_status=%d, sync_status=%d", diff --git a/drivers/cam_sync/cam_sync_api.h b/drivers/cam_sync/cam_sync_api.h index a46e37b31b10..c79fda8df74c 100644 --- a/drivers/cam_sync/cam_sync_api.h +++ b/drivers/cam_sync/cam_sync_api.h @@ -76,10 +76,11 @@ int cam_sync_deregister_callback(sync_callback cb_func, * @param sync_obj: int referencing the sync object. * @param status: Status of the signaling. Can be either SYNC_SIGNAL_ERROR or * SYNC_SIGNAL_SUCCESS. + * @param evt_param: Event parameter * * @return Status of operation. Negative in case of error. Zero otherwise. */ -int cam_sync_signal(int32_t sync_obj, uint32_t status); +int cam_sync_signal(int32_t sync_obj, uint32_t status, uint32_t evt_param); /** * @brief: Merges multiple sync objects diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index 8d95efe2cf88..2f270ae181aa 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -182,6 +182,7 @@ struct cam_signalable_info { * @cam_sync_eventq : Event queue used to dispatch user payloads to user space * @bitmap : Bitmap representation of all sync objects * @params : Parameters for synx call back registration + * @version : version support */ struct sync_device { struct video_device *vdev; @@ -198,6 +199,7 @@ struct sync_device { #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) struct synx_register_params params; #endif + uint32_t version; }; diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c index 44a7bd4d0574..7e939fcbbbfe 100644 --- a/drivers/cam_sync/cam_sync_util.c +++ b/drivers/cam_sync/cam_sync_util.c @@ -300,7 +300,7 @@ void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work) } void cam_sync_util_dispatch_signaled_cb(int32_t sync_obj, - uint32_t status) + uint32_t status, uint32_t event_cause) { struct sync_callback_info *sync_cb; struct sync_user_payload *payload_info; @@ -339,7 +339,8 @@ void cam_sync_util_dispatch_signaled_cb(int32_t sync_obj, sync_obj, status, payload_info->payload_data, - CAM_SYNC_PAYLOAD_WORDS * sizeof(__u64)); + CAM_SYNC_PAYLOAD_WORDS * sizeof(__u64), + event_cause); list_del_init(&payload_info->list); /* @@ -361,24 +362,40 @@ void cam_sync_util_send_v4l2_event(uint32_t id, uint32_t sync_obj, int status, void *payload, - int len) + int len, uint32_t event_cause) { struct v4l2_event event; __u64 *payload_data = NULL; - struct cam_sync_ev_header *ev_header = NULL; - event.id = id; - event.type = CAM_SYNC_V4L_EVENT; + if (sync_dev->version == CAM_SYNC_V4L_EVENT_V2) { + struct cam_sync_ev_header_v2 *ev_header = NULL; - ev_header = CAM_SYNC_GET_HEADER_PTR(event); - ev_header->sync_obj = sync_obj; - ev_header->status = status; + event.id = id; + event.type = CAM_SYNC_V4L_EVENT_V2; + + ev_header = CAM_SYNC_GET_HEADER_PTR_V2(event); + ev_header->sync_obj = sync_obj; + ev_header->status = status; + ev_header->version = sync_dev->version; + ev_header->evt_param[CAM_SYNC_EVENT_REASON_CODE_INDEX] = + event_cause; + payload_data = CAM_SYNC_GET_PAYLOAD_PTR_V2(event, __u64); + } else { + struct cam_sync_ev_header *ev_header = NULL; + + event.id = id; + event.type = CAM_SYNC_V4L_EVENT; + + ev_header = CAM_SYNC_GET_HEADER_PTR(event); + ev_header->sync_obj = sync_obj; + ev_header->status = status; + payload_data = CAM_SYNC_GET_PAYLOAD_PTR(event, __u64); + } - payload_data = CAM_SYNC_GET_PAYLOAD_PTR(event, __u64); memcpy(payload_data, payload, len); - v4l2_event_queue(sync_dev->vdev, &event); - CAM_DBG(CAM_SYNC, "send v4l2 event for sync_obj :%d", + CAM_DBG(CAM_SYNC, "send v4l2 event version %d for sync_obj :%d", + sync_dev->version, sync_obj); } diff --git a/drivers/cam_sync/cam_sync_util.h b/drivers/cam_sync/cam_sync_util.h index e114c33c655a..00bceb634961 100644 --- a/drivers/cam_sync/cam_sync_util.h +++ b/drivers/cam_sync/cam_sync_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __CAM_SYNC_UTIL_H__ @@ -82,13 +82,14 @@ void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work); /** * @brief: Function to dispatch callbacks for a signaled sync object * - * @sync_obj : Sync object that is signaled - * @status : Status of the signaled object + * @sync_obj : Sync object that is signaled + * @status : Status of the signaled object + * @evt_param : Event paramaeter * * @return None */ void cam_sync_util_dispatch_signaled_cb(int32_t sync_obj, - uint32_t status); + uint32_t status, uint32_t evt_param); /** * @brief: Function to send V4L event to user space @@ -97,6 +98,7 @@ void cam_sync_util_dispatch_signaled_cb(int32_t sync_obj, * @param status : Status of the event * @payload : Payload that needs to be sent to user space * @len : Length of the payload + * @evt_param : Event Paramenter * * @return None */ @@ -104,7 +106,8 @@ void cam_sync_util_send_v4l2_event(uint32_t id, uint32_t sync_obj, int status, void *payload, - int len); + int len, + uint32_t evt_param); /** * @brief: Function which gets the next state of the sync object based on the diff --git a/include/uapi/camera/media/cam_sync.h b/include/uapi/camera/media/cam_sync.h index c2031c5d8e10..87681dd121fd 100644 --- a/include/uapi/camera/media/cam_sync.h +++ b/include/uapi/camera/media/cam_sync.h @@ -15,6 +15,7 @@ /* V4L event which user space will subscribe to */ #define CAM_SYNC_V4L_EVENT (V4L2_EVENT_PRIVATE_START + 0) +#define CAM_SYNC_V4L_EVENT_V2 (V4L2_EVENT_PRIVATE_START + 1) /* Specific event ids to get notified in user space */ #define CAM_SYNC_V4L_EVENT_ID_CB_TRIG 0 @@ -31,12 +32,96 @@ #define CAM_SYNC_GET_HEADER_PTR(ev) \ ((struct cam_sync_ev_header *)ev.u.data) +#define CAM_SYNC_GET_PAYLOAD_PTR_V2(ev, type) \ + (type *)((char *)ev.u.data + sizeof(struct cam_sync_ev_header_v2)) + +#define CAM_SYNC_GET_HEADER_PTR_V2(ev) \ + ((struct cam_sync_ev_header_v2 *)ev.u.data) + #define CAM_SYNC_STATE_INVALID 0 #define CAM_SYNC_STATE_ACTIVE 1 #define CAM_SYNC_STATE_SIGNALED_SUCCESS 2 #define CAM_SYNC_STATE_SIGNALED_ERROR 3 #define CAM_SYNC_STATE_SIGNALED_CANCEL 4 +/* Top level sync event reason types */ +#define CAM_SYNC_EVENT_UNKNOWN 0 +#define CAM_SYNC_EVENT_SUCCESS 1 +#define CAM_SYNC_EVENT_FLUSH 2 +#define CAM_SYNC_EVENT_STOP 3 +#define CAM_SYNC_EVENT_SYNX 4 + + +/* ISP Sync event reason types */ +#define CAM_SYNC_ISP_EVENT_START 20 +#define CAM_SYNC_ISP_EVENT_UNKNOWN (CAM_SYNC_ISP_EVENT_START + 0) +#define CAM_SYNC_ISP_EVENT_BUBBLE (CAM_SYNC_ISP_EVENT_START + 1) +#define CAM_SYNC_ISP_EVENT_OVERFLOW (CAM_SYNC_ISP_EVENT_START + 2) +#define CAM_SYNC_ISP_EVENT_P2I_ERROR (CAM_SYNC_ISP_EVENT_START + 3) +#define CAM_SYNC_ISP_EVENT_VIOLATION (CAM_SYNC_ISP_EVENT_START + 4) +#define CAM_SYNC_ISP_EVENT_BUSIF_OVERFLOW (CAM_SYNC_ISP_EVENT_START + 5) +#define CAM_SYNC_ISP_EVENT_FLUSH (CAM_SYNC_ISP_EVENT_START + 6) +#define CAM_SYNC_ISP_EVENT_HW_STOP (CAM_SYNC_ISP_EVENT_START + 7) +#define CAM_SYNC_ISP_EVENT_END (CAM_SYNC_ISP_EVENT_START + 50) + +/* ICP Sync event reason types */ +#define CAM_SYNC_ICP_EVENT_START (CAM_SYNC_ISP_EVENT_END + 1) +#define CAM_SYNC_ICP_EVENT_UNKNOWN (CAM_SYNC_ICP_EVENT_START + 0) +#define CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE (CAM_SYNC_ICP_EVENT_START + 1) +#define CAM_SYNC_ICP_EVENT_CONFIG_ERR (CAM_SYNC_ICP_EVENT_START + 2) +#define CAM_SYNC_ICP_EVENT_END (CAM_SYNC_ICP_EVENT_START + 50) + +/* JPEG Sync event reason types */ +#define CAM_SYNC_JPEG_EVENT_START (CAM_SYNC_ICP_EVENT_END + 1) +#define CAM_SYNC_JPEG_EVENT_UNKNOWN (CAM_SYNC_JPEG_EVENT_START + 0) +#define CAM_SYNC_JPEG_EVENT_INVLD_CMD (CAM_SYNC_JPEG_EVENT_START + 1) +#define CAM_SYNC_JPEG_EVENT_SET_IRQ_CB (CAM_SYNC_JPEG_EVENT_START + 2) +#define CAM_SYNC_JPEG_EVENT_HW_RESET_FAILED (CAM_SYNC_JPEG_EVENT_START + 3) +#define CAM_SYNC_JPEG_EVENT_CDM_CHANGE_BASE_ERR (CAM_SYNC_JPEG_EVENT_START + 4) +#define CAM_SYNC_JPEG_EVENT_CDM_CONFIG_ERR (CAM_SYNC_JPEG_EVENT_START + 5) +#define CAM_SYNC_JPEG_EVENT_START_HW_ERR (CAM_SYNC_JPEG_EVENT_START + 6) +#define CAM_SYNC_JPEG_EVENT_END (CAM_SYNC_JPEG_EVENT_START + 50) + +/* FD Sync event reason types */ +#define CAM_SYNC_FD_EVENT_START (CAM_SYNC_JPEG_EVENT_END + 1) +#define CAM_SYNC_FD_EVENT_UNKNOWN (CAM_SYNC_FD_EVENT_START + 0) +#define CAM_SYNC_FD_EVENT_IRQ_FRAME_DONE (CAM_SYNC_FD_EVENT_START + 1) +#define CAM_SYNC_FD_EVENT_IRQ_RESET_DONE (CAM_SYNC_FD_EVENT_START + 2) +#define CAM_SYNC_FD_EVENT_HALT (CAM_SYNC_FD_EVENT_START + 3) +#define CAM_SYNC_FD_EVENT_END (CAM_SYNC_FD_EVENT_START + 50) + +/* LRME Sync event reason types */ +#define CAM_SYNC_LRME_EVENT_START (CAM_SYNC_FD_EVENT_END + 1) +#define CAM_SYNC_LRME_EVENT_UNKNOWN (CAM_SYNC_LRME_EVENT_START + 0) +#define CAM_SYNC_LRME_EVENT_CB_ERROR (CAM_SYNC_LRME_EVENT_START + 1) +#define CAM_SYNC_LRME_EVENT_END (CAM_SYNC_LRME_EVENT_START + 50) + +/* OPE Sync event reason types */ +#define CAM_SYNC_OPE_EVENT_START (CAM_SYNC_LRME_EVENT_END + 1) +#define CAM_SYNC_OPE_EVENT_UNKNOWN (CAM_SYNC_OPE_EVENT_START + 0) +#define CAM_SYNC_OPE_EVENT_PAGE_FAULT (CAM_SYNC_OPE_EVENT_START + 1) +#define CAM_SYNC_OPE_EVENT_HW_HANG (CAM_SYNC_OPE_EVENT_START + 2) +#define CAM_SYNC_OPE_EVENT_HALT (CAM_SYNC_OPE_EVENT_START + 3) +#define CAM_SYNC_OPE_EVENT_CONFIG_ERR (CAM_SYNC_OPE_EVENT_START + 4) +#define CAM_SYNC_OPE_EVENT_HW_FLUSH (CAM_SYNC_OPE_EVENT_START + 5) +#define CAM_SYNC_OPE_EVENT_HW_RESUBMIT (CAM_SYNC_OPE_EVENT_START + 6) +#define CAM_SYNC_OPE_EVENT_HW_RESET_DONE (CAM_SYNC_OPE_EVENT_START + 7) +#define CAM_SYNC_OPE_EVENT_HW_ERROR (CAM_SYNC_OPE_EVENT_START + 8) +#define CAM_SYNC_OPE_EVENT_INVLD_CMD (CAM_SYNC_OPE_EVENT_START + 9) +#define CAM_SYNC_OPE_EVENT_HW_RESET_FAILED (CAM_SYNC_OPE_EVENT_START + 10) +#define CAM_SYNC_OPE_EVENT_END (CAM_SYNC_OPE_EVENT_START + 50) + +/* Others ioctl/v4l2 Sync event reason types */ +#define CAM_SYNC_OTHER_EVENT_START (CAM_SYNC_OPE_EVENT_END + 1) +#define CAM_SYNC_REGISTER_PAYLOAD_EVENT (CAM_SYNC_OTHER_EVENT_START + 0) +#define CAM_SYNC_CAM_SYNC_SIGNAL_EVENT (CAM_SYNC_OTHER_EVENT_START + 1) +#define CAM_SYNC_v4l2_RELEASE_EVENT (CAM_SYNC_OTHER_EVENT_START + 2) +#define CAM_SYNC_OTHER_EVENT_END (CAM_SYNC_OTHER_EVENT_START + 50) + +#define CAM_SYNC_EVENT_CNT 7 +#define CAM_SYNC_EVENT_REASON_CODE_INDEX 0 + + /** * struct cam_sync_ev_header - Event header for sync event notification * @@ -48,6 +133,21 @@ struct cam_sync_ev_header { __s32 status; }; +/** + * struct cam_sync_ev_header_v2 - Event header for sync event notification + * + * @sync_obj: Sync object + * @status: Status of the object + * @version: sync driver version + * @evt_param: event parameter + */ +struct cam_sync_ev_header_v2 { + __s32 sync_obj; + __s32 status; + uint32_t version; + uint32_t evt_param[CAM_SYNC_EVENT_CNT]; +}; + /** * struct cam_sync_info - Sync object creation information * From acb34abbad21a099614e1ceecf8ca89a5ad73eba Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 29 Jul 2020 12:32:17 +0530 Subject: [PATCH 457/790] msm: camera: core: Handle event failure reason propagation Handle event failure reason propagation in camera kernel driver. Individual camera kernel driver will fill reason codes for sync failure and send it to sync driver. Sync driver will add this as part of sync event header and propagate to user space. CRs-Fixed: 2750553 Change-Id: I284390fc45757ba8291a44400e2263b9be64b092 Signed-off-by: Alok Chauhan --- drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c | 4 ++++ .../cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 2 ++ drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 17 ++++++++++++++--- drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 4 ++++ drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 14 ++++++++++++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index 079047c51e84..3035982861ee 100644 --- a/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "cam_io_util.h" #include "cam_soc_util.h" @@ -1032,6 +1033,9 @@ notify_context: buf_data.num_handles = frame_req->num_hw_update_entries; buf_data.request_id = frame_req->request_id; + buf_data.evt_param = (irq_type == CAM_FD_IRQ_FRAME_DONE) ? + CAM_SYNC_FD_EVENT_IRQ_FRAME_DONE : + CAM_SYNC_FD_EVENT_IRQ_RESET_DONE; rc = frame_req->hw_ctx->event_cb(frame_req->hw_ctx->cb_priv, evt_id, &buf_data); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 9ca55f30db5f..079984bd94e7 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -2103,6 +2103,7 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) idx = i; if (flag == ICP_FRAME_PROCESS_FAILURE) { + buf_data.evt_param = CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE; if (ioconfig_ack->err_type == CAMERAICP_EABORTED) { CAM_WARN(CAM_ICP, "ctx_id %d req %llu dev %d has been aborted[flushed]", @@ -3860,6 +3861,7 @@ static int cam_icp_mgr_handle_config_err( struct cam_hw_done_event_data buf_data; buf_data.request_id = *(uint64_t *)config_args->priv; + buf_data.evt_param = CAM_SYNC_ICP_EVENT_CONFIG_ERR; ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_SUCCESS, &buf_data); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index b270ce955285..222924fe75b0 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "cam_packet_util.h" #include "cam_hw.h" @@ -43,7 +44,8 @@ static int cam_jpeg_insert_cdm_change_base( struct cam_jpeg_hw_ctx_data *ctx_data, struct cam_jpeg_hw_mgr *hw_mgr); -static int cam_jpeg_process_next_hw_update(void *priv, void *data) +static int cam_jpeg_process_next_hw_update(void *priv, void *data, + struct cam_hw_done_event_data *buf_data) { int rc; int i = 0; @@ -68,6 +70,7 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data) if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { CAM_ERR(CAM_JPEG, "op reset null "); + buf_data->evt_param = CAM_SYNC_JPEG_EVENT_INVLD_CMD; rc = -EFAULT; goto end_error; } @@ -76,6 +79,7 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data) NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + buf_data->evt_param = CAM_SYNC_JPEG_EVENT_HW_RESET_FAILED; goto end_error; } @@ -91,6 +95,7 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data) ctx_data, hw_mgr); if (rc) { CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); + buf_data->evt_param = CAM_SYNC_JPEG_EVENT_CDM_CHANGE_BASE_ERR; goto end_error; } @@ -124,11 +129,13 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data) cdm_cmd); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); + buf_data->evt_param = CAM_SYNC_JPEG_EVENT_CDM_CONFIG_ERR; goto end_error; } if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { CAM_ERR(CAM_JPEG, "op start null "); + buf_data->evt_param = CAM_SYNC_JPEG_EVENT_INVLD_CMD; rc = -EINVAL; goto end_error; } @@ -137,6 +144,7 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data) if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); + buf_data->evt_param = CAM_SYNC_JPEG_EVENT_START_HW_ERR; goto end_error; } @@ -199,7 +207,8 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) (p_cfg_req->num_hw_entry_processed < p_cfg_req->hw_cfg_args.num_hw_update_entries - 2)) { /* start processing next entry before marking device free */ - rc = cam_jpeg_process_next_hw_update(priv, ctx_data); + rc = cam_jpeg_process_next_hw_update(priv, ctx_data, + &buf_data); if (!rc) { mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); return 0; @@ -533,6 +542,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) irq_cb.b_set_cb = true; if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) { CAM_ERR(CAM_JPEG, "op process_cmd null "); + buf_data.evt_param = CAM_SYNC_JPEG_EVENT_INVLD_CMD; rc = -EFAULT; goto end_callcb; } @@ -542,11 +552,12 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) &irq_cb, sizeof(irq_cb)); if (rc) { CAM_ERR(CAM_JPEG, "SET_IRQ_CB failed %d", rc); + buf_data.evt_param = CAM_SYNC_JPEG_EVENT_SET_IRQ_CB; goto end_callcb; } /* insert one of the cdm payloads */ - rc = cam_jpeg_process_next_hw_update(priv, ctx_data); + rc = cam_jpeg_process_next_hw_update(priv, ctx_data, &buf_data); if (rc) { CAM_ERR(CAM_JPEG, "next hw update failed %d", rc); goto end_callcb; diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index df5b61eb916d..40f851c30d1d 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "cam_io_util.h" #include "cam_soc_util.h" @@ -544,6 +545,9 @@ static int cam_lrme_mgr_cb(void *data, struct cam_hw_done_event_data buf_data; buf_data.request_id = frame_req->req_id; + buf_data.evt_param = (cb_args->cb_type & CAM_LRME_CB_ERROR) ? + CAM_SYNC_LRME_EVENT_CB_ERROR : + CAM_SYNC_EVENT_SUCCESS; CAM_DBG(CAM_LRME, "frame req %llu, evt_id %d", frame_req->req_id, evt_id); rc = hw_mgr->event_cb(frame_req->ctxt_to_hw_map, diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index f16b329aaadd..0b7b0ec13db0 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1567,8 +1567,10 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id, ctx->ctx_id); cam_ope_req_timer_reset(ctx); cam_ope_device_timer_reset(ope_hw_mgr); + buf_data.evt_param = CAM_SYNC_EVENT_SUCCESS; } else if (status == CAM_CDM_CB_STATUS_HW_RESUBMIT) { CAM_INFO(CAM_OPE, "After reset of CDM and OPE, reapply req"); + buf_data.evt_param = CAM_SYNC_OPE_EVENT_HW_RESUBMIT; rc = cam_ope_mgr_reapply_config(ope_hw_mgr, ctx, ope_req); if (!rc) goto end; @@ -1583,6 +1585,17 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, cam_ope_dump_req_data(ope_req); rc = cam_ope_mgr_reset_hw(); evt_id = CAM_CTX_EVT_ID_ERROR; + + if (status == CAM_CDM_CB_STATUS_PAGEFAULT) + buf_data.evt_param = CAM_SYNC_OPE_EVENT_PAGE_FAULT; + else if (status == CAM_CDM_CB_STATUS_HW_FLUSH) + buf_data.evt_param = CAM_SYNC_OPE_EVENT_HW_FLUSH; + else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE) + buf_data.evt_param = CAM_SYNC_OPE_EVENT_HW_RESET_DONE; + else if (status == CAM_CDM_CB_STATUS_HW_ERROR) + buf_data.evt_param = CAM_SYNC_OPE_EVENT_HW_ERROR; + else + buf_data.evt_param = CAM_SYNC_OPE_EVENT_UNKNOWN; } ctx->req_cnt--; @@ -3201,6 +3214,7 @@ static int cam_ope_mgr_handle_config_err( ope_req = config_args->priv; buf_data.request_id = ope_req->request_id; + buf_data.evt_param = CAM_SYNC_OPE_EVENT_CONFIG_ERR; ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_ERROR, &buf_data); From 7264d367c385773100f49bf8bc8151fda1749541 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Sun, 16 Aug 2020 11:59:12 +0530 Subject: [PATCH 458/790] msm: camera: tfe: Adds support PHY3 input source Adds support for CSID input source PHY3. CRs-Fixed: 2756383 Change-Id: I988ffc353518b5d932fa95eedeef8607726e183f Signed-off-by: Trishansh Bhardwaj --- .../cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h | 2 +- include/uapi/camera/media/cam_isp_tfe.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h index 4d267bb0868d..94267ca0d1d8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h @@ -162,7 +162,7 @@ static struct cam_tfe_csid_csi2_rx_reg_offset .csi2_capture_short_pkt_vc_shift = 12, .csi2_capture_cphy_pkt_dt_shift = 14, .csi2_capture_cphy_pkt_vc_shift = 20, - .csi2_rx_phy_num_mask = 0x3, + .csi2_rx_phy_num_mask = 0x7, .csi2_rx_long_pkt_hdr_rst_stb_shift = 0x1, .csi2_rx_short_pkt_hdr_rst_stb_shift = 0x2, }; diff --git a/include/uapi/camera/media/cam_isp_tfe.h b/include/uapi/camera/media/cam_isp_tfe.h index fc716311367d..3db5fbf62348 100644 --- a/include/uapi/camera/media/cam_isp_tfe.h +++ b/include/uapi/camera/media/cam_isp_tfe.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_ISP_TFE_H__ @@ -30,6 +30,7 @@ #define CAM_ISP_TFE_IN_RES_PHY_0 (CAM_ISP_TFE_IN_RES_BASE + 1) #define CAM_ISP_TFE_IN_RES_PHY_1 (CAM_ISP_TFE_IN_RES_BASE + 2) #define CAM_ISP_TFE_IN_RES_PHY_2 (CAM_ISP_TFE_IN_RES_BASE + 3) -#define CAM_ISP_TFE_IN_RES_MAX (CAM_ISP_TFE_IN_RES_BASE + 4) +#define CAM_ISP_TFE_IN_RES_PHY_3 (CAM_ISP_TFE_IN_RES_BASE + 4) +#define CAM_ISP_TFE_IN_RES_MAX (CAM_ISP_TFE_IN_RES_BASE + 5) #endif /* __UAPI_CAM_ISP_TFE_H__ */ From 55944b020136d4cddf8fa321c202e4368fe2b237 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Tue, 30 Jun 2020 20:46:28 +0530 Subject: [PATCH 459/790] msm: camera: cpas: read and pass fuse information to user space This change extract the fuse info from DTSI and reads the fuse value then communicate the same to user space using query_cpas_v2 ioctl. CRs-Fixed: 2749665 Change-Id: Ie161dc58a7eab3e7b74a5c406ab696af0e7b546e Signed-off-by: Vikram Sharma --- drivers/cam_cpas/cam_cpas_hw.c | 10 +++- drivers/cam_cpas/cam_cpas_hw_intf.h | 2 + drivers/cam_cpas/cam_cpas_intf.c | 43 +++++++++++++++-- drivers/cam_cpas/cam_cpas_soc.c | 47 ++++++++++++++++++- drivers/cam_cpas/cam_cpas_soc.h | 2 + drivers/cam_cpas/include/cam_cpas_api.h | 10 ++-- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 3 +- drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c | 3 +- include/uapi/camera/media/cam_cpas.h | 43 ++++++++++++++++- include/uapi/camera/media/cam_defs.h | 3 +- 10 files changed, 151 insertions(+), 15 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index edfc42a4f2e9..d8f18a8220bb 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1747,6 +1747,7 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, struct cam_hw_info *cpas_hw; struct cam_cpas *cpas_core; struct cam_cpas_hw_caps *hw_caps; + struct cam_cpas_private_soc *soc_private; if (!hw_priv || !get_hw_cap_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", @@ -1763,9 +1764,16 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, cpas_hw = (struct cam_hw_info *)hw_priv; cpas_core = (struct cam_cpas *) cpas_hw->core_info; hw_caps = (struct cam_cpas_hw_caps *)get_hw_cap_args; - *hw_caps = cpas_core->hw_caps; + /*Extract Fuse Info*/ + soc_private = (struct cam_cpas_private_soc *) + cpas_hw->soc_info.soc_private; + + hw_caps->fuse_info = soc_private->fuse_info; + CAM_INFO(CAM_CPAS, "fuse info->num_fuses %d", + hw_caps->fuse_info.num_fuses); + return 0; } diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index 096437408043..c1e81f2a7624 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -114,6 +114,7 @@ struct cam_cpas_hw_cmd_stop { * @camera_version: Camera version * @cpas_version: CPAS version * @camera_capability: Camera hw capabilities + * @fuse_info: Fuse information * */ struct cam_cpas_hw_caps { @@ -121,6 +122,7 @@ struct cam_cpas_hw_caps { struct cam_hw_version camera_version; struct cam_hw_version cpas_version; uint32_t camera_capability; + struct cam_cpas_fuse_info fuse_info; }; int cam_cpas_hw_probe(struct platform_device *pdev, diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index ddbb3bb2efb9..d75c51488e31 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -173,7 +173,8 @@ int cam_cpas_get_cpas_hw_version(uint32_t *hw_version) int cam_cpas_get_hw_info(uint32_t *camera_family, struct cam_hw_version *camera_version, struct cam_hw_version *cpas_version, - uint32_t *cam_caps) + uint32_t *cam_caps, + struct cam_cpas_fuse_info *cam_fuse_info) { if (!CAM_CPAS_INTF_INITIALIZED()) { CAM_ERR(CAM_CPAS, "cpas intf not initialized"); @@ -186,10 +187,16 @@ int cam_cpas_get_hw_info(uint32_t *camera_family, return -EINVAL; } - *camera_family = g_cpas_intf->hw_caps.camera_family; + *camera_family = g_cpas_intf->hw_caps.camera_family; *camera_version = g_cpas_intf->hw_caps.camera_version; - *cpas_version = g_cpas_intf->hw_caps.cpas_version; - *cam_caps = g_cpas_intf->hw_caps.camera_capability; + *cpas_version = g_cpas_intf->hw_caps.cpas_version; + *cam_caps = g_cpas_intf->hw_caps.camera_capability; + if (cam_fuse_info) + *cam_fuse_info = g_cpas_intf->hw_caps.fuse_info; + + CAM_DBG(CAM_CPAS, "Family %d, version %d.%d cam_caps %d", + *camera_family, camera_version->major, + camera_version->minor, *cam_caps); return 0; } @@ -529,7 +536,32 @@ int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf, rc = cam_cpas_get_hw_info(&query.camera_family, &query.camera_version, &query.cpas_version, - &query.reserved); + &query.reserved, NULL); + if (rc) + break; + + rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query, + sizeof(query)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc); + + break; + } + case CAM_QUERY_CAP_V2: { + struct cam_cpas_query_cap_v2 query; + + rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle), + sizeof(query)); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d", + rc); + break; + } + + rc = cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, + &query.reserved, + &query.fuse_info); if (rc) break; @@ -729,6 +761,7 @@ static int cam_cpas_dev_component_bind(struct device *dev, hw_intf = g_cpas_intf->hw_intf; hw_caps = &g_cpas_intf->hw_caps; + if (hw_intf->hw_ops.get_hw_caps) { rc = hw_intf->hw_ops.get_hw_caps(hw_intf->hw_priv, hw_caps, sizeof(struct cam_cpas_hw_caps)); diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index a7550a397405..f569078ac841 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -18,7 +18,6 @@ static uint cpas_dump; module_param(cpas_dump, uint, 0644); - void cam_cpas_dump_axi_vote_info( const struct cam_cpas_client *cpas_client, const char *identifier, @@ -467,6 +466,51 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, return 0; } +int cam_cpas_get_hw_fuse(struct platform_device *pdev, + struct cam_cpas_private_soc *soc_private) +{ + struct device_node *of_node; + void *fuse; + uint32_t fuse_addr, fuse_bit; + uint32_t fuse_val = 0, feature_bit_pos; + int count = 0, i = 0; + + memset(&soc_private->fuse_info, 0, sizeof(soc_private->fuse_info)); + + of_node = pdev->dev.of_node; + count = of_property_count_u32_elems(of_node, "cam_hw_fuse"); + if (count <= 0) { + CAM_INFO(CAM_CPAS, "no or invalid fuse enrties %d", count); + return 0; + } else if (count%3 != 0) { + CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 3 %d", + count); + return -EINVAL; + } + + for (i = 0; i < count; i = i + 3) { + of_property_read_u32_index(of_node, "cam_hw_fuse", i, + &feature_bit_pos); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1, + &fuse_addr); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2, + &fuse_bit); + CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d", + feature_bit_pos, fuse_addr, fuse_bit); + fuse = ioremap(fuse_addr, 4); + if (fuse) { + fuse_val = cam_io_r(fuse); + soc_private->fuse_info.fuse_val[i].fuse_id = fuse_addr; + soc_private->fuse_info.fuse_val[i].fuse_val = fuse_val; + } + CAM_INFO(CAM_CPAS, "fuse_addr 0x%x, fuse_val %x", + fuse_addr, fuse_val); + soc_private->fuse_info.num_fuses++; + iounmap(fuse); + } + + return 0; +} int cam_cpas_get_hw_features(struct platform_device *pdev, struct cam_cpas_private_soc *soc_private) @@ -532,6 +576,7 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, } cam_cpas_get_hw_features(pdev, soc_private); + cam_cpas_get_hw_fuse(pdev, soc_private); soc_private->camnoc_axi_min_ib_bw = 0; rc = of_property_read_u64(of_node, diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index 45a045ef6f55..71d11bdfc3cb 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -91,6 +91,7 @@ struct cam_cpas_tree_node { * camnoc axi clock * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target * @feature_mask: feature mask value for hw supported features + * @fuse_info: fuse information * */ struct cam_cpas_private_soc { @@ -109,6 +110,7 @@ struct cam_cpas_private_soc { uint32_t camnoc_axi_clk_bw_margin; uint64_t camnoc_axi_min_ib_bw; uint32_t feature_mask; + struct cam_cpas_fuse_info fuse_info; }; void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 1b08b427ddb9..1c248060bb56 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -575,15 +575,17 @@ int cam_cpas_reg_read( * @camera_version : Camera platform version * @cpas_version : Camera cpas version * @cam_caps : Camera capability + * @cam_fuse_info : Camera fuse info * * @return 0 on success. * */ int cam_cpas_get_hw_info( - uint32_t *camera_family, - struct cam_hw_version *camera_version, - struct cam_hw_version *cpas_version, - uint32_t *cam_caps); + uint32_t *camera_family, + struct cam_hw_version *camera_version, + struct cam_hw_version *cpas_version, + uint32_t *cam_caps, + struct cam_cpas_fuse_info *cam_fuse_info); /** * cam_cpas_get_cpas_hw_version() diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 9ca55f30db5f..1cb3ed520c2e 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -6093,7 +6093,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, mutex_init(&icp_hw_mgr.ctx_data[i].ctx_mutex); rc = cam_cpas_get_hw_info(&query.camera_family, - &query.camera_version, &query.cpas_version, &cam_caps); + &query.camera_version, &query.cpas_version, + &cam_caps, NULL); if (rc) { CAM_ERR(CAM_ICP, "failed to get hw info rc=%d", rc); goto destroy_mutex; diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c index d7eee64a37b5..7b0618526058 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -77,7 +77,8 @@ static int cam_ipe_component_bind(struct device *dev, "cell-index", &hw_idx); rc = cam_cpas_get_hw_info(&query.camera_family, - &query.camera_version, &query.cpas_version, &cam_caps); + &query.camera_version, &query.cpas_version, + &cam_caps, NULL); if (rc) { CAM_ERR(CAM_ICP, "failed to get hw info rc=%d", rc); return rc; diff --git a/include/uapi/camera/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h index 71d1f131cbbf..b30326af26c3 100644 --- a/include/uapi/camera/media/cam_cpas.h +++ b/include/uapi/camera/media/cam_cpas.h @@ -61,7 +61,30 @@ #define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) -#define CAM_AXI_PATH_DATA_ALL 256 +#define CAM_AXI_PATH_DATA_ALL 256 +#define CAM_CPAS_FUSES_MAX 32 + +/** + * struct cam_cpas_fuse_value - CPAS fuse value + * + * @fuse_id : Camera fuse identification + * @fuse_val : Camera Fuse Value + */ +struct cam_cpas_fuse_value { + __u32 fuse_id; + __u32 fuse_val; +}; + +/** + * struct cam_cpas_fuse_info - CPAS fuse info + * + * @num_fuses : Number of fuses + * @fuse_val : Array of different fuse info. + */ +struct cam_cpas_fuse_info { + __u32 num_fuses; + struct cam_cpas_fuse_value fuse_val[CAM_CPAS_FUSES_MAX]; +}; /** * struct cam_cpas_query_cap - CPAS query device capability payload @@ -79,6 +102,24 @@ struct cam_cpas_query_cap { struct cam_hw_version cpas_version; }; +/** + * struct cam_cpas_query_cap - CPAS query device capability payload + * + * @camera_family : Camera family type + * @reserved : Reserved field for alignment + * @camera_version : Camera platform version + * @cpas_version : Camera CPAS version within camera platform + * @fuse_info : Camera fuse info + * + */ +struct cam_cpas_query_cap_v2 { + __u32 camera_family; + __u32 reserved; + struct cam_hw_version camera_version; + struct cam_hw_version cpas_version; + struct cam_cpas_fuse_info fuse_info; +}; + /** * struct cam_axi_per_path_bw_vote - Per path bandwidth vote information * diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index 4c132a8a2fe6..d6e2a7fb15e1 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -21,7 +21,8 @@ #define CAM_RELEASE_DEV (CAM_COMMON_OPCODE_BASE + 0x6) #define CAM_SD_SHUTDOWN (CAM_COMMON_OPCODE_BASE + 0x7) #define CAM_FLUSH_REQ (CAM_COMMON_OPCODE_BASE + 0x8) -#define CAM_COMMON_OPCODE_MAX (CAM_COMMON_OPCODE_BASE + 0x9) +#define CAM_QUERY_CAP_V2 (CAM_COMMON_OPCODE_BASE + 0x9) +#define CAM_COMMON_OPCODE_MAX (CAM_COMMON_OPCODE_BASE + 0xa) #define CAM_COMMON_OPCODE_BASE_v2 0x150 #define CAM_ACQUIRE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x1) From b746c4f5272f7b1fd5907697658fa28a7577aa37 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Tue, 30 Jun 2020 17:27:30 +0530 Subject: [PATCH 460/790] msm: camera: core: Send event on smmu page fault Currently when page fault happen, iommu driver callers camera handler with CB details and iova address which caused the page fault. With iommu iova address cam smmu driver finds the closest mapping address for that cb and call the corresponding driver to find the which port caused page fault. This has limitation has page fault address always not mapped. New approach is get the page fault ids from iommu driver. Based on the Pid and Mid values, get the HW id and port ids, go through all context which has this hw id and port id and log the data. Once context id is identified, log the acquire data and last consumed client address details. Dump the hw register data in the given buffer. Send the smmu page fault event through v4l2 queue to user. CRs-Fixed: 2750690 Change-Id: I87c809b3229992c7c95655a4f3c6c70ebc035ae8 Signed-off-by: Ravikishore Pampana --- drivers/cam_cdm/cam_cdm_hw_core.c | 12 +- drivers/cam_core/cam_context.c | 6 +- drivers/cam_core/cam_context.h | 8 +- drivers/cam_core/cam_context_utils.c | 13 +- drivers/cam_core/cam_context_utils.h | 6 +- drivers/cam_core/cam_hw_mgr_intf.h | 16 +- drivers/cam_cpas/cam_cpas_hw.c | 3 + drivers/cam_cust/cam_custom_dev.c | 10 +- drivers/cam_icp/cam_icp_context.c | 9 +- drivers/cam_icp/cam_icp_subdev.c | 13 +- drivers/cam_isp/cam_isp_context.c | 78 +++-- drivers/cam_isp/cam_isp_dev.c | 11 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 268 +++++++++++++++--- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 7 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 52 ++++ .../isp_hw/include/cam_ife_csid_hw_intf.h | 1 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 32 +++ .../isp_hw/include/cam_vfe_hw_intf.h | 3 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c | 25 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 22 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h | 4 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 34 +++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 4 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 54 +++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 2 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 75 ++++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 2 + drivers/cam_jpeg/cam_jpeg_context.c | 9 +- drivers/cam_jpeg/cam_jpeg_dev.c | 12 +- drivers/cam_ope/cam_ope_context.c | 9 +- drivers/cam_ope/cam_ope_subdev.c | 12 +- drivers/cam_smmu/cam_smmu_api.c | 43 ++- drivers/cam_smmu/cam_smmu_api.h | 31 +- include/uapi/camera/media/cam_req_mgr.h | 3 +- 35 files changed, 728 insertions(+), 162 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index fd903f336414..128edaf3e54a 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1224,16 +1224,14 @@ static void cam_hw_cdm_work(struct work_struct *work) } -static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, - struct device *dev, unsigned long iova, int flags, void *token, - uint32_t buf_info) +static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; int i; - if (token) { - cdm_hw = (struct cam_hw_info *)token; + if (pf_info->token) { + cdm_hw = (struct cam_hw_info *)pf_info->token; core = (struct cam_cdm *)cdm_hw->core_info; set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); mutex_lock(&cdm_hw->hw_mutex); @@ -1254,9 +1252,9 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, mutex_unlock(&core->bl_fifo[i].fifo_lock); mutex_unlock(&cdm_hw->hw_mutex); CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n", - (void *)iova); + (void *)pf_info->iova); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT, - (void *)iova); + (void *)pf_info->iova); clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "Invalid token"); diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 4b3078ad79e5..5fc9387e339b 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -287,8 +287,8 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx, return rc; } -int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, - uint32_t buf_info) +int cam_context_dump_pf_info(struct cam_context *ctx, + struct cam_smmu_pf_info *pf_info) { int rc = 0; @@ -301,7 +301,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, (ctx->state < CAM_CTX_STATE_MAX)) { if (ctx->state_machine[ctx->state].pagefault_ops) { rc = ctx->state_machine[ctx->state].pagefault_ops( - ctx, iova, buf_info); + ctx, pf_info); } else { CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", ctx->dev_hdl, ctx->state); diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index c959edb8a2cf..10bc72b89ab9 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -11,6 +11,7 @@ #include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" +#include "cam_smmu_api.h" /* Forward declarations */ struct cam_context; @@ -360,12 +361,11 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx, * @brief: Handle dump active request request command * * @ctx: Object pointer for cam_context - * @iova: Page fault address - * @buf_info: Information about closest memory handle + * @pf_info: Smmu page fault info * */ -int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, - uint32_t buf_info); +int cam_context_dump_pf_info(struct cam_context *ctx, + struct cam_smmu_pf_info *pf_info); /** * cam_context_handle_acquire_dev() diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 99a51ad193bb..d62b9e13499d 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -994,8 +994,8 @@ end: } int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, - struct cam_packet *packet, unsigned long iova, uint32_t buf_info, - bool *mem_found) + struct cam_packet *packet, bool *mem_found, bool *ctx_found, + uint32_t *resource_type, struct cam_smmu_pf_info *pf_info) { int rc = 0; struct cam_hw_cmd_args cmd_args; @@ -1017,9 +1017,14 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO; cmd_args.u.pf_args.pf_data.packet = packet; - cmd_args.u.pf_args.iova = iova; - cmd_args.u.pf_args.buf_info = buf_info; + cmd_args.u.pf_args.iova = pf_info->iova; + cmd_args.u.pf_args.buf_info = pf_info->buf_info; cmd_args.u.pf_args.mem_found = mem_found; + cmd_args.u.pf_args.ctx_found = ctx_found; + cmd_args.u.pf_args.resource_type = resource_type; + cmd_args.u.pf_args.bid = pf_info->bid; + cmd_args.u.pf_args.pid = pf_info->pid; + cmd_args.u.pf_args.mid = pf_info->mid; ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &cmd_args); } diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h index 4aeb7dd338ba..559c4e254b51 100644 --- a/drivers/cam_core/cam_context_utils.h +++ b/drivers/cam_core/cam_context_utils.h @@ -7,6 +7,7 @@ #define _CAM_CONTEXT_UTILS_H_ #include +#include "cam_smmu_api.h" int cam_context_buf_done_from_hw(struct cam_context *ctx, void *done_event_data, uint32_t evt_id); @@ -27,8 +28,9 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx); int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, - struct cam_packet *packet, unsigned long iova, uint32_t buf_info, - bool *mem_found); + struct cam_packet *packet, bool *mem_found, bool *ctx_found, + uint32_t *resource_type, + struct cam_smmu_pf_info *pf_info); int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx); int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 626b3be1489e..126588680d79 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -9,6 +9,8 @@ #include #include #include +#include "cam_smmu_api.h" + /* * This file declares Constants, Enums, Structures and APIs to be used as * Interface between HW Manager and Context. @@ -44,8 +46,8 @@ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, void *evt_data); /* hardware page fault callback function type */ -typedef int (*cam_hw_pagefault_cb_func)(void *context, unsigned long iova, - uint32_t buf_info); +typedef int (*cam_hw_pagefault_cb_func)(void *context, + struct cam_smmu_pf_info *pf_info); /* ctx dump callback function type */ typedef int (*cam_ctx_info_dump_cb_func)(void *context, @@ -293,6 +295,11 @@ struct cam_hw_flush_args { * fault occurred * @mem_found: If fault memory found in current * request + * @ctx_found If fault pid found in context acquired hardware + * @resource_type Resource type of the port which caused pf + * @bid: Indicate the bus id + * @pid: Indicates unique hw group ports + * @mid: Indicates port id of the camera hw * */ struct cam_hw_dump_pf_args { @@ -300,6 +307,11 @@ struct cam_hw_dump_pf_args { unsigned long iova; uint32_t buf_info; bool *mem_found; + bool *ctx_found; + uint32_t *resource_type; + uint32_t bid; + uint32_t pid; + uint32_t mid; }; /** diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index edfc42a4f2e9..99474ab77b13 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -14,6 +14,7 @@ #include "cam_cpas_hw_intf.h" #include "cam_cpas_soc.h" #include "cam_req_mgr_dev.h" +#include "cam_smmu_api.h" static uint cam_min_camnoc_ib_bw; module_param(cam_min_camnoc_ib_bw, uint, 0644); @@ -1431,6 +1432,8 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, } CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); + + cam_smmu_reset_cb_page_fault_cnt(); cpas_hw->hw_state = CAM_HW_STATE_POWER_UP; } diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index af3c7b907af5..d1a344408493 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -25,22 +25,20 @@ static struct cam_custom_dev g_custom_dev; static void cam_custom_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) + struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { + if (!pf_info || !pf_info->token) { CAM_ERR(CAM_CUSTOM, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static const struct of_device_id cam_custom_dt_match[] = { diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index c2edab7d3fd5..064236f007fa 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -22,15 +22,16 @@ static const char icp_dev_name[] = "cam-icp"; -static int cam_icp_context_dump_active_request(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_icp_context_dump_active_request(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + uint32_t resource_type = 0; int rc = 0; - bool b_mem_found = false; + bool b_mem_found = false, b_ctx_found = false; if (!ctx) { CAM_ERR(CAM_ICP, "Invalid ctx"); @@ -52,7 +53,7 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova, CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &b_mem_found); + &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ICP, "Failed to dump pf info"); diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index ee7fe5132d6c..8c79bbbde5fe 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -50,23 +50,20 @@ static const struct of_device_id cam_icp_dt_match[] = { {} }; -static void cam_icp_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) +static void cam_icp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { - CAM_ERR(CAM_ICP, "invalid token in page handler cb"); + if (!pf_info || !pf_info->token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static int cam_icp_subdev_open(struct v4l2_subdev *sd, diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 21c1f9416583..394bfe3f1b65 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -28,8 +28,8 @@ static struct cam_isp_ctx_debug isp_ctx_debug; div_u64_rem(atomic64_add_return(1, head),\ max_entries, (ret)) -static int cam_isp_context_dump_requests(void *data, unsigned long iova, - uint32_t buf_info); +static int cam_isp_context_dump_requests(void *data, + struct cam_smmu_pf_info *pf_info); static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); @@ -5390,9 +5390,8 @@ static struct cam_ctx_ops }, }; - -static int cam_isp_context_dump_requests(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_isp_context_dump_requests(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; @@ -5401,7 +5400,10 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, struct cam_isp_ctx_req *req_isp = NULL; struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; - bool mem_found = false; + struct cam_req_mgr_message req_msg; + struct cam_isp_context *ctx_isp; + uint32_t resource_type = 0; + bool mem_found = false, ctx_found = false, send_error = false; int rc = 0; struct cam_isp_context *isp_ctx = @@ -5424,13 +5426,12 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &mem_found); + &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); - if (mem_found) - CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", - req->request_id, rc); + if (ctx_found) + send_error = true; } CAM_INFO(CAM_ISP, "Iterating over wait_list of isp ctx %d state %d", @@ -5444,13 +5445,12 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, CAM_INFO(CAM_ISP, "Wait List: req_id : %lld ", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &mem_found); + &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); - if (mem_found) - CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", - req->request_id, rc); + if (ctx_found) + send_error = true; } /* @@ -5475,15 +5475,57 @@ static int cam_isp_context_dump_requests(void *data, unsigned long iova, req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &mem_found); + &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); - if (mem_found) - CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", - req->request_id, rc); + if (ctx_found) + send_error = true; } + if (resource_type) { + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + if (ctx_isp->isp_device_type == CAM_IFE_DEVICE_TYPE) + CAM_ERR(CAM_ISP, + "Page fault on resource id:%s (0x%x) ctx id:%d frame id:%d reported id:%lld applied id:%lld", + __cam_isp_resource_handle_id_to_type( + resource_type), + resource_type, ctx->ctx_id, ctx_isp->frame_id, + ctx_isp->reported_req_id, + ctx_isp->last_applied_req_id); + else + CAM_ERR(CAM_ISP, + "Page fault on resource id:%s (0x%x) ctx id:%d frame id:%d reported id:%lld applied id:%lld", + __cam_isp_tfe_resource_handle_id_to_type( + resource_type), + resource_type, ctx->ctx_id, ctx_isp->frame_id, + ctx_isp->reported_req_id, + ctx_isp->last_applied_req_id); + + } + + if (send_error) { + CAM_INFO(CAM_ISP, + "page fault notifying to umd ctx %u session_hdl:%d device_hdl:%d link_hdl:%d", + ctx->ctx_id, ctx->session_hdl, + ctx->dev_hdl, ctx->link_hdl); + + req_msg.session_hdl = ctx->session_hdl; + req_msg.u.err_msg.device_hdl = ctx->dev_hdl; + req_msg.u.err_msg.error_type = + CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT; + req_msg.u.err_msg.link_hdl = ctx->link_hdl; + req_msg.u.err_msg.request_id = 0; + 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, + "could not send page fault notification ctx %u session_hdl:%d device_hdl:%d link_hdl:%d", + ctx->ctx_id, ctx->session_hdl, + ctx->dev_hdl, ctx->link_hdl); + } return rc; } diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 778621bcdb40..10aa46ffc0f4 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -22,23 +22,20 @@ static struct cam_isp_dev g_isp_dev; -static void cam_isp_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) +static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { + if (!pf_info || !pf_info->token) { CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static const struct of_device_id cam_isp_dt_match[] = { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c41af53f91e6..00a6fd9fc1fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1527,7 +1527,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( continue; hw_intf = ife_hw_mgr->ife_devices[ - csid_res->hw_res[i]->hw_intf->hw_idx]; + csid_res->hw_res[i]->hw_intf->hw_idx]->hw_intf; if (i == CAM_ISP_HW_SPLIT_LEFT && ife_src_res->is_dual_isp) { @@ -2348,7 +2348,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_bus_rd( if (!ife_hw_mgr->ife_devices[j]) continue; - hw_intf = ife_hw_mgr->ife_devices[j]; + hw_intf = ife_hw_mgr->ife_devices[j]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -2379,7 +2379,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_bus_rd( if (j == ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx) continue; - hw_intf = ife_hw_mgr->ife_devices[j]; + hw_intf = ife_hw_mgr->ife_devices[j]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -2463,7 +2463,7 @@ static int cam_ife_hw_mgr_acquire_offline_res_ife_camif( vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE; hw_intf = ife_hw_mgr->ife_devices[ - ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx]; + ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -2493,7 +2493,7 @@ static int cam_ife_hw_mgr_acquire_offline_res_ife_camif( vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE; hw_intf = ife_hw_mgr->ife_devices[ - ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx]; + ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire, sizeof(struct cam_vfe_acquire_args)); @@ -4163,10 +4163,10 @@ static int cam_ife_mgr_reset_vfe_hw(struct cam_ife_hw_mgr *hw_mgr, if (!hw_mgr->ife_devices[i]) continue; - if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + if (hw_idx != hw_mgr->ife_devices[i]->hw_intf->hw_idx) continue; CAM_DBG(CAM_ISP, "VFE (id = %d) reset", hw_idx); - vfe_hw_intf = hw_mgr->ife_devices[i]; + vfe_hw_intf = hw_mgr->ife_devices[i]->hw_intf; vfe_hw_intf->hw_ops.reset(vfe_hw_intf->hw_priv, &vfe_reset_type, sizeof(vfe_reset_type)); break; @@ -4188,12 +4188,15 @@ static int cam_ife_mgr_unmask_bus_wr_irq(struct cam_ife_hw_mgr *hw_mgr, } for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) { - if (hw_idx != hw_mgr->ife_devices[i]->hw_idx) + if (!hw_mgr->ife_devices[i]) + continue; + + if (hw_idx != hw_mgr->ife_devices[i]->hw_intf->hw_idx) continue; CAM_DBG(CAM_ISP, "Unmask VFE:%d BUS_WR IRQ", hw_idx); - vfe_hw_intf = hw_mgr->ife_devices[i]; + vfe_hw_intf = hw_mgr->ife_devices[i]->hw_intf; vfe_hw_intf->hw_ops.process_cmd(vfe_hw_intf->hw_priv, CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, @@ -4632,6 +4635,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->dsp_enabled = false; ctx->is_fe_enabled = false; ctx->is_offline = false; + ctx->pf_mid_found = false; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; @@ -6421,42 +6425,43 @@ static int cam_ife_mgr_sof_irq_debug( return rc; } -static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, - int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, - bool *mem_found) +static void cam_ife_mgr_print_io_bufs(struct cam_ife_hw_mgr *hw_mgr, + uint32_t res_id, struct cam_packet *packet, + bool *ctx_found, struct cam_ife_hw_mgr_ctx *ctx) { - dma_addr_t iova_addr; - size_t src_buf_size; - int i; - int j; - int rc = 0; - int32_t mmu_hdl; struct cam_buf_io_cfg *io_cfg = NULL; + int32_t mmu_hdl, iommu_hdl, sec_mmu_hdl; + dma_addr_t iova_addr; + size_t src_buf_size; + int i, j, rc = 0; - if (mem_found) - *mem_found = false; + iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl; + sec_mmu_hdl = hw_mgr->mgr_common.img_iommu_hdl_secure; io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + packet->io_configs_offset / 4); for (i = 0; i < packet->num_io_configs; i++) { + if (io_cfg[i].resource_type != res_id) + continue; + else + break; + } + + if (i == packet->num_io_configs) { + *ctx_found = false; + CAM_ERR(CAM_ISP, + "getting io port for mid resource id failed ctx id:%d req id:%lld res id:0x%x", + ctx->ctx_index, packet->header.request_id, + res_id); + return; + } + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { if (!io_cfg[i].mem_handle[j]) break; - 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", - io_cfg[i].resource_type, - io_cfg[i].mem_handle[j], - pf_buf_info); - if (mem_found) - *mem_found = true; - } - CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d", io_cfg[i].resource_type, io_cfg[i].fence, @@ -6476,7 +6481,6 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, } if ((iova_addr & 0xFFFFFFFF) != iova_addr) { CAM_ERR(CAM_ISP, "Invalid mapped address"); - rc = -EINVAL; continue; } @@ -6492,7 +6496,185 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, io_cfg[i].offsets[j], io_cfg[i].mem_handle[j]); } +} + +static void cam_ife_mgr_pf_dump(uint32_t res_id, + struct cam_ife_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_event_info event_info; + uint32_t res_id_out; + int i, rc = 0; + + /* dump the registers */ + rc = cam_ife_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, + CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, NULL, false); + if (rc) + CAM_ERR(CAM_ISP, + "Reg dump on pf failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + + + /* dump the acquire data */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, 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) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_LOG_ACQUIRE_DATA, + hw_mgr_res->hw_res[i], + sizeof(void *)); + if (rc) + CAM_ERR(CAM_ISP, + "csid acquire data dump failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } } + + event_info.res_id = res_id; + res_id_out = res_id & 0xFF; + + if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid out resource id :%x", + res_id); + return; + } + + hw_mgr_res = &ctx->res_list_ife_out[res_id_out]; + 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_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)&event_info, + sizeof(struct cam_isp_hw_event_info)); + } + } +} + +static void cam_ife_mgr_dump_pf_data( + struct cam_ife_hw_mgr *hw_mgr, + struct cam_hw_cmd_args *hw_cmd_args) +{ + struct cam_ife_hw_mgr_ctx *ctx; + + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_get_cmd_update cmd_update; + struct cam_isp_hw_get_res_for_mid get_res; + struct cam_packet *packet; + uint32_t hw_id; + uint32_t *resource_type; + bool *ctx_found, hw_id_found = false; + int i, j, rc = 0; + + ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map; + + packet = hw_cmd_args->u.pf_args.pf_data.packet; + ctx_found = hw_cmd_args->u.pf_args.ctx_found; + resource_type = hw_cmd_args->u.pf_args.resource_type; + + if ((*ctx_found) && (*resource_type)) + goto outportlog; + + if (ctx->pf_mid_found) + goto outportlog; + + if (!g_ife_hw_mgr.hw_pid_support) + goto mid_check; + + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + if (!hw_mgr->ife_devices[i]) + continue; + + for (j = 0; j < g_ife_hw_mgr.ife_devices[i]->num_hw_pid; j++) { + if (g_ife_hw_mgr.ife_devices[i]->hw_pid[j] == + hw_cmd_args->u.pf_args.pid) { + hw_id_found = true; + hw_id = i; + break; + } + } + if (hw_id_found) + break; + } + + if (i == CAM_IFE_HW_NUM_MAX) { + CAM_INFO(CAM_ISP, + "PID:%d is not matching with any IFE HW PIDs ctx id:%d", + hw_cmd_args->u.pf_args.pid, ctx->ctx_index); + return; + } + + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == hw_id) { + *ctx_found = true; + break; + } + } + + if (!(*ctx_found)) { + CAM_INFO(CAM_ISP, + "This context does not cause pf:pid:%d hw id:%d ctx_id:%d", + hw_cmd_args->u.pf_args.pid, hw_id, ctx->ctx_index); + return; + } + +mid_check: + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + hw_mgr_res = &ctx->res_list_ife_out[i]; + if (!hw_mgr_res->hw_res[0]) + continue; + + break; + } + + if (i >= CAM_IFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, + "NO valid outport resources ctx id:%d req id:%lld", + ctx->ctx_index, packet->header.request_id); + return; + } + + get_res.mid = hw_cmd_args->u.pf_args.mid; + cmd_update.res = hw_mgr_res->hw_res[0]; + cmd_update.cmd_type = CAM_ISP_HW_CMD_GET_RES_FOR_MID; + cmd_update.data = (void *) &get_res; + + /* get resource id for given mid */ + rc = hw_mgr_res->hw_res[0]->hw_intf->hw_ops.process_cmd( + hw_mgr_res->hw_res[0]->hw_intf->hw_priv, + cmd_update.cmd_type, &cmd_update, + sizeof(struct cam_isp_hw_get_cmd_update)); + + if (rc) { + CAM_ERR(CAM_ISP, + "getting mid port resource id failed ctx id:%d req id:%lld", + ctx->ctx_index, packet->header.request_id); + return; + } + + CAM_ERR(CAM_ISP, + "Page fault on resource id:(0x%x) ctx id:%d req id:%lld", + get_res.out_res_id, ctx->ctx_index, packet->header.request_id); + *resource_type = get_res.out_res_id; + ctx->pf_mid_found = true; + + cam_ife_mgr_pf_dump(get_res.out_res_id, ctx); + +outportlog: + cam_ife_mgr_print_io_bufs(hw_mgr, *resource_type, packet, + ctx_found, ctx); + } static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) @@ -6567,12 +6749,8 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) } break; case CAM_HW_MGR_CMD_DUMP_PF_INFO: - cam_ife_mgr_print_io_bufs( - hw_cmd_args->u.pf_args.pf_data.packet, - hw_mgr->mgr_common.img_iommu_hdl, - hw_mgr->mgr_common.img_iommu_hdl_secure, - hw_cmd_args->u.pf_args.buf_info, - hw_cmd_args->u.pf_args.mem_found); + cam_ife_mgr_dump_pf_data(hw_mgr, hw_cmd_args); + break; case CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH: if (ctx->last_dump_flush_req_id == ctx->applied_req_id) @@ -7548,9 +7726,9 @@ static int cam_ife_hw_mgr_sort_dev_with_caps( for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (!ife_hw_mgr->ife_devices[i]) continue; - if (ife_hw_mgr->ife_devices[i]->hw_ops.get_hw_caps) { - ife_hw_mgr->ife_devices[i]->hw_ops.get_hw_caps( - ife_hw_mgr->ife_devices[i]->hw_priv, + if (ife_hw_mgr->ife_devices[i]->hw_intf->hw_ops.get_hw_caps) { + ife_hw_mgr->ife_devices[i]->hw_intf->hw_ops.get_hw_caps( + ife_hw_mgr->ife_devices[i]->hw_intf->hw_priv, &ife_hw_mgr->ife_dev_caps[i], sizeof(ife_hw_mgr->ife_dev_caps[i])); } @@ -7671,7 +7849,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) rc = cam_vfe_hw_init(&g_ife_hw_mgr.ife_devices[i], i); if (!rc) { struct cam_hw_intf *ife_device = - g_ife_hw_mgr.ife_devices[i]; + g_ife_hw_mgr.ife_devices[i]->hw_intf; struct cam_hw_info *vfe_hw = (struct cam_hw_info *) ife_device->hw_priv; @@ -7690,6 +7868,10 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) "reg_map: mem base = %pK cam_base = 0x%llx", (void __iomem *)soc_info->reg_map[0].mem_base, (uint64_t) soc_info->reg_map[0].mem_cam_base); + + if (g_ife_hw_mgr.ife_devices[i]->num_hw_pid) + g_ife_hw_mgr.hw_pid_support = true; + } else { g_ife_hw_mgr.cdm_reg_map[i] = NULL; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 15adc1713c74..010c7dda16a1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -99,6 +99,7 @@ struct cam_ife_hw_mgr_debug { * @dsp_enabled Indicate whether dsp is enabled in this context * @hw_enabled Array to indicate active HW * @internal_cdm Indicate whether context uses internal CDM + * @pf_mid_found in page fault, mid found for this ctx. */ struct cam_ife_hw_mgr_ctx { struct list_head list; @@ -154,6 +155,7 @@ struct cam_ife_hw_mgr_ctx { bool is_offline; bool dsp_enabled; bool internal_cdm; + bool pf_mid_found; }; /** @@ -172,13 +174,15 @@ struct cam_ife_hw_mgr_ctx { * @ife_dev_caps ife device capability per core * @work q work queue for IFE hw manager * @debug_cfg debug configuration + * @ctx_lock context lock * @support_consumed_addr indicate whether hw supports last consumed address + * @hw_pid_support hw pid support for this target */ struct cam_ife_hw_mgr { struct cam_isp_hw_mgr mgr_common; struct cam_hw_intf *tpg_devices[CAM_TOP_TPG_HW_NUM_MAX]; struct cam_hw_intf *csid_devices[CAM_IFE_CSID_HW_NUM_MAX]; - struct cam_hw_intf *ife_devices[CAM_IFE_HW_NUM_MAX]; + struct cam_isp_hw_intf_data *ife_devices[CAM_IFE_HW_NUM_MAX]; struct cam_soc_reg_map *cdm_reg_map[CAM_IFE_HW_NUM_MAX]; struct mutex ctx_mutex; @@ -194,6 +198,7 @@ struct cam_ife_hw_mgr { struct cam_ife_hw_mgr_debug debug_cfg; spinlock_t ctx_lock; bool support_consumed_addr; + bool hw_pid_support; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index dd85eb45d4ab..1ec669eca3f3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4118,6 +4118,55 @@ static int cam_ife_csid_dump_hw( return 0; } +static int cam_ife_csid_log_acquire_data( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_isp_resource_node *res = + (struct cam_isp_resource_node *)cmd_args; + struct cam_ife_csid_path_cfg *path_data; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_reg_offset *csid_reg; + const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + uint32_t byte_cnt_ping, byte_cnt_pong; + + path_data = (struct cam_ife_csid_path_cfg *)res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d invalid res id:%d res type: %d state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_type, + res->res_state); + return -EINVAL; + } + + /* Dump all the acquire data for this hardware */ + CAM_INFO(CAM_ISP, + "CSID:%d res id:%d type:%d state:%d in f:%d out f:%d st pix:%d end pix:%d st line:%d end line:%d h bin:%d qcfa bin:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_type, + res->res_type, path_data->in_format, path_data->out_format, + path_data->start_pixel, path_data->end_pixel, + path_data->start_line, path_data->end_line, + path_data->horizontal_bin, path_data->qcfa_bin); + + if (res->res_id >= CAM_IFE_PIX_PATH_RES_RDI_0 && + res->res_id <= CAM_IFE_PIX_PATH_RES_RDI_3) { + rdi_reg = csid_reg->rdi_reg[res->res_id]; + /* read total number of bytes transmitted through RDI */ + byte_cnt_ping = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_byte_cntr_ping_addr); + byte_cnt_pong = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_byte_cntr_pong_addr); + CAM_INFO(CAM_ISP, + "CSID:%d res id:%d byte cnt val ping:%d pong:%d", + csid_hw->hw_intf->hw_idx, res->res_id, + byte_cnt_ping, byte_cnt_pong); + } + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -4164,6 +4213,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG: rc = cam_ife_csid_set_sensor_dimension(csid_hw, cmd_args); break; + case CAM_IFE_CSID_LOG_ACQUIRE_DATA: + rc = cam_ife_csid_log_acquire_data(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index a399d2fdc479..bd866c6202f3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -212,6 +212,7 @@ enum cam_ife_csid_cmd_type { CAM_IFE_CSID_SOF_IRQ_DEBUG, CAM_IFE_CSID_SET_CONFIG, CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, + CAM_IFE_CSID_LOG_ACQUIRE_DATA, CAM_IFE_CSID_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 9181fdc2eb40..03e76b627d8b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -15,6 +15,8 @@ /* Maximum length of tag while dumping */ #define CAM_ISP_HW_DUMP_TAG_MAX_LEN 32 +/* Max isp hw pid values number */ +#define CAM_ISP_HW_MAX_PID_VAL 4 /* * struct cam_isp_timestamp: * @@ -121,6 +123,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_FE_TRIGGER_CMD, CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + CAM_ISP_HW_CMD_GET_RES_FOR_MID, CAM_ISP_HW_CMD_MAX, }; @@ -233,6 +236,20 @@ struct cam_isp_hw_get_wm_update { struct cam_buf_io_cfg *io_cfg; }; +/* + * struct cam_isp_hw_get_res_for_mid: + * + * @Brief: Get the out resource id for given mid + * + * @mid: Mid number of hw outport numb + * @out_res_id: Out resource id + * + */ +struct cam_isp_hw_get_res_for_mid { + uint32_t mid; + uint32_t out_res_id; +}; + /* * struct cam_isp_hw_get_cmd_update: * @@ -308,4 +325,19 @@ struct cam_isp_hw_dump_header { uint32_t word_size; }; +/** + * struct cam_isp_hw_intf_data - ISP hw intf data + * + * @Brief: isp hw intf pointer and pid list data + * + * @isp_hw_intf: Isp hw intf pointer + * @num_hw_pid: Number of pids for this hw + * @isp_hw_pid: Isp hw pid values + * + */ +struct cam_isp_hw_intf_data { + struct cam_hw_intf *hw_intf; + uint32_t num_hw_pid; + uint32_t hw_pid[CAM_ISP_HW_MAX_PID_VAL]; +}; #endif /* _CAM_ISP_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index adb33444cf8c..bd2c808bf150 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -389,7 +389,8 @@ struct cam_vfe_generic_ubwc_config { * successful initialization * @hw_idx: Index of VFE HW */ -int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx); +int cam_vfe_hw_init(struct cam_isp_hw_intf_data **vfe_hw, + uint32_t hw_idx); /* * cam_vfe_put_evt_payload() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 8eaca71f1e38..158190296478 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -616,6 +616,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c index 1dfa48cbfbf4..4be7e8e8de13 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c @@ -14,8 +14,7 @@ #include "cam_vfe_soc.h" #include "cam_debug_util.h" -static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX]; - +static struct cam_isp_hw_intf_data cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX]; static char vfe_dev_name[8]; static int cam_vfe_component_bind(struct device *dev, @@ -28,6 +27,8 @@ static int cam_vfe_component_bind(struct device *dev, struct cam_vfe_hw_info *hw_info = NULL; int rc = 0; struct platform_device *pdev = to_platform_device(dev); + struct cam_vfe_soc_private *vfe_soc_priv; + uint32_t i; vfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!vfe_hw_intf) { @@ -109,7 +110,13 @@ static int cam_vfe_component_bind(struct device *dev, init_completion(&vfe_hw->hw_complete); if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) - cam_vfe_hw_list[vfe_hw_intf->hw_idx] = vfe_hw_intf; + cam_vfe_hw_list[vfe_hw_intf->hw_idx].hw_intf = vfe_hw_intf; + + vfe_soc_priv = vfe_hw->soc_info.soc_private; + cam_vfe_hw_list[vfe_hw_intf->hw_idx].num_hw_pid = vfe_soc_priv->num_pid; + for (i = 0; i < vfe_soc_priv->num_pid; i++) + cam_vfe_hw_list[vfe_hw_intf->hw_idx].hw_pid[i] = + vfe_soc_priv->pid[i]; cam_vfe_init_hw(vfe_hw, NULL, 0); cam_vfe_deinit_hw(vfe_hw, NULL, 0); @@ -150,7 +157,7 @@ static void cam_vfe_component_unbind(struct device *dev, vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx); if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX) - cam_vfe_hw_list[vfe_hw_intf->hw_idx] = NULL; + cam_vfe_hw_list[vfe_hw_intf->hw_idx].hw_intf = NULL; vfe_hw = vfe_hw_intf->hw_priv; if (!vfe_hw) { @@ -207,15 +214,17 @@ int cam_vfe_remove(struct platform_device *pdev) return 0; } -int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx) +int cam_vfe_hw_init(struct cam_isp_hw_intf_data **vfe_hw_intf, + uint32_t hw_idx) { int rc = 0; - if (cam_vfe_hw_list[hw_idx]) { - *vfe_hw = cam_vfe_hw_list[hw_idx]; + if (cam_vfe_hw_list[hw_idx].hw_intf) { + *vfe_hw_intf = &cam_vfe_hw_list[hw_idx]; rc = 0; } else { - *vfe_hw = NULL; + CAM_ERR(CAM_ISP, "inval param"); + *vfe_hw_intf = NULL; rc = -ENODEV; } return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 61b7efe5bfa3..6b1bb46b94ee 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -36,7 +36,7 @@ static bool cam_vfe_cpas_cb(uint32_t client_handle, void *userdata, static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) { - int rc = 0, num_ubwc_cfg = 0, i = 0; + int rc = 0, num_ubwc_cfg = 0, i = 0, num_pid = 0; struct device_node *of_node = NULL; struct platform_device *pdev = NULL; struct cam_vfe_soc_private *vfe_soc_private; @@ -55,7 +55,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) if (strnstr(soc_info->compatible, "lite", strlen(soc_info->compatible)) != NULL) { vfe_soc_private->is_ife_lite = true; - goto end; + goto pid; } switch (soc_info->hw_version) { @@ -69,7 +69,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) CAM_ERR(CAM_ISP, "wrong num_ubwc_cfg: %d", num_ubwc_cfg); rc = num_ubwc_cfg; - goto end; + goto pid; } for (i = 0; i < num_ubwc_cfg; i++) { @@ -86,8 +86,24 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) default: break; } +pid: + /* set some default values */ + vfe_soc_private->num_pid = 0; + + num_pid = of_property_count_u32_elems(pdev->dev.of_node, "cam_hw_pid"); + CAM_DBG(CAM_CPAS, "vfe:%d pid count %d", soc_info->index, num_pid); + + if (num_pid <= 0 || num_pid > CAM_ISP_HW_MAX_PID_VAL) + goto end; + + for (i = 0; i < num_pid; i++) + of_property_read_u32_index(pdev->dev.of_node, "cam_hw_pid", i, + &vfe_soc_private->pid[i]); + + vfe_soc_private->num_pid = num_pid; end: + return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h index eef02079628a..cb76b8479004 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h @@ -25,6 +25,8 @@ * @ubwc_static_ctrl: UBWC static control configuration * @is_ife_lite: Flag to indicate full vs lite IFE * @ife_clk_src: IFE source clock + * @num_pid: Number of pids of ife + * @pid: IFE pid values list */ struct cam_vfe_soc_private { uint32_t cpas_handle; @@ -35,6 +37,8 @@ struct cam_vfe_soc_private { uint32_t ubwc_static_ctrl[UBWC_STATIC_CONFIG_MAX]; bool is_ife_lite; uint64_t ife_clk_src; + uint32_t num_pid; + uint32_t pid[CAM_ISP_HW_MAX_PID_VAL]; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index bda439a4c959..bd0390e04aa5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1176,60 +1176,77 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .mid[0] = 8, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_4, + .mid[0] = 9, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_5, + .mid[0] = 10, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL, .max_width = 4096, .max_height = 4096, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 32, + .mid[1] = 33, + .mid[2] = 34, + .mid[3] = 35, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 16, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 17, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 11, + .mid[1] = 12, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FD, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 20, + .mid[1] = 21, + .mid[2] = 22, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_PDAF, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 25, + .mid[1] = 26, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 40, }, { .vfe_out_type = @@ -1237,6 +1254,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 41, }, { .vfe_out_type = @@ -1244,72 +1262,88 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 42, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 43, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 44, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 45, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 46, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 47, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 48, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, .max_width = 4096, .max_height = 4096, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 36, + .mid[1] = 37, + .mid[2] = 38, + .mid[3] = 39, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 18, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 19, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD, .max_width = 1920, .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .mid[0] = 23, + .mid[1] = 24, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LCR, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .mid[0] = 27, }, }, .comp_done_shift = 6, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 730af4c945c2..5478bb021dc8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -373,24 +373,28 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .mid[0] = 16, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .mid[0] = 17, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .mid[0] = 18, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, .max_width = -1, .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .mid[0] = 19, }, }, .comp_done_shift = 4, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index a5bb5b86213b..69a69817b528 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -180,6 +180,7 @@ struct cam_vfe_bus_ver2_vfe_out_data { struct cam_cdm_utils_ops *cdm_util_ops; uint32_t secure_mode; void *priv; + uint32_t mid[CAM_VFE_BUS_VER2_MAX_MID_PER_PORT]; }; struct cam_vfe_bus_ver2_priv { @@ -2431,7 +2432,7 @@ static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, { struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; - int rc = 0; + int rc = 0, i; int32_t vfe_out_type = ver2_hw_info->vfe_out_hw_info[index].vfe_out_type; @@ -2481,6 +2482,9 @@ static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf; vfe_out->irq_handle = 0; + for (i = 0; i < CAM_VFE_BUS_VER2_MAX_MID_PER_PORT; i++) + rsrc_data->mid[i] = ver2_hw_info->vfe_out_hw_info[index].mid[i]; + return 0; } @@ -3576,6 +3580,50 @@ int cam_vfe_bus_dump_wm_data(void *priv, void *cmd_args, uint32_t arg_size) return 0; } +static int cam_vfe_bus_get_res_for_mid( + struct cam_vfe_bus_ver2_priv *bus_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_vfe_out_data *out_data = NULL; + struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; + struct cam_isp_hw_get_res_for_mid *get_res = NULL; + int i, j; + + get_res = (struct cam_isp_hw_get_res_for_mid *)cmd_update->data; + if (!get_res) { + CAM_ERR(CAM_ISP, + "invalid get resource for mid paramas"); + return -EINVAL; + } + + for (i = 0; i < bus_priv->num_out; i++) { + out_data = (struct cam_vfe_bus_ver2_vfe_out_data *) + bus_priv->vfe_out[i].res_priv; + + if (!out_data) + continue; + + for (j = 0; j < CAM_VFE_BUS_VER2_MAX_MID_PER_PORT; j++) { + if (out_data->mid[j] == get_res->mid) + goto end; + } + } + + if (i == bus_priv->num_out) { + CAM_ERR(CAM_ISP, + "mid:%d does not match with any out resource", + get_res->mid); + get_res->out_res_id = 0; + return -EINVAL; + } + +end: + CAM_INFO(CAM_ISP, "match mid :%d out resource:0x%x found", + get_res->mid, bus_priv->vfe_out[i].res_id); + get_res->out_res_id = bus_priv->vfe_out[i].res_id; + return 0; +} + static int cam_vfe_bus_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -3636,6 +3684,10 @@ static int cam_vfe_bus_process_cmd( *support_consumed_addr = bus_priv->common_data.support_consumed_addr; break; + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index cfb8dda17d9f..a9d4168c9086 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -10,6 +10,7 @@ #include "cam_vfe_bus.h" #define CAM_VFE_BUS_VER2_MAX_CLIENTS 24 +#define CAM_VFE_BUS_VER2_MAX_MID_PER_PORT 4 enum cam_vfe_bus_ver2_vfe_core_id { CAM_VFE_BUS_VER2_VFE_CORE_0, @@ -167,6 +168,7 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info { enum cam_vfe_bus_ver2_vfe_out_type vfe_out_type; uint32_t max_width; uint32_t max_height; + uint32_t mid[CAM_VFE_BUS_VER2_MAX_MID_PER_PORT]; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 727febe397ba..3e8ddb7385ff 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -177,6 +177,7 @@ struct cam_vfe_bus_ver3_vfe_out_data { struct cam_cdm_utils_ops *cdm_util_ops; uint32_t secure_mode; void *priv; + uint32_t mid[CAM_VFE_BUS_VER3_MAX_MID_PER_PORT]; }; struct cam_vfe_bus_ver3_priv { @@ -2641,7 +2642,7 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, { struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; - int rc = 0; + int rc = 0, i; int32_t vfe_out_type = ver3_hw_info->vfe_out_hw_info[index].vfe_out_type; @@ -2694,6 +2695,10 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, vfe_out->hw_intf = ver3_bus_priv->common_data.hw_intf; vfe_out->irq_handle = 0; + for (i = 0; i < CAM_VFE_BUS_VER3_MAX_MID_PER_PORT; i++) + rsrc_data->mid[i] = ver3_hw_info->vfe_out_hw_info[index].mid[i]; + + return 0; } @@ -2735,7 +2740,9 @@ static int cam_vfe_bus_ver3_print_dimensions( struct cam_isp_resource_node *rsrc_node = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_vfe_bus_ver3_common_data *common_data = NULL; int i, wm_idx; + uint32_t addr_status0, addr_status1, addr_status2, addr_status3; rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; @@ -2748,6 +2755,16 @@ static int cam_vfe_bus_ver3_print_dimensions( return -EINVAL; } wm_data = bus_priv->bus_client[wm_idx].res_priv; + common_data = rsrc_data->common_data; + addr_status0 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_0); + addr_status1 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_1); + addr_status2 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_2); + addr_status3 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_3); + CAM_INFO(CAM_ISP, "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", wm_data->common_data->core_index, wm_idx, @@ -2757,6 +2774,14 @@ static int cam_vfe_bus_ver3_print_dimensions( wm_data->en_cfg, wm_data->acquired_width, wm_data->acquired_height); + CAM_INFO(CAM_ISP, + "hw:%d WM:%d last consumed address:0x%x last frame addr:0x%x fifo cnt:0x%x current client address:0x%x", + common_data->hw_intf->hw_idx, + wm_data->index, + addr_status0, + addr_status1, + addr_status2, + addr_status3); } return 0; } @@ -3689,6 +3714,50 @@ static int cam_vfe_bus_ver3_deinit_hw(void *hw_priv, return rc; } +static int cam_vfe_bus_get_res_for_mid( + struct cam_vfe_bus_ver3_priv *bus_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_vfe_out_data *out_data = NULL; + struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; + struct cam_isp_hw_get_res_for_mid *get_res = NULL; + int i, j; + + get_res = (struct cam_isp_hw_get_res_for_mid *)cmd_update->data; + if (!get_res) { + CAM_ERR(CAM_ISP, + "invalid get resource for mid paramas"); + return -EINVAL; + } + + for (i = 0; i < bus_priv->num_out; i++) { + out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + bus_priv->vfe_out[i].res_priv; + + if (!out_data) + continue; + + for (j = 0; j < CAM_VFE_BUS_VER3_MAX_MID_PER_PORT; j++) { + if (out_data->mid[j] == get_res->mid) + goto end; + } + } + + if (i == bus_priv->num_out) { + CAM_ERR(CAM_ISP, + "mid:%d does not match with any out resource", + get_res->mid); + get_res->out_res_id = 0; + return -EINVAL; + } + +end: + CAM_INFO(CAM_ISP, "match mid :%d out resource:0x%x found", + get_res->mid, bus_priv->vfe_out[i].res_id); + get_res->out_res_id = bus_priv->vfe_out[i].res_id; + return 0; +} + static int __cam_vfe_bus_ver3_process_cmd(void *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -3766,6 +3835,10 @@ static int cam_vfe_bus_ver3_process_cmd( *support_consumed_addr = bus_priv->common_data.support_consumed_addr; break; + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index 7b39c97f4510..e713b26f6de7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -12,6 +12,7 @@ #define CAM_VFE_BUS_VER3_MAX_CLIENTS 26 #define CAM_VFE_BUS_VER3_MAX_SUB_GRPS 6 +#define CAM_VFE_BUS_VER3_MAX_MID_PER_PORT 4 enum cam_vfe_bus_ver3_vfe_core_id { CAM_VFE_BUS_VER3_VFE_CORE_0, @@ -160,6 +161,7 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { uint32_t max_width; uint32_t max_height; uint32_t source_group; + uint32_t mid[CAM_VFE_BUS_VER3_MAX_MID_PER_PORT]; }; /* diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index b28f8b667239..511da77d34b3 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -16,17 +16,18 @@ static const char jpeg_dev_name[] = "cam-jpeg"; -static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_jpeg_context_dump_active_request(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + uint32_t resource_type = 0; int rc = 0; int closest_port; - bool b_mem_found = false; + bool b_mem_found = false, b_ctx_found = false; if (!ctx) { @@ -44,7 +45,7 @@ static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &b_mem_found); + &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_JPEG, "Failed to dump pf info"); diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 76a055b89149..f627e8850de9 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -22,22 +22,20 @@ static struct cam_jpeg_dev g_jpeg_dev; static void cam_jpeg_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) + struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { - CAM_ERR(CAM_JPEG, "invalid token in page handler cb"); + if (!pf_info || !pf_info->token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static const struct of_device_id cam_jpeg_dt_match[] = { diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index 0ff45243edd3..1c6b940f9b2b 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -23,15 +23,16 @@ static const char ope_dev_name[] = "cam-ope"; -static int cam_ope_context_dump_active_request(void *data, unsigned long iova, - uint32_t buf_info) +static int cam_ope_context_dump_active_request(void *data, + struct cam_smmu_pf_info *pf_info) { struct cam_context *ctx = (struct cam_context *)data; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp = NULL; struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + uint32_t resource_type = 0; int rc = 0; - bool b_mem_found = false; + bool b_mem_found = false, b_ctx_found = false; if (!ctx) { CAM_ERR(CAM_OPE, "Invalid ctx"); @@ -54,7 +55,7 @@ static int cam_ope_context_dump_active_request(void *data, unsigned long iova, CAM_INFO(CAM_OPE, "req_id : %lld", req->request_id); rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, - iova, buf_info, &b_mem_found); + &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_OPE, "Failed to dump pf info"); diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index 3ac839a47407..df9de9993a3e 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -46,22 +46,20 @@ struct cam_ope_subdev { static struct cam_ope_subdev g_ope_dev; static void cam_ope_dev_iommu_fault_handler( - struct iommu_domain *domain, struct device *dev, unsigned long iova, - int flags, void *token, uint32_t buf_info) + struct cam_smmu_pf_info *pf_info) { int i = 0; struct cam_node *node = NULL; - if (!token) { - CAM_ERR(CAM_OPE, "invalid token in page handler cb"); + if (!pf_info || !pf_info->token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); return; } - node = (struct cam_node *)token; + node = (struct cam_node *)pf_info->token; for (i = 0; i < node->ctx_size; i++) - cam_context_dump_pf_info(&(node->ctx_list[i]), iova, - buf_info); + cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } static int cam_ope_subdev_open(struct v4l2_subdev *sd, diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 7376c2964f83..4e6ee1b10d4f 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -47,7 +47,7 @@ div_u64_rem(atomic64_add_return(1, head),\ CAM_SMMU_MONITOR_MAX_ENTRIES, (ret)) -static int g_num_pf_handled = 4; +static int g_num_pf_handled = 1; module_param(g_num_pf_handled, int, 0644); struct cam_fw_alloc_info icp_fw; @@ -145,7 +145,7 @@ struct cam_context_bank_info { int handle; enum cam_smmu_ops_param state; - cam_smmu_client_page_fault_handler handler[CAM_SMMU_CB_MAX]; + void (*handler[CAM_SMMU_CB_MAX]) (struct cam_smmu_pf_info *pf_info); void *token[CAM_SMMU_CB_MAX]; int cb_count; int secure_count; @@ -363,6 +363,8 @@ static void cam_smmu_page_fault_work(struct work_struct *work) int idx; struct cam_smmu_work_payload *payload; uint32_t buf_info; + struct iommu_fault_ids fault_ids = {0, 0, 0}; + struct cam_smmu_pf_info pf_info; mutex_lock(&iommu_cb_set.payload_list_lock); if (list_empty(&iommu_cb_set.payload_list)) { @@ -377,21 +379,33 @@ static void cam_smmu_page_fault_work(struct work_struct *work) list_del(&payload->list); mutex_unlock(&iommu_cb_set.payload_list_lock); + + if ((iommu_get_fault_ids(payload->domain, &fault_ids))) + CAM_ERR(CAM_SMMU, + "Error: Can not get smmu fault ids"); + + CAM_ERR(CAM_SMMU, "smmu fault ids bid:%d pid:%d mid:%d", + fault_ids.bid, fault_ids.pid, fault_ids.mid); + /* Dereference the payload to call the handler */ idx = payload->idx; buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova); if (buf_info != 0) CAM_INFO(CAM_SMMU, "closest buf 0x%x idx %d", buf_info, idx); + pf_info.domain = payload->domain; + pf_info.dev = payload->dev; + pf_info.iova = payload->iova; + pf_info.flags = payload->flags; + pf_info.buf_info = buf_info; + pf_info.bid = fault_ids.bid; + pf_info.pid = fault_ids.pid; + pf_info.mid = fault_ids.mid; + for (j = 0; j < CAM_SMMU_CB_MAX; j++) { if ((iommu_cb_set.cb_info[idx].handler[j])) { - iommu_cb_set.cb_info[idx].handler[j]( - payload->domain, - payload->dev, - payload->iova, - payload->flags, - iommu_cb_set.cb_info[idx].token[j], - buf_info); + pf_info.token = iommu_cb_set.cb_info[idx].token[j]; + iommu_cb_set.cb_info[idx].handler[j](&pf_info); } } cam_smmu_dump_cb_info(idx); @@ -565,7 +579,7 @@ end: } void cam_smmu_set_client_page_fault_handler(int handle, - cam_smmu_client_page_fault_handler handler_cb, void *token) + void (*handler_cb)(struct cam_smmu_pf_info *pf_info), void *token) { int idx, i = 0; @@ -726,6 +740,15 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, return -EINVAL; } +void cam_smmu_reset_cb_page_fault_cnt(void) +{ + int idx; + + for (idx = 0; idx < iommu_cb_set.cb_num; idx++) + iommu_cb_set.cb_info[idx].pf_count = 0; + +} + static int cam_smmu_translate_dir_to_iommu_dir( enum cam_smmu_map_dir dir) { diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index 19d96e4e242b..df1cbdf58f8f 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -43,8 +43,7 @@ enum cam_smmu_region_id { }; /** - * @brief : Callback function type that gets called back on cam - * smmu page fault. + * @brief : cam_smmu_pf_info * * @param domain : Iommu domain received in iommu page fault handler * @param dev : Device received in iommu page fault handler @@ -52,10 +51,22 @@ enum cam_smmu_region_id { * @param flags : Flags received in iommu page fault handler * @param token : Userdata given during callback registration * @param buf_info : Closest mapped buffer info + * @bid : bus id + * @pid : unique id for hw group of ports + * @mid : port id of hw */ -typedef void (*cam_smmu_client_page_fault_handler)(struct iommu_domain *domain, - struct device *dev, unsigned long iova, int flags, void *token, - uint32_t buf_info); + +struct cam_smmu_pf_info { + struct iommu_domain *domain; + struct device *dev; + unsigned long iova; + int flags; + void *token; + uint32_t buf_info; + uint32_t bid; + uint32_t pid; + uint32_t mid; +}; /** * @brief : Structure to store region information @@ -234,7 +245,7 @@ int cam_smmu_find_index_by_handle(int hdl); * @param token: It is input param when trigger page fault handler */ void cam_smmu_set_client_page_fault_handler(int handle, - cam_smmu_client_page_fault_handler handler_cb, void *token); + void (*handler_cb)(struct cam_smmu_pf_info *pf_info), void *token); /** * @brief : Unregisters smmu fault handler for client @@ -403,6 +414,13 @@ int cam_smmu_get_io_region_info(int32_t smmu_hdl, dma_addr_t *iova, size_t *len, dma_addr_t *discard_iova_start, size_t *discard_iova_len); +/** + * @brief : API to reset the call context bank page fault count + * This should be done on the starting of new camera open + * @return void. + */ +void cam_smmu_reset_cb_page_fault_cnt(void); + /** * @brief : API to register SMMU hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. @@ -413,4 +431,5 @@ int cam_smmu_init_module(void); * @brief : API to remove SMMU Hw from platform framework. */ void cam_smmu_exit_module(void); + #endif /* _CAM_SMMU_API_H_ */ diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 58071bc3419e..dfa698bd195a 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -424,6 +424,7 @@ struct cam_mem_cache_ops_cmd { * @CAM_REQ_MGR_ERROR_TYPE_BUFFER: Buffer was not filled, not fatal * @CAM_REQ_MGR_ERROR_TYPE_RECOVERY: Fatal error, can be recovered * @CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE: SOF freeze, can be recovered + * @CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT: page fault, can be recovered */ #define CAM_REQ_MGR_ERROR_TYPE_DEVICE 0 #define CAM_REQ_MGR_ERROR_TYPE_REQUEST 1 @@ -431,7 +432,7 @@ struct cam_mem_cache_ops_cmd { #define CAM_REQ_MGR_ERROR_TYPE_RECOVERY 3 #define CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE 4 #define CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY 5 - +#define CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT 6 /** * struct cam_req_mgr_error_msg From dc5342fbf36e714680bb36aefce1335851a54f3c Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 13 Aug 2020 15:25:59 -0700 Subject: [PATCH 461/790] msm: camera: cpas: Update QoS settings for custom usecase Update QoS settings for devices with custom hw. CRs-Fixed: 2755917 Change-Id: Idb62f79a7a9b82d63a253343979c93dc98845501 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cpas_top/cpastop_v580_custom.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h index 4b97ee206ed2..cbb80b5fbeed 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h @@ -331,7 +331,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ - .value = 0x3, + .value = 0x2, }, .danger_lut = { .enable = true, @@ -362,7 +362,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -388,7 +388,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ - .value = 0x000F, + .value = 0x0000, }, .ubwc_ctl = { /* @@ -407,7 +407,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7430, /* IFE_RDI_WR_1_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -433,7 +433,7 @@ static struct cam_camnoc_specific .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7448, /* IFE_RDI_WR_1_SAFELUT_LOW */ - .value = 0x000F, + .value = 0x0000, }, .ubwc_ctl = { /* From 018cb6845f81891ed49061653b4a033663f5c0ca Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 17 Mar 2020 18:30:01 -0700 Subject: [PATCH 462/790] msm: camera: smmu: Remove extra shared mem map Cleans up extra mapping used to get the scatter list entries. CRs-Fixed: 2702021 Change-Id: I787159169e3b3d1259e41e51c0534bd68bcbb326 Signed-off-by: Karthik Anantha Ram Signed-off-by: Karthik Jayakumar --- drivers/cam_smmu/cam_smmu_api.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 7376c2964f83..ad6f9a2a774e 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -1933,7 +1933,7 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, } else { CAM_ERR(CAM_SMMU, "Error: Wrong region id passed"); rc = -EINVAL; - goto err_unmap_sg; + goto err_detach; } CAM_DBG(CAM_SMMU, @@ -1989,6 +1989,10 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, idx, buf, (void *)iommu_cb_set.cb_info[idx].dev, (void *)*paddr_ptr, (unsigned int)*len_ptr); + /* Unmap the mapping in dma region as this is not used anyway */ + if (region_id == CAM_SMMU_REGION_SHARED) + dma_buf_unmap_attachment(attach, table, dma_dir); + return 0; err_alloc: @@ -2135,14 +2139,16 @@ static int cam_smmu_unmap_buf_and_remove_from_list( iommu_cb_set.cb_info[idx].shared_mapping_size -= mapping_info->len; } else if (mapping_info->region_id == CAM_SMMU_REGION_IO) { + if (mapping_info->is_internal) + mapping_info->attach->dma_map_attrs |= + DMA_ATTR_SKIP_CPU_SYNC; + + dma_buf_unmap_attachment(mapping_info->attach, + mapping_info->table, mapping_info->dir); iommu_cb_set.cb_info[idx].io_mapping_size -= mapping_info->len; } - if (mapping_info->is_internal) - mapping_info->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; - dma_buf_unmap_attachment(mapping_info->attach, - mapping_info->table, mapping_info->dir); dma_buf_detach(mapping_info->buf, mapping_info->attach); dma_buf_put(mapping_info->buf); From 23fc6a670cc5d491c4780e35247e3823da11071b Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Mon, 25 May 2020 19:25:02 +0530 Subject: [PATCH 463/790] msm: camera: common: Define debugflag to allocate usecase info Define debug flag to allocate usecase info for debug purpose. This flag can be used to get usecase buffer index at issue time. CRs-Fixed: 2707314 Change-Id: Iffacdb48f77ec6907b8070d4c19eb1c56be30f14 Signed-off-by: Alok Chauhan --- drivers/cam_req_mgr/cam_mem_mgr.c | 4 ++++ drivers/cam_req_mgr/cam_mem_mgr.h | 2 ++ include/uapi/camera/media/cam_req_mgr.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 650bfa0ab216..d6d5fcc8e7e3 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -733,6 +733,9 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) } } + if (cmd->flags & CAM_MEM_FLAG_KMD_DEBUG_FLAG) + tbl.dbg_buf_idx = idx; + tbl.bufq[idx].kmdvaddr = kvaddr; tbl.bufq[idx].vaddr = hw_vaddr; tbl.bufq[idx].dma_buf = dmabuf; @@ -1023,6 +1026,7 @@ void cam_mem_mgr_deinit(void) bitmap_zero(tbl.bitmap, tbl.bits); kfree(tbl.bitmap); tbl.bitmap = NULL; + tbl.dbg_buf_idx = -1; mutex_unlock(&tbl.m_lock); mutex_destroy(&tbl.m_lock); } diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index 69637ba1dc8e..b87119067b9a 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -71,6 +71,7 @@ struct cam_mem_buf_queue { * @bufq: array of buffers * @dentry: Debugfs entry * @alloc_profile_enable: Whether to enable alloc profiling + * @dbg_buf_idx: debug buffer index to get usecases info */ struct cam_mem_table { struct mutex m_lock; @@ -79,6 +80,7 @@ struct cam_mem_table { struct cam_mem_buf_queue bufq[CAM_MEM_BUFQ_MAX]; struct dentry *dentry; bool alloc_profile_enable; + size_t dbg_buf_idx; }; /** diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 58071bc3419e..a1dd6050184a 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -284,6 +284,8 @@ struct cam_req_mgr_link_control { #define CAM_MEM_FLAG_HW_SHARED_ACCESS (1<<11) #define CAM_MEM_FLAG_CDSP_OUTPUT (1<<12) #define CAM_MEM_FLAG_DISABLE_DELAYED_UNMAP (1<<13) +#define CAM_MEM_FLAG_KMD_DEBUG_FLAG (1<<14) + #define CAM_MEM_MMU_MAX_HANDLE 16 From 7ed86436a39d89b38ca4b54cb8bf28a820213fc7 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 14 Aug 2020 14:08:11 -0700 Subject: [PATCH 464/790] msm: camera: sensor: Add logic to call the res_mgr api if needed Currently any slave can call pinctrl api for res_mgr which may lead in corruption of pinctrl state. This change identify whether slave is resposible for the shared pinctrl access by searching/matching the gpio defined under res_mgr dtsi. Also remove post_init pinctrl as this functionality is not used anymore. This can help to avoid the unnecessary calls to the res_mgr which can avoid mutex operations to imporve the performance. CRs-Fixed: 2758167 Change-Id: Id0e863ae00eeef6c3877f02d34878c131695a604 Signed-off-by: Jigarkumar Zala --- .../cam_res_mgr/cam_res_mgr.c | 66 ++++++------- .../cam_res_mgr/cam_res_mgr_api.h | 16 ++-- .../cam_sensor_utils/cam_sensor_util.c | 93 ++++++++++++++----- 3 files changed, 108 insertions(+), 67 deletions(-) diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index abe1b2c7a0fd..592b68002c87 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -318,43 +318,6 @@ int cam_res_mgr_shared_pinctrl_select_state(bool active) } EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_select_state); -int cam_res_mgr_shared_pinctrl_post_init(void) -{ - int ret = 0; - struct cam_soc_pinctrl_info *pinctrl_info; - - if (!cam_res || !cam_res->shared_gpio_enabled) { - CAM_DBG(CAM_RES, "Not support shared gpio."); - return ret; - } - - mutex_lock(&cam_res->gpio_res_lock); - if (cam_res->pstatus == PINCTRL_STATUS_PUT) { - CAM_DBG(CAM_RES, "The shared pinctrl alerady been put.!"); - mutex_unlock(&cam_res->gpio_res_lock); - return ret; - } - - pinctrl_info = &cam_res->dt.pinctrl_info; - - /* - * If no gpio resource in gpio_res_list, and - * no shared clk now, it means this device - * don't have shared gpio. - */ - if (list_empty(&cam_res->gpio_res_list) && - cam_res->shared_clk_ref_count < 1) { - ret = pinctrl_select_state(pinctrl_info->pinctrl, - pinctrl_info->gpio_state_suspend); - devm_pinctrl_put(pinctrl_info->pinctrl); - cam_res->pstatus = PINCTRL_STATUS_PUT; - } - mutex_unlock(&cam_res->gpio_res_lock); - - return ret; -} -EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_post_init); - static int cam_res_mgr_add_device(struct device *dev, struct cam_gpio_res *gpio_res) { @@ -477,6 +440,35 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio, } EXPORT_SYMBOL(cam_res_mgr_gpio_request); +bool cam_res_mgr_check_if_gpio_is_shared( + struct gpio *gpio_tbl, uint8_t size) +{ + bool found = false; + int i = 0; + + if (!cam_res) { + CAM_DBG(CAM_RES, "cam_res data is not avaialbe"); + return false; + } + + if (!cam_res->shared_gpio_enabled) { + CAM_DBG(CAM_RES, "shared gpio support is not enabled"); + return false; + } + + for (i = 0; i < size; i++) { + found = cam_res_mgr_gpio_is_shared(gpio_tbl[i].gpio); + if (found) { + CAM_DBG(CAM_RES, "gpio: %d is shared gpio", + gpio_tbl[i].gpio); + break; + } + } + + return found; +} +EXPORT_SYMBOL(cam_res_mgr_check_if_gpio_is_shared); + static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) { bool found = false; diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h index b47c68dea675..096cb0916e7d 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __CAM_RES_MGR_API_H__ @@ -75,14 +75,18 @@ void cam_res_mgr_shared_pinctrl_put(void); int cam_res_mgr_shared_pinctrl_select_state(bool active); /** - * @brief: Post init shared pinctrl + * @brief: Check for shared gpio * - * Post init to check if the device really has shared gpio, - * suspend and put the pinctrl if not use shared gpio. + * Will check whether requested device shares the gpio with other + * device. This function check against gpio table from device and + * shared gpio resources has been defined at res-mgr level * - * @return Status of operation. Negative in case of error. Zero otherwise. + * @gpio_tbl : The GPIO table for respective device + * @size : GPIO table size + * @return Status of operation. False if not shared, true otherwise. */ -int cam_res_mgr_shared_pinctrl_post_init(void); +bool cam_res_mgr_check_if_gpio_is_shared( + struct gpio *gpio_tbl, uint8_t size); /** * @brief: Request a gpio diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 7334c9accbb2..9b13ff7e4d02 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1227,6 +1227,45 @@ int cam_sensor_util_request_gpio_table( return rc; } +static bool cam_sensor_util_check_gpio_is_shared( + struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + uint8_t size = 0; + struct cam_soc_gpio_data *gpio_conf = + soc_info->gpio_data; + struct gpio *gpio_tbl = NULL; + + if (!gpio_conf) { + CAM_DBG(CAM_SENSOR, "No GPIO data"); + return false; + } + + if (gpio_conf->cam_gpio_common_tbl_size <= 0) { + CAM_DBG(CAM_SENSOR, "No GPIO entry"); + return false; + } + + gpio_tbl = gpio_conf->cam_gpio_req_tbl; + size = gpio_conf->cam_gpio_req_tbl_size; + + if (!gpio_tbl || !size) { + CAM_ERR(CAM_SENSOR, "invalid gpio_tbl %pK / size %d", + gpio_tbl, size); + return false; + } + + rc = cam_res_mgr_check_if_gpio_is_shared( + gpio_tbl, size); + if (!rc) { + CAM_DBG(CAM_SENSOR, + "dev: %s don't have shared gpio resources", + soc_info->dev_name); + return false; + } + + return true; +} static int32_t cam_sensor_validate(void *ptr, size_t remain_buf) { @@ -1949,6 +1988,7 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info) { int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0, i = 0; + bool shared_gpio = false; int32_t vreg_idx = -1; struct cam_sensor_power_setting *power_setting = NULL; struct msm_camera_gpio_num_info *gpio_num_info = NULL; @@ -1979,16 +2019,21 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, ctrl->cam_pinctrl_status = 1; } - if (cam_res_mgr_shared_pinctrl_init()) { - CAM_ERR(CAM_SENSOR, - "Failed to init shared pinctrl"); - return -EINVAL; - } - + shared_gpio = cam_sensor_util_check_gpio_is_shared(soc_info); rc = cam_sensor_util_request_gpio_table(soc_info, 1); if (rc < 0) no_gpio = rc; + if (shared_gpio) { + rc = cam_res_mgr_shared_pinctrl_init(); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Failed to init shared pinctrl"); + shared_gpio = false; + return -EINVAL; + } + } + if (ctrl->cam_pinctrl_status) { ret = pinctrl_select_state( ctrl->pinctrl_info.pinctrl, @@ -1997,11 +2042,12 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, CAM_ERR(CAM_SENSOR, "cannot set pin to active state"); } - ret = cam_res_mgr_shared_pinctrl_select_state(true); - if (ret) - CAM_ERR(CAM_SENSOR, - "Cannot set shared pin to active state"); - + if (shared_gpio) { + ret = cam_res_mgr_shared_pinctrl_select_state(true); + if (ret) + CAM_ERR(CAM_SENSOR, + "Cannot set shared pin to active state"); + } CAM_DBG(CAM_SENSOR, "power setting size: %d", ctrl->power_setting_size); for (index = 0; index < ctrl->power_setting_size; index++) { @@ -2185,11 +2231,6 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, (power_setting->delay * 1000) + 1000); } - ret = cam_res_mgr_shared_pinctrl_post_init(); - if (ret) - CAM_ERR(CAM_SENSOR, - "Failed to post init shared pinctrl"); - return 0; power_up_failed: CAM_ERR(CAM_SENSOR, "failed"); @@ -2294,8 +2335,10 @@ power_up_failed: if (soc_info->use_shared_clk) cam_res_mgr_shared_clk_config(false); - cam_res_mgr_shared_pinctrl_select_state(false); - cam_res_mgr_shared_pinctrl_put(); + if (shared_gpio) { + cam_res_mgr_shared_pinctrl_select_state(false); + cam_res_mgr_shared_pinctrl_put(); + } ctrl->cam_pinctrl_status = 0; @@ -2329,6 +2372,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info) { int index = 0, ret = 0, num_vreg = 0, i; + bool shared_gpio = false; struct cam_sensor_power_setting *pd = NULL; struct cam_sensor_power_setting *ps = NULL; struct msm_camera_gpio_num_info *gpio_num_info = NULL; @@ -2339,6 +2383,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, return -EINVAL; } + shared_gpio = cam_sensor_util_check_gpio_is_shared(soc_info); gpio_num_info = ctrl->gpio_num_info; num_vreg = soc_info->num_rgltr; @@ -2475,15 +2520,15 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, devm_pinctrl_put(ctrl->pinctrl_info.pinctrl); } + cam_sensor_util_request_gpio_table(soc_info, 0); + if (soc_info->use_shared_clk) cam_res_mgr_shared_clk_config(false); - - cam_res_mgr_shared_pinctrl_select_state(false); - cam_res_mgr_shared_pinctrl_put(); - + if (shared_gpio) { + cam_res_mgr_shared_pinctrl_select_state(false); + cam_res_mgr_shared_pinctrl_put(); + } ctrl->cam_pinctrl_status = 0; - cam_sensor_util_request_gpio_table(soc_info, 0); - return 0; } From baf2d520ed70a459b956eb15cdce8e4ee66e4e47 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 19 Aug 2020 00:40:28 +0530 Subject: [PATCH 465/790] msm: camera: sync: Rearrange sync reason events Rearrange sync error reason code for better code readability. CRs-Fixed: 2750553 Change-Id: Ia64694155921c074946167763815a87beb856b35 Signed-off-by: Alok Chauhan --- drivers/cam_core/cam_context_utils.c | 6 ++--- drivers/cam_cust/cam_custom_context.c | 10 +++---- drivers/cam_isp/cam_isp_context.c | 4 +-- .../cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c | 2 +- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 2 +- drivers/cam_sync/cam_sync.c | 8 +++--- include/uapi/camera/media/cam_sync.h | 27 +++++++++---------- 7 files changed, 28 insertions(+), 31 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 86f1bf43af63..a79ed3867091 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -663,7 +663,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) rc = cam_sync_signal( req->out_map_entries[i].sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_FLUSH); + CAM_SYNC_COMMON_EVENT_FLUSH); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled, sync_id:%d", @@ -736,7 +736,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) rc = cam_sync_signal( req->out_map_entries[i].sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_FLUSH); + CAM_SYNC_COMMON_EVENT_FLUSH); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled ctx: %pK dev_name: %s dev_handle: %d ctx_state: %d", @@ -850,7 +850,7 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, if (sync_id != -1) { rc = cam_sync_signal(sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_FLUSH); + CAM_SYNC_COMMON_EVENT_FLUSH); if (rc == -EALREADY) { CAM_ERR(CAM_CTXT, "Req: %llu already signalled, sync_id:%d", diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 7126f6ba7e7c..b0aebffafa7a 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -183,7 +183,7 @@ static int __cam_custom_ctx_frame_done( rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, - CAM_SYNC_EVENT_SUCCESS); + CAM_SYNC_COMMON_EVENT_SUCCESS); if (rc) CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); @@ -370,7 +370,7 @@ static int __cam_custom_ctx_flush_req(struct cam_context *ctx, rc = cam_sync_signal( req_custom->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_FLUSH); + CAM_SYNC_COMMON_EVENT_FLUSH); if (rc) CAM_ERR_RATE_LIMIT(CAM_CUSTOM, "signal fence failed\n"); @@ -546,7 +546,7 @@ static int __cam_custom_stop_dev_core( cam_sync_signal( req_custom->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_STOP); + CAM_SYNC_COMMON_EVENT_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -563,7 +563,7 @@ static int __cam_custom_stop_dev_core( cam_sync_signal( req_custom->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_STOP); + CAM_SYNC_COMMON_EVENT_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } @@ -580,7 +580,7 @@ static int __cam_custom_stop_dev_core( cam_sync_signal( req_custom->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_CANCEL, - CAM_SYNC_EVENT_STOP); + CAM_SYNC_COMMON_EVENT_STOP); } list_add_tail(&req->list, &ctx->free_req_list); } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 3ed41d95f7ad..82d41f71e910 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -937,7 +937,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, - CAM_SYNC_EVENT_SUCCESS); + CAM_SYNC_COMMON_EVENT_SUCCESS); if (rc) CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); @@ -1078,7 +1078,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, - CAM_SYNC_EVENT_SUCCESS); + CAM_SYNC_COMMON_EVENT_SUCCESS); if (rc) CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); diff --git a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 40f851c30d1d..d878271403d1 100644 --- a/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -547,7 +547,7 @@ static int cam_lrme_mgr_cb(void *data, buf_data.request_id = frame_req->req_id; buf_data.evt_param = (cb_args->cb_type & CAM_LRME_CB_ERROR) ? CAM_SYNC_LRME_EVENT_CB_ERROR : - CAM_SYNC_EVENT_SUCCESS; + CAM_SYNC_COMMON_EVENT_SUCCESS; CAM_DBG(CAM_LRME, "frame req %llu, evt_id %d", frame_req->req_id, evt_id); rc = hw_mgr->event_cb(frame_req->ctxt_to_hw_map, diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 0b7b0ec13db0..8dfff457a6d6 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1567,7 +1567,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id, ctx->ctx_id); cam_ope_req_timer_reset(ctx); cam_ope_device_timer_reset(ope_hw_mgr); - buf_data.evt_param = CAM_SYNC_EVENT_SUCCESS; + buf_data.evt_param = CAM_SYNC_COMMON_EVENT_SUCCESS; } else if (status == CAM_CDM_CB_STATUS_HW_RESUBMIT) { CAM_INFO(CAM_OPE, "After reset of CDM and OPE, reapply req"); buf_data.evt_param = CAM_SYNC_OPE_EVENT_HW_RESUBMIT; diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 748878e94478..5cdfa9bdc19a 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -516,7 +516,7 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl) return cam_sync_signal(sync_signal.sync_obj, sync_signal.sync_state, - CAM_SYNC_CAM_SYNC_SIGNAL_EVENT); + CAM_SYNC_COMMON_SYNC_SIGNAL_EVENT); } static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl) @@ -667,7 +667,7 @@ static int cam_sync_handle_register_user_payload( row->state, user_payload_kernel->payload_data, CAM_SYNC_USER_PAYLOAD_SIZE * sizeof(__u64), - CAM_SYNC_REGISTER_PAYLOAD_EVENT); + CAM_SYNC_COMMON_REG_PAYLOAD_EVENT); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); kfree(user_payload_kernel); @@ -873,7 +873,7 @@ static int cam_sync_close(struct file *filep) if (row->state == CAM_SYNC_STATE_ACTIVE) { rc = cam_sync_signal(i, CAM_SYNC_STATE_SIGNALED_ERROR, - CAM_SYNC_v4l2_RELEASE_EVENT); + CAM_SYNC_COMMON_RELEASE_EVENT); if (rc < 0) CAM_ERR(CAM_SYNC, "Cleanup signal fail idx:%d\n", @@ -1099,7 +1099,7 @@ int cam_synx_sync_signal(int32_t sync_obj, uint32_t synx_status) break; } - rc = cam_sync_signal(sync_obj, sync_status, CAM_SYNC_EVENT_SYNX); + rc = cam_sync_signal(sync_obj, sync_status, CAM_SYNC_COMMON_EVENT_SYNX); if (rc) { CAM_ERR(CAM_SYNC, "synx signal failed with %d, sync_obj=%d, synx_status=%d, sync_status=%d", diff --git a/include/uapi/camera/media/cam_sync.h b/include/uapi/camera/media/cam_sync.h index 87681dd121fd..9131afcacbb2 100644 --- a/include/uapi/camera/media/cam_sync.h +++ b/include/uapi/camera/media/cam_sync.h @@ -44,16 +44,20 @@ #define CAM_SYNC_STATE_SIGNALED_ERROR 3 #define CAM_SYNC_STATE_SIGNALED_CANCEL 4 -/* Top level sync event reason types */ -#define CAM_SYNC_EVENT_UNKNOWN 0 -#define CAM_SYNC_EVENT_SUCCESS 1 -#define CAM_SYNC_EVENT_FLUSH 2 -#define CAM_SYNC_EVENT_STOP 3 -#define CAM_SYNC_EVENT_SYNX 4 - +/* Top level common sync event reason types */ +#define CAM_SYNC_COMMON_EVENT_START 0 +#define CAM_SYNC_COMMON_EVENT_UNUSED (CAM_SYNC_COMMON_EVENT_START + 0) +#define CAM_SYNC_COMMON_EVENT_SUCCESS (CAM_SYNC_COMMON_EVENT_START + 1) +#define CAM_SYNC_COMMON_EVENT_FLUSH (CAM_SYNC_COMMON_EVENT_START + 2) +#define CAM_SYNC_COMMON_EVENT_STOP (CAM_SYNC_COMMON_EVENT_START + 3) +#define CAM_SYNC_COMMON_EVENT_SYNX (CAM_SYNC_COMMON_EVENT_START + 4) +#define CAM_SYNC_COMMON_REG_PAYLOAD_EVENT (CAM_SYNC_COMMON_EVENT_START + 5) +#define CAM_SYNC_COMMON_SYNC_SIGNAL_EVENT (CAM_SYNC_COMMON_EVENT_START + 6) +#define CAM_SYNC_COMMON_RELEASE_EVENT (CAM_SYNC_COMMON_EVENT_START + 7) +#define CAM_SYNC_COMMON_EVENT_END (CAM_SYNC_COMMON_EVENT_START + 50) /* ISP Sync event reason types */ -#define CAM_SYNC_ISP_EVENT_START 20 +#define CAM_SYNC_ISP_EVENT_START (CAM_SYNC_COMMON_EVENT_END + 1) #define CAM_SYNC_ISP_EVENT_UNKNOWN (CAM_SYNC_ISP_EVENT_START + 0) #define CAM_SYNC_ISP_EVENT_BUBBLE (CAM_SYNC_ISP_EVENT_START + 1) #define CAM_SYNC_ISP_EVENT_OVERFLOW (CAM_SYNC_ISP_EVENT_START + 2) @@ -111,13 +115,6 @@ #define CAM_SYNC_OPE_EVENT_HW_RESET_FAILED (CAM_SYNC_OPE_EVENT_START + 10) #define CAM_SYNC_OPE_EVENT_END (CAM_SYNC_OPE_EVENT_START + 50) -/* Others ioctl/v4l2 Sync event reason types */ -#define CAM_SYNC_OTHER_EVENT_START (CAM_SYNC_OPE_EVENT_END + 1) -#define CAM_SYNC_REGISTER_PAYLOAD_EVENT (CAM_SYNC_OTHER_EVENT_START + 0) -#define CAM_SYNC_CAM_SYNC_SIGNAL_EVENT (CAM_SYNC_OTHER_EVENT_START + 1) -#define CAM_SYNC_v4l2_RELEASE_EVENT (CAM_SYNC_OTHER_EVENT_START + 2) -#define CAM_SYNC_OTHER_EVENT_END (CAM_SYNC_OTHER_EVENT_START + 50) - #define CAM_SYNC_EVENT_CNT 7 #define CAM_SYNC_EVENT_REASON_CODE_INDEX 0 From 64cd69547ad4c4c5b2e78d120630f4f3b6cc3d36 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Fri, 14 Aug 2020 19:32:43 +0530 Subject: [PATCH 466/790] msm: camera: csiphy: Update secure PHY HW version checks Add HW version checks for CSIPHY 1.2.3/1.2.4 in the secure CP register bitmask logic. CRs-Fixed: 2761303 Change-Id: Ib831b71115f46839e691f58ab3128529efb2270c Signed-off-by: Shravan Nevatia --- .../cam_csiphy/cam_csiphy_core.c | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 4230a12fc0c7..4f371b4d0a70 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -24,7 +24,12 @@ #define LANE_MASK_2PH 0x1F #define LANE_MASK_3PH 0x7 +/* Size of CPAS_SEC_LANE_CP_CTRL register mask */ #define SEC_LANE_CP_REG_LEN 32 +/* + * PHY index at which CPAS_SEC_LANE_CP_CTRL register mask + * changes depending on PHY HW version + */ #define MAX_PHY_MSK_PER_REG 4 /* Mask to enable skew calibration registers */ @@ -111,19 +116,24 @@ static int32_t cam_csiphy_update_secure_info( lane_assign >>= 4; } - if ((csiphy_dev->hw_version == CSIPHY_VERSION_V201) || - (csiphy_dev->hw_version == CSIPHY_VERSION_V125)) { - phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + - CAM_CSIPHY_MAX_CPHY_LANES + 1; - } else if (csiphy_dev->hw_version == CSIPHY_VERSION_V121) { + switch (csiphy_dev->hw_version) { + case CSIPHY_VERSION_V201: + case CSIPHY_VERSION_V125: phy_mask_len = - (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) ? - (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) - : (CAM_CSIPHY_MAX_DPHY_LANES + - CAM_CSIPHY_MAX_CPHY_LANES + 1); - } else { - phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + - CAM_CSIPHY_MAX_CPHY_LANES; + CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES + 1; + break; + case CSIPHY_VERSION_V121: + case CSIPHY_VERSION_V123: + case CSIPHY_VERSION_V124: + phy_mask_len = + (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) ? + (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) : + (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES + 1); + break; + default: + phy_mask_len = + CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES; + break; } if (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) { From 3bcfbc3de7e07d08feeb463d4a86e1a61e699d88 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Mon, 24 Aug 2020 16:38:36 +0530 Subject: [PATCH 467/790] msm: camera: common: Enable dlkm for holi Compile camera as dynamic loadable kernel module for holi. CRs-Fixed: 2761499 Change-Id: Id7a4578bfc91ff5036c10aa8c59c07e358683795 Signed-off-by: Trishansh Bhardwaj --- config/holicamera.conf | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/config/holicamera.conf b/config/holicamera.conf index bfc74856aa7d..85bc1dae00c6 100644 --- a/config/holicamera.conf +++ b/config/holicamera.conf @@ -1,13 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only # Copyright (c) 2020, The Linux Foundation. All rights reserved. -ifeq ($(CONFIG_QGKI),y) -export CONFIG_SPECTRA_CAMERA=y -$(info "SPECTRA_CAMERA IS STATIC") -else -$(info "SPECTRA_CAMERA IS MODULAR") +$(info "HOLI SPECTRA_CAMERA IS MODULAR") export CONFIG_SPECTRA_CAMERA=m -endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) export CONFIG_SPECTRA_ISP=y From f4ec43b7482f76ddeb027d6865c2c8d710d1b82f Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 13 Aug 2020 14:33:28 -0700 Subject: [PATCH 468/790] msm: camera: cpas: Add more debug information in cpas dump Enhance cpas state dump to get more information about bandwidth and clock status. This additional state dump can be enabled using debugfs. adb shell "echo 1 > /sys/kernel/debug/camera_cpas/full_state_dump" Traverse through all bw tree nodes and print info in each node. Print current clk frequencies of all clocks that cpas enables. Read rpmh bcm status registers to understand mmnoc clk freq. Add cpas monitor to save important info whenever clients notify with an event. This monitor info is printed in cpas state dump. CRs-Fixed: 2754299 Change-Id: Ib9007091f7e34127f1ca92498e2537b2a06887cb Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 259 +++++++++++++++++- drivers/cam_cpas/cam_cpas_hw.h | 69 +++++ drivers/cam_cpas/cam_cpas_hw_intf.h | 13 + drivers/cam_cpas/cam_cpas_intf.c | 31 +++ drivers/cam_cpas/cam_cpas_soc.c | 34 +++ drivers/cam_cpas/cam_cpas_soc.h | 3 +- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 13 + drivers/cam_cpas/include/cam_cpas_api.h | 20 ++ .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 54 ++-- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 51 ++-- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 8 + drivers/cam_utils/cam_soc_util.c | 39 +++ drivers/cam_utils/cam_soc_util.h | 12 + 13 files changed, 562 insertions(+), 44 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index d8f18a8220bb..6d3f0e2b968c 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -18,6 +18,11 @@ static uint cam_min_camnoc_ib_bw; module_param(cam_min_camnoc_ib_bw, uint, 0644); +static void cam_cpas_update_monitor_array(struct cam_hw_info *cpas_hw, + const char *identifier_string, int32_t identifier_value); +static void cam_cpas_dump_monitor_array( + struct cam_cpas *cpas_core); + static void cam_cpas_process_bw_overrides( struct cam_cpas_bus_client *bus_client, uint64_t *ab, uint64_t *ib, const struct cam_cpas_debug_settings *cpas_settings) @@ -1067,9 +1072,16 @@ static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], "Translated Vote", &axi_vote); + /* Log an entry whenever there is an AXI update - before updating */ + cam_cpas_update_monitor_array(cpas_hw, "CPAS AXI pre-update", + client_indx); + rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, cpas_core->cpas_client[client_indx], &axi_vote); + /* Log an entry whenever there is an AXI update - after updating */ + cam_cpas_update_monitor_array(cpas_hw, "CPAS AXI post-update", + client_indx); unlock_client: mutex_unlock(&cpas_core->client_mutex[client_indx]); mutex_unlock(&cpas_hw->hw_mutex); @@ -1782,8 +1794,52 @@ static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_cpas_private_soc *soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; - int rc = 0; uint32_t i; + struct cam_cpas_tree_node *curr_node; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + + /* + * First print rpmh registers as early as possible to catch nearest + * state of rpmh after an issue (overflow) occurs. + */ + if ((cpas_core->streamon_clients > 0) && + (cpas_core->regbase_index[CAM_CPAS_REG_RPMH] != -1)) { + int reg_base_index = + cpas_core->regbase_index[CAM_CPAS_REG_RPMH]; + void __iomem *rpmh_base = + soc_info->reg_map[reg_base_index].mem_base; + uint32_t offset_fe, offset_be; + uint32_t fe_val, be_val; + uint32_t *rpmh_info = &soc_private->rpmh_info[0]; + uint32_t ddr_bcm_index = + soc_private->rpmh_info[CAM_RPMH_BCM_DDR_INDEX]; + uint32_t mnoc_bcm_index = + soc_private->rpmh_info[CAM_RPMH_BCM_MNOC_INDEX]; + + /* + * print 12 registers from 0x4, 0x800 offsets - + * this will give ddr, mmnoc and other BCM info. + * i=0 for DDR, i=4 for mnoc, but double check for each chipset. + */ + for (i = 0; i < rpmh_info[CAM_RPMH_NUMBER_OF_BCMS]; i++) { + if ((!cpas_core->full_state_dump) && + (i != ddr_bcm_index) && + (i != mnoc_bcm_index)) + continue; + + offset_fe = rpmh_info[CAM_RPMH_BCM_FE_OFFSET] + + (i * 0x4); + offset_be = rpmh_info[CAM_RPMH_BCM_BE_OFFSET] + + (i * 0x4); + + fe_val = cam_io_r_mb(rpmh_base + offset_fe); + be_val = cam_io_r_mb(rpmh_base + offset_be); + + CAM_INFO(CAM_CPAS, + "i=%d, FE[offset=0x%x, value=0x%x] BE[offset=0x%x, value=0x%x]", + i, offset_fe, fe_val, offset_be, be_val); + } + } for (i = 0; i < cpas_core->num_axi_ports; i++) { CAM_INFO(CAM_CPAS, @@ -1815,7 +1871,182 @@ static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]", cpas_core->ahb_bus_client.curr_vote_level); - return rc; + if (!cpas_core->full_state_dump) { + CAM_DBG(CAM_CPAS, "CPAS full state dump not enabled"); + return 0; + } + + /* This will traverse through all nodes in the tree and print stats*/ + for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) { + if (!soc_private->tree_node[i]) + continue; + curr_node = soc_private->tree_node[i]; + + CAM_INFO(CAM_CPAS, + "[%s] Cell[%d] level[%d] PortIdx[%d][%d] camnoc_bw[%d %d %lld %lld] mnoc_bw[%lld %lld]", + curr_node->node_name, curr_node->cell_idx, + curr_node->level_idx, curr_node->axi_port_idx, + curr_node->camnoc_axi_port_idx, + curr_node->camnoc_max_needed, + curr_node->bus_width_factor, + curr_node->camnoc_bw, + curr_node->camnoc_bw * curr_node->bus_width_factor, + curr_node->mnoc_ab_bw, curr_node->mnoc_ib_bw); + } + + if (cpas_core->streamon_clients > 0) { + /* + * Means, cpas has clocks turned on, so we can query clk freq. + * Print clk frequencies that cpas enables - this will print + * camcc_ahb, camcc_axi, gcc_hf, gcc_sf as well. + */ + cam_soc_util_print_clk_freq(&cpas_hw->soc_info); + } + + cam_cpas_dump_monitor_array(cpas_core); + + return 0; +} + +static void cam_cpas_update_monitor_array(struct cam_hw_info *cpas_hw, + const char *identifier_string, int32_t identifier_value) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + struct cam_cpas_monitor *entry; + int iterator; + int i; + + CAM_CPAS_INC_MONITOR_HEAD(&cpas_core->monitor_head, &iterator); + + entry = &cpas_core->monitor_entries[iterator]; + + ktime_get_real_ts64(&entry->timestamp); + strlcpy(entry->identifier_string, identifier_string, + sizeof(entry->identifier_string)); + + entry->identifier_value = identifier_value; + + for (i = 0; i < cpas_core->num_axi_ports; i++) { + entry->axi_info[i].axi_port_name = + cpas_core->axi_port[i].axi_port_name; + entry->axi_info[i].ab_bw = cpas_core->axi_port[i].ab_bw; + entry->axi_info[i].ib_bw = cpas_core->axi_port[i].ib_bw; + entry->axi_info[i].camnoc_bw = cpas_core->axi_port[i].camnoc_bw; + entry->axi_info[i].applied_ab_bw = + cpas_core->axi_port[i].applied_ab_bw; + entry->axi_info[i].applied_ib_bw = + cpas_core->axi_port[i].applied_ib_bw; + } + + entry->applied_camnoc_clk = cpas_core->applied_camnoc_axi_rate; + entry->applied_ahb_level = cpas_core->ahb_bus_client.curr_vote_level; + + if ((cpas_core->streamon_clients > 0) && + (cpas_core->regbase_index[CAM_CPAS_REG_RPMH] != -1) && + soc_private->rpmh_info[CAM_RPMH_NUMBER_OF_BCMS]) { + int reg_base_index = + cpas_core->regbase_index[CAM_CPAS_REG_RPMH]; + void __iomem *rpmh_base = + soc_info->reg_map[reg_base_index].mem_base; + uint32_t fe_ddr_offset = + soc_private->rpmh_info[CAM_RPMH_BCM_FE_OFFSET] + + (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_DDR_INDEX]); + uint32_t fe_mnoc_offset = + soc_private->rpmh_info[CAM_RPMH_BCM_FE_OFFSET] + + (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_MNOC_INDEX]); + uint32_t be_ddr_offset = + soc_private->rpmh_info[CAM_RPMH_BCM_BE_OFFSET] + + (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_DDR_INDEX]); + uint32_t be_mnoc_offset = + soc_private->rpmh_info[CAM_RPMH_BCM_BE_OFFSET] + + (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_MNOC_INDEX]); + + /* + * 0x4, 0x800 - DDR + * 0x800, 0x810 - mmnoc + */ + entry->fe_ddr = cam_io_r_mb(rpmh_base + fe_ddr_offset); + entry->fe_mnoc = cam_io_r_mb(rpmh_base + fe_mnoc_offset); + entry->be_ddr = cam_io_r_mb(rpmh_base + be_ddr_offset); + entry->be_mnoc = cam_io_r_mb(rpmh_base + be_mnoc_offset); + } +} + +static void cam_cpas_dump_monitor_array( + struct cam_cpas *cpas_core) +{ + int i = 0, j = 0; + int64_t state_head = 0; + uint32_t index, num_entries, oldest_entry; + uint64_t ms, tmp, hrs, min, sec; + struct cam_cpas_monitor *entry; + + if (!cpas_core->full_state_dump) + return; + + state_head = atomic64_read(&cpas_core->monitor_head); + + if (state_head == -1) { + CAM_WARN(CAM_CPAS, "No valid entries in cpas monitor array"); + return; + } else if (state_head < CAM_CPAS_MONITOR_MAX_ENTRIES) { + num_entries = state_head; + oldest_entry = 0; + } else { + num_entries = CAM_CPAS_MONITOR_MAX_ENTRIES; + div_u64_rem(state_head + 1, + CAM_CPAS_MONITOR_MAX_ENTRIES, &oldest_entry); + } + + CAM_INFO(CAM_CPAS, "======== Dumping monitor information ==========="); + + index = oldest_entry; + + for (i = 0; i < num_entries; i++) { + entry = &cpas_core->monitor_entries[index]; + tmp = entry->timestamp.tv_sec; + ms = (entry->timestamp.tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); + + CAM_INFO(CAM_CPAS, + "**** %llu:%llu:%llu.%llu : Index[%d] Identifier[%s][%d] camnoc=%lld, ahb=%d", + hrs, min, sec, ms, + index, + entry->identifier_string, entry->identifier_value, + entry->applied_camnoc_clk, entry->applied_ahb_level); + + for (j = 0; j < cpas_core->num_axi_ports; j++) { + CAM_INFO(CAM_CPAS, + "MNOC BW [%s] : ab=%lld, ib=%lld, camnoc=%lld", + entry->axi_info[j].axi_port_name, + entry->axi_info[j].applied_ab_bw, + entry->axi_info[j].applied_ib_bw, + entry->axi_info[j].camnoc_bw); + } + + if (cpas_core->regbase_index[CAM_CPAS_REG_RPMH] != -1) { + CAM_INFO(CAM_CPAS, + "fe_ddr=0x%x, fe_mnoc=0x%x, be_ddr=0x%x, be_mnoc=0x%x", + entry->fe_ddr, entry->fe_mnoc, + entry->be_ddr, entry->be_mnoc); + } + + index = (index + 1) % CAM_CPAS_MONITOR_MAX_ENTRIES; + } +} + +static int cam_cpas_log_event(struct cam_hw_info *cpas_hw, + const char *identifier_string, int32_t identifier_value) +{ + cam_cpas_update_monitor_array(cpas_hw, identifier_string, + identifier_value); + + return 0; } static int cam_cpas_select_qos(struct cam_hw_info *cpas_hw, @@ -1954,6 +2185,22 @@ static int cam_cpas_hw_process_cmd(void *hw_priv, break; } + case CAM_CPAS_HW_CMD_LOG_EVENT: { + struct cam_cpas_hw_cmd_notify_event *event; + + if (sizeof(struct cam_cpas_hw_cmd_notify_event) != arg_size) { + CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d", + cmd_type, arg_size); + break; + } + + event = (struct cam_cpas_hw_cmd_notify_event *)cmd_args; + + rc = cam_cpas_log_event(hw_priv, event->identifier_string, + event->identifier_value); + break; + } + case CAM_CPAS_HW_CMD_SELECT_QOS: { uint32_t *selection_mask; @@ -2049,6 +2296,10 @@ static int cam_cpas_util_create_debugfs(struct cam_cpas *cpas_core) dbgfileptr = debugfs_create_bool("ahb_bus_scaling_disable", 0644, cpas_core->dentry, &cpas_core->ahb_bus_scaling_disable); + + dbgfileptr = debugfs_create_bool("full_state_dump", 0644, + cpas_core->dentry, &cpas_core->full_state_dump); + if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) CAM_WARN(CAM_CPAS, "DebugFS not enabled in kernel!"); @@ -2099,6 +2350,10 @@ int cam_cpas_hw_probe(struct platform_device *pdev, cpas_hw->soc_info.dev_name = pdev->name; cpas_hw->open_count = 0; cpas_core->ahb_bus_scaling_disable = false; + cpas_core->full_state_dump = false; + + atomic64_set(&cpas_core->monitor_head, -1); + mutex_init(&cpas_hw->hw_mutex); spin_lock_init(&cpas_hw->hw_lock); init_completion(&cpas_hw->hw_complete); diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index 4d76b80fa7d1..3301cdbff82d 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -37,6 +37,19 @@ ((CAM_CPAS_CLIENT_REGISTERED(cpas_core, indx)) && \ (cpas_core->cpas_client[indx]->started)) +/* Array indices to represent corresponding RPMH BCM info */ +#define CAM_RPMH_NUMBER_OF_BCMS 0 +#define CAM_RPMH_BCM_FE_OFFSET 1 +#define CAM_RPMH_BCM_BE_OFFSET 2 +#define CAM_RPMH_BCM_DDR_INDEX 3 +#define CAM_RPMH_BCM_MNOC_INDEX 4 +#define CAM_RPMH_BCM_INFO_MAX 5 + +#define CAM_CPAS_MONITOR_MAX_ENTRIES 20 +#define CAM_CPAS_INC_MONITOR_HEAD(head, ret) \ + div_u64_rem(atomic64_add_return(1, head),\ + CAM_CPAS_MONITOR_MAX_ENTRIES, (ret)) + /** * enum cam_cpas_access_type - Enum for Register access type */ @@ -163,6 +176,56 @@ struct cam_cpas_axi_port { uint64_t applied_ib_bw; }; +/** + * struct cam_cpas_axi_port_debug_info : AXI port information + * + * @axi_port_name: Name of this AXI port + * @ab_bw: AB bw value for this port + * @ib_bw: IB bw value for this port + * @camnoc_bw: CAMNOC bw value for this port + * @applied_ab_bw: applied ab bw for this port + * @applied_ib_bw: applied ib bw for this port + */ +struct cam_cpas_axi_port_debug_info { + const char *axi_port_name; + uint64_t ab_bw; + uint64_t ib_bw; + uint64_t camnoc_bw; + uint64_t applied_ab_bw; + uint64_t applied_ib_bw; +}; + +/** + * struct cam_cpas_monitor : CPAS monitor array + * + * @timestamp: Timestamp at which this monitor entry is saved + * @axi_info: AXI port information + * @identifier_string: String passed by caller + * @identifier_value: Identifier value passed by caller + * @applied_camnoc_clk: Applied camnoc axi clock rate + * @applied_ahb_level: Applied camcc ahb level + * @fe_ddr: RPMH DDR BCM FE (front-end) status register value. + * This indicates requested clock plan + * @be_ddr: RPMH DDR BCM BE (back-end) status register value. + * This indicates actual current clock plan + * @fe_mnoc: RPMH MNOC BCM FE (front-end) status register value. + * This indicates requested clock plan + * @be_mnoc: RPMH MNOC BCM BE (back-end) status register value. + * This indicates actual current clock plan + */ +struct cam_cpas_monitor { + struct timespec64 timestamp; + char identifier_string[128]; + int32_t identifier_value; + struct cam_cpas_axi_port_debug_info axi_info[CAM_CPAS_MAX_AXI_PORTS]; + uint64_t applied_camnoc_clk; + unsigned int applied_ahb_level; + uint32_t fe_ddr; + uint32_t be_ddr; + uint32_t fe_mnoc; + uint32_t be_mnoc; +}; + /** * struct cam_cpas : CPAS core data structure info * @@ -186,6 +249,9 @@ struct cam_cpas_axi_port { * @dentry: debugfs file entry * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus * @applied_camnoc_axi_rate: applied camnoc axi clock rate + * @monitor_head: Monitor array head + * @monitor_entries: cpas monitor array + * @full_state_dump: Whether to enable full cpas state dump or not */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; @@ -208,6 +274,9 @@ struct cam_cpas { struct dentry *dentry; bool ahb_bus_scaling_disable; uint64_t applied_camnoc_axi_rate; + atomic64_t monitor_head; + struct cam_cpas_monitor monitor_entries[CAM_CPAS_MONITOR_MAX_ENTRIES]; + bool full_state_dump; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index c1e81f2a7624..fc9297ac69c1 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -40,6 +40,7 @@ enum cam_cpas_hw_cmd_process { CAM_CPAS_HW_CMD_AXI_VOTE, CAM_CPAS_HW_CMD_LOG_VOTE, CAM_CPAS_HW_CMD_SELECT_QOS, + CAM_CPAS_HW_CMD_LOG_EVENT, CAM_CPAS_HW_CMD_INVALID, }; @@ -107,6 +108,18 @@ struct cam_cpas_hw_cmd_stop { uint32_t client_handle; }; +/** + * struct cam_cpas_hw_cmd_notify_event : CPAS cmd struct for notify event + * + * @identifier_string: Identifier string passed by caller + * @identifier_value: Identifier value passed by caller + * + */ +struct cam_cpas_hw_cmd_notify_event { + const char *identifier_string; + int32_t identifier_value; +}; + /** * struct cam_cpas_hw_caps : CPAS HW capabilities * diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index d75c51488e31..a3ae586186df 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -461,6 +461,37 @@ int cam_cpas_select_qos_settings(uint32_t selection_mask) } EXPORT_SYMBOL(cam_cpas_select_qos_settings); +int cam_cpas_notify_event(const char *identifier_string, + int32_t identifier_value) +{ + int rc = 0; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -EBADR; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + struct cam_cpas_hw_cmd_notify_event event = { 0 }; + + event.identifier_string = identifier_string; + event.identifier_value = identifier_value; + + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_LOG_EVENT, &event, + sizeof(event)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + rc = -EBADR; + } + + return rc; +} +EXPORT_SYMBOL(cam_cpas_notify_event); + int cam_cpas_unregister_client(uint32_t client_handle) { int rc; diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index f569078ac841..b46640850988 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -834,6 +834,40 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, goto cleanup_tree; } + /* Optional rpmh bcm info */ + count = of_property_count_u32_elems(of_node, "rpmh-bcm-info"); + /* + * We expect count=5(CAM_RPMH_BCM_INFO_MAX) if valid rpmh bcm info + * is available. + * 0 - Total number of BCMs + * 1 - First BCM FE (front-end) register offset. + * These represent requested clk plan by sw + * 2 - First BCM BE (back-end) register offset. + * These represent actual clk plan at hw + * 3 - DDR BCM index + * 4 - MMNOC BCM index + */ + if (count == CAM_RPMH_BCM_INFO_MAX) { + for (i = 0; i < count; i++) { + rc = of_property_read_u32_index(of_node, + "rpmh-bcm-info", i, &soc_private->rpmh_info[i]); + if (rc) { + CAM_ERR(CAM_CPAS, + "Incorrect rpmh info at %d, count=%d", + i, count); + break; + } + CAM_DBG(CAM_CPAS, "RPMH BCM Info [%d]=0x%x", + i, soc_private->rpmh_info[i]); + } + + if (rc) + soc_private->rpmh_info[CAM_RPMH_NUMBER_OF_BCMS] = 0; + } else { + CAM_DBG(CAM_CPAS, "RPMH BCM info not available in DT, count=%d", + count); + } + return 0; cleanup_tree: diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index 71d11bdfc3cb..50d94549ba2a 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -92,7 +92,7 @@ struct cam_cpas_tree_node { * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target * @feature_mask: feature mask value for hw supported features * @fuse_info: fuse information - * + * @rpmh_info: RPMH BCM info */ struct cam_cpas_private_soc { const char *arch_compat; @@ -111,6 +111,7 @@ struct cam_cpas_private_soc { uint64_t camnoc_axi_min_ib_bw; uint32_t feature_mask; struct cam_cpas_fuse_info fuse_info; + uint32_t rpmh_info[CAM_RPMH_BCM_INFO_MAX]; }; void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index ea1a076ca7de..f07e16d7f44c 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -314,6 +314,19 @@ static int cam_cpastop_setup_regbase_indices(struct cam_hw_soc_info *soc_info, return -EINVAL; } + /* optional - rpmh register map */ + rc = cam_common_util_get_string_index(soc_info->mem_block_name, + soc_info->num_mem_block, "cam_rpmh", &index); + if ((rc == 0) && (index < num_reg_map)) { + regbase_index[CAM_CPAS_REG_RPMH] = index; + CAM_DBG(CAM_CPAS, "regbase found for RPMH, rc=%d, %d %d", + rc, index, num_reg_map); + } else { + CAM_DBG(CAM_CPAS, "regbase not found for RPMH, rc=%d, %d %d", + rc, index, num_reg_map); + regbase_index[CAM_CPAS_REG_RPMH] = -1; + } + return 0; } diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 1c248060bb56..4c895ec3918e 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -33,6 +33,7 @@ enum cam_cpas_reg_base { CAM_CPAS_REG_CPASTOP, CAM_CPAS_REG_CAMNOC, CAM_CPAS_REG_CAMSS, + CAM_CPAS_REG_RPMH, CAM_CPAS_REG_MAX }; @@ -660,4 +661,23 @@ void cam_cpas_log_votes(void); */ int cam_cpas_select_qos_settings(uint32_t selection_mask); +/** + * cam_cpas_notify_event() + * + * @brief: API that clients can notify about their events. CPAS save the event + * and any other useful information related to this event. This will + * be printed while cpas state dump - cam_cpas_log_votes. + * One such example is IFE notifiying SOF or EPOCH to cpas and cpas + * saving axi clock information (camnoc_axi, mnoc_hf) at that point + * and printing latest history on IFE overflow. + * + * @identifier_string: Identifier string passed by caller + * @identifier_value: Identifier value passed by caller + * + * @return 0 on success. + * + */ +int cam_cpas_notify_event(const char *identifier_string, + int32_t identifier_value); + #endif /* _CAM_CPAS_API_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index b54c43a145bc..1cc89c32013a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -840,7 +840,7 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, uint32_t violation_mask = 0x3F00, violation_status = 0; uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private = NULL; - uint32_t val0, val1, val2; + uint32_t val0, val1, val2, val3, val4; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -897,24 +897,12 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, if (bus_overflow_status & 0x02000000) CAM_INFO(CAM_ISP, "RDI2 BUS OVERFLOW"); - - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - CAM_INFO(CAM_ISP, - "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", - val0, val1, val2); - cam_cpas_log_votes(); } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "PDLIB / LCR Module hang"); /* print debug registers */ cam_vfe_camif_lite_overflow_debug_info(camif_lite_priv); - return; } if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { @@ -952,7 +940,7 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, } - return; + goto print_state; ife_lite: if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) { @@ -993,23 +981,12 @@ ife_lite: if (bus_overflow_status & 0x08) CAM_INFO(CAM_ISP, "RDI3 BUS OVERFLOW"); - - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - CAM_INFO(CAM_ISP, - "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", - val0, val1, val2); } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "RDI hang"); /* print debug registers */ cam_vfe_camif_lite_overflow_debug_info(camif_lite_priv); - return; } if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { @@ -1025,6 +1002,33 @@ ife_lite: if (status_2 & 0x800) CAM_INFO(CAM_ISP, "RDI3 CAMIF VIOLATION"); } + +print_state: + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + + CAM_INFO(CAM_ISP, + "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", + (val0 & 0x7FF), (val0 & 0x7F0000) >> 16, + (val1 & 0x7FF), (val1 & 0x7F0000) >> 16, + (val2 & 0x7FF), (val2 & 0x7F0000) >> 16, + (val3 & 0x7FF), (val3 & 0x7F0000) >> 16, + (val4 & 0x7FF), (val4 & 0x7F0000) >> 16); + + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", soc_private->ife_clk_src); + + if ((err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) && + bus_overflow_status) + cam_cpas_log_votes(); + } static int cam_vfe_camif_lite_handle_irq_top_half(uint32_t evt_id, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 27fdde7718c0..67cd7f4cd587 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -915,7 +915,7 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, uint32_t violation_mask = 0x3F, module_id = 0; uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private; - uint32_t val0, val1, val2; + uint32_t val0, val1, val2, val3, val4; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -1000,26 +1000,14 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, if (bus_overflow_status & 0x0200000) CAM_INFO(CAM_ISP, "PDAF BUS OVERFLOW"); - - soc_private = camif_priv->soc_info->soc_private; - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - CAM_INFO(CAM_ISP, - "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", - val0, val1, val2); - cam_cpas_log_votes(); - return; + goto print_state; } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { CAM_INFO(CAM_ISP, "PIXEL PIPE Module hang"); /* print debug registers */ cam_vfe_camif_ver3_overflow_debug_info(camif_priv); - return; + goto print_state; } if (err_type == CAM_VFE_IRQ_STATUS_VIOLATION) { @@ -1243,6 +1231,35 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, break; } } + +print_state: + soc_private = camif_priv->soc_info->soc_private; + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + + CAM_INFO(CAM_ISP, + "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", + (val0 & 0x7FF), (val0 & 0x7F0000) >> 16, + (val1 & 0x7FF), (val1 & 0x7F0000) >> 16, + (val2 & 0x7FF), (val2 & 0x7F0000) >> 16, + (val3 & 0x7FF), (val3 & 0x7F0000) >> 16, + (val4 & 0x7FF), (val4 & 0x7F0000) >> 16); + + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", soc_private->ife_clk_src); + + if ((err_type == CAM_VFE_IRQ_STATUS_OVERFLOW) && + ((camif_priv->cam_common_cfg.input_mux_sel_pp & 0x3) || + (bus_overflow_status))) + cam_cpas_log_votes(); } static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, @@ -1368,7 +1385,9 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, payload->ts.mono_time.tv_sec; camif_priv->sof_ts.tv_usec = payload->ts.mono_time.tv_usec; - } + } + + cam_cpas_notify_event("IFE SOF", evt_info.hw_idx); if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 6a66955ed280..f3a8217dbe6e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -106,6 +106,8 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); if (!rc) { + soc_private->ife_clk_src = max_clk_rate; + top_priv->hw_clk_rate = max_clk_rate; rc = cam_soc_util_get_clk_level(soc_info, max_clk_rate, soc_info->src_clk_idx, &clk_lvl); @@ -609,6 +611,8 @@ int cam_vfe_top_ver3_stop(void *device_priv, struct cam_vfe_top_ver3_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int i, rc = 0; if (!device_priv || !stop_args) { @@ -619,6 +623,8 @@ int cam_vfe_top_ver3_stop(void *device_priv, top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; mux_res = (struct cam_isp_resource_node *)stop_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; if (mux_res->res_id < CAM_ISP_HW_VFE_IN_MAX) { rc = mux_res->stop(mux_res); @@ -641,6 +647,8 @@ int cam_vfe_top_ver3_stop(void *device_priv, } } + soc_private->ife_clk_src = 0; + return rc; } diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 764002d2ac31..80611f9bff3e 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -2488,3 +2488,42 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, end: return rc; } + +/** + * cam_soc_util_print_clk_freq() + * + * @brief: This function gets the clk rates for each clk from clk + * driver and prints in log + * + * @soc_info: Device soc struct to be populated + * + * @return: success or failure + */ +int cam_soc_util_print_clk_freq(struct cam_hw_soc_info *soc_info) +{ + int i; + unsigned long clk_rate = 0; + + if (!soc_info) { + CAM_ERR(CAM_UTIL, "Invalid soc info"); + return -EINVAL; + } + + if ((soc_info->num_clk == 0) || + (soc_info->num_clk >= CAM_SOC_MAX_CLK)) { + CAM_ERR(CAM_UTIL, "[%s] Invalid number of clock %d", + soc_info->dev_name, soc_info->num_clk); + return -EINVAL; + } + + for (i = 0; i < soc_info->num_clk; i++) { + clk_rate = clk_get_rate(soc_info->clk[i]); + + CAM_INFO(CAM_UTIL, + "[%s] idx = %d clk name = %s clk_rate=%lld", + soc_info->dev_name, i, soc_info->clk_name[i], + clk_rate); + } + + return 0; +} diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index a71820a0759e..04e0e9136881 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -687,4 +687,16 @@ int cam_soc_util_reg_dump_to_cmd_buf(void *ctx, struct cam_hw_soc_dump_args *soc_dump_args, bool user_triggered_dump); +/** + * cam_soc_util_print_clk_freq() + * + * @brief: This function gets the clk rates for each clk from clk + * driver and prints in log + * + * @soc_info: Device soc struct to be populated + * + * @return: success or failure + */ +int cam_soc_util_print_clk_freq(struct cam_hw_soc_info *soc_info); + #endif /* _CAM_SOC_UTIL_H_ */ From ca73e251f0e851ac89c50d2863605eb619c37855 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Tue, 25 Aug 2020 04:13:14 -0700 Subject: [PATCH 469/790] msm: camera: utils: Route camera logs to ftrace Add debugfs setting to route camera logs : ERR, WARN, INFO, DBG to ftrace. Add CAM_TRACE macro for adding any new traces in drivers. Usage: CAM_TRACE : By default printed in ftrace CAM_ERR, CAM_WARN, CAM_INFO, CAM_DBG : enable using debugfs debug_type = 1 or 2 For CAM_DBG : In addition to above enable debug_mdl with required mask. adb shell "echo > /sys/module/camera/parameters/debug_type" All CAM_xx (except CAM_TRACE) logs are routed as below : 0 (default) - only logcat 1 - only ftrace 2 - both logcat and ftrace. CRs-Fixed: 2762931 Change-Id: I5254a7fef346c7ba21a3ea1eed21e5353f42fd03 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_utils/cam_debug_util.c | 77 +++++++++++- drivers/cam_utils/cam_debug_util.h | 185 ++++++++++++++++++++--------- drivers/cam_utils/cam_trace.h | 15 +++ 3 files changed, 216 insertions(+), 61 deletions(-) diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index a345947dee58..32b9b2744422 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -6,11 +6,17 @@ #include #include #include +#include "cam_trace.h" #include "cam_debug_util.h" static uint debug_mdl; module_param(debug_mdl, uint, 0644); + +/* 0x0 - only logs, 0x1 - only trace, 0x2 - logs + trace */ +static uint debug_type; +module_param(debug_type, uint, 0644); + struct camera_debug_settings cam_debug; const struct camera_debug_settings *cam_debug_get_settings() @@ -217,6 +223,34 @@ const char *cam_get_module_name(unsigned int module_id) return name; } +const char *cam_get_tag_name(unsigned int tag_id) +{ + const char *name = NULL; + + switch (tag_id) { + case CAM_TYPE_TRACE: + name = "CAM_TRACE"; + break; + case CAM_TYPE_ERR: + name = "CAM_ERR"; + break; + case CAM_TYPE_WARN: + name = "CAM_WARN"; + break; + case CAM_TYPE_INFO: + name = "CAM_INFO"; + break; + case CAM_TYPE_DBG: + name = "CAM_DBG"; + break; + default: + name = "CAM"; + break; + } + + return name; +} + void cam_debug_log(unsigned int module_id, const char *func, const int line, const char *fmt, ...) { @@ -227,10 +261,47 @@ void cam_debug_log(unsigned int module_id, const char *func, const int line, if (debug_mdl & module_id) { vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args); - pr_info("CAM_DBG: %s: %s: %d: %s\n", - cam_get_module_name(module_id), - func, line, str_buffer); + + if ((debug_type == 0) || (debug_type == 2)) { + pr_info("CAM_DBG: %s: %s: %d: %s\n", + cam_get_module_name(module_id), + func, line, str_buffer); + } + + if ((debug_type == 1) || (debug_type == 2)) { + char trace_buffer[STR_BUFFER_MAX_LENGTH]; + + snprintf(trace_buffer, sizeof(trace_buffer), + "%s: %s: %s: %d: %s", + cam_get_tag_name(CAM_TYPE_DBG), + cam_get_module_name(module_id), + func, line, str_buffer); + trace_cam_log_debug(trace_buffer); + } } va_end(args); } + +void cam_debug_trace(unsigned int tag, unsigned int module_id, + const char *func, const int line, const char *fmt, ...) +{ + char str_buffer[STR_BUFFER_MAX_LENGTH]; + va_list args; + + if ((tag == CAM_TYPE_TRACE) || (debug_type == 1) || (debug_type == 2)) { + char trace_buffer[STR_BUFFER_MAX_LENGTH]; + + va_start(args, fmt); + + vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args); + + snprintf(trace_buffer, sizeof(trace_buffer), + "%s: %s: %s: %d: %s", + cam_get_tag_name(tag), cam_get_module_name(module_id), + func, line, str_buffer); + trace_cam_log_debug(trace_buffer); + + va_end(args); + } +} diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index fdeb3e758b66..69bdc6d62d3c 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -8,6 +8,7 @@ #include +/* Module IDs used for debug logging */ #define CAM_CDM (1 << 0) #define CAM_CORE (1 << 1) #define CAM_CPAS (1 << 2) @@ -31,23 +32,22 @@ #define CAM_OIS (1 << 20) #define CAM_RES (1 << 21) #define CAM_MEM (1 << 22) - -/* CAM_IRQ_CTRL: For events in irq controller */ #define CAM_IRQ_CTRL (1 << 23) - -/* CAM_REQ: Tracks a request submitted to KMD */ #define CAM_REQ (1 << 24) - -/* CAM_PERF: Used for performance (clock, BW etc) logs */ #define CAM_PERF (1 << 25) #define CAM_CUSTOM (1 << 26) -#define CAM_OPE (1 << 28) #define CAM_PRESIL (1 << 27) +#define CAM_OPE (1 << 28) +#define CAM_IO_ACCESS (1 << 29) -/* CAM_IO_ACCESS: Tracks IO read/write */ -#define CAM_IO_ACCESS (1 << 29) +/* Log level types */ +#define CAM_TYPE_TRACE (1 << 0) +#define CAM_TYPE_ERR (1 << 1) +#define CAM_TYPE_WARN (1 << 2) +#define CAM_TYPE_INFO (1 << 3) +#define CAM_TYPE_DBG (1 << 4) -#define STR_BUFFER_MAX_LENGTH 1024 +#define STR_BUFFER_MAX_LENGTH 512 /** * struct cam_cpas_debug_settings - Sysfs debug settings for cpas driver @@ -91,6 +91,23 @@ struct camera_debug_settings { void cam_debug_log(unsigned int module_id, const char *func, const int line, const char *fmt, ...); +/* + * cam_debug_trace() + * + * @brief : Get the Module name from module ID and print + * respective debug logs in ftrace + * + * @tag : Tag indicating whether TRACE, ERR, WARN, INFO, DBG + * @module_id : Respective Module ID which is calling this function + * @func : Function which is calling to print logs + * @line : Line number associated with the function which is calling + * to print log + * @fmt : Formatted string which needs to be print in the log + * + */ +void cam_debug_trace(unsigned int tag, unsigned int module_id, + const char *func, const int line, const char *fmt, ...); + /* * cam_get_module_name() * @@ -100,6 +117,20 @@ void cam_debug_log(unsigned int module_id, const char *func, const int line, */ const char *cam_get_module_name(unsigned int module_id); +/* + * CAM_TRACE + * @brief : This Macro will print logs in ftrace + * + * @__module : Respective module id which is been calling this Macro + * @fmt : Formatted string which needs to be print in log + * @args : Arguments which needs to be print in log + */ +#define CAM_TRACE(__module, fmt, args...) \ + ({ \ + cam_debug_trace(CAM_TYPE_TRACE, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) + /* * CAM_ERR * @brief : This Macro will print error logs @@ -108,9 +139,15 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_ERR(__module, fmt, args...) \ - pr_info("CAM_ERR: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_ERR(__module, fmt, args...) \ + ({ \ + pr_info("CAM_ERR: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_ERR, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) + /* * CAM_WARN * @brief : This Macro will print warning logs @@ -119,9 +156,15 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_WARN(__module, fmt, args...) \ - pr_info("CAM_WARN: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_WARN(__module, fmt, args...) \ + ({ \ + pr_info("CAM_WARN: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_ERR, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) + /* * CAM_INFO * @brief : This Macro will print Information logs @@ -130,9 +173,14 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_INFO(__module, fmt, args...) \ - pr_info("CAM_INFO: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_INFO(__module, fmt, args...) \ + ({ \ + pr_info("CAM_INFO: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_INFO, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) /* * CAM_INFO_RATE_LIMIT @@ -142,9 +190,14 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_INFO_RATE_LIMIT(__module, fmt, args...) \ - pr_info_ratelimited("CAM_INFO: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_INFO_RATE_LIMIT(__module, fmt, args...) \ + ({ \ + pr_info_ratelimited("CAM_INFO: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_INFO, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) /* * CAM_DBG @@ -161,9 +214,14 @@ const char *cam_get_module_name(unsigned int module_id); * CAM_ERR_RATE_LIMIT * @brief : This Macro will print error print logs with ratelimit */ -#define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ - pr_info_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ + ({ \ + pr_info_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_INFO, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) /* * CAM_WARN_RATE_LIMIT * @brief : This Macro will print warning logs with ratelimit @@ -172,9 +230,14 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_WARN_RATE_LIMIT(__module, fmt, args...) \ - pr_info_ratelimited("CAM_WARN: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_WARN_RATE_LIMIT(__module, fmt, args...) \ + ({ \ + pr_info_ratelimited("CAM_WARN: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_WARN, __module, __func__, __LINE__, \ + fmt, ##args); \ + }) /* * CAM_WARN_RATE_LIMIT_CUSTOM @@ -186,16 +249,18 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_WARN_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ - ({ \ - static DEFINE_RATELIMIT_STATE(_rs, \ - (interval * HZ), \ - burst); \ - if (__ratelimit(&_rs)) \ - pr_info( \ - "CAM_WARN: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, \ - __LINE__, ##args); \ +#define CAM_WARN_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ + ({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + (interval * HZ), \ + burst); \ + if (__ratelimit(&_rs)) \ + pr_info( \ + "CAM_WARN: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_WARN, __module, __func__, __LINE__, \ + fmt, ##args); \ }) /* @@ -208,16 +273,18 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_INFO_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ - ({ \ - static DEFINE_RATELIMIT_STATE(_rs, \ - (interval * HZ), \ - burst); \ - if (__ratelimit(&_rs)) \ - pr_info( \ - "CAM_INFO: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, \ - __LINE__, ##args); \ +#define CAM_INFO_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ + ({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + (interval * HZ), \ + burst); \ + if (__ratelimit(&_rs)) \ + pr_info( \ + "CAM_INFO: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_INFO, __module, __func__, __LINE__, \ + fmt, ##args); \ }) /* @@ -230,16 +297,18 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_ERR_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ - ({ \ - static DEFINE_RATELIMIT_STATE(_rs, \ - (interval * HZ), \ - burst); \ - if (__ratelimit(&_rs)) \ - pr_info( \ - "CAM_ERR: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, \ - __LINE__, ##args); \ +#define CAM_ERR_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ + ({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + (interval * HZ), \ + burst); \ + if (__ratelimit(&_rs)) \ + pr_info( \ + "CAM_ERR: %s: %s: %d " fmt "\n", \ + cam_get_module_name(__module), __func__, \ + __LINE__, ##args); \ + cam_debug_trace(CAM_TYPE_ERR, __module, __func__, __LINE__, \ + fmt, ##args); \ }) /** diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h index 8868c430684b..51df326068fc 100644 --- a/drivers/cam_utils/cam_trace.h +++ b/drivers/cam_utils/cam_trace.h @@ -86,6 +86,21 @@ TRACE_EVENT(cam_log_event, ) ); +TRACE_EVENT(cam_log_debug, + TP_PROTO(const char *string1), + TP_ARGS(string1), + TP_STRUCT__entry( + __string(string1, string1) + ), + TP_fast_assign( + __assign_str(string1, string1); + ), + TP_printk( + "%s", + __get_str(string1) + ) +); + TRACE_EVENT(cam_icp_fw_dbg, TP_PROTO(char *dbg_message, uint64_t timestamp), TP_ARGS(dbg_message, timestamp), From 86c892ec3aa3828d5259c0982f5ee7a598da9ab9 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Tue, 25 Aug 2020 01:38:54 -0700 Subject: [PATCH 470/790] msm: camera: cpas: Add qosgen shaping config Add qosgen shaping configuration setup. These parameters will be tuned for every chipset along with other QoS settings. CRs-Fixed: 2755917 Change-Id: Ia75e7afc9148ebe94c7cf184de1158b91bee7028 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 6 + drivers/cam_cpas/cpas_top/cpastop_v580_100.h | 258 +++++++++++++++++- .../cam_cpas/cpas_top/cpastop_v580_custom.h | 256 +++++++++++++++++ 3 files changed, 519 insertions(+), 1 deletion(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index f12010116bec..c3ec408c5fb6 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -160,6 +160,9 @@ enum cam_camnoc_port_type { * @danger_lut: Danger LUT mapping for this connection * @safe_lut: Safe LUT mapping for this connection * @ubwc_ctl: UBWC control settings for this connection + * @qosgen_mainctl: qosgen shaping control configuration for this connection + * @qosgen_shaping_low: qosgen shaping low configuration for this connection + * @qosgen_shaping_high: qosgen shaping high configuration for this connection * */ struct cam_camnoc_specific { @@ -172,6 +175,9 @@ struct cam_camnoc_specific { struct cam_cpas_reg safe_lut; struct cam_cpas_reg ubwc_ctl; struct cam_cpas_reg flag_out_set0_low; + struct cam_cpas_reg qosgen_mainctl; + struct cam_cpas_reg qosgen_shaping_low; + struct cam_cpas_reg qosgen_shaping_high; }; /** diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h index d79ca4af21bc..550adc7e0861 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V580_100_H_ @@ -263,6 +263,27 @@ static struct cam_camnoc_specific .ubwc_ctl = { .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x408, /* CDM_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x420, /* CDM_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x424, /* CDM_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_LINEAR, @@ -308,6 +329,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE08, /* IFE_LINEAR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE20, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE24, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_RD, @@ -353,6 +395,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF08, /* IFE_RDI_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF20, /* IFE_RDI_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF24, /* IFE_RDI_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_WR, @@ -398,6 +461,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1808, /* IFE_RDI_WR_0_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1820, /* IFE_RDI_WR_0_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1824, /* IFE_RDI_WR_0_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_WR_1, @@ -443,6 +527,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C08, /* IFE_RDI_WR_1_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C20, /* IFE_RDI_WR_1_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C24, /* IFE_RDI_WR_1_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_UBWC_STATS, @@ -493,6 +598,29 @@ static struct cam_camnoc_specific .offset = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1908, /* IFE_UBWC_STATS_0_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1920, + /* IFE_UBWC_STATS_0_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1924, + /* IFE_UBWC_STATS_0_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_UBWC_STATS_1, @@ -543,6 +671,29 @@ static struct cam_camnoc_specific .offset = 0x7788, /* IFE_UBWC_STATS_1_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C88, /* IFE_UBWC_STATS_1_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7CA0, + /* IFE_UBWC_STATS_1_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7CA4, + /* IFE_UBWC_STATS_1_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IPE0_RD, @@ -594,6 +745,27 @@ static struct cam_camnoc_specific .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2208, /* IPE0_RD_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ + .value = 0x13131313, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x13131313, + }, }, { .port_type = CAM_CAMNOC_IPE1_BPS_RD, @@ -645,6 +817,27 @@ static struct cam_camnoc_specific .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ + .value = 0x24242424, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x24242424, + }, }, { .port_type = CAM_CAMNOC_IPE_BPS_WR, @@ -696,6 +889,27 @@ static struct cam_camnoc_specific .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C08, /* IPE_BPS_WR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C20, /* IPE_BPS_WR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C24, /* IPE_BPS_WR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_JPEG, @@ -738,6 +952,27 @@ static struct cam_camnoc_specific .ubwc_ctl = { .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_ICP, @@ -749,6 +984,27 @@ static struct cam_camnoc_specific .offset = 0x3888, .value = 0x100000, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3488, /* ICP_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34A0, /* ICP_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34A4, /* ICP_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h index 4b97ee206ed2..1e1c6a759565 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h @@ -263,6 +263,27 @@ static struct cam_camnoc_specific .ubwc_ctl = { .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x408, /* CDM_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x420, /* CDM_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x424, /* CDM_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_LINEAR, @@ -308,6 +329,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE08, /* IFE_LINEAR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE20, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE24, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_RD, @@ -353,6 +395,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF08, /* IFE_RDI_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF20, /* IFE_RDI_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF24, /* IFE_RDI_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_WR, @@ -398,6 +461,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1808, /* IFE_RDI_WR_0_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1820, /* IFE_RDI_WR_0_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1824, /* IFE_RDI_WR_0_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_WR_1, @@ -443,6 +527,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C08, /* IFE_RDI_WR_1_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C20, /* IFE_RDI_WR_1_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C24, /* IFE_RDI_WR_1_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_UBWC_STATS, @@ -493,6 +598,29 @@ static struct cam_camnoc_specific .offset = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1908, /* IFE_UBWC_STATS_0_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1920, + /* IFE_UBWC_STATS_0_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1924, + /* IFE_UBWC_STATS_0_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_UBWC_STATS_1, @@ -543,6 +671,29 @@ static struct cam_camnoc_specific .offset = 0x7788, /* IFE_UBWC_STATS_1_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7C88, /* IFE_UBWC_STATS_1_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7CA0, + /* IFE_UBWC_STATS_1_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7CA4, + /* IFE_UBWC_STATS_1_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IPE0_RD, @@ -594,6 +745,27 @@ static struct cam_camnoc_specific .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2208, /* IPE0_RD_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ + .value = 0x13131313, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x13131313, + }, }, { .port_type = CAM_CAMNOC_IPE1_BPS_RD, @@ -645,6 +817,27 @@ static struct cam_camnoc_specific .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ + .value = 0x24242424, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x24242424, + }, }, { .port_type = CAM_CAMNOC_IPE_BPS_WR, @@ -696,6 +889,27 @@ static struct cam_camnoc_specific .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C08, /* IPE_BPS_WR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C20, /* IPE_BPS_WR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C24, /* IPE_BPS_WR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_JPEG, @@ -738,6 +952,27 @@ static struct cam_camnoc_specific .ubwc_ctl = { .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_ICP, @@ -749,6 +984,27 @@ static struct cam_camnoc_specific .offset = 0x3888, .value = 0x100000, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3488, /* ICP_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34A0, /* ICP_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34A4, /* ICP_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, }; From 3de038d4a67dea3fb25264ac8e81cb9d36ca241d Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Wed, 26 Aug 2020 23:00:38 +0800 Subject: [PATCH 471/790] msm: camera: reqmgr: Workqueue congestion handling When workqueue is congested, CRM may apply same request to device which will trigger recovery due to apply fails. This change prevent CRM triggering recovery if the current idx is same with last applied idx. CRs-Fixed: 2761601 Change-Id: I6ccf44f050a18e8a2a35916f61513ad852e7bdee Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 3119298468e4..208037c255f6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1694,18 +1694,24 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger, &dev); if (rc < 0) { - /* Apply req failed retry at next sof */ - slot->status = CRM_SLOT_STATUS_REQ_PENDING; + if (in_q->last_applied_idx < in_q->rd_idx) { + /* Apply req failed retry at next sof */ + slot->status = CRM_SLOT_STATUS_REQ_PENDING; - link->retry_cnt++; - if (link->retry_cnt == MAXIMUM_RETRY_ATTEMPTS) { - CAM_DBG(CAM_CRM, - "Max retry attempts reached on link[0x%x] for req [%lld]", - link->link_hdl, - in_q->slot[in_q->rd_idx].req_id); - __cam_req_mgr_notify_error_on_link(link, dev); - link->retry_cnt = 0; - } + link->retry_cnt++; + if (link->retry_cnt == MAXIMUM_RETRY_ATTEMPTS) { + CAM_DBG(CAM_CRM, + "Max retry attempts reached on link[0x%x] for req [%lld]", + link->link_hdl, + in_q->slot[in_q->rd_idx].req_id); + __cam_req_mgr_notify_error_on_link(link, dev); + link->retry_cnt = 0; + } + } else + CAM_WARN(CAM_CRM, + "workqueue congestion, last applied idx:%d rd idx:%d", + in_q->last_applied_idx, + in_q->rd_idx); } else { if (link->retry_cnt) link->retry_cnt = 0; From ecd191e638fd3da93a178ed1e3e26a5c8841598c Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Tue, 19 May 2020 17:56:17 -0700 Subject: [PATCH 472/790] msm: camera: icp: Teach A5 to power resume/collapse via its hw_ops The LX7 processor will require a new mechanism to resume/collapse. Make the current mechanism transparent to the ICP HW manager in preparation for the new proc. By going through the hw_ops we let the device interface decide which mechanism to use. CRs-Fixed: 2722486 Change-Id: I719314b3f505270a33892cb247082e43dad2e92d Signed-off-by: Fernando Pacheco --- drivers/cam_icp/fw_inc/hfi_intf.h | 19 +--- drivers/cam_icp/fw_inc/hfi_reg.h | 28 ----- drivers/cam_icp/hfi.c | 93 +--------------- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 65 ++++++++++++ drivers/cam_icp/icp_hw/a5_hw/a5_reg.h | 29 +++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 100 +++++++++++------- 6 files changed, 162 insertions(+), 172 deletions(-) create mode 100644 drivers/cam_icp/icp_hw/a5_hw/a5_reg.h diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 6a5ec8482457..062762306454 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -73,12 +73,11 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); * @event_driven_mode: event mode * @hfi_mem: hfi memory info * @icp_base: icp base address - * @debug: debug flag * * Returns success(zero)/failure(non zero) */ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void *__iomem icp_base, bool debug); + void *__iomem icp_base); /** * hfi_get_hw_caps() - hardware capabilities from firmware @@ -96,18 +95,6 @@ int hfi_get_hw_caps(void *query_caps); */ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); -/** - * cam_hfi_enable_cpu() - enable A5 CPU - * @icp_base: icp base address - */ -void cam_hfi_enable_cpu(void __iomem *icp_base); - -/** - * cam_hfi_disable_cpu() - disable A5 CPU - * @icp_base: icp base address - */ -void cam_hfi_disable_cpu(void __iomem *icp_base); - /** * cam_hfi_deinit() - cleanup HFI */ @@ -154,12 +141,10 @@ int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg); * cam_hfi_resume() - function to resume * @hfi_mem: hfi memory info * @icp_base: icp base address - * @debug: debug flag * * Returns success(zero)/failure(non zero) */ -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, - void __iomem *icp_base, bool debug); +int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base); /** * cam_hfi_queue_dump() - utility function to dump hfi queues diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index 200bfe6bc2b1..cf928ed1db43 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -9,21 +9,10 @@ #include #include "hfi_intf.h" - /* start of ICP CSR registers */ #define HFI_REG_A5_HW_VERSION 0x0 -#define HFI_REG_A5_CSR_NSEC_RESET 0x4 -#define HFI_REG_A5_CSR_A5_CONTROL 0x8 -#define HFI_REG_A5_CSR_ETM 0xC #define HFI_REG_A5_CSR_A2HOSTINTEN 0x10 -#define HFI_REG_A5_CSR_A2HOSTINT 0x14 -#define HFI_REG_A5_CSR_A2HOSTINTCLR 0x18 -#define HFI_REG_A5_CSR_A2HOSTINTSTATUS 0x1C -#define HFI_REG_A5_CSR_A2HOSTINTSET 0x20 #define HFI_REG_A5_CSR_HOST2ICPINT 0x30 -#define HFI_REG_A5_CSR_A5_STATUS 0x200 -#define HFI_REG_A5_QGIC2_LM_ID 0x204 -#define HFI_REG_A5_SPARE 0x400 /* general purpose registers from */ #define HFI_REG_FW_VERSION 0x44 @@ -44,23 +33,6 @@ /* end of ICP CSR registers */ -/* flags for ICP CSR registers */ -#define ICP_FLAG_CSR_WAKE_UP_EN (1 << 4) -#define ICP_FLAG_CSR_A5_EN (1 << 9) -#define ICP_CSR_EN_CLKGATE_WFI (1 << 12) -#define ICP_CSR_EDBGRQ (1 << 14) -#define ICP_CSR_DBGSWENABLE (1 << 22) -#define ICP_CSR_A5_STATUS_WFI (1 << 7) - -#define ICP_FLAG_A5_CTRL_DBG_EN (ICP_FLAG_CSR_WAKE_UP_EN|\ - ICP_FLAG_CSR_A5_EN|\ - ICP_CSR_EDBGRQ|\ - ICP_CSR_DBGSWENABLE) - -#define ICP_FLAG_A5_CTRL_EN (ICP_FLAG_CSR_WAKE_UP_EN|\ - ICP_FLAG_CSR_A5_EN|\ - ICP_CSR_EN_CLKGATE_WFI) - /* start of Queue table and queues */ #define MAX_ICP_HFI_QUEUES 4 #define ICP_QHDR_TX_TYPE_MASK 0xFF000000 diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index b62cdf1fa9f7..f88450aad166 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -34,9 +34,6 @@ #define HFI_POLL_DELAY_US 100 #define HFI_POLL_TIMEOUT_US 10000 -#define HFI_MAX_PC_POLL_TRY 150 -#define HFI_POLL_TRY_SLEEP 1 - static struct hfi_info *g_hfi; unsigned int g_icp_mmu_hdl; static DEFINE_MUTEX(hfi_cmd_q_mutex); @@ -542,75 +539,13 @@ int hfi_get_hw_caps(void *query_buf) return 0; } -void cam_hfi_disable_cpu(void __iomem *icp_base) -{ - uint32_t data; - uint32_t val; - uint32_t try = 0; - - 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) - break; - /* Need to poll here to confirm that FW is going trigger wfi - * and Host can the proceed. No interrupt is expected from FW - * at this time. - */ - usleep_range(HFI_POLL_TRY_SLEEP * 1000, - (HFI_POLL_TRY_SLEEP * 1000) + 1000); - try++; - } - - val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL); - val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN); - cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL); - - val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET); - cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET); - - cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET, - icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); - cam_io_w_mb((uint32_t)INTR_DISABLE, - icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); -} - -void cam_hfi_enable_cpu(void __iomem *icp_base) -{ - cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - cam_io_w_mb((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET); -} - -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, - void __iomem *icp_base, bool debug) +int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) { int rc = 0; - uint32_t data; uint32_t fw_version, status = 0; - cam_hfi_enable_cpu(icp_base); g_hfi->csr_base = icp_base; - if (debug) { - cam_io_w_mb(ICP_FLAG_A5_CTRL_DBG_EN, - (icp_base + HFI_REG_A5_CSR_A5_CONTROL)); - - /* Barrier needed as next write should be done after - * sucessful previous write. Next write enable clock - * gating - */ - wmb(); - - cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - - } else { - cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - } - if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, status, status == ICP_INIT_RESP_SUCCESS, HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { @@ -625,9 +560,6 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version); - data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS); - CAM_DBG(CAM_HFI, "wfi status = %x", (int)data); - cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR); cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova, icp_base + HFI_REG_SFR_PTR); @@ -661,7 +593,7 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, } int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void __iomem *icp_base, bool debug) + void __iomem *icp_base) { int rc = 0; struct hfi_qtbl *qtbl; @@ -688,27 +620,6 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map)); g_hfi->hfi_state = HFI_DEINIT; - if (debug) { - cam_io_w_mb( - (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN | - ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE), - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - msleep(100); - cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN | - ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI), - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - } else { - /* Due to hardware bug in V1 ICP clock gating has to be - * disabled, this is supposed to be fixed in V-2. But enabling - * the clock gating is causing the firmware hang, hence - * disabling the clock gating on both V1 and V2 until the - * hardware team root causes this - */ - cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN | - ICP_FLAG_CSR_WAKE_UP_EN | - ICP_CSR_EN_CLKGATE_WFI, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - } qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; qtbl_hdr = &qtbl->q_tbl_hdr; diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 1ac27511f7ac..6b257392a3ec 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -13,12 +13,14 @@ #include #include #include +#include #include #include "cam_io_util.h" #include "cam_a5_hw_intf.h" #include "cam_hw.h" #include "cam_hw_intf.h" #include "a5_core.h" +#include "a5_reg.h" #include "a5_soc.h" #include "cam_soc_util.h" #include "cam_io_util.h" @@ -28,6 +30,9 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" +#define PC_POLL_DELAY_US 100 +#define PC_POLL_TIMEOUT_US 10000 + static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info, struct cam_icp_cpas_vote *cpas_vote) { @@ -388,6 +393,60 @@ int cam_a5_deinit_hw(void *device_priv, return rc; } +static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) +{ + uint32_t val = A5_CSR_FULL_CPU_EN; + void __iomem *base; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return -EINVAL; + } + + base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + + cam_io_w_mb(A5_CSR_A5_CPU_EN, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + cam_io_w_mb(A5_CSR_FUNC_RESET, base + ICP_SIERRA_A5_CSR_NSEC_RESET); + + if (debug_enabled) + val |= A5_CSR_FULL_DBG_EN; + + cam_io_w_mb(val, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + + return 0; +} + +static int cam_a5_power_collapse(struct cam_hw_info *a5_info) +{ + uint32_t val, status = 0; + void __iomem *base; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return -EINVAL; + } + + base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + + /** + * Need to poll here to confirm that FW has triggered WFI + * and Host can then proceed. No interrupt is expected + * from FW at this time. + */ + if (readl_poll_timeout(base + ICP_SIERRA_A5_CSR_A5_STATUS, + status, status & A5_CSR_A5_STANDBYWFI, + PC_POLL_DELAY_US, PC_POLL_TIMEOUT_US)) { + CAM_ERR(CAM_ICP, "WFI poll timed out: status=0x%08x", status); + return -ETIMEDOUT; + } + + val = cam_io_r(base + ICP_SIERRA_A5_CSR_A5_CONTROL); + val &= ~(A5_CSR_A5_CPU_EN | A5_CSR_WAKE_UP_EN); + cam_io_w_mb(val, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + + return 0; +} + irqreturn_t cam_a5_irq(int irq_num, void *data) { struct cam_hw_info *a5_dev = data; @@ -458,6 +517,12 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_A5_CMD_FW_DOWNLOAD: rc = cam_a5_download_fw(device_priv); break; + case CAM_ICP_A5_CMD_POWER_COLLAPSE: + rc = cam_a5_power_collapse(a5_dev); + break; + case CAM_ICP_A5_CMD_POWER_RESUME: + rc = cam_a5_power_resume(a5_dev, *((bool *)cmd_args)); + break; case CAM_ICP_A5_CMD_SET_FW_BUF: { struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args; diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h new file mode 100644 index 000000000000..049748adbe1a --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_A5_REG_H_ +#define _CAM_A5_REG_H_ + +#define ICP_SIERRA_A5_CSR_NSEC_RESET 0x4 +#define A5_CSR_FUNC_RESET (1 << 4) +#define A5_CSR_DBG_RESET (1 << 3) +#define A5_CSR_CPU_RESET (1 << 2) + +#define ICP_SIERRA_A5_CSR_A5_CONTROL 0x8 +#define A5_CSR_DBGSWENABLE (1 << 22) +#define A5_CSR_EDBGRQ (1 << 14) +#define A5_CSR_EN_CLKGATE_WFI (1 << 12) +#define A5_CSR_A5_CPU_EN (1 << 9) +#define A5_CSR_WAKE_UP_EN (1 << 4) + +#define A5_CSR_FULL_DBG_EN (A5_CSR_DBGSWENABLE | A5_CSR_EDBGRQ) +#define A5_CSR_FULL_CPU_EN (A5_CSR_A5_CPU_EN | \ + A5_CSR_WAKE_UP_EN | \ + A5_CSR_EN_CLKGATE_WFI) + +#define ICP_SIERRA_A5_CSR_A5_STATUS 0x200 +#define A5_CSR_A5_STANDBYWFI (1 << 7) + +#endif /* _CAM_A5_REG_H_ */ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 3ba173281027..9be1a940fe6d 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3054,32 +3054,63 @@ static int cam_icp_mgr_hw_close_k(void *hw_priv, void *hw_close_args) } -static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) +static int cam_icp_mgr_proc_resume(struct cam_icp_hw_mgr *hw_mgr) { - int rc; - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; + struct cam_hw_intf *icp_dev_intf = hw_mgr->a5_dev_intf; - CAM_DBG(CAM_PERF, "ENTER"); - - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); + if (!icp_dev_intf) return -EINVAL; - } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + + return icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_A5_CMD_POWER_RESUME, + &hw_mgr->a5_jtag_debug, + sizeof(hw_mgr->a5_jtag_debug)); +} + +static void cam_icp_mgr_proc_suspend(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *icp_dev_intf = hw_mgr->a5_dev_intf; + + if (!icp_dev_intf) + return; + + icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_A5_CMD_POWER_COLLAPSE, + NULL, 0); +} + +static int __power_collapse(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; if (!hw_mgr->icp_pc_flag || atomic_read(&hw_mgr->recovery)) { - cam_hfi_disable_cpu( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_icp_mgr_proc_suspend(hw_mgr); rc = cam_icp_mgr_hw_close_k(hw_mgr, NULL); } else { CAM_DBG(CAM_PERF, "Sending PC prep ICP PC enabled"); rc = cam_icp_mgr_send_pc_prep(hw_mgr); - cam_hfi_disable_cpu( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_icp_mgr_proc_suspend(hw_mgr); } + + return rc; +} + +static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *a5_dev_intf = hw_mgr->a5_dev_intf; + int rc; + + CAM_DBG(CAM_PERF, "ENTER"); + + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "A5 device interface is NULL"); + return -EINVAL; + } + + rc = __power_collapse(hw_mgr); + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + CAM_DBG(CAM_PERF, "EXIT"); return rc; @@ -3173,8 +3204,7 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.len); return cam_hfi_resume(&hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, - hw_mgr->a5_jtag_debug); + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); } static int cam_icp_retry_wait_for_abort( @@ -3550,7 +3580,6 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) { int rc; struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct cam_icp_a5_set_irq_cb irq_cb; struct cam_icp_a5_set_fw_buf_info fw_buf_info; @@ -3559,7 +3588,6 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; irq_cb.icp_hw_mgr_cb = cam_icp_hw_mgr_cb; irq_cb.data = hw_mgr; @@ -3568,7 +3596,7 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) CAM_ICP_A5_SET_IRQ_CB, &irq_cb, sizeof(irq_cb)); if (rc) - goto set_irq_failed; + return rc; fw_buf_info.kva = icp_hw_mgr.hfi_mem.fw_buf.kva; fw_buf_info.iova = icp_hw_mgr.hfi_mem.fw_buf.iova; @@ -3579,22 +3607,16 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) CAM_ICP_A5_CMD_SET_FW_BUF, &fw_buf_info, sizeof(fw_buf_info)); if (rc) - goto set_irq_failed; - - cam_hfi_enable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + return rc; rc = a5_dev_intf->hw_ops.process_cmd( a5_dev_intf->hw_priv, CAM_ICP_A5_CMD_FW_DOWNLOAD, NULL, 0); if (rc) - goto fw_download_failed; + return rc; - return rc; -fw_download_failed: - cam_hfi_disable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); -set_irq_failed: - return rc; + return cam_icp_mgr_proc_resume(hw_mgr); } static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) @@ -3667,8 +3689,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) } return cam_hfi_init(0, &hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, - hw_mgr->a5_jtag_debug); + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) @@ -3760,14 +3781,22 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) if (rc) return -EINVAL; + rc = cam_icp_mgr_proc_resume(hw_mgr); + if (rc) + goto hw_deinit; + rc = cam_icp_mgr_hfi_resume(hw_mgr); if (rc) - goto hfi_resume_failed; + goto power_collapse; CAM_DBG(CAM_ICP, "Exit"); return rc; -hfi_resume_failed: - cam_icp_mgr_icp_power_collapse(hw_mgr); + +power_collapse: + __power_collapse(hw_mgr); +hw_deinit: + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + return rc; } @@ -3843,8 +3872,7 @@ fw_init_failed: cam_hfi_deinit( a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); hfi_init_failed: - cam_hfi_disable_cpu( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_icp_mgr_proc_suspend(hw_mgr); fw_download_failed: cam_icp_mgr_device_deinit(hw_mgr); dev_init_fail: From 762751a88cd4dd3a9f8afc4ae04350251e0a164f Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 3 Aug 2020 19:16:27 +0530 Subject: [PATCH 473/790] msm: camera: ife: Configure epoch to exactly half of the frame Some customers have sensor mode with more blanking width. Due to this, time is not sufficient for applying setting thus resulted in frame drops. To avoid this situation, epoch is calculated on complete frame and configured at half the frame. CRs-Fixed: 2757095 Change-Id: I92927c23762f717d6ddca67a7e641422e8fb6d8f Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 67 +++++++++++++++++++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 15 +++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 15 ++++- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c | 3 + .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 3 + .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 33 ++++++++- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 29 +++++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c | 37 ++++++++-- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 28 ++++++++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 29 ++++++++ include/uapi/camera/media/cam_isp.h | 12 ++++ 12 files changed, 263 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 196a558799d3..0780034df25c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -49,6 +49,7 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = { CAM_ISP_HW_CMD_CORE_CONFIG, CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, CAM_ISP_HW_CMD_BW_UPDATE_V2, + CAM_ISP_HW_CMD_BLANKING_UPDATE, }; static struct cam_ife_hw_mgr g_ife_hw_mgr; @@ -5577,6 +5578,53 @@ static int cam_isp_blob_csid_config_update( return rc; } + +static int cam_isp_blob_sensor_blanking_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_sensor_blanking_config *sensor_blanking_config, + struct cam_hw_prepare_update_args *prepare) + +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_blanking_config blanking_config; + int rc = 0, i; + + ctx = prepare->ctxt_to_hw_map; + if (list_empty(&ctx->res_list_ife_src)) { + CAM_ERR(CAM_ISP, "Mux List empty"); + return -ENODEV; + } + + 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; + + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + blanking_config.node_res = hw_mgr_res->hw_res[i]; + blanking_config.vbi = sensor_blanking_config->vbi; + blanking_config.hbi = sensor_blanking_config->hbi; + + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_BLANKING_UPDATE, + &blanking_config, + sizeof( + struct cam_isp_blanking_config)); + if (rc) + CAM_ERR(CAM_ISP, + "blanking update failed"); + } + } + } + return rc; +} + static int cam_isp_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { @@ -6057,6 +6105,25 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "CSID Config failed rc: %d", rc); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG: { + struct cam_isp_sensor_blanking_config *sensor_blanking_config; + + if (blob_size < sizeof(struct cam_isp_sensor_blanking_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %zu expected %zu", + blob_size, + sizeof(struct cam_isp_sensor_blanking_config)); + return -EINVAL; + } + sensor_blanking_config = + (struct cam_isp_sensor_blanking_config *)blob_data; + + rc = cam_isp_blob_sensor_blanking_config(blob_type, blob_info, + sensor_blanking_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, + "Epoch Configuration Update Failed rc:%d", rc); + } + break; case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG: { struct cam_isp_sensor_config *csid_dim_config; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 03e76b627d8b..443d1550772d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -124,6 +124,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, CAM_ISP_HW_CMD_GET_RES_FOR_MID, + CAM_ISP_HW_CMD_BLANKING_UPDATE, CAM_ISP_HW_CMD_MAX, }; @@ -178,6 +179,20 @@ struct cam_isp_resource_node { CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; }; +/* + * struct cam_isp_blanking_config: + * + * @Brief: Structure to pass blanking details + * @hbi: HBI Value + * @vbi: VBI Value + * node_res: Pointer to Resource Node object + */ +struct cam_isp_blanking_config { + uint32_t hbi; + uint32_t vbi; + struct cam_isp_resource_node *node_res; +}; + /* * struct cam_isp_hw_event_info: * diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index f4b7d669e800..c1914ec97686 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -79,6 +79,8 @@ struct cam_tfe_camif_data { uint32_t camif_debug; uint32_t camif_pd_enable; uint32_t dual_tfe_sync_sel; + uint32_t hbi_value; + uint32_t vbi_value; }; struct cam_tfe_rdi_data { @@ -265,6 +267,10 @@ static void cam_tfe_log_tfe_in_debug_status( "Acquired line start:0x%x line end:0x%x", camif_data->first_line, camif_data->last_line); + CAM_INFO(CAM_ISP, "vbi_value:0x%x hbi_value:0x%x", + camif_data->vbi_value, + camif_data->hbi_value); + } else if ((top_priv->in_rsrc[i].res_id >= CAM_ISP_HW_TFE_IN_RDI0) || (top_priv->in_rsrc[i].res_id <= @@ -1815,6 +1821,10 @@ int cam_tfe_top_reserve(void *device_priv, acquire_args->in_port->line_start; camif_data->last_line = acquire_args->in_port->line_end; + camif_data->vbi_value = + acquire_args->in_port->sensor_vbi; + camif_data->hbi_value = + acquire_args->in_port->sensor_hbi; camif_data->camif_pd_enable = acquire_args->camif_pd_enable; camif_data->dual_tfe_sync_sel = @@ -1978,9 +1988,12 @@ static int cam_tfe_camif_resource_start( } /* Epoch config */ - epoch0_irq_mask = ((rsrc_data->last_line - + epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) - rsrc_data->first_line) / 2) + rsrc_data->first_line; + if (epoch0_irq_mask > rsrc_data->last_line) + epoch0_irq_mask = rsrc_data->last_line; + epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; computed_epoch_line_cfg = (epoch0_irq_mask << 16) | diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 158190296478..b741cc153732 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -601,6 +601,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_ADD_WAIT: case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: case CAM_ISP_HW_CMD_CAMIF_DATA: + case CAM_ISP_HW_CMD_BLANKING_UPDATE: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c index ad4e7eca7186..1c2f03c28e85 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -371,6 +371,9 @@ static int cam_vfe_camif_lite_process_cmd( break; case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = 0; + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index 1cc89c32013a..be5c41976098 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -772,6 +772,9 @@ static int cam_vfe_camif_lite_process_cmd( rsrc_node->res_priv; camif_lite_priv->camif_debug = *((uint32_t *)cmd_args); break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = 0; + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 1f7824763cfe..6b7efaa2c4cf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -45,6 +45,8 @@ struct cam_vfe_mux_camif_data { uint32_t first_line; uint32_t last_pixel; uint32_t last_line; + uint32_t hbi_value; + uint32_t vbi_value; bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; @@ -269,6 +271,8 @@ int cam_vfe_camif_ver2_acquire_resource( camif_data->event_cb = acquire_data->event_cb; camif_data->priv = acquire_data->priv; camif_data->is_dual = acquire_data->vfe_in.is_dual; + camif_data->hbi_value = 0; + camif_data->vbi_value = 0; if (acquire_data->vfe_in.is_dual) camif_data->dual_hw_idx = @@ -420,9 +424,13 @@ static int cam_vfe_camif_resource_start( rsrc_data->camif_reg->epoch_irq); break; default: - epoch0_irq_mask = ((rsrc_data->last_line - + epoch0_irq_mask = (((rsrc_data->last_line + + rsrc_data->vbi_value) - rsrc_data->first_line) / 2) + rsrc_data->first_line; + if (epoch0_irq_mask > rsrc_data->last_line) + epoch0_irq_mask = rsrc_data->last_line; + epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; computed_epoch_line_cfg = (epoch0_irq_mask << 16) | @@ -431,10 +439,11 @@ static int cam_vfe_camif_resource_start( rsrc_data->mem_base + rsrc_data->camif_reg->epoch_irq); CAM_DBG(CAM_ISP, "first_line: %u\n" - "last_line: %u\n" + "last_line: %u vbi: %u\n" "epoch_line_cfg: 0x%x", rsrc_data->first_line, rsrc_data->last_line, + rsrc_data->vbi_value, computed_epoch_line_cfg); break; } @@ -669,6 +678,23 @@ int cam_vfe_camif_dump_timestamps( return 0; } +static int cam_vfe_camif_blanking_update( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_data *camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + + struct cam_isp_blanking_config *blanking_config = + (struct cam_isp_blanking_config *)cmd_args; + + camif_priv->hbi_value = blanking_config->hbi; + camif_priv->vbi_value = blanking_config->vbi; + + CAM_DBG(CAM_ISP, "hbi:%d vbi:%d", + camif_priv->hbi_value, camif_priv->vbi_value); + return 0; +} + static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -696,6 +722,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_CAMIF_DATA: rc = cam_vfe_camif_dump_timestamps(rsrc_node, cmd_args); break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = cam_vfe_camif_blanking_update(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 67cd7f4cd587..f5e2f7a0ea15 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -48,6 +48,8 @@ struct cam_vfe_mux_camif_ver3_data { uint32_t first_line; uint32_t last_pixel; uint32_t last_line; + uint32_t hbi_value; + uint32_t vbi_value; bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; @@ -276,6 +278,8 @@ int cam_vfe_camif_ver3_acquire_resource( camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin; camif_data->horizontal_bin = acquire_data->vfe_in.in_port->horizontal_bin; + camif_data->hbi_value = 0; + camif_data->vbi_value = 0; if (camif_data->is_dual) camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx; @@ -464,8 +468,11 @@ static int cam_vfe_camif_ver3_resource_start( case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: case CAM_CPAS_TITAN_570_V200: - epoch0_line_cfg = (rsrc_data->last_line - + epoch0_line_cfg = ((rsrc_data->last_line + + rsrc_data->vbi_value) - rsrc_data->first_line) / 4; + if (epoch0_line_cfg > rsrc_data->last_line) + epoch0_line_cfg = rsrc_data->last_line; /* epoch line cfg will still be configured at midpoint of the * frame width. We use '/ 4' instead of '/ 2' * cause it is multipixel path @@ -811,6 +818,23 @@ int cam_vfe_camif_ver3_dump_timestamps( return 0; } +static int cam_vfe_camif_ver3_blanking_update( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv = + (struct cam_vfe_mux_camif_ver3_data *)rsrc_node->res_priv; + + struct cam_isp_blanking_config *blanking_config = + (struct cam_isp_blanking_config *)cmd_args; + + camif_priv->hbi_value = blanking_config->hbi; + camif_priv->vbi_value = blanking_config->vbi; + + CAM_DBG(CAM_ISP, "hbi:%d vbi:%d", + camif_priv->hbi_value, camif_priv->vbi_value); + return 0; +} + static int cam_vfe_camif_ver3_process_cmd( struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -850,6 +874,9 @@ static int cam_vfe_camif_ver3_process_cmd( case CAM_ISP_HW_CMD_CAMIF_DATA: rc = cam_vfe_camif_ver3_dump_timestamps(rsrc_node, cmd_args); break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = cam_vfe_camif_ver3_blanking_update(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c index 7815da674872..85868105bb74 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -36,6 +36,8 @@ struct cam_vfe_mux_fe_data { uint32_t first_line; uint32_t last_pixel; uint32_t last_line; + uint32_t hbi_value; + uint32_t vbi_value; bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t fe_cfg_data; @@ -179,6 +181,8 @@ int cam_vfe_fe_ver1_acquire_resource( 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; + fe_data->hbi_value = 0; + fe_data->vbi_value = 0; CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d", fe_res->hw_intf->hw_idx, @@ -302,16 +306,19 @@ static int cam_vfe_fe_resource_start( 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; + epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) - + rsrc_data->first_line) / 2) + rsrc_data->first_line; + if (epoch0_irq_mask > rsrc_data->last_line) + epoch0_irq_mask = rsrc_data->last_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", + CAM_DBG(CAM_ISP, + "first_line:0x%x last_line:0x%x vbi:0x%x epoch_line_cfg: 0x%x", rsrc_data->first_line, rsrc_data->last_line, - computed_epoch_line_cfg); + rsrc_data->vbi_value, computed_epoch_line_cfg); fe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; @@ -446,6 +453,23 @@ static int cam_vfe_fe_sof_irq_debug( return 0; } +static int cam_vfe_fe_blanking_update( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_fe_data *fe_priv = + (struct cam_vfe_mux_fe_data *)rsrc_node->res_priv; + + struct cam_isp_blanking_config *blanking_config = + (struct cam_isp_blanking_config *)cmd_args; + + fe_priv->hbi_value = blanking_config->hbi; + fe_priv->vbi_value = blanking_config->vbi; + CAM_DBG(CAM_ISP, "hbi:%d vbi:%d", + fe_priv->hbi_value, fe_priv->vbi_value); + + 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) { @@ -467,6 +491,9 @@ static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD: rc = cam_vfe_fe_update(rsrc_node, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = cam_vfe_fe_blanking_update(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 6e1ae838bca3..1e5f66df4c1c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -169,6 +169,31 @@ static int cam_vfe_top_clock_update( return rc; } +static int cam_vfe_top_blanking_update(uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_blanking_config *blanking_config = NULL; + struct cam_isp_resource_node *node_res = NULL; + + blanking_config = + (struct cam_isp_blanking_config *)cmd_args; + node_res = blanking_config->node_res; + + if (!node_res) { + CAM_ERR(CAM_PERF, "Invalid input res %pK", node_res); + return -EINVAL; + } + + if (!node_res->process_cmd) { + CAM_ERR(CAM_PERF, "Invalid input res process_cmd %pK", + node_res->process_cmd); + return -EINVAL; + } + + return node_res->process_cmd(node_res, + cmd_type, cmd_args, arg_size); +} + static int cam_vfe_top_mux_get_reg_update( struct cam_vfe_top_ver2_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -795,6 +820,9 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = cam_vfe_top_blanking_update(cmd_type, cmd_args, arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index f3a8217dbe6e..9bd442f8d96e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -189,6 +189,31 @@ static int cam_vfe_top_ver3_clock_update( return rc; } +static int cam_vfe_top_ver3_blanking_update(uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_blanking_config *blanking_config = NULL; + struct cam_isp_resource_node *node_res = NULL; + + blanking_config = + (struct cam_isp_blanking_config *)cmd_args; + node_res = blanking_config->node_res; + + if (!node_res) { + CAM_ERR(CAM_PERF, "Invalid input res %pK", node_res); + return -EINVAL; + } + + if (!node_res->process_cmd) { + CAM_ERR(CAM_PERF, "Invalid input res process_cmd %pK", + node_res->process_cmd); + return -EINVAL; + } + + return node_res->process_cmd(node_res, + cmd_type, cmd_args, arg_size); +} + static int cam_vfe_core_config_control( struct cam_vfe_top_ver3_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -727,6 +752,10 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_BLANKING_UPDATE: + rc = cam_vfe_top_ver3_blanking_update(cmd_type, + cmd_args, arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type); diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index 5e0acdf496e0..d99e0476fc18 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -107,6 +107,7 @@ #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG 10 #define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG 11 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG 12 +#define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG 13 #define CAM_ISP_VC_DT_CFG 4 @@ -616,6 +617,17 @@ struct cam_isp_sensor_dimension { __u32 measure_enabled; } __attribute__((packed)); +/** + * struct cam_isp_sensor_blanking_config + * + * @hbi HBI value + * @vbi VBI value + */ +struct cam_isp_sensor_blanking_config { + __u32 hbi; + __u32 vbi; +} __attribute__((packed)); + /** * struct cam_isp_sensor_config - Sensor Dimension configuration * From 55a25c185b62b278f200988bdabc9f3f909aa352 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 20 Aug 2020 11:43:41 -0700 Subject: [PATCH 474/790] msm: camera: csiphy: Add logic to program userspace settle count Currently settle count is programmed from hardware register data value metioned in bring up sequence. It is more reliable and suitable to program the value coming from userspace as that value is more accurate with respect to sensor specific datarate. This change add logic to accomplish that operation. CRs-Fixed: 2759031 Change-Id: I87215b206632d15e2d51d6383345d2ffa16b6b9f Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 4230a12fc0c7..ad151aa817ed 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -520,6 +520,11 @@ static int cam_csiphy_cphy_data_rate_config( uint32_t lane_enable = 0; uint8_t lane_cnt = 0; uint16_t lane_assign = 0; + uint64_t intermediate_var = 0; + uint16_t settle_cnt = 0; + uint32_t reg_addr = 0, reg_data = 0, reg_param_type = 0; + uint8_t skew_cal_enable = 0; + int32_t delay = 0; if ((csiphy_device == NULL) || (csiphy_device->ctrl_reg == NULL) || @@ -538,6 +543,12 @@ static int cam_csiphy_cphy_data_rate_config( settings_table->num_data_rate_settings; lane_cnt = csiphy_device->csiphy_info[idx].lane_cnt; + intermediate_var = csiphy_device->csiphy_info[idx].settle_time; + do_div(intermediate_var, 200000000); + settle_cnt = intermediate_var; + skew_cal_enable = + csiphy_device->csiphy_info[idx].mipi_flags & SKEW_CAL_MASK; + CAM_DBG(CAM_CSIPHY, "required data rate : %llu", phy_data_rate); for (data_rate_idx = 0; data_rate_idx < num_table_entries; data_rate_idx++) { @@ -574,15 +585,43 @@ static int cam_csiphy_cphy_data_rate_config( per_lane = &drate_settings[data_rate_idx].per_lane_info[lane_idx]; for (i = 0; i < num_reg_entries; i++) { - uint32_t reg_addr = - per_lane->csiphy_data_rate_regs[i].reg_addr; - - uint32_t reg_data = - per_lane->csiphy_data_rate_regs[i].reg_data; - - CAM_DBG(CAM_CSIPHY, "writing reg : %x val : %x", - reg_addr, reg_data); - cam_io_w_mb(reg_data, csiphybase + reg_addr); + reg_addr = per_lane->csiphy_data_rate_regs[i] + .reg_addr; + reg_data = per_lane->csiphy_data_rate_regs[i] + .reg_data; + reg_param_type = + per_lane->csiphy_data_rate_regs[i] + .csiphy_param_type; + delay = per_lane->csiphy_data_rate_regs[i] + .delay; + CAM_DBG(CAM_CSIPHY, + "param_type: %d writing reg : %x val : %x delay: %dus", + reg_param_type, reg_addr, reg_data, + delay); + switch (reg_param_type) { + case CSIPHY_DEFAULT_PARAMS: + cam_io_w_mb(reg_data, + csiphybase + reg_addr); + break; + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + cam_io_w_mb(settle_cnt & 0xFF, + csiphybase + reg_addr); + break; + case CSIPHY_SETTLE_CNT_HIGHER_BYTE: + cam_io_w_mb((settle_cnt >> 8) & 0xFF, + csiphybase + reg_addr); + break; + case CSIPHY_SKEW_CAL: + if (skew_cal_enable) + cam_io_w_mb(reg_data, + csiphybase + reg_addr); + break; + default: + CAM_DBG(CAM_CSIPHY, "Do Nothing"); + break; + } + if (delay > 0) + usleep_range(delay, delay + 5); } } break; From e45fa615bf9fe9d2484800166fa37affeb938c8e Mon Sep 17 00:00:00 2001 From: Anand Ravi Date: Thu, 16 Jul 2020 13:16:52 -0700 Subject: [PATCH 475/790] msm: camera: smmu: Fixes label_is_string warning in camera dtsi files Property 'label' is a reserved property of type string. At present, device trees use the property as list of strings. Rename the property to 'cam-smmu-label' to resolve conflict. CRs-Fixed: 2729703 Change-Id: I8bfb3af4daeaad4cc9dfc633a0256186ba1416c9 Signed-off-by: Anand Ravi --- drivers/cam_smmu/cam_smmu_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 4e6ee1b10d4f..5f82359c1d62 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3864,7 +3864,7 @@ static int cam_populate_smmu_context_banks(struct device *dev, of_property_read_bool(dev->of_node, "multiple-client-devices"); cb->num_shared_hdl = of_property_count_strings(dev->of_node, - "label"); + "cam-smmu-label"); if (cb->num_shared_hdl > CAM_SMMU_SHARED_HDL_MAX) { @@ -3877,7 +3877,7 @@ static int cam_populate_smmu_context_banks(struct device *dev, /* set the name of the context bank */ for (i = 0; i < cb->num_shared_hdl; i++) rc = of_property_read_string_index(dev->of_node, - "label", i, &cb->name[i]); + "cam-smmu-label", i, &cb->name[i]); if (rc < 0) { CAM_ERR(CAM_SMMU, "Error: failed to read label from sub device"); From 46812a7030e46f5d030907a28570535ef8626b50 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Thu, 27 Aug 2020 10:22:58 -0700 Subject: [PATCH 476/790] msm: camera: ife: Always send stop immediately when stopping hw As the name implies, we stop the HW sooner, so prefer it over "stop at frame boundary". CRs-Fixed: 2724889 Change-Id: I7fa353c09dbe733e57f099893edc0e7f7fa18e7a Signed-off-by: Fernando Pacheco --- drivers/cam_isp/cam_isp_context.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 79f0885a2f43..67480b578c69 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5028,13 +5028,9 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( if (ctx_isp->hw_ctx) { stop.ctxt_to_hw_map = ctx_isp->hw_ctx; - if (stop_cmd) - stop_isp.hw_stop_cmd = - CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; - else - stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; - + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_isp.stop_only = false; + stop.args = (void *) &stop_isp; ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop); From 11a5797354af482a3c3590c7024ba4203effe06e Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 6 Aug 2020 19:14:29 -0700 Subject: [PATCH 477/790] msm: camera: sensor: Correct delete request logic Currently per frame array is not getting filled up with NOP packet settings and as a part of that delete request is picking up wrong request to get delete. This change fill the request id to the correct per frame array index for NOP and Update packet. CRs-Fixed: 2759031 Change-Id: I5ff96851adccc81a8a527d2a5f5b3f8763ebd80f Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 67c52c72b1c2..ed1206cd4f0e 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -289,6 +289,12 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, goto end; } + i2c_reg_settings = + &i2c_data->per_frame[csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY]; + i2c_reg_settings->request_id = csl_packet->header.request_id; + i2c_reg_settings->is_settings_valid = 1; + rc = cam_sensor_update_req_mgr(s_ctrl, csl_packet); if (rc) CAM_ERR(CAM_SENSOR, @@ -1303,6 +1309,7 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, return rc; } } + CAM_DBG(CAM_SENSOR, "applied req_id: %llu", req_id); } else { CAM_DBG(CAM_SENSOR, "Invalid/NOP request to apply: %lld", req_id); From 4f8f47ab0f9aa550b7cfcddf64aaa07df7cc1e42 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Thu, 27 Aug 2020 17:58:52 -0700 Subject: [PATCH 478/790] msm: camera: common: Fix enable/disable for dsp clock source Currently, if dsp clock source is not found in device tree, still we are trying to enable/disable clock source. Check for availability of that optional clock before toggling it. CRs-Fixed: 2762106 Change-Id: I2a4467f5383343bdf1e6607712270f574c76e51e Signed-off-by: Mukund Madhusudan Atre --- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 26 +++++++++++++++---- drivers/cam_utils/cam_soc_util.c | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 6b1bb46b94ee..b60528dff714 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -298,11 +298,18 @@ int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, if (!soc_info) { CAM_ERR(CAM_ISP, "Error Invalid params"); rc = -EINVAL; - return rc; + goto end; } soc_private = soc_info->soc_private; - if (strcmp(clk_name, CAM_VFE_DSP_CLK_NAME) == 0) { + if (!strcmp(clk_name, CAM_VFE_DSP_CLK_NAME)) { + if (soc_private->dsp_clk_index == -1) { + CAM_ERR(CAM_ISP, + "DSP clock not supported for vfe: %d", soc_info->index); + rc = -EPERM; + goto end; + } + rc = cam_soc_util_clk_enable(soc_private->dsp_clk, CAM_VFE_DSP_CLK_NAME, soc_private->dsp_clk_rate); if (rc) @@ -310,6 +317,7 @@ int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, "Error enable dsp clk failed rc=%d", rc); } +end: return rc; } @@ -322,18 +330,26 @@ int cam_vfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, if (!soc_info) { CAM_ERR(CAM_ISP, "Error Invalid params"); rc = -EINVAL; - return rc; + goto end; } soc_private = soc_info->soc_private; - if (strcmp(clk_name, CAM_VFE_DSP_CLK_NAME) == 0) { + if (!strcmp(clk_name, CAM_VFE_DSP_CLK_NAME)) { + if (soc_private->dsp_clk_index == -1) { + CAM_ERR(CAM_ISP, + "DSP clock not supported for vfe: %d", soc_info->index); + rc = -EPERM; + goto end; + } + rc = cam_soc_util_clk_disable(soc_private->dsp_clk, CAM_VFE_DSP_CLK_NAME); if (rc) CAM_ERR(CAM_ISP, - "Error enable dsp clk failed rc=%d", rc); + "Error disable dsp clk failed rc=%d", rc); } +end: return rc; } diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 80611f9bff3e..db2dd9dd77f2 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -544,7 +544,6 @@ int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info, index = of_property_match_string(of_node, "clock-names-option", clk_name); - if (index < 0) { CAM_DBG(CAM_UTIL, "No clk data for %s", clk_name); *clk_index = -1; @@ -557,6 +556,7 @@ int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info, CAM_ERR(CAM_UTIL, "No clk named %s found. Dev %s", clk_name, soc_info->dev_name); *clk_index = -1; + *clk = NULL; return -EFAULT; } *clk_index = index; From 3d671618a45c2adbb8df7b2102ead2d5e458db8a Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 27 Jul 2020 13:15:21 -0700 Subject: [PATCH 479/790] msm: camera: sensor: Correct the datatype for request id Request id is having uint64 type from request manager, but sensor driver is handling it with int64. This may cause the out of bound access while accessing the data. This change corrects the data type to handle data correctly. CRs-Fixed: 2759031 Change-Id: I607ea3c123a7b050403e18f7f1bac2a23e1e585f Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c | 2 +- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 67c52c72b1c2..dbe297fb1c9f 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1236,7 +1236,7 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl) } int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, - int64_t req_id, enum cam_sensor_packet_opcodes opcode) + uint64_t req_id, enum cam_sensor_packet_opcodes opcode) { int rc = 0, offset, i; uint64_t top = 0, del_req_id = 0; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h index 507776843add..825c08bbfd1d 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h @@ -37,7 +37,7 @@ int cam_sensor_power(struct v4l2_subdev *sd, int on); * * This API applies the req_id settings to sensor */ -int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, int64_t req_id, +int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, uint64_t req_id, enum cam_sensor_packet_opcodes opcode); /** From 7aa0932eeb3af294f8072a9881e6916647414ea5 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Wed, 1 Apr 2020 14:26:18 +0530 Subject: [PATCH 480/790] msm: camera: common: Merge camera-kernel.3.1 changes in camera-kernel.4.0 msm: camera: ope: Fix OPE hang dump msm: camera: cdm: Add a check for fifo list in cdm workqueue msm: camera: ope: Add a check to validate dmi cmd address msm: camera: ope: Add check for number of stripe msm: camera: tfe: Support tfe pdaf port msm: camera: ope: Handle reset IRQ delay msm: camera: ope: enable pp modules hw status dump msm: camera: ope: Fix OPE clock issue msm: camera: ope: Add LDAR dump support msm: camera: ope: Add context state check in process cmd msm: camera: ope: Change parameters to find time difference msm: camera: ope: Add debug fs for dumping frame setting logs msm: camera: ope: Add debugfs support to dump ope hang dump msm: camera: tfe: Handle unsupported outport format msm: camera: ope: add page fault handlers in ope driver msm: camera: ope: Reduce OPE BUS memory msm: camera: ope: Change turbo clock limit. CRs-Fixed: 2729996 Change-Id: I683ed07082b455599f89dbc18f353b6a1e48b129 Signed-off-by: Trishansh Bhardwaj --- drivers/cam_cdm/cam_cdm_hw_core.c | 16 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 30 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 17 - drivers/cam_ope/cam_ope_context.c | 14 + drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 340 +++++++++++++++--- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 10 +- .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 83 ++--- .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h | 2 +- .../ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c | 41 +-- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 81 +++-- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 1 + drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 15 + .../cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h | 96 +++++ .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 97 +++-- .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h | 2 + 15 files changed, 644 insertions(+), 201 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 128edaf3e54a..d3c00193d9e6 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1085,6 +1085,9 @@ static void cam_hw_cdm_reset_cleanup( &core->bl_fifo[i].bl_request_list, entry) { if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) { + CAM_DBG(CAM_CDM, + "Notifying client %d for tag %d", + node->client_hdl, node->bl_tag); if (flush_hw) cam_cdm_notify_clients(cdm_hw, (node->client_hdl == handle) ? @@ -1145,6 +1148,17 @@ static void cam_hw_cdm_work(struct work_struct *work) if (core->bl_fifo[payload->fifo_idx].work_record) core->bl_fifo[payload->fifo_idx].work_record--; + if (list_empty(&core->bl_fifo[payload->fifo_idx] + .bl_request_list)) { + CAM_INFO(CAM_CDM, + "Fifo list empty, idx %d tag %d arb %d", + payload->fifo_idx, payload->irq_data, + core->arbitration); + mutex_unlock(&core->bl_fifo[payload->fifo_idx] + .fifo_lock); + return; + } + if (core->bl_fifo[payload->fifo_idx] .last_bl_tag_done != payload->irq_data) { @@ -1174,7 +1188,7 @@ static void cam_hw_cdm_work(struct work_struct *work) } } } else { - CAM_DBG(CAM_CDM, + CAM_INFO(CAM_CDM, "Skip GenIRQ, tag 0x%x fifo %d", payload->irq_data, payload->fifo_idx); } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 05b5924003d3..7d207060d39e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -78,6 +78,7 @@ struct cam_tfe_bus_common_data { struct cam_tfe_bus_wm_resource_data { uint32_t index; + uint32_t out_id; struct cam_tfe_bus_common_data *common_data; struct cam_tfe_bus_reg_offset_bus_client *hw_regs; @@ -631,6 +632,7 @@ static int cam_tfe_bus_acquire_wm( rsrc_data->height = out_port_info->height; rsrc_data->stride = out_port_info->stride; rsrc_data->mode = out_port_info->wm_mode; + rsrc_data->out_id = tfe_out_res_id; /* * Store the acquire width, height separately. For frame based ports @@ -644,14 +646,16 @@ static int cam_tfe_bus_acquire_wm( /* Set WM offset value to default */ rsrc_data->offset = 0; - if (rsrc_data->index > 6) { + if ((rsrc_data->index > 6) && + (tfe_out_res_id != CAM_TFE_BUS_TFE_OUT_PDAF)) { /* WM 7-9 refers to RDI 0/ RDI 1/RDI 2 */ rc = cam_tfe_bus_acquire_rdi_wm(rsrc_data); if (rc) return rc; - } else if (rsrc_data->index == 0 || rsrc_data->index == 1) { - /* WM 0 FULL_OUT */ + } else if (rsrc_data->index == 0 || rsrc_data->index == 1 || + (tfe_out_res_id == CAM_TFE_BUS_TFE_OUT_PDAF)) { + /* WM 0 FULL_OUT WM 1 IDEAL RAW WM9 for pdaf */ switch (rsrc_data->format) { case CAM_FORMAT_MIPI_RAW_8: rsrc_data->pack_fmt = 0x1; @@ -747,9 +751,14 @@ static int cam_tfe_bus_start_wm(struct cam_isp_resource_node *wm_res) /* Configure stride for RDIs on full TFE and TFE lite */ if ((rsrc_data->index > 6) && - (rsrc_data->mode != CAM_ISP_TFE_WM_LINE_BASED_MODE)) + ((rsrc_data->mode != CAM_ISP_TFE_WM_LINE_BASED_MODE) && + (rsrc_data->out_id != CAM_TFE_BUS_TFE_OUT_PDAF))) { cam_io_w_mb(rsrc_data->stride, (common_data->mem_base + rsrc_data->hw_regs->image_cfg_2)); + CAM_DBG(CAM_ISP, "WM:%d configure stride reg :0x%x", + rsrc_data->index, + rsrc_data->stride); + } /* Enable WM */ cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + @@ -1183,9 +1192,9 @@ static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; enum cam_tfe_bus_tfe_out_id tfe_out_res_id; enum cam_tfe_bus_comp_grp_id comp_grp_id; - int rc = -ENODEV; + int i, rc = -ENODEV; uint32_t secure_caps = 0, mode; - uint32_t i, format, num_wm, client_done_mask = 0; + uint32_t format, num_wm, client_done_mask = 0; if (!bus_priv || !acquire_args) { CAM_ERR(CAM_ISP, "Invalid Param"); @@ -1310,10 +1319,10 @@ static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, release_wm: for (i--; i >= 0; i--) - cam_tfe_bus_release_wm(bus_priv, - rsrc_data->wm_res[i]); + cam_tfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]); - cam_tfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); + if (rsrc_data->comp_grp) + cam_tfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); return rc; } @@ -1918,7 +1927,8 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, wm_data->index, reg_val_pair[j-1]); if ((wm_data->index < 7) || ((wm_data->index >= 7) && - (wm_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE))) { + (wm_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE)) || + (wm_data->out_id == CAM_TFE_BUS_TFE_OUT_PDAF)) { CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->image_cfg_2, io_cfg->planes[i].plane_stride); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index f4b7d669e800..198505db6ab1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -1923,23 +1923,6 @@ static int cam_tfe_camif_resource_start( return -ENODEV; } - /* Camif module config */ - val = cam_io_r(rsrc_data->mem_base + - rsrc_data->camif_reg->module_cfg); - val &= ~(rsrc_data->reg_data->pixel_pattern_mask); - val |= (rsrc_data->pix_pattern << - rsrc_data->reg_data->pixel_pattern_shift); - val |= (1 << rsrc_data->reg_data->module_enable_shift); - val |= (1 << rsrc_data->reg_data->pix_out_enable_shift); - if (rsrc_data->camif_pd_enable) - val |= (1 << rsrc_data->reg_data->pdaf_output_enable_shift); - - cam_io_w_mb(val, rsrc_data->mem_base + - rsrc_data->camif_reg->module_cfg); - - CAM_DBG(CAM_ISP, "TFE:%d camif module config val:%d", - core_info->core_index, val); - /* Config tfe core*/ val = 0; if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index 1c6b940f9b2b..d82b4ba84afd 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -123,6 +123,18 @@ static int __cam_ope_flush_dev_in_ready(struct cam_context *ctx, return rc; } +static int __cam_ope_dump_dev_in_ready(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc; + + rc = cam_context_dump_dev_to_hw(ctx, cmd); + if (rc) + CAM_ERR(CAM_OPE, "Failed to dump device"); + + return rc; +} + static int __cam_ope_config_dev_in_ready(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { @@ -206,6 +218,7 @@ static struct cam_ctx_ops .start_dev = __cam_ope_start_dev_in_acquired, .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, + .dump_dev = __cam_ope_dump_dev_in_ready, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -218,6 +231,7 @@ static struct cam_ctx_ops .release_dev = __cam_ope_release_dev_in_ready, .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, + .dump_dev = __cam_ope_dump_dev_in_ready, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 8dfff457a6d6..ca17328d41ae 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -96,12 +96,19 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) task_data = (struct ope_cmd_work_data *)data; cdm_cmd = task_data->data; - CAM_DBG(CAM_OPE, - "cam_cdm_submit_bls: handle 0x%x, ctx_id %d req %d cookie %d", - ctx_data->ope_cdm.cdm_handle, ctx_data->ctx_id, - task_data->req_id, cdm_cmd->cookie); + if (!cdm_cmd) { + CAM_ERR(CAM_OPE, "Invalid params%pK", cdm_cmd); + return -EINVAL; + } mutex_lock(&hw_mgr->hw_mgr_mutex); + if (ctx_data->ctx_state != OPE_CTX_STATE_ACQUIRED) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + CAM_ERR(CAM_OPE, "ctx id :%u is not in use", + ctx_data->ctx_id); + return -EINVAL; + } + if (task_data->req_id <= ctx_data->last_flush_req) { CAM_WARN(CAM_OPE, "request %lld has been flushed, reject packet", @@ -110,6 +117,11 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) return -EINVAL; } + CAM_DBG(CAM_OPE, + "cam_cdm_submit_bls: handle 0x%x, ctx_id %d req %d cookie %d", + ctx_data->ope_cdm.cdm_handle, ctx_data->ctx_id, + task_data->req_id, cdm_cmd->cookie); + if (task_data->req_id > ctx_data->last_flush_req) ctx_data->last_flush_req = 0; @@ -536,13 +548,21 @@ static int cam_ope_dump_bls(struct cam_ope_request *ope_req, struct cam_ope_hang_dump *dump) { struct cam_cdm_bl_request *cdm_cmd; - int i; + size_t size; + int i, rc; + dma_addr_t iova_addr; cdm_cmd = ope_req->cdm_cmd; for (i = 0; i < cdm_cmd->cmd_arrary_count; i++) { + rc = cam_mem_get_io_buf(cdm_cmd->cmd[i].bl_addr.mem_handle, + ope_hw_mgr->iommu_hdl, &iova_addr, &size); + if (rc) { + CAM_ERR(CAM_OPE, "get io buf fail 0x%x", + cdm_cmd->cmd[i].bl_addr.mem_handle); + return rc; + } dump->bl_entries[dump->num_bls].base = - (uint32_t)cdm_cmd->cmd[i].bl_addr.hw_iova + - cdm_cmd->cmd[i].offset; + (uint32_t)iova_addr + cdm_cmd->cmd[i].offset; dump->bl_entries[dump->num_bls].len = cdm_cmd->cmd[i].len; dump->bl_entries[dump->num_bls].arbitration = cdm_cmd->cmd[i].arbitrate; @@ -568,6 +588,7 @@ static void cam_ope_dump_req_data(struct cam_ope_request *ope_req) ope_req->ope_debug_buf.offset); return; } + dump = (struct cam_ope_hang_dump *)ope_req->ope_debug_buf.cpu_addr; memset(dump, 0, sizeof(struct cam_ope_hang_dump)); dump->num_bufs = 0; @@ -1013,8 +1034,11 @@ static int cam_ope_get_lower_clk_rate(struct cam_ope_hw_mgr *hw_mgr, i = cam_ope_get_actual_clk_rate_idx(ctx_data, base_clk); - if (i > 0) - return ctx_data->clk_info.clk_rate[i - 1]; + while (i > 0) { + if (ctx_data->clk_info.clk_rate[i - 1]) + return ctx_data->clk_info.clk_rate[i - 1]; + i--; + } CAM_DBG(CAM_OPE, "Already clk at lower level"); @@ -1028,8 +1052,11 @@ static int cam_ope_get_next_clk_rate(struct cam_ope_hw_mgr *hw_mgr, i = cam_ope_get_actual_clk_rate_idx(ctx_data, base_clk); - if (i < CAM_MAX_VOTE - 1) - return ctx_data->clk_info.clk_rate[i + 1]; + while (i < CAM_MAX_VOTE - 1) { + if (ctx_data->clk_info.clk_rate[i + 1]) + return ctx_data->clk_info.clk_rate[i + 1]; + i++; + } CAM_DBG(CAM_OPE, "Already clk at higher level"); @@ -1520,6 +1547,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, struct cam_hw_done_event_data buf_data; struct timespec64 ts; uint32_t evt_id = CAM_CTX_EVT_ID_SUCCESS; + bool dump_flag = true; if (!userdata) { CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); @@ -1581,8 +1609,10 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id, ctx->ctx_id); CAM_ERR(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", ope_req->request_id); - if (status != CAM_CDM_CB_STATUS_HW_FLUSH) + if (status != CAM_CDM_CB_STATUS_HW_FLUSH) { cam_ope_dump_req_data(ope_req); + dump_flag = false; + } rc = cam_ope_mgr_reset_hw(); evt_id = CAM_CTX_EVT_ID_ERROR; @@ -1598,6 +1628,9 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, buf_data.evt_param = CAM_SYNC_OPE_EVENT_UNKNOWN; } + if (ope_hw_mgr->dump_req_data_enable && dump_flag) + cam_ope_dump_req_data(ope_req); + ctx->req_cnt--; buf_data.request_id = ope_req->request_id; @@ -1779,15 +1812,14 @@ static void cam_ope_mgr_print_stripe_info(uint32_t batch, { CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d: E", batch, io_buf, plane, stripe); - CAM_DBG(CAM_OPE, "width: %d s_w: %u s_h: %u s_s: %u", - stripe_info->width, stripe_info->width, - stripe_info->height, stripe_info->stride); + CAM_DBG(CAM_OPE, "width: %d s_h: %u s_s: %u", + stripe_info->width, stripe_info->height, + stripe_info->stride); CAM_DBG(CAM_OPE, "s_xinit = %u iova = %x s_loc = %u", - stripe_info->s_location, stripe_info->x_init, - iova_addr); - CAM_DBG(CAM_OPE, "s_off = %u s_format = %u s_len = %u", + stripe_info->x_init, iova_addr, stripe_info->s_location); + CAM_DBG(CAM_OPE, "s_off = %u s_format = %u s_len = %u d_bus %d", stripe_info->offset, stripe_info->format, - stripe_info->len); + stripe_info->len, stripe_info->disable_bus); CAM_DBG(CAM_OPE, "s_align = %u s_pack = %u s_unpack = %u", stripe_info->alignment, stripe_info->pack_format, stripe_info->unpack_format); @@ -1827,29 +1859,15 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, in_frame_set = &in_frame_process->frame_set[i]; for (j = 0; j < in_frame_set->num_io_bufs; j++) { in_io_buf = &in_frame_set->io_buf[j]; - CAM_DBG(CAM_OPE, "i:%d j:%d dir: %x rsc: %u plane: %d", - i, j, in_io_buf->direction, - in_io_buf->resource_type, - in_io_buf->num_planes); for (k = 0; k < in_io_buf->num_planes; k++) { - CAM_DBG(CAM_OPE, "i:%d j:%d k:%d numstripe: %d", - i, j, k, in_io_buf->num_stripes[k]); - CAM_DBG(CAM_OPE, "m_hdl: %d len: %d", - in_io_buf->mem_handle[k], - in_io_buf->length[k]); + if (!in_io_buf->num_stripes[k]) { + CAM_ERR(CAM_OPE, "Null num_stripes"); + return -EINVAL; + } for (l = 0; l < in_io_buf->num_stripes[k]; l++) { in_stripe_info = &in_io_buf->stripe_info[k][l]; - CAM_DBG(CAM_OPE, "i:%d j:%d k:%d l:%d", - i, j, k, l); - CAM_DBG(CAM_OPE, "%d s_loc:%d w:%d", - in_stripe_info->x_init, - in_stripe_info->stripe_location, - in_stripe_info->width); - CAM_DBG(CAM_OPE, "s_off: %d d_bus: %d", - in_stripe_info->offset, - in_stripe_info->disable_bus); } } } @@ -1907,9 +1925,6 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, unpack_format = 0; } - CAM_DBG(CAM_OPE, "i:%d j:%d dir:%d rsc type:%d fmt:%d", - i, j, io_buf->direction, io_buf->resource_type, - io_buf->format); for (k = 0; k < in_io_buf->num_planes; k++) { io_buf->num_stripes[k] = in_io_buf->num_stripes[k]; @@ -1936,6 +1951,11 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, return -EINVAL; } iova_addr += in_io_buf->plane_offset[k]; + CAM_DBG(CAM_OPE, + "E rsc %d stripes %d dir %d plane %d", + in_io_buf->resource_type, + in_io_buf->direction, + in_io_buf->num_stripes[k], k); for (l = 0; l < in_io_buf->num_stripes[k]; l++) { in_stripe_info = @@ -1966,6 +1986,11 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, cam_ope_mgr_print_stripe_info(i, j, k, l, stripe_info, iova_addr); } + CAM_DBG(CAM_OPE, + "X rsc %d stripes %d dir %d plane %d", + in_io_buf->resource_type, + in_io_buf->direction, + in_io_buf->num_stripes[k], k); } } } @@ -2491,6 +2516,9 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) struct cam_ope_dev_clk_update clk_update; struct cam_ope_dev_bw_update *bw_update; struct cam_ope_set_irq_cb irq_cb; + struct cam_hw_info *dev = NULL; + struct cam_hw_soc_info *soc_info = NULL; + int32_t idx; if ((!hw_priv) || (!hw_acquire_args)) { CAM_ERR(CAM_OPE, "Invalid args: %x %x", @@ -2579,8 +2607,14 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } } - hw_mgr->clk_info.base_clk = 600000000; - hw_mgr->clk_info.curr_clk = 600000000; + dev = (struct cam_hw_info *)hw_mgr->ope_dev_intf[0]->hw_priv; + soc_info = &dev->soc_info; + idx = soc_info->src_clk_idx; + + hw_mgr->clk_info.base_clk = + soc_info->clk_rate[CAM_TURBO_VOTE][idx]; + hw_mgr->clk_info.curr_clk = + soc_info->clk_rate[CAM_TURBO_VOTE][idx]; hw_mgr->clk_info.threshold = 5; hw_mgr->clk_info.over_clked = 0; @@ -2607,7 +2641,11 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) } for (i = 0; i < ope_hw_mgr->num_ope; i++) { - clk_update.clk_rate = 600000000; + dev = (struct cam_hw_info *)hw_mgr->ope_dev_intf[i]->hw_priv; + soc_info = &dev->soc_info; + idx = soc_info->src_clk_idx; + clk_update.clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][idx]; + rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_CLK_UPDATE, &clk_update, sizeof(clk_update)); @@ -3302,6 +3340,7 @@ static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args) cdm_cmd->cookie = ope_req->req_idx; cam_ope_mgr_ope_clk_update(hw_mgr, ctx_data, ope_req->req_idx); + ctx_data->req_list[ope_req->req_idx]->submit_timestamp = ktime_get(); if (ope_req->request_id <= ctx_data->last_flush_req) CAM_WARN(CAM_OPE, @@ -3327,6 +3366,112 @@ config_err: return rc; } +static void cam_ope_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + dma_addr_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_OPE, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_OPE, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, + "get src buf address fail rc %d mem %x", + rc, io_cfg[i].mem_handle[j]); + continue; + } + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { + CAM_ERR(CAM_OPE, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_OPE, + "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], + io_cfg[i].mem_handle[j]); + + iova_addr += io_cfg[i].offsets[j]; + + } + } + cam_packet_dump_patch_info(packet, ope_hw_mgr->iommu_hdl, + ope_hw_mgr->iommu_sec_hdl); +} + +static int cam_ope_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_ope_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_OPE, "Invalid arguments"); + return -EINVAL; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_ope_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->iommu_hdl, + 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_OPE, "Invalid cmd"); + } + + return rc; +} + static int cam_ope_mgr_hw_open_u(void *hw_priv, void *fw_download_args) { struct cam_ope_hw_mgr *hw_mgr; @@ -3429,6 +3574,76 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data, return rc; } +static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) +{ + struct cam_ope_ctx *ctx_data; + struct cam_ope_hw_mgr *hw_mgr = hw_priv; + struct cam_hw_dump_args *dump_args; + int idx; + ktime_t cur_time; + struct timespec64 cur_ts, req_ts; + uint64_t diff; + + if ((!hw_priv) || (!hw_dump_args)) { + CAM_ERR(CAM_OPE, "Invalid params %pK %pK", + hw_priv, hw_dump_args); + return -EINVAL; + } + + dump_args = (struct cam_hw_dump_args *)hw_dump_args; + ctx_data = dump_args->ctxt_to_hw_map; + + if (!ctx_data) { + CAM_ERR(CAM_OPE, "Invalid context"); + return -EINVAL; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + + CAM_INFO(CAM_OPE, "Req %lld", dump_args->request_id); + for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) { + if (!ctx_data->req_list[idx]) + continue; + + if (ctx_data->req_list[idx]->request_id == + dump_args->request_id) + break; + } + + /* no matching request found */ + if (idx == CAM_CTX_REQ_MAX) { + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; + } + + cur_time = ktime_get(); + diff = ktime_us_delta(cur_time, + ctx_data->req_list[idx]->submit_timestamp); + cur_ts = ktime_to_timespec64(cur_time); + req_ts = ktime_to_timespec64(ctx_data->req_list[idx]->submit_timestamp); + + if (diff < (OPE_REQUEST_TIMEOUT * 1000)) { + CAM_INFO(CAM_OPE, "No Error req %llu %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; + } + + CAM_ERR(CAM_OPE, "Error req %llu %ld:%06ld %ld:%06ld", + dump_args->request_id, + req_ts.tv_sec, + req_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, + cur_ts.tv_nsec/NSEC_PER_USEC); + + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return 0; +} + static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args) { struct cam_hw_flush_args *flush_args = hw_flush_args; @@ -3683,6 +3898,40 @@ cmd_work_failed: return rc; } +static int cam_ope_create_debug_fs(void) +{ + ope_hw_mgr->dentry = debugfs_create_dir("camera_ope", + NULL); + + if (!ope_hw_mgr->dentry) { + CAM_ERR(CAM_OPE, "failed to create dentry"); + return -ENOMEM; + } + + if (!debugfs_create_bool("frame_dump_enable", + 0644, + ope_hw_mgr->dentry, + &ope_hw_mgr->frame_dump_enable)) { + CAM_ERR(CAM_OPE, + "failed to create dump_enable_debug"); + goto err; + } + + if (!debugfs_create_bool("dump_req_data_enable", + 0644, + ope_hw_mgr->dentry, + &ope_hw_mgr->dump_req_data_enable)) { + CAM_ERR(CAM_OPE, + "failed to create dump_enable_debug"); + goto err; + } + + return 0; +err: + debugfs_remove_recursive(ope_hw_mgr->dentry); + return -ENOMEM; +} + int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl) @@ -3716,10 +3965,11 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, hw_mgr_intf->hw_config = cam_ope_mgr_config_hw; hw_mgr_intf->hw_read = NULL; hw_mgr_intf->hw_write = NULL; - hw_mgr_intf->hw_cmd = NULL; + hw_mgr_intf->hw_cmd = cam_ope_mgr_cmd; hw_mgr_intf->hw_open = cam_ope_mgr_hw_open_u; hw_mgr_intf->hw_close = cam_ope_mgr_hw_close_u; hw_mgr_intf->hw_flush = cam_ope_mgr_hw_flush; + hw_mgr_intf->hw_dump = cam_ope_mgr_hw_dump; ope_hw_mgr->secure_mode = false; mutex_init(&ope_hw_mgr->hw_mgr_mutex); @@ -3787,6 +4037,8 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, if (rc) goto ope_wq_create_failed; + cam_ope_create_debug_fs(); + if (iommu_hdl) *iommu_hdl = ope_hw_mgr->iommu_hdl; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index 07ef8203bbef..98d3587ac929 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -62,8 +62,6 @@ #define OPE_DEVICE_IDLE_TIMEOUT 400 #define OPE_REQUEST_TIMEOUT 200 - - /** * struct cam_ope_clk_bw_request_v2 * @budget_ns: Time required to process frame @@ -390,6 +388,7 @@ struct ope_io_buf { * @clk_info: Clock Info V1 * @clk_info_v2: Clock Info V2 * @hang_data: Debug data for HW error + * @submit_timestamp: Submit timestamp to hw */ struct cam_ope_request { uint64_t request_id; @@ -410,6 +409,7 @@ struct cam_ope_request { struct cam_ope_clk_bw_request clk_info; struct cam_ope_clk_bw_req_internal_v2 clk_info_v2; struct cam_hw_mgr_dump_pf_data hang_data; + ktime_t submit_timestamp; }; /** @@ -499,6 +499,9 @@ struct cam_ope_ctx { * @ope_dev_intf: OPE device interface * @cdm_reg_map: OPE CDM register map * @clk_info: OPE clock Info for HW manager + * @dentry: Pointer to OPE debugfs directory + * @frame_dump_enable: OPE frame setting dump enablement + * @dump_req_data_enable: OPE hang dump enablement */ struct cam_ope_hw_mgr { int32_t open_cnt; @@ -529,6 +532,9 @@ struct cam_ope_hw_mgr { struct cam_hw_intf *ope_dev_intf[OPE_DEV_MAX]; struct cam_soc_reg_map *cdm_reg_map[OPE_DEV_MAX][OPE_BASE_MAX]; struct cam_ope_clk_info clk_info; + struct dentry *dentry; + bool frame_dump_enable; + bool dump_req_data_enable; }; /** diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index d58d4dd5e94a..0042675f1821 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -193,13 +193,17 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, CAM_DBG(CAM_OPE, "req_idx = %d req_id = %lld KMDbuf %x offset %d", req_idx, ope_request->request_id, kmd_buf, prepare->kmd_buf_offset); - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; io_port_info = &bus_rd_ctx->io_port_info; rd_reg = ope_hw_info->bus_rd_reg; rd_reg_val = ope_hw_info->bus_rd_reg_val; - io_buf = ope_request->io_buf[batch_idx][io_idx]; + CAM_DBG(CAM_OPE, + "req_idx = %d req_id = %lld KMDbuf 0x%x offset %d rsc %d", + req_idx, ope_request->request_id, + kmd_buf, prepare->kmd_buf_offset, + io_buf->resource_type); CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d", batch_idx, io_idx, io_buf->direction); io_port_cdm = @@ -307,20 +311,15 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, sizeof(temp)); CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", batch_idx, io_idx, k, l); - for (m = 0; m < count; m++) - CAM_DBG(CAM_OPE, "%d:temp:%x", - m, temp_reg[m]); + for (m = 0; m < count; m += 2) + CAM_DBG(CAM_OPE, "%d: off: 0x%x val: 0x%x", + m, temp_reg[m], temp_reg[m+1]); CAM_DBG(CAM_OPE, "kmd_buf:%x offset:%d", - kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "%x count: %d size:%d", - temp_reg, count, header_size); - CAM_DBG(CAM_OPE, "RD cmdbufs:%d off:%d", - io_port_cdm->num_s_cmd_bufs[l], - io_port_cdm->s_cdm_info[l][idx].offset); - CAM_DBG(CAM_OPE, "len:%d", - io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); + kmd_buf, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, "RD cmdbufs:%d off:%d len %d", + io_port_cdm->num_s_cmd_bufs[l], + io_port_cdm->s_cdm_info[l][idx].offset, + io_port_cdm->s_cdm_info[l][idx].len); count = 0; } } @@ -368,12 +367,13 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info, req_idx = prepare->req_idx; cdm_ops = ctx_data->ope_cdm.cdm_ops; - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; io_port_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; rd_reg = ope_hw_info->bus_rd_reg; - CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d", - kmd_buf, req_idx, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, + "kmd_buf = 0x%x req_idx = %d offset = %d rd_idx %d b %d", + kmd_buf, req_idx, prepare->kmd_buf_offset, rm_idx, batch_idx); io_port_cdm = &bus_rd_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; @@ -402,20 +402,11 @@ static uint32_t *cam_ope_bus_rm_disable(struct ope_hw *ope_hw_info, prepare->kmd_buf_offset += ((count + header_size) * sizeof(temp)); - CAM_DBG(CAM_OPE, "b:%d s:%d", - batch_idx, l); - CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", - kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", - count, temp_reg, header_size); - CAM_DBG(CAM_OPE, "header_size:%d", header_size); - CAM_DBG(CAM_OPE, "RD cmd bufs = %d", + CAM_DBG(CAM_OPE, "RD cmd bufs = %d", io_port_cdm->num_s_cmd_bufs[l]); - CAM_DBG(CAM_OPE, "off:%d len:%d", - io_port_cdm->s_cdm_info[l][idx].offset, + CAM_DBG(CAM_OPE, "stripe %d off:%d len:%d", + l, io_port_cdm->s_cdm_info[l][idx].offset, io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d s:%d", - batch_idx, l); count = 0; } @@ -464,7 +455,7 @@ static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info, req_idx, ope_request->request_id); CAM_DBG(CAM_OPE, "KMD buf and offset = %x %d", kmd_buf, prepare->kmd_buf_offset); - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; io_port_cdm_batch = &bus_rd_ctx->io_port_cdm_batch; memset(io_port_cdm_batch, 0, @@ -562,25 +553,15 @@ end: static int cam_ope_bus_rd_release(struct ope_hw *ope_hw_info, int32_t ctx_id, void *data) { - int rc = 0, i; - struct ope_acquire_dev_info *in_acquire; - struct ope_bus_rd_ctx *bus_rd_ctx; + int rc = 0; - if (ctx_id < 0) { + if (ctx_id < 0 || ctx_id >= OPE_CTX_MAX) { CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id); return -EINVAL; } - in_acquire = bus_rd->bus_rd_ctx[ctx_id].ope_acquire; - bus_rd->bus_rd_ctx[ctx_id].ope_acquire = NULL; - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; - bus_rd_ctx->num_in_ports = 0; - - for (i = 0; i < bus_rd_ctx->num_in_ports; i++) { - bus_rd_ctx->io_port_info.input_port_id[i] = 0; - bus_rd_ctx->io_port_info.input_format_type[i - 1] = 0; - bus_rd_ctx->io_port_info.pixel_pattern[i - 1] = 0; - } + vfree(bus_rd->bus_rd_ctx[ctx_id]); + bus_rd->bus_rd_ctx[ctx_id] = NULL; return rc; } @@ -597,15 +578,21 @@ static int cam_ope_bus_rd_acquire(struct ope_hw *ope_hw_info, int in_port_idx; - if (ctx_id < 0 || !data || !ope_hw_info) { + if (ctx_id < 0 || !data || !ope_hw_info || ctx_id >= OPE_CTX_MAX) { CAM_ERR(CAM_OPE, "Invalid data: %d %x %x", ctx_id, data, ope_hw_info); return -EINVAL; } - bus_rd->bus_rd_ctx[ctx_id].ope_acquire = data; + bus_rd->bus_rd_ctx[ctx_id] = vzalloc(sizeof(struct ope_bus_rd_ctx)); + if (!bus_rd->bus_rd_ctx[ctx_id]) { + CAM_ERR(CAM_OPE, "Out of memory"); + return -ENOMEM; + } + + bus_rd->bus_rd_ctx[ctx_id]->ope_acquire = data; in_acquire = data; - bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id]; + bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id]; bus_rd_ctx->num_in_ports = in_acquire->num_in_res; bus_rd_ctx->security_flag = in_acquire->secure_mode; bus_rd_reg_val = ope_hw_info->bus_rd_reg_val; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h index 15a45a6bea51..b461374c2a63 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h @@ -132,7 +132,7 @@ struct ope_bus_rd_ctx { struct ope_bus_rd { struct ope_hw *ope_hw_info; struct ope_bus_in_port_to_rm in_port_to_rm[OPE_IN_RES_MAX]; - struct ope_bus_rd_ctx bus_rd_ctx[OPE_CTX_MAX]; + struct ope_bus_rd_ctx *bus_rd_ctx[OPE_CTX_MAX]; struct completion reset_complete; }; #endif /* OPE_BUS_RD_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c index bade41972a26..df5cb89b1eea 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c @@ -169,7 +169,7 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, int batch_idx, int io_idx, uint32_t *kmd_buf, uint32_t *num_stripes) { - int k, l, out_port_idx; + int k, l, m, out_port_idx; uint32_t idx; uint32_t num_wm_ports; uint32_t comb_idx; @@ -226,8 +226,8 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, prepare->kmd_buf_offset); io_buf = ope_request->io_buf[batch_idx][io_idx]; - CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d", - batch_idx, io_idx, io_buf->direction); + CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d rsc %d", + batch_idx, io_idx, io_buf->direction, io_buf->resource_type); io_port_cdm = &bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; @@ -335,19 +335,15 @@ static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info, CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", batch_idx, io_idx, k, l); + for (m = 0; m < count; m += 2) + CAM_DBG(CAM_OPE, "%d: off: 0x%x val: 0x%x", + m, temp_reg[m], temp_reg[m+1]); CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", - count, temp_reg, header_size); - CAM_DBG(CAM_OPE, "header_size:%d", header_size); - - CAM_DBG(CAM_OPE, "WR cmd bufs = %d", - io_port_cdm->num_s_cmd_bufs[l]); - CAM_DBG(CAM_OPE, "off:%d len:%d", + CAM_DBG(CAM_OPE, "WR cmd bufs = %d off:%d len:%d", + io_port_cdm->num_s_cmd_bufs[l], io_port_cdm->s_cdm_info[l][idx].offset, io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); count = 0; } } @@ -398,8 +394,9 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch; wr_reg = ope_hw_info->bus_wr_reg; - CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d", - kmd_buf, req_idx, prepare->kmd_buf_offset); + CAM_DBG(CAM_OPE, + "kmd_buf = %x req_idx = %d offset = %d out_idx %d b %d", + kmd_buf, req_idx, prepare->kmd_buf_offset, io_idx, batch_idx); io_port_cdm = &bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx]; @@ -409,8 +406,6 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, for (k = 0; k < num_wm_ports; k++) { for (l = 0; l < num_stripes; l++) { - CAM_DBG(CAM_OPE, "comb_idx = %d p_idx = %d s_idx = %d", - comb_idx, k, l); /* frame level info */ /* stripe level info */ wm_port_id = out_port_to_wm->wm_port_id[comb_idx][k]; @@ -436,21 +431,11 @@ static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info, prepare->kmd_buf_offset += ((count + header_size) * sizeof(temp)); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); - CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d", - kmd_buf, prepare->kmd_buf_offset); - CAM_DBG(CAM_OPE, "count:%d temp_reg:%x", - count, temp_reg, header_size); - CAM_DBG(CAM_OPE, "header_size:%d", header_size); - CAM_DBG(CAM_OPE, "WR cmd bufs = %d", io_port_cdm->num_s_cmd_bufs[l]); - CAM_DBG(CAM_OPE, "off:%d len:%d", - io_port_cdm->s_cdm_info[l][idx].offset, + CAM_DBG(CAM_OPE, "s:%d off:%d len:%d", + l, io_port_cdm->s_cdm_info[l][idx].offset, io_port_cdm->s_cdm_info[l][idx].len); - CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d", - batch_idx, io_idx, k, l); count = 0; } } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index 8a46b71241d6..dee7186aad3d 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -427,7 +427,7 @@ static int dump_dmi_cmd(uint32_t print_idx, return 0; } -static int dump_frame_direct(uint32_t print_idx, +static int dump_direct_cmd(uint32_t print_idx, uint32_t *print_ptr, struct ope_frame_process *frm_proc, int batch_idx, int cmd_buf_idx) @@ -569,7 +569,7 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, iova_addr, frm_proc->cmd_buf[i][j].length); print_ptr = (uint32_t *)cpu_addr; - dump_frame_direct(print_idx, print_ptr, + dump_direct_cmd(print_idx, print_ptr, frm_proc, i, j); } else { num_dmi = frm_proc->cmd_buf[i][j].length / @@ -581,21 +581,28 @@ static uint32_t *ope_create_frame_cmd_batch(struct cam_ope_hw_mgr *hw_mgr, memcpy(temp, (const void *)print_ptr, sizeof(struct cdm_dmi_cmd)); dmi_cmd = (struct cdm_dmi_cmd *)temp; + if (!dmi_cmd->addr) { + CAM_ERR(CAM_OPE, "Null dmi cmd addr"); + return NULL; + } + kmd_buf = cdm_ops->cdm_write_dmi( kmd_buf, 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, dmi_cmd->addr, dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); + if (hw_mgr->frame_dump_enable) + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); print_ptr += sizeof(struct cdm_dmi_cmd) / sizeof(uint32_t); } CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); } - dump_frame_cmd(frm_proc, i, j, - iova_addr, kmd_buf, buf_len); + if (hw_mgr->frame_dump_enable) + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); } return kmd_buf; @@ -719,8 +726,9 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, iova_addr, frm_proc->cmd_buf[i][j].length); print_ptr = (uint32_t *)cpu_addr; - dump_frame_direct(print_idx, print_ptr, - frm_proc, i, j); + if (hw_mgr->frame_dump_enable) + dump_direct_cmd(print_idx, print_ptr, + frm_proc, i, j); } else { num_dmi = frm_proc->cmd_buf[i][j].length / sizeof(struct cdm_dmi_cmd); @@ -731,21 +739,30 @@ static uint32_t *ope_create_frame_cmd(struct cam_ope_hw_mgr *hw_mgr, memcpy(temp, (const void *)print_ptr, sizeof(struct cdm_dmi_cmd)); dmi_cmd = (struct cdm_dmi_cmd *)temp; + if (!dmi_cmd->addr) { + CAM_ERR(CAM_OPE, + "Null dmi cmd addr"); + return NULL; + } + kmd_buf = cdm_ops->cdm_write_dmi( kmd_buf, 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, dmi_cmd->addr, dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); + if (hw_mgr->frame_dump_enable) + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, + temp); print_ptr += sizeof(struct cdm_dmi_cmd) / sizeof(uint32_t); } CAM_DBG(CAM_OPE, "Frame DB : In direct: X"); } - dump_frame_cmd(frm_proc, i, j, - iova_addr, kmd_buf, buf_len); + if (hw_mgr->frame_dump_enable) + dump_frame_cmd(frm_proc, i, j, + iova_addr, kmd_buf, buf_len); } } return kmd_buf; @@ -817,15 +834,12 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, kmd_buf, iova_addr, frm_proc->cmd_buf[i][k].length); - print_ptr = (uint32_t *)cpu_addr; - CAM_DBG(CAM_OPE, "Stripe:%d direct:E", - stripe_idx); - for (print_idx = 0; print_idx < - frm_proc->cmd_buf[i][k].length / 4; - print_idx++) { - CAM_DBG(CAM_OPE, "%d: %x", print_idx, - print_ptr[print_idx]); - } + print_ptr = (uint32_t *)cpu_addr; + CAM_DBG(CAM_OPE, "Stripe:%d direct:E", + stripe_idx); + if (hw_mgr->frame_dump_enable) + dump_direct_cmd(print_idx, print_ptr, + frm_proc, i, k); CAM_DBG(CAM_OPE, "Stripe:%d direct:X", stripe_idx); } else if (frm_proc->cmd_buf[i][k].type == OPE_CMD_BUF_TYPE_INDIRECT) { @@ -837,18 +851,25 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, memcpy(temp, (const void *)print_ptr, sizeof(struct cdm_dmi_cmd)); dmi_cmd = (struct cdm_dmi_cmd *)temp; + if (!dmi_cmd->addr) { + CAM_ERR(CAM_OPE, "Null dmi cmd addr"); + return NULL; + } + kmd_buf = cdm_ops->cdm_write_dmi(kmd_buf, 0, dmi_cmd->DMIAddr, dmi_cmd->DMISel, dmi_cmd->addr, dmi_cmd->length); - dump_dmi_cmd(print_idx, - print_ptr, dmi_cmd, temp); + if (hw_mgr->frame_dump_enable) + dump_dmi_cmd(print_idx, + print_ptr, dmi_cmd, temp); print_ptr += sizeof(struct cdm_dmi_cmd) / sizeof(uint32_t); } CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx); } - dump_stripe_cmd(frm_proc, stripe_idx, i, k, - iova_addr, kmd_buf, buf_len); + if (hw_mgr->frame_dump_enable) + dump_stripe_cmd(frm_proc, stripe_idx, i, k, + iova_addr, kmd_buf, buf_len); } return kmd_buf; } @@ -1511,10 +1532,12 @@ static int cam_ope_dev_process_prepare(struct ope_hw *ope_hw, void *cmd_args) if (rc) goto end; - cam_ope_dev_create_kmd_buf(ope_dev_prepare_req->hw_mgr, - ope_dev_prepare_req->prepare_args, - ope_dev_prepare_req->ctx_data, ope_dev_prepare_req->req_idx, - ope_dev_prepare_req->kmd_buf_offset, ope_dev_prepare_req); + rc = cam_ope_dev_create_kmd_buf(ope_dev_prepare_req->hw_mgr, + ope_dev_prepare_req->prepare_args, + ope_dev_prepare_req->ctx_data, + ope_dev_prepare_req->req_idx, + ope_dev_prepare_req->kmd_buf_offset, + ope_dev_prepare_req); end: return rc; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index e3c7cedafff3..cb80739071d9 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -80,6 +80,7 @@ static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info, ope_hw_100.top_reg->base = core_info->ope_hw_info->ope_top_base; ope_hw_100.bus_rd_reg->base = core_info->ope_hw_info->ope_bus_rd_base; ope_hw_100.bus_wr_reg->base = core_info->ope_hw_info->ope_bus_wr_base; + ope_hw_100.pp_reg->base = core_info->ope_hw_info->ope_pp_base; return rc; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index ecff57eeb96b..a54a2ec5b80d 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -14,6 +14,7 @@ #define MAX_RD_CLIENTS 2 #define MAX_WR_CLIENTS 8 +#define MAX_PP_CLIENTS 29 #define OPE_CDM_BASE 0x0 #define OPE_TOP_BASE 0x1 @@ -386,6 +387,18 @@ struct cam_ope_debug_register { uint32_t offset; }; +struct cam_ope_bus_pp_client_reg { + uint32_t hw_status; +}; + +struct cam_ope_pp_reg { + void *base; + uint32_t offset; + + uint32_t num_clients; + struct cam_ope_bus_pp_client_reg pp_clients[MAX_PP_CLIENTS]; +}; + struct ope_hw { struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; @@ -400,6 +413,8 @@ struct ope_hw { struct cam_ope_qos_reg_val *qos_reg_val; struct cam_ope_common *common; + + struct cam_ope_pp_reg *pp_reg; }; struct hw_version_reg { diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index 95ae384161af..727b43c68512 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -554,6 +554,101 @@ static struct cam_ope_bus_wr_reg_val ope_bus_wr_reg_val = { }, }, }; + +static struct cam_ope_pp_reg ope_pp_reg = { + .offset = 0x800, + .num_clients = MAX_PP_CLIENTS, + .pp_clients = { + { + .hw_status = 0x4, + }, + { + .hw_status = 0x204, + }, + { + .hw_status = 0x404, + }, + { + .hw_status = 0x604, + }, + { + .hw_status = 0x804, + }, + { + .hw_status = 0xA04, + }, + { + .hw_status = 0xC04, + }, + { + .hw_status = 0xE04, + }, + { + .hw_status = 0x1004, + }, + { + .hw_status = 0x1204, + }, + { + .hw_status = 0x1404, + }, + { + .hw_status = 0x1604, + }, + { + .hw_status = 0x1804, + }, + { + .hw_status = 0x1A04, + }, + { + .hw_status = 0x1C04, + }, + { + .hw_status = 0x1E04, + }, + { + .hw_status = 0x2204, + }, + { + .hw_status = 0x2604, + }, + { + .hw_status = 0x2804, + }, + { + .hw_status = 0x2A04, + }, + { + .hw_status = 0x2C04, + }, + { + .hw_status = 0x2E04, + }, + { + .hw_status = 0x3004, + }, + { + .hw_status = 0x3204, + }, + { + .hw_status = 0x3404, + }, + { + .hw_status = 0x3604, + }, + { + .hw_status = 0x3804, + }, + { + .hw_status = 0x3A04, + }, + { + .hw_status = 0x3C04, + }, + }, +}; + static struct ope_hw ope_hw_100 = { .top_reg = &ope_top_reg, .top_reg_val = &ope_top_reg_val, @@ -561,6 +656,7 @@ static struct ope_hw ope_hw_100 = { .bus_rd_reg_val = &ope_bus_rd_reg_val, .bus_wr_reg = &ope_bus_wr_reg, .bus_wr_reg_val = &ope_bus_wr_reg_val, + .pp_reg = &ope_pp_reg, }; #endif /* CAM_OPE_HW_100_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index 1034e55febc2..ee59b8d277c5 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -50,6 +50,7 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; uint32_t irq_mask, irq_status; + unsigned long flags; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -72,21 +73,37 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info, rc = wait_for_completion_timeout( &ope_top_info.reset_complete, - msecs_to_jiffies(30)); + msecs_to_jiffies(60)); cam_io_w_mb(top_reg_val->debug_cfg_val, top_reg->base + top_reg->debug_cfg); if (!rc || rc < 0) { - CAM_ERR(CAM_OPE, "reset error result = %d", rc); - irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_mask); - irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_status); - CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x", - irq_mask, irq_status); - cam_ope_top_dump_debug_reg(ope_hw_info); - rc = -ETIMEDOUT; + spin_lock_irqsave(&ope_top_info.hw_lock, flags); + if (!completion_done(&ope_top_info.reset_complete)) { + CAM_DBG(CAM_OPE, + "IRQ delayed, checking the status registers"); + irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_mask); + irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_status); + if (irq_status & top_reg_val->rst_done) { + CAM_DBG(CAM_OPE, "ope reset done"); + cam_io_w_mb(irq_status, + top_reg->base + top_reg->irq_clear); + cam_io_w_mb(top_reg_val->irq_set_clear, + top_reg->base + top_reg->irq_cmd); + } else { + CAM_ERR(CAM_OPE, + "irq mask 0x%x irq status 0x%x", + irq_mask, irq_status); + cam_ope_top_dump_debug_reg(ope_hw_info); + rc = -ETIMEDOUT; + } + } else { + rc = 0; + } + spin_unlock_irqrestore(&ope_top_info.hw_lock, flags); } else { rc = 0; } @@ -137,6 +154,7 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, struct cam_ope_top_reg_val *top_reg_val; struct cam_ope_dev_init *dev_init = data; uint32_t irq_mask, irq_status; + unsigned long flags; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -160,25 +178,41 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info, rc = wait_for_completion_timeout( &ope_top_info.reset_complete, - msecs_to_jiffies(30)); + msecs_to_jiffies(60)); cam_io_w_mb(top_reg_val->debug_cfg_val, top_reg->base + top_reg->debug_cfg); if (!rc || rc < 0) { - CAM_ERR(CAM_OPE, "reset error result = %d", rc); - irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_mask); - irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + - top_reg->irq_status); - CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x", - irq_mask, irq_status); - cam_ope_top_dump_debug_reg(ope_hw_info); - rc = -ETIMEDOUT; + spin_lock_irqsave(&ope_top_info.hw_lock, flags); + if (!completion_done(&ope_top_info.reset_complete)) { + CAM_DBG(CAM_OPE, + "IRQ delayed, checking the status registers"); + irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_mask); + irq_status = cam_io_r_mb(ope_hw_info->top_reg->base + + top_reg->irq_status); + if (irq_status & top_reg_val->rst_done) { + CAM_DBG(CAM_OPE, "ope reset done"); + cam_io_w_mb(irq_status, + top_reg->base + top_reg->irq_clear); + cam_io_w_mb(top_reg_val->irq_set_clear, + top_reg->base + top_reg->irq_cmd); + } else { + CAM_ERR(CAM_OPE, + "irq mask 0x%x irq status 0x%x", + irq_mask, irq_status); + cam_ope_top_dump_debug_reg(ope_hw_info); + rc = -ETIMEDOUT; + } + } else { + CAM_DBG(CAM_OPE, "reset done"); + rc = 0; + } + spin_unlock_irqrestore(&ope_top_info.hw_lock, flags); } else { rc = 0; } - /* enable interrupt mask */ cam_io_w_mb(top_reg_val->irq_mask, ope_hw_info->top_reg->base + top_reg->irq_mask); @@ -197,6 +231,7 @@ static int cam_ope_top_probe(struct ope_hw *ope_hw_info, } ope_top_info.ope_hw_info = ope_hw_info; + spin_lock_init(&ope_top_info.hw_lock); return rc; } @@ -207,9 +242,12 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info, int rc = 0; uint32_t irq_status; uint32_t violation_status; + uint32_t pp_hw_status = 0; struct cam_ope_top_reg *top_reg; struct cam_ope_top_reg_val *top_reg_val; + struct cam_ope_pp_reg *pp_reg; struct cam_ope_irq_data *irq_data = data; + int i; if (!ope_hw_info) { CAM_ERR(CAM_OPE, "Invalid ope_hw_info"); @@ -218,7 +256,9 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info, top_reg = ope_hw_info->top_reg; top_reg_val = ope_hw_info->top_reg_val; + pp_reg = ope_hw_info->pp_reg; + spin_lock(&ope_top_info.hw_lock); /* Read and Clear Top Interrupt status */ irq_status = cam_io_r_mb(top_reg->base + top_reg->irq_status); cam_io_w_mb(irq_status, @@ -237,7 +277,22 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info, top_reg->violation_status); irq_data->error = 1; CAM_ERR(CAM_OPE, "ope violation: %x", violation_status); + + for (i = 0; i < pp_reg->num_clients ; i++) { + pp_hw_status = 0; + pp_hw_status = + cam_io_r_mb(pp_reg->base + + pp_reg->pp_clients[i] + .hw_status); + + if (pp_hw_status) + CAM_ERR(CAM_OPE, + "ope pp hw_status offset 0x%x val 0x%x", + pp_reg->pp_clients[i].hw_status, + pp_hw_status); + } } + spin_unlock(&ope_top_info.hw_lock); return rc; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h index 428d66f7e9b8..57d90712bdeb 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h @@ -33,11 +33,13 @@ struct ope_top_ctx { * @top_ctx: OPE top context * @reset_complete: Reset complete flag * @ope_mutex: OPE hardware mutex + * @hw_lock: OPE hardware spinlock */ struct ope_top { struct ope_hw *ope_hw_info; struct ope_top_ctx top_ctx[OPE_CTX_MAX]; struct completion reset_complete; struct mutex ope_hw_mutex; + spinlock_t hw_lock; }; #endif /* OPE_TOP_H */ From 1406c9f45bfb4bd6bd910360c4542676819aec79 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Tue, 11 Aug 2020 13:53:02 +0530 Subject: [PATCH 481/790] msm: camera: ife: dump bandwidth and clock for cpas and ife At the time of overflow dump bandwidth and axi clock information from cpas along with the ife clock and csid clock. In RDI only use case add a check for rdi_irq_status mask; if it is not present skip checking which port has resulted in overflow. CRs-Fixed: 2764286 Change-Id: I8080d140c34f2ab64f7e56b080a0dab57488336e Signed-off-by: Tejas Prajapati --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 43 +++++++++++++------ .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 16 +++++++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 9 ++++ .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 13 +++++- .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 17 ++++++++ .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 12 ++++++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 5 ++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 4 ++ 9 files changed, 106 insertions(+), 14 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 0780034df25c..77391a4c2f7a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7347,6 +7347,7 @@ static int cam_ife_hw_mgr_handle_hw_dump_info( struct cam_isp_resource_node *rsrc_node = NULL; struct cam_hw_intf *hw_intf; uint32_t i, out_port_id; + uint64_t dummy_args; int rc = 0; list_for_each_entry(hw_mgr_res, @@ -7373,6 +7374,24 @@ static int cam_ife_hw_mgr_handle_hw_dump_info( } } + list_for_each_entry(hw_mgr_res, + &ife_hw_mgr_ctx->res_list_ife_csid, 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_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, + &dummy_args, + sizeof(uint64_t)); + if (rc) + CAM_ERR(CAM_ISP, + "CSID Clock Dump failed"); + } + } + } out_port_id = event_info->res_id & 0xFF; hw_mgr_res = @@ -7431,18 +7450,6 @@ static int cam_ife_hw_mgr_handle_hw_err( struct cam_ife_hw_event_recovery_data recovery_data = {0}; int rc = -EINVAL; - if (ctx) { - ife_hw_mgr_ctx = - (struct cam_ife_hw_mgr_ctx *)ctx; - if (event_info->res_type == - CAM_ISP_RESOURCE_VFE_IN && - !ife_hw_mgr_ctx->is_rdi_only_context && - event_info->res_id != - CAM_ISP_HW_VFE_IN_CAMIF) - cam_ife_hw_mgr_handle_hw_dump_info( - ife_hw_mgr_ctx, event_info); - } - if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; else if (event_info->res_type == CAM_ISP_RESOURCE_VFE_IN) @@ -7457,6 +7464,18 @@ static int cam_ife_hw_mgr_handle_hw_err( return rc; } + if (ctx) { + ife_hw_mgr_ctx = + (struct cam_ife_hw_mgr_ctx *)ctx; + if (event_info->res_type == + CAM_ISP_RESOURCE_VFE_IN && + !ife_hw_mgr_ctx->is_rdi_only_context && + event_info->res_id != + CAM_ISP_HW_VFE_IN_CAMIF) + cam_ife_hw_mgr_handle_hw_dump_info( + ife_hw_mgr_ctx, event_info); + } + core_idx = event_info->hw_idx; if (g_ife_hw_mgr.debug_cfg.enable_recovery) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 8b9e93a47cb1..627c5c5deaa1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3971,6 +3971,19 @@ static int cam_ife_csid_set_csid_clock( return 0; } +static int cam_ife_csid_dump_csid_clock( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + if (!csid_hw) + return -EINVAL; + + CAM_INFO(CAM_ISP, "CSID:%d clock rate %llu", + csid_hw->hw_intf->hw_idx, + csid_hw->clk_rate); + + return 0; +} + static int cam_ife_csid_set_sensor_dimension( struct cam_ife_csid_hw *csid_hw, void *cmd_args) { @@ -4203,6 +4216,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE: rc = cam_ife_csid_set_csid_clock(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_CLOCK_DUMP: + rc = cam_ife_csid_dump_csid_clock(csid_hw, cmd_args); + break; case CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED: rc = cam_ife_csid_set_csid_qcfa(csid_hw, cmd_args); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 443d1550772d..de5b0499603b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -125,6 +125,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, CAM_ISP_HW_CMD_GET_RES_FOR_MID, CAM_ISP_HW_CMD_BLANKING_UPDATE, + CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index 8139744ce84a..dbe17815130c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -87,6 +87,14 @@ static struct cam_vfe_rdi_reg_data vfe17x_rdi_3_data = { .reg_update_irq_mask = 0x100, }; +static struct cam_vfe_rdi_overflow_status vfe17x_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + static struct cam_vfe_top_ver2_hw_info vfe17x_top_hw_info = { .common_reg = &vfe17x_top_common_reg, .camif_hw_info = { @@ -104,6 +112,7 @@ static struct cam_vfe_top_ver2_hw_info vfe17x_top_hw_info = { &vfe17x_rdi_2_data, &vfe17x_rdi_3_data, }, + .rdi_irq_status = &vfe17x_rdi_irq_status, }, .num_mux = 4, .mux_type = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index be5c41976098..74614722f4fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -881,8 +881,13 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, if (status_0 & 0x20000000) CAM_INFO(CAM_ISP, "RDI0 OVERFLOW"); - if (status_0 & 0x40000000) + if (status_0 & 0x40000000) { CAM_INFO(CAM_ISP, "PD PIPE OVERFLOW"); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x1010, true, &val3); + CAM_INFO(CAM_ISP, "ife_rdi_Rd: 0x%x", val3); + cam_cpas_log_votes(); + } } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && bus_overflow_status) { @@ -1207,6 +1212,9 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + cam_vfe_camif_lite_print_status(irq_status, ret, camif_lite_priv); @@ -1226,6 +1234,9 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( ret = CAM_VFE_IRQ_STATUS_VIOLATION; + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + cam_vfe_camif_lite_print_status(irq_status, ret, camif_lite_priv); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 6b7efaa2c4cf..14960449e497 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -777,6 +777,8 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_mux_camif_data *camif_priv; struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; uint32_t irq_status0; uint32_t irq_status1; uint32_t val; @@ -793,6 +795,9 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_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]; + soc_info = camif_priv->soc_info; + soc_private = (struct cam_vfe_soc_private *)soc_info->soc_private; + evt_info.hw_idx = camif_node->hw_intf->hw_idx; evt_info.res_id = camif_node->res_id; evt_info.res_type = camif_node->res_type; @@ -882,6 +887,12 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, payload->irq_reg_val[2]); ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + + cam_cpas_log_votes(); + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_reg_dump(camif_node->res_priv); } @@ -902,6 +913,12 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, payload->irq_reg_val[2]); ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + + cam_cpas_log_votes(); + if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_reg_dump(camif_node->res_priv); } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index f5e2f7a0ea15..5de4a5d61a14 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1366,6 +1366,8 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_mux_camif_ver3_data *camif_priv; struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; struct timespec64 ts; uint32_t val = 0; @@ -1382,6 +1384,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, camif_priv = camif_node->res_priv; payload = evt_payload_priv; + soc_info = camif_priv->soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; + for (i = 0; i < CAM_IFE_IRQ_REGISTERS_MAX; i++) irq_status[i] = payload->irq_reg_val[i]; @@ -1469,6 +1475,9 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + cam_vfe_camif_ver3_print_status(irq_status, ret, camif_priv); if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) @@ -1498,6 +1507,9 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_VIOLATION; + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + cam_vfe_camif_ver3_print_status(irq_status, ret, camif_priv); if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index f9c6d8f4dc1d..4b47cf722338 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -523,6 +523,9 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_SUCCESS; } + if (!rdi_priv->rdi_irq_status) + goto end; + irq_rdi_status = (irq_status1 & rdi_priv->rdi_irq_status->rdi_overflow_mask); @@ -566,7 +569,7 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, (void *)&evt_info); cam_cpas_log_votes(); } - +end: cam_vfe_rdi_put_evt_payload(rdi_priv, &payload); CAM_DBG(CAM_ISP, "returing status = %d", ret); return ret; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 9bd442f8d96e..3b0b1f5f072c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -119,6 +119,7 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( rc = 0; goto end; } + ahb_vote.type = CAM_VOTE_ABSOLUTE; ahb_vote.vote.level = clk_lvl; cam_cpas_update_ahb_vote(soc_private->cpas_handle, &ahb_vote); @@ -651,6 +652,9 @@ int cam_vfe_top_ver3_stop(void *device_priv, soc_info = top_priv->common_data.soc_info; soc_private = soc_info->soc_private; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (mux_res->res_id < CAM_ISP_HW_VFE_IN_MAX) { rc = mux_res->stop(mux_res); } else { From f44caab86655c181e30a0ab035a86e9cc1351f11 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 14 Apr 2020 11:27:26 -0700 Subject: [PATCH 482/790] msm: camera: isp: Add uapi for IFE/SFE HW blocks Add support for IFE/SFE UAPI changes in ISP driver for Waipio SoC. CRs-Fixed: 2733230 Change-Id: I5320d2cf02afe1a2d203da65604c83d7b38cad38 Signed-off-by: Karthik Anantha Ram Signed-off-by: Vishalsingh Hajeri Signed-off-by: Mukund Madhusudan Atre --- include/uapi/Kbuild | 1 + include/uapi/camera/media/cam_cpas.h | 18 ++-- include/uapi/camera/media/cam_isp.h | 133 ++++++++++++++++++++++-- include/uapi/camera/media/cam_isp_sfe.h | 37 +++++++ 4 files changed, 170 insertions(+), 19 deletions(-) create mode 100644 include/uapi/camera/media/cam_isp_sfe.h diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild index 7aa1e88b6a77..d2a2f1fc3083 100644 --- a/include/uapi/Kbuild +++ b/include/uapi/Kbuild @@ -19,3 +19,4 @@ header-y += camera/media/cam_sync.h header-y += camera/media/cam_ope.h header-y += camera/media/cam_isp_tfe.h header-y += camera/media/cam_tfe.h +header-y += camera/media/cam_isp_sfe.h diff --git a/include/uapi/camera/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h index b30326af26c3..733770ffa477 100644 --- a/include/uapi/camera/media/cam_cpas.h +++ b/include/uapi/camera/media/cam_cpas.h @@ -52,14 +52,16 @@ #define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) -#define CAM_AXI_PATH_DATA_OPE_START_OFFSET 64 -#define CAM_AXI_PATH_DATA_OPE_RD_IN (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 0) -#define CAM_AXI_PATH_DATA_OPE_RD_REF (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 1) -#define CAM_AXI_PATH_DATA_OPE_WR_VID (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 2) -#define CAM_AXI_PATH_DATA_OPE_WR_DISP (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 3) -#define CAM_AXI_PATH_DATA_OPE_WR_REF (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 4) -#define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ - (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) +#define CAM_AXI_PATH_DATA_SFE_START_OFFSET 96 +#define CAM_AXI_PATH_DATA_SFE_NRDI (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 0) +#define CAM_AXI_PATH_DATA_SFE_RDI0 (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 1) +#define CAM_AXI_PATH_DATA_SFE_RDI1 (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 2) +#define CAM_AXI_PATH_DATA_SFE_RDI2 (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 3) +#define CAM_AXI_PATH_DATA_SFE_RDI3 (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 4) +#define CAM_AXI_PATH_DATA_SFE_RDI4 (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 5) +#define CAM_AXI_PATH_DATA_SFE_STATS (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 6) +#define CAM_AXI_PATH_DATA_SFE_MAX_OFFSET \ + (CAM_AXI_PATH_DATA_SFE_START_OFFSET + 31) #define CAM_AXI_PATH_DATA_ALL 256 #define CAM_CPAS_FUSES_MAX 32 diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index d99e0476fc18..848bab7f22b1 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -9,6 +9,7 @@ #include #include #include +#include #include /* ISP driver name */ @@ -22,7 +23,8 @@ #define CAM_ISP_HW_ISPIF 4 #define CAM_ISP_HW_IFE_LITE 5 #define CAM_ISP_HW_CSID_LITE 6 -#define CAM_ISP_HW_MAX 7 +#define CAM_ISP_HW_SFE 7 +#define CAM_ISP_HW_MAX 8 /* Color Pattern */ #define CAM_ISP_PATTERN_BAYER_RGRGRG 0 @@ -87,6 +89,16 @@ #define CAM_ISP_PACKET_META_REG_DUMP_PER_REQUEST 13 #define CAM_ISP_PACKET_META_REG_DUMP_ON_FLUSH 14 #define CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR 15 +#define CAM_ISP_PACKET_META_MODE_SWITCH_CONFIG 16 +#define CAM_ISP_PACKET_META_CSID_LEFT 17 +#define CAM_ISP_PACKET_META_CSID_RIGHT 18 +#define CAM_ISP_PACKET_META_CSID_COMMON 19 + +/* SFE packet meta_data type for command buffer */ +#define CAM_ISP_SFE_PACKET_META_LEFT 0x15 +#define CAM_ISP_SFE_PACKET_META_RIGHT 0x16 +#define CAM_ISP_SFE_PACKET_META_COMMON 0x17 +#define CAM_ISP_SFE_PACKET_META_DUAL_CONFIG 0x18 /* DSP mode */ #define CAM_ISP_DSP_MODE_NONE 0 @@ -108,6 +120,13 @@ #define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG 11 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG 12 #define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG 13 +#define CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG 14 +#define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CLOCK_CONFIG 21 +#define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CORE_CONFIG 22 +#define CAM_ISP_GENERIC_BLOB_TYPE_SFE_OUT_CONFIG 23 +#define CAM_ISP_GENERIC_BLOB_TYPE_SFE_HFR_CONFIG 24 +#define CAM_ISP_GENERIC_BLOB_TYPE_SFE_FE_CONFIG 25 +#define CAM_ISP_GENERIC_BLOB_TYPE_SFE_SCRATCH_BUF_CFG 26 #define CAM_ISP_VC_DT_CFG 4 @@ -119,6 +138,8 @@ #define CAM_ISP_IFE3_LITE_HW 0x20 #define CAM_ISP_IFE4_LITE_HW 0x40 #define CAM_ISP_IFE2_HW 0x100 +#define CAM_ISP_SFE0_HW 0x1000 +#define CAM_ISP_SFE1_HW 0x2000 #define CAM_ISP_PXL_PATH 0x1 #define CAM_ISP_PPP_PATH 0x2 @@ -133,6 +154,9 @@ #define CAM_ISP_USAGE_LEFT_PX 1 #define CAM_ISP_USAGE_RIGHT_PX 2 #define CAM_ISP_USAGE_RDI 3 +#define CAM_ISP_USAGE_SFE_LEFT 4 +#define CAM_ISP_USAGE_SFE_RIGHT 5 +#define CAM_ISP_USAGE_SFE_RDI 6 /* Acquire with custom hw */ #define CAM_ISP_ACQ_CUSTOM_NONE 0 @@ -141,6 +165,13 @@ #define CAM_IFE_CSID_RDI_MAX 4 +/* Feature Flag indicators */ +#define CAM_ISP_PARAM_FETCH_SECURITY_MODE BIT(0) + +/* ISP core cfg flag params */ +#define CAM_ISP_PARAM_CORE_CFG_HDR_MUX_SEL BIT(0) +#define CAM_ISP_PARAM_CORE_CFG_PP_FORMAT BIT(16) + /* Query devices */ /** * struct cam_isp_dev_cap_info - A cap info for particular hw type @@ -327,9 +358,15 @@ struct cam_isp_in_port_info { * @num_out_res: number of the output resource associated * @horizontal_bin: Horizontal Binning info * @qcfa_bin: Quadra Binning info - * @csid_res_1: payload for future use - * @csid_res_2: payload for future use - * @ife_res_1: payload for future use + * @sfe_in_path_type: SFE input path type + * 0:15 - refer to cam_isp_sfe.h for SFE paths + * 16:31 - Corresponding IFE i/p path type + * Example:((CAM_ISP_PXL_PATH << 16) | + * CAM_ISP_SFE_INLINE_PIX) + * This will acquire SFE inline IPP and IFE IPP + * PPP is an exception CSID PPP -> IFE PPP + * @vc_dt_pattern_id: TPG pattern - SparsePD, sHDR etc. + * @feature_flag: See the macros defined under feature flag above * @ife_res_2: payload for future use * @data: payload that contains the output resources * @@ -363,9 +400,9 @@ struct cam_isp_in_port_info_v2 { __u32 offline_mode; __u32 horizontal_bin; __u32 qcfa_bin; - __u32 csid_res_1; - __u32 csid_res_2; - __u32 ife_res_1; + __u32 sfe_in_path_type; + __u32 vc_dt_pattern_id; + __u32 feature_flag; __u32 ife_res_2; struct cam_isp_out_port_info_v2 data[1]; }; @@ -659,7 +696,8 @@ struct cam_isp_sensor_config { * @hdr_bhist_src_sel: Selects input for HDR BHIST module * @input_mux_sel_pdaf: Selects input for PDAF * @input_mux_sel_pp: Selects input for Pixel Pipe - * @reserved: Reserved + * @core_cfg_flag: Core config flag to set HDR mux/PP + * input format type */ struct cam_isp_core_config { __u32 version; @@ -673,7 +711,79 @@ struct cam_isp_core_config { __u32 hdr_bhist_src_sel; __u32 input_mux_sel_pdaf; __u32 input_mux_sel_pp; - __u32 reserved; + __u32 core_cfg_flag; +} __attribute__((packed)); + +/** + * struct cam_isp_sfe_core_config - SFE core registers configuration + * + * @version : Version info + * @mode_sel : Selects core for sHDR/non-sHDR mode + * @ops_mode_cfg : Selects core if is inline/offline mode + * @fs_mode_cfg : Selects output in fast shutter mode + * @sfe_params : SFE params for future use + */ +struct cam_isp_sfe_core_config { + __u32 version; + __u32 mode_sel; + __u32 ops_mode_cfg; + __u32 fs_mode_cfg; + __u32 sfe_params[6]; +} __attribute__((packed)); + +/** + * struct cam_isp_sfe_scratch_buf_info - Scratch buf info + * + * @mem_handle : Scratch buffer handle + * @offset : Offset to the buffer + * @width : Width in pixels + * @height : Height in pixels + * @stride : Stride in pixels + * @slice_height : Slice height in lines + * @resource_type : rsrc type + * @scratch_buf_params : for future use + */ +struct cam_isp_sfe_scratch_buf_info { + __s32 mem_handle; + __u32 offset; + __u32 width; + __u32 height; + __u32 stride; + __u32 slice_height; + __u32 resource_type; + __u32 scratch_buf_params[5]; +}; + +/** + * struct cam_isp_sfe_init_scratch_buf_config - SFE init buffer cfg + * Provides scratch buffer info for SFE ports + * as part of INIT packet + * + * @num_ports : Number of ports + * @reserved : reserved + * @port_scratch_cfg : scratch buffer info + */ +struct cam_isp_sfe_init_scratch_buf_config { + __u32 num_ports; + __u32 reserved; + struct cam_isp_sfe_scratch_buf_info port_scratch_cfg[1]; +}; + +/** + * struct cam_isp_tpg_core_config - TPG core registers configuration + * + * @version : Version info + * @vc_dt_pattern_id : TPG pattern - SparsePD, sHDR etc. + * @qcfa_en : Selects qcfa in color bar + * @pix_pattern : Pix pattern color bar cfg + * @tpg_params : TPG params for future use + */ +struct cam_isp_tpg_core_config { + __u32 version; + __u32 vc_dt_pattern_id; + __u32 qcfa_en; + __u32 pix_pattern; + __u32 tpg_params[6]; } __attribute__((packed)); /** @@ -715,7 +825,8 @@ struct cam_isp_acquire_hw_info { * being sent to NOC * @stride : Write master stride * @offset : Write master offset - * @reserved_1 : Reserved field for Write master config + * @addr_reuse_en : Enabling addr-reuse will write output to the same addr + * after the last addr that was read from FIFO. * @reserved_2 : Reserved field for Write master config * @reserved_3 : Reserved field for Write master config * @reserved_4 : Reserved field for Write master config @@ -729,7 +840,7 @@ struct cam_isp_vfe_wm_config { __u32 virtual_frame_en; __u32 stride; __u32 offset; - __u32 reserved_1; + __u32 addr_reuse_en; __u32 reserved_2; __u32 reserved_3; __u32 reserved_4; diff --git a/include/uapi/camera/media/cam_isp_sfe.h b/include/uapi/camera/media/cam_isp_sfe.h new file mode 100644 index 000000000000..629e2c07b9f6 --- /dev/null +++ b/include/uapi/camera/media/cam_isp_sfe.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __UAPI_CAM_ISP_SFE_H__ +#define __UAPI_CAM_ISP_SFE_H__ + +/* SFE output port resource type */ +#define CAM_ISP_SFE_OUT_RES_BASE 0x6000 + +#define CAM_ISP_SFE_OUT_RES_RDI_0 (CAM_ISP_SFE_OUT_RES_BASE + 0) +#define CAM_ISP_SFE_OUT_RES_RDI_1 (CAM_ISP_SFE_OUT_RES_BASE + 1) +#define CAM_ISP_SFE_OUT_RES_RDI_2 (CAM_ISP_SFE_OUT_RES_BASE + 2) +#define CAM_ISP_SFE_OUT_RES_RDI_3 (CAM_ISP_SFE_OUT_RES_BASE + 3) +#define CAM_ISP_SFE_OUT_RES_RDI_4 (CAM_ISP_SFE_OUT_RES_BASE + 4) +#define CAM_ISP_SFE_OUT_BE_STATS_0 (CAM_ISP_SFE_OUT_RES_BASE + 5) +#define CAM_ISP_SFE_OUT_BHIST_STATS_0 (CAM_ISP_SFE_OUT_RES_BASE + 6) +#define CAM_ISP_SFE_OUT_BE_STATS_1 (CAM_ISP_SFE_OUT_RES_BASE + 7) +#define CAM_ISP_SFE_OUT_BHIST_STATS_1 (CAM_ISP_SFE_OUT_RES_BASE + 8) +#define CAM_ISP_SFE_OUT_BE_STATS_2 (CAM_ISP_SFE_OUT_RES_BASE + 9) +#define CAM_ISP_SFE_OUT_BHIST_STATS_2 (CAM_ISP_SFE_OUT_RES_BASE + 10) +#define CAM_ISP_SFE_OUT_RES_LCR (CAM_ISP_SFE_OUT_RES_BASE + 11) +#define CAM_ISP_SFE_OUT_RES_RAW_DUMP (CAM_ISP_SFE_OUT_RES_BASE + 12) + +#define CAM_ISP_SFE_OUT_RES_MAX (CAM_ISP_SFE_OUT_RES_BASE + 13) + +/* SFE input port resource type */ +#define CAM_ISP_SFE_IN_RES_BASE 0x5000 + +#define CAM_ISP_SFE_INLINE_PIX (CAM_ISP_SFE_IN_RES_BASE + 0) +#define CAM_ISP_SFE_IN_RD_0 (CAM_ISP_SFE_IN_RES_BASE + 1) +#define CAM_ISP_SFE_IN_RD_1 (CAM_ISP_SFE_IN_RES_BASE + 2) +#define CAM_ISP_SFE_IN_RD_2 (CAM_ISP_SFE_IN_RES_BASE + 3) +#define CAM_ISP_SFE_IN_RES_MAX (CAM_ISP_SFE_IN_RES_BASE + 4) + +#endif /* __UAPI_CAM_ISP_SFE_H__ */ From 5bd4d81525f08700f063db2b0c5d6aaa3c3028ac Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 23 Jul 2020 16:24:20 -0700 Subject: [PATCH 483/790] msm: camera: csiphy: Remove config counter Currently config counter is being maintained at improper places as it is increment at configuration parser and decrease at release dev IOCTL. There are usecase where configuration can come multiple times without release dev IOCTL being called, in this case config counter will be out of sync with operation. Also, config counter is not being use anywhere in any decision making. This change removes config counter attributes to reduce the future maintenance and better code readabiltiy. Also, acquire count is correct check to make decision whether all device are release or not and with that reason update correct check in release dev IOCTL. CRs-Fixed: 2759031 Change-Id: Id0f36bc661ef1ae8070cc8d4fc148409c13e30bc Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 41 +++++++++---------- .../cam_csiphy/cam_csiphy_dev.h | 2 - 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 04814d45eacb..2cfdc2a99136 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -63,6 +63,19 @@ int32_t cam_csiphy_get_instance_offset( return i; } +static void cam_csiphy_reset_phyconfig_param(struct csiphy_device *csiphy_dev, + int32_t index) +{ + CAM_DBG(CAM_CSIPHY, "Resetting phyconfig param at index: %d", index); + csiphy_dev->csiphy_info[index].lane_cnt = 0; + csiphy_dev->csiphy_info[index].lane_assign = 0; + csiphy_dev->csiphy_info[index].lane_enable = 0; + csiphy_dev->csiphy_info[index].settle_time = 0; + csiphy_dev->csiphy_info[index].data_rate = 0; + csiphy_dev->csiphy_info[index].secure_mode = 0; + csiphy_dev->csiphy_info[index].hdl_data.device_hdl = -1; +} + void cam_csiphy_query_cap(struct csiphy_device *csiphy_dev, struct cam_csiphy_query_cap *csiphy_cap) { @@ -389,8 +402,6 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, cam_csiphy_update_secure_info(csiphy_dev, index); - csiphy_dev->config_count++; - CAM_DBG(CAM_CSIPHY, "phy version:%d, phy_idx: %d", csiphy_dev->hw_version, @@ -411,13 +422,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, return rc; reset_settings: - csiphy_dev->csiphy_info[index].lane_cnt = 0; - csiphy_dev->csiphy_info[index].lane_assign = 0; - csiphy_dev->csiphy_info[index].lane_enable = 0; - csiphy_dev->csiphy_info[index].settle_time = 0; - csiphy_dev->csiphy_info[index].data_rate = 0; - csiphy_dev->csiphy_info[index].secure_mode = 0; - csiphy_dev->csiphy_info[index].hdl_data.device_hdl = -1; + cam_csiphy_reset_phyconfig_param(csiphy_dev, index); return rc; } @@ -881,9 +886,7 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) csiphy_dev->csiphy_info[i].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_info[i].csiphy_cpas_cp_reg_mask = 0; - csiphy_dev->csiphy_info[i].settle_time = 0; - csiphy_dev->csiphy_info[i].data_rate = 0; + cam_csiphy_reset_phyconfig_param(csiphy_dev, i); } cam_csiphy_reset(csiphy_dev); @@ -1258,24 +1261,20 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev->csiphy_info[offset].hdl_data.device_hdl = -1; csiphy_dev->csiphy_info[offset].hdl_data.session_hdl = -1; - csiphy_dev->config_count--; + cam_csiphy_reset_phyconfig_param(csiphy_dev, offset); + if (csiphy_dev->acquire_count) { csiphy_dev->acquire_count--; CAM_DBG(CAM_CSIPHY, "Acquire_cnt: %d", csiphy_dev->acquire_count); } - if (csiphy_dev->start_dev_count == 0) { + if (csiphy_dev->acquire_count == 0) { CAM_DBG(CAM_CSIPHY, "All PHY devices released"); + csiphy_dev->combo_mode = 0; csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; } - if (csiphy_dev->config_count == 0) { - CAM_DBG(CAM_CSIPHY, "reset csiphy_info"); - csiphy_dev->csiphy_info[offset].lane_cnt = 0; - csiphy_dev->csiphy_info[offset].lane_assign = 0; - csiphy_dev->csiphy_info[offset].csiphy_3phase = -1; - csiphy_dev->combo_mode = 0; - } + break; } case CAM_CONFIG_DEV: { diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 3d467375d1e4..557fd4e70499 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -268,7 +268,6 @@ struct cam_csiphy_param { * @start_dev_count: Start count * @soc_info: SOC information * @cpas_handle: CPAS handle - * @config_count: Config reg count * @current_data_rate: Data rate in mbps * @csiphy_3phase: To identify DPHY or CPHY at top level * @combo_mode: Info regarding combo_mode is enable / disable @@ -298,7 +297,6 @@ struct csiphy_device { uint32_t start_dev_count; struct cam_hw_soc_info soc_info; uint32_t cpas_handle; - uint32_t config_count; uint64_t current_data_rate; uint64_t csiphy_cpas_cp_reg_mask[ CSIPHY_MAX_INSTANCES_PER_PHY]; From f1e30d210ad7207ffe867fd26beeff6ed37c19a4 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 28 Aug 2020 13:24:00 -0700 Subject: [PATCH 484/790] msm: camera: isp: Add go_cmd after rup_cmd for offline use-cases Add go_cmd after rup_cmd in cdm packet so that bus_rd is triggered after rup has been configured for IFE. CRs-Fixed: 2767783 Change-Id: I8978d582825bc0e4edc9f26a1d3f8f988bc11b81 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 0780034df25c..68c7d4fa22a2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6355,17 +6355,6 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } - /* add go_cmd for offline context */ - if (prepare->num_out_map_entries && prepare->num_in_map_entries && - ctx->is_offline) { - rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd, - ctx->base[i].idx, &kmd_buf); - if (rc) - CAM_ERR(CAM_ISP, - "Add GO_CMD faled i: %d, idx: %d, rc: %d", - i, ctx->base[i].idx, rc); - } - /* * reg update will be done later for the initial configure. * need to plus one to the op_code and only take the lower @@ -6437,6 +6426,17 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } + /* add go_cmd for offline context */ + if (prepare->num_out_map_entries && prepare->num_in_map_entries && + ctx->is_offline) { + rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd, + ctx->base[i].idx, &kmd_buf); + if (rc) + CAM_ERR(CAM_ISP, + "Add GO_CMD faled i: %d, idx: %d, rc: %d", + i, ctx->base[i].idx, rc); + } + end: return rc; } From c14978cb20816c2e33b4f3ba887b5bb10e96aa35 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 2 Sep 2020 16:54:40 -0700 Subject: [PATCH 485/790] msm: camera: icp: Increase request queue depth and frame cmd bitmap Increase the queue depth to support EIS3 use-cases. CRs-Fixed: 2768737 Change-Id: I02ef9da1a0d37208d2b3fd27092e9e03d38e4346 Signed-off-by: Karthik Anantha Ram --- drivers/cam_core/cam_context.h | 2 +- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 10bc72b89ab9..d649b22167a1 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -21,7 +21,7 @@ struct cam_context; /* max request number */ #define CAM_CTX_REQ_MAX 20 -#define CAM_CTX_ICP_REQ_MAX 36 +#define CAM_CTX_ICP_REQ_MAX 40 #define CAM_CTX_CFG_MAX 20 #define CAM_CTX_RES_MAX 20 diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index a4b3817680e8..1000ce72d425 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -23,7 +23,7 @@ #define CAM_ICP_ROLE_PARENT 1 #define CAM_ICP_ROLE_CHILD 2 -#define CAM_FRAME_CMD_MAX 20 +#define CAM_FRAME_CMD_MAX 40 #define CAM_MAX_OUT_RES 6 #define CAM_MAX_IN_RES 8 From 334028442ca40d8ee90fc50e3252f0bebd9d6bbe Mon Sep 17 00:00:00 2001 From: zhuo Date: Wed, 2 Sep 2020 17:44:07 +0800 Subject: [PATCH 486/790] msm: camera: memmgr: fix lack of condition lead to memory leak When multi map fails, the first mapping does not unmap due to lack of condition. CRs-Fixed: 2768768 Change-Id: Ib61ce8f5a73e5c27b1b19bbd23d6649c62feb0da Signed-off-by: zhuo --- drivers/cam_req_mgr/cam_mem_mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index a2952787762e..cb45531e1f32 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -626,10 +626,10 @@ static int cam_mem_util_map_hw_va(uint32_t flags, return rc; multi_map_fail: if (flags & CAM_MEM_FLAG_PROTECTED_MODE) - for (--i; i > 0; i--) + for (--i; i >= 0; i--) cam_smmu_unmap_stage2_iova(mmu_hdls[i], fd); else - for (--i; i > 0; i--) + for (--i; i >= 0; i--) cam_smmu_unmap_user_iova(mmu_hdls[i], fd, CAM_SMMU_REGION_IO); From f42f7b1e9ac0ba8b7a668eb85e298e011a8dea97 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Fri, 17 Jul 2020 16:18:06 -0700 Subject: [PATCH 487/790] msm: camera: icp: Adapt HFI to processor specific irq management The steps to enable and send interrupts will differ between processors. Pull this logic out of the HFI and out to the devices, so that we can adapt to the specific irq management of any processor. CRs-Fixed: 2722486 Change-Id: I2a889b91ec13295aa14bb2b16252332482a1225a Signed-off-by: Fernando Pacheco --- drivers/cam_icp/fw_inc/hfi_intf.h | 18 ++++++++-- drivers/cam_icp/fw_inc/hfi_reg.h | 19 +++------- drivers/cam_icp/hfi.c | 35 ++++++++++++++----- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 28 +++++++++++++++ drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 5 ++- drivers/cam_icp/icp_hw/a5_hw/a5_reg.h | 8 +++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 8 +++-- 7 files changed, 92 insertions(+), 29 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 062762306454..01777b831fab 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -49,6 +49,16 @@ struct hfi_mem_info { void __iomem *icp_base; }; +/** + * struct hfi_ops + * @irq_raise: called to raise H2ICP interrupt + * @irq_enable: called to enable interrupts from ICP + */ +struct hfi_ops { + void (*irq_raise)(void *data); + void (*irq_enable)(void *data); +}; + /** * hfi_write_cmd() - function for hfi write * @cmd_ptr: pointer to command data for hfi write @@ -70,14 +80,16 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); /** * hfi_init() - function initialize hfi after firmware download - * @event_driven_mode: event mode * @hfi_mem: hfi memory info + * @hfi_ops: processor-specific hfi ops + * @priv: device private data + * @event_driven_mode: event mode * @icp_base: icp base address * * Returns success(zero)/failure(non zero) */ -int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void *__iomem icp_base); +int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode, void *__iomem icp_base); /** * hfi_get_hw_caps() - hardware capabilities from firmware diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index cf928ed1db43..c96080bd67fb 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -11,8 +11,6 @@ /* start of ICP CSR registers */ #define HFI_REG_A5_HW_VERSION 0x0 -#define HFI_REG_A5_CSR_A2HOSTINTEN 0x10 -#define HFI_REG_A5_CSR_HOST2ICPINT 0x30 /* general purpose registers from */ #define HFI_REG_FW_VERSION 0x44 @@ -97,19 +95,6 @@ enum reg_settings { SET_WM = 1024 }; -/** - * @INTR_DISABLE: Disable interrupt - * @INTR_ENABLE: Enable interrupt - * @INTR_ENABLE_WD0: Enable WD0 - * @INTR_ENABLE_WD1: Enable WD1 - */ -enum intr_status { - INTR_DISABLE, - INTR_ENABLE, - INTR_ENABLE_WD0, - INTR_ENABLE_WD1 = 0x4 -}; - /** * @ICP_INIT_RESP_RESET: reset init state * @ICP_INIT_RESP_SUCCESS: init success @@ -284,6 +269,7 @@ struct hfi_qtbl { /** * struct hfi_info * @map: Hfi shared memory info + * @ops: processor-specific ops * @smem_size: Shared memory size * @uncachedheap_size: uncached heap size * @msgpacket_buf: message buffer @@ -293,9 +279,11 @@ struct hfi_qtbl { * @mutex msg_q_lock: Lock for message queue * @msg_q_state: State of message queue * @csr_base: CSR base address + * @priv: device private data */ struct hfi_info { struct hfi_mem_info map; + struct hfi_ops ops; uint32_t smem_size; uint32_t uncachedheap_size; uint32_t msgpacket_buf[ICP_HFI_MAX_MSG_SIZE_IN_WORDS]; @@ -305,6 +293,7 @@ struct hfi_info { struct mutex msg_q_lock; bool msg_q_state; void __iomem *csr_base; + void *priv; }; #endif /* _CAM_HFI_REG_H_ */ diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index f88450aad166..32f0fe0f7810 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -39,6 +39,18 @@ unsigned int g_icp_mmu_hdl; static DEFINE_MUTEX(hfi_cmd_q_mutex); static DEFINE_MUTEX(hfi_msg_q_mutex); +static void hfi_irq_raise(struct hfi_info *hfi) +{ + if (hfi->ops.irq_raise) + hfi->ops.irq_raise(hfi->priv); +} + +static void hfi_irq_enable(struct hfi_info *hfi) +{ + if (hfi->ops.irq_enable) + hfi->ops.irq_enable(hfi->priv); +} + void cam_hfi_queue_dump(void) { struct hfi_qtbl *qtbl; @@ -160,8 +172,7 @@ int hfi_write_cmd(void *cmd_ptr) * firmware to process */ wmb(); - cam_io_w_mb((uint32_t)INTR_ENABLE, - g_hfi->csr_base + HFI_REG_A5_CSR_HOST2ICPINT); + hfi_irq_raise(g_hfi); err: mutex_unlock(&hfi_cmd_q_mutex); return rc; @@ -554,8 +565,7 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) return -ETIMEDOUT; } - cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), - icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); + hfi_irq_enable(g_hfi); fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version); @@ -592,8 +602,8 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) return rc; } -int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void __iomem *icp_base) +int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode, void __iomem *icp_base) { int rc = 0; struct hfi_qtbl *qtbl; @@ -602,6 +612,13 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, uint32_t hw_version, fw_version, status = 0; struct sfr_buf *sfr_buffer; + if (!hfi_mem || !hfi_ops || !priv) { + CAM_ERR(CAM_HFI, + "invalid arg: hfi_mem=%pK hfi_ops=%pK priv=%pK", + hfi_mem, hfi_ops, priv); + return -EINVAL; + } + mutex_lock(&hfi_cmd_q_mutex); mutex_lock(&hfi_msg_q_mutex); @@ -784,8 +801,10 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; g_hfi->msg_q_state = true; - cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), - icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); + g_hfi->ops = *hfi_ops; + g_hfi->priv = priv; + + hfi_irq_enable(g_hfi); mutex_unlock(&hfi_cmd_q_mutex); mutex_unlock(&hfi_msg_q_mutex); diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 6b257392a3ec..8b6b068a64cd 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -485,6 +485,34 @@ irqreturn_t cam_a5_irq(int irq_num, void *data) return IRQ_HANDLED; } +void cam_a5_irq_raise(void *priv) +{ + struct cam_hw_info *a5_info = priv; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return; + } + + cam_io_w_mb(A5_HOSTINT, + a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base + + ICP_SIERRA_A5_CSR_HOST2ICPINT); +} + +void cam_a5_irq_enable(void *priv) +{ + struct cam_hw_info *a5_info = priv; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return; + } + + cam_io_w_mb(A5_WDT_WS0EN | A5_A2HOSTINTEN, + a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base + + ICP_SIERRA_A5_CSR_A2HOSTINTEN); +} + int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h index f6edebbc3141..98a18165dd0d 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_A5_CORE_H @@ -81,6 +81,9 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, irqreturn_t cam_a5_irq(int irq_num, void *data); +void cam_a5_irq_raise(void *priv); +void cam_a5_irq_enable(void *priv); + /** * @brief : API to register a5 hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h index 049748adbe1a..0a8e38d9ad52 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h @@ -23,6 +23,14 @@ A5_CSR_WAKE_UP_EN | \ A5_CSR_EN_CLKGATE_WFI) +#define ICP_SIERRA_A5_CSR_A2HOSTINTEN 0x10 +#define A5_WDT_WS1EN (1 << 2) +#define A5_WDT_WS0EN (1 << 1) +#define A5_A2HOSTINTEN (1 << 0) + +#define ICP_SIERRA_A5_CSR_HOST2ICPINT 0x30 +#define A5_HOSTINT (1 << 0) + #define ICP_SIERRA_A5_CSR_A5_STATUS 0x200 #define A5_CSR_A5_STANDBYWFI (1 << 7) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 9be1a940fe6d..ed8e9cb0b61e 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3624,6 +3624,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) struct cam_hw_intf *a5_dev_intf = NULL; struct cam_hw_info *a5_dev = NULL; struct hfi_mem_info hfi_mem; + struct hfi_ops hfi_ops; a5_dev_intf = hw_mgr->a5_dev_intf; if (!a5_dev_intf) { @@ -3688,8 +3689,11 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.len = 0x0; } - return cam_hfi_init(0, &hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + hfi_ops.irq_raise = cam_a5_irq_raise; + hfi_ops.irq_enable = cam_a5_irq_enable; + + return cam_hfi_init(&hfi_mem, &hfi_ops, a5_dev, 0, + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) From 8b0144bd3a112169ce80ebadb8d022f3a688cd2b Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 1 Sep 2020 11:00:33 -0700 Subject: [PATCH 488/790] msm: camera: isp: Enable PIX & LINE count irqs by default Enable these format measure error IRQs by default in CSID. CRs-Fixed: 2767775 Change-Id: Ie23d343cf2ac80d2b22096db3cbfc044a4e64fc9 Signed-off-by: Karthik Anantha Ram --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 8b9e93a47cb1..e84a2b5d5f7a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2154,9 +2154,8 @@ static int cam_ife_csid_enable_pxl_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; - if (path_config->measure_enabled) - val |= (CSID_PATH_ERROR_PIX_COUNT | - CSID_PATH_ERROR_LINE_COUNT); + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_mask_addr); @@ -2781,9 +2780,8 @@ static int cam_ife_csid_enable_rdi_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; - if (csid_hw->rdi_path_config[id].measure_enabled) - val |= (CSID_PATH_ERROR_PIX_COUNT | - CSID_PATH_ERROR_LINE_COUNT); + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); @@ -4827,14 +4825,15 @@ handle_fatal_error: csid_hw->hw_intf->hw_idx, irq_status[CAM_IFE_CSID_IRQ_REG_IPP]); CAM_ERR(CAM_ISP, - "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", + "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x [format_measure0: 0x%x]", csid_hw->ipp_path_config.height, csid_hw->ipp_path_config.width, ((val >> csid_reg->cmn_reg->format_measure_height_shift_val) & csid_reg->cmn_reg->format_measure_height_mask_val), val & - csid_reg->cmn_reg->format_measure_width_mask_val); + csid_reg->cmn_reg->format_measure_width_mask_val, + val); } } @@ -4898,14 +4897,15 @@ handle_fatal_error: csid_hw->hw_intf->hw_idx, irq_status[CAM_IFE_CSID_IRQ_REG_PPP]); CAM_ERR(CAM_ISP, - "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", + "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x [format_measure0: 0x%x]", csid_hw->ppp_path_config.height, csid_hw->ppp_path_config.width, ((val >> csid_reg->cmn_reg->format_measure_height_shift_val) & csid_reg->cmn_reg->format_measure_height_mask_val), val & - csid_reg->cmn_reg->format_measure_width_mask_val); + csid_reg->cmn_reg->format_measure_width_mask_val, + val); } } @@ -4963,7 +4963,7 @@ handle_fatal_error: "CSID:%d irq_status_rdi[%d]:0x%x", csid_hw->hw_intf->hw_idx, i, irq_status[i]); CAM_ERR(CAM_ISP, - "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x", + "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x [format_measure0: 0x%x]", ((val2 >> csid_reg->cmn_reg->format_measure_height_shift_val) & csid_reg->cmn_reg->format_measure_height_mask_val), @@ -4973,7 +4973,8 @@ handle_fatal_error: csid_reg->cmn_reg->format_measure_height_shift_val) & csid_reg->cmn_reg->format_measure_height_mask_val), val & - csid_reg->cmn_reg->format_measure_width_mask_val); + csid_reg->cmn_reg->format_measure_width_mask_val, + val); } } From 19dbfda860f76397d394b33e7cb12fb6b470c34e Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 5 Jun 2020 22:42:27 +0530 Subject: [PATCH 489/790] msm: camera: ope: Updated logic to calculate num bw path Ope driver was incorrectly calculating the number of bw path. This is causing bw to be skip for some of the ports. Updated logic to correctly calculate number of path based on valid path type. CRs-Fixed: 2715586 Change-Id: I95b6dcfae454713a7b5db6d629310244bb304b19 Signed-off-by: Alok Chauhan --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 43 ++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index ca17328d41ae..ef01db9b13f7 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1320,6 +1320,46 @@ static int cam_ope_mgr_update_clk_rate(struct cam_ope_hw_mgr *hw_mgr, return 0; } +static int cam_ope_mgr_calculate_num_path( + struct cam_ope_clk_bw_req_internal_v2 *clk_info, + struct cam_ope_ctx *ctx_data) +{ + int i, path_index = 0; + + for (i = 0; i < CAM_OPE_MAX_PER_PATH_VOTES; i++) { + if ((clk_info->axi_path[i].path_data_type < + CAM_AXI_PATH_DATA_OPE_START_OFFSET) || + (clk_info->axi_path[i].path_data_type > + CAM_AXI_PATH_DATA_OPE_MAX_OFFSET) || + ((clk_info->axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_OPE_START_OFFSET) >= + CAM_OPE_MAX_PER_PATH_VOTES)) { + CAM_WARN(CAM_OPE, + "Invalid path %d, start offset=%d, max=%d", + ctx_data->clk_info.axi_path[i].path_data_type, + CAM_AXI_PATH_DATA_OPE_START_OFFSET, + CAM_OPE_MAX_PER_PATH_VOTES); + continue; + } + + path_index = clk_info->axi_path[i].path_data_type - + CAM_AXI_PATH_DATA_OPE_START_OFFSET; + + CAM_DBG(CAM_OPE, + "clk_info: i[%d]: [%s %s] bw [%lld %lld] num_path: %d", + i, + cam_cpas_axi_util_trans_type_to_string( + clk_info->axi_path[i].transac_type), + cam_cpas_axi_util_path_type_to_string( + clk_info->axi_path[i].path_data_type), + clk_info->axi_path[i].camnoc_bw, + clk_info->axi_path[i].mnoc_ab_bw, + clk_info->num_paths); + } + + return (path_index+1); +} + static bool cam_ope_update_bw_v2(struct cam_ope_hw_mgr *hw_mgr, struct cam_ope_ctx *ctx_data, struct cam_ope_clk_info *hw_mgr_clk_info, @@ -1402,7 +1442,8 @@ static bool cam_ope_update_bw_v2(struct cam_ope_hw_mgr *hw_mgr, ctx_data->clk_info.axi_path[i].ddr_ib_bw; } - ctx_data->clk_info.num_paths = clk_info->num_paths; + ctx_data->clk_info.num_paths = + cam_ope_mgr_calculate_num_path(clk_info, ctx_data); memcpy(&ctx_data->clk_info.axi_path[0], &clk_info->axi_path[0], From eadc13255c4f7679ad815a14df3abd26b5ebf7ca Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 18 Aug 2020 16:55:47 -0700 Subject: [PATCH 490/790] msm: camera: cdm: Fix parsing of supported cdm clients cdm client check for loading number of clients is not correct. It does not take error codes into account. The variable that holds the value is of incorrect data type. CRs-fixed: 2768636 Change-Id: Ie5b752aa6bc7a70fe777c16a70a5bdb2e5a663a4 Signed-off-by: Jigar Agrawal --- drivers/cam_cdm/cam_cdm_soc.c | 62 ++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_soc.c b/drivers/cam_cdm/cam_cdm_soc.c index ec8a9e096a7b..ba4ff1ac6e33 100644 --- a/drivers/cam_cdm/cam_cdm_soc.c +++ b/drivers/cam_cdm/cam_cdm_soc.c @@ -78,51 +78,52 @@ permission_error: } int cam_cdm_soc_load_dt_private(struct platform_device *pdev, - struct cam_cdm_private_dt_data *ptr) + struct cam_cdm_private_dt_data *cdm_pvt_data) { - int i, rc = -EINVAL, num_fifo_entries = 0; + int i, rc = -EINVAL, num_fifo_entries = 0, num_clients = 0; - ptr->dt_num_supported_clients = of_property_count_strings( - pdev->dev.of_node, - "cdm-client-names"); - CAM_DBG(CAM_CDM, "Num supported cdm_client = %d", - ptr->dt_num_supported_clients); - if (ptr->dt_num_supported_clients > - CAM_PER_CDM_MAX_REGISTERED_CLIENTS) { + num_clients = of_property_count_strings( + pdev->dev.of_node, "cdm-client-names"); + if ((num_clients <= 0) || + (num_clients > CAM_PER_CDM_MAX_REGISTERED_CLIENTS)) { CAM_ERR(CAM_CDM, "Invalid count of client names count=%d", - ptr->dt_num_supported_clients); + num_clients); + rc = -EINVAL; goto end; } - if (ptr->dt_num_supported_clients < 0) { - CAM_DBG(CAM_CDM, "No cdm client names found"); - ptr->dt_num_supported_clients = 0; - ptr->dt_cdm_shared = false; - } else { - ptr->dt_cdm_shared = true; - } - for (i = 0; i < ptr->dt_num_supported_clients; i++) { + + cdm_pvt_data->dt_num_supported_clients = (uint32_t)num_clients; + CAM_DBG(CAM_CDM, "Num supported cdm_client = %u", + cdm_pvt_data->dt_num_supported_clients); + + cdm_pvt_data->dt_cdm_shared = true; + + for (i = 0; i < cdm_pvt_data->dt_num_supported_clients; i++) { rc = of_property_read_string_index(pdev->dev.of_node, - "cdm-client-names", i, &(ptr->dt_cdm_client_name[i])); - CAM_DBG(CAM_CDM, "cdm-client-names[%d] = %s", i, - ptr->dt_cdm_client_name[i]); + "cdm-client-names", i, + &(cdm_pvt_data->dt_cdm_client_name[i])); + CAM_DBG(CAM_CDM, "cdm-client-names[%d] = %s", i, + cdm_pvt_data->dt_cdm_client_name[i]); if (rc < 0) { - CAM_ERR(CAM_CDM, "Reading cdm-client-names failed"); + CAM_ERR(CAM_CDM, + "Reading cdm-client-names failed for client: %d", + i); goto end; } } rc = of_property_read_u8(pdev->dev.of_node, "cdm-priority-group", - &ptr->priority_group); + &cdm_pvt_data->priority_group); if (rc < 0) { - ptr->priority_group = 0; + cdm_pvt_data->priority_group = 0; rc = 0; } - ptr->config_fifo = of_property_read_bool(pdev->dev.of_node, + cdm_pvt_data->config_fifo = of_property_read_bool(pdev->dev.of_node, "config-fifo"); - if (ptr->config_fifo) { + if (cdm_pvt_data->config_fifo) { num_fifo_entries = of_property_count_u32_elems( pdev->dev.of_node, "fifo-depths"); @@ -135,7 +136,7 @@ int cam_cdm_soc_load_dt_private(struct platform_device *pdev, } for (i = 0; i < num_fifo_entries; i++) { rc = of_property_read_u32_index(pdev->dev.of_node, - "fifo-depths", i, &ptr->fifo_depth[i]); + "fifo-depths", i, &cdm_pvt_data->fifo_depth[i]); if (rc < 0) { CAM_ERR(CAM_CDM, "Unable to read fifo-depth rc %d", @@ -143,13 +144,14 @@ int cam_cdm_soc_load_dt_private(struct platform_device *pdev, goto end; } CAM_DBG(CAM_CDM, "FIFO%d depth is %d", - i, ptr->fifo_depth[i]); + i, cdm_pvt_data->fifo_depth[i]); } } else { for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) { - ptr->fifo_depth[i] = CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT; + cdm_pvt_data->fifo_depth[i] = + CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT; CAM_DBG(CAM_CDM, "FIFO%d depth is %d", - i, ptr->fifo_depth[i]); + i, cdm_pvt_data->fifo_depth[i]); } } end: From e262fee611f72c7a6b791e0843cf4b33dff5ccf6 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 3 Sep 2020 17:52:37 +0530 Subject: [PATCH 491/790] msm: camera: isp: Add check to dump supported fifo level registers in shima Add check to dump supported debug register for shima target. This change prevent unexpected behaviour during reading unsupported fifo level register. CRs-Fixed: 2770220 Change-Id: I33608e1ef92ca45acdc04667f61bb2d1536cbb8b Signed-off-by: Chandan Kumar Jha --- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 21 +++++++++++++++---- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 21 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index 1cc89c32013a..a718fc056d34 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -841,12 +841,22 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private = NULL; uint32_t val0, val1, val2, val3, val4; + uint32_t camera_hw_version; + int rc = 0; + + val3 = val4 = 0; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + return; + } + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; violation_status = status[CAM_IFE_IRQ_VIOLATION_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; @@ -1010,10 +1020,13 @@ print_state: CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + + if (camera_hw_version == CAM_CPAS_TITAN_580_V100) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + } CAM_INFO(CAM_ISP, "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 67cd7f4cd587..b07dbbb6ea74 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -916,12 +916,22 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private; uint32_t val0, val1, val2, val3, val4; + uint32_t camera_hw_version; + int rc = 0; + + val3 = val4 = 0; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + return; + } + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; @@ -1241,10 +1251,13 @@ print_state: CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + + if (camera_hw_version == CAM_CPAS_TITAN_580_V100) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + } CAM_INFO(CAM_ISP, "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", From 0934fe0103b8442d1dbfc9c9491f42b0db388444 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 30 Mar 2020 16:55:19 -0700 Subject: [PATCH 492/790] msm: camera: isp: Add code for SFE HW Add initial code drop for SFE HW. CRs-Fixed: 2733230 Change-Id: I44437bbe05d8c60d219c31cb626a4c9845a469e0 Signed-off-by: Jigarkumar Zala --- drivers/Makefile | 5 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw/include/cam_sfe_hw_intf.h | 157 +++++++++++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c | 263 ++++++++++++++++++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h | 61 ++++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c | 193 +++++++++++++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h | 35 +++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c | 126 +++++++++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h | 106 +++++++ drivers/cam_utils/cam_debug_util.c | 3 + drivers/cam_utils/cam_debug_util.h | 1 + 11 files changed, 951 insertions(+) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h diff --git a/drivers/Makefile b/drivers/Makefile index 154009e6005c..b4cd9bb27356 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -97,6 +97,11 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/cam_isp_dev.o \ cam_isp/cam_isp_context.o +camera-$(CONFIG_SPECTRA_SFE) += \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.o + camera-$(CONFIG_SPECTRA_ICP) += \ cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.o \ cam_icp/icp_hw/ipe_hw/ipe_dev.o \ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index de5b0499603b..7bbff8fab2ae 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -49,6 +49,7 @@ enum cam_isp_hw_type { CAM_ISP_HW_TYPE_TFE, CAM_ISP_HW_TYPE_TFE_CSID, CAM_ISP_HW_TYPE_TPG, + CAM_ISP_HW_TYPE_SFE, CAM_ISP_HW_TYPE_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h new file mode 100644 index 000000000000..8fab99e2128b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_HW_INTF_H_ +#define _CAM_SFE_HW_INTF_H_ + +#include "cam_isp_hw.h" + +#define CAM_SFE_HW_NUM_MAX 2 +#define SFE_CORE_BASE_IDX 0 + +enum cam_isp_hw_sfe_in { + CAM_ISP_HW_SFE_IN_PIX, + CAM_ISP_HW_SFE_IN_RD0, + CAM_ISP_HW_SFE_IN_RD1, + CAM_ISP_HW_SFE_IN_RD2, + CAM_ISP_HW_SFE_IN_RDI0, + CAM_ISP_HW_SFE_IN_RDI1, + CAM_ISP_HW_SFE_IN_RDI2, + CAM_ISP_HW_SFE_IN_RDI3, + CAM_ISP_HW_SFE_IN_RDI4, + CAM_ISP_HW_SFE_IN_MAX, +}; + +enum cam_sfe_hw_irq_status { + CAM_SFE_IRQ_STATUS_SUCCESS, + CAM_SFE_IRQ_STATUS_ERR, + CAM_SFE_IRQ_STATUS_OVERFLOW, + CAM_SFE_IRQ_STATUS_VIOLATION, + CAM_SFE_IRQ_STATUS_MAX, +}; + +/* + * struct cam_sfe_hw_get_hw_cap: + * + * @reserved_1: reserved + * @reserved_2: reserved + * @reserved_3: reserved + * @reserved_4: reserved + */ +struct cam_sfe_hw_get_hw_cap { + uint32_t reserved_1; + uint32_t reserved_2; + uint32_t reserved_3; + uint32_t reserved_4; +}; + +/* + * struct cam_sfe_hw_vfe_bus_rd_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @res_id: Unique Identity of port to associate with this + * resource. + * @is_dual: Flag to indicate dual SFE usecase + * @cdm_ops: CDM operations + * @unpacket_fmt: Unpacker format for read engine + * @is_offline: Flag to indicate offline usecase + */ +struct cam_sfe_hw_sfe_bus_rd_acquire_args { + struct cam_isp_resource_node *rsrc_node; + uint32_t res_id; + uint32_t is_dual; + struct cam_cdm_utils_ops *cdm_ops; + uint32_t unpacker_fmt; + bool is_offline; +}; + +/* + * struct cam_sfe_hw_sfe_bus_in_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @res_id: Unique Identity of port to associate with this + * resource. + * @cdm_ops: CDM operations + * @is_dual: Dual mode usecase + * @sync_mode: If in dual mode, indicates master/slave + * @in_port: in port info + * @is_fe_enabled: Flag to indicate if FE is enabled + * @is_offline: Flag to indicate Offline IFE + */ +struct cam_sfe_hw_sfe_in_acquire_args { + struct cam_isp_resource_node *rsrc_node; + uint32_t res_id; + struct cam_cdm_utils_ops *cdm_ops; + uint32_t is_dual; + enum cam_isp_hw_sync_mode sync_mode; + struct cam_isp_in_port_generic_info *in_port; + bool is_fe_enabled; + bool is_offline; +}; + +/* + * struct cam_sfe_hw_sfe_out_acquire_args: + * + * @rsrc_node: Pointer to Resource Node object, filled if acquire + * is successful + * @out_port_info: Output Port details to acquire + * @unique_id: Unique Identity of Context to associate with this + * resource. Used for composite grouping of multiple + * resources in the same context + * @is_dual: Dual SFE or not + * @split_id: In case of Dual SFE, this is Left or Right. + * @is_master: In case of Dual SFE, this is Master or Slave. + * @cdm_ops: CDM operations + */ +struct cam_sfe_hw_sfe_out_acquire_args { + struct cam_isp_resource_node *rsrc_node; + struct cam_isp_out_port_generic_info *out_port_info; + uint32_t unique_id; + uint32_t is_dual; + enum cam_isp_hw_split_id split_id; + uint32_t is_master; + struct cam_cdm_utils_ops *cdm_ops; +}; + +/* + * struct cam_sfe_acquire_args: + * + * @rsrc_type: Type of Resource (OUT/IN) to acquire + * @tasklet: Tasklet to associate with this resource. This is + * used to schedule bottom of IRQ events associated + * with this resource. + * @priv: Context data + * @event_cb: Callback function to hw mgr in case of hw events + * @sfe_out: Acquire args for SFE_OUT + * @sfe_bus_rd Acquire args for SFE_BUS_READ + * @sfe_in: Acquire args for SFE_IN + */ +struct cam_sfe_acquire_args { + enum cam_isp_resource_type rsrc_type; + void *tasklet; + void *priv; + cam_hw_mgr_event_cb_func event_cb; + union { + struct cam_sfe_hw_sfe_out_acquire_args sfe_out; + struct cam_sfe_hw_sfe_in_acquire_args sfe_in; + struct cam_sfe_hw_sfe_bus_rd_acquire_args sfe_rd; + }; +}; + +/* + * cam_sfe_hw_init() + * + * @Brief: Initialize SFE HW device + * + * @sfe_hw: sfe_hw interface to fill in and return on + * successful initialization + * @hw_idx: Index of SFE HW + */ +int cam_sfe_hw_init(struct cam_hw_intf **sfe_hw, uint32_t hw_idx); + +#endif /* _CAM_SFE_HW_INTF_H_ */ + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c new file mode 100644 index 000000000000..73e29bee3c46 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "cam_tasklet_util.h" +#include "cam_sfe_hw_intf.h" +#include "cam_sfe_soc.h" +#include "cam_sfe_core.h" +#include "cam_debug_util.h" + +static const char drv_name[] = "sfe"; +#define SFE_CORE_BASE_IDX 0 + +int cam_sfe_get_hw_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size) +{ + CAM_DBG(CAM_SFE, "Enter"); + return 0; +} + +int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_isp_resource_node *isp_res = NULL; + int rc = 0; + + CAM_DBG(CAM_SFE, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_SFE, "Invalid arguments"); + return -EINVAL; + } + + mutex_lock(&sfe_hw->hw_mutex); + sfe_hw->open_count++; + if (sfe_hw->open_count > 1) { + mutex_unlock(&sfe_hw->hw_mutex); + CAM_DBG(CAM_SFE, "SFE has already been initialized cnt %d", + sfe_hw->open_count); + return 0; + } + mutex_unlock(&sfe_hw->hw_mutex); + + soc_info = &sfe_hw->soc_info; + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + + /* Turn ON Regulators, Clocks and other SOC resources */ + rc = cam_sfe_enable_soc_resources(soc_info); + if (rc) { + CAM_ERR(CAM_SFE, "Enable SOC failed"); + rc = -EFAULT; + goto decrement_open_cnt; + } + + isp_res = (struct cam_isp_resource_node *)init_hw_args; + if (isp_res && isp_res->init) { + rc = isp_res->init(isp_res, NULL, 0); + if (rc) { + CAM_ERR(CAM_SFE, "init Failed rc=%d", rc); + goto disable_soc; + } + } + + CAM_DBG(CAM_SFE, "Enable soc done"); + + /* Do HW Reset */ + rc = cam_sfe_reset(hw_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_SFE, "Reset Failed rc=%d", rc); + goto deinit_sfe_res; + } + + sfe_hw->hw_state = CAM_HW_STATE_POWER_UP; + return rc; + +deinit_sfe_res: + if (isp_res && isp_res->deinit) + isp_res->deinit(isp_res, NULL, 0); +disable_soc: + cam_sfe_disable_soc_resources(soc_info); +decrement_open_cnt: + mutex_lock(&sfe_hw->hw_mutex); + sfe_hw->open_count--; + mutex_unlock(&sfe_hw->hw_mutex); + return rc; +} + +int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_isp_resource_node *isp_res = NULL; + int rc = 0; + + CAM_DBG(CAM_SFE, "Enter"); + if (!hw_priv) { + CAM_ERR(CAM_SFE, "Invalid arguments"); + return -EINVAL; + } + + mutex_lock(&sfe_hw->hw_mutex); + if (!sfe_hw->open_count) { + mutex_unlock(&sfe_hw->hw_mutex); + CAM_ERR(CAM_SFE, "Error! Unbalanced deinit"); + return -EFAULT; + } + sfe_hw->open_count--; + if (sfe_hw->open_count) { + mutex_unlock(&sfe_hw->hw_mutex); + CAM_DBG(CAM_SFE, "open_cnt non-zero =%d", sfe_hw->open_count); + return 0; + } + mutex_unlock(&sfe_hw->hw_mutex); + + soc_info = &sfe_hw->soc_info; + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + + isp_res = (struct cam_isp_resource_node *)deinit_hw_args; + if (isp_res && isp_res->deinit) { + rc = isp_res->deinit(isp_res, NULL, 0); + if (rc) + CAM_ERR(CAM_SFE, "deinit failed"); + } + + /* Turn OFF Regulators, Clocks and other SOC resources */ + CAM_DBG(CAM_SFE, "Disable SOC resource"); + rc = cam_sfe_disable_soc_resources(soc_info); + if (rc) + CAM_ERR(CAM_SFE, "Disable SOC failed"); + + sfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; + + CAM_DBG(CAM_SFE, "Exit"); + return rc; +} + +int cam_sfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) +{ + CAM_DBG(CAM_SFE, "Enter"); + return 0; +} + +int cam_sfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) +{ + CAM_DBG(CAM_SFE, "Enter"); + return 0; +} + +int cam_sfe_release(void *hw_priv, void *release_args, uint32_t arg_size) +{ + CAM_DBG(CAM_SFE, "Enter"); + return 0; +} + +int cam_sfe_start(void *hw_priv, void *start_args, uint32_t arg_size) +{ + CAM_DBG(CAM_SFE, "Enter"); + return 0; +} + +int cam_sfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size) +{ + CAM_DBG(CAM_SFE, "Enter"); + return 0; +} + +int cam_sfe_read(void *hw_priv, void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_sfe_write(void *hw_priv, void *write_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_sfe_hw_info *hw_info = NULL; + int rc; + + if (!hw_priv) { + CAM_ERR(CAM_SFE, "Invalid arguments"); + return -EINVAL; + } + + soc_info = &sfe_hw->soc_info; + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + hw_info = core_info->sfe_hw_info; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_CHANGE_BASE: + case CAM_ISP_HW_CMD_GET_REG_UPDATE: + rc = 0; + break; + + default: + CAM_ERR(CAM_SFE, "Invalid cmd type:%d", cmd_type); + rc = -EINVAL; + break; + } + + return rc; +} + +irqreturn_t cam_sfe_irq(int irq_num, void *data) +{ + struct cam_hw_info *sfe_hw; + struct cam_sfe_hw_core_info *core_info; + + if (!data) + return IRQ_NONE; + + sfe_hw = (struct cam_hw_info *)data; + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + + return cam_irq_controller_handle_irq(irq_num, + core_info->sfe_irq_controller); +} + +int cam_sfe_core_init( + struct cam_sfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_sfe_hw_info *sfe_hw_info) +{ + + CAM_DBG(CAM_SFE, "Enter"); + + INIT_LIST_HEAD(&core_info->free_payload_list); + spin_lock_init(&core_info->spin_lock); + + return 0; +} + +int cam_sfe_core_deinit( + struct cam_sfe_hw_core_info *core_info, + struct cam_sfe_hw_info *sfe_hw_info) +{ + int rc = -EINVAL; + unsigned long flags; + + spin_lock_irqsave(&core_info->spin_lock, flags); + + INIT_LIST_HEAD(&core_info->free_payload_list); + + rc = cam_irq_controller_deinit(&core_info->sfe_irq_controller); + if (rc) + CAM_ERR(CAM_SFE, + "Error cam_irq_controller_deinit failed rc=%d", rc); + + spin_unlock_irqrestore(&core_info->spin_lock, flags); + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h new file mode 100644 index 000000000000..4c25b4458456 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_CORE_H_ +#define _CAM_SFE_CORE_H_ + +#include +#include "cam_hw_intf.h" +#include "cam_sfe_hw_intf.h" + +struct cam_sfe_hw_info { + struct cam_irq_controller_reg_info *irq_reg_info; +}; + +#define CAM_SFE_EVT_MAX 256 + +struct cam_sfe_hw_core_info { + struct cam_sfe_hw_info *sfe_hw_info; + void *sfe_irq_controller; + void *tasklet_info; + struct list_head free_payload_list; + spinlock_t spin_lock; + int irq_handle; +}; + +int cam_sfe_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size); +int cam_sfe_init_hw(void *device_priv, + void *init_hw_args, uint32_t arg_size); +int cam_sfe_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size); +int cam_sfe_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size); +int cam_sfe_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size); +int cam_sfe_release(void *device_priv, + void *reserve_args, uint32_t arg_size); +int cam_sfe_start(void *device_priv, + void *start_args, uint32_t arg_size); +int cam_sfe_stop(void *device_priv, + void *stop_args, uint32_t arg_size); +int cam_sfe_read(void *device_priv, + void *read_args, uint32_t arg_size); +int cam_sfe_write(void *device_priv, + void *write_args, uint32_t arg_size); +int cam_sfe_process_cmd(void *device_priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size); + +irqreturn_t cam_sfe_irq(int irq_num, void *data); + +int cam_sfe_core_init(struct cam_sfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_sfe_hw_info *sfe_hw_info); + +int cam_sfe_core_deinit(struct cam_sfe_hw_core_info *core_info, + struct cam_sfe_hw_info *sfe_hw_info); + +#endif /* _CAM_SFE_CORE_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c new file mode 100644 index 000000000000..3e41a654cfee --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include "cam_sfe_dev.h" +#include "cam_sfe_core.h" +#include "cam_sfe_soc.h" +#include "cam_sfe_hw_intf.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *sfe_instance; + +static char sfe_dev_name[8]; + +int cam_sfe_probe(struct platform_device *pdev) +{ + struct cam_hw_info *sfe_info = NULL; + struct cam_hw_intf *sfe_intf = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_sfe_hw_info *hw_info = NULL; + int rc = 0; + + sfe_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!sfe_intf) { + rc = -ENOMEM; + goto end; + } + + of_property_read_u32(pdev->dev.of_node, + "cell-index", &sfe_intf->hw_idx); + + sfe_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!sfe_info) { + rc = -ENOMEM; + goto free_sfe_intf; + } + + memset(sfe_dev_name, 0, sizeof(sfe_dev_name)); + snprintf(sfe_dev_name, sizeof(sfe_dev_name), + "sfe%1u", sfe_intf->hw_idx); + + sfe_info->soc_info.pdev = pdev; + sfe_info->soc_info.dev = &pdev->dev; + sfe_info->soc_info.dev_name = sfe_dev_name; + sfe_intf->hw_priv = sfe_info; + sfe_intf->hw_ops.get_hw_caps = cam_sfe_get_hw_caps; + sfe_intf->hw_ops.init = cam_sfe_init_hw; + sfe_intf->hw_ops.deinit = cam_sfe_deinit_hw; + sfe_intf->hw_ops.reset = cam_sfe_reset; + sfe_intf->hw_ops.reserve = cam_sfe_reserve; + sfe_intf->hw_ops.release = cam_sfe_release; + sfe_intf->hw_ops.start = cam_sfe_start; + sfe_intf->hw_ops.stop = cam_sfe_stop; + sfe_intf->hw_ops.read = cam_sfe_read; + sfe_intf->hw_ops.write = cam_sfe_write; + sfe_intf->hw_ops.process_cmd = cam_sfe_process_cmd; + sfe_intf->hw_type = CAM_ISP_HW_TYPE_SFE; + + CAM_DBG(CAM_SFE, "type %d index %d", + sfe_intf->hw_type, sfe_intf->hw_idx); + + platform_set_drvdata(pdev, sfe_intf); + + sfe_info->core_info = kzalloc(sizeof(struct cam_sfe_hw_core_info), + GFP_KERNEL); + if (!sfe_info->core_info) { + CAM_DBG(CAM_SFE, "Failed to alloc for core"); + rc = -ENOMEM; + goto free_sfe_hw; + } + core_info = (struct cam_sfe_hw_core_info *)sfe_info->core_info; + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_SFE, "Of_match Failed"); + rc = -EINVAL; + goto free_core_info; + } + hw_info = (struct cam_sfe_hw_info *)match_dev->data; + core_info->sfe_hw_info = hw_info; + + rc = cam_sfe_init_soc_resources(&sfe_info->soc_info, cam_sfe_irq, + sfe_info); + if (rc < 0) { + CAM_ERR(CAM_SFE, "Failed to init soc rc=%d", rc); + goto free_core_info; + } + + rc = cam_sfe_core_init(core_info, &sfe_info->soc_info, + sfe_intf, hw_info); + if (rc < 0) { + CAM_ERR(CAM_SFE, "Failed to init core rc=%d", rc); + goto deinit_soc; + } + + sfe_info->hw_state = CAM_HW_STATE_POWER_DOWN; + mutex_init(&sfe_info->hw_mutex); + spin_lock_init(&sfe_info->hw_lock); + init_completion(&sfe_info->hw_complete); + + sfe_instance = sfe_intf; + + CAM_DBG(CAM_SFE, "SFE%d probe successful", sfe_intf->hw_idx); + + return rc; + +deinit_soc: + if (cam_sfe_deinit_soc_resources(&sfe_info->soc_info)) + CAM_ERR(CAM_SFE, "Failed to deinit soc"); +free_core_info: + kfree(sfe_info->core_info); +free_sfe_hw: + kfree(sfe_info); +free_sfe_intf: + kfree(sfe_intf); +end: + return rc; +} + +int cam_sfe_remove(struct platform_device *pdev) +{ + struct cam_hw_info *sfe_info = NULL; + struct cam_hw_intf *sfe_intf = NULL; + struct cam_sfe_hw_core_info *core_info = NULL; + int rc = 0; + + sfe_intf = platform_get_drvdata(pdev); + if (!sfe_intf) { + CAM_ERR(CAM_SFE, "Error! No data in pdev"); + return -EINVAL; + } + + CAM_DBG(CAM_SFE, "type %d index %d", + sfe_intf->hw_type, sfe_intf->hw_idx); + + sfe_instance = NULL; + + sfe_info = sfe_intf->hw_priv; + if (!sfe_info) { + CAM_ERR(CAM_SFE, "Error! HW data is NULL"); + rc = -ENODEV; + goto free_sfe_intf; + } + + core_info = (struct cam_sfe_hw_core_info *)sfe_info->core_info; + if (!core_info) { + CAM_ERR(CAM_SFE, "Error! core data NULL"); + rc = -EINVAL; + goto deinit_soc; + } + + rc = cam_sfe_core_deinit(core_info, core_info->sfe_hw_info); + if (rc < 0) + CAM_ERR(CAM_SFE, "Failed to deinit core rc=%d", rc); + + kfree(sfe_info->core_info); + +deinit_soc: + rc = cam_sfe_deinit_soc_resources(&sfe_info->soc_info); + if (rc < 0) + CAM_ERR(CAM_SFE, "Failed to deinit soc rc=%d", rc); + + mutex_destroy(&sfe_info->hw_mutex); + kfree(sfe_info); + + CAM_DBG(CAM_SFE, "SFE%d remove successful", sfe_intf->hw_idx); + +free_sfe_intf: + kfree(sfe_intf); + + return rc; +} + +int cam_sfe_hw_init(struct cam_hw_intf **sfe_intf, uint32_t hw_idx) +{ + int rc = 0; + + if (sfe_instance) { + *sfe_intf = sfe_instance; + rc = 0; + } else { + *sfe_intf = NULL; + rc = -ENODEV; + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h new file mode 100644 index 000000000000..b49ad3217812 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_DEV_H_ +#define _CAM_SFE_DEV_H_ + +#include + +/* + * cam_sfe_probe() + * + * @brief: Driver probe function called on Boot + * + * @pdev: Platform Device pointer + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_probe(struct platform_device *pdev); + +/* + * cam_sfe_remove() + * + * @brief: Driver remove function + * + * @pdev: Platform Device pointer + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_remove(struct platform_device *pdev); + +#endif /* _CAM_SFE_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c new file mode 100644 index 000000000000..fb72657a15bf --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_cpas_api.h" +#include "cam_sfe_soc.h" +#include "cam_debug_util.h" + +static int cam_sfe_get_dt_properties(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) + CAM_ERR(CAM_SFE, "Error get DT properties failed rc=%d", rc); + + return rc; +} + +static int cam_sfe_request_platform_resource( + struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler_func, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_request_platform_resource(soc_info, irq_handler_func, + irq_data); + if (rc) + CAM_ERR(CAM_SFE, + "Error Request platform resource failed rc=%d", rc); + + return rc; +} + +static int cam_sfe_release_platform_resource(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_release_platform_resource(soc_info); + if (rc) + CAM_ERR(CAM_SFE, + "Error Release platform resource failed rc=%d", rc); + + return rc; +} + +int cam_sfe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t irq_handler_func, void *irq_data) +{ + int rc = 0; + + rc = cam_sfe_get_dt_properties(soc_info); + if (rc < 0) { + CAM_ERR(CAM_SFE, "Error Get DT properties failed rc=%d", rc); + goto end; + } + + rc = cam_sfe_request_platform_resource(soc_info, + irq_handler_func, irq_data); + if (rc < 0) { + CAM_ERR(CAM_SFE, + "Error Request platform resources failed rc=%d", rc); + goto end; + } + +end: + return rc; +} + +int cam_sfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + if (!soc_info) { + CAM_ERR(CAM_SFE, "Error soc_info NULL"); + return -ENODEV; + } + + rc = cam_sfe_release_platform_resource(soc_info); + if (rc < 0) + CAM_ERR(CAM_SFE, + "Error Release platform resources failed rc=%d", rc); + + return rc; +} + +int cam_sfe_enable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_TURBO_VOTE, true); + if (rc) { + CAM_ERR(CAM_SFE, "Error enable platform failed rc=%d", rc); + goto end; + } + +end: + return rc; +} + +int cam_sfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name) +{ + return -EPERM; +} + +int cam_sfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name) +{ + return -EPERM; +} + + +int cam_sfe_disable_soc_resources(struct cam_hw_soc_info *soc_info) +{ + int rc = 0; + + rc = cam_soc_util_disable_platform_resource(soc_info, true, true); + if (rc) + CAM_ERR(CAM_SFE, "Disable platform failed rc=%d", rc); + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h new file mode 100644 index 000000000000..37bf2918c585 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_SOC_H_ +#define _CAM_SFE_SOC_H_ + +#include "cam_soc_util.h" +#include "cam_isp_hw.h" + +/* + * struct cam_sfe_soc_private: + * + * @Brief: Private SOC data specific to SFE HW Driver + * + * @cpas_handle: Handle returned on registering with CPAS driver + * This handle is used for all further interface + * with CPAS. + * @cpas_version: CPAS version + */ +struct cam_sfe_soc_private { + uint32_t cpas_handle; + uint32_t cpas_version; +}; + +/* + * cam_sfe_init_soc_resources() + * + * @Brief: Initialize SOC resources including private data + * + * @soc_info: Device soc information + * @handler: Irq handler function pointer + * @irq_data: Irq handler function Callback data + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t vfe_irq_handler, void *irq_data); + +/* + * cam_sfe_deinit_soc_resources() + * + * @Brief: Deinitialize SOC resources including private data + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_sfe_enable_soc_resources() + * + * @brief: Enable regulator, irq resources, Clocks + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_enable_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_sfe_disable_soc_resources() + * + * @brief: Disable regulator, irq resources, Clocks + * + * @soc_info: Device soc information + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_disable_soc_resources(struct cam_hw_soc_info *soc_info); + +/* + * cam_sfe_soc_enable_clk() + * + * @brief: Enable clock wsfe given name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to enable + * + * @Return: 0: Success + * Non-zero: Failure + */ +extern int cam_sfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name); + +/* + * cam_sfe_soc_disable_clk() + * + * @brief: Disable clock wsfe given name + * + * @soc_info: Device soc information + * @clk_name: Name of clock to enable + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, + const char *clk_name); + +#endif /* _CAM_SFE_SOC_H_ */ diff --git a/drivers/cam_utils/cam_debug_util.c b/drivers/cam_utils/cam_debug_util.c index 32b9b2744422..d4ea078119c9 100644 --- a/drivers/cam_utils/cam_debug_util.c +++ b/drivers/cam_utils/cam_debug_util.c @@ -215,6 +215,9 @@ const char *cam_get_module_name(unsigned int module_id) case CAM_IO_ACCESS: name = "CAM-IO-ACCESS"; break; + case CAM_SFE: + name = "CAM-SFE"; + break; default: name = "CAM"; break; diff --git a/drivers/cam_utils/cam_debug_util.h b/drivers/cam_utils/cam_debug_util.h index 69bdc6d62d3c..5232501525d1 100644 --- a/drivers/cam_utils/cam_debug_util.h +++ b/drivers/cam_utils/cam_debug_util.h @@ -39,6 +39,7 @@ #define CAM_PRESIL (1 << 27) #define CAM_OPE (1 << 28) #define CAM_IO_ACCESS (1 << 29) +#define CAM_SFE (1 << 30) /* Log level types */ #define CAM_TYPE_TRACE (1 << 0) From d2461de353968d900cd07a7bae5fc956144e428e Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 7 Aug 2020 15:00:29 -0700 Subject: [PATCH 493/790] msm: camera: isp: Add support for TPG cfg blob TPG core cfg data is sent by userspace as a blob. Add support to configure the same at stream on. CRs-Fixed: 2772256 Change-Id: I94b9e3fd8aaf02e9ea6d1e7fa10de9cbbc43e39d Signed-off-by: Karthik Anantha Ram Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 50 +++++++++++++++++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw/top_tpg/cam_top_tpg103.h | 1 + .../isp_hw/top_tpg/cam_top_tpg_core.h | 2 + .../isp_hw/top_tpg/cam_top_tpg_ver3.c | 54 +++++++++++++++++-- .../isp_hw/top_tpg/cam_top_tpg_ver3.h | 1 + 6 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 99c25aa7d957..ab7adf18e91d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5370,6 +5370,37 @@ static int cam_isp_blob_clock_update( return rc; } +static int cam_isp_blob_tpg_config( + struct cam_isp_tpg_core_config *tpg_config, + struct cam_hw_prepare_update_args *prepare) +{ + int i, rc = -EINVAL; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + + ctx = prepare->ctxt_to_hw_map; + hw_mgr_res = &ctx->res_list_tpg; + + 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; + CAM_DBG(CAM_ISP, "TPG ctrl config for hw %u", + hw_intf->hw_idx); + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, tpg_config, + sizeof(struct cam_isp_tpg_core_config)); + if (rc) + goto end; + } + } + +end: + return rc; +} + static int cam_isp_blob_sensor_config( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, @@ -6144,6 +6175,25 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, "Sensor Dimension Update Failed rc: %d", rc); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG: { + struct cam_isp_tpg_core_config *tpg_config; + + if (blob_size < sizeof(struct cam_isp_tpg_core_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %zu expected %zu", + blob_size, + sizeof(struct cam_isp_tpg_core_config)); + return -EINVAL; + } + + tpg_config = + (struct cam_isp_tpg_core_config *)blob_data; + + rc = cam_isp_blob_tpg_config(tpg_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, + "TPG config failed rc: %d", rc); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index de5b0499603b..1935c5cd0d3c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -126,6 +126,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_GET_RES_FOR_MID, CAM_ISP_HW_CMD_BLANKING_UPDATE, CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, + CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h index 396671852799..89880ae809bc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h @@ -112,6 +112,7 @@ static struct cam_top_tpg_ver3_reg_offset cam_top_tpg103_reg = { .top_mux_reg_offset = 0x1C, .tpg_vc_dt_pattern_id_shift = 6, .tpg_num_active_vcs_shift = 30, + .tpg_color_bar_qcfa_en_shift = 3, }; struct cam_top_tpg_hw_info cam_top_tpg103_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h index eb6e03a36cce..d904eb949817 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h @@ -80,6 +80,7 @@ struct cam_top_tpg_dt_cfg { * @vbi_cnt: vbi count * @num_active_dts: number of active dts need to configure * @num_frames: number of output frames + * @qcfa_en: enable qcfa in color bar cfg * @dt_cfg: dt configuration values * */ @@ -94,6 +95,7 @@ struct cam_top_tpg_cfg { uint32_t num_active_dts; uint32_t num_frames; uint32_t vc_dt_pattern_id; + uint32_t qcfa_en; struct cam_top_tpg_dt_cfg dt_cfg[4]; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c index ee862e3db199..6955cf8729df 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c @@ -47,6 +47,52 @@ static int cam_top_tpg_ver3_get_hw_caps( return rc; } +static int cam_top_tpg_ver3_process_cmd(void *hw_priv, + uint32_t cmd_type, void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_top_tpg_hw *tpg_hw; + struct cam_hw_info *tpg_hw_info; + struct cam_isp_tpg_core_config *core_cfg; + struct cam_top_tpg_cfg *tpg_data; + + if (!hw_priv || !cmd_args) { + CAM_ERR(CAM_ISP, "TPG: Invalid args"); + return -EINVAL; + } + + tpg_hw_info = (struct cam_hw_info *)hw_priv; + tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info; + tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD: + if (arg_size != sizeof(struct cam_isp_tpg_core_config)) { + CAM_ERR(CAM_ISP, "Invalid size %u expected %u", + arg_size, + sizeof(struct cam_isp_tpg_core_config)); + rc = -EINVAL; + break; + } + + core_cfg = (struct cam_isp_tpg_core_config *)cmd_args; + tpg_data->pix_pattern = core_cfg->pix_pattern; + tpg_data->vc_dt_pattern_id = core_cfg->vc_dt_pattern_id; + tpg_data->qcfa_en = core_cfg->qcfa_en; + CAM_DBG(CAM_ISP, + "pattern_id: 0x%x pix_pattern: 0x%x qcfa_en: 0x%x", + tpg_data->vc_dt_pattern_id, tpg_data->pix_pattern, + tpg_data->qcfa_en); + break; + default: + CAM_ERR(CAM_ISP, "Invalid TPG cmd type %u", cmd_type); + rc = -EINVAL; + break; + } + + return rc; +} + static int cam_top_tpg_ver3_reserve( void *hw_priv, void *reserve_args, @@ -95,7 +141,7 @@ static int cam_top_tpg_ver3_reserve( } tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; - + memset(tpg_data, 0, sizeof(*tpg_data)); for (i = 0; i < reserv->in_port->num_valid_vc_dt; i++) { if (reserv->in_port->dt[i] > 0x3f || reserv->in_port->vc[i] > 0x1f) { @@ -218,6 +264,8 @@ static int cam_top_tpg_ver3_start( val = (1 << tpg_reg->tpg_split_en_shift); val |= tpg_data->pix_pattern; + if (tpg_data->qcfa_en) + val |= (1 << tpg_reg->tpg_color_bar_qcfa_en_shift); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_color_bar_cfg + 0x60 * i); @@ -236,7 +284,7 @@ static int cam_top_tpg_ver3_start( tpg_reg->tpg_vc0_hbi_cfg + 0x60 * i); if (tpg_data->v_blank_count) - cam_io_w_mb(tpg_data->h_blank_count, + cam_io_w_mb(tpg_data->v_blank_count, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc0_vbi_cfg + 0x60 * i); else @@ -340,6 +388,6 @@ int cam_top_tpg_ver3_init( tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver3_reserve; tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver3_start; tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver3_stop; - + tpg_hw->hw_intf->hw_ops.process_cmd = cam_top_tpg_ver3_process_cmd; return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h index b8853d6215a2..401ba8127cd1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h @@ -111,6 +111,7 @@ struct cam_top_tpg_ver3_reg_offset { uint32_t top_mux_reg_offset; uint32_t tpg_vc_dt_pattern_id_shift; uint32_t tpg_num_active_vcs_shift; + uint32_t tpg_color_bar_qcfa_en_shift; }; int cam_top_tpg_ver3_init(struct cam_top_tpg_hw *tpg_hw); From a5485a8560e357491924a78ada8977666489e9bf Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Thu, 11 Jun 2020 11:19:00 -0700 Subject: [PATCH 494/790] msm: camera: sensor: Add error logs in case of wrong ioctl Add wrong IOCTL command logs across sensor submodules. CRs-Fixed: 2759031 Change-Id: Idf63749855e60b2a5bd9db9b5d78e129629431af Signed-off-by: Jigarkumar Zala Signed-off-by: Fernando Pacheco --- .../cam_actuator/cam_actuator_dev.c | 12 ++++++++---- .../cam_sensor_module/cam_csiphy/cam_csiphy_dev.c | 14 +++++++++----- .../cam_sensor_module/cam_eeprom/cam_eeprom_dev.c | 3 +++ .../cam_sensor_module/cam_flash/cam_flash_dev.c | 8 ++++++-- drivers/cam_sensor_module/cam_ois/cam_ois_dev.c | 7 ++++++- .../cam_sensor_module/cam_sensor/cam_sensor_dev.c | 10 +++++++--- 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index e0df270b80cb..8b180a767d37 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -20,10 +20,13 @@ static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, switch (cmd) { case VIDIOC_CAM_CONTROL: rc = cam_actuator_driver_cmd(a_ctrl, arg); + if (rc) + CAM_ERR(CAM_ACTUATOR, + "Failed for driver_cmd: %d", rc); break; default: - CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd"); - rc = -EINVAL; + CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd: %u", cmd); + rc = -ENOIOCTLCMD; break; } return rc; @@ -54,10 +57,11 @@ static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, rc); return rc; } - break; + break; default: CAM_ERR(CAM_ACTUATOR, "Invalid compat ioctl: %d", cmd); - rc = -EINVAL; + rc = -ENOIOCTLCMD; + break; } if (!rc) { diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 1d8dc2af07c9..5d5f58748cec 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -38,13 +38,13 @@ static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, switch (cmd) { case VIDIOC_CAM_CONTROL: rc = cam_csiphy_core_cfg(csiphy_dev, arg); - if (rc != 0) { - CAM_ERR(CAM_CSIPHY, "in configuring the device"); - return rc; - } + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in configuring the device: %d", rc); break; default: CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + rc = -ENOIOCTLCMD; break; } @@ -89,10 +89,14 @@ static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, switch (cmd) { case VIDIOC_CAM_CONTROL: rc = cam_csiphy_subdev_ioctl(sd, cmd, &cmd_data); + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in subdev_ioctl: %d", rc); break; default: CAM_ERR(CAM_CSIPHY, "Invalid compat ioctl cmd: %d", cmd); - rc = -EINVAL; + rc = -ENOIOCTLCMD; + break; } if (!rc) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 486632399e60..435ca815e4c9 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -19,6 +19,9 @@ static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, switch (cmd) { case VIDIOC_CAM_CONTROL: rc = cam_eeprom_driver_cmd(e_ctrl, arg); + if (rc) + CAM_ERR(CAM_EEPROM, + "Failed in Driver cmd: %d", rc); break; default: rc = -ENOIOCTLCMD; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index ae6620017d62..bb7bd78ae275 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -251,11 +251,14 @@ static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, case VIDIOC_CAM_CONTROL: { rc = cam_flash_driver_cmd(fctrl, arg, soc_private); + if (rc) + CAM_ERR(CAM_FLASH, + "Failed in driver cmd: %d", rc); break; } default: CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); - rc = -EINVAL; + rc = -ENOIOCTLCMD; break; } @@ -288,7 +291,8 @@ static long cam_flash_subdev_do_ioctl(struct v4l2_subdev *sd, default: CAM_ERR(CAM_FLASH, "Invalid compat ioctl cmd_type:%d", cmd); - rc = -EINVAL; + rc = -ENOIOCTLCMD; + break; } if (!rc) { diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 8797252ab7b6..a52e59b25af0 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -19,8 +19,12 @@ static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, switch (cmd) { case VIDIOC_CAM_CONTROL: rc = cam_ois_driver_cmd(o_ctrl, arg); + if (rc) + CAM_ERR(CAM_OIS, + "Failed with driver cmd: %d", rc); break; default: + CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); rc = -ENOIOCTLCMD; break; } @@ -95,7 +99,8 @@ static long cam_ois_init_subdev_do_ioctl(struct v4l2_subdev *sd, break; default: CAM_ERR(CAM_OIS, "Invalid compat ioctl: %d", cmd); - rc = -EINVAL; + rc = -ENOIOCTLCMD; + break; } if (!rc) { diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index fd529205cdf7..1b7f0261260e 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -19,10 +19,13 @@ static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, switch (cmd) { case VIDIOC_CAM_CONTROL: rc = cam_sensor_driver_cmd(s_ctrl, arg); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in Driver cmd: %d", rc); break; default: CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); - rc = -EINVAL; + rc = -ENOIOCTLCMD; break; } return rc; @@ -65,10 +68,11 @@ static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, rc = cam_sensor_subdev_ioctl(sd, cmd, &cmd_data); if (rc < 0) CAM_ERR(CAM_SENSOR, "cam_sensor_subdev_ioctl failed"); - break; + break; default: CAM_ERR(CAM_SENSOR, "Invalid compat ioctl cmd_type: %d", cmd); - rc = -EINVAL; + rc = -ENOIOCTLCMD; + break; } if (!rc) { From 9d1e44a94fcdbb2d5bb0541891277707653576d4 Mon Sep 17 00:00:00 2001 From: bohahuan Date: Mon, 7 Sep 2020 15:46:56 +0800 Subject: [PATCH 495/790] msm: camera: memmgr: increase max slot count into 2048 In case large memory slot usage scene like MFHDR, MFSR. increase kernel slot count to avoid out of memory issue. CRs-Fixed: 2718732 Change-Id: I49dd2d9bdda548d5f95fa49c290364ecb6d40f6e Signed-off-by: bohahuan --- drivers/cam_req_mgr/cam_mem_mgr.h | 2 -- include/uapi/camera/media/cam_req_mgr.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index b87119067b9a..79d60cb96f6f 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -11,8 +11,6 @@ #include #include "cam_mem_mgr_api.h" -#define CAM_MEM_BUFQ_MAX 1024 - /* Enum for possible mem mgr states */ enum cam_mem_mgr_state { CAM_MEM_MGR_UNINITIALIZED, diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index c26da7a06a29..5a635774aafb 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -290,7 +290,7 @@ struct cam_req_mgr_link_control { #define CAM_MEM_MMU_MAX_HANDLE 16 /* Maximum allowed buffers in existence */ -#define CAM_MEM_BUFQ_MAX 1024 +#define CAM_MEM_BUFQ_MAX 2048 #define CAM_MEM_MGR_SECURE_BIT_POS 15 #define CAM_MEM_MGR_HDL_IDX_SIZE 15 From 746527f23882bc3d3d447034fe3e997e1fe4ece1 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Fri, 4 Sep 2020 15:44:28 -0700 Subject: [PATCH 496/790] msm: camera: isp: Program min hbi in IPP path Userspace sends the hbi count as part of acquire. Use that value to compute min hbi and progam the same in IPP path cfg. CRs-Fixed: 2772278 Change-Id: Ia41c435b0fb010a3b841fa11bfcdffc4c4a11006 Signed-off-by: Karthik Anantha Ram --- .../isp_hw/ife_csid_hw/cam_ife_csid480.h | 1 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 16 ++++++++++++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 ++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h index 316c3e2ab629..f9a3e8bc4bae 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid480.h @@ -54,6 +54,7 @@ static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_480_ipp_reg_offset = { .quad_cfa_bin_en_shift_val = 30, .ccif_violation_en = 1, .overflow_ctrl_en = 1, + .hblank_cfg_shift_val = 4, }; static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_480_ppp_reg_offset = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 0c9995946874..a99d3f902e24 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1153,12 +1153,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->horizontal_bin = reserve->in_port->horizontal_bin; path_data->qcfa_bin = reserve->in_port->qcfa_bin; path_data->num_bytes_out = reserve->in_port->num_bytes_out; + path_data->hblank_cnt = reserve->in_port->hbi_cnt; CAM_DBG(CAM_ISP, - "Res id: %d height:%d line_start %d line_stop %d crop_en %d", + "Res id: %d height:%d line_start %d line_stop %d crop_en %d hblank %u", reserve->res_id, reserve->in_port->height, reserve->in_port->line_start, reserve->in_port->line_stop, - path_data->crop_enable); + path_data->crop_enable, path_data->hblank_cnt); if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || @@ -1857,6 +1858,17 @@ static int cam_ife_csid_init_config_pxl_path( val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg1_addr); + /* Program min hbi between lines */ + if ((path_data->hblank_cnt) && (path_data->hblank_cnt <= + (CAM_CSID_MIN_HBI_CFG_MAX_VAL * 16))) { + if ((path_data->hblank_cnt % 16) == 0) + val |= ((path_data->hblank_cnt / 16) << + pxl_reg->hblank_cfg_shift_val); + else + val |= (((path_data->hblank_cnt / 16) + 1) << + pxl_reg->hblank_cfg_shift_val); + } + /* select the post irq sub sample strobe for time stamp capture */ val |= CSID_TIMESTAMP_STB_POST_IRQ; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 6854e9767917..b3500a1fb10e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -73,6 +73,7 @@ #define CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) #define CAM_CSID_EVT_PAYLOAD_MAX 10 +#define CAM_CSID_MIN_HBI_CFG_MAX_VAL 0xF /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_csid_path_halt_mode { @@ -159,6 +160,7 @@ struct cam_ife_csid_pxl_reg_offset { uint32_t quad_cfa_bin_en_shift_val; uint32_t ccif_violation_en; uint32_t overflow_ctrl_en; + uint32_t hblank_cfg_shift_val; uint32_t halt_master_sel_en; uint32_t halt_sel_internal_master_val; }; @@ -518,6 +520,7 @@ struct cam_ife_csid_cid_data { * Slave will synchronize with master Start and stop operations * @clk_rate Clock rate * @num_bytes_out: Number of output bytes per cycle + * @hblank_cnt: HBI count * */ struct cam_ife_csid_path_cfg { @@ -543,6 +546,7 @@ struct cam_ife_csid_path_cfg { uint32_t horizontal_bin; uint32_t qcfa_bin; uint32_t num_bytes_out; + uint32_t hblank_cnt; }; /** From 0690b71d8bcca485c7a2d38e0097c2c6c997ac8a Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 3 Sep 2020 17:52:37 +0530 Subject: [PATCH 497/790] msm: camera: isp: Add check to dump supported fifo level registers in shima Add check to dump supported debug register for shima target. This change prevent unexpected behaviour during reading unsupported fifo level register. CRs-Fixed: 2770220 Change-Id: I33608e1ef92ca45acdc04667f61bb2d1536cbb8b Signed-off-by: Chandan Kumar Jha --- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 21 +++++++++++++++---- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 21 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index 74614722f4fa..722ab62a5d0c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -844,12 +844,22 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private = NULL; uint32_t val0, val1, val2, val3, val4; + uint32_t camera_hw_version; + int rc = 0; + + val3 = val4 = 0; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + return; + } + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; violation_status = status[CAM_IFE_IRQ_VIOLATION_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; @@ -1018,10 +1028,13 @@ print_state: CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + + if (camera_hw_version == CAM_CPAS_TITAN_580_V100) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + } CAM_INFO(CAM_ISP, "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 5de4a5d61a14..2cc592014e46 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -943,12 +943,22 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private; uint32_t val0, val1, val2, val3, val4; + uint32_t camera_hw_version; + int rc = 0; + + val3 = val4 = 0; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } + rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); + return; + } + bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; @@ -1268,10 +1278,13 @@ print_state: CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + + if (camera_hw_version == CAM_CPAS_TITAN_580_V100) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); + } CAM_INFO(CAM_ISP, "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", From 5298a2471e1ffc2dfa3d91a3094344acc6d33e54 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Fri, 28 Aug 2020 19:32:46 -0700 Subject: [PATCH 498/790] msm: camera: cdm: Support CDM2.1 for new Chipset Add support single-context CDM for CDM2.1. CRs-fixed: 2770438 Change-Id: I894ebc9fc770fe25c7cd1c18099d3c06af319245 Signed-off-by: Jigar Agrawal --- drivers/cam_cdm/cam_cdm.h | 5 +- drivers/cam_cdm/cam_cdm_hw_core.c | 99 ++++++++++--------- drivers/cam_cdm/cam_cdm_intf_api.h | 1 + drivers/cam_cdm/cam_cdm_soc.c | 4 + drivers/cam_cdm/cam_cdm_soc.h | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 25 +++-- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 3 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 10 +- .../hw_utils/cam_isp_packet_parser.c | 5 +- .../hw_utils/include/cam_isp_packet_parser.h | 17 +++- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 3 + .../isp_hw/include/cam_vfe_hw_intf.h | 1 + 12 files changed, 107 insertions(+), 68 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 714bff32c399..540c03b0185f 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -503,7 +503,6 @@ struct cam_cdm_bl_fifo { * @gen_irq: memory region in which gen_irq command will be written * @cpas_handle: handle for cpas driver * @arbitration: type of arbitration to be used for the CDM - * @rst_done_cnt: CMD reset done count */ struct cam_cdm { uint32_t index; @@ -526,13 +525,13 @@ struct cam_cdm { struct cam_cdm_hw_mem gen_irq[CAM_CDM_BL_FIFO_MAX]; uint32_t cpas_handle; enum cam_cdm_arbitration arbitration; - uint32_t rst_done_cnt; }; /* struct cam_cdm_private_dt_data - CDM hw custom dt data */ struct cam_cdm_private_dt_data { bool dt_cdm_shared; bool config_fifo; + bool is_single_ctx_cdm; uint8_t priority_group; uint32_t fifo_depth[CAM_CDM_BL_FIFO_MAX]; uint32_t dt_num_supported_clients; @@ -550,10 +549,10 @@ struct cam_cdm_intf_devices { /* struct cam_cdm_intf_mgr - CDM mgr interface device struct */ struct cam_cdm_intf_mgr { bool probe_done; - struct cam_cdm_intf_devices nodes[CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM]; uint32_t cdm_count; uint32_t dt_supported_hw_cdm; int32_t refcount; + struct cam_cdm_intf_devices nodes[CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM]; }; int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index d3c00193d9e6..c03e0eec29d4 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -66,14 +66,13 @@ static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { .data = &cam_cdm_2_1_reg_offset, }, { - .compatible = CAM_HW_CDM_OPE_NAME_2_1, + .compatible = CAM_HW_CDM_RT_NAME_2_1, .data = &cam_cdm_2_1_reg_offset, }, { - .compatible = CAM_HW_CDM_IFE_NAME_2_1, + .compatible = CAM_HW_CDM_OPE_NAME_2_1, .data = &cam_cdm_2_1_reg_offset, }, - {} }; static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) @@ -102,12 +101,12 @@ static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) if (strnstr(name, CAM_HW_CDM_CPAS_NAME_2_1, strlen(CAM_HW_CDM_CPAS_NAME_2_1))) return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_RT_NAME_2_1, + strlen(CAM_HW_CDM_RT_NAME_2_1))) + return CAM_CDM_RT; if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_1, strlen(CAM_HW_CDM_OPE_NAME_2_1))) return CAM_CDM_OPE; - if (strnstr(name, CAM_HW_CDM_IFE_NAME_2_1, - strlen(CAM_HW_CDM_IFE_NAME_2_1))) - return CAM_CDM_IFE; return CAM_CDM_MAX; } @@ -320,7 +319,7 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw) { - uint32_t dump_reg, core_dbg; + uint32_t dump_reg, dump_reg1, dump_reg2, core_dbg; int i; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; @@ -353,6 +352,19 @@ void cam_hw_cdm_dump_core_debug_registers( CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->icl_reg->data_regs->icl_inv_data, + &dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->icl_reg->misc_regs->icl_inv_bl_addr, + &dump_reg1); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->icl_reg->misc_regs->icl_status, + &dump_reg2); + CAM_INFO(CAM_CDM, + "Last Inv Cmd Log(ICL)Status: 0x%x, Last Inv cmd: 0x%x, Last Inv bl_addr: 0x%x", + dump_reg2, dump_reg, dump_reg1); + cam_hw_cdm_dump_bl_fifo_data(cdm_hw); CAM_INFO(CAM_CDM, "CDM HW default dump"); @@ -360,9 +372,7 @@ void cam_hw_cdm_dump_core_debug_registers( core->offsets->cmn_reg->core_cfg, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); - for (i = 0; i < - core->offsets->reg_data->num_bl_fifo_irq; - i++) { + for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_status, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg); @@ -412,7 +422,6 @@ enum cam_cdm_arbitration cam_cdm_get_arbitration_type( arbitration = CAM_CDM_ARBITRATION_NONE; goto end; } - switch (id) { case CAM_CDM_CPAS: arbitration = CAM_CDM_ARBITRATION_ROUND_ROBIN; @@ -427,14 +436,13 @@ end: int cam_hw_cdm_set_cdm_blfifo_cfg(struct cam_hw_info *cdm_hw) { - uint32_t blfifo_cfg_mask = 0; int rc = 0, i; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - blfifo_cfg_mask = blfifo_cfg_mask | - CAM_CDM_BL_FIFO_REQ_SIZE_MAX; - for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { + if (!core->bl_fifo[i].bl_depth) + continue; + rc = cam_cdm_write_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_mask, 0x70003); if (rc) { @@ -447,24 +455,10 @@ int cam_hw_cdm_set_cdm_blfifo_cfg(struct cam_hw_info *cdm_hw) if (core->hw_version >= CAM_CDM_VERSION_2_0) { for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { - blfifo_cfg_mask = blfifo_cfg_mask | - (core->bl_fifo[i].bl_depth + rc = cam_cdm_write_hw_reg(cdm_hw, + core->offsets->bl_fifo_reg[i]->bl_fifo_cfg, + core->bl_fifo[i].bl_depth << CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT); - rc = cam_cdm_write_hw_reg(cdm_hw, - core->offsets->bl_fifo_reg[i]->bl_fifo_cfg, - blfifo_cfg_mask); - if (rc) { - CAM_ERR(CAM_CDM, - "Unable to write to cdm irq mask register"); - rc = -EIO; - goto end; - } - } - } else { - for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { - rc = cam_cdm_write_hw_reg(cdm_hw, - core->offsets->bl_fifo_reg[i]->bl_fifo_cfg, - blfifo_cfg_mask); if (rc) { CAM_ERR(CAM_CDM, "Unable to write to cdm irq mask register"); @@ -484,7 +478,7 @@ int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) int rc; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; struct cam_cdm_private_dt_data *pvt_data = - pvt_data = cdm_hw->soc_info.soc_private; + (struct cam_cdm_private_dt_data *)cdm_hw->soc_info.soc_private; cfg_mask = cfg_mask | CAM_CDM_AHB_STOP_ON_ERROR| @@ -501,7 +495,8 @@ int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) } if (cdm_version >= CAM_CDM_VERSION_2_0) { - if (core->id != CAM_CDM_CPAS) + if (core->id != CAM_CDM_CPAS && + (!pvt_data->is_single_ctx_cdm)) cfg_mask = cfg_mask | CAM_CDM_IMPLICIT_WAIT_EN; if (core->arbitration == CAM_CDM_ARBITRATION_ROUND_ROBIN) @@ -1281,6 +1276,7 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) struct cam_hw_info *cdm_hw = data; struct cam_cdm *cdm_core = cdm_hw->core_info; struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0}; + uint8_t rst_done_cnt = 0; uint32_t user_data = 0; uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0}; uint32_t irq_context_summary = 0xF; @@ -1332,7 +1328,7 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) continue; if (irq_status[i] & CAM_CDM_IRQ_STATUS_RST_DONE_MASK) { - cdm_core->rst_done_cnt++; + rst_done_cnt++; continue; } @@ -1391,17 +1387,15 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) kfree(payload[i]); } } - if (cdm_core->rst_done_cnt == - cdm_core->offsets->reg_data->num_bl_fifo_irq) { + if (rst_done_cnt == cdm_core->offsets->reg_data->num_bl_fifo_irq) { CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); complete(&cdm_core->reset_complete); } - if (cdm_core->rst_done_cnt && - cdm_core->rst_done_cnt != - cdm_core->offsets->reg_data->num_bl_fifo_irq) + if (rst_done_cnt && + (rst_done_cnt != cdm_core->offsets->reg_data->num_bl_fifo_irq)) CAM_INFO(CAM_CDM, "Reset IRQ received for %d fifos instead of %d", - cdm_core->rst_done_cnt, + rst_done_cnt, cdm_core->offsets->reg_data->num_bl_fifo_irq); return IRQ_HANDLED; } @@ -1422,6 +1416,9 @@ int cam_hw_cdm_alloc_genirq_mem(void *hw_priv) genirq_alloc_cmd.smmu_hdl = cdm_core->iommu_hdl.non_secure; genirq_alloc_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE; for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (!cdm_core->bl_fifo[i].bl_depth) + continue; + genirq_alloc_cmd.size = (8 * cdm_core->bl_fifo[i].bl_depth); rc = cam_mem_mgr_request_mem(&genirq_alloc_cmd, @@ -1478,7 +1475,7 @@ int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); - cdm_core->rst_done_cnt = 0; + reinit_completion(&cdm_core->reset_complete); /* First pause CDM, If it fails still proceed to reset CDM HW */ @@ -1486,6 +1483,9 @@ int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) usleep_range(1000, 1010); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (!cdm_core->bl_fifo[i].bl_depth) + continue; + reset_val = reset_val | (1 << (i + CAM_CDM_BL_FIFO_FLUSH_SHIFT)); if (cam_cdm_write_hw_reg(cdm_hw, @@ -1549,7 +1549,6 @@ int cam_hw_cdm_handle_error_info( for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); - cdm_core->rst_done_cnt = 0; reinit_completion(&cdm_core->reset_complete); set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); set_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); @@ -1578,6 +1577,9 @@ int cam_hw_cdm_handle_error_info( cam_hw_cdm_dump_core_debug_registers(cdm_hw); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (!cdm_core->bl_fifo[i].bl_depth) + continue; + reset_val = reset_val | (1 << (i + CAM_CDM_BL_FIFO_FLUSH_SHIFT)); if (cam_cdm_write_hw_reg(cdm_hw, @@ -1811,10 +1813,14 @@ int cam_hw_cdm_init(void *hw_priv, goto disable_return; } else { CAM_DBG(CAM_CDM, "CDM Init success"); - for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) + for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (!cdm_core->bl_fifo[i].bl_depth) + continue; + cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_mask, 0x70003); + } rc = 0; goto end; } @@ -1860,7 +1866,6 @@ int cam_hw_cdm_deinit(void *hw_priv, } set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); - cdm_core->rst_done_cnt = 0; reinit_completion(&cdm_core->reset_complete); /* First pause CDM, If it fails still proceed to reset CDM HW */ @@ -1868,6 +1873,9 @@ int cam_hw_cdm_deinit(void *hw_priv, usleep_range(1000, 1010); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { + if (!cdm_core->bl_fifo[i].bl_depth) + continue; + reset_val = reset_val | (1 << (i + CAM_CDM_BL_FIFO_FLUSH_SHIFT)); if (cam_cdm_write_hw_reg(cdm_hw, @@ -1973,7 +1981,6 @@ static int cam_hw_cdm_component_bind(struct device *dev, goto release_private_mem; } - cdm_core->rst_done_cnt = 0; init_completion(&cdm_core->reset_complete); cdm_hw_intf->hw_priv = cdm_hw; cdm_hw_intf->hw_ops.get_hw_caps = cam_cdm_get_caps; diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index 58ffd4f8a0f9..adf6930593ce 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -22,6 +22,7 @@ enum cam_cdm_id { CAM_CDM_IPE1, CAM_CDM_BPS, CAM_CDM_VFE, + CAM_CDM_RT, CAM_CDM_MAX }; diff --git a/drivers/cam_cdm/cam_cdm_soc.c b/drivers/cam_cdm/cam_cdm_soc.c index ba4ff1ac6e33..f2658448c33b 100644 --- a/drivers/cam_cdm/cam_cdm_soc.c +++ b/drivers/cam_cdm/cam_cdm_soc.c @@ -114,6 +114,10 @@ int cam_cdm_soc_load_dt_private(struct platform_device *pdev, } + cdm_pvt_data->is_single_ctx_cdm = + of_property_read_bool(pdev->dev.of_node, + "single-context-cdm"); + rc = of_property_read_u8(pdev->dev.of_node, "cdm-priority-group", &cdm_pvt_data->priority_group); if (rc < 0) { diff --git a/drivers/cam_cdm/cam_cdm_soc.h b/drivers/cam_cdm/cam_cdm_soc.h index 59129c7031c7..11afd1f676b9 100644 --- a/drivers/cam_cdm/cam_cdm_soc.h +++ b/drivers/cam_cdm/cam_cdm_soc.h @@ -14,8 +14,8 @@ #define CAM_HW_CDM_CPAS_NAME_2_0 "qcom,cam-cpas-cdm2_0" #define CAM_HW_CDM_OPE_NAME_2_0 "qcom,cam-ope-cdm2_0" #define CAM_HW_CDM_CPAS_NAME_2_1 "qcom,cam-cpas-cdm2_1" +#define CAM_HW_CDM_RT_NAME_2_1 "qcom,cam-rt-cdm2_1" #define CAM_HW_CDM_OPE_NAME_2_1 "qcom,cam-ope-cdm2_1" -#define CAM_HW_CDM_IFE_NAME_2_1 "qcom,cam-ife-cdm2_1" int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, const struct of_device_id *table); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 99c25aa7d957..9ef62524bb3e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3001,7 +3001,6 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) uint32_t total_pd_port = 0; struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; uint32_t input_size = 0; - uint32_t hw_version; CAM_DBG(CAM_ISP, "Enter..."); @@ -3110,15 +3109,16 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto free_cdm; } - cam_cpas_get_cpas_hw_version(&hw_version); - ife_ctx->hw_version = hw_version; - + cam_cpas_get_cpas_hw_version(&ife_ctx->hw_version); if (ife_ctx->is_dual) memcpy(cdm_acquire.identifier, "dualife", sizeof("dualife")); else memcpy(cdm_acquire.identifier, "ife", sizeof("ife")); - cdm_acquire.cell_index = ife_ctx->base[0].idx; + if (ife_ctx->is_dual) + cdm_acquire.cell_index = ife_ctx->master_hw_idx; + else + cdm_acquire.cell_index = ife_ctx->base[0].idx; cdm_acquire.handle = 0; cdm_acquire.userdata = ife_ctx; cdm_acquire.base_array_cnt = CAM_IFE_HW_NUM_MAX; @@ -3141,6 +3141,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) "Successfully acquired CDM Id: %d, CDM HW hdl=%x, is_dual=%d", cdm_acquire.id, cdm_acquire.handle, ife_ctx->is_dual); ife_ctx->cdm_handle = cdm_acquire.handle; + ife_ctx->cdm_id = cdm_acquire.id; if (cdm_acquire.id == CAM_CDM_IFE) ife_ctx->internal_cdm = true; atomic_set(&ife_ctx->cdm_done, 1); @@ -3242,7 +3243,6 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; uint32_t in_port_length = 0; - uint32_t hw_version; CAM_DBG(CAM_ISP, "Enter..."); @@ -3375,8 +3375,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto free_res; } - cam_cpas_get_cpas_hw_version(&hw_version); - ife_ctx->hw_version = hw_version; + cam_cpas_get_cpas_hw_version(&ife_ctx->hw_version); ife_ctx->internal_cdm = false; if (ife_ctx->is_dual) @@ -3408,6 +3407,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) if (cdm_acquire.id == CAM_CDM_IFE) ife_ctx->internal_cdm = true; ife_ctx->cdm_handle = cdm_acquire.handle; + ife_ctx->cdm_id = cdm_acquire.id; atomic_set(&ife_ctx->cdm_done, 1); acquire_args->ctxt_to_hw_map = ife_ctx; @@ -6219,6 +6219,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, bool frame_header_enable = false; struct cam_isp_prepare_hw_update_data *prepare_hw_data; struct cam_isp_frame_header_info frame_header_info; + struct cam_isp_change_base_args change_base_info = {0}; if (!hw_mgr_priv || !prepare_hw_update_args) { CAM_ERR(CAM_ISP, "Invalid args"); @@ -6289,9 +6290,11 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, /* Add change base */ if (!ctx->internal_cdm) { + change_base_info.base_idx = ctx->base[i].idx; + change_base_info.cdm_id = ctx->cdm_id; rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf); + &change_base_info, &kmd_buf); if (rc) { CAM_ERR(CAM_ISP, "Failed in change base i=%d, idx=%d, rc=%d", @@ -6401,11 +6404,13 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, /* add reg update commands */ for (i = 0; i < ctx->num_base; i++) { + change_base_info.base_idx = ctx->base[i].idx; + change_base_info.cdm_id = ctx->cdm_id; /* Add change base */ if (!ctx->internal_cdm) { rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src, - ctx->base[i].idx, &kmd_buf); + &change_base_info, &kmd_buf); if (rc) { CAM_ERR(CAM_ISP, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 010c7dda16a1..7a5e658da1b7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -74,6 +74,7 @@ struct cam_ife_hw_mgr_debug { * @cdm_ops cdm util operation pointer for building * cdm commands * @cdm_cmd cdm base and length request pointer + * @cdm_id cdm id of the acquired cdm * @sof_cnt sof count value per core, used for dual VFE * @epoch_cnt epoch count value per core, used for dual VFE * @eof_cnt eof count value per core, used for dual VFE @@ -130,7 +131,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t cdm_handle; struct cam_cdm_utils_ops *cdm_ops; struct cam_cdm_bl_request *cdm_cmd; - + enum cam_cdm_id cdm_id; uint32_t sof_cnt[CAM_IFE_HW_NUM_MAX]; uint32_t epoch_cnt[CAM_IFE_HW_NUM_MAX]; uint32_t eof_cnt[CAM_IFE_HW_NUM_MAX]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 8a26c06e7cd0..8aa68af8ca62 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -4008,6 +4008,7 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, bool fill_fence = true; struct cam_isp_prepare_hw_update_data *prepare_hw_data; struct cam_isp_frame_header_info frame_header_info; + struct cam_isp_change_base_args change_base_info = {0}; if (!hw_mgr_priv || !prepare_hw_update_args) { CAM_ERR(CAM_ISP, "Invalid args"); @@ -4060,9 +4061,12 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, "change base i=%d, idx=%d", i, ctx->base[i].idx); + change_base_info.base_idx = ctx->base[i].idx; + change_base_info.cdm_id = CAM_CDM_MAX; + /* Add change base */ rc = cam_isp_add_change_base(prepare, &ctx->res_list_tfe_in, - ctx->base[i].idx, &kmd_buf); + &change_base_info, &kmd_buf); if (rc) { CAM_ERR(CAM_ISP, "Failed in change base i=%d, idx=%d, rc=%d", @@ -4157,9 +4161,11 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, /* add reg update commands */ for (i = 0; i < ctx->num_base; i++) { + change_base_info.base_idx = ctx->base[i].idx; + change_base_info.cdm_id = CAM_CDM_MAX; /* Add change base */ rc = cam_isp_add_change_base(prepare, &ctx->res_list_tfe_in, - ctx->base[i].idx, &kmd_buf); + &change_base_info, &kmd_buf); if (rc) { CAM_ERR(CAM_ISP, "Failed in change base adding reg_update cmd i=%d, idx=%d, rc=%d", diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 6cad5f6e73ed..384970891721 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -15,7 +15,7 @@ int cam_isp_add_change_base( struct cam_hw_prepare_update_args *prepare, struct list_head *res_list_isp_src, - uint32_t base_idx, + struct cam_isp_change_base_args *change_base_args, struct cam_kmd_buf_info *kmd_buf_info) { int rc = -EINVAL; @@ -44,10 +44,11 @@ int cam_isp_add_change_base( continue; res = hw_mgr_res->hw_res[i]; - if (res->hw_intf->hw_idx != base_idx) + if (res->hw_intf->hw_idx != change_base_args->base_idx) continue; get_base.res = res; + get_base.cdm_id = change_base_args->cdm_id; get_base.cmd_type = CAM_ISP_HW_CMD_GET_CHANGE_BASE; get_base.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + kmd_buf_info->used_bytes/4; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index 1be8507e20f0..ccd990799614 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -12,6 +12,7 @@ #include "cam_isp_hw_mgr.h" #include "cam_hw_intf.h" #include "cam_packet_util.h" +#include "cam_cdm_intf_api.h" /* enum cam_isp_cdm_bl_type - isp cdm packet type*/ enum cam_isp_cdm_bl_type { @@ -47,6 +48,17 @@ struct cam_isp_frame_header_info { uint32_t frame_header_res_id; }; +/* + * struct cam_isp_change_base_args + * + * @cdm_id: CDM id + * @base_idx: Base index + */ +struct cam_isp_change_base_args { + enum cam_cdm_id cdm_id; + uint32_t base_idx; +}; + /* * cam_isp_add_change_base() * @@ -56,8 +68,7 @@ struct cam_isp_frame_header_info { * * @prepare: Contain the packet and HW update variables * @res_list_isp_src: Resource list for IFE/VFE source - * @base_idx: Base or dev index of the IFE/VFE HW instance for - * which change change base need to be added + * @change_base_args: Arguments for Change base function * @kmd_buf_info: Kmd buffer to store the change base command * @return: 0 for success * -EINVAL for Fail @@ -65,7 +76,7 @@ struct cam_isp_frame_header_info { int cam_isp_add_change_base( struct cam_hw_prepare_update_args *prepare, struct list_head *res_list_isp_src, - uint32_t base_idx, + struct cam_isp_change_base_args *change_base_args, struct cam_kmd_buf_info *kmd_buf_info); /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index de5b0499603b..b90705766ebe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -12,6 +12,7 @@ #include "cam_soc_util.h" #include "cam_irq_controller.h" #include "cam_hw_intf.h" +#include "cam_cdm_intf_api.h" /* Maximum length of tag while dumping */ #define CAM_ISP_HW_DUMP_TAG_MAX_LEN 32 @@ -273,12 +274,14 @@ struct cam_isp_hw_get_res_for_mid { * * @res: Resource node * @cmd_type: Command type for which to get update + * @cdm_id : CDM id * @cmd: Command buffer information * */ struct cam_isp_hw_get_cmd_update { struct cam_isp_resource_node *res; enum cam_isp_hw_cmd_type cmd_type; + enum cam_cdm_id cdm_id; struct cam_isp_hw_cmd_buf_update cmd; union { void *data; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index bd2c808bf150..1caf997c8f6e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -14,6 +14,7 @@ #define CAM_VFE_HW_NUM_MAX 7 #define VFE_CORE_BASE_IDX 0 +#define RT_BASE_IDX 2 /* * VBIF and BUS do not exist on same HW. * Hence both can be 1 below. From 8e746194c9ab33c733d1e64e8ec240dabc717c66 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 5 Aug 2020 14:28:13 +0530 Subject: [PATCH 499/790] msm: camera: ope: remove the check for dev_type Calculate the total clk of all the ctx irrespective of the use case for the ctx. Remove dev_type check to add all the ctx clk while calculating total clk. CRs-Fixed: 2754351 Change-Id: I5c1681ac1a88cfec752ff58fd8b1f6ac5d05b28a Signed-off-by: Tejas Prajapati --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index ef01db9b13f7..db9e760d1e15 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1084,8 +1084,7 @@ static int cam_ope_calc_total_clk(struct cam_ope_hw_mgr *hw_mgr, hw_mgr_clk_info->base_clk = 0; for (i = 0; i < OPE_CTX_MAX; i++) { ctx_data = &hw_mgr->ctx[i]; - if (ctx_data->ctx_state == OPE_CTX_STATE_ACQUIRED && - ctx_data->ope_acquire.dev_type == dev_type) + if (ctx_data->ctx_state == OPE_CTX_STATE_ACQUIRED) hw_mgr_clk_info->base_clk += ctx_data->clk_info.base_clk; } From 5fb9f83c771e6ac486df059c0622761e8e72a571 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Sun, 13 Sep 2020 13:10:31 +0530 Subject: [PATCH 500/790] Revert "msm: camera: isp: Add check to dump supported fifo level registers in shima" This reverts commit 0690b71d8bcca485c7a2d38e0097c2c6c997ac8a. Change-Id: I3a85c38a188339a6df0ca97352ed6aa4413896c7 Signed-off-by: Salendarsingh Gaud --- .../vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c | 21 ++++--------------- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 21 ++++--------------- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index 722ab62a5d0c..74614722f4fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -844,22 +844,12 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private = NULL; uint32_t val0, val1, val2, val3, val4; - uint32_t camera_hw_version; - int rc = 0; - - val3 = val4 = 0; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } - rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); - return; - } - bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; violation_status = status[CAM_IFE_IRQ_VIOLATION_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; @@ -1028,13 +1018,10 @@ print_state: CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - - if (camera_hw_version == CAM_CPAS_TITAN_580_V100) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); - } + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); CAM_INFO(CAM_ISP, "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 2cc592014e46..5de4a5d61a14 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -943,22 +943,12 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, uint32_t bus_overflow_status = 0, status_0 = 0, status_2 = 0; struct cam_vfe_soc_private *soc_private; uint32_t val0, val1, val2, val3, val4; - uint32_t camera_hw_version; - int rc = 0; - - val3 = val4 = 0; if (!status) { CAM_ERR(CAM_ISP, "Invalid params"); return; } - rc = cam_cpas_get_cpas_hw_version(&camera_hw_version); - if (rc) { - CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc); - return; - } - bus_overflow_status = status[CAM_IFE_IRQ_BUS_OVERFLOW_STATUS]; status_0 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; status_2 = status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]; @@ -1278,13 +1268,10 @@ print_state: CAM_CPAS_REG_CAMNOC, 0x1420, true, &val1); cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x1A20, true, &val2); - - if (camera_hw_version == CAM_CPAS_TITAN_580_V100) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); - } + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7620, true, &val3); + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x7420, true, &val4); CAM_INFO(CAM_ISP, "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", From c5f8e70b0f3697e04d2f59c0b39ac1c15bfc29a4 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Mon, 14 Sep 2020 15:55:56 +0530 Subject: [PATCH 501/790] msm: camera: cci: Enable compilation for cci dump code CCI register dump is only enable when dump flag is defined. Remove this flag and add control via debugfs entry. This change helps debugfs entry to control cci device individually on the fly for debugging rather than to rebuild. CRs-Fixed: 2692379 Change-Id: Ic13dc903e861e7c49bf3b375a66b96bfbe5d9c70 Signed-off-by: shiwgupt --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 33 ++++---- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 80 +++++++++++++++++++ .../cam_sensor_module/cam_cci/cam_cci_dev.h | 8 ++ 3 files changed, 107 insertions(+), 14 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index af1cd28144ff..0d1b90932eeb 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -193,17 +193,26 @@ static int32_t cam_cci_lock_queue(struct cci_device *cci_dev, return cam_cci_write_i2c_queue(cci_dev, val, master, queue); } -#ifdef DUMP_CCI_REGISTERS -static void cam_cci_dump_registers(struct cci_device *cci_dev, + +void cam_cci_dump_registers(struct cci_device *cci_dev, enum cci_i2c_master_t master, enum cci_i2c_queue_t queue) { + uint32_t dump_en = 0; uint32_t read_val = 0; uint32_t i = 0; uint32_t reg_offset = 0; void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base; + dump_en = cci_dev->dump_en; + if (!(dump_en & CAM_CCI_NACK_DUMP_EN) && + !(dump_en & CAM_CCI_TIMEOUT_DUMP_EN)) { + CAM_DBG(CAM_CCI, + "Nack and Timeout dump is not enabled"); + return; + } + CAM_INFO(CAM_CCI, "**** CCI:%d register dump ****", - cci_dev->soc_info->index); + cci_dev->soc_info.index); /* CCI Top Registers */ CAM_INFO(CAM_CCI, "****CCI TOP Registers ****"); @@ -247,7 +256,7 @@ static void cam_cci_dump_registers(struct cci_device *cci_dev, reg_offset, read_val); } } -#endif +EXPORT_SYMBOL(cam_cci_dump_registers); static uint32_t cam_cci_wait(struct cci_device *cci_dev, enum cci_i2c_master_t master, @@ -263,9 +272,8 @@ static uint32_t cam_cci_wait(struct cci_device *cci_dev, if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].report_q[queue], CCI_TIMEOUT)) { -#ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); -#endif + CAM_ERR(CAM_CCI, "wait timeout for cci:%d, Maser:%d, Queue:%d, rc=%d", cci_dev->soc_info.index, master, queue, rc); @@ -1076,9 +1084,8 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, CAM_ERR(CAM_CCI, "wait timeout for th_complete cci: %d, master: %d, FIFO buf_lvl:0x%x, rc: %d", cci_dev->soc_info.index, master, val, rc); -#ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); -#endif + cam_cci_flush_queue(cci_dev, master); goto rel_mutex_q; } @@ -1167,11 +1174,10 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, "wait timeout for RD_DONE irq for cci: %d, master: %d, rc = %d FIFO buf_lvl:0x%x, rc: %d", cci_dev->soc_info.index, master, val, rc); - #ifdef DUMP_CCI_REGISTERS - cam_cci_dump_registers(cci_dev, + cam_cci_dump_registers(cci_dev, master, queue); - #endif - cam_cci_flush_queue(cci_dev, master); + + cam_cci_flush_queue(cci_dev, master); goto rel_mutex_q; } @@ -1364,9 +1370,8 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT)) { -#ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); -#endif + rc = -ETIMEDOUT; val = cam_io_r_mb(base + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 68bd320d89a8..8b5ab58539f1 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -12,6 +12,7 @@ #define CCI_MAX_DELAY 1000000 static struct v4l2_subdev *g_cci_subdev[MAX_CCI]; +static struct dentry *debugfs_root; struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) { @@ -233,6 +234,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK,cci: %d, M0_Q0 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_0, + QUEUE_0); complete_all(&cci_dev->cci_master_info[MASTER_0] .report_q[QUEUE_0]); } @@ -240,6 +243,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK,cci: %d, M0_Q1 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_0, + QUEUE_1); complete_all(&cci_dev->cci_master_info[MASTER_0] .report_q[QUEUE_1]); } @@ -261,6 +266,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK, cci: %d, M1_Q0 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_1, + QUEUE_0); complete_all(&cci_dev->cci_master_info[MASTER_1] .report_q[QUEUE_0]); } @@ -268,6 +275,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK, cci: %d, M1_Q1 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_1, + QUEUE_1); complete_all(&cci_dev->cci_master_info[MASTER_1] .report_q[QUEUE_1]); } @@ -372,6 +381,70 @@ static const struct v4l2_subdev_ops cci_subdev_ops = { static const struct v4l2_subdev_internal_ops cci_subdev_intern_ops; +static int cam_cci_get_debug(void *data, u64 *val) +{ + struct cci_device *cci_dev = (struct cci_device *)data; + + *val = cci_dev->dump_en; + + return 0; +} + +static int cam_cci_set_debug(void *data, u64 val) +{ + struct cci_device *cci_dev = (struct cci_device *)data; + + cci_dev->dump_en = val; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(cam_cci_debug, + cam_cci_get_debug, + cam_cci_set_debug, "%16llu\n"); + +static int cam_cci_create_debugfs_entry(struct cci_device *cci_dev) +{ + int rc = 0; + struct dentry *dbgfileptr = NULL; + + if (!debugfs_root) { + dbgfileptr = debugfs_create_dir("cam_cci", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_CCI, "debugfs directory creation fail"); + rc = -ENOENT; + goto end; + } + debugfs_root = dbgfileptr; + } + + if (cci_dev->soc_info.index == 0) { + dbgfileptr = debugfs_create_file("en_dump_cci0", 0644, + debugfs_root, cci_dev, &cam_cci_debug); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_CCI, "DebugFS not enabled"); + else { + rc = PTR_ERR(dbgfileptr); + goto end; + } + } + } else { + dbgfileptr = debugfs_create_file("en_dump_cci1", 0644, + debugfs_root, cci_dev, &cam_cci_debug); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_CCI, "DebugFS not enabled"); + else { + rc = PTR_ERR(dbgfileptr); + goto end; + } + } + } +end: + return rc; +} + static int cam_cci_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -447,6 +520,12 @@ static int cam_cci_component_bind(struct device *dev, CAM_DBG(CAM_CCI, "CPAS registration successful handle=%d", cpas_parms.client_handle); new_cci_dev->cpas_handle = cpas_parms.client_handle; + + rc = cam_cci_create_debugfs_entry(new_cci_dev); + if (rc) { + CAM_WARN(CAM_CCI, "debugfs creation failed"); + rc = 0; + } CAM_DBG(CAM_CCI, "Component bound successfully"); return rc; @@ -468,6 +547,7 @@ static void cam_cci_component_unbind(struct device *dev, v4l2_get_subdevdata(subdev); cam_cpas_unregister_client(cci_dev->cpas_handle); + debugfs_remove_recursive(debugfs_root); cam_cci_soc_remove(pdev, cci_dev); rc = cam_unregister_subdev(&(cci_dev->v4l2_dev_str)); if (rc < 0) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 62652c0397e4..808cf6177fb5 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,9 @@ #define PRIORITY_QUEUE (QUEUE_0) #define SYNC_QUEUE (QUEUE_1) +#define CAM_CCI_NACK_DUMP_EN BIT(1) +#define CAM_CCI_TIMEOUT_DUMP_EN BIT(2) + #define CCI_VERSION_1_2_9 0x10020009 enum cci_i2c_sync { MSM_SYNC_DISABLE, @@ -200,6 +204,7 @@ enum cam_cci_state_t { * @irqs_disabled: Mask for IRQs that are disabled * @init_mutex: Mutex for maintaining refcount for attached * devices to cci during init/deinit. + * @dump_en: To enable the selective dump */ struct cci_device { struct v4l2_subdev subdev; @@ -230,6 +235,7 @@ struct cci_device { bool is_burst_read; uint32_t irqs_disabled; struct mutex init_mutex; + uint64_t dump_en; }; enum cam_cci_i2c_cmd_type { @@ -301,6 +307,8 @@ struct cci_write_async { irqreturn_t cam_cci_irq(int irq_num, void *data); struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index); +void cam_cci_dump_registers(struct cci_device *cci_dev, + enum cci_i2c_master_t master, enum cci_i2c_queue_t queue); /** * @brief : API to register CCI hw to platform framework. From f1823039c0275e2b5729a5f7aae2c4da6a6e585f Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 10 Feb 2020 20:09:37 +0530 Subject: [PATCH 502/790] msm: camera: cpas: Setting the vote level on max supported clock lvl basis In Some targets number of use cases are 7 and it was an issue during setting TURBO clock level. Changed the validation from number of client usecase to MAX supported clock level. CRs-Fixed: 2571273 Change-Id: I05cd06ff11c2c43eb4b70d69314e04055894c5fc Signed-off-by: Chandan Kumar Jha --- drivers/cam_cpas/cam_cpas_hw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 521bf9246723..d809157d7b69 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -122,6 +122,14 @@ static int cam_cpas_util_vote_bus_client_level( goto end; } + if (level >= CAM_MAX_VOTE) { + CAM_ERR(CAM_CPAS, + "Invalid votelevel=%d,usecases=%d,Bus client=[%s]", + level, bus_client->common_data.num_usecases, + bus_client->common_data.name); + return -EINVAL; + } + if (level == bus_client->curr_vote_level) goto end; From d9a20488d897b7f0d86d4619d7cac5225c7c9adb Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 15 Sep 2020 13:29:11 -0700 Subject: [PATCH 503/790] msm: camera: common: Handle epoch if bubble recovery is disabled If bubble recovery is disabled, IFE driver should continue to notify that epoch to CRM as opposed to dropping that frame in IFE. In case of sHDR if bubble recovery is disabled and IFE does not notify the epoch at which bubble was detected it will lead to a trigger count mismatch in CRM. CRs-Fixed: 2768309 Change-Id: I311ce80857a905496c633708a5f4ee2391679037 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 48 ++++++++++++++++++++++++-- drivers/cam_req_mgr/cam_req_mgr_core.c | 5 +++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 67480b578c69..745d7670d5e1 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -942,7 +942,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); } else if (!req_isp->bubble_report) { - CAM_ERR(CAM_ISP, + CAM_DBG(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, @@ -1083,7 +1083,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); } else if (!req_isp->bubble_report) { - CAM_ERR(CAM_ISP, + CAM_DBG(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, @@ -1726,6 +1726,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { uint64_t request_id = 0; + struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; @@ -1784,6 +1785,27 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; + CAM_DBG(CAM_ISP, "Skip bubble recovery for req %lld ctx %u", + req->request_id, ctx->ctx_id); + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger && + ctx_isp->active_req_cnt <= 1) { + 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; + notify.req_id = + ctx_isp->req_info.last_bufdone_req_id; + notify.sof_timestamp_val = + ctx_isp->sof_timestamp_val; + notify.trigger_id = ctx_isp->trigger_id; + + ctx->ctx_crm_intf->notify_trigger(¬ify); + CAM_DBG(CAM_ISP, + "Notify CRM SOF frame %lld ctx %u", + ctx_isp->frame_id, ctx->ctx_id); + } + } } /* @@ -1905,6 +1927,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( struct cam_isp_context *ctx_isp, void *evt_data) { uint64_t request_id = 0; + struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; @@ -1966,6 +1989,27 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; + CAM_DBG(CAM_ISP, "Skip bubble recovery for req %lld ctx %u", + req->request_id, ctx->ctx_id); + if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger && + ctx_isp->active_req_cnt <= 1) { + 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; + notify.req_id = + ctx_isp->req_info.last_bufdone_req_id; + notify.sof_timestamp_val = + ctx_isp->sof_timestamp_val; + notify.trigger_id = ctx_isp->trigger_id; + + ctx->ctx_crm_intf->notify_trigger(¬ify); + CAM_DBG(CAM_ISP, + "Notify CRM SOF frame %lld ctx %u", + ctx_isp->frame_id, ctx->ctx_id); + } + } } /* diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 208037c255f6..9c7c687e016d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -554,6 +554,8 @@ static void __cam_req_mgr_flush_req_slot( atomic_set(&link->eof_event_cnt, 0); in_q->wr_idx = 0; in_q->rd_idx = 0; + link->trigger_cnt[0] = 0; + link->trigger_cnt[1] = 0; } /** @@ -3028,6 +3030,9 @@ static int __cam_req_mgr_check_for_dual_trigger( { int rc = -EAGAIN; + CAM_DBG(CAM_CRM, "trigger_cnt [%u: %u]", + link->trigger_cnt[0], link->trigger_cnt[1]); + if (link->trigger_cnt[0] == link->trigger_cnt[1]) { link->trigger_cnt[0] = 0; link->trigger_cnt[1] = 0; From 528d44a312a3c12f79995eeb66619627b33b3131 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Tue, 21 Jul 2020 16:37:09 -0700 Subject: [PATCH 504/790] msm: camera: icp: Support processor-specific HFI register offsets The HFI interface registers will have a different base address on the LX7 processor. We can utilize the newly added HFI ops to abstract the calculation of the address by kicking that info out to the device interface. The HFI register definitions have been tweaked to support offsets based on the calculated addresses. CRs-Fixed: 2722486 Change-Id: I93b9b2827ec0820eaac6ee2e6a611363b96a3223 Signed-off-by: Fernando Pacheco --- drivers/cam_icp/fw_inc/hfi_intf.h | 14 +++--- drivers/cam_icp/fw_inc/hfi_reg.h | 39 +++++++--------- drivers/cam_icp/hfi.c | 46 +++++++++++++------ drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 17 +++++++ drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 1 + .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 40 +++++++--------- 6 files changed, 90 insertions(+), 67 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 01777b831fab..e3af27e0f820 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -33,7 +33,6 @@ struct hfi_mem { * @qdss: qdss mapped memory for fw * @io_mem: io memory info * @io_mem2: 2nd io memory info - * @icp_base: icp base address */ struct hfi_mem_info { struct hfi_mem qtbl; @@ -46,17 +45,18 @@ struct hfi_mem_info { struct hfi_mem qdss; struct hfi_mem io_mem; struct hfi_mem io_mem2; - void __iomem *icp_base; }; /** * struct hfi_ops * @irq_raise: called to raise H2ICP interrupt * @irq_enable: called to enable interrupts from ICP + * @iface_addr: called to get interface registers base address */ struct hfi_ops { void (*irq_raise)(void *data); void (*irq_enable)(void *data); + void __iomem *(*iface_addr)(void *data); }; /** @@ -84,12 +84,11 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); * @hfi_ops: processor-specific hfi ops * @priv: device private data * @event_driven_mode: event mode - * @icp_base: icp base address * * Returns success(zero)/failure(non zero) */ -int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, - void *priv, uint8_t event_driven_mode, void *__iomem icp_base); +int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode); /** * hfi_get_hw_caps() - hardware capabilities from firmware @@ -110,7 +109,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); /** * cam_hfi_deinit() - cleanup HFI */ -void cam_hfi_deinit(void __iomem *icp_base); +void cam_hfi_deinit(void); /** * hfi_set_debug_level() - set debug level * @a5_dbg_type: 1 for debug_q & 2 for qdss @@ -152,11 +151,10 @@ int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg); /** * cam_hfi_resume() - function to resume * @hfi_mem: hfi memory info - * @icp_base: icp base address * * Returns success(zero)/failure(non zero) */ -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base); +int cam_hfi_resume(struct hfi_mem_info *hfi_mem); /** * cam_hfi_queue_dump() - utility function to dump hfi queues diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index c96080bd67fb..cfb459d27bb8 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -9,27 +9,24 @@ #include #include "hfi_intf.h" -/* start of ICP CSR registers */ -#define HFI_REG_A5_HW_VERSION 0x0 +/* general purpose registers */ +#define GEN_PURPOSE_REG(n) (n * 4) -/* general purpose registers from */ -#define HFI_REG_FW_VERSION 0x44 -#define HFI_REG_HOST_ICP_INIT_REQUEST 0x48 -#define HFI_REG_ICP_HOST_INIT_RESPONSE 0x4C -#define HFI_REG_SHARED_MEM_PTR 0x50 -#define HFI_REG_SHARED_MEM_SIZE 0x54 -#define HFI_REG_QTBL_PTR 0x58 -#define HFI_REG_UNCACHED_HEAP_PTR 0x5C -#define HFI_REG_UNCACHED_HEAP_SIZE 0x60 -#define HFI_REG_QDSS_IOVA 0x6C -#define HFI_REG_SFR_PTR 0x68 -#define HFI_REG_QDSS_IOVA_SIZE 0x70 -#define HFI_REG_IO_REGION_IOVA 0x74 -#define HFI_REG_IO_REGION_SIZE 0x78 -#define HFI_REG_IO2_REGION_IOVA 0x7C -#define HFI_REG_IO2_REGION_SIZE 0x80 - -/* end of ICP CSR registers */ +#define HFI_REG_FW_VERSION GEN_PURPOSE_REG(1) +#define HFI_REG_HOST_ICP_INIT_REQUEST GEN_PURPOSE_REG(2) +#define HFI_REG_ICP_HOST_INIT_RESPONSE GEN_PURPOSE_REG(3) +#define HFI_REG_SHARED_MEM_PTR GEN_PURPOSE_REG(4) +#define HFI_REG_SHARED_MEM_SIZE GEN_PURPOSE_REG(5) +#define HFI_REG_QTBL_PTR GEN_PURPOSE_REG(6) +#define HFI_REG_UNCACHED_HEAP_PTR GEN_PURPOSE_REG(7) +#define HFI_REG_UNCACHED_HEAP_SIZE GEN_PURPOSE_REG(8) +#define HFI_REG_SFR_PTR GEN_PURPOSE_REG(10) +#define HFI_REG_QDSS_IOVA GEN_PURPOSE_REG(11) +#define HFI_REG_QDSS_IOVA_SIZE GEN_PURPOSE_REG(12) +#define HFI_REG_IO_REGION_IOVA GEN_PURPOSE_REG(13) +#define HFI_REG_IO_REGION_SIZE GEN_PURPOSE_REG(14) +#define HFI_REG_IO2_REGION_IOVA GEN_PURPOSE_REG(15) +#define HFI_REG_IO2_REGION_SIZE GEN_PURPOSE_REG(16) /* start of Queue table and queues */ #define MAX_ICP_HFI_QUEUES 4 @@ -278,7 +275,6 @@ struct hfi_qtbl { * @cmd_q_state: State of command queue * @mutex msg_q_lock: Lock for message queue * @msg_q_state: State of message queue - * @csr_base: CSR base address * @priv: device private data */ struct hfi_info { @@ -292,7 +288,6 @@ struct hfi_info { bool cmd_q_state; struct mutex msg_q_lock; bool msg_q_state; - void __iomem *csr_base; void *priv; }; diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 32f0fe0f7810..f94301f4275b 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -51,6 +51,16 @@ static void hfi_irq_enable(struct hfi_info *hfi) hfi->ops.irq_enable(hfi->priv); } +static void __iomem *hfi_iface_addr(struct hfi_info *hfi) +{ + void __iomem *ret = NULL; + + if (hfi->ops.iface_addr) + ret = hfi->ops.iface_addr(hfi->priv); + + return IS_ERR_OR_NULL(ret) ? NULL : ret; +} + void cam_hfi_queue_dump(void) { struct hfi_qtbl *qtbl; @@ -550,12 +560,16 @@ int hfi_get_hw_caps(void *query_buf) return 0; } -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) +int cam_hfi_resume(struct hfi_mem_info *hfi_mem) { int rc = 0; uint32_t fw_version, status = 0; + void __iomem *icp_base = hfi_iface_addr(g_hfi); - g_hfi->csr_base = icp_base; + if (!icp_base) { + CAM_ERR(CAM_HFI, "invalid HFI interface address"); + return -EINVAL; + } if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, status, status == ICP_INIT_RESP_SUCCESS, @@ -602,15 +616,16 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) return rc; } -int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, - void *priv, uint8_t event_driven_mode, void __iomem *icp_base) +int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode) { int rc = 0; + uint32_t status = 0; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; - uint32_t hw_version, fw_version, status = 0; struct sfr_buf *sfr_buffer; + void __iomem *icp_base; if (!hfi_mem || !hfi_ops || !priv) { CAM_ERR(CAM_HFI, @@ -752,6 +767,16 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, break; } + g_hfi->ops = *hfi_ops; + g_hfi->priv = priv; + + icp_base = hfi_iface_addr(g_hfi); + if (!icp_base) { + CAM_ERR(CAM_HFI, "invalid HFI interface address"); + rc = -EINVAL; + goto regions_fail; + } + cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR); cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova, @@ -792,17 +817,12 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, goto regions_fail; } - hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]", - hw_version, fw_version); + CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", + cam_io_r(icp_base + HFI_REG_FW_VERSION)); - g_hfi->csr_base = icp_base; g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; g_hfi->msg_q_state = true; - g_hfi->ops = *hfi_ops; - g_hfi->priv = priv; hfi_irq_enable(g_hfi); @@ -819,7 +839,7 @@ alloc_fail: return rc; } -void cam_hfi_deinit(void __iomem *icp_base) +void cam_hfi_deinit(void) { mutex_lock(&hfi_cmd_q_mutex); mutex_lock(&hfi_msg_q_mutex); diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 8b6b068a64cd..646fc6cef0ef 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -33,6 +33,8 @@ #define PC_POLL_DELAY_US 100 #define PC_POLL_TIMEOUT_US 10000 +#define A5_GEN_PURPOSE_REG_OFFSET 0x40 + static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info, struct cam_icp_cpas_vote *cpas_vote) { @@ -513,6 +515,21 @@ void cam_a5_irq_enable(void *priv) ICP_SIERRA_A5_CSR_A2HOSTINTEN); } +void __iomem *cam_a5_iface_addr(void *priv) +{ + struct cam_hw_info *a5_info = priv; + void __iomem *base; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return ERR_PTR(-EINVAL); + } + + base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + + return base + A5_GEN_PURPOSE_REG_OFFSET; +} + int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h index 98a18165dd0d..49ab5ab2488f 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -83,6 +83,7 @@ irqreturn_t cam_a5_irq(int irq_num, void *data); void cam_a5_irq_raise(void *priv); void cam_a5_irq_enable(void *priv); +void __iomem *cam_a5_iface_addr(void *priv); /** * @brief : API to register a5 hw to platform framework. diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index ed8e9cb0b61e..f299f6bf258c 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -53,6 +53,12 @@ #define ICP_DEVICE_IDLE_TIMEOUT 400 +static const struct hfi_ops hfi_a5_ops = { + .irq_raise = cam_a5_irq_raise, + .irq_enable = cam_a5_irq_enable, + .iface_addr = cam_a5_iface_addr, +}; + static struct cam_icp_hw_mgr icp_hw_mgr; static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl); @@ -3118,17 +3124,8 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct hfi_mem_info hfi_mem; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); - return -EINVAL; - } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; - hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva; hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova; hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len; @@ -3203,8 +3200,7 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.iova, hfi_mem.io_mem2.len); - return cam_hfi_resume(&hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + return cam_hfi_resume(&hfi_mem); } static int cam_icp_retry_wait_for_abort( @@ -3479,7 +3475,6 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) { struct cam_icp_hw_mgr *hw_mgr = hw_priv; struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct cam_icp_a5_set_irq_cb irq_cb; struct cam_icp_a5_set_fw_buf_info fw_buf_info; int rc = 0; @@ -3494,7 +3489,7 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) CAM_DBG(CAM_ICP, "a5_dev_intf is NULL"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + fw_buf_info.kva = 0; fw_buf_info.iova = 0; fw_buf_info.len = 0; @@ -3505,8 +3500,9 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) sizeof(fw_buf_info)); if (rc) CAM_ERR(CAM_ICP, "nullify the fw buf failed"); - cam_hfi_deinit( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + + cam_hfi_deinit(); + irq_cb.icp_hw_mgr_cb = NULL; irq_cb.data = NULL; rc = a5_dev_intf->hw_ops.process_cmd( @@ -3624,7 +3620,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) struct cam_hw_intf *a5_dev_intf = NULL; struct cam_hw_info *a5_dev = NULL; struct hfi_mem_info hfi_mem; - struct hfi_ops hfi_ops; + const struct hfi_ops *hfi_ops; a5_dev_intf = hw_mgr->a5_dev_intf; if (!a5_dev_intf) { @@ -3689,11 +3685,9 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.len = 0x0; } - hfi_ops.irq_raise = cam_a5_irq_raise; - hfi_ops.irq_enable = cam_a5_irq_enable; + hfi_ops = &hfi_a5_ops; - return cam_hfi_init(&hfi_mem, &hfi_ops, a5_dev, 0, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + return cam_hfi_init(&hfi_mem, hfi_ops, a5_dev, 0); } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) @@ -3807,7 +3801,6 @@ hw_deinit: static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) { struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; bool icp_pc = false; int rc = 0; @@ -3827,7 +3820,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + rc = cam_icp_allocate_hfi_mem(); if (rc) goto alloc_hfi_mem_failed; @@ -3873,8 +3866,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) return rc; fw_init_failed: - cam_hfi_deinit( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_hfi_deinit(); hfi_init_failed: cam_icp_mgr_proc_suspend(hw_mgr); fw_download_failed: From 1bd8f23dd5fc74728e619a23663392fdf01258c2 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Fri, 5 Jun 2020 11:33:37 -0700 Subject: [PATCH 505/790] msm: camera: icp: Generalize proc references within hw manager The A5 references sprinkled throughout the hw manager will no longer make sesne within the context of two possible processors. We will instead prefer the more generic "icp" term to reference the processor in use e.g. icp_dev instead of a5_dev. Note that some references to A5 remain and will be cleaned up when LX7 is introduced. CRs-Fixed: 2722486 Change-Id: I9af73cc2af27a2aed2f4d7baaead89a20442e9ed Signed-off-by: Fernando Pacheco --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 30 +-- drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 2 +- drivers/cam_icp/icp_hw/bps_hw/bps_core.c | 3 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 215 ++++++++---------- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 4 +- .../icp_hw_mgr/include/cam_a5_hw_intf.h | 24 -- .../icp_hw_mgr/include/cam_icp_hw_intf.h | 32 ++- drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 3 +- 8 files changed, 148 insertions(+), 165 deletions(-) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 646fc6cef0ef..6882433c0252 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -549,7 +549,7 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, return -EINVAL; } - if (cmd_type >= CAM_ICP_A5_CMD_MAX) { + if (cmd_type >= CAM_ICP_CMD_MAX) { CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type); return -EINVAL; } @@ -559,16 +559,16 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, hw_info = core_info->a5_hw_info; switch (cmd_type) { - case CAM_ICP_A5_CMD_FW_DOWNLOAD: + case CAM_ICP_CMD_FW_DOWNLOAD: rc = cam_a5_download_fw(device_priv); break; - case CAM_ICP_A5_CMD_POWER_COLLAPSE: + case CAM_ICP_CMD_POWER_COLLAPSE: rc = cam_a5_power_collapse(a5_dev); break; - case CAM_ICP_A5_CMD_POWER_RESUME: + case CAM_ICP_CMD_POWER_RESUME: rc = cam_a5_power_resume(a5_dev, *((bool *)cmd_args)); break; - case CAM_ICP_A5_CMD_SET_FW_BUF: { + case CAM_ICP_CMD_SET_FW_BUF: { struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args; if (!cmd_args) { @@ -585,8 +585,8 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, core_info->fw_buf_len); break; } - case CAM_ICP_A5_SET_IRQ_CB: { - struct cam_icp_a5_set_irq_cb *irq_cb = cmd_args; + case CAM_ICP_SET_IRQ_CB: { + struct cam_icp_set_irq_cb *irq_cb = cmd_args; if (!cmd_args) { CAM_ERR(CAM_ICP, "cmd args NULL"); @@ -600,15 +600,15 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, break; } - case CAM_ICP_A5_SEND_INIT: + case CAM_ICP_SEND_INIT: hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0); break; - case CAM_ICP_A5_CMD_PC_PREP: + case CAM_ICP_CMD_PC_PREP: hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0); break; - case CAM_ICP_A5_CMD_VOTE_CPAS: { + case CAM_ICP_CMD_VOTE_CPAS: { struct cam_icp_cpas_vote *cpas_vote = cmd_args; if (!cmd_args) { @@ -620,7 +620,7 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, break; } - case CAM_ICP_A5_CMD_CPAS_START: { + case CAM_ICP_CMD_CPAS_START: { struct cam_icp_cpas_vote *cpas_vote = cmd_args; if (!cmd_args) { @@ -637,13 +637,13 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, break; } - case CAM_ICP_A5_CMD_CPAS_STOP: + case CAM_ICP_CMD_CPAS_STOP: if (core_info->cpas_start) { cam_cpas_stop(core_info->cpas_handle); core_info->cpas_start = false; } break; - case CAM_ICP_A5_CMD_UBWC_CFG: { + case CAM_ICP_CMD_UBWC_CFG: { struct a5_ubwc_cfg_ext *ubwc_cfg_ext = NULL; a5_soc = soc_info->soc_private; @@ -676,7 +676,7 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, break; } - case CAM_ICP_A5_CMD_CLK_UPDATE: { + case CAM_ICP_CMD_CLK_UPDATE: { int32_t clk_level = 0; struct cam_ahb_vote ahb_vote; @@ -700,7 +700,7 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, core_info->cpas_handle, &ahb_vote); break; } - case CAM_ICP_A5_CMD_HW_DUMP: { + case CAM_ICP_CMD_HW_DUMP: { struct cam_icp_hw_dump_args *dump_args = cmd_args; rc = cam_a5_fw_dump(dump_args, core_info); diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h index 49ab5ab2488f..b1d47d6e8a48 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -67,7 +67,7 @@ struct cam_a5_device_core_info { uint64_t fw_buf_len; struct cam_icp_a5_query_cap query_cap; struct cam_icp_a5_acquire_dev a5_acquire[8]; - struct cam_icp_a5_set_irq_cb irq_cb; + struct cam_icp_set_irq_cb irq_cb; uint32_t cpas_handle; bool cpas_start; }; diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index eea5ac24d82c..998e3f904df4 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -411,8 +411,7 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_bps_handle_resume(bps_dev); break; case CAM_ICP_BPS_CMD_UPDATE_CLK: { - struct cam_a5_clk_update_cmd *clk_upd_cmd = - (struct cam_a5_clk_update_cmd *)cmd_args; + struct cam_icp_clk_update_cmd *clk_upd_cmd = cmd_args; struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index f299f6bf258c..c0696d785316 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -111,20 +111,18 @@ static const char *cam_icp_dev_type_to_name( static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; int rc; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is NULL"); + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_CMD_UBWC_CFG, NULL, 0); + rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_CMD_UBWC_CFG, NULL, 0); if (rc) - CAM_ERR(CAM_ICP, "CAM_ICP_A5_CMD_UBWC_CFG is failed"); + CAM_ERR(CAM_ICP, "CAM_ICP_CMD_UBWC_CFG is failed"); return rc; } @@ -348,7 +346,7 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data) struct cam_hw_intf *ipe1_dev_intf = NULL; struct cam_hw_intf *bps_dev_intf = NULL; struct cam_hw_intf *dev_intf = NULL; - struct cam_a5_clk_update_cmd clk_upd_cmd; + struct cam_icp_clk_update_cmd clk_upd_cmd; int rc = 0; bool busy = false; @@ -407,14 +405,13 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data) clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, - &clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd)); + &clk_upd_cmd, sizeof(clk_upd_cmd)); if (clk_info->hw_type != ICP_CLK_HW_BPS) if (ipe1_dev_intf) ipe1_dev_intf->hw_ops.process_cmd( ipe1_dev_intf->hw_priv, id, - &clk_upd_cmd, - sizeof(struct cam_a5_clk_update_cmd)); + &clk_upd_cmd, sizeof(clk_upd_cmd)); done: mutex_unlock(&hw_mgr->hw_mgr_mutex); @@ -1436,14 +1433,14 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, struct cam_hw_intf *ipe0_dev_intf = NULL; struct cam_hw_intf *ipe1_dev_intf = NULL; struct cam_hw_intf *bps_dev_intf = NULL; - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = NULL; struct cam_hw_intf *dev_intf = NULL; - struct cam_a5_clk_update_cmd clk_upd_cmd; + struct cam_icp_clk_update_cmd clk_upd_cmd; ipe0_dev_intf = hw_mgr->ipe0_dev_intf; ipe1_dev_intf = hw_mgr->ipe1_dev_intf; bps_dev_intf = hw_mgr->bps_dev_intf; - a5_dev_intf = hw_mgr->a5_dev_intf; + icp_dev_intf = hw_mgr->icp_dev_intf; if ((!ipe0_dev_intf) || (!bps_dev_intf)) { @@ -1468,21 +1465,20 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, clk_upd_cmd.clk_level = -1; dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, - &clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd)); + &clk_upd_cmd, sizeof(clk_upd_cmd)); if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS) { if (ipe1_dev_intf) { ipe1_dev_intf->hw_ops.process_cmd( ipe1_dev_intf->hw_priv, id, - &clk_upd_cmd, - sizeof(struct cam_a5_clk_update_cmd)); + &clk_upd_cmd, sizeof(clk_upd_cmd)); } /* update a5 clock */ CAM_DBG(CAM_PERF, "Update ICP clk to level [%d]", clk_upd_cmd.clk_level); - a5_dev_intf->hw_ops.process_cmd(a5_dev_intf->hw_priv, - CAM_ICP_A5_CMD_CLK_UPDATE, &clk_upd_cmd.clk_level, + icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_CMD_CLK_UPDATE, &clk_upd_cmd.clk_level, sizeof(clk_upd_cmd.clk_level)); } @@ -2330,16 +2326,11 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr) { struct cam_icp_hw_ctx_data *ctx_data = NULL; struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL; - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; int rc = 0; - a5_dev_intf = icp_hw_mgr.a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + if (!msg_ptr) return -EINVAL; - } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + switch (msg_ptr[ICP_PACKET_OPCODE]) { case HFI_IPEBPS_CMD_OPCODE_IPE_ABORT: case HFI_IPEBPS_CMD_OPCODE_BPS_ABORT: @@ -2543,14 +2534,14 @@ static int cam_icp_process_msg_pkt_type( switch (msg_ptr[ICP_PACKET_TYPE]) { case HFI_MSG_SYS_INIT_DONE: CAM_DBG(CAM_ICP, "received SYS_INIT_DONE"); - complete(&hw_mgr->a5_complete); + complete(&hw_mgr->icp_complete); size_processed = ( (struct hfi_msg_init_done *)msg_ptr)->size; break; case HFI_MSG_SYS_PC_PREP_DONE: CAM_DBG(CAM_ICP, "HFI_MSG_SYS_PC_PREP_DONE is received\n"); - complete(&hw_mgr->a5_complete); + complete(&hw_mgr->icp_complete); size_processed = sizeof(struct hfi_msg_pc_prep_done); break; @@ -2968,25 +2959,24 @@ static void cam_icp_mgr_put_ctx(struct cam_icp_hw_ctx_data *ctx_data) static int cam_icp_mgr_send_pc_prep(struct cam_icp_hw_mgr *hw_mgr) { int rc; - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; unsigned long rem_jiffies; int timeout = 5000; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } - reinit_completion(&hw_mgr->a5_complete); + reinit_completion(&hw_mgr->icp_complete); CAM_DBG(CAM_ICP, "Sending HFI init command"); - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, CAM_ICP_A5_CMD_PC_PREP, NULL, 0); + rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_CMD_PC_PREP, NULL, 0); if (rc) return rc; CAM_DBG(CAM_ICP, "Wait for PC_PREP_DONE Message\n"); - rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.a5_complete, + rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.icp_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { rc = -ETIMEDOUT; @@ -3062,26 +3052,26 @@ static int cam_icp_mgr_hw_close_k(void *hw_priv, void *hw_close_args) static int cam_icp_mgr_proc_resume(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *icp_dev_intf = hw_mgr->a5_dev_intf; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; if (!icp_dev_intf) return -EINVAL; return icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, - CAM_ICP_A5_CMD_POWER_RESUME, + CAM_ICP_CMD_POWER_RESUME, &hw_mgr->a5_jtag_debug, sizeof(hw_mgr->a5_jtag_debug)); } static void cam_icp_mgr_proc_suspend(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *icp_dev_intf = hw_mgr->a5_dev_intf; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; if (!icp_dev_intf) return; icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, - CAM_ICP_A5_CMD_POWER_COLLAPSE, + CAM_ICP_CMD_POWER_COLLAPSE, NULL, 0); } @@ -3103,19 +3093,19 @@ static int __power_collapse(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *a5_dev_intf = hw_mgr->a5_dev_intf; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; int rc; CAM_DBG(CAM_PERF, "ENTER"); - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "A5 device interface is NULL"); + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } rc = __power_collapse(hw_mgr); - a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, NULL, 0); CAM_DBG(CAM_PERF, "EXIT"); @@ -3447,17 +3437,17 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = NULL; struct cam_hw_intf *ipe0_dev_intf = NULL; struct cam_hw_intf *ipe1_dev_intf = NULL; struct cam_hw_intf *bps_dev_intf = NULL; - a5_dev_intf = hw_mgr->a5_dev_intf; + icp_dev_intf = hw_mgr->icp_dev_intf; ipe0_dev_intf = hw_mgr->ipe0_dev_intf; ipe1_dev_intf = hw_mgr->ipe1_dev_intf; bps_dev_intf = hw_mgr->bps_dev_intf; - if ((!a5_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) { + if ((!icp_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) { CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close"); return; } @@ -3466,7 +3456,7 @@ static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr) ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv, NULL, 0); ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0); bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0); - a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, NULL, 0); hw_mgr->bps_clk_state = false; hw_mgr->ipe_clk_state = false; } @@ -3474,8 +3464,8 @@ static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) { struct cam_icp_hw_mgr *hw_mgr = hw_priv; - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_icp_a5_set_irq_cb irq_cb; + struct cam_hw_intf *icp_dev_intf = NULL; + struct cam_icp_set_irq_cb irq_cb; struct cam_icp_a5_set_fw_buf_info fw_buf_info; int rc = 0; @@ -3484,18 +3474,19 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) CAM_DBG(CAM_ICP, "hw mgr is already closed"); return 0; } - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_DBG(CAM_ICP, "a5_dev_intf is NULL"); + + icp_dev_intf = hw_mgr->icp_dev_intf; + if (!icp_dev_intf) { + CAM_DBG(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } fw_buf_info.kva = 0; fw_buf_info.iova = 0; fw_buf_info.len = 0; - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_CMD_SET_FW_BUF, + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_CMD_SET_FW_BUF, &fw_buf_info, sizeof(fw_buf_info)); if (rc) @@ -3505,9 +3496,9 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) irq_cb.icp_hw_mgr_cb = NULL; irq_cb.data = NULL; - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_SET_IRQ_CB, + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_SET_IRQ_CB, &irq_cb, sizeof(irq_cb)); if (rc) CAM_ERR(CAM_ICP, "deregister irq call back failed"); @@ -3522,24 +3513,24 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) static int cam_icp_mgr_device_init(struct cam_icp_hw_mgr *hw_mgr) { int rc = 0; - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = NULL; struct cam_hw_intf *ipe0_dev_intf = NULL; struct cam_hw_intf *ipe1_dev_intf = NULL; struct cam_hw_intf *bps_dev_intf = NULL; - a5_dev_intf = hw_mgr->a5_dev_intf; + icp_dev_intf = hw_mgr->icp_dev_intf; ipe0_dev_intf = hw_mgr->ipe0_dev_intf; ipe1_dev_intf = hw_mgr->ipe1_dev_intf; bps_dev_intf = hw_mgr->bps_dev_intf; - if ((!a5_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) { + if ((!icp_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) { CAM_ERR(CAM_ICP, "dev intfs are wrong"); return -EINVAL; } - rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0); + rc = icp_dev_intf->hw_ops.init(icp_dev_intf->hw_priv, NULL, 0); if (rc) - goto a5_dev_init_failed; + goto icp_dev_init_failed; rc = bps_dev_intf->hw_ops.init(bps_dev_intf->hw_priv, NULL, 0); if (rc) @@ -3567,29 +3558,29 @@ ipe0_dev_init_failed: bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0); hw_mgr->bps_clk_state = false; bps_dev_init_failed: - a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); -a5_dev_init_failed: + icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, NULL, 0); +icp_dev_init_failed: return rc; } static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) { int rc; - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_icp_a5_set_irq_cb irq_cb; + struct cam_hw_intf *icp_dev_intf = NULL; + struct cam_icp_set_irq_cb irq_cb; struct cam_icp_a5_set_fw_buf_info fw_buf_info; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + icp_dev_intf = hw_mgr->icp_dev_intf; + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is invalid"); return -EINVAL; } irq_cb.icp_hw_mgr_cb = cam_icp_hw_mgr_cb; irq_cb.data = hw_mgr; - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_SET_IRQ_CB, + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_SET_IRQ_CB, &irq_cb, sizeof(irq_cb)); if (rc) return rc; @@ -3598,16 +3589,16 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) fw_buf_info.iova = icp_hw_mgr.hfi_mem.fw_buf.iova; fw_buf_info.len = icp_hw_mgr.hfi_mem.fw_buf.len; - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_CMD_SET_FW_BUF, + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_CMD_SET_FW_BUF, &fw_buf_info, sizeof(fw_buf_info)); if (rc) return rc; - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_CMD_FW_DOWNLOAD, + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_CMD_FW_DOWNLOAD, NULL, 0); if (rc) return rc; @@ -3617,17 +3608,17 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; + struct cam_hw_intf *icp_dev_intf = NULL; + struct cam_hw_info *icp_dev = NULL; struct hfi_mem_info hfi_mem; const struct hfi_ops *hfi_ops; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + icp_dev_intf = hw_mgr->icp_dev_intf; + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is invalid"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + icp_dev = (struct cam_hw_info *)icp_dev_intf->hw_priv; hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva; hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova; @@ -3687,32 +3678,29 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_ops = &hfi_a5_ops; - return cam_hfi_init(&hfi_mem, hfi_ops, a5_dev, 0); + return cam_hfi_init(&hfi_mem, hfi_ops, icp_dev, 0); } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) { int rc; - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; unsigned long rem_jiffies; int timeout = 5000; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } - reinit_completion(&hw_mgr->a5_complete); + reinit_completion(&hw_mgr->icp_complete); CAM_DBG(CAM_ICP, "Sending HFI init command"); - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_SEND_INIT, - NULL, 0); + rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_SEND_INIT, NULL, 0); if (rc) return rc; - rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.a5_complete, + rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.icp_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { rc = -ETIMEDOUT; @@ -3757,14 +3745,13 @@ static int cam_icp_mgr_hw_open_k(void *hw_mgr_priv, void *download_fw_args) static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) { int rc = 0; - struct cam_hw_intf *a5_dev_intf = NULL; + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; bool downloadFromResume = true; CAM_DBG(CAM_ICP, "Enter"); - a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0]; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5 dev intf is wrong"); + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } @@ -3775,7 +3762,7 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) return rc; } - rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0); + rc = icp_dev_intf->hw_ops.init(icp_dev_intf->hw_priv, NULL, 0); if (rc) return -EINVAL; @@ -3793,14 +3780,13 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) power_collapse: __power_collapse(hw_mgr); hw_deinit: - a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, NULL, 0); return rc; } static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) { - struct cam_hw_intf *a5_dev_intf = NULL; struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; bool icp_pc = false; int rc = 0; @@ -3815,9 +3801,8 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) return rc; } - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); + if (!hw_mgr->icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is invalid"); return -EINVAL; } @@ -5167,7 +5152,7 @@ static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args) struct timespec64 cur_ts; struct timespec64 req_ts; ktime_t cur_time; - struct cam_hw_intf *a5_dev_intf; + struct cam_hw_intf *icp_dev_intf; struct cam_icp_hw_mgr *hw_mgr; struct cam_hw_dump_args *dump_args; struct cam_icp_hw_ctx_data *ctx_data; @@ -5253,10 +5238,10 @@ hw_dump: dump_args->offset += (hdr->size + sizeof(struct cam_icp_dump_header)); /* Dumping the fw image*/ icp_dump_args.offset = dump_args->offset; - a5_dev_intf = hw_mgr->a5_dev_intf; - rc = a5_dev_intf->hw_ops.process_cmd( - a5_dev_intf->hw_priv, - CAM_ICP_A5_CMD_HW_DUMP, &icp_dump_args, + icp_dev_intf = hw_mgr->icp_dev_intf; + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_CMD_HW_DUMP, &icp_dump_args, sizeof(struct cam_icp_hw_dump_args)); CAM_DBG(CAM_ICP, "Offset before %zu after %zu", dump_args->offset, icp_dump_args.offset); @@ -5932,7 +5917,7 @@ static int cam_icp_mgr_init_devs(struct device_node *of_node) of_node_put(child_node); } - icp_hw_mgr.a5_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_A5][0]; + icp_hw_mgr.icp_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_A5][0]; icp_hw_mgr.bps_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_BPS][0]; icp_hw_mgr.ipe0_dev_intf = icp_hw_mgr.devices[CAM_ICP_DEV_IPE][0]; if (icp_hw_mgr.ipe1_enable) @@ -6174,7 +6159,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, if (iommu_hdl) *iommu_hdl = icp_hw_mgr.iommu_hdl; - init_completion(&icp_hw_mgr.a5_complete); + init_completion(&icp_hw_mgr.icp_complete); return rc; icp_wq_create_failed: diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 1000ce72d425..f1de37240c16 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -373,7 +373,7 @@ struct cam_icp_hw_mgr { struct cam_req_mgr_core_workq *timer_work; uint32_t msg_buf[ICP_MSG_BUF_SIZE]; uint32_t dbg_buf[ICP_DBG_BUF_SIZE]; - struct completion a5_complete; + struct completion icp_complete; struct hfi_cmd_work_data *cmd_work_data; struct hfi_msg_work_data *msg_work_data; struct hfi_msg_work_data *timer_work_data; @@ -395,7 +395,7 @@ struct cam_icp_hw_mgr { bool ipe0_enable; bool ipe1_enable; bool bps_enable; - struct cam_hw_intf *a5_dev_intf; + struct cam_hw_intf *icp_dev_intf; struct cam_hw_intf *ipe0_dev_intf; struct cam_hw_intf *ipe1_dev_intf; struct cam_hw_intf *bps_dev_intf; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h index c3fefdc09ba9..f40c1d397f94 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h @@ -12,25 +12,6 @@ #include "cam_hw_mgr_intf.h" #include "cam_icp_hw_intf.h" -enum cam_icp_a5_cmd_type { - CAM_ICP_A5_CMD_FW_DOWNLOAD, - CAM_ICP_A5_CMD_POWER_COLLAPSE, - CAM_ICP_A5_CMD_POWER_RESUME, - CAM_ICP_A5_CMD_SET_FW_BUF, - CAM_ICP_A5_CMD_ACQUIRE, - CAM_ICP_A5_SET_IRQ_CB, - CAM_ICP_A5_TEST_IRQ, - CAM_ICP_A5_SEND_INIT, - CAM_ICP_A5_CMD_VOTE_CPAS, - CAM_ICP_A5_CMD_CPAS_START, - CAM_ICP_A5_CMD_CPAS_STOP, - CAM_ICP_A5_CMD_UBWC_CFG, - CAM_ICP_A5_CMD_PC_PREP, - CAM_ICP_A5_CMD_CLK_UPDATE, - CAM_ICP_A5_CMD_HW_DUMP, - CAM_ICP_A5_CMD_MAX, -}; - struct cam_icp_a5_set_fw_buf_info { uint32_t iova; uint64_t kva; @@ -65,11 +46,6 @@ struct cam_icp_a5_acquire_dev { uint32_t fw_handle; }; -struct cam_icp_a5_set_irq_cb { - int32_t (*icp_hw_mgr_cb)(uint32_t irq_status, void *data); - void *data; -}; - struct cam_icp_a5_test_irq { uint32_t test_irq; }; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h index 80a724b53d94..0890bd8583cf 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_ICP_HW_INTF_H @@ -13,15 +13,39 @@ #define CAM_ICP_BW_CONFIG_V1 1 #define CAM_ICP_BW_CONFIG_V2 2 -enum cam_a5_hw_type { +enum cam_icp_hw_type { CAM_ICP_DEV_A5, CAM_ICP_DEV_IPE, CAM_ICP_DEV_BPS, CAM_ICP_DEV_MAX, }; +enum cam_icp_cmd_type { + CAM_ICP_CMD_FW_DOWNLOAD, + CAM_ICP_CMD_POWER_COLLAPSE, + CAM_ICP_CMD_POWER_RESUME, + CAM_ICP_CMD_SET_FW_BUF, + CAM_ICP_CMD_ACQUIRE, + CAM_ICP_SET_IRQ_CB, + CAM_ICP_TEST_IRQ, + CAM_ICP_SEND_INIT, + CAM_ICP_CMD_VOTE_CPAS, + CAM_ICP_CMD_CPAS_START, + CAM_ICP_CMD_CPAS_STOP, + CAM_ICP_CMD_UBWC_CFG, + CAM_ICP_CMD_PC_PREP, + CAM_ICP_CMD_CLK_UPDATE, + CAM_ICP_CMD_HW_DUMP, + CAM_ICP_CMD_MAX, +}; + +struct cam_icp_set_irq_cb { + int32_t (*icp_hw_mgr_cb)(uint32_t irq_status, void *data); + void *data; +}; + /** - * struct cam_a5_clk_update_cmd - Payload for hw manager command + * struct cam_icp_clk_update_cmd - Payload for hw manager command * * @curr_clk_rate: clk rate to HW * @ipe_bps_pc_enable power collpase enable flag @@ -29,7 +53,7 @@ enum cam_a5_hw_type { * populated as output while the clk is being * updated to the given rate */ -struct cam_a5_clk_update_cmd { +struct cam_icp_clk_update_cmd { uint32_t curr_clk_rate; bool ipe_bps_pc_enable; int32_t clk_level; diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 2c82b1a5ac9a..2a53d53a5985 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -404,8 +404,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_ipe_handle_resume(ipe_dev); break; case CAM_ICP_IPE_CMD_UPDATE_CLK: { - struct cam_a5_clk_update_cmd *clk_upd_cmd = - (struct cam_a5_clk_update_cmd *)cmd_args; + struct cam_icp_clk_update_cmd *clk_upd_cmd = cmd_args; struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; From f1d47bfd71a24840edb8ad21bbb1712cc38e27e2 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Tue, 12 May 2020 11:34:57 -0700 Subject: [PATCH 506/790] msm: camera: icp: Rename debugfs entries to be proc hw agnostic Drop references to A5 within the debugfs entries so that they may be reused with other processors. CRs-Fixed: 2722486 Change-Id: I2680a98dd3d38906e616712da3d6e2835ebb9a85 Signed-off-by: Fernando Pacheco --- drivers/cam_icp/fw_inc/hfi_intf.h | 4 +- drivers/cam_icp/hfi.c | 4 +- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 80 +++++++++---------- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 9 +-- 4 files changed, 48 insertions(+), 49 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index e3af27e0f820..edbc26b1e8a7 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -112,10 +112,10 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); void cam_hfi_deinit(void); /** * hfi_set_debug_level() - set debug level - * @a5_dbg_type: 1 for debug_q & 2 for qdss + * @icp_dbg_type: 1 for debug_q & 2 for qdss * @lvl: FW debug message level */ -int hfi_set_debug_level(u64 a5_dbg_type, uint32_t lvl); +int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl); /** * hfi_set_fw_dump_level() - set firmware dump level diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index f94301f4275b..2cc4e53b523f 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -382,7 +382,7 @@ int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info) return 0; } -int hfi_set_debug_level(u64 a5_dbg_type, uint32_t lvl) +int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl) { uint8_t *prop; struct hfi_cmd_prop *dbg_prop; @@ -413,7 +413,7 @@ int hfi_set_debug_level(u64 a5_dbg_type, uint32_t lvl) dbg_prop->num_prop = 1; dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG; dbg_prop->prop_data[1] = lvl; - dbg_prop->prop_data[2] = a5_dbg_type; + dbg_prop->prop_data[2] = icp_dbg_type; hfi_write_cmd(prop); kfree(prop); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index c0696d785316..ef867225159b 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1836,53 +1836,53 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_default_clk, cam_icp_get_dbg_default_clk, cam_icp_set_dbg_default_clk, "%16llu"); -static int cam_icp_set_a5_dbg_lvl(void *data, u64 val) +static int cam_icp_set_icp_dbg_lvl(void *data, u64 val) { - icp_hw_mgr.a5_dbg_lvl = val; + icp_hw_mgr.icp_dbg_lvl = val; return 0; } -static int cam_icp_get_a5_dbg_lvl(void *data, u64 *val) +static int cam_icp_get_icp_dbg_lvl(void *data, u64 *val) { - *val = icp_hw_mgr.a5_dbg_lvl; + *val = icp_hw_mgr.icp_dbg_lvl; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fs, cam_icp_get_a5_dbg_lvl, - cam_icp_set_a5_dbg_lvl, "%08llu"); +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fs, cam_icp_get_icp_dbg_lvl, + cam_icp_set_icp_dbg_lvl, "%08llu"); -static int cam_icp_set_a5_dbg_type(void *data, u64 val) +static int cam_icp_set_icp_dbg_type(void *data, u64 val) { if (val <= NUM_HFI_DEBUG_MODE) - icp_hw_mgr.a5_debug_type = val; + icp_hw_mgr.icp_debug_type = val; return 0; } -static int cam_icp_get_a5_dbg_type(void *data, u64 *val) +static int cam_icp_get_icp_dbg_type(void *data, u64 *val) { - *val = icp_hw_mgr.a5_debug_type; + *val = icp_hw_mgr.icp_debug_type; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_type_fs, cam_icp_get_a5_dbg_type, - cam_icp_set_a5_dbg_type, "%08llu"); +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_type_fs, cam_icp_get_icp_dbg_type, + cam_icp_set_icp_dbg_type, "%08llu"); -static int cam_icp_set_a5_fw_dump_lvl(void *data, u64 val) +static int cam_icp_set_icp_fw_dump_lvl(void *data, u64 val) { if (val < NUM_HFI_DUMP_LVL) - icp_hw_mgr.a5_fw_dump_lvl = val; + icp_hw_mgr.icp_fw_dump_lvl = val; return 0; } -static int cam_icp_get_a5_fw_dump_lvl(void *data, u64 *val) +static int cam_icp_get_icp_fw_dump_lvl(void *data, u64 *val) { - *val = icp_hw_mgr.a5_fw_dump_lvl; + *val = icp_hw_mgr.icp_fw_dump_lvl; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_a5_fw_dump_lvl, - cam_icp_set_a5_fw_dump_lvl, "%08llu"); +DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_icp_fw_dump_lvl, + cam_icp_set_icp_fw_dump_lvl, "%08llu"); static int cam_icp_hw_mgr_create_debugfs_entry(void) { @@ -1907,16 +1907,16 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void) dbgfileptr = debugfs_create_file("icp_debug_clk", 0644, icp_hw_mgr.dentry, NULL, &cam_icp_debug_default_clk); - dbgfileptr = debugfs_create_bool("a5_jtag_debug", 0644, - icp_hw_mgr.dentry, &icp_hw_mgr.a5_jtag_debug); + dbgfileptr = debugfs_create_bool("icp_jtag_debug", 0644, + icp_hw_mgr.dentry, &icp_hw_mgr.icp_jtag_debug); - dbgfileptr = debugfs_create_file("a5_debug_type", 0644, + dbgfileptr = debugfs_create_file("icp_debug_type", 0644, icp_hw_mgr.dentry, NULL, &cam_icp_debug_type_fs); - dbgfileptr = debugfs_create_file("a5_debug_lvl", 0644, + dbgfileptr = debugfs_create_file("icp_debug_lvl", 0644, icp_hw_mgr.dentry, NULL, &cam_icp_debug_fs); - dbgfileptr = debugfs_create_file("a5_fw_dump_lvl", 0644, + dbgfileptr = debugfs_create_file("icp_fw_dump_lvl", 0644, icp_hw_mgr.dentry, NULL, &cam_icp_debug_fw_dump); if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) @@ -1926,7 +1926,7 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void) } end: /* Set default hang dump lvl */ - icp_hw_mgr.a5_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; + icp_hw_mgr.icp_fw_dump_lvl = HFI_FW_DUMP_ON_FAILURE; return rc; } @@ -2480,7 +2480,7 @@ static int cam_icp_mgr_process_fatal_error( BUG(); } rc = cam_icp_mgr_trigger_recovery(hw_mgr); - cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); } return rc; @@ -2635,7 +2635,7 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data) } } - cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); if ((task_data->irq_status & A5_WDT_0) || (task_data->irq_status & A5_WDT_1)) { @@ -3059,8 +3059,8 @@ static int cam_icp_mgr_proc_resume(struct cam_icp_hw_mgr *hw_mgr) return icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_CMD_POWER_RESUME, - &hw_mgr->a5_jtag_debug, - sizeof(hw_mgr->a5_jtag_debug)); + &hw_mgr->icp_jtag_debug, + sizeof(hw_mgr->icp_jtag_debug)); } static void cam_icp_mgr_proc_suspend(struct cam_icp_hw_mgr *hw_mgr) @@ -3323,7 +3323,7 @@ static int cam_icp_mgr_abort_handle( CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command ctx: %u", ctx_data->ctx_id); - cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } } @@ -3379,7 +3379,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); - cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } kfree(destroy_cmd); @@ -3705,7 +3705,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_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message"); @@ -3961,7 +3961,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_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } @@ -5130,7 +5130,7 @@ static int cam_icp_mgr_enqueue_abort( CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command ctx: %u", ctx_data->ctx_id); - cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); return rc; } @@ -5408,7 +5408,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_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } @@ -5455,7 +5455,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_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } @@ -5622,11 +5622,11 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) if (rc) goto get_io_buf_failed; - if (icp_hw_mgr.a5_debug_type) - hfi_set_debug_level(icp_hw_mgr.a5_debug_type, - icp_hw_mgr.a5_dbg_lvl); + if (icp_hw_mgr.icp_debug_type) + hfi_set_debug_level(icp_hw_mgr.icp_debug_type, + icp_hw_mgr.icp_dbg_lvl); - hfi_set_fw_dump_level(icp_hw_mgr.a5_fw_dump_lvl); + hfi_set_fw_dump_level(icp_hw_mgr.icp_fw_dump_lvl); rc = cam_icp_send_ubwc_cfg(hw_mgr); if (rc) @@ -5745,7 +5745,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); + cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); mutex_unlock(&ctx_data->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); return rc; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index f1de37240c16..e49f30d246f4 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -381,17 +381,16 @@ struct cam_icp_hw_mgr { uint32_t ipe_ctxt_cnt; uint32_t bps_ctxt_cnt; struct dentry *dentry; - bool a5_debug; bool icp_pc_flag; bool ipe_bps_pc_flag; uint64_t icp_debug_clk; uint64_t icp_default_clk; struct cam_icp_clk_info clk_info[ICP_CLK_HW_MAX]; bool secure_mode; - bool a5_jtag_debug; - u64 a5_debug_type; - u64 a5_dbg_lvl; - u64 a5_fw_dump_lvl; + bool icp_jtag_debug; + u64 icp_debug_type; + u64 icp_dbg_lvl; + u64 icp_fw_dump_lvl; bool ipe0_enable; bool ipe1_enable; bool bps_enable; From 8e99e13a5a87074bc6b505ef0f348ad43ebeb13d Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 15 Sep 2020 17:41:21 +0800 Subject: [PATCH 507/790] msm: camera: reqmgr: Add protection for workqueue congestion When workqueue is congested, CRM may apply same request to device which will trigger recovery due to apply fails. This change prevent CRM triggering recovery if the time interval of continuous applying req less than 5ms. CRs-Fixed: 2775372 Change-Id: I45c2ed76334b1bbf4547bbf21f90cf0a6c169323 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 22 +++++++++++++++++++--- drivers/cam_req_mgr/cam_req_mgr_core.h | 4 ++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 208037c255f6..3b9f36ae352d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -53,6 +53,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->prev_sof_timestamp = 0; link->skip_init_frame = false; link->num_sync_links = 0; + link->last_applied_jiffies = 0; atomic_set(&link->eof_event_cnt, 0); for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { @@ -1584,6 +1585,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, { int rc = 0, idx, i; int reset_step = 0; + bool check_retry_cnt = false; uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; struct cam_req_mgr_req_queue *in_q; @@ -1694,10 +1696,14 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger, &dev); if (rc < 0) { - if (in_q->last_applied_idx < in_q->rd_idx) { - /* Apply req failed retry at next sof */ - slot->status = CRM_SLOT_STATUS_REQ_PENDING; + /* Apply req failed retry at next sof */ + slot->status = CRM_SLOT_STATUS_REQ_PENDING; + if (jiffies_to_msecs(jiffies - link->last_applied_jiffies) > + MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS) + check_retry_cnt = true; + + if ((in_q->last_applied_idx < in_q->rd_idx) && check_retry_cnt) { link->retry_cnt++; if (link->retry_cnt == MAXIMUM_RETRY_ATTEMPTS) { CAM_DBG(CAM_CRM, @@ -1771,6 +1777,16 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } + /* + * Only update the jiffies of last applied request + * for SOF trigger, since it is used to protect from + * applying fails in ISP which is triggered at SOF. + * And, also don't need to do update for error case + * since error case doesn't check the retry count. + */ + if (trigger == CAM_TRIGGER_POINT_SOF) + link->last_applied_jiffies = jiffies; + mutex_unlock(&session->lock); return rc; error: diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index ebe440828ecf..b9f57a203197 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -36,6 +36,8 @@ #define MAXIMUM_RETRY_ATTEMPTS 2 +#define MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS 5 + #define VERSION_1 1 #define VERSION_2 2 #define CAM_REQ_MGR_MAX_TRIGGERS 2 @@ -371,6 +373,7 @@ struct cam_req_mgr_connected_device { * @eof_event_cnt : Atomic variable to track the number of EOF requests * @skip_init_frame : skip initial frames crm_wd_timer validation in the * case of long exposure use case + * @last_applied_jiffies : Record the jiffies of last applied req */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -407,6 +410,7 @@ struct cam_req_mgr_core_link { uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; atomic_t eof_event_cnt; bool skip_init_frame; + uint64_t last_applied_jiffies; }; /** From 64910dc3d6542b1498b6c72ab5be11f958a1ccb7 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 11 Sep 2020 17:11:00 +0530 Subject: [PATCH 508/790] msm: camera: tfe: Change csid stop sequence during flush This change takes care of a race which we see when we halt master csid immediately and slave csid halt to follow. In some scenarios after master csid halt, slave gives violation errors. With this change we are first changing the mode of slave to master then issue halt commands to both master and slave. CRs-Fixed: 2773668 Change-Id: Iab7baa41a69b2e4e0a658c7abac29d2dcb80c289 Signed-off-by: Ayush Kumar --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 55 +++++++++++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw/include/cam_tfe_csid_hw_intf.h | 27 ++++++ .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 97 ++++++++++++++++++- 4 files changed, 179 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 8aa68af8ca62..4f2c990e0faf 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -529,6 +529,48 @@ static int cam_tfe_hw_mgr_free_hw_res( return 0; } +static int cam_tfe_mgr_csid_change_halt_mode(struct list_head *halt_list, + uint32_t base_idx, enum cam_tfe_csid_halt_mode halt_mode) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_csid_hw_halt_args halt; + struct cam_hw_intf *hw_intf; + uint32_t i; + int rc = 0; + + list_for_each_entry(hw_mgr_res, halt_list, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i] || + (hw_mgr_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING)) + continue; + + isp_res = hw_mgr_res->hw_res[i]; + if (isp_res->hw_intf->hw_idx != base_idx) + continue; + + if ((isp_res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && + (isp_res->res_id == + CAM_TFE_CSID_PATH_RES_IPP)) { + hw_intf = isp_res->hw_intf; + halt.node_res = isp_res; + halt.halt_mode = halt_mode; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, + &halt, + sizeof(struct cam_csid_hw_halt_args)); + if (rc) + CAM_ERR(CAM_ISP, "Halt update failed"); + break; + } + } + } + + return rc; +} + static int cam_tfe_mgr_csid_stop_hw( struct cam_tfe_hw_mgr_ctx *ctx, struct list_head *stop_list, uint32_t base_idx, uint32_t stop_cmd) @@ -2650,6 +2692,19 @@ static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) */ if (i == ctx->num_base) master_base_idx = ctx->base[0].idx; + + /*Change slave mode*/ + if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) { + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == master_base_idx) + continue; + cam_tfe_mgr_csid_change_halt_mode( + &ctx->res_list_tfe_csid, + ctx->base[i].idx, + CAM_TFE_CSID_HALT_MODE_INTERNAL); + } + } + CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); /* Stop the master CSID path first */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index a3aef55354ea..8cec98ffeb4d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -129,6 +129,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_BLANKING_UPDATE, CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, + CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h index a665ac589311..f93c606392cb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h @@ -95,6 +95,33 @@ enum cam_tfe_csid_halt_cmd { CAM_TFE_CSID_HALT_MAX, }; +/** + * enum cam_tfe_csid_halt_mode_cmd - Specify the halt command type + */ +enum cam_tfe_csid_halt_mode { + CAM_TFE_CSID_HALT_MODE_INTERNAL, + CAM_TFE_CSID_HALT_MODE_GLOBAL, + CAM_TFE_CSID_HALT_MODE_MASTER, + CAM_TFE_CSID_HALT_MODE_SLAVE, + CAM_TFE_CSID_HALT_MODE_MAX, +}; + +/** + * struct cam_csid_hw_halt_args + * @halt_mode : Applicable only for PATH resources + * 0 Internal : The CSID responds to the HALT_CMD + * 1 Global : The CSID responds to the GLOBAL_HALT_CMD + * 2 Master : The CSID responds to the HALT_CMD + * 3 Slave : The CSID responds to the external halt command + * and not the HALT_CMD register + * @node_res : reource pointer array( ie cid or CSID) + * + */ +struct cam_csid_hw_halt_args { + enum cam_tfe_csid_halt_mode halt_mode; + struct cam_isp_resource_node *node_res; +}; + /** * struct cam_csid_hw_stop- stop all resources * @stop_cmd : Applicable only for PATH resources diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index f9325204ba72..0958b9790068 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1246,6 +1246,63 @@ static int cam_tfe_csid_enable_pxl_path( return 0; } +static void cam_tfe_csid_change_pxl_halt_mode( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res, + enum cam_tfe_csid_halt_mode halt_mode) +{ + uint32_t val = 0; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg; + bool is_ipp; + + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d", + csid_hw->hw_intf->hw_idx, res->res_id); + goto end; + } + + if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || + res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + goto end; + } + + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { + is_ipp = true; + pxl_reg = csid_reg->ipp_reg; + } else { + goto end; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "CSID:%d %s path Res:%d Invalid state%d", + csid_hw->hw_intf->hw_idx, "IPP", + res->res_id, res->res_state); + goto end; + } + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + + /* configure Halt for slave */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val &= ~0xC; + val |= (halt_mode << 2); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); +end: + return; +} + static int cam_tfe_csid_disable_pxl_path( struct cam_tfe_csid_hw *csid_hw, struct cam_isp_resource_node *res, @@ -2088,6 +2145,41 @@ end: return rc; } +int cam_tfe_csid_halt(struct cam_tfe_csid_hw *csid_hw, + void *halt_args) +{ + struct cam_isp_resource_node *res; + struct cam_csid_hw_halt_args *csid_halt; + + if (!csid_hw || !halt_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_halt = (struct cam_csid_hw_halt_args *)halt_args; + + /* Change the halt mode */ + res = csid_halt->node_res; + CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id); + + switch (res->res_type) { + case CAM_ISP_RESOURCE_PIX_PATH: + if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) + cam_tfe_csid_change_pxl_halt_mode(csid_hw, res, + csid_halt->halt_mode); + break; + default: + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + csid_hw->hw_intf->hw_idx, + res->res_type); + break; + } + + return 0; +} + static int cam_tfe_csid_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { @@ -2095,7 +2187,7 @@ static int cam_tfe_csid_stop(void *hw_priv, struct cam_tfe_csid_hw *csid_hw; struct cam_hw_info *csid_hw_info; struct cam_isp_resource_node *res; - struct cam_tfe_csid_hw_stop_args *csid_stop; + struct cam_tfe_csid_hw_stop_args *csid_stop; uint32_t i; uint32_t res_mask = 0; @@ -2472,6 +2564,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_DUMP_HW: rc = cam_tfe_csid_dump_hw(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE: + rc = cam_tfe_csid_halt(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); From 79b117017629014b2cc3073bdbe199f77d651fe8 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Wed, 16 Sep 2020 11:34:17 -0700 Subject: [PATCH 509/790] msm: camera: csiphy: Remove unused flags Remove following unused CCI and CPHY flags. CRs-Fixed: 2709537 Change-Id: I7a936733da75c71877ae52cfae9ddd358775c305 Signed-off-by: Jigar Agrawal --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 9 --------- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h | 8 -------- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h | 1 - 3 files changed, 18 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 62652c0397e4..8f84931a403d 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -31,7 +31,6 @@ #include "cam_soc_util.h" #include "cam_debug_util.h" -#define V4L2_IDENT_CCI 50005 #define CCI_I2C_QUEUE_0_SIZE 128 #define CCI_I2C_QUEUE_1_SIZE 32 #define CCI_I2C_QUEUE_0_SIZE_V_1_2 64 @@ -42,16 +41,8 @@ #define CCI_TIMEOUT msecs_to_jiffies(1500) #define NUM_QUEUES 2 -#define CCI_PINCTRL_STATE_DEFAULT "cci_default" -#define CCI_PINCTRL_STATE_SLEEP "cci_suspend" - -#define CCI_NUM_CLK_MAX 16 -#define CCI_NUM_CLK_CASES 5 -#define CCI_CLK_SRC_NAME "cci_src_clk" -#define MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_10 10 #define MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11 11 #define BURST_MIN_FREE_SIZE 8 -#define MAX_LRME_V4l2_EVENTS 30 /* Max bytes that can be read per CCI read transaction */ #define CCI_READ_MAX 256 diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 557fd4e70499..74d2dbd59080 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -30,10 +30,7 @@ #define MAX_CSIPHY 6 -#define MAX_LRME_V4l2_EVENTS 30 #define CSIPHY_NUM_CLK_MAX 16 -#define MAX_CSIPHY_REG_ARRAY 70 -#define MAX_CSIPHY_CMN_REG_ARRAY 5 #define MAX_LANES 5 #define MAX_SETTINGS_PER_LANE 43 @@ -43,9 +40,6 @@ #define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver" #define CAM_CSIPHY_RX_CLK_SRC "cphy_rx_src_clk" -#define CSIPHY_POWER_UP 0 -#define CSIPHY_POWER_DOWN 1 - #define CSIPHY_DEFAULT_PARAMS 0 #define CSIPHY_LANE_ENABLE 1 #define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 @@ -60,8 +54,6 @@ #define CAM_CSIPHY_MAX_DPHY_LANES 4 #define CAM_CSIPHY_MAX_CPHY_LANES 3 #define CAM_CSIPHY_MAX_CPHY_DPHY_COMBO_LN 3 -#define CAM_CSIPHY_MAX_CPHY_COMBO_LN 3 - #define DPHY_LANE_0 BIT(0) #define CPHY_LANE_0 BIT(1) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index e41464a35c20..6faf856d7aa4 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -22,7 +22,6 @@ #include "cam_csiphy_core.h" #define CSI_3PHASE_HW 1 -#define CSIPHY_VERSION_V35 0x35 #define CSIPHY_VERSION_V10 0x10 #define CSIPHY_VERSION_V11 0x11 #define CSIPHY_VERSION_V12 0x12 From 1beadb140b58d28d35e29e9338193c24e998edcd Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Wed, 20 May 2020 20:23:40 +0530 Subject: [PATCH 510/790] msm: camera: tfe: Handle sof monotonic boot time stamp Modify the sof monotonic boot timestamp logic. Boot time stamp difference between two frames should not change, it should be same as qtime csid time stamp difference. So modified logic to give proper boot time stamp with no difference in the successive frames, the difference of sof time stamp taken from qtime stamp value. Delayed IRQ handling can lead to torn read of timestamp register (LSB from nth frame and MSB from n+1th frame). This change tries to detect torn read cases and corrects timestamp close to the actual value. CRs-Fixed: 2688271 Change-Id: I1dc75629887cfcf971d51a7dae6ea28624d272f1 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 64 ++++++------- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 89 +++++++++++++++---- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 4 + 3 files changed, 107 insertions(+), 50 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 8aa68af8ca62..6ca6384c7e79 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -4467,41 +4467,43 @@ static int cam_tfe_mgr_cmd_get_sof_timestamp( struct cam_hw_intf *hw_intf; struct cam_tfe_csid_get_time_stamp_args csid_get_time; - list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_csid, list) { - for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (!hw_mgr_res->hw_res[i]) - continue; + hw_mgr_res = list_first_entry(&tfe_ctx->res_list_tfe_csid, + struct cam_isp_hw_mgr_res, list); + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + /* + * Get the SOF time stamp from left resource only. + * Left resource is master for dual tfe 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) { /* - * Get the SOF time stamp from left resource only. - * Left resource is master for dual tfe case and - * Rdi only context case left resource only hold - * the RDI resource + * Single TFE case, Get the time stamp from + * available one csid hw in the context + * Dual TFE case, get the time stamp from + * master(left) would be sufficient */ - hw_intf = hw_mgr_res->hw_res[i]->hw_intf; - if (hw_intf->hw_ops.process_cmd) { - /* - * Single TFE case, Get the time stamp from - * available one csid hw in the context - * Dual TFE 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( - hw_intf->hw_priv, - CAM_TFE_CSID_CMD_GET_TIME_STAMP, - &csid_get_time, - sizeof(struct - cam_tfe_csid_get_time_stamp_args)); - if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { - *time_stamp = - csid_get_time.time_stamp_val; - *boot_time_stamp = - csid_get_time.boot_timestamp; - } + csid_get_time.node_res = + hw_mgr_res->hw_res[i]; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_TFE_CSID_CMD_GET_TIME_STAMP, + &csid_get_time, + sizeof(struct + cam_tfe_csid_get_time_stamp_args)); + if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { + *time_stamp = + csid_get_time.time_stamp_val; + *boot_time_stamp = + csid_get_time.boot_timestamp; + break; } } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index f9325204ba72..5b7a03a51cef 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -345,6 +345,7 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d", csid_hw->hw_intf->hw_idx, val); csid_hw->error_irq_count = 0; + csid_hw->prev_boot_timestamp = 0; return rc; } @@ -998,6 +999,7 @@ static int cam_tfe_csid_disable_hw(struct cam_tfe_csid_hw *csid_hw) spin_unlock_irqrestore(&csid_hw->spin_lock, flags); csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; csid_hw->error_irq_count = 0; + csid_hw->prev_boot_timestamp = 0; return rc; } @@ -1612,16 +1614,36 @@ static int cam_tfe_csid_poll_stop_status( return rc; } +static int __cam_tfe_csid_read_timestamp(void __iomem *base, + uint32_t msb_offset, uint32_t lsb_offset, uint64_t *timestamp) +{ + uint32_t lsb, msb, tmp, torn = 0; + + msb = cam_io_r_mb(base + msb_offset); + do { + tmp = msb; + torn++; + lsb = cam_io_r_mb(base + lsb_offset); + msb = cam_io_r_mb(base + msb_offset); + } while (tmp != msb); + + *timestamp = msb; + *timestamp = (*timestamp << 32) | lsb; + + return (torn > 1); +} + static int cam_tfe_csid_get_time_stamp( struct cam_tfe_csid_hw *csid_hw, void *cmd_args) { - struct cam_tfe_csid_get_time_stamp_args *time_stamp; + struct cam_tfe_csid_get_time_stamp_args *time_stamp; struct cam_isp_resource_node *res; const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; const struct cam_tfe_csid_rdi_reg_offset *rdi_reg; struct timespec64 ts; - uint32_t time_32, id; + uint32_t id, torn; + uint64_t time_delta; time_stamp = (struct cam_tfe_csid_get_time_stamp_args *)cmd_args; res = time_stamp->node_res; @@ -1644,33 +1666,61 @@ static int cam_tfe_csid_get_time_stamp( } if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { - time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + - csid_reg->ipp_reg->csid_pxl_timestamp_curr1_sof_addr); - time_stamp->time_stamp_val = (uint64_t) time_32; - time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; - time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + - csid_reg->ipp_reg->csid_pxl_timestamp_curr0_sof_addr); + torn = __cam_tfe_csid_read_timestamp( + soc_info->reg_map[0].mem_base, + csid_reg->ipp_reg->csid_pxl_timestamp_curr1_sof_addr, + csid_reg->ipp_reg->csid_pxl_timestamp_curr0_sof_addr, + &time_stamp->time_stamp_val); } else { id = res->res_id; rdi_reg = csid_reg->rdi_reg[id]; - time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + - rdi_reg->csid_rdi_timestamp_curr1_sof_addr); - time_stamp->time_stamp_val = (uint64_t) time_32; - time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32; - - time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base + - rdi_reg->csid_rdi_timestamp_curr0_sof_addr); + torn = __cam_tfe_csid_read_timestamp( + soc_info->reg_map[0].mem_base, + rdi_reg->csid_rdi_timestamp_curr1_sof_addr, + rdi_reg->csid_rdi_timestamp_curr0_sof_addr, + &time_stamp->time_stamp_val); } - time_stamp->time_stamp_val |= (uint64_t) time_32; time_stamp->time_stamp_val = mul_u64_u32_div( time_stamp->time_stamp_val, CAM_TFE_CSID_QTIMER_MUL_FACTOR, CAM_TFE_CSID_QTIMER_DIV_FACTOR); - ktime_get_boottime_ts64(&ts); - time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) + - ts.tv_nsec); + if (!csid_hw->prev_boot_timestamp) { + ktime_get_boottime_ts64(&ts); + time_stamp->boot_timestamp = + (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + csid_hw->prev_qtimer_ts = 0; + CAM_DBG(CAM_ISP, "timestamp:%lld", + time_stamp->boot_timestamp); + } else { + time_delta = time_stamp->time_stamp_val - + csid_hw->prev_qtimer_ts; + + if (csid_hw->prev_boot_timestamp > + U64_MAX - time_delta) { + CAM_WARN(CAM_ISP, "boottimestamp overflowed"); + CAM_INFO(CAM_ISP, + "currQTimer %lx prevQTimer %lx prevBootTimer %lx torn %d", + time_stamp->time_stamp_val, + csid_hw->prev_qtimer_ts, + csid_hw->prev_boot_timestamp, torn); + return -EINVAL; + } + + time_stamp->boot_timestamp = + csid_hw->prev_boot_timestamp + time_delta; + } + + CAM_DBG(CAM_ISP, + "currQTimer %lx prevQTimer %lx currBootTimer %lx prevBootTimer %lx torn %d", + time_stamp->time_stamp_val, + csid_hw->prev_qtimer_ts, time_stamp->boot_timestamp, + csid_hw->prev_boot_timestamp, torn); + + csid_hw->prev_qtimer_ts = time_stamp->time_stamp_val; + csid_hw->prev_boot_timestamp = time_stamp->boot_timestamp; return 0; } @@ -2997,6 +3047,7 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, tfe_csid_hw->csid_debug = 0; tfe_csid_hw->error_irq_count = 0; + tfe_csid_hw->prev_boot_timestamp = 0; rc = cam_tfe_csid_disable_soc_resources( &tfe_csid_hw->hw_info->soc_info); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index d211a70c56bc..b9430e18f8cf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -387,6 +387,8 @@ struct cam_tfe_csid_path_cfg { * @ppi_hw_intf interface to ppi hardware * @ppi_enabled flag to specify if the hardware has ppi bridge * or not + * @prev_boot_timestamp previous frame bootime stamp + * @prev_qtimer_ts previous frame qtimer csid timestamp * */ struct cam_tfe_csid_hw { @@ -415,6 +417,8 @@ struct cam_tfe_csid_hw { void *event_cb_priv; struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX]; bool ppi_enable; + uint64_t prev_boot_timestamp; + uint64_t prev_qtimer_ts; }; int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, From b457f5fae557e4b000ab0a95f40d371c64bab64e Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Fri, 11 Sep 2020 15:46:09 +0530 Subject: [PATCH 511/790] msm: camera: ope: Increase max bl limit Increase max bl limit for OPE to 24 to support maximum 48 stripes. CRs-Fixed: 2761455 Change-Id: I961be1344fac0084649df321225e94a50d4e5a98 Signed-off-by: Rishabh Jain --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 2 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index 98d3587ac929..3d3d11598701 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -50,7 +50,7 @@ #define OPE_CMDS OPE_MAX_CMD_BUFS #define CAM_MAX_IN_RES 8 -#define OPE_MAX_CDM_BLS 16 +#define OPE_MAX_CDM_BLS 24 #define CAM_OPE_MAX_PER_PATH_VOTES 6 #define CAM_OPE_BW_CONFIG_UNKNOWN 0 diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index dee7186aad3d..922b5eab523e 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -393,6 +393,7 @@ static int cam_ope_dev_prepare_cdm_request( ope_request->ope_kmd_buf.offset; cdm_cmd->cmd[i].len = len; cdm_cmd->cmd[i].arbitrate = arbitrate; + cdm_cmd->cmd[i].enable_debug_gen_irq = false; cdm_cmd->cmd_arrary_count++; From 8f95314e7464df6be7d83a5b8ed0909a0e4c1eca Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Mon, 14 Sep 2020 14:17:53 -0700 Subject: [PATCH 512/790] msm: camera: sync: Fix imports for types Fix the order of imports for to resolve cam_sync typedef for kernel CFI. CRs-Fixed: 2772200 Change-Id: I4e5e642e6b45412904585aaa68c0ef77fedeee2d Signed-off-by: Karthik Jayakumar --- drivers/cam_sync/cam_sync_private.h | 1 + drivers/cam_sync/cam_sync_util.c | 5 ++--- drivers/cam_sync/cam_sync_util.h | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index 2f270ae181aa..40ca3a99de54 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -16,6 +16,7 @@ #include #include #include +#include "cam_sync_api.h" #if IS_REACHABLE(CONFIG_MSM_GLOBAL_SYNX) #include diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c index 7e939fcbbbfe..7bc8c947e4ee 100644 --- a/drivers/cam_sync/cam_sync_util.c +++ b/drivers/cam_sync/cam_sync_util.c @@ -291,10 +291,9 @@ void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work) struct sync_callback_info *cb_info = container_of(cb_dispatch_work, struct sync_callback_info, cb_dispatch_work); + sync_callback sync_data = cb_info->callback_func; - cb_info->callback_func(cb_info->sync_obj, - cb_info->status, - cb_info->cb_data); + sync_data(cb_info->sync_obj, cb_info->status, cb_info->cb_data); kfree(cb_info); } diff --git a/drivers/cam_sync/cam_sync_util.h b/drivers/cam_sync/cam_sync_util.h index 00bceb634961..ebe5a8ffdb71 100644 --- a/drivers/cam_sync/cam_sync_util.h +++ b/drivers/cam_sync/cam_sync_util.h @@ -7,7 +7,6 @@ #define __CAM_SYNC_UTIL_H__ -#include #include "cam_sync_private.h" #include "cam_debug_util.h" From 8b38e86abd5ddbcc266dd5bac26db757223a34ee Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Fri, 12 Jun 2020 10:46:09 +0530 Subject: [PATCH 513/790] msm: camera: isp: Max requests per context reduction in isp driver Reduced maximum no of requests per context from 20 to 8 in isp driver. CRs-Fixed: 2720238 Change-Id: If557b190fe94af72cc6fb28f36c3e1f6189218a5 Signed-off-by: Shravya Samala --- drivers/cam_isp/cam_isp_context.c | 4 ++-- drivers/cam_isp/cam_isp_context.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 745d7670d5e1..1b966b1f2831 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5678,14 +5678,14 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->init_timestamp = jiffies_to_msecs(jiffies); ctx->isp_device_type = isp_device_type; - for (i = 0; i < CAM_CTX_REQ_MAX; i++) { + for (i = 0; i < CAM_ISP_CTX_REQ_MAX; i++) { ctx->req_base[i].req_priv = &ctx->req_isp[i]; ctx->req_isp[i].base = &ctx->req_base[i]; } /* camera context setup */ rc = cam_context_init(ctx_base, isp_dev_name, CAM_ISP, ctx_id, - crm_node_intf, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX); + crm_node_intf, hw_intf, ctx->req_base, CAM_ISP_CTX_REQ_MAX); if (rc) { CAM_ERR(CAM_ISP, "Camera Context Base init failed"); goto err; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 26cc377c608f..2f85193bd4c9 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -26,6 +26,8 @@ */ #define CAM_ISP_CTX_RES_MAX 24 +/* max requests per ctx for isp */ +#define CAM_ISP_CTX_REQ_MAX 8 /* * Maximum configuration entry size - This is based on the * worst case DUAL IFE use case plus some margin. @@ -270,8 +272,8 @@ struct cam_isp_context { struct cam_ctx_ops *substate_machine; struct cam_isp_ctx_irq_ops *substate_machine_irq; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; - struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; + struct cam_ctx_request req_base[CAM_ISP_CTX_REQ_MAX]; + struct cam_isp_ctx_req req_isp[CAM_ISP_CTX_REQ_MAX]; void *hw_ctx; uint64_t sof_timestamp_val; From 9703cf925e04cf01257a50a6bdc14ad8d2e82887 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Fri, 24 Jul 2020 12:36:37 +0530 Subject: [PATCH 514/790] msm: camera: cci: Add CCI Global reset during CCI HW init During first CCI HW initialization, CCI HW global reset has to be called. Removed is_initialized removed, as it can be controlled through master_active_slave ref count to verify there is any active slave or not. CRs-Fixed: 2782553 Change-Id: Id845bfc936b976e160231ed3a0acbc951c32ad7f Signed-off-by: Anil Kumar Kanakanti --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 2 +- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 1 - .../cam_sensor_module/cam_cci/cam_cci_soc.c | 213 +++++++++--------- 3 files changed, 108 insertions(+), 108 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 0d1b90932eeb..4f309d4eab6b 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1171,7 +1171,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); CAM_ERR(CAM_CCI, - "wait timeout for RD_DONE irq for cci: %d, master: %d, rc = %d FIFO buf_lvl:0x%x, rc: %d", + "wait timeout for RD_DONE irq for cci: %d, master: %d, FIFO buf_lvl:0x%x, rc: %d", cci_dev->soc_info.index, master, val, rc); cam_cci_dump_registers(cci_dev, diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 808cf6177fb5..b8969926ce15 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -144,7 +144,6 @@ struct cam_cci_master_info { struct semaphore master_sem; bool is_first_req; uint16_t freq_ref_cnt; - bool is_initilized; }; struct cam_cci_clk_params_t { diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 302983958780..2f9d807e2d2a 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -13,6 +13,7 @@ static int cam_cci_init_master(struct cci_device *cci_dev, void __iomem *base = NULL; struct cam_hw_soc_info *soc_info = NULL; uint32_t max_queue_0_size = 0, max_queue_1_size = 0; + struct cam_cci_master_info *cci_master; soc_info = &cci_dev->soc_info; base = soc_info->reg_map[0].mem_base; @@ -25,51 +26,41 @@ static int cam_cci_init_master(struct cci_device *cci_dev, max_queue_1_size = CCI_I2C_QUEUE_1_SIZE; } - cci_dev->master_active_slave[master]++; - if (!cci_dev->cci_master_info[master].is_initilized) { - /* Re-initialize the completion */ - reinit_completion( - &cci_dev->cci_master_info[master].reset_complete); - reinit_completion(&cci_dev->cci_master_info[master].rd_done); + cci_master = &cci_dev->cci_master_info[master]; + /* Re-initialize the completion */ + reinit_completion(&cci_master->reset_complete); + reinit_completion(&cci_master->rd_done); - /* reinit the reports for the queue */ - for (i = 0; i < NUM_QUEUES; i++) - reinit_completion( - &cci_dev->cci_master_info[master].report_q[i]); + /* reinit the reports for the queue */ + for (i = 0; i < NUM_QUEUES; i++) + reinit_completion(&cci_master->report_q[i]); - /* Set reset pending flag to true */ - cci_dev->cci_master_info[master].reset_pending = true; - cam_io_w_mb((master == MASTER_0) ? - CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, - base + CCI_RESET_CMD_ADDR); - if (!wait_for_completion_timeout( - &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT)) { - CAM_ERR(CAM_CCI, - "Failed: reset complete timeout for master: %d", - master); - rc = -ETIMEDOUT; - cci_dev->master_active_slave[master]--; - return rc; - } - - flush_workqueue(cci_dev->write_wq[master]); - - /* Setting up the queue size for master */ - cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size - = max_queue_0_size; - cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size - = max_queue_1_size; - - CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0: %d Q1: %d", master, - cci_dev->cci_i2c_queue_info[master][QUEUE_0] - .max_queue_size, - cci_dev->cci_i2c_queue_info[master][QUEUE_1] - .max_queue_size); - - cci_dev->cci_master_info[master].status = 0; - cci_dev->cci_master_info[master].is_initilized = true; + /* Set reset pending flag to true */ + cci_master->reset_pending = true; + cam_io_w_mb((master == MASTER_0) ? + CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + if (!wait_for_completion_timeout( + &cci_master->reset_complete, CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "Failed: reset complete timeout for master: %d", + master); + rc = -ETIMEDOUT; + return rc; } + flush_workqueue(cci_dev->write_wq[master]); + + /* Setting up the queue size for master */ + cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size + = max_queue_0_size; + cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size + = max_queue_1_size; + + CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0: %d Q1: %d", master, + cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size, + cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size); + + cci_dev->cci_master_info[master].status = 0; return 0; } @@ -117,82 +108,94 @@ int cam_cci_init(struct v4l2_subdev *sd, return rc; } - if (cci_dev->ref_count++) { + if (!cci_dev->ref_count) { + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(cci_dev->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_CCI, "CPAS start failed rc= %d", rc); + return rc; + } + + cam_cci_get_clk_rates(cci_dev, c_ctrl); + + /* Enable Regulators and IRQ*/ + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_LOWSVS_VOTE, true); + if (rc < 0) { + CAM_DBG(CAM_CCI, + "request platform resources failed,rc:%d", rc); + goto platform_enable_failed; + } + + cci_dev->hw_version = cam_io_r_mb(base + CCI_HW_VERSION_ADDR); + CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version); + + cci_dev->payload_size = MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; + cci_dev->support_seq_write = 1; + + for (i = 0; i < MASTER_MAX; i++) + cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; + + reinit_completion( + &cci_dev->cci_master_info[master].reset_complete); + cci_dev->cci_master_info[master].reset_pending = true; + cci_dev->cci_master_info[master].status = 0; + + cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); + + if (!wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "Failed: reset complete timeout for master: %d", + master); + rc = -ETIMEDOUT; + goto platform_enable_failed; + } + + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_MASK_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_CLEAR_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_CLEAR_1_ADDR); + cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); + + /* Set RD FIFO threshold for M0 & M1 */ + if (cci_dev->hw_version != CCI_VERSION_1_2_9) { + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M0_RD_THRESHOLD_ADDR); + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M1_RD_THRESHOLD_ADDR); + } + cci_dev->cci_state = CCI_STATE_ENABLED; + } + cci_dev->ref_count++; + + if (!cci_dev->master_active_slave[master]) { rc = cam_cci_init_master(cci_dev, master); if (rc) { CAM_ERR(CAM_CCI, "Failed to init: Master: %d: rc: %d", master, rc); - cci_dev->ref_count--; + goto reset_complete_failed; } CAM_DBG(CAM_CCI, "ref_count %d, master: %d", cci_dev->ref_count, master); - return rc; } - - ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_LOWSVS_VOTE; - axi_vote.num_paths = 1; - axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; - axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; - axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; - - rc = cam_cpas_start(cci_dev->cpas_handle, &ahb_vote, &axi_vote); - if (rc) { - CAM_ERR(CAM_CCI, "CPAS start failed rc= %d", rc); - return rc; - } - - cam_cci_get_clk_rates(cci_dev, c_ctrl); - - /* Enable Regulators and IRQ*/ - rc = cam_soc_util_enable_platform_resource(soc_info, true, - CAM_LOWSVS_VOTE, true); - if (rc < 0) { - CAM_DBG(CAM_CCI, "request platform resources failed, rc: %d", - rc); - goto platform_enable_failed; - } - - cci_dev->hw_version = cam_io_r_mb(base + CCI_HW_VERSION_ADDR); - CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version); - - cci_dev->payload_size = MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; - cci_dev->support_seq_write = 1; - - rc = cam_cci_init_master(cci_dev, master); - if (rc) { - CAM_ERR(CAM_CCI, "Failed to init: Master: %d, rc: %d", - master, rc); - goto reset_complete_failed; - } - - for (i = 0; i < MASTER_MAX; i++) - cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; - - cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_MASK_0_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_CLEAR_0_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_MASK_1_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_CLEAR_1_ADDR); - cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); - - /* Set RD FIFO threshold for M0 & M1 */ - if (cci_dev->hw_version != CCI_VERSION_1_2_9) { - cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, - base + CCI_I2C_M0_RD_THRESHOLD_ADDR); - cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, - base + CCI_I2C_M1_RD_THRESHOLD_ADDR); - } - - cci_dev->cci_state = CCI_STATE_ENABLED; + cci_dev->master_active_slave[master]++; return 0; reset_complete_failed: cam_soc_util_disable_platform_resource(soc_info, 1, 1); -platform_enable_failed: cci_dev->ref_count--; +platform_enable_failed: cam_cpas_stop(cci_dev->cpas_handle); return rc; @@ -213,7 +216,6 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) for (i = 0; i < MASTER_MAX; i++) { new_cci_dev->cci_master_info[i].status = 0; new_cci_dev->cci_master_info[i].is_first_req = true; - new_cci_dev->cci_master_info[i].is_initilized = false; 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); @@ -404,7 +406,6 @@ int cam_cci_soc_release(struct cci_device *cci_dev, } if (!(--cci_dev->master_active_slave[master])) { - cci_dev->cci_master_info[master].is_initilized = false; CAM_DBG(CAM_CCI, "All submodules are released for master: %d", master); } From 5a37a310f7aab0c2f176894f1cae74fb7258487b Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 1 Sep 2020 14:19:27 -0700 Subject: [PATCH 515/790] msm: camera: sensor: Add pinctrl specific handling in res_mgr Currently pinctrl is handled together regardless of pinctrl is requested for the active/suspend state. This change adds the per pinctrl handling when pinctrl gpio is shared among multiple slaves. Also remove mclk specific logic as this change will handle it at gpio/pinctrl level. CRs-Fixed: 2758167 Change-Id: I4fa028d3eee80e056a74324a420c08967cbf6c5f Signed-off-by: Jigarkumar Zala --- .../cam_res_mgr/cam_res_mgr.c | 733 ++++++++++++------ .../cam_res_mgr/cam_res_mgr_api.h | 64 +- .../cam_res_mgr/cam_res_mgr_private.h | 65 +- .../cam_sensor_utils/cam_sensor_util.c | 47 +- .../cam_sensor_utils/cam_sensor_util.h | 4 + 5 files changed, 558 insertions(+), 355 deletions(-) diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 592b68002c87..c5d6c1504fc8 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -45,10 +45,6 @@ static void cam_res_mgr_free_res(void) kfree(flash_res); } mutex_unlock(&cam_res->flash_res_lock); - - mutex_lock(&cam_res->clk_res_lock); - cam_res->shared_clk_ref_count = 0; - mutex_unlock(&cam_res->clk_res_lock); } void cam_res_mgr_led_trigger_register(const char *name, struct led_trigger **tp) @@ -158,77 +154,117 @@ void cam_res_mgr_led_trigger_event(struct led_trigger *trig, } EXPORT_SYMBOL(cam_res_mgr_led_trigger_event); -int cam_res_mgr_shared_pinctrl_init(void) -{ - struct cam_soc_pinctrl_info *pinctrl_info; - - /* - * We allow the cam_res is NULL or shared_gpio_enabled - * is false, it means this driver no probed or doesn't - * have shared gpio in this device. - */ - if (!cam_res || !cam_res->shared_gpio_enabled) { - CAM_DBG(CAM_RES, "Not support shared gpio."); - 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; - } - - pinctrl_info = &cam_res->dt.pinctrl_info; - - pinctrl_info->pinctrl = - devm_pinctrl_get(cam_res->dev); - 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; - } - - pinctrl_info->gpio_state_active = - pinctrl_lookup_state(pinctrl_info->pinctrl, - CAM_RES_MGR_DEFAULT); - if (IS_ERR_OR_NULL(pinctrl_info->gpio_state_active)) { - 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; - } - - pinctrl_info->gpio_state_suspend = - pinctrl_lookup_state(pinctrl_info->pinctrl, - CAM_RES_MGR_SLEEP); - if (IS_ERR_OR_NULL(pinctrl_info->gpio_state_suspend)) { - 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; - } - - cam_res->pstatus = PINCTRL_STATUS_GOT; - mutex_unlock(&cam_res->gpio_res_lock); - - return 0; -} -EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_init); - -static bool cam_res_mgr_shared_pinctrl_check_hold(void) +int cam_res_mgr_util_get_idx_from_shared_pctrl_gpio( + uint gpio) { int index = 0; - int dev_num = 0; - bool hold = false; - struct list_head *list; - struct cam_gpio_res *gpio_res; + struct cam_res_mgr_dt *dt = &cam_res->dt; + + for (index = 0; index < dt->num_shared_pctrl_gpio; index++) { + if (gpio == dt->shared_pctrl_gpio[index]) + break; + } + + if (index == dt->num_shared_pctrl_gpio) + return -EINVAL; + + return index; +} +EXPORT_SYMBOL(cam_res_mgr_util_get_idx_from_shared_pctrl_gpio); + +int cam_res_mgr_util_get_idx_from_shared_gpio( + uint gpio) +{ + int index = 0; + struct cam_res_mgr_dt *dt = &cam_res->dt; + + for (index = 0; index < dt->num_shared_gpio; index++) { + if (gpio == dt->shared_gpio[index]) + break; + } + + if (index == dt->num_shared_gpio) + return -EINVAL; + + return index; +} +EXPORT_SYMBOL(cam_res_mgr_util_get_idx_from_shared_gpio); + +static bool cam_res_mgr_gpio_is_in_shared_pctrl_gpio( + uint gpio) +{ + int index = 0; + bool found = false; + struct cam_res_mgr_dt *dt = &cam_res->dt; + + for (index = 0; index < dt->num_shared_pctrl_gpio; index++) { + if (gpio == dt->shared_pctrl_gpio[index]) { + found = true; + break; + } + } + + return found; +} + +static bool cam_res_mgr_gpio_is_in_shared_gpio( + uint gpio) +{ + int index = 0; + bool found = false; struct cam_res_mgr_dt *dt = &cam_res->dt; for (; index < dt->num_shared_gpio; index++) { + if (gpio == dt->shared_gpio[index]) { + found = true; + break; + } + } + + return found; +} + +int cam_res_mgr_util_shared_gpio_check_hold(uint gpio) +{ + int index = 0; + int dev_num = 0; + struct list_head *list; + struct cam_gpio_res *gpio_res = NULL; + struct cam_res_mgr_dt *dt = NULL; + bool is_shared_gpio = false; + bool is_shared_pctrl_gpio = false; + + if (!cam_res) { + CAM_DBG(CAM_RES, "res mgr is not initilized"); + return 0; + } + + if (!cam_res->shared_gpio_enabled) { + CAM_DBG(CAM_RES, "Res_mgr is not sharing any gpios"); + return 0; + } + + dt = &cam_res->dt; + + is_shared_gpio = + cam_res_mgr_gpio_is_in_shared_gpio(gpio); + is_shared_pctrl_gpio = + cam_res_mgr_gpio_is_in_shared_pctrl_gpio(gpio); + + if (is_shared_gpio && is_shared_pctrl_gpio) { + CAM_ERR(CAM_RES, + "gpio %u cannot be shared between pinctrl and gpio"); + return -EINVAL; + } + + if (is_shared_gpio) { + index = cam_res_mgr_util_get_idx_from_shared_gpio(gpio); + if (index < 0) { + CAM_ERR(CAM_RES, "Gpio%u not found in shared gpio list", + gpio); + return -EINVAL; + } + list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { @@ -238,85 +274,113 @@ static bool cam_res_mgr_shared_pinctrl_check_hold(void) dev_num++; if (dev_num >= 2) { - hold = true; - break; + return RES_MGR_GPIO_NEED_HOLD; } } } } - if (cam_res->shared_clk_ref_count > 1) - hold = true; + if (is_shared_pctrl_gpio) { + index = cam_res_mgr_util_get_idx_from_shared_pctrl_gpio(gpio); + if (index < 0) { + CAM_ERR(CAM_RES, + "gpio%u not found in shared pctrl gpio list", + gpio); + return -EINVAL; + } - return hold; + list_for_each_entry(gpio_res, + &cam_res->gpio_res_list, list) { + if (gpio_res->gpio == + dt->shared_pctrl_gpio[index]) { + list_for_each(list, &gpio_res->dev_list) + dev_num++; + + if (dev_num >= 2) { + CAM_DBG(CAM_RES, + "gpio: %u needs to hold", gpio); + return RES_MGR_GPIO_NEED_HOLD; + } + } + } + } + + for (index = 0; index < dt->num_shared_gpio; index++) { + list_for_each_entry(gpio_res, + &cam_res->gpio_res_list, list) { + + if (gpio_res->gpio == + dt->shared_gpio[index]) { + list_for_each(list, &gpio_res->dev_list) + dev_num++; + + if (dev_num >= 2) { + CAM_DBG(CAM_RES, + "gpio: %u needs to hold", gpio); + return RES_MGR_GPIO_NEED_HOLD; + } + } + } + } + + for (index = 0; index < dt->num_shared_pctrl_gpio; index++) { + list_for_each_entry(gpio_res, + &cam_res->gpio_res_list, list) { + + if (gpio_res->gpio == + dt->shared_pctrl_gpio[index]) { + list_for_each(list, &gpio_res->dev_list) + dev_num++; + + if (dev_num >= 2) { + CAM_DBG(CAM_RES, + "gpio: %u needs to hold", gpio); + return RES_MGR_GPIO_NEED_HOLD; + } + } + } + } + + CAM_DBG(CAM_RES, "gpio: %u can free the resource", gpio); + return RES_MGR_GPIO_CAN_FREE; } +EXPORT_SYMBOL(cam_res_mgr_util_shared_gpio_check_hold); -void cam_res_mgr_shared_pinctrl_put(void) -{ - struct cam_soc_pinctrl_info *pinctrl_info; - - if (!cam_res || !cam_res->shared_gpio_enabled) { - CAM_DBG(CAM_RES, "Not support shared gpio."); - return; - } - - mutex_lock(&cam_res->gpio_res_lock); - if (cam_res->pstatus == PINCTRL_STATUS_PUT) { - CAM_DBG(CAM_RES, "The shared pinctrl already been put"); - mutex_unlock(&cam_res->gpio_res_lock); - return; - } - - if (cam_res_mgr_shared_pinctrl_check_hold()) { - CAM_INFO(CAM_RES, "Need hold put this pinctrl"); - mutex_unlock(&cam_res->gpio_res_lock); - return; - } - - pinctrl_info = &cam_res->dt.pinctrl_info; - - devm_pinctrl_put(pinctrl_info->pinctrl); - - cam_res->pstatus = PINCTRL_STATUS_PUT; - mutex_unlock(&cam_res->gpio_res_lock); -} -EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_put); - -int cam_res_mgr_shared_pinctrl_select_state(bool active) +static int cam_res_mgr_shared_pinctrl_select_state( + int idx, bool active) { int rc = 0; - struct cam_soc_pinctrl_info *pinctrl_info; if (!cam_res || !cam_res->shared_gpio_enabled) { CAM_DBG(CAM_RES, "Not support shared gpio."); return 0; } - mutex_lock(&cam_res->gpio_res_lock); - if (cam_res->pstatus == PINCTRL_STATUS_PUT) { + if (cam_res->pctrl_res[idx].pstatus == PINCTRL_STATUS_PUT) { CAM_DBG(CAM_RES, "The shared pinctrl alerady been put.!"); - mutex_unlock(&cam_res->gpio_res_lock); return 0; } - pinctrl_info = &cam_res->dt.pinctrl_info; - - if (active && (cam_res->pstatus != PINCTRL_STATUS_ACTIVE)) { - rc = pinctrl_select_state(pinctrl_info->pinctrl, - pinctrl_info->gpio_state_active); - cam_res->pstatus = PINCTRL_STATUS_ACTIVE; + if (active && + (cam_res->pctrl_res[idx].pstatus != PINCTRL_STATUS_ACTIVE)) { + CAM_DBG(CAM_RES, + "pinctrl select state to active for the shared_pctrl_gpio idx: %d", + idx); + rc = pinctrl_select_state(cam_res->pinctrl, + cam_res->pctrl_res[idx].active); + cam_res->pctrl_res[idx].pstatus = PINCTRL_STATUS_ACTIVE; } else if (!active && - !cam_res_mgr_shared_pinctrl_check_hold()) { - rc = pinctrl_select_state(pinctrl_info->pinctrl, - pinctrl_info->gpio_state_suspend); - cam_res->pstatus = PINCTRL_STATUS_SUSPEND; + (cam_res->pctrl_res[idx].pstatus == PINCTRL_STATUS_ACTIVE)) { + CAM_DBG(CAM_RES, + "pinctrl select state to suspend for the shared_pctrl_gpio idx: %d", + idx); + rc = pinctrl_select_state(cam_res->pinctrl, + cam_res->pctrl_res[idx].suspend); + cam_res->pctrl_res[idx].pstatus = PINCTRL_STATUS_SUSPEND; } - mutex_unlock(&cam_res->gpio_res_lock); - - return rc; + return 0; } -EXPORT_SYMBOL(cam_res_mgr_shared_pinctrl_select_state); static int cam_res_mgr_add_device(struct device *dev, struct cam_gpio_res *gpio_res) @@ -329,61 +393,78 @@ static int cam_res_mgr_add_device(struct device *dev, dev_res->dev = dev; INIT_LIST_HEAD(&dev_res->list); - list_add_tail(&dev_res->list, &gpio_res->dev_list); return 0; } -static bool cam_res_mgr_gpio_is_shared(uint gpio) +static struct cam_gpio_res *cam_res_mgr_find_if_gpio_in_list(uint gpio) { - int index = 0; - bool found = false; - struct cam_res_mgr_dt *dt = &cam_res->dt; + struct cam_gpio_res *gpio_res = NULL; - mutex_lock(&cam_res->gpio_res_lock); - for (; index < dt->num_shared_gpio; index++) { - if (gpio == dt->shared_gpio[index]) { - found = true; - break; - } + list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { + if (gpio == gpio_res->gpio) + return gpio_res; } - mutex_unlock(&cam_res->gpio_res_lock); - return found; + return NULL; } +static bool __cam_res_mgr_find_if_gpio_is_shared(uint gpio) +{ + bool found_in_shared_gpio = false; + bool found_in_shared_pctrl_gpio = false; + + found_in_shared_gpio = cam_res_mgr_gpio_is_in_shared_gpio(gpio); + + found_in_shared_pctrl_gpio = + cam_res_mgr_gpio_is_in_shared_pctrl_gpio(gpio); + + if (found_in_shared_pctrl_gpio && found_in_shared_gpio) { + CAM_WARN(CAM_RES, "gpio: %u cannot be shared in both list", + gpio); + return false; + } + + if (found_in_shared_pctrl_gpio || found_in_shared_gpio) + return true; + + return false; +} + + int cam_res_mgr_gpio_request(struct device *dev, uint gpio, unsigned long flags, const char *label) { - int rc = 0; - bool found = false; - struct cam_gpio_res *gpio_res = NULL; + int rc = 0; + bool dev_found = false; + bool gpio_found = false; + int pctrl_idx = -1; + struct cam_gpio_res *gpio_res = NULL; + mutex_lock(&cam_res->gpio_res_lock); if (cam_res && cam_res->shared_gpio_enabled) { - mutex_lock(&cam_res->gpio_res_lock); - list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { - if (gpio == gpio_res->gpio) { - found = true; - break; - } - } - mutex_unlock(&cam_res->gpio_res_lock); + gpio_res = cam_res_mgr_find_if_gpio_in_list(gpio); + if (gpio_res == NULL) + gpio_found = false; + else + gpio_found = true; } /* - * found equal to false has two situation: - * 1. shared gpio not enabled - * 2. shared gpio enabled, but not find this gpio + * gpio_found equal to false has two situation: + * 1. shared gpio/pinctrl_gpio not enabled + * 2. shared gpio/pinctrl_gpio enabled, but not find this gpio * from the gpio_res_list - * These two situation both need request gpio. + * These two situations both need request gpio. */ - if (!found) { + if (!gpio_found) { + CAM_DBG(CAM_RES, "gpio: %u not found in gpio_res list", gpio); rc = gpio_request_one(gpio, flags, label); if (rc) { CAM_ERR(CAM_RES, "gpio %d:%s request fails", gpio, label); - return rc; + goto end; } } @@ -392,59 +473,83 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio, * from gpio_res_list, then insert a cam_gpio_res * to gpio_res_list. */ - if (!found && cam_res - && cam_res->shared_gpio_enabled && - cam_res_mgr_gpio_is_shared(gpio)) { + if ((!gpio_found && cam_res + && cam_res->shared_gpio_enabled) && + (cam_res_mgr_gpio_is_in_shared_gpio(gpio) || + (cam_res_mgr_gpio_is_in_shared_pctrl_gpio(gpio)))) { + CAM_DBG(CAM_RES, "gpio: %u is shared", gpio); gpio_res = kzalloc(sizeof(struct cam_gpio_res), GFP_KERNEL); - if (!gpio_res) - return -ENOMEM; - + if (!gpio_res) { + rc = -ENOMEM; + goto end; + } gpio_res->gpio = gpio; gpio_res->power_on_count = 0; 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; + goto end; } list_add_tail(&gpio_res->list, &cam_res->gpio_res_list); - mutex_unlock(&cam_res->gpio_res_lock); } - if (found && cam_res + /* if shared gpio is in pinctrl gpio list */ + if (!gpio_found && cam_res + && cam_res->shared_gpio_enabled && + cam_res_mgr_gpio_is_in_shared_pctrl_gpio(gpio)) { + pctrl_idx = + cam_res_mgr_util_get_idx_from_shared_pctrl_gpio(gpio); + CAM_DBG(CAM_RES, + "shared_pctrl_gpio is at idx: %d", pctrl_idx); + if (pctrl_idx < 0) { + CAM_ERR(CAM_RES, + "pctrl_gpio: %u not found", gpio); + rc = -EINVAL; + goto end; + } + + /* Update Pinctrl state to active */ + cam_res_mgr_shared_pinctrl_select_state(pctrl_idx, true); + } + + if (gpio_found && cam_res && cam_res->shared_gpio_enabled) { struct cam_dev_res *dev_res = NULL; - found = 0; - mutex_lock(&cam_res->gpio_res_lock); list_for_each_entry(dev_res, &gpio_res->dev_list, list) { if (dev_res->dev == dev) { - found = 1; + dev_found = true; break; } } - if (!found) + if (!dev_found) { rc = cam_res_mgr_add_device(dev, gpio_res); - - mutex_unlock(&cam_res->gpio_res_lock); + if (rc) { + CAM_ERR(CAM_RES, + "add device to gpio res list failed rc: %d", + rc); + goto end; + } + } } +end: + mutex_unlock(&cam_res->gpio_res_lock); return rc; } EXPORT_SYMBOL(cam_res_mgr_gpio_request); -bool cam_res_mgr_check_if_gpio_is_shared( +bool cam_res_mgr_util_check_if_gpio_is_shared( struct gpio *gpio_tbl, uint8_t size) { - bool found = false; int i = 0; + bool found = false; if (!cam_res) { CAM_DBG(CAM_RES, "cam_res data is not avaialbe"); @@ -457,42 +562,44 @@ bool cam_res_mgr_check_if_gpio_is_shared( } for (i = 0; i < size; i++) { - found = cam_res_mgr_gpio_is_shared(gpio_tbl[i].gpio); - if (found) { - CAM_DBG(CAM_RES, "gpio: %d is shared gpio", - gpio_tbl[i].gpio); - break; - } + found = __cam_res_mgr_find_if_gpio_is_shared(gpio_tbl[i].gpio); + if (found) + return found; } - return found; + return false; } -EXPORT_SYMBOL(cam_res_mgr_check_if_gpio_is_shared); +EXPORT_SYMBOL(cam_res_mgr_util_check_if_gpio_is_shared); static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) { - bool found = false; - bool need_free = true; - int dev_num = 0; - struct cam_gpio_res *gpio_res = NULL; + bool gpio_found = false; + bool need_free = true; + int dev_num = 0; + struct cam_gpio_res *gpio_res = NULL; + bool is_shared_gpio = false; + bool is_shared_pctrl_gpio = false; + int pctrl_idx = -1; + is_shared_gpio = cam_res_mgr_gpio_is_in_shared_gpio(gpio); + is_shared_pctrl_gpio = + cam_res_mgr_gpio_is_in_shared_pctrl_gpio(gpio); + + mutex_lock(&cam_res->gpio_res_lock); if (cam_res && cam_res->shared_gpio_enabled) { - mutex_lock(&cam_res->gpio_res_lock); list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { if (gpio == gpio_res->gpio) { - found = true; + gpio_found = true; break; } } - mutex_unlock(&cam_res->gpio_res_lock); } - if (found && cam_res + if (gpio_found && cam_res && cam_res->shared_gpio_enabled) { struct list_head *list; struct cam_dev_res *dev_res = NULL; - mutex_lock(&cam_res->gpio_res_lock); /* Count the dev number in the dev_list */ list_for_each(list, &gpio_res->dev_list) dev_num++; @@ -507,7 +614,6 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) struct cam_dev_res, list); list_del_init(&dev_res->list); kfree(dev_res); - list_del_init(&gpio_res->list); kfree(gpio_res); } else { @@ -521,11 +627,22 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) } } } - mutex_unlock(&cam_res->gpio_res_lock); } - if (need_free) + if (need_free) { + if (is_shared_pctrl_gpio) { + pctrl_idx = + cam_res_mgr_util_get_idx_from_shared_pctrl_gpio( + gpio); + cam_res_mgr_shared_pinctrl_select_state( + pctrl_idx, false); + } + + CAM_DBG(CAM_RES, "freeing gpio: %u", gpio); gpio_free(gpio); + } + + mutex_unlock(&cam_res->gpio_res_lock); } void cam_res_mgr_gpio_free_arry(struct device *dev, @@ -542,15 +659,14 @@ int cam_res_mgr_gpio_set_value(unsigned int gpio, int value) bool found = false; struct cam_gpio_res *gpio_res = NULL; + mutex_lock(&cam_res->gpio_res_lock); if (cam_res && cam_res->shared_gpio_enabled) { - mutex_lock(&cam_res->gpio_res_lock); list_for_each_entry(gpio_res, &cam_res->gpio_res_list, list) { if (gpio == gpio_res->gpio) { found = true; break; } } - mutex_unlock(&cam_res->gpio_res_lock); } /* @@ -577,42 +693,85 @@ int cam_res_mgr_gpio_set_value(unsigned int gpio, int value) } } + mutex_unlock(&cam_res->gpio_res_lock); return rc; } EXPORT_SYMBOL(cam_res_mgr_gpio_set_value); -void cam_res_mgr_shared_clk_config(bool value) +static int cam_res_mgr_shared_pinctrl_init( + struct device *dev) { - if (!cam_res) - return; + int i = 0; + char pctrl_active[50]; + char pctrl_suspend[50]; + struct cam_res_mgr_dt *dt = &cam_res->dt; - mutex_lock(&cam_res->clk_res_lock); - if (value) - cam_res->shared_clk_ref_count++; - else - cam_res->shared_clk_ref_count--; - mutex_unlock(&cam_res->clk_res_lock); + cam_res->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR_OR_NULL(cam_res->pinctrl)) { + CAM_ERR(CAM_RES, "Pinctrl not available"); + return -EINVAL; + } + + for (i = 0; i < dt->num_shared_pctrl_gpio; i++) { + memset(pctrl_active, '\0', sizeof(pctrl_active)); + memset(pctrl_suspend, '\0', sizeof(pctrl_suspend)); + snprintf(pctrl_active, sizeof(pctrl_active), + "%s%s", + cam_res->dt.pctrl_name[i], + "_active"); + CAM_DBG(CAM_RES, "pctrl_active at index: %d name: %s", + i, pctrl_active); + snprintf(pctrl_suspend, sizeof(pctrl_suspend), + "%s%s", + cam_res->dt.pctrl_name[i], + "_suspend"); + CAM_DBG(CAM_RES, "pctrl_suspend at index: %d name: %s", + i, pctrl_suspend); + cam_res->pctrl_res[i].active = + pinctrl_lookup_state(cam_res->pinctrl, + pctrl_active); + if (IS_ERR_OR_NULL(cam_res->pctrl_res[i].active)) { + CAM_ERR(CAM_RES, + "Failed to get the active state pinctrl handle"); + return -EINVAL; + } + cam_res->pctrl_res[i].suspend = + pinctrl_lookup_state(cam_res->pinctrl, + pctrl_suspend); + if (IS_ERR_OR_NULL(cam_res->pctrl_res[i].active)) { + CAM_ERR(CAM_RES, + "Failed to get the active state pinctrl handle"); + return -EINVAL; + } + cam_res->pctrl_res[i].pstatus = PINCTRL_STATUS_GOT; + } + + cam_res->pstatus = PINCTRL_STATUS_GOT; + + return 0; } -EXPORT_SYMBOL(cam_res_mgr_shared_clk_config); -static int cam_res_mgr_parse_dt(struct device *dev) +static int cam_res_mgr_parse_dt_shared_gpio( + struct device *dev) { int rc = 0; struct device_node *of_node = NULL; struct cam_res_mgr_dt *dt = &cam_res->dt; of_node = dev->of_node; - dt->num_shared_gpio = of_property_count_u32_elems(of_node, "shared-gpios"); - if (dt->num_shared_gpio > MAX_SHARED_GPIO_SIZE || - dt->num_shared_gpio <= 0) { - /* - * Not really an error, it means dtsi not configure - * the shared gpio. - */ - CAM_DBG(CAM_RES, "Invalid GPIO number %d. No shared gpio.", + if (dt->num_shared_gpio <= 0) { + CAM_DBG(CAM_RES, + "Not found any shared gpio"); + return -ENODEV; + } + + if (dt->num_shared_gpio >= MAX_SHARED_GPIO_SIZE) { + CAM_ERR(CAM_RES, + "shared_gpio: %d max supported: %d", + MAX_SHARED_GPIO_SIZE, dt->num_shared_gpio); return -EINVAL; } @@ -624,39 +783,110 @@ static int cam_res_mgr_parse_dt(struct device *dev) return -EINVAL; } - dt->pinctrl_info.pinctrl = devm_pinctrl_get(dev); - if (IS_ERR_OR_NULL(dt->pinctrl_info.pinctrl)) { - CAM_ERR(CAM_RES, "Pinctrl not available"); - return -EINVAL; + return rc; +} + +static int cam_res_mgr_parse_dt_shared_pinctrl_gpio( + struct device *dev) +{ + int rc = 0, i = 0; + int pinctrl_name_nodes = 0; + struct device_node *of_node = NULL; + struct cam_res_mgr_dt *dt = &cam_res->dt; + + of_node = dev->of_node; + dt->num_shared_pctrl_gpio = of_property_count_u32_elems(of_node, + "shared-pinctrl-gpios"); + + if (dt->num_shared_pctrl_gpio <= 0) { + CAM_DBG(CAM_RES, + "Not found any shared pinctrl res"); + return -ENODEV; } - /* - * Check the pinctrl state to make sure the gpio - * shared enabled. - */ - dt->pinctrl_info.gpio_state_active = - pinctrl_lookup_state(dt->pinctrl_info.pinctrl, - CAM_RES_MGR_DEFAULT); - if (IS_ERR_OR_NULL(dt->pinctrl_info.gpio_state_active)) { + if (dt->num_shared_pctrl_gpio >= MAX_SHARED_PCTRL_GPIO_SIZE) { CAM_ERR(CAM_RES, - "Failed to get the active state pinctrl handle"); + "Invalid Pinctrl GPIO number %d. No shared gpio.", + dt->num_shared_pctrl_gpio); return -EINVAL; } - dt->pinctrl_info.gpio_state_suspend = - pinctrl_lookup_state(dt->pinctrl_info.pinctrl, - CAM_RES_MGR_SLEEP); - if (IS_ERR_OR_NULL(dt->pinctrl_info.gpio_state_suspend)) { + pinctrl_name_nodes = of_property_count_strings(of_node, + "shared-pctrl-gpio-names"); + + if (pinctrl_name_nodes != dt->num_shared_pctrl_gpio) { CAM_ERR(CAM_RES, - "Failed to get the active state pinctrl handle"); + "Mismatch between entries:: pctrl_gpio: %d and pctrl_name: %d", + dt->num_shared_pctrl_gpio, + pinctrl_name_nodes); return -EINVAL; } - devm_pinctrl_put(dt->pinctrl_info.pinctrl); + CAM_INFO(CAM_RES, + "number of pctrl_gpio: %d", dt->num_shared_pctrl_gpio); + + rc = of_property_read_u32_array(of_node, "shared-pinctrl-gpios", + dt->shared_pctrl_gpio, dt->num_shared_pctrl_gpio); + if (rc) { + CAM_ERR(CAM_RES, "Get shared pinctrl gpio array failed."); + return -EINVAL; + } + + for (i = 0; i < pinctrl_name_nodes; i++) { + rc = of_property_read_string_index(of_node, + "shared-pctrl-gpio-names", + i, &(dt->pctrl_name[i])); + CAM_INFO(CAM_RES, "shared-pctrl-gpio-names[%d] = %s", + i, dt->pctrl_name[i]); + if (rc) { + CAM_ERR(CAM_RES, + "i= %d pinctrl_name_nodes= %d reading clock-names failed", + i, pinctrl_name_nodes); + return rc; + } + } return rc; } +static int cam_res_mgr_parse_dt(struct device *dev) +{ + int rc = 0; + + rc = cam_res_mgr_parse_dt_shared_gpio(dev); + if (rc) { + if (rc == -ENODEV) { + CAM_DBG(CAM_RES, + "Shared GPIO resources not available"); + } else { + CAM_ERR(CAM_RES, + "Shared gpio parsing failed: rc: %d", rc); + return rc; + } + } + + rc = cam_res_mgr_parse_dt_shared_pinctrl_gpio(dev); + if (rc) { + if (rc == -ENODEV) { + CAM_DBG(CAM_RES, + "Pinctrl shared resources not available"); + } else { + CAM_ERR(CAM_RES, "Pinctrl parsing failed: rc: %d", + rc); + return rc; + } + } else { + /* When shared pinctrl is detected do the init */ + rc = cam_res_mgr_shared_pinctrl_init(dev); + if (rc) { + CAM_ERR(CAM_RES, "Pinctrl init failed rc: %d", rc); + return rc; + } + } + + return 0; +} + static int cam_res_mgr_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -664,25 +894,31 @@ static int cam_res_mgr_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); cam_res = kzalloc(sizeof(*cam_res), GFP_KERNEL); - if (!cam_res) + if (!cam_res) { + CAM_ERR(CAM_RES, "Not Enough Mem"); return -ENOMEM; - + } cam_res->dev = &pdev->dev; - mutex_init(&cam_res->flash_res_lock); - mutex_init(&cam_res->gpio_res_lock); - mutex_init(&cam_res->clk_res_lock); + CAM_DBG(CAM_RES, "ENTER"); rc = cam_res_mgr_parse_dt(&pdev->dev); if (rc) { - CAM_DBG(CAM_RES, "Disable shared gpio support."); - cam_res->shared_gpio_enabled = false; - } else { - CAM_DBG(CAM_RES, "Enable shared gpio support."); - cam_res->shared_gpio_enabled = true; + CAM_ERR(CAM_RES, + "Error in parsing device tree, rc: %d", rc); + kfree(cam_res); + return rc; } - cam_res->shared_clk_ref_count = 0; - cam_res->pstatus = PINCTRL_STATUS_PUT; + if (cam_res->dt.num_shared_gpio || cam_res->dt.num_shared_pctrl_gpio) { + CAM_DBG(CAM_RES, "Enable shared gpio support."); + cam_res->shared_gpio_enabled = true; + } else { + CAM_DBG(CAM_RES, "Disable shared gpio support."); + cam_res->shared_gpio_enabled = false; + } + + mutex_init(&cam_res->flash_res_lock); + mutex_init(&cam_res->gpio_res_lock); INIT_LIST_HEAD(&cam_res->gpio_res_list); INIT_LIST_HEAD(&cam_res->flash_res_list); @@ -696,9 +932,14 @@ static void cam_res_mgr_component_unbind(struct device *dev, { if (cam_res) { cam_res_mgr_free_res(); + devm_pinctrl_put(cam_res->pinctrl); + cam_res->pinctrl = NULL; + cam_res->pstatus = PINCTRL_STATUS_PUT; kfree(cam_res); cam_res = NULL; } + + CAM_DBG(CAM_RES, "Component unbound successfully"); } const static struct component_ops cam_res_mgr_component_ops = { diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h index 096cb0916e7d..cb5022f482e5 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h @@ -43,37 +43,6 @@ void cam_res_mgr_led_trigger_unregister(struct led_trigger *tp); void cam_res_mgr_led_trigger_event(struct led_trigger *trig, enum led_brightness brightness); -/** - * @brief: Get the corresponding pinctrl of dev - * - * Init the shared pinctrl if shared pinctrl enabled. - * - * @return None - */ -int cam_res_mgr_shared_pinctrl_init(void); - -/** - * @brief: Put the pinctrl - * - * Put the shared pinctrl. - * - * @return Status of operation. Negative in case of error. Zero otherwise. - */ -void cam_res_mgr_shared_pinctrl_put(void); - -/** - * @brief: Select the corresponding state - * - * Active state can be selected directly, but need hold to suspend the - * pinctrl if the gpios in this pinctrl also held by other pinctrl. - * - * @active : The flag to indicate whether active or suspend - * the shared pinctrl. - * - * @return Status of operation. Negative in case of error. Zero otherwise. - */ -int cam_res_mgr_shared_pinctrl_select_state(bool active); - /** * @brief: Check for shared gpio * @@ -85,7 +54,7 @@ int cam_res_mgr_shared_pinctrl_select_state(bool active); * @size : GPIO table size * @return Status of operation. False if not shared, true otherwise. */ -bool cam_res_mgr_check_if_gpio_is_shared( +bool cam_res_mgr_util_check_if_gpio_is_shared( struct gpio *gpio_tbl, uint8_t size); /** @@ -131,16 +100,6 @@ void cam_res_mgr_gpio_free_arry(struct device *dev, */ int cam_res_mgr_gpio_set_value(unsigned int gpio, int value); -/** - * @brief: Config the shared clk ref count - * - * Config the shared clk ref count.. - * - * @value : get or put the shared clk. - * - * @return None - */ -void cam_res_mgr_shared_clk_config(bool value); /** * @brief : API to register RES_MGR to platform framework. @@ -152,4 +111,25 @@ int cam_res_mgr_init(void); * @brief : API to remove RES_MGR from platform framework. */ void cam_res_mgr_exit(void); + +/** + * @brief : API to get gpio idx from shared gpio list. + * @return idx for Success and error if gpio not found or invalid. + */ +int cam_res_mgr_util_get_idx_from_shared_gpio(uint gpio); + +/** + * @brief : API to get gpio idx from shared pinctrl gpio list. + * @return idx for Success and error if gpio not found or invalid. + */ +int cam_res_mgr_util_get_idx_from_shared_pctrl_gpio(uint gpio); + +/** + * @brief : API to check whether gpio is in use or can be free. + * @return NEED_HOLD macro if gpio is in use CAN_FREE if gpio can be free, + * error if operation is not valid, 0 in case of res_mgr is not + * available. + */ +int cam_res_mgr_util_shared_gpio_check_hold(uint gpio); + #endif /* __CAM_RES_MGR_API_H__ */ diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h index 48611f6fbd7e..bee7085579ea 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef __CAM_RES_MGR_PRIVATE_H__ @@ -9,12 +9,10 @@ #include #include #include "cam_soc_util.h" +#include "cam_sensor_util.h" -#define MAX_SHARED_GPIO_SIZE 16 - -/* pinctrl states name */ -#define CAM_RES_MGR_SLEEP "cam_res_mgr_suspend" -#define CAM_RES_MGR_DEFAULT "cam_res_mgr_default" +#define MAX_SHARED_GPIO_SIZE 16 +#define MAX_SHARED_PCTRL_GPIO_SIZE 10 /** * enum pinctrl_status - Enum for pinctrl status @@ -65,17 +63,34 @@ struct cam_flash_res { struct led_trigger *trigger; }; +/** + * struct cam_pinctrl_res + * + * @active : Pinctrl state pointer for active state + * @suspend : Pinctrl state pointer for suspend state + * @pstatus : Pinctrl status holder + */ +struct cam_pinctrl_res { + struct pinctrl_state *active; + struct pinctrl_state *suspend; + enum pinctrl_status pstatus; +}; + /** * struct cam_res_mgr_dt * - * @shared_gpio : Shared gpios list in the device tree - * @num_shared_gpio : The number of shared gpio - * @pinctrl_info : Pinctrl information + * @shared_gpio : Shared gpios list + * @shared_pctrl_gpio : Shared pinctrl gpio list + * @num_shared_gpio : Number of shared gpio + * @num_shared_pctrl_gpio : Number of shared pinctrl gpio + * @pctrl_name : Pinctrl name from shared pinctrl gpio list */ struct cam_res_mgr_dt { - uint shared_gpio[MAX_SHARED_GPIO_SIZE]; - int num_shared_gpio; - struct cam_soc_pinctrl_info pinctrl_info; + uint shared_gpio[MAX_SHARED_GPIO_SIZE]; + uint shared_pctrl_gpio[MAX_SHARED_PCTRL_GPIO_SIZE]; + int num_shared_gpio; + int num_shared_pctrl_gpio; + const char *pctrl_name[MAX_SHARED_PCTRL_GPIO_SIZE]; }; /** @@ -84,27 +99,27 @@ struct cam_res_mgr_dt { * @dev : Pointer to the device * @dt : Device tree resource * @shared_gpio_enabled : The flag to indicate if support shared gpio - * @pstatus : Shared pinctrl status + * @pstatus : Top level device pinctrl status + * @pinctrl : Device pinctrl pointer + * @pctrl_res : Pinctrl resource array * @gpio_res_list : List head of the gpio resource * @flash_res_list : List head of the flash resource * @gpio_res_lock : GPIO resource lock * @flash_res_lock : Flash resource lock - * @clk_res_lock : Clk resource lock */ struct cam_res_mgr { - struct device *dev; - struct cam_res_mgr_dt dt; + struct device *dev; + struct cam_res_mgr_dt dt; + bool shared_gpio_enabled; - bool shared_gpio_enabled; - enum pinctrl_status pstatus; + enum pinctrl_status pstatus; + struct pinctrl *pinctrl; + struct cam_pinctrl_res pctrl_res[MAX_SHARED_PCTRL_GPIO_SIZE]; - uint shared_clk_ref_count; - - struct list_head gpio_res_list; - struct list_head flash_res_list; - struct mutex gpio_res_lock; - struct mutex flash_res_lock; - struct mutex clk_res_lock; + struct list_head gpio_res_list; + struct list_head flash_res_list; + struct mutex gpio_res_lock; + struct mutex flash_res_lock; }; #endif /* __CAM_RES_MGR_PRIVATE_H__ */ diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 9b13ff7e4d02..e965049730a7 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1201,7 +1201,8 @@ int cam_sensor_util_request_gpio_table( } for (i = 0; i < size; i++) { - CAM_DBG(CAM_SENSOR, "i: %d, gpio %d dir %ld", i, + CAM_DBG(CAM_SENSOR, "%s%d, i: %d, gpio %d dir %lld", + soc_info->dev_name, soc_info->index, i, gpio_tbl[i].gpio, gpio_tbl[i].flags); } @@ -1227,7 +1228,7 @@ int cam_sensor_util_request_gpio_table( return rc; } -static bool cam_sensor_util_check_gpio_is_shared( +bool cam_sensor_util_check_gpio_is_shared( struct cam_hw_soc_info *soc_info) { int rc = 0; @@ -1255,7 +1256,7 @@ static bool cam_sensor_util_check_gpio_is_shared( return false; } - rc = cam_res_mgr_check_if_gpio_is_shared( + rc = cam_res_mgr_util_check_if_gpio_is_shared( gpio_tbl, size); if (!rc) { CAM_DBG(CAM_SENSOR, @@ -1988,7 +1989,6 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info) { int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0, i = 0; - bool shared_gpio = false; int32_t vreg_idx = -1; struct cam_sensor_power_setting *power_setting = NULL; struct msm_camera_gpio_num_info *gpio_num_info = NULL; @@ -2007,9 +2007,6 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, return -EINVAL; } - if (soc_info->use_shared_clk) - cam_res_mgr_shared_clk_config(true); - ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev); if (ret < 0) { /* Some sensor subdev no pinctrl. */ @@ -2019,19 +2016,9 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, ctrl->cam_pinctrl_status = 1; } - shared_gpio = cam_sensor_util_check_gpio_is_shared(soc_info); rc = cam_sensor_util_request_gpio_table(soc_info, 1); - if (rc < 0) + if (rc < 0) { no_gpio = rc; - - if (shared_gpio) { - rc = cam_res_mgr_shared_pinctrl_init(); - if (rc) { - CAM_ERR(CAM_SENSOR, - "Failed to init shared pinctrl"); - shared_gpio = false; - return -EINVAL; - } } if (ctrl->cam_pinctrl_status) { @@ -2042,12 +2029,6 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, CAM_ERR(CAM_SENSOR, "cannot set pin to active state"); } - if (shared_gpio) { - ret = cam_res_mgr_shared_pinctrl_select_state(true); - if (ret) - CAM_ERR(CAM_SENSOR, - "Cannot set shared pin to active state"); - } CAM_DBG(CAM_SENSOR, "power setting size: %d", ctrl->power_setting_size); for (index = 0; index < ctrl->power_setting_size; index++) { @@ -2332,16 +2313,7 @@ power_up_failed: devm_pinctrl_put(ctrl->pinctrl_info.pinctrl); } - if (soc_info->use_shared_clk) - cam_res_mgr_shared_clk_config(false); - - if (shared_gpio) { - cam_res_mgr_shared_pinctrl_select_state(false); - cam_res_mgr_shared_pinctrl_put(); - } - ctrl->cam_pinctrl_status = 0; - cam_sensor_util_request_gpio_table(soc_info, 0); return rc; @@ -2372,7 +2344,6 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info) { int index = 0, ret = 0, num_vreg = 0, i; - bool shared_gpio = false; struct cam_sensor_power_setting *pd = NULL; struct cam_sensor_power_setting *ps = NULL; struct msm_camera_gpio_num_info *gpio_num_info = NULL; @@ -2383,7 +2354,6 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, return -EINVAL; } - shared_gpio = cam_sensor_util_check_gpio_is_shared(soc_info); gpio_num_info = ctrl->gpio_num_info; num_vreg = soc_info->num_rgltr; @@ -2521,13 +2491,6 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, } cam_sensor_util_request_gpio_table(soc_info, 0); - - if (soc_info->use_shared_clk) - cam_res_mgr_shared_clk_config(false); - if (shared_gpio) { - cam_res_mgr_shared_pinctrl_select_state(false); - cam_res_mgr_shared_pinctrl_put(); - } ctrl->cam_pinctrl_status = 0; return 0; diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 690b7189e7c7..66731008826b 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -20,6 +20,8 @@ #include "cam_sensor_io.h" #define INVALID_VREG 100 +#define RES_MGR_GPIO_NEED_HOLD 1 +#define RES_MGR_GPIO_CAN_FREE 2 /* * Constant Factors needed to change QTimer ticks to nanoseconds @@ -77,4 +79,6 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf, int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info, int bob_reg_idx, bool flag); + +bool cam_sensor_util_check_gpio_is_shared(struct cam_hw_soc_info *soc_info); #endif /* _CAM_SENSOR_UTIL_H_ */ From 27db3b226ba70130fb9245cb52db586efd041f57 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Tue, 1 Sep 2020 19:20:30 +0530 Subject: [PATCH 516/790] msm: camera: tfe: Add pid and mid support for tfe Process tfe page faults based on the pid and mid values. When page fault happen kernel api gives the pid and mid value, From pid and mid values TFE hw and tfe port that caused the Page fault can be find. Added support for this in the tfe driver. Based on the Pid and Mid values, get the HW id and port ids, go through all context which has this hw id and port id and log the data. Once context id is identified, log the acquire data and last consumed client address details. Dump the hw register data in the given buffer. Send the smmu page fault event through v4l2 queue to user. CRs-Fixed: 2775154 Change-Id: Iafaa7d1283ea0b836c223ed1fe6c419b0ac50c15 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 1 - drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 307 ++++++++++++++---- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 2 +- .../isp_hw/include/cam_tfe_csid_hw_intf.h | 1 + .../isp_hw/include/cam_tfe_hw_intf.h | 2 +- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 50 +++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 11 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 115 +++++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h | 3 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 2 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c | 28 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c | 23 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h | 4 + 13 files changed, 469 insertions(+), 80 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 6450b5d37ea9..e8b016ae98a9 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6689,7 +6689,6 @@ static void cam_ife_mgr_dump_pf_data( struct cam_hw_cmd_args *hw_cmd_args) { struct cam_ife_hw_mgr_ctx *ctx; - struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_hw_get_cmd_update cmd_update; struct cam_isp_hw_get_res_for_mid get_res; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 4f2c990e0faf..e3618e858d0e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1105,7 +1105,7 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_in( continue; hw_intf = tfe_hw_mgr->tfe_devices[ - csid_res->hw_res[i]->hw_intf->hw_idx]; + csid_res->hw_res[i]->hw_intf->hw_idx]->hw_intf; /* fill in more acquire information as needed */ /* slave Camif resource, */ @@ -2782,10 +2782,10 @@ static int cam_tfe_mgr_reset_tfe_hw(struct cam_tfe_hw_mgr *hw_mgr, if (!hw_mgr->tfe_devices[i]) continue; - if (hw_idx != hw_mgr->tfe_devices[i]->hw_idx) + if (hw_idx != hw_mgr->tfe_devices[i]->hw_intf->hw_idx) continue; CAM_DBG(CAM_ISP, "TFE (id = %d) reset", hw_idx); - tfe_hw_intf = hw_mgr->tfe_devices[i]; + tfe_hw_intf = hw_mgr->tfe_devices[i]->hw_intf; tfe_hw_intf->hw_ops.reset(tfe_hw_intf->hw_priv, &tfe_reset_type, sizeof(tfe_reset_type)); break; @@ -3089,7 +3089,7 @@ static int cam_tfe_mgr_user_dump_hw( rc = cam_tfe_mgr_handle_reg_dump(tfe_ctx, tfe_ctx->reg_dump_buf_desc, tfe_ctx->num_reg_dump_buf, - CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR, + CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR, &soc_dump_args, true); if (rc) { @@ -4294,77 +4294,250 @@ static int cam_tfe_mgr_sof_irq_debug( return rc; } -static void cam_tfe_mgr_print_io_bufs(struct cam_packet *packet, - int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, - bool *mem_found) +static void cam_tfe_mgr_print_io_bufs(struct cam_tfe_hw_mgr *hw_mgr, + uint32_t res_id, struct cam_packet *packet, + bool *ctx_found, struct cam_tfe_hw_mgr_ctx *ctx) { - dma_addr_t iova_addr; - size_t src_buf_size; - int i, j; - int rc = 0; - int32_t mmu_hdl; struct cam_buf_io_cfg *io_cfg = NULL; + int32_t mmu_hdl, iommu_hdl, sec_mmu_hdl; + dma_addr_t iova_addr; + size_t src_buf_size; + int i, j, rc = 0; - if (mem_found) - *mem_found = false; + iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl; + sec_mmu_hdl = hw_mgr->mgr_common.img_iommu_hdl_secure; io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + packet->io_configs_offset / 4); for (i = 0; i < packet->num_io_configs; i++) { - for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { - if (!io_cfg[i].mem_handle[j]) - break; + if (io_cfg[i].resource_type != res_id) + continue; + else + break; + } - 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", - io_cfg[i].resource_type, - io_cfg[i].mem_handle[j], - pf_buf_info); - if (mem_found) - *mem_found = true; - } + if (i == packet->num_io_configs) { + CAM_ERR(CAM_ISP, + "getting io port for mid resource id failed ctx id:%d req id:%lld res id:0x%x", + ctx->ctx_index, packet->header.request_id, + res_id); + return; + } - CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d", - io_cfg[i].resource_type, - io_cfg[i].fence, - io_cfg[i].format, - io_cfg[i].direction); + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; - mmu_hdl = cam_mem_is_secure_buf( - io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : - iommu_hdl; - rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], - mmu_hdl, &iova_addr, &src_buf_size); - if (rc < 0) { - CAM_ERR(CAM_ISP, - "get src buf address fail mem_handle 0x%x", - io_cfg[i].mem_handle[j]); - continue; - } - if ((iova_addr & 0xFFFFFFFF) != iova_addr) { - CAM_ERR(CAM_ISP, "Invalid mapped address"); - rc = -EINVAL; - continue; - } + CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); - CAM_INFO(CAM_ISP, - "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 + - (unsigned int)src_buf_size, - io_cfg[i].offsets[j], + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "get src buf address fail mem_handle 0x%x", io_cfg[i].mem_handle[j]); + continue; + } + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { + CAM_ERR(CAM_ISP, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_ISP, + "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 + + (unsigned int)src_buf_size, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + } +} + +static void cam_tfe_mgr_pf_dump(uint32_t res_id, + struct cam_tfe_hw_mgr_ctx *ctx) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_get_cmd_update cmd_update; + uint32_t res_id_out; + int i, rc = 0; + + /* dump the registers */ + rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc, + ctx->num_reg_dump_buf, + CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR, NULL, false); + if (rc) { + CAM_ERR(CAM_ISP, + "Reg dump on pf failed req id: %llu rc: %d", + ctx->applied_req_id, rc); + } + + /* dump the acquire data */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, 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) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_TFE_CSID_LOG_ACQUIRE_DATA, + hw_mgr_res->hw_res[i], + sizeof(void *)); + if (rc) + CAM_ERR(CAM_ISP, + "acquire dump data failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); } } + + res_id_out = res_id & 0xFF; + + if (res_id_out >= CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid out resource id :%x", + res_id); + return; + } + + hw_mgr_res = + &ctx->res_list_tfe_out[res_id_out]; + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + cmd_update.cmd_type = CAM_ISP_HW_CMD_DUMP_BUS_INFO; + cmd_update.res = hw_mgr_res->hw_res[i]; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)&cmd_update, + sizeof(struct cam_isp_hw_get_cmd_update)); + } + } +} + +static void cam_tfe_mgr_dump_pf_data( + struct cam_tfe_hw_mgr *hw_mgr, + struct cam_hw_cmd_args *hw_cmd_args) +{ + struct cam_tfe_hw_mgr_ctx *ctx; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_get_cmd_update cmd_update; + struct cam_isp_hw_get_res_for_mid get_res; + struct cam_packet *packet; + uint32_t *resource_type; + uint32_t hw_id; + bool *ctx_found, hw_id_found = false; + int i, j, rc = 0; + + ctx = (struct cam_tfe_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map; + + packet = hw_cmd_args->u.pf_args.pf_data.packet; + ctx_found = hw_cmd_args->u.pf_args.ctx_found; + resource_type = hw_cmd_args->u.pf_args.resource_type; + + if ((*ctx_found) && (*resource_type)) + goto outportlog; + + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { + if (!g_tfe_hw_mgr.tfe_devices[i]) + continue; + + for (j = 0; j < g_tfe_hw_mgr.tfe_devices[i]->num_hw_pid; j++) { + if (g_tfe_hw_mgr.tfe_devices[i]->hw_pid[j] == + hw_cmd_args->u.pf_args.pid) { + hw_id_found = true; + hw_id = i; + break; + } + } + if (hw_id_found) + break; + } + + if (i == CAM_TFE_HW_NUM_MAX) { + CAM_INFO(CAM_ISP, + "PID:%d is not matching with any TFE HW PIDs ctx id:%d", + hw_cmd_args->u.pf_args.pid, ctx->ctx_index); + return; + } + + for (i = 0; i < ctx->num_base; i++) { + if (ctx->base[i].idx == hw_id) { + *ctx_found = true; + break; + } + } + + if (!(*ctx_found)) { + CAM_INFO(CAM_ISP, + "This context does not cause pf:pid:%d hw id:%d ctx_id:%d", + hw_cmd_args->u.pf_args.pid, hw_id, ctx->ctx_index); + return; + } + + for (i = 0; i < CAM_TFE_HW_OUT_RES_MAX; i++) { + hw_mgr_res = &ctx->res_list_tfe_out[i]; + if (!hw_mgr_res->hw_res[0]) + continue; + + break; + } + + if (i >= CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, + "NO valid outport resources ctx id:%d req id:%lld", + ctx->ctx_index, packet->header.request_id); + return; + } + + get_res.mid = hw_cmd_args->u.pf_args.mid; + cmd_update.res = hw_mgr_res->hw_res[0]; + cmd_update.cmd_type = CAM_ISP_HW_CMD_GET_RES_FOR_MID; + cmd_update.data = (void *) &get_res; + + /* get resource id for given mid */ + rc = hw_mgr_res->hw_res[0]->hw_intf->hw_ops.process_cmd( + hw_mgr_res->hw_res[0]->hw_intf->hw_priv, + cmd_update.cmd_type, &cmd_update, + sizeof(struct cam_isp_hw_get_cmd_update)); + + if (rc) { + CAM_ERR(CAM_ISP, + "getting mid port resource id failed ctx id:%d req id:%lld", + ctx->ctx_index, packet->header.request_id); + return; + } + CAM_ERR(CAM_ISP, + "Page fault on resource id:0x%x ctx id:%d req id:%lld", + get_res.out_res_id, ctx->ctx_index, packet->header.request_id); + *resource_type = get_res.out_res_id; + + cam_tfe_mgr_pf_dump(get_res.out_res_id, ctx); + +outportlog: + cam_tfe_mgr_print_io_bufs(hw_mgr, *resource_type, packet, + ctx_found, ctx); + + } static void cam_tfe_mgr_ctx_irq_dump(struct cam_tfe_hw_mgr_ctx *ctx) @@ -4463,12 +4636,7 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) } break; case CAM_HW_MGR_CMD_DUMP_PF_INFO: - cam_tfe_mgr_print_io_bufs( - hw_cmd_args->u.pf_args.pf_data.packet, - hw_mgr->mgr_common.img_iommu_hdl, - hw_mgr->mgr_common.img_iommu_hdl_secure, - hw_cmd_args->u.pf_args.buf_info, - hw_cmd_args->u.pf_args.mem_found); + cam_tfe_mgr_dump_pf_data(hw_mgr, hw_cmd_args); break; case CAM_HW_MGR_CMD_REG_DUMP_ON_FLUSH: if (ctx->last_dump_flush_req_id == ctx->applied_req_id) @@ -5277,9 +5445,10 @@ static int cam_tfe_hw_mgr_sort_dev_with_caps( for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { if (!tfe_hw_mgr->tfe_devices[i]) continue; - if (tfe_hw_mgr->tfe_devices[i]->hw_ops.get_hw_caps) { - tfe_hw_mgr->tfe_devices[i]->hw_ops.get_hw_caps( - tfe_hw_mgr->tfe_devices[i]->hw_priv, + + if (tfe_hw_mgr->tfe_devices[i]->hw_intf->hw_ops.get_hw_caps) { + tfe_hw_mgr->tfe_devices[i]->hw_intf->hw_ops.get_hw_caps( + tfe_hw_mgr->tfe_devices[i]->hw_intf->hw_priv, &tfe_hw_mgr->tfe_dev_caps[i], sizeof(tfe_hw_mgr->tfe_dev_caps[i])); } @@ -5406,7 +5575,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) rc = cam_tfe_hw_init(&g_tfe_hw_mgr.tfe_devices[i], i); if (!rc) { struct cam_hw_info *tfe_hw = (struct cam_hw_info *) - g_tfe_hw_mgr.tfe_devices[i]->hw_priv; + g_tfe_hw_mgr.tfe_devices[i]->hw_intf->hw_priv; struct cam_hw_soc_info *soc_info = &tfe_hw->soc_info; j++; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 971863d5b5b6..b074ab1b4bb5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -152,7 +152,7 @@ struct cam_tfe_hw_mgr { struct cam_isp_hw_mgr mgr_common; struct cam_hw_intf *tpg_devices[CAM_TOP_TPG_HW_NUM_MAX]; struct cam_hw_intf *csid_devices[CAM_TFE_CSID_HW_NUM_MAX]; - struct cam_hw_intf *tfe_devices[CAM_TFE_HW_NUM_MAX]; + struct cam_isp_hw_intf_data *tfe_devices[CAM_TFE_HW_NUM_MAX]; struct cam_soc_reg_map *cdm_reg_map[CAM_TFE_HW_NUM_MAX]; struct mutex ctx_mutex; atomic_t active_ctx_cnt; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h index f93c606392cb..37094775db62 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h @@ -179,6 +179,7 @@ enum cam_tfe_csid_cmd_type { CAM_TFE_CSID_SET_CSID_DEBUG, CAM_TFE_CSID_SOF_IRQ_DEBUG, CAM_TFE_CSID_CMD_GET_REG_DUMP, + CAM_TFE_CSID_LOG_ACQUIRE_DATA, CAM_TFE_CSID_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h index cdbae72678d5..4b9dce38ca9a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h @@ -248,6 +248,6 @@ struct cam_tfe_irq_evt_payload { * successful initialization * @hw_idx: Index of TFE HW */ -int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx); +int cam_tfe_hw_init(struct cam_isp_hw_intf_data **tfe_hw, uint32_t hw_idx); #endif /* _CAM_TFE_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 0958b9790068..931a54b61ec4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -2530,6 +2530,53 @@ dump_bw: return 0; } +static int cam_tfe_csid_log_acquire_data( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_isp_resource_node *res = + (struct cam_isp_resource_node *)cmd_args; + struct cam_tfe_csid_path_cfg *path_data; + struct cam_hw_soc_info *soc_info; + const struct cam_tfe_csid_reg_offset *csid_reg; + uint32_t byte_cnt_ping, byte_cnt_pong; + + path_data = (struct cam_tfe_csid_path_cfg *)res->res_priv; + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_ISP, + "CSID:%d invalid res id:%d res type: %d state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_type, + res->res_state); + return -EINVAL; + } + + /* Dump all the acquire data for this */ + CAM_INFO(CAM_ISP, + "CSID:%d res id:%d type:%d state:%d in f:%d out f:%d st pix:%d end pix:%d st line:%d end line:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_type, + res->res_type, path_data->in_format, path_data->out_format, + path_data->start_pixel, path_data->end_pixel, + path_data->start_line, path_data->end_line); + + if (res->res_id >= CAM_TFE_CSID_PATH_RES_RDI_0 && + res->res_id <= CAM_TFE_CSID_PATH_RES_RDI_2) { + /* read total number of bytes transmitted through RDI */ + byte_cnt_ping = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[res->res_id]->csid_rdi_byte_cntr_ping_addr); + byte_cnt_pong = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[res->res_id]->csid_rdi_byte_cntr_pong_addr); + CAM_INFO(CAM_ISP, + "CSID:%d res id:%d byte cnt val ping:%d pong:%d", + csid_hw->hw_intf->hw_idx, res->res_id, + byte_cnt_ping, byte_cnt_pong); + } + + return 0; + +} + static int cam_tfe_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -2567,6 +2614,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE: rc = cam_tfe_csid_halt(csid_hw, cmd_args); break; + case CAM_TFE_CSID_LOG_ACQUIRE_DATA: + rc = cam_tfe_csid_log_acquire_data(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index 6be379a393ac..ae0be9d2c9e9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -740,6 +740,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_5, .rup_group_id = CAM_TFE_BUS_RUP_GRP_1, + .mid = 23, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI1, @@ -747,6 +748,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_6, .rup_group_id = CAM_TFE_BUS_RUP_GRP_2, + .mid = 24, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI2, @@ -754,6 +756,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_7, .rup_group_id = CAM_TFE_BUS_RUP_GRP_3, + .mid = 25, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_FULL, @@ -761,6 +764,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = 4096, .composite_group = CAM_TFE_BUS_COMP_GRP_0, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 16, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_RAW_DUMP, @@ -768,6 +772,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = 4096, .composite_group = CAM_TFE_BUS_COMP_GRP_1, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 17, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_PDAF, @@ -775,6 +780,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = 4096, .composite_group = CAM_TFE_BUS_COMP_GRP_7, .rup_group_id = CAM_TFE_BUS_RUP_GRP_3, + .mid = 25, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE, @@ -782,6 +788,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_3, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 21, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST, @@ -789,6 +796,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_2, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 19, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_TL_BG, @@ -796,6 +804,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_2, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 18, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG, @@ -803,6 +812,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_3, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 20, }, { .tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_BF, @@ -810,6 +820,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .max_height = -1, .composite_group = CAM_TFE_BUS_COMP_GRP_4, .rup_group_id = CAM_TFE_BUS_RUP_GRP_0, + .mid = 22, }, }, .comp_done_shift = 8, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 7d207060d39e..cdc009429bc5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -145,6 +145,7 @@ struct cam_tfe_bus_tfe_out_data { uint32_t secure_mode; void *priv; cam_hw_mgr_event_cb_func event_cb; + uint32_t mid; }; struct cam_tfe_bus_priv { @@ -1544,6 +1545,7 @@ static int cam_tfe_bus_init_tfe_out_resource(uint32_t index, rsrc_data->max_height = hw_info->tfe_out_hw_info[index].max_height; rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + rsrc_data->mid = hw_info->tfe_out_hw_info[index].mid; tfe_out->hw_intf = bus_priv->common_data.hw_intf; @@ -2099,6 +2101,113 @@ static int cam_tfe_bus_update_stripe_cfg(void *priv, void *cmd_args, return 0; } +static int cam_tfe_bus_get_res_id_for_mid( + struct cam_tfe_bus_priv *bus_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_isp_hw_get_cmd_update *cmd_update = + (struct cam_isp_hw_get_cmd_update *)cmd_args; + struct cam_isp_hw_get_res_for_mid *get_res = NULL; + int i; + + get_res = (struct cam_isp_hw_get_res_for_mid *)cmd_update->data; + if (!get_res) { + CAM_ERR(CAM_ISP, + "invalid get resource for mid paramas"); + return -EINVAL; + } + + for (i = 0; i < bus_priv->num_out; i++) { + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) + bus_priv->tfe_out[i].res_priv; + + if (!tfe_out_data) + continue; + + if (tfe_out_data->mid == get_res->mid) + goto end; + } + + if (i == bus_priv->num_out) { + CAM_ERR(CAM_ISP, + "mid:%d does not match with any out resource", + get_res->mid); + get_res->out_res_id = 0; + return -EINVAL; + } + +end: + CAM_INFO(CAM_ISP, "match mid :%d out resource:%d found", + get_res->mid, bus_priv->tfe_out[i].res_id); + get_res->out_res_id = bus_priv->tfe_out[i].res_id; + return 0; +} + +static int cam_tfe_bus_dump_bus_info( + struct cam_tfe_bus_priv *bus_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_isp_hw_get_cmd_update *cmd_update = + (struct cam_isp_hw_get_cmd_update *)cmd_args; + struct cam_tfe_bus_wm_resource_data *wm_data; + struct cam_tfe_bus_common_data *common_data; + uint32_t i, addr_status0, addr_status1, addr_status2, addr_status3; + + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) + cmd_update->res->res_priv; + common_data = tfe_out_data->common_data; + + for (i = 0; i < tfe_out_data->num_wm; i++) { + wm_data = tfe_out_data->wm_res[i]->res_priv; + addr_status0 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_0); + addr_status1 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_1); + addr_status2 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_2); + addr_status3 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->addr_status_3); + CAM_INFO(CAM_ISP, + "TFE:%d WM:%d %s last consumed addr:0x%x last frame addr:0x%x fifo cnt:0x%x cur clt addr:0x%x", + common_data->hw_intf->hw_idx, + wm_data->index, + wm_data->hw_regs->client_name, + addr_status0, + addr_status1, + addr_status2, + addr_status3); + + CAM_INFO(CAM_ISP, + "WM:%d %s width0x%x height:0x%x format:%d stride:0x%x offset:0x%x encfg:%x", + wm_data->index, + wm_data->hw_regs->client_name, + wm_data->acquired_width, + wm_data->acquired_height, + wm_data->format, + wm_data->acquired_stride, + wm_data->offset, + wm_data->en_cfg); + + CAM_INFO(CAM_ISP, + "WM:%d current width:0x%x height:0x%x stride:0x%x", + wm_data->index, + wm_data->width, + wm_data->height, + wm_data->stride); + } + + for (i = 0; i < CAM_TFE_BUS_MAX_CLIENTS; i++) { + wm_data = bus_priv->bus_client[i].res_priv; + /* disable WM */ + cam_io_w_mb(0, common_data->mem_base + + wm_data->hw_regs->cfg); + + } + return 0; +} + static int cam_tfe_bus_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) { @@ -2198,6 +2307,12 @@ static int cam_tfe_bus_process_cmd(void *priv, *support_consumed_addr = bus_priv->common_data.support_consumed_addr; break; + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + rc = cam_tfe_bus_get_res_id_for_mid(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: + rc = cam_tfe_bus_dump_bus_info(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h index 2b2ca16ab1d5..98c12063c4b1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h @@ -18,6 +18,7 @@ #define CAM_TFE_BUS_CLIENT_NAME_MAX_LENGTH 32 #define CAM_TFE_BUS_1_0 0x1000 +#define CAM_TFE_BUS_MAX_MID_PER_PORT 1 #define CAM_TFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \ @@ -157,6 +158,7 @@ struct cam_tfe_bus_reg_offset_bus_client { * max_height Max height supported by outport * composite_group Out port composite group id * rup_group_id Reg update group of outport id + * mid: ouport mid value */ struct cam_tfe_bus_tfe_out_hw_info { enum cam_tfe_bus_tfe_out_id tfe_out_id; @@ -164,6 +166,7 @@ struct cam_tfe_bus_tfe_out_hw_info { uint32_t max_height; uint32_t composite_group; uint32_t rup_group_id; + uint32_t mid; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 088652dab48b..60b456e44fd3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -2811,6 +2811,8 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: rc = core_info->tfe_bus->hw_ops.process_cmd( core_info->tfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c index 0f8c057b7bb4..3d932262dbbe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c @@ -12,7 +12,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static struct cam_hw_intf *cam_tfe_hw_list[CAM_TFE_HW_NUM_MAX] = {0, 0, 0}; +static struct cam_isp_hw_intf_data cam_tfe_hw_list[CAM_TFE_HW_NUM_MAX]; static char tfe_dev_name[8]; @@ -24,8 +24,10 @@ static int cam_tfe_component_bind(struct device *dev, const struct of_device_id *match_dev = NULL; struct cam_tfe_hw_core_info *core_info = NULL; struct cam_tfe_hw_info *hw_info = NULL; + struct cam_tfe_soc_private *tfe_soc_priv; int rc = 0; struct platform_device *pdev = to_platform_device(dev); + uint32_t i; tfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!tfe_hw_intf) { @@ -108,7 +110,18 @@ static int cam_tfe_component_bind(struct device *dev, init_completion(&tfe_hw->hw_complete); if (tfe_hw_intf->hw_idx < CAM_TFE_HW_NUM_MAX) - cam_tfe_hw_list[tfe_hw_intf->hw_idx] = tfe_hw_intf; + cam_tfe_hw_list[tfe_hw_intf->hw_idx].hw_intf = tfe_hw_intf; + else { + CAM_ERR(CAM_ISP, "HW index:%d is wrong max HW idx:%d", + tfe_hw_intf->hw_idx, CAM_TFE_HW_NUM_MAX); + goto deinit_soc; + } + + tfe_soc_priv = tfe_hw->soc_info.soc_private; + cam_tfe_hw_list[tfe_hw_intf->hw_idx].num_hw_pid = tfe_soc_priv->num_pid; + for (i = 0; i < tfe_soc_priv->num_pid; i++) + cam_tfe_hw_list[tfe_hw_intf->hw_idx].hw_pid[i] = + tfe_soc_priv->pid[i]; cam_tfe_init_hw(tfe_hw, NULL, 0); cam_tfe_deinit_hw(tfe_hw, NULL, 0); @@ -149,7 +162,7 @@ static void cam_tfe_component_unbind(struct device *dev, tfe_hw_intf->hw_type, tfe_hw_intf->hw_idx); if (tfe_hw_intf->hw_idx < CAM_TFE_HW_NUM_MAX) - cam_tfe_hw_list[tfe_hw_intf->hw_idx] = NULL; + cam_tfe_hw_list[tfe_hw_intf->hw_idx].hw_intf = NULL; tfe_hw = tfe_hw_intf->hw_priv; if (!tfe_hw) { @@ -206,15 +219,16 @@ int cam_tfe_remove(struct platform_device *pdev) return 0; } -int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx) +int cam_tfe_hw_init(struct cam_isp_hw_intf_data **tfe_hw_intf, + uint32_t hw_idx) { int rc = 0; - if (cam_tfe_hw_list[hw_idx]) { - *tfe_hw = cam_tfe_hw_list[hw_idx]; + if (cam_tfe_hw_list[hw_idx].hw_intf) { + *tfe_hw_intf = &cam_tfe_hw_list[hw_idx]; rc = 0; } else { - *tfe_hw = NULL; + *tfe_hw_intf = NULL; rc = -ENODEV; } return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c index 6041c5e3f026..a28144a2a51d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c @@ -25,9 +25,9 @@ static bool cam_tfe_cpas_cb(uint32_t client_handle, void *userdata, int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t tfe_irq_handler, void *irq_data) { - int rc = 0; struct cam_tfe_soc_private *soc_private; struct cam_cpas_register_params cpas_register_param; + int rc = 0, i = 0, num_pid = 0; soc_private = kzalloc(sizeof(struct cam_tfe_soc_private), GFP_KERNEL); @@ -43,6 +43,27 @@ int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info, goto free_soc_private; } + /* set some default values */ + soc_private->num_pid = 0; + + num_pid = of_property_count_u32_elems(soc_info->pdev->dev.of_node, + "cam_hw_pid"); + CAM_DBG(CAM_CPAS, "tfe:%d pid count %d", soc_info->index, num_pid); + + if (num_pid <= 0 || num_pid > CAM_ISP_HW_MAX_PID_VAL) + goto clk_option; + + for (i = 0; i < num_pid; i++) { + of_property_read_u32_index(soc_info->pdev->dev.of_node, + "cam_hw_pid", i, &soc_private->pid[i]); + CAM_INFO(CAM_CPAS, "tfe:%d I:%d pid %d", soc_info->index, + i, soc_private->pid[i]); + } + + soc_private->num_pid = num_pid; + +clk_option: + rc = cam_soc_util_get_option_clk_by_name(soc_info, CAM_TFE_DSP_CLK_NAME, &soc_private->dsp_clk, &soc_private->dsp_clk_index, &soc_private->dsp_clk_rate); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h index 6e08a98fbbfa..5cb137142b5b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h @@ -26,6 +26,8 @@ enum cam_cpas_handle_id { * This handle is used for all further interface * with CPAS. * @cpas_version: Has cpas version read from Hardware + * @num_pid: number of pids of tfe + * @pid: TFE pid value list */ struct cam_tfe_soc_private { uint32_t cpas_handle; @@ -33,6 +35,8 @@ struct cam_tfe_soc_private { struct clk *dsp_clk; int32_t dsp_clk_index; int32_t dsp_clk_rate; + uint32_t num_pid; + uint32_t pid[CAM_ISP_HW_MAX_PID_VAL]; }; /* From 0f9ba5f0cc8869e10cac54fce68c617344c32125 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Wed, 16 Sep 2020 21:11:23 +0800 Subject: [PATCH 517/790] msm: camera: isp: Fix some stability issues This change updates the order of error notification, in case the UMD already receive the error notification and power down the isp, then the following register dump may meet problem. This change also add lock protection for csid cmd processing, in case the csid has released before processing the cmd. CRs-Fixed: 2783264 Change-Id: I7399d819d1cdadb96b6824cdb4b53aa0167e527b Signed-off-by: Depeng Shao --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 4 ++++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 16 ++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index a99d3f902e24..d4821d9f7420 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4208,6 +4208,8 @@ static int cam_ife_csid_process_cmd(void *hw_priv, csid_hw_info = (struct cam_hw_info *)hw_priv; csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; + mutex_lock(&csid_hw->hw_info->hw_mutex); + switch (cmd_type) { case CAM_IFE_CSID_CMD_GET_TIME_STAMP: rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args); @@ -4251,6 +4253,8 @@ static int cam_ife_csid_process_cmd(void *hw_priv, break; } + mutex_unlock(&csid_hw->hw_info->hw_mutex); + return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 2cc592014e46..73b0114ba57f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1482,10 +1482,6 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, "current monotonic time stamp seconds %lld:%lld", ts.tv_sec, ts.tv_nsec/1000); - if (camif_priv->event_cb) - camif_priv->event_cb(camif_priv->priv, - CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); - ret = CAM_VFE_IRQ_STATUS_OVERFLOW; CAM_INFO(CAM_ISP, "ife_clk_src:%lld", @@ -1495,6 +1491,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_ver3_reg_dump(camif_node); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); } if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] @@ -1514,10 +1514,6 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, "current monotonic time stamp seconds %lld:%lld", ts.tv_sec, ts.tv_nsec/1000); - if (camif_priv->event_cb) - camif_priv->event_cb(camif_priv->priv, - CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); - ret = CAM_VFE_IRQ_STATUS_VIOLATION; CAM_INFO(CAM_ISP, "ife_clk_src:%lld", @@ -1527,6 +1523,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) cam_vfe_camif_ver3_reg_dump(camif_node); + + if (camif_priv->event_cb) + camif_priv->event_cb(camif_priv->priv, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); } if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { From 25522a65e0cd78b09dc095a8301fe1b8374fbdc9 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 11 Aug 2020 09:11:18 -0700 Subject: [PATCH 518/790] msm: camera: csid: Add support for unmapped vc dt detection in csid Add a debugfs support for unmapped vc dt detction. Subscribe to Unmapped vc dt detction in csid. Turn on debugfs with command adb shell "echo 512 >> sys/kernel/debug/camera_ife/ife_csid_debug". CRs-Fixed: 2709537 Change-Id: Ica2030f5914bfe86811f4f3c4501fa06dd310751 Signed-off-by: Jigar Agrawal --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 74 ++++++++++++++++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 1 + 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index a99d3f902e24..c56e5f10f216 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2085,6 +2085,7 @@ static int cam_ife_csid_enable_pxl_path( bool is_ipp; uint32_t val = 0; struct cam_isp_sensor_dimension *path_config; + unsigned int irq_mask_val = 0; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2118,6 +2119,25 @@ static int cam_ife_csid_enable_pxl_path( CAM_DBG(CAM_ISP, "Enable %s path", (is_ipp) ? "IPP" : "PPP"); + if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_UNMAPPED_VC_DT_IRQ) && + (path_data->sync_mode != CAM_ISP_HW_SYNC_SLAVE)) { + irq_mask_val = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + if (!(irq_mask_val & + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT)) { + CAM_DBG(CAM_ISP, + "Subscribing to UNMAPPED_VC_DT event for sync_mode: %d", + path_data->sync_mode); + irq_mask_val |= + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT; + cam_io_w_mb(irq_mask_val, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + } + } + /* Set master or slave path */ if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) { /*Set halt mode as master */ @@ -2756,6 +2776,7 @@ static int cam_ife_csid_enable_rdi_path( { const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + unsigned int irq_mask_val = 0; uint32_t id, val; csid_reg = csid_hw->csid_info->csid_reg; @@ -2772,6 +2793,22 @@ static int cam_ife_csid_enable_rdi_path( return -EINVAL; } + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_UNMAPPED_VC_DT_IRQ) { + irq_mask_val = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + if (!(irq_mask_val & + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT)) { + CAM_DBG(CAM_ISP, "Subscribing to UNMAPPED_VC_DT event"); + irq_mask_val |= + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT; + cam_io_w_mb(irq_mask_val, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + } + } + /*resume at frame boundary */ cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY, soc_info->reg_map[0].mem_base + @@ -2809,6 +2846,7 @@ static int cam_ife_csid_enable_udi_path( { const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + unsigned int irq_mask_val = 0; uint32_t id, val; csid_reg = csid_hw->csid_info->csid_reg; @@ -2826,6 +2864,23 @@ static int cam_ife_csid_enable_udi_path( return -EINVAL; } + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_UNMAPPED_VC_DT_IRQ) { + irq_mask_val = + cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + + if (!(irq_mask_val & + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT)) { + CAM_DBG(CAM_ISP, + "Subscribing to UNMAPPED_VC_DT event"); + irq_mask_val |= + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT; + cam_io_w_mb(irq_mask_val, + soc_info->reg_map[0].mem_base + + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + } + } + /*resume at frame boundary */ cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY, soc_info->reg_map[0].mem_base + @@ -3733,7 +3788,6 @@ int cam_ife_csid_start(void *hw_priv, void *start_args, if (!csid_hw->device_enabled) cam_ife_csid_csi2_irq_ctrl(csid_hw, true); csid_hw->device_enabled = 1; - spin_unlock_irqrestore(&csid_hw->lock_state, flags); CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d", csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); @@ -3759,7 +3813,7 @@ int cam_ife_csid_start(void *hw_priv, void *start_args, } else { CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id); rc = -EINVAL; - goto end; + goto irq_restore; } break; @@ -3769,6 +3823,8 @@ int cam_ife_csid_start(void *hw_priv, void *start_args, res->res_type); break; } +irq_restore: + spin_unlock_irqrestore(&csid_hw->lock_state, flags); end: return rc; } @@ -4656,6 +4712,20 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT", csid_hw->hw_intf->hw_idx); } + if ((irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT) && + (csid_hw->csid_debug & + CSID_DEBUG_ENABLE_UNMAPPED_VC_DT_IRQ)) { + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); + + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d UNMAPPED_VC_DT. VC: %d DT: %d WC: %d", + csid_hw->hw_intf->hw_idx, (val >> 22), + ((val >> 16) & 0x3F), (val & 0xFFFF)); + csid_hw->error_irq_count++; + } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) { CAM_ERR_RATE_LIMIT(CAM_ISP, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index b3500a1fb10e..efd5b0a47591 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -71,6 +71,7 @@ #define CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6) #define CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7) #define CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) +#define CSID_DEBUG_ENABLE_UNMAPPED_VC_DT_IRQ BIT(9) #define CAM_CSID_EVT_PAYLOAD_MAX 10 #define CAM_CSID_MIN_HBI_CFG_MAX_VAL 0xF From 033864b04f4baf6eec4f1e1b3e87da024f55e9e8 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Thu, 17 Sep 2020 16:38:35 -0700 Subject: [PATCH 519/790] msm: camera: icp: Fix potential deadlock scenario in cam_hfi_init Make sure we perform the necessary unlock operations before we return on an invalid HFI state. CRs-Fixed: 2783934 Change-Id: I7c611fb98d245952f2f4e9a57dc5fcb249572a40 Signed-off-by: Fernando Pacheco --- drivers/cam_icp/hfi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 2cc4e53b523f..9b9ea4bfc723 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -647,7 +647,8 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, if (g_hfi->hfi_state != HFI_DEINIT) { CAM_ERR(CAM_HFI, "hfi_init: invalid state"); - return -EINVAL; + rc = -EINVAL; + goto regions_fail; } memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map)); From 02f65e4927a1ca9e3d463b46b7e8c8e547f677d7 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Tue, 22 Sep 2020 13:24:35 +0530 Subject: [PATCH 520/790] msm: camera: tfe: Add support last consumed address for tfe Tfe hardware support the last consumed buf address. Request port buf done verified with last consumed buffer Address. Buf done irq delays can be handled through last consumed address verification. CRs-Fixed: 2784348 Change-Id: I4d629da44cf6f1b7755c7785eac11f72384c78c7 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/cam_isp_context.c | 3 ++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 40 ++++++------------- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 2 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 1 + 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 1b966b1f2831..b967dad7c9f6 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4534,6 +4534,9 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, goto free_res; } + ctx_isp->support_consumed_addr = + param.support_consumed_addr; + /* 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; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index e3618e858d0e..e779dca55779 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1775,32 +1775,6 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, } } -static bool cam_tfe_mgr_is_consumed_addr_supported( - struct cam_tfe_hw_mgr_ctx *ctx) -{ - bool support_consumed_addr = false; - struct cam_isp_hw_mgr_res *isp_hw_res = NULL; - struct cam_hw_intf *hw_intf = NULL; - - isp_hw_res = &ctx->res_list_tfe_out[0]; - - if (!isp_hw_res || !isp_hw_res->hw_res[0]) { - CAM_ERR(CAM_ISP, "Invalid ife out res."); - goto end; - } - - hw_intf = isp_hw_res->hw_res[0]->hw_intf; - if (hw_intf && hw_intf->hw_ops.process_cmd) { - hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, - CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, - &support_consumed_addr, - sizeof(support_consumed_addr)); - } - -end: - return support_consumed_addr; -} - /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -2011,7 +1985,7 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->num_reg_dump_buf = 0; acquire_args->support_consumed_addr = - cam_tfe_mgr_is_consumed_addr_supported(tfe_ctx); + g_tfe_hw_mgr.support_consumed_addr; cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx); @@ -5359,6 +5333,7 @@ static int cam_tfe_hw_mgr_handle_hw_buf_done( buf_done_event_data.num_handles = 1; buf_done_event_data.resource_handle[0] = event_info->res_id; + buf_done_event_data.last_consumed_addr[0] = event_info->reg_val; if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) return 0; @@ -5558,6 +5533,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) struct cam_iommu_handle cdm_handles; struct cam_tfe_hw_mgr_ctx *ctx_pool; struct cam_isp_hw_mgr_res *res_list_tfe_out; + bool support_consumed_addr = false; CAM_DBG(CAM_ISP, "Enter"); @@ -5574,10 +5550,19 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) for (i = 0, j = 0; i < CAM_TFE_HW_NUM_MAX; i++) { rc = cam_tfe_hw_init(&g_tfe_hw_mgr.tfe_devices[i], i); if (!rc) { + struct cam_hw_intf *tfe_device = + g_tfe_hw_mgr.tfe_devices[i]->hw_intf; struct cam_hw_info *tfe_hw = (struct cam_hw_info *) g_tfe_hw_mgr.tfe_devices[i]->hw_intf->hw_priv; struct cam_hw_soc_info *soc_info = &tfe_hw->soc_info; + if (j == 0) + tfe_device->hw_ops.process_cmd( + tfe_hw, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + &support_consumed_addr, + sizeof(support_consumed_addr)); + j++; g_tfe_hw_mgr.cdm_reg_map[i] = &soc_info->reg_map[0]; @@ -5594,6 +5579,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return -EINVAL; } + g_tfe_hw_mgr.support_consumed_addr = support_consumed_addr; /* fill csid hw intf information */ for (i = 0, j = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { rc = cam_tfe_csid_hw_init(&g_tfe_hw_mgr.csid_devices[i], i); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index b074ab1b4bb5..b51d0673630e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -147,6 +147,7 @@ struct cam_tfe_hw_mgr_ctx { * @tfe_dev_caps tfe device capability per core * @work q work queue for TFE hw manager * @debug_cfg debug configuration + * @support_consumed_addr indicate whether hw supports last consumed address */ struct cam_tfe_hw_mgr { struct cam_isp_hw_mgr mgr_common; @@ -165,6 +166,7 @@ struct cam_tfe_hw_mgr { struct cam_tfe_hw_get_hw_cap tfe_dev_caps[CAM_TFE_HW_NUM_MAX]; struct cam_req_mgr_core_workq *workq; struct cam_tfe_hw_mgr_debug debug_cfg; + bool support_consumed_addr; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index cdc009429bc5..033450f86a5b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -1947,6 +1947,7 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, update_buf->wm_update->image_buf[i]); CAM_DBG(CAM_ISP, "WM %d image address 0x%x", wm_data->index, reg_val_pair[j-1]); + update_buf->wm_update->image_buf_offset[i] = 0; CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->frame_incr, frame_inc); From c2ef7b6bfb13ad47f033c9c4ee7c7a5f9a635929 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 24 Sep 2020 17:34:11 +0530 Subject: [PATCH 521/790] msm: camera: isp: Add Phy source for CPHY TPG Add Phy selection logic if PHY TPG is enabled. Add phy resource in case of external TPG. CRs-Fixed: 2787956 Change-Id: Ib9d827dc411965d8dd849de53932c62c9b4a4a02 Signed-off-by: Chandan Kumar Jha --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 16 ++++++++++++++++ .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 14 ++++++++++++++ .../isp_hw/include/cam_ife_csid_hw_intf.h | 2 ++ .../isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 6450b5d37ea9..af0014d56a74 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1667,6 +1667,13 @@ static int cam_ife_mgr_acquire_cid_res( if (in_port->num_out_res) out_port = &(in_port->data[0]); + if (ife_ctx->is_tpg) { + if (ife_ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx == 0) + csid_acquire.phy_sel = CAM_ISP_IFE_IN_RES_PHY_0; + else + csid_acquire.phy_sel = CAM_ISP_IFE_IN_RES_PHY_1; + } + /* Try acquiring CID resource from previously acquired HW */ list_for_each_entry(cid_res_iterator, &ife_ctx->res_list_ife_cid, list) { @@ -1766,6 +1773,15 @@ acquire_successful: csid_acquire.node_res = NULL; csid_acquire.res_type = CAM_ISP_RESOURCE_CID; csid_acquire.in_port = in_port; + + if (ife_ctx->is_tpg) { + if (ife_ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx + == 0) + csid_acquire.phy_sel = CAM_ISP_IFE_IN_RES_PHY_0; + else + csid_acquire.phy_sel = CAM_ISP_IFE_IN_RES_PHY_1; + } + for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) { if (!ife_hw_mgr->csid_devices[j]) continue; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index a99d3f902e24..dcc42185c6c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -689,6 +689,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, struct cam_ife_csid_cid_data *cid_data; uint32_t camera_hw_version; uint32_t valid_vc_dt; + uint32_t res_type; CAM_DBG(CAM_ISP, "CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d", @@ -953,6 +954,19 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->csi2_rx_cfg.lane_num = cid_reserv->in_port->lane_num; + res_type = cid_reserv->in_port->res_type; + if ((res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || + (res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || + (res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) { + csid_hw->csi2_rx_cfg.phy_sel = + (cid_reserv->phy_sel & 0xFF) - 1; + csid_hw->csi2_reserve_cnt++; + CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired", + csid_hw->hw_intf->hw_idx, + cid_reserv->node_res->res_id); + goto end; + } + if (cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) { csid_hw->csi2_rx_cfg.phy_sel = (cid_reserv->in_port->res_type & 0xFF) - 1; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index bd866c6202f3..28e0c14b3761 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -127,6 +127,7 @@ struct cam_isp_in_port_generic_info { * @drop_enable : Flag to indicate CSID drop enable * @priv: private data to be sent in callback * @event_cb: CSID event callback to hw manager + * @phy_sel: Phy selection number if tpg is enabled from userspace * */ struct cam_csid_hw_reserve_resource_args { @@ -142,6 +143,7 @@ struct cam_csid_hw_reserve_resource_args { bool drop_enable; void *priv; cam_hw_mgr_event_cb_func event_cb; + uint32_t phy_sel; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c index 555cebf79f8f..9ba520323b86 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c @@ -173,7 +173,7 @@ static int cam_top_tpg_ver2_start( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_2); /* program number of frames */ - cam_io_w_mb(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_3); + cam_io_w_mb(0xFFFFF, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_3); cam_io_w_mb(tpg_reg->tpg_module_en, soc_info->reg_map[0].mem_base + tpg_reg->tpg_module_cfg); From 1f5f70bfab13dca6f8ed1bc8dab69ee0c8e8155e Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 22 Sep 2020 13:48:15 -0700 Subject: [PATCH 522/790] msm: camera: ife: Remove epd reset operation from csid global reset EPD support is configured as a part of config blob. Currently global reset is invoked after CSID is configured and as a part of that epd support attributre gets reset. This cause CPHY_EOT_RECEPTION error from CSID. This change removes reset part of epd supported attribute to continue with the expected opertion set during configuration of CSID. Also, set this attribute to zero by default at probe time to make sure epd is not supported. CRs-Fixed: 2775508 Change-Id: I0f49f952d2156d92eb0fb1813951a325b63e60b0 Signed-off-by: Jigarkumar Zala --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index a99d3f902e24..65490b4ac4a7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -538,7 +538,6 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) csid_hw->hw_intf->hw_idx, val); csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; - csid_hw->epd_supported = 0; end: return rc; @@ -5241,6 +5240,7 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->error_irq_count = 0; ife_csid_hw->ipp_path_config.measure_enabled = 0; ife_csid_hw->ppp_path_config.measure_enabled = 0; + ife_csid_hw->epd_supported = 0; for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) ife_csid_hw->rdi_path_config[i].measure_enabled = 0; From 58dd3620571a7d1ef6a3cf1aa93d527277cebc0f Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Thu, 24 Sep 2020 09:45:31 -0700 Subject: [PATCH 523/790] Revert "msm: camera: cci: Add CCI Global reset during CCI HW init" This reverts commit 9703cf925e04cf01257a50a6bdc14ad8d2e82887. CRs-Fixed: 2784358 Change-Id: I1f192623104683e3f82c004f6d96a84d155e2455 Signed-off-by: Anil Kumar Kanakanti --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 2 +- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 1 + .../cam_sensor_module/cam_cci/cam_cci_soc.c | 213 +++++++++--------- 3 files changed, 108 insertions(+), 108 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 4f309d4eab6b..0d1b90932eeb 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1171,7 +1171,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); CAM_ERR(CAM_CCI, - "wait timeout for RD_DONE irq for cci: %d, master: %d, FIFO buf_lvl:0x%x, rc: %d", + "wait timeout for RD_DONE irq for cci: %d, master: %d, rc = %d FIFO buf_lvl:0x%x, rc: %d", cci_dev->soc_info.index, master, val, rc); cam_cci_dump_registers(cci_dev, diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 3688b9cba906..7f464b6f24d2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -135,6 +135,7 @@ struct cam_cci_master_info { struct semaphore master_sem; bool is_first_req; uint16_t freq_ref_cnt; + bool is_initilized; }; struct cam_cci_clk_params_t { diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 2f9d807e2d2a..302983958780 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -13,7 +13,6 @@ static int cam_cci_init_master(struct cci_device *cci_dev, void __iomem *base = NULL; struct cam_hw_soc_info *soc_info = NULL; uint32_t max_queue_0_size = 0, max_queue_1_size = 0; - struct cam_cci_master_info *cci_master; soc_info = &cci_dev->soc_info; base = soc_info->reg_map[0].mem_base; @@ -26,41 +25,51 @@ static int cam_cci_init_master(struct cci_device *cci_dev, max_queue_1_size = CCI_I2C_QUEUE_1_SIZE; } - cci_master = &cci_dev->cci_master_info[master]; - /* Re-initialize the completion */ - reinit_completion(&cci_master->reset_complete); - reinit_completion(&cci_master->rd_done); + cci_dev->master_active_slave[master]++; + if (!cci_dev->cci_master_info[master].is_initilized) { + /* Re-initialize the completion */ + reinit_completion( + &cci_dev->cci_master_info[master].reset_complete); + reinit_completion(&cci_dev->cci_master_info[master].rd_done); - /* reinit the reports for the queue */ - for (i = 0; i < NUM_QUEUES; i++) - reinit_completion(&cci_master->report_q[i]); + /* reinit the reports for the queue */ + for (i = 0; i < NUM_QUEUES; i++) + reinit_completion( + &cci_dev->cci_master_info[master].report_q[i]); - /* Set reset pending flag to true */ - cci_master->reset_pending = true; - cam_io_w_mb((master == MASTER_0) ? - CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, - base + CCI_RESET_CMD_ADDR); - if (!wait_for_completion_timeout( - &cci_master->reset_complete, CCI_TIMEOUT)) { - CAM_ERR(CAM_CCI, - "Failed: reset complete timeout for master: %d", - master); - rc = -ETIMEDOUT; - return rc; + /* Set reset pending flag to true */ + cci_dev->cci_master_info[master].reset_pending = true; + cam_io_w_mb((master == MASTER_0) ? + CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + if (!wait_for_completion_timeout( + &cci_dev->cci_master_info[master].reset_complete, + CCI_TIMEOUT)) { + CAM_ERR(CAM_CCI, + "Failed: reset complete timeout for master: %d", + master); + rc = -ETIMEDOUT; + cci_dev->master_active_slave[master]--; + return rc; + } + + flush_workqueue(cci_dev->write_wq[master]); + + /* Setting up the queue size for master */ + cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size + = max_queue_0_size; + cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size + = max_queue_1_size; + + CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0: %d Q1: %d", master, + cci_dev->cci_i2c_queue_info[master][QUEUE_0] + .max_queue_size, + cci_dev->cci_i2c_queue_info[master][QUEUE_1] + .max_queue_size); + + cci_dev->cci_master_info[master].status = 0; + cci_dev->cci_master_info[master].is_initilized = true; } - flush_workqueue(cci_dev->write_wq[master]); - - /* Setting up the queue size for master */ - cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size - = max_queue_0_size; - cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size - = max_queue_1_size; - - CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0: %d Q1: %d", master, - cci_dev->cci_i2c_queue_info[master][QUEUE_0].max_queue_size, - cci_dev->cci_i2c_queue_info[master][QUEUE_1].max_queue_size); - - cci_dev->cci_master_info[master].status = 0; return 0; } @@ -108,94 +117,82 @@ int cam_cci_init(struct v4l2_subdev *sd, return rc; } - if (!cci_dev->ref_count) { - ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_LOWSVS_VOTE; - axi_vote.num_paths = 1; - axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; - axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; - axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; - - rc = cam_cpas_start(cci_dev->cpas_handle, &ahb_vote, &axi_vote); - if (rc) { - CAM_ERR(CAM_CCI, "CPAS start failed rc= %d", rc); - return rc; - } - - cam_cci_get_clk_rates(cci_dev, c_ctrl); - - /* Enable Regulators and IRQ*/ - rc = cam_soc_util_enable_platform_resource(soc_info, true, - CAM_LOWSVS_VOTE, true); - if (rc < 0) { - CAM_DBG(CAM_CCI, - "request platform resources failed,rc:%d", rc); - goto platform_enable_failed; - } - - cci_dev->hw_version = cam_io_r_mb(base + CCI_HW_VERSION_ADDR); - CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version); - - cci_dev->payload_size = MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; - cci_dev->support_seq_write = 1; - - for (i = 0; i < MASTER_MAX; i++) - cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; - - reinit_completion( - &cci_dev->cci_master_info[master].reset_complete); - cci_dev->cci_master_info[master].reset_pending = true; - cci_dev->cci_master_info[master].status = 0; - - cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); - - if (!wait_for_completion_timeout( - &cci_dev->cci_master_info[master].reset_complete, - CCI_TIMEOUT)) { - CAM_ERR(CAM_CCI, - "Failed: reset complete timeout for master: %d", - master); - rc = -ETIMEDOUT; - goto platform_enable_failed; - } - - cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_MASK_0_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_CLEAR_0_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_MASK_1_ADDR); - cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_CLEAR_1_ADDR); - cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); - - /* Set RD FIFO threshold for M0 & M1 */ - if (cci_dev->hw_version != CCI_VERSION_1_2_9) { - cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, - base + CCI_I2C_M0_RD_THRESHOLD_ADDR); - cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, - base + CCI_I2C_M1_RD_THRESHOLD_ADDR); - } - cci_dev->cci_state = CCI_STATE_ENABLED; - } - cci_dev->ref_count++; - - if (!cci_dev->master_active_slave[master]) { + if (cci_dev->ref_count++) { rc = cam_cci_init_master(cci_dev, master); if (rc) { CAM_ERR(CAM_CCI, "Failed to init: Master: %d: rc: %d", master, rc); - goto reset_complete_failed; + cci_dev->ref_count--; } CAM_DBG(CAM_CCI, "ref_count %d, master: %d", cci_dev->ref_count, master); + return rc; } - cci_dev->master_active_slave[master]++; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(cci_dev->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_CCI, "CPAS start failed rc= %d", rc); + return rc; + } + + cam_cci_get_clk_rates(cci_dev, c_ctrl); + + /* Enable Regulators and IRQ*/ + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_LOWSVS_VOTE, true); + if (rc < 0) { + CAM_DBG(CAM_CCI, "request platform resources failed, rc: %d", + rc); + goto platform_enable_failed; + } + + cci_dev->hw_version = cam_io_r_mb(base + CCI_HW_VERSION_ADDR); + CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version); + + cci_dev->payload_size = MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11; + cci_dev->support_seq_write = 1; + + rc = cam_cci_init_master(cci_dev, master); + if (rc) { + CAM_ERR(CAM_CCI, "Failed to init: Master: %d, rc: %d", + master, rc); + goto reset_complete_failed; + } + + for (i = 0; i < MASTER_MAX; i++) + cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES; + + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_MASK_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_0_RMSK, base + CCI_IRQ_CLEAR_0_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(CCI_IRQ_MASK_1_RMSK, base + CCI_IRQ_CLEAR_1_ADDR); + cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); + + /* Set RD FIFO threshold for M0 & M1 */ + if (cci_dev->hw_version != CCI_VERSION_1_2_9) { + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M0_RD_THRESHOLD_ADDR); + cam_io_w_mb(CCI_I2C_RD_THRESHOLD_VALUE, + base + CCI_I2C_M1_RD_THRESHOLD_ADDR); + } + + cci_dev->cci_state = CCI_STATE_ENABLED; return 0; reset_complete_failed: cam_soc_util_disable_platform_resource(soc_info, 1, 1); - cci_dev->ref_count--; platform_enable_failed: + cci_dev->ref_count--; cam_cpas_stop(cci_dev->cpas_handle); return rc; @@ -216,6 +213,7 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) for (i = 0; i < MASTER_MAX; i++) { new_cci_dev->cci_master_info[i].status = 0; new_cci_dev->cci_master_info[i].is_first_req = true; + new_cci_dev->cci_master_info[i].is_initilized = false; 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); @@ -406,6 +404,7 @@ int cam_cci_soc_release(struct cci_device *cci_dev, } if (!(--cci_dev->master_active_slave[master])) { + cci_dev->cci_master_info[master].is_initilized = false; CAM_DBG(CAM_CCI, "All submodules are released for master: %d", master); } From 6cd4af283f62ce6cd941642ce97f6d34ae712b89 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Thu, 24 Sep 2020 13:20:05 +0800 Subject: [PATCH 524/790] msm: camera: reqmgr: Reset the number of sync links This change resets the number of sync links in case unsync link fails due to any reason, which will result in device crash, since the number of sync links can be increased to an invalid value, then we will get an invalid link. CRs-Fixed: 2786144 Change-Id: I61bbac9849ce80c319de40ffae411f61c8deeaa9 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index ee3972096998..11b910818708 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -4026,6 +4026,7 @@ int cam_req_mgr_sync_config( link[i]->is_master = false; link[i]->in_msync_mode = false; link[i]->initial_sync_req = -1; + link[i]->num_sync_links = 0; for (j = 0; j < sync_info->num_links-1; j++) link[i]->sync_link[j] = NULL; @@ -4054,7 +4055,6 @@ int cam_req_mgr_sync_config( for (j = 0; j < sync_info->num_links; j++) { link[j]->initial_skip = true; link[j]->sof_timestamp = 0; - link[j]->num_sync_links = 0; } } From 9943af257a1d711264e0777f19f2f464b8b69993 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Thu, 24 Sep 2020 23:59:10 +0530 Subject: [PATCH 525/790] msm: camera: cci: Add CCI Global reset during CCI HW init During first CCI HW initialization, CCI HW global reset has to be called. CRs-Fixed: 2782553 Change-Id: Ifc02f512859932636c79b0bfed1f60e7c0626cee Signed-off-by: Anil Kumar Kanakanti --- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 302983958780..fde91ad13459 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -39,9 +39,16 @@ static int cam_cci_init_master(struct cci_device *cci_dev, /* Set reset pending flag to true */ cci_dev->cci_master_info[master].reset_pending = true; - cam_io_w_mb((master == MASTER_0) ? - CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, - base + CCI_RESET_CMD_ADDR); + cci_dev->cci_master_info[master].status = 0; + if (cci_dev->ref_count == 1) { + cam_io_w_mb(CCI_RESET_CMD_RMSK, + base + CCI_RESET_CMD_ADDR); + cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); + } else { + cam_io_w_mb((master == MASTER_0) ? + CCI_M0_RESET_RMSK : CCI_M1_RESET_RMSK, + base + CCI_RESET_CMD_ADDR); + } if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT)) { From afa957e59e325ce86ef22414a0dcb034c6e3201e Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 21 Sep 2020 14:33:26 -0700 Subject: [PATCH 526/790] msm: camera: isp: Write zero to clear register after global clear command Clear registers hold the programmed values unless explicitly set to zero. This can cause problems in cases where a global clear is issued which encompasses the registers for which clear mask was set in a different instance of IRQ controller. We should not wait for the next IRQ to clear the undesired bits in clear register. This change makes sure that the actions of a particular IRQ controller do not affect the other. Write zeros explicitly to clear registers corresponding to status registers after global clear is issued in IRQ handler. CRs-Fixed: 2775499 Change-Id: Ic57302e5862d9453a94c4e8f470215dacb8978ec Signed-off-by: Mukund Madhusudan Atre --- .../irq_controller/cam_irq_controller.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index 83d4a61a2682..75958d0dff70 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -722,19 +722,28 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv) if (irq_register->top_half_enable_mask[j] & controller->irq_status_arr[i]) need_th_processing[j] = true; - CAM_DBG(CAM_IRQ_CTRL, - "i %d j %d need_th_processing = %d", - i, j, need_th_processing[j]); + + CAM_DBG(CAM_IRQ_CTRL, + "i %d j %d need_th_processing = %d", + i, j, need_th_processing[j]); } } CAM_DBG(CAM_IRQ_CTRL, "Status Registers read Successful"); - if (controller->global_clear_offset) + if (controller->global_clear_offset) { cam_io_w_mb(controller->global_clear_bitmask, controller->mem_base + controller->global_clear_offset); + for (i = 0; i < controller->num_registers; i++) { + irq_register = &controller->irq_register_arr[i]; + if (controller->irq_status_arr[i]) + cam_io_w_mb(0x0, controller->mem_base + + irq_register->clear_reg_offset); + } - CAM_DBG(CAM_IRQ_CTRL, "Status Clear done"); + CAM_DBG(CAM_IRQ_CTRL, "Global Clear done from %s", + controller->name); + } for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++) { if (need_th_processing[i]) { From 345ff8c6334eaf8c00905f5ef6cfeac1feff1290 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 17 Aug 2020 11:35:28 +0530 Subject: [PATCH 527/790] msm: camera: ope: Handle race while dumping ope req list While dumping OPE req list we were not protecting it in context mutex, this can result into unexpected behaviors. This change take care of protecting the dump logic using mutex. CRs-Fixed: 2750458 Change-Id: I916822b498cde3922274c18a06b98c898bff1d65 Signed-off-by: Vikram Sharma --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index db9e760d1e15..1485e3a5eebe 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -43,6 +43,8 @@ static struct cam_ope_hw_mgr *ope_hw_mgr; +static int cam_ope_req_timer_reset(struct cam_ope_ctx *ctx_data); + static int cam_ope_mgr_get_rsc_idx(struct cam_ope_ctx *ctx_data, struct ope_io_buf_info *in_io_buf) { @@ -125,6 +127,8 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) if (task_data->req_id > ctx_data->last_flush_req) ctx_data->last_flush_req = 0; + cam_ope_req_timer_reset(ctx_data); + rc = cam_cdm_submit_bls(ctx_data->ope_cdm.cdm_handle, cdm_cmd); if (!rc) @@ -3639,6 +3643,7 @@ static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) } mutex_lock(&hw_mgr->hw_mgr_mutex); + mutex_lock(&ctx_data->ctx_mutex); CAM_INFO(CAM_OPE, "Req %lld", dump_args->request_id); for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) { @@ -3652,6 +3657,7 @@ static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) /* no matching request found */ if (idx == CAM_CTX_REQ_MAX) { + mutex_unlock(&ctx_data->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); return 0; } @@ -3669,6 +3675,7 @@ static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) req_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC); + mutex_unlock(&ctx_data->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); return 0; } @@ -3680,6 +3687,7 @@ static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args) cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC); + mutex_unlock(&ctx_data->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); return 0; } From 6588824f3482262011ce049d5ea68d2a4a27bcb7 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 28 Sep 2020 11:46:24 -0700 Subject: [PATCH 528/790] msm: camera: csiphy: Update the csiphy programming sequence Update the csiphy 1.2.3 programming sequence. CRs-Fixed: 2787142 Change-Id: Ie859440acb49528fd414df32c66680db93878ad6 Signed-off-by: Jigar Agrawal --- .../cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index e626c13a70f5..8614ed1c8d0e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -23,11 +23,11 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { }; struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { - {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0814, 0xd5, 0x00, CSIPHY_2PH_REGS}, + {0x0814, 0x2A, 0x00, CSIPHY_3PH_REGS}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x5A, 0x00, CSIPHY_2PH_REGS}, + {0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, - {0x081C, 0x5A, 0x00, CSIPHY_3PH_REGS}, {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, @@ -55,8 +55,7 @@ struct csiphy_reg_t csiphy_irq_reg_1_2_3[] = { {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, }; -struct -csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { +struct csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { { {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -253,7 +252,7 @@ struct csiphy_reg_t { {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0628, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, From c37f48cfc5dc57ea1ff6393cfc6a80eb7b3a8ed2 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Mon, 3 Aug 2020 14:53:12 +0530 Subject: [PATCH 529/790] msm: camera: cpas: Add fuse MP limit support If MP limit fuse feature is enabled in DTSI then read the fuse register to get information about maximum allowed resolution. According to that restrict CSID acquire. Also if only DTSI based max_width is enabled then restrict acquire with maximum allowed width. CRs-Fixed: 2785460 Depends-on: 3349044 Change-Id: If861289aebe2921183276780a086dfa1b1d5f372 Signed-off-by: Wyes Karny --- drivers/cam_cpas/cam_cpas_intf.c | 40 +++- drivers/cam_cpas/cam_cpas_soc.c | 188 ++++++++++++------ drivers/cam_cpas/cam_cpas_soc.h | 24 ++- drivers/cam_cpas/include/cam_cpas_api.h | 24 ++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 134 ++++++++++++- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 + .../isp_hw/ife_csid_hw/cam_ife_csid_soc.c | 10 + .../isp_hw/ife_csid_hw/cam_ife_csid_soc.h | 4 + .../cam_csiphy/cam_csiphy_core.c | 10 +- 9 files changed, 362 insertions(+), 76 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index a3ae586186df..f3af861cb614 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -119,28 +119,56 @@ const char *cam_cpas_axi_util_trans_type_to_string( } EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string); -int cam_cpas_is_feature_supported(uint32_t flag) +bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map, + uint32_t *fuse_val) { struct cam_hw_info *cpas_hw = NULL; struct cam_cpas_private_soc *soc_private = NULL; - uint32_t feature_mask; + bool supported = true; + int32_t i; if (!CAM_CPAS_INTF_INITIALIZED()) { CAM_ERR(CAM_CPAS, "cpas intf not initialized"); - return -ENODEV; + return false; } cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv; soc_private = (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private; - feature_mask = soc_private->feature_mask; if (flag >= CAM_CPAS_FUSE_FEATURE_MAX) { CAM_ERR(CAM_CPAS, "Unknown feature flag %x", flag); - return -EINVAL; + return false; } - return feature_mask & flag ? 1 : 0; + for (i = 0; i < soc_private->num_feature_info; i++) + if (soc_private->feature_info[i].feature == flag) + break; + + if (i == soc_private->num_feature_info) { + CAM_INFO(CAM_CPAS, "Feature not found, no of featues: %d", + soc_private->num_feature_info); + goto end; + } + + if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE + || (soc_private->feature_info[i].type == + CAM_CPAS_FEATURE_TYPE_ENABLE)) { + if ((soc_private->feature_info[i].hw_map & hw_map) == hw_map) + supported = soc_private->feature_info[i].enable; + else + supported = !soc_private->feature_info[i].enable; + } else { + if (!fuse_val) { + CAM_ERR(CAM_CPAS, + "Invalid arg fuse_val"); + } else { + *fuse_val = soc_private->feature_info[i].value; + } + } + +end: + return supported; } EXPORT_SYMBOL(cam_cpas_is_feature_supported); diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index b46640850988..5347d02b9197 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -466,87 +466,155 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, return 0; } -int cam_cpas_get_hw_fuse(struct platform_device *pdev, - struct cam_cpas_private_soc *soc_private) -{ - struct device_node *of_node; - void *fuse; - uint32_t fuse_addr, fuse_bit; - uint32_t fuse_val = 0, feature_bit_pos; - int count = 0, i = 0; - memset(&soc_private->fuse_info, 0, sizeof(soc_private->fuse_info)); - - of_node = pdev->dev.of_node; - count = of_property_count_u32_elems(of_node, "cam_hw_fuse"); - if (count <= 0) { - CAM_INFO(CAM_CPAS, "no or invalid fuse enrties %d", count); - return 0; - } else if (count%3 != 0) { - CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 3 %d", - count); - return -EINVAL; - } - - for (i = 0; i < count; i = i + 3) { - of_property_read_u32_index(of_node, "cam_hw_fuse", i, - &feature_bit_pos); - of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1, - &fuse_addr); - of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2, - &fuse_bit); - CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d", - feature_bit_pos, fuse_addr, fuse_bit); - fuse = ioremap(fuse_addr, 4); - if (fuse) { - fuse_val = cam_io_r(fuse); - soc_private->fuse_info.fuse_val[i].fuse_id = fuse_addr; - soc_private->fuse_info.fuse_val[i].fuse_val = fuse_val; - } - CAM_INFO(CAM_CPAS, "fuse_addr 0x%x, fuse_val %x", - fuse_addr, fuse_val); - soc_private->fuse_info.num_fuses++; - iounmap(fuse); - } - - return 0; -} int cam_cpas_get_hw_features(struct platform_device *pdev, struct cam_cpas_private_soc *soc_private) { struct device_node *of_node; void *fuse; - uint32_t fuse_addr, fuse_bit; - uint32_t fuse_val = 0, feature_bit_pos; - int count = 0, i = 0; + uint32_t fuse_addr, fuse_mask, fuse_shift; + uint32_t val = 0, fuse_val = 0, feature; + uint32_t enable_type = 0, hw_map = 0; + int count = 0, i = 0, j = 0, num_feature = 0, num_fuse = 0; + struct cam_cpas_feature_info *feature_info; of_node = pdev->dev.of_node; count = of_property_count_u32_elems(of_node, "cam_hw_fuse"); - for (i = 0; (i + 3) <= count; i = i + 3) { + CAM_DBG(CAM_CPAS, "fuse info elements count %d", count); + + if (count <= 0) { + CAM_INFO(CAM_CPAS, "No or invalid fuse entries count: %d", + count); + goto end; + } else if (count%5 != 0) { + CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 5 %d", + count); + goto end; + } + + for (i = 0; (i + 5) <= count; i = i + 5) { of_property_read_u32_index(of_node, "cam_hw_fuse", i, - &feature_bit_pos); + &feature); of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1, &fuse_addr); of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2, - &fuse_bit); - CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d", - feature_bit_pos, fuse_addr, fuse_bit); + &fuse_mask); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 3, + &enable_type); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 4, + &hw_map); + val = ffs(fuse_mask); + if (val == 0) { + CAM_ERR(CAM_CPAS, "fuse_mask not valid 0x%x", + fuse_mask); + fuse_shift = 0; + } else { + fuse_shift = val - 1; + } + CAM_INFO(CAM_CPAS, + "feature 0x%x addr 0x%x, mask 0x%x, shift 0x%x type 0x%x hw_map 0x%x", + feature, fuse_addr, fuse_mask, fuse_shift, enable_type, + hw_map); fuse = ioremap(fuse_addr, 4); if (fuse) { fuse_val = cam_io_r(fuse); - if (fuse_val & BIT(fuse_bit)) - soc_private->feature_mask |= feature_bit_pos; - else - soc_private->feature_mask &= ~feature_bit_pos; - } - CAM_INFO(CAM_CPAS, "fuse %pK, fuse_val %x, feature_mask %x", - fuse, fuse_val, soc_private->feature_mask); + for (j = 0; (j < num_fuse) && (j < CAM_CPAS_FUSES_MAX); + j++) { + if (soc_private->fuse_info.fuse_val[j].fuse_id + == fuse_addr) + break; + } + if (j >= CAM_CPAS_FUSES_MAX) { + CAM_ERR(CAM_CPAS, + "fuse_info array overflow! %d", j); + goto end; + } + if (j == num_fuse) { + soc_private->fuse_info.fuse_val[j].fuse_id = + fuse_addr; + soc_private->fuse_info.fuse_val[j].fuse_val = + fuse_val; + CAM_INFO(CAM_CPAS, + "fuse_addr 0x%x, fuse_val %x", + fuse_addr, fuse_val); + num_fuse++; + } + } else { + /* if fuse ioremap is failed, disable the feature */ + CAM_ERR(CAM_CPAS, + "fuse register io remap failed fuse_addr:0x%x feature0x%x ", + fuse_addr, feature); + if (enable_type == CAM_CPAS_FEATURE_TYPE_ENABLE || + enable_type == CAM_CPAS_FEATURE_TYPE_DISABLE) + fuse_val = (enable_type) ? ~fuse_mask : + fuse_mask; + else + fuse_val = 0; + } + + if (num_feature >= CAM_CPAS_MAX_FUSE_FEATURE) { + CAM_ERR(CAM_CPAS, "feature_info array overflow %d", + num_feature); + goto end; + } + + soc_private->feature_info[num_feature].feature = + feature; + soc_private->feature_info[num_feature].hw_map = hw_map; + soc_private->feature_info[num_feature].type = enable_type; + feature_info = &soc_private->feature_info[num_feature]; + + if (enable_type != CAM_CPAS_FEATURE_TYPE_VALUE) { + if (enable_type == CAM_CPAS_FEATURE_TYPE_ENABLE) { + /* + * fuse is for enable feature + * if fust bit is set means feature is enabled + * or HW is enabled + */ + if (fuse_val & fuse_mask) + feature_info->enable = true; + else + feature_info->enable = false; + } else if (enable_type == + CAM_CPAS_FEATURE_TYPE_DISABLE){ + /* + * fuse is for disable feature + * if fust bit is set means feature is disabled + * or HW is disabled + */ + if (fuse_val & fuse_mask) + feature_info->enable = false; + else + feature_info->enable = true; + } else { + CAM_ERR(CAM_CPAS, + "Feature type not valid, type: %d", + enable_type); + goto end; + } + CAM_INFO(CAM_CPAS, + "feature 0x%x enable=%d hw_map=0x%x", + feature_info->feature, feature_info->enable, + feature_info->hw_map); + } else { + feature_info->value = + (fuse_val & fuse_mask) >> fuse_shift; + CAM_INFO(CAM_CPAS, + "feature 0x%x value=0x%x hw_map=0x%x", + feature_info->feature, feature_info->value, + feature_info->hw_map); + } + num_feature++; + iounmap(fuse); } +end: + soc_private->fuse_info.num_fuses = num_fuse; + soc_private->num_feature_info = num_feature; return 0; } @@ -565,7 +633,6 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, } of_node = pdev->dev.of_node; - soc_private->feature_mask = 0xFFFFFFFF; rc = of_property_read_string(of_node, "arch-compat", &soc_private->arch_compat); @@ -576,7 +643,6 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, } cam_cpas_get_hw_features(pdev, soc_private); - cam_cpas_get_hw_fuse(pdev, soc_private); soc_private->camnoc_axi_min_ib_bw = 0; rc = of_property_read_u64(of_node, diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index 50d94549ba2a..b12ea3c6e48d 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -11,6 +11,7 @@ #define CAM_REGULATOR_LEVEL_MAX 16 #define CAM_CPAS_MAX_TREE_NODES 50 +#define CAM_CPAS_MAX_FUSE_FEATURE 10 /** * struct cam_cpas_vdd_ahb_mapping : Voltage to ahb level mapping @@ -71,6 +72,23 @@ struct cam_cpas_tree_node { struct cam_cpas_tree_node *parent_node; }; +/** + * struct cam_cpas_feature_info : CPAS fuse feature info + * @feature: Identifier for feature + * @type: Type of feature + * @value: Fuse value + * @enable: Feature enable or disable + * @hw_map: Each bit position indicates if the hw_id for the feature + */ + +struct cam_cpas_feature_info { + uint32_t feature; + uint32_t type; + uint32_t value; + bool enable; + uint32_t hw_map; +}; + /** * struct cam_cpas_private_soc : CPAS private DT info * @@ -90,9 +108,10 @@ struct cam_cpas_tree_node { * @camnoc_axi_clk_bw_margin : BW Margin in percentage to add while calculating * camnoc axi clock * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target - * @feature_mask: feature mask value for hw supported features * @fuse_info: fuse information * @rpmh_info: RPMH BCM info + * @num_feature_info: number of feature_info entries + * @feature_info: Structure for storing feature information */ struct cam_cpas_private_soc { const char *arch_compat; @@ -109,9 +128,10 @@ struct cam_cpas_private_soc { uint32_t camnoc_bus_width; uint32_t camnoc_axi_clk_bw_margin; uint64_t camnoc_axi_min_ib_bw; - uint32_t feature_mask; struct cam_cpas_fuse_info fuse_info; uint32_t rpmh_info[CAM_RPMH_BCM_INFO_MAX]; + uint32_t num_feature_info; + struct cam_cpas_feature_info feature_info[CAM_CPAS_MAX_FUSE_FEATURE]; }; void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 4c895ec3918e..2380c5527a3e 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -37,6 +37,22 @@ enum cam_cpas_reg_base { CAM_CPAS_REG_MAX }; +/** + * enum cam_cpas_hw_index - Enum for identify HW index + */ +enum cam_cpas_hw_index { + CAM_CPAS_HW_IDX_ANY = 0, + CAM_CPAS_HW_IDX_0 = 1<<0, + CAM_CPAS_HW_IDX_1 = 1<<1, + CAM_CPAS_HW_IDX_2 = 1<<2, + CAM_CPAS_HW_IDX_3 = 1<<3, + CAM_CPAS_HW_IDX_4 = 1<<4, + CAM_CPAS_HW_IDX_5 = 1<<5, + CAM_CPAS_HW_IDX_6 = 1<<6, + CAM_CPAS_HW_IDX_7 = 1<<7, + CAM_CPAS_HW_IDX_MAX = 1<<8 +}; + /** * enum cam_cpas_camera_version Enum for Titan Camera Versions */ @@ -608,11 +624,15 @@ int cam_cpas_get_cpas_hw_version( * * @flag : Camera hw features to check * + * @hw_map : To indicate which HWs are supported + * + * @fule_val : Return fule value in case of value type feature + * * @return 1 if feature is supported * */ -int cam_cpas_is_feature_supported( - uint32_t flag); +bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map, + uint32_t *fuse_val); /** * cam_cpas_axi_util_path_type_to_string() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 1f9749b2b34a..961b19fbec91 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1002,6 +1002,116 @@ end: return rc; } +bool cam_ife_csid_is_resolution_supported_by_fuse(uint32_t width) +{ + bool supported = true; + uint32_t hw_version, fuse_val = UINT_MAX; + int rc = 0; + + rc = cam_cpas_get_cpas_hw_version(&hw_version); + + if (rc) { + CAM_ERR(CAM_ISP, "Could not get CPAS version"); + return supported; + } + + switch (hw_version) { + case CAM_CPAS_TITAN_570_V200: + cam_cpas_is_feature_supported(CAM_CPAS_MP_LIMIT_FUSE, + CAM_CPAS_HW_IDX_ANY, &fuse_val); + switch (fuse_val) { + case 0x0: + if (width > CAM_CSID_RESOLUTION_22MP_WIDTH) { + CAM_ERR(CAM_ISP, + "Resolution not supported required_width: %d max_supported_width: %d", + width, CAM_CSID_RESOLUTION_22MP_WIDTH); + supported = false; + } + break; + case 0x1: + if (width > CAM_CSID_RESOLUTION_25MP_WIDTH) { + CAM_ERR(CAM_ISP, + "Resolution not supported required_width: %d max_supported_width: %d", + width, CAM_CSID_RESOLUTION_25MP_WIDTH); + supported = false; + } + break; + case 0x2: + if (width > CAM_CSID_RESOLUTION_28MP_WIDTH) { + CAM_ERR(CAM_ISP, + "Resolution not supported required_width: %d max_supported_width: %d", + width, CAM_CSID_RESOLUTION_28MP_WIDTH); + supported = false; + } + break; + case UINT_MAX: + CAM_WARN(CAM_ISP, "Fuse value not updated"); + break; + default: + CAM_ERR(CAM_ISP, + "Fuse value not defined, fuse_val: 0x%x", + fuse_val); + supported = false; + break; + } + break; + default: + break; + } + return supported; +} + +bool cam_ife_csid_is_resolution_supported_by_dt(struct cam_ife_csid_hw *csid_hw, + uint32_t width) +{ + bool supported = true; + struct cam_hw_soc_info soc_info; + struct cam_csid_soc_private *soc_private = NULL; + + if (!csid_hw || !csid_hw->hw_info) { + CAM_ERR(CAM_ISP, "Argument parsing error!"); + supported = false; + goto end; + } + + soc_info = csid_hw->hw_info->soc_info; + + soc_private = (struct cam_csid_soc_private *)soc_info.soc_private; + + if (!soc_private) { + CAM_ERR(CAM_ISP, "soc_private not found"); + supported = false; + goto end; + } + + if (soc_private->max_width_enabled) { + if (width > soc_private->max_width) { + CAM_ERR(CAM_ISP, + "Resolution not supported required_width: %d max_supported_width: %d", + width, soc_private->max_width); + supported = false; + } + } +end: + return supported; +} + +bool cam_ife_csid_is_resolution_supported(struct cam_ife_csid_hw *csid_hw, + uint32_t width) +{ + bool supported = false; + + if (!csid_hw) { + CAM_ERR(CAM_ISP, "csid_hw is NULL"); + return supported; + } + + if (cam_ife_csid_is_resolution_supported_by_fuse(width) && + cam_ife_csid_is_resolution_supported_by_dt(csid_hw, width)) + supported = true; + return supported; +} + int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, struct cam_csid_hw_reserve_resource_args *reserve) { @@ -1179,6 +1289,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, } if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { + if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) && + !(cam_ife_csid_is_resolution_supported(csid_hw, + reserve->in_port->left_stop - + reserve->in_port->left_start + 1))) { + rc = -EINVAL; + goto end; + } path_data->start_pixel = reserve->in_port->left_start; path_data->end_pixel = reserve->in_port->left_stop; path_data->width = reserve->in_port->left_width; @@ -1198,6 +1315,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, reserve->res_id, path_data->start_line, path_data->end_line); } else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { + if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) && + !(cam_ife_csid_is_resolution_supported(csid_hw, + reserve->in_port->right_stop - + reserve->in_port->right_start + 1))) { + rc = -EINVAL; + goto end; + } path_data->master_idx = reserve->master_idx; CAM_DBG(CAM_ISP, "CSID:%d master_idx=%d", csid_hw->hw_intf->hw_idx, path_data->master_idx); @@ -1214,6 +1338,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, reserve->res_id, path_data->start_line, path_data->end_line); } else { + if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) && + !(cam_ife_csid_is_resolution_supported(csid_hw, + reserve->in_port->left_stop - + reserve->in_port->left_start + 1))) { + rc = -EINVAL; + goto end; + } path_data->width = reserve->in_port->left_width; path_data->start_pixel = reserve->in_port->left_start; path_data->end_pixel = reserve->in_port->left_stop; @@ -5188,7 +5319,8 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, goto err; } - if (cam_cpas_is_feature_supported(CAM_CPAS_QCFA_BINNING_ENABLE) == 1) + if (cam_cpas_is_feature_supported(CAM_CPAS_QCFA_BINNING_ENABLE, + CAM_CPAS_HW_IDX_ANY, NULL)) ife_csid_hw->binning_enable = 1; ife_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_ife_csid_get_hw_caps; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index efd5b0a47591..55d23566060a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -76,6 +76,10 @@ #define CAM_CSID_EVT_PAYLOAD_MAX 10 #define CAM_CSID_MIN_HBI_CFG_MAX_VAL 0xF +#define CAM_CSID_RESOLUTION_22MP_WIDTH 5612 +#define CAM_CSID_RESOLUTION_25MP_WIDTH 6048 +#define CAM_CSID_RESOLUTION_28MP_WIDTH 7308 + /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_csid_path_halt_mode { CSID_HALT_MODE_INTERNAL, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c index 5a008f2b4521..01c66cb9607a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -21,6 +21,16 @@ static int cam_ife_csid_get_dt_properties(struct cam_hw_soc_info *soc_info) soc_private = (struct cam_csid_soc_private *)soc_info->soc_private; + rc = of_property_read_u32(of_node, "max-width", + &soc_private->max_width); + if (rc) { + CAM_DBG(CAM_ISP, "No max-width declared"); + soc_private->max_width_enabled = false; + rc = 0; + } else { + soc_private->max_width_enabled = true; + } + soc_private->is_ife_csid_lite = false; if (strnstr(soc_info->compatible, "lite", strlen(soc_info->compatible)) != NULL) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h index 3391bcaf463f..3a9bfd8e01c8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h @@ -17,10 +17,14 @@ * This handle is used for all further interface * with CPAS. * @is_ife_csid_lite: Flag to indicate Whether a full csid or a Lite csid + * @max_width_enabled: Flag to enable max width restriction + * @max_width: Maxinum allowed width */ struct cam_csid_soc_private { uint32_t cpas_handle; bool is_ife_csid_lite; + bool max_width_enabled; + uint32_t max_width; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 2cfdc2a99136..903d12bf53a3 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1347,8 +1347,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { - if (cam_cpas_is_feature_supported( - CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { + if (!cam_cpas_is_feature_supported( + CAM_CPAS_SECURE_CAMERA_ENABLE, + CAM_CPAS_HW_IDX_ANY, NULL)) { CAM_ERR(CAM_CSIPHY, "sec_cam: camera fuse bit not set"); goto release_mutex; @@ -1411,8 +1412,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { - if (cam_cpas_is_feature_supported( - CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { + if (!cam_cpas_is_feature_supported( + CAM_CPAS_SECURE_CAMERA_ENABLE, + CAM_CPAS_HW_IDX_ANY, NULL)) { CAM_ERR(CAM_CSIPHY, "sec_cam: camera fuse bit not set"); cam_cpas_stop(csiphy_dev->cpas_handle); From 89fc8fcc81db16979efd4184e8ad2f6326491ba5 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Wed, 30 Sep 2020 19:48:52 -0700 Subject: [PATCH 530/790] msm: camera: cpas: Write qosgen registers when enabled Call qosgen register update to write values into corresponding registers. CRs-Fixed: 2789495 Change-Id: I43eb6bc9d4cce42b78d55b4519931b15b7f6a383 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index f07e16d7f44c..b0e07e0adb0e 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -683,6 +683,8 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) cam_cpastop_reset_irq(cpas_hw); for (i = 0; i < camnoc_info->specific_size; i++) { if (camnoc_info->specific[i].enable) { + CAM_DBG(CAM_CPAS, "Updating QoS settings for %d", + camnoc_info->specific[i].port_type); cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, &camnoc_info->specific[i].priority_lut_low); cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, @@ -697,6 +699,12 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) &camnoc_info->specific[i].ubwc_ctl); cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, &camnoc_info->specific[i].flag_out_set0_low); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].qosgen_mainctl); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].qosgen_shaping_low); + cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].qosgen_shaping_high); } } From 58588fb689a95a740106d60597155d83de3e843b Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Mon, 28 Sep 2020 17:18:36 -0700 Subject: [PATCH 531/790] msm: camera: memmgr: Add error handling get slot failure Not calling unmap_hw_va if get_slot() fails causes a stale entry in smmu CB. since get_slot failed, memmgr table returns error and memmgr, umd doesn't keep info about this map entry though smmu CB still has this mapping - This causes any further map calls on the same 'fd' as smmu return MAP_EXISTS but CSL bookkeeping doesn't have it. CRs-Fixed: 2788167 Change-Id: Ibb1450f089b9f175ccdbcfb4f5ecc245a5539bd1 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_req_mgr/cam_mem_mgr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index cb45531e1f32..a3e18f3d729d 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -830,6 +830,14 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) is_internal = cam_mem_util_is_map_internal(cmd->fd); + idx = cam_mem_get_slot(); + if (idx < 0) { + CAM_ERR(CAM_MEM, "Failed in getting mem slot, idx=%d, fd=%d", + idx, cmd->fd); + rc = -ENOMEM; + goto slot_fail; + } + if ((cmd->flags & CAM_MEM_FLAG_HW_READ_WRITE) || (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE)) { rc = cam_mem_util_map_hw_va(cmd->flags, @@ -855,12 +863,6 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) } } - idx = cam_mem_get_slot(); - if (idx < 0) { - rc = -ENOMEM; - goto map_fail; - } - mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].fd = cmd->fd; tbl.bufq[idx].dma_buf = NULL; @@ -893,8 +895,9 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) tbl.bufq[idx].len); return rc; - map_fail: + cam_mem_put_slot(idx); +slot_fail: dma_buf_put(dmabuf); return rc; } @@ -1266,6 +1269,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, idx = cam_mem_get_slot(); if (idx < 0) { + CAM_ERR(CAM_MEM, "Failed in getting mem slot, idx=%d", idx); rc = -ENOMEM; goto slot_fail; } @@ -1414,6 +1418,7 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, idx = cam_mem_get_slot(); if (idx < 0) { + CAM_ERR(CAM_MEM, "Failed in getting mem slot, idx=%d", idx); rc = -ENOMEM; goto slot_fail; } From f5f9d74e97ec9e2b9931a5285267ebc784c16c7b Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Wed, 30 Sep 2020 15:30:11 +0530 Subject: [PATCH 532/790] msm: camera: core: Change the error logs to rate limited In bubble cases and if not recovered, error logs causing excessive logging issues. Change the error and warn logs to rate limited in error bubble and apply failure cases. CRs-Fixed: 2785070 Change-Id: Ia7268cfc7b672c24f3161cd65c53df5ee357e7ee Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/cam_isp_context.c | 44 ++++++++++++------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 6 ++- drivers/cam_req_mgr/cam_req_mgr_core.c | 6 +-- drivers/cam_req_mgr/cam_req_mgr_dev.c | 2 +- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index b967dad7c9f6..3ddf1cbd9719 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1467,8 +1467,9 @@ static int __cam_isp_ctx_reg_upd_in_epoch_bubble_state( __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); else - CAM_WARN(CAM_ISP, - "Unexpected reg update in activated Substate[%s] for frame_id:%lld", + CAM_WARN_RATE_LIMIT(CAM_ISP, + "ctx_id:%d Unexpected reg update in activated Substate[%s] for frame_id:%lld", + ctx_isp->base->ctx_id, __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated), ctx_isp->frame_id); @@ -1761,7 +1762,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp->bubble_detected = true; req_isp->reapply = true; - CAM_INFO(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", + CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { @@ -1776,7 +1777,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); trace_cam_log_event("Bubble", "Rcvd epoch in applied state", @@ -1965,7 +1966,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; - CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", + CAM_INFO_RATE_LIMIT(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; @@ -1982,7 +1983,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - CAM_WARN(CAM_REQ, + CAM_WARN_RATE_LIMIT(CAM_REQ, "Notify CRM about Bubble req_id %llu frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); @@ -2790,7 +2791,9 @@ static int __cam_isp_ctx_apply_req_in_activated_state( struct cam_hw_config_args cfg = {0}; if (list_empty(&ctx->pending_req_list)) { - CAM_ERR(CAM_ISP, "No available request for Apply id %lld", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "ctx_id:%d No available request for Apply id %lld", + ctx->ctx_id, apply->request_id); rc = -EFAULT; goto end; @@ -2805,8 +2808,9 @@ 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_INFO(CAM_ISP, - "Processing bubble cannot apply Request Id %llu", + CAM_INFO_RATE_LIMIT(CAM_ISP, + "ctx_id:%d Processing bubble cannot apply Request Id %llu", + ctx->ctx_id, apply->request_id); rc = -EAGAIN; goto end; @@ -2814,8 +2818,9 @@ static int __cam_isp_ctx_apply_req_in_activated_state( if (apply->re_apply) if (apply->request_id <= ctx_isp->last_applied_req_id) { - CAM_INFO(CAM_ISP, - "Trying to reapply the same request %llu again", + CAM_INFO_RATE_LIMIT(CAM_ISP, + "ctx_id:%d Trying to reapply the same request %llu again", + ctx->ctx_id, apply->request_id); return 0; } @@ -2831,7 +2836,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state( */ if (req->request_id != apply->request_id) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "Invalid Request Id asking %llu existing %llu", + "ctx_id:%d Invalid Request Id asking %llu existing %llu", + ctx->ctx_id, apply->request_id, req->request_id); rc = -EFAULT; goto end; @@ -2844,7 +2850,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state( req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (ctx_isp->active_req_cnt >= 2) { - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Reject apply request (id %lld) due to congestion(cnt = %d) ctx %u", req->request_id, ctx_isp->active_req_cnt, @@ -2884,7 +2890,9 @@ static int __cam_isp_ctx_apply_req_in_activated_state( rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (rc) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration"); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "ctx_id:%d ,Can not apply the configuration", + ctx->ctx_id); } else { spin_lock_bh(&ctx->lock); ctx_isp->substate_activated = next_state; @@ -3599,7 +3607,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; - CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", + CAM_INFO_RATE_LIMIT(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; @@ -3616,7 +3624,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld ctx %u", req->request_id, ctx_isp->frame_id, @@ -3914,7 +3922,9 @@ static int __cam_isp_ctx_rdi_only_apply_req_top_state( ctx_isp->substate_activated)); if (rc) - CAM_ERR(CAM_ISP, "Apply failed in Substate[%s], rc %d", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "ctx_id:%d Apply failed in Substate[%s], rc %d", + ctx->ctx_id, __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated), rc); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 1f9749b2b34a..f6f641259fd0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -3261,7 +3261,11 @@ static int cam_ife_csid_get_time_stamp( time_stamp->boot_timestamp = csid_hw->prev_boot_timestamp + time_delta; if (time_delta == 0) - CAM_WARN(CAM_ISP, "No qtimer update"); + CAM_WARN_RATE_LIMIT(CAM_ISP, + "CSID:%d No qtimer update ts: %lld prev ts:%lld", + csid_hw->hw_intf->hw_idx, + time_stamp->time_stamp_val, + csid_hw->prev_qtimer_ts); } csid_hw->prev_qtimer_ts = time_stamp->time_stamp_val; csid_hw->prev_boot_timestamp = time_stamp->boot_timestamp; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index ee3972096998..263d3320e774 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -320,7 +320,7 @@ static int __cam_req_mgr_notify_error_on_link( return -EINVAL; } - CAM_ERR(CAM_CRM, + CAM_ERR_RATE_LIMIT(CAM_CRM, "Notifying userspace to trigger recovery on link 0x%x for session %d", link->link_hdl, session->session_hdl); @@ -340,7 +340,7 @@ static int __cam_req_mgr_notify_error_on_link( V4L_EVENT_CAM_REQ_MGR_EVENT); if (rc) - CAM_ERR(CAM_CRM, + CAM_ERR_RATE_LIMIT(CAM_CRM, "Error in notifying recovery for session %d link 0x%x rc %d", session->session_hdl, link->link_hdl, rc); @@ -2826,7 +2826,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) } if (link->state == CAM_CRM_LINK_STATE_ERR) - CAM_WARN(CAM_CRM, "Error recovery idx %d status %d", + CAM_WARN_RATE_LIMIT(CAM_CRM, "Error recovery idx %d status %d", in_q->rd_idx, in_q->slot[in_q->rd_idx].status); diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 6043f2999323..bd5b04c923b5 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -240,7 +240,7 @@ static void cam_v4l2_event_queue_notify_error(const struct v4l2_event *old, ev_header->u.frame_msg.link_hdl); break; case V4L_EVENT_CAM_REQ_MGR_ERROR: - CAM_ERR(CAM_CRM, + CAM_ERR_RATE_LIMIT(CAM_CRM, "Failed to notify ERROR Sess %X ReqId %d Link %X Type %d", ev_header->session_hdl, ev_header->u.err_msg.request_id, From d74902f0cff446525e2327bacd84143157fe61f6 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 1 Sep 2020 18:12:19 -0700 Subject: [PATCH 533/790] msm: camera: cdm: Add CDM hang detect and debug registers dump support Add support to dump the cdm core debug registers and CDM hang detect support for better debugging purpose in case of cdm timeout at config ife. Add a debugfs for CDM command buffer dump for cdm hang events. Fix the possible NULL derefernce while dumping the cdm registers. Turn on debugfs using following command in adb shell: echo 1 >> /sys/kernel/debug/camera_isp_ctx/enable_cdm_cmd_buffer_dump. CRs-Fixed: 2748715, 2782720, 2770565 Change-Id: Ibb9aa1d232d742ca1b6e64c16e9718bfc0bc8624 Signed-off-by: Jigar Agrawal --- drivers/cam_cdm/cam_cdm.h | 1 + drivers/cam_cdm/cam_cdm_core_common.c | 16 +++ drivers/cam_cdm/cam_cdm_core_common.h | 2 + drivers/cam_cdm/cam_cdm_hw_core.c | 150 ++++++++++---------- drivers/cam_cdm/cam_cdm_intf.c | 26 ++++ drivers/cam_cdm/cam_cdm_intf_api.h | 9 ++ drivers/cam_isp/cam_isp_context.c | 12 +- drivers/cam_isp/cam_isp_context.h | 6 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 5 +- 9 files changed, 142 insertions(+), 85 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 540c03b0185f..fbd3fc5f5c51 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -378,6 +378,7 @@ enum cam_cdm_hw_process_intf_cmd { CAM_CDM_HW_INTF_CMD_FLUSH_HW, CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, CAM_CDM_HW_INTF_CMD_HANG_DETECT, + CAM_CDM_HW_INTF_DUMP_DBG_REGS, CAM_CDM_HW_INTF_CMD_INVALID, }; diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index 9e08c08b6d5d..e98bbc9fe747 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -822,6 +822,22 @@ int cam_cdm_process_cmd(void *hw_priv, mutex_unlock(&cdm_hw->hw_mutex); break; } + case CAM_CDM_HW_INTF_DUMP_DBG_REGS: + { + uint32_t *handle = cmd_args; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=0x%x", + cmd, arg_size, *handle); + return -EINVAL; + } + + mutex_lock(&cdm_hw->hw_mutex); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } default: CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); break; diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h index 1dd43b678dfe..d4875e2717a8 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.h +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -56,5 +56,7 @@ struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( uint32_t tag, struct list_head *bl_list); void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, enum cam_cdm_cb_status status, void *data); +void cam_hw_cdm_dump_core_debug_registers( + struct cam_hw_info *cdm_hw, bool pause_core); #endif /* _CAM_CDM_CORE_COMMON_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index c03e0eec29d4..6b58cf08c695 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -169,14 +169,14 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause) return rc; } -int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) +int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw, uint32_t value) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, - 0x10100)) { + value)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } @@ -263,24 +263,7 @@ end: return rc; } -int cam_hw_cdm_enable_core_dbg_per_fifo( - struct cam_hw_info *cdm_hw, - uint32_t fifo_idx) -{ - int rc = 0; - struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - - if (cam_cdm_write_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_debug, - (0x10100 | fifo_idx << 20))) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); - rc = -EIO; - } - - return rc; -} - -void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) +static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) { struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; int i, j; @@ -289,13 +272,7 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, i, &num_pending_req); - - if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) { - CAM_ERR(CAM_CDM, - "Problem in selecting the fifo for readback"); - continue; - } - for (j = 0 ; j < num_pending_req ; j++) { + for (j = 0; j < num_pending_req ; j++) { cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->bl_fifo_rb, j); cam_cdm_read_hw_reg(cdm_hw, @@ -316,83 +293,111 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) } } -void cam_hw_cdm_dump_core_debug_registers( - struct cam_hw_info *cdm_hw) +void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, + bool pause_core) { - uint32_t dump_reg, dump_reg1, dump_reg2, core_dbg; + uint32_t dump_reg, core_dbg = 0x100; int i; + bool is_core_paused_already; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + const struct cam_cdm_icl_regs *inv_cmd_log = + core->offsets->cmn_reg->icl_reg; cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg); + CAM_INFO(CAM_CDM, "CDM HW core status=0x%x", dump_reg); + + if (pause_core) { + cam_hw_cdm_pause_core(cdm_hw, true); + usleep_range(1000, 1010); + } + cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, &dump_reg); CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg); - usleep_range(1000, 1010); - cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_debug, - &core_dbg); + CAM_INFO(CAM_CDM, "CDM HW Debug status reg=0x%x", dump_reg); + if (core_dbg & 0x100) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_addr, &dump_reg); - CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); + CAM_INFO(CAM_CDM, "AHB dump reglastaddr=0x%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_data, &dump_reg); - CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); + CAM_INFO(CAM_CDM, "AHB dump reglastdata=0x%x", dump_reg); } else { CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->icl_reg->data_regs->icl_inv_data, - &dump_reg); - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->icl_reg->misc_regs->icl_inv_bl_addr, - &dump_reg1); - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->icl_reg->misc_regs->icl_status, - &dump_reg2); - CAM_INFO(CAM_CDM, - "Last Inv Cmd Log(ICL)Status: 0x%x, Last Inv cmd: 0x%x, Last Inv bl_addr: 0x%x", - dump_reg2, dump_reg, dump_reg1); + if (inv_cmd_log) { + if (inv_cmd_log->misc_regs) { + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->misc_regs->icl_status, + &dump_reg); + CAM_INFO(CAM_CDM, + "Last Inv Cmd Log(ICL)Status: 0x%x", + dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->misc_regs->icl_inv_bl_addr, + &dump_reg); + CAM_INFO(CAM_CDM, + "Last Inv bl_addr: 0x%x", + dump_reg); + } + if (inv_cmd_log->data_regs) { + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_inv_data, + &dump_reg); + CAM_INFO(CAM_CDM, "Last Inv cmd: 0x%x", dump_reg); + } + } - cam_hw_cdm_dump_bl_fifo_data(cdm_hw); + if (core_dbg & 0x10000) { + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_en, &dump_reg); + is_core_paused_already = (bool)(dump_reg & 0x20); + if (!is_core_paused_already) { + cam_hw_cdm_pause_core(cdm_hw, true); + usleep_range(1000, 1010); + } + + cam_hw_cdm_dump_bl_fifo_data(cdm_hw); + + if (!is_core_paused_already) + cam_hw_cdm_pause_core(cdm_hw, false); + } CAM_INFO(CAM_CDM, "CDM HW default dump"); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_cfg, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); + CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg); for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_status, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq status%d=0x%x", i, dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_set, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq set%d=0x%x", i, dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_mask, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq mask%d=0x%x", i, dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->irq_reg[i]->irq_clear, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg); + CAM_INFO(CAM_CDM, "CDM HW irq clear%d=0x%x", i, dump_reg); } cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_base, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg); + CAM_INFO(CAM_CDM, "CDM HW current BL base=0x%x", dump_reg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_len, &dump_reg); @@ -408,8 +413,11 @@ void cam_hw_cdm_dump_core_debug_registers( cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); + CAM_INFO(CAM_CDM, "CDM HW current AHB base=0x%x", dump_reg); + cam_hw_cdm_disable_core_dbg(cdm_hw); + if (pause_core) + cam_hw_cdm_pause_core(cdm_hw, false); } enum cam_cdm_arbitration cam_cdm_get_arbitration_type( @@ -1209,14 +1217,7 @@ static void cam_hw_cdm_work(struct work_struct *work) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); - /* - * First pause CDM, If it fails still proceed - * to dump debug info - */ - cam_hw_cdm_pause_core(cdm_hw, true); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); - /* Resume CDM back */ - cam_hw_cdm_pause_core(cdm_hw, false); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); @@ -1247,14 +1248,7 @@ static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { - /* - * First pause CDM, If it fails still proceed - * to dump debug info - */ - cam_hw_cdm_pause_core(cdm_hw, true); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); - /* Resume CDM back */ - cam_hw_cdm_pause_core(cdm_hw, false); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); } else CAM_INFO(CAM_CDM, "CDM hw is power in off state"); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) @@ -1574,7 +1568,7 @@ int cam_hw_cdm_handle_error_info( current_fifo, current_tag); /* dump cdm registers for further debug */ - cam_hw_cdm_dump_core_debug_registers(cdm_hw); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, false); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { if (!cdm_core->bl_fifo[i].bl_depth) @@ -1690,8 +1684,8 @@ int cam_hw_cdm_hang_detect( for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) if (cdm_core->bl_fifo[i].work_record) { CAM_WARN(CAM_CDM, - "workqueue got delayed, work_record :%u", - cdm_core->bl_fifo[i].work_record); + "workqueue got delayed, bl_fifo: %d, work_record :%u", + i, cdm_core->bl_fifo[i].work_record); rc = 0; break; } diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index 04b2a7393546..e0575955225f 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -507,6 +507,32 @@ int cam_cdm_detect_hang_error(uint32_t handle) } EXPORT_SYMBOL(cam_cdm_detect_hang_error); +int cam_cdm_dump_debug_registers(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_DUMP_DBG_REGS, + &handle, + sizeof(handle)); + } + put_cdm_mgr_refcount(); + + return rc; +} + int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, uint32_t *index) diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index adf6930593ce..2315b0a0ed8e 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -290,4 +290,13 @@ struct cam_cdm_utils_ops *cam_cdm_publish_ops(void); * @return 0 on success */ int cam_cdm_detect_hang_error(uint32_t handle); + +/** + * @brief : API to dump the CDM Debug registers + * + * @handle : Input handle of the CDM to dump the registers + * + * @return 0 on success + */ +int cam_cdm_dump_debug_registers(uint32_t handle); #endif /* _CAM_CDM_API_H_ */ diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index b967dad7c9f6..283ce1f2e626 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5033,9 +5033,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, /* HW failure. user need to clean up the resource */ CAM_ERR(CAM_ISP, "Start HW failed"); ctx->state = CAM_CTX_READY; - trace_cam_context_state("ISP", ctx); - if (rc == -ETIMEDOUT) + if ((rc == -ETIMEDOUT) && + (isp_ctx_debug.enable_cdm_cmd_buff_dump)) rc = cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false); + + trace_cam_context_state("ISP", ctx); list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); goto end; @@ -5628,7 +5630,7 @@ static int cam_isp_context_debug_register(void) dbgfileptr = debugfs_create_dir("camera_isp_ctx", NULL); if (!dbgfileptr) { - CAM_ERR(CAM_ICP,"DebugFS could not create directory!"); + CAM_ERR(CAM_ISP, "DebugFS could not create directory!"); rc = -ENOENT; goto end; } @@ -5637,9 +5639,11 @@ static int cam_isp_context_debug_register(void) dbgfileptr = debugfs_create_u32("enable_state_monitor_dump", 0644, isp_ctx_debug.dentry, &isp_ctx_debug.enable_state_monitor_dump); + dbgfileptr = debugfs_create_u8("enable_cdm_cmd_buffer_dump", 0644, + isp_ctx_debug.dentry, &isp_ctx_debug.enable_cdm_cmd_buff_dump); if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) - CAM_WARN(CAM_ICP, "DebugFS not enabled in kernel!"); + CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel!"); else rc = PTR_ERR(dbgfileptr); } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 2f85193bd4c9..8ee0ff1d5273 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -114,13 +114,15 @@ enum cam_isp_state_change_trigger { /** * struct cam_isp_ctx_debug - Contains debug parameters * - * @dentry: Debugfs entry - * @enable_state_monitor_dump: Enable isp state monitor dump + * @dentry: Debugfs entry + * @enable_state_monitor_dump: Enable isp state monitor dump + * @enable_cdm_cmd_buff_dump: Enable CDM Command buffer dump * */ struct cam_isp_ctx_debug { struct dentry *dentry; uint32_t enable_state_monitor_dump; + uint8_t enable_cdm_cmd_buff_dump; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index e8b016ae98a9..f05fe483217f 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3852,11 +3852,14 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, if (cfg->init_packet) { rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete, - msecs_to_jiffies(30)); + msecs_to_jiffies(60)); if (rem_jiffies == 0) { CAM_ERR(CAM_ISP, "config done completion timeout for req_id=%llu ctx_index %d", cfg->request_id, ctx->ctx_index); + if (cam_cdm_detect_hang_error(ctx->cdm_handle)) + cam_cdm_dump_debug_registers( + ctx->cdm_handle); rc = -ETIMEDOUT; } else CAM_DBG(CAM_ISP, From 21feb1f6511f0b3422ac089f5876376837bd97bc Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Tue, 22 Sep 2020 19:23:48 +0530 Subject: [PATCH 534/790] msm: camera: isp: Add UBWC compression disable support Adding UBWC compression disable support. CRs-Fixed: 2789618 Change-Id: I994e6698ce945b7bed2a1207d4b52e4f10b99df1 Signed-off-by: Wyes Karny --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 12 +++++++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 13 +++++++-- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h | 2 ++ .../icp_hw_mgr/include/cam_icp_hw_intf.h | 2 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 27 ++++++++++++++++++- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 4 +++ .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 11 ++++++++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 12 +++++++++ 10 files changed, 82 insertions(+), 3 deletions(-) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 6882433c0252..3c7cccd2b132 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -645,6 +645,7 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, break; case CAM_ICP_CMD_UBWC_CFG: { struct a5_ubwc_cfg_ext *ubwc_cfg_ext = NULL; + uint32_t *disable_ubwc_comp; a5_soc = soc_info->soc_private; if (!a5_soc) { @@ -652,6 +653,13 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, return -EINVAL; } + if (!cmd_args) { + CAM_ERR(CAM_ICP, "Invalid args"); + return -EINVAL; + } + + disable_ubwc_comp = (uint32_t *)cmd_args; + if (a5_soc->ubwc_config_ext) { /* Invoke kernel API to determine DDR type */ ddr_type = of_fdt_get_ddrtype(); @@ -668,6 +676,10 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, ubwc_cfg_ext->ubwc_bps_fetch_cfg[index]; ubwc_bps_cfg[1] = ubwc_cfg_ext->ubwc_bps_write_cfg[index]; + if (*disable_ubwc_comp) { + ubwc_ipe_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; + ubwc_bps_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; + } rc = hfi_cmd_ubwc_config_ext(&ubwc_ipe_cfg[0], &ubwc_bps_cfg[0]); } else { diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index ef867225159b..f911901ad207 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -113,14 +113,19 @@ static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr) { struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; int rc; + uint32_t disable_ubwc_comp = 0; if (!icp_dev_intf) { CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } - rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, - CAM_ICP_CMD_UBWC_CFG, NULL, 0); + disable_ubwc_comp = hw_mgr->disable_ubwc_comp; + + rc = icp_dev_intf->hw_ops.process_cmd( + icp_dev_intf->hw_priv, + CAM_ICP_CMD_UBWC_CFG, (void *)&disable_ubwc_comp, + sizeof(disable_ubwc_comp)); if (rc) CAM_ERR(CAM_ICP, "CAM_ICP_CMD_UBWC_CFG is failed"); @@ -1918,6 +1923,10 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void) dbgfileptr = debugfs_create_file("icp_fw_dump_lvl", 0644, icp_hw_mgr.dentry, NULL, &cam_icp_debug_fw_dump); + + dbgfileptr = debugfs_create_bool("disable_ubwc_comp", 0644, + icp_hw_mgr.dentry, &icp_hw_mgr.disable_ubwc_comp); + if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) CAM_WARN(CAM_ICP, "DebugFS not enabled in kernel!"); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index e49f30d246f4..bfe920415b22 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -352,6 +352,7 @@ struct cam_icp_clk_info { * @bps_dev_intf: Device interface for BPS * @ipe_clk_state: IPE clock state flag * @bps_clk_state: BPS clock state flag + * @disable_ubwc_comp: Disable UBWC compression * @recovery: Flag to validate if in previous session FW * reported a fatal error or wdt. If set FW is * re-downloaded for new camera session. @@ -400,6 +401,7 @@ struct cam_icp_hw_mgr { struct cam_hw_intf *bps_dev_intf; bool ipe_clk_state; bool bps_clk_state; + bool disable_ubwc_comp; atomic_t recovery; }; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h index 0890bd8583cf..08dd8dbbf8bf 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h @@ -13,6 +13,8 @@ #define CAM_ICP_BW_CONFIG_V1 1 #define CAM_ICP_BW_CONFIG_V2 2 +#define CAM_ICP_UBWC_COMP_EN BIT(1) + enum cam_icp_hw_type { CAM_ICP_DEV_A5, CAM_ICP_DEV_IPE, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index f05fe483217f..01e2028005c0 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -4299,7 +4299,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *rsrc_node = NULL; - uint32_t i, camif_debug; + uint32_t i, j, camif_debug, disable_ubwc_comp; bool res_rdi_context_set = false; uint32_t primary_rdi_src_res; uint32_t primary_rdi_out_res; @@ -4373,6 +4373,27 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } } + if (g_ife_hw_mgr.debug_cfg.disable_ubwc_comp) { + disable_ubwc_comp = 1; + for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + hw_mgr_res = &ctx->res_list_ife_out[i]; + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->hw_intf->hw_ops.process_cmd) { + rc = rsrc_node->hw_intf->hw_ops.process_cmd( + rsrc_node->hw_intf->hw_priv, + CAM_ISP_HW_CMD_DISABLE_UBWC_COMP, + &disable_ubwc_comp, + sizeof(disable_ubwc_comp)); + } + } + break; + } + } + rc = cam_ife_hw_mgr_init_hw(ctx); if (rc) { CAM_ERR(CAM_ISP, "Init failed"); @@ -7960,6 +7981,10 @@ static int cam_ife_hw_mgr_debug_register(void) dbgfileptr = debugfs_create_bool("per_req_reg_dump", 0644, g_ife_hw_mgr.debug_cfg.dentry, &g_ife_hw_mgr.debug_cfg.per_req_reg_dump); + dbgfileptr = debugfs_create_bool("disable_ubwc_comp", 0644, + g_ife_hw_mgr.debug_cfg.dentry, + &g_ife_hw_mgr.debug_cfg.disable_ubwc_comp); + if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) CAM_WARN(CAM_ISP, "DebugFS not enabled in kernel!"); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 7a5e658da1b7..52833a5567c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -24,6 +24,8 @@ #define CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS BIT(0) #define CAM_IFE_CUSTOM_CFG_SW_SYNC_ON BIT(1) +#define CAM_IFE_UBWC_COMP_EN BIT(1) + /** * struct cam_ife_hw_mgr_debug - contain the debug information * @@ -34,6 +36,7 @@ * @enable_diag_sensor_status: enable sensor diagnosis status * @enable_req_dump: Enable request dump on HW errors * @per_req_reg_dump: Enable per request reg dump + * @disable_ubwc_comp: Disable UBWC compression * */ struct cam_ife_hw_mgr_debug { @@ -44,6 +47,7 @@ struct cam_ife_hw_mgr_debug { uint32_t camif_debug; bool enable_req_dump; bool per_req_reg_dump; + bool disable_ubwc_comp; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 8cec98ffeb4d..637257baeb76 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -130,6 +130,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, + CAM_ISP_HW_CMD_DISABLE_UBWC_COMP, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index b741cc153732..f4cc7102d973 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -618,6 +618,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_DUMP_BUS_INFO: case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: case CAM_ISP_HW_CMD_GET_RES_FOR_MID: + case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 69a69817b528..935ed271d86b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -101,6 +101,7 @@ struct cam_vfe_bus_ver2_common_data { cam_hw_mgr_event_cb_func event_cb; bool hw_init; bool support_consumed_addr; + bool disable_ubwc_comp; }; struct cam_vfe_bus_ver2_wm_resource_data { @@ -1223,6 +1224,7 @@ static int cam_vfe_bus_start_wm( struct cam_vfe_bus_ver2_common_data *common_data = rsrc_data->common_data; uint32_t camera_hw_version; + uint32_t disable_ubwc_comp = rsrc_data->common_data->disable_ubwc_comp; cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit); @@ -1259,6 +1261,8 @@ static int cam_vfe_bus_start_wm( val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg_0); val |= 0x1; + if (disable_ubwc_comp) + val &= ~CAM_IFE_UBWC_COMP_EN; cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg_0); } else if ((camera_hw_version == CAM_CPAS_TITAN_175_V100) || @@ -1275,6 +1279,8 @@ static int cam_vfe_bus_start_wm( val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg_0); val |= 0x1; + if (disable_ubwc_comp) + val &= ~CAM_IFE_UBWC_COMP_EN; cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg_0); } else { @@ -3688,6 +3694,10 @@ static int cam_vfe_bus_process_cmd( bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + bus_priv->common_data.disable_ubwc_comp = true; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3752,6 +3762,7 @@ int cam_vfe_bus_ver2_init( bus_priv->common_data.hw_init = false; bus_priv->common_data.support_consumed_addr = ver2_hw_info->support_consumed_addr; + bus_priv->common_data.disable_ubwc_comp = false; mutex_init(&bus_priv->common_data.bus_mutex); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 3e8ddb7385ff..c8668b696a03 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -91,6 +91,7 @@ struct cam_vfe_bus_ver3_common_data { bool is_lite; bool hw_init; bool support_consumed_addr; + bool disable_ubwc_comp; cam_hw_mgr_event_cb_func event_cb; int rup_irq_handle[CAM_VFE_BUS_VER3_SRC_GRP_MAX]; }; @@ -1625,6 +1626,7 @@ static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) struct cam_vfe_bus_ver3_common_data *common_data = rsrc_data->common_data; struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_regs; + bool disable_ubwc_comp = rsrc_data->common_data->disable_ubwc_comp; ubwc_regs = (struct cam_vfe_bus_ver3_reg_offset_ubwc_client *) rsrc_data->hw_regs->ubwc_regs; @@ -1640,6 +1642,8 @@ static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) if (rsrc_data->en_ubwc) { val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg); val |= 0x1; + if (disable_ubwc_comp) + val &= ~(0x1<<1); cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg); } @@ -2985,6 +2989,9 @@ static int cam_vfe_bus_ver3_update_ubwc_regs( CAM_DBG(CAM_ISP, "WM:%d meta stride 0x%X", wm_data->index, reg_val_pair[*j-1]); + if (wm_data->common_data->disable_ubwc_comp) + wm_data->ubwc_mode_cfg &= ~(0x1<<1); + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, ubwc_regs->mode_cfg, wm_data->ubwc_mode_cfg); CAM_DBG(CAM_ISP, "WM:%d ubwc_mode_cfg 0x%X", @@ -3839,6 +3846,10 @@ static int cam_vfe_bus_ver3_process_cmd( bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + bus_priv->common_data.disable_ubwc_comp = true; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3913,6 +3924,7 @@ int cam_vfe_bus_ver3_init( bus_priv->common_data.is_lite = soc_private->is_ife_lite; bus_priv->common_data.support_consumed_addr = ver3_hw_info->support_consumed_addr; + bus_priv->common_data.disable_ubwc_comp = false; for (i = 0; i < CAM_VFE_BUS_VER3_SRC_GRP_MAX; i++) bus_priv->common_data.rup_irq_handle[i] = 0; From 2c95c5a40b884f49fcd55622ef504e97a3b99033 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Tue, 23 Jun 2020 10:48:35 +0530 Subject: [PATCH 535/790] msm: camera: csid: Increment error count for ERROR_CRC and ERROR_ECC This change will help recovring from multiple CRC and ECC errors. CRs-Fixed: 2715172 Change-Id: Ie76703a100b1b90b3bf8a9c47deac1a5d5654c00 Signed-off-by: Vikram Sharma --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 1f9749b2b34a..d47a94ab7c08 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4699,16 +4699,19 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CSID_CSI2_RX_ERROR_CPHY_PH_CRC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC", csid_hw->hw_intf->hw_idx); + csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CRC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC", csid_hw->hw_intf->hw_idx); + csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_ECC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC", csid_hw->hw_intf->hw_idx); + csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) { From 49ea8fb393b904b9b277aedffc9097e30c56052f Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 1 Oct 2020 16:27:51 +0530 Subject: [PATCH 536/790] msm: camera: reqmgr: Fix for apply stuck issue for pd 1 device In a edge case if there are only pd 1 devices then avoid reset slot if last buf done req if last applied req. If rd_idx is equal to last bufdone index then reset previous slot. Based on max PD in the link calculate max retry attempt before triggering recovery to UMD. Also fill trigger information during notify error. CRs-Fixed: 2776184 Change-Id: Ifabf660df7861b78e7801dc7eebe0c5e71908e74 Signed-off-by: Wyes Karny --- drivers/cam_req_mgr/cam_req_mgr_core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index ee3972096998..5881df747c2a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1594,6 +1594,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_session *session; struct cam_req_mgr_connected_device *dev; struct cam_req_mgr_core_link *tmp_link = NULL; + uint32_t max_retry = 0; in_q = link->req.in_q; session = (struct cam_req_mgr_core_session *)link->parent; @@ -1700,6 +1701,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (rc < 0) { /* Apply req failed retry at next sof */ slot->status = CRM_SLOT_STATUS_REQ_PENDING; + max_retry = MAXIMUM_RETRY_ATTEMPTS; + if (link->max_delay == 1) + max_retry++; if (jiffies_to_msecs(jiffies - link->last_applied_jiffies) > MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS) @@ -1707,10 +1711,10 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if ((in_q->last_applied_idx < in_q->rd_idx) && check_retry_cnt) { link->retry_cnt++; - if (link->retry_cnt == MAXIMUM_RETRY_ATTEMPTS) { + if (link->retry_cnt == max_retry) { CAM_DBG(CAM_CRM, - "Max retry attempts reached on link[0x%x] for req [%lld]", - link->link_hdl, + "Max retry attempts (count %d) reached on link[0x%x] for req [%lld]", + max_retry, link->link_hdl, in_q->slot[in_q->rd_idx].req_id); __cam_req_mgr_notify_error_on_link(link, dev); link->retry_cnt = 0; @@ -2805,6 +2809,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) if (idx >= 0) { if (idx == in_q->last_applied_idx) in_q->last_applied_idx = -1; + if (idx == in_q->rd_idx) + __cam_req_mgr_dec_idx(&idx, 1, in_q->num_slots); __cam_req_mgr_reset_req_slot(link, idx); } } @@ -3034,6 +3040,7 @@ static int cam_req_mgr_cb_notify_err( notify_err->link_hdl = err_info->link_hdl; notify_err->dev_hdl = err_info->dev_hdl; notify_err->error = err_info->error; + notify_err->trigger = err_info->trigger; task->process_cb = &cam_req_mgr_process_error; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); From 1232bfaa25993d5f3cae6e8d7cb6902b919a649b Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 16 Sep 2020 10:36:23 -0700 Subject: [PATCH 537/790] msm: camera: isp: Add support for SFE HW layer in ISP driver Add support for SFE TOP, SFE BUS_WR & SFE BUS_RD in ISP driver. CRs-Fixed: 2733230 Change-Id: I85d356d28879b5cf9144a459fcdbd9f57526fa91 Signed-off-by: Karthik Anantha Ram --- config/waipiocamera.conf | 10 + config/waipiocameraconf.h | 11 + drivers/Makefile | 12 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 22 +- .../isp_hw/include/cam_sfe_hw_intf.h | 95 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h | 695 ++++++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c | 367 ++- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h | 32 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c | 166 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h | 24 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c | 106 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h | 2 +- .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c | 91 + .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c | 1144 ++++++++++ .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h | 115 + .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c | 1995 +++++++++++++++++ .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h | 181 ++ .../sfe_hw/sfe_bus/include/cam_sfe_bus.h | 99 + .../isp_hw/sfe_hw/sfe_top/cam_sfe_top.c | 682 ++++++ .../isp_hw/sfe_hw/sfe_top/cam_sfe_top.h | 102 + drivers/camera_main.c | 4 + drivers/camera_main.h | 6 + 22 files changed, 5787 insertions(+), 174 deletions(-) create mode 100644 config/waipiocamera.conf create mode 100644 config/waipiocameraconf.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h diff --git a/config/waipiocamera.conf b/config/waipiocamera.conf new file mode 100644 index 000000000000..407c5956ddd2 --- /dev/null +++ b/config/waipiocamera.conf @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2020, The Linux Foundation. All rights reserved. + +export CONFIG_SPECTRA_CAMERA=m + +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SFE=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y diff --git a/config/waipiocameraconf.h b/config/waipiocameraconf.h new file mode 100644 index 000000000000..91cfae4d85da --- /dev/null +++ b/config/waipiocameraconf.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SFE 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 diff --git a/drivers/Makefile b/drivers/Makefile index b4cd9bb27356..7a7b0250f03f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -85,6 +85,13 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.o \ cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.o \ cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.o \ + cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \ cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \ @@ -97,11 +104,6 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/cam_isp_dev.o \ cam_isp/cam_isp_context.o -camera-$(CONFIG_SPECTRA_SFE) += \ - cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.o \ - cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.o \ - cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.o - camera-$(CONFIG_SPECTRA_ICP) += \ cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.o \ cam_icp/icp_hw/ipe_hw/ipe_dev.o \ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 637257baeb76..e01bfeb20b5a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -86,6 +86,9 @@ enum cam_isp_resource_type { CAM_ISP_RESOURCE_TPG, CAM_ISP_RESOURCE_TFE_IN, CAM_ISP_RESOURCE_TFE_OUT, + CAM_ISP_RESOURCE_SFE_IN, + CAM_ISP_RESOURCE_SFE_RD, + CAM_ISP_RESOURCE_SFE_OUT, CAM_ISP_RESOURCE_MAX, }; @@ -131,6 +134,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, CAM_ISP_HW_CMD_DISABLE_UBWC_COMP, + CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG, CAM_ISP_HW_CMD_MAX, }; @@ -245,6 +249,10 @@ struct cam_isp_hw_cmd_buf_update { * @ num_buf: Number of buffers in the image_buf array * @ frame_header: frame header iova * @ local_id: local id for the wm + * @ width: width of scratch buffer + * @ height: height of scratch buffer + * @ stride: stride of scratch buffer + * @ slice_height: slice height of scratch buffer * @ io_cfg: IO buffer config information sent from UMD * */ @@ -254,6 +262,10 @@ struct cam_isp_hw_get_wm_update { uint32_t num_buf; uint64_t frame_header; uint32_t local_id; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t slice_height; struct cam_buf_io_cfg *io_cfg; }; @@ -276,10 +288,11 @@ struct cam_isp_hw_get_res_for_mid { * * @Brief: Get cmd buffer update for different CMD types * - * @res: Resource node - * @cmd_type: Command type for which to get update - * @cdm_id : CDM id - * @cmd: Command buffer information + * @res: Resource node + * @cmd_type: Command type for which to get update + * @cdm_id: CDM id + * @cmd: Command buffer information + * @use_scratch_cfg: To indicate if it's scratch buffer config * */ struct cam_isp_hw_get_cmd_update { @@ -287,6 +300,7 @@ struct cam_isp_hw_get_cmd_update { enum cam_isp_hw_cmd_type cmd_type; enum cam_cdm_id cdm_id; struct cam_isp_hw_cmd_buf_update cmd; + bool use_scratch_cfg; union { void *data; struct cam_isp_hw_get_wm_update *wm_update; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h index 8fab99e2128b..55f76f30f38a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h @@ -8,8 +8,9 @@ #include "cam_isp_hw.h" -#define CAM_SFE_HW_NUM_MAX 2 -#define SFE_CORE_BASE_IDX 0 +#define SFE_CORE_BASE_IDX 0 +#define SFE_RT_CDM_BASE_IDX 1 +#define CAM_SFE_HW_NUM_MAX 2 enum cam_isp_hw_sfe_in { CAM_ISP_HW_SFE_IN_PIX, @@ -32,6 +33,86 @@ enum cam_sfe_hw_irq_status { CAM_SFE_IRQ_STATUS_MAX, }; +enum cam_sfe_bw_control_action { + CAM_SFE_BW_CONTROL_EXCLUDE, + CAM_SFE_BW_CONTROL_INCLUDE, +}; + +enum cam_sfe_hw_irq_regs { + CAM_SFE_IRQ_TOP_REG_STATUS0, + CAM_SFE_IRQ_REGISTERS_MAX, +}; + +enum cam_sfe_bus_irq_regs { + CAM_SFE_IRQ_BUS_REG_STATUS0, + CAM_SFE_BUS_IRQ_REGISTERS_MAX, +}; + +/* + * struct cam_sfe_fe_update_args: + * + * @node_res: Resource to get fetch configuration + * @fe_config: fetch engine configuration + * + */ +struct cam_sfe_fe_update_args { + struct cam_isp_resource_node *node_res; + struct cam_fe_config fe_config; +}; + +/* + * struct cam_sfe_clock_update_args: + * + * @node_res: ISP Resource + * @clk_rate: Clock rate requested + */ +struct cam_sfe_clock_update_args { + struct cam_isp_resource_node *node_res; + uint64_t clk_rate; +}; + +/* + * struct cam_sfe_core_config_args: + * + * @node_res: ISP Resource + * @core_config: Core config for SFE + */ +struct cam_sfe_core_config_args { + struct cam_isp_resource_node *node_res; + struct cam_isp_sfe_core_config core_config; +}; + +/* + * struct cam_sfe_irq_evt_payload: + * + * @Brief: This structure is used to save payload for IRQ + * related to SFE resources + * + * @list: list_head node for the payload + * @core_index: Index of SFE HW that generated this IRQ event + * @evt_id: IRQ event + * @irq_reg_val: IRQ and Error register values, read when IRQ was + * handled + * @bus_irq_val Bus irq register status + * @ccif_violation_status ccif violation status + * @overflow_status bus overflow status + * @image_size_vio_sts image size violations status + * @error_type: Identify different errors + * @ts: Timestamp + */ +struct cam_sfe_irq_evt_payload { + struct list_head list; + uint32_t core_index; + uint32_t evt_id; + uint32_t irq_reg_val[CAM_SFE_IRQ_REGISTERS_MAX]; + uint32_t bus_irq_val[CAM_SFE_BUS_IRQ_REGISTERS_MAX]; + uint32_t ccif_violation_status; + uint32_t overflow_status; + uint32_t image_size_vio_sts; + uint32_t error_type; + struct cam_isp_timestamp ts; +}; + /* * struct cam_sfe_hw_get_hw_cap: * @@ -54,18 +135,18 @@ struct cam_sfe_hw_get_hw_cap { * is successful * @res_id: Unique Identity of port to associate with this * resource. - * @is_dual: Flag to indicate dual SFE usecase * @cdm_ops: CDM operations * @unpacket_fmt: Unpacker format for read engine * @is_offline: Flag to indicate offline usecase + * @secure_mode: If fetch is from secure/non-secure buffer */ struct cam_sfe_hw_sfe_bus_rd_acquire_args { struct cam_isp_resource_node *rsrc_node; uint32_t res_id; - uint32_t is_dual; struct cam_cdm_utils_ops *cdm_ops; uint32_t unpacker_fmt; bool is_offline; + bool secure_mode; }; /* @@ -77,9 +158,7 @@ struct cam_sfe_hw_sfe_bus_rd_acquire_args { * resource. * @cdm_ops: CDM operations * @is_dual: Dual mode usecase - * @sync_mode: If in dual mode, indicates master/slave * @in_port: in port info - * @is_fe_enabled: Flag to indicate if FE is enabled * @is_offline: Flag to indicate Offline IFE */ struct cam_sfe_hw_sfe_in_acquire_args { @@ -87,9 +166,7 @@ struct cam_sfe_hw_sfe_in_acquire_args { uint32_t res_id; struct cam_cdm_utils_ops *cdm_ops; uint32_t is_dual; - enum cam_isp_hw_sync_mode sync_mode; struct cam_isp_in_port_generic_info *in_port; - bool is_fe_enabled; bool is_offline; }; @@ -126,6 +203,7 @@ struct cam_sfe_hw_sfe_out_acquire_args { * with this resource. * @priv: Context data * @event_cb: Callback function to hw mgr in case of hw events + * @buf_done_controller: Buf done controller * @sfe_out: Acquire args for SFE_OUT * @sfe_bus_rd Acquire args for SFE_BUS_READ * @sfe_in: Acquire args for SFE_IN @@ -135,6 +213,7 @@ struct cam_sfe_acquire_args { void *tasklet; void *priv; cam_hw_mgr_event_cb_func event_cb; + void *buf_done_controller; union { struct cam_sfe_hw_sfe_out_acquire_args sfe_out; struct cam_sfe_hw_sfe_in_acquire_args sfe_in; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h new file mode 100644 index 000000000000..2da1d3f35d57 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h @@ -0,0 +1,695 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE680_H_ +#define _CAM_SFE680_H_ +#include "cam_sfe_core.h" +#include "cam_sfe_bus.h" +#include "cam_sfe_bus_rd.h" +#include "cam_sfe_bus_wr.h" + +static struct cam_sfe_top_common_reg_offset sfe680_top_commong_reg = { + .hw_version = 0x00000000, + .hw_capability = 0x00000004, + .stats_feature = 0x00000008, + .core_cgc_ctrl = 0x00000010, + .ahb_clk_ovd = 0x00000014, + .core_cfg = 0x00000018, + .violation_status = 0x00000030, + .diag_config = 0x00000034, + .diag_sensor_status_0 = 0x00000038, + .diag_sensor_status_1 = 0x0000003C, + .diag_sensor_frame_cnt_status0 = 0x00000040, + .diag_sensor_frame_cnt_status1 = 0x00000044, + .top_debug_0 = 0x0000004C, + .top_debug_1 = 0x00000050, + .top_debug_2 = 0x00000054, + .top_debug_3 = 0x00000058, + .top_debug_4 = 0x0000005C, + .top_debug_5 = 0x00000060, + .top_debug_6 = 0x00000064, + .top_debug_7 = 0x00000068, + .top_debug_8 = 0x0000006C, + .top_debug_9 = 0x00000070, + .top_debug_10 = 0x00000074, + .top_debug_11 = 0x00000078, + .top_debug_cfg = 0x0000007C, + .stats_ch2_throttle_cfg = 0x000000B0, + .stats_ch1_throttle_cfg = 0x000000B4, + .stats_ch0_throttle_cfg = 0x000000B8, + .lcr_throttle_cfg = 0x000000BC, + .hdr_throttle_cfg = 0x000000C0, + .sfe_op_throttle_cfg = 0x000000C4, +}; + +static struct cam_sfe_modules_common_reg_offset sfe680_modules_common_reg = { + .demux_module_cfg = 0x00003060, + .demux_qcfa_cfg = 0x00003064, + .demux_hdr_cfg = 0x00003074, + .demux_lcr_sel = 0x00003078, + .hdrc_remo_mod_cfg = 0x00005860, + .hdrc_remo_qcfa_bin_cfg = 0x00005A78, + .qcfa_hdrc_remo_out_mux_cfg = 0x00005A74, +}; + +static struct cam_sfe_path_common_reg_data sfe_680_pix_reg_data = { + .sof_irq_mask = 0x4, + .eof_irq_mask = 0x8, + .error_irq_mask = 0x1C000, + .subscribe_irq_mask = 0xC, + .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x3, +}; + +static struct cam_sfe_path_common_reg_data sfe_680_rdi0_reg_data = { + .sof_irq_mask = 0x10, + .eof_irq_mask = 0x20, + .error_irq_mask = 0x1C000, + .subscribe_irq_mask = 0x30, + .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x3, +}; + +static struct cam_sfe_path_common_reg_data sfe_680_rdi1_reg_data = { + .sof_irq_mask = 0x40, + .eof_irq_mask = 0x80, + .error_irq_mask = 0x1C000, + .subscribe_irq_mask = 0xC0, + .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x3, +}; + +static struct cam_sfe_path_common_reg_data sfe_680_rdi2_reg_data = { + .sof_irq_mask = 0x100, + .eof_irq_mask = 0x200, + .error_irq_mask = 0x1C000, + .subscribe_irq_mask = 0x300, + .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x3, +}; + +static struct cam_sfe_path_common_reg_data sfe_680_rdi3_reg_data = { + .sof_irq_mask = 0x400, + .eof_irq_mask = 0x800, + .error_irq_mask = 0x1C000, + .subscribe_irq_mask = 0xC00, + .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x3, +}; + +static struct cam_sfe_path_common_reg_data sfe_680_rdi4_reg_data = { + .sof_irq_mask = 0x1000, + .eof_irq_mask = 0x2000, + .error_irq_mask = 0x1C000, + .subscribe_irq_mask = 0x3000, + .enable_diagnostic_hw = 0x1, + .top_debug_cfg_en = 0x3, +}; + +static struct cam_sfe_top_hw_info sfe680_top_hw_info = { + .common_reg = &sfe680_top_commong_reg, + .modules_hw_info = &sfe680_modules_common_reg, + .pix_reg_data = &sfe_680_pix_reg_data, + .rdi_reg_data[0] = &sfe_680_rdi0_reg_data, + .rdi_reg_data[1] = &sfe_680_rdi1_reg_data, + .rdi_reg_data[2] = &sfe_680_rdi2_reg_data, + .rdi_reg_data[3] = &sfe_680_rdi3_reg_data, + .rdi_reg_data[4] = &sfe_680_rdi4_reg_data, + .num_inputs = 6, + .input_type = { + CAM_SFE_PIX_VER_1_0, + CAM_SFE_RDI_VER_1_0, + CAM_SFE_RDI_VER_1_0, + CAM_SFE_RDI_VER_1_0, + CAM_SFE_RDI_VER_1_0, + CAM_SFE_RDI_VER_1_0, + }, +}; + +static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = { + .common_reg = { + .hw_version = 0x00000400, + .misr_reset = 0x0000041C, + .pwr_iso_cfg = 0x00000424, + .input_if_cmd = 0x00000414, + .test_bus_ctrl = 0x0000042C, + .security_cfg = 0x00000420, + }, + .num_client = 3, + .bus_client_reg = { + /* BUS Client 0 */ + { + .cfg = 0x00000450, + .image_addr = 0x00000458, + .buf_width = 0x0000045C, + .buf_height = 0x00000460, + .stride = 0x00000464, + .unpacker_cfg = 0x00000468, + .latency_buf_allocation = 0x0000047C, + }, + /* BUS Client 1 */ + { + .cfg = 0x000004F0, + .image_addr = 0x000004F8, + .buf_width = 0x000004FC, + .buf_height = 0x00000500, + .stride = 0x00000504, + .unpacker_cfg = 0x00000508, + .latency_buf_allocation = 0x0000051C, + }, + /* BUS Client 2 */ + { + .cfg = 0x00000590, + .image_addr = 0x00000598, + .buf_width = 0x0000059C, + .buf_height = 0x000005A0, + .stride = 0x000005A4, + .unpacker_cfg = 0x000005A8, + .latency_buf_allocation = 0x000005BC, + }, + }, + .num_bus_rd_resc = 3, + .sfe_bus_rd_info = { + { + .sfe_bus_rd_type = CAM_SFE_BUS_RD_RDI0, + .max_width = -1, + .max_height = -1, + }, + { + .sfe_bus_rd_type = CAM_SFE_BUS_RD_RDI1, + .max_width = -1, + .max_height = -1, + }, + { + .sfe_bus_rd_type = CAM_SFE_BUS_RD_RDI2, + .max_width = -1, + .max_height = -1, + }, + }, + .top_irq_shift = 0x1, +}; + +static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { + .common_reg = { + .hw_version = 0x00000800, + .cgc_ovd = 0x00000808, + .if_frameheader_cfg = { + 0x00000834, + 0x00000838, + 0x0000083C, + 0x00000840, + 0x00000844, + 0x00000848, + }, + .pwr_iso_cfg = 0x0000085C, + .overflow_status_clear = 0x00000860, + .ccif_violation_status = 0x00000864, + .overflow_status = 0x00000868, + .image_size_violation_status = 0x00000870, + .debug_status_top_cfg = 0x000008D4, + .debug_status_top = 0x000008D8, + .test_bus_ctrl = 0x000008DC, + .top_irq_mask_0 = 0x00000818, + }, + .num_client = 13, + .bus_client_reg = { + /* BUS Client 0 REMOSAIC */ + { + .cfg = 0x00000A00, + .image_addr = 0x00000A04, + .frame_incr = 0x00000A08, + .image_cfg_0 = 0x00000A0C, + .image_cfg_1 = 0x00000A10, + .image_cfg_2 = 0x00000A14, + .packer_cfg = 0x00000A18, + .frame_header_addr = 0x00000A20, + .frame_header_incr = 0x00000A24, + .frame_header_cfg = 0x00000A28, + .line_done_cfg = 0, + .irq_subsample_period = 0x00000A30, + .irq_subsample_pattern = 0x00000A34, + .framedrop_period = 0x00000A38, + .framedrop_pattern = 0x00000A3C, + .system_cache_cfg = 0x00000A68, + .addr_status_0 = 0x00000A70, + .addr_status_1 = 0x00000A74, + .addr_status_2 = 0x00000A78, + .addr_status_3 = 0x00000A7C, + .debug_status_cfg = 0x00000A80, + .debug_status_0 = 0x00000A84, + .debug_status_1 = 0x00000A88, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_0, + }, + /* BUS Client 1 LCR */ + { + .cfg = 0x00000B00, + .image_addr = 0x00000B04, + .frame_incr = 0x00000B08, + .image_cfg_0 = 0x00000B0C, + .image_cfg_1 = 0x00000B10, + .image_cfg_2 = 0x00000B14, + .packer_cfg = 0x00000B18, + .frame_header_addr = 0x00000B20, + .frame_header_incr = 0x00000B24, + .frame_header_cfg = 0x00000B28, + .line_done_cfg = 0, + .irq_subsample_period = 0x00000B30, + .irq_subsample_pattern = 0x00000B34, + .framedrop_period = 0x00000B38, + .framedrop_pattern = 0x00000B3C, + .system_cache_cfg = 0x00000B68, + .addr_status_0 = 0x00000B70, + .addr_status_1 = 0x00000B74, + .addr_status_2 = 0x00000B78, + .addr_status_3 = 0x00000B7C, + .debug_status_cfg = 0x00000B80, + .debug_status_0 = 0x00000B84, + .debug_status_1 = 0x00000B88, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_1, + }, + /* BUS Client 2 STATS_BE_0 */ + { + .cfg = 0x00000C00, + .image_addr = 0x00000C04, + .frame_incr = 0x00000C08, + .image_cfg_0 = 0x00000C0C, + .image_cfg_1 = 0x00000C10, + .image_cfg_2 = 0x00000C14, + .packer_cfg = 0x00000C18, + .frame_header_addr = 0x00000C20, + .frame_header_incr = 0x00000C24, + .frame_header_cfg = 0x00000C28, + .line_done_cfg = 0, + .irq_subsample_period = 0x00000C30, + .irq_subsample_pattern = 0x00000C34, + .framedrop_period = 0x00000C38, + .framedrop_pattern = 0x00000C3C, + .system_cache_cfg = 0x00000C68, + .addr_status_0 = 0x00000C70, + .addr_status_1 = 0x00000C74, + .addr_status_2 = 0x00000C78, + .addr_status_3 = 0x00000C7C, + .debug_status_cfg = 0x00000C80, + .debug_status_0 = 0x00000C84, + .debug_status_1 = 0x00000C88, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_2, + }, + /* BUS Client 3 STATS_BHIST_0 */ + { + .cfg = 0x00000D00, + .image_addr = 0x00000D04, + .frame_incr = 0x00000D08, + .image_cfg_0 = 0x00000D0C, + .image_cfg_1 = 0x00000D10, + .image_cfg_2 = 0x00000D14, + .packer_cfg = 0x00000D18, + .frame_header_addr = 0x00000D20, + .frame_header_incr = 0x00000D24, + .frame_header_cfg = 0x00000D28, + .line_done_cfg = 0, + .irq_subsample_period = 0x00000D30, + .irq_subsample_pattern = 0x00000D34, + .framedrop_period = 0x00000D38, + .framedrop_pattern = 0x00000D3C, + .system_cache_cfg = 0x00000D68, + .addr_status_0 = 0x00000D70, + .addr_status_1 = 0x00000D74, + .addr_status_2 = 0x00000D78, + .addr_status_3 = 0x00000D7C, + .debug_status_cfg = 0x00000D80, + .debug_status_0 = 0x00000D84, + .debug_status_1 = 0x00000D88, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_2, + }, + /* BUS Client 4 STATS_BE_1 */ + { + .cfg = 0x00000E00, + .image_addr = 0x00000E04, + .frame_incr = 0x00000E08, + .image_cfg_0 = 0x00000E0C, + .image_cfg_1 = 0x00000E10, + .image_cfg_2 = 0x00000E14, + .packer_cfg = 0x00000E18, + .frame_header_addr = 0x00000E20, + .frame_header_incr = 0x00000E24, + .frame_header_cfg = 0x00000E28, + .line_done_cfg = 0, + .irq_subsample_period = 0x00000E30, + .irq_subsample_pattern = 0x00000E34, + .framedrop_period = 0x00000E38, + .framedrop_pattern = 0x00000E3C, + .system_cache_cfg = 0x00000E68, + .addr_status_0 = 0x00000E70, + .addr_status_1 = 0x00000E74, + .addr_status_2 = 0x00000E78, + .addr_status_3 = 0x00000E7C, + .debug_status_cfg = 0x00000E80, + .debug_status_0 = 0x00000E84, + .debug_status_1 = 0x00000E88, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_3, + }, + /* BUS Client 5 STATS_BHIST_1 */ + { + .cfg = 0x00000F00, + .image_addr = 0x00000F04, + .frame_incr = 0x00000F08, + .image_cfg_0 = 0x00000F0C, + .image_cfg_1 = 0x00000F10, + .image_cfg_2 = 0x00000F14, + .packer_cfg = 0x00000F18, + .frame_header_addr = 0x00000F20, + .frame_header_incr = 0x00000F24, + .frame_header_cfg = 0x00000F28, + .line_done_cfg = 0, + .irq_subsample_period = 0x00000F30, + .irq_subsample_pattern = 0x00000F34, + .framedrop_period = 0x00000F38, + .framedrop_pattern = 0x00000F3C, + .system_cache_cfg = 0x00000F68, + .addr_status_0 = 0x00000F70, + .addr_status_1 = 0x00000F74, + .addr_status_2 = 0x00000F78, + .addr_status_3 = 0x00000F7C, + .debug_status_cfg = 0x00000F80, + .debug_status_0 = 0x00000F84, + .debug_status_1 = 0x00000F88, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_3, + }, + /* BUS Client 6 STATS_BE_2 */ + { + .cfg = 0x00001000, + .image_addr = 0x00001004, + .frame_incr = 0x00001008, + .image_cfg_0 = 0x0000100C, + .image_cfg_1 = 0x00001010, + .image_cfg_2 = 0x00001014, + .packer_cfg = 0x00001018, + .frame_header_addr = 0x00001020, + .frame_header_incr = 0x00001024, + .frame_header_cfg = 0x00001028, + .line_done_cfg = 0, + .irq_subsample_period = 0x00001030, + .irq_subsample_pattern = 0x00001034, + .framedrop_period = 0x00001038, + .framedrop_pattern = 0x0000103C, + .system_cache_cfg = 0x00001068, + .addr_status_0 = 0x00001070, + .addr_status_1 = 0x00001074, + .addr_status_2 = 0x00001078, + .addr_status_3 = 0x0000107C, + .debug_status_cfg = 0x00001080, + .debug_status_0 = 0x00001084, + .debug_status_1 = 0x00001088, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_4, + }, + /* BUS Client 7 STATS_BHIST_2 */ + { + .cfg = 0x00001100, + .image_addr = 0x00001104, + .frame_incr = 0x00001108, + .image_cfg_0 = 0x0000110C, + .image_cfg_1 = 0x00001110, + .image_cfg_2 = 0x00001114, + .packer_cfg = 0x00001118, + .frame_header_addr = 0x00001120, + .frame_header_incr = 0x00001124, + .frame_header_cfg = 0x00001128, + .line_done_cfg = 0, + .irq_subsample_period = 0x00001130, + .irq_subsample_pattern = 0x00001134, + .framedrop_period = 0x00001138, + .framedrop_pattern = 0x0000113C, + .system_cache_cfg = 0x00001168, + .addr_status_0 = 0x00001170, + .addr_status_1 = 0x00001174, + .addr_status_2 = 0x00001178, + .addr_status_3 = 0x0000117C, + .debug_status_cfg = 0x00001180, + .debug_status_0 = 0x00001184, + .debug_status_1 = 0x00001188, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_4, + }, + /* BUS Client 8 RDI0 */ + { + .cfg = 0x00001200, + .image_addr = 0x00001204, + .frame_incr = 0x00001208, + .image_cfg_0 = 0x0000120C, + .image_cfg_1 = 0x00001210, + .image_cfg_2 = 0x00001214, + .packer_cfg = 0x00001218, + .frame_header_addr = 0x00001220, + .frame_header_incr = 0x00001224, + .frame_header_cfg = 0x00001228, + .line_done_cfg = 0x0000122C, + .irq_subsample_period = 0x00001230, + .irq_subsample_pattern = 0x00001234, + .framedrop_period = 0x00001238, + .framedrop_pattern = 0x0000123C, + .system_cache_cfg = 0x00001268, + .addr_status_0 = 0x00001270, + .addr_status_1 = 0x00001274, + .addr_status_2 = 0x00001278, + .addr_status_3 = 0x0000127C, + .debug_status_cfg = 0x00001280, + .debug_status_0 = 0x00001284, + .debug_status_1 = 0x00001288, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_5, + }, + /* BUS Client 9 RDI1 */ + { + .cfg = 0x00001300, + .image_addr = 0x00001304, + .frame_incr = 0x00001308, + .image_cfg_0 = 0x0000130C, + .image_cfg_1 = 0x00001310, + .image_cfg_2 = 0x00001314, + .packer_cfg = 0x00001318, + .frame_header_addr = 0x00001320, + .frame_header_incr = 0x00001324, + .frame_header_cfg = 0x00001328, + .line_done_cfg = 0x0000132C, + .irq_subsample_period = 0x00001330, + .irq_subsample_pattern = 0x00001334, + .framedrop_period = 0x00001338, + .framedrop_pattern = 0x0000133C, + .system_cache_cfg = 0x00001368, + .addr_status_0 = 0x00001370, + .addr_status_1 = 0x00001374, + .addr_status_2 = 0x00001378, + .addr_status_3 = 0x0000137C, + .debug_status_cfg = 0x00001380, + .debug_status_0 = 0x00001384, + .debug_status_1 = 0x00001388, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_6, + }, + /* BUS Client 10 RDI2 */ + { + .cfg = 0x00001400, + .image_addr = 0x00001404, + .frame_incr = 0x00001408, + .image_cfg_0 = 0x0000140C, + .image_cfg_1 = 0x00001410, + .image_cfg_2 = 0x00001414, + .packer_cfg = 0x00001418, + .frame_header_addr = 0x00001420, + .frame_header_incr = 0x00001424, + .frame_header_cfg = 0x00001428, + .line_done_cfg = 0x0000142C, + .irq_subsample_period = 0x00001430, + .irq_subsample_pattern = 0x00001434, + .framedrop_period = 0x00001438, + .framedrop_pattern = 0x0000143C, + .system_cache_cfg = 0x00001468, + .addr_status_0 = 0x00001470, + .addr_status_1 = 0x00001474, + .addr_status_2 = 0x00001478, + .addr_status_3 = 0x0000147C, + .debug_status_cfg = 0x00001480, + .debug_status_0 = 0x00001484, + .debug_status_1 = 0x00001488, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_7, + }, + /* BUS Client 11 RDI3 */ + { + .cfg = 0x00001500, + .image_addr = 0x00001504, + .frame_incr = 0x00001508, + .image_cfg_0 = 0x0000150C, + .image_cfg_1 = 0x00001510, + .image_cfg_2 = 0x00001514, + .packer_cfg = 0x00001518, + .frame_header_addr = 0x00001520, + .frame_header_incr = 0x00001524, + .frame_header_cfg = 0x00001528, + .line_done_cfg = 0x0000152C, + .irq_subsample_period = 0x00001530, + .irq_subsample_pattern = 0x00001534, + .framedrop_period = 0x00001538, + .framedrop_pattern = 0x0000153C, + .system_cache_cfg = 0x00001568, + .addr_status_0 = 0x00001570, + .addr_status_1 = 0x00001574, + .addr_status_2 = 0x00001578, + .addr_status_3 = 0x0000157C, + .debug_status_cfg = 0x00001580, + .debug_status_0 = 0x00001584, + .debug_status_1 = 0x00001588, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_8, + }, + /* BUS Client 12 RDI4 */ + { + .cfg = 0x00001600, + .image_addr = 0x00001604, + .frame_incr = 0x00001608, + .image_cfg_0 = 0x0000160C, + .image_cfg_1 = 0x00001610, + .image_cfg_2 = 0x00001614, + .packer_cfg = 0x00001618, + .frame_header_addr = 0x00001620, + .frame_header_incr = 0x00001624, + .frame_header_cfg = 0x00001628, + .line_done_cfg = 0x0000162C, + .irq_subsample_period = 0x00001630, + .irq_subsample_pattern = 0x00001634, + .framedrop_period = 0x00001638, + .framedrop_pattern = 0x0000163C, + .system_cache_cfg = 0x00001668, + .addr_status_0 = 0x00001670, + .addr_status_1 = 0x00001674, + .addr_status_2 = 0x00001678, + .addr_status_3 = 0x0000167C, + .debug_status_cfg = 0x00001680, + .debug_status_0 = 0x00001684, + .debug_status_1 = 0x00001688, + .comp_group = CAM_SFE_BUS_WR_COMP_GRP_9, + }, + }, + .num_out = 13, + .sfe_out_hw_info = { + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_RDI0, + .max_width = -1, + .max_height = -1, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_1, + .num_wm = 1, + .wm_idx = 8, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_RDI1, + .max_width = -1, + .max_height = -1, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_2, + .num_wm = 1, + .wm_idx = 9, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_RDI2, + .max_width = -1, + .max_height = -1, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_3, + .num_wm = 1, + .wm_idx = 10, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_RDI3, + .max_width = -1, + .max_height = -1, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_4, + .num_wm = 1, + .wm_idx = 11, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_RDI4, + .max_width = -1, + .max_height = -1, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_4, + .num_wm = 1, + .wm_idx = 12, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_RAW_DUMP, + .max_width = 9312, + .max_height = 6992, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 0, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_LCR, + .max_width = 9312, + .max_height = 2048, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 1, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_BE_0, + .max_width = 7296, + .max_height = 5472, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 2, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_BHIST_0, + .max_width = 7296, + .max_height = 5472, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 3, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_BE_1, + .max_width = 7296, + .max_height = 5472, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 4, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_BHIST_1, + .max_width = 7296, + .max_height = 5472, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 5, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_BE_2, + .max_width = 7296, + .max_height = 5472, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 6, + }, + { + .sfe_out_type = CAM_SFE_BUS_SFE_OUT_BHIST_2, + .max_width = 7296, + .max_height = 5472, + .source_group = CAM_SFE_BUS_WR_SRC_GRP_0, + .num_wm = 1, + .wm_idx = 7, + }, + }, + .num_comp_grp = 10, + .comp_done_shift = 17, + .top_irq_shift = 0x0, +}; + +struct cam_sfe_hw_info cam_sfe680_hw_info = { + .irq_reg_info = NULL, + + .bus_wr_version = CAM_SFE_BUS_WR_VER_1_0, + .bus_wr_hw_info = &sfe680_bus_wr_hw_info, + + .bus_rd_version = CAM_SFE_BUS_RD_VER_1_0, + .bus_rd_hw_info = &sfe680_bus_rd_hw_info, + + .top_version = CAM_SFE_TOP_VER_1_0, + .top_hw_info = &sfe680_top_hw_info, +}; + +#endif /* _CAM_SFE680_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c index 73e29bee3c46..ca0220c10d22 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c @@ -12,12 +12,29 @@ #include "cam_debug_util.h" static const char drv_name[] = "sfe"; -#define SFE_CORE_BASE_IDX 0 -int cam_sfe_get_hw_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size) +int cam_sfe_get_hw_caps(void *device_priv, + void *get_hw_cap_args, uint32_t arg_size) { - CAM_DBG(CAM_SFE, "Enter"); - return 0; + return -EPERM; +} + +int cam_sfe_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_sfe_read(void *device_priv, + void *read_args, uint32_t arg_size) +{ + return -EPERM; +} + +int cam_sfe_write(void *device_priv, + void *write_args, uint32_t arg_size) +{ + return -EPERM; } int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) @@ -25,10 +42,8 @@ int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; - struct cam_isp_resource_node *isp_res = NULL; int rc = 0; - CAM_DBG(CAM_SFE, "Enter"); if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; @@ -38,7 +53,7 @@ int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) sfe_hw->open_count++; if (sfe_hw->open_count > 1) { mutex_unlock(&sfe_hw->hw_mutex); - CAM_DBG(CAM_SFE, "SFE has already been initialized cnt %d", + CAM_DBG(CAM_SFE, "SFE has already been initialized cnt: %d", sfe_hw->open_count); return 0; } @@ -55,30 +70,34 @@ int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) goto decrement_open_cnt; } - isp_res = (struct cam_isp_resource_node *)init_hw_args; - if (isp_res && isp_res->init) { - rc = isp_res->init(isp_res, NULL, 0); - if (rc) { - CAM_ERR(CAM_SFE, "init Failed rc=%d", rc); - goto disable_soc; - } + CAM_DBG(CAM_SFE, "SFE SOC resource enabled"); + + /* Async Reset as part of power ON */ + /* Sync Reset in CSID */ + + /* INIT SFE BUS WR */ + rc = core_info->sfe_bus_wr->hw_ops.init( + core_info->sfe_bus_wr->bus_priv, NULL, 0); + if (rc) { + CAM_ERR(CAM_SFE, + "SFE bus wr init failed rc: %d", rc); + goto disable_soc; } - CAM_DBG(CAM_SFE, "Enable soc done"); - - /* Do HW Reset */ - rc = cam_sfe_reset(hw_priv, NULL, 0); + /* INIT SFE BUS RD */ + rc = core_info->sfe_bus_rd->hw_ops.init( + core_info->sfe_bus_rd->bus_priv, NULL, 0); if (rc) { - CAM_ERR(CAM_SFE, "Reset Failed rc=%d", rc); - goto deinit_sfe_res; + CAM_ERR(CAM_SFE, "SFE bus rd init failed rc: %d", rc); + goto deinit_bus_wr; } sfe_hw->hw_state = CAM_HW_STATE_POWER_UP; return rc; -deinit_sfe_res: - if (isp_res && isp_res->deinit) - isp_res->deinit(isp_res, NULL, 0); +deinit_bus_wr: + core_info->sfe_bus_wr->hw_ops.deinit( + core_info->sfe_bus_wr->bus_priv, NULL, 0); disable_soc: cam_sfe_disable_soc_resources(soc_info); decrement_open_cnt: @@ -93,10 +112,8 @@ int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; - struct cam_isp_resource_node *isp_res = NULL; int rc = 0; - CAM_DBG(CAM_SFE, "Enter"); if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; @@ -105,13 +122,15 @@ int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) mutex_lock(&sfe_hw->hw_mutex); if (!sfe_hw->open_count) { mutex_unlock(&sfe_hw->hw_mutex); - CAM_ERR(CAM_SFE, "Error! Unbalanced deinit"); + CAM_ERR(CAM_SFE, "Unbalanced deinit"); return -EFAULT; } + sfe_hw->open_count--; if (sfe_hw->open_count) { mutex_unlock(&sfe_hw->hw_mutex); - CAM_DBG(CAM_SFE, "open_cnt non-zero =%d", sfe_hw->open_count); + CAM_DBG(CAM_SFE, "open_cnt non-zero: %d", + sfe_hw->open_count); return 0; } mutex_unlock(&sfe_hw->hw_mutex); @@ -119,63 +138,196 @@ int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; - isp_res = (struct cam_isp_resource_node *)deinit_hw_args; - if (isp_res && isp_res->deinit) { - rc = isp_res->deinit(isp_res, NULL, 0); - if (rc) - CAM_ERR(CAM_SFE, "deinit failed"); - } + rc = core_info->sfe_bus_wr->hw_ops.deinit( + core_info->sfe_bus_wr->bus_priv, NULL, 0); + if (rc) + CAM_ERR(CAM_SFE, "SFE bus wr deinit failed rc: %d", + rc); + + rc = core_info->sfe_bus_rd->hw_ops.deinit( + core_info->sfe_bus_rd->bus_priv, NULL, 0); + if (rc) + CAM_ERR(CAM_SFE, "SFE bus rd deinit failed rc: %d", + rc); /* Turn OFF Regulators, Clocks and other SOC resources */ - CAM_DBG(CAM_SFE, "Disable SOC resource"); + CAM_DBG(CAM_SFE, "Disable SFE SOC resource"); rc = cam_sfe_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_SFE, "Disable SOC failed"); sfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; - CAM_DBG(CAM_SFE, "Exit"); + CAM_DBG(CAM_SFE, "SFE deinit done rc: %d", rc); return rc; } -int cam_sfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) -{ - CAM_DBG(CAM_SFE, "Enter"); - return 0; -} - int cam_sfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) { - CAM_DBG(CAM_SFE, "Enter"); - return 0; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_sfe_acquire_args *acquire; + int rc = -ENODEV; + + if (!hw_priv || !reserve_args || (arg_size != + sizeof(struct cam_sfe_acquire_args))) { + CAM_ERR(CAM_SFE, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + acquire = (struct cam_sfe_acquire_args *)reserve_args; + + CAM_DBG(CAM_SFE, "SFE acquire for res type: %d", + acquire->rsrc_type); + + mutex_lock(&sfe_hw->hw_mutex); + if (acquire->rsrc_type == CAM_ISP_RESOURCE_SFE_IN) + rc = core_info->sfe_top->hw_ops.reserve( + core_info->sfe_top->top_priv, + reserve_args, arg_size); + else if (acquire->rsrc_type == CAM_ISP_RESOURCE_SFE_OUT) + rc = core_info->sfe_bus_wr->hw_ops.reserve( + core_info->sfe_bus_wr->bus_priv, acquire, + sizeof(*acquire)); + else if (acquire->rsrc_type == CAM_ISP_RESOURCE_SFE_RD) + rc = core_info->sfe_bus_rd->hw_ops.reserve( + core_info->sfe_bus_rd->bus_priv, acquire, + sizeof(*acquire)); + else + CAM_ERR(CAM_SFE, "Invalid SFE res_type: %d", + acquire->rsrc_type); + mutex_unlock(&sfe_hw->hw_mutex); + + return rc; } int cam_sfe_release(void *hw_priv, void *release_args, uint32_t arg_size) { - CAM_DBG(CAM_SFE, "Enter"); - return 0; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_isp_resource_node *sfe_res; + int rc = -ENODEV; + + if (!hw_priv || !release_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_SFE, "Invalid input arguments"); + return -EINVAL; + } + + core_info = (struct cam_sfe_hw_core_info *) sfe_hw->core_info; + sfe_res = (struct cam_isp_resource_node *) release_args; + + CAM_DBG(CAM_SFE, "SFE release for res type: %d", + sfe_res->res_type); + + mutex_lock(&sfe_hw->hw_mutex); + if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_IN) + rc = core_info->sfe_top->hw_ops.release( + core_info->sfe_top->top_priv, sfe_res, + sizeof(struct cam_isp_resource_node)); + else if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_OUT) + rc = core_info->sfe_bus_wr->hw_ops.release( + core_info->sfe_bus_wr->bus_priv, sfe_res, + sizeof(*sfe_res)); + else if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_RD) + rc = core_info->sfe_bus_rd->hw_ops.release( + core_info->sfe_bus_rd->bus_priv, sfe_res, + sizeof(*sfe_res)); + else + CAM_ERR(CAM_SFE, "Invalid SFE res type: %d", + sfe_res->res_type); + mutex_unlock(&sfe_hw->hw_mutex); + + return rc; } int cam_sfe_start(void *hw_priv, void *start_args, uint32_t arg_size) { - CAM_DBG(CAM_SFE, "Enter"); - return 0; + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_isp_resource_node *sfe_res; + struct cam_hw_soc_info *soc_info = NULL; + int rc; + + if (!hw_priv || !start_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_SFE, "Invalid input arguments"); + return -EINVAL; + } + + soc_info = &sfe_hw->soc_info; + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + sfe_res = (struct cam_isp_resource_node *)start_args; + core_info->tasklet_info = sfe_res->tasklet_info; + + mutex_lock(&sfe_hw->hw_mutex); + if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_IN) { + rc = core_info->sfe_top->hw_ops.start( + core_info->sfe_top->top_priv, sfe_res, + sizeof(struct cam_isp_resource_node)); + if (rc) + CAM_ERR(CAM_SFE, "Failed to start SFE IN rc: %d", rc); + } else if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_OUT) { + rc = core_info->sfe_bus_wr->hw_ops.start(sfe_res, NULL, 0); + if (rc) + CAM_ERR(CAM_SFE, "Failed to start SFE BUS WR rc: %d", + rc); + } else if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_RD) { + rc = core_info->sfe_bus_rd->hw_ops.start(sfe_res, + NULL, 0); + if (rc) + CAM_ERR(CAM_SFE, "Failed to start SFE BUS RD rc: %d", + rc); + } else { + CAM_ERR(CAM_SFE, "Invalid SFE res type:%d", + sfe_res->res_type); + rc = -EINVAL; + } + + mutex_unlock(&sfe_hw->hw_mutex); + CAM_DBG(CAM_SFE, + "Start for SFE res type: %u res id: %u res_state: %d rc: %d", + sfe_res->res_type, sfe_res->res_id, + sfe_res->res_state, rc); + return rc; } int cam_sfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { - CAM_DBG(CAM_SFE, "Enter"); - return 0; -} + struct cam_sfe_hw_core_info *core_info = NULL; + struct cam_hw_info *sfe_hw = hw_priv; + struct cam_isp_resource_node *sfe_res; + int rc = -EINVAL; -int cam_sfe_read(void *hw_priv, void *read_args, uint32_t arg_size) -{ - return -EPERM; -} + if (!hw_priv || !stop_args || + (arg_size != sizeof(struct cam_isp_resource_node))) { + CAM_ERR(CAM_SFE, "Invalid input arguments"); + return -EINVAL; + } -int cam_sfe_write(void *hw_priv, void *write_args, uint32_t arg_size) -{ - return -EPERM; + core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; + sfe_res = (struct cam_isp_resource_node *)stop_args; + mutex_lock(&sfe_hw->hw_mutex); + + if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_IN) + rc = core_info->sfe_top->hw_ops.stop( + core_info->sfe_top->top_priv, sfe_res, + sizeof(struct cam_isp_resource_node)); + else if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_OUT) + rc = core_info->sfe_bus_wr->hw_ops.stop(sfe_res, NULL, 0); + else if (sfe_res->res_type == CAM_ISP_RESOURCE_SFE_RD) + rc = core_info->sfe_bus_rd->hw_ops.stop(sfe_res, NULL, 0); + else + CAM_ERR(CAM_SFE, "Invalid SFE res type: %d", sfe_res->res_type); + + mutex_unlock(&sfe_hw->hw_mutex); + CAM_DBG(CAM_SFE, + "Stop for SFE res type: %u res id: %u res_state: %d rc: %d", + sfe_res->res_type, sfe_res->res_id, + sfe_res->res_state, rc); + + return rc; } int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, @@ -185,7 +337,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_sfe_hw_info *hw_info = NULL; - int rc; + int rc = 0; if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); @@ -198,12 +350,35 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: - case CAM_ISP_HW_CMD_GET_REG_UPDATE: - rc = 0; + case CAM_ISP_HW_CMD_CLOCK_UPDATE: + case CAM_ISP_HW_CMD_BW_UPDATE_V2: + case CAM_ISP_HW_CMD_BW_CONTROL: + case CAM_ISP_HW_CMD_CORE_CONFIG: + rc = core_info->sfe_top->hw_ops.process_cmd( + core_info->sfe_top->top_priv, cmd_type, + cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_BUF_UPDATE: + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = core_info->sfe_bus_wr->hw_ops.process_cmd( + core_info->sfe_bus_wr->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: + case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD: + rc = core_info->sfe_bus_rd->hw_ops.process_cmd( + core_info->sfe_bus_rd->bus_priv, cmd_type, + cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: + /* Needs to be handled based on hw_mgr change */ break; - default: - CAM_ERR(CAM_SFE, "Invalid cmd type:%d", cmd_type); + CAM_ERR(CAM_SFE, "Invalid cmd type: %d", cmd_type); rc = -EINVAL; break; } @@ -227,37 +402,85 @@ irqreturn_t cam_sfe_irq(int irq_num, void *data) } int cam_sfe_core_init( - struct cam_sfe_hw_core_info *core_info, - struct cam_hw_soc_info *soc_info, - struct cam_hw_intf *hw_intf, - struct cam_sfe_hw_info *sfe_hw_info) + struct cam_sfe_hw_core_info *core_info, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + struct cam_sfe_hw_info *sfe_hw_info) { + int rc; - CAM_DBG(CAM_SFE, "Enter"); + rc = cam_sfe_top_init(sfe_hw_info->top_version, soc_info, hw_intf, + sfe_hw_info->top_hw_info, &core_info->sfe_top); + if (rc) { + CAM_ERR(CAM_SFE, "SFE top init failed rc: %d", rc); + return rc; + } + + rc = cam_sfe_bus_init(sfe_hw_info->bus_wr_version, BUS_TYPE_SFE_WR, + soc_info, hw_intf, sfe_hw_info->bus_wr_hw_info, + &core_info->sfe_bus_wr); + if (rc) { + CAM_ERR(CAM_SFE, "SFE bus wr init failed rc: %d", rc); + goto deinit_top; + } + + rc = cam_sfe_bus_init(sfe_hw_info->bus_rd_version, BUS_TYPE_SFE_RD, + soc_info, hw_intf, sfe_hw_info->bus_rd_hw_info, + &core_info->sfe_bus_rd); + if (rc) { + CAM_ERR(CAM_SFE, "SFE bus rd init failed rc: %d", rc); + goto deinit_bus_wr; + } INIT_LIST_HEAD(&core_info->free_payload_list); spin_lock_init(&core_info->spin_lock); + CAM_DBG(CAM_SFE, "SFE device [%u] INIT success", + hw_intf->hw_idx); + return rc; - return 0; +deinit_bus_wr: + cam_sfe_bus_deinit(BUS_TYPE_SFE_WR, + sfe_hw_info->bus_wr_version, + &core_info->sfe_bus_wr); +deinit_top: + cam_sfe_top_deinit(sfe_hw_info->top_version, + &core_info->sfe_top); + return rc; } int cam_sfe_core_deinit( struct cam_sfe_hw_core_info *core_info, struct cam_sfe_hw_info *sfe_hw_info) { - int rc = -EINVAL; + int rc = -EINVAL, i; unsigned long flags; spin_lock_irqsave(&core_info->spin_lock, flags); INIT_LIST_HEAD(&core_info->free_payload_list); + for (i = 0; i < CAM_SFE_EVT_MAX; i++) + INIT_LIST_HEAD(&core_info->evt_payload[i].list); - rc = cam_irq_controller_deinit(&core_info->sfe_irq_controller); + rc = cam_sfe_bus_deinit(BUS_TYPE_SFE_RD, + sfe_hw_info->bus_rd_version, + &core_info->sfe_bus_rd); if (rc) CAM_ERR(CAM_SFE, - "Error cam_irq_controller_deinit failed rc=%d", rc); + "SFE bus rd deinit failed rc: %d", rc); + + rc = cam_sfe_bus_deinit(BUS_TYPE_SFE_WR, + sfe_hw_info->bus_wr_version, + &core_info->sfe_bus_wr); + if (rc) + CAM_ERR(CAM_SFE, + "SFE bus wr deinit failed rc: %d", rc); + + rc = cam_sfe_top_deinit(sfe_hw_info->top_version, + &core_info->sfe_top); + if (rc) + CAM_ERR(CAM_SFE, + "SFE top deinit failed rc: %d", rc); spin_unlock_irqrestore(&core_info->spin_lock, flags); - return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h index 4c25b4458456..349de9e7e15a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h @@ -9,30 +9,48 @@ #include #include "cam_hw_intf.h" #include "cam_sfe_hw_intf.h" +#include "cam_sfe_bus.h" +#include "cam_sfe_top.h" + +#define CAM_SFE_EVT_MAX 256 struct cam_sfe_hw_info { struct cam_irq_controller_reg_info *irq_reg_info; -}; -#define CAM_SFE_EVT_MAX 256 + uint32_t bus_wr_version; + void *bus_wr_hw_info; + + uint32_t bus_rd_version; + void *bus_rd_hw_info; + + uint32_t top_version; + void *top_hw_info; +}; struct cam_sfe_hw_core_info { struct cam_sfe_hw_info *sfe_hw_info; + struct cam_sfe_top *sfe_top; + struct cam_sfe_bus *sfe_bus_wr; + struct cam_sfe_bus *sfe_bus_rd; void *sfe_irq_controller; void *tasklet_info; + struct cam_sfe_irq_evt_payload evt_payload[CAM_SFE_EVT_MAX]; struct list_head free_payload_list; spinlock_t spin_lock; - int irq_handle; }; int cam_sfe_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size); +int cam_sfe_reset(void *device_priv, + void *reset_core_args, uint32_t arg_size); +int cam_sfe_read(void *device_priv, + void *read_args, uint32_t arg_size); +int cam_sfe_write(void *device_priv, + void *write_args, uint32_t arg_size); int cam_sfe_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size); -int cam_sfe_reset(void *device_priv, - void *reset_core_args, uint32_t arg_size); int cam_sfe_reserve(void *device_priv, void *reserve_args, uint32_t arg_size); int cam_sfe_release(void *device_priv, @@ -41,10 +59,6 @@ int cam_sfe_start(void *device_priv, void *start_args, uint32_t arg_size); int cam_sfe_stop(void *device_priv, void *stop_args, uint32_t arg_size); -int cam_sfe_read(void *device_priv, - void *read_args, uint32_t arg_size); -int cam_sfe_write(void *device_priv, - void *write_args, uint32_t arg_size); int cam_sfe_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c index 3e41a654cfee..009d812073ae 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c @@ -6,65 +6,71 @@ #include #include #include +#include #include "cam_sfe_dev.h" #include "cam_sfe_core.h" #include "cam_sfe_soc.h" -#include "cam_sfe_hw_intf.h" +#include "cam_sfe680.h" #include "cam_debug_util.h" +#include "camera_main.h" -static struct cam_hw_intf *sfe_instance; +static struct cam_hw_intf *cam_sfe_hw_list[CAM_SFE_HW_NUM_MAX]; static char sfe_dev_name[8]; -int cam_sfe_probe(struct platform_device *pdev) +static int cam_sfe_component_bind(struct device *dev, + struct device *master_dev, void *data) { + struct cam_hw_info *sfe_info = NULL; - struct cam_hw_intf *sfe_intf = NULL; + struct cam_hw_intf *sfe_hw_intf = NULL; const struct of_device_id *match_dev = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_sfe_hw_info *hw_info = NULL; + struct platform_device *pdev = NULL; int rc = 0; - sfe_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); - if (!sfe_intf) { + pdev = to_platform_device(dev); + sfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!sfe_hw_intf) { rc = -ENOMEM; goto end; } of_property_read_u32(pdev->dev.of_node, - "cell-index", &sfe_intf->hw_idx); + "cell-index", &sfe_hw_intf->hw_idx); sfe_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); if (!sfe_info) { rc = -ENOMEM; - goto free_sfe_intf; + goto free_sfe_hw_intf; } memset(sfe_dev_name, 0, sizeof(sfe_dev_name)); snprintf(sfe_dev_name, sizeof(sfe_dev_name), - "sfe%1u", sfe_intf->hw_idx); + "sfe%1u", sfe_hw_intf->hw_idx); sfe_info->soc_info.pdev = pdev; sfe_info->soc_info.dev = &pdev->dev; sfe_info->soc_info.dev_name = sfe_dev_name; - sfe_intf->hw_priv = sfe_info; - sfe_intf->hw_ops.get_hw_caps = cam_sfe_get_hw_caps; - sfe_intf->hw_ops.init = cam_sfe_init_hw; - sfe_intf->hw_ops.deinit = cam_sfe_deinit_hw; - sfe_intf->hw_ops.reset = cam_sfe_reset; - sfe_intf->hw_ops.reserve = cam_sfe_reserve; - sfe_intf->hw_ops.release = cam_sfe_release; - sfe_intf->hw_ops.start = cam_sfe_start; - sfe_intf->hw_ops.stop = cam_sfe_stop; - sfe_intf->hw_ops.read = cam_sfe_read; - sfe_intf->hw_ops.write = cam_sfe_write; - sfe_intf->hw_ops.process_cmd = cam_sfe_process_cmd; - sfe_intf->hw_type = CAM_ISP_HW_TYPE_SFE; + sfe_hw_intf->hw_priv = sfe_info; + sfe_hw_intf->hw_ops.get_hw_caps = cam_sfe_get_hw_caps; + sfe_hw_intf->hw_ops.init = cam_sfe_init_hw; + sfe_hw_intf->hw_ops.deinit = cam_sfe_deinit_hw; + sfe_hw_intf->hw_ops.reset = cam_sfe_reset; + sfe_hw_intf->hw_ops.reserve = cam_sfe_reserve; + sfe_hw_intf->hw_ops.release = cam_sfe_release; + sfe_hw_intf->hw_ops.start = cam_sfe_start; + sfe_hw_intf->hw_ops.stop = cam_sfe_stop; + sfe_hw_intf->hw_ops.read = cam_sfe_read; + sfe_hw_intf->hw_ops.write = cam_sfe_write; + sfe_hw_intf->hw_ops.process_cmd = cam_sfe_process_cmd; + sfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_SFE; - CAM_DBG(CAM_SFE, "type %d index %d", - sfe_intf->hw_type, sfe_intf->hw_idx); + CAM_DBG(CAM_SFE, "SFE component bind type %d index %d", + sfe_hw_intf->hw_type, sfe_hw_intf->hw_idx); - platform_set_drvdata(pdev, sfe_intf); + platform_set_drvdata(pdev, sfe_hw_intf); sfe_info->core_info = kzalloc(sizeof(struct cam_sfe_hw_core_info), GFP_KERNEL); @@ -93,7 +99,7 @@ int cam_sfe_probe(struct platform_device *pdev) } rc = cam_sfe_core_init(core_info, &sfe_info->soc_info, - sfe_intf, hw_info); + sfe_hw_intf, hw_info); if (rc < 0) { CAM_ERR(CAM_SFE, "Failed to init core rc=%d", rc); goto deinit_soc; @@ -104,9 +110,11 @@ int cam_sfe_probe(struct platform_device *pdev) spin_lock_init(&sfe_info->hw_lock); init_completion(&sfe_info->hw_complete); - sfe_instance = sfe_intf; + if (sfe_hw_intf->hw_idx < CAM_SFE_HW_NUM_MAX) + cam_sfe_hw_list[sfe_hw_intf->hw_idx] = sfe_hw_intf; - CAM_DBG(CAM_SFE, "SFE%d probe successful", sfe_intf->hw_idx); + CAM_DBG(CAM_SFE, "SFE%d bound successfully", + sfe_hw_intf->hw_idx); return rc; @@ -117,40 +125,45 @@ free_core_info: kfree(sfe_info->core_info); free_sfe_hw: kfree(sfe_info); -free_sfe_intf: - kfree(sfe_intf); +free_sfe_hw_intf: + kfree(sfe_hw_intf); end: return rc; } -int cam_sfe_remove(struct platform_device *pdev) +static void cam_sfe_component_unbind(struct device *dev, + struct device *master_dev, void *data) { + struct cam_hw_info *sfe_info = NULL; - struct cam_hw_intf *sfe_intf = NULL; + struct cam_hw_intf *sfe_hw_intf = NULL; struct cam_sfe_hw_core_info *core_info = NULL; + struct platform_device *pdev = NULL; int rc = 0; - sfe_intf = platform_get_drvdata(pdev); - if (!sfe_intf) { + pdev = to_platform_device(dev); + sfe_hw_intf = platform_get_drvdata(pdev); + if (!sfe_hw_intf) { CAM_ERR(CAM_SFE, "Error! No data in pdev"); - return -EINVAL; + return; } - CAM_DBG(CAM_SFE, "type %d index %d", - sfe_intf->hw_type, sfe_intf->hw_idx); + CAM_DBG(CAM_SFE, "SFE component unbound type %d index %d", + sfe_hw_intf->hw_type, sfe_hw_intf->hw_idx); - sfe_instance = NULL; + if (sfe_hw_intf->hw_idx < CAM_SFE_HW_NUM_MAX) + cam_sfe_hw_list[sfe_hw_intf->hw_idx] = NULL; - sfe_info = sfe_intf->hw_priv; + sfe_info = sfe_hw_intf->hw_priv; if (!sfe_info) { - CAM_ERR(CAM_SFE, "Error! HW data is NULL"); + CAM_ERR(CAM_SFE, "HW data is NULL"); rc = -ENODEV; - goto free_sfe_intf; + goto free_sfe_hw_intf; } core_info = (struct cam_sfe_hw_core_info *)sfe_info->core_info; if (!core_info) { - CAM_ERR(CAM_SFE, "Error! core data NULL"); + CAM_ERR(CAM_SFE, "core data NULL"); rc = -EINVAL; goto deinit_soc; } @@ -169,25 +182,80 @@ deinit_soc: mutex_destroy(&sfe_info->hw_mutex); kfree(sfe_info); - CAM_DBG(CAM_SFE, "SFE%d remove successful", sfe_intf->hw_idx); + CAM_DBG(CAM_SFE, "SFE%d remove successful", sfe_hw_intf->hw_idx); -free_sfe_intf: - kfree(sfe_intf); +free_sfe_hw_intf: + kfree(sfe_hw_intf); +} + +const static struct component_ops cam_sfe_component_ops = { + .bind = cam_sfe_component_bind, + .unbind = cam_sfe_component_unbind, +}; + +int cam_sfe_probe(struct platform_device *pdev) +{ + int rc = 0; + + CAM_DBG(CAM_SFE, "Adding SFE component"); + rc = component_add(&pdev->dev, &cam_sfe_component_ops); + if (rc) + CAM_ERR(CAM_SFE, "failed to add component rc: %d", rc); return rc; } -int cam_sfe_hw_init(struct cam_hw_intf **sfe_intf, uint32_t hw_idx) +int cam_sfe_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &cam_sfe_component_ops); + return 0; +} + +int cam_sfe_hw_init(struct cam_hw_intf **sfe_hw, uint32_t hw_idx) { int rc = 0; - if (sfe_instance) { - *sfe_intf = sfe_instance; + if (cam_sfe_hw_list[hw_idx]) { + *sfe_hw = cam_sfe_hw_list[hw_idx]; rc = 0; } else { - *sfe_intf = NULL; + *sfe_hw = NULL; rc = -ENODEV; } return rc; } + +static const struct of_device_id cam_sfe_dt_match[] = { + { + .compatible = "", + .data = &cam_sfe680_hw_info, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cam_sfe_dt_match); + +struct platform_driver cam_sfe_driver = { + .probe = cam_sfe_probe, + .remove = cam_sfe_remove, + .driver = { + .name = "cam_sfe", + .owner = THIS_MODULE, + .of_match_table = cam_sfe_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_sfe_init_module(void) +{ + return platform_driver_register(&cam_sfe_driver); +} + + +void cam_sfe_exit_module(void) +{ + platform_driver_unregister(&cam_sfe_driver); +} + +MODULE_DESCRIPTION("CAM SFE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h index b49ad3217812..d00bcc6144b8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.h @@ -6,30 +6,18 @@ #ifndef _CAM_SFE_DEV_H_ #define _CAM_SFE_DEV_H_ -#include - -/* - * cam_sfe_probe() - * - * @brief: Driver probe function called on Boot - * - * @pdev: Platform Device pointer - * +/** + * @brief : API to register SFE hw to platform framework. * @Return: 0: Success * Non-zero: Failure */ -int cam_sfe_probe(struct platform_device *pdev); +int cam_sfe_init_module(void); -/* - * cam_sfe_remove() - * - * @brief: Driver remove function - * - * @pdev: Platform Device pointer - * +/** + * @brief : API to remove SFE Hw from platform framework. * @Return: 0: Success * Non-zero: Failure */ -int cam_sfe_remove(struct platform_device *pdev); +void cam_sfe_exit_module(void); #endif /* _CAM_SFE_DEV_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c index fb72657a15bf..aa6b42db8c20 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c @@ -50,11 +50,26 @@ int cam_sfe_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t irq_handler_func, void *irq_data) { int rc = 0; + struct cam_sfe_soc_private *soc_private; + struct cam_cpas_register_params cpas_register_param; + + soc_private = kzalloc(sizeof(struct cam_sfe_soc_private), + GFP_KERNEL); + if (!soc_private) + return -ENOMEM; + + soc_info->soc_private = soc_private; + rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version); + if (rc) { + CAM_ERR(CAM_SFE, "Error! Invalid cpas version rc=%d", rc); + goto free_soc_private; + } + soc_info->hw_version = soc_private->cpas_version; rc = cam_sfe_get_dt_properties(soc_info); if (rc < 0) { CAM_ERR(CAM_SFE, "Error Get DT properties failed rc=%d", rc); - goto end; + goto free_soc_private; } rc = cam_sfe_request_platform_resource(soc_info, @@ -62,41 +77,104 @@ int cam_sfe_init_soc_resources(struct cam_hw_soc_info *soc_info, if (rc < 0) { CAM_ERR(CAM_SFE, "Error Request platform resources failed rc=%d", rc); - goto end; + goto free_soc_private; } -end: + memset(&cpas_register_param, 0, sizeof(cpas_register_param)); + strlcpy(cpas_register_param.identifier, "sfe", + 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 = NULL; + cpas_register_param.userdata = soc_info; + rc = cam_cpas_register_client(&cpas_register_param); + if (rc) { + CAM_ERR(CAM_SFE, "CPAS registration failed rc=%d", rc); + goto release_soc; + } else { + soc_private->cpas_handle = cpas_register_param.client_handle; + } + + return rc; + +release_soc: + cam_soc_util_release_platform_resource(soc_info); +free_soc_private: + kfree(soc_private); return rc; } int cam_sfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info) { int rc = 0; + struct cam_sfe_soc_private *soc_private; if (!soc_info) { CAM_ERR(CAM_SFE, "Error soc_info NULL"); return -ENODEV; } + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_SFE, "Error! soc_private NULL"); + return -ENODEV; + } + + rc = cam_cpas_unregister_client(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_SFE, "CPAS unregistration failed rc=%d", rc); + rc = cam_sfe_release_platform_resource(soc_info); if (rc < 0) CAM_ERR(CAM_SFE, "Error Release platform resources failed rc=%d", rc); + kfree(soc_private); return rc; } int cam_sfe_enable_soc_resources(struct cam_hw_soc_info *soc_info) { - int rc = 0; + int rc = 0; + struct cam_sfe_soc_private *soc_private; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; - rc = cam_soc_util_enable_platform_resource(soc_info, true, - CAM_TURBO_VOTE, true); + if (!soc_info) { + CAM_ERR(CAM_SFE, "Error! Invalid params"); + rc = -EINVAL; + goto end; + } + soc_private = soc_info->soc_private; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_SFE_NRDI; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE; + axi_vote.axi_path[0].camnoc_bw = 10640000000L; + axi_vote.axi_path[0].mnoc_ab_bw = 10640000000L; + axi_vote.axi_path[0].mnoc_ib_bw = 10640000000L; + + rc = cam_cpas_start(soc_private->cpas_handle, + &ahb_vote, &axi_vote); if (rc) { - CAM_ERR(CAM_SFE, "Error enable platform failed rc=%d", rc); + CAM_ERR(CAM_SFE, "CPAS start failed rc=%d", rc); + rc = -EFAULT; goto end; } + rc = cam_soc_util_enable_platform_resource(soc_info, true, + CAM_LOWSVS_VOTE, true); + if (rc) { + CAM_ERR(CAM_SFE, "Enable platform failed rc=%d", rc); + goto stop_cpas; + } + + return rc; + +stop_cpas: + cam_cpas_stop(soc_private->cpas_handle); end: return rc; } @@ -113,14 +191,26 @@ int cam_sfe_soc_disable_clk(struct cam_hw_soc_info *soc_info, return -EPERM; } - int cam_sfe_disable_soc_resources(struct cam_hw_soc_info *soc_info) { int rc = 0; + struct cam_sfe_soc_private *soc_private; + + if (!soc_info) { + CAM_ERR(CAM_SFE, "Invalid params"); + rc = -EINVAL; + return rc; + } + + soc_private = soc_info->soc_private; rc = cam_soc_util_disable_platform_resource(soc_info, true, true); if (rc) CAM_ERR(CAM_SFE, "Disable platform failed rc=%d", rc); + rc = cam_cpas_stop(soc_private->cpas_handle); + if (rc) + CAM_ERR(CAM_SFE, "CPAS stop failed rc=%d", rc); + return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h index 37bf2918c585..735e6215520d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.h @@ -37,7 +37,7 @@ struct cam_sfe_soc_private { * Non-zero: Failure */ int cam_sfe_init_soc_resources(struct cam_hw_soc_info *soc_info, - irq_handler_t vfe_irq_handler, void *irq_data); + irq_handler_t sfe_irq_handler, void *irq_data); /* * cam_sfe_deinit_soc_resources() diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c new file mode 100644 index 000000000000..d713714e1dab --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "cam_sfe_bus.h" +#include "cam_sfe_bus_rd.h" +#include "cam_sfe_bus_wr.h" +#include "cam_debug_util.h" + +int cam_sfe_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, + struct cam_sfe_bus **sfe_bus) +{ + int rc = -ENODEV; + + switch (bus_type) { + case BUS_TYPE_SFE_WR: + switch (bus_version) { + case CAM_SFE_BUS_WR_VER_1_0: + rc = cam_sfe_bus_wr_init(soc_info, hw_intf, + bus_hw_info, sfe_bus); + break; + default: + CAM_ERR(CAM_SFE, "Unsupported Bus WR Version 0x%x", + bus_version); + break; + } + break; + case BUS_TYPE_SFE_RD: + switch (bus_version) { + case CAM_SFE_BUS_RD_VER_1_0: + rc = cam_sfe_bus_rd_init(soc_info, hw_intf, + bus_hw_info, sfe_bus); + break; + default: + CAM_ERR(CAM_SFE, "Unsupported Bus RD Version 0x%x", + bus_version); + break; + } + break; + default: + CAM_ERR(CAM_SFE, "Unsupported Bus type %d", bus_type); + break; + } + + return rc; +} + +int cam_sfe_bus_deinit( + uint32_t bus_version, + int bus_type, + struct cam_sfe_bus **sfe_bus) +{ + int rc = -ENODEV; + + switch (bus_type) { + case BUS_TYPE_SFE_WR: + switch (bus_version) { + case CAM_SFE_BUS_WR_VER_1_0: + rc = cam_sfe_bus_wr_deinit(sfe_bus); + break; + default: + CAM_ERR(CAM_SFE, "Unsupported Bus WR Version 0x%x", + bus_version); + break; + } + break; + case BUS_TYPE_SFE_RD: + switch (bus_version) { + case CAM_SFE_BUS_RD_VER_1_0: + rc = cam_sfe_bus_rd_deinit(sfe_bus); + break; + default: + CAM_ERR(CAM_SFE, "Unsupported Bus RD Version 0x%x", + bus_version); + break; + } + break; + default: + CAM_ERR(CAM_SFE, "Unsupported Bus type %d", bus_type); + break; + } + + return rc; +} + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c new file mode 100644 index 000000000000..f9ad59da9fa1 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c @@ -0,0 +1,1144 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include + +#include + +#include "cam_io_util.h" +#include "cam_debug_util.h" +#include "cam_hw_intf.h" +#include "cam_ife_hw_mgr.h" +#include "cam_sfe_hw_intf.h" +#include "cam_tasklet_util.h" +#include "cam_sfe_bus.h" +#include "cam_sfe_bus_rd.h" +#include "cam_sfe_core.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" + +static const char drv_name[] = "sfe_bus_rd"; + +#define MAX_BUF_UPDATE_REG_NUM \ + (sizeof(struct cam_sfe_bus_rd_reg_offset_bus_client)/4) + +#define MAX_REG_VAL_PAIR_SIZE \ + (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) + +#define BUS_RD_DEFAULT_LATENCY_BUF_ALLOC 512 + +enum cam_sfe_bus_rd_unpacker_format { + BUS_RD_UNPACKER_FMT_PLAIN_128 = 0x0, + BUS_RD_UNPACKER_FMT_PLAIN_8 = 0x1, + BUS_RD_UNPACKER_FMT_PLAIN_16_10BPP = 0x2, + BUS_RD_UNPACKER_FMT_PLAIN_16_12BPP = 0x3, + BUS_RD_UNPACKER_FMT_PLAIN_16_14BPP = 0x4, + BUS_RD_UNPACKER_FMT_PLAIN_32_20BPP = 0x5, + BUS_RD_UNPACKER_FMT_ARGB_10 = 0x6, + BUS_RD_UNPACKER_FMT_ARGB_12 = 0x7, + BUS_RD_UNPACKER_FMT_ARGB_14 = 0x8, + BUS_RD_UNPACKER_FMT_PLAIN_32 = 0x9, + BUS_RD_UNPACKER_FMT_PLAIN_64 = 0xA, + BUS_RD_UNPACKER_FMT_TP_10 = 0xB, + BUS_RD_UNPACKER_FMT_MIPI8 = 0xC, + BUS_RD_UNPACKER_FMT_MIPI10 = 0xD, + BUS_RD_UNPACKER_FMT_MIPI12 = 0xE, + BUS_RD_UNPACKER_FMT_MIPI14 = 0xF, + BUS_RD_UNPACKER_FMT_PLAIN_16_16BPP = 0x10, + BUS_RD_UNPACKER_FMT_PLAIN_128_ODD_EVEN = 0x11, + BUS_RD_UNPACKER_FMT_PLAIN_8_ODD_EVEN = 0x12, + BUS_RD_UNPACKER_FMT_MAX = 0x13, +}; + +struct cam_sfe_bus_rd_common_data { + uint32_t core_index; + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + struct cam_sfe_bus_rd_reg_offset_common *common_reg; + uint32_t io_buf_update[ + MAX_REG_VAL_PAIR_SIZE]; + + cam_hw_mgr_event_cb_func event_cb; +}; + +struct cam_sfe_bus_rd_rm_resource_data { + uint32_t index; + struct cam_sfe_bus_rd_common_data *common_data; + struct cam_sfe_bus_rd_reg_offset_bus_client *hw_regs; + void *ctx; + 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 en_cfg; + uint32_t img_addr; + uint32_t input_if_cmd; +}; + +struct cam_sfe_bus_rd_data { + uint32_t bus_rd_type; + struct cam_sfe_bus_rd_common_data *common_data; + + uint32_t num_rm; + struct cam_isp_resource_node *rm_res[PLANE_MAX]; + uint32_t format; + uint32_t max_width; + uint32_t max_height; + struct cam_cdm_utils_ops *cdm_util_ops; + void *priv; + uint32_t status; + uint32_t secure_mode; + uint32_t fs_sync_enable; + uint32_t fs_line_sync_en; + bool is_offline; +}; + +struct cam_sfe_bus_rd_priv { + struct cam_sfe_bus_rd_common_data common_data; + uint32_t num_client; + uint32_t num_bus_rd_resc; + + struct cam_isp_resource_node bus_client[ + CAM_SFE_BUS_RD_MAX_CLIENTS]; + struct cam_isp_resource_node sfe_bus_rd[ + CAM_SFE_BUS_RD_MAX]; + + void *tasklet_info; + uint32_t top_irq_shift; +}; + +static void cam_sfe_bus_rd_pxls_to_bytes(uint32_t pxls, uint32_t fmt, + uint32_t *bytes) +{ + switch (fmt) { + case BUS_RD_UNPACKER_FMT_PLAIN_128: + *bytes = pxls * 16; + break; + case BUS_RD_UNPACKER_FMT_PLAIN_8: + case BUS_RD_UNPACKER_FMT_PLAIN_8_ODD_EVEN: + case BUS_RD_UNPACKER_FMT_PLAIN_16_10BPP: + case BUS_RD_UNPACKER_FMT_PLAIN_16_12BPP: + case BUS_RD_UNPACKER_FMT_PLAIN_16_14BPP: + case BUS_RD_UNPACKER_FMT_PLAIN_16_16BPP: + case BUS_RD_UNPACKER_FMT_ARGB_10: + case BUS_RD_UNPACKER_FMT_ARGB_12: + case BUS_RD_UNPACKER_FMT_ARGB_14: + *bytes = pxls * 2; + break; + case BUS_RD_UNPACKER_FMT_PLAIN_32_20BPP: + case BUS_RD_UNPACKER_FMT_PLAIN_32: + *bytes = pxls * 4; + break; + case BUS_RD_UNPACKER_FMT_PLAIN_64: + *bytes = pxls * 8; + break; + case BUS_RD_UNPACKER_FMT_TP_10: + *bytes = ALIGNUP(pxls, 3) * 4 / 3; + break; + case BUS_RD_UNPACKER_FMT_MIPI8: + *bytes = pxls; + break; + case BUS_RD_UNPACKER_FMT_MIPI10: + *bytes = ALIGNUP(pxls * 5, 4) / 4; + break; + case BUS_RD_UNPACKER_FMT_MIPI12: + *bytes = ALIGNUP(pxls * 3, 2) / 2; + break; + case BUS_RD_UNPACKER_FMT_MIPI14: + *bytes = ALIGNUP(pxls * 7, 4) / 4; + break; + default: + CAM_ERR(CAM_SFE, "Invalid unpacker_fmt:%d", fmt); + break; + } +} + +static enum cam_sfe_bus_rd_unpacker_format + cam_sfe_bus_get_unpacker_fmt(uint32_t unpack_fmt) +{ + switch (unpack_fmt) { + case CAM_FORMAT_PLAIN128: + return BUS_RD_UNPACKER_FMT_PLAIN_128; + case CAM_FORMAT_PLAIN8: + return BUS_RD_UNPACKER_FMT_PLAIN_8; + case CAM_FORMAT_PLAIN16_10: + return BUS_RD_UNPACKER_FMT_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return BUS_RD_UNPACKER_FMT_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return BUS_RD_UNPACKER_FMT_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN32_20: + return BUS_RD_UNPACKER_FMT_PLAIN_32_20BPP; + case CAM_FORMAT_ARGB_10: + return BUS_RD_UNPACKER_FMT_ARGB_10; + case CAM_FORMAT_ARGB_12: + return BUS_RD_UNPACKER_FMT_ARGB_12; + case CAM_FORMAT_ARGB_14: + return BUS_RD_UNPACKER_FMT_ARGB_14; + case CAM_FORMAT_PLAIN32: + case CAM_FORMAT_ARGB: + return BUS_RD_UNPACKER_FMT_PLAIN_32; + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_ARGB_16: + case CAM_FORMAT_PD10: + return BUS_RD_UNPACKER_FMT_PLAIN_64; + case CAM_FORMAT_TP10: + return BUS_RD_UNPACKER_FMT_TP_10; + case CAM_FORMAT_MIPI_RAW_8: + return BUS_RD_UNPACKER_FMT_MIPI8; + case CAM_FORMAT_MIPI_RAW_10: + return BUS_RD_UNPACKER_FMT_MIPI10; + case CAM_FORMAT_MIPI_RAW_12: + return BUS_RD_UNPACKER_FMT_MIPI12; + case CAM_FORMAT_MIPI_RAW_14: + return BUS_RD_UNPACKER_FMT_MIPI14; + case CAM_FORMAT_PLAIN16_16: + return BUS_RD_UNPACKER_FMT_PLAIN_16_16BPP; + case CAM_FORMAT_PLAIN8_SWAP: + return BUS_RD_UNPACKER_FMT_PLAIN_8_ODD_EVEN; + default: + return BUS_RD_UNPACKER_FMT_MAX; + } +} + +static enum cam_sfe_bus_rd_type + cam_sfe_bus_get_bus_rd_res_id(uint32_t res_type) +{ + switch (res_type) { + case CAM_ISP_HW_SFE_IN_RD0: + return CAM_SFE_BUS_RD_RDI0; + case CAM_ISP_HW_SFE_IN_RD1: + return CAM_SFE_BUS_RD_RDI1; + case CAM_ISP_HW_SFE_IN_RD2: + return CAM_SFE_BUS_RD_RDI2; + default: + return CAM_SFE_BUS_RD_MAX; + } +} + +static int cam_sfe_bus_get_num_rm( + enum cam_sfe_bus_rd_type res_type) +{ + switch (res_type) { + case CAM_SFE_BUS_RD_RDI0: + case CAM_SFE_BUS_RD_RDI1: + case CAM_SFE_BUS_RD_RDI2: + return 1; + default: + CAM_ERR(CAM_SFE, "Unsupported resource_type %u", res_type); + return -EINVAL; + } +} + +static int cam_sfe_bus_get_rm_idx( + enum cam_sfe_bus_rd_type sfe_bus_rd_res_id, + enum cam_sfe_bus_plane_type plane) +{ + int rm_idx = -1; + + switch (sfe_bus_rd_res_id) { + case CAM_SFE_BUS_RD_RDI0: + switch (plane) { + case PLANE_Y: + rm_idx = 0; + break; + default: + break; + } + break; + case CAM_SFE_BUS_RD_RDI1: + switch (plane) { + case PLANE_Y: + rm_idx = 1; + break; + default: + break; + } + break; + case CAM_SFE_BUS_RD_RDI2: + switch (plane) { + case PLANE_Y: + rm_idx = 2; + break; + default: + break; + } + break; + default: + break; + } + + return rm_idx; +} + +static int cam_sfe_bus_acquire_rm( + struct cam_sfe_bus_rd_priv *bus_rd_priv, + void *tasklet, + void *ctx, + enum cam_sfe_bus_rd_type sfe_bus_rd_res_id, + enum cam_sfe_bus_plane_type plane, + struct cam_isp_resource_node **rm_res, + uint32_t unpacker_fmt) +{ + uint32_t rm_idx = 0; + struct cam_isp_resource_node *rm_res_local = NULL; + struct cam_sfe_bus_rd_rm_resource_data *rsrc_data = NULL; + + *rm_res = NULL; + + rm_idx = cam_sfe_bus_get_rm_idx(sfe_bus_rd_res_id, plane); + if (rm_idx < 0 || rm_idx >= bus_rd_priv->num_client) { + CAM_ERR(CAM_SFE, "Unsupported SFE RM:%d plane:%d", + sfe_bus_rd_res_id, plane); + return -EINVAL; + } + + rm_res_local = &bus_rd_priv->bus_client[rm_idx]; + if (rm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_SFE, "SFE:%d RM:%d res not available state:%d", + bus_rd_priv->common_data.core_index, rm_idx, + 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->ctx = ctx; + rsrc_data->unpacker_cfg = + cam_sfe_bus_get_unpacker_fmt(unpacker_fmt); + rsrc_data->latency_buf_allocation = + BUS_RD_DEFAULT_LATENCY_BUF_ALLOC; + + *rm_res = rm_res_local; + + CAM_DBG(CAM_SFE, "SFE:%d RM:%d Acquired", + rsrc_data->common_data->core_index, rsrc_data->index); + return 0; +} + +static int cam_sfe_bus_release_rm(void *bus_priv, + struct cam_isp_resource_node *rm_res) +{ + struct cam_sfe_bus_rd_rm_resource_data *rsrc_data = + rm_res->res_priv; + + 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->en_cfg = 0; + + rm_res->tasklet_info = NULL; + rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + CAM_DBG(CAM_SFE, "SFE:%d RM:%d released", + rsrc_data->common_data->core_index, rsrc_data->index); + return 0; +} + +static int cam_sfe_bus_start_rm(struct cam_isp_resource_node *rm_res) +{ + struct cam_sfe_bus_rd_rm_resource_data *rm_data; + struct cam_sfe_bus_rd_common_data *common_data; + + rm_data = rm_res->res_priv; + common_data = rm_data->common_data; + + cam_io_w_mb(rm_data->width, common_data->mem_base + + rm_data->hw_regs->buf_width); + cam_io_w_mb(rm_data->height, common_data->mem_base + + rm_data->hw_regs->buf_height); + cam_io_w_mb(rm_data->width, common_data->mem_base + + rm_data->hw_regs->stride); + cam_io_w_mb(rm_data->unpacker_cfg, common_data->mem_base + + rm_data->hw_regs->unpacker_cfg); + cam_io_w_mb(rm_data->latency_buf_allocation, common_data->mem_base + + rm_data->hw_regs->latency_buf_allocation); + cam_io_w_mb(0x1, common_data->mem_base + rm_data->hw_regs->cfg); + + rm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + CAM_DBG(CAM_SFE, + "Start SFE:%d RM:%d offset:0x%X en_cfg:0x%X width:%d height:%d", + rm_data->common_data->core_index, rm_data->index, + (uint32_t) rm_data->hw_regs->cfg, rm_data->en_cfg, + rm_data->width, rm_data->height); + CAM_DBG(CAM_SFE, "RM:%d pk_fmt:%d stride:%d", rm_data->index, + rm_data->unpacker_cfg, rm_data->stride); + + return 0; +} + +static int cam_sfe_bus_stop_rm(struct cam_isp_resource_node *rm_res) +{ + struct cam_sfe_bus_rd_rm_resource_data *rsrc_data = + rm_res->res_priv; + struct cam_sfe_bus_rd_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; + + CAM_DBG(CAM_SFE, "SFE:%d RM:%d stopped", + rsrc_data->common_data->core_index, rsrc_data->index); + + return 0; +} + +static int cam_sfe_bus_init_rm_resource(uint32_t index, + struct cam_sfe_bus_rd_priv *bus_rd_priv, + struct cam_sfe_bus_rd_hw_info *bus_rd_hw_info, + struct cam_isp_resource_node *rm_res) +{ + struct cam_sfe_bus_rd_rm_resource_data *rsrc_data; + + rsrc_data = kzalloc(sizeof(struct cam_sfe_bus_rd_rm_resource_data), + GFP_KERNEL); + if (!rsrc_data) { + CAM_DBG(CAM_SFE, "Failed to alloc SFE:%d RM res priv", + bus_rd_priv->common_data.core_index); + 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 = &bus_rd_priv->common_data; + + rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&rm_res->list); + + rm_res->start = cam_sfe_bus_start_rm; + rm_res->stop = cam_sfe_bus_stop_rm; + rm_res->hw_intf = bus_rd_priv->common_data.hw_intf; + + return 0; +} + +static int cam_sfe_bus_deinit_rm_resource( + struct cam_isp_resource_node *rm_res) +{ + struct cam_sfe_bus_rd_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_sfe_bus_rd_get_secure_mode(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_isp_hw_get_cmd_update *secure_mode = cmd_args; + struct cam_sfe_bus_rd_data *rsrc_data = NULL; + uint32_t *mode; + + rsrc_data = (struct cam_sfe_bus_rd_data *) + secure_mode->res->res_priv; + mode = (uint32_t *)secure_mode->data; + *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? + true : false; + + return 0; +} + +static int cam_sfe_bus_acquire_bus_rd(void *bus_priv, void *acquire_args, + uint32_t args_size) +{ + int rc = -ENODEV; + int i; + enum cam_sfe_bus_rd_type bus_rd_res_id; + int num_rm; + struct cam_sfe_bus_rd_priv *bus_rd_priv = + bus_priv; + struct cam_sfe_acquire_args *acq_args = acquire_args; + struct cam_sfe_hw_sfe_bus_rd_acquire_args *bus_rd_acquire_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_sfe_bus_rd_data *rsrc_data = NULL; + + if (!bus_priv || !acquire_args) { + CAM_ERR(CAM_SFE, "Invalid Param"); + return -EINVAL; + } + + bus_rd_acquire_args = &acq_args->sfe_rd; + + bus_rd_res_id = cam_sfe_bus_get_bus_rd_res_id( + bus_rd_acquire_args->res_id); + if (bus_rd_res_id == CAM_SFE_BUS_RD_MAX) + return -ENODEV; + + num_rm = cam_sfe_bus_get_num_rm(bus_rd_res_id); + if (num_rm < 1) + return -EINVAL; + + rsrc_node = &bus_rd_priv->sfe_bus_rd[bus_rd_res_id]; + if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_SFE, "SFE:%d RM:0x%x not available state:%d", + bus_rd_priv->common_data.core_index, + acq_args->rsrc_type, rsrc_node->res_state); + return -EBUSY; + } + + rsrc_node->res_id = bus_rd_acquire_args->res_id; + rsrc_data = rsrc_node->res_priv; + + CAM_DBG(CAM_SFE, "SFE:%d acquire RD type:0x%x", + rsrc_data->common_data->core_index, acq_args->rsrc_type); + + rsrc_data->num_rm = num_rm; + rsrc_node->tasklet_info = acq_args->tasklet; + bus_rd_priv->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; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + rsrc_data->is_offline = bus_rd_acquire_args->is_offline; + if (!rsrc_data->secure_mode) { + rsrc_data->secure_mode = + bus_rd_acquire_args->secure_mode; + } else if (rsrc_data->secure_mode != + bus_rd_acquire_args->secure_mode) { + CAM_ERR(CAM_SFE, + "Current Mode %u Requesting Mode %u", + rsrc_data->secure_mode, + bus_rd_acquire_args->secure_mode); + return -EINVAL; + } + + for (i = 0; i < num_rm; i++) { + rc = cam_sfe_bus_acquire_rm(bus_rd_priv, + acq_args->tasklet, + acq_args->priv, + bus_rd_res_id, + i, + &rsrc_data->rm_res[i], + bus_rd_acquire_args->unpacker_fmt); + if (rc) { + CAM_ERR(CAM_SFE, + "SFE:%d RM:%d acquire failed 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_SFE, "SFE:%d acquire RD 0x%x successful", + rsrc_data->common_data->core_index, acq_args->rsrc_type); + return rc; + +release_rm: + for (i--; i >= 0; i--) + cam_sfe_bus_release_rm(bus_rd_priv, rsrc_data->rm_res[i]); + return rc; +} + +static int cam_sfe_bus_release_bus_rd(void *bus_priv, void *release_args, + uint32_t args_size) +{ + uint32_t i; + struct cam_isp_resource_node *sfe_bus_rd = NULL; + struct cam_sfe_bus_rd_data *rsrc_data = NULL; + + if (!bus_priv || !release_args) { + CAM_ERR(CAM_SFE, "Invalid input bus_priv %pK release_args %pK", + bus_priv, release_args); + return -EINVAL; + } + + sfe_bus_rd = release_args; + rsrc_data = sfe_bus_rd->res_priv; + + if (sfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_SFE, + "SFE:%d RD type:0x%x invalid resource state:%d", + rsrc_data->common_data->core_index, + sfe_bus_rd->res_id, sfe_bus_rd->res_state); + } + + for (i = 0; i < rsrc_data->num_rm; i++) + cam_sfe_bus_release_rm(bus_priv, rsrc_data->rm_res[i]); + rsrc_data->num_rm = 0; + + sfe_bus_rd->tasklet_info = NULL; + sfe_bus_rd->cdm_ops = NULL; + rsrc_data->cdm_util_ops = NULL; + rsrc_data->secure_mode = 0; + + if (sfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) + sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +static int cam_sfe_bus_start_bus_rd( + void *hw_priv, void *stop_hw_args, uint32_t arg_size) +{ + int rc, i; + struct cam_isp_resource_node *sfe_bus_rd = NULL; + struct cam_sfe_bus_rd_data *rsrc_data = NULL; + struct cam_sfe_bus_rd_common_data *common_data = NULL; + uint32_t val = 0; + + if (!hw_priv) { + CAM_ERR(CAM_SFE, "Invalid input"); + return -EINVAL; + } + + sfe_bus_rd = (struct cam_isp_resource_node *)hw_priv; + rsrc_data = sfe_bus_rd->res_priv; + common_data = rsrc_data->common_data; + + CAM_DBG(CAM_SFE, "SFE:%d start RD type:0x%x", sfe_bus_rd->res_id); + + if (sfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_SFE, "Invalid resource state:%d", + sfe_bus_rd->res_state); + return -EACCES; + } + + if (!rsrc_data->is_offline) { + val = (rsrc_data->fs_sync_enable << 5); + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->input_if_cmd); + } + + if (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) + cam_io_w_mb(1, common_data->mem_base + + common_data->common_reg->security_cfg); + + for (i = 0; i < rsrc_data->num_rm; i++) + rc = cam_sfe_bus_start_rm(rsrc_data->rm_res[i]); + + /* Subscribe mask for buf_done */ + + sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return rc; +} + +static int cam_sfe_bus_stop_bus_rd( + void *hw_priv, void *stop_hw_args, uint32_t arg_size) +{ + int rc = 0, i; + struct cam_isp_resource_node *sfe_bus_rd = NULL; + struct cam_sfe_bus_rd_data *rsrc_data = NULL; + + if (!hw_priv) { + CAM_ERR(CAM_SFE, "Invalid input"); + return -EINVAL; + } + + sfe_bus_rd = (struct cam_isp_resource_node *)hw_priv; + rsrc_data = sfe_bus_rd->res_priv; + + if (sfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE || + sfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_SFE, "SFE: %d res_id: 0x%x state: %d", + rsrc_data->common_data->core_index, sfe_bus_rd->res_id, + sfe_bus_rd->res_state); + return rc; + } + for (i = 0; i < rsrc_data->num_rm; i++) + rc = cam_sfe_bus_stop_rm(rsrc_data->rm_res[i]); + + sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + /* Unsubscribe mask for this wm IRQ controller */ + CAM_DBG(CAM_SFE, "SFE:%d stopped Bus RD:0x%x", + rsrc_data->common_data->core_index, + sfe_bus_rd->res_id); + return rc; +} + +static int cam_sfe_bus_init_sfe_bus_read_resource( + uint32_t index, + struct cam_sfe_bus_rd_priv *bus_rd_priv, + struct cam_sfe_bus_rd_hw_info *bus_rd_hw_info) +{ + struct cam_isp_resource_node *sfe_bus_rd = NULL; + struct cam_sfe_bus_rd_data *rsrc_data = NULL; + int rc = 0; + int32_t sfe_bus_rd_resc_type = + bus_rd_hw_info->sfe_bus_rd_info[index].sfe_bus_rd_type; + + if (sfe_bus_rd_resc_type < 0 || + sfe_bus_rd_resc_type >= CAM_SFE_BUS_RD_MAX) { + CAM_ERR(CAM_SFE, "Init SFE RD failed, Invalid type=%d", + sfe_bus_rd_resc_type); + return -EINVAL; + } + + sfe_bus_rd = &bus_rd_priv->sfe_bus_rd[sfe_bus_rd_resc_type]; + if (sfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || + sfe_bus_rd->res_priv) { + CAM_ERR(CAM_SFE, + "Error. Looks like same resource is init again"); + return -EFAULT; + } + + rsrc_data = kzalloc(sizeof(struct cam_sfe_bus_rd_data), + GFP_KERNEL); + if (!rsrc_data) { + rc = -ENOMEM; + return rc; + } + + sfe_bus_rd->res_priv = rsrc_data; + + sfe_bus_rd->res_type = CAM_ISP_RESOURCE_SFE_RD; + sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&sfe_bus_rd->list); + + rsrc_data->bus_rd_type = + bus_rd_hw_info->sfe_bus_rd_info[index].sfe_bus_rd_type; + rsrc_data->common_data = &bus_rd_priv->common_data; + rsrc_data->max_width = + bus_rd_hw_info->sfe_bus_rd_info[index].max_width; + rsrc_data->max_height = + bus_rd_hw_info->sfe_bus_rd_info[index].max_height; + rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + sfe_bus_rd->hw_intf = bus_rd_priv->common_data.hw_intf; + + return 0; +} + +static int cam_sfe_bus_deinit_sfe_bus_rd_resource( + struct cam_isp_resource_node *sfe_bus_rd_res) +{ + struct cam_sfe_bus_rd_data *rsrc_data = + sfe_bus_rd_res->res_priv; + + if (sfe_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_SFE, "HW%d Res %d already deinitialized"); + return 0; + } + + sfe_bus_rd_res->start = NULL; + sfe_bus_rd_res->stop = NULL; + sfe_bus_rd_res->top_half_handler = NULL; + sfe_bus_rd_res->bottom_half_handler = NULL; + sfe_bus_rd_res->hw_intf = NULL; + + sfe_bus_rd_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&sfe_bus_rd_res->list); + sfe_bus_rd_res->res_priv = NULL; + + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bus_rd_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_buf; + struct cam_buf_io_cfg *io_cfg = NULL; + struct cam_sfe_bus_rd_data *sfe_bus_rd_data = NULL; + struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL; + uint32_t *reg_val_pair; + uint32_t width = 0, height = 0, stride = 0; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_sfe_bus_rd_priv *) priv; + update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *) + update_buf->res->res_priv; + + if (!sfe_bus_rd_data || !sfe_bus_rd_data->cdm_util_ops) { + CAM_ERR(CAM_SFE, "Failed! Invalid data"); + return -EINVAL; + } + + CAM_DBG(CAM_SFE, "#of RM: %d scratch_buf_cfg: %s", + sfe_bus_rd_data->num_rm, + update_buf->use_scratch_cfg ? "true" : "false"); + if (update_buf->rm_update->num_buf != sfe_bus_rd_data->num_rm) { + CAM_ERR(CAM_SFE, + "Failed! Invalid number buffers:%d required:%d", + update_buf->rm_update->num_buf, + sfe_bus_rd_data->num_rm); + return -EINVAL; + } + + reg_val_pair = &sfe_bus_rd_data->common_data->io_buf_update[0]; + if (!update_buf->use_scratch_cfg) + io_cfg = update_buf->rm_update->io_cfg; + + for (i = 0, j = 0; i < sfe_bus_rd_data->num_rm; i++) { + if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { + CAM_ERR(CAM_SFE, + "reg_val_pair %d exceeds the array limit %lu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + rm_data = sfe_bus_rd_data->rm_res[i]->res_priv; + if (update_buf->use_scratch_cfg) { + stride = update_buf->rm_update->stride; + width = update_buf->rm_update->width; + height = update_buf->rm_update->height; + } else { + stride = io_cfg->planes[i].plane_stride; + width = io_cfg->planes[i].width; + height = io_cfg->planes[i].height; + } + + /* update size register */ + cam_sfe_bus_rd_pxls_to_bytes(width, + rm_data->unpacker_cfg, &rm_data->width); + rm_data->height = height; + + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + rm_data->hw_regs->buf_width, rm_data->width); + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + rm_data->hw_regs->buf_height, rm_data->height); + CAM_DBG(CAM_SFE, "SFE:%d RM:%d width:0x%X height:0x%X", + rm_data->common_data->core_index, + rm_data->index, rm_data->width, + rm_data->height); + + rm_data->stride = stride; + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + rm_data->hw_regs->stride, rm_data->stride); + CAM_DBG(CAM_SFE, "SFE:%d RM:%d image_stride:0x%X", + rm_data->common_data->core_index, + rm_data->index, reg_val_pair[j-1]); + + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + rm_data->hw_regs->image_addr, + update_buf->rm_update->image_buf[i]); + CAM_DBG(CAM_SFE, "SFE:%d RM:%d image_address:0x%X", + rm_data->common_data->core_index, + rm_data->index, reg_val_pair[j-1]); + rm_data->img_addr = reg_val_pair[j-1]; + } + + size = sfe_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_SFE, + "Failed! Buf size:%d insufficient, expected size:%d", + update_buf->cmd.size, size); + return -ENOMEM; + } + + sfe_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_sfe_bus_rd_update_fs_cfg(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bus_rd_priv *bus_priv; + struct cam_sfe_bus_rd_data *sfe_bus_rd_data = NULL; + struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL; + struct cam_sfe_fe_update_args *fe_upd_args; + struct cam_fe_config *fe_cfg; + struct cam_sfe_bus_rd_common_data *common_data; + int i = 0; + + bus_priv = (struct cam_sfe_bus_rd_priv *) priv; + fe_upd_args = (struct cam_sfe_fe_update_args *)cmd_args; + + sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *) + fe_upd_args->node_res->res_priv; + + if (!sfe_bus_rd_data || !sfe_bus_rd_data->cdm_util_ops) { + CAM_ERR(CAM_SFE, "Failed! Invalid data"); + return -EINVAL; + } + + fe_cfg = &fe_upd_args->fe_config; + + for (i = 0; i < sfe_bus_rd_data->num_rm; i++) { + + rm_data = sfe_bus_rd_data->rm_res[i]->res_priv; + common_data = rm_data->common_data; + + rm_data->format = fe_cfg->format; + rm_data->unpacker_cfg = fe_cfg->unpacker_cfg; + rm_data->latency_buf_allocation = fe_cfg->latency_buf_size; + rm_data->stride = fe_cfg->stride; + rm_data->hbi_count = fe_cfg->hbi_count; + rm_data->fs_mode = fe_cfg->fs_mode; + rm_data->min_vbi = fe_cfg->min_vbi; + sfe_bus_rd_data->fs_sync_enable = + fe_cfg->fs_sync_enable; + sfe_bus_rd_data->fs_line_sync_en = + fe_cfg->fs_line_sync_en; + + CAM_DBG(CAM_SFE, + "SFE:%d RM:%d format:0x%x unpacker_cfg:0x%x", + rm_data->format, rm_data->unpacker_cfg); + CAM_DBG(CAM_SFE, + "latency_buf_alloc:0x%x stride:0x%x", + rm_data->latency_buf_allocation, rm_data->stride); + CAM_DBG(CAM_SFE, + "fs_sync_en:%d hbi_cnt:0x%x fs_mode:0x%x min_vbi:0x%x", + sfe_bus_rd_data->fs_sync_enable, + rm_data->hbi_count, rm_data->fs_mode, + rm_data->min_vbi); + } + return 0; +} + +static int cam_sfe_bus_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_sfe_bus_rd_priv *bus_priv = hw_priv; + uint32_t sfe_top_irq_mask = 0; + uint32_t offset = 0; + struct cam_sfe_bus_rd_reg_offset_common *common_reg; + + if (!bus_priv) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + common_reg = bus_priv->common_data.common_reg; + sfe_top_irq_mask = (1 << bus_priv->top_irq_shift); + + /* Subscribe for error IRQs */ + + /* BUS_RD_TEST_BUS_CTRL disabling test bus */ + offset = common_reg->test_bus_ctrl; + cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset); + + return 0; +} + +static int cam_sfe_bus_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_sfe_bus_rd_priv *bus_priv = hw_priv; + uint32_t sfe_top_irq_mask = 0; + int rc = 0; + + if (!bus_priv) { + CAM_ERR(CAM_SFE, "Error: Invalid args"); + return -EINVAL; + } + + sfe_top_irq_mask = 1 << bus_priv->top_irq_shift; + + /* Unsubscribe for err irqs */ + + return rc; +} + +static int cam_sfe_bus_rd_process_cmd( + void *priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + int rc = -EINVAL; + + if (!priv || !cmd_args) { + CAM_ERR_RATE_LIMIT(CAM_SFE, + "Invalid input arguments"); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM: + rc = cam_sfe_bus_rd_update_rm(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = cam_sfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD: + rc = cam_sfe_bus_rd_update_fs_cfg(priv, cmd_args, arg_size); + break; + default: + CAM_ERR_RATE_LIMIT(CAM_SFE, + "Invalid SFE BUS RD command type: %d", + cmd_type); + break; + } + + return rc; +} + +int cam_sfe_bus_rd_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + struct cam_sfe_bus **sfe_bus) +{ + int i, rc = 0; + struct cam_sfe_bus_rd_priv *bus_priv = NULL; + struct cam_sfe_bus *sfe_bus_local; + struct cam_sfe_bus_rd_hw_info *bus_rd_hw_info = bus_hw_info; + + if (!soc_info || !hw_intf || !bus_hw_info) { + CAM_ERR(CAM_SFE, + "Invalid_params soc_info:%pK hw_intf:%pK hw_info:%pK data:%pK", + soc_info, hw_intf, bus_rd_hw_info); + rc = -EINVAL; + goto end; + } + + sfe_bus_local = kzalloc(sizeof(struct cam_sfe_bus), GFP_KERNEL); + if (!sfe_bus_local) { + CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus"); + rc = -ENOMEM; + goto end; + } + + bus_priv = kzalloc(sizeof(struct cam_sfe_bus_rd_priv), + GFP_KERNEL); + if (!bus_priv) { + CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus_priv"); + rc = -ENOMEM; + goto free_bus_local; + } + + sfe_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.core_index = soc_info->index; + bus_priv->common_data.mem_base = + CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX); + bus_priv->common_data.hw_intf = hw_intf; + bus_priv->common_data.common_reg = &bus_rd_hw_info->common_reg; + bus_priv->top_irq_shift = bus_rd_hw_info->top_irq_shift; + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_sfe_bus_init_rm_resource(i, bus_priv, bus_hw_info, + &bus_priv->bus_client[i]); + if (rc < 0) { + CAM_ERR(CAM_SFE, "Init RM failed rc=%d", rc); + goto deinit_rm; + } + } + + for (i = 0; i < bus_priv->num_bus_rd_resc; i++) { + rc = cam_sfe_bus_init_sfe_bus_read_resource(i, bus_priv, + bus_rd_hw_info); + if (rc < 0) { + CAM_ERR(CAM_SFE, "Init SFE RD failed rc=%d", rc); + goto deinit_sfe_bus_rd; + } + } + + sfe_bus_local->hw_ops.reserve = cam_sfe_bus_acquire_bus_rd; + sfe_bus_local->hw_ops.release = cam_sfe_bus_release_bus_rd; + sfe_bus_local->hw_ops.start = cam_sfe_bus_start_bus_rd; + sfe_bus_local->hw_ops.stop = cam_sfe_bus_stop_bus_rd; + sfe_bus_local->hw_ops.init = cam_sfe_bus_init_hw; + sfe_bus_local->hw_ops.deinit = cam_sfe_bus_deinit_hw; + sfe_bus_local->bottom_half_handler = NULL; + sfe_bus_local->hw_ops.process_cmd = cam_sfe_bus_rd_process_cmd; + + *sfe_bus = sfe_bus_local; + + return rc; + +deinit_sfe_bus_rd: + if (i < 0) + i = CAM_SFE_BUS_RD_MAX; + for (--i; i >= 0; i--) + cam_sfe_bus_deinit_sfe_bus_rd_resource( + &bus_priv->sfe_bus_rd[i]); +deinit_rm: + if (i < 0) + i = bus_priv->num_client; + for (--i; i >= 0; i--) + cam_sfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]); + + kfree(sfe_bus_local->bus_priv); + +free_bus_local: + kfree(sfe_bus_local); + +end: + return rc; +} + +int cam_sfe_bus_rd_deinit( + struct cam_sfe_bus **sfe_bus) +{ + int i, rc = 0; + struct cam_sfe_bus_rd_priv *bus_priv = NULL; + struct cam_sfe_bus *sfe_bus_local; + + if (!sfe_bus || !*sfe_bus) { + CAM_ERR(CAM_SFE, "Invalid input"); + return -EINVAL; + } + sfe_bus_local = *sfe_bus; + + bus_priv = sfe_bus_local->bus_priv; + if (!bus_priv) { + CAM_ERR(CAM_SFE, "bus_priv is NULL"); + rc = -ENODEV; + goto free_bus_local; + } + + for (i = 0; i < bus_priv->num_client; i++) { + rc = cam_sfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]); + if (rc < 0) + CAM_ERR(CAM_SFE, + "Deinit RM failed rc=%d", rc); + } + for (i = 0; i < CAM_SFE_BUS_RD_MAX; i++) { + rc = cam_sfe_bus_deinit_sfe_bus_rd_resource( + &bus_priv->sfe_bus_rd[i]); + if (rc < 0) + CAM_ERR(CAM_SFE, + "Deinit SFE RD failed rc=%d", rc); + } + + kfree(sfe_bus_local->bus_priv); + +free_bus_local: + kfree(sfe_bus_local); + + *sfe_bus = NULL; + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h new file mode 100644 index 000000000000..e3dd0988105b --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_BUS_RD_H_ +#define _CAM_SFE_BUS_RD_H_ + +#include "cam_sfe_bus.h" + +#define CAM_SFE_BUS_RD_MAX_CLIENTS 3 + +enum cam_sfe_bus_rd_type { + CAM_SFE_BUS_RD_RDI0, + CAM_SFE_BUS_RD_RDI1, + CAM_SFE_BUS_RD_RDI2, + CAM_SFE_BUS_RD_MAX, +}; + +/* + * struct cam_sfe_bus_rd_reg_offset_common: + * + * @Brief: Common registers across BUS RD Clients + */ +struct cam_sfe_bus_rd_reg_offset_common { + uint32_t hw_version; + uint32_t misr_reset; + uint32_t pwr_iso_cfg; + uint32_t input_if_cmd; + uint32_t test_bus_ctrl; + uint32_t security_cfg; +}; + +/* + * struct cam_sfe_bus_rd_reg_offset_bus_client: + * + * @Brief: Register offsets for BUS RD Clients + */ +struct cam_sfe_bus_rd_reg_offset_bus_client { + uint32_t cfg; + uint32_t image_addr; + uint32_t buf_width; + uint32_t buf_height; + uint32_t stride; + uint32_t unpacker_cfg; + uint32_t latency_buf_allocation; +}; + +/* + * struct cam_sfe_bus_rd_hw_info: + * + * @Brief: HW capability of SFE Bus RD Client + */ +struct cam_sfe_bus_rd_info { + enum cam_sfe_bus_rd_type sfe_bus_rd_type; + uint32_t max_width; + uint32_t max_height; +}; + +/* + * struct cam_sfe_bus_rd_hw_info: + * + * @Brief: HW register info for entire Bus + * + * @common_reg: Common register details + * @num_client: Number of bus rd clients + * @bus_client_reg: Bus client register info + * @num_bus_rd_resc: Number of SFE BUS RD masters + * @sfe_bus_rd_info: SFE bus rd client info + * @top_irq_shift: Top irq shift val + */ +struct cam_sfe_bus_rd_hw_info { + struct cam_sfe_bus_rd_reg_offset_common common_reg; + uint32_t num_client; + struct cam_sfe_bus_rd_reg_offset_bus_client + bus_client_reg[CAM_SFE_BUS_RD_MAX_CLIENTS]; + uint32_t num_bus_rd_resc; + struct cam_sfe_bus_rd_info + sfe_bus_rd_info[CAM_SFE_BUS_RD_MAX]; + uint32_t top_irq_shift; +}; + +/* + * cam_sfe_bus_rd_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 + * @sfe_bus: Pointer to sfe_bus structure which will be filled + * and returned on successful initialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_bus_rd_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + struct cam_sfe_bus **sfe_bus); + +/* + * cam_sfe_bus_rd_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @vfe_bus: Pointer to sfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_bus_rd_deinit(struct cam_sfe_bus **sfe_bus); + +#endif /* _CAM_SFE_BUS_RD_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c new file mode 100644 index 000000000000..9dac41227e24 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c @@ -0,0 +1,1995 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + + +#include +#include + +#include + +#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_sfe_hw_intf.h" +#include "cam_irq_controller.h" +#include "cam_tasklet_util.h" +#include "cam_sfe_bus.h" +#include "cam_sfe_bus_wr.h" +#include "cam_sfe_core.h" +#include "cam_sfe_soc.h" +#include "cam_debug_util.h" +#include "cam_cpas_api.h" +#include "cam_trace.h" + +static const char drv_name[] = "sfe_bus_wr"; + +#define CAM_SFE_BUS_WR_PAYLOAD_MAX 256 + +#define CAM_SFE_RDI_BUS_DEFAULT_WIDTH 0xFFFF +#define CAM_SFE_RDI_BUS_DEFAULT_STRIDE 0xFFFF + +#define MAX_BUF_UPDATE_REG_NUM \ + (sizeof(struct cam_sfe_bus_reg_offset_bus_client) / 4) +#define MAX_REG_VAL_PAIR_SIZE \ + (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) + +enum cam_sfe_bus_wr_packer_format { + PACKER_FMT_PLAIN_128, + PACKER_FMT_PLAIN_8, + PACKER_FMT_PLAIN_8_ODD_EVEN, + PACKER_FMT_PLAIN_8_LSB_MSB_10, + PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN, + PACKER_FMT_PLAIN_16_10BPP, + PACKER_FMT_PLAIN_16_12BPP, + PACKER_FMT_PLAIN_16_14BPP, + PACKER_FMT_PLAIN_16_16BPP, + PACKER_FMT_PLAIN_32, + PACKER_FMT_PLAIN_64, + PACKER_FMT_TP_10, + PACKER_FMT_MIPI10, + PACKER_FMT_MIPI12, + PACKER_FMT_MIPI14, + PACKER_FMT_MIPI20, + PACKER_FMT_PLAIN_32_20BPP, + PACKER_FMT_MAX, +}; + +struct cam_sfe_bus_wr_common_data { + uint32_t core_index; + uint32_t hw_version; + void __iomem *mem_base; + struct cam_hw_intf *hw_intf; + void *buf_done_controller; + struct cam_sfe_bus_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 addr_no_sync; + uint32_t comp_done_shift; + bool hw_init; + cam_hw_mgr_event_cb_func event_cb; +}; + +struct cam_sfe_wr_scratch_buf_info { + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t slice_height; + dma_addr_t io_addr; +}; + +struct cam_sfe_bus_wr_wm_resource_data { + uint32_t index; + struct cam_sfe_bus_wr_common_data *common_data; + struct cam_sfe_bus_reg_offset_bus_client *hw_regs; + struct cam_sfe_wr_scratch_buf_info scratch_buf_info; + + bool init_cfg_done; + bool hfr_cfg_done; + + uint32_t offset; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; + enum cam_sfe_bus_wr_packer_format pack_fmt; + + uint32_t packer_cfg; + uint32_t h_init; + + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + + uint32_t en_cfg; + uint32_t is_dual; + + uint32_t acquired_width; + uint32_t acquired_height; +}; + +struct cam_sfe_bus_wr_comp_grp_data { + enum cam_sfe_bus_wr_comp_grp_type comp_grp_type; + struct cam_sfe_bus_wr_common_data *common_data; + + uint32_t is_master; + uint32_t is_dual; + uint32_t dual_slave_core; + uint32_t intra_client_mask; + uint32_t addr_sync_mode; + uint32_t composite_mask; + + uint32_t acquire_dev_cnt; + uint32_t irq_trigger_cnt; +}; + +struct cam_sfe_bus_wr_out_data { + uint32_t out_type; + uint32_t source_group; + struct cam_sfe_bus_wr_common_data *common_data; + + uint32_t num_wm; + struct cam_isp_resource_node *wm_res; + + struct cam_isp_resource_node *comp_grp; + struct list_head sfe_out_list; + + uint32_t is_master; + uint32_t is_dual; + + uint32_t format; + uint32_t max_width; + uint32_t max_height; + struct cam_cdm_utils_ops *cdm_util_ops; + uint32_t secure_mode; + void *priv; +}; + +struct cam_sfe_bus_wr_priv { + struct cam_sfe_bus_wr_common_data common_data; + uint32_t num_client; + uint32_t num_out; + uint32_t num_comp_grp; + uint32_t top_irq_shift; + + struct cam_isp_resource_node *comp_grp; + struct cam_isp_resource_node *sfe_out; + + struct list_head free_comp_grp; + struct list_head used_comp_grp; + + //int bus_irq_handle; + //int rup_irq_handle; + //int error_irq_handle; + //void *tasklet_info; +}; + +static int cam_sfe_bus_wr_process_cmd( + struct cam_isp_resource_node *priv, + uint32_t cmd_type, void *cmd_args, + uint32_t arg_size); + +static bool cam_sfe_bus_can_be_secure(uint32_t out_type) +{ + switch (out_type) { + case CAM_SFE_BUS_SFE_OUT_RAW_DUMP: + case CAM_SFE_BUS_SFE_OUT_RDI0: + case CAM_SFE_BUS_SFE_OUT_RDI1: + case CAM_SFE_BUS_SFE_OUT_RDI2: + case CAM_SFE_BUS_SFE_OUT_RDI3: + case CAM_SFE_BUS_SFE_OUT_RDI4: + return true; + case CAM_SFE_BUS_SFE_OUT_LCR: + case CAM_SFE_BUS_SFE_OUT_BE_0: + case CAM_SFE_BUS_SFE_OUT_BHIST_0: + case CAM_SFE_BUS_SFE_OUT_BE_1: + case CAM_SFE_BUS_SFE_OUT_BHIST_1: + case CAM_SFE_BUS_SFE_OUT_BE_2: + case CAM_SFE_BUS_SFE_OUT_BHIST_2: + default: + return false; + } +} + +static enum cam_sfe_bus_sfe_out_type + cam_sfe_bus_wr_get_out_res_id(uint32_t res_type) +{ + switch (res_type) { + case CAM_ISP_SFE_OUT_RES_RAW_DUMP: + return CAM_SFE_BUS_SFE_OUT_RAW_DUMP; + case CAM_ISP_SFE_OUT_RES_RDI_0: + return CAM_SFE_BUS_SFE_OUT_RDI0; + case CAM_ISP_SFE_OUT_RES_RDI_1: + return CAM_SFE_BUS_SFE_OUT_RDI1; + case CAM_ISP_SFE_OUT_RES_RDI_2: + return CAM_SFE_BUS_SFE_OUT_RDI2; + case CAM_ISP_SFE_OUT_RES_RDI_3: + return CAM_SFE_BUS_SFE_OUT_RDI3; + case CAM_ISP_SFE_OUT_RES_RDI_4: + return CAM_SFE_BUS_SFE_OUT_RDI4; + case CAM_ISP_SFE_OUT_BE_STATS_0: + return CAM_SFE_BUS_SFE_OUT_BE_0; + case CAM_ISP_SFE_OUT_BHIST_STATS_0: + return CAM_SFE_BUS_SFE_OUT_BHIST_0; + case CAM_ISP_SFE_OUT_BE_STATS_1: + return CAM_SFE_BUS_SFE_OUT_BE_1; + case CAM_ISP_SFE_OUT_BHIST_STATS_1: + return CAM_SFE_BUS_SFE_OUT_BHIST_1; + case CAM_ISP_SFE_OUT_BE_STATS_2: + return CAM_SFE_BUS_SFE_OUT_BE_2; + case CAM_ISP_SFE_OUT_BHIST_STATS_2: + return CAM_SFE_BUS_SFE_OUT_BHIST_2; + case CAM_ISP_SFE_OUT_RES_LCR: + return CAM_SFE_BUS_SFE_OUT_LCR; + default: + return CAM_SFE_BUS_SFE_OUT_MAX; + } +} + +static enum cam_sfe_bus_wr_packer_format + cam_sfe_bus_get_packer_fmt(uint32_t out_fmt, int wm_index) +{ + switch (out_fmt) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PD8: + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_MIPI_RAW_10: + if (wm_index == 0) + return PACKER_FMT_MIPI10; + else + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_MIPI_RAW_12: + if (wm_index == 0) + return PACKER_FMT_MIPI12; + else + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_MIPI_RAW_14: + if (wm_index == 0) + return PACKER_FMT_MIPI14; + else + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_MIPI_RAW_20: + if (wm_index == 0) + return PACKER_FMT_MIPI20; + else + return PACKER_FMT_PLAIN_128; + case CAM_FORMAT_PLAIN8: + return PACKER_FMT_PLAIN_8; + case CAM_FORMAT_NV12: + case CAM_FORMAT_UBWC_NV12: + case CAM_FORMAT_UBWC_NV12_4R: + case CAM_FORMAT_Y_ONLY: + return PACKER_FMT_PLAIN_8_LSB_MSB_10; + case CAM_FORMAT_PLAIN16_10: + return PACKER_FMT_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return PACKER_FMT_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return PACKER_FMT_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN16_16: + return PACKER_FMT_PLAIN_16_16BPP; + case CAM_FORMAT_PLAIN32: + case CAM_FORMAT_ARGB: + return PACKER_FMT_PLAIN_32; + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_ARGB_16: + case CAM_FORMAT_PD10: + return PACKER_FMT_PLAIN_64; + case CAM_FORMAT_UBWC_TP10: + case CAM_FORMAT_TP10: + return PACKER_FMT_TP_10; + default: + return PACKER_FMT_MAX; + } +} + +static int cam_sfe_bus_acquire_wm( + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_isp_out_port_generic_info *out_port_info, + void *tasklet, + enum cam_sfe_bus_sfe_out_type sfe_out_res_id, + enum cam_sfe_bus_plane_type plane, + struct cam_isp_resource_node *wm_res, + uint32_t *comp_done_mask, + uint32_t is_dual, + enum cam_sfe_bus_wr_comp_grp_type *comp_grp_id) +{ + int32_t wm_idx = 0; + struct cam_sfe_bus_wr_wm_resource_data *rsrc_data = NULL; + char wm_mode[50] = {0}; + + if (wm_res->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_SFE, "WM:%d not available state:%d", + wm_idx, wm_res->res_state); + return -EALREADY; + } + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + wm_res->tasklet_info = tasklet; + + rsrc_data = wm_res->res_priv; + wm_idx = rsrc_data->index; + rsrc_data->format = out_port_info->format; + rsrc_data->pack_fmt = cam_sfe_bus_get_packer_fmt(rsrc_data->format, + wm_idx); + + rsrc_data->width = out_port_info->width; + rsrc_data->height = out_port_info->height; + rsrc_data->is_dual = is_dual; + /* Set WM offset value to default */ + rsrc_data->offset = 0; + CAM_DBG(CAM_SFE, "WM:%d width %d height %d", rsrc_data->index, + rsrc_data->width, rsrc_data->height); + + if ((sfe_out_res_id >= CAM_SFE_BUS_SFE_OUT_RDI0) && + (sfe_out_res_id <= CAM_SFE_BUS_SFE_OUT_RDI4)) { + + rsrc_data->pack_fmt = 0x0; + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_6: + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_MIPI_RAW_14: + case CAM_FORMAT_MIPI_RAW_16: + case CAM_FORMAT_MIPI_RAW_20: + case CAM_FORMAT_PLAIN128: + case CAM_FORMAT_PLAIN32_20: + rsrc_data->width = CAM_SFE_RDI_BUS_DEFAULT_WIDTH; + rsrc_data->height = 0; + rsrc_data->stride = CAM_SFE_RDI_BUS_DEFAULT_STRIDE; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + case CAM_FORMAT_PLAIN8: + rsrc_data->en_cfg = 0x1; + rsrc_data->stride = rsrc_data->width * 2; + break; + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + rsrc_data->width = + ALIGNUP(rsrc_data->width * 2, 16) / 16; + rsrc_data->en_cfg = 0x1; + break; + case CAM_FORMAT_PLAIN64: + rsrc_data->width = + ALIGNUP(rsrc_data->width * 8, 16) / 16; + rsrc_data->en_cfg = 0x1; + break; + default: + CAM_ERR(CAM_SFE, "Unsupported RDI format %d", + rsrc_data->format); + return -EINVAL; + } + + } else if (sfe_out_res_id == CAM_SFE_BUS_SFE_OUT_RAW_DUMP) { + rsrc_data->stride = rsrc_data->width; + rsrc_data->en_cfg = 0x1; + } else if ((sfe_out_res_id >= CAM_SFE_BUS_SFE_OUT_BE_0) && + (sfe_out_res_id <= CAM_SFE_BUS_SFE_OUT_BHIST_2)) { + + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + + } else if (sfe_out_res_id == CAM_SFE_BUS_SFE_OUT_LCR) { + + switch (rsrc_data->format) { + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + case CAM_FORMAT_PLAIN16_14: + case CAM_FORMAT_PLAIN16_16: + rsrc_data->stride = ALIGNUP(rsrc_data->width * 2, 8); + rsrc_data->en_cfg = 0x1; + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x20; + break; + default: + CAM_ERR(CAM_SFE, "Invalid format %d out_type:%d", + rsrc_data->format, sfe_out_res_id); + return -EINVAL; + } + + } else { + CAM_ERR(CAM_SFE, "Invalid out_type:%d requested", + sfe_out_res_id); + return -EINVAL; + } + + *comp_grp_id = rsrc_data->hw_regs->comp_group; + *comp_done_mask |= (1 << sfe_out_res_id); + + switch (rsrc_data->en_cfg) { + case 0x1: + strlcpy(wm_mode, "line-based", sizeof(wm_mode)); + break; + case ((0x1 << 16) | 0x1): + strlcpy(wm_mode, "frame-based", sizeof(wm_mode)); + break; + case ((0x2 << 16) | 0x1): + strlcpy(wm_mode, "index-based", sizeof(wm_mode)); + break; + } + + CAM_DBG(CAM_SFE, + "SFE:%d WM:%d processed width:%d height:%d format:0x%X pack_fmt 0x%x %s", + rsrc_data->common_data->core_index, rsrc_data->index, + rsrc_data->width, rsrc_data->height, rsrc_data->format, + rsrc_data->pack_fmt, wm_mode); + return 0; +} + +static int cam_sfe_bus_release_wm(void *bus_priv, + struct cam_isp_resource_node *wm_res) +{ + struct cam_sfe_bus_wr_wm_resource_data *rsrc_data = + wm_res->res_priv; + + rsrc_data->offset = 0; + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 0; + rsrc_data->format = 0; + rsrc_data->pack_fmt = 0; + rsrc_data->irq_subsample_period = 0; + rsrc_data->irq_subsample_pattern = 0; + rsrc_data->framedrop_period = 0; + rsrc_data->framedrop_pattern = 0; + rsrc_data->packer_cfg = 0; + rsrc_data->h_init = 0; + rsrc_data->init_cfg_done = false; + rsrc_data->hfr_cfg_done = false; + rsrc_data->en_cfg = 0; + rsrc_data->is_dual = 0; + + wm_res->tasklet_info = NULL; + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + CAM_DBG(CAM_SFE, "SFE:%d Release WM:%d", + rsrc_data->common_data->core_index, rsrc_data->index); + + return 0; +} + +static int cam_sfe_bus_start_wm(struct cam_isp_resource_node *wm_res) +{ + const uint32_t image_cfg_height_shift_val = 16; + struct cam_sfe_bus_wr_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_sfe_bus_wr_common_data *common_data = + rsrc_data->common_data; + + cam_io_w((rsrc_data->height << image_cfg_height_shift_val) + | rsrc_data->width, common_data->mem_base + + rsrc_data->hw_regs->image_cfg_0); + cam_io_w(rsrc_data->pack_fmt, + common_data->mem_base + rsrc_data->hw_regs->packer_cfg); + + /* Enable WM */ + cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + + rsrc_data->hw_regs->cfg); + + CAM_DBG(CAM_SFE, + "Start SFE:%d WM:%d offset:0x%X en_cfg:0x%X width:%d height:%d", + rsrc_data->common_data->core_index, rsrc_data->index, + (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg, + rsrc_data->width, rsrc_data->height); + CAM_DBG(CAM_SFE, "WM:%d pk_fmt:%d stride:%d", + rsrc_data->index, rsrc_data->pack_fmt & PACKER_FMT_MAX, + rsrc_data->stride); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return 0; +} + +static int cam_sfe_bus_stop_wm(struct cam_isp_resource_node *wm_res) +{ + struct cam_sfe_bus_wr_wm_resource_data *rsrc_data = + wm_res->res_priv; + struct cam_sfe_bus_wr_common_data *common_data = + rsrc_data->common_data; + + /* Disable WM */ + cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg); + CAM_DBG(CAM_SFE, "Stop SFE:%d WM:%d", + rsrc_data->common_data->core_index, rsrc_data->index); + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + rsrc_data->init_cfg_done = false; + rsrc_data->hfr_cfg_done = false; + + return 0; +} + +static int cam_sfe_bus_handle_wm_done_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + return -EPERM; +} + +static int cam_sfe_bus_handle_wm_done_bottom_half(void *wm_node, + void *evt_payload_priv) +{ + return -EPERM; +} + +static int cam_sfe_bus_init_wm_resource(uint32_t index, + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_sfe_bus_wr_hw_info *hw_info, + struct cam_isp_resource_node *wm_res) +{ + struct cam_sfe_bus_wr_wm_resource_data *rsrc_data; + + rsrc_data = kzalloc(sizeof(struct cam_sfe_bus_wr_wm_resource_data), + GFP_KERNEL); + if (!rsrc_data) { + CAM_DBG(CAM_SFE, "Failed to alloc for WM res priv"); + return -ENOMEM; + } + wm_res->res_priv = rsrc_data; + + rsrc_data->index = index; + rsrc_data->hw_regs = &hw_info->bus_client_reg[index]; + rsrc_data->common_data = &bus_priv->common_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = cam_sfe_bus_start_wm; + wm_res->stop = cam_sfe_bus_stop_wm; + wm_res->top_half_handler = cam_sfe_bus_handle_wm_done_top_half; + wm_res->bottom_half_handler = + cam_sfe_bus_handle_wm_done_bottom_half; + wm_res->hw_intf = bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_sfe_bus_deinit_wm_resource( + struct cam_isp_resource_node *wm_res) +{ + struct cam_sfe_bus_wr_wm_resource_data *rsrc_data; + + wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&wm_res->list); + + wm_res->start = NULL; + wm_res->stop = NULL; + wm_res->top_half_handler = NULL; + wm_res->bottom_half_handler = NULL; + wm_res->hw_intf = NULL; + + rsrc_data = wm_res->res_priv; + wm_res->res_priv = NULL; + if (!rsrc_data) + return -ENOMEM; + kfree(rsrc_data); + + return 0; +} + +static void cam_sfe_bus_add_wm_to_comp_grp( + struct cam_isp_resource_node *comp_grp, + uint32_t composite_mask) +{ + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = comp_grp->res_priv; + + rsrc_data->composite_mask |= composite_mask; +} + +static bool cam_sfe_bus_match_comp_grp( + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_isp_resource_node **comp_grp, + uint32_t comp_grp_id) +{ + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = NULL; + struct cam_isp_resource_node *comp_grp_local = NULL; + + list_for_each_entry(comp_grp_local, + &bus_priv->used_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_type == comp_grp_id) { + /* Match found */ + *comp_grp = comp_grp_local; + return true; + } + } + + list_for_each_entry(comp_grp_local, + &bus_priv->free_comp_grp, list) { + rsrc_data = comp_grp_local->res_priv; + if (rsrc_data->comp_grp_type == comp_grp_id) { + /* Match found */ + *comp_grp = comp_grp_local; + list_del(&comp_grp_local->list); + list_add_tail(&comp_grp_local->list, + &bus_priv->used_comp_grp); + return false; + } + } + + *comp_grp = NULL; + return false; +} + +static int cam_sfe_bus_acquire_comp_grp( + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_isp_out_port_generic_info *out_port_info, + void *tasklet, + uint32_t is_dual, + uint32_t is_master, + struct cam_isp_resource_node **comp_grp, + enum cam_sfe_bus_wr_comp_grp_type comp_grp_id) +{ + int rc = 0; + struct cam_isp_resource_node *comp_grp_local = NULL; + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = NULL; + bool previously_acquired = false; + + /* Check if matching comp_grp has already been acquired */ + previously_acquired = cam_sfe_bus_match_comp_grp( + bus_priv, &comp_grp_local, comp_grp_id); + + if (!comp_grp_local) { + CAM_ERR(CAM_SFE, "Invalid comp_grp:%d", comp_grp_id); + return -ENODEV; + } + + rsrc_data = comp_grp_local->res_priv; + + if (!previously_acquired) { + rsrc_data->intra_client_mask = 0x1; + comp_grp_local->tasklet_info = tasklet; + comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + rsrc_data->is_master = is_master; + rsrc_data->is_dual = is_dual; + + if (is_master) + rsrc_data->addr_sync_mode = 0; + else + rsrc_data->addr_sync_mode = 1; + + } else { + rsrc_data = comp_grp_local->res_priv; + /* Do not support runtime change in composite mask */ + if (comp_grp_local->res_state == + CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_SFE, "Invalid State %d comp_grp:%u", + comp_grp_local->res_state, + rsrc_data->comp_grp_type); + return -EBUSY; + } + } + + CAM_DBG(CAM_SFE, "Acquire SFE:%d comp_grp:%u", + rsrc_data->common_data->core_index, rsrc_data->comp_grp_type); + + rsrc_data->acquire_dev_cnt++; + *comp_grp = comp_grp_local; + + return rc; +} + +static int cam_sfe_bus_release_comp_grp( + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_isp_resource_node *in_comp_grp) +{ + struct cam_isp_resource_node *comp_grp = NULL; + struct cam_sfe_bus_wr_comp_grp_data *in_rsrc_data = NULL; + int match_found = 0; + + if (!in_comp_grp) { + CAM_ERR(CAM_SFE, "Invalid Params comp_grp %pK", in_comp_grp); + return -EINVAL; + } + + if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_SFE, "Already released comp_grp"); + return 0; + } + + if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_SFE, "Invalid State %d", + in_comp_grp->res_state); + return -EBUSY; + } + + in_rsrc_data = in_comp_grp->res_priv; + CAM_DBG(CAM_SFE, "Release SFE:%d comp_grp:%u", + bus_priv->common_data.core_index, + in_rsrc_data->comp_grp_type); + + list_for_each_entry(comp_grp, &bus_priv->used_comp_grp, list) { + if (comp_grp == in_comp_grp) { + match_found = 1; + break; + } + } + + if (!match_found) { + CAM_ERR(CAM_SFE, "Could not find comp_grp:%u", + in_rsrc_data->comp_grp_type); + return -ENODEV; + } + + in_rsrc_data->acquire_dev_cnt--; + if (in_rsrc_data->acquire_dev_cnt == 0) { + list_del(&comp_grp->list); + + in_rsrc_data->dual_slave_core = CAM_SFE_BUS_SFE_CORE_MAX; + in_rsrc_data->addr_sync_mode = 0; + in_rsrc_data->composite_mask = 0; + + comp_grp->tasklet_info = NULL; + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + list_add_tail(&comp_grp->list, &bus_priv->free_comp_grp); + } + + return 0; +} + +static int cam_sfe_bus_start_comp_grp( + struct cam_isp_resource_node *comp_grp, + uint32_t *bus_irq_reg_mask) +{ + int rc = 0; + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = NULL; + struct cam_sfe_bus_wr_common_data *common_data = NULL; + + rsrc_data = comp_grp->res_priv; + common_data = rsrc_data->common_data; + + CAM_DBG(CAM_SFE, + "Start SFE:%d comp_grp:%d streaming state:%d comp_mask:0x%X", + rsrc_data->common_data->core_index, + rsrc_data->comp_grp_type, comp_grp->res_state, + rsrc_data->composite_mask); + + if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) + return 0; + + /* TO DO Enable top irq */ + + CAM_DBG(CAM_SFE, "Start Done SFE:%d comp_grp:%d", + rsrc_data->common_data->core_index, + rsrc_data->comp_grp_type, + bus_irq_reg_mask[0]); + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + return rc; +} + +static inline int cam_sfe_bus_stop_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + return 0; +} + +static int cam_sfe_bus_wr_init_comp_grp(uint32_t index, + struct cam_hw_soc_info *soc_info, + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_sfe_bus_wr_hw_info *hw_info, + struct cam_isp_resource_node *comp_grp) +{ + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = NULL; + + rsrc_data = kzalloc(sizeof(struct cam_sfe_bus_wr_comp_grp_data), + GFP_KERNEL); + if (!rsrc_data) + return -ENOMEM; + + comp_grp->res_priv = rsrc_data; + + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&comp_grp->list); + + rsrc_data->comp_grp_type = index; + rsrc_data->common_data = &bus_priv->common_data; + rsrc_data->dual_slave_core = CAM_SFE_BUS_SFE_CORE_MAX; + + list_add_tail(&comp_grp->list, &bus_priv->free_comp_grp); + + /* TO DO set top half */ + comp_grp->top_half_handler = NULL; + comp_grp->hw_intf = bus_priv->common_data.hw_intf; + + return 0; +} + +static int cam_sfe_bus_deinit_comp_grp( + struct cam_isp_resource_node *comp_grp) +{ + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = + comp_grp->res_priv; + + comp_grp->start = NULL; + comp_grp->stop = NULL; + comp_grp->top_half_handler = NULL; + comp_grp->bottom_half_handler = NULL; + comp_grp->hw_intf = NULL; + + list_del_init(&comp_grp->list); + comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + + comp_grp->res_priv = NULL; + + if (!rsrc_data) { + CAM_ERR(CAM_SFE, "comp_grp_priv is NULL"); + return -ENODEV; + } + kfree(rsrc_data); + + return 0; +} + +static int cam_sfe_bus_wr_get_secure_mode(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_isp_hw_get_cmd_update *secure_mode = cmd_args; + struct cam_sfe_bus_wr_out_data *rsrc_data; + uint32_t *mode; + + rsrc_data = (struct cam_sfe_bus_wr_out_data *) + secure_mode->res->res_priv; + mode = (uint32_t *)secure_mode->data; + *mode = (rsrc_data->secure_mode == CAM_SECURE_MODE_SECURE) ? + true : false; + + return 0; +} + +static int cam_sfe_bus_acquire_sfe_out(void *priv, void *acquire_args, + uint32_t args_size) +{ + int rc = -ENODEV; + int i; + enum cam_sfe_bus_sfe_out_type sfe_out_res_id; + uint32_t format; + struct cam_sfe_bus_wr_priv *bus_priv = priv; + struct cam_sfe_acquire_args *acq_args = acquire_args; + struct cam_sfe_hw_sfe_out_acquire_args *out_acquire_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + uint32_t secure_caps = 0, mode; + enum cam_sfe_bus_wr_comp_grp_type comp_grp_id; + uint32_t client_done_mask = 0; + + if (!bus_priv || !acquire_args) { + CAM_ERR(CAM_SFE, "Invalid Param"); + return -EINVAL; + } + + out_acquire_args = &acq_args->sfe_out; + format = out_acquire_args->out_port_info->format; + + CAM_DBG(CAM_SFE, "SFE:%d Acquire out_type:0x%X", + bus_priv->common_data.core_index, + out_acquire_args->out_port_info->res_type); + + sfe_out_res_id = cam_sfe_bus_wr_get_out_res_id( + out_acquire_args->out_port_info->res_type); + if (sfe_out_res_id == CAM_SFE_BUS_SFE_OUT_MAX) + return -ENODEV; + + rsrc_node = &bus_priv->sfe_out[sfe_out_res_id]; + if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + CAM_ERR(CAM_SFE, + "SFE:%d out_type:0x%X resource not available state:%d", + bus_priv->common_data.core_index, + sfe_out_res_id, rsrc_node->res_state); + return -EBUSY; + } + + if (!acq_args->buf_done_controller) { + CAM_ERR(CAM_SFE, "Invalid buf done controller"); + return -EINVAL; + } + + rsrc_data = rsrc_node->res_priv; + rsrc_data->common_data->buf_done_controller = + acq_args->buf_done_controller; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + secure_caps = cam_sfe_bus_can_be_secure( + rsrc_data->out_type); + mode = out_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_SFE, + "Mismatch: Acquire mode[%d], drvr mode[%d]", + rsrc_data->common_data->secure_mode, + mode); + mutex_unlock( + &rsrc_data->common_data->bus_mutex); + return rc; + } + } + rsrc_data->common_data->num_sec_out++; + } + mutex_unlock(&rsrc_data->common_data->bus_mutex); + + //bus_priv->tasklet_info = acq_args->tasklet; + rsrc_node->rdi_only_ctx = 0; + rsrc_node->res_id = out_acquire_args->out_port_info->res_type; + rsrc_node->tasklet_info = acq_args->tasklet; + rsrc_node->cdm_ops = out_acquire_args->cdm_ops; + rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops; + rsrc_data->format = out_acquire_args->out_port_info->format; + + /* Acquire WM and retrieve COMP GRP ID */ + for (i = 0; i < rsrc_data->num_wm; i++) { + rc = cam_sfe_bus_acquire_wm(bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + sfe_out_res_id, + i, + &rsrc_data->wm_res[i], + &client_done_mask, + out_acquire_args->is_dual, + &comp_grp_id); + if (rc) { + CAM_ERR(CAM_SFE, + "Failed to acquire WM SFE:%d out_type:%d rc:%d", + rsrc_data->common_data->core_index, + sfe_out_res_id, rc); + goto release_wm; + } + } + + /* Acquire composite group using COMP GRP ID */ + rc = cam_sfe_bus_acquire_comp_grp(bus_priv, + out_acquire_args->out_port_info, + acq_args->tasklet, + out_acquire_args->is_dual, + out_acquire_args->is_master, + &rsrc_data->comp_grp, + comp_grp_id); + if (rc) { + CAM_ERR(CAM_SFE, + "Failed to acquire comp_grp SFE:%d out_type:%d rc:%d", + rsrc_data->common_data->core_index, + sfe_out_res_id, rc); + return rc; + } + + rsrc_data->is_dual = out_acquire_args->is_dual; + rsrc_data->is_master = out_acquire_args->is_master; + + cam_sfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp, + client_done_mask); + + rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + out_acquire_args->rsrc_node = rsrc_node; + + CAM_DBG(CAM_SFE, "Acquire successful"); + return rc; + +release_wm: + for (i--; i >= 0; i--) + cam_sfe_bus_release_wm(bus_priv, + &rsrc_data->wm_res[i]); + + cam_sfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp); + + return rc; +} + +static int cam_sfe_bus_release_sfe_out(void *bus_priv, void *release_args, + uint32_t args_size) +{ + uint32_t i; + struct cam_isp_resource_node *sfe_out = NULL; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + uint32_t secure_caps = 0; + + if (!bus_priv || !release_args) { + CAM_ERR(CAM_SFE, "Invalid input bus_priv %pK release_args %pK", + bus_priv, release_args); + return -EINVAL; + } + + sfe_out = release_args; + rsrc_data = sfe_out->res_priv; + + if (sfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_SFE, + "Invalid resource state:%d SFE:%d out_type:0x%X", + sfe_out->res_state, rsrc_data->common_data->core_index, + sfe_out->res_id); + } + + for (i = 0; i < rsrc_data->num_wm; i++) + cam_sfe_bus_release_wm(bus_priv, &rsrc_data->wm_res[i]); + rsrc_data->num_wm = 0; + + if (rsrc_data->comp_grp) + cam_sfe_bus_release_comp_grp(bus_priv, + rsrc_data->comp_grp); + rsrc_data->comp_grp = NULL; + + sfe_out->tasklet_info = NULL; + sfe_out->cdm_ops = NULL; + rsrc_data->cdm_util_ops = NULL; + + secure_caps = cam_sfe_bus_can_be_secure(rsrc_data->out_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_SFE, "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 (sfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) + sfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + + return 0; +} + +static int cam_sfe_bus_start_sfe_out( + struct cam_isp_resource_node *sfe_out) +{ + int rc = 0, i; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + struct cam_sfe_bus_wr_common_data *common_data = NULL; + uint32_t bus_irq_reg_mask[2]; + uint32_t source_group = 0; + + if (!sfe_out) { + CAM_ERR(CAM_SFE, "Invalid input"); + return -EINVAL; + } + + rsrc_data = sfe_out->res_priv; + common_data = rsrc_data->common_data; + source_group = rsrc_data->source_group; + + if (sfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_SFE, + "Invalid resource state:%d SFE:%d out_type:0x%X", + sfe_out->res_state, rsrc_data->common_data->core_index, + rsrc_data->out_type); + return -EACCES; + } + + CAM_DBG(CAM_SFE, "Start SFE:%d out_type:0x%X", + rsrc_data->common_data->core_index, rsrc_data->out_type); + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_sfe_bus_start_wm(&rsrc_data->wm_res[i]); + + memset(bus_irq_reg_mask, 0, sizeof(bus_irq_reg_mask)); + rc = cam_sfe_bus_start_comp_grp(rsrc_data->comp_grp, + bus_irq_reg_mask); + + if (rsrc_data->is_dual && !rsrc_data->is_master) + goto end; + + /* TO DO IRQ handling */ + +end: + sfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return rc; +} + +static int cam_sfe_bus_stop_sfe_out( + struct cam_isp_resource_node *sfe_out) +{ + int rc = 0, i; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + struct cam_sfe_bus_wr_common_data *common_data = NULL; + + if (!sfe_out) { + CAM_ERR(CAM_SFE, "Invalid input"); + return -EINVAL; + } + + rsrc_data = sfe_out->res_priv; + common_data = rsrc_data->common_data; + + if (sfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE || + sfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_DBG(CAM_SFE, "Stop SFE:%d out_type:0x%X state:%d", + rsrc_data->common_data->core_index, rsrc_data->out_type, + sfe_out->res_state); + return rc; + } + + rc = cam_sfe_bus_stop_comp_grp(rsrc_data->comp_grp); + + for (i = 0; i < rsrc_data->num_wm; i++) + rc = cam_sfe_bus_stop_wm(&rsrc_data->wm_res[i]); + + /* TO DO any IRQ handling */ + sfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + return rc; +} + +static int cam_sfe_bus_init_sfe_out_resource( + uint32_t index, + struct cam_sfe_bus_wr_priv *bus_priv, + struct cam_sfe_bus_wr_hw_info *hw_info) +{ + struct cam_isp_resource_node *sfe_out = NULL; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + int rc = 0, i = 0; + int32_t sfe_out_type = + hw_info->sfe_out_hw_info[index].sfe_out_type; + + if (sfe_out_type < 0 || + sfe_out_type >= CAM_SFE_BUS_SFE_OUT_MAX) { + CAM_ERR(CAM_SFE, "Init SFE Out failed, Invalid type=%d", + sfe_out_type); + return -EINVAL; + } + + sfe_out = &bus_priv->sfe_out[sfe_out_type]; + if (sfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || + sfe_out->res_priv) { + CAM_ERR(CAM_SFE, "sfe_out_type %d has already been initialized", + sfe_out_type); + return -EFAULT; + } + + rsrc_data = kzalloc(sizeof(struct cam_sfe_bus_wr_out_data), + GFP_KERNEL); + if (!rsrc_data) { + rc = -ENOMEM; + return rc; + } + + sfe_out->res_priv = rsrc_data; + + sfe_out->res_type = CAM_ISP_RESOURCE_SFE_OUT; + sfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + INIT_LIST_HEAD(&sfe_out->list); + + rsrc_data->source_group = + hw_info->sfe_out_hw_info[index].source_group; + rsrc_data->out_type = + hw_info->sfe_out_hw_info[index].sfe_out_type; + rsrc_data->common_data = &bus_priv->common_data; + rsrc_data->max_width = + hw_info->sfe_out_hw_info[index].max_width; + rsrc_data->max_height = + hw_info->sfe_out_hw_info[index].max_height; + rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + rsrc_data->num_wm = hw_info->sfe_out_hw_info[index].num_wm; + + rsrc_data->wm_res = kzalloc((sizeof(struct cam_isp_resource_node) * + rsrc_data->num_wm), GFP_KERNEL); + if (!rsrc_data->wm_res) { + CAM_ERR(CAM_SFE, "Failed to alloc for wm_res"); + return -ENOMEM; + } + + rc = cam_sfe_bus_init_wm_resource( + hw_info->sfe_out_hw_info[index].wm_idx, + bus_priv, hw_info, + &rsrc_data->wm_res[i]); + if (rc < 0) { + CAM_ERR(CAM_SFE, "SFE:%d init WM:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + return rc; + } + + /* TO DO top & bh */ + sfe_out->start = cam_sfe_bus_start_sfe_out; + sfe_out->stop = cam_sfe_bus_stop_sfe_out; + sfe_out->top_half_handler = NULL; + sfe_out->bottom_half_handler = NULL; + sfe_out->process_cmd = cam_sfe_bus_wr_process_cmd; + sfe_out->hw_intf = bus_priv->common_data.hw_intf; + sfe_out->irq_handle = 0; + + return 0; +} + +static int cam_sfe_bus_deinit_sfe_out_resource( + struct cam_isp_resource_node *sfe_out) +{ + struct cam_sfe_bus_wr_out_data *rsrc_data = sfe_out->res_priv; + int rc = 0, i = 0; + + if (sfe_out->res_state == CAM_ISP_RESOURCE_STATE_UNAVAILABLE) { + /* + * This is not error. It can happen if the resource is + * never supported in the HW. + */ + return 0; + } + + sfe_out->start = NULL; + sfe_out->stop = NULL; + sfe_out->top_half_handler = NULL; + sfe_out->bottom_half_handler = NULL; + sfe_out->hw_intf = NULL; + sfe_out->irq_handle = 0; + + sfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + INIT_LIST_HEAD(&sfe_out->list); + sfe_out->res_priv = NULL; + + if (!rsrc_data) + return -ENOMEM; + + for (i = 0; i < rsrc_data->num_wm; i++) { + rc = cam_sfe_bus_deinit_wm_resource(&rsrc_data->wm_res[i]); + if (rc < 0) + CAM_ERR(CAM_SFE, + "SFE:%d deinit WM:%d failed rc:%d", + rsrc_data->common_data->core_index, i, rc); + } + + kfree(rsrc_data); + + return 0; +} + +static int cam_sfe_bus_wr_print_dimensions( + enum cam_sfe_bus_sfe_out_type sfe_out_res_id, + struct cam_sfe_bus_wr_priv *bus_priv) +{ + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL; + int i, wm_idx; + + rsrc_node = &bus_priv->sfe_out[sfe_out_res_id]; + rsrc_data = rsrc_node->res_priv; + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_data = (struct cam_sfe_bus_wr_wm_resource_data *) + &rsrc_data->wm_res[i].res_priv; + wm_idx = wm_data->index; + if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { + CAM_ERR(CAM_SFE, "Unsupported SFE out %d", + sfe_out_res_id); + return -EINVAL; + } + + CAM_INFO(CAM_SFE, + "SFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_idx, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); + } + return 0; +} + +static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bus_wr_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_buf; + struct cam_buf_io_cfg *io_cfg = NULL; + struct cam_sfe_bus_wr_out_data *sfe_out_data = NULL; + struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, k, size = 0; + uint32_t frame_inc = 0, val; + uint32_t loop_size = 0, stride = 0, slice_h = 0; + + bus_priv = (struct cam_sfe_bus_wr_priv *) priv; + update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + sfe_out_data = (struct cam_sfe_bus_wr_out_data *) + update_buf->res->res_priv; + + if (!sfe_out_data || !sfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_SFE, "Failed! Invalid data"); + return -EINVAL; + } + + if (update_buf->wm_update->num_buf != sfe_out_data->num_wm) { + CAM_ERR(CAM_SFE, + "Failed! Invalid number buffers:%d required:%d", + update_buf->wm_update->num_buf, sfe_out_data->num_wm); + return -EINVAL; + } + + reg_val_pair = &sfe_out_data->common_data->io_buf_update[0]; + if (update_buf->use_scratch_cfg) + CAM_DBG(CAM_SFE, "Using scratch buf config"); + else + io_cfg = update_buf->wm_update->io_cfg; + + for (i = 0, j = 0; i < sfe_out_data->num_wm; i++) { + if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { + CAM_ERR(CAM_SFE, + "reg_val_pair %d exceeds the array limit %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = (struct cam_sfe_bus_wr_wm_resource_data *) + sfe_out_data->wm_res[i].res_priv; + + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->cfg, wm_data->en_cfg); + CAM_DBG(CAM_SFE, "WM:%d en_cfg 0x%X", + wm_data->index, reg_val_pair[j-1]); + + val = (wm_data->height << 16) | wm_data->width; + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_0, val); + CAM_DBG(CAM_SFE, "WM:%d image height and width 0x%X", + wm_data->index, reg_val_pair[j-1]); + + /* For initial configuration program all bus registers */ + if (update_buf->use_scratch_cfg) { + stride = update_buf->wm_update->stride; + slice_h = update_buf->wm_update->slice_height; + } else { + stride = io_cfg->planes[i].plane_stride; + slice_h = io_cfg->planes[i].slice_height; + } + + val = stride; + CAM_DBG(CAM_SFE, "before stride %d", val); + val = ALIGNUP(val, 16); + if (val != stride && + val != wm_data->stride) + CAM_WARN(CAM_SFE, "Warning stride %u expected %u", + stride, val); + + if (wm_data->stride != val || !wm_data->init_cfg_done) { + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_2, + stride); + wm_data->stride = val; + CAM_DBG(CAM_SFE, "WM:%d image stride 0x%X", + wm_data->index, reg_val_pair[j-1]); + } + + frame_inc = stride * slice_h; + + if (!(wm_data->en_cfg & (0x3 << 16))) { + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_cfg_1, wm_data->h_init); + CAM_DBG(CAM_SFE, "WM:%d h_init 0x%X", + wm_data->index, reg_val_pair[j-1]); + } + + if (wm_data->index > 7) + loop_size = wm_data->irq_subsample_period + 1; + else + loop_size = 1; + + /* WM Image address */ + for (k = 0; k < loop_size; k++) { + if (wm_data->en_cfg & (0x3 << 16)) + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + (update_buf->wm_update->image_buf[i] + + wm_data->offset + k * frame_inc)); + else + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + (update_buf->wm_update->image_buf[i] + + k * frame_inc)); + + CAM_DBG(CAM_SFE, "WM:%d image address 0x%X", + wm_data->index, reg_val_pair[j-1]); + } + + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_incr, frame_inc); + CAM_DBG(CAM_SFE, "WM:%d frame_inc %d", + wm_data->index, reg_val_pair[j-1]); + + /* enable the WM */ + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->cfg, + wm_data->en_cfg); + + /* set initial configuration done */ + if (!wm_data->init_cfg_done) + wm_data->init_cfg_done = true; + } + + size = sfe_out_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_SFE, + "Failed! Buf size:%d insufficient, expected size:%d", + update_buf->cmd.size, size); + return -ENOMEM; + } + + sfe_out_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_sfe_bus_wr_update_hfr(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bus_wr_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_hfr; + struct cam_sfe_bus_wr_out_data *sfe_out_data = NULL; + struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL; + struct cam_isp_port_hfr_config *hfr_cfg = NULL; + uint32_t *reg_val_pair; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_sfe_bus_wr_priv *) priv; + update_hfr = (struct cam_isp_hw_get_cmd_update *) cmd_args; + + sfe_out_data = (struct cam_sfe_bus_wr_out_data *) + update_hfr->res->res_priv; + + if (!sfe_out_data || !sfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_SFE, "Failed! Invalid data"); + return -EINVAL; + } + + reg_val_pair = &sfe_out_data->common_data->io_buf_update[0]; + hfr_cfg = (struct cam_isp_port_hfr_config *)update_hfr->data; + + for (i = 0, j = 0; i < sfe_out_data->num_wm; i++) { + if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { + CAM_ERR(CAM_SFE, + "reg_val_pair %d exceeds the array limit %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + + wm_data = sfe_out_data->wm_res[i].res_priv; + if ((wm_data->framedrop_pattern != + hfr_cfg->framedrop_pattern) || + !wm_data->hfr_cfg_done) { + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_pattern, + hfr_cfg->framedrop_pattern); + wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern; + CAM_DBG(CAM_SFE, "WM:%d framedrop pattern 0x%X", + wm_data->index, wm_data->framedrop_pattern); + } + + if (wm_data->framedrop_period != hfr_cfg->framedrop_period || + !wm_data->hfr_cfg_done) { + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->framedrop_period, + hfr_cfg->framedrop_period); + wm_data->framedrop_period = hfr_cfg->framedrop_period; + CAM_DBG(CAM_SFE, "WM:%d framedrop period 0x%X", + wm_data->index, wm_data->framedrop_period); + } + + if (wm_data->irq_subsample_period != hfr_cfg->subsample_period + || !wm_data->hfr_cfg_done) { + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_period, + hfr_cfg->subsample_period); + wm_data->irq_subsample_period = + hfr_cfg->subsample_period; + CAM_DBG(CAM_SFE, "WM:%d irq subsample period 0x%X", + wm_data->index, wm_data->irq_subsample_period); + } + + if (wm_data->irq_subsample_pattern != hfr_cfg->subsample_pattern + || !wm_data->hfr_cfg_done) { + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->irq_subsample_pattern, + hfr_cfg->subsample_pattern); + wm_data->irq_subsample_pattern = + hfr_cfg->subsample_pattern; + CAM_DBG(CAM_SFE, "WM:%d irq subsample pattern 0x%X", + wm_data->index, wm_data->irq_subsample_pattern); + } + + /* set initial configuration done */ + if (!wm_data->hfr_cfg_done) + wm_data->hfr_cfg_done = true; + } + + size = sfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2); + + /* cdm util returns dwords, need to convert to bytes */ + if ((size * 4) > update_hfr->cmd.size) { + CAM_ERR(CAM_SFE, + "Failed! Buf size:%d insufficient, expected size:%d", + update_hfr->cmd.size, size); + return -ENOMEM; + } + + sfe_out_data->cdm_util_ops->cdm_write_regrandom( + update_hfr->cmd.cmd_buf_addr, j/2, reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + update_hfr->cmd.used_bytes = size * 4; + + return 0; +} + +static int cam_sfe_bus_wr_update_stripe_cfg(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bus_wr_priv *bus_priv; + struct cam_isp_hw_dual_isp_update_args *stripe_args; + struct cam_sfe_bus_wr_out_data *sfe_out_data = NULL; + struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL; + struct cam_isp_dual_stripe_config *stripe_config; + uint32_t outport_id, ports_plane_idx, i; + + bus_priv = (struct cam_sfe_bus_wr_priv *) priv; + stripe_args = (struct cam_isp_hw_dual_isp_update_args *)cmd_args; + + sfe_out_data = (struct cam_sfe_bus_wr_out_data *) + stripe_args->res->res_priv; + + if (!sfe_out_data) { + CAM_ERR(CAM_SFE, "Failed! Invalid data"); + return -EINVAL; + } + + outport_id = stripe_args->res->res_id & 0xFF; + if (stripe_args->res->res_id < CAM_ISP_SFE_OUT_RES_BASE || + stripe_args->res->res_id >= CAM_ISP_SFE_OUT_RES_MAX) + return 0; + + ports_plane_idx = (stripe_args->split_id * + (stripe_args->dual_cfg->num_ports * CAM_PACKET_MAX_PLANES)) + + (outport_id * CAM_PACKET_MAX_PLANES); + for (i = 0; i < sfe_out_data->num_wm; i++) { + wm_data = sfe_out_data->wm_res[i].res_priv; + stripe_config = (struct cam_isp_dual_stripe_config *) + &stripe_args->dual_cfg->stripes[ports_plane_idx + i]; + wm_data->width = stripe_config->width; + + /* + * UMD sends buffer offset address as offset for clients + * programmed to operate in frame/index based mode and h_init + * value as offset for clients programmed to operate in line + * based mode. + */ + + if (wm_data->en_cfg & (0x3 << 16)) + wm_data->offset = stripe_config->offset; + else + wm_data->h_init = stripe_config->offset; + + CAM_DBG(CAM_SFE, + "out_type:0x%X WM:%d width:%d offset:0x%X h_init:%d", + stripe_args->res->res_id, wm_data->index, + wm_data->width, wm_data->offset, wm_data->h_init); + } + + return 0; +} + +static int cam_sfe_bus_wr_update_wm_config( + void *cmd_args) +{ + int i; + struct cam_isp_hw_get_cmd_update *wm_config_update; + struct cam_sfe_bus_wr_out_data *sfe_out_data = NULL; + struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL; + struct cam_isp_vfe_wm_config *wm_config = NULL; + + if (!cmd_args) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + + wm_config_update = cmd_args; + sfe_out_data = wm_config_update->res->res_priv; + wm_config = (struct cam_isp_vfe_wm_config *) + wm_config_update->data; + + if (!sfe_out_data || !sfe_out_data->cdm_util_ops || !wm_config) { + CAM_ERR(CAM_SFE, "Invalid data"); + return -EINVAL; + } + + for (i = 0; i < sfe_out_data->num_wm; i++) { + wm_data = sfe_out_data->wm_res[i].res_priv; + + if (wm_config->wm_mode > 0x2) { + CAM_ERR(CAM_SFE, "Invalid wm_mode: 0x%X WM:%d", + wm_config->wm_mode, wm_data->index); + return -EINVAL; + } + + wm_data->en_cfg = (wm_config->wm_mode << 16) | 0x1; + wm_data->width = wm_config->width; + + if (i == PLANE_C) + wm_data->height = wm_config->height / 2; + else + wm_data->height = wm_config->height; + + CAM_DBG(CAM_SFE, + "WM:%d en_cfg:0x%X height:%d width:%d", + wm_data->index, wm_data->en_cfg, wm_data->height, + wm_data->width); + } + + return 0; +} + +static int cam_sfe_bus_wr_start_hw(void *hw_priv, + void *start_hw_args, uint32_t arg_size) +{ + return cam_sfe_bus_start_sfe_out(hw_priv); +} + +static int cam_sfe_bus_wr_stop_hw(void *hw_priv, + void *stop_hw_args, uint32_t arg_size) +{ + return cam_sfe_bus_stop_sfe_out(hw_priv); +} + +static int cam_sfe_bus_wr_init_hw(void *hw_priv, + void *init_hw_args, uint32_t arg_size) +{ + struct cam_sfe_bus_wr_priv *bus_priv = hw_priv; + + if (!bus_priv) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + + if (bus_priv->common_data.hw_init) + return 0; + + /* To Do Subscribe IRQs */ + + /* BUS_WR_TEST_BUS_CTRL */ + cam_io_w_mb(0x0, bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->test_bus_ctrl); + + bus_priv->common_data.hw_init = true; + + return 0; +} + +static int cam_sfe_bus_wr_deinit_hw(void *hw_priv, + void *deinit_hw_args, uint32_t arg_size) +{ + struct cam_sfe_bus_wr_priv *bus_priv = hw_priv; + int rc = 0; + + if (!bus_priv) { + CAM_ERR(CAM_SFE, "Error: Invalid args"); + return -EINVAL; + } + + if (!bus_priv->common_data.hw_init) + return 0; + + /* To Do Unsubscribe IRQs */ + + return rc; +} + +static int __cam_sfe_bus_wr_process_cmd( + void *priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + return cam_sfe_bus_wr_process_cmd(priv, cmd_type, + cmd_args, arg_size); +} + +static int cam_sfe_bus_wr_process_cmd( + struct cam_isp_resource_node *priv, + uint32_t cmd_type, void *cmd_args, + uint32_t arg_size) +{ + int rc = -EINVAL; + struct cam_sfe_bus_wr_priv *bus_priv; + + if (!priv || !cmd_args) { + CAM_ERR_RATE_LIMIT(CAM_SFE, "Invalid input arguments"); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_BUF_UPDATE: + rc = cam_sfe_bus_wr_update_wm(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_HFR_UPDATE: + rc = cam_sfe_bus_wr_update_hfr(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_GET_SECURE_MODE: + rc = cam_sfe_bus_wr_get_secure_mode(priv, cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STRIPE_UPDATE: + rc = cam_sfe_bus_wr_update_stripe_cfg(priv, + cmd_args, arg_size); + break; + case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: + bus_priv = (struct cam_sfe_bus_wr_priv *) priv; + /* Handle bus err IRQ */ + break; + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: { + struct cam_isp_hw_event_info *event_info; + enum cam_sfe_bus_sfe_out_type sfe_out_res_id; + + event_info = + (struct cam_isp_hw_event_info *)cmd_args; + bus_priv = (struct cam_sfe_bus_wr_priv *) priv; + sfe_out_res_id = + cam_sfe_bus_wr_get_out_res_id(event_info->res_id); + rc = cam_sfe_bus_wr_print_dimensions( + sfe_out_res_id, bus_priv); + break; + } + case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: + rc = cam_sfe_bus_wr_update_wm_config(cmd_args); + break; + default: + CAM_ERR_RATE_LIMIT(CAM_SFE, "Invalid HW command type:%d", + cmd_type); + break; + } + + return rc; +} + +int cam_sfe_bus_wr_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + struct cam_sfe_bus **sfe_bus) +{ + int i, rc = 0; + struct cam_sfe_bus_wr_priv *bus_priv = NULL; + struct cam_sfe_bus *sfe_bus_local; + struct cam_sfe_bus_wr_hw_info *hw_info = bus_hw_info; + struct cam_sfe_soc_private *soc_private = NULL; + + CAM_DBG(CAM_SFE, "Enter"); + + if (!soc_info || !hw_intf || !bus_hw_info) { + CAM_ERR(CAM_SFE, + "Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK", + soc_info, hw_intf, bus_hw_info); + rc = -EINVAL; + goto end; + } + + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_SFE, "Invalid soc_private"); + rc = -ENODEV; + goto end; + } + + sfe_bus_local = kzalloc(sizeof(struct cam_sfe_bus), GFP_KERNEL); + if (!sfe_bus_local) { + CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus"); + rc = -ENOMEM; + goto end; + } + + bus_priv = kzalloc(sizeof(struct cam_sfe_bus_wr_priv), + GFP_KERNEL); + if (!bus_priv) { + CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus_priv"); + rc = -ENOMEM; + goto free_bus_local; + } + sfe_bus_local->bus_priv = bus_priv; + + bus_priv->num_client = hw_info->num_client; + bus_priv->num_out = hw_info->num_out; + bus_priv->num_comp_grp = hw_info->num_comp_grp; + bus_priv->top_irq_shift = hw_info->top_irq_shift; + 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, SFE_CORE_BASE_IDX); + bus_priv->common_data.hw_intf = hw_intf; + bus_priv->common_data.common_reg = &hw_info->common_reg; + bus_priv->common_data.comp_done_shift = hw_info->comp_done_shift; + bus_priv->common_data.hw_init = false; + + rc = cam_cpas_get_cpas_hw_version(&bus_priv->common_data.hw_version); + if (rc) { + CAM_ERR(CAM_SFE, "Failed to get hw_version rc:%d", rc); + goto end; + } + + bus_priv->comp_grp = kzalloc((sizeof(struct cam_isp_resource_node) * + bus_priv->num_comp_grp), GFP_KERNEL); + if (!bus_priv->comp_grp) { + CAM_ERR(CAM_SFE, "Failed to alloc for bus comp groups"); + rc = -ENOMEM; + goto free_bus_priv; + } + + bus_priv->sfe_out = kzalloc((sizeof(struct cam_isp_resource_node) * + CAM_SFE_BUS_SFE_OUT_MAX), GFP_KERNEL); + if (!bus_priv->sfe_out) { + CAM_ERR(CAM_SFE, "Failed to alloc for bus out res"); + rc = -ENOMEM; + goto free_comp_grp; + } + + mutex_init(&bus_priv->common_data.bus_mutex); + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + for (i = 0; i < bus_priv->num_comp_grp; i++) { + rc = cam_sfe_bus_wr_init_comp_grp(i, soc_info, + bus_priv, bus_hw_info, + &bus_priv->comp_grp[i]); + if (rc < 0) { + CAM_ERR(CAM_SFE, "SFE:%d init comp_grp:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + goto deinit_comp_grp; + } + } + + for (i = 0; i < bus_priv->num_out; i++) { + rc = cam_sfe_bus_init_sfe_out_resource(i, bus_priv, + bus_hw_info); + if (rc < 0) { + CAM_ERR(CAM_SFE, + "SFE:%d init out_type:0x%X failed rc:%d", + bus_priv->common_data.core_index, i, rc); + goto deinit_sfe_out; + } + } + + spin_lock_init(&bus_priv->common_data.spin_lock); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + + sfe_bus_local->hw_ops.reserve = cam_sfe_bus_acquire_sfe_out; + sfe_bus_local->hw_ops.release = cam_sfe_bus_release_sfe_out; + sfe_bus_local->hw_ops.start = cam_sfe_bus_wr_start_hw; + sfe_bus_local->hw_ops.stop = cam_sfe_bus_wr_stop_hw; + sfe_bus_local->hw_ops.init = cam_sfe_bus_wr_init_hw; + sfe_bus_local->hw_ops.deinit = cam_sfe_bus_wr_deinit_hw; + sfe_bus_local->top_half_handler = NULL; + sfe_bus_local->bottom_half_handler = NULL; + sfe_bus_local->hw_ops.process_cmd = __cam_sfe_bus_wr_process_cmd; + + *sfe_bus = sfe_bus_local; + + CAM_DBG(CAM_SFE, "Exit"); + return rc; + +deinit_sfe_out: + if (i < 0) + i = CAM_SFE_BUS_SFE_OUT_MAX; + for (--i; i >= 0; i--) + cam_sfe_bus_deinit_sfe_out_resource(&bus_priv->sfe_out[i]); + +deinit_comp_grp: + if (i < 0) + i = bus_priv->num_comp_grp; + for (--i; i >= 0; i--) + cam_sfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]); + kfree(bus_priv->sfe_out); + +free_comp_grp: + kfree(bus_priv->comp_grp); + +free_bus_priv: + kfree(sfe_bus_local->bus_priv); + +free_bus_local: + kfree(sfe_bus_local); + +end: + return rc; +} + +int cam_sfe_bus_wr_deinit( + struct cam_sfe_bus **sfe_bus) +{ + int i, rc = 0; + struct cam_sfe_bus_wr_priv *bus_priv = NULL; + struct cam_sfe_bus *sfe_bus_local; + unsigned long flags; + + if (!sfe_bus || !*sfe_bus) { + CAM_ERR(CAM_SFE, "Invalid input"); + return -EINVAL; + } + sfe_bus_local = *sfe_bus; + + bus_priv = sfe_bus_local->bus_priv; + if (!bus_priv) { + CAM_ERR(CAM_SFE, "bus_priv is NULL"); + rc = -ENODEV; + goto free_bus_local; + } + + spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + //for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++) + //INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + bus_priv->common_data.hw_init = false; + spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); + + for (i = 0; i < CAM_SFE_BUS_WR_COMP_GRP_MAX; i++) { + rc = cam_sfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]); + if (rc < 0) + CAM_ERR(CAM_SFE, + "SFE:%d deinit comp_grp:%d failed rc:%d", + bus_priv->common_data.core_index, i, rc); + } + + for (i = 0; i < CAM_SFE_BUS_SFE_OUT_MAX; i++) { + rc = cam_sfe_bus_deinit_sfe_out_resource( + &bus_priv->sfe_out[i]); + if (rc < 0) + CAM_ERR(CAM_SFE, + "SFE:%d deinit out_type:0x%X failed rc:%d", + bus_priv->common_data.core_index, i, rc); + } + + INIT_LIST_HEAD(&bus_priv->free_comp_grp); + INIT_LIST_HEAD(&bus_priv->used_comp_grp); + + mutex_destroy(&bus_priv->common_data.bus_mutex); + kfree(sfe_bus_local->bus_priv); + +free_bus_local: + kfree(sfe_bus_local); + + *sfe_bus = NULL; + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h new file mode 100644 index 000000000000..54ea96bb3d46 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_SFE_BUS_WR_H_ +#define _CAM_SFE_BUS_WR_H_ + +#include "cam_irq_controller.h" +#include "cam_sfe_bus.h" + +#define CAM_SFE_BUS_WR_MAX_CLIENTS 13 +#define CAM_SFE_BUS_WR_MAX_SUB_GRPS 6 + +enum cam_sfe_bus_wr_src_grp { + CAM_SFE_BUS_WR_SRC_GRP_0, + CAM_SFE_BUS_WR_SRC_GRP_1, + CAM_SFE_BUS_WR_SRC_GRP_2, + CAM_SFE_BUS_WR_SRC_GRP_3, + CAM_SFE_BUS_WR_SRC_GRP_4, + CAM_SFE_BUS_WR_SRC_GRP_5, + CAM_SFE_BUS_WR_SRC_GRP_MAX, +}; + +enum cam_sfe_bus_wr_comp_grp_type { + CAM_SFE_BUS_WR_COMP_GRP_0, + CAM_SFE_BUS_WR_COMP_GRP_1, + CAM_SFE_BUS_WR_COMP_GRP_2, + CAM_SFE_BUS_WR_COMP_GRP_3, + CAM_SFE_BUS_WR_COMP_GRP_4, + CAM_SFE_BUS_WR_COMP_GRP_5, + CAM_SFE_BUS_WR_COMP_GRP_6, + CAM_SFE_BUS_WR_COMP_GRP_7, + CAM_SFE_BUS_WR_COMP_GRP_8, + CAM_SFE_BUS_WR_COMP_GRP_9, + CAM_SFE_BUS_WR_COMP_GRP_MAX, +}; + +enum cam_sfe_bus_sfe_out_type { + CAM_SFE_BUS_SFE_OUT_RDI0, + CAM_SFE_BUS_SFE_OUT_RDI1, + CAM_SFE_BUS_SFE_OUT_RDI2, + CAM_SFE_BUS_SFE_OUT_RDI3, + CAM_SFE_BUS_SFE_OUT_RDI4, + CAM_SFE_BUS_SFE_OUT_RAW_DUMP, + CAM_SFE_BUS_SFE_OUT_LCR, + CAM_SFE_BUS_SFE_OUT_BE_0, + CAM_SFE_BUS_SFE_OUT_BHIST_0, + CAM_SFE_BUS_SFE_OUT_BE_1, + CAM_SFE_BUS_SFE_OUT_BHIST_1, + CAM_SFE_BUS_SFE_OUT_BE_2, + CAM_SFE_BUS_SFE_OUT_BHIST_2, + CAM_SFE_BUS_SFE_OUT_MAX, +}; + +/* + * struct cam_sfe_bus_reg_offset_common: + * + * @Brief: Common registers across all BUS Clients + */ +struct cam_sfe_bus_reg_offset_common { + uint32_t hw_version; + uint32_t cgc_ovd; + uint32_t if_frameheader_cfg[CAM_SFE_BUS_WR_MAX_SUB_GRPS]; + uint32_t pwr_iso_cfg; + uint32_t overflow_status_clear; + uint32_t ccif_violation_status; + uint32_t overflow_status; + uint32_t image_size_violation_status; + uint32_t debug_status_top_cfg; + uint32_t debug_status_top; + uint32_t test_bus_ctrl; + uint32_t top_irq_mask_0; +}; + +/* + * struct cam_sfe_bus_reg_offset_bus_client: + * + * @Brief: Register offsets for BUS Clients + */ +struct cam_sfe_bus_reg_offset_bus_client { + uint32_t cfg; + uint32_t image_addr; + uint32_t frame_incr; + uint32_t image_cfg_0; + uint32_t image_cfg_1; + uint32_t image_cfg_2; + uint32_t packer_cfg; + uint32_t frame_header_addr; + uint32_t frame_header_incr; + uint32_t frame_header_cfg; + uint32_t line_done_cfg; + uint32_t irq_subsample_period; + uint32_t irq_subsample_pattern; + uint32_t framedrop_period; + uint32_t framedrop_pattern; + uint32_t system_cache_cfg; + uint32_t addr_status_0; + uint32_t addr_status_1; + uint32_t addr_status_2; + uint32_t addr_status_3; + uint32_t debug_status_cfg; + uint32_t debug_status_0; + uint32_t debug_status_1; + uint32_t comp_group; +}; + +/* + * struct cam_sfe_bus_sfe_out_hw_info: + * + * @Brief: HW capability of SFE Bus Client + */ +struct cam_sfe_bus_sfe_out_hw_info { + enum cam_sfe_bus_sfe_out_type sfe_out_type; + uint32_t max_width; + uint32_t max_height; + uint32_t source_group; + uint32_t num_wm; + uint32_t wm_idx; +}; + +/* + * struct cam_sfe_bus_wr_hw_info: + * + * @Brief: HW register info for entire Bus + * + * @common_reg: Common register details + * @num_client: Total number of write clients + * @bus_client_reg: Bus client register info + * @sfe_out_hw_info: SFE output capability + * @num_comp_grp: Number of composite groups + * @comp_done_shift: Mask shift for comp done mask + * @top_irq_shift: Mask shift for top level BUS WR irq + */ +struct cam_sfe_bus_wr_hw_info { + struct cam_sfe_bus_reg_offset_common common_reg; + uint32_t num_client; + struct cam_sfe_bus_reg_offset_bus_client + bus_client_reg[CAM_SFE_BUS_WR_MAX_CLIENTS]; + uint32_t num_out; + struct cam_sfe_bus_sfe_out_hw_info + sfe_out_hw_info[CAM_SFE_BUS_SFE_OUT_MAX]; + uint32_t num_comp_grp; + uint32_t comp_done_shift; + uint32_t top_irq_shift; +}; + +/* + * cam_sfe_bus_wr_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 + * @sfe_bus: Pointer to sfe_bus structure which will be filled + * and returned on successful initialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_bus_wr_init( + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *bus_hw_info, + struct cam_sfe_bus **sfe_bus); + +/* + * cam_sfe_bus_wr_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @sfe_bus: Pointer to sfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_bus_wr_deinit(struct cam_sfe_bus **sfe_bus); + +#endif /* _CAM_SFE_BUS_WR_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h new file mode 100644 index 000000000000..7cac8108397e --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_BUS_H_ +#define _CAM_SFE_BUS_H_ + +#include "cam_isp_hw.h" +#include "cam_sfe_hw_intf.h" + +#define CAM_SFE_BUS_WR_VER_1_0 0x1000 +#define CAM_SFE_BUS_RD_VER_1_0 0x1000 + +#define CAM_SFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \ + do { \ + buf_array[(index)++] = offset; \ + buf_array[(index)++] = val; \ + } while (0) + +#define ALIGNUP(value, alignment) \ + ((value + alignment - 1) / alignment * alignment) + +enum cam_sfe_bus_sfe_core_id { + CAM_SFE_BUS_SFE_CORE_0, + CAM_SFE_BUS_SFE_CORE_1, + CAM_SFE_BUS_SFE_CORE_MAX, +}; + +enum cam_sfe_bus_plane_type { + PLANE_Y, + PLANE_C, + PLANE_MAX, +}; + +enum cam_sfe_bus_type { + BUS_TYPE_SFE_WR, + BUS_TYPE_SFE_RD, + BUS_TYPE_SFE_MAX, +}; + +/* + * struct cam_sfe_bus: + * + * @Brief: Bus interface structure + * + * @bus_priv: Private data of BUS + * @hw_ops: Hardware interface functions + * @top_half_handler: Top Half handler function + * @bottom_half_handler: Bottom Half handler function + */ +struct cam_sfe_bus { + void *bus_priv; + + struct cam_hw_ops hw_ops; + CAM_IRQ_HANDLER_TOP_HALF top_half_handler; + CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; +}; + +/* + * cam_sfe_bus_init() + * + * @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 + * @sfe_bus: Pointer to sfe_bus structure which will be filled + * and returned on successful initialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_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, + struct cam_sfe_bus **sfe_bus); + +/* + * cam_sfe_bus_deinit() + * + * @Brief: Deinitialize Bus layer + * + * @bus_version: Version of BUS to deinitialize + * @sfe_bus: Pointer to sfe_bus structure to deinitialize + * + * @Return: 0: Success + * Non-zero: Failure + */ +int cam_sfe_bus_deinit( + uint32_t bus_version, + int bus_type, + struct cam_sfe_bus **sfe_bus); + +#endif /* _CAM_SFE_BUS_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c new file mode 100644 index 000000000000..a61a539fdb44 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c @@ -0,0 +1,682 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_io_util.h" +#include "cam_cdm_util.h" +#include "cam_sfe_hw_intf.h" +#include "cam_sfe_top.h" +#include "cam_debug_util.h" +#include "cam_sfe_soc.h" + +struct cam_sfe_core_cfg { + uint32_t mode_sel; + uint32_t ops_mode_cfg; + uint32_t fs_mode_cfg; +}; + +struct cam_sfe_top_common_data { + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *hw_intf; + struct cam_sfe_top_common_reg_offset *common_reg; +}; + +struct cam_sfe_top_priv { + struct cam_sfe_top_common_data common_data; + struct cam_isp_resource_node in_rsrc[CAM_SFE_TOP_IN_PORT_MAX]; + uint32_t num_in_ports; + unsigned long hw_clk_rate; + unsigned long req_clk_rate[CAM_SFE_TOP_IN_PORT_MAX]; + uint32_t last_counter; + uint64_t total_bw_applied; + struct cam_axi_vote req_axi_vote[CAM_SFE_TOP_IN_PORT_MAX]; + struct cam_axi_vote last_vote[ + CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES]; + enum cam_sfe_bw_control_action axi_vote_control[ + CAM_SFE_TOP_IN_PORT_MAX]; + struct cam_sfe_core_cfg core_cfg; + uint32_t sfe_debug_cfg; +}; + +struct cam_sfe_path_data { + void __iomem *mem_base; + void *priv; + struct cam_hw_intf *hw_intf; + struct cam_sfe_top_common_reg_offset *common_reg; + struct cam_sfe_modules_common_reg_offset *modules_reg; + struct cam_sfe_path_common_reg_data *path_reg_data; + struct cam_hw_soc_info *soc_info; + uint32_t min_hblank_cnt; + cam_hw_mgr_event_cb_func event_cb; +}; + +static int cam_sfe_top_core_cfg( + struct cam_sfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_sfe_core_config_args *sfe_core_cfg = NULL; + + if ((!cmd_args) || + (arg_size != sizeof(struct cam_sfe_core_config_args))) { + CAM_ERR(CAM_SFE, "Invalid inputs"); + return -EINVAL; + } + + sfe_core_cfg = (struct cam_sfe_core_config_args *)cmd_args; + top_priv->core_cfg.mode_sel = + sfe_core_cfg->core_config.mode_sel; + top_priv->core_cfg.fs_mode_cfg = + sfe_core_cfg->core_config.fs_mode_cfg; + top_priv->core_cfg.ops_mode_cfg = + sfe_core_cfg->core_config.ops_mode_cfg; + + return 0; +} + +static int cam_sfe_top_set_hw_clk_rate( + struct cam_sfe_top_priv *top_priv) +{ + struct cam_hw_soc_info *soc_info = NULL; + struct cam_sfe_soc_private *soc_private = NULL; + struct cam_ahb_vote ahb_vote; + int rc, clk_lvl = -1, i; + unsigned long max_clk_rate = 0; + + soc_info = top_priv->common_data.soc_info; + for (i = 0; i < top_priv->num_in_ports; i++) { + if (top_priv->req_clk_rate[i] > max_clk_rate) + max_clk_rate = top_priv->req_clk_rate[i]; + } + + if (max_clk_rate == top_priv->hw_clk_rate) + return 0; + + soc_private = (struct cam_sfe_soc_private *) + soc_info->soc_private; + CAM_DBG(CAM_PERF, "SFE [%u]: clk: %s idx: %d rate: %llu", + soc_info->index, + soc_info->clk_name[soc_info->src_clk_idx], + soc_info->src_clk_idx, top_priv->req_clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, + max_clk_rate); + + if (!rc) { + top_priv->hw_clk_rate = max_clk_rate; + rc = cam_soc_util_get_clk_level(soc_info, + max_clk_rate, + soc_info->src_clk_idx, &clk_lvl); + if (rc) { + CAM_WARN(CAM_SFE, + "Failed to get clk level for %s with clk_rate %llu src_idx %d rc: %d", + soc_info->dev_name, max_clk_rate, + soc_info->src_clk_idx, rc); + rc = 0; + goto end; + } + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = clk_lvl; + cam_cpas_update_ahb_vote(soc_private->cpas_handle, &ahb_vote); + } else { + CAM_ERR(CAM_PERF, + "Set clk rate failed for SFE [%u] clk: %s rate: %llu rc: %d", + soc_info->index, + soc_info->clk_name[soc_info->src_clk_idx], + max_clk_rate, rc); + } + +end: + return rc; +} + +static int cam_sfe_top_get_base( + struct cam_sfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + uint32_t size = 0; + uint32_t mem_base = 0; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_SFE, "Invalid cmd size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + + cdm_util_ops = + (struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops; + + if (!cdm_util_ops) { + CAM_ERR(CAM_SFE, "Invalid CDM ops"); + return -EINVAL; + } + + size = cdm_util_ops->cdm_required_size_changebase(); + if ((size * 4) > cdm_args->cmd.size) { + CAM_ERR(CAM_SFE, "buf size: %d is not sufficient, expected: %d", + cdm_args->cmd.size, size); + return -EINVAL; + } + + mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE( + top_priv->common_data.soc_info, + SFE_CORE_BASE_IDX); + + if (cdm_args->cdm_id == CAM_CDM_RT) + mem_base -= CAM_SOC_GET_REG_MAP_CAM_BASE( + top_priv->common_data.soc_info, + SFE_RT_CDM_BASE_IDX); + + CAM_DBG(CAM_SFE, "core %d mem_base 0x%x, CDM Id: %d", + top_priv->common_data.soc_info->index, mem_base, + cdm_args->cdm_id); + + cdm_util_ops->cdm_write_changebase( + cdm_args->cmd.cmd_buf_addr, mem_base); + cdm_args->cmd.used_bytes = (size * 4); + + return 0; +} + +static int cam_sfe_top_clock_update( + struct cam_sfe_top_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_sfe_clock_update_args *clk_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0, i; + + if (arg_size != sizeof(struct cam_sfe_clock_update_args)) { + CAM_ERR(CAM_SFE, "Invalid cmd size"); + return -EINVAL; + } + + clk_update = + (struct cam_sfe_clock_update_args *)cmd_args; + if (!clk_update || !clk_update->node_res || !top_priv || + !top_priv->common_data.soc_info) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + + res = clk_update->node_res; + + if (!res || !res->hw_intf->hw_priv) { + CAM_ERR(CAM_PERF, "Invalid inputs"); + return -EINVAL; + } + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || + res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { + CAM_ERR(CAM_PERF, + "SFE: %d Invalid res_type: %d res_id: %d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < top_priv->num_in_ports; i++) { + if (top_priv->in_rsrc[i].res_id == res->res_id) { + top_priv->req_clk_rate[i] = clk_update->clk_rate; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_DBG(CAM_PERF, + "SFE: %d not ready to set clocks yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + rc = -EAGAIN; + } else + rc = cam_sfe_top_set_hw_clk_rate(top_priv); + + return rc; +} + +static int cam_sfe_set_top_debug( + struct cam_sfe_top_priv *top_priv, + void *cmd_args) +{ + uint32_t *sfe_debug; + + sfe_debug = (uint32_t *)cmd_args; + top_priv->sfe_debug_cfg = *sfe_debug; + + return 0; +} + +int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, + void *cmd_args, uint32_t arg_size) +{ + int rc = 0; + struct cam_sfe_top_priv *top_priv; + + if (!priv) { + CAM_ERR(CAM_SFE, "Invalid top_priv"); + return -EINVAL; + } + + top_priv = (struct cam_sfe_top_priv *) priv; + + switch (cmd_type) { + case CAM_ISP_HW_CMD_GET_CHANGE_BASE: + rc = cam_sfe_top_get_base(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_CLOCK_UPDATE: + rc = cam_sfe_top_clock_update(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_BW_UPDATE_V2: + break; + case CAM_ISP_HW_CMD_BW_CONTROL: + break; + case CAM_ISP_HW_CMD_CORE_CONFIG: + rc = cam_sfe_top_core_cfg(top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG: + rc = cam_sfe_set_top_debug(top_priv, cmd_args); + break; + default: + CAM_ERR(CAM_SFE, "Invalid cmd type: %d", cmd_type); + rc = -EINVAL; + break; + } + + return rc; +} + +int cam_sfe_top_reserve(void *device_priv, + void *reserve_args, uint32_t arg_size) +{ + struct cam_sfe_top_priv *top_priv; + struct cam_sfe_acquire_args *args; + struct cam_sfe_hw_sfe_in_acquire_args *acquire_args; + struct cam_sfe_path_data *path_data; + int rc = -EINVAL, i; + + if (!device_priv || !reserve_args) { + CAM_ERR(CAM_SFE, + "Error invalid input arguments"); + return rc; + } + + top_priv = (struct cam_sfe_top_priv *)device_priv; + args = (struct cam_sfe_acquire_args *)reserve_args; + acquire_args = &args->sfe_in; + + for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) { + CAM_DBG(CAM_SFE, "i: %d res_id: %d state: %d", i, + acquire_args->res_id, top_priv->in_rsrc[i].res_state); + + if ((top_priv->in_rsrc[i].res_id == acquire_args->res_id) && + (top_priv->in_rsrc[i].res_state == + CAM_ISP_RESOURCE_STATE_AVAILABLE)) { + path_data = (struct cam_sfe_path_data *) + top_priv->in_rsrc[i].res_priv; + path_data->event_cb = args->event_cb; + path_data->priv = args->priv; + CAM_DBG(CAM_SFE, + "SFE [%u] for rsrc: %u acquired", + top_priv->in_rsrc[i].hw_intf->hw_idx, + acquire_args->res_id); + + top_priv->in_rsrc[i].cdm_ops = acquire_args->cdm_ops; + top_priv->in_rsrc[i].tasklet_info = args->tasklet; + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_RESERVED; + acquire_args->rsrc_node = + &top_priv->in_rsrc[i]; + rc = 0; + break; + } + } + + return rc; +} + +int cam_sfe_top_release(void *device_priv, + void *release_args, uint32_t arg_size) +{ + struct cam_sfe_top_priv *top_priv; + struct cam_isp_resource_node *in_res; + + if (!device_priv || !release_args) { + CAM_ERR(CAM_SFE, "Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_sfe_top_priv *)device_priv; + in_res = (struct cam_isp_resource_node *)release_args; + + CAM_DBG(CAM_SFE, + "Release for SFE [%u] resource id: %u in state: %d", + in_res->hw_intf->hw_idx, in_res->res_id, + in_res->res_state); + if (in_res->res_state < CAM_ISP_RESOURCE_STATE_RESERVED) { + CAM_ERR(CAM_SFE, "SFE [%u] invalid res_state: %d", + in_res->hw_intf->hw_idx, in_res->res_state); + return -EINVAL; + } + + in_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + in_res->cdm_ops = NULL; + in_res->tasklet_info = NULL; + + return 0; +} + +int cam_sfe_top_start( + void *priv, void *start_args, uint32_t arg_size) +{ + int rc = -EINVAL; + struct cam_sfe_top_priv *top_priv; + struct cam_isp_resource_node *sfe_res; + struct cam_hw_info *hw_info = NULL; + struct cam_sfe_path_data *path_data; + + if (!priv || !start_args) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + + top_priv = (struct cam_sfe_top_priv *)priv; + sfe_res = (struct cam_isp_resource_node *) start_args; + + hw_info = (struct cam_hw_info *)sfe_res->hw_intf->hw_priv; + if (!hw_info) { + CAM_ERR(CAM_SFE, "Invalid input"); + return rc; + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_SFE, "SFE HW [%u] not powered up", + hw_info->soc_info.index); + rc = -EPERM; + return rc; + } + + path_data = (struct cam_sfe_path_data *)sfe_res->res_priv; + rc = cam_sfe_top_set_hw_clk_rate(top_priv); + if (rc) + return rc; + + /* core cfg updated via CDM */ + CAM_DBG(CAM_SFE, "SFE HW [%u] core_cfg: 0x%x", + hw_info->soc_info.index, + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->core_cfg)); + + /* Enable debug cfg registers */ + cam_io_w_mb(path_data->path_reg_data->top_debug_cfg_en, + path_data->mem_base + + path_data->common_reg->top_debug_cfg); + + /* Enable sensor diag info */ + /* Enable SOF & EOF IRQ based on debug flag */ + /* Enable error IRQ by default */ + + sfe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return 0; +} + +int cam_sfe_top_stop( + void *priv, void *stop_args, uint32_t arg_size) +{ + int i; + struct cam_sfe_top_priv *top_priv; + struct cam_isp_resource_node *sfe_res; + + if (!priv || !stop_args) { + CAM_ERR(CAM_SFE, "Invalid args"); + return -EINVAL; + } + + top_priv = (struct cam_sfe_top_priv *)priv; + sfe_res = (struct cam_isp_resource_node *) stop_args; + + if (sfe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED || + sfe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) + return 0; + + /* Unsubscribe for IRQs */ + sfe_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) { + if (top_priv->in_rsrc[i].res_id == sfe_res->res_id) { + top_priv->req_clk_rate[i] = 0; + memset(&top_priv->req_axi_vote[i], 0, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_SFE_BW_CONTROL_EXCLUDE; + break; + } + } + + return 0; +} + +int cam_sfe_top_init( + uint32_t hw_version, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + struct cam_sfe_top **sfe_top_ptr) +{ + int i, j, rc = 0; + struct cam_sfe_top_priv *top_priv = NULL; + struct cam_sfe_path_data *path_data = NULL; + struct cam_sfe_top *sfe_top; + struct cam_sfe_top_hw_info *sfe_top_hw_info = + (struct cam_sfe_top_hw_info *)top_hw_info; + + sfe_top = kzalloc(sizeof(struct cam_sfe_top), GFP_KERNEL); + if (!sfe_top) { + CAM_DBG(CAM_SFE, "Error, Failed to alloc for sfe_top"); + rc = -ENOMEM; + goto end; + } + + top_priv = kzalloc(sizeof(struct cam_sfe_top_priv), + GFP_KERNEL); + if (!top_priv) { + rc = -ENOMEM; + goto free_sfe_top; + } + + sfe_top->top_priv = top_priv; + if (sfe_top_hw_info->num_inputs > CAM_SFE_TOP_IN_PORT_MAX) { + CAM_ERR(CAM_SFE, + "Invalid number of input resources: %d max: %d", + sfe_top_hw_info->num_inputs, + CAM_SFE_TOP_IN_PORT_MAX); + rc = -EINVAL; + goto free_top_priv; + } + + top_priv->hw_clk_rate = 0; + top_priv->num_in_ports = sfe_top_hw_info->num_inputs; + memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * + CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES); + memset(&top_priv->core_cfg, 0x0, + sizeof(struct cam_sfe_core_config_args)); + + CAM_DBG(CAM_SFE, + "Initializing SFE [%u] top with hw_version: 0x%x", + hw_intf->hw_idx, hw_version); + for (i = 0, j = 0; i < top_priv->num_in_ports && + j < CAM_SFE_RDI_MAX; i++) { + top_priv->in_rsrc[i].res_type = + CAM_ISP_RESOURCE_SFE_IN; + top_priv->in_rsrc[i].hw_intf = hw_intf; + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_AVAILABLE; + top_priv->req_clk_rate[i] = 0; + + if (sfe_top_hw_info->input_type[i] == + CAM_SFE_PIX_VER_1_0) { + top_priv->in_rsrc[i].res_id = + CAM_ISP_HW_SFE_IN_PIX; + + path_data = kzalloc(sizeof(struct cam_sfe_path_data), + GFP_KERNEL); + if (!path_data) { + CAM_DBG(CAM_SFE, + "Failed to alloc SFE [%u] pix data", + hw_intf->hw_idx); + goto deinit_resources; + } + top_priv->in_rsrc[i].res_priv = path_data; + path_data->mem_base = + soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base; + path_data->path_reg_data = + sfe_top_hw_info->pix_reg_data; + path_data->common_reg = sfe_top_hw_info->common_reg; + path_data->modules_reg = + sfe_top_hw_info->modules_hw_info; + path_data->hw_intf = hw_intf; + path_data->soc_info = soc_info; + } else if (sfe_top_hw_info->input_type[i] == + CAM_SFE_RDI_VER_1_0) { + top_priv->in_rsrc[i].res_id = + CAM_ISP_HW_SFE_IN_RDI0 + j; + + path_data = kzalloc(sizeof(struct cam_sfe_path_data), + GFP_KERNEL); + if (!path_data) { + CAM_DBG(CAM_SFE, + "Failed to alloc SFE [%u] rdi data res_id: %u", + hw_intf->hw_idx, + (CAM_ISP_HW_SFE_IN_RDI0 + j)); + goto deinit_resources; + } + + top_priv->in_rsrc[i].res_priv = path_data; + + path_data->mem_base = + soc_info->reg_map[SFE_CORE_BASE_IDX].mem_base; + path_data->hw_intf = hw_intf; + path_data->common_reg = sfe_top_hw_info->common_reg; + path_data->modules_reg = + sfe_top_hw_info->modules_hw_info; + path_data->soc_info = soc_info; + path_data->path_reg_data = + sfe_top_hw_info->rdi_reg_data[j++]; + } else { + CAM_WARN(CAM_SFE, "Invalid SFE input type: %u", + sfe_top_hw_info->input_type[i]); + } + } + + top_priv->common_data.soc_info = soc_info; + top_priv->common_data.hw_intf = hw_intf; + top_priv->common_data.common_reg = + sfe_top_hw_info->common_reg; + + sfe_top->hw_ops.process_cmd = cam_sfe_top_process_cmd; + sfe_top->hw_ops.start = cam_sfe_top_start; + sfe_top->hw_ops.stop = cam_sfe_top_stop; + sfe_top->hw_ops.reserve = cam_sfe_top_reserve; + sfe_top->hw_ops.release = cam_sfe_top_release; + *sfe_top_ptr = sfe_top; + + return rc; + +deinit_resources: + for (--i; i >= 0; i--) { + top_priv->in_rsrc[i].start = NULL; + top_priv->in_rsrc[i].stop = NULL; + top_priv->in_rsrc[i].process_cmd = NULL; + top_priv->in_rsrc[i].top_half_handler = NULL; + top_priv->in_rsrc[i].bottom_half_handler = NULL; + + if (!top_priv->in_rsrc[i].res_priv) + continue; + + kfree(top_priv->in_rsrc[i].res_priv); + top_priv->in_rsrc[i].res_priv = NULL; + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + } +free_top_priv: + kfree(sfe_top->top_priv); + sfe_top->top_priv = NULL; +free_sfe_top: + kfree(sfe_top); +end: + *sfe_top_ptr = NULL; + return rc; +} + +int cam_sfe_top_deinit( + uint32_t hw_version, + struct cam_sfe_top **sfe_top_ptr) +{ + int i, rc = 0; + struct cam_sfe_top *sfe_top; + struct cam_sfe_top_priv *top_priv; + + if (!sfe_top_ptr) { + CAM_ERR(CAM_SFE, "Error Invalid input"); + return -ENODEV; + } + + sfe_top = *sfe_top_ptr; + if (!sfe_top) { + CAM_ERR(CAM_SFE, "Error sfe top NULL"); + return -ENODEV; + } + + top_priv = sfe_top->top_priv; + if (!top_priv) { + CAM_ERR(CAM_SFE, "Error sfe top priv NULL"); + rc = -ENODEV; + goto free_sfe_top; + } + + CAM_DBG(CAM_SFE, + "Deinit SFE [%u] top with hw_version 0x%x", + top_priv->common_data.hw_intf->hw_idx, + hw_version); + + for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) { + top_priv->in_rsrc[i].res_state = + CAM_ISP_RESOURCE_STATE_UNAVAILABLE; + + top_priv->in_rsrc[i].start = NULL; + top_priv->in_rsrc[i].stop = NULL; + top_priv->in_rsrc[i].process_cmd = NULL; + top_priv->in_rsrc[i].top_half_handler = NULL; + top_priv->in_rsrc[i].bottom_half_handler = NULL; + + if (!top_priv->in_rsrc[i].res_priv) { + CAM_ERR(CAM_SFE, "Error res_priv is NULL"); + continue; + } + + kfree(top_priv->in_rsrc[i].res_priv); + top_priv->in_rsrc[i].res_priv = NULL; + } + + kfree(sfe_top->top_priv); + +free_sfe_top: + kfree(sfe_top); + *sfe_top_ptr = NULL; + + return rc; +} + + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h new file mode 100644 index 000000000000..c6ad17579293 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_SFE_TOP_H_ +#define _CAM_SFE_TOP_H_ + +#include "cam_cpas_api.h" + +#define CAM_SFE_PIX_VER_1_0 0x10 +#define CAM_SFE_RDI_VER_1_0 0x1000 +#define CAM_SFE_TOP_VER_1_0 0x10000 + +#define CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES 18 +#define CAM_SFE_TOP_IN_PORT_MAX 6 +#define CAM_SFE_RDI_MAX 5 + +#define CAM_SHIFT_TOP_CORE_CFG_MODE_SEL 2 +#define CAM_SHIFT_TOP_CORE_CFG_OPS_MODE_CFG 1 +#define CAM_SHIFT_TOP_CORE_CFG_FS_MODE_CFG 0 + +struct cam_sfe_top { + void *top_priv; + struct cam_hw_ops hw_ops; +}; + +struct cam_sfe_top_common_reg_offset { + uint32_t hw_version; + uint32_t hw_capability; + uint32_t stats_feature; + uint32_t core_cgc_ctrl; + uint32_t ahb_clk_ovd; + uint32_t core_cfg; + uint32_t violation_status; + uint32_t diag_config; + uint32_t diag_sensor_status_0; + uint32_t diag_sensor_status_1; + uint32_t diag_sensor_frame_cnt_status0; + uint32_t diag_sensor_frame_cnt_status1; + uint32_t top_debug_0; + uint32_t top_debug_1; + uint32_t top_debug_2; + uint32_t top_debug_3; + uint32_t top_debug_4; + uint32_t top_debug_5; + uint32_t top_debug_6; + uint32_t top_debug_7; + uint32_t top_debug_8; + uint32_t top_debug_9; + uint32_t top_debug_10; + uint32_t top_debug_11; + uint32_t top_debug_cfg; + uint32_t stats_ch2_throttle_cfg; + uint32_t stats_ch1_throttle_cfg; + uint32_t stats_ch0_throttle_cfg; + uint32_t lcr_throttle_cfg; + uint32_t hdr_throttle_cfg; + uint32_t sfe_op_throttle_cfg; +}; + +struct cam_sfe_modules_common_reg_offset { + uint32_t demux_module_cfg; + uint32_t demux_qcfa_cfg; + uint32_t demux_hdr_cfg; + uint32_t demux_lcr_sel; + uint32_t hdrc_remo_mod_cfg; + uint32_t hdrc_remo_qcfa_bin_cfg; + uint32_t qcfa_hdrc_remo_out_mux_cfg; +}; + +struct cam_sfe_path_common_reg_data { + uint32_t sof_irq_mask; + uint32_t eof_irq_mask; + uint32_t error_irq_mask; + uint32_t subscribe_irq_mask; + uint32_t enable_diagnostic_hw; + uint32_t top_debug_cfg_en; +}; + +struct cam_sfe_top_hw_info { + struct cam_sfe_top_common_reg_offset *common_reg; + struct cam_sfe_modules_common_reg_offset *modules_hw_info; + struct cam_sfe_path_common_reg_data *pix_reg_data; + struct cam_sfe_path_common_reg_data *rdi_reg_data[CAM_SFE_RDI_MAX]; + uint32_t num_inputs; + uint32_t input_type[ + CAM_SFE_TOP_IN_PORT_MAX]; +}; + +int cam_sfe_top_init( + uint32_t hw_version, + struct cam_hw_soc_info *soc_info, + struct cam_hw_intf *hw_intf, + void *top_hw_info, + struct cam_sfe_top **sfe_top); + +int cam_sfe_top_deinit( + uint32_t hw_version, + struct cam_sfe_top **sfe_top); + +#endif /* _CAM_SFE_TOP_H_ */ diff --git a/drivers/camera_main.c b/drivers/camera_main.c index db91401f13dc..f59be8dbe113 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -13,6 +13,7 @@ #include "cam_ife_csid_dev.h" #include "cam_vfe.h" +#include "cam_sfe_dev.h" #include "cam_isp_dev.h" #include "cam_res_mgr_api.h" @@ -91,6 +92,9 @@ static const struct camera_submodule_component camera_isp[] = { {&cam_ife_csid17x_init_module, &cam_ife_csid17x_exit_module}, {&cam_ife_csid_lite_init_module, &cam_ife_csid_lite_exit_module}, {&cam_vfe_init_module, &cam_vfe_exit_module}, +#ifdef CONFIG_SPECTRA_SFE + {&cam_sfe_init_module, &cam_sfe_exit_module}, +#endif {&cam_isp_dev_init_module, &cam_isp_dev_exit_module}, #endif }; diff --git a/drivers/camera_main.h b/drivers/camera_main.h index 255985fc8c09..4cc6a6ae3e57 100644 --- a/drivers/camera_main.h +++ b/drivers/camera_main.h @@ -19,6 +19,9 @@ extern struct platform_driver cam_top_tpg_driver; extern struct platform_driver cam_ife_csid17x_driver; extern struct platform_driver cam_ife_csid_lite_driver; extern struct platform_driver cam_vfe_driver; +#ifdef CONFIG_SPECTRA_SFE +extern struct platform_driver cam_sfe_driver; +#endif extern struct platform_driver isp_driver; #endif #ifdef CONFIG_SPECTRA_TFE @@ -89,6 +92,9 @@ static struct platform_driver *const cam_component_drivers[] = { &cam_ife_csid17x_driver, &cam_ife_csid_lite_driver, &cam_vfe_driver, +#ifdef CONFIG_SPECTRA_SFE + &cam_sfe_driver, +#endif &isp_driver, #endif #ifdef CONFIG_SPECTRA_SENSOR From 8f5a2cd4273d42479fd876bcb99f1c3a62b918d6 Mon Sep 17 00:00:00 2001 From: Anand Ravi Date: Tue, 15 Sep 2020 14:56:16 -0700 Subject: [PATCH 538/790] msm: camera: isp: Print context on release HW error Print the context id in the error statement when release_hw is called in top state with no hw resources acquired. CRs-Fixed: 2709537 Change-Id: Ic153cc7f92cfc15a56e7989b0337a4e051af4c43 Signed-off-by: Anand Ravi --- drivers/cam_isp/cam_isp_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d8847b00a4fd..069a45bab1a6 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3998,7 +3998,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, &rel_arg); ctx_isp->hw_ctx = NULL; } else { - CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx"); + CAM_ERR(CAM_ISP, "No hw resources acquired for ctx[%u]", ctx->ctx_id); } ctx->last_flush_req = 0; From ef90082f0b724a31c26eff2f6c1b9cefb606c057 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 1 Oct 2020 16:20:45 +0530 Subject: [PATCH 539/790] msm: camera: ope: Fix false hw hang detection While preparing config packet at HW layer, we are setting Ope request timer even before processing command buffer and IO cfg. This is leading to false hw hand detection. Expectation is Ope request timer has to start after req is submitted to HW. CRs-Fixed: 2788900 Change-Id: Idd1420b2ee1aed4bfe947cf5617bbec9b39147d3 Signed-off-by: Shravya Samala --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 26 +++++++++------------ 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 1485e3a5eebe..69dbdc77a4ee 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1337,7 +1337,7 @@ static int cam_ope_mgr_calculate_num_path( ((clk_info->axi_path[i].path_data_type - CAM_AXI_PATH_DATA_OPE_START_OFFSET) >= CAM_OPE_MAX_PER_PATH_VOTES)) { - CAM_WARN(CAM_OPE, + CAM_DBG(CAM_OPE, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i].path_data_type, CAM_AXI_PATH_DATA_OPE_START_OFFSET, @@ -3191,21 +3191,13 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, CAM_ERR(CAM_OPE, "Invalid ctx req slot = %d", request_idx); return -EINVAL; } - ktime_get_boottime_ts64(&ts); - ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) + - ts.tv_nsec); - CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lrt=%llu", - packet->header.request_id, ctx_data->ctx_id, - ctx_data->last_req_time); - cam_ope_req_timer_modify(ctx_data, OPE_REQUEST_TIMEOUT); - set_bit(request_idx, ctx_data->bitmap); + ctx_data->req_list[request_idx] = kzalloc(sizeof(struct cam_ope_request), GFP_KERNEL); if (!ctx_data->req_list[request_idx]) { CAM_ERR(CAM_OPE, "mem allocation failed ctx:%d req_idx:%d", ctx_data->ctx_id, request_idx); rc = -ENOMEM; - mutex_unlock(&ctx_data->ctx_mutex); goto req_mem_alloc_failed; } @@ -3219,14 +3211,12 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, CAM_ERR(CAM_OPE, "Cdm mem alloc failed ctx:%d req_idx:%d", ctx_data->ctx_id, request_idx); rc = -ENOMEM; - mutex_unlock(&ctx_data->ctx_mutex); goto req_cdm_mem_alloc_failed; } rc = cam_ope_mgr_process_cmd_desc(hw_mgr, packet, ctx_data, &ope_cmd_buf_addr, request_idx); if (rc) { - mutex_unlock(&ctx_data->ctx_mutex); CAM_ERR(CAM_OPE, "cmd desc processing failed :%d ctx: %d req_id:%d", rc, ctx_data->ctx_id, packet->header.request_id); @@ -3236,7 +3226,6 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, rc = cam_ope_mgr_process_io_cfg(hw_mgr, packet, prepare_args, ctx_data, request_idx); if (rc) { - mutex_unlock(&ctx_data->ctx_mutex); CAM_ERR(CAM_OPE, "IO cfg processing failed: %d ctx: %d req_id:%d", rc, ctx_data->ctx_id, packet->header.request_id); @@ -3246,7 +3235,6 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, rc = cam_ope_mgr_create_kmd_buf(hw_mgr, packet, prepare_args, ctx_data, request_idx, ope_cmd_buf_addr); if (rc) { - mutex_unlock(&ctx_data->ctx_mutex); CAM_ERR(CAM_OPE, "create kmd buf failed: %d ctx: %d request_id:%d", rc, ctx_data->ctx_id, packet->header.request_id); @@ -3256,7 +3244,6 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, rc = cam_ope_process_generic_cmd_buffer(packet, ctx_data, request_idx, NULL); if (rc) { - mutex_unlock(&ctx_data->ctx_mutex); CAM_ERR(CAM_OPE, "Failed: %d ctx: %d req_id: %d req_idx: %d", rc, ctx_data->ctx_id, packet->header.request_id, request_idx); @@ -3268,6 +3255,14 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, prepare_args->priv = ctx_data->req_list[request_idx]; prepare_args->pf_data->packet = packet; ope_req->hang_data.packet = packet; + ktime_get_boottime_ts64(&ts); + ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lrt=%llu", + packet->header.request_id, ctx_data->ctx_id, + ctx_data->last_req_time); + cam_ope_req_timer_modify(ctx_data, OPE_REQUEST_TIMEOUT); + set_bit(request_idx, ctx_data->bitmap); mutex_unlock(&ctx_data->ctx_mutex); CAM_DBG(CAM_REQ, "Prepare Hw update Successful request_id: %d ctx: %d", @@ -3282,6 +3277,7 @@ req_cdm_mem_alloc_failed: ctx_data->req_list[request_idx] = NULL; req_mem_alloc_failed: clear_bit(request_idx, ctx_data->bitmap); + mutex_unlock(&ctx_data->ctx_mutex); return rc; } From e4b180abaf756fb9e6a6094365b4d220b5ac9390 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 28 Jul 2020 22:25:46 -0700 Subject: [PATCH 540/790] msm: camera: isp: Support for SFE IRQ handling Add irq controller support for the SFE core & bus interfaces. CRs-Fixed: 2783797 Change-Id: I84c04a13fa26a9d040bab9e7ec7ba2d3061e1f76 Signed-off-by: Jigarkumar Zala Signed-off-by: Karthik Anantha Ram --- .../isp_hw/include/cam_sfe_hw_intf.h | 69 ++- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h | 48 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c | 35 +- .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h | 2 - .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c | 5 +- .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c | 274 ++++++++++- .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h | 5 +- .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c | 465 +++++++++++++++++- .../isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h | 4 +- .../sfe_hw/sfe_bus/include/cam_sfe_bus.h | 9 +- .../isp_hw/sfe_hw/sfe_top/cam_sfe_top.c | 355 ++++++++++++- .../isp_hw/sfe_hw/sfe_top/cam_sfe_top.h | 1 + 12 files changed, 1201 insertions(+), 71 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h index 55f76f30f38a..c517563bdd32 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h @@ -7,6 +7,7 @@ #define _CAM_SFE_HW_INTF_H_ #include "cam_isp_hw.h" +#include "cam_isp_hw_mgr_intf.h" #define SFE_CORE_BASE_IDX 0 #define SFE_RT_CDM_BASE_IDX 1 @@ -48,6 +49,11 @@ enum cam_sfe_bus_irq_regs { CAM_SFE_BUS_IRQ_REGISTERS_MAX, }; +enum cam_sfe_bus_rd_irq_regs { + CAM_SFE_IRQ_BUS_RD_REG_STATUS0, + CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX, +}; + /* * struct cam_sfe_fe_update_args: * @@ -83,33 +89,78 @@ struct cam_sfe_core_config_args { }; /* - * struct cam_sfe_irq_evt_payload: + * struct cam_sfe_top_irq_evt_payload: * * @Brief: This structure is used to save payload for IRQ - * related to SFE resources + * related to SFE top resource * * @list: list_head node for the payload * @core_index: Index of SFE HW that generated this IRQ event * @evt_id: IRQ event * @irq_reg_val: IRQ and Error register values, read when IRQ was * handled - * @bus_irq_val Bus irq register status - * @ccif_violation_status ccif violation status - * @overflow_status bus overflow status - * @image_size_vio_sts image size violations status + * @violation_status ccif violation status * @error_type: Identify different errors * @ts: Timestamp */ -struct cam_sfe_irq_evt_payload { +struct cam_sfe_top_irq_evt_payload { struct list_head list; uint32_t core_index; uint32_t evt_id; uint32_t irq_reg_val[CAM_SFE_IRQ_REGISTERS_MAX]; - uint32_t bus_irq_val[CAM_SFE_BUS_IRQ_REGISTERS_MAX]; + uint32_t violation_status; + uint32_t error_type; + struct cam_isp_timestamp ts; +}; + +/* + * struct cam_sfe_bus_wr_irq_evt_payload: + * + * @Brief: This structure is used to save payload for IRQ + * BUS related to SFE resources + * + * @list: list_head node for the payload + * @core_index: Index of SFE HW that generated this IRQ event + * @irq_reg_val Bus irq register status + * @ccif_violation_status ccif violation status + * @overflow_status bus overflow status + * @image_size_vio_sts image size violations status + * @error_type: Identify different errors + * @evt_id: IRQ event + * @ts: Timestamp + */ +struct cam_sfe_bus_wr_irq_evt_payload { + struct list_head list; + uint32_t core_index; + uint32_t irq_reg_val[CAM_SFE_BUS_IRQ_REGISTERS_MAX]; uint32_t ccif_violation_status; uint32_t overflow_status; - uint32_t image_size_vio_sts; + uint32_t image_size_violation_status; uint32_t error_type; + uint32_t evt_id; + struct cam_isp_timestamp ts; +}; + +/* + * struct cam_sfe_bus_rd_irq_evt_payload: + * + * @Brief: This structure is used to save payload for IRQ + * BUS related to SFE resources + * + * @list: list_head node for the payload + * @irq_reg_val Bus irq register status + * @constraint_violation constraint violation + * @error_type: Identify different errors + * @evt_id: IRQ event + * @ts: Timestamp + */ +struct cam_sfe_bus_rd_irq_evt_payload { + struct list_head list; + uint32_t irq_reg_val[ + CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX]; + uint32_t constraint_violation; + uint32_t error_type; + uint32_t evt_id; struct cam_isp_timestamp ts; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h index 2da1d3f35d57..1821310f9ba7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h @@ -128,6 +128,14 @@ static struct cam_sfe_top_hw_info sfe680_top_hw_info = { }, }; +static struct cam_irq_register_set sfe680_bus_rd_irq_reg[1] = { + { + .mask_reg_offset = 0x00000404, + .clear_reg_offset = 0x00000408, + .status_reg_offset = 0x00000410, + }, +}; + static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = { .common_reg = { .hw_version = 0x00000400, @@ -136,6 +144,13 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = { .input_if_cmd = 0x00000414, .test_bus_ctrl = 0x0000042C, .security_cfg = 0x00000420, + .cons_violation_status = 0x00000434, + .irq_reg_info = { + .num_registers = 1, + .irq_reg_set = sfe680_bus_rd_irq_reg, + .global_clear_offset = 0x0000040C, + .global_clear_bitmask = 0x00000001, + }, }, .num_client = 3, .bus_client_reg = { @@ -191,6 +206,14 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = { .top_irq_shift = 0x1, }; +static struct cam_irq_register_set sfe680_bus_wr_irq_reg[1] = { + { + .mask_reg_offset = 0x00000818, + .clear_reg_offset = 0x00000820, + .status_reg_offset = 0x00000828, + }, +}; + static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .common_reg = { .hw_version = 0x00000800, @@ -211,7 +234,13 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_top_cfg = 0x000008D4, .debug_status_top = 0x000008D8, .test_bus_ctrl = 0x000008DC, - .top_irq_mask_0 = 0x00000818, + .top_irq_mask_0 = 0x00000020, + .irq_reg_info = { + .num_registers = 1, + .irq_reg_set = sfe680_bus_wr_irq_reg, + .global_clear_offset = 0x00000830, + .global_clear_bitmask = 0x00000001, + }, }, .num_client = 13, .bus_client_reg = { @@ -679,8 +708,23 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .top_irq_shift = 0x0, }; +static struct cam_irq_register_set sfe680_top_irq_reg_set[1] = { +{ + .mask_reg_offset = 0x00000020, + .clear_reg_offset = 0x00000024, + .status_reg_offset = 0x00000028, + }, +}; + +static struct cam_irq_controller_reg_info sfe680_top_irq_reg_info = { + .num_registers = 1, + .irq_reg_set = sfe680_top_irq_reg_set, + .global_clear_offset = 0x0000001C, + .global_clear_bitmask = 0x00000001, +}; + struct cam_sfe_hw_info cam_sfe680_hw_info = { - .irq_reg_info = NULL, + .irq_reg_info = &sfe680_top_irq_reg_info, .bus_wr_version = CAM_SFE_BUS_WR_VER_1_0, .bus_wr_hw_info = &sfe680_bus_wr_hw_info, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c index ca0220c10d22..8c6907f29725 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c @@ -407,17 +407,28 @@ int cam_sfe_core_init( struct cam_hw_intf *hw_intf, struct cam_sfe_hw_info *sfe_hw_info) { - int rc; + int rc = -EINVAL; + + rc = cam_irq_controller_init(drv_name, + CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX), + sfe_hw_info->irq_reg_info, &core_info->sfe_irq_controller, + true); + if (rc) { + CAM_ERR(CAM_SFE, "SFE irq controller init failed"); + return rc; + } rc = cam_sfe_top_init(sfe_hw_info->top_version, soc_info, hw_intf, - sfe_hw_info->top_hw_info, &core_info->sfe_top); + sfe_hw_info->top_hw_info, core_info->sfe_irq_controller, + &core_info->sfe_top); if (rc) { CAM_ERR(CAM_SFE, "SFE top init failed rc: %d", rc); - return rc; + goto deinit_controller; } rc = cam_sfe_bus_init(sfe_hw_info->bus_wr_version, BUS_TYPE_SFE_WR, soc_info, hw_intf, sfe_hw_info->bus_wr_hw_info, + core_info->sfe_irq_controller, &core_info->sfe_bus_wr); if (rc) { CAM_ERR(CAM_SFE, "SFE bus wr init failed rc: %d", rc); @@ -426,13 +437,13 @@ int cam_sfe_core_init( rc = cam_sfe_bus_init(sfe_hw_info->bus_rd_version, BUS_TYPE_SFE_RD, soc_info, hw_intf, sfe_hw_info->bus_rd_hw_info, + core_info->sfe_irq_controller, &core_info->sfe_bus_rd); if (rc) { CAM_ERR(CAM_SFE, "SFE bus rd init failed rc: %d", rc); goto deinit_bus_wr; } - INIT_LIST_HEAD(&core_info->free_payload_list); spin_lock_init(&core_info->spin_lock); CAM_DBG(CAM_SFE, "SFE device [%u] INIT success", hw_intf->hw_idx); @@ -445,6 +456,11 @@ deinit_bus_wr: deinit_top: cam_sfe_top_deinit(sfe_hw_info->top_version, &core_info->sfe_top); +deinit_controller: + if (cam_irq_controller_deinit(&core_info->sfe_irq_controller)) + CAM_ERR(CAM_SFE, + "Error cam_irq_controller_deinit failed rc=%d", rc); + return rc; } @@ -452,15 +468,11 @@ int cam_sfe_core_deinit( struct cam_sfe_hw_core_info *core_info, struct cam_sfe_hw_info *sfe_hw_info) { - int rc = -EINVAL, i; + int rc = -EINVAL; unsigned long flags; spin_lock_irqsave(&core_info->spin_lock, flags); - INIT_LIST_HEAD(&core_info->free_payload_list); - for (i = 0; i < CAM_SFE_EVT_MAX; i++) - INIT_LIST_HEAD(&core_info->evt_payload[i].list); - rc = cam_sfe_bus_deinit(BUS_TYPE_SFE_RD, sfe_hw_info->bus_rd_version, &core_info->sfe_bus_rd); @@ -481,6 +493,11 @@ int cam_sfe_core_deinit( CAM_ERR(CAM_SFE, "SFE top deinit failed rc: %d", rc); + rc = cam_irq_controller_deinit(&core_info->sfe_irq_controller); + if (rc) + CAM_ERR(CAM_SFE, + "Error cam_irq_controller_deinit failed rc=%d", rc); + spin_unlock_irqrestore(&core_info->spin_lock, flags); return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h index 349de9e7e15a..b8ed146e3407 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h @@ -34,8 +34,6 @@ struct cam_sfe_hw_core_info { struct cam_sfe_bus *sfe_bus_rd; void *sfe_irq_controller; void *tasklet_info; - struct cam_sfe_irq_evt_payload evt_payload[CAM_SFE_EVT_MAX]; - struct list_head free_payload_list; spinlock_t spin_lock; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c index d713714e1dab..39bf7eb4b3c9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c @@ -14,6 +14,7 @@ int cam_sfe_bus_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *bus_hw_info, + void *sfe_irq_controller, struct cam_sfe_bus **sfe_bus) { int rc = -ENODEV; @@ -23,7 +24,7 @@ int cam_sfe_bus_init( switch (bus_version) { case CAM_SFE_BUS_WR_VER_1_0: rc = cam_sfe_bus_wr_init(soc_info, hw_intf, - bus_hw_info, sfe_bus); + bus_hw_info, sfe_irq_controller, sfe_bus); break; default: CAM_ERR(CAM_SFE, "Unsupported Bus WR Version 0x%x", @@ -35,7 +36,7 @@ int cam_sfe_bus_init( switch (bus_version) { case CAM_SFE_BUS_RD_VER_1_0: rc = cam_sfe_bus_rd_init(soc_info, hw_intf, - bus_hw_info, sfe_bus); + bus_hw_info, sfe_irq_controller, sfe_bus); break; default: CAM_ERR(CAM_SFE, "Unsupported Bus RD Version 0x%x", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c index f9ad59da9fa1..7bed7948c5cf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c @@ -28,7 +28,12 @@ static const char drv_name[] = "sfe_bus_rd"; #define MAX_REG_VAL_PAIR_SIZE \ (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) -#define BUS_RD_DEFAULT_LATENCY_BUF_ALLOC 512 +#define BUS_RD_DEFAULT_LATENCY_BUF_ALLOC 512 +#define CAM_SFE_BUS_RD_PAYLOAD_MAX 16 + +static uint32_t bus_rd_error_irq_mask[1] = { + 0x00000001, +}; enum cam_sfe_bus_rd_unpacker_format { BUS_RD_UNPACKER_FMT_PLAIN_128 = 0x0, @@ -60,7 +65,12 @@ struct cam_sfe_bus_rd_common_data { struct cam_sfe_bus_rd_reg_offset_common *common_reg; uint32_t io_buf_update[ MAX_REG_VAL_PAIR_SIZE]; - + void *bus_irq_controller; + void *sfe_irq_controller; + spinlock_t spin_lock; + struct list_head free_payload_list; + struct cam_sfe_bus_rd_irq_evt_payload evt_payload[ + CAM_SFE_BUS_RD_PAYLOAD_MAX]; cam_hw_mgr_event_cb_func event_cb; }; @@ -95,7 +105,6 @@ struct cam_sfe_bus_rd_data { uint32_t max_height; struct cam_cdm_utils_ops *cdm_util_ops; void *priv; - uint32_t status; uint32_t secure_mode; uint32_t fs_sync_enable; uint32_t fs_line_sync_en; @@ -112,6 +121,8 @@ struct cam_sfe_bus_rd_priv { struct cam_isp_resource_node sfe_bus_rd[ CAM_SFE_BUS_RD_MAX]; + int irq_handle; + int error_irq_handle; void *tasklet_info; uint32_t top_irq_shift; }; @@ -280,6 +291,73 @@ static int cam_sfe_bus_get_rm_idx( return rm_idx; } +static int cam_sfe_bus_rd_get_evt_payload( + struct cam_sfe_bus_rd_common_data *common_data, + struct cam_sfe_bus_rd_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&common_data->spin_lock); + + if (list_empty(&common_data->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_SFE, + "No free BUS RD event payload"); + *evt_payload = NULL; + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&common_data->free_payload_list, + struct cam_sfe_bus_rd_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + +done: + spin_unlock(&common_data->spin_lock); + return rc; +} + +static int cam_sfe_bus_rd_put_evt_payload( + struct cam_sfe_bus_rd_common_data *common_data, + struct cam_sfe_bus_rd_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!common_data) { + CAM_ERR(CAM_SFE, "Invalid param common_data NULL"); + return -EINVAL; + } + + if (*evt_payload == NULL) { + CAM_ERR(CAM_SFE, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&common_data->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, + &common_data->free_payload_list); + spin_unlock_irqrestore(&common_data->spin_lock, flags); + + *evt_payload = NULL; + + return 0; +} + +static int cam_sfe_bus_rd_handle_irq( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_sfe_bus_rd_priv *bus_priv; + int rc = 0; + + bus_priv = th_payload->handler_priv; + CAM_DBG(CAM_SFE, "Top Bus RD IRQ Received"); + + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.bus_irq_controller); + + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; +} + static int cam_sfe_bus_acquire_rm( struct cam_sfe_bus_rd_priv *bus_rd_priv, void *tasklet, @@ -452,6 +530,99 @@ static int cam_sfe_bus_deinit_rm_resource( return 0; } +static int cam_sfe_bus_rd_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int i, rc = 0; + struct cam_sfe_bus_rd_priv *bus_priv; + struct cam_sfe_bus_rd_irq_evt_payload *evt_payload = NULL; + + bus_priv = th_payload->handler_priv; + rc = cam_sfe_bus_rd_get_evt_payload( + &bus_priv->common_data, &evt_payload); + if (rc) + return rc; + + for (i = 0; i < th_payload->num_registers; i++) { + evt_payload->irq_reg_val[i] = + th_payload->evt_status_arr[i]; + CAM_DBG(CAM_SFE, "SFE:%d Bus RD IRQ status_%d: 0x%x", + bus_priv->common_data.core_index, i, + th_payload->evt_status_arr[i]); + } + + evt_payload->constraint_violation = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->cons_violation_status); + if (evt_payload->constraint_violation) { + CAM_ERR(CAM_SFE, "SFE:%d constraint violation:0x%x", + bus_priv->common_data.core_index, + evt_payload->constraint_violation); + cam_irq_controller_disable_irq( + bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + cam_irq_controller_clear_and_mask(evt_id, + bus_priv->common_data.bus_irq_controller); + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + th_payload->evt_payload_priv = evt_payload; + return 0; +} + +static int cam_sfe_bus_rd_handle_irq_bottom_half( + void *handler_priv, void *evt_payload_priv) +{ + struct cam_sfe_bus_rd_irq_evt_payload *evt_payload; + struct cam_sfe_bus_rd_priv *bus_priv; + struct cam_sfe_bus_rd_common_data *common_data = NULL; + struct cam_isp_hw_event_info evt_info; + uint32_t status = 0, constraint_violation = 0; + + if (!handler_priv || !evt_payload_priv) + return -EINVAL; + + bus_priv = (struct cam_sfe_bus_rd_priv *)handler_priv; + evt_payload = (struct cam_sfe_bus_rd_irq_evt_payload *)evt_payload_priv; + common_data = &bus_priv->common_data; + status = evt_payload->irq_reg_val[CAM_SFE_IRQ_BUS_RD_REG_STATUS0]; + constraint_violation = evt_payload->constraint_violation; + cam_sfe_bus_rd_put_evt_payload(common_data, &evt_payload); + + if (status & 0x2) + CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD RUP", + bus_priv->common_data.core_index); + + if (status & 0x4) + CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD0 BUF DONE", + bus_priv->common_data.core_index); + + if (status & 0x8) + CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD1 BUF DONE", + bus_priv->common_data.core_index); + + if (status & 0x10) + CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD2 BUF DONE", + bus_priv->common_data.core_index); + + if (status & 0x1) { + CAM_ERR(CAM_SFE, "SFE:%d Constraint violation status:0x%x", + bus_priv->common_data.core_index, + constraint_violation); + + evt_info.hw_idx = bus_priv->common_data.core_index; + evt_info.res_type = CAM_ISP_RESOURCE_SFE_RD; + evt_info.res_id = CAM_SFE_BUS_RD_MAX; + evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION; + + if (common_data->event_cb) + common_data->event_cb(NULL, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + } + + return 0; +} + static int cam_sfe_bus_rd_get_secure_mode(void *priv, void *cmd_args, uint32_t arg_size) { @@ -639,7 +810,7 @@ static int cam_sfe_bus_start_bus_rd( for (i = 0; i < rsrc_data->num_rm; i++) rc = cam_sfe_bus_start_rm(rsrc_data->rm_res[i]); - /* Subscribe mask for buf_done */ + /* TO DO Subscribe mask for buf_done */ sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; return rc; @@ -930,19 +1101,52 @@ static int cam_sfe_bus_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) { struct cam_sfe_bus_rd_priv *bus_priv = hw_priv; - uint32_t sfe_top_irq_mask = 0; uint32_t offset = 0; struct cam_sfe_bus_rd_reg_offset_common *common_reg; + uint32_t sfe_top_irq_mask[CAM_SFE_IRQ_REGISTERS_MAX] = {0}; if (!bus_priv) { CAM_ERR(CAM_SFE, "Invalid args"); return -EINVAL; } common_reg = bus_priv->common_data.common_reg; - sfe_top_irq_mask = (1 << bus_priv->top_irq_shift); + sfe_top_irq_mask[0] = (1 << bus_priv->top_irq_shift); - /* Subscribe for error IRQs */ + /* Subscribe for top IRQ */ + bus_priv->irq_handle = cam_irq_controller_subscribe_irq( + bus_priv->common_data.sfe_irq_controller, + CAM_IRQ_PRIORITY_2, + sfe_top_irq_mask, + bus_priv, + cam_sfe_bus_rd_handle_irq, + NULL, + NULL, + NULL); + if (bus_priv->irq_handle < 1) { + CAM_ERR(CAM_SFE, + "Failed to subscribe TOP IRQ for BUS RD"); + bus_priv->irq_handle = 0; + 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_1, + bus_rd_error_irq_mask, + bus_priv, + cam_sfe_bus_rd_handle_irq_top_half, + cam_sfe_bus_rd_handle_irq_bottom_half, + bus_priv->tasklet_info, + &tasklet_bh_api); + + if (bus_priv->error_irq_handle < 1) { + CAM_ERR(CAM_SFE, "Failed to subscribe error IRQ"); + bus_priv->error_irq_handle = 0; + return -EFAULT; + } + } /* BUS_RD_TEST_BUS_CTRL disabling test bus */ offset = common_reg->test_bus_ctrl; cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset); @@ -954,7 +1158,6 @@ static int cam_sfe_bus_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) { struct cam_sfe_bus_rd_priv *bus_priv = hw_priv; - uint32_t sfe_top_irq_mask = 0; int rc = 0; if (!bus_priv) { @@ -962,9 +1165,24 @@ static int cam_sfe_bus_deinit_hw(void *hw_priv, return -EINVAL; } - sfe_top_irq_mask = 1 << bus_priv->top_irq_shift; + /* Unsubscribe irqs */ + if (bus_priv->irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + bus_priv->common_data.sfe_irq_controller, + bus_priv->irq_handle); + if (rc) + CAM_ERR(CAM_SFE, "Failed to unsubscribe top irq"); + bus_priv->irq_handle = 0; + } - /* Unsubscribe for err irqs */ + 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_SFE, "Failed to unsubscribe error irq"); + bus_priv->error_irq_handle = 0; + } return rc; } @@ -1005,6 +1223,7 @@ int cam_sfe_bus_rd_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *bus_hw_info, + void *sfe_irq_controller, struct cam_sfe_bus **sfe_bus) { int i, rc = 0; @@ -1036,7 +1255,6 @@ int cam_sfe_bus_rd_init( } sfe_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; @@ -1044,9 +1262,19 @@ int cam_sfe_bus_rd_init( bus_priv->common_data.mem_base = CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX); bus_priv->common_data.hw_intf = hw_intf; + bus_priv->common_data.sfe_irq_controller = sfe_irq_controller; bus_priv->common_data.common_reg = &bus_rd_hw_info->common_reg; bus_priv->top_irq_shift = bus_rd_hw_info->top_irq_shift; + 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, true); + if (rc) { + CAM_ERR(CAM_SFE, "IRQ controller init failed"); + goto free_bus_priv; + } + for (i = 0; i < bus_priv->num_client; i++) { rc = cam_sfe_bus_init_rm_resource(i, bus_priv, bus_hw_info, &bus_priv->bus_client[i]); @@ -1065,12 +1293,21 @@ int cam_sfe_bus_rd_init( } } + spin_lock_init(&bus_priv->common_data.spin_lock); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_SFE_BUS_RD_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + list_add_tail(&bus_priv->common_data.evt_payload[i].list, + &bus_priv->common_data.free_payload_list); + } + sfe_bus_local->hw_ops.reserve = cam_sfe_bus_acquire_bus_rd; sfe_bus_local->hw_ops.release = cam_sfe_bus_release_bus_rd; sfe_bus_local->hw_ops.start = cam_sfe_bus_start_bus_rd; sfe_bus_local->hw_ops.stop = cam_sfe_bus_stop_bus_rd; sfe_bus_local->hw_ops.init = cam_sfe_bus_init_hw; sfe_bus_local->hw_ops.deinit = cam_sfe_bus_deinit_hw; + sfe_bus_local->top_half_handler = cam_sfe_bus_rd_handle_irq; sfe_bus_local->bottom_half_handler = NULL; sfe_bus_local->hw_ops.process_cmd = cam_sfe_bus_rd_process_cmd; @@ -1090,6 +1327,7 @@ deinit_rm: for (--i; i >= 0; i--) cam_sfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]); +free_bus_priv: kfree(sfe_bus_local->bus_priv); free_bus_local: @@ -1103,6 +1341,7 @@ int cam_sfe_bus_rd_deinit( struct cam_sfe_bus **sfe_bus) { int i, rc = 0; + unsigned long flags; struct cam_sfe_bus_rd_priv *bus_priv = NULL; struct cam_sfe_bus *sfe_bus_local; @@ -1119,6 +1358,12 @@ int cam_sfe_bus_rd_deinit( goto free_bus_local; } + spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); + INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_SFE_BUS_RD_PAYLOAD_MAX; i++) + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); + for (i = 0; i < bus_priv->num_client; i++) { rc = cam_sfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]); if (rc < 0) @@ -1133,11 +1378,16 @@ int cam_sfe_bus_rd_deinit( "Deinit SFE RD failed rc=%d", rc); } + rc = cam_irq_controller_deinit( + &bus_priv->common_data.bus_irq_controller); + if (rc) + CAM_ERR(CAM_SFE, + "Deinit IRQ Controller failed rc=%d", rc); + kfree(sfe_bus_local->bus_priv); free_bus_local: kfree(sfe_bus_local); - *sfe_bus = NULL; return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h index e3dd0988105b..39ad21d74779 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h @@ -29,6 +29,8 @@ struct cam_sfe_bus_rd_reg_offset_common { uint32_t input_if_cmd; uint32_t test_bus_ctrl; uint32_t security_cfg; + uint32_t cons_violation_status; + struct cam_irq_controller_reg_info irq_reg_info; }; /* @@ -98,6 +100,7 @@ int cam_sfe_bus_rd_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *bus_hw_info, + void *sfe_irq_controller, struct cam_sfe_bus **sfe_bus); /* @@ -105,7 +108,7 @@ int cam_sfe_bus_rd_init( * * @Brief: Deinitialize Bus layer * - * @vfe_bus: Pointer to sfe_bus structure to deinitialize + * @sfe_bus: Pointer to sfe_bus structure to deinitialize * * @Return: 0: Success * Non-zero: Failure diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c index 9dac41227e24..5666b8df1479 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c @@ -37,6 +37,10 @@ static const char drv_name[] = "sfe_bus_wr"; #define MAX_REG_VAL_PAIR_SIZE \ (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) +static uint32_t bus_wr_error_irq_mask[1] = { + 0xD0000000, +}; + enum cam_sfe_bus_wr_packer_format { PACKER_FMT_PLAIN_128, PACKER_FMT_PLAIN_8, @@ -63,12 +67,16 @@ struct cam_sfe_bus_wr_common_data { uint32_t hw_version; void __iomem *mem_base; struct cam_hw_intf *hw_intf; + void *sfe_irq_controller; void *buf_done_controller; + void *bus_irq_controller; struct cam_sfe_bus_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 cam_sfe_bus_wr_irq_evt_payload evt_payload[ + CAM_SFE_BUS_WR_PAYLOAD_MAX]; struct mutex bus_mutex; uint32_t secure_mode; uint32_t num_sec_out; @@ -167,10 +175,9 @@ struct cam_sfe_bus_wr_priv { struct list_head free_comp_grp; struct list_head used_comp_grp; - //int bus_irq_handle; - //int rup_irq_handle; - //int error_irq_handle; - //void *tasklet_info; + int bus_irq_handle; + int error_irq_handle; + void *tasklet_info; }; static int cam_sfe_bus_wr_process_cmd( @@ -235,6 +242,54 @@ static enum cam_sfe_bus_sfe_out_type } } +static int cam_sfe_bus_get_comp_sfe_out_res_id_list( + uint32_t comp_mask, uint32_t *out_list, int *num_out) +{ + int count = 0; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI0)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_0; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI1)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_1; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI2)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_2; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI3)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_3; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI4)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_4; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RAW_DUMP)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_RAW_DUMP; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BE_0)) + out_list[count++] = CAM_ISP_SFE_OUT_BE_STATS_0; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BHIST_0)) + out_list[count++] = CAM_ISP_SFE_OUT_BHIST_STATS_0; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BE_1)) + out_list[count++] = CAM_ISP_SFE_OUT_BE_STATS_1; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BHIST_1)) + out_list[count++] = CAM_ISP_SFE_OUT_BHIST_STATS_1; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BE_2)) + out_list[count++] = CAM_ISP_SFE_OUT_BE_STATS_2; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BHIST_2)) + out_list[count++] = CAM_ISP_SFE_OUT_BHIST_STATS_2; + + if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_LCR)) + out_list[count++] = CAM_ISP_SFE_OUT_RES_LCR; + + *num_out = count; + return 0; +} + static enum cam_sfe_bus_wr_packer_format cam_sfe_bus_get_packer_fmt(uint32_t out_fmt, int wm_index) { @@ -766,7 +821,9 @@ static int cam_sfe_bus_start_comp_grp( if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) return 0; - /* TO DO Enable top irq */ + bus_irq_reg_mask[CAM_SFE_IRQ_BUS_REG_STATUS0] = + (0x1 << (rsrc_data->comp_grp_type + + rsrc_data->common_data->comp_done_shift)); CAM_DBG(CAM_SFE, "Start Done SFE:%d comp_grp:%d", rsrc_data->common_data->core_index, @@ -1073,13 +1130,73 @@ static int cam_sfe_bus_release_sfe_out(void *bus_priv, void *release_args, return 0; } +static int cam_sfe_bus_wr_get_evt_payload( + struct cam_sfe_bus_wr_common_data *common_data, + struct cam_sfe_bus_wr_irq_evt_payload **evt_payload) +{ + int rc; + + spin_lock(&common_data->spin_lock); + + if (!common_data->hw_init) { + CAM_ERR_RATE_LIMIT(CAM_SFE, "SFE:%d Bus uninitialized", + common_data->core_index); + *evt_payload = NULL; + rc = -EPERM; + goto done; + } + + if (list_empty(&common_data->free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_SFE, "No free BUS event payload"); + *evt_payload = NULL; + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry(&common_data->free_payload_list, + struct cam_sfe_bus_wr_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + rc = 0; +done: + spin_unlock(&common_data->spin_lock); + return rc; +} + +static int cam_sfe_bus_wr_put_evt_payload( + struct cam_sfe_bus_wr_common_data *common_data, + struct cam_sfe_bus_wr_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!common_data) { + CAM_ERR(CAM_SFE, "Invalid param common_data NULL"); + return -EINVAL; + } + + if (*evt_payload == NULL) { + CAM_ERR(CAM_SFE, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&common_data->spin_lock, flags); + if (common_data->hw_init) + list_add_tail(&(*evt_payload)->list, + &common_data->free_payload_list); + spin_unlock_irqrestore(&common_data->spin_lock, flags); + + *evt_payload = NULL; + + CAM_DBG(CAM_SFE, "Done"); + return 0; +} + static int cam_sfe_bus_start_sfe_out( struct cam_isp_resource_node *sfe_out) { int rc = 0, i; struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; struct cam_sfe_bus_wr_common_data *common_data = NULL; - uint32_t bus_irq_reg_mask[2]; + uint32_t bus_irq_reg_mask[CAM_SFE_IRQ_REGISTERS_MAX]; uint32_t source_group = 0; if (!sfe_out) { @@ -1112,8 +1229,21 @@ static int cam_sfe_bus_start_sfe_out( if (rsrc_data->is_dual && !rsrc_data->is_master) goto end; - /* TO DO IRQ handling */ - + sfe_out->irq_handle = cam_irq_controller_subscribe_irq( + common_data->buf_done_controller, + CAM_IRQ_PRIORITY_1, + bus_irq_reg_mask, + sfe_out, + sfe_out->top_half_handler, + sfe_out->bottom_half_handler, + sfe_out->tasklet_info, + &tasklet_bh_api); + if (sfe_out->irq_handle < 1) { + CAM_ERR(CAM_SFE, "Subscribe IRQ failed for sfe out_res: %d", + sfe_out->res_id); + sfe_out->irq_handle = 0; + return -EFAULT; + } end: sfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; return rc; @@ -1148,10 +1278,161 @@ static int cam_sfe_bus_stop_sfe_out( rc = cam_sfe_bus_stop_wm(&rsrc_data->wm_res[i]); /* TO DO any IRQ handling */ + if (sfe_out->irq_handle) { + cam_irq_controller_unsubscribe_irq( + common_data->buf_done_controller, + sfe_out->irq_handle); + sfe_out->irq_handle = 0; + } + sfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; return rc; } +static int cam_sfe_bus_handle_sfe_out_done_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int32_t rc; + int i; + struct cam_isp_resource_node *sfe_out = NULL; + struct cam_sfe_bus_wr_out_data *rsrc_data = NULL; + struct cam_sfe_bus_wr_irq_evt_payload *evt_payload; + struct cam_sfe_bus_wr_comp_grp_data *resource_data; + uint32_t status_0; + + sfe_out = th_payload->handler_priv; + if (!sfe_out) { + CAM_ERR_RATE_LIMIT(CAM_SFE, "No resource"); + return -ENODEV; + } + + rsrc_data = sfe_out->res_priv; + resource_data = rsrc_data->comp_grp->res_priv; + + CAM_DBG(CAM_SFE, "SFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + + rc = cam_sfe_bus_wr_get_evt_payload(rsrc_data->common_data, + &evt_payload); + if (rc) { + CAM_INFO_RATE_LIMIT(CAM_SFE, + "SFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0], + th_payload->evt_status_arr[1]); + return rc; + } + + cam_isp_hw_get_timestamp(&evt_payload->ts); + + evt_payload->core_index = rsrc_data->common_data->core_index; + evt_payload->evt_id = evt_id; + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + th_payload->evt_payload_priv = evt_payload; + + status_0 = th_payload->evt_status_arr[CAM_SFE_IRQ_BUS_REG_STATUS0]; + + if (status_0 & BIT(resource_data->comp_grp_type + + rsrc_data->common_data->comp_done_shift)) { + trace_cam_log_event("bufdone", "bufdone_IRQ", + status_0, resource_data->comp_grp_type); + } + + return rc; +} + +static int cam_sfe_bus_handle_comp_done_bottom_half( + void *handler_priv, + void *evt_payload_priv, + uint32_t *comp_mask) +{ + int rc = CAM_SFE_IRQ_STATUS_ERR; + struct cam_isp_resource_node *comp_grp = handler_priv; + struct cam_sfe_bus_wr_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = comp_grp->res_priv; + uint32_t *cam_ife_irq_regs; + uint32_t status_0; + + if (!evt_payload) + return rc; + + if (rsrc_data->is_dual && (!rsrc_data->is_master)) { + CAM_ERR(CAM_SFE, "Invalid comp_grp:%u is_master:%u", + rsrc_data->comp_grp_type, rsrc_data->is_master); + return rc; + } + + cam_ife_irq_regs = evt_payload->irq_reg_val; + status_0 = cam_ife_irq_regs[CAM_SFE_IRQ_BUS_REG_STATUS0]; + + if (status_0 & BIT(rsrc_data->comp_grp_type + + rsrc_data->common_data->comp_done_shift)) { + evt_payload->evt_id = CAM_ISP_HW_EVENT_DONE; + rc = CAM_SFE_IRQ_STATUS_SUCCESS; + } + + CAM_DBG(CAM_SFE, "SFE:%d comp_grp:%d Bus IRQ status_0: 0x%X rc:%d", + rsrc_data->common_data->core_index, rsrc_data->comp_grp_type, + status_0, rc); + + *comp_mask = rsrc_data->composite_mask; + + return rc; +} + +static int cam_sfe_bus_handle_sfe_out_done_bottom_half( + void *handler_priv, + void *evt_payload_priv) +{ + int rc = -EINVAL, num_out = 0, i = 0; + struct cam_isp_resource_node *sfe_out = handler_priv; + struct cam_sfe_bus_wr_out_data *rsrc_data = sfe_out->res_priv; + struct cam_sfe_bus_wr_irq_evt_payload *evt_payload = evt_payload_priv; + struct cam_isp_hw_event_info evt_info; + void *ctx = NULL; + uint32_t evt_id = 0, comp_mask = 0; + uint32_t out_list[CAM_SFE_BUS_SFE_OUT_MAX]; + + rc = cam_sfe_bus_handle_comp_done_bottom_half( + rsrc_data->comp_grp, evt_payload_priv, &comp_mask); + CAM_DBG(CAM_SFE, "SFE:%d out_type:0x%X rc:%d", + rsrc_data->common_data->core_index, rsrc_data->out_type, + rsrc_data->out_type, rc); + + ctx = rsrc_data->priv; + memset(out_list, 0, sizeof(out_list)); + + switch (rc) { + case CAM_SFE_IRQ_STATUS_SUCCESS: + evt_id = evt_payload->evt_id; + + evt_info.res_type = sfe_out->res_type; + evt_info.hw_idx = sfe_out->hw_intf->hw_idx; + + rc = cam_sfe_bus_get_comp_sfe_out_res_id_list( + comp_mask, out_list, &num_out); + for (i = 0; i < num_out; i++) { + evt_info.res_id = out_list[i]; + if (rsrc_data->common_data->event_cb) + rsrc_data->common_data->event_cb(ctx, evt_id, + (void *)&evt_info); + } + break; + default: + break; + } + + cam_sfe_bus_wr_put_evt_payload(rsrc_data->common_data, &evt_payload); + + return rc; +} + static int cam_sfe_bus_init_sfe_out_resource( uint32_t index, struct cam_sfe_bus_wr_priv *bus_priv, @@ -1220,11 +1501,12 @@ static int cam_sfe_bus_init_sfe_out_resource( return rc; } - /* TO DO top & bh */ sfe_out->start = cam_sfe_bus_start_sfe_out; sfe_out->stop = cam_sfe_bus_stop_sfe_out; - sfe_out->top_half_handler = NULL; - sfe_out->bottom_half_handler = NULL; + sfe_out->top_half_handler = + cam_sfe_bus_handle_sfe_out_done_top_half; + sfe_out->bottom_half_handler = + cam_sfe_bus_handle_sfe_out_done_bottom_half; sfe_out->process_cmd = cam_sfe_bus_wr_process_cmd; sfe_out->hw_intf = bus_priv->common_data.hw_intf; sfe_out->irq_handle = 0; @@ -1307,6 +1589,97 @@ static int cam_sfe_bus_wr_print_dimensions( return 0; } +static int cam_sfe_bus_wr_handle_bus_irq(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_sfe_bus_wr_priv *bus_priv; + int rc = 0; + + bus_priv = th_payload->handler_priv; + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.bus_irq_controller); + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; +} + +static int cam_sfe_bus_wr_err_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + + int i = 0, rc = 0; + struct cam_sfe_bus_wr_priv *bus_priv = + th_payload->handler_priv; + struct cam_sfe_bus_wr_irq_evt_payload *evt_payload; + + CAM_ERR_RATE_LIMIT(CAM_ISP, "SFE:%d BUS Err IRQ", + bus_priv->common_data.core_index); + + for (i = 0; i < th_payload->num_registers; i++) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "SFE:%d BUS IRQ status_%d: 0x%X", + bus_priv->common_data.core_index, i, + th_payload->evt_status_arr[i]); + } + cam_irq_controller_disable_irq( + bus_priv->common_data.bus_irq_controller, + bus_priv->error_irq_handle); + + rc = cam_sfe_bus_wr_get_evt_payload(&bus_priv->common_data, + &evt_payload); + if (rc) + return rc; + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + + evt_payload->core_index = bus_priv->common_data.core_index; + + evt_payload->ccif_violation_status = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->ccif_violation_status); + + evt_payload->image_size_violation_status = cam_io_r_mb( + bus_priv->common_data.mem_base + + bus_priv->common_data.common_reg->image_size_violation_status); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_sfe_bus_wr_irq_bottom_half( + void *handler_priv, void *evt_payload_priv) +{ + uint32_t status = 0; + struct cam_sfe_bus_wr_priv *bus_priv = handler_priv; + struct cam_sfe_bus_wr_common_data *common_data; + struct cam_isp_hw_event_info evt_info; + struct cam_sfe_bus_wr_irq_evt_payload *evt_payload = evt_payload_priv; + + if (!handler_priv || !evt_payload_priv) + return -EINVAL; + + common_data = &bus_priv->common_data; + + status = evt_payload->irq_reg_val[CAM_SFE_IRQ_BUS_REG_STATUS0]; + + CAM_ERR(CAM_SFE, + "SFE:%d status 0x%x Image Size violation status 0x%x CCIF violation status 0x%x", + bus_priv->common_data.core_index, status, + evt_payload->image_size_violation_status, + evt_payload->ccif_violation_status); + + cam_sfe_bus_wr_put_evt_payload(common_data, &evt_payload); + + evt_info.hw_idx = common_data->core_index; + evt_info.res_type = CAM_ISP_RESOURCE_SFE_OUT; + evt_info.res_id = CAM_SFE_BUS_SFE_OUT_MAX; + evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION; + + if (common_data->event_cb) + common_data->event_cb(NULL, CAM_ISP_HW_EVENT_ERROR, + (void *)&evt_info); + return 0; +} + static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args, uint32_t arg_size) { @@ -1680,6 +2053,7 @@ static int cam_sfe_bus_wr_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) { struct cam_sfe_bus_wr_priv *bus_priv = hw_priv; + uint32_t top_irq_reg_mask[CAM_SFE_IRQ_REGISTERS_MAX] = {0}; if (!bus_priv) { CAM_ERR(CAM_SFE, "Invalid args"); @@ -1689,7 +2063,42 @@ static int cam_sfe_bus_wr_init_hw(void *hw_priv, if (bus_priv->common_data.hw_init) return 0; - /* To Do Subscribe IRQs */ + /* Subscribe top IRQ */ + top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift); + + bus_priv->bus_irq_handle = cam_irq_controller_subscribe_irq( + bus_priv->common_data.sfe_irq_controller, + CAM_IRQ_PRIORITY_4, + top_irq_reg_mask, + bus_priv, + cam_sfe_bus_wr_handle_bus_irq, + NULL, + NULL, + NULL); + + if (bus_priv->bus_irq_handle < 1) { + CAM_ERR(CAM_SFE, "Failed to subscribe BUS (buf_done) IRQ"); + bus_priv->bus_irq_handle = 0; + 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_wr_error_irq_mask, + bus_priv, + cam_sfe_bus_wr_err_irq_top_half, + cam_sfe_bus_wr_irq_bottom_half, + bus_priv->tasklet_info, + &tasklet_bh_api); + + if (bus_priv->error_irq_handle < 1) { + CAM_ERR(CAM_SFE, "Failed to subscribe BUS Error IRQ"); + bus_priv->error_irq_handle = 0; + return -EFAULT; + } + } /* BUS_WR_TEST_BUS_CTRL */ cam_io_w_mb(0x0, bus_priv->common_data.mem_base + @@ -1787,13 +2196,13 @@ int cam_sfe_bus_wr_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *bus_hw_info, + void *sfe_irq_controller, struct cam_sfe_bus **sfe_bus) { int i, rc = 0; struct cam_sfe_bus_wr_priv *bus_priv = NULL; struct cam_sfe_bus *sfe_bus_local; struct cam_sfe_bus_wr_hw_info *hw_info = bus_hw_info; - struct cam_sfe_soc_private *soc_private = NULL; CAM_DBG(CAM_SFE, "Enter"); @@ -1805,13 +2214,6 @@ int cam_sfe_bus_wr_init( goto end; } - soc_private = soc_info->soc_private; - if (!soc_private) { - CAM_ERR(CAM_SFE, "Invalid soc_private"); - rc = -ENODEV; - goto end; - } - sfe_bus_local = kzalloc(sizeof(struct cam_sfe_bus), GFP_KERNEL); if (!sfe_bus_local) { CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus"); @@ -1841,11 +2243,11 @@ int cam_sfe_bus_wr_init( bus_priv->common_data.common_reg = &hw_info->common_reg; bus_priv->common_data.comp_done_shift = hw_info->comp_done_shift; bus_priv->common_data.hw_init = false; - + bus_priv->common_data.sfe_irq_controller = sfe_irq_controller; rc = cam_cpas_get_cpas_hw_version(&bus_priv->common_data.hw_version); if (rc) { CAM_ERR(CAM_SFE, "Failed to get hw_version rc:%d", rc); - goto end; + goto free_bus_priv; } bus_priv->comp_grp = kzalloc((sizeof(struct cam_isp_resource_node) * @@ -1865,6 +2267,15 @@ int cam_sfe_bus_wr_init( } mutex_init(&bus_priv->common_data.bus_mutex); + rc = cam_irq_controller_init(drv_name, + bus_priv->common_data.mem_base, + &hw_info->common_reg.irq_reg_info, + &bus_priv->common_data.bus_irq_controller, + false); + if (rc) { + CAM_ERR(CAM_SFE, "Init bus_irq_controller failed"); + goto free_bus_priv; + } INIT_LIST_HEAD(&bus_priv->free_comp_grp); INIT_LIST_HEAD(&bus_priv->used_comp_grp); @@ -1894,6 +2305,12 @@ int cam_sfe_bus_wr_init( spin_lock_init(&bus_priv->common_data.spin_lock); INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); + for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + list_add_tail(&bus_priv->common_data.evt_payload[i].list, + &bus_priv->common_data.free_payload_list); + } + sfe_bus_local->hw_ops.reserve = cam_sfe_bus_acquire_sfe_out; sfe_bus_local->hw_ops.release = cam_sfe_bus_release_sfe_out; sfe_bus_local->hw_ops.start = cam_sfe_bus_wr_start_hw; @@ -1958,8 +2375,8 @@ int cam_sfe_bus_wr_deinit( spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags); INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list); - //for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++) - //INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); + for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++) + INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list); bus_priv->common_data.hw_init = false; spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h index 54ea96bb3d46..1b448247edad 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h @@ -7,7 +7,6 @@ #ifndef _CAM_SFE_BUS_WR_H_ #define _CAM_SFE_BUS_WR_H_ -#include "cam_irq_controller.h" #include "cam_sfe_bus.h" #define CAM_SFE_BUS_WR_MAX_CLIENTS 13 @@ -72,6 +71,7 @@ struct cam_sfe_bus_reg_offset_common { uint32_t debug_status_top; uint32_t test_bus_ctrl; uint32_t top_irq_mask_0; + struct cam_irq_controller_reg_info irq_reg_info; }; /* @@ -154,6 +154,7 @@ struct cam_sfe_bus_wr_hw_info { * @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 + * @sfe_irq_controller: SFE irq controller * @sfe_bus: Pointer to sfe_bus structure which will be filled * and returned on successful initialize * @@ -164,6 +165,7 @@ int cam_sfe_bus_wr_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *bus_hw_info, + void *sfe_irq_controller, struct cam_sfe_bus **sfe_bus); /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h index 7cac8108397e..00cc78689bb1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h @@ -6,7 +6,6 @@ #ifndef _CAM_SFE_BUS_H_ #define _CAM_SFE_BUS_H_ -#include "cam_isp_hw.h" #include "cam_sfe_hw_intf.h" #define CAM_SFE_BUS_WR_VER_1_0 0x1000 @@ -50,8 +49,7 @@ enum cam_sfe_bus_type { * @bottom_half_handler: Bottom Half handler function */ struct cam_sfe_bus { - void *bus_priv; - + void *bus_priv; struct cam_hw_ops hw_ops; CAM_IRQ_HANDLER_TOP_HALF top_half_handler; CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; @@ -67,17 +65,20 @@ struct cam_sfe_bus { * @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 + * @sfe_irq_controller: SFE irq controller * @sfe_bus: Pointer to sfe_bus structure which will be filled * and returned on successful initialize * * @Return: 0: Success * Non-zero: Failure */ -int cam_sfe_bus_init(uint32_t bus_version, +int cam_sfe_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, + void *sfe_irq_controller, struct cam_sfe_bus **sfe_bus); /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c index a61a539fdb44..e3586e65de61 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c @@ -7,9 +7,11 @@ #include "cam_io_util.h" #include "cam_cdm_util.h" #include "cam_sfe_hw_intf.h" +#include "cam_tasklet_util.h" #include "cam_sfe_top.h" #include "cam_debug_util.h" #include "cam_sfe_soc.h" +#include "cam_sfe_core.h" struct cam_sfe_core_cfg { uint32_t mode_sel; @@ -18,9 +20,12 @@ struct cam_sfe_core_cfg { }; struct cam_sfe_top_common_data { - struct cam_hw_soc_info *soc_info; - struct cam_hw_intf *hw_intf; - struct cam_sfe_top_common_reg_offset *common_reg; + struct cam_hw_soc_info *soc_info; + struct cam_hw_intf *hw_intf; + struct cam_sfe_top_common_reg_offset *common_reg; + struct cam_irq_controller *sfe_irq_controller; + struct cam_sfe_top_irq_evt_payload evt_payload[CAM_SFE_EVT_MAX]; + struct list_head free_payload_list; }; struct cam_sfe_top_priv { @@ -38,20 +43,45 @@ struct cam_sfe_top_priv { CAM_SFE_TOP_IN_PORT_MAX]; struct cam_sfe_core_cfg core_cfg; uint32_t sfe_debug_cfg; + spinlock_t spin_lock; }; struct cam_sfe_path_data { void __iomem *mem_base; void *priv; struct cam_hw_intf *hw_intf; + struct cam_sfe_top_priv *top_priv; struct cam_sfe_top_common_reg_offset *common_reg; struct cam_sfe_modules_common_reg_offset *modules_reg; struct cam_sfe_path_common_reg_data *path_reg_data; struct cam_hw_soc_info *soc_info; uint32_t min_hblank_cnt; + int error_irq_handle; + int sof_eof_handle; cam_hw_mgr_event_cb_func event_cb; }; +static const char *cam_sfe_top_res_id_to_string( + uint32_t res_id) +{ + switch (res_id) { + case CAM_ISP_HW_SFE_IN_PIX: + return "PP"; + case CAM_ISP_HW_SFE_IN_RDI0: + return "RDI0"; + case CAM_ISP_HW_SFE_IN_RDI1: + return "RDI1"; + case CAM_ISP_HW_SFE_IN_RDI2: + return "RDI2"; + case CAM_ISP_HW_SFE_IN_RDI3: + return "RDI3"; + case CAM_ISP_HW_SFE_IN_RDI4: + return "RDI4"; + default: + return ""; + } +} + static int cam_sfe_top_core_cfg( struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -329,6 +359,7 @@ int cam_sfe_top_reserve(void *device_priv, top_priv->in_rsrc[i].res_priv; path_data->event_cb = args->event_cb; path_data->priv = args->priv; + path_data->top_priv = top_priv; CAM_DBG(CAM_SFE, "SFE [%u] for rsrc: %u acquired", top_priv->in_rsrc[i].hw_intf->hw_idx, @@ -379,6 +410,244 @@ int cam_sfe_top_release(void *device_priv, return 0; } +static int cam_sfe_top_get_evt_payload( + struct cam_sfe_top_priv *top_priv, + struct cam_sfe_top_irq_evt_payload **evt_payload) +{ + int rc = 0; + + spin_lock(&top_priv->spin_lock); + if (list_empty(&top_priv->common_data.free_payload_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free CAMIF LITE event payload"); + *evt_payload = NULL; + rc = -ENODEV; + goto done; + } + + *evt_payload = list_first_entry( + &top_priv->common_data.free_payload_list, + struct cam_sfe_top_irq_evt_payload, list); + list_del_init(&(*evt_payload)->list); + +done: + spin_unlock(&top_priv->spin_lock); + return rc; +} + +static int cam_sfe_top_put_evt_payload( + struct cam_sfe_top_priv *top_priv, + struct cam_sfe_top_irq_evt_payload **evt_payload) +{ + unsigned long flags; + + if (!top_priv) { + CAM_ERR(CAM_SFE, "Invalid param core_info NULL"); + return -EINVAL; + } + if (*evt_payload == NULL) { + CAM_ERR(CAM_SFE, "No payload to put"); + return -EINVAL; + } + + spin_lock_irqsave(&top_priv->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, + &top_priv->common_data.free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&top_priv->spin_lock, flags); + + CAM_DBG(CAM_SFE, "Done"); + return 0; +} + +static void cam_sfe_top_print_debug_reg_info( + struct cam_sfe_path_data *path_data) +{ + CAM_INFO(CAM_SFE, + "Debug0: 0x%x Debug1: 0x%x Debug2: 0x%x Debug3: 0x%x", + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_0), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_1), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_2), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_3)); + CAM_INFO(CAM_SFE, + "Debug4: 0x%x Debug5: 0x%x Debug6: 0x%x Debug7: 0x%x", + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_4), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_5), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_6), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_7)); + CAM_INFO(CAM_SFE, + "Debug8: 0x%x Debug9: 0x%x Debug10: 0x%x Debug11: 0x%x", + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_8), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_9), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_10), + cam_io_r_mb(path_data->mem_base + + path_data->common_reg->top_debug_11)); +} + +static int cam_sfe_top_handle_err_irq_top_half( + uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int rc = 0, i; + uint32_t irq_status = 0; + void __iomem *base = NULL; + struct cam_sfe_top_priv *top_priv; + struct cam_isp_resource_node *res; + struct cam_sfe_path_data *path_data; + struct cam_sfe_top_irq_evt_payload *evt_payload; + + res = th_payload->handler_priv; + path_data = res->res_priv; + top_priv = path_data->priv; + + CAM_DBG(CAM_SFE, "Top error IRQ Received"); + + irq_status = th_payload->evt_status_arr[0]; + + base = path_data->mem_base; + if (irq_status & path_data->path_reg_data->error_irq_mask) { + CAM_ERR(CAM_SFE, + "SFE Violation Detected irq_status: 0x%x", + irq_status); + cam_irq_controller_disable_irq( + top_priv->common_data.sfe_irq_controller, + path_data->error_irq_handle); + cam_irq_controller_clear_and_mask(evt_id, + top_priv->common_data.sfe_irq_controller); + } + + rc = cam_sfe_top_get_evt_payload(top_priv, &evt_payload); + if (rc) + return rc; + + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = + th_payload->evt_status_arr[i]; + + cam_isp_hw_get_timestamp(&evt_payload->ts); + evt_payload->violation_status = + cam_io_r(base + + top_priv->common_data.common_reg->violation_status); + + th_payload->evt_payload_priv = evt_payload; + + return rc; +} + +static int cam_sfe_top_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + int rc = 0, i; + uint32_t irq_status = 0; + struct cam_sfe_top_priv *top_priv; + struct cam_isp_resource_node *res; + struct cam_sfe_path_data *path_data; + struct cam_sfe_top_irq_evt_payload *evt_payload; + + res = th_payload->handler_priv; + path_data = res->res_priv; + top_priv = path_data->top_priv; + + rc = cam_sfe_top_get_evt_payload(top_priv, &evt_payload); + if (rc) + return rc; + + irq_status = th_payload->evt_status_arr[0]; + CAM_DBG(CAM_SFE, "SFE top irq status: 0x%x", + irq_status); + for (i = 0; i < th_payload->num_registers; i++) + evt_payload->irq_reg_val[i] = + th_payload->evt_status_arr[i]; + + cam_isp_hw_get_timestamp(&evt_payload->ts); + th_payload->evt_payload_priv = evt_payload; + return rc; +} + +static int cam_sfe_top_handle_irq_bottom_half( + void *handler_priv, void *evt_payload_priv) +{ + int i; + uint32_t irq_status[CAM_SFE_IRQ_REGISTERS_MAX] = {0}; + enum cam_sfe_hw_irq_status ret; + struct cam_isp_hw_event_info evt_info; + struct cam_isp_resource_node *res = handler_priv; + struct cam_sfe_path_data *path_data = res->res_priv; + struct cam_sfe_top_priv *top_priv = path_data->top_priv; + struct cam_sfe_top_irq_evt_payload *payload = evt_payload_priv; + + for (i = 0; i < CAM_SFE_IRQ_REGISTERS_MAX; i++) + irq_status[i] = payload->irq_reg_val[i]; + + evt_info.hw_idx = res->hw_intf->hw_idx; + evt_info.res_id = res->res_id; + evt_info.res_type = res->res_type; + evt_info.reg_val = 0; + + if (irq_status[0] & + path_data->path_reg_data->error_irq_mask) { + if (irq_status[0] & 0x4000) + CAM_ERR(CAM_SFE, "PP VIOLATION"); + + if (irq_status[0] & 0x8000) + CAM_ERR(CAM_SFE, "DIAG VIOLATION"); + + if (irq_status[0] & 0x10000) + CAM_ERR(CAM_SFE, "LINE SMOOTH VIOLATION"); + + CAM_INFO(CAM_SFE, "Violation status 0x%x", + payload->violation_status); + + evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION; + cam_sfe_top_print_debug_reg_info(path_data); + if (path_data->event_cb) + path_data->event_cb(NULL, + CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + ret = CAM_SFE_IRQ_STATUS_VIOLATION; + } + + /* To Do Debugfs entry to control the enablement */ + if (irq_status[0] & path_data->path_reg_data->subscribe_irq_mask) { + if (irq_status[0] & path_data->path_reg_data->sof_irq_mask) { + CAM_INFO_RATE_LIMIT(CAM_SFE, "SFE:%d Received %s SOF", + evt_info.hw_idx, + cam_sfe_top_res_id_to_string(res->res_id)); + } + + if (irq_status[0] & + path_data->path_reg_data->eof_irq_mask) { + CAM_INFO_RATE_LIMIT(CAM_SFE, "SFE:%d Received %s EOF", + evt_info.hw_idx, + cam_sfe_top_res_id_to_string(res->res_id)); + } + ret = CAM_SFE_IRQ_STATUS_SUCCESS; + } + + /* To DO frame counter under debugfs */ + CAM_DBG(CAM_SFE, + "SFE:%d SFE_DIAG_SENSOR_STATUS0: 0x%x SFE_DIAG_SENSOR_STATUS1: 0x%x", + evt_info.hw_idx, + cam_io_r(path_data->mem_base + + path_data->common_reg->diag_sensor_status_0), + cam_io_r(path_data->mem_base + + path_data->common_reg->diag_sensor_status_1)); + + cam_sfe_top_put_evt_payload(top_priv, &payload); + + return ret; +} + int cam_sfe_top_start( void *priv, void *start_args, uint32_t arg_size) { @@ -387,6 +656,8 @@ int cam_sfe_top_start( struct cam_isp_resource_node *sfe_res; struct cam_hw_info *hw_info = NULL; struct cam_sfe_path_data *path_data; + uint32_t error_mask[CAM_SFE_IRQ_REGISTERS_MAX]; + uint32_t sof_eof_mask[CAM_SFE_IRQ_REGISTERS_MAX]; if (!priv || !start_args) { CAM_ERR(CAM_SFE, "Invalid args"); @@ -421,13 +692,54 @@ int cam_sfe_top_start( path_data->common_reg->core_cfg)); /* Enable debug cfg registers */ - cam_io_w_mb(path_data->path_reg_data->top_debug_cfg_en, + cam_io_w(path_data->path_reg_data->top_debug_cfg_en, path_data->mem_base + path_data->common_reg->top_debug_cfg); /* Enable sensor diag info */ - /* Enable SOF & EOF IRQ based on debug flag */ + /* TO DO - debug fs to enable*/ + cam_io_w(path_data->path_reg_data->enable_diagnostic_hw, + path_data->mem_base + path_data->common_reg->diag_config); + + error_mask[0] = path_data->path_reg_data->error_irq_mask; /* Enable error IRQ by default */ + if (!path_data->error_irq_handle) { + path_data->error_irq_handle = cam_irq_controller_subscribe_irq( + top_priv->common_data.sfe_irq_controller, + CAM_IRQ_PRIORITY_0, + error_mask, + sfe_res, + cam_sfe_top_handle_err_irq_top_half, + cam_sfe_top_handle_irq_bottom_half, + sfe_res->tasklet_info, + &tasklet_bh_api); + + if (path_data->error_irq_handle < 1) { + CAM_ERR(CAM_SFE, "Failed to subscribe Top IRQ"); + path_data->error_irq_handle = 0; + return -EFAULT; + } + } + + /* TO DO define the debugfs to enable/disable sof/eof irq */ + if (!path_data->sof_eof_handle) { + sof_eof_mask[0] = path_data->path_reg_data->subscribe_irq_mask; + path_data->sof_eof_handle = cam_irq_controller_subscribe_irq( + top_priv->common_data.sfe_irq_controller, + CAM_IRQ_PRIORITY_1, + sof_eof_mask, + sfe_res, + cam_sfe_top_handle_irq_top_half, + cam_sfe_top_handle_irq_bottom_half, + sfe_res->tasklet_info, + &tasklet_bh_api); + + if (path_data->sof_eof_handle < 1) { + CAM_ERR(CAM_SFE, "Failed to subscribe SOF/EOF IRQ"); + path_data->sof_eof_handle = 0; + return -EFAULT; + } + } sfe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; return 0; @@ -439,6 +751,7 @@ int cam_sfe_top_stop( int i; struct cam_sfe_top_priv *top_priv; struct cam_isp_resource_node *sfe_res; + struct cam_sfe_path_data *path_data; if (!priv || !stop_args) { CAM_ERR(CAM_SFE, "Invalid args"); @@ -447,6 +760,7 @@ int cam_sfe_top_stop( top_priv = (struct cam_sfe_top_priv *)priv; sfe_res = (struct cam_isp_resource_node *) stop_args; + path_data = sfe_res->res_priv; if (sfe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED || sfe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) @@ -465,6 +779,18 @@ int cam_sfe_top_stop( } } + if (path_data->error_irq_handle > 0) { + cam_irq_controller_unsubscribe_irq( + top_priv->common_data.sfe_irq_controller, + path_data->error_irq_handle); + } + + if (path_data->sof_eof_handle > 0) { + cam_irq_controller_unsubscribe_irq( + top_priv->common_data.sfe_irq_controller, + path_data->sof_eof_handle); + } + return 0; } @@ -473,6 +799,7 @@ int cam_sfe_top_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *top_hw_info, + void *sfe_irq_controller, struct cam_sfe_top **sfe_top_ptr) { int i, j, rc = 0; @@ -497,6 +824,7 @@ int cam_sfe_top_init( } sfe_top->top_priv = top_priv; + top_priv->common_data.sfe_irq_controller = sfe_irq_controller; if (sfe_top_hw_info->num_inputs > CAM_SFE_TOP_IN_PORT_MAX) { CAM_ERR(CAM_SFE, "Invalid number of input resources: %d max: %d", @@ -590,6 +918,15 @@ int cam_sfe_top_init( sfe_top->hw_ops.stop = cam_sfe_top_stop; sfe_top->hw_ops.reserve = cam_sfe_top_reserve; sfe_top->hw_ops.release = cam_sfe_top_release; + + spin_lock_init(&top_priv->spin_lock); + INIT_LIST_HEAD(&top_priv->common_data.free_payload_list); + for (i = 0; i < CAM_SFE_EVT_MAX; i++) { + INIT_LIST_HEAD(&top_priv->common_data.evt_payload[i].list); + list_add_tail(&top_priv->common_data.evt_payload[i].list, + &top_priv->common_data.free_payload_list); + } + *sfe_top_ptr = sfe_top; return rc; @@ -625,6 +962,7 @@ int cam_sfe_top_deinit( struct cam_sfe_top **sfe_top_ptr) { int i, rc = 0; + unsigned long flags; struct cam_sfe_top *sfe_top; struct cam_sfe_top_priv *top_priv; @@ -651,6 +989,13 @@ int cam_sfe_top_deinit( top_priv->common_data.hw_intf->hw_idx, hw_version); + spin_lock_irqsave(&top_priv->spin_lock, flags); + INIT_LIST_HEAD(&top_priv->common_data.free_payload_list); + for (i = 0; i < CAM_SFE_EVT_MAX; i++) + INIT_LIST_HEAD( + &top_priv->common_data.evt_payload[i].list); + spin_unlock_irqrestore(&top_priv->spin_lock, flags); + for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) { top_priv->in_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h index c6ad17579293..fc3024808800 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.h @@ -93,6 +93,7 @@ int cam_sfe_top_init( struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, void *top_hw_info, + void *sfe_irq_controller, struct cam_sfe_top **sfe_top); int cam_sfe_top_deinit( From 9f092f1d49119a3c191d7b790f18355212be23c3 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Mon, 15 Jun 2020 16:45:11 -0700 Subject: [PATCH 541/790] msm: camera: isp: Add BW voting path for SFE HW Add register, start, stop and bw update/control functions. CRs-Fixed: 2783797 Change-Id: I587e6eca66ee9d7316f2602d60bfc77b9f8704cf Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Karthik Anantha Ram --- drivers/cam_cpas/cam_cpas_intf.c | 16 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 18 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 2 +- .../isp_hw/include/cam_sfe_hw_intf.h | 23 ++ .../isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c | 2 +- .../isp_hw/sfe_hw/sfe_top/cam_sfe_top.c | 287 ++++++++++++++++++ 6 files changed, 337 insertions(+), 11 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f3af861cb614..1ff8f92fdd70 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -96,6 +96,22 @@ const char *cam_cpas_axi_util_path_type_to_string( case CAM_AXI_PATH_DATA_OPE_WR_REF: return "OPE_WR_REF"; + /* SFE Paths */ + case CAM_AXI_PATH_DATA_SFE_NRDI: + return "SFE_NRDI"; + case CAM_AXI_PATH_DATA_SFE_RDI0: + return "IFE_RDI0"; + case CAM_AXI_PATH_DATA_SFE_RDI1: + return "IFE_RDI1"; + case CAM_AXI_PATH_DATA_SFE_RDI2: + return "IFE_RDI2"; + case CAM_AXI_PATH_DATA_SFE_RDI3: + return "IFE_RDI3"; + case CAM_AXI_PATH_DATA_SFE_RDI4: + return "IFE_RDI4"; + case CAM_AXI_PATH_DATA_SFE_STATS: + return "SFE_STATS"; + /* Common Paths */ case CAM_AXI_PATH_DATA_ALL: return "DATA_ALL"; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 01e2028005c0..03ee81c12cc1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3472,8 +3472,8 @@ static int cam_isp_classify_vote_info( struct cam_isp_bw_config_v2 *bw_config, struct cam_axi_vote *isp_vote, uint32_t split_idx, - bool *camif_l_bw_updated, - bool *camif_r_bw_updated) + bool *nrdi_l_bw_updated, + bool *nrdi_r_bw_updated) { int rc = 0, i, j = 0; @@ -3482,7 +3482,7 @@ static int cam_isp_classify_vote_info( (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_LCR)) { if (split_idx == CAM_ISP_HW_SPLIT_LEFT) { - if (*camif_l_bw_updated) + if (*nrdi_l_bw_updated) return rc; for (i = 0; i < bw_config->num_paths; i++) { @@ -3497,9 +3497,9 @@ static int cam_isp_classify_vote_info( } isp_vote->num_paths = j; - *camif_l_bw_updated = true; + *nrdi_l_bw_updated = true; } else { - if (*camif_r_bw_updated) + if (*nrdi_r_bw_updated) return rc; for (i = 0; i < bw_config->num_paths; i++) { @@ -3514,7 +3514,7 @@ static int cam_isp_classify_vote_info( } isp_vote->num_paths = j; - *camif_r_bw_updated = true; + *nrdi_r_bw_updated = true; } } else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && (hw_mgr_res->res_id <= @@ -3570,8 +3570,8 @@ static int cam_isp_blob_bw_update_v2( struct cam_vfe_bw_update_args_v2 bw_upd_args; int rc = -EINVAL; uint32_t i, split_idx; - bool camif_l_bw_updated = false; - bool camif_r_bw_updated = false; + bool nrdi_l_bw_updated = false; + bool nrdi_r_bw_updated = false; for (i = 0; i < bw_config->num_paths; i++) { CAM_DBG(CAM_PERF, @@ -3598,7 +3598,7 @@ static int cam_isp_blob_bw_update_v2( sizeof(struct cam_axi_vote)); rc = cam_isp_classify_vote_info(hw_mgr_res, bw_config, &bw_upd_args.isp_vote, split_idx, - &camif_l_bw_updated, &camif_r_bw_updated); + &nrdi_l_bw_updated, &nrdi_r_bw_updated); if (rc) return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 4243f1acebfc..2d3d30df1525 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -21,7 +21,7 @@ #define CAM_TFE_RDI_NUM_MAX 3 /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ -#define CAM_ISP_MAX_PER_PATH_VOTES 30 +#define CAM_ISP_MAX_PER_PATH_VOTES 40 /** * enum cam_isp_hw_event_type - Collection of the ISP hardware events diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h index c517563bdd32..2d445feeedba 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h @@ -8,6 +8,7 @@ #include "cam_isp_hw.h" #include "cam_isp_hw_mgr_intf.h" +#include "cam_cpas_api.h" #define SFE_CORE_BASE_IDX 0 #define SFE_RT_CDM_BASE_IDX 1 @@ -54,6 +55,28 @@ enum cam_sfe_bus_rd_irq_regs { CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX, }; +/* + * struct cam_sfe_bw_control_args: + * + * @node_res: Resource node info + * @action: Bandwidth control action + */ +struct cam_sfe_bw_control_args { + struct cam_isp_resource_node *node_res; + enum cam_sfe_bw_control_action action; +}; + +/* + * struct cam_sfe_bw_update_args: + * + * @node_res: Resource to get the BW + * @sfe_vote: Vote info according to usage data (left/right/rdi) + */ +struct cam_sfe_bw_update_args { + struct cam_isp_resource_node *node_res; + struct cam_axi_vote sfe_vote; +}; + /* * struct cam_sfe_fe_update_args: * diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c index aa6b42db8c20..d5277edfb843 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c @@ -157,7 +157,7 @@ int cam_sfe_enable_soc_resources(struct cam_hw_soc_info *soc_info) axi_vote.axi_path[0].mnoc_ib_bw = 10640000000L; rc = cam_cpas_start(soc_private->cpas_handle, - &ahb_vote, &axi_vote); + &ahb_vote, &axi_vote); if (rc) { CAM_ERR(CAM_SFE, "CPAS start failed rc=%d", rc); rc = -EFAULT; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c index e3586e65de61..aabe64a87fd6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c @@ -13,6 +13,8 @@ #include "cam_sfe_soc.h" #include "cam_sfe_core.h" +#define CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES 18 + struct cam_sfe_core_cfg { uint32_t mode_sel; uint32_t ops_mode_cfg; @@ -41,6 +43,7 @@ struct cam_sfe_top_priv { CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES]; enum cam_sfe_bw_control_action axi_vote_control[ CAM_SFE_TOP_IN_PORT_MAX]; + struct cam_axi_vote applied_axi_vote; struct cam_sfe_core_cfg core_cfg; uint32_t sfe_debug_cfg; spinlock_t spin_lock; @@ -82,6 +85,279 @@ static const char *cam_sfe_top_res_id_to_string( } } +static struct cam_axi_vote *cam_sfe_top_delay_bw_reduction( + struct cam_sfe_top_priv *top_priv, + uint64_t *to_be_applied_bw) +{ + uint32_t i, j; + int vote_idx = -1; + uint64_t max_bw = 0; + uint64_t total_bw; + struct cam_axi_vote *curr_l_vote; + + for (i = 0; i < CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; i++) { + total_bw = 0; + curr_l_vote = &top_priv->last_vote[i]; + for (j = 0; j < curr_l_vote->num_paths; j++) { + if (total_bw > + (U64_MAX - + curr_l_vote->axi_path[j].camnoc_bw)) { + CAM_ERR(CAM_PERF, + "sfe[%d] : Integer overflow at hist idx: %d, path: %d, total_bw = %llu, camnoc_bw = %llu", + top_priv->common_data.hw_intf->hw_idx, + i, j, total_bw, + curr_l_vote->axi_path[j].camnoc_bw); + return NULL; + } + + total_bw += curr_l_vote->axi_path[j].camnoc_bw; + } + + if (total_bw > max_bw) { + vote_idx = i; + max_bw = total_bw; + } + } + + if (vote_idx < 0) + return NULL; + + *to_be_applied_bw = max_bw; + + return &top_priv->last_vote[vote_idx]; +} + +int cam_sfe_top_set_axi_bw_vote(struct cam_sfe_soc_private *soc_private, + struct cam_sfe_top_priv *top_priv, bool start_stop) +{ + struct cam_axi_vote agg_vote = {0}; + struct cam_axi_vote *to_be_applied_axi_vote = NULL; + int rc = 0; + uint32_t i; + uint32_t num_paths = 0; + uint64_t total_bw_new_vote = 0; + bool bw_unchanged = true; + bool apply_bw_update = false; + + for (i = 0; i < top_priv->num_in_ports; i++) { + if (top_priv->axi_vote_control[i] == + CAM_SFE_BW_CONTROL_INCLUDE) { + if (num_paths + + top_priv->req_axi_vote[i].num_paths > + CAM_CPAS_MAX_PATHS_PER_CLIENT) { + CAM_ERR(CAM_PERF, + "Required paths(%d) more than max(%d)", + num_paths + + top_priv->req_axi_vote[i].num_paths, + CAM_CPAS_MAX_PATHS_PER_CLIENT); + return -EINVAL; + } + + memcpy(&agg_vote.axi_path[num_paths], + &top_priv->req_axi_vote[i].axi_path[0], + top_priv->req_axi_vote[i].num_paths * + sizeof( + struct cam_axi_per_path_bw_vote)); + num_paths += top_priv->req_axi_vote[i].num_paths; + } + } + + agg_vote.num_paths = num_paths; + + for (i = 0; i < agg_vote.num_paths; i++) { + CAM_DBG(CAM_PERF, + "sfe[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + top_priv->last_counter, + cam_cpas_axi_util_path_type_to_string( + agg_vote.axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + agg_vote.axi_path[i].transac_type), + agg_vote.axi_path[i].camnoc_bw, + agg_vote.axi_path[i].mnoc_ab_bw, + agg_vote.axi_path[i].mnoc_ib_bw); + + total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; + } + + memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, + sizeof(struct cam_axi_vote)); + top_priv->last_counter = (top_priv->last_counter + 1) % + CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; + + if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + bw_unchanged = false; + + CAM_DBG(CAM_PERF, + "applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", + top_priv->total_bw_applied, + total_bw_new_vote, bw_unchanged, start_stop); + + if (bw_unchanged) { + CAM_DBG(CAM_PERF, "BW config unchanged"); + return 0; + } + + if (start_stop) { + /* need to vote current request immediately */ + to_be_applied_axi_vote = &agg_vote; + /* Reset everything, we can start afresh */ + memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * + CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES); + top_priv->last_counter = 0; + top_priv->last_vote[top_priv->last_counter] = agg_vote; + top_priv->last_counter = (top_priv->last_counter + 1) % + CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; + } else { + /* + * Find max bw request in last few frames. This will the bw + * that we want to vote to CPAS now. + */ + to_be_applied_axi_vote = + cam_sfe_top_delay_bw_reduction(top_priv, + &total_bw_new_vote); + if (!to_be_applied_axi_vote) { + CAM_ERR(CAM_PERF, "to_be_applied_axi_vote is NULL"); + return -EINVAL; + } + } + + for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { + CAM_DBG(CAM_PERF, + "sfe[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", + top_priv->common_data.hw_intf->hw_idx, + cam_cpas_axi_util_path_type_to_string( + to_be_applied_axi_vote->axi_path[i].path_data_type), + cam_cpas_axi_util_trans_type_to_string( + to_be_applied_axi_vote->axi_path[i].transac_type), + to_be_applied_axi_vote->axi_path[i].camnoc_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, + to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); + } + + if ((to_be_applied_axi_vote->num_paths != + top_priv->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_priv->total_bw_applied)) + apply_bw_update = true; + + CAM_DBG(CAM_PERF, + "sfe[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", + top_priv->common_data.hw_intf->hw_idx, + top_priv->total_bw_applied, total_bw_new_vote, apply_bw_update, + start_stop); + + if (apply_bw_update) { + rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, + to_be_applied_axi_vote); + if (!rc) { + memcpy(&top_priv->applied_axi_vote, + to_be_applied_axi_vote, + sizeof(struct cam_axi_vote)); + top_priv->total_bw_applied = total_bw_new_vote; + } else { + CAM_ERR(CAM_PERF, "BW request failed, rc=%d", rc); + } + } + + return rc; +} + +int cam_sfe_top_bw_update(struct cam_sfe_soc_private *soc_private, + struct cam_sfe_top_priv *top_priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bw_update_args *bw_update = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_update = (struct cam_sfe_bw_update_args *)cmd_args; + res = bw_update->node_res; + + if (!res || !res->hw_intf || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || + res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { + CAM_ERR(CAM_SFE, "SFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < top_priv->num_in_ports; i++) { + if (top_priv->in_rsrc[i].res_id == res->res_id) { + memcpy(&top_priv->req_axi_vote[i], + &bw_update->sfe_vote, + sizeof(struct cam_axi_vote)); + top_priv->axi_vote_control[i] = + CAM_SFE_BW_CONTROL_INCLUDE; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_SFE, + "SFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_sfe_top_set_axi_bw_vote(soc_private, top_priv, + false); + } + + return rc; +} + +int cam_sfe_top_bw_control(struct cam_sfe_soc_private *soc_private, + struct cam_sfe_top_priv *top_priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_sfe_bw_control_args *bw_ctrl = NULL; + struct cam_isp_resource_node *res = NULL; + struct cam_hw_info *hw_info = NULL; + int rc = 0; + int i; + + bw_ctrl = (struct cam_sfe_bw_control_args *)cmd_args; + res = bw_ctrl->node_res; + + if (!res || !res->hw_intf->hw_priv) + return -EINVAL; + + hw_info = res->hw_intf->hw_priv; + + if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || + res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { + CAM_ERR(CAM_SFE, "SFE:%d Invalid res_type:%d res id%d", + res->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + for (i = 0; i < top_priv->num_in_ports; i++) { + if (top_priv->in_rsrc[i].res_id == res->res_id) { + top_priv->axi_vote_control[i] = bw_ctrl->action; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_SFE, + "SFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_sfe_top_set_axi_bw_vote(soc_private, top_priv, true); + } + + return rc; +} + static int cam_sfe_top_core_cfg( struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -292,6 +568,8 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, { int rc = 0; struct cam_sfe_top_priv *top_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_sfe_soc_private *soc_private = NULL; if (!priv) { CAM_ERR(CAM_SFE, "Invalid top_priv"); @@ -299,6 +577,13 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, } top_priv = (struct cam_sfe_top_priv *) priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + + if (!soc_private) { + CAM_ERR(CAM_SFE, "soc private is NULL"); + return -EINVAL; + } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: @@ -310,6 +595,8 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: + rc = cam_sfe_top_bw_update(soc_private, top_priv, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: break; From 84d283314034dc088ace3b6826f3a50a5e2441cb Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Tue, 6 Oct 2020 15:44:56 +0530 Subject: [PATCH 542/790] msm: camera: csiphy: Enable dynamic clock selection for CSIPHY 1.2.4 - Make CSIPHY 1.2.4 clock selection logic dynamic in order to utilize the LOWSVS corner. - Fix is_divisor_32_comp values for all PHY versions. CRs-Fixed: 2792275 Change-Id: I66a12fe6f0e01d1a649559b9ebffff5a7c9308d5 Signed-off-by: Shravan Nevatia --- .../cam_sensor_module/cam_csiphy/cam_csiphy_soc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 0d73d3925795..68770d526c31 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -15,9 +15,13 @@ #include "include/cam_csiphy_2_0_hwreg.h" #include "include/cam_csiphy_2_1_0_hwreg.h" +/* Clock divide factor for CPHY spec v1.0 */ #define CSIPHY_DIVISOR_16 16 +/* Clock divide factor for CPHY spec v1.2 and up */ #define CSIPHY_DIVISOR_32 32 +/* Clock divide factor for DPHY */ #define CSIPHY_DIVISOR_8 8 + #define BYTES_PER_REGISTER 4 #define NUM_REGISTER_PER_LINE 4 #define REG_OFFSET(__start, __i) ((__start) + ((__i) * BYTES_PER_REGISTER)) @@ -399,7 +403,7 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_3; csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; - csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->is_divisor_32_comp = true; csiphy_dev->hw_version = CSIPHY_VERSION_V123; csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = @@ -416,10 +420,10 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_common_reg_1_2_3; csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_2_3; - csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic; csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2_3; csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; - csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->is_divisor_32_comp = true; csiphy_dev->hw_version = CSIPHY_VERSION_V124; csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = @@ -492,7 +496,7 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default; csiphy_dev->hw_version = CSIPHY_VERSION_V210; csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; - csiphy_dev->is_divisor_32_comp = false; + csiphy_dev->is_divisor_32_comp = true; csiphy_dev->clk_lane = 0; csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_2_1_0; From 6980d712c2afccb60f9873e3c3e6a32ac544dfd2 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Oct 2020 19:20:19 +0530 Subject: [PATCH 543/790] msm: camera: cpas: Add qosgen shaping config Add qosgen shaping configuration setup. These parameters will be tuned for every chipset along with other QoS settings. CRs-Fixed: 2787956 Change-Id: I2659192bd23f7f558554e18768e96020b929a145 Signed-off-by: Chandan Kumar Jha --- drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 212 +++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index a8bd3112f226..02dcfc1468a3 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -240,6 +240,27 @@ static struct cam_camnoc_specific .ubwc_ctl = { .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x408, /* CDM_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x420, /* CDM_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x424, /* CDM_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_LINEAR, @@ -285,6 +306,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE08, /* IFE_LINEAR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE20, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE24, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_RD, @@ -330,6 +372,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF08, /* IFE_RDI_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF20, /* IFE_RDI_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xF24, /* IFE_RDI_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_RDI_WR, @@ -375,6 +438,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1808, /* IFE_RDI_WR_0_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1820, /* IFE_RDI_WR_0_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1824, /* IFE_RDI_WR_0_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IFE_UBWC_STATS, @@ -425,6 +509,29 @@ static struct cam_camnoc_specific .offset = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1908, /* IFE_UBWC_STATS_0_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1920, + /* IFE_UBWC_STATS_0_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1924, + /* IFE_UBWC_STATS_0_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_IPE0_RD, @@ -476,6 +583,27 @@ static struct cam_camnoc_specific .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2208, /* IPE0_RD_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ + .value = 0x13131313, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x13131313, + }, }, { .port_type = CAM_CAMNOC_IPE1_BPS_RD, @@ -527,6 +655,27 @@ static struct cam_camnoc_specific .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ + .value = 0x24242424, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x24242424, + }, }, { .port_type = CAM_CAMNOC_IPE_BPS_WR, @@ -578,6 +727,27 @@ static struct cam_camnoc_specific .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C08, /* IPE_BPS_WR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C20, /* IPE_BPS_WR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2C24, /* IPE_BPS_WR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, { .port_type = CAM_CAMNOC_JPEG, @@ -620,6 +790,27 @@ static struct cam_camnoc_specific .ubwc_ctl = { .enable = false, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ + .value = 0x05050505, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ + .value = 0x05050505, + }, }, { .port_type = CAM_CAMNOC_ICP, @@ -631,6 +822,27 @@ static struct cam_camnoc_specific .offset = 0x3888, .value = 0x100000, }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3488, /* ICP_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34A0, /* ICP_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34A4, /* ICP_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, }, }; From 71d305df0bf24a6c95fb79636cb18ec74679adff Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Fri, 11 Sep 2020 11:22:14 -0700 Subject: [PATCH 544/790] msm: camera: cpas: Add cpas support for camera v680 platform Add register info, initial QoS settings info to program camera static settings for chipsets having camera v680. CRs-fixed: 2792910 Change-Id: I8f054a8466035b8388ea84f3a50f562838611990 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Jigar Agrawal --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 17 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 120 +- drivers/cam_cpas/cpas_top/cpastop_v680_100.h | 1213 ++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 18 + 4 files changed, 1330 insertions(+), 38 deletions(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v680_100.h diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index b0e07e0adb0e..ed1a951fa549 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -29,6 +29,7 @@ #include "cpastop_v520_100.h" #include "cpastop_v545_100.h" #include "cpastop_v570_200.h" +#include "cpastop_v680_100.h" struct cam_camnoc_info *camnoc_info; @@ -175,6 +176,10 @@ static int cam_cpas_translate_camera_cpas_version_id( *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_570; break; + case CAM_CPAS_CAMERA_VERSION_680: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_680; + break; + default: CAM_ERR(CAM_CPAS, "Invalid cam version %u", cam_version); @@ -810,6 +815,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_570_V200: camnoc_info = &cam570_cpas200_camnoc_info; break; + case CAM_CPAS_TITAN_680_V100: + camnoc_info = &cam680_cpas100_camnoc_info; + break; default: CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", hw_caps->camera_version.major, @@ -853,6 +861,15 @@ static int cam_cpastop_setup_qos_settings(struct cam_hw_info *cpas_hw, "Invalid selection mask 0x%x for hw 0x%x", selection_mask, soc_info->hw_version); break; + case CAM_CPAS_TITAN_680_V100: + if ((selection_mask & CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK) || + (selection_mask & CAM_CPAS_QOS_DEFAULT_SETTINGS_MASK)) + camnoc_info = &cam680_cpas100_camnoc_info; + else + CAM_ERR(CAM_CPAS, + "Invalid selection mask 0x%x for hw 0x%x", + selection_mask, soc_info->hw_version); + break; default: CAM_WARN(CAM_CPAS, "QoS selection not supported for 0x%x", soc_info->hw_version); diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index c3ec408c5fb6..dd1e1f5273e1 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -12,49 +12,65 @@ /** * enum cam_camnoc_hw_irq_type - Enum for camnoc error types * - * @CAM_CAMNOC_HW_IRQ_SLAVE_ERROR: Each slave port in CAMNOC (3 QSB ports and - * 1 QHB port) has an error logger. The error - * observed at any slave port is logged into - * the error logger register and an IRQ is - * triggered - * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR: Triggered if any error - * detected in the IFE UBWC- - * Stats encoder instance + * @CAM_CAMNOC_HW_IRQ_SLAVE_ERROR : Each slave port in CAMNOC + * (3 QSB ports and 1 QHB port) + * has an error logger. The + * error observed at any slave + * port is logged into the + * error logger register and + * an IRQ is triggered + * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IFE UBWC + * encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR : Triggered if any error + * detected in the IFE UBWC- + * Stats encoder instance * @CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR: Triggered if any error - * detected in the IFE UBWC- - * Stats 1 encoder instance - * @CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error - * detected in the IFE0 UBWC - * encoder instance - * @CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR : Triggered if any error - * detected in the IFE1 or IFE3 - * UBWC encoder instance - * @CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR: Triggered if any error - * detected in the IPE1/BPS read - * path decoder instance - * @CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR : Triggered if any error detected - * in the IPE0 read path decoder - * instance - * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR: Triggered if any error - * detected in the IPE/BPS - * UBWC decoder instance - * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR: Triggered if any error - * detected in the IPE/BPS UBWC - * encoder instance - * @CAM_CAMNOC_HW_IRQ_IFE0_UBWC_ENCODE_ERROR: Triggered if any UBWC error - * is detected in IFE0 write path - * @CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR: Triggered if any UBWC error - * is detected in IFE1 write path - * @CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT : Triggered when the QHS_ICP - * slave times out after 4000 - * AHB cycles - * @CAM_CAMNOC_HW_IRQ_RESERVED1 : Reserved - * @CAM_CAMNOC_HW_IRQ_RESERVED2 : Reserved - * @CAM_CAMNOC_HW_IRQ_CAMNOC_TEST : To test the IRQ logic + * detected in the IFE UBWC- + * Stats 1 encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IFE0 UBWC + * encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IFE1 or + * IFE3 UBWC encoder instance + * @CAM_CAMNOC_HW_IRQ_IFE0_UBWC_ENCODE_ERROR : Triggered if any UBWC error + * is detected in IFE0 write + * path + * @CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR : Triggered if any UBWC error + * is detected in IFE1 write + * path slave times out after + * 4000 AHB cycles + * @CAM_CAMNOC_HW_IRQ_IPE_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IPE + * UBWC encoder instance + * @CAM_CAMNOC_HW_IRQ_BPS_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the BPS + * UBWC encoder instance + * @CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR : Triggered if any error + * detected in the IPE1/BPS + * read path decoder instance + * @CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR : Triggered if any error + * detected in the IPE0 read + * path decoder instance + * @CAM_CAMNOC_HW_IRQ_IPE1_UBWC_DECODE_ERROR : Triggered if any error + * detected in the IPE1 read + * path decoder instance + * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR : Triggered if any error + * detected in the IPE/BPS + * UBWC decoder instance + * @CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR : Triggered if any error + * detected in the IPE/BPS + * UBWC encoder instance + * @CAM_CAMNOC_HW_IRQ_RESERVED1 : Reserved + * @CAM_CAMNOC_HW_IRQ_RESERVED2 : Reserved + * @CAM_CAMNOC_HW_IRQ_CAMNOC_TEST : To test the IRQ logic */ enum cam_camnoc_hw_irq_type { CAM_CAMNOC_HW_IRQ_SLAVE_ERROR = CAM_CAMNOC_IRQ_SLAVE_ERROR, + CAM_CAMNOC_HW_IRQ_IFE_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IFE_UBWC_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_ENCODE_ERROR = CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR = @@ -67,10 +83,16 @@ enum cam_camnoc_hw_irq_type { CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR = CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_IPE_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_IPE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_HW_IRQ_BPS_UBWC_ENCODE_ERROR = + CAM_CAMNOC_IRQ_BPS_UBWC_ENCODE_ERROR, CAM_CAMNOC_HW_IRQ_IPE1_BPS_UBWC_DECODE_ERROR = CAM_CAMNOC_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR = CAM_CAMNOC_IRQ_IPE0_UBWC_DECODE_ERROR, + CAM_CAMNOC_HW_IRQ_IPE1_UBWC_DECODE_ERROR = + CAM_CAMNOC_IRQ_IPE1_UBWC_DECODE_ERROR, CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR = CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR, CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR = @@ -88,9 +110,17 @@ enum cam_camnoc_hw_irq_type { * each of these ports. * * @CAM_CAMNOC_CDM: Indicates CDM HW connection to camnoc + * @CAM_CAMNOC_SFE_RD: Indicates read data from all SFEs to cammnoc * @CAM_CAMNOC_IFE02: Indicates IFE0, IFE2 HW connection to camnoc * @CAM_CAMNOC_IFE13: Indicates IFE1, IFE3 HW connection to camnoc + * @CAM_CAMNOC_IFE_LITE: Indicates all IFE lites connection to camnoc * @CAM_CAMNOC_IFE_LINEAR: Indicates linear data from all IFEs to cammnoc + * @CAM_CAMNOC_IFE_LINEAR_STATS: Indicates linear and stats data from certan + * IFEs to cammnoc + * @CAM_CAMNOC_IFE_LINEAR_STATS_1: Indicates linear and stats data from certan + * IFEs to cammnoc + * @CAM_CAMNOC_IFE_PDAF: Indicates pdaf data from all IFEs to cammnoc + * @CAM_CAMNOC_IFE_UBWC: Indicates ubwc from all IFEs to cammnoc * @CAM_CAMNOC_IFE_UBWC_STATS: Indicates ubwc+stats from certain IFEs to cammnoc * @CAM_CAMNOC_IFE_UBWC_STATS_1: Indicates ubwc+stats from certain * IFEs to cammnoc @@ -108,10 +138,14 @@ enum cam_camnoc_hw_irq_type { * connection to camnoc * @CAM_CAMNOC_IPE_VID_DISP_WRITE: Indicates IPE's VID/DISP Wrire HW * connection to camnoc + * @CAM_CAMNOC_IPE_WR: Indicates IPE HW's write connection to camnoc * @CAM_CAMNOC_IPE0_RD: Indicates IPE's Read0 HW connection to camnoc + * @CAM_CAMNOC_IPE1_RD: Indicates IPE's Read1 HW connection to camnoc * @CAM_CAMNOC_IPE1_BPS_RD: Indicates IPE's Read1 + BPS Read HW connection * to camnoc * @CAM_CAMNOC_IPE_BPS_WR: Indicates IPE+BPS Write HW connection to camnoc + * @CAM_CAMNOC_BPS_WR: Indicates BPS HW's write connection to camnoc + * @CAM_CAMNOC_BPS_RD: Indicates BPS HW's read connection to camnoc * @CAM_CAMNOC_JPEG: Indicates JPEG HW connection to camnoc * @CAM_CAMNOC_FD: Indicates FD HW connection to camnoc * @CAM_CAMNOC_ICP: Indicates ICP HW connection to camnoc @@ -122,9 +156,15 @@ enum cam_camnoc_hw_irq_type { */ enum cam_camnoc_port_type { CAM_CAMNOC_CDM, + CAM_CAMNOC_SFE_RD, CAM_CAMNOC_IFE02, CAM_CAMNOC_IFE13, + CAM_CAMNOC_IFE_LITE, CAM_CAMNOC_IFE_LINEAR, + CAM_CAMNOC_IFE_LINEAR_STATS, + CAM_CAMNOC_IFE_LINEAR_STATS_1, + CAM_CAMNOC_IFE_PDAF, + CAM_CAMNOC_IFE_UBWC, CAM_CAMNOC_IFE_UBWC_STATS, CAM_CAMNOC_IFE_UBWC_STATS_1, CAM_CAMNOC_IFE_RDI_WR, @@ -137,9 +177,13 @@ enum cam_camnoc_port_type { CAM_CAMNOC_IPE_BPS_LRME_READ, CAM_CAMNOC_IPE_BPS_LRME_WRITE, CAM_CAMNOC_IPE_VID_DISP_WRITE, + CAM_CAMNOC_IPE_WR, CAM_CAMNOC_IPE0_RD, + CAM_CAMNOC_IPE1_RD, CAM_CAMNOC_IPE1_BPS_RD, CAM_CAMNOC_IPE_BPS_WR, + CAM_CAMNOC_BPS_WR, + CAM_CAMNOC_BPS_RD, CAM_CAMNOC_JPEG, CAM_CAMNOC_FD, CAM_CAMNOC_ICP, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v680_100.h b/drivers/cam_cpas/cpas_top/cpastop_v680_100.h new file mode 100644 index 000000000000..fd1b1e8e569b --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v680_100.h @@ -0,0 +1,1213 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V680_100_H_ +#define _CPASTOP_V680_100_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v680_100_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2240, /* CAM_NOC_SBM_FAULTINEN0_LOW */ + .value = 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x04 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x08 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */ + (TEST_IRQ_ENABLE ? + 0x80 : /* SBM_FAULTINEN0_LOW_PORT7_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2248, /* CAM_NOC_SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2280, /* CAM_NOC_SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x5 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v680_100_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = false, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2008, /* CAM_NOC_ERL_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2010, /* CAM_NOC_ERL_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2018, /* CAM_NOC_ERL_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x59A0, /* IFE_UBWC_NIU_ENCERREN_LOW */ + .value = 0xF, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x5990, /* IFE_UBWC_NIU_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x5998, /* IFE_UBWC_NIU_ENCERRCLR_LOW */ + .value = 0X1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_BPS_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 = 0x7A0, /* CAM_NOC_BPS_WR_NIU_ENCERREN_LOW */ + .value = 0XF, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x790, /* CAM_NOC_BPS_WR_NIU_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x798, /* CAM_NOC_BPS_WR_NIU_ENCERRCLR_LOW */ + .value = 0X1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE0_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x5F20, /* CAM_NOC_IPE_0_RD_NIU_DECERREN_LOW */ + .value = 0xFF, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x5F10, /* CAM_NOC_IPE_0_RD_NIU_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x5F18, /* CAM_NOC_IPE_0_RD_NIU_DECERRCLR_LOW */ + .value = 0X1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE1_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 = 0x6520, /* CAM_NOC_IPE_1_RD_NIU_DECERREN_LOW */ + .value = 0XFF, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x6510, /* CAM_NOC_IPE_1_RD_NIU_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x6518, /* CAM_NOC_IPE_1_RD_NIU_DECERRCLR_LOW */ + .value = 0X1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE_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 = 0x6BA0, /* CAM_NOC_IPE_WR_NIU_ENCERREN_LOW */ + .value = 0XF, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x6B90, /* CAM_NOC_IPE_WR_NIU_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x6B98, /* CAM_NOC_IPE_WR_NIU_ENCERRCLR_LOW */ + .value = 0x1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = false, + .sbm_port = 0x40, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2288, /* CAM_NOC_SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2290, /* CAM_NOC_SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, /* CAM_NOC_SBM_FLAGOUTCLR0_LOW */ + }, + }, + { + .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 = 0x80, /* SBM_FAULTINSTATUS0_LOW_PORT7_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2288, /* CAM_NOC_SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2290, /* CAM_NOC_SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, /* CAM_NOC_SBM_FLAGOUTCLR0_LOW */ + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v680_100_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_IFE_UBWC, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5830, /* IFE_UBWC_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5834, /* IFE_UBWC_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5838, /* IFE_UBWC_URGENCY_LOW */ + .value = 0x1B30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5840, /* IFE_UBWC_DANGERLUT_LOW */ + .value = 0xffffff00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5848, /* IFE_UBWC_SAFELUT_LOW */ + .value = 0x000f, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5A08, /* IFE_UBWC_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5A20, /* IFE_UBWC_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5A24, /* IFE_UBWC_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_RDI_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5230, /* IFE_RDI_WR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5234, /* IFE_RDI_WR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5238, /* IFE_RDI_WR_URGENCY_LOW */ + .value = 0x1B30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5240, /* IFE_RDI_WR_DANGERLUT_LOW */ + .value = 0xffffff00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5248, /* IFE_RDI_WR_SAFELUT_LOW */ + .value = 0x000f, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5408, /* IFE_RDI_WR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5420, /* IFE_RDI_WR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5424, /* IFE_RDI_WR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_PDAF, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4c30, /* IFE_PDAF_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4c34, /* IFE_PDAF_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4c38, /* IFE_PDAF_URGENCY_LOW */ + .value = 0x1B30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4c40, /* IFE_PDAF_DANGERLUT_LOW */ + .value = 0xffffff00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4c48, /* IFE_PDAF_SAFELUT_LOW */ + .value = 0x000f, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4e08, /* IFE_PDAF_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4e20, /* IFE_PDAF_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4e24, /* IFE_PDAF_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR_STATS, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4030, /* IFE_LINEAR_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4034, /* IFE_LINEAR_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4038, /* IFE_LINEAR_URGENCY_LOW */ + .value = 0x1B30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4040, /* IFE_LINEAR_DANGERLUT_LOW */ + .value = 0xffffff00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4048, /* IFE_LINEAR_SAFELUT_LOW */ + .value = 0x000f, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4208, /* IFE_LINEAR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4220, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4224, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LINEAR_STATS_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8230, /* IFE_LINEAR_1_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8234, /* IFE_LINEAR_1_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8238, /* IFE_LINEAR_1_URGENCY_LOW */ + .value = 0x1B30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8240, /* IFE_LINEAR_1_DANGERLUT_LOW */ + .value = 0xffffff00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8248, /* IFE_LINEAR_1_SAFELUT_LOW */ + .value = 0x000f, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8408, /* IFE_LINEAR_1_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8420, /* IFE_LINEAR_1_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x8424, /* IFE_LINEAR_1_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IFE_LITE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4630, /* IFE_LITE_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4634, /* IFE_LITE_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4638, /* IFE_LITE_URGENCY_LOW */ + .value = 0x1B30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4640, /* IFE_LITE_DANGERLUT_LOW */ + .value = 0xffffff00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4648, /* IFE_LITE_SAFELUT_LOW */ + .value = 0x000f, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4808, /* IFE_LITE_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4820, /* IFE_LITE_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4824, /* IFE_LITE_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_SFE_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7030, /* SFE_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7034, /* SFE_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7038, /* SFE_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7040, /* SFE_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7048, /* SFE_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, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7208, /* SFE_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7220, /* SFE_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7224, /* SFE_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6a30, /* IPE_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6a34, /* IPE_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6a38, /* IPE_WR_URGENCY_LOW */ + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6a40, /* IPE_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6a48, /* IPE_WR_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6c08, /* IPE_WR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6c20, /* IPE_WR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6c24, /* IPE_WR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_BPS_WR, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x630, /* BPS_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x634, /* BPS_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x638, /* BPS_WR_URGENCY_LOW */ + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x640, /* BPS_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x648, /* BPS_WR_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x808, /* BPS_WR_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x820, /* BPS_WR_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x824, /* BPS_WR_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_BPS_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* BPS_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* BPS_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* BPS_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* BPS_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* BPS_RD_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x208, /* BPS_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x220, /* BPS_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x224, /* BPS_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_JPEG, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7c30, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7c34, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7c38, /* JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7c40, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7c48, /* JPEG_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7e08, /* JPEG_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7e20, /* JPEG_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7e24, /* JPEG_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IPE0_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5E30, /* IPE0_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5E34, /* IPE0_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5E38, /* IPE0_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5E40, /* IPE0_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5E48, /* IPE0_RD_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5F08, /* IPE0_RD_DECCTL_LOW */ + .value = 1, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6008, /* IPE0_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6020, /* IPE0_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6024, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_IPE1_RD, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6430, /* IPE1_RD_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6434, /* IPE1_RD_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6438, /* IPE1_RD_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6440, /* IPE1_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6448, /* IPE1_RD_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6608, /* IPE1_RD_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6620, /* IPE1_RD_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x6624, /* IPE1_RD_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3830, /* CDM_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3834, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3838, /* CDM_URGENCY_LOW */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3840, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3848, /* CDM_SAFELUT_LOW */ + .value = 0xffff, + }, + .ubwc_ctl = { + .enable = false, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3a08, /* CDM_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3a20, /* CDM_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3a24, /* CDM_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, + { + .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, + }, + .qosgen_mainctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x7688, /* ICP_QOSGEN_MAINCTL */ + .value = 0x0, + }, + .qosgen_shaping_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x76A0, /* ICP_QOSGEN_SHAPING_LOW */ + .value = 0x0, + }, + .qosgen_shaping_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x76A4, /* ICP_QOSGEN_SHAPING_HIGH */ + .value = 0x0, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam680_cpas100_err_logger_offsets = { + .mainctrl = 0x2008, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x2010, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x2020, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x2024, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x2028, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x202c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x2030, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x2034, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x2038, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x203c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam680_cpas100_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x2300, /* sbm_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam680_cpas100_camnoc_info = { + .specific = &cam_cpas_v680_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v680_100_camnoc_specific), + .irq_sbm = &cam_cpas_v680_100_irq_sbm, + .irq_err = &cam_cpas_v680_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v680_100_irq_err), + .err_logger = &cam680_cpas100_err_logger_offsets, + .errata_wa_list = &cam680_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP_V680_100_H_ */ + diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 2380c5527a3e..5d288f54f6df 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -67,6 +67,7 @@ enum cam_cpas_camera_version { CAM_CPAS_CAMERA_VERSION_580 = 0x00050800, CAM_CPAS_CAMERA_VERSION_545 = 0x00050405, CAM_CPAS_CAMERA_VERSION_570 = 0x00050700, + CAM_CPAS_CAMERA_VERSION_680 = 0x00060800, CAM_CPAS_CAMERA_VERSION_MAX }; @@ -98,6 +99,7 @@ enum cam_cpas_camera_version_map_id { CAM_CPAS_CAMERA_VERSION_ID_540 = 0x6, CAM_CPAS_CAMERA_VERSION_ID_545 = 0x7, CAM_CPAS_CAMERA_VERSION_ID_570 = 0x8, + CAM_CPAS_CAMERA_VERSION_ID_680 = 0x9, CAM_CPAS_CAMERA_VERSION_ID_MAX }; @@ -135,6 +137,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_520_V100 = 0x520100, CAM_CPAS_TITAN_545_V100 = 0x545100, CAM_CPAS_TITAN_570_V200 = 0x570200, + CAM_CPAS_TITAN_680_V100 = 0x680100, CAM_CPAS_TITAN_MAX }; @@ -146,6 +149,8 @@ enum cam_cpas_hw_version { * observed at any slave port is logged into * the error logger register and an IRQ is * triggered + * @CAM_CAMNOC_IRQ_IFE_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the IFE UBWC encoder instance * @CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR: Triggered if any error detected * in the IFE UBWC-Stats encoder * instance @@ -159,12 +164,21 @@ enum cam_cpas_hw_version { * @CAM_CAMNOC_IRQ_IFE1_WR_UBWC_ENCODE_ERROR : Triggered if any error detected * in the IFE1 UBWC encoder * instance + * @CAM_CAMNOC_IRQ_IPE_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the IPE write path encoder + * instance + * @CAM_CAMNOC_IRQ_BPS_UBWC_ENCODE_ERROR : Triggered if any error detected + * in the BPS write path encoder + * instance * @CAM_CAMNOC_IRQ_IPE1_BPS_UBWC_DECODE_ERROR: Triggered if any error detected * in the IPE1/BPS read path decoder * instance * @CAM_CAMNOC_IRQ_IPE0_UBWC_DECODE_ERROR : Triggered if any error detected * in the IPE0 read path decoder * instance + * @CAM_CAMNOC_IRQ_IPE1_UBWC_DECODE_ERROR : Triggered if any error detected + * in the IPE1 read path decoder + * instance * @CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR: Triggered if any error detected * in the IPE/BPS UBWC decoder * instance @@ -176,14 +190,18 @@ enum cam_cpas_hw_version { */ enum cam_camnoc_irq_type { CAM_CAMNOC_IRQ_SLAVE_ERROR, + CAM_CAMNOC_IRQ_IFE_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE_UBWC_STATS_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE_UBWC_STATS_1_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_IPE_UBWC_ENCODE_ERROR, + CAM_CAMNOC_IRQ_BPS_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_IPE1_BPS_UBWC_DECODE_ERROR, CAM_CAMNOC_IRQ_IPE0_UBWC_DECODE_ERROR, + CAM_CAMNOC_IRQ_IPE1_UBWC_DECODE_ERROR, CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR, CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR, CAM_CAMNOC_IRQ_AHB_TIMEOUT, From ab2e87cde116670fbdccc3c311ffca37697d9686 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 21 Sep 2020 19:09:33 +0530 Subject: [PATCH 545/790] msm: camera: ife: Adjust epoch configuration In case if calculated epoch is more than last active line, then there is a chance that calculated epoch is closer to EOF. This results in missing Epoch notification at CRM. Check if calculated epoch is greater than half of last active line, then configure epoch at half the active lines. CRs-Fixed: 2781565 Change-Id: Icb44d2e0e72b4ff36bd500ce51016cce418ff205 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 8 ++++---- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 7 ++++--- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 6 ++++-- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c | 6 +++--- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 60b456e44fd3..b7104c15bf13 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -1972,10 +1972,10 @@ static int cam_tfe_camif_resource_start( /* Epoch config */ epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) - - rsrc_data->first_line) / 2) + - rsrc_data->first_line; - if (epoch0_irq_mask > rsrc_data->last_line) - epoch0_irq_mask = rsrc_data->last_line; + rsrc_data->first_line) / 2); + if (epoch0_irq_mask > (rsrc_data->last_line - rsrc_data->first_line)) + epoch0_irq_mask = (rsrc_data->last_line - + rsrc_data->first_line); epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 14960449e497..4a109ba7802d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -426,10 +426,11 @@ static int cam_vfe_camif_resource_start( default: epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) - - rsrc_data->first_line) / 2) + + rsrc_data->first_line) / 2); + if ((epoch0_irq_mask) > + (rsrc_data->last_line - rsrc_data->first_line)) + epoch0_irq_mask = rsrc_data->last_line - rsrc_data->first_line; - if (epoch0_irq_mask > rsrc_data->last_line) - epoch0_irq_mask = rsrc_data->last_line; epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 73b0114ba57f..49e76452c165 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -471,8 +471,10 @@ static int cam_vfe_camif_ver3_resource_start( epoch0_line_cfg = ((rsrc_data->last_line + rsrc_data->vbi_value) - rsrc_data->first_line) / 4; - if (epoch0_line_cfg > rsrc_data->last_line) - epoch0_line_cfg = rsrc_data->last_line; + if ((epoch0_line_cfg * 2) > + (rsrc_data->last_line - rsrc_data->first_line)) + epoch0_line_cfg = (rsrc_data->last_line - + rsrc_data->first_line)/2; /* epoch line cfg will still be configured at midpoint of the * frame width. We use '/ 4' instead of '/ 2' * cause it is multipixel path diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c index 85868105bb74..ec9e48237f75 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c @@ -307,9 +307,9 @@ static int cam_vfe_fe_resource_start( /* epoch config */ epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) - - rsrc_data->first_line) / 2) + rsrc_data->first_line; - if (epoch0_irq_mask > rsrc_data->last_line) - epoch0_irq_mask = rsrc_data->last_line; + rsrc_data->first_line) / 2); + if (epoch0_irq_mask > (rsrc_data->last_line - rsrc_data->first_line)) + epoch0_irq_mask = rsrc_data->last_line - 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; From 4574450a12b85d0eea0d1535d4e796ef71068c88 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 7 Oct 2020 12:54:08 +0530 Subject: [PATCH 546/790] msm: camera: common: Merge camera-kernel.3.1 changes in camera-kernel.4.0 msm: camera: cdm: Fix dangling pointer issue msm: camera: cdm: change work record to atomic variable msm: camera: utils: Adding device type to track device handles msm: camera: tfe: Reduce stack footprint during bw vote msm: camera: req_mgr: Thread switch delay detection mechanisms msm: camera: cdm: Avoid submitting BL if FIFO is full msm: camera: tfe: check cdm hang in the tfe config timeout msm: camera: req_mgr: Delay detection mechanism msm: camera: cdm: Debug info in case of cdm page fault msm: camera: isp: Max context reduction for TFE in isp driver msm: camera: ope: Maintain current clock value during acquire msm: camera: req_mgr: Limit CAM_ERR log in case of no empty task msm: camera: cdm: Decrement write-count only after Bl commit msm: camera: isp: Added CSID recovery mechanism. CRs-Fixed: 2792394 Change-Id: I1c7a903ae15b572acf3f6318cda7394cb6549c8d Signed-off-by: Tejas Prajapati --- drivers/cam_cdm/cam_cdm.h | 3 +- drivers/cam_cdm/cam_cdm_core_common.c | 5 +- drivers/cam_cdm/cam_cdm_hw_core.c | 320 +++++++++++------- drivers/cam_cdm/cam_cdm_intf_api.h | 37 ++ drivers/cam_cdm/cam_cdm_util.c | 78 ++++- drivers/cam_cdm/cam_cdm_virtual_core.c | 11 +- drivers/cam_core/cam_context_utils.c | 2 +- drivers/cam_core/cam_node.c | 9 +- drivers/cam_cpas/cam_cpas_hw.c | 28 +- drivers/cam_cpas/cam_cpas_soc.c | 1 - drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 5 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 2 + drivers/cam_isp/cam_isp_context.c | 17 +- drivers/cam_isp/cam_isp_dev.c | 60 +++- drivers/cam_isp/cam_isp_dev.h | 10 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 8 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 4 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 316 ++++++++++++++--- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 13 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 8 + .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 1 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 215 ++++++++++++ .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 26 ++ drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 8 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 22 +- drivers/cam_req_mgr/cam_req_mgr_debug.c | 11 +- drivers/cam_req_mgr/cam_req_mgr_debug.h | 6 +- drivers/cam_req_mgr/cam_req_mgr_dev.c | 3 +- drivers/cam_req_mgr/cam_req_mgr_util.c | 29 +- drivers/cam_req_mgr/cam_req_mgr_util.h | 6 +- drivers/cam_req_mgr/cam_req_mgr_workq.c | 24 ++ drivers/cam_req_mgr/cam_req_mgr_workq.h | 32 +- .../cam_actuator/cam_actuator_core.c | 1 + .../cam_sensor_module/cam_cci/cam_cci_core.c | 4 + .../cam_sensor_module/cam_cci/cam_cci_dev.h | 2 + .../cam_csiphy/cam_csiphy_core.c | 1 + .../cam_eeprom/cam_eeprom_core.c | 1 + .../cam_flash/cam_flash_dev.c | 1 + .../cam_sensor_module/cam_ois/cam_ois_core.c | 1 + .../cam_sensor/cam_sensor_core.c | 1 + drivers/cam_sync/cam_sync.c | 2 + drivers/cam_sync/cam_sync_private.h | 14 +- drivers/cam_sync/cam_sync_util.c | 3 + drivers/cam_utils/cam_packet_util.c | 3 + drivers/cam_utils/cam_trace.h | 35 ++ include/uapi/camera/media/cam_req_mgr.h | 1 + 46 files changed, 1134 insertions(+), 256 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index fbd3fc5f5c51..08adc052b448 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -440,6 +440,7 @@ struct cam_cdm_work_payload { uint32_t irq_status; uint32_t irq_data; int fifo_idx; + ktime_t workq_scheduled_ts; struct work_struct work; }; @@ -476,7 +477,7 @@ struct cam_cdm_bl_fifo { uint8_t bl_tag; uint32_t bl_depth; uint8_t last_bl_tag_done; - uint32_t work_record; + atomic_t work_record; }; /** diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index e98bbc9fe747..d7ddcee6d9b7 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -206,6 +206,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE || status == CAM_CDM_CB_STATUS_HW_FLUSH || status == CAM_CDM_CB_STATUS_HW_RESUBMIT || + status == CAM_CDM_CB_STATUS_INVALID_BL_CMD || status == CAM_CDM_CB_STATUS_HW_ERROR) { int client_idx; struct cam_cdm_bl_cb_request_entry *node = @@ -800,13 +801,11 @@ int cam_cdm_process_cmd(void *hw_priv, } idx = CAM_CDM_GET_CLIENT_IDX(*handle); - mutex_lock(&cdm_hw->hw_mutex); client = core->clients[idx]; if (!client) { CAM_ERR(CAM_CDM, "Client not present for handle %d", *handle); - mutex_unlock(&cdm_hw->hw_mutex); break; } @@ -814,12 +813,10 @@ int cam_cdm_process_cmd(void *hw_priv, CAM_ERR(CAM_CDM, "handle mismatch, client handle %d index %d received handle %d", client->handle, idx, *handle); - mutex_unlock(&cdm_hw->hw_mutex); break; } rc = cam_hw_cdm_hang_detect(cdm_hw, *handle); - mutex_unlock(&cdm_hw->hw_mutex); break; } case CAM_CDM_HW_INTF_DUMP_DBG_REGS: diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 6b58cf08c695..2539bcd51a75 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -25,6 +25,7 @@ #include "cam_cdm_hw_reg_2_1.h" #include "camera_main.h" #include "cam_trace.h" +#include "cam_req_mgr_workq.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 #define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff @@ -569,7 +570,7 @@ int cam_hw_cdm_wait_for_bl_fifo( CAM_DBG(CAM_CDM, "BL slot available_cnt=%d requested=%d", (available_bl_slots - 1), bl_count); - rc = bl_count; + rc = available_bl_slots - 1; break; } else if (0 == (available_bl_slots - 1)) { rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, @@ -595,7 +596,7 @@ int cam_hw_cdm_wait_for_bl_fifo( if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, false, fifo_idx)) CAM_ERR(CAM_CDM, "Disable BL done irq failed"); - rc = 0; + rc = 1; CAM_DBG(CAM_CDM, "CDM HW is ready for data"); } else { rc = (bl_count - (available_bl_slots - 1)); @@ -702,6 +703,7 @@ int cam_hw_cdm_submit_gen_irq( core->bl_fifo[fifo_idx].bl_tag); list_del_init(&node->entry); kfree(node); + node = NULL; rc = -EIO; goto end; } @@ -712,6 +714,7 @@ int cam_hw_cdm_submit_gen_irq( core->bl_fifo[fifo_idx].bl_tag); list_del_init(&node->entry); kfree(node); + node = NULL; rc = -EIO; } @@ -922,8 +925,6 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, rc = -EIO; break; } - } else { - write_count--; } if (req->data->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE) { @@ -1026,27 +1027,58 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, rc = -EIO; break; } + write_count--; CAM_DBG(CAM_CDM, "commit success BL %d tag=%d", i, core->bl_fifo[fifo_idx].bl_tag); } core->bl_fifo[fifo_idx].bl_tag++; if (cdm_cmd->cmd[i].enable_debug_gen_irq) { + if (write_count == 0) { + write_count = + cam_hw_cdm_wait_for_bl_fifo( + cdm_hw, 1, fifo_idx); + if (write_count < 0) { + CAM_ERR(CAM_CDM, + "wait for bl fifo failed %d:%d", + i, req->data->cmd_arrary_count); + rc = -EIO; + break; + } + } + rc = cam_hw_cdm_submit_debug_gen_irq(cdm_hw, fifo_idx); - if (rc == 0) + if (rc == 0) { + write_count--; core->bl_fifo[fifo_idx].bl_tag++; + } if (core->bl_fifo[fifo_idx].bl_tag >= (bl_fifo->bl_depth - 1)) core->bl_fifo[fifo_idx].bl_tag = 0; } - if ((req->data->flag == true) && + if ((!rc) && (req->data->flag == true) && (i == (req->data->cmd_arrary_count - 1))) { + + if (write_count == 0) { + write_count = + cam_hw_cdm_wait_for_bl_fifo( + cdm_hw, 1, fifo_idx); + if (write_count < 0) { + CAM_ERR(CAM_CDM, + "wait for bl fifo failed %d:%d", + i, req->data->cmd_arrary_count); + rc = -EIO; + break; + } + } + if (core->arbitration != CAM_CDM_ARBITRATION_PRIORITY_BASED) { + rc = cam_hw_cdm_submit_gen_irq( cdm_hw, req, fifo_idx, cdm_cmd->gen_irq_arb); @@ -1080,7 +1112,8 @@ static void cam_hw_cdm_reset_cleanup( struct cam_cdm_bl_cb_request_entry *node, *tnode; bool flush_hw = false; - if (test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) + if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || + test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) flush_hw = true; for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { @@ -1104,10 +1137,11 @@ static void cam_hw_cdm_reset_cleanup( } list_del_init(&node->entry); kfree(node); + node = NULL; } core->bl_fifo[i].bl_tag = 0; core->bl_fifo[i].last_bl_tag_done = -1; - core->bl_fifo[i].work_record = 0; + atomic_set(&core->bl_fifo[i].work_record, 0); } } @@ -1116,121 +1150,165 @@ static void cam_hw_cdm_work(struct work_struct *work) struct cam_cdm_work_payload *payload; struct cam_hw_info *cdm_hw; struct cam_cdm *core; - int i; + int i, fifo_idx; + struct cam_cdm_bl_cb_request_entry *tnode = NULL; + struct cam_cdm_bl_cb_request_entry *node = NULL; payload = container_of(work, struct cam_cdm_work_payload, work); - if (payload) { - cdm_hw = payload->hw; - core = (struct cam_cdm *)cdm_hw->core_info; - if (payload->fifo_idx >= core->offsets->reg_data->num_bl_fifo) { - CAM_ERR(CAM_CDM, "Invalid fifo idx %d", - payload->fifo_idx); + if (!payload) { + CAM_ERR(CAM_CDM, "NULL payload"); + return; + } + + cdm_hw = payload->hw; + core = (struct cam_cdm *)cdm_hw->core_info; + fifo_idx = payload->fifo_idx; + if (fifo_idx >= core->offsets->reg_data->num_bl_fifo) { + CAM_ERR(CAM_CDM, "Invalid fifo idx %d", + fifo_idx); + kfree(payload); + payload = NULL; + return; + } + + cam_req_mgr_thread_switch_delay_detect( + payload->workq_scheduled_ts); + + CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { + CAM_DBG(CAM_CDM, "inline IRQ data=0x%x last tag: 0x%x", + payload->irq_data, + core->bl_fifo[payload->fifo_idx] + .last_bl_tag_done); + + if (payload->irq_data == 0xff) { + CAM_INFO(CAM_CDM, "Debug genirq received"); kfree(payload); + payload = NULL; return; } - CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); - if (payload->irq_status & - CAM_CDM_IRQ_STATUS_INLINE_IRQ_MASK) { - struct cam_cdm_bl_cb_request_entry *node, *tnode; + mutex_lock(&core->bl_fifo[fifo_idx].fifo_lock); - CAM_DBG(CAM_CDM, "inline IRQ data=0x%x last tag: 0x%x", - payload->irq_data, - core->bl_fifo[payload->fifo_idx] - .last_bl_tag_done); + if (atomic_read(&core->bl_fifo[fifo_idx].work_record)) + atomic_dec(&core->bl_fifo[fifo_idx].work_record); - if (payload->irq_data == 0xff) { - CAM_INFO(CAM_CDM, "Debug genirq received"); - kfree(payload); - return; - } + if (list_empty(&core->bl_fifo[fifo_idx] + .bl_request_list)) { + CAM_INFO(CAM_CDM, + "Fifo list empty, idx %d tag %d arb %d", + fifo_idx, payload->irq_data, + core->arbitration); + mutex_unlock(&core->bl_fifo[fifo_idx] + .fifo_lock); + return; + } - mutex_lock(&core->bl_fifo[payload->fifo_idx] - .fifo_lock); - - if (core->bl_fifo[payload->fifo_idx].work_record) - core->bl_fifo[payload->fifo_idx].work_record--; - - if (list_empty(&core->bl_fifo[payload->fifo_idx] - .bl_request_list)) { - CAM_INFO(CAM_CDM, - "Fifo list empty, idx %d tag %d arb %d", - payload->fifo_idx, payload->irq_data, - core->arbitration); - mutex_unlock(&core->bl_fifo[payload->fifo_idx] - .fifo_lock); - return; - } - - if (core->bl_fifo[payload->fifo_idx] - .last_bl_tag_done != - payload->irq_data) { - core->bl_fifo[payload->fifo_idx] - .last_bl_tag_done = - payload->irq_data; - list_for_each_entry_safe(node, tnode, - &core->bl_fifo[payload->fifo_idx] - .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_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; - } + if (core->bl_fifo[fifo_idx].last_bl_tag_done != + payload->irq_data) { + core->bl_fifo[fifo_idx].last_bl_tag_done = + payload->irq_data; + list_for_each_entry_safe(node, tnode, + &core->bl_fifo[fifo_idx].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_ERR(CAM_CDM, + "Invalid node=%pK %d", + node, + node->request_type); } - } else { - CAM_INFO(CAM_CDM, - "Skip GenIRQ, tag 0x%x fifo %d", - payload->irq_data, payload->fifo_idx); + list_del_init(&node->entry); + if (node->bl_tag == payload->irq_data) { + kfree(node); + node = NULL; + break; + } + kfree(node); + node = NULL; } - mutex_unlock(&core->bl_fifo[payload->fifo_idx] - .fifo_lock); + } else { + CAM_INFO(CAM_CDM, + "Skip GenIRQ, tag 0x%x fifo %d", + payload->irq_data, payload->fifo_idx); } + mutex_unlock(&core->bl_fifo[payload->fifo_idx] + .fifo_lock); + } + + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_BL_DONE_MASK) { + if (test_bit(payload->fifo_idx, &core->cdm_status)) { + CAM_DBG(CAM_CDM, "CDM HW BL done IRQ"); + complete(&core->bl_fifo[payload->fifo_idx] + .bl_complete); + } + } + if (payload->irq_status & + CAM_CDM_IRQ_STATUS_ERRORS) { + int reset_hw_hdl = 0x0; + + CAM_ERR_RATE_LIMIT(CAM_CDM, + "CDM Error IRQ status %d\n", + payload->irq_status); + set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); + mutex_lock(&cdm_hw->hw_mutex); + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; + i++) + mutex_lock(&core->bl_fifo[i].fifo_lock); + /* + * First pause CDM, If it fails still proceed + * to dump debug info + */ + cam_hw_cdm_pause_core(cdm_hw, true); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); if (payload->irq_status & - CAM_CDM_IRQ_STATUS_BL_DONE_MASK) { - if (test_bit(payload->fifo_idx, &core->cdm_status)) { - CAM_DBG(CAM_CDM, "CDM HW BL done IRQ"); - complete(&core->bl_fifo[payload->fifo_idx] - .bl_complete); + CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { + node = list_first_entry_or_null( + &core->bl_fifo[payload->fifo_idx].bl_request_list, + struct cam_cdm_bl_cb_request_entry, entry); + + if (node != NULL) { + if (node->request_type == + CAM_HW_CDM_BL_CB_CLIENT) { + cam_cdm_notify_clients(cdm_hw, + CAM_CDM_CB_STATUS_INVALID_BL_CMD, + (void *)node); + } else if (node->request_type == + CAM_HW_CDM_BL_CB_INTERNAL) { + CAM_ERR(CAM_CDM, + "Invalid node=%pK %d", node, + node->request_type); + } + list_del_init(&node->entry); + kfree(node); } } + /* Resume CDM back */ + cam_hw_cdm_pause_core(cdm_hw, false); + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; + i++) + mutex_unlock(&core->bl_fifo[i].fifo_lock); + if (payload->irq_status & - CAM_CDM_IRQ_STATUS_ERRORS) { - CAM_ERR_RATE_LIMIT(CAM_CDM, - "CDM Error IRQ status %d\n", - payload->irq_status); - set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); - mutex_lock(&cdm_hw->hw_mutex); - for (i = 0; i < core->offsets->reg_data->num_bl_fifo; - i++) - mutex_lock(&core->bl_fifo[i].fifo_lock); - cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); - for (i = 0; i < core->offsets->reg_data->num_bl_fifo; - i++) - mutex_unlock(&core->bl_fifo[i].fifo_lock); - mutex_unlock(&cdm_hw->hw_mutex); - if (!(payload->irq_status & - CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) - clear_bit(CAM_CDM_ERROR_HW_STATUS, - &core->cdm_status); - } - kfree(payload); - } else { - CAM_ERR(CAM_CDM, "NULL payload"); + CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) + cam_hw_cdm_reset_hw(cdm_hw, reset_hw_hdl); + + mutex_unlock(&cdm_hw->hw_mutex); + if (!(payload->irq_status & + CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) + clear_bit(CAM_CDM_ERROR_HW_STATUS, + &core->cdm_status); } + kfree(payload); + payload = NULL; } @@ -1369,7 +1447,9 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) return IRQ_HANDLED; } - cdm_core->bl_fifo[i].work_record++; + atomic_inc(&cdm_core->bl_fifo[i].work_record); + payload[i]->workq_scheduled_ts = ktime_get(); + work_status = queue_work( cdm_core->bl_fifo[i].work_queue, &payload[i]->work); @@ -1379,6 +1459,7 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) "Failed to queue work for FIFO: %d irq=0x%x", i, payload[i]->irq_status); kfree(payload[i]); + payload[i] = NULL; } } if (rst_done_cnt == cdm_core->offsets->reg_data->num_bl_fifo_irq) { @@ -1629,6 +1710,7 @@ int cam_hw_cdm_handle_error_info( } list_del_init(&node->entry); kfree(node); + node = NULL; } cam_hw_cdm_reset_cleanup(cdm_hw, reset_hw_hdl); @@ -1679,20 +1761,14 @@ int cam_hw_cdm_hang_detect( cdm_core = (struct cam_cdm *)cdm_hw->core_info; for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) - mutex_lock(&cdm_core->bl_fifo[i].fifo_lock); - - for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) - if (cdm_core->bl_fifo[i].work_record) { + if (atomic_read(&cdm_core->bl_fifo[i].work_record)) { CAM_WARN(CAM_CDM, - "workqueue got delayed, bl_fifo: %d, work_record :%u", - i, cdm_core->bl_fifo[i].work_record); + "workqueue got delayed, work_record :%u", + atomic_read(&cdm_core->bl_fifo[i].work_record)); rc = 0; break; } - for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) - mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); - return rc; } @@ -1797,7 +1873,7 @@ int cam_hw_cdm_init(void *hw_priv, } for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { cdm_core->bl_fifo[i].last_bl_tag_done = -1; - cdm_core->bl_fifo[i].work_record = 0; + atomic_set(&cdm_core->bl_fifo[i].work_record, 0); } rc = cam_hw_cdm_reset_hw(cdm_hw, reset_hw_hdl); @@ -1856,6 +1932,7 @@ int cam_hw_cdm_deinit(void *hw_priv, &cdm_core->bl_fifo[i].bl_request_list, entry) { list_del_init(&node->entry); kfree(node); + node = NULL; } } @@ -1931,13 +2008,16 @@ static int cam_hw_cdm_component_bind(struct device *dev, cdm_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); if (!cdm_hw) { kfree(cdm_hw_intf); + cdm_hw_intf = NULL; return -ENOMEM; } cdm_hw->core_info = kzalloc(sizeof(struct cam_cdm), GFP_KERNEL); if (!cdm_hw->core_info) { kfree(cdm_hw); + cdm_hw = NULL; kfree(cdm_hw_intf); + cdm_hw_intf = NULL; return -ENOMEM; } @@ -2174,11 +2254,15 @@ unlock_release_mem: mutex_unlock(&cdm_hw->hw_mutex); release_private_mem: kfree(cdm_hw->soc_info.soc_private); + cdm_hw->soc_info.soc_private = NULL; release_mem: mutex_destroy(&cdm_hw->hw_mutex); kfree(cdm_hw_intf); + cdm_hw_intf = NULL; kfree(cdm_hw->core_info); + cdm_hw->core_info = NULL; kfree(cdm_hw); + cdm_hw = NULL; return rc; } @@ -2256,9 +2340,13 @@ static void cam_hw_cdm_component_unbind(struct device *dev, mutex_destroy(&cdm_hw->hw_mutex); kfree(cdm_hw->soc_info.soc_private); + cdm_hw->soc_info.soc_private = NULL; kfree(cdm_hw_intf); + cdm_hw_intf = NULL; kfree(cdm_hw->core_info); + cdm_hw->core_info = NULL; kfree(cdm_hw); + cdm_hw = NULL; } const static struct component_ops cam_hw_cdm_component_ops = { diff --git a/drivers/cam_cdm/cam_cdm_intf_api.h b/drivers/cam_cdm/cam_cdm_intf_api.h index 2315b0a0ed8e..e34fde74f4fd 100644 --- a/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/cam_cdm/cam_cdm_intf_api.h @@ -10,6 +10,8 @@ #include "cam_cdm_util.h" #include "cam_soc_util.h" +#define CAM_CDM_BL_CMD_MAX 25 + /* enum cam_cdm_id - Enum for possible CAM CDM hardwares */ enum cam_cdm_id { CAM_CDM_VIRTUAL, @@ -151,6 +153,41 @@ struct cam_cdm_bl_request { struct cam_cdm_bl_cmd cmd[1]; }; +/** + * struct cam_cdm_bl_data - last submiited CDM BL data + * + * @mem_handle : Input mem handle of bl cmd + * @hw_addr : Hw address of submitted Bl command + * @offset : Input offset of the actual bl cmd in the memory pointed + * by mem_handle + * @len : length of submitted Bl command to CDM. + * @input_len : Input length of the BL command, Cannot be more than 1MB and + * this is will be validated with offset+size of the memory pointed + * by mem_handle + * @type : CDM bl cmd addr types. + */ +struct cam_cdm_bl_data { + int32_t mem_handle; + dma_addr_t hw_addr; + uint32_t offset; + size_t len; + uint32_t input_len; + enum cam_cdm_bl_cmd_addr_type type; +}; + +/** + * struct cam_cdm_bl_info + * + * @bl_count : No. of Bl commands submiited to CDM. + * @cmd : payload holding the BL cmd's arrary + * that is sumbitted. + * + */ +struct cam_cdm_bl_info { + int32_t bl_count; + struct cam_cdm_bl_data cmd[CAM_CDM_BL_CMD_MAX]; +}; + /** * @brief : API to get the CDM capabilities for a camera device type * diff --git a/drivers/cam_cdm/cam_cdm_util.c b/drivers/cam_cdm/cam_cdm_util.c index 67b584066a08..aba90904eb02 100644 --- a/drivers/cam_cdm/cam_cdm_util.c +++ b/drivers/cam_cdm/cam_cdm_util.c @@ -689,25 +689,53 @@ int cam_cdm_util_cmd_buf_write(void __iomem **current_device_base, return ret; } -static long cam_cdm_util_dump_dmi_cmd(uint32_t *cmd_buf_addr) +static long cam_cdm_util_dump_dmi_cmd(uint32_t *cmd_buf_addr, + uint32_t *cmd_buf_addr_end) { long ret = 0; + struct cdm_dmi_cmd *p_dmi_cmd; + uint32_t *temp_ptr = cmd_buf_addr; + p_dmi_cmd = (struct cdm_dmi_cmd *)cmd_buf_addr; + temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI]; - CAM_INFO(CAM_CDM, "DMI"); + + if (temp_ptr > cmd_buf_addr_end) + CAM_ERR(CAM_CDM, + "Invalid cmd start addr:%pK end addr:%pK", + temp_ptr, cmd_buf_addr_end); + + CAM_INFO(CAM_CDM, + "DMI: LEN: %u DMIAddr: 0x%X DMISel: 0x%X LUT_addr: 0x%X", + p_dmi_cmd->length, p_dmi_cmd->DMIAddr, + p_dmi_cmd->DMISel, p_dmi_cmd->addr); return ret; } -static long cam_cdm_util_dump_buff_indirect(uint32_t *cmd_buf_addr) +static long cam_cdm_util_dump_buff_indirect(uint32_t *cmd_buf_addr, + uint32_t *cmd_buf_addr_end) { long ret = 0; + struct cdm_indirect_cmd *p_indirect_cmd; + uint32_t *temp_ptr = cmd_buf_addr; + p_indirect_cmd = (struct cdm_indirect_cmd *)cmd_buf_addr; + temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT]; - CAM_INFO(CAM_CDM, "Buff Indirect"); + + if (temp_ptr > cmd_buf_addr_end) + CAM_ERR(CAM_CDM, + "Invalid cmd start addr:%pK end addr:%pK", + temp_ptr, cmd_buf_addr_end); + + CAM_INFO(CAM_CDM, + "Buff Indirect: LEN: %u addr: 0x%X", + p_indirect_cmd->length, p_indirect_cmd->addr); return ret; } -static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr) +static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr, + uint32_t *cmd_buf_addr_end) { long ret = 0; struct cdm_regcontinuous_cmd *p_regcont_cmd; @@ -722,6 +750,12 @@ static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr) p_regcont_cmd->count, p_regcont_cmd->offset); for (i = 0; i < p_regcont_cmd->count; i++) { + if (temp_ptr > cmd_buf_addr_end) { + CAM_ERR(CAM_CDM, + "Invalid cmd(%d) start addr:%pK end addr:%pK", + i, temp_ptr, cmd_buf_addr_end); + break; + } CAM_INFO(CAM_CDM, "DATA_%d: 0x%X", i, *temp_ptr); temp_ptr++; @@ -731,7 +765,8 @@ static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr) return ret; } -static long cam_cdm_util_dump_reg_random_cmd(uint32_t *cmd_buf_addr) +static long cam_cdm_util_dump_reg_random_cmd(uint32_t *cmd_buf_addr, + uint32_t *cmd_buf_addr_end) { struct cdm_regrandom_cmd *p_regrand_cmd; uint32_t *temp_ptr = cmd_buf_addr; @@ -746,6 +781,12 @@ static long cam_cdm_util_dump_reg_random_cmd(uint32_t *cmd_buf_addr) p_regrand_cmd->count); for (i = 0; i < p_regrand_cmd->count; i++) { + if (temp_ptr > cmd_buf_addr_end) { + CAM_ERR(CAM_CDM, + "Invalid cmd(%d) start addr:%pK end addr:%pK", + i, temp_ptr, cmd_buf_addr_end); + break; + } CAM_INFO(CAM_CDM, "OFFSET_%d: 0x%X DATA_%d: 0x%X", i, *temp_ptr & CAM_CDM_REG_OFFSET_MASK, i, *(temp_ptr + 1)); @@ -778,15 +819,22 @@ static long cam_cdm_util_dump_wait_event_cmd(uint32_t *cmd_buf_addr) return ret; } -static long cam_cdm_util_dump_change_base_cmd(uint32_t *cmd_buf_addr) +static long cam_cdm_util_dump_change_base_cmd(uint32_t *cmd_buf_addr, + uint32_t *cmd_buf_addr_end) { long ret = 0; struct cdm_changebase_cmd *p_cbase_cmd; uint32_t *temp_ptr = cmd_buf_addr; p_cbase_cmd = (struct cdm_changebase_cmd *)temp_ptr; + temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE]; ret += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE]; + if (temp_ptr > cmd_buf_addr_end) + CAM_ERR(CAM_CDM, + "Invalid cmd start addr:%pK end addr:%pK", + temp_ptr, cmd_buf_addr_end); + CAM_INFO(CAM_CDM, "CHANGE_BASE: 0x%X", p_cbase_cmd->base); @@ -819,6 +867,7 @@ void cam_cdm_util_dump_cmd_buf( uint32_t *cmd_buf_start, uint32_t *cmd_buf_end) { uint32_t *buf_now = cmd_buf_start; + uint32_t *buf_end = cmd_buf_end; uint32_t cmd = 0; if (!cmd_buf_start || !cmd_buf_end) { @@ -834,16 +883,20 @@ void cam_cdm_util_dump_cmd_buf( case CAM_CDM_CMD_DMI: case CAM_CDM_CMD_DMI_32: case CAM_CDM_CMD_DMI_64: - buf_now += cam_cdm_util_dump_dmi_cmd(buf_now); + buf_now += cam_cdm_util_dump_dmi_cmd(buf_now, + buf_end); break; case CAM_CDM_CMD_REG_CONT: - buf_now += cam_cdm_util_dump_reg_cont_cmd(buf_now); + buf_now += cam_cdm_util_dump_reg_cont_cmd(buf_now, + buf_end); break; case CAM_CDM_CMD_REG_RANDOM: - buf_now += cam_cdm_util_dump_reg_random_cmd(buf_now); + buf_now += cam_cdm_util_dump_reg_random_cmd(buf_now, + buf_end); break; case CAM_CDM_CMD_BUFF_INDIRECT: - buf_now += cam_cdm_util_dump_buff_indirect(buf_now); + buf_now += cam_cdm_util_dump_buff_indirect(buf_now, + buf_end); break; case CAM_CDM_CMD_GEN_IRQ: buf_now += cam_cdm_util_dump_gen_irq_cmd(buf_now); @@ -852,7 +905,8 @@ void cam_cdm_util_dump_cmd_buf( buf_now += cam_cdm_util_dump_wait_event_cmd(buf_now); break; case CAM_CDM_CMD_CHANGE_BASE: - buf_now += cam_cdm_util_dump_change_base_cmd(buf_now); + buf_now += cam_cdm_util_dump_change_base_cmd(buf_now, + buf_end); break; case CAM_CDM_CMD_PERF_CTRL: buf_now += cam_cdm_util_dump_perf_ctrl_cmd(buf_now); diff --git a/drivers/cam_cdm/cam_cdm_virtual_core.c b/drivers/cam_cdm/cam_cdm_virtual_core.c index 5abca3939338..481d37616c48 100644 --- a/drivers/cam_cdm/cam_cdm_virtual_core.c +++ b/drivers/cam_cdm/cam_cdm_virtual_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -19,6 +19,7 @@ #include "cam_cdm_core_common.h" #include "cam_cdm_soc.h" #include "cam_io_util.h" +#include "cam_req_mgr_workq.h" #define CAM_CDM_VIRTUAL_NAME "qcom,cam_virtual_cdm" @@ -32,6 +33,10 @@ static void cam_virtual_cdm_work(struct work_struct *work) if (payload) { cdm_hw = payload->hw; core = (struct cam_cdm *)cdm_hw->core_info; + + cam_req_mgr_thread_switch_delay_detect( + payload->workq_scheduled_ts); + if (payload->irq_status & 0x2) { struct cam_cdm_bl_cb_request_entry *node; @@ -183,9 +188,11 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw, INIT_WORK((struct work_struct *) &payload->work, cam_virtual_cdm_work); + payload->workq_scheduled_ts = + ktime_get(); queue_work(core->work_queue, &payload->work); - } + } } core->bl_tag++; CAM_DBG(CAM_CDM, diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index a79ed3867091..dee6d1708fbd 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -573,7 +573,7 @@ int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx, req_hdl_param.media_entity_flag = 0; req_hdl_param.priv = ctx; req_hdl_param.ops = ctx->crm_ctx_intf; - + req_hdl_param.dev_id = ctx->dev_id; ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param); if (ctx->dev_hdl <= 0) { rc = -EFAULT; diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 6b24bde92a8c..75ec613e7112 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -96,8 +96,9 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node, ctx = cam_node_get_ctxt_from_free_list(node); if (!ctx) { - CAM_ERR(CAM_CORE, "No free ctx in free list node %s", - node->name); + CAM_ERR(CAM_CORE, + "No free ctx in free list node %s with size:%d", + node->name, node->ctx_size); cam_node_print_ctx_state(node); rc = -ENOMEM; @@ -818,14 +819,14 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr); if (rc) { CAM_ERR(CAM_CORE, - "acquire device failed(rc = %d)", rc); + "acquire hw failed(rc = %d)", rc); goto acquire_kfree; } } else if (api_version == 2) { rc = __cam_node_handle_acquire_hw_v2(node, acquire_ptr); if (rc) { CAM_ERR(CAM_CORE, - "acquire device failed(rc = %d)", rc); + "acquire hw failed(rc = %d)", rc); goto acquire_kfree; } } diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index d809157d7b69..ca777c7a01bb 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1041,7 +1041,7 @@ static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, { struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_cpas_client *cpas_client = NULL; - struct cam_axi_vote axi_vote = {0}; + struct cam_axi_vote *axi_vote = NULL; uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle); int rc = 0; @@ -1051,16 +1051,24 @@ static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, return -EINVAL; } - memcpy(&axi_vote, client_axi_vote, sizeof(struct cam_axi_vote)); - if (!CAM_CPAS_CLIENT_VALID(client_indx)) return -EINVAL; - cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], - "Incoming Vote", &axi_vote); - mutex_lock(&cpas_hw->hw_mutex); mutex_lock(&cpas_core->client_mutex[client_indx]); + + axi_vote = kmemdup(client_axi_vote, sizeof(struct cam_axi_vote), + GFP_KERNEL); + if (!axi_vote) { + CAM_ERR(CAM_CPAS, "Out of memory"); + mutex_unlock(&cpas_core->client_mutex[client_indx]); + mutex_unlock(&cpas_hw->hw_mutex); + return -ENOMEM; + } + + cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], + "Incoming Vote", axi_vote); + cpas_client = cpas_core->cpas_client[client_indx]; if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) { @@ -1071,7 +1079,7 @@ static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, goto unlock_client; } - rc = cam_cpas_util_translate_client_paths(&axi_vote); + rc = cam_cpas_util_translate_client_paths(axi_vote); if (rc) { CAM_ERR(CAM_CPAS, "Unable to translate per path votes rc: %d", rc); @@ -1079,19 +1087,21 @@ static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, } cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], - "Translated Vote", &axi_vote); + "Translated Vote", axi_vote); /* Log an entry whenever there is an AXI update - before updating */ cam_cpas_update_monitor_array(cpas_hw, "CPAS AXI pre-update", client_indx); rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, - cpas_core->cpas_client[client_indx], &axi_vote); + cpas_core->cpas_client[client_indx], axi_vote); /* Log an entry whenever there is an AXI update - after updating */ cam_cpas_update_monitor_array(cpas_hw, "CPAS AXI post-update", client_indx); unlock_client: + kzfree(axi_vote); + axi_vote = NULL; mutex_unlock(&cpas_core->client_mutex[client_indx]); mutex_unlock(&cpas_hw->hw_mutex); return rc; diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index 5347d02b9197..fefc6dcde12f 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -933,7 +933,6 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, CAM_DBG(CAM_CPAS, "RPMH BCM info not available in DT, count=%d", count); } - return 0; cleanup_tree: diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index ed1a951fa549..0bef0a434343 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -30,6 +30,7 @@ #include "cpastop_v545_100.h" #include "cpastop_v570_200.h" #include "cpastop_v680_100.h" +#include "cam_req_mgr_workq.h" struct cam_camnoc_info *camnoc_info; @@ -571,6 +572,9 @@ static void cam_cpastop_work(struct work_struct *work) return; } + cam_req_mgr_thread_switch_delay_detect( + payload->workq_scheduled_ts); + cpas_hw = payload->hw; cpas_core = (struct cam_cpas *) cpas_hw->core_info; soc_info = &cpas_hw->soc_info; @@ -670,6 +674,7 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data) cam_cpastop_reset_irq(cpas_hw); + payload->workq_scheduled_ts = ktime_get(); queue_work(cpas_core->work_queue, &payload->work); done: atomic_dec(&cpas_core->irq_count); diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index dd1e1f5273e1..57bdf4100b8a 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -341,6 +341,7 @@ struct cam_camnoc_info { * @hw: Pointer to HW info * @irq_status: IRQ status value * @irq_data: IRQ data + * @workq_scheduled_ts: workqueue scheduled timestamp * @work: Work handle * */ @@ -348,6 +349,7 @@ struct cam_cpas_work_payload { struct cam_hw_info *hw; uint32_t irq_status; uint32_t irq_data; + ktime_t workq_scheduled_ts; struct work_struct work; }; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 069a45bab1a6..8fd7cb0d0c43 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -19,6 +19,7 @@ #include "cam_cdm_util.h" #include "cam_isp_context.h" #include "cam_common_util.h" +#include "cam_req_mgr_debug.h" static const char isp_dev_name[] = "cam-isp"; @@ -1832,6 +1833,12 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); + + cam_req_mgr_debug_delay_detect(); + trace_cam_delay_detect("ISP", + "bubble epoch_in_applied", req->request_id, + ctx->ctx_id, ctx->link_hdl, ctx->session_hdl, + CAM_DEFAULT_VALUE); end: if (request_id == 0) { req = list_last_entry(&ctx->active_req_list, @@ -2048,6 +2055,13 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); + + cam_req_mgr_debug_delay_detect(); + trace_cam_delay_detect("ISP", + "bubble epoch_in_bubble_applied", + req->request_id, ctx->ctx_id, + ctx->link_hdl, ctx->session_hdl, + CAM_DEFAULT_VALUE); end: req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request, list); @@ -4223,6 +4237,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; req_isp->bubble_detected = false; + req_isp->hw_update_data.packet = packet; for (i = 0; i < req_isp->num_fence_map_out; i++) { rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id); @@ -4444,7 +4459,7 @@ get_dev_handle: req_hdl_param.media_entity_flag = 0; req_hdl_param.ops = ctx->crm_ctx_intf; req_hdl_param.priv = ctx; - + req_hdl_param.dev_id = CAM_ISP; CAM_DBG(CAM_ISP, "get device handle form bridge"); ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param); if (ctx->dev_hdl <= 0) { diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 10aa46ffc0f4..68eb02e9b466 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -96,7 +96,6 @@ static int cam_isp_dev_component_bind(struct device *dev, struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; const char *compat_str = NULL; - uint32_t isp_device_type; struct platform_device *pdev = to_platform_device(dev); int iommu_hdl = -1; @@ -109,11 +108,13 @@ static int cam_isp_dev_component_bind(struct device *dev, if (strnstr(compat_str, "ife", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, CAM_IFE_DEVICE_TYPE); - isp_device_type = CAM_IFE_DEVICE_TYPE; + g_isp_dev.isp_device_type = CAM_IFE_DEVICE_TYPE; + g_isp_dev.max_context = CAM_IFE_CTX_MAX; } else if (strnstr(compat_str, "tfe", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, CAM_TFE_DEVICE_TYPE); - isp_device_type = CAM_TFE_DEVICE_TYPE; + g_isp_dev.isp_device_type = CAM_TFE_DEVICE_TYPE; + g_isp_dev.max_context = CAM_TFE_CTX_MAX; } else { CAM_ERR(CAM_ISP, "Invalid ISP hw type %s", compat_str); rc = -EINVAL; @@ -127,30 +128,51 @@ static int cam_isp_dev_component_bind(struct device *dev, node = (struct cam_node *) g_isp_dev.sd.token; memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf)); - rc = cam_isp_hw_mgr_init(compat_str, &hw_mgr_intf, &iommu_hdl); - if (rc != 0) { - CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!"); + g_isp_dev.ctx = kcalloc(g_isp_dev.max_context, + sizeof(struct cam_context), + GFP_KERNEL); + if (!g_isp_dev.ctx) { + CAM_ERR(CAM_ISP, + "Mem Allocation failed for ISP base context"); goto unregister; } - for (i = 0; i < CAM_CTX_MAX; i++) { + g_isp_dev.ctx_isp = kcalloc(g_isp_dev.max_context, + sizeof(struct cam_isp_context), + GFP_KERNEL); + if (!g_isp_dev.ctx_isp) { + CAM_ERR(CAM_ISP, + "Mem Allocation failed for Isp private context"); + kfree(g_isp_dev.ctx); + g_isp_dev.ctx = NULL; + goto unregister; + } + + rc = cam_isp_hw_mgr_init(compat_str, &hw_mgr_intf, &iommu_hdl); + if (rc != 0) { + CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!"); + goto kfree; + } + + for (i = 0; i < g_isp_dev.max_context; i++) { rc = cam_isp_context_init(&g_isp_dev.ctx_isp[i], &g_isp_dev.ctx[i], &node->crm_node_intf, &node->hw_mgr_intf, i, - isp_device_type); + g_isp_dev.isp_device_type); if (rc) { CAM_ERR(CAM_ISP, "ISP context init failed!"); - goto unregister; + goto kfree; } } - rc = cam_node_init(node, &hw_mgr_intf, g_isp_dev.ctx, CAM_CTX_MAX, - CAM_ISP_DEV_NAME); + rc = cam_node_init(node, &hw_mgr_intf, g_isp_dev.ctx, + g_isp_dev.max_context, CAM_ISP_DEV_NAME); + if (rc) { CAM_ERR(CAM_ISP, "ISP node init failed!"); - goto unregister; + goto kfree; } cam_smmu_set_client_page_fault_handler(iommu_hdl, @@ -161,6 +183,13 @@ static int cam_isp_dev_component_bind(struct device *dev, CAM_DBG(CAM_ISP, "Component bound successfully"); return 0; + +kfree: + kfree(g_isp_dev.ctx); + g_isp_dev.ctx = NULL; + kfree(g_isp_dev.ctx_isp); + g_isp_dev.ctx_isp = NULL; + unregister: rc = cam_subdev_remove(&g_isp_dev.sd); err: @@ -180,13 +209,18 @@ static void cam_isp_dev_component_unbind(struct device *dev, cam_isp_hw_mgr_deinit(compat_str); /* clean up resources */ - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < g_isp_dev.max_context; i++) { rc = cam_isp_context_deinit(&g_isp_dev.ctx_isp[i]); if (rc) CAM_ERR(CAM_ISP, "ISP context %d deinit failed", i); } + kfree(g_isp_dev.ctx); + g_isp_dev.ctx = NULL; + kfree(g_isp_dev.ctx_isp); + g_isp_dev.ctx_isp = NULL; + rc = cam_subdev_remove(&g_isp_dev.sd); if (rc) CAM_ERR(CAM_ISP, "Unregister failed rc: %d", rc); diff --git a/drivers/cam_isp/cam_isp_dev.h b/drivers/cam_isp/cam_isp_dev.h index d58ab7a8274e..53d126c316d6 100644 --- a/drivers/cam_isp/cam_isp_dev.h +++ b/drivers/cam_isp/cam_isp_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_DEV_H_ @@ -19,13 +19,17 @@ * @ctx_isp: Isp private context storage * @isp_mutex: ISP dev mutex * @open_cnt: Open device count + * @isp_device_type ISP device type + * @max_context maximum contexts for TFE is 4 and for IFE is 8 */ struct cam_isp_dev { struct cam_subdev sd; - struct cam_context ctx[CAM_CTX_MAX]; - struct cam_isp_context ctx_isp[CAM_CTX_MAX]; + struct cam_context *ctx; + struct cam_isp_context *ctx_isp; struct mutex isp_mutex; int32_t open_cnt; + uint32_t isp_device_type; + int32_t max_context; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b87cadb04850..d8a3806bbe43 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7401,7 +7401,7 @@ static int cam_ife_hw_mgr_find_affected_ctx( /* Add affected_context in list of recovery data */ CAM_DBG(CAM_ISP, "Add affected ctx %d to list", ife_hwr_mgr_ctx->ctx_index); - if (recovery_data->no_of_context < CAM_CTX_MAX) + if (recovery_data->no_of_context < CAM_IFE_CTX_MAX) recovery_data->affected_ctx[ recovery_data->no_of_context++] = ife_hwr_mgr_ctx; @@ -8141,7 +8141,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) } atomic_set(&g_ife_hw_mgr.active_ctx_cnt, 0); - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_IFE_CTX_MAX; i++) { memset(&g_ife_hw_mgr.ctx_pool[i], 0, sizeof(g_ife_hw_mgr.ctx_pool[i])); INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].list); @@ -8224,7 +8224,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return 0; end: if (rc) { - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_IFE_CTX_MAX; i++) { cam_tasklet_deinit( &g_ife_hw_mgr.mgr_common.tasklet_pool[i]); kfree(g_ife_hw_mgr.ctx_pool[i].cdm_cmd); @@ -8249,7 +8249,7 @@ void cam_ife_hw_mgr_deinit(void) debugfs_remove_recursive(g_ife_hw_mgr.debug_cfg.dentry); g_ife_hw_mgr.debug_cfg.dentry = NULL; - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_IFE_CTX_MAX; i++) { cam_tasklet_deinit( &g_ife_hw_mgr.mgr_common.tasklet_pool[i]); kfree(g_ife_hw_mgr.ctx_pool[i].cdm_cmd); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 52833a5567c3..ba6c594025d1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -194,7 +194,7 @@ struct cam_ife_hw_mgr { atomic_t active_ctx_cnt; struct list_head free_ctx_list; struct list_head used_ctx_list; - struct cam_ife_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; + struct cam_ife_hw_mgr_ctx ctx_pool[CAM_IFE_CTX_MAX]; struct cam_ife_csid_hw_caps ife_csid_dev_caps[ CAM_IFE_CSID_HW_NUM_MAX]; @@ -218,7 +218,7 @@ struct cam_ife_hw_mgr { struct cam_ife_hw_event_recovery_data { uint32_t error_type; uint32_t affected_core[CAM_ISP_HW_NUM_MAX]; - struct cam_ife_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX]; + struct cam_ife_hw_mgr_ctx *affected_ctx[CAM_IFE_CTX_MAX]; uint32_t no_of_context; }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 4f88ac4d1f37..5f05ef93a1b2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -23,9 +23,12 @@ #include "cam_mem_mgr_api.h" #include "cam_common_util.h" #include "cam_compat.h" +#include "cam_req_mgr_debug.h" +#include "cam_trace.h" #define CAM_TFE_HW_ENTRIES_MAX 20 #define CAM_TFE_HW_CONFIG_TIMEOUT 60 +#define CAM_TFE_HW_CONFIG_WAIT_MAX_TRY 3 #define TZ_SVC_SMMU_PROGRAM 0x15 #define TZ_SAFE_SYSCALL_ID 0x3 @@ -1497,6 +1500,8 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_csid_rdi( csid_acquire.out_port = out_port; csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; csid_acquire.node_res = NULL; + csid_acquire.event_cb = cam_tfe_hw_mgr_event_handler; + csid_acquire.event_cb_prv = tfe_ctx; if (tfe_ctx->is_tpg) { if (tfe_ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx == @@ -1747,16 +1752,21 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, { struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; struct cam_tfe_hw_mgr_ctx *ctx = NULL; + uint32_t *buf_start, *buf_end; + int i, rc = 0; + size_t len = 0; + uint32_t *buf_addr; if (!userdata) { CAM_ERR(CAM_ISP, "Invalid args"); return; } - hw_update_data = (struct cam_isp_prepare_hw_update_data *)userdata; - ctx = (struct cam_tfe_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; - if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) { + hw_update_data = + (struct cam_isp_prepare_hw_update_data *)userdata; + ctx = + (struct cam_tfe_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; complete_all(&ctx->config_done_complete); atomic_set(&ctx->cdm_done, 1); if (g_tfe_hw_mgr.debug_cfg.per_req_reg_dump) @@ -1768,6 +1778,40 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, CAM_DBG(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d", handle, userdata, status, cookie, ctx->ctx_index); + } else if (status == CAM_CDM_CB_STATUS_PAGEFAULT || + status == CAM_CDM_CB_STATUS_INVALID_BL_CMD || + status == CAM_CDM_CB_STATUS_HW_ERROR) { + ctx = userdata; + CAM_INFO(CAM_ISP, + "req_id =%d ctx_id =%d Bl_cmd_count =%d status=%d", + ctx->applied_req_id, ctx->ctx_index, + ctx->last_submit_bl_cmd.bl_count, status); + + for (i = 0; i < ctx->last_submit_bl_cmd.bl_count; i++) { + CAM_INFO(CAM_ISP, + "BL(%d) hdl=0x%x addr=0x%x len=%d input_len =%d offset=0x%x type=%d", + i, ctx->last_submit_bl_cmd.cmd[i].mem_handle, + ctx->last_submit_bl_cmd.cmd[i].hw_addr, + ctx->last_submit_bl_cmd.cmd[i].len, + ctx->last_submit_bl_cmd.cmd[i].input_len, + ctx->last_submit_bl_cmd.cmd[i].offset, + ctx->last_submit_bl_cmd.cmd[i].type); + + rc = cam_packet_util_get_cmd_mem_addr( + ctx->last_submit_bl_cmd.cmd[i].mem_handle, + &buf_addr, &len); + + buf_start = (uint32_t *)((uint8_t *) buf_addr + + ctx->last_submit_bl_cmd.cmd[i].offset); + buf_end = (uint32_t *)((uint8_t *) buf_start + + ctx->last_submit_bl_cmd.cmd[i].input_len - 1); + + cam_cdm_util_dump_cmd_buf(buf_start, buf_end); + } + if (ctx->packet != NULL) + cam_packet_dump_patch_info(ctx->packet, + g_tfe_hw_mgr.mgr_common.img_iommu_hdl, + g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure); } else { CAM_WARN(CAM_ISP, "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu", @@ -2311,7 +2355,7 @@ static int cam_isp_tfe_blob_bw_update( { struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_hw_intf *hw_intf; - struct cam_tfe_bw_update_args bw_upd_args; + struct cam_tfe_bw_update_args *bw_upd_args = NULL; int rc = -EINVAL; uint32_t i, split_idx; bool camif_l_bw_updated = false; @@ -2332,32 +2376,38 @@ static int cam_isp_tfe_blob_bw_update( bw_config->axi_path[i].mnoc_ib_bw); } + bw_upd_args = kzalloc(sizeof(struct cam_tfe_bw_update_args), + GFP_KERNEL); + if (!bw_upd_args) { + CAM_ERR(CAM_ISP, "Out of memory"); + return -ENOMEM; + } list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { for (split_idx = 0; split_idx < CAM_ISP_HW_SPLIT_MAX; split_idx++) { if (!hw_mgr_res->hw_res[split_idx]) continue; - memset(&bw_upd_args.isp_vote, 0, + memset(&bw_upd_args->isp_vote, 0, sizeof(struct cam_axi_vote)); rc = cam_tfe_classify_vote_info(hw_mgr_res, bw_config, - &bw_upd_args.isp_vote, split_idx, + &bw_upd_args->isp_vote, split_idx, &camif_l_bw_updated, &camif_r_bw_updated); if (rc) - return rc; + goto end; - if (!bw_upd_args.isp_vote.num_paths) + if (!bw_upd_args->isp_vote.num_paths) continue; hw_intf = hw_mgr_res->hw_res[split_idx]->hw_intf; if (hw_intf && hw_intf->hw_ops.process_cmd) { - bw_upd_args.node_res = + bw_upd_args->node_res = hw_mgr_res->hw_res[split_idx]; rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_BW_UPDATE_V2, - &bw_upd_args, + bw_upd_args, sizeof( struct cam_tfe_bw_update_args)); if (rc) @@ -2369,6 +2419,9 @@ static int cam_isp_tfe_blob_bw_update( } } +end: + kzfree(bw_upd_args); + bw_upd_args = NULL; return rc; } @@ -2430,21 +2483,28 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, "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; - cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; - cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; - cdm_cmd->flag = true; - cdm_cmd->userdata = hw_update_data; - cdm_cmd->cookie = cfg->request_id; - cdm_cmd->gen_irq_arb = false; + if (cfg->num_hw_update_entries <= 0) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Enter ctx id:%d no valid hw entries:%d request id: %llu", + ctx->ctx_index, cfg->num_hw_update_entries, + cfg->request_id); + goto end; + } - for (i = 0; i < cfg->num_hw_update_entries; i++) { - cmd = cfg->hw_update_entries + i; - if (cfg->reapply && cmd->flags == CAM_ISP_IQ_BL) { - skip++; - continue; - } + cdm_cmd = ctx->cdm_cmd; + cdm_cmd->cmd_arrary_count = cfg->num_hw_update_entries; + cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; + cdm_cmd->flag = true; + cdm_cmd->userdata = hw_update_data; + cdm_cmd->cookie = cfg->request_id; + cdm_cmd->gen_irq_arb = false; + + for (i = 0; i < cfg->num_hw_update_entries; i++) { + cmd = (cfg->hw_update_entries + i); + if (cfg->reapply && cmd->flags == CAM_ISP_IQ_BL) { + skip++; + continue; + } if (cmd->flags == CAM_ISP_UNUSED_BL || cmd->flags >= CAM_ISP_BL_MAX) @@ -2471,29 +2531,99 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, return rc; } - if (cfg->init_packet) { - rc = wait_for_completion_timeout( - &ctx->config_done_complete, - msecs_to_jiffies(CAM_TFE_HW_CONFIG_TIMEOUT)); - if (rc <= 0) { - CAM_ERR(CAM_ISP, - "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 ctx_index %d", - cfg->request_id, - ctx->ctx_index); + ctx->packet = (struct cam_packet *)hw_update_data->packet; + ctx->last_submit_bl_cmd.bl_count = cdm_cmd->cmd_arrary_count; + + for (i = 0; i < cdm_cmd->cmd_arrary_count; i++) { + if (cdm_cmd->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE) { + ctx->last_submit_bl_cmd.cmd[i].mem_handle = + cdm_cmd->cmd[i].bl_addr.mem_handle; + + rc = cam_mem_get_io_buf( + cdm_cmd->cmd[i].bl_addr.mem_handle, + g_tfe_hw_mgr.mgr_common.cmd_iommu_hdl, + &ctx->last_submit_bl_cmd.cmd[i].hw_addr, + &ctx->last_submit_bl_cmd.cmd[i].len); + } else if (cdm_cmd->type == + CAM_CDM_BL_CMD_TYPE_HW_IOVA) { + if (!cdm_cmd->cmd[i].bl_addr.hw_iova) { + CAM_ERR(CAM_CDM, + "Submitted Hw bl hw_iova is invalid %d:%d", + i, cdm_cmd->cmd_arrary_count); + rc = -EINVAL; + break; } - } - } else { - CAM_ERR(CAM_ISP, "No commands to config"); + rc = 0; + ctx->last_submit_bl_cmd.cmd[i].hw_addr = + (uint64_t)cdm_cmd->cmd[i].bl_addr.hw_iova; + ctx->last_submit_bl_cmd.cmd[i].len = + cdm_cmd->cmd[i].len + cdm_cmd->cmd[i].offset; + ctx->last_submit_bl_cmd.cmd[i].mem_handle = 0; + } else + CAM_INFO(CAM_ISP, + "submitted invalid bl cmd addr type :%d for Bl(%d)", + cdm_cmd->type, i); + + ctx->last_submit_bl_cmd.cmd[i].offset = + cdm_cmd->cmd[i].offset; + ctx->last_submit_bl_cmd.cmd[i].type = + cdm_cmd->type; + ctx->last_submit_bl_cmd.cmd[i].input_len = + cdm_cmd->cmd[i].len; } + if (!cfg->init_packet) + goto end; + + for (i = 0; i < CAM_TFE_HW_CONFIG_WAIT_MAX_TRY; i++) { + rc = wait_for_completion_timeout( + &ctx->config_done_complete, + msecs_to_jiffies( + CAM_TFE_HW_CONFIG_TIMEOUT)); + if (rc <= 0) { + if (!cam_cdm_detect_hang_error(ctx->cdm_handle)) { + CAM_ERR(CAM_ISP, + "CDM workqueue delay detected, wait for some more time req_id=%llu rc=%d ctx_index %d", + cfg->request_id, rc, + ctx->ctx_index); + cam_req_mgr_debug_delay_detect(); + trace_cam_delay_detect("CDM", + "CDM workqueue delay detected", + cfg->request_id, ctx->ctx_index, + CAM_DEFAULT_VALUE, + CAM_DEFAULT_VALUE, rc); + continue; + } + + CAM_ERR(CAM_ISP, + "config done completion timeout for req_id=%llu rc=%d ctx_index %d", + cfg->request_id, rc, + ctx->ctx_index); + + cam_req_mgr_debug_delay_detect(); + trace_cam_delay_detect("ISP", + "config done completion timeout", + cfg->request_id, ctx->ctx_index, + CAM_DEFAULT_VALUE, CAM_DEFAULT_VALUE, + rc); + + if (rc == 0) + rc = -ETIMEDOUT; + + goto end; + } else { + rc = 0; + CAM_DBG(CAM_ISP, + "config done Success for req_id=%llu ctx_index %d", + cfg->request_id, ctx->ctx_index); + break; + } + } + + if ((i == CAM_TFE_HW_CONFIG_WAIT_MAX_TRY) && (rc == 0)) + rc = -ETIMEDOUT; + +end: CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); return rc; @@ -2734,6 +2864,17 @@ static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) atomic_dec_return(&g_tfe_hw_mgr.active_ctx_cnt); mutex_unlock(&g_tfe_hw_mgr.ctx_mutex); + for (i = 0; i < ctx->last_submit_bl_cmd.bl_count; i++) { + ctx->last_submit_bl_cmd.cmd[i].mem_handle = 0; + ctx->last_submit_bl_cmd.cmd[i].hw_addr = 0; + ctx->last_submit_bl_cmd.cmd[i].len = 0; + ctx->last_submit_bl_cmd.cmd[i].offset = 0; + ctx->last_submit_bl_cmd.cmd[i].type = 0; + ctx->last_submit_bl_cmd.cmd[i].input_len = 0; + } + ctx->last_submit_bl_cmd.bl_count = 0; + ctx->packet = NULL; + end: return rc; } @@ -3288,6 +3429,18 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, ctx->num_reg_dump_buf = 0; ctx->res_list_tpg.res_type = CAM_ISP_RESOURCE_MAX; atomic_set(&ctx->overflow_pending, 0); + + for (i = 0; i < ctx->last_submit_bl_cmd.bl_count; i++) { + ctx->last_submit_bl_cmd.cmd[i].mem_handle = 0; + ctx->last_submit_bl_cmd.cmd[i].hw_addr = 0; + ctx->last_submit_bl_cmd.cmd[i].len = 0; + ctx->last_submit_bl_cmd.cmd[i].offset = 0; + ctx->last_submit_bl_cmd.cmd[i].type = 0; + ctx->last_submit_bl_cmd.cmd[i].input_len = 0; + } + ctx->last_submit_bl_cmd.bl_count = 0; + ctx->packet = NULL; + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; ctx->eof_cnt[i] = 0; @@ -4987,13 +5140,19 @@ static int cam_tfe_hw_mgr_find_affected_ctx( affected_core, CAM_TFE_HW_NUM_MAX)) continue; + if (atomic_read(&tfe_hwr_mgr_ctx->overflow_pending)) { + CAM_INFO(CAM_ISP, "CTX:%d already error reported", + tfe_hwr_mgr_ctx->ctx_index); + continue; + } + atomic_set(&tfe_hwr_mgr_ctx->overflow_pending, 1); notify_err_cb = tfe_hwr_mgr_ctx->common.event_cb[event_type]; /* Add affected_context in list of recovery data */ CAM_DBG(CAM_ISP, "Add affected ctx %d to list", tfe_hwr_mgr_ctx->ctx_index); - if (recovery_data->no_of_context < CAM_CTX_MAX) + if (recovery_data->no_of_context < CAM_TFE_CTX_MAX) recovery_data->affected_ctx[ recovery_data->no_of_context++] = tfe_hwr_mgr_ctx; @@ -5002,8 +5161,13 @@ static int cam_tfe_hw_mgr_find_affected_ctx( * In the call back function corresponding ISP context * will update CRM about fatal Error */ - notify_err_cb(tfe_hwr_mgr_ctx->common.cb_priv, + if (notify_err_cb) { + notify_err_cb(tfe_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_ERROR, error_event_data); + } else { + CAM_WARN(CAM_ISP, "Error call back is not set"); + goto end; + } } /* fill the affected_core in recovery data */ @@ -5012,7 +5176,34 @@ static int cam_tfe_hw_mgr_find_affected_ctx( CAM_DBG(CAM_ISP, "tfe core %d is affected (%d)", i, recovery_data->affected_core[i]); } +end: + return 0; +} +static int cam_tfe_hw_mgr_handle_csid_event( + struct cam_isp_hw_event_info *event_info) +{ + struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_tfe_hw_event_recovery_data recovery_data = {0}; + + /* this can be extended based on the types of error + * received from CSID + */ + switch (event_info->err_type) { + case CAM_ISP_HW_ERROR_CSID_FATAL: { + + if (!g_tfe_hw_mgr.debug_cfg.enable_csid_recovery) + break; + + error_event_data.error_type = event_info->err_type; + cam_tfe_hw_mgr_find_affected_ctx(&error_event_data, + event_info->hw_idx, + &recovery_data); + break; + } + default: + break; + } return 0; } @@ -5033,6 +5224,13 @@ static int cam_tfe_hw_mgr_handle_hw_err( else if (event_info->res_type == CAM_ISP_RESOURCE_TFE_OUT) error_event_data.error_type = CAM_ISP_HW_ERROR_BUSIF_OVERFLOW; + spin_lock(&g_tfe_hw_mgr.ctx_lock); + if (event_info->err_type == CAM_ISP_HW_ERROR_CSID_FATAL) { + rc = cam_tfe_hw_mgr_handle_csid_event(event_info); + spin_unlock(&g_tfe_hw_mgr.ctx_lock); + return rc; + } + core_idx = event_info->hw_idx; if (g_tfe_hw_mgr.debug_cfg.enable_recovery) @@ -5042,9 +5240,13 @@ static int cam_tfe_hw_mgr_handle_hw_err( rc = cam_tfe_hw_mgr_find_affected_ctx(&error_event_data, core_idx, &recovery_data); + if (rc || !(recovery_data.no_of_context)) + goto end; - if (event_info->res_type == CAM_ISP_RESOURCE_TFE_OUT) + if (event_info->res_type == CAM_ISP_RESOURCE_TFE_OUT) { + spin_unlock(&g_tfe_hw_mgr.ctx_lock); return rc; + } if (g_tfe_hw_mgr.debug_cfg.enable_recovery) { /* Trigger for recovery */ @@ -5057,7 +5259,8 @@ static int cam_tfe_hw_mgr_handle_hw_err( CAM_DBG(CAM_ISP, "recovery is not enabled"); rc = 0; } - +end: + spin_unlock(&g_tfe_hw_mgr.ctx_lock); return rc; } @@ -5169,8 +5372,13 @@ static int cam_tfe_hw_mgr_check_irq_for_dual_tfe( tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; } - if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt == 1) + if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt == 1) { cam_tfe_mgr_ctx_irq_dump(tfe_hw_mgr_ctx); + trace_cam_delay_detect("ISP", "dual tfe irq mismatch", + CAM_DEFAULT_VALUE, tfe_hw_mgr_ctx->ctx_index, + CAM_DEFAULT_VALUE, CAM_DEFAULT_VALUE, + rc); + } rc = 0; } @@ -5499,6 +5707,9 @@ static int cam_tfe_hw_mgr_debug_register(void) dbgfileptr = debugfs_create_u32("enable_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, &g_tfe_hw_mgr.debug_cfg.enable_reg_dump); + dbgfileptr = debugfs_create_u32("enable_csid_recovery", 0644, + g_tfe_hw_mgr.debug_cfg.dentry, + &g_tfe_hw_mgr.debug_cfg.enable_csid_recovery); dbgfileptr = debugfs_create_file("tfe_camif_debug", 0644, g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_camif_debug); dbgfileptr = debugfs_create_u32("per_req_reg_dump", 0644, @@ -5542,6 +5753,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) memset(&g_tfe_hw_mgr, 0, sizeof(g_tfe_hw_mgr)); mutex_init(&g_tfe_hw_mgr.ctx_mutex); + spin_lock_init(&g_tfe_hw_mgr.ctx_lock); if (CAM_TFE_HW_NUM_MAX != CAM_TFE_CSID_HW_NUM_MAX) { CAM_ERR(CAM_ISP, "CSID num is different then TFE num"); @@ -5645,7 +5857,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) } atomic_set(&g_tfe_hw_mgr.active_ctx_cnt, 0); - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_TFE_CTX_MAX; i++) { memset(&g_tfe_hw_mgr.ctx_pool[i], 0, sizeof(g_tfe_hw_mgr.ctx_pool[i])); INIT_LIST_HEAD(&g_tfe_hw_mgr.ctx_pool[i].list); @@ -5724,7 +5936,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return 0; end: if (rc) { - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_TFE_CTX_MAX; i++) { cam_tasklet_deinit( &g_tfe_hw_mgr.mgr_common.tasklet_pool[i]); kfree(g_tfe_hw_mgr.ctx_pool[i].cdm_cmd); @@ -5749,7 +5961,7 @@ void cam_tfe_hw_mgr_deinit(void) debugfs_remove_recursive(g_tfe_hw_mgr.debug_cfg.dentry); g_tfe_hw_mgr.debug_cfg.dentry = NULL; - for (i = 0; i < CAM_CTX_MAX; i++) { + for (i = 0; i < CAM_TFE_CTX_MAX; i++) { cam_tasklet_deinit( &g_tfe_hw_mgr.mgr_common.tasklet_pool[i]); kfree(g_tfe_hw_mgr.ctx_pool[i].cdm_cmd); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index b51d0673630e..81a4e19fcfa1 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -13,6 +13,7 @@ #include "cam_tfe_csid_hw_intf.h" #include "cam_top_tpg_hw_intf.h" #include "cam_tasklet_util.h" +#include "cam_cdm_intf_api.h" @@ -27,6 +28,7 @@ * @dentry: Debugfs entry * @csid_debug: csid debug information * @enable_recovery: enable recovery + * @enable_csid_recovery: enable csid recovery * @camif_debug: enable sensor diagnosis status * @enable_reg_dump: enable reg dump on error; * @per_req_reg_dump: Enable per request reg dump @@ -36,6 +38,7 @@ struct cam_tfe_hw_mgr_debug { struct dentry *dentry; uint64_t csid_debug; uint32_t enable_recovery; + uint32_t enable_csid_recovery; uint32_t camif_debug; uint32_t enable_reg_dump; uint32_t per_req_reg_dump; @@ -61,6 +64,7 @@ struct cam_tfe_hw_mgr_debug { * @cdm_ops cdm util operation pointer for building * cdm commands * @cdm_cmd cdm base and length request pointer + * @last_submit_bl_cmd last submiited CDM BL command data * @config_done_complete indicator for configuration complete * @sof_cnt sof count value per core, used for dual TFE * @epoch_cnt epoch count value per core, used for dual TFE @@ -82,6 +86,7 @@ struct cam_tfe_hw_mgr_debug { * @slave_hw_idx slave hardware index in dual tfe case * @dual_tfe_irq_mismatch_cnt irq mismatch count value per core, used for * dual TFE + * packet CSL packet from user mode driver */ struct cam_tfe_hw_mgr_ctx { struct list_head list; @@ -105,6 +110,7 @@ struct cam_tfe_hw_mgr_ctx { uint32_t cdm_handle; struct cam_cdm_utils_ops *cdm_ops; struct cam_cdm_bl_request *cdm_cmd; + struct cam_cdm_bl_info last_submit_bl_cmd; struct completion config_done_complete; uint32_t sof_cnt[CAM_TFE_HW_NUM_MAX]; @@ -125,6 +131,7 @@ struct cam_tfe_hw_mgr_ctx { uint32_t master_hw_idx; uint32_t slave_hw_idx; uint32_t dual_tfe_irq_mismatch_cnt; + struct cam_packet *packet; }; /** @@ -148,6 +155,7 @@ struct cam_tfe_hw_mgr_ctx { * @work q work queue for TFE hw manager * @debug_cfg debug configuration * @support_consumed_addr indicate whether hw supports last consumed address + * @ctx_lock Spinlock for HW manager */ struct cam_tfe_hw_mgr { struct cam_isp_hw_mgr mgr_common; @@ -159,7 +167,7 @@ struct cam_tfe_hw_mgr { atomic_t active_ctx_cnt; struct list_head free_ctx_list; struct list_head used_ctx_list; - struct cam_tfe_hw_mgr_ctx ctx_pool[CAM_CTX_MAX]; + struct cam_tfe_hw_mgr_ctx ctx_pool[CAM_TFE_CTX_MAX]; struct cam_tfe_csid_hw_caps tfe_csid_dev_caps[ CAM_TFE_CSID_HW_NUM_MAX]; @@ -167,6 +175,7 @@ struct cam_tfe_hw_mgr { struct cam_req_mgr_core_workq *workq; struct cam_tfe_hw_mgr_debug debug_cfg; bool support_consumed_addr; + spinlock_t ctx_lock; }; /** @@ -181,7 +190,7 @@ struct cam_tfe_hw_mgr { struct cam_tfe_hw_event_recovery_data { uint32_t error_type; uint32_t affected_core[CAM_TFE_HW_NUM_MAX]; - struct cam_tfe_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX]; + struct cam_tfe_hw_mgr_ctx *affected_ctx[CAM_TFE_CTX_MAX]; uint32_t no_of_context; }; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 2d3d30df1525..681177737046 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -20,6 +20,12 @@ #define CAM_TFE_HW_NUM_MAX 3 #define CAM_TFE_RDI_NUM_MAX 3 +/* maximum context numbers for TFE */ +#define CAM_TFE_CTX_MAX 4 + +/* maximum context numbers for IFE */ +#define CAM_IFE_CTX_MAX 8 + /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 40 @@ -122,6 +128,7 @@ struct cam_isp_bw_config_internal { * is valid or not * @reg_dump_buf_desc: cmd buffer descriptors for reg dump * @num_reg_dump_buf: Count of descriptors in reg_dump_buf_desc + * @packet CSL packet from user mode driver * */ struct cam_isp_prepare_hw_update_data { @@ -137,6 +144,7 @@ struct cam_isp_prepare_hw_update_data { struct cam_cmd_buf_desc reg_dump_buf_desc[ CAM_REG_DUMP_MAX_BUF_ENTRIES]; uint32_t num_reg_dump_buf; + struct cam_packet *packet; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 7eb1a64184b9..f54356f3ee3a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4638,6 +4638,7 @@ static int cam_csid_handle_hw_err_irq( "CSID[%d] Can not get cmd for tasklet, evt_type %d", csid_hw->hw_intf->hw_idx, evt_type); + cam_csid_put_evt_payload(csid_hw, &evt_payload); return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index ab495472d396..6cd9a9d758c6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -18,6 +18,7 @@ #include "cam_cpas_api.h" #include "cam_isp_hw_mgr_intf.h" #include "cam_subdev.h" +#include "cam_tasklet_util.h" /* Timeout value in msec */ #define TFE_CSID_TIMEOUT 1000 @@ -869,6 +870,7 @@ static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t i, val, clk_lvl; + unsigned long flags; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -941,6 +943,12 @@ static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) if (rc) goto disable_soc; + spin_lock_irqsave(&csid_hw->spin_lock, flags); + csid_hw->fatal_err_detected = false; + csid_hw->device_enabled = 1; + spin_unlock_irqrestore(&csid_hw->spin_lock, flags); + cam_tasklet_start(csid_hw->tasklet); + return rc; disable_soc: @@ -994,6 +1002,7 @@ static int cam_tfe_csid_disable_hw(struct cam_tfe_csid_hw *csid_hw) CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed", csid_hw->hw_intf->hw_idx); + cam_tasklet_stop(csid_hw->tasklet); spin_lock_irqsave(&csid_hw->spin_lock, flags); csid_hw->device_enabled = 0; spin_unlock_irqrestore(&csid_hw->spin_lock, flags); @@ -1933,6 +1942,9 @@ static int cam_tfe_csid_release(void *hw_priv, goto end; } + csid_hw->event_cb = NULL; + csid_hw->event_cb_priv = NULL; + if ((res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE) || (res->res_state >= CAM_ISP_RESOURCE_STATE_STREAMING)) { CAM_WARN(CAM_ISP, @@ -2677,6 +2689,189 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, return rc; } +static int cam_csid_get_evt_payload( + struct cam_tfe_csid_hw *csid_hw, + struct cam_csid_evt_payload **evt_payload) +{ + + spin_lock(&csid_hw->spin_lock); + + if (list_empty(&csid_hw->free_payload_list)) { + *evt_payload = NULL; + spin_unlock(&csid_hw->spin_lock); + CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload core %d", + csid_hw->hw_intf->hw_idx); + return -ENOMEM; + } + + *evt_payload = list_first_entry(&csid_hw->free_payload_list, + struct cam_csid_evt_payload, list); + list_del_init(&(*evt_payload)->list); + spin_unlock(&csid_hw->spin_lock); + + return 0; +} + +static int cam_csid_put_evt_payload( + struct cam_tfe_csid_hw *csid_hw, + struct cam_csid_evt_payload **evt_payload) +{ + unsigned long flags; + + if (*evt_payload == NULL) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid payload core %d", + csid_hw->hw_intf->hw_idx); + return -EINVAL; + } + spin_lock_irqsave(&csid_hw->spin_lock, flags); + list_add_tail(&(*evt_payload)->list, + &csid_hw->free_payload_list); + *evt_payload = NULL; + spin_unlock_irqrestore(&csid_hw->spin_lock, flags); + + return 0; +} +static char *cam_csid_status_to_str(uint32_t status) +{ + switch (status) { + case TFE_CSID_IRQ_REG_TOP: + return "TOP"; + case TFE_CSID_IRQ_REG_RX: + return "RX"; + case TFE_CSID_IRQ_REG_IPP: + return "IPP"; + case TFE_CSID_IRQ_REG_RDI0: + return "RDI0"; + case TFE_CSID_IRQ_REG_RDI1: + return "RDI1"; + case TFE_CSID_IRQ_REG_RDI2: + return "RDI2"; + default: + return "Invalid IRQ"; + } +} + +static int cam_csid_evt_bottom_half_handler( + void *handler_priv, + void *evt_payload_priv) +{ + struct cam_tfe_csid_hw *csid_hw; + struct cam_csid_evt_payload *evt_payload; + int i; + int rc = 0; + struct cam_isp_hw_event_info event_info; + + if (!handler_priv || !evt_payload_priv) { + CAM_ERR(CAM_ISP, + "Invalid Param handler_priv %pK evt_payload_priv %pK", + handler_priv, evt_payload_priv); + return 0; + } + + csid_hw = (struct cam_tfe_csid_hw *)handler_priv; + evt_payload = (struct cam_csid_evt_payload *)evt_payload_priv; + + if (!csid_hw->event_cb || !csid_hw->event_cb_priv) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "hw_idx %d Invalid args %pK %pK", + csid_hw->hw_intf->hw_idx, + csid_hw->event_cb, + csid_hw->event_cb_priv); + goto end; + } + + if (csid_hw->event_cb_priv != evt_payload->priv) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "hw_idx %d priv mismatch %pK, %pK", + csid_hw->hw_intf->hw_idx, + csid_hw->event_cb_priv, + evt_payload->priv); + goto end; + } + + CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type, + csid_hw->csi2_rx_cfg.phy_sel); + + for (i = 0; i < TFE_CSID_IRQ_REG_MAX; i++) + CAM_ERR_RATE_LIMIT(CAM_ISP, "status %s: %x", + cam_csid_status_to_str(i), + evt_payload->irq_status[i]); + + /* this hunk can be extended to handle more cases + * which we want to offload to bottom half from + * irq handlers + */ + event_info.err_type = evt_payload->evt_type; + event_info.hw_idx = evt_payload->hw_idx; + + switch (evt_payload->evt_type) { + case CAM_ISP_HW_ERROR_CSID_FATAL: + if (csid_hw->fatal_err_detected) + break; + csid_hw->fatal_err_detected = true; + rc = csid_hw->event_cb(NULL, + CAM_ISP_HW_EVENT_ERROR, (void *)&event_info); + break; + + default: + CAM_DBG(CAM_ISP, "CSID[%d] invalid error type %d", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type); + break; + } +end: + cam_csid_put_evt_payload(csid_hw, &evt_payload); + return 0; +} + +static int cam_csid_handle_hw_err_irq( + struct cam_tfe_csid_hw *csid_hw, + int evt_type, + uint32_t *irq_status) +{ + int rc = 0; + int i; + void *bh_cmd = NULL; + struct cam_csid_evt_payload *evt_payload; + + CAM_DBG(CAM_ISP, "CSID[%d] error %d", + csid_hw->hw_intf->hw_idx, evt_type); + + rc = cam_csid_get_evt_payload(csid_hw, &evt_payload); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "No free payload core %d", + csid_hw->hw_intf->hw_idx); + return rc; + } + + rc = tasklet_bh_api.get_bh_payload_func(csid_hw->tasklet, &bh_cmd); + if (rc || !bh_cmd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID[%d] Can not get cmd for tasklet, evt_type %d", + csid_hw->hw_intf->hw_idx, + evt_type); + return rc; + } + + evt_payload->evt_type = evt_type; + evt_payload->priv = csid_hw->event_cb_priv; + evt_payload->hw_idx = csid_hw->hw_intf->hw_idx; + + for (i = 0; i < TFE_CSID_IRQ_REG_MAX; i++) + evt_payload->irq_status[i] = irq_status[i]; + + tasklet_bh_api.bottom_half_enqueue_func(csid_hw->tasklet, + bh_cmd, + csid_hw, + evt_payload, + cam_csid_evt_bottom_half_handler); + + return rc; +} + irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) { struct cam_tfe_csid_hw *csid_hw; @@ -2756,20 +2951,24 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) if (irq_status[TFE_CSID_IRQ_REG_RX] & TFE_CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) { fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[TFE_CSID_IRQ_REG_RX] & TFE_CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) { fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[TFE_CSID_IRQ_REG_RX] & TFE_CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) { fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[TFE_CSID_IRQ_REG_RX] & TFE_CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) { fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[TFE_CSID_IRQ_REG_RX] & @@ -2800,6 +2999,7 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) TFE_CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) is_error_irq = true; } +handle_fatal_error: spin_unlock_irqrestore(&csid_hw->spin_lock, flags); if (csid_hw->error_irq_count || fatal_err_detected) @@ -2825,6 +3025,8 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) CAM_SUBDEV_MESSAGE_IRQ_ERR, (csid_hw->csi2_rx_cfg.phy_sel - 1)); } + cam_csid_handle_hw_err_irq(csid_hw, + CAM_ISP_HW_ERROR_CSID_FATAL, irq_status); } if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOT_IRQ) { @@ -3190,6 +3392,19 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, tfe_csid_hw->rdi_res[i].res_priv = path_data; } + rc = cam_tasklet_init(&tfe_csid_hw->tasklet, tfe_csid_hw, csid_idx); + if (rc) { + CAM_ERR(CAM_ISP, "Unable to create CSID tasklet rc %d", rc); + goto err; + } + + INIT_LIST_HEAD(&tfe_csid_hw->free_payload_list); + for (i = 0; i < CAM_CSID_EVT_PAYLOAD_MAX; i++) { + INIT_LIST_HEAD(&tfe_csid_hw->evt_payload[i].list); + list_add_tail(&tfe_csid_hw->evt_payload[i].list, + &tfe_csid_hw->free_payload_list); + } + tfe_csid_hw->csid_debug = 0; tfe_csid_hw->error_irq_count = 0; tfe_csid_hw->prev_boot_timestamp = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index b9430e18f8cf..94783a7c813c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -74,6 +74,8 @@ #define TFE_CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) #define TFE_CSID_DEBUG_ENABLE_RST_IRQ_LOG BIT(9) +#define CAM_CSID_EVT_PAYLOAD_MAX 10 + /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_tfe_csid_path_halt_mode { TFE_CSID_HALT_MODE_INTERNAL, @@ -354,12 +356,31 @@ struct cam_tfe_csid_path_cfg { uint32_t sensor_vbi; }; +/** + * struct cam_csid_evt_payload- payload for csid hw event + * @list : list head + * @evt_type : Event type from CSID + * @irq_status : IRQ Status register + * @hw_idx : Hw index + * @priv : Private data of payload + */ +struct cam_csid_evt_payload { + struct list_head list; + uint32_t evt_type; + uint32_t irq_status[TFE_CSID_IRQ_REG_MAX]; + uint32_t hw_idx; + void *priv; +}; + /** * struct cam_tfe_csid_hw- csid hw device resources data * * @hw_intf: contain the csid hw interface information * @hw_info: csid hw device information * @csid_info: csid hw specific information + * @tasklet: tasklet to handle csid errors + * @free_payload_list: list head for payload + * @evt_payload: Event payload to be passed to tasklet * @in_res_id: csid in resource type * @csi2_rx_cfg: csi2 rx decoder configuration for csid * @csi2_rx_reserve_cnt: csi2 reservations count value @@ -382,6 +403,7 @@ struct cam_tfe_csid_path_cfg { * @device_enabled Device enabled will set once CSID powered on and * initial configuration are done. * @lock_state csid spin lock + * @fatal_err_detected flag to indicate fatal errror is reported * @event_cb: Callback function to hw mgr in case of hw events * @event_cb_priv: Context data * @ppi_hw_intf interface to ppi hardware @@ -395,6 +417,9 @@ struct cam_tfe_csid_hw { struct cam_hw_intf *hw_intf; struct cam_hw_info *hw_info; struct cam_tfe_csid_hw_info *csid_info; + void *tasklet; + struct list_head free_payload_list; + struct cam_csid_evt_payload evt_payload[CAM_CSID_EVT_PAYLOAD_MAX]; uint32_t in_res_id; struct cam_tfe_csid_csi2_rx_cfg csi2_rx_cfg; uint32_t csi2_reserve_cnt; @@ -413,6 +438,7 @@ struct cam_tfe_csid_hw { uint32_t error_irq_count; uint32_t device_enabled; spinlock_t spin_lock; + bool fatal_err_detected; cam_hw_mgr_event_cb_func event_cb; void *event_cb_priv; struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX]; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 69dbdc77a4ee..8560c77f89fc 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1647,11 +1647,11 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, if (!rc) goto end; } else { - CAM_ERR(CAM_OPE, + CAM_INFO(CAM_OPE, "CDM hdl=%x, udata=%pK, status=%d, cookie=%d req_id = %llu ctx_id=%d", handle, userdata, status, cookie, ope_req->request_id, ctx->ctx_id); - CAM_ERR(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", + CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", ope_req->request_id); if (status != CAM_CDM_CB_STATUS_HW_FLUSH) { cam_ope_dump_req_data(ope_req); @@ -2657,8 +2657,6 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) hw_mgr->clk_info.base_clk = soc_info->clk_rate[CAM_TURBO_VOTE][idx]; - hw_mgr->clk_info.curr_clk = - soc_info->clk_rate[CAM_TURBO_VOTE][idx]; hw_mgr->clk_info.threshold = 5; hw_mgr->clk_info.over_clked = 0; @@ -2689,6 +2687,8 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) soc_info = &dev->soc_info; idx = soc_info->src_clk_idx; clk_update.clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][idx]; + hw_mgr->clk_info.curr_clk = + soc_info->clk_rate[CAM_TURBO_VOTE][idx]; rc = hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_CLK_UPDATE, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index fde0b85f2f64..1be94c5d35be 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -15,6 +15,7 @@ #include "cam_trace.h" #include "cam_debug_util.h" #include "cam_req_mgr_dev.h" +#include "cam_req_mgr_debug.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]; @@ -1716,6 +1717,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, "Max retry attempts (count %d) reached on link[0x%x] for req [%lld]", max_retry, link->link_hdl, in_q->slot[in_q->rd_idx].req_id); + + cam_req_mgr_debug_delay_detect(); + trace_cam_delay_detect("CRM", + "Max retry attempts reached", + in_q->slot[in_q->rd_idx].req_id, + CAM_DEFAULT_VALUE, + link->link_hdl, + CAM_DEFAULT_VALUE, rc); + __cam_req_mgr_notify_error_on_link(link, dev); link->retry_cnt = 0; } @@ -2350,6 +2360,7 @@ int cam_req_mgr_process_flush_req(void *priv, void *data) rc = -EINVAL; goto end; } + link = (struct cam_req_mgr_core_link *)priv; task_data = (struct crm_task_payload *)data; flush_info = (struct cam_req_mgr_flush_info *)&task_data->u; @@ -2667,6 +2678,7 @@ int cam_req_mgr_process_error(void *priv, void *data) rc = -EINVAL; goto end; } + link = (struct cam_req_mgr_core_link *)priv; task_data = (struct crm_task_payload *)data; err_info = (struct cam_req_mgr_error_notify *)&task_data->u; @@ -2760,6 +2772,7 @@ int cam_req_mgr_process_stop(void *priv, void *data) rc = -EINVAL; goto end; } + link = (struct cam_req_mgr_core_link *)priv; __cam_req_mgr_flush_req_slot(link); end: @@ -2790,6 +2803,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) rc = -EINVAL; goto end; } + link = (struct cam_req_mgr_core_link *)priv; task_data = (struct crm_task_payload *)data; trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u; @@ -3260,7 +3274,7 @@ static int cam_req_mgr_cb_notify_trigger( task = cam_req_mgr_workq_get_task(link->workq); if (!task) { - CAM_ERR(CAM_CRM, "no empty task frame %lld", + CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task frame %lld", trigger_data->frame_id); rc = -EBUSY; goto end; @@ -3520,7 +3534,8 @@ int cam_req_mgr_create_session( ses_info->session_hdl = session_hdl; mutex_init(&cam_session->lock); - CAM_DBG(CAM_CRM, "LOCK_DBG session lock %pK", &cam_session->lock); + CAM_DBG(CAM_CRM, "LOCK_DBG session lock %pK hdl 0x%x", + &cam_session->lock, session_hdl); mutex_lock(&cam_session->lock); cam_session->session_hdl = session_hdl; @@ -3685,7 +3700,7 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info) memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl)); root_dev.session_hdl = link_info->u.link_info_v1.session_hdl; root_dev.priv = (void *)link; - + root_dev.dev_id = CAM_CRM; mutex_lock(&link->lock); /* Create unique dev handle for link */ link->link_hdl = cam_create_device_hdl(&root_dev); @@ -3795,6 +3810,7 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl)); root_dev.session_hdl = link_info->u.link_info_v2.session_hdl; root_dev.priv = (void *)link; + root_dev.dev_id = CAM_CRM; mutex_lock(&link->lock); /* Create unique dev handle for link */ diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.c b/drivers/cam_req_mgr/cam_req_mgr_debug.c index 41d9258e9a7f..fa3d2792a0c6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.c +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.c @@ -8,6 +8,7 @@ #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; +static int cam_debug_mgr_delay_detect; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { @@ -131,6 +132,8 @@ int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) debugfs_root, core_dev, &bubble_recovery); dbgfileptr = debugfs_create_bool("recovery_on_apply_fail", 0644, debugfs_root, &core_dev->recovery_on_apply_fail); + dbgfileptr = debugfs_create_u32("delay_detect_count", 0644, + debugfs_root, &cam_debug_mgr_delay_detect); if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel!"); @@ -141,7 +144,13 @@ end: return rc; } -void cam_req_mgr_debug_unregister(void) +int cam_req_mgr_debug_unregister(void) { debugfs_remove_recursive(debugfs_root); + return 0; +} + +void cam_req_mgr_debug_delay_detect(void) +{ + cam_debug_mgr_delay_detect += 1; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_debug.h b/drivers/cam_req_mgr/cam_req_mgr_debug.h index defe55a731e7..5a06f08a111f 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_debug.h +++ b/drivers/cam_req_mgr/cam_req_mgr_debug.h @@ -11,6 +11,10 @@ #include "cam_debug_util.h" int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev); -void cam_req_mgr_debug_unregister(void); +int cam_req_mgr_debug_unregister(void); +/* cam_req_mgr_debug_delay_detect() + * @brief : increment debug_fs varaible by 1 whenever delay occurred. + */ +void cam_req_mgr_debug_delay_detect(void); #endif diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index bd5b04c923b5..5785beaf15a6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -162,7 +162,8 @@ static int cam_req_mgr_close(struct file *filep) struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); CAM_WARN(CAM_CRM, - "release invoked associated userspace process has died"); + "release invoked associated userspace process has died, open_cnt: %d", + g_dev.open_cnt); mutex_lock(&g_dev.cam_lock); if (g_dev.open_cnt <= 0) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 88b6bf079e9c..df180a615104 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__ @@ -113,14 +113,30 @@ static int32_t cam_get_free_handle_index(void) idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits); - if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) + if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) { + CAM_DBG(CAM_CRM, "idx: %d", idx); return -ENOSR; + } set_bit(idx, hdl_tbl->bitmap); return idx; } +void cam_dump_tbl_info(void) +{ + int i; + + for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) + CAM_INFO(CAM_CRM, + "i: %d session_hdl=0x%x hdl_value=0x%x type=%d state=%d dev_id=0x%llx", + i, hdl_tbl->hdl[i].session_hdl, + hdl_tbl->hdl[i].hdl_value, + hdl_tbl->hdl[i].type, + hdl_tbl->hdl[i].state, + hdl_tbl->hdl[i].dev_id); +} + int32_t cam_create_session_hdl(void *priv) { int idx; @@ -137,6 +153,7 @@ int32_t cam_create_session_hdl(void *priv) idx = cam_get_free_handle_index(); if (idx < 0) { CAM_ERR(CAM_CRM, "Unable to create session handle"); + cam_dump_tbl_info(); spin_unlock_bh(&hdl_tbl_lock); return idx; } @@ -149,6 +166,7 @@ int32_t cam_create_session_hdl(void *priv) hdl_tbl->hdl[idx].state = HDL_ACTIVE; hdl_tbl->hdl[idx].priv = priv; hdl_tbl->hdl[idx].ops = NULL; + hdl_tbl->hdl[idx].dev_id = CAM_CRM; spin_unlock_bh(&hdl_tbl_lock); return handle; @@ -169,7 +187,9 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) idx = cam_get_free_handle_index(); if (idx < 0) { - CAM_ERR(CAM_CRM, "Unable to create device handle"); + CAM_ERR(CAM_CRM, + "Unable to create device handle(idx= %d)", idx); + cam_dump_tbl_info(); spin_unlock_bh(&hdl_tbl_lock); return idx; } @@ -182,9 +202,10 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) hdl_tbl->hdl[idx].state = HDL_ACTIVE; hdl_tbl->hdl[idx].priv = hdl_data->priv; hdl_tbl->hdl[idx].ops = hdl_data->ops; + hdl_tbl->hdl[idx].dev_id = hdl_data->dev_id; spin_unlock_bh(&hdl_tbl_lock); - pr_debug("%s: handle = %x", __func__, handle); + pr_debug("%s: handle = 0x%x idx = %d\n", __func__, handle, idx); return handle; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index c0e339eedd9b..9cf733871569 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_UTIL_API_H_ @@ -35,6 +35,7 @@ enum hdl_type { * @hdl_value: Allocated handle * @type: session/device handle * @state: free/used + * @dev_id: device id for handle * @ops: ops structure * @priv: private data of a handle */ @@ -43,6 +44,7 @@ struct handle { uint32_t hdl_value; enum hdl_type type; enum hdl_state state; + uint64_t dev_id; void *ops; void *priv; }; @@ -65,6 +67,7 @@ struct cam_req_mgr_util_hdl_tbl { * @v4l2_sub_dev_flag: flag to create v4l2 sub device * @media_entity_flag: flag for media entity * @reserved: reserved field + * @dev_id: device id for handle * @ops: ops pointer for a device handle * @priv: private data for a device handle */ @@ -73,6 +76,7 @@ struct cam_create_dev_hdl { int32_t v4l2_sub_dev_flag; int32_t media_entity_flag; int32_t reserved; + uint64_t dev_id; void *ops; void *priv; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.c b/drivers/cam_req_mgr/cam_req_mgr_workq.c index 0c9ff7c419ca..aaac21028589 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.c +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.c @@ -102,6 +102,7 @@ void cam_req_mgr_process_workq(struct work_struct *w) workq = (struct cam_req_mgr_core_workq *) container_of(w, struct cam_req_mgr_core_workq, work); + cam_req_mgr_thread_switch_delay_detect(workq->workq_scheduled_ts); while (i < CRM_TASK_PRIORITY_MAX) { WORKQ_ACQUIRE_LOCK(workq, flags); while (!list_empty(&workq->task.process_head[i])) { @@ -164,6 +165,7 @@ int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d", task, atomic_read(&workq->task.pending_cnt)); + workq->workq_scheduled_ts = ktime_get(); queue_work(workq->job, &workq->work); WORKQ_RELEASE_LOCK(workq, flags); end: @@ -265,3 +267,25 @@ void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq) *crm_workq = NULL; } } + +void cam_req_mgr_thread_switch_delay_detect(ktime_t workq_scheduled) +{ + uint64_t diff; + ktime_t cur_time; + struct timespec64 cur_ts; + struct timespec64 workq_scheduled_ts; + + cur_time = ktime_get(); + diff = ktime_ms_delta(cur_time, workq_scheduled); + workq_scheduled_ts = ktime_to_timespec64(workq_scheduled); + cur_ts = ktime_to_timespec64(cur_time); + + if (diff > CAM_WORKQ_RESPONSE_TIME_THRESHOLD) { + CAM_WARN(CAM_CRM, + "Workq delay detected %ld:%06ld %ld:%06ld %ld:", + workq_scheduled_ts.tv_sec, + workq_scheduled_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC, + diff); + } +} diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.h b/drivers/cam_req_mgr/cam_req_mgr_workq.h index 95c435ced9ed..01e600ac3cb6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.h +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.h @@ -26,6 +26,13 @@ */ #define CAM_WORKQ_FLAG_SERIAL (1 << 1) +/* + * Response time threshold in ms beyond which it is considered + * as workq scheduling/processing delay. + */ +#define CAM_WORKQ_RESPONSE_TIME_THRESHOLD 5 + + /* Task priorities, lower the number higher the priority*/ enum crm_task_priority { CRM_TASK_PRIORITY_0, @@ -54,14 +61,14 @@ enum crm_workq_context { * @ret : return value in future to use for blocking calls */ struct crm_workq_task { - int32_t priority; - void *payload; - int32_t (*process_cb)(void *priv, void *data); - void *parent; - struct list_head entry; - uint8_t cancel; - void *priv; - int32_t ret; + int32_t priority; + void *payload; + int32_t (*process_cb)(void *priv, void *data); + void *parent; + struct list_head entry; + uint8_t cancel; + void *priv; + int32_t ret; }; /** struct cam_req_mgr_core_workq @@ -84,6 +91,7 @@ struct cam_req_mgr_core_workq { struct workqueue_struct *job; spinlock_t lock_bh; uint32_t in_irq; + ktime_t workq_scheduled_ts; /* tasks */ struct { @@ -142,6 +150,14 @@ void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **workq); int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, void *priv, int32_t prio); +/** + * cam_req_mgr_thread_switch_delay_detect() + * @brief: Detects if workq delay has occurred or not + * @timestamp: workq scheduled timestamp + */ +void cam_req_mgr_thread_switch_delay_detect( + ktime_t timestamp); + /** * cam_req_mgr_workq_get_task() * @brief: Returns empty task pointer for use diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index a3fc2d7756ad..7ee27f9f5764 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -848,6 +848,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = a_ctrl; + bridge_params.dev_id = CAM_ACTUATOR; actuator_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 0d1b90932eeb..6dd5f92b0e62 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -6,6 +6,7 @@ #include #include "cam_cci_core.h" #include "cam_cci_dev.h" +#include "cam_req_mgr_workq.h" static int32_t cam_cci_convert_type_to_num_bytes( enum camera_sensor_i2c_type type) @@ -1533,6 +1534,8 @@ static void cam_cci_write_async_helper(struct work_struct *work) enum cci_i2c_master_t master; struct cam_cci_master_info *cci_master_info; + cam_req_mgr_thread_switch_delay_detect( + write_async->workq_scheduled_ts); cci_dev = write_async->cci_dev; i2c_msg = &write_async->c_ctrl.cfg.cci_i2c_write_cfg; master = write_async->c_ctrl.cci_info->cci_i2c_master; @@ -1601,6 +1604,7 @@ static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd, cci_i2c_write_cfg_w->size = cci_i2c_write_cfg->size; cci_i2c_write_cfg_w->delay = cci_i2c_write_cfg->delay; + write_async->workq_scheduled_ts = ktime_get(); queue_work(cci_dev->write_wq[write_async->queue], &write_async->work); return rc; diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 7f464b6f24d2..3284c64ad3b1 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -31,6 +31,7 @@ #include "cam_cci_hwreg.h" #include "cam_soc_util.h" #include "cam_debug_util.h" +#include "cam_req_mgr_workq.h" #define CCI_I2C_QUEUE_0_SIZE 128 #define CCI_I2C_QUEUE_1_SIZE 32 @@ -292,6 +293,7 @@ struct cci_write_async { struct cam_cci_ctrl c_ctrl; enum cci_i2c_queue_t queue; struct work_struct work; + ktime_t workq_scheduled_ts; enum cci_i2c_sync sync_en; }; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 903d12bf53a3..704ffb0a24aa 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1110,6 +1110,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = csiphy_dev; + bridge_params.dev_id = CAM_CSIPHY; index = csiphy_dev->acquire_count; csiphy_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index caf5132b3df2..8b9bd2adcb63 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -351,6 +351,7 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = e_ctrl; + bridge_params.dev_id = CAM_EEPROM; eeprom_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index bb7bd78ae275..8929a4b889fa 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -64,6 +64,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = fctrl; + bridge_params.dev_id = CAM_FLASH; flash_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index fcd7a0e7938f..9130d595ed06 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -82,6 +82,7 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = o_ctrl; + bridge_params.dev_id = CAM_OIS; ois_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 5714a94fdf2c..2f2db1e05281 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -835,6 +835,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = s_ctrl; + bridge_params.dev_id = CAM_SENSOR; sensor_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 5cdfa9bdc19a..4f447eff8c90 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -17,6 +17,7 @@ #include "cam_debug_util.h" #include "cam_common_util.h" #include "camera_main.h" +#include "cam_req_mgr_workq.h" struct sync_device *sync_dev; @@ -130,6 +131,7 @@ int cam_sync_register_callback(sync_callback cb_func, sync_cb->status = row->state; CAM_DBG(CAM_SYNC, "Enqueue callback for sync object:%d", sync_cb->sync_obj); + sync_cb->workq_scheduled_ts = ktime_get(); queue_work(sync_dev->work_queue, &sync_cb->cb_dispatch_work); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index 40ca3a99de54..27cdcdadb3b2 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -94,18 +94,20 @@ struct sync_child_info { * struct sync_callback_info - Single node of information about a kernel * callback registered on a sync object * - * @callback_func : Callback function, registered by client driver - * @cb_data : Callback data, registered by client driver - * @status........ : Status with which callback will be invoked in client - * @sync_obj : Sync id of the object for which callback is registered - * @cb_dispatch_work : Work representing the call dispatch - * @list : List member used to append this node to a linked list + * @callback_func : Callback function, registered by client driver + * @cb_data : Callback data, registered by client driver + * @status : Status with which callback will be invoked in client + * @sync_obj : Sync id of the object for which callback is registered + * @workq_scheduled_ts : workqueue scheduled timestamp + * @cb_dispatch_work : Work representing the call dispatch + * @list : List member used to append this node to a linked list */ struct sync_callback_info { sync_callback callback_func; void *cb_data; int status; int32_t sync_obj; + ktime_t workq_scheduled_ts; struct work_struct cb_dispatch_work; struct list_head list; }; diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c index 7bc8c947e4ee..84d885c8109e 100644 --- a/drivers/cam_sync/cam_sync_util.c +++ b/drivers/cam_sync/cam_sync_util.c @@ -4,6 +4,7 @@ */ #include "cam_sync_util.h" +#include "cam_req_mgr_workq.h" int cam_sync_util_find_and_set_empty_row(struct sync_device *sync_dev, long *idx) @@ -293,6 +294,8 @@ void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work) cb_dispatch_work); sync_callback sync_data = cb_info->callback_func; + cam_req_mgr_thread_switch_delay_detect( + cb_info->workq_scheduled_ts); sync_data(cb_info->sync_obj, cb_info->status, cb_info->cb_data); kfree(cb_info); diff --git a/drivers/cam_utils/cam_packet_util.c b/drivers/cam_utils/cam_packet_util.c index a462fb970e92..ebcd36cd4e11 100644 --- a/drivers/cam_utils/cam_packet_util.c +++ b/drivers/cam_utils/cam_packet_util.c @@ -179,6 +179,9 @@ void cam_packet_dump_patch_info(struct cam_packet *packet, ((uint32_t *) &packet->payload + packet->patch_offset/4); + CAM_INFO(CAM_UTIL, "Total num of patches : %d", + packet->num_patches); + 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; diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h index 51df326068fc..b27b861ffdcc 100644 --- a/drivers/cam_utils/cam_trace.h +++ b/drivers/cam_utils/cam_trace.h @@ -19,6 +19,8 @@ #include "cam_req_mgr_interface.h" #include "cam_context.h" +#define CAM_DEFAULT_VALUE 0xFF + TRACE_EVENT(cam_context_state, TP_PROTO(const char *name, struct cam_context *ctx), TP_ARGS(name, ctx), @@ -282,6 +284,39 @@ TRACE_EVENT(cam_req_mgr_add_req, ) ); +TRACE_EVENT(cam_delay_detect, + TP_PROTO(const char *entity, + const char *text, uint64_t req_id, + uint32_t ctx_id, int32_t link_hdl, + int32_t session_hdl, int rc), + TP_ARGS(entity, text, req_id, ctx_id, + link_hdl, session_hdl, rc), + TP_STRUCT__entry( + __string(entity, entity) + __string(text, text) + __field(uint64_t, req_id) + __field(uint64_t, ctx_id) + __field(int32_t, link_hdl) + __field(int32_t, session_hdl) + __field(int32_t, rc) + ), + TP_fast_assign( + __assign_str(entity, entity); + __assign_str(text, text); + __entry->req_id = req_id; + __entry->ctx_id = ctx_id; + __entry->link_hdl = link_hdl; + __entry->session_hdl = session_hdl; + __entry->rc = rc; + ), + TP_printk( + "%s: %s request=%lld ctx_id=%d link_hdl=0x%x session_hdl=0x%x rc=%d", + __get_str(entity), __get_str(text), __entry->req_id, + __entry->ctx_id, __entry->link_hdl, + __entry->session_hdl, __entry->rc + ) +); + TRACE_EVENT(cam_submit_to_hw, TP_PROTO(const char *entity, uint64_t req_id), TP_ARGS(entity, req_id), diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 5a635774aafb..2ce529fdf82b 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -426,6 +426,7 @@ struct cam_mem_cache_ops_cmd { * @CAM_REQ_MGR_ERROR_TYPE_BUFFER: Buffer was not filled, not fatal * @CAM_REQ_MGR_ERROR_TYPE_RECOVERY: Fatal error, can be recovered * @CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE: SOF freeze, can be recovered + * @CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY: Full recovery, can be recovered * @CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT: page fault, can be recovered */ #define CAM_REQ_MGR_ERROR_TYPE_DEVICE 0 From 8974656ba917bef6abc8a042efb28bc2d027136f Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Wed, 30 Sep 2020 20:39:52 +0530 Subject: [PATCH 547/790] msm: camera: ife: Detect RDI only context before acquire hw In current code, rdi only context is upated after acquiring the hw. In cases, where the first in_port comes as RDI only and second in_port comes as Pix and RDI, IFE lite along with Full IFE will be acquired. Context in question will not be marked as rdi_only. This causes issues as the interrupts for Lite will be enabled only if the context is rdi_only. Also, the rdi_only state machine will not be activated. To handle such scenarios, before acquiring the hw, we now detect whether the context is rdi_only. Based on this, hw manager can pass the information to CSID driver if LITE can be used or not. Based on this, the reserve call can take decision inside CSID driver. This information can also be used in advanced targets where LITE has more capabilities and CSID driver needs more information to make decisions while reserving hw. This commit fixes some existing issues of releasing the resources while handling the early exit from acquire call. It also adds logging in case there is a failure in acquire because of non availability of required resources. CRs-Fixed: 2794147 Change-Id: I0591a83c23504eb67f3b87f17e172a9c67e7c82b Signed-off-by: Gaurav Jindal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 601 ++++++++++-------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 10 + .../isp_hw/include/cam_ife_csid_hw_intf.h | 8 + 3 files changed, 342 insertions(+), 277 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b87cadb04850..f98d2e572b40 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -731,6 +731,62 @@ static const char *cam_ife_hw_mgr_get_src_res_id( } } +static void cam_ife_hw_mgr_dump_all_ctx(void) +{ + uint32_t i; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_hw_mgr_res *hw_mgr_res_temp; + struct cam_ife_hw_mgr_ctx *ctx_temp; + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + list_for_each_entry_safe(ctx, ctx_temp, + &g_ife_hw_mgr.used_ctx_list, list) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "ctx id:%d is_dual:%d is_tpg:%d num_base:%d rdi only:%d", + ctx->ctx_index, ctx->is_dual, ctx->is_tpg, + ctx->num_base, ctx->is_rdi_only_context); + + if (ctx->res_list_tpg.res_type == CAM_ISP_RESOURCE_TPG) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "Acquired TPG HW:%d", + ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx); + } + + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + CAM_INFO_RATE_LIMIT(CAM_ISP, + "csid:%d res_type:%d res_id:%d res_state:%d", + hw_mgr_res->hw_res[i]->hw_intf->hw_idx, + hw_mgr_res->hw_res[i]->res_type, + hw_mgr_res->hw_res[i]->res_id, + hw_mgr_res->hw_res[i]->res_state); + } + } + + list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, + &ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + CAM_INFO_RATE_LIMIT(CAM_ISP, + "ife IN:%d res_type:%d res_id:%d res_state:%d", + hw_mgr_res->hw_res[i]->hw_intf->hw_idx, + hw_mgr_res->hw_res[i]->res_type, + hw_mgr_res->hw_res[i]->res_id, + hw_mgr_res->hw_res[i]->res_state); + } + } + } + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); + +} + static void cam_ife_hw_mgr_print_acquire_info( struct cam_ife_hw_mgr_ctx *hw_mgr_ctx, uint32_t num_pix_port, uint32_t num_pd_port, uint32_t num_rdi_port, int acquire_failed) @@ -768,10 +824,10 @@ static void cam_ife_hw_mgr_print_acquire_info( fail: CAM_ERR(CAM_ISP, "Acquire HW failed for ctx:%u", hw_mgr_ctx->ctx_index); CAM_INFO(CAM_ISP, - "Previously acquired %s IFE[%d %d] with [%u pix] [%u pd] [%u rdi] ports for ctx:%u", - (hw_mgr_ctx->is_dual) ? "dual" : "single", + "Acquire fail for ctx:%u %s IFE[%d %d] with [%u pix] [%u pd] [%u rdi] ports", + hw_mgr_ctx->ctx_index, (hw_mgr_ctx->is_dual) ? "dual" : "single", hw_idx[CAM_ISP_HW_SPLIT_LEFT], hw_idx[CAM_ISP_HW_SPLIT_RIGHT], - num_pix_port, num_pd_port, num_rdi_port, hw_mgr_ctx->ctx_index); + num_pix_port, num_pd_port, num_rdi_port); list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, &hw_mgr_ctx->res_list_ife_src, list) { @@ -788,6 +844,7 @@ fail: (hw_res->res_state)); } } + cam_ife_hw_mgr_dump_all_ctx(); } static void cam_ife_hw_mgr_dump_acq_data( @@ -1644,7 +1701,7 @@ static int cam_ife_mgr_acquire_cid_res( struct cam_ife_hw_mgr *ife_hw_mgr; struct cam_hw_intf *hw_intf; struct cam_isp_hw_mgr_res *cid_res_temp, *cid_res_iterator; - struct cam_csid_hw_reserve_resource_args csid_acquire; + struct cam_csid_hw_reserve_resource_args csid_acquire = {0}; uint32_t acquired_cnt = 0; struct cam_isp_out_port_generic_info *out_port = NULL; @@ -1662,6 +1719,10 @@ 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 = path_res_id; + + if (ife_ctx->is_rdi_only_context) + csid_acquire.can_use_lite = true; + CAM_DBG(CAM_ISP, "path_res_id %d", path_res_id); if (in_port->num_out_res) @@ -2283,18 +2344,8 @@ static int cam_ife_mgr_check_and_update_fe( static int cam_ife_hw_mgr_preprocess_port( struct cam_ife_hw_mgr_ctx *ife_ctx, - struct cam_isp_in_port_generic_info *in_port, - int *ipp_count, - int *rdi_count, - int *ppp_count, - int *ife_rd_count, - int *lcr_count) + struct cam_isp_in_port_generic_info *in_port) { - int ipp_num = 0; - int rdi_num = 0; - int ppp_num = 0; - int ife_rd_num = 0; - int lcr_num = 0; uint32_t i; struct cam_isp_out_port_generic_info *out_port; struct cam_ife_hw_mgr *ife_hw_mgr; @@ -2302,31 +2353,27 @@ static int cam_ife_hw_mgr_preprocess_port( ife_hw_mgr = ife_ctx->hw_mgr; if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) - ife_rd_num++; + in_port->ife_rd_count++; 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++; + in_port->rdi_count++; else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD) - ppp_num++; + in_port->ppp_count++; else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR) - lcr_num++; + in_port->lcr_count++; else { CAM_DBG(CAM_ISP, "out_res_type %d", out_port->res_type); - ipp_num++; + in_port->ipp_count++; } } - *ipp_count = ipp_num; - *rdi_count = rdi_num; - *ppp_count = ppp_num; - *ife_rd_count = ife_rd_num; - *lcr_count = lcr_num; - CAM_DBG(CAM_ISP, "rdi: %d ipp: %d ppp: %d ife_rd: %d lcr: %d", - rdi_num, ipp_num, ppp_num, ife_rd_num, lcr_num); + in_port->rdi_count, in_port->ipp_count, + in_port->ppp_count, in_port->ife_rd_count, + in_port->lcr_count); return 0; } @@ -2546,32 +2593,24 @@ end: static int cam_ife_mgr_acquire_hw_for_offline_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, - uint32_t *num_pix_port, uint32_t *acquired_hw_id, uint32_t *acquired_hw_path) { int rc = -1; - int ipp_count = 0; - int rdi_count = 0; - int ppp_count = 0; - int ife_rd_count = 0; - int lcr_count = 0; ife_ctx->is_dual = (bool)in_port->usage_type; - cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, - &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); - - if ((!ipp_count && !lcr_count) || !ife_rd_count) { + if ((!in_port->ipp_count && !in_port->lcr_count) || + !in_port->ife_rd_count) { CAM_ERR(CAM_ISP, "Invalid %d BUS RD %d PIX %d LCR ports for FE ctx"); return -EINVAL; } - if (rdi_count || ppp_count) { + if (in_port->rdi_count || in_port->ppp_count) { CAM_ERR(CAM_ISP, "%d RDI %d PPP ports invalid for FE ctx", - rdi_count, ppp_count); + in_port->rdi_count, in_port->ppp_count); return -EINVAL; } @@ -2582,7 +2621,7 @@ static int cam_ife_mgr_acquire_hw_for_offline_ctx( goto err; } - if (ipp_count) + if (in_port->ipp_count) rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx, in_port, false, acquired_hw_id, acquired_hw_path); @@ -2591,7 +2630,7 @@ static int cam_ife_mgr_acquire_hw_for_offline_ctx( goto err; } - if (lcr_count) + if (in_port->lcr_count) rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx, in_port, true, acquired_hw_id, acquired_hw_path); @@ -2606,8 +2645,6 @@ static int cam_ife_mgr_acquire_hw_for_offline_ctx( goto err; } - *num_pix_port += ipp_count + lcr_count; - return 0; err: @@ -2618,17 +2655,11 @@ err: static int cam_ife_mgr_acquire_hw_for_ctx( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_generic_info *in_port, - uint32_t *num_pix_port, uint32_t *num_rdi_port, - uint32_t *num_pd_port, uint32_t *acquired_hw_id, + uint32_t *acquired_hw_id, uint32_t *acquired_hw_path) { int rc = -1; int is_dual_isp = 0; - int ipp_count = 0; - int rdi_count = 0; - int ppp_count = 0; - int ife_rd_count = 0; - int lcr_count = 0; bool crop_enable = true; is_dual_isp = in_port->usage_type; @@ -2641,16 +2672,14 @@ static int cam_ife_mgr_acquire_hw_for_ctx( goto err; } - cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count, - &rdi_count, &ppp_count, &ife_rd_count, &lcr_count); - - if (!ipp_count && !rdi_count && !ppp_count && !lcr_count) { + if (!in_port->ipp_count && !in_port->rdi_count && + !in_port->ppp_count && !in_port->lcr_count) { CAM_ERR(CAM_ISP, "No PIX or RDI or PPP or LCR resource"); return -EINVAL; } - if (ife_rd_count) { + if (in_port->ife_rd_count) { rc = cam_ife_hw_mgr_acquire_res_ife_bus_rd(ife_ctx, in_port); if (rc) { @@ -2659,7 +2688,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( } } - if (ipp_count || lcr_count) { + if (in_port->ipp_count || in_port->lcr_count) { /* get ife csid IPP resource */ rc = cam_ife_hw_mgr_acquire_res_ife_csid_pxl(ife_ctx, in_port, true, crop_enable); @@ -2670,7 +2699,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( } } - if (rdi_count) { + if (in_port->rdi_count) { /* get ife csid RDI resource */ rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port); if (rc) { @@ -2680,14 +2709,14 @@ static int cam_ife_mgr_acquire_hw_for_ctx( } } - if (ppp_count) { + if (in_port->ppp_count) { /* get ife csid PPP resource */ /* If both IPP and PPP paths are requested with the same vc dt * it is implied that the sensor is a type 3 PD sensor. Crop * must be enabled for this sensor on PPP path as well. */ - if (!ipp_count) + if (!in_port->ipp_count) crop_enable = false; rc = cam_ife_hw_mgr_acquire_res_ife_csid_pxl(ife_ctx, @@ -2700,7 +2729,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( } /* get ife src resource */ - if (ipp_count || ppp_count || rdi_count) { + if (in_port->ipp_count || in_port->ppp_count || in_port->rdi_count) { rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port, false, acquired_hw_id, acquired_hw_path); @@ -2712,7 +2741,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( } } - if (lcr_count) { + if (in_port->lcr_count) { rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port, true, acquired_hw_id, acquired_hw_path); @@ -2729,10 +2758,6 @@ static int cam_ife_mgr_acquire_hw_for_ctx( goto err; } - *num_pix_port = ipp_count + ife_rd_count + lcr_count; - *num_pd_port = ppp_count; - *num_rdi_port = rdi_count; - return 0; err: /* release resource at the acquire entry funciton */ @@ -2779,11 +2804,10 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, static int cam_ife_mgr_acquire_get_unified_structure_v0( struct cam_isp_acquire_hw_info *acquire_hw_info, uint32_t offset, uint32_t *input_size, - struct cam_isp_in_port_generic_info **in_port) + struct cam_isp_in_port_generic_info *in_port) { struct cam_isp_in_port_info *in = NULL; uint32_t in_port_length = 0; - struct cam_isp_in_port_generic_info *port_info = NULL; int32_t rc = 0, i; in = (struct cam_isp_in_port_info *) @@ -2796,83 +2820,75 @@ static int cam_ife_mgr_acquire_get_unified_structure_v0( *input_size += in_port_length; - if ((*input_size) > acquire_hw_info->input_info_size) { + if (!in_port || ((*input_size) > acquire_hw_info->input_info_size)) { CAM_ERR(CAM_ISP, "Input is not proper"); rc = -EINVAL; + goto err; } - port_info = kzalloc( - sizeof(struct cam_isp_in_port_generic_info), GFP_KERNEL); - - if (!port_info) - return -ENOMEM; - - port_info->major_ver = + in_port->major_ver = (acquire_hw_info->input_info_version >> 16) & 0xFFFF; - port_info->minor_ver = + in_port->minor_ver = acquire_hw_info->input_info_version & 0xFFFF; - port_info->res_type = in->res_type; - port_info->lane_type = in->lane_type; - port_info->lane_num = in->lane_num; - port_info->lane_cfg = in->lane_cfg; - port_info->vc[0] = in->vc; - port_info->dt[0] = in->dt; - port_info->num_valid_vc_dt = 1; - port_info->format = in->format; - port_info->test_pattern = in->test_pattern; - port_info->usage_type = in->usage_type; - port_info->left_start = in->left_start; - port_info->left_stop = in->left_stop; - port_info->left_width = in->left_width; - port_info->right_start = in->right_start; - port_info->right_stop = in->right_stop; - port_info->right_width = in->right_width; - port_info->line_start = in->line_start; - port_info->line_stop = in->line_stop; - port_info->height = in->height; - port_info->pixel_clk = in->pixel_clk; - port_info->batch_size = in->batch_size; - port_info->dsp_mode = in->dsp_mode; - port_info->hbi_cnt = in->hbi_cnt; - port_info->cust_node = 0; - port_info->horizontal_bin = 0; - port_info->qcfa_bin = 0; - port_info->num_out_res = in->num_out_res; + in_port->res_type = in->res_type; + in_port->lane_type = in->lane_type; + in_port->lane_num = in->lane_num; + in_port->lane_cfg = in->lane_cfg; + in_port->vc[0] = in->vc; + in_port->dt[0] = in->dt; + in_port->num_valid_vc_dt = 1; + in_port->format = in->format; + in_port->test_pattern = in->test_pattern; + in_port->usage_type = in->usage_type; + in_port->left_start = in->left_start; + in_port->left_stop = in->left_stop; + in_port->left_width = in->left_width; + in_port->right_start = in->right_start; + in_port->right_stop = in->right_stop; + in_port->right_width = in->right_width; + in_port->line_start = in->line_start; + in_port->line_stop = in->line_stop; + in_port->height = in->height; + in_port->pixel_clk = in->pixel_clk; + in_port->batch_size = in->batch_size; + in_port->dsp_mode = in->dsp_mode; + in_port->hbi_cnt = in->hbi_cnt; + in_port->cust_node = 0; + in_port->horizontal_bin = 0; + in_port->qcfa_bin = 0; + in_port->num_out_res = in->num_out_res; - port_info->data = kcalloc(in->num_out_res, + in_port->data = kcalloc(in->num_out_res, sizeof(struct cam_isp_out_port_generic_info), GFP_KERNEL); - if (port_info->data == NULL) { + if (in_port->data == NULL) { rc = -ENOMEM; - goto release_port_mem; + goto err; } for (i = 0; i < in->num_out_res; i++) { - port_info->data[i].res_type = in->data[i].res_type; - port_info->data[i].format = in->data[i].format; - port_info->data[i].width = in->data[i].width; - port_info->data[i].height = in->data[i].height; - port_info->data[i].comp_grp_id = in->data[i].comp_grp_id; - port_info->data[i].split_point = in->data[i].split_point; - port_info->data[i].secure_mode = in->data[i].secure_mode; - port_info->data[i].reserved = in->data[i].reserved; + in_port->data[i].res_type = in->data[i].res_type; + in_port->data[i].format = in->data[i].format; + in_port->data[i].width = in->data[i].width; + in_port->data[i].height = in->data[i].height; + in_port->data[i].comp_grp_id = in->data[i].comp_grp_id; + in_port->data[i].split_point = in->data[i].split_point; + in_port->data[i].secure_mode = in->data[i].secure_mode; + in_port->data[i].reserved = in->data[i].reserved; } - *in_port = port_info; return 0; -release_port_mem: - kfree(port_info); +err: return rc; } static int cam_ife_mgr_acquire_get_unified_structure_v2( struct cam_isp_acquire_hw_info *acquire_hw_info, uint32_t offset, uint32_t *input_size, - struct cam_isp_in_port_generic_info **in_port) + struct cam_isp_in_port_generic_info *in_port) { struct cam_isp_in_port_info_v2 *in = NULL; uint32_t in_port_length = 0; - struct cam_isp_in_port_generic_info *port_info = NULL; int32_t rc = 0, i; in = (struct cam_isp_in_port_info_v2 *) @@ -2885,95 +2901,87 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2( *input_size += in_port_length; - if ((*input_size) > acquire_hw_info->input_info_size) { + if (!in_port || ((*input_size) > acquire_hw_info->input_info_size)) { CAM_ERR(CAM_ISP, "Input is not proper"); rc = -EINVAL; + goto err; } - port_info = kzalloc( - sizeof(struct cam_isp_in_port_generic_info), GFP_KERNEL); - - if (!port_info) - return -ENOMEM; - - port_info->major_ver = + in_port->major_ver = (acquire_hw_info->input_info_version >> 16) & 0xFFFF; - port_info->minor_ver = + in_port->minor_ver = acquire_hw_info->input_info_version & 0xFFFF; - port_info->res_type = in->res_type; - port_info->lane_type = in->lane_type; - port_info->lane_num = in->lane_num; - port_info->lane_cfg = in->lane_cfg; - port_info->num_valid_vc_dt = in->num_valid_vc_dt; + in_port->res_type = in->res_type; + in_port->lane_type = in->lane_type; + in_port->lane_num = in->lane_num; + in_port->lane_cfg = in->lane_cfg; + in_port->num_valid_vc_dt = in->num_valid_vc_dt; - if (port_info->num_valid_vc_dt == 0 || - port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) { + if (in_port->num_valid_vc_dt == 0 || + in_port->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) { if (in->res_type != CAM_ISP_IFE_IN_RES_RD) { CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d", in->num_valid_vc_dt); rc = -EINVAL; - goto release_mem; + goto err; } } - for (i = 0; i < port_info->num_valid_vc_dt; i++) { - port_info->vc[i] = in->vc[i]; - port_info->dt[i] = in->dt[i]; + for (i = 0; i < in_port->num_valid_vc_dt; i++) { + in_port->vc[i] = in->vc[i]; + in_port->dt[i] = in->dt[i]; } - port_info->format = in->format; - port_info->test_pattern = in->test_pattern; - port_info->usage_type = in->usage_type; - port_info->left_start = in->left_start; - port_info->left_stop = in->left_stop; - port_info->left_width = in->left_width; - port_info->right_start = in->right_start; - port_info->right_stop = in->right_stop; - port_info->right_width = in->right_width; - port_info->line_start = in->line_start; - port_info->line_stop = in->line_stop; - port_info->height = in->height; - port_info->pixel_clk = in->pixel_clk; - port_info->batch_size = in->batch_size; - port_info->dsp_mode = in->dsp_mode; - port_info->fe_unpacker_fmt = in->format; - port_info->hbi_cnt = in->hbi_cnt; - port_info->cust_node = in->cust_node; - port_info->horizontal_bin = in->horizontal_bin; - port_info->qcfa_bin = in->qcfa_bin; - port_info->num_out_res = in->num_out_res; + in_port->format = in->format; + in_port->test_pattern = in->test_pattern; + in_port->usage_type = in->usage_type; + in_port->left_start = in->left_start; + in_port->left_stop = in->left_stop; + in_port->left_width = in->left_width; + in_port->right_start = in->right_start; + in_port->right_stop = in->right_stop; + in_port->right_width = in->right_width; + in_port->line_start = in->line_start; + in_port->line_stop = in->line_stop; + in_port->height = in->height; + in_port->pixel_clk = in->pixel_clk; + in_port->batch_size = in->batch_size; + in_port->dsp_mode = in->dsp_mode; + in_port->fe_unpacker_fmt = in->format; + in_port->hbi_cnt = in->hbi_cnt; + in_port->cust_node = in->cust_node; + in_port->horizontal_bin = in->horizontal_bin; + in_port->qcfa_bin = in->qcfa_bin; + in_port->num_out_res = in->num_out_res; - port_info->data = kcalloc(in->num_out_res, + in_port->data = kcalloc(in->num_out_res, sizeof(struct cam_isp_out_port_generic_info), GFP_KERNEL); - if (port_info->data == NULL) { + if (in_port->data == NULL) { rc = -ENOMEM; - goto release_mem; + goto err; } - for (i = 0; i < port_info->num_out_res; i++) { - port_info->data[i].res_type = in->data[i].res_type; - port_info->data[i].format = in->data[i].format; - port_info->data[i].width = in->data[i].width; - port_info->data[i].height = in->data[i].height; - port_info->data[i].comp_grp_id = in->data[i].comp_grp_id; - port_info->data[i].split_point = in->data[i].split_point; - port_info->data[i].secure_mode = in->data[i].secure_mode; + for (i = 0; i < in_port->num_out_res; i++) { + in_port->data[i].res_type = in->data[i].res_type; + in_port->data[i].format = in->data[i].format; + in_port->data[i].width = in->data[i].width; + in_port->data[i].height = in->data[i].height; + in_port->data[i].comp_grp_id = in->data[i].comp_grp_id; + in_port->data[i].split_point = in->data[i].split_point; + in_port->data[i].secure_mode = in->data[i].secure_mode; } - *in_port = port_info; - return 0; -release_mem: - kfree(port_info); +err: return rc; } static int cam_ife_mgr_acquire_get_unified_structure( struct cam_isp_acquire_hw_info *acquire_hw_info, uint32_t offset, uint32_t *input_size, - struct cam_isp_in_port_generic_info **in_port) + struct cam_isp_in_port_generic_info *in_port) { uint32_t major_ver = 0, minor_ver = 0; @@ -3009,9 +3017,6 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) struct cam_ife_hw_mgr_ctx *ife_ctx; struct cam_isp_in_port_generic_info *in_port = NULL; struct cam_cdm_acquire_data cdm_acquire; - uint32_t num_pix_port_per_in = 0; - uint32_t num_rdi_port_per_in = 0; - uint32_t num_pd_port_per_in = 0; uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; uint32_t total_pd_port = 0; @@ -3050,66 +3055,35 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_args->acquire_info_size); if (rc) { CAM_ERR(CAM_ISP, "buffer size is not enough"); - goto free_cdm; + goto free_ctx; } - /* acquire HW resources */ + in_port = kcalloc(acquire_hw_info->num_inputs, + sizeof(struct cam_isp_in_port_generic_info), + GFP_KERNEL); + + if (!in_port) { + CAM_ERR(CAM_ISP, "No memory available"); + rc = -ENOMEM; + goto free_ctx; + } + + /* Update in_port structure */ for (i = 0; i < acquire_hw_info->num_inputs; i++) { rc = cam_ife_mgr_acquire_get_unified_structure(acquire_hw_info, - i, &input_size, &in_port); + i, &input_size, &in_port[i]); + if (rc < 0) { CAM_ERR(CAM_ISP, "Failed in parsing: %d", rc); - goto free_res; - } - CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type); - - if ((in_port->cust_node) && (!ife_ctx->custom_enabled)) { - ife_ctx->custom_enabled = true; - /* These can be obtained from uapi */ - ife_ctx->custom_config |= - CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS; - ife_ctx->custom_config |= - CAM_IFE_CUSTOM_CFG_SW_SYNC_ON; - } - - if ((in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || - (in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || - (in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) - rc = cam_ife_hw_mgr_acquire_tpg(ife_ctx, in_port, - acquire_hw_info->num_inputs); - - if (rc) { - CAM_ERR(CAM_ISP, "can not acquire TPG resource"); goto free_mem; } - if (ife_ctx->is_offline) - rc = cam_ife_mgr_acquire_hw_for_offline_ctx( - ife_ctx, in_port, - &num_pix_port_per_in, - &acquire_args->acquired_hw_id[i], - acquire_args->acquired_hw_path[i]); - else - rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, - &num_pix_port_per_in, &num_rdi_port_per_in, - &num_pd_port_per_in, - &acquire_args->acquired_hw_id[i], - acquire_args->acquired_hw_path[i]); - - total_pix_port += num_pix_port_per_in; - total_rdi_port += num_rdi_port_per_in; - total_pd_port += num_pd_port_per_in; - - if (rc) { - cam_ife_hw_mgr_print_acquire_info(ife_ctx, - total_pix_port, total_pd_port, - total_rdi_port, rc); - goto free_mem; - } - - kfree(in_port->data); - kfree(in_port); - in_port = NULL; + cam_ife_hw_mgr_preprocess_port(ife_ctx, &in_port[i]); + total_pix_port += in_port[i].ipp_count + + in_port[i].ife_rd_count + + in_port[i].lcr_count; + total_rdi_port += in_port[i].rdi_count; + total_pd_port += in_port[i].ppp_count; } /* Check whether context has only RDI resource */ @@ -3118,11 +3092,61 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) CAM_DBG(CAM_ISP, "RDI only context"); } + /* acquire HW resources */ + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + + CAM_DBG(CAM_ISP, "in_res_type %x", in_port[i].res_type); + + if ((in_port[i].cust_node) && (!ife_ctx->custom_enabled)) { + ife_ctx->custom_enabled = true; + /* These can be obtained from uapi */ + ife_ctx->custom_config |= + CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS; + ife_ctx->custom_config |= + CAM_IFE_CUSTOM_CFG_SW_SYNC_ON; + } + + if ((in_port[i].res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || + (in_port[i].res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || + (in_port[i].res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) + rc = cam_ife_hw_mgr_acquire_tpg(ife_ctx, &in_port[i], + acquire_hw_info->num_inputs); + + if (rc) { + CAM_ERR(CAM_ISP, "can not acquire TPG resource"); + goto free_res; + } + + if (ife_ctx->is_offline) + rc = cam_ife_mgr_acquire_hw_for_offline_ctx( + ife_ctx, &in_port[i], + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + else + rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, + &in_port[i], + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + + if (rc) { + cam_ife_hw_mgr_print_acquire_info(ife_ctx, + total_pix_port, total_pd_port, + total_rdi_port, rc); + goto free_res; + } + + kfree(in_port[i].data); + in_port[i].data = NULL; + } + + kfree(in_port); + in_port = NULL; + /* Process base info */ rc = cam_ife_mgr_process_base_info(ife_ctx); if (rc) { CAM_ERR(CAM_ISP, "Process base info failed"); - goto free_cdm; + goto free_res; } cam_cpas_get_cpas_hw_version(&ife_ctx->hw_version); @@ -3150,7 +3174,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) rc = cam_cdm_acquire(&cdm_acquire); if (rc) { CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW"); - goto free_ctx; + goto free_res; } CAM_DBG(CAM_ISP, @@ -3183,13 +3207,19 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); return 0; -free_mem: - kfree(in_port->data); - kfree(in_port); -free_cdm: - cam_cdm_release(ife_ctx->cdm_handle); + free_res: cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); +free_mem: + if (in_port) { + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + kfree(in_port[i].data); + in_port[i].data = NULL; + } + + kfree(in_port); + in_port = NULL; + } free_ctx: cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); err: @@ -3252,9 +3282,6 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) struct cam_isp_resource *isp_resource = NULL; struct cam_cdm_acquire_data cdm_acquire; struct cam_isp_in_port_generic_info *gen_port_info = NULL; - uint32_t num_pix_port_per_in = 0; - uint32_t num_rdi_port_per_in = 0; - uint32_t num_pd_port_per_in = 0; uint32_t total_pd_port = 0; uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; @@ -3284,7 +3311,16 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; - /* acquire HW resources */ + gen_port_info = kcalloc(acquire_args->num_acq, + sizeof(struct cam_isp_in_port_generic_info), + GFP_KERNEL); + + if (!gen_port_info) { + CAM_ERR(CAM_ISP, "No memory available"); + rc = -ENOMEM; + goto err; + } + for (i = 0; i < acquire_args->num_acq; i++) { if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT) continue; @@ -3326,64 +3362,66 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto free_res; } - gen_port_info = kzalloc( - sizeof(struct cam_isp_in_port_generic_info), - GFP_KERNEL); - if (gen_port_info == NULL) { - rc = -ENOMEM; - goto free_res; - } - - gen_port_info->data = kcalloc( + gen_port_info[i].data = kcalloc( + in_port->num_out_res, sizeof(struct cam_isp_out_port_generic_info), - in_port->num_out_res, GFP_KERNEL); - if (gen_port_info->data == NULL) { - kfree(gen_port_info); - gen_port_info = NULL; + GFP_KERNEL); + if (gen_port_info[i].data == NULL) { rc = -ENOMEM; goto free_res; } cam_ife_mgr_acquire_get_unified_dev_str(in_port, - gen_port_info); + &gen_port_info[i]); + cam_ife_hw_mgr_preprocess_port(ife_ctx, + &gen_port_info[i]); - rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, - gen_port_info, &num_pix_port_per_in, - &num_rdi_port_per_in, &num_pd_port_per_in, - &acquire_args->acquired_hw_id[i], - acquire_args->acquired_hw_path[i]); - - total_pix_port += num_pix_port_per_in; - total_rdi_port += num_rdi_port_per_in; - total_pd_port += num_pd_port_per_in; + total_pix_port += gen_port_info[i].ipp_count + + gen_port_info[i].ife_rd_count + + gen_port_info[i].lcr_count; + total_rdi_port += gen_port_info[i].rdi_count; + total_pd_port += gen_port_info[i].ppp_count; kfree(in_port); - if (gen_port_info != NULL) { - kfree(gen_port_info->data); - kfree(gen_port_info); - gen_port_info = NULL; - } - if (rc) { - cam_ife_hw_mgr_print_acquire_info(ife_ctx, - total_pix_port, total_pd_port, - total_rdi_port, rc); - goto free_res; - } } else { CAM_ERR(CAM_ISP, "Copy from user failed with in_port = %pK", in_port); rc = -EFAULT; - goto free_res; + goto free_mem; } } /* Check whether context has only RDI resource */ - if (!total_pix_port) { + if (!total_pix_port || !total_pd_port) { ife_ctx->is_rdi_only_context = 1; CAM_DBG(CAM_ISP, "RDI only context"); } + /* acquire HW resources */ + for (i = 0; i < acquire_args->num_acq; i++) { + if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT) + continue; + + rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, + &gen_port_info[i], + &acquire_args->acquired_hw_id[i], + acquire_args->acquired_hw_path[i]); + + if (rc) { + cam_ife_hw_mgr_print_acquire_info(ife_ctx, + total_pix_port, total_pd_port, + total_rdi_port, rc); + goto free_res; + } + + kfree(gen_port_info[i].data); + gen_port_info[i].data = NULL; + } + + kfree(gen_port_info); + gen_port_info = NULL; + /* Process base info */ rc = cam_ife_mgr_process_base_info(ife_ctx); if (rc) { @@ -3440,6 +3478,15 @@ free_res: cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); cam_cdm_release(ife_ctx->cdm_handle); cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx); +free_mem: + if (gen_port_info) { + for (i = 0; i < acquire_args->num_acq; i++) { + kfree(gen_port_info[i].data); + gen_port_info[i].data = NULL; + } + kfree(gen_port_info); + gen_port_info = NULL; + } err: CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 7eb1a64184b9..17fce2031b80 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -689,6 +689,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, uint32_t camera_hw_version; uint32_t valid_vc_dt; uint32_t res_type; + struct cam_csid_soc_private *soc_priv; CAM_DBG(CAM_ISP, "CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d", @@ -699,6 +700,15 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, cid_reserv->in_port->dt[0], cid_reserv->in_port->vc[0]); + soc_priv = (struct cam_csid_soc_private *) + (csid_hw->hw_info->soc_info.soc_private); + + if (soc_priv->is_ife_csid_lite && !cid_reserv->can_use_lite) { + CAM_INFO(CAM_ISP, "CSID[%u] not lite context", + csid_hw->hw_intf->hw_idx); + return -EINVAL; + } + if (cid_reserv->in_port->res_type >= CAM_ISP_IFE_IN_RES_MAX) { CAM_ERR(CAM_ISP, "CSID:%d Invalid phy sel %d", csid_hw->hw_intf->hw_idx, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 28e0c14b3761..9159481935c2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -104,6 +104,12 @@ struct cam_isp_in_port_generic_info { uint32_t horizontal_bin; uint32_t qcfa_bin; uint32_t num_bytes_out; + uint32_t ipp_count; + uint32_t ppp_count; + uint32_t rdi_count; + uint32_t udi_count; + uint32_t lcr_count; + uint32_t ife_rd_count; struct cam_isp_out_port_generic_info *data; }; @@ -128,6 +134,7 @@ struct cam_isp_in_port_generic_info { * @priv: private data to be sent in callback * @event_cb: CSID event callback to hw manager * @phy_sel: Phy selection number if tpg is enabled from userspace + * @can_use_lite: Flag to indicate if current call qualifies for acquire lite * */ struct cam_csid_hw_reserve_resource_args { @@ -144,6 +151,7 @@ struct cam_csid_hw_reserve_resource_args { void *priv; cam_hw_mgr_event_cb_func event_cb; uint32_t phy_sel; + bool can_use_lite; }; /** From 3584602abfd8f918164de82edccd2805ac38a3f9 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 8 Oct 2020 13:19:21 +0530 Subject: [PATCH 548/790] msm: camera: tfe: Dont consider vbi for epoch configuration in case of tpg In case of TPG enabled, vbi value should be not be consider in calculating epoch configuration because vbi value passed is in cycles not in terms of lines when TPG is selected. CRs-Fixed: 2797039 Change-Id: Ia8870a8c2516fc2e0b3347ccb6b69db3774e33c1 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index b7104c15bf13..a8568fcab3e0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -1821,8 +1821,11 @@ int cam_tfe_top_reserve(void *device_priv, acquire_args->in_port->line_start; camif_data->last_line = acquire_args->in_port->line_end; - camif_data->vbi_value = - acquire_args->in_port->sensor_vbi; + if (acquire_args->in_port->res_id == CAM_ISP_TFE_IN_RES_TPG) + camif_data->vbi_value = 0; + else + camif_data->vbi_value = + acquire_args->in_port->sensor_vbi; camif_data->hbi_value = acquire_args->in_port->sensor_hbi; camif_data->camif_pd_enable = From 5673c120863f9f6c3334783d0f095a9b327cb08c Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 9 Oct 2020 15:45:49 +0530 Subject: [PATCH 549/790] msm: camera: isp: removed mutext lock from irq context get sof timestamp called from tasklet which intern should not take mutex as it may sleep. This change removes the mutext lock from irq context. CRs-Fixed: 2794250 Change-Id: If73acde1a4b931e4bfc3650638f7f977e18cb3ea Signed-off-by: Vikram Sharma --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 7eb1a64184b9..c321b1523154 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4412,8 +4412,6 @@ static int cam_ife_csid_process_cmd(void *hw_priv, csid_hw_info = (struct cam_hw_info *)hw_priv; csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; - mutex_lock(&csid_hw->hw_info->hw_mutex); - switch (cmd_type) { case CAM_IFE_CSID_CMD_GET_TIME_STAMP: rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args); @@ -4457,8 +4455,6 @@ static int cam_ife_csid_process_cmd(void *hw_priv, break; } - mutex_unlock(&csid_hw->hw_info->hw_mutex); - return rc; } From a3077c7802838975546dd0329ff1ac891abaaa46 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 1 Oct 2020 17:19:28 +0530 Subject: [PATCH 550/790] msm: camera: isp: Change csid stop sequence during flush This change takes care of a race which we see when we halt master csid immediately and slave csid halt to follow. In some scenarios after master csid halt, slave gives violation errors. With this change we are first changing the halt mode of slave to internal so that dependency on master is removed and then issue halt commands to both master and slave. CRs-Fixed: 2785781 Change-Id: Ib84a8c416e05a4ac54b6afad5c06017931d67a05 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 53 +++++++++++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 38 ++++---- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 90 +++++++++++++++++++ .../isp_hw/include/cam_ife_csid_hw_intf.h | 27 ++++++ .../isp_hw/include/cam_tfe_csid_hw_intf.h | 10 +-- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 78 ++++++++-------- 6 files changed, 229 insertions(+), 67 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b87cadb04850..dfbde0177f91 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -897,6 +897,52 @@ static void cam_ife_hw_mgr_dump_acq_data( } } +static int cam_ife_mgr_csid_change_halt_mode(struct cam_ife_hw_mgr_ctx *ctx, + enum cam_ife_csid_halt_mode halt_mode) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_ife_csid_hw_halt_args halt; + struct cam_hw_intf *hw_intf; + uint32_t i; + int rc = 0; + + if (!ctx->is_dual) + return 0; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (i == CAM_ISP_HW_SPLIT_LEFT) + continue; + + if (!hw_mgr_res->hw_res[i] || + (hw_mgr_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING)) + continue; + + isp_res = hw_mgr_res->hw_res[i]; + + if ((isp_res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && + (isp_res->res_id == CAM_IFE_PIX_PATH_RES_IPP)) { + hw_intf = isp_res->hw_intf; + halt.node_res = isp_res; + halt.halt_mode = halt_mode; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, + &halt, + sizeof( + struct cam_ife_csid_hw_halt_args)); + if (rc) + CAM_ERR(CAM_ISP, "Halt update failed"); + break; + } + } + } + + return rc; +} + static int cam_ife_mgr_csid_stop_hw( struct cam_ife_hw_mgr_ctx *ctx, struct list_head *stop_list, uint32_t base_idx, uint32_t stop_cmd) @@ -4074,6 +4120,13 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) */ if (i == ctx->num_base) master_base_idx = ctx->base[0].idx; + + /*Change slave mode*/ + if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) + cam_ife_mgr_csid_change_halt_mode(ctx, + CAM_CSID_HALT_MODE_INTERNAL); + + CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); /* Stop the master CSID path first */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 4f88ac4d1f37..2911ebc49e47 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -529,26 +529,30 @@ static int cam_tfe_hw_mgr_free_hw_res( return 0; } -static int cam_tfe_mgr_csid_change_halt_mode(struct list_head *halt_list, - uint32_t base_idx, enum cam_tfe_csid_halt_mode halt_mode) +static int cam_tfe_mgr_csid_change_halt_mode(struct cam_tfe_hw_mgr_ctx *ctx, + enum cam_tfe_csid_halt_mode halt_mode) { - struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_isp_resource_node *isp_res; - struct cam_csid_hw_halt_args halt; - struct cam_hw_intf *hw_intf; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_tfe_csid_hw_halt_args halt; + struct cam_hw_intf *hw_intf; uint32_t i; int rc = 0; - list_for_each_entry(hw_mgr_res, halt_list, list) { + if (!ctx->is_dual) + return 0; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (i == CAM_ISP_HW_SPLIT_LEFT) + continue; + if (!hw_mgr_res->hw_res[i] || (hw_mgr_res->hw_res[i]->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) continue; isp_res = hw_mgr_res->hw_res[i]; - if (isp_res->hw_intf->hw_idx != base_idx) - continue; if ((isp_res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && (isp_res->res_id == @@ -560,7 +564,8 @@ static int cam_tfe_mgr_csid_change_halt_mode(struct list_head *halt_list, hw_intf->hw_priv, CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, &halt, - sizeof(struct cam_csid_hw_halt_args)); + sizeof( + struct cam_tfe_csid_hw_halt_args)); if (rc) CAM_ERR(CAM_ISP, "Halt update failed"); break; @@ -2668,16 +2673,9 @@ static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) master_base_idx = ctx->base[0].idx; /*Change slave mode*/ - if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) { - for (i = 0; i < ctx->num_base; i++) { - if (ctx->base[i].idx == master_base_idx) - continue; - cam_tfe_mgr_csid_change_halt_mode( - &ctx->res_list_tfe_csid, - ctx->base[i].idx, - CAM_TFE_CSID_HALT_MODE_INTERNAL); - } - } + if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) + cam_tfe_mgr_csid_change_halt_mode(ctx, + CAM_TFE_CSID_HALT_MODE_INTERNAL); CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 7eb1a64184b9..baefed8613b1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2344,6 +2344,52 @@ static int cam_ife_csid_enable_pxl_path( return 0; } + +static int cam_ife_csid_change_pxl_halt_mode( + struct cam_ife_csid_hw *csid_hw, + struct cam_ife_csid_hw_halt_args *csid_halt) +{ + uint32_t val = 0; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_pxl_reg_offset *pxl_reg; + struct cam_isp_resource_node *res; + + res = csid_halt->node_res; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id != CAM_IFE_PIX_PATH_RES_IPP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id %d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "CSID:%d Res:%d in invalid state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return -EINVAL; + } + + pxl_reg = csid_reg->ipp_reg; + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + + /* configure Halt for slave */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val &= ~0xC; + val |= (csid_halt->halt_mode << 2); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + CAM_DBG(CAM_ISP, "CSID:%d IPP path Res halt mode:%d configured:%x", + csid_hw->hw_intf->hw_idx, csid_halt->halt_mode, val); + + return 0; +} + static int cam_ife_csid_disable_pxl_path( struct cam_ife_csid_hw *csid_hw, struct cam_isp_resource_node *res, @@ -3977,6 +4023,47 @@ end: return rc; } +int cam_ife_csid_halt(struct cam_ife_csid_hw *csid_hw, + void *halt_args) +{ + struct cam_isp_resource_node *res; + struct cam_ife_csid_hw_halt_args *csid_halt; + int rc = 0; + + if (!csid_hw || !halt_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_halt = (struct cam_ife_csid_hw_halt_args *)halt_args; + + /* Change the halt mode */ + res = csid_halt->node_res; + CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id); + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type %d", + csid_hw->hw_intf->hw_idx, + res->res_type); + return -EINVAL; + } + + switch (res->res_id) { + case CAM_IFE_PIX_PATH_RES_IPP: + rc = cam_ife_csid_change_pxl_halt_mode(csid_hw, csid_halt); + break; + default: + CAM_DBG(CAM_ISP, "CSID:%d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_id); + break; + } + + return rc; +} + int cam_ife_csid_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { @@ -4450,6 +4537,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_LOG_ACQUIRE_DATA: rc = cam_ife_csid_log_acquire_data(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE: + rc = cam_ife_csid_halt(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 28e0c14b3761..0d6e0513d423 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -156,6 +156,33 @@ enum cam_ife_csid_halt_cmd { CAM_CSID_HALT_MAX, }; +/** + * enum cam_ife_csid_halt_mode - Specify the halt command type + */ +enum cam_ife_csid_halt_mode { + CAM_CSID_HALT_MODE_INTERNAL, + CAM_CSID_HALT_MODE_GLOBAL, + CAM_CSID_HALT_MODE_MASTER, + CAM_CSID_HALT_MODE_SLAVE, + CAM_CSID_HALT_MODE_MAX, +}; + +/** + * struct cam_ife_csid_hw_halt_args + * @halt_mode : Applicable only for PATH resources + * 0 Internal : The CSID responds to the HALT_CMD + * 1 Global : The CSID responds to the GLOBAL_HALT_CMD + * 2 Master : The CSID responds to the HALT_CMD + * 3 Slave : The CSID responds to the external halt command + * and not the HALT_CMD register + * @node_res : reource pointer array( ie cid or CSID) + * + */ +struct cam_ife_csid_hw_halt_args { + enum cam_ife_csid_halt_mode halt_mode; + struct cam_isp_resource_node *node_res; +}; + /** * struct cam_csid_hw_stop- stop all resources * @stop_cmd : Applicable only for PATH resources diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h index 37094775db62..1f274be9eb0b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h @@ -96,7 +96,7 @@ enum cam_tfe_csid_halt_cmd { }; /** - * enum cam_tfe_csid_halt_mode_cmd - Specify the halt command type + * enum cam_tfe_csid_halt_mode - Specify the halt command type */ enum cam_tfe_csid_halt_mode { CAM_TFE_CSID_HALT_MODE_INTERNAL, @@ -107,7 +107,7 @@ enum cam_tfe_csid_halt_mode { }; /** - * struct cam_csid_hw_halt_args + * struct cam_tfe_csid_hw_halt_args * @halt_mode : Applicable only for PATH resources * 0 Internal : The CSID responds to the HALT_CMD * 1 Global : The CSID responds to the GLOBAL_HALT_CMD @@ -117,9 +117,9 @@ enum cam_tfe_csid_halt_mode { * @node_res : reource pointer array( ie cid or CSID) * */ -struct cam_csid_hw_halt_args { - enum cam_tfe_csid_halt_mode halt_mode; - struct cam_isp_resource_node *node_res; +struct cam_tfe_csid_hw_halt_args { + enum cam_tfe_csid_halt_mode halt_mode; + struct cam_isp_resource_node *node_res; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index ab495472d396..7036c660c67b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1248,49 +1248,35 @@ static int cam_tfe_csid_enable_pxl_path( return 0; } -static void cam_tfe_csid_change_pxl_halt_mode( - struct cam_tfe_csid_hw *csid_hw, - struct cam_isp_resource_node *res, - enum cam_tfe_csid_halt_mode halt_mode) +static int cam_tfe_csid_change_pxl_halt_mode( + struct cam_tfe_csid_hw *csid_hw, + struct cam_tfe_csid_hw_halt_args *csid_halt) { uint32_t val = 0; const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; - struct cam_tfe_csid_path_cfg *path_data; const struct cam_tfe_csid_pxl_reg_offset *pxl_reg; - bool is_ipp; + struct cam_isp_resource_node *res; + + res = csid_halt->node_res; - path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; - if (res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { - CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d", + if (res->res_id != CAM_TFE_CSID_PATH_RES_IPP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id %d", csid_hw->hw_intf->hw_idx, res->res_id); - goto end; - } - - if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || - res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { - CAM_ERR(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d", - csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); - goto end; - } - - if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { - is_ipp = true; - pxl_reg = csid_reg->ipp_reg; - } else { - goto end; + return -EINVAL; } if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { - CAM_ERR(CAM_ISP, "CSID:%d %s path Res:%d Invalid state%d", - csid_hw->hw_intf->hw_idx, "IPP", - res->res_id, res->res_state); - goto end; + CAM_ERR(CAM_ISP, "CSID:%d Res:%d in invalid state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return -EINVAL; } + pxl_reg = csid_reg->ipp_reg; + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_mask_addr); @@ -1298,11 +1284,13 @@ static void cam_tfe_csid_change_pxl_halt_mode( val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_ctrl_addr); val &= ~0xC; - val |= (halt_mode << 2); + val |= (csid_halt->halt_mode << 2); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_ctrl_addr); -end: - return; + CAM_DBG(CAM_ISP, "CSID:%d IPP path Res halt mode:%d configured:%x", + csid_hw->hw_intf->hw_idx, csid_halt->halt_mode, val); + + return 0; } static int cam_tfe_csid_disable_pxl_path( @@ -2199,14 +2187,15 @@ int cam_tfe_csid_halt(struct cam_tfe_csid_hw *csid_hw, void *halt_args) { struct cam_isp_resource_node *res; - struct cam_csid_hw_halt_args *csid_halt; + struct cam_tfe_csid_hw_halt_args *csid_halt; + int rc = 0; if (!csid_hw || !halt_args) { CAM_ERR(CAM_ISP, "CSID: Invalid args"); return -EINVAL; } - csid_halt = (struct cam_csid_hw_halt_args *)halt_args; + csid_halt = (struct cam_tfe_csid_hw_halt_args *)halt_args; /* Change the halt mode */ res = csid_halt->node_res; @@ -2214,20 +2203,25 @@ int cam_tfe_csid_halt(struct cam_tfe_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); - switch (res->res_type) { - case CAM_ISP_RESOURCE_PIX_PATH: - if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) - cam_tfe_csid_change_pxl_halt_mode(csid_hw, res, - csid_halt->halt_mode); - break; - default: - CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res type %d", csid_hw->hw_intf->hw_idx, res->res_type); + return -EINVAL; + } + + switch (res->res_id) { + case CAM_TFE_CSID_PATH_RES_IPP: + rc = cam_tfe_csid_change_pxl_halt_mode(csid_hw, csid_halt); + break; + default: + CAM_DBG(CAM_ISP, "CSID:%d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_id); break; } - return 0; + return rc; } static int cam_tfe_csid_stop(void *hw_priv, From 1fa7773fb13b2db38ba3eaf0811fdc3acc8ed9bd Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 8 Oct 2020 18:45:20 +0530 Subject: [PATCH 551/790] msm: camera: tfe: Enable only master interrupts in dual tfe usecase Enable only master sof, eof, epoch interrupts in dual tfe case. Due to scheduling issues one tfe core interrupts will be delayed that cause mis match of dual core interrupts events and eventually cause the frame drops. CRs-Fixed: 2796046 Change-Id: Ic16de3242e902bebaf79f83b9a332f0b7006908e Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 161 ++---------------- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 6 - .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 9 +- 3 files changed, 22 insertions(+), 154 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 5f05ef93a1b2..6867defe103c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -3441,11 +3441,6 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, ctx->last_submit_bl_cmd.bl_count = 0; ctx->packet = NULL; - for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { - ctx->sof_cnt[i] = 0; - ctx->eof_cnt[i] = 0; - ctx->epoch_cnt[i] = 0; - } CAM_DBG(CAM_ISP, "Exit...ctx id:%d", ctx->ctx_index); cam_tfe_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx); @@ -4667,36 +4662,6 @@ outportlog: } -static void cam_tfe_mgr_ctx_irq_dump(struct cam_tfe_hw_mgr_ctx *ctx) -{ - struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_hw_intf *hw_intf; - struct cam_isp_hw_get_cmd_update cmd_update; - int i = 0; - - list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { - if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT) - continue; - for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (!hw_mgr_res->hw_res[i]) - continue; - switch (hw_mgr_res->hw_res[i]->res_id) { - case CAM_ISP_HW_TFE_IN_CAMIF: - hw_intf = hw_mgr_res->hw_res[i]->hw_intf; - cmd_update.res = hw_mgr_res->hw_res[i]; - cmd_update.cmd_type = - CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP; - hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, - CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, - &cmd_update, sizeof(cmd_update)); - break; - default: - break; - } - } - } -} - static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -5312,82 +5277,6 @@ static int cam_tfe_hw_mgr_handle_hw_rup( return 0; } -static int cam_tfe_hw_mgr_check_irq_for_dual_tfe( - struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx, - uint32_t hw_event_type) -{ - int32_t rc = -EINVAL; - uint32_t *event_cnt = NULL; - uint32_t master_hw_idx; - uint32_t slave_hw_idx; - - if (!tfe_hw_mgr_ctx->is_dual) - return 0; - - master_hw_idx = tfe_hw_mgr_ctx->master_hw_idx; - slave_hw_idx = tfe_hw_mgr_ctx->slave_hw_idx; - - switch (hw_event_type) { - case CAM_ISP_HW_EVENT_SOF: - event_cnt = tfe_hw_mgr_ctx->sof_cnt; - break; - case CAM_ISP_HW_EVENT_EPOCH: - event_cnt = tfe_hw_mgr_ctx->epoch_cnt; - break; - case CAM_ISP_HW_EVENT_EOF: - event_cnt = tfe_hw_mgr_ctx->eof_cnt; - break; - default: - return 0; - } - - if (event_cnt[master_hw_idx] == event_cnt[slave_hw_idx]) { - - event_cnt[master_hw_idx] = 0; - event_cnt[slave_hw_idx] = 0; - - return 0; - } - - if ((event_cnt[master_hw_idx] && - (event_cnt[master_hw_idx] - event_cnt[slave_hw_idx] > 1)) || - (event_cnt[slave_hw_idx] && - (event_cnt[slave_hw_idx] - event_cnt[master_hw_idx] > 1))) { - - if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt > 10) { - rc = -1; - return rc; - } - - CAM_ERR_RATE_LIMIT(CAM_ISP, - "One TFE could not generate hw event %d master id :%d slave id:%d", - hw_event_type, event_cnt[master_hw_idx], - event_cnt[slave_hw_idx]); - if (event_cnt[master_hw_idx] >= 2) { - event_cnt[master_hw_idx]--; - tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; - } - if (event_cnt[slave_hw_idx] >= 2) { - event_cnt[slave_hw_idx]--; - tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt++; - } - - if (tfe_hw_mgr_ctx->dual_tfe_irq_mismatch_cnt == 1) { - cam_tfe_mgr_ctx_irq_dump(tfe_hw_mgr_ctx); - trace_cam_delay_detect("ISP", "dual tfe irq mismatch", - CAM_DEFAULT_VALUE, tfe_hw_mgr_ctx->ctx_index, - CAM_DEFAULT_VALUE, CAM_DEFAULT_VALUE, - rc); - } - rc = 0; - } - - CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d", - hw_event_type); - - return rc; -} - static int cam_tfe_hw_mgr_handle_hw_epoch( void *ctx, void *evt_info) @@ -5396,22 +5285,16 @@ static int cam_tfe_hw_mgr_handle_hw_epoch( struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; cam_hw_event_cb_func tfe_hw_irq_epoch_cb; struct cam_isp_hw_epoch_event_data epoch_done_event_data; - int rc = 0; tfe_hw_irq_epoch_cb = tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EPOCH]; switch (event_info->res_id) { case CAM_ISP_HW_TFE_IN_CAMIF: - tfe_hw_mgr_ctx->epoch_cnt[event_info->hw_idx]++; - rc = cam_tfe_hw_mgr_check_irq_for_dual_tfe(tfe_hw_mgr_ctx, - CAM_ISP_HW_EVENT_EPOCH); - if (!rc) { - if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) - break; - tfe_hw_irq_epoch_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); - } + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hw_irq_epoch_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); break; case CAM_ISP_HW_TFE_IN_RDI0: @@ -5438,27 +5321,22 @@ static int cam_tfe_hw_mgr_handle_hw_sof( struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; cam_hw_event_cb_func tfe_hw_irq_sof_cb; struct cam_isp_hw_sof_event_data sof_done_event_data; - int rc = 0; tfe_hw_irq_sof_cb = tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF]; switch (event_info->res_id) { case CAM_ISP_HW_TFE_IN_CAMIF: - tfe_hw_mgr_ctx->sof_cnt[event_info->hw_idx]++; - rc = cam_tfe_hw_mgr_check_irq_for_dual_tfe(tfe_hw_mgr_ctx, - CAM_ISP_HW_EVENT_SOF); - if (!rc) { - cam_tfe_mgr_cmd_get_sof_timestamp(tfe_hw_mgr_ctx, - &sof_done_event_data.timestamp, - &sof_done_event_data.boot_time); + cam_tfe_mgr_cmd_get_sof_timestamp(tfe_hw_mgr_ctx, + &sof_done_event_data.timestamp, + &sof_done_event_data.boot_time); - if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) - break; + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + + tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); - tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); - } break; case CAM_ISP_HW_TFE_IN_RDI0: @@ -5494,22 +5372,17 @@ static int cam_tfe_hw_mgr_handle_hw_eof( struct cam_tfe_hw_mgr_ctx *tfe_hw_mgr_ctx = ctx; cam_hw_event_cb_func tfe_hw_irq_eof_cb; struct cam_isp_hw_eof_event_data eof_done_event_data; - int rc = 0; tfe_hw_irq_eof_cb = tfe_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EOF]; switch (event_info->res_id) { case CAM_ISP_HW_TFE_IN_CAMIF: - tfe_hw_mgr_ctx->eof_cnt[event_info->hw_idx]++; - rc = cam_tfe_hw_mgr_check_irq_for_dual_tfe(tfe_hw_mgr_ctx, - CAM_ISP_HW_EVENT_EOF); - if (!rc) { - if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) - break; - tfe_hw_irq_eof_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); - } + if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) + break; + tfe_hw_irq_eof_cb(tfe_hw_mgr_ctx->common.cb_priv, + CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + break; case CAM_ISP_HW_TFE_IN_RDI0: diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 81a4e19fcfa1..6ea17d74ec19 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -66,9 +66,6 @@ struct cam_tfe_hw_mgr_debug { * @cdm_cmd cdm base and length request pointer * @last_submit_bl_cmd last submiited CDM BL command data * @config_done_complete indicator for configuration complete - * @sof_cnt sof count value per core, used for dual TFE - * @epoch_cnt epoch count value per core, used for dual TFE - * @eof_cnt eof count value per core, used for dual TFE * @overflow_pending flat to specify the overflow is pending for the * context * @cdm_done flag to indicate cdm has finished writing shadow @@ -113,9 +110,6 @@ struct cam_tfe_hw_mgr_ctx { struct cam_cdm_bl_info last_submit_bl_cmd; struct completion config_done_complete; - uint32_t sof_cnt[CAM_TFE_HW_NUM_MAX]; - uint32_t epoch_cnt[CAM_TFE_HW_NUM_MAX]; - uint32_t eof_cnt[CAM_TFE_HW_NUM_MAX]; atomic_t overflow_pending; atomic_t cdm_done; uint32_t is_rdi_only_context; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 60b456e44fd3..cf1696540e3e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -2000,7 +2000,7 @@ static int cam_tfe_camif_resource_start( CAM_DBG(CAM_ISP, "hw id:%d RUP val:%d", camif_res->hw_intf->hw_idx, rsrc_data->reg_data->reg_update_cmd_data); - /* Disable sof irq debug flag */ + /* Disable sof irq debug flag */ rsrc_data->enable_sof_irq_debug = false; rsrc_data->irq_debug_cnt = 0; @@ -2012,9 +2012,10 @@ static int cam_tfe_camif_resource_start( rsrc_data->common_reg->diag_config); } - /* Enable the irq */ - cam_tfe_irq_config(core_info, rsrc_data->reg_data->subscribe_irq_mask, - CAM_TFE_TOP_IRQ_REG_NUM, true); + /* Enable the irq only for master or single tfe usecase */ + if (rsrc_data->sync_mode != CAM_ISP_HW_SYNC_SLAVE) + cam_tfe_irq_config(core_info, rsrc_data->reg_data->subscribe_irq_mask, + CAM_TFE_TOP_IRQ_REG_NUM, true); /* Program perf counters */ val = (1 << rsrc_data->reg_data->perf_cnt_start_cmd_shift) | From 33899faa8bf40f7ddd7909901f296d6b4115d120 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Wed, 14 Oct 2020 21:48:12 -0700 Subject: [PATCH 552/790] msm: camera: sensor: Power down in case of cci init failure Currently power down is not happening in case of cci_init failure. This can lead to corruption for the next power up, as power down did not happen for the previous session. This change does power down in case of cci failure and as a part of that it can power up resources correctly in next session. CRs-Fixed: 2797857 Change-Id: I9089222cb45834ae895903a4a3e21dd799beb3ed Signed-off-by: Jigarkumar Zala --- .../cam_sensor_module/cam_actuator/cam_actuator_core.c | 9 ++++++++- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c | 7 ++++++- drivers/cam_sensor_module/cam_ois/cam_ois_core.c | 9 ++++++++- drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c | 4 ++-- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c | 10 +++++++++- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 7ee27f9f5764..47a261808873 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -106,8 +106,15 @@ static int32_t cam_actuator_power_up(struct cam_actuator_ctrl_t *a_ctrl) } rc = camera_io_init(&a_ctrl->io_master_info); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "cci init failed: rc: %d", rc); + goto cci_failure; + } + + return rc; +cci_failure: + if (cam_sensor_util_power_down(power_info, soc_info)) + CAM_ERR(CAM_ACTUATOR, "Power down failure"); return rc; } diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index 8b9bd2adcb63..8e4270373331 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -185,10 +185,15 @@ static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl, rc = camera_io_init(&(e_ctrl->io_master_info)); if (rc) { CAM_ERR(CAM_EEPROM, "cci_init failed"); - return -EINVAL; + goto cci_failure; } } return rc; +cci_failure: + if (cam_sensor_util_power_down(power_info, soc_info)) + CAM_ERR(CAM_EEPROM, "Power down failure"); + + return rc; } /** diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 9130d595ed06..543f7a9f3eb2 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -153,8 +153,15 @@ static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl) } rc = camera_io_init(&o_ctrl->io_master_info); - if (rc) + if (rc) { CAM_ERR(CAM_OIS, "cci_init failed: rc: %d", rc); + goto cci_failure; + } + + return rc; +cci_failure: + if (cam_sensor_util_power_down(power_info, soc_info)) + CAM_ERR(CAM_OIS, "Power Down failed"); return rc; } diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index c5d6c1504fc8..52e164525244 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -462,8 +462,8 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio, CAM_DBG(CAM_RES, "gpio: %u not found in gpio_res list", gpio); rc = gpio_request_one(gpio, flags, label); if (rc) { - CAM_ERR(CAM_RES, "gpio %d:%s request fails", - gpio, label); + CAM_ERR(CAM_RES, "gpio %d:%s request fails rc = %d", + gpio, label, rc); goto end; } } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 2f2db1e05281..413b5405045d 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1197,10 +1197,18 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl) } rc = camera_io_init(&(s_ctrl->io_master_info)); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_SENSOR, "cci_init failed: rc: %d", rc); + goto cci_failure; + } return rc; +cci_failure: + if (cam_sensor_util_power_down(power_info, soc_info)) + CAM_ERR(CAM_SENSOR, "power down failure"); + + return rc; + } int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl) From 41cdb719fdff34734f12abdcaf8e6d0741211533 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 15 Oct 2020 14:34:10 +0530 Subject: [PATCH 553/790] msm: camera: sync: Increase V4l2 queue size to 250 For MFHDR plus EIS case, both long and short exposure input ports will be connected. Thus overall connected ports for EIS will be 8, resulting in V4L2 queue depth to 240. CRs-Fixed: 2794286 Change-Id: I12a1ae4129ccb7e3b7211a22891016ecd769b949 Signed-off-by: Shravya Samala --- drivers/cam_sync/cam_sync_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sync/cam_sync_private.h b/drivers/cam_sync/cam_sync_private.h index 27cdcdadb3b2..9a66e59f2593 100644 --- a/drivers/cam_sync/cam_sync_private.h +++ b/drivers/cam_sync/cam_sync_private.h @@ -30,7 +30,7 @@ #define CAM_SYNC_OBJ_NAME_LEN 64 #define CAM_SYNC_MAX_OBJS 2048 -#define CAM_SYNC_MAX_V4L2_EVENTS 100 +#define CAM_SYNC_MAX_V4L2_EVENTS 250 #define CAM_SYNC_DEBUG_FILENAME "cam_debug" #define CAM_SYNC_DEBUG_BASEDIR "cam" #define CAM_SYNC_DEBUG_BUF_SIZE 32 From 5155e8b6126459a2c205beacbcd6ce247118a43a Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 3 Sep 2020 17:38:27 +0530 Subject: [PATCH 554/790] msm: camera: tfe: TPG stop Call Move TPG stop call before checking if Deinit call is required or not. CRs-Fixed: 2777023 Change-Id: I9c7be620c2ba2762324129e547efc1d2a8dd6f40 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 01bfce100ce4..ebe69a1eac77 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -2844,15 +2844,15 @@ static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) wait_for_completion_timeout(&ctx->config_done_complete, msecs_to_jiffies(5)); + if (ctx->is_tpg) + cam_tfe_hw_mgr_stop_hw_res(&ctx->res_list_tpg); + if (stop_isp->stop_only) goto end; if (cam_cdm_stream_off(ctx->cdm_handle)) CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); - if (ctx->is_tpg) - cam_tfe_hw_mgr_stop_hw_res(&ctx->res_list_tpg); - cam_tfe_hw_mgr_deinit_hw(ctx); CAM_DBG(CAM_ISP, From bb2e9aaeb91a24f2ebb67c45d95b52da51d034d3 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 15 Oct 2020 14:49:59 +0530 Subject: [PATCH 555/790] msm: camera: tfe: Move the CSID irq logs to bottom half Remove the sof log in CSID irq handler and handle it in the Bottom half. Sof irq enabled during the sof freeze scenario and sof log getting printed in the irq handler causing the interrupt handling taking more time. CRs-Fixed: 2796120 Change-Id: I29341efcf0134f69b9dc8284785044ee08be13b6 Signed-off-by: Ravikishore Pampana --- .../isp_hw/tfe_csid_hw/cam_tfe_csid530.h | 1 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 141 ++++++++++-------- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 1 + 3 files changed, 84 insertions(+), 59 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h index 94267ca0d1d8..b0e9dc862c4d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h @@ -165,6 +165,7 @@ static struct cam_tfe_csid_csi2_rx_reg_offset .csi2_rx_phy_num_mask = 0x7, .csi2_rx_long_pkt_hdr_rst_stb_shift = 0x1, .csi2_rx_short_pkt_hdr_rst_stb_shift = 0x2, + .csi2_rx_cphy_pkt_hdr_rst_stb_shift = 0x3, }; static struct cam_tfe_csid_common_reg_offset diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 4aa783286a6f..136b4e382199 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -2334,7 +2334,8 @@ static int cam_tfe_csid_sof_irq_debug( if (csid_hw->hw_info->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_WARN(CAM_ISP, - "CSID powered down unable to %s sof irq", + "CSID:%d powered down unable to %s sof irq", + csid_hw->hw_intf->hw_idx, sof_irq_enable ? "enable" : "disable"); return 0; } @@ -2378,8 +2379,10 @@ static int cam_tfe_csid_sof_irq_debug( csid_hw->sof_irq_triggered = false; } - CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s", - sof_irq_enable ? "enabled" : "disabled"); + if (!in_irq()) + CAM_INFO(CAM_ISP, "SOF freeze: CSID:%d SOF irq %s", + csid_hw->hw_intf->hw_idx, + sof_irq_enable ? "enabled" : "disabled"); return 0; } @@ -2683,7 +2686,7 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, return rc; } -static int cam_csid_get_evt_payload( +static int cam_tfe_csid_get_evt_payload( struct cam_tfe_csid_hw *csid_hw, struct cam_csid_evt_payload **evt_payload) { @@ -2706,7 +2709,7 @@ static int cam_csid_get_evt_payload( return 0; } -static int cam_csid_put_evt_payload( +static int cam_tfe_csid_put_evt_payload( struct cam_tfe_csid_hw *csid_hw, struct cam_csid_evt_payload **evt_payload) { @@ -2725,35 +2728,17 @@ static int cam_csid_put_evt_payload( return 0; } -static char *cam_csid_status_to_str(uint32_t status) -{ - switch (status) { - case TFE_CSID_IRQ_REG_TOP: - return "TOP"; - case TFE_CSID_IRQ_REG_RX: - return "RX"; - case TFE_CSID_IRQ_REG_IPP: - return "IPP"; - case TFE_CSID_IRQ_REG_RDI0: - return "RDI0"; - case TFE_CSID_IRQ_REG_RDI1: - return "RDI1"; - case TFE_CSID_IRQ_REG_RDI2: - return "RDI2"; - default: - return "Invalid IRQ"; - } -} -static int cam_csid_evt_bottom_half_handler( +static int cam_tfe_csid_evt_bottom_half_handler( void *handler_priv, void *evt_payload_priv) { struct cam_tfe_csid_hw *csid_hw; struct cam_csid_evt_payload *evt_payload; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_isp_hw_event_info event_info; int i; int rc = 0; - struct cam_isp_hw_event_info event_info; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, @@ -2764,6 +2749,7 @@ static int cam_csid_evt_bottom_half_handler( csid_hw = (struct cam_tfe_csid_hw *)handler_priv; evt_payload = (struct cam_csid_evt_payload *)evt_payload_priv; + csid_reg = csid_hw->csid_info->csid_reg; if (!csid_hw->event_cb || !csid_hw->event_cb_priv) { CAM_ERR_RATE_LIMIT(CAM_ISP, @@ -2783,16 +2769,35 @@ static int cam_csid_evt_bottom_half_handler( goto end; } - CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d", - csid_hw->hw_intf->hw_idx, - evt_payload->evt_type, - csid_hw->csi2_rx_cfg.phy_sel); - - for (i = 0; i < TFE_CSID_IRQ_REG_MAX; i++) - CAM_ERR_RATE_LIMIT(CAM_ISP, "status %s: %x", - cam_csid_status_to_str(i), - evt_payload->irq_status[i]); + if (csid_hw->sof_irq_triggered && (evt_payload->evt_type == + CAM_ISP_HW_ERROR_NONE)) { + if (evt_payload->irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_INFO_INPUT_SOF) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + } + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + if (evt_payload->irq_status[i] & + TFE_CSID_PATH_INFO_INPUT_SOF) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d RDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); + } + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID %d err %d phy %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type, + csid_hw->csi2_rx_cfg.phy_sel, + evt_payload->irq_status[TFE_CSID_IRQ_REG_TOP], + evt_payload->irq_status[TFE_CSID_IRQ_REG_RX], + evt_payload->irq_status[TFE_CSID_IRQ_REG_IPP], + evt_payload->irq_status[TFE_CSID_IRQ_REG_RDI0], + evt_payload->irq_status[TFE_CSID_IRQ_REG_RDI1], + evt_payload->irq_status[TFE_CSID_IRQ_REG_RDI2]); + } /* this hunk can be extended to handle more cases * which we want to offload to bottom half from * irq handlers @@ -2810,17 +2815,17 @@ static int cam_csid_evt_bottom_half_handler( break; default: - CAM_DBG(CAM_ISP, "CSID[%d] invalid error type %d", + CAM_DBG(CAM_ISP, "CSID[%d] error type %d", csid_hw->hw_intf->hw_idx, evt_payload->evt_type); break; } end: - cam_csid_put_evt_payload(csid_hw, &evt_payload); + cam_tfe_csid_put_evt_payload(csid_hw, &evt_payload); return 0; } -static int cam_csid_handle_hw_err_irq( +static int cam_tfe_csid_handle_hw_err_irq( struct cam_tfe_csid_hw *csid_hw, int evt_type, uint32_t *irq_status) @@ -2833,7 +2838,7 @@ static int cam_csid_handle_hw_err_irq( CAM_DBG(CAM_ISP, "CSID[%d] error %d", csid_hw->hw_intf->hw_idx, evt_type); - rc = cam_csid_get_evt_payload(csid_hw, &evt_payload); + rc = cam_tfe_csid_get_evt_payload(csid_hw, &evt_payload); if (rc) { CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload core %d", @@ -2861,7 +2866,7 @@ static int cam_csid_handle_hw_err_irq( bh_cmd, csid_hw, evt_payload, - cam_csid_evt_bottom_half_handler); + cam_tfe_csid_evt_bottom_half_handler); return rc; } @@ -2874,7 +2879,7 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) const struct cam_tfe_csid_csi2_rx_reg_offset *csi2_reg; uint32_t irq_status[TFE_CSID_IRQ_REG_MAX]; bool fatal_err_detected = false, is_error_irq = false; - uint32_t sof_irq_debug_en = 0; + uint32_t sof_irq_debug_en = 0, log_en = 0; unsigned long flags; uint32_t i, val; @@ -3019,7 +3024,7 @@ handle_fatal_error: CAM_SUBDEV_MESSAGE_IRQ_ERR, (csid_hw->csi2_rx_cfg.phy_sel - 1)); } - cam_csid_handle_hw_err_irq(csid_hw, + cam_tfe_csid_handle_hw_err_irq(csid_hw, CAM_ISP_HW_ERROR_CSID_FATAL, irq_status); } @@ -3097,6 +3102,10 @@ handle_fatal_error: CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d long pkt cal CRC:%d expected CRC:%d", csid_hw->hw_intf->hw_idx, (val >> 16), (val & 0xFFFF)); + /* reset long pkt strobe to capture next long packet */ + val = (1 << csi2_reg->csi2_rx_long_pkt_hdr_rst_stb_shift); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_rst_strobes_addr); } if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) && (irq_status[TFE_CSID_IRQ_REG_RX] & @@ -3113,6 +3122,10 @@ handle_fatal_error: csi2_reg->csid_csi2_rx_captured_short_pkt_1_addr); CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d short packet ECC :%d", csid_hw->hw_intf->hw_idx, val); + /* reset short pkt strobe to capture next short packet */ + val = (1 << csi2_reg->csi2_rx_short_pkt_hdr_rst_stb_shift); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_rst_strobes_addr); } if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) && @@ -3126,6 +3139,10 @@ handle_fatal_error: "CSID:%d cphy packet VC :%d DT:%d WC:%d", csid_hw->hw_intf->hw_idx, (val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF)); + /* reset cphy pkt strobe to capture next short packet */ + val = (1 << csi2_reg->csi2_rx_cphy_pkt_hdr_rst_stb_shift); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_rst_strobes_addr); } if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_RST_IRQ_LOG) { @@ -3157,8 +3174,13 @@ handle_fatal_error: if ((irq_status[TFE_CSID_IRQ_REG_IPP] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP SOF received", - csid_hw->hw_intf->hw_idx); + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -3192,18 +3214,25 @@ handle_fatal_error: (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_RST_IRQ_LOG)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI%d reset complete", i); + "CSID:%d RDI%d reset complete", + csid_hw->hw_intf->hw_idx, i); if (irq_status[i] & BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) { - CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i); + CAM_DBG(CAM_ISP, "CSID:%d RDI%d reset complete", + csid_hw->hw_intf->hw_idx, i); complete(&csid_hw->csid_rdin_complete[i]); } if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI:%d SOF received", i); + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d RDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -3211,7 +3240,8 @@ handle_fatal_error: if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_EOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ)) { CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID RDI:%d EOF received", i); + "CSID:%d RDI:%d EOF received", + csid_hw->hw_intf->hw_idx, i); } if (irq_status[i] & TFE_CSID_PATH_ERROR_FIFO_OVERFLOW) { @@ -3228,16 +3258,9 @@ handle_fatal_error: is_error_irq = true; } - if (is_error_irq) - CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x", - csid_hw->hw_intf->hw_idx, - irq_status[TFE_CSID_IRQ_REG_TOP], - irq_status[TFE_CSID_IRQ_REG_RX], - irq_status[TFE_CSID_IRQ_REG_IPP], - irq_status[TFE_CSID_IRQ_REG_RDI0], - irq_status[TFE_CSID_IRQ_REG_RDI1], - irq_status[TFE_CSID_IRQ_REG_RDI2]); + if (is_error_irq || log_en) + cam_tfe_csid_handle_hw_err_irq(csid_hw, + CAM_ISP_HW_ERROR_NONE, irq_status); if (csid_hw->irq_debug_cnt >= CAM_TFE_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_tfe_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index 94783a7c813c..55d71df6fada 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -201,6 +201,7 @@ struct cam_tfe_csid_csi2_rx_reg_offset { uint32_t csi2_rx_phy_num_mask; uint32_t csi2_rx_long_pkt_hdr_rst_stb_shift; uint32_t csi2_rx_short_pkt_hdr_rst_stb_shift; + uint32_t csi2_rx_cphy_pkt_hdr_rst_stb_shift; }; struct cam_tfe_csid_common_reg_offset { From 975ced97e2cb8325fb2b1ffc1608d3918399c7c8 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Thu, 15 Oct 2020 07:46:11 -0700 Subject: [PATCH 556/790] msm: camera: csid: Fix the EOT IRQ Reception for Sensors with EPD Sensors with EPD feature do not subscribe to the ERROR_EOT IRQ. However, the CSID IRQ mask do not prevent from setting the IRQ status, it only prevents the IRQ from getting fired. Add check in csid irq to prevent detecting the EOT for Sensors with EPD. CRs-Fixed: 2798458 Change-Id: I8e029834918326b70154a989fbdff747de7851ed Signed-off-by: Jigar Agrawal --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 84a47891f570..febc58054032 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4927,8 +4927,9 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) fatal_err_detected = true; goto handle_fatal_error; } - if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & - CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) { + if ((irq_status[CAM_IFE_CSID_IRQ_REG_RX] & + CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) && + (!csid_hw->epd_supported)) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_EOT_RECEPTION", csid_hw->hw_intf->hw_idx); From bf2282bad6e6524815736c5fe3033e62fd22ea64 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 20 Oct 2020 14:00:43 -0700 Subject: [PATCH 557/790] msm: camera: smmu: Fix the smmu create_handle function Fix the smmu create_handle function to not generate null handles. CRs-Fixed: 2801574 Change-Id: Ia6de2b80915a8fd937d3745eb4c1f25ba16d21aa Signed-off-by: Jigar Agrawal --- drivers/cam_smmu/cam_smmu_api.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index c336c0230f2c..48ac8f0ebeb9 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -218,7 +218,7 @@ static struct cam_iommu_cb_set iommu_cb_set; static enum dma_data_direction cam_smmu_translate_dir( enum cam_smmu_map_dir dir); -static int cam_smmu_check_handle_unique(int hdl); +static bool cam_smmu_is_hdl_nonunique_or_null(int hdl); static int cam_smmu_create_iommu_handle(int idx); @@ -810,13 +810,12 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops) } } -static int cam_smmu_check_handle_unique(int hdl) +static bool cam_smmu_is_hdl_nonunique_or_null(int hdl) { int i; - if (hdl == HANDLE_INIT) { - CAM_DBG(CAM_SMMU, - "iommu handle is init number. Need to try again"); + if ((hdl == HANDLE_INIT) || (!hdl)) { + CAM_DBG(CAM_SMMU, "iommu handle: %d is not valid", hdl); return 1; } @@ -876,11 +875,12 @@ static int cam_smmu_create_add_handle_in_table(char *name, if (iommu_cb_set.cb_info[i].handle == HANDLE_INIT) { mutex_lock(&iommu_cb_set.cb_info[i].lock); - /* make sure handle is unique */ + /* make sure handle is unique and non-zero*/ do { handle = cam_smmu_create_iommu_handle(i); - } while (cam_smmu_check_handle_unique(handle)); + } while (cam_smmu_is_hdl_nonunique_or_null( + handle)); /* put handle in the table */ iommu_cb_set.cb_info[i].handle = handle; From 60d4dbf3de04e06135b0485711aa9789d13d4aa1 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 22 Oct 2020 13:18:59 +0530 Subject: [PATCH 558/790] msm: camera: tfe: Correct Configuration of top tpg mux selection In case of concurrent tpg use case, configure top tpg mux sel properly. CRs-Fixed: 2804168 Change-Id: I9955c9f03cebac854a339ff5161a99ecaf27cbdf Signed-off-by: Shravya Samala --- .../isp_hw/top_tpg/cam_top_tpg_ver1.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c index 8a657e753509..2f7d461383a9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c @@ -273,8 +273,14 @@ static int cam_top_tpg_ver1_start( soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); /* Set the TOP tpg mux sel*/ - cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx), + val = cam_io_r_mb(soc_info->reg_map[1].mem_base + + tpg_reg->top_mux_reg_offset); + val |= (1 << tpg_hw->hw_intf->hw_idx); + + cam_io_w_mb(val, soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); + CAM_DBG(CAM_ISP, "TPG:%d Set top Mux: 0x%x", + tpg_hw->hw_intf->hw_idx, val); val = ((tpg_data->num_active_lanes - 1) << tpg_reg->tpg_num_active_lines_shift) | @@ -307,6 +313,7 @@ static int cam_top_tpg_ver1_stop( struct cam_isp_resource_node *tpg_res; const struct cam_top_tpg_ver1_reg_offset *tpg_reg; struct cam_top_tpg_cfg *tpg_data; + uint32_t val; if (!hw_priv || !stop_args || (arg_size != sizeof(struct cam_isp_resource_node))) { @@ -333,6 +340,16 @@ static int cam_top_tpg_ver1_stop( cam_io_w_mb(0, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); + /* Reset the TOP tpg mux sel*/ + val = cam_io_r_mb(soc_info->reg_map[1].mem_base + + tpg_reg->top_mux_reg_offset); + val &= ~(1 << tpg_hw->hw_intf->hw_idx); + + cam_io_w_mb(val, + soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); + CAM_DBG(CAM_ISP, "TPG:%d Reset Top Mux: 0x%x", + tpg_hw->hw_intf->hw_idx, val); + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); From 353c16eb68fc6bc2eee0022c66b81431f82e9a81 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 22 Oct 2020 18:21:06 +0530 Subject: [PATCH 559/790] msm: camera: icp: remove the ioconfig dump during the error If io config send failure happens, currently dumping the io configuration for debug purpose. If more io configuration data is there, it will cause excessive logs. So removed io configuration dump in icp driver. On acquire failure, acquire node can dump the same. CRs-Fixed: 2800304 Change-Id: I4c6a7973eb789de8c3384311bce033070e07692f Signed-off-by: Ravikishore Pampana --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index f911901ad207..54a0914b4557 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -64,10 +64,11 @@ 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_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data, - int32_t buf_handle) + int32_t buf_handle, uint32_t size) { uintptr_t vaddr_ptr; uint32_t *ptr; + uint32_t io_size; size_t len; int rc, i; char buf[512]; @@ -80,13 +81,13 @@ static int cam_icp_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data, return rc; } - len = len / sizeof(uint32_t); + io_size = size / sizeof(uint32_t); ptr = (uint32_t *)vaddr_ptr; - for (i = 0; i < len; i++) { + for (i = 0; i < io_size; i++) { used += snprintf(buf + used, sizeof(buf) - used, "0X%08X-", ptr[i]); if (!(i % 8)) { - CAM_INFO(CAM_ICP, "%s: %s", __func__, buf); + CAM_DBG(CAM_ICP, "%s: %s", __func__, buf); used = 0; } } @@ -3936,8 +3937,14 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data, uint32_t size_in_words; task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); - if (!task) + if (!task) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "No free task ctx id:%d dev hdl:0x%x session hdl:0x%x dev_type:%d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); return -ENOMEM; + } ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async); ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT; @@ -3962,14 +3969,26 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data, CAM_DBG(CAM_ICP, "size_in_words %u", size_in_words); rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, CRM_TASK_PRIORITY_0); - if (rc) + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "Enqueue task failed ctx id:%d dev hdl:0x%x session hdl:0x%x dev_type:%d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); return rc; + } rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { - rc = -ETIMEDOUT; - CAM_ERR(CAM_ICP, "FW response timed out %d", rc); + /* send specific error for io config failure */ + rc = -EREMOTEIO; + CAM_ERR(CAM_ICP, + "FW response timed out %d ctx id:%d dev hdl:0x%x session hdl:0x%x dev_type:%d", + rc, + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } @@ -5683,9 +5702,12 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr); if (rc) { - CAM_ERR(CAM_ICP, "IO Config command failed %d", rc); + CAM_ERR_RATE_LIMIT(CAM_ICP, + "IO Config command failed %d size:%d", + rc, icp_dev_acquire_info->io_config_cmd_size); cam_icp_dump_io_cfg(ctx_data, - icp_dev_acquire_info->io_config_cmd_handle); + icp_dev_acquire_info->io_config_cmd_handle, + icp_dev_acquire_info->io_config_cmd_size); goto ioconfig_failed; } @@ -5703,16 +5725,29 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) bitmap_size = BITS_TO_LONGS(CAM_FRAME_CMD_MAX) * sizeof(long); ctx_data->hfi_frame_process.bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!ctx_data->hfi_frame_process.bitmap) + if (!ctx_data->hfi_frame_process.bitmap) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "hfi frame bitmap failed ctx id:%d dev hdl:0x%x session hdl:0x%x dev type %d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); goto ioconfig_failed; + } ctx_data->hfi_frame_process.bits = bitmap_size * BITS_PER_BYTE; hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb; icp_dev_acquire_info->scratch_mem_size = ctx_data->scratch_mem_size; if (copy_to_user((void __user *)args->acquire_info, - icp_dev_acquire_info, sizeof(struct cam_icp_acquire_dev_info))) + icp_dev_acquire_info, + sizeof(struct cam_icp_acquire_dev_info))) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "copy from user failed ctx id:%d dev hdl:0x%x session hdl:0x%x dev type %d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); goto copy_to_user_failed; + } cam_icp_ctx_clk_info_init(ctx_data); ctx_data->state = CAM_ICP_CTX_STATE_ACQUIRED; From d2639c26500423e52884a5a84cacf1ca9a771ad1 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 16 Oct 2020 15:23:04 -0700 Subject: [PATCH 560/790] msm: camera: sensor: Rename the dtsi entry to avoid the predefined string shared-pinctrl-gpios and shared-gpios needs to rename with gpios-shared and gpios-shared-pinctrl to avoid the predefined format of base kernel dtsi parsing string. Due to this there is a probe sequence delay happening and as it is hitting the boottime KPI badly. CRs-Fixed: 2804449 Change-Id: I26a0149ba1abb89b52750fb069e064642ca446f5 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 52e164525244..5165f6b2d1c9 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -760,7 +760,7 @@ static int cam_res_mgr_parse_dt_shared_gpio( of_node = dev->of_node; dt->num_shared_gpio = of_property_count_u32_elems(of_node, - "shared-gpios"); + "gpios-shared"); if (dt->num_shared_gpio <= 0) { CAM_DBG(CAM_RES, @@ -776,7 +776,7 @@ static int cam_res_mgr_parse_dt_shared_gpio( return -EINVAL; } - rc = of_property_read_u32_array(of_node, "shared-gpios", + rc = of_property_read_u32_array(of_node, "gpios-shared", dt->shared_gpio, dt->num_shared_gpio); if (rc) { CAM_ERR(CAM_RES, "Get shared gpio array failed."); @@ -796,7 +796,7 @@ static int cam_res_mgr_parse_dt_shared_pinctrl_gpio( of_node = dev->of_node; dt->num_shared_pctrl_gpio = of_property_count_u32_elems(of_node, - "shared-pinctrl-gpios"); + "gpios-shared-pinctrl"); if (dt->num_shared_pctrl_gpio <= 0) { CAM_DBG(CAM_RES, @@ -825,7 +825,7 @@ static int cam_res_mgr_parse_dt_shared_pinctrl_gpio( CAM_INFO(CAM_RES, "number of pctrl_gpio: %d", dt->num_shared_pctrl_gpio); - rc = of_property_read_u32_array(of_node, "shared-pinctrl-gpios", + rc = of_property_read_u32_array(of_node, "gpios-shared-pinctrl", dt->shared_pctrl_gpio, dt->num_shared_pctrl_gpio); if (rc) { CAM_ERR(CAM_RES, "Get shared pinctrl gpio array failed."); From 96a10ecb425802c49aa5f8fe4bf572ab956f0f63 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 6 Oct 2020 16:33:59 -0700 Subject: [PATCH 561/790] msm: camera: common: Enable flash operation at EOF Flash operation is currently being done at EPOCH timeframe. In order to support flash operation at EPOCH extra frame needs to skip to avoid partial lit on previous request. Moving flash operation to EOF saves one frame and also give more stability to perform the operation with higher stablility with removing partial lit. This change gives flash hardware extra time to perform the operation for turn on/off the flash hardware. CRs-Fixed: 2795719 Change-Id: I08b82527006d8a9c81c5a5be0768705051cbd3f1 Signed-off-by: Jigarkumar Zala Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 11 +++-------- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 9 +++------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 1be94c5d35be..35c2a504e856 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -558,6 +558,8 @@ static void __cam_req_mgr_flush_req_slot( in_q->rd_idx = 0; link->trigger_cnt[0] = 0; link->trigger_cnt[1] = 0; + link->trigger_mask = 0; + link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF; } /** @@ -811,12 +813,6 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, continue; } - if (slot->ops.apply_at_eof && slot->ops.skip_next_frame) { - CAM_ERR(CAM_CRM, - "Both EOF and SOF trigger is not supported"); - return -EINVAL; - } - if (dev->dev_hdl != slot->ops.dev_hdl) { CAM_DBG(CAM_CRM, "Dev_hdl : %d Not matched:: Expected dev_hdl: %d", @@ -2586,8 +2582,7 @@ int cam_req_mgr_process_add_req(void *priv, void *data) (add_req->skip_before_applying & 0xFF)); } - /* Used when Precise Flash is enabled */ - if ((add_req->trigger_eof) && (!add_req->skip_before_applying)) { + if (add_req->trigger_eof) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 15def761af55..caa1c83512ca 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1546,12 +1546,9 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) CAM_DBG(CAM_FLASH, "FLASH_CMD_TYPE op:%d", flash_data->opcode); - if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) - add_req.skip_before_applying |= SKIP_NEXT_FRAME; if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREDURATION) { - add_req.trigger_eof = true; /* Active time for the preflash */ flash_data->flash_active_time_ms = (flash_operation_info->time_on_duration_ns) @@ -1748,12 +1745,12 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) if ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS) { + add_req.skip_before_applying |= SKIP_NEXT_FRAME; + add_req.trigger_eof = true; + if ((flash_data->opcode != CAMERA_SENSOR_FLASH_OP_FIREDURATION)) add_req.skip_before_applying |= 1; - else if (flash_data->opcode == - CAMERA_SENSOR_FLASH_OP_FIREDURATION) - add_req.trigger_eof = true; else add_req.skip_before_applying = 0; } else { From dd78fbce96f13404005ea415f7454a4a8f3055f5 Mon Sep 17 00:00:00 2001 From: Ashwini Muduganti Date: Thu, 22 Oct 2020 02:20:53 +0530 Subject: [PATCH 562/790] msm: camera: crm: Add protection while destroying the link This change handles a race while destroying session. Protecting the session destroy with session lock. CRs-Fixed: 2799907 Change-Id: Ia1f90a56f6bfed00439b8012e41bfae9e8f739a3 Signed-off-by: Vikram Sharma Signed-off-by: Ashwini Muduganti --- drivers/cam_req_mgr/cam_req_mgr_core.c | 62 +++++++++++++++++--------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 1be94c5d35be..0eb61dbb29f2 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1116,8 +1116,8 @@ static int __cam_req_mgr_check_sync_for_mslave( int64_t req_id = 0, sync_req_id = 0; int32_t sync_num_slots = 0; - if (!sync_link) { - CAM_ERR(CAM_CRM, "Sync link null"); + if (!sync_link || !link) { + CAM_ERR(CAM_CRM, "Sync link or link is null"); return -EINVAL; } @@ -1323,20 +1323,21 @@ static int __cam_req_mgr_check_sync_req_is_ready( uint64_t master_slave_diff = 0; bool ready = true, sync_ready = true; - if (!sync_link) { + if (!sync_link ||!link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } req_id = slot->req_id; + sync_num_slots = sync_link->req.in_q->num_slots; - sync_rd_idx = sync_link->req.in_q->rd_idx; - sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; - sync_req_id = sync_rd_slot->req_id; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; CAM_DBG(CAM_REQ, - "link_hdl %x req %lld frame_skip_flag %d ", - link->link_hdl, req_id, link->sync_link_sof_skip); + "link_hdl %x sync link_hdl %x req %lld", + link->link_hdl, sync_link->link_hdl, req_id); if (sync_link->initial_skip) { link->initial_skip = false; @@ -1440,13 +1441,18 @@ static int __cam_req_mgr_check_sync_req_is_ready( ready = false; } - 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); - sync_ready = false; + if (sync_link->req.in_q) { + 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); + sync_ready = false; + } + } else { + CAM_ERR(CAM_CRM, "Sync link->req null"); + return -EINVAL; } /* @@ -1512,7 +1518,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EAGAIN; } } - CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); @@ -1526,8 +1531,20 @@ static int __cam_req_mgr_check_multi_sync_link_ready( { int i, rc = 0; + if (link->state == CAM_CRM_LINK_STATE_IDLE) { + CAM_ERR(CAM_CRM, "link state is idle %x", + link->state); + return -EINVAL; + } + for (i = 0; i < link->num_sync_links; i++) { if (link->sync_link[i]) { + if (link->sync_link[i]->state == + CAM_CRM_LINK_STATE_IDLE) { + CAM_ERR(CAM_CRM, "sync link state is idle %x", + link->sync_link[i]->state); + return -EINVAL; + } if (link->max_delay == link->sync_link[i]->max_delay) { rc = __cam_req_mgr_check_sync_req_is_ready( link, link->sync_link[i], slot); @@ -1558,6 +1575,9 @@ static int __cam_req_mgr_check_multi_sync_link_ready( return rc; } } + } else { + CAM_ERR(CAM_REQ, "Sync link is null"); + return -EINVAL; } } @@ -2839,7 +2859,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) spin_lock_bh(&link->link_state_spin_lock); if (link->state < CAM_CRM_LINK_STATE_READY) { - CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + CAM_WARN(CAM_CRM, "invalid link state:%d for link 0x%x", + link->state, link->link_hdl); spin_unlock_bh(&link->link_state_spin_lock); rc = -EPERM; goto release_lock; @@ -3622,17 +3643,18 @@ int cam_req_mgr_destroy_session( goto end; } + mutex_lock(&cam_session->lock); if (cam_session->num_links) { - CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d", + CAM_INFO(CAM_CRM, "destroy session %x num_active_links %d", ses_info->session_hdl, cam_session->num_links); for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { link = cam_session->links[i]; - if (!link) continue; + CAM_INFO(CAM_CRM, "Unlink link hdl 0x%x", link->link_hdl); /* Ignore return value since session is going away */ link->is_shutdown = is_shutdown; __cam_req_mgr_unlink(link); @@ -3640,7 +3662,7 @@ int cam_req_mgr_destroy_session( } } list_del(&cam_session->entry); - mutex_destroy(&cam_session->lock); + mutex_unlock(&cam_session->lock); kfree(cam_session); rc = cam_destroy_session_hdl(ses_info->session_hdl); From fde5d66e836925b047da021961b48baa0b3eba2f Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 13 Oct 2020 18:19:26 -0700 Subject: [PATCH 563/790] msm: camera: isp: Skip qtimer shutter for invalid req_id In order to reduce the traffic on the v4l2 queue, avoid posting qtimer shutter for bubbled frames. CRs-Fixed: 2799794 Change-Id: Id752605e7aff89246edfeec9337612bb7c9b4790 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 8fd7cb0d0c43..ba6ea97c8bcd 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -712,8 +712,7 @@ static void __cam_isp_ctx_send_sof_timestamp( { struct cam_req_mgr_message req_msg; - if ((ctx_isp->use_frame_header_ts) && (request_id) && - (sof_event_status == CAM_REQ_MGR_SOF_EVENT_SUCCESS)) + if ((ctx_isp->use_frame_header_ts) || (request_id == 0)) goto end; req_msg.session_hdl = ctx_isp->base->session_hdl; From 593ababe3a6d05b7b8e5602e2428d5f8a2d4076c Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Thu, 22 Oct 2020 15:25:28 -0700 Subject: [PATCH 564/790] msm: camera: icp: Tidy up hfi queue dump Two changes packed as one: refactor queue dump code and reformat dump output. The first should be self-explanatory. For the second, displaying one double word per line places an unnecessary burden on the reader. We can balance the vertical and horizontal space utilized for the dump by printing four double words at a time. Example: word[0000]: 0x00000008 0x00010001 0x00000008 0x00010002 word[0004]: 0x00000014 0x00010003 0x00000001 0x00000008 word[0008]: 0x00000001 0x00000020 0x00010003 0x00000001 word[0012]: 0x00000009 0x00007083 0x0001620f 0x00007083 word[0016]: 0x0001620f 0x00000018 0x00010003 0x00000001 word[0020]: 0x00000005 0x00000001 0x00010000 0x00000010 word[0024]: 0x00010005 0x84f07c60 0xffffffd8 0x0000001c word[0028]: 0x01010008 0x00000002 0x84f07c60 0xffffffd8 ... CRs-Fixed: 2805272 Change-Id: Ibc0ef955b5120ca2265cd1262fd91c124843dac0 Signed-off-by: Fernando Pacheco --- drivers/cam_icp/hfi.c | 87 ++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 9b9ea4bfc723..1d1d44b6a2f4 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -61,47 +61,76 @@ static void __iomem *hfi_iface_addr(struct hfi_info *hfi) return IS_ERR_OR_NULL(ret) ? NULL : ret; } +static void hfi_queue_dump(uint32_t *dwords, int count) +{ + int i; + int rows; + int remaining; + + rows = count / 4; + remaining = count % 4; + + for (i = 0; i < rows; i++, dwords += 4) + CAM_DBG(CAM_HFI, + "word[%04d]: 0x%08x 0x%08x 0x%08x 0x%08x", + i * 4, dwords[0], dwords[1], dwords[2], dwords[3]); + + if (remaining == 1) + CAM_DBG(CAM_HFI, "word[%04d]: 0x%08x", rows * 4, dwords[0]); + else if (remaining == 2) + CAM_DBG(CAM_HFI, "word[%04d]: 0x%08x 0x%08x", + rows * 4, dwords[0], dwords[1]); + else if (remaining == 3) + CAM_DBG(CAM_HFI, "word[%04d]: 0x%08x 0x%08x 0x%08x", + rows * 4, dwords[0], dwords[1], dwords[2]); +} + void cam_hfi_queue_dump(void) { + struct hfi_mem_info *hfi_mem = &g_hfi->map; struct hfi_qtbl *qtbl; - struct hfi_qtbl_hdr *qtbl_hdr; - struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr; - struct hfi_mem_info *hfi_mem = NULL; - uint32_t *read_q, *read_ptr; - int i; + struct hfi_q_hdr *q_hdr; + uint32_t *dwords; + int num_dwords; - hfi_mem = &g_hfi->map; if (!hfi_mem) { - CAM_ERR(CAM_HFI, "Unable to dump queues hfi memory is NULL"); + CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues"); return; } qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; - qtbl_hdr = &qtbl->q_tbl_hdr; CAM_DBG(CAM_HFI, - "qtbl: version = %x size = %u num q = %u qhdr_size = %u", - qtbl_hdr->qtbl_version, qtbl_hdr->qtbl_size, - qtbl_hdr->qtbl_num_q, qtbl_hdr->qtbl_qhdr_size); + "qtbl header: version=0x%08x tbl_size=%u numq=%u qhdr_size=%u", + qtbl->q_tbl_hdr.qtbl_version, + qtbl->q_tbl_hdr.qtbl_size, + qtbl->q_tbl_hdr.qtbl_num_q, + qtbl->q_tbl_hdr.qtbl_qhdr_size); - cmd_q_hdr = &qtbl->q_hdr[Q_CMD]; - CAM_DBG(CAM_HFI, "cmd: size = %u r_idx = %u w_idx = %u addr = %x", - cmd_q_hdr->qhdr_q_size, cmd_q_hdr->qhdr_read_idx, - cmd_q_hdr->qhdr_write_idx, hfi_mem->cmd_q.iova); - read_q = (uint32_t *)g_hfi->map.cmd_q.kva; - read_ptr = (uint32_t *)(read_q + 0); - CAM_DBG(CAM_HFI, "CMD Q START"); - for (i = 0; i < ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++) - CAM_DBG(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]); + q_hdr = &qtbl->q_hdr[Q_CMD]; + CAM_DBG(CAM_HFI, + "cmd_q: addr=0x%08x size=%u read_idx=%u write_idx=%u", + hfi_mem->cmd_q.iova, + q_hdr->qhdr_q_size, + q_hdr->qhdr_read_idx, + q_hdr->qhdr_write_idx); - msg_q_hdr = &qtbl->q_hdr[Q_MSG]; - CAM_DBG(CAM_HFI, "msg: size = %u r_idx = %u w_idx = %u addr = %x", - msg_q_hdr->qhdr_q_size, msg_q_hdr->qhdr_read_idx, - msg_q_hdr->qhdr_write_idx, hfi_mem->msg_q.iova); - read_q = (uint32_t *)g_hfi->map.msg_q.kva; - read_ptr = (uint32_t *)(read_q + 0); - CAM_DBG(CAM_HFI, "MSG Q START"); - for (i = 0; i < ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++) - CAM_DBG(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]); + dwords = (uint32_t *)hfi_mem->cmd_q.kva; + num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; + + hfi_queue_dump(dwords, num_dwords); + + q_hdr = &qtbl->q_hdr[Q_MSG]; + CAM_DBG(CAM_HFI, + "msg_q: addr=0x%08x size=%u read_idx=%u write_idx=%u", + hfi_mem->msg_q.iova, + q_hdr->qhdr_q_size, + q_hdr->qhdr_read_idx, + q_hdr->qhdr_write_idx); + + dwords = (uint32_t *)hfi_mem->msg_q.kva; + num_dwords = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; + + hfi_queue_dump(dwords, num_dwords); } int hfi_write_cmd(void *cmd_ptr) From 0bc1d527852155b8e0bc13e3175ac4590be7be1f Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 22 Oct 2020 02:20:53 +0530 Subject: [PATCH 565/790] msm: camera: reqmgr: Add protection while destroying the link This change handles a race while destroying session. Protecting the session destroy with session lock. CRs-Fixed: 2799907 Change-Id: Ia1f90a56f6bfed00439b8012e41bfae9e8f739a3 Signed-off-by: Vikram Sharma --- drivers/cam_req_mgr/cam_req_mgr_core.c | 93 ++++++++++++++++++++------ 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 1be94c5d35be..51f8d7828c18 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -314,6 +314,10 @@ static int __cam_req_mgr_notify_error_on_link( int rc = 0, pd; session = (struct cam_req_mgr_core_session *)link->parent; + if (!session) { + CAM_WARN(CAM_CRM, "session ptr NULL %x", link->link_hdl); + return -EINVAL; + } pd = dev->dev_info.p_delay; if (pd >= CAM_PIPELINE_DELAY_MAX) { @@ -1116,12 +1120,19 @@ static int __cam_req_mgr_check_sync_for_mslave( int64_t req_id = 0, sync_req_id = 0; int32_t sync_num_slots = 0; - if (!sync_link) { - CAM_ERR(CAM_CRM, "Sync link null"); + if (!sync_link || !link) { + CAM_ERR(CAM_CRM, "Sync link or link is null"); return -EINVAL; } req_id = slot->req_id; + + if (!sync_link->req.in_q) { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + sync_num_slots = sync_link->req.in_q->num_slots; sync_rd_idx = sync_link->req.in_q->rd_idx; @@ -1189,7 +1200,6 @@ static int __cam_req_mgr_check_sync_for_mslave( (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]", @@ -1323,20 +1333,27 @@ static int __cam_req_mgr_check_sync_req_is_ready( uint64_t master_slave_diff = 0; bool ready = true, sync_ready = true; - if (!sync_link) { + if (!sync_link || !link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } req_id = slot->req_id; + + if (!sync_link->req.in_q) { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + sync_num_slots = sync_link->req.in_q->num_slots; - sync_rd_idx = sync_link->req.in_q->rd_idx; - sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; - sync_req_id = sync_rd_slot->req_id; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; CAM_DBG(CAM_REQ, - "link_hdl %x req %lld frame_skip_flag %d ", - link->link_hdl, req_id, link->sync_link_sof_skip); + "link_hdl %x sync link_hdl %x req %lld", + link->link_hdl, sync_link->link_hdl, req_id); if (sync_link->initial_skip) { link->initial_skip = false; @@ -1440,13 +1457,20 @@ static int __cam_req_mgr_check_sync_req_is_ready( ready = false; } - 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); - sync_ready = false; + if (sync_link->req.in_q) { + 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 link: %x, rc=%d", + req_id, sync_link->link_hdl, rc); + sync_ready = false; + } + } else { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; } /* @@ -1512,7 +1536,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EAGAIN; } } - CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); @@ -1526,8 +1549,20 @@ static int __cam_req_mgr_check_multi_sync_link_ready( { int i, rc = 0; + if (link->state == CAM_CRM_LINK_STATE_IDLE) { + CAM_ERR(CAM_CRM, "link hdl %x is in idle state", + link->link_hdl); + return -EINVAL; + } + for (i = 0; i < link->num_sync_links; i++) { if (link->sync_link[i]) { + if (link->sync_link[i]->state == + CAM_CRM_LINK_STATE_IDLE) { + CAM_ERR(CAM_CRM, "sync link hdl %x is idle", + link->sync_link[i]->link_hdl); + return -EINVAL; + } if (link->max_delay == link->sync_link[i]->max_delay) { rc = __cam_req_mgr_check_sync_req_is_ready( link, link->sync_link[i], slot); @@ -1558,6 +1593,9 @@ static int __cam_req_mgr_check_multi_sync_link_ready( return rc; } } + } else { + CAM_ERR(CAM_REQ, "Sync link is null"); + return -EINVAL; } } @@ -1597,9 +1635,14 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *tmp_link = NULL; uint32_t max_retry = 0; - in_q = link->req.in_q; session = (struct cam_req_mgr_core_session *)link->parent; + if (!session) { + CAM_WARN(CAM_CRM, "session ptr NULL %x", link->link_hdl); + return -EINVAL; + } + mutex_lock(&session->lock); + in_q = link->req.in_q; /* * Check if new read index, * - if in pending state, traverse again to complete @@ -2016,6 +2059,10 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) link = (struct cam_req_mgr_core_link *)priv; session = (struct cam_req_mgr_core_session *)link->parent; + if (!session) { + CAM_WARN(CAM_CRM, "session ptr NULL %x", link->link_hdl); + return -EINVAL; + } spin_lock_bh(&link->link_state_spin_lock); if ((link->watchdog) && (link->watchdog->pause_timer)) { @@ -2278,6 +2325,7 @@ 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; + link->parent = NULL; i = link - g_links; CAM_DBG(CAM_CRM, "free link index %d", i); cam_req_mgr_core_link_reset(link); @@ -2839,7 +2887,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) spin_lock_bh(&link->link_state_spin_lock); if (link->state < CAM_CRM_LINK_STATE_READY) { - CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); + CAM_WARN(CAM_CRM, "invalid link state:%d for link 0x%x", + link->state, link->link_hdl); spin_unlock_bh(&link->link_state_spin_lock); rc = -EPERM; goto release_lock; @@ -3622,6 +3671,7 @@ int cam_req_mgr_destroy_session( goto end; } + mutex_lock(&cam_session->lock); if (cam_session->num_links) { CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d", ses_info->session_hdl, @@ -3629,10 +3679,11 @@ int cam_req_mgr_destroy_session( for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { link = cam_session->links[i]; - if (!link) continue; + CAM_DBG(CAM_CRM, "Unlink link hdl 0x%x", + link->link_hdl); /* Ignore return value since session is going away */ link->is_shutdown = is_shutdown; __cam_req_mgr_unlink(link); @@ -3640,7 +3691,9 @@ int cam_req_mgr_destroy_session( } } list_del(&cam_session->entry); + mutex_unlock(&cam_session->lock); mutex_destroy(&cam_session->lock); + kfree(cam_session); rc = cam_destroy_session_hdl(ses_info->session_hdl); From d1177505aea057a2a710b5892bf22b456eb9d285 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Sat, 17 Oct 2020 13:46:06 -0700 Subject: [PATCH 566/790] msm: camera: utils: Add option to not set src clk rate Clients like cpas scale some clocks like slow_ahb, fast_ahb through vote level based on other hw's src clk freq while the actual src clock (camnoc) is calculated and set directly through set_src_clk API. This will overwrite freq of camnoc_axi with the same level as AHB when ahb clocks are set. Do not set src clk rate while setting rate for other clocks using level. CRs-Fixed: 2793673 Change-Id: I5538a5cebf4e47c407a2bf9778136500b1162b4a Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 2 +- .../cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 2 +- drivers/cam_utils/cam_soc_util.c | 12 +++++++++++- drivers/cam_utils/cam_soc_util.h | 3 ++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index ca777c7a01bb..17c557fe3491 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1204,7 +1204,7 @@ static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw, if (cpas_core->streamon_clients) { rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info, - highest_level); + highest_level, true); if (rc) { CAM_ERR(CAM_CPAS, "Failed in scaling clock rate level %d for AHB", diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 704ffb0a24aa..6eda1796590d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1339,7 +1339,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev->ctrl_reg->getclockvoting( csiphy_dev, offset); rc = cam_soc_util_set_clk_rate_level( - &csiphy_dev->soc_info, clk_vote_level); + &csiphy_dev->soc_info, clk_vote_level, false); if (rc) { CAM_WARN(CAM_CSIPHY, "Failed to set the clk_rate level: %d", diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index db2dd9dd77f2..2371c5c1c068 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -907,7 +907,7 @@ end: } int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, - enum cam_vote_level clk_level) + enum cam_vote_level clk_level, bool do_not_set_src_clk) { int i, rc = 0; enum cam_vote_level apply_level; @@ -928,6 +928,16 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level); for (i = 0; i < soc_info->num_clk; i++) { + if (do_not_set_src_clk && (i == soc_info->src_clk_idx)) { + CAM_DBG(CAM_UTIL, "Skipping set rate for src clk %s", + soc_info->clk_name[i]); + continue; + } + + CAM_DBG(CAM_UTIL, "Set rate for clk %s rate %d", + soc_info->clk_name[i], + soc_info->clk_rate[apply_level][i]); + rc = cam_soc_util_set_clk_rate(soc_info->clk[i], soc_info->clk_name[i], soc_info->clk_rate[apply_level][i]); diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index 04e0e9136881..ff75fca12d5d 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -470,11 +470,12 @@ int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name, * * @soc_info: Device soc information * @clk_level: Clock level number to set + * @do_not_set_src_clk: If true, set clock rates except the src clk * * @return: Success or failure */ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, - enum cam_vote_level clk_level); + enum cam_vote_level clk_level, bool do_not_set_src_clk); /** * cam_soc_util_clk_disable() From 60ad5470c2ef703b0a3730c71a2c3e6c6d6ab4f4 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 21 Oct 2020 17:21:39 +0530 Subject: [PATCH 567/790] msm: camera: icp: Support NRT ipe clock bump-up Whenever there are NRT request then bump-up ipe clock to max. Clock will get reduced as part of context timer expires. CRs-Fixed: 2793751 Change-Id: I28a0b32bd52b58e293439042008711ea454a64f3 Signed-off-by: Alok Chauhan --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index f911901ad207..933859818b98 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1349,11 +1349,17 @@ static bool cam_icp_check_clk_update(struct cam_icp_hw_mgr *hw_mgr, if (!clk_info->frame_cycles) return cam_icp_default_clk_update(hw_mgr_clk_info); - /* Calculate base clk rate */ - base_clk = cam_icp_mgr_calc_base_clk( - clk_info->frame_cycles, clk_info->budget_ns); ctx_data->clk_info.rt_flag = clk_info->rt_flag; + /* Override base clock to max or calculate base clk rate */ + if (!ctx_data->clk_info.rt_flag && + (ctx_data->icp_dev_acquire_info->dev_type != + CAM_ICP_RES_TYPE_BPS)) + base_clk = ctx_data->clk_info.clk_rate[CAM_MAX_VOTE-1]; + else + base_clk = cam_icp_mgr_calc_base_clk(clk_info->frame_cycles, + clk_info->budget_ns); + if (busy) rc = cam_icp_update_clk_busy(hw_mgr, ctx_data, hw_mgr_clk_info, clk_info, base_clk); From 0dd46d80346ab89a3dbddb0877c503650f93256e Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 22 Oct 2020 18:21:06 +0530 Subject: [PATCH 568/790] msm: camera: icp: remove the ioconfig dump during the error If io config send failure happens, currently dumping the io configuration for debug purpose. If more io configuration data is there, it will cause excessive logs. So removed io configuration dump in icp driver. On acquire failure, acquire node can dump the same. CRs-Fixed: 2800304 Change-Id: I4c6a7973eb789de8c3384311bce033070e07692f Signed-off-by: Ravikishore Pampana --- .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index f911901ad207..54a0914b4557 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -64,10 +64,11 @@ 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_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data, - int32_t buf_handle) + int32_t buf_handle, uint32_t size) { uintptr_t vaddr_ptr; uint32_t *ptr; + uint32_t io_size; size_t len; int rc, i; char buf[512]; @@ -80,13 +81,13 @@ static int cam_icp_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data, return rc; } - len = len / sizeof(uint32_t); + io_size = size / sizeof(uint32_t); ptr = (uint32_t *)vaddr_ptr; - for (i = 0; i < len; i++) { + for (i = 0; i < io_size; i++) { used += snprintf(buf + used, sizeof(buf) - used, "0X%08X-", ptr[i]); if (!(i % 8)) { - CAM_INFO(CAM_ICP, "%s: %s", __func__, buf); + CAM_DBG(CAM_ICP, "%s: %s", __func__, buf); used = 0; } } @@ -3936,8 +3937,14 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data, uint32_t size_in_words; task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work); - if (!task) + if (!task) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "No free task ctx id:%d dev hdl:0x%x session hdl:0x%x dev_type:%d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); return -ENOMEM; + } ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async); ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT; @@ -3962,14 +3969,26 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data, CAM_DBG(CAM_ICP, "size_in_words %u", size_in_words); rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr, CRM_TASK_PRIORITY_0); - if (rc) + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "Enqueue task failed ctx id:%d dev hdl:0x%x session hdl:0x%x dev_type:%d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); return rc; + } rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete, msecs_to_jiffies((timeout))); if (!rem_jiffies) { - rc = -ETIMEDOUT; - CAM_ERR(CAM_ICP, "FW response timed out %d", rc); + /* send specific error for io config failure */ + rc = -EREMOTEIO; + CAM_ERR(CAM_ICP, + "FW response timed out %d ctx id:%d dev hdl:0x%x session hdl:0x%x dev_type:%d", + rc, + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl); cam_hfi_queue_dump(); } @@ -5683,9 +5702,12 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr); if (rc) { - CAM_ERR(CAM_ICP, "IO Config command failed %d", rc); + CAM_ERR_RATE_LIMIT(CAM_ICP, + "IO Config command failed %d size:%d", + rc, icp_dev_acquire_info->io_config_cmd_size); cam_icp_dump_io_cfg(ctx_data, - icp_dev_acquire_info->io_config_cmd_handle); + icp_dev_acquire_info->io_config_cmd_handle, + icp_dev_acquire_info->io_config_cmd_size); goto ioconfig_failed; } @@ -5703,16 +5725,29 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) bitmap_size = BITS_TO_LONGS(CAM_FRAME_CMD_MAX) * sizeof(long); ctx_data->hfi_frame_process.bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!ctx_data->hfi_frame_process.bitmap) + if (!ctx_data->hfi_frame_process.bitmap) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "hfi frame bitmap failed ctx id:%d dev hdl:0x%x session hdl:0x%x dev type %d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); goto ioconfig_failed; + } ctx_data->hfi_frame_process.bits = bitmap_size * BITS_PER_BYTE; hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb; icp_dev_acquire_info->scratch_mem_size = ctx_data->scratch_mem_size; if (copy_to_user((void __user *)args->acquire_info, - icp_dev_acquire_info, sizeof(struct cam_icp_acquire_dev_info))) + icp_dev_acquire_info, + sizeof(struct cam_icp_acquire_dev_info))) { + CAM_ERR_RATE_LIMIT(CAM_ICP, + "copy from user failed ctx id:%d dev hdl:0x%x session hdl:0x%x dev type %d", + ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle, + ctx_data->acquire_dev_cmd.session_handle, + ctx_data->icp_dev_acquire_info->dev_type); goto copy_to_user_failed; + } cam_icp_ctx_clk_info_init(ctx_data); ctx_data->state = CAM_ICP_CTX_STATE_ACQUIRED; From 6b90e928885a0e1d8ab7b92f9533b0d3199b9a36 Mon Sep 17 00:00:00 2001 From: chengxue Date: Mon, 28 Sep 2020 21:38:49 +0800 Subject: [PATCH 569/790] msm: camera: cci: Add back mutex on cci there should be a race condition on rd_done read/write between cam_cci_irq and cam_cci_read_bytes, add mutex to avoid. CRs-Fixed: 2786609 Change-Id: Ic55976133bfdc7958b4b3c8b0efdf896f82e7ccf Signed-off-by: chengxue --- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 0d1b90932eeb..6f41d870babf 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1725,8 +1725,10 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, * THRESHOLD irq's, we reinit the threshold wait before * we load the burst read cmd. */ + mutex_lock(&cci_dev->cci_master_info[master].mutex_q[QUEUE_1]); reinit_completion(&cci_dev->cci_master_info[master].rd_done); reinit_completion(&cci_dev->cci_master_info[master].th_complete); + mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[QUEUE_1]); CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes); do { From f3965d4eec11b481685b571ee3ddd3951641a5a1 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 16 Sep 2020 09:31:22 -0700 Subject: [PATCH 570/790] msm: camera: isp: Add UAPI changes for new VFE hardware Add UAPI definitions for output resources of new VFE hardware. Add changes to get the max output resource value based on hardware version, at the time of probe. CRs-Fixed: 2794540 Change-Id: I5f11be0546012c5f806153c2fd6b0aeb993f5d93 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 89 +++++++++++-------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 7 +- .../hw_utils/cam_isp_packet_parser.c | 5 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 15 ++++ .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 2 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 1 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 21 +++-- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 2 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 20 +++-- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 2 + include/uapi/camera/media/cam_isp_ife.h | 11 ++- 17 files changed, 120 insertions(+), 61 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index cce16d647687..40f1d24701e6 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -54,6 +54,8 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = { static struct cam_ife_hw_mgr g_ife_hw_mgr; +static uint32_t max_ife_out_res; + static int cam_ife_hw_mgr_event_handler( void *priv, uint32_t evt_id, @@ -507,7 +509,7 @@ static void cam_ife_hw_mgr_deinit_hw( } /* Deinit IFE OUT */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) + for (i = 0; i < max_ife_out_res; i++) cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]); ctx->init_done = false; @@ -583,7 +585,7 @@ static int cam_ife_hw_mgr_init_hw( CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d", ctx->ctx_index); - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (i = 0; i < max_ife_out_res; i++) { rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)", @@ -939,7 +941,7 @@ static void cam_ife_hw_mgr_dump_acq_data( } /* Iterate over IFE OUT resources */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (i = 0; i < max_ife_out_res; i++) { for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { hw_mgr_res = &hwr_mgr_ctx->res_list_ife_out[i]; hw_res = hw_mgr_res->hw_res[j]; @@ -1048,7 +1050,7 @@ static int cam_ife_hw_mgr_release_hw_for_ctx( struct cam_isp_hw_mgr_res *hw_mgr_res_temp; /* ife leaf resource */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) + for (i = 0; i < max_ife_out_res; i++) cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_out[i]); /* ife bus rd resource */ @@ -1308,7 +1310,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( for (i = 0; i < in_port->num_out_res; i++) { out_port = &in_port->data[i]; k = out_port->res_type & 0xFF; - if (k >= CAM_IFE_HW_OUT_RES_MAX) { + if (k >= max_ife_out_res) { CAM_ERR(CAM_ISP, "invalid output resource type 0x%x", out_port->res_type); continue; @@ -2262,7 +2264,7 @@ static int cam_ife_mgr_check_and_update_fe_v0( return -EINVAL; } - if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || + if ((in_port->num_out_res > max_ife_out_res) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", in_port->num_out_res); @@ -2325,7 +2327,7 @@ static int cam_ife_mgr_check_and_update_fe_v2( return -EINVAL; } - if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) || + if ((in_port->num_out_res > max_ife_out_res) || (in_port->num_out_res <= 0)) { CAM_ERR(CAM_ISP, "Invalid num output res %u", in_port->num_out_res); @@ -3390,7 +3392,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) u64_to_user_ptr(isp_resource[i].res_hdl), isp_resource[i].length); if (!IS_ERR(in_port)) { - if (in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) { + if (in_port->num_out_res > max_ife_out_res) { CAM_ERR(CAM_ISP, "too many output res %d", in_port->num_out_res); rc = -EINVAL; @@ -4057,7 +4059,7 @@ static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args) } /* IFE out resources */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) + for (i = 0; i < max_ife_out_res; i++) cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]); @@ -4210,7 +4212,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) CAM_DBG(CAM_ISP, "Going to stop IFE Out"); /* IFE out resources */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) + for (i = 0; i < max_ife_out_res; i++) cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]); CAM_DBG(CAM_ISP, "Going to stop IFE Mux"); @@ -4353,7 +4355,7 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args) cam_tasklet_start(ctx->common.tasklet_info); /* start the IFE out devices */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (i = 0; i < max_ife_out_res; i++) { rc = cam_ife_hw_mgr_start_hw_res( &ctx->res_list_ife_out[i], ctx); if (rc) { @@ -4421,7 +4423,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) uint32_t primary_rdi_out_res; primary_rdi_src_res = CAM_ISP_HW_VFE_IN_MAX; - primary_rdi_out_res = CAM_ISP_IFE_OUT_RES_MAX; + primary_rdi_out_res = g_ife_hw_mgr.max_vfe_out_res_type; if (!hw_mgr_priv || !start_isp) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -4491,7 +4493,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) if (g_ife_hw_mgr.debug_cfg.disable_ubwc_comp) { disable_ubwc_comp = 1; - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (i = 0; i < max_ife_out_res; i++) { hw_mgr_res = &ctx->res_list_ife_out[i]; for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { if (!hw_mgr_res->hw_res[i]) @@ -4553,7 +4555,7 @@ start_only: CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); /* start the IFE out devices */ - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (i = 0; i < max_ife_out_res; i++) { hw_mgr_res = &ctx->res_list_ife_out[i]; switch (hw_mgr_res->res_id) { case CAM_ISP_IFE_OUT_RES_RDI_0: @@ -4579,7 +4581,7 @@ start_only: } } - if (primary_rdi_out_res < CAM_ISP_IFE_OUT_RES_MAX) + if (primary_rdi_out_res < g_ife_hw_mgr.max_vfe_out_res_type) primary_rdi_src_res = cam_convert_rdi_out_res_id_to_src(primary_rdi_out_res); @@ -4909,7 +4911,7 @@ static int cam_isp_blob_ubwc_update( CAM_DBG(CAM_ISP, "UBWC config idx %d, port_type=%d", i, ubwc_plane_cfg->port_type); - if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + if (res_id_out >= max_ife_out_res) { CAM_ERR(CAM_ISP, "Invalid port type:%x", ubwc_plane_cfg->port_type); rc = -EINVAL; @@ -5079,7 +5081,7 @@ static int cam_isp_blob_ubwc_update_v2( CAM_DBG(CAM_ISP, "UBWC config idx %d, port_type=%d", i, ubwc_plane_cfg->port_type); - if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + if (res_id_out >= max_ife_out_res) { CAM_ERR(CAM_ISP, "Invalid port type:%x", ubwc_plane_cfg->port_type); rc = -EINVAL; @@ -5190,7 +5192,7 @@ static int cam_isp_blob_hfr_update( CAM_DBG(CAM_ISP, "hfr config idx %d, type=%d", i, res_id_out); - if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + if (res_id_out >= max_ife_out_res) { CAM_ERR(CAM_ISP, "invalid out restype:%x", port_hfr_config->resource_type); return -EINVAL; @@ -5645,7 +5647,7 @@ static int cam_isp_blob_vfe_out_update( CAM_DBG(CAM_ISP, "VFE out config idx: %d port: 0x%x", i, wm_config->port_type); - if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + if (res_id_out >= max_ife_out_res) { CAM_ERR(CAM_ISP, "Invalid out port:0x%x", wm_config->port_type); return -EINVAL; @@ -5832,7 +5834,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, hfr_config = (struct cam_isp_resource_hfr_config *)blob_data; - if (hfr_config->num_ports > CAM_ISP_IFE_OUT_RES_MAX || + if (hfr_config->num_ports > g_ife_hw_mgr.max_vfe_out_res_type || hfr_config->num_ports == 0) { CAM_ERR(CAM_ISP, "Invalid num_ports %u in HFR config", hfr_config->num_ports); @@ -6221,12 +6223,12 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, vfe_out_config = (struct cam_isp_vfe_out_config *)blob_data; - if (vfe_out_config->num_ports > CAM_IFE_HW_OUT_RES_MAX || + if (vfe_out_config->num_ports > max_ife_out_res || vfe_out_config->num_ports == 0) { CAM_ERR(CAM_ISP, "Invalid num_ports:%u in vfe out config", vfe_out_config->num_ports, - CAM_IFE_HW_OUT_RES_MAX); + max_ife_out_res); return -EINVAL; } @@ -6497,7 +6499,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, rc = cam_isp_add_command_buffers(prepare, &kmd_buf, &ctx->base[i], cam_isp_packet_generic_blob_handler, - ctx->res_list_ife_out, CAM_IFE_HW_OUT_RES_MAX); + ctx->res_list_ife_out, max_ife_out_res); if (rc) { CAM_ERR(CAM_ISP, "Failed in add cmdbuf, i=%d, split_id=%d, rc=%d", @@ -6521,7 +6523,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, prepare, ctx->base[i].idx, &kmd_buf, ctx->res_list_ife_out, &ctx->res_list_ife_in_rd, - CAM_IFE_HW_OUT_RES_MAX, fill_fence, + max_ife_out_res, fill_fence, &frame_header_info); if (rc) { @@ -6803,7 +6805,7 @@ static void cam_ife_mgr_pf_dump(uint32_t res_id, event_info.res_id = res_id; res_id_out = res_id & 0xFF; - if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) { + if (res_id_out >= max_ife_out_res) { CAM_ERR(CAM_ISP, "Invalid out resource id :%x", res_id); return; @@ -6891,7 +6893,7 @@ static void cam_ife_mgr_dump_pf_data( } mid_check: - for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { + for (i = 0; i < max_ife_out_res; i++) { hw_mgr_res = &ctx->res_list_ife_out[i]; if (!hw_mgr_res->hw_res[0]) continue; @@ -6899,7 +6901,7 @@ mid_check: break; } - if (i >= CAM_IFE_HW_OUT_RES_MAX) { + if (i >= max_ife_out_res) { CAM_ERR(CAM_ISP, "NO valid outport resources ctx id:%d req id:%lld", ctx->ctx_index, packet->header.request_id); @@ -8121,10 +8123,10 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { int rc = -EFAULT; int i, j; - bool support_consumed_addr = false; struct cam_iommu_handle cdm_handles; struct cam_ife_hw_mgr_ctx *ctx_pool; struct cam_isp_hw_mgr_res *res_list_ife_out; + struct cam_isp_hw_bus_cap isp_bus_cap = {0}; memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr)); @@ -8147,14 +8149,17 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) ife_device->hw_priv; struct cam_hw_soc_info *soc_info = &vfe_hw->soc_info; - if (j == 0) + if (j == 0) { ife_device->hw_ops.process_cmd( vfe_hw, - CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, - &support_consumed_addr, - sizeof(support_consumed_addr)); - j++; + CAM_ISP_HW_CMD_QUERY_BUS_CAP, + &isp_bus_cap, + sizeof(struct cam_isp_hw_bus_cap)); + CAM_DBG(CAM_ISP, "max VFE out resources: 0x%x", + isp_bus_cap.max_vfe_out_res_type); + } + j++; g_ife_hw_mgr.cdm_reg_map[i] = &soc_info->reg_map[0]; CAM_DBG(CAM_ISP, "reg_map: mem base = %pK cam_base = 0x%llx", @@ -8173,7 +8178,9 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return -EINVAL; } - g_ife_hw_mgr.support_consumed_addr = support_consumed_addr; + g_ife_hw_mgr.support_consumed_addr = isp_bus_cap.support_consumed_addr; + g_ife_hw_mgr.max_vfe_out_res_type = isp_bus_cap.max_vfe_out_res_type; + max_ife_out_res = g_ife_hw_mgr.max_vfe_out_res_type & 0xFF; /* fill csid hw intf information */ for (i = 0, j = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { @@ -8253,7 +8260,15 @@ 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_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++) { + ctx_pool->res_list_ife_out = kzalloc((max_ife_out_res * + sizeof(struct cam_isp_hw_mgr_res)), GFP_KERNEL); + if (!ctx_pool->res_list_ife_out) { + rc = -ENOMEM; + CAM_ERR(CAM_ISP, "Alloc failed for ife out res list"); + goto end; + } + + for (j = 0; j < max_ife_out_res; j++) { res_list_ife_out = &ctx_pool->res_list_ife_out[j]; INIT_LIST_HEAD(&res_list_ife_out->list); } @@ -8329,6 +8344,8 @@ end: &g_ife_hw_mgr.mgr_common.tasklet_pool[i]); kfree(g_ife_hw_mgr.ctx_pool[i].cdm_cmd); g_ife_hw_mgr.ctx_pool[i].cdm_cmd = NULL; + kfree(g_ife_hw_mgr.ctx_pool[i].res_list_ife_out); + g_ife_hw_mgr.ctx_pool[i].res_list_ife_out = NULL; g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = NULL; } } @@ -8354,6 +8371,8 @@ void cam_ife_hw_mgr_deinit(void) &g_ife_hw_mgr.mgr_common.tasklet_pool[i]); kfree(g_ife_hw_mgr.ctx_pool[i].cdm_cmd); g_ife_hw_mgr.ctx_pool[i].cdm_cmd = NULL; + kfree(g_ife_hw_mgr.ctx_pool[i].res_list_ife_out); + g_ife_hw_mgr.ctx_pool[i].res_list_ife_out = NULL; g_ife_hw_mgr.ctx_pool[i].common.tasklet_info = NULL; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index ba6c594025d1..f7f5461124f0 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -17,7 +17,6 @@ /* IFE resource constants */ #define CAM_IFE_HW_IN_RES_MAX (CAM_ISP_IFE_IN_RES_MAX & 0xFF) -#define CAM_IFE_HW_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_MAX & 0xFF) #define CAM_IFE_HW_RES_POOL_MAX 64 /* IFE_HW_MGR custom config */ @@ -122,9 +121,7 @@ struct cam_ife_hw_mgr_ctx { struct list_head res_list_ife_csid; struct list_head res_list_ife_src; struct list_head res_list_ife_in_rd; - struct cam_isp_hw_mgr_res res_list_ife_out[ - CAM_IFE_HW_OUT_RES_MAX]; - + struct cam_isp_hw_mgr_res *res_list_ife_out; struct list_head free_res_list; struct cam_isp_hw_mgr_res res_pool[CAM_IFE_HW_RES_POOL_MAX]; @@ -182,6 +179,7 @@ struct cam_ife_hw_mgr_ctx { * @ctx_lock context lock * @support_consumed_addr indicate whether hw supports last consumed address * @hw_pid_support hw pid support for this target + * @max_vfe_out_res_type max ife out res type value from hw */ struct cam_ife_hw_mgr { struct cam_isp_hw_mgr mgr_common; @@ -204,6 +202,7 @@ struct cam_ife_hw_mgr { spinlock_t ctx_lock; bool support_consumed_addr; bool hw_pid_support; + uint32_t max_vfe_out_res_type; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 384970891721..3e39ce2fa5ad 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -132,7 +132,7 @@ static int cam_isp_update_dual_config( } for (i = 0; i < dual_config->num_ports; i++) { - if (i >= CAM_ISP_IFE_OUT_RES_MAX) { + if (i >= CAM_ISP_IFE_OUT_RES_BASE + size_isp_out) { CAM_ERR(CAM_ISP, "failed update for i:%d > size_isp_out:%d", i, size_isp_out); @@ -151,7 +151,8 @@ static int cam_isp_update_dual_config( res = hw_mgr_res->hw_res[j]; if (res->res_id < CAM_ISP_IFE_OUT_RES_BASE || - res->res_id >= CAM_ISP_IFE_OUT_RES_MAX) + res->res_id >= (CAM_ISP_IFE_OUT_RES_BASE + + size_isp_out)) continue; outport_id = res->res_id & 0xFF; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index e01bfeb20b5a..2e5be6f75d5a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -135,6 +135,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, CAM_ISP_HW_CMD_DISABLE_UBWC_COMP, CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG, + CAM_ISP_HW_CMD_QUERY_BUS_CAP, CAM_ISP_HW_CMD_MAX, }; @@ -377,4 +378,18 @@ struct cam_isp_hw_intf_data { uint32_t num_hw_pid; uint32_t hw_pid[CAM_ISP_HW_MAX_PID_VAL]; }; +/** + * struct cam_isp_hw_bus_cap: + * + * @Brief: ISP hw bus capabilities + * + * @support_consumed_addr: Indicate whether HW has last consumed addr reg + * @max_vfe_out_res_type: Maximum value of out resource type supported by hw + * + */ +struct cam_isp_hw_bus_cap { + bool support_consumed_addr; + uint32_t max_vfe_out_res_type; +}; + #endif /* _CAM_ISP_HW_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index f4cc7102d973..fa0a6b6221d9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -616,9 +616,9 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: - case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: case CAM_ISP_HW_CMD_GET_RES_FOR_MID: case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: + case CAM_ISP_HW_CMD_QUERY_BUS_CAP: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index aa42c874e40f..e9b21e3b2eaa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -861,6 +861,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { }, .top_irq_shift = 9, .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 19, }; static struct cam_vfe_hw_info cam_vfe170_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h index 670316b85c95..7be90ea08257 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h @@ -829,6 +829,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_150_bus_hw_info = { }, }, .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 19, }; static struct cam_vfe_hw_info cam_vfe170_150_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index 7b7dee78b9f8..2328bf9f818e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -1022,6 +1022,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { }, .top_irq_shift = 9, .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 23, }; static struct cam_vfe_hw_info cam_vfe175_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index dd74b028f934..84fff673a597 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -1137,6 +1137,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { }, .top_irq_shift = 9, .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 23, }; static struct cam_vfe_hw_info cam_vfe175_130_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index bd0390e04aa5..7caa1eea1ee4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1349,6 +1349,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .comp_done_shift = 6, .top_irq_shift = 7, .support_consumed_addr = true, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 25, }; static struct cam_irq_register_set vfe480_bus_rd_irq_reg[1] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index dbe17815130c..19d4ff383ef6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -334,6 +334,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe17x_bus_hw_info = { }, .top_irq_shift = 9, .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 23, }; static struct cam_vfe_hw_info cam_vfe_lite17x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 5478bb021dc8..c118c8020292 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -400,6 +400,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .comp_done_shift = 4, .top_irq_shift = 4, .support_consumed_addr = true, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 25, }; static struct cam_vfe_hw_info cam_vfe_lite48x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 935ed271d86b..c7e77ac65e71 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -201,6 +201,7 @@ struct cam_vfe_bus_ver2_priv { int irq_handle; int error_irq_handle; void *tasklet_info; + uint32_t max_out_res; }; static int cam_vfe_bus_process_cmd( @@ -3394,7 +3395,7 @@ static int cam_vfe_bus_update_stripe_cfg(void *priv, void *cmd_args, outport_id = stripe_args->res->res_id & 0xFF; if (stripe_args->res->res_id < CAM_ISP_IFE_OUT_RES_BASE || - stripe_args->res->res_id >= CAM_ISP_IFE_OUT_RES_MAX) + stripe_args->res->res_id >= bus_priv->max_out_res) return 0; ports_plane_idx = (stripe_args->split_id * @@ -3637,7 +3638,8 @@ static int cam_vfe_bus_process_cmd( int rc = -EINVAL; struct cam_vfe_bus_ver2_priv *bus_priv; uint32_t top_mask_0 = 0; - bool *support_consumed_addr; + struct cam_isp_hw_bus_cap *vfe_bus_cap; + if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3684,12 +3686,6 @@ static int cam_vfe_bus_process_cmd( cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->top_irq_mask_0); break; - case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: - bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; - support_consumed_addr = (bool *)cmd_args; - *support_consumed_addr = - bus_priv->common_data.support_consumed_addr; - break; case CAM_ISP_HW_CMD_GET_RES_FOR_MID: bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); @@ -3697,6 +3693,14 @@ static int cam_vfe_bus_process_cmd( case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; bus_priv->common_data.disable_ubwc_comp = true; + break; + case CAM_ISP_HW_CMD_QUERY_BUS_CAP: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + vfe_bus_cap = (struct cam_isp_hw_bus_cap *) cmd_args; + vfe_bus_cap->max_vfe_out_res_type = bus_priv->max_out_res; + vfe_bus_cap->support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", @@ -3749,6 +3753,7 @@ int cam_vfe_bus_ver2_init( bus_priv->num_client = ver2_hw_info->num_client; bus_priv->num_out = ver2_hw_info->num_out; bus_priv->top_irq_shift = ver2_hw_info->top_irq_shift; + bus_priv->max_out_res = ver2_hw_info->max_out_res; 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; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index a9d4168c9086..64884f184077 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -182,6 +182,7 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info { * @vfe_out_hw_info: VFE output capability * @top_irq_shift: Mask shift for top level BUS WR irq * @support_consumed_addr: Indicate if bus support consumed address + * @max_out_res: Max vfe out resource value supported for hw */ struct cam_vfe_bus_ver2_hw_info { struct cam_vfe_bus_ver2_reg_offset_common common_reg; @@ -195,6 +196,7 @@ struct cam_vfe_bus_ver2_hw_info { vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; uint32_t top_irq_shift; bool support_consumed_addr; + uint32_t max_out_res; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index c8668b696a03..4202fbfe17b2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -198,6 +198,7 @@ struct cam_vfe_bus_ver3_priv { int rup_irq_handle; int error_irq_handle; void *tasklet_info; + uint32_t max_out_res; }; static const struct cam_vfe_bus_error_info vfe_error_list[] = { @@ -3497,7 +3498,7 @@ static int cam_vfe_bus_ver3_update_stripe_cfg(void *priv, void *cmd_args, outport_id = stripe_args->res->res_id & 0xFF; if (stripe_args->res->res_id < CAM_ISP_IFE_OUT_RES_BASE || - stripe_args->res->res_id >= CAM_ISP_IFE_OUT_RES_MAX) + stripe_args->res->res_id >= bus_priv->max_out_res) return 0; ports_plane_idx = (stripe_args->split_id * @@ -3778,7 +3779,8 @@ static int cam_vfe_bus_ver3_process_cmd( int rc = -EINVAL; struct cam_vfe_bus_ver3_priv *bus_priv; uint32_t top_mask_0 = 0; - bool *support_consumed_addr; + struct cam_isp_hw_bus_cap *vfe_bus_cap; + if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3836,12 +3838,6 @@ static int cam_vfe_bus_ver3_process_cmd( cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->top_irq_mask_0); break; - case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: - bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; - support_consumed_addr = (bool *)cmd_args; - *support_consumed_addr = - bus_priv->common_data.support_consumed_addr; - break; case CAM_ISP_HW_CMD_GET_RES_FOR_MID: bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); @@ -3850,6 +3846,13 @@ static int cam_vfe_bus_ver3_process_cmd( bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; bus_priv->common_data.disable_ubwc_comp = true; break; + case CAM_ISP_HW_CMD_QUERY_BUS_CAP: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + vfe_bus_cap = (struct cam_isp_hw_bus_cap *) cmd_args; + vfe_bus_cap->max_vfe_out_res_type = bus_priv->max_out_res; + vfe_bus_cap->support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3909,6 +3912,7 @@ int cam_vfe_bus_ver3_init( bus_priv->num_client = ver3_hw_info->num_client; bus_priv->num_out = ver3_hw_info->num_out; bus_priv->top_irq_shift = ver3_hw_info->top_irq_shift; + bus_priv->max_out_res = ver3_hw_info->max_out_res; 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; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index e713b26f6de7..dbc7a8c15a51 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -176,6 +176,7 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { * @comp_done_shift: Mask shift for comp done mask * @top_irq_shift: Mask shift for top level BUS WR irq * @support_consumed_addr: Indicate if bus support consumed address + * @max_out_res: Max vfe out resource value supported for hw */ struct cam_vfe_bus_ver3_hw_info { struct cam_vfe_bus_ver3_reg_offset_common common_reg; @@ -188,6 +189,7 @@ struct cam_vfe_bus_ver3_hw_info { uint32_t comp_done_shift; uint32_t top_irq_shift; bool support_consumed_addr; + uint32_t max_out_res; }; /* diff --git a/include/uapi/camera/media/cam_isp_ife.h b/include/uapi/camera/media/cam_isp_ife.h index 28a21140d87b..92a0f3e913c4 100644 --- a/include/uapi/camera/media/cam_isp_ife.h +++ b/include/uapi/camera/media/cam_isp_ife.h @@ -34,9 +34,14 @@ #define CAM_ISP_IFE_OUT_RES_2PD (CAM_ISP_IFE_OUT_RES_BASE + 22) #define CAM_ISP_IFE_OUT_RES_RDI_RD (CAM_ISP_IFE_OUT_RES_BASE + 23) #define CAM_ISP_IFE_OUT_RES_LCR (CAM_ISP_IFE_OUT_RES_BASE + 24) - -#define CAM_ISP_IFE_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_BASE + 25) - +#define CAM_ISP_IFE_OUT_RES_SPARSE_PD (CAM_ISP_IFE_OUT_RES_BASE + 25) +#define CAM_ISP_IFE_OUT_RES_2PD_STATS (CAM_ISP_IFE_OUT_RES_BASE + 26) +#define CAM_ISP_IFE_OUT_RES_AWB_BFW (CAM_ISP_IFE_OUT_RES_BASE + 27) +#define CAM_ISP_IFE_OUT_RES_STATS_AEC_BE (CAM_ISP_IFE_OUT_RES_BASE + 28) +#define CAM_ISP_IFE_OUT_RES_LTM_STATS (CAM_ISP_IFE_OUT_RES_BASE + 29) +#define CAM_ISP_IFE_OUT_RES_STATS_GTM_BHIST (CAM_ISP_IFE_OUT_RES_BASE + 30) +#define CAM_ISP_IFE_LITE_OUT_RES_STATS_BE (CAM_ISP_IFE_OUT_RES_BASE + 31) +#define CAM_ISP_IFE_LITE_OUT_RES_GAMMA (CAM_ISP_IFE_OUT_RES_BASE + 32) /* IFE input port resource type (global unique) */ #define CAM_ISP_IFE_IN_RES_BASE 0x4000 From c57b4483bc3eef23a6455c8e29f15d6a71818d16 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 6 May 2020 03:34:47 -0700 Subject: [PATCH 571/790] msm: camera: vfe: Add support for new VFE hardware This change adds hardware information for VFE version 680 hardware. CRs-Fixed: 2794540 Change-Id: I0c2f3cceca5d40cece1312a21f984a9f14f80a9a Signed-off-by: Vishalsingh Hajeri Signed-off-by: Venkat Chinta Signed-off-by: Mukund Madhusudan Atre --- .../isp_hw/vfe_hw/vfe17x/cam_vfe680.h | 1306 +++++++++++++++++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h | 235 +++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 16 +- .../vfe_hw/vfe_top/include/cam_vfe_top.h | 3 +- 4 files changed, 1557 insertions(+), 3 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h new file mode 100644 index 000000000000..2883d9ca6907 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h @@ -0,0 +1,1306 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_VFE680_H_ +#define _CAM_VFE680_H_ +#include "cam_vfe_camif_ver3.h" +#include "cam_vfe_top_ver3.h" +#include "cam_vfe_core.h" +#include "cam_vfe_bus_ver3.h" +#include "cam_irq_controller.h" + +static struct cam_irq_register_set vfe680_top_irq_reg_set[3] = { + { + .mask_reg_offset = 0x00000034, + .clear_reg_offset = 0x0000003c, + .status_reg_offset = 0x00000044, + }, + { + .mask_reg_offset = 0x00000038, + .clear_reg_offset = 0x00000040, + .status_reg_offset = 0x00000048, + }, +}; + +static struct cam_irq_controller_reg_info vfe680_top_irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe680_top_irq_reg_set, + .global_clear_offset = 0x00000030, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_top_ver3_reg_offset_common vfe680_top_common_reg = { + .hw_version = 0x00000000, + .hw_capability = 0x00000004, + .lens_feature = 0x00000008, + .stats_feature = 0x0000000C, + .color_feature = 0x00000010, + .zoom_feature = 0x00000014, + .core_cfg_0 = 0x00000024, + .core_cfg_1 = 0x00000028, + .core_cfg_2 = 0x0000002C, + .global_reset_cmd = 0x00000030, + .diag_config = 0x00000050, + .diag_sensor_status_0 = 0x00000054, + .diag_sensor_status_1 = 0x00000058, + .diag_frm_cnt_status_0 = 0x0000005C, + .diag_frm_cnt_status_1 = 0x00000060, + .violation_status = 0x00000064, + .core_cfg_3 = 0x00000068, + .core_cgc_ovd_0 = 0x00000018, + .core_cgc_ovd_1 = 0x0000001C, + .ahb_cgc_ovd = 0x00000020, + .dsp_status = 0x0000006C, + .stats_throttle_cfg_0 = 0x00000070, + .stats_throttle_cfg_1 = 0x00000074, + .stats_throttle_cfg_2 = 0x00000078, + .core_cfg_4 = 0x00000080, + .core_cfg_5 = 0x00000084, + .core_cfg_6 = 0x00000088, + .period_cfg = 0x0000008C, + .irq_sub_pattern_cfg = 0x00000090, + .epoch0_pattern_cfg = 0x00000094, + .epoch1_pattern_cfg = 0x00000098, + .epoch_height_cfg = 0x0000009C, + .bus_overflow_status = 0x0000AA68, + .top_debug_cfg = 0x000000FC, + .top_debug_0 = 0x000000A0, + .top_debug_1 = 0x000000A4, + .top_debug_2 = 0x000000A8, + .top_debug_3 = 0x000000AC, + .top_debug_4 = 0x000000B0, + .top_debug_5 = 0x000000B4, + .top_debug_6 = 0x000000B8, + .top_debug_7 = 0x000000BC, + .top_debug_8 = 0x000000C0, + .top_debug_9 = 0x000000C4, + .top_debug_10 = 0x000000C8, + .top_debug_11 = 0x000000CC, + .top_debug_12 = 0x000000D0, + .top_debug_13 = 0x000000D4, + .top_debug_14 = 0x000000D8, + .top_debug_15 = 0x000000DC, + .top_debug_16 = 0x000000E0, +}; + + +static struct cam_vfe_top_ver3_hw_info vfe680_top_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_reg = &vfe480_camif_reg, + .reg_data = &vfe_480_camif_reg_data, + }, + .pdlib_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_pd, + .reg_data = &vfe480_camif_pd_reg_data, + }, + .rdi_hw_info[0] = &rdi_hw_info_arr[0], + .rdi_hw_info[1] = &rdi_hw_info_arr[1], + .rdi_hw_info[2] = &rdi_hw_info_arr[2], + .lcr_hw_info = { + .common_reg = &vfe480_top_common_reg, + .camif_lite_reg = &vfe480_camif_lcr, + .reg_data = &vfe480_camif_lcr_reg_data, + }, + .num_mux = 6, + .mux_type = { + CAM_VFE_CAMIF_VER_3_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_RDI_VER_1_0, + CAM_VFE_PDLIB_VER_1_0, + CAM_VFE_LCR_VER_1_0, + }, +}; + +static struct cam_irq_register_set vfe680_bus_irq_reg[2] = { + { + .mask_reg_offset = 0x00000C18, + .clear_reg_offset = 0x00000C20, + .status_reg_offset = 0x00000C28, + }, + { + .mask_reg_offset = 0x00000C1C, + .clear_reg_offset = 0x00000C24, + .status_reg_offset = 0x00000C2C, + }, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe680_ubwc_regs_client_0 = { + .meta_addr = 0x00000E40, + .meta_cfg = 0x00000E44, + .mode_cfg = 0x00000E48, + .stats_ctrl = 0x00000E4C, + .ctrl_2 = 0x00000E50, + .lossy_thresh0 = 0x00000E54, + .lossy_thresh1 = 0x00000E58, + .off_lossy_var = 0x00000E5C, + .bw_limit = 0x00000E1C, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe680_ubwc_regs_client_1 = { + .meta_addr = 0x00000F40, + .meta_cfg = 0x00000F44, + .mode_cfg = 0x00000F48, + .stats_ctrl = 0x00000F4C, + .ctrl_2 = 0x00000F50, + .lossy_thresh0 = 0x00000F54, + .lossy_thresh1 = 0x00000F58, + .off_lossy_var = 0x00000F5C, + .bw_limit = 0x00000F1C, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe680_ubwc_regs_client_4 = { + .meta_addr = 0x00001240, + .meta_cfg = 0x00001244, + .mode_cfg = 0x00001248, + .stats_ctrl = 0x0000124C, + .ctrl_2 = 0x00001250, + .lossy_thresh0 = 0x00001254, + .lossy_thresh1 = 0x00001258, + .off_lossy_var = 0x0000125C, + .bw_limit = 0x0000121C, +}; + +static struct cam_vfe_bus_ver3_reg_offset_ubwc_client + vfe680_ubwc_regs_client_5 = { + .meta_addr = 0x00001340, + .meta_cfg = 0x00001344, + .mode_cfg = 0x00001348, + .stats_ctrl = 0x0000134C, + .ctrl_2 = 0x00001350, + .lossy_thresh0 = 0x00001354, + .lossy_thresh1 = 0x00001358, + .off_lossy_var = 0x0000135C, + .bw_limit = 0x0000131C, +}; + +static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { + .common_reg = { + .hw_version = 0x00000C00, + .cgc_ovd = 0x00000C08, + .if_frameheader_cfg = { + 0x00000C34, + 0x00000C38, + 0x00000C3C, + 0x00000C40, + 0x00000C44, + 0x00000C48, + }, + .ubwc_static_ctrl = 0x00000C58, + .pwr_iso_cfg = 0x00000C5C, + .overflow_status_clear = 0x00000C60, + .ccif_violation_status = 0x00000C64, + .overflow_status = 0x00000C68, + .image_size_violation_status = 0x00000C70, + .debug_status_top_cfg = 0x00000CD4, + .debug_status_top = 0x00000CD8, + .test_bus_ctrl = 0x00000CDC, + .irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe680_bus_irq_reg, + .global_clear_offset = 0x00000C30, + .global_clear_bitmask = 0x00000001, + }, + }, + .num_client = CAM_VFE_BUS_VER3_680_MAX_CLIENTS, + .bus_client_reg = { + /* BUS Client 0 FULL Y */ + { + .cfg = 0x00000E00, + .image_addr = 0x00000E04, + .frame_incr = 0x00000E08, + .image_cfg_0 = 0x00000E0C, + .image_cfg_1 = 0x00000E10, + .image_cfg_2 = 0x00000E14, + .packer_cfg = 0x00000E18, + .frame_header_addr = 0x00000E20, + .frame_header_incr = 0x00000E24, + .frame_header_cfg = 0x00000E28, + .irq_subsample_period = 0x00000E30, + .irq_subsample_pattern = 0x00000E34, + .framedrop_period = 0x00000E38, + .framedrop_pattern = 0x00000E3C, + .mmu_prefetch_cfg = 0x00000E60, + .mmu_prefetch_max_offset = 0x00000E64, + .system_cache_cfg = 0x00000E68, + .addr_status_0 = 0x00000E70, + .addr_status_1 = 0x00000E74, + .addr_status_2 = 0x00000E78, + .addr_status_3 = 0x00000E7C, + .debug_status_cfg = 0x00000E80, + .debug_status_0 = 0x00000E84, + .debug_status_1 = 0x00000E88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = &vfe680_ubwc_regs_client_0, + }, + /* BUS Client 1 FULL C */ + { + .cfg = 0x00000F00, + .image_addr = 0x00000F04, + .frame_incr = 0x00000F08, + .image_cfg_0 = 0x00000F0C, + .image_cfg_1 = 0x00000F10, + .image_cfg_2 = 0x00000F14, + .packer_cfg = 0x00000F18, + .frame_header_addr = 0x00000F20, + .frame_header_incr = 0x00000F24, + .frame_header_cfg = 0x00000F28, + .irq_subsample_period = 0x00000F30, + .irq_subsample_pattern = 0x00000F34, + .framedrop_period = 0x00000F38, + .framedrop_pattern = 0x00000F3C, + .mmu_prefetch_cfg = 0x00000F60, + .mmu_prefetch_max_offset = 0x00000F64, + .system_cache_cfg = 0x00000F68, + .addr_status_0 = 0x00000F70, + .addr_status_1 = 0x00000F74, + .addr_status_2 = 0x00000F78, + .addr_status_3 = 0x00000F7C, + .debug_status_cfg = 0x00000F80, + .debug_status_0 = 0x00000F84, + .debug_status_1 = 0x00000F88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = &vfe680_ubwc_regs_client_1, + }, + /* BUS Client 2 DS4 */ + { + .cfg = 0x00001000, + .image_addr = 0x00001004, + .frame_incr = 0x00001008, + .image_cfg_0 = 0x0000100C, + .image_cfg_1 = 0x00001010, + .image_cfg_2 = 0x00001014, + .packer_cfg = 0x00001018, + .frame_header_addr = 0x00001020, + .frame_header_incr = 0x00001024, + .frame_header_cfg = 0x00001028, + .irq_subsample_period = 0x00001030, + .irq_subsample_pattern = 0x00001034, + .framedrop_period = 0x00001038, + .framedrop_pattern = 0x0000103C, + .mmu_prefetch_cfg = 0x00001060, + .mmu_prefetch_max_offset = 0x00001064, + .system_cache_cfg = 0x00001068, + .addr_status_0 = 0x00001070, + .addr_status_1 = 0x00001074, + .addr_status_2 = 0x00001078, + .addr_status_3 = 0x0000107C, + .debug_status_cfg = 0x00001080, + .debug_status_0 = 0x00001084, + .debug_status_1 = 0x00001088, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* BUS Client 3 DS16 */ + { + .cfg = 0x00001100, + .image_addr = 0x00001104, + .frame_incr = 0x00001108, + .image_cfg_0 = 0x0000110C, + .image_cfg_1 = 0x00001110, + .image_cfg_2 = 0x00001114, + .packer_cfg = 0x00001118, + .frame_header_addr = 0x00001120, + .frame_header_incr = 0x00001124, + .frame_header_cfg = 0x00001128, + .irq_subsample_period = 0x00001130, + .irq_subsample_pattern = 0x00001134, + .framedrop_period = 0x00001138, + .framedrop_pattern = 0x0000113C, + .mmu_prefetch_cfg = 0x00001160, + .mmu_prefetch_max_offset = 0x00001164, + .system_cache_cfg = 0x00001168, + .addr_status_0 = 0x00001170, + .addr_status_1 = 0x00001174, + .addr_status_2 = 0x00001178, + .addr_status_3 = 0x0000117C, + .debug_status_cfg = 0x00001180, + .debug_status_0 = 0x00001184, + .debug_status_1 = 0x00001188, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* BUS Client 4 DISP Y */ + { + .cfg = 0x00001200, + .image_addr = 0x00001204, + .frame_incr = 0x00001208, + .image_cfg_0 = 0x0000120C, + .image_cfg_1 = 0x00001210, + .image_cfg_2 = 0x00001214, + .packer_cfg = 0x00001218, + .frame_header_addr = 0x00001220, + .frame_header_incr = 0x00001224, + .frame_header_cfg = 0x00001228, + .irq_subsample_period = 0x00001230, + .irq_subsample_pattern = 0x00001234, + .framedrop_period = 0x00001238, + .framedrop_pattern = 0x0000123C, + .mmu_prefetch_cfg = 0x00001260, + .mmu_prefetch_max_offset = 0x00001264, + .system_cache_cfg = 0x00001268, + .addr_status_0 = 0x00001270, + .addr_status_1 = 0x00001274, + .addr_status_2 = 0x00001278, + .addr_status_3 = 0x0000127C, + .debug_status_cfg = 0x00001280, + .debug_status_0 = 0x00001284, + .debug_status_1 = 0x00001288, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = &vfe680_ubwc_regs_client_4, + }, + /* BUS Client 5 DISP C */ + { + .cfg = 0x00001300, + .image_addr = 0x00001304, + .frame_incr = 0x00001308, + .image_cfg_0 = 0x0000130C, + .image_cfg_1 = 0x00001310, + .image_cfg_2 = 0x00001314, + .packer_cfg = 0x00001318, + .frame_header_addr = 0x00001320, + .frame_header_incr = 0x00001324, + .frame_header_cfg = 0x00001328, + .irq_subsample_period = 0x00001330, + .irq_subsample_pattern = 0x00001334, + .framedrop_period = 0x00001338, + .framedrop_pattern = 0x0000133C, + .mmu_prefetch_cfg = 0x00001360, + .mmu_prefetch_max_offset = 0x00001364, + .system_cache_cfg = 0x00001368, + .addr_status_0 = 0x00001370, + .addr_status_1 = 0x00001374, + .addr_status_2 = 0x00001378, + .addr_status_3 = 0x0000137C, + .debug_status_cfg = 0x00001380, + .debug_status_0 = 0x00001384, + .debug_status_1 = 0x00001388, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = &vfe680_ubwc_regs_client_5, + }, + /* BUS Client 6 DISP DS4 */ + { + .cfg = 0x00001400, + .image_addr = 0x00001404, + .frame_incr = 0x00001408, + .image_cfg_0 = 0x0000140C, + .image_cfg_1 = 0x00001410, + .image_cfg_2 = 0x00001414, + .packer_cfg = 0x00001418, + .frame_header_addr = 0x00001420, + .frame_header_incr = 0x00001424, + .frame_header_cfg = 0x00001428, + .irq_subsample_period = 0x00001430, + .irq_subsample_pattern = 0x00001434, + .framedrop_period = 0x00001438, + .framedrop_pattern = 0x0000143C, + .mmu_prefetch_cfg = 0x00001460, + .mmu_prefetch_max_offset = 0x00001464, + .system_cache_cfg = 0x00001468, + .addr_status_0 = 0x00001470, + .addr_status_1 = 0x00001474, + .addr_status_2 = 0x00001478, + .addr_status_3 = 0x0000147C, + .debug_status_cfg = 0x00001480, + .debug_status_0 = 0x00001484, + .debug_status_1 = 0x00001488, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = NULL, + }, + /* BUS Client 7 DISP DS16 */ + { + .cfg = 0x00001500, + .image_addr = 0x00001504, + .frame_incr = 0x00001508, + .image_cfg_0 = 0x0000150C, + .image_cfg_1 = 0x00001510, + .image_cfg_2 = 0x00001514, + .packer_cfg = 0x00001518, + .frame_header_addr = 0x00001520, + .frame_header_incr = 0x00001524, + .frame_header_cfg = 0x00001528, + .irq_subsample_period = 0x00001530, + .irq_subsample_pattern = 0x00001534, + .framedrop_period = 0x00001538, + .framedrop_pattern = 0x0000153C, + .mmu_prefetch_cfg = 0x00001560, + .mmu_prefetch_max_offset = 0x00001564, + .system_cache_cfg = 0x00001568, + .addr_status_0 = 0x00001570, + .addr_status_1 = 0x00001574, + .addr_status_2 = 0x00001578, + .addr_status_3 = 0x0000157C, + .debug_status_cfg = 0x00001580, + .debug_status_0 = 0x00001584, + .debug_status_1 = 0x00001588, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = NULL, + }, + /* BUS Client 8 FD Y */ + { + .cfg = 0x00001600, + .image_addr = 0x00001604, + .frame_incr = 0x00001608, + .image_cfg_0 = 0x0000160C, + .image_cfg_1 = 0x00001610, + .image_cfg_2 = 0x00001614, + .packer_cfg = 0x00001618, + .frame_header_addr = 0x00001620, + .frame_header_incr = 0x00001624, + .frame_header_cfg = 0x00001628, + .irq_subsample_period = 0x00001630, + .irq_subsample_pattern = 0x00001634, + .framedrop_period = 0x00001638, + .framedrop_pattern = 0x0000163C, + .mmu_prefetch_cfg = 0x00001660, + .mmu_prefetch_max_offset = 0x00001664, + .system_cache_cfg = 0x00001668, + .addr_status_0 = 0x00001670, + .addr_status_1 = 0x00001674, + .addr_status_2 = 0x00001678, + .addr_status_3 = 0x0000167C, + .debug_status_cfg = 0x00001680, + .debug_status_0 = 0x00001684, + .debug_status_1 = 0x00001688, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .ubwc_regs = NULL, + }, + /* BUS Client 9 FD C */ + { + .cfg = 0x00001700, + .image_addr = 0x00001704, + .frame_incr = 0x00001708, + .image_cfg_0 = 0x0000170C, + .image_cfg_1 = 0x00001710, + .image_cfg_2 = 0x00001714, + .packer_cfg = 0x00001718, + .frame_header_addr = 0x00001720, + .frame_header_incr = 0x00001724, + .frame_header_cfg = 0x00001728, + .irq_subsample_period = 0x00001730, + .irq_subsample_pattern = 0x00001734, + .framedrop_period = 0x00001738, + .framedrop_pattern = 0x0000173C, + .mmu_prefetch_cfg = 0x00001760, + .mmu_prefetch_max_offset = 0x00001764, + .system_cache_cfg = 0x00001768, + .addr_status_0 = 0x00001770, + .addr_status_1 = 0x00001774, + .addr_status_2 = 0x00001778, + .addr_status_3 = 0x0000177C, + .debug_status_cfg = 0x00001780, + .debug_status_0 = 0x00001784, + .debug_status_1 = 0x00001788, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .ubwc_regs = NULL, + }, + /* BUS Client 10 PIXEL RAW */ + { + .cfg = 0x00001800, + .image_addr = 0x00001804, + .frame_incr = 0x00001808, + .image_cfg_0 = 0x0000180C, + .image_cfg_1 = 0x00001810, + .image_cfg_2 = 0x00001814, + .packer_cfg = 0x00001818, + .frame_header_addr = 0x00001820, + .frame_header_incr = 0x00001824, + .frame_header_cfg = 0x00001828, + .irq_subsample_period = 0x00001830, + .irq_subsample_pattern = 0x00001834, + .framedrop_period = 0x00001838, + .framedrop_pattern = 0x0000183C, + .mmu_prefetch_cfg = 0x00001860, + .mmu_prefetch_max_offset = 0x00001864, + .system_cache_cfg = 0x00001868, + .addr_status_0 = 0x00001870, + .addr_status_1 = 0x00001874, + .addr_status_2 = 0x00001878, + .addr_status_3 = 0x0000187C, + .debug_status_cfg = 0x00001880, + .debug_status_0 = 0x00001884, + .debug_status_1 = 0x00001888, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, + .ubwc_regs = NULL, + }, + /* BUS Client 11 STATS BE 0 */ + { + .cfg = 0x00001900, + .image_addr = 0x00001904, + .frame_incr = 0x00001908, + .image_cfg_0 = 0x0000190C, + .image_cfg_1 = 0x00001910, + .image_cfg_2 = 0x00001914, + .packer_cfg = 0x00001918, + .frame_header_addr = 0x00001920, + .frame_header_incr = 0x00001924, + .frame_header_cfg = 0x00001928, + .irq_subsample_period = 0x00001930, + .irq_subsample_pattern = 0x00001934, + .framedrop_period = 0x00001938, + .framedrop_pattern = 0x0000193C, + .mmu_prefetch_cfg = 0x00001960, + .mmu_prefetch_max_offset = 0x00001964, + .system_cache_cfg = 0x00001968, + .addr_status_0 = 0x00001970, + .addr_status_1 = 0x00001974, + .addr_status_2 = 0x00001978, + .addr_status_3 = 0x0000197C, + .debug_status_cfg = 0x00001980, + .debug_status_0 = 0x00001984, + .debug_status_1 = 0x00001988, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_4, + .ubwc_regs = NULL, + }, + /* BUS Client 12 STATS BHIST 0 */ + { + .cfg = 0x00001A00, + .image_addr = 0x00001A04, + .frame_incr = 0x00001A08, + .image_cfg_0 = 0x00001A0C, + .image_cfg_1 = 0x00001A10, + .image_cfg_2 = 0x00001A14, + .packer_cfg = 0x00001A18, + .frame_header_addr = 0x00001A20, + .frame_header_incr = 0x00001A24, + .frame_header_cfg = 0x00001A28, + .irq_subsample_period = 0x00001A30, + .irq_subsample_pattern = 0x00001A34, + .framedrop_period = 0x00001A38, + .framedrop_pattern = 0x00001A3C, + .mmu_prefetch_cfg = 0x00001A60, + .mmu_prefetch_max_offset = 0x00001A64, + .system_cache_cfg = 0x00001A68, + .addr_status_0 = 0x00001A70, + .addr_status_1 = 0x00001A74, + .addr_status_2 = 0x00001A78, + .addr_status_3 = 0x00001A7C, + .debug_status_cfg = 0x00001A80, + .debug_status_0 = 0x00001A84, + .debug_status_1 = 0x00001A88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_4, + .ubwc_regs = NULL, + }, + /* BUS Client 13 STATS TINTLESS BG */ + { + .cfg = 0x00001B00, + .image_addr = 0x00001B04, + .frame_incr = 0x00001B08, + .image_cfg_0 = 0x00001B0C, + .image_cfg_1 = 0x00001B10, + .image_cfg_2 = 0x00001B14, + .packer_cfg = 0x00001B18, + .frame_header_addr = 0x00001B20, + .frame_header_incr = 0x00001B24, + .frame_header_cfg = 0x00001B28, + .irq_subsample_period = 0x00001B30, + .irq_subsample_pattern = 0x00001B34, + .framedrop_period = 0x00001B38, + .framedrop_pattern = 0x00001B3C, + .mmu_prefetch_cfg = 0x00001B60, + .mmu_prefetch_max_offset = 0x00001B64, + .system_cache_cfg = 0x00001B68, + .addr_status_0 = 0x00001B70, + .addr_status_1 = 0x00001B74, + .addr_status_2 = 0x00001B78, + .addr_status_3 = 0x00001B7C, + .debug_status_cfg = 0x00001B80, + .debug_status_0 = 0x00001B84, + .debug_status_1 = 0x00001B88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_5, + .ubwc_regs = NULL, + }, + /* BUS Client 14 STATS AWB BG */ + { + .cfg = 0x00001C00, + .image_addr = 0x00001C04, + .frame_incr = 0x00001C08, + .image_cfg_0 = 0x00001C0C, + .image_cfg_1 = 0x00001C10, + .image_cfg_2 = 0x00001C14, + .packer_cfg = 0x00001C18, + .frame_header_addr = 0x00001C20, + .frame_header_incr = 0x00001C24, + .frame_header_cfg = 0x00001C28, + .irq_subsample_period = 0x00001C30, + .irq_subsample_pattern = 0x00001C34, + .framedrop_period = 0x00001C38, + .framedrop_pattern = 0x00001C3C, + .mmu_prefetch_cfg = 0x00001C60, + .mmu_prefetch_max_offset = 0x00001C64, + .system_cache_cfg = 0x00001C68, + .addr_status_0 = 0x00001C70, + .addr_status_1 = 0x00001C74, + .addr_status_2 = 0x00001C78, + .addr_status_3 = 0x00001C7C, + .debug_status_cfg = 0x00001C80, + .debug_status_0 = 0x00001C84, + .debug_status_1 = 0x00001C88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_6, + .ubwc_regs = NULL, + }, + /* BUS Client 15 STATS AWB BFW */ + { + .cfg = 0x00001D00, + .image_addr = 0x00001D04, + .frame_incr = 0x00001D08, + .image_cfg_0 = 0x00001D0C, + .image_cfg_1 = 0x00001D10, + .image_cfg_2 = 0x00001D14, + .packer_cfg = 0x00001D18, + .frame_header_addr = 0x00001D20, + .frame_header_incr = 0x00001D24, + .frame_header_cfg = 0x00001D28, + .irq_subsample_period = 0x00001D30, + .irq_subsample_pattern = 0x00001D34, + .framedrop_period = 0x00001D38, + .framedrop_pattern = 0x00001D3C, + .mmu_prefetch_cfg = 0x00001D60, + .mmu_prefetch_max_offset = 0x00001D64, + .system_cache_cfg = 0x00001D68, + .addr_status_0 = 0x00001D70, + .addr_status_1 = 0x00001D74, + .addr_status_2 = 0x00001D78, + .addr_status_3 = 0x00001D7C, + .debug_status_cfg = 0x00001D80, + .debug_status_0 = 0x00001D84, + .debug_status_1 = 0x00001D88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_6, + .ubwc_regs = NULL, + }, + /* BUS Client 16 STATS BAF */ + { + .cfg = 0x00001E00, + .image_addr = 0x00001E04, + .frame_incr = 0x00001E08, + .image_cfg_0 = 0x00001E0C, + .image_cfg_1 = 0x00001E10, + .image_cfg_2 = 0x00001E14, + .packer_cfg = 0x00001E18, + .frame_header_addr = 0x00001E20, + .frame_header_incr = 0x00001E24, + .frame_header_cfg = 0x00001E28, + .irq_subsample_period = 0x00001E30, + .irq_subsample_pattern = 0x00001E34, + .framedrop_period = 0x00001E38, + .framedrop_pattern = 0x00001E3C, + .mmu_prefetch_cfg = 0x00001E60, + .mmu_prefetch_max_offset = 0x00001E64, + .system_cache_cfg = 0x00001E68, + .addr_status_0 = 0x00001E70, + .addr_status_1 = 0x00001E74, + .addr_status_2 = 0x00001E78, + .addr_status_3 = 0x00001E7C, + .debug_status_cfg = 0x00001E80, + .debug_status_0 = 0x00001E84, + .debug_status_1 = 0x00001E88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_7, + .ubwc_regs = NULL, + }, + /* BUS Client 17 STATS BHIST */ + { + .cfg = 0x00001F00, + .image_addr = 0x00001F04, + .frame_incr = 0x00001F08, + .image_cfg_0 = 0x00001F0C, + .image_cfg_1 = 0x00001F10, + .image_cfg_2 = 0x00001F14, + .packer_cfg = 0x00001F18, + .frame_header_addr = 0x00001F20, + .frame_header_incr = 0x00001F24, + .frame_header_cfg = 0x00001F28, + .irq_subsample_period = 0x00001F30, + .irq_subsample_pattern = 0x00001F34, + .framedrop_period = 0x00001F38, + .framedrop_pattern = 0x00001F3C, + .mmu_prefetch_cfg = 0x00001F60, + .mmu_prefetch_max_offset = 0x00001F64, + .system_cache_cfg = 0x00001F68, + .addr_status_0 = 0x00001F70, + .addr_status_1 = 0x00001F74, + .addr_status_2 = 0x00001F78, + .addr_status_3 = 0x00001F7C, + .debug_status_cfg = 0x00001F80, + .debug_status_0 = 0x00001F84, + .debug_status_1 = 0x00001F88, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_8, + .ubwc_regs = NULL, + }, + /* BUS Client 18 STATS RS */ + { + .cfg = 0x00002000, + .image_addr = 0x00002004, + .frame_incr = 0x00002008, + .image_cfg_0 = 0x0000200C, + .image_cfg_1 = 0x00002010, + .image_cfg_2 = 0x00002014, + .packer_cfg = 0x00002018, + .frame_header_addr = 0x00002020, + .frame_header_incr = 0x00002024, + .frame_header_cfg = 0x00002028, + .irq_subsample_period = 0x00002030, + .irq_subsample_pattern = 0x00002034, + .framedrop_period = 0x00002038, + .framedrop_pattern = 0x0000203C, + .mmu_prefetch_cfg = 0x00002060, + .mmu_prefetch_max_offset = 0x00002064, + .system_cache_cfg = 0x00002068, + .addr_status_0 = 0x00002070, + .addr_status_1 = 0x00002074, + .addr_status_2 = 0x00002078, + .addr_status_3 = 0x0000207C, + .debug_status_cfg = 0x00002080, + .debug_status_0 = 0x00002084, + .debug_status_1 = 0x00002088, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_9, + .ubwc_regs = NULL, + }, + /* BUS Client 19 STATS IHIST */ + { + .cfg = 0x00002100, + .image_addr = 0x00002104, + .frame_incr = 0x00002108, + .image_cfg_0 = 0x0000210C, + .image_cfg_1 = 0x00002110, + .image_cfg_2 = 0x00002114, + .packer_cfg = 0x00002118, + .frame_header_addr = 0x00002120, + .frame_header_incr = 0x00002124, + .frame_header_cfg = 0x00002128, + .irq_subsample_period = 0x00002130, + .irq_subsample_pattern = 0x00002134, + .framedrop_period = 0x00002138, + .framedrop_pattern = 0x0000213C, + .mmu_prefetch_cfg = 0x00002160, + .mmu_prefetch_max_offset = 0x00002164, + .system_cache_cfg = 0x00002168, + .addr_status_0 = 0x00002170, + .addr_status_1 = 0x00002174, + .addr_status_2 = 0x00002178, + .addr_status_3 = 0x0000217C, + .debug_status_cfg = 0x00002180, + .debug_status_0 = 0x00002184, + .debug_status_1 = 0x00002188, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_10, + .ubwc_regs = NULL, + }, + /* BUS Client 20 CAMIF PD - PDAF */ + { + .cfg = 0x00002200, + .image_addr = 0x00002204, + .frame_incr = 0x00002208, + .image_cfg_0 = 0x0000220C, + .image_cfg_1 = 0x00002210, + .image_cfg_2 = 0x00002214, + .packer_cfg = 0x00002218, + .frame_header_addr = 0x00002220, + .frame_header_incr = 0x00002224, + .frame_header_cfg = 0x00002228, + .irq_subsample_period = 0x00002230, + .irq_subsample_pattern = 0x00002234, + .framedrop_period = 0x00002238, + .framedrop_pattern = 0x0000223C, + .mmu_prefetch_cfg = 0x00002260, + .mmu_prefetch_max_offset = 0x00002264, + .system_cache_cfg = 0x00002268, + .addr_status_0 = 0x00002270, + .addr_status_1 = 0x00002274, + .addr_status_2 = 0x00002278, + .addr_status_3 = 0x0000227C, + .debug_status_cfg = 0x00002280, + .debug_status_0 = 0x00002284, + .debug_status_1 = 0x00002288, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_12, + .ubwc_regs = NULL, + }, + /* BUS Client 21 PDAF V2.0 PD DATA - 2PD */ + { + .cfg = 0x00002300, + .image_addr = 0x00002304, + .frame_incr = 0x00002308, + .image_cfg_0 = 0x0000230C, + .image_cfg_1 = 0x00002310, + .image_cfg_2 = 0x00002314, + .packer_cfg = 0x00002318, + .frame_header_addr = 0x00002320, + .frame_header_incr = 0x00002324, + .frame_header_cfg = 0x00002328, + .irq_subsample_period = 0x00002330, + .irq_subsample_pattern = 0x00002334, + .framedrop_period = 0x00002338, + .framedrop_pattern = 0x0000233C, + .mmu_prefetch_cfg = 0x00002360, + .mmu_prefetch_max_offset = 0x00002364, + .system_cache_cfg = 0x00002368, + .addr_status_0 = 0x00002370, + .addr_status_1 = 0x00002374, + .addr_status_2 = 0x00002378, + .addr_status_3 = 0x0000237C, + .debug_status_cfg = 0x00002380, + .debug_status_0 = 0x00002384, + .debug_status_1 = 0x00002388, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_13, + .ubwc_regs = NULL, + }, + /* BUS Client 22 PDAF V2.0 SAD STATS */ + { + .cfg = 0x00002400, + .image_addr = 0x00002404, + .frame_incr = 0x00002408, + .image_cfg_0 = 0x0000240C, + .image_cfg_1 = 0x00002410, + .image_cfg_2 = 0x00002414, + .packer_cfg = 0x00002418, + .frame_header_addr = 0x00002420, + .frame_header_incr = 0x00002424, + .frame_header_cfg = 0x00002428, + .irq_subsample_period = 0x00002430, + .irq_subsample_pattern = 0x00002434, + .framedrop_period = 0x00002438, + .framedrop_pattern = 0x0000243C, + .mmu_prefetch_cfg = 0x00002460, + .mmu_prefetch_max_offset = 0x00002464, + .system_cache_cfg = 0x00002468, + .addr_status_0 = 0x00002470, + .addr_status_1 = 0x00002474, + .addr_status_2 = 0x00002478, + .addr_status_3 = 0x0000247C, + .debug_status_cfg = 0x00002480, + .debug_status_0 = 0x00002484, + .debug_status_1 = 0x00002488, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_13, + .ubwc_regs = NULL, + }, + /* BUS Client 23 LCR */ + { + .cfg = 0x00002500, + .image_addr = 0x00002504, + .frame_incr = 0x00002508, + .image_cfg_0 = 0x0000250C, + .image_cfg_1 = 0x00002510, + .image_cfg_2 = 0x00002514, + .packer_cfg = 0x00002518, + .frame_header_addr = 0x00002520, + .frame_header_incr = 0x00002524, + .frame_header_cfg = 0x00002528, + .irq_subsample_period = 0x00002530, + .irq_subsample_pattern = 0x00002534, + .framedrop_period = 0x00002538, + .framedrop_pattern = 0x0000253C, + .mmu_prefetch_cfg = 0x00002560, + .mmu_prefetch_max_offset = 0x00002564, + .system_cache_cfg = 0x00002568, + .addr_status_0 = 0x00002570, + .addr_status_1 = 0x00002574, + .addr_status_2 = 0x00002578, + .addr_status_3 = 0x0000257C, + .debug_status_cfg = 0x00002580, + .debug_status_0 = 0x00002584, + .debug_status_1 = 0x00002588, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_11, + .ubwc_regs = NULL, + }, + /* BUS Client 24 RDI0 */ + { + .cfg = 0x00002600, + .image_addr = 0x00002604, + .frame_incr = 0x00002608, + .image_cfg_0 = 0x0000260C, + .image_cfg_1 = 0x00002610, + .image_cfg_2 = 0x00002614, + .packer_cfg = 0x00002618, + .frame_header_addr = 0x00002620, + .frame_header_incr = 0x00002624, + .frame_header_cfg = 0x00002628, + .irq_subsample_period = 0x00002630, + .irq_subsample_pattern = 0x00002634, + .framedrop_period = 0x00002638, + .framedrop_pattern = 0x0000263C, + .mmu_prefetch_cfg = 0x00002660, + .mmu_prefetch_max_offset = 0x00002664, + .system_cache_cfg = 0x00002668, + .addr_status_0 = 0x00002670, + .addr_status_1 = 0x00002674, + .addr_status_2 = 0x00002678, + .addr_status_3 = 0x0000267C, + .debug_status_cfg = 0x00002680, + .debug_status_0 = 0x00002684, + .debug_status_1 = 0x00002688, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_14, + .ubwc_regs = NULL, + }, + /* BUS Client 25 RDI1 */ + { + .cfg = 0x00002700, + .image_addr = 0x00002704, + .frame_incr = 0x00002708, + .image_cfg_0 = 0x0000270C, + .image_cfg_1 = 0x00002710, + .image_cfg_2 = 0x00002714, + .packer_cfg = 0x00002718, + .frame_header_addr = 0x00002720, + .frame_header_incr = 0x00002724, + .frame_header_cfg = 0x00002728, + .irq_subsample_period = 0x00002730, + .irq_subsample_pattern = 0x00002734, + .framedrop_period = 0x00002738, + .framedrop_pattern = 0x0000273C, + .mmu_prefetch_cfg = 0x00002760, + .mmu_prefetch_max_offset = 0x00002764, + .system_cache_cfg = 0x00002768, + .addr_status_0 = 0x00002770, + .addr_status_1 = 0x00002774, + .addr_status_2 = 0x00002778, + .addr_status_3 = 0x0000277C, + .debug_status_cfg = 0x00002780, + .debug_status_0 = 0x00002784, + .debug_status_1 = 0x00002788, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_15, + .ubwc_regs = NULL, + }, + /* BUS Client 26 RDI2 */ + { + .cfg = 0x00002800, + .image_addr = 0x00002804, + .frame_incr = 0x00002808, + .image_cfg_0 = 0x0000280C, + .image_cfg_1 = 0x00002810, + .image_cfg_2 = 0x00002814, + .packer_cfg = 0x00002818, + .frame_header_addr = 0x00002820, + .frame_header_incr = 0x00002824, + .frame_header_cfg = 0x00002828, + .irq_subsample_period = 0x00002830, + .irq_subsample_pattern = 0x00002834, + .framedrop_period = 0x00002838, + .framedrop_pattern = 0x0000283C, + .mmu_prefetch_cfg = 0x00002860, + .mmu_prefetch_max_offset = 0x00002864, + .system_cache_cfg = 0x00002868, + .addr_status_0 = 0x00002870, + .addr_status_1 = 0x00002874, + .addr_status_2 = 0x00002878, + .addr_status_3 = 0x0000287C, + .debug_status_cfg = 0x00002880, + .debug_status_0 = 0x00002884, + .debug_status_1 = 0x00002888, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_16, + .ubwc_regs = NULL, + }, + /* BUS Client 27 LTM STATS */ + { + .cfg = 0x00002900, + .image_addr = 0x00002904, + .frame_incr = 0x00002908, + .image_cfg_0 = 0x0000290C, + .image_cfg_1 = 0x00002910, + .image_cfg_2 = 0x00002914, + .packer_cfg = 0x00002918, + .frame_header_addr = 0x00002920, + .frame_header_incr = 0x00002924, + .frame_header_cfg = 0x00002928, + .irq_subsample_period = 0x00002930, + .irq_subsample_pattern = 0x00002934, + .framedrop_period = 0x00002938, + .framedrop_pattern = 0x0000293C, + .mmu_prefetch_cfg = 0x00002960, + .mmu_prefetch_max_offset = 0x00002964, + .system_cache_cfg = 0x00002968, + .addr_status_0 = 0x00002970, + .addr_status_1 = 0x00002974, + .addr_status_2 = 0x00002978, + .addr_status_3 = 0x0000297C, + .debug_status_cfg = 0x00002980, + .debug_status_0 = 0x00002984, + .debug_status_1 = 0x00002988, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, + .ubwc_regs = NULL, + }, + }, + .num_out = 25, + .vfe_out_hw_info = { + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .num_wm = 1, + .wm_idx = { + 24, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .num_wm = 1, + .wm_idx = { + 25, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_4, + .num_wm = 1, + .wm_idx = { + 26, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL, + .max_width = 4096, + .max_height = 4096, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 2, + .wm_idx = { + 0, + 1, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 2, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 3, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 10, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FD, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 2, + .wm_idx = { + 8, + 9, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_PDAF, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 20, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 11, + }, + }, + { + .vfe_out_type = + CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 12, + }, + }, + { + .vfe_out_type = + CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 13, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 16, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 14, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 17, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 18, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 19, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, + .max_width = 4096, + .max_height = 4096, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 2, + .wm_idx = { + 4, + 5, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 6, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 7, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .num_wm = 1, + .wm_idx = { + 21, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LCR, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 23, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 15, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .num_wm = 1, + .wm_idx = { + 22, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 27, + }, + }, + }, + .comp_done_shift = 6, + .top_irq_shift = 7, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 33, +}; + + +static struct cam_vfe_hw_info cam_vfe680_hw_info = { + .irq_reg_info = &vfe680_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_3_0, + .bus_hw_info = &vfe680_bus_hw_info, + + .bus_rd_version = NULL, + .bus_rd_hw_info = NULL, + + .top_version = CAM_VFE_TOP_VER_4_0, + .top_hw_info = &vfe680_top_hw_info, +}; + +#endif /* _CAM_VFE680_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h new file mode 100644 index 000000000000..1c53bf79e04f --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + + +#ifndef _CAM_VFE_LITE680X_H_ +#define _CAM_VFE_LITE680X_H_ +#include "cam_vfe_camif_ver3.h" +#include "cam_vfe_top_ver3.h" +#include "cam_vfe_core.h" +#include "cam_vfe_bus_ver3.h" +#include "cam_irq_controller.h" + +static struct cam_irq_register_set vfe680x_bus_irq_reg[2] = { + { + .mask_reg_offset = 0x00000218, + .clear_reg_offset = 0x00000220, + .status_reg_offset = 0x00000228, + }, + { + .mask_reg_offset = 0x0000021C, + .clear_reg_offset = 0x00000224, + .status_reg_offset = 0x0000022C, + }, +}; + +static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { + .common_reg = { + .hw_version = 0x00000200, + .cgc_ovd = 0x00000208, + .if_frameheader_cfg = { + 0x00000234, + 0x00000238, + 0x0000023C, + 0x00000240, + 0x00000244, + 0x00000248, + }, + .pwr_iso_cfg = 0x0000025C, + .overflow_status_clear = 0x00000260, + .ccif_violation_status = 0x00000264, + .overflow_status = 0x00000268, + .image_size_violation_status = 0x00000270, + .debug_status_top_cfg = 0x000002D4, + .debug_status_top = 0x000002D8, + .test_bus_ctrl = 0x000002DC, + .irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe680x_bus_irq_reg, + .global_clear_offset = 0x00000230, + .global_clear_bitmask = 0x00000001, + }, + }, + .num_client = 4, + .bus_client_reg = { + /* BUS Client 0 RDI0 */ + { + .cfg = 0x00000400, + .image_addr = 0x00000404, + .frame_incr = 0x00000408, + .image_cfg_0 = 0x0000040C, + .image_cfg_1 = 0x00000410, + .image_cfg_2 = 0x00000414, + .packer_cfg = 0x00000418, + .frame_header_addr = 0x00000420, + .frame_header_incr = 0x00000424, + .frame_header_cfg = 0x00000428, + .irq_subsample_period = 0x00000430, + .irq_subsample_pattern = 0x00000434, + .framedrop_period = 0x00000438, + .framedrop_pattern = 0x0000043C, + .mmu_prefetch_cfg = 0x00000460, + .mmu_prefetch_max_offset = 0x00000464, + .system_cache_cfg = 0x00000468, + .addr_status_0 = 0x00000470, + .addr_status_1 = 0x00000474, + .addr_status_2 = 0x00000478, + .addr_status_3 = 0x0000047C, + .debug_status_cfg = 0x00000480, + .debug_status_0 = 0x00000484, + .debug_status_1 = 0x00000488, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* BUS Client 1 RDI1 */ + { + .cfg = 0x00000500, + .image_addr = 0x00000504, + .frame_incr = 0x00000508, + .image_cfg_0 = 0x0000050C, + .image_cfg_1 = 0x00000510, + .image_cfg_2 = 0x00000514, + .packer_cfg = 0x00000518, + .frame_header_addr = 0x00000520, + .frame_header_incr = 0x00000524, + .frame_header_cfg = 0x00000528, + .irq_subsample_period = 0x00000530, + .irq_subsample_pattern = 0x00000534, + .framedrop_period = 0x00000538, + .framedrop_pattern = 0x0000053C, + .mmu_prefetch_cfg = 0x00000560, + .mmu_prefetch_max_offset = 0x00000564, + .system_cache_cfg = 0x00000568, + .addr_status_0 = 0x00000570, + .addr_status_1 = 0x00000574, + .addr_status_2 = 0x00000578, + .addr_status_3 = 0x0000057C, + .debug_status_cfg = 0x00000580, + .debug_status_0 = 0x00000584, + .debug_status_1 = 0x00000588, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .ubwc_regs = NULL, + }, + /* BUS Client 2 RDI2 */ + { + .cfg = 0x00000600, + .image_addr = 0x00000604, + .frame_incr = 0x00000608, + .image_cfg_0 = 0x0000060C, + .image_cfg_1 = 0x00000610, + .image_cfg_2 = 0x00000614, + .packer_cfg = 0x00000618, + .frame_header_addr = 0x00000620, + .frame_header_incr = 0x00000624, + .frame_header_cfg = 0x00000628, + .irq_subsample_period = 0x00000630, + .irq_subsample_pattern = 0x00000634, + .framedrop_period = 0x00000638, + .framedrop_pattern = 0x0000063C, + .mmu_prefetch_cfg = 0x00000660, + .mmu_prefetch_max_offset = 0x00000664, + .system_cache_cfg = 0x00000668, + .addr_status_0 = 0x00000670, + .addr_status_1 = 0x00000674, + .addr_status_2 = 0x00000678, + .addr_status_3 = 0x0000067C, + .debug_status_cfg = 0x00000680, + .debug_status_0 = 0x00000684, + .debug_status_1 = 0x00000688, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .ubwc_regs = NULL, + }, + /* BUS Client 3 RDI3 */ + { + .cfg = 0x00000700, + .image_addr = 0x00000704, + .frame_incr = 0x00000708, + .image_cfg_0 = 0x0000070C, + .image_cfg_1 = 0x00000710, + .image_cfg_2 = 0x00000714, + .packer_cfg = 0x00000718, + .frame_header_addr = 0x00000720, + .frame_header_incr = 0x00000724, + .frame_header_cfg = 0x00000728, + .irq_subsample_period = 0x00000730, + .irq_subsample_pattern = 0x00000734, + .framedrop_period = 0x00000738, + .framedrop_pattern = 0x0000073C, + .mmu_prefetch_cfg = 0x00000760, + .mmu_prefetch_max_offset = 0x00000764, + .system_cache_cfg = 0x00000768, + .addr_status_0 = 0x00000770, + .addr_status_1 = 0x00000774, + .addr_status_2 = 0x00000778, + .addr_status_3 = 0x0000077C, + .debug_status_cfg = 0x00000780, + .debug_status_0 = 0x00000784, + .debug_status_1 = 0x00000788, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, + .ubwc_regs = NULL, + }, + }, + .num_out = 4, + .vfe_out_hw_info = { + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 0, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .num_wm = 1, + .wm_idx = { + 1, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .num_wm = 1, + .wm_idx = { + 2, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .num_wm = 1, + .wm_idx = { + 3, + }, + }, + }, + .comp_done_shift = 6, + .top_irq_shift = 1, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 33, +}; + +static struct cam_vfe_hw_info cam_vfe_lite68x_hw_info = { + .irq_reg_info =, + + .bus_version = CAM_VFE_BUS_VER_3_0, + .bus_hw_info = &vfe680x_bus_hw_info, + + .bus_rd_version = NULL, + .bus_rd_hw_info = NULL, + + .top_version =, + .top_hw_info =, +}; + +#endif /* _CAM_VFE_LITE680X_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index dbc7a8c15a51..fd00b852888e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -11,8 +11,10 @@ #include "cam_vfe_bus.h" #define CAM_VFE_BUS_VER3_MAX_CLIENTS 26 -#define CAM_VFE_BUS_VER3_MAX_SUB_GRPS 6 +#define CAM_VFE_BUS_VER3_MAX_SUB_GRPS 6 #define CAM_VFE_BUS_VER3_MAX_MID_PER_PORT 4 +#define CAM_VFE_BUS_VER3_480_MAX_CLIENTS 26 +#define CAM_VFE_BUS_VER3_680_MAX_CLIENTS 28 enum cam_vfe_bus_ver3_vfe_core_id { CAM_VFE_BUS_VER3_VFE_CORE_0, @@ -45,6 +47,9 @@ enum cam_vfe_bus_ver3_comp_grp_type { CAM_VFE_BUS_VER3_COMP_GRP_11, CAM_VFE_BUS_VER3_COMP_GRP_12, CAM_VFE_BUS_VER3_COMP_GRP_13, + CAM_VFE_BUS_VER3_COMP_GRP_14, + CAM_VFE_BUS_VER3_COMP_GRP_15, + CAM_VFE_BUS_VER3_COMP_GRP_16, CAM_VFE_BUS_VER3_COMP_GRP_MAX, }; @@ -73,6 +78,9 @@ enum cam_vfe_bus_ver3_vfe_out_type { CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, CAM_VFE_BUS_VER3_VFE_OUT_2PD, CAM_VFE_BUS_VER3_VFE_OUT_LCR, + CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW, + CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS, + CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS, CAM_VFE_BUS_VER3_VFE_OUT_MAX, }; @@ -138,6 +146,8 @@ struct cam_vfe_bus_ver3_reg_offset_bus_client { uint32_t irq_subsample_pattern; uint32_t framedrop_period; uint32_t framedrop_pattern; + uint32_t mmu_prefetch_cfg; + uint32_t mmu_prefetch_max_offset; uint32_t burst_limit; uint32_t system_cache_cfg; void *ubwc_regs; @@ -162,6 +172,8 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { uint32_t max_height; uint32_t source_group; uint32_t mid[CAM_VFE_BUS_VER3_MAX_MID_PER_PORT]; + uint32_t num_wm; + uint32_t wm_idx[PLANE_MAX]; }; /* @@ -182,7 +194,7 @@ struct cam_vfe_bus_ver3_hw_info { struct cam_vfe_bus_ver3_reg_offset_common common_reg; uint32_t num_client; struct cam_vfe_bus_ver3_reg_offset_bus_client - bus_client_reg[CAM_VFE_BUS_VER3_MAX_CLIENTS]; + bus_client_reg[CAM_VFE_BUS_VER3_680_MAX_CLIENTS]; uint32_t num_out; struct cam_vfe_bus_ver3_vfe_out_hw_info vfe_out_hw_info[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h index 932cab858a70..22118d011294 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_TOP_H_ @@ -12,6 +12,7 @@ #define CAM_VFE_TOP_VER_1_0 0x100000 #define CAM_VFE_TOP_VER_2_0 0x200000 #define CAM_VFE_TOP_VER_3_0 0x300000 +#define CAM_VFE_TOP_VER_4_0 0x400000 #define CAM_VFE_CAMIF_VER_1_0 0x10 #define CAM_VFE_CAMIF_VER_2_0 0x20 From 1332b49e26da791e689c41d62cc1c91c6a91774e Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Wed, 13 May 2020 18:12:33 -0700 Subject: [PATCH 572/790] msm: camera: ife: Add support for camera v680 bus This change adds support for Waipio bus hardware. It also changes the bus private structure to be pointer based so that most of the information is filled from hardware specific headers. CRs-Fixed: 2794540 Change-Id: Ie9d30442246a896f372512b62bd54be32c4921ad Signed-off-by: Venkat Chinta Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/cam_isp_context.c | 14 + .../isp_hw/include/cam_vfe_hw_intf.h | 2 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h | 9 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 100 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe680.h | 30 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 19 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h | 103 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 967 +++++++----------- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 11 +- 9 files changed, 639 insertions(+), 616 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 8fd7cb0d0c43..890520c78e19 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -569,6 +569,20 @@ static const char *__cam_isp_resource_handle_id_to_type( return "RDI_RD"; case CAM_ISP_IFE_OUT_RES_LCR: return "LCR"; + case CAM_ISP_IFE_OUT_RES_AWB_BFW: + return "AWB_BFW"; + case CAM_ISP_IFE_OUT_RES_2PD_STATS: + return "2PD_STATS"; + case CAM_ISP_IFE_OUT_RES_STATS_AEC_BE: + return "STATS_AEC_BE"; + case CAM_ISP_IFE_OUT_RES_LTM_STATS: + return "LTM_STATS"; + case CAM_ISP_IFE_OUT_RES_STATS_GTM_BHIST: + return "STATS_GTM_BHIST"; + case CAM_ISP_IFE_LITE_OUT_RES_STATS_BE: + return "STATS_BE"; + case CAM_ISP_IFE_LITE_OUT_RES_GAMMA: + return "GAMMA"; default: return "CAM_ISP_Invalid_Resource_Type"; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 1caf997c8f6e..1cb9ec7d8c6e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -190,6 +190,7 @@ struct cam_vfe_hw_vfe_in_acquire_args { * with this resource. * @priv: Context data * @event_cb: Callback function to hw mgr in case of hw events + * @buf_done_controller: Buf done controller for isp * @vfe_out: Acquire args for VFE_OUT * @vfe_bus_rd Acquire args for VFE_BUS_READ * @vfe_in: Acquire args for VFE_IN @@ -199,6 +200,7 @@ struct cam_vfe_acquire_args { void *tasklet; void *priv; cam_hw_mgr_event_cb_func event_cb; + void *buf_done_controller; union { struct cam_vfe_hw_vfe_out_acquire_args vfe_out; struct cam_vfe_hw_vfe_bus_rd_acquire_args vfe_bus_rd; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h index 43afd0377057..928f01ebcea1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_CORE_H_ @@ -12,6 +12,13 @@ #include "cam_vfe_bus.h" #include "cam_vfe_hw_intf.h" +#define CAM_VFE_HW_IRQ_CAP_SOF 0x1 +#define CAM_VFE_HW_IRQ_CAP_EPOCH_0 0x2 +#define CAM_VFE_HW_IRQ_CAP_EPOCH_1 0x4 +#define CAM_VFE_HW_IRQ_CAP_RUP 0x8 +#define CAM_VFE_HW_IRQ_CAP_BUF_DONE 0x10 +#define CAM_VFE_HW_IRQ_CAP_EOF 0x20 + struct cam_vfe_hw_info { struct cam_irq_controller_reg_info *irq_reg_info; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 7caa1eea1ee4..b70ad12bb26a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -412,7 +412,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .global_clear_bitmask = 0x00000001, }, }, - .num_client = CAM_VFE_BUS_VER3_MAX_CLIENTS, + .num_client = CAM_VFE_BUS_VER3_480_MAX_CLIENTS, .bus_client_reg = { /* BUS Client 0 FULL Y */ { @@ -1177,6 +1177,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, .mid[0] = 8, + .num_wm = 1, + .wm_idx = { + 23, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, @@ -1184,6 +1188,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_4, .mid[0] = 9, + .num_wm = 1, + .wm_idx = { + 24, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, @@ -1191,6 +1199,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_5, .mid[0] = 10, + .num_wm = 1, + .wm_idx = { + 25, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL, @@ -1201,6 +1213,11 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .mid[1] = 33, .mid[2] = 34, .mid[3] = 35, + .num_wm = 2, + .wm_idx = { + 0, + 1, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4, @@ -1208,6 +1225,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 16, + .num_wm = 1, + .wm_idx = { + 2, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16, @@ -1215,6 +1236,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 17, + .num_wm = 1, + .wm_idx = { + 3, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, @@ -1223,6 +1248,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 11, .mid[1] = 12, + .num_wm = 1, + .wm_idx = { + 10, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FD, @@ -1232,6 +1261,11 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .mid[0] = 20, .mid[1] = 21, .mid[2] = 22, + .num_wm = 2, + .wm_idx = { + 8, + 9, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_PDAF, @@ -1240,6 +1274,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 25, .mid[1] = 26, + .num_wm = 1, + .wm_idx = { + 11, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, @@ -1247,6 +1285,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 40, + .num_wm = 1, + .wm_idx = { + 12, + } }, { .vfe_out_type = @@ -1255,6 +1297,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 41, + .num_wm = 1, + .wm_idx = { + 13, + } }, { .vfe_out_type = @@ -1263,6 +1309,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 42, + .num_wm = 1, + .wm_idx = { + 14, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, @@ -1270,6 +1320,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 43, + .num_wm = 1, + .wm_idx = { + 20, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, @@ -1277,6 +1331,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 44, + .num_wm = 1, + .wm_idx = { + 15, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, @@ -1284,6 +1342,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 45, + .num_wm = 1, + .wm_idx = { + 16, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, @@ -1291,6 +1353,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 46, + .num_wm = 1, + .wm_idx = { + 17, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, @@ -1298,6 +1364,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 47, + .num_wm = 1, + .wm_idx = { + 18, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, @@ -1305,6 +1375,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 48, + .num_wm = 1, + .wm_idx = { + 19, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, @@ -1315,6 +1389,11 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .mid[1] = 37, .mid[2] = 38, .mid[3] = 39, + .num_wm = 2, + .wm_idx = { + 4, + 5, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, @@ -1322,6 +1401,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 18, + .num_wm = 1, + .wm_idx = { + 6, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, @@ -1329,6 +1412,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = 1080, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 19, + .num_wm = 1, + .wm_idx = { + 7, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD, @@ -1337,6 +1424,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, .mid[0] = 23, .mid[1] = 24, + .num_wm = 1, + .wm_idx = { + 21, + } }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LCR, @@ -1344,12 +1435,19 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, .mid[0] = 27, + .num_wm = 1, + .wm_idx = { + 22, + } }, }, + .num_comp_grp = 14, .comp_done_shift = 6, .top_irq_shift = 7, .support_consumed_addr = true, .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 25, + .supported_irq = CAM_VFE_HW_IRQ_CAP_BUF_DONE | CAM_VFE_HW_IRQ_CAP_RUP, + .comp_cfg_needed = true, }; static struct cam_irq_register_set vfe480_bus_rd_irq_reg[1] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h index 2883d9ca6907..2f2fb4cb667e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h @@ -1026,7 +1026,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .ubwc_regs = NULL, }, }, - .num_out = 25, + .num_out = 27, .vfe_out_hw_info = { { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, @@ -1179,7 +1179,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .num_wm = 1, .wm_idx = { - 17, + 12, }, }, { @@ -1273,6 +1273,16 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { 22, }, }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 11, + }, + }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS, .max_width = -1, @@ -1283,9 +1293,21 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { 27, }, }, + { + .vfe_out_type = + CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 17, + }, + }, }, - .comp_done_shift = 6, - .top_irq_shift = 7, + .num_comp_grp = 17, + .comp_done_shift = 0, + .top_irq_shift = 1, .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 33, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index c118c8020292..3f1efb1a70e7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -374,6 +374,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, .mid[0] = 16, + .num_wm = 1, + .wm_idx = { + 0, + }, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, @@ -381,6 +385,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, .mid[0] = 17, + .num_wm = 1, + .wm_idx = { + 1, + }, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, @@ -388,6 +396,10 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, .mid[0] = 18, + .num_wm = 1, + .wm_idx = { + 2, + }, }, { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, @@ -395,12 +407,19 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { .max_height = -1, .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, .mid[0] = 19, + .num_wm = 1, + .wm_idx = { + 3, + }, }, }, + .num_comp_grp = 4, .comp_done_shift = 4, .top_irq_shift = 4, .support_consumed_addr = true, .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 25, + .supported_irq = CAM_VFE_HW_IRQ_CAP_BUF_DONE | CAM_VFE_HW_IRQ_CAP_RUP, + .comp_cfg_needed = true, }; static struct cam_vfe_hw_info cam_vfe_lite48x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h index 1c53bf79e04f..b16857e91c58 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h @@ -35,7 +35,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { 0x0000023C, 0x00000240, 0x00000244, - 0x00000248, }, .pwr_iso_cfg = 0x0000025C, .overflow_status_clear = 0x00000260, @@ -52,7 +51,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .global_clear_bitmask = 0x00000001, }, }, - .num_client = 4, + .num_client = 6, .bus_client_reg = { /* BUS Client 0 RDI0 */ { @@ -80,7 +79,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .debug_status_cfg = 0x00000480, .debug_status_0 = 0x00000484, .debug_status_1 = 0x00000488, - .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, .ubwc_regs = NULL, }, /* BUS Client 1 RDI1 */ @@ -109,7 +108,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .debug_status_cfg = 0x00000580, .debug_status_0 = 0x00000584, .debug_status_1 = 0x00000588, - .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, .ubwc_regs = NULL, }, /* BUS Client 2 RDI2 */ @@ -138,7 +137,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .debug_status_cfg = 0x00000680, .debug_status_0 = 0x00000684, .debug_status_1 = 0x00000688, - .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, .ubwc_regs = NULL, }, /* BUS Client 3 RDI3 */ @@ -167,17 +166,75 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .debug_status_cfg = 0x00000780, .debug_status_0 = 0x00000784, .debug_status_1 = 0x00000788, - .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_4, .ubwc_regs = NULL, }, + /* BUS Client 4 Gamma */ + { + .cfg = 0x00000800, + .image_addr = 0x00000804, + .frame_incr = 0x00000808, + .image_cfg_0 = 0x0000080C, + .image_cfg_1 = 0x00000810, + .image_cfg_2 = 0x00000814, + .packer_cfg = 0x00000818, + .frame_header_addr = 0x00000820, + .frame_header_incr = 0x00000824, + .frame_header_cfg = 0x00000828, + .irq_subsample_period = 0x00000830, + .irq_subsample_pattern = 0x00000834, + .framedrop_period = 0x00000838, + .framedrop_pattern = 0x0000083C, + .mmu_prefetch_cfg = 0x00000860, + .mmu_prefetch_max_offset = 0x00000864, + .system_cache_cfg = 0x00000868, + .addr_status_0 = 0x00000870, + .addr_status_1 = 0x00000874, + .addr_status_2 = 0x00000878, + .addr_status_3 = 0x0000087C, + .debug_status_cfg = 0x00000880, + .debug_status_0 = 0x00000884, + .debug_status_1 = 0x00000888, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, + /* BUS Client 5 Stats BE */ + { + .cfg = 0x00000900, + .image_addr = 0x00000904, + .frame_incr = 0x00000908, + .image_cfg_0 = 0x0000090C, + .image_cfg_1 = 0x00000910, + .image_cfg_2 = 0x00000914, + .packer_cfg = 0x00000918, + .frame_header_addr = 0x00000920, + .frame_header_incr = 0x00000924, + .frame_header_cfg = 0x00000928, + .irq_subsample_period = 0x00000930, + .irq_subsample_pattern = 0x00000934, + .framedrop_period = 0x00000938, + .framedrop_pattern = 0x0000093C, + .mmu_prefetch_cfg = 0x00000960, + .mmu_prefetch_max_offset = 0x00000964, + .system_cache_cfg = 0x00000968, + .addr_status_0 = 0x00000970, + .addr_status_1 = 0x00000974, + .addr_status_2 = 0x00000978, + .addr_status_3 = 0x0000097C, + .debug_status_cfg = 0x00000980, + .debug_status_0 = 0x00000984, + .debug_status_1 = 0x00000988, + .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, + .ubwc_regs = NULL, + }, }, - .num_out = 4, + .num_out = 6, .vfe_out_hw_info = { { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0, .max_width = -1, .max_height = -1, - .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, .num_wm = 1, .wm_idx = { 0, @@ -187,7 +244,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, - .source_group = CAM_VFE_BUS_VER3_SRC_GRP_1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, .num_wm = 1, .wm_idx = { 1, @@ -197,7 +254,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, - .source_group = CAM_VFE_BUS_VER3_SRC_GRP_2, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, .num_wm = 1, .wm_idx = { 2, @@ -207,14 +264,36 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3, .max_width = -1, .max_height = -1, - .source_group = CAM_VFE_BUS_VER3_SRC_GRP_3, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_4, .num_wm = 1, .wm_idx = { 3, }, }, + { + .vfe_out_type = + CAM_VFE_BUS_VER3_VFE_OUT_GAMMA, + .max_width = 1920, + .max_height = 1080, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 4, + }, + }, + { + .vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE, + .max_width = -1, + .max_height = -1, + .source_group = CAM_VFE_BUS_VER3_SRC_GRP_0, + .num_wm = 1, + .wm_idx = { + 5, + }, + }, }, - .comp_done_shift = 6, + .num_comp_grp = 4, + .comp_done_shift = 0, .top_irq_shift = 1, .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 33, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 4202fbfe17b2..5fa123654ef8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -42,7 +42,7 @@ static const char drv_name[] = "vfe_bus"; (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES) static uint32_t bus_error_irq_mask[2] = { - 0xC0000000, + 0xD0000000, 0x00000000, }; @@ -62,6 +62,11 @@ enum cam_vfe_bus_ver3_packer_format { PACKER_FMT_VER3_MAX, }; +struct cam_vfe_bus_ver3_comp_grp_acquire_args { + enum cam_vfe_bus_ver3_comp_grp_type comp_grp_id; + uint32_t composite_mask; +}; + struct cam_vfe_bus_error_info { uint32_t bitmask; uint32_t vfe_output; @@ -75,6 +80,7 @@ struct cam_vfe_bus_ver3_common_data { void *bus_irq_controller; void *rup_irq_controller; void *vfe_irq_controller; + void *buf_done_controller; struct cam_vfe_bus_ver3_reg_offset_common *common_reg; uint32_t io_buf_update[ MAX_REG_VAL_PAIR_SIZE]; @@ -88,6 +94,8 @@ struct cam_vfe_bus_ver3_common_data { uint32_t num_sec_out; uint32_t addr_no_sync; uint32_t comp_done_shift; + uint32_t supported_irq; + bool comp_config_needed; bool is_lite; bool hw_init; bool support_consumed_addr; @@ -162,7 +170,7 @@ struct cam_vfe_bus_ver3_vfe_out_data { struct cam_vfe_bus_ver3_priv *bus_priv; uint32_t num_wm; - struct cam_isp_resource_node *wm_res[PLANE_MAX]; + struct cam_isp_resource_node *wm_res; struct cam_isp_resource_node *comp_grp; enum cam_isp_hw_sync_mode dual_comp_sync_mode; @@ -185,11 +193,12 @@ struct cam_vfe_bus_ver3_priv { struct cam_vfe_bus_ver3_common_data common_data; uint32_t num_client; uint32_t num_out; + uint32_t num_comp_grp; uint32_t top_irq_shift; - struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER3_MAX_CLIENTS]; - struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER3_COMP_GRP_MAX]; - struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; + struct cam_isp_resource_node *bus_client; + struct cam_isp_resource_node *comp_grp; + struct cam_isp_resource_node *vfe_out; struct list_head free_comp_grp; struct list_head used_comp_grp; @@ -606,477 +615,122 @@ static enum cam_vfe_bus_ver3_vfe_out_type return CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP; case CAM_ISP_IFE_OUT_RES_LCR: return CAM_VFE_BUS_VER3_VFE_OUT_LCR; + case CAM_ISP_IFE_OUT_RES_AWB_BFW: + return CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW; + case CAM_ISP_IFE_OUT_RES_2PD_STATS: + return CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS; + case CAM_ISP_IFE_OUT_RES_STATS_AEC_BE: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE; + case CAM_ISP_IFE_OUT_RES_LTM_STATS: + return CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS; + case CAM_ISP_IFE_OUT_RES_STATS_GTM_BHIST: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST; + case CAM_ISP_IFE_LITE_OUT_RES_STATS_BE: + return CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE; + case CAM_ISP_IFE_LITE_OUT_RES_GAMMA: + return CAM_VFE_BUS_VER3_VFE_OUT_GAMMA; default: return CAM_VFE_BUS_VER3_VFE_OUT_MAX; } } -static int cam_vfe_bus_ver3_get_num_wm( - enum cam_vfe_bus_ver3_vfe_out_type res_type, - uint32_t format) -{ - switch (res_type) { - case CAM_VFE_BUS_VER3_VFE_OUT_RDI0: - case CAM_VFE_BUS_VER3_VFE_OUT_RDI1: - case CAM_VFE_BUS_VER3_VFE_OUT_RDI2: - case CAM_VFE_BUS_VER3_VFE_OUT_RDI3: - switch (format) { - case CAM_FORMAT_MIPI_RAW_8: - case CAM_FORMAT_MIPI_RAW_10: - case CAM_FORMAT_MIPI_RAW_12: - case CAM_FORMAT_MIPI_RAW_14: - case CAM_FORMAT_MIPI_RAW_16: - case CAM_FORMAT_MIPI_RAW_20: - case CAM_FORMAT_DPCM_10_6_10: - case CAM_FORMAT_DPCM_10_8_10: - case CAM_FORMAT_DPCM_12_6_12: - case CAM_FORMAT_DPCM_12_8_12: - case CAM_FORMAT_DPCM_14_8_14: - case CAM_FORMAT_DPCM_14_10_14: - case CAM_FORMAT_PLAIN8: - case CAM_FORMAT_PLAIN16_10: - case CAM_FORMAT_PLAIN16_12: - case CAM_FORMAT_PLAIN16_14: - case CAM_FORMAT_PLAIN16_16: - case CAM_FORMAT_PLAIN32_20: - case CAM_FORMAT_PLAIN128: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_FULL: - case CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP: - switch (format) { - case CAM_FORMAT_NV21: - case CAM_FORMAT_NV12: - case CAM_FORMAT_MIPI_RAW_8: - case CAM_FORMAT_PLAIN8: - case CAM_FORMAT_TP10: - case CAM_FORMAT_UBWC_NV12: - case CAM_FORMAT_UBWC_NV12_4R: - case CAM_FORMAT_UBWC_TP10: - case CAM_FORMAT_UBWC_P010: - case CAM_FORMAT_PLAIN16_10: - return 2; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_FD: - switch (format) { - case CAM_FORMAT_NV21: - case CAM_FORMAT_NV12: - case CAM_FORMAT_PLAIN8: - case CAM_FORMAT_TP10: - case CAM_FORMAT_PLAIN16_10: - return 2; - case CAM_FORMAT_Y_ONLY: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_DS4: - case CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP: - case CAM_VFE_BUS_VER3_VFE_OUT_DS16: - case CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP: - switch (format) { - case CAM_FORMAT_PD8: - case CAM_FORMAT_PD10: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP: - switch (format) { - case CAM_FORMAT_ARGB_14: - case CAM_FORMAT_PLAIN8: - case CAM_FORMAT_PLAIN16_10: - case CAM_FORMAT_PLAIN16_12: - case CAM_FORMAT_PLAIN16_14: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_2PD: - switch (format) { - case CAM_FORMAT_PLAIN16_8: - case CAM_FORMAT_PLAIN16_10: - case CAM_FORMAT_PLAIN16_12: - case CAM_FORMAT_PLAIN16_14: - case CAM_FORMAT_PLAIN16_16: - case CAM_FORMAT_PLAIN64: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS: - switch (format) { - case CAM_FORMAT_PLAIN64: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS: - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST: - switch (format) { - case CAM_FORMAT_PLAIN16_16: - return 1; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_LCR: - return 1; - default: - break; - } - - CAM_ERR(CAM_ISP, "Unsupported format %u for out_type:0x%X", - format, res_type); - - return -EINVAL; -} - -static int cam_vfe_bus_ver3_get_wm_idx( - enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, - enum cam_vfe_bus_plane_type plane, - bool is_lite) -{ - int wm_idx = -1; - - switch (vfe_out_res_id) { - case CAM_VFE_BUS_VER3_VFE_OUT_RDI0: - switch (plane) { - case PLANE_Y: - if (is_lite) - wm_idx = 0; - else - wm_idx = 23; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_RDI1: - switch (plane) { - case PLANE_Y: - if (is_lite) - wm_idx = 1; - else - wm_idx = 24; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_RDI2: - switch (plane) { - case PLANE_Y: - if (is_lite) - wm_idx = 2; - else - wm_idx = 25; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_RDI3: - switch (plane) { - case PLANE_Y: - wm_idx = 3; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_FULL: - switch (plane) { - case PLANE_Y: - wm_idx = 0; - break; - case PLANE_C: - wm_idx = 1; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_DS4: - switch (plane) { - case PLANE_Y: - wm_idx = 2; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_DS16: - switch (plane) { - case PLANE_Y: - wm_idx = 3; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_FD: - switch (plane) { - case PLANE_Y: - wm_idx = 8; - break; - case PLANE_C: - wm_idx = 9; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP: - switch (plane) { - case PLANE_Y: - wm_idx = 10; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_2PD: - switch (plane) { - case PLANE_Y: - wm_idx = 21; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE: - switch (plane) { - case PLANE_Y: - wm_idx = 12; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST: - switch (plane) { - case PLANE_Y: - wm_idx = 13; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG: - switch (plane) { - case PLANE_Y: - wm_idx = 14; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF: - switch (plane) { - case PLANE_Y: - wm_idx = 20; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG: - switch (plane) { - case PLANE_Y: - wm_idx = 15; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST: - switch (plane) { - case PLANE_Y: - wm_idx = 16; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS: - switch (plane) { - case PLANE_Y: - wm_idx = 17; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS: - switch (plane) { - case PLANE_Y: - wm_idx = 18; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST: - switch (plane) { - case PLANE_Y: - wm_idx = 19; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP: - switch (plane) { - case PLANE_Y: - wm_idx = 4; - break; - case PLANE_C: - wm_idx = 5; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP: - switch (plane) { - case PLANE_Y: - wm_idx = 6; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP: - switch (plane) { - case PLANE_Y: - wm_idx = 7; - break; - default: - break; - } - break; - case CAM_VFE_BUS_VER3_VFE_OUT_LCR: - switch (plane) { - case PLANE_Y: - wm_idx = 22; - break; - default: - break; - } - default: - break; - } - - return wm_idx; -} - static int cam_vfe_bus_ver3_get_comp_vfe_out_res_id_list( - uint32_t comp_mask, uint32_t *out_list, int *num_out, bool is_lite) + uint32_t comp_mask, uint32_t *out_list, int *num_out) { int count = 0; - if (is_lite) - goto vfe_lite; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI0)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_0; - if (comp_mask & 0x3) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI1)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_1; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI2)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_2; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI3)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_3; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_FULL)) out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL; - if (comp_mask & 0x4) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_DS4)) out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4; - if (comp_mask & 0x8) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_DS16)) out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16; - if (comp_mask & 0x30) - out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL_DISP; - - if (comp_mask & 0x40) - out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4_DISP; - - if (comp_mask & 0x80) - out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16_DISP; - - if (comp_mask & 0x300) - out_list[count++] = CAM_ISP_IFE_OUT_RES_FD; - - if (comp_mask & 0x400) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP)) out_list[count++] = CAM_ISP_IFE_OUT_RES_RAW_DUMP; - if (comp_mask & 0x1000) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_FD)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FD; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_PDAF)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_PDAF; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE)) out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_HDR_BE; - if (comp_mask & 0x2000) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST)) out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST; - if (comp_mask & 0x4000) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG)) out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_TL_BG; - if (comp_mask & 0x8000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_AWB_BG; - - if (comp_mask & 0x10000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BHIST; - - if (comp_mask & 0x20000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_RS; - - if (comp_mask & 0x40000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_CS; - - if (comp_mask & 0x80000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_IHIST; - - if (comp_mask & 0x100000) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF)) out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BF; - if (comp_mask & 0x200000) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_AWB_BG; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_BHIST; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_RS; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_CS; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_IHIST; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_FULL_DISP; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS4_DISP; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_DS16_DISP; + + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_2PD)) out_list[count++] = CAM_ISP_IFE_OUT_RES_2PD; - if (comp_mask & 0x400000) + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_LCR)) out_list[count++] = CAM_ISP_IFE_OUT_RES_LCR; - if (comp_mask & 0x800000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_0; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_AWB_BFW; - if (comp_mask & 0x1000000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_1; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_2PD_STATS; - if (comp_mask & 0x2000000) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_2; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_AEC_BE; - *num_out = count; - return 0; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_LTM_STATS; -vfe_lite: - if (comp_mask & 0x1) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_0; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST)) + out_list[count++] = CAM_ISP_IFE_OUT_RES_STATS_GTM_BHIST; - if (comp_mask & 0x2) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_1; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE)) + out_list[count++] = CAM_ISP_IFE_LITE_OUT_RES_STATS_BE; - if (comp_mask & 0x4) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_2; - - if (comp_mask & 0x8) - out_list[count++] = CAM_ISP_IFE_OUT_RES_RDI_3; + if (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_GAMMA)) + out_list[count++] = CAM_ISP_IFE_LITE_OUT_RES_GAMMA; *num_out = count; return 0; @@ -1347,39 +1001,26 @@ static int cam_vfe_bus_ver3_acquire_wm( void *tasklet, enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, enum cam_vfe_bus_plane_type plane, - struct cam_isp_resource_node **wm_res, - uint32_t *client_done_mask, + struct cam_isp_resource_node *wm_res, uint32_t is_dual, enum cam_vfe_bus_ver3_comp_grp_type *comp_grp_id) { int32_t wm_idx = 0; - struct cam_isp_resource_node *wm_res_local = NULL; struct cam_vfe_bus_ver3_wm_resource_data *rsrc_data = NULL; + char wm_mode[50]; - *wm_res = NULL; + memset(wm_mode, '\0', sizeof(wm_mode)); - /* VFE OUT to WM is fixed. */ - wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, plane, - ver3_bus_priv->common_data.is_lite); - if (wm_idx < 0 || wm_idx >= ver3_bus_priv->num_client || - plane > PLANE_C) { - CAM_ERR(CAM_ISP, - "Unsupported VFE out_type:0x%X plane:%d wm_idx:%d max_idx:%d", - vfe_out_res_id, plane, wm_idx, - ver3_bus_priv->num_client - 1); - return -EINVAL; - } - - wm_res_local = &ver3_bus_priv->bus_client[wm_idx]; - if (wm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { + if (wm_res->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { CAM_ERR(CAM_ISP, "WM:%d not available state:%d", - wm_idx, wm_res_local->res_state); + wm_idx, wm_res->res_state); return -EALREADY; } - wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; - wm_res_local->tasklet_info = tasklet; + wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + wm_res->tasklet_info = tasklet; - rsrc_data = wm_res_local->res_priv; + rsrc_data = wm_res->res_priv; + wm_idx = rsrc_data->index; rsrc_data->format = out_port_info->format; rsrc_data->pack_fmt = cam_vfe_bus_ver3_get_packer_fmt(rsrc_data->format, wm_idx); @@ -1394,9 +1035,10 @@ static int cam_vfe_bus_ver3_acquire_wm( CAM_DBG(CAM_ISP, "WM:%d width %d height %d", rsrc_data->index, rsrc_data->width, rsrc_data->height); - if (ver3_bus_priv->common_data.is_lite || (rsrc_data->index > 22)) { + if ((vfe_out_res_id >= CAM_VFE_BUS_VER3_VFE_OUT_RDI0) && + (vfe_out_res_id <= CAM_VFE_BUS_VER3_VFE_OUT_RDI3)) { + rsrc_data->pack_fmt = 0x0; - /* WM 23-25 refers to RDI 0/ RDI 1/RDI 2 */ switch (rsrc_data->format) { case CAM_FORMAT_MIPI_RAW_6: case CAM_FORMAT_MIPI_RAW_8: @@ -1434,13 +1076,18 @@ static int cam_vfe_bus_ver3_acquire_wm( rsrc_data->format); return -EINVAL; } - } else if ((rsrc_data->index < 2) || - (rsrc_data->index == 8) || (rsrc_data->index == 9) || - (rsrc_data->index == 4) || (rsrc_data->index == 5)) { - /* - * WM 0-1 FULL_OUT, WM 8-9 FD_OUT, - * WM 4-5 FULL_DISP - */ + + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP) { + + rsrc_data->stride = rsrc_data->width; + rsrc_data->en_cfg = 0x1; + /* LSB aligned */ + rsrc_data->pack_fmt |= 0x10; + + } else if ((vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_FULL) || + (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_FD) || + (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP)) { + switch (rsrc_data->format) { case CAM_FORMAT_UBWC_NV12_4R: rsrc_data->en_ubwc = 1; @@ -1510,33 +1157,33 @@ static int cam_vfe_bus_ver3_acquire_wm( } break; default: - CAM_ERR(CAM_ISP, "Invalid format %d", - rsrc_data->format); + CAM_ERR(CAM_ISP, "Invalid format %d out_type:%d", + rsrc_data->format, vfe_out_res_id); return -EINVAL; } rsrc_data->en_cfg = 0x1; - } else if (rsrc_data->index == 20) { - /* WM 20 stats BAF */ + + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF) { + rsrc_data->en_cfg = (0x1 << 16) | 0x1; - } else if (rsrc_data->index > 11 && rsrc_data->index < 20) { - /* WM 12-19 stats */ + + } else if ((vfe_out_res_id >= CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE) && + (vfe_out_res_id <= CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST)) { + rsrc_data->width = 0; rsrc_data->height = 0; rsrc_data->stride = 1; rsrc_data->en_cfg = (0x1 << 16) | 0x1; - } else if (rsrc_data->index == 21) { - /* WM 21 PD */ + + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_2PD) { + rsrc_data->width = 0; rsrc_data->height = 0; rsrc_data->stride = 1; rsrc_data->en_cfg = (0x1 << 16) | 0x1; - } else if (rsrc_data->index == 10) { - /* WM 10 Raw dump */ - rsrc_data->stride = rsrc_data->width; - rsrc_data->en_cfg = 0x1; - /* LSB aligned */ - rsrc_data->pack_fmt |= 0x10; - } else if (rsrc_data->index == 22) { + + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_LCR) { + switch (rsrc_data->format) { case CAM_FORMAT_PLAIN16_16: rsrc_data->stride = ALIGNUP(rsrc_data->width * 2, 8); @@ -1545,32 +1192,114 @@ static int cam_vfe_bus_ver3_acquire_wm( rsrc_data->pack_fmt |= 0x10; break; default: - CAM_ERR(CAM_ISP, "Invalid format %d", - rsrc_data->format); + CAM_ERR(CAM_ISP, "Invalid format %d out_type:%d", + rsrc_data->format, vfe_out_res_id); return -EINVAL; } - } else if ((rsrc_data->index == 2) || (rsrc_data->index == 3) || - (rsrc_data->index == 6) || (rsrc_data->index == 7)) { - /* Write master 2-3 and 6-7 DS ports */ + + } else if ((vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_DS4) || + (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_DS16) || + (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP) || + (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP)) { rsrc_data->height = rsrc_data->height / 2; rsrc_data->width = rsrc_data->width / 2; rsrc_data->en_cfg = 0x1; + } else if ((vfe_out_res_id >= CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW) && + (vfe_out_res_id <= CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS)) { + switch (rsrc_data->format) { + case CAM_FORMAT_PLAIN64: + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d out_type:%d", + rsrc_data->format, vfe_out_res_id); + return -EINVAL; + } + + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS) { + switch (rsrc_data->format) { + case CAM_FORMAT_PLAIN32: + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d out_type:%d", + rsrc_data->format, vfe_out_res_id); + return -EINVAL; + } + + } else if ((vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE) || + (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST)) { + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE) { + switch (rsrc_data->format) { + case CAM_FORMAT_MIPI_RAW_8: + case CAM_FORMAT_MIPI_RAW_10: + case CAM_FORMAT_MIPI_RAW_12: + case CAM_FORMAT_PLAIN8: + case CAM_FORMAT_PLAIN16_8: + case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_12: + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d out_type:%d", + rsrc_data->format, vfe_out_res_id); + return -EINVAL; + } + + } else if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_GAMMA) { + switch (rsrc_data->format) { + case CAM_FORMAT_PLAIN64: + rsrc_data->width = 0; + rsrc_data->height = 0; + rsrc_data->stride = 1; + rsrc_data->en_cfg = (0x1 << 16) | 0x1; + break; + default: + CAM_ERR(CAM_ISP, "Invalid format %d out_type:%d", + rsrc_data->format, vfe_out_res_id); + return -EINVAL; + } + } else { - CAM_ERR(CAM_ISP, "Invalid WM:%d requested", rsrc_data->index); + CAM_ERR(CAM_ISP, "Invalid out_type:%d requested", + vfe_out_res_id); return -EINVAL; } - *wm_res = wm_res_local; *comp_grp_id = rsrc_data->hw_regs->comp_group; - *client_done_mask |= (1 << wm_idx); + + switch (rsrc_data->en_cfg) { + case 0x1: + strlcpy(wm_mode, "line-based", sizeof(wm_mode)); + break; + case ((0x1 << 16) | 0x1): + strlcpy(wm_mode, "frame-based", sizeof(wm_mode)); + break; + case ((0x2 << 16) | 0x1): + strlcpy(wm_mode, "index-based", sizeof(wm_mode)); + break; + } CAM_DBG(CAM_ISP, - "VFE:%d WM:%d processed width:%d height:%d format:0x%X en_ubwc:%d", + "VFE:%d WM:%d processed width:%d height:%d format:0x%X en_ubwc:%d %s", rsrc_data->common_data->core_index, rsrc_data->index, rsrc_data->width, rsrc_data->height, rsrc_data->format, - rsrc_data->en_ubwc); + rsrc_data->en_ubwc, wm_mode); return 0; } @@ -1758,15 +1487,6 @@ static int cam_vfe_bus_ver3_deinit_wm_resource( return 0; } -static void cam_vfe_bus_ver3_add_wm_to_comp_grp( - struct cam_isp_resource_node *comp_grp, - uint32_t composite_mask) -{ - struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = comp_grp->res_priv; - - rsrc_data->composite_mask |= composite_mask; -} - static bool cam_vfe_bus_ver3_match_comp_grp( struct cam_vfe_bus_ver3_priv *ver3_bus_priv, struct cam_isp_resource_node **comp_grp, @@ -1804,28 +1524,24 @@ static bool cam_vfe_bus_ver3_match_comp_grp( static int cam_vfe_bus_ver3_acquire_comp_grp( struct cam_vfe_bus_ver3_priv *ver3_bus_priv, - struct cam_isp_out_port_generic_info *out_port_info, void *tasklet, uint32_t is_dual, uint32_t is_master, - enum cam_vfe_bus_ver3_vfe_core_id dual_slave_core, struct cam_isp_resource_node **comp_grp, - enum cam_vfe_bus_ver3_comp_grp_type comp_grp_id) + struct cam_vfe_bus_ver3_comp_grp_acquire_args *comp_acq_args) { int rc = 0; struct cam_isp_resource_node *comp_grp_local = NULL; struct cam_vfe_bus_ver3_comp_grp_data *rsrc_data = NULL; bool previously_acquired = false; - if (comp_grp_id >= CAM_VFE_BUS_VER3_COMP_GRP_0 && - comp_grp_id <= CAM_VFE_BUS_VER3_COMP_GRP_13) { - /* Check if matching comp_grp has already been acquired */ - previously_acquired = cam_vfe_bus_ver3_match_comp_grp( - ver3_bus_priv, &comp_grp_local, comp_grp_id); - } + /* Check if matching comp_grp has already been acquired */ + previously_acquired = cam_vfe_bus_ver3_match_comp_grp( + ver3_bus_priv, &comp_grp_local, comp_acq_args->comp_grp_id); if (!comp_grp_local) { - CAM_ERR(CAM_ISP, "Invalid comp_grp:%d", comp_grp_id); + CAM_ERR(CAM_ISP, "Invalid comp_grp:%d", + comp_acq_args->comp_grp_id); return -ENODEV; } @@ -1860,6 +1576,7 @@ static int cam_vfe_bus_ver3_acquire_comp_grp( rsrc_data->common_data->core_index, rsrc_data->comp_grp_type); rsrc_data->acquire_dev_cnt++; + rsrc_data->composite_mask |= comp_acq_args->composite_mask; *comp_grp = comp_grp_local; return rc; @@ -1944,6 +1661,9 @@ static int cam_vfe_bus_ver3_start_comp_grp( if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) return 0; + if (!common_data->comp_config_needed) + goto skip_comp_cfg; + if (rsrc_data->is_dual) { if (rsrc_data->is_master) { val = cam_io_r_mb(common_data->mem_base + @@ -1981,6 +1701,8 @@ static int cam_vfe_bus_ver3_start_comp_grp( } } +skip_comp_cfg: + if (rsrc_data->ubwc_static_ctrl) { val = cam_io_r_mb(common_data->mem_base + common_data->common_reg->ubwc_static_ctrl); @@ -2151,15 +1873,13 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, int i; enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id; uint32_t format; - int num_wm; struct cam_vfe_bus_ver3_priv *ver3_bus_priv = bus_priv; struct cam_vfe_acquire_args *acq_args = acquire_args; struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args; struct cam_isp_resource_node *rsrc_node = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; uint32_t secure_caps = 0, mode; - enum cam_vfe_bus_ver3_comp_grp_type comp_grp_id; - uint32_t client_done_mask = 0; + struct cam_vfe_bus_ver3_comp_grp_acquire_args comp_acq_args = {0}; if (!bus_priv || !acquire_args) { CAM_ERR(CAM_ISP, "Invalid Param"); @@ -2178,10 +1898,6 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_MAX) return -ENODEV; - num_wm = cam_vfe_bus_ver3_get_num_wm(vfe_out_res_id, format); - if (num_wm < 1) - return -EINVAL; - rsrc_node = &ver3_bus_priv->vfe_out[vfe_out_res_id]; if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { CAM_ERR(CAM_ISP, @@ -2195,6 +1911,16 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, rsrc_data->common_data->event_cb = acq_args->event_cb; rsrc_data->priv = acq_args->priv; rsrc_data->bus_priv = ver3_bus_priv; + comp_acq_args.composite_mask = (1 << vfe_out_res_id); + + /* for some hw versions, buf done is not received from vfe but + * from IP external to VFE. In such case, we get the controller + * from hw manager and assign it here + */ + if (!(ver3_bus_priv->common_data.supported_irq & + CAM_VFE_HW_IRQ_CAP_BUF_DONE)) + rsrc_data->common_data->buf_done_controller = + acq_args->buf_done_controller; secure_caps = cam_vfe_bus_ver3_can_be_secure( rsrc_data->out_type); @@ -2224,24 +1950,27 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, mutex_unlock(&rsrc_data->common_data->bus_mutex); ver3_bus_priv->tasklet_info = acq_args->tasklet; - rsrc_data->num_wm = num_wm; rsrc_node->rdi_only_ctx = 0; rsrc_node->res_id = out_acquire_args->out_port_info->res_type; rsrc_node->tasklet_info = acq_args->tasklet; rsrc_node->cdm_ops = out_acquire_args->cdm_ops; rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops; + rsrc_data->format = out_acquire_args->out_port_info->format; + + if ((rsrc_data->out_type == CAM_VFE_BUS_VER3_VFE_OUT_FD) && + (rsrc_data->format == CAM_FORMAT_Y_ONLY)) + rsrc_data->num_wm = 1; /* Acquire WM and retrieve COMP GRP ID */ - for (i = 0; i < num_wm; i++) { + for (i = 0; i < rsrc_data->num_wm; i++) { rc = cam_vfe_bus_ver3_acquire_wm(ver3_bus_priv, out_acquire_args->out_port_info, acq_args->tasklet, vfe_out_res_id, i, &rsrc_data->wm_res[i], - &client_done_mask, out_acquire_args->is_dual, - &comp_grp_id); + &comp_acq_args.comp_grp_id); if (rc) { CAM_ERR(CAM_ISP, "Failed to acquire WM VFE:%d out_type:%d rc:%d", @@ -2251,15 +1980,14 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, } } + /* Acquire composite group using COMP GRP ID */ rc = cam_vfe_bus_ver3_acquire_comp_grp(ver3_bus_priv, - out_acquire_args->out_port_info, acq_args->tasklet, out_acquire_args->is_dual, out_acquire_args->is_master, - out_acquire_args->dual_slave_core, &rsrc_data->comp_grp, - comp_grp_id); + &comp_acq_args); if (rc) { CAM_ERR(CAM_ISP, "Failed to acquire comp_grp VFE:%d out_typp:%d rc:%d", @@ -2271,9 +1999,6 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, rsrc_data->is_dual = out_acquire_args->is_dual; rsrc_data->is_master = out_acquire_args->is_master; - cam_vfe_bus_ver3_add_wm_to_comp_grp(rsrc_data->comp_grp, - client_done_mask); - rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; out_acquire_args->rsrc_node = rsrc_node; @@ -2283,7 +2008,7 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, release_wm: for (i--; i >= 0; i--) cam_vfe_bus_ver3_release_wm(ver3_bus_priv, - rsrc_data->wm_res[i]); + &rsrc_data->wm_res[i]); cam_vfe_bus_ver3_release_comp_grp(ver3_bus_priv, rsrc_data->comp_grp); @@ -2315,8 +2040,11 @@ static int cam_vfe_bus_ver3_release_vfe_out(void *bus_priv, void *release_args, } for (i = 0; i < rsrc_data->num_wm; i++) - cam_vfe_bus_ver3_release_wm(bus_priv, rsrc_data->wm_res[i]); - rsrc_data->num_wm = 0; + cam_vfe_bus_ver3_release_wm(bus_priv, &rsrc_data->wm_res[i]); + + if ((rsrc_data->out_type == CAM_VFE_BUS_VER3_VFE_OUT_FD) && + (rsrc_data->format == CAM_FORMAT_Y_ONLY)) + rsrc_data->num_wm = 2; if (rsrc_data->comp_grp) cam_vfe_bus_ver3_release_comp_grp(bus_priv, @@ -2390,7 +2118,7 @@ static int cam_vfe_bus_ver3_start_vfe_out( } for (i = 0; i < rsrc_data->num_wm; i++) - rc = cam_vfe_bus_ver3_start_wm(rsrc_data->wm_res[i]); + rc = cam_vfe_bus_ver3_start_wm(&rsrc_data->wm_res[i]); memset(bus_irq_reg_mask, 0, sizeof(bus_irq_reg_mask)); rc = cam_vfe_bus_ver3_start_comp_grp(rsrc_data->comp_grp, @@ -2400,7 +2128,7 @@ static int cam_vfe_bus_ver3_start_vfe_out( goto end; vfe_out->irq_handle = cam_irq_controller_subscribe_irq( - common_data->bus_irq_controller, + common_data->buf_done_controller, CAM_IRQ_PRIORITY_1, bus_irq_reg_mask, vfe_out, @@ -2420,7 +2148,8 @@ static int cam_vfe_bus_ver3_start_vfe_out( && !vfe_out->rdi_only_ctx) goto end; - if (!common_data->rup_irq_handle[source_group]) { + if ((common_data->supported_irq & CAM_VFE_HW_IRQ_CAP_RUP) && + (!common_data->rup_irq_handle[source_group])) { memset(rup_irq_reg_mask, 0, sizeof(rup_irq_reg_mask)); rup_irq_reg_mask[CAM_VFE_BUS_VER3_IRQ_REG0] |= 0x1 << source_group; @@ -2479,7 +2208,7 @@ static int cam_vfe_bus_ver3_stop_vfe_out( rc = cam_vfe_bus_ver3_stop_comp_grp(rsrc_data->comp_grp); for (i = 0; i < rsrc_data->num_wm; i++) - rc = cam_vfe_bus_ver3_stop_wm(rsrc_data->wm_res[i]); + rc = cam_vfe_bus_ver3_stop_wm(&rsrc_data->wm_res[i]); if (common_data->rup_irq_handle[rsrc_data->source_group]) { rc = cam_irq_controller_unsubscribe_irq( @@ -2580,7 +2309,7 @@ static uint32_t cam_vfe_bus_ver3_get_last_consumed_addr( rsrc_node = &bus_priv->vfe_out[res_id]; rsrc_data = rsrc_node->res_priv; - wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv; + wm_rsrc_data = rsrc_data->wm_res[PLANE_Y].res_priv; val = cam_io_r_mb( wm_rsrc_data->common_data->mem_base + @@ -2619,8 +2348,7 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( evt_info.hw_idx = vfe_out->hw_intf->hw_idx; rc = cam_vfe_bus_ver3_get_comp_vfe_out_res_id_list( - comp_mask, out_list, &num_out, - rsrc_data->common_data->is_lite); + comp_mask, out_list, &num_out); for (i = 0; i < num_out; i++) { evt_info.res_id = out_list[i]; evt_info.reg_val = @@ -2647,7 +2375,7 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, { struct cam_isp_resource_node *vfe_out = NULL; struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; - int rc = 0, i; + int rc = 0, i = 0; int32_t vfe_out_type = ver3_hw_info->vfe_out_hw_info[index].vfe_out_type; @@ -2689,6 +2417,26 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, rsrc_data->max_height = ver3_hw_info->vfe_out_hw_info[index].max_height; rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE; + rsrc_data->num_wm = ver3_hw_info->vfe_out_hw_info[index].num_wm; + + rsrc_data->wm_res = kzalloc((sizeof(struct cam_isp_resource_node) * + rsrc_data->num_wm), GFP_KERNEL); + if (!rsrc_data->wm_res) { + CAM_ERR(CAM_ISP, "Failed to alloc for wm_res"); + return -ENOMEM; + } + + for (i = 0; i < rsrc_data->num_wm; i++) { + rc = cam_vfe_bus_ver3_init_wm_resource( + ver3_hw_info->vfe_out_hw_info[index].wm_idx[i], + ver3_bus_priv, ver3_hw_info, + &rsrc_data->wm_res[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, "VFE:%d init WM:%d failed rc:%d", + ver3_bus_priv->common_data.core_index, i, rc); + return rc; + } + } vfe_out->start = cam_vfe_bus_ver3_start_vfe_out; vfe_out->stop = cam_vfe_bus_ver3_stop_vfe_out; @@ -2711,6 +2459,7 @@ static int cam_vfe_bus_ver3_deinit_vfe_out_resource( struct cam_isp_resource_node *vfe_out) { struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = vfe_out->res_priv; + int rc = 0, i = 0; if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_UNAVAILABLE) { /* @@ -2733,6 +2482,16 @@ static int cam_vfe_bus_ver3_deinit_vfe_out_resource( if (!rsrc_data) return -ENOMEM; + + for (i = 0; i < rsrc_data->num_wm; i++) { + rc = cam_vfe_bus_ver3_deinit_wm_resource(&rsrc_data->wm_res[i]); + if (rc < 0) + CAM_ERR(CAM_ISP, + "VFE:%d deinit WM:%d failed rc:%d", + rsrc_data->common_data->core_index, i, rc); + } + + rsrc_data->wm_res = NULL; kfree(rsrc_data); return 0; @@ -2752,8 +2511,7 @@ static int cam_vfe_bus_ver3_print_dimensions( rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; for (i = 0; i < rsrc_data->num_wm; i++) { - wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, i, - bus_priv->common_data.is_lite); + wm_idx = 0; if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { CAM_ERR(CAM_ISP, "Unsupported VFE out %d", vfe_out_res_id); @@ -3073,7 +2831,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, return -ENOMEM; } - wm_data = vfe_out_data->wm_res[i]->res_priv; + wm_data = vfe_out_data->wm_res[i].res_priv; ubwc_client = wm_data->hw_regs->ubwc_regs; /* Disable frame header in case it was previously enabled */ @@ -3273,7 +3031,7 @@ static int cam_vfe_bus_ver3_update_hfr(void *priv, void *cmd_args, return -ENOMEM; } - wm_data = vfe_out_data->wm_res[i]->res_priv; + wm_data = vfe_out_data->wm_res[i].res_priv; if (((!bus_priv->common_data.is_lite && wm_data->index > 22) || bus_priv->common_data.is_lite) && @@ -3383,7 +3141,7 @@ static int cam_vfe_bus_ver3_update_ubwc_config_v2(void *cmd_args) for (i = 0; i < vfe_out_data->num_wm; i++) { - wm_data = vfe_out_data->wm_res[i]->res_priv; + wm_data = vfe_out_data->wm_res[i].res_priv; ubwc_generic_plane_cfg = &ubwc_generic_cfg->ubwc_plane_cfg[i]; if (!wm_data->hw_regs->ubwc_regs) { @@ -3505,7 +3263,7 @@ static int cam_vfe_bus_ver3_update_stripe_cfg(void *priv, void *cmd_args, (stripe_args->dual_cfg->num_ports * CAM_PACKET_MAX_PLANES)) + (outport_id * CAM_PACKET_MAX_PLANES); for (i = 0; i < vfe_out_data->num_wm; i++) { - wm_data = vfe_out_data->wm_res[i]->res_priv; + wm_data = vfe_out_data->wm_res[i].res_priv; stripe_config = (struct cam_isp_dual_stripe_config *) &stripe_args->dual_cfg->stripes[ports_plane_idx + i]; wm_data->width = stripe_config->width; @@ -3556,7 +3314,7 @@ static int cam_vfe_bus_ver3_update_wm_config( } for (i = 0; i < vfe_out_data->num_wm; i++) { - wm_data = vfe_out_data->wm_res[i]->res_priv; + wm_data = vfe_out_data->wm_res[i].res_priv; if (wm_config->wm_mode > 0x2) { CAM_ERR(CAM_ISP, "Invalid wm_mode: 0x%X WM:%d", @@ -3625,20 +3383,22 @@ static int cam_vfe_bus_ver3_init_hw(void *hw_priv, return -EFAULT; } - bus_priv->rup_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_ver3_handle_rup_irq, - NULL, - NULL, - NULL); + if (bus_priv->common_data.supported_irq & CAM_VFE_HW_IRQ_CAP_RUP) { + bus_priv->rup_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_ver3_handle_rup_irq, + NULL, + NULL, + NULL); - if (bus_priv->rup_irq_handle < 1) { - CAM_ERR(CAM_ISP, "Failed to subscribe BUS (rup) IRQ"); - bus_priv->rup_irq_handle = 0; - return -EFAULT; + if (bus_priv->rup_irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS (rup) IRQ"); + bus_priv->rup_irq_handle = 0; + return -EFAULT; + } } if (bus_priv->tasklet_info != NULL) { @@ -3659,6 +3419,13 @@ static int cam_vfe_bus_ver3_init_hw(void *hw_priv, } } + /* We take the controller only if the buf done is supported on vfe side + * for some hw, it is taken from IP extenal to VFE like CSID + */ + if ((bus_priv->common_data.supported_irq & CAM_VFE_HW_IRQ_CAP_BUF_DONE)) + bus_priv->common_data.buf_done_controller = + bus_priv->common_data.bus_irq_controller; + /* no clock gating at bus input */ CAM_DBG(CAM_ISP, "Overriding clock gating at bus input"); cam_io_w_mb(0x3FFFFFF, bus_priv->common_data.mem_base + @@ -3911,6 +3678,7 @@ int cam_vfe_bus_ver3_init( bus_priv->num_client = ver3_hw_info->num_client; bus_priv->num_out = ver3_hw_info->num_out; + bus_priv->num_comp_grp = ver3_hw_info->num_comp_grp; bus_priv->top_irq_shift = ver3_hw_info->top_irq_shift; bus_priv->max_out_res = ver3_hw_info->max_out_res; bus_priv->common_data.num_sec_out = 0; @@ -3929,6 +3697,25 @@ int cam_vfe_bus_ver3_init( bus_priv->common_data.support_consumed_addr = ver3_hw_info->support_consumed_addr; bus_priv->common_data.disable_ubwc_comp = false; + bus_priv->common_data.supported_irq = ver3_hw_info->supported_irq; + bus_priv->common_data.comp_config_needed = + ver3_hw_info->comp_cfg_needed; + + bus_priv->comp_grp = kzalloc((sizeof(struct cam_isp_resource_node) * + bus_priv->num_comp_grp), GFP_KERNEL); + if (!bus_priv->comp_grp) { + CAM_ERR(CAM_ISP, "Failed to alloc for bus comp groups"); + rc = -ENOMEM; + goto free_bus_priv; + } + + bus_priv->vfe_out = kzalloc((sizeof(struct cam_isp_resource_node) * + bus_priv->num_out), GFP_KERNEL); + if (!bus_priv->vfe_out) { + CAM_ERR(CAM_ISP, "Failed to alloc for bus out res"); + rc = -ENOMEM; + goto free_comp_grp; + } for (i = 0; i < CAM_VFE_BUS_VER3_SRC_GRP_MAX; i++) bus_priv->common_data.rup_irq_handle[i] = 0; @@ -3940,32 +3727,24 @@ int cam_vfe_bus_ver3_init( &bus_priv->common_data.bus_irq_controller, false); if (rc) { CAM_ERR(CAM_ISP, "Init bus_irq_controller failed"); - goto free_bus_priv; + goto free_vfe_out; } - rc = cam_irq_controller_init("vfe_bus_rup", - bus_priv->common_data.mem_base, - &ver3_hw_info->common_reg.irq_reg_info, - &bus_priv->common_data.rup_irq_controller, false); - if (rc) { - CAM_ERR(CAM_ISP, "Init rup_irq_controller failed"); - goto free_bus_priv; + if (bus_priv->common_data.supported_irq & CAM_VFE_HW_IRQ_CAP_RUP) { + rc = cam_irq_controller_init("vfe_bus_rup", + bus_priv->common_data.mem_base, + &ver3_hw_info->common_reg.irq_reg_info, + &bus_priv->common_data.rup_irq_controller, false); + if (rc) { + CAM_ERR(CAM_ISP, "Init rup_irq_controller failed"); + goto free_vfe_out; + } } INIT_LIST_HEAD(&bus_priv->free_comp_grp); INIT_LIST_HEAD(&bus_priv->used_comp_grp); - for (i = 0; i < bus_priv->num_client; i++) { - rc = cam_vfe_bus_ver3_init_wm_resource(i, bus_priv, bus_hw_info, - &bus_priv->bus_client[i]); - if (rc < 0) { - CAM_ERR(CAM_ISP, "VFE:%d init WM:%d failed rc:%d", - bus_priv->common_data.core_index, i, rc); - goto deinit_wm; - } - } - - for (i = 0; i < CAM_VFE_BUS_VER3_COMP_GRP_MAX; i++) { + for (i = 0; i < bus_priv->num_comp_grp; i++) { rc = cam_vfe_bus_ver3_init_comp_grp(i, soc_info, bus_priv, bus_hw_info, &bus_priv->comp_grp[i]); @@ -4018,15 +3797,15 @@ deinit_vfe_out: deinit_comp_grp: if (i < 0) - i = CAM_VFE_BUS_VER3_COMP_GRP_MAX; + i = bus_priv->num_comp_grp; for (--i; i >= 0; i--) cam_vfe_bus_ver3_deinit_comp_grp(&bus_priv->comp_grp[i]); -deinit_wm: - if (i < 0) - i = bus_priv->num_client; - for (--i; i >= 0; i--) - cam_vfe_bus_ver3_deinit_wm_resource(&bus_priv->bus_client[i]); +free_vfe_out: + kfree(bus_priv->vfe_out); + +free_comp_grp: + kfree(bus_priv->comp_grp); free_bus_priv: kfree(vfe_bus_local->bus_priv); @@ -4066,15 +3845,6 @@ int cam_vfe_bus_ver3_deinit( bus_priv->common_data.hw_init = false; spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags); - for (i = 0; i < bus_priv->num_client; i++) { - rc = cam_vfe_bus_ver3_deinit_wm_resource( - &bus_priv->bus_client[i]); - if (rc < 0) - CAM_ERR(CAM_ISP, - "VFE:%d deinit WM:%d failed rc:%d", - bus_priv->common_data.core_index, i, rc); - } - for (i = 0; i < CAM_VFE_BUS_VER3_COMP_GRP_MAX; i++) { rc = cam_vfe_bus_ver3_deinit_comp_grp(&bus_priv->comp_grp[i]); if (rc < 0) @@ -4107,6 +3877,9 @@ int cam_vfe_bus_ver3_deinit( CAM_ERR(CAM_ISP, "Deinit RUP IRQ Controller failed rc=%d", rc); + kfree(bus_priv->comp_grp); + kfree(bus_priv->vfe_out); + mutex_destroy(&bus_priv->common_data.bus_mutex); kfree(vfe_bus_local->bus_priv); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index fd00b852888e..50fd2e42443c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -10,7 +10,6 @@ #include "cam_irq_controller.h" #include "cam_vfe_bus.h" -#define CAM_VFE_BUS_VER3_MAX_CLIENTS 26 #define CAM_VFE_BUS_VER3_MAX_SUB_GRPS 6 #define CAM_VFE_BUS_VER3_MAX_MID_PER_PORT 4 #define CAM_VFE_BUS_VER3_480_MAX_CLIENTS 26 @@ -80,7 +79,11 @@ enum cam_vfe_bus_ver3_vfe_out_type { CAM_VFE_BUS_VER3_VFE_OUT_LCR, CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW, CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE, CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST, + CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE, + CAM_VFE_BUS_VER3_VFE_OUT_GAMMA, CAM_VFE_BUS_VER3_VFE_OUT_MAX, }; @@ -185,10 +188,13 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { * @num_client: Total number of write clients * @bus_client_reg: Bus client register info * @vfe_out_hw_info: VFE output capability + * @num_comp_grp: Number of composite groups * @comp_done_shift: Mask shift for comp done mask * @top_irq_shift: Mask shift for top level BUS WR irq * @support_consumed_addr: Indicate if bus support consumed address * @max_out_res: Max vfe out resource value supported for hw + * @supported_irq: Mask to indicate the IRQ supported + * @comp_cfg_needed: Composite group config is needed for hw */ struct cam_vfe_bus_ver3_hw_info { struct cam_vfe_bus_ver3_reg_offset_common common_reg; @@ -198,10 +204,13 @@ struct cam_vfe_bus_ver3_hw_info { uint32_t num_out; struct cam_vfe_bus_ver3_vfe_out_hw_info vfe_out_hw_info[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; + uint32_t num_comp_grp; uint32_t comp_done_shift; uint32_t top_irq_shift; bool support_consumed_addr; uint32_t max_out_res; + uint32_t supported_irq; + bool comp_cfg_needed; }; /* From d71c9ccbe5f6f775de5fecc0cb8361fc7fa5eeb5 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Wed, 30 Sep 2020 18:52:14 -0700 Subject: [PATCH 573/790] msm: camera: cpas: Update jpeg qosgen settings Use OT limit as 16 for jpeg niu path. This help in controlling jpeg bw flow and to avoid any backpressure on IFE paths. CRs-Fixed: 2789495 Change-Id: I458fa076f59915a7c11be9e7c3d78b412c5c7c5a Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cpas_top/cpastop_v580_100.h | 12 ++++++------ drivers/cam_cpas/cpas_top/cpastop_v580_custom.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h index 550adc7e0861..9855fdf6821c 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h @@ -953,25 +953,25 @@ static struct cam_camnoc_specific .enable = false, }, .qosgen_mainctl = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ - .value = 0x0, + .value = 0x2, }, .qosgen_shaping_low = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ - .value = 0x0, + .value = 0x10101010, }, .qosgen_shaping_high = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ - .value = 0x0, + .value = 0x10101010, }, }, { diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h index cf6e51367f2a..99f9302b575c 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h @@ -953,25 +953,25 @@ static struct cam_camnoc_specific .enable = false, }, .qosgen_mainctl = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ - .value = 0x0, + .value = 0x2, }, .qosgen_shaping_low = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ - .value = 0x0, + .value = 0x10101010, }, .qosgen_shaping_high = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ - .value = 0x0, + .value = 0x10101010, }, }, { From fdff0bcadc140ae669ebd8040759c17c0e2bdaf0 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Tue, 27 Oct 2020 01:44:04 -0700 Subject: [PATCH 574/790] msm: camera: cpas: Removing getting clk rate in cpas dump cpas dump may be called from tasklets where sleep is not allowed. Remove calling clk get rate APIs which will internally have mutexes which can sleep. CRs-Fixed: 2797701 Change-Id: Ia46238c26e4f39978f58643716a43fbdb60e8ae6 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index ca777c7a01bb..778dfd5e8544 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1915,15 +1915,6 @@ static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) curr_node->mnoc_ab_bw, curr_node->mnoc_ib_bw); } - if (cpas_core->streamon_clients > 0) { - /* - * Means, cpas has clocks turned on, so we can query clk freq. - * Print clk frequencies that cpas enables - this will print - * camcc_ahb, camcc_axi, gcc_hf, gcc_sf as well. - */ - cam_soc_util_print_clk_freq(&cpas_hw->soc_info); - } - cam_cpas_dump_monitor_array(cpas_core); return 0; From 297cc95f5f3ad13ffab3bcb301bc97241c2e31c1 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Tue, 27 Oct 2020 02:48:53 -0700 Subject: [PATCH 575/790] msm: camera: jpeg: Add traces to profile jpeg processing time Add traces before starting jpeg encode and once done irq is generated from hw. CRs-Fixed: 2789495 Change-Id: I02da722ed9ba0b7f4450536e35d298b8757c0655 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 3 +++ drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 222924fe75b0..737a681dfcb3 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -139,6 +139,9 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data, rc = -EINVAL; goto end_error; } + + CAM_TRACE(CAM_JPEG, "Start JPEG ENC Req %llu", config_args->request_id); + rc = hw_mgr->devices[dev_type][0]->hw_ops.start( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index 62d0cb562aa5..8661dbfc72e6 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -202,6 +202,7 @@ irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data) if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) { spin_lock(&jpeg_enc_dev->hw_lock); if (core_info->core_state == CAM_JPEG_ENC_CORE_READY) { + CAM_TRACE(CAM_JPEG, "FrameDone IRQ"); encoded_size = cam_io_r_mb(mem_base + core_info->jpeg_enc_hw_info->reg_offset.encode_size); if (core_info->irq_cb.jpeg_hw_mgr_cb) { From 4e09bf5f9756491d43c1a455553f722401b8dfcc Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Fri, 23 Oct 2020 13:56:35 -0700 Subject: [PATCH 576/790] msm: camera: smmu: Avoid NULL dereference in cam_smmu_alloc_firmware The iommu domain we grab from iommu_get_domain_for_dev can be NULL. Eventually we will hit a NULL dereference in the cam_smmu_alloc_firmware due to the missing check. Modify the existing check to account for the possiblity of a NULL domain and bail early. CRs-Fixed: 2804766 Change-Id: I201260c3559b847cfb0bf7f85226816af148671d Signed-off-by: Fernando Pacheco --- drivers/cam_smmu/cam_smmu_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 48ac8f0ebeb9..e2fdfeed93a9 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -3552,7 +3552,7 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, /* create a virtual mapping */ if (cb->io_support) { cb->domain = iommu_get_domain_for_dev(dev); - if (IS_ERR(cb->domain)) { + if (IS_ERR_OR_NULL(cb->domain)) { CAM_ERR(CAM_SMMU, "Error: create domain Failed"); rc = -ENODEV; goto end; From 22004e3a95df817e575f3e7606ad756dbf8c54fb Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 22 Oct 2020 23:03:57 +0530 Subject: [PATCH 577/790] msm: camera: reqmgr: Move skip frame log to rate limit for WQ congestion In the case of workqueue congestion move the skip frame logs to rate info limit. CRs-Fixed: 2800932 Change-Id: I96988ff73ae182d55eb3f3d15de9b02f13c34b39 Signed-off-by: Wyes Karny --- drivers/cam_req_mgr/cam_req_mgr_core.c | 60 ++++++++++++++------------ drivers/cam_req_mgr/cam_req_mgr_core.h | 6 ++- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index e09e1a1470dc..f9b8ed3c7f9a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -54,7 +54,8 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->prev_sof_timestamp = 0; link->skip_init_frame = false; link->num_sync_links = 0; - link->last_applied_jiffies = 0; + link->last_sof_trigger_jiffies = 0; + link->wq_congestion = false; atomic_set(&link->eof_event_cnt, 0); for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { @@ -214,11 +215,16 @@ static void __cam_req_mgr_find_dev_name( if (dev->dev_info.p_delay == pd) { if (masked_val & (1 << dev->dev_bit)) continue; - - CAM_INFO(CAM_CRM, - "Skip Frame: req: %lld not ready on link: 0x%x for pd: %d dev: %s open_req count: %d", - req_id, link->link_hdl, pd, dev->dev_info.name, - link->open_req_cnt); + if (link->wq_congestion) + CAM_INFO_RATE_LIMIT(CAM_CRM, + "WQ congestion, Skip Frame: req: %lld not ready on link: 0x%x for pd: %d dev: %s open_req count: %d", + req_id, link->link_hdl, pd, + dev->dev_info.name, link->open_req_cnt); + else + CAM_INFO(CAM_CRM, + "Skip Frame: req: %lld not ready on link: 0x%x for pd: %d dev: %s open_req count: %d", + req_id, link->link_hdl, pd, + dev->dev_info.name, link->open_req_cnt); } } } @@ -1622,7 +1628,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, { int rc = 0, idx, i; int reset_step = 0; - bool check_retry_cnt = false; uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; struct cam_req_mgr_req_queue *in_q; @@ -1656,18 +1661,18 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (slot->status == CRM_SLOT_STATUS_NO_REQ) { CAM_DBG(CAM_CRM, "No Pending req"); rc = 0; - goto error; + goto end; } if ((trigger != CAM_TRIGGER_POINT_SOF) && (trigger != CAM_TRIGGER_POINT_EOF)) - goto error; + goto end; if ((trigger == CAM_TRIGGER_POINT_EOF) && (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) { CAM_DBG(CAM_CRM, "Applying for last SOF fails"); rc = -EINVAL; - goto error; + goto end; } if (trigger == CAM_TRIGGER_POINT_SOF) { @@ -1678,11 +1683,19 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->prev_sof_timestamp = link->sof_timestamp; link->sof_timestamp = trigger_data->sof_timestamp_val; + /* Check for WQ congestion */ + if (jiffies_to_msecs(jiffies - + link->last_sof_trigger_jiffies) < + MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS) + link->wq_congestion = true; + else + link->wq_congestion = false; + if (link->trigger_mask) { CAM_ERR_RATE_LIMIT(CAM_CRM, "Applying for last EOF fails"); rc = -EINVAL; - goto error; + goto end; } if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { @@ -1733,7 +1746,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } spin_unlock_bh(&link->link_state_spin_lock); __cam_req_mgr_notify_frame_skip(link, trigger); - goto error; + goto end; } } @@ -1745,11 +1758,8 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->max_delay == 1) max_retry++; - if (jiffies_to_msecs(jiffies - link->last_applied_jiffies) > - MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS) - check_retry_cnt = true; - - if ((in_q->last_applied_idx < in_q->rd_idx) && check_retry_cnt) { + if ((in_q->last_applied_idx < in_q->rd_idx) && + !link->wq_congestion) { link->retry_cnt++; if (link->retry_cnt == max_retry) { CAM_DBG(CAM_CRM, @@ -1769,7 +1779,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->retry_cnt = 0; } } else - CAM_WARN(CAM_CRM, + CAM_WARN_RATE_LIMIT(CAM_CRM, "workqueue congestion, last applied idx:%d rd idx:%d", in_q->last_applied_idx, in_q->rd_idx); @@ -1831,20 +1841,14 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->open_req_cnt--; } } - +end: /* - * Only update the jiffies of last applied request - * for SOF trigger, since it is used to protect from + * Only update the jiffies for SOF trigger, + * since it is used to protect from * applying fails in ISP which is triggered at SOF. - * And, also don't need to do update for error case - * since error case doesn't check the retry count. */ if (trigger == CAM_TRIGGER_POINT_SOF) - link->last_applied_jiffies = jiffies; - - mutex_unlock(&session->lock); - return rc; -error: + link->last_sof_trigger_jiffies = jiffies; mutex_unlock(&session->lock); return rc; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index b9f57a203197..ffba72cf3c58 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -373,7 +373,8 @@ struct cam_req_mgr_connected_device { * @eof_event_cnt : Atomic variable to track the number of EOF requests * @skip_init_frame : skip initial frames crm_wd_timer validation in the * case of long exposure use case - * @last_applied_jiffies : Record the jiffies of last applied req + * @last_sof_trigger_jiffies : Record the jiffies of last sof trigger jiffies + * @wq_congestion : Indicates if WQ congestion is detected or not */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -410,7 +411,8 @@ struct cam_req_mgr_core_link { uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; atomic_t eof_event_cnt; bool skip_init_frame; - uint64_t last_applied_jiffies; + uint64_t last_sof_trigger_jiffies; + bool wq_congestion; }; /** From d3650f098c312203c85f3be368e35d2f0736a3c3 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Thu, 29 Oct 2020 17:04:43 -0700 Subject: [PATCH 578/790] msm: camera: isp: Fix the callback arguments in IFE Fix the callback arguments in IFE to avoid the CFI check failure. A few callbacks invokes do not typecast for the last argument of the event callback. Since callbacks are indirect function call, CFI check for this will fail. CRs-Fixed: 2807933 Change-Id: I4e72cf07de701bbfd8f7d7829207256918beeb4c Signed-off-by: Jigar Agrawal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 40f1d24701e6..0804b52c404a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7718,7 +7718,7 @@ static int cam_ife_hw_mgr_handle_hw_rup( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; ife_hwr_irq_rup_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&rup_event_data); break; case CAM_ISP_HW_VFE_IN_RDI0: @@ -7730,7 +7730,7 @@ static int cam_ife_hw_mgr_handle_hw_rup( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; ife_hwr_irq_rup_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&rup_event_data); break; case CAM_ISP_HW_VFE_IN_PDLIB: @@ -7768,7 +7768,7 @@ static int cam_ife_hw_mgr_handle_hw_epoch( epoch_done_event_data.frame_id_meta = event_info->reg_val; ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); + CAM_ISP_HW_EVENT_EPOCH, (void *)&epoch_done_event_data); break; @@ -7836,7 +7836,7 @@ static int cam_ife_hw_mgr_handle_hw_sof( break; ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data); break; @@ -7852,7 +7852,7 @@ static int cam_ife_hw_mgr_handle_hw_sof( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data); break; case CAM_ISP_HW_VFE_IN_PDLIB: @@ -7889,7 +7889,7 @@ static int cam_ife_hw_mgr_handle_hw_eof( break; ife_hw_irq_eof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + CAM_ISP_HW_EVENT_EOF, (void *)&eof_done_event_data); break; @@ -7936,7 +7936,7 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( if (buf_done_event_data.num_handles > 0 && ife_hwr_irq_wm_done_cb) { CAM_DBG(CAM_ISP, "Notify ISP context"); ife_hwr_irq_wm_done_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); + CAM_ISP_HW_EVENT_DONE, (void *)&buf_done_event_data); } CAM_DBG(CAM_ISP, From ee8e8ee8844732889fad79aa30ca9eca2c834748 Mon Sep 17 00:00:00 2001 From: zhuo Date: Fri, 30 Oct 2020 15:21:24 +0800 Subject: [PATCH 579/790] msm: camera: reqmgr: Fix timing issue while destroying the session During destroying the session, sof freeze timeout happens after destroying workqueue. Then sof freeze timeout callback will access workqueue causing use after free memory issue. This change invokes destroying timer prior to workqueue. CRs-Fixed: 2807936 Change-Id: I1f0dcb7a03fbf802f4ec872727e3b627a78f56f8 Signed-off-by: zhuo --- drivers/cam_req_mgr/cam_req_mgr_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index fde0b85f2f64..48bea0d2a2cb 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3559,12 +3559,12 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) mutex_lock(&link->lock); - /* Destroy workq of link */ - cam_req_mgr_workq_destroy(&link->workq); spin_lock_bh(&link->link_state_spin_lock); /* Destroy timer of link */ crm_timer_exit(&link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); + /* Destroy workq of link */ + cam_req_mgr_workq_destroy(&link->workq); /* Cleanup request tables and unlink devices */ __cam_req_mgr_destroy_link_info(link); From ed6a1ed193ff8a8a2733bdd5a247b77137e72613 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 27 Oct 2020 17:24:46 +0530 Subject: [PATCH 580/790] msm: camera: isp: Validate the ife bw blob data If ife bandwidth number of paths configuration is zero then do not proceed. Number of bandwidth paths should be minimum one and should not be greater than max value. CRs-Fixed: 2801769 Change-Id: I2bf5cd4ea76ca7ecd9ca968bced2957a76691001 Signed-off-by: Ayush Kumar --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 40f1d24701e6..ca5fadfb7a85 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5962,7 +5962,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, if (!prepare || !prepare->priv || (bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) { - CAM_ERR(CAM_ISP, "Invalid inputs"); + CAM_ERR(CAM_ISP, "Invalid inputs usage type %d", + bw_config->usage_type); return -EINVAL; } @@ -5987,7 +5988,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, bw_config = (struct cam_isp_bw_config_v2 *)blob_data; - if (bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) { + if (bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES || + !bw_config->num_paths) { CAM_ERR(CAM_ISP, "Invalid num paths %d", bw_config->num_paths); return -EINVAL; @@ -6022,7 +6024,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, if (!prepare || !prepare->priv || (bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) { - CAM_ERR(CAM_ISP, "Invalid inputs"); + CAM_ERR(CAM_ISP, "Invalid inputs usage type %d", + bw_config->usage_type); return -EINVAL; } From 0ce4dfa52b075b3702004b2e76812d9df1c739f1 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Sat, 24 Oct 2020 14:03:15 -0700 Subject: [PATCH 581/790] msm: camera: isp: Change dual IFE acquire sequence In case of dual, acquire IFEs from a higher to lower idx. The IFE with the higher hw_idx will be configured as slave. CRs-Fixed: 2805265 Change-Id: I35e3af84e2ac6586056e6d74373642a85e5c797a Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 36 ++++++++++++--------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 40f1d24701e6..d6c3d65876fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1840,9 +1840,9 @@ static int cam_ife_mgr_acquire_cid_res( } } - /* Acquire Left if not already acquired */ - /* For dual IFE cases, start acquiring the lower idx first */ - if (ife_ctx->is_fe_enabled || in_port->usage_type || + /* Acquire right if not already acquired */ + /* For dual IFE cases, master will be lower idx */ + if (ife_ctx->is_fe_enabled || ife_ctx->dsp_enabled) rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr, &csid_acquire, true); @@ -1854,10 +1854,15 @@ static int cam_ife_mgr_acquire_cid_res( CAM_ERR(CAM_ISP, "No %d paths available", path_res_id); goto put_res; } - cid_res_temp->hw_res[acquired_cnt++] = csid_acquire.node_res; + + if (in_port->usage_type) + cid_res_temp->hw_res[++acquired_cnt] = csid_acquire.node_res; + else + cid_res_temp->hw_res[acquired_cnt++] = csid_acquire.node_res; acquire_successful: - CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d", + CAM_DBG(CAM_ISP, "CID %s acquired success is_dual %d", + (in_port->usage_type ? "Right" : " Left"), in_port->usage_type); cid_res_temp->res_type = CAM_ISP_RESOURCE_CID; @@ -1865,16 +1870,13 @@ acquire_successful: cid_res_temp->res_id = csid_acquire.node_res->res_id; cid_res_temp->is_dual_isp = in_port->usage_type; ife_ctx->is_dual = (bool)in_port->usage_type; - if (ife_ctx->is_dual) - ife_ctx->master_hw_idx = - cid_res_temp->hw_res[0]->hw_intf->hw_idx; if (in_port->num_out_res) cid_res_temp->is_secure = out_port->secure_mode; cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, cid_res); /* - * Acquire Right if not already acquired. + * Acquire left if not already acquired. * Dual IFE for RDI and PPP is not currently supported. */ if (cid_res_temp->is_dual_isp && path_res_id @@ -1891,11 +1893,11 @@ acquire_successful: csid_acquire.phy_sel = CAM_ISP_IFE_IN_RES_PHY_1; } - for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) { + for (j = CAM_IFE_CSID_HW_NUM_MAX - 1; j >= 0; j--) { if (!ife_hw_mgr->csid_devices[j]) continue; - if (j == cid_res_temp->hw_res[0]->hw_intf->hw_idx) + if (j == cid_res_temp->hw_res[1]->hw_intf->hw_idx) continue; hw_intf = ife_hw_mgr->csid_devices[j]; @@ -1909,14 +1911,18 @@ acquire_successful: if (j == CAM_IFE_CSID_HW_NUM_MAX) { CAM_ERR(CAM_ISP, - "Can not acquire ife csid rdi resource"); + "Can not acquire ife csid dual resource"); goto end; } - cid_res_temp->hw_res[1] = csid_acquire.node_res; + cid_res_temp->hw_res[0] = csid_acquire.node_res; ife_ctx->slave_hw_idx = cid_res_temp->hw_res[1]->hw_intf->hw_idx; - CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d", - in_port->usage_type); + ife_ctx->master_hw_idx = + cid_res_temp->hw_res[0]->hw_intf->hw_idx; + CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d [master %u: slave %u]", + in_port->usage_type, + ife_ctx->master_hw_idx, + ife_ctx->slave_hw_idx); } return 0; From 5ef9d03a86f8190afe22e60dcf1593ac74af3241 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 22 Oct 2020 16:53:25 -0700 Subject: [PATCH 582/790] msm: camera: isp: Wait for cdm submit incase of custom HW If IFE is connected to custom HW in the pipeline, make the cdm submit a blocking call to ensure settings are programmed to IFE on time. CRs-Fixed: 2805278 Change-Id: Ia0d771a0f875a3b41c67eef496a96461c579dac0 Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 40f1d24701e6..299f9f8da733 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -3960,7 +3960,8 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, return rc; } - if (cfg->init_packet) { + if (cfg->init_packet || + (ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) { rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete, msecs_to_jiffies(60)); From 162bc103f2aad5003adf1c3520a5799abbfa6564 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Fri, 16 Oct 2020 15:03:01 +0530 Subject: [PATCH 583/790] msm: camera: tfe: Enable the tfe diag debug feature Tfe sensor diag feature is not enabled properly. Enable the diag feature based on the debug fs value. Log the tfe measured sensor diag status for camif and rdi paths. Enable the tfe diag status with below command adb shell "echo 0x1 > /sys/kernel/debug/camera_ife/tfe_camif_debug". CRs-Fixed: 2810952 Change-Id: I47cd57e38a38010fb7fba048c35e907e1980b797 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 44 +++++--- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 10 ++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 102 +++++++++++++++--- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h | 7 ++ 4 files changed, 131 insertions(+), 32 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index ebe69a1eac77..1b4a1eb37435 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -2981,11 +2981,12 @@ static int cam_tfe_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_isp_stop_args stop_isp; struct cam_tfe_hw_mgr_ctx *ctx; struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_isp_resource_node *rsrc_node = NULL; - uint32_t i, camif_debug; + struct cam_hw_intf *hw_intf; + uint32_t i; bool res_rdi_context_set = false; uint32_t primary_rdi_in_res; uint32_t primary_rdi_out_res; + bool hw_id[CAM_TFE_HW_NUM_MAX] = {0}; primary_rdi_in_res = CAM_ISP_HW_TFE_IN_MAX; primary_rdi_out_res = CAM_ISP_TFE_OUT_RES_MAX; @@ -3018,31 +3019,40 @@ static int cam_tfe_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) if (ctx->init_done && start_isp->start_only) goto start_only; - /* set current csid debug information to CSID HW */ - for (i = 0; i < CAM_TFE_CSID_HW_NUM_MAX; i++) { - if (g_tfe_hw_mgr.csid_devices[i]) - rc = g_tfe_hw_mgr.csid_devices[i]->hw_ops.process_cmd( - g_tfe_hw_mgr.csid_devices[i]->hw_priv, + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, 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_id[hw_intf->hw_idx]) + continue; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, CAM_TFE_CSID_SET_CSID_DEBUG, &g_tfe_hw_mgr.debug_cfg.csid_debug, sizeof(g_tfe_hw_mgr.debug_cfg.csid_debug)); + hw_id[hw_intf->hw_idx] = true; + } } - camif_debug = g_tfe_hw_mgr.debug_cfg.camif_debug; + memset(&hw_id[0], 0, sizeof(hw_id)); list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) continue; - rsrc_node = hw_mgr_res->hw_res[i]; - if (rsrc_node->process_cmd && (rsrc_node->res_id == - CAM_ISP_HW_TFE_IN_CAMIF)) { - rc = hw_mgr_res->hw_res[i]->process_cmd( - hw_mgr_res->hw_res[i], - CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, - &camif_debug, - sizeof(camif_debug)); - } + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_id[hw_intf->hw_idx]) + continue; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + &g_tfe_hw_mgr.debug_cfg.camif_debug, + sizeof(g_tfe_hw_mgr.debug_cfg.camif_debug)); + hw_id[hw_intf->hw_idx] = true; } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index ae0be9d2c9e9..9e0e6e06fd13 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -40,6 +40,9 @@ static struct cam_tfe_top_reg_offset_common tfe530_top_commong_reg = { .perf_stall_count = 0x000010EC, .perf_always_count = 0x000010F0, .perf_count_status = 0x000010F4, + .diag_min_hbi_error_shift = 15, + .diag_neq_hbi_shift = 14, + .diag_sensor_hbi_mask = 0x3FFF, }; static struct cam_tfe_camif_reg tfe530_camif_reg = { @@ -131,6 +134,8 @@ static struct cam_tfe_rdi_reg_data tfe530_rdi0_reg_data = { 0x00000000, }, .enable_diagnostic_hw = 0x1, + .diag_sensor_sel = 0x1, + .diag_sensor_shift = 0x1, }; static struct cam_tfe_rdi_reg tfe530_rdi1_reg = { @@ -166,6 +171,8 @@ static struct cam_tfe_rdi_reg_data tfe530_rdi1_reg_data = { 0x00000000, }, .enable_diagnostic_hw = 0x1, + .diag_sensor_sel = 0x2, + .diag_sensor_shift = 0x1, }; static struct cam_tfe_rdi_reg tfe530_rdi2_reg = { @@ -201,6 +208,9 @@ static struct cam_tfe_rdi_reg_data tfe530_rdi2_reg_data = { 0x00000000, }, .enable_diagnostic_hw = 0x1, + .diag_sensor_sel = 0x3, + .diag_sensor_shift = 0x1, + }; static struct cam_tfe_clc_hw_status tfe530_clc_hw_info[CAM_TFE_MAX_CLC] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index c06e5d24c6fd..66f3ead97fed 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -52,6 +52,7 @@ struct cam_tfe_top_priv { struct timeval epoch_ts; struct timeval eof_ts; struct timeval error_ts; + uint32_t top_debug; }; struct cam_tfe_camif_data { @@ -497,9 +498,11 @@ static int cam_tfe_rdi_irq_bottom_half( bool epoch_process, struct cam_tfe_irq_evt_payload *evt_payload) { - struct cam_tfe_rdi_data *rdi_priv; - struct cam_isp_hw_event_info evt_info; - struct cam_hw_info *hw_info; + struct cam_tfe_rdi_data *rdi_priv; + struct cam_isp_hw_event_info evt_info; + struct cam_hw_info *hw_info; + struct cam_tfe_top_reg_offset_common *common_reg; + uint32_t val, val2; rdi_priv = (struct cam_tfe_rdi_data *)rdi_node->res_priv; hw_info = rdi_node->hw_intf->hw_priv; @@ -532,6 +535,23 @@ static int cam_tfe_rdi_irq_bottom_half( if (rdi_priv->event_cb) rdi_priv->event_cb(rdi_priv->priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + + if (top_priv->top_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + common_reg = rdi_priv->common_reg; + val = cam_io_r(rdi_priv->mem_base + + common_reg->diag_sensor_status_0); + val2 = cam_io_r(rdi_priv->mem_base + + common_reg->diag_sensor_status_1); + CAM_INFO(CAM_ISP, + "TFE:%d diag sensor hbi min error:%d neq hbi:%d HBI:%d VBI:%d", + rdi_node->hw_intf->hw_idx, + ((val >> common_reg->diag_min_hbi_error_shift) + & 0x1), + ((val >> common_reg->diag_neq_hbi_shift) & 0x1), + (val & common_reg->diag_sensor_hbi_mask), + val2); + } } if (epoch_process && (evt_payload->irq_reg_val[1] & @@ -556,10 +576,11 @@ static int cam_tfe_camif_irq_bottom_half( bool epoch_process, struct cam_tfe_irq_evt_payload *evt_payload) { - struct cam_tfe_camif_data *camif_priv; - struct cam_isp_hw_event_info evt_info; - struct cam_hw_info *hw_info; - uint32_t val; + struct cam_tfe_camif_data *camif_priv; + struct cam_isp_hw_event_info evt_info; + struct cam_hw_info *hw_info; + struct cam_tfe_top_reg_offset_common *common_reg; + uint32_t val, val2; camif_priv = camif_node->res_priv; hw_info = camif_node->hw_intf->hw_priv; @@ -606,6 +627,23 @@ static int cam_tfe_camif_irq_bottom_half( if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); + + if (top_priv->top_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + common_reg = camif_priv->common_reg; + val = cam_io_r(camif_priv->mem_base + + common_reg->diag_sensor_status_0); + val2 = cam_io_r(camif_priv->mem_base + + common_reg->diag_sensor_status_1); + CAM_INFO(CAM_ISP, + "TFE:%d diag sensor hbi min error:%d neq hbi:%d HBI:%d VBI:%d", + camif_node->hw_intf->hw_idx, + ((val >> common_reg->diag_min_hbi_error_shift) + & 0x1), + ((val >> common_reg->diag_neq_hbi_shift) & 0x1), + (val & common_reg->diag_sensor_hbi_mask), + val2); + } } if (epoch_process && (evt_payload->irq_reg_val[1] & @@ -622,13 +660,6 @@ static int cam_tfe_camif_irq_bottom_half( CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info); } - if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { - val = cam_io_r(camif_priv->mem_base + - camif_priv->common_reg->diag_sensor_status_0); - CAM_DBG(CAM_ISP, "TFE_DIAG_SENSOR_STATUS: 0x%x", - camif_priv->mem_base, val); - } - return 0; } @@ -1770,6 +1801,29 @@ static int cam_tfe_camif_irq_reg_dump( return rc; } +int cam_tfe_set_top_debug(struct cam_tfe_hw_core_info *core_info, + void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_top_priv *top_priv; + uint32_t *debug_val; + + if (!cmd_args) { + CAM_ERR(CAM_ISP, "Error! Invalid input arguments"); + return -EINVAL; + } + + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; + debug_val = (uint32_t *)cmd_args; + top_priv->top_debug = *debug_val; + + CAM_DBG(CAM_ISP, "TFE:%d top debug set:%d", + core_info->core_index, + top_priv->top_debug); + + return 0; +} + + int cam_tfe_top_reserve(void *device_priv, void *reserve_args, uint32_t arg_size) { @@ -1910,6 +1964,7 @@ static int cam_tfe_camif_resource_start( { struct cam_tfe_camif_data *rsrc_data; struct cam_tfe_soc_private *soc_private; + struct cam_tfe_top_priv *top_priv; uint32_t val = 0; uint32_t epoch0_irq_mask; uint32_t epoch1_irq_mask; @@ -1929,6 +1984,7 @@ static int cam_tfe_camif_resource_start( rsrc_data = (struct cam_tfe_camif_data *)camif_res->res_priv; soc_private = rsrc_data->soc_info->soc_private; + top_priv = (struct cam_tfe_top_priv *)core_info->top_priv; if (!soc_private) { CAM_ERR(CAM_ISP, "TFE:%d Error soc_private NULL", @@ -2007,7 +2063,7 @@ static int cam_tfe_camif_resource_start( rsrc_data->enable_sof_irq_debug = false; rsrc_data->irq_debug_cnt = 0; - if (rsrc_data->camif_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + if (top_priv->top_debug & CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { val = cam_io_r_mb(rsrc_data->mem_base + rsrc_data->common_reg->diag_config); val |= rsrc_data->reg_data->enable_diagnostic_hw; @@ -2109,6 +2165,17 @@ int cam_tfe_top_start(struct cam_tfe_hw_core_info *core_info, rsrc_rdi_data->reg_data->subscribe_irq_mask, CAM_TFE_TOP_IRQ_REG_NUM, true); + if (top_priv->top_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r_mb(rsrc_rdi_data->mem_base + + rsrc_rdi_data->common_reg->diag_config); + val |= ((rsrc_rdi_data->reg_data->enable_diagnostic_hw)| + (rsrc_rdi_data->reg_data->diag_sensor_sel << + rsrc_rdi_data->reg_data->diag_sensor_shift)); + cam_io_w_mb(val, rsrc_rdi_data->mem_base + + rsrc_rdi_data->common_reg->diag_config); + } + CAM_DBG(CAM_ISP, "TFE:%d Start RDI %d", core_info->core_index, in_res->res_id - CAM_ISP_HW_TFE_IN_RDI0); } @@ -2762,6 +2829,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, struct cam_hw_soc_info *soc_info = NULL; struct cam_tfe_hw_core_info *core_info = NULL; struct cam_tfe_hw_info *hw_info = NULL; + int rc = 0; if (!hw_priv) { @@ -2809,6 +2877,10 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, rc = cam_tfe_hw_dump(core_info, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: + rc = cam_tfe_set_top_debug(core_info, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_GET_BUF_UPDATE: case CAM_ISP_HW_CMD_GET_HFR_UPDATE: case CAM_ISP_HW_CMD_STRIPE_UPDATE: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h index 2418831d00c1..cc193f9e029f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h @@ -97,6 +97,11 @@ struct cam_tfe_top_reg_offset_common { uint32_t perf_stall_count; uint32_t perf_always_count; uint32_t perf_count_status; + + /*reg data */ + uint32_t diag_min_hbi_error_shift; + uint32_t diag_neq_hbi_shift; + uint32_t diag_sensor_hbi_mask; }; struct cam_tfe_camif_reg { @@ -190,6 +195,8 @@ struct cam_tfe_rdi_reg_data { uint32_t error_irq_mask2; uint32_t subscribe_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM]; uint32_t enable_diagnostic_hw; + uint32_t diag_sensor_sel; + uint32_t diag_sensor_shift; }; struct cam_tfe_clc_hw_status { From 55eb3c37f439550ef975d72ecc557c9d8ba165d8 Mon Sep 17 00:00:00 2001 From: Anand Ravi Date: Mon, 2 Nov 2020 13:31:52 -0800 Subject: [PATCH 584/790] msm: camera: ife: Fix bus print dimension Fixes the null pointer dereference in the print dimension function. CRs-Fixed: 2809214 Change-Id: I6467f183cca9f665c89f1a418b320cd55be7700a Signed-off-by: Anand Ravi --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 5fa123654ef8..a20b79676cac 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2505,19 +2505,13 @@ static int cam_vfe_bus_ver3_print_dimensions( struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; struct cam_vfe_bus_ver3_common_data *common_data = NULL; - int i, wm_idx; + int i; uint32_t addr_status0, addr_status1, addr_status2, addr_status3; rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; for (i = 0; i < rsrc_data->num_wm; i++) { - wm_idx = 0; - if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { - CAM_ERR(CAM_ISP, "Unsupported VFE out %d", - vfe_out_res_id); - return -EINVAL; - } - wm_data = bus_priv->bus_client[wm_idx].res_priv; + wm_data = rsrc_data->wm_res[i].res_priv; common_data = rsrc_data->common_data; addr_status0 = cam_io_r_mb(common_data->mem_base + wm_data->hw_regs->addr_status_0); @@ -2530,7 +2524,7 @@ static int cam_vfe_bus_ver3_print_dimensions( CAM_INFO(CAM_ISP, "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", - wm_data->common_data->core_index, wm_idx, + wm_data->common_data->core_index, wm_data->index, wm_data->width, wm_data->height, wm_data->stride, wm_data->h_init, From 68f9e9185d1ad3f233dd7b88a913d39d279bd02e Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 27 Oct 2020 22:37:04 +0530 Subject: [PATCH 585/790] msm: camera: isp: Move the CSID irq logs to bottom half Remove the sof log in CSID irq handler and handle it in the Bottom half.Sof irq enabled during the sof freeze scenario and sof log getting printed in the irq handler causing the interrupt handling taking more time. CRs-Fixed: 2804588 Change-Id: I9514bf79333665dcd9407932789ce00c4ed480d8 Signed-off-by: Chandan Kumar Jha --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 149 +++++++++++------- 1 file changed, 94 insertions(+), 55 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index febc58054032..0ece0bf29e40 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1910,9 +1910,6 @@ static void cam_ife_csid_halt_csi2( csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); - cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, - CAM_SUBDEV_MESSAGE_IRQ_ERR, - csid_hw->csi2_rx_cfg.phy_sel); } static int cam_ife_csid_init_config_pxl_path( @@ -4199,7 +4196,8 @@ static int cam_ife_csid_sof_irq_debug( if (csid_hw->hw_info->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_WARN(CAM_ISP, - "CSID powered down unable to %s sof irq", + "CSID:%d powered down unable to %s sof irq", + csid_hw->hw_intf->hw_idx, (sof_irq_enable == true) ? "enable" : "disable"); return 0; } @@ -4258,9 +4256,10 @@ static int cam_ife_csid_sof_irq_debug( csid_hw->sof_irq_triggered = false; } - CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s, CSID HW:%d", - (sof_irq_enable) ? "enabled" : "disabled", - csid_hw->hw_intf->hw_idx); + if (!in_irq()) + CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s, CSID HW:%d", + (sof_irq_enable) ? "enabled" : "disabled", + csid_hw->hw_intf->hw_idx); return 0; } @@ -4601,35 +4600,6 @@ static int cam_csid_put_evt_payload( return 0; } -static char *cam_csid_status_to_str(uint32_t status) -{ - switch (status) { - case CAM_IFE_CSID_IRQ_REG_TOP: - return "TOP"; - case CAM_IFE_CSID_IRQ_REG_RX: - return "RX"; - case CAM_IFE_CSID_IRQ_REG_IPP: - return "IPP"; - case CAM_IFE_CSID_IRQ_REG_PPP: - return "PPP"; - case CAM_IFE_CSID_IRQ_REG_RDI_0: - return "RDI0"; - case CAM_IFE_CSID_IRQ_REG_RDI_1: - return "RDI1"; - case CAM_IFE_CSID_IRQ_REG_RDI_2: - return "RDI2"; - case CAM_IFE_CSID_IRQ_REG_RDI_3: - return "RDI3"; - case CAM_IFE_CSID_IRQ_REG_UDI_0: - return "UDI0"; - case CAM_IFE_CSID_IRQ_REG_UDI_1: - return "UDI1"; - case CAM_IFE_CSID_IRQ_REG_UDI_2: - return "UDI2"; - default: - return "Invalid IRQ"; - } -} static int cam_csid_evt_bottom_half_handler( void *handler_priv, @@ -4640,6 +4610,8 @@ static int cam_csid_evt_bottom_half_handler( int i; int rc = 0; struct cam_isp_hw_event_info event_info; + const struct cam_ife_csid_reg_offset *csid_reg; + int udi_start_idx = CAM_IFE_CSID_IRQ_REG_UDI_0; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, @@ -4650,6 +4622,7 @@ static int cam_csid_evt_bottom_half_handler( csid_hw = (struct cam_ife_csid_hw *)handler_priv; evt_payload = (struct cam_csid_evt_payload *)evt_payload_priv; + csid_reg = csid_hw->csid_info->csid_reg; if (!csid_hw->event_cb || !csid_hw->priv) { CAM_ERR_RATE_LIMIT(CAM_ISP, @@ -4669,16 +4642,60 @@ static int cam_csid_evt_bottom_half_handler( goto end; } - CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d cnt %d", - csid_hw->hw_intf->hw_idx, - evt_payload->evt_type, - csid_hw->csi2_rx_cfg.phy_sel, - csid_hw->csi2_cfg_cnt); + if (csid_hw->sof_irq_triggered && (evt_payload->evt_type == + CAM_ISP_HW_ERROR_NONE)) { + if (evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_INFO_INPUT_SOF) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + } - for (i = 0; i < CAM_IFE_CSID_IRQ_REG_MAX; i++) - CAM_ERR_RATE_LIMIT(CAM_ISP, "status %s: %x", - cam_csid_status_to_str(i), - evt_payload->irq_status[i]); + if (evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_INFO_INPUT_SOF) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PPP SOF received", + csid_hw->hw_intf->hw_idx); + } + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + if (evt_payload->irq_status[i] & + CSID_PATH_INFO_INPUT_SOF) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d RDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); + } + + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { + if (evt_payload->irq_status[udi_start_idx + i] & + CSID_PATH_INFO_INPUT_SOF) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d UDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); + } + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID %d err %d phy %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x PPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x RDI3: 0x%x UDI0: 0x%x UDI1: 0x%x UDI2: 0x%x", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type, + csid_hw->csi2_rx_cfg.phy_sel, + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_TOP], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RX], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_IPP], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_PPP], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_0], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_1], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_2], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_3], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_1], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_2]); + } + + if (evt_payload->evt_type == CAM_ISP_HW_ERROR_CSID_FATAL) + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + csid_hw->csi2_rx_cfg.phy_sel); /* this hunk can be extended to handle more cases * which we want to offload to bottom half from @@ -4697,7 +4714,7 @@ static int cam_csid_evt_bottom_half_handler( break; default: - CAM_DBG(CAM_ISP, "CSID[%d] invalid error type %d", + CAM_DBG(CAM_ISP, "CSID[%d] error type %d", csid_hw->hw_intf->hw_idx, evt_payload->evt_type); break; @@ -4763,7 +4780,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX] = {0}; uint32_t i, val, val2; bool fatal_err_detected = false; - uint32_t sof_irq_debug_en = 0; + uint32_t sof_irq_debug_en = 0, log_en = 0; unsigned long flags; csid_hw = (struct cam_ife_csid_hw *)data; @@ -5129,8 +5146,13 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP SOF received", - csid_hw->hw_intf->hw_idx); + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5201,8 +5223,13 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP SOF received", - csid_hw->hw_intf->hw_idx); + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5270,9 +5297,13 @@ handle_fatal_error: if ((irq_status[i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d RDI:%d SOF received", - csid_hw->hw_intf->hw_idx, i); + csid_hw->hw_intf->hw_idx, i); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5340,9 +5371,13 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d UDI:%d SOF received", - csid_hw->hw_intf->hw_idx, i); + csid_hw->hw_intf->hw_idx, i); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5378,6 +5413,10 @@ handle_fatal_error: } } + if (log_en) + cam_csid_handle_hw_err_irq(csid_hw, + CAM_ISP_HW_ERROR_NONE, irq_status); + if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_ife_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); csid_hw->irq_debug_cnt = 0; From ab996a3ace390c47c85b393173f95707d3755099 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Tue, 3 Nov 2020 15:34:57 +0530 Subject: [PATCH 586/790] msm: camera: isp: Handle QCFA bin eanbled case for MP limit fuse When QCFA binning is enabled adjust MP limit fuse checking to check actual proessing width for IFE. CRs-Fixed: 2808086 Change-Id: I22af38ba36ad84372699a177c203c1acbae76cb9 Signed-off-by: Wyes Karny --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index febc58054032..6183e438ba0b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1143,6 +1143,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, struct cam_ife_csid_path_cfg *path_data; struct cam_isp_resource_node *res; bool is_rdi = false; + uint32_t width = 0; /* CSID CSI2 v2.0 supports 31 vc */ if (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX) { @@ -1313,10 +1314,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, } if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { + width = reserve->in_port->left_stop - + reserve->in_port->left_start + 1; + if (path_data->horizontal_bin || path_data->qcfa_bin) + width /= 2; if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) && !(cam_ife_csid_is_resolution_supported(csid_hw, - reserve->in_port->left_stop - - reserve->in_port->left_start + 1))) { + width))) { rc = -EINVAL; goto end; } @@ -1339,10 +1343,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, reserve->res_id, path_data->start_line, path_data->end_line); } else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { + width = reserve->in_port->right_stop - + reserve->in_port->right_start + 1; + if (path_data->horizontal_bin || path_data->qcfa_bin) + width /= 2; if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) && !(cam_ife_csid_is_resolution_supported(csid_hw, - reserve->in_port->right_stop - - reserve->in_port->right_start + 1))) { + width))) { rc = -EINVAL; goto end; } @@ -1362,10 +1369,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, reserve->res_id, path_data->start_line, path_data->end_line); } else { + width = reserve->in_port->left_stop - + reserve->in_port->left_start + 1; + if (path_data->horizontal_bin || path_data->qcfa_bin) + width /= 2; if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) && !(cam_ife_csid_is_resolution_supported(csid_hw, - reserve->in_port->left_stop - - reserve->in_port->left_start + 1))) { + width))) { rc = -EINVAL; goto end; } From 9ada4e4a26b7ce802bad1c0621c4fccbf86a6d27 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 21 Oct 2020 18:23:00 -0700 Subject: [PATCH 587/790] msm: camera: custom: Add support for bubble handling Add support for bubble handling in custom driver allowing the custom block to re-apply bubbled request in sync with IFE. CRs-Fixed: 2805278 Change-Id: I411d033f2470de3fab7587c7c019a933bda28020 Signed-off-by: Karthik Anantha Ram --- drivers/cam_cust/cam_custom_context.c | 182 ++++++++++++++++++++++---- drivers/cam_cust/cam_custom_context.h | 8 +- 2 files changed, 164 insertions(+), 26 deletions(-) diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index b0aebffafa7a..de40a58176f7 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -181,11 +181,28 @@ static int __cam_custom_ctx_frame_done( continue; } - rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, + if (!req_custom->bubble_detected) { + rc = cam_sync_signal( + req_custom->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, CAM_SYNC_COMMON_EVENT_SUCCESS); - if (rc) - CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Sync failed with rc = %d", rc); + } else if (!req_custom->bubble_report) { + rc = cam_sync_signal( + req_custom->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Sync failed with rc = %d", rc); + } else { + req_custom->num_acked++; + CAM_DBG(CAM_CUSTOM, "frame done with bubble for %llu", + req->request_id); + continue; + } req_custom->num_acked++; req_custom->fence_map_out[j].sync_id = -1; @@ -203,15 +220,131 @@ static int __cam_custom_ctx_frame_done( custom_ctx->active_req_cnt--; frame_done_req_id = req->request_id; - 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], ctx %u", - frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); + if (req_custom->bubble_detected && req_custom->bubble_report) { + req_custom->num_acked = 0; + req_custom->bubble_detected = false; + list_del_init(&req->list); + if (frame_done_req_id <= ctx->last_flush_req) { + for (i = 0; i < req_custom->num_fence_map_out; i++) + rc = cam_sync_signal( + req_custom->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); + + list_add_tail(&req->list, &ctx->free_req_list); + atomic_set(&custom_ctx->process_bubble, 0); + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", + frame_done_req_id, custom_ctx->active_req_cnt, + ctx->ctx_id); + } else { + list_add(&req->list, &ctx->pending_req_list); + atomic_set(&custom_ctx->process_bubble, 0); + CAM_DBG(CAM_REQ, + "Move active request %lld to pending list in ctx %u", + frame_done_req_id, 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], ctx %u", + frame_done_req_id, + custom_ctx->active_req_cnt, + ctx->ctx_id); + } return rc; } +static int __cam_custom_ctx_handle_bubble( + struct cam_context *ctx, uint64_t req_id) +{ + int rc = -EINVAL; + bool found = false; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp; + struct cam_custom_dev_ctx_req *req_custom; + + list_for_each_entry_safe(req, req_temp, + &ctx->wait_req_list, list) { + if (req->request_id == req_id) { + req_custom = + (struct cam_custom_dev_ctx_req *)req->req_priv; + if (!req_custom->bubble_report) { + CAM_DBG(CAM_CUSTOM, + "Skip bubble recovery for %llu", + req_id); + goto end; + } + + req_custom->bubble_detected = true; + found = true; + CAM_DBG(CAM_CUSTOM, + "Found bubbled req %llu in wait list", + req_id); + } + } + + if (found) { + rc = 0; + goto end; + } + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + if (req->request_id == req_id) { + req_custom = + (struct cam_custom_dev_ctx_req *)req->req_priv; + if (!req_custom->bubble_report) { + CAM_DBG(CAM_CUSTOM, + "Skip bubble recovery for %llu", + req_id); + goto end; + } + + req_custom->bubble_detected = true; + found = true; + CAM_DBG(CAM_CUSTOM, + "Found bubbled req %llu in active list", + req_id); + } + } + + if (found) + rc = 0; + else + CAM_ERR(CAM_CUSTOM, + "req %llu not found in wait or active list bubble recovery failed ctx: %u", + req_id, ctx->ctx_id); + +end: + return rc; +} + +static int __cam_custom_ctx_handle_evt( + struct cam_context *ctx, + struct cam_req_mgr_link_evt_data *evt_data) +{ + int rc = -1; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + if (evt_data->u.error == CRM_KMD_ERR_BUBBLE) { + rc = __cam_custom_ctx_handle_bubble(ctx, evt_data->req_id); + if (rc) + return rc; + } else { + CAM_WARN(CAM_CUSTOM, "Unsupported error type %d", + evt_data->u.error); + } + + CAM_DBG(CAM_CUSTOM, "Set bubble flag for req %llu in ctx %u", + evt_data->req_id, ctx->ctx_id); + atomic_set(&custom_ctx->process_bubble, 1); + return 0; +} + static struct cam_ctx_ops cam_custom_ctx_activated_state_machine [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { @@ -487,6 +620,7 @@ static int __cam_custom_ctx_flush_req_in_top_state( } end: + atomic_set(&custom_ctx->process_bubble, 0); return rc; } @@ -495,6 +629,8 @@ static int __cam_custom_ctx_flush_req_in_ready( struct cam_req_mgr_flush_request *flush_req) { int rc = 0; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; CAM_DBG(CAM_CUSTOM, "try to flush pending list"); spin_lock_bh(&ctx->lock); @@ -505,6 +641,7 @@ static int __cam_custom_ctx_flush_req_in_ready( ctx->state = CAM_CTX_ACQUIRED; spin_unlock_bh(&ctx->lock); + atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_CUSTOM, "Flush request in ready state. next state %d", ctx->state); return rc; @@ -751,6 +888,14 @@ static int __cam_custom_ctx_apply_req_in_activated_state( struct cam_custom_context *custom_ctx = NULL; struct cam_hw_config_args cfg; + if (atomic_read(&custom_ctx->process_bubble)) { + CAM_WARN(CAM_CUSTOM, + "ctx_id:%d Processing bubble cannot apply Request Id %llu", + ctx->ctx_id, apply->request_id); + rc = -EAGAIN; + goto end; + } + if (list_empty(&ctx->pending_req_list)) { CAM_ERR(CAM_CUSTOM, "No available request for Apply id %lld", apply->request_id); @@ -779,7 +924,7 @@ static int __cam_custom_ctx_apply_req_in_activated_state( } req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; - + req_custom->bubble_report = apply->report_if_bubble; cfg.ctxt_to_hw_map = custom_ctx->hw_ctx; cfg.request_id = req->request_id; cfg.hw_update_entries = req_custom->cfg; @@ -1287,6 +1432,7 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, ctx_custom->frame_id = 0; ctx_custom->active_req_cnt = 0; + atomic_set(&ctx_custom->process_bubble, 0); ctx_custom->substate_activated = (req_custom->num_fence_map_out) ? CAM_CUSTOM_CTX_ACTIVATED_APPLIED : @@ -1349,21 +1495,6 @@ static int __cam_custom_ctx_unlink_in_activated(struct cam_context *ctx, return rc; } -static int __cam_custom_ctx_process_evt(struct cam_context *ctx, - struct cam_req_mgr_link_evt_data *link_evt_data) -{ - switch (link_evt_data->evt_type) { - case CAM_REQ_MGR_LINK_EVT_ERR: - /* Handle error/bubble related issues */ - break; - default: - CAM_WARN(CAM_CUSTOM, "Unknown event from CRM"); - break; - } - - return 0; -} - static int __cam_custom_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { @@ -1537,6 +1668,7 @@ static struct cam_ctx_ops }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, + .process_evt = __cam_custom_ctx_handle_evt, }, .irq_ops = NULL, }, @@ -1556,7 +1688,7 @@ static struct cam_ctx_ops .notify_frame_skip = __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, - .process_evt = __cam_custom_ctx_process_evt, + .process_evt = __cam_custom_ctx_handle_evt, }, .irq_ops = __cam_custom_ctx_handle_irq_in_activated, .pagefault_ops = NULL, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index d2bf069b47f2..b352d3a374cb 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only * - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CUSTOM_CONTEXT_H_ @@ -65,6 +65,8 @@ struct cam_custom_ctx_irq_ops { * @num_acked: Count to track acked entried for output. * If count equals the number of fence out, it means * the request has been completed. + * @bubble_report: If bubble recovery is needed + * @bubble_detected: request has bubbled * @hw_update_data: HW update data for this request * */ @@ -80,6 +82,8 @@ struct cam_custom_dev_ctx_req { [CAM_CUSTOM_DEV_CTX_RES_MAX]; uint32_t num_fence_map_in; uint32_t num_acked; + int32_t bubble_report; + bool bubble_detected; struct cam_custom_prepare_hw_update_data hw_update_data; }; @@ -95,6 +99,7 @@ struct cam_custom_dev_ctx_req { * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context * @hw_acquired: Flag to indicate if HW is acquired for this context + * @process_bubble: If ctx currently processing bubble * @substate_actiavted: Current substate for the activated state. * @substate_machine: Custom substate machine for external interface * @substate_machine_irq: Custom substate machine for irq handling @@ -113,6 +118,7 @@ struct cam_custom_context { int64_t frame_id; bool hw_acquired; uint32_t substate_activated; + atomic_t process_bubble; struct cam_ctx_ops *substate_machine; struct cam_custom_ctx_irq_ops *substate_machine_irq; struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; From ffe8a4ab108bbb71c6974413b831e101b99c11c3 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 6 Nov 2020 11:53:57 +0530 Subject: [PATCH 588/790] Revert "msm: camera: crm: Add protection while destroying the link" This reverts commit dd78fbce96f13404005ea415f7454a4a8f3055f5. Change-Id: Ie4b8b68c8f29f607a58267693dd101a946e7bdf8 Signed-off-by: Salendarsingh Gaud --- drivers/cam_req_mgr/cam_req_mgr_core.c | 62 +++++++++----------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 0eb61dbb29f2..1be94c5d35be 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1116,8 +1116,8 @@ static int __cam_req_mgr_check_sync_for_mslave( int64_t req_id = 0, sync_req_id = 0; int32_t sync_num_slots = 0; - if (!sync_link || !link) { - CAM_ERR(CAM_CRM, "Sync link or link is null"); + if (!sync_link) { + CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } @@ -1323,21 +1323,20 @@ static int __cam_req_mgr_check_sync_req_is_ready( uint64_t master_slave_diff = 0; bool ready = true, sync_ready = true; - if (!sync_link ||!link) { + if (!sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } req_id = slot->req_id; - sync_num_slots = sync_link->req.in_q->num_slots; - sync_rd_idx = sync_link->req.in_q->rd_idx; - sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; - sync_req_id = sync_rd_slot->req_id; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; CAM_DBG(CAM_REQ, - "link_hdl %x sync link_hdl %x req %lld", - link->link_hdl, sync_link->link_hdl, req_id); + "link_hdl %x req %lld frame_skip_flag %d ", + link->link_hdl, req_id, link->sync_link_sof_skip); if (sync_link->initial_skip) { link->initial_skip = false; @@ -1441,18 +1440,13 @@ static int __cam_req_mgr_check_sync_req_is_ready( ready = false; } - if (sync_link->req.in_q) { - 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); - sync_ready = false; - } - } else { - CAM_ERR(CAM_CRM, "Sync link->req null"); - 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 [other link] link: %x, rc=%d", + req_id, sync_link->link_hdl, rc); + sync_ready = false; } /* @@ -1518,6 +1512,7 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EAGAIN; } } + CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); @@ -1531,20 +1526,8 @@ static int __cam_req_mgr_check_multi_sync_link_ready( { int i, rc = 0; - if (link->state == CAM_CRM_LINK_STATE_IDLE) { - CAM_ERR(CAM_CRM, "link state is idle %x", - link->state); - return -EINVAL; - } - for (i = 0; i < link->num_sync_links; i++) { if (link->sync_link[i]) { - if (link->sync_link[i]->state == - CAM_CRM_LINK_STATE_IDLE) { - CAM_ERR(CAM_CRM, "sync link state is idle %x", - link->sync_link[i]->state); - return -EINVAL; - } if (link->max_delay == link->sync_link[i]->max_delay) { rc = __cam_req_mgr_check_sync_req_is_ready( link, link->sync_link[i], slot); @@ -1575,9 +1558,6 @@ static int __cam_req_mgr_check_multi_sync_link_ready( return rc; } } - } else { - CAM_ERR(CAM_REQ, "Sync link is null"); - return -EINVAL; } } @@ -2859,8 +2839,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) spin_lock_bh(&link->link_state_spin_lock); if (link->state < CAM_CRM_LINK_STATE_READY) { - CAM_WARN(CAM_CRM, "invalid link state:%d for link 0x%x", - link->state, link->link_hdl); + CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); spin_unlock_bh(&link->link_state_spin_lock); rc = -EPERM; goto release_lock; @@ -3643,18 +3622,17 @@ int cam_req_mgr_destroy_session( goto end; } - mutex_lock(&cam_session->lock); if (cam_session->num_links) { - CAM_INFO(CAM_CRM, "destroy session %x num_active_links %d", + CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d", ses_info->session_hdl, cam_session->num_links); for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { link = cam_session->links[i]; + if (!link) continue; - CAM_INFO(CAM_CRM, "Unlink link hdl 0x%x", link->link_hdl); /* Ignore return value since session is going away */ link->is_shutdown = is_shutdown; __cam_req_mgr_unlink(link); @@ -3662,7 +3640,7 @@ int cam_req_mgr_destroy_session( } } list_del(&cam_session->entry); - mutex_unlock(&cam_session->lock); + mutex_destroy(&cam_session->lock); kfree(cam_session); rc = cam_destroy_session_hdl(ses_info->session_hdl); From 50e3fc5c42c8459cbb0f2ba1826a71add33cf3c1 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 29 Oct 2020 00:14:00 +0530 Subject: [PATCH 589/790] msm: camera: isp: Fixing KW errors Fixes KW errors for ISP. CRs-Fixed: 2813979 Change-Id: I5b09b1c5a678352c2f2d467c6e8bbf587c1f8e35 Signed-off-by: Chandan Kumar Jha --- .../cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c | 7 ++++++- .../isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c | 5 +++-- .../isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c | 1 + .../cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c | 4 ++-- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 3e39ce2fa5ad..fe6b43330b30 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -476,7 +476,7 @@ int cam_isp_add_io_buffers( 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 *out_map_entries = NULL; struct cam_hw_fence_map_entry *in_map_entries; struct cam_isp_hw_get_cmd_update secure_mode; uint32_t kmd_buf_remain_size; @@ -738,6 +738,11 @@ int cam_isp_add_io_buffers( } io_cfg_used_bytes += update_buf.cmd.used_bytes; + if (!out_map_entries) { + CAM_ERR(CAM_ISP, "out_map_entries is NULL"); + rc = -EINVAL; + return rc; + } image_buf_addr = out_map_entries->image_buf_addr; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c index 7bed7948c5cf..4493d990edab 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c @@ -774,7 +774,7 @@ static int cam_sfe_bus_release_bus_rd(void *bus_priv, void *release_args, static int cam_sfe_bus_start_bus_rd( void *hw_priv, void *stop_hw_args, uint32_t arg_size) { - int rc, i; + int rc = -ENODEV, i; struct cam_isp_resource_node *sfe_bus_rd = NULL; struct cam_sfe_bus_rd_data *rsrc_data = NULL; struct cam_sfe_bus_rd_common_data *common_data = NULL; @@ -811,8 +811,9 @@ static int cam_sfe_bus_start_bus_rd( rc = cam_sfe_bus_start_rm(rsrc_data->rm_res[i]); /* TO DO Subscribe mask for buf_done */ + if (!rc) + sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; - sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; return rc; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c index 5666b8df1479..b1c4ddb1b98b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c @@ -937,6 +937,7 @@ static int cam_sfe_bus_acquire_sfe_out(void *priv, void *acquire_args, return -EINVAL; } + comp_grp_id = CAM_SFE_BUS_WR_COMP_GRP_MAX; out_acquire_args = &acq_args->sfe_out; format = out_acquire_args->out_port_info->format; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c index aabe64a87fd6..11b054918c6c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c @@ -866,7 +866,7 @@ static int cam_sfe_top_handle_irq_bottom_half( { int i; uint32_t irq_status[CAM_SFE_IRQ_REGISTERS_MAX] = {0}; - enum cam_sfe_hw_irq_status ret; + enum cam_sfe_hw_irq_status ret = CAM_SFE_IRQ_STATUS_MAX; struct cam_isp_hw_event_info evt_info; struct cam_isp_resource_node *res = handler_priv; struct cam_sfe_path_data *path_data = res->res_priv; @@ -1126,7 +1126,7 @@ int cam_sfe_top_init( memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES); memset(&top_priv->core_cfg, 0x0, - sizeof(struct cam_sfe_core_config_args)); + sizeof(struct cam_sfe_core_cfg)); CAM_DBG(CAM_SFE, "Initializing SFE [%u] top with hw_version: 0x%x", diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index caa1c83512ca..f50fb5da4e21 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1748,7 +1748,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) add_req.skip_before_applying |= SKIP_NEXT_FRAME; add_req.trigger_eof = true; - if ((flash_data->opcode != + if (flash_data && (flash_data->opcode != CAMERA_SENSOR_FLASH_OP_FIREDURATION)) add_req.skip_before_applying |= 1; else From de3c732e6c23c0c1eb2d31841865dcd804c0f6a5 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 14 Oct 2020 20:28:05 -0700 Subject: [PATCH 590/790] msm: camera: reqmgr: Remove idx check when detecting congestion Remove last applied idx check when detecting workq delays. CRs-Fixed: 2801863 Change-Id: I85fe5aa9af446b25a3dd139a75cf1ed6b2a1253c Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 33ea1bb6785e..fdbd9565ab49 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1758,8 +1758,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->max_delay == 1) max_retry++; - if ((in_q->last_applied_idx < in_q->rd_idx) && - !link->wq_congestion) { + if (!link->wq_congestion) { link->retry_cnt++; if (link->retry_cnt == max_retry) { CAM_DBG(CAM_CRM, From 38b660d92f2a0129eeb4e0475a13d48d2818aeed Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Fri, 30 Oct 2020 02:39:03 -0700 Subject: [PATCH 591/790] msm: camera: cpas: Enhance cpas dump with more info 1. Add more triggers to save cpas state info. IFE EOF, ReqBufDone 2. Save camnoc fill levels in each cpas log state 3. Print camnoc QoS settings in cpas state dump for debug purpose. Though these are static settings, printing will help in making sure correct settings are applied. CRs-Fixed: 2814346 Change-Id: Ic3018c5f7fdeaac3a123c6d046eb5e6a34a675e7 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_cpas/cam_cpas_hw.c | 74 +++++++++++++++++-- drivers/cam_cpas/cam_cpas_hw.h | 8 +- drivers/cam_cpas/camss_top/cam_camsstop_hw.c | 1 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 36 +++++++++ drivers/cam_isp/cam_isp_context.c | 3 + .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 2 + 6 files changed, 118 insertions(+), 6 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index c5f3653de497..56bea71d400b 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -77,6 +77,30 @@ static void cam_cpas_process_bw_overrides( bus_client->common_data.name, *ab, *ib, curr_ab, curr_ib); } +int cam_cpas_util_reg_read(struct cam_hw_info *cpas_hw, + enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + uint32_t value; + int reg_base_index; + + if (!reg_info->enable) + return 0; + + reg_base_index = cpas_core->regbase_index[reg_base]; + if (reg_base_index == -1) + return -EINVAL; + + value = cam_io_r_mb( + soc_info->reg_map[reg_base_index].mem_base + reg_info->offset); + + CAM_INFO(CAM_CPAS, "Base[%d] Offset[0x%08x] Value[0x%08x]", + reg_base, reg_info->offset, value); + + return 0; +} + int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info) { @@ -1089,10 +1113,6 @@ static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw, cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx], "Translated Vote", axi_vote); - /* Log an entry whenever there is an AXI update - before updating */ - cam_cpas_update_monitor_array(cpas_hw, "CPAS AXI pre-update", - client_indx); - rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, cpas_core->cpas_client[client_indx], axi_vote); @@ -1917,6 +1937,11 @@ static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) cam_cpas_dump_monitor_array(cpas_core); + if (cpas_core->internal_ops.print_poweron_settings) + cpas_core->internal_ops.print_poweron_settings(cpas_hw); + else + CAM_DBG(CAM_CPAS, "No ops for print_poweron_settings"); + return 0; } @@ -1930,6 +1955,7 @@ static void cam_cpas_update_monitor_array(struct cam_hw_info *cpas_hw, struct cam_cpas_monitor *entry; int iterator; int i; + int reg_camnoc = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; CAM_CPAS_INC_MONITOR_HEAD(&cpas_core->monitor_head, &iterator); @@ -1985,6 +2011,20 @@ static void cam_cpas_update_monitor_array(struct cam_hw_info *cpas_hw, entry->be_ddr = cam_io_r_mb(rpmh_base + be_ddr_offset); entry->be_mnoc = cam_io_r_mb(rpmh_base + be_mnoc_offset); } + + entry->camnoc_fill_level[0] = cam_io_r_mb( + soc_info->reg_map[reg_camnoc].mem_base + 0xA20); + entry->camnoc_fill_level[1] = cam_io_r_mb( + soc_info->reg_map[reg_camnoc].mem_base + 0x1420); + entry->camnoc_fill_level[2] = cam_io_r_mb( + soc_info->reg_map[reg_camnoc].mem_base + 0x1A20); + + if (cpas_hw->soc_info.hw_version == CAM_CPAS_TITAN_580_V100) { + entry->camnoc_fill_level[3] = cam_io_r_mb( + soc_info->reg_map[reg_camnoc].mem_base + 0x7620); + entry->camnoc_fill_level[4] = cam_io_r_mb( + soc_info->reg_map[reg_camnoc].mem_base + 0x7420); + } } static void cam_cpas_dump_monitor_array( @@ -1995,6 +2035,7 @@ static void cam_cpas_dump_monitor_array( uint32_t index, num_entries, oldest_entry; uint64_t ms, tmp, hrs, min, sec; struct cam_cpas_monitor *entry; + struct timespec64 curr_timestamp; if (!cpas_core->full_state_dump) return; @@ -2013,7 +2054,17 @@ static void cam_cpas_dump_monitor_array( CAM_CPAS_MONITOR_MAX_ENTRIES, &oldest_entry); } - CAM_INFO(CAM_CPAS, "======== Dumping monitor information ==========="); + + ktime_get_real_ts64(&curr_timestamp); + tmp = curr_timestamp.tv_sec; + ms = (curr_timestamp.tv_nsec) / 1000000; + sec = do_div(tmp, 60); + min = do_div(tmp, 60); + hrs = do_div(tmp, 24); + + CAM_INFO(CAM_CPAS, + "**** %llu:%llu:%llu.%llu : ======== Dumping monitor information ===========", + hrs, min, sec, ms); index = oldest_entry; @@ -2048,6 +2099,19 @@ static void cam_cpas_dump_monitor_array( entry->be_ddr, entry->be_mnoc); } + CAM_INFO(CAM_CPAS, + "CAMNOC REG[Queued Pending] linear[%d %d] rdi0_wr[%d %d] ubwc_stats0[%d %d] ubwc_stats1[%d %d] rdi1_wr[%d %d]", + (entry->camnoc_fill_level[0] & 0x7FF), + (entry->camnoc_fill_level[0] & 0x7F0000) >> 16, + (entry->camnoc_fill_level[1] & 0x7FF), + (entry->camnoc_fill_level[1] & 0x7F0000) >> 16, + (entry->camnoc_fill_level[2] & 0x7FF), + (entry->camnoc_fill_level[2] & 0x7F0000) >> 16, + (entry->camnoc_fill_level[3] & 0x7FF), + (entry->camnoc_fill_level[3] & 0x7F0000) >> 16, + (entry->camnoc_fill_level[4] & 0x7FF), + (entry->camnoc_fill_level[4] & 0x7F0000) >> 16); + index = (index + 1) % CAM_CPAS_MONITOR_MAX_ENTRIES; } } diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index 3301cdbff82d..1c25d0f56203 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -45,7 +45,7 @@ #define CAM_RPMH_BCM_MNOC_INDEX 4 #define CAM_RPMH_BCM_INFO_MAX 5 -#define CAM_CPAS_MONITOR_MAX_ENTRIES 20 +#define CAM_CPAS_MONITOR_MAX_ENTRIES 60 #define CAM_CPAS_INC_MONITOR_HEAD(head, ret) \ div_u64_rem(atomic64_add_return(1, head),\ CAM_CPAS_MONITOR_MAX_ENTRIES, (ret)) @@ -69,6 +69,7 @@ enum cam_cpas_access_type { * @power_on: Function pointer for hw core specific power on settings * @power_off: Function pointer for hw core specific power off settings * @setup_qos_settings: Function pointer for hw to select a specific qos header + * @print_poweron_settings: Function pointer for hw to print poweron settings * */ struct cam_cpas_internal_ops { @@ -83,6 +84,7 @@ struct cam_cpas_internal_ops { int (*power_off)(struct cam_hw_info *cpas_hw); int (*setup_qos_settings)(struct cam_hw_info *cpas_hw, uint32_t selection_mask); + int (*print_poweron_settings)(struct cam_hw_info *cpas_hw); }; /** @@ -212,6 +214,7 @@ struct cam_cpas_axi_port_debug_info { * This indicates requested clock plan * @be_mnoc: RPMH MNOC BCM BE (back-end) status register value. * This indicates actual current clock plan + * @camnoc_fill_level: Camnoc fill level register info */ struct cam_cpas_monitor { struct timespec64 timestamp; @@ -224,6 +227,7 @@ struct cam_cpas_monitor { uint32_t be_ddr; uint32_t fe_mnoc; uint32_t be_mnoc; + uint32_t camnoc_fill_level[5]; }; /** @@ -284,6 +288,8 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info); +int cam_cpas_util_reg_read(struct cam_hw_info *cpas_hw, + enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info); int cam_cpas_util_client_cleanup(struct cam_hw_info *cpas_hw); diff --git a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c index 32415b0baf5d..23f8542cdd87 100644 --- a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c +++ b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c @@ -78,6 +78,7 @@ int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->power_on = NULL; internal_ops->power_off = NULL; internal_ops->setup_qos_settings = NULL; + internal_ops->print_poweron_settings = NULL; return 0; } diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 0bef0a434343..c5bbcbb79013 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -683,6 +683,40 @@ done: return IRQ_HANDLED; } +static int cam_cpastop_print_poweron_settings(struct cam_hw_info *cpas_hw) +{ + int i; + + for (i = 0; i < camnoc_info->specific_size; i++) { + if (camnoc_info->specific[i].enable) { + CAM_INFO(CAM_CPAS, "Reading QoS settings for %d", + camnoc_info->specific[i].port_type); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].priority_lut_low); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].priority_lut_high); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].urgency); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].danger_lut); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].safe_lut); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].ubwc_ctl); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].flag_out_set0_low); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].qosgen_mainctl); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].qosgen_shaping_low); + cam_cpas_util_reg_read(cpas_hw, CAM_CPAS_REG_CAMNOC, + &camnoc_info->specific[i].qosgen_shaping_high); + } + } + + return 0; +} + static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) { int i; @@ -899,6 +933,8 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->power_on = cam_cpastop_poweron; internal_ops->power_off = cam_cpastop_poweroff; internal_ops->setup_qos_settings = cam_cpastop_setup_qos_settings; + internal_ops->print_poweron_settings = + cam_cpastop_print_poweron_settings; return 0; } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 890520c78e19..65a282d2e741 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -20,6 +20,7 @@ #include "cam_isp_context.h" #include "cam_common_util.h" #include "cam_req_mgr_debug.h" +#include "cam_cpas_api.h" static const char isp_dev_name[] = "cam-isp"; @@ -862,6 +863,8 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( ctx_isp->req_info.last_bufdone_req_id = req->request_id; } + cam_cpas_notify_event("IFE BufDone", buf_done_req_id); + __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 49e76452c165..2c215fbacce8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1468,6 +1468,8 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, camif_priv->eof_ts.tv_usec = payload->ts.mono_time.tv_usec; + cam_cpas_notify_event("IFE EOF", evt_info.hw_idx); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); From eafe32715324ca98a0dc0d7b1c88e165241de336 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 8 Nov 2020 01:25:27 -0800 Subject: [PATCH 592/790] msm: camera: isp: Add checks to ensure valid out resource info in dump Currently, in case of violation on camif side, we initiate hw dump with event info havinf input resource id. This resource id is not applicable on vfe bus side. Add necessary check to ensure only valid vfe out resource info is dumped. CRs-Fixed: 2814398 Change-Id: Ifc7bac81e7a4d9993e1492b609b84d64ea3fd1f4 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 28 ++++++++++--------- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 20 +++++++++++++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index ac67d6237718..0a872944332a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7598,19 +7598,21 @@ static int cam_ife_hw_mgr_handle_hw_dump_info( } } - out_port_id = event_info->res_id & 0xFF; - hw_mgr_res = - &ife_hw_mgr_ctx->res_list_ife_out[out_port_id]; - 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_ops.process_cmd) { - rc = hw_intf->hw_ops.process_cmd( - hw_intf->hw_priv, - CAM_ISP_HW_CMD_DUMP_BUS_INFO, - (void *)event_info, - sizeof(struct cam_isp_hw_event_info)); + if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) { + out_port_id = event_info->res_id & 0xFF; + hw_mgr_res = + &ife_hw_mgr_ctx->res_list_ife_out[out_port_id]; + 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_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)event_info, + sizeof(struct cam_isp_hw_event_info)); + } } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index a20b79676cac..4502b07283a8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -630,6 +630,8 @@ static enum cam_vfe_bus_ver3_vfe_out_type case CAM_ISP_IFE_LITE_OUT_RES_GAMMA: return CAM_VFE_BUS_VER3_VFE_OUT_GAMMA; default: + CAM_WARN(CAM_ISP, "Invalid isp res id: %d , assigning max", + res_type); return CAM_VFE_BUS_VER3_VFE_OUT_MAX; } } @@ -2508,8 +2510,26 @@ static int cam_vfe_bus_ver3_print_dimensions( int i; uint32_t addr_status0, addr_status1, addr_status2, addr_status3; + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid bus private data, res_id: %d", + vfe_out_res_id); + return -EINVAL; + } + + if (vfe_out_res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "Invalid out resource for dump: %d", + vfe_out_res_id); + return -EINVAL; + } + rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "VFE out data is null, res_id: %d", + vfe_out_res_id); + return -EINVAL; + } + for (i = 0; i < rsrc_data->num_wm; i++) { wm_data = rsrc_data->wm_res[i].res_priv; common_data = rsrc_data->common_data; From a702cc226a67d968496c5ecf57085806b0a09257 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 29 Oct 2020 04:35:01 -0700 Subject: [PATCH 593/790] msm: camera: smmu: Add support to force all CACHED Add implementation to allow forcing all camera buffer allocations to be CACHED and mapped as CACHED while iommu_map. This is enabled based on DT property. Force this only if io-coherency is enabled. Validations are added to make sure a correct combination of "force_cache" and "io-coherency" properties are mentioned in DT. CRs-Fixed: 2814719 Change-Id: I0d291ce199f523d67e8cd0105386cc63a671806e Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_req_mgr/cam_mem_mgr.c | 11 ++ drivers/cam_req_mgr/cam_mem_mgr.h | 2 + drivers/cam_smmu/cam_smmu_api.c | 174 +++++++++++++++++++++++++++++- drivers/cam_smmu/cam_smmu_api.h | 6 ++ 4 files changed, 190 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index a3e18f3d729d..a8db5ef8b744 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -166,6 +166,11 @@ int cam_mem_mgr_init(void) memset(tbl.bufq, 0, sizeof(tbl.bufq)); + if (cam_smmu_need_force_alloc_cached(&tbl.force_cache_allocs)) { + CAM_ERR(CAM_MEM, "Error in getting force cache alloc flag"); + return -EINVAL; + } + bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long); tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL); if (!tbl.bitmap) @@ -415,6 +420,9 @@ static int cam_mem_util_get_dma_buf(size_t len, return -EINVAL; } + if (tbl.force_cache_allocs && (!(flags & ION_FLAG_SECURE))) + flags |= ION_FLAG_CACHED; + *buf = ion_alloc(len, heap_id_mask, flags); if (IS_ERR_OR_NULL(*buf)) return -ENOMEM; @@ -442,6 +450,9 @@ static int cam_mem_util_get_dma_buf_fd(size_t len, if (tbl.alloc_profile_enable) CAM_GET_TIMESTAMP(ts1); + if (tbl.force_cache_allocs && (!(flags & ION_FLAG_SECURE))) + flags |= ION_FLAG_CACHED; + *buf = ion_alloc(len, heap_id_mask, flags); if (IS_ERR_OR_NULL(*buf)) return -ENOMEM; diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index 79d60cb96f6f..b4310db58d2b 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -70,6 +70,7 @@ struct cam_mem_buf_queue { * @dentry: Debugfs entry * @alloc_profile_enable: Whether to enable alloc profiling * @dbg_buf_idx: debug buffer index to get usecases info + * @force_cache_allocs: Force all internal buffer allocations with cache */ struct cam_mem_table { struct mutex m_lock; @@ -79,6 +80,7 @@ struct cam_mem_table { struct dentry *dentry; bool alloc_profile_enable; size_t dbg_buf_idx; + bool force_cache_allocs; }; /** diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index e2fdfeed93a9..14734c75a15d 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -62,6 +62,12 @@ struct cam_smmu_work_payload { struct list_head list; }; +enum cam_io_coherency_mode { + CAM_SMMU_NO_COHERENCY, + CAM_SMMU_DMA_COHERENT, + CAM_SMMU_DMA_COHERENT_HINT_CACHED, +}; + enum cam_protection_type { CAM_PROT_INVALID, CAM_NON_SECURE, @@ -155,6 +161,7 @@ struct cam_context_bank_info { bool is_mul_client; int device_count; int num_shared_hdl; + enum cam_io_coherency_mode coherency_mode; /* discard iova - non-zero values are valid */ dma_addr_t discard_iova_start; @@ -175,6 +182,7 @@ struct cam_iommu_cb_set { struct dentry *dentry; bool cb_dump_enable; bool map_profile_enable; + bool force_cache_allocs; }; static const struct of_device_id msm_cam_smmu_dt_match[] = { @@ -357,6 +365,111 @@ static void cam_smmu_dump_monitor_array( } } +int cam_smmu_need_force_alloc_cached(bool *force_alloc_cached) +{ + int idx; + uint32_t curr_mode = 0, final_mode = 0; + bool validate = false; + + if (!force_alloc_cached) { + CAM_ERR(CAM_SMMU, "Invalid arg"); + return -EINVAL; + } + + CAM_INFO(CAM_SMMU, "force_cache_allocs=%d", + iommu_cb_set.force_cache_allocs); + + /* + * First validate whether all SMMU CBs are properly setup to comply with + * iommu_cb_set.force_alloc_cached flag. + * This helps as a validation check to make sure a valid DT combination + * is set for a given chipset. + */ + for (idx = 0; idx < iommu_cb_set.cb_num; idx++) { + /* ignore secure cb for now. need to revisit */ + if (iommu_cb_set.cb_info[idx].is_secure) + continue; + + curr_mode = iommu_cb_set.cb_info[idx].coherency_mode; + + /* + * 1. No coherency: + * We can map both CACHED and UNCACHED buffers into same CB. + * We need to allocate UNCACHED buffers for Cmdbuffers + * and Shared Buffers. UNCAHE support must exists with memory + * allocators (ion or dma-buf-heaps) for CmdBuffers, + * SharedBuffers to work - as it is difficult to do + * cache operations on these buffers in camera design. + * ImageBuffers can be CACHED or UNCACHED. If CACHED, clients + * need to make required CACHE operations. + * Cannot force all allocations to CACHE. + * 2. dma-coherent: + * We cannot map CACHED and UNCACHED buffers into the same CB + * This means, we must force allocate all buffers to be + * CACHED. + * 3. dma-coherent-hint-cached + * We can map both CACHED and UNCACHED buffers into the same + * CB. So any option is fine force_cache_allocs. + * Forcing to cache is preferable though. + * + * Other rule we are enforcing is - all camera CBs (except + * secure CB) must have same coherency mode set. Assume one CB + * is having no_coherency mode and other CB is having + * dma_coherent. For no_coherency CB to work - we must not force + * buffers to be CACHE (exa cmd buffers), for dma_coherent mode + * we must force all buffers to be CACHED. But at the time of + * allocation, we dont know to which CB we will be mapping this + * buffer. So it becomes difficult to generalize cache + * allocations and io coherency mode that we want to support. + * So, to simplify, all camera CBs will have same mode. + */ + + CAM_DBG(CAM_SMMU, "[%s] : curr_mode=%d", + iommu_cb_set.cb_info[idx].name[0], curr_mode); + + if (curr_mode == CAM_SMMU_NO_COHERENCY) { + if (iommu_cb_set.force_cache_allocs) { + CAM_ERR(CAM_SMMU, + "[%s] Can't force alloc cache with no coherency", + iommu_cb_set.cb_info[idx].name[0]); + return -EINVAL; + } + } else if (curr_mode == CAM_SMMU_DMA_COHERENT) { + if (!iommu_cb_set.force_cache_allocs) { + CAM_ERR(CAM_SMMU, + "[%s] Must force cache allocs for dma coherent device", + iommu_cb_set.cb_info[idx].name[0]); + return -EINVAL; + } + } + + if (validate) { + if (curr_mode != final_mode) { + CAM_ERR(CAM_SMMU, + "[%s] CBs having different coherency modes final=%d, curr=%d", + iommu_cb_set.cb_info[idx].name[0], + final_mode, curr_mode); + return -EINVAL; + } + } else { + validate = true; + final_mode = curr_mode; + } + } + + /* + * To be more accurate - if this flag is TRUE and if this buffer will + * be mapped to external devices like CVP - we need to ensure we do + * one of below : + * 1. CVP CB having dma-coherent or dma-coherent-hint-cached + * 2. camera/cvp sw layers properly doing required cache operations. We + * cannot anymore assume these buffers (camera <--> cvp) are uncached + */ + *force_alloc_cached = iommu_cb_set.force_cache_allocs; + + return 0; +} + static void cam_smmu_page_fault_work(struct work_struct *work) { int j; @@ -1352,6 +1465,14 @@ int cam_smmu_alloc_firmware(int32_t smmu_hdl, icp_fw.fw_kva, (void *)icp_fw.fw_hdl); domain = iommu_cb_set.cb_info[idx].domain; + + /* + * Revisit this - what should we map this with - CACHED or UNCACHED? + * chipsets using dma-coherent-hint-cached - leaving it like this is + * fine as we can map both CACHED and UNCACHED on same CB. + * But on chipsets which use dma-coherent - all the buffers that are + * being mapped to this CB must be CACHED + */ rc = iommu_map(domain, firmware_start, (phys_addr_t) icp_fw.fw_hdl, @@ -1492,6 +1613,14 @@ int cam_smmu_alloc_qdss(int32_t smmu_hdl, CAM_DBG(CAM_SMMU, "QDSS area len from DT = %zu", qdss_len); domain = iommu_cb_set.cb_info[idx].domain; + + /* + * Revisit this - what should we map this with - CACHED or UNCACHED? + * chipsets using dma-coherent-hint-cached - leaving it like this is + * fine as we can map both CACHED and UNCACHED on same CB. + * But on chipsets which use dma-coherent - all the buffers that are + * being mapped to this CB must be CACHED + */ rc = iommu_map(domain, qdss_start, qdss_phy_addr, @@ -1721,6 +1850,7 @@ int cam_smmu_reserve_sec_heap(int32_t smmu_hdl, size_t sec_heap_iova_len = 0; int idx; int rc = 0; + int prot = 0; idx = GET_SMMU_TABLE_IDX(smmu_hdl); if (idx < 0 || idx >= iommu_cb_set.cb_num) { @@ -1771,11 +1901,16 @@ int cam_smmu_reserve_sec_heap(int32_t smmu_hdl, sec_heap_iova = iommu_cb_set.cb_info[idx].secheap_info.iova_start; sec_heap_iova_len = iommu_cb_set.cb_info[idx].secheap_info.iova_len; + + prot = IOMMU_READ | IOMMU_WRITE; + if (iommu_cb_set.force_cache_allocs) + prot |= IOMMU_CACHE; + size = iommu_map_sg(iommu_cb_set.cb_info[idx].domain, sec_heap_iova, secheap_buf->table->sgl, secheap_buf->table->nents, - IOMMU_READ | IOMMU_WRITE); + prot); if (size != sec_heap_iova_len) { CAM_ERR(CAM_SMMU, "IOMMU mapping failed"); goto err_unmap_sg; @@ -1868,6 +2003,7 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, int rc = 0; struct timespec64 ts1, ts2; long microsec = 0; + int prot = 0; if (IS_ERR_OR_NULL(buf)) { rc = PTR_ERR(buf); @@ -1918,8 +2054,12 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf, goto err_unmap_sg; } + prot = IOMMU_READ | IOMMU_WRITE; + if (iommu_cb_set.force_cache_allocs) + prot |= IOMMU_CACHE; + size = iommu_map_sg(domain, iova, table->sgl, table->nents, - IOMMU_READ | IOMMU_WRITE); + prot); if (size < 0) { CAM_ERR(CAM_SMMU, "IOMMU mapping failed"); @@ -2415,6 +2555,9 @@ static int cam_smmu_alloc_scratch_buffer_add_to_list(int idx, goto err_iommu_map; } + if (iommu_cb_set.force_cache_allocs) + iommu_dir |= IOMMU_CACHE; + if (iommu_map_sg(domain, iova, table->sgl, @@ -3880,6 +4023,7 @@ static int cam_populate_smmu_context_banks(struct device *dev, struct cam_context_bank_info *cb; struct device *ctx = NULL; int i = 0; + bool dma_coherent, dma_coherent_hint; if (!dev) { CAM_ERR(CAM_SMMU, "Error: Invalid device"); @@ -3944,6 +4088,27 @@ static int cam_populate_smmu_context_banks(struct device *dev, ctx = dev; CAM_DBG(CAM_SMMU, "getting Arm SMMU ctx : %s", cb->name[0]); + cb->coherency_mode = CAM_SMMU_NO_COHERENCY; + + dma_coherent = of_property_read_bool(dev->of_node, "dma-coherent"); + dma_coherent_hint = of_property_read_bool(dev->of_node, + "dma-coherent-hint-cached"); + + if (dma_coherent && dma_coherent_hint) { + CAM_ERR(CAM_SMMU, + "[%s] : Cannot enable both dma-coherent and dma-coherent-hint-cached", + cb->name[0]); + return -EBADR; + } + + if (dma_coherent) + cb->coherency_mode = CAM_SMMU_DMA_COHERENT; + else if (dma_coherent_hint) + cb->coherency_mode = CAM_SMMU_DMA_COHERENT_HINT_CACHED; + + CAM_DBG(CAM_SMMU, "[%s] : io cohereny mode %d", cb->name[0], + cb->coherency_mode); + rc = cam_smmu_setup_cb(cb, ctx); if (rc < 0) { CAM_ERR(CAM_SMMU, "Error: failed to setup cb : %s", @@ -3998,7 +4163,7 @@ static int cam_smmu_create_debug_fs(void) iommu_cb_set.dentry, &iommu_cb_set.map_profile_enable); if (IS_ERR(dbgfileptr)) { if (PTR_ERR(dbgfileptr) == -ENODEV) - CAM_WARN(CAM_MEM, "DebugFS not enabled in kernel!"); + CAM_WARN(CAM_SMMU, "DebugFS not enabled in kernel!"); else rc = PTR_ERR(dbgfileptr); } @@ -4098,6 +4263,9 @@ static int cam_smmu_component_bind(struct device *dev, INIT_LIST_HEAD(&iommu_cb_set.payload_list); cam_smmu_create_debug_fs(); + iommu_cb_set.force_cache_allocs = + of_property_read_bool(dev->of_node, "force_cache_allocs"); + CAM_DBG(CAM_SMMU, "Main component bound successfully"); return 0; } diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index df1cbdf58f8f..81c0170a8eb8 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -432,4 +432,10 @@ int cam_smmu_init_module(void); */ void cam_smmu_exit_module(void); +/** + * @brief : API to determine whether to force all allocations to CACHED + */ +int cam_smmu_need_force_alloc_cached(bool *force_alloc_cached); + + #endif /* _CAM_SMMU_API_H_ */ From db35bc782a0629efff34271fb0425e02e4f96928 Mon Sep 17 00:00:00 2001 From: Anand Ravi Date: Mon, 2 Nov 2020 13:31:52 -0800 Subject: [PATCH 594/790] msm: camera: ife: Fix bus print dimension Fixes the null pointer dereference in the print dimension function. CRs-Fixed: 2809214 Change-Id: I6467f183cca9f665c89f1a418b320cd55be7700a Signed-off-by: Anand Ravi --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 5fa123654ef8..a20b79676cac 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2505,19 +2505,13 @@ static int cam_vfe_bus_ver3_print_dimensions( struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; struct cam_vfe_bus_ver3_common_data *common_data = NULL; - int i, wm_idx; + int i; uint32_t addr_status0, addr_status1, addr_status2, addr_status3; rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; for (i = 0; i < rsrc_data->num_wm; i++) { - wm_idx = 0; - if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { - CAM_ERR(CAM_ISP, "Unsupported VFE out %d", - vfe_out_res_id); - return -EINVAL; - } - wm_data = bus_priv->bus_client[wm_idx].res_priv; + wm_data = rsrc_data->wm_res[i].res_priv; common_data = rsrc_data->common_data; addr_status0 = cam_io_r_mb(common_data->mem_base + wm_data->hw_regs->addr_status_0); @@ -2530,7 +2524,7 @@ static int cam_vfe_bus_ver3_print_dimensions( CAM_INFO(CAM_ISP, "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", - wm_data->common_data->core_index, wm_idx, + wm_data->common_data->core_index, wm_data->index, wm_data->width, wm_data->height, wm_data->stride, wm_data->h_init, From 5433b7e49db9f442f7756df02f64325b10fb7327 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Thu, 29 Oct 2020 17:04:43 -0700 Subject: [PATCH 595/790] msm: camera: isp: Fix the callback arguments in IFE Fix the callback arguments in IFE to avoid the CFI check failure. A few callbacks invokes do not typecast for the last argument of the event callback. Since callbacks are indirect function call, CFI check for this will fail. CRs-Fixed: 2807933 Change-Id: I4e72cf07de701bbfd8f7d7829207256918beeb4c Signed-off-by: Jigar Agrawal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 40f1d24701e6..0804b52c404a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7718,7 +7718,7 @@ static int cam_ife_hw_mgr_handle_hw_rup( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; ife_hwr_irq_rup_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&rup_event_data); break; case CAM_ISP_HW_VFE_IN_RDI0: @@ -7730,7 +7730,7 @@ static int cam_ife_hw_mgr_handle_hw_rup( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; ife_hwr_irq_rup_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&rup_event_data); break; case CAM_ISP_HW_VFE_IN_PDLIB: @@ -7768,7 +7768,7 @@ static int cam_ife_hw_mgr_handle_hw_epoch( epoch_done_event_data.frame_id_meta = event_info->reg_val; ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); + CAM_ISP_HW_EVENT_EPOCH, (void *)&epoch_done_event_data); break; @@ -7836,7 +7836,7 @@ static int cam_ife_hw_mgr_handle_hw_sof( break; ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data); break; @@ -7852,7 +7852,7 @@ static int cam_ife_hw_mgr_handle_hw_sof( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; ife_hw_irq_sof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data); break; case CAM_ISP_HW_VFE_IN_PDLIB: @@ -7889,7 +7889,7 @@ static int cam_ife_hw_mgr_handle_hw_eof( break; ife_hw_irq_eof_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + CAM_ISP_HW_EVENT_EOF, (void *)&eof_done_event_data); break; @@ -7936,7 +7936,7 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( if (buf_done_event_data.num_handles > 0 && ife_hwr_irq_wm_done_cb) { CAM_DBG(CAM_ISP, "Notify ISP context"); ife_hwr_irq_wm_done_cb(ife_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); + CAM_ISP_HW_EVENT_DONE, (void *)&buf_done_event_data); } CAM_DBG(CAM_ISP, From 7c41ceeabffc51df1c3ab4b0e904cc7025fc415e Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 27 Oct 2020 22:37:04 +0530 Subject: [PATCH 596/790] msm: camera: isp: Move the CSID irq logs to bottom half Remove the sof log in CSID irq handler and handle it in the Bottom half.Sof irq enabled during the sof freeze scenario and sof log getting printed in the irq handler causing the interrupt handling taking more time. CRs-Fixed: 2804588 Change-Id: I9514bf79333665dcd9407932789ce00c4ed480d8 Signed-off-by: Chandan Kumar Jha --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 149 +++++++++++------- 1 file changed, 94 insertions(+), 55 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index febc58054032..0ece0bf29e40 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1910,9 +1910,6 @@ static void cam_ife_csid_halt_csi2( csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); - cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, - CAM_SUBDEV_MESSAGE_IRQ_ERR, - csid_hw->csi2_rx_cfg.phy_sel); } static int cam_ife_csid_init_config_pxl_path( @@ -4199,7 +4196,8 @@ static int cam_ife_csid_sof_irq_debug( if (csid_hw->hw_info->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_WARN(CAM_ISP, - "CSID powered down unable to %s sof irq", + "CSID:%d powered down unable to %s sof irq", + csid_hw->hw_intf->hw_idx, (sof_irq_enable == true) ? "enable" : "disable"); return 0; } @@ -4258,9 +4256,10 @@ static int cam_ife_csid_sof_irq_debug( csid_hw->sof_irq_triggered = false; } - CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s, CSID HW:%d", - (sof_irq_enable) ? "enabled" : "disabled", - csid_hw->hw_intf->hw_idx); + if (!in_irq()) + CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s, CSID HW:%d", + (sof_irq_enable) ? "enabled" : "disabled", + csid_hw->hw_intf->hw_idx); return 0; } @@ -4601,35 +4600,6 @@ static int cam_csid_put_evt_payload( return 0; } -static char *cam_csid_status_to_str(uint32_t status) -{ - switch (status) { - case CAM_IFE_CSID_IRQ_REG_TOP: - return "TOP"; - case CAM_IFE_CSID_IRQ_REG_RX: - return "RX"; - case CAM_IFE_CSID_IRQ_REG_IPP: - return "IPP"; - case CAM_IFE_CSID_IRQ_REG_PPP: - return "PPP"; - case CAM_IFE_CSID_IRQ_REG_RDI_0: - return "RDI0"; - case CAM_IFE_CSID_IRQ_REG_RDI_1: - return "RDI1"; - case CAM_IFE_CSID_IRQ_REG_RDI_2: - return "RDI2"; - case CAM_IFE_CSID_IRQ_REG_RDI_3: - return "RDI3"; - case CAM_IFE_CSID_IRQ_REG_UDI_0: - return "UDI0"; - case CAM_IFE_CSID_IRQ_REG_UDI_1: - return "UDI1"; - case CAM_IFE_CSID_IRQ_REG_UDI_2: - return "UDI2"; - default: - return "Invalid IRQ"; - } -} static int cam_csid_evt_bottom_half_handler( void *handler_priv, @@ -4640,6 +4610,8 @@ static int cam_csid_evt_bottom_half_handler( int i; int rc = 0; struct cam_isp_hw_event_info event_info; + const struct cam_ife_csid_reg_offset *csid_reg; + int udi_start_idx = CAM_IFE_CSID_IRQ_REG_UDI_0; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, @@ -4650,6 +4622,7 @@ static int cam_csid_evt_bottom_half_handler( csid_hw = (struct cam_ife_csid_hw *)handler_priv; evt_payload = (struct cam_csid_evt_payload *)evt_payload_priv; + csid_reg = csid_hw->csid_info->csid_reg; if (!csid_hw->event_cb || !csid_hw->priv) { CAM_ERR_RATE_LIMIT(CAM_ISP, @@ -4669,16 +4642,60 @@ static int cam_csid_evt_bottom_half_handler( goto end; } - CAM_ERR_RATE_LIMIT(CAM_ISP, "idx %d err %d phy %d cnt %d", - csid_hw->hw_intf->hw_idx, - evt_payload->evt_type, - csid_hw->csi2_rx_cfg.phy_sel, - csid_hw->csi2_cfg_cnt); + if (csid_hw->sof_irq_triggered && (evt_payload->evt_type == + CAM_ISP_HW_ERROR_NONE)) { + if (evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & + CSID_PATH_INFO_INPUT_SOF) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + } - for (i = 0; i < CAM_IFE_CSID_IRQ_REG_MAX; i++) - CAM_ERR_RATE_LIMIT(CAM_ISP, "status %s: %x", - cam_csid_status_to_str(i), - evt_payload->irq_status[i]); + if (evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & + CSID_PATH_INFO_INPUT_SOF) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d PPP SOF received", + csid_hw->hw_intf->hw_idx); + } + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + if (evt_payload->irq_status[i] & + CSID_PATH_INFO_INPUT_SOF) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d RDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); + } + + for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) { + if (evt_payload->irq_status[udi_start_idx + i] & + CSID_PATH_INFO_INPUT_SOF) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d UDI:%d SOF received", + csid_hw->hw_intf->hw_idx, i); + } + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID %d err %d phy %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x PPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x RDI3: 0x%x UDI0: 0x%x UDI1: 0x%x UDI2: 0x%x", + csid_hw->hw_intf->hw_idx, + evt_payload->evt_type, + csid_hw->csi2_rx_cfg.phy_sel, + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_TOP], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RX], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_IPP], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_PPP], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_0], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_1], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_2], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_RDI_3], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_1], + evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_2]); + } + + if (evt_payload->evt_type == CAM_ISP_HW_ERROR_CSID_FATAL) + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + csid_hw->csi2_rx_cfg.phy_sel); /* this hunk can be extended to handle more cases * which we want to offload to bottom half from @@ -4697,7 +4714,7 @@ static int cam_csid_evt_bottom_half_handler( break; default: - CAM_DBG(CAM_ISP, "CSID[%d] invalid error type %d", + CAM_DBG(CAM_ISP, "CSID[%d] error type %d", csid_hw->hw_intf->hw_idx, evt_payload->evt_type); break; @@ -4763,7 +4780,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX] = {0}; uint32_t i, val, val2; bool fatal_err_detected = false; - uint32_t sof_irq_debug_en = 0; + uint32_t sof_irq_debug_en = 0, log_en = 0; unsigned long flags; csid_hw = (struct cam_ife_csid_hw *)data; @@ -5129,8 +5146,13 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP SOF received", - csid_hw->hw_intf->hw_idx); + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5201,8 +5223,13 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP SOF received", - csid_hw->hw_intf->hw_idx); + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP SOF received", + csid_hw->hw_intf->hw_idx); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5270,9 +5297,13 @@ handle_fatal_error: if ((irq_status[i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d RDI:%d SOF received", - csid_hw->hw_intf->hw_idx, i); + csid_hw->hw_intf->hw_idx, i); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5340,9 +5371,13 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) { - CAM_INFO_RATE_LIMIT(CAM_ISP, + if (!csid_hw->sof_irq_triggered) + CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d UDI:%d SOF received", - csid_hw->hw_intf->hw_idx, i); + csid_hw->hw_intf->hw_idx, i); + else + log_en = 1; + if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; } @@ -5378,6 +5413,10 @@ handle_fatal_error: } } + if (log_en) + cam_csid_handle_hw_err_irq(csid_hw, + CAM_ISP_HW_ERROR_NONE, irq_status); + if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_ife_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); csid_hw->irq_debug_cnt = 0; From 6103984425372d73f6b3dce5fba766d729b763a5 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 3 Nov 2020 12:48:53 +0800 Subject: [PATCH 597/790] msm: camera: isp: Add trigger id for EOF event When we do flash operation in SHDR usecase, the trigger count will mismatch if we don't pass trigger id to CRM. CRs-Fixed: 2813321 Change-Id: Ic557f1122f8698f987d249fe1d15e35b90326e1d Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 890520c78e19..6c4a6ac969b8 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1631,6 +1631,7 @@ static int __cam_isp_ctx_notify_eof_in_activated_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_EOF; + notify.trigger_id = ctx_isp->trigger_id; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld ctx %u", From c1cc445da857d89865a93ccdfe1c0912434c78e4 Mon Sep 17 00:00:00 2001 From: Mukund Madhusudan Atre Date: Sun, 8 Nov 2020 01:25:27 -0800 Subject: [PATCH 598/790] msm: camera: isp: Add checks to ensure valid out resource info in dump Currently, in case of violation on camif side, we initiate hw dump with event info havinf input resource id. This resource id is not applicable on vfe bus side. Add necessary check to ensure only valid vfe out resource info is dumped. CRs-Fixed: 2814398 Change-Id: Ifc7bac81e7a4d9993e1492b609b84d64ea3fd1f4 Signed-off-by: Mukund Madhusudan Atre --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 28 ++++++++++--------- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 20 +++++++++++++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 0804b52c404a..543c468195d7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7589,19 +7589,21 @@ static int cam_ife_hw_mgr_handle_hw_dump_info( } } - out_port_id = event_info->res_id & 0xFF; - hw_mgr_res = - &ife_hw_mgr_ctx->res_list_ife_out[out_port_id]; - 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_ops.process_cmd) { - rc = hw_intf->hw_ops.process_cmd( - hw_intf->hw_priv, - CAM_ISP_HW_CMD_DUMP_BUS_INFO, - (void *)event_info, - sizeof(struct cam_isp_hw_event_info)); + if (event_info->res_type == CAM_ISP_RESOURCE_VFE_OUT) { + out_port_id = event_info->res_id & 0xFF; + hw_mgr_res = + &ife_hw_mgr_ctx->res_list_ife_out[out_port_id]; + 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_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)event_info, + sizeof(struct cam_isp_hw_event_info)); + } } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index a20b79676cac..4502b07283a8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -630,6 +630,8 @@ static enum cam_vfe_bus_ver3_vfe_out_type case CAM_ISP_IFE_LITE_OUT_RES_GAMMA: return CAM_VFE_BUS_VER3_VFE_OUT_GAMMA; default: + CAM_WARN(CAM_ISP, "Invalid isp res id: %d , assigning max", + res_type); return CAM_VFE_BUS_VER3_VFE_OUT_MAX; } } @@ -2508,8 +2510,26 @@ static int cam_vfe_bus_ver3_print_dimensions( int i; uint32_t addr_status0, addr_status1, addr_status2, addr_status3; + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid bus private data, res_id: %d", + vfe_out_res_id); + return -EINVAL; + } + + if (vfe_out_res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "Invalid out resource for dump: %d", + vfe_out_res_id); + return -EINVAL; + } + rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; rsrc_data = rsrc_node->res_priv; + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "VFE out data is null, res_id: %d", + vfe_out_res_id); + return -EINVAL; + } + for (i = 0; i < rsrc_data->num_wm; i++) { wm_data = rsrc_data->wm_res[i].res_priv; common_data = rsrc_data->common_data; From 05abdc71b01e72adbc938b2ed50feb2350466892 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Wed, 14 Oct 2020 19:54:34 -0700 Subject: [PATCH 599/790] msm: camera: common: Improve IFE and CRM Logging Improve IFE acquire logging and CRM SOF Freeze logging for better debugging. CRs-Fixed: 2812910 Change-Id: Ice9638872c9cf540b8721cd07f3d0c6b1f4b3bd4 Signed-off-by: Karthik Anantha Ram Signed-off-by: Jigar Agrawal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 55 ++++++++++++------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 32 ++++++----- drivers/cam_req_mgr/cam_req_mgr_core.c | 15 ++++- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index ac67d6237718..94c6a6ce925d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -742,6 +742,12 @@ static void cam_ife_hw_mgr_dump_all_ctx(void) struct cam_ife_hw_mgr_ctx *ctx_temp; mutex_lock(&g_ife_hw_mgr.ctx_mutex); + if (list_empty(&g_ife_hw_mgr.used_ctx_list)) { + CAM_INFO(CAM_ISP, "Currently no ctx in use"); + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); + return; + } + list_for_each_entry_safe(ctx, ctx_temp, &g_ife_hw_mgr.used_ctx_list, list) { CAM_INFO_RATE_LIMIT(CAM_ISP, @@ -799,17 +805,15 @@ static void cam_ife_hw_mgr_print_acquire_info( int hw_idx[CAM_ISP_HW_SPLIT_MAX] = {-1, -1}; int i = 0; - hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_csid, - struct cam_isp_hw_mgr_res, list); - - if (hw_mgr_ctx->is_offline) + if (!list_empty(&hw_mgr_ctx->res_list_ife_src)) { hw_mgr_res = list_first_entry(&hw_mgr_ctx->res_list_ife_src, struct cam_isp_hw_mgr_res, list); - for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - hw_res = hw_mgr_res->hw_res[i]; - if (hw_res && hw_res->hw_intf) - hw_idx[i] = hw_res->hw_intf->hw_idx; + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + hw_res = hw_mgr_res->hw_res[i]; + if (hw_res && hw_res->hw_intf) + hw_idx[i] = hw_res->hw_intf->hw_idx; + } } if (acquire_failed) @@ -824,12 +828,12 @@ static void cam_ife_hw_mgr_print_acquire_info( return; fail: - CAM_ERR(CAM_ISP, "Acquire HW failed for ctx:%u", hw_mgr_ctx->ctx_index); - CAM_INFO(CAM_ISP, - "Acquire fail for ctx:%u %s IFE[%d %d] with [%u pix] [%u pd] [%u rdi] ports", - hw_mgr_ctx->ctx_index, (hw_mgr_ctx->is_dual) ? "dual" : "single", - hw_idx[CAM_ISP_HW_SPLIT_LEFT], hw_idx[CAM_ISP_HW_SPLIT_RIGHT], - num_pix_port, num_pd_port, num_rdi_port); + CAM_ERR(CAM_ISP, + "Failed to acquire %s-IFE with [%u pix] [%u pd] [%u rdi] ports for ctx:%u", + (hw_mgr_ctx->is_dual) ? "dual" : "single", + num_pix_port, num_pd_port, num_rdi_port, hw_mgr_ctx->ctx_index); + CAM_INFO(CAM_ISP, "Previously acquired IFEs[%d %d]", + hw_idx[CAM_ISP_HW_SPLIT_LEFT], hw_idx[CAM_ISP_HW_SPLIT_RIGHT]); list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp, &hw_mgr_ctx->res_list_ife_src, list) { @@ -1706,6 +1710,7 @@ static int cam_ife_hw_mgr_acquire_csid_hw( return -EINVAL; } + CAM_DBG(CAM_ISP, "Acquire CSID HW lower_idx: %d", is_start_lower_idx); if (is_start_lower_idx) { for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { if (!ife_hw_mgr->csid_devices[i]) @@ -1767,6 +1772,7 @@ 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 = path_res_id; + csid_acquire.node_res = NULL; if (ife_ctx->is_rdi_only_context) csid_acquire.can_use_lite = true; @@ -1840,8 +1846,12 @@ static int cam_ife_mgr_acquire_cid_res( } } - /* Acquire right if not already acquired */ - /* For dual IFE cases, master will be lower idx */ + /* Acquire Left if not already acquired */ + /* For dual IFE cases, start acquiring the lower idx first */ + CAM_DBG(CAM_ISP, "acquire new rsrc fe: %d usage_type %d dsp %d rsrc %p", + ife_ctx->is_fe_enabled, in_port->usage_type, + ife_ctx->dsp_enabled, csid_acquire.node_res); + if (ife_ctx->is_fe_enabled || ife_ctx->dsp_enabled) rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr, @@ -1851,7 +1861,8 @@ static int cam_ife_mgr_acquire_cid_res( &csid_acquire, false); if (rc || !csid_acquire.node_res) { - CAM_ERR(CAM_ISP, "No %d paths available", path_res_id); + CAM_ERR(CAM_ISP, "No %d paths available rc %d rsrc %p", + path_res_id, rc, csid_acquire.node_res); goto put_res; } @@ -2718,6 +2729,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx( is_dual_isp = in_port->usage_type; ife_ctx->dsp_enabled = (bool)in_port->dsp_mode; + ife_ctx->is_dual = (bool)in_port->usage_type; /* get root node resource */ rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port); @@ -3131,6 +3143,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) CAM_ERR(CAM_ISP, "Failed in parsing: %d", rc); goto free_mem; } + CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type); cam_ife_hw_mgr_preprocess_port(ife_ctx, &in_port[i]); total_pix_port += in_port[i].ipp_count + @@ -3148,7 +3161,6 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) /* acquire HW resources */ for (i = 0; i < acquire_hw_info->num_inputs; i++) { - CAM_DBG(CAM_ISP, "in_res_type %x", in_port[i].res_type); if ((in_port[i].cust_node) && (!ife_ctx->custom_enabled)) { @@ -3184,8 +3196,11 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) if (rc) { cam_ife_hw_mgr_print_acquire_info(ife_ctx, - total_pix_port, total_pd_port, - total_rdi_port, rc); + (in_port[i].ipp_count + + in_port[i].ife_rd_count + + in_port[i].lcr_count), + in_port[i].ppp_count, + in_port[i].rdi_count, rc); goto free_res; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index ed3e0a75c6ab..83b2a2c2ba90 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -692,19 +692,20 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, struct cam_csid_soc_private *soc_priv; CAM_DBG(CAM_ISP, - "CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d", + "CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d cust_node:%u", csid_hw->hw_intf->hw_idx, cid_reserv->in_port->res_type, cid_reserv->in_port->lane_type, cid_reserv->in_port->lane_num, cid_reserv->in_port->dt[0], - cid_reserv->in_port->vc[0]); + cid_reserv->in_port->vc[0], + cid_reserv->in_port->cust_node); soc_priv = (struct cam_csid_soc_private *) (csid_hw->hw_info->soc_info.soc_private); if (soc_priv->is_ife_csid_lite && !cid_reserv->can_use_lite) { - CAM_INFO(CAM_ISP, "CSID[%u] not lite context", + CAM_DBG(CAM_ISP, "CSID[%u] not lite context", csid_hw->hw_intf->hw_idx); return -EINVAL; } @@ -821,8 +822,10 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, if (cid_reserv->in_port->cust_node == CAM_ISP_ACQ_CUSTOM_PRIMARY) { if (csid_hw->hw_intf->hw_idx != 0) { - CAM_ERR(CAM_ISP, "CSID%d not eligible", - csid_hw->hw_intf->hw_idx); + CAM_ERR(CAM_ISP, + "CSID%d not eligible for cust_node: %u", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->cust_node); rc = -EINVAL; goto end; } @@ -831,8 +834,10 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, if (cid_reserv->in_port->cust_node == CAM_ISP_ACQ_CUSTOM_SECONDARY) { if (csid_hw->hw_intf->hw_idx != 1) { - CAM_ERR(CAM_ISP, "CSID%d not eligible", - csid_hw->hw_intf->hw_idx); + CAM_ERR(CAM_ISP, + "CSID%d not eligible for cust_node: %u", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->cust_node); rc = -EINVAL; goto end; } @@ -859,7 +864,6 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, cid_reserv->in_port->lane_type || csid_hw->csi2_rx_cfg.lane_num != cid_reserv->in_port->lane_num)) { - rc = -EINVAL; goto end; } @@ -873,7 +877,6 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, cid_reserv->in_port->height || csid_hw->tpg_cfg.test_pattern != cid_reserv->in_port->test_pattern)) { - rc = -EINVAL; goto end; } @@ -953,6 +956,7 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, cid_data = (struct cam_ife_csid_cid_data *) cid_reserv->node_res->res_priv; + CAM_DBG(CAM_ISP, "Obtained cid:%d", cid_reserv->node_res->res_id); if (!csid_hw->csi2_reserve_cnt) { csid_hw->res_type = cid_reserv->in_port->res_type; @@ -1018,9 +1022,10 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, } csid_hw->csi2_reserve_cnt++; - CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired", + CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired phy_sel %u", csid_hw->hw_intf->hw_idx, - cid_reserv->node_res->res_id); + cid_reserv->node_res->res_id, + csid_hw->csi2_rx_cfg.phy_sel); end: return rc; @@ -3681,9 +3686,10 @@ int cam_ife_csid_release(void *hw_priv, memset(&csid_hw->csi2_rx_cfg, 0, sizeof(struct cam_ife_csid_csi2_rx_cfg)); - CAM_DBG(CAM_ISP, "CSID:%d res id :%d cnt:%d reserv cnt:%d", + CAM_DBG(CAM_ISP, "CSID:%d res id :%d cnt:%d reserv cnt:%d res_state:%d", csid_hw->hw_intf->hw_idx, - res->res_id, cid_data->cnt, csid_hw->csi2_reserve_cnt); + res->res_id, cid_data->cnt, csid_hw->csi2_reserve_cnt, + res->res_state); break; case CAM_ISP_RESOURCE_PIX_PATH: diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 33ea1bb6785e..7044ac5b39a6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2048,9 +2048,11 @@ static void __cam_req_mgr_notify_sof_freeze( static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) { struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_req_queue *in_q = NULL; struct cam_req_mgr_core_session *session = NULL; struct cam_req_mgr_message msg; int rc = 0; + int64_t last_applied_req_id = -EINVAL; if (!data || !priv) { CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); @@ -2064,6 +2066,13 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) return -EINVAL; } + in_q = link->req.in_q; + if (in_q) { + mutex_lock(&link->req.lock); + last_applied_req_id = in_q->slot[in_q->last_applied_idx].req_id; + mutex_unlock(&link->req.lock); + } + spin_lock_bh(&link->link_state_spin_lock); if ((link->watchdog) && (link->watchdog->pause_timer)) { CAM_INFO(CAM_CRM, "Watchdog Paused"); @@ -2072,8 +2081,10 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) } spin_unlock_bh(&link->link_state_spin_lock); - CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x", - session->session_hdl, link->link_hdl); + CAM_ERR(CAM_CRM, + "SOF freeze for session: %d link: 0x%x max_pd: %d last_req_id:%d", + session->session_hdl, link->link_hdl, link->max_delay, + last_applied_req_id); __cam_req_mgr_notify_sof_freeze(link); memset(&msg, 0, sizeof(msg)); From 9075af087029b54ac8cf11774419ab1710a8c916 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Fri, 16 Oct 2020 16:59:57 +0530 Subject: [PATCH 600/790] msm: camera: isp: Bubble re-apply with CDM callback detect Re-apply bubble request if buf done has not come for 2 bubble frames. Also before re-submitting the request to CDM check if CDM callback for that request has come or not, if CDM callback is received then wait for buf done else reset CDM and re-submit the request to CDM. CRs-Fixed: 2807378 Change-Id: I1fd209482e14d58aa48d12194084d0a2ab943e31 Signed-off-by: Wyes Karny --- drivers/cam_core/cam_hw_mgr_intf.h | 19 +-- drivers/cam_isp/cam_isp_context.c | 120 ++++++++++++++++-- drivers/cam_isp/cam_isp_context.h | 37 +++--- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 34 +++++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 2 + drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 34 +++++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 2 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 13 +- 8 files changed, 225 insertions(+), 36 deletions(-) diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 238932786346..9b6942acab61 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -243,14 +243,16 @@ struct cam_hw_stream_setttings { /** * struct cam_hw_config_args - Payload for config command * - * @ctxt_to_hw_map: HW context from the acquire - * @num_hw_update_entries: Number of hardware update entries - * @hw_update_entries: Hardware update list - * @out_map_entries: Out map info - * @num_out_map_entries: Number of out map entries - * @priv: Private pointer - * @request_id: Request ID - * @reapply True if reapplying after bubble + * @ctxt_to_hw_map: HW context from the acquire + * @num_hw_update_entries: Number of hardware update entries + * @hw_update_entries: Hardware update list + * @out_map_entries: Out map info + * @num_out_map_entries: Number of out map entries + * @priv: Private pointer + * @request_id: Request ID + * @reapply: True if reapplying after bubble + * @cdm_reset_before_apply: True is need to reset CDM before re-apply bubble + * request * */ struct cam_hw_config_args { @@ -263,6 +265,7 @@ struct cam_hw_config_args { uint64_t request_id; bool init_packet; bool reapply; + bool cdm_reset_before_apply; }; /** diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 890520c78e19..998a9fa77edb 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -823,6 +823,8 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( req_isp->bubble_detected = false; list_del_init(&req->list); atomic_set(&ctx_isp->process_bubble, 0); + req_isp->cdm_reset_before_apply = false; + ctx_isp->bubble_frame_cnt = 0; if (buf_done_req_id <= ctx->last_flush_req) { for (i = 0; i < req_isp->num_fence_map_out; i++) @@ -855,6 +857,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); req_isp->reapply = false; + req_isp->cdm_reset_before_apply = false; CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", @@ -1551,6 +1554,9 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + uint64_t last_cdm_done_req = 0; struct cam_isp_hw_epoch_event_data *epoch_done_event_data = (struct cam_isp_hw_epoch_event_data *)evt_data; @@ -1561,6 +1567,82 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; + if (atomic_read(&ctx_isp->process_bubble)) { + if (list_empty(&ctx->active_req_list)) { + CAM_ERR(CAM_ISP, + "No available active req in bubble"); + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->bubble_frame_cnt = 0; + rc = -EINVAL; + return rc; + } + + if (ctx_isp->last_sof_timestamp == + ctx_isp->sof_timestamp_val) { + CAM_DBG(CAM_ISP, + "Tasklet delay detected! Bubble frame check skipped, sof_timestamp: %lld", + ctx_isp->sof_timestamp_val); + goto notify_only; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + if (ctx_isp->bubble_frame_cnt >= 1 && + req_isp->bubble_detected) { + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = + CAM_ISP_HW_MGR_GET_LAST_CDM_DONE; + 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); + if (rc) { + CAM_ERR(CAM_ISP, "HW command failed"); + return rc; + } + + last_cdm_done_req = isp_hw_cmd_args.u.last_cdm_done; + CAM_DBG(CAM_ISP, "last_cdm_done req: %d", + last_cdm_done_req); + + if (last_cdm_done_req >= req->request_id) { + CAM_DBG(CAM_ISP, + "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", + req->request_id); + ctx_isp->bubble_frame_cnt = 0; + } else { + CAM_DBG(CAM_ISP, + "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", + req->request_id); + req_isp->num_acked = 0; + ctx_isp->bubble_frame_cnt = 0; + req_isp->bubble_detected = false; + req_isp->cdm_reset_before_apply = true; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->active_req_cnt--; + CAM_DBG(CAM_REQ, + "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", + req->request_id, + ctx_isp->active_req_cnt, ctx->ctx_id); + } + } else if (req_isp->bubble_detected) { + ctx_isp->bubble_frame_cnt++; + CAM_DBG(CAM_ISP, + "Waiting on bufdone for bubble req: %lld, since frame_cnt = %lld", + req->request_id, + ctx_isp->bubble_frame_cnt); + } else { + CAM_DBG(CAM_ISP, "Delayed bufdone for req: %lld", + req->request_id); + } + } + +notify_only: /* * notify reqmgr with sof signal. Note, due to scheduling delay * we can run into situation that two active requests has already @@ -1611,7 +1693,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( ctx->ctx_id); rc = -EFAULT; } - + ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val; return 0; } @@ -1776,6 +1858,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp = (struct cam_isp_ctx_req *)req->req_priv; req_isp->bubble_detected = true; req_isp->reapply = true; + req_isp->cdm_reset_before_apply = false; CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); @@ -1990,6 +2073,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( CAM_INFO_RATE_LIMIT(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; + req_isp->cdm_reset_before_apply = false; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { @@ -2914,14 +2998,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( cfg.priv = &req_isp->hw_update_data; cfg.init_packet = 0; cfg.reapply = req_isp->reapply; + cfg.cdm_reset_before_apply = req_isp->cdm_reset_before_apply; - rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, - &cfg); - if (rc) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "ctx_id:%d ,Can not apply the configuration", - ctx->ctx_id); - } else { + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); + if (!rc) { spin_lock_bh(&ctx->lock); ctx_isp->substate_activated = next_state; ctx_isp->last_applied_req_id = apply->request_id; @@ -2937,6 +3017,22 @@ static int __cam_isp_ctx_apply_req_in_activated_state( req->request_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_APPLY, req); + } else if (rc == -EALREADY) { + spin_lock_bh(&ctx->lock); + req_isp->bubble_detected = true; + req_isp->cdm_reset_before_apply = false; + atomic_set(&ctx_isp->process_bubble, 1); + list_del_init(&req->list); + list_add(&req->list, &ctx->active_req_list); + ctx_isp->active_req_cnt++; + spin_unlock_bh(&ctx->lock); + 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 { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "ctx_id:%d ,Can not apply (req %lld) the configuration, rc %d", + ctx->ctx_id, apply->request_id, rc); } end: return rc; @@ -3274,6 +3370,7 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, } } req_isp->reapply = false; + req_isp->cdm_reset_before_apply = false; list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); } @@ -3373,6 +3470,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( } end: + ctx_isp->bubble_frame_cnt = 0; atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); return rc; @@ -3638,6 +3736,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( CAM_INFO_RATE_LIMIT(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); req_isp->reapply = true; + req_isp->cdm_reset_before_apply = false; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { @@ -4251,6 +4350,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; req_isp->bubble_detected = false; + req_isp->cdm_reset_before_apply = false; req_isp->hw_update_data.packet = packet; for (i = 0; i < req_isp->num_fence_map_out; i++) { @@ -5008,6 +5108,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.hw_config.reapply = 0; + start_isp.hw_config.cdm_reset_before_apply = false; ctx_isp->last_applied_req_id = req->request_id; @@ -5021,6 +5122,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; + ctx_isp->bubble_frame_cnt = 0; ctx_isp->substate_activated = ctx_isp->rdi_only_context ? CAM_ISP_CTX_ACTIVATED_APPLIED : (req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH : @@ -5200,6 +5302,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->reported_req_id = 0; ctx_isp->last_applied_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0; + ctx_isp->bubble_frame_cnt = 0; atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -5715,6 +5818,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->use_frame_header_ts = false; ctx->active_req_cnt = 0; ctx->reported_req_id = 0; + ctx->bubble_frame_cnt = 0; ctx->req_info.last_bufdone_req_id = 0; ctx->hw_ctx = NULL; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 8ee0ff1d5273..a0c9f7bc547e 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -138,21 +138,23 @@ struct cam_isp_ctx_irq_ops { /** * struct cam_isp_ctx_req - ISP context request object * - * @base: Common request object ponter - * @cfg: ISP hardware configuration array - * @num_cfg: Number of ISP hardware configuration entries - * @fence_map_out: Output fence mapping array - * @num_fence_map_out: Number of the output fence map - * @fence_map_in: Input fence mapping array - * @num_fence_map_in: Number of input fence map - * @num_acked: Count to track acked entried for output. - * If count equals the number of fence out, it means - * the request has been completed. - * @bubble_report: Flag to track if bubble report is active on - * current request - * @hw_update_data: HW update data for this request - * @event_timestamp: Timestamp for different stage of request - * @reapply: True if reapplying after bubble + * @base: Common request object ponter + * @cfg: ISP hardware configuration array + * @num_cfg: Number of ISP hardware configuration entries + * @fence_map_out: Output fence mapping array + * @num_fence_map_out: Number of the output fence map + * @fence_map_in: Input fence mapping array + * @num_fence_map_in: Number of input fence map + * @num_acked: Count to track acked entried for output. + * If count equals the number of fence out, it means + * the request has been completed. + * @bubble_report: Flag to track if bubble report is active on + * current request + * @hw_update_data: HW update data for this request + * @event_timestamp: Timestamp for different stage of request + * @reapply: True if reapplying after bubble + * @cdm_reset_before_apply: For bubble re-apply when buf done not coming set + * to True * */ struct cam_isp_ctx_req { @@ -171,6 +173,7 @@ struct cam_isp_ctx_req { [CAM_ISP_CTX_EVENT_MAX]; bool bubble_detected; bool reapply; + bool cdm_reset_before_apply; }; /** @@ -242,6 +245,8 @@ struct cam_isp_context_event_record { * @subscribe_event: The irq event mask that CRM subscribes to, IFE * will invoke CRM cb at those event. * @last_applied_req_id: Last applied request id + * @last_sof_timestamp: SOF timestamp of the last frame + * @bubble_frame_cnt: Count of the frame after bubble * @state_monitor_head: Write index to the state monitoring array * @req_info Request id information about last buf done * @cam_isp_ctx_state_monitor: State monitoring array @@ -284,6 +289,8 @@ struct cam_isp_context { int64_t reported_req_id; uint32_t subscribe_event; int64_t last_applied_req_id; + uint64_t last_sof_timestamp; + uint32_t bubble_frame_cnt; atomic64_t state_monitor_head; struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 40f1d24701e6..38115122094f 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2831,6 +2831,7 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata, complete_all(&ctx->config_done_complete); reg_dump_done = atomic_read(&ctx->cdm_done); atomic_set(&ctx->cdm_done, 1); + ctx->last_cdm_done_req = cookie; if ((g_ife_hw_mgr.debug_cfg.per_req_reg_dump) && (!reg_dump_done)) cam_ife_mgr_handle_reg_dump(ctx, @@ -3233,6 +3234,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) if (cdm_acquire.id == CAM_CDM_IFE) ife_ctx->internal_cdm = true; atomic_set(&ife_ctx->cdm_done, 1); + ife_ctx->last_cdm_done_req = 0; acquire_args->support_consumed_addr = g_ife_hw_mgr.support_consumed_addr; @@ -3511,6 +3513,7 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->cdm_handle = cdm_acquire.handle; ife_ctx->cdm_id = cdm_acquire.id; atomic_set(&ife_ctx->cdm_done, 1); + ife_ctx->last_cdm_done_req = 0; acquire_args->ctxt_to_hw_map = ife_ctx; ife_ctx->ctx_in_use = 1; @@ -3847,6 +3850,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; unsigned long rem_jiffies = 0; + bool cdm_hang_detect = false; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, @@ -3882,6 +3886,31 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Ctx[%pK][%d] : Applying Req %lld, init_packet=%d", ctx, ctx->ctx_index, cfg->request_id, cfg->init_packet); + if (cfg->reapply && cfg->cdm_reset_before_apply) { + if (ctx->last_cdm_done_req < cfg->request_id) { + cdm_hang_detect = + cam_cdm_detect_hang_error(ctx->cdm_handle); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CDM callback not received for req: %lld, last_cdm_done_req: %lld, cdm_hang_detect: %d", + cfg->request_id, ctx->last_cdm_done_req, + cdm_hang_detect); + rc = cam_cdm_reset_hw(ctx->cdm_handle); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CDM reset unsuccessful for req: %lld. ctx: %d, rc: %d", + cfg->request_id, ctx->ctx_index, rc); + ctx->last_cdm_done_req = 0; + return rc; + } + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CDM callback received, should wait for buf done for req: %lld", + cfg->request_id); + return -EALREADY; + } + ctx->last_cdm_done_req = 0; + } + for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { @@ -4779,6 +4808,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->is_fe_enabled = false; ctx->is_offline = false; ctx->pf_mid_found = false; + ctx->last_cdm_done_req = 0; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { ctx->sof_cnt[i] = 0; @@ -7004,6 +7034,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) isp_hw_cmd_args->u.packet_op_code = CAM_ISP_PACKET_UPDATE_DEV; break; + case CAM_ISP_HW_MGR_GET_LAST_CDM_DONE: + isp_hw_cmd_args->u.last_cdm_done = + ctx->last_cdm_done_req; + break; default: CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", hw_cmd_args->cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index f7f5461124f0..a0bbf78b1941 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -85,6 +85,7 @@ struct cam_ife_hw_mgr_debug { * context * @cdm_done flag to indicate cdm has finished writing shadow * registers + * @last_cdm_done_req: Last cdm done request * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete * @reg_dump_buf_desc: cmd buffer descriptors for reg dump @@ -138,6 +139,7 @@ struct cam_ife_hw_mgr_ctx { uint32_t eof_cnt[CAM_IFE_HW_NUM_MAX]; atomic_t overflow_pending; atomic_t cdm_done; + uint64_t last_cdm_done_req; uint32_t is_rdi_only_context; struct completion config_done_complete; uint32_t hw_version; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index ebe69a1eac77..646a575d731a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1774,6 +1774,7 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, (struct cam_tfe_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx; complete_all(&ctx->config_done_complete); atomic_set(&ctx->cdm_done, 1); + ctx->last_cdm_done_req = cookie; if (g_tfe_hw_mgr.debug_cfg.per_req_reg_dump) cam_tfe_mgr_handle_reg_dump(ctx, hw_update_data->reg_dump_buf_desc, @@ -1891,6 +1892,7 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->cdm_handle = cdm_acquire.handle; tfe_ctx->cdm_ops = cdm_acquire.ops; atomic_set(&tfe_ctx->cdm_done, 1); + tfe_ctx->last_cdm_done_req = 0; acquire_hw_info = (struct cam_isp_tfe_acquire_hw_info *) acquire_args->acquire_info; @@ -2127,6 +2129,7 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->cdm_handle = cdm_acquire.handle; tfe_ctx->cdm_ops = cdm_acquire.ops; atomic_set(&tfe_ctx->cdm_done, 1); + tfe_ctx->last_cdm_done_req = 0; isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; @@ -2440,6 +2443,7 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, struct cam_cdm_bl_request *cdm_cmd; struct cam_tfe_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; + bool cdm_hang_detect = false; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -2463,6 +2467,31 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, hw_update_data = (struct cam_isp_prepare_hw_update_data *) cfg->priv; hw_update_data->isp_mgr_ctx = ctx; + if (cfg->reapply && cfg->cdm_reset_before_apply) { + if (ctx->last_cdm_done_req < cfg->request_id) { + cdm_hang_detect = + cam_cdm_detect_hang_error(ctx->cdm_handle); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CDM callback not received for req: %lld, last_cdm_done_req: %lld, cdm_hang_detect: %d", + cfg->request_id, ctx->last_cdm_done_req, + cdm_hang_detect); + rc = cam_cdm_reset_hw(ctx->cdm_handle); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CDM reset unsuccessful for req: %lld, ctx: %d, rc: %d", + cfg->request_id, ctx->ctx_index, rc); + ctx->last_cdm_done_req = 0; + return rc; + } + } else { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CDM callback received, should wait for buf done for req: %lld", + cfg->request_id); + return -EALREADY; + } + ctx->last_cdm_done_req = 0; + } + for (i = 0; i < CAM_TFE_HW_NUM_MAX; i++) { if (hw_update_data->bw_config_valid[i] == true) { @@ -3426,6 +3455,7 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, ctx->is_tpg = false; ctx->num_reg_dump_buf = 0; ctx->res_list_tpg.res_type = CAM_ISP_RESOURCE_MAX; + ctx->last_cdm_done_req = 0; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < ctx->last_submit_bl_cmd.bl_count; i++) { @@ -4718,6 +4748,10 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) isp_hw_cmd_args->u.packet_op_code = CAM_ISP_TFE_PACKET_CONFIG_DEV; break; + case CAM_ISP_HW_MGR_GET_LAST_CDM_DONE: + isp_hw_cmd_args->u.last_cdm_done = + ctx->last_cdm_done_req; + break; default: CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", hw_cmd_args->cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 6ea17d74ec19..b4b75d91103b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -70,6 +70,7 @@ struct cam_tfe_hw_mgr_debug { * context * @cdm_done flag to indicate cdm has finished writing shadow * registers + * @last_cdm_done_req: Last CDM done request * @is_rdi_only_context flag to specify the context has only rdi resource * @reg_dump_buf_desc: cmd buffer descriptors for reg dump * @num_reg_dump_buf: count of descriptors in reg_dump_buf_desc @@ -112,6 +113,7 @@ struct cam_tfe_hw_mgr_ctx { atomic_t overflow_pending; atomic_t cdm_done; + uint64_t last_cdm_done_req; uint32_t is_rdi_only_context; struct cam_cmd_buf_desc reg_dump_buf_desc[ CAM_REG_DUMP_MAX_BUF_ENTRIES]; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 681177737046..4508752dba21 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -234,6 +234,7 @@ enum cam_isp_hw_mgr_command { CAM_ISP_HW_MGR_CMD_SOF_DEBUG, CAM_ISP_HW_MGR_CMD_CTX_TYPE, CAM_ISP_HW_MGR_GET_PACKET_OPCODE, + CAM_ISP_HW_MGR_GET_LAST_CDM_DONE, CAM_ISP_HW_MGR_CMD_MAX, }; @@ -247,11 +248,12 @@ enum cam_isp_ctx_type { /** * struct cam_isp_hw_cmd_args - Payload for hw manager command * - * @cmd_type HW command type - * @cmd_data command data - * @sof_irq_enable To debug if SOF irq is enabled - * @ctx_type RDI_ONLY, PIX and RDI, or FS2 - * @packet_op_code packet opcode + * @cmd_type: HW command type + * @cmd_data: Command data + * @sof_irq_enable: To debug if SOF irq is enabled + * @ctx_type: RDI_ONLY, PIX and RDI, or FS2 + * @packet_op_code: Packet opcode + * @last_cdm_done: Last cdm done request */ struct cam_isp_hw_cmd_args { uint32_t cmd_type; @@ -260,6 +262,7 @@ struct cam_isp_hw_cmd_args { uint32_t sof_irq_enable; uint32_t ctx_type; uint32_t packet_op_code; + uint64_t last_cdm_done; } u; }; From 69fbe4cf55e5463926744e26fab3c6b2ff55bc1d Mon Sep 17 00:00:00 2001 From: chengxue Date: Fri, 16 Oct 2020 17:44:36 +0800 Subject: [PATCH 601/790] msm: camera: reqmgr: check applied req id for sync mode While links out of sync, one link faster than another. the early link reset its slot while receive trigger from isp, and the slow link will check ready always fail on sync link, and stuck happens. CRs-Fixed: 2800759 Change-Id: If615828304947d79ecbb2c87f03af29824598be0 Signed-off-by: chengxue --- drivers/cam_req_mgr/cam_req_mgr_core.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index fdbd9565ab49..2b37fc1a7e1a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -950,7 +950,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.trigger_point = trigger; CAM_DBG(CAM_REQ, - "SEND: %d link_hdl: %x pd %d req_id %lld", + "SEND: link_hdl: %x pd %d req_id %lld", link->link_hdl, pd, apply_req.request_id); if (dev->ops && dev->ops->apply_req) { rc = dev->ops->apply_req(&apply_req); @@ -1334,6 +1334,7 @@ static int __cam_req_mgr_check_sync_req_is_ready( uint64_t sof_timestamp_delta = 0; uint64_t master_slave_diff = 0; bool ready = true, sync_ready = true; + int slot_idx_diff = 0; if (!sync_link || !link) { CAM_ERR(CAM_CRM, "Sync link null"); @@ -1439,12 +1440,14 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EAGAIN; } + slot_idx_diff = (sync_slot_idx - sync_rd_idx + sync_num_slots) % + sync_num_slots; if ((sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) && - (((sync_slot_idx - sync_rd_idx + sync_num_slots) % - sync_num_slots) >= 1) && + ((slot_idx_diff > 1) || + ((slot_idx_diff == 1) && (sync_rd_slot->status != - CRM_SLOT_STATUS_REQ_APPLIED)) { + 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); From 5e697fee2a425973f110815ea55be9a91e159b58 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 9 Nov 2020 18:30:54 +0530 Subject: [PATCH 602/790] msm: camera: ife: Fix Constraint error print Fixes the null pointer dereference in the print Constraint error function. CRs-Fixed: 2815855 Change-Id: I1ce982dd271e379b0a24e094b83a52f4dfb36e37 Signed-off-by: Chandan Kumar Jha --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index a20b79676cac..afbdf3715652 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -853,17 +853,23 @@ static void cam_vfe_bus_ver3_print_constraint_errors( static void cam_vfe_bus_ver3_get_constraint_errors( struct cam_vfe_bus_ver3_priv *bus_priv) { - uint32_t i, constraint_errors; - struct cam_vfe_bus_ver3_wm_resource_data *wm_data; + uint32_t i, j, constraint_errors; + struct cam_isp_resource_node *out_rsrc_node = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *out_rsrc_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; - for (i = 0; i < bus_priv->num_client; i++) { - wm_data = bus_priv->bus_client[i].res_priv; - if (wm_data) { - constraint_errors = cam_io_r_mb( - bus_priv->common_data.mem_base + - wm_data->hw_regs->debug_status_1); - cam_vfe_bus_ver3_print_constraint_errors(i, - constraint_errors); + for (i = 0; i < bus_priv->num_out; i++) { + out_rsrc_node = &bus_priv->vfe_out[i]; + out_rsrc_data = out_rsrc_node->res_priv; + for (j = 0; j < out_rsrc_data->num_wm; j++) { + wm_data = out_rsrc_data->wm_res[j].res_priv; + if (wm_data) { + constraint_errors = cam_io_r_mb( + bus_priv->common_data.mem_base + + wm_data->hw_regs->debug_status_1); + cam_vfe_bus_ver3_print_constraint_errors(j, + constraint_errors); + } } } } From adfc0a0da2eb84b4ccb76fa899ec20cebe68bf80 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 10 Nov 2020 14:55:03 -0800 Subject: [PATCH 603/790] msm: camera: cdm: Add more registers in cdm dump Add more CDM registers in cdm dump function for better debugging. CRs-fixed: 2816605 Change-Id: I3925a094ee89e7f8f3d6ed6eead45c099ca4ac09 Signed-off-by: Jigar Agrawal --- drivers/cam_cdm/cam_cdm_hw_core.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 2539bcd51a75..85721865f81e 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -354,7 +354,24 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_inv_data, &dump_reg); - CAM_INFO(CAM_CDM, "Last Inv cmd: 0x%x", dump_reg); + CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x", + dump_reg); + + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_last_data_0, + &dump_reg); + CAM_INFO(CAM_CDM, "First word of Last Good cmd: 0x%x", + dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_last_data_1, + &dump_reg); + CAM_INFO(CAM_CDM, "Second word of Last Good cmd: 0x%x", + dump_reg); + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_last_data_2, + &dump_reg); + CAM_INFO(CAM_CDM, "Third word of Last Good cmd: 0x%x", + dump_reg); } } From 6886644fec2abd0139c94f7e7b61d0242638f2fd Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 5 Nov 2020 17:48:19 +0530 Subject: [PATCH 604/790] msm: camera: cpas: Update jpeg qosgen settings Use OT limit as 10 for jpeg niu path. This help in controlling jpeg bw flow and to avoid any backpressure on IFE paths. CRs-Fixed: 2802862 Change-Id: Iaaf9ef2a9ab6182aa7da1a160676a6e918454278 Signed-off-by: Alok Chauhan --- drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index 02dcfc1468a3..02410cc00876 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -802,14 +802,14 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ - .value = 0x05050505, + .value = 0xA0A0A0A, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ - .value = 0x05050505, + .value = 0xA0A0A0A, }, }, { From 4c4ed69a5c08783c2c7eed1ac1b6277f833db2fa Mon Sep 17 00:00:00 2001 From: Pavan Kumar Chilamkurthi Date: Thu, 5 Nov 2020 14:59:03 -0800 Subject: [PATCH 605/790] msm: camera: isp: Handle buf_done without request in active_list In cases where we see a buf done without request being in active_list, there could be a possibility that the request is applied just before SOF, RUP but the context state is not moved to Applied state, at this time the request is in wait_list. In such cases RUP event doesn't move the request into active_list. Also if the BUF_DONE on a port is happening before EPOCH, we simply drop that BUF_DONE and then the request will eventually be tagged as BUBBLE at the time of EPOCH. But since BUF_DONE is dropped, the request will never come out of BUBBLE. To handle such cases and to come out of BUBBLE, check if BUF_DONE matches with the request in wait_list by checking last_consumed address and if so, mark it as deferred buf_done and handle once the request is moved to active_list. CRs-Fixed: 2814346 Change-Id: I778a6a684076d5327d536f319a23206ccc0c25b6 Signed-off-by: Pavan Kumar Chilamkurthi --- drivers/cam_isp/cam_isp_context.c | 161 ++++++++++++++++++++++++++++-- drivers/cam_isp/cam_isp_context.h | 11 ++ 2 files changed, 164 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 3734e0e0364b..a23cffa52eb8 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -819,6 +819,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( if (req_isp->bubble_detected && req_isp->bubble_report) { req_isp->num_acked = 0; + req_isp->num_deferred_acks = 0; req_isp->bubble_detected = false; list_del_init(&req->list); atomic_set(&ctx_isp->process_bubble, 0); @@ -1019,12 +1020,75 @@ static int __cam_isp_ctx_handle_buf_done_for_request( return rc; } +static int __cam_isp_handle_deferred_buf_done( + struct cam_isp_context *ctx_isp, + struct cam_ctx_request *req, + bool bubble_handling, + uint32_t status, uint32_t event_cause) +{ + int i, j; + int rc = 0; + struct cam_isp_ctx_req *req_isp = + (struct cam_isp_ctx_req *) req->req_priv; + struct cam_context *ctx = ctx_isp->base; + + CAM_DBG(CAM_ISP, + "ctx[%d] : Req %llu : Handling %d deferred buf_dones num_acked=%d, bubble_handling=%d", + ctx->ctx_id, req->request_id, req_isp->num_deferred_acks, + req_isp->num_acked, bubble_handling); + + for (i = 0; i < req_isp->num_deferred_acks; i++) { + j = req_isp->deferred_fence_map_index[i]; + + CAM_DBG(CAM_ISP, + "ctx[%d] : Sync with status=%d, event_cause=%d: req %lld res 0x%x sync_id 0x%x", + ctx->ctx_id, status, event_cause, + req->request_id, + req_isp->fence_map_out[j].resource_handle, + req_isp->fence_map_out[j].sync_id); + + if (req_isp->fence_map_out[j].sync_id == -1) { + CAM_WARN(CAM_ISP, + "ctx[%d Deferred buf_done already signalled, req_id=%llu, j=%d, res=0x%x", + ctx->ctx_id, req->request_id, j, + req_isp->fence_map_out[j].resource_handle); + continue; + } + + if (!bubble_handling) { + CAM_WARN(CAM_ISP, + "ctx[%d] : Req %llu, status=%d res=0x%x should never happen", + ctx->ctx_id, req->request_id, status, + req_isp->fence_map_out[j].resource_handle); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + status, event_cause); + if (rc) { + CAM_ERR(CAM_ISP, + "ctx[%d] : Sync signal for Req %llu, sync_id %d status=%d failed with rc = %d", + ctx->ctx_id, req->request_id, + req_isp->fence_map_out[j].sync_id, + status, rc); + } else { + req_isp->num_acked++; + req_isp->fence_map_out[j].sync_id = -1; + } + } else { + req_isp->num_acked++; + } + } + + req_isp->num_deferred_acks = 0; + + return rc; +} static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( struct cam_isp_context *ctx_isp, struct cam_ctx_request *req, struct cam_isp_hw_done_event_data *done, uint32_t bubble_state, - bool verify_consumed_addr) + bool verify_consumed_addr, + bool defer_buf_done) { int rc = 0; int i, j; @@ -1085,7 +1149,32 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( continue; } - if (!req_isp->bubble_detected) { + if (defer_buf_done) { + uint32_t deferred_indx = req_isp->num_deferred_acks; + + /* + * If we are handling this BUF_DONE event for a request + * that is still in wait_list, do not signal now, + * instead mark it as done and handle it later - + * if this request is going into BUBBLE state later + * it will automatically be re-applied. If this is not + * going into BUBBLE, signal fences later. + * Note - we will come here only if the last consumed + * address matches with this ports buffer. + */ + req_isp->deferred_fence_map_index[deferred_indx] = j; + req_isp->num_deferred_acks++; + CAM_WARN(CAM_ISP, + "ctx[%d] : Deferred buf done for %llu with bubble state %d recovery %d", + ctx->ctx_id, req->request_id, bubble_state, + req_isp->bubble_report); + CAM_WARN(CAM_ISP, + "ctx[%d] : Deferred info : num_acks=%d, fence_map_index=%d, resource_handle=0x%x, sync_id=%d", + ctx->ctx_id, req_isp->num_deferred_acks, j, + req_isp->fence_map_out[j].resource_handle, + req_isp->fence_map_out[j].sync_id); + continue; + } else if (!req_isp->bubble_detected) { CAM_DBG(CAM_ISP, "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u", req->request_id, @@ -1096,9 +1185,16 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, CAM_SYNC_COMMON_EVENT_SUCCESS); - if (rc) + if (rc) { CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc); + } else if (req_isp->num_deferred_acks) { + /* Process deferred buf_done acks */ + __cam_isp_handle_deferred_buf_done(ctx_isp, + req, false, + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_COMMON_EVENT_SUCCESS); + } } else if (!req_isp->bubble_report) { CAM_DBG(CAM_ISP, "Sync with failure: req %lld res 0x%x fd 0x%x, ctx %u", @@ -1110,9 +1206,16 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, CAM_SYNC_ISP_EVENT_BUBBLE); - if (rc) + if (rc) { CAM_ERR(CAM_ISP, "Sync failed with rc = %d", rc); + } else if (req_isp->num_deferred_acks) { + /* Process deferred buf_done acks */ + __cam_isp_handle_deferred_buf_done(ctx_isp, req, + false, + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); + } } else { /* * Ignore the buffer done if bubble detect is on @@ -1124,6 +1227,14 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( CAM_DBG(CAM_ISP, "buf done with bubble state %d recovery %d", bubble_state, req_isp->bubble_report); + /* Process deferred buf_done acks */ + + if (req_isp->num_deferred_acks) + __cam_isp_handle_deferred_buf_done(ctx_isp, req, + true, + CAM_SYNC_STATE_SIGNALED_ERROR, + CAM_SYNC_ISP_EVENT_BUBBLE); + continue; } @@ -1171,7 +1282,7 @@ static int __cam_isp_ctx_handle_buf_done( struct cam_isp_hw_done_event_data done_next_req; if (list_empty(&ctx->active_req_list)) { - CAM_DBG(CAM_ISP, "Buf done with no active request"); + CAM_WARN(CAM_ISP, "Buf done with no active request"); return 0; } @@ -1271,7 +1382,31 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( struct cam_context *ctx = ctx_isp->base; if (list_empty(&ctx->active_req_list)) { - CAM_DBG(CAM_ISP, "Buf done with no active request"); + CAM_WARN(CAM_ISP, + "Buf done with no active request bubble_state=%d", + bubble_state); + + if (!list_empty(&ctx->wait_req_list)) { + struct cam_isp_ctx_req *req_isp; + + req = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + CAM_WARN(CAM_ISP, + "Buf done with no active request but with req in wait list, req %llu", + req->request_id); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + /* + * Verify consumed address for this request to make sure + * we are handling the buf_done for the correct + * buffer. Also defer actual buf_done handling, i.e + * do not signal the fence as this request may go into + * Bubble state eventully. + */ + rc = + __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + ctx_isp, req, done, bubble_state, true, true); + } return 0; } @@ -1299,7 +1434,7 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( */ rc = __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx_isp, req, done, bubble_state, - !irq_delay_detected); + !irq_delay_detected, false); /* * Verify the consumed address for next req all the time, @@ -1309,7 +1444,7 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( if (!rc && irq_delay_detected) rc = __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx_isp, next_req, done, - bubble_state, true); + bubble_state, true, false); return rc; } @@ -1392,6 +1527,7 @@ static int __cam_isp_ctx_apply_req_offline( ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_APPLIED; prev_applied_req = ctx_isp->last_applied_req_id; ctx_isp->last_applied_req_id = req->request_id; + atomic_set(&ctx_isp->apply_in_progress, 1); list_del_init(&req->list); list_add_tail(&req->list, &ctx->wait_req_list); @@ -1405,12 +1541,14 @@ static int __cam_isp_ctx_apply_req_offline( ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; ctx_isp->last_applied_req_id = prev_applied_req; + atomic_set(&ctx_isp->apply_in_progress, 0); list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); spin_unlock_bh(&ctx->lock); } else { + atomic_set(&ctx_isp->apply_in_progress, 0); CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld", CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp->last_applied_req_id); @@ -1975,6 +2113,9 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, return -EINVAL; } + if (atomic_read(&ctx_isp->apply_in_progress)) + CAM_INFO(CAM_ISP, "Apply is in progress at the time of SOF"); + ctx_isp->frame_id++; ctx_isp->sof_timestamp_val = sof_event_data->timestamp; ctx_isp->boot_timestamp = sof_event_data->boot_time; @@ -3000,6 +3141,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state( cfg.reapply = req_isp->reapply; cfg.cdm_reset_before_apply = req_isp->cdm_reset_before_apply; + atomic_set(&ctx_isp->apply_in_progress, 1); + rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg); if (!rc) { spin_lock_bh(&ctx->lock); @@ -3034,6 +3177,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state( "ctx_id:%d ,Can not apply (req %lld) the configuration, rc %d", ctx->ctx_id, apply->request_id, rc); } + atomic_set(&ctx_isp->apply_in_progress, 0); end: return rc; } @@ -4349,6 +4493,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req_isp->num_fence_map_out = cfg.num_out_map_entries; req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; + req_isp->num_deferred_acks = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = false; req_isp->hw_update_data.packet = packet; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index a0c9f7bc547e..7f97929261bf 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -148,6 +148,13 @@ struct cam_isp_ctx_irq_ops { * @num_acked: Count to track acked entried for output. * If count equals the number of fence out, it means * the request has been completed. + * @num_deferred_acks: Number of buf_dones/acks that are deferred to + * handle or signalled in special scenarios. + * Increment this count instead of num_acked and + * handle the events later where eventually + * increment num_acked. + * @deferred_fence_map_index Saves the indices of fence_map_out for which + * handling of buf_done is deferred. * @bubble_report: Flag to track if bubble report is active on * current request * @hw_update_data: HW update data for this request @@ -167,6 +174,8 @@ struct cam_isp_ctx_req { struct cam_hw_fence_map_entry fence_map_in[CAM_ISP_CTX_RES_MAX]; uint32_t num_fence_map_in; uint32_t num_acked; + uint32_t num_deferred_acks; + uint32_t deferred_fence_map_index[CAM_ISP_CTX_RES_MAX]; int32_t bubble_report; struct cam_isp_prepare_hw_update_data hw_update_data; ktime_t event_timestamp @@ -261,6 +270,7 @@ struct cam_isp_context_event_record { * @custom_enabled: Custom HW enabled for this ctx * @use_frame_header_ts: Use frame header for qtimer ts * @support_consumed_addr: Indicate whether HW has last consumed addr reg + * @apply_in_progress Whether request apply is in progress * @init_timestamp: Timestamp at which this context is initialized * @isp_device_type: ISP device type * @rxd_epoch: Indicate whether epoch has been received. Used to @@ -307,6 +317,7 @@ struct cam_isp_context { bool custom_enabled; bool use_frame_header_ts; bool support_consumed_addr; + atomic_t apply_in_progress; unsigned int init_timestamp; uint32_t isp_device_type; atomic_t rxd_epoch; From 99eaacc2c2cf2cbdb63843df24cf45651e80262e Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Sat, 31 Oct 2020 00:04:25 +0530 Subject: [PATCH 606/790] msm: camera: utils: Rate limit error log in case of invalid handles Rate limit errors logs in case of incoming invalid handles from userspace. CRs-Fixed: 2807712 Change-Id: I3f8765be2f07f869149b9315ab38b7d02ae71a58 Signed-off-by: Shravya Samala --- drivers/cam_core/cam_context_utils.c | 4 ++-- drivers/cam_core/cam_node.c | 27 +++++++++++++++++--------- drivers/cam_req_mgr/cam_req_mgr_util.c | 18 +++++++++-------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index dee6d1708fbd..10613a326590 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -535,8 +535,8 @@ int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx, cmd->resource_hdl); if (cmd->num_resources > CAM_CTX_RES_MAX) { - CAM_ERR(CAM_CTXT, "[%s][%d] resource limit exceeded", - ctx->dev_name, ctx->ctx_id); + CAM_ERR(CAM_CTXT, "[%s][%d] resource[%d] limit exceeded", + ctx->dev_name, ctx->ctx_id, cmd->num_resources); rc = -ENOMEM; goto end; } diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 75ec613e7112..c3770f2df745 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -346,31 +346,36 @@ static int __cam_node_handle_flush_dev(struct cam_node *node, return -EINVAL; if (flush->dev_handle <= 0) { - CAM_ERR(CAM_CORE, "Invalid device handle for context"); + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Invalid device handle for context"); return -EINVAL; } if (flush->session_handle <= 0) { - CAM_ERR(CAM_CORE, "Invalid session handle for context"); + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Invalid session handle for context"); return -EINVAL; } ctx = (struct cam_context *)cam_get_device_priv(flush->dev_handle); if (!ctx) { - CAM_ERR(CAM_CORE, "Can not get context for handle %d", + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Can not get context for handle %d", flush->dev_handle); return -EINVAL; } if (strcmp(node->name, ctx->dev_name)) { - CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching", + CAM_ERR_RATE_LIMIT(CAM_CORE, + "node name %s dev name:%s not matching", node->name, ctx->dev_name); return -EINVAL; } rc = cam_context_handle_flush_dev(ctx, flush); if (rc) - CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name); + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Flush failure for node %s", node->name); return rc; } @@ -446,25 +451,29 @@ static int __cam_node_handle_dump_dev(struct cam_node *node, return -EINVAL; if (dump->dev_handle <= 0) { - CAM_ERR(CAM_CORE, "Invalid device handle for context"); + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Invalid device handle for context"); return -EINVAL; } if (dump->session_handle <= 0) { - CAM_ERR(CAM_CORE, "Invalid session handle for context"); + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Invalid session handle for context"); return -EINVAL; } ctx = (struct cam_context *)cam_get_device_priv(dump->dev_handle); if (!ctx) { - CAM_ERR(CAM_CORE, "Can not get context for handle %d", + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Can not get context for handle %d", dump->dev_handle); return -EINVAL; } rc = cam_context_handle_dump_dev(ctx, dump); if (rc) - CAM_ERR(CAM_CORE, "Dump failure for node %s", node->name); + CAM_ERR_RATE_LIMIT(CAM_CORE, + "Dump failure for node %s", node->name); return rc; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index df180a615104..4b1f4d8e8622 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -223,23 +223,25 @@ void *cam_get_device_priv(int32_t dev_hdl) idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx"); + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx:%d", idx); + goto device_priv_fail; + } + + if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) { + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid hdl [%d] [%d]", + dev_hdl, hdl_tbl->hdl[idx].hdl_value); goto device_priv_fail; } if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) { - CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid state"); + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid state:%d", + hdl_tbl->hdl[idx].state); goto device_priv_fail; } type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl); if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) { - CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid type"); - goto device_priv_fail; - } - - if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) { - CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid hdl"); + CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid type:%d", type); goto device_priv_fail; } From 60a0d836da97b9e55de95801019933b650a2a72d Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Thu, 8 Oct 2020 11:36:38 +0530 Subject: [PATCH 607/790] msm: camera: csiphy: CSIPHY DPHY DeSkew Calibration - Disable skew calibration by default for CSIPHY. - When last bits of data are 0, Sensor flips data to static 1 in HS-Trail. This creates a false calibration header in HS-Trail period depending on last bits of data. CRs-Fixed: 2777521 Change-Id: I285f74652cc3c8b74e280e7edfb92eb4661d2692 Signed-off-by: shiwgupt --- .../include/cam_csiphy_1_2_3_hwreg.h | 32 +------------------ .../include/cam_csiphy_1_2_5_hwreg.h | 20 +----------- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 8614ed1c8d0e..02d34d64b89d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -15,7 +15,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 19, + .csiphy_2ph_config_array_size = 16, .csiphy_3ph_config_array_size = 26, .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, @@ -72,9 +72,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x005C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0060, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -93,9 +90,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x075C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0760, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0764, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -114,9 +108,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x025C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0260, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0264, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -135,9 +126,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x045C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0460, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -156,9 +144,6 @@ struct csiphy_reg_t csiphy_2ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x065C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0660, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0664, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -181,9 +166,6 @@ struct csiphy_reg_t {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x005C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0060, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -202,9 +184,6 @@ struct csiphy_reg_t {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x075C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0760, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0764, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -223,9 +202,6 @@ struct csiphy_reg_t {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x025C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0260, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0264, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -244,9 +220,6 @@ struct csiphy_reg_t {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x045C, 0xC0, 0x00, CSIPHY_SKEW_CAL}, - {0x0460, 0x0D, 0x00, CSIPHY_SKEW_CAL}, - {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -265,9 +238,6 @@ struct csiphy_reg_t {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x065C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0660, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x0664, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h index 0a680857b048..d472aa5e48e3 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h @@ -15,7 +15,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_5 = { .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 6, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 23, + .csiphy_2ph_config_array_size = 21, .csiphy_3ph_config_array_size = 30, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -74,8 +74,6 @@ csiphy_reg_t csiphy_2ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, @@ -124,8 +122,6 @@ csiphy_reg_t csiphy_2ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, @@ -149,8 +145,6 @@ csiphy_reg_t csiphy_2ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, @@ -174,8 +168,6 @@ csiphy_reg_t csiphy_2ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, @@ -202,8 +194,6 @@ struct csiphy_reg_t {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x005C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0060, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -229,8 +219,6 @@ struct csiphy_reg_t {0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x075C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0760, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { @@ -252,8 +240,6 @@ struct csiphy_reg_t {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x025C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0260, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -278,8 +264,6 @@ struct csiphy_reg_t {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x045C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0460, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x00, 0x00, CSIPHY_DNP_PARAMS}, }, @@ -304,8 +288,6 @@ struct csiphy_reg_t {0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x065C, 0xC0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0660, 0x0D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; From e9fb6cfda64a3e620c7df7bd3b8a48ce735caf5b Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 12 Nov 2020 15:32:11 +0530 Subject: [PATCH 608/790] msm: camera: reqmgr: Add checks before reporting the error Add the null check for dev parameter before reporting the error on link. Certain corner scenario for flash, send request return native value in that case dev parameter could be null. CRs-Fixed: 2814597 Change-Id: Ibe08f12c2f2c1864c46b17b0ae0f8df5c5648d35 Signed-off-by: Ravikishore Pampana --- drivers/cam_req_mgr/cam_req_mgr_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index fdbd9565ab49..8a904c025af6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1632,7 +1632,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_slot *slot = NULL; struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_core_session *session; - struct cam_req_mgr_connected_device *dev; + struct cam_req_mgr_connected_device *dev = NULL; struct cam_req_mgr_core_link *tmp_link = NULL; uint32_t max_retry = 0; @@ -1758,7 +1758,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->max_delay == 1) max_retry++; - if (!link->wq_congestion) { + if (!link->wq_congestion && dev) { link->retry_cnt++; if (link->retry_cnt == max_retry) { CAM_DBG(CAM_CRM, From b3673cb6b933658ee450d640b29b9aef800fa23c Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 5 Nov 2020 14:17:56 +0530 Subject: [PATCH 609/790] msm: camera: reqmgr: update timer even after skip frame If Nth request has additional exposure timeout, after applying sensor settings for Nth request; CRM watchdog timer should be updated with the Nth requests additional timeout on next frame irrespective of skip frame to avoid sof freeze. CRs-Fixed: 2802634 Change-Id: Iae70df66f0a1c22c2410e4826aea964ffd6d887b Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_req_mgr_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index fdbd9565ab49..9a300ca8479d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1746,6 +1746,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } spin_unlock_bh(&link->link_state_spin_lock); __cam_req_mgr_notify_frame_skip(link, trigger); + __cam_req_mgr_validate_crm_wd_timer(link); goto end; } } @@ -3324,6 +3325,10 @@ static int cam_req_mgr_cb_notify_trigger( CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task frame %lld", trigger_data->frame_id); rc = -EBUSY; + spin_lock_bh(&link->link_state_spin_lock); + if ((link->watchdog) && !(link->watchdog->pause_timer)) + link->watchdog->pause_timer = true; + spin_unlock_bh(&link->link_state_spin_lock); goto end; } task_data = (struct crm_task_payload *)task->payload; From ddfe75dc7a0b77b70bb40e2421adbfabbfc1ebe8 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 11 Nov 2020 14:58:16 -0800 Subject: [PATCH 610/790] msm: camera: icp: Check HW state prior to IRQ processing Check ICP HW state before processing any IRQ to avoid any unclocked access. CRs-Fixed: 2816854 Change-Id: I31fc03f655b1068f5d171385891eba7d281bd4fd Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 3c7cccd2b132..3e4c6f8d9d69 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -297,6 +297,7 @@ int cam_a5_init_hw(void *device_priv, struct cam_a5_device_core_info *core_info = NULL; struct a5_soc_info *a5_soc_info; struct cam_icp_cpas_vote cpas_vote; + unsigned long flags; int rc = 0; if (!device_priv) { @@ -356,6 +357,10 @@ int cam_a5_init_hw(void *device_priv, ICP_SIERRA_A5_CSR_ACCESS); } + spin_lock_irqsave(&a5_dev->hw_lock, flags); + a5_dev->hw_state = CAM_HW_STATE_POWER_UP; + spin_unlock_irqrestore(&a5_dev->hw_lock, flags); + error: return rc; } @@ -366,6 +371,7 @@ int cam_a5_deinit_hw(void *device_priv, struct cam_hw_info *a5_dev = device_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_a5_device_core_info *core_info = NULL; + unsigned long flags; int rc = 0; if (!device_priv) { @@ -381,6 +387,10 @@ int cam_a5_deinit_hw(void *device_priv, return -EINVAL; } + spin_lock_irqsave(&a5_dev->hw_lock, flags); + a5_dev->hw_state = CAM_HW_STATE_POWER_DOWN; + spin_unlock_irqrestore(&a5_dev->hw_lock, flags); + rc = cam_a5_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc); @@ -462,6 +472,14 @@ irqreturn_t cam_a5_irq(int irq_num, void *data) return IRQ_HANDLED; } + spin_lock(&a5_dev->hw_lock); + if (a5_dev->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_WARN(CAM_ICP, "ICP HW powered off"); + spin_unlock(&a5_dev->hw_lock); + return IRQ_HANDLED; + } + spin_unlock(&a5_dev->hw_lock); + soc_info = &a5_dev->soc_info; core_info = (struct cam_a5_device_core_info *)a5_dev->core_info; hw_info = core_info->a5_hw_info; From b1c38c6f5a3e6868d6e6c371191086726c7f4fdd Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 11 Nov 2020 09:59:40 -0800 Subject: [PATCH 611/790] msm: camera: reqmgr: Rate limit workq delay warning Rate limit log that indicates workq delay to reduce logging impact. CRs-Fixed: 2823945 Change-Id: I5954d5d08250955455003937e6490e4499a67378 Signed-off-by: Karthik Anantha Ram --- drivers/cam_req_mgr/cam_req_mgr_workq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.c b/drivers/cam_req_mgr/cam_req_mgr_workq.c index aaac21028589..c2ed7f0d2c00 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.c +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.c @@ -281,7 +281,7 @@ void cam_req_mgr_thread_switch_delay_detect(ktime_t workq_scheduled) cur_ts = ktime_to_timespec64(cur_time); if (diff > CAM_WORKQ_RESPONSE_TIME_THRESHOLD) { - CAM_WARN(CAM_CRM, + CAM_WARN_RATE_LIMIT(CAM_CRM, "Workq delay detected %ld:%06ld %ld:%06ld %ld:", workq_scheduled_ts.tv_sec, workq_scheduled_ts.tv_nsec/NSEC_PER_USEC, From 6bbdcb3f6d0f737c6318426cc07924de033dc0ef Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Tue, 17 Nov 2020 15:01:50 -0800 Subject: [PATCH 612/790] msm: camera: sensor: Reset actuator flush requestId When camera module shut down happens reset the last flush request ID for the new session to continue as fresh start. CRs-Fixed: 2822543 Change-Id: Ic5b43d7acaeb7e7b6999c02cbb4654598469638b Signed-off-by: Sureshnaidu Laveti --- drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 47a261808873..aa761a729c07 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -801,6 +801,7 @@ void cam_actuator_shutdown(struct cam_actuator_ctrl_t *a_ctrl) power_info->power_down_setting = NULL; power_info->power_setting_size = 0; power_info->power_down_setting_size = 0; + a_ctrl->last_flush_req = 0; a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; } From c861a8d97aba8b7286413544723a6f5996f0bc66 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Fri, 20 Nov 2020 19:24:05 +0530 Subject: [PATCH 613/790] msm: camera: isp: Fix for NULL dereference for failure case of dual IFE In the case of dual IFE acquire if left CSID reserve fails there is a possibility of NULL pointer dereference. CRs-Fixed: 2823225 Change-Id: Ib2bef582f69b245ee1d5b5b9ee8f5dacf8e2607a Signed-off-by: Wyes Karny --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 60e21abf0788..bff0a89cd560 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1909,7 +1909,7 @@ acquire_successful: break; } - if (j == CAM_IFE_CSID_HW_NUM_MAX) { + if (j == -1 || !csid_acquire.node_res) { CAM_ERR(CAM_ISP, "Can not acquire ife csid dual resource"); goto end; From f7ef5c55116cb2b24ec2c7480ae62658e936f2d9 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 20 Nov 2020 20:53:19 +0530 Subject: [PATCH 614/790] msm: camera: isp: Add null check for vfe out res data Change-Id: I72d8e51257fcfeca8386e626cf04db448bf3b483 Signed-off-by: Ayush Kumar --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 40bf7427546b..b595c5fec315 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -862,6 +862,12 @@ static void cam_vfe_bus_ver3_get_constraint_errors( for (i = 0; i < bus_priv->num_out; i++) { out_rsrc_node = &bus_priv->vfe_out[i]; + if (!out_rsrc_node || !out_rsrc_node->res_priv) { + CAM_INFO(CAM_ISP, + "wm :%d out rsrc node or data is NULL (%p)", + i, out_rsrc_node); + continue; + } out_rsrc_data = out_rsrc_node->res_priv; for (j = 0; j < out_rsrc_data->num_wm; j++) { wm_data = out_rsrc_data->wm_res[j].res_priv; From a4c423f6f88bfb0d1bfdcbb03a2baa1d9f89eaaa Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Fri, 20 Nov 2020 19:24:05 +0530 Subject: [PATCH 615/790] msm: camera: isp: Fix for NULL dereference for failure case of dual IFE In the case of dual IFE acquire if left CSID reserve fails there is a possibility of NULL pointer dereference. CRs-Fixed: 2823225 Change-Id: Ib2bef582f69b245ee1d5b5b9ee8f5dacf8e2607a Signed-off-by: Wyes Karny --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 60e21abf0788..bff0a89cd560 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1909,7 +1909,7 @@ acquire_successful: break; } - if (j == CAM_IFE_CSID_HW_NUM_MAX) { + if (j == -1 || !csid_acquire.node_res) { CAM_ERR(CAM_ISP, "Can not acquire ife csid dual resource"); goto end; From 3a8069737e1ddeb95103eb4ff0364dd2385131a7 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Sun, 22 Nov 2020 18:17:12 +0530 Subject: [PATCH 616/790] msm: camera: reqmgr: reduce bufdone error logs If buf done error come for same applied request id then log only once. Change the bufdone deferred logs to debug logs. Change-Id: I870708bfb0c4f0ad0a1fade3a7e334551d055c73 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/cam_isp_context.c | 34 +++++++++++++++++++++++-------- drivers/cam_isp/cam_isp_context.h | 2 ++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index a23cffa52eb8..8f6abd21af32 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -838,6 +838,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + ctx_isp->last_bufdone_error_apply_req_id = 0; } else { list_add(&req->list, &ctx->pending_req_list); CAM_DBG(CAM_REQ, @@ -863,6 +864,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); ctx_isp->req_info.last_bufdone_req_id = req->request_id; + ctx_isp->last_bufdone_error_apply_req_id = 0; } __cam_isp_ctx_update_state_monitor_array(ctx_isp, @@ -1164,11 +1166,11 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( */ req_isp->deferred_fence_map_index[deferred_indx] = j; req_isp->num_deferred_acks++; - CAM_WARN(CAM_ISP, + CAM_DBG(CAM_ISP, "ctx[%d] : Deferred buf done for %llu with bubble state %d recovery %d", ctx->ctx_id, req->request_id, bubble_state, req_isp->bubble_report); - CAM_WARN(CAM_ISP, + CAM_DBG(CAM_ISP, "ctx[%d] : Deferred info : num_acks=%d, fence_map_index=%d, resource_handle=0x%x, sync_id=%d", ctx->ctx_id, req_isp->num_deferred_acks, j, req_isp->fence_map_out[j].resource_handle, @@ -1380,20 +1382,27 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( struct cam_ctx_request *req; struct cam_ctx_request *next_req = NULL; struct cam_context *ctx = ctx_isp->base; + bool req_in_wait_list = false; if (list_empty(&ctx->active_req_list)) { - CAM_WARN(CAM_ISP, - "Buf done with no active request bubble_state=%d", - bubble_state); if (!list_empty(&ctx->wait_req_list)) { struct cam_isp_ctx_req *req_isp; req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); - CAM_WARN(CAM_ISP, - "Buf done with no active request but with req in wait list, req %llu", - req->request_id); + + req_in_wait_list = true; + if (ctx_isp->last_applied_req_id != + ctx_isp->last_bufdone_error_apply_req_id) { + CAM_WARN(CAM_ISP, + "Buf done with no active request but with req in wait list, req %llu last apply id:%lld", + req->request_id, + ctx_isp->last_applied_req_id); + ctx_isp->last_bufdone_error_apply_req_id = + ctx_isp->last_applied_req_id; + } + req_isp = (struct cam_isp_ctx_req *) req->req_priv; /* @@ -1407,6 +1416,15 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx_isp, req, done, bubble_state, true, true); } + + if (!req_in_wait_list && (ctx_isp->last_applied_req_id != + ctx_isp->last_bufdone_error_apply_req_id)) { + CAM_WARN(CAM_ISP, + "Buf done with no active request bubble_state=%d last_applied_req_id:%lld ", + bubble_state, ctx_isp->last_applied_req_id); + ctx_isp->last_bufdone_error_apply_req_id = + ctx_isp->last_applied_req_id; + } return 0; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 7f97929261bf..b02977cf1121 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -277,6 +277,7 @@ struct cam_isp_context_event_record { * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife * @trigger_id: ID provided by CRM for each ctx on the link + * @last_bufdone_error_apply_req_id: last bufdone error apply request id * */ struct cam_isp_context { @@ -323,6 +324,7 @@ struct cam_isp_context { atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; int32_t trigger_id; + int64_t last_bufdone_error_apply_req_id; }; /** From b9e826686f07d25c128e0a61c9516b36cba8b0ae Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 19 Nov 2020 18:01:04 -0800 Subject: [PATCH 617/790] msm: camera: isp: Choose appropriate WM for frame header Frame header is not enabled on all WMs. Currently frame header is piggy backed with the first WM for which buffer is configured. It is possible that this WM does not support frame header. This change tries with all WMs till it finds a WM that supports frame header. CRs-Fixed: 2823154 Change-Id: I300cb449cdeebc74300d100dfdd8dbe50bec9bce Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 9 ++++++ .../hw_utils/cam_isp_packet_parser.c | 17 +++++++---- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 ++ .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 15 ---------- .../isp_hw/vfe_hw/vfe17x/cam_vfe680.h | 15 ---------- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 29 ++++++++++--------- 6 files changed, 37 insertions(+), 50 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index bff0a89cd560..ea98fad2205a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6485,6 +6485,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, return rc; frame_header_enable = true; + prepare_hw_data->frame_header_res_id = 0x0; } if (ctx->internal_cdm) @@ -6590,6 +6591,14 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, } } + /* Check if frame header was enabled for any WM */ + if ((ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) && + (prepare->num_out_map_entries) && + (!prepare_hw_data->frame_header_res_id)) { + CAM_ERR(CAM_ISP, "Failed to configure frame header"); + goto end; + } + /* * reg update will be done later for the initial configure. * need to plus one to the op_code and only take the lower diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index fe6b43330b30..4147efe58af0 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -700,6 +700,7 @@ int cam_isp_add_io_buffers( wm_update.num_buf = plane_id; wm_update.io_cfg = &io_cfg[i]; wm_update.frame_header = 0; + wm_update.fh_enabled = false; for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; plane_id++) @@ -709,14 +710,8 @@ int cam_isp_add_io_buffers( if ((frame_header_info->frame_header_enable) && !(frame_header_info->frame_header_res_id)) { wm_update.frame_header = iova_addr; - frame_header_info->frame_header_res_id = - res->res_id; wm_update.local_id = prepare->packet->header.request_id; - CAM_DBG(CAM_ISP, - "Frame header enabled for res: 0x%x iova: %pK", - frame_header_info->frame_header_res_id, - wm_update.frame_header); } update_buf.cmd.size = kmd_buf_remain_size; @@ -736,6 +731,16 @@ int cam_isp_add_io_buffers( rc = -ENOMEM; return rc; } + + if (wm_update.fh_enabled) { + frame_header_info->frame_header_res_id = + res->res_id; + CAM_DBG(CAM_ISP, + "Frame header enabled for res: 0x%x iova: %pK", + frame_header_info->frame_header_res_id, + wm_update.frame_header); + } + io_cfg_used_bytes += update_buf.cmd.used_bytes; if (!out_map_entries) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 2e5be6f75d5a..21c0e0e27a90 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -249,6 +249,7 @@ struct cam_isp_hw_cmd_buf_update { * @ image_buf_offset: image buffer address offset array * @ num_buf: Number of buffers in the image_buf array * @ frame_header: frame header iova + * @ fh_enabled: flag to indicate if this WM enables frame header * @ local_id: local id for the wm * @ width: width of scratch buffer * @ height: height of scratch buffer @@ -262,6 +263,7 @@ struct cam_isp_hw_get_wm_update { uint32_t image_buf_offset[CAM_PACKET_MAX_PLANES]; uint32_t num_buf; uint64_t frame_header; + bool fh_enabled; uint32_t local_id; uint32_t width; uint32_t height; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index b70ad12bb26a..d12ed2904f3e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -481,9 +481,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .image_cfg_1 = 0x0000AE10, .image_cfg_2 = 0x0000AE14, .packer_cfg = 0x0000AE18, - .frame_header_addr = 0x0000AE20, - .frame_header_incr = 0x0000AE24, - .frame_header_cfg = 0x0000AE28, .line_done_cfg = 0, .irq_subsample_period = 0x0000AE30, .irq_subsample_pattern = 0x0000AE34, @@ -510,9 +507,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .image_cfg_1 = 0x0000AF10, .image_cfg_2 = 0x0000AF14, .packer_cfg = 0x0000AF18, - .frame_header_addr = 0x0000AF20, - .frame_header_incr = 0x0000AF24, - .frame_header_cfg = 0x0000AF28, .line_done_cfg = 0, .irq_subsample_period = 0x0000AF30, .irq_subsample_pattern = 0x0000AF34, @@ -597,9 +591,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .image_cfg_1 = 0x0000B210, .image_cfg_2 = 0x0000B214, .packer_cfg = 0x0000B218, - .frame_header_addr = 0x0000B220, - .frame_header_incr = 0x0000B224, - .frame_header_cfg = 0x0000B228, .line_done_cfg = 0, .irq_subsample_period = 0x0000B230, .irq_subsample_pattern = 0x0000B234, @@ -626,9 +617,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .image_cfg_1 = 0x0000B310, .image_cfg_2 = 0x0000B314, .packer_cfg = 0x0000B318, - .frame_header_addr = 0x0000B320, - .frame_header_incr = 0x0000B324, - .frame_header_cfg = 0x0000B328, .line_done_cfg = 0, .irq_subsample_period = 0x0000B330, .irq_subsample_pattern = 0x0000B334, @@ -684,9 +672,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { .image_cfg_1 = 0x0000B510, .image_cfg_2 = 0x0000B514, .packer_cfg = 0x0000B518, - .frame_header_addr = 0x0000B520, - .frame_header_incr = 0x0000B524, - .frame_header_cfg = 0x0000B528, .line_done_cfg = 0, .irq_subsample_period = 0x0000B530, .irq_subsample_pattern = 0x0000B534, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h index 2f2fb4cb667e..2abeaff9cee7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h @@ -280,9 +280,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .image_cfg_1 = 0x00001010, .image_cfg_2 = 0x00001014, .packer_cfg = 0x00001018, - .frame_header_addr = 0x00001020, - .frame_header_incr = 0x00001024, - .frame_header_cfg = 0x00001028, .irq_subsample_period = 0x00001030, .irq_subsample_pattern = 0x00001034, .framedrop_period = 0x00001038, @@ -309,9 +306,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .image_cfg_1 = 0x00001110, .image_cfg_2 = 0x00001114, .packer_cfg = 0x00001118, - .frame_header_addr = 0x00001120, - .frame_header_incr = 0x00001124, - .frame_header_cfg = 0x00001128, .irq_subsample_period = 0x00001130, .irq_subsample_pattern = 0x00001134, .framedrop_period = 0x00001138, @@ -396,9 +390,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .image_cfg_1 = 0x00001410, .image_cfg_2 = 0x00001414, .packer_cfg = 0x00001418, - .frame_header_addr = 0x00001420, - .frame_header_incr = 0x00001424, - .frame_header_cfg = 0x00001428, .irq_subsample_period = 0x00001430, .irq_subsample_pattern = 0x00001434, .framedrop_period = 0x00001438, @@ -425,9 +416,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .image_cfg_1 = 0x00001510, .image_cfg_2 = 0x00001514, .packer_cfg = 0x00001518, - .frame_header_addr = 0x00001520, - .frame_header_incr = 0x00001524, - .frame_header_cfg = 0x00001528, .irq_subsample_period = 0x00001530, .irq_subsample_pattern = 0x00001534, .framedrop_period = 0x00001538, @@ -483,9 +471,6 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .image_cfg_1 = 0x00001710, .image_cfg_2 = 0x00001714, .packer_cfg = 0x00001718, - .frame_header_addr = 0x00001720, - .frame_header_incr = 0x00001724, - .frame_header_cfg = 0x00001728, .irq_subsample_period = 0x00001730, .irq_subsample_pattern = 0x00001734, .framedrop_period = 0x00001738, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 40bf7427546b..47090497f9b7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2820,7 +2820,6 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, uint32_t i, j, k, size = 0; uint32_t frame_inc = 0, val; uint32_t loop_size = 0; - bool frame_header_enable = false; bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; @@ -2859,20 +2858,22 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, wm_data->en_cfg &= ~(1 << 2); if (update_buf->wm_update->frame_header && - !frame_header_enable) { - wm_data->en_cfg |= 1 << 2; - frame_header_enable = true; - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->frame_header_addr, - update_buf->wm_update->frame_header); - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->frame_header_cfg, + !update_buf->wm_update->fh_enabled) { + if (wm_data->hw_regs->frame_header_addr) { + wm_data->en_cfg |= 1 << 2; + update_buf->wm_update->fh_enabled = true; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_header_addr, + update_buf->wm_update->frame_header); + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_header_cfg, + update_buf->wm_update->local_id); + CAM_DBG(CAM_ISP, + "WM: %d en_cfg 0x%x frame_header %pK local_id %u", + wm_data->index, wm_data->en_cfg, + update_buf->wm_update->frame_header, update_buf->wm_update->local_id); - CAM_DBG(CAM_ISP, - "WM: %d en_cfg 0x%x frame_header %pK local_id %u", - wm_data->index, wm_data->en_cfg, - update_buf->wm_update->frame_header, - update_buf->wm_update->local_id); + } } CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, From e874b94c3ad30f580246b22599277826b0736f33 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Tue, 13 Oct 2020 16:55:34 +0530 Subject: [PATCH 618/790] msm: camera: ope: Avoid submitting NULL request to CDM In corner case, there is a chance that userspace can submit request while flush is ongoing. In some cases submitted request can get flushed and corresponding data structures memory gets freed. Add a logic to check for pending request before submitting request to cdm hw. CRs-Fixed: 2815901 Change-Id: I74096201e204f204c4f15d14698b4e9af6435f55 Signed-off-by: Alok Chauhan --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 8560c77f89fc..2b46462dbdc9 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -81,6 +81,11 @@ end: return rsc_idx; } +static bool cam_ope_is_pending_request(struct cam_ope_ctx *ctx_data) +{ + return !bitmap_empty(ctx_data->bitmap, CAM_CTX_REQ_MAX); +} + static int cam_ope_mgr_process_cmd(void *priv, void *data) { int rc; @@ -96,14 +101,16 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) ctx_data = priv; task_data = (struct ope_cmd_work_data *)data; + + mutex_lock(&hw_mgr->hw_mgr_mutex); cdm_cmd = task_data->data; if (!cdm_cmd) { CAM_ERR(CAM_OPE, "Invalid params%pK", cdm_cmd); + mutex_unlock(&hw_mgr->hw_mgr_mutex); return -EINVAL; } - mutex_lock(&hw_mgr->hw_mgr_mutex); if (ctx_data->ctx_state != OPE_CTX_STATE_ACQUIRED) { mutex_unlock(&hw_mgr->hw_mgr_mutex); CAM_ERR(CAM_OPE, "ctx id :%u is not in use", @@ -119,6 +126,13 @@ static int cam_ope_mgr_process_cmd(void *priv, void *data) return -EINVAL; } + if (!cam_ope_is_pending_request(ctx_data)) { + CAM_WARN(CAM_OPE, "no pending req, req %lld last flush %lld", + task_data->req_id, ctx_data->last_flush_req); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + CAM_DBG(CAM_OPE, "cam_cdm_submit_bls: handle 0x%x, ctx_id %d req %d cookie %d", ctx_data->ope_cdm.cdm_handle, ctx_data->ctx_id, @@ -256,11 +270,6 @@ static int cam_ope_mgr_reapply_config(struct cam_ope_hw_mgr *hw_mgr, return rc; } -static bool cam_ope_is_pending_request(struct cam_ope_ctx *ctx_data) -{ - return !bitmap_empty(ctx_data->bitmap, CAM_CTX_REQ_MAX); -} - static int cam_get_valid_ctx_id(void) { struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr; From 1f9cc4f48c3153b7af9f2c3374cadf45597996d4 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Sun, 22 Nov 2020 18:17:12 +0530 Subject: [PATCH 619/790] msm: camera: isp: reduce bufdone error logs If buf done error come for same applied request id then log only once. Change the bufdone deferred logs to debug logs. CRs-Fixed: 2824276 Change-Id: I870708bfb0c4f0ad0a1fade3a7e334551d055c73 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/cam_isp_context.c | 35 ++++++++++++++++++++++++------- drivers/cam_isp/cam_isp_context.h | 2 ++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9828d5c51090..dec2c31f6500 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -839,6 +839,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + ctx_isp->last_bufdone_err_apply_req_id = 0; } else { list_add(&req->list, &ctx->pending_req_list); CAM_DBG(CAM_REQ, @@ -864,6 +865,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); ctx_isp->req_info.last_bufdone_req_id = req->request_id; + ctx_isp->last_bufdone_err_apply_req_id = 0; } cam_cpas_notify_event("IFE BufDone", buf_done_req_id); @@ -1167,11 +1169,11 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( */ req_isp->deferred_fence_map_index[deferred_indx] = j; req_isp->num_deferred_acks++; - CAM_WARN(CAM_ISP, + CAM_DBG(CAM_ISP, "ctx[%d] : Deferred buf done for %llu with bubble state %d recovery %d", ctx->ctx_id, req->request_id, bubble_state, req_isp->bubble_report); - CAM_WARN(CAM_ISP, + CAM_DBG(CAM_ISP, "ctx[%d] : Deferred info : num_acks=%d, fence_map_index=%d, resource_handle=0x%x, sync_id=%d", ctx->ctx_id, req_isp->num_deferred_acks, j, req_isp->fence_map_out[j].resource_handle, @@ -1383,20 +1385,28 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( struct cam_ctx_request *req; struct cam_ctx_request *next_req = NULL; struct cam_context *ctx = ctx_isp->base; + bool req_in_wait_list = false; if (list_empty(&ctx->active_req_list)) { - CAM_WARN(CAM_ISP, - "Buf done with no active request bubble_state=%d", - bubble_state); if (!list_empty(&ctx->wait_req_list)) { struct cam_isp_ctx_req *req_isp; req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); - CAM_WARN(CAM_ISP, - "Buf done with no active request but with req in wait list, req %llu", - req->request_id); + + req_in_wait_list = true; + if (ctx_isp->last_applied_req_id != + ctx_isp->last_bufdone_err_apply_req_id) { + CAM_WARN(CAM_ISP, + "Buf done with no active request but with req in wait list, req %llu last apply id:%lld last err id:%lld", + req->request_id, + ctx_isp->last_applied_req_id, + ctx_isp->last_bufdone_err_apply_req_id); + ctx_isp->last_bufdone_err_apply_req_id = + ctx_isp->last_applied_req_id; + } + req_isp = (struct cam_isp_ctx_req *) req->req_priv; /* @@ -1410,6 +1420,15 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx_isp, req, done, bubble_state, true, true); } + + if (!req_in_wait_list && (ctx_isp->last_applied_req_id != + ctx_isp->last_bufdone_err_apply_req_id)) { + CAM_WARN(CAM_ISP, + "Buf done with no active request bubble_state=%d last_applied_req_id:%lld ", + bubble_state, ctx_isp->last_applied_req_id); + ctx_isp->last_bufdone_err_apply_req_id = + ctx_isp->last_applied_req_id; + } return 0; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 7f97929261bf..6d9477d4fd7b 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -277,6 +277,7 @@ struct cam_isp_context_event_record { * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife * @trigger_id: ID provided by CRM for each ctx on the link + * @last_bufdone_err_apply_req_id: last bufdone error apply request id * */ struct cam_isp_context { @@ -323,6 +324,7 @@ struct cam_isp_context { atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; int32_t trigger_id; + int64_t last_bufdone_err_apply_req_id; }; /** From 5a24b2b912982576a279ca76fbed271f8baa2e6d Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 26 Nov 2020 14:26:46 +0530 Subject: [PATCH 620/790] msm: camera: ope: free unused memory in ope acquire OPE driver allocate memory dynamically to store cdm acquire and bw data in acquire time and don't use later. These memories can be freed before returning from acquire. CRs-Fixed: 2827058 Change-Id: Ibf87282862f2ae4655da3c69016bedb7f96bca1c Signed-off-by: Alok Chauhan --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 8560c77f89fc..6bad7c22de53 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -2734,6 +2734,10 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) ctx->ctxt_event_cb = args->event_cb; cam_ope_ctx_clk_info_init(ctx); ctx->ctx_state = OPE_CTX_STATE_ACQUIRED; + kzfree(cdm_acquire); + cdm_acquire = NULL; + kzfree(bw_update); + bw_update = NULL; mutex_unlock(&ctx->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); From f9b9771412902e09a018e8c1f119e13ab8373263 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 26 Nov 2020 19:02:36 +0530 Subject: [PATCH 621/790] msm: camera: ife: Handle vfe out array properly Bus vfe out array is getting accessed beyond allocated space. Check the index with max supported number vfe out values before accessing the vfe out array. Use the proper index to access the vfe out array. CRs-Fixed: 2819234 Change-Id: I21865cb7025cc88f6b6015576eadd81eb3819eab Signed-off-by: Ravikishore Pampana --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 174 +++++++++++++----- 1 file changed, 124 insertions(+), 50 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 40bf7427546b..f26c6e44628e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -199,6 +199,7 @@ struct cam_vfe_bus_ver3_priv { struct cam_isp_resource_node *bus_client; struct cam_isp_resource_node *comp_grp; struct cam_isp_resource_node *vfe_out; + uint32_t vfe_out_map_outtype[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; struct list_head free_comp_grp; struct list_head used_comp_grp; @@ -566,74 +567,114 @@ static bool cam_vfe_bus_ver3_can_be_secure(uint32_t out_type) } static enum cam_vfe_bus_ver3_vfe_out_type - cam_vfe_bus_ver3_get_out_res_id(uint32_t res_type) + cam_vfe_bus_ver3_get_out_res_id_and_index( + struct cam_vfe_bus_ver3_priv *bus_priv, + uint32_t res_type, uint32_t *index) { + uint32_t vfe_out_type; + switch (res_type) { case CAM_ISP_IFE_OUT_RES_FULL: - return CAM_VFE_BUS_VER3_VFE_OUT_FULL; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL; + break; case CAM_ISP_IFE_OUT_RES_DS4: - return CAM_VFE_BUS_VER3_VFE_OUT_DS4; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4; + break; case CAM_ISP_IFE_OUT_RES_DS16: - return CAM_VFE_BUS_VER3_VFE_OUT_DS16; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16; + break; case CAM_ISP_IFE_OUT_RES_FD: - return CAM_VFE_BUS_VER3_VFE_OUT_FD; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FD; + break; case CAM_ISP_IFE_OUT_RES_RAW_DUMP: - return CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP; + break; case CAM_ISP_IFE_OUT_RES_2PD: - return CAM_VFE_BUS_VER3_VFE_OUT_2PD; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD; + break; case CAM_ISP_IFE_OUT_RES_RDI_0: - return CAM_VFE_BUS_VER3_VFE_OUT_RDI0; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI0; + break; case CAM_ISP_IFE_OUT_RES_RDI_1: - return CAM_VFE_BUS_VER3_VFE_OUT_RDI1; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI1; + break; case CAM_ISP_IFE_OUT_RES_RDI_2: - return CAM_VFE_BUS_VER3_VFE_OUT_RDI2; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI2; + break; case CAM_ISP_IFE_OUT_RES_RDI_3: - return CAM_VFE_BUS_VER3_VFE_OUT_RDI3; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_RDI3; + break; case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE; + break; case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST; + break; case CAM_ISP_IFE_OUT_RES_STATS_TL_BG: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG; + break; case CAM_ISP_IFE_OUT_RES_STATS_BF: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF; + break; case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG; + break; case CAM_ISP_IFE_OUT_RES_STATS_BHIST: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST; + break; case CAM_ISP_IFE_OUT_RES_STATS_RS: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS; + break; case CAM_ISP_IFE_OUT_RES_STATS_CS: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS; + break; case CAM_ISP_IFE_OUT_RES_STATS_IHIST: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST; + break; case CAM_ISP_IFE_OUT_RES_FULL_DISP: - return CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP; + break; case CAM_ISP_IFE_OUT_RES_DS4_DISP: - return CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP; + break; case CAM_ISP_IFE_OUT_RES_DS16_DISP: - return CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP; + break; case CAM_ISP_IFE_OUT_RES_LCR: - return CAM_VFE_BUS_VER3_VFE_OUT_LCR; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LCR; + break; case CAM_ISP_IFE_OUT_RES_AWB_BFW: - return CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_AWB_BFW; + break; case CAM_ISP_IFE_OUT_RES_2PD_STATS: - return CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_2PD_STATS; + break; case CAM_ISP_IFE_OUT_RES_STATS_AEC_BE: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_AEC_BE; + break; + case CAM_ISP_IFE_OUT_RES_LTM_STATS: - return CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_LTM_STATS; + break; case CAM_ISP_IFE_OUT_RES_STATS_GTM_BHIST: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_GTM_BHIST; + break; case CAM_ISP_IFE_LITE_OUT_RES_STATS_BE: - return CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_STATS_BE; + break; case CAM_ISP_IFE_LITE_OUT_RES_GAMMA: - return CAM_VFE_BUS_VER3_VFE_OUT_GAMMA; + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_GAMMA; + break; default: CAM_WARN(CAM_ISP, "Invalid isp res id: %d , assigning max", res_type); + vfe_out_type = CAM_VFE_BUS_VER3_VFE_OUT_MAX; + *index = CAM_VFE_BUS_VER3_VFE_OUT_MAX; return CAM_VFE_BUS_VER3_VFE_OUT_MAX; } + *index = bus_priv->vfe_out_map_outtype[vfe_out_type]; + + return vfe_out_type; } static int cam_vfe_bus_ver3_get_comp_vfe_out_res_id_list( @@ -1888,6 +1929,7 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; uint32_t secure_caps = 0, mode; struct cam_vfe_bus_ver3_comp_grp_acquire_args comp_acq_args = {0}; + uint32_t outmap_index = CAM_VFE_BUS_VER3_VFE_OUT_MAX; if (!bus_priv || !acquire_args) { CAM_ERR(CAM_ISP, "Invalid Param"); @@ -1901,12 +1943,20 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, ver3_bus_priv->common_data.core_index, out_acquire_args->out_port_info->res_type); - vfe_out_res_id = cam_vfe_bus_ver3_get_out_res_id( - out_acquire_args->out_port_info->res_type); - if (vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_MAX) + vfe_out_res_id = cam_vfe_bus_ver3_get_out_res_id_and_index( + ver3_bus_priv, + out_acquire_args->out_port_info->res_type, + &outmap_index); + if ((vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_MAX) || + (outmap_index >= ver3_bus_priv->num_out)) { + CAM_WARN(CAM_ISP, + "target does not support req res id :0x%x outtype:%d index:%d", + out_acquire_args->out_port_info->res_type, + vfe_out_res_id, outmap_index); return -ENODEV; + } - rsrc_node = &ver3_bus_priv->vfe_out[vfe_out_res_id]; + rsrc_node = &ver3_bus_priv->vfe_out[outmap_index]; if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { CAM_ERR(CAM_ISP, "VFE:%d out_type:0x%X resource not available state:%d", @@ -2307,15 +2357,20 @@ static uint32_t cam_vfe_bus_ver3_get_last_consumed_addr( struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; struct cam_vfe_bus_ver3_wm_resource_data *wm_rsrc_data = NULL; enum cam_vfe_bus_ver3_vfe_out_type res_id; + uint32_t outmap_index = CAM_VFE_BUS_VER3_VFE_OUT_MAX; - res_id = cam_vfe_bus_ver3_get_out_res_id(res_type); + res_id = cam_vfe_bus_ver3_get_out_res_id_and_index(bus_priv, + res_type, &outmap_index); - if (res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { - CAM_ERR(CAM_ISP, "invalid res id:%u", res_id); + if ((res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) || + (outmap_index >= bus_priv->num_out)) { + CAM_WARN(CAM_ISP, + "target does not support req res id :0x%x outtype:%d index:%d", + res_type, res_id, outmap_index); return 0; } - rsrc_node = &bus_priv->vfe_out[res_id]; + rsrc_node = &bus_priv->vfe_out[outmap_index]; rsrc_data = rsrc_node->res_priv; wm_rsrc_data = rsrc_data->wm_res[PLANE_Y].res_priv; @@ -2394,7 +2449,8 @@ static int cam_vfe_bus_ver3_init_vfe_out_resource(uint32_t index, return -EINVAL; } - vfe_out = &ver3_bus_priv->vfe_out[vfe_out_type]; + ver3_bus_priv->vfe_out_map_outtype[vfe_out_type] = index; + vfe_out = &ver3_bus_priv->vfe_out[index]; if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || vfe_out->res_priv) { CAM_ERR(CAM_ISP, "vfe_out_type %d has already been initialized", @@ -2506,7 +2562,7 @@ static int cam_vfe_bus_ver3_deinit_vfe_out_resource( } static int cam_vfe_bus_ver3_print_dimensions( - enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, + uint32_t res_id, struct cam_vfe_bus_ver3_priv *bus_priv) { struct cam_isp_resource_node *rsrc_node = NULL; @@ -2515,20 +2571,29 @@ static int cam_vfe_bus_ver3_print_dimensions( struct cam_vfe_bus_ver3_common_data *common_data = NULL; int i; uint32_t addr_status0, addr_status1, addr_status2, addr_status3; + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id = + CAM_VFE_BUS_VER3_VFE_OUT_MAX; + uint32_t outmap_index = CAM_VFE_BUS_VER3_VFE_OUT_MAX; if (!bus_priv) { CAM_ERR(CAM_ISP, "Invalid bus private data, res_id: %d", - vfe_out_res_id); + res_id); return -EINVAL; } - if (vfe_out_res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { - CAM_ERR(CAM_ISP, "Invalid out resource for dump: %d", - vfe_out_res_id); + vfe_out_res_id = cam_vfe_bus_ver3_get_out_res_id_and_index(bus_priv, + res_id, &outmap_index); + + if ((vfe_out_res_id == CAM_VFE_BUS_VER3_VFE_OUT_MAX) || + (outmap_index >= bus_priv->num_out)) { + CAM_WARN_RATE_LIMIT(CAM_ISP, + "target does not support req res id :0x%x outtype:%d index:%d", + res_id, + vfe_out_res_id, outmap_index); return -EINVAL; } - rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; + rsrc_node = &bus_priv->vfe_out[outmap_index]; rsrc_data = rsrc_node->res_priv; if (!rsrc_data) { CAM_ERR(CAM_ISP, "VFE out data is null, res_id: %d", @@ -3600,15 +3665,13 @@ static int cam_vfe_bus_ver3_process_cmd( break; case CAM_ISP_HW_CMD_DUMP_BUS_INFO: { struct cam_isp_hw_event_info *event_info; - enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id; event_info = (struct cam_isp_hw_event_info *)cmd_args; bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; - vfe_out_res_id = - cam_vfe_bus_ver3_get_out_res_id(event_info->res_id); + rc = cam_vfe_bus_ver3_print_dimensions( - vfe_out_res_id, bus_priv); + event_info->res_id, bus_priv); break; } case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: @@ -3721,6 +3784,13 @@ int cam_vfe_bus_ver3_init( bus_priv->common_data.comp_config_needed = ver3_hw_info->comp_cfg_needed; + if (bus_priv->num_out >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "number of vfe out:%d more than max value:%d ", + bus_priv->num_out, CAM_VFE_BUS_VER3_VFE_OUT_MAX); + rc = -EINVAL; + goto free_bus_priv; + } + bus_priv->comp_grp = kzalloc((sizeof(struct cam_isp_resource_node) * bus_priv->num_comp_grp), GFP_KERNEL); if (!bus_priv->comp_grp) { @@ -3775,6 +3845,10 @@ int cam_vfe_bus_ver3_init( } } + for (i = 0; i < CAM_VFE_BUS_VER3_VFE_OUT_MAX; i++) + bus_priv->vfe_out_map_outtype[i] = + CAM_VFE_BUS_VER3_VFE_OUT_MAX; + for (i = 0; i < bus_priv->num_out; i++) { rc = cam_vfe_bus_ver3_init_vfe_out_resource(i, bus_priv, bus_hw_info); From b8fa5623704014f4ea68149afdfc184591592f68 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 17 Nov 2020 11:47:11 -0800 Subject: [PATCH 622/790] msm: camera: isp: Update err type when notifying to HW MGR Currently violation in FULL IFE on IPP/PPP path is treated as overflow in HW_MGR. Update the err type correctly. CRs-Fixed: 2815428 Change-Id: I2bbcdca03afc5be48281c39c50ecb32342ad7fbe Signed-off-by: Karthik Anantha Ram --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 2c215fbacce8..03adaac7492b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1487,6 +1487,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, ts.tv_sec, ts.tv_nsec/1000); ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + evt_info.err_type = CAM_VFE_IRQ_STATUS_OVERFLOW; CAM_INFO(CAM_ISP, "ife_clk_src:%lld", soc_private->ife_clk_src); @@ -1519,6 +1520,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, ts.tv_sec, ts.tv_nsec/1000); ret = CAM_VFE_IRQ_STATUS_VIOLATION; + evt_info.err_type = CAM_VFE_IRQ_STATUS_VIOLATION; CAM_INFO(CAM_ISP, "ife_clk_src:%lld", soc_private->ife_clk_src); From a73a482f7600ebd449117a578b65c4bd983c1d78 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 20 Nov 2020 20:53:19 +0530 Subject: [PATCH 623/790] msm: camera: isp: Add null check for vfe out res data Fixes the null pointer dereference in the get Constraint error function. CRs-Fixed: 2825045 Change-Id: I72d8e51257fcfeca8386e626cf04db448bf3b483 Signed-off-by: Ayush Kumar --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 40bf7427546b..282361507761 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -862,6 +862,11 @@ static void cam_vfe_bus_ver3_get_constraint_errors( for (i = 0; i < bus_priv->num_out; i++) { out_rsrc_node = &bus_priv->vfe_out[i]; + if (!out_rsrc_node || !out_rsrc_node->res_priv) { + CAM_DBG(CAM_ISP, + "Vfe out:%d out rsrc node or data is NULL", i); + continue; + } out_rsrc_data = out_rsrc_node->res_priv; for (j = 0; j < out_rsrc_data->num_wm; j++) { wm_data = out_rsrc_data->wm_res[j].res_priv; From c3c20451153ef69b5382b3a1841706009176cef6 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Fri, 20 Nov 2020 11:44:42 +0530 Subject: [PATCH 624/790] msm: camera: ope: Check array size of input sync obj Incase of input buffer, check array size of input sync obj before assigning fence. CRs-Fixed: 2821583 Change-Id: I5cd7968cfbe0be86a8967565616bf6eb1cf7fcf7 Signed-off-by: Shravya Samala --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 54 ++++++++++++--------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 8560c77f89fc..223d18321522 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1757,7 +1757,7 @@ end: static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, struct cam_packet *packet, - struct cam_hw_prepare_update_args *prep_args, + struct cam_hw_prepare_update_args *prep_arg, struct cam_ope_ctx *ctx_data, uint32_t req_idx) { @@ -1768,8 +1768,8 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, struct cam_ope_request *ope_request; ope_request = ctx_data->req_list[req_idx]; - prep_args->num_out_map_entries = 0; - prep_args->num_in_map_entries = 0; + prep_arg->num_out_map_entries = 0; + prep_arg->num_in_map_entries = 0; ope_request = ctx_data->req_list[req_idx]; CAM_DBG(CAM_OPE, "E: req_idx = %u %x", req_idx, packet); @@ -1779,8 +1779,16 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, io_buf = ope_request->io_buf[i][l]; if (io_buf->direction == CAM_BUF_INPUT) { if (io_buf->fence != -1) { - sync_in_obj[j++] = io_buf->fence; - prep_args->num_in_map_entries++; + if (j < CAM_MAX_IN_RES) { + sync_in_obj[j++] = + io_buf->fence; + prep_arg->num_in_map_entries++; + } else { + CAM_ERR(CAM_OPE, + "reached max in_res %d %d", + io_buf->resource_type, + ope_request->request_id); + } } else { CAM_ERR(CAM_OPE, "Invalid fence %d %d", io_buf->resource_type, @@ -1788,10 +1796,10 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, } } else { if (io_buf->fence != -1) { - prep_args->out_map_entries[k].sync_id = + prep_arg->out_map_entries[k].sync_id = io_buf->fence; k++; - prep_args->num_out_map_entries++; + prep_arg->num_out_map_entries++; } else { if (io_buf->resource_type != OPE_OUT_RES_STATS_LTM) { @@ -1812,38 +1820,38 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, } } - if (prep_args->num_in_map_entries > 1 && - prep_args->num_in_map_entries <= CAM_MAX_IN_RES) - prep_args->num_in_map_entries = + if (prep_arg->num_in_map_entries > 1 && + prep_arg->num_in_map_entries <= CAM_MAX_IN_RES) + prep_arg->num_in_map_entries = cam_common_util_remove_duplicate_arr( - sync_in_obj, prep_args->num_in_map_entries); + sync_in_obj, prep_arg->num_in_map_entries); - if (prep_args->num_in_map_entries > 1 && - prep_args->num_in_map_entries <= CAM_MAX_IN_RES) { + if (prep_arg->num_in_map_entries > 1 && + prep_arg->num_in_map_entries <= CAM_MAX_IN_RES) { rc = cam_sync_merge(&sync_in_obj[0], - prep_args->num_in_map_entries, &merged_sync_in_obj); + prep_arg->num_in_map_entries, &merged_sync_in_obj); if (rc) { - prep_args->num_out_map_entries = 0; - prep_args->num_in_map_entries = 0; + prep_arg->num_out_map_entries = 0; + prep_arg->num_in_map_entries = 0; return rc; } ope_request->in_resource = merged_sync_in_obj; - prep_args->in_map_entries[0].sync_id = merged_sync_in_obj; - prep_args->num_in_map_entries = 1; + prep_arg->in_map_entries[0].sync_id = merged_sync_in_obj; + prep_arg->num_in_map_entries = 1; CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d", ctx_data->ctx_id, packet->header.request_id, merged_sync_in_obj); - } else if (prep_args->num_in_map_entries == 1) { - prep_args->in_map_entries[0].sync_id = sync_in_obj[0]; - prep_args->num_in_map_entries = 1; + } else if (prep_arg->num_in_map_entries == 1) { + prep_arg->in_map_entries[0].sync_id = sync_in_obj[0]; + prep_arg->num_in_map_entries = 1; ope_request->in_resource = 0; CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]); } else { CAM_DBG(CAM_OPE, "Invalid count of input fences, count: %d", - prep_args->num_in_map_entries); - prep_args->num_in_map_entries = 0; + prep_arg->num_in_map_entries); + prep_arg->num_in_map_entries = 0; ope_request->in_resource = 0; rc = -EINVAL; } From b3b1177fdfb636ea94a859693a1d22d457aae155 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Thu, 19 Nov 2020 12:34:10 -0800 Subject: [PATCH 625/790] msm: camera: isp: Print the expected height & width In case of pix/line count error, print the configured pixels and lines directly from the format measure config register as opposed to the data from the blob. CRs-Fixed: 2825795 Change-Id: I8cdfb5afbd8cf573abeb7d4e3522d24fa37d8201 Signed-off-by: Karthik Anantha Ram --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index ed3e0a75c6ab..3b864d41d2fe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -5202,6 +5202,9 @@ handle_fatal_error: CSID_PATH_ERROR_LINE_COUNT)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_format_measure0_addr); + val2 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_format_measure_cfg1_addr + ); CAM_ERR(CAM_ISP, "CSID:%d irq_status_ipp:0x%x", @@ -5209,8 +5212,11 @@ handle_fatal_error: irq_status[CAM_IFE_CSID_IRQ_REG_IPP]); CAM_ERR(CAM_ISP, "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x [format_measure0: 0x%x]", - csid_hw->ipp_path_config.height, - csid_hw->ipp_path_config.width, + ((val2 >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val2 & + csid_reg->cmn_reg->format_measure_width_mask_val, ((val >> csid_reg->cmn_reg->format_measure_height_shift_val) & csid_reg->cmn_reg->format_measure_height_mask_val), @@ -5279,6 +5285,9 @@ handle_fatal_error: CSID_PATH_ERROR_LINE_COUNT)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_format_measure0_addr); + val2 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_format_measure_cfg1_addr + ); CAM_ERR(CAM_ISP, "CSID:%d irq_status_ppp:0x%x", @@ -5286,8 +5295,11 @@ handle_fatal_error: irq_status[CAM_IFE_CSID_IRQ_REG_PPP]); CAM_ERR(CAM_ISP, "Expected:: h: 0x%x w: 0x%x actual:: h: 0x%x w: 0x%x [format_measure0: 0x%x]", - csid_hw->ppp_path_config.height, - csid_hw->ppp_path_config.width, + ((val2 >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val2 & + csid_reg->cmn_reg->format_measure_width_mask_val, ((val >> csid_reg->cmn_reg->format_measure_height_shift_val) & csid_reg->cmn_reg->format_measure_height_mask_val), From b3f31ae7266a0897fdc62e29df6b0371f085ce77 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Sat, 21 Nov 2020 12:36:25 -0800 Subject: [PATCH 626/790] msm: camera: isp: Transition to HALT state prior to HW stop In case of any error IRQs encountered during stop, there is no need to notify them to UMD since the entire pipeline would be reset prior to next session start. With this change we transition to HALT state and then issue stop. CRs-Fixed: 2825121 Change-Id: I9535439d1a29e3b6f8da968b60e5b2b5bc32c1bf Signed-off-by: Karthik Anantha Ram --- drivers/cam_isp/cam_isp_context.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9828d5c51090..cb17a392fb56 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5362,6 +5362,11 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( (struct cam_isp_context *) ctx->ctx_priv; struct cam_isp_stop_args stop_isp; + /* Mask off all the incoming hardware events */ + spin_lock_bh(&ctx->lock); + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; + spin_unlock_bh(&ctx->lock); + /* stop hw first */ if (ctx_isp->hw_ctx) { stop.ctxt_to_hw_map = ctx_isp->hw_ctx; @@ -5374,10 +5379,6 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( &stop); } - /* Mask off all the incoming hardware events */ - spin_lock_bh(&ctx->lock); - ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT; - spin_unlock_bh(&ctx->lock); CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); From d87d172bde615073260d3885377b243250cf25cd Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Sat, 12 Sep 2020 00:11:53 +0530 Subject: [PATCH 627/790] msm: camera: cci: Fix logic to update cci clk freq When multiple frequency slaves running on a same I2C bus, then there is a chance of overriding I2C bus frequency even if another I2C operation is running. This could lead to CCI timeout at driver level. Updated synchronization logic, to properly update I2C clock frequency, only when no other I2C operation running. CRs-Fixed: 2815310 Change-Id: Ia341d7cda118497bf1acea8ea59f7f03124f31c3 Signed-off-by: Anil Kumar Kanakanti --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 155 ++++++------------ .../cam_sensor_module/cam_cci/cam_cci_dev.h | 3 +- .../cam_sensor_module/cam_cci/cam_cci_soc.c | 4 +- 3 files changed, 54 insertions(+), 108 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 80ce7c2e8ff3..0d6348108c18 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -609,19 +609,42 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev, struct cam_cci_clk_params_t *clk_params = NULL; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; - struct cam_hw_soc_info *soc_info = - &cci_dev->soc_info; - void __iomem *base = soc_info->reg_map[0].mem_base; + void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base; + struct cam_cci_master_info *cci_master = + &cci_dev->cci_master_info[master]; if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode); return -EINVAL; } + /* + * If no change in i2c freq, then acquire semaphore only for the first + * i2c transaction to indicate I2C transaction is in progress, else + * always try to acquire semaphore, to make sure that no other I2C + * transaction is in progress. + */ + mutex_lock(&cci_master->mutex); + if (i2c_freq_mode == cci_dev->i2c_freq_mode[master]) { + CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d", master, + i2c_freq_mode); + spin_lock(&cci_master->freq_cnt_lock); + if (cci_master->freq_ref_cnt == 0) + down(&cci_master->master_sem); + cci_master->freq_ref_cnt++; + spin_unlock(&cci_master->freq_cnt_lock); + mutex_unlock(&cci_master->mutex); + return 0; + } + CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d", + master, cci_dev->i2c_freq_mode[master], i2c_freq_mode); + down(&cci_master->master_sem); + + spin_lock(&cci_master->freq_cnt_lock); + cci_master->freq_ref_cnt++; + spin_unlock(&cci_master->freq_cnt_lock); clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; - if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode) - return 0; if (master == MASTER_0) { cam_io_w_mb(clk_params->hw_thigh << 16 | clk_params->hw_tlow, @@ -655,6 +678,7 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev, } cci_dev->i2c_freq_mode[master] = i2c_freq_mode; + mutex_unlock(&cci_master->mutex); return 0; } @@ -938,42 +962,19 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, return -EINVAL; } - soc_info = &cci_dev->soc_info; - base = soc_info->reg_map[0].mem_base; - - mutex_lock(&cci_dev->cci_master_info[master].mutex); - if (cci_dev->cci_master_info[master].is_first_req) { - 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); - mutex_unlock(&cci_dev->cci_master_info[master].mutex); - goto rel_master; + return rc; } - mutex_unlock(&cci_dev->cci_master_info[master].mutex); mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); + + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + /* * 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 @@ -1198,13 +1199,11 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, 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) + + spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock); + 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); + spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock); return rc; } @@ -1234,42 +1233,19 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, return -EINVAL; } - soc_info = &cci_dev->soc_info; - base = soc_info->reg_map[0].mem_base; - - mutex_lock(&cci_dev->cci_master_info[master].mutex); - if (cci_dev->cci_master_info[master].is_first_req) { - 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_master; + return rc; } - mutex_unlock(&cci_dev->cci_master_info[master].mutex); mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); + + soc_info = &cci_dev->soc_info; + base = soc_info->reg_map[0].mem_base; + /* * 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 @@ -1425,13 +1401,11 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, } 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) + + spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock); + 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); + spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock); return rc; } @@ -1455,37 +1429,12 @@ 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) { - 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); - mutex_unlock(&cci_dev->cci_master_info[master].mutex); - goto ERROR; + return rc; } - mutex_unlock(&cci_dev->cci_master_info[master].mutex); - reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); /* * Call validate queue to make sure queue is empty before starting. @@ -1515,12 +1464,10 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd, } ERROR: - spin_lock(&cci_dev->cci_master_info[master].freq_cnt); - if (cci_dev->cci_master_info[master].freq_ref_cnt == 0) + spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock); + 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); + spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock); return rc; } diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 3284c64ad3b1..a72f4d836683 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -132,9 +132,8 @@ 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; + spinlock_t freq_cnt_lock; uint16_t freq_ref_cnt; bool is_initilized; }; diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index fde91ad13459..39433a3f43e1 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -219,11 +219,11 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) for (i = 0; i < MASTER_MAX; i++) { new_cci_dev->cci_master_info[i].status = 0; - new_cci_dev->cci_master_info[i].is_first_req = true; + new_cci_dev->cci_master_info[i].freq_ref_cnt = 0; new_cci_dev->cci_master_info[i].is_initilized = false; 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); + spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt_lock); init_completion( &new_cci_dev->cci_master_info[i].reset_complete); init_completion( From 63bca8c33d0465a709e9f34b0e92fe869efb54c0 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 26 Nov 2020 17:58:46 +0530 Subject: [PATCH 628/790] msm: camera: cdm: Improve error handling during cdm hang Reduce logging as part of error handling to avoid flooding kernel log with excessive log. Apart from that send feedback to client irrespective of cdm reset status. CRs-Fixed: 2826285 Change-Id: I9b0d8c6f64ced4972bb20e26774508573c815e4f Signed-off-by: Alok Chauhan --- drivers/cam_cdm/cam_cdm.h | 1 + drivers/cam_cdm/cam_cdm_hw_core.c | 121 +++++++++--------- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 4 +- .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 16 ++- 4 files changed, 76 insertions(+), 66 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 08adc052b448..584375e852cc 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -83,6 +83,7 @@ #define CAM_CDM_RESET_HW_STATUS 0x4 #define CAM_CDM_ERROR_HW_STATUS 0x5 #define CAM_CDM_FLUSH_HW_STATUS 0x6 +#define CAM_CDM_RESET_ERR_STATUS 0x7 /* Curent BL command masks and shifts */ #define CAM_CDM_CURRENT_BL_LEN 0xFFFFF diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 85721865f81e..d1db45011049 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -297,15 +297,15 @@ static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, bool pause_core) { - uint32_t dump_reg, core_dbg = 0x100; + uint32_t dump_reg[4], core_dbg = 0x100; int i; bool is_core_paused_already; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; const struct cam_cdm_icl_regs *inv_cmd_log = core->offsets->cmn_reg->icl_reg; - cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core status=0x%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, + &dump_reg[0]); if (pause_core) { cam_hw_cdm_pause_core(cdm_hw, true); @@ -314,23 +314,24 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, - &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg); + &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, - &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW Debug status reg=0x%x", dump_reg); + &dump_reg[2]); + + CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x", + dump_reg[0], dump_reg[1], dump_reg[2]); if (core_dbg & 0x100) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_addr, - &dump_reg); - CAM_INFO(CAM_CDM, "AHB dump reglastaddr=0x%x", dump_reg); + &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_data, - &dump_reg); - CAM_INFO(CAM_CDM, "AHB dump reglastdata=0x%x", dump_reg); + &dump_reg[1]); + CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x", + dump_reg[0], dump_reg[1]); } else { CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } @@ -339,46 +340,41 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, if (inv_cmd_log->misc_regs) { cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->misc_regs->icl_status, - &dump_reg); - CAM_INFO(CAM_CDM, - "Last Inv Cmd Log(ICL)Status: 0x%x", - dump_reg); + &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->misc_regs->icl_inv_bl_addr, - &dump_reg); + &dump_reg[1]); CAM_INFO(CAM_CDM, - "Last Inv bl_addr: 0x%x", - dump_reg); + "Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x", + dump_reg[0], dump_reg[1]); } if (inv_cmd_log->data_regs) { cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_inv_data, - &dump_reg); + &dump_reg[0]); CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x", - dump_reg); + dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_0, - &dump_reg); - CAM_INFO(CAM_CDM, "First word of Last Good cmd: 0x%x", - dump_reg); + &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_1, - &dump_reg); - CAM_INFO(CAM_CDM, "Second word of Last Good cmd: 0x%x", - dump_reg); + &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, inv_cmd_log->data_regs->icl_last_data_2, - &dump_reg); - CAM_INFO(CAM_CDM, "Third word of Last Good cmd: 0x%x", - dump_reg); + &dump_reg[2]); + + + CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x", + dump_reg[0], dump_reg[1], dump_reg[2]); } } if (core_dbg & 0x10000) { cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_en, &dump_reg); - is_core_paused_already = (bool)(dump_reg & 0x20); + core->offsets->cmn_reg->core_en, &dump_reg[0]); + is_core_paused_already = (bool)(dump_reg[0] & 0x20); if (!is_core_paused_already) { cam_hw_cdm_pause_core(cdm_hw, true); usleep_range(1000, 1010); @@ -390,49 +386,44 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, cam_hw_cdm_pause_core(cdm_hw, false); } - CAM_INFO(CAM_CDM, "CDM HW default dump"); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_cfg, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg); + core->offsets->cmn_reg->core_cfg, &dump_reg[0]); + CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]); for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_status, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq status%d=0x%x", i, dump_reg); - + core->offsets->irq_reg[i]->irq_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_set, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq set%d=0x%x", i, dump_reg); - + core->offsets->irq_reg[i]->irq_set, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_mask, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq mask%d=0x%x", i, dump_reg); - + core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_clear, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq clear%d=0x%x", i, dump_reg); + core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]); + + CAM_INFO(CAM_CDM, + "cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x", + i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]); } cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->current_bl_base, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW current BL base=0x%x", dump_reg); + core->offsets->cmn_reg->current_bl_base, &dump_reg[0]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]); + CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x", + dump_reg[0], dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->current_bl_len, &dump_reg); + core->offsets->cmn_reg->current_bl_len, &dump_reg[0]); CAM_INFO(CAM_CDM, "CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ", - (dump_reg & CAM_CDM_CURRENT_BL_LEN), - (dump_reg & CAM_CDM_CURRENT_BL_ARB) >> + (dump_reg[0] & CAM_CDM_CURRENT_BL_LEN), + (dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >> CAM_CDM_CURRENT_BL_ARB_SHIFT, - (dump_reg & CAM_CDM_CURRENT_BL_FIFO) >> + (dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >> CAM_CDM_CURRENT_BL_FIFO_SHIFT, - (dump_reg & CAM_CDM_CURRENT_BL_TAG) >> + (dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >> CAM_CDM_CURRENT_BL_TAG_SHIFT); - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW current AHB base=0x%x", dump_reg); - cam_hw_cdm_disable_core_dbg(cdm_hw); if (pause_core) cam_hw_cdm_pause_core(cdm_hw, false); @@ -1128,11 +1119,15 @@ static void cam_hw_cdm_reset_cleanup( int i; struct cam_cdm_bl_cb_request_entry *node, *tnode; bool flush_hw = false; + bool reset_err = false; if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) flush_hw = true; + if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status)) + reset_err = true; + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { list_for_each_entry_safe(node, tnode, &core->bl_fifo[i].bl_request_list, entry) { @@ -1141,12 +1136,19 @@ static void cam_hw_cdm_reset_cleanup( CAM_DBG(CAM_CDM, "Notifying client %d for tag %d", node->client_hdl, node->bl_tag); - if (flush_hw) + if (flush_hw) { + enum cam_cdm_cb_status status; + + status = reset_err ? + CAM_CDM_CB_STATUS_HW_ERROR : + CAM_CDM_CB_STATUS_HW_RESUBMIT; + cam_cdm_notify_clients(cdm_hw, (node->client_hdl == handle) ? CAM_CDM_CB_STATUS_HW_FLUSH : - CAM_CDM_CB_STATUS_HW_RESUBMIT, + status, (void *)node); + } else cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_HW_RESET_DONE, @@ -1695,7 +1697,7 @@ int cam_hw_cdm_handle_error_info( if (time_left <= 0) { rc = -ETIMEDOUT; CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); - goto end; + set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); } rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); @@ -1734,6 +1736,7 @@ int cam_hw_cdm_handle_error_info( end: clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 8560c77f89fc..6f10eec180d2 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -686,9 +686,7 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) } CAM_ERR(CAM_OPE, - "pending requests means, issue is with HW for ctx %d", - ctx_data->ctx_id); - CAM_ERR(CAM_OPE, "ctx: %d, lrt: %llu, lct: %llu", + "pending req at HW, ctx %d lrt %llu lct %llu", ctx_data->ctx_id, ctx_data->last_req_time, ope_hw_mgr->last_callback_time); hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index ee59b8d277c5..1929a4d6e601 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -31,14 +31,22 @@ static struct ope_top ope_top_info; static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info) { - uint32_t i, val; + uint32_t i, val[3]; struct cam_ope_top_reg *top_reg; top_reg = ope_hw_info->top_reg; - for (i = 0; i < top_reg->num_debug_registers; i++) { - val = cam_io_r_mb(top_reg->base + + for (i = 0; i < top_reg->num_debug_registers; i = i+3) { + val[0] = cam_io_r_mb(top_reg->base + top_reg->debug_regs[i].offset); - CAM_INFO(CAM_OPE, "Debug_status_%d val: 0x%x", i, val); + val[1] = ((i+1) < top_reg->num_debug_registers) ? + cam_io_r_mb(top_reg->base + + top_reg->debug_regs[i+1].offset) : 0; + val[2] = ((i+2) < top_reg->num_debug_registers) ? + cam_io_r_mb(top_reg->base + + top_reg->debug_regs[i+2].offset) : 0; + + CAM_INFO(CAM_OPE, "status[%d-%d] : 0x%x 0x%x 0x%x", + i, i+2, val[0], val[1], val[2]); } return 0; } From d788dadae17b6db105542e1e5e9c036c6befcb3d Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 4 Dec 2020 16:35:28 +0530 Subject: [PATCH 629/790] Revert "msm: camera: isp: Add null check for vfe out res data" This reverts commit f7ef5c55116cb2b24ec2c7480ae62658e936f2d9. Change-Id: I497c1b93607ce52f9876da7f44e9c8ff971e9814 Signed-off-by: Salendarsingh Gaud --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index b595c5fec315..40bf7427546b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -862,12 +862,6 @@ static void cam_vfe_bus_ver3_get_constraint_errors( for (i = 0; i < bus_priv->num_out; i++) { out_rsrc_node = &bus_priv->vfe_out[i]; - if (!out_rsrc_node || !out_rsrc_node->res_priv) { - CAM_INFO(CAM_ISP, - "wm :%d out rsrc node or data is NULL (%p)", - i, out_rsrc_node); - continue; - } out_rsrc_data = out_rsrc_node->res_priv; for (j = 0; j < out_rsrc_data->num_wm; j++) { wm_data = out_rsrc_data->wm_res[j].res_priv; From c6b809ec7543d39089097b2d42f9c62363cd4cab Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 20 Nov 2020 20:53:19 +0530 Subject: [PATCH 630/790] msm: camera: isp: Add null check for vfe out res data Fixes the null pointer dereference in the get Constraint error function. Change-Id: Ib79aeac5dfd1a5f44770d363087dc5d242a3fd9d CRs-Fixed: 2825045 Signed-off-by: Ayush Kumar --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 40bf7427546b..282361507761 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -862,6 +862,11 @@ static void cam_vfe_bus_ver3_get_constraint_errors( for (i = 0; i < bus_priv->num_out; i++) { out_rsrc_node = &bus_priv->vfe_out[i]; + if (!out_rsrc_node || !out_rsrc_node->res_priv) { + CAM_DBG(CAM_ISP, + "Vfe out:%d out rsrc node or data is NULL", i); + continue; + } out_rsrc_data = out_rsrc_node->res_priv; for (j = 0; j < out_rsrc_data->num_wm; j++) { wm_data = out_rsrc_data->wm_res[j].res_priv; From 36db836a81b4ae73e979d60fe912272dca35f0ad Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 23 Nov 2020 11:43:14 +0530 Subject: [PATCH 631/790] msm: camera: icp: Increase hfi poll retry rate Increase HFI poll retry rate on init response to 5. Change-Id: Ibfab1e44e320dbcb1e1b47ba91d91c5ef2f9b3c1 Signed-off-by: Shravya Samala --- drivers/cam_icp/hfi.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 1d1d44b6a2f4..4909343d6d16 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -31,6 +31,7 @@ #define HFI_VERSION_INFO_STEP_BMSK 0xFF #define HFI_VERSION_INFO_STEP_SHFT 0 +#define HFI_MAX_POLL_TRY 5 #define HFI_POLL_DELAY_US 100 #define HFI_POLL_TIMEOUT_US 10000 @@ -649,10 +650,11 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, void *priv, uint8_t event_driven_mode) { int rc = 0; - uint32_t status = 0; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; + uint32_t fw_version, status = 0; + uint32_t retry_cnt = 0; struct sfr_buf *sfr_buffer; void __iomem *icp_base; @@ -838,17 +840,41 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); - if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), status, status == ICP_INIT_RESP_SUCCESS, - HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { - CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", - status); - rc = -ETIMEDOUT; + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US); + CAM_DBG(CAM_HFI, "1: status = %u rc = %d", status, rc); + status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); + CAM_DBG(CAM_HFI, "2: status = %u rc = %d", status, rc); + if (status == ICP_INIT_RESP_SUCCESS) + break; + + if (status == ICP_INIT_RESP_FAILED) { + CAM_ERR(CAM_HFI, "ICP Init Failed. status = %u", + status); + CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); + goto regions_fail; + } + retry_cnt++; + } + + if ((retry_cnt == HFI_MAX_POLL_TRY) && + (status != ICP_INIT_RESP_SUCCESS)) { + CAM_ERR(CAM_HFI, "Reached Max retries. status = %u", + status); + CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); + + status = + cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); + if (status != ICP_INIT_RESP_SUCCESS) + BUG(); goto regions_fail; } - CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", - cam_io_r(icp_base + HFI_REG_FW_VERSION)); + CAM_WARN(CAM_HFI, "fw version : [%x]", fw_version); g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; From db8e88d7db4af60cf623a914fda388debab17d94 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 4 Dec 2020 16:49:59 +0530 Subject: [PATCH 632/790] Revert "msm: camera: reqmgr: reduce bufdone error logs" This reverts commit 3a8069737e1ddeb95103eb4ff0364dd2385131a7. Change-Id: Ic342e764fff1a8beea07a01725ec98fb449cf71f Signed-off-by: Salendarsingh Gaud --- drivers/cam_isp/cam_isp_context.c | 34 ++++++++----------------------- drivers/cam_isp/cam_isp_context.h | 2 -- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5a99cd447302..9828d5c51090 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -839,7 +839,6 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); - ctx_isp->last_bufdone_error_apply_req_id = 0; } else { list_add(&req->list, &ctx->pending_req_list); CAM_DBG(CAM_REQ, @@ -865,7 +864,6 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); ctx_isp->req_info.last_bufdone_req_id = req->request_id; - ctx_isp->last_bufdone_error_apply_req_id = 0; } cam_cpas_notify_event("IFE BufDone", buf_done_req_id); @@ -1169,11 +1167,11 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( */ req_isp->deferred_fence_map_index[deferred_indx] = j; req_isp->num_deferred_acks++; - CAM_DBG(CAM_ISP, + CAM_WARN(CAM_ISP, "ctx[%d] : Deferred buf done for %llu with bubble state %d recovery %d", ctx->ctx_id, req->request_id, bubble_state, req_isp->bubble_report); - CAM_DBG(CAM_ISP, + CAM_WARN(CAM_ISP, "ctx[%d] : Deferred info : num_acks=%d, fence_map_index=%d, resource_handle=0x%x, sync_id=%d", ctx->ctx_id, req_isp->num_deferred_acks, j, req_isp->fence_map_out[j].resource_handle, @@ -1385,27 +1383,20 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( struct cam_ctx_request *req; struct cam_ctx_request *next_req = NULL; struct cam_context *ctx = ctx_isp->base; - bool req_in_wait_list = false; if (list_empty(&ctx->active_req_list)) { + CAM_WARN(CAM_ISP, + "Buf done with no active request bubble_state=%d", + bubble_state); if (!list_empty(&ctx->wait_req_list)) { struct cam_isp_ctx_req *req_isp; req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); - - req_in_wait_list = true; - if (ctx_isp->last_applied_req_id != - ctx_isp->last_bufdone_error_apply_req_id) { - CAM_WARN(CAM_ISP, - "Buf done with no active request but with req in wait list, req %llu last apply id:%lld", - req->request_id, - ctx_isp->last_applied_req_id); - ctx_isp->last_bufdone_error_apply_req_id = - ctx_isp->last_applied_req_id; - } - + CAM_WARN(CAM_ISP, + "Buf done with no active request but with req in wait list, req %llu", + req->request_id); req_isp = (struct cam_isp_ctx_req *) req->req_priv; /* @@ -1419,15 +1410,6 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx_isp, req, done, bubble_state, true, true); } - - if (!req_in_wait_list && (ctx_isp->last_applied_req_id != - ctx_isp->last_bufdone_error_apply_req_id)) { - CAM_WARN(CAM_ISP, - "Buf done with no active request bubble_state=%d last_applied_req_id:%lld ", - bubble_state, ctx_isp->last_applied_req_id); - ctx_isp->last_bufdone_error_apply_req_id = - ctx_isp->last_applied_req_id; - } return 0; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index b02977cf1121..7f97929261bf 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -277,7 +277,6 @@ struct cam_isp_context_event_record { * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife * @trigger_id: ID provided by CRM for each ctx on the link - * @last_bufdone_error_apply_req_id: last bufdone error apply request id * */ struct cam_isp_context { @@ -324,7 +323,6 @@ struct cam_isp_context { atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; int32_t trigger_id; - int64_t last_bufdone_error_apply_req_id; }; /** From 11dee0a944cdb00f06f866d93655c7e05551de44 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Sun, 22 Nov 2020 18:17:12 +0530 Subject: [PATCH 633/790] msm: camera: isp: reduce bufdone error logs If buf done error come for same applied request id then log only once. Change the bufdone deferred logs to debug logs. Change-Id: I91f8a48ea8f2bf9b9acfda4eb9a4d2b93dc87a66 CRs-Fixed: 2824276 Signed-off-by: Ravikishore Pampana --- drivers/cam_isp/cam_isp_context.c | 35 ++++++++++++++++++++++++------- drivers/cam_isp/cam_isp_context.h | 2 ++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 9828d5c51090..dec2c31f6500 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -839,6 +839,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + ctx_isp->last_bufdone_err_apply_req_id = 0; } else { list_add(&req->list, &ctx->pending_req_list); CAM_DBG(CAM_REQ, @@ -864,6 +865,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); ctx_isp->req_info.last_bufdone_req_id = req->request_id; + ctx_isp->last_bufdone_err_apply_req_id = 0; } cam_cpas_notify_event("IFE BufDone", buf_done_req_id); @@ -1167,11 +1169,11 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( */ req_isp->deferred_fence_map_index[deferred_indx] = j; req_isp->num_deferred_acks++; - CAM_WARN(CAM_ISP, + CAM_DBG(CAM_ISP, "ctx[%d] : Deferred buf done for %llu with bubble state %d recovery %d", ctx->ctx_id, req->request_id, bubble_state, req_isp->bubble_report); - CAM_WARN(CAM_ISP, + CAM_DBG(CAM_ISP, "ctx[%d] : Deferred info : num_acks=%d, fence_map_index=%d, resource_handle=0x%x, sync_id=%d", ctx->ctx_id, req_isp->num_deferred_acks, j, req_isp->fence_map_out[j].resource_handle, @@ -1383,20 +1385,28 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( struct cam_ctx_request *req; struct cam_ctx_request *next_req = NULL; struct cam_context *ctx = ctx_isp->base; + bool req_in_wait_list = false; if (list_empty(&ctx->active_req_list)) { - CAM_WARN(CAM_ISP, - "Buf done with no active request bubble_state=%d", - bubble_state); if (!list_empty(&ctx->wait_req_list)) { struct cam_isp_ctx_req *req_isp; req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); - CAM_WARN(CAM_ISP, - "Buf done with no active request but with req in wait list, req %llu", - req->request_id); + + req_in_wait_list = true; + if (ctx_isp->last_applied_req_id != + ctx_isp->last_bufdone_err_apply_req_id) { + CAM_WARN(CAM_ISP, + "Buf done with no active request but with req in wait list, req %llu last apply id:%lld last err id:%lld", + req->request_id, + ctx_isp->last_applied_req_id, + ctx_isp->last_bufdone_err_apply_req_id); + ctx_isp->last_bufdone_err_apply_req_id = + ctx_isp->last_applied_req_id; + } + req_isp = (struct cam_isp_ctx_req *) req->req_priv; /* @@ -1410,6 +1420,15 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr( __cam_isp_ctx_handle_buf_done_for_request_verify_addr( ctx_isp, req, done, bubble_state, true, true); } + + if (!req_in_wait_list && (ctx_isp->last_applied_req_id != + ctx_isp->last_bufdone_err_apply_req_id)) { + CAM_WARN(CAM_ISP, + "Buf done with no active request bubble_state=%d last_applied_req_id:%lld ", + bubble_state, ctx_isp->last_applied_req_id); + ctx_isp->last_bufdone_err_apply_req_id = + ctx_isp->last_applied_req_id; + } return 0; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 7f97929261bf..6d9477d4fd7b 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -277,6 +277,7 @@ struct cam_isp_context_event_record { * decide whether to apply request in offline ctx * @workq: Worker thread for offline ife * @trigger_id: ID provided by CRM for each ctx on the link + * @last_bufdone_err_apply_req_id: last bufdone error apply request id * */ struct cam_isp_context { @@ -323,6 +324,7 @@ struct cam_isp_context { atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; int32_t trigger_id; + int64_t last_bufdone_err_apply_req_id; }; /** From da8fdb3095d47a947d0593dcff5a4550c0422c2d Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 19 Nov 2020 19:42:14 +0530 Subject: [PATCH 634/790] msm: camera: icp: Fetch the firmware name from soc info Use the a5 firmware name from soc info instead of hard coding. CRs-Fixed: 2825675 Change-Id: Ifb089857777ae4d48c1c7ab6f12259a711c46152 Signed-off-by: Vikram Sharma --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 20 ++++++++++++++++---- drivers/cam_icp/icp_hw/a5_hw/a5_soc.c | 3 ++- drivers/cam_icp/icp_hw/a5_hw/a5_soc.h | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 3e4c6f8d9d69..0301120b1978 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -199,10 +199,22 @@ static int32_t cam_a5_download_fw(void *device_priv) pdev = soc_info->pdev; cam_a5_soc_info = soc_info->soc_private; - rc = request_firmware(&core_info->fw_elf, "CAMERA_ICP.elf", &pdev->dev); - if (rc) { - CAM_ERR(CAM_ICP, "Failed to locate fw: %d", rc); - return rc; + if (cam_a5_soc_info->fw_name) { + CAM_INFO(CAM_ICP, "Downloading firmware %s", + cam_a5_soc_info->fw_name); + rc = request_firmware(&core_info->fw_elf, + cam_a5_soc_info->fw_name, &pdev->dev); + if (rc) { + CAM_ERR(CAM_ICP, "Failed to locate fw: %d", rc); + return rc; + } + } else { + rc = request_firmware(&core_info->fw_elf, + "CAMERA_ICP.elf", &pdev->dev); + if (rc) { + CAM_ERR(CAM_ICP, "Failed to locate fw: %d", rc); + return rc; + } } if (!core_info->fw_elf) { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c index 6e9bace10ca4..e19396ee2adc 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.c @@ -32,7 +32,6 @@ static int cam_a5_get_dt_properties(struct cam_hw_soc_info *soc_info) } a5_soc_info = soc_info->soc_private; - fw_name = a5_soc_info->fw_name; rc = of_property_read_string(of_node, "fw_name", &fw_name); if (rc < 0) { @@ -40,6 +39,8 @@ static int cam_a5_get_dt_properties(struct cam_hw_soc_info *soc_info) goto end; } + a5_soc_info->fw_name = fw_name; + rc = of_property_read_u32(of_node, "qos-val", &a5_soc_info->a5_qos_val); if (rc < 0) { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h index 8b5bc1c23c26..3c962ce01f2d 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_soc.h @@ -18,7 +18,7 @@ struct a5_ubwc_cfg_ext { }; struct a5_soc_info { - char *fw_name; + const char *fw_name; bool ubwc_config_ext; uint32_t a5_qos_val; union { From ebe8cb5e879f2c8b7353e74b878c9021a4cdfbfe Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 8 Dec 2020 11:32:33 +0530 Subject: [PATCH 635/790] msm: camera: isp: Remove WARN_ON() from error case in buf done This change prevents excessive logging. WARN_ON() prints call stack which cause excessive logging in tasklet. Removes WARN_ON() in error case where buf done irq for a request exceeds actual number of out port. CRs-Fixed: 2828453 Change-Id: I020cc74b73841e9599c4d1570829c6b086e768ec Signed-off-by: Chandan Kumar Jha --- drivers/cam_isp/cam_isp_context.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 94acea7e5ed9..80343c2957d2 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1266,7 +1266,6 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( "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, ctx->ctx_id); - WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out); } if (req_isp->num_acked != req_isp->num_fence_map_out) From 18f1c8147094e776ecc6b761fcab7d0aede7e91a Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Thu, 5 Nov 2020 16:20:35 +0530 Subject: [PATCH 636/790] msm: camera: ope: Add support to dynamic switch pix_pattern Add support to dynamically switch pix_pattern of read clients based on data received in each request. CRs-Fixed: 2811530 Change-Id: Icb3ebd33cae59b8db87bc0011d6560492ad29c3a Signed-off-by: Rishabh Jain --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 8 ++++++++ drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 1 + drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 2 +- include/uapi/camera/media/cam_ope.h | 4 ++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index d850833d720a..ec541cf6784d 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1978,6 +1978,14 @@ static int cam_ope_mgr_process_cmd_io_buf_req(struct cam_ope_hw_mgr *hw_mgr, alignment = in_res->alignment; unpack_format = in_res->unpacker_format; pack_format = 0; + if (in_io_buf->pix_pattern > + PIXEL_PATTERN_CRYCBY) { + CAM_ERR(CAM_OPE, + "Invalid pix pattern = %u", + in_io_buf->pix_pattern); + return -EINVAL; + } + io_buf->pix_pattern = in_io_buf->pix_pattern; } else if (in_io_buf->direction == CAM_BUF_OUTPUT) { out_res = &ctx_data->ope_acquire.out_res[rsc_idx]; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index 3d3d11598701..3bc09be0b88c 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -363,6 +363,7 @@ struct ope_io_buf { uint32_t format; uint32_t fence; uint32_t num_planes; + uint32_t pix_pattern; uint32_t num_stripes[OPE_MAX_PLANES]; struct ope_stripe_io s_io[OPE_MAX_PLANES][OPE_MAX_STRIPES]; }; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index 0042675f1821..033df2b6666d 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -244,7 +244,7 @@ static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info, temp = 0; temp |= stripe_io->s_location & rd_res_val_client->stripe_location_mask; - temp |= (io_port_info->pixel_pattern[rsc_type] & + temp |= (io_buf->pix_pattern & rd_res_val_client->pix_pattern_mask) << rd_res_val_client->pix_pattern_shift; temp_reg[count++] = temp; diff --git a/include/uapi/camera/media/cam_ope.h b/include/uapi/camera/media/cam_ope.h index cfd153cccd6e..d9badbcdff3d 100644 --- a/include/uapi/camera/media/cam_ope.h +++ b/include/uapi/camera/media/cam_ope.h @@ -104,7 +104,7 @@ struct ope_stripe_info { * @direction: Direction of a buffer of a port(Input/Output) * @resource_type: Port type * @num_planes: Number of planes for a port - * @reserved: Reserved + * @pix_pattern: Pixel pattern for raw input * @num_stripes: Stripes per plane * @mem_handle: Memhandles of each Input/Output Port * @plane_offset: Offsets of planes @@ -120,7 +120,7 @@ struct ope_io_buf_info { __u32 direction; __u32 resource_type; __u32 num_planes; - __u32 reserved; + __u32 pix_pattern; __u32 num_stripes[OPE_MAX_PLANES]; __u32 mem_handle[OPE_MAX_PLANES]; __u32 plane_offset[OPE_MAX_PLANES]; From 315ec1178d7568066df7ed965895645eb0489890 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 20 Nov 2020 03:40:37 +0530 Subject: [PATCH 637/790] msm: camera: cpas: Add support for Yupik camnoc Add register information. Initial QoS settings info to program camera static settings for chipsets having camera V165_100. CRs-Fixed: 2825675 Change-Id: I433cfbe50705f09b961770371a3d3f29ff5f348c Signed-off-by: Ayush Kumar --- Makefile | 9 + config/yupikcamera.conf | 18 + config/yupikcameraconf.h | 11 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 17 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 3 + drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 605 ++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 3 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 1 + 8 files changed, 667 insertions(+) create mode 100644 config/yupikcamera.conf create mode 100644 config/yupikcameraconf.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v165_100.h diff --git a/Makefile b/Makefile index dd08f9f140d6..44714b7440f5 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,10 @@ ifeq ($(CONFIG_ARCH_SHIMA), y) include $(srctree)/techpack/camera/config/shimacamera.conf endif +ifeq ($(CONFIG_ARCH_YUPIK), y) +include $(srctree)/techpack/camera/config/yupikcamera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h @@ -56,6 +60,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/shimacameraconf.h endif +ifeq ($(CONFIG_ARCH_YUPIK), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/yupikcameraconf.h +endif + endif ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) diff --git a/config/yupikcamera.conf b/config/yupikcamera.conf new file mode 100644 index 000000000000..7f259936c904 --- /dev/null +++ b/config/yupikcamera.conf @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2020, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=m +$(info "SPECTRA_CAMERA IS MODULAR") +else +$(info "SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_ICP=y +export CONFIG_SPECTRA_JPEG=y +export CONFIG_SPECTRA_LRME=y +endif diff --git a/config/yupikcameraconf.h b/config/yupikcameraconf.h new file mode 100644 index 000000000000..e40f43edaa9e --- /dev/null +++ b/config/yupikcameraconf.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_ICP 1 +#define CONFIG_SPECTRA_JPEG 1 +#define CONFIG_SPECTRA_LRME 1 diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index c5bbcbb79013..67faa3443260 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -30,6 +30,7 @@ #include "cpastop_v545_100.h" #include "cpastop_v570_200.h" #include "cpastop_v680_100.h" +#include "cpastop_v165_100.h" #include "cam_req_mgr_workq.h" struct cam_camnoc_info *camnoc_info; @@ -130,6 +131,15 @@ static const uint32_t cam_cpas_hw_version_map 0, CAM_CPAS_TITAN_570_V200, }, + /* for camera_165 */ + { + CAM_CPAS_TITAN_165_V100, + 0, + 0, + 0, + 0, + 0, + }, }; static int cam_cpas_translate_camera_cpas_version_id( @@ -181,6 +191,10 @@ static int cam_cpas_translate_camera_cpas_version_id( *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_680; break; + case CAM_CPAS_CAMERA_VERSION_165: + *cam_version_id = CAM_CPAS_CAMERA_VERSION_ID_165; + break; + default: CAM_ERR(CAM_CPAS, "Invalid cam version %u", cam_version); @@ -857,6 +871,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_680_V100: camnoc_info = &cam680_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_165_V100: + camnoc_info = &cam165_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/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 57bdf4100b8a..2d59122cab92 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -191,6 +191,9 @@ enum cam_camnoc_port_type { CAM_CAMNOC_TFE_1, CAM_CAMNOC_TFE_2, CAM_CAMNOC_OPE, + CAM_CAMNOC_IFE01234_RDI_WRITE, + CAM_CAMNOC_IFE01_NRDI_WRITE, + CAM_CAMNOC_IFE2_NRDI_WRITE, }; /** diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h new file mode 100644 index 000000000000..9d2bdfc92633 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -0,0 +1,605 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + + #ifndef _CPASTOP_V165_100_H_ + #define _CPASTOP_V165_100_H_ + + #define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v165_100_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 */ + (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_v165_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 = 0x4F08, /* ERL_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x4F10, /* ERL_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x4F18, /* ERL_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_IFE0_MAIN_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x3B90, + /* SPECIFIC_IFE0_MAIN_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x3B98, /* SPECIFIC_IFE0_MAIN_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_IFE1_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x5590, /* SPECIFIC_IFE1_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x5598, /* SPECIFIC_IFE1_WR_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 = false, + .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 = 0x40, /* 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_v165_100_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4230, /* CDM_PRIORITYLUT_LOW */ + .value = 0x0, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4234, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x0, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, /* CDM_Urgency_Low */ + .offset = 0x4238, + .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */ + .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */ + .value = 0x3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4240, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4248, /* CDM_SAFELUT_LOW */ + .value = 0xFFFF, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE01234_RDI_WRITE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3630, /* IFE01234_RDI_PRIORITYLUT_LOW */ + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3634, /* IFE01234_RDI_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3638, /* IFE01234_RDI_LINEAR_URGENCY_LOW */ + .mask = 0x1FF0, + .shift = 0x4, + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x3640, /* IFE01234_RDI_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x3648, /* IFE01234_RDI_SAFELUT_LOW */ + .value = 0x000F, + }, + .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_IFE01_NRDI_WRITE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3A30, /* IFE01_NRDI_PRIORITYLUT_LOW */ + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x3A34, /* IFE01_NRDI_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x3A38, /* IFE01_NRDI_URGENCY_LOW */ + /* IFE01_NRDI_URGENCY_LOW_WRITE_MASK */ + .mask = 0x1FF0, + /* IFE01_NRDI_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x3A40, /* IFE01_NRDI_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x3A48, /* IFE01_NRDI_SAFELUT_LOW */ + .value = 0xF, + }, + /* no reg for this */ + .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, /* IFE01_NRDI_ENCCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IFE2_NRDI_WRITE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5430, /* IFE2_NDRI_PRIORITYLUT_LOW */ + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* IFE2_NRDI_PRIORITYLUT_HIGH */ + .offset = 0x5434, + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x5438, /* IFE2_NRDI_URGENCY_LOW */ + /* IFE2_NRDI_URGENCY_LOW_WRITE_MASK */ + .mask = 0x1FF0, + /* IFE2_NRDI_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x1030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5440, /* IFE2_NRDI_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5448, /* IFE2_NRDI_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, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5588, /* IFE2_NRDI_ENCCTL_LOW */ + .value = 0, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E30, /* IPE_BPS_LRME_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, /*Value is 0 in excel sheet */ + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E34, /* IPE_BPS_LRME_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, /*Value is 0 in excel sheet */ + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x2E38, /* IPE_BPS_LRME_RD_URGENCY_LOW */ + /* IPE_BPS_LRME_RD_URGENCY_LOW_READ_MASK */ + .mask = 0x7, + /* IPE_BPS_LRME_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, /* IPE_BPS_LRME_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2E48, /* IPE_BPS_LRME_RD_SAFELUT_LOW */ + .value = 0xFFFF, + }, + .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, /* IPE_BPS_LRME_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, /* IPE_BPS_LRME_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2A34, /* IPE_BPS_LRME_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x2A38, /* IPE_BPS_LRME_WR_URGENCY_LOW */ + /* IPE_BPS_LRME_WR_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* IPE_BPS_LRME_WR_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2A40, /* IPE_BPS_LRME_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2A48, /* IPE_BPS_LRME_WR_SAFELUT_LOW */ + .value = 0xFFFF, + }, + .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, /* IPE_BPS_LRME_WR_ENCCTL_LOW */ + .value = 0, + }, + }, + { + .port_type = CAM_CAMNOC_JPEG, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2630, /* JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2634, /* JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x2638, /* JPEG_URGENCY_LOW */ + .mask = 0x3F, + .shift = 0x0, + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2640, /* JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x2648, /* JPEG_SAFELUT_LOW */ + .value = 0xFFFF, + }, + .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 = 0x5088, + .value = 0x50, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam165_cpas100_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 cam165_cpas100_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x2300, /* sbm_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam165_cpas100_camnoc_info = { + .specific = &cam_cpas_v165_100_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v165_100_camnoc_specific), + .irq_sbm = &cam_cpas_v165_100_irq_sbm, + .irq_err = &cam_cpas_v165_100_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v165_100_irq_err), + .err_logger = &cam165_cpas100_err_logger_offsets, + .errata_wa_list = &cam165_cpas100_errata_wa_list, +}; + +#endif /* _CPASTOP_V165_100_H_ */ + diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 5d288f54f6df..c96a25e1481d 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -68,6 +68,7 @@ enum cam_cpas_camera_version { CAM_CPAS_CAMERA_VERSION_545 = 0x00050405, CAM_CPAS_CAMERA_VERSION_570 = 0x00050700, CAM_CPAS_CAMERA_VERSION_680 = 0x00060800, + CAM_CPAS_CAMERA_VERSION_165 = 0x00010605, CAM_CPAS_CAMERA_VERSION_MAX }; @@ -100,6 +101,7 @@ enum cam_cpas_camera_version_map_id { CAM_CPAS_CAMERA_VERSION_ID_545 = 0x7, CAM_CPAS_CAMERA_VERSION_ID_570 = 0x8, CAM_CPAS_CAMERA_VERSION_ID_680 = 0x9, + CAM_CPAS_CAMERA_VERSION_ID_165 = 0xA, CAM_CPAS_CAMERA_VERSION_ID_MAX }; @@ -138,6 +140,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_545_V100 = 0x545100, CAM_CPAS_TITAN_570_V200 = 0x570200, CAM_CPAS_TITAN_680_V100 = 0x680100, + CAM_CPAS_TITAN_165_V100 = 0x165100, CAM_CPAS_TITAN_MAX }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index b60528dff714..0445ebf378d5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -62,6 +62,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) case CAM_CPAS_TITAN_480_V100: case CAM_CPAS_TITAN_580_V100: case CAM_CPAS_TITAN_570_V200: + case CAM_CPAS_TITAN_165_V100: num_ubwc_cfg = of_property_count_u32_elems(of_node, "ubwc-static-cfg"); From 92dbea0ccb1ddba631fead05c87492d4f8b398b1 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 26 Nov 2020 11:48:18 +0530 Subject: [PATCH 638/790] msm: camera: cpas: Add hw version checks for Yupik camera This change add titan hw version checks in csid, vfe and icp camera drivers for Yupik camera. CRs-Fixed: 2825675 Change-Id: Ibb704efa5eae327fc7c376328ceafc45a8217f44 Signed-off-by: Ayush Kumar --- drivers/cam_cpas/include/cam_cpas_api.h | 2 +- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 1 + .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 ++- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 5 ++++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c | 3 ++- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 3 ++- .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 3 ++- 7 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index c96a25e1481d..1179f3999922 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -125,6 +125,7 @@ enum cam_cpas_version_map_id { enum cam_cpas_hw_version { CAM_CPAS_TITAN_NONE = 0, CAM_CPAS_TITAN_150_V100 = 0x150100, + CAM_CPAS_TITAN_165_V100 = 0x165100, CAM_CPAS_TITAN_170_V100 = 0x170100, CAM_CPAS_TITAN_170_V110 = 0x170110, CAM_CPAS_TITAN_170_V120 = 0x170120, @@ -140,7 +141,6 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_545_V100 = 0x545100, CAM_CPAS_TITAN_570_V200 = 0x570200, CAM_CPAS_TITAN_680_V100 = 0x680100, - CAM_CPAS_TITAN_165_V100 = 0x165100, CAM_CPAS_TITAN_MAX }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b600e51b1fdb..b6e9cb1e4127 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1479,6 +1479,7 @@ static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx) break; case CAM_CPAS_TITAN_580_V100: case CAM_CPAS_TITAN_570_V200: + case CAM_CPAS_TITAN_165_V100: if (hw_idx == 0) return CAM_ISP_IFE0_HW; else if (hw_idx == 1) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 2748d8916286..55e09e1317a7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2559,7 +2559,8 @@ static int cam_ife_csid_init_config_rdi_path( if (camera_hw_version == CAM_CPAS_TITAN_480_V100 || camera_hw_version == CAM_CPAS_TITAN_175_V130 || camera_hw_version == CAM_CPAS_TITAN_580_V100 || - camera_hw_version == CAM_CPAS_TITAN_570_V200) { + camera_hw_version == CAM_CPAS_TITAN_570_V200 || + camera_hw_version == CAM_CPAS_TITAN_165_V100) { val |= (path_data->drop_enable << csid_reg->cmn_reg->drop_h_en_shift_val) | (path_data->drop_enable << diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index c7e77ac65e71..33d570c496a9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1269,7 +1269,8 @@ static int cam_vfe_bus_start_wm( } else if ((camera_hw_version == CAM_CPAS_TITAN_175_V100) || (camera_hw_version == CAM_CPAS_TITAN_175_V101) || (camera_hw_version == CAM_CPAS_TITAN_175_V120) || - (camera_hw_version == CAM_CPAS_TITAN_175_V130)) { + (camera_hw_version == CAM_CPAS_TITAN_175_V130) || + (camera_hw_version == CAM_CPAS_TITAN_165_V100)) { struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *ubwc_regs; @@ -2620,6 +2621,7 @@ static void cam_vfe_bus_update_ubwc_meta_addr( case CAM_CPAS_TITAN_175_V101: case CAM_CPAS_TITAN_175_V120: case CAM_CPAS_TITAN_175_V130: + case CAM_CPAS_TITAN_165_V100: ubwc_3_regs = (struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *) regs; @@ -2835,6 +2837,7 @@ static int cam_vfe_bus_update_ubwc_regs( case CAM_CPAS_TITAN_175_V101: case CAM_CPAS_TITAN_175_V120: case CAM_CPAS_TITAN_175_V130: + case CAM_CPAS_TITAN_165_V100: rc = cam_vfe_bus_update_ubwc_3_regs( wm_data, reg_val_pair, i, j); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c index 1c2f03c28e85..f239d20665da 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -427,7 +427,8 @@ static int cam_vfe_camif_lite_cpas_fifo_levels_reg_dump( uint32_t val; if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || - soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130 || + soc_private->cpas_version == CAM_CPAS_TITAN_165_V100) { rc = cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); if (rc) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 4a109ba7802d..f220e9ff5927 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -557,7 +557,8 @@ static int cam_vfe_camif_reg_dump( soc_private = camif_priv->soc_info->soc_private; if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || - soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130 || + soc_private->cpas_version == CAM_CPAS_TITAN_165_V100) { cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index 4b47cf722338..1d8863c741e8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -94,7 +94,8 @@ struct cam_vfe_mux_rdi_data *rdi_priv) uint32_t val; if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || - soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130 || + soc_private->cpas_version == CAM_CPAS_TITAN_165_V100) { rc = cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); if (rc) { From fd450fbd22d7067aa295b0d46d5cbedd945016de Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 7 Dec 2020 17:10:57 +0800 Subject: [PATCH 639/790] msm: camera: reqmgr: Pause the timer before sensor stream on Sometimes, the cpu load is very high, then the devcies stream on will be delayed, but the CRM watchdog is already enabled before streaming on, then we will have a chance to notify SOF freeze issue. This change pauses the CRM watchdog timer before streaming on sensor and after stopping ife, when we can detect the stream on and stream off delay, but don't notify error, also can detect the real SOF freeze issue. CRs-Fixed: 2804587 Change-Id: Iccaee837930ea22290b109eff45b05300d844312 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 19 ++++++++++++++++--- .../cam_sensor/cam_sensor_core.c | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 15ba9a7e9018..646cb6783f54 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2078,7 +2078,9 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) spin_lock_bh(&link->link_state_spin_lock); if ((link->watchdog) && (link->watchdog->pause_timer)) { - CAM_INFO(CAM_CRM, "Watchdog Paused"); + CAM_INFO(CAM_CRM, + "link:%x watchdog paused, maybe stream on/off is delayed", + link->link_hdl); spin_unlock_bh(&link->link_state_spin_lock); return rc; } @@ -3190,8 +3192,16 @@ static int cam_req_mgr_cb_notify_timer( rc = -EPERM; goto end; } - if ((link->watchdog) && (!timer_data->state)) - link->watchdog->pause_timer = true; + if (link->watchdog) { + if (!timer_data->state) + link->watchdog->pause_timer = true; + else + link->watchdog->pause_timer = false; + crm_timer_reset(link->watchdog); + CAM_DBG(CAM_CRM, "link %x pause_timer %d", + link->link_hdl, link->watchdog->pause_timer); + } + spin_unlock_bh(&link->link_state_spin_lock); end: @@ -3238,6 +3248,7 @@ static int cam_req_mgr_cb_notify_stop( goto end; } crm_timer_reset(link->watchdog); + link->watchdog->pause_timer = true; spin_unlock_bh(&link->link_state_spin_lock); task = cam_req_mgr_workq_get_task(link->workq); @@ -4286,6 +4297,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->link_hdl); rc = -EFAULT; } + /* Pause the timer before sensor stream on */ + link->watchdog->pause_timer = true; /* notify nodes */ for (j = 0; j < link->num_devs; j++) { dev = &link->l_dev[j]; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 413b5405045d..c1400a8ff99a 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -932,6 +932,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, break; } case CAM_START_DEV: { + struct cam_req_mgr_timer_notify timer; if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || (s_ctrl->sensor_state == CAM_SENSOR_START)) { rc = -EINVAL; @@ -952,6 +953,21 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } } s_ctrl->sensor_state = CAM_SENSOR_START; + + if (s_ctrl->bridge_intf.crm_cb && + s_ctrl->bridge_intf.crm_cb->notify_timer) { + timer.link_hdl = s_ctrl->bridge_intf.link_hdl; + timer.dev_hdl = s_ctrl->bridge_intf.device_hdl; + timer.state = true; + rc = s_ctrl->bridge_intf.crm_cb->notify_timer(&timer); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Enable CRM SOF freeze timer failed rc: %d", + rc); + return rc; + } + } + CAM_INFO(CAM_SENSOR, "CAM_START_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", s_ctrl->sensordata->slave_info.sensor_id, From 6d2e9d6d247291682a961bea49f22f5711fe0d99 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 20 Nov 2020 02:35:59 +0530 Subject: [PATCH 640/790] msm: camera: isp: Add header file changes This commit adds header file changes for version 165 hardware. CRs-Fixed: 2825675 Change-Id: Ib81be5bc02fbbe9c7d5174413cfd328fdca5599b Signed-off-by: Ayush Kumar --- .../isp_hw/ife_csid_hw/cam_ife_csid17x.c | 10 + .../isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c | 4 + .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c | 10 + .../isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h | 1164 +++++++++++++++++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h | 352 +++++ 5 files changed, 1540 insertions(+) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c index a59903040257..d5d571a62148 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c @@ -18,6 +18,7 @@ #define CAM_CSID_VERSION_V170 0x10070000 #define CAM_CSID_VERSION_V175 0x10070050 #define CAM_CSID_VERSION_V480 0x40080000 +#define CAM_CSID_VERSION_V165 0x10060050 static struct cam_ife_csid_hw_info cam_ife_csid170_hw_info = { .csid_reg = &cam_ife_csid_170_reg_offset, @@ -44,6 +45,11 @@ static struct cam_ife_csid_hw_info cam_ife_csid480_hw_info = { .hw_dts_version = CAM_CSID_VERSION_V480, }; +static struct cam_ife_csid_hw_info cam_ife_csid165_204_hw_info = { + .csid_reg = &cam_ife_csid_175_200_reg_offset, + .hw_dts_version = CAM_CSID_VERSION_V165, +}; + static const struct of_device_id cam_ife_csid17x_dt_match[] = { { .compatible = "qcom,csid170", @@ -69,6 +75,10 @@ static const struct of_device_id cam_ife_csid17x_dt_match[] = { .compatible = "qcom,csid580", .data = &cam_ife_csid480_hw_info, }, + { + .compatible = "qcom,csid165_204", + .data = &cam_ife_csid165_204_hw_info, + }, {} }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c index cf0174d6b60a..4dc530b182aa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c @@ -37,6 +37,10 @@ static const struct of_device_id cam_ife_csid_lite_dt_match[] = { .compatible = "qcom,csid-lite580", .data = &cam_ife_csid_lite_480_hw_info, }, + { + .compatible = "qcom,csid-lite165", + .data = &cam_ife_csid_lite_17x_hw_info, + }, {} }; MODULE_DEVICE_TABLE(of, cam_ife_csid_lite_dt_match); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c index 7bc27a1b63bc..75b39a3ebb52 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.c @@ -10,8 +10,10 @@ #include "cam_vfe175_130.h" #include "cam_vfe480.h" #include "cam_vfe580.h" +#include "cam_vfe165_160.h" #include "cam_vfe_lite17x.h" #include "cam_vfe_lite48x.h" +#include "cam_vfe_lite16x.h" #include "cam_vfe_hw_intf.h" #include "cam_vfe_core.h" #include "cam_vfe_dev.h" @@ -42,6 +44,10 @@ static const struct of_device_id cam_vfe_dt_match[] = { .compatible = "qcom,vfe580", .data = &cam_vfe580_hw_info, }, + { + .compatible = "qcom,vfe165_160", + .data = &cam_vfe165_160_hw_info, + }, { .compatible = "qcom,vfe-lite170", .data = &cam_vfe_lite17x_hw_info, @@ -58,6 +64,10 @@ static const struct of_device_id cam_vfe_dt_match[] = { .compatible = "qcom,vfe-lite580", .data = &cam_vfe_lite48x_hw_info, }, + { + .compatible = "qcom,vfe-lite165", + .data = &cam_vfe_lite16x_hw_info, + }, {} }; MODULE_DEVICE_TABLE(of, cam_vfe_dt_match); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h new file mode 100644 index 000000000000..1e28760bf2a9 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h @@ -0,0 +1,1164 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE165_160_H_ +#define _CAM_VFE165_160_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 vfe165_160_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_vfe_rdi_overflow_status vfe165_160_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + +static struct cam_irq_controller_reg_info vfe165_160_top_irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe165_160_top_irq_reg_set, + .global_clear_offset = 0x00000058, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_camif_ver2_reg vfe165_160_camif_reg = { + .dual_vfe_sync = 0x00000080, + .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_165_160_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, + .subscribe_irq_mask0 = 0x00000017, + .subscribe_irq_mask1 = 0x00000000, + .enable_diagnostic_hw = 0x1, +}; + +static struct cam_vfe_fe_ver1_reg vfe165_160_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_165_160_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 vfe165_160_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 + vfe165_160_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_err_irq_mask0 = 0x00400000, + .lite_err_irq_mask1 = 0x00004100, + .extern_reg_update_shift = 4, + .dual_pd_path_sel_shift = 24, +}; + +static struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_165_160_reg = { + .reset = 0x0000001C, + .cgc_ovd = 0x0000002C, + .enable = 0x00000040, +}; + +static struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_165_160_reg = { + .reset = 0x00000020, + .cgc_ovd = 0x00000030, + .enable = 0x00000044, +}; + +static struct cam_vfe_top_ver2_reg_offset_module_ctrl color_165_160_reg = { + .reset = 0x00000024, + .cgc_ovd = 0x00000034, + .enable = 0x00000048, +}; + +static struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_165_160_reg = { + .reset = 0x00000028, + .cgc_ovd = 0x00000038, + .enable = 0x0000004C, +}; + +static struct cam_vfe_top_ver2_reg_offset_common vfe165_160_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_165_160_reg, + &stats_165_160_reg, + &color_165_160_reg, + &zoom_165_160_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 vfe165_160_rdi_reg = { + .reg_update_cmd = 0x000004AC, +}; + +static struct cam_vfe_rdi_common_reg_data vfe165_160_rdi_reg_data = { + .subscribe_irq_mask0 = 0x780001E0, + .subscribe_irq_mask1 = 0x0, + .error_irq_mask0 = 0x0, + .error_irq_mask1 = 0x3C, +}; + +static struct cam_vfe_rdi_reg_data vfe_165_160_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_165_160_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_165_160_rdi_2_data = { + .reg_update_cmd_data = 0x8, + .sof_irq_mask = 0x20000000, + .reg_update_irq_mask = 0x80, +}; + +struct cam_vfe_top_dump_data vfe165_160_dump_data = { + .num_reg_dump_entries = 2, + .num_lut_dump_entries = 1, + .dmi_cfg = 0xc24, + .dmi_addr = 0xc28, + .dmi_data_path_hi = 0xc2C, + .dmi_data_path_lo = 0xc30, + .reg_entry = { + { + .reg_dump_start = 0x0, + .reg_dump_end = 0x1164, + }, + { + .reg_dump_start = 0x2000, + .reg_dump_end = 0x397C, + }, + }, + .lut_entry = { + { + .lut_word_size = 64, + .lut_bank_sel = 0x40, + .lut_addr_size = 180, + }, + }, +}; + +static struct cam_vfe_top_ver2_hw_info vfe165_160_top_hw_info = { + .common_reg = &vfe165_160_top_common_reg, + .camif_hw_info = { + .common_reg = &vfe165_160_top_common_reg, + .camif_reg = &vfe165_160_camif_reg, + .reg_data = &vfe_165_160_camif_reg_data, + }, + .camif_lite_hw_info = { + .common_reg = &vfe165_160_top_common_reg, + .camif_lite_reg = &vfe165_160_camif_lite_reg, + .reg_data = &vfe165_160_camif_lite_reg_data, + }, + .rdi_hw_info = { + .common_reg = &vfe165_160_top_common_reg, + .rdi_reg = &vfe165_160_rdi_reg, + .common_reg_data = &vfe165_160_rdi_reg_data, + .rdi_irq_status = &vfe165_160_rdi_irq_status, + .reg_data = { + &vfe_165_160_rdi_0_data, + &vfe_165_160_rdi_1_data, + &vfe_165_160_rdi_2_data, + NULL, + }, + }, + .fe_hw_info = { + .common_reg = &vfe165_160_top_common_reg, + .fe_reg = &vfe165_160_fe_reg, + .reg_data = &vfe_165_160_fe_reg_data, + }, + .num_mux = 6, + .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, + }, + .dump_data = &vfe165_160_dump_data, +}; + +static struct cam_irq_register_set vfe165_160_bus_rd_irq_reg[1] = { + { + .mask_reg_offset = 0x00005010, + .clear_reg_offset = 0x00005014, + .status_reg_offset = 0x0000501C, + }, +}; + +static struct cam_irq_register_set vfe165_160_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 + vfe165_160_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 + vfe165_160_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 + vfe165_160_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 + vfe165_160_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 vfe165_160_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 = vfe165_160_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, + .buf_size = 0x0000505C, + .stride = 0x00005060, + .unpacker_cfg = 0x00005064, + .latency_buf_allocation = 0x00005078, + .burst_limit = 0x00005080, + }, + }, + .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, + }, + }, + .top_irq_shift = 23, +}; + +static struct cam_vfe_bus_ver2_hw_info vfe165_160_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 = vfe165_160_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, + .debug_status_cfg = 0x0000226C, + .debug_status_0 = 0x00002270, + .top_irq_mask_0 = 0x0000005C, + }, + .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 = + &vfe165_160_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 = + &vfe165_160_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 = + &vfe165_160_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 = + &vfe165_160_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, + }, + }, + .top_irq_shift = 9, + .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 23, +}; + +static struct cam_vfe_hw_info cam_vfe165_160_hw_info = { + .irq_reg_info = &vfe165_160_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_2_0, + .bus_hw_info = &vfe165_160_bus_hw_info, + + .bus_rd_version = CAM_VFE_BUS_RD_VER_1_0, + .bus_rd_hw_info = &vfe165_160_bus_rd_hw_info, + + .top_version = CAM_VFE_TOP_VER_2_0, + .top_hw_info = &vfe165_160_top_hw_info, + + .camif_version = CAM_VFE_CAMIF_VER_2_0, + .camif_reg = &vfe165_160_camif_reg, + + .camif_lite_version = CAM_VFE_CAMIF_LITE_VER_2_0, + .camif_lite_reg = &vfe165_160_camif_lite_reg, + +}; + +#endif /* _CAM_VFE165_160_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h new file mode 100644 index 000000000000..e1d7a80f04a3 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h @@ -0,0 +1,352 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_LITE16X_H_ +#define _CAM_VFE_LITE16X_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 vfe16x_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 vfe16x_top_irq_reg_info = { + .num_registers = 2, + .irq_reg_set = vfe16x_top_irq_reg_set, + .global_clear_offset = 0x00000058, + .global_clear_bitmask = 0x00000001, +}; + +static struct cam_vfe_top_ver2_reg_offset_common vfe16x_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 vfe16x_rdi_reg = { + .reg_update_cmd = 0x000004AC, +}; + +static struct cam_vfe_rdi_common_reg_data vfe16x_rdi_reg_data = { + .subscribe_irq_mask0 = 0x780001E0, + .subscribe_irq_mask1 = 0x0, + .error_irq_mask0 = 0x0, + .error_irq_mask1 = 0x3C, +}; + +static struct cam_vfe_rdi_reg_data vfe16x_rdi_0_data = { + .reg_update_cmd_data = 0x2, + .sof_irq_mask = 0x8000000, + .reg_update_irq_mask = 0x20, +}; + +static struct cam_vfe_rdi_reg_data vfe16x_rdi_1_data = { + .reg_update_cmd_data = 0x4, + .sof_irq_mask = 0x10000000, + .reg_update_irq_mask = 0x40, +}; + +static struct cam_vfe_rdi_reg_data vfe16x_rdi_2_data = { + .reg_update_cmd_data = 0x8, + .sof_irq_mask = 0x20000000, + .reg_update_irq_mask = 0x80, +}; + +static struct cam_vfe_rdi_reg_data vfe16x_rdi_3_data = { + .reg_update_cmd_data = 0x10, + .sof_irq_mask = 0x40000000, + .reg_update_irq_mask = 0x100, +}; + +static struct cam_vfe_rdi_overflow_status vfe16x_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + +static struct cam_vfe_top_ver2_hw_info vfe16x_top_hw_info = { + .common_reg = &vfe16x_top_common_reg, + .camif_hw_info = { + .common_reg = NULL, + .camif_reg = NULL, + .reg_data = NULL, + }, + .rdi_hw_info = { + .common_reg = &vfe16x_top_common_reg, + .rdi_reg = &vfe16x_rdi_reg, + .common_reg_data = &vfe16x_rdi_reg_data, + .reg_data = { + &vfe16x_rdi_0_data, + &vfe16x_rdi_1_data, + &vfe16x_rdi_2_data, + &vfe16x_rdi_3_data, + }, + .rdi_irq_status = &vfe16x_rdi_irq_status, + }, + .num_mux = 4, + .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 vfe16x_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 vfe16x_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 = vfe16x_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, + .top_irq_mask_0 = 0x0000005C, + }, + .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, + }, + }, + .top_irq_shift = 9, + .support_consumed_addr = false, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 23, +}; + +static struct cam_vfe_hw_info cam_vfe_lite16x_hw_info = { + .irq_reg_info = &vfe16x_top_irq_reg_info, + + .bus_version = CAM_VFE_BUS_VER_2_0, + .bus_hw_info = &vfe16x_bus_hw_info, + + .top_version = CAM_VFE_TOP_VER_2_0, + .top_hw_info = &vfe16x_top_hw_info, + +}; + +#endif /* _CAM_VFE_LITE16X_H_ */ + From 797410a43f09f9a5f69754fee1d7cf3f38166c5e Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Mon, 30 Nov 2020 20:42:31 +0530 Subject: [PATCH 641/790] msm: camera: isp: Fix for disable UBWC case Sometimes multiple io cofigs comes before start_dev. Therefore even we force disable UBWC compression at start_dev time it can be override by those io configs. Therefore moving disable UBWC comp logic to acquire time. Acquire time a flag is sent if we have to enable or disable ubwc compression, based on this we set bus side ubwc_disable flag. When ever we start the WM or update the WM UBWC config we check this flag and based on this flag we override the ubwc_mode_cfg register. CRs-Fixed: 2833514 Change-Id: I8efc3f7abd53e0757f8e77ac0788e303f7c695b9 Signed-off-by: Wyes Karny --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 3 ++ drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 27 +++--------- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h | 2 - .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 - .../isp_hw/include/cam_vfe_hw_intf.h | 2 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 - .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 2 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h | 2 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 4 ++ .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 4 ++ .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 4 ++ .../isp_hw/vfe_hw/vfe17x/cam_vfe680.h | 4 ++ .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 43 +++++++++++++++---- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 2 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 30 +++++++++---- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 1 + 16 files changed, 90 insertions(+), 42 deletions(-) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 0301120b1978..7d79a46b251d 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -709,6 +709,9 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, if (*disable_ubwc_comp) { ubwc_ipe_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; ubwc_bps_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; + CAM_DBG(CAM_ICP, + "Force disable UBWC compression, ubwc_ipe_cfg: 0x%x, ubwc_bps_cfg: 0x%x", + ubwc_ipe_cfg[1], ubwc_bps_cfg[1]); } rc = hfi_cmd_ubwc_config_ext(&ubwc_ipe_cfg[0], &ubwc_bps_cfg[0]); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b6e9cb1e4127..12b03f42cf33 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1267,6 +1267,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi( vfe_acquire.vfe_out.split_id = CAM_ISP_HW_SPLIT_LEFT; vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; vfe_acquire.vfe_out.is_dual = 0; + vfe_acquire.vfe_out.disable_ubwc_comp = + g_ife_hw_mgr.debug_cfg.disable_ubwc_comp; vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; hw_intf = ife_src_res->hw_res[0]->hw_intf; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, @@ -1347,6 +1349,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel( vfe_acquire.vfe_out.out_port_info = out_port; vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_isp; vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index; + vfe_acquire.vfe_out.disable_ubwc_comp = + g_ife_hw_mgr.debug_cfg.disable_ubwc_comp; vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { @@ -4469,7 +4473,7 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_ife_hw_mgr_ctx *ctx; struct cam_isp_hw_mgr_res *hw_mgr_res; struct cam_isp_resource_node *rsrc_node = NULL; - uint32_t i, j, camif_debug, disable_ubwc_comp; + uint32_t i, camif_debug; bool res_rdi_context_set = false; uint32_t primary_rdi_src_res; uint32_t primary_rdi_out_res; @@ -4543,27 +4547,6 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } } - if (g_ife_hw_mgr.debug_cfg.disable_ubwc_comp) { - disable_ubwc_comp = 1; - for (i = 0; i < max_ife_out_res; i++) { - hw_mgr_res = &ctx->res_list_ife_out[i]; - for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { - if (!hw_mgr_res->hw_res[i]) - continue; - - rsrc_node = hw_mgr_res->hw_res[i]; - if (rsrc_node->hw_intf->hw_ops.process_cmd) { - rc = rsrc_node->hw_intf->hw_ops.process_cmd( - rsrc_node->hw_intf->hw_priv, - CAM_ISP_HW_CMD_DISABLE_UBWC_COMP, - &disable_ubwc_comp, - sizeof(disable_ubwc_comp)); - } - } - break; - } - } - rc = cam_ife_hw_mgr_init_hw(ctx); if (rc) { CAM_ERR(CAM_ISP, "Init failed"); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index a0bbf78b1941..6801260a0dd7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -23,8 +23,6 @@ #define CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS BIT(0) #define CAM_IFE_CUSTOM_CFG_SW_SYNC_ON BIT(1) -#define CAM_IFE_UBWC_COMP_EN BIT(1) - /** * struct cam_ife_hw_mgr_debug - contain the debug information * diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 21c0e0e27a90..64b22f7d7b62 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -133,7 +133,6 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CSID_CLOCK_DUMP, CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, - CAM_ISP_HW_CMD_DISABLE_UBWC_COMP, CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG, CAM_ISP_HW_CMD_QUERY_BUS_CAP, CAM_ISP_HW_CMD_MAX, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 1cb9ec7d8c6e..6c3213aec6c7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -141,6 +141,7 @@ struct cam_vfe_hw_vfe_bus_rd_acquire_args { * (Default is Master in case of Single VFE) * @dual_slave_core: If Master and Slave exists, HW Index of Slave * @cdm_ops: CDM operations + * @disable_ubwc_comp: Disable UBWC compression */ struct cam_vfe_hw_vfe_out_acquire_args { struct cam_isp_resource_node *rsrc_node; @@ -151,6 +152,7 @@ struct cam_vfe_hw_vfe_out_acquire_args { uint32_t is_master; uint32_t dual_slave_core; struct cam_cdm_utils_ops *cdm_ops; + bool disable_ubwc_comp; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index fa0a6b6221d9..6b0b2113bfe1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -617,7 +617,6 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: case CAM_ISP_HW_CMD_GET_RES_FOR_MID: - case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: case CAM_ISP_HW_CMD_QUERY_BUS_CAP: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index e9b21e3b2eaa..47a41f830163 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -238,6 +238,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_client ubwc_regs_client_3 = { .meta_stride = 0x00002540, .mode_cfg_0 = 0x00002544, .bw_limit = 0x000025A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_client ubwc_regs_client_4 = { @@ -249,6 +250,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_client ubwc_regs_client_4 = { .meta_stride = 0x00002640, .mode_cfg_0 = 0x00002644, .bw_limit = 0x000026A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h index 7be90ea08257..5d627632896d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h @@ -205,6 +205,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_client .meta_stride = 0x00002540, .mode_cfg_0 = 0x00002544, .bw_limit = 0x000025A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_client @@ -217,6 +218,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_client .meta_stride = 0x00002640, .mode_cfg_0 = 0x00002644, .bw_limit = 0x000026A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_hw_info vfe170_150_bus_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index 2328bf9f818e..fc92af8eec68 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -267,6 +267,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00002544, .mode_cfg_1 = 0x000025A4, .bw_limit = 0x000025A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -280,6 +281,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00002644, .mode_cfg_1 = 0x000026A4, .bw_limit = 0x000026A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -293,6 +295,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00003644, .mode_cfg_1 = 0x000036A4, .bw_limit = 0x000036A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -306,6 +309,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00003744, .mode_cfg_1 = 0x000037A4, .bw_limit = 0x000037A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 84fff673a597..a112779239f1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -338,6 +338,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00002544, .mode_cfg_1 = 0x000025A4, .bw_limit = 0x000025A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -351,6 +352,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00002644, .mode_cfg_1 = 0x000026A4, .bw_limit = 0x000026A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -364,6 +366,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00003644, .mode_cfg_1 = 0x000036A4, .bw_limit = 0x000036A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -377,6 +380,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00003744, .mode_cfg_1 = 0x000037A4, .bw_limit = 0x000037A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index d12ed2904f3e..4ef45cac2f51 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -340,6 +340,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x0000AC58, .off_lossy_var = 0x0000AC5C, .bw_limit = 0x0000AC1C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_reg_offset_ubwc_client @@ -353,6 +354,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x0000AD58, .off_lossy_var = 0x0000AD5C, .bw_limit = 0x0000AD1C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_reg_offset_ubwc_client @@ -366,6 +368,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x0000B058, .off_lossy_var = 0x0000B05C, .bw_limit = 0x0000B01C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_reg_offset_ubwc_client @@ -379,6 +382,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x0000B158, .off_lossy_var = 0x0000B15C, .bw_limit = 0x0000B11C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h index 2abeaff9cee7..12491937c037 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h @@ -142,6 +142,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x00000E58, .off_lossy_var = 0x00000E5C, .bw_limit = 0x00000E1C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_reg_offset_ubwc_client @@ -155,6 +156,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x00000F58, .off_lossy_var = 0x00000F5C, .bw_limit = 0x00000F1C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_reg_offset_ubwc_client @@ -168,6 +170,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x00001258, .off_lossy_var = 0x0000125C, .bw_limit = 0x0000121C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_reg_offset_ubwc_client @@ -181,6 +184,7 @@ static struct cam_vfe_bus_ver3_reg_offset_ubwc_client .lossy_thresh1 = 0x00001358, .off_lossy_var = 0x0000135C, .bw_limit = 0x0000131C, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 33d570c496a9..68622900b9a8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1259,11 +1259,19 @@ static int cam_vfe_bus_start_wm( (struct cam_vfe_bus_ver2_reg_offset_ubwc_client *) rsrc_data->hw_regs->ubwc_regs; + if (!ubwc_regs) { + CAM_ERR(CAM_ISP, "ubwc_regs is NULL"); + return -EINVAL; + } val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg_0); val |= 0x1; - if (disable_ubwc_comp) - val &= ~CAM_IFE_UBWC_COMP_EN; + if (disable_ubwc_comp) { + val &= ~ubwc_regs->ubwc_comp_en_bit; + CAM_DBG(CAM_ISP, + "Force disable UBWC compression, ubwc_mode_cfg: 0x%x", + val); + } cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg_0); } else if ((camera_hw_version == CAM_CPAS_TITAN_175_V100) || @@ -1278,11 +1286,19 @@ static int cam_vfe_bus_start_wm( (struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *) rsrc_data->hw_regs->ubwc_regs; + if (!ubwc_regs) { + CAM_ERR(CAM_ISP, "ubwc_regs is NULL"); + return -EINVAL; + } val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg_0); val |= 0x1; - if (disable_ubwc_comp) - val &= ~CAM_IFE_UBWC_COMP_EN; + if (disable_ubwc_comp) { + val &= ~ubwc_regs->ubwc_comp_en_bit; + CAM_DBG(CAM_ISP, + "Force disable UBWC compression, ubwc_mode_cfg: 0x%x", + val); + } cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg_0); } else { @@ -2069,6 +2085,8 @@ static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args, rsrc_data = rsrc_node->res_priv; rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->common_data->disable_ubwc_comp = + out_acquire_args->disable_ubwc_comp; rsrc_data->priv = acq_args->priv; secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->out_type); @@ -2687,6 +2705,13 @@ static int cam_vfe_bus_update_ubwc_3_regs( CAM_DBG(CAM_ISP, "WM %d meta stride 0x%x", wm_data->index, reg_val_pair[*j-1]); + if (wm_data->common_data->disable_ubwc_comp) { + wm_data->ubwc_mode_cfg_0 &= ~ubwc_regs->ubwc_comp_en_bit; + CAM_DBG(CAM_ISP, + "Force disable UBWC compression on VFE:%d WM:%d", + wm_data->common_data->core_index, wm_data->index); + } + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, ubwc_regs->mode_cfg_0, wm_data->ubwc_mode_cfg_0); CAM_DBG(CAM_ISP, "WM %d ubwc_mode_cfg_0 0x%x", @@ -2766,6 +2791,12 @@ static int cam_vfe_bus_update_ubwc_legacy_regs( CAM_DBG(CAM_ISP, "WM %d meta stride 0x%x", wm_data->index, reg_val_pair[*j-1]); + if (wm_data->common_data->disable_ubwc_comp) { + wm_data->ubwc_mode_cfg_0 &= ~ubwc_regs->ubwc_comp_en_bit; + CAM_DBG(CAM_ISP, + "Force disable UBWC compression on VFE:%d WM:%d", + wm_data->common_data->core_index, wm_data->index); + } CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, ubwc_regs->mode_cfg_0, wm_data->ubwc_mode_cfg_0); CAM_DBG(CAM_ISP, "WM %d ubwc_mode_cfg_0 0x%x", @@ -3693,10 +3724,6 @@ static int cam_vfe_bus_process_cmd( bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); break; - case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: - bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; - bus_priv->common_data.disable_ubwc_comp = true; - break; case CAM_ISP_HW_CMD_QUERY_BUS_CAP: bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; vfe_bus_cap = (struct cam_isp_hw_bus_cap *) cmd_args; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index 64884f184077..0a2726b6c7e8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -101,6 +101,7 @@ struct cam_vfe_bus_ver2_reg_offset_ubwc_client { uint32_t meta_stride; uint32_t mode_cfg_0; uint32_t bw_limit; + uint32_t ubwc_comp_en_bit; }; /* @@ -118,6 +119,7 @@ struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client { uint32_t mode_cfg_0; uint32_t mode_cfg_1; uint32_t bw_limit; + uint32_t ubwc_comp_en_bit; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index dd92dd72b987..d0c0822021c6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1424,10 +1424,22 @@ static int cam_vfe_bus_ver3_start_wm(struct cam_isp_resource_node *wm_res) /* enable ubwc if needed*/ if (rsrc_data->en_ubwc) { + if (!ubwc_regs) { + CAM_ERR(CAM_ISP, + "ubwc_regs is NULL, VFE:%d WM:%d en_ubwc:%d", + rsrc_data->common_data->core_index, + rsrc_data->index, rsrc_data->en_ubwc); + return -EINVAL; + } val = cam_io_r_mb(common_data->mem_base + ubwc_regs->mode_cfg); val |= 0x1; - if (disable_ubwc_comp) - val &= ~(0x1<<1); + if (disable_ubwc_comp) { + val &= ~ubwc_regs->ubwc_comp_en_bit; + CAM_DBG(CAM_ISP, + "Force disable UBWC compression, VFE:%d WM:%d ubwc_mode_cfg: 0x%x", + rsrc_data->common_data->core_index, + rsrc_data->index, val); + } cam_io_w_mb(val, common_data->mem_base + ubwc_regs->mode_cfg); } @@ -1972,6 +1984,8 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, rsrc_data = rsrc_node->res_priv; rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->common_data->disable_ubwc_comp = + out_acquire_args->disable_ubwc_comp; rsrc_data->priv = acq_args->priv; rsrc_data->bus_priv = ver3_bus_priv; comp_acq_args.composite_mask = (1 << vfe_out_res_id); @@ -2838,8 +2852,12 @@ static int cam_vfe_bus_ver3_update_ubwc_regs( CAM_DBG(CAM_ISP, "WM:%d meta stride 0x%X", wm_data->index, reg_val_pair[*j-1]); - if (wm_data->common_data->disable_ubwc_comp) - wm_data->ubwc_mode_cfg &= ~(0x1<<1); + if (wm_data->common_data->disable_ubwc_comp) { + wm_data->ubwc_mode_cfg &= ~ubwc_regs->ubwc_comp_en_bit; + CAM_DBG(CAM_ISP, + "Force disable UBWC compression on VFE:%d WM:%d", + wm_data->common_data->core_index, wm_data->index); + } CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, ubwc_regs->mode_cfg, wm_data->ubwc_mode_cfg); @@ -3698,10 +3716,6 @@ static int cam_vfe_bus_ver3_process_cmd( bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; rc = cam_vfe_bus_get_res_for_mid(bus_priv, cmd_args, arg_size); break; - case CAM_ISP_HW_CMD_DISABLE_UBWC_COMP: - bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; - bus_priv->common_data.disable_ubwc_comp = true; - break; case CAM_ISP_HW_CMD_QUERY_BUS_CAP: bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; vfe_bus_cap = (struct cam_isp_hw_bus_cap *) cmd_args; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index 50fd2e42443c..962b4535e2f9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -126,6 +126,7 @@ struct cam_vfe_bus_ver3_reg_offset_ubwc_client { uint32_t lossy_thresh1; uint32_t off_lossy_var; uint32_t bw_limit; + uint32_t ubwc_comp_en_bit; }; /* From 93e206364c57138e03b6d4d1159ca9bfd4a8448d Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 23 Nov 2020 11:43:14 +0530 Subject: [PATCH 642/790] msm: camera: icp: Increase hfi poll retry rate In certain scenarios, ICP init response was not received on time. Hence added retry logic to counter ICP init failures. CRs-Fixed: 2836166 Change-Id: Ibfab1e44e320dbcb1e1b47ba91d91c5ef2f9b3c1 Signed-off-by: Shravya Samala --- drivers/cam_icp/hfi.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 1d1d44b6a2f4..32b38cbb7c27 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -31,6 +31,7 @@ #define HFI_VERSION_INFO_STEP_BMSK 0xFF #define HFI_VERSION_INFO_STEP_SHFT 0 +#define HFI_MAX_POLL_TRY 5 #define HFI_POLL_DELAY_US 100 #define HFI_POLL_TIMEOUT_US 10000 @@ -649,10 +650,11 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, void *priv, uint8_t event_driven_mode) { int rc = 0; - uint32_t status = 0; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; + uint32_t fw_version, status = 0; + uint32_t retry_cnt = 0; struct sfr_buf *sfr_buffer; void __iomem *icp_base; @@ -838,17 +840,36 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); - if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), status, status == ICP_INIT_RESP_SUCCESS, - HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { - CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", - status); - rc = -ETIMEDOUT; + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US); + CAM_DBG(CAM_HFI, "1: status = %u rc = %d", status, rc); + status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); + CAM_DBG(CAM_HFI, "2: status = %u rc = %d", status, rc); + if (status == ICP_INIT_RESP_SUCCESS) + break; + + if (status == ICP_INIT_RESP_FAILED) { + CAM_ERR(CAM_HFI, + "ICP Init Failed. status %u fw version :[%x]", + status, fw_version); + goto regions_fail; + } + retry_cnt++; + } + + if ((retry_cnt == HFI_MAX_POLL_TRY) && + (status != ICP_INIT_RESP_SUCCESS)) { + CAM_ERR(CAM_HFI, + "Reached Max retries. status = %u fw version : [%x]", + status, fw_version); goto regions_fail; } - CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", - cam_io_r(icp_base + HFI_REG_FW_VERSION)); + CAM_INFO(CAM_HFI, "fw version : [%x]", fw_version); g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; From 0d76e160eb8f03cc197eea9c2bc1ad17cfa02730 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Wed, 9 Dec 2020 16:47:20 +0530 Subject: [PATCH 643/790] msm: camera: isp: Fix type mismatch arguments in indirect function calls To avoid CFI failures, fix type mismatch arguments in callback functions. CRs-Fixed: 2836088 Change-Id: Ib1d79ca3f4489081c909aeb9ead2e66ef20aed64 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 3 ++- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b6e9cb1e4127..941d1c46b280 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7583,7 +7583,8 @@ static int cam_ife_hw_mgr_find_affected_ctx( */ if (notify_err_cb) notify_err_cb(ife_hwr_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_ERROR, error_event_data); + CAM_ISP_HW_EVENT_ERROR, + (void *)error_event_data); else { CAM_WARN(CAM_ISP, "Error call back is not set"); goto end; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 13e093257b16..3aa2040baaa7 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5170,7 +5170,7 @@ static int cam_tfe_hw_mgr_find_affected_ctx( */ if (notify_err_cb) { notify_err_cb(tfe_hwr_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_ERROR, error_event_data); + CAM_ISP_HW_EVENT_ERROR, (void *)error_event_data); } else { CAM_WARN(CAM_ISP, "Error call back is not set"); goto end; @@ -5304,7 +5304,7 @@ static int cam_tfe_hw_mgr_handle_hw_rup( if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) break; tfe_hwr_irq_rup_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data); + CAM_ISP_HW_EVENT_REG_UPDATE, (void *)&rup_event_data); break; default: @@ -5336,7 +5336,8 @@ static int cam_tfe_hw_mgr_handle_hw_epoch( if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) break; tfe_hw_irq_epoch_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); + CAM_ISP_HW_EVENT_EPOCH, + (void *)&epoch_done_event_data); break; case CAM_ISP_HW_TFE_IN_RDI0: @@ -5377,7 +5378,7 @@ static int cam_tfe_hw_mgr_handle_hw_sof( break; tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data); break; @@ -5392,7 +5393,7 @@ static int cam_tfe_hw_mgr_handle_hw_sof( if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) break; tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_SOF, &sof_done_event_data); + CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data); break; default: @@ -5423,7 +5424,7 @@ static int cam_tfe_hw_mgr_handle_hw_eof( if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending)) break; tfe_hw_irq_eof_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + CAM_ISP_HW_EVENT_EOF, (void *)&eof_done_event_data); break; @@ -5466,7 +5467,7 @@ static int cam_tfe_hw_mgr_handle_hw_buf_done( if (buf_done_event_data.num_handles > 0 && tfe_hwr_irq_wm_done_cb) { CAM_DBG(CAM_ISP, "Notify ISP context"); tfe_hwr_irq_wm_done_cb(tfe_hw_mgr_ctx->common.cb_priv, - CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); + CAM_ISP_HW_EVENT_DONE, (void *)&buf_done_event_data); } CAM_DBG(CAM_ISP, "Buf done for out_res->res_id: 0x%x", From 2cfae8fecc125dc20f24d47b10fc3701c2190c18 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 14 Dec 2020 14:35:27 -0800 Subject: [PATCH 644/790] msm: camera: icp: Update a5 qos values post reset Update a5 R/W priorities post a5 reset. CRs-Fixed: 2834780 Change-Id: I81736f780c70a648b81f4cd05db7caa0bdcc5195 Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 0301120b1978..b1c331cd1d17 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -421,6 +421,8 @@ static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) { uint32_t val = A5_CSR_FULL_CPU_EN; void __iomem *base; + struct cam_hw_soc_info *soc_info = NULL; + struct a5_soc_info *a5_soc_info; if (!a5_info) { CAM_ERR(CAM_ICP, "invalid A5 device info"); @@ -428,6 +430,8 @@ static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) } base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + soc_info = &a5_info->soc_info; + a5_soc_info = soc_info->soc_private; cam_io_w_mb(A5_CSR_A5_CPU_EN, base + ICP_SIERRA_A5_CSR_A5_CONTROL); cam_io_w_mb(A5_CSR_FUNC_RESET, base + ICP_SIERRA_A5_CSR_NSEC_RESET); @@ -436,6 +440,11 @@ static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) val |= A5_CSR_FULL_DBG_EN; cam_io_w_mb(val, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + cam_io_w_mb(a5_soc_info->a5_qos_val, + base + ICP_SIERRA_A5_CSR_ACCESS); + + CAM_DBG(CAM_ICP, "a5 qos-val : 0x%x", + cam_io_r_mb(base + ICP_SIERRA_A5_CSR_ACCESS)); return 0; } From 91eddafa10695ae5e568536b03b59e7d2ad95d15 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 9 Dec 2020 18:53:23 +0530 Subject: [PATCH 645/790] msm: camera: isp: increase number of hw entries increase number of hw entries to allocate sufficient memory for cdm bl commands. CRs-Fixed: 2837487 Change-Id: Id890ab07cc66ef704a1317d545540f36dfc7f3c2 Signed-off-by: Alok Chauhan --- drivers/cam_isp/cam_isp_context.h | 5 ----- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 4 +--- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 3 +-- drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 6 ++++++ 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 6d9477d4fd7b..4a905a798380 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -28,11 +28,6 @@ /* max requests per ctx for isp */ #define CAM_ISP_CTX_REQ_MAX 8 -/* - * Maximum configuration entry size - This is based on the - * worst case DUAL IFE use case plus some margin. - */ -#define CAM_ISP_CTX_CFG_MAX 25 /* * Maximum entries in state monitoring array for error logging diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index b6e9cb1e4127..41bb945cada0 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -26,8 +26,6 @@ #include "cam_mem_mgr_api.h" #include "cam_common_util.h" -#define CAM_IFE_HW_ENTRIES_MAX 20 - #define CAM_IFE_SAFE_DISABLE 0 #define CAM_IFE_SAFE_ENABLE 1 #define SMMU_SE_IFE 0 @@ -8356,7 +8354,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) g_ife_hw_mgr.ctx_pool[i].cdm_cmd = kzalloc(((sizeof(struct cam_cdm_bl_request)) + - ((CAM_IFE_HW_ENTRIES_MAX - 1) * + ((CAM_ISP_CTX_CFG_MAX - 1) * sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); if (!g_ife_hw_mgr.ctx_pool[i].cdm_cmd) { rc = -ENOMEM; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 13e093257b16..f2de3ccec5c5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -26,7 +26,6 @@ #include "cam_req_mgr_debug.h" #include "cam_trace.h" -#define CAM_TFE_HW_ENTRIES_MAX 20 #define CAM_TFE_HW_CONFIG_TIMEOUT 60 #define CAM_TFE_HW_CONFIG_WAIT_MAX_TRY 3 @@ -5796,7 +5795,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) g_tfe_hw_mgr.ctx_pool[i].cdm_cmd = kzalloc(((sizeof(struct cam_cdm_bl_request)) + - ((CAM_TFE_HW_ENTRIES_MAX - 1) * + ((CAM_ISP_CTX_CFG_MAX - 1) * sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL); if (!g_tfe_hw_mgr.ctx_pool[i].cdm_cmd) { rc = -ENOMEM; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 4508752dba21..e093a8bccfbc 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -29,6 +29,12 @@ /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 40 +/* + * Maximum configuration entry size - This is based on the + * worst case DUAL IFE use case plus some margin. + */ +#define CAM_ISP_CTX_CFG_MAX 25 + /** * enum cam_isp_hw_event_type - Collection of the ISP hardware events */ From 5a5062ae18cbb39ec71e0006f788a2a065540cd4 Mon Sep 17 00:00:00 2001 From: Mohit Sharma Date: Tue, 15 Dec 2020 15:57:07 +0530 Subject: [PATCH 646/790] Revert "msm: camera: icp: Increase hfi poll retry rate" This reverts commit 36db836a81b4ae73e979d60fe912272dca35f0ad. Change-Id: Icda8b7af176e566adb296316f820725a4869dea9 Signed-off-by: Mohit Sharma --- drivers/cam_icp/hfi.c | 42 ++++++++---------------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 4909343d6d16..1d1d44b6a2f4 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -31,7 +31,6 @@ #define HFI_VERSION_INFO_STEP_BMSK 0xFF #define HFI_VERSION_INFO_STEP_SHFT 0 -#define HFI_MAX_POLL_TRY 5 #define HFI_POLL_DELAY_US 100 #define HFI_POLL_TIMEOUT_US 10000 @@ -650,11 +649,10 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, void *priv, uint8_t event_driven_mode) { int rc = 0; + uint32_t status = 0; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; - uint32_t fw_version, status = 0; - uint32_t retry_cnt = 0; struct sfr_buf *sfr_buffer; void __iomem *icp_base; @@ -840,41 +838,17 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - - while (retry_cnt < HFI_MAX_POLL_TRY) { - readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), + if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, status, status == ICP_INIT_RESP_SUCCESS, - HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US); - CAM_DBG(CAM_HFI, "1: status = %u rc = %d", status, rc); - status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); - CAM_DBG(CAM_HFI, "2: status = %u rc = %d", status, rc); - if (status == ICP_INIT_RESP_SUCCESS) - break; - - if (status == ICP_INIT_RESP_FAILED) { - CAM_ERR(CAM_HFI, "ICP Init Failed. status = %u", - status); - CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); - goto regions_fail; - } - retry_cnt++; - } - - if ((retry_cnt == HFI_MAX_POLL_TRY) && - (status != ICP_INIT_RESP_SUCCESS)) { - CAM_ERR(CAM_HFI, "Reached Max retries. status = %u", - status); - CAM_ERR(CAM_HFI, "fw version : [%x]", fw_version); - - status = - cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); - if (status != ICP_INIT_RESP_SUCCESS) - BUG(); + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { + CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", + status); + rc = -ETIMEDOUT; goto regions_fail; } - CAM_WARN(CAM_HFI, "fw version : [%x]", fw_version); + CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", + cam_io_r(icp_base + HFI_REG_FW_VERSION)); g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; From ed833dc42a3dd2813784e8d116bd85354783cdcd Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 23 Nov 2020 11:43:14 +0530 Subject: [PATCH 647/790] msm: camera: icp: Increase hfi poll retry rate In certain scenarios, ICP init response was not received on time. Hence added retry logic to counter ICP init failures. CRs-Fixed: 2836166 Change-Id: I8066ab09a4809acd71be8981b46b5030ab3ebb01 Signed-off-by: Shravya Samala --- drivers/cam_icp/hfi.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 1d1d44b6a2f4..32b38cbb7c27 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -31,6 +31,7 @@ #define HFI_VERSION_INFO_STEP_BMSK 0xFF #define HFI_VERSION_INFO_STEP_SHFT 0 +#define HFI_MAX_POLL_TRY 5 #define HFI_POLL_DELAY_US 100 #define HFI_POLL_TIMEOUT_US 10000 @@ -649,10 +650,11 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, void *priv, uint8_t event_driven_mode) { int rc = 0; - uint32_t status = 0; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; + uint32_t fw_version, status = 0; + uint32_t retry_cnt = 0; struct sfr_buf *sfr_buffer; void __iomem *icp_base; @@ -838,17 +840,36 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); - if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, + fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + + while (retry_cnt < HFI_MAX_POLL_TRY) { + readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE), status, status == ICP_INIT_RESP_SUCCESS, - HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { - CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", - status); - rc = -ETIMEDOUT; + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US); + CAM_DBG(CAM_HFI, "1: status = %u rc = %d", status, rc); + status = cam_io_r_mb(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE); + CAM_DBG(CAM_HFI, "2: status = %u rc = %d", status, rc); + if (status == ICP_INIT_RESP_SUCCESS) + break; + + if (status == ICP_INIT_RESP_FAILED) { + CAM_ERR(CAM_HFI, + "ICP Init Failed. status %u fw version :[%x]", + status, fw_version); + goto regions_fail; + } + retry_cnt++; + } + + if ((retry_cnt == HFI_MAX_POLL_TRY) && + (status != ICP_INIT_RESP_SUCCESS)) { + CAM_ERR(CAM_HFI, + "Reached Max retries. status = %u fw version : [%x]", + status, fw_version); goto regions_fail; } - CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", - cam_io_r(icp_base + HFI_REG_FW_VERSION)); + CAM_INFO(CAM_HFI, "fw version : [%x]", fw_version); g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; From 8fcc66faf4a7f37b7f9f63fb37066eccc5300faf Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Tue, 24 Nov 2020 16:34:52 +0530 Subject: [PATCH 648/790] msm: camera: cdm: Added cdm power state check There is chance that handle error info get scheduled after cdm deinit. As clock and regulator gets disabled as part of deinit so this can cause issue for cdm hw interaction as part of handle error. Added cdm power state check before dumping CDM HW status at the time of error. CRs-Fixed: 2833653 Change-Id: I4bf01ce3900196909cf66ffdb24607c50ab03295 Signed-off-by: Alok Chauhan --- drivers/cam_cdm/cam_cdm_hw_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index d1db45011049..cfa6684175ae 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1647,6 +1647,11 @@ int cam_hw_cdm_handle_error_info( set_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); set_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); + if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { + CAM_WARN(CAM_CDM, "CDM is in power down state"); + goto end; + } + /* First pause CDM, If it fails still proceed to dump debug info */ cam_hw_cdm_pause_core(cdm_hw, true); From 7809f88ad5d311cf20f4e0615b068f924f3dedd3 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 14 Dec 2020 14:36:30 -0800 Subject: [PATCH 649/790] msm: camera: csiphy: Update the csiphy logging Update the csiphy logging for better debugging purpose. CRs-Fixed: 2839060 Change-Id: I8af110ae895ee09cdf9404d0e6d6165188a6db55 Signed-off-by: Jigar Agrawal --- .../cam_csiphy/cam_csiphy_core.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 6eda1796590d..edbde5a6c401 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1176,12 +1176,6 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - CAM_INFO(CAM_CSIPHY, - "STOP_DEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", - csiphy_dev->soc_info.index, offset, - csiphy_dev->csiphy_info[offset].data_rate, - csiphy_dev->csiphy_info[offset].settle_time); - if (--csiphy_dev->start_dev_count) { CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d", csiphy_dev->start_dev_count); @@ -1219,6 +1213,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, CAM_DBG(CAM_CSIPHY, "All PHY devices stopped"); csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; + + CAM_INFO(CAM_CSIPHY, + "CAM_STOP_PHYDEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", + csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].data_rate, + csiphy_dev->csiphy_info[offset].settle_time); } break; case CAM_RELEASE_DEV: { @@ -1327,13 +1327,6 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - CAM_INFO(CAM_CSIPHY, - "CAM_START_PHYDEV: CSIPHY_IDX: %d, Device_slot: %d, cp_mode: %d, Datarate: %llu, Settletime: %llu", - csiphy_dev->soc_info.index, offset, - csiphy_dev->csiphy_info[offset].secure_mode, - csiphy_dev->csiphy_info[offset].data_rate, - csiphy_dev->csiphy_info[offset].settle_time); - if (csiphy_dev->start_dev_count) { clk_vote_level = csiphy_dev->ctrl_reg->getclockvoting( @@ -1454,6 +1447,13 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, CAM_DBG(CAM_CSIPHY, "START DEV CNT: %d", csiphy_dev->start_dev_count); csiphy_dev->csiphy_state = CAM_CSIPHY_START; + + CAM_INFO(CAM_CSIPHY, + "CAM_START_PHYDEV: CSIPHY_IDX: %d, Device_slot: %d, cp_mode: %d, Datarate: %llu, Settletime: %llu", + csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].secure_mode, + csiphy_dev->csiphy_info[offset].data_rate, + csiphy_dev->csiphy_info[offset].settle_time); } break; case CAM_CONFIG_DEV_EXTERNAL: { From 8d269581d06ca1a718a374e884ca34d1499edaf7 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Wed, 9 Dec 2020 14:12:33 -0800 Subject: [PATCH 650/790] msm: camera: cdm: Improve cdm logging Improve the CDM logging for better debugging purpose. CRs-Fixed: 2836601 Change-Id: I75213e17edf2fb42204a6e3d983a76892362b1d4 Signed-off-by: Jigar Agrawal --- drivers/cam_cdm/cam_cdm_hw_core.c | 162 +++++++++++++++++++++--------- 1 file changed, 117 insertions(+), 45 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index d1db45011049..b7360304b26c 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -163,7 +163,9 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause) if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, val)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW core_en"); + CAM_ERR(CAM_CDM, "Failed to Write core_en for %s%u", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); rc = -EIO; } @@ -319,6 +321,8 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, &dump_reg[2]); + CAM_INFO(CAM_CDM, "Dumping debug data for %s%u", + cdm_hw->soc_info.label_name, cdm_hw->soc_info.index); CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x", dump_reg[0], dump_reg[1], dump_reg[2]); @@ -464,7 +468,9 @@ int cam_hw_cdm_set_cdm_blfifo_cfg(struct cam_hw_info *cdm_hw) core->offsets->irq_reg[i]->irq_mask, 0x70003); if (rc) { CAM_ERR(CAM_CDM, - "Unable to write to cdm irq mask register"); + "Unable to write to %s%u irq mask register", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); rc = -EIO; goto end; } @@ -478,7 +484,9 @@ int cam_hw_cdm_set_cdm_blfifo_cfg(struct cam_hw_info *cdm_hw) << CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT); if (rc) { CAM_ERR(CAM_CDM, - "Unable to write to cdm irq mask register"); + "Unable to write to %s%u irq mask register", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); rc = -EIO; goto end; } @@ -506,7 +514,9 @@ int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) if (cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->cdm_hw_version, &cdm_version)) { - CAM_ERR(CAM_CDM, "Error reading CDM register"); + CAM_ERR(CAM_CDM, "Error reading %s%u register", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); rc = -EIO; goto end; } @@ -529,7 +539,9 @@ int cam_hw_cdm_set_cdm_core_cfg(struct cam_hw_info *cdm_hw) rc = cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_cfg, cfg_mask); if (rc) { - CAM_ERR(CAM_CDM, "Error writing cdm core cfg"); + CAM_ERR(CAM_CDM, "Error writing %s%u core cfg", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); rc = -EIO; goto end; } @@ -863,6 +875,8 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw, fifo_idx = CAM_CDM_GET_BLFIFO_IDX(client->handle); + CAM_DBG(CAM_CDM, "Submit bl to %s%u", cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); if (fifo_idx >= CAM_CDM_BL_FIFO_MAX) { rc = -EINVAL; CAM_ERR(CAM_CDM, "Invalid handle 0x%x, rc = %d", @@ -1202,7 +1216,9 @@ static void cam_hw_cdm_work(struct work_struct *work) .last_bl_tag_done); if (payload->irq_data == 0xff) { - CAM_INFO(CAM_CDM, "Debug genirq received"); + CAM_INFO(CAM_CDM, "%s%u Debug genirq received", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); kfree(payload); payload = NULL; return; @@ -1264,7 +1280,9 @@ static void cam_hw_cdm_work(struct work_struct *work) if (payload->irq_status & CAM_CDM_IRQ_STATUS_BL_DONE_MASK) { if (test_bit(payload->fifo_idx, &core->cdm_status)) { - CAM_DBG(CAM_CDM, "CDM HW BL done IRQ"); + CAM_DBG(CAM_CDM, "%s%u HW BL done IRQ", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); complete(&core->bl_fifo[payload->fifo_idx] .bl_complete); } @@ -1274,8 +1292,9 @@ static void cam_hw_cdm_work(struct work_struct *work) int reset_hw_hdl = 0x0; CAM_ERR_RATE_LIMIT(CAM_CDM, - "CDM Error IRQ status %d\n", - payload->irq_status); + "%s%u Error IRQ status %d\n", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index, payload->irq_status); set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); mutex_lock(&cdm_hw->hw_mutex); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; @@ -1347,7 +1366,9 @@ static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); } else - CAM_INFO(CAM_CDM, "CDM hw is power in off state"); + CAM_INFO(CAM_CDM, "%s%u hw is power in off state", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); mutex_unlock(&cdm_hw->hw_mutex); @@ -1365,6 +1386,7 @@ static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) { struct cam_hw_info *cdm_hw = data; + struct cam_hw_soc_info *soc_info = &cdm_hw->soc_info; struct cam_cdm *cdm_core = cdm_hw->core_info; struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0}; uint8_t rst_done_cnt = 0; @@ -1374,7 +1396,9 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) bool work_status; int i; - CAM_DBG(CAM_CDM, "Got irq hw_version 0x%x", cdm_core->hw_version); + CAM_DBG(CAM_CDM, "Got irq hw_version 0x%x from %s%u", + cdm_core->hw_version, soc_info->label_name, + soc_info->index); spin_lock(&cdm_hw->hw_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_DBG(CAM_CDM, "CDM is in power down state"); @@ -1395,23 +1419,30 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) if (cam_cdm_read_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_status, &irq_status[i])) { - CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status"); + CAM_ERR(CAM_CDM, "Failed to read %s%u HW IRQ status", + soc_info->label_name, + soc_info->index); } if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_clear, irq_status[i])) { - CAM_ERR(CAM_CDM, - "Failed to Write CDM HW IRQ Clear"); + CAM_ERR(CAM_CDM, "Failed to Write %s%u HW IRQ Clear", + soc_info->label_name, + soc_info->index); } } if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[0]->irq_clear_cmd, 0x01)) - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ clr cmd"); + CAM_ERR(CAM_CDM, "Failed to Write %s%u HW IRQ clr cmd", + soc_info->label_name, + soc_info->index); if (cam_cdm_read_hw_reg(cdm_hw, cdm_core->offsets->cmn_reg->usr_data, &user_data)) - CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ data"); + CAM_ERR(CAM_CDM, "Failed to read %s%u HW IRQ data", + soc_info->label_name, + soc_info->index); spin_unlock(&cdm_hw->hw_lock); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { @@ -1460,8 +1491,9 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_clear, payload[i]->irq_status)) { - CAM_ERR(CAM_CDM, - "Failed to Write CDM HW IRQ Clear"); + CAM_ERR(CAM_CDM, "Failed to Write %s%u HW IRQ Clear", + soc_info->label_name, + soc_info->index); kfree(payload[i]); return IRQ_HANDLED; } @@ -1482,14 +1514,17 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) } } if (rst_done_cnt == cdm_core->offsets->reg_data->num_bl_fifo_irq) { - CAM_DBG(CAM_CDM, "CDM HW reset done IRQ"); + CAM_DBG(CAM_CDM, "%s%u HW reset done IRQ", + soc_info->label_name, + soc_info->index); complete(&cdm_core->reset_complete); } if (rst_done_cnt && (rst_done_cnt != cdm_core->offsets->reg_data->num_bl_fifo_irq)) CAM_INFO(CAM_CDM, - "Reset IRQ received for %d fifos instead of %d", - rst_done_cnt, + "%s%u Reset IRQ received for %d fifos instead of %d", + soc_info->label_name, + soc_info->index, rst_done_cnt, cdm_core->offsets->reg_data->num_bl_fifo_irq); return IRQ_HANDLED; } @@ -1559,6 +1594,7 @@ int cam_hw_cdm_release_genirq_mem(void *hw_priv) int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) { struct cam_cdm *cdm_core = NULL; + struct cam_hw_soc_info *soc_info = &cdm_hw->soc_info; long time_left; int i, rc = -EIO; int reset_val = 1; @@ -1585,36 +1621,47 @@ int cam_hw_cdm_reset_hw(struct cam_hw_info *cdm_hw, uint32_t handle) if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_mask, 0x70003)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask"); + CAM_ERR(CAM_CDM, "Failed to Write %s%u HW IRQ mask", + soc_info->label_name, + soc_info->index); goto end; } } if (cam_cdm_write_hw_reg(cdm_hw, cdm_core->offsets->cmn_reg->rst_cmd, reset_val)) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); + CAM_ERR(CAM_CDM, "Failed to Write %s%u HW reset", + soc_info->label_name, + soc_info->index); goto end; } - CAM_DBG(CAM_CDM, "Waiting for CDM HW reset done"); + CAM_DBG(CAM_CDM, "Waiting for %s%u HW reset done", + soc_info->label_name, soc_info->index); time_left = wait_for_completion_timeout(&cdm_core->reset_complete, msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); if (time_left <= 0) { rc = -ETIMEDOUT; - CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + CAM_ERR(CAM_CDM, "%s%u HW reset Wait failed rc=%d", + soc_info->label_name, + soc_info->index, rc); goto end; } rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); if (rc) { - CAM_ERR(CAM_CDM, "Failed to configure CDM rc=%d", rc); + CAM_ERR(CAM_CDM, "Failed to configure %s%u rc=%d", + soc_info->label_name, + soc_info->index, rc); goto end; } rc = cam_hw_cdm_set_cdm_blfifo_cfg(cdm_hw); if (rc) { - CAM_ERR(CAM_CDM, "Failed to configure CDM fifo rc=%d", rc); + CAM_ERR(CAM_CDM, "Failed to configure %s%u fifo rc=%d", + soc_info->label_name, + soc_info->index, rc); goto end; } @@ -1637,6 +1684,7 @@ int cam_hw_cdm_handle_error_info( int i, rc = -EIO, reset_hw_hdl = 0x0; uint32_t current_bl_data = 0, current_fifo = 0, current_tag = 0; int reset_val = 1; + struct cam_hw_soc_info *soc_info = &cdm_hw->soc_info; cdm_core = (struct cam_cdm *)cdm_hw->core_info; @@ -1664,7 +1712,8 @@ int cam_hw_cdm_handle_error_info( goto end; } - CAM_ERR(CAM_CDM, "Hang detected for fifo %d with tag 0x%x", + CAM_ERR(CAM_CDM, "Hang detected for %s%u's fifo %d with tag 0x%x", + soc_info->label_name, soc_info->index, current_fifo, current_tag); /* dump cdm registers for further debug */ @@ -1807,14 +1856,16 @@ int cam_hw_cdm_get_cdm_config(struct cam_hw_info *cdm_hw) soc_info->dev_name); goto end; } else { - CAM_DBG(CAM_CDM, "CDM init success"); + CAM_DBG(CAM_CDM, "%s%u init success", + soc_info->label_name, soc_info->index); cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; } if (cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->cdm_hw_version, &core->hw_version)) { - CAM_ERR(CAM_CDM, "Failed to read CDM HW Version"); + CAM_ERR(CAM_CDM, "Failed to read HW Version for %s%u", + soc_info->label_name, soc_info->index); rc = -EIO; goto disable_platform_resource; } @@ -1823,14 +1874,16 @@ int cam_hw_cdm_get_cdm_config(struct cam_hw_info *cdm_hw) if (cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->cam_version->hw_version, &core->hw_family_version)) { - CAM_ERR(CAM_CDM, "Failed to read CDM family Version"); + CAM_ERR(CAM_CDM, "Failed to read %s%d family Version", + soc_info->label_name, soc_info->index); rc = -EIO; goto disable_platform_resource; } } CAM_DBG(CAM_CDM, - "CDM Hw version read success family =%x hw =%x", + "%s%d Hw version read success family =%x hw =%x", + soc_info->label_name, soc_info->index, core->hw_family_version, core->hw_version); core->ops = cam_cdm_get_ops(core->hw_version, NULL, @@ -1850,7 +1903,8 @@ disable_platform_resource: CAM_ERR(CAM_CDM, "disable platform failed for dev %s", soc_info->dev_name); } else { - CAM_DBG(CAM_CDM, "CDM Deinit success"); + CAM_DBG(CAM_CDM, "%s%d Deinit success", + soc_info->label_name, soc_info->index); cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN; } end: @@ -1875,14 +1929,16 @@ int cam_hw_cdm_init(void *hw_priv, rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_SVS_VOTE, true); if (rc) { - CAM_ERR(CAM_CDM, "Enable platform failed"); + CAM_ERR(CAM_CDM, "Enable platform failed for %s%d", + soc_info->label_name, soc_info->index); goto end; } spin_lock_irqsave(&cdm_hw->hw_lock, flags); cdm_hw->hw_state = CAM_HW_STATE_POWER_UP; spin_unlock_irqrestore(&cdm_hw->hw_lock, flags); - CAM_DBG(CAM_CDM, "Enable soc done"); + CAM_DBG(CAM_CDM, "Enable soc done for %s%d", + soc_info->label_name, soc_info->index); /* Before triggering the reset to HW, clear the reset complete */ clear_bit(CAM_CDM_ERROR_HW_STATUS, &cdm_core->cdm_status); @@ -1899,10 +1955,13 @@ int cam_hw_cdm_init(void *hw_priv, rc = cam_hw_cdm_reset_hw(cdm_hw, reset_hw_hdl); if (rc) { - CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + CAM_ERR(CAM_CDM, "%s%u HW reset Wait failed rc=%d", + soc_info->label_name, + soc_info->index, rc); goto disable_return; } else { - CAM_DBG(CAM_CDM, "CDM Init success"); + CAM_DBG(CAM_CDM, "%s%u Init success", + soc_info->label_name, soc_info->index); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { if (!cdm_core->bl_fifo[i].bl_depth) continue; @@ -1981,13 +2040,15 @@ int cam_hw_cdm_deinit(void *hw_priv, CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset"); } - CAM_DBG(CAM_CDM, "Waiting for CDM HW reset done"); + CAM_DBG(CAM_CDM, "Waiting for %s%u HW reset done", + soc_info->label_name, soc_info->index); time_left = wait_for_completion_timeout(&cdm_core->reset_complete, msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT)); if (time_left <= 0) { rc = -ETIMEDOUT; - CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); + CAM_ERR(CAM_CDM, "%s%u HW reset Wait failed rc=%d", + soc_info->label_name, soc_info->index, rc); } clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); @@ -1999,9 +2060,11 @@ int cam_hw_cdm_deinit(void *hw_priv, spin_unlock_irqrestore(&cdm_hw->hw_lock, flags); rc = cam_soc_util_disable_platform_resource(soc_info, true, true); if (rc) { - CAM_ERR(CAM_CDM, "disable platform failed"); + CAM_ERR(CAM_CDM, "disable platform failed for %s%u", + soc_info->label_name, soc_info->index); } else { - CAM_DBG(CAM_CDM, "CDM Deinit success"); + CAM_DBG(CAM_CDM, "%s%u Deinit success", + soc_info->label_name, soc_info->index); } return rc; @@ -2136,7 +2199,10 @@ static int cam_hw_cdm_component_bind(struct device *dev, rc = cam_soc_util_request_platform_resource(&cdm_hw->soc_info, cam_hw_cdm_irq, cdm_hw); if (rc) { - CAM_ERR(CAM_CDM, "Failed to request platform resource"); + CAM_ERR(CAM_CDM, + "Failed to request platform resource for %s%u", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); goto destroy_non_secure_hdl; } cpas_parms.cam_cpas_client_cb = cam_cdm_cpas_cb; @@ -2198,7 +2264,9 @@ static int cam_hw_cdm_component_bind(struct device *dev, rc = cam_hw_cdm_init(cdm_hw, NULL, 0); if (rc) { - CAM_ERR(CAM_CDM, "Failed to Init CDM HW"); + CAM_ERR(CAM_CDM, "Failed to Init %s%u HW", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); goto cpas_stop; } cdm_hw->open_count++; @@ -2207,7 +2275,9 @@ static int cam_hw_cdm_component_bind(struct device *dev, false); if (!cdm_core->ops) { - CAM_ERR(CAM_CDM, "Failed to util ops for hw"); + CAM_ERR(CAM_CDM, "Failed to util ops for %s%u HW", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); rc = -EINVAL; goto deinit; } @@ -2221,7 +2291,9 @@ static int cam_hw_cdm_component_bind(struct device *dev, rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); if (rc) { - CAM_ERR(CAM_CDM, "Failed to Deinit CDM HW"); + CAM_ERR(CAM_CDM, "Failed to Deinit %s%u HW", + cdm_hw->soc_info.label_name, + cdm_hw->soc_info.index); cdm_hw->open_count--; goto cpas_stop; } From 540afc09e91d3bef7122ab436cb508122b03fef3 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 14 Dec 2020 14:35:27 -0800 Subject: [PATCH 651/790] msm: camera: icp: Update a5 qos values post reset Update a5 R/W priorities post a5 reset. CRs-Fixed: 2834780 Change-Id: I81736f780c70a648b81f4cd05db7caa0bdcc5195 Signed-off-by: Karthik Anantha Ram --- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 3e4c6f8d9d69..0c0ace51dd26 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -409,6 +409,8 @@ static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) { uint32_t val = A5_CSR_FULL_CPU_EN; void __iomem *base; + struct cam_hw_soc_info *soc_info = NULL; + struct a5_soc_info *a5_soc_info; if (!a5_info) { CAM_ERR(CAM_ICP, "invalid A5 device info"); @@ -416,6 +418,8 @@ static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) } base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + soc_info = &a5_info->soc_info; + a5_soc_info = soc_info->soc_private; cam_io_w_mb(A5_CSR_A5_CPU_EN, base + ICP_SIERRA_A5_CSR_A5_CONTROL); cam_io_w_mb(A5_CSR_FUNC_RESET, base + ICP_SIERRA_A5_CSR_NSEC_RESET); @@ -424,6 +428,11 @@ static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) val |= A5_CSR_FULL_DBG_EN; cam_io_w_mb(val, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + cam_io_w_mb(a5_soc_info->a5_qos_val, + base + ICP_SIERRA_A5_CSR_ACCESS); + + CAM_DBG(CAM_ICP, "a5 qos-val : 0x%x", + cam_io_r_mb(base + ICP_SIERRA_A5_CSR_ACCESS)); return 0; } From 8694f8c885eb0d924d60f427cc0f9fba68adab0c Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 17 Dec 2020 11:39:11 +0530 Subject: [PATCH 652/790] msm: camera: reqmgr: check validity of last_applied_idx last_applied_idx is updated on every successful applied request and the buf_done. After buf_done last_applied_idx is set to -1. While accessing last applied req the same index is used, if the last_applied_idx is -1 accessing last applied request will result in slab out of bound error, so check last_applied_idx before accessing last applied request. CRs-Fixed: 2840329 Change-Id: I8f49b9df097859cde20e651149167db7316976bb Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_req_mgr_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 646cb6783f54..78be9bcf3e2d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2072,7 +2072,9 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) in_q = link->req.in_q; if (in_q) { mutex_lock(&link->req.lock); - last_applied_req_id = in_q->slot[in_q->last_applied_idx].req_id; + if (in_q->last_applied_idx >= 0) + last_applied_req_id = + in_q->slot[in_q->last_applied_idx].req_id; mutex_unlock(&link->req.lock); } From d8083b502511c185a8a14d2dd3ed33ffde6c562c Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Sun, 13 Dec 2020 11:25:59 -0800 Subject: [PATCH 653/790] msm: camera: csiphy: Add logic to program common register All csiphy hw common register need to program on first streamon from any of csiphy hw in order to reduce the noise interferance for other csiphy hw. CRs-Fixed: 2839793 Change-Id: I256307b8b909da4a940be25a3aab60e8a301b6f8 Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 108 ++++++++++++++++++ .../cam_csiphy/cam_csiphy_core.h | 9 +- .../cam_csiphy/cam_csiphy_dev.c | 4 + .../cam_csiphy/cam_csiphy_dev.h | 1 + .../include/cam_csiphy_1_2_3_hwreg.h | 11 +- 5 files changed, 124 insertions(+), 9 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 6eda1796590d..cea15fecc025 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -35,9 +35,19 @@ /* Mask to enable skew calibration registers */ #define SKEW_CAL_MASK 0x2 +static DEFINE_MUTEX(active_csiphy_cnt_mutex); + static int csiphy_dump; module_param(csiphy_dump, int, 0644); +struct g_csiphy_data { + void __iomem *base_address; + uint8_t is_3phase; +}; + +static struct g_csiphy_data g_phy_data[MAX_CSIPHY] = {{0, 0}}; +static int active_csiphy_hw_cnt; + int32_t cam_csiphy_get_instance_offset( struct csiphy_device *csiphy_dev, int32_t dev_handle) @@ -109,6 +119,59 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev) } } +static void cam_csiphy_prgm_cmn_data( + struct csiphy_device *csiphy_dev, + bool reset) +{ + int csiphy_idx = 0; + uint32_t size = 0; + int i = 0; + void __iomem *csiphybase; + bool is_3phase = false; + struct csiphy_reg_t *csiphy_common_reg = NULL; + + size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; + + if (active_csiphy_hw_cnt < 0 || active_csiphy_hw_cnt >= MAX_CSIPHY) { + CAM_WARN(CAM_CSIPHY, + "MisMatched in active phy hw: %d and Max supported: %d", + active_csiphy_hw_cnt, MAX_CSIPHY); + return; + } + + if (active_csiphy_hw_cnt == 0) { + CAM_DBG(CAM_CSIPHY, "CSIPHYs HW state needs to be %s", + reset ? "reset" : "set"); + } else { + CAM_DBG(CAM_CSIPHY, "Active CSIPHY hws are %d", + active_csiphy_hw_cnt); + return; + } + + for (csiphy_idx = 0; csiphy_idx < MAX_CSIPHY; csiphy_idx++) { + csiphybase = g_phy_data[csiphy_idx].base_address; + is_3phase = g_phy_data[csiphy_idx].is_3phase; + + for (i = 0; i < size; i++) { + csiphy_common_reg = + &csiphy_dev->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_DEFAULT_PARAMS: + cam_io_w_mb(reset ? 0x00 : + csiphy_common_reg->reg_data, + csiphybase + + csiphy_common_reg->reg_addr); + break; + default: + break; + } + if (csiphy_common_reg->delay > 0) + usleep_range(csiphy_common_reg->delay, + csiphy_common_reg->delay + 5); + } + } +} + static int32_t cam_csiphy_update_secure_info( struct csiphy_device *csiphy_dev, int32_t index) { @@ -1132,6 +1195,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } + if (!csiphy_dev->acquire_count) { + g_phy_data[csiphy_dev->soc_info.index].is_3phase = + csiphy_acq_params.csiphy_3phase; + CAM_DBG(CAM_CSIPHY, + "g_csiphy data is updated for index: %d is_3phase: %u", + csiphy_dev->soc_info.index, + g_phy_data[csiphy_dev->soc_info.index].is_3phase); + } + csiphy_dev->acquire_count++; CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d", csiphy_dev->acquire_count); @@ -1209,6 +1281,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0; + if (csiphy_dev->ctrl_reg->csiphy_reg + .prgm_cmn_reg_across_csiphy) { + mutex_lock(&active_csiphy_cnt_mutex); + active_csiphy_hw_cnt--; + mutex_unlock(&active_csiphy_cnt_mutex); + + cam_csiphy_prgm_cmn_data(csiphy_dev, true); + } + rc = cam_csiphy_disable_hw(csiphy_dev); if (rc < 0) CAM_ERR(CAM_CSIPHY, "Failed in csiphy release"); @@ -1451,6 +1532,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } csiphy_dev->start_dev_count++; + + if (csiphy_dev->ctrl_reg->csiphy_reg + .prgm_cmn_reg_across_csiphy) { + cam_csiphy_prgm_cmn_data(csiphy_dev, false); + + mutex_lock(&active_csiphy_cnt_mutex); + active_csiphy_hw_cnt++; + mutex_unlock(&active_csiphy_cnt_mutex); + } + CAM_DBG(CAM_CSIPHY, "START DEV CNT: %d", csiphy_dev->start_dev_count); csiphy_dev->csiphy_state = CAM_CSIPHY_START; @@ -1480,3 +1571,20 @@ release_mutex: return rc; } + +void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev) +{ + if (!csiphy_dev) { + CAM_WARN(CAM_CSIPHY, "Data is NULL"); + return; + } + + if (csiphy_dev->soc_info.index >= MAX_CSIPHY) { + CAM_ERR(CAM_CSIPHY, "Invalid soc index: %u Max soc index: %u", + csiphy_dev->soc_info.index, MAX_CSIPHY); + return; + } + + g_phy_data[csiphy_dev->soc_info.index].base_address = + csiphy_dev->soc_info.reg_map[0].mem_base; +} diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h index 237fa787f226..271f6b0e28cd 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_CORE_H_ @@ -49,4 +49,11 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data); */ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev); +/** + * @soc_idx : CSIPHY cell index + * + * This API registers base address per soc_idx + */ +void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev); + #endif /* _CAM_CSIPHY_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 5d5f58748cec..29efc2a7f119 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -221,6 +221,10 @@ static int cam_csiphy_component_bind(struct device *dev, CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d", cpas_parms.client_handle); new_csiphy_dev->cpas_handle = cpas_parms.client_handle; + + cam_csiphy_register_baseaddress(new_csiphy_dev); + + CAM_DBG(CAM_CSIPHY, "%s component bound successfully", pdev->name); return rc; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 74d2dbd59080..4643b119805c 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -117,6 +117,7 @@ struct csiphy_reg_parms_t { uint32_t csiphy_cpas_cp_3ph_offset; uint32_t csiphy_2ph_clock_lane; uint32_t csiphy_2ph_combo_ck_ln; + uint32_t prgm_cmn_reg_across_csiphy; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 02d34d64b89d..1bfc6ca97b92 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -13,13 +13,14 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, .csiphy_interrupt_status_size = 11, - .csiphy_common_array_size = 8, - .csiphy_reset_array_size = 5, + .csiphy_common_array_size = 5, + .csiphy_reset_array_size = 2, .csiphy_2ph_config_array_size = 16, .csiphy_3ph_config_array_size = 26, .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, + .prgm_cmn_reg_across_csiphy = 1, }; struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { @@ -28,15 +29,9 @@ struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, - {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, - {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, }; struct csiphy_reg_t csiphy_reset_reg_1_2_3[] = { - {0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE}, - {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }; From af9556d493a635b585b5ce019c2e05bccb726b6c Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 14 Dec 2020 11:21:07 +0530 Subject: [PATCH 654/790] msm: camera: tfe: Change debug fs directory name Change debug fs directory name from IFE to TFE CRs-Fixed: 2837303 Change-Id: I1871ad37338bc2d2aa001b6c81f92e2215a010b8 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 3aa2040baaa7..f6e7f0d4dbed 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -5606,7 +5606,7 @@ static int cam_tfe_hw_mgr_debug_register(void) int rc = 0; struct dentry *dbgfileptr = NULL; - dbgfileptr = debugfs_create_dir("camera_ife", NULL); + dbgfileptr = debugfs_create_dir("camera_tfe", NULL); if (!dbgfileptr) { CAM_ERR(CAM_ISP,"DebugFS could not create directory!"); rc = -ENOENT; From e3d11961d1e36d362c7841e018fe4acc4bf90a3e Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Fri, 18 Dec 2020 15:20:52 +0530 Subject: [PATCH 655/790] msm: camera: isp: Reset num_deferred_acks when re-applying bubble req When re-applying bubble request after 2 frames reset num_deferred_acks also. CRs-Fixed: 2824276 Change-Id: I57e7ac89da69a2d65546c6f9a7f1d3c9f2c7e58f Signed-off-by: Wyes Karny --- drivers/cam_isp/cam_isp_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 80343c2957d2..713c6a23c4c1 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1776,6 +1776,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", req->request_id); req_isp->num_acked = 0; + req_isp->num_deferred_acks = 0; ctx_isp->bubble_frame_cnt = 0; req_isp->bubble_detected = false; req_isp->cdm_reset_before_apply = true; From 0204c76b587b09a3f2906c62d50e7179c3d18872 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 21 Dec 2020 22:17:26 +0530 Subject: [PATCH 656/790] msm: camera: jpeg: Add more data in case of smmu pf When we have smmu page fault of unmapped address and active flag is false we can cache and store unmapped address and print in case of error. Added check for last flushed req during config hw for jpeg as well. CRs-Fixed: 2834236 Change-Id: I9b9bb735587799871f9bdef94985f6269ca6a29d Signed-off-by: Vikram Sharma --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 9 ++++++ drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 2 ++ drivers/cam_req_mgr/cam_mem_mgr.c | 16 ++++++++--- drivers/cam_req_mgr/cam_mem_mgr.h | 32 ++++++++++++---------- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 737a681dfcb3..fc1d8c507af2 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -643,6 +643,14 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; request_id = (uintptr_t)config_args->priv; + if (request_id <= ctx_data->last_flush_req) { + CAM_WARN(CAM_JPEG, + "Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u", + request_id, ctx_data->last_flush_req); + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return -EINVAL; + } + p_cfg_req->req_id = request_id; p_cfg_req->num_hw_entry_processed = 0; hw_update_entries = config_args->hw_update_entries; @@ -1085,6 +1093,7 @@ static int cam_jpeg_mgr_hw_flush(void *hw_mgr_priv, void *flush_hw_args) return -EINVAL; } + ctx_data->last_flush_req = flush_args->last_flush_req; switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: rc = cam_jpeg_mgr_flush(hw_mgr_priv, ctx_data); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 9de5f2950d3a..6af8e9e0df35 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -98,6 +98,7 @@ struct cam_jpeg_hw_cfg_req { * @in_use: Flag for context usage * @wait_complete: Completion info * @cdm_cmd: Cdm cmd submitted for that context. + * @last_flush_req: req id which was flushed last. */ struct cam_jpeg_hw_ctx_data { void *context_priv; @@ -107,6 +108,7 @@ struct cam_jpeg_hw_ctx_data { bool in_use; struct completion wait_complete; struct cam_cdm_bl_request *cdm_cmd; + uint64_t last_flush_req; }; /** diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index a8db5ef8b744..900d7537966f 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -244,8 +244,9 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, return -ENOENT; if (!tbl.bufq[idx].active) { - CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", - idx); + CAM_ERR(CAM_MEM, + "Buffer at idx=%d is already unmapped, vaddr 0x%x unmaped_vaddr 0x%x", + idx, tbl.bufq[idx].vaddr, tbl.bufq[idx].unmaped_vaddr); return -EAGAIN; } @@ -757,6 +758,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) tbl.bufq[idx].kmdvaddr = kvaddr; tbl.bufq[idx].vaddr = hw_vaddr; + tbl.bufq[idx].unmaped_vaddr = 0; tbl.bufq[idx].dma_buf = dmabuf; tbl.bufq[idx].len = cmd->len; tbl.bufq[idx].num_hdl = cmd->num_hdl; @@ -883,10 +885,12 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) CAM_MEM_MGR_SET_SECURE_HDL(tbl.bufq[idx].buf_handle, true); tbl.bufq[idx].kmdvaddr = 0; - if (cmd->num_hdl > 0) + if (cmd->num_hdl > 0) { tbl.bufq[idx].vaddr = hw_vaddr; - else + tbl.bufq[idx].unmaped_vaddr = 0; + } else { tbl.bufq[idx].vaddr = 0; + } tbl.bufq[idx].dma_buf = dmabuf; tbl.bufq[idx].len = len; @@ -1020,6 +1024,7 @@ static int cam_mem_mgr_cleanup_table(void) tbl.bufq[i].flags = 0; tbl.bufq[i].buf_handle = -1; tbl.bufq[i].vaddr = 0; + tbl.bufq[i].unmaped_vaddr = 0; tbl.bufq[i].len = 0; memset(tbl.bufq[i].hdls, 0, sizeof(int32_t) * tbl.bufq[i].num_hdl); @@ -1078,6 +1083,7 @@ static int cam_mem_util_unmap(int32_t idx, /* Deactivate the buffer queue to prevent multiple unmap */ mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].active = false; + tbl.bufq[idx].unmaped_vaddr = tbl.bufq[idx].vaddr; tbl.bufq[idx].vaddr = 0; mutex_unlock(&tbl.bufq[idx].q_lock); mutex_unlock(&tbl.m_lock); @@ -1294,6 +1300,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, tbl.bufq[idx].kmdvaddr = kvaddr; tbl.bufq[idx].vaddr = iova; + tbl.bufq[idx].unmaped_vaddr = 0; tbl.bufq[idx].len = inp->size; tbl.bufq[idx].num_hdl = num_hdl; @@ -1443,6 +1450,7 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, tbl.bufq[idx].kmdvaddr = 0; tbl.bufq[idx].vaddr = iova; + tbl.bufq[idx].unmaped_vaddr = 0; tbl.bufq[idx].len = request_len; tbl.bufq[idx].num_hdl = num_hdl; diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index b4310db58d2b..c9931fc4f06b 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -26,21 +26,22 @@ enum cam_smmu_mapping_client { /** * struct cam_mem_buf_queue * - * @dma_buf: pointer to the allocated dma_buf in the table - * @q_lock: mutex lock for buffer - * @hdls: list of mapped handles - * @num_hdl: number of handles - * @fd: file descriptor of buffer - * @buf_handle: unique handle for buffer - * @align: alignment for allocation - * @len: size of buffer - * @flags: attributes of buffer - * @vaddr: IOVA of buffer - * @kmdvaddr: Kernel virtual address - * @active: state of the buffer - * @is_imported: Flag indicating if buffer is imported from an FD in user space - * @is_internal: Flag indicating kernel allocated buffer - * @timestamp: Timestamp at which this entry in tbl was made + * @dma_buf: pointer to the allocated dma_buf in the table + * @q_lock: mutex lock for buffer + * @hdls: list of mapped handles + * @num_hdl: number of handles + * @fd: file descriptor of buffer + * @buf_handle: unique handle for buffer + * @align: alignment for allocation + * @len: size of buffer + * @flags: attributes of buffer + * @vaddr: IOVA of buffer + * @kmdvaddr: Kernel virtual address + * @active: state of the buffer + * @is_imported: Flag indicating if buffer is imported from an FD in user space + * @is_internal: Flag indicating kernel allocated buffer + * @timestamp: Timestamp at which this entry in tbl was made + * @unmaped_vaddr: This will cache the vaddr if it is unmapped. */ struct cam_mem_buf_queue { struct dma_buf *dma_buf; @@ -53,6 +54,7 @@ struct cam_mem_buf_queue { size_t len; uint32_t flags; uint64_t vaddr; + uint64_t unmaped_vaddr; uintptr_t kmdvaddr; bool active; bool is_imported; From 472804a0fc0383d10fd639c4c669cf6b6c71eb55 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Mon, 21 Dec 2020 18:37:42 +0530 Subject: [PATCH 657/790] msm: camera: isp: Add YUV support in CAMIF Add support to configure the incoming format in the top core Camif register. Changes in CSID file to support YUV TPG are also integrated. CRs-Fixed: 2846873 Change-Id: I87fa0171a60013ba356a33455170cf1ecfbb0563 Signed-off-by: Gaurav Jindal --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 68 +++++++++++++++---- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 1 + .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 19 ++++-- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.h | 3 + .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h | 2 + 5 files changed, 74 insertions(+), 19 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 55e09e1317a7..ef50a1ab51eb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -27,11 +27,11 @@ /* TPG VC/DT values */ #define CAM_IFE_CSID_TPG_VC_VAL 0xA -#define CAM_IFE_CSID_TPG_DT_VAL 0x2B +#define CAM_IFE_CSID_TPG_YUV_DT_VAL 0x1e +#define CAM_IFE_CSID_TPG_RGB_DT_VAL 0x2B /* CSIPHY TPG VC/DT values */ #define CAM_IFE_CPHY_TPG_VC_VAL 0x0 -#define CAM_IFE_CPHY_TPG_DT_VAL 0x2B /* Timeout values in usec */ #define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000 @@ -76,6 +76,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported( case CAM_FORMAT_DPCM_14_8_14: case CAM_FORMAT_DPCM_14_10_14: case CAM_FORMAT_DPCM_12_10_12: + case CAM_FORMAT_YUV422: rc = 0; break; default: @@ -254,6 +255,10 @@ static int cam_ife_csid_get_format_rdi( *decode_fmt = 0xD; *plain_fmt = 0x1; break; + case CAM_FORMAT_YUV422: + *decode_fmt = 0x1; + *plain_fmt = 0x0; + break; default: rc = -EINVAL; break; @@ -332,6 +337,10 @@ static int cam_ife_csid_get_format_ipp_ppp( *decode_fmt = 0xD; *plain_fmt = 0x1; break; + case CAM_FORMAT_YUV422: + *decode_fmt = 0x1; + *plain_fmt = 0; + break; default: CAM_ERR(CAM_ISP, "Unsupported format %d", in_format); @@ -992,9 +1001,11 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw, /* Below code is executed only for TPG in_res type */ csid_hw->csi2_rx_cfg.phy_sel = 0; - if (cid_reserv->in_port->format > - CAM_FORMAT_MIPI_RAW_16) { - CAM_ERR(CAM_ISP, " Wrong TPG format"); + if ((cid_reserv->in_port->format != CAM_FORMAT_YUV422) && + (cid_reserv->in_port->format > + CAM_FORMAT_MIPI_RAW_16)) { + CAM_ERR(CAM_ISP, " Wrong TPG format %d", + cid_reserv->in_port->format); rc = -EINVAL; goto end; } @@ -1300,15 +1311,30 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, reserve->in_port->line_start, reserve->in_port->line_stop, path_data->crop_enable, path_data->hblank_cnt); - if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) || - (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) || - (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) { - path_data->dt = CAM_IFE_CPHY_TPG_DT_VAL; + + switch (reserve->in_port->res_type) { + + case CAM_ISP_IFE_IN_RES_CPHY_TPG_0: + case CAM_ISP_IFE_IN_RES_CPHY_TPG_1: + case CAM_ISP_IFE_IN_RES_CPHY_TPG_2: path_data->vc = CAM_IFE_CPHY_TPG_VC_VAL; - } else if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) { - path_data->dt = CAM_IFE_CSID_TPG_DT_VAL; + + if (path_data->in_format == CAM_FORMAT_YUV422) + path_data->dt = CAM_IFE_CSID_TPG_YUV_DT_VAL; + else + path_data->dt = CAM_IFE_CSID_TPG_RGB_DT_VAL; + break; + + case CAM_ISP_IFE_IN_RES_TPG: path_data->vc = CAM_IFE_CSID_TPG_VC_VAL; - } else { + + if (path_data->in_format == CAM_FORMAT_YUV422) + path_data->dt = CAM_IFE_CSID_TPG_YUV_DT_VAL; + else + path_data->dt = CAM_IFE_CSID_TPG_RGB_DT_VAL; + break; + + default: path_data->dt = reserve->in_port->dt[0]; path_data->vc = reserve->in_port->vc[0]; if (reserve->in_port->num_valid_vc_dt) { @@ -1316,6 +1342,7 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw, path_data->vc1 = reserve->in_port->vc[1]; path_data->is_valid_vc1_dt1 = 1; } + break; } if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { @@ -1691,6 +1718,7 @@ static int cam_ife_csid_config_tpg(struct cam_ife_csid_hw *csid_hw, const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t val = 0; + uint32_t dt, in_format, test_pattern; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1716,14 +1744,24 @@ static int cam_ife_csid_config_tpg(struct cam_ife_csid_hw *csid_hw, cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->tpg_reg->csid_tpg_dt_n_cfg_0_addr); - cam_io_w_mb(CAM_IFE_CSID_TPG_DT_VAL, soc_info->reg_map[0].mem_base + + if (csid_hw->tpg_cfg.in_format == CAM_FORMAT_YUV422) { + in_format = 0x2; + dt = CAM_IFE_CSID_TPG_YUV_DT_VAL; + test_pattern = 0x4; + } else { + in_format = csid_hw->tpg_cfg.in_format; + dt = CAM_IFE_CSID_TPG_RGB_DT_VAL; + test_pattern = csid_hw->tpg_cfg.test_pattern; + } + + cam_io_w_mb(dt, soc_info->reg_map[0].mem_base + csid_reg->tpg_reg->csid_tpg_dt_n_cfg_1_addr); /* * in_format is the same as the input resource format. * it is one larger than the register spec format. */ - val = ((csid_hw->tpg_cfg.in_format - 1) << 16) | 0x8; + val = ((in_format - 1) << 16) | 0x8; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->tpg_reg->csid_tpg_dt_n_cfg_2_addr); @@ -1732,7 +1770,7 @@ static int cam_ife_csid_config_tpg(struct cam_ife_csid_hw *csid_hw, cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->tpg_reg->csid_tpg_color_bars_cfg_addr); /* config pix pattern */ - cam_io_w_mb(csid_hw->tpg_cfg.test_pattern, + cam_io_w_mb(test_pattern, soc_info->reg_map[0].mem_base + csid_reg->tpg_reg->csid_tpg_common_gen_cfg_addr); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index d0c0822021c6..957539d28dfc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1103,6 +1103,7 @@ static int cam_vfe_bus_ver3_acquire_wm( case CAM_FORMAT_MIPI_RAW_20: case CAM_FORMAT_PLAIN128: case CAM_FORMAT_PLAIN32_20: + case CAM_FORMAT_YUV422: rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; rsrc_data->height = 0; rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 03adaac7492b..72f108d9621a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -169,7 +169,8 @@ static int cam_vfe_camif_ver3_err_irq_top_half( return rc; } -static int cam_vfe_camif_ver3_validate_pix_pattern(uint32_t pattern) +static int cam_vfe_camif_ver3_validate_pix_pattern(uint32_t pattern, + uint32_t *input_pp_fmt) { int rc; @@ -178,11 +179,16 @@ static int cam_vfe_camif_ver3_validate_pix_pattern(uint32_t pattern) case CAM_ISP_PATTERN_BAYER_GRGRGR: case CAM_ISP_PATTERN_BAYER_BGBGBG: case CAM_ISP_PATTERN_BAYER_GBGBGB: + rc = 0; + *input_pp_fmt = CAM_ISP_PP_INPUT_BAYER_FMT; + break; + 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; + *input_pp_fmt = CAM_ISP_PP_INPUT_YUV_FMT; break; default: CAM_ERR(CAM_ISP, "Error, Invalid pix pattern:%d", pattern); @@ -256,7 +262,8 @@ int cam_vfe_camif_ver3_acquire_resource( acquire_data = (struct cam_vfe_acquire_args *)acquire_param; rc = cam_vfe_camif_ver3_validate_pix_pattern( - acquire_data->vfe_in.in_port->test_pattern); + acquire_data->vfe_in.in_port->test_pattern, + &camif_data->cam_common_cfg.input_pp_fmt); if (rc) { CAM_ERR(CAM_ISP, "Validate pix pattern failed, rc = %d", rc); @@ -285,10 +292,11 @@ int cam_vfe_camif_ver3_acquire_resource( camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx; CAM_DBG(CAM_ISP, - "VFE:%d CAMIF pix_pattern:%d dsp_mode=%d is_dual:%d dual_hw_idx:%d", + "VFE:%d CAMIF pix_pattern:%d dsp_mode=%d is_dual:%d dual_hw_idx:%d format = %d", camif_res->hw_intf->hw_idx, camif_data->pix_pattern, camif_data->dsp_mode, - camif_data->is_dual, camif_data->dual_hw_idx); + camif_data->is_dual, camif_data->dual_hw_idx, + acquire_data->vfe_in.in_port->format); return rc; } @@ -445,6 +453,9 @@ static int cam_vfe_camif_ver3_resource_start( CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BHIST; val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) << CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP; + val |= (rsrc_data->cam_common_cfg.input_pp_fmt & 0x3) << + CAM_SHIFT_TOP_CORE_CFG_INPUT_PP_FMT; + if (rsrc_data->is_fe_enabled && !rsrc_data->is_offline) val |= 0x2 << rsrc_data->reg_data->operating_mode_shift; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h index 6e02c58ee63b..f91a08d3165f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -9,6 +9,9 @@ #include "cam_isp_hw.h" #include "cam_vfe_top.h" +#define CAM_ISP_PP_INPUT_BAYER_FMT 0 +#define CAM_ISP_PP_INPUT_YUV_FMT 1 + struct cam_vfe_camif_ver3_pp_clc_reg { uint32_t hw_version; uint32_t hw_status; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h index 4a24ba6ddf76..1a1d240d3049 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -17,6 +17,7 @@ #define CAM_SHIFT_TOP_CORE_CFG_DISP_DS16_R2PD 28 #define CAM_SHIFT_TOP_CORE_CFG_DISP_DS4_R2PD 27 #define CAM_SHIFT_TOP_CORE_CFG_DSP_STREAMING 25 +#define CAM_SHIFT_TOP_CORE_CFG_INPUT_PP_FMT 14 #define CAM_SHIFT_TOP_CORE_CFG_STATS_IHIST 10 #define CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BE 9 #define CAM_SHIFT_TOP_CORE_CFG_STATS_HDR_BHIST 8 @@ -75,6 +76,7 @@ struct cam_vfe_camif_common_cfg { uint32_t hdr_bhist_src_sel; uint32_t input_mux_sel_pdaf; uint32_t input_mux_sel_pp; + uint32_t input_pp_fmt; }; struct cam_vfe_top_ver3_hw_info { From ac4585870ac7505ad6e228417a8fbcc821178248 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Sun, 13 Dec 2020 11:25:59 -0800 Subject: [PATCH 658/790] msm: camera: csiphy: Add logic to program common register All csiphy hw common register need to program on first streamon from any of csiphy hw in order to reduce the noise interferance for other csiphy hw. CRs-Fixed: 2839793 Change-Id: I256307b8b909da4a940be25a3aab60e8a301b6f8 Signed-off-by: Jigarkumar Zala --- .../cam_csiphy/cam_csiphy_core.c | 108 ++++++++++++++++++ .../cam_csiphy/cam_csiphy_core.h | 9 +- .../cam_csiphy/cam_csiphy_dev.c | 4 + .../cam_csiphy/cam_csiphy_dev.h | 1 + .../include/cam_csiphy_1_2_3_hwreg.h | 11 +- 5 files changed, 124 insertions(+), 9 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index edbde5a6c401..c5c7b70edba6 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -35,9 +35,19 @@ /* Mask to enable skew calibration registers */ #define SKEW_CAL_MASK 0x2 +static DEFINE_MUTEX(active_csiphy_cnt_mutex); + static int csiphy_dump; module_param(csiphy_dump, int, 0644); +struct g_csiphy_data { + void __iomem *base_address; + uint8_t is_3phase; +}; + +static struct g_csiphy_data g_phy_data[MAX_CSIPHY] = {{0, 0}}; +static int active_csiphy_hw_cnt; + int32_t cam_csiphy_get_instance_offset( struct csiphy_device *csiphy_dev, int32_t dev_handle) @@ -109,6 +119,59 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev) } } +static void cam_csiphy_prgm_cmn_data( + struct csiphy_device *csiphy_dev, + bool reset) +{ + int csiphy_idx = 0; + uint32_t size = 0; + int i = 0; + void __iomem *csiphybase; + bool is_3phase = false; + struct csiphy_reg_t *csiphy_common_reg = NULL; + + size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; + + if (active_csiphy_hw_cnt < 0 || active_csiphy_hw_cnt >= MAX_CSIPHY) { + CAM_WARN(CAM_CSIPHY, + "MisMatched in active phy hw: %d and Max supported: %d", + active_csiphy_hw_cnt, MAX_CSIPHY); + return; + } + + if (active_csiphy_hw_cnt == 0) { + CAM_DBG(CAM_CSIPHY, "CSIPHYs HW state needs to be %s", + reset ? "reset" : "set"); + } else { + CAM_DBG(CAM_CSIPHY, "Active CSIPHY hws are %d", + active_csiphy_hw_cnt); + return; + } + + for (csiphy_idx = 0; csiphy_idx < MAX_CSIPHY; csiphy_idx++) { + csiphybase = g_phy_data[csiphy_idx].base_address; + is_3phase = g_phy_data[csiphy_idx].is_3phase; + + for (i = 0; i < size; i++) { + csiphy_common_reg = + &csiphy_dev->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_DEFAULT_PARAMS: + cam_io_w_mb(reset ? 0x00 : + csiphy_common_reg->reg_data, + csiphybase + + csiphy_common_reg->reg_addr); + break; + default: + break; + } + if (csiphy_common_reg->delay > 0) + usleep_range(csiphy_common_reg->delay, + csiphy_common_reg->delay + 5); + } + } +} + static int32_t cam_csiphy_update_secure_info( struct csiphy_device *csiphy_dev, int32_t index) { @@ -1132,6 +1195,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } + if (!csiphy_dev->acquire_count) { + g_phy_data[csiphy_dev->soc_info.index].is_3phase = + csiphy_acq_params.csiphy_3phase; + CAM_DBG(CAM_CSIPHY, + "g_csiphy data is updated for index: %d is_3phase: %u", + csiphy_dev->soc_info.index, + g_phy_data[csiphy_dev->soc_info.index].is_3phase); + } + csiphy_dev->acquire_count++; CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d", csiphy_dev->acquire_count); @@ -1203,6 +1275,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0; + if (csiphy_dev->ctrl_reg->csiphy_reg + .prgm_cmn_reg_across_csiphy) { + mutex_lock(&active_csiphy_cnt_mutex); + active_csiphy_hw_cnt--; + mutex_unlock(&active_csiphy_cnt_mutex); + + cam_csiphy_prgm_cmn_data(csiphy_dev, true); + } + rc = cam_csiphy_disable_hw(csiphy_dev); if (rc < 0) CAM_ERR(CAM_CSIPHY, "Failed in csiphy release"); @@ -1444,6 +1525,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } csiphy_dev->start_dev_count++; + + if (csiphy_dev->ctrl_reg->csiphy_reg + .prgm_cmn_reg_across_csiphy) { + cam_csiphy_prgm_cmn_data(csiphy_dev, false); + + mutex_lock(&active_csiphy_cnt_mutex); + active_csiphy_hw_cnt++; + mutex_unlock(&active_csiphy_cnt_mutex); + } + CAM_DBG(CAM_CSIPHY, "START DEV CNT: %d", csiphy_dev->start_dev_count); csiphy_dev->csiphy_state = CAM_CSIPHY_START; @@ -1480,3 +1571,20 @@ release_mutex: return rc; } + +void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev) +{ + if (!csiphy_dev) { + CAM_WARN(CAM_CSIPHY, "Data is NULL"); + return; + } + + if (csiphy_dev->soc_info.index >= MAX_CSIPHY) { + CAM_ERR(CAM_CSIPHY, "Invalid soc index: %u Max soc index: %u", + csiphy_dev->soc_info.index, MAX_CSIPHY); + return; + } + + g_phy_data[csiphy_dev->soc_info.index].base_address = + csiphy_dev->soc_info.reg_map[0].mem_base; +} diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h index 237fa787f226..271f6b0e28cd 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_CORE_H_ @@ -49,4 +49,11 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data); */ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev); +/** + * @soc_idx : CSIPHY cell index + * + * This API registers base address per soc_idx + */ +void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev); + #endif /* _CAM_CSIPHY_CORE_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 5d5f58748cec..29efc2a7f119 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -221,6 +221,10 @@ static int cam_csiphy_component_bind(struct device *dev, CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d", cpas_parms.client_handle); new_csiphy_dev->cpas_handle = cpas_parms.client_handle; + + cam_csiphy_register_baseaddress(new_csiphy_dev); + + CAM_DBG(CAM_CSIPHY, "%s component bound successfully", pdev->name); return rc; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 74d2dbd59080..4643b119805c 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -117,6 +117,7 @@ struct csiphy_reg_parms_t { uint32_t csiphy_cpas_cp_3ph_offset; uint32_t csiphy_2ph_clock_lane; uint32_t csiphy_2ph_combo_ck_ln; + uint32_t prgm_cmn_reg_across_csiphy; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 02d34d64b89d..1bfc6ca97b92 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -13,13 +13,14 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, .csiphy_interrupt_status_size = 11, - .csiphy_common_array_size = 8, - .csiphy_reset_array_size = 5, + .csiphy_common_array_size = 5, + .csiphy_reset_array_size = 2, .csiphy_2ph_config_array_size = 16, .csiphy_3ph_config_array_size = 26, .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, + .prgm_cmn_reg_across_csiphy = 1, }; struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { @@ -28,15 +29,9 @@ struct csiphy_reg_t csiphy_common_reg_1_2_3[] = { {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0824, 0x72, 0x00, CSIPHY_2PH_REGS}, - {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, - {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, }; struct csiphy_reg_t csiphy_reset_reg_1_2_3[] = { - {0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE}, - {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }; From 66d043d43ab5a93d11a8a7016a0b93f723ad321d Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Tue, 22 Dec 2020 16:52:47 +0530 Subject: [PATCH 659/790] msm: camera: cdm: corrected submit bl logic CDM driver check for available bl fifo slots before submitting to HW. If no free slots available then it wait for CDM HW to process all the BLs and return available slots. CDM driver was incorrectly calculating the available bl slots and causing bl fifo overflow. Corrected the sequence in wait for bl fifo logic. CRs-Fixed: 2837583 Change-Id: I2861f8c66822e0739f0546eaf153d8e2af0caefe Signed-off-by: Alok Chauhan --- drivers/cam_cdm/cam_cdm_hw_core.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index eb39ecded292..eb9cab56c634 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -586,13 +586,9 @@ int cam_hw_cdm_wait_for_bl_fifo( pending_bl); break; } - if (bl_count < (available_bl_slots - 1)) { - CAM_DBG(CAM_CDM, - "BL slot available_cnt=%d requested=%d", - (available_bl_slots - 1), bl_count); - rc = available_bl_slots - 1; - break; - } else if (0 == (available_bl_slots - 1)) { + if (0 == (available_bl_slots - 1)) { + reinit_completion(&core->bl_fifo[fifo_idx].bl_complete); + rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, true, fifo_idx); if (rc) { @@ -619,7 +615,10 @@ int cam_hw_cdm_wait_for_bl_fifo( rc = 1; CAM_DBG(CAM_CDM, "CDM HW is ready for data"); } else { - rc = (bl_count - (available_bl_slots - 1)); + CAM_DBG(CAM_CDM, + "BL slot available_cnt=%d requested=%d", + (available_bl_slots - 1), bl_count); + rc = available_bl_slots - 1; break; } } while (1); From 3f527598f0858114f45662fce1bccfaa35798c85 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 2 Dec 2020 17:09:07 +0530 Subject: [PATCH 660/790] msm: camera: cpas: Add mechanism to check camnoc idle status Qchannel interface is used to ensure camnoc is idle. This needs to be check before camera core power collapse and after camera core power on sequence to make sure camera hw blocks are in proper state. CRs-Fixed: 2847646 Change-Id: If9dbd980c2e8e983ac973f91e3d1ed132719c395 Signed-off-by: Alok Chauhan --- drivers/cam_cpas/cam_cpas_hw.c | 26 ++++++++ drivers/cam_cpas/cam_cpas_hw.h | 3 + drivers/cam_cpas/cam_cpas_hw_intf.h | 2 + drivers/cam_cpas/camss_top/cam_camsstop_hw.c | 1 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 62 ++++++++++++++++++++ drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 12 ++++ drivers/cam_cpas/cpas_top/cpastop_v520_100.h | 4 ++ drivers/cam_cpas/cpas_top/cpastop_v540_100.h | 4 ++ drivers/cam_cpas/cpas_top/cpastop_v545_100.h | 4 ++ drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 4 ++ drivers/cam_cpas/cpas_top/cpastop_v580_100.h | 4 ++ 11 files changed, 126 insertions(+) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 56bea71d400b..2119e1b6885b 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1544,6 +1544,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, struct cam_cpas_private_soc *soc_private = NULL; int rc = 0; long result; + int retry_camnoc_idle = 0; if (!hw_priv || !stop_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", @@ -1597,6 +1598,18 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, } } + if (cpas_core->internal_ops.qchannel_handshake) { + rc = cpas_core->internal_ops.qchannel_handshake( + cpas_hw, false); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed in qchannel_handshake rc=%d", + rc); + retry_camnoc_idle = 1; + /* Do not return error, passthrough */ + } + } + rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info); if (rc) { CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc); @@ -1612,6 +1625,19 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, atomic_read(&cpas_core->irq_count)); } + /* try again incase camnoc is still not idle */ + if (cpas_core->internal_ops.qchannel_handshake && + retry_camnoc_idle) { + rc = cpas_core->internal_ops.qchannel_handshake( + cpas_hw, false); + if (rc) { + CAM_ERR(CAM_CPAS, + "failed in qchannel_handshake rc=%d", + rc); + /* Do not return error, passthrough */ + } + } + rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, false); if (rc) { diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index 1c25d0f56203..a7c7f429ccc2 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -70,6 +70,8 @@ enum cam_cpas_access_type { * @power_off: Function pointer for hw core specific power off settings * @setup_qos_settings: Function pointer for hw to select a specific qos header * @print_poweron_settings: Function pointer for hw to print poweron settings + * @qchannel_handshake: Function pointer for hw core specific qchannel + * handshake settings * */ struct cam_cpas_internal_ops { @@ -85,6 +87,7 @@ struct cam_cpas_internal_ops { int (*setup_qos_settings)(struct cam_hw_info *cpas_hw, uint32_t selection_mask); int (*print_poweron_settings)(struct cam_hw_info *cpas_hw); + int (*qchannel_handshake)(struct cam_hw_info *cpas_hw, bool power_on); }; /** diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index fc9297ac69c1..09d1180a4b01 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -19,6 +19,8 @@ #define CAM_CPAS_POLL_MIN_USECS 200 /* Maximum usecs to sleep while polling */ #define CAM_CPAS_POLL_MAX_USECS 250 +/* Number of times to retry while polling */ +#define CAM_CPAS_POLL_QH_RETRY_CNT 50 /** * enum cam_cpas_hw_type - Enum for CPAS HW type diff --git a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c index 23f8542cdd87..d8552c56d1db 100644 --- a/drivers/cam_cpas/camss_top/cam_camsstop_hw.c +++ b/drivers/cam_cpas/camss_top/cam_camsstop_hw.c @@ -79,6 +79,7 @@ int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->power_off = NULL; internal_ops->setup_qos_settings = NULL; internal_ops->print_poweron_settings = NULL; + internal_ops->qchannel_handshake = NULL; return 0; } diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 67faa3443260..8c0f3e618082 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -34,6 +34,8 @@ #include "cam_req_mgr_workq.h" struct cam_camnoc_info *camnoc_info; +struct cam_cpas_camnoc_qchannel *qchannel_info; + #define CAMNOC_SLAVE_MAX_ERR_CODE 7 static const char * const camnoc_salve_err_code[] = { @@ -809,11 +811,65 @@ static int cam_cpastop_poweroff(struct cam_hw_info *cpas_hw) return rc; } +static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw, + bool power_on) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CPASTOP]; + uint32_t mask = 0; + uint32_t wait_data, qchannel_status, qdeny; + int rc = 0; + + if (reg_indx == -1) + return -EINVAL; + + if (!qchannel_info) + return 0; + + if (power_on) { + /* wait for QACCEPTN in QCHANNEL status*/ + mask = BIT(0); + wait_data = 1; + } else { + /* Clear the quiecience request in QCHANNEL ctrl*/ + cam_io_w_mb(0, soc_info->reg_map[reg_indx].mem_base + + qchannel_info->qchannel_ctrl); + /* wait for QACCEPTN and QDENY in QCHANNEL status*/ + mask = BIT(1) | BIT(0); + wait_data = 0; + } + + rc = cam_io_poll_value_wmask( + soc_info->reg_map[reg_indx].mem_base + + qchannel_info->qchannel_status, + wait_data, mask, CAM_CPAS_POLL_QH_RETRY_CNT, + CAM_CPAS_POLL_MIN_USECS, CAM_CPAS_POLL_MAX_USECS); + if (rc) { + CAM_ERR(CAM_CPAS, + "camnoc idle sequence failed, qstat 0x%x", + cam_io_r(soc_info->reg_map[reg_indx].mem_base + + qchannel_info->qchannel_status)); + /* Do not return error, passthrough */ + rc = 0; + } + + /* check if deny bit is set */ + qchannel_status = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + + qchannel_info->qchannel_status); + qdeny = (qchannel_status & BIT(1)); + if (!power_on && qdeny) + rc = -EBUSY; + + return rc; +} + static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, struct cam_cpas_hw_caps *hw_caps) { int rc = 0; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + qchannel_info = NULL; CAM_DBG(CAM_CPAS, "hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d", @@ -855,18 +911,23 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, break; case CAM_CPAS_TITAN_580_V100: camnoc_info = &cam580_cpas100_camnoc_info; + qchannel_info = &cam580_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_540_V100: camnoc_info = &cam540_cpas100_camnoc_info; + qchannel_info = &cam540_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_520_V100: camnoc_info = &cam520_cpas100_camnoc_info; + qchannel_info = &cam520_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_545_V100: camnoc_info = &cam545_cpas100_camnoc_info; + qchannel_info = &cam545_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_570_V200: camnoc_info = &cam570_cpas200_camnoc_info; + qchannel_info = &cam570_cpas200_qchannel_info; break; case CAM_CPAS_TITAN_680_V100: camnoc_info = &cam680_cpas100_camnoc_info; @@ -952,6 +1013,7 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->setup_qos_settings = cam_cpastop_setup_qos_settings; internal_ops->print_poweron_settings = cam_cpastop_print_poweron_settings; + internal_ops->qchannel_handshake = cam_cpastop_qchannel_handshake; return 0; } diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 2d59122cab92..3992e079ad18 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -356,4 +356,16 @@ struct cam_cpas_work_payload { struct work_struct work; }; +/** + * struct cam_cpas_camnoc_qchannel : Cpas camnoc qchannel info + * + * @qchannel_ctrl: offset to configure to control camnoc qchannel interface + * @qchannel_status: offset to read camnoc qchannel interface status + * + */ +struct cam_cpas_camnoc_qchannel { + uint32_t qchannel_ctrl; + uint32_t qchannel_status; +}; + #endif /* _CAM_CPASTOP_HW_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v520_100.h b/drivers/cam_cpas/cpas_top/cpastop_v520_100.h index ec99574ebf10..4a8c4f945d03 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v520_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v520_100.h @@ -237,4 +237,8 @@ static struct cam_camnoc_info cam520_cpas100_camnoc_info = { .errata_wa_list = NULL, }; +static struct cam_cpas_camnoc_qchannel cam520_cpas100_qchannel_info = { + .qchannel_ctrl = 0x14, + .qchannel_status = 0x18, +}; #endif /* _CPASTOP_V520_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h index 65cb1fabc701..3d9e65ed3c1f 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h @@ -238,4 +238,8 @@ static struct cam_camnoc_info cam540_cpas100_camnoc_info = { .errata_wa_list = NULL, }; +static struct cam_cpas_camnoc_qchannel cam540_cpas100_qchannel_info = { + .qchannel_ctrl = 0x14, + .qchannel_status = 0x18, +}; #endif /* _CPASTOP_V540_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h index d7cbe7794f6e..d3ad5fbc1075 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h @@ -315,4 +315,8 @@ static struct cam_camnoc_info cam545_cpas100_camnoc_info = { .errata_wa_list = NULL, }; +static struct cam_cpas_camnoc_qchannel cam545_cpas100_qchannel_info = { + .qchannel_ctrl = 0x14, + .qchannel_status = 0x18, +}; #endif /* _CPASTOP_V545_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index 02410cc00876..49978a0f5279 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -881,4 +881,8 @@ static struct cam_camnoc_info cam570_cpas200_camnoc_info = { .errata_wa_list = &cam570_cpas200_errata_wa_list, }; +static struct cam_cpas_camnoc_qchannel cam570_cpas200_qchannel_info = { + .qchannel_ctrl = 0x5C, + .qchannel_status = 0x60, +}; #endif /* _CPASTOP_V570_200_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h index 9855fdf6821c..7c01ae3cdcb0 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h @@ -1043,5 +1043,9 @@ static struct cam_camnoc_info cam580_cpas100_camnoc_info = { .errata_wa_list = &cam580_cpas100_errata_wa_list, }; +static struct cam_cpas_camnoc_qchannel cam580_cpas100_qchannel_info = { + .qchannel_ctrl = 0x5C, + .qchannel_status = 0x60, +}; #endif /* _CPASTOP_V580_100_H_ */ From cce99f8e4f8fcc798f13e8f51267ced24a799369 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 24 Dec 2020 14:43:26 +0530 Subject: [PATCH 661/790] msm: camera: cpas: Add version map entry for 680 titan version This change add cpas hw version map entry for 680 titan version. And remove cpas version check for ubwc support. CRs-Fixed: 2825675 Change-Id: I858838a5a774c964a1a09d96114442f69058670a Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 9 ++++ .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 45 +++++++++---------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 67faa3443260..d8cb87978ffd 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -131,6 +131,15 @@ static const uint32_t cam_cpas_hw_version_map 0, CAM_CPAS_TITAN_570_V200, }, + /* for camera_680 */ + { + CAM_CPAS_TITAN_680_V100, + 0, + 0, + 0, + 0, + 0, + }, /* for camera_165 */ { CAM_CPAS_TITAN_165_V100, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index 0445ebf378d5..d684f27f3989 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -58,34 +58,29 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info) goto pid; } - switch (soc_info->hw_version) { - case CAM_CPAS_TITAN_480_V100: - case CAM_CPAS_TITAN_580_V100: - case CAM_CPAS_TITAN_570_V200: - case CAM_CPAS_TITAN_165_V100: - num_ubwc_cfg = of_property_count_u32_elems(of_node, - "ubwc-static-cfg"); + if (!of_property_read_bool(of_node, "ubwc-static-cfg")) { + CAM_DBG(CAM_ISP, "ubwc-static-cfg not supported"); + goto pid; + } - if (num_ubwc_cfg < 0 || num_ubwc_cfg > UBWC_STATIC_CONFIG_MAX) { - CAM_ERR(CAM_ISP, "wrong num_ubwc_cfg: %d", - num_ubwc_cfg); - rc = num_ubwc_cfg; - goto pid; - } + num_ubwc_cfg = of_property_count_u32_elems(of_node, + "ubwc-static-cfg"); - for (i = 0; i < num_ubwc_cfg; i++) { - rc = of_property_read_u32_index(of_node, - "ubwc-static-cfg", i, - &vfe_soc_private->ubwc_static_ctrl[i]); - if (rc < 0) { - CAM_ERR(CAM_ISP, - "unable to read ubwc static config"); - break; - } + if (num_ubwc_cfg < 0 || num_ubwc_cfg > UBWC_STATIC_CONFIG_MAX) { + CAM_ERR(CAM_ISP, "wrong num_ubwc_cfg: %d", + num_ubwc_cfg); + rc = num_ubwc_cfg; + goto pid; + } + + for (i = 0; i < num_ubwc_cfg; i++) { + rc = of_property_read_u32_index(of_node, + "ubwc-static-cfg", i, + &vfe_soc_private->ubwc_static_ctrl[i]); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "unable to read ubwc static config"); } - break; - default: - break; } pid: /* set some default values */ From afb3736650122de189e575793badca123103d813 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 8 Dec 2020 20:26:15 +0530 Subject: [PATCH 662/790] msm: camera: isp: IFE and CSID probe based on fuse Some ISP hardware id instances are disabled on some target skus. Cpas driver has fuse information based on the dtsi entries. ISP hw driver queries the cpas driver whether hw instance is supported or not. If ISP hardware is supported on the target then continue the isp hardware probe. CRs-Fixed: 2825675 Change-Id: I37f059c6591f3a6e57277029859e1b8b0e48905d Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cam_cpas_intf.c | 5 +---- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 12 ++++++++++++ .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 12 ++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index 1ff8f92fdd70..45eba95e1052 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -161,11 +161,8 @@ bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map, if (soc_private->feature_info[i].feature == flag) break; - if (i == soc_private->num_feature_info) { - CAM_INFO(CAM_CPAS, "Feature not found, no of featues: %d", - soc_private->num_feature_info); + if (i == soc_private->num_feature_info) goto end; - } if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE || (soc_private->feature_info[i].type == diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index ef50a1ab51eb..2601110a3719 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -21,6 +21,7 @@ #include "cam_cpas_api.h" #include "cam_subdev.h" #include "cam_tasklet_util.h" +#include "dt-bindings/msm/msm-camera.h" /* Timeout value in msec */ #define IFE_CSID_TIMEOUT 1000 @@ -5522,6 +5523,17 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->device_enabled = 0; ife_csid_hw->is_resetting = false; ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + + if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, + (1 << ife_csid_hw->hw_intf->hw_idx), 0) || + !cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE, + (1 << ife_csid_hw->hw_intf->hw_idx), 0)) { + CAM_DBG(CAM_ISP, "IFE:%d is not supported", + ife_csid_hw->hw_intf->hw_idx); + rc = -EINVAL; + return rc; + } + 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); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 6b0b2113bfe1..725c716ffb4a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -17,6 +17,8 @@ #include "cam_ife_hw_mgr.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include + static const char drv_name[] = "vfe"; @@ -681,6 +683,16 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info, return -ENODEV; } + if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, + (1 << hw_intf->hw_idx), 0) || + !cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE, + (1 << hw_intf->hw_idx), 0)) { + CAM_DBG(CAM_ISP, "IFE:%d is not supported", + hw_intf->hw_idx); + rc = -EINVAL; + return rc; + } + rc = cam_irq_controller_init(drv_name, CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX), vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller, From c15edd4c3d7f01bb0a5995a2fb87e69816b79149 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 21 Dec 2020 13:28:38 +0530 Subject: [PATCH 663/790] msm: camera: isp: Maintain clock rate relation between CSIHPY, CSID and TFE Added checks to confirm CSID frequency greater than CSIPHY frequency, TFE frequency greater than CSID frequency. Also TFE frequency should be such that it can accommodate PHY data rate. CRs-Fixed: 2847155 Change-Id: I5d3dcc53a6f27129f4b82cba1254445f58f6d0cf Signed-off-by: Shravya Samala --- drivers/cam_core/cam_context.c | 25 +++ drivers/cam_core/cam_context.h | 26 ++- drivers/cam_core/cam_hw_mgr_intf.h | 3 + drivers/cam_isp/cam_isp_context.c | 34 ++++ drivers/cam_isp/cam_isp_dev.c | 17 ++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 178 ++++++++++++++++++ .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 2 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 52 +++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 64 +++++++ drivers/cam_req_mgr/cam_subdev.h | 3 +- drivers/cam_utils/cam_soc_util.c | 17 ++ drivers/cam_utils/cam_soc_util.h | 13 ++ 13 files changed, 429 insertions(+), 7 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 5fc9387e339b..75424db0c16a 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -311,6 +311,31 @@ int cam_context_dump_pf_info(struct cam_context *ctx, return rc; } +int cam_context_handle_message(struct cam_context *ctx, + uint32_t msg_type, uint32_t *data) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if ((ctx->state > CAM_CTX_AVAILABLE) && + (ctx->state < CAM_CTX_STATE_MAX)) { + if (ctx->state_machine[ctx->state].msg_cb_ops) { + rc = ctx->state_machine[ctx->state].msg_cb_ops( + ctx, msg_type, data); + } else { + CAM_WARN(CAM_CORE, + "No message handler for ctx %d, state %d msg_type :%d", + ctx->dev_hdl, ctx->state, msg_type); + } + } + + return rc; +} + int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index d649b22167a1..5be078536ff5 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -158,14 +158,17 @@ struct cam_ctx_crm_ops { * @pagefault_ops: Function to be called on page fault * @dumpinfo_ops: Function to be invoked for dumping any * context info + * @msg_cb_ops: Function to be called on any message from + * other subdev notifications * */ struct cam_ctx_ops { - struct cam_ctx_ioctl_ops ioctl_ops; - struct cam_ctx_crm_ops crm_ops; - cam_hw_event_cb_func irq_ops; - cam_hw_pagefault_cb_func pagefault_ops; - cam_ctx_info_dump_cb_func dumpinfo_ops; + struct cam_ctx_ioctl_ops ioctl_ops; + struct cam_ctx_crm_ops crm_ops; + cam_hw_event_cb_func irq_ops; + cam_hw_pagefault_cb_func pagefault_ops; + cam_ctx_info_dump_cb_func dumpinfo_ops; + cam_ctx_message_cb_func msg_cb_ops; }; /** @@ -367,6 +370,19 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx, int cam_context_dump_pf_info(struct cam_context *ctx, struct cam_smmu_pf_info *pf_info); +/** + * cam_context_handle_message() + * + * @brief: Handle message callback command + * + * @ctx: Object pointer for cam_context + * @msg_type: message type sent from other subdev + * @data: data from other subdev + * + */ +int cam_context_handle_message(struct cam_context *ctx, + uint32_t msg_type, uint32_t *data); + /** * cam_context_handle_acquire_dev() * diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 9b6942acab61..c7537b5f361b 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -53,6 +53,9 @@ typedef int (*cam_hw_pagefault_cb_func)(void *context, typedef int (*cam_ctx_info_dump_cb_func)(void *context, enum cam_context_dump_id dump_id); +/* message callback function type */ +typedef int (*cam_ctx_message_cb_func)(void *context, + uint32_t message_type, uint32_t *data); /** * struct cam_hw_update_entry - Entry for hardware config * diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 713c6a23c4c1..e7e55e94b619 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -21,6 +21,7 @@ #include "cam_common_util.h" #include "cam_req_mgr_debug.h" #include "cam_cpas_api.h" +#include "cam_subdev.h" static const char isp_dev_name[] = "cam-isp"; @@ -33,6 +34,9 @@ static struct cam_isp_ctx_debug isp_ctx_debug; static int cam_isp_context_dump_requests(void *data, struct cam_smmu_pf_info *pf_info); +static int cam_isp_context_handle_message(void *context, + uint32_t msg_type, uint32_t *data); + static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); @@ -5772,6 +5776,7 @@ static struct cam_ctx_ops .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, + .msg_cb_ops = cam_isp_context_handle_message, }, /* Activated */ { @@ -5791,6 +5796,7 @@ static struct cam_ctx_ops .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, + .msg_cb_ops = cam_isp_context_handle_message, }, }; @@ -5933,6 +5939,34 @@ static int cam_isp_context_dump_requests(void *data, return rc; } +static int cam_isp_context_handle_message(void *context, + uint32_t msg_type, uint32_t *data) +{ + int rc = 0; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_context *ctx = (struct cam_context *)context; + + memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); + hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + + switch (msg_type) { + case CAM_SUBDEV_MESSAGE_CLOCK_UPDATE: + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_UPDATE_CLOCK; + isp_hw_cmd_args.cmd_data = (void *)data; + 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); + if (rc) + CAM_ERR(CAM_ISP, "Update clock rate failed rc: %d", rc); + break; + default: + CAM_ERR(CAM_ISP, "Invalid message type %d", msg_type); + } + return rc; +} + static int cam_isp_context_debug_register(void) { int rc = 0; diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 68eb02e9b466..6908a0807acb 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -38,6 +38,22 @@ static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } +static void cam_isp_subdev_handle_message( + struct v4l2_subdev *sd, + enum cam_subdev_message_type_t message_type, + uint32_t data) +{ + int i, rc = 0; + struct cam_node *node = v4l2_get_subdevdata(sd); + + CAM_DBG(CAM_ISP, "node name %s", node->name, data); + for (i = 0; i < node->ctx_size; i++) { + rc = cam_context_handle_message(&(node->ctx_list[i]), message_type, &data); + if (rc) + CAM_ERR(CAM_ISP, "Failed to handle message for %s", node->name); + } +} + static const struct of_device_id cam_isp_dt_match[] = { { .compatible = "qcom,cam-isp" @@ -113,6 +129,7 @@ static int cam_isp_dev_component_bind(struct device *dev, } else if (strnstr(compat_str, "tfe", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, CAM_TFE_DEVICE_TYPE); + g_isp_dev.sd.msg_cb = cam_isp_subdev_handle_message; g_isp_dev.isp_device_type = CAM_TFE_DEVICE_TYPE; g_isp_dev.max_context = CAM_TFE_CTX_MAX; } else { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index e930f6addb65..245ef46d6b7a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -306,6 +306,82 @@ err: return rc; } +static int cam_tfe_hw_mgr_get_clock_rate( + struct cam_isp_hw_mgr_res *isp_hw_res, + uint32_t *get_clock_rate) +{ + int i; + int rc = -EINVAL; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_CLOCK_RATE, + get_clock_rate, + sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + return rc; + } + } + } + + return rc; +} + +static int cam_tfe_hw_mgr_update_clock_rate( + struct cam_isp_hw_mgr_res *isp_hw_res, + uint32_t *set_clock_rate, + uint32_t *updated_clock_rate) +{ + int i; + int rc = 0; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, + set_clock_rate, + sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + return rc; + } + } + + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_CLOCK_RATE, + updated_clock_rate, + sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + return rc; + } + } + } + + return rc; +} + static int cam_tfe_hw_mgr_start_hw_res( struct cam_isp_hw_mgr_res *isp_hw_res, struct cam_tfe_hw_mgr_ctx *ctx) @@ -1824,6 +1900,105 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, } } +int cam_tfe_cshiphy_callback( + struct cam_tfe_hw_mgr_ctx *ctx, void *cmd_args) +{ + int rc = -EINVAL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + uint32_t *phy_clock_rate; + uint32_t clock_rate = 0; + uint32_t csid_clock_rate = 0, tfe_clock_rate = 0; + uint32_t updated_tfe_clk = 0, updated_csid_clk = 0; + + if (!ctx || !cmd_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + phy_clock_rate = (uint32_t *)cmd_args; + CAM_DBG(CAM_ISP, "clk rate csid ... in ctx id:%d", + ctx->ctx_index); + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_get_clock_rate(hw_mgr_res, + &clock_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "Can not get CSID clock rate(id :%d)", + hw_mgr_res->res_id); + return rc; + } + + if (!csid_clock_rate) + csid_clock_rate = clock_rate; + + if (clock_rate < csid_clock_rate) + csid_clock_rate = clock_rate; + + CAM_DBG(CAM_ISP, "clk rate csid: %lld %lld", + clock_rate, csid_clock_rate); + } + + CAM_DBG(CAM_ISP, "clk rate TFE in resource ctx id:%d", + ctx->ctx_index); + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_get_clock_rate(hw_mgr_res, + &clock_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "Can not get TFE clock rate (%d)", + hw_mgr_res->res_id); + return rc; + } + + if (!tfe_clock_rate) + tfe_clock_rate = clock_rate; + + if (clock_rate < tfe_clock_rate) + tfe_clock_rate = clock_rate; + + CAM_DBG(CAM_ISP, "clk rate tfe: %lld %lld", + clock_rate, tfe_clock_rate); + } + + if (*phy_clock_rate > csid_clock_rate) { + list_for_each_entry(hw_mgr_res, + &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, + phy_clock_rate, &updated_csid_clk); + } + + if (updated_csid_clk > tfe_clock_rate) { + list_for_each_entry(hw_mgr_res, + &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, + &updated_csid_clk, &updated_tfe_clk); + } + } + goto end; + } + + if (csid_clock_rate > tfe_clock_rate) { + list_for_each_entry(hw_mgr_res, + &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, + &csid_clock_rate, &updated_tfe_clk); + } + } +end: + /* final check */ + if ((*phy_clock_rate > updated_csid_clk) || + (updated_csid_clk > updated_tfe_clk) || + (*phy_clock_rate > updated_tfe_clk)) { + CAM_ERR(CAM_ISP, + "improper clock rates, phy:%lld csid:%lld tfe:%lld", + *phy_clock_rate, updated_csid_clk, updated_tfe_clk); + + return -EINVAL; + } + + return 0; +} + /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -4761,6 +4936,9 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) isp_hw_cmd_args->u.last_cdm_done = ctx->last_cdm_done_req; break; + case CAM_ISP_HW_MGR_CMD_UPDATE_CLOCK: + rc = cam_tfe_cshiphy_callback(ctx, isp_hw_cmd_args->cmd_data); + break; default: CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", hw_cmd_args->cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index e093a8bccfbc..cfac2f5b68ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -48,7 +48,6 @@ enum cam_isp_hw_event_type { CAM_ISP_HW_EVENT_MAX }; - /** * enum cam_isp_hw_err_type - Collection of the ISP error types for * ISP hardware event CAM_ISP_HW_EVENT_ERROR @@ -241,6 +240,7 @@ enum cam_isp_hw_mgr_command { CAM_ISP_HW_MGR_CMD_CTX_TYPE, CAM_ISP_HW_MGR_GET_PACKET_OPCODE, CAM_ISP_HW_MGR_GET_LAST_CDM_DONE, + CAM_ISP_HW_MGR_CMD_UPDATE_CLOCK, CAM_ISP_HW_MGR_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 64b22f7d7b62..64b6cd3ed253 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -135,6 +135,8 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG, CAM_ISP_HW_CMD_QUERY_BUS_CAP, + CAM_ISP_HW_CMD_GET_CLOCK_RATE, + CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 136b4e382199..a22a68e1efe0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -2404,6 +2404,52 @@ static int cam_tfe_csid_set_csid_clock( return 0; } +static int cam_tfe_csid_get_csid_clock( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_hw_soc_info *soc_info; + uint32_t *curr_clk_rate; + int src_clk_idx; + int rc = 0; + + if (!csid_hw) + return -EINVAL; + + soc_info = &csid_hw->hw_info->soc_info; + src_clk_idx = soc_info->src_clk_idx; + + curr_clk_rate = (uint32_t *)cmd_args; + + rc = cam_soc_util_get_clk_rate(soc_info->clk[src_clk_idx], + soc_info->clk_name[src_clk_idx], curr_clk_rate); + + CAM_DBG(CAM_ISP, "CSID clock rate %llu", *curr_clk_rate); + + return rc; +} + +static int cam_tfe_csid_set_csid_clock_dynamically( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_hw_soc_info *soc_info; + uint32_t *clk_rate; + int rc = 0; + + soc_info = &csid_hw->hw_info->soc_info; + clk_rate = (uint32_t *)cmd_args; + + CAM_DBG(CAM_ISP, "CSID clock rate %lld", *clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, *clk_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "unable to set clock dynamically rate:%lld", *clk_rate); + return rc; + } + + return rc; +} + static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, void *cmd_args) { @@ -2676,6 +2722,12 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_TFE_CSID_LOG_ACQUIRE_DATA: rc = cam_tfe_csid_log_acquire_data(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_GET_CLOCK_RATE: + rc = cam_tfe_csid_get_csid_clock(csid_hw, cmd_args); + break; + case CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE: + rc = cam_tfe_csid_set_csid_clock_dynamically(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 66f3ead97fed..74eae1a23ff3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -969,6 +969,62 @@ static int cam_tfe_top_set_hw_clk_rate( return rc; } +static int cam_tfe_top_get_hw_clk_rate( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, + uint32_t arg_size) +{ + struct cam_hw_soc_info *soc_info; + uint32_t *curr_clk_rate; + int src_clk_idx; + int rc = 0; + + if (!top_priv) { + CAM_ERR(CAM_ISP, "Error top_private NULL"); + return -EINVAL; + } + + soc_info = top_priv->common_data.soc_info; + src_clk_idx = soc_info->src_clk_idx; + + curr_clk_rate = (uint32_t *)cmd_args; + + rc = cam_soc_util_get_clk_rate(soc_info->clk[src_clk_idx], + soc_info->clk_name[src_clk_idx], curr_clk_rate); + + CAM_DBG(CAM_ISP, "TFE clock rate %llu", *curr_clk_rate); + + return rc; +} + +static int cam_tfe_top_dynamic_clock_update( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, + uint32_t arg_size) +{ + struct cam_hw_soc_info *soc_info; + int src_clk_idx; + uint32_t *clk_rate; + int rc = 0; + + soc_info = top_priv->common_data.soc_info; + src_clk_idx = soc_info->src_clk_idx; + + clk_rate = (uint32_t *)cmd_args; + + CAM_DBG(CAM_ISP, "TFE clock rate %lld", *clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, *clk_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "unable to set clock dynamically rate:%lld", + *clk_rate); + return rc; + } + + return rc; +} + static struct cam_axi_vote *cam_tfe_top_delay_bw_reduction( struct cam_tfe_top_priv *top_priv, uint64_t *to_be_applied_bw) @@ -2881,6 +2937,14 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, rc = cam_tfe_set_top_debug(core_info, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_GET_CLOCK_RATE: + rc = cam_tfe_top_get_hw_clk_rate(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE: + rc = cam_tfe_top_dynamic_clock_update(core_info->top_priv, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_GET_BUF_UPDATE: case CAM_ISP_HW_CMD_GET_HFR_UPDATE: case CAM_ISP_HW_CMD_STRIPE_UPDATE: diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index c2ded0c9103e..ae22529ef2a1 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -17,7 +17,8 @@ #define CAM_SUBDEVICE_EVENT_MAX 30 enum cam_subdev_message_type_t { - CAM_SUBDEV_MESSAGE_IRQ_ERR = 0x1 + CAM_SUBDEV_MESSAGE_IRQ_ERR = 0x1, + CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; /** diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 2371c5c1c068..474c7c34d9b1 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -346,6 +346,23 @@ int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info) return 0; } +int cam_soc_util_get_clk_rate(struct clk *clk, const char *clk_name, + uint32_t *clk_rate) +{ + uint32_t clk_rate_round; + + clk_rate_round = clk_get_rate(clk); + if (clk_rate_round < 0) { + CAM_ERR(CAM_UTIL, "get_rate failed on %s", clk_name); + return clk_rate_round; + } + + *clk_rate = clk_rate_round; + CAM_DBG(CAM_UTIL, "get rate %lld on %s", *clk_rate, clk_name); + + return 0; +} + long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_index, unsigned long clk_rate) { diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index ff75fca12d5d..aea1a396e4fd 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -405,6 +405,19 @@ int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_index, unsigned long clk_rate); +/** + * cam_soc_util_get_clk_rate() + * + * @brief: Get the rate on the source clock. + * @clk: Src clock reference pointer to get clock rate + * @clk_name: Name of src clock + * @clk_rate: Clock rate associated with the src clk + * + * @return: success or failure + */ +int cam_soc_util_get_clk_rate(struct clk *clk, const char *clk_name, + uint32_t *clk_rate); + /** * cam_soc_util_set_src_clk_rate() * From 1fbbac1512e3e4d0862314d9dda3807d9566ada4 Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Fri, 8 Jan 2021 10:24:52 +0530 Subject: [PATCH 664/790] Revert "msm: camera: jpeg: Add more data in case of smmu pf" This reverts commit 0204c76b587b09a3f2906c62d50e7179c3d18872. Change-Id: I43ff50e01db0ac0cc2b9b56753198ef1653d942a Signed-off-by: Sridhar Gujje --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 11 +------ drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 4 +-- drivers/cam_req_mgr/cam_mem_mgr.c | 18 ++++-------- drivers/cam_req_mgr/cam_mem_mgr.h | 34 ++++++++++------------ 4 files changed, 23 insertions(+), 44 deletions(-) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index fc1d8c507af2..7d3b42e7a740 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -643,14 +643,6 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; request_id = (uintptr_t)config_args->priv; - if (request_id <= ctx_data->last_flush_req) { - CAM_WARN(CAM_JPEG, - "Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u", - request_id, ctx_data->last_flush_req); - mutex_unlock(&hw_mgr->hw_mgr_mutex); - return -EINVAL; - } - p_cfg_req->req_id = request_id; p_cfg_req->num_hw_entry_processed = 0; hw_update_entries = config_args->hw_update_entries; @@ -1093,7 +1085,6 @@ static int cam_jpeg_mgr_hw_flush(void *hw_mgr_priv, void *flush_hw_args) return -EINVAL; } - ctx_data->last_flush_req = flush_args->last_flush_req; switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: rc = cam_jpeg_mgr_flush(hw_mgr_priv, ctx_data); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 6af8e9e0df35..4e90f5386f32 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_HW_MGR_H @@ -98,7 +98,6 @@ struct cam_jpeg_hw_cfg_req { * @in_use: Flag for context usage * @wait_complete: Completion info * @cdm_cmd: Cdm cmd submitted for that context. - * @last_flush_req: req id which was flushed last. */ struct cam_jpeg_hw_ctx_data { void *context_priv; @@ -108,7 +107,6 @@ struct cam_jpeg_hw_ctx_data { bool in_use; struct completion wait_complete; struct cam_cdm_bl_request *cdm_cmd; - uint64_t last_flush_req; }; /** diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 900d7537966f..b928c7da46c7 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -244,9 +244,8 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, return -ENOENT; if (!tbl.bufq[idx].active) { - CAM_ERR(CAM_MEM, - "Buffer at idx=%d is already unmapped, vaddr 0x%x unmaped_vaddr 0x%x", - idx, tbl.bufq[idx].vaddr, tbl.bufq[idx].unmaped_vaddr); + CAM_ERR(CAM_MEM, "Buffer at idx=%d is already unmapped,", + idx); return -EAGAIN; } @@ -758,7 +757,6 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd) tbl.bufq[idx].kmdvaddr = kvaddr; tbl.bufq[idx].vaddr = hw_vaddr; - tbl.bufq[idx].unmaped_vaddr = 0; tbl.bufq[idx].dma_buf = dmabuf; tbl.bufq[idx].len = cmd->len; tbl.bufq[idx].num_hdl = cmd->num_hdl; @@ -885,12 +883,10 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd) CAM_MEM_MGR_SET_SECURE_HDL(tbl.bufq[idx].buf_handle, true); tbl.bufq[idx].kmdvaddr = 0; - if (cmd->num_hdl > 0) { + if (cmd->num_hdl > 0) tbl.bufq[idx].vaddr = hw_vaddr; - tbl.bufq[idx].unmaped_vaddr = 0; - } else { + else tbl.bufq[idx].vaddr = 0; - } tbl.bufq[idx].dma_buf = dmabuf; tbl.bufq[idx].len = len; @@ -1024,7 +1020,6 @@ static int cam_mem_mgr_cleanup_table(void) tbl.bufq[i].flags = 0; tbl.bufq[i].buf_handle = -1; tbl.bufq[i].vaddr = 0; - tbl.bufq[i].unmaped_vaddr = 0; tbl.bufq[i].len = 0; memset(tbl.bufq[i].hdls, 0, sizeof(int32_t) * tbl.bufq[i].num_hdl); @@ -1083,7 +1078,6 @@ static int cam_mem_util_unmap(int32_t idx, /* Deactivate the buffer queue to prevent multiple unmap */ mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].active = false; - tbl.bufq[idx].unmaped_vaddr = tbl.bufq[idx].vaddr; tbl.bufq[idx].vaddr = 0; mutex_unlock(&tbl.bufq[idx].q_lock); mutex_unlock(&tbl.m_lock); @@ -1300,7 +1294,6 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, tbl.bufq[idx].kmdvaddr = kvaddr; tbl.bufq[idx].vaddr = iova; - tbl.bufq[idx].unmaped_vaddr = 0; tbl.bufq[idx].len = inp->size; tbl.bufq[idx].num_hdl = num_hdl; @@ -1450,7 +1443,6 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp, tbl.bufq[idx].kmdvaddr = 0; tbl.bufq[idx].vaddr = iova; - tbl.bufq[idx].unmaped_vaddr = 0; tbl.bufq[idx].len = request_len; tbl.bufq[idx].num_hdl = num_hdl; diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index c9931fc4f06b..26ab9cb75319 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_MEM_MGR_H_ @@ -26,22 +26,21 @@ enum cam_smmu_mapping_client { /** * struct cam_mem_buf_queue * - * @dma_buf: pointer to the allocated dma_buf in the table - * @q_lock: mutex lock for buffer - * @hdls: list of mapped handles - * @num_hdl: number of handles - * @fd: file descriptor of buffer - * @buf_handle: unique handle for buffer - * @align: alignment for allocation - * @len: size of buffer - * @flags: attributes of buffer - * @vaddr: IOVA of buffer - * @kmdvaddr: Kernel virtual address - * @active: state of the buffer - * @is_imported: Flag indicating if buffer is imported from an FD in user space - * @is_internal: Flag indicating kernel allocated buffer - * @timestamp: Timestamp at which this entry in tbl was made - * @unmaped_vaddr: This will cache the vaddr if it is unmapped. + * @dma_buf: pointer to the allocated dma_buf in the table + * @q_lock: mutex lock for buffer + * @hdls: list of mapped handles + * @num_hdl: number of handles + * @fd: file descriptor of buffer + * @buf_handle: unique handle for buffer + * @align: alignment for allocation + * @len: size of buffer + * @flags: attributes of buffer + * @vaddr: IOVA of buffer + * @kmdvaddr: Kernel virtual address + * @active: state of the buffer + * @is_imported: Flag indicating if buffer is imported from an FD in user space + * @is_internal: Flag indicating kernel allocated buffer + * @timestamp: Timestamp at which this entry in tbl was made */ struct cam_mem_buf_queue { struct dma_buf *dma_buf; @@ -54,7 +53,6 @@ struct cam_mem_buf_queue { size_t len; uint32_t flags; uint64_t vaddr; - uint64_t unmaped_vaddr; uintptr_t kmdvaddr; bool active; bool is_imported; From c3f06e4d02d9bf72c5b945a5a3851fd40478df24 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Tue, 15 Dec 2020 16:10:13 +0530 Subject: [PATCH 665/790] msm: camera: isp: Add new packer format to support LSB alignment Add new packer format to support LSB alignment for plain16_10 packer format. CRs-Fixed: 2825675 Change-Id: I401241dc14dc67d3b363d3d39b37aabe716e167c Signed-off-by: Vikram Sharma --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 22 +++++++++++++++++++ include/uapi/camera/media/cam_defs.h | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 68622900b9a8..dac865bea9f5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -483,6 +483,7 @@ static int cam_vfe_bus_get_num_wm( case CAM_FORMAT_DPCM_14_10_14: case CAM_FORMAT_PLAIN8: case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: case CAM_FORMAT_PLAIN16_12: case CAM_FORMAT_PLAIN16_14: case CAM_FORMAT_PLAIN16_16: @@ -506,6 +507,7 @@ static int cam_vfe_bus_get_num_wm( case CAM_FORMAT_UBWC_TP10: case CAM_FORMAT_UBWC_P010: case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: return 2; default: break; @@ -518,6 +520,7 @@ static int cam_vfe_bus_get_num_wm( case CAM_FORMAT_PLAIN8: case CAM_FORMAT_TP10: case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: return 2; case CAM_FORMAT_Y_ONLY: return 1; @@ -542,6 +545,7 @@ static int cam_vfe_bus_get_num_wm( case CAM_FORMAT_ARGB_14: case CAM_FORMAT_PLAIN8: case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: case CAM_FORMAT_PLAIN16_12: case CAM_FORMAT_PLAIN16_14: return 1; @@ -553,6 +557,7 @@ static int cam_vfe_bus_get_num_wm( switch (format) { case CAM_FORMAT_PLAIN8: case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: case CAM_FORMAT_PLAIN16_12: case CAM_FORMAT_PLAIN16_14: return 1; @@ -564,6 +569,7 @@ static int cam_vfe_bus_get_num_wm( switch (format) { case CAM_FORMAT_PLAIN16_8: case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: case CAM_FORMAT_PLAIN16_12: case CAM_FORMAT_PLAIN16_14: case CAM_FORMAT_PLAIN16_16: @@ -920,6 +926,7 @@ static enum cam_vfe_bus_packer_format case CAM_FORMAT_PLAIN8: return PACKER_FMT_PLAIN_8; case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: return PACKER_FMT_PLAIN_16_10BPP; case CAM_FORMAT_PLAIN16_12: return PACKER_FMT_PLAIN_16_12BPP; @@ -1022,6 +1029,7 @@ static int cam_vfe_bus_acquire_wm( rsrc_data->stride = rsrc_data->width; break; case CAM_FORMAT_PLAIN16_10: + case CAM_FORMAT_PLAIN16_10_LSB: case CAM_FORMAT_PLAIN16_12: case CAM_FORMAT_PLAIN16_14: case CAM_FORMAT_PLAIN16_16: @@ -1109,6 +1117,20 @@ static int cam_vfe_bus_acquire_wm( return -EINVAL; } break; + case CAM_FORMAT_PLAIN16_10_LSB: + rsrc_data->pack_fmt |= 0x10; + switch (plane) { + case PLANE_C: + rsrc_data->height /= 2; + break; + case PLANE_Y: + break; + default: + CAM_ERR(CAM_ISP, "Invalid plane %d", plane); + return -EINVAL; + } + rsrc_data->width *= 2; + break; case CAM_FORMAT_PLAIN16_10: switch (plane) { case PLANE_C: diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index d6e2a7fb15e1..8716d1e7066c 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -178,7 +178,8 @@ struct cam_iommu_handle { #define CAM_FORMAT_DPCM_12_10_12 46 #define CAM_FORMAT_PLAIN32 47 #define CAM_FORMAT_ARGB_16 48 -#define CAM_FORMAT_MAX 49 +#define CAM_FORMAT_PLAIN16_10_LSB 49 +#define CAM_FORMAT_MAX 50 /* Pixel Patterns */ #define PIXEL_PATTERN_RGRGRG 0x0 From 851a04fce1153c37332c2e6c2b35e5cb3cfb1f15 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Tue, 19 Jan 2021 10:39:02 +0530 Subject: [PATCH 666/790] msm: camera: csiphy: Trigger ISP callback on phy clock change Trigger callback to ISP each time when there is a change in phy clock so that csid and tfe clock rates can be updated accordingly. Argument passed in callback api is the final phy clock rate that is applied. CRs-Fixed: 2854066 Change-Id: Ia74465e4082e08b4c50338e0eb779f996afa2795 Signed-off-by: shiwgupt --- .../cam_csiphy/cam_csiphy_core.c | 21 ++++++++++++-- .../cam_csiphy/cam_csiphy_soc.c | 9 +++++- drivers/cam_utils/cam_soc_util.c | 28 ++++++++++++++++++- drivers/cam_utils/cam_soc_util.h | 6 +++- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index c5c7b70edba6..ece371256868 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -16,6 +16,7 @@ #include "cam_mem_mgr.h" #include "cam_cpas_api.h" #include "cam_compat.h" +#include "cam_subdev.h" #define SCM_SVC_CAMERASS 0x18 #define SECURE_SYSCALL_ID 0x6 @@ -1379,8 +1380,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote = {0}; struct cam_start_stop_dev_cmd config; - int32_t offset; + int32_t i, offset; int clk_vote_level = -1; + unsigned long clk_rate = 0; rc = copy_from_user(&config, (void __user *)cmd->handle, sizeof(config)); @@ -1421,6 +1423,21 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = 0; } + for (i = 0; i < csiphy_dev->soc_info.num_clk; i++) { + if (i == csiphy_dev->soc_info.src_clk_idx) { + CAM_DBG(CAM_CSIPHY, "Skipping call back for src clk %s", + csiphy_dev->soc_info.clk_name[i]); + continue; + } + clk_rate = cam_soc_util_get_clk_rate_applied( + &csiphy_dev->soc_info, i, false, clk_vote_level); + if(clk_rate > 0) { + cam_subdev_notify_message(CAM_TFE_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_CLOCK_UPDATE, + clk_rate); + } + } + if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { if (!cam_cpas_is_feature_supported( CAM_CPAS_SECURE_CAMERA_ENABLE, diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 68770d526c31..dd89452150ea 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_csiphy_soc.h" @@ -14,6 +14,7 @@ #include "include/cam_csiphy_1_2_5_hwreg.h" #include "include/cam_csiphy_2_0_hwreg.h" #include "include/cam_csiphy_2_1_0_hwreg.h" +#include "cam_subdev.h" /* Clock divide factor for CPHY spec v1.0 */ #define CSIPHY_DIVISOR_16 16 @@ -189,6 +190,7 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index) int32_t rc = 0; struct cam_hw_soc_info *soc_info; enum cam_vote_level vote_level = CAM_SVS_VOTE; + unsigned long clk_rate = 0; soc_info = &csiphy_dev->soc_info; @@ -209,6 +211,11 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index) rc = cam_soc_util_set_src_clk_rate(soc_info, soc_info->clk_rate[0][soc_info->src_clk_idx]); + clk_rate = cam_soc_util_get_clk_rate_applied(soc_info, + soc_info->src_clk_idx, true, vote_level); + cam_subdev_notify_message(CAM_TFE_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_CLOCK_UPDATE, + clk_rate); if (rc < 0) { CAM_ERR(CAM_CSIPHY, "csiphy_clk_set_rate failed rc: %d", rc); diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 474c7c34d9b1..13fe14f2c3c3 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include @@ -312,6 +312,32 @@ static int cam_soc_util_get_clk_level_to_apply( return 0; } +unsigned long cam_soc_util_get_clk_rate_applied( + struct cam_hw_soc_info *soc_info, int32_t index, bool is_src, + enum cam_vote_level clk_level) +{ + unsigned long clk_rate = 0; + struct clk *clk = NULL; + int rc = 0; + enum cam_vote_level apply_level; + + if (is_src) { + clk = soc_info->clk[index]; + clk_rate = clk_get_rate(clk); + } + else { + rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level, + &apply_level); + if (rc) + return rc; + if(soc_info->clk_rate[apply_level][index] > 0) { + clk = soc_info->clk[index]; + clk_rate = clk_get_rate(clk); + } + } + return clk_rate; +} + int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info) { if (!soc_info) { diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index aea1a396e4fd..2c9d27e4e199 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SOC_UTIL_H_ @@ -674,6 +674,10 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info, int64_t clk_rate, int clk_idx, int32_t *clk_lvl); +unsigned long cam_soc_util_get_clk_rate_applied( + struct cam_hw_soc_info *soc_info, int32_t index, bool is_src, + enum cam_vote_level clk_level); + /* Callback to get reg space data for specific HW */ typedef int (*cam_soc_util_regspace_data_cb)(uint32_t reg_base_type, void *ctx, struct cam_hw_soc_info **soc_info_ptr, From d2808569625e0c7831ed1ccc9b4f2f93fb78b842 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Tue, 27 Oct 2020 08:49:22 +0530 Subject: [PATCH 667/790] msm: camera: cci: Add report id in report command for CCI I2C queue -Report id is a unique 4-bit value associated with the report command. Interrupt is generated on each report command execution. This change helps to know whether interrupt is received for a corresponding report id. Report id can be checked in REPORT_STATUS register. This change adds report id in report command of CCI I2C queue as per HPG. CRs-Fixed: 2857533 Change-Id: I0c3066962e21c7c024e67ae81ecb762ba331e329 Signed-off-by: shiwgupt --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 21 ++++++++++++++++--- .../cam_sensor_module/cam_cci/cam_cci_dev.h | 1 + 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 0d6348108c18..59dad9ee4e72 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -104,13 +104,20 @@ static int32_t cam_cci_validate_queue(struct cci_device *cci_dev, if ((read_val + len + 1) > cci_dev->cci_i2c_queue_info[master][queue].max_queue_size) { uint32_t reg_val = 0; - uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8); + uint32_t report_id = + cci_dev->cci_i2c_queue_info[master][queue].report_id; + uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8) | + (1 << 9) | (report_id << 4); CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD"); cam_io_w_mb(report_val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); read_val++; + cci_dev->cci_i2c_queue_info[master][queue].report_id++; + if (cci_dev->cci_i2c_queue_info[master][queue].report_id == REPORT_IDSIZE) + cci_dev->cci_i2c_queue_info[master][queue].report_id = 0; + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d, queue: %d", read_val, queue); @@ -305,14 +312,22 @@ static void cam_cci_load_report_cmd(struct cci_device *cci_dev, uint32_t reg_offset = master * 0x200 + queue * 0x100; uint32_t read_val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); - uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8); + uint32_t report_id = + cci_dev->cci_i2c_queue_info[master][queue].report_id; + uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8) | + (1 << 9) | (report_id << 4); - CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD curr_w_cnt: %d", read_val); + CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD curr_w_cnt: %d report_id %d", + read_val, report_id); cam_io_w_mb(report_val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); read_val++; + cci_dev->cci_i2c_queue_info[master][queue].report_id++; + if (cci_dev->cci_i2c_queue_info[master][queue].report_id == REPORT_IDSIZE) + cci_dev->cci_i2c_queue_info[master][queue].report_id = 0; + CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d", read_val); cam_io_w_mb(read_val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index a72f4d836683..46cf0315dcab 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -65,6 +65,7 @@ #define CAM_CCI_TIMEOUT_DUMP_EN BIT(2) #define CCI_VERSION_1_2_9 0x10020009 +#define REPORT_IDSIZE 16 enum cci_i2c_sync { MSM_SYNC_DISABLE, MSM_SYNC_ENABLE, From 1996f82b710f29ac6b17979d1556dbd6fa55667a Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 8 Dec 2020 13:11:52 -0800 Subject: [PATCH 668/790] msm: camera: common: Improve the CSID logging Improve CSID irq logging for better debugging. Add support to dump the hw source clock. CRs-Fixed: 2808577 Change-Id: I06608588ef7a6e0ebc174a1ba138f6e16a9094f2 Signed-off-by: Jigar Agrawal --- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 62 ++++-- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 16 +- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 183 ++++++++++-------- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 4 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 3 +- .../isp_hw/ppi_hw/cam_csid_ppi_core.c | 4 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c | 4 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 3 +- .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c | 4 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 28 ++- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 29 ++- .../cam_csiphy/cam_csiphy_soc.c | 4 +- .../cam_sensor_utils/cam_sensor_util.c | 5 +- drivers/cam_utils/cam_soc_util.c | 48 +++-- drivers/cam_utils/cam_soc_util.h | 7 +- 15 files changed, 274 insertions(+), 130 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 9fd46a2f3f8a..f0ea6fe8fb24 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -323,6 +323,41 @@ static int cam_ife_hw_mgr_is_rdi_res(uint32_t res_id) return rc; } +static int cam_ife_hw_mgr_dump_hw_src_clock(uint8_t hw_idx, + enum cam_isp_hw_type hw_type) +{ + + struct cam_isp_hw_intf_data *hw_intf_data = NULL; + struct cam_hw_intf *hw_intf = NULL; + uint8_t dummy_args; + + switch (hw_type) { + case CAM_ISP_HW_TYPE_VFE: + if (!g_ife_hw_mgr.ife_devices[hw_idx]) { + CAM_ERR(CAM_ISP, "No vfe device added yet"); + return -ENODEV; + } + + hw_intf_data = g_ife_hw_mgr.ife_devices[hw_idx]; + if (!hw_intf_data->hw_intf) { + CAM_ERR(CAM_ISP, "hw_intf is null"); + return -EINVAL; + } + + hw_intf = hw_intf_data->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE, + (void *)&dummy_args, sizeof(uint8_t)); + } + break; + default: + CAM_ERR(CAM_ISP, "Unsupported HW Type: %u", hw_type); + } + + return 0; +} + static int cam_ife_hw_mgr_reset_csid_res( struct cam_isp_hw_mgr_res *isp_hw_res) { @@ -7664,15 +7699,14 @@ static int cam_ife_hw_mgr_handle_hw_dump_info( static int cam_ife_hw_mgr_handle_csid_event( struct cam_isp_hw_event_info *event_info) { - struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_isp_hw_error_event_data error_event_data = {0}; struct cam_ife_hw_event_recovery_data recovery_data = {0}; /* this can be extended based on the types of error * received from CSID */ switch (event_info->err_type) { - case CAM_ISP_HW_ERROR_CSID_FATAL: { - + case CAM_ISP_HW_ERROR_CSID_FATAL: if (!g_ife_hw_mgr.debug_cfg.enable_csid_recovery) break; @@ -7681,7 +7715,12 @@ static int cam_ife_hw_mgr_handle_csid_event( event_info->hw_idx, &recovery_data); break; - } + case CAM_ISP_HW_ERROR_CSID_OVERFLOW: + if (cam_ife_hw_mgr_dump_hw_src_clock(event_info->hw_idx, + CAM_ISP_HW_TYPE_VFE)) + CAM_ERR_RATE_LIMIT(CAM_ISP, + "VFE%d src_clk_rate dump failed"); + break; default: break; } @@ -7692,12 +7731,12 @@ static int cam_ife_hw_mgr_handle_hw_err( void *ctx, void *evt_info) { - struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx; - struct cam_isp_hw_event_info *event_info = evt_info; - uint32_t core_idx; - struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx; + struct cam_isp_hw_event_info *event_info = evt_info; + uint32_t core_idx; + struct cam_isp_hw_error_event_data error_event_data = {0}; struct cam_ife_hw_event_recovery_data recovery_data = {0}; - int rc = -EINVAL; + int rc = -EINVAL; if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; @@ -7707,7 +7746,8 @@ static int cam_ife_hw_mgr_handle_hw_err( error_event_data.error_type = CAM_ISP_HW_ERROR_BUSIF_OVERFLOW; spin_lock(&g_ife_hw_mgr.ctx_lock); - if (event_info->err_type == CAM_ISP_HW_ERROR_CSID_FATAL) { + if ((event_info->err_type == CAM_ISP_HW_ERROR_CSID_FATAL) || + (event_info->err_type == CAM_ISP_HW_ERROR_CSID_OVERFLOW)) { rc = cam_ife_hw_mgr_handle_csid_event(event_info); spin_unlock(&g_ife_hw_mgr.ctx_lock); return rc; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index cfac2f5b68ca..1e1ac79be6fd 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_MGR_INTF_H_ @@ -53,13 +53,13 @@ enum cam_isp_hw_event_type { * ISP hardware event CAM_ISP_HW_EVENT_ERROR */ enum cam_isp_hw_err_type { - CAM_ISP_HW_ERROR_NONE, - CAM_ISP_HW_ERROR_OVERFLOW, - CAM_ISP_HW_ERROR_P2I_ERROR, - CAM_ISP_HW_ERROR_VIOLATION, - CAM_ISP_HW_ERROR_BUSIF_OVERFLOW, - CAM_ISP_HW_ERROR_CSID_FATAL, - CAM_ISP_HW_ERROR_MAX, + CAM_ISP_HW_ERROR_NONE = 0x0001, + CAM_ISP_HW_ERROR_OVERFLOW = 0x0002, + CAM_ISP_HW_ERROR_P2I_ERROR = 0x0004, + CAM_ISP_HW_ERROR_VIOLATION = 0x0008, + CAM_ISP_HW_ERROR_BUSIF_OVERFLOW = 0x0010, + CAM_ISP_HW_ERROR_CSID_FATAL = 0x0020, + CAM_ISP_HW_ERROR_CSID_OVERFLOW = 0x0040, }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index ef50a1ab51eb..6efeb80bbdb5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -4663,7 +4663,6 @@ static int cam_csid_evt_bottom_half_handler( struct cam_ife_csid_hw *csid_hw; struct cam_csid_evt_payload *evt_payload; int i; - int rc = 0; struct cam_isp_hw_event_info event_info; const struct cam_ife_csid_reg_offset *csid_reg; int udi_start_idx = CAM_IFE_CSID_IRQ_REG_UDI_0; @@ -4697,7 +4696,10 @@ static int cam_csid_evt_bottom_half_handler( goto end; } - if (csid_hw->sof_irq_triggered && (evt_payload->evt_type == + CAM_DBG(CAM_ISP, "CSID[%d] error type 0x%x", csid_hw->hw_intf->hw_idx, + evt_payload->evt_type); + + if (csid_hw->sof_irq_triggered && (evt_payload->evt_type & CAM_ISP_HW_ERROR_NONE)) { if (evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & CSID_PATH_INFO_INPUT_SOF) { @@ -4728,9 +4730,12 @@ static int cam_csid_evt_bottom_half_handler( "CSID:%d UDI:%d SOF received", csid_hw->hw_intf->hw_idx, i); } - } else { + } + + if ((evt_payload->evt_type & CAM_ISP_HW_ERROR_CSID_FATAL) || + (evt_payload->evt_type & CAM_ISP_HW_ERROR_CSID_OVERFLOW)) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID %d err %d phy %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x PPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x RDI3: 0x%x UDI0: 0x%x UDI1: 0x%x UDI2: 0x%x", + "CSID %d err 0x%x phy %d irq status TOP: 0x%x RX: 0x%x IPP: 0x%x PPP: 0x%x RDI0: 0x%x RDI1: 0x%x RDI2: 0x%x RDI3: 0x%x UDI0: 0x%x UDI1: 0x%x UDI2: 0x%x", csid_hw->hw_intf->hw_idx, evt_payload->evt_type, csid_hw->csi2_rx_cfg.phy_sel, @@ -4747,32 +4752,28 @@ static int cam_csid_evt_bottom_half_handler( evt_payload->irq_status[CAM_IFE_CSID_IRQ_REG_UDI_2]); } - if (evt_payload->evt_type == CAM_ISP_HW_ERROR_CSID_FATAL) - cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, - CAM_SUBDEV_MESSAGE_IRQ_ERR, - csid_hw->csi2_rx_cfg.phy_sel); - /* this hunk can be extended to handle more cases * which we want to offload to bottom half from * irq handlers */ - event_info.err_type = evt_payload->evt_type; event_info.hw_idx = evt_payload->hw_idx; - switch (evt_payload->evt_type) { - case CAM_ISP_HW_ERROR_CSID_FATAL: + if (evt_payload->evt_type & CAM_ISP_HW_ERROR_CSID_FATAL) { + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + csid_hw->csi2_rx_cfg.phy_sel); if (csid_hw->fatal_err_detected) - break; + goto end; csid_hw->fatal_err_detected = true; - rc = csid_hw->event_cb(NULL, + event_info.err_type = CAM_ISP_HW_ERROR_CSID_FATAL; + csid_hw->event_cb(NULL, CAM_ISP_HW_EVENT_ERROR, (void *)&event_info); - break; + } - default: - CAM_DBG(CAM_ISP, "CSID[%d] error type %d", - csid_hw->hw_intf->hw_idx, - evt_payload->evt_type); - break; + if (evt_payload->evt_type & CAM_ISP_HW_ERROR_CSID_OVERFLOW) { + event_info.err_type = CAM_ISP_HW_ERROR_CSID_OVERFLOW; + csid_hw->event_cb(NULL, + CAM_ISP_HW_EVENT_ERROR, (void *)&event_info); } end: cam_csid_put_evt_payload(csid_hw, &evt_payload); @@ -4781,7 +4782,7 @@ end: static int cam_csid_handle_hw_err_irq( struct cam_ife_csid_hw *csid_hw, - int evt_type, + uint32_t evt_type, uint32_t *irq_status) { int rc = 0; @@ -4789,7 +4790,7 @@ static int cam_csid_handle_hw_err_irq( void *bh_cmd = NULL; struct cam_csid_evt_payload *evt_payload; - CAM_DBG(CAM_ISP, "CSID[%d] error %d", + CAM_DBG(CAM_ISP, "CSID[%d] error 0x%x", csid_hw->hw_intf->hw_idx, evt_type); rc = cam_csid_get_evt_payload(csid_hw, &evt_payload); @@ -4803,7 +4804,7 @@ static int cam_csid_handle_hw_err_irq( rc = tasklet_bh_api.get_bh_payload_func(csid_hw->tasklet, &bh_cmd); if (rc || !bh_cmd) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID[%d] Can not get cmd for tasklet, evt_type %d", + "CSID[%d] Can not get cmd for tasklet, evt_type 0x%x", csid_hw->hw_intf->hw_idx, evt_type); cam_csid_put_evt_payload(csid_hw, &evt_payload); @@ -4832,11 +4833,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) struct cam_hw_soc_info *soc_info; const struct cam_ife_csid_reg_offset *csid_reg; const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg; - uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX] = {0}; - uint32_t i, val, val2; - bool fatal_err_detected = false; - uint32_t sof_irq_debug_en = 0, log_en = 0; - unsigned long flags; + uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX] = {0}; + uint32_t i, val, val2; + bool fatal_err_detected = false; + uint32_t sof_irq_debug_en = 0; + uint32_t event_type = 0; + unsigned long flags; csid_hw = (struct cam_ife_csid_hw *)data; @@ -4966,76 +4968,94 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if (csid_hw->device_enabled == 1) { if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RX_ERROR_LANE0_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz", + csid_hw->hw_intf->hw_idx, + soc_info->applied_src_clk_rate); fatal_err_detected = true; goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RX_ERROR_LANE1_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz", + csid_hw->hw_intf->hw_idx, + soc_info->applied_src_clk_rate); fatal_err_detected = true; goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RX_ERROR_LANE2_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz", + csid_hw->hw_intf->hw_idx, + soc_info->applied_src_clk_rate); fatal_err_detected = true; goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RX_ERROR_LANE3_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz", + csid_hw->hw_intf->hw_idx, + soc_info->applied_src_clk_rate); fatal_err_detected = true; goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RX_ERROR_TPG_FIFO_OVERFLOW: Backpressure from IFE", csid_hw->hw_intf->hw_idx); fatal_err_detected = true; + event_type |= CAM_ISP_HW_ERROR_CSID_OVERFLOW; goto handle_fatal_error; } if ((irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) && (!csid_hw->epd_supported)) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d CPHY_EOT_RECEPTION", + "CSID:%d CPHY_EOT_RECEPTION: No EOT on lane/s", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) { CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d CPHY_SOT_RECEPTION", + "CSID:%d CPHY_SOT_RECEPTION: Less SOTs on lane/s", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d CPHY_PH_CRC CPHY: Pkt Hdr CRC mismatch", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CRC) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d ERROR_CRC CPHY: Long pkt payload CRC mismatch", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_ECC) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d ERROR_ECC: Dphy pkt hdr errors unrecoverable", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_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); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); + + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d MMAPPED_VC_DT: VC:%d DT:%d mapped to more than 1 csid paths", + csid_hw->hw_intf->hw_idx, (val >> 22), + ((val >> 16) & 0x3F), (val & 0xFFFF)); } if ((irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT) && @@ -5046,21 +5066,25 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d UNMAPPED_VC_DT. VC: %d DT: %d WC: %d", + "CSID:%d UNMAPPED_VC_DT: VC:%d DT:%d WC:%d not mapped to any csid paths", csid_hw->hw_intf->hw_idx, (val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF)); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); + CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d ERROR_STREAM_UNDERFLOW", - csid_hw->hw_intf->hw_idx); + "CSID:%d ERROR_STREAM_UNDERFLOW: Fewer bytes rcvd than WC:%d in pkt hdr", + csid_hw->hw_intf->hw_idx, (val & 0xFFFF)); csid_hw->error_irq_count++; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) { - CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME", + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d UNBOUNDED_FRAME: Frame started with EOF or No EOF", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; } @@ -5078,7 +5102,8 @@ handle_fatal_error: if (fatal_err_detected) { cam_ife_csid_halt_csi2(csid_hw); cam_csid_handle_hw_err_irq(csid_hw, - CAM_ISP_HW_ERROR_CSID_FATAL, irq_status); + (event_type | CAM_ISP_HW_ERROR_CSID_FATAL), irq_status); + event_type = 0; } if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) { @@ -5206,7 +5231,7 @@ handle_fatal_error: "CSID:%d IPP SOF received", csid_hw->hw_intf->hw_idx); else - log_en = 1; + event_type |= CAM_ISP_HW_ERROR_NONE; if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; @@ -5221,24 +5246,25 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID:%d IPP CCIF violation", + "CSID:%d IPP_PATH_ERROR_CCIF_VIOLATION: Bad frame timings", csid_hw->hw_intf->hw_idx); if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID:%d IPP Overflow due to back pressure", + "CSID:%d IPP_PATH_OVERFLOW_RECOVERY: Back pressure/output fifo ovrfl", csid_hw->hw_intf->hw_idx); if (irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & CSID_PATH_ERROR_FIFO_OVERFLOW) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d IPP fifo over flow", - csid_hw->hw_intf->hw_idx); /* Stop IPP path immediately */ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_ctrl_addr); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d IPP_PATH_ERROR_O/P_FIFO_OVERFLOW: Slow IFE read", + csid_hw->hw_intf->hw_idx); + event_type |= CAM_ISP_HW_ERROR_CSID_OVERFLOW; } if ((irq_status[CAM_IFE_CSID_IRQ_REG_IPP] & @@ -5289,7 +5315,7 @@ handle_fatal_error: "CSID:%d IPP SOF received", csid_hw->hw_intf->hw_idx); else - log_en = 1; + event_type |= CAM_ISP_HW_ERROR_NONE; if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; @@ -5304,24 +5330,25 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID:%d PPP CCIF violation", + "CSID:%d PPP_PATH_ERROR_CCIF_VIOLATION: Bad frame timings", csid_hw->hw_intf->hw_idx); if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID:%d IPP Overflow due to back pressure", + "CSID:%d PPP_PATH_OVERFLOW_RECOVERY: Back pressure/output fifo ovrfl", csid_hw->hw_intf->hw_idx); if (irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & CSID_PATH_ERROR_FIFO_OVERFLOW) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d PPP fifo over flow", - csid_hw->hw_intf->hw_idx); /* Stop PPP path immediately */ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, soc_info->reg_map[0].mem_base + csid_reg->ppp_reg->csid_pxl_ctrl_addr); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d PPP_PATH_ERROR_O/P_FIFO_OVERFLOW: Slow IFE read", + csid_hw->hw_intf->hw_idx); + event_type |= CAM_ISP_HW_ERROR_CSID_OVERFLOW; } if ((irq_status[CAM_IFE_CSID_IRQ_REG_PPP] & @@ -5369,7 +5396,7 @@ handle_fatal_error: "CSID:%d RDI:%d SOF received", csid_hw->hw_intf->hw_idx, i); else - log_en = 1; + event_type |= CAM_ISP_HW_ERROR_NONE; if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; @@ -5383,22 +5410,24 @@ handle_fatal_error: if ((irq_status[i] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID:%d RDI :%d CCIF violation", + "CSID:%d RDI :%d PATH_ERROR_CCIF_VIOLATION: Bad frame timings", csid_hw->hw_intf->hw_idx, i); if ((irq_status[i] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_INFO_RATE_LIMIT(CAM_ISP, - "CSID:%d RDI :%d Overflow due to back pressure", + "CSID:%d RDI :%d PATH_OVERFLOW_RECOVERY: Back pressure/output fifo ovrfl", csid_hw->hw_intf->hw_idx, i); if (irq_status[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d RDI fifo over flow", - csid_hw->hw_intf->hw_idx); /* Stop RDI path immediately */ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d RDI_PATH_ERROR_O/P_FIFO_OVERFLOW: Slow IFE read", + csid_hw->hw_intf->hw_idx); + + event_type |= CAM_ISP_HW_ERROR_CSID_OVERFLOW; } if ((irq_status[i] & CSID_PATH_ERROR_PIX_COUNT) || @@ -5443,7 +5472,7 @@ handle_fatal_error: "CSID:%d UDI:%d SOF received", csid_hw->hw_intf->hw_idx, i); else - log_en = 1; + event_type |= CAM_ISP_HW_ERROR_NONE; if (csid_hw->sof_irq_triggered) csid_hw->irq_debug_cnt++; @@ -5459,30 +5488,30 @@ handle_fatal_error: if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & CSID_PATH_ERROR_CCIF_VIOLATION)) CAM_WARN_RATE_LIMIT(CAM_ISP, - "CSID:%d UDI :%d CCIF violation", + "CSID:%d UDI :%d PATH_ERROR_CCIF_VIOLATION: Bad frame timings", csid_hw->hw_intf->hw_idx, i); if ((irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & CSID_PATH_OVERFLOW_RECOVERY)) CAM_WARN_RATE_LIMIT(CAM_ISP, - "CSID:%d UDI :%d Overflow due to back pressure", + "CSID:%d UDI :%d PATH_OVERFLOW_RECOVERY: Back pressure/output fifo ovrfl", csid_hw->hw_intf->hw_idx, i); if (irq_status[CAM_IFE_CSID_IRQ_REG_UDI_0 + i] & CSID_PATH_ERROR_FIFO_OVERFLOW) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "CSID:%d UDI fifo over flow", - csid_hw->hw_intf->hw_idx); /* Stop UDI path immediately */ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY, soc_info->reg_map[0].mem_base + csid_reg->udi_reg[i]->csid_udi_ctrl_addr); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "CSID:%d UDI_PATH_ERROR_O/P_FIFO_OVERFLOW: Slow ife read", + csid_hw->hw_intf->hw_idx); + event_type |= CAM_ISP_HW_ERROR_CSID_OVERFLOW; } } - if (log_en) - cam_csid_handle_hw_err_irq(csid_hw, - CAM_ISP_HW_ERROR_NONE, irq_status); + if (event_type) + cam_csid_handle_hw_err_irq(csid_hw, event_type, irq_status); if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { cam_ife_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 55d23566060a..b2096b454395 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_HW_H_ @@ -599,7 +599,7 @@ struct cam_csid_evt_payload { * @csid_udin_reset_complete: udi n completion * @csid_debug: csid debug information to enable the SOT, EOT, * SOF, EOF, measure etc in the csid hw - * @clk_rate Clock rate + * @clk_rate Current clock rate * @sof_irq_triggered: Flag is set on receiving event to enable sof irq * incase of SOF freeze. * @is_resetting: informs whether reset is started or not. diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 64b6cd3ed253..ad5d25abe7fc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_H_ @@ -137,6 +137,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_QUERY_BUS_CAP, CAM_ISP_HW_CMD_GET_CLOCK_RATE, CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, + CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c index 21316b09f29f..42a84af64e24 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include @@ -75,7 +75,7 @@ static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw *ppi_hw) for (i = 0; i < soc_info->num_clk; i++) { rc = cam_soc_util_clk_enable(soc_info->clk[i], - soc_info->clk_name[i], 0); + soc_info->clk_name[i], 0, NULL); if (rc) goto clk_disable; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c index a28144a2a51d..39760807288c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -199,7 +199,7 @@ int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) { rc = cam_soc_util_clk_enable(soc_private->dsp_clk, - CAM_TFE_DSP_CLK_NAME, soc_private->dsp_clk_rate); + CAM_TFE_DSP_CLK_NAME, soc_private->dsp_clk_rate, NULL); if (rc) CAM_ERR(CAM_ISP, "Error enable dsp clk failed rc=%d", rc); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 6b0b2113bfe1..17580dca5079 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -601,6 +601,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_ADD_WAIT: case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: case CAM_ISP_HW_CMD_CAMIF_DATA: + case CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE: case CAM_ISP_HW_CMD_BLANKING_UPDATE: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c index d684f27f3989..0138ace0b39f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -307,7 +307,7 @@ int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info, } rc = cam_soc_util_clk_enable(soc_private->dsp_clk, - CAM_VFE_DSP_CLK_NAME, soc_private->dsp_clk_rate); + CAM_VFE_DSP_CLK_NAME, soc_private->dsp_clk_rate, NULL); if (rc) CAM_ERR(CAM_ISP, "Error enable dsp clk failed rc=%d", rc); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 1e5f66df4c1c..44edd50295de 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -169,6 +169,29 @@ static int cam_vfe_top_clock_update( return rc; } +static int cam_vfe_top_dump_info( + struct cam_vfe_top_ver2_priv *top_priv, uint32_t cmd_type) +{ + struct cam_hw_soc_info *soc_info = top_priv->common_data.soc_info; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Null soc_info"); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE: + CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE%d src_clk_rate:%luHz", + soc_info->index, soc_info->applied_src_clk_rate); + break; + default: + CAM_ERR(CAM_ISP, "cmd_type: %u not supported", cmd_type); + break; + } + + return 0; +} + static int cam_vfe_top_blanking_update(uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -794,6 +817,9 @@ 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_DUMP_HW_SRC_CLK_RATE: + rc = cam_vfe_top_dump_info(top_priv, cmd_type); + break; case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD: rc = cam_vfe_top_fs_update(top_priv, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 3b0b1f5f072c..279fbc845df0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -190,6 +190,30 @@ static int cam_vfe_top_ver3_clock_update( return rc; } +static int cam_vfe_top_ver3_dump_info( + struct cam_vfe_top_ver3_priv *top_priv, uint32_t cmd_type) +{ + struct cam_hw_soc_info *soc_info = top_priv->common_data.soc_info; + + if (!soc_info) { + CAM_ERR(CAM_ISP, "Null soc_info"); + return -EINVAL; + } + + switch (cmd_type) { + case CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE: + CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE%d src_clk_rate:%luHz", + soc_info->index, soc_info->applied_src_clk_rate); + break; + default: + CAM_ERR(CAM_ISP, "cmd_type: %u not supported", cmd_type); + break; + } + + return 0; +} + + static int cam_vfe_top_ver3_blanking_update(uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -731,6 +755,9 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_top_ver3_clock_update(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE: + rc = cam_vfe_top_ver3_dump_info(top_priv, cmd_type); + break; case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD: rc = cam_vfe_top_fs_update(top_priv, cmd_args, arg_size); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 68770d526c31..7dc0128940b7 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_csiphy_soc.h" @@ -130,8 +130,6 @@ int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) return rc; } - - enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev, int32_t index) { diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index e965049730a7..4dde033a2fbd 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -2098,7 +2098,8 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, for (j = 0; j < soc_info->num_clk; j++) { rc = cam_soc_util_clk_enable(soc_info->clk[j], soc_info->clk_name[j], - soc_info->clk_rate[0][j]); + soc_info->clk_rate[0][j], + NULL); if (rc) break; } diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 474c7c34d9b1..8b648c4bf446 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include @@ -378,19 +378,20 @@ long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, /** * cam_soc_util_set_clk_rate() * - * @brief: Sets the given rate for the clk requested for + * @brief: Sets the given rate for the clk requested for * - * @clk: Clock structure information for which rate is to be set - * @clk_name: Name of the clock for which rate is being set - * @clk_rate Clock rate to be set + * @clk: Clock structure information for which rate is to be set + * @clk_name: Name of the clock for which rate is being set + * @clk_rate: Clock rate to be set + * @applied_clk_rate: Final clock rate set to the clk * * @return: Success or failure */ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, - int64_t clk_rate) + int64_t clk_rate, unsigned long *applied_clk_rate) { int rc = 0; - long clk_rate_round; + long clk_rate_round = -1; if (!clk || !clk_name) return -EINVAL; @@ -427,6 +428,9 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name, } } + if (applied_clk_rate) + *applied_clk_rate = clk_rate_round; + return rc; } @@ -475,7 +479,8 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, } rc = cam_soc_util_set_clk_rate(clk, - soc_info->clk_name[src_clk_idx], clk_rate); + soc_info->clk_name[src_clk_idx], clk_rate, + &soc_info->applied_src_clk_rate); if (rc) { CAM_ERR(CAM_UTIL, "SET_RATE Failed: src clk: %s, rate %lld, dev_name = %s rc: %d", @@ -495,7 +500,8 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, clk = soc_info->clk[scl_clk_idx]; rc = cam_soc_util_set_clk_rate(clk, soc_info->clk_name[scl_clk_idx], - soc_info->clk_rate[apply_level][scl_clk_idx]); + soc_info->clk_rate[apply_level][scl_clk_idx], + NULL); if (rc) { CAM_WARN(CAM_UTIL, "SET_RATE Failed: scl clk: %s, rate %d dev_name = %s, rc: %d", @@ -602,14 +608,15 @@ int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info, } int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name, - int32_t clk_rate) + int32_t clk_rate, unsigned long *applied_clock_rate) { int rc = 0; if (!clk || !clk_name) return -EINVAL; - rc = cam_soc_util_set_clk_rate(clk, clk_name, clk_rate); + rc = cam_soc_util_set_clk_rate(clk, clk_name, clk_rate, + applied_clock_rate); if (rc) return rc; @@ -647,8 +654,9 @@ int cam_soc_util_clk_disable(struct clk *clk, const char *clk_name) int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level) { - int i, rc = 0; - enum cam_vote_level apply_level; + int i, rc = 0; + enum cam_vote_level apply_level; + unsigned long applied_clk_rate; if ((soc_info->num_clk == 0) || (soc_info->num_clk >= CAM_SOC_MAX_CLK)) { @@ -668,9 +676,14 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, 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]); + soc_info->clk_rate[apply_level][i], + &applied_clk_rate); if (rc) goto clk_disable; + + if (i == soc_info->src_clk_idx) + soc_info->applied_src_clk_rate = applied_clk_rate; + if (soc_info->cam_cx_ipeak_enable) { CAM_DBG(CAM_UTIL, "dev name = %s clk name = %s idx = %d\n" @@ -928,6 +941,7 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, { int i, rc = 0; enum cam_vote_level apply_level; + unsigned long applied_clk_rate; if ((soc_info->num_clk == 0) || (soc_info->num_clk >= CAM_SOC_MAX_CLK)) { @@ -957,7 +971,8 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, rc = cam_soc_util_set_clk_rate(soc_info->clk[i], soc_info->clk_name[i], - soc_info->clk_rate[apply_level][i]); + soc_info->clk_rate[apply_level][i], + &applied_clk_rate); if (rc < 0) { CAM_DBG(CAM_UTIL, "dev name = %s clk_name = %s idx = %d\n" @@ -968,6 +983,9 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info, cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0); break; } + + if (i == soc_info->src_clk_idx) + soc_info->applied_src_clk_rate = applied_clk_rate; } return rc; diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index aea1a396e4fd..8db6f1869cf8 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SOC_UTIL_H_ @@ -160,6 +160,7 @@ struct cam_soc_gpio_data { * @clk_level_valid: Indicates whether corresponding level is valid * @scl_clk_count: Number of scalable clocks present * @scl_clk_idx: Index of scalable clocks + * @applied_src_clk_rate Current clock rate of the core source clk * @gpio_data: Pointer to gpio info * @pinctrl_info: Pointer to pinctrl info * @dentry: Debugfs entry @@ -206,6 +207,7 @@ struct cam_hw_soc_info { int32_t clk_rate[CAM_MAX_VOTE][CAM_SOC_MAX_CLK]; int32_t prev_clk_level; int32_t src_clk_idx; + unsigned long applied_src_clk_rate; bool clk_level_valid[CAM_MAX_VOTE]; int32_t scl_clk_count; int32_t scl_clk_idx[CAM_SOC_MAX_CLK]; @@ -468,11 +470,12 @@ int cam_soc_util_clk_put(struct clk **clk); * @clk: Clock that needs to be turned ON * @clk_name: Clocks name associated with clk * @clk_rate: Clocks rate associated with clk + * @applied_clock_rate Final Clock rate applied to the clk * * @return: Success or failure */ int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name, - int32_t clk_rate); + int32_t clk_rate, unsigned long *applied_clock_rate); /** * cam_soc_util_set_clk_rate_level() From 2e1910ed075c6ab39940e233835485c095d50e87 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 21 Dec 2020 23:41:32 +0530 Subject: [PATCH 669/790] msm: camera: ope: Handle OPE smmu fault with pid info Kernel apis provide information fault caused pid and mid data. Handle the OPE smmu fault using pid and mid data. Based on the mid data, dump only corresponding port info which caused the fault. Pid and mid values are target dependent, these values will be updated on the ope node dt entries. CRs-Fixed: 2857868 Change-Id: I909f1787e71e67e5ed1d3464dfeb506418d151e4 Signed-off-by: Vikram Sharma --- drivers/cam_cdm/cam_cdm.h | 9 + drivers/cam_cdm/cam_cdm_hw_core.c | 23 +- drivers/cam_cdm/cam_cdm_hw_reg_2_1.h | 8 + drivers/cam_core/cam_context_utils.c | 4 +- drivers/cam_core/cam_context_utils.h | 2 +- drivers/cam_core/cam_hw_mgr_intf.h | 4 +- drivers/cam_icp/cam_icp_context.c | 2 +- drivers/cam_isp/cam_isp_context.c | 6 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 2 +- drivers/cam_jpeg/cam_jpeg_context.c | 2 +- drivers/cam_ope/cam_ope_context.c | 2 +- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 294 ++++++++++++------ drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h | 78 +++-- .../cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h | 4 + .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c | 1 - .../ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h | 1 - drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 41 ++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h | 5 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c | 40 ++- .../cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h | 43 ++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 13 +- .../cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h | 81 ++++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c | 26 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h | 14 +- 24 files changed, 524 insertions(+), 181 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 584375e852cc..dc2c164e0b2c 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -109,6 +109,14 @@ CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK | \ CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) + +struct cam_cdm_pid_mid_data { + int cdm_pid; + int cdm_mid; + int ope_cdm_pid; + int ope_cdm_mid; +}; + /* Structure to store hw version info */ struct cam_version_reg { uint32_t hw_version; @@ -352,6 +360,7 @@ struct cam_cdm_common_regs { const struct cam_cdm_icl_regs *icl_reg; uint32_t spare; uint32_t priority_group_bit_offset; + struct cam_cdm_pid_mid_data *cdm_pid_mid_info; }; /** diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index eb9cab56c634..49bcb027f130 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1353,11 +1353,31 @@ static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; + struct cam_cdm_pid_mid_data *pid_mid_info = NULL; int i; if (pf_info->token) { cdm_hw = (struct cam_hw_info *)pf_info->token; core = (struct cam_cdm *)cdm_hw->core_info; + pid_mid_info = core->offsets->cmn_reg->cdm_pid_mid_info; + CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n", + (void *)pf_info->iova); + + if (pid_mid_info) { + /* + * If its CDM or OPE CDM then only handle the pf for CDM + * else return. + */ + if (((pf_info->pid == pid_mid_info->cdm_pid) && + (pf_info->mid == pid_mid_info->cdm_mid)) || + ((pf_info->pid == pid_mid_info->ope_cdm_pid) && + (pf_info->mid == pid_mid_info->ope_cdm_mid))) + goto handle_cdm_pf; + else + return; + } + +handle_cdm_pf: set_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); mutex_lock(&cdm_hw->hw_mutex); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) @@ -1371,15 +1391,12 @@ static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); mutex_unlock(&cdm_hw->hw_mutex); - CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n", - (void *)pf_info->iova); cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT, (void *)pf_info->iova); clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); } else { CAM_ERR(CAM_CDM, "Invalid token"); } - } irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h b/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h index b9c8e1df7bb8..2797c64dfcf7 100644 --- a/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h +++ b/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h @@ -5,6 +5,13 @@ #include "cam_cdm.h" +struct cam_cdm_pid_mid_data cdm_hw_2_1_pid_mid_data = { + .cdm_pid = 2, + .cdm_mid = 0, + .ope_cdm_pid = 0, + .ope_cdm_mid = 2, +}; + struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_1_bl_pending_req0 = { .rb_offset = 0x6c, .rb_mask = 0x1ff, @@ -226,6 +233,7 @@ static struct cam_cdm_common_regs cdm_hw_2_1_cmn_reg_offset = { .icl_reg = &cdm_2_1_icl, .spare = 0x3fc, .priority_group_bit_offset = 20, + .cdm_pid_mid_info = &cdm_hw_2_1_pid_mid_data, }; static struct cam_cdm_common_reg_data cdm_hw_2_1_cmn_reg_data = { diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 10613a326590..0abd3ac3ebff 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -998,7 +998,7 @@ end: } int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, - struct cam_packet *packet, bool *mem_found, bool *ctx_found, + struct cam_hw_mgr_dump_pf_data *pf_data, bool *mem_found, bool *ctx_found, uint32_t *resource_type, struct cam_smmu_pf_info *pf_info) { int rc = 0; @@ -1020,7 +1020,7 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, if (ctx->hw_mgr_intf->hw_cmd) { cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO; - cmd_args.u.pf_args.pf_data.packet = packet; + cmd_args.u.pf_args.pf_data = *pf_data; cmd_args.u.pf_args.iova = pf_info->iova; cmd_args.u.pf_args.buf_info = pf_info->buf_info; cmd_args.u.pf_args.mem_found = mem_found; diff --git a/drivers/cam_core/cam_context_utils.h b/drivers/cam_core/cam_context_utils.h index 559c4e254b51..635bb6f171f9 100644 --- a/drivers/cam_core/cam_context_utils.h +++ b/drivers/cam_core/cam_context_utils.h @@ -28,7 +28,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx); int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, - struct cam_packet *packet, bool *mem_found, bool *ctx_found, + struct cam_hw_mgr_dump_pf_data *pf_data, bool *mem_found, bool *ctx_found, uint32_t *resource_type, struct cam_smmu_pf_info *pf_info); int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx); diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index c7537b5f361b..359f54850ce8 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -182,10 +182,12 @@ struct cam_hw_stop_args { /** * struct cam_hw_mgr_dump_pf_data - page fault debug data * - * packet: pointer to packet + * @packet: pointer to packet + * @req: pointer to req (HW specific) */ struct cam_hw_mgr_dump_pf_data { void *packet; + void *req; }; /** diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 064236f007fa..aa25e137b6c6 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -52,7 +52,7 @@ static int cam_icp_context_dump_active_request(void *data, pf_dbg_entry = &(req->pf_data); CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id); - rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry, &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ICP, "Failed to dump pf info"); diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index e7e55e94b619..dd91ae6971ce 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5835,7 +5835,7 @@ static int cam_isp_context_dump_requests(void *data, CAM_INFO(CAM_ISP, "Active List: req_id : %lld ", req->request_id); - rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry, &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); @@ -5854,7 +5854,7 @@ static int cam_isp_context_dump_requests(void *data, pf_dbg_entry = &(req->pf_data); CAM_INFO(CAM_ISP, "Wait List: req_id : %lld ", req->request_id); - rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry, &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); @@ -5884,7 +5884,7 @@ static int cam_isp_context_dump_requests(void *data, CAM_INFO(CAM_ISP, "Pending List: req_id : %lld ", req->request_id); - rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry, &mem_found, &ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_ISP, "Failed to dump pf info"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 68622900b9a8..cbcc73168267 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -3627,7 +3627,7 @@ static int cam_vfe_bus_get_res_for_mid( { struct cam_vfe_bus_ver2_vfe_out_data *out_data = NULL; struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args; - struct cam_isp_hw_get_res_for_mid *get_res = NULL; + struct cam_isp_hw_get_res_for_mid *get_res = NULL; int i, j; get_res = (struct cam_isp_hw_get_res_for_mid *)cmd_update->data; diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index 511da77d34b3..f8d92c26f02f 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -44,7 +44,7 @@ static int cam_jpeg_context_dump_active_request(void *data, closest_port = -1; CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id); - rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry, &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_JPEG, "Failed to dump pf info"); diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index d82b4ba84afd..cbd4cf50c236 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -54,7 +54,7 @@ static int cam_ope_context_dump_active_request(void *data, pf_dbg_entry = &(req->pf_data); CAM_INFO(CAM_OPE, "req_id : %lld", req->request_id); - rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry, &b_mem_found, &b_ctx_found, &resource_type, pf_info); if (rc) CAM_ERR(CAM_OPE, "Failed to dump pf info"); diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index f78d257d26c8..917dc596dcb8 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -45,6 +45,9 @@ static struct cam_ope_hw_mgr *ope_hw_mgr; static int cam_ope_req_timer_reset(struct cam_ope_ctx *ctx_data); +static void cam_ope_mgr_dump_pf_data(struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_cmd_args *hw_cmd_args); + static int cam_ope_mgr_get_rsc_idx(struct cam_ope_ctx *ctx_data, struct ope_io_buf_info *in_io_buf) { @@ -1767,7 +1770,6 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, struct cam_hw_prepare_update_args *prep_arg, struct cam_ope_ctx *ctx_data, uint32_t req_idx) { - int i, j = 0, k = 0, l, rc = 0; struct ope_io_buf *io_buf; int32_t sync_in_obj[CAM_MAX_IN_RES]; @@ -2724,7 +2726,7 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) bw_update = kzalloc(sizeof(struct cam_ope_dev_bw_update), GFP_KERNEL); if (!bw_update) { - CAM_ERR(CAM_ISP, "Out of memory"); + CAM_ERR(CAM_OPE, "Out of memory"); goto ope_clk_update_failed; } bw_update->ahb_vote_valid = false; @@ -3281,6 +3283,8 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv, (uintptr_t)ctx_data->req_list[request_idx]->cdm_cmd; prepare_args->priv = ctx_data->req_list[request_idx]; prepare_args->pf_data->packet = packet; + prepare_args->pf_data->req = ope_req; + CAM_INFO(CAM_REQ, "OPE req %x num_batch %d", ope_req, ope_req->num_batch); ope_req->hang_data.packet = packet; ktime_get_boottime_ts64(&ts); ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) + @@ -3433,84 +3437,6 @@ config_err: return rc; } -static void cam_ope_mgr_print_io_bufs(struct cam_packet *packet, - int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, - bool *mem_found) -{ - dma_addr_t iova_addr; - size_t src_buf_size; - int i; - int j; - int rc = 0; - int32_t mmu_hdl; - - struct cam_buf_io_cfg *io_cfg = NULL; - - if (mem_found) - *mem_found = false; - - io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + - packet->io_configs_offset / 4); - - for (i = 0; i < packet->num_io_configs; i++) { - for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { - if (!io_cfg[i].mem_handle[j]) - break; - - if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == - GET_FD_FROM_HANDLE(pf_buf_info)) { - CAM_INFO(CAM_OPE, - "Found PF at port: %d mem %x fd: %x", - io_cfg[i].resource_type, - io_cfg[i].mem_handle[j], - pf_buf_info); - if (mem_found) - *mem_found = true; - } - - CAM_INFO(CAM_OPE, "port: %d f: %u format: %d dir %d", - io_cfg[i].resource_type, - io_cfg[i].fence, - io_cfg[i].format, - io_cfg[i].direction); - - mmu_hdl = cam_mem_is_secure_buf( - io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : - iommu_hdl; - rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], - mmu_hdl, &iova_addr, &src_buf_size); - if (rc < 0) { - CAM_ERR(CAM_UTIL, - "get src buf address fail rc %d mem %x", - rc, io_cfg[i].mem_handle[j]); - continue; - } - if ((iova_addr & 0xFFFFFFFF) != iova_addr) { - CAM_ERR(CAM_OPE, "Invalid mapped address"); - rc = -EINVAL; - continue; - } - - CAM_INFO(CAM_OPE, - "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], - io_cfg[i].mem_handle[j]); - - iova_addr += io_cfg[i].offsets[j]; - - } - } - cam_packet_dump_patch_info(packet, ope_hw_mgr->iommu_hdl, - ope_hw_mgr->iommu_sec_hdl); -} - static int cam_ope_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -3524,16 +3450,11 @@ static int cam_ope_mgr_cmd(void *hw_mgr_priv, void *cmd_args) switch (hw_cmd_args->cmd_type) { case CAM_HW_MGR_CMD_DUMP_PF_INFO: - cam_ope_mgr_print_io_bufs( - hw_cmd_args->u.pf_args.pf_data.packet, - hw_mgr->iommu_hdl, - hw_mgr->iommu_sec_hdl, - hw_cmd_args->u.pf_args.buf_info, - hw_cmd_args->u.pf_args.mem_found); - + cam_ope_mgr_dump_pf_data(hw_mgr, hw_cmd_args); break; default: - CAM_ERR(CAM_OPE, "Invalid cmd"); + CAM_ERR(CAM_OPE, "Invalid cmd: %d", + hw_cmd_args->cmd_type); } return rc; @@ -3854,13 +3775,14 @@ static int cam_ope_mgr_init_devs(struct device_node *of_node) } ope_hw_mgr->num_ope = count; + for (i = 0; i < count; i++) { ope_hw_mgr->ope_dev_intf[i] = ope_hw_mgr->devices[OPE_DEV_OPE][i]; - ope_dev = ope_hw_mgr->ope_dev_intf[i]->hw_priv; - soc_info = &ope_dev->soc_info; - ope_hw_mgr->cdm_reg_map[i][0] = - soc_info->reg_map[0].mem_base; + ope_dev = ope_hw_mgr->ope_dev_intf[i]->hw_priv; + soc_info = &ope_dev->soc_info; + ope_hw_mgr->cdm_reg_map[i][0] = + soc_info->reg_map[0].mem_base; } ope_hw_mgr->hfi_en = of_property_read_bool(of_node, "hfi_en"); @@ -4027,20 +3949,20 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, hw_mgr_intf->hw_mgr_priv = ope_hw_mgr; hw_mgr_intf->hw_get_caps = cam_ope_mgr_get_hw_caps; - hw_mgr_intf->hw_acquire = cam_ope_mgr_acquire_hw; - hw_mgr_intf->hw_release = cam_ope_mgr_release_hw; - hw_mgr_intf->hw_start = NULL; - hw_mgr_intf->hw_stop = NULL; + hw_mgr_intf->hw_acquire = cam_ope_mgr_acquire_hw; + hw_mgr_intf->hw_release = cam_ope_mgr_release_hw; + hw_mgr_intf->hw_start = NULL; + hw_mgr_intf->hw_stop = NULL; hw_mgr_intf->hw_prepare_update = cam_ope_mgr_prepare_hw_update; hw_mgr_intf->hw_config_stream_settings = NULL; hw_mgr_intf->hw_config = cam_ope_mgr_config_hw; hw_mgr_intf->hw_read = NULL; hw_mgr_intf->hw_write = NULL; - hw_mgr_intf->hw_cmd = cam_ope_mgr_cmd; - hw_mgr_intf->hw_open = cam_ope_mgr_hw_open_u; - hw_mgr_intf->hw_close = cam_ope_mgr_hw_close_u; - hw_mgr_intf->hw_flush = cam_ope_mgr_hw_flush; - hw_mgr_intf->hw_dump = cam_ope_mgr_hw_dump; + hw_mgr_intf->hw_cmd = cam_ope_mgr_cmd; + hw_mgr_intf->hw_open = cam_ope_mgr_hw_open_u; + hw_mgr_intf->hw_close = cam_ope_mgr_hw_close_u; + hw_mgr_intf->hw_flush = cam_ope_mgr_hw_flush; + hw_mgr_intf->hw_dump = cam_ope_mgr_hw_dump; ope_hw_mgr->secure_mode = false; mutex_init(&ope_hw_mgr->hw_mgr_mutex); @@ -4079,6 +4001,12 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, ope_hw_mgr->ctx_bits = ope_hw_mgr->ctx_bitmap_size * BITS_PER_BYTE; + for (i = 0; i < OPE_DEV_MAX; i++) { + rc = cam_ope_hw_init(&ope_hw_mgr->ope_dev_data[i], i); + if (rc) + goto ctx_bitmap_alloc_failed; + } + rc = cam_smmu_get_handle("ope", &ope_hw_mgr->iommu_hdl); if (rc) { CAM_ERR(CAM_OPE, "get mmu handle failed: %d", rc); @@ -4148,3 +4076,167 @@ ope_ctx_bitmap_failed: return rc; } +static void cam_ope_mgr_dump_pf_data( + struct cam_ope_hw_mgr *hw_mgr, + struct cam_hw_cmd_args *hw_cmd_args) +{ + struct cam_ope_ctx *ctx_data; + struct cam_packet *packet; + struct cam_buf_io_cfg *io_cfg = NULL; + struct cam_ope_request *ope_request; + struct ope_io_buf *io_buf = NULL; + struct cam_ope_match_pid_args ope_pid_mid_args; + + dma_addr_t iova_addr; + int device_idx; + bool *ctx_found; + bool io_buf_found = false; + size_t src_buf_size; + int i, j; + int32_t mmu_hdl; + bool hw_pid_support = true; + bool hw_id_found = false; + uint32_t *resource_type; + int stripe_num; + int rc = 0; + + ctx_data = (struct cam_ope_ctx *)hw_cmd_args->ctxt_to_hw_map; + packet = hw_cmd_args->u.pf_args.pf_data.packet; + ope_request = hw_cmd_args->u.pf_args.pf_data.req; + + if (ctx_data->pf_mid_found) + goto stripedump; + + ope_pid_mid_args.fault_mid = hw_cmd_args->u.pf_args.mid; + ope_pid_mid_args.fault_pid = hw_cmd_args->u.pf_args.pid; + ctx_found = hw_cmd_args->u.pf_args.ctx_found; + resource_type = hw_cmd_args->u.pf_args.resource_type; + + if (*ctx_found && *resource_type) { + hw_pid_support = false; + goto stripedump; + } else { + *ctx_found = false; + } + + for (i = 0; i < ope_hw_mgr->num_ope; i++) { + if (!ope_hw_mgr->ope_dev_data[i]->hw_intf) + continue; + for (j = 0; j < ope_hw_mgr->ope_dev_data[i]->num_hw_pid; j++) { + if (ope_hw_mgr->ope_dev_data[i]->hw_pid[j] == + hw_cmd_args->u.pf_args.pid) { + hw_id_found = true; + device_idx = i; + *ctx_found = true; + break; + } + } + if (hw_id_found) + break; + } + + if (i == ope_hw_mgr->num_ope) { + CAM_INFO(CAM_OPE, + "PID:%d is not matching with any OPE HW PIDs ctx id:%d", + hw_cmd_args->u.pf_args.pid, ctx_data->ctx_id); + return; + } + + ope_pid_mid_args.device_idx = device_idx; + + rc = hw_mgr->devices[OPE_DEV_OPE][device_idx]->hw_ops.process_cmd( + hw_mgr->devices[OPE_DEV_OPE][device_idx]->hw_priv, + OPE_HW_MATCH_PID_MID, + &ope_pid_mid_args, sizeof(ope_pid_mid_args)); + if (rc) { + CAM_ERR(CAM_OPE, + "CAM_OPE_CMD_MATCH_PID_MID failed %d", rc); + return; + } + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + *resource_type = ope_pid_mid_args.match_res; + CAM_INFO(CAM_OPE, "Fault port %d", *resource_type); + +stripedump: + if (!ope_request) + goto iodump; + + CAM_INFO(CAM_OPE, "req_id %d Num of batches %d", + ope_request->request_id, ope_request->num_batch); + + for (i = 0; i < ope_request->num_batch; i++) { + for (j = 0; j < ope_request->num_io_bufs[i]; j++) { + io_buf = ope_request->io_buf[i][j]; + if (io_buf) { + if (io_buf->resource_type == *resource_type) { + io_buf_found = true; + break; + } + } + } + if (io_buf_found) + break; + } +iodump: + for (i = 0; i < packet->num_io_configs; i++) { + if (hw_pid_support) { + if (io_cfg[i].resource_type != + *resource_type) + continue; + } + + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + CAM_INFO(CAM_OPE, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? + hw_mgr->iommu_sec_hdl : + hw_mgr->iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get src buf address fail"); + continue; + } + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { + CAM_ERR(CAM_OPE, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + CAM_INFO(CAM_OPE, + "pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x", + j, 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], + io_cfg[i].mem_handle[j]); + + if (io_buf_found) { + for (stripe_num = 0; stripe_num < io_buf->num_stripes[j]; + stripe_num++) { + CAM_INFO(CAM_OPE, + "pln_num %d stripe_num %d width %d height %d stride %d io vaddr 0x%x", + j, stripe_num, io_buf->s_io[j][stripe_num].width, + io_buf->s_io[j][stripe_num].height, + io_buf->s_io[j][stripe_num].stride, + io_buf->s_io[j][stripe_num].iova_addr); + } + } + } + if (hw_pid_support) + return; + } +} + diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h index 3bc09be0b88c..f6206f0c8bf0 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h @@ -469,39 +469,58 @@ struct cam_ope_ctx { struct cam_req_mgr_timer *clk_watch_dog; uint32_t clk_watch_dog_reset_counter; uint64_t last_flush_req; + bool pf_mid_found; +}; + +/** + * struct cam_ope_hw_intf_data - OPE hw intf data + * + * @Brief: ope hw intf pointer and pid list data + * + * @devices: ope hw intf pointer + * @num_devices: Number of OPE devices + * @num_hw_pid: Number of pids for this hw + * @hw_pid: ope hw pid values + * + */ +struct cam_ope_hw_intf_data { + struct cam_hw_intf *hw_intf; + uint32_t num_hw_pid; + uint32_t hw_pid[OPE_DEV_MAX]; }; /** * struct cam_ope_hw_mgr * - * @open_cnt: OPE device open count - * @ope_ctx_cnt: Open context count - * @hw_mgr_mutex: Mutex for HW manager - * @hw_mgr_lock: Spinlock for HW manager - * @hfi_en: Flag for HFI - * @iommu_hdl: OPE Handle - * @iommu_sec_hdl: OPE Handle for secure - * @iommu_cdm_hdl: CDM Handle - * @iommu_sec_cdm_hdl: CDM Handle for secure - * @num_ope: Number of OPE - * @secure_mode: Mode of OPE operation - * @ctx_bitmap: Context bit map - * @ctx_bitmap_size: Context bit map size - * @ctx_bits: Context bit map bits - * @ctx: OPE context - * @devices: OPE devices - * @ope_caps: OPE capabilities - * @cmd_work: Command work - * @msg_work: Message work - * @timer_work: Timer work - * @cmd_work_data: Command work data - * @msg_work_data: Message work data - * @timer_work_data: Timer work data - * @ope_dev_intf: OPE device interface - * @cdm_reg_map: OPE CDM register map - * @clk_info: OPE clock Info for HW manager - * @dentry: Pointer to OPE debugfs directory - * @frame_dump_enable: OPE frame setting dump enablement + * @open_cnt: OPE device open count + * @ope_ctx_cnt: Open context count + * @hw_mgr_mutex: Mutex for HW manager + * @hw_mgr_lock: Spinlock for HW manager + * @hfi_en: Flag for HFI + * @iommu_hdl: OPE Handle + * @iommu_sec_hdl: OPE Handle for secure + * @iommu_cdm_hdl: CDM Handle + * @iommu_sec_cdm_hdl: CDM Handle for secure + * @num_ope: Number of OPE + * @secure_mode: Mode of OPE operation + * @ctx_bitmap: Context bit map + * @ctx_bitmap_size: Context bit map size + * @ctx_bits: Context bit map bits + * @ctx: OPE context + * @devices: OPE devices + * @ope_dev_data: OPE device specific data + * @ope_caps: OPE capabilities + * @cmd_work: Command work + * @msg_work: Message work + * @timer_work: Timer work + * @cmd_work_data: Command work data + * @msg_work_data: Message work data + * @timer_work_data: Timer work data + * @ope_dev_intf: OPE device interface + * @cdm_reg_map: OPE CDM register map + * @clk_info: OPE clock Info for HW manager + * @dentry: Pointer to OPE debugfs directory + * @frame_dump_enable: OPE frame setting dump enablement * @dump_req_data_enable: OPE hang dump enablement */ struct cam_ope_hw_mgr { @@ -520,7 +539,8 @@ struct cam_ope_hw_mgr { size_t ctx_bitmap_size; size_t ctx_bits; struct cam_ope_ctx ctx[OPE_CTX_MAX]; - struct cam_hw_intf **devices[OPE_DEV_MAX]; + struct cam_hw_intf **devices[OPE_DEV_MAX]; + struct cam_ope_hw_intf_data *ope_dev_data[OPE_DEV_MAX]; struct ope_query_cap_cmd ope_caps; uint64_t last_callback_time; diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h index 89454d0e169d..b5abaf48e08e 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h @@ -9,8 +9,12 @@ #include #include #include +#include "cam_ope_hw_mgr.h" int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl); +int cam_ope_hw_init(struct cam_ope_hw_intf_data **ope_hw_intf_data, + uint32_t hw_idx); + #endif /* CAM_OPE_HW_MGR_INTF_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c index 033df2b6666d..2d47ef767202 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c @@ -871,4 +871,3 @@ int cam_ope_bus_rd_process(struct ope_hw *ope_hw_info, return rc; } - diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h index b461374c2a63..d6ebb3313cf0 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h @@ -17,7 +17,6 @@ #include "cam_ope_context.h" #include "cam_ope_hw_mgr.h" - /** * struct ope_bus_rd_cdm_info * diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index 922b5eab523e..fc9903d565e3 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -1614,12 +1614,15 @@ int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { int rc = 0; - struct cam_hw_info *ope_dev = device_priv; - struct cam_hw_soc_info *soc_info = NULL; - struct cam_ope_device_core_info *core_info = NULL; - struct ope_hw *ope_hw; - bool hfi_en; + struct cam_hw_info *ope_dev = device_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_ope_device_core_info *core_info = NULL; + struct cam_ope_match_pid_args *match_pid_mid = NULL; + struct ope_hw *ope_hw; + bool hfi_en; unsigned long flags; + int i; + uint32_t device_idx; if (!device_priv) { CAM_ERR(CAM_OPE, "Invalid args %x for cmd %u", @@ -1718,6 +1721,33 @@ int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type, case OPE_HW_DUMP_DEBUG: rc = cam_ope_process_dump_debug_reg(ope_hw, hfi_en); break; + case OPE_HW_MATCH_PID_MID: + if (!cmd_args) { + CAM_ERR(CAM_OPE, "cmd args NULL"); + return -EINVAL; + } + + match_pid_mid = (struct cam_ope_match_pid_args *)cmd_args; + match_pid_mid->mid_match_found = false; + + device_idx = match_pid_mid->device_idx; + + for (i = 0; i < MAX_RW_CLIENTS; i++) { + if ((match_pid_mid->fault_mid == + ope_hw->common->ope_mid_info[device_idx][i].mid) && + (match_pid_mid->fault_pid == + ope_hw->common->ope_mid_info[device_idx][i].pid)) { + match_pid_mid->match_res = + ope_hw->common->ope_mid_info[device_idx][i].cam_ope_res_type; + match_pid_mid->mid_match_found = true; + break; + } + } + if (!match_pid_mid->mid_match_found) { + rc = -1; + CAM_INFO(CAM_OPE, "mid match not found"); + } + break; default: break; } @@ -1756,3 +1786,4 @@ irqreturn_t cam_ope_irq(int irq_num, void *data) return IRQ_HANDLED; } + diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h index c4b7dd7f8e55..363b0982ad40 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h @@ -6,6 +6,7 @@ #ifndef CAM_OPE_CORE_H #define CAM_OPE_CORE_H + #include #include #include @@ -15,6 +16,9 @@ #include "cam_cpas_api.h" #include "ope_hw.h" #include "ope_dev_intf.h" + +#define CAM_OPE_HW_MAX_NUM_PID 2 + /** * struct cam_ope_cpas_vote * @ahb_vote: AHB vote info @@ -79,7 +83,6 @@ struct cam_ope_device_core_info { struct cam_ope_set_irq_cb irq_cb; }; - int cam_ope_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_ope_deinit_hw(void *device_priv, diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index cb80739071d9..914539ccb086 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -21,8 +21,9 @@ #include "ope_dev_intf.h" #include "camera_main.h" +static struct cam_ope_hw_intf_data cam_ope_dev_list[OPE_DEV_MAX]; static struct cam_ope_device_hw_info ope_hw_info; -static struct ope_dev_soc ope_soc_info; +static struct cam_ope_soc_private ope_soc_info; EXPORT_SYMBOL(ope_soc_info); static struct hw_version_reg ope_hw_version_reg = { @@ -115,10 +116,13 @@ static int cam_ope_component_bind(struct device *dev, struct cam_hw_info *ope_dev = NULL; const struct of_device_id *match_dev = NULL; struct cam_ope_device_core_info *core_info = NULL; - int rc = 0; + struct cam_ope_dev_probe ope_probe; + struct cam_ope_cpas_vote cpas_vote; + struct cam_ope_soc_private *soc_private; + int i; uint32_t hw_idx; - struct cam_ope_dev_probe ope_probe; - struct cam_ope_cpas_vote cpas_vote; + int rc = 0; + struct platform_device *pdev = to_platform_device(dev); of_property_read_u32(pdev->dev.of_node, @@ -156,8 +160,13 @@ static int cam_ope_component_bind(struct device *dev, ope_dev_intf->hw_type, ope_dev_intf->hw_idx); + if (ope_dev_intf->hw_idx < OPE_DEV_MAX) + cam_ope_dev_list[ope_dev_intf->hw_idx].hw_intf = + ope_dev_intf; + platform_set_drvdata(pdev, ope_dev_intf); + ope_dev->core_info = kzalloc(sizeof(struct cam_ope_device_core_info), GFP_KERNEL); if (!ope_dev->core_info) { @@ -232,6 +241,14 @@ static int cam_ope_component_bind(struct device *dev, CAM_DBG(CAM_OPE, "OPE:%d component bound successfully", ope_dev_intf->hw_idx); + soc_private = ope_dev->soc_info.soc_private; + cam_ope_dev_list[ope_dev_intf->hw_idx].num_hw_pid = + soc_private->num_pid; + + for (i = 0; i < soc_private->num_pid; i++) + cam_ope_dev_list[ope_dev_intf->hw_idx].hw_pid[i] = + soc_private->pid[i]; + return rc; init_hw_failure: @@ -255,6 +272,21 @@ static void cam_ope_component_unbind(struct device *dev, CAM_DBG(CAM_OPE, "Unbinding component: %s", pdev->name); } +int cam_ope_hw_init(struct cam_ope_hw_intf_data **ope_hw_intf_data, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_ope_dev_list[hw_idx].hw_intf) { + *ope_hw_intf_data = &cam_ope_dev_list[hw_idx]; + rc = 0; + } else { + CAM_ERR(CAM_OPE, "inval param"); + *ope_hw_intf_data = NULL; + rc = -ENODEV; + } + return rc; +} const static struct component_ops cam_ope_component_ops = { .bind = cam_ope_component_bind, diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h index 1e191961b5d4..304d30dd356f 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h @@ -12,23 +12,32 @@ #include "cam_cpas_api.h" -#define OPE_HW_INIT 0x1 -#define OPE_HW_DEINIT 0x2 -#define OPE_HW_ACQUIRE 0x3 -#define OPE_HW_RELEASE 0x4 -#define OPE_HW_START 0x5 -#define OPE_HW_STOP 0x6 -#define OPE_HW_FLUSH 0x7 -#define OPE_HW_PREPARE 0x8 -#define OPE_HW_ISR 0x9 -#define OPE_HW_PROBE 0xA -#define OPE_HW_CLK_UPDATE 0xB -#define OPE_HW_BW_UPDATE 0xC -#define OPE_HW_RESET 0xD -#define OPE_HW_SET_IRQ_CB 0xE -#define OPE_HW_CLK_DISABLE 0xF -#define OPE_HW_CLK_ENABLE 0x10 -#define OPE_HW_DUMP_DEBUG 0x11 +#define OPE_HW_INIT 0x1 +#define OPE_HW_DEINIT 0x2 +#define OPE_HW_ACQUIRE 0x3 +#define OPE_HW_RELEASE 0x4 +#define OPE_HW_START 0x5 +#define OPE_HW_STOP 0x6 +#define OPE_HW_FLUSH 0x7 +#define OPE_HW_PREPARE 0x8 +#define OPE_HW_ISR 0x9 +#define OPE_HW_PROBE 0xA +#define OPE_HW_CLK_UPDATE 0xB +#define OPE_HW_BW_UPDATE 0xC +#define OPE_HW_RESET 0xD +#define OPE_HW_SET_IRQ_CB 0xE +#define OPE_HW_CLK_DISABLE 0xF +#define OPE_HW_CLK_ENABLE 0x10 +#define OPE_HW_DUMP_DEBUG 0x11 +#define OPE_HW_MATCH_PID_MID 0x12 + +struct cam_ope_match_pid_args { + uint32_t fault_pid; + uint32_t fault_mid; + uint32_t match_res; + uint32_t device_idx; + bool mid_match_found; +}; /** * struct cam_ope_dev_probe diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index a54a2ec5b80d..0c4c10ca751f 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -12,10 +12,12 @@ #define OPE_DEV_OPE 0 #define OPE_DEV_MAX 1 -#define MAX_RD_CLIENTS 2 +#define MAX_RD_CLIENTS 3 #define MAX_WR_CLIENTS 8 #define MAX_PP_CLIENTS 29 +#define MAX_RW_CLIENTS (MAX_RD_CLIENTS + MAX_WR_CLIENTS) + #define OPE_CDM_BASE 0x0 #define OPE_TOP_BASE 0x1 #define OPE_QOS_BASE 0x2 @@ -24,7 +26,6 @@ #define OPE_BUS_WR 0x5 #define OPE_BASE_MAX 0x6 - #define BUS_RD_COMBO_BAYER_MASK 0x1 #define BUS_RD_COMBO_YUV_MASK 0x2 #define BUS_RD_COMBO_MAX 0x2 @@ -53,8 +54,16 @@ #define OPE_MAX_DEBUG_REGISTER 30 +struct cam_ope_pid_mid_info { + int cam_ope_res_type; + uint32_t pid; + uint32_t mid; + bool read; +}; + struct cam_ope_common { uint32_t mode[CAM_FORMAT_MAX]; + struct cam_ope_pid_mid_info (*ope_mid_info)[MAX_RW_CLIENTS]; }; struct cam_ope_top_reg { diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index 727b43c68512..b917b2fabd1b 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -9,6 +9,7 @@ #define OPE_BUS_RD_TYPE_BAYER 0x0 #define OPE_BUS_RD_TYPE_YUV_Y 0x0 #define OPE_BUS_RD_TYPE_YUC_C 0x1 +#define OPE_BUS_RD_TYPE_CDM 0x2 #define OPE_BUS_WR_TYPE_VID_Y 0x0 #define OPE_BUS_WR_TYPE_VID_C 0x1 @@ -19,6 +20,81 @@ #define OPE_BUS_WR_TYPE_IHIST 0x6 #define OPE_BUS_WR_TYPE_LTM 0x7 +static struct cam_ope_pid_mid_info g_ope_mid_info[OPE_DEV_MAX][MAX_RW_CLIENTS] = { + { + { + .cam_ope_res_type = OPE_IN_RES_FULL, + .pid = 0, + .mid = 0, + .read = true, + }, + { + .cam_ope_res_type = OPE_IN_RES_FULL, + .pid = 0, + .mid = 1, + .read = true, + }, + { + .cam_ope_res_type = OPE_IN_RES_FULL, + .pid = 0, + .mid = 2, + .read = true, + }, + { + .cam_ope_res_type = OPE_OUT_RES_VIDEO, + .pid = 1, + .mid = 16, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_VIDEO, + .pid = 1, + .mid = 17, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_DISP, + .pid = 1, + .mid = 18, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_DISP, + .pid = 1, + .mid = 19, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_ARGB, + .pid = 1, + .mid = 20, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_STATS_RS, + .pid = 1, + .mid = 21, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_STATS_IHIST, + .pid = 1, + .mid = 22, + .read = false, + }, + { + .cam_ope_res_type = OPE_OUT_RES_STATS_LTM, + .pid = 1, + .mid = 23, + .read = false, + }, + }, +}; + +static struct cam_ope_common common_data = { + .ope_mid_info = g_ope_mid_info, +}; + enum cam_ope_bus_rd_unpacker_format { BUS_RD_VER1_PACKER_FMT_PLAIN_128_BYPASS = 0x0, BUS_RD_VER1_PACKER_FMT_PLAIN_8 = 0x1, @@ -100,8 +176,8 @@ static struct cam_ope_top_reg_val ope_top_reg_val = { .incr_mask = 0xF0000000, .incr_shift = 0x1B, .irq_mask = 0x0000000F, - .sw_reset_cmd = 0x2, - .hw_reset_cmd = 0x1, + .sw_reset_cmd = 0x2, + .hw_reset_cmd = 0x1, .irq_set_clear = 0x1, .rst_done = 0x1, .we_done = 0x2, @@ -657,6 +733,7 @@ static struct ope_hw ope_hw_100 = { .bus_wr_reg = &ope_bus_wr_reg, .bus_wr_reg_val = &ope_bus_wr_reg_val, .pp_reg = &ope_pp_reg, + .common = &common_data, }; #endif /* CAM_OPE_HW_100_H */ diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c index ca83bb31dbe4..ca1491c7cabb 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c @@ -19,7 +19,7 @@ static int cam_ope_get_dt_properties(struct cam_hw_soc_info *soc_info) int rc = 0; struct platform_device *pdev = NULL; struct device_node *of_node = NULL; - struct ope_dev_soc *ope_soc_info; + struct cam_ope_soc_private *ope_soc_info; if (!soc_info) { CAM_ERR(CAM_OPE, "soc_info is NULL"); @@ -54,8 +54,18 @@ static int cam_ope_request_platform_resource( int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t ope_irq_handler, void *irq_data) { + struct cam_ope_soc_private *soc_private; + struct platform_device *pdev = NULL; + int num_pid = 0, i = 0; int rc = 0; + soc_private = kzalloc(sizeof(struct cam_ope_soc_private), GFP_KERNEL); + if (!soc_private) { + CAM_DBG(CAM_ISP, "Error! soc_private Alloc Failed"); + return -ENOMEM; + } + soc_info->soc_private = soc_private; + rc = cam_ope_get_dt_properties(soc_info); if (rc < 0) return rc; @@ -65,6 +75,20 @@ int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info, if (rc < 0) return rc; + soc_private->num_pid = 0; + pdev = soc_info->pdev; + num_pid = of_property_count_u32_elems(pdev->dev.of_node, "cam_hw_pid"); + CAM_DBG(CAM_OPE, "ope: %d pid count %d", soc_info->index, num_pid); + + if (num_pid <= 0 || num_pid > CAM_OPE_HW_MAX_NUM_PID) + goto end; + + soc_private->num_pid = num_pid; + + for (i = 0; i < num_pid; i++) + of_property_read_u32_index(pdev->dev.of_node, "cam_hw_pid", i, + &soc_private->pid[i]); +end: return rc; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h index a6f0b13a3d2e..3af5c8c3450f 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h @@ -8,15 +8,23 @@ #include "cam_soc_util.h" +#define CAM_OPE_HW_MAX_NUM_PID 2 + /** - * struct ope_dev_soc + * struct cam_ope_soc_private * - * @hfi_en: HFI enable flag + * @hfi_en: HFI enable flag + * @num_pid: OPE number of pids + * @pid: OPE pid value list */ -struct ope_dev_soc { +struct cam_ope_soc_private { uint32_t hfi_en; + uint32_t num_pid; + uint32_t pid[CAM_OPE_HW_MAX_NUM_PID]; }; + + int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t ope_irq_handler, void *irq_data); From e1ea9edec2a9d6d5eea0bb26b29eb1ba3ad19c8d Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Fri, 15 Jan 2021 12:29:26 +0530 Subject: [PATCH 670/790] msm: camera: isp: Correct assignment of clock rates If there is no change in CSID and TFE clock rates then correctly assign current clock rates to local varaibles. CRs-Fixed: 2855742 Change-Id: Ibd71274ba7a7844c3841060eb3b3b14ba80ed4b0 Signed-off-by: Shravya Samala --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 245ef46d6b7a..d3e2b3d24cf9 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -1984,6 +1984,12 @@ int cam_tfe_cshiphy_callback( &csid_clock_rate, &updated_tfe_clk); } } + + if (!updated_csid_clk) + updated_csid_clk = csid_clock_rate; + + if (!updated_tfe_clk) + updated_tfe_clk = tfe_clock_rate; end: /* final check */ if ((*phy_clock_rate > updated_csid_clk) || From f36a214704647ccacdd48583b8347abe11ce9c73 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Tue, 12 Jan 2021 17:28:37 -0800 Subject: [PATCH 671/790] msm: camera: csiphy: Update the csiphy programming sequence Update the 3 phase bring up sequence for csiphy1.2.3 header to align with version_8 updated on 01/08/2021. CRs-Fixed: 2856350 Change-Id: I06b164fbb0a589f22f973476709008d0c7ac32ca Signed-off-by: Jigar Agrawal --- .../include/cam_csiphy_1_2_3_hwreg.h | 121 +++++------------- 1 file changed, 29 insertions(+), 92 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 1bfc6ca97b92..2c39d9d188f1 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_3_HWREG_H_ @@ -16,7 +16,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .csiphy_common_array_size = 5, .csiphy_reset_array_size = 2, .csiphy_2ph_config_array_size = 16, - .csiphy_3ph_config_array_size = 26, + .csiphy_3ph_config_array_size = 31, .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -248,6 +248,8 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -259,11 +261,14 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0980, 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -276,6 +281,8 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -287,11 +294,14 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A80, 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -304,6 +314,8 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -315,11 +327,14 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B80, 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -331,44 +346,26 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 4, + .data_rate_reg_array_size = 1, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { - {0x010C, 0x12, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0108, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x144, 0x22, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x0A, + {0x9B4, 0x08, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { - {0x030C, 0x12, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0308, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x344, 0x22, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x0A, + {0xAB4, 0x08, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { - {0x050C, 0x12, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0508, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x544, 0x22, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x0A, + {0xBB4, 0x08, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, @@ -377,56 +374,26 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 6, + .data_rate_reg_array_size = 1, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { - {0x010C, 0x08, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0108, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x144, 0xB2, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x988, 0x05, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x980, 0x60, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x02, 0x0A, + {0x9B4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { - {0x030C, 0x08, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0308, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x344, 0xB2, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xA88, 0x05, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xA80, 0x60, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x02, 0x0A, + {0xAB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { - {0x050C, 0x08, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0508, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x544, 0xB2, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xB88, 0x05, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xB80, 0x60, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x02, 0x0A, + {0xBB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, @@ -435,56 +402,26 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 6, + .data_rate_reg_array_size = 1, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { - {0x010C, 0x08, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0108, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x144, 0xB2, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x988, 0x05, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x980, 0x60, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x01, 0x0A, + {0x9B4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { - {0x030C, 0x08, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0308, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x344, 0xB2, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xA88, 0x05, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xA80, 0x60, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x01, 0x0A, + {0xAB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { - {0x050C, 0x08, 0x00, - CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {0x0508, 0x00, 0x00, - CSIPHY_SETTLE_CNT_HIGHER_BYTE}, - {0x544, 0xB2, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xB88, 0x05, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xB80, 0x60, 0x00, - CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x0A, + {0xBB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, }, From 39c0ecd734d7ae32778ada4e8827f52e73627405 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 22 Jan 2021 04:30:07 +0530 Subject: [PATCH 672/790] msm: camera: isp: Correct halt command for Yupik camera This change is to correct csid halt command and correct qos setting for Yupik camera. CRs-Fixed: 2825675 Change-Id: I002a3f5864f6c157249465bdf71d268b547eb196 Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 6 +++--- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 7 ++++++- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h | 3 ++- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 9 +++------ 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 9d2bdfc92633..3e739d3c33a3 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V165_100_H_ @@ -337,7 +337,7 @@ static struct cam_camnoc_specific * Power on default values are taking care of required * register settings. */ - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3B88, /* IFE01_NRDI_ENCCTL_LOW */ @@ -555,7 +555,7 @@ static struct cam_camnoc_specific { /*SidebandManager_main_SidebandManager_FlagOutSet0_Low*/ .port_type = CAM_CAMNOC_ICP, - .enable = true, + .enable = false, .flag_out_set0_low = { .enable = true, .access_type = CAM_REG_TYPE_WRITE, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 6efeb80bbdb5..b807a9a5ab48 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2290,6 +2290,7 @@ static int cam_ife_csid_enable_pxl_path( uint32_t val = 0; struct cam_isp_sensor_dimension *path_config; unsigned int irq_mask_val = 0; + uint32_t camera_hw_version; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2342,6 +2343,8 @@ static int cam_ife_csid_enable_pxl_path( } } + cam_cpas_get_cpas_hw_version(&camera_hw_version); + /* Set master or slave path */ if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) { /*Set halt mode as master */ @@ -2352,7 +2355,8 @@ static int cam_ife_csid_enable_pxl_path( val = CSID_HALT_MODE_MASTER << 2; } else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { /*Set halt mode as slave and set master idx */ - if (pxl_reg->halt_master_sel_en) + if (pxl_reg->halt_master_sel_en || + camera_hw_version == CAM_CPAS_TITAN_165_V100) val = CSID_HALT_MODE_SLAVE << 2; else val = path_data->master_idx << 4 | @@ -2361,6 +2365,7 @@ static int cam_ife_csid_enable_pxl_path( /* Default is internal halt mode */ val = 0; } + /* * Resume at frame boundary if Master or No Sync. * Slave will get resume command from Master. diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h index 1e28760bf2a9..bba9302a4f04 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE165_160_H_ @@ -88,6 +88,7 @@ static struct cam_vfe_camif_reg_data vfe_165_160_camif_reg_data = { .subscribe_irq_mask0 = 0x00000017, .subscribe_irq_mask1 = 0x00000000, .enable_diagnostic_hw = 0x1, + .dual_vfe_sync_mask = 0x3, }; static struct cam_vfe_fe_ver1_reg vfe165_160_fe_reg = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 0a6d62412f1d..be9a5352504a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -2639,11 +2639,6 @@ static void cam_vfe_bus_update_ubwc_meta_addr( if (rc) { CAM_ERR(CAM_ISP, "Failed to get HW version rc: %d", rc); goto end; - } else if ((camera_hw_version < CAM_CPAS_TITAN_170_V100) || - (camera_hw_version > CAM_CPAS_TITAN_175_V130)) { - CAM_ERR(CAM_ISP, "Invalid HW version: %d", - camera_hw_version); - goto end; } switch (camera_hw_version) { @@ -2670,6 +2665,8 @@ static void cam_vfe_bus_update_ubwc_meta_addr( image_buf); break; default: + CAM_ERR(CAM_ISP, "Invalid HW version: %d", + camera_hw_version); break; } end: From bf2c5a30cddd47caed96a673b24ab966ba4c141c Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Mon, 1 Feb 2021 00:30:58 +0530 Subject: [PATCH 673/790] Revert "msm: camera: isp: IFE and CSID probe based on fuse" This reverts commit afb3736650122de189e575793badca123103d813. Change-Id: I6f77e1c24a14eacff6a7a3b7e74726557343fd45 Signed-off-by: Sridhar Gujje --- drivers/cam_cpas/cam_cpas_intf.c | 7 +++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 12 ------------ .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 12 ------------ 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index 45eba95e1052..94c0101433ee 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -161,8 +161,11 @@ bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map, if (soc_private->feature_info[i].feature == flag) break; - if (i == soc_private->num_feature_info) + if (i == soc_private->num_feature_info) { + CAM_INFO(CAM_CPAS, "Feature not found, no of featues: %d", + soc_private->num_feature_info); goto end; + } if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE || (soc_private->feature_info[i].type == diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 147f73699488..6efeb80bbdb5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -21,7 +21,6 @@ #include "cam_cpas_api.h" #include "cam_subdev.h" #include "cam_tasklet_util.h" -#include "dt-bindings/msm/msm-camera.h" /* Timeout value in msec */ #define IFE_CSID_TIMEOUT 1000 @@ -5552,17 +5551,6 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->device_enabled = 0; ife_csid_hw->is_resetting = false; ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; - - if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, - (1 << ife_csid_hw->hw_intf->hw_idx), 0) || - !cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE, - (1 << ife_csid_hw->hw_intf->hw_idx), 0)) { - CAM_DBG(CAM_ISP, "IFE:%d is not supported", - ife_csid_hw->hw_intf->hw_idx); - rc = -EINVAL; - return rc; - } - 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); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 8f1f3286540e..17580dca5079 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -17,8 +17,6 @@ #include "cam_ife_hw_mgr.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" -#include - static const char drv_name[] = "vfe"; @@ -684,16 +682,6 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info, return -ENODEV; } - if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, - (1 << hw_intf->hw_idx), 0) || - !cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE, - (1 << hw_intf->hw_idx), 0)) { - CAM_DBG(CAM_ISP, "IFE:%d is not supported", - hw_intf->hw_idx); - rc = -EINVAL; - return rc; - } - rc = cam_irq_controller_init(drv_name, CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX), vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller, From e4e543bb04623f9065a8ad11e4025506948cd516 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Mon, 16 Nov 2020 16:32:47 -0800 Subject: [PATCH 674/790] msm: camera: csiphy: Add debugfs support for csiphy Add debugfs support for csiphy and create a new debugfs for enable/disable csiphy irqs. Following command can be used to enable the csiphy0 irqs: adb shell "echo 0x1 >> /sys/kernel/debug/camera_csiphy/csiphy0_en_irq_dump". CRs-Fixed: 2829969 Change-Id: I769c84f0cd0bf048652cf2d186d900e470973b0a Signed-off-by: Jigar Agrawal --- .../cam_csiphy/cam_csiphy_core.c | 25 +++------ .../cam_csiphy/cam_csiphy_dev.c | 55 ++++++++++++++++++- .../cam_csiphy/cam_csiphy_dev.h | 6 +- .../cam_csiphy/cam_csiphy_soc.c | 19 +++---- 4 files changed, 70 insertions(+), 35 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index ece371256868..9a51499ba10f 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -517,8 +517,6 @@ void cam_csiphy_cphy_irq_disable(struct csiphy_device *csiphy_dev) irqreturn_t cam_csiphy_irq(int irq_num, void *data) { - uint32_t irq; - uint8_t i; struct csiphy_device *csiphy_dev = (struct csiphy_device *)data; struct cam_hw_soc_info *soc_info = NULL; @@ -531,25 +529,16 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data) } soc_info = &csiphy_dev->soc_info; - base = csiphy_dev->soc_info.reg_map[0].mem_base; + base = csiphy_dev->soc_info.reg_map[0].mem_base; csiphy_reg = &csiphy_dev->ctrl_reg->csiphy_reg; - for (i = 0; i < csiphy_dev->num_irq_registers; i++) { - irq = cam_io_r(base + - csiphy_reg->mipi_csiphy_interrupt_status0_addr + - (0x4 * i)); - cam_io_w_mb(irq, base + - csiphy_reg->mipi_csiphy_interrupt_clear0_addr + - (0x4 * i)); - CAM_ERR_RATE_LIMIT(CAM_CSIPHY, - "CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x", - soc_info->index, i, irq); - cam_io_w_mb(0x0, base + - csiphy_reg->mipi_csiphy_interrupt_clear0_addr + - (0x4 * i)); + if (csiphy_dev->enable_irq_dump) { + cam_csiphy_status_dmp(csiphy_dev); + cam_io_w_mb(0x1, + base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr); + cam_io_w_mb(0x0, + base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr); } - cam_io_w_mb(0x1, base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr); - cam_io_w_mb(0x0, base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr); return IRQ_HANDLED; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 29efc2a7f119..95a2ce931c0e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_csiphy_dev.h" @@ -10,6 +10,8 @@ #include #include "camera_main.h" +static struct dentry *root_dentry; + static void cam_csiphy_subdev_handle_message( struct v4l2_subdev *sd, enum cam_subdev_message_type_t message_type, @@ -29,6 +31,51 @@ static void cam_csiphy_subdev_handle_message( } } +static int cam_csiphy_debug_register(struct csiphy_device *csiphy_dev) +{ + int rc = 0; + struct dentry *dbgfileptr = NULL; + char debugfs_name[25]; + + if (!csiphy_dev) { + CAM_ERR(CAM_CSIPHY, "null CSIPHY dev ptr"); + return -EINVAL; + } + + if (!root_dentry) { + dbgfileptr = debugfs_create_dir("camera_csiphy", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_CSIPHY, + "Debugfs could not create directory!"); + rc = -ENOENT; + goto end; + } + /* Store parent inode for cleanup in caller */ + root_dentry = dbgfileptr; + } + + snprintf(debugfs_name, 25, "%s%d%s", "csiphy", + csiphy_dev->soc_info.index, + "_en_irq_dump"); + dbgfileptr = debugfs_create_bool(debugfs_name, 0644, + root_dentry, &csiphy_dev->enable_irq_dump); + + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_CSIPHY, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); + } +end: + return rc; +} + +static void cam_csiphy_debug_unregister(void) +{ + debugfs_remove_recursive(root_dentry); + root_dentry = NULL; +} + static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -212,6 +259,7 @@ static int cam_csiphy_component_bind(struct device *dev, cpas_parms.userdata = new_csiphy_dev; strlcpy(cpas_parms.identifier, "csiphy", CAM_HW_IDENTIFIER_LENGTH); + rc = cam_cpas_register_client(&cpas_parms); if (rc) { CAM_ERR(CAM_CSIPHY, "CPAS registration failed rc: %d", rc); @@ -224,9 +272,11 @@ static int cam_csiphy_component_bind(struct device *dev, cam_csiphy_register_baseaddress(new_csiphy_dev); - CAM_DBG(CAM_CSIPHY, "%s component bound successfully", pdev->name); + + cam_csiphy_debug_register(new_csiphy_dev); + return rc; csiphy_unregister_subdev: @@ -246,6 +296,7 @@ static void cam_csiphy_component_unbind(struct device *dev, struct v4l2_subdev *subdev = platform_get_drvdata(pdev); struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(subdev); + cam_csiphy_debug_unregister(); CAM_INFO(CAM_CSIPHY, "Unbind CSIPHY component"); cam_cpas_unregister_client(csiphy_dev->cpas_handle); cam_csiphy_soc_release(csiphy_dev); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 4643b119805c..59f8b92936d9 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_DEV_H_ @@ -64,8 +64,6 @@ #define DPHY_LANE_3 BIT(6) #define DPHY_CLK_LN BIT(7) -#define ENABLE_IRQ false - enum cam_csiphy_state { CAM_CSIPHY_INIT, CAM_CSIPHY_ACQUIRE, @@ -266,6 +264,7 @@ struct cam_csiphy_param { * @combo_mode: Info regarding combo_mode is enable / disable * @ops: KMD operations * @crm_cb: Callback API pointers + * @enable_irq_dump: Debugfs variable to enable hw IRQ register dump */ struct csiphy_device { char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; @@ -298,6 +297,7 @@ struct csiphy_device { uint8_t cphy_dphy_combo_mode; struct cam_req_mgr_kmd_ops ops; struct cam_req_mgr_crm_cb *crm_cb; + bool enable_irq_dump; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index dde463e37ce6..d882e3b78297 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -88,11 +88,11 @@ int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info) int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) { struct csiphy_reg_parms_t *csiphy_reg = NULL; - int32_t rc = 0; - resource_size_t size = 0; + int32_t rc = 0; + resource_size_t size = 0; void __iomem *phy_base = NULL; - int reg_id = 0; - uint32_t irq, status_reg, clear_reg; + int reg_id = 0; + uint32_t irq, status_reg, clear_reg; if (!csiphy_dev) { rc = -EINVAL; @@ -111,13 +111,8 @@ int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) if (phy_base != NULL) { for (reg_id = 0; reg_id < size; reg_id++) { - uint32_t offset; - - offset = status_reg + (0x4 * reg_id); - irq = cam_io_r(phy_base + offset); - offset = clear_reg + (0x4 * reg_id); - cam_io_w_mb(irq, phy_base + offset); - cam_io_w_mb(0, phy_base + offset); + irq = cam_io_r(phy_base + status_reg + (0x4 * reg_id)); + cam_io_w_mb(irq, phy_base + clear_reg + (0x4 * reg_id)); CAM_INFO(CAM_CSIPHY, "CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x", @@ -200,7 +195,7 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index) vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, index); rc = cam_soc_util_enable_platform_resource(soc_info, true, - vote_level, ENABLE_IRQ); + vote_level, true); if (rc < 0) { CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d", rc); From 017b57c8a19efd36d21509660837e0a36256ba2c Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 22 Jan 2021 04:30:07 +0530 Subject: [PATCH 675/790] msm: camera: isp: Correct halt command for Yupik camera This change is to correct csid halt command and correct qos setting for Yupik camera. CRs-Fixed: 2825675 Change-Id: I002a3f5864f6c157249465bdf71d268b547eb196 Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 6 +++--- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 7 ++++++- .../isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h | 3 ++- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 9 +++------ 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 9d2bdfc92633..3e739d3c33a3 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V165_100_H_ @@ -337,7 +337,7 @@ static struct cam_camnoc_specific * Power on default values are taking care of required * register settings. */ - .enable = true, + .enable = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3B88, /* IFE01_NRDI_ENCCTL_LOW */ @@ -555,7 +555,7 @@ static struct cam_camnoc_specific { /*SidebandManager_main_SidebandManager_FlagOutSet0_Low*/ .port_type = CAM_CAMNOC_ICP, - .enable = true, + .enable = false, .flag_out_set0_low = { .enable = true, .access_type = CAM_REG_TYPE_WRITE, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 6efeb80bbdb5..b807a9a5ab48 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2290,6 +2290,7 @@ static int cam_ife_csid_enable_pxl_path( uint32_t val = 0; struct cam_isp_sensor_dimension *path_config; unsigned int irq_mask_val = 0; + uint32_t camera_hw_version; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -2342,6 +2343,8 @@ static int cam_ife_csid_enable_pxl_path( } } + cam_cpas_get_cpas_hw_version(&camera_hw_version); + /* Set master or slave path */ if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) { /*Set halt mode as master */ @@ -2352,7 +2355,8 @@ static int cam_ife_csid_enable_pxl_path( val = CSID_HALT_MODE_MASTER << 2; } else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE) { /*Set halt mode as slave and set master idx */ - if (pxl_reg->halt_master_sel_en) + if (pxl_reg->halt_master_sel_en || + camera_hw_version == CAM_CPAS_TITAN_165_V100) val = CSID_HALT_MODE_SLAVE << 2; else val = path_data->master_idx << 4 | @@ -2361,6 +2365,7 @@ static int cam_ife_csid_enable_pxl_path( /* Default is internal halt mode */ val = 0; } + /* * Resume at frame boundary if Master or No Sync. * Slave will get resume command from Master. diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h index 1e28760bf2a9..bba9302a4f04 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE165_160_H_ @@ -88,6 +88,7 @@ static struct cam_vfe_camif_reg_data vfe_165_160_camif_reg_data = { .subscribe_irq_mask0 = 0x00000017, .subscribe_irq_mask1 = 0x00000000, .enable_diagnostic_hw = 0x1, + .dual_vfe_sync_mask = 0x3, }; static struct cam_vfe_fe_ver1_reg vfe165_160_fe_reg = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 0a6d62412f1d..be9a5352504a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -2639,11 +2639,6 @@ static void cam_vfe_bus_update_ubwc_meta_addr( if (rc) { CAM_ERR(CAM_ISP, "Failed to get HW version rc: %d", rc); goto end; - } else if ((camera_hw_version < CAM_CPAS_TITAN_170_V100) || - (camera_hw_version > CAM_CPAS_TITAN_175_V130)) { - CAM_ERR(CAM_ISP, "Invalid HW version: %d", - camera_hw_version); - goto end; } switch (camera_hw_version) { @@ -2670,6 +2665,8 @@ static void cam_vfe_bus_update_ubwc_meta_addr( image_buf); break; default: + CAM_ERR(CAM_ISP, "Invalid HW version: %d", + camera_hw_version); break; } end: From 26182c7d5866547403310c56092789cbafef5c63 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 11 Feb 2021 14:24:39 +0530 Subject: [PATCH 676/790] msm: camera: isp: IFE and CSID probe based on fuse Some ISP hardware id instances are disabled on some target skus. Cpas driver has fuse information based on the dtsi entries. ISP hw driver queries the cpas driver whether hw instance is supported or not. If ISP hardware is supported on the target then continue the isp hardware probe. Fix for get HW feature: When feature is enable or disable type and HW mask is not indicating the HW index, do not update the supported. By default it is supported. CRs-Fixed: 2825675 Change-Id: I777e5790060388458562e7a53fea8a7324ffa9d3 Signed-off-by: Wyes Karny --- drivers/cam_cpas/cam_cpas_intf.c | 7 +------ .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 11 +++++++++++ .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c | 7 +++++-- .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 11 +++++++++++ .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c | 4 +++- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index 94c0101433ee..7d007f4b3c29 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -161,19 +161,14 @@ bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map, if (soc_private->feature_info[i].feature == flag) break; - if (i == soc_private->num_feature_info) { - CAM_INFO(CAM_CPAS, "Feature not found, no of featues: %d", - soc_private->num_feature_info); + if (i == soc_private->num_feature_info) goto end; - } if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE || (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_ENABLE)) { if ((soc_private->feature_info[i].hw_map & hw_map) == hw_map) supported = soc_private->feature_info[i].enable; - else - supported = !soc_private->feature_info[i].enable; } else { if (!fuse_val) { CAM_ERR(CAM_CPAS, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index b807a9a5ab48..22f2c0ca37f5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -21,6 +21,7 @@ #include "cam_cpas_api.h" #include "cam_subdev.h" #include "cam_tasklet_util.h" +#include "dt-bindings/msm/msm-camera.h" /* Timeout value in msec */ #define IFE_CSID_TIMEOUT 1000 @@ -5556,6 +5557,16 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->device_enabled = 0; ife_csid_hw->is_resetting = false; ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + + if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, + (1 << ife_csid_hw->hw_intf->hw_idx), 0) || + !cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE, + (1 << ife_csid_hw->hw_intf->hw_idx), 0)) { + CAM_DBG(CAM_ISP, "IFE:%d is not supported", + ife_csid_hw->hw_intf->hw_idx); + return -ENODEV; + } + 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); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c index 55c8cd4274df..f8fc0f651481 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -79,8 +79,11 @@ static int cam_ife_csid_component_bind(struct device *dev, csid_dev->csid_info = csid_hw_data; rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx, false); - if (rc) + if (rc) { + if (rc == -ENODEV) + rc = 0; goto free_dev; + } platform_set_drvdata(pdev, csid_dev); CAM_DBG(CAM_ISP, "CSID:%d component bound successfully", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 17580dca5079..dc763c481855 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -17,6 +17,8 @@ #include "cam_ife_hw_mgr.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include + static const char drv_name[] = "vfe"; @@ -682,6 +684,15 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info, return -ENODEV; } + if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, + (1 << hw_intf->hw_idx), 0) || + !cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE, + (1 << hw_intf->hw_idx), 0)) { + CAM_DBG(CAM_ISP, "IFE:%d is not supported", + hw_intf->hw_idx); + return -ENXIO; + } + rc = cam_irq_controller_init(drv_name, CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX), vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c index 4be7e8e8de13..4183e59c319f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ @@ -100,6 +100,8 @@ static int cam_vfe_component_bind(struct device *dev, rc = cam_vfe_core_init(core_info, &vfe_hw->soc_info, vfe_hw_intf, hw_info); if (rc < 0) { + if (rc == -ENXIO) + rc = 0; CAM_ERR(CAM_ISP, "Failed to init core rc=%d", rc); goto deinit_soc; } From 363894c03bfbb5abd4adc6b677301d34636583c3 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 10 Feb 2021 10:19:11 +0530 Subject: [PATCH 677/790] msm: camera: ope: Dump stripe info at the time of hang Add logic to dump stripe info and wait event status at the time of cdm hang. CRs-Fixed: 2878214 Change-Id: Ib9892b0273e4436988c5f1384d18d60d29529c94 Signed-off-by: Alok Chauhan --- drivers/cam_cdm/cam_cdm_hw_core.c | 13 ++++++++++++- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 10 +++++++++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c | 18 +++++++++++++++++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 3 ++- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h | 8 ++++++-- .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 6 +++++- 6 files changed, 51 insertions(+), 7 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 49bcb027f130..f8937e8844d0 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -416,6 +416,17 @@ void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x", dump_reg[0], dump_reg[1]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->wait_status, &dump_reg[0]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->comp_wait[0]->comp_wait_status, + &dump_reg[1]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->comp_wait[1]->comp_wait_status, + &dump_reg[2]); + CAM_INFO(CAM_CDM, "wait status 0x%x comp wait status 0x%x: 0x%x", + dump_reg[0], dump_reg[1], dump_reg[2]); + cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->current_bl_len, &dump_reg[0]); CAM_INFO(CAM_CDM, diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 917dc596dcb8..637cdf0e1e5a 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -705,6 +705,7 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_DUMP_DEBUG, NULL, 0); + task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work); if (!task) { CAM_ERR(CAM_OPE, "no empty task"); @@ -1602,6 +1603,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, struct timespec64 ts; uint32_t evt_id = CAM_CTX_EVT_ID_SUCCESS; bool dump_flag = true; + int i; if (!userdata) { CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); @@ -1663,9 +1665,15 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id, ctx->ctx_id); CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", ope_req->request_id); + if (status != CAM_CDM_CB_STATUS_HW_FLUSH) { cam_ope_dump_req_data(ope_req); dump_flag = false; + + CAM_INFO(CAM_OPE, "bach_size: %d", ctx->req_list[cookie]->num_batch); + for (i = 0; i < ctx->req_list[cookie]->num_batch; i++) + CAM_INFO(CAM_OPE, "i: %d num_stripes: %d", + i, ctx->req_list[cookie]->num_stripes[i]); } rc = cam_ope_mgr_reset_hw(); evt_id = CAM_CTX_EVT_ID_ERROR; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index fc9903d565e3..164706b6a5d9 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -787,6 +787,11 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, uint32_t *print_ptr; int num_dmi = 0; struct cam_cdm_utils_ops *cdm_ops; + uint32_t reg_val_pair[2]; + struct cam_hw_info *ope_dev; + struct cam_ope_device_core_info *core_info; + struct ope_hw *ope_hw; + struct cam_ope_top_reg *top_reg; if (s_idx >= OPE_MAX_CMD_BUFS || batch_idx >= OPE_MAX_BATCH_SIZE) { @@ -868,10 +873,21 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, } CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx); } + if (hw_mgr->frame_dump_enable) dump_stripe_cmd(frm_proc, stripe_idx, i, k, iova_addr, kmd_buf, buf_len); } + + ope_dev = hw_mgr->ope_dev_intf[0]->hw_priv; + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + ope_hw = core_info->ope_hw_info->ope_hw; + top_reg = ope_hw->top_reg; + + reg_val_pair[0] = top_reg->offset + top_reg->scratch_reg; + reg_val_pair[1] = stripe_idx; + kmd_buf = cdm_ops->cdm_write_regrandom(kmd_buf, 1, reg_val_pair); + return kmd_buf; } diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index 0c4c10ca751f..5cdaec6820bb 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_OPE_HW_H @@ -82,6 +82,7 @@ struct cam_ope_top_reg { uint32_t violation_status; uint32_t throttle_cnt_cfg; uint32_t debug_cfg; + uint32_t scratch_reg; uint32_t num_debug_registers; struct cam_ope_debug_register *debug_regs; }; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index b917b2fabd1b..2141350445e3 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_OPE_HW_100_H @@ -146,6 +146,9 @@ static struct cam_ope_debug_register ope_debug_regs[OPE_MAX_DEBUG_REGISTER] = { { .offset = 0xD0, }, + { + .offset = 0xD4, + }, }; static struct cam_ope_top_reg ope_top_reg = { @@ -163,7 +166,8 @@ static struct cam_ope_top_reg ope_top_reg = { .violation_status = 0x28, .throttle_cnt_cfg = 0x2C, .debug_cfg = 0xDC, - .num_debug_registers = 9, + .scratch_reg = 0x1F0, + .num_debug_registers = 10, .debug_regs = ope_debug_regs, }; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index 1929a4d6e601..caa36e947ff5 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -48,6 +48,10 @@ static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info) CAM_INFO(CAM_OPE, "status[%d-%d] : 0x%x 0x%x 0x%x", i, i+2, val[0], val[1], val[2]); } + + CAM_INFO(CAM_OPE, "scrath reg: 0x%x, stripe_idx: %d", + top_reg->offset + top_reg->scratch_reg, + cam_io_r_mb(top_reg->base + top_reg->scratch_reg)); return 0; } From 2ee0a3ec893513f15ee1f749b078c130e5f7e3ab Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 11 Feb 2021 10:20:31 +0530 Subject: [PATCH 678/790] msm: camera: ope: Update for new IQ modules Added changes to dump new IQ modules as well in OPE during page fault and hang scenario. CRs-Fixed: 2878214 Change-Id: I97e7d4ee2ed9899ed299155c9aca8b094dff18f0 Signed-off-by: Alok Chauhan --- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h | 2 +- drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h | 9 +++++++++ .../cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index 5cdaec6820bb..680c8e0b7da9 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -14,7 +14,7 @@ #define MAX_RD_CLIENTS 3 #define MAX_WR_CLIENTS 8 -#define MAX_PP_CLIENTS 29 +#define MAX_PP_CLIENTS 32 #define MAX_RW_CLIENTS (MAX_RD_CLIENTS + MAX_WR_CLIENTS) diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index 2141350445e3..3ccf9ee120ba 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -726,6 +726,15 @@ static struct cam_ope_pp_reg ope_pp_reg = { { .hw_status = 0x3C04, }, + { + .hw_status = 0x3E04, + }, + { + .hw_status = 0x4004, + }, + { + .hw_status = 0x4204, + }, }, }; diff --git a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index caa36e947ff5..1ec6552d807c 100644 --- a/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -33,8 +33,12 @@ static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info) { uint32_t i, val[3]; struct cam_ope_top_reg *top_reg; + struct cam_ope_pp_reg *pp_reg; + uint32_t pp_hw_status = 0; top_reg = ope_hw_info->top_reg; + pp_reg = ope_hw_info->pp_reg; + for (i = 0; i < top_reg->num_debug_registers; i = i+3) { val[0] = cam_io_r_mb(top_reg->base + top_reg->debug_regs[i].offset); @@ -52,6 +56,20 @@ static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info) CAM_INFO(CAM_OPE, "scrath reg: 0x%x, stripe_idx: %d", top_reg->offset + top_reg->scratch_reg, cam_io_r_mb(top_reg->base + top_reg->scratch_reg)); + + for (i = 0; i < pp_reg->num_clients ; i++) { + pp_hw_status = 0; + pp_hw_status = + cam_io_r_mb(pp_reg->base + + pp_reg->pp_clients[i] + .hw_status); + + if (pp_hw_status) + CAM_ERR(CAM_OPE, + "ope pp hw_status offset 0x%x val 0x%x", + pp_reg->pp_clients[i].hw_status, + pp_hw_status); + } return 0; } From d0e2538e98010f1afb1b8dd8311543e13d3f5f28 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Mon, 8 Feb 2021 20:48:48 +0530 Subject: [PATCH 679/790] msm: camera: cdm: Update hang detect logic Currently cdm driver is updating work records in case of all the interrupts received, but decrementing only when it schedule workq for inline irq interrupt. This causes the mismatch in work records and return incorrect work record count when cdm client check the cdm hang detect. Updated hang detect logic in cdm driver. CRs-Fixed: 2878695 Change-Id: I7039422bf573a7105c16ac2f752eb235c377bfee Signed-off-by: Alok Chauhan --- drivers/cam_cdm/cam_cdm_hw_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index f8937e8844d0..f068f9f51c59 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1499,6 +1499,8 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) if (payload[i]->irq_data == CAM_CDM_DBG_GEN_IRQ_USR_DATA) CAM_INFO(CAM_CDM, "Debug gen_irq received"); + + atomic_inc(&cdm_core->bl_fifo[i].work_record); } CAM_DBG(CAM_CDM, @@ -1525,7 +1527,6 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) return IRQ_HANDLED; } - atomic_inc(&cdm_core->bl_fifo[i].work_record); payload[i]->workq_scheduled_ts = ktime_get(); work_status = queue_work( @@ -1857,14 +1858,17 @@ int cam_hw_cdm_hang_detect( uint32_t handle) { struct cam_cdm *cdm_core = NULL; + struct cam_hw_soc_info *soc_info; int i, rc = -1; cdm_core = (struct cam_cdm *)cdm_hw->core_info; + soc_info = &cdm_hw->soc_info; for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) if (atomic_read(&cdm_core->bl_fifo[i].work_record)) { CAM_WARN(CAM_CDM, - "workqueue got delayed, work_record :%u", + "workqueue got delayed for %s%u, work_record :%u", + soc_info->label_name, soc_info->index, atomic_read(&cdm_core->bl_fifo[i].work_record)); rc = 0; break; From 6bda2323cb930e5d85dc6c5705c6e7f342dc9caf Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Fri, 12 Feb 2021 09:48:29 +0530 Subject: [PATCH 680/790] msm: camera: flash: Apply flash packets at epoch instead of eof Partial lighted frame can be observed if flash packet is getting applied at eof instead of epoch. This change make the flash packet to be applied at epoch instead of eof. CRs-Fixed: 2853936 Change-Id: I77dac7c0b8cb8149f26c5f89cced590bc3b957ee Signed-off-by: Tony Lijo Jose --- drivers/cam_req_mgr/cam_req_mgr_core.c | 13 +++++++++---- .../cam_sensor_module/cam_flash/cam_flash_core.c | 16 ++++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 78be9bcf3e2d..5a74aff10652 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -568,8 +568,6 @@ static void __cam_req_mgr_flush_req_slot( in_q->rd_idx = 0; link->trigger_cnt[0] = 0; link->trigger_cnt[1] = 0; - link->trigger_mask = 0; - link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF; } /** @@ -823,6 +821,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, continue; } + if (slot->ops.apply_at_eof && slot->ops.skip_next_frame) { + CAM_ERR(CAM_CRM, + "Both EOF and SOF trigger is not supported"); + return -EINVAL; + } + if (dev->dev_hdl != slot->ops.dev_hdl) { CAM_DBG(CAM_CRM, "Dev_hdl : %d Not matched:: Expected dev_hdl: %d", @@ -2652,7 +2656,8 @@ int cam_req_mgr_process_add_req(void *priv, void *data) (add_req->skip_before_applying & 0xFF)); } - if (add_req->trigger_eof) { + /* Used when Precise Flash is enabled */ + if ((add_req->trigger_eof) && (!add_req->skip_before_applying)) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index f50fb5da4e21..156fcf0dbafe 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -1546,9 +1546,12 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) CAM_DBG(CAM_FLASH, "FLASH_CMD_TYPE op:%d", flash_data->opcode); + if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) + add_req.skip_before_applying |= SKIP_NEXT_FRAME; if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREDURATION) { + add_req.trigger_eof = true; /* Active time for the preflash */ flash_data->flash_active_time_ms = (flash_operation_info->time_on_duration_ns) @@ -1745,13 +1748,14 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) if ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS) { - add_req.skip_before_applying |= SKIP_NEXT_FRAME; - add_req.trigger_eof = true; - - if (flash_data && (flash_data->opcode != + if ((flash_data->opcode != CAMERA_SENSOR_FLASH_OP_FIREDURATION)) add_req.skip_before_applying |= 1; - else + else if (flash_data->opcode == + CAMERA_SENSOR_FLASH_OP_FIREDURATION) { + CAM_DBG(CAM_FLASH, "Trigger eof is set for request "); + add_req.trigger_eof = true; + } else add_req.skip_before_applying = 0; } else { add_req.skip_before_applying = 0; From 39627307832fbe73e54441fbb0031241219d43ca Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 10 Feb 2021 14:33:02 +0530 Subject: [PATCH 681/790] msm: camera: isp: Add MID information for IFE Add MID information for IFE and IFE lite. CRs-Fixed: 2876970 Change-Id: I2de1b87decacbef7e06bb38c419d13cf78a6fe59 Signed-off-by: Tejas Prajapati --- .../isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h | 28 +++++++++++++++++++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h | 6 +++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h index bba9302a4f04..8dbcfc5da319 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h @@ -1021,115 +1021,143 @@ static struct cam_vfe_bus_ver2_hw_info vfe165_160_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, .max_width = -1, .max_height = -1, + .mid[0] = 4, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, + .mid[0] = 5, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, + .mid[0] = 6, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL, .max_width = 4096, .max_height = 4096, + .mid[0] = 32, + .mid[1] = 33, + .mid[2] = 34, + .mid[3] = 35, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4, .max_width = 1920, .max_height = 1080, + .mid[0] = 36, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16, .max_width = 1920, .max_height = 1080, + .mid[0] = 37, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP, .max_width = -1, .max_height = -1, + .mid[0] = 40, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FD, .max_width = 1920, .max_height = 1080, + .mid[0] = 38, + .mid[1] = 39, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_PDAF, .max_width = -1, .max_height = -1, + .mid[0] = 41, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE, .max_width = -1, .max_height = -1, + .mid[0] = 42, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST, .max_width = 1920, .max_height = 1080, + .mid[0] = 43, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG, .max_width = -1, .max_height = -1, + .mid[0] = 44, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF, .max_width = -1, .max_height = -1, + .mid[0] = 45, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG, .max_width = -1, .max_height = -1, + .mid[0] = 46, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST, .max_width = -1, .max_height = -1, + .mid[0] = 47, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS, .max_width = -1, .max_height = -1, + .mid[0] = 48, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS, .max_width = -1, .max_height = -1, + .mid[0] = 49, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST, .max_width = -1, .max_height = -1, + .mid[0] = 50, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, .max_width = 4096, .max_height = 4096, + .mid[0] = 51, + .mid[1] = 52, + .mid[2] = 53, + .mid[3] = 54, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP, .max_width = 1920, .max_height = 1080, + .mid[0] = 55, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP, .max_width = 1920, .max_height = 1080, + .mid[0] = 56, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_2PD, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h index e1d7a80f04a3..3aab089d58fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE16X_H_ @@ -315,21 +315,25 @@ static struct cam_vfe_bus_ver2_hw_info vfe16x_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, .max_width = -1, .max_height = -1, + .mid[0] = 4, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, + .mid[0] = 5, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, + .mid[0] = 6, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI3, .max_width = -1, .max_height = -1, + .mid[0] = 7, }, }, .top_irq_shift = 9, From ab5a6389c6d21ea58dd07ec13d9f845a62dbb0d2 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Wed, 16 Dec 2020 13:12:28 +0530 Subject: [PATCH 682/790] msm: camera: jpeg: Handle JPEG smmu fault with pid info Kernel apis provide information fault caused pid and mid data. Handle the JPEG smmu fault using pid and mid data. Based on the mid data, dump only corresponding port info which caused the fault. Pid and mid values are target dependent, these values will be updated on the jpeg node dt entries. CRs-Fixed: 2878371 Change-Id: I0d2d1e474d4662707d85efd022ccce87e67f0d93 Signed-off-by: Ravikishore Pampana --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 194 +++++++++++------- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 2 + .../jpeg_hw/include/cam_jpeg_hw_intf.h | 12 +- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 47 ++++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 6 +- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 16 +- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c | 36 +++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h | 20 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 47 ++++- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h | 6 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 16 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c | 35 +++- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h | 20 +- 13 files changed, 366 insertions(+), 91 deletions(-) diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 7d3b42e7a740..8078ee59dc20 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -694,75 +694,6 @@ err_after_dq_free_list: return rc; } -static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, - int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, - bool *mem_found) -{ - dma_addr_t iova_addr; - size_t src_buf_size; - int i; - int j; - int rc = 0; - int32_t mmu_hdl; - struct cam_buf_io_cfg *io_cfg = NULL; - - if (mem_found) - *mem_found = false; - - io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + - packet->io_configs_offset / 4); - - for (i = 0; i < packet->num_io_configs; i++) { - for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { - if (!io_cfg[i].mem_handle[j]) - break; - - if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == - GET_FD_FROM_HANDLE(pf_buf_info)) { - CAM_INFO(CAM_JPEG, - "Found PF at port: %d mem %x fd: %x", - io_cfg[i].resource_type, - io_cfg[i].mem_handle[j], - pf_buf_info); - if (mem_found) - *mem_found = true; - } - - CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d", - io_cfg[i].resource_type, - io_cfg[i].fence, - io_cfg[i].format, - io_cfg[i].direction); - - mmu_hdl = cam_mem_is_secure_buf( - io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : - iommu_hdl; - rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], - mmu_hdl, &iova_addr, &src_buf_size); - if (rc < 0) { - CAM_ERR(CAM_UTIL, "get src buf address fail"); - continue; - } - if ((iova_addr & 0xFFFFFFFF) != iova_addr) { - CAM_ERR(CAM_JPEG, "Invalid mapped address"); - rc = -EINVAL; - continue; - } - - CAM_INFO(CAM_JPEG, - "pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x", - j, 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], - io_cfg[i].mem_handle[j]); - } - } -} - static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { @@ -1570,6 +1501,18 @@ static int cam_jpeg_init_devices(struct device_node *of_node, g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_DMA][0] = &dma_soc_info->reg_map[0]; + rc = g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_ops.process_cmd( + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_priv, + CAM_JPEG_CMD_GET_NUM_PID, + &g_jpeg_hw_mgr.num_pid[CAM_JPEG_DEV_ENC], + sizeof(uint32_t)); + + rc = g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_ops.process_cmd( + g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_priv, + CAM_JPEG_CMD_GET_NUM_PID, + &g_jpeg_hw_mgr.num_pid[CAM_JPEG_DEV_DMA], + sizeof(uint32_t)); + *p_num_enc_dev = num_dev; *p_num_dma_dev = num_dma_dev; @@ -1722,6 +1665,109 @@ hw_dump: return rc; } +static void cam_jpeg_mgr_dump_pf_data( + struct cam_jpeg_hw_mgr *hw_mgr, + struct cam_hw_cmd_args *hw_cmd_args) +{ + struct cam_jpeg_hw_ctx_data *ctx_data; + struct cam_packet *packet; + struct cam_jpeg_match_pid_args jpeg_pid_mid_args; + struct cam_buf_io_cfg *io_cfg = NULL; + uint32_t dev_type; + dma_addr_t iova_addr; + size_t src_buf_size; + int i, j; + int32_t mmu_hdl; + bool hw_pid_support = true; + int rc = 0; + + ctx_data = (struct cam_jpeg_hw_ctx_data *)hw_cmd_args->ctxt_to_hw_map; + packet = hw_cmd_args->u.pf_args.pf_data.packet; + + jpeg_pid_mid_args.fault_mid = hw_cmd_args->u.pf_args.mid; + jpeg_pid_mid_args.pid = hw_cmd_args->u.pf_args.pid; + dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; + + if (!hw_mgr->num_pid[dev_type]) { + hw_pid_support = false; + goto iodump; + } + + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_MATCH_PID_MID, + &jpeg_pid_mid_args, sizeof(jpeg_pid_mid_args)); + if (rc) { + CAM_ERR(CAM_JPEG, "CAM_JPEG_CMD_MATCH_PID_MID failed %d", rc); + return; + } + + if (!jpeg_pid_mid_args.pid_match_found) { + CAM_INFO(CAM_JPEG, "This context data is not matched with pf pid and mid"); + return; + } + +iodump: + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + if (hw_pid_support) { + if (io_cfg[i].resource_type != + jpeg_pid_mid_args.match_res) + continue; + + if (i == packet->num_io_configs) { + CAM_ERR(CAM_JPEG, + "getting io port for mid resource id failed req id:%lld res id:0x%x", + packet->header.request_id, + jpeg_pid_mid_args.match_res); + return; + } + } + + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? hw_mgr->iommu_sec_hdl : + hw_mgr->iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get src buf address fail"); + continue; + } + if ((iova_addr & 0xFFFFFFFF) != iova_addr) { + CAM_ERR(CAM_JPEG, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_JPEG, + "pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x", + j, 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], + io_cfg[i].mem_handle[j]); + } + + if (hw_pid_support) + return; + } +} + static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -1735,15 +1781,11 @@ static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args) switch (hw_cmd_args->cmd_type) { case CAM_HW_MGR_CMD_DUMP_PF_INFO: - cam_jpeg_mgr_print_io_bufs( - hw_cmd_args->u.pf_args.pf_data.packet, - hw_mgr->iommu_hdl, - hw_mgr->iommu_sec_hdl, - hw_cmd_args->u.pf_args.buf_info, - hw_cmd_args->u.pf_args.mem_found); + cam_jpeg_mgr_dump_pf_data(hw_mgr, hw_cmd_args); break; default: - CAM_ERR(CAM_JPEG, "Invalid cmd"); + CAM_ERR(CAM_JPEG, "Invalid cmd :%d", + hw_cmd_args->cmd_type); } return rc; diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 4e90f5386f32..c4cd35307701 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -132,6 +132,7 @@ struct cam_jpeg_hw_ctx_data { * @hw_config_req_list: Pending hw update requests list * @free_req_list: Free nodes for above list * @req_list: Nodes of hw update list + * @num_pid: num of pids supported in the device */ struct cam_jpeg_hw_mgr { struct mutex hw_mgr_mutex; @@ -160,6 +161,7 @@ struct cam_jpeg_hw_mgr { struct list_head hw_config_req_list; struct list_head free_req_list; struct cam_jpeg_hw_cfg_req req_list[CAM_JPEG_HW_CFG_Q_MAX]; + uint32_t num_pid[CAM_JPEG_DEV_TYPE_MAX]; }; #endif /* CAM_JPEG_HW_MGR_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h index df552c4d04cf..1856e6e3cc13 100644 --- a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_HW_INTF_H @@ -17,6 +17,7 @@ #define CAM_JPEG_HW_DUMP_TAG_MAX_LEN 32 #define CAM_JPEG_HW_DUMP_NUM_WORDS 5 +#define CAM_JPEG_HW_MAX_NUM_PID 2 enum cam_jpeg_hw_type { CAM_JPEG_DEV_ENC, @@ -43,10 +44,19 @@ struct cam_jpeg_hw_dump_header { uint32_t word_size; }; +struct cam_jpeg_match_pid_args { + uint32_t pid; + uint32_t fault_mid; + bool pid_match_found; + uint32_t match_res; +}; + enum cam_jpeg_cmd_type { CAM_JPEG_CMD_CDM_CFG, CAM_JPEG_CMD_SET_IRQ_CB, CAM_JPEG_CMD_HW_DUMP, + CAM_JPEG_CMD_GET_NUM_PID, + CAM_JPEG_CMD_MATCH_PID_MID, CAM_JPEG_CMD_MAX, }; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c index 87431897d4b1..bae4f3d9982d 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -377,7 +377,9 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, { struct cam_hw_info *jpeg_dma_dev = device_priv; struct cam_jpeg_dma_device_core_info *core_info = NULL; - int rc; + struct cam_jpeg_match_pid_args *match_pid_mid = NULL; + uint32_t *num_pid = NULL; + int i, rc = 0; if (!device_priv) { CAM_ERR(CAM_JPEG, "Invalid arguments"); @@ -412,6 +414,47 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, rc = 0; break; } + case CAM_JPEG_CMD_GET_NUM_PID: + if (!cmd_args) { + CAM_ERR(CAM_JPEG, "cmd args NULL"); + return -EINVAL; + } + + num_pid = (uint32_t *)cmd_args; + *num_pid = core_info->num_pid; + + break; + case CAM_JPEG_CMD_MATCH_PID_MID: + match_pid_mid = (struct cam_jpeg_match_pid_args *)cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_JPEG, "cmd args NULL"); + return -EINVAL; + } + + for (i = 0; i < core_info->num_pid; i++) { + if (core_info->pid[i] == match_pid_mid->pid) + break; + } + + if (i == core_info->num_pid) + match_pid_mid->pid_match_found = false; + else + match_pid_mid->pid_match_found = true; + + if (match_pid_mid->pid_match_found) { + if (match_pid_mid->fault_mid == core_info->rd_mid) { + match_pid_mid->match_res = + CAM_JPEG_DMA_INPUT_IMAGE; + } else if (match_pid_mid->fault_mid == + core_info->wr_mid) { + match_pid_mid->match_res = + CAM_JPEG_DMA_OUTPUT_IMAGE; + } else + match_pid_mid->pid_match_found = false; + } + + break; default: rc = -EINVAL; break; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h index 94085814b472..8f08033b04f6 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_DMA_CORE_H @@ -63,6 +63,10 @@ struct cam_jpeg_dma_device_core_info { int32_t ref_count; struct mutex core_mutex; int32_t result_size; + uint32_t num_pid; + uint32_t pid[CAM_JPEG_HW_MAX_NUM_PID]; + uint32_t rd_mid; + uint32_t wr_mid; }; int cam_jpeg_dma_init_hw(void *device_priv, diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index 214bde71bcb6..c5c4b78cc1f4 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -66,7 +66,8 @@ static int cam_jpeg_dma_component_bind(struct device *dev, const struct of_device_id *match_dev = NULL; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; - int rc; + struct cam_jpeg_dma_soc_private *soc_private; + int i, rc; struct platform_device *pdev = to_platform_device(dev); jpeg_dma_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); @@ -135,6 +136,17 @@ static int cam_jpeg_dma_component_bind(struct device *dev, spin_lock_init(&jpeg_dma_dev->hw_lock); init_completion(&jpeg_dma_dev->hw_complete); CAM_DBG(CAM_JPEG, "JPEG-DMA component bound successfully"); + + soc_private = (struct cam_jpeg_dma_soc_private *) + jpeg_dma_dev->soc_info.soc_private; + + core_info->num_pid = soc_private->num_pid; + for (i = 0; i < soc_private->num_pid; i++) + core_info->pid[i] = soc_private->pid[i]; + + core_info->rd_mid = soc_private->rd_mid; + core_info->wr_mid = soc_private->wr_mid; + return rc; error_reg_cpas: diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c index 9dda8f284c35..b5abbd499087 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. */ #include @@ -16,8 +16,20 @@ int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t jpeg_dma_irq_handler, void *irq_data) { + struct cam_jpeg_dma_soc_private *soc_private; + struct platform_device *pdev = NULL; + int num_pid = 0, i = 0; int rc; + soc_private = kzalloc(sizeof(struct cam_jpeg_dma_soc_private), + GFP_KERNEL); + if (!soc_private) { + CAM_DBG(CAM_JPEG, "Error! soc_private Alloc Failed"); + return -ENOMEM; + } + soc_info->soc_private = soc_private; + pdev = soc_info->pdev; + rc = cam_soc_util_get_dt_properties(soc_info); if (rc) return rc; @@ -28,6 +40,28 @@ int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info, if (rc) CAM_ERR(CAM_JPEG, "init soc failed %d", rc); + soc_private->num_pid = 0; + soc_private->rd_mid = UINT_MAX; + soc_private->wr_mid = UINT_MAX; + + num_pid = of_property_count_u32_elems(pdev->dev.of_node, "cam_hw_pid"); + CAM_DBG(CAM_JPEG, "jpeg:%d pid count %d", soc_info->index, num_pid); + + if (num_pid <= 0 || num_pid > CAM_JPEG_HW_MAX_NUM_PID) + goto end; + + soc_private->num_pid = num_pid; + for (i = 0; i < num_pid; i++) + of_property_read_u32_index(pdev->dev.of_node, "cam_hw_pid", i, + &soc_private->pid[i]); + + of_property_read_u32(pdev->dev.of_node, + "cam_hw_rd_mid", &soc_private->rd_mid); + + of_property_read_u32(pdev->dev.of_node, + "cam_hw_wr_mid", &soc_private->wr_mid); + +end: return rc; } diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h index a0c07489ee77..418dd1efe3ce 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h @@ -1,12 +1,30 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved. */ #ifndef _CAM_JPEG_DMA_SOC_H_ #define _CAM_JPEG_DMA_SOC_H_ #include "cam_soc_util.h" +#include "cam_jpeg_hw_intf.h" + +/* + * struct cam_jpeg_dma_soc_private: + * + * @Brief: Private SOC data specific to JPEG DMA Driver + * + * @num_pid JPEG number of pids + * @pid: JPEG DMA pid value list + * @rd_mid: JPEG DMA inport read mid value + * @wr_mid: JPEG DMA outport write mid value + */ +struct cam_jpeg_dma_soc_private { + uint32_t num_pid; + uint32_t pid[CAM_JPEG_HW_MAX_NUM_PID]; + uint32_t rd_mid; + uint32_t wr_mid; +}; int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t jpeg_dma_irq_handler, void *irq_data); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index 8661dbfc72e6..5f79260e1391 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -498,7 +498,9 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, { struct cam_hw_info *jpeg_enc_dev = device_priv; struct cam_jpeg_enc_device_core_info *core_info = NULL; - int rc; + struct cam_jpeg_match_pid_args *match_pid_mid = NULL; + uint32_t *num_pid = NULL; + int i, rc = 0; if (!device_priv) { CAM_ERR(CAM_JPEG, "Invalid arguments"); @@ -539,6 +541,47 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, cmd_args); break; } + case CAM_JPEG_CMD_GET_NUM_PID: + if (!cmd_args) { + CAM_ERR(CAM_JPEG, "cmd args NULL"); + return -EINVAL; + } + + num_pid = (uint32_t *)cmd_args; + *num_pid = core_info->num_pid; + + break; + case CAM_JPEG_CMD_MATCH_PID_MID: + match_pid_mid = (struct cam_jpeg_match_pid_args *)cmd_args; + + if (!cmd_args) { + CAM_ERR(CAM_JPEG, "cmd args NULL"); + return -EINVAL; + } + + for (i = 0 ; i < core_info->num_pid; i++) { + if (core_info->pid[i] == match_pid_mid->pid) + break; + } + + if (i == core_info->num_pid) + match_pid_mid->pid_match_found = false; + else + match_pid_mid->pid_match_found = true; + + if (match_pid_mid->pid_match_found) { + if (match_pid_mid->fault_mid == core_info->rd_mid) { + match_pid_mid->match_res = + CAM_JPEG_ENC_INPUT_IMAGE; + } else if (match_pid_mid->fault_mid == + core_info->wr_mid) { + match_pid_mid->match_res = + CAM_JPEG_ENC_OUTPUT_IMAGE; + } else + match_pid_mid->pid_match_found = false; + } + + break; default: rc = -EINVAL; break; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h index db505bf5bab7..8dfc443ccd70 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_ENC_CORE_H @@ -66,6 +66,10 @@ struct cam_jpeg_enc_device_core_info { struct cam_jpeg_set_irq_cb irq_cb; int32_t ref_count; struct mutex core_mutex; + uint32_t num_pid; + uint32_t pid[CAM_JPEG_HW_MAX_NUM_PID]; + uint32_t rd_mid; + uint32_t wr_mid; }; int cam_jpeg_enc_init_hw(void *device_priv, diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index e9c9ebd6e193..5b6c307778a8 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -66,8 +66,10 @@ static int cam_jpeg_enc_component_bind(struct device *dev, const struct of_device_id *match_dev = NULL; struct cam_jpeg_enc_device_core_info *core_info = NULL; struct cam_jpeg_enc_device_hw_info *hw_info = NULL; - int rc; struct platform_device *pdev = to_platform_device(dev); + struct cam_jpeg_enc_soc_private *soc_private; + int i; + int rc; jpeg_enc_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); if (!jpeg_enc_dev_intf) @@ -136,6 +138,16 @@ static int cam_jpeg_enc_component_bind(struct device *dev, init_completion(&jpeg_enc_dev->hw_complete); CAM_DBG(CAM_JPEG, "JPEG-Encoder component bound successfully"); + soc_private = (struct cam_jpeg_enc_soc_private *) + jpeg_enc_dev->soc_info.soc_private; + + core_info->num_pid = soc_private->num_pid; + for (i = 0; i < soc_private->num_pid; i++) + core_info->pid[i] = soc_private->pid[i]; + + core_info->rd_mid = soc_private->rd_mid; + core_info->wr_mid = soc_private->wr_mid; + return rc; error_reg_cpas: diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c index 4a5d9e0a9b60..79428a6c4ca4 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. */ #include @@ -16,8 +16,19 @@ int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t jpeg_enc_irq_handler, void *irq_data) { + struct cam_jpeg_enc_soc_private *soc_private; + struct platform_device *pdev = NULL; + int num_pid = 0, i = 0; int rc; + soc_private = kzalloc(sizeof(struct cam_jpeg_enc_soc_private), + GFP_KERNEL); + if (!soc_private) { + CAM_DBG(CAM_ISP, "Error! soc_private Alloc Failed"); + return -ENOMEM; + } + soc_info->soc_private = soc_private; + rc = cam_soc_util_get_dt_properties(soc_info); if (rc) return rc; @@ -28,6 +39,28 @@ int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info, if (rc) CAM_ERR(CAM_JPEG, "init soc failed %d", rc); + soc_private->num_pid = 0; + soc_private->rd_mid = UINT_MAX; + soc_private->wr_mid = UINT_MAX; + + pdev = soc_info->pdev; + num_pid = of_property_count_u32_elems(pdev->dev.of_node, "cam_hw_pid"); + CAM_DBG(CAM_JPEG, "jpeg enc:%d pid count %d", soc_info->index, num_pid); + + if (num_pid <= 0 || num_pid > CAM_JPEG_HW_MAX_NUM_PID) + goto end; + + soc_private->num_pid = num_pid; + for (i = 0; i < num_pid; i++) + of_property_read_u32_index(pdev->dev.of_node, "cam_hw_pid", i, + &soc_private->pid[i]); + + of_property_read_u32(pdev->dev.of_node, + "cam_hw_rd_mid", &soc_private->rd_mid); + + of_property_read_u32(pdev->dev.of_node, + "cam_hw_wr_mid", &soc_private->wr_mid); +end: return rc; } diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h index e0fb0103de75..6e7938c87b1b 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h @@ -1,12 +1,30 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved. */ #ifndef _CAM_JPEG_ENC_SOC_H_ #define _CAM_JPEG_ENC_SOC_H_ #include "cam_soc_util.h" +#include "cam_jpeg_hw_intf.h" + +/* + * struct cam_jpeg_enc_soc_private: + * + * @Brief: Private SOC data specific to JPEG ENC Driver + * + * @num_pid JPEG number of pids + * @pid: JPEG enc pid value list + * @rd_mid: JPEG enc inport read mid value + * @wr_mid: JPEG enc outport write mid value + */ +struct cam_jpeg_enc_soc_private { + uint32_t num_pid; + uint32_t pid[CAM_JPEG_HW_MAX_NUM_PID]; + uint32_t rd_mid; + uint32_t wr_mid; +}; int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info, irq_handler_t jpeg_enc_irq_handler, void *irq_data); From 87fff904c1b404b8184c72eaa2a3db8a4369b79b Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Tue, 5 Jan 2021 17:26:47 +0530 Subject: [PATCH 683/790] msm: camera: cdm: check reset status for error If there are any reset errors for the CDM, CDM should send error to UMD upon reset failure. Updated the error status with relevant error code. CRs-Fixed: 2882732 Change-Id: I12e746f71b1a294aa4e7ef540f39aec91fb44648 Signed-off-by: Tejas Prajapati --- drivers/cam_cdm/cam_cdm_hw_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index f068f9f51c59..61086ae5d13c 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1149,7 +1149,7 @@ static void cam_hw_cdm_reset_cleanup( test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) flush_hw = true; - if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status)) + if (test_bit(CAM_CDM_RESET_ERR_STATUS, &core->cdm_status)) reset_err = true; for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { From 4b76edff35ad91da202c8db57946b3e1c7b08745 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 7 Jan 2021 15:36:46 +0530 Subject: [PATCH 684/790] msm: camera: icp: allow icp debug clock for debug purpose Max support clock frequency varies from target to target. Do not restrict the debug icp clock with max supported clock and allow it to set with any value. CRs-Fixed: 2878329 Change-Id: Ia157d38c4aa4b1183650bf6ff47f3181fb8012cd Signed-off-by: Alok Chauhan --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index e556ca6f1857..d6a1ecee86f9 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -1062,8 +1062,7 @@ static bool cam_icp_update_clk_free(struct cam_icp_hw_mgr *hw_mgr, static bool cam_icp_debug_clk_update(struct cam_icp_clk_info *hw_mgr_clk_info) { - if (icp_hw_mgr.icp_debug_clk < ICP_CLK_TURBO_HZ && - icp_hw_mgr.icp_debug_clk && + if (icp_hw_mgr.icp_debug_clk && icp_hw_mgr.icp_debug_clk != hw_mgr_clk_info->curr_clk) { hw_mgr_clk_info->base_clk = icp_hw_mgr.icp_debug_clk; hw_mgr_clk_info->curr_clk = icp_hw_mgr.icp_debug_clk; From 48b8d7499529b9d5542cfe8dfc50e01e4f57a423 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 10 Feb 2021 14:33:02 +0530 Subject: [PATCH 685/790] msm: camera: isp: Add MID information for IFE Add MID information for IFE and IFE lite. CRs-Fixed: 2876970 Change-Id: I2de1b87decacbef7e06bb38c419d13cf78a6fe59 Signed-off-by: Tejas Prajapati --- .../isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h | 28 +++++++++++++++++++ .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h | 6 +++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h index bba9302a4f04..8dbcfc5da319 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h @@ -1021,115 +1021,143 @@ static struct cam_vfe_bus_ver2_hw_info vfe165_160_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, .max_width = -1, .max_height = -1, + .mid[0] = 4, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, + .mid[0] = 5, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, + .mid[0] = 6, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL, .max_width = 4096, .max_height = 4096, + .mid[0] = 32, + .mid[1] = 33, + .mid[2] = 34, + .mid[3] = 35, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4, .max_width = 1920, .max_height = 1080, + .mid[0] = 36, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16, .max_width = 1920, .max_height = 1080, + .mid[0] = 37, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP, .max_width = -1, .max_height = -1, + .mid[0] = 40, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FD, .max_width = 1920, .max_height = 1080, + .mid[0] = 38, + .mid[1] = 39, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_PDAF, .max_width = -1, .max_height = -1, + .mid[0] = 41, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE, .max_width = -1, .max_height = -1, + .mid[0] = 42, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST, .max_width = 1920, .max_height = 1080, + .mid[0] = 43, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG, .max_width = -1, .max_height = -1, + .mid[0] = 44, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF, .max_width = -1, .max_height = -1, + .mid[0] = 45, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG, .max_width = -1, .max_height = -1, + .mid[0] = 46, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST, .max_width = -1, .max_height = -1, + .mid[0] = 47, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS, .max_width = -1, .max_height = -1, + .mid[0] = 48, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS, .max_width = -1, .max_height = -1, + .mid[0] = 49, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST, .max_width = -1, .max_height = -1, + .mid[0] = 50, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, .max_width = 4096, .max_height = 4096, + .mid[0] = 51, + .mid[1] = 52, + .mid[2] = 53, + .mid[3] = 54, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP, .max_width = 1920, .max_height = 1080, + .mid[0] = 55, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP, .max_width = 1920, .max_height = 1080, + .mid[0] = 56, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_2PD, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h index e1d7a80f04a3..3aab089d58fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite16x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE16X_H_ @@ -315,21 +315,25 @@ static struct cam_vfe_bus_ver2_hw_info vfe16x_bus_hw_info = { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, .max_width = -1, .max_height = -1, + .mid[0] = 4, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, .max_width = -1, .max_height = -1, + .mid[0] = 5, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, .max_width = -1, .max_height = -1, + .mid[0] = 6, }, { .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI3, .max_width = -1, .max_height = -1, + .mid[0] = 7, }, }, .top_irq_shift = 9, From a379fd5e5d611d11122d305a9abd250655b64747 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 23 Feb 2021 15:27:17 +0530 Subject: [PATCH 686/790] msm: camera: isp: Change warn logs to rate limited In apply failure due to congestion and if not recovered, warn logs causing excessive logging issues. Change the warn logs to rate limit in apply failure due to congestion. CRs-Fixed: 2884313 Change-Id: Id46a0cbe6a248a9186a6267577374f4fbadcf64f Signed-off-by: Ayush Kumar --- drivers/cam_isp/cam_isp_context.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index dd91ae6971ce..2f6e9b7a97c4 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -772,11 +772,11 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( return; } - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Prev Req[%lld] : num_out=%d, num_acked=%d, bubble : report=%d, detected=%d", request_id, req_isp->num_fence_map_out, req_isp->num_acked, req_isp->bubble_report, req_isp->bubble_detected); - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Resource Handles that fail to generate buf_done in prev frame"); for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) { @@ -800,7 +800,7 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( request_id, req_isp->fence_map_out[i].sync_id); } - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]", handle_type, req_isp->fence_map_out[i].resource_handle, From dc8a8bf6234850401a26566dfe93ffaf459ba700 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 24 Feb 2021 22:10:13 -0800 Subject: [PATCH 687/790] msm: camera: isp: Update UAPI to remove tpg pattern ID Update UAPI on lahaina kernel to remove tpg pattern ID. CRs-Fixed: 2886651 Change-Id: I2d2f451ce80f965a656952791e55467f4ffd2f6e Signed-off-by: Karthik Anantha Ram --- include/uapi/camera/media/cam_isp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index 848bab7f22b1..b291ccf637b8 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_ISP_H__ @@ -365,8 +365,8 @@ struct cam_isp_in_port_info { * CAM_ISP_SFE_INLINE_PIX) * This will acquire SFE inline IPP and IFE IPP * PPP is an exception CSID PPP -> IFE PPP - * @vc_dt_pattern_id: TPG pattern - SparsePD, sHDR etc. * @feature_flag: See the macros defined under feature flag above + * @ife_res_1: payload for future use * @ife_res_2: payload for future use * @data: payload that contains the output resources * @@ -401,8 +401,8 @@ struct cam_isp_in_port_info_v2 { __u32 horizontal_bin; __u32 qcfa_bin; __u32 sfe_in_path_type; - __u32 vc_dt_pattern_id; __u32 feature_flag; + __u32 ife_res_1; __u32 ife_res_2; struct cam_isp_out_port_info_v2 data[1]; }; From 2ea3cac9d4fb4c393775260b4e4ea064ed966756 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 26 Feb 2021 12:33:25 +0530 Subject: [PATCH 688/790] msm: camera: isp: Change state of all CID resource to RESERVE on deinit This change is to update state of all acquired CID resources state to Reserve on disable CSI2. It will allow, proper release of all CID resources even in case multiple CID for single CSID. CRs-Fixed: 2883120 Change-Id: I0630c08a269bfebc6867dd039e752693ffe97ba9 Signed-off-by: Tejas Prajapati --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 22 ++++++++++++++----- .../isp_hw/ife_csid_hw/cam_ife_csid_core.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 22f2c0ca37f5..82f9679bd7a0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1855,8 +1855,9 @@ static int cam_ife_csid_enable_csi2( csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; - CAM_DBG(CAM_ISP, "CSID:%d count:%d config csi2 rx", - csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt); + CAM_DBG(CAM_ISP, "CSID:%d count:%d config csi2 rx res_id: %d", + csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt, + res->res_id); /* overflow check before increment */ if (csid_hw->csi2_cfg_cnt == UINT_MAX) { @@ -1866,7 +1867,7 @@ static int cam_ife_csid_enable_csi2( } cid_data = (struct cam_ife_csid_cid_data *)res->res_priv; - + cid_data->init_cnt++; res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; csid_hw->csi2_cfg_cnt++; if (csid_hw->csi2_cfg_cnt > 1) @@ -1913,6 +1914,7 @@ static int cam_ife_csid_disable_csi2( { const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_ife_csid_cid_data *cid_data; if (res->res_id >= CAM_IFE_CSID_CID_MAX) { CAM_ERR(CAM_ISP, "CSID:%d Invalid res id :%d", @@ -1922,12 +1924,22 @@ static int cam_ife_csid_disable_csi2( csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; - CAM_DBG(CAM_ISP, "CSID:%d cnt : %d Disable csi2 rx", - csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt); + cid_data = (struct cam_ife_csid_cid_data *)res->res_priv; + CAM_DBG(CAM_ISP, "CSID:%d cnt : %d Disable csi2 rx res->res_id: %d", + csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt, + res->res_id); + + if (cid_data->init_cnt) + cid_data->init_cnt--; + if (!cid_data->init_cnt) + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; if (csid_hw->csi2_cfg_cnt) csid_hw->csi2_cfg_cnt--; + CAM_DBG(CAM_ISP, "res_id %d res_state=%d", + res->res_id, res->res_state); + if (csid_hw->csi2_cfg_cnt) return 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index b2096b454395..f9806a1ce11c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -487,6 +487,7 @@ struct cam_ife_csid_tpg_cfg { * @cnt: Cid resource reference count. * @tpg_set: Tpg used for this cid resource * @is_valid_vc1_dt1: Valid vc1 and dt1 + * @init_cnt cid resource init count * */ struct cam_ife_csid_cid_data { @@ -497,6 +498,7 @@ struct cam_ife_csid_cid_data { uint32_t cnt; uint32_t tpg_set; uint32_t is_valid_vc1_dt1; + uint32_t init_cnt; }; From a165c58fefe8df64c41daa4726d9fb7bea9483a4 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 13 Aug 2020 17:09:07 +0530 Subject: [PATCH 689/790] msm: camera: isp: Add per frame register support Adding per frame register dump for camera version 2 targets. CRs-Fixed: 2778464 Change-Id: I0f45e021959d1b812807f9e7500645f2d8365f54 Signed-off-by: Wyes Karny --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index f220e9ff5927..7c5b27ed08b0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -727,6 +727,12 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_BLANKING_UPDATE: rc = cam_vfe_camif_blanking_update(rsrc_node, cmd_args); break; + case CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA: + camif_priv = (struct cam_vfe_mux_camif_data *) + rsrc_node->res_priv; + *((struct cam_hw_soc_info **)cmd_args) = camif_priv->soc_info; + rc = 0; + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); From f8f1def0f19db166b79141749e122308674121fd Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Fri, 19 Feb 2021 18:08:40 -0800 Subject: [PATCH 690/790] msm: camera: common: Print error irq count in csid irq Make STREAM_UNDERFLOW, ERROR_ECC and ERROR_CPHY_PH_CRC fatal errors. Print IRQ error counts for non fatal errors. CRs-Fixed: 2882318 Change-Id: Id98bfd166071b2fe58fb9c129259c747f746b259 Signed-off-by: Jigar Agrawal --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 22f2c0ca37f5..1d209089b56c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4842,6 +4842,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) uint32_t irq_status[CAM_IFE_CSID_IRQ_REG_MAX] = {0}; uint32_t i, val, val2; bool fatal_err_detected = false; + bool non_fatal_detected = false; uint32_t sof_irq_debug_en = 0; uint32_t event_type = 0; unsigned long flags; @@ -5024,6 +5025,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) "CSID:%d CPHY_EOT_RECEPTION: No EOT on lane/s", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; + non_fatal_detected = true; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) { @@ -5031,13 +5033,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) "CSID:%d CPHY_SOT_RECEPTION: Less SOTs on lane/s", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; + non_fatal_detected = true; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC CPHY: Pkt Hdr CRC mismatch", csid_hw->hw_intf->hw_idx); - csid_hw->error_irq_count++; + fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_CRC) { @@ -5045,13 +5049,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) "CSID:%d ERROR_CRC CPHY: Long pkt payload CRC mismatch", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; + non_fatal_detected = true; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_ECC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC: Dphy pkt hdr errors unrecoverable", csid_hw->hw_intf->hw_idx); - csid_hw->error_irq_count++; + fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) { @@ -5069,13 +5075,14 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CSID_DEBUG_ENABLE_UNMAPPED_VC_DT_IRQ)) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + - csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr); + csi2_reg->csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr); CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNMAPPED_VC_DT: VC:%d DT:%d WC:%d not mapped to any csid paths", csid_hw->hw_intf->hw_idx, (val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF)); csid_hw->error_irq_count++; + non_fatal_detected = true; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) { @@ -5085,7 +5092,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_STREAM_UNDERFLOW: Fewer bytes rcvd than WC:%d in pkt hdr", csid_hw->hw_intf->hw_idx, (val & 0xFFFF)); - csid_hw->error_irq_count++; + fatal_err_detected = true; + goto handle_fatal_error; } if (irq_status[CAM_IFE_CSID_IRQ_REG_RX] & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) { @@ -5093,7 +5101,13 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) "CSID:%d UNBOUNDED_FRAME: Frame started with EOF or No EOF", csid_hw->hw_intf->hw_idx); csid_hw->error_irq_count++; + non_fatal_detected = true; } + + if (non_fatal_detected) + CAM_INFO(CAM_ISP, "CSID: %u Error IRQ Count:%u", + csid_hw->hw_intf->hw_idx, + csid_hw->error_irq_count++); } handle_fatal_error: From b7e6988ef451bc593f1b6352151ebeca0d5a91a1 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 23 Feb 2021 13:56:09 +0800 Subject: [PATCH 691/790] msm: camera: isp: Check whether flush list is empty We will get invalid req from flush_list if the flush list is empty when we get each req by list API list_for_each_entry_safe. This change checks whether flush list is empty before accessing this list. CRs-Fixed: 2885145 Change-Id: I9b2828b03706a0f7412828905cc0a9e28d15fd76 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index dd91ae6971ce..142466a60190 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -3520,6 +3520,17 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, CAM_ISP_STATE_CHANGE_TRIGGER_FLUSH, req->request_id); } + if (list_empty(&flush_list)) { + /* + * Maybe the req isn't sent to KMD since UMD already skip + * req in CSL layer. + */ + CAM_INFO(CAM_ISP, + "flush list is empty, flush type %d for req %llu", + flush_req->type, flush_req->req_id); + return 0; + } + list_for_each_entry_safe(req, req_temp, &flush_list, list) { req_isp = (struct cam_isp_ctx_req *) req->req_priv; for (i = 0; i < req_isp->num_fence_map_out; i++) { @@ -3545,12 +3556,6 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx, list_add_tail(&req->list, &ctx->free_req_list); } - if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && - !cancel_req_id_found) - CAM_DBG(CAM_ISP, - "Flush request id:%lld is not found in the list", - flush_req->req_id); - return 0; } From ffa96f1fc7aa8e45a429fdd650b63734c0fed861 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 25 Feb 2021 18:08:02 +0530 Subject: [PATCH 692/790] msm: camera: isp: Fix for UBWC comp en HW bit Add UBWC compression enable bit in HW file for yupik. CRs-Fixed: 2889723 Change-Id: I7cc3994099c51be3305269721f091ee3461da6d9 Signed-off-by: Wyes Karny --- .../cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h index bba9302a4f04..ec3a080ee811 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe165_160.h @@ -340,6 +340,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00002544, .mode_cfg_1 = 0x000025A4, .bw_limit = 0x000025A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -353,6 +354,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00002644, .mode_cfg_1 = 0x000026A4, .bw_limit = 0x000026A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -366,6 +368,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00003644, .mode_cfg_1 = 0x000036A4, .bw_limit = 0x000036A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client @@ -379,6 +382,7 @@ static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client .mode_cfg_0 = 0x00003744, .mode_cfg_1 = 0x000037A4, .bw_limit = 0x000037A0, + .ubwc_comp_en_bit = BIT(1), }; static struct cam_vfe_bus_rd_ver1_hw_info vfe165_160_bus_rd_hw_info = { From ee418bbd88d3c7be5b454f19da2b97ff28c9fd86 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 19 Jan 2021 17:03:57 +0800 Subject: [PATCH 693/790] msm: camera: reqmgr: Reset the trigger cnt when trigger cnt mismatch In sHDR case, the trigger cnt may be different when one of the IFE meet bubble or irq delay issue, then reset the trigger cnt when we find the trigger cnt is different. CRs-Fixed: 2857614 Change-Id: Ie02fd7204bebd16d32d7a277ac1f2e45f8357dd9 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 5a74aff10652..5439c344e069 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -3153,8 +3153,12 @@ static int __cam_req_mgr_check_for_dual_trigger( (link->trigger_cnt[1] && (link->trigger_cnt[1] - link->trigger_cnt[0] > 1))) { - CAM_ERR(CAM_CRM, + CAM_WARN(CAM_CRM, "One of the devices could not generate trigger"); + + link->trigger_cnt[0] = 0; + link->trigger_cnt[1] = 0; + CAM_DBG(CAM_CRM, "Reset the trigger cnt"); return rc; } From 5fcdbf95f3cc037e6a0f18043db95642dac2e13f Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 29 Dec 2020 10:53:23 +0800 Subject: [PATCH 694/790] msm: camera: reqmgr: Mask re-apply for SHDR usecase SHDR case has two ISP instances, if one of them apply req failed sometimes, but the other one is good and the buf done has been handled successfully, then we don't need to apply the req again for the successful ISP. CRs-Fixed: 2842495 Change-Id: I3dfbb455244daa0d155858dd59f4a661fd3b87cd Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 22 +++++++++++----------- drivers/cam_req_mgr/cam_req_mgr_core.c | 13 +++++++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 2f6e9b7a97c4..38f5489d9aa4 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3069,6 +3069,17 @@ static int __cam_isp_ctx_apply_req_in_activated_state( struct cam_isp_context *ctx_isp = NULL; struct cam_hw_config_args cfg = {0}; + ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + + if (apply->re_apply) + if (apply->request_id <= ctx_isp->last_applied_req_id) { + CAM_INFO_RATE_LIMIT(CAM_ISP, + "ctx_id:%d Trying to reapply the same request %llu again", + ctx->ctx_id, + apply->request_id); + return 0; + } + if (list_empty(&ctx->pending_req_list)) { CAM_ERR_RATE_LIMIT(CAM_ISP, "ctx_id:%d No available request for Apply id %lld", @@ -3084,8 +3095,6 @@ static int __cam_isp_ctx_apply_req_in_activated_state( * The maximum number of request allowed to be outstanding is 2. * */ - ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - if (atomic_read(&ctx_isp->process_bubble)) { CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx_id:%d Processing bubble cannot apply Request Id %llu", @@ -3095,15 +3104,6 @@ static int __cam_isp_ctx_apply_req_in_activated_state( goto end; } - if (apply->re_apply) - if (apply->request_id <= ctx_isp->last_applied_req_id) { - CAM_INFO_RATE_LIMIT(CAM_ISP, - "ctx_id:%d Trying to reapply the same request %llu again", - ctx->ctx_id, - apply->request_id); - return 0; - } - spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 5439c344e069..d4516ad63884 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -929,6 +929,19 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.report_if_bubble = in_q->slot[idx].recover; + /* + * If it is dual trigger usecase, need to tell + * devices that the req is re-applied, then the + * devices need to skip applying if the req has + * been handled. + * e.x. ISP device + */ + if (link->retry_cnt > 0) { + if (!apply_req.report_if_bubble && + link->dual_trigger) + apply_req.re_apply = true; + } + if ((slot->ops.dev_hdl == dev->dev_hdl) && (slot->ops.is_applied)) { slot->ops.is_applied = false; From 43ecbe5c9b8ec60869e7185526b60ca5997d4800 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Mon, 14 Dec 2020 19:14:12 +0530 Subject: [PATCH 695/790] msm: camera: csiphy: Add support for CSIPHY fuse Add support for CSIPHY fuse using software fuse info from CPAS. CRs-Fixed: 2876091 Change-Id: I7010a321e61561dff269c954dc8f83ca0b08956d Signed-off-by: Anil Kumar Kanakanti --- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 95a2ce931c0e..fbe53591fc6e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -8,6 +8,7 @@ #include "cam_csiphy_soc.h" #include "cam_csiphy_core.h" #include +#include #include "camera_main.h" static struct dentry *root_dentry; @@ -209,6 +210,15 @@ static int cam_csiphy_component_bind(struct device *dev, CAM_ERR(CAM_CSIPHY, "DT parsing failed: %d", rc); goto csiphy_no_resource; } + /* validate PHY FUSE only for CSIPHY4 */ + if ((new_csiphy_dev->soc_info.index == 4) && + !cam_cpas_is_feature_supported( + CAM_CPAS_CSIPHY_FUSE, + (1 << new_csiphy_dev->soc_info.index), NULL)) { + CAM_ERR(CAM_CSIPHY, "PHY%d is not supported: %d", + new_csiphy_dev->soc_info.index); + goto csiphy_no_resource; + } new_csiphy_dev->v4l2_dev_str.internal_ops = &csiphy_subdev_intern_ops; From b26fbc393e7d70be75d0e21b30bdd070273297f9 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Wed, 3 Mar 2021 21:22:26 +0530 Subject: [PATCH 696/790] msm: camera: isp: Fix for wrong CPAS version selection in WM start Add fix for wrong CPAS version selection in WM start. CRs-Fixed: 2889723 Change-Id: Ic11f4ced601f3bb5f0f557714a1d2bd1f2143b78 Signed-off-by: Wyes Karny --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index be9a5352504a..53436df08dfa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1273,7 +1273,8 @@ static int cam_vfe_bus_start_wm( return rc; } if ((camera_hw_version > CAM_CPAS_TITAN_NONE) && - (camera_hw_version < CAM_CPAS_TITAN_175_V100)) { + (camera_hw_version < CAM_CPAS_TITAN_175_V100) && + (camera_hw_version != CAM_CPAS_TITAN_165_V100)) { struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_regs; From 018d8dae943321b3ce7138090855c94831124846 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Fri, 5 Feb 2021 15:00:12 +0800 Subject: [PATCH 697/790] msm: camera: core: Allocate memory for flush req array dynamically Allocate memory for flush req array dynamically based on the list count, in case the req count bigger than the size of req list. CRs-Fixed: 2835525 Change-Id: I7e48fb9dc7815cb991c84195e761a3c3f1c26b48 Signed-off-by: Depeng Shao --- drivers/cam_core/cam_context_utils.c | 106 ++++++++++++++++++++++++--- drivers/cam_core/cam_hw_mgr_intf.h | 6 +- 2 files changed, 97 insertions(+), 15 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 0abd3ac3ebff..0e4ed8843728 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -602,7 +602,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) struct cam_hw_flush_args flush_args; struct list_head temp_list; struct cam_ctx_request *req; - uint32_t i; + uint32_t i, j; int rc = 0; bool free_req; @@ -618,15 +618,31 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) INIT_LIST_HEAD(&temp_list); spin_lock(&ctx->lock); list_splice_init(&ctx->pending_req_list, &temp_list); + flush_args.num_req_pending = 0; + list_for_each_entry(req, &temp_list, list) { + flush_args.num_req_pending++; + } spin_unlock(&ctx->lock); + flush_args.flush_req_pending = kcalloc(flush_args.num_req_pending, + sizeof(void *), GFP_KERNEL); + if (!flush_args.flush_req_pending) { + rc = -ENOMEM; + CAM_ERR(CAM_CTXT, + "[%s][%d] : Failed to malloc memory for flush_req_pending", + ctx->dev_name, ctx->ctx_id); + mutex_unlock(&ctx->sync_mutex); + goto err; + } + if (cam_debug_ctx_req_list & ctx->dev_id) CAM_INFO(CAM_CTXT, "[%s][%d] : Moving all pending requests from pending_list to temp_list", ctx->dev_name, ctx->ctx_id); - flush_args.num_req_pending = 0; flush_args.last_flush_req = ctx->last_flush_req; + + j = 0; while (true) { spin_lock(&ctx->lock); if (list_empty(&temp_list)) { @@ -641,7 +657,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) spin_unlock(&ctx->lock); req->flushed = 1; - flush_args.flush_req_pending[flush_args.num_req_pending++] = + flush_args.flush_req_pending[j++] = req->req_priv; free_req = false; @@ -692,11 +708,31 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } mutex_unlock(&ctx->sync_mutex); + kfree(flush_args.flush_req_pending); + flush_args.flush_req_pending = NULL; + if (ctx->hw_mgr_intf->hw_flush) { - flush_args.num_req_active = 0; spin_lock(&ctx->lock); + flush_args.num_req_active = 0; list_for_each_entry(req, &ctx->active_req_list, list) { - flush_args.flush_req_active[flush_args.num_req_active++] + flush_args.num_req_active++; + } + spin_unlock(&ctx->lock); + + flush_args.flush_req_active = kcalloc(flush_args.num_req_active, + sizeof(void *), GFP_KERNEL); + if (!flush_args.flush_req_active) { + rc = -ENOMEM; + CAM_ERR(CAM_CTXT, + "[%s][%d] : Failed to malloc memory for flush_req_active", + ctx->dev_name, ctx->ctx_id); + goto err; + } + + spin_lock(&ctx->lock); + j = 0; + list_for_each_entry(req, &ctx->active_req_list, list) { + flush_args.flush_req_active[j++] = req->req_priv; } spin_unlock(&ctx->lock); @@ -709,6 +745,9 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } } + kfree(flush_args.flush_req_active); + flush_args.flush_req_active = NULL; + INIT_LIST_HEAD(&temp_list); spin_lock(&ctx->lock); list_splice_init(&ctx->active_req_list, &temp_list); @@ -762,7 +801,8 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) CAM_DBG(CAM_CTXT, "[%s] X: NRT flush ctx", ctx->dev_name); - return 0; +err: + return rc; } int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, @@ -782,6 +822,25 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, flush_args.num_req_active = 0; mutex_lock(&ctx->sync_mutex); spin_lock(&ctx->lock); + list_for_each_entry(req, &ctx->pending_req_list, list) { + if (req->request_id != cmd->req_id) + continue; + flush_args.num_req_pending++; + } + spin_unlock(&ctx->lock); + + flush_args.flush_req_pending = kcalloc(flush_args.num_req_pending, + sizeof(void *), GFP_KERNEL); + if (!flush_args.flush_req_pending) { + rc = -ENOMEM; + CAM_ERR(CAM_CTXT, + "[%s][%d] : Failed to malloc memory for flush_req_pending", + ctx->dev_name, ctx->ctx_id); + goto err; + } + + spin_lock(&ctx->lock); + i = 0; list_for_each_entry(req, &ctx->pending_req_list, list) { if (req->request_id != cmd->req_id) continue; @@ -794,24 +853,41 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, list_del_init(&req->list); req->flushed = 1; - flush_args.flush_req_pending[flush_args.num_req_pending++] = + flush_args.flush_req_pending[i++] = req->req_priv; break; } spin_unlock(&ctx->lock); - mutex_unlock(&ctx->sync_mutex); if (ctx->hw_mgr_intf->hw_flush) { if (!flush_args.num_req_pending) { spin_lock(&ctx->lock); + list_for_each_entry(req, &ctx->active_req_list, list) { + if (req->request_id != cmd->req_id) + continue; + flush_args.num_req_active++; + } + spin_unlock(&ctx->lock); + + flush_args.flush_req_active = kcalloc(flush_args.num_req_active, + sizeof(void *), GFP_KERNEL); + if (!flush_args.flush_req_pending) { + rc = -ENOMEM; + CAM_ERR(CAM_CTXT, + "[%s][%d] : Failed to malloc memory for flush_req_pending", + ctx->dev_name, ctx->ctx_id); + goto err; + } + + spin_lock(&ctx->lock); + i = 0; list_for_each_entry(req, &ctx->active_req_list, list) { if (req->request_id != cmd->req_id) continue; list_del_init(&req->list); - flush_args.flush_req_active[ - flush_args.num_req_active++] = + flush_args.flush_req_active[i++] = req->req_priv; break; } @@ -823,6 +899,10 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, flush_args.flush_type = CAM_FLUSH_TYPE_REQ; ctx->hw_mgr_intf->hw_flush( ctx->hw_mgr_intf->hw_mgr_priv, &flush_args); + kfree(flush_args.flush_req_pending); + flush_args.flush_req_pending = NULL; + kfree(flush_args.flush_req_active); + flush_args.flush_req_active = NULL; } } @@ -878,7 +958,9 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, } CAM_DBG(CAM_CTXT, "[%s] X: NRT flush req", ctx->dev_name); - return 0; +err: + mutex_unlock(&ctx->sync_mutex); + return rc; } int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 359f54850ce8..64149fb7c662 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HW_MGR_INTF_H_ @@ -289,9 +289,9 @@ struct cam_hw_config_args { struct cam_hw_flush_args { void *ctxt_to_hw_map; uint32_t num_req_pending; - void *flush_req_pending[20]; + void **flush_req_pending; uint32_t num_req_active; - void *flush_req_active[20]; + void **flush_req_active; enum flush_type_t flush_type; uint32_t last_flush_req; }; From b1f064f8058e453b1bf96cd03a685fb712d21d05 Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Sat, 6 Feb 2021 20:30:51 +0530 Subject: [PATCH 698/790] msm: camera: cpas: workaround fix for Shima-CAMNOC RDI latency buffer This is a workaround suggested by SPT team to overcome line corruption on RDI stream. This is specific to SHIMA. Change-Id: Id90ee86fafe1bc898dbee028944ac8d8a4b2afb9 Signed-off-by: Alok Pandey --- drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 15 ++++++++------- .../cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index 49978a0f5279..2c5bd4048e53 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -270,7 +270,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -402,7 +402,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -468,7 +468,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -595,14 +595,14 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ - .value = 0x13131313, + .value = 0x12121212, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ - .value = 0x13131313, + .value = 0x12121212, }, }, { @@ -662,19 +662,20 @@ static struct cam_camnoc_specific .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ .value = 0x2, }, + // TITAN_A_CAMNOC_cam_noc_amm_nrt_niu_0_qosgen_Shaping_Low | 0xAC44320 .qosgen_shaping_low = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ - .value = 0x24242424, + .value = 0x23232323, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ - .value = 0x24242424, + .value = 0x23232323, }, }, { diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index e556ca6f1857..f628ba453d6c 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1448,6 +1448,7 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, struct cam_hw_intf *icp_dev_intf = NULL; struct cam_hw_intf *dev_intf = NULL; struct cam_icp_clk_update_cmd clk_upd_cmd; + uint32_t camera_hw_version; ipe0_dev_intf = hw_mgr->ipe0_dev_intf; ipe1_dev_intf = hw_mgr->ipe1_dev_intf; @@ -1470,8 +1471,17 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, id = CAM_ICP_IPE_CMD_UPDATE_CLK; } - CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d", curr_clk_rate, - ctx_data->icp_dev_acquire_info->dev_type); + cam_cpas_get_cpas_hw_version(&camera_hw_version); + if ((camera_hw_version == 0x570200)&& + (curr_clk_rate > ctx_data->clk_info.clk_rate[CAM_MAX_VOTE-1]) && + (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS)) { + + curr_clk_rate = ctx_data->clk_info.clk_rate[CAM_MAX_VOTE-1]; + } + + CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d, ver %x", curr_clk_rate, + ctx_data->icp_dev_acquire_info->dev_type, camera_hw_version); + clk_upd_cmd.curr_clk_rate = curr_clk_rate; clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; clk_upd_cmd.clk_level = -1; From 773c327366a0eeaaec408a936259a12c2f64c9ec Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 23 Feb 2021 15:27:17 +0530 Subject: [PATCH 699/790] msm: camera: isp: Change warn logs to rate limited In apply failure due to congestion and if not recovered, warn logs causing excessive logging issues. Change the warn logs to rate limit in apply failure due to congestion. CRs-Fixed: 2884313 Change-Id: Id46a0cbe6a248a9186a6267577374f4fbadcf64f Signed-off-by: Ayush Kumar --- drivers/cam_isp/cam_isp_context.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index dd91ae6971ce..2f6e9b7a97c4 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -772,11 +772,11 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( return; } - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Prev Req[%lld] : num_out=%d, num_acked=%d, bubble : report=%d, detected=%d", request_id, req_isp->num_fence_map_out, req_isp->num_acked, req_isp->bubble_report, req_isp->bubble_detected); - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Resource Handles that fail to generate buf_done in prev frame"); for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) { @@ -800,7 +800,7 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( request_id, req_isp->fence_map_out[i].sync_id); } - CAM_WARN(CAM_ISP, + CAM_WARN_RATE_LIMIT(CAM_ISP, "Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]", handle_type, req_isp->fence_map_out[i].resource_handle, From eebf64c41bfda9719f95a9e8d7cb0d6d119b97e1 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Thu, 13 Aug 2020 17:09:07 +0530 Subject: [PATCH 700/790] msm: camera: isp: Add per frame register support Adding per frame register dump for camera version 2 targets. CRs-Fixed: 2778464 Change-Id: I0f45e021959d1b812807f9e7500645f2d8365f54 Signed-off-by: Wyes Karny --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index f220e9ff5927..7c5b27ed08b0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -727,6 +727,12 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_BLANKING_UPDATE: rc = cam_vfe_camif_blanking_update(rsrc_node, cmd_args); break; + case CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA: + camif_priv = (struct cam_vfe_mux_camif_data *) + rsrc_node->res_priv; + *((struct cam_hw_soc_info **)cmd_args) = camif_priv->soc_info; + rc = 0; + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); From f86171a1b8cfae6238860ac490459e130b2044b0 Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Wed, 3 Mar 2021 20:37:40 +0530 Subject: [PATCH 701/790] msm: camera: cpas: fix for Shima-CAMNOC RDI latency buffer corruption This is a fix to handle line corruption on RDI stream by giving more priority to IFE traffic. This is specific to SHIMA CAMNOC. - Set Priority for IFE (RT) stream to P6. - OT = 55 for IPE RD. - IPE clk to be capped to SVS. CRs-Fixed: 2887253 Change-Id: Ica574742052f018e94072240a0fd1d08be223727 Signed-off-by: Alok Pandey --- drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 17 +++++++++-------- drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c | 4 ++-- drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c | 12 ++++++------ drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h | 4 ++-- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index 49978a0f5279..a8cb5c88acd7 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V570_200_H_ @@ -270,7 +270,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -402,7 +402,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -468,7 +468,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ - .value = 0x66665433, + .value = 0x66666666, }, .priority_lut_high = { .enable = true, @@ -595,14 +595,14 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ - .value = 0x13131313, + .value = 0x12121212, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ - .value = 0x13131313, + .value = 0x12121212, }, }, { @@ -662,19 +662,20 @@ static struct cam_camnoc_specific .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ .value = 0x2, }, + // TITAN_A_CAMNOC_cam_noc_amm_nrt_niu_0_qosgen_Shaping_Low .qosgen_shaping_low = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ - .value = 0x24242424, + .value = 0x23232323, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ - .value = 0x24242424, + .value = 0x23232323, }, }, { diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 2a53d53a5985..5638f0be97f5 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -430,7 +430,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, } CAM_DBG(CAM_PERF, "clock rate %d", clk_rate); - rc = cam_ipe_update_clk_rate(soc_info, clk_rate); + rc = cam_ipe_update_clk_rate(soc_info, &clk_rate); if (rc) CAM_ERR(CAM_PERF, "Failed to update clk %d", clk_rate); diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c index 92d3390a9a74..656f4e1ce459 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -140,7 +140,7 @@ int cam_ipe_disable_soc_resources(struct cam_hw_soc_info *soc_info, } int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, - uint32_t clk_rate) + uint32_t *clk_rate) { int32_t src_clk_idx; @@ -151,14 +151,14 @@ int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) && (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) && - (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { + (*clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) { CAM_DBG(CAM_PERF, "clk_rate %d greater than max, reset to %d", - clk_rate, + *clk_rate, soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]); - clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; + *clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]; } - return cam_soc_util_set_src_clk_rate(soc_info, clk_rate); + return cam_soc_util_set_src_clk_rate(soc_info, *clk_rate); } int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable) diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h index c7e11506251a..b2b297860b00 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_IPE_SOC_H @@ -21,7 +21,7 @@ int cam_ipe_get_gdsc_control(struct cam_hw_soc_info *soc_info); int cam_ipe_transfer_gdsc_control(struct cam_hw_soc_info *soc_info); int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info, - uint32_t clk_rate); + uint32_t *clk_rate); int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable); void cam_ipe_deinit_soc_resources(struct cam_hw_soc_info *soc_info); #endif /* CAM_IPE_SOC_H */ From d2b3015ac59752da7e9b363177401ed201ec599a Mon Sep 17 00:00:00 2001 From: chengxue Date: Mon, 25 Jan 2021 15:19:13 +0800 Subject: [PATCH 702/790] msm: camera: csiphy: add logic for csiphy shutdown While csiphy is shutdown abnormally, we also need to program off csiphy hw common register, to avoid the residual of active csiphy hw cnt during monkey test. CRs-Fixed: 2861912 Change-Id: I1767c729b205a96e5f298265e65b37150dac03b6 Signed-off-by: chengxue --- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 9a51499ba10f..4781285ea46d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -942,6 +942,15 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) cam_csiphy_reset_phyconfig_param(csiphy_dev, i); } + if (csiphy_dev->ctrl_reg->csiphy_reg + .prgm_cmn_reg_across_csiphy) { + mutex_lock(&active_csiphy_cnt_mutex); + active_csiphy_hw_cnt--; + mutex_unlock(&active_csiphy_cnt_mutex); + + cam_csiphy_prgm_cmn_data(csiphy_dev, true); + } + cam_csiphy_reset(csiphy_dev); cam_soc_util_disable_platform_resource(soc_info, true, true); From 511809e56c131fda596d04df62928c751d3fa4e0 Mon Sep 17 00:00:00 2001 From: Shankar Ravi Date: Thu, 11 Mar 2021 12:28:28 +0530 Subject: [PATCH 703/790] msm: camera: csiphy: Dump CSIPHY Status Reg at SOF freeze PHY status dump analysis need to be done to check issue with transmitter when SOF freeze occurs as recommended by PHY HW team. CRs-Fixed: 2890861 Change-Id: Ibaabe1c7e5968aa384313619e8a21f589f1d880e Signed-off-by: Shankar Ravi --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index eb973d11de34..1ba93e2425fc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4334,6 +4334,13 @@ static int cam_ife_csid_sof_irq_debug( (sof_irq_enable) ? "enabled" : "disabled", csid_hw->hw_intf->hw_idx); + CAM_INFO(CAM_ISP, "Notify CSIPHY: %d", + csid_hw->csi2_rx_cfg.phy_sel); + + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + csid_hw->csi2_rx_cfg.phy_sel); + return 0; } From 3476bc16fdf6927a31edc26fa22a448146a6708a Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 24 Nov 2020 16:44:47 +0800 Subject: [PATCH 704/790] msm: camera: reqmgr: Handle flash properly Apply the flash at EOF and apply the other devices at the EPOCH of next frame, then the flash can cover all the exposure zone of current request. Add the inject delay for SOF and EOF separate, then we can use inject delay for more flexible frame skip control. CRs-Fixed: 2820683 Change-Id: Ic6a58327a0ae44c54190884ba42ea7926ec7c90e Signed-off-by: Depeng Shao --- drivers/cam_cust/cam_custom_context.c | 5 +- drivers/cam_cust/cam_custom_context.h | 5 +- drivers/cam_isp/cam_isp_context.c | 3 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 391 +++++++++++------- drivers/cam_req_mgr/cam_req_mgr_core.h | 45 +- drivers/cam_req_mgr/cam_req_mgr_interface.h | 15 +- .../cam_actuator/cam_actuator_core.c | 5 +- .../cam_flash/cam_flash_core.c | 58 +-- .../cam_sensor/cam_sensor_core.c | 5 +- 9 files changed, 318 insertions(+), 214 deletions(-) diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index de40a58176f7..ca4d1d1e35d5 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -1266,10 +1266,10 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, if ((ctx->state != CAM_CTX_FLUSHED) && (ctx->state >= CAM_CTX_READY) && (ctx->ctx_crm_intf->add_req)) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; - add_req.skip_before_applying = 0; rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_CUSTOM, @@ -1375,7 +1375,6 @@ static int __cam_custom_ctx_link_in_acquired(struct cam_context *ctx, ctx->link_hdl = link->link_hdl; ctx->ctx_crm_intf = link->crm_cb; - ctx_custom->subscribe_event = link->subscribe_event; /* change state only if we had the init config */ if (ctx_custom->init_received) diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index b352d3a374cb..ef7fe1f87434 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only * - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CUSTOM_CONTEXT_H_ @@ -94,8 +94,6 @@ struct cam_custom_dev_ctx_req { * @state: Common context state * @hw_ctx: HW object returned by the acquire device command * @init_received: Indicate whether init config packet is received - * @subscribe_event: The irq event mask that CRM subscribes to, - * custom HW will invoke CRM cb at those event. * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context * @hw_acquired: Flag to indicate if HW is acquired for this context @@ -113,7 +111,6 @@ struct cam_custom_context { uint32_t state; void *hw_ctx; bool init_received; - uint32_t subscribe_event; uint32_t active_req_cnt; int64_t frame_id; bool hw_acquired; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index c9c16340b8f0..86a3ae579c38 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4567,11 +4567,10 @@ static int __cam_isp_ctx_config_dev_in_top_state( } else if ((ctx->state != CAM_CTX_FLUSHED) && (ctx->state >= CAM_CTX_READY) && ctx->ctx_crm_intf->add_req) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; - add_req.skip_before_applying = 0; - add_req.trigger_eof = false; rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_ISP, "Add req failed: req id=%llu", diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index d4516ad63884..feb9d4c69174 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -37,15 +37,15 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->watchdog = NULL; link->state = CAM_CRM_LINK_STATE_AVAILABLE; link->parent = NULL; - link->subscribe_event = 0; - link->trigger_mask = 0; link->sync_link_sof_skip = false; link->open_req_cnt = 0; link->last_flush_id = 0; link->initial_sync_req = -1; link->dual_trigger = false; - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + link->trigger_cnt[0][0] = 0; + link->trigger_cnt[0][1] = 0; + link->trigger_cnt[1][0] = 0; + link->trigger_cnt[1][1] = 0; link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; @@ -161,25 +161,34 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val) /** * __cam_req_mgr_inject_delay() * - * @brief : Check if any pd device is injecting delay - * @tbl : cam_req_mgr_req_tbl - * @curr_idx : slot idx + * @brief : Check if any pd device is injecting delay + * @tbl : cam_req_mgr_req_tbl + * @curr_idx : slot idx + * @trigger : Trigger point * * @return : 0 for success, negative for failure */ static int __cam_req_mgr_inject_delay( - struct cam_req_mgr_req_tbl *tbl, - int32_t curr_idx) + struct cam_req_mgr_req_tbl *tbl, + int32_t curr_idx, uint32_t trigger) { 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--; + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (slot->inject_delay_at_sof > 0)) { + slot->inject_delay_at_sof--; CAM_DBG(CAM_CRM, - "Delay injected by pd %d device", + "Delay injected by pd %d device at SOF", + tbl->pd); + rc = -EAGAIN; + } else if ((trigger == CAM_TRIGGER_POINT_EOF) && + (slot->inject_delay_at_eof > 0)) { + slot->inject_delay_at_eof--; + CAM_DBG(CAM_CRM, + "Delay injected by pd %d device at EOF", tbl->pd); rc = -EAGAIN; } @@ -556,7 +565,6 @@ static void __cam_req_mgr_flush_req_slot( tbl->slot[idx].req_ready_map = 0; tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; tbl->slot[idx].ops.apply_at_eof = false; - tbl->slot[idx].ops.skip_next_frame = false; tbl->slot[idx].ops.dev_hdl = -1; tbl->slot[idx].ops.is_applied = false; tbl = tbl->next; @@ -566,8 +574,10 @@ static void __cam_req_mgr_flush_req_slot( atomic_set(&link->eof_event_cnt, 0); in_q->wr_idx = 0; in_q->rd_idx = 0; - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + link->trigger_cnt[0][0] = 0; + link->trigger_cnt[0][1] = 0; + link->trigger_cnt[1][0] = 0; + link->trigger_cnt[1][1] = 0; } /** @@ -608,8 +618,9 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, tbl->pd, idx, tbl->slot[idx].state); tbl->slot[idx].req_ready_map = 0; tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; + tbl->slot[idx].inject_delay_at_sof = 0; + tbl->slot[idx].inject_delay_at_eof = 0; tbl->slot[idx].ops.apply_at_eof = false; - tbl->slot[idx].ops.skip_next_frame = false; tbl->slot[idx].ops.dev_hdl = -1; tbl->slot[idx].ops.is_applied = false; tbl = tbl->next; @@ -817,16 +828,11 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (slot->ops.dev_hdl < 0) { CAM_DBG(CAM_CRM, - "No special ops detected for this table slot"); + "No special ops detected for slot %d dev %s", + idx, dev->dev_info.name); continue; } - if (slot->ops.apply_at_eof && slot->ops.skip_next_frame) { - CAM_ERR(CAM_CRM, - "Both EOF and SOF trigger is not supported"); - return -EINVAL; - } - if (dev->dev_hdl != slot->ops.dev_hdl) { CAM_DBG(CAM_CRM, "Dev_hdl : %d Not matched:: Expected dev_hdl: %d", @@ -834,6 +840,23 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, continue; } + if (apply_data[pd].skip_idx || + (apply_data[pd].req_id < 0)) { + CAM_DBG(CAM_CRM, + "dev %s skip %d req_id %lld", + dev->dev_info.name, + apply_data[pd].skip_idx, + apply_data[pd].req_id); + apply_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = + link->req.prev_apply_data[pd].req_id; + apply_req.trigger_point = 0; + apply_req.report_if_bubble = 0; + if ((dev->ops) && (dev->ops->notify_frame_skip)) + dev->ops->notify_frame_skip(&apply_req); + continue; + } + /* This one is to prevent EOF request to apply on SOF*/ if ((trigger == CAM_TRIGGER_POINT_SOF) && (slot->ops.apply_at_eof)) { @@ -861,31 +884,24 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, trigger); return rc; } + } else { + CAM_DBG(CAM_REQ, + "link_hdl: %x pd: %d req_id %lld has applied", + link->link_hdl, pd, apply_req.request_id); + break; } CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd: %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); + "SEND: link_hdl %x dev %s pd %d req_id %lld", + link->link_hdl, dev->dev_info.name, + pd, apply_req.request_id); - if (trigger == CAM_TRIGGER_POINT_SOF && - slot->ops.skip_next_frame) { - slot->ops.skip_next_frame = false; - slot->ops.is_applied = true; - CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd: %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); - __cam_req_mgr_notify_frame_skip(link, - trigger); - return -EAGAIN; - } else if ((trigger == CAM_TRIGGER_POINT_EOF) && + if ((trigger == CAM_TRIGGER_POINT_EOF) && (slot->ops.apply_at_eof)) { + slot->ops.is_applied = true; slot->ops.apply_at_eof = false; if (atomic_read(&link->eof_event_cnt) > 0) atomic_dec(&link->eof_event_cnt); - CAM_DBG(CAM_REQ, - "Req_id: %llu eof_event_cnt : %d", - apply_data[pd].req_id, - link->eof_event_cnt); return 0; } } @@ -967,8 +983,9 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.trigger_point = trigger; CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); + "SEND: link_hdl %x dev %s pd %d req_id %lld", + link->link_hdl, dev->dev_info.name, + pd, apply_req.request_id); if (dev->ops && dev->ops->apply_req) { rc = dev->ops->apply_req(&apply_req); if (rc < 0) { @@ -1166,7 +1183,6 @@ static int __cam_req_mgr_check_sync_for_mslave( "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; } @@ -1184,15 +1200,6 @@ static int __cam_req_mgr_check_sync_for_mslave( } 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 (sync_link->initial_skip) { CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", sync_link->link_hdl); @@ -1256,15 +1263,6 @@ static int __cam_req_mgr_check_sync_for_mslave( 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, @@ -1377,7 +1375,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( if (sync_link->initial_skip) { link->initial_skip = false; - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); CAM_DBG(CAM_CRM, "sync link %x not streamed on", sync_link->link_hdl); @@ -1411,7 +1408,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( * link, then we need to skip this frame, since the * previous frame of sync link is also skipped. */ - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); CAM_DBG(CAM_CRM, "This frame sync with previous sync_link %x frame", sync_link->link_hdl); @@ -1424,7 +1420,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( * we need to skip this SOF event since the sync * link's SOF event is also skipped. */ - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); CAM_DBG(CAM_CRM, "The previous frame of sync link is skipped"); return -EAGAIN; @@ -1436,18 +1431,9 @@ static int __cam_req_mgr_check_sync_req_is_ready( "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; } - 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); - ready = false; - } - sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, req_id); if (sync_slot_idx == -1) { @@ -1567,7 +1553,8 @@ static int __cam_req_mgr_check_sync_req_is_ready( static int __cam_req_mgr_check_multi_sync_link_ready( struct cam_req_mgr_core_link *link, - struct cam_req_mgr_slot *slot) + struct cam_req_mgr_slot *slot, + uint32_t trigger) { int i, rc = 0; @@ -1621,6 +1608,16 @@ static int __cam_req_mgr_check_multi_sync_link_ready( } } + rc = __cam_req_mgr_inject_delay(link->req.l_tbl, + slot->idx, trigger); + if (rc < 0) { + CAM_DBG(CAM_CRM, + "Req: %lld needs to inject delay at %s", + slot->req_id, + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"); + return -EINVAL; + } + /* * At this point all validation is successfully done * and we can proceed to apply the given request. @@ -1633,6 +1630,57 @@ static int __cam_req_mgr_check_multi_sync_link_ready( return 0; } +/** + * __cam_req_mgr_check_for_eof() + * + * @brief : Checks for eof trigger type + * @link : pointer to link whose input queue and req tbl are + * traversed through + * + * @return : eof trigger type + * + */ +enum crm_req_eof_trigger_type __cam_req_mgr_check_for_eof( + struct cam_req_mgr_core_link *link) +{ + int32_t curr_idx; + struct cam_req_mgr_req_queue *in_q; + enum crm_req_eof_trigger_type eof_trigger_type; + struct cam_req_mgr_tbl_slot *slot = NULL; + struct cam_req_mgr_req_tbl *tbl; + + in_q = link->req.in_q; + tbl = link->req.l_tbl; + curr_idx = in_q->rd_idx; + eof_trigger_type = CAM_REQ_EOF_TRIGGER_NONE; + + while (tbl != NULL) { + slot = &tbl->slot[curr_idx]; + + if (slot->ops.is_applied) { + eof_trigger_type = CAM_REQ_EOF_TRIGGER_APPLIED; + break; + } else if (slot->ops.apply_at_eof) { + eof_trigger_type = CAM_REQ_EOF_TRIGGER_NOT_APPLY; + break; + } + + if (tbl->next) + __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, + tbl->num_slots); + + tbl = tbl->next; + } + + CAM_DBG(CAM_REQ, + "Req[%lld] idx %d req_status %d link_hdl %x eof_trigger_type %x", + in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx, + in_q->slot[in_q->rd_idx].status, link->link_hdl, + eof_trigger_type); + + return eof_trigger_type; +} + /** * __cam_req_mgr_process_req() * @@ -1655,6 +1703,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_connected_device *dev = NULL; struct cam_req_mgr_core_link *tmp_link = NULL; uint32_t max_retry = 0; + enum crm_req_eof_trigger_type eof_trigger_type; session = (struct cam_req_mgr_core_session *)link->parent; if (!session) { @@ -1672,10 +1721,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, * - if in no_req state, no new req */ CAM_DBG(CAM_REQ, - "SOF Req[%lld] idx %d req_status %d link_hdl %x wd_timeout %d ms", + "%s Req[%lld] idx %d req_status %d link_hdl %x wd_timeout %d ms trigger:%d", + ((trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"), in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx, in_q->slot[in_q->rd_idx].status, link->link_hdl, - in_q->slot[in_q->rd_idx].additional_timeout); + in_q->slot[in_q->rd_idx].additional_timeout, trigger); slot = &in_q->slot[in_q->rd_idx]; if (slot->status == CRM_SLOT_STATUS_NO_REQ) { @@ -1688,10 +1738,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, (trigger != CAM_TRIGGER_POINT_EOF)) goto end; + eof_trigger_type = __cam_req_mgr_check_for_eof(link); + if ((trigger == CAM_TRIGGER_POINT_EOF) && - (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) { - CAM_DBG(CAM_CRM, "Applying for last SOF fails"); - rc = -EINVAL; + (eof_trigger_type == CAM_REQ_EOF_TRIGGER_NONE)) { + CAM_DBG(CAM_CRM, "Not any request to schedule at EOF"); goto end; } @@ -1710,17 +1761,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->wq_congestion = true; else link->wq_congestion = false; + } - if (link->trigger_mask) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Applying for last EOF fails"); - rc = -EINVAL; - goto end; - } - + if (slot->status != CRM_SLOT_STATUS_REQ_READY) { if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { rc = __cam_req_mgr_check_multi_sync_link_ready( - link, slot); + link, slot, trigger); } else { if (link->in_msync_mode) { CAM_DBG(CAM_CRM, @@ -1737,11 +1783,34 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } - 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); + /* + * Validate that if the req is ready to apply before + * checking the inject delay. + */ + rc = __cam_req_mgr_check_link_is_ready(link, + slot->idx, true); + + if (!rc) { + rc = __cam_req_mgr_inject_delay(link->req.l_tbl, + slot->idx, trigger); + if (rc < 0) + CAM_DBG(CAM_CRM, + "Req: %lld needs to inject delay at %s", + slot->req_id, + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"); + + if (!rc) + rc = __cam_req_mgr_check_link_is_ready(link, + slot->idx, false); + } + } + + if (!rc) { + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (eof_trigger_type == CAM_REQ_EOF_TRIGGER_NOT_APPLY)) { + CAM_DBG(CAM_CRM, "EOF apply first"); + rc = -EAGAIN; + } } if (rc < 0) { @@ -1768,6 +1837,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, __cam_req_mgr_notify_frame_skip(link, trigger); __cam_req_mgr_validate_crm_wd_timer(link); goto end; + } else { + slot->status = CRM_SLOT_STATUS_REQ_READY; + CAM_DBG(CAM_REQ, + "linx_hdl %x Req[%lld] idx %d ready to apply", + link->link_hdl, in_q->slot[in_q->rd_idx].req_id, + in_q->rd_idx); } } @@ -1807,8 +1882,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->retry_cnt) link->retry_cnt = 0; - link->trigger_mask |= trigger; - /* Check for any long exposure settings */ __cam_req_mgr_validate_crm_wd_timer(link); @@ -1825,16 +1898,17 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->sync_link_sof_skip) link->sync_link_sof_skip = false; - if (link->trigger_mask == link->subscribe_event) { + /* + * Below two cases can move slot to APPLIED status, + * 1# there is no eof trigger request + * 2# eof trigger is applied and the devcies which need to + * be applied at SOF are also applied. + */ + if (((eof_trigger_type == CAM_REQ_EOF_TRIGGER_NONE) || + (eof_trigger_type == CAM_REQ_EOF_TRIGGER_APPLIED)) && + (trigger == CAM_TRIGGER_POINT_SOF)) { slot->status = CRM_SLOT_STATUS_REQ_APPLIED; - link->trigger_mask = 0; - if (!(atomic_read(&link->eof_event_cnt)) && - (trigger == CAM_TRIGGER_POINT_EOF)) { - link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF; - CAM_DBG(CAM_CRM, - "Update link subscribe_event: %d", - link->subscribe_event); - } + CAM_DBG(CAM_CRM, "req %d is applied on link %x", slot->req_id, link->link_hdl); @@ -1936,7 +2010,6 @@ static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay) CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots); for (i = 0; i < MAX_REQ_SLOTS; i++) { tbl->slot[i].ops.apply_at_eof = false; - tbl->slot[i].ops.skip_next_frame = false; tbl->slot[i].ops.dev_hdl = -1; tbl->slot[i].ops.is_applied = false; } @@ -2216,7 +2289,6 @@ static int __cam_req_mgr_disconnect_link(struct cam_req_mgr_core_link *link) link_data.link_enable = 0; link_data.link_hdl = link->link_hdl; link_data.crm_cb = NULL; - link_data.subscribe_event = 0; /* Using device ops unlink devices */ for (i = 0; i < link->num_devs; i++) { @@ -2658,24 +2730,31 @@ int cam_req_mgr_process_add_req(void *priv, void *data) slot = &tbl->slot[idx]; slot->ops.is_applied = false; - if ((add_req->skip_before_applying & 0xFF) > slot->inject_delay) { - slot->inject_delay = (add_req->skip_before_applying & 0xFF); - if (add_req->skip_before_applying & SKIP_NEXT_FRAME) { - slot->ops.skip_next_frame = true; - slot->ops.dev_hdl = add_req->dev_hdl; - } - CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %llu", + + if ((add_req->skip_at_sof & 0xFF) > slot->inject_delay_at_sof) { + slot->inject_delay_at_sof = (add_req->skip_at_sof & 0xFF); + CAM_DBG(CAM_CRM, + "Req_id %llu injecting delay %llu frame at SOF by %s", add_req->req_id, - (add_req->skip_before_applying & 0xFF)); + slot->inject_delay_at_sof, + device->dev_info.name); } - /* Used when Precise Flash is enabled */ - if ((add_req->trigger_eof) && (!add_req->skip_before_applying)) { + if ((add_req->skip_at_eof & 0xFF) > slot->inject_delay_at_eof) { + slot->inject_delay_at_eof = (add_req->skip_at_eof & 0xFF); + CAM_DBG(CAM_CRM, + "Req_id %llu injecting delay %llu frame at EOF by %s", + add_req->req_id, + slot->inject_delay_at_eof, + device->dev_info.name); + } + + if (add_req->trigger_eof) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, - "Req_id %llu added for EOF tigger for Device: %s", - add_req->req_id, device->dev_info.name); + "Req_id %llu slot:%d added for EOF tigger for Device: %s", + add_req->req_id, idx, device->dev_info.name); } if (slot->state != CRM_REQ_STATE_PENDING && @@ -2804,7 +2883,7 @@ int cam_req_mgr_process_error(void *priv, void *data) evt_data.dev_hdl = device->dev_hdl; evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_ERR; - evt_data.link_hdl = link->link_hdl; + evt_data.link_hdl = link->link_hdl; evt_data.req_id = err_info->req_id; evt_data.u.error = err_info->error; if (device->ops && @@ -2936,6 +3015,10 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) spin_unlock_bh(&link->link_state_spin_lock); + /* + * Move to next req at SOF only in case + * the rd_idx is updated at EOF. + */ if (in_q->slot[in_q->rd_idx].status == CRM_SLOT_STATUS_REQ_APPLIED) { /* * Do NOT reset req q slot data here, it can not be done @@ -3061,15 +3144,13 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) dev_req->req_id = add_req->req_id; dev_req->link_hdl = add_req->link_hdl; dev_req->dev_hdl = add_req->dev_hdl; - dev_req->skip_before_applying = add_req->skip_before_applying; dev_req->trigger_eof = add_req->trigger_eof; + dev_req->skip_at_sof = add_req->skip_at_sof; + dev_req->skip_at_eof = add_req->skip_at_eof; if (dev_req->trigger_eof) { - link->subscribe_event |= CAM_TRIGGER_POINT_EOF; atomic_inc(&link->eof_event_cnt); - CAM_DBG(CAM_REQ, - "Req_id: %llu, eof_event_cnt: %d, link subscribe event: %d", - dev_req->req_id, link->eof_event_cnt, - link->subscribe_event); + CAM_DBG(CAM_REQ, "Req_id: %llu, eof_event_cnt: %d", + dev_req->req_id, link->eof_event_cnt); } task->process_cb = &cam_req_mgr_process_add_req; @@ -3147,35 +3228,38 @@ end: } static int __cam_req_mgr_check_for_dual_trigger( - struct cam_req_mgr_core_link *link) + struct cam_req_mgr_core_link *link, + uint32_t trigger) { int rc = -EAGAIN; - CAM_DBG(CAM_CRM, "trigger_cnt [%u: %u]", - link->trigger_cnt[0], link->trigger_cnt[1]); + CAM_DBG(CAM_CRM, "%s trigger_cnt [%u: %u]", + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF", + link->trigger_cnt[0][trigger], link->trigger_cnt[1][trigger]); - if (link->trigger_cnt[0] == link->trigger_cnt[1]) { - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + if (link->trigger_cnt[0][trigger] == link->trigger_cnt[1][trigger]) { + link->trigger_cnt[0][trigger] = 0; + link->trigger_cnt[1][trigger] = 0; rc = 0; return rc; } - if ((link->trigger_cnt[0] && - (link->trigger_cnt[0] - link->trigger_cnt[1] > 1)) || - (link->trigger_cnt[1] && - (link->trigger_cnt[1] - link->trigger_cnt[0] > 1))) { + if ((link->trigger_cnt[0][trigger] && + (link->trigger_cnt[0][trigger] - link->trigger_cnt[1][trigger] > 1)) || + (link->trigger_cnt[1][trigger] && + (link->trigger_cnt[1][trigger] - link->trigger_cnt[0][trigger] > 1))) { CAM_WARN(CAM_CRM, "One of the devices could not generate trigger"); - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + link->trigger_cnt[0][trigger] = 0; + link->trigger_cnt[1][trigger] = 0; CAM_DBG(CAM_CRM, "Reset the trigger cnt"); return rc; } - CAM_DBG(CAM_CRM, "Only one device has generated trigger"); + CAM_DBG(CAM_CRM, "Only one device has generated trigger for %s", + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"); return rc; } @@ -3308,13 +3392,14 @@ static int cam_req_mgr_cb_notify_trigger( struct cam_req_mgr_trigger_notify *trigger_data) { int32_t rc = 0, trigger_id = 0; + uint32_t trigger; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_trigger_notify *notify_trigger; struct crm_task_payload *task_data; if (!trigger_data) { - CAM_ERR(CAM_CRM, "sof_data is NULL"); + CAM_ERR(CAM_CRM, "trigger_data is NULL"); rc = -EINVAL; goto end; } @@ -3327,10 +3412,20 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } - trigger_id = trigger_data->trigger_id; + CAM_DBG(CAM_REQ, "link_hdl %x frame_id %lld, trigger %x\n", + trigger_data->link_hdl, + trigger_data->frame_id, + trigger_data->trigger); + trigger_id = trigger_data->trigger_id; + trigger = trigger_data->trigger; + + /* + * Reduce the workq overhead when there is + * not any eof event found. + */ if ((!atomic_read(&link->eof_event_cnt)) && - (trigger_data->trigger == CAM_TRIGGER_POINT_EOF)) { + (trigger == CAM_TRIGGER_POINT_EOF)) { CAM_DBG(CAM_CRM, "Not any request to schedule at EOF"); goto end; } @@ -3344,14 +3439,14 @@ static int cam_req_mgr_cb_notify_trigger( } if ((link->watchdog) && (link->watchdog->pause_timer) && - (trigger_data->trigger == CAM_TRIGGER_POINT_SOF)) + (trigger == CAM_TRIGGER_POINT_SOF)) link->watchdog->pause_timer = false; if (link->dual_trigger) { if ((trigger_id >= 0) && (trigger_id < CAM_REQ_MGR_MAX_TRIGGERS)) { - link->trigger_cnt[trigger_id]++; - rc = __cam_req_mgr_check_for_dual_trigger(link); + link->trigger_cnt[trigger_id][trigger]++; + rc = __cam_req_mgr_check_for_dual_trigger(link, trigger); if (rc) { spin_unlock_bh(&link->link_state_spin_lock); goto end; @@ -3424,7 +3519,6 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, struct cam_req_mgr_connected_device *dev; struct cam_req_mgr_req_tbl *pd_tbl; enum cam_pipeline_delay max_delay; - uint32_t subscribe_event = 0; uint32_t num_trigger_devices = 0; if (link_info->version == VERSION_1) { if (link_info->u.link_info_v1.num_devices > @@ -3512,8 +3606,6 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, } if (dev->dev_info.p_delay > max_delay) max_delay = dev->dev_info.p_delay; - - subscribe_event |= (uint32_t)dev->dev_info.trigger; } if (dev->dev_info.trigger_on) @@ -3528,12 +3620,10 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, goto error; } - link->subscribe_event = subscribe_event; link_data.link_enable = 1; link_data.link_hdl = link->link_hdl; link_data.crm_cb = &cam_req_mgr_ops; link_data.max_delay = max_delay; - link_data.subscribe_event = subscribe_event; if (num_trigger_devices == CAM_REQ_MGR_MAX_TRIGGERS) link->dual_trigger = true; @@ -3968,6 +4058,11 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) goto setup_failed; } + link->trigger_cnt[0][0] = 0; + link->trigger_cnt[0][1] = 0; + link->trigger_cnt[1][0] = 0; + link->trigger_cnt[1][1] = 0; + mutex_unlock(&link->lock); mutex_unlock(&g_crm_core_dev->crm_lock); return rc; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index ffba72cf3c58..6e6415c85fc0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_CORE_H_ #define _CAM_REQ_MGR_CORE_H_ @@ -42,6 +42,16 @@ #define VERSION_2 2 #define CAM_REQ_MGR_MAX_TRIGGERS 2 +/** + * enum crm_req_eof_trigger_type + * @codes: to identify which type of eof trigger for next slot + */ +enum crm_req_eof_trigger_type { + CAM_REQ_EOF_TRIGGER_NONE, + CAM_REQ_EOF_TRIGGER_NOT_APPLY, + CAM_REQ_EOF_TRIGGER_APPLIED, +}; + /** * enum crm_workq_task_type * @codes: to identify which type of task is present @@ -105,6 +115,7 @@ enum crm_req_state { * NO_REQ : empty slot * REQ_ADDED : new entry in slot * REQ_PENDING : waiting for next trigger to apply + * REQ_READY : req is ready * REQ_APPLIED : req is sent to all devices * INVALID : invalid state */ @@ -112,6 +123,7 @@ enum crm_slot_status { CRM_SLOT_STATUS_NO_REQ, CRM_SLOT_STATUS_REQ_ADDED, CRM_SLOT_STATUS_REQ_PENDING, + CRM_SLOT_STATUS_REQ_READY, CRM_SLOT_STATUS_REQ_APPLIED, CRM_SLOT_STATUS_INVALID, }; @@ -186,34 +198,34 @@ struct cam_req_mgr_apply { * struct crm_tbl_slot_special_ops * @dev_hdl : Device handle who requested for special ops * @apply_at_eof : Boolean Identifier for request to be applied at EOF - * @skip_next_frame : Flag to drop the frame after skip_before_apply frame * @is_applied : Flag to identify if request is already applied to device * in previous frame */ struct crm_tbl_slot_special_ops { int32_t dev_hdl; bool apply_at_eof; - bool skip_next_frame; bool is_applied; }; /** * struct cam_req_mgr_tbl_slot - * @idx : slot index - * @req_ready_map : mask tracking which all devices have request ready - * @state : state machine for life cycle of a slot - * @inject_delay : insert extra bubbling for flash type of use cases - * @ops : special operation for the table slot - * e.g. - * skip_next frame: in case of applying one device - * and skip others - * apply_at_eof: device that needs to apply at EOF + * @idx : slot index + * @req_ready_map : mask tracking which all devices have request ready + * @state : state machine for life cycle of a slot + * @inject_delay_at_sof : insert extra bubbling for flash type of use cases + * @inject_delay_at_eof : insert extra bubbling for flash type of use cases + * @ops : special operation for the table slot + * e.g. + * skip_next frame: in case of applying one device + * and skip others + * apply_at_eof: device that needs to apply at EOF */ struct cam_req_mgr_tbl_slot { int32_t idx; uint32_t req_ready_map; enum crm_req_state state; - uint32_t inject_delay; + uint32_t inject_delay_at_sof; + uint32_t inject_delay_at_eof; struct crm_tbl_slot_special_ops ops; }; @@ -342,9 +354,6 @@ struct cam_req_mgr_connected_device { * @parent : pvt data - link's parent is session * @lock : mutex lock to guard link data operations * @link_state_spin_lock : spin lock to protect link state variable - * @subscribe_event : irqs that link subscribes, IFE should send - * notification to CRM at those hw events. - * @trigger_mask : mask on which irq the req is already applied * @sync_link : array of pointer to the sync link for synchronization * @num_sync_links : num of links sync associated with this link * @sync_link_sof_skip : flag determines if a pkt is not available for a given @@ -390,8 +399,6 @@ struct cam_req_mgr_core_link { void *parent; struct mutex lock; spinlock_t link_state_spin_lock; - uint32_t subscribe_event; - uint32_t trigger_mask; struct cam_req_mgr_core_link *sync_link[MAXIMUM_LINKS_PER_SESSION - 1]; int32_t num_sync_links; @@ -408,7 +415,7 @@ struct cam_req_mgr_core_link { uint64_t sof_timestamp; uint64_t prev_sof_timestamp; bool dual_trigger; - uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; + uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS][CAM_TRIGGER_MAX_POINTS]; atomic_t eof_event_cnt; bool skip_init_frame; uint64_t last_sof_trigger_jiffies; diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 231cf397f3d8..b6807ed4a7f0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_INTERFACE_H @@ -23,8 +23,6 @@ struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; struct cam_req_mgr_dump_info; -#define SKIP_NEXT_FRAME 0x100 - /* Request Manager -- camera device driver interface */ /** * @brief: camera kernel drivers to cam req mgr communication @@ -119,9 +117,11 @@ enum cam_pipeline_delay { /** * @CAM_TRIGGER_POINT_SOF : Trigger point for Start Of Frame * @CAM_TRIGGER_POINT_EOF : Trigger point for End Of Frame + * @CAM_TRIGGER_MAX_POINTS : Maximum number of trigger point */ #define CAM_TRIGGER_POINT_SOF (1 << 0) #define CAM_TRIGGER_POINT_EOF (1 << 1) +#define CAM_TRIGGER_MAX_POINTS 2 /** * enum cam_req_status @@ -266,7 +266,9 @@ struct cam_req_mgr_error_notify { * @link_hdl : link identifier * @dev_hdl : device handle which has sent this req id * @req_id : req id which device is ready to process - * @skip_before_applying : before applying req mgr introduce bubble + * @skip_at_sof : before applying req mgr introduce bubble + * by not sending request to devices. ex: IFE and Flash + * @skip_at_eof : before applying req mgr introduce bubble * by not sending request to devices. ex: IFE and Flash * @trigger_eof : to identify that one of the device at this slot needs * to be apply at EOF @@ -275,7 +277,8 @@ struct cam_req_mgr_add_request { int32_t link_hdl; int32_t dev_hdl; uint64_t req_id; - uint32_t skip_before_applying; + uint32_t skip_at_sof; + uint32_t skip_at_eof; bool trigger_eof; }; @@ -316,7 +319,6 @@ struct cam_req_mgr_device_info { * @dev_hdl : device handle for reference * @max_delay : max pipeline delay on this link * @crm_cb : callback funcs to communicate with req mgr - * @subscribe_event : the mask of trigger points this link subscribes * @trigger_id : Unique ID provided to the triggering device */ struct cam_req_mgr_core_dev_link_setup { @@ -325,7 +327,6 @@ struct cam_req_mgr_core_dev_link_setup { int32_t dev_hdl; enum cam_pipeline_delay max_delay; struct cam_req_mgr_crm_cb *crm_cb; - uint32_t subscribe_event; int32_t trigger_id; }; diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index aa761a729c07..9c0d7abd043d 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -374,11 +374,10 @@ static int cam_actuator_update_req_mgr( int rc = 0; struct cam_req_mgr_add_request add_req; + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = a_ctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl; - add_req.skip_before_applying = 0; - add_req.trigger_eof = false; if (a_ctrl->bridge_intf.crm_cb && a_ctrl->bridge_intf.crm_cb->add_req) { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 156fcf0dbafe..8cda6c3831c8 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1263,18 +1263,19 @@ update_req_mgr: CAM_PKT_NOP_OPCODE) || ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = fctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = fctrl->bridge_intf.device_hdl; if ((csl_packet->header.op_code & 0xFFFFF) == - CAM_FLASH_PACKET_OPCODE_SET_OPS) - add_req.skip_before_applying = 1; - else - add_req.skip_before_applying = 0; + CAM_FLASH_PACKET_OPCODE_SET_OPS) { + add_req.trigger_eof = true; + add_req.skip_at_sof = 1; + } if (fctrl->bridge_intf.crm_cb && - fctrl->bridge_intf.crm_cb->add_req) + fctrl->bridge_intf.crm_cb->add_req) { rc = fctrl->bridge_intf.crm_cb->add_req(&add_req); if (rc) { CAM_ERR(CAM_FLASH, @@ -1282,7 +1283,10 @@ update_req_mgr: csl_packet->header.request_id); return rc; } - CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); + CAM_DBG(CAM_FLASH, + "add req %lld to req_mgr, trigger_eof %d", + add_req.req_id, add_req.trigger_eof); + } } return rc; } @@ -1507,7 +1511,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) switch (cmn_hdr->cmd_type) { case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: { CAM_DBG(CAM_FLASH, - "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called"); + "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called, req:%lld", + csl_packet->header.request_id); if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { @@ -1545,9 +1550,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) = flash_operation_info->led_current_ma[i]; CAM_DBG(CAM_FLASH, - "FLASH_CMD_TYPE op:%d", flash_data->opcode); - if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) - add_req.skip_before_applying |= SKIP_NEXT_FRAME; + "FLASH_CMD_TYPE op:%d, req:%lld", + flash_data->opcode, csl_packet->header.request_id); if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREDURATION) { @@ -1742,30 +1746,34 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) CAM_PKT_NOP_OPCODE) || ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = fctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = fctrl->bridge_intf.device_hdl; if ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS) { - if ((flash_data->opcode != - CAMERA_SENSOR_FLASH_OP_FIREDURATION)) - add_req.skip_before_applying |= 1; - else if (flash_data->opcode == - CAMERA_SENSOR_FLASH_OP_FIREDURATION) { - CAM_DBG(CAM_FLASH, "Trigger eof is set for request "); - add_req.trigger_eof = true; + add_req.trigger_eof = true; + if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) { + add_req.skip_at_sof = 1; + add_req.skip_at_eof = 1; } else - add_req.skip_before_applying = 0; - } else { - add_req.skip_before_applying = 0; + add_req.skip_at_sof = 1; } - CAM_DBG(CAM_FLASH, - "add req to req_mgr= %lld:: trigger_eof: %d", - add_req.req_id, add_req.trigger_eof); + if (fctrl->bridge_intf.crm_cb && - fctrl->bridge_intf.crm_cb->add_req) - fctrl->bridge_intf.crm_cb->add_req(&add_req); + fctrl->bridge_intf.crm_cb->add_req) { + rc = fctrl->bridge_intf.crm_cb->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in adding request: %llu to request manager", + csl_packet->header.request_id); + return rc; + } + CAM_DBG(CAM_FLASH, + "add req %lld to req_mgr, trigger_eof %d", + add_req.req_id, add_req.trigger_eof); + } } return rc; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index c1400a8ff99a..32b05eadfc64 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -20,13 +20,12 @@ static int cam_sensor_update_req_mgr( int rc = 0; struct cam_req_mgr_add_request add_req; + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = s_ctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; CAM_DBG(CAM_SENSOR, " Rxed Req Id: %llu", csl_packet->header.request_id); add_req.dev_hdl = s_ctrl->bridge_intf.device_hdl; - add_req.skip_before_applying = 0; - add_req.trigger_eof = false; if (s_ctrl->bridge_intf.crm_cb && s_ctrl->bridge_intf.crm_cb->add_req) { rc = s_ctrl->bridge_intf.crm_cb->add_req(&add_req); From 661a4191316057b23029f97c6ea8480d157d46b3 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 15 Mar 2021 15:46:44 +0530 Subject: [PATCH 705/790] msm: camera: isp: Add horizontal binning with qcfa binning This change is to add horizontal and vertical binning if qcfa binning is enabled. In qcfa binning, horizontal and vertical binning should be enable along with qcfa binning, whereas for only horizontal and vertical binning is required for bayer binning. CRs-Fixed: 2890967 Change-Id: I096d170cfb7a4a725deaffe5dc3996b23070040f Signed-off-by: Ayush Kumar --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h | 3 ++- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h index 1794a860b84e..e22cc1404c43 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_IFE_CSID_175_200_H_ @@ -47,6 +47,7 @@ static struct cam_ife_csid_pxl_reg_offset /* configurations */ .pix_store_en_shift_val = 7, .early_eof_en_shift_val = 29, + .horizontal_bin_en_shift_val = 2, .quad_cfa_bin_en_shift_val = 30, .ccif_violation_en = 1, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 1ba93e2425fc..91c9cabf0af4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2055,8 +2055,10 @@ static int cam_ife_csid_init_config_pxl_path( } if (is_ipp && csid_hw->binning_supported && - csid_hw->binning_enable) + csid_hw->binning_enable) { val |= (1 << pxl_reg->quad_cfa_bin_en_shift_val); + val |= (1 << pxl_reg->horizontal_bin_en_shift_val); + } val |= (1 << pxl_reg->pix_store_en_shift_val); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + From 65a86de9799e86931dddae537b56a868220fdade Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 22 Dec 2020 13:59:52 +0530 Subject: [PATCH 706/790] msm: camera: req_mgr: Re-design CRM to support multi links in sync mode This change is to support multi links in sync mode. Supports dynmanic switching to select master link in rtb and sat use case in sync mode. Supports sync logic for rtb and sat use case in sync mode. Apply requests for all links is triggered only on master epoch. Supports bubble recovery and sync logic for different pd links in sync mode. CRs-Fixed: 2783209 Change-Id: I81d1d0d37aa0d6e18c19ca87eac51ef3f160abfb Signed-off-by: Ayush Kumar --- drivers/cam_core/cam_context.c | 29 +- drivers/cam_core/cam_context.h | 17 +- drivers/cam_core/cam_node.c | 21 +- drivers/cam_cust/cam_custom_context.c | 1 + drivers/cam_isp/cam_isp_context.c | 202 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 10 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 1805 +++++++++++------ drivers/cam_req_mgr/cam_req_mgr_core.h | 55 +- drivers/cam_req_mgr/cam_req_mgr_interface.h | 66 +- .../cam_actuator/cam_actuator_core.c | 1 + .../cam_flash/cam_flash_core.c | 2 + .../cam_sensor/cam_sensor_core.c | 1 + 12 files changed, 1547 insertions(+), 663 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 75424db0c16a..9492d681ea77 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -182,6 +182,33 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } +int cam_context_handle_crm_state_change(struct cam_context *ctx, + struct cam_req_mgr_request_change_state *state_info) +{ + int rc; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!state_info) { + CAM_ERR(CAM_CORE, "Invalid change state payload"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].crm_ops.change_state) { + rc = ctx->state_machine[ctx->state].crm_ops.change_state(ctx, + state_info); + } else { + CAM_ERR(CAM_CORE, "No crm change state req in dev %d, state %d", + ctx->dev_hdl, ctx->state); + rc = -EPROTO; + } + + return rc; +} + int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 5be078536ff5..0ca3cccd8d87 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -127,6 +127,7 @@ struct cam_ctx_ioctl_ops { * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request + * @change_state: Change sub-state of hw context layer to bubble * */ struct cam_ctx_crm_ops { @@ -146,6 +147,8 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_link_evt_data *evt_data); int (*dump_req)(struct cam_context *ctx, struct cam_req_mgr_dump_info *dump); + int (*change_state)(struct cam_context *ctx, + struct cam_req_mgr_request_change_state *change_state); }; @@ -310,6 +313,18 @@ int cam_context_handle_crm_unlink(struct cam_context *ctx, int cam_context_handle_crm_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); +/** + * cam_context_handle_crm_state_change() + * + * @brief: Handle state change request + * + * @ctx: Object pointer for cam_context + * @state_info: State change request command payload + * + */ +int cam_context_handle_crm_state_change(struct cam_context *ctx, + struct cam_req_mgr_request_change_state *state_info); + /** * cam_context_handle_crm_notify_frame_skip() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index c3770f2df745..5df221f71b6c 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -619,6 +619,24 @@ static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) return cam_context_handle_crm_flush_req(ctx, flush); } +static int __cam_node_crm_state_change_req( + struct cam_req_mgr_request_change_state *state_info) +{ + struct cam_context *ctx = NULL; + + if (!state_info) + return -EINVAL; + + ctx = (struct cam_context *) cam_get_device_priv(state_info->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + state_info->dev_hdl); + return -EINVAL; + } + + return cam_context_handle_crm_state_change(ctx, state_info); +} + static int __cam_node_crm_process_evt( struct cam_req_mgr_link_evt_data *evt_data) { @@ -715,6 +733,7 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.dump_req = __cam_node_crm_dump_req; node->crm_node_intf.notify_frame_skip = __cam_node_crm_notify_frame_skip; + node->crm_node_intf.change_state = __cam_node_crm_state_change_req; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index ca4d1d1e35d5..134b5aa2b995 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -549,6 +549,7 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; + dev_info->sof_ts_cb = NULL; return 0; } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 86a3ae579c38..d4ba000210aa 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -743,8 +743,8 @@ static void __cam_isp_ctx_send_sof_timestamp( req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u", - request_id, ctx_isp->frame_id, + "link hdl 0x%x request id:%lld frame number:%lld SOF time stamp:%lld status:%u", + ctx_isp->base->link_hdl, request_id, ctx_isp->frame_id, ctx_isp->sof_timestamp_val, sof_event_status); if (cam_req_mgr_notify_message(&req_msg, @@ -1671,6 +1671,7 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( } 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; @@ -1679,8 +1680,9 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( ctx_isp->active_req_cnt++; request_id = req->request_id; 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); + "move request %lld to active list(cnt = %d), ctx %u link %x", + req->request_id, ctx_isp->active_req_cnt, + ctx->ctx_id, ctx->link_hdl); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_RUP, req); } else { @@ -1822,6 +1824,7 @@ notify_only: notify.trigger = CAM_TRIGGER_POINT_SOF; notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; + notify.sof_boottime = ctx_isp->boot_timestamp; notify.trigger_id = ctx_isp->trigger_id; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -1941,8 +1944,9 @@ static int __cam_isp_ctx_sof_in_activated_state( __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_SOF, request_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); + CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u link %x", + ctx_isp->frame_id, ctx_isp->sof_timestamp_val, + ctx->ctx_id, ctx->link_hdl); return rc; } @@ -1987,6 +1991,7 @@ end: static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { + bool rc = false; uint64_t request_id = 0; struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; @@ -2024,8 +2029,9 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; - CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", - ctx->ctx_id, req_isp->bubble_report, req->request_id); + CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d link %x Report Bubble flag %d req id:%lld", + ctx->ctx_id, ctx->link_hdl, + req_isp->bubble_report, req->request_id); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; @@ -2039,12 +2045,25 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; + notify.sof_boottime_val = ctx_isp->boot_timestamp; + notify.need_recovery = true; CAM_WARN_RATE_LIMIT(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); trace_cam_log_event("Bubble", "Rcvd epoch in applied state", req->request_id, ctx->ctx_id); - ctx->ctx_crm_intf->notify_err(¬ify); + rc = ctx->ctx_crm_intf->notify_err(¬ify); + + CAM_DBG(CAM_CRM, "Need bubble recovery %d", rc); + + if (rc) { + req_isp->bubble_detected = false; + req_isp->reapply = false; + CAM_DBG(CAM_ISP, "Disable bubble for ctx %d link %d", + ctx->ctx_id, ctx->link_hdl); + return 0; + } + atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; @@ -2198,6 +2217,7 @@ static int __cam_isp_ctx_buf_done_in_bubble( static int __cam_isp_ctx_epoch_in_bubble_applied( struct cam_isp_context *ctx_isp, void *evt_data) { + int rc = 0; uint64_t request_id = 0; struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; @@ -2255,10 +2275,17 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; + notify.sof_boottime_val = ctx_isp->boot_timestamp; + notify.need_recovery = true; CAM_WARN_RATE_LIMIT(CAM_REQ, "Notify CRM about Bubble req_id %llu frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); - ctx->ctx_crm_intf->notify_err(¬ify); + rc = ctx->ctx_crm_intf->notify_err(¬ify); + if (rc) { + req_isp->bubble_detected = false; + req_isp->reapply = false; + return 0; + } atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; @@ -3122,10 +3149,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( goto end; } - CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u", + CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u link %x", req->request_id, __cam_isp_ctx_substate_val_to_type(ctx_isp->substate_activated), - ctx->ctx_id); + ctx->ctx_id, ctx->link_hdl); req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (ctx_isp->active_req_cnt >= 2) { @@ -3208,6 +3235,81 @@ end: return rc; } +static int __cam_isp_ctx_change_substate( + struct cam_context *ctx, + struct cam_req_mgr_request_change_state *state_info) +{ + int rc = 0; + uint64_t request_id = 0; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_ctx_request *bubble_req = NULL; + struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + if (!list_empty(&ctx->wait_req_list)) { + req = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, + list); + if (req->request_id == state_info->req_id) { + req_isp = (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; + req_isp->reapply = true; + bubble_req = req; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + goto end; + } + } else { + CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id); + } + + if (!bubble_req) { + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + if (req->request_id == state_info->req_id) { + req_isp = + (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; + req_isp->reapply = true; + bubble_req = req; + break; + } + } + } + + if (!bubble_req) { + CAM_ERR(CAM_ISP, "Req %lld not in active list ctx : %d", + state_info->req_id, + ctx->ctx_id); + goto done; + } + +end: + + if (req_isp->bubble_report) + atomic_set(&ctx_isp->process_bubble, 1); + + if ((req->request_id > ctx_isp->reported_req_id) + && !req_isp->bubble_report) { + request_id = req->request_id; + ctx_isp->reported_req_id = request_id; + } + + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + CAM_REQ_MGR_SOF_EVENT_ERROR); + + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; + + CAM_DBG(CAM_ISP, "next Substate[%s] ctx : %d", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated), ctx->ctx_id); + +done: + return rc; +} + static int __cam_isp_ctx_apply_req_in_sof( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -3268,8 +3370,8 @@ static int __cam_isp_ctx_apply_req_in_bubble( ctx_isp->substate_activated)); rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply, CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED); - CAM_DBG(CAM_ISP, "new Substate[%s]", - __cam_isp_ctx_substate_val_to_type( + CAM_DBG(CAM_ISP, "ctx %d link %x new Substate[%s]", + ctx->ctx_id, ctx->link_hdl, __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); if (rc) @@ -3633,6 +3735,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( flush_req); ctx_isp->active_req_cnt = 0; + spin_unlock_bh(&ctx->lock); reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; @@ -3680,13 +3783,16 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_sof, + .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, /* APPLIED */ { .ioctl_ops = {}, - .crm_ops = {}, + .crm_ops = { + .change_state = __cam_isp_ctx_change_substate, + }, .irq_ops = NULL, }, /* EPOCH */ @@ -3694,6 +3800,7 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_epoch, + .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, @@ -3702,13 +3809,16 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_bubble, + .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, /* Bubble Applied */ { .ioctl_ops = {}, - .crm_ops = {}, + .crm_ops = { + .change_state = __cam_isp_ctx_change_substate, + }, .irq_ops = NULL, }, /* HW ERROR */ @@ -5227,6 +5337,33 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_isp_ctx_get_isp_info(int32_t dev_hdl, void *data) +{ + int rc = 0; + struct cam_context *ctx; + struct cam_req_mgr_dev_info *isp_dev = data; + struct cam_isp_context *isp_ctx = NULL; + + ctx = (struct cam_context *)cam_get_device_priv(dev_hdl); + + isp_ctx = (struct cam_isp_context *)ctx->ctx_priv; + + isp_dev->state = isp_ctx->substate_activated; + isp_dev->timestamp = isp_ctx->sof_timestamp_val; + isp_dev->boot_time = isp_ctx->boot_timestamp; + isp_dev->frame_id = isp_ctx->frame_id; + + if ((isp_ctx->substate_activated == + CAM_ISP_CTX_ACTIVATED_APPLIED) || + (isp_ctx->substate_activated == + CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED)) + isp_dev->is_applied = true; + else + isp_dev->is_applied = false; + + return rc; +} + static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { @@ -5238,6 +5375,7 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; dev_info->trigger_on = true; + dev_info->sof_ts_cb = &__cam_isp_ctx_get_isp_info; return rc; } @@ -5295,6 +5433,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); ctx_isp->frame_id = 0; + ctx_isp->sof_timestamp_val = 0; + ctx_isp->boot_timestamp = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->bubble_frame_cnt = 0; @@ -5644,6 +5784,33 @@ static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx, return rc; } +static int __cam_isp_ctx_change_state_req(struct cam_context *ctx, + struct cam_req_mgr_request_change_state *state_info) +{ + int rc = 0; + struct cam_ctx_ops *ctx_ops = NULL; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + + CAM_DBG(CAM_ISP, "Enter: changes state ctx id %d link 0x%x", + ctx->ctx_id, ctx->link_hdl); + ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated]; + if (ctx_ops->crm_ops.change_state) { + rc = ctx_ops->crm_ops.change_state(ctx, state_info); + } else { + CAM_WARN_RATE_LIMIT(CAM_ISP, + "No handle function in activated Substate[%s]", + __cam_isp_ctx_substate_val_to_type( + ctx_isp->substate_activated)); + rc = -EFAULT; + } + + if (rc) + CAM_WARN_RATE_LIMIT(CAM_ISP, + "changes state failed"); + return rc; +} + static int __cam_isp_ctx_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -5796,6 +5963,7 @@ static struct cam_ctx_ops .flush_req = __cam_isp_ctx_flush_req_in_top_state, .process_evt = __cam_isp_ctx_process_evt, .dump_req = __cam_isp_ctx_dump_in_top_state, + .change_state = __cam_isp_ctx_change_state_req, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_requests, @@ -6020,6 +6188,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->base = ctx_base; ctx->frame_id = 0; + ctx->sof_timestamp_val = 0; + ctx->boot_timestamp = 0; ctx->custom_enabled = false; ctx->use_frame_header_ts = false; ctx->active_req_cnt = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 1e1ac79be6fd..d3f748e93c04 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -260,15 +260,17 @@ enum cam_isp_ctx_type { * @ctx_type: RDI_ONLY, PIX and RDI, or FS2 * @packet_op_code: Packet opcode * @last_cdm_done: Last cdm done request + * @cam_isp_hw_sof_event_data sof event timestamp */ struct cam_isp_hw_cmd_args { uint32_t cmd_type; void *cmd_data; union { - uint32_t sof_irq_enable; - uint32_t ctx_type; - uint32_t packet_op_code; - uint64_t last_cdm_done; + uint32_t sof_irq_enable; + uint32_t ctx_type; + uint32_t packet_op_code; + uint64_t last_cdm_done; + struct cam_isp_hw_sof_event_data sof_done_event_data; } u; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index feb9d4c69174..27c6e22b594b 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -17,9 +17,14 @@ #include "cam_req_mgr_dev.h" #include "cam_req_mgr_debug.h" +#define THRESHOLD_FACTOR 3 + static struct cam_req_mgr_core_device *g_crm_core_dev; static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION]; +static char *__cam_req_mgr_dev_handle_to_name( + int32_t dev_hdl, struct cam_req_mgr_core_link *link); + void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) { uint32_t pd = 0; @@ -41,6 +46,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->open_req_cnt = 0; link->last_flush_id = 0; link->initial_sync_req = -1; + link->modified_init_sync_req = -1; link->dual_trigger = false; link->trigger_cnt[0][0] = 0; link->trigger_cnt[0][1] = 0; @@ -49,13 +55,18 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; - link->initial_skip = true; + link->initial_skip = 0; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; link->skip_init_frame = false; - link->num_sync_links = 0; link->last_sof_trigger_jiffies = 0; link->wq_congestion = false; + link->num_sync_link = 0; + link->activate_seq = -1; + link->bubble_skip = 0; + link->sync_frame_id = 0; + link->is_sync_req = true; + link->skip_sync_apply = false; atomic_set(&link->eof_event_cnt, 0); for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { @@ -199,6 +210,33 @@ static int __cam_req_mgr_inject_delay( return rc; } +/** + * cam_req_mgr_get_dev_hdl() + * + * @brief : Finds device handle based on the device name + * @dev_name : Device name whose dev handle is to be found + * @link : Link on which the device is connected + * @return : device handle + * + */ +static int32_t cam_req_mgr_get_dev_hdl( + char *dev_name, struct cam_req_mgr_core_link *link) +{ + struct cam_req_mgr_connected_device *dev = NULL; + int i = 0; + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + CAM_DBG(CAM_CRM, "dev name %s, iterate dev name %s", + dev_name, dev->dev_info.name); + if (strcmp(dev_name, dev->dev_info.name) == 0) + goto end; + } + return -EINVAL; +end: + return dev->dev_hdl; +} + /** * __cam_req_mgr_find_dev_name() * @@ -381,10 +419,10 @@ static int __cam_req_mgr_notify_error_on_link( * @return: 0 for success, negative for failure * */ -static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) +static int __cam_req_mgr_traverse( + struct cam_req_mgr_traverse *traverse_data) { int rc = 0; - int32_t next_idx = traverse_data->idx; int32_t curr_idx = traverse_data->idx; struct cam_req_mgr_req_tbl *tbl; struct cam_req_mgr_apply *apply_data; @@ -400,24 +438,18 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) tbl = traverse_data->tbl; apply_data = traverse_data->apply_data; slot = &tbl->slot[curr_idx]; - CAM_DBG(CAM_CRM, - "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", - tbl->pd, curr_idx, tbl->slot[curr_idx].state, - tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, - traverse_data->in_q->slot[curr_idx].skip_idx); - /* 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 || - tbl->skip_traverse > 0) { - if (tbl->next) { - __cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta, - tbl->num_slots); - traverse_data->idx = next_idx; - traverse_data->tbl = tbl->next; - rc = __cam_req_mgr_traverse(traverse_data); - } - if (rc >= 0) { + while (tbl) { + CAM_DBG(CAM_CRM, + "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", + tbl->pd, curr_idx, tbl->slot[curr_idx].state, + tbl->skip_traverse, + traverse_data->in_q->slot[curr_idx].status, + traverse_data->in_q->slot[curr_idx].skip_idx); + if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || + traverse_data->in_q->slot[curr_idx].skip_idx == 1 || + tbl->skip_traverse > 0) { + SET_SUCCESS_BIT(traverse_data->result, tbl->pd); if (traverse_data->validate_only == false) { @@ -428,33 +460,34 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) apply_data[tbl->pd].idx = curr_idx; CAM_DBG(CAM_CRM, "req_id: %lld with pd of %d", - apply_data[tbl->pd].req_id, - apply_data[tbl->pd].pd); - /* - * If traverse is successful decrement - * traverse skip - */ + apply_data[tbl->pd].req_id, + apply_data[tbl->pd].pd); + if (tbl->skip_traverse > 0) { apply_data[tbl->pd].req_id = -1; tbl->skip_traverse--; } } + rc = 0; } else { - /* linked pd table is not ready for this traverse yet */ - return rc; + traverse_data->result_data.req_id = + CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); + traverse_data->result_data.pd = tbl->pd; + traverse_data->result_data.masked_value = + (tbl->dev_mask & slot->req_ready_map); + SET_FAILURE_BIT(traverse_data->result, tbl->pd); + rc = -EAGAIN; + break; } - } else { - /* This pd table is not ready to proceed with asked idx */ - traverse_data->result_data.req_id = - CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); - traverse_data->result_data.pd = tbl->pd; - traverse_data->result_data.masked_value = - (tbl->dev_mask & slot->req_ready_map); - SET_FAILURE_BIT(traverse_data->result, tbl->pd); - return -EAGAIN; + if (tbl->next) { + __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, + tbl->num_slots); + traverse_data->idx = curr_idx; + traverse_data->tbl = tbl->next; + } + tbl = tbl->next; } - - return 0; + return rc; } /** @@ -735,6 +768,51 @@ static int __cam_req_mgr_check_for_lower_pd_devices( return -EAGAIN; } +/** + * cam_req_mgr_dump_link_info() + * @brief : Dump link info on failure + * + * @dump_info : payload to dump data + */ +static void cam_req_mgr_dump_link_info( + struct cam_req_mgr_dump_link_data *dump_info) +{ + int i = 0; + struct cam_req_mgr_core_link *m_link; + struct cam_req_mgr_dev_info dev_data; + + m_link = dump_info->m_link; + dev_data = dump_info->dev_data; + + CAM_DBG(CAM_CRM, + "Master link req_id %lld 0x%x Slave link 0x%x req_id %lld frame id %lld csid time %lld boottime %lld", + m_link->link_hdl, dump_info->s_link->link_hdl, + dump_info->m_req_id, dump_info->s_req_id, + dev_data.frame_id, dev_data.timestamp, + dev_data.boot_time); + + CAM_DBG(CAM_CRM, + "Master link 0x%x csid time %lld bootime %lld frame id %lld sync frame id %lld init sync req %lld", + m_link->link_hdl, + m_link->sof_timestamp, + m_link->sof_boottime, + m_link->frame_id, + m_link->sync_frame_id, + m_link->initial_sync_req); + + for (i = 0; i < m_link->num_sync_link; i++) { + CAM_DBG(CAM_CRM, + "slave link 0x%x csid time %lld bootime %lld frame id %lld sync frame id %lld init sync req %lld", + m_link->sync_link[i]->link_hdl, + m_link->sync_link[i]->sof_timestamp, + m_link->sync_link[i]->sof_boottime, + m_link->sync_link[i]->frame_id, + m_link->sync_link[i]->sync_frame_id, + m_link->sync_link[i]->initial_sync_req); + } +} + + /** * __cam_req_mgr_check_next_req_slot() * @@ -1061,19 +1139,6 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.validate_only = validate_only; traverse_data.open_req_cnt = link->open_req_cnt; - /* - * Some no-sync mode requests are processed after link config, - * then process the sync mode requests after no-sync mode requests - * are handled, the initial_skip should be false when processing - * the sync mode requests. - */ - if (link->initial_skip) { - CAM_DBG(CAM_CRM, - "Set initial_skip to false for link %x", - link->link_hdl); - link->initial_skip = false; - } - /* * Traverse through all pd tables, if result is success, * apply the settings @@ -1135,420 +1200,29 @@ static int32_t __cam_req_mgr_find_slot_for_req( } /** - * __cam_req_mgr_check_sync_for_mslave() + * cam_req_mgr_get_device_info() * - * @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 + * @brief : Get state and qtime info from device + * @link : pointer to link + * @sof_ts : pointer to dev_info payload + * + * @return : void * */ -static int __cam_req_mgr_check_sync_for_mslave( + +static void cam_req_mgr_get_device_info( struct cam_req_mgr_core_link *link, - struct cam_req_mgr_core_link *sync_link, - struct cam_req_mgr_slot *slot) + struct cam_req_mgr_dev_info *dev_info) { - 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; - int32_t sync_num_slots = 0; + int i; + struct cam_req_mgr_connected_device *dev; - if (!sync_link || !link) { - CAM_ERR(CAM_CRM, "Sync link or link is null"); - return -EINVAL; + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + dev_info->link_hdl = link->link_hdl; + if (dev && dev->dev_info.sof_ts_cb) + dev->dev_info.sof_ts_cb(dev->dev_hdl, dev_info); } - - req_id = slot->req_id; - - if (!sync_link->req.in_q) { - CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", - sync_link->link_hdl); - return -EINVAL; - } - - sync_num_slots = sync_link->req.in_q->num_slots; - sync_rd_idx = sync_link->req.in_q->rd_idx; - - CAM_DBG(CAM_CRM, - "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); - - 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; - return -EAGAIN; - } - - 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; - } - - if (link->is_master) { - if (sync_link->initial_skip) { - CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", - sync_link->link_hdl); - return -EAGAIN; - } - - 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; - } - - 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 + sync_num_slots) % - sync_num_slots) >= 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_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 + sync_num_slots) % - sync_num_slots) >= 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; - } - } - } - - CAM_DBG(CAM_REQ, - "Req: %lld ready to apply on link: %x [validation successful]", - req_id, link->link_hdl); - - return 0; -} - - -/** - * __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 - * traversed through - * @slot : pointer to the current slot being processed - * @return : 0 for success, negative for failure - * - */ -static int __cam_req_mgr_check_sync_req_is_ready( - struct cam_req_mgr_core_link *link, - struct cam_req_mgr_core_link *sync_link, - struct cam_req_mgr_slot *slot) -{ - struct cam_req_mgr_slot *sync_rd_slot = NULL; - int64_t req_id = 0, sync_req_id = 0; - int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; - int32_t sync_num_slots = 0; - uint64_t sync_frame_duration = 0; - uint64_t sof_timestamp_delta = 0; - uint64_t master_slave_diff = 0; - bool ready = true, sync_ready = true; - int slot_idx_diff = 0; - - if (!sync_link || !link) { - CAM_ERR(CAM_CRM, "Sync link null"); - return -EINVAL; - } - - req_id = slot->req_id; - - if (!sync_link->req.in_q) { - CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", - sync_link->link_hdl); - return -EINVAL; - } - - sync_num_slots = sync_link->req.in_q->num_slots; - sync_rd_idx = sync_link->req.in_q->rd_idx; - sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; - sync_req_id = sync_rd_slot->req_id; - - CAM_DBG(CAM_REQ, - "link_hdl %x sync link_hdl %x req %lld", - link->link_hdl, sync_link->link_hdl, req_id); - - if (sync_link->initial_skip) { - link->initial_skip = false; - CAM_DBG(CAM_CRM, - "sync link %x not streamed on", - sync_link->link_hdl); - return -EAGAIN; - } - - if (sync_link->prev_sof_timestamp) - sync_frame_duration = sync_link->sof_timestamp - - sync_link->prev_sof_timestamp; - else - sync_frame_duration = DEFAULT_FRAME_DURATION; - - sof_timestamp_delta = - link->sof_timestamp >= sync_link->sof_timestamp - ? link->sof_timestamp - sync_link->sof_timestamp - : sync_link->sof_timestamp - link->sof_timestamp; - - CAM_DBG(CAM_CRM, - "sync link %x last frame_duration is %d ns", - sync_link->link_hdl, sync_frame_duration); - - if (link->initial_skip) { - link->initial_skip = false; - - if ((link->sof_timestamp > sync_link->sof_timestamp) && - (sync_link->sof_timestamp > 0) && - (link->sof_timestamp - sync_link->sof_timestamp) < - (sync_frame_duration / 2)) { - /* - * If this frame sync with the previous frame of sync - * link, then we need to skip this frame, since the - * previous frame of sync link is also skipped. - */ - CAM_DBG(CAM_CRM, - "This frame sync with previous sync_link %x frame", - sync_link->link_hdl); - return -EAGAIN; - } else if (link->sof_timestamp <= sync_link->sof_timestamp) { - /* - * Sometimes, link receives the SOF event is eariler - * than sync link in IFE CSID side, but link's SOF - * event is processed later than sync link's, then - * we need to skip this SOF event since the sync - * link's SOF event is also skipped. - */ - CAM_DBG(CAM_CRM, - "The previous frame of sync link is skipped"); - return -EAGAIN; - } - } - - 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; - return -EAGAIN; - } - - sync_slot_idx = __cam_req_mgr_find_slot_for_req( - sync_link->req.in_q, req_id); - if (sync_slot_idx == -1) { - CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", - req_id, sync_link->link_hdl); - sync_ready = false; - return -EAGAIN; - } - - slot_idx_diff = (sync_slot_idx - sync_rd_idx + sync_num_slots) % - sync_num_slots; - if ((sync_link->req.in_q->slot[sync_slot_idx].status != - CRM_SLOT_STATUS_REQ_APPLIED) && - ((slot_idx_diff > 1) || - ((slot_idx_diff == 1) && - (sync_rd_slot->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); - return -EAGAIN; - } - - rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); - if (rc) { - CAM_DBG(CAM_CRM, - "Req: %lld [My link] not ready on link: %x, rc=%d", - req_id, link->link_hdl, rc); - ready = false; - } - - if (sync_link->req.in_q) { - 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 link: %x, rc=%d", - req_id, sync_link->link_hdl, rc); - sync_ready = false; - } - } else { - CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", - sync_link->link_hdl); - return -EINVAL; - } - - /* - * If both of them are ready or not ready, then just - * skip this sof and don't skip sync link next SOF. - */ - if (sync_ready != ready) { - CAM_DBG(CAM_CRM, - "Req: %lld ready %d sync_ready %d, ignore sync link next SOF", - req_id, ready, sync_ready); - - /* - * Only skip the frames if current frame sync with - * next frame of sync link. - */ - if (link->sof_timestamp - sync_link->sof_timestamp > - sync_frame_duration / 2) - link->sync_link_sof_skip = true; - return -EINVAL; - } else if (ready == false) { - CAM_DBG(CAM_CRM, - "Req: %lld not ready on link: %x", - req_id, link->link_hdl); - return -EINVAL; - } - - /* - * Do the self-correction when the frames are sync, - * we consider that the frames are synced if the - * difference of two SOF timestamp less than - * (sync_frame_duration / 5). - */ - master_slave_diff = sync_frame_duration; - do_div(master_slave_diff, 5); - if ((sync_link->sof_timestamp > 0) && - (sof_timestamp_delta < master_slave_diff) && - (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { - - /* - * This means current frame should sync with next - * frame of sync link, then the request id of in - * rd slot of two links should be same. - */ - CAM_DBG(CAM_CRM, - "link %x req_id %lld, sync_link %x req_id %lld", - link->link_hdl, req_id, - sync_link->link_hdl, sync_req_id); - - if (req_id > sync_req_id) { - CAM_DBG(CAM_CRM, - "link %x too quickly, skip this frame", - link->link_hdl); - return -EAGAIN; - } else if (req_id < sync_req_id) { - CAM_DBG(CAM_CRM, - "sync link %x too quickly, skip next frame of sync link", - sync_link->link_hdl); - link->sync_link_sof_skip = true; - } else if (sync_link->req.in_q->slot[sync_slot_idx].status != - CRM_SLOT_STATUS_REQ_APPLIED) { - CAM_DBG(CAM_CRM, - "link %x other not applied", link->link_hdl); - return -EAGAIN; - } - } - CAM_DBG(CAM_REQ, - "Req: %lld ready to apply on link: %x [validation successful]", - req_id, link->link_hdl); - - return 0; } static int __cam_req_mgr_check_multi_sync_link_ready( @@ -1556,60 +1230,16 @@ static int __cam_req_mgr_check_multi_sync_link_ready( struct cam_req_mgr_slot *slot, uint32_t trigger) { - int i, rc = 0; + int rc = 0; if (link->state == CAM_CRM_LINK_STATE_IDLE) { CAM_ERR(CAM_CRM, "link hdl %x is in idle state", - link->link_hdl); + link->link_hdl); return -EINVAL; } - for (i = 0; i < link->num_sync_links; i++) { - if (link->sync_link[i]) { - if (link->sync_link[i]->state == - CAM_CRM_LINK_STATE_IDLE) { - CAM_ERR(CAM_CRM, "sync link hdl %x is idle", - link->sync_link[i]->link_hdl); - return -EINVAL; - } - if (link->max_delay == link->sync_link[i]->max_delay) { - rc = __cam_req_mgr_check_sync_req_is_ready( - link, link->sync_link[i], slot); - if (rc < 0) { - CAM_DBG(CAM_CRM, "link %x not ready", - link->link_hdl); - return rc; - } - } else if (link->max_delay > - link->sync_link[i]->max_delay) { - link->is_master = true; - link->sync_link[i]->is_master = false; - rc = __cam_req_mgr_check_sync_for_mslave( - link, link->sync_link[i], slot); - if (rc < 0) { - CAM_DBG(CAM_CRM, "link%x not ready", - link->link_hdl); - return rc; - } - } else { - link->is_master = false; - link->sync_link[i]->is_master = true; - rc = __cam_req_mgr_check_sync_for_mslave( - link, link->sync_link[i], slot); - if (rc < 0) { - CAM_DBG(CAM_CRM, "link %x not ready", - link->link_hdl); - return rc; - } - } - } else { - CAM_ERR(CAM_REQ, "Sync link is null"); - return -EINVAL; - } - } - rc = __cam_req_mgr_inject_delay(link->req.l_tbl, - slot->idx, trigger); + slot->idx, trigger); if (rc < 0) { CAM_DBG(CAM_CRM, "Req: %lld needs to inject delay at %s", @@ -1694,7 +1324,7 @@ enum crm_req_eof_trigger_type __cam_req_mgr_check_for_eof( static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_trigger_notify *trigger_data) { - int rc = 0, idx, i; + int i = 0, rc = 0, idx; int reset_step = 0; uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; @@ -1728,6 +1358,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, in_q->slot[in_q->rd_idx].additional_timeout, trigger); slot = &in_q->slot[in_q->rd_idx]; + if (slot->status == CRM_SLOT_STATUS_NO_REQ) { CAM_DBG(CAM_CRM, "No Pending req"); rc = 0; @@ -1747,12 +1378,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } if (trigger == CAM_TRIGGER_POINT_SOF) { - /* - * Update the timestamp in session lock protection - * to avoid timing issue. - */ - link->prev_sof_timestamp = link->sof_timestamp; - link->sof_timestamp = trigger_data->sof_timestamp_val; /* Check for WQ congestion */ if (jiffies_to_msecs(jiffies - @@ -1765,8 +1390,14 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (slot->status != CRM_SLOT_STATUS_REQ_READY) { if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + 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_multi_sync_link_ready( - link, slot, trigger); + link, slot, trigger); } else { if (link->in_msync_mode) { CAM_DBG(CAM_CRM, @@ -1774,9 +1405,10 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); link->in_msync_mode = false; link->initial_sync_req = -1; - for (i = 0; i < link->num_sync_links; i++) { - if (link->sync_link[i]) { - tmp_link = link->sync_link[i]; + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; + i++) { + tmp_link = link->sync_link[i]; + if (tmp_link) { tmp_link->initial_sync_req = -1; tmp_link->in_msync_mode = false; } @@ -1846,6 +1478,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } + if (link->num_sync_link && + (link->initial_sync_req == slot->req_id)) { + link->sync_frame_id = trigger_data->frame_id; + CAM_DBG(CAM_CRM, "link %x sync frame %lld", + link->link_hdl, link->sync_frame_id); + } + rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger, &dev); if (rc < 0) { /* Apply req failed retry at next sof */ @@ -1914,15 +1553,10 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); idx = in_q->rd_idx; reset_step = link->max_delay; - - for (i = 0; i < link->num_sync_links; i++) { - if (link->sync_link[i]) { - if ((link->in_msync_mode) && - (link->sync_link[i]->max_delay > - reset_step)) - reset_step = + for (i = 0; i < link->num_sync_link - 1; i++) { + if (reset_step < link->sync_link[i]->max_delay) + reset_step = link->sync_link[i]->max_delay; - } } if (slot->req_id > 0) @@ -2478,8 +2112,9 @@ static void __cam_req_mgr_unreserve_link( } } - for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) - link->sync_link[j] = NULL; + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++) + link->sync_link[i] = NULL; + session->num_links--; CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); mutex_unlock(&session->lock); @@ -2609,13 +2244,6 @@ 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 is_master %d exp_timeout_val %d ms", - sched_req->link_hdl, sched_req->req_id, - in_q->wr_idx, sched_req->sync_mode, - link->is_master, - sched_req->additional_timeout); - mutex_lock(&link->req.lock); slot = &in_q->slot[in_q->wr_idx]; @@ -2625,9 +2253,10 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) slot->status = CRM_SLOT_STATUS_REQ_ADDED; slot->req_id = sched_req->req_id; - slot->sync_mode = sched_req->sync_mode; slot->skip_idx = 0; slot->recover = sched_req->bubble_enable; + slot->sync_mode = sched_req->sync_mode; + slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; if (sched_req->additional_timeout < 0) { CAM_WARN(CAM_CRM, "Requested timeout is invalid [%dms]", @@ -2648,16 +2277,63 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) __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) + if (link->initial_sync_req == -1) { link->initial_sync_req = slot->req_id; + link->modified_init_sync_req = slot->req_id; + } } else { link->initial_sync_req = -1; - for (i = 0; i < link->num_sync_links; i++) { - if (link->sync_link[i]) + for (i = 0; i < link->num_sync_link; i++) { + if (link->sync_link[i]) { link->sync_link[i]->initial_sync_req = -1; + link->modified_init_sync_req = -1; + } } } + CAM_DBG(CAM_CRM, + "link_hdl %x req_id %lld at slot %d schedule_mode %d slot mode %d is_master %d exp_timeout_val %d ms", + sched_req->link_hdl, sched_req->req_id, + in_q->wr_idx, sched_req->sync_mode, + slot->sync_mode, + link->is_master, + sched_req->additional_timeout); + /* + * This logic is to make first few requests in non-sync mode + * so that these requests should apply irrespective of threshold + * time condition as difference in sensor stream on may be more than + * threshold value at start. For sw sync logic to work, first few + * requests needs to apply in same frame duration. + */ + + if (link->is_sync_req && slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC + && ((link->initial_sync_req + 5) > slot->req_id)) { + slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_SYNC; + } else if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + if (link->is_sync_req && (link->initial_skip == 0)) { + link->is_sync_req = false; + link->initial_sync_req = slot->req_id + 1; + CAM_DBG(CAM_CRM, "Initial sync req %lld link %x", + link->initial_sync_req, link->link_hdl); + } + + if (link->initial_skip && link->initial_sync_req) { + link->initial_skip--; + slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; + slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_SYNC; + CAM_DBG(CAM_CRM, "Initial sync req %lld link %x", + link->initial_sync_req, link->link_hdl); + } + } + CAM_DBG(CAM_CRM, + "link_hdl %x req_id %lld at slot %d schedule_mode %d slot mode %d is_master %d exp_timeout_val %d ms init sync %d", + sched_req->link_hdl, sched_req->req_id, + in_q->wr_idx, sched_req->sync_mode, + slot->sync_mode, + link->is_master, + sched_req->additional_timeout, + link->initial_sync_req); mutex_unlock(&link->req.lock); end: @@ -2676,12 +2352,19 @@ end: */ int cam_req_mgr_process_add_req(void *priv, void *data) { - int rc = 0, i = 0, idx; + int rc = 0, i = 0, j = 0; + int idx, idx2; struct cam_req_mgr_add_request *add_req = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_connected_device *device = NULL; + struct cam_req_mgr_connected_device *device2 = NULL; struct cam_req_mgr_req_tbl *tbl = NULL; + struct cam_req_mgr_req_tbl *tbl2 = NULL; struct cam_req_mgr_tbl_slot *slot = NULL; + struct cam_req_mgr_tbl_slot *sync_slot = NULL; + int32_t sync_dev_hdl = -1; + char *dev_name = NULL; + struct cam_req_mgr_slot *link_slot = NULL; struct crm_task_payload *task_data = NULL; if (!data || !priv) { @@ -2709,6 +2392,7 @@ int cam_req_mgr_process_add_req(void *priv, void *data) rc = -EINVAL; goto end; } + /* * Go through request table and add * request id to proper table @@ -2728,6 +2412,7 @@ int cam_req_mgr_process_add_req(void *priv, void *data) goto end; } + link_slot = &link->req.in_q->slot[idx]; slot = &tbl->slot[idx]; slot->ops.is_applied = false; @@ -2738,6 +2423,62 @@ int cam_req_mgr_process_add_req(void *priv, void *data) add_req->req_id, slot->inject_delay_at_sof, device->dev_info.name); + + if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + for (i = 0; i < link->num_sync_link; i++) { + mutex_lock(&link->sync_link[i]->req.lock); + idx2 = __cam_req_mgr_find_slot_for_req( + link->sync_link[i]->req.in_q, + add_req->req_id); + if (idx2 < 0) { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q for dev %s on link 0x%x", + add_req->req_id, + device->dev_info.name, + link->sync_link[i]->link_hdl); + rc = -EBADSLT; + mutex_unlock( + &link->sync_link[i]->req.lock); + mutex_unlock(&link->req.lock); + goto end; + } + dev_name = __cam_req_mgr_dev_handle_to_name( + add_req->dev_hdl, link); + sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, + link->sync_link[i]); + for (j = 0; + j < link->sync_link[i]->num_devs; j++) { + device2 = &link->sync_link[i]->l_dev[j]; + CAM_ERR(CAM_CRM, "device hdl %x : sync link dev hdl %x", + device2->dev_hdl, sync_dev_hdl); + if (device2->dev_hdl == sync_dev_hdl) { + tbl2 = device2->pd_tbl; + break; + } + } + if (!tbl2) { + CAM_ERR_RATE_LIMIT(CAM_CRM, + "Sync link dev hdl %x not found", + sync_dev_hdl); + rc = -EINVAL; + mutex_unlock( + &link->sync_link[i]->req.lock); + mutex_unlock(&link->req.lock); + goto end; + } + sync_slot = &tbl2->slot[idx2]; + sync_slot->ops.dev_hdl = sync_dev_hdl; + sync_slot->inject_delay_at_sof = + (add_req->skip_at_sof & 0xFF); + CAM_DBG(CAM_CRM, + "link %x Req_id %llu injecting delay %llu frame at SOF by %s", + link->sync_link[i]->link_hdl, + add_req->req_id, + slot->inject_delay_at_sof, + device->dev_info.name); + mutex_unlock(&link->sync_link[i]->req.lock); + } + } } if ((add_req->skip_at_eof & 0xFF) > slot->inject_delay_at_eof) { @@ -2747,14 +2488,123 @@ int cam_req_mgr_process_add_req(void *priv, void *data) add_req->req_id, slot->inject_delay_at_eof, device->dev_info.name); + + if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + for (i = 0; i < link->num_sync_link; i++) { + mutex_lock(&link->sync_link[i]->req.lock); + idx2 = __cam_req_mgr_find_slot_for_req( + link->sync_link[i]->req.in_q, + add_req->req_id); + if (idx2 < 0) { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q for dev %s on link 0x%x", + add_req->req_id, + device->dev_info.name, + link->sync_link[i]->link_hdl); + rc = -EBADSLT; + mutex_unlock( + &link->sync_link[i]->req.lock); + mutex_unlock(&link->req.lock); + goto end; + } + dev_name = __cam_req_mgr_dev_handle_to_name( + add_req->dev_hdl, link); + sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, + link->sync_link[i]); + for (j = 0; + j < link->sync_link[i]->num_devs; j++) { + device2 = &link->sync_link[i]->l_dev[j]; + CAM_ERR(CAM_CRM, "device hdl %x : sync link dev hdl %x", + device2->dev_hdl, sync_dev_hdl); + if (device2->dev_hdl == sync_dev_hdl) { + tbl2 = device2->pd_tbl; + break; + } + } + if (!tbl2) { + CAM_ERR_RATE_LIMIT(CAM_CRM, + "Synclink dev hdl %x not found", + sync_dev_hdl); + rc = -EINVAL; + mutex_unlock( + &link->sync_link[i]->req.lock); + mutex_unlock(&link->req.lock); + goto end; + } + sync_slot = &tbl2->slot[idx2]; + sync_slot->ops.dev_hdl = sync_dev_hdl; + sync_slot->inject_delay_at_eof = + (add_req->skip_at_eof & 0xFF); + CAM_DBG(CAM_CRM, + "link %x Req_id %llu injecting delay %llu frame at EOF by %s", + link->sync_link[i]->link_hdl, + add_req->req_id, + slot->inject_delay_at_sof, + device->dev_info.name); + mutex_unlock(&link->sync_link[i]->req.lock); + } + } } if (add_req->trigger_eof) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, - "Req_id %llu slot:%d added for EOF tigger for Device: %s", + "link %x Req_id %llu slot:%d added for EOF tigger for Device: %s", + link->link_hdl, add_req->req_id, idx, device->dev_info.name); + + if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + for (i = 0; i < link->num_sync_link; i++) { + mutex_lock(&link->sync_link[i]->req.lock); + idx2 = __cam_req_mgr_find_slot_for_req( + link->sync_link[i]->req.in_q, + add_req->req_id); + if (idx2 < 0) { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q for dev %s on link 0x%x", + add_req->req_id, + device->dev_info.name, + link->sync_link[i]->link_hdl); + rc = -EBADSLT; + mutex_unlock( + &link->sync_link[i]->req.lock); + mutex_unlock(&link->req.lock); + goto end; + } + dev_name = __cam_req_mgr_dev_handle_to_name( + add_req->dev_hdl, link); + sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, + link->sync_link[i]); + for (j = 0; + j < link->sync_link[i]->num_devs; j++) { + device2 = &link->sync_link[i]->l_dev[j]; + CAM_ERR(CAM_CRM, + "device hdl %x : sync link dev hdl %x", + device2->dev_hdl, sync_dev_hdl); + if (device2->dev_hdl == sync_dev_hdl) { + tbl2 = device2->pd_tbl; + break; + } + } + if (!tbl2) { + CAM_ERR_RATE_LIMIT(CAM_CRM, + "Sync link dev hdl %x not found", + sync_dev_hdl); + rc = -EINVAL; + mutex_unlock( + &link->sync_link[i]->req.lock); + mutex_unlock(&link->req.lock); + goto end; + } + sync_slot = &tbl2->slot[idx2]; + sync_slot->ops.is_applied = false; + sync_slot->ops.apply_at_eof = true; + sync_slot->ops.dev_hdl = sync_dev_hdl; + mutex_unlock(&link->sync_link[i]->req.lock); + } + } + } if (slot->state != CRM_REQ_STATE_PENDING && @@ -2768,8 +2618,8 @@ int cam_req_mgr_process_add_req(void *priv, void *data) slot->state = CRM_REQ_STATE_PENDING; slot->req_ready_map |= (1 << device->dev_bit); - CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x", - idx, add_req->dev_hdl, add_req->req_id, tbl->pd, + CAM_DBG(CAM_CRM, "link %x idx %d dev_hdl %x req_id %lld pd %d ready_map %x", + link->link_hdl, idx, add_req->dev_hdl, add_req->req_id, tbl->pd, slot->req_ready_map); trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); @@ -2896,12 +2746,7 @@ int cam_req_mgr_process_error(void *priv, void *data) __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl); in_q->rd_idx = idx; in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; - if (link->sync_link[0]) { - in_q->slot[idx].sync_mode = 0; - __cam_req_mgr_inc_idx(&idx, 1, - link->req.l_tbl->num_slots); - in_q->slot[idx].sync_mode = 0; - } + spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_ERR; spin_unlock_bh(&link->link_state_spin_lock); @@ -2979,7 +2824,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) mutex_lock(&link->req.lock); - if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) { + if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF + && !link->num_sync_link) { idx = __cam_req_mgr_find_slot_for_req(in_q, trigger_data->req_id); if (idx >= 0) { @@ -3014,6 +2860,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) in_q->slot[in_q->rd_idx].status); spin_unlock_bh(&link->link_state_spin_lock); + CAM_DBG(CAM_CRM, "Link %x req id %lld", + link->link_hdl, in_q->slot[in_q->rd_idx].req_id); /* * Move to next req at SOF only in case @@ -3058,7 +2906,7 @@ end: * @return : String containing the device name * */ -static const char *__cam_req_mgr_dev_handle_to_name( +static char *__cam_req_mgr_dev_handle_to_name( int32_t dev_hdl, struct cam_req_mgr_core_link *link) { struct cam_req_mgr_connected_device *dev = NULL; @@ -3087,11 +2935,12 @@ static const char *__cam_req_mgr_dev_handle_to_name( */ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) { - int rc = 0, idx; + int i, rc = 0, idx; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_add_request *dev_req; struct crm_task_payload *task_data; + struct cam_req_mgr_slot *slot = NULL; if (!add_req) { CAM_ERR(CAM_CRM, "sof_data is NULL"); @@ -3130,6 +2979,8 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) goto end; } + slot = &link->req.in_q->slot[idx]; + task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task dev %x req %lld", @@ -3151,6 +3002,10 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) atomic_inc(&link->eof_event_cnt); CAM_DBG(CAM_REQ, "Req_id: %llu, eof_event_cnt: %d", dev_req->req_id, link->eof_event_cnt); + if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + for (i = 0; i < link->num_sync_link; i++) + atomic_inc(&link->sync_link[i]->eof_event_cnt); + } } task->process_cb = &cam_req_mgr_process_add_req; @@ -3167,23 +3022,30 @@ end: * cam_req_mgr_cb_notify_err() * * @brief : Error received from device, sends bubble recovery + * * @err_info : contains information about error occurred like bubble/overflow * - * @return : 0 on success, negative in case of failure + * @return : true on skipping bubble processing, otherwise, false * */ -static int cam_req_mgr_cb_notify_err( +static bool cam_req_mgr_cb_notify_err( struct cam_req_mgr_error_notify *err_info) { - int rc = 0; + bool rc = false; + int i, j; + uint32_t idx; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_error_notify *notify_err; struct crm_task_payload *task_data; + struct cam_req_mgr_slot *slot = NULL; + struct cam_req_mgr_slot *tmp_slot = NULL; + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_request_change_state state_info; if (!err_info) { CAM_ERR(CAM_CRM, "err_info is NULL"); - rc = -EINVAL; + rc = false; goto end; } @@ -3191,37 +3053,127 @@ static int cam_req_mgr_cb_notify_err( cam_get_device_priv(err_info->link_hdl); if (!link) { CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl); - rc = -EINVAL; + rc = false; goto end; } + idx = __cam_req_mgr_find_slot_for_req( + link->req.in_q, err_info->req_id); + if (idx < 0) { + CAM_ERR(CAM_CRM, + "req %lld not found in in_q link %x", + err_info->req_id, link->link_hdl); + rc = false; + goto end; + } + + tmp_slot = &link->req.in_q->slot[idx]; + + /* Incrementing slot idx to find if request in the slot + * is applied in sync mode or non-sync mode. + */ + __cam_req_mgr_inc_idx( + &idx, 1, link->req.in_q->num_slots); + + slot = &link->req.in_q->slot[idx]; + + /* Condition to check if crm need to process bubble notified by + * crm or isp. If bubble is reported for slave link then don't + * process bubble recovery. Checking previous slot with tmp_slot + * to handle condition where bubble is reported for last request. + */ + if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || + tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) && + !link->is_master) { + crm_timer_reset(link->watchdog); + CAM_DBG(CAM_CRM, "Not processing bubble as it is slave link %x", + link->link_hdl); + return true; + } + spin_lock_bh(&link->link_state_spin_lock); if (link->state != CAM_CRM_LINK_STATE_READY) { CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); spin_unlock_bh(&link->link_state_spin_lock); - rc = -EPERM; + rc = false; goto end; } crm_timer_reset(link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); - task = cam_req_mgr_workq_get_task(link->workq); - if (!task) { - CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id); - rc = -EBUSY; - goto end; + if (link->is_master && + slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + for (i = 0; i < link->num_sync_link; i++) { + CAM_DBG(CAM_CRM, "Bubble for sync link %x", + link->sync_link[i]->link_hdl); + state_info.link_hdl = link->sync_link[i]->link_hdl; + state_info.req_id = err_info->req_id; + for (j = 0; j < link->sync_link[i]->num_devs; j++) { + dev = &link->sync_link[i]->l_dev[j]; + if (dev->ops && dev->ops->change_state) { + state_info.dev_hdl = dev->dev_hdl; + + if (!(dev->ops->change_state( + &state_info))) { + CAM_DBG(CAM_CRM, + "Err on bubble notify"); + rc = false; + } + + task = cam_req_mgr_workq_get_task( + link->workq); + if (!task) { + CAM_ERR(CAM_CRM, + "no empty task req_id %lld", + err_info->req_id); + rc = false; + goto end; + } + + task_data = (struct crm_task_payload *) + task->payload; + task_data->type = + CRM_WORKQ_TASK_NOTIFY_ERR; + notify_err = + (struct cam_req_mgr_error_notify *)& + task_data->u; + notify_err->req_id = err_info->req_id; + notify_err->link_hdl = + link->sync_link[i]->link_hdl; + notify_err->dev_hdl = dev->dev_hdl; + notify_err->error = err_info->error; + task->process_cb = + &cam_req_mgr_process_error; + cam_req_mgr_workq_enqueue_task( + task, + link->sync_link[i], + CRM_TASK_PRIORITY_0); + } + } + } } - task_data = (struct crm_task_payload *)task->payload; - task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; - notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; - notify_err->req_id = err_info->req_id; - notify_err->link_hdl = err_info->link_hdl; - notify_err->dev_hdl = err_info->dev_hdl; - notify_err->error = err_info->error; - notify_err->trigger = err_info->trigger; - task->process_cb = &cam_req_mgr_process_error; - rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); + if (err_info->need_recovery) { + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "no empty task req_id %lld", + err_info->req_id); + rc = false; + goto end; + } + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; + notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; + notify_err->req_id = err_info->req_id; + notify_err->link_hdl = err_info->link_hdl; + notify_err->dev_hdl = err_info->dev_hdl; + notify_err->error = err_info->error; + notify_err->trigger = err_info->trigger; + task->process_cb = &cam_req_mgr_process_error; + rc = cam_req_mgr_workq_enqueue_task( + task, link, CRM_TASK_PRIORITY_0); + } end: return rc; @@ -3377,7 +3329,51 @@ end: return rc; } +static int cam_req_mgr_send_to_bubble( + struct cam_req_mgr_core_link *link, + uint64_t req_id) +{ + int rc = 0, i; + struct cam_req_mgr_error_notify notify; + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_request_change_state state_info; + struct cam_req_mgr_dev_info dev_data; + notify.link_hdl = link->link_hdl; + notify.req_id = req_id; + notify.error = CRM_KMD_ERR_BUBBLE; + notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.frame_id = link->frame_id; + notify.sof_timestamp_val = link->sof_timestamp; + notify.need_recovery = false; + + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + if (dev->ops && dev->ops->change_state) { + notify.dev_hdl = dev->dev_hdl; + if (dev->ops && dev->ops->change_state) { + cam_req_mgr_get_device_info(link, &dev_data); + if (dev_data.is_applied) { + state_info.link_hdl = link->link_hdl; + state_info.req_id = req_id; + state_info.dev_hdl = dev->dev_hdl; + rc = dev->ops->change_state( + &state_info); + if (rc < 0) + CAM_INFO(CAM_CRM, + "Failed to change state"); + } else { + link->bubble_skip = link->max_delay; + } + } + rc = cam_req_mgr_cb_notify_err(¬ify); + if (!rc) + CAM_INFO(CAM_CRM, + "Bubble recovery failed"); + } + } + return rc; +} /** * cam_req_mgr_cb_notify_trigger() @@ -3391,12 +3387,27 @@ end: static int cam_req_mgr_cb_notify_trigger( struct cam_req_mgr_trigger_notify *trigger_data) { - int32_t rc = 0, trigger_id = 0; - uint32_t trigger; - struct crm_workq_task *task = NULL; - struct cam_req_mgr_core_link *link = NULL; + int32_t i = 0, rc = 0, trigger_id = 0; + int32_t sync_dev_hdl = -1, sync_id = 0; + int64_t req_diff = 0; + uint32_t trigger; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_trigger_notify *notify_trigger; - struct crm_task_payload *task_data; + struct crm_task_payload *task_data; + struct cam_req_mgr_slot *slot = NULL; + struct cam_req_mgr_slot *tmp_slot = NULL; + struct cam_req_mgr_req_queue *in_q; + struct timespec64 ts; + struct cam_req_mgr_dev_info dev_data; + struct cam_req_mgr_slot *sync_slot = NULL; + struct cam_req_mgr_req_queue *sync_in_q; + int32_t sync_rd_idx = 0; + char *dev_name = NULL; + uint64_t curr_sync_time = 0; + uint64_t frame_duration = 0; + uint64_t curr_boot_timestamp; + uint64_t threshold = 0; if (!trigger_data) { CAM_ERR(CAM_CRM, "trigger_data is NULL"); @@ -3419,6 +3430,10 @@ static int cam_req_mgr_cb_notify_trigger( trigger_id = trigger_data->trigger_id; trigger = trigger_data->trigger; + ktime_get_boottime_ts64(&ts); + curr_boot_timestamp = + (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); /* * Reduce the workq overhead when there is @@ -3462,8 +3477,416 @@ static int cam_req_mgr_cb_notify_trigger( if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) crm_timer_reset(link->watchdog); + link->prev_sof_timestamp = link->sof_timestamp; + link->sof_timestamp = trigger_data->sof_timestamp_val; + link->frame_id = trigger_data->frame_id; + link->sof_boottime = trigger_data->sof_boottime; spin_unlock_bh(&link->link_state_spin_lock); + in_q = link->req.in_q; + slot = &in_q->slot[in_q->rd_idx]; + tmp_slot = &in_q->slot[in_q->rd_idx]; + + CAM_DBG(CAM_CRM, + "link %x req %lld idx %d state %d real sync mode %d", + link->link_hdl, slot->req_id, sync_id, slot->status, + slot->real_sync_mode); + + if (link->initial_sync_req != -1 && + slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC && + link->num_sync_link) { + sync_id = slot->idx; + __cam_req_mgr_inc_idx( + &sync_id, 1, link->req.in_q->num_slots); + slot = &in_q->slot[sync_id]; + CAM_DBG(CAM_CRM, + "E link %x req %lld idx %d state %d", + link->link_hdl, slot->req_id, sync_id, slot->status); + } + + + CAM_DBG(CAM_CRM, + "link %x req %lld slot mode %d tmp slot mode %d init sync %lld", + link->link_hdl, slot->req_id, + slot->sync_mode, tmp_slot->sync_mode, + link->initial_sync_req); + + if (trigger == CAM_TRIGGER_POINT_SOF && + (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || + (tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC && + (link->initial_sync_req != -1)))) { + /* If in sync and slave link then don't apply */ + if (!link->is_master) { + + CAM_DBG(CAM_CRM, + "Skipping slave link 0x%x apply sof timestamp %llx frame %lld slot req %lld", + link->link_hdl, + link->sof_timestamp, + trigger_data->frame_id, + slot->req_id); + + CAM_DBG(CAM_CRM, + "[Slave %x] epoch time %lld sof boottime %lld frame id %lld open cnt %d req id %lld", + link->link_hdl, + curr_boot_timestamp, + link->sof_boottime, + trigger_data->frame_id, + link->open_req_cnt, + slot->req_id); + + goto end; + } else { + + frame_duration = + (curr_boot_timestamp - link->sof_boottime) * 2; + CAM_DBG(CAM_CRM, + "[Master %x] epoch time %lld sof boottime %lld frame id %lld frame duration %d ms open cnt %d req id %lld", + link->link_hdl, + curr_boot_timestamp, + link->sof_boottime, + trigger_data->frame_id, + frame_duration/1000000, + link->open_req_cnt, + slot->req_id); + + rc = __cam_req_mgr_check_next_req_slot(link); + 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", + slot->req_id, link->link_hdl, rc); + return rc; + } + + /* Checking each sync link if they are ready to apply + * on this epoch, if not then skip apply on this epoch + */ + for (i = 0; i < link->num_sync_link; i++) { + sync_in_q = link->sync_link[i]->req.in_q; + sync_rd_idx = sync_in_q->rd_idx; + __cam_req_mgr_inc_idx( + &sync_rd_idx, 1, + link->sync_link[i]->req.in_q->num_slots); + sync_slot = &sync_in_q->slot[sync_rd_idx]; + rc = __cam_req_mgr_check_next_req_slot( + link->sync_link[i]); + + /* This condition is for SAT usecase, + * if request id to be sync is different + * then this will help to sync + */ + if (link->initial_sync_req != -1 && + (link->sync_link[i]->initial_sync_req != + -1) && (link->initial_sync_req == + slot->req_id) && + (link->sync_link[i]->initial_sync_req > + sync_slot->req_id)) { + CAM_DBG(CAM_CRM, + "Not applying on Master %x as slave %x is not in sync", + link->link_hdl, + link->sync_link[i]->link_hdl); + return rc; + } + + /* checking if packet for synclink is + * available or not + */ + rc = __cam_req_mgr_check_link_is_ready( + link->sync_link[i], sync_rd_idx, true); + + if (rc) { + CAM_DBG(CAM_CRM, + "Req:%lld [sync] not ready on link: %x, rc=%d", + sync_slot->req_id, + link->sync_link[i]->link_hdl, + rc); + return rc; + } + + /* Getting time and state info ISP context */ + cam_req_mgr_get_device_info( + link->sync_link[i], &dev_data); + + /* Checking if frame difference is maintain */ + req_diff = + (link->sync_frame_id - + link->sync_link[i]->sync_frame_id); + if (!link->sync_link_sof_skip && + link->sync_frame_id && + link->initial_sync_req != slot->req_id + && (req_diff != (link->frame_id - + dev_data.frame_id))) { + struct cam_req_mgr_dump_link_data + dump_info; + + CAM_DBG(CAM_CRM, + "Frame diff not matching %d", + link->frame_id - + dev_data.frame_id); + dump_info.m_link = link; + dump_info.s_link = link->sync_link[i]; + dump_info.dev_data = dev_data; + dump_info.s_req_id = sync_slot->req_id; + dump_info.m_req_id = slot->req_id; + cam_req_mgr_dump_link_info(&dump_info); + return rc; + } + + /* Calculating sof time differnce + * of master and slave for current frame + */ + curr_sync_time = + (dev_data.timestamp >= + link->sof_timestamp) ? + dev_data.timestamp - link->sof_timestamp : + link->sof_timestamp - dev_data.timestamp; + + threshold = frame_duration / THRESHOLD_FACTOR; + + /* Checking if master and sync links are in + * same frame duration considering master frame + * duration in calculating threshold value + */ + if (curr_sync_time > threshold) { + struct cam_req_mgr_dump_link_data + dump_info; + CAM_DBG(CAM_CRM, + "Master %x and slave %x are not in same time frame time diff %lld threshold %lld", + link->link_hdl, + link->sync_link[i]->link_hdl, + curr_sync_time/1000000, + threshold/1000000); + + dump_info.m_link = link; + dump_info.s_link = link->sync_link[i]; + dump_info.dev_data = dev_data; + dump_info.s_req_id = sync_slot->req_id; + dump_info.m_req_id = slot->req_id; + cam_req_mgr_dump_link_info(&dump_info); + return 0; + } + + /* If ISP substate is in applied state then + * condition it as bubble condition, + * Trigger bubble recovery + */ + if (dev_data.is_applied && + link->initial_sync_req != slot->req_id) { + CAM_ERR(CAM_CRM, + "Slave link %x req %lld is in applied state, triggering bubble recovery", + link->sync_link[i]->link_hdl, + (sync_slot->req_id - + link->sync_link[i]->max_delay)); + rc = cam_req_mgr_send_to_bubble(link, + (sync_slot->req_id - + link->sync_link[i]->max_delay)); + link->sync_link_sof_skip = true; + CAM_DBG(CAM_CRM, + "Master sof %lld slave sof %lld", + link->sof_timestamp, + dev_data.timestamp); + return rc; + } + + /* Checking if the initial request + * difference is maintained + */ + req_diff = link->initial_sync_req - + link->sync_link[i]->initial_sync_req; + + if (!link->sync_link_sof_skip && + req_diff != + (slot->req_id - sync_slot->req_id)) { + struct cam_req_mgr_dump_link_data + dump_info; + + CAM_DBG(CAM_CRM, + "Req diff %lld Master link %x req %lld slave link %x req %lld", + req_diff, + link->link_hdl, + slot->req_id, + link->sync_link[i]->link_hdl, + sync_slot->req_id); + + dump_info.m_link = link; + dump_info.s_link = link->sync_link[i]; + dump_info.dev_data = dev_data; + dump_info.s_req_id = sync_slot->req_id; + dump_info.m_req_id = slot->req_id; + cam_req_mgr_dump_link_info(&dump_info); + return rc; + } + } + } + } + + if (link->bubble_skip) { + link->bubble_skip--; + if (link->bubble_skip == 0) + link->sync_link_sof_skip = false; + goto slave; + } + + + if (trigger == CAM_TRIGGER_POINT_SOF && + slot->real_sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { + int32_t slot_rd_idx; + + slot_rd_idx = link->req.in_q->rd_idx; + slot = &link->req.in_q->slot[slot_rd_idx]; + CAM_DBG(CAM_CRM, + "link %x idx %d req %lld state %d slot idx %d", + link->link_hdl, slot->idx, + slot->req_id, slot->status, slot_rd_idx); + if (slot->status == CRM_SLOT_STATUS_REQ_APPLIED) { + 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 row; + } + __cam_req_mgr_inc_idx( + &slot_rd_idx, 1, + link->req.in_q->num_slots); + } +row: + slot = &link->req.in_q->slot[slot_rd_idx]; + CAM_DBG(CAM_CRM, + "link %x idx %d req %lld state %d slot idx %d", + link->link_hdl, slot->idx, + slot->req_id, slot->status, slot_rd_idx); + + CAM_DBG(CAM_ISP, + "Start sync cond link %x modified sync req %lld enter", + slot->req_id, link->link_hdl); + + for (i = 0; i < link->num_sync_link; i++) { + int32_t sync_req_idx; + + //Checking if need to skip apply for this epoch + if (link->sync_link[i]->skip_sync_apply) { + CAM_INFO(CAM_ISP, + "Skipping apply on link %x as applied failed on other link %x", + link->link_hdl, + link->sync_link[i]->link_hdl); + link->sync_link[i]->skip_sync_apply = false; + return 0; + } + + //Check if other link is streaming or not + cam_req_mgr_get_device_info( + link->sync_link[i], &dev_data); + if (!dev_data.timestamp) { + CAM_INFO(CAM_ISP, "Link %x not streaming", + link->sync_link[i]->link_hdl); + return 0; + } + + sync_in_q = link->sync_link[i]->req.in_q; + if (slot->req_id == -1) { + sync_req_idx = sync_in_q->rd_idx; + } else { + sync_req_idx = __cam_req_mgr_find_slot_for_req( + link->sync_link[i]->req.in_q, slot->req_id); + } + + if (sync_req_idx == -1) { + CAM_DBG(CAM_CRM, + "Request %lld not in in_q link %x", + slot->req_id, + link->sync_link[i]->link_hdl); + if (slot->sync_mode != + CAM_REQ_MGR_SYNC_MODE_SYNC) { + CAM_DBG(CAM_CRM, + "slot not in sync mode %lld"); + __cam_req_mgr_inc_idx( + &sync_req_idx, 1, + link->req.in_q->num_slots); + goto cl; + } + return 0; + } + + __cam_req_mgr_dec_idx( + &sync_req_idx, 1, + link->sync_link[i]->req.in_q->num_slots); +cl: + sync_slot = &sync_in_q->slot[sync_req_idx]; + + //Checking if corresponding req is applied in other link or not + if (link->sync_link[i]->modified_init_sync_req != -1 && + sync_slot->req_id != -1 && + (link->sync_link[i]->modified_init_sync_req != + sync_slot->req_id) && + (link->sync_link[i]->modified_init_sync_req < + sync_slot->req_id) && + (sync_slot->status != + CRM_SLOT_STATUS_REQ_APPLIED)) { + CAM_ERR(CAM_ISP, + "ERROR Req %lld on link %x not applied", + sync_slot->req_id, + link->sync_link[i]->link_hdl); + return 0; + } + + CAM_DBG(CAM_ISP, + "Link %x modified sync req %lld enter state %d", + link->sync_link[i]->link_hdl, + sync_slot->req_id, sync_slot->status); + + __cam_req_mgr_inc_idx( + &sync_req_idx, 1, + link->sync_link[i]->req.in_q->num_slots); + + sync_slot = &sync_in_q->slot[sync_req_idx]; + + CAM_DBG(CAM_CRM, + "Check Req:%lld state %d link: %x, rc=%d", + sync_slot->req_id, sync_slot->status, + link->sync_link[i]->link_hdl, rc); + + if (sync_slot->status != CRM_SLOT_STATUS_REQ_APPLIED) { + rc = __cam_req_mgr_check_next_req_slot( + link->sync_link[i]); + if (rc) { + CAM_DBG(CAM_REQ, + "No pending req to apply to lower pd devices"); + rc = 0; + goto low; + } + rc = __cam_req_mgr_check_link_is_ready( + link->sync_link[i], sync_req_idx, true); + if (rc) { + CAM_DBG(CAM_CRM, + "Req:%lld not ready on link: %x, rc=%d", + sync_slot->req_id, + link->sync_link[i]->link_hdl, + rc); + link->skip_sync_apply = true; + return 0; + } + } +low: + CAM_DBG(CAM_ISP, + "End sync cond Link %x modified sync req %lld enter", + link->sync_link[i]->link_hdl, + sync_slot->req_id); + } + + rc = __cam_req_mgr_check_link_is_ready( + link, slot_rd_idx, true); + if (rc) { + CAM_DBG(CAM_CRM, + "M Req:%lld not ready on link: %x, rc=%d", + slot->req_id, link->link_hdl, rc); + link->skip_sync_apply = true; + return 0; + } + } + task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task frame %lld", @@ -3488,6 +3911,69 @@ static int cam_req_mgr_cb_notify_trigger( task->process_cb = &cam_req_mgr_process_trigger; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); +slave: + + /* If sync mode is on and master epoch then enqueue workqueue to apply + * request for all sync link of master. + */ + + if (trigger == CAM_TRIGGER_POINT_SOF && + ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || + (tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC && + (link->initial_sync_req != -1))) && + link->is_master && + tmp_slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC)) { + + CAM_DBG(CAM_CRM, + "In sync mode req %lld tmp mode % real mode %d sync mode %d link %x ", + slot->req_id, tmp_slot->sync_mode, + tmp_slot->real_sync_mode, + slot->sync_mode, link->link_hdl); + + dev_name = __cam_req_mgr_dev_handle_to_name( + trigger_data->dev_hdl, link); + + for (i = 0; i < link->num_sync_link; i++) { + + task = cam_req_mgr_workq_get_task( + link->sync_link[i]->workq); + if (!task) { + CAM_ERR(CAM_CRM, "No empty task frame %lld", + trigger_data->frame_id); + rc = -EBUSY; + goto end; + } + + sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, + link->sync_link[i]); + + if (sync_dev_hdl == -1) { + CAM_ERR(CAM_CRM, "Sync dev hdl is null"); + goto end; + } + CAM_DBG(CAM_CRM, "Sync link 0x%x sync dev hdl %x", + link->sync_link[i]->link_hdl, sync_dev_hdl); + + cam_req_mgr_get_device_info( + link->sync_link[i], &dev_data); + + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF; + notify_trigger = (struct cam_req_mgr_trigger_notify *) + &task_data->u; + notify_trigger->frame_id = dev_data.frame_id; + notify_trigger->link_hdl = link->sync_link[i]->link_hdl; + notify_trigger->dev_hdl = sync_dev_hdl; + notify_trigger->trigger = trigger_data->trigger; + notify_trigger->req_id = trigger_data->req_id; + notify_trigger->sof_timestamp_val = + trigger_data->sof_timestamp_val; + task->process_cb = &cam_req_mgr_process_trigger; + rc = cam_req_mgr_workq_enqueue_task(task, + link->sync_link[i], CRM_TASK_PRIORITY_0); + } + } + end: return rc; } @@ -3832,6 +4318,8 @@ int cam_req_mgr_destroy_session( __cam_req_mgr_free_link(link); } } + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) + clear_bit(i, g_crm_core_dev->bitmap); list_del(&cam_session->entry); mutex_unlock(&cam_session->lock); mutex_destroy(&cam_session->lock); @@ -4186,11 +4674,66 @@ end: return rc; } +/** + * __cam_req_mgr_set_master_link() + * + * @brief : Select master link based on the activate sequence + * + * @link : pointer to array of links + * @num_of_links : number of links to be sync + * + * @return : void + * + */ +static void __cam_req_mgr_set_master_link( + struct cam_req_mgr_core_link **link, + int32_t num_of_links) +{ + int i = 0, j = 0, k = 0; + int idx = -1; + + idx = find_first_bit(g_crm_core_dev->bitmap, + MAXIMUM_LINKS_PER_SESSION); + + for (i = 0; i < num_of_links; i++) { + + CAM_DBG(CAM_CRM, "idx %d, link%d 0x%x active seq %d", + idx, i, link[i]->link_hdl, + link[i]->activate_seq); + + if (link[i]->activate_seq == idx) { + + link[i]->is_master = true; + CAM_DBG(CAM_CRM, "Master link 0x%x num of links %d ", + link[i]->link_hdl, num_of_links); + + for (j = 0, k = 0; j < num_of_links; j++) { + if (link[i]->link_hdl != + link[j]->link_hdl) { + + link[i]->sync_link[k] = link[j]; + link[i]->num_sync_link++; + + link[j]->sync_link[0] = link[i]; + link[j]->num_sync_link = 1; + link[j]->is_master = false; + + k++; + } + } + } + + link[i]->initial_skip = + g_crm_core_dev->max_delay - link[i]->max_delay; + CAM_DBG(CAM_CRM, "link %x initial skip %d", + link[i]->link_hdl, link[i]->initial_skip); + } +} + int cam_req_mgr_sync_config( struct cam_req_mgr_sync_mode *sync_info) { - int i, j, rc = 0; - int sync_idx = 0; + int i, j, rc = 0; struct cam_req_mgr_core_session *cam_session; struct cam_req_mgr_core_link *link[MAX_LINKS_PER_SESSION]; @@ -4212,10 +4755,12 @@ int cam_req_mgr_sync_config( 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]); - return -EINVAL; + for (i = 0; i < sync_info->num_links; i++) { + if (!sync_info->link_hdls[i]) { + CAM_WARN(CAM_CRM, "Invalid link handles 0x%x", + sync_info->link_hdls[i]); + return -EINVAL; + } } mutex_lock(&g_crm_core_dev->crm_lock); @@ -4231,60 +4776,56 @@ int cam_req_mgr_sync_config( mutex_lock(&cam_session->lock); for (i = 0; i < sync_info->num_links; i++) { - - if (!sync_info->link_hdls[i]) { - CAM_ERR(CAM_CRM, "link handle %d is null", i); - rc = -EINVAL; - goto done; - } - link[i] = cam_get_device_priv(sync_info->link_hdls[i]); if (!link[i]) { CAM_ERR(CAM_CRM, "link%d NULL pointer", i); rc = -EINVAL; goto done; } + CAM_DBG(CAM_CRM, "Link hdl %x sync mode %d", + link[i]->link_hdl, + sync_info->sync_mode); link[i]->sync_link_sof_skip = false; + link[i]->is_master = false; + link[i]->in_msync_mode = false; link[i]->initial_sync_req = -1; - link[i]->num_sync_links = 0; + link[i]->num_sync_link = 0; + link[i]->bubble_skip = 0; + link[i]->sync_frame_id = 0; + link[i]->is_sync_req = true; + link[i]->modified_init_sync_req = -1; for (j = 0; j < sync_info->num_links-1; j++) link[i]->sync_link[j] = NULL; + + g_crm_core_dev->max_delay = CAM_PIPELINE_DELAY_0; + + if (g_crm_core_dev->max_delay < link[i]->max_delay) + g_crm_core_dev->max_delay = link[i]->max_delay; } if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < sync_info->num_links; i++) { - j = 0; - sync_idx = 0; - CAM_DBG(CAM_REQ, "link %x adds sync link:", - link[i]->link_hdl); - while (j < sync_info->num_links) { - if (i != j) { - link[i]->sync_link[sync_idx++] = - link[j]; - link[i]->num_sync_links++; - CAM_DBG(CAM_REQ, "sync_link[%d] : %x", - sync_idx-1, link[j]->link_hdl); - } - j++; - } - link[i]->initial_skip = true; - link[i]->sof_timestamp = 0; - } + __cam_req_mgr_set_master_link(link, sync_info->num_links); + } else { - for (j = 0; j < sync_info->num_links; j++) { - link[j]->initial_skip = true; - link[j]->sof_timestamp = 0; + for (i = 0; i < sync_info->num_links; i++) { + /* + * Reset below info after the mode is configured + * to NO-SYNC mode since they may be overridden + * if the sync config is invoked after SOF comes. + */ + link[i]->initial_skip = 0; + link[i]->sof_timestamp = 0; + link[i]->num_sync_link = 0; + link[i]->initial_sync_req = -1; + link[i]->modified_init_sync_req = -1; } } cam_session->sync_mode = sync_info->sync_mode; - CAM_DBG(CAM_REQ, - "Sync config completed on %d links with sync_mode %d", - sync_info->num_links, sync_info->sync_mode); done: mutex_unlock(&cam_session->lock); @@ -4362,13 +4903,13 @@ end: int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) { - int rc = 0; - int i, j; - struct cam_req_mgr_core_link *link = NULL; - - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_link_evt_data evt_data; - int init_timeout = 0; + int rc = 0, i, j; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_link_evt_data evt_data; + int init_timeout = 0; + long idx; + bool bit; if (!control) { CAM_ERR(CAM_CRM, "Control command is NULL"); @@ -4399,6 +4940,22 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) { spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_READY; + do { + idx = find_first_zero_bit( + g_crm_core_dev->bitmap, + MAXIMUM_LINKS_PER_SESSION); + if (idx >= MAXIMUM_LINKS_PER_SESSION) { + CAM_ERR(CAM_SYNC, + "Error: Unable to allocate link bit"); + rc = -ENOMEM; + break; + } + bit = test_and_set_bit( + idx, g_crm_core_dev->bitmap); + } while (bit); + link->activate_seq = idx; + CAM_DBG(CAM_CRM, "link hdl 0x%x activate idx %d", + link->link_hdl, link->activate_seq); spin_unlock_bh(&link->link_state_spin_lock); if (control->init_timeout[i]) link->skip_init_frame = true; @@ -4444,6 +5001,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->state = CAM_CRM_LINK_STATE_IDLE; link->skip_init_frame = false; crm_timer_exit(&link->watchdog); + clear_bit(link->activate_seq, g_crm_core_dev->bitmap); + link->activate_seq = -1; spin_unlock_bh(&link->link_state_spin_lock); CAM_DBG(CAM_CRM, "De-activate link: 0x%x", link->link_hdl); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 6e6415c85fc0..1bbc47f71ff6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -263,7 +263,8 @@ struct cam_req_mgr_req_tbl { * - members updated due to external events * @recover : if user enabled recovery for this request. * @req_id : mask tracking which all devices have request ready - * @sync_mode : Sync mode in which req id in this slot has to applied + * @sync_mode : Modified sync mode in which req id in this slot has to applied + * @real_sync_mode : Actual sync mode in which req id in this slot has to applied * @additional_timeout : Adjusted watchdog timeout value associated with * this request */ @@ -274,6 +275,7 @@ struct cam_req_mgr_slot { int32_t recover; int64_t req_id; int32_t sync_mode; + int32_t real_sync_mode; int32_t additional_timeout; }; @@ -355,7 +357,7 @@ struct cam_req_mgr_connected_device { * @lock : mutex lock to guard link data operations * @link_state_spin_lock : spin lock to protect link state variable * @sync_link : array of pointer to the sync link for synchronization - * @num_sync_links : num of links sync associated with this link + * @num_sync_link : total number of sync links * @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. @@ -365,11 +367,14 @@ struct cam_req_mgr_connected_device { * @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 + * @initial_skip : Flag to determine if initial req need to skip for + * diff pd + * @is_sync_req : flag used for deciding sync and non-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 + * @modified_init_sync_req : Modified initial req which is required to sync + * with the other link * @retry_cnt : Counter that tracks number of attempts to apply * the same req * @is_shutdown : Flag to indicate if link needs to be disconnected @@ -384,6 +389,10 @@ struct cam_req_mgr_connected_device { * case of long exposure use case * @last_sof_trigger_jiffies : Record the jiffies of last sof trigger jiffies * @wq_congestion : Indicates if WQ congestion is detected or not + * @activate_seq : sequence in which link is activated + * @frame_id : current frame id + * @sync_frame_id : current frame id of sync link + * @bubble_skip : req to skip on bubble */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -399,19 +408,22 @@ struct cam_req_mgr_core_link { void *parent; struct mutex lock; spinlock_t link_state_spin_lock; - struct cam_req_mgr_core_link - *sync_link[MAXIMUM_LINKS_PER_SESSION - 1]; - int32_t num_sync_links; + struct cam_req_mgr_core_link *sync_link[ + MAXIMUM_LINKS_PER_SESSION]; + int32_t num_sync_link; 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; + uint32_t initial_skip; + bool is_sync_req; bool in_msync_mode; int64_t initial_sync_req; + int64_t modified_init_sync_req; uint32_t retry_cnt; bool is_shutdown; + uint64_t sof_boottime; uint64_t sof_timestamp; uint64_t prev_sof_timestamp; bool dual_trigger; @@ -420,6 +432,11 @@ struct cam_req_mgr_core_link { bool skip_init_frame; uint64_t last_sof_trigger_jiffies; bool wq_congestion; + int32_t activate_seq; + uint64_t frame_id; + uint64_t sync_frame_id; + int32_t bubble_skip; + bool skip_sync_apply; }; /** @@ -453,11 +470,33 @@ struct cam_req_mgr_core_session { * @session_head : list head holding sessions * @crm_lock : mutex lock to protect session creation & destruction * @recovery_on_apply_fail : Recovery on apply failure using debugfs. + * @bitmap : bitmap to store index of link + * @max_delay : max pipeline delay in a session */ struct cam_req_mgr_core_device { struct list_head session_head; struct mutex crm_lock; bool recovery_on_apply_fail; + DECLARE_BITMAP(bitmap, MAXIMUM_LINKS_PER_SESSION); + uint32_t max_delay; +}; + +/** + * struct cam_req_mgr_dump_link_data + * - Dump data + * @m_link : master link handle + * @s_link : slave link handle + * @m_req_id : master req id + * @s_req_id : slave req id + * @dev_info : current timing data of slave link + * + */ +struct cam_req_mgr_dump_link_data { + struct cam_req_mgr_core_link *m_link; + struct cam_req_mgr_core_link *s_link; + uint64_t m_req_id; + uint64_t s_req_id; + struct cam_req_mgr_dev_info dev_data; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index b6807ed4a7f0..e8e4f941a39c 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -22,6 +22,7 @@ struct cam_req_mgr_apply_request; struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; struct cam_req_mgr_dump_info; +struct cam_req_mgr_request_change_state; /* Request Manager -- camera device driver interface */ /** @@ -33,8 +34,9 @@ struct cam_req_mgr_dump_info; * userspace * @cam_req_mgr_notify_timer : start the timer */ -typedef int (*cam_req_mgr_notify_trigger)(struct cam_req_mgr_trigger_notify *); -typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); +typedef int (*cam_req_mgr_notify_trigger)( + struct cam_req_mgr_trigger_notify *); +typedef bool (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *); typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); @@ -48,8 +50,9 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); * @cam_req_mgr_notify_frame_skip: CRM asks device to apply setting for * frame skip * @cam_req_mgr_flush_req : Flush or cancel request - * cam_req_mgr_process_evt : generic events + * @cam_req_mgr_process_evt : generic events * @cam_req_mgr_dump_req : dump request + * @cam_req_mgr_change_state : CRM asks device to change its state */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); @@ -59,6 +62,8 @@ typedef int (*cam_req_mgr_notify_frame_skip)( typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); +typedef int (*cam_req_mgr_change_state)( + struct cam_req_mgr_request_change_state *); /** * @brief : cam_req_mgr_crm_cb - func table @@ -87,15 +92,17 @@ struct cam_req_mgr_crm_cb { * @flush_req : payload to flush request * @process_evt : payload to generic event * @dump_req : payload to dump request + * @change_state : payload to change state */ struct cam_req_mgr_kmd_ops { - cam_req_mgr_get_dev_info get_dev_info; - cam_req_mgr_link_setup link_setup; - cam_req_mgr_apply_req apply_req; + cam_req_mgr_get_dev_info get_dev_info; + cam_req_mgr_link_setup link_setup; + cam_req_mgr_apply_req apply_req; cam_req_mgr_notify_frame_skip notify_frame_skip; - cam_req_mgr_flush_req flush_req; - cam_req_mgr_process_evt process_evt; - cam_req_mgr_dump_req dump_req; + cam_req_mgr_flush_req flush_req; + cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; + cam_req_mgr_change_state change_state; }; /** @@ -216,6 +223,7 @@ enum cam_req_mgr_link_evt_type { * @trigger : trigger point of this notification, CRM will send apply * only to the devices which subscribe to this point. * @sof_timestamp_val: Captured time stamp value at sof hw event + * @sof_boottime : Captured boot time stamp value at sof hw event * @req_id : req id which returned buf_done * @trigger_id: ID to differentiate between the trigger devices */ @@ -225,6 +233,7 @@ struct cam_req_mgr_trigger_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; + uint64_t sof_boottime; uint64_t req_id; int32_t trigger_id; }; @@ -249,6 +258,8 @@ struct cam_req_mgr_timer_notify { * @frame_id : frame id for internal tracking * @trigger : trigger point of this notification, CRM will send apply * @sof_timestamp_val : Captured time stamp value at sof hw event + * @sof_boottime_val : Captured boottime stamp value at sof hw event + * @need_recovery : flag to check if recovery is needed * @error : what error device hit while processing this req */ struct cam_req_mgr_error_notify { @@ -258,6 +269,8 @@ struct cam_req_mgr_error_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; + uint64_t sof_boottime_val; + bool need_recovery; enum cam_req_mgr_device_error error; }; @@ -302,6 +315,7 @@ struct cam_req_mgr_notify_stop { * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client * @trigger_on : This device provides trigger + * @sof_ts_cb : callback to real time drivers */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -310,6 +324,7 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; + int32_t (*sof_ts_cb)(int32_t dev_hdl, void *data); }; /** @@ -408,4 +423,37 @@ struct cam_req_mgr_dump_info { int32_t link_hdl; int32_t dev_hdl; }; + +/** + * struct cam_req_mgr_dev_info + * @link_hdl : link identifier + * @state : Current substate for the activated state. + * @timestamp : time stamp for the sof event + * @boot_time : boot time stamp for the sof event + * @frame_id : frame id + * @is_applied : if ISP is in applied state + * + */ +struct cam_req_mgr_dev_info { + int32_t link_hdl; + uint32_t state; + uint64_t timestamp; + uint64_t boot_time; + uint64_t frame_id; + bool is_applied; +}; + +/** + * struct cam_req_mgr_request_change_state + * @link_hdl : link identifier + * @dev_hdl : device handle or identifier + * @req_id : request id + * + */ +struct cam_req_mgr_request_change_state { + int32_t link_hdl; + int32_t dev_hdl; + uint64_t req_id; +}; + #endif diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 9c0d7abd043d..c9c2906ce56c 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -410,6 +410,7 @@ int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info) strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name)); info->p_delay = 1; info->trigger = CAM_TRIGGER_POINT_SOF; + info->sof_ts_cb = NULL; return 0; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 8cda6c3831c8..2d71dc8c00d2 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1785,6 +1785,8 @@ int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info) strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name)); info->p_delay = CAM_FLASH_PIPELINE_DELAY; info->trigger = CAM_TRIGGER_POINT_SOF; + info->sof_ts_cb = NULL; + return 0; } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 32b05eadfc64..19dbffc4a2bc 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1129,6 +1129,7 @@ int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info) else info->p_delay = 2; info->trigger = CAM_TRIGGER_POINT_SOF; + info->sof_ts_cb = NULL; return rc; } From ae6cf7f33140fb5067e07bf52d290cbed96b6cf8 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 16 Mar 2021 15:18:00 +0530 Subject: [PATCH 707/790] msm: camera: cdm: Add cdm debug status register This change adds missing cdm debug status register offsets for cdm version 1.0 that are read during cdm hang. CRs-Fixed: 2898496 Change-Id: I3a83d13f6b18231561973054845cb87b1ffc4b2d Signed-off-by: Chandan Kumar Jha --- drivers/cam_cdm/cam_cdm_hw_reg_1_0.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h b/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h index f1564dfafcbd..d1505eeef72a 100644 --- a/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h +++ b/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #include "cam_cdm.h" @@ -71,6 +71,14 @@ static struct cam_cdm_perf_mon_regs cdm_1_0_perf_mon0 = { .perf_mon_2 = 0x11c, }; +static struct cam_cdm_comp_wait_status cdm_1_0_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_1_0_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + static struct cam_cdm_common_regs cdm_hw_1_0_cmn_reg_offset = { .cdm_hw_version = 0x0, .cam_version = &cdm_hw_1_0_titan_version, @@ -100,7 +108,10 @@ static struct cam_cdm_common_regs cdm_hw_1_0_cmn_reg_offset = { &cdm_hw_1_0_bl_pending_req0, NULL, }, - .comp_wait = { NULL, NULL }, + .comp_wait = { + &cdm_1_0_comp_wait_status0, + &cdm_1_0_comp_wait_status1, + }, .perf_mon = { &cdm_1_0_perf_mon0, NULL, From 647861d3442f833b96720335ef85a6ca8908073f Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Fri, 29 Jan 2021 15:40:47 +0800 Subject: [PATCH 708/790] msm: camera: isp: Get the first active req during bubble Sometimes, UMD reports nonincrementing shutter request id issue during monkey test on sHDR usecase, isp reports last one req in active req list during bubble, so if the active req count is 2, we will meet this issue. This change gets the first active req during bubble in case the active req cnt is 2. CRs-Fixed: 2885087 Change-Id: I67d1ecfe9c88123e6d0887383961bfc676455a0d Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 36 +++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d4ba000210aa..2ab653a7e77e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1993,6 +1993,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, { bool rc = false; uint64_t request_id = 0; + uint32_t sof_event_status = CAM_REQ_MGR_SOF_EVENT_SUCCESS; struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; @@ -2100,15 +2101,36 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, 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); - if ((req->request_id > ctx_isp->reported_req_id) - && !req_isp->bubble_report) { - request_id = req->request_id; - ctx_isp->reported_req_id = request_id; - } - __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, - CAM_REQ_MGR_SOF_EVENT_ERROR); + /* + * Update the record before req pointer to + * other invalid req. + */ __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); + + /* + * Get the req again from active_req_list in case + * the active req cnt is 2. + */ + list_for_each_entry(req, &ctx->active_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if ((!req_isp->bubble_report) && + (req->request_id > ctx_isp->reported_req_id)) { + request_id = req->request_id; + ctx_isp->reported_req_id = request_id; + CAM_DBG(CAM_ISP, + "ctx %d reported_req_id update to %lld", + ctx->ctx_id, ctx_isp->reported_req_id); + break; + } + } + + if ((request_id != 0) && req_isp->bubble_detected) + sof_event_status = CAM_REQ_MGR_SOF_EVENT_ERROR; + + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, + sof_event_status); + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; CAM_DBG(CAM_ISP, "next Substate[%s]", __cam_isp_ctx_substate_val_to_type( From ac2aea5b619b2cb006ce3eaaa484b8b81609483b Mon Sep 17 00:00:00 2001 From: Thirupathi Reddy R Date: Fri, 19 Mar 2021 11:25:59 +0530 Subject: [PATCH 709/790] Revert "msm: camera: cpas: workaround fix for Shima-CAMNOC RDI latency buffer" This reverts commit b1f064f8058e453b1bf96cd03a685fb712d21d05. Change-Id: I39ed14906fedc2cd6e7e87b0cf2652a1b08b246a Signed-off-by: Thirupathi Reddy R --- drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 15 +++++++-------- .../cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 14 ++------------ 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index 2c5bd4048e53..49978a0f5279 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -270,7 +270,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ - .value = 0x66666666, + .value = 0x66665433, }, .priority_lut_high = { .enable = true, @@ -402,7 +402,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ - .value = 0x66666666, + .value = 0x66665433, }, .priority_lut_high = { .enable = true, @@ -468,7 +468,7 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ - .value = 0x66666666, + .value = 0x66665433, }, .priority_lut_high = { .enable = true, @@ -595,14 +595,14 @@ static struct cam_camnoc_specific .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ - .value = 0x12121212, + .value = 0x13131313, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ - .value = 0x12121212, + .value = 0x13131313, }, }, { @@ -662,20 +662,19 @@ static struct cam_camnoc_specific .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ .value = 0x2, }, - // TITAN_A_CAMNOC_cam_noc_amm_nrt_niu_0_qosgen_Shaping_Low | 0xAC44320 .qosgen_shaping_low = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ - .value = 0x23232323, + .value = 0x24242424, }, .qosgen_shaping_high = { .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ - .value = 0x23232323, + .value = 0x24242424, }, }, { diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index f628ba453d6c..e556ca6f1857 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1448,7 +1448,6 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, struct cam_hw_intf *icp_dev_intf = NULL; struct cam_hw_intf *dev_intf = NULL; struct cam_icp_clk_update_cmd clk_upd_cmd; - uint32_t camera_hw_version; ipe0_dev_intf = hw_mgr->ipe0_dev_intf; ipe1_dev_intf = hw_mgr->ipe1_dev_intf; @@ -1471,17 +1470,8 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, id = CAM_ICP_IPE_CMD_UPDATE_CLK; } - cam_cpas_get_cpas_hw_version(&camera_hw_version); - if ((camera_hw_version == 0x570200)&& - (curr_clk_rate > ctx_data->clk_info.clk_rate[CAM_MAX_VOTE-1]) && - (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS)) { - - curr_clk_rate = ctx_data->clk_info.clk_rate[CAM_MAX_VOTE-1]; - } - - CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d, ver %x", curr_clk_rate, - ctx_data->icp_dev_acquire_info->dev_type, camera_hw_version); - + CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d", curr_clk_rate, + ctx_data->icp_dev_acquire_info->dev_type); clk_upd_cmd.curr_clk_rate = curr_clk_rate; clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag; clk_upd_cmd.clk_level = -1; From be6b59fb715a2dc5423889c9ba17f68345c368c1 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Tue, 16 Mar 2021 15:18:00 +0530 Subject: [PATCH 710/790] msm: camera: cdm: Add cdm debug status register This change adds missing cdm debug status register offsets for cdm version 1.0 that are read during cdm hang. CRs-Fixed: 2898496 Change-Id: I3a83d13f6b18231561973054845cb87b1ffc4b2d Signed-off-by: Chandan Kumar Jha --- drivers/cam_cdm/cam_cdm_hw_reg_1_0.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h b/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h index f1564dfafcbd..d1505eeef72a 100644 --- a/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h +++ b/drivers/cam_cdm/cam_cdm_hw_reg_1_0.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #include "cam_cdm.h" @@ -71,6 +71,14 @@ static struct cam_cdm_perf_mon_regs cdm_1_0_perf_mon0 = { .perf_mon_2 = 0x11c, }; +static struct cam_cdm_comp_wait_status cdm_1_0_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_1_0_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + static struct cam_cdm_common_regs cdm_hw_1_0_cmn_reg_offset = { .cdm_hw_version = 0x0, .cam_version = &cdm_hw_1_0_titan_version, @@ -100,7 +108,10 @@ static struct cam_cdm_common_regs cdm_hw_1_0_cmn_reg_offset = { &cdm_hw_1_0_bl_pending_req0, NULL, }, - .comp_wait = { NULL, NULL }, + .comp_wait = { + &cdm_1_0_comp_wait_status0, + &cdm_1_0_comp_wait_status1, + }, .perf_mon = { &cdm_1_0_perf_mon0, NULL, From f6f83ee97d3a669258d4b8a32d4e25a82c1220f0 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Fri, 19 Mar 2021 11:07:33 +0530 Subject: [PATCH 711/790] Revert "msm: camera: core: Allocate memory for flush req array dynamically" This reverts commit 018d8dae943321b3ce7138090855c94831124846. CRs-Fixed: 2901141 Change-Id: I13e91b3a2fb8b9cad144173a02ba74092671c3ab Signed-off-by: Ravikishore Pampana --- drivers/cam_core/cam_context_utils.c | 104 +++------------------------ drivers/cam_core/cam_hw_mgr_intf.h | 6 +- 2 files changed, 14 insertions(+), 96 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 0e4ed8843728..0abd3ac3ebff 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -602,7 +602,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) struct cam_hw_flush_args flush_args; struct list_head temp_list; struct cam_ctx_request *req; - uint32_t i, j; + uint32_t i; int rc = 0; bool free_req; @@ -618,31 +618,15 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) INIT_LIST_HEAD(&temp_list); spin_lock(&ctx->lock); list_splice_init(&ctx->pending_req_list, &temp_list); - flush_args.num_req_pending = 0; - list_for_each_entry(req, &temp_list, list) { - flush_args.num_req_pending++; - } spin_unlock(&ctx->lock); - flush_args.flush_req_pending = kcalloc(flush_args.num_req_pending, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_pending) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_pending", - ctx->dev_name, ctx->ctx_id); - mutex_unlock(&ctx->sync_mutex); - goto err; - } - if (cam_debug_ctx_req_list & ctx->dev_id) CAM_INFO(CAM_CTXT, "[%s][%d] : Moving all pending requests from pending_list to temp_list", ctx->dev_name, ctx->ctx_id); + flush_args.num_req_pending = 0; flush_args.last_flush_req = ctx->last_flush_req; - - j = 0; while (true) { spin_lock(&ctx->lock); if (list_empty(&temp_list)) { @@ -657,7 +641,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) spin_unlock(&ctx->lock); req->flushed = 1; - flush_args.flush_req_pending[j++] = + flush_args.flush_req_pending[flush_args.num_req_pending++] = req->req_priv; free_req = false; @@ -708,31 +692,11 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } mutex_unlock(&ctx->sync_mutex); - kfree(flush_args.flush_req_pending); - flush_args.flush_req_pending = NULL; - if (ctx->hw_mgr_intf->hw_flush) { - spin_lock(&ctx->lock); flush_args.num_req_active = 0; - list_for_each_entry(req, &ctx->active_req_list, list) { - flush_args.num_req_active++; - } - spin_unlock(&ctx->lock); - - flush_args.flush_req_active = kcalloc(flush_args.num_req_active, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_active) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_active", - ctx->dev_name, ctx->ctx_id); - goto err; - } - spin_lock(&ctx->lock); - j = 0; list_for_each_entry(req, &ctx->active_req_list, list) { - flush_args.flush_req_active[j++] + flush_args.flush_req_active[flush_args.num_req_active++] = req->req_priv; } spin_unlock(&ctx->lock); @@ -745,9 +709,6 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } } - kfree(flush_args.flush_req_active); - flush_args.flush_req_active = NULL; - INIT_LIST_HEAD(&temp_list); spin_lock(&ctx->lock); list_splice_init(&ctx->active_req_list, &temp_list); @@ -801,8 +762,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) CAM_DBG(CAM_CTXT, "[%s] X: NRT flush ctx", ctx->dev_name); -err: - return rc; + return 0; } int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, @@ -822,25 +782,6 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, flush_args.num_req_active = 0; mutex_lock(&ctx->sync_mutex); spin_lock(&ctx->lock); - list_for_each_entry(req, &ctx->pending_req_list, list) { - if (req->request_id != cmd->req_id) - continue; - flush_args.num_req_pending++; - } - spin_unlock(&ctx->lock); - - flush_args.flush_req_pending = kcalloc(flush_args.num_req_pending, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_pending) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_pending", - ctx->dev_name, ctx->ctx_id); - goto err; - } - - spin_lock(&ctx->lock); - i = 0; list_for_each_entry(req, &ctx->pending_req_list, list) { if (req->request_id != cmd->req_id) continue; @@ -853,41 +794,24 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, list_del_init(&req->list); req->flushed = 1; - flush_args.flush_req_pending[i++] = + flush_args.flush_req_pending[flush_args.num_req_pending++] = req->req_priv; break; } spin_unlock(&ctx->lock); + mutex_unlock(&ctx->sync_mutex); if (ctx->hw_mgr_intf->hw_flush) { if (!flush_args.num_req_pending) { spin_lock(&ctx->lock); - list_for_each_entry(req, &ctx->active_req_list, list) { - if (req->request_id != cmd->req_id) - continue; - flush_args.num_req_active++; - } - spin_unlock(&ctx->lock); - - flush_args.flush_req_active = kcalloc(flush_args.num_req_active, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_pending) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_pending", - ctx->dev_name, ctx->ctx_id); - goto err; - } - - spin_lock(&ctx->lock); - i = 0; list_for_each_entry(req, &ctx->active_req_list, list) { if (req->request_id != cmd->req_id) continue; list_del_init(&req->list); - flush_args.flush_req_active[i++] = + flush_args.flush_req_active[ + flush_args.num_req_active++] = req->req_priv; break; } @@ -899,10 +823,6 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, flush_args.flush_type = CAM_FLUSH_TYPE_REQ; ctx->hw_mgr_intf->hw_flush( ctx->hw_mgr_intf->hw_mgr_priv, &flush_args); - kfree(flush_args.flush_req_pending); - flush_args.flush_req_pending = NULL; - kfree(flush_args.flush_req_active); - flush_args.flush_req_active = NULL; } } @@ -958,9 +878,7 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, } CAM_DBG(CAM_CTXT, "[%s] X: NRT flush req", ctx->dev_name); -err: - mutex_unlock(&ctx->sync_mutex); - return rc; + return 0; } int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 64149fb7c662..359f54850ce8 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HW_MGR_INTF_H_ @@ -289,9 +289,9 @@ struct cam_hw_config_args { struct cam_hw_flush_args { void *ctxt_to_hw_map; uint32_t num_req_pending; - void **flush_req_pending; + void *flush_req_pending[20]; uint32_t num_req_active; - void **flush_req_active; + void *flush_req_active[20]; enum flush_type_t flush_type; uint32_t last_flush_req; }; From 0b798d0f8cb984e199f0c153b9dc9bdc6c57522b Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Fri, 19 Mar 2021 11:05:29 +0800 Subject: [PATCH 712/790] msm: camera: reqmgr: Reset the status for next req if bubble If req#N in slot idx, and this req meets bubble issue, then the req#(N+1) in slot (idx+1) may also be applied, and its status is APPLIED. If req#(N+1) applies failed after finishing bubble recovery due to some reasons, but we still can move to next slot since the status of slot (idx+1) is already APPLIED. This change resets the status of slot (idx+1) to ADDED if it is APPLIED during processing error. CRs-Fixed: 2902809 Change-Id: I32f318569ad8f24fdf0f324603f4ea0036867e98 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 27c6e22b594b..36a105be5a1d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2747,6 +2747,14 @@ int cam_req_mgr_process_error(void *priv, void *data) in_q->rd_idx = idx; in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; + /* The next req may also be applied */ + idx = in_q->rd_idx; + __cam_req_mgr_inc_idx(&idx, 1, + link->req.l_tbl->num_slots); + + if (in_q->slot[idx].status == CRM_SLOT_STATUS_REQ_APPLIED) + in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; + spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_ERR; spin_unlock_bh(&link->link_state_spin_lock); From 21fea5466493e99cd4cd9e7a72479a042dac678e Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Thu, 25 Feb 2021 16:32:33 +0530 Subject: [PATCH 713/790] msm: camera: sensor: Change regulator get,put to devres entry This change modifies regulator_get, regulator_put to devres entry. Devres is linked list of arbitrarily sized memory areas associated with a struct device. Each devres entry is associated with a release function. All devres entries are released on driver detach. This avoids potential leaking of resources on driver detach or having half broken failure path implementation in probe call which would leak resources when failure occurs. CRs-Fixed: 2890861 Change-Id: Ibd46bc37bd6e31aeb2a5ea90ed75a1f596b57bf9 Signed-off-by: shiwgupt --- .../cam_actuator/cam_actuator_soc.c | 6 ++- .../cam_eeprom/cam_eeprom_soc.c | 4 +- .../cam_sensor_module/cam_ois/cam_ois_soc.c | 6 ++- .../cam_sensor/cam_sensor_soc.c | 7 +++- .../cam_sensor_utils/cam_sensor_util.c | 38 ++++++++++--------- .../cam_sensor_utils/cam_sensor_util.h | 5 ++- 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c index 0248effdfbe4..cb852423a228 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -56,6 +56,10 @@ int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl, CAM_DBG(CAM_ACTUATOR, "cci-device %d", a_ctrl->cci_num); } + rc = cam_sensor_util_regulator_powerup(soc_info); + if (rc < 0) + return rc; + if (!soc_info->gpio_data) { CAM_DBG(CAM_ACTUATOR, "No GPIO found"); rc = 0; diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c index 33f80b0c9716..c725beb0af3f 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -380,5 +380,7 @@ int cam_eeprom_parse_dt(struct cam_eeprom_ctrl_t *e_ctrl) } } + rc = cam_sensor_util_regulator_powerup(soc_info); + return rc; } diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c index 9c14d87e233d..510c81d9e9f3 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -41,6 +41,10 @@ static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl) return rc; } + rc = cam_sensor_util_regulator_powerup(soc_info); + if (rc < 0) + return rc; + if (!soc_info->gpio_data) { CAM_INFO(CAM_OIS, "No GPIO found"); return 0; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c index 2c25ee0aa6f0..d5cfe48223a5 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -268,6 +268,11 @@ int32_t cam_sensor_parse_dt(struct cam_sensor_ctrl_t *s_ctrl) return rc; } } + + rc = cam_sensor_util_regulator_powerup(soc_info); + if (rc < 0) + return rc; + rc = msm_sensor_init_default_params(s_ctrl); if (rc < 0) { CAM_ERR(CAM_SENSOR, diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 4dde033a2fbd..4147c1dc7409 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -64,6 +64,27 @@ int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns) return rc; } +int32_t cam_sensor_util_regulator_powerup(struct cam_hw_soc_info *soc_info) +{ + int32_t i, rc = 0; + /* Initialize regulators to default parameters */ + for (i = 0; i < soc_info->num_rgltr; i++) { + soc_info->rgltr[i] = devm_regulator_get(soc_info->dev, + soc_info->rgltr_name[i]); + if (IS_ERR_OR_NULL(soc_info->rgltr[i])) { + rc = PTR_ERR(soc_info->rgltr[i]); + rc = rc ? rc : -EINVAL; + CAM_ERR(CAM_ACTUATOR, "get failed for regulator %s %d", + soc_info->rgltr_name[i], rc); + return rc; + } + CAM_DBG(CAM_ACTUATOR, "get for regulator %s", + soc_info->rgltr_name[i]); + } + + return rc; +} + int32_t delete_request(struct i2c_settings_array *i2c_array) { struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL; @@ -1974,10 +1995,6 @@ static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl, ps->data[0] = soc_info->rgltr[j]; - - regulator_put( - soc_info->rgltr[j]); - soc_info->rgltr[j] = NULL; } } } @@ -2057,11 +2074,6 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, CAM_DBG(CAM_SENSOR, "Enable cam_clk: %d", j); - soc_info->rgltr[j] = - regulator_get( - soc_info->dev, - soc_info->rgltr_name[j]); - if (IS_ERR_OR_NULL( soc_info->rgltr[j])) { rc = PTR_ERR( @@ -2156,9 +2168,6 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, CAM_DBG(CAM_SENSOR, "Enable Regulator"); vreg_idx = power_setting->seq_val; - soc_info->rgltr[vreg_idx] = - regulator_get(soc_info->dev, - soc_info->rgltr_name[vreg_idx]); if (IS_ERR_OR_NULL( soc_info->rgltr[vreg_idx])) { rc = PTR_ERR(soc_info->rgltr[vreg_idx]); @@ -2281,8 +2290,6 @@ power_up_failed: power_setting->data[0] = soc_info->rgltr[vreg_idx]; - regulator_put(soc_info->rgltr[vreg_idx]); - soc_info->rgltr[vreg_idx] = NULL; } else { CAM_ERR(CAM_SENSOR, "seq_val:%d > num_vreg: %d", power_setting->seq_val, num_vreg); @@ -2449,9 +2456,6 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, } ps->data[0] = soc_info->rgltr[ps->seq_val]; - regulator_put( - soc_info->rgltr[ps->seq_val]); - soc_info->rgltr[ps->seq_val] = NULL; } else { CAM_ERR(CAM_SENSOR, "seq_val:%d > num_vreg: %d", diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 66731008826b..4fc0ee857ae9 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_UTIL_H_ @@ -41,6 +41,9 @@ int msm_camera_pinctrl_init int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns); +int32_t cam_sensor_util_regulator_powerup( + struct cam_hw_soc_info *soc_info); + int32_t cam_sensor_util_write_qtimer_to_io_buffer( struct cam_buf_io_cfg *io_cfg); From 29e9e0482063cd2f2c991ff80f06130e9c022620 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Fri, 19 Mar 2021 11:07:33 +0530 Subject: [PATCH 714/790] Revert "msm: camera: core: Allocate memory for flush req array dynamically" This reverts commit 018d8dae943321b3ce7138090855c94831124846. CRs-Fixed: 2901141 Change-Id: Ida945ea1b83fdf1f60d19b072f667a133ac9b9dc Signed-off-by: Ravikishore Pampana --- drivers/cam_core/cam_context_utils.c | 102 +++------------------------ drivers/cam_core/cam_hw_mgr_intf.h | 4 +- 2 files changed, 12 insertions(+), 94 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 0e4ed8843728..cfef68791326 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -602,7 +602,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) struct cam_hw_flush_args flush_args; struct list_head temp_list; struct cam_ctx_request *req; - uint32_t i, j; + uint32_t i; int rc = 0; bool free_req; @@ -618,31 +618,15 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) INIT_LIST_HEAD(&temp_list); spin_lock(&ctx->lock); list_splice_init(&ctx->pending_req_list, &temp_list); - flush_args.num_req_pending = 0; - list_for_each_entry(req, &temp_list, list) { - flush_args.num_req_pending++; - } spin_unlock(&ctx->lock); - flush_args.flush_req_pending = kcalloc(flush_args.num_req_pending, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_pending) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_pending", - ctx->dev_name, ctx->ctx_id); - mutex_unlock(&ctx->sync_mutex); - goto err; - } - if (cam_debug_ctx_req_list & ctx->dev_id) CAM_INFO(CAM_CTXT, "[%s][%d] : Moving all pending requests from pending_list to temp_list", ctx->dev_name, ctx->ctx_id); + flush_args.num_req_pending = 0; flush_args.last_flush_req = ctx->last_flush_req; - - j = 0; while (true) { spin_lock(&ctx->lock); if (list_empty(&temp_list)) { @@ -657,7 +641,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) spin_unlock(&ctx->lock); req->flushed = 1; - flush_args.flush_req_pending[j++] = + flush_args.flush_req_pending[flush_args.num_req_pending++] = req->req_priv; free_req = false; @@ -708,31 +692,11 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } mutex_unlock(&ctx->sync_mutex); - kfree(flush_args.flush_req_pending); - flush_args.flush_req_pending = NULL; - if (ctx->hw_mgr_intf->hw_flush) { - spin_lock(&ctx->lock); flush_args.num_req_active = 0; - list_for_each_entry(req, &ctx->active_req_list, list) { - flush_args.num_req_active++; - } - spin_unlock(&ctx->lock); - - flush_args.flush_req_active = kcalloc(flush_args.num_req_active, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_active) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_active", - ctx->dev_name, ctx->ctx_id); - goto err; - } - spin_lock(&ctx->lock); - j = 0; list_for_each_entry(req, &ctx->active_req_list, list) { - flush_args.flush_req_active[j++] + flush_args.flush_req_active[flush_args.num_req_active++] = req->req_priv; } spin_unlock(&ctx->lock); @@ -745,9 +709,6 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) } } - kfree(flush_args.flush_req_active); - flush_args.flush_req_active = NULL; - INIT_LIST_HEAD(&temp_list); spin_lock(&ctx->lock); list_splice_init(&ctx->active_req_list, &temp_list); @@ -801,8 +762,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx) CAM_DBG(CAM_CTXT, "[%s] X: NRT flush ctx", ctx->dev_name); -err: - return rc; + return 0; } int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, @@ -822,25 +782,6 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, flush_args.num_req_active = 0; mutex_lock(&ctx->sync_mutex); spin_lock(&ctx->lock); - list_for_each_entry(req, &ctx->pending_req_list, list) { - if (req->request_id != cmd->req_id) - continue; - flush_args.num_req_pending++; - } - spin_unlock(&ctx->lock); - - flush_args.flush_req_pending = kcalloc(flush_args.num_req_pending, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_pending) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_pending", - ctx->dev_name, ctx->ctx_id); - goto err; - } - - spin_lock(&ctx->lock); - i = 0; list_for_each_entry(req, &ctx->pending_req_list, list) { if (req->request_id != cmd->req_id) continue; @@ -853,41 +794,24 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, list_del_init(&req->list); req->flushed = 1; - flush_args.flush_req_pending[i++] = + flush_args.flush_req_pending[flush_args.num_req_pending++] = req->req_priv; break; } spin_unlock(&ctx->lock); + mutex_unlock(&ctx->sync_mutex); if (ctx->hw_mgr_intf->hw_flush) { if (!flush_args.num_req_pending) { spin_lock(&ctx->lock); - list_for_each_entry(req, &ctx->active_req_list, list) { - if (req->request_id != cmd->req_id) - continue; - flush_args.num_req_active++; - } - spin_unlock(&ctx->lock); - - flush_args.flush_req_active = kcalloc(flush_args.num_req_active, - sizeof(void *), GFP_KERNEL); - if (!flush_args.flush_req_pending) { - rc = -ENOMEM; - CAM_ERR(CAM_CTXT, - "[%s][%d] : Failed to malloc memory for flush_req_pending", - ctx->dev_name, ctx->ctx_id); - goto err; - } - - spin_lock(&ctx->lock); - i = 0; list_for_each_entry(req, &ctx->active_req_list, list) { if (req->request_id != cmd->req_id) continue; list_del_init(&req->list); - flush_args.flush_req_active[i++] = + flush_args.flush_req_active[ + flush_args.num_req_active++] = req->req_priv; break; } @@ -899,10 +823,6 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, flush_args.flush_type = CAM_FLUSH_TYPE_REQ; ctx->hw_mgr_intf->hw_flush( ctx->hw_mgr_intf->hw_mgr_priv, &flush_args); - kfree(flush_args.flush_req_pending); - flush_args.flush_req_pending = NULL; - kfree(flush_args.flush_req_active); - flush_args.flush_req_active = NULL; } } @@ -958,9 +878,7 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, } CAM_DBG(CAM_CTXT, "[%s] X: NRT flush req", ctx->dev_name); -err: - mutex_unlock(&ctx->sync_mutex); - return rc; + return 0; } int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 64149fb7c662..2b56d21b20be 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -289,9 +289,9 @@ struct cam_hw_config_args { struct cam_hw_flush_args { void *ctxt_to_hw_map; uint32_t num_req_pending; - void **flush_req_pending; + void *flush_req_pending[20]; uint32_t num_req_active; - void **flush_req_active; + void *flush_req_active[20]; enum flush_type_t flush_type; uint32_t last_flush_req; }; From 1283cb07a1dfa929dfb0f17cd910bbcc418373b5 Mon Sep 17 00:00:00 2001 From: Karthik Jayakumar Date: Tue, 23 Feb 2021 16:45:30 -0800 Subject: [PATCH 715/790] msm: camera: cdm: Fix of_match table null entry KASAN identified global-out-of-bounds issue on: msm_cam_hw_cdm_dt_match Due to no null-terminating struct in the array. CRs-Fixed: 2883523 Change-Id: I36e4811f239993e1e6de158df959157217c28bfe Signed-off-by: Karthik Jayakumar --- drivers/cam_cdm/cam_cdm_hw_core.c | 1 + drivers/cam_utils/cam_compat.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 61086ae5d13c..013b9f3267ed 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -74,6 +74,7 @@ static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { .compatible = CAM_HW_CDM_OPE_NAME_2_1, .data = &cam_cdm_2_1_reg_offset, }, + {}, }; static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 21ebc95ab35e..03e1a2f73c5d 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. */ #include @@ -201,6 +201,7 @@ int camera_component_match_add_drivers(struct device *master_dev, { int i, rc = 0; struct platform_device *pdev = NULL; + struct device *start_dev = NULL, *match_dev = NULL; if (!master_dev || !match_list) { CAM_ERR(CAM_UTIL, "Invalid parameters for component match add"); @@ -217,14 +218,12 @@ int camera_component_match_add_drivers(struct device *master_dev, struct device_driver *drv = &cam_component_drivers[i]->driver; void *drv_ptr = (void *)drv; #endif - struct device *start_dev = NULL, *match_dev; - + start_dev = NULL; while ((match_dev = bus_find_device(&platform_bus_type, start_dev, drv_ptr, &camera_platform_compare_dev))) { put_device(start_dev); pdev = to_platform_device(match_dev); - CAM_DBG(CAM_UTIL, "Adding matched component:%s", - pdev->name); + CAM_DBG(CAM_UTIL, "Adding matched component:%s", pdev->name); component_match_add(master_dev, match_list, camera_component_compare_dev, match_dev); start_dev = match_dev; From f1bd9e7379598924b3d1f5ca62746737bd9b6927 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 4 Sep 2020 12:47:50 +0530 Subject: [PATCH 716/790] msm: camera: ife: dump fill level registers on overflow Dump camnoc fill level registers for overflow and violations along with the SOF, EPOCH and EOF timestamps. CRs-Fixed: 2908055 Change-Id: I774140794eae6580f4332cd9cd39b8c65d7197a5 Signed-off-by: Tejas Prajapati --- drivers/cam_cpas/cam_cpas_intf.c | 20 +++ drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 121 ++++++++++++++++++ drivers/cam_cpas/cpas_top/cam_cpastop_hw.h | 30 +++++ drivers/cam_cpas/cpas_top/cpastop_v150_100.h | 8 +- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 6 + drivers/cam_cpas/cpas_top/cpastop_v170_110.h | 8 +- drivers/cam_cpas/cpas_top/cpastop_v170_200.h | 8 +- drivers/cam_cpas/cpas_top/cpastop_v175_100.h | 8 +- drivers/cam_cpas/cpas_top/cpastop_v175_101.h | 8 +- drivers/cam_cpas/cpas_top/cpastop_v175_120.h | 9 +- drivers/cam_cpas/cpas_top/cpastop_v175_130.h | 9 +- drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 9 +- drivers/cam_cpas/include/cam_cpas_api.h | 33 ++++- .../vfe_hw/vfe_top/cam_vfe_camif_ver2.c | 53 ++++---- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 22 ++++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c | 5 + 16 files changed, 316 insertions(+), 41 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index 7d007f4b3c29..f5bb5db85c29 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -18,6 +18,7 @@ #include "cam_cpas_hw_intf.h" #include "cam_cpas_soc.h" #include "camera_main.h" +#include "cam_cpas_api.h" #define CAM_CPAS_DEV_NAME "cam-cpas" #define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done) @@ -209,6 +210,25 @@ int cam_cpas_get_cpas_hw_version(uint32_t *hw_version) return 0; } +int cam_cpas_get_camnoc_fifo_fill_level_info( + uint32_t cpas_version, + uint32_t client_handle) +{ + int rc = 0; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return -ENODEV; + } + + rc = cam_cpas_hw_get_camnoc_fill_level_info(cpas_version, + client_handle); + if (rc) + CAM_ERR(CAM_CPAS, "Failed to dump fifo reg rc %d", rc); + + return rc; +} + int cam_cpas_get_hw_info(uint32_t *camera_family, struct cam_hw_version *camera_version, struct cam_hw_version *cpas_version, diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index bbcdbed8fc35..6447b3b40dc3 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -1006,6 +1006,127 @@ static int cam_cpastop_setup_qos_settings(struct cam_hw_info *cpas_hw, return rc; } +int cam_cpas_hw_get_camnoc_fill_level_info( + uint32_t cpas_version, + uint32_t client_handle) +{ + struct cam_camnoc_fifo_lvl_info *camnoc_reg_info; + uint32_t val; + + if (!camnoc_info->fill_lvl_register) + return -EFAULT; + + camnoc_reg_info = camnoc_info->fill_lvl_register; + + switch (cpas_version) { + case CAM_CPAS_TITAN_175_V120: + case CAM_CPAS_TITAN_175_V130: + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, + camnoc_reg_info->IFE0_nRDI_maxwr_offset, + true, &val); + CAM_INFO(CAM_CPAS, "IFE0_nRDI_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE0_nRDI_maxwr_offset, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, + camnoc_reg_info->IFE1_nRDI_maxwr_offset, + true, &val); + CAM_INFO(CAM_CPAS, "IFE1_nRDI_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE1_nRDI_maxwr_offset, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, + camnoc_reg_info->IFE0123_RDI_maxwr_offset, + true, &val); + CAM_INFO(CAM_CPAS, "IFE0_nRDI_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE0123_RDI_maxwr_offset, + val); + break; + case CAM_CPAS_TITAN_480_V100: + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->ife_linear, + true, &val); + CAM_INFO(CAM_CPAS, "ife_linear offset 0x%x val 0x%x", + camnoc_reg_info->ife_linear, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->ife_rdi_wr, + true, &val); + CAM_INFO(CAM_CPAS, "ife_rdi_wr offset 0x%x val 0x%x", + camnoc_reg_info->ife_rdi_wr, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->ife_ubwc_stats, + true, &val); + CAM_INFO(CAM_CPAS, "ife_ubwc_stats offset 0x%x val 0x%x", + camnoc_reg_info->ife_ubwc_stats, + val); + + break; + case CAM_CPAS_TITAN_170_V200: + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->IFE01_MAXWR_LOW, + true, &val); + CAM_INFO(CAM_ISP, "IFE01_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE01_MAXWR_LOW, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->IFE23_MAXWR_LOW, + true, &val); + CAM_INFO(CAM_ISP, "IFE23_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE23_MAXWR_LOW, + val); + + break; + case CAM_CPAS_TITAN_165_V100: + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->IFE0_MAXWR_LOW, + true, &val); + CAM_INFO(CAM_ISP, "IFE0_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE0_MAXWR_LOW, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->IFE1_MAXWR_LOW, + true, &val); + CAM_INFO(CAM_ISP, "IFE1_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE1_MAXWR_LOW, + val); + break; + case CAM_CPAS_TITAN_150_V100: + case CAM_CPAS_TITAN_170_V100: + case CAM_CPAS_TITAN_170_V110: + case CAM_CPAS_TITAN_170_V120: + case CAM_CPAS_TITAN_175_V100: + case CAM_CPAS_TITAN_175_V101: + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->IFE02_MAXWR_LOW, + true, &val); + CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE02_MAXWR_LOW, + val); + + cam_cpas_reg_read(client_handle, + CAM_CPAS_REG_CAMNOC, camnoc_reg_info->IFE13_MAXWR_LOW, + true, &val); + CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x%x val 0x%x", + camnoc_reg_info->IFE13_MAXWR_LOW, + val); + break; + default: + CAM_ERR(CAM_CPAS, "Camera version not supported %d", + cpas_version); + break; + } + return 0; +} + int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) { if (!internal_ops) { diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 3992e079ad18..ca4c3d0a8f1f 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -316,6 +316,34 @@ struct cam_camnoc_err_logger_info { uint32_t errlog3_high; }; +/** + * struct cam_camnoc_fifo_lvl_info : Struct for fifo fill level registers + * @IFE0_nRDI_maxwr_offset: Register offset for fill level for IFE0 + * @IFE1_nRDI_maxwr_offset: Register offset for fill level for IFE1 + * @IFE0123_RDI_maxwr_low_offset: Register offset for RDI + * @ife_linear: Register offset for ife linear + * @ife_rdi_wr: Register offset for rdi wr + * @ife_ubwc_stats: Register offset for ubwc stats + * @IFE02_MAXWR_LOW: Register offset for IFE02 + * @IFE13_MAXWR_LOW: Register offset for IFE13 + * @IFE01_MAXWR_LOW: Register offset for IFE01 + * @IFE23_MAXWR_LOW: Register offset for IFE23 + */ +struct cam_camnoc_fifo_lvl_info { + uint32_t IFE0_nRDI_maxwr_offset; + uint32_t IFE1_nRDI_maxwr_offset; + uint32_t IFE0123_RDI_maxwr_offset; + uint32_t ife_linear; + uint32_t ife_rdi_wr; + uint32_t ife_ubwc_stats; + uint32_t IFE02_MAXWR_LOW; + uint32_t IFE13_MAXWR_LOW; + uint32_t IFE01_MAXWR_LOW; + uint32_t IFE23_MAXWR_LOW; + uint32_t IFE0_MAXWR_LOW; + uint32_t IFE1_MAXWR_LOW; +}; + /** * struct cam_camnoc_info : Overall CAMNOC settings info * @@ -326,6 +354,7 @@ struct cam_camnoc_err_logger_info { * @irq_err_size: Array size of IRQ Error settings * @err_logger: Pointer to CAMNOC IRQ Error logger read registers * @errata_wa_list: HW Errata workaround info + * @fill_level_register: Fill level registers * */ struct cam_camnoc_info { @@ -336,6 +365,7 @@ struct cam_camnoc_info { int irq_err_size; struct cam_camnoc_err_logger_info *err_logger; struct cam_cpas_hw_errata_wa_list *errata_wa_list; + struct cam_camnoc_fifo_lvl_info *fill_lvl_register; }; /** diff --git a/drivers/cam_cpas/cpas_top/cpastop_v150_100.h b/drivers/cam_cpas/cpas_top/cpastop_v150_100.h index df9711e74379..edad15043dda 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v150_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v150_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V150_100_H_ @@ -515,6 +515,11 @@ static struct cam_cpas_hw_errata_wa_list cam150_cpas100_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam150_cpas100_camnoc_fifo_info = { + .IFE02_MAXWR_LOW = 0x420, + .IFE13_MAXWR_LOW = 0x820, +}; + 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) / @@ -525,6 +530,7 @@ static struct cam_camnoc_info cam150_cpas100_camnoc_info = { sizeof(cam_cpas_v150_100_irq_err[0]), .err_logger = &cam150_cpas100_err_logger_offsets, .errata_wa_list = &cam150_cpas100_errata_wa_list, + .fill_lvl_register = &cam150_cpas100_camnoc_fifo_info, }; #endif /* _CPASTOP_V150_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 3e739d3c33a3..8e41284604f6 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -591,6 +591,11 @@ static struct cam_cpas_hw_errata_wa_list cam165_cpas100_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam165_cpas100_camnoc_fifo_info = { + .IFE0_MAXWR_LOW = 0x3A20, + .IFE1_MAXWR_LOW = 0x5420, +}; + static struct cam_camnoc_info cam165_cpas100_camnoc_info = { .specific = &cam_cpas_v165_100_camnoc_specific[0], .specific_size = ARRAY_SIZE(cam_cpas_v165_100_camnoc_specific), @@ -599,6 +604,7 @@ static struct cam_camnoc_info cam165_cpas100_camnoc_info = { .irq_err_size = ARRAY_SIZE(cam_cpas_v165_100_irq_err), .err_logger = &cam165_cpas100_err_logger_offsets, .errata_wa_list = &cam165_cpas100_errata_wa_list, + .fill_lvl_register = &cam165_cpas100_camnoc_fifo_info, }; #endif /* _CPASTOP_V165_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/cam_cpas/cpas_top/cpastop_v170_110.h index 788f571a3a13..fc986f598e33 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v170_110.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v170_110.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V170_110_H_ @@ -523,6 +523,11 @@ static struct cam_cpas_hw_errata_wa_list cam170_cpas110_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam170_cpas110_camnoc_fifo_info = { + .IFE02_MAXWR_LOW = 0x420, + .IFE13_MAXWR_LOW = 0x820, +}; + static struct cam_camnoc_info cam170_cpas110_camnoc_info = { .specific = &cam_cpas110_camnoc_specific[0], .specific_size = sizeof(cam_cpas110_camnoc_specific) / @@ -533,6 +538,7 @@ static struct cam_camnoc_info cam170_cpas110_camnoc_info = { sizeof(cam_cpas110_irq_err[0]), .err_logger = &cam170_cpas110_err_logger_offsets, .errata_wa_list = &cam170_cpas110_errata_wa_list, + .fill_lvl_register = &cam170_cpas110_camnoc_fifo_info, }; #endif /* _CPASTOP_V170_110_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v170_200.h b/drivers/cam_cpas/cpas_top/cpastop_v170_200.h index 98aabc984c87..3827e8dfff68 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v170_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v170_200.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V170_200_H_ @@ -525,6 +525,11 @@ static struct cam_cpas_hw_errata_wa_list cam170_cpas200_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam170_cpas200_camnoc_fifo_info = { + .IFE01_MAXWR_LOW = 0x2420, + .IFE23_MAXWR_LOW = 0x2620, +}; + static struct cam_camnoc_info cam170_cpas200_camnoc_info = { .specific = &cam_cpas_v170_200_camnoc_specific[0], .specific_size = ARRAY_SIZE(cam_cpas_v170_200_camnoc_specific), @@ -533,6 +538,7 @@ static struct cam_camnoc_info cam170_cpas200_camnoc_info = { .irq_err_size = ARRAY_SIZE(cam_cpas_v170_200_irq_err), .err_logger = &cam170_cpas200_err_logger_offsets, .errata_wa_list = &cam170_cpas200_errata_wa_list, + .fill_lvl_register = &cam170_cpas200_camnoc_fifo_info, }; #endif /* _CPASTOP_V170_200_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_100.h b/drivers/cam_cpas/cpas_top/cpastop_v175_100.h index aae26b5a9178..ab20db01cd18 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_100_H_ @@ -543,6 +543,11 @@ static struct cam_cpas_hw_errata_wa_list cam175_cpas100_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam175_cpas100_camnoc_fifo_info = { + .IFE02_MAXWR_LOW = 0x420, + .IFE13_MAXWR_LOW = 0x820, +}; + static struct cam_camnoc_info cam175_cpas100_camnoc_info = { .specific = &cam_cpas_v175_100_camnoc_specific[0], .specific_size = sizeof(cam_cpas_v175_100_camnoc_specific) / @@ -553,6 +558,7 @@ static struct cam_camnoc_info cam175_cpas100_camnoc_info = { sizeof(cam_cpas_v175_100_irq_err[0]), .err_logger = &cam175_cpas100_err_logger_offsets, .errata_wa_list = &cam175_cpas100_errata_wa_list, + .fill_lvl_register = &cam175_cpas100_camnoc_fifo_info, }; #endif /* _CPASTOP_V175_100_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_101.h b/drivers/cam_cpas/cpas_top/cpastop_v175_101.h index 7ec9bec36fd1..12ed226008e6 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_101.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_101.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_101_H_ @@ -543,6 +543,11 @@ static struct cam_cpas_hw_errata_wa_list cam175_cpas101_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam175_cpas101_camnoc_fifo_info = { + .IFE02_MAXWR_LOW = 0x420, + .IFE13_MAXWR_LOW = 0x820, +}; + static struct cam_camnoc_info cam175_cpas101_camnoc_info = { .specific = &cam_cpas_v175_101_camnoc_specific[0], .specific_size = sizeof(cam_cpas_v175_101_camnoc_specific) / @@ -553,6 +558,7 @@ static struct cam_camnoc_info cam175_cpas101_camnoc_info = { sizeof(cam_cpas_v175_101_irq_err[0]), .err_logger = &cam175_cpas101_err_logger_offsets, .errata_wa_list = &cam175_cpas101_errata_wa_list, + .fill_lvl_register = &cam175_cpas101_camnoc_fifo_info, }; #endif /* _CPASTOP_V175_101_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_120.h b/drivers/cam_cpas/cpas_top/cpastop_v175_120.h index 5844c38ae52c..83e5fb415472 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_120.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_120.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_120_H_ @@ -747,6 +747,12 @@ static struct cam_cpas_hw_errata_wa_list cam175_cpas120_errata_wa_list = { }, }; +static struct cam_camnoc_fifo_lvl_info cam175_cpas120_camnoc_fifo_info = { + .IFE0_nRDI_maxwr_offset = 0x3A20, + .IFE1_nRDI_maxwr_offset = 0x5420, + .IFE0123_RDI_maxwr_offset = 0x3620, +}; + static struct cam_camnoc_info cam175_cpas120_camnoc_info = { .specific = &cam_cpas_v175_120_camnoc_specific[0], .specific_size = ARRAY_SIZE(cam_cpas_v175_120_camnoc_specific), @@ -755,6 +761,7 @@ static struct cam_camnoc_info cam175_cpas120_camnoc_info = { .irq_err_size = ARRAY_SIZE(cam_cpas_v175_120_irq_err), .err_logger = &cam175_cpas120_err_logger_offsets, .errata_wa_list = &cam175_cpas120_errata_wa_list, + .fill_lvl_register = &cam175_cpas120_camnoc_fifo_info, }; #endif /* _CPASTOP_V175_120_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h index 769e77fc3d6b..f7acca0f039f 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_130_H_ @@ -760,6 +760,12 @@ static struct cam_cpas_hw_errata_wa_list cam175_cpas130_errata_wa_list = { }, }; +static struct cam_camnoc_fifo_lvl_info cam175_cpas130_camnoc_fifo_info = { + .IFE0_nRDI_maxwr_offset = 0x3A20, + .IFE1_nRDI_maxwr_offset = 0x5420, + .IFE0123_RDI_maxwr_offset = 0x3620, +}; + static struct cam_camnoc_info cam175_cpas130_camnoc_info = { .specific = &cam_cpas_v175_130_camnoc_specific[0], .specific_size = ARRAY_SIZE(cam_cpas_v175_130_camnoc_specific), @@ -768,6 +774,7 @@ static struct cam_camnoc_info cam175_cpas130_camnoc_info = { .irq_err_size = ARRAY_SIZE(cam_cpas_v175_130_irq_err), .err_logger = &cam175_cpas130_err_logger_offsets, .errata_wa_list = &cam175_cpas130_errata_wa_list, + .fill_lvl_register = &cam175_cpas130_camnoc_fifo_info, }; #endif /* _CPASTOP_V175_130_H_ */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h index 0d46e0ddcc20..49b1e8fb63a1 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V480_100_H_ @@ -698,6 +698,12 @@ static struct cam_cpas_hw_errata_wa_list cam480_cpas100_errata_wa_list = { }, }; +struct cam_camnoc_fifo_lvl_info cam480_cpas100_camnoc_fifo_info = { + .ife_linear = 0xA20, + .ife_rdi_wr = 0x1420, + .ife_ubwc_stats = 0x1A20, +}; + static struct cam_camnoc_info cam480_cpas100_camnoc_info = { .specific = &cam_cpas_v480_100_camnoc_specific[0], .specific_size = ARRAY_SIZE(cam_cpas_v480_100_camnoc_specific), @@ -706,6 +712,7 @@ static struct cam_camnoc_info cam480_cpas100_camnoc_info = { .irq_err_size = ARRAY_SIZE(cam_cpas_v480_100_irq_err), .err_logger = &cam480_cpas100_err_logger_offsets, .errata_wa_list = &cam480_cpas100_errata_wa_list, + .fill_lvl_register = &cam480_cpas100_camnoc_fifo_info, }; #endif /* _CPASTOP_V480_100_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 1179f3999922..2b82d1f283e4 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -638,6 +638,21 @@ int cam_cpas_get_hw_info( int cam_cpas_get_cpas_hw_version( uint32_t *hw_version); +/** + * cam_cpas_get_camnoc_fifo_fill_level_info() + * + * @brief: API to get camera camnoc hw version + * + * @cpas_version: hw version + * @client_handle: cpas client handle + * + * @return 0 on success. + * + */ +int cam_cpas_get_camnoc_fifo_fill_level_info( + uint32_t cpas_version, + uint32_t client_handle); + /** * cam_cpas_is_feature_supported() * @@ -714,11 +729,23 @@ int cam_cpas_select_qos_settings(uint32_t selection_mask); * * @identifier_string: Identifier string passed by caller * @identifier_value: Identifier value passed by caller - * - * @return 0 on success. - * */ int cam_cpas_notify_event(const char *identifier_string, int32_t identifier_value); +/* + * cam_cpas_hw_get_camnoc_fill_level_info() + * + * @brief: API to get camnoc info + * + * @cpas_version: cpas hw version + * @client_handle: cpas client handle + * + * @return 0 on success. + * + */ +int cam_cpas_hw_get_camnoc_fill_level_info( + uint32_t cpas_version, + uint32_t client_handle); + #endif /* _CAM_CPAS_API_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 7c5b27ed08b0..6c2b701ded7f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -523,7 +523,6 @@ 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_soc_private *soc_private; uint32_t offset, val, wm_idx; if (!camif_res) { @@ -555,35 +554,6 @@ static int cam_vfe_camif_reg_dump( } } - soc_private = camif_priv->soc_info->soc_private; - if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || - soc_private->cpas_version == CAM_CPAS_TITAN_175_V130 || - soc_private->cpas_version == CAM_CPAS_TITAN_165_V100) { - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); - CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", - val); - - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); - CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", - val); - - cam_cpas_reg_read(soc_private->cpas_handle, - CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); - CAM_INFO(CAM_ISP, - "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); - - } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { - 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); - - 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); - } - return 0; } @@ -891,6 +861,15 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + CAM_INFO(CAM_ISP, + "SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); + CAM_INFO(CAM_ISP, "Violation status = %x", payload->irq_reg_val[2]); @@ -899,6 +878,9 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, CAM_INFO(CAM_ISP, "ife_clk_src:%lld", soc_private->ife_clk_src); + cam_cpas_get_camnoc_fifo_fill_level_info( + soc_private->cpas_version, + soc_private->cpas_handle); cam_cpas_log_votes(); if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) @@ -908,6 +890,14 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status1 & camif_priv->reg_data->error_irq_mask1) { CAM_DBG(CAM_ISP, "Received ERROR"); + CAM_INFO(CAM_ISP, + "SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); ktime_get_boottime_ts64(&ts); CAM_INFO(CAM_ISP, "current monotonic time stamp seconds %lld:%lld", @@ -925,6 +915,9 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, CAM_INFO(CAM_ISP, "ife_clk_src:%lld", soc_private->ife_clk_src); + cam_cpas_get_camnoc_fifo_fill_level_info( + soc_private->cpas_version, + soc_private->cpas_handle); cam_cpas_log_votes(); if (camif_priv->camif_debug & CAMIF_DEBUG_ENABLE_REG_DUMP) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 72f108d9621a..9509561d5a26 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1285,6 +1285,12 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, print_state: soc_private = camif_priv->soc_info->soc_private; + cam_cpas_get_camnoc_fifo_fill_level_info( + soc_private->cpas_version, + soc_private->cpas_handle); + + cam_cpas_log_votes(); + cam_cpas_reg_read(soc_private->cpas_handle, CAM_CPAS_REG_CAMNOC, 0xA20, true, &val0); cam_cpas_reg_read(soc_private->cpas_handle, @@ -1492,6 +1498,14 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, & camif_priv->reg_data->error_irq_mask0) { CAM_ERR(CAM_ISP, "VFE:%d Overflow", evt_info.hw_idx); + CAM_INFO(CAM_ISP, + "SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); ktime_get_boottime_ts64(&ts); CAM_INFO(CAM_ISP, "current monotonic time stamp seconds %lld:%lld", @@ -1525,6 +1539,14 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx); + CAM_INFO(CAM_ISP, + "SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); ktime_get_boottime_ts64(&ts); CAM_INFO(CAM_ISP, "current monotonic time stamp seconds %lld:%lld", diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index 1d8863c741e8..c1beec26e91d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -14,6 +14,7 @@ #include "cam_cdm_util.h" #include "cam_irq_controller.h" #include "cam_tasklet_util.h" +#include "cam_cpas_api.h" struct cam_vfe_mux_rdi_data { void __iomem *mem_base; @@ -568,6 +569,10 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, rdi_priv->event_cb(rdi_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); + + cam_cpas_get_camnoc_fifo_fill_level_info( + soc_private->cpas_version, + soc_private->cpas_handle); cam_cpas_log_votes(); } end: From be81f378023a5a25dbf639f07526cc797581c89e Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Thu, 25 Feb 2021 10:37:29 +0530 Subject: [PATCH 717/790] msm: camera: isp: Reapply bubble request in RDI path For recovery of the bubble the request from active list should be added back to pending request list. CRs-Fixed: 2887188 Change-Id: I9bd14db82f96d2fda99bb542bd0df4c9c4a06745 Signed-off-by: Tejas Prajapati --- drivers/cam_isp/cam_isp_context.c | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d4ba000210aa..1aeef7b7fc21 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4042,6 +4042,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( ctx_isp->frame_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); + atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; } @@ -4087,7 +4088,11 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( struct cam_req_mgr_trigger_notify notify; struct cam_isp_hw_sof_event_data *sof_event_data = evt_data; struct cam_isp_ctx_req *req_isp; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; uint64_t request_id = 0; + uint64_t last_cdm_done_req = 0; + int rc = 0; if (!evt_data) { CAM_ERR(CAM_ISP, "in valid sof event data"); @@ -4099,6 +4104,73 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->boot_timestamp = sof_event_data->boot_time; CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", ctx_isp->frame_id, ctx_isp->sof_timestamp_val); + + + if (atomic_read(&ctx_isp->process_bubble)) { + if (list_empty(&ctx->active_req_list)) { + CAM_ERR(CAM_ISP, "No available active req in bubble"); + atomic_set(&ctx_isp->process_bubble, 0); + return -EINVAL; + } + + if (ctx_isp->last_sof_timestamp == + ctx_isp->sof_timestamp_val) { + CAM_DBG(CAM_ISP, + "Tasklet delay detected! Bubble frame: %lld check skipped, sof_timestamp: %lld, ctx_id: %d", + ctx_isp->frame_id, + ctx_isp->sof_timestamp_val, + ctx->ctx_id); + goto end; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + if (req_isp->bubble_detected) { + hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = + CAM_ISP_HW_MGR_GET_LAST_CDM_DONE; + 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); + if (rc) { + CAM_ERR(CAM_ISP, "HW command failed"); + return rc; + } + + last_cdm_done_req = isp_hw_cmd_args.u.last_cdm_done; + CAM_DBG(CAM_ISP, "last_cdm_done req: %d ctx_id: %d", + last_cdm_done_req, ctx->ctx_id); + + if (last_cdm_done_req >= req->request_id) { + CAM_DBG(CAM_ISP, + "CDM callback detected for req: %lld, possible buf_done delay, waiting for buf_done", + req->request_id); + goto end; + } else { + CAM_WARN(CAM_ISP, + "CDM callback not happened for req: %lld, possible CDM stuck or workqueue delay", + req->request_id); + req_isp->num_acked = 0; + req_isp->num_deferred_acks = 0; + req_isp->bubble_detected = false; + req_isp->cdm_reset_before_apply = true; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->active_req_cnt--; + CAM_DBG(CAM_REQ, + "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", + req->request_id, + ctx_isp->active_req_cnt, ctx->ctx_id); + } + goto end; + } + } + /* * Signal all active requests with error and move the all the active * requests to free list @@ -4121,6 +4193,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->active_req_cnt--; } +end: /* notify reqmgr with sof signal */ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { notify.link_hdl = ctx->link_hdl; @@ -4151,6 +4224,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); + ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val; return 0; } From 70e5d8ea1a90f3248fab72f0b3ab2fee14b505d1 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Wed, 31 Mar 2021 17:25:15 +0530 Subject: [PATCH 718/790] msm: camera: sensor: Add data rate table for holi Add data rate table in csiphy driver for cphy lane for holi. CRs-Fixed: 2913428 Change-Id: I57c6ab503ed6535ae80e2268e76fb29bfccad856 Signed-off-by: shiwgupt --- .../cam_csiphy/cam_csiphy_soc.c | 3 +- .../include/cam_csiphy_1_2_5_hwreg.h | 170 +++++++++++++++++- 2 files changed, 171 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index d882e3b78297..f6040e720a69 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -446,7 +446,8 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->is_divisor_32_comp = false; csiphy_dev->hw_version = CSIPHY_VERSION_V125; csiphy_dev->clk_lane = 0; - csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2_5; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h index d472aa5e48e3..413ba535ce40 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_5_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_5_HWREG_H_ @@ -392,4 +392,172 @@ csiphy_reg_t csiphy_3ph_v1_2_5_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { }, }; +struct data_rate_settings_t data_rate_delta_table_1_2_5 = { + .num_data_rate_settings = 3, + .data_rate_settings = { + { + /* (2.5 * 10**3 * 2.28) rounded value*/ + .bandwidth = 5700000000, + .data_rate_reg_array_size = 4, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x010C, 0x12, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x144, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x030C, 0x12, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x344, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x050C, 0x12, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x544, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, + }, + { + /* (3.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 7980000000, + .data_rate_reg_array_size = 6, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x010C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x030C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x050C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x544, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, + }, + { + /* (4.5 * 10**3 * 2.28) rounded value */ + .bandwidth = 10260000000, + .data_rate_reg_array_size = 6, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x010C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x144, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x01, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x030C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x344, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x01, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x050C, 0x08, 0x00, + CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, + CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x544, 0xB2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x60, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x01, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, + }, + }, +}; + #endif /* _CAM_CSIPHY_1_2_5_HWREG_H_ */ From 4580f024fed5cd208c1dab2470fa34dd149d5770 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Sat, 27 Mar 2021 14:32:34 +0530 Subject: [PATCH 719/790] msm: camera: req_mgr: Validate active sequence id in link control Validate active sequence id before clear bit. This avoid invalid clear bit scenario if link is created but try to deactivate with out link activate. CRs-Fixed: 2909190 Change-Id: Ie12f6bb100e1e12c41b9addf516446f4088ae8a3 Signed-off-by: Ravikishore Pampana --- drivers/cam_req_mgr/cam_req_mgr_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 27c6e22b594b..3942655f58f9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -5001,7 +5001,10 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->state = CAM_CRM_LINK_STATE_IDLE; link->skip_init_frame = false; crm_timer_exit(&link->watchdog); - clear_bit(link->activate_seq, g_crm_core_dev->bitmap); + if ((link->activate_seq >= 0) && + (link->activate_seq < MAXIMUM_LINKS_PER_SESSION)) + clear_bit(link->activate_seq, g_crm_core_dev->bitmap); + link->activate_seq = -1; spin_unlock_bh(&link->link_state_spin_lock); CAM_DBG(CAM_CRM, From 81360e9bfae1fda53d7339f2cb80330add68b827 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 25 Mar 2021 23:28:22 +0530 Subject: [PATCH 720/790] msm: camera: isp: Dont enable Wm configurations during HW start There is a chance that during acquire time while updating write master, for few resources io buffers are not allocated. If Wm configurations are enabled without receiving io buffers then there is a chance of hitting page fault issues. This commit takes care of enabling Wm configurations for each client only if io buffers are allocated. CRs-Fixed: 2887053 Change-Id: I868bd01dbd896dd86eeec4fc92a8a62e746f79cf Signed-off-by: Shravya Samala --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 53436df08dfa..c5fe7d82fa0d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1330,10 +1330,9 @@ static int cam_vfe_bus_start_wm( return -EINVAL; } } - - /* Enable WM */ - cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + - rsrc_data->hw_regs->cfg); + /* enabling Wm configuratons are taken care in update_wm(). + * i.e enable wm only if io buffers are allocated + */ CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index, rsrc_data->width, rsrc_data->height); From ac3906ff6e901c1480d4bb5b8ab2a55212d1c86e Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 1 Apr 2021 17:01:50 +0530 Subject: [PATCH 721/790] msm: camera: isp: Change logic of acquiring dual composite group There is a possibility of composite groups in free dual composite group list are not in sequential order. In case of dual ife use case, if composite groups are not in sequential manner then we landed into a scenario where two different IFE with same resource have two different composite group index, which is not expected. This commit ensures if it is dual IFE usecase then at the time of acquiring composite group, both IFEs have same composite group ID for same resource. CRs-Fixed: 2912721 Change-Id: I734d1d1660c1e70e0480e2dc0b8377a1c441c634 Signed-off-by: Shravya Samala --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 53436df08dfa..d1e8db83c6bf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -262,6 +262,28 @@ static enum cam_vfe_bus_comp_grp_id } } +static enum cam_vfe_bus_ver2_comp_grp_type + cam_vfe_bus_dual_comp_grp_id_convert(uint32_t comp_grp) +{ + switch (comp_grp) { + case CAM_VFE_BUS_COMP_GROUP_ID_0: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0; + case CAM_VFE_BUS_COMP_GROUP_ID_1: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1; + case CAM_VFE_BUS_COMP_GROUP_ID_2: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2; + case CAM_VFE_BUS_COMP_GROUP_ID_3: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3; + case CAM_VFE_BUS_COMP_GROUP_ID_4: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4; + case CAM_VFE_BUS_COMP_GROUP_ID_5: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5; + case CAM_VFE_BUS_COMP_GROUP_NONE: + default: + return CAM_VFE_BUS_VER2_COMP_GRP_MAX; + } +} + static int cam_vfe_bus_put_evt_payload( struct cam_vfe_bus_ver2_common_data *common_data, struct cam_vfe_bus_irq_evt_payload **evt_payload) @@ -1609,6 +1631,38 @@ static void cam_vfe_bus_match_comp_grp( *comp_grp = NULL; } +static int cam_vfe_bus_get_free_dual_comp_grp( + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_isp_resource_node **comp_grp, + uint32_t comp_grp_local_idx) +{ + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; + struct cam_isp_resource_node *dual_comp_grp_local = NULL; + struct cam_isp_resource_node *dual_comp_grp_local_temp = NULL; + int32_t dual_comp_grp_idx = 0; + int rc = -EINVAL; + + dual_comp_grp_idx = cam_vfe_bus_dual_comp_grp_id_convert(comp_grp_local_idx); + + CAM_DBG(CAM_ISP, "dual_comp_grp_idx :%d", dual_comp_grp_idx); + + list_for_each_entry_safe(dual_comp_grp_local, dual_comp_grp_local_temp, + &ver2_bus_priv->free_dual_comp_grp, list) { + rsrc_data = dual_comp_grp_local->res_priv; + CAM_DBG(CAM_ISP, "current grp type : %d expected :%d", + rsrc_data->comp_grp_type, dual_comp_grp_idx); + if (dual_comp_grp_idx != rsrc_data->comp_grp_type) { + continue; + } else { + list_del_init(&dual_comp_grp_local->list); + *comp_grp = dual_comp_grp_local; + return 0; + } + } + + return rc; +} + static int cam_vfe_bus_acquire_comp_grp( struct cam_vfe_bus_ver2_priv *ver2_bus_priv, struct cam_isp_out_port_generic_info *out_port_info, @@ -1641,9 +1695,14 @@ static int cam_vfe_bus_acquire_comp_grp( CAM_ERR(CAM_ISP, "No Free Composite Group"); return -ENODEV; } - comp_grp_local = list_first_entry( - &ver2_bus_priv->free_dual_comp_grp, - struct cam_isp_resource_node, list); + rc = cam_vfe_bus_get_free_dual_comp_grp( + ver2_bus_priv, &comp_grp_local, bus_comp_grp_id); + if (rc || !comp_grp_local) { + CAM_ERR(CAM_ISP, + "failed to acquire dual comp grp for :%d rc :%d", + bus_comp_grp_id, rc); + return rc; + } rsrc_data = comp_grp_local->res_priv; rc = cam_vfe_bus_ver2_get_intra_client_mask( dual_slave_core, From a4a349c82fa78de4e09643b594e32114c655d3b9 Mon Sep 17 00:00:00 2001 From: Alok Pandey Date: Thu, 1 Apr 2021 15:17:18 +0530 Subject: [PATCH 722/790] msm: camera: req_mgr: Sending event_cause for frame error for shima When camnoc fill level for RDI port goes beyond 25%, notify UMD with BAD frames to take corrective actions. CRs-Fixed: 2913934 Change-Id: I5427ce94cdd2a48d8647ff4593cb1605a2f90a37 Signed-off-by: Alok Pandey --- drivers/cam_isp/cam_isp_context.c | 65 ++++++++++++----- drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 1 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 5 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 3 +- .../isp_hw/include/cam_vfe_hw_intf.h | 5 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 72 ++++++++++++++++--- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 21 +++++- include/uapi/camera/media/cam_sync.h | 1 + 8 files changed, 139 insertions(+), 34 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d4ba000210aa..6915cf20bc3d 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -899,8 +899,9 @@ static int __cam_isp_ctx_handle_buf_done_for_request( req_isp = (struct cam_isp_ctx_req *) req->req_priv; - CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", - bubble_state, req_isp->bubble_detected); + CAM_DBG(CAM_ISP, + "Enter with bubble_state %d, req_bubble_detected %d evt_param = %d", + bubble_state, req_isp->bubble_detected, done->evt_param); done_next_req->num_handles = 0; done_next_req->timestamp = done->timestamp; @@ -956,18 +957,31 @@ static int __cam_isp_ctx_handle_buf_done_for_request( if (!req_isp->bubble_detected) { CAM_DBG(CAM_ISP, - "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u", + "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u, Bad_frame %u", req->request_id, req_isp->fence_map_out[j].resource_handle, req_isp->fence_map_out[j].sync_id, - ctx->ctx_id); + ctx->ctx_id, done->evt_param); - rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, - CAM_SYNC_STATE_SIGNALED_SUCCESS, - CAM_SYNC_COMMON_EVENT_SUCCESS); + if (done->evt_param == 1) { + + CAM_WARN(CAM_ISP, + "Bad frame 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, + ctx->ctx_id); + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_ISP_EVENT_BAD_FRAME); + } else { + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_COMMON_EVENT_SUCCESS); + } if (rc) CAM_DBG(CAM_ISP, "Sync failed with rc = %d", - rc); + rc); } else if (!req_isp->bubble_report) { CAM_DBG(CAM_ISP, "Sync with failure: req %lld res 0x%x fd 0x%x, ctx %u", @@ -1104,13 +1118,15 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; const char *handle_type; + uint32_t event_cause = CAM_SYNC_COMMON_EVENT_SUCCESS; trace_cam_buf_done("ISP", ctx, req); req_isp = (struct cam_isp_ctx_req *) req->req_priv; - CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", - bubble_state, req_isp->bubble_detected); + CAM_DBG(CAM_ISP, + "Enter with bubble_state %d, req_bubble_detected %d evt_param %d", + bubble_state, req_isp->bubble_detected, done->evt_param); for (i = 0; i < done->num_handles; i++) { for (j = 0; j < req_isp->num_fence_map_out; j++) { @@ -1185,24 +1201,37 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( continue; } else if (!req_isp->bubble_detected) { CAM_DBG(CAM_ISP, - "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u", + "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u isBadFrame %u", req->request_id, req_isp->fence_map_out[j].resource_handle, 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, - CAM_SYNC_COMMON_EVENT_SUCCESS); + ctx->ctx_id, done->evt_param); + if (done->evt_param == 1) { + CAM_WARN(CAM_ISP, + "Bad Frame 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, + ctx->ctx_id); + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_ISP_EVENT_BAD_FRAME); + event_cause = CAM_SYNC_ISP_EVENT_BAD_FRAME; + } else { + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS, + CAM_SYNC_COMMON_EVENT_SUCCESS); + event_cause = CAM_SYNC_COMMON_EVENT_SUCCESS; + } if (rc) { CAM_DBG(CAM_ISP, "Sync failed with rc = %d", - rc); + rc); } else if (req_isp->num_deferred_acks) { /* Process deferred buf_done acks */ __cam_isp_handle_deferred_buf_done(ctx_isp, req, false, CAM_SYNC_STATE_SIGNALED_SUCCESS, - CAM_SYNC_COMMON_EVENT_SUCCESS); + event_cause); } } else if (!req_isp->bubble_report) { CAM_DBG(CAM_ISP, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index f0ea6fe8fb24..487f1eda3457 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -8022,6 +8022,7 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( buf_done_event_data.resource_handle[0] = event_info->res_id; buf_done_event_data.last_consumed_addr[0] = event_info->reg_val; + buf_done_event_data.evt_param = event_info->evt_param; if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) return 0; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index d3f748e93c04..b04c3448b6b5 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -194,7 +194,7 @@ struct cam_isp_hw_epoch_event_data { * @resource_handle: Resource handle array * @last_consumed_addr: Last consumed addr * @timestamp: Timestamp for the buf done event - * + * @evt_param: Specific info about the frame */ struct cam_isp_hw_done_event_data { uint32_t num_handles; @@ -202,7 +202,8 @@ struct cam_isp_hw_done_event_data { CAM_NUM_OUT_PER_COMP_IRQ_MAX]; uint32_t last_consumed_addr[ CAM_NUM_OUT_PER_COMP_IRQ_MAX]; - uint64_t timestamp; + uint64_t timestamp; + uint32_t evt_param; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index ad5d25abe7fc..6638b9269a58 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -216,7 +216,7 @@ struct cam_isp_blanking_config { * @hw_idx: IFE hw index * @err_type: Error type if any * @reg_val: Any critical register value captured during irq handling - * + * @evt_param Specific info about frame */ struct cam_isp_hw_event_info { enum cam_isp_resource_type res_type; @@ -224,6 +224,7 @@ struct cam_isp_hw_event_info { uint32_t hw_idx; uint32_t err_type; uint32_t reg_val; + uint32_t evt_param; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 6c3213aec6c7..b2357032e704 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_HW_INTF_H_ @@ -14,6 +14,7 @@ #define CAM_VFE_HW_NUM_MAX 7 #define VFE_CORE_BASE_IDX 0 +#define CAMNOC_CORE_BASE_IDX 1 #define RT_BASE_IDX 2 /* * VBIF and BUS do not exist on same HW. @@ -320,6 +321,7 @@ struct cam_vfe_top_irq_evt_payload { * handled * @error_type: Identify different errors * @ts: Timestamp + * @evt_param Specific info about frame */ struct cam_vfe_bus_irq_evt_payload { struct list_head list; @@ -331,6 +333,7 @@ struct cam_vfe_bus_irq_evt_payload { uint32_t evt_id; uint32_t irq_reg_val[CAM_IFE_BUS_IRQ_REGISTERS_MAX]; struct cam_isp_timestamp ts; + uint32_t evt_param; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 957539d28dfc..b11a9e285ff7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ @@ -76,6 +76,9 @@ struct cam_vfe_bus_error_info { struct cam_vfe_bus_ver3_common_data { uint32_t core_index; void __iomem *mem_base; + void __iomem *camnoc_mem_base; + uint32_t cpas_version; + struct cam_hw_soc_info *soc_info; struct cam_hw_intf *hw_intf; void *bus_irq_controller; void *rup_irq_controller; @@ -950,6 +953,7 @@ static int cam_vfe_bus_ver3_handle_rup_bottom_half(void *handler_priv, evt_info.hw_idx = rsrc_data->common_data->core_index; evt_info.res_type = CAM_ISP_RESOURCE_VFE_IN; + evt_info.evt_param = payload->evt_param; if (!rsrc_data->common_data->is_lite) { if (irq_status & 0x1) { @@ -2309,13 +2313,17 @@ static int cam_vfe_bus_ver3_stop_vfe_out( static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, struct cam_irq_th_payload *th_payload) { - int32_t rc; - int i; - struct cam_isp_resource_node *vfe_out = NULL; - struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; - struct cam_vfe_bus_irq_evt_payload *evt_payload; - struct cam_vfe_bus_ver3_comp_grp_data *resource_data; - uint32_t status_0; + int32_t rc; + int i; + struct cam_isp_resource_node *vfe_out = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_irq_evt_payload *evt_payload; + struct cam_vfe_bus_ver3_comp_grp_data *resource_data; + uint32_t status_0; + struct cam_vfe_bus_ver3_priv *bus_priv; + void __iomem *camnoc_mem_base = NULL; + uint32_t val0 = 0, val1 = 0, val2 = 0; + uint32_t comp_mask = 0; vfe_out = th_payload->handler_priv; if (!vfe_out) { @@ -2326,14 +2334,15 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, rsrc_data = vfe_out->res_priv; resource_data = rsrc_data->comp_grp->res_priv; + bus_priv = rsrc_data->bus_priv; + camnoc_mem_base = bus_priv->common_data.camnoc_mem_base; + CAM_DBG(CAM_ISP, "VFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", rsrc_data->common_data->core_index, th_payload->evt_status_arr[0], th_payload->evt_status_arr[1]); - rc = cam_vfe_bus_ver3_get_evt_payload(rsrc_data->common_data, &evt_payload); - if (rc) { CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X", @@ -2347,10 +2356,47 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, evt_payload->core_index = rsrc_data->common_data->core_index; evt_payload->evt_id = evt_id; + evt_payload->evt_param = 0; for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + if (bus_priv->common_data.cpas_version == CAM_CPAS_TITAN_570_V200) { + rc = cam_vfe_bus_ver3_handle_comp_done_bottom_half( + rsrc_data->comp_grp, evt_payload, &comp_mask); + + if ((comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI0)) || + (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI1)) || + (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI2)) || + (comp_mask & (1 << CAM_VFE_BUS_VER3_VFE_OUT_RDI3))) { + + /* Read Fill Level */ + val0 = cam_io_r_mb(camnoc_mem_base + 0xA20); + val1 = cam_io_r_mb(camnoc_mem_base + 0x1420); + val2 = cam_io_r_mb(camnoc_mem_base + 0x1A20); + CAM_DBG(CAM_ISP, + "comp_mask %d: CAMNOC REG[Queued Pending] ife_niu_1[%d %d] ife_niu_3[%d %d] ife_niu_0[%d %d]", + comp_mask, + (val0 & 0x7FF), (val0 & 0x7F0000) >> 16, + (val1 & 0x7FF), (val1 & 0x7F0000) >> 16, + (val2 & 0x7FF), (val2 & 0x7F0000) >> 16); + + if ((val1 & 0x7FF) > 205) { + CAM_ERR(CAM_ISP, "VFE:%d, Potential Error!!!", + rsrc_data->common_data->core_index); + CAM_INFO(CAM_ISP, + "comp_mask %d: CAMNOC REG[Queued Pending] ife_niu_1[%d %d] ife_niu_3[%d %d] ife_niu_0[%d %d]", + comp_mask, + (val0 & 0x7FF), (val0 & 0x7F0000) >> 16, + (val1 & 0x7FF), (val1 & 0x7F0000) >> 16, + (val2 & 0x7FF), (val2 & 0x7F0000) >> 16); + + evt_payload->evt_param = 1; + } + + } + } + th_payload->evt_payload_priv = evt_payload; status_0 = th_payload->evt_status_arr[CAM_IFE_IRQ_BUS_VER3_REG_STATUS0]; @@ -2412,7 +2458,7 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( struct cam_isp_hw_event_info evt_info; void *ctx = NULL; uint32_t evt_id = 0, comp_mask = 0; - uint32_t out_list[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; + uint32_t out_list[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; rc = cam_vfe_bus_ver3_handle_comp_done_bottom_half( rsrc_data->comp_grp, evt_payload_priv, &comp_mask); @@ -2429,6 +2475,7 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( evt_info.res_type = vfe_out->res_type; evt_info.hw_idx = vfe_out->hw_intf->hw_idx; + evt_info.evt_param = evt_payload->evt_param; rc = cam_vfe_bus_ver3_get_comp_vfe_out_res_id_list( comp_mask, out_list, &num_out); @@ -3790,6 +3837,9 @@ int cam_vfe_bus_ver3_init( 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.camnoc_mem_base = + CAM_SOC_GET_REG_MAP_START(soc_info, CAMNOC_CORE_BASE_IDX); + bus_priv->common_data.cpas_version = soc_private->cpas_version; bus_priv->common_data.hw_intf = hw_intf; bus_priv->common_data.vfe_irq_controller = vfe_irq_controller; bus_priv->common_data.common_reg = &ver3_hw_info->common_reg; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 72f108d9621a..3529babc8823 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -1323,10 +1323,18 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, struct cam_isp_resource_node *camif_node; struct cam_vfe_mux_camif_ver3_data *camif_priv; struct cam_vfe_top_irq_evt_payload *evt_payload; + struct cam_hw_soc_info *soc_info = NULL; + void __iomem *camnoc_mem_base = NULL; + struct cam_vfe_soc_private *soc_private = NULL; camif_node = th_payload->handler_priv; camif_priv = camif_node->res_priv; + soc_info = camif_priv->soc_info; + camnoc_mem_base = CAM_SOC_GET_REG_MAP_START(soc_info, 1); + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; + CAM_DBG(CAM_ISP, "VFE:%d CAMIF IRQ status_0: 0x%X status_1: 0x%X status_2: 0x%X", camif_node->hw_intf->hw_idx, th_payload->evt_status_arr[0], @@ -1364,6 +1372,17 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, trace_cam_log_event("SOF", "TOP_HALF", th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1], camif_node->hw_intf->hw_idx); + + switch (soc_private->cpas_version) { + case CAM_CPAS_TITAN_570_V200: + /* Reset Fill levels */ + cam_io_w_mb(0x1, camnoc_mem_base + 0x1A28); + cam_io_w_mb(0x1, camnoc_mem_base + 0xA28); + cam_io_w_mb(0x1, camnoc_mem_base + 0x1428); + break; + default: + break; + } } if (th_payload->evt_status_arr[CAM_IFE_IRQ_CAMIF_REG_STATUS1] diff --git a/include/uapi/camera/media/cam_sync.h b/include/uapi/camera/media/cam_sync.h index 9131afcacbb2..13b2e795c710 100644 --- a/include/uapi/camera/media/cam_sync.h +++ b/include/uapi/camera/media/cam_sync.h @@ -66,6 +66,7 @@ #define CAM_SYNC_ISP_EVENT_BUSIF_OVERFLOW (CAM_SYNC_ISP_EVENT_START + 5) #define CAM_SYNC_ISP_EVENT_FLUSH (CAM_SYNC_ISP_EVENT_START + 6) #define CAM_SYNC_ISP_EVENT_HW_STOP (CAM_SYNC_ISP_EVENT_START + 7) +#define CAM_SYNC_ISP_EVENT_BAD_FRAME (CAM_SYNC_ISP_EVENT_START + 8) #define CAM_SYNC_ISP_EVENT_END (CAM_SYNC_ISP_EVENT_START + 50) /* ICP Sync event reason types */ From 8564c269200e19e4785b8fde69900d17b4c88276 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 15 Oct 2020 20:32:53 +0530 Subject: [PATCH 723/790] msm: camera: req_mgr: Enhance camera v4l2 subdev shutdown sequence when provider crash occurred, there was a CSID lane overflow observed due to shutdown sequence from CRM(sensor, csid, csiphy). To fix the issue need to change the shutdown sequence (csid, sensor, csiphy). This change will update the devices sequence in order while registering and close the sequence accordingly. CRs-Fixed: 2852076 Change-Id: Ia6d8022e995823bf031400c33528eb8544dc2e29 Signed-off-by: Alok Chauhan --- drivers/cam_core/cam_context.c | 25 +++++++ drivers/cam_core/cam_context.h | 17 +++++ drivers/cam_core/cam_node.c | 21 ++++++ drivers/cam_core/cam_node.h | 28 +++++++- drivers/cam_core/cam_subdev.c | 17 ++++- drivers/cam_cpas/cam_cpas_intf.c | 24 ++++++- drivers/cam_cust/cam_custom_context.c | 18 +++++ drivers/cam_cust/cam_custom_context.h | 12 ++++ drivers/cam_cust/cam_custom_dev.c | 18 ++++- drivers/cam_fd/cam_fd_context.c | 28 +++++++- drivers/cam_fd/cam_fd_context.h | 13 +++- drivers/cam_fd/cam_fd_dev.c | 23 +++++- drivers/cam_icp/cam_icp_context.c | 21 +++++- drivers/cam_icp/cam_icp_context.h | 10 ++- drivers/cam_icp/cam_icp_subdev.c | 25 +++++-- drivers/cam_isp/cam_isp_context.c | 11 +++ drivers/cam_isp/cam_isp_context.h | 13 +++- drivers/cam_isp/cam_isp_dev.c | 17 ++++- drivers/cam_jpeg/cam_jpeg_context.c | 28 +++++++- drivers/cam_jpeg/cam_jpeg_context.h | 14 +++- drivers/cam_jpeg/cam_jpeg_dev.c | 18 ++++- drivers/cam_lrme/cam_lrme_context.c | 21 +++++- drivers/cam_lrme/cam_lrme_context.h | 14 +++- drivers/cam_lrme/cam_lrme_dev.c | 17 ++++- drivers/cam_ope/cam_ope_context.c | 21 +++++- drivers/cam_ope/cam_ope_context.h | 10 ++- drivers/cam_ope/cam_ope_subdev.c | 18 ++++- drivers/cam_req_mgr/cam_req_mgr_dev.c | 68 ++++++++++++++++-- drivers/cam_req_mgr/cam_req_mgr_dev.h | 8 ++- drivers/cam_req_mgr/cam_req_mgr_util.c | 33 ++++++++- drivers/cam_req_mgr/cam_req_mgr_util.h | 7 ++ drivers/cam_req_mgr/cam_subdev.h | 29 +++++++- .../cam_actuator/cam_actuator_dev.c | 65 +++++++++++------ .../cam_csiphy/cam_csiphy_dev.c | 69 ++++++++++++------ .../cam_eeprom/cam_eeprom_dev.c | 68 ++++++++++++------ .../cam_flash/cam_flash_dev.c | 60 +++++++++++----- .../cam_sensor_module/cam_ois/cam_ois_dev.c | 69 +++++++++++------- .../cam_sensor/cam_sensor_dev.c | 71 ++++++++++++------- 38 files changed, 869 insertions(+), 180 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 9492d681ea77..e07cac74ab9b 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -608,6 +608,31 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid stop device command payload"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev( + (struct v4l2_subdev *)cmd->handle, fh); + else + CAM_WARN(CAM_CORE, "No shutdown device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + + return rc; +} + int cam_context_handle_info_dump(void *context, enum cam_context_dump_id id) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 0ca3cccd8d87..8183ef9eb4de 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" #include "cam_smmu_api.h" @@ -95,6 +96,7 @@ struct cam_ctx_request { * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * @dump_dev: Function pointer for dump dev + * @shutdown_dev: Function pointer for shutdown dev * */ struct cam_ctx_ioctl_ops { @@ -114,6 +116,8 @@ struct cam_ctx_ioctl_ops { int (*release_hw)(struct cam_context *ctx, void *args); int (*dump_dev)(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); + int (*shutdown_dev)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); }; /** @@ -494,6 +498,19 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +/** + * cam_context_handle_shutdown_dev() + * + * @brief: Handle shutdown device command + * + * @ctx: Object pointer for cam_context + * @cmd: Shutdown device command payload + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + /** * cam_context_handle_dump_dev() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 5df221f71b6c..51e77066a09b 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -297,6 +297,27 @@ static int __cam_node_handle_stop_dev(struct cam_node *node, return rc; } +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + struct cam_context *ctx = NULL; + int32_t dev_index = -1; + int rc = 0, ret = 0; + + while ((dev_index = cam_get_dev_handle_info(cmd->handle, + &ctx, dev_index)) < CAM_REQ_MGR_MAX_HANDLES_V2) { + ret = cam_context_handle_shutdown_dev(ctx, cmd, fh); + if (ret) { + rc = ret; + CAM_ERR(CAM_CORE, "Shutdown failure for node %s", + node->name); + continue; + } + } + + return rc; +} + static int __cam_node_handle_config_dev(struct cam_node *node, struct cam_config_dev_cmd *config) { diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h index 062d0213115c..8b707a15246f 100644 --- a/drivers/cam_core/cam_node.h +++ b/drivers/cam_core/cam_node.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_NODE_H_ @@ -100,4 +100,30 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, */ void cam_node_put_ctxt_to_free_list(struct kref *ref); +/** + * cam_get_dev_handle_info() + * + * @brief: provides the active dev index. + * + * @handle: pointer to struct v4l2_dev + * @ctx: pointer to struct cam_context + * @dev_index: dev index + * + */ +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index); + +/** + * cam_node_handle_shutdown_dev() + * + * @brief: Shutdowns all the active devices. + * + * @node: pointer to struct node + * @cmd: pointer to struct cmd + * @fh: pointer to struct v4l2_subdev_fh + * + */ +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + #endif /* _CAM_NODE_H_ */ diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c index 1a81a4d59e99..a0e345840084 100644 --- a/drivers/cam_core/cam_subdev.c +++ b/drivers/cam_core/cam_subdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved. */ #include "cam_subdev.h" @@ -45,6 +45,8 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, long rc; struct cam_node *node = (struct cam_node *) v4l2_get_subdevdata(sd); + struct v4l2_subdev_fh *fh = (struct v4l2_subdev_fh *)arg; + struct cam_control cntrl_cmd; if (!node || node->state == CAM_NODE_STATE_UNINIT) { rc = -EINVAL; @@ -56,6 +58,19 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, rc = cam_node_handle_ioctl(node, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_WARN(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + cntrl_cmd.op_code = CAM_SD_SHUTDOWN; + cntrl_cmd.handle = (uint64_t)sd; + rc = cam_node_handle_shutdown_dev(node, &cntrl_cmd, fh); + if (rc) + CAM_ERR(CAM_CORE, "shutdown device failed(rc = %d)", + rc); + break; default: CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, node->name); diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index 7d007f4b3c29..bb6b9b97aaa4 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -671,7 +671,7 @@ static int cam_cpas_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_cpas_subdev_close(struct v4l2_subdev *sd, +static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); @@ -682,6 +682,11 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, } mutex_lock(&cpas_intf->intf_lock); + if (cpas_intf->open_cnt <= 0) { + CAM_WARN(CAM_CPAS, "device already closed, open_cnt: %d", cpas_intf->open_cnt); + mutex_unlock(&cpas_intf->intf_lock); + return 0; + } cpas_intf->open_cnt--; CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt); mutex_unlock(&cpas_intf->intf_lock); @@ -689,6 +694,19 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_cpas_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CPAS); + + if (crm_active) { + CAM_DBG(CAM_CPAS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return __cam_cpas_subdev_close(sd, fh); +} + static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -704,6 +722,9 @@ static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, case VIDIOC_CAM_CONTROL: rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + rc = __cam_cpas_subdev_close(sd, NULL); + break; default: CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); rc = -EINVAL; @@ -791,6 +812,7 @@ static int cam_cpas_subdev_register(struct platform_device *pdev) subdev->sd_flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->ent_function = CAM_CPAS_DEVICE_TYPE; + subdev->close_seq_prior = CAM_SD_CLOSE_LOW_PRIORITY; rc = cam_register_subdev(subdev); if (rc) { diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 134b5aa2b995..1df9bb29dde6 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1605,6 +1605,19 @@ static int __cam_custom_ctx_apply_default_req( return rc; } +static int __cam_custom_ctx_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_CUSTOM, "Invalid input pointer"); + return rc; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1619,6 +1632,7 @@ static struct cam_ctx_ops .ioctl_ops = { .acquire_dev = __cam_custom_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -1630,6 +1644,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev_in_acquired, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .link = __cam_custom_ctx_link_in_acquired, @@ -1648,6 +1663,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1665,6 +1681,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1681,6 +1698,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index ef7fe1f87434..74c45d541610 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -150,4 +150,16 @@ int cam_custom_dev_context_init(struct cam_custom_context *ctx, */ int cam_custom_dev_context_deinit(struct cam_custom_context *ctx); +/** + * cam_custom_subdev_close_internal() + * + * @brief: Close function for the Custom context + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_CUSTOM_CONTEXT_H_ */ diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index d1a344408493..36dde62fc51d 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -58,7 +58,7 @@ static int cam_custom_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_custom_subdev_close(struct v4l2_subdev *sd, +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -86,6 +86,19 @@ end: return rc; } +static int cam_custom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CUSTOM); + + if (crm_active) { + CAM_DBG(CAM_CUSTOM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { .close = cam_custom_subdev_close, .open = cam_custom_subdev_open, @@ -102,6 +115,7 @@ static int cam_custom_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; + g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME, CAM_CUSTOM_DEVICE_TYPE); diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index 99887d30242d..0f3fa85f079e 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -169,6 +169,19 @@ static int __cam_fd_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_fd_shutdown_dev(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_FD, "Invalid input pointer"); + return rc; + } + + return cam_fd_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -182,6 +195,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_fd_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -192,18 +206,25 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_acquired, .config_dev = __cam_fd_ctx_config_dev_in_acquired, .start_dev = __cam_fd_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = { }, + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, + }, /* Activated */ { .ioctl_ops = { @@ -212,6 +233,7 @@ static struct cam_ctx_ops .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, diff --git a/drivers/cam_fd/cam_fd_context.h b/drivers/cam_fd/cam_fd_context.h index ab0fa92b43f2..a57ed91d45b2 100644 --- a/drivers/cam_fd/cam_fd_context.h +++ b/drivers/cam_fd/cam_fd_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_CONTEXT_H_ @@ -27,4 +27,15 @@ int cam_fd_context_init(struct cam_fd_context *fd_ctx, uint32_t ctx_id); int cam_fd_context_deinit(struct cam_fd_context *ctx); +/** + * cam_fd_dev_close_internal() + * + * @brief: Close function for the fd dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_fd_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_FD_CONTEXT_H_ */ diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index e4285e2bf066..a58db056f6fb 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -57,7 +57,7 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_fd_dev_close(struct v4l2_subdev *sd, +static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_fd_dev *fd_dev = &g_fd_dev; @@ -69,6 +69,11 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, } mutex_lock(&fd_dev->lock); + if (fd_dev->open_cnt == 0) { + CAM_WARN(CAM_FD, "device already closed"); + mutex_unlock(&fd_dev->lock); + return 0; + } fd_dev->open_cnt--; CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); mutex_unlock(&fd_dev->lock); @@ -83,6 +88,19 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, return 0; } +static int cam_fd_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FD); + + if (crm_active) { + CAM_DBG(CAM_FD, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_fd_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { .open = cam_fd_dev_open, .close = cam_fd_dev_close, @@ -98,6 +116,7 @@ static int cam_fd_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; + g_fd_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ rc = cam_subdev_probe(&g_fd_dev.sd, pdev, CAM_FD_DEV_NAME, diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index aa25e137b6c6..03ead2c3b693 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -221,6 +221,12 @@ static int __cam_icp_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_icp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_icp_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -233,6 +239,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_icp_acquire_dev_in_available, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -245,6 +252,7 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, @@ -258,16 +266,23 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, .pagefault_ops = cam_icp_context_dump_active_request, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_icp_context_dump_active_request, diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h index 1062e8f005ff..9150bcf43f62 100644 --- a/drivers/cam_icp/cam_icp_context.h +++ b/drivers/cam_icp/cam_icp_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ICP_CONTEXT_H_ @@ -39,4 +39,12 @@ int cam_icp_context_init(struct cam_icp_context *ctx, */ int cam_icp_context_deinit(struct cam_icp_context *ctx); +/** + * cam_icp_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_ICP_CONTEXT_H_ */ diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 8c79bbbde5fe..3288964444ef 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -98,7 +98,7 @@ end: return rc; } -static int cam_icp_subdev_close(struct v4l2_subdev *sd, +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -107,9 +107,8 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_DBG(CAM_ICP, "ICP subdev is already closed"); - rc = -EINVAL; - goto end; + CAM_WARN(CAM_ICP, "ICP subdev is already closed"); + return 0; } g_icp_dev.open_cnt--; if (!node) { @@ -133,7 +132,20 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, end: mutex_unlock(&g_icp_dev.icp_lock); - return 0; + return rc; +} + +static int cam_icp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ICP); + + if (crm_active) { + CAM_DBG(CAM_ICP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_icp_subdev_close_internal(sd, fh); } const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { @@ -157,6 +169,7 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.sd.pdev = pdev; g_icp_dev.sd.internal_ops = &cam_icp_subdev_internal_ops; + g_icp_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME, CAM_ICP_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 68dd57d626fa..c979b6423e91 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5930,6 +5930,12 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_isp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_isp_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -5943,6 +5949,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_isp_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -5954,6 +5961,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, @@ -5973,6 +5981,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5990,6 +5999,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_flushed, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -6007,6 +6017,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 4a905a798380..108dc096d897 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ @@ -364,5 +364,16 @@ int cam_isp_context_init(struct cam_isp_context *ctx, */ int cam_isp_context_deinit(struct cam_isp_context *ctx); +/** + * cam_isp_subdev_close_internal() + * + * @brief: Close function for the isp dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); #endif /* __CAM_ISP_CONTEXT_H__ */ diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 6908a0807acb..9409c1015c6c 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -71,7 +71,7 @@ static int cam_isp_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_isp_subdev_close(struct v4l2_subdev *sd, +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -99,6 +99,18 @@ end: return rc; } +static int cam_isp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ISP); + + if (crm_active) { + CAM_DBG(CAM_ISP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_isp_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .close = cam_isp_subdev_close, .open = cam_isp_subdev_open, @@ -120,6 +132,7 @@ static int cam_isp_dev_component_bind(struct device *dev, (const char **)&compat_str); g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; + g_isp_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ if (strnstr(compat_str, "ife", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index f8d92c26f02f..20dd4a02127b 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -135,6 +135,12 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_jpeg_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_jpeg_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -148,6 +154,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = NULL, @@ -160,11 +167,30 @@ static struct cam_ctx_ops .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, .pagefault_ops = cam_jpeg_context_dump_active_request, }, + /* Ready */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Activated */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, }; int cam_jpeg_context_init(struct cam_jpeg_context *ctx, diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h index 3a11865a6051..d36bfb8bb175 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.h +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_JPEG_CONTEXT_H_ @@ -64,4 +64,16 @@ int cam_jpeg_context_init(struct cam_jpeg_context *ctx, */ int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx); +/** + * cam_jpeg_subdev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* __CAM_JPEG_CONTEXT_H__ */ diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index f627e8850de9..a47476a06144 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -56,13 +56,12 @@ static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); - mutex_lock(&g_jpeg_dev.jpeg_mutex); if (g_jpeg_dev.open_cnt <= 0) { CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); @@ -86,6 +85,18 @@ end: return rc; } +static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_JPEG); + + if (crm_active) { + CAM_DBG(CAM_JPEG, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_jpeg_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .close = cam_jpeg_subdev_close, .open = cam_jpeg_subdev_open, @@ -102,6 +113,7 @@ static int cam_jpeg_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; + g_jpeg_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, CAM_JPEG_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index 857aab9dd476..7025b384b1d2 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -172,6 +172,12 @@ static int __cam_lrme_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_lrme_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_lrme_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -185,6 +191,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_lrme_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -195,18 +202,25 @@ static struct cam_ctx_ops .config_dev = __cam_lrme_ctx_config_dev_in_activated, .release_dev = __cam_lrme_ctx_release_dev_in_acquired, .start_dev = __cam_lrme_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, + }, /* Activate */ { .ioctl_ops = { @@ -215,6 +229,7 @@ static struct cam_ctx_ops .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, .dump_dev = __cam_lrme_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h index 9fb88ed85f1b..f1b5ff267f6a 100644 --- a/drivers/cam_lrme/cam_lrme_context.h +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_LRME_CONTEXT_H_ @@ -30,4 +30,16 @@ int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, uint32_t index); int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx); +/** + * cam_lrme_dev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_LRME_CONTEXT_H_ */ diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 28d11305223a..5055444c3d8a 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -72,7 +72,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_lrme_dev_close(struct v4l2_subdev *sd, +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -106,6 +106,18 @@ end: return rc; } +static int cam_lrme_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_LRME); + + if (crm_active) { + CAM_DBG(CAM_LRME, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_lrme_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { .open = cam_lrme_dev_open, .close = cam_lrme_dev_close, @@ -126,6 +138,7 @@ static int cam_lrme_component_bind(struct device *dev, return -ENOMEM; } g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops; + g_lrme_dev->sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; mutex_init(&g_lrme_dev->lock); diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index cbd4cf50c236..c8be0da353d4 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -195,6 +195,12 @@ static int __cam_ope_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_ope_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_ope_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -207,6 +213,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_ope_acquire_dev_in_available, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -219,6 +226,7 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -232,14 +240,23 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, .pagefault_ops = cam_ope_context_dump_active_request, }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_ope_context_dump_active_request, diff --git a/drivers/cam_ope/cam_ope_context.h b/drivers/cam_ope/cam_ope_context.h index 9d0779ce2b3d..5e6d28c3ff59 100644 --- a/drivers/cam_ope/cam_ope_context.h +++ b/drivers/cam_ope/cam_ope_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_OPE_CONTEXT_H_ @@ -41,4 +41,12 @@ int cam_ope_context_init(struct cam_ope_context *ctx, */ int cam_ope_context_deinit(struct cam_ope_context *ctx); +/** + * cam_ope_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_OPE_CONTEXT_H_ */ diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index df9de9993a3e..a04abe3bcf8c 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -95,7 +95,7 @@ end: return rc; } -static int cam_ope_subdev_close(struct v4l2_subdev *sd, +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -134,6 +134,19 @@ end: return rc; } +static int cam_ope_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OPE); + + if (crm_active) { + CAM_DBG(CAM_OPE, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ope_subdev_close_internal(sd, fh); +} + const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { .open = cam_ope_subdev_open, .close = cam_ope_subdev_close, @@ -156,6 +169,7 @@ static int cam_ope_subdev_component_bind(struct device *dev, g_ope_dev.sd.pdev = pdev; g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops; + g_ope_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME, CAM_OPE_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 5785beaf15a6..350c9ea171bf 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -17,6 +17,7 @@ #include #include #include +#include #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" @@ -32,6 +33,7 @@ static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; +static struct list_head cam_req_mgr_ordered_sd_list; static struct device_attribute camera_debug_sysfs_attr = __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); @@ -122,6 +124,7 @@ static int cam_req_mgr_open(struct file *filep) spin_unlock_bh(&g_dev.cam_eventq_lock); g_dev.open_cnt++; + g_dev.read_active_dev_id_hdls = 0; rc = cam_mem_mgr_init(); if (rc) { g_dev.open_cnt--; @@ -158,6 +161,7 @@ static unsigned int cam_req_mgr_poll(struct file *f, static int cam_req_mgr_close(struct file *filep) { struct v4l2_subdev *sd; + struct cam_subdev *csd; struct v4l2_fh *vfh = filep->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); @@ -172,18 +176,23 @@ static int cam_req_mgr_close(struct file *filep) } cam_req_mgr_handle_core_shutdown(); + g_dev.shutdown_state = true; - list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + list_for_each_entry(csd, &cam_req_mgr_ordered_sd_list, list) { + sd = &csd->sd; if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) continue; - if (sd->internal_ops && sd->internal_ops->close) { + if (sd->internal_ops) { CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", sd->name); - sd->internal_ops->close(sd, subdev_fh); + v4l2_subdev_call(sd, core, ioctl, + CAM_SD_SHUTDOWN, subdev_fh); } } g_dev.open_cnt--; + g_dev.shutdown_state = false; + g_dev.read_active_dev_id_hdls = 0; v4l2_fh_release(filep); spin_lock_bh(&g_dev.cam_eventq_lock); @@ -659,6 +668,51 @@ void cam_subdev_notify_message(u32 subdev_type, } EXPORT_SYMBOL(cam_subdev_notify_message); + +static int cam_req_mgr_ordered_list_cmp(void *priv, + struct list_head *head_1, struct list_head *head_2) +{ + struct cam_subdev *entry_1 = + list_entry(head_1, struct cam_subdev, list); + struct cam_subdev *entry_2 = + list_entry(head_2, struct cam_subdev, list); + int ret = -1; + + if (entry_1->close_seq_prior > entry_2->close_seq_prior) + return 1; + else if (entry_1->close_seq_prior < entry_2->close_seq_prior) + return ret; + else + return 0; +} + +bool cam_req_mgr_is_open(uint64_t dev_id) +{ + bool crm_status; + bool dev_id_status; + + mutex_lock(&g_dev.cam_lock); + crm_status = g_dev.open_cnt ? true : false; + + if (!g_dev.read_active_dev_id_hdls) { + g_dev.active_dev_id_hdls = cam_get_dev_handle_status(); + g_dev.read_active_dev_id_hdls++; + } + + dev_id_status = (g_dev.active_dev_id_hdls & dev_id) ? true : false; + crm_status &= dev_id_status; + mutex_unlock(&g_dev.cam_lock); + + return crm_status; +} +EXPORT_SYMBOL(cam_req_mgr_is_open); + +bool cam_req_mgr_is_shutdown(void) +{ + return g_dev.shutdown_state; +} +EXPORT_SYMBOL(cam_req_mgr_is_shutdown); + int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -687,6 +741,10 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; + list_add(&csd->list, &cam_req_mgr_ordered_sd_list); + list_sort(NULL, &cam_req_mgr_ordered_sd_list, + cam_req_mgr_ordered_list_cmp); + rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); @@ -747,6 +805,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto video_setup_fail; g_dev.open_cnt = 0; + g_dev.shutdown_state = false; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); mutex_init(&g_dev.dev_lock); @@ -764,6 +823,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) } g_dev.state = true; + INIT_LIST_HEAD(&cam_req_mgr_ordered_sd_list); if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 464720efb0a2..0a55789b7c7d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_DEV_H_ @@ -19,6 +19,9 @@ * @cam_lock: per file handle lock * @cam_eventq: event queue * @cam_eventq_lock: lock for event queue + * @shutdown_state: shutdown state + * @active_dev_id_hdls: active dev id handles + * @read_active_dev_id_hdls: read active_dev_id_hdls status */ struct cam_req_mgr_device { struct video_device *video; @@ -30,6 +33,9 @@ struct cam_req_mgr_device { struct mutex cam_lock; struct v4l2_fh *cam_eventq; spinlock_t cam_eventq_lock; + bool shutdown_state; + uint64_t active_dev_id_hdls; + int read_active_dev_id_hdls; }; #define CAM_REQ_MGR_GET_PAYLOAD_PTR(ev, type) \ diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 4b1f4d8e8622..00b919fcec30 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__ @@ -14,6 +14,7 @@ #include #include "cam_req_mgr_util.h" #include "cam_debug_util.h" +#include "cam_context.h" static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static DEFINE_SPINLOCK(hdl_tbl_lock); @@ -209,6 +210,36 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) return handle; } +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index) +{ + int32_t idx; + struct v4l2_subdev *sd = (struct v4l2_subdev *)handle; + + for (idx = dev_index + 1; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) { + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) { + *ctx = (struct cam_context *)cam_get_device_priv( + hdl_tbl->hdl[idx].hdl_value); + if ((*ctx) && !strcmp(sd->name, (*ctx)->dev_name)) + return idx; + } + } + *ctx = NULL; + return CAM_REQ_MGR_MAX_HANDLES_V2; +} + +uint64_t cam_get_dev_handle_status(void) +{ + int32_t idx; + uint64_t active_dev_hdls = 0; + + for (idx = 0; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) + active_dev_hdls |= hdl_tbl->hdl[idx].dev_id; + + return active_dev_hdls; +} + void *cam_get_device_priv(int32_t dev_hdl) { int idx; diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index 9cf733871569..6656f1d1dad6 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -166,4 +166,11 @@ int32_t cam_req_mgr_util_deinit(void); */ int32_t cam_req_mgr_util_free_hdls(void); +/** + * cam_get_dev_handle_status() - get dev handles status + * + * Returns dev handle status + */ +uint64_t cam_get_dev_handle_status(void); + #endif /* _CAM_REQ_MGR_UTIL_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index ae22529ef2a1..e37d7177c8a3 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SUBDEV_H_ @@ -21,6 +21,13 @@ enum cam_subdev_message_type_t { CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; +/* Enum for close sequence priority */ +enum cam_subdev_close_seq_priority { + CAM_SD_CLOSE_HIGH_PRIORITY, + CAM_SD_CLOSE_MEDIUM_PRIORITY, + CAM_SD_CLOSE_LOW_PRIORITY +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -39,6 +46,8 @@ enum cam_subdev_message_type_t { * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. + * @list: list pointer + * @close_seq_prior: cam_subdev_close_seq_priority type * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be @@ -58,6 +67,8 @@ struct cam_subdev { struct v4l2_subdev *sd, enum cam_subdev_message_type_t msg_type, uint32_t data); + struct list_head list; + enum cam_subdev_close_seq_priority close_seq_prior; }; /** @@ -119,4 +130,20 @@ int cam_register_subdev(struct cam_subdev *sd); */ int cam_unregister_subdev(struct cam_subdev *sd); +/** + * cam_req_mgr_is_open() + * + * @brief: This common utility function returns the crm active status + * + * @dev_id: device id type + */ +bool cam_req_mgr_is_open(uint64_t dev_id); + +/** + * cam_req_mgr_is_shutdown() + * + * @brief: This common utility function returns the shutdown state + */ +bool cam_req_mgr_is_shutdown(void); + #endif /* _CAM_SUBDEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 8b180a767d37..d51dae6d37d7 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_actuator_dev.h" @@ -10,6 +10,38 @@ #include "cam_trace.h" #include "camera_main.h" +static int cam_actuator_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + cam_actuator_shutdown(a_ctrl); + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + +static int cam_actuator_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); + + if (crm_active) { + CAM_INFO(CAM_ACTUATOR, + "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_actuator_subdev_close_internal(sd, fh); +} + static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -24,6 +56,14 @@ static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, CAM_ERR(CAM_ACTUATOR, "Failed for driver_cmd: %d", rc); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_actuator_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd: %u", cmd); rc = -ENOIOCTLCMD; @@ -77,24 +117,6 @@ static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, } #endif -static int cam_actuator_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_actuator_ctrl_t *a_ctrl = - v4l2_get_subdevdata(sd); - - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&(a_ctrl->actuator_mutex)); - cam_actuator_shutdown(a_ctrl); - mutex_unlock(&(a_ctrl->actuator_mutex)); - - return 0; -} - static struct v4l2_subdev_core_ops cam_actuator_subdev_core_ops = { .ioctl = cam_actuator_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -127,10 +149,13 @@ static int cam_actuator_init_subdev(struct cam_actuator_ctrl_t *a_ctrl) a_ctrl->v4l2_dev_str.ent_function = CAM_ACTUATOR_DEVICE_TYPE; a_ctrl->v4l2_dev_str.token = a_ctrl; + a_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str)); if (rc) - CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); + CAM_ERR(CAM_ACTUATOR, + "Fail with cam_register_subdev rc: %d", rc); return rc; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index fbe53591fc6e..17216d86d038 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -77,29 +77,7 @@ static void cam_csiphy_debug_unregister(void) root_dentry = NULL; } -static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); - int rc = 0; - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_csiphy_core_cfg(csiphy_dev, arg); - if (rc) - CAM_ERR(CAM_CSIPHY, - "Failed in configuring the device: %d", rc); - break; - default: - CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, +static int cam_csiphy_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct csiphy_device *csiphy_dev = @@ -117,6 +95,49 @@ static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); + + if (crm_active) { + CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_csiphy_subdev_close_internal(sd, fh); +} + +static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + int rc = 0; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_core_cfg(csiphy_dev, arg); + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in configuring the device: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_csiphy_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + #ifdef CONFIG_COMPAT static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -236,6 +257,8 @@ static int cam_csiphy_component_bind(struct device *dev, cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; + new_csiphy_dev->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str)); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 435ca815e4c9..cfcc166892d7 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_eeprom_dev.h" @@ -10,28 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_eeprom_driver_cmd(e_ctrl, arg); - if (rc) - CAM_ERR(CAM_EEPROM, - "Failed in Driver cmd: %d", rc); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, +static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_eeprom_ctrl_t *e_ctrl = @@ -49,6 +28,48 @@ static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); + + if (crm_active) { + CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_eeprom_subdev_close_internal(sd, fh); +} + +static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_driver_cmd(e_ctrl, arg); + if (rc) + CAM_ERR(CAM_EEPROM, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_eeprom_subdev_close_internal(sd, NULL); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_i2c_info_t *i2c_info) { @@ -147,6 +168,7 @@ static int cam_eeprom_init_subdev(struct cam_eeprom_ctrl_t *e_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE; e_ctrl->v4l2_dev_str.token = e_ctrl; + e_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 8929a4b889fa..8386d8d6b817 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -236,6 +236,37 @@ static const struct of_device_id cam_flash_dt_match[] = { {} }; +static int cam_flash_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_flash_ctrl *fctrl = + v4l2_get_subdevdata(sd); + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + +static int cam_flash_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FLASH); + + if (crm_active) { + CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_flash_subdev_close_internal(sd, fh); +} + static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -257,6 +288,14 @@ static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, "Failed in driver cmd: %d", rc); break; } + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_flash_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); rc = -ENOIOCTLCMD; @@ -328,24 +367,6 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) return rc; } -static int cam_flash_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_flash_ctrl *fctrl = - v4l2_get_subdevdata(sd); - - if (!fctrl) { - CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&fctrl->flash_mutex); - cam_flash_shutdown(fctrl); - mutex_unlock(&fctrl->flash_mutex); - - return 0; -} - static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = { .ioctl = cam_flash_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -375,6 +396,7 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; fctrl->v4l2_dev_str.token = fctrl; + fctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index a52e59b25af0..94b6a9cd8271 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_ois_dev.h" @@ -10,29 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_ois_driver_cmd(o_ctrl, arg); - if (rc) - CAM_ERR(CAM_OIS, - "Failed with driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_ois_subdev_close(struct v4l2_subdev *sd, +static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_ois_ctrl_t *o_ctrl = @@ -50,6 +28,48 @@ static int cam_ois_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_ois_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OIS); + + if (crm_active) { + CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ois_subdev_close_internal(sd, fh); +} + +static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_driver_cmd(o_ctrl, arg); + if (rc) + CAM_ERR(CAM_OIS, + "Failed with driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + rc = cam_ois_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl, struct cam_ois_i2c_info_t *i2c_info) { @@ -144,6 +164,7 @@ static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE; o_ctrl->v4l2_dev_str.token = o_ctrl; + o_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 1b7f0261260e..9c6e2f2a2060 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_sensor_dev.h" @@ -9,29 +9,7 @@ #include "cam_sensor_core.h" #include "camera_main.h" -static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_sensor_ctrl_t *s_ctrl = - v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_sensor_driver_cmd(s_ctrl, arg); - if (rc) - CAM_ERR(CAM_SENSOR, - "Failed in Driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -static int cam_sensor_subdev_close(struct v4l2_subdev *sd, +static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_sensor_ctrl_t *s_ctrl = @@ -49,6 +27,49 @@ static int cam_sensor_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_sensor_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); + + if (crm_active) { + CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_sensor_subdev_close_internal(sd, fh); +} + +static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_sensor_driver_cmd(s_ctrl, arg); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_sensor_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + #ifdef CONFIG_COMPAT static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -122,6 +143,8 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE; s_ctrl->v4l2_dev_str.token = s_ctrl; + s_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); if (rc) From 89c548e862201e2163f0f869dd869de535316d1d Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Mon, 8 Mar 2021 12:33:46 +0530 Subject: [PATCH 724/790] msm: camera: csiphy: Update CSIPHY settings based recommendation CSIPHY settings updated based on latest HPG settings and enabled deskew calibration. CRs-Fixed: 2918358 Change-Id: I130bf9024cda95b0d5742ec32a2efd0968127f7c Signed-off-by: Anil Kumar Kanakanti --- .../include/cam_csiphy_1_2_1_hwreg.h | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 4d8a32940299..56cf75b9a866 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_1_HWREG_H_ @@ -15,7 +15,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 20, + .csiphy_2ph_config_array_size = 23, .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -71,9 +71,12 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -93,7 +96,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -115,9 +118,12 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x025C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0260, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0264, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -137,9 +143,12 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -159,9 +168,12 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x065C, 0x00, 0x00, CSIPHY_SKEW_CAL}, + {0x0660, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0664, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -185,7 +197,7 @@ struct csiphy_reg_t {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -207,7 +219,7 @@ struct csiphy_reg_t {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -229,7 +241,7 @@ struct csiphy_reg_t {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -251,7 +263,7 @@ struct csiphy_reg_t {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -273,7 +285,7 @@ struct csiphy_reg_t {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, From e315662891dbf51773246a1e0c82cf88cf1c53ce Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 25 Mar 2021 23:28:22 +0530 Subject: [PATCH 725/790] msm: camera: isp: Dont enable Wm configurations during HW start There is a chance that during acquire time while updating write master, for few resources io buffers are not allocated. If Wm configurations are enabled without receiving io buffers then there is a chance of hitting page fault issues. This commit takes care of enabling Wm configurations for each client only if io buffers are allocated. CRs-Fixed: 2887053 Change-Id: I868bd01dbd896dd86eeec4fc92a8a62e746f79cf Signed-off-by: Shravya Samala --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 53436df08dfa..c5fe7d82fa0d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -1330,10 +1330,9 @@ static int cam_vfe_bus_start_wm( return -EINVAL; } } - - /* Enable WM */ - cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base + - rsrc_data->hw_regs->cfg); + /* enabling Wm configuratons are taken care in update_wm(). + * i.e enable wm only if io buffers are allocated + */ CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index, rsrc_data->width, rsrc_data->height); From 7773e50836468c497b9459fe2c6e44b809f5b9cb Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 1 Apr 2021 17:01:50 +0530 Subject: [PATCH 726/790] msm: camera: isp: Change logic of acquiring dual composite group There is a possibility of composite groups in free dual composite group list are not in sequential order. In case of dual ife use case, if composite groups are not in sequential manner then we landed into a scenario where two different IFE with same resource have two different composite group index, which is not expected. This commit ensures if it is dual IFE usecase then at the time of acquiring composite group, both IFEs have same composite group ID for same resource. CRs-Fixed: 2912721 Change-Id: I734d1d1660c1e70e0480e2dc0b8377a1c441c634 Signed-off-by: Shravya Samala --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 53436df08dfa..d1e8db83c6bf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -262,6 +262,28 @@ static enum cam_vfe_bus_comp_grp_id } } +static enum cam_vfe_bus_ver2_comp_grp_type + cam_vfe_bus_dual_comp_grp_id_convert(uint32_t comp_grp) +{ + switch (comp_grp) { + case CAM_VFE_BUS_COMP_GROUP_ID_0: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0; + case CAM_VFE_BUS_COMP_GROUP_ID_1: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1; + case CAM_VFE_BUS_COMP_GROUP_ID_2: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2; + case CAM_VFE_BUS_COMP_GROUP_ID_3: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3; + case CAM_VFE_BUS_COMP_GROUP_ID_4: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4; + case CAM_VFE_BUS_COMP_GROUP_ID_5: + return CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5; + case CAM_VFE_BUS_COMP_GROUP_NONE: + default: + return CAM_VFE_BUS_VER2_COMP_GRP_MAX; + } +} + static int cam_vfe_bus_put_evt_payload( struct cam_vfe_bus_ver2_common_data *common_data, struct cam_vfe_bus_irq_evt_payload **evt_payload) @@ -1609,6 +1631,38 @@ static void cam_vfe_bus_match_comp_grp( *comp_grp = NULL; } +static int cam_vfe_bus_get_free_dual_comp_grp( + struct cam_vfe_bus_ver2_priv *ver2_bus_priv, + struct cam_isp_resource_node **comp_grp, + uint32_t comp_grp_local_idx) +{ + struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; + struct cam_isp_resource_node *dual_comp_grp_local = NULL; + struct cam_isp_resource_node *dual_comp_grp_local_temp = NULL; + int32_t dual_comp_grp_idx = 0; + int rc = -EINVAL; + + dual_comp_grp_idx = cam_vfe_bus_dual_comp_grp_id_convert(comp_grp_local_idx); + + CAM_DBG(CAM_ISP, "dual_comp_grp_idx :%d", dual_comp_grp_idx); + + list_for_each_entry_safe(dual_comp_grp_local, dual_comp_grp_local_temp, + &ver2_bus_priv->free_dual_comp_grp, list) { + rsrc_data = dual_comp_grp_local->res_priv; + CAM_DBG(CAM_ISP, "current grp type : %d expected :%d", + rsrc_data->comp_grp_type, dual_comp_grp_idx); + if (dual_comp_grp_idx != rsrc_data->comp_grp_type) { + continue; + } else { + list_del_init(&dual_comp_grp_local->list); + *comp_grp = dual_comp_grp_local; + return 0; + } + } + + return rc; +} + static int cam_vfe_bus_acquire_comp_grp( struct cam_vfe_bus_ver2_priv *ver2_bus_priv, struct cam_isp_out_port_generic_info *out_port_info, @@ -1641,9 +1695,14 @@ static int cam_vfe_bus_acquire_comp_grp( CAM_ERR(CAM_ISP, "No Free Composite Group"); return -ENODEV; } - comp_grp_local = list_first_entry( - &ver2_bus_priv->free_dual_comp_grp, - struct cam_isp_resource_node, list); + rc = cam_vfe_bus_get_free_dual_comp_grp( + ver2_bus_priv, &comp_grp_local, bus_comp_grp_id); + if (rc || !comp_grp_local) { + CAM_ERR(CAM_ISP, + "failed to acquire dual comp grp for :%d rc :%d", + bus_comp_grp_id, rc); + return rc; + } rsrc_data = comp_grp_local->res_priv; rc = cam_vfe_bus_ver2_get_intra_client_mask( dual_slave_core, From ec6656b5fc4425798304501ab286e001f59cc15d Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 12 Apr 2021 21:08:13 +0530 Subject: [PATCH 727/790] Revert "msm: camera: req_mgr: Validate active sequence id in link control" This reverts commit 4580f024fed5cd208c1dab2470fa34dd149d5770. CRs-Fixed: 2898158 Change-Id: I29ab6ef02df0b30093c9f6a295eb74351f480a00 Signed-off-by: Ayush Kumar --- drivers/cam_req_mgr/cam_req_mgr_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index a18a1ab56bd0..36a105be5a1d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -5009,10 +5009,7 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->state = CAM_CRM_LINK_STATE_IDLE; link->skip_init_frame = false; crm_timer_exit(&link->watchdog); - if ((link->activate_seq >= 0) && - (link->activate_seq < MAXIMUM_LINKS_PER_SESSION)) - clear_bit(link->activate_seq, g_crm_core_dev->bitmap); - + clear_bit(link->activate_seq, g_crm_core_dev->bitmap); link->activate_seq = -1; spin_unlock_bh(&link->link_state_spin_lock); CAM_DBG(CAM_CRM, From 7176fc67991de37fca893cbc27c6683bb232f0f8 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 22 Dec 2020 13:59:52 +0530 Subject: [PATCH 728/790] Revert "msm: camera: req_mgr: Re-design CRM to support multi links in sync mode" This reverts commit 65a86de9799e86931dddae537b56a868220fdade. CRs-Fixed: 2898158 Change-Id: I9818bb8a0714f8251e2c8edc9e36743b1a2f9f96 Signed-off-by: Ayush Kumar --- drivers/cam_core/cam_context.c | 29 +- drivers/cam_core/cam_context.h | 17 +- drivers/cam_core/cam_node.c | 21 +- drivers/cam_cust/cam_custom_context.c | 1 - drivers/cam_isp/cam_isp_context.c | 202 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 10 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 1796 ++++++----------- drivers/cam_req_mgr/cam_req_mgr_core.h | 55 +- drivers/cam_req_mgr/cam_req_mgr_interface.h | 66 +- .../cam_actuator/cam_actuator_core.c | 1 - .../cam_flash/cam_flash_core.c | 2 - .../cam_sensor/cam_sensor_core.c | 1 - 12 files changed, 656 insertions(+), 1545 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 9492d681ea77..75424db0c16a 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -182,33 +182,6 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } -int cam_context_handle_crm_state_change(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info) -{ - int rc; - - if (!ctx->state_machine) { - CAM_ERR(CAM_CORE, "Context is not ready"); - return -EINVAL; - } - - if (!state_info) { - CAM_ERR(CAM_CORE, "Invalid change state payload"); - return -EINVAL; - } - - if (ctx->state_machine[ctx->state].crm_ops.change_state) { - rc = ctx->state_machine[ctx->state].crm_ops.change_state(ctx, - state_info); - } else { - CAM_ERR(CAM_CORE, "No crm change state req in dev %d, state %d", - ctx->dev_hdl, ctx->state); - rc = -EPROTO; - } - - return rc; -} - int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 0ca3cccd8d87..5be078536ff5 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -127,7 +127,6 @@ struct cam_ctx_ioctl_ops { * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request - * @change_state: Change sub-state of hw context layer to bubble * */ struct cam_ctx_crm_ops { @@ -147,8 +146,6 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_link_evt_data *evt_data); int (*dump_req)(struct cam_context *ctx, struct cam_req_mgr_dump_info *dump); - int (*change_state)(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *change_state); }; @@ -313,18 +310,6 @@ int cam_context_handle_crm_unlink(struct cam_context *ctx, int cam_context_handle_crm_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); -/** - * cam_context_handle_crm_state_change() - * - * @brief: Handle state change request - * - * @ctx: Object pointer for cam_context - * @state_info: State change request command payload - * - */ -int cam_context_handle_crm_state_change(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info); - /** * cam_context_handle_crm_notify_frame_skip() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 5df221f71b6c..c3770f2df745 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -619,24 +619,6 @@ static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) return cam_context_handle_crm_flush_req(ctx, flush); } -static int __cam_node_crm_state_change_req( - struct cam_req_mgr_request_change_state *state_info) -{ - struct cam_context *ctx = NULL; - - if (!state_info) - return -EINVAL; - - ctx = (struct cam_context *) cam_get_device_priv(state_info->dev_hdl); - if (!ctx) { - CAM_ERR(CAM_CORE, "Can not get context for handle %d", - state_info->dev_hdl); - return -EINVAL; - } - - return cam_context_handle_crm_state_change(ctx, state_info); -} - static int __cam_node_crm_process_evt( struct cam_req_mgr_link_evt_data *evt_data) { @@ -733,7 +715,6 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.dump_req = __cam_node_crm_dump_req; node->crm_node_intf.notify_frame_skip = __cam_node_crm_notify_frame_skip; - node->crm_node_intf.change_state = __cam_node_crm_state_change_req; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 134b5aa2b995..ca4d1d1e35d5 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -549,7 +549,6 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; - dev_info->sof_ts_cb = NULL; return 0; } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 68dd57d626fa..d9556ccb895c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -743,8 +743,8 @@ static void __cam_isp_ctx_send_sof_timestamp( req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, - "link hdl 0x%x request id:%lld frame number:%lld SOF time stamp:%lld status:%u", - ctx_isp->base->link_hdl, request_id, ctx_isp->frame_id, + "request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u", + request_id, ctx_isp->frame_id, ctx_isp->sof_timestamp_val, sof_event_status); if (cam_req_mgr_notify_message(&req_msg, @@ -1700,7 +1700,6 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( } 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; @@ -1709,9 +1708,8 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( ctx_isp->active_req_cnt++; request_id = req->request_id; CAM_DBG(CAM_REQ, - "move request %lld to active list(cnt = %d), ctx %u link %x", - req->request_id, ctx_isp->active_req_cnt, - ctx->ctx_id, ctx->link_hdl); + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_RUP, req); } else { @@ -1853,7 +1851,6 @@ notify_only: notify.trigger = CAM_TRIGGER_POINT_SOF; notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - notify.sof_boottime = ctx_isp->boot_timestamp; notify.trigger_id = ctx_isp->trigger_id; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -1973,9 +1970,8 @@ static int __cam_isp_ctx_sof_in_activated_state( __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_SOF, request_id); - CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u link %x", - ctx_isp->frame_id, ctx_isp->sof_timestamp_val, - ctx->ctx_id, ctx->link_hdl); + 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; } @@ -2020,7 +2016,6 @@ end: static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { - bool rc = false; uint64_t request_id = 0; uint32_t sof_event_status = CAM_REQ_MGR_SOF_EVENT_SUCCESS; struct cam_req_mgr_trigger_notify notify; @@ -2059,9 +2054,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; - CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d link %x Report Bubble flag %d req id:%lld", - ctx->ctx_id, ctx->link_hdl, - req_isp->bubble_report, req->request_id); + CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", + ctx->ctx_id, req_isp->bubble_report, req->request_id); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; @@ -2075,25 +2069,12 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - notify.sof_boottime_val = ctx_isp->boot_timestamp; - notify.need_recovery = true; CAM_WARN_RATE_LIMIT(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); trace_cam_log_event("Bubble", "Rcvd epoch in applied state", req->request_id, ctx->ctx_id); - rc = ctx->ctx_crm_intf->notify_err(¬ify); - - CAM_DBG(CAM_CRM, "Need bubble recovery %d", rc); - - if (rc) { - req_isp->bubble_detected = false; - req_isp->reapply = false; - CAM_DBG(CAM_ISP, "Disable bubble for ctx %d link %d", - ctx->ctx_id, ctx->link_hdl); - return 0; - } - + ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; @@ -2268,7 +2249,6 @@ static int __cam_isp_ctx_buf_done_in_bubble( static int __cam_isp_ctx_epoch_in_bubble_applied( struct cam_isp_context *ctx_isp, void *evt_data) { - int rc = 0; uint64_t request_id = 0; struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; @@ -2326,17 +2306,10 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - notify.sof_boottime_val = ctx_isp->boot_timestamp; - notify.need_recovery = true; CAM_WARN_RATE_LIMIT(CAM_REQ, "Notify CRM about Bubble req_id %llu frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); - rc = ctx->ctx_crm_intf->notify_err(¬ify); - if (rc) { - req_isp->bubble_detected = false; - req_isp->reapply = false; - return 0; - } + ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; @@ -3200,10 +3173,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( goto end; } - CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u link %x", + CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u", req->request_id, __cam_isp_ctx_substate_val_to_type(ctx_isp->substate_activated), - ctx->ctx_id, ctx->link_hdl); + ctx->ctx_id); req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (ctx_isp->active_req_cnt >= 2) { @@ -3286,81 +3259,6 @@ end: return rc; } -static int __cam_isp_ctx_change_substate( - struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info) -{ - int rc = 0; - uint64_t request_id = 0; - struct cam_ctx_request *req = NULL; - struct cam_ctx_request *req_temp = NULL; - struct cam_ctx_request *bubble_req = NULL; - struct cam_isp_ctx_req *req_isp = NULL; - struct cam_isp_context *ctx_isp = - (struct cam_isp_context *) ctx->ctx_priv; - - if (!list_empty(&ctx->wait_req_list)) { - req = list_first_entry(&ctx->wait_req_list, - struct cam_ctx_request, - list); - if (req->request_id == state_info->req_id) { - req_isp = (struct cam_isp_ctx_req *)req->req_priv; - req_isp->bubble_detected = true; - req_isp->reapply = true; - bubble_req = req; - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->active_req_list); - goto end; - } - } else { - CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id); - } - - if (!bubble_req) { - list_for_each_entry_safe(req, req_temp, - &ctx->active_req_list, list) { - if (req->request_id == state_info->req_id) { - req_isp = - (struct cam_isp_ctx_req *)req->req_priv; - req_isp->bubble_detected = true; - req_isp->reapply = true; - bubble_req = req; - break; - } - } - } - - if (!bubble_req) { - CAM_ERR(CAM_ISP, "Req %lld not in active list ctx : %d", - state_info->req_id, - ctx->ctx_id); - goto done; - } - -end: - - if (req_isp->bubble_report) - atomic_set(&ctx_isp->process_bubble, 1); - - if ((req->request_id > ctx_isp->reported_req_id) - && !req_isp->bubble_report) { - request_id = req->request_id; - ctx_isp->reported_req_id = request_id; - } - - __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, - CAM_REQ_MGR_SOF_EVENT_ERROR); - - ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; - - CAM_DBG(CAM_ISP, "next Substate[%s] ctx : %d", - __cam_isp_ctx_substate_val_to_type( - ctx_isp->substate_activated), ctx->ctx_id); - -done: - return rc; -} - static int __cam_isp_ctx_apply_req_in_sof( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -3421,8 +3319,8 @@ static int __cam_isp_ctx_apply_req_in_bubble( ctx_isp->substate_activated)); rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply, CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED); - CAM_DBG(CAM_ISP, "ctx %d link %x new Substate[%s]", - ctx->ctx_id, ctx->link_hdl, __cam_isp_ctx_substate_val_to_type( + CAM_DBG(CAM_ISP, "new Substate[%s]", + __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); if (rc) @@ -3786,7 +3684,6 @@ static int __cam_isp_ctx_flush_req_in_top_state( flush_req); ctx_isp->active_req_cnt = 0; - spin_unlock_bh(&ctx->lock); reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; @@ -3834,16 +3731,13 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_sof, - .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, /* APPLIED */ { .ioctl_ops = {}, - .crm_ops = { - .change_state = __cam_isp_ctx_change_substate, - }, + .crm_ops = {}, .irq_ops = NULL, }, /* EPOCH */ @@ -3851,7 +3745,6 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_epoch, - .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, @@ -3860,16 +3753,13 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_bubble, - .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, /* Bubble Applied */ { .ioctl_ops = {}, - .crm_ops = { - .change_state = __cam_isp_ctx_change_substate, - }, + .crm_ops = {}, .irq_ops = NULL, }, /* HW ERROR */ @@ -5388,33 +5278,6 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx, return rc; } -static int __cam_isp_ctx_get_isp_info(int32_t dev_hdl, void *data) -{ - int rc = 0; - struct cam_context *ctx; - struct cam_req_mgr_dev_info *isp_dev = data; - struct cam_isp_context *isp_ctx = NULL; - - ctx = (struct cam_context *)cam_get_device_priv(dev_hdl); - - isp_ctx = (struct cam_isp_context *)ctx->ctx_priv; - - isp_dev->state = isp_ctx->substate_activated; - isp_dev->timestamp = isp_ctx->sof_timestamp_val; - isp_dev->boot_time = isp_ctx->boot_timestamp; - isp_dev->frame_id = isp_ctx->frame_id; - - if ((isp_ctx->substate_activated == - CAM_ISP_CTX_ACTIVATED_APPLIED) || - (isp_ctx->substate_activated == - CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED)) - isp_dev->is_applied = true; - else - isp_dev->is_applied = false; - - return rc; -} - static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { @@ -5426,7 +5289,6 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; dev_info->trigger_on = true; - dev_info->sof_ts_cb = &__cam_isp_ctx_get_isp_info; return rc; } @@ -5484,8 +5346,6 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); ctx_isp->frame_id = 0; - ctx_isp->sof_timestamp_val = 0; - ctx_isp->boot_timestamp = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->bubble_frame_cnt = 0; @@ -5835,33 +5695,6 @@ static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx, return rc; } -static int __cam_isp_ctx_change_state_req(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info) -{ - int rc = 0; - struct cam_ctx_ops *ctx_ops = NULL; - struct cam_isp_context *ctx_isp = - (struct cam_isp_context *) ctx->ctx_priv; - - CAM_DBG(CAM_ISP, "Enter: changes state ctx id %d link 0x%x", - ctx->ctx_id, ctx->link_hdl); - ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated]; - if (ctx_ops->crm_ops.change_state) { - rc = ctx_ops->crm_ops.change_state(ctx, state_info); - } else { - CAM_WARN_RATE_LIMIT(CAM_ISP, - "No handle function in activated Substate[%s]", - __cam_isp_ctx_substate_val_to_type( - ctx_isp->substate_activated)); - rc = -EFAULT; - } - - if (rc) - CAM_WARN_RATE_LIMIT(CAM_ISP, - "changes state failed"); - return rc; -} - static int __cam_isp_ctx_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -6014,7 +5847,6 @@ static struct cam_ctx_ops .flush_req = __cam_isp_ctx_flush_req_in_top_state, .process_evt = __cam_isp_ctx_process_evt, .dump_req = __cam_isp_ctx_dump_in_top_state, - .change_state = __cam_isp_ctx_change_state_req, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_requests, @@ -6239,8 +6071,6 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->base = ctx_base; ctx->frame_id = 0; - ctx->sof_timestamp_val = 0; - ctx->boot_timestamp = 0; ctx->custom_enabled = false; ctx->use_frame_header_ts = false; ctx->active_req_cnt = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index b04c3448b6b5..a4f15165d0bf 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -261,17 +261,15 @@ enum cam_isp_ctx_type { * @ctx_type: RDI_ONLY, PIX and RDI, or FS2 * @packet_op_code: Packet opcode * @last_cdm_done: Last cdm done request - * @cam_isp_hw_sof_event_data sof event timestamp */ struct cam_isp_hw_cmd_args { uint32_t cmd_type; void *cmd_data; union { - uint32_t sof_irq_enable; - uint32_t ctx_type; - uint32_t packet_op_code; - uint64_t last_cdm_done; - struct cam_isp_hw_sof_event_data sof_done_event_data; + uint32_t sof_irq_enable; + uint32_t ctx_type; + uint32_t packet_op_code; + uint64_t last_cdm_done; } u; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 36a105be5a1d..1239416b90c9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -17,14 +17,9 @@ #include "cam_req_mgr_dev.h" #include "cam_req_mgr_debug.h" -#define THRESHOLD_FACTOR 3 - static struct cam_req_mgr_core_device *g_crm_core_dev; static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION]; -static char *__cam_req_mgr_dev_handle_to_name( - int32_t dev_hdl, struct cam_req_mgr_core_link *link); - void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) { uint32_t pd = 0; @@ -46,7 +41,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->open_req_cnt = 0; link->last_flush_id = 0; link->initial_sync_req = -1; - link->modified_init_sync_req = -1; link->dual_trigger = false; link->trigger_cnt[0][0] = 0; link->trigger_cnt[0][1] = 0; @@ -55,18 +49,13 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; - link->initial_skip = 0; + link->initial_skip = true; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; link->skip_init_frame = false; + link->num_sync_links = 0; link->last_sof_trigger_jiffies = 0; link->wq_congestion = false; - link->num_sync_link = 0; - link->activate_seq = -1; - link->bubble_skip = 0; - link->sync_frame_id = 0; - link->is_sync_req = true; - link->skip_sync_apply = false; atomic_set(&link->eof_event_cnt, 0); for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { @@ -210,33 +199,6 @@ static int __cam_req_mgr_inject_delay( return rc; } -/** - * cam_req_mgr_get_dev_hdl() - * - * @brief : Finds device handle based on the device name - * @dev_name : Device name whose dev handle is to be found - * @link : Link on which the device is connected - * @return : device handle - * - */ -static int32_t cam_req_mgr_get_dev_hdl( - char *dev_name, struct cam_req_mgr_core_link *link) -{ - struct cam_req_mgr_connected_device *dev = NULL; - int i = 0; - - for (i = 0; i < link->num_devs; i++) { - dev = &link->l_dev[i]; - CAM_DBG(CAM_CRM, "dev name %s, iterate dev name %s", - dev_name, dev->dev_info.name); - if (strcmp(dev_name, dev->dev_info.name) == 0) - goto end; - } - return -EINVAL; -end: - return dev->dev_hdl; -} - /** * __cam_req_mgr_find_dev_name() * @@ -419,10 +381,10 @@ static int __cam_req_mgr_notify_error_on_link( * @return: 0 for success, negative for failure * */ -static int __cam_req_mgr_traverse( - struct cam_req_mgr_traverse *traverse_data) +static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) { int rc = 0; + int32_t next_idx = traverse_data->idx; int32_t curr_idx = traverse_data->idx; struct cam_req_mgr_req_tbl *tbl; struct cam_req_mgr_apply *apply_data; @@ -438,18 +400,24 @@ static int __cam_req_mgr_traverse( tbl = traverse_data->tbl; apply_data = traverse_data->apply_data; slot = &tbl->slot[curr_idx]; + CAM_DBG(CAM_CRM, + "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", + tbl->pd, curr_idx, tbl->slot[curr_idx].state, + tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, + traverse_data->in_q->slot[curr_idx].skip_idx); - while (tbl) { - CAM_DBG(CAM_CRM, - "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", - tbl->pd, curr_idx, tbl->slot[curr_idx].state, - tbl->skip_traverse, - traverse_data->in_q->slot[curr_idx].status, - traverse_data->in_q->slot[curr_idx].skip_idx); - if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || - traverse_data->in_q->slot[curr_idx].skip_idx == 1 || - tbl->skip_traverse > 0) { - + /* 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 || + tbl->skip_traverse > 0) { + if (tbl->next) { + __cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta, + tbl->num_slots); + traverse_data->idx = next_idx; + traverse_data->tbl = tbl->next; + rc = __cam_req_mgr_traverse(traverse_data); + } + if (rc >= 0) { SET_SUCCESS_BIT(traverse_data->result, tbl->pd); if (traverse_data->validate_only == false) { @@ -460,34 +428,33 @@ static int __cam_req_mgr_traverse( apply_data[tbl->pd].idx = curr_idx; CAM_DBG(CAM_CRM, "req_id: %lld with pd of %d", - apply_data[tbl->pd].req_id, - apply_data[tbl->pd].pd); - + apply_data[tbl->pd].req_id, + apply_data[tbl->pd].pd); + /* + * If traverse is successful decrement + * traverse skip + */ if (tbl->skip_traverse > 0) { apply_data[tbl->pd].req_id = -1; tbl->skip_traverse--; } } - rc = 0; } else { - traverse_data->result_data.req_id = - CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); - traverse_data->result_data.pd = tbl->pd; - traverse_data->result_data.masked_value = - (tbl->dev_mask & slot->req_ready_map); - SET_FAILURE_BIT(traverse_data->result, tbl->pd); - rc = -EAGAIN; - break; + /* linked pd table is not ready for this traverse yet */ + return rc; } - if (tbl->next) { - __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, - tbl->num_slots); - traverse_data->idx = curr_idx; - traverse_data->tbl = tbl->next; - } - tbl = tbl->next; + } else { + /* This pd table is not ready to proceed with asked idx */ + traverse_data->result_data.req_id = + CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); + traverse_data->result_data.pd = tbl->pd; + traverse_data->result_data.masked_value = + (tbl->dev_mask & slot->req_ready_map); + SET_FAILURE_BIT(traverse_data->result, tbl->pd); + return -EAGAIN; } - return rc; + + return 0; } /** @@ -768,51 +735,6 @@ static int __cam_req_mgr_check_for_lower_pd_devices( return -EAGAIN; } -/** - * cam_req_mgr_dump_link_info() - * @brief : Dump link info on failure - * - * @dump_info : payload to dump data - */ -static void cam_req_mgr_dump_link_info( - struct cam_req_mgr_dump_link_data *dump_info) -{ - int i = 0; - struct cam_req_mgr_core_link *m_link; - struct cam_req_mgr_dev_info dev_data; - - m_link = dump_info->m_link; - dev_data = dump_info->dev_data; - - CAM_DBG(CAM_CRM, - "Master link req_id %lld 0x%x Slave link 0x%x req_id %lld frame id %lld csid time %lld boottime %lld", - m_link->link_hdl, dump_info->s_link->link_hdl, - dump_info->m_req_id, dump_info->s_req_id, - dev_data.frame_id, dev_data.timestamp, - dev_data.boot_time); - - CAM_DBG(CAM_CRM, - "Master link 0x%x csid time %lld bootime %lld frame id %lld sync frame id %lld init sync req %lld", - m_link->link_hdl, - m_link->sof_timestamp, - m_link->sof_boottime, - m_link->frame_id, - m_link->sync_frame_id, - m_link->initial_sync_req); - - for (i = 0; i < m_link->num_sync_link; i++) { - CAM_DBG(CAM_CRM, - "slave link 0x%x csid time %lld bootime %lld frame id %lld sync frame id %lld init sync req %lld", - m_link->sync_link[i]->link_hdl, - m_link->sync_link[i]->sof_timestamp, - m_link->sync_link[i]->sof_boottime, - m_link->sync_link[i]->frame_id, - m_link->sync_link[i]->sync_frame_id, - m_link->sync_link[i]->initial_sync_req); - } -} - - /** * __cam_req_mgr_check_next_req_slot() * @@ -1139,6 +1061,19 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.validate_only = validate_only; traverse_data.open_req_cnt = link->open_req_cnt; + /* + * Some no-sync mode requests are processed after link config, + * then process the sync mode requests after no-sync mode requests + * are handled, the initial_skip should be false when processing + * the sync mode requests. + */ + if (link->initial_skip) { + CAM_DBG(CAM_CRM, + "Set initial_skip to false for link %x", + link->link_hdl); + link->initial_skip = false; + } + /* * Traverse through all pd tables, if result is success, * apply the settings @@ -1200,29 +1135,420 @@ static int32_t __cam_req_mgr_find_slot_for_req( } /** - * cam_req_mgr_get_device_info() + * __cam_req_mgr_check_sync_for_mslave() * - * @brief : Get state and qtime info from device - * @link : pointer to link - * @sof_ts : pointer to dev_info payload - * - * @return : void + * @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_get_device_info( +static int __cam_req_mgr_check_sync_for_mslave( struct cam_req_mgr_core_link *link, - struct cam_req_mgr_dev_info *dev_info) + struct cam_req_mgr_core_link *sync_link, + struct cam_req_mgr_slot *slot) { - int i; - struct cam_req_mgr_connected_device *dev; + 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; + int32_t sync_num_slots = 0; - for (i = 0; i < link->num_devs; i++) { - dev = &link->l_dev[i]; - dev_info->link_hdl = link->link_hdl; - if (dev && dev->dev_info.sof_ts_cb) - dev->dev_info.sof_ts_cb(dev->dev_hdl, dev_info); + if (!sync_link || !link) { + CAM_ERR(CAM_CRM, "Sync link or link is null"); + return -EINVAL; } + + req_id = slot->req_id; + + if (!sync_link->req.in_q) { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + + sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + + CAM_DBG(CAM_CRM, + "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); + + 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; + return -EAGAIN; + } + + 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; + } + + if (link->is_master) { + if (sync_link->initial_skip) { + CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + 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; + } + + 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 + sync_num_slots) % + sync_num_slots) >= 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_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 + sync_num_slots) % + sync_num_slots) >= 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; + } + } + } + + CAM_DBG(CAM_REQ, + "Req: %lld ready to apply on link: %x [validation successful]", + req_id, link->link_hdl); + + return 0; +} + + +/** + * __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 + * traversed through + * @slot : pointer to the current slot being processed + * @return : 0 for success, negative for failure + * + */ +static int __cam_req_mgr_check_sync_req_is_ready( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_core_link *sync_link, + struct cam_req_mgr_slot *slot) +{ + struct cam_req_mgr_slot *sync_rd_slot = NULL; + int64_t req_id = 0, sync_req_id = 0; + int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; + int32_t sync_num_slots = 0; + uint64_t sync_frame_duration = 0; + uint64_t sof_timestamp_delta = 0; + uint64_t master_slave_diff = 0; + bool ready = true, sync_ready = true; + int slot_idx_diff = 0; + + if (!sync_link || !link) { + CAM_ERR(CAM_CRM, "Sync link null"); + return -EINVAL; + } + + req_id = slot->req_id; + + if (!sync_link->req.in_q) { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + + sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; + + CAM_DBG(CAM_REQ, + "link_hdl %x sync link_hdl %x req %lld", + link->link_hdl, sync_link->link_hdl, req_id); + + if (sync_link->initial_skip) { + link->initial_skip = false; + CAM_DBG(CAM_CRM, + "sync link %x not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + if (sync_link->prev_sof_timestamp) + sync_frame_duration = sync_link->sof_timestamp - + sync_link->prev_sof_timestamp; + else + sync_frame_duration = DEFAULT_FRAME_DURATION; + + sof_timestamp_delta = + link->sof_timestamp >= sync_link->sof_timestamp + ? link->sof_timestamp - sync_link->sof_timestamp + : sync_link->sof_timestamp - link->sof_timestamp; + + CAM_DBG(CAM_CRM, + "sync link %x last frame_duration is %d ns", + sync_link->link_hdl, sync_frame_duration); + + if (link->initial_skip) { + link->initial_skip = false; + + if ((link->sof_timestamp > sync_link->sof_timestamp) && + (sync_link->sof_timestamp > 0) && + (link->sof_timestamp - sync_link->sof_timestamp) < + (sync_frame_duration / 2)) { + /* + * If this frame sync with the previous frame of sync + * link, then we need to skip this frame, since the + * previous frame of sync link is also skipped. + */ + CAM_DBG(CAM_CRM, + "This frame sync with previous sync_link %x frame", + sync_link->link_hdl); + return -EAGAIN; + } else if (link->sof_timestamp <= sync_link->sof_timestamp) { + /* + * Sometimes, link receives the SOF event is eariler + * than sync link in IFE CSID side, but link's SOF + * event is processed later than sync link's, then + * we need to skip this SOF event since the sync + * link's SOF event is also skipped. + */ + CAM_DBG(CAM_CRM, + "The previous frame of sync link is skipped"); + return -EAGAIN; + } + } + + 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; + return -EAGAIN; + } + + sync_slot_idx = __cam_req_mgr_find_slot_for_req( + sync_link->req.in_q, req_id); + if (sync_slot_idx == -1) { + CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", + req_id, sync_link->link_hdl); + sync_ready = false; + return -EAGAIN; + } + + slot_idx_diff = (sync_slot_idx - sync_rd_idx + sync_num_slots) % + sync_num_slots; + if ((sync_link->req.in_q->slot[sync_slot_idx].status != + CRM_SLOT_STATUS_REQ_APPLIED) && + ((slot_idx_diff > 1) || + ((slot_idx_diff == 1) && + (sync_rd_slot->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); + return -EAGAIN; + } + + rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); + if (rc) { + CAM_DBG(CAM_CRM, + "Req: %lld [My link] not ready on link: %x, rc=%d", + req_id, link->link_hdl, rc); + ready = false; + } + + if (sync_link->req.in_q) { + 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 link: %x, rc=%d", + req_id, sync_link->link_hdl, rc); + sync_ready = false; + } + } else { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + + /* + * If both of them are ready or not ready, then just + * skip this sof and don't skip sync link next SOF. + */ + if (sync_ready != ready) { + CAM_DBG(CAM_CRM, + "Req: %lld ready %d sync_ready %d, ignore sync link next SOF", + req_id, ready, sync_ready); + + /* + * Only skip the frames if current frame sync with + * next frame of sync link. + */ + if (link->sof_timestamp - sync_link->sof_timestamp > + sync_frame_duration / 2) + link->sync_link_sof_skip = true; + return -EINVAL; + } else if (ready == false) { + CAM_DBG(CAM_CRM, + "Req: %lld not ready on link: %x", + req_id, link->link_hdl); + return -EINVAL; + } + + /* + * Do the self-correction when the frames are sync, + * we consider that the frames are synced if the + * difference of two SOF timestamp less than + * (sync_frame_duration / 5). + */ + master_slave_diff = sync_frame_duration; + do_div(master_slave_diff, 5); + if ((sync_link->sof_timestamp > 0) && + (sof_timestamp_delta < master_slave_diff) && + (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { + + /* + * This means current frame should sync with next + * frame of sync link, then the request id of in + * rd slot of two links should be same. + */ + CAM_DBG(CAM_CRM, + "link %x req_id %lld, sync_link %x req_id %lld", + link->link_hdl, req_id, + sync_link->link_hdl, sync_req_id); + + if (req_id > sync_req_id) { + CAM_DBG(CAM_CRM, + "link %x too quickly, skip this frame", + link->link_hdl); + return -EAGAIN; + } else if (req_id < sync_req_id) { + CAM_DBG(CAM_CRM, + "sync link %x too quickly, skip next frame of sync link", + sync_link->link_hdl); + link->sync_link_sof_skip = true; + } else if (sync_link->req.in_q->slot[sync_slot_idx].status != + CRM_SLOT_STATUS_REQ_APPLIED) { + CAM_DBG(CAM_CRM, + "link %x other not applied", link->link_hdl); + return -EAGAIN; + } + } + CAM_DBG(CAM_REQ, + "Req: %lld ready to apply on link: %x [validation successful]", + req_id, link->link_hdl); + + return 0; } static int __cam_req_mgr_check_multi_sync_link_ready( @@ -1230,16 +1556,60 @@ static int __cam_req_mgr_check_multi_sync_link_ready( struct cam_req_mgr_slot *slot, uint32_t trigger) { - int rc = 0; + int i, rc = 0; if (link->state == CAM_CRM_LINK_STATE_IDLE) { CAM_ERR(CAM_CRM, "link hdl %x is in idle state", - link->link_hdl); + link->link_hdl); return -EINVAL; } + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if (link->sync_link[i]->state == + CAM_CRM_LINK_STATE_IDLE) { + CAM_ERR(CAM_CRM, "sync link hdl %x is idle", + link->sync_link[i]->link_hdl); + return -EINVAL; + } + if (link->max_delay == link->sync_link[i]->max_delay) { + rc = __cam_req_mgr_check_sync_req_is_ready( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link %x not ready", + link->link_hdl); + return rc; + } + } else if (link->max_delay > + link->sync_link[i]->max_delay) { + link->is_master = true; + link->sync_link[i]->is_master = false; + rc = __cam_req_mgr_check_sync_for_mslave( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link%x not ready", + link->link_hdl); + return rc; + } + } else { + link->is_master = false; + link->sync_link[i]->is_master = true; + rc = __cam_req_mgr_check_sync_for_mslave( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link %x not ready", + link->link_hdl); + return rc; + } + } + } else { + CAM_ERR(CAM_REQ, "Sync link is null"); + return -EINVAL; + } + } + rc = __cam_req_mgr_inject_delay(link->req.l_tbl, - slot->idx, trigger); + slot->idx, trigger); if (rc < 0) { CAM_DBG(CAM_CRM, "Req: %lld needs to inject delay at %s", @@ -1324,7 +1694,7 @@ enum crm_req_eof_trigger_type __cam_req_mgr_check_for_eof( static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_trigger_notify *trigger_data) { - int i = 0, rc = 0, idx; + int rc = 0, idx, i; int reset_step = 0; uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; @@ -1358,7 +1728,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, in_q->slot[in_q->rd_idx].additional_timeout, trigger); slot = &in_q->slot[in_q->rd_idx]; - if (slot->status == CRM_SLOT_STATUS_NO_REQ) { CAM_DBG(CAM_CRM, "No Pending req"); rc = 0; @@ -1378,6 +1747,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } if (trigger == CAM_TRIGGER_POINT_SOF) { + /* + * Update the timestamp in session lock protection + * to avoid timing issue. + */ + link->prev_sof_timestamp = link->sof_timestamp; + link->sof_timestamp = trigger_data->sof_timestamp_val; /* Check for WQ congestion */ if (jiffies_to_msecs(jiffies - @@ -1390,14 +1765,8 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (slot->status != CRM_SLOT_STATUS_REQ_READY) { if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - 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_multi_sync_link_ready( - link, slot, trigger); + link, slot, trigger); } else { if (link->in_msync_mode) { CAM_DBG(CAM_CRM, @@ -1405,10 +1774,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); link->in_msync_mode = false; link->initial_sync_req = -1; - for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; - i++) { - tmp_link = link->sync_link[i]; - if (tmp_link) { + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + tmp_link = link->sync_link[i]; tmp_link->initial_sync_req = -1; tmp_link->in_msync_mode = false; } @@ -1478,13 +1846,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } - if (link->num_sync_link && - (link->initial_sync_req == slot->req_id)) { - link->sync_frame_id = trigger_data->frame_id; - CAM_DBG(CAM_CRM, "link %x sync frame %lld", - link->link_hdl, link->sync_frame_id); - } - rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger, &dev); if (rc < 0) { /* Apply req failed retry at next sof */ @@ -1553,10 +1914,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); idx = in_q->rd_idx; reset_step = link->max_delay; - for (i = 0; i < link->num_sync_link - 1; i++) { - if (reset_step < link->sync_link[i]->max_delay) - reset_step = + + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if ((link->in_msync_mode) && + (link->sync_link[i]->max_delay > + reset_step)) + reset_step = link->sync_link[i]->max_delay; + } } if (slot->req_id > 0) @@ -2112,9 +2478,8 @@ static void __cam_req_mgr_unreserve_link( } } - for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++) - link->sync_link[i] = NULL; - + for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) + link->sync_link[j] = NULL; session->num_links--; CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); mutex_unlock(&session->lock); @@ -2244,6 +2609,13 @@ 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 is_master %d exp_timeout_val %d ms", + sched_req->link_hdl, sched_req->req_id, + in_q->wr_idx, sched_req->sync_mode, + link->is_master, + sched_req->additional_timeout); + mutex_lock(&link->req.lock); slot = &in_q->slot[in_q->wr_idx]; @@ -2253,10 +2625,9 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) slot->status = CRM_SLOT_STATUS_REQ_ADDED; slot->req_id = sched_req->req_id; + slot->sync_mode = sched_req->sync_mode; slot->skip_idx = 0; slot->recover = sched_req->bubble_enable; - slot->sync_mode = sched_req->sync_mode; - slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; if (sched_req->additional_timeout < 0) { CAM_WARN(CAM_CRM, "Requested timeout is invalid [%dms]", @@ -2277,63 +2648,16 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) __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) { + if (link->initial_sync_req == -1) link->initial_sync_req = slot->req_id; - link->modified_init_sync_req = slot->req_id; - } } else { link->initial_sync_req = -1; - for (i = 0; i < link->num_sync_link; i++) { - if (link->sync_link[i]) { + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) link->sync_link[i]->initial_sync_req = -1; - link->modified_init_sync_req = -1; - } } } - CAM_DBG(CAM_CRM, - "link_hdl %x req_id %lld at slot %d schedule_mode %d slot mode %d is_master %d exp_timeout_val %d ms", - sched_req->link_hdl, sched_req->req_id, - in_q->wr_idx, sched_req->sync_mode, - slot->sync_mode, - link->is_master, - sched_req->additional_timeout); - /* - * This logic is to make first few requests in non-sync mode - * so that these requests should apply irrespective of threshold - * time condition as difference in sensor stream on may be more than - * threshold value at start. For sw sync logic to work, first few - * requests needs to apply in same frame duration. - */ - - if (link->is_sync_req && slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC - && ((link->initial_sync_req + 5) > slot->req_id)) { - slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_SYNC; - } else if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - if (link->is_sync_req && (link->initial_skip == 0)) { - link->is_sync_req = false; - link->initial_sync_req = slot->req_id + 1; - CAM_DBG(CAM_CRM, "Initial sync req %lld link %x", - link->initial_sync_req, link->link_hdl); - } - - if (link->initial_skip && link->initial_sync_req) { - link->initial_skip--; - slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_SYNC; - CAM_DBG(CAM_CRM, "Initial sync req %lld link %x", - link->initial_sync_req, link->link_hdl); - } - } - CAM_DBG(CAM_CRM, - "link_hdl %x req_id %lld at slot %d schedule_mode %d slot mode %d is_master %d exp_timeout_val %d ms init sync %d", - sched_req->link_hdl, sched_req->req_id, - in_q->wr_idx, sched_req->sync_mode, - slot->sync_mode, - link->is_master, - sched_req->additional_timeout, - link->initial_sync_req); mutex_unlock(&link->req.lock); end: @@ -2352,19 +2676,12 @@ end: */ int cam_req_mgr_process_add_req(void *priv, void *data) { - int rc = 0, i = 0, j = 0; - int idx, idx2; + int rc = 0, i = 0, idx; struct cam_req_mgr_add_request *add_req = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_connected_device *device = NULL; - struct cam_req_mgr_connected_device *device2 = NULL; struct cam_req_mgr_req_tbl *tbl = NULL; - struct cam_req_mgr_req_tbl *tbl2 = NULL; struct cam_req_mgr_tbl_slot *slot = NULL; - struct cam_req_mgr_tbl_slot *sync_slot = NULL; - int32_t sync_dev_hdl = -1; - char *dev_name = NULL; - struct cam_req_mgr_slot *link_slot = NULL; struct crm_task_payload *task_data = NULL; if (!data || !priv) { @@ -2392,7 +2709,6 @@ int cam_req_mgr_process_add_req(void *priv, void *data) rc = -EINVAL; goto end; } - /* * Go through request table and add * request id to proper table @@ -2412,7 +2728,6 @@ int cam_req_mgr_process_add_req(void *priv, void *data) goto end; } - link_slot = &link->req.in_q->slot[idx]; slot = &tbl->slot[idx]; slot->ops.is_applied = false; @@ -2423,62 +2738,6 @@ int cam_req_mgr_process_add_req(void *priv, void *data) add_req->req_id, slot->inject_delay_at_sof, device->dev_info.name); - - if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - mutex_lock(&link->sync_link[i]->req.lock); - idx2 = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, - add_req->req_id); - if (idx2 < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q for dev %s on link 0x%x", - add_req->req_id, - device->dev_info.name, - link->sync_link[i]->link_hdl); - rc = -EBADSLT; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - dev_name = __cam_req_mgr_dev_handle_to_name( - add_req->dev_hdl, link); - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - for (j = 0; - j < link->sync_link[i]->num_devs; j++) { - device2 = &link->sync_link[i]->l_dev[j]; - CAM_ERR(CAM_CRM, "device hdl %x : sync link dev hdl %x", - device2->dev_hdl, sync_dev_hdl); - if (device2->dev_hdl == sync_dev_hdl) { - tbl2 = device2->pd_tbl; - break; - } - } - if (!tbl2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Sync link dev hdl %x not found", - sync_dev_hdl); - rc = -EINVAL; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - sync_slot = &tbl2->slot[idx2]; - sync_slot->ops.dev_hdl = sync_dev_hdl; - sync_slot->inject_delay_at_sof = - (add_req->skip_at_sof & 0xFF); - CAM_DBG(CAM_CRM, - "link %x Req_id %llu injecting delay %llu frame at SOF by %s", - link->sync_link[i]->link_hdl, - add_req->req_id, - slot->inject_delay_at_sof, - device->dev_info.name); - mutex_unlock(&link->sync_link[i]->req.lock); - } - } } if ((add_req->skip_at_eof & 0xFF) > slot->inject_delay_at_eof) { @@ -2488,123 +2747,14 @@ int cam_req_mgr_process_add_req(void *priv, void *data) add_req->req_id, slot->inject_delay_at_eof, device->dev_info.name); - - if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - mutex_lock(&link->sync_link[i]->req.lock); - idx2 = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, - add_req->req_id); - if (idx2 < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q for dev %s on link 0x%x", - add_req->req_id, - device->dev_info.name, - link->sync_link[i]->link_hdl); - rc = -EBADSLT; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - dev_name = __cam_req_mgr_dev_handle_to_name( - add_req->dev_hdl, link); - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - for (j = 0; - j < link->sync_link[i]->num_devs; j++) { - device2 = &link->sync_link[i]->l_dev[j]; - CAM_ERR(CAM_CRM, "device hdl %x : sync link dev hdl %x", - device2->dev_hdl, sync_dev_hdl); - if (device2->dev_hdl == sync_dev_hdl) { - tbl2 = device2->pd_tbl; - break; - } - } - if (!tbl2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Synclink dev hdl %x not found", - sync_dev_hdl); - rc = -EINVAL; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - sync_slot = &tbl2->slot[idx2]; - sync_slot->ops.dev_hdl = sync_dev_hdl; - sync_slot->inject_delay_at_eof = - (add_req->skip_at_eof & 0xFF); - CAM_DBG(CAM_CRM, - "link %x Req_id %llu injecting delay %llu frame at EOF by %s", - link->sync_link[i]->link_hdl, - add_req->req_id, - slot->inject_delay_at_sof, - device->dev_info.name); - mutex_unlock(&link->sync_link[i]->req.lock); - } - } } if (add_req->trigger_eof) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, - "link %x Req_id %llu slot:%d added for EOF tigger for Device: %s", - link->link_hdl, + "Req_id %llu slot:%d added for EOF tigger for Device: %s", add_req->req_id, idx, device->dev_info.name); - - if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - mutex_lock(&link->sync_link[i]->req.lock); - idx2 = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, - add_req->req_id); - if (idx2 < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q for dev %s on link 0x%x", - add_req->req_id, - device->dev_info.name, - link->sync_link[i]->link_hdl); - rc = -EBADSLT; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - dev_name = __cam_req_mgr_dev_handle_to_name( - add_req->dev_hdl, link); - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - for (j = 0; - j < link->sync_link[i]->num_devs; j++) { - device2 = &link->sync_link[i]->l_dev[j]; - CAM_ERR(CAM_CRM, - "device hdl %x : sync link dev hdl %x", - device2->dev_hdl, sync_dev_hdl); - if (device2->dev_hdl == sync_dev_hdl) { - tbl2 = device2->pd_tbl; - break; - } - } - if (!tbl2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Sync link dev hdl %x not found", - sync_dev_hdl); - rc = -EINVAL; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - sync_slot = &tbl2->slot[idx2]; - sync_slot->ops.is_applied = false; - sync_slot->ops.apply_at_eof = true; - sync_slot->ops.dev_hdl = sync_dev_hdl; - mutex_unlock(&link->sync_link[i]->req.lock); - } - } - } if (slot->state != CRM_REQ_STATE_PENDING && @@ -2618,8 +2768,8 @@ int cam_req_mgr_process_add_req(void *priv, void *data) slot->state = CRM_REQ_STATE_PENDING; slot->req_ready_map |= (1 << device->dev_bit); - CAM_DBG(CAM_CRM, "link %x idx %d dev_hdl %x req_id %lld pd %d ready_map %x", - link->link_hdl, idx, add_req->dev_hdl, add_req->req_id, tbl->pd, + CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x", + idx, add_req->dev_hdl, add_req->req_id, tbl->pd, slot->req_ready_map); trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); @@ -2832,8 +2982,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) mutex_lock(&link->req.lock); - if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF - && !link->num_sync_link) { + if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) { idx = __cam_req_mgr_find_slot_for_req(in_q, trigger_data->req_id); if (idx >= 0) { @@ -2868,8 +3017,6 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) in_q->slot[in_q->rd_idx].status); spin_unlock_bh(&link->link_state_spin_lock); - CAM_DBG(CAM_CRM, "Link %x req id %lld", - link->link_hdl, in_q->slot[in_q->rd_idx].req_id); /* * Move to next req at SOF only in case @@ -2914,7 +3061,7 @@ end: * @return : String containing the device name * */ -static char *__cam_req_mgr_dev_handle_to_name( +static const char *__cam_req_mgr_dev_handle_to_name( int32_t dev_hdl, struct cam_req_mgr_core_link *link) { struct cam_req_mgr_connected_device *dev = NULL; @@ -2943,12 +3090,11 @@ static char *__cam_req_mgr_dev_handle_to_name( */ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) { - int i, rc = 0, idx; + int rc = 0, idx; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_add_request *dev_req; struct crm_task_payload *task_data; - struct cam_req_mgr_slot *slot = NULL; if (!add_req) { CAM_ERR(CAM_CRM, "sof_data is NULL"); @@ -2987,8 +3133,6 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) goto end; } - slot = &link->req.in_q->slot[idx]; - task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task dev %x req %lld", @@ -3010,10 +3154,6 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) atomic_inc(&link->eof_event_cnt); CAM_DBG(CAM_REQ, "Req_id: %llu, eof_event_cnt: %d", dev_req->req_id, link->eof_event_cnt); - if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) - atomic_inc(&link->sync_link[i]->eof_event_cnt); - } } task->process_cb = &cam_req_mgr_process_add_req; @@ -3030,30 +3170,23 @@ end: * cam_req_mgr_cb_notify_err() * * @brief : Error received from device, sends bubble recovery - * * @err_info : contains information about error occurred like bubble/overflow * - * @return : true on skipping bubble processing, otherwise, false + * @return : 0 on success, negative in case of failure * */ -static bool cam_req_mgr_cb_notify_err( +static int cam_req_mgr_cb_notify_err( struct cam_req_mgr_error_notify *err_info) { - bool rc = false; - int i, j; - uint32_t idx; + int rc = 0; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_error_notify *notify_err; struct crm_task_payload *task_data; - struct cam_req_mgr_slot *slot = NULL; - struct cam_req_mgr_slot *tmp_slot = NULL; - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_request_change_state state_info; if (!err_info) { CAM_ERR(CAM_CRM, "err_info is NULL"); - rc = false; + rc = -EINVAL; goto end; } @@ -3061,127 +3194,37 @@ static bool cam_req_mgr_cb_notify_err( cam_get_device_priv(err_info->link_hdl); if (!link) { CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl); - rc = false; + rc = -EINVAL; goto end; } - idx = __cam_req_mgr_find_slot_for_req( - link->req.in_q, err_info->req_id); - if (idx < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q link %x", - err_info->req_id, link->link_hdl); - rc = false; - goto end; - } - - tmp_slot = &link->req.in_q->slot[idx]; - - /* Incrementing slot idx to find if request in the slot - * is applied in sync mode or non-sync mode. - */ - __cam_req_mgr_inc_idx( - &idx, 1, link->req.in_q->num_slots); - - slot = &link->req.in_q->slot[idx]; - - /* Condition to check if crm need to process bubble notified by - * crm or isp. If bubble is reported for slave link then don't - * process bubble recovery. Checking previous slot with tmp_slot - * to handle condition where bubble is reported for last request. - */ - if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || - tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) && - !link->is_master) { - crm_timer_reset(link->watchdog); - CAM_DBG(CAM_CRM, "Not processing bubble as it is slave link %x", - link->link_hdl); - return true; - } - spin_lock_bh(&link->link_state_spin_lock); if (link->state != CAM_CRM_LINK_STATE_READY) { CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); spin_unlock_bh(&link->link_state_spin_lock); - rc = false; + rc = -EPERM; goto end; } crm_timer_reset(link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); - if (link->is_master && - slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - CAM_DBG(CAM_CRM, "Bubble for sync link %x", - link->sync_link[i]->link_hdl); - state_info.link_hdl = link->sync_link[i]->link_hdl; - state_info.req_id = err_info->req_id; - for (j = 0; j < link->sync_link[i]->num_devs; j++) { - dev = &link->sync_link[i]->l_dev[j]; - if (dev->ops && dev->ops->change_state) { - state_info.dev_hdl = dev->dev_hdl; - - if (!(dev->ops->change_state( - &state_info))) { - CAM_DBG(CAM_CRM, - "Err on bubble notify"); - rc = false; - } - - task = cam_req_mgr_workq_get_task( - link->workq); - if (!task) { - CAM_ERR(CAM_CRM, - "no empty task req_id %lld", - err_info->req_id); - rc = false; - goto end; - } - - task_data = (struct crm_task_payload *) - task->payload; - task_data->type = - CRM_WORKQ_TASK_NOTIFY_ERR; - notify_err = - (struct cam_req_mgr_error_notify *)& - task_data->u; - notify_err->req_id = err_info->req_id; - notify_err->link_hdl = - link->sync_link[i]->link_hdl; - notify_err->dev_hdl = dev->dev_hdl; - notify_err->error = err_info->error; - task->process_cb = - &cam_req_mgr_process_error; - cam_req_mgr_workq_enqueue_task( - task, - link->sync_link[i], - CRM_TASK_PRIORITY_0); - } - } - } + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id); + rc = -EBUSY; + goto end; } - if (err_info->need_recovery) { - task = cam_req_mgr_workq_get_task(link->workq); - if (!task) { - CAM_ERR(CAM_CRM, "no empty task req_id %lld", - err_info->req_id); - rc = false; - goto end; - } - - task_data = (struct crm_task_payload *)task->payload; - task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; - notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; - notify_err->req_id = err_info->req_id; - notify_err->link_hdl = err_info->link_hdl; - notify_err->dev_hdl = err_info->dev_hdl; - notify_err->error = err_info->error; - notify_err->trigger = err_info->trigger; - task->process_cb = &cam_req_mgr_process_error; - rc = cam_req_mgr_workq_enqueue_task( - task, link, CRM_TASK_PRIORITY_0); - } + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; + notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; + notify_err->req_id = err_info->req_id; + notify_err->link_hdl = err_info->link_hdl; + notify_err->dev_hdl = err_info->dev_hdl; + notify_err->error = err_info->error; + notify_err->trigger = err_info->trigger; + task->process_cb = &cam_req_mgr_process_error; + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); end: return rc; @@ -3337,51 +3380,7 @@ end: return rc; } -static int cam_req_mgr_send_to_bubble( - struct cam_req_mgr_core_link *link, - uint64_t req_id) -{ - int rc = 0, i; - struct cam_req_mgr_error_notify notify; - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_request_change_state state_info; - struct cam_req_mgr_dev_info dev_data; - notify.link_hdl = link->link_hdl; - notify.req_id = req_id; - notify.error = CRM_KMD_ERR_BUBBLE; - notify.trigger = CAM_TRIGGER_POINT_SOF; - notify.frame_id = link->frame_id; - notify.sof_timestamp_val = link->sof_timestamp; - notify.need_recovery = false; - - for (i = 0; i < link->num_devs; i++) { - dev = &link->l_dev[i]; - if (dev->ops && dev->ops->change_state) { - notify.dev_hdl = dev->dev_hdl; - if (dev->ops && dev->ops->change_state) { - cam_req_mgr_get_device_info(link, &dev_data); - if (dev_data.is_applied) { - state_info.link_hdl = link->link_hdl; - state_info.req_id = req_id; - state_info.dev_hdl = dev->dev_hdl; - rc = dev->ops->change_state( - &state_info); - if (rc < 0) - CAM_INFO(CAM_CRM, - "Failed to change state"); - } else { - link->bubble_skip = link->max_delay; - } - } - rc = cam_req_mgr_cb_notify_err(¬ify); - if (!rc) - CAM_INFO(CAM_CRM, - "Bubble recovery failed"); - } - } - return rc; -} /** * cam_req_mgr_cb_notify_trigger() @@ -3395,27 +3394,12 @@ static int cam_req_mgr_send_to_bubble( static int cam_req_mgr_cb_notify_trigger( struct cam_req_mgr_trigger_notify *trigger_data) { - int32_t i = 0, rc = 0, trigger_id = 0; - int32_t sync_dev_hdl = -1, sync_id = 0; - int64_t req_diff = 0; - uint32_t trigger; - struct crm_workq_task *task = NULL; - struct cam_req_mgr_core_link *link = NULL; + int32_t rc = 0, trigger_id = 0; + uint32_t trigger; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_trigger_notify *notify_trigger; - struct crm_task_payload *task_data; - struct cam_req_mgr_slot *slot = NULL; - struct cam_req_mgr_slot *tmp_slot = NULL; - struct cam_req_mgr_req_queue *in_q; - struct timespec64 ts; - struct cam_req_mgr_dev_info dev_data; - struct cam_req_mgr_slot *sync_slot = NULL; - struct cam_req_mgr_req_queue *sync_in_q; - int32_t sync_rd_idx = 0; - char *dev_name = NULL; - uint64_t curr_sync_time = 0; - uint64_t frame_duration = 0; - uint64_t curr_boot_timestamp; - uint64_t threshold = 0; + struct crm_task_payload *task_data; if (!trigger_data) { CAM_ERR(CAM_CRM, "trigger_data is NULL"); @@ -3438,10 +3422,6 @@ static int cam_req_mgr_cb_notify_trigger( trigger_id = trigger_data->trigger_id; trigger = trigger_data->trigger; - ktime_get_boottime_ts64(&ts); - curr_boot_timestamp = - (uint64_t)((ts.tv_sec * 1000000000) + - ts.tv_nsec); /* * Reduce the workq overhead when there is @@ -3485,416 +3465,8 @@ static int cam_req_mgr_cb_notify_trigger( if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) crm_timer_reset(link->watchdog); - link->prev_sof_timestamp = link->sof_timestamp; - link->sof_timestamp = trigger_data->sof_timestamp_val; - link->frame_id = trigger_data->frame_id; - link->sof_boottime = trigger_data->sof_boottime; spin_unlock_bh(&link->link_state_spin_lock); - in_q = link->req.in_q; - slot = &in_q->slot[in_q->rd_idx]; - tmp_slot = &in_q->slot[in_q->rd_idx]; - - CAM_DBG(CAM_CRM, - "link %x req %lld idx %d state %d real sync mode %d", - link->link_hdl, slot->req_id, sync_id, slot->status, - slot->real_sync_mode); - - if (link->initial_sync_req != -1 && - slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC && - link->num_sync_link) { - sync_id = slot->idx; - __cam_req_mgr_inc_idx( - &sync_id, 1, link->req.in_q->num_slots); - slot = &in_q->slot[sync_id]; - CAM_DBG(CAM_CRM, - "E link %x req %lld idx %d state %d", - link->link_hdl, slot->req_id, sync_id, slot->status); - } - - - CAM_DBG(CAM_CRM, - "link %x req %lld slot mode %d tmp slot mode %d init sync %lld", - link->link_hdl, slot->req_id, - slot->sync_mode, tmp_slot->sync_mode, - link->initial_sync_req); - - if (trigger == CAM_TRIGGER_POINT_SOF && - (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || - (tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC && - (link->initial_sync_req != -1)))) { - /* If in sync and slave link then don't apply */ - if (!link->is_master) { - - CAM_DBG(CAM_CRM, - "Skipping slave link 0x%x apply sof timestamp %llx frame %lld slot req %lld", - link->link_hdl, - link->sof_timestamp, - trigger_data->frame_id, - slot->req_id); - - CAM_DBG(CAM_CRM, - "[Slave %x] epoch time %lld sof boottime %lld frame id %lld open cnt %d req id %lld", - link->link_hdl, - curr_boot_timestamp, - link->sof_boottime, - trigger_data->frame_id, - link->open_req_cnt, - slot->req_id); - - goto end; - } else { - - frame_duration = - (curr_boot_timestamp - link->sof_boottime) * 2; - CAM_DBG(CAM_CRM, - "[Master %x] epoch time %lld sof boottime %lld frame id %lld frame duration %d ms open cnt %d req id %lld", - link->link_hdl, - curr_boot_timestamp, - link->sof_boottime, - trigger_data->frame_id, - frame_duration/1000000, - link->open_req_cnt, - slot->req_id); - - rc = __cam_req_mgr_check_next_req_slot(link); - 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", - slot->req_id, link->link_hdl, rc); - return rc; - } - - /* Checking each sync link if they are ready to apply - * on this epoch, if not then skip apply on this epoch - */ - for (i = 0; i < link->num_sync_link; i++) { - sync_in_q = link->sync_link[i]->req.in_q; - sync_rd_idx = sync_in_q->rd_idx; - __cam_req_mgr_inc_idx( - &sync_rd_idx, 1, - link->sync_link[i]->req.in_q->num_slots); - sync_slot = &sync_in_q->slot[sync_rd_idx]; - rc = __cam_req_mgr_check_next_req_slot( - link->sync_link[i]); - - /* This condition is for SAT usecase, - * if request id to be sync is different - * then this will help to sync - */ - if (link->initial_sync_req != -1 && - (link->sync_link[i]->initial_sync_req != - -1) && (link->initial_sync_req == - slot->req_id) && - (link->sync_link[i]->initial_sync_req > - sync_slot->req_id)) { - CAM_DBG(CAM_CRM, - "Not applying on Master %x as slave %x is not in sync", - link->link_hdl, - link->sync_link[i]->link_hdl); - return rc; - } - - /* checking if packet for synclink is - * available or not - */ - rc = __cam_req_mgr_check_link_is_ready( - link->sync_link[i], sync_rd_idx, true); - - if (rc) { - CAM_DBG(CAM_CRM, - "Req:%lld [sync] not ready on link: %x, rc=%d", - sync_slot->req_id, - link->sync_link[i]->link_hdl, - rc); - return rc; - } - - /* Getting time and state info ISP context */ - cam_req_mgr_get_device_info( - link->sync_link[i], &dev_data); - - /* Checking if frame difference is maintain */ - req_diff = - (link->sync_frame_id - - link->sync_link[i]->sync_frame_id); - if (!link->sync_link_sof_skip && - link->sync_frame_id && - link->initial_sync_req != slot->req_id - && (req_diff != (link->frame_id - - dev_data.frame_id))) { - struct cam_req_mgr_dump_link_data - dump_info; - - CAM_DBG(CAM_CRM, - "Frame diff not matching %d", - link->frame_id - - dev_data.frame_id); - dump_info.m_link = link; - dump_info.s_link = link->sync_link[i]; - dump_info.dev_data = dev_data; - dump_info.s_req_id = sync_slot->req_id; - dump_info.m_req_id = slot->req_id; - cam_req_mgr_dump_link_info(&dump_info); - return rc; - } - - /* Calculating sof time differnce - * of master and slave for current frame - */ - curr_sync_time = - (dev_data.timestamp >= - link->sof_timestamp) ? - dev_data.timestamp - link->sof_timestamp : - link->sof_timestamp - dev_data.timestamp; - - threshold = frame_duration / THRESHOLD_FACTOR; - - /* Checking if master and sync links are in - * same frame duration considering master frame - * duration in calculating threshold value - */ - if (curr_sync_time > threshold) { - struct cam_req_mgr_dump_link_data - dump_info; - CAM_DBG(CAM_CRM, - "Master %x and slave %x are not in same time frame time diff %lld threshold %lld", - link->link_hdl, - link->sync_link[i]->link_hdl, - curr_sync_time/1000000, - threshold/1000000); - - dump_info.m_link = link; - dump_info.s_link = link->sync_link[i]; - dump_info.dev_data = dev_data; - dump_info.s_req_id = sync_slot->req_id; - dump_info.m_req_id = slot->req_id; - cam_req_mgr_dump_link_info(&dump_info); - return 0; - } - - /* If ISP substate is in applied state then - * condition it as bubble condition, - * Trigger bubble recovery - */ - if (dev_data.is_applied && - link->initial_sync_req != slot->req_id) { - CAM_ERR(CAM_CRM, - "Slave link %x req %lld is in applied state, triggering bubble recovery", - link->sync_link[i]->link_hdl, - (sync_slot->req_id - - link->sync_link[i]->max_delay)); - rc = cam_req_mgr_send_to_bubble(link, - (sync_slot->req_id - - link->sync_link[i]->max_delay)); - link->sync_link_sof_skip = true; - CAM_DBG(CAM_CRM, - "Master sof %lld slave sof %lld", - link->sof_timestamp, - dev_data.timestamp); - return rc; - } - - /* Checking if the initial request - * difference is maintained - */ - req_diff = link->initial_sync_req - - link->sync_link[i]->initial_sync_req; - - if (!link->sync_link_sof_skip && - req_diff != - (slot->req_id - sync_slot->req_id)) { - struct cam_req_mgr_dump_link_data - dump_info; - - CAM_DBG(CAM_CRM, - "Req diff %lld Master link %x req %lld slave link %x req %lld", - req_diff, - link->link_hdl, - slot->req_id, - link->sync_link[i]->link_hdl, - sync_slot->req_id); - - dump_info.m_link = link; - dump_info.s_link = link->sync_link[i]; - dump_info.dev_data = dev_data; - dump_info.s_req_id = sync_slot->req_id; - dump_info.m_req_id = slot->req_id; - cam_req_mgr_dump_link_info(&dump_info); - return rc; - } - } - } - } - - if (link->bubble_skip) { - link->bubble_skip--; - if (link->bubble_skip == 0) - link->sync_link_sof_skip = false; - goto slave; - } - - - if (trigger == CAM_TRIGGER_POINT_SOF && - slot->real_sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - int32_t slot_rd_idx; - - slot_rd_idx = link->req.in_q->rd_idx; - slot = &link->req.in_q->slot[slot_rd_idx]; - CAM_DBG(CAM_CRM, - "link %x idx %d req %lld state %d slot idx %d", - link->link_hdl, slot->idx, - slot->req_id, slot->status, slot_rd_idx); - if (slot->status == CRM_SLOT_STATUS_REQ_APPLIED) { - 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 row; - } - __cam_req_mgr_inc_idx( - &slot_rd_idx, 1, - link->req.in_q->num_slots); - } -row: - slot = &link->req.in_q->slot[slot_rd_idx]; - CAM_DBG(CAM_CRM, - "link %x idx %d req %lld state %d slot idx %d", - link->link_hdl, slot->idx, - slot->req_id, slot->status, slot_rd_idx); - - CAM_DBG(CAM_ISP, - "Start sync cond link %x modified sync req %lld enter", - slot->req_id, link->link_hdl); - - for (i = 0; i < link->num_sync_link; i++) { - int32_t sync_req_idx; - - //Checking if need to skip apply for this epoch - if (link->sync_link[i]->skip_sync_apply) { - CAM_INFO(CAM_ISP, - "Skipping apply on link %x as applied failed on other link %x", - link->link_hdl, - link->sync_link[i]->link_hdl); - link->sync_link[i]->skip_sync_apply = false; - return 0; - } - - //Check if other link is streaming or not - cam_req_mgr_get_device_info( - link->sync_link[i], &dev_data); - if (!dev_data.timestamp) { - CAM_INFO(CAM_ISP, "Link %x not streaming", - link->sync_link[i]->link_hdl); - return 0; - } - - sync_in_q = link->sync_link[i]->req.in_q; - if (slot->req_id == -1) { - sync_req_idx = sync_in_q->rd_idx; - } else { - sync_req_idx = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, slot->req_id); - } - - if (sync_req_idx == -1) { - CAM_DBG(CAM_CRM, - "Request %lld not in in_q link %x", - slot->req_id, - link->sync_link[i]->link_hdl); - if (slot->sync_mode != - CAM_REQ_MGR_SYNC_MODE_SYNC) { - CAM_DBG(CAM_CRM, - "slot not in sync mode %lld"); - __cam_req_mgr_inc_idx( - &sync_req_idx, 1, - link->req.in_q->num_slots); - goto cl; - } - return 0; - } - - __cam_req_mgr_dec_idx( - &sync_req_idx, 1, - link->sync_link[i]->req.in_q->num_slots); -cl: - sync_slot = &sync_in_q->slot[sync_req_idx]; - - //Checking if corresponding req is applied in other link or not - if (link->sync_link[i]->modified_init_sync_req != -1 && - sync_slot->req_id != -1 && - (link->sync_link[i]->modified_init_sync_req != - sync_slot->req_id) && - (link->sync_link[i]->modified_init_sync_req < - sync_slot->req_id) && - (sync_slot->status != - CRM_SLOT_STATUS_REQ_APPLIED)) { - CAM_ERR(CAM_ISP, - "ERROR Req %lld on link %x not applied", - sync_slot->req_id, - link->sync_link[i]->link_hdl); - return 0; - } - - CAM_DBG(CAM_ISP, - "Link %x modified sync req %lld enter state %d", - link->sync_link[i]->link_hdl, - sync_slot->req_id, sync_slot->status); - - __cam_req_mgr_inc_idx( - &sync_req_idx, 1, - link->sync_link[i]->req.in_q->num_slots); - - sync_slot = &sync_in_q->slot[sync_req_idx]; - - CAM_DBG(CAM_CRM, - "Check Req:%lld state %d link: %x, rc=%d", - sync_slot->req_id, sync_slot->status, - link->sync_link[i]->link_hdl, rc); - - if (sync_slot->status != CRM_SLOT_STATUS_REQ_APPLIED) { - rc = __cam_req_mgr_check_next_req_slot( - link->sync_link[i]); - if (rc) { - CAM_DBG(CAM_REQ, - "No pending req to apply to lower pd devices"); - rc = 0; - goto low; - } - rc = __cam_req_mgr_check_link_is_ready( - link->sync_link[i], sync_req_idx, true); - if (rc) { - CAM_DBG(CAM_CRM, - "Req:%lld not ready on link: %x, rc=%d", - sync_slot->req_id, - link->sync_link[i]->link_hdl, - rc); - link->skip_sync_apply = true; - return 0; - } - } -low: - CAM_DBG(CAM_ISP, - "End sync cond Link %x modified sync req %lld enter", - link->sync_link[i]->link_hdl, - sync_slot->req_id); - } - - rc = __cam_req_mgr_check_link_is_ready( - link, slot_rd_idx, true); - if (rc) { - CAM_DBG(CAM_CRM, - "M Req:%lld not ready on link: %x, rc=%d", - slot->req_id, link->link_hdl, rc); - link->skip_sync_apply = true; - return 0; - } - } - task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task frame %lld", @@ -3919,69 +3491,6 @@ low: task->process_cb = &cam_req_mgr_process_trigger; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); -slave: - - /* If sync mode is on and master epoch then enqueue workqueue to apply - * request for all sync link of master. - */ - - if (trigger == CAM_TRIGGER_POINT_SOF && - ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || - (tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC && - (link->initial_sync_req != -1))) && - link->is_master && - tmp_slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC)) { - - CAM_DBG(CAM_CRM, - "In sync mode req %lld tmp mode % real mode %d sync mode %d link %x ", - slot->req_id, tmp_slot->sync_mode, - tmp_slot->real_sync_mode, - slot->sync_mode, link->link_hdl); - - dev_name = __cam_req_mgr_dev_handle_to_name( - trigger_data->dev_hdl, link); - - for (i = 0; i < link->num_sync_link; i++) { - - task = cam_req_mgr_workq_get_task( - link->sync_link[i]->workq); - if (!task) { - CAM_ERR(CAM_CRM, "No empty task frame %lld", - trigger_data->frame_id); - rc = -EBUSY; - goto end; - } - - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - - if (sync_dev_hdl == -1) { - CAM_ERR(CAM_CRM, "Sync dev hdl is null"); - goto end; - } - CAM_DBG(CAM_CRM, "Sync link 0x%x sync dev hdl %x", - link->sync_link[i]->link_hdl, sync_dev_hdl); - - cam_req_mgr_get_device_info( - link->sync_link[i], &dev_data); - - task_data = (struct crm_task_payload *)task->payload; - task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF; - notify_trigger = (struct cam_req_mgr_trigger_notify *) - &task_data->u; - notify_trigger->frame_id = dev_data.frame_id; - notify_trigger->link_hdl = link->sync_link[i]->link_hdl; - notify_trigger->dev_hdl = sync_dev_hdl; - notify_trigger->trigger = trigger_data->trigger; - notify_trigger->req_id = trigger_data->req_id; - notify_trigger->sof_timestamp_val = - trigger_data->sof_timestamp_val; - task->process_cb = &cam_req_mgr_process_trigger; - rc = cam_req_mgr_workq_enqueue_task(task, - link->sync_link[i], CRM_TASK_PRIORITY_0); - } - } - end: return rc; } @@ -4326,8 +3835,6 @@ int cam_req_mgr_destroy_session( __cam_req_mgr_free_link(link); } } - for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) - clear_bit(i, g_crm_core_dev->bitmap); list_del(&cam_session->entry); mutex_unlock(&cam_session->lock); mutex_destroy(&cam_session->lock); @@ -4682,66 +4189,11 @@ end: return rc; } -/** - * __cam_req_mgr_set_master_link() - * - * @brief : Select master link based on the activate sequence - * - * @link : pointer to array of links - * @num_of_links : number of links to be sync - * - * @return : void - * - */ -static void __cam_req_mgr_set_master_link( - struct cam_req_mgr_core_link **link, - int32_t num_of_links) -{ - int i = 0, j = 0, k = 0; - int idx = -1; - - idx = find_first_bit(g_crm_core_dev->bitmap, - MAXIMUM_LINKS_PER_SESSION); - - for (i = 0; i < num_of_links; i++) { - - CAM_DBG(CAM_CRM, "idx %d, link%d 0x%x active seq %d", - idx, i, link[i]->link_hdl, - link[i]->activate_seq); - - if (link[i]->activate_seq == idx) { - - link[i]->is_master = true; - CAM_DBG(CAM_CRM, "Master link 0x%x num of links %d ", - link[i]->link_hdl, num_of_links); - - for (j = 0, k = 0; j < num_of_links; j++) { - if (link[i]->link_hdl != - link[j]->link_hdl) { - - link[i]->sync_link[k] = link[j]; - link[i]->num_sync_link++; - - link[j]->sync_link[0] = link[i]; - link[j]->num_sync_link = 1; - link[j]->is_master = false; - - k++; - } - } - } - - link[i]->initial_skip = - g_crm_core_dev->max_delay - link[i]->max_delay; - CAM_DBG(CAM_CRM, "link %x initial skip %d", - link[i]->link_hdl, link[i]->initial_skip); - } -} - int cam_req_mgr_sync_config( struct cam_req_mgr_sync_mode *sync_info) { - int i, j, rc = 0; + int i, j, rc = 0; + int sync_idx = 0; struct cam_req_mgr_core_session *cam_session; struct cam_req_mgr_core_link *link[MAX_LINKS_PER_SESSION]; @@ -4763,12 +4215,10 @@ int cam_req_mgr_sync_config( return -EINVAL; } - for (i = 0; i < sync_info->num_links; i++) { - if (!sync_info->link_hdls[i]) { - CAM_WARN(CAM_CRM, "Invalid link handles 0x%x", - sync_info->link_hdls[i]); - 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]); + return -EINVAL; } mutex_lock(&g_crm_core_dev->crm_lock); @@ -4784,56 +4234,60 @@ int cam_req_mgr_sync_config( mutex_lock(&cam_session->lock); for (i = 0; i < sync_info->num_links; i++) { + + if (!sync_info->link_hdls[i]) { + CAM_ERR(CAM_CRM, "link handle %d is null", i); + rc = -EINVAL; + goto done; + } + link[i] = cam_get_device_priv(sync_info->link_hdls[i]); if (!link[i]) { CAM_ERR(CAM_CRM, "link%d NULL pointer", i); rc = -EINVAL; goto done; } - CAM_DBG(CAM_CRM, "Link hdl %x sync mode %d", - link[i]->link_hdl, - sync_info->sync_mode); link[i]->sync_link_sof_skip = false; - link[i]->is_master = false; - link[i]->in_msync_mode = false; link[i]->initial_sync_req = -1; - link[i]->num_sync_link = 0; - link[i]->bubble_skip = 0; - link[i]->sync_frame_id = 0; - link[i]->is_sync_req = true; - link[i]->modified_init_sync_req = -1; + link[i]->num_sync_links = 0; for (j = 0; j < sync_info->num_links-1; j++) link[i]->sync_link[j] = NULL; - - g_crm_core_dev->max_delay = CAM_PIPELINE_DELAY_0; - - if (g_crm_core_dev->max_delay < link[i]->max_delay) - g_crm_core_dev->max_delay = link[i]->max_delay; } if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - __cam_req_mgr_set_master_link(link, sync_info->num_links); - - } else { for (i = 0; i < sync_info->num_links; i++) { - /* - * Reset below info after the mode is configured - * to NO-SYNC mode since they may be overridden - * if the sync config is invoked after SOF comes. - */ - link[i]->initial_skip = 0; + j = 0; + sync_idx = 0; + CAM_DBG(CAM_REQ, "link %x adds sync link:", + link[i]->link_hdl); + while (j < sync_info->num_links) { + if (i != j) { + link[i]->sync_link[sync_idx++] = + link[j]; + link[i]->num_sync_links++; + CAM_DBG(CAM_REQ, "sync_link[%d] : %x", + sync_idx-1, link[j]->link_hdl); + } + j++; + } + link[i]->initial_skip = true; link[i]->sof_timestamp = 0; - link[i]->num_sync_link = 0; - link[i]->initial_sync_req = -1; - link[i]->modified_init_sync_req = -1; + } + } else { + for (j = 0; j < sync_info->num_links; j++) { + link[j]->initial_skip = true; + link[j]->sof_timestamp = 0; } } cam_session->sync_mode = sync_info->sync_mode; + CAM_DBG(CAM_REQ, + "Sync config completed on %d links with sync_mode %d", + sync_info->num_links, sync_info->sync_mode); done: mutex_unlock(&cam_session->lock); @@ -4911,13 +4365,13 @@ end: int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) { - int rc = 0, i, j; - struct cam_req_mgr_core_link *link = NULL; - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_link_evt_data evt_data; - int init_timeout = 0; - long idx; - bool bit; + int rc = 0; + int i, j; + struct cam_req_mgr_core_link *link = NULL; + + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_link_evt_data evt_data; + int init_timeout = 0; if (!control) { CAM_ERR(CAM_CRM, "Control command is NULL"); @@ -4948,22 +4402,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) { spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_READY; - do { - idx = find_first_zero_bit( - g_crm_core_dev->bitmap, - MAXIMUM_LINKS_PER_SESSION); - if (idx >= MAXIMUM_LINKS_PER_SESSION) { - CAM_ERR(CAM_SYNC, - "Error: Unable to allocate link bit"); - rc = -ENOMEM; - break; - } - bit = test_and_set_bit( - idx, g_crm_core_dev->bitmap); - } while (bit); - link->activate_seq = idx; - CAM_DBG(CAM_CRM, "link hdl 0x%x activate idx %d", - link->link_hdl, link->activate_seq); spin_unlock_bh(&link->link_state_spin_lock); if (control->init_timeout[i]) link->skip_init_frame = true; @@ -5009,8 +4447,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->state = CAM_CRM_LINK_STATE_IDLE; link->skip_init_frame = false; crm_timer_exit(&link->watchdog); - clear_bit(link->activate_seq, g_crm_core_dev->bitmap); - link->activate_seq = -1; spin_unlock_bh(&link->link_state_spin_lock); CAM_DBG(CAM_CRM, "De-activate link: 0x%x", link->link_hdl); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 1bbc47f71ff6..6e6415c85fc0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -263,8 +263,7 @@ struct cam_req_mgr_req_tbl { * - members updated due to external events * @recover : if user enabled recovery for this request. * @req_id : mask tracking which all devices have request ready - * @sync_mode : Modified sync mode in which req id in this slot has to applied - * @real_sync_mode : Actual sync mode in which req id in this slot has to applied + * @sync_mode : Sync mode in which req id in this slot has to applied * @additional_timeout : Adjusted watchdog timeout value associated with * this request */ @@ -275,7 +274,6 @@ struct cam_req_mgr_slot { int32_t recover; int64_t req_id; int32_t sync_mode; - int32_t real_sync_mode; int32_t additional_timeout; }; @@ -357,7 +355,7 @@ struct cam_req_mgr_connected_device { * @lock : mutex lock to guard link data operations * @link_state_spin_lock : spin lock to protect link state variable * @sync_link : array of pointer to the sync link for synchronization - * @num_sync_link : total number of sync links + * @num_sync_links : num of links sync associated with this link * @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. @@ -367,14 +365,11 @@ struct cam_req_mgr_connected_device { * @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 initial req need to skip for - * diff pd - * @is_sync_req : flag used for deciding sync and non-sync + * @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 - * @modified_init_sync_req : Modified initial req which is required to sync - * with the other link * @retry_cnt : Counter that tracks number of attempts to apply * the same req * @is_shutdown : Flag to indicate if link needs to be disconnected @@ -389,10 +384,6 @@ struct cam_req_mgr_connected_device { * case of long exposure use case * @last_sof_trigger_jiffies : Record the jiffies of last sof trigger jiffies * @wq_congestion : Indicates if WQ congestion is detected or not - * @activate_seq : sequence in which link is activated - * @frame_id : current frame id - * @sync_frame_id : current frame id of sync link - * @bubble_skip : req to skip on bubble */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -408,22 +399,19 @@ struct cam_req_mgr_core_link { void *parent; struct mutex lock; spinlock_t link_state_spin_lock; - struct cam_req_mgr_core_link *sync_link[ - MAXIMUM_LINKS_PER_SESSION]; - int32_t num_sync_link; + struct cam_req_mgr_core_link + *sync_link[MAXIMUM_LINKS_PER_SESSION - 1]; + int32_t num_sync_links; bool sync_link_sof_skip; int32_t open_req_cnt; uint32_t last_flush_id; atomic_t is_used; bool is_master; - uint32_t initial_skip; - bool is_sync_req; + bool initial_skip; bool in_msync_mode; int64_t initial_sync_req; - int64_t modified_init_sync_req; uint32_t retry_cnt; bool is_shutdown; - uint64_t sof_boottime; uint64_t sof_timestamp; uint64_t prev_sof_timestamp; bool dual_trigger; @@ -432,11 +420,6 @@ struct cam_req_mgr_core_link { bool skip_init_frame; uint64_t last_sof_trigger_jiffies; bool wq_congestion; - int32_t activate_seq; - uint64_t frame_id; - uint64_t sync_frame_id; - int32_t bubble_skip; - bool skip_sync_apply; }; /** @@ -470,33 +453,11 @@ struct cam_req_mgr_core_session { * @session_head : list head holding sessions * @crm_lock : mutex lock to protect session creation & destruction * @recovery_on_apply_fail : Recovery on apply failure using debugfs. - * @bitmap : bitmap to store index of link - * @max_delay : max pipeline delay in a session */ struct cam_req_mgr_core_device { struct list_head session_head; struct mutex crm_lock; bool recovery_on_apply_fail; - DECLARE_BITMAP(bitmap, MAXIMUM_LINKS_PER_SESSION); - uint32_t max_delay; -}; - -/** - * struct cam_req_mgr_dump_link_data - * - Dump data - * @m_link : master link handle - * @s_link : slave link handle - * @m_req_id : master req id - * @s_req_id : slave req id - * @dev_info : current timing data of slave link - * - */ -struct cam_req_mgr_dump_link_data { - struct cam_req_mgr_core_link *m_link; - struct cam_req_mgr_core_link *s_link; - uint64_t m_req_id; - uint64_t s_req_id; - struct cam_req_mgr_dev_info dev_data; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index e8e4f941a39c..b6807ed4a7f0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -22,7 +22,6 @@ struct cam_req_mgr_apply_request; struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; struct cam_req_mgr_dump_info; -struct cam_req_mgr_request_change_state; /* Request Manager -- camera device driver interface */ /** @@ -34,9 +33,8 @@ struct cam_req_mgr_request_change_state; * userspace * @cam_req_mgr_notify_timer : start the timer */ -typedef int (*cam_req_mgr_notify_trigger)( - struct cam_req_mgr_trigger_notify *); -typedef bool (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); +typedef int (*cam_req_mgr_notify_trigger)(struct cam_req_mgr_trigger_notify *); +typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *); typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); @@ -50,9 +48,8 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); * @cam_req_mgr_notify_frame_skip: CRM asks device to apply setting for * frame skip * @cam_req_mgr_flush_req : Flush or cancel request - * @cam_req_mgr_process_evt : generic events + * cam_req_mgr_process_evt : generic events * @cam_req_mgr_dump_req : dump request - * @cam_req_mgr_change_state : CRM asks device to change its state */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); @@ -62,8 +59,6 @@ typedef int (*cam_req_mgr_notify_frame_skip)( typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); -typedef int (*cam_req_mgr_change_state)( - struct cam_req_mgr_request_change_state *); /** * @brief : cam_req_mgr_crm_cb - func table @@ -92,17 +87,15 @@ struct cam_req_mgr_crm_cb { * @flush_req : payload to flush request * @process_evt : payload to generic event * @dump_req : payload to dump request - * @change_state : payload to change state */ struct cam_req_mgr_kmd_ops { - cam_req_mgr_get_dev_info get_dev_info; - cam_req_mgr_link_setup link_setup; - cam_req_mgr_apply_req apply_req; + cam_req_mgr_get_dev_info get_dev_info; + cam_req_mgr_link_setup link_setup; + cam_req_mgr_apply_req apply_req; cam_req_mgr_notify_frame_skip notify_frame_skip; - cam_req_mgr_flush_req flush_req; - cam_req_mgr_process_evt process_evt; - cam_req_mgr_dump_req dump_req; - cam_req_mgr_change_state change_state; + cam_req_mgr_flush_req flush_req; + cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; }; /** @@ -223,7 +216,6 @@ enum cam_req_mgr_link_evt_type { * @trigger : trigger point of this notification, CRM will send apply * only to the devices which subscribe to this point. * @sof_timestamp_val: Captured time stamp value at sof hw event - * @sof_boottime : Captured boot time stamp value at sof hw event * @req_id : req id which returned buf_done * @trigger_id: ID to differentiate between the trigger devices */ @@ -233,7 +225,6 @@ struct cam_req_mgr_trigger_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; - uint64_t sof_boottime; uint64_t req_id; int32_t trigger_id; }; @@ -258,8 +249,6 @@ struct cam_req_mgr_timer_notify { * @frame_id : frame id for internal tracking * @trigger : trigger point of this notification, CRM will send apply * @sof_timestamp_val : Captured time stamp value at sof hw event - * @sof_boottime_val : Captured boottime stamp value at sof hw event - * @need_recovery : flag to check if recovery is needed * @error : what error device hit while processing this req */ struct cam_req_mgr_error_notify { @@ -269,8 +258,6 @@ struct cam_req_mgr_error_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; - uint64_t sof_boottime_val; - bool need_recovery; enum cam_req_mgr_device_error error; }; @@ -315,7 +302,6 @@ struct cam_req_mgr_notify_stop { * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client * @trigger_on : This device provides trigger - * @sof_ts_cb : callback to real time drivers */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -324,7 +310,6 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; - int32_t (*sof_ts_cb)(int32_t dev_hdl, void *data); }; /** @@ -423,37 +408,4 @@ struct cam_req_mgr_dump_info { int32_t link_hdl; int32_t dev_hdl; }; - -/** - * struct cam_req_mgr_dev_info - * @link_hdl : link identifier - * @state : Current substate for the activated state. - * @timestamp : time stamp for the sof event - * @boot_time : boot time stamp for the sof event - * @frame_id : frame id - * @is_applied : if ISP is in applied state - * - */ -struct cam_req_mgr_dev_info { - int32_t link_hdl; - uint32_t state; - uint64_t timestamp; - uint64_t boot_time; - uint64_t frame_id; - bool is_applied; -}; - -/** - * struct cam_req_mgr_request_change_state - * @link_hdl : link identifier - * @dev_hdl : device handle or identifier - * @req_id : request id - * - */ -struct cam_req_mgr_request_change_state { - int32_t link_hdl; - int32_t dev_hdl; - uint64_t req_id; -}; - #endif diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index c9c2906ce56c..9c0d7abd043d 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -410,7 +410,6 @@ int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info) strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name)); info->p_delay = 1; info->trigger = CAM_TRIGGER_POINT_SOF; - info->sof_ts_cb = NULL; return 0; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 2d71dc8c00d2..8cda6c3831c8 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1785,8 +1785,6 @@ int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info) strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name)); info->p_delay = CAM_FLASH_PIPELINE_DELAY; info->trigger = CAM_TRIGGER_POINT_SOF; - info->sof_ts_cb = NULL; - return 0; } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 19dbffc4a2bc..32b05eadfc64 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1129,7 +1129,6 @@ int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info) else info->p_delay = 2; info->trigger = CAM_TRIGGER_POINT_SOF; - info->sof_ts_cb = NULL; return rc; } From bb921ff616ca71617600c69a68c15c6068bfe8cc Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 22 Dec 2020 13:59:52 +0530 Subject: [PATCH 729/790] Revert "msm: camera: req_mgr: Re-design CRM to support multi links in sync mode" This reverts commit 65a86de9799e86931dddae537b56a868220fdade. CRs-Fixed: 2898158 Change-Id: I40efe11908603fddc8aec025edca2536ada46e99 Signed-off-by: Ayush Kumar --- drivers/cam_core/cam_context.c | 29 +- drivers/cam_core/cam_context.h | 17 +- drivers/cam_core/cam_node.c | 21 +- drivers/cam_cust/cam_custom_context.c | 1 - drivers/cam_isp/cam_isp_context.c | 202 +- .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 10 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 1796 ++++++----------- drivers/cam_req_mgr/cam_req_mgr_core.h | 55 +- drivers/cam_req_mgr/cam_req_mgr_interface.h | 66 +- .../cam_actuator/cam_actuator_core.c | 1 - .../cam_flash/cam_flash_core.c | 2 - .../cam_sensor/cam_sensor_core.c | 1 - 12 files changed, 656 insertions(+), 1545 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 9492d681ea77..75424db0c16a 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -182,33 +182,6 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } -int cam_context_handle_crm_state_change(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info) -{ - int rc; - - if (!ctx->state_machine) { - CAM_ERR(CAM_CORE, "Context is not ready"); - return -EINVAL; - } - - if (!state_info) { - CAM_ERR(CAM_CORE, "Invalid change state payload"); - return -EINVAL; - } - - if (ctx->state_machine[ctx->state].crm_ops.change_state) { - rc = ctx->state_machine[ctx->state].crm_ops.change_state(ctx, - state_info); - } else { - CAM_ERR(CAM_CORE, "No crm change state req in dev %d, state %d", - ctx->dev_hdl, ctx->state); - rc = -EPROTO; - } - - return rc; -} - int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 0ca3cccd8d87..5be078536ff5 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -127,7 +127,6 @@ struct cam_ctx_ioctl_ops { * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request - * @change_state: Change sub-state of hw context layer to bubble * */ struct cam_ctx_crm_ops { @@ -147,8 +146,6 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_link_evt_data *evt_data); int (*dump_req)(struct cam_context *ctx, struct cam_req_mgr_dump_info *dump); - int (*change_state)(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *change_state); }; @@ -313,18 +310,6 @@ int cam_context_handle_crm_unlink(struct cam_context *ctx, int cam_context_handle_crm_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); -/** - * cam_context_handle_crm_state_change() - * - * @brief: Handle state change request - * - * @ctx: Object pointer for cam_context - * @state_info: State change request command payload - * - */ -int cam_context_handle_crm_state_change(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info); - /** * cam_context_handle_crm_notify_frame_skip() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 5df221f71b6c..c3770f2df745 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -619,24 +619,6 @@ static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) return cam_context_handle_crm_flush_req(ctx, flush); } -static int __cam_node_crm_state_change_req( - struct cam_req_mgr_request_change_state *state_info) -{ - struct cam_context *ctx = NULL; - - if (!state_info) - return -EINVAL; - - ctx = (struct cam_context *) cam_get_device_priv(state_info->dev_hdl); - if (!ctx) { - CAM_ERR(CAM_CORE, "Can not get context for handle %d", - state_info->dev_hdl); - return -EINVAL; - } - - return cam_context_handle_crm_state_change(ctx, state_info); -} - static int __cam_node_crm_process_evt( struct cam_req_mgr_link_evt_data *evt_data) { @@ -733,7 +715,6 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.dump_req = __cam_node_crm_dump_req; node->crm_node_intf.notify_frame_skip = __cam_node_crm_notify_frame_skip; - node->crm_node_intf.change_state = __cam_node_crm_state_change_req; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 134b5aa2b995..ca4d1d1e35d5 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -549,7 +549,6 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; - dev_info->sof_ts_cb = NULL; return 0; } diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index ccf3f7a4d19f..f7a95795744b 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -743,8 +743,8 @@ static void __cam_isp_ctx_send_sof_timestamp( req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta; CAM_DBG(CAM_ISP, - "link hdl 0x%x request id:%lld frame number:%lld SOF time stamp:%lld status:%u", - ctx_isp->base->link_hdl, request_id, ctx_isp->frame_id, + "request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u", + request_id, ctx_isp->frame_id, ctx_isp->sof_timestamp_val, sof_event_status); if (cam_req_mgr_notify_message(&req_msg, @@ -1700,7 +1700,6 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( } 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; @@ -1709,9 +1708,8 @@ static int __cam_isp_ctx_reg_upd_in_applied_state( ctx_isp->active_req_cnt++; request_id = req->request_id; CAM_DBG(CAM_REQ, - "move request %lld to active list(cnt = %d), ctx %u link %x", - req->request_id, ctx_isp->active_req_cnt, - ctx->ctx_id, ctx->link_hdl); + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_RUP, req); } else { @@ -1853,7 +1851,6 @@ notify_only: notify.trigger = CAM_TRIGGER_POINT_SOF; notify.req_id = ctx_isp->req_info.last_bufdone_req_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - notify.sof_boottime = ctx_isp->boot_timestamp; notify.trigger_id = ctx_isp->trigger_id; ctx->ctx_crm_intf->notify_trigger(¬ify); @@ -1973,9 +1970,8 @@ static int __cam_isp_ctx_sof_in_activated_state( __cam_isp_ctx_update_state_monitor_array(ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_SOF, request_id); - CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u link %x", - ctx_isp->frame_id, ctx_isp->sof_timestamp_val, - ctx->ctx_id, ctx->link_hdl); + 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; } @@ -2020,7 +2016,6 @@ end: static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { - bool rc = false; uint64_t request_id = 0; uint32_t sof_event_status = CAM_REQ_MGR_SOF_EVENT_SUCCESS; struct cam_req_mgr_trigger_notify notify; @@ -2059,9 +2054,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req_isp->reapply = true; req_isp->cdm_reset_before_apply = false; - CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d link %x Report Bubble flag %d req id:%lld", - ctx->ctx_id, ctx->link_hdl, - req_isp->bubble_report, req->request_id); + CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", + ctx->ctx_id, req_isp->bubble_report, req->request_id); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; @@ -2075,25 +2069,12 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - notify.sof_boottime_val = ctx_isp->boot_timestamp; - notify.need_recovery = true; CAM_WARN_RATE_LIMIT(CAM_ISP, "Notify CRM about Bubble req %lld frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); trace_cam_log_event("Bubble", "Rcvd epoch in applied state", req->request_id, ctx->ctx_id); - rc = ctx->ctx_crm_intf->notify_err(¬ify); - - CAM_DBG(CAM_CRM, "Need bubble recovery %d", rc); - - if (rc) { - req_isp->bubble_detected = false; - req_isp->reapply = false; - CAM_DBG(CAM_ISP, "Disable bubble for ctx %d link %d", - ctx->ctx_id, ctx->link_hdl); - return 0; - } - + ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; @@ -2268,7 +2249,6 @@ static int __cam_isp_ctx_buf_done_in_bubble( static int __cam_isp_ctx_epoch_in_bubble_applied( struct cam_isp_context *ctx_isp, void *evt_data) { - int rc = 0; uint64_t request_id = 0; struct cam_req_mgr_trigger_notify notify; struct cam_ctx_request *req; @@ -2326,17 +2306,10 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( notify.trigger = CAM_TRIGGER_POINT_SOF; notify.frame_id = ctx_isp->frame_id; notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; - notify.sof_boottime_val = ctx_isp->boot_timestamp; - notify.need_recovery = true; CAM_WARN_RATE_LIMIT(CAM_REQ, "Notify CRM about Bubble req_id %llu frame %lld, ctx %u", req->request_id, ctx_isp->frame_id, ctx->ctx_id); - rc = ctx->ctx_crm_intf->notify_err(¬ify); - if (rc) { - req_isp->bubble_detected = false; - req_isp->reapply = false; - return 0; - } + ctx->ctx_crm_intf->notify_err(¬ify); atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; @@ -3200,10 +3173,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state( goto end; } - CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u link %x", + CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u", req->request_id, __cam_isp_ctx_substate_val_to_type(ctx_isp->substate_activated), - ctx->ctx_id, ctx->link_hdl); + ctx->ctx_id); req_isp = (struct cam_isp_ctx_req *) req->req_priv; if (ctx_isp->active_req_cnt >= 2) { @@ -3286,81 +3259,6 @@ end: return rc; } -static int __cam_isp_ctx_change_substate( - struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info) -{ - int rc = 0; - uint64_t request_id = 0; - struct cam_ctx_request *req = NULL; - struct cam_ctx_request *req_temp = NULL; - struct cam_ctx_request *bubble_req = NULL; - struct cam_isp_ctx_req *req_isp = NULL; - struct cam_isp_context *ctx_isp = - (struct cam_isp_context *) ctx->ctx_priv; - - if (!list_empty(&ctx->wait_req_list)) { - req = list_first_entry(&ctx->wait_req_list, - struct cam_ctx_request, - list); - if (req->request_id == state_info->req_id) { - req_isp = (struct cam_isp_ctx_req *)req->req_priv; - req_isp->bubble_detected = true; - req_isp->reapply = true; - bubble_req = req; - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->active_req_list); - goto end; - } - } else { - CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id); - } - - if (!bubble_req) { - list_for_each_entry_safe(req, req_temp, - &ctx->active_req_list, list) { - if (req->request_id == state_info->req_id) { - req_isp = - (struct cam_isp_ctx_req *)req->req_priv; - req_isp->bubble_detected = true; - req_isp->reapply = true; - bubble_req = req; - break; - } - } - } - - if (!bubble_req) { - CAM_ERR(CAM_ISP, "Req %lld not in active list ctx : %d", - state_info->req_id, - ctx->ctx_id); - goto done; - } - -end: - - if (req_isp->bubble_report) - atomic_set(&ctx_isp->process_bubble, 1); - - if ((req->request_id > ctx_isp->reported_req_id) - && !req_isp->bubble_report) { - request_id = req->request_id; - ctx_isp->reported_req_id = request_id; - } - - __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, - CAM_REQ_MGR_SOF_EVENT_ERROR); - - ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE; - - CAM_DBG(CAM_ISP, "next Substate[%s] ctx : %d", - __cam_isp_ctx_substate_val_to_type( - ctx_isp->substate_activated), ctx->ctx_id); - -done: - return rc; -} - static int __cam_isp_ctx_apply_req_in_sof( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -3421,8 +3319,8 @@ static int __cam_isp_ctx_apply_req_in_bubble( ctx_isp->substate_activated)); rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply, CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED); - CAM_DBG(CAM_ISP, "ctx %d link %x new Substate[%s]", - ctx->ctx_id, ctx->link_hdl, __cam_isp_ctx_substate_val_to_type( + CAM_DBG(CAM_ISP, "new Substate[%s]", + __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); if (rc) @@ -3786,7 +3684,6 @@ static int __cam_isp_ctx_flush_req_in_top_state( flush_req); ctx_isp->active_req_cnt = 0; - spin_unlock_bh(&ctx->lock); reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; @@ -3834,16 +3731,13 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_sof, - .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, /* APPLIED */ { .ioctl_ops = {}, - .crm_ops = { - .change_state = __cam_isp_ctx_change_substate, - }, + .crm_ops = {}, .irq_ops = NULL, }, /* EPOCH */ @@ -3851,7 +3745,6 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_epoch, - .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, @@ -3860,16 +3753,13 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_isp_ctx_apply_req_in_bubble, - .change_state = __cam_isp_ctx_change_substate, }, .irq_ops = NULL, }, /* Bubble Applied */ { .ioctl_ops = {}, - .crm_ops = { - .change_state = __cam_isp_ctx_change_substate, - }, + .crm_ops = {}, .irq_ops = NULL, }, /* HW ERROR */ @@ -5462,33 +5352,6 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx, return rc; } -static int __cam_isp_ctx_get_isp_info(int32_t dev_hdl, void *data) -{ - int rc = 0; - struct cam_context *ctx; - struct cam_req_mgr_dev_info *isp_dev = data; - struct cam_isp_context *isp_ctx = NULL; - - ctx = (struct cam_context *)cam_get_device_priv(dev_hdl); - - isp_ctx = (struct cam_isp_context *)ctx->ctx_priv; - - isp_dev->state = isp_ctx->substate_activated; - isp_dev->timestamp = isp_ctx->sof_timestamp_val; - isp_dev->boot_time = isp_ctx->boot_timestamp; - isp_dev->frame_id = isp_ctx->frame_id; - - if ((isp_ctx->substate_activated == - CAM_ISP_CTX_ACTIVATED_APPLIED) || - (isp_ctx->substate_activated == - CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED)) - isp_dev->is_applied = true; - else - isp_dev->is_applied = false; - - return rc; -} - static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { @@ -5500,7 +5363,6 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; dev_info->trigger_on = true; - dev_info->sof_ts_cb = &__cam_isp_ctx_get_isp_info; return rc; } @@ -5558,8 +5420,6 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->rxd_epoch, 0); ctx_isp->frame_id = 0; - ctx_isp->sof_timestamp_val = 0; - ctx_isp->boot_timestamp = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->bubble_frame_cnt = 0; @@ -5909,33 +5769,6 @@ static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx, return rc; } -static int __cam_isp_ctx_change_state_req(struct cam_context *ctx, - struct cam_req_mgr_request_change_state *state_info) -{ - int rc = 0; - struct cam_ctx_ops *ctx_ops = NULL; - struct cam_isp_context *ctx_isp = - (struct cam_isp_context *) ctx->ctx_priv; - - CAM_DBG(CAM_ISP, "Enter: changes state ctx id %d link 0x%x", - ctx->ctx_id, ctx->link_hdl); - ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated]; - if (ctx_ops->crm_ops.change_state) { - rc = ctx_ops->crm_ops.change_state(ctx, state_info); - } else { - CAM_WARN_RATE_LIMIT(CAM_ISP, - "No handle function in activated Substate[%s]", - __cam_isp_ctx_substate_val_to_type( - ctx_isp->substate_activated)); - rc = -EFAULT; - } - - if (rc) - CAM_WARN_RATE_LIMIT(CAM_ISP, - "changes state failed"); - return rc; -} - static int __cam_isp_ctx_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -6088,7 +5921,6 @@ static struct cam_ctx_ops .flush_req = __cam_isp_ctx_flush_req_in_top_state, .process_evt = __cam_isp_ctx_process_evt, .dump_req = __cam_isp_ctx_dump_in_top_state, - .change_state = __cam_isp_ctx_change_state_req, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_requests, @@ -6313,8 +6145,6 @@ int cam_isp_context_init(struct cam_isp_context *ctx, ctx->base = ctx_base; ctx->frame_id = 0; - ctx->sof_timestamp_val = 0; - ctx->boot_timestamp = 0; ctx->custom_enabled = false; ctx->use_frame_header_ts = false; ctx->active_req_cnt = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index b04c3448b6b5..a4f15165d0bf 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -261,17 +261,15 @@ enum cam_isp_ctx_type { * @ctx_type: RDI_ONLY, PIX and RDI, or FS2 * @packet_op_code: Packet opcode * @last_cdm_done: Last cdm done request - * @cam_isp_hw_sof_event_data sof event timestamp */ struct cam_isp_hw_cmd_args { uint32_t cmd_type; void *cmd_data; union { - uint32_t sof_irq_enable; - uint32_t ctx_type; - uint32_t packet_op_code; - uint64_t last_cdm_done; - struct cam_isp_hw_sof_event_data sof_done_event_data; + uint32_t sof_irq_enable; + uint32_t ctx_type; + uint32_t packet_op_code; + uint64_t last_cdm_done; } u; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 36a105be5a1d..0bd68d76fa68 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -17,14 +17,9 @@ #include "cam_req_mgr_dev.h" #include "cam_req_mgr_debug.h" -#define THRESHOLD_FACTOR 3 - static struct cam_req_mgr_core_device *g_crm_core_dev; static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION]; -static char *__cam_req_mgr_dev_handle_to_name( - int32_t dev_hdl, struct cam_req_mgr_core_link *link); - void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) { uint32_t pd = 0; @@ -46,7 +41,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->open_req_cnt = 0; link->last_flush_id = 0; link->initial_sync_req = -1; - link->modified_init_sync_req = -1; link->dual_trigger = false; link->trigger_cnt[0][0] = 0; link->trigger_cnt[0][1] = 0; @@ -55,18 +49,13 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; - link->initial_skip = 0; + link->initial_skip = true; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; link->skip_init_frame = false; + link->num_sync_links = 0; link->last_sof_trigger_jiffies = 0; link->wq_congestion = false; - link->num_sync_link = 0; - link->activate_seq = -1; - link->bubble_skip = 0; - link->sync_frame_id = 0; - link->is_sync_req = true; - link->skip_sync_apply = false; atomic_set(&link->eof_event_cnt, 0); for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { @@ -210,33 +199,6 @@ static int __cam_req_mgr_inject_delay( return rc; } -/** - * cam_req_mgr_get_dev_hdl() - * - * @brief : Finds device handle based on the device name - * @dev_name : Device name whose dev handle is to be found - * @link : Link on which the device is connected - * @return : device handle - * - */ -static int32_t cam_req_mgr_get_dev_hdl( - char *dev_name, struct cam_req_mgr_core_link *link) -{ - struct cam_req_mgr_connected_device *dev = NULL; - int i = 0; - - for (i = 0; i < link->num_devs; i++) { - dev = &link->l_dev[i]; - CAM_DBG(CAM_CRM, "dev name %s, iterate dev name %s", - dev_name, dev->dev_info.name); - if (strcmp(dev_name, dev->dev_info.name) == 0) - goto end; - } - return -EINVAL; -end: - return dev->dev_hdl; -} - /** * __cam_req_mgr_find_dev_name() * @@ -419,10 +381,10 @@ static int __cam_req_mgr_notify_error_on_link( * @return: 0 for success, negative for failure * */ -static int __cam_req_mgr_traverse( - struct cam_req_mgr_traverse *traverse_data) +static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) { int rc = 0; + int32_t next_idx = traverse_data->idx; int32_t curr_idx = traverse_data->idx; struct cam_req_mgr_req_tbl *tbl; struct cam_req_mgr_apply *apply_data; @@ -438,18 +400,24 @@ static int __cam_req_mgr_traverse( tbl = traverse_data->tbl; apply_data = traverse_data->apply_data; slot = &tbl->slot[curr_idx]; + CAM_DBG(CAM_CRM, + "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", + tbl->pd, curr_idx, tbl->slot[curr_idx].state, + tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, + traverse_data->in_q->slot[curr_idx].skip_idx); - while (tbl) { - CAM_DBG(CAM_CRM, - "Enter pd %d idx %d state %d skip %d status %d skip_idx %d", - tbl->pd, curr_idx, tbl->slot[curr_idx].state, - tbl->skip_traverse, - traverse_data->in_q->slot[curr_idx].status, - traverse_data->in_q->slot[curr_idx].skip_idx); - if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || - traverse_data->in_q->slot[curr_idx].skip_idx == 1 || - tbl->skip_traverse > 0) { - + /* 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 || + tbl->skip_traverse > 0) { + if (tbl->next) { + __cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta, + tbl->num_slots); + traverse_data->idx = next_idx; + traverse_data->tbl = tbl->next; + rc = __cam_req_mgr_traverse(traverse_data); + } + if (rc >= 0) { SET_SUCCESS_BIT(traverse_data->result, tbl->pd); if (traverse_data->validate_only == false) { @@ -460,34 +428,33 @@ static int __cam_req_mgr_traverse( apply_data[tbl->pd].idx = curr_idx; CAM_DBG(CAM_CRM, "req_id: %lld with pd of %d", - apply_data[tbl->pd].req_id, - apply_data[tbl->pd].pd); - + apply_data[tbl->pd].req_id, + apply_data[tbl->pd].pd); + /* + * If traverse is successful decrement + * traverse skip + */ if (tbl->skip_traverse > 0) { apply_data[tbl->pd].req_id = -1; tbl->skip_traverse--; } } - rc = 0; } else { - traverse_data->result_data.req_id = - CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); - traverse_data->result_data.pd = tbl->pd; - traverse_data->result_data.masked_value = - (tbl->dev_mask & slot->req_ready_map); - SET_FAILURE_BIT(traverse_data->result, tbl->pd); - rc = -EAGAIN; - break; + /* linked pd table is not ready for this traverse yet */ + return rc; } - if (tbl->next) { - __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, - tbl->num_slots); - traverse_data->idx = curr_idx; - traverse_data->tbl = tbl->next; - } - tbl = tbl->next; + } else { + /* This pd table is not ready to proceed with asked idx */ + traverse_data->result_data.req_id = + CRM_GET_REQ_ID(traverse_data->in_q, curr_idx); + traverse_data->result_data.pd = tbl->pd; + traverse_data->result_data.masked_value = + (tbl->dev_mask & slot->req_ready_map); + SET_FAILURE_BIT(traverse_data->result, tbl->pd); + return -EAGAIN; } - return rc; + + return 0; } /** @@ -768,51 +735,6 @@ static int __cam_req_mgr_check_for_lower_pd_devices( return -EAGAIN; } -/** - * cam_req_mgr_dump_link_info() - * @brief : Dump link info on failure - * - * @dump_info : payload to dump data - */ -static void cam_req_mgr_dump_link_info( - struct cam_req_mgr_dump_link_data *dump_info) -{ - int i = 0; - struct cam_req_mgr_core_link *m_link; - struct cam_req_mgr_dev_info dev_data; - - m_link = dump_info->m_link; - dev_data = dump_info->dev_data; - - CAM_DBG(CAM_CRM, - "Master link req_id %lld 0x%x Slave link 0x%x req_id %lld frame id %lld csid time %lld boottime %lld", - m_link->link_hdl, dump_info->s_link->link_hdl, - dump_info->m_req_id, dump_info->s_req_id, - dev_data.frame_id, dev_data.timestamp, - dev_data.boot_time); - - CAM_DBG(CAM_CRM, - "Master link 0x%x csid time %lld bootime %lld frame id %lld sync frame id %lld init sync req %lld", - m_link->link_hdl, - m_link->sof_timestamp, - m_link->sof_boottime, - m_link->frame_id, - m_link->sync_frame_id, - m_link->initial_sync_req); - - for (i = 0; i < m_link->num_sync_link; i++) { - CAM_DBG(CAM_CRM, - "slave link 0x%x csid time %lld bootime %lld frame id %lld sync frame id %lld init sync req %lld", - m_link->sync_link[i]->link_hdl, - m_link->sync_link[i]->sof_timestamp, - m_link->sync_link[i]->sof_boottime, - m_link->sync_link[i]->frame_id, - m_link->sync_link[i]->sync_frame_id, - m_link->sync_link[i]->initial_sync_req); - } -} - - /** * __cam_req_mgr_check_next_req_slot() * @@ -1139,6 +1061,19 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.validate_only = validate_only; traverse_data.open_req_cnt = link->open_req_cnt; + /* + * Some no-sync mode requests are processed after link config, + * then process the sync mode requests after no-sync mode requests + * are handled, the initial_skip should be false when processing + * the sync mode requests. + */ + if (link->initial_skip) { + CAM_DBG(CAM_CRM, + "Set initial_skip to false for link %x", + link->link_hdl); + link->initial_skip = false; + } + /* * Traverse through all pd tables, if result is success, * apply the settings @@ -1200,29 +1135,420 @@ static int32_t __cam_req_mgr_find_slot_for_req( } /** - * cam_req_mgr_get_device_info() + * __cam_req_mgr_check_sync_for_mslave() * - * @brief : Get state and qtime info from device - * @link : pointer to link - * @sof_ts : pointer to dev_info payload - * - * @return : void + * @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_get_device_info( +static int __cam_req_mgr_check_sync_for_mslave( struct cam_req_mgr_core_link *link, - struct cam_req_mgr_dev_info *dev_info) + struct cam_req_mgr_core_link *sync_link, + struct cam_req_mgr_slot *slot) { - int i; - struct cam_req_mgr_connected_device *dev; + 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; + int32_t sync_num_slots = 0; - for (i = 0; i < link->num_devs; i++) { - dev = &link->l_dev[i]; - dev_info->link_hdl = link->link_hdl; - if (dev && dev->dev_info.sof_ts_cb) - dev->dev_info.sof_ts_cb(dev->dev_hdl, dev_info); + if (!sync_link || !link) { + CAM_ERR(CAM_CRM, "Sync link or link is null"); + return -EINVAL; } + + req_id = slot->req_id; + + if (!sync_link->req.in_q) { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + + sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + + CAM_DBG(CAM_CRM, + "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); + + 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; + return -EAGAIN; + } + + 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; + } + + if (link->is_master) { + if (sync_link->initial_skip) { + CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + 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; + } + + 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 + sync_num_slots) % + sync_num_slots) >= 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_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 + sync_num_slots) % + sync_num_slots) >= 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; + } + } + } + + CAM_DBG(CAM_REQ, + "Req: %lld ready to apply on link: %x [validation successful]", + req_id, link->link_hdl); + + return 0; +} + + +/** + * __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 + * traversed through + * @slot : pointer to the current slot being processed + * @return : 0 for success, negative for failure + * + */ +static int __cam_req_mgr_check_sync_req_is_ready( + struct cam_req_mgr_core_link *link, + struct cam_req_mgr_core_link *sync_link, + struct cam_req_mgr_slot *slot) +{ + struct cam_req_mgr_slot *sync_rd_slot = NULL; + int64_t req_id = 0, sync_req_id = 0; + int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; + int32_t sync_num_slots = 0; + uint64_t sync_frame_duration = 0; + uint64_t sof_timestamp_delta = 0; + uint64_t master_slave_diff = 0; + bool ready = true, sync_ready = true; + int slot_idx_diff = 0; + + if (!sync_link || !link) { + CAM_ERR(CAM_CRM, "Sync link null"); + return -EINVAL; + } + + req_id = slot->req_id; + + if (!sync_link->req.in_q) { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + + sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; + + CAM_DBG(CAM_REQ, + "link_hdl %x sync link_hdl %x req %lld", + link->link_hdl, sync_link->link_hdl, req_id); + + if (sync_link->initial_skip) { + link->initial_skip = false; + CAM_DBG(CAM_CRM, + "sync link %x not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + if (sync_link->prev_sof_timestamp) + sync_frame_duration = sync_link->sof_timestamp - + sync_link->prev_sof_timestamp; + else + sync_frame_duration = DEFAULT_FRAME_DURATION; + + sof_timestamp_delta = + link->sof_timestamp >= sync_link->sof_timestamp + ? link->sof_timestamp - sync_link->sof_timestamp + : sync_link->sof_timestamp - link->sof_timestamp; + + CAM_DBG(CAM_CRM, + "sync link %x last frame_duration is %d ns", + sync_link->link_hdl, sync_frame_duration); + + if (link->initial_skip) { + link->initial_skip = false; + + if ((link->sof_timestamp > sync_link->sof_timestamp) && + (sync_link->sof_timestamp > 0) && + (link->sof_timestamp - sync_link->sof_timestamp) < + (sync_frame_duration / 2)) { + /* + * If this frame sync with the previous frame of sync + * link, then we need to skip this frame, since the + * previous frame of sync link is also skipped. + */ + CAM_DBG(CAM_CRM, + "This frame sync with previous sync_link %x frame", + sync_link->link_hdl); + return -EAGAIN; + } else if (link->sof_timestamp <= sync_link->sof_timestamp) { + /* + * Sometimes, link receives the SOF event is eariler + * than sync link in IFE CSID side, but link's SOF + * event is processed later than sync link's, then + * we need to skip this SOF event since the sync + * link's SOF event is also skipped. + */ + CAM_DBG(CAM_CRM, + "The previous frame of sync link is skipped"); + return -EAGAIN; + } + } + + 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; + return -EAGAIN; + } + + sync_slot_idx = __cam_req_mgr_find_slot_for_req( + sync_link->req.in_q, req_id); + if (sync_slot_idx == -1) { + CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", + req_id, sync_link->link_hdl); + sync_ready = false; + return -EAGAIN; + } + + slot_idx_diff = (sync_slot_idx - sync_rd_idx + sync_num_slots) % + sync_num_slots; + if ((sync_link->req.in_q->slot[sync_slot_idx].status != + CRM_SLOT_STATUS_REQ_APPLIED) && + ((slot_idx_diff > 1) || + ((slot_idx_diff == 1) && + (sync_rd_slot->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); + return -EAGAIN; + } + + rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); + if (rc) { + CAM_DBG(CAM_CRM, + "Req: %lld [My link] not ready on link: %x, rc=%d", + req_id, link->link_hdl, rc); + ready = false; + } + + if (sync_link->req.in_q) { + 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 link: %x, rc=%d", + req_id, sync_link->link_hdl, rc); + sync_ready = false; + } + } else { + CAM_ERR(CAM_CRM, "Link hdl %x in_q is NULL", + sync_link->link_hdl); + return -EINVAL; + } + + /* + * If both of them are ready or not ready, then just + * skip this sof and don't skip sync link next SOF. + */ + if (sync_ready != ready) { + CAM_DBG(CAM_CRM, + "Req: %lld ready %d sync_ready %d, ignore sync link next SOF", + req_id, ready, sync_ready); + + /* + * Only skip the frames if current frame sync with + * next frame of sync link. + */ + if (link->sof_timestamp - sync_link->sof_timestamp > + sync_frame_duration / 2) + link->sync_link_sof_skip = true; + return -EINVAL; + } else if (!ready) { + CAM_DBG(CAM_CRM, + "Req: %lld not ready on link: %x", + req_id, link->link_hdl); + return -EINVAL; + } + + /* + * Do the self-correction when the frames are sync, + * we consider that the frames are synced if the + * difference of two SOF timestamp less than + * (sync_frame_duration / 5). + */ + master_slave_diff = sync_frame_duration; + do_div(master_slave_diff, 5); + if ((sync_link->sof_timestamp > 0) && + (sof_timestamp_delta < master_slave_diff) && + (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { + + /* + * This means current frame should sync with next + * frame of sync link, then the request id of in + * rd slot of two links should be same. + */ + CAM_DBG(CAM_CRM, + "link %x req_id %lld, sync_link %x req_id %lld", + link->link_hdl, req_id, + sync_link->link_hdl, sync_req_id); + + if (req_id > sync_req_id) { + CAM_DBG(CAM_CRM, + "link %x too quickly, skip this frame", + link->link_hdl); + return -EAGAIN; + } else if (req_id < sync_req_id) { + CAM_DBG(CAM_CRM, + "sync link %x too quickly, skip next frame of sync link", + sync_link->link_hdl); + link->sync_link_sof_skip = true; + } else if (sync_link->req.in_q->slot[sync_slot_idx].status != + CRM_SLOT_STATUS_REQ_APPLIED) { + CAM_DBG(CAM_CRM, + "link %x other not applied", link->link_hdl); + return -EAGAIN; + } + } + CAM_DBG(CAM_REQ, + "Req: %lld ready to apply on link: %x [validation successful]", + req_id, link->link_hdl); + + return 0; } static int __cam_req_mgr_check_multi_sync_link_ready( @@ -1230,16 +1556,60 @@ static int __cam_req_mgr_check_multi_sync_link_ready( struct cam_req_mgr_slot *slot, uint32_t trigger) { - int rc = 0; + int i, rc = 0; if (link->state == CAM_CRM_LINK_STATE_IDLE) { CAM_ERR(CAM_CRM, "link hdl %x is in idle state", - link->link_hdl); + link->link_hdl); return -EINVAL; } + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if (link->sync_link[i]->state == + CAM_CRM_LINK_STATE_IDLE) { + CAM_ERR(CAM_CRM, "sync link hdl %x is idle", + link->sync_link[i]->link_hdl); + return -EINVAL; + } + if (link->max_delay == link->sync_link[i]->max_delay) { + rc = __cam_req_mgr_check_sync_req_is_ready( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link %x not ready", + link->link_hdl); + return rc; + } + } else if (link->max_delay > + link->sync_link[i]->max_delay) { + link->is_master = true; + link->sync_link[i]->is_master = false; + rc = __cam_req_mgr_check_sync_for_mslave( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link%x not ready", + link->link_hdl); + return rc; + } + } else { + link->is_master = false; + link->sync_link[i]->is_master = true; + rc = __cam_req_mgr_check_sync_for_mslave( + link, link->sync_link[i], slot); + if (rc < 0) { + CAM_DBG(CAM_CRM, "link %x not ready", + link->link_hdl); + return rc; + } + } + } else { + CAM_ERR(CAM_REQ, "Sync link is null"); + return -EINVAL; + } + } + rc = __cam_req_mgr_inject_delay(link->req.l_tbl, - slot->idx, trigger); + slot->idx, trigger); if (rc < 0) { CAM_DBG(CAM_CRM, "Req: %lld needs to inject delay at %s", @@ -1324,7 +1694,7 @@ enum crm_req_eof_trigger_type __cam_req_mgr_check_for_eof( static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_trigger_notify *trigger_data) { - int i = 0, rc = 0, idx; + int rc = 0, idx, i; int reset_step = 0; uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; @@ -1358,7 +1728,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, in_q->slot[in_q->rd_idx].additional_timeout, trigger); slot = &in_q->slot[in_q->rd_idx]; - if (slot->status == CRM_SLOT_STATUS_NO_REQ) { CAM_DBG(CAM_CRM, "No Pending req"); rc = 0; @@ -1378,6 +1747,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } if (trigger == CAM_TRIGGER_POINT_SOF) { + /* + * Update the timestamp in session lock protection + * to avoid timing issue. + */ + link->prev_sof_timestamp = link->sof_timestamp; + link->sof_timestamp = trigger_data->sof_timestamp_val; /* Check for WQ congestion */ if (jiffies_to_msecs(jiffies - @@ -1390,14 +1765,8 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (slot->status != CRM_SLOT_STATUS_REQ_READY) { if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - 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_multi_sync_link_ready( - link, slot, trigger); + link, slot, trigger); } else { if (link->in_msync_mode) { CAM_DBG(CAM_CRM, @@ -1405,10 +1774,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); link->in_msync_mode = false; link->initial_sync_req = -1; - for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; - i++) { - tmp_link = link->sync_link[i]; - if (tmp_link) { + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + tmp_link = link->sync_link[i]; tmp_link->initial_sync_req = -1; tmp_link->in_msync_mode = false; } @@ -1478,13 +1846,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } - if (link->num_sync_link && - (link->initial_sync_req == slot->req_id)) { - link->sync_frame_id = trigger_data->frame_id; - CAM_DBG(CAM_CRM, "link %x sync frame %lld", - link->link_hdl, link->sync_frame_id); - } - rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger, &dev); if (rc < 0) { /* Apply req failed retry at next sof */ @@ -1553,10 +1914,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->link_hdl); idx = in_q->rd_idx; reset_step = link->max_delay; - for (i = 0; i < link->num_sync_link - 1; i++) { - if (reset_step < link->sync_link[i]->max_delay) - reset_step = + + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if ((link->in_msync_mode) && + (link->sync_link[i]->max_delay > + reset_step)) + reset_step = link->sync_link[i]->max_delay; + } } if (slot->req_id > 0) @@ -2112,9 +2478,8 @@ static void __cam_req_mgr_unreserve_link( } } - for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++) - link->sync_link[i] = NULL; - + for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) + link->sync_link[j] = NULL; session->num_links--; CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); mutex_unlock(&session->lock); @@ -2244,6 +2609,13 @@ 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 is_master %d exp_timeout_val %d ms", + sched_req->link_hdl, sched_req->req_id, + in_q->wr_idx, sched_req->sync_mode, + link->is_master, + sched_req->additional_timeout); + mutex_lock(&link->req.lock); slot = &in_q->slot[in_q->wr_idx]; @@ -2253,10 +2625,9 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) slot->status = CRM_SLOT_STATUS_REQ_ADDED; slot->req_id = sched_req->req_id; + slot->sync_mode = sched_req->sync_mode; slot->skip_idx = 0; slot->recover = sched_req->bubble_enable; - slot->sync_mode = sched_req->sync_mode; - slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; if (sched_req->additional_timeout < 0) { CAM_WARN(CAM_CRM, "Requested timeout is invalid [%dms]", @@ -2277,63 +2648,16 @@ int cam_req_mgr_process_sched_req(void *priv, void *data) __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) { + if (link->initial_sync_req == -1) link->initial_sync_req = slot->req_id; - link->modified_init_sync_req = slot->req_id; - } } else { link->initial_sync_req = -1; - for (i = 0; i < link->num_sync_link; i++) { - if (link->sync_link[i]) { + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) link->sync_link[i]->initial_sync_req = -1; - link->modified_init_sync_req = -1; - } } } - CAM_DBG(CAM_CRM, - "link_hdl %x req_id %lld at slot %d schedule_mode %d slot mode %d is_master %d exp_timeout_val %d ms", - sched_req->link_hdl, sched_req->req_id, - in_q->wr_idx, sched_req->sync_mode, - slot->sync_mode, - link->is_master, - sched_req->additional_timeout); - /* - * This logic is to make first few requests in non-sync mode - * so that these requests should apply irrespective of threshold - * time condition as difference in sensor stream on may be more than - * threshold value at start. For sw sync logic to work, first few - * requests needs to apply in same frame duration. - */ - - if (link->is_sync_req && slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC - && ((link->initial_sync_req + 5) > slot->req_id)) { - slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_SYNC; - } else if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - if (link->is_sync_req && (link->initial_skip == 0)) { - link->is_sync_req = false; - link->initial_sync_req = slot->req_id + 1; - CAM_DBG(CAM_CRM, "Initial sync req %lld link %x", - link->initial_sync_req, link->link_hdl); - } - - if (link->initial_skip && link->initial_sync_req) { - link->initial_skip--; - slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - slot->real_sync_mode = CAM_REQ_MGR_SYNC_MODE_SYNC; - CAM_DBG(CAM_CRM, "Initial sync req %lld link %x", - link->initial_sync_req, link->link_hdl); - } - } - CAM_DBG(CAM_CRM, - "link_hdl %x req_id %lld at slot %d schedule_mode %d slot mode %d is_master %d exp_timeout_val %d ms init sync %d", - sched_req->link_hdl, sched_req->req_id, - in_q->wr_idx, sched_req->sync_mode, - slot->sync_mode, - link->is_master, - sched_req->additional_timeout, - link->initial_sync_req); mutex_unlock(&link->req.lock); end: @@ -2352,19 +2676,12 @@ end: */ int cam_req_mgr_process_add_req(void *priv, void *data) { - int rc = 0, i = 0, j = 0; - int idx, idx2; + int rc = 0, i = 0, idx; struct cam_req_mgr_add_request *add_req = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_connected_device *device = NULL; - struct cam_req_mgr_connected_device *device2 = NULL; struct cam_req_mgr_req_tbl *tbl = NULL; - struct cam_req_mgr_req_tbl *tbl2 = NULL; struct cam_req_mgr_tbl_slot *slot = NULL; - struct cam_req_mgr_tbl_slot *sync_slot = NULL; - int32_t sync_dev_hdl = -1; - char *dev_name = NULL; - struct cam_req_mgr_slot *link_slot = NULL; struct crm_task_payload *task_data = NULL; if (!data || !priv) { @@ -2392,7 +2709,6 @@ int cam_req_mgr_process_add_req(void *priv, void *data) rc = -EINVAL; goto end; } - /* * Go through request table and add * request id to proper table @@ -2412,7 +2728,6 @@ int cam_req_mgr_process_add_req(void *priv, void *data) goto end; } - link_slot = &link->req.in_q->slot[idx]; slot = &tbl->slot[idx]; slot->ops.is_applied = false; @@ -2423,62 +2738,6 @@ int cam_req_mgr_process_add_req(void *priv, void *data) add_req->req_id, slot->inject_delay_at_sof, device->dev_info.name); - - if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - mutex_lock(&link->sync_link[i]->req.lock); - idx2 = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, - add_req->req_id); - if (idx2 < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q for dev %s on link 0x%x", - add_req->req_id, - device->dev_info.name, - link->sync_link[i]->link_hdl); - rc = -EBADSLT; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - dev_name = __cam_req_mgr_dev_handle_to_name( - add_req->dev_hdl, link); - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - for (j = 0; - j < link->sync_link[i]->num_devs; j++) { - device2 = &link->sync_link[i]->l_dev[j]; - CAM_ERR(CAM_CRM, "device hdl %x : sync link dev hdl %x", - device2->dev_hdl, sync_dev_hdl); - if (device2->dev_hdl == sync_dev_hdl) { - tbl2 = device2->pd_tbl; - break; - } - } - if (!tbl2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Sync link dev hdl %x not found", - sync_dev_hdl); - rc = -EINVAL; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - sync_slot = &tbl2->slot[idx2]; - sync_slot->ops.dev_hdl = sync_dev_hdl; - sync_slot->inject_delay_at_sof = - (add_req->skip_at_sof & 0xFF); - CAM_DBG(CAM_CRM, - "link %x Req_id %llu injecting delay %llu frame at SOF by %s", - link->sync_link[i]->link_hdl, - add_req->req_id, - slot->inject_delay_at_sof, - device->dev_info.name); - mutex_unlock(&link->sync_link[i]->req.lock); - } - } } if ((add_req->skip_at_eof & 0xFF) > slot->inject_delay_at_eof) { @@ -2488,123 +2747,14 @@ int cam_req_mgr_process_add_req(void *priv, void *data) add_req->req_id, slot->inject_delay_at_eof, device->dev_info.name); - - if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - mutex_lock(&link->sync_link[i]->req.lock); - idx2 = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, - add_req->req_id); - if (idx2 < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q for dev %s on link 0x%x", - add_req->req_id, - device->dev_info.name, - link->sync_link[i]->link_hdl); - rc = -EBADSLT; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - dev_name = __cam_req_mgr_dev_handle_to_name( - add_req->dev_hdl, link); - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - for (j = 0; - j < link->sync_link[i]->num_devs; j++) { - device2 = &link->sync_link[i]->l_dev[j]; - CAM_ERR(CAM_CRM, "device hdl %x : sync link dev hdl %x", - device2->dev_hdl, sync_dev_hdl); - if (device2->dev_hdl == sync_dev_hdl) { - tbl2 = device2->pd_tbl; - break; - } - } - if (!tbl2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Synclink dev hdl %x not found", - sync_dev_hdl); - rc = -EINVAL; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - sync_slot = &tbl2->slot[idx2]; - sync_slot->ops.dev_hdl = sync_dev_hdl; - sync_slot->inject_delay_at_eof = - (add_req->skip_at_eof & 0xFF); - CAM_DBG(CAM_CRM, - "link %x Req_id %llu injecting delay %llu frame at EOF by %s", - link->sync_link[i]->link_hdl, - add_req->req_id, - slot->inject_delay_at_sof, - device->dev_info.name); - mutex_unlock(&link->sync_link[i]->req.lock); - } - } } if (add_req->trigger_eof) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, - "link %x Req_id %llu slot:%d added for EOF tigger for Device: %s", - link->link_hdl, + "Req_id %llu slot:%d added for EOF tigger for Device: %s", add_req->req_id, idx, device->dev_info.name); - - if (link_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - mutex_lock(&link->sync_link[i]->req.lock); - idx2 = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, - add_req->req_id); - if (idx2 < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q for dev %s on link 0x%x", - add_req->req_id, - device->dev_info.name, - link->sync_link[i]->link_hdl); - rc = -EBADSLT; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - dev_name = __cam_req_mgr_dev_handle_to_name( - add_req->dev_hdl, link); - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - for (j = 0; - j < link->sync_link[i]->num_devs; j++) { - device2 = &link->sync_link[i]->l_dev[j]; - CAM_ERR(CAM_CRM, - "device hdl %x : sync link dev hdl %x", - device2->dev_hdl, sync_dev_hdl); - if (device2->dev_hdl == sync_dev_hdl) { - tbl2 = device2->pd_tbl; - break; - } - } - if (!tbl2) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Sync link dev hdl %x not found", - sync_dev_hdl); - rc = -EINVAL; - mutex_unlock( - &link->sync_link[i]->req.lock); - mutex_unlock(&link->req.lock); - goto end; - } - sync_slot = &tbl2->slot[idx2]; - sync_slot->ops.is_applied = false; - sync_slot->ops.apply_at_eof = true; - sync_slot->ops.dev_hdl = sync_dev_hdl; - mutex_unlock(&link->sync_link[i]->req.lock); - } - } - } if (slot->state != CRM_REQ_STATE_PENDING && @@ -2618,8 +2768,8 @@ int cam_req_mgr_process_add_req(void *priv, void *data) slot->state = CRM_REQ_STATE_PENDING; slot->req_ready_map |= (1 << device->dev_bit); - CAM_DBG(CAM_CRM, "link %x idx %d dev_hdl %x req_id %lld pd %d ready_map %x", - link->link_hdl, idx, add_req->dev_hdl, add_req->req_id, tbl->pd, + CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x", + idx, add_req->dev_hdl, add_req->req_id, tbl->pd, slot->req_ready_map); trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); @@ -2832,8 +2982,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) mutex_lock(&link->req.lock); - if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF - && !link->num_sync_link) { + if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) { idx = __cam_req_mgr_find_slot_for_req(in_q, trigger_data->req_id); if (idx >= 0) { @@ -2868,8 +3017,6 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) in_q->slot[in_q->rd_idx].status); spin_unlock_bh(&link->link_state_spin_lock); - CAM_DBG(CAM_CRM, "Link %x req id %lld", - link->link_hdl, in_q->slot[in_q->rd_idx].req_id); /* * Move to next req at SOF only in case @@ -2914,7 +3061,7 @@ end: * @return : String containing the device name * */ -static char *__cam_req_mgr_dev_handle_to_name( +static const char *__cam_req_mgr_dev_handle_to_name( int32_t dev_hdl, struct cam_req_mgr_core_link *link) { struct cam_req_mgr_connected_device *dev = NULL; @@ -2943,12 +3090,11 @@ static char *__cam_req_mgr_dev_handle_to_name( */ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) { - int i, rc = 0, idx; + int rc = 0, idx; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_add_request *dev_req; struct crm_task_payload *task_data; - struct cam_req_mgr_slot *slot = NULL; if (!add_req) { CAM_ERR(CAM_CRM, "sof_data is NULL"); @@ -2987,8 +3133,6 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) goto end; } - slot = &link->req.in_q->slot[idx]; - task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task dev %x req %lld", @@ -3010,10 +3154,6 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) atomic_inc(&link->eof_event_cnt); CAM_DBG(CAM_REQ, "Req_id: %llu, eof_event_cnt: %d", dev_req->req_id, link->eof_event_cnt); - if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) - atomic_inc(&link->sync_link[i]->eof_event_cnt); - } } task->process_cb = &cam_req_mgr_process_add_req; @@ -3030,30 +3170,23 @@ end: * cam_req_mgr_cb_notify_err() * * @brief : Error received from device, sends bubble recovery - * * @err_info : contains information about error occurred like bubble/overflow * - * @return : true on skipping bubble processing, otherwise, false + * @return : 0 on success, negative in case of failure * */ -static bool cam_req_mgr_cb_notify_err( +static int cam_req_mgr_cb_notify_err( struct cam_req_mgr_error_notify *err_info) { - bool rc = false; - int i, j; - uint32_t idx; + int rc = 0; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_error_notify *notify_err; struct crm_task_payload *task_data; - struct cam_req_mgr_slot *slot = NULL; - struct cam_req_mgr_slot *tmp_slot = NULL; - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_request_change_state state_info; if (!err_info) { CAM_ERR(CAM_CRM, "err_info is NULL"); - rc = false; + rc = -EINVAL; goto end; } @@ -3061,127 +3194,37 @@ static bool cam_req_mgr_cb_notify_err( cam_get_device_priv(err_info->link_hdl); if (!link) { CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl); - rc = false; + rc = -EINVAL; goto end; } - idx = __cam_req_mgr_find_slot_for_req( - link->req.in_q, err_info->req_id); - if (idx < 0) { - CAM_ERR(CAM_CRM, - "req %lld not found in in_q link %x", - err_info->req_id, link->link_hdl); - rc = false; - goto end; - } - - tmp_slot = &link->req.in_q->slot[idx]; - - /* Incrementing slot idx to find if request in the slot - * is applied in sync mode or non-sync mode. - */ - __cam_req_mgr_inc_idx( - &idx, 1, link->req.in_q->num_slots); - - slot = &link->req.in_q->slot[idx]; - - /* Condition to check if crm need to process bubble notified by - * crm or isp. If bubble is reported for slave link then don't - * process bubble recovery. Checking previous slot with tmp_slot - * to handle condition where bubble is reported for last request. - */ - if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || - tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) && - !link->is_master) { - crm_timer_reset(link->watchdog); - CAM_DBG(CAM_CRM, "Not processing bubble as it is slave link %x", - link->link_hdl); - return true; - } - spin_lock_bh(&link->link_state_spin_lock); if (link->state != CAM_CRM_LINK_STATE_READY) { CAM_WARN(CAM_CRM, "invalid link state:%d", link->state); spin_unlock_bh(&link->link_state_spin_lock); - rc = false; + rc = -EPERM; goto end; } crm_timer_reset(link->watchdog); spin_unlock_bh(&link->link_state_spin_lock); - if (link->is_master && - slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - for (i = 0; i < link->num_sync_link; i++) { - CAM_DBG(CAM_CRM, "Bubble for sync link %x", - link->sync_link[i]->link_hdl); - state_info.link_hdl = link->sync_link[i]->link_hdl; - state_info.req_id = err_info->req_id; - for (j = 0; j < link->sync_link[i]->num_devs; j++) { - dev = &link->sync_link[i]->l_dev[j]; - if (dev->ops && dev->ops->change_state) { - state_info.dev_hdl = dev->dev_hdl; - - if (!(dev->ops->change_state( - &state_info))) { - CAM_DBG(CAM_CRM, - "Err on bubble notify"); - rc = false; - } - - task = cam_req_mgr_workq_get_task( - link->workq); - if (!task) { - CAM_ERR(CAM_CRM, - "no empty task req_id %lld", - err_info->req_id); - rc = false; - goto end; - } - - task_data = (struct crm_task_payload *) - task->payload; - task_data->type = - CRM_WORKQ_TASK_NOTIFY_ERR; - notify_err = - (struct cam_req_mgr_error_notify *)& - task_data->u; - notify_err->req_id = err_info->req_id; - notify_err->link_hdl = - link->sync_link[i]->link_hdl; - notify_err->dev_hdl = dev->dev_hdl; - notify_err->error = err_info->error; - task->process_cb = - &cam_req_mgr_process_error; - cam_req_mgr_workq_enqueue_task( - task, - link->sync_link[i], - CRM_TASK_PRIORITY_0); - } - } - } + task = cam_req_mgr_workq_get_task(link->workq); + if (!task) { + CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id); + rc = -EBUSY; + goto end; } - if (err_info->need_recovery) { - task = cam_req_mgr_workq_get_task(link->workq); - if (!task) { - CAM_ERR(CAM_CRM, "no empty task req_id %lld", - err_info->req_id); - rc = false; - goto end; - } - - task_data = (struct crm_task_payload *)task->payload; - task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; - notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; - notify_err->req_id = err_info->req_id; - notify_err->link_hdl = err_info->link_hdl; - notify_err->dev_hdl = err_info->dev_hdl; - notify_err->error = err_info->error; - notify_err->trigger = err_info->trigger; - task->process_cb = &cam_req_mgr_process_error; - rc = cam_req_mgr_workq_enqueue_task( - task, link, CRM_TASK_PRIORITY_0); - } + task_data = (struct crm_task_payload *)task->payload; + task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR; + notify_err = (struct cam_req_mgr_error_notify *)&task_data->u; + notify_err->req_id = err_info->req_id; + notify_err->link_hdl = err_info->link_hdl; + notify_err->dev_hdl = err_info->dev_hdl; + notify_err->error = err_info->error; + notify_err->trigger = err_info->trigger; + task->process_cb = &cam_req_mgr_process_error; + rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); end: return rc; @@ -3337,51 +3380,7 @@ end: return rc; } -static int cam_req_mgr_send_to_bubble( - struct cam_req_mgr_core_link *link, - uint64_t req_id) -{ - int rc = 0, i; - struct cam_req_mgr_error_notify notify; - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_request_change_state state_info; - struct cam_req_mgr_dev_info dev_data; - notify.link_hdl = link->link_hdl; - notify.req_id = req_id; - notify.error = CRM_KMD_ERR_BUBBLE; - notify.trigger = CAM_TRIGGER_POINT_SOF; - notify.frame_id = link->frame_id; - notify.sof_timestamp_val = link->sof_timestamp; - notify.need_recovery = false; - - for (i = 0; i < link->num_devs; i++) { - dev = &link->l_dev[i]; - if (dev->ops && dev->ops->change_state) { - notify.dev_hdl = dev->dev_hdl; - if (dev->ops && dev->ops->change_state) { - cam_req_mgr_get_device_info(link, &dev_data); - if (dev_data.is_applied) { - state_info.link_hdl = link->link_hdl; - state_info.req_id = req_id; - state_info.dev_hdl = dev->dev_hdl; - rc = dev->ops->change_state( - &state_info); - if (rc < 0) - CAM_INFO(CAM_CRM, - "Failed to change state"); - } else { - link->bubble_skip = link->max_delay; - } - } - rc = cam_req_mgr_cb_notify_err(¬ify); - if (!rc) - CAM_INFO(CAM_CRM, - "Bubble recovery failed"); - } - } - return rc; -} /** * cam_req_mgr_cb_notify_trigger() @@ -3395,27 +3394,12 @@ static int cam_req_mgr_send_to_bubble( static int cam_req_mgr_cb_notify_trigger( struct cam_req_mgr_trigger_notify *trigger_data) { - int32_t i = 0, rc = 0, trigger_id = 0; - int32_t sync_dev_hdl = -1, sync_id = 0; - int64_t req_diff = 0; - uint32_t trigger; - struct crm_workq_task *task = NULL; - struct cam_req_mgr_core_link *link = NULL; + int32_t rc = 0, trigger_id = 0; + uint32_t trigger; + struct crm_workq_task *task = NULL; + struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_trigger_notify *notify_trigger; - struct crm_task_payload *task_data; - struct cam_req_mgr_slot *slot = NULL; - struct cam_req_mgr_slot *tmp_slot = NULL; - struct cam_req_mgr_req_queue *in_q; - struct timespec64 ts; - struct cam_req_mgr_dev_info dev_data; - struct cam_req_mgr_slot *sync_slot = NULL; - struct cam_req_mgr_req_queue *sync_in_q; - int32_t sync_rd_idx = 0; - char *dev_name = NULL; - uint64_t curr_sync_time = 0; - uint64_t frame_duration = 0; - uint64_t curr_boot_timestamp; - uint64_t threshold = 0; + struct crm_task_payload *task_data; if (!trigger_data) { CAM_ERR(CAM_CRM, "trigger_data is NULL"); @@ -3438,10 +3422,6 @@ static int cam_req_mgr_cb_notify_trigger( trigger_id = trigger_data->trigger_id; trigger = trigger_data->trigger; - ktime_get_boottime_ts64(&ts); - curr_boot_timestamp = - (uint64_t)((ts.tv_sec * 1000000000) + - ts.tv_nsec); /* * Reduce the workq overhead when there is @@ -3485,416 +3465,8 @@ static int cam_req_mgr_cb_notify_trigger( if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) crm_timer_reset(link->watchdog); - link->prev_sof_timestamp = link->sof_timestamp; - link->sof_timestamp = trigger_data->sof_timestamp_val; - link->frame_id = trigger_data->frame_id; - link->sof_boottime = trigger_data->sof_boottime; spin_unlock_bh(&link->link_state_spin_lock); - in_q = link->req.in_q; - slot = &in_q->slot[in_q->rd_idx]; - tmp_slot = &in_q->slot[in_q->rd_idx]; - - CAM_DBG(CAM_CRM, - "link %x req %lld idx %d state %d real sync mode %d", - link->link_hdl, slot->req_id, sync_id, slot->status, - slot->real_sync_mode); - - if (link->initial_sync_req != -1 && - slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC && - link->num_sync_link) { - sync_id = slot->idx; - __cam_req_mgr_inc_idx( - &sync_id, 1, link->req.in_q->num_slots); - slot = &in_q->slot[sync_id]; - CAM_DBG(CAM_CRM, - "E link %x req %lld idx %d state %d", - link->link_hdl, slot->req_id, sync_id, slot->status); - } - - - CAM_DBG(CAM_CRM, - "link %x req %lld slot mode %d tmp slot mode %d init sync %lld", - link->link_hdl, slot->req_id, - slot->sync_mode, tmp_slot->sync_mode, - link->initial_sync_req); - - if (trigger == CAM_TRIGGER_POINT_SOF && - (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || - (tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC && - (link->initial_sync_req != -1)))) { - /* If in sync and slave link then don't apply */ - if (!link->is_master) { - - CAM_DBG(CAM_CRM, - "Skipping slave link 0x%x apply sof timestamp %llx frame %lld slot req %lld", - link->link_hdl, - link->sof_timestamp, - trigger_data->frame_id, - slot->req_id); - - CAM_DBG(CAM_CRM, - "[Slave %x] epoch time %lld sof boottime %lld frame id %lld open cnt %d req id %lld", - link->link_hdl, - curr_boot_timestamp, - link->sof_boottime, - trigger_data->frame_id, - link->open_req_cnt, - slot->req_id); - - goto end; - } else { - - frame_duration = - (curr_boot_timestamp - link->sof_boottime) * 2; - CAM_DBG(CAM_CRM, - "[Master %x] epoch time %lld sof boottime %lld frame id %lld frame duration %d ms open cnt %d req id %lld", - link->link_hdl, - curr_boot_timestamp, - link->sof_boottime, - trigger_data->frame_id, - frame_duration/1000000, - link->open_req_cnt, - slot->req_id); - - rc = __cam_req_mgr_check_next_req_slot(link); - 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", - slot->req_id, link->link_hdl, rc); - return rc; - } - - /* Checking each sync link if they are ready to apply - * on this epoch, if not then skip apply on this epoch - */ - for (i = 0; i < link->num_sync_link; i++) { - sync_in_q = link->sync_link[i]->req.in_q; - sync_rd_idx = sync_in_q->rd_idx; - __cam_req_mgr_inc_idx( - &sync_rd_idx, 1, - link->sync_link[i]->req.in_q->num_slots); - sync_slot = &sync_in_q->slot[sync_rd_idx]; - rc = __cam_req_mgr_check_next_req_slot( - link->sync_link[i]); - - /* This condition is for SAT usecase, - * if request id to be sync is different - * then this will help to sync - */ - if (link->initial_sync_req != -1 && - (link->sync_link[i]->initial_sync_req != - -1) && (link->initial_sync_req == - slot->req_id) && - (link->sync_link[i]->initial_sync_req > - sync_slot->req_id)) { - CAM_DBG(CAM_CRM, - "Not applying on Master %x as slave %x is not in sync", - link->link_hdl, - link->sync_link[i]->link_hdl); - return rc; - } - - /* checking if packet for synclink is - * available or not - */ - rc = __cam_req_mgr_check_link_is_ready( - link->sync_link[i], sync_rd_idx, true); - - if (rc) { - CAM_DBG(CAM_CRM, - "Req:%lld [sync] not ready on link: %x, rc=%d", - sync_slot->req_id, - link->sync_link[i]->link_hdl, - rc); - return rc; - } - - /* Getting time and state info ISP context */ - cam_req_mgr_get_device_info( - link->sync_link[i], &dev_data); - - /* Checking if frame difference is maintain */ - req_diff = - (link->sync_frame_id - - link->sync_link[i]->sync_frame_id); - if (!link->sync_link_sof_skip && - link->sync_frame_id && - link->initial_sync_req != slot->req_id - && (req_diff != (link->frame_id - - dev_data.frame_id))) { - struct cam_req_mgr_dump_link_data - dump_info; - - CAM_DBG(CAM_CRM, - "Frame diff not matching %d", - link->frame_id - - dev_data.frame_id); - dump_info.m_link = link; - dump_info.s_link = link->sync_link[i]; - dump_info.dev_data = dev_data; - dump_info.s_req_id = sync_slot->req_id; - dump_info.m_req_id = slot->req_id; - cam_req_mgr_dump_link_info(&dump_info); - return rc; - } - - /* Calculating sof time differnce - * of master and slave for current frame - */ - curr_sync_time = - (dev_data.timestamp >= - link->sof_timestamp) ? - dev_data.timestamp - link->sof_timestamp : - link->sof_timestamp - dev_data.timestamp; - - threshold = frame_duration / THRESHOLD_FACTOR; - - /* Checking if master and sync links are in - * same frame duration considering master frame - * duration in calculating threshold value - */ - if (curr_sync_time > threshold) { - struct cam_req_mgr_dump_link_data - dump_info; - CAM_DBG(CAM_CRM, - "Master %x and slave %x are not in same time frame time diff %lld threshold %lld", - link->link_hdl, - link->sync_link[i]->link_hdl, - curr_sync_time/1000000, - threshold/1000000); - - dump_info.m_link = link; - dump_info.s_link = link->sync_link[i]; - dump_info.dev_data = dev_data; - dump_info.s_req_id = sync_slot->req_id; - dump_info.m_req_id = slot->req_id; - cam_req_mgr_dump_link_info(&dump_info); - return 0; - } - - /* If ISP substate is in applied state then - * condition it as bubble condition, - * Trigger bubble recovery - */ - if (dev_data.is_applied && - link->initial_sync_req != slot->req_id) { - CAM_ERR(CAM_CRM, - "Slave link %x req %lld is in applied state, triggering bubble recovery", - link->sync_link[i]->link_hdl, - (sync_slot->req_id - - link->sync_link[i]->max_delay)); - rc = cam_req_mgr_send_to_bubble(link, - (sync_slot->req_id - - link->sync_link[i]->max_delay)); - link->sync_link_sof_skip = true; - CAM_DBG(CAM_CRM, - "Master sof %lld slave sof %lld", - link->sof_timestamp, - dev_data.timestamp); - return rc; - } - - /* Checking if the initial request - * difference is maintained - */ - req_diff = link->initial_sync_req - - link->sync_link[i]->initial_sync_req; - - if (!link->sync_link_sof_skip && - req_diff != - (slot->req_id - sync_slot->req_id)) { - struct cam_req_mgr_dump_link_data - dump_info; - - CAM_DBG(CAM_CRM, - "Req diff %lld Master link %x req %lld slave link %x req %lld", - req_diff, - link->link_hdl, - slot->req_id, - link->sync_link[i]->link_hdl, - sync_slot->req_id); - - dump_info.m_link = link; - dump_info.s_link = link->sync_link[i]; - dump_info.dev_data = dev_data; - dump_info.s_req_id = sync_slot->req_id; - dump_info.m_req_id = slot->req_id; - cam_req_mgr_dump_link_info(&dump_info); - return rc; - } - } - } - } - - if (link->bubble_skip) { - link->bubble_skip--; - if (link->bubble_skip == 0) - link->sync_link_sof_skip = false; - goto slave; - } - - - if (trigger == CAM_TRIGGER_POINT_SOF && - slot->real_sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - int32_t slot_rd_idx; - - slot_rd_idx = link->req.in_q->rd_idx; - slot = &link->req.in_q->slot[slot_rd_idx]; - CAM_DBG(CAM_CRM, - "link %x idx %d req %lld state %d slot idx %d", - link->link_hdl, slot->idx, - slot->req_id, slot->status, slot_rd_idx); - if (slot->status == CRM_SLOT_STATUS_REQ_APPLIED) { - 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 row; - } - __cam_req_mgr_inc_idx( - &slot_rd_idx, 1, - link->req.in_q->num_slots); - } -row: - slot = &link->req.in_q->slot[slot_rd_idx]; - CAM_DBG(CAM_CRM, - "link %x idx %d req %lld state %d slot idx %d", - link->link_hdl, slot->idx, - slot->req_id, slot->status, slot_rd_idx); - - CAM_DBG(CAM_ISP, - "Start sync cond link %x modified sync req %lld enter", - slot->req_id, link->link_hdl); - - for (i = 0; i < link->num_sync_link; i++) { - int32_t sync_req_idx; - - //Checking if need to skip apply for this epoch - if (link->sync_link[i]->skip_sync_apply) { - CAM_INFO(CAM_ISP, - "Skipping apply on link %x as applied failed on other link %x", - link->link_hdl, - link->sync_link[i]->link_hdl); - link->sync_link[i]->skip_sync_apply = false; - return 0; - } - - //Check if other link is streaming or not - cam_req_mgr_get_device_info( - link->sync_link[i], &dev_data); - if (!dev_data.timestamp) { - CAM_INFO(CAM_ISP, "Link %x not streaming", - link->sync_link[i]->link_hdl); - return 0; - } - - sync_in_q = link->sync_link[i]->req.in_q; - if (slot->req_id == -1) { - sync_req_idx = sync_in_q->rd_idx; - } else { - sync_req_idx = __cam_req_mgr_find_slot_for_req( - link->sync_link[i]->req.in_q, slot->req_id); - } - - if (sync_req_idx == -1) { - CAM_DBG(CAM_CRM, - "Request %lld not in in_q link %x", - slot->req_id, - link->sync_link[i]->link_hdl); - if (slot->sync_mode != - CAM_REQ_MGR_SYNC_MODE_SYNC) { - CAM_DBG(CAM_CRM, - "slot not in sync mode %lld"); - __cam_req_mgr_inc_idx( - &sync_req_idx, 1, - link->req.in_q->num_slots); - goto cl; - } - return 0; - } - - __cam_req_mgr_dec_idx( - &sync_req_idx, 1, - link->sync_link[i]->req.in_q->num_slots); -cl: - sync_slot = &sync_in_q->slot[sync_req_idx]; - - //Checking if corresponding req is applied in other link or not - if (link->sync_link[i]->modified_init_sync_req != -1 && - sync_slot->req_id != -1 && - (link->sync_link[i]->modified_init_sync_req != - sync_slot->req_id) && - (link->sync_link[i]->modified_init_sync_req < - sync_slot->req_id) && - (sync_slot->status != - CRM_SLOT_STATUS_REQ_APPLIED)) { - CAM_ERR(CAM_ISP, - "ERROR Req %lld on link %x not applied", - sync_slot->req_id, - link->sync_link[i]->link_hdl); - return 0; - } - - CAM_DBG(CAM_ISP, - "Link %x modified sync req %lld enter state %d", - link->sync_link[i]->link_hdl, - sync_slot->req_id, sync_slot->status); - - __cam_req_mgr_inc_idx( - &sync_req_idx, 1, - link->sync_link[i]->req.in_q->num_slots); - - sync_slot = &sync_in_q->slot[sync_req_idx]; - - CAM_DBG(CAM_CRM, - "Check Req:%lld state %d link: %x, rc=%d", - sync_slot->req_id, sync_slot->status, - link->sync_link[i]->link_hdl, rc); - - if (sync_slot->status != CRM_SLOT_STATUS_REQ_APPLIED) { - rc = __cam_req_mgr_check_next_req_slot( - link->sync_link[i]); - if (rc) { - CAM_DBG(CAM_REQ, - "No pending req to apply to lower pd devices"); - rc = 0; - goto low; - } - rc = __cam_req_mgr_check_link_is_ready( - link->sync_link[i], sync_req_idx, true); - if (rc) { - CAM_DBG(CAM_CRM, - "Req:%lld not ready on link: %x, rc=%d", - sync_slot->req_id, - link->sync_link[i]->link_hdl, - rc); - link->skip_sync_apply = true; - return 0; - } - } -low: - CAM_DBG(CAM_ISP, - "End sync cond Link %x modified sync req %lld enter", - link->sync_link[i]->link_hdl, - sync_slot->req_id); - } - - rc = __cam_req_mgr_check_link_is_ready( - link, slot_rd_idx, true); - if (rc) { - CAM_DBG(CAM_CRM, - "M Req:%lld not ready on link: %x, rc=%d", - slot->req_id, link->link_hdl, rc); - link->skip_sync_apply = true; - return 0; - } - } - task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task frame %lld", @@ -3919,69 +3491,6 @@ low: task->process_cb = &cam_req_mgr_process_trigger; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); -slave: - - /* If sync mode is on and master epoch then enqueue workqueue to apply - * request for all sync link of master. - */ - - if (trigger == CAM_TRIGGER_POINT_SOF && - ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC || - (tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC && - (link->initial_sync_req != -1))) && - link->is_master && - tmp_slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC)) { - - CAM_DBG(CAM_CRM, - "In sync mode req %lld tmp mode % real mode %d sync mode %d link %x ", - slot->req_id, tmp_slot->sync_mode, - tmp_slot->real_sync_mode, - slot->sync_mode, link->link_hdl); - - dev_name = __cam_req_mgr_dev_handle_to_name( - trigger_data->dev_hdl, link); - - for (i = 0; i < link->num_sync_link; i++) { - - task = cam_req_mgr_workq_get_task( - link->sync_link[i]->workq); - if (!task) { - CAM_ERR(CAM_CRM, "No empty task frame %lld", - trigger_data->frame_id); - rc = -EBUSY; - goto end; - } - - sync_dev_hdl = cam_req_mgr_get_dev_hdl(dev_name, - link->sync_link[i]); - - if (sync_dev_hdl == -1) { - CAM_ERR(CAM_CRM, "Sync dev hdl is null"); - goto end; - } - CAM_DBG(CAM_CRM, "Sync link 0x%x sync dev hdl %x", - link->sync_link[i]->link_hdl, sync_dev_hdl); - - cam_req_mgr_get_device_info( - link->sync_link[i], &dev_data); - - task_data = (struct crm_task_payload *)task->payload; - task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF; - notify_trigger = (struct cam_req_mgr_trigger_notify *) - &task_data->u; - notify_trigger->frame_id = dev_data.frame_id; - notify_trigger->link_hdl = link->sync_link[i]->link_hdl; - notify_trigger->dev_hdl = sync_dev_hdl; - notify_trigger->trigger = trigger_data->trigger; - notify_trigger->req_id = trigger_data->req_id; - notify_trigger->sof_timestamp_val = - trigger_data->sof_timestamp_val; - task->process_cb = &cam_req_mgr_process_trigger; - rc = cam_req_mgr_workq_enqueue_task(task, - link->sync_link[i], CRM_TASK_PRIORITY_0); - } - } - end: return rc; } @@ -4326,8 +3835,6 @@ int cam_req_mgr_destroy_session( __cam_req_mgr_free_link(link); } } - for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) - clear_bit(i, g_crm_core_dev->bitmap); list_del(&cam_session->entry); mutex_unlock(&cam_session->lock); mutex_destroy(&cam_session->lock); @@ -4682,66 +4189,11 @@ end: return rc; } -/** - * __cam_req_mgr_set_master_link() - * - * @brief : Select master link based on the activate sequence - * - * @link : pointer to array of links - * @num_of_links : number of links to be sync - * - * @return : void - * - */ -static void __cam_req_mgr_set_master_link( - struct cam_req_mgr_core_link **link, - int32_t num_of_links) -{ - int i = 0, j = 0, k = 0; - int idx = -1; - - idx = find_first_bit(g_crm_core_dev->bitmap, - MAXIMUM_LINKS_PER_SESSION); - - for (i = 0; i < num_of_links; i++) { - - CAM_DBG(CAM_CRM, "idx %d, link%d 0x%x active seq %d", - idx, i, link[i]->link_hdl, - link[i]->activate_seq); - - if (link[i]->activate_seq == idx) { - - link[i]->is_master = true; - CAM_DBG(CAM_CRM, "Master link 0x%x num of links %d ", - link[i]->link_hdl, num_of_links); - - for (j = 0, k = 0; j < num_of_links; j++) { - if (link[i]->link_hdl != - link[j]->link_hdl) { - - link[i]->sync_link[k] = link[j]; - link[i]->num_sync_link++; - - link[j]->sync_link[0] = link[i]; - link[j]->num_sync_link = 1; - link[j]->is_master = false; - - k++; - } - } - } - - link[i]->initial_skip = - g_crm_core_dev->max_delay - link[i]->max_delay; - CAM_DBG(CAM_CRM, "link %x initial skip %d", - link[i]->link_hdl, link[i]->initial_skip); - } -} - int cam_req_mgr_sync_config( struct cam_req_mgr_sync_mode *sync_info) { - int i, j, rc = 0; + int i, j, rc = 0; + int sync_idx = 0; struct cam_req_mgr_core_session *cam_session; struct cam_req_mgr_core_link *link[MAX_LINKS_PER_SESSION]; @@ -4763,12 +4215,10 @@ int cam_req_mgr_sync_config( return -EINVAL; } - for (i = 0; i < sync_info->num_links; i++) { - if (!sync_info->link_hdls[i]) { - CAM_WARN(CAM_CRM, "Invalid link handles 0x%x", - sync_info->link_hdls[i]); - 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]); + return -EINVAL; } mutex_lock(&g_crm_core_dev->crm_lock); @@ -4784,56 +4234,60 @@ int cam_req_mgr_sync_config( mutex_lock(&cam_session->lock); for (i = 0; i < sync_info->num_links; i++) { + + if (!sync_info->link_hdls[i]) { + CAM_ERR(CAM_CRM, "link handle %d is null", i); + rc = -EINVAL; + goto done; + } + link[i] = cam_get_device_priv(sync_info->link_hdls[i]); if (!link[i]) { CAM_ERR(CAM_CRM, "link%d NULL pointer", i); rc = -EINVAL; goto done; } - CAM_DBG(CAM_CRM, "Link hdl %x sync mode %d", - link[i]->link_hdl, - sync_info->sync_mode); link[i]->sync_link_sof_skip = false; - link[i]->is_master = false; - link[i]->in_msync_mode = false; link[i]->initial_sync_req = -1; - link[i]->num_sync_link = 0; - link[i]->bubble_skip = 0; - link[i]->sync_frame_id = 0; - link[i]->is_sync_req = true; - link[i]->modified_init_sync_req = -1; + link[i]->num_sync_links = 0; for (j = 0; j < sync_info->num_links-1; j++) link[i]->sync_link[j] = NULL; - - g_crm_core_dev->max_delay = CAM_PIPELINE_DELAY_0; - - if (g_crm_core_dev->max_delay < link[i]->max_delay) - g_crm_core_dev->max_delay = link[i]->max_delay; } if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { - __cam_req_mgr_set_master_link(link, sync_info->num_links); - - } else { for (i = 0; i < sync_info->num_links; i++) { - /* - * Reset below info after the mode is configured - * to NO-SYNC mode since they may be overridden - * if the sync config is invoked after SOF comes. - */ - link[i]->initial_skip = 0; + j = 0; + sync_idx = 0; + CAM_DBG(CAM_REQ, "link %x adds sync link:", + link[i]->link_hdl); + while (j < sync_info->num_links) { + if (i != j) { + link[i]->sync_link[sync_idx++] = + link[j]; + link[i]->num_sync_links++; + CAM_DBG(CAM_REQ, "sync_link[%d] : %x", + sync_idx-1, link[j]->link_hdl); + } + j++; + } + link[i]->initial_skip = true; link[i]->sof_timestamp = 0; - link[i]->num_sync_link = 0; - link[i]->initial_sync_req = -1; - link[i]->modified_init_sync_req = -1; + } + } else { + for (j = 0; j < sync_info->num_links; j++) { + link[j]->initial_skip = true; + link[j]->sof_timestamp = 0; } } cam_session->sync_mode = sync_info->sync_mode; + CAM_DBG(CAM_REQ, + "Sync config completed on %d links with sync_mode %d", + sync_info->num_links, sync_info->sync_mode); done: mutex_unlock(&cam_session->lock); @@ -4911,13 +4365,13 @@ end: int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) { - int rc = 0, i, j; - struct cam_req_mgr_core_link *link = NULL; - struct cam_req_mgr_connected_device *dev = NULL; - struct cam_req_mgr_link_evt_data evt_data; - int init_timeout = 0; - long idx; - bool bit; + int rc = 0; + int i, j; + struct cam_req_mgr_core_link *link = NULL; + + struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_link_evt_data evt_data; + int init_timeout = 0; if (!control) { CAM_ERR(CAM_CRM, "Control command is NULL"); @@ -4948,22 +4402,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) { spin_lock_bh(&link->link_state_spin_lock); link->state = CAM_CRM_LINK_STATE_READY; - do { - idx = find_first_zero_bit( - g_crm_core_dev->bitmap, - MAXIMUM_LINKS_PER_SESSION); - if (idx >= MAXIMUM_LINKS_PER_SESSION) { - CAM_ERR(CAM_SYNC, - "Error: Unable to allocate link bit"); - rc = -ENOMEM; - break; - } - bit = test_and_set_bit( - idx, g_crm_core_dev->bitmap); - } while (bit); - link->activate_seq = idx; - CAM_DBG(CAM_CRM, "link hdl 0x%x activate idx %d", - link->link_hdl, link->activate_seq); spin_unlock_bh(&link->link_state_spin_lock); if (control->init_timeout[i]) link->skip_init_frame = true; @@ -5009,8 +4447,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->state = CAM_CRM_LINK_STATE_IDLE; link->skip_init_frame = false; crm_timer_exit(&link->watchdog); - clear_bit(link->activate_seq, g_crm_core_dev->bitmap); - link->activate_seq = -1; spin_unlock_bh(&link->link_state_spin_lock); CAM_DBG(CAM_CRM, "De-activate link: 0x%x", link->link_hdl); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 1bbc47f71ff6..6e6415c85fc0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -263,8 +263,7 @@ struct cam_req_mgr_req_tbl { * - members updated due to external events * @recover : if user enabled recovery for this request. * @req_id : mask tracking which all devices have request ready - * @sync_mode : Modified sync mode in which req id in this slot has to applied - * @real_sync_mode : Actual sync mode in which req id in this slot has to applied + * @sync_mode : Sync mode in which req id in this slot has to applied * @additional_timeout : Adjusted watchdog timeout value associated with * this request */ @@ -275,7 +274,6 @@ struct cam_req_mgr_slot { int32_t recover; int64_t req_id; int32_t sync_mode; - int32_t real_sync_mode; int32_t additional_timeout; }; @@ -357,7 +355,7 @@ struct cam_req_mgr_connected_device { * @lock : mutex lock to guard link data operations * @link_state_spin_lock : spin lock to protect link state variable * @sync_link : array of pointer to the sync link for synchronization - * @num_sync_link : total number of sync links + * @num_sync_links : num of links sync associated with this link * @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. @@ -367,14 +365,11 @@ struct cam_req_mgr_connected_device { * @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 initial req need to skip for - * diff pd - * @is_sync_req : flag used for deciding sync and non-sync + * @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 - * @modified_init_sync_req : Modified initial req which is required to sync - * with the other link * @retry_cnt : Counter that tracks number of attempts to apply * the same req * @is_shutdown : Flag to indicate if link needs to be disconnected @@ -389,10 +384,6 @@ struct cam_req_mgr_connected_device { * case of long exposure use case * @last_sof_trigger_jiffies : Record the jiffies of last sof trigger jiffies * @wq_congestion : Indicates if WQ congestion is detected or not - * @activate_seq : sequence in which link is activated - * @frame_id : current frame id - * @sync_frame_id : current frame id of sync link - * @bubble_skip : req to skip on bubble */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -408,22 +399,19 @@ struct cam_req_mgr_core_link { void *parent; struct mutex lock; spinlock_t link_state_spin_lock; - struct cam_req_mgr_core_link *sync_link[ - MAXIMUM_LINKS_PER_SESSION]; - int32_t num_sync_link; + struct cam_req_mgr_core_link + *sync_link[MAXIMUM_LINKS_PER_SESSION - 1]; + int32_t num_sync_links; bool sync_link_sof_skip; int32_t open_req_cnt; uint32_t last_flush_id; atomic_t is_used; bool is_master; - uint32_t initial_skip; - bool is_sync_req; + bool initial_skip; bool in_msync_mode; int64_t initial_sync_req; - int64_t modified_init_sync_req; uint32_t retry_cnt; bool is_shutdown; - uint64_t sof_boottime; uint64_t sof_timestamp; uint64_t prev_sof_timestamp; bool dual_trigger; @@ -432,11 +420,6 @@ struct cam_req_mgr_core_link { bool skip_init_frame; uint64_t last_sof_trigger_jiffies; bool wq_congestion; - int32_t activate_seq; - uint64_t frame_id; - uint64_t sync_frame_id; - int32_t bubble_skip; - bool skip_sync_apply; }; /** @@ -470,33 +453,11 @@ struct cam_req_mgr_core_session { * @session_head : list head holding sessions * @crm_lock : mutex lock to protect session creation & destruction * @recovery_on_apply_fail : Recovery on apply failure using debugfs. - * @bitmap : bitmap to store index of link - * @max_delay : max pipeline delay in a session */ struct cam_req_mgr_core_device { struct list_head session_head; struct mutex crm_lock; bool recovery_on_apply_fail; - DECLARE_BITMAP(bitmap, MAXIMUM_LINKS_PER_SESSION); - uint32_t max_delay; -}; - -/** - * struct cam_req_mgr_dump_link_data - * - Dump data - * @m_link : master link handle - * @s_link : slave link handle - * @m_req_id : master req id - * @s_req_id : slave req id - * @dev_info : current timing data of slave link - * - */ -struct cam_req_mgr_dump_link_data { - struct cam_req_mgr_core_link *m_link; - struct cam_req_mgr_core_link *s_link; - uint64_t m_req_id; - uint64_t s_req_id; - struct cam_req_mgr_dev_info dev_data; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index e8e4f941a39c..b6807ed4a7f0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -22,7 +22,6 @@ struct cam_req_mgr_apply_request; struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; struct cam_req_mgr_dump_info; -struct cam_req_mgr_request_change_state; /* Request Manager -- camera device driver interface */ /** @@ -34,9 +33,8 @@ struct cam_req_mgr_request_change_state; * userspace * @cam_req_mgr_notify_timer : start the timer */ -typedef int (*cam_req_mgr_notify_trigger)( - struct cam_req_mgr_trigger_notify *); -typedef bool (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); +typedef int (*cam_req_mgr_notify_trigger)(struct cam_req_mgr_trigger_notify *); +typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *); typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *); typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); @@ -50,9 +48,8 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); * @cam_req_mgr_notify_frame_skip: CRM asks device to apply setting for * frame skip * @cam_req_mgr_flush_req : Flush or cancel request - * @cam_req_mgr_process_evt : generic events + * cam_req_mgr_process_evt : generic events * @cam_req_mgr_dump_req : dump request - * @cam_req_mgr_change_state : CRM asks device to change its state */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); @@ -62,8 +59,6 @@ typedef int (*cam_req_mgr_notify_frame_skip)( typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); -typedef int (*cam_req_mgr_change_state)( - struct cam_req_mgr_request_change_state *); /** * @brief : cam_req_mgr_crm_cb - func table @@ -92,17 +87,15 @@ struct cam_req_mgr_crm_cb { * @flush_req : payload to flush request * @process_evt : payload to generic event * @dump_req : payload to dump request - * @change_state : payload to change state */ struct cam_req_mgr_kmd_ops { - cam_req_mgr_get_dev_info get_dev_info; - cam_req_mgr_link_setup link_setup; - cam_req_mgr_apply_req apply_req; + cam_req_mgr_get_dev_info get_dev_info; + cam_req_mgr_link_setup link_setup; + cam_req_mgr_apply_req apply_req; cam_req_mgr_notify_frame_skip notify_frame_skip; - cam_req_mgr_flush_req flush_req; - cam_req_mgr_process_evt process_evt; - cam_req_mgr_dump_req dump_req; - cam_req_mgr_change_state change_state; + cam_req_mgr_flush_req flush_req; + cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; }; /** @@ -223,7 +216,6 @@ enum cam_req_mgr_link_evt_type { * @trigger : trigger point of this notification, CRM will send apply * only to the devices which subscribe to this point. * @sof_timestamp_val: Captured time stamp value at sof hw event - * @sof_boottime : Captured boot time stamp value at sof hw event * @req_id : req id which returned buf_done * @trigger_id: ID to differentiate between the trigger devices */ @@ -233,7 +225,6 @@ struct cam_req_mgr_trigger_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; - uint64_t sof_boottime; uint64_t req_id; int32_t trigger_id; }; @@ -258,8 +249,6 @@ struct cam_req_mgr_timer_notify { * @frame_id : frame id for internal tracking * @trigger : trigger point of this notification, CRM will send apply * @sof_timestamp_val : Captured time stamp value at sof hw event - * @sof_boottime_val : Captured boottime stamp value at sof hw event - * @need_recovery : flag to check if recovery is needed * @error : what error device hit while processing this req */ struct cam_req_mgr_error_notify { @@ -269,8 +258,6 @@ struct cam_req_mgr_error_notify { int64_t frame_id; uint32_t trigger; uint64_t sof_timestamp_val; - uint64_t sof_boottime_val; - bool need_recovery; enum cam_req_mgr_device_error error; }; @@ -315,7 +302,6 @@ struct cam_req_mgr_notify_stop { * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client * @trigger_on : This device provides trigger - * @sof_ts_cb : callback to real time drivers */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -324,7 +310,6 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; - int32_t (*sof_ts_cb)(int32_t dev_hdl, void *data); }; /** @@ -423,37 +408,4 @@ struct cam_req_mgr_dump_info { int32_t link_hdl; int32_t dev_hdl; }; - -/** - * struct cam_req_mgr_dev_info - * @link_hdl : link identifier - * @state : Current substate for the activated state. - * @timestamp : time stamp for the sof event - * @boot_time : boot time stamp for the sof event - * @frame_id : frame id - * @is_applied : if ISP is in applied state - * - */ -struct cam_req_mgr_dev_info { - int32_t link_hdl; - uint32_t state; - uint64_t timestamp; - uint64_t boot_time; - uint64_t frame_id; - bool is_applied; -}; - -/** - * struct cam_req_mgr_request_change_state - * @link_hdl : link identifier - * @dev_hdl : device handle or identifier - * @req_id : request id - * - */ -struct cam_req_mgr_request_change_state { - int32_t link_hdl; - int32_t dev_hdl; - uint64_t req_id; -}; - #endif diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index c9c2906ce56c..9c0d7abd043d 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -410,7 +410,6 @@ int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info) strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name)); info->p_delay = 1; info->trigger = CAM_TRIGGER_POINT_SOF; - info->sof_ts_cb = NULL; return 0; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 2d71dc8c00d2..8cda6c3831c8 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1785,8 +1785,6 @@ int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info) strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name)); info->p_delay = CAM_FLASH_PIPELINE_DELAY; info->trigger = CAM_TRIGGER_POINT_SOF; - info->sof_ts_cb = NULL; - return 0; } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 19dbffc4a2bc..32b05eadfc64 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1129,7 +1129,6 @@ int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info) else info->p_delay = 2; info->trigger = CAM_TRIGGER_POINT_SOF; - info->sof_ts_cb = NULL; return rc; } From daefdfbe1dcfd922c51c6a86d1a7b1c70da71b27 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Fri, 2 Apr 2021 12:28:33 +0530 Subject: [PATCH 730/790] msm: camera: ife: pagefault_ops access protected with mutex_lock Pagefault_ops is protected by the mutex_lock to avoid the list corruption by concurrent access by flush calls. CRs-Fixed: 2904307 Change-Id: Ia6519a382ace7b89b6bd59a2dacfeca3c31e2705 Signed-off-by: Tejas Prajapati --- drivers/cam_core/cam_context.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index e07cac74ab9b..aa6a7f3050ba 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -324,6 +324,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, return -EINVAL; } + mutex_lock(&ctx->ctx_mutex); if ((ctx->state > CAM_CTX_AVAILABLE) && (ctx->state < CAM_CTX_STATE_MAX)) { if (ctx->state_machine[ctx->state].pagefault_ops) { @@ -334,6 +335,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, ctx->dev_hdl, ctx->state); } } + mutex_unlock(&ctx->ctx_mutex); return rc; } From d3c7cff028bb770d1f728aa1769eee624017635d Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 1 Apr 2021 14:36:58 +0530 Subject: [PATCH 731/790] msm: camera: cpas: Change to set OT value to 8 for RT block This change is set the OT values for RT client of Camonc to 8 for Yupik camera. CRs-Fixed: 2924987 Change-Id: Icb7f30c23f5899558a41308fe313d46fd8d992a3 Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 63 ++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 8e41284604f6..9dc47566bb37 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -289,6 +289,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4808, /* IFE01234_RDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4820, /* IFE01234_RDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4824, /* IFE01234_RDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IFE01_NRDI_WRITE, @@ -343,6 +364,27 @@ static struct cam_camnoc_specific .offset = 0x3B88, /* IFE01_NRDI_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4708, /* IFE01_NRDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4720, /* IFE01_NRDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4724, /* IFE01_NRDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IFE2_NRDI_WRITE, @@ -397,6 +439,27 @@ static struct cam_camnoc_specific .offset = 0x5588, /* IFE2_NRDI_ENCCTL_LOW */ .value = 0, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5188, /* IFE2_NRDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x51A0, /* IFE2_NRDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x51A4, /* IFE2_NRDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ, From 2ca3aa523b0e477d22f9dca75cc6fb640a916171 Mon Sep 17 00:00:00 2001 From: Gaurav Jindal Date: Wed, 14 Apr 2021 14:40:01 +0530 Subject: [PATCH 732/790] msm: camera: isp: Add support for YUV422 10 bit Add support for YUV422 format 10 bit in CSID and bus drivers. CRs-Fixed: 2923254 Change-Id: Icecc367d88509b9ed08f5d0cab8c4da788886a0a Signed-off-by: Gaurav Jindal --- .../isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 9 +++++++++ .../isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 1 + include/uapi/camera/media/cam_defs.h | 5 +++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 91c9cabf0af4..1445bd098aa2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -78,6 +78,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported( case CAM_FORMAT_DPCM_14_10_14: case CAM_FORMAT_DPCM_12_10_12: case CAM_FORMAT_YUV422: + case CAM_FORMAT_YUV422_10: rc = 0; break; default: @@ -260,6 +261,10 @@ static int cam_ife_csid_get_format_rdi( *decode_fmt = 0x1; *plain_fmt = 0x0; break; + case CAM_FORMAT_YUV422_10: + *decode_fmt = 0x2; + *plain_fmt = 0x1; + break; default: rc = -EINVAL; break; @@ -342,6 +347,10 @@ static int cam_ife_csid_get_format_ipp_ppp( *decode_fmt = 0x1; *plain_fmt = 0; break; + case CAM_FORMAT_YUV422_10: + *decode_fmt = 0x2; + *plain_fmt = 0x1; + break; default: CAM_ERR(CAM_ISP, "Unsupported format %d", in_format); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index b11a9e285ff7..3796f94bfe4d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -1108,6 +1108,7 @@ static int cam_vfe_bus_ver3_acquire_wm( case CAM_FORMAT_PLAIN128: case CAM_FORMAT_PLAIN32_20: case CAM_FORMAT_YUV422: + case CAM_FORMAT_YUV422_10: rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH; rsrc_data->height = 0; rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE; diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index 8716d1e7066c..9da3a636ab0e 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_DEFS_H__ @@ -179,7 +179,8 @@ struct cam_iommu_handle { #define CAM_FORMAT_PLAIN32 47 #define CAM_FORMAT_ARGB_16 48 #define CAM_FORMAT_PLAIN16_10_LSB 49 -#define CAM_FORMAT_MAX 50 +#define CAM_FORMAT_YUV422_10 50 +#define CAM_FORMAT_MAX 51 /* Pixel Patterns */ #define PIXEL_PATTERN_RGRGRG 0x0 From 8f9d699778908bbcbcf8044e734b16231d44dece Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 15 Apr 2021 13:31:25 +0530 Subject: [PATCH 733/790] msm: camera: tfe: Drop first rdi frame in dual tfe scenario In Dual tfe scenario, tfe csid drop first frame in the ipp pix path to sync both master and slave, but rdi frame will go to tfe. this will cause issues in the camif and rdi sub sampling scenarios. in sub sampling scenarios both camif and rdi should be subsampled on same frames. To achieve this drop the rdi first frame from csid in dual tfe scenarios. Change-Id: I73e98a6d3d973af93bbe6afef7585a95578f2a2b CRs-Fixed: 2923045 Signed-off-by: Ravikishore Pampana --- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 216 +++++++++++++++++- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 12 +- 2 files changed, 219 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index a22a68e1efe0..8dd9f0f0337e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -203,6 +203,152 @@ static int cam_tfe_csid_get_format_ipp( return rc; } +static void cam_tfe_csid_enable_path_for_init_frame_drop( + struct cam_tfe_csid_hw *csid_hw, + int res_id) +{ + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg = NULL; + const struct cam_tfe_csid_rdi_reg_offset *rdi_reg = NULL; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *res; + uint32_t val; + + if (!csid_hw) { + CAM_WARN(CAM_ISP, "csid_hw cannot be NULL"); + return; + } + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res_id == CAM_TFE_CSID_PATH_RES_IPP) { + res = &csid_hw->ipp_res; + pxl_reg = csid_reg->ipp_reg; + } else if (res_id >= CAM_TFE_CSID_PATH_RES_RDI_0 && + res_id <= CAM_TFE_CSID_PATH_RES_RDI_2) { + res = &csid_hw->rdi_res[res_id]; + rdi_reg = csid_reg->rdi_reg[res_id]; + } else { + CAM_ERR(CAM_ISP, "Invalid res_id"); + return; + } + + path_data = (struct cam_tfe_csid_path_cfg *)res->res_priv; + + if (!path_data || !path_data->init_frame_drop) + return; + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) + return; + + path_data->res_sof_cnt++; + if ((path_data->res_sof_cnt + 1) < + path_data->res_sof_cnt) { + CAM_WARN(CAM_ISP, "Res %d sof count overflow %d", + res_id, path_data->res_sof_cnt); + return; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id %d SOF cnt:%d init_frame_drop:%d", + csid_hw->hw_intf->hw_idx, res_id, path_data->res_sof_cnt, + path_data->init_frame_drop); + + if ((path_data->res_sof_cnt == + path_data->init_frame_drop) && + pxl_reg) { + CAM_DBG(CAM_ISP, "Enabling pixel IPP Path"); + if (path_data->sync_mode != + CAM_ISP_HW_SYNC_SLAVE) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val |= CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + } + + if (!(csid_hw->csid_debug & + TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + val &= ~(TFE_CSID_PATH_INFO_INPUT_SOF); + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + } + } else if ((path_data->res_sof_cnt == + path_data->init_frame_drop) && rdi_reg) { + CAM_DBG(CAM_ISP, "Enabling RDI %d Path", res_id); + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_ctrl_addr); + if (!(csid_hw->csid_debug & + TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_irq_mask_addr); + val &= ~(TFE_CSID_PATH_INFO_INPUT_SOF); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_irq_mask_addr); + } + } +} + +static bool cam_tfe_csid_check_path_active(struct cam_tfe_csid_hw *csid_hw) +{ + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t i; + uint32_t path_status = 1; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + /* check the IPP path status */ + if (csid_reg->cmn_reg->num_pix) { + path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_status_addr); + CAM_DBG(CAM_ISP, "CSID:%d IPP path status:%d", + csid_hw->hw_intf->hw_idx, path_status); + /* if status is 0 then it is active */ + if (!path_status) + goto end; + } + + /* Check the RDI path status */ + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_status_addr); + CAM_DBG(CAM_ISP, "CSID:%d RDI:%d path status:%d", + csid_hw->hw_intf->hw_idx, i, path_status); + /* if status is 0 then it is active */ + if (!path_status) + goto end; + } + +end: + /* if status is 0 then path is active */ + return path_status ? false : true; +} + +static void cam_tfe_csid_reset_path_data( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + struct cam_tfe_csid_path_cfg *path_data = NULL; + + if (!csid_hw || !res) { + CAM_WARN(CAM_ISP, "csid_hw or res cannot be NULL"); + return; + } + path_data = res->res_priv; + + if (path_data) { + path_data->init_frame_drop = 0; + path_data->res_sof_cnt = 0; + } +} + static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, int32_t vc, uint32_t dt, uint32_t *cid) { @@ -249,6 +395,7 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) { struct cam_hw_soc_info *soc_info; const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_tfe_csid_path_cfg *path_data = NULL; int rc = 0; uint32_t val = 0, i; uint32_t status; @@ -348,6 +495,15 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; + path_data = (struct cam_tfe_csid_path_cfg *)csid_hw->ipp_res.res_priv; + path_data->res_sof_cnt = 0; + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + path_data = (struct cam_tfe_csid_path_cfg *) + csid_hw->rdi_res[i].res_priv; + path_data->res_sof_cnt = 0; + } + return rc; } @@ -675,6 +831,7 @@ static int cam_tfe_csid_path_reserve(struct cam_tfe_csid_hw *csid_hw, path_data->height = reserve->in_port->height; path_data->start_line = reserve->in_port->line_start; path_data->end_line = reserve->in_port->line_end; + path_data->usage_type = reserve->in_port->usage_type; csid_hw->event_cb = reserve->event_cb; csid_hw->event_cb_priv = reserve->event_cb_prv; @@ -868,7 +1025,8 @@ static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) { int rc = 0; const struct cam_tfe_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data = NULL; uint32_t i, val, clk_lvl; unsigned long flags; @@ -949,6 +1107,16 @@ static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) spin_unlock_irqrestore(&csid_hw->spin_lock, flags); cam_tasklet_start(csid_hw->tasklet); + path_data = (struct cam_tfe_csid_path_cfg *)csid_hw->ipp_res.res_priv; + path_data->res_sof_cnt = 0; + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + path_data = (struct cam_tfe_csid_path_cfg *) + csid_hw->rdi_res[i].res_priv; + path_data->res_sof_cnt = 0; + } + + return rc; disable_soc: @@ -1512,11 +1680,14 @@ static int cam_tfe_csid_enable_rdi_path( { const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; uint32_t id, val; + bool path_active = false; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; id = res->res_id; + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW || res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2 || @@ -1528,17 +1699,38 @@ static int cam_tfe_csid_enable_rdi_path( return -EINVAL; } - /* resume at frame boundary */ - cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, - soc_info->reg_map[0].mem_base + - csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + /*Drop one frame extra on RDI for dual TFE use case */ + if (path_data->usage_type == CAM_ISP_TFE_IN_RES_USAGE_DUAL) + path_data->init_frame_drop = 1; + + /*resume at frame boundary */ + if (!path_data->init_frame_drop) { + CAM_DBG(CAM_ISP, "Start RDI:%d path", id); + /* resume at frame boundary */ + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + } else { + path_active = cam_tfe_csid_check_path_active(csid_hw); + if (path_active) + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + + CAM_DBG(CAM_ISP, + "CSID:%d %s RDI:%d path frame drop %d", + csid_hw->hw_intf->hw_idx, + path_active ? "Starting" : "Not Starting", id, + path_data->init_frame_drop); + } /* Enable the required RDI interrupts */ val = TFE_CSID_PATH_INFO_RST_DONE | TFE_CSID_PATH_ERROR_FIFO_OVERFLOW | TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION | TFE_CSID_PATH_RDI_OVERFLOW_IRQ; - if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) + if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) || + (path_data->init_frame_drop && !path_active)) val |= TFE_CSID_PATH_INFO_INPUT_SOF; if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) val |= TFE_CSID_PATH_INFO_INPUT_EOF; @@ -1560,10 +1752,12 @@ static int cam_tfe_csid_disable_rdi_path( uint32_t id, val = 0; const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; id = res->res_id; + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; if ((res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2) || (!csid_reg->rdi_reg[res->res_id])) { @@ -1599,6 +1793,9 @@ static int cam_tfe_csid_disable_rdi_path( CAM_DBG(CAM_ISP, "CSID:%d res_id:%d", csid_hw->hw_intf->hw_idx, res->res_id); + path_data->init_frame_drop = 0; + path_data->res_sof_cnt = 0; + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); @@ -1964,6 +2161,8 @@ static int cam_tfe_csid_release(void *hw_priv, res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + cam_tfe_csid_reset_path_data(csid_hw, res); + end: mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; @@ -3276,6 +3475,9 @@ handle_fatal_error: complete(&csid_hw->csid_rdin_complete[i]); } + if (irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) + cam_tfe_csid_enable_path_for_init_frame_drop(csid_hw, i); + if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { if (!csid_hw->sof_irq_triggered) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index 55d71df6fada..b13d4b0473f8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_HW_H_ @@ -332,7 +332,12 @@ struct cam_tfe_csid_cid_data { * @sensor_fps Sensor fps * @sensor_hbi Sensor horizontal blanking interval * @sensor_vbi Sensor vertical blanking interval - * + * @usage_type: dual or single tfe information + * @init_frame_drop init frame drop value. In dual ife case rdi need to drop one + * more frame than pix. + * @res_sof_cnt path resource sof count value. it used for initial + * frame drop + */ struct cam_tfe_csid_path_cfg { uint32_t vc; @@ -355,6 +360,9 @@ struct cam_tfe_csid_path_cfg { uint32_t sensor_fps; uint32_t sensor_hbi; uint32_t sensor_vbi; + uint32_t usage_type; + uint32_t init_frame_drop; + uint32_t res_sof_cnt; }; /** From 4a487d963840940caf55c9de4026573bf0768eed Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Wed, 14 Apr 2021 23:44:17 +0530 Subject: [PATCH 734/790] Revert "msm: camera: req_mgr: Enhance camera v4l2 subdev shutdown sequence" This reverts commit 8564c269200e19e4785b8fde69900d17b4c88276. Change-Id: Idb956f2da5cf954c08f2f3e2af391939d859fd8a Signed-off-by: Sridhar Gujje --- drivers/cam_core/cam_context.c | 25 ------- drivers/cam_core/cam_context.h | 17 ----- drivers/cam_core/cam_node.c | 21 ------ drivers/cam_core/cam_node.h | 28 +------- drivers/cam_core/cam_subdev.c | 17 +---- drivers/cam_cpas/cam_cpas_intf.c | 24 +------ drivers/cam_cust/cam_custom_context.c | 18 ----- drivers/cam_cust/cam_custom_context.h | 12 ---- drivers/cam_cust/cam_custom_dev.c | 16 +---- drivers/cam_fd/cam_fd_context.c | 26 +------ drivers/cam_fd/cam_fd_context.h | 13 +--- drivers/cam_fd/cam_fd_dev.c | 21 +----- drivers/cam_icp/cam_icp_context.c | 19 +---- drivers/cam_icp/cam_icp_context.h | 8 --- drivers/cam_icp/cam_icp_subdev.c | 23 ++----- drivers/cam_isp/cam_isp_context.c | 11 --- drivers/cam_isp/cam_isp_context.h | 11 --- drivers/cam_isp/cam_isp_dev.c | 15 +--- drivers/cam_jpeg/cam_jpeg_context.c | 26 ------- drivers/cam_jpeg/cam_jpeg_context.h | 14 +--- drivers/cam_jpeg/cam_jpeg_dev.c | 16 +---- drivers/cam_lrme/cam_lrme_context.c | 19 +---- drivers/cam_lrme/cam_lrme_context.h | 14 +--- drivers/cam_lrme/cam_lrme_dev.c | 15 +--- drivers/cam_ope/cam_ope_context.c | 19 +---- drivers/cam_ope/cam_ope_context.h | 8 --- drivers/cam_ope/cam_ope_subdev.c | 16 +---- drivers/cam_req_mgr/cam_req_mgr_dev.c | 66 +----------------- drivers/cam_req_mgr/cam_req_mgr_dev.h | 6 -- drivers/cam_req_mgr/cam_req_mgr_util.c | 31 --------- drivers/cam_req_mgr/cam_req_mgr_util.h | 9 +-- drivers/cam_req_mgr/cam_subdev.h | 27 -------- .../cam_actuator/cam_actuator_dev.c | 63 +++++------------ .../cam_csiphy/cam_csiphy_dev.c | 69 +++++++------------ .../cam_eeprom/cam_eeprom_dev.c | 66 ++++++------------ .../cam_flash/cam_flash_dev.c | 58 +++++----------- .../cam_sensor_module/cam_ois/cam_ois_dev.c | 67 +++++++----------- .../cam_sensor/cam_sensor_dev.c | 59 +++++----------- 38 files changed, 152 insertions(+), 841 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index e07cac74ab9b..9492d681ea77 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -608,31 +608,6 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } -int cam_context_handle_shutdown_dev(struct cam_context *ctx, - struct cam_control *cmd, struct v4l2_subdev_fh *fh) -{ - int rc = 0; - - if (!ctx || !ctx->state_machine) { - CAM_ERR(CAM_CORE, "Context is not ready"); - return -EINVAL; - } - - if (!cmd) { - CAM_ERR(CAM_CORE, "Invalid stop device command payload"); - return -EINVAL; - } - - if (ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev) - rc = ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev( - (struct v4l2_subdev *)cmd->handle, fh); - else - CAM_WARN(CAM_CORE, "No shutdown device in dev %d, state %d", - ctx->dev_hdl, ctx->state); - - return rc; -} - int cam_context_handle_info_dump(void *context, enum cam_context_dump_id id) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 8183ef9eb4de..0ca3cccd8d87 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -9,7 +9,6 @@ #include #include #include -#include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" #include "cam_smmu_api.h" @@ -96,7 +95,6 @@ struct cam_ctx_request { * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * @dump_dev: Function pointer for dump dev - * @shutdown_dev: Function pointer for shutdown dev * */ struct cam_ctx_ioctl_ops { @@ -116,8 +114,6 @@ struct cam_ctx_ioctl_ops { int (*release_hw)(struct cam_context *ctx, void *args); int (*dump_dev)(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); - int (*shutdown_dev)(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); }; /** @@ -498,19 +494,6 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); -/** - * cam_context_handle_shutdown_dev() - * - * @brief: Handle shutdown device command - * - * @ctx: Object pointer for cam_context - * @cmd: Shutdown device command payload - * @fh: Pointer to struct v4l2_subdev_fh - * - */ -int cam_context_handle_shutdown_dev(struct cam_context *ctx, - struct cam_control *cmd, struct v4l2_subdev_fh *fh); - /** * cam_context_handle_dump_dev() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 51e77066a09b..5df221f71b6c 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -297,27 +297,6 @@ static int __cam_node_handle_stop_dev(struct cam_node *node, return rc; } -int cam_node_handle_shutdown_dev(struct cam_node *node, - struct cam_control *cmd, struct v4l2_subdev_fh *fh) -{ - struct cam_context *ctx = NULL; - int32_t dev_index = -1; - int rc = 0, ret = 0; - - while ((dev_index = cam_get_dev_handle_info(cmd->handle, - &ctx, dev_index)) < CAM_REQ_MGR_MAX_HANDLES_V2) { - ret = cam_context_handle_shutdown_dev(ctx, cmd, fh); - if (ret) { - rc = ret; - CAM_ERR(CAM_CORE, "Shutdown failure for node %s", - node->name); - continue; - } - } - - return rc; -} - static int __cam_node_handle_config_dev(struct cam_node *node, struct cam_config_dev_cmd *config) { diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h index 8b707a15246f..640798b387d6 100644 --- a/drivers/cam_core/cam_node.h +++ b/drivers/cam_core/cam_node.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_NODE_H_ @@ -100,30 +100,4 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, */ void cam_node_put_ctxt_to_free_list(struct kref *ref); -/** - * cam_get_dev_handle_info() - * - * @brief: provides the active dev index. - * - * @handle: pointer to struct v4l2_dev - * @ctx: pointer to struct cam_context - * @dev_index: dev index - * - */ -int32_t cam_get_dev_handle_info(uint64_t handle, - struct cam_context **ctx, int32_t dev_index); - -/** - * cam_node_handle_shutdown_dev() - * - * @brief: Shutdowns all the active devices. - * - * @node: pointer to struct node - * @cmd: pointer to struct cmd - * @fh: pointer to struct v4l2_subdev_fh - * - */ -int cam_node_handle_shutdown_dev(struct cam_node *node, - struct cam_control *cmd, struct v4l2_subdev_fh *fh); - #endif /* _CAM_NODE_H_ */ diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c index a0e345840084..52612951dca7 100644 --- a/drivers/cam_core/cam_subdev.c +++ b/drivers/cam_core/cam_subdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_subdev.h" @@ -45,8 +45,6 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, long rc; struct cam_node *node = (struct cam_node *) v4l2_get_subdevdata(sd); - struct v4l2_subdev_fh *fh = (struct v4l2_subdev_fh *)arg; - struct cam_control cntrl_cmd; if (!node || node->state == CAM_NODE_STATE_UNINIT) { rc = -EINVAL; @@ -58,19 +56,6 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, rc = cam_node_handle_ioctl(node, (struct cam_control *) arg); break; - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_WARN(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - - cntrl_cmd.op_code = CAM_SD_SHUTDOWN; - cntrl_cmd.handle = (uint64_t)sd; - rc = cam_node_handle_shutdown_dev(node, &cntrl_cmd, fh); - if (rc) - CAM_ERR(CAM_CORE, "shutdown device failed(rc = %d)", - rc); - break; default: CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, node->name); diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index 3c8f5dc166e2..f5bb5db85c29 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -691,7 +691,7 @@ static int cam_cpas_subdev_open(struct v4l2_subdev *sd, return 0; } -static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, +static int cam_cpas_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); @@ -702,11 +702,6 @@ static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, } mutex_lock(&cpas_intf->intf_lock); - if (cpas_intf->open_cnt <= 0) { - CAM_WARN(CAM_CPAS, "device already closed, open_cnt: %d", cpas_intf->open_cnt); - mutex_unlock(&cpas_intf->intf_lock); - return 0; - } cpas_intf->open_cnt--; CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt); mutex_unlock(&cpas_intf->intf_lock); @@ -714,19 +709,6 @@ static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, return 0; } -static int cam_cpas_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_CPAS); - - if (crm_active) { - CAM_DBG(CAM_CPAS, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return __cam_cpas_subdev_close(sd, fh); -} - static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -742,9 +724,6 @@ static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, case VIDIOC_CAM_CONTROL: rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg); break; - case CAM_SD_SHUTDOWN: - rc = __cam_cpas_subdev_close(sd, NULL); - break; default: CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); rc = -EINVAL; @@ -832,7 +811,6 @@ static int cam_cpas_subdev_register(struct platform_device *pdev) subdev->sd_flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->ent_function = CAM_CPAS_DEVICE_TYPE; - subdev->close_seq_prior = CAM_SD_CLOSE_LOW_PRIORITY; rc = cam_register_subdev(subdev); if (rc) { diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 1df9bb29dde6..134b5aa2b995 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1605,19 +1605,6 @@ static int __cam_custom_ctx_apply_default_req( return rc; } -static int __cam_custom_ctx_shutdown_dev( - struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - int rc = -EINVAL; - - if (!sd || !fh) { - CAM_ERR(CAM_CUSTOM, "Invalid input pointer"); - return rc; - } - - return cam_custom_subdev_close_internal(sd, fh); -} - /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1632,7 +1619,6 @@ static struct cam_ctx_ops .ioctl_ops = { .acquire_dev = __cam_custom_ctx_acquire_dev_in_available, - .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -1644,7 +1630,6 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev_in_acquired, .release_hw = __cam_custom_ctx_release_hw_in_top_state, - .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .link = __cam_custom_ctx_link_in_acquired, @@ -1663,7 +1648,6 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_top_state, - .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1681,7 +1665,6 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, - .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1698,7 +1681,6 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, - .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index 74c45d541610..ef7fe1f87434 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -150,16 +150,4 @@ int cam_custom_dev_context_init(struct cam_custom_context *ctx, */ int cam_custom_dev_context_deinit(struct cam_custom_context *ctx); -/** - * cam_custom_subdev_close_internal() - * - * @brief: Close function for the Custom context - * - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - * - */ -int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); - #endif /* _CAM_CUSTOM_CONTEXT_H_ */ diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index 36dde62fc51d..3c3bea4c22c0 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -58,7 +58,7 @@ static int cam_custom_subdev_open(struct v4l2_subdev *sd, return 0; } -int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, +static int cam_custom_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -86,19 +86,6 @@ end: return rc; } -static int cam_custom_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_CUSTOM); - - if (crm_active) { - CAM_DBG(CAM_CUSTOM, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_custom_subdev_close_internal(sd, fh); -} - static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { .close = cam_custom_subdev_close, .open = cam_custom_subdev_open, @@ -115,7 +102,6 @@ static int cam_custom_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; - g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME, CAM_CUSTOM_DEVICE_TYPE); diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index 0f3fa85f079e..c79f2f90e007 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -169,19 +169,6 @@ static int __cam_fd_ctx_handle_irq_in_activated(void *context, return rc; } -static int __cam_fd_shutdown_dev(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - int rc = -EINVAL; - - if (!sd || !fh) { - CAM_ERR(CAM_FD, "Invalid input pointer"); - return rc; - } - - return cam_fd_dev_close_internal(sd, fh); -} - /* top state machine */ static struct cam_ctx_ops cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -195,7 +182,6 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_fd_ctx_acquire_dev_in_available, - .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -206,25 +192,18 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_acquired, .config_dev = __cam_fd_ctx_config_dev_in_acquired, .start_dev = __cam_fd_ctx_start_dev_in_acquired, - .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = { - .shutdown_dev = __cam_fd_shutdown_dev, - }, + .ioctl_ops = { }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - { - .ioctl_ops = { - .shutdown_dev = __cam_fd_shutdown_dev, - }, - }, + {}, /* Activated */ { .ioctl_ops = { @@ -233,7 +212,6 @@ static struct cam_ctx_ops .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, - .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, diff --git a/drivers/cam_fd/cam_fd_context.h b/drivers/cam_fd/cam_fd_context.h index a57ed91d45b2..a751a04d2d67 100644 --- a/drivers/cam_fd/cam_fd_context.h +++ b/drivers/cam_fd/cam_fd_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_CONTEXT_H_ @@ -27,15 +27,4 @@ int cam_fd_context_init(struct cam_fd_context *fd_ctx, uint32_t ctx_id); int cam_fd_context_deinit(struct cam_fd_context *ctx); -/** - * cam_fd_dev_close_internal() - * - * @brief: Close function for the fd dev - * - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - */ -int cam_fd_dev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); - #endif /* _CAM_FD_CONTEXT_H_ */ diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index a58db056f6fb..bc1864edb24e 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -57,7 +57,7 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, +static int cam_fd_dev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_fd_dev *fd_dev = &g_fd_dev; @@ -69,11 +69,6 @@ static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, } mutex_lock(&fd_dev->lock); - if (fd_dev->open_cnt == 0) { - CAM_WARN(CAM_FD, "device already closed"); - mutex_unlock(&fd_dev->lock); - return 0; - } fd_dev->open_cnt--; CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); mutex_unlock(&fd_dev->lock); @@ -88,19 +83,6 @@ static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, return 0; } -static int cam_fd_dev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_FD); - - if (crm_active) { - CAM_DBG(CAM_FD, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_fd_dev_close_internal(sd, fh); -} - static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { .open = cam_fd_dev_open, .close = cam_fd_dev_close, @@ -116,7 +98,6 @@ static int cam_fd_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; - g_fd_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ rc = cam_subdev_probe(&g_fd_dev.sd, pdev, CAM_FD_DEV_NAME, diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 03ead2c3b693..57a80bcd7341 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -221,12 +221,6 @@ static int __cam_icp_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } -static int __cam_icp_shutdown_dev( - struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - return cam_icp_subdev_close_internal(sd, fh); -} - static struct cam_ctx_ops cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -239,7 +233,6 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_icp_acquire_dev_in_available, - .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -252,7 +245,6 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, - .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, @@ -266,23 +258,16 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, - .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, .pagefault_ops = cam_icp_context_dump_active_request, }, /* Flushed */ - { - .ioctl_ops = { - .shutdown_dev = __cam_icp_shutdown_dev, - }, - }, + {}, /* Activated */ { - .ioctl_ops = { - .shutdown_dev = __cam_icp_shutdown_dev, - }, + .ioctl_ops = {}, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_icp_context_dump_active_request, diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h index 9150bcf43f62..dc9018d1c229 100644 --- a/drivers/cam_icp/cam_icp_context.h +++ b/drivers/cam_icp/cam_icp_context.h @@ -39,12 +39,4 @@ int cam_icp_context_init(struct cam_icp_context *ctx, */ int cam_icp_context_deinit(struct cam_icp_context *ctx); -/** - * cam_icp_subdev_close_internal() - Close function for the icp dev - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - */ -int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); - #endif /* _CAM_ICP_CONTEXT_H_ */ diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 3288964444ef..6a12cdd3e2fc 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -98,7 +98,7 @@ end: return rc; } -int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, +static int cam_icp_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -107,8 +107,9 @@ int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_WARN(CAM_ICP, "ICP subdev is already closed"); - return 0; + CAM_DBG(CAM_ICP, "ICP subdev is already closed"); + rc = -EINVAL; + goto end; } g_icp_dev.open_cnt--; if (!node) { @@ -132,20 +133,7 @@ int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, end: mutex_unlock(&g_icp_dev.icp_lock); - return rc; -} - -static int cam_icp_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_ICP); - - if (crm_active) { - CAM_DBG(CAM_ICP, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_icp_subdev_close_internal(sd, fh); + return 0; } const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { @@ -169,7 +157,6 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.sd.pdev = pdev; g_icp_dev.sd.internal_ops = &cam_icp_subdev_internal_ops; - g_icp_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME, CAM_ICP_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f601e72d9dd2..ccf3f7a4d19f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -6004,12 +6004,6 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, return rc; } -static int __cam_isp_shutdown_dev( - struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - return cam_isp_subdev_close_internal(sd, fh); -} - /* top state machine */ static struct cam_ctx_ops cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -6023,7 +6017,6 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_isp_ctx_acquire_dev_in_available, - .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -6035,7 +6028,6 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, - .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, @@ -6055,7 +6047,6 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, - .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -6073,7 +6064,6 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_flushed, .release_hw = __cam_isp_ctx_release_hw_in_activated, - .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -6091,7 +6081,6 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, - .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 108dc096d897..c0861f07964e 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -364,16 +364,5 @@ int cam_isp_context_init(struct cam_isp_context *ctx, */ int cam_isp_context_deinit(struct cam_isp_context *ctx); -/** - * cam_isp_subdev_close_internal() - * - * @brief: Close function for the isp dev - * - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - * - */ -int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); #endif /* __CAM_ISP_CONTEXT_H__ */ diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 9409c1015c6c..98de92cb3d58 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -71,7 +71,7 @@ static int cam_isp_subdev_open(struct v4l2_subdev *sd, return 0; } -int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, +static int cam_isp_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -99,18 +99,6 @@ end: return rc; } -static int cam_isp_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_ISP); - - if (crm_active) { - CAM_DBG(CAM_ISP, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - return cam_isp_subdev_close_internal(sd, fh); -} - static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .close = cam_isp_subdev_close, .open = cam_isp_subdev_open, @@ -132,7 +120,6 @@ static int cam_isp_dev_component_bind(struct device *dev, (const char **)&compat_str); g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; - g_isp_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ if (strnstr(compat_str, "ife", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index 20dd4a02127b..93d4ade12c42 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -135,12 +135,6 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx, return rc; } -static int __cam_jpeg_shutdown_dev( - struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - return cam_jpeg_subdev_close_internal(sd, fh); -} - /* top state machine */ static struct cam_ctx_ops cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -154,7 +148,6 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available, - .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = NULL, @@ -167,30 +160,11 @@ static struct cam_ctx_ops .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired, - .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, .pagefault_ops = cam_jpeg_context_dump_active_request, }, - /* Ready */ - { - .ioctl_ops = { - .shutdown_dev = __cam_jpeg_shutdown_dev, - }, - }, - /* Flushed */ - { - .ioctl_ops = { - .shutdown_dev = __cam_jpeg_shutdown_dev, - }, - }, - /* Activated */ - { - .ioctl_ops = { - .shutdown_dev = __cam_jpeg_shutdown_dev, - }, - }, }; int cam_jpeg_context_init(struct cam_jpeg_context *ctx, diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h index d36bfb8bb175..85394047d97f 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.h +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_JPEG_CONTEXT_H_ @@ -64,16 +64,4 @@ int cam_jpeg_context_init(struct cam_jpeg_context *ctx, */ int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx); -/** - * cam_jpeg_subdev_close_internal() - * - * @brief: Close function for the jpeg dev - * - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - * - */ -int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); - #endif /* __CAM_JPEG_CONTEXT_H__ */ diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index a47476a06144..966bbb1fab06 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -56,12 +56,13 @@ static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, return 0; } -int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, +static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); + mutex_lock(&g_jpeg_dev.jpeg_mutex); if (g_jpeg_dev.open_cnt <= 0) { CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); @@ -85,18 +86,6 @@ end: return rc; } -static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_JPEG); - - if (crm_active) { - CAM_DBG(CAM_JPEG, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - return cam_jpeg_subdev_close_internal(sd, fh); -} - static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .close = cam_jpeg_subdev_close, .open = cam_jpeg_subdev_open, @@ -113,7 +102,6 @@ static int cam_jpeg_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; - g_jpeg_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, CAM_JPEG_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index 7025b384b1d2..537432f982bf 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -172,12 +172,6 @@ static int __cam_lrme_ctx_handle_irq_in_activated(void *context, return rc; } -static int __cam_lrme_shutdown_dev( - struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - return cam_lrme_dev_close_internal(sd, fh); -} - /* top state machine */ static struct cam_ctx_ops cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -191,7 +185,6 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_lrme_ctx_acquire_dev_in_available, - .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -202,25 +195,18 @@ static struct cam_ctx_ops .config_dev = __cam_lrme_ctx_config_dev_in_activated, .release_dev = __cam_lrme_ctx_release_dev_in_acquired, .start_dev = __cam_lrme_ctx_start_dev_in_acquired, - .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = { - .shutdown_dev = __cam_lrme_shutdown_dev, - }, + .ioctl_ops = {}, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - { - .ioctl_ops = { - .shutdown_dev = __cam_lrme_shutdown_dev, - }, - }, + {}, /* Activate */ { .ioctl_ops = { @@ -229,7 +215,6 @@ static struct cam_ctx_ops .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, .dump_dev = __cam_lrme_ctx_dump_dev_in_activated, - .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h index f1b5ff267f6a..bc459cce2f95 100644 --- a/drivers/cam_lrme/cam_lrme_context.h +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_LRME_CONTEXT_H_ @@ -30,16 +30,4 @@ int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, uint32_t index); int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx); -/** - * cam_lrme_dev_close_internal() - * - * @brief: Close function for the jpeg dev - * - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - * - */ -int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); - #endif /* _CAM_LRME_CONTEXT_H_ */ diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 5055444c3d8a..3735ff9370a2 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -72,7 +72,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, return 0; } -int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, +static int cam_lrme_dev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -106,18 +106,6 @@ end: return rc; } -static int cam_lrme_dev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_LRME); - - if (crm_active) { - CAM_DBG(CAM_LRME, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - return cam_lrme_dev_close_internal(sd, fh); -} - static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { .open = cam_lrme_dev_open, .close = cam_lrme_dev_close, @@ -138,7 +126,6 @@ static int cam_lrme_component_bind(struct device *dev, return -ENOMEM; } g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops; - g_lrme_dev->sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; mutex_init(&g_lrme_dev->lock); diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index c8be0da353d4..d1f39e8fce17 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -195,12 +195,6 @@ static int __cam_ope_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } -static int __cam_ope_shutdown_dev( - struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - return cam_ope_subdev_close_internal(sd, fh); -} - static struct cam_ctx_ops cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -213,7 +207,6 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_ope_acquire_dev_in_available, - .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -226,7 +219,6 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, - .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -240,23 +232,14 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, - .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, .pagefault_ops = cam_ope_context_dump_active_request, }, - /* Flushed */ - { - .ioctl_ops = { - .shutdown_dev = __cam_ope_shutdown_dev, - }, - }, /* Activated */ { - .ioctl_ops = { - .shutdown_dev = __cam_ope_shutdown_dev, - }, + .ioctl_ops = {}, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_ope_context_dump_active_request, diff --git a/drivers/cam_ope/cam_ope_context.h b/drivers/cam_ope/cam_ope_context.h index 5e6d28c3ff59..e79e0f33225d 100644 --- a/drivers/cam_ope/cam_ope_context.h +++ b/drivers/cam_ope/cam_ope_context.h @@ -41,12 +41,4 @@ int cam_ope_context_init(struct cam_ope_context *ctx, */ int cam_ope_context_deinit(struct cam_ope_context *ctx); -/** - * cam_ope_subdev_close_internal() - Close function for the icp dev - * @sd: Pointer to struct v4l2_subdev - * @fh: Pointer to struct v4l2_subdev_fh - */ -int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh); - #endif /* _CAM_OPE_CONTEXT_H_ */ diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index a04abe3bcf8c..edfdd1e75e77 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -95,7 +95,7 @@ end: return rc; } -int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, +static int cam_ope_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -134,19 +134,6 @@ end: return rc; } -static int cam_ope_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_OPE); - - if (crm_active) { - CAM_DBG(CAM_OPE, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_ope_subdev_close_internal(sd, fh); -} - const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { .open = cam_ope_subdev_open, .close = cam_ope_subdev_close, @@ -169,7 +156,6 @@ static int cam_ope_subdev_component_bind(struct device *dev, g_ope_dev.sd.pdev = pdev; g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops; - g_ope_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME, CAM_OPE_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 350c9ea171bf..6ae85e826c5e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" @@ -33,7 +32,6 @@ static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; -static struct list_head cam_req_mgr_ordered_sd_list; static struct device_attribute camera_debug_sysfs_attr = __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); @@ -124,7 +122,6 @@ static int cam_req_mgr_open(struct file *filep) spin_unlock_bh(&g_dev.cam_eventq_lock); g_dev.open_cnt++; - g_dev.read_active_dev_id_hdls = 0; rc = cam_mem_mgr_init(); if (rc) { g_dev.open_cnt--; @@ -161,7 +158,6 @@ static unsigned int cam_req_mgr_poll(struct file *f, static int cam_req_mgr_close(struct file *filep) { struct v4l2_subdev *sd; - struct cam_subdev *csd; struct v4l2_fh *vfh = filep->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); @@ -176,23 +172,18 @@ static int cam_req_mgr_close(struct file *filep) } cam_req_mgr_handle_core_shutdown(); - g_dev.shutdown_state = true; - list_for_each_entry(csd, &cam_req_mgr_ordered_sd_list, list) { - sd = &csd->sd; + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) continue; - if (sd->internal_ops) { + if (sd->internal_ops && sd->internal_ops->close) { CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", sd->name); - v4l2_subdev_call(sd, core, ioctl, - CAM_SD_SHUTDOWN, subdev_fh); + sd->internal_ops->close(sd, subdev_fh); } } g_dev.open_cnt--; - g_dev.shutdown_state = false; - g_dev.read_active_dev_id_hdls = 0; v4l2_fh_release(filep); spin_lock_bh(&g_dev.cam_eventq_lock); @@ -668,51 +659,6 @@ void cam_subdev_notify_message(u32 subdev_type, } EXPORT_SYMBOL(cam_subdev_notify_message); - -static int cam_req_mgr_ordered_list_cmp(void *priv, - struct list_head *head_1, struct list_head *head_2) -{ - struct cam_subdev *entry_1 = - list_entry(head_1, struct cam_subdev, list); - struct cam_subdev *entry_2 = - list_entry(head_2, struct cam_subdev, list); - int ret = -1; - - if (entry_1->close_seq_prior > entry_2->close_seq_prior) - return 1; - else if (entry_1->close_seq_prior < entry_2->close_seq_prior) - return ret; - else - return 0; -} - -bool cam_req_mgr_is_open(uint64_t dev_id) -{ - bool crm_status; - bool dev_id_status; - - mutex_lock(&g_dev.cam_lock); - crm_status = g_dev.open_cnt ? true : false; - - if (!g_dev.read_active_dev_id_hdls) { - g_dev.active_dev_id_hdls = cam_get_dev_handle_status(); - g_dev.read_active_dev_id_hdls++; - } - - dev_id_status = (g_dev.active_dev_id_hdls & dev_id) ? true : false; - crm_status &= dev_id_status; - mutex_unlock(&g_dev.cam_lock); - - return crm_status; -} -EXPORT_SYMBOL(cam_req_mgr_is_open); - -bool cam_req_mgr_is_shutdown(void) -{ - return g_dev.shutdown_state; -} -EXPORT_SYMBOL(cam_req_mgr_is_shutdown); - int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -741,10 +687,6 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; - list_add(&csd->list, &cam_req_mgr_ordered_sd_list); - list_sort(NULL, &cam_req_mgr_ordered_sd_list, - cam_req_mgr_ordered_list_cmp); - rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); @@ -805,7 +747,6 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto video_setup_fail; g_dev.open_cnt = 0; - g_dev.shutdown_state = false; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); mutex_init(&g_dev.dev_lock); @@ -823,7 +764,6 @@ static int cam_req_mgr_component_master_bind(struct device *dev) } g_dev.state = true; - INIT_LIST_HEAD(&cam_req_mgr_ordered_sd_list); if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index 0a55789b7c7d..d374f6cce319 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -19,9 +19,6 @@ * @cam_lock: per file handle lock * @cam_eventq: event queue * @cam_eventq_lock: lock for event queue - * @shutdown_state: shutdown state - * @active_dev_id_hdls: active dev id handles - * @read_active_dev_id_hdls: read active_dev_id_hdls status */ struct cam_req_mgr_device { struct video_device *video; @@ -33,9 +30,6 @@ struct cam_req_mgr_device { struct mutex cam_lock; struct v4l2_fh *cam_eventq; spinlock_t cam_eventq_lock; - bool shutdown_state; - uint64_t active_dev_id_hdls; - int read_active_dev_id_hdls; }; #define CAM_REQ_MGR_GET_PAYLOAD_PTR(ev, type) \ diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 00b919fcec30..02e4e53ef5d7 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -14,7 +14,6 @@ #include #include "cam_req_mgr_util.h" #include "cam_debug_util.h" -#include "cam_context.h" static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static DEFINE_SPINLOCK(hdl_tbl_lock); @@ -210,36 +209,6 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) return handle; } -int32_t cam_get_dev_handle_info(uint64_t handle, - struct cam_context **ctx, int32_t dev_index) -{ - int32_t idx; - struct v4l2_subdev *sd = (struct v4l2_subdev *)handle; - - for (idx = dev_index + 1; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) { - if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) { - *ctx = (struct cam_context *)cam_get_device_priv( - hdl_tbl->hdl[idx].hdl_value); - if ((*ctx) && !strcmp(sd->name, (*ctx)->dev_name)) - return idx; - } - } - *ctx = NULL; - return CAM_REQ_MGR_MAX_HANDLES_V2; -} - -uint64_t cam_get_dev_handle_status(void) -{ - int32_t idx; - uint64_t active_dev_hdls = 0; - - for (idx = 0; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) - if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) - active_dev_hdls |= hdl_tbl->hdl[idx].dev_id; - - return active_dev_hdls; -} - void *cam_get_device_priv(int32_t dev_hdl) { int idx; diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index 6656f1d1dad6..0d0fec1f8e01 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_UTIL_API_H_ @@ -166,11 +166,4 @@ int32_t cam_req_mgr_util_deinit(void); */ int32_t cam_req_mgr_util_free_hdls(void); -/** - * cam_get_dev_handle_status() - get dev handles status - * - * Returns dev handle status - */ -uint64_t cam_get_dev_handle_status(void); - #endif /* _CAM_REQ_MGR_UTIL_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index e37d7177c8a3..a6f6d7062c0f 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -21,13 +21,6 @@ enum cam_subdev_message_type_t { CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; -/* Enum for close sequence priority */ -enum cam_subdev_close_seq_priority { - CAM_SD_CLOSE_HIGH_PRIORITY, - CAM_SD_CLOSE_MEDIUM_PRIORITY, - CAM_SD_CLOSE_LOW_PRIORITY -}; - /** * struct cam_subdev - describes a camera sub-device * @@ -46,8 +39,6 @@ enum cam_subdev_close_seq_priority { * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. - * @list: list pointer - * @close_seq_prior: cam_subdev_close_seq_priority type * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be @@ -67,8 +58,6 @@ struct cam_subdev { struct v4l2_subdev *sd, enum cam_subdev_message_type_t msg_type, uint32_t data); - struct list_head list; - enum cam_subdev_close_seq_priority close_seq_prior; }; /** @@ -130,20 +119,4 @@ int cam_register_subdev(struct cam_subdev *sd); */ int cam_unregister_subdev(struct cam_subdev *sd); -/** - * cam_req_mgr_is_open() - * - * @brief: This common utility function returns the crm active status - * - * @dev_id: device id type - */ -bool cam_req_mgr_is_open(uint64_t dev_id); - -/** - * cam_req_mgr_is_shutdown() - * - * @brief: This common utility function returns the shutdown state - */ -bool cam_req_mgr_is_shutdown(void); - #endif /* _CAM_SUBDEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index d51dae6d37d7..96435bcd5fe6 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -10,38 +10,6 @@ #include "cam_trace.h" #include "camera_main.h" -static int cam_actuator_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_actuator_ctrl_t *a_ctrl = - v4l2_get_subdevdata(sd); - - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&(a_ctrl->actuator_mutex)); - cam_actuator_shutdown(a_ctrl); - mutex_unlock(&(a_ctrl->actuator_mutex)); - - return 0; -} - -static int cam_actuator_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); - - if (crm_active) { - CAM_INFO(CAM_ACTUATOR, - "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_actuator_subdev_close_internal(sd, fh); -} - static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -56,14 +24,6 @@ static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, CAM_ERR(CAM_ACTUATOR, "Failed for driver_cmd: %d", rc); break; - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - - rc = cam_actuator_subdev_close_internal(sd, NULL); - break; default: CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd: %u", cmd); rc = -ENOIOCTLCMD; @@ -117,6 +77,24 @@ static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, } #endif +static int cam_actuator_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + cam_actuator_shutdown(a_ctrl); + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + static struct v4l2_subdev_core_ops cam_actuator_subdev_core_ops = { .ioctl = cam_actuator_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -149,13 +127,10 @@ static int cam_actuator_init_subdev(struct cam_actuator_ctrl_t *a_ctrl) a_ctrl->v4l2_dev_str.ent_function = CAM_ACTUATOR_DEVICE_TYPE; a_ctrl->v4l2_dev_str.token = a_ctrl; - a_ctrl->v4l2_dev_str.close_seq_prior = - CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str)); if (rc) - CAM_ERR(CAM_ACTUATOR, - "Fail with cam_register_subdev rc: %d", rc); + CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); return rc; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 17216d86d038..fbe53591fc6e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -77,7 +77,29 @@ static void cam_csiphy_debug_unregister(void) root_dentry = NULL; } -static int cam_csiphy_subdev_close_internal(struct v4l2_subdev *sd, +static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + int rc = 0; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_core_cfg(csiphy_dev, arg); + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in configuring the device: %d", rc); + break; + default: + CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + +static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct csiphy_device *csiphy_dev = @@ -95,49 +117,6 @@ static int cam_csiphy_subdev_close_internal(struct v4l2_subdev *sd, return 0; } -static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); - - if (crm_active) { - CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_csiphy_subdev_close_internal(sd, fh); -} - -static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); - int rc = 0; - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_csiphy_core_cfg(csiphy_dev, arg); - if (rc) - CAM_ERR(CAM_CSIPHY, - "Failed in configuring the device: %d", rc); - break; - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - - rc = cam_csiphy_subdev_close_internal(sd, NULL); - break; - default: - CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - #ifdef CONFIG_COMPAT static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -257,8 +236,6 @@ static int cam_csiphy_component_bind(struct device *dev, cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; - new_csiphy_dev->v4l2_dev_str.close_seq_prior = - CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str)); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index cfcc166892d7..2c0f791b6f7e 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -10,7 +10,28 @@ #include "cam_debug_util.h" #include "camera_main.h" -static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd, +static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_driver_cmd(e_ctrl, arg); + if (rc) + CAM_ERR(CAM_EEPROM, + "Failed in Driver cmd: %d", rc); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + +static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_eeprom_ctrl_t *e_ctrl = @@ -28,48 +49,6 @@ static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd, return 0; } -static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); - - if (crm_active) { - CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_eeprom_subdev_close_internal(sd, fh); -} - -static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_eeprom_driver_cmd(e_ctrl, arg); - if (rc) - CAM_ERR(CAM_EEPROM, - "Failed in Driver cmd: %d", rc); - break; - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - - rc = cam_eeprom_subdev_close_internal(sd, NULL); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_i2c_info_t *i2c_info) { @@ -168,7 +147,6 @@ static int cam_eeprom_init_subdev(struct cam_eeprom_ctrl_t *e_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE; e_ctrl->v4l2_dev_str.token = e_ctrl; - e_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 8386d8d6b817..5a4655834eaa 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -236,37 +236,6 @@ static const struct of_device_id cam_flash_dt_match[] = { {} }; -static int cam_flash_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_flash_ctrl *fctrl = - v4l2_get_subdevdata(sd); - - if (!fctrl) { - CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&fctrl->flash_mutex); - cam_flash_shutdown(fctrl); - mutex_unlock(&fctrl->flash_mutex); - - return 0; -} - -static int cam_flash_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_FLASH); - - if (crm_active) { - CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_flash_subdev_close_internal(sd, fh); -} - static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -288,14 +257,6 @@ static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, "Failed in driver cmd: %d", rc); break; } - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - - rc = cam_flash_subdev_close_internal(sd, NULL); - break; default: CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); rc = -ENOIOCTLCMD; @@ -367,6 +328,24 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) return rc; } +static int cam_flash_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_flash_ctrl *fctrl = + v4l2_get_subdevdata(sd); + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = { .ioctl = cam_flash_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -396,7 +375,6 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; fctrl->v4l2_dev_str.token = fctrl; - fctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 94b6a9cd8271..b47d90225ca0 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -10,7 +10,29 @@ #include "cam_debug_util.h" #include "camera_main.h" -static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd, +static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_driver_cmd(o_ctrl, arg); + if (rc) + CAM_ERR(CAM_OIS, + "Failed with driver cmd: %d", rc); + break; + default: + CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + +static int cam_ois_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_ois_ctrl_t *o_ctrl = @@ -28,48 +50,6 @@ static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd, return 0; } -static int cam_ois_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_OIS); - - if (crm_active) { - CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_ois_subdev_close_internal(sd, fh); -} - -static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_ois_driver_cmd(o_ctrl, arg); - if (rc) - CAM_ERR(CAM_OIS, - "Failed with driver cmd: %d", rc); - break; - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - rc = cam_ois_subdev_close_internal(sd, NULL); - break; - default: - CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl, struct cam_ois_i2c_info_t *i2c_info) { @@ -164,7 +144,6 @@ static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE; o_ctrl->v4l2_dev_str.token = o_ctrl; - o_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 9c6e2f2a2060..92a5d940f339 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -9,37 +9,6 @@ #include "cam_sensor_core.h" #include "camera_main.h" -static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_sensor_ctrl_t *s_ctrl = - v4l2_get_subdevdata(sd); - - if (!s_ctrl) { - CAM_ERR(CAM_SENSOR, "s_ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&(s_ctrl->cam_sensor_mutex)); - cam_sensor_shutdown(s_ctrl); - mutex_unlock(&(s_ctrl->cam_sensor_mutex)); - - return 0; -} - -static int cam_sensor_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); - - if (crm_active) { - CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); - return 0; - } - - return cam_sensor_subdev_close_internal(sd, fh); -} - static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -54,14 +23,6 @@ static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, CAM_ERR(CAM_SENSOR, "Failed in Driver cmd: %d", rc); break; - case CAM_SD_SHUTDOWN: - if (!cam_req_mgr_is_shutdown()) { - CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); - return 0; - } - - rc = cam_sensor_subdev_close_internal(sd, NULL); - break; default: CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); rc = -ENOIOCTLCMD; @@ -70,6 +31,24 @@ static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, return rc; } +static int cam_sensor_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "s_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + cam_sensor_shutdown(s_ctrl); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + + return 0; +} + #ifdef CONFIG_COMPAT static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -143,8 +122,6 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE; s_ctrl->v4l2_dev_str.token = s_ctrl; - s_ctrl->v4l2_dev_str.close_seq_prior = - CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); if (rc) From 8570262453322571fbe8b26d3a284813735b2ef2 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 19 Apr 2021 16:38:46 +0530 Subject: [PATCH 735/790] msm: camera: isp: Reset csid error irq count on flush This change is to reset csid_error_irq_count on flush to prevent from recovery. CRs-Fixed: 2926200 Change-Id: I8568fdc679317e41c31f4aeb9cf8c3ae579d8448 Signed-off-by: Ayush Kumar --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 91c9cabf0af4..84c286ba3bfe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4232,6 +4232,8 @@ int cam_ife_csid_stop(void *hw_priv, res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; } + csid_hw->error_irq_count = 0; + CAM_DBG(CAM_ISP, "%s: Exit\n", __func__); return rc; From 0067edcd2217c7dbc6a31a0428c9d2b17796c7c2 Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Tue, 20 Apr 2021 18:20:11 +0530 Subject: [PATCH 736/790] Revert "msm: camera: csiphy: Update CSIPHY settings based recommendation" This reverts commit 89c548e862201e2163f0f869dd869de535316d1d. Change-Id: I0a979e5352aec48df946dd9cd584de6a69bde674 Signed-off-by: Sridhar Gujje --- .../include/cam_csiphy_1_2_1_hwreg.h | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 56cf75b9a866..813d978eb536 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -15,7 +15,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, - .csiphy_2ph_config_array_size = 23, + .csiphy_2ph_config_array_size = 20, .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -71,12 +71,9 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL}, - {0x0060, 0xFD, 0x00, CSIPHY_SKEW_CAL}, - {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -96,7 +93,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -118,12 +115,9 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x025C, 0x00, 0x00, CSIPHY_SKEW_CAL}, - {0x0260, 0xFD, 0x00, CSIPHY_SKEW_CAL}, - {0x0264, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -143,12 +137,9 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL}, - {0x0460, 0xFD, 0x00, CSIPHY_SKEW_CAL}, - {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -168,12 +159,9 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS}, - {0x065C, 0x00, 0x00, CSIPHY_SKEW_CAL}, - {0x0660, 0xFD, 0x00, CSIPHY_SKEW_CAL}, - {0x0664, 0x7F, 0x00, CSIPHY_SKEW_CAL}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -197,7 +185,7 @@ struct csiphy_reg_t {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -219,7 +207,7 @@ struct csiphy_reg_t {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -241,7 +229,7 @@ struct csiphy_reg_t {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -263,7 +251,7 @@ struct csiphy_reg_t {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -285,7 +273,7 @@ struct csiphy_reg_t {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, From 72c9ddcce942bf7701b5be6d6d7948d5c6d6b8a3 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 5 Apr 2021 10:21:18 +0530 Subject: [PATCH 737/790] msm: camera: isp: Check ife out res validity This change adds validity check for ife out res. If ife out res is NULL we can run into crash or issues. CRs-Fixed: 2915741 Change-Id: I8722b2a4e2634bda42f0080e00bf09050bbd6b91 Signed-off-by: Vikram Sharma --- .../isp_hw_mgr/hw_utils/cam_isp_packet_parser.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 4147efe58af0..09b0cdb0e881 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -141,6 +141,14 @@ static int cam_isp_update_dual_config( } hw_mgr_res = &res_list_isp_out[i]; + if (!hw_mgr_res) { + CAM_ERR(CAM_ISP, + "Invalid isp out resource i %d num_out_res %d", + i, dual_config->num_ports); + rc = -EINVAL; + goto end; + } + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { if (!hw_mgr_res->hw_res[j]) continue; From 0587c6ae056c293602da5590573455913c8d5a58 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 12 Apr 2021 21:08:13 +0530 Subject: [PATCH 738/790] Revert "msm: camera: req_mgr: Validate active sequence id in link control" This reverts commit 4580f024fed5cd208c1dab2470fa34dd149d5770. CRs-Fixed: 2898158 Change-Id: I29ab6ef02df0b30093c9f6a295eb74351f480a00 Signed-off-by: Ayush Kumar --- drivers/cam_core/cam_context_utils.c | 2 +- drivers/cam_core/cam_hw_mgr_intf.h | 2 +- drivers/cam_req_mgr/cam_req_mgr_core.c | 7 +------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/cam_core/cam_context_utils.c b/drivers/cam_core/cam_context_utils.c index 0abd3ac3ebff..cfef68791326 100644 --- a/drivers/cam_core/cam_context_utils.c +++ b/drivers/cam_core/cam_context_utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 359f54850ce8..2b56d21b20be 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_HW_MGR_INTF_H_ diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index d72b7dc8809b..0bd68d76fa68 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1498,7 +1498,7 @@ static int __cam_req_mgr_check_sync_req_is_ready( sync_frame_duration / 2) link->sync_link_sof_skip = true; return -EINVAL; - } else if (ready == false) { + } else if (!ready) { CAM_DBG(CAM_CRM, "Req: %lld not ready on link: %x", req_id, link->link_hdl); @@ -4447,11 +4447,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) link->state = CAM_CRM_LINK_STATE_IDLE; link->skip_init_frame = false; crm_timer_exit(&link->watchdog); - if ((link->activate_seq >= 0) && - (link->activate_seq < MAXIMUM_LINKS_PER_SESSION)) - clear_bit(link->activate_seq, g_crm_core_dev->bitmap); - - link->activate_seq = -1; spin_unlock_bh(&link->link_state_spin_lock); CAM_DBG(CAM_CRM, "De-activate link: 0x%x", link->link_hdl); From aa74199c197edcce2d1c52d254b85fb0b8d5e60d Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 1 Apr 2021 14:36:58 +0530 Subject: [PATCH 739/790] msm: camera: cpas: Change to set OT value to 8 for RT block This change is set the OT values for RT client of Camonc to 8 for Yupik camera. CRs-Fixed: 2924987 Change-Id: Icb7f30c23f5899558a41308fe313d46fd8d992a3 Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 63 ++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 8e41284604f6..9dc47566bb37 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -289,6 +289,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4808, /* IFE01234_RDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4820, /* IFE01234_RDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4824, /* IFE01234_RDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IFE01_NRDI_WRITE, @@ -343,6 +364,27 @@ static struct cam_camnoc_specific .offset = 0x3B88, /* IFE01_NRDI_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4708, /* IFE01_NRDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4720, /* IFE01_NRDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4724, /* IFE01_NRDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IFE2_NRDI_WRITE, @@ -397,6 +439,27 @@ static struct cam_camnoc_specific .offset = 0x5588, /* IFE2_NRDI_ENCCTL_LOW */ .value = 0, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5188, /* IFE2_NRDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x51A0, /* IFE2_NRDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x51A4, /* IFE2_NRDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ, From dd8b69b832c77733b7ee73c1fde2bb2ab864ea86 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 26 Apr 2021 13:44:16 +0800 Subject: [PATCH 740/790] msm: camera: isp: Update the reported_req_id correctly The request id is updated to 0 when the substate is BUBBLE, then the original request id can't be notified to UMD, since the reported_req_id is already updated to the original request id. This change updateds the reported_req_id only when the final request id is valid. CRs-Fixed: 2932602 Change-Id: Ib30f849782283c647f784cfb0deb49bee3d04287 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f7a95795744b..c6b227fdd6d3 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1863,7 +1863,6 @@ notify_only: if ((!req_isp->bubble_detected) && (req->request_id > ctx_isp->reported_req_id)) { request_id = req->request_id; - ctx_isp->reported_req_id = request_id; __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); break; @@ -1873,6 +1872,9 @@ notify_only: if (ctx_isp->substate_activated == CAM_ISP_CTX_ACTIVATED_BUBBLE) request_id = 0; + if (request_id != 0) + ctx_isp->reported_req_id = request_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); From 6f9f6f4854211a1de0997672d5e961851d6d9d19 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 26 Apr 2021 15:44:42 +0800 Subject: [PATCH 741/790] msm: camera: reqmgr: Only do self-correction at SOF Since the SOF timestamp is only updated at SOF, so we can't do self-correction at EOF. When the frames already in sync, but the req is a EOF triggered req, then the req can't be applied at SOF, but it will fail to pass self-correction checking at EOF. Then we will loop this progress, the req can't be applied anymore. CRs-Fixed: 2930497 Change-Id: I079cbd3cb9ac9541f049c5369baeee831f7444a2 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 0bd68d76fa68..c7d6e8252b02 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1339,7 +1339,8 @@ static int __cam_req_mgr_check_sync_for_mslave( static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *sync_link, - struct cam_req_mgr_slot *slot) + struct cam_req_mgr_slot *slot, + uint32_t trigger) { struct cam_req_mgr_slot *sync_rd_slot = NULL; int64_t req_id = 0, sync_req_id = 0; @@ -1513,7 +1514,8 @@ static int __cam_req_mgr_check_sync_req_is_ready( */ master_slave_diff = sync_frame_duration; do_div(master_slave_diff, 5); - if ((sync_link->sof_timestamp > 0) && + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (sync_link->sof_timestamp > 0) && (sof_timestamp_delta < master_slave_diff) && (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { @@ -1574,7 +1576,8 @@ static int __cam_req_mgr_check_multi_sync_link_ready( } if (link->max_delay == link->sync_link[i]->max_delay) { rc = __cam_req_mgr_check_sync_req_is_ready( - link, link->sync_link[i], slot); + link, link->sync_link[i], + slot, trigger); if (rc < 0) { CAM_DBG(CAM_CRM, "link %x not ready", link->link_hdl); From c4d768fad0324bee097a2015a72afb24e54ee154 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Tue, 27 Apr 2021 16:39:24 +0530 Subject: [PATCH 742/790] msm: camera: ife: Program image addr for once in RDI batch mode For RDI only batch mode use case the image address needs to be programmed only once the consecutive image address is taken from the frame increament address and image address we have provided. CRs-Fixed: 2948881 Change-Id: I94bce9522aaace00b567b023bba1cc3443d849ef Signed-off-by: Tejas Prajapati --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 3796f94bfe4d..44de3efdb383 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2954,9 +2954,8 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_client = NULL; uint32_t *reg_val_pair; - uint32_t i, j, k, size = 0; + uint32_t i, j, size = 0; uint32_t frame_inc = 0, val; - uint32_t loop_size = 0; bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; @@ -3086,41 +3085,31 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, wm_data->index, reg_val_pair[j-1]); } - if ((!bus_priv->common_data.is_lite && wm_data->index > 22) || - bus_priv->common_data.is_lite) - loop_size = wm_data->irq_subsample_period + 1; - else - loop_size = 1; - /* WM Image address */ - for (k = 0; k < loop_size; k++) { - if (wm_data->en_ubwc) { - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->image_addr, - update_buf->wm_update->image_buf[i] + - io_cfg->planes[i].meta_size + - k * frame_inc); - update_buf->wm_update->image_buf_offset[i] = - io_cfg->planes[i].meta_size; - } else if (wm_data->en_cfg & (0x3 << 16)) { - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->image_addr, - (update_buf->wm_update->image_buf[i] + - wm_data->offset + k * frame_inc)); - update_buf->wm_update->image_buf_offset[i] = - wm_data->offset; - } else { - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->image_addr, - (update_buf->wm_update->image_buf[i] + - k * frame_inc)); - update_buf->wm_update->image_buf_offset[i] = 0; - } - - CAM_DBG(CAM_ISP, "WM:%d image address 0x%X", - wm_data->index, reg_val_pair[j-1]); + if (wm_data->en_ubwc) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i] + + io_cfg->planes[i].meta_size); + update_buf->wm_update->image_buf_offset[i] = + io_cfg->planes[i].meta_size; + } else if (wm_data->en_cfg & (0x3 << 16)) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + (update_buf->wm_update->image_buf[i] + + wm_data->offset)); + update_buf->wm_update->image_buf_offset[i] = + wm_data->offset; + } else { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i]); + update_buf->wm_update->image_buf_offset[i] = 0; } + CAM_DBG(CAM_ISP, "WM:%d image address 0x%X", + wm_data->index, reg_val_pair[j-1]); + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->frame_incr, frame_inc); CAM_DBG(CAM_ISP, "WM:%d frame_inc %d", From e1f751f7606d52ab176c14529e29ee91c3f8cc1d Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 30 Apr 2021 16:25:28 +0530 Subject: [PATCH 743/790] msm: camera: ife: Update resource state in tpg start Resource state is not proper during csid stop for PHY TPG hence stop doesn't call for it. Update the correct resource state during tpg start for PHY TPG. CRs-Fixed: 2906168 Change-Id: Ib5fd05a380f6e1dbb303af23b7b0017d9f88c125 Signed-off-by: Alok Chauhan --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 1445bd098aa2..aa6f9a4c7392 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1684,6 +1684,8 @@ static int cam_ife_csid_tpg_start(struct cam_ife_csid_hw *csid_hw, CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", 0x600, val); } + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return 0; } From f6f57c8d7fa751a3228f99a6608e8fce21754ed1 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 4 May 2021 14:20:25 +0530 Subject: [PATCH 744/790] msm: camera: cpas: Add support for blair camnoc Blair has different version of CPAS version which requires camnoc interface changes and CPAS version change. This change adds the same. CRs-Fixed: 2944976 Change-Id: I700d99e52dacee9badcb2f66a7a295fb18771231 Signed-off-by: Ayush Kumar --- Makefile | 9 + config/blaircamera.conf | 17 + config/blaircameraconf.h | 10 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 9 +- drivers/cam_cpas/cpas_top/cpastop_v545_110.h | 322 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 3 +- 6 files changed, 367 insertions(+), 3 deletions(-) create mode 100644 config/blaircamera.conf create mode 100644 config/blaircameraconf.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v545_110.h diff --git a/Makefile b/Makefile index 44714b7440f5..ecbee305dbf2 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,10 @@ ifeq ($(CONFIG_ARCH_HOLI), y) include $(srctree)/techpack/camera/config/holicamera.conf endif +ifeq ($(CONFIG_ARCH_BLAIR), y) +include $(srctree)/techpack/camera/config/blaircamera.conf +endif + ifeq ($(CONFIG_ARCH_SHIMA), y) include $(srctree)/techpack/camera/config/shimacamera.conf endif @@ -55,6 +59,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/holicameraconf.h endif +ifeq ($(CONFIG_ARCH_BLAIR), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/blaircameraconf.h +endif + ifeq ($(CONFIG_ARCH_SHIMA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/shimacameraconf.h diff --git a/config/blaircamera.conf b/config/blaircamera.conf new file mode 100644 index 000000000000..be2ce67888d1 --- /dev/null +++ b/config/blaircamera.conf @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2021, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=y +$(info "SPECTRA_CAMERA IS STATIC") +else +$(info "SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_OPE=y +export CONFIG_SPECTRA_TFE=y +export CONFIG_SPECTRA_SENSOR=y +endif diff --git a/config/blaircameraconf.h b/config/blaircameraconf.h new file mode 100644 index 000000000000..816797dee642 --- /dev/null +++ b/config/blaircameraconf.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_OPE 1 +#define CONFIG_SPECTRA_TFE 1 +#define CONFIG_SPECTRA_SENSOR 1 diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 6447b3b40dc3..01a376dd51c1 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -28,6 +28,7 @@ #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" #include "cpastop_v545_100.h" +#include "cpastop_v545_110.h" #include "cpastop_v570_200.h" #include "cpastop_v680_100.h" #include "cpastop_v165_100.h" @@ -119,7 +120,7 @@ static const uint32_t cam_cpas_hw_version_map { CAM_CPAS_TITAN_545_V100, 0, - 0, + CAM_CPAS_TITAN_545_V110, 0, 0, 0, @@ -934,6 +935,10 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, camnoc_info = &cam545_cpas100_camnoc_info; qchannel_info = &cam545_cpas100_qchannel_info; break; + case CAM_CPAS_TITAN_545_V110: + camnoc_info = &cam545_cpas110_camnoc_info; + qchannel_info = &cam545_cpas110_qchannel_info; + break; case CAM_CPAS_TITAN_570_V200: camnoc_info = &cam570_cpas200_camnoc_info; qchannel_info = &cam570_cpas200_qchannel_info; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_110.h b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h new file mode 100644 index 000000000000..d8833047c250 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h @@ -0,0 +1,322 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V545_110_H_ +#define _CPASTOP_V545_110_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v545_110_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v545_110_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 = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +static struct cam_camnoc_specific + cam_cpas_v545_110_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 = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x00000003, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + .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_TFE_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x4030, + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x4034, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4040, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_TFE_2, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x5030, + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x5034, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5040, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_OPE, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x00000033, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_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, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam545_cpas110_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam545_cpas110_camnoc_info = { + .specific = &cam_cpas_v545_110_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v545_110_camnoc_specific), + .irq_sbm = &cam_cpas_v545_110_irq_sbm, + .irq_err = &cam_cpas_v545_110_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v545_110_irq_err), + .err_logger = &cam545_cpas110_err_logger_offsets, + .errata_wa_list = NULL, +}; + +static struct cam_cpas_camnoc_qchannel cam545_cpas110_qchannel_info = { + .qchannel_ctrl = 0x14, + .qchannel_status = 0x18, +}; +#endif /* _CPASTOP_V545_110_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 2b82d1f283e4..87fe72a42a64 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_API_H_ @@ -139,6 +139,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_520_V100 = 0x520100, CAM_CPAS_TITAN_545_V100 = 0x545100, + CAM_CPAS_TITAN_545_V110 = 0x545110, CAM_CPAS_TITAN_570_V200 = 0x570200, CAM_CPAS_TITAN_680_V100 = 0x680100, CAM_CPAS_TITAN_MAX From 9f18463541eee28977c4e8639fa13ae78ed37f38 Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Sun, 9 May 2021 02:16:46 +0530 Subject: [PATCH 745/790] Revert "Revert "msm: camera: req_mgr: Enhance camera v4l2 subdev shutdown sequence"" This reverts commit 4a487d963840940caf55c9de4026573bf0768eed. Change-Id: I9d052d9260581ed8155d3fbd3e5eff3a81247306 Signed-off-by: Sridhar Gujje --- drivers/cam_core/cam_context.c | 27 +++++++- drivers/cam_core/cam_context.h | 19 ++++- drivers/cam_core/cam_node.c | 23 ++++++- drivers/cam_core/cam_node.h | 26 +++++++ drivers/cam_core/cam_subdev.c | 15 ++++ drivers/cam_cpas/cam_cpas_intf.c | 24 ++++++- drivers/cam_cust/cam_custom_context.c | 18 +++++ drivers/cam_cust/cam_custom_context.h | 12 ++++ drivers/cam_cust/cam_custom_dev.c | 16 ++++- drivers/cam_fd/cam_fd_context.c | 26 ++++++- drivers/cam_fd/cam_fd_context.h | 11 +++ drivers/cam_fd/cam_fd_dev.c | 21 +++++- drivers/cam_icp/cam_icp_context.c | 19 ++++- drivers/cam_icp/cam_icp_context.h | 8 +++ drivers/cam_icp/cam_icp_subdev.c | 23 +++++-- drivers/cam_isp/cam_isp_context.c | 11 +++ drivers/cam_isp/cam_isp_context.h | 11 +++ drivers/cam_isp/cam_isp_dev.c | 15 +++- drivers/cam_jpeg/cam_jpeg_context.c | 26 +++++++ drivers/cam_jpeg/cam_jpeg_context.h | 12 ++++ drivers/cam_jpeg/cam_jpeg_dev.c | 16 ++++- drivers/cam_lrme/cam_lrme_context.c | 19 ++++- drivers/cam_lrme/cam_lrme_context.h | 12 ++++ drivers/cam_lrme/cam_lrme_dev.c | 15 +++- drivers/cam_ope/cam_ope_context.c | 19 ++++- drivers/cam_ope/cam_ope_context.h | 8 +++ drivers/cam_ope/cam_ope_subdev.c | 16 ++++- drivers/cam_req_mgr/cam_req_mgr_dev.c | 66 +++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_dev.h | 6 ++ drivers/cam_req_mgr/cam_req_mgr_util.c | 31 +++++++++ drivers/cam_req_mgr/cam_req_mgr_util.h | 7 ++ drivers/cam_req_mgr/cam_subdev.h | 27 ++++++++ .../cam_actuator/cam_actuator_dev.c | 63 ++++++++++++----- .../cam_csiphy/cam_csiphy_dev.c | 69 ++++++++++++------- .../cam_eeprom/cam_eeprom_dev.c | 66 ++++++++++++------ .../cam_flash/cam_flash_dev.c | 58 +++++++++++----- .../cam_sensor_module/cam_ois/cam_ois_dev.c | 67 +++++++++++------- .../cam_sensor/cam_sensor_dev.c | 69 ++++++++++++------- 38 files changed, 843 insertions(+), 154 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 9637a8715af6..a9a635d606f9 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -583,6 +583,31 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid stop device command payload"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev( + (struct v4l2_subdev *)cmd->handle, fh); + else + CAM_WARN(CAM_CORE, "No shutdown device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + + return rc; +} + int cam_context_handle_info_dump(void *context, enum cam_context_dump_id id) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 5be078536ff5..e55da3c3c4e7 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -9,6 +9,7 @@ #include #include #include +#include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" #include "cam_smmu_api.h" @@ -95,6 +96,7 @@ struct cam_ctx_request { * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * @dump_dev: Function pointer for dump dev + * @shutdown_dev: Function pointer for shutdown dev * */ struct cam_ctx_ioctl_ops { @@ -114,6 +116,8 @@ struct cam_ctx_ioctl_ops { int (*release_hw)(struct cam_context *ctx, void *args); int (*dump_dev)(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); + int (*shutdown_dev)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); }; /** @@ -479,6 +483,19 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +/** + * cam_context_handle_shutdown_dev() + * + * @brief: Handle shutdown device command + * + * @ctx: Object pointer for cam_context + * @cmd: Shutdown device command payload + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + /** * cam_context_handle_dump_dev() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index c3770f2df745..d27bcdd6bf0d 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -297,6 +297,27 @@ static int __cam_node_handle_stop_dev(struct cam_node *node, return rc; } +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + struct cam_context *ctx = NULL; + int32_t dev_index = -1; + int rc = 0, ret = 0; + + while ((dev_index = cam_get_dev_handle_info(cmd->handle, + &ctx, dev_index)) < CAM_REQ_MGR_MAX_HANDLES_V2) { + ret = cam_context_handle_shutdown_dev(ctx, cmd, fh); + if (ret) { + rc = ret; + CAM_ERR(CAM_CORE, "Shutdown failure for node %s", + node->name); + continue; + } + } + + return rc; +} + static int __cam_node_handle_config_dev(struct cam_node *node, struct cam_config_dev_cmd *config) { diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h index 640798b387d6..81503f28974f 100644 --- a/drivers/cam_core/cam_node.h +++ b/drivers/cam_core/cam_node.h @@ -100,4 +100,30 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, */ void cam_node_put_ctxt_to_free_list(struct kref *ref); +/** + * cam_get_dev_handle_info() + * + * @brief: provides the active dev index. + * + * @handle: pointer to struct v4l2_dev + * @ctx: pointer to struct cam_context + * @dev_index: dev index + * + */ +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index); + +/** + * cam_node_handle_shutdown_dev() + * + * @brief: Shutdowns all the active devices. + * + * @node: pointer to struct node + * @cmd: pointer to struct cmd + * @fh: pointer to struct v4l2_subdev_fh + * + */ +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + #endif /* _CAM_NODE_H_ */ diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c index 52612951dca7..cbe1b4ca3336 100644 --- a/drivers/cam_core/cam_subdev.c +++ b/drivers/cam_core/cam_subdev.c @@ -45,6 +45,8 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, long rc; struct cam_node *node = (struct cam_node *) v4l2_get_subdevdata(sd); + struct v4l2_subdev_fh *fh = (struct v4l2_subdev_fh *)arg; + struct cam_control cntrl_cmd; if (!node || node->state == CAM_NODE_STATE_UNINIT) { rc = -EINVAL; @@ -56,6 +58,19 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, rc = cam_node_handle_ioctl(node, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_WARN(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + cntrl_cmd.op_code = CAM_SD_SHUTDOWN; + cntrl_cmd.handle = (uint64_t)sd; + rc = cam_node_handle_shutdown_dev(node, &cntrl_cmd, fh); + if (rc) + CAM_ERR(CAM_CORE, "shutdown device failed(rc = %d)", + rc); + break; default: CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, node->name); diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f5bb5db85c29..3c8f5dc166e2 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -691,7 +691,7 @@ static int cam_cpas_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_cpas_subdev_close(struct v4l2_subdev *sd, +static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); @@ -702,6 +702,11 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, } mutex_lock(&cpas_intf->intf_lock); + if (cpas_intf->open_cnt <= 0) { + CAM_WARN(CAM_CPAS, "device already closed, open_cnt: %d", cpas_intf->open_cnt); + mutex_unlock(&cpas_intf->intf_lock); + return 0; + } cpas_intf->open_cnt--; CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt); mutex_unlock(&cpas_intf->intf_lock); @@ -709,6 +714,19 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_cpas_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CPAS); + + if (crm_active) { + CAM_DBG(CAM_CPAS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return __cam_cpas_subdev_close(sd, fh); +} + static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -724,6 +742,9 @@ static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, case VIDIOC_CAM_CONTROL: rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + rc = __cam_cpas_subdev_close(sd, NULL); + break; default: CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); rc = -EINVAL; @@ -811,6 +832,7 @@ static int cam_cpas_subdev_register(struct platform_device *pdev) subdev->sd_flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->ent_function = CAM_CPAS_DEVICE_TYPE; + subdev->close_seq_prior = CAM_SD_CLOSE_LOW_PRIORITY; rc = cam_register_subdev(subdev); if (rc) { diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index ca4d1d1e35d5..2b617b15f5a0 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1604,6 +1604,19 @@ static int __cam_custom_ctx_apply_default_req( return rc; } +static int __cam_custom_ctx_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_CUSTOM, "Invalid input pointer"); + return rc; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1618,6 +1631,7 @@ static struct cam_ctx_ops .ioctl_ops = { .acquire_dev = __cam_custom_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -1629,6 +1643,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev_in_acquired, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .link = __cam_custom_ctx_link_in_acquired, @@ -1647,6 +1662,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1664,6 +1680,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1680,6 +1697,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index ef7fe1f87434..74c45d541610 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -150,4 +150,16 @@ int cam_custom_dev_context_init(struct cam_custom_context *ctx, */ int cam_custom_dev_context_deinit(struct cam_custom_context *ctx); +/** + * cam_custom_subdev_close_internal() + * + * @brief: Close function for the Custom context + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_CUSTOM_CONTEXT_H_ */ diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index 3c3bea4c22c0..36dde62fc51d 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -58,7 +58,7 @@ static int cam_custom_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_custom_subdev_close(struct v4l2_subdev *sd, +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -86,6 +86,19 @@ end: return rc; } +static int cam_custom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CUSTOM); + + if (crm_active) { + CAM_DBG(CAM_CUSTOM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { .close = cam_custom_subdev_close, .open = cam_custom_subdev_open, @@ -102,6 +115,7 @@ static int cam_custom_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; + g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME, CAM_CUSTOM_DEVICE_TYPE); diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index c79f2f90e007..0f3fa85f079e 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -169,6 +169,19 @@ static int __cam_fd_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_fd_shutdown_dev(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_FD, "Invalid input pointer"); + return rc; + } + + return cam_fd_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -182,6 +195,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_fd_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -192,18 +206,25 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_acquired, .config_dev = __cam_fd_ctx_config_dev_in_acquired, .start_dev = __cam_fd_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = { }, + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, + }, /* Activated */ { .ioctl_ops = { @@ -212,6 +233,7 @@ static struct cam_ctx_ops .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, diff --git a/drivers/cam_fd/cam_fd_context.h b/drivers/cam_fd/cam_fd_context.h index a751a04d2d67..615e8d94cf6e 100644 --- a/drivers/cam_fd/cam_fd_context.h +++ b/drivers/cam_fd/cam_fd_context.h @@ -27,4 +27,15 @@ int cam_fd_context_init(struct cam_fd_context *fd_ctx, uint32_t ctx_id); int cam_fd_context_deinit(struct cam_fd_context *ctx); +/** + * cam_fd_dev_close_internal() + * + * @brief: Close function for the fd dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_fd_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_FD_CONTEXT_H_ */ diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index bc1864edb24e..a58db056f6fb 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -57,7 +57,7 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_fd_dev_close(struct v4l2_subdev *sd, +static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_fd_dev *fd_dev = &g_fd_dev; @@ -69,6 +69,11 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, } mutex_lock(&fd_dev->lock); + if (fd_dev->open_cnt == 0) { + CAM_WARN(CAM_FD, "device already closed"); + mutex_unlock(&fd_dev->lock); + return 0; + } fd_dev->open_cnt--; CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); mutex_unlock(&fd_dev->lock); @@ -83,6 +88,19 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, return 0; } +static int cam_fd_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FD); + + if (crm_active) { + CAM_DBG(CAM_FD, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_fd_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { .open = cam_fd_dev_open, .close = cam_fd_dev_close, @@ -98,6 +116,7 @@ static int cam_fd_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; + g_fd_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ rc = cam_subdev_probe(&g_fd_dev.sd, pdev, CAM_FD_DEV_NAME, diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 57a80bcd7341..03ead2c3b693 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -221,6 +221,12 @@ static int __cam_icp_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_icp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_icp_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -233,6 +239,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_icp_acquire_dev_in_available, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -245,6 +252,7 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, @@ -258,16 +266,23 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, .pagefault_ops = cam_icp_context_dump_active_request, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_icp_context_dump_active_request, diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h index dc9018d1c229..9150bcf43f62 100644 --- a/drivers/cam_icp/cam_icp_context.h +++ b/drivers/cam_icp/cam_icp_context.h @@ -39,4 +39,12 @@ int cam_icp_context_init(struct cam_icp_context *ctx, */ int cam_icp_context_deinit(struct cam_icp_context *ctx); +/** + * cam_icp_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_ICP_CONTEXT_H_ */ diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 6a12cdd3e2fc..3288964444ef 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -98,7 +98,7 @@ end: return rc; } -static int cam_icp_subdev_close(struct v4l2_subdev *sd, +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -107,9 +107,8 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_DBG(CAM_ICP, "ICP subdev is already closed"); - rc = -EINVAL; - goto end; + CAM_WARN(CAM_ICP, "ICP subdev is already closed"); + return 0; } g_icp_dev.open_cnt--; if (!node) { @@ -133,7 +132,20 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, end: mutex_unlock(&g_icp_dev.icp_lock); - return 0; + return rc; +} + +static int cam_icp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ICP); + + if (crm_active) { + CAM_DBG(CAM_ICP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_icp_subdev_close_internal(sd, fh); } const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { @@ -157,6 +169,7 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.sd.pdev = pdev; g_icp_dev.sd.internal_ops = &cam_icp_subdev_internal_ops; + g_icp_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME, CAM_ICP_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f7a95795744b..d7cdaa4aa67e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5837,6 +5837,12 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_isp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_isp_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -5850,6 +5856,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_isp_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -5861,6 +5868,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, @@ -5880,6 +5888,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5897,6 +5906,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_flushed, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5914,6 +5924,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index c0861f07964e..108dc096d897 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -364,5 +364,16 @@ int cam_isp_context_init(struct cam_isp_context *ctx, */ int cam_isp_context_deinit(struct cam_isp_context *ctx); +/** + * cam_isp_subdev_close_internal() + * + * @brief: Close function for the isp dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); #endif /* __CAM_ISP_CONTEXT_H__ */ diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 98de92cb3d58..9409c1015c6c 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -71,7 +71,7 @@ static int cam_isp_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_isp_subdev_close(struct v4l2_subdev *sd, +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -99,6 +99,18 @@ end: return rc; } +static int cam_isp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ISP); + + if (crm_active) { + CAM_DBG(CAM_ISP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_isp_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .close = cam_isp_subdev_close, .open = cam_isp_subdev_open, @@ -120,6 +132,7 @@ static int cam_isp_dev_component_bind(struct device *dev, (const char **)&compat_str); g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; + g_isp_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ if (strnstr(compat_str, "ife", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index 93d4ade12c42..20dd4a02127b 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -135,6 +135,12 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_jpeg_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_jpeg_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -148,6 +154,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = NULL, @@ -160,11 +167,30 @@ static struct cam_ctx_ops .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, .pagefault_ops = cam_jpeg_context_dump_active_request, }, + /* Ready */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Activated */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, }; int cam_jpeg_context_init(struct cam_jpeg_context *ctx, diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h index 85394047d97f..f8a8b06d09f0 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.h +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -64,4 +64,16 @@ int cam_jpeg_context_init(struct cam_jpeg_context *ctx, */ int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx); +/** + * cam_jpeg_subdev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* __CAM_JPEG_CONTEXT_H__ */ diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 966bbb1fab06..a47476a06144 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -56,13 +56,12 @@ static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); - mutex_lock(&g_jpeg_dev.jpeg_mutex); if (g_jpeg_dev.open_cnt <= 0) { CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); @@ -86,6 +85,18 @@ end: return rc; } +static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_JPEG); + + if (crm_active) { + CAM_DBG(CAM_JPEG, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_jpeg_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .close = cam_jpeg_subdev_close, .open = cam_jpeg_subdev_open, @@ -102,6 +113,7 @@ static int cam_jpeg_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; + g_jpeg_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, CAM_JPEG_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index 537432f982bf..7025b384b1d2 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -172,6 +172,12 @@ static int __cam_lrme_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_lrme_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_lrme_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -185,6 +191,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_lrme_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -195,18 +202,25 @@ static struct cam_ctx_ops .config_dev = __cam_lrme_ctx_config_dev_in_activated, .release_dev = __cam_lrme_ctx_release_dev_in_acquired, .start_dev = __cam_lrme_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, + }, /* Activate */ { .ioctl_ops = { @@ -215,6 +229,7 @@ static struct cam_ctx_ops .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, .dump_dev = __cam_lrme_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h index bc459cce2f95..34ed1693f944 100644 --- a/drivers/cam_lrme/cam_lrme_context.h +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -30,4 +30,16 @@ int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, uint32_t index); int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx); +/** + * cam_lrme_dev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_LRME_CONTEXT_H_ */ diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 3735ff9370a2..5055444c3d8a 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -72,7 +72,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_lrme_dev_close(struct v4l2_subdev *sd, +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -106,6 +106,18 @@ end: return rc; } +static int cam_lrme_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_LRME); + + if (crm_active) { + CAM_DBG(CAM_LRME, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_lrme_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { .open = cam_lrme_dev_open, .close = cam_lrme_dev_close, @@ -126,6 +138,7 @@ static int cam_lrme_component_bind(struct device *dev, return -ENOMEM; } g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops; + g_lrme_dev->sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; mutex_init(&g_lrme_dev->lock); diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index d1f39e8fce17..c8be0da353d4 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -195,6 +195,12 @@ static int __cam_ope_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_ope_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_ope_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -207,6 +213,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_ope_acquire_dev_in_available, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -219,6 +226,7 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -232,14 +240,23 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, .pagefault_ops = cam_ope_context_dump_active_request, }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_ope_context_dump_active_request, diff --git a/drivers/cam_ope/cam_ope_context.h b/drivers/cam_ope/cam_ope_context.h index e79e0f33225d..5e6d28c3ff59 100644 --- a/drivers/cam_ope/cam_ope_context.h +++ b/drivers/cam_ope/cam_ope_context.h @@ -41,4 +41,12 @@ int cam_ope_context_init(struct cam_ope_context *ctx, */ int cam_ope_context_deinit(struct cam_ope_context *ctx); +/** + * cam_ope_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_OPE_CONTEXT_H_ */ diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index edfdd1e75e77..a04abe3bcf8c 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -95,7 +95,7 @@ end: return rc; } -static int cam_ope_subdev_close(struct v4l2_subdev *sd, +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -134,6 +134,19 @@ end: return rc; } +static int cam_ope_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OPE); + + if (crm_active) { + CAM_DBG(CAM_OPE, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ope_subdev_close_internal(sd, fh); +} + const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { .open = cam_ope_subdev_open, .close = cam_ope_subdev_close, @@ -156,6 +169,7 @@ static int cam_ope_subdev_component_bind(struct device *dev, g_ope_dev.sd.pdev = pdev; g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops; + g_ope_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME, CAM_OPE_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 6ae85e826c5e..350c9ea171bf 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" @@ -32,6 +33,7 @@ static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; +static struct list_head cam_req_mgr_ordered_sd_list; static struct device_attribute camera_debug_sysfs_attr = __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); @@ -122,6 +124,7 @@ static int cam_req_mgr_open(struct file *filep) spin_unlock_bh(&g_dev.cam_eventq_lock); g_dev.open_cnt++; + g_dev.read_active_dev_id_hdls = 0; rc = cam_mem_mgr_init(); if (rc) { g_dev.open_cnt--; @@ -158,6 +161,7 @@ static unsigned int cam_req_mgr_poll(struct file *f, static int cam_req_mgr_close(struct file *filep) { struct v4l2_subdev *sd; + struct cam_subdev *csd; struct v4l2_fh *vfh = filep->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); @@ -172,18 +176,23 @@ static int cam_req_mgr_close(struct file *filep) } cam_req_mgr_handle_core_shutdown(); + g_dev.shutdown_state = true; - list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + list_for_each_entry(csd, &cam_req_mgr_ordered_sd_list, list) { + sd = &csd->sd; if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) continue; - if (sd->internal_ops && sd->internal_ops->close) { + if (sd->internal_ops) { CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", sd->name); - sd->internal_ops->close(sd, subdev_fh); + v4l2_subdev_call(sd, core, ioctl, + CAM_SD_SHUTDOWN, subdev_fh); } } g_dev.open_cnt--; + g_dev.shutdown_state = false; + g_dev.read_active_dev_id_hdls = 0; v4l2_fh_release(filep); spin_lock_bh(&g_dev.cam_eventq_lock); @@ -659,6 +668,51 @@ void cam_subdev_notify_message(u32 subdev_type, } EXPORT_SYMBOL(cam_subdev_notify_message); + +static int cam_req_mgr_ordered_list_cmp(void *priv, + struct list_head *head_1, struct list_head *head_2) +{ + struct cam_subdev *entry_1 = + list_entry(head_1, struct cam_subdev, list); + struct cam_subdev *entry_2 = + list_entry(head_2, struct cam_subdev, list); + int ret = -1; + + if (entry_1->close_seq_prior > entry_2->close_seq_prior) + return 1; + else if (entry_1->close_seq_prior < entry_2->close_seq_prior) + return ret; + else + return 0; +} + +bool cam_req_mgr_is_open(uint64_t dev_id) +{ + bool crm_status; + bool dev_id_status; + + mutex_lock(&g_dev.cam_lock); + crm_status = g_dev.open_cnt ? true : false; + + if (!g_dev.read_active_dev_id_hdls) { + g_dev.active_dev_id_hdls = cam_get_dev_handle_status(); + g_dev.read_active_dev_id_hdls++; + } + + dev_id_status = (g_dev.active_dev_id_hdls & dev_id) ? true : false; + crm_status &= dev_id_status; + mutex_unlock(&g_dev.cam_lock); + + return crm_status; +} +EXPORT_SYMBOL(cam_req_mgr_is_open); + +bool cam_req_mgr_is_shutdown(void) +{ + return g_dev.shutdown_state; +} +EXPORT_SYMBOL(cam_req_mgr_is_shutdown); + int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -687,6 +741,10 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; + list_add(&csd->list, &cam_req_mgr_ordered_sd_list); + list_sort(NULL, &cam_req_mgr_ordered_sd_list, + cam_req_mgr_ordered_list_cmp); + rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); @@ -747,6 +805,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto video_setup_fail; g_dev.open_cnt = 0; + g_dev.shutdown_state = false; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); mutex_init(&g_dev.dev_lock); @@ -764,6 +823,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) } g_dev.state = true; + INIT_LIST_HEAD(&cam_req_mgr_ordered_sd_list); if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index d374f6cce319..0a55789b7c7d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -19,6 +19,9 @@ * @cam_lock: per file handle lock * @cam_eventq: event queue * @cam_eventq_lock: lock for event queue + * @shutdown_state: shutdown state + * @active_dev_id_hdls: active dev id handles + * @read_active_dev_id_hdls: read active_dev_id_hdls status */ struct cam_req_mgr_device { struct video_device *video; @@ -30,6 +33,9 @@ struct cam_req_mgr_device { struct mutex cam_lock; struct v4l2_fh *cam_eventq; spinlock_t cam_eventq_lock; + bool shutdown_state; + uint64_t active_dev_id_hdls; + int read_active_dev_id_hdls; }; #define CAM_REQ_MGR_GET_PAYLOAD_PTR(ev, type) \ diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 02e4e53ef5d7..00b919fcec30 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -14,6 +14,7 @@ #include #include "cam_req_mgr_util.h" #include "cam_debug_util.h" +#include "cam_context.h" static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static DEFINE_SPINLOCK(hdl_tbl_lock); @@ -209,6 +210,36 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) return handle; } +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index) +{ + int32_t idx; + struct v4l2_subdev *sd = (struct v4l2_subdev *)handle; + + for (idx = dev_index + 1; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) { + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) { + *ctx = (struct cam_context *)cam_get_device_priv( + hdl_tbl->hdl[idx].hdl_value); + if ((*ctx) && !strcmp(sd->name, (*ctx)->dev_name)) + return idx; + } + } + *ctx = NULL; + return CAM_REQ_MGR_MAX_HANDLES_V2; +} + +uint64_t cam_get_dev_handle_status(void) +{ + int32_t idx; + uint64_t active_dev_hdls = 0; + + for (idx = 0; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) + active_dev_hdls |= hdl_tbl->hdl[idx].dev_id; + + return active_dev_hdls; +} + void *cam_get_device_priv(int32_t dev_hdl) { int idx; diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index 0d0fec1f8e01..fb70401306d9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -166,4 +166,11 @@ int32_t cam_req_mgr_util_deinit(void); */ int32_t cam_req_mgr_util_free_hdls(void); +/** + * cam_get_dev_handle_status() - get dev handles status + * + * Returns dev handle status + */ +uint64_t cam_get_dev_handle_status(void); + #endif /* _CAM_REQ_MGR_UTIL_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index a6f6d7062c0f..e37d7177c8a3 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -21,6 +21,13 @@ enum cam_subdev_message_type_t { CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; +/* Enum for close sequence priority */ +enum cam_subdev_close_seq_priority { + CAM_SD_CLOSE_HIGH_PRIORITY, + CAM_SD_CLOSE_MEDIUM_PRIORITY, + CAM_SD_CLOSE_LOW_PRIORITY +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -39,6 +46,8 @@ enum cam_subdev_message_type_t { * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. + * @list: list pointer + * @close_seq_prior: cam_subdev_close_seq_priority type * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be @@ -58,6 +67,8 @@ struct cam_subdev { struct v4l2_subdev *sd, enum cam_subdev_message_type_t msg_type, uint32_t data); + struct list_head list; + enum cam_subdev_close_seq_priority close_seq_prior; }; /** @@ -119,4 +130,20 @@ int cam_register_subdev(struct cam_subdev *sd); */ int cam_unregister_subdev(struct cam_subdev *sd); +/** + * cam_req_mgr_is_open() + * + * @brief: This common utility function returns the crm active status + * + * @dev_id: device id type + */ +bool cam_req_mgr_is_open(uint64_t dev_id); + +/** + * cam_req_mgr_is_shutdown() + * + * @brief: This common utility function returns the shutdown state + */ +bool cam_req_mgr_is_shutdown(void); + #endif /* _CAM_SUBDEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 96435bcd5fe6..d51dae6d37d7 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -10,6 +10,38 @@ #include "cam_trace.h" #include "camera_main.h" +static int cam_actuator_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + cam_actuator_shutdown(a_ctrl); + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + +static int cam_actuator_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); + + if (crm_active) { + CAM_INFO(CAM_ACTUATOR, + "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_actuator_subdev_close_internal(sd, fh); +} + static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -24,6 +56,14 @@ static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, CAM_ERR(CAM_ACTUATOR, "Failed for driver_cmd: %d", rc); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_actuator_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd: %u", cmd); rc = -ENOIOCTLCMD; @@ -77,24 +117,6 @@ static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, } #endif -static int cam_actuator_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_actuator_ctrl_t *a_ctrl = - v4l2_get_subdevdata(sd); - - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&(a_ctrl->actuator_mutex)); - cam_actuator_shutdown(a_ctrl); - mutex_unlock(&(a_ctrl->actuator_mutex)); - - return 0; -} - static struct v4l2_subdev_core_ops cam_actuator_subdev_core_ops = { .ioctl = cam_actuator_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -127,10 +149,13 @@ static int cam_actuator_init_subdev(struct cam_actuator_ctrl_t *a_ctrl) a_ctrl->v4l2_dev_str.ent_function = CAM_ACTUATOR_DEVICE_TYPE; a_ctrl->v4l2_dev_str.token = a_ctrl; + a_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str)); if (rc) - CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); + CAM_ERR(CAM_ACTUATOR, + "Fail with cam_register_subdev rc: %d", rc); return rc; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index fbe53591fc6e..17216d86d038 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -77,29 +77,7 @@ static void cam_csiphy_debug_unregister(void) root_dentry = NULL; } -static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); - int rc = 0; - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_csiphy_core_cfg(csiphy_dev, arg); - if (rc) - CAM_ERR(CAM_CSIPHY, - "Failed in configuring the device: %d", rc); - break; - default: - CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, +static int cam_csiphy_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct csiphy_device *csiphy_dev = @@ -117,6 +95,49 @@ static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); + + if (crm_active) { + CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_csiphy_subdev_close_internal(sd, fh); +} + +static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + int rc = 0; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_core_cfg(csiphy_dev, arg); + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in configuring the device: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_csiphy_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + #ifdef CONFIG_COMPAT static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -236,6 +257,8 @@ static int cam_csiphy_component_bind(struct device *dev, cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; + new_csiphy_dev->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str)); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 2c0f791b6f7e..cfcc166892d7 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -10,28 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_eeprom_driver_cmd(e_ctrl, arg); - if (rc) - CAM_ERR(CAM_EEPROM, - "Failed in Driver cmd: %d", rc); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, +static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_eeprom_ctrl_t *e_ctrl = @@ -49,6 +28,48 @@ static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); + + if (crm_active) { + CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_eeprom_subdev_close_internal(sd, fh); +} + +static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_driver_cmd(e_ctrl, arg); + if (rc) + CAM_ERR(CAM_EEPROM, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_eeprom_subdev_close_internal(sd, NULL); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_i2c_info_t *i2c_info) { @@ -147,6 +168,7 @@ static int cam_eeprom_init_subdev(struct cam_eeprom_ctrl_t *e_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE; e_ctrl->v4l2_dev_str.token = e_ctrl; + e_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 5a4655834eaa..8386d8d6b817 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -236,6 +236,37 @@ static const struct of_device_id cam_flash_dt_match[] = { {} }; +static int cam_flash_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_flash_ctrl *fctrl = + v4l2_get_subdevdata(sd); + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + +static int cam_flash_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FLASH); + + if (crm_active) { + CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_flash_subdev_close_internal(sd, fh); +} + static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -257,6 +288,14 @@ static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, "Failed in driver cmd: %d", rc); break; } + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_flash_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); rc = -ENOIOCTLCMD; @@ -328,24 +367,6 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) return rc; } -static int cam_flash_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_flash_ctrl *fctrl = - v4l2_get_subdevdata(sd); - - if (!fctrl) { - CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&fctrl->flash_mutex); - cam_flash_shutdown(fctrl); - mutex_unlock(&fctrl->flash_mutex); - - return 0; -} - static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = { .ioctl = cam_flash_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -375,6 +396,7 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; fctrl->v4l2_dev_str.token = fctrl; + fctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index b47d90225ca0..94b6a9cd8271 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -10,29 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_ois_driver_cmd(o_ctrl, arg); - if (rc) - CAM_ERR(CAM_OIS, - "Failed with driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_ois_subdev_close(struct v4l2_subdev *sd, +static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_ois_ctrl_t *o_ctrl = @@ -50,6 +28,48 @@ static int cam_ois_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_ois_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OIS); + + if (crm_active) { + CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ois_subdev_close_internal(sd, fh); +} + +static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_driver_cmd(o_ctrl, arg); + if (rc) + CAM_ERR(CAM_OIS, + "Failed with driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + rc = cam_ois_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl, struct cam_ois_i2c_info_t *i2c_info) { @@ -144,6 +164,7 @@ static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE; o_ctrl->v4l2_dev_str.token = o_ctrl; + o_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 92a5d940f339..9c6e2f2a2060 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -9,29 +9,7 @@ #include "cam_sensor_core.h" #include "camera_main.h" -static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_sensor_ctrl_t *s_ctrl = - v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_sensor_driver_cmd(s_ctrl, arg); - if (rc) - CAM_ERR(CAM_SENSOR, - "Failed in Driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -static int cam_sensor_subdev_close(struct v4l2_subdev *sd, +static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_sensor_ctrl_t *s_ctrl = @@ -49,6 +27,49 @@ static int cam_sensor_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_sensor_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); + + if (crm_active) { + CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_sensor_subdev_close_internal(sd, fh); +} + +static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_sensor_driver_cmd(s_ctrl, arg); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_sensor_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + #ifdef CONFIG_COMPAT static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -122,6 +143,8 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE; s_ctrl->v4l2_dev_str.token = s_ctrl; + s_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); if (rc) From 41716fade55176e8d73865491fec824e9a78784d Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 30 Apr 2021 16:11:43 +0530 Subject: [PATCH 746/790] msm: camera: req_mgr: Fix deadlock in ICP driver in close sequence ICP driver is not releasing mutex in error scenario in close sequence and causing deadlock further in open. Fix the deadlock and avoid prints in other driver while close in provider crash. CRs-Fixed: 2938073 Change-Id: I226c9a8e9b2d0c30e90282b11fbd15ea0b085f87 Signed-off-by: Alok Chauhan --- drivers/cam_icp/cam_icp_subdev.c | 4 ++-- drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c | 2 +- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c | 2 +- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c | 2 +- drivers/cam_sensor_module/cam_flash/cam_flash_dev.c | 2 +- drivers/cam_sensor_module/cam_ois/cam_ois_dev.c | 2 +- drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 3288964444ef..1a3be9b64ad5 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -107,8 +107,8 @@ int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_WARN(CAM_ICP, "ICP subdev is already closed"); - return 0; + CAM_DBG(CAM_ICP, "ICP subdev is already closed"); + goto end; } g_icp_dev.open_cnt--; if (!node) { diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index d51dae6d37d7..17b310eee33a 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -34,7 +34,7 @@ static int cam_actuator_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); if (crm_active) { - CAM_INFO(CAM_ACTUATOR, + CAM_DBG(CAM_ACTUATOR, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 17216d86d038..204f1df7c653 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -101,7 +101,7 @@ static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); if (crm_active) { - CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index cfcc166892d7..00d695326bcf 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -34,7 +34,7 @@ static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); if (crm_active) { - CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 8386d8d6b817..471b788cc211 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -260,7 +260,7 @@ static int cam_flash_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_FLASH); if (crm_active) { - CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 94b6a9cd8271..a7616d4d19b1 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -34,7 +34,7 @@ static int cam_ois_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_OIS); if (crm_active) { - CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 9c6e2f2a2060..d4982ab2311e 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -33,7 +33,7 @@ static int cam_sensor_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); if (crm_active) { - CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); return 0; } From 4c9ba2b3627c6719616c41ac3a8ecde4c35d7afa Mon Sep 17 00:00:00 2001 From: Amit Somani Date: Mon, 8 Feb 2021 19:22:07 +0530 Subject: [PATCH 747/790] msm: camera: config: Add Support for monaco target Add camera config support for MONACO target. CRs-Fixed: 2918290 Change-Id: I98ff2a0d540aa6a4fb5a31a8d26f7abe0750918d Signed-off-by: Amit Somani --- Makefile | 9 +++++++++ config/monacocamera.conf | 8 ++++++++ config/monacocameraconf.h | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 config/monacocamera.conf create mode 100644 config/monacocameraconf.h diff --git a/Makefile b/Makefile index 44714b7440f5..e25a6ede1961 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,10 @@ ifeq ($(CONFIG_ARCH_BENGAL), y) include $(srctree)/techpack/camera/config/bengalcamera.conf endif +ifeq ($(CONFIG_ARCH_MONACO), y) +include $(srctree)/techpack/camera/config/monacocamera.conf +endif + ifeq ($(CONFIG_ARCH_LAHAINA), y) include $(srctree)/techpack/camera/config/lahainacamera.conf endif @@ -45,6 +49,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/bengalcameraconf.h endif +ifeq ($(CONFIG_ARCH_MONACO), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/monacocameraconf.h +endif + ifeq ($(CONFIG_ARCH_LAHAINA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/lahainacameraconf.h diff --git a/config/monacocamera.conf b/config/monacocamera.conf new file mode 100644 index 000000000000..99b81918e8a3 --- /dev/null +++ b/config/monacocamera.conf @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2019,2021 The Linux Foundation. All rights reserved. + +export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_TFE=y +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_OPE=y diff --git a/config/monacocameraconf.h b/config/monacocameraconf.h new file mode 100644 index 000000000000..17a038cc14d9 --- /dev/null +++ b/config/monacocameraconf.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_TFE 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_OPE 1 + From d3f13f02a4b0acf7a61a3b88a4783347b60bc24c Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 21 May 2021 12:22:20 +0530 Subject: [PATCH 748/790] msm: camera: core: Make Blair camera module dynamic This change is to make Blair camera module dynamic. CRs-Fixed: 2944976 Change-Id: I1af60fd3e1e607f52285d7abf30321ff6682149e Signed-off-by: Ayush Kumar --- config/blaircamera.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/blaircamera.conf b/config/blaircamera.conf index be2ce67888d1..4a5de0e8362a 100644 --- a/config/blaircamera.conf +++ b/config/blaircamera.conf @@ -2,7 +2,7 @@ # Copyright (c) 2021, The Linux Foundation. All rights reserved. ifeq ($(CONFIG_QGKI),y) -export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_CAMERA=m $(info "SPECTRA_CAMERA IS STATIC") else $(info "SPECTRA_CAMERA IS MODULAR") From 5c97b95b7b76869cfb5e60a945021ceeec5f9cf5 Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Fri, 5 Mar 2021 16:17:57 -0800 Subject: [PATCH 749/790] msm: camera: sensor: extend I2C read/write size Extend I2C read/write capability to 20kb CRs-Fixed: 2952585 Change-Id: Ia5465342fd1d434f90e472c3dd5a5275c3fab8cd Signed-off-by: Sureshnaidu Laveti --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 6 +++--- drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 46cf0315dcab..5e12aa557cd9 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_DEV_H_ @@ -50,8 +50,8 @@ #define CCI_READ_MAX 256 #define CCI_READ_MAX_V_1_2 0xE #define CCI_I2C_READ_MAX_RETRIES 3 -#define CCI_I2C_MAX_READ 10240 -#define CCI_I2C_MAX_WRITE 10240 +#define CCI_I2C_MAX_READ 20480 +#define CCI_I2C_MAX_WRITE 20480 #define CCI_I2C_MAX_BYTE_COUNT 65535 #define CAMX_CCI_DEV_NAME "cam-cci-driver" diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h index e37314a46571..6cece10403c9 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_I2C_H_ @@ -18,7 +18,7 @@ #define I2C_COMPARE_MATCH 0 #define I2C_COMPARE_MISMATCH 1 -#define I2C_REG_DATA_MAX (10*1024) +#define I2C_REG_DATA_MAX (20*1024) /** * @client: CCI client structure From 93f25fccc80cf7e3103beaabf44c70a70c52da62 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 13 Apr 2021 13:54:28 +0800 Subject: [PATCH 750/790] msm: camera: isp: Mask process_bubble for SHDR usecase SHDR usecase doesn't report bubble to CRM, but we still need to know whether it is processing bubble during applying request, since we may haven't received the reg update of the previous applied request, then we have a chance to apply a new req to HW, this may result in overflow issue. This change masks the process_bubble for SHDR case during epoch in applied sub state. CRs-Fixed: 2948932 Change-Id: I699a2f59ea874693b78a918895db98727b95c634 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 60f974ff94e7..00af70d8a093 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -864,6 +864,18 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( list_add_tail(&req->list, &ctx->free_req_list); req_isp->reapply = false; req_isp->cdm_reset_before_apply = false; + req_isp->num_acked = 0; + req_isp->num_deferred_acks = 0; + req_isp->bubble_detected = false; + /* + * Only update the process_bubble and bubble_frame_cnt + * when bubble is detected on this req, in case the other + * request is processing bubble. + */ + if (req_isp->bubble_detected) { + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->bubble_frame_cnt = 0; + } CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", @@ -2101,6 +2113,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, ctx_isp->frame_id, ctx->ctx_id); } } + atomic_set(&ctx_isp->process_bubble, 1); } /* @@ -2336,6 +2349,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( ctx_isp->frame_id, ctx->ctx_id); } } + atomic_set(&ctx_isp->process_bubble, 1); } /* From 56f616b4634fa5cb6068e9b9305a50053204ca11 Mon Sep 17 00:00:00 2001 From: Amit Somani Date: Thu, 20 May 2021 06:10:23 +0530 Subject: [PATCH 751/790] msm: camera: sensor: fix 64-bit division for 32-bit kernel compilation Fix a 64bit division error for 32bit kernel compilation. CRs-Fixed: 2918290 Change-Id: Ic729644088eb6e8640de240d76b2e8971d2f569c Signed-off-by: Amit Somani --- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 4 ++-- drivers/cam_utils/cam_soc_icc.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 8cda6c3831c8..8fe5b78243f3 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -10,6 +10,7 @@ #include "cam_res_mgr_api.h" #include "cam_common_util.h" #include "cam_packet_util.h" +#include static uint default_on_timer = 2; module_param(default_on_timer, uint, 0644); @@ -1558,8 +1559,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) add_req.trigger_eof = true; /* Active time for the preflash */ flash_data->flash_active_time_ms = - (flash_operation_info->time_on_duration_ns) - / 1000000; + do_div(flash_operation_info->time_on_duration_ns, 1000000); CAM_DBG(CAM_FLASH, "PRECISE FLASH: active_time: %llu", flash_data->flash_active_time_ms); diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index a30e0f153b1b..757254777740 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include #include "cam_soc_bus.h" - +#include /** * struct cam_soc_bus_client_data : Bus client data * @@ -37,8 +37,8 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) CAM_DBG(CAM_PERF, "Bus client=[%s] index[%d] ab[%llu] ib[%llu]", bus_client->common_data->name, idx, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), - Bps_to_icc(ib)); + rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), + do_div(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s], idx: %d", @@ -60,8 +60,8 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) CAM_DBG(CAM_PERF, "Bus client=[%s] :ab[%llu] ib[%llu]", bus_client->common_data->name, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), - Bps_to_icc(ib)); + rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), + do_div(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s]", bus_client->common_data->name); From 7a10111a875e1f380cf3739e745fa8230fe0d5d5 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Thu, 4 Feb 2021 11:54:21 -0800 Subject: [PATCH 752/790] msm: camera: sensor: Increase slot ids in sensor Increase the max supported slot ids to 16 in sensor. CRs-Fixed: 2871214 Change-Id: I08910f2c34f70333bf25dbb31de5994c3beb7a8f Signed-off-by: Jigar Agrawal --- .../cam_sensor_utils/cam_sensor_cmn_header.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 25ab72ae6069..58a248f4c882 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_CMN_HEADER_ @@ -345,6 +345,12 @@ enum msm_sensor_camera_id_t { CAMERA_7, CAMERA_8, CAMERA_9, + CAMERA_10, + CAMERA_11, + CAMERA_12, + CAMERA_13, + CAMERA_14, + CAMERA_15, MAX_CAMERAS, }; From de2b0fb94b1ac6910cefea9512805a123cf3aa7f Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Thu, 6 May 2021 11:38:30 +0530 Subject: [PATCH 753/790] msm: camera: flash: Add support for I2C flash - Add Regulator power up for I2C flash - Add GPIO support in probe call for I2C flash - Add flash type in query capability call of flash. CRs-Fixed: 2938804 Change-Id: I7d5575ecdf4c1c3b329e6bf49586771e37611e5a Signed-off-by: shiwgupt --- .../cam_sensor_module/cam_flash/cam_flash_dev.c | 17 ++++++++++++++++- .../cam_sensor_module/cam_flash/cam_flash_dev.h | 5 ++++- .../cam_sensor_module/cam_flash/cam_flash_soc.c | 8 +++++++- .../cam_sensor_utils/cam_sensor_util.c | 4 ++++ include/uapi/camera/media/cam_sensor.h | 4 +++- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 5a4655834eaa..d92b81605fdc 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -133,7 +133,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, struct cam_flash_query_cap_info flash_cap = {0}; CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); - flash_cap.slot_info = fctrl->soc_info.index; + flash_cap.slot_info = fctrl->soc_info.index; + flash_cap.flash_type = soc_private->flash_type; for (i = 0; i < fctrl->flash_num_sources; i++) { flash_cap.max_current_flash[i] = soc_private->flash_max_current[i]; @@ -390,6 +391,7 @@ static int cam_flash_component_bind(struct device *dev, struct cam_flash_ctrl *fctrl = NULL; struct device_node *of_parent = NULL; struct platform_device *pdev = to_platform_device(dev); + struct cam_hw_soc_info *soc_info = NULL; CAM_DBG(CAM_FLASH, "Binding flash component"); if (!pdev->dev.of_node) { @@ -445,6 +447,19 @@ static int cam_flash_component_bind(struct device *dev, fctrl->io_master_info.cci_client->cci_device = fctrl->cci_num; CAM_DBG(CAM_FLASH, "cci-index %d", fctrl->cci_num, rc); + soc_info = &fctrl->soc_info; + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &fctrl->power_info.gpio_num_info); + if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) { + CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs"); + return -EINVAL; + } + rc = cam_sensor_util_regulator_powerup(soc_info); + if (rc < 0) { + CAM_ERR(CAM_FLASH, "regulator power up for flash failed %d", rc); + return rc; + } + fctrl->i2c_data.per_frame = kzalloc(sizeof(struct i2c_settings_array) * MAX_PER_FRAME_ARRAY, GFP_KERNEL); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index b8416cd15d8b..cc1c9738d2b6 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FLASH_DEV_H_ @@ -30,6 +30,7 @@ #include "cam_subdev.h" #include "cam_mem_mgr.h" #include "cam_sensor_cmn_header.h" +#include "cam_sensor_util.h" #include "cam_soc_util.h" #include "cam_debug_util.h" #include "cam_sensor_io.h" @@ -137,6 +138,7 @@ struct cam_flash_frame_setting { * @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 + * @flash_type : Flash type */ struct cam_flash_private_soc { @@ -149,6 +151,7 @@ struct cam_flash_private_soc { uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; bool is_wled_flash; + uint32_t flash_type; }; struct cam_flash_func_tbl { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 17b7c7e0aec8..9af39e9560fb 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -73,6 +73,12 @@ static int32_t cam_get_source_node_info( soc_private->is_wled_flash = of_property_read_bool(of_node, "wled-flash-support"); + rc = of_property_read_u32(of_node, "flash-type", &soc_private->flash_type); + if (rc) { + CAM_ERR(CAM_FLASH, + "flash-type read failed rc=%d", rc); + } + switch_src_node = of_parse_phandle(of_node, "switch-source", 0); if (!switch_src_node) { CAM_WARN(CAM_FLASH, "switch_src_node NULL"); diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 4147c1dc7409..771ca38fa6d8 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -2407,6 +2407,10 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, case SENSOR_CUSTOM_GPIO1: case SENSOR_CUSTOM_GPIO2: + if (!gpio_num_info) { + CAM_ERR(CAM_SENSOR, "failed: No gpio"); + continue; + } if (!gpio_num_info->valid[pd->seq_type]) continue; diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index cff997346943..f935a7a702b3 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_SENSOR_H__ @@ -476,6 +476,7 @@ struct cam_flash_query_curr { * @max_current_flash : max supported current for flash * @max_duration_flash : max flash turn on duration * @max_current_torch : max supported current for torch + * @flash_type : Indicates about the flash type -I2C,GPIO,PMIC * */ struct cam_flash_query_cap_info { @@ -483,6 +484,7 @@ struct cam_flash_query_cap_info { __u32 max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS]; __u32 max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; __u32 max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; + __u32 flash_type; } __attribute__ ((packed)); #endif From bc32fa9ef8ba4c3a18673b9ef9c60d2dce1fd416 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Thu, 8 Apr 2021 17:07:47 +0530 Subject: [PATCH 754/790] msm: camera: smmu: Disable SMMU stall on page fault Changes are made to disable stall on pagefault for all the driver contexts inorder to support for smmu stall on page fault. CRs-Fixed: 2936320 Change-Id: Id3d16b4d980349044de1bc1d1bf4bfad5aee79f4 Signed-off-by: Shravya Samala --- drivers/cam_smmu/cam_smmu_api.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 14734c75a15d..05b3700bddfb 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. */ #include @@ -133,6 +133,7 @@ struct cam_context_bank_info { bool is_fw_allocated; bool is_secheap_allocated; bool is_qdss_allocated; + bool stall_disable; struct scratch_mapping scratch_map; struct gen_pool *shared_mem_pool; @@ -3641,6 +3642,8 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, struct device *dev) { int rc = 0; + int32_t stall_disable = 1; + int32_t hupcf = 1; if (!cb || !dev) { CAM_ERR(CAM_SMMU, "Error: invalid input params"); @@ -3708,6 +3711,24 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, cb->discard_iova_len); cb->state = CAM_SMMU_ATTACH; + + if (cb->stall_disable) { + if (iommu_domain_set_attr(cb->domain, + DOMAIN_ATTR_FAULT_MODEL_NO_STALL, + &stall_disable) < 0) { + CAM_ERR(CAM_SMMU, + "Error: failed to set cb stall disable for node: %s", + cb->name[0]); + } + + if (iommu_domain_set_attr(cb->domain, + DOMAIN_ATTR_FAULT_MODEL_HUPCF, + &hupcf) < 0) { + CAM_ERR(CAM_SMMU, + "Error: failed to set attribute HUPCF for node: %s", + cb->name[0]); + } + } } else { CAM_ERR(CAM_SMMU, "Context bank does not have IO region"); rc = -ENODEV; @@ -4046,6 +4067,9 @@ static int cam_populate_smmu_context_banks(struct device *dev, cb->num_shared_hdl = of_property_count_strings(dev->of_node, "cam-smmu-label"); + cb->stall_disable = + of_property_read_bool(dev->of_node, "stall-disable"); + if (cb->num_shared_hdl > CAM_SMMU_SHARED_HDL_MAX) { CAM_ERR(CAM_CDM, "Invalid count of client names count=%d", From aead69dc61ff7f6f17b91de0235a017b905c83ca Mon Sep 17 00:00:00 2001 From: Om Parkash Date: Sun, 6 Jun 2021 13:30:56 +0530 Subject: [PATCH 755/790] msm: camera: sensor: Use correct addr_type & data_type for probe Use correct Address type & data type for camera sensor probe use the type received from sensor driver instead of hardcoding. CRs-Fixed: 2948896 Change-Id: I3e355d86fca6a49fb96ab782213dc158f0a6ea39 Signed-off-by: Om Parkash --- drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 32b05eadfc64..38846433fd0a 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -688,8 +688,9 @@ int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl) rc = camera_io_dev_read( &(s_ctrl->io_master_info), slave_info->sensor_id_reg_addr, - &chipid, CAMERA_SENSOR_I2C_TYPE_WORD, - CAMERA_SENSOR_I2C_TYPE_WORD); + &chipid, + s_ctrl->sensor_probe_addr_type, + s_ctrl->sensor_probe_data_type); CAM_DBG(CAM_SENSOR, "read id: 0x%x expected id 0x%x:", chipid, slave_info->sensor_id); From 0c570733eee53cf47a261d84e438cbaa6d0eb6d2 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Tue, 1 Jun 2021 19:56:41 +0530 Subject: [PATCH 756/790] msm: camera: cci: Fix CCI Timeout during burst_read concurrency During burst read concurrency, is_burst_read variable not updated properly leading to missing th_complete signal. is_burst_read variable updated per master to avoid concurrency issue. CRs-Fixed: 2962232 Change-Id: Id741d48e0b9a6987b4aa7bc7361daf555d9bc587 Signed-off-by: Anil Kumar Kanakanti --- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 10 ++++------ drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 6 +++--- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 4 ++-- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 3 ++- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 59dad9ee4e72..e4e185bb28c1 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -985,6 +985,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, } mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + cci_dev->is_burst_read[master] = true; reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); soc_info = &cci_dev->soc_info; @@ -1256,6 +1257,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, } mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + cci_dev->is_burst_read[master] = false; reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); soc_info = &cci_dev->soc_info; @@ -1622,7 +1624,7 @@ static int32_t cam_cci_read_bytes_v_1_2(struct v4l2_subdev *sd, else read_cfg->num_byte = read_bytes; - cci_dev->is_burst_read = false; + cci_dev->is_burst_read[master] = false; rc = cam_cci_read(sd, c_ctrl); if (rc) { CAM_ERR(CAM_CCI, "failed to read rc:%d", rc); @@ -1639,7 +1641,6 @@ static int32_t cam_cci_read_bytes_v_1_2(struct v4l2_subdev *sd, } while (read_bytes); ERROR: - cci_dev->is_burst_read = false; return rc; } @@ -1704,10 +1705,8 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, read_cfg->num_byte = read_bytes; if (read_cfg->num_byte >= CCI_READ_MAX) { - cci_dev->is_burst_read = true; rc = cam_cci_burst_read(sd, c_ctrl); } else { - cci_dev->is_burst_read = false; rc = cam_cci_read(sd, c_ctrl); } if (rc) { @@ -1726,7 +1725,6 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, } while (read_bytes); ERROR: - cci_dev->is_burst_read = false; return rc; } diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 8b5ab58539f1..e496ca83cf65 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" @@ -112,7 +112,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) (!rd_done_th_assert)) { cci_dev->cci_master_info[MASTER_0].status = 0; rd_done_th_assert = true; - if (cci_dev->is_burst_read) + if (cci_dev->is_burst_read[MASTER_0]) complete( &cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].rd_done); @@ -168,7 +168,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) (!rd_done_th_assert)) { cci_dev->cci_master_info[MASTER_1].status = 0; rd_done_th_assert = true; - if (cci_dev->is_burst_read) + if (cci_dev->is_burst_read[MASTER_1]) complete( &cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].rd_done); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 46cf0315dcab..6ea516b361b2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_DEV_H_ @@ -224,7 +224,7 @@ struct cci_device { uint32_t cpas_handle; uint32_t irq_status1; spinlock_t lock_status; - bool is_burst_read; + bool is_burst_read[MASTER_MAX]; uint32_t irqs_disabled; struct mutex init_mutex; uint64_t dump_en; diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 39433a3f43e1..268e6c119824 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" @@ -76,6 +76,7 @@ static int cam_cci_init_master(struct cci_device *cci_dev, cci_dev->cci_master_info[master].status = 0; cci_dev->cci_master_info[master].is_initilized = true; + cci_dev->is_burst_read[master] = false; } return 0; From 62b8ede47a33ec1e6155424659d6c13d654011de Mon Sep 17 00:00:00 2001 From: Rohith M Date: Thu, 10 Jun 2021 20:44:48 +0530 Subject: [PATCH 757/790] msm: camera: cpas: Add support for new cpas version Added support for 520_110 CPAS version CRs-Fixed: 2948896 Change-Id: I03ee4e81a33f41d634f6162bc5043e9ad0dc6f1c Signed-off-by: Rohith M --- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 7 +- drivers/cam_cpas/cpas_top/cpastop_v520_110.h | 244 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 1 + 3 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v520_110.h diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 01a376dd51c1..4baab87eec64 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -27,6 +27,7 @@ #include "cpastop_v580_custom.h" #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" +#include "cpastop_v520_110.h" #include "cpastop_v545_100.h" #include "cpastop_v545_110.h" #include "cpastop_v570_200.h" @@ -101,7 +102,7 @@ static const uint32_t cam_cpas_hw_version_map { CAM_CPAS_TITAN_520_V100, 0, - 0, + CAM_CPAS_TITAN_520_V110, 0, 0, 0, @@ -931,6 +932,10 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, camnoc_info = &cam520_cpas100_camnoc_info; qchannel_info = &cam520_cpas100_qchannel_info; break; + case CAM_CPAS_TITAN_520_V110: + camnoc_info = &cam520_cpas110_camnoc_info; + qchannel_info = &cam520_cpas110_qchannel_info; + break; case CAM_CPAS_TITAN_545_V100: camnoc_info = &cam545_cpas100_camnoc_info; qchannel_info = &cam545_cpas100_qchannel_info; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v520_110.h b/drivers/cam_cpas/cpas_top/cpastop_v520_110.h new file mode 100644 index 000000000000..f1328122e644 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v520_110.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V520_110_H_ +#define _CPASTOP_V520_110_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v520_110_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v520_110_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 = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +static struct cam_camnoc_specific + cam_cpas_v520_110_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 = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x00000003, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x44443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66665555, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + .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_OPE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x00000033, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_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, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam520_cpas110_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam520_cpas110_camnoc_info = { + .specific = &cam_cpas_v520_110_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v520_110_camnoc_specific), + .irq_sbm = &cam_cpas_v520_110_irq_sbm, + .irq_err = &cam_cpas_v520_110_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v520_110_irq_err), + .err_logger = &cam520_cpas110_err_logger_offsets, + .errata_wa_list = NULL, +}; + +static struct cam_cpas_camnoc_qchannel cam520_cpas110_qchannel_info = { + .qchannel_ctrl = 0x14, + .qchannel_status = 0x18, +}; +#endif /* _CPASTOP_V520_110_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 87fe72a42a64..158b4ba3c5e0 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -138,6 +138,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_580_V100 = 0x580100, CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_520_V100 = 0x520100, + CAM_CPAS_TITAN_520_V110 = 0x520110, CAM_CPAS_TITAN_545_V100 = 0x545100, CAM_CPAS_TITAN_545_V110 = 0x545110, CAM_CPAS_TITAN_570_V200 = 0x570200, From 6c3073f63a272705628a0cbc349e6098e1ec2d9d Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 15 Jun 2021 10:48:38 +0800 Subject: [PATCH 758/790] msm: camera: isp: Fix the assignment of bubble_detected Fix the assignment of bubble_detected. CRs-Fixed: 2948932 Change-Id: Ie9a289f732d12a0238e643e81c8a5bbdcaca059a Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 00af70d8a093..ea569d0521bc 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -866,7 +866,6 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( req_isp->cdm_reset_before_apply = false; req_isp->num_acked = 0; req_isp->num_deferred_acks = 0; - req_isp->bubble_detected = false; /* * Only update the process_bubble and bubble_frame_cnt * when bubble is detected on this req, in case the other @@ -875,6 +874,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( if (req_isp->bubble_detected) { atomic_set(&ctx_isp->process_bubble, 0); ctx_isp->bubble_frame_cnt = 0; + req_isp->bubble_detected = false; } CAM_DBG(CAM_REQ, From b77fca2cb0b85b57b758e574b8db627faf967055 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 14 Jun 2021 10:56:24 -0700 Subject: [PATCH 759/790] msm: camera: csiphy: Continue in case of unavailibility of CSIPHY hw During the common control register programming across csiphy hws, there can be chance that number of CSIPHY hw supported is differnt than max csiphy hw supported among various targets. This change make sure to continue to next available hardware index in case of unavailibility of csiphy hw soc index. CRs-Fixed: 2948896 Change-Id: I1572974226701dcd3aadeb3d9cf95924e05520a9 Signed-off-by: Jigarkumar Zala --- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 4781285ea46d..210179307a9e 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -153,6 +153,12 @@ static void cam_csiphy_prgm_cmn_data( csiphybase = g_phy_data[csiphy_idx].base_address; is_3phase = g_phy_data[csiphy_idx].is_3phase; + if (!csiphybase) { + CAM_DBG(CAM_CSIPHY, "CSIPHY: %d is not available in platform", + csiphy_idx); + continue; + } + for (i = 0; i < size; i++) { csiphy_common_reg = &csiphy_dev->ctrl_reg->csiphy_common_reg[i]; From 5bf8f7b7ae49965d42c453a445a8696c5e466027 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Mon, 14 Jun 2021 22:49:14 +0530 Subject: [PATCH 760/790] msm: camera: flash: Init default flash type to PMIC flash Initialize default flash type to PMIC flash. CRs-Fixed: 2969985 Change-Id: Id563435f78b7412362bd1f6a1db53cbdfc3664cc Signed-off-by: Anil Kumar Kanakanti --- drivers/cam_sensor_module/cam_flash/cam_flash_soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 9af39e9560fb..9ec28e953f8b 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -7,6 +7,7 @@ #include #include "cam_flash_soc.h" #include "cam_res_mgr_api.h" +#include void cam_flash_put_source_node_data(struct cam_flash_ctrl *fctrl) { @@ -77,6 +78,7 @@ static int32_t cam_get_source_node_info( if (rc) { CAM_ERR(CAM_FLASH, "flash-type read failed rc=%d", rc); + soc_private->flash_type = CAM_FLASH_TYPE_PMIC; // default to PMIC flash } switch_src_node = of_parse_phandle(of_node, "switch-source", 0); From e1261386ea9c5a220093aa1e47108e012471edf1 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Tue, 22 Jun 2021 12:18:26 +0530 Subject: [PATCH 761/790] msm: camera: common: Fix for wrong ab ib value send to ICC While passing ab and ib value to interconnect for conversion from BPS to ICC units wrong kernel macro is used. Therefore use correct macro to get the proper ICC units. In the same way, update the correct flash on active time (use div_u64 instead of do_div). CRs-Fixed: 2971025 Change-Id: I4cd0de06bd081ea95cdc76eb74887c4d5815241a Signed-off-by: Wyes Karny --- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 4 ++-- drivers/cam_utils/cam_soc_icc.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 8fe5b78243f3..0dbc38b0280b 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -10,7 +10,7 @@ #include "cam_res_mgr_api.h" #include "cam_common_util.h" #include "cam_packet_util.h" -#include +#include static uint default_on_timer = 2; module_param(default_on_timer, uint, 0644); @@ -1559,7 +1559,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) add_req.trigger_eof = true; /* Active time for the preflash */ flash_data->flash_active_time_ms = - do_div(flash_operation_info->time_on_duration_ns, 1000000); + div_u64(flash_operation_info->time_on_duration_ns, 1000000); CAM_DBG(CAM_FLASH, "PRECISE FLASH: active_time: %llu", flash_data->flash_active_time_ms); diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index 757254777740..c6b405b509c5 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -5,7 +5,7 @@ #include #include "cam_soc_bus.h" -#include +#include /** * struct cam_soc_bus_client_data : Bus client data * @@ -37,8 +37,8 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) CAM_DBG(CAM_PERF, "Bus client=[%s] index[%d] ab[%llu] ib[%llu]", bus_client->common_data->name, idx, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), - do_div(ib, 1000)); + rc = icc_set_bw(bus_client_data->icc_data, div_u64(ab, 1000), + div_u64(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s], idx: %d", @@ -60,8 +60,8 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) CAM_DBG(CAM_PERF, "Bus client=[%s] :ab[%llu] ib[%llu]", bus_client->common_data->name, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), - do_div(ib, 1000)); + rc = icc_set_bw(bus_client_data->icc_data, div_u64(ab, 1000), + div_u64(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s]", bus_client->common_data->name); From 8940d2ec7362b363d2e87d1d0c54e479165a7666 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Tue, 22 Jun 2021 14:17:41 +0530 Subject: [PATCH 762/790] msm: camera: csiphy: Update CSIPHY settings as per HPG CSIPHY settings updated based on latest HPG settings. CRs-Fixed: 2974853 Change-Id: I3cb3d25bddf707ee9d57a145e0506487b12e487e Signed-off-by: Anil Kumar Kanakanti --- .../include/cam_csiphy_1_2_1_hwreg.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 813d978eb536..3881b21bfab8 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -71,7 +71,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -93,7 +93,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -115,7 +115,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -137,7 +137,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -159,7 +159,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -185,7 +185,7 @@ struct csiphy_reg_t {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -207,7 +207,7 @@ struct csiphy_reg_t {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -229,7 +229,7 @@ struct csiphy_reg_t {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -251,7 +251,7 @@ struct csiphy_reg_t {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -273,7 +273,7 @@ struct csiphy_reg_t {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, From d6ba43879479b424d3e3c962dab4bd816abb1c45 Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Tue, 22 Jun 2021 12:18:26 +0530 Subject: [PATCH 763/790] msm: camera: common: Fix for wrong ab ib value send to ICC While passing ab and ib value to interconnect for conversion from BPS to ICC units wrong kernel macro is used. Therefore use correct macro to get the proper ICC units. In the same way, update the correct flash on active time (use div_u64 instead of do_div). CRs-Fixed: 2971025 Change-Id: I4cd0de06bd081ea95cdc76eb74887c4d5815241a Signed-off-by: Wyes Karny --- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 4 ++-- drivers/cam_utils/cam_soc_icc.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 8fe5b78243f3..0dbc38b0280b 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -10,7 +10,7 @@ #include "cam_res_mgr_api.h" #include "cam_common_util.h" #include "cam_packet_util.h" -#include +#include static uint default_on_timer = 2; module_param(default_on_timer, uint, 0644); @@ -1559,7 +1559,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) add_req.trigger_eof = true; /* Active time for the preflash */ flash_data->flash_active_time_ms = - do_div(flash_operation_info->time_on_duration_ns, 1000000); + div_u64(flash_operation_info->time_on_duration_ns, 1000000); CAM_DBG(CAM_FLASH, "PRECISE FLASH: active_time: %llu", flash_data->flash_active_time_ms); diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index 757254777740..c6b405b509c5 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -5,7 +5,7 @@ #include #include "cam_soc_bus.h" -#include +#include /** * struct cam_soc_bus_client_data : Bus client data * @@ -37,8 +37,8 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) CAM_DBG(CAM_PERF, "Bus client=[%s] index[%d] ab[%llu] ib[%llu]", bus_client->common_data->name, idx, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), - do_div(ib, 1000)); + rc = icc_set_bw(bus_client_data->icc_data, div_u64(ab, 1000), + div_u64(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s], idx: %d", @@ -60,8 +60,8 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) CAM_DBG(CAM_PERF, "Bus client=[%s] :ab[%llu] ib[%llu]", bus_client->common_data->name, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), - do_div(ib, 1000)); + rc = icc_set_bw(bus_client_data->icc_data, div_u64(ab, 1000), + div_u64(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s]", bus_client->common_data->name); From 146310b60e7e63029e020859f8e113f5eb25229b Mon Sep 17 00:00:00 2001 From: Hongwei Ren Date: Fri, 25 Jun 2021 11:00:54 +0530 Subject: [PATCH 764/790] msm: camera: core: Make Bengal camera module dynamic This change is to make Bengal camera module dynamic. CRs-Fixed: 2977410 Change-Id: I447fa17c907c5e1993dbf86ae1347e4e15de6b30 Signed-off-by: Hongwei Ren --- config/bengalcamera.conf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/config/bengalcamera.conf b/config/bengalcamera.conf index 38e163af7ebd..7d85536d439c 100644 --- a/config/bengalcamera.conf +++ b/config/bengalcamera.conf @@ -1,8 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only -# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# Copyright (c) 2019,2021 The Linux Foundation. All rights reserved. -export CONFIG_SPECTRA_CAMERA=y +$(info "BENGAL SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) export CONFIG_SPECTRA_TFE=y export CONFIG_SPECTRA_ISP=y export CONFIG_SPECTRA_SENSOR=y export CONFIG_SPECTRA_OPE=y +endif \ No newline at end of file From 3273afefe75420434b64a356ba3743292d9d6bfb Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Tue, 1 Jun 2021 01:03:52 +0530 Subject: [PATCH 765/790] msm: camera: reqmgr: Reset sync mode for sync link in bubble Reset sync link in case of bubble recovery. When dual link is enabled, it is not required to re-apply the sync link request in bubble recovery as the sync link request is already applied and by the time reapply comes request would not be in pending list. Therefore set the sync mode to zero for that index, so that there would not be any dependency on the sync link. CRs-Fixed: 2978526 Change-Id: I327371baecfd6d378cb773bc27c412ba6d2ba42d Signed-off-by: Wyes Karny --- drivers/cam_req_mgr/cam_req_mgr_core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index c7d6e8252b02..beeb2ec07f3a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2900,6 +2900,13 @@ int cam_req_mgr_process_error(void *priv, void *data) in_q->rd_idx = idx; in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED; + if (link->sync_link[0]) { + in_q->slot[idx].sync_mode = 0; + __cam_req_mgr_inc_idx(&idx, 1, + link->req.l_tbl->num_slots); + in_q->slot[idx].sync_mode = 0; + } + /* The next req may also be applied */ idx = in_q->rd_idx; __cam_req_mgr_inc_idx(&idx, 1, From c99311f326af03fd25cde0e9baa2edfb9a72a797 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 2 Nov 2020 05:21:18 +0530 Subject: [PATCH 766/790] msm: camera: core: Add delay detection support This changes is to detect workqueue and tasklet scheduling and execution delay. CRs-Fixed: 2977775 Change-Id: Ia4b4845a067c22bd1f24bd63a971d103fcfc049c Signed-off-by: Ayush Kumar --- drivers/cam_cdm/cam_cdm_hw_core.c | 7 +++- drivers/cam_cdm/cam_cdm_virtual_core.c | 9 +++-- drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 7 +++- .../isp_hw_mgr/hw_utils/cam_tasklet_util.c | 27 ++++++++++++- drivers/cam_req_mgr/cam_req_mgr_workq.c | 38 +++++++------------ drivers/cam_req_mgr/cam_req_mgr_workq.h | 24 ++++-------- .../cam_sensor_module/cam_cci/cam_cci_core.c | 7 +++- drivers/cam_sync/cam_sync_util.c | 9 +++-- drivers/cam_utils/cam_common_util.c | 26 ++++++++++++- drivers/cam_utils/cam_common_util.h | 15 +++++++- 10 files changed, 112 insertions(+), 57 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 013b9f3267ed..37f2a0a10967 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -26,6 +26,7 @@ #include "camera_main.h" #include "cam_trace.h" #include "cam_req_mgr_workq.h" +#include "cam_common_util.h" #define CAM_CDM_BL_FIFO_WAIT_TIMEOUT 2000 #define CAM_CDM_DBG_GEN_IRQ_USR_DATA 0xff @@ -1215,8 +1216,10 @@ static void cam_hw_cdm_work(struct work_struct *work) return; } - cam_req_mgr_thread_switch_delay_detect( - payload->workq_scheduled_ts); + cam_common_util_thread_switch_delay_detect( + "CDM workq schedule", + payload->workq_scheduled_ts, + CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status); if (payload->irq_status & diff --git a/drivers/cam_cdm/cam_cdm_virtual_core.c b/drivers/cam_cdm/cam_cdm_virtual_core.c index 481d37616c48..3f5a9a3e90f3 100644 --- a/drivers/cam_cdm/cam_cdm_virtual_core.c +++ b/drivers/cam_cdm/cam_cdm_virtual_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -20,6 +20,7 @@ #include "cam_cdm_soc.h" #include "cam_io_util.h" #include "cam_req_mgr_workq.h" +#include "cam_common_util.h" #define CAM_CDM_VIRTUAL_NAME "qcom,cam_virtual_cdm" @@ -34,8 +35,10 @@ static void cam_virtual_cdm_work(struct work_struct *work) cdm_hw = payload->hw; core = (struct cam_cdm *)cdm_hw->core_info; - cam_req_mgr_thread_switch_delay_detect( - payload->workq_scheduled_ts); + cam_common_util_thread_switch_delay_detect( + "Virtual CDM workq schedule", + payload->workq_scheduled_ts, + CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); if (payload->irq_status & 0x2) { struct cam_cdm_bl_cb_request_entry *node; diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 01a376dd51c1..15c96c66ae59 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -33,6 +33,7 @@ #include "cpastop_v680_100.h" #include "cpastop_v165_100.h" #include "cam_req_mgr_workq.h" +#include "cam_common_util.h" struct cam_camnoc_info *camnoc_info; struct cam_cpas_camnoc_qchannel *qchannel_info; @@ -598,8 +599,10 @@ static void cam_cpastop_work(struct work_struct *work) return; } - cam_req_mgr_thread_switch_delay_detect( - payload->workq_scheduled_ts); + cam_common_util_thread_switch_delay_detect( + "CPAS workq schedule", + payload->workq_scheduled_ts, + CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); cpas_hw = payload->hw; cpas_core = (struct cam_cpas *) cpas_hw->core_info; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c index 356c9a0a8919..cd9bd82c7938 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. */ #include @@ -11,8 +11,16 @@ #include "cam_tasklet_util.h" #include "cam_irq_controller.h" #include "cam_debug_util.h" +#include "cam_common_util.h" -#define CAM_TASKLETQ_SIZE 256 + +/* Threshold for scheduling delay in ms */ +#define CAM_TASKLET_SCHED_TIME_THRESHOLD 5 + +/* Threshold for execution delay in ms */ +#define CAM_TASKLET_EXE_TIME_THRESHOLD 10 + +#define CAM_TASKLETQ_SIZE 256 static void cam_tasklet_action(unsigned long data); @@ -27,6 +35,7 @@ static void cam_tasklet_action(unsigned long data); * @handler_priv: Private data passed at event subscribe * @bottom_half_handler: Function pointer for event handler in bottom * half context + * @tasklet_enqueue_ts: enqueue time of tasklet * */ struct cam_tasklet_queue_cmd { @@ -34,6 +43,7 @@ struct cam_tasklet_queue_cmd { void *payload; void *handler_priv; CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler; + ktime_t tasklet_enqueue_ts; }; /** @@ -209,6 +219,7 @@ void cam_tasklet_enqueue_cmd( tasklet_cmd->bottom_half_handler = bottom_half_handler; tasklet_cmd->payload = evt_payload_priv; tasklet_cmd->handler_priv = handler_priv; + tasklet_cmd->tasklet_enqueue_ts = ktime_get(); spin_lock_irqsave(&tasklet->tasklet_lock, flags); list_add_tail(&tasklet_cmd->list, &tasklet->used_cmd_list); @@ -322,12 +333,24 @@ static void cam_tasklet_action(unsigned long data) { struct cam_tasklet_info *tasklet_info = NULL; struct cam_tasklet_queue_cmd *tasklet_cmd = NULL; + ktime_t curr_time; tasklet_info = (struct cam_tasklet_info *)data; while (!cam_tasklet_dequeue_cmd(tasklet_info, &tasklet_cmd)) { + cam_common_util_thread_switch_delay_detect( + "Tasklet schedule", + tasklet_cmd->tasklet_enqueue_ts, + CAM_TASKLET_SCHED_TIME_THRESHOLD); + curr_time = ktime_get(); + tasklet_cmd->bottom_half_handler(tasklet_cmd->handler_priv, tasklet_cmd->payload); + + cam_common_util_thread_switch_delay_detect( + "Tasklet execution", + curr_time, + CAM_TASKLET_EXE_TIME_THRESHOLD); cam_tasklet_put_cmd(tasklet_info, (void **)(&tasklet_cmd)); } } diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.c b/drivers/cam_req_mgr/cam_req_mgr_workq.c index c2ed7f0d2c00..cfa7df88eef3 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.c +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.c @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include "cam_req_mgr_workq.h" #include "cam_debug_util.h" +#include "cam_common_util.h" #define WORKQ_ACQUIRE_LOCK(workq, flags) {\ if ((workq)->in_irq) \ @@ -94,6 +95,7 @@ void cam_req_mgr_process_workq(struct work_struct *w) struct crm_workq_task *task; int32_t i = CRM_TASK_PRIORITY_0; unsigned long flags = 0; + ktime_t curr_time; if (!w) { CAM_ERR(CAM_CRM, "NULL task pointer can not schedule"); @@ -102,7 +104,11 @@ void cam_req_mgr_process_workq(struct work_struct *w) workq = (struct cam_req_mgr_core_workq *) container_of(w, struct cam_req_mgr_core_workq, work); - cam_req_mgr_thread_switch_delay_detect(workq->workq_scheduled_ts); + cam_common_util_thread_switch_delay_detect( + "CRM workq schedule", + workq->workq_scheduled_ts, + CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); + curr_time = ktime_get(); while (i < CRM_TASK_PRIORITY_MAX) { WORKQ_ACQUIRE_LOCK(workq, flags); while (!list_empty(&workq->task.process_head[i])) { @@ -119,6 +125,10 @@ void cam_req_mgr_process_workq(struct work_struct *w) WORKQ_RELEASE_LOCK(workq, flags); i++; } + cam_common_util_thread_switch_delay_detect( + "CRM workq execution", + curr_time, + CAM_WORKQ_EXE_TIME_THRESHOLD); } int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, @@ -165,8 +175,8 @@ int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d", task, atomic_read(&workq->task.pending_cnt)); - workq->workq_scheduled_ts = ktime_get(); queue_work(workq->job, &workq->work); + workq->workq_scheduled_ts = ktime_get(); WORKQ_RELEASE_LOCK(workq, flags); end: return rc; @@ -267,25 +277,3 @@ void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq) *crm_workq = NULL; } } - -void cam_req_mgr_thread_switch_delay_detect(ktime_t workq_scheduled) -{ - uint64_t diff; - ktime_t cur_time; - struct timespec64 cur_ts; - struct timespec64 workq_scheduled_ts; - - cur_time = ktime_get(); - diff = ktime_ms_delta(cur_time, workq_scheduled); - workq_scheduled_ts = ktime_to_timespec64(workq_scheduled); - cur_ts = ktime_to_timespec64(cur_time); - - if (diff > CAM_WORKQ_RESPONSE_TIME_THRESHOLD) { - CAM_WARN_RATE_LIMIT(CAM_CRM, - "Workq delay detected %ld:%06ld %ld:%06ld %ld:", - workq_scheduled_ts.tv_sec, - workq_scheduled_ts.tv_nsec/NSEC_PER_USEC, - cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC, - diff); - } -} diff --git a/drivers/cam_req_mgr/cam_req_mgr_workq.h b/drivers/cam_req_mgr/cam_req_mgr_workq.h index 01e600ac3cb6..caef3c990586 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_workq.h +++ b/drivers/cam_req_mgr/cam_req_mgr_workq.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_WORKQ_H_ @@ -16,6 +16,12 @@ #include "cam_req_mgr_core.h" +/* Threshold for scheduling delay in ms */ +#define CAM_WORKQ_SCHEDULE_TIME_THRESHOLD 5 + +/* Threshold for execution delay in ms */ +#define CAM_WORKQ_EXE_TIME_THRESHOLD 10 + /* Flag to create a high priority workq */ #define CAM_WORKQ_FLAG_HIGH_PRIORITY (1 << 0) @@ -26,13 +32,6 @@ */ #define CAM_WORKQ_FLAG_SERIAL (1 << 1) -/* - * Response time threshold in ms beyond which it is considered - * as workq scheduling/processing delay. - */ -#define CAM_WORKQ_RESPONSE_TIME_THRESHOLD 5 - - /* Task priorities, lower the number higher the priority*/ enum crm_task_priority { CRM_TASK_PRIORITY_0, @@ -76,6 +75,7 @@ struct crm_workq_task { * @job : workqueue internal job struct * @lock_bh : lock for task structs * @in_irq : set true if workque can be used in irq context + * @workq_scheduled_ts: enqueue time of workq * task - * @lock : Current task's lock handle * @pending_cnt : # of tasks left in queue @@ -150,14 +150,6 @@ void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **workq); int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task, void *priv, int32_t prio); -/** - * cam_req_mgr_thread_switch_delay_detect() - * @brief: Detects if workq delay has occurred or not - * @timestamp: workq scheduled timestamp - */ -void cam_req_mgr_thread_switch_delay_detect( - ktime_t timestamp); - /** * cam_req_mgr_workq_get_task() * @brief: Returns empty task pointer for use diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index e4e185bb28c1..a9ff832eb5c2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -7,6 +7,7 @@ #include "cam_cci_core.h" #include "cam_cci_dev.h" #include "cam_req_mgr_workq.h" +#include "cam_common_util.h" static int32_t cam_cci_convert_type_to_num_bytes( enum camera_sensor_i2c_type type) @@ -1498,8 +1499,10 @@ static void cam_cci_write_async_helper(struct work_struct *work) enum cci_i2c_master_t master; struct cam_cci_master_info *cci_master_info; - cam_req_mgr_thread_switch_delay_detect( - write_async->workq_scheduled_ts); + cam_common_util_thread_switch_delay_detect( + "CCI workq schedule", + write_async->workq_scheduled_ts, + CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); cci_dev = write_async->cci_dev; i2c_msg = &write_async->c_ctrl.cfg.cci_i2c_write_cfg; master = write_async->c_ctrl.cci_info->cci_i2c_master; diff --git a/drivers/cam_sync/cam_sync_util.c b/drivers/cam_sync/cam_sync_util.c index 84d885c8109e..43e9709fca05 100644 --- a/drivers/cam_sync/cam_sync_util.c +++ b/drivers/cam_sync/cam_sync_util.c @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020-2021 The Linux Foundation. All rights reserved. */ #include "cam_sync_util.h" #include "cam_req_mgr_workq.h" +#include "cam_common_util.h" int cam_sync_util_find_and_set_empty_row(struct sync_device *sync_dev, long *idx) @@ -294,8 +295,10 @@ void cam_sync_util_cb_dispatch(struct work_struct *cb_dispatch_work) cb_dispatch_work); sync_callback sync_data = cb_info->callback_func; - cam_req_mgr_thread_switch_delay_detect( - cb_info->workq_scheduled_ts); + cam_common_util_thread_switch_delay_detect( + "CAM-SYNC workq schedule", + cb_info->workq_scheduled_ts, + CAM_WORKQ_SCHEDULE_TIME_THRESHOLD); sync_data(cb_info->sync_obj, cb_info->status, cb_info->cb_data); kfree(cb_info); diff --git a/drivers/cam_utils/cam_common_util.c b/drivers/cam_utils/cam_common_util.c index dbcb31d7bf0e..23681509f490 100644 --- a/drivers/cam_utils/cam_common_util.c +++ b/drivers/cam_utils/cam_common_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. */ #include @@ -48,3 +48,27 @@ uint32_t cam_common_util_remove_duplicate_arr(int32_t *arr, uint32_t num) return wr_idx; } + +void cam_common_util_thread_switch_delay_detect( + const char *token, ktime_t scheduled_time, uint32_t threshold) +{ + uint64_t diff; + ktime_t cur_time; + struct timespec64 cur_ts; + struct timespec64 scheduled_ts; + + cur_time = ktime_get(); + diff = ktime_ms_delta(cur_time, scheduled_time); + + if (diff > threshold) { + scheduled_ts = ktime_to_timespec64(scheduled_time); + cur_ts = ktime_to_timespec64(cur_time); + CAM_WARN_RATE_LIMIT_CUSTOM(CAM_UTIL, 1, 1, + "%s delay detected %ld:%06ld cur %ld:%06ld diff %ld: threshold %d", + token, scheduled_ts.tv_sec, + scheduled_ts.tv_nsec/NSEC_PER_USEC, + cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC, + diff, threshold); + } + +} diff --git a/drivers/cam_utils/cam_common_util.h b/drivers/cam_utils/cam_common_util.h index 5bf20501af2e..60fd2f629c3d 100644 --- a/drivers/cam_utils/cam_common_util.h +++ b/drivers/cam_utils/cam_common_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_COMMON_UTIL_H_ @@ -64,4 +64,17 @@ int cam_common_util_get_string_index(const char **strings, uint32_t cam_common_util_remove_duplicate_arr(int32_t *array, uint32_t num); +/** + * cam_common_util_thread_switch_delay_detect() + * + * @brief Detect if there is any scheduling delay + * + * @token: String identifier to print workq name or tasklet + * @scheduled_time: Time when workq or tasklet was scheduled + * @threshold: Threshold time + * + */ +void cam_common_util_thread_switch_delay_detect(const char *token, + ktime_t scheduled_time, uint32_t threshold); + #endif /* _CAM_COMMON_UTIL_H_ */ From 84373dc0398b6e31fb31fe8a3c574d3ab19ee84a Mon Sep 17 00:00:00 2001 From: Tony Lijo Jose Date: Thu, 24 Jun 2021 12:26:59 +0530 Subject: [PATCH 767/790] msm: camera: csiphy: Publish rx clock to other subnodes Currently we are publishing csiphy timer clock to other submodules who needs to maintain the clock ratio between the submodules. This change changes it publish the phy_rx clock as the phy clock rate. CRs-Fixed: 2975394 Change-Id: I7331d66ebdd1e6ded0d5ac7dd6f47b4c42c2b06f Signed-off-by: Tony Lijo Jose --- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index f6040e720a69..e54335e97996 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -205,7 +205,7 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index) rc = cam_soc_util_set_src_clk_rate(soc_info, soc_info->clk_rate[0][soc_info->src_clk_idx]); clk_rate = cam_soc_util_get_clk_rate_applied(soc_info, - soc_info->src_clk_idx, true, vote_level); + csiphy_dev->rx_clk_src_idx, true, vote_level); cam_subdev_notify_message(CAM_TFE_DEVICE_TYPE, CAM_SUBDEV_MESSAGE_CLOCK_UPDATE, clk_rate); From a3589a0965e84733c6ae2d817046e219d42ce640 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 30 Jun 2021 18:12:27 +0530 Subject: [PATCH 768/790] msm: camera: reqmgr: check link state before taking mutex In case if the destroy session is processed first it will as a part of unlink try to drain the work queue. This will schedule all the enqueued wq. Workqueue when scheduled try to acquire same mutex destroy session has already acquried this will lead to dead-lock. To avoid that, check the link state first if it is in idle state then return from the workqueue without trying to acquire mutex. CRs-Fixed: 2976325 Change-Id: I57a53455c69e5f4f38c92413f9d1b7f2d06c9960 Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_req_mgr_core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index c7d6e8252b02..e1e5cbe00083 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1714,6 +1714,19 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, return -EINVAL; } + /* + * In case if the wq is scheduled while destroying session + * the session mutex is already taken and will cause a + * dead lock. To avoid further processing check link state + * and exit. + */ + spin_lock_bh(&link->link_state_spin_lock); + if (link->state == CAM_CRM_LINK_STATE_IDLE) { + spin_unlock_bh(&link->link_state_spin_lock); + return -EPERM; + } + spin_unlock_bh(&link->link_state_spin_lock); + mutex_lock(&session->lock); in_q = link->req.in_q; /* From 9c2449a015df555fbfaeae3c130a63ad8acd4548 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Thu, 8 Jul 2021 10:55:02 +0530 Subject: [PATCH 769/790] msm: camera: csiphy: Update PHY setting in 1+1 combo mode Enable FORCE_TERM_EN for LN6 in 1+1 combo mode. Change-Id: I2a23b2f5cb04102e1268a749ec5ca055da9c719a CRs-Fixed: 2986671 Signed-off-by: Anil Kumar Kanakanti --- .../cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index 3881b21bfab8..22debd87d6c5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -275,7 +275,7 @@ struct csiphy_reg_t {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, From 1972aa1c0ec3eded6e16c5a8020e15504541665a Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Wed, 30 Jun 2021 18:12:27 +0530 Subject: [PATCH 770/790] msm: camera: reqmgr: check link state before taking mutex In case if the destroy session is processed first it will as a part of unlink try to drain the work queue. This will schedule all the enqueued wq. Workqueue when scheduled try to acquire same mutex destroy session has already acquried this will lead to dead-lock. To avoid that, check the link state first if it is in idle state then return from the workqueue without trying to acquire mutex. CRs-Fixed: 2976325 Change-Id: I57a53455c69e5f4f38c92413f9d1b7f2d06c9960 Signed-off-by: Tejas Prajapati --- drivers/cam_req_mgr/cam_req_mgr_core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index c7d6e8252b02..e1e5cbe00083 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1714,6 +1714,19 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, return -EINVAL; } + /* + * In case if the wq is scheduled while destroying session + * the session mutex is already taken and will cause a + * dead lock. To avoid further processing check link state + * and exit. + */ + spin_lock_bh(&link->link_state_spin_lock); + if (link->state == CAM_CRM_LINK_STATE_IDLE) { + spin_unlock_bh(&link->link_state_spin_lock); + return -EPERM; + } + spin_unlock_bh(&link->link_state_spin_lock); + mutex_lock(&session->lock); in_q = link->req.in_q; /* From 1666f6b6d481707a4b3b201f8944b2e6182a7eb4 Mon Sep 17 00:00:00 2001 From: zhuo Date: Fri, 9 Jul 2021 14:52:29 +0800 Subject: [PATCH 771/790] msm: camera: common: Change judgement condition Icc_get return value is IS_ERR type, so the commit change the judgement condition. CRs-Fixed: 2988670 Change-Id: I2c3375922bc42b598aa8872c756a47e881ccb80c Signed-off-by: zhuo --- drivers/cam_utils/cam_soc_icc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index c6b405b509c5..707ba5ab790d 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -103,7 +103,7 @@ int cam_soc_bus_client_register(struct platform_device *pdev, bus_client_data->icc_data = icc_get(&pdev->dev, bus_client->common_data->src_id, bus_client->common_data->dst_id); - if (!bus_client_data->icc_data) { + if (IS_ERR_OR_NULL(bus_client_data->icc_data)) { CAM_ERR(CAM_UTIL, "failed in register bus client"); rc = -EINVAL; goto error; From 8df447806563780219602a14ceaf5ee7f8526fd4 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 22 Jul 2021 12:16:32 +0530 Subject: [PATCH 772/790] msm: camera: cpas: Enable Priority LUT for Blair OPE This change is to enable priority lut QoS settings in OPE Hw for Blair Camera. CRs-Fixed: 2944976 Change-Id: Icb7b457b96698669a260a589fb445e246a8d100a Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cpastop_v545_110.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_110.h b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h index d8833047c250..4a2509507acc 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v545_110.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h @@ -250,14 +250,14 @@ static struct cam_camnoc_specific .port_type = CAM_CAMNOC_OPE, .enable = true, .priority_lut_low = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ .value = 0x33333333, }, .priority_lut_high = { - .enable = false, + .enable = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ From 496cf578aad6c21c09bcab2f476734797e4aa373 Mon Sep 17 00:00:00 2001 From: Sujit Das Date: Thu, 22 Jul 2021 11:53:55 +0530 Subject: [PATCH 773/790] msm: camera: ife: Null pointer check for dump_data When pipeline is IFE_Lite and IFE_LITE doesn't define dump_data, Need to have null check for dump_data. CRs-Fixed: 2980840 Change-Id: Icb3322b82b265829e4a54271fa30260a00f90175 Signed-off-by: Sujit Das --- .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 44edd50295de..ba17011c61b3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -405,6 +405,12 @@ static int cam_vfe_hw_dump( return -ENOSPC; } dump_data = top_priv->common_data.dump_data; + + if (!dump_data) { + CAM_ERR(CAM_ISP, "Dump data not available"); + return -EINVAL; + } + soc_info = top_priv->common_data.soc_info; /*Dump registers */ From 672b8abddef65b5670dfc1464f7f17b33ccb4db0 Mon Sep 17 00:00:00 2001 From: Shravan Nevatia Date: Thu, 15 Jul 2021 12:22:32 +0530 Subject: [PATCH 774/790] msm: camera: csiphy: Update csiphy-v1.2.3 CPHY sequences Update the CPHY sequences to align to HPG rev X. Data rate: <=1.9Gsps 1.9Gsps->3Gsps >3Gsps 144/344/544 0x22 0xA2 0xA2 988/A88/B88 0 5 5 980/A80/B80 0 0x61 0x61 9B4/AB4/BB4 8 8 4. CRs-Fixed: 3000765 Change-Id: I6cda0471399c5724a6b9e50a175fc5b69a72b025 Signed-off-by: Shravan Nevatia --- .../cam_csiphy/cam_csiphy_dev.h | 2 +- .../include/cam_csiphy_1_2_3_hwreg.h | 111 +++++++++++++++--- 2 files changed, 96 insertions(+), 17 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 59f8b92936d9..0a16b75595d9 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -34,7 +34,7 @@ #define MAX_LANES 5 #define MAX_SETTINGS_PER_LANE 43 -#define MAX_DATA_RATES 3 +#define MAX_DATA_RATES 4 #define MAX_DATA_RATE_REGS 30 #define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver" diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index 2c39d9d188f1..aaa8bae0b667 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -16,7 +16,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .csiphy_common_array_size = 5, .csiphy_reset_array_size = 2, .csiphy_2ph_config_array_size = 16, - .csiphy_3ph_config_array_size = 31, + .csiphy_3ph_config_array_size = 28, .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, @@ -261,14 +261,11 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0980, 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -294,14 +291,11 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A80, 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -327,30 +321,29 @@ csiphy_reg_t csiphy_3ph_v1_2_3_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B80, 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; struct data_rate_settings_t data_rate_delta_table_1_2_3 = { - .num_data_rate_settings = 3, + .num_data_rate_settings = 4, .data_rate_settings = { { - /* (2.5 * 10**3 * 2.28) rounded value*/ - .bandwidth = 5700000000, - .data_rate_reg_array_size = 1, + /* (1.9 * 10**3 * 2.28) rounded value*/ + .bandwidth = 4332000000, + .data_rate_reg_array_size = 2, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { + {0x144, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x08, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -358,6 +351,8 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { + {0x344, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x08, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -365,6 +360,54 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { + {0x544, 0x22, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x08, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, + }, + { + /* (3 * 10**3 * 2.28) rounded value */ + .bandwidth = 6840000000, + .data_rate_reg_array_size = 4, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x144, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x08, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x344, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x08, 0x0A, + CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x544, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x08, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -374,11 +417,17 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 1, + .data_rate_reg_array_size = 4, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { + {0x144, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -386,6 +435,12 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { + {0x344, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -393,6 +448,12 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { + {0x544, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -402,11 +463,17 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 1, + .data_rate_reg_array_size = 4, .per_lane_info = { { .lane_identifier = CPHY_LANE_0, .csiphy_data_rate_regs = { + {0x144, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x988, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0x980, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -414,6 +481,12 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_1, .csiphy_data_rate_regs = { + {0x344, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xA80, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, @@ -421,6 +494,12 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = { { .lane_identifier = CPHY_LANE_2, .csiphy_data_rate_regs = { + {0x544, 0xA2, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB88, 0x05, 0x00, + CSIPHY_DEFAULT_PARAMS}, + {0xB80, 0x61, 0x00, + CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x04, 0x0A, CSIPHY_DEFAULT_PARAMS}, }, From f1f8fc1c9356eef29ca568b48157c6a392278f56 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 20 Jul 2021 12:35:14 +0800 Subject: [PATCH 775/790] msm: camera: cci: Enhance burst read timing In burst read flow, we need to wait CCI irq once one set data is read, but the fifo may has new data what can be read immediately and don't need to wait the irq. This change also optimize the irq processing, we can reset irq mask first, then process the irq status, it can avoids some timing issue, e.g. the read context runs too quickly, then read context enable the read threshold bit in irq mask1, but irq context runs late, then irq context clear the read threshold, then we can't receive read threshold again. CRs-Fixed: 2995920 Change-Id: I8acfadf07b95782725bf4bf8b05b88789874c1da Signed-off-by: Depeng Shao --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 75 ++++++----- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 117 +++++++++--------- 2 files changed, 100 insertions(+), 92 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index a9ff832eb5c2..bf4a2b975121 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1119,46 +1119,53 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, goto rel_mutex_q; } - read_words = cam_io_r_mb(base + - CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); - if (read_words <= 0) { - CAM_DBG(CAM_CCI, "FIFO Buffer lvl is 0"); - continue; - } - - j++; - CAM_DBG(CAM_CCI, "Iteration: %u read_words %d", j, read_words); - - total_read_words += read_words; - while (read_words > 0) { - val = cam_io_r_mb(base + - CCI_I2C_M0_READ_DATA_ADDR + master * 0x100); - for (i = 0; (i < 4) && - (index < read_cfg->num_byte); i++) { - CAM_DBG(CAM_CCI, "i:%d index:%d", i, index); - if (!first_byte) { - CAM_DBG(CAM_CCI, "sid 0x%x", - val & 0xFF); - first_byte++; - } else { - read_cfg->data[index] = - (val >> (i * 8)) & 0xFF; - CAM_DBG(CAM_CCI, "data[%d] 0x%x", index, - read_cfg->data[index]); - index++; - } + while (true) { + read_words = cam_io_r_mb(base + + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + + master * 0x100); + if (read_words <= 0) { + CAM_DBG(CAM_CCI, "FIFO Buffer lvl is 0"); + break; } - read_words--; - } - CAM_DBG(CAM_CCI, "Iteraion:%u total_read_words %d", - j, total_read_words); + j++; + CAM_DBG(CAM_CCI, "Iteration: %u read_words %d", + j, read_words); + + total_read_words += read_words; + while (read_words > 0) { + val = cam_io_r_mb(base + + CCI_I2C_M0_READ_DATA_ADDR + + master * 0x100); + for (i = 0; (i < 4) && + (index < read_cfg->num_byte); i++) { + CAM_DBG(CAM_CCI, "i:%d index:%d", + i, index); + if (!first_byte) { + CAM_DBG(CAM_CCI, "sid 0x%x", + val & 0xFF); + first_byte++; + } else { + read_cfg->data[index] = + (val >> (i * 8)) & 0xFF; + CAM_DBG(CAM_CCI, "data[%d] 0x%x", + index, + read_cfg->data[index]); + index++; + } + } + read_words--; + } + + CAM_DBG(CAM_CCI, + "Iteration:%u total_read_words %d", + j, total_read_words); + } spin_lock_irqsave(&cci_dev->lock_status, flags); if (cci_dev->irqs_disabled) { irq_mask_update = - cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR) | - CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR); if (master == MASTER_0 && cci_dev->irqs_disabled & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) irq_mask_update |= diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index e496ca83cf65..28b76aef1c12 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -77,6 +77,65 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) "BASE: %pK, irq0:%x irq1:%x", base, irq_status0, irq_status1); + cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); + cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR); + + reg_bmsk = CCI_IRQ_MASK_1_RMSK; + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && + !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK)) { + reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + spin_lock_irqsave(&cci_dev->lock_status, flags); + cci_dev->irqs_disabled |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && + !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK)) { + reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + spin_lock_irqsave(&cci_dev->lock_status, flags); + cci_dev->irqs_disabled |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + + if (reg_bmsk != CCI_IRQ_MASK_1_RMSK) { + cam_io_w_mb(reg_bmsk, base + CCI_IRQ_MASK_1_ADDR); + CAM_DBG(CAM_CCI, "Updating the reg mask for irq1: 0x%x", + reg_bmsk); + } else if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK || + irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) { + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) { + irq_update_rd_done |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + cci_dev->irqs_disabled &= + ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) { + irq_update_rd_done |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + cci_dev->irqs_disabled &= + ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + } + + if (irq_update_rd_done != 0) { + irq_update_rd_done |= cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(irq_update_rd_done, base + CCI_IRQ_MASK_1_ADDR); + } + + cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); + if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { struct cam_cci_master_info *cci_master_info; if (cci_dev->cci_master_info[MASTER_0].reset_pending == true) { @@ -293,64 +352,6 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR); } - cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); - - reg_bmsk = CCI_IRQ_MASK_1_RMSK; - if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && - !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK)) { - reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; - spin_lock_irqsave(&cci_dev->lock_status, flags); - cci_dev->irqs_disabled |= - CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; - spin_unlock_irqrestore(&cci_dev->lock_status, flags); - } - - if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && - !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK)) { - reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; - spin_lock_irqsave(&cci_dev->lock_status, flags); - cci_dev->irqs_disabled |= - CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; - spin_unlock_irqrestore(&cci_dev->lock_status, flags); - } - - if (reg_bmsk != CCI_IRQ_MASK_1_RMSK) { - cam_io_w_mb(reg_bmsk, base + CCI_IRQ_MASK_1_ADDR); - CAM_DBG(CAM_CCI, "Updating the reg mask for irq1: 0x%x", - reg_bmsk); - } else if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK || - irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { - if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) { - spin_lock_irqsave(&cci_dev->lock_status, flags); - if (cci_dev->irqs_disabled & - CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) { - irq_update_rd_done |= - CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; - cci_dev->irqs_disabled &= - ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; - } - spin_unlock_irqrestore(&cci_dev->lock_status, flags); - } - if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { - spin_lock_irqsave(&cci_dev->lock_status, flags); - if (cci_dev->irqs_disabled & - CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) { - irq_update_rd_done |= - CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; - cci_dev->irqs_disabled &= - ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; - } - spin_unlock_irqrestore(&cci_dev->lock_status, flags); - } - } - - if (irq_update_rd_done != 0) { - irq_update_rd_done |= cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR); - cam_io_w_mb(irq_update_rd_done, base + CCI_IRQ_MASK_1_ADDR); - } - - cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR); - cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); return IRQ_HANDLED; } From a84ec521b54ec1d69b689281181476cf2c3181c8 Mon Sep 17 00:00:00 2001 From: zhuo Date: Mon, 22 Mar 2021 12:32:30 +0800 Subject: [PATCH 776/790] msm: camera: csiphy: Add csiphy header file delta This change add csiphy header file delta from camera-kernel.3.1 to camera-kernel.4.0. CRs-Fixed: 2998514 Change-Id: I802b25fe3939edb5294536f2e26307105c6667f0 Signed-off-by: zhuo --- .../cam_csiphy/cam_csiphy_soc.c | 2 +- .../cam_csiphy/include/cam_csiphy_2_0_hwreg.h | 59 ++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index e54335e97996..abd9acc0fce0 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -481,7 +481,7 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; csiphy_dev->is_divisor_32_comp = false; csiphy_dev->clk_lane = 0; - csiphy_dev->ctrl_reg->data_rates_settings_table = NULL; + csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_2_0; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.1.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_1_0_reg; diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h index f7be2b60a4b5..45e7a6235857 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_2_0_HWREG_H_ @@ -291,4 +291,61 @@ struct csiphy_reg_t csiphy_3ph_v2_0_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { }, }; +struct data_rate_settings_t data_rate_delta_table_2_0 = { + .num_data_rate_settings = 2, + .data_rate_settings = { + { + /* (2 * 10**9 * 2.28) rounded value*/ + .bandwidth = 4560000000, + .data_rate_reg_array_size = 1, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x164, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x364, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x564, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, + }, + { + /* (2.5 * 10**9 * 2.28) rounded value*/ + .bandwidth = 5700000000, + .data_rate_reg_array_size = 1, + .per_lane_info = { + { + .lane_identifier = CPHY_LANE_0, + .csiphy_data_rate_regs = { + {0x164, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_1, + .csiphy_data_rate_regs = { + {0x364, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + { + .lane_identifier = CPHY_LANE_2, + .csiphy_data_rate_regs = { + {0x564, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + }, + }, + }, + }, + +}; + #endif /* _CAM_CSIPHY_2_0_HWREG_H_ */ From 2f0fa5b4cd1735346b396d0eb98c49ecca46f14a Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Wed, 28 Jul 2021 19:17:52 +0530 Subject: [PATCH 777/790] msm: camera: isp: Correct error check in clock rate assignment Error check is not proper while assigning clock rates. this is causing failure on updated clock rates. CRs-Fixed: 2998722 Change-Id: Id8634438a7930362e4b8eb010b523dc2def1f043 Signed-off-by: Alok Chauhan --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index d3e2b3d24cf9..f947249cd129 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1965,6 +1965,12 @@ int cam_tfe_cshiphy_callback( &ctx->res_list_tfe_csid, list) { rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, phy_clock_rate, &updated_csid_clk); + if (rc) { + CAM_ERR(CAM_ISP, + "csid clock update failed: %d, csid:%lld tfe:%lld", + rc, csid_clock_rate, tfe_clock_rate); + goto end; + } } if (updated_csid_clk > tfe_clock_rate) { @@ -1972,9 +1978,15 @@ int cam_tfe_cshiphy_callback( &ctx->res_list_tfe_in, list) { rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, &updated_csid_clk, &updated_tfe_clk); + if (rc) { + CAM_ERR(CAM_ISP, + "tfe clock update failed: %d, csid:%lld tfe:%lld", + rc, updated_csid_clk, tfe_clock_rate); + goto end; + } } } - goto end; + goto skip_tfe_update; } if (csid_clock_rate > tfe_clock_rate) { @@ -1982,9 +1994,16 @@ int cam_tfe_cshiphy_callback( &ctx->res_list_tfe_in, list) { rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, &csid_clock_rate, &updated_tfe_clk); + if (rc) { + CAM_ERR(CAM_ISP, + "tfe clock update failed: %d, csid:%lld tfe:%lld", + rc, csid_clock_rate, tfe_clock_rate); + goto end; + } } } +skip_tfe_update: if (!updated_csid_clk) updated_csid_clk = csid_clock_rate; From 3cc02962410d95ec7f3da5d1ca075923fb8d289f Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 2 Aug 2021 20:28:17 +0530 Subject: [PATCH 778/790] msm: camera: cpas: Support OT enablement through Fuse This change is to support enable and disable of OT values for real time block through fuse. CRs-Fixed: 2924987 Change-Id: If4c6b89cafd517a5c6f7706bf65cc0a47ecdc62e Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cam_cpas_hw.c | 6 +- drivers/cam_cpas/cam_cpas_hw.h | 4 +- drivers/cam_cpas/cpas_top/cpastop100.h | 37 ++++- drivers/cam_cpas/cpas_top/cpastop_v150_100.h | 35 ++++- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 48 +++++++ drivers/cam_cpas/cpas_top/cpastop_v170_110.h | 38 ++++- drivers/cam_cpas/cpas_top/cpastop_v170_200.h | 37 +++++ drivers/cam_cpas/cpas_top/cpastop_v175_100.h | 39 +++++- drivers/cam_cpas/cpas_top/cpastop_v175_101.h | 39 +++++- drivers/cam_cpas/cpas_top/cpastop_v175_120.h | 63 ++++++++- drivers/cam_cpas/cpas_top/cpastop_v175_130.h | 63 ++++++++- drivers/cam_cpas/cpas_top/cpastop_v480_100.h | 63 ++++++++- .../cam_cpas/cpas_top/cpastop_v480_custom.h | 63 ++++++++- drivers/cam_cpas/cpas_top/cpastop_v520_100.h | 20 ++- drivers/cam_cpas/cpas_top/cpastop_v520_110.h | 18 +++ drivers/cam_cpas/cpas_top/cpastop_v540_100.h | 20 ++- drivers/cam_cpas/cpas_top/cpastop_v545_100.h | 30 +++- drivers/cam_cpas/cpas_top/cpastop_v545_110.h | 28 ++++ drivers/cam_cpas/cpas_top/cpastop_v570_200.h | 85 +++++++++++ drivers/cam_cpas/cpas_top/cpastop_v580_100.h | 105 +++++++++++++- .../cam_cpas/cpas_top/cpastop_v580_custom.h | 105 +++++++++++++- drivers/cam_cpas/cpas_top/cpastop_v680_100.h | 132 +++++++++++++++++- 22 files changed, 1061 insertions(+), 17 deletions(-) diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 2119e1b6885b..15623b525e55 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -112,6 +112,10 @@ int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw, if (reg_info->enable == false) return 0; + if (reg_info->is_fuse_based && + !cam_cpas_is_feature_supported(CAM_CPAS_RT_OT_FUSE, 0xFF, 0)) + return 0; + reg_base_index = cpas_core->regbase_index[reg_base]; if (reg_base_index == -1) return -EINVAL; diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index a7c7f429ccc2..086dce12a2be 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_H_ @@ -94,6 +94,7 @@ struct cam_cpas_internal_ops { * struct cam_cpas_reg : CPAS register info * * @enable: Whether this reg info need to be enabled + * @is_fuse_based : Whether this reg info need to be enabled based on fuse * @access_type: Register access type * @masked_value: Whether this register write/read is based on mask, shift * @mask: Mask for this register value @@ -103,6 +104,7 @@ struct cam_cpas_internal_ops { */ struct cam_cpas_reg { bool enable; + bool is_fuse_based; enum cam_cpas_access_type access_type; bool masked_value; uint32_t offset; diff --git a/drivers/cam_cpas/cpas_top/cpastop100.h b/drivers/cam_cpas/cpas_top/cpastop100.h index 2f444710e9f4..7707f7b27b70 100644 --- a/drivers/cam_cpas/cpas_top/cpastop100.h +++ b/drivers/cam_cpas/cpas_top/cpastop100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP100_H_ @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ @@ -227,6 +230,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -234,6 +238,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -248,6 +253,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ @@ -255,6 +261,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ @@ -262,6 +269,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ @@ -273,18 +281,21 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ .value = 0x3, }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ @@ -296,6 +307,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ @@ -303,6 +315,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ @@ -310,6 +323,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ @@ -321,18 +335,21 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ .value = 0x3, }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */ @@ -344,6 +361,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -351,6 +369,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -358,6 +377,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -369,6 +389,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -376,6 +397,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -383,6 +405,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -394,6 +417,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -401,6 +425,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -408,6 +433,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -419,6 +445,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -426,6 +453,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -433,6 +461,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -444,6 +473,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -451,6 +481,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -458,6 +489,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -465,6 +497,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -472,6 +505,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -479,6 +513,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { diff --git a/drivers/cam_cpas/cpas_top/cpastop_v150_100.h b/drivers/cam_cpas/cpas_top/cpastop_v150_100.h index edad15043dda..771c6e5610ff 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v150_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v150_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V150_100_H_ @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ @@ -227,6 +230,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -234,6 +238,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -248,6 +253,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ @@ -255,6 +261,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ @@ -262,6 +269,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ @@ -273,12 +281,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ .value = 0x1, @@ -292,6 +302,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ @@ -299,6 +310,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ @@ -306,6 +318,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ @@ -317,12 +330,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ .value = 0x1, @@ -336,6 +351,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -343,6 +359,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -350,6 +367,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -361,6 +379,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -368,6 +387,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -375,6 +395,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -386,6 +407,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -393,6 +415,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -400,6 +423,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -411,6 +435,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -418,6 +443,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -425,6 +451,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -436,6 +463,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -443,6 +471,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -450,6 +479,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -457,6 +487,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -464,6 +495,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -482,6 +514,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 9dc47566bb37..6bffe5026cbb 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4230, /* CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4234, /* CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* CDM_Urgency_Low */ .offset = 0x4238, @@ -227,6 +230,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4240, /* CDM_DANGERLUT_LOW */ @@ -234,6 +238,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4248, /* CDM_SAFELUT_LOW */ @@ -248,6 +253,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3630, /* IFE01234_RDI_PRIORITYLUT_LOW */ @@ -255,6 +261,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3634, /* IFE01234_RDI_PRIORITYLUT_HIGH */ @@ -262,6 +269,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3638, /* IFE01234_RDI_LINEAR_URGENCY_LOW */ @@ -271,12 +279,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3640, /* IFE01234_RDI_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3648, /* IFE01234_RDI_SAFELUT_LOW */ .value = 0x000F, @@ -291,6 +301,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4808, /* IFE01234_RDI_QOSGEN_MAINCTL */ @@ -298,6 +309,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4820, /* IFE01234_RDI_QOSGEN_SHAPING_LOW */ @@ -305,6 +317,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4824, /* IFE01234_RDI_QOSGEN_SHAPING_HIGH */ @@ -316,6 +329,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3A30, /* IFE01_NRDI_PRIORITYLUT_LOW */ @@ -323,6 +337,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3A34, /* IFE01_NRDI_PRIORITYLUT_HIGH */ @@ -330,6 +345,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3A38, /* IFE01_NRDI_URGENCY_LOW */ @@ -341,12 +357,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3A40, /* IFE01_NRDI_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3A48, /* IFE01_NRDI_SAFELUT_LOW */ .value = 0xF, @@ -366,6 +384,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4708, /* IFE01_NRDI_QOSGEN_MAINCTL */ @@ -373,6 +392,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4720, /* IFE01_NRDI_QOSGEN_SHAPING_LOW */ @@ -380,6 +400,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4724, /* IFE01_NRDI_QOSGEN_SHAPING_HIGH */ @@ -391,6 +412,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5430, /* IFE2_NDRI_PRIORITYLUT_LOW */ @@ -398,6 +420,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* IFE2_NRDI_PRIORITYLUT_HIGH */ @@ -406,6 +429,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x5438, /* IFE2_NRDI_URGENCY_LOW */ @@ -417,12 +441,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5440, /* IFE2_NRDI_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5448, /* IFE2_NRDI_SAFELUT_LOW */ .value = 0xF, @@ -441,6 +467,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5188, /* IFE2_NRDI_QOSGEN_MAINCTL */ @@ -448,6 +475,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x51A0, /* IFE2_NRDI_QOSGEN_SHAPING_LOW */ @@ -455,6 +483,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = true, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x51A4, /* IFE2_NRDI_QOSGEN_SHAPING_HIGH */ @@ -466,6 +495,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* IPE_BPS_LRME_RD_PRIORITYLUT_LOW */ @@ -473,6 +503,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* IPE_BPS_LRME_RD_PRIORITYLUT_HIGH */ @@ -480,6 +511,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2E38, /* IPE_BPS_LRME_RD_URGENCY_LOW */ @@ -491,6 +523,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* IPE_BPS_LRME_RD_DANGERLUT_LOW */ @@ -498,6 +531,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* IPE_BPS_LRME_RD_SAFELUT_LOW */ @@ -510,6 +544,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2F08, /* IPE_BPS_LRME_RD_DECCTL_LOW */ @@ -521,6 +556,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A30, /* IPE_BPS_LRME_WR_PRIORITYLUT_LOW */ @@ -528,6 +564,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A34, /* IPE_BPS_LRME_WR_PRIORITYLUT_HIGH */ @@ -535,6 +572,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2A38, /* IPE_BPS_LRME_WR_URGENCY_LOW */ @@ -546,6 +584,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A40, /* IPE_BPS_LRME_WR_DANGERLUT_LOW */ @@ -553,6 +592,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A48, /* IPE_BPS_LRME_WR_SAFELUT_LOW */ @@ -565,6 +605,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2B88, /* IPE_BPS_LRME_WR_ENCCTL_LOW */ @@ -576,6 +617,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2630, /* JPEG_PRIORITYLUT_LOW */ @@ -583,6 +625,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2634, /* JPEG_PRIORITYLUT_HIGH */ @@ -590,6 +633,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2638, /* JPEG_URGENCY_LOW */ @@ -599,6 +643,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2640, /* JPEG_DANGERLUT_LOW */ @@ -606,6 +651,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2648, /* JPEG_SAFELUT_LOW */ @@ -613,6 +659,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -621,6 +668,7 @@ static struct cam_camnoc_specific .enable = false, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x5088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/cam_cpas/cpas_top/cpastop_v170_110.h index fc986f598e33..0883541fc72a 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v170_110.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v170_110.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V170_110_H_ @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ @@ -227,6 +230,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -234,6 +238,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -248,6 +253,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ @@ -255,6 +261,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ @@ -262,6 +269,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ @@ -273,18 +281,21 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ .value = 0x1, }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ @@ -296,6 +307,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ @@ -303,6 +315,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ @@ -310,6 +323,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ @@ -321,18 +335,21 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ .value = 0x1, }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */ @@ -344,6 +361,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -351,6 +369,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -358,6 +377,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -369,6 +389,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -376,6 +397,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -383,6 +405,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -394,6 +417,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -401,6 +425,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -408,6 +433,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -419,6 +445,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -426,6 +453,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -433,6 +461,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -444,6 +473,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -451,6 +481,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -458,6 +489,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -465,6 +497,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -472,6 +505,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -479,6 +513,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -490,6 +525,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v170_200.h b/drivers/cam_cpas/cpas_top/cpastop_v170_200.h index 3827e8dfff68..5994097559bb 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v170_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v170_200.h @@ -206,6 +206,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -213,6 +214,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -220,6 +222,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ @@ -229,6 +232,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -236,6 +240,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -243,6 +248,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -250,6 +256,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ @@ -257,6 +264,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ @@ -264,6 +272,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ @@ -275,18 +284,21 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ .value = 0x1, }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ @@ -298,6 +310,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ @@ -305,6 +318,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ @@ -312,6 +326,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ @@ -323,18 +338,21 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ .value = 0x1, }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */ @@ -346,6 +364,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -353,6 +372,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -360,6 +380,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -371,6 +392,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -378,6 +400,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -385,6 +408,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -396,6 +420,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -403,6 +428,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -410,6 +436,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -421,6 +448,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -428,6 +456,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -435,6 +464,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -446,6 +476,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -453,6 +484,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -460,6 +492,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -467,6 +500,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -474,6 +508,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -481,6 +516,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -492,6 +528,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_100.h b/drivers/cam_cpas/cpas_top/cpastop_v175_100.h index ab20db01cd18..257891195c48 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_100_H_ @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ @@ -227,6 +230,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -234,6 +238,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -241,6 +246,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -248,6 +254,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ @@ -255,6 +262,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ @@ -262,6 +270,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ @@ -273,12 +282,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ .value = 0x1, @@ -290,6 +301,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ @@ -301,6 +313,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ @@ -308,6 +321,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ @@ -315,6 +329,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ @@ -326,12 +341,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ .value = 0x1, @@ -343,6 +360,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */ @@ -354,6 +372,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -361,6 +380,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -368,6 +388,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -379,6 +400,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -386,6 +408,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -398,6 +421,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -409,6 +433,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -416,6 +441,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -423,6 +449,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -434,6 +461,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -441,6 +469,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -453,6 +482,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -464,6 +494,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -471,6 +502,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -478,6 +510,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -485,6 +518,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -492,6 +526,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -499,6 +534,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -510,6 +546,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_101.h b/drivers/cam_cpas/cpas_top/cpastop_v175_101.h index 12ed226008e6..e4e433f71fe0 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_101.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_101.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_101_H_ @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ @@ -227,6 +230,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -234,6 +238,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -241,6 +246,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -248,6 +254,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ @@ -255,6 +262,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ @@ -262,6 +270,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ @@ -273,12 +282,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ .value = 0x1, @@ -290,6 +301,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */ @@ -301,6 +313,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ @@ -308,6 +321,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ @@ -315,6 +329,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ @@ -326,12 +341,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ .value = 0x1, @@ -343,6 +360,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */ @@ -354,6 +372,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -361,6 +380,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -368,6 +388,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -379,6 +400,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -386,6 +408,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -398,6 +421,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -409,6 +433,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -416,6 +441,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -423,6 +449,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -434,6 +461,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -441,6 +469,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -453,6 +482,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -464,6 +494,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -471,6 +502,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -478,6 +510,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -485,6 +518,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -492,6 +526,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -499,6 +534,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -510,6 +546,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_120.h b/drivers/cam_cpas/cpas_top/cpastop_v175_120.h index 83e5fb415472..38ed54413877 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_120.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_120.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_120_H_ @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4230, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4234, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, /* cdm_main_SpecificToNttpTr_Urgency_Low */ @@ -228,6 +231,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4240, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -235,6 +239,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4248, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -242,6 +247,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -249,6 +255,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IFE0123_PRIORITYLUT_LOW */ @@ -257,6 +264,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IFE0123_PRIORITYLUT_HIGH */ @@ -265,6 +273,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3638, /* SPECIFIC_IFE0123_URGENCY_LOW */ @@ -276,12 +285,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3640, /* SPECIFIC_IFE0123_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3648, /* SPECIFIC_IFE0123_SAFELUT_LOW */ .value = 0xF, @@ -293,6 +304,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -300,6 +312,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3A30, /* SPECIFIC_IFE0_PRIORITYLUT_LOW */ @@ -307,6 +320,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3A34, /* SPECIFIC_IFE0_PRIORITYLUT_HIGH */ @@ -314,6 +328,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3A38, /* SPECIFIC_IFE0_URGENCY_LOW */ @@ -325,12 +340,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3A40, /* SPECIFIC_IFE0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3A48, /* SPECIFIC_IFE0_SAFELUT_LOW */ .value = 0xF, @@ -342,6 +359,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3B88, /* SPECIFIC_IFE0_ENCCTL_LOW */ @@ -354,6 +372,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3230, /* SPECIFIC_IFE1_PRIORITYLUT_LOW */ @@ -361,6 +380,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3234, /* SPECIFIC_IFE1_PRIORITYLUT_HIGH */ @@ -368,6 +388,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3238, /* SPECIFIC_IFE1_URGENCY_LOW */ @@ -379,12 +400,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3240, /* SPECIFIC_IFE1_DANGERLUT_LOW */ .value = 0x00000000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3248, /* SPECIFIC_IFE1_SAFELUT_LOW */ .value = 0xF, @@ -396,6 +419,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -403,6 +427,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5430, /* SPECIFIC_IFE1_WR_PRIORITYLUT_LOW */ @@ -410,6 +435,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IFE1_WR_PRIORITYLUT_HIGH */ @@ -418,6 +444,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x5438, /* SPECIFIC_IFE1_WR_URGENCY_LOW */ @@ -429,12 +456,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5440, /* SPECIFIC_IFE1_WR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5448, /* SPECIFIC_IFE1_WR_SAFELUT_LOW */ .value = 0xF, @@ -446,6 +475,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5588, /* SPECIFIC_IFE1_WR_ENCCTL_LOW */ @@ -457,6 +487,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -464,6 +495,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -471,6 +503,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2E38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -482,6 +515,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -489,6 +523,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -501,6 +536,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2F08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -512,6 +548,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A30, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -519,6 +556,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A34, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -526,6 +564,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2A38, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -537,6 +576,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A40, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -544,6 +584,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A48, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -556,6 +597,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2B88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -567,6 +609,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_LOW */ @@ -575,6 +618,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_HIGH */ @@ -583,6 +627,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW */ @@ -595,6 +640,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC__IPE_VID_DISP_DANGERLUT_LOW */ @@ -603,6 +649,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IPE_VID_DISP_SAFELUT_LOW */ @@ -616,6 +663,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5F88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -628,6 +676,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2630, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -635,6 +684,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2634, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -642,6 +692,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2638, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -649,6 +700,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2640, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -656,6 +708,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2648, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -663,6 +716,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -670,6 +724,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E30, /* SPECIFIC_FD_PRIORITYLUT_LOW */ @@ -677,6 +732,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E34, /* SPECIFIC_FD_PRIORITYLUT_HIGH */ @@ -684,6 +740,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E38, /* SPECIFIC_FD_URGENCY_LOW */ @@ -691,6 +748,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E40, /* SPECIFIC_FD_DANGERLUT_LOW */ @@ -698,6 +756,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E48, /* SPECIFIC_FD_SAFELUT_LOW */ @@ -705,6 +764,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, @@ -714,6 +774,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2288, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h index f7acca0f039f..8c0a00aae4f4 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v175_130.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v175_130.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V175_130_H_ @@ -206,6 +206,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4230, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ @@ -213,6 +214,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4234, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ @@ -220,6 +222,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, /* cdm_main_SpecificToNttpTr_Urgency_Low */ @@ -230,6 +233,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4240, /* SPECIFIC_CDM_DANGERLUT_LOW */ @@ -237,6 +241,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4248, /* SPECIFIC_CDM_SAFELUT_LOW */ @@ -244,6 +249,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -251,6 +257,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IFE0123_PRIORITYLUT_LOW */ @@ -259,6 +266,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IFE0123_PRIORITYLUT_HIGH */ @@ -267,6 +275,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3638, /* SPECIFIC_IFE0123_URGENCY_LOW */ @@ -278,12 +287,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3640, /* SPECIFIC_IFE0123_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3648, /* SPECIFIC_IFE0123_SAFELUT_LOW */ .value = 0xF, @@ -295,6 +306,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -302,6 +314,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3A30, /* SPECIFIC_IFE0_PRIORITYLUT_LOW */ @@ -309,6 +322,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3A34, /* SPECIFIC_IFE0_PRIORITYLUT_HIGH */ @@ -316,6 +330,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3A38, /* SPECIFIC_IFE0_URGENCY_LOW */ @@ -327,12 +342,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3A40, /* SPECIFIC_IFE0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3A48, /* SPECIFIC_IFE0_SAFELUT_LOW */ .value = 0xF, @@ -344,6 +361,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3B88, /* SPECIFIC_IFE0_ENCCTL_LOW */ @@ -356,6 +374,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3230, /* SPECIFIC_IFE1_PRIORITYLUT_LOW */ @@ -363,6 +382,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3234, /* SPECIFIC_IFE1_PRIORITYLUT_HIGH */ @@ -370,6 +390,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x3238, /* SPECIFIC_IFE1_URGENCY_LOW */ @@ -381,12 +402,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3240, /* SPECIFIC_IFE1_DANGERLUT_LOW */ .value = 0x00000000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x3248, /* SPECIFIC_IFE1_SAFELUT_LOW */ .value = 0xFFFFFFFF, @@ -398,6 +421,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -405,6 +429,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5430, /* SPECIFIC_IFE1_WR_PRIORITYLUT_LOW */ @@ -412,6 +437,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IFE1_WR_PRIORITYLUT_HIGH */ @@ -420,6 +446,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x5438, /* SPECIFIC_IFE1_WR_URGENCY_LOW */ @@ -431,12 +458,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5440, /* SPECIFIC_IFE1_WR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5448, /* SPECIFIC_IFE1_WR_SAFELUT_LOW */ .value = 0xF, @@ -448,6 +477,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5588, /* SPECIFIC_IFE1_WR_ENCCTL_LOW */ @@ -459,6 +489,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ @@ -466,6 +497,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ @@ -473,6 +505,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2E38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ @@ -484,6 +517,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ @@ -491,6 +525,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ @@ -503,6 +538,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2F08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ @@ -514,6 +550,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A30, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ @@ -521,6 +558,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A34, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ @@ -528,6 +566,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, .offset = 0x2A38, /* SPECIFIC_IBL_WR_URGENCY_LOW */ @@ -539,6 +578,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A40, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ @@ -546,6 +586,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2A48, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ @@ -558,6 +599,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2B88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -569,6 +611,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_LOW */ @@ -577,6 +620,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_HIGH */ @@ -585,6 +629,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 1, /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW */ @@ -597,6 +642,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC__IPE_VID_DISP_DANGERLUT_LOW */ @@ -605,6 +651,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* SPECIFIC_IPE_VID_DISP_SAFELUT_LOW */ @@ -618,6 +665,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5F88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ @@ -630,6 +678,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2630, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ @@ -637,6 +686,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2634, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ @@ -644,6 +694,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2638, /* SPECIFIC_JPEG_URGENCY_LOW */ @@ -651,6 +702,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2640, /* SPECIFIC_JPEG_DANGERLUT_LOW */ @@ -658,6 +710,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2648, /* SPECIFIC_JPEG_SAFELUT_LOW */ @@ -665,6 +718,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -672,6 +726,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E30, /* SPECIFIC_FD_PRIORITYLUT_LOW */ @@ -679,6 +734,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E34, /* SPECIFIC_FD_PRIORITYLUT_HIGH */ @@ -686,6 +742,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E38, /* SPECIFIC_FD_URGENCY_LOW */ @@ -693,6 +750,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E40, /* SPECIFIC_FD_DANGERLUT_LOW */ @@ -700,6 +758,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3E48, /* SPECIFIC_FD_SAFELUT_LOW */ @@ -707,6 +766,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, @@ -716,6 +776,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2288, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h index 49b1e8fb63a1..8ddb4b69f79c 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V480_100_H_ @@ -202,6 +202,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ @@ -209,6 +210,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ @@ -216,6 +218,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* CDM_URGENCY_LOW */ @@ -223,6 +226,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* CDM_DANGERLUT_LOW */ @@ -230,6 +234,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* CDM_SAFELUT_LOW */ @@ -237,6 +242,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -244,6 +250,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x630, /* FD_PRIORITYLUT_LOW */ @@ -251,6 +258,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x634, /* FD_PRIORITYLUT_HIGH */ @@ -258,6 +266,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x638, /* FD_URGENCY_LOW */ @@ -265,6 +274,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x640, /* FD_DANGERLUT_LOW */ @@ -272,6 +282,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x648, /* FD_SAFELUT_LOW */ @@ -279,6 +290,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -286,6 +298,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ @@ -293,6 +306,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ @@ -300,6 +314,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ @@ -307,12 +322,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ .value = 0x000F, @@ -324,6 +341,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -331,6 +349,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ @@ -338,6 +357,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ @@ -345,6 +365,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ @@ -352,12 +373,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ .value = 0x0, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ .value = 0x0, @@ -369,6 +392,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -376,6 +400,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_PRIORITYLUT_LOW */ @@ -383,6 +408,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* IFE_RDI_WR_PRIORITYLUT_HIGH */ @@ -390,6 +416,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* IFE_RDI_WR_URGENCY_LOW */ @@ -397,12 +424,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1440, /* IFE_RDI_WR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_SAFELUT_LOW */ .value = 0x000F, @@ -414,6 +443,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -421,6 +451,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_PRIORITYLUT_LOW */ @@ -428,6 +459,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A34, /* IFE_UBWC_STATS_PRIORITYLUT_HIGH */ @@ -435,6 +467,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A38, /* IFE_UBWC_STATS_URGENCY_LOW */ @@ -442,12 +475,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A40, /* IFE_UBWC_STATS_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_SAFELUT_LOW */ .value = 0x000F, @@ -459,6 +494,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1B88, /* IFE_ENCCTL_LOW */ @@ -470,6 +506,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ @@ -477,6 +514,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -484,6 +522,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ @@ -491,6 +530,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ @@ -498,6 +538,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E48, /* IPE0_RD_SAFELUT_LOW */ @@ -510,6 +551,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ @@ -521,6 +563,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ @@ -528,6 +571,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ @@ -535,6 +579,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ @@ -542,6 +587,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ @@ -549,6 +595,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2448, /* IPE1_BPS_RD_SAFELUT_LOW */ @@ -561,6 +608,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ @@ -572,6 +620,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ @@ -579,6 +628,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ @@ -586,6 +636,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ @@ -593,6 +644,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ @@ -600,6 +652,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2848, /* IPE_BPS_WR_SAFELUT_LOW */ @@ -612,6 +665,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ @@ -623,6 +677,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ @@ -630,6 +685,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ @@ -637,6 +693,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E38, /* JPEG_URGENCY_LOW */ @@ -644,6 +701,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ @@ -651,6 +709,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ @@ -658,6 +717,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -665,6 +725,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h index 1b2767b3232c..01882c1c1196 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v480_custom.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V480_CUSTOM_H_ @@ -202,6 +202,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ @@ -209,6 +210,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ @@ -216,6 +218,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* CDM_URGENCY_LOW */ @@ -223,6 +226,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* CDM_DANGERLUT_LOW */ @@ -230,6 +234,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* CDM_SAFELUT_LOW */ @@ -237,6 +242,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -244,6 +250,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x630, /* FD_PRIORITYLUT_LOW */ @@ -251,6 +258,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x634, /* FD_PRIORITYLUT_HIGH */ @@ -258,6 +266,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x638, /* FD_URGENCY_LOW */ @@ -265,6 +274,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x640, /* FD_DANGERLUT_LOW */ @@ -272,6 +282,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x648, /* FD_SAFELUT_LOW */ @@ -279,6 +290,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -286,6 +298,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ @@ -293,6 +306,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ @@ -300,6 +314,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ @@ -307,12 +322,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ .value = 0x000F, @@ -324,6 +341,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -331,6 +349,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ @@ -338,6 +357,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ @@ -345,6 +365,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ @@ -352,12 +373,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ .value = 0x0, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ .value = 0x0, @@ -369,6 +392,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -376,6 +400,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_PRIORITYLUT_LOW */ @@ -383,6 +408,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* IFE_RDI_WR_PRIORITYLUT_HIGH */ @@ -390,6 +416,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* IFE_RDI_WR_URGENCY_LOW */ @@ -397,12 +424,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1440, /* IFE_RDI_WR_DANGERLUT_LOW */ .value = 0xFFFFFFF0, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_SAFELUT_LOW */ .value = 0x1, @@ -414,6 +443,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -421,6 +451,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_PRIORITYLUT_LOW */ @@ -428,6 +459,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A34, /* IFE_UBWC_STATS_PRIORITYLUT_HIGH */ @@ -435,6 +467,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A38, /* IFE_UBWC_STATS_URGENCY_LOW */ @@ -442,12 +475,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A40, /* IFE_UBWC_STATS_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_SAFELUT_LOW */ .value = 0x000F, @@ -459,6 +494,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1B88, /* IFE_ENCCTL_LOW */ @@ -470,6 +506,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ @@ -477,6 +514,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -484,6 +522,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ @@ -491,6 +530,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ @@ -498,6 +538,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E48, /* IPE0_RD_SAFELUT_LOW */ @@ -510,6 +551,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ @@ -521,6 +563,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ @@ -528,6 +571,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ @@ -535,6 +579,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ @@ -542,6 +587,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ @@ -549,6 +595,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2448, /* IPE1_BPS_RD_SAFELUT_LOW */ @@ -561,6 +608,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ @@ -572,6 +620,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ @@ -579,6 +628,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ @@ -586,6 +636,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ @@ -593,6 +644,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ @@ -600,6 +652,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2848, /* IPE_BPS_WR_SAFELUT_LOW */ @@ -612,6 +665,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ @@ -623,6 +677,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ @@ -630,6 +685,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ @@ -637,6 +693,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E38, /* JPEG_URGENCY_LOW */ @@ -644,6 +701,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ @@ -651,6 +709,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ @@ -658,6 +717,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -665,6 +725,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2088, diff --git a/drivers/cam_cpas/cpas_top/cpastop_v520_100.h b/drivers/cam_cpas/cpas_top/cpastop_v520_100.h index 4a8c4f945d03..962d582b0ecd 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v520_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v520_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V520_100_H_ @@ -84,6 +84,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ @@ -91,6 +92,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ @@ -98,6 +100,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE38, /* CDM_URGENCY_LOW */ @@ -105,6 +108,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE40, /* CDM_DANGERLUT_LOW */ @@ -112,6 +116,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE48, /* CDM_SAFELUT_LOW */ @@ -119,6 +124,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -126,6 +132,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -134,6 +141,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -142,6 +150,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* TFE_URGENCY_LOW */ @@ -149,12 +158,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x40, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x48, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -166,6 +177,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -173,6 +185,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ @@ -180,6 +193,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ @@ -187,18 +201,21 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x438, /* OPE_URGENCY_LOW */ .value = 0x00000033, }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* OPE_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* OPE_SAFELUT_LOW */ .value = 0xF, @@ -210,6 +227,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v520_110.h b/drivers/cam_cpas/cpas_top/cpastop_v520_110.h index f1328122e644..e0ea6c032372 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v520_110.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v520_110.h @@ -84,6 +84,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ @@ -91,6 +92,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ @@ -98,6 +100,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE38, /* CDM_URGENCY_LOW */ @@ -105,6 +108,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE40, /* CDM_DANGERLUT_LOW */ @@ -112,6 +116,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE48, /* CDM_SAFELUT_LOW */ @@ -119,6 +124,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -126,6 +132,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -134,6 +141,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -142,6 +150,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* TFE_URGENCY_LOW */ @@ -149,12 +158,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x40, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x48, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -166,6 +177,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -173,6 +185,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ @@ -180,6 +193,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ @@ -187,18 +201,21 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x438, /* OPE_URGENCY_LOW */ .value = 0x00000033, }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* OPE_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* OPE_SAFELUT_LOW */ .value = 0xF, @@ -210,6 +227,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h index 3d9e65ed3c1f..7ab153fc528f 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v540_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v540_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V540_100_H_ @@ -85,6 +85,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ @@ -92,6 +93,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ @@ -99,6 +101,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE38, /* CDM_URGENCY_LOW */ @@ -106,6 +109,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE40, /* CDM_DANGERLUT_LOW */ @@ -113,6 +117,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE48, /* CDM_SAFELUT_LOW */ @@ -120,6 +125,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -127,6 +133,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -135,6 +142,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -143,6 +151,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* TFE_URGENCY_LOW */ @@ -150,12 +159,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x40, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x48, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -167,6 +178,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -174,6 +186,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ @@ -181,6 +194,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ @@ -188,18 +202,21 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x438, /* OPE_URGENCY_LOW */ .value = 0x00000033, }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* OPE_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* OPE_SAFELUT_LOW */ .value = 0xF, @@ -211,6 +228,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h index d3ad5fbc1075..f5161aa630dd 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v545_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V545_100_H_ @@ -84,6 +84,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ @@ -91,6 +92,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ @@ -98,6 +100,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE38, /* CDM_URGENCY_LOW */ @@ -105,6 +108,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE40, /* CDM_DANGERLUT_LOW */ @@ -112,6 +116,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE48, /* CDM_SAFELUT_LOW */ @@ -119,6 +124,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -126,6 +132,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -134,6 +141,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -142,6 +150,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* TFE_URGENCY_LOW */ @@ -149,12 +158,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x40, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x48, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -166,6 +177,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -173,6 +185,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -181,6 +194,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -189,6 +203,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4038, /* TFE_URGENCY_LOW */ @@ -196,12 +211,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x4040, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x4048, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -212,6 +229,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -220,6 +238,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -228,6 +247,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5038, /* TFE_URGENCY_LOW */ @@ -235,12 +255,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5040, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5048, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -251,6 +273,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ @@ -258,6 +281,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ @@ -265,18 +289,21 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x438, /* OPE_URGENCY_LOW */ .value = 0x00000033, }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* OPE_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* OPE_SAFELUT_LOW */ .value = 0xF, @@ -288,6 +315,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_110.h b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h index 4a2509507acc..6afed55ca0b9 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v545_110.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h @@ -84,6 +84,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ @@ -91,6 +92,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ @@ -98,6 +100,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE38, /* CDM_URGENCY_LOW */ @@ -105,6 +108,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE40, /* CDM_DANGERLUT_LOW */ @@ -112,6 +116,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE48, /* CDM_SAFELUT_LOW */ @@ -119,6 +124,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, }, { @@ -126,6 +132,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -134,6 +141,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -142,6 +150,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* TFE_URGENCY_LOW */ @@ -149,12 +158,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x40, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x48, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -166,6 +177,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, { @@ -173,6 +185,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -181,6 +194,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -189,6 +203,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4038, /* TFE_URGENCY_LOW */ @@ -196,12 +211,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x4040, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x4048, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -212,6 +229,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_LOW */ @@ -220,6 +238,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, /* TFE_PRIORITYLUT_HIGH */ @@ -228,6 +247,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5038, /* TFE_URGENCY_LOW */ @@ -235,12 +255,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5040, /* TFE_DANGERLUT_LOW */ .value = 0xffff0000, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x5048, /* TFE_SAFELUT_LOW */ .value = 0x00000003, @@ -251,6 +273,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ @@ -258,6 +281,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ @@ -265,18 +289,21 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x438, /* OPE_URGENCY_LOW */ .value = 0x00000033, }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x440, /* OPE_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x448, /* OPE_SAFELUT_LOW */ .value = 0xF, @@ -288,6 +315,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, }, }; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h index a8cb5c88acd7..af549e4a27d3 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v570_200.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v570_200.h @@ -204,6 +204,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ @@ -211,6 +212,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ @@ -218,6 +220,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* CDM_URGENCY_LOW */ @@ -225,6 +228,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* CDM_DANGERLUT_LOW */ @@ -232,6 +236,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* CDM_SAFELUT_LOW */ @@ -239,9 +244,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x408, /* CDM_QOSGEN_MAINCTL */ @@ -249,6 +256,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x420, /* CDM_QOSGEN_SHAPING_LOW */ @@ -256,6 +264,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x424, /* CDM_QOSGEN_SHAPING_HIGH */ @@ -267,6 +276,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ @@ -274,6 +284,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ @@ -281,6 +292,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ @@ -288,12 +300,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ .value = 0x000F, @@ -305,9 +319,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE08, /* IFE_LINEAR_QOSGEN_MAINCTL */ @@ -315,6 +331,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE20, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ @@ -322,6 +339,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE24, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ @@ -333,6 +351,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ @@ -340,6 +359,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ @@ -347,6 +367,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ @@ -354,12 +375,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ .value = 0x0, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ .value = 0x0, @@ -371,9 +394,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF08, /* IFE_RDI_RD_QOSGEN_MAINCTL */ @@ -381,6 +406,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF20, /* IFE_RDI_RD_QOSGEN_SHAPING_LOW */ @@ -388,6 +414,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF24, /* IFE_RDI_RD_QOSGEN_SHAPING_HIGH */ @@ -399,6 +426,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ @@ -406,6 +434,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* IFE_RDI_WR_0_PRIORITYLUT_HIGH */ @@ -413,6 +442,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* IFE_RDI_WR_0_URGENCY_LOW */ @@ -420,12 +450,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1440, /* IFE_RDI_WR_0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ .value = 0x000F, @@ -437,9 +469,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1808, /* IFE_RDI_WR_0_QOSGEN_MAINCTL */ @@ -447,6 +481,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1820, /* IFE_RDI_WR_0_QOSGEN_SHAPING_LOW */ @@ -454,6 +489,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1824, /* IFE_RDI_WR_0_QOSGEN_SHAPING_HIGH */ @@ -465,6 +501,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ @@ -472,6 +509,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A34, @@ -480,6 +518,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A38, /* IFE_UBWC_STATS_0_URGENCY_LOW */ @@ -487,12 +526,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A40, /* IFE_UBWC_STATS_0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_0_SAFELUT_LOW */ .value = 0x000F, @@ -504,6 +545,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ @@ -511,6 +553,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1908, /* IFE_UBWC_STATS_0_QOSGEN_MAINCTL */ @@ -518,6 +561,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1920, @@ -526,6 +570,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1924, @@ -538,6 +583,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ @@ -545,6 +591,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -552,6 +599,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ @@ -559,6 +607,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ @@ -566,6 +615,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E48, /* IPE0_RD_SAFELUT_LOW */ @@ -578,6 +628,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ @@ -585,6 +636,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2208, /* IPE0_RD_QOSGEN_MAINCTL */ @@ -592,6 +644,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ @@ -599,6 +652,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ @@ -610,6 +664,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ @@ -617,6 +672,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ @@ -624,6 +680,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ @@ -631,6 +688,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ @@ -638,6 +696,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2448, /* IPE1_BPS_RD_SAFELUT_LOW */ @@ -650,6 +709,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ @@ -657,6 +717,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ @@ -665,6 +726,7 @@ static struct cam_camnoc_specific // TITAN_A_CAMNOC_cam_noc_amm_nrt_niu_0_qosgen_Shaping_Low .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ @@ -672,6 +734,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ @@ -683,6 +746,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ @@ -690,6 +754,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ @@ -697,6 +762,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ @@ -704,6 +770,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ @@ -711,6 +778,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2848, /* IPE_BPS_WR_SAFELUT_LOW */ @@ -723,6 +791,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ @@ -730,6 +799,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C08, /* IPE_BPS_WR_QOSGEN_MAINCTL */ @@ -737,6 +807,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C20, /* IPE_BPS_WR_QOSGEN_SHAPING_LOW */ @@ -744,6 +815,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C24, /* IPE_BPS_WR_QOSGEN_SHAPING_HIGH */ @@ -755,6 +827,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ @@ -762,6 +835,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ @@ -769,6 +843,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E38, /* JPEG_URGENCY_LOW */ @@ -776,6 +851,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ @@ -783,6 +859,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ @@ -790,9 +867,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ @@ -800,6 +879,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ @@ -807,6 +887,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ @@ -818,6 +899,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x3888, @@ -825,6 +907,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3488, /* ICP_QOSGEN_MAINCTL */ @@ -832,6 +915,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34A0, /* ICP_QOSGEN_SHAPING_LOW */ @@ -839,6 +923,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34A4, /* ICP_QOSGEN_SHAPING_HIGH */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h index 7c01ae3cdcb0..4559b745e152 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V580_100_H_ @@ -227,6 +227,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ @@ -234,6 +235,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ @@ -241,6 +243,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* CDM_URGENCY_LOW */ @@ -248,6 +251,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* CDM_DANGERLUT_LOW */ @@ -255,6 +259,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* CDM_SAFELUT_LOW */ @@ -262,9 +267,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x408, /* CDM_QOSGEN_MAINCTL */ @@ -272,6 +279,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x420, /* CDM_QOSGEN_SHAPING_LOW */ @@ -279,6 +287,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x424, /* CDM_QOSGEN_SHAPING_HIGH */ @@ -290,6 +299,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ @@ -297,6 +307,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ @@ -304,6 +315,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ @@ -311,12 +323,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ .value = 0x000F, @@ -328,9 +342,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE08, /* IFE_LINEAR_QOSGEN_MAINCTL */ @@ -338,6 +354,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE20, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ @@ -345,6 +362,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE24, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ @@ -356,6 +374,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ @@ -363,6 +382,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ @@ -370,6 +390,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ @@ -377,12 +398,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ .value = 0x0, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ .value = 0x0, @@ -394,9 +417,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF08, /* IFE_RDI_RD_QOSGEN_MAINCTL */ @@ -404,6 +429,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF20, /* IFE_RDI_RD_QOSGEN_SHAPING_LOW */ @@ -411,6 +437,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF24, /* IFE_RDI_RD_QOSGEN_SHAPING_HIGH */ @@ -422,6 +449,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ @@ -429,6 +457,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* IFE_RDI_WR_0_PRIORITYLUT_HIGH */ @@ -436,6 +465,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* IFE_RDI_WR_0_URGENCY_LOW */ @@ -443,12 +473,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1440, /* IFE_RDI_WR_0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ .value = 0x000F, @@ -460,9 +492,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1808, /* IFE_RDI_WR_0_QOSGEN_MAINCTL */ @@ -470,6 +504,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1820, /* IFE_RDI_WR_0_QOSGEN_SHAPING_LOW */ @@ -477,6 +512,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1824, /* IFE_RDI_WR_0_QOSGEN_SHAPING_HIGH */ @@ -488,6 +524,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7430, /* IFE_RDI_WR_1_PRIORITYLUT_LOW */ @@ -495,6 +532,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7434, /* IFE_RDI_WR_1_PRIORITYLUT_HIGH */ @@ -502,6 +540,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7438, /* IFE_RDI_WR_1_URGENCY_LOW */ @@ -509,12 +548,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7440, /* IFE_RDI_WR_1_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7448, /* IFE_RDI_WR_1_SAFELUT_LOW */ .value = 0x000F, @@ -526,9 +567,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C08, /* IFE_RDI_WR_1_QOSGEN_MAINCTL */ @@ -536,6 +579,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C20, /* IFE_RDI_WR_1_QOSGEN_SHAPING_LOW */ @@ -543,6 +587,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C24, /* IFE_RDI_WR_1_QOSGEN_SHAPING_HIGH */ @@ -554,6 +599,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ @@ -561,6 +607,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A34, @@ -569,6 +616,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A38, /* IFE_UBWC_STATS_0_URGENCY_LOW */ @@ -576,12 +624,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A40, /* IFE_UBWC_STATS_0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_0_SAFELUT_LOW */ .value = 0x000F, @@ -593,6 +643,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ @@ -600,6 +651,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1908, /* IFE_UBWC_STATS_0_QOSGEN_MAINCTL */ @@ -607,6 +659,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1920, @@ -615,6 +668,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1924, @@ -627,6 +681,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7630, /* IFE_UBWC_STATS_1_PRIORITYLUT_LOW */ @@ -634,6 +689,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7634, @@ -642,6 +698,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7638, /* IFE_UBWC_STATS_1_URGENCY_LOW */ @@ -649,12 +706,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7640, /* IFE_UBWC_STATS_1_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7648, /* IFE_UBWC_STATS_1_SAFELUT_LOW */ .value = 0x000F, @@ -666,6 +725,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7788, /* IFE_UBWC_STATS_1_ENCCTL_LOW */ @@ -673,6 +733,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C88, /* IFE_UBWC_STATS_1_QOSGEN_MAINCTL */ @@ -680,6 +741,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7CA0, @@ -688,6 +750,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7CA4, @@ -700,6 +763,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ @@ -707,6 +771,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -714,6 +779,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ @@ -721,6 +787,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ @@ -728,6 +795,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E48, /* IPE0_RD_SAFELUT_LOW */ @@ -740,6 +808,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ @@ -747,6 +816,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2208, /* IPE0_RD_QOSGEN_MAINCTL */ @@ -754,6 +824,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ @@ -761,6 +832,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ @@ -772,6 +844,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ @@ -779,6 +852,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ @@ -786,6 +860,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ @@ -793,6 +868,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ @@ -800,6 +876,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2448, /* IPE1_BPS_RD_SAFELUT_LOW */ @@ -812,6 +889,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ @@ -819,6 +897,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ @@ -826,6 +905,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ @@ -833,6 +913,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ @@ -844,6 +925,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ @@ -851,6 +933,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ @@ -858,6 +941,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ @@ -865,6 +949,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ @@ -872,6 +957,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2848, /* IPE_BPS_WR_SAFELUT_LOW */ @@ -884,6 +970,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ @@ -891,6 +978,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C08, /* IPE_BPS_WR_QOSGEN_MAINCTL */ @@ -898,6 +986,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C20, /* IPE_BPS_WR_QOSGEN_SHAPING_LOW */ @@ -905,6 +994,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C24, /* IPE_BPS_WR_QOSGEN_SHAPING_HIGH */ @@ -916,6 +1006,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ @@ -923,6 +1014,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ @@ -930,6 +1022,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E38, /* JPEG_URGENCY_LOW */ @@ -937,6 +1030,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ @@ -944,6 +1038,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ @@ -951,9 +1046,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ @@ -961,6 +1058,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ @@ -968,6 +1066,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ @@ -979,6 +1078,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x3888, @@ -986,6 +1086,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3488, /* ICP_QOSGEN_MAINCTL */ @@ -993,6 +1094,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34A0, /* ICP_QOSGEN_SHAPING_LOW */ @@ -1000,6 +1102,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34A4, /* ICP_QOSGEN_SHAPING_HIGH */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h index 99f9302b575c..9429963451a5 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v580_custom.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V580_CUSTOM_H_ @@ -227,6 +227,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* CDM_PRIORITYLUT_LOW */ @@ -234,6 +235,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* CDM_PRIORITYLUT_HIGH */ @@ -241,6 +243,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* CDM_URGENCY_LOW */ @@ -248,6 +251,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* CDM_DANGERLUT_LOW */ @@ -255,6 +259,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* CDM_SAFELUT_LOW */ @@ -262,9 +267,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x408, /* CDM_QOSGEN_MAINCTL */ @@ -272,6 +279,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x420, /* CDM_QOSGEN_SHAPING_LOW */ @@ -279,6 +287,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x424, /* CDM_QOSGEN_SHAPING_HIGH */ @@ -290,6 +299,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA30, /* IFE_LINEAR_PRIORITYLUT_LOW */ @@ -297,6 +307,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA34, /* IFE_LINEAR_PRIORITYLUT_HIGH */ @@ -304,6 +315,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xA38, /* IFE_LINEAR_URGENCY_LOW */ @@ -311,12 +323,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA40, /* IFE_LINEAR_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0xA48, /* IFE_LINEAR_SAFELUT_LOW */ .value = 0x000F, @@ -328,9 +342,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE08, /* IFE_LINEAR_QOSGEN_MAINCTL */ @@ -338,6 +354,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE20, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ @@ -345,6 +362,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xE24, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ @@ -356,6 +374,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1030, /* IFE_RDI_RD_PRIORITYLUT_LOW */ @@ -363,6 +382,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1034, /* IFE_RDI_RD_PRIORITYLUT_HIGH */ @@ -370,6 +390,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1038, /* IFE_RDI_RD_URGENCY_LOW */ @@ -377,12 +398,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1040, /* IFE_RDI_RD_DANGERLUT_LOW */ .value = 0x0, }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1048, /* IFE_RDI_RD_SAFELUT_LOW */ .value = 0x0, @@ -394,9 +417,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF08, /* IFE_RDI_RD_QOSGEN_MAINCTL */ @@ -404,6 +429,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF20, /* IFE_RDI_RD_QOSGEN_SHAPING_LOW */ @@ -411,6 +437,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0xF24, /* IFE_RDI_RD_QOSGEN_SHAPING_HIGH */ @@ -422,6 +449,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1430, /* IFE_RDI_WR_0_PRIORITYLUT_LOW */ @@ -429,6 +457,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1434, /* IFE_RDI_WR_0_PRIORITYLUT_HIGH */ @@ -436,6 +465,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1438, /* IFE_RDI_WR_0_URGENCY_LOW */ @@ -443,12 +473,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1440, /* IFE_RDI_WR_0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1448, /* IFE_RDI_WR_0_SAFELUT_LOW */ .value = 0x0000, @@ -460,9 +492,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1808, /* IFE_RDI_WR_0_QOSGEN_MAINCTL */ @@ -470,6 +504,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1820, /* IFE_RDI_WR_0_QOSGEN_SHAPING_LOW */ @@ -477,6 +512,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1824, /* IFE_RDI_WR_0_QOSGEN_SHAPING_HIGH */ @@ -488,6 +524,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7430, /* IFE_RDI_WR_1_PRIORITYLUT_LOW */ @@ -495,6 +532,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7434, /* IFE_RDI_WR_1_PRIORITYLUT_HIGH */ @@ -502,6 +540,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7438, /* IFE_RDI_WR_1_URGENCY_LOW */ @@ -509,12 +548,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7440, /* IFE_RDI_WR_1_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7448, /* IFE_RDI_WR_1_SAFELUT_LOW */ .value = 0x0000, @@ -526,9 +567,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C08, /* IFE_RDI_WR_1_QOSGEN_MAINCTL */ @@ -536,6 +579,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C20, /* IFE_RDI_WR_1_QOSGEN_SHAPING_LOW */ @@ -543,6 +587,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C24, /* IFE_RDI_WR_1_QOSGEN_SHAPING_HIGH */ @@ -554,6 +599,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A30, /* IFE_UBWC_STATS_0_PRIORITYLUT_LOW */ @@ -561,6 +607,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A34, @@ -569,6 +616,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1A38, /* IFE_UBWC_STATS_0_URGENCY_LOW */ @@ -576,12 +624,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A40, /* IFE_UBWC_STATS_0_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x1A48, /* IFE_UBWC_STATS_0_SAFELUT_LOW */ .value = 0x000F, @@ -593,6 +643,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1B88, /* IFE_UBWC_STATS_0_ENCCTL_LOW */ @@ -600,6 +651,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1908, /* IFE_UBWC_STATS_0_QOSGEN_MAINCTL */ @@ -607,6 +659,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1920, @@ -615,6 +668,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1924, @@ -627,6 +681,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7630, /* IFE_UBWC_STATS_1_PRIORITYLUT_LOW */ @@ -634,6 +689,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7634, @@ -642,6 +698,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7638, /* IFE_UBWC_STATS_1_URGENCY_LOW */ @@ -649,12 +706,14 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7640, /* IFE_UBWC_STATS_1_DANGERLUT_LOW */ .value = 0xFFFFFF00, }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .offset = 0x7648, /* IFE_UBWC_STATS_1_SAFELUT_LOW */ .value = 0x000F, @@ -666,6 +725,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7788, /* IFE_UBWC_STATS_1_ENCCTL_LOW */ @@ -673,6 +733,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7C88, /* IFE_UBWC_STATS_1_QOSGEN_MAINCTL */ @@ -680,6 +741,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7CA0, @@ -688,6 +750,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7CA4, @@ -700,6 +763,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E30, /* IPE0_RD_PRIORITYLUT_LOW */ @@ -707,6 +771,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -714,6 +779,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E38, /* IPE0_RD_URGENCY_LOW */ @@ -721,6 +787,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E40, /* IPE0_RD_DANGERLUT_LOW */ @@ -728,6 +795,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1E48, /* IPE0_RD_SAFELUT_LOW */ @@ -740,6 +808,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x1F08, /* IPE0_RD_DECCTL_LOW */ @@ -747,6 +816,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2208, /* IPE0_RD_QOSGEN_MAINCTL */ @@ -754,6 +824,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2220, /* IPE0_RD_QOSGEN_SHAPING_LOW */ @@ -761,6 +832,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2224, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ @@ -772,6 +844,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2430, /* IPE1_BPS_RD_PRIORITYLUT_LOW */ @@ -779,6 +852,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2434, /* IPE1_BPS_RD_PRIORITYLUT_HIGH */ @@ -786,6 +860,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2438, /* IPE1_BPS_RD_URGENCY_LOW */ @@ -793,6 +868,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2440, /* IPE1_BPS_RD_DANGERLUT_LOW */ @@ -800,6 +876,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2448, /* IPE1_BPS_RD_SAFELUT_LOW */ @@ -812,6 +889,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2508, /* IPE1_BPS_RD_DECCTL_LOW */ @@ -819,6 +897,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2308, /* IPE1_BPS_RD_QOSGEN_MAINCTL */ @@ -826,6 +905,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2320, /* IPE1_BPS_RD_QOSGEN_SHAPING_LOW */ @@ -833,6 +913,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2324, /* IPE1_BPS_RD_QOSGEN_SHAPING_HIGH */ @@ -844,6 +925,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2830, /* IPE_BPS_WR_PRIORITYLUT_LOW */ @@ -851,6 +933,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2834, /* IPE_BPS_WR_PRIORITYLUT_HIGH */ @@ -858,6 +941,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2838, /* IPE_BPS_WR_URGENCY_LOW */ @@ -865,6 +949,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2840, /* IPE_BPS_WR_DANGERLUT_LOW */ @@ -872,6 +957,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2848, /* IPE_BPS_WR_SAFELUT_LOW */ @@ -884,6 +970,7 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2988, /* IPE_BPS_WR_ENCCTL_LOW */ @@ -891,6 +978,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C08, /* IPE_BPS_WR_QOSGEN_MAINCTL */ @@ -898,6 +986,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C20, /* IPE_BPS_WR_QOSGEN_SHAPING_LOW */ @@ -905,6 +994,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2C24, /* IPE_BPS_WR_QOSGEN_SHAPING_HIGH */ @@ -916,6 +1006,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E30, /* JPEG_PRIORITYLUT_LOW */ @@ -923,6 +1014,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E34, /* JPEG_PRIORITYLUT_HIGH */ @@ -930,6 +1022,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E38, /* JPEG_URGENCY_LOW */ @@ -937,6 +1030,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E40, /* JPEG_DANGERLUT_LOW */ @@ -944,6 +1038,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2E48, /* JPEG_SAFELUT_LOW */ @@ -951,9 +1046,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D08, /* JPEG_QOSGEN_MAINCTL */ @@ -961,6 +1058,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D20, /* JPEG_QOSGEN_SHAPING_LOW */ @@ -968,6 +1066,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x2D24, /* JPEG_QOSGEN_SHAPING_HIGH */ @@ -979,6 +1078,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x3888, @@ -986,6 +1086,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3488, /* ICP_QOSGEN_MAINCTL */ @@ -993,6 +1094,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34A0, /* ICP_QOSGEN_SHAPING_LOW */ @@ -1000,6 +1102,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34A4, /* ICP_QOSGEN_SHAPING_HIGH */ diff --git a/drivers/cam_cpas/cpas_top/cpastop_v680_100.h b/drivers/cam_cpas/cpas_top/cpastop_v680_100.h index fd1b1e8e569b..369b214f3194 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v680_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v680_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CPASTOP_V680_100_H_ @@ -224,6 +224,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5830, /* IFE_UBWC_PRIORITYLUT_LOW */ @@ -231,6 +232,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5834, /* IFE_UBWC_PRIORITYLUT_HIGH */ @@ -238,6 +240,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5838, /* IFE_UBWC_URGENCY_LOW */ @@ -245,6 +248,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5840, /* IFE_UBWC_DANGERLUT_LOW */ @@ -252,6 +256,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5848, /* IFE_UBWC_SAFELUT_LOW */ @@ -264,9 +269,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5A08, /* IFE_UBWC_QOSGEN_MAINCTL */ @@ -274,6 +281,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5A20, /* IFE_UBWC_QOSGEN_SHAPING_LOW */ @@ -281,6 +289,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5A24, /* IFE_UBWC_QOSGEN_SHAPING_HIGH */ @@ -292,6 +301,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5230, /* IFE_RDI_WR_PRIORITYLUT_LOW */ @@ -299,6 +309,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5234, /* IFE_RDI_WR_PRIORITYLUT_HIGH */ @@ -306,6 +317,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5238, /* IFE_RDI_WR_URGENCY_LOW */ @@ -313,6 +325,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5240, /* IFE_RDI_WR_DANGERLUT_LOW */ @@ -320,6 +333,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5248, /* IFE_RDI_WR_SAFELUT_LOW */ @@ -332,9 +346,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5408, /* IFE_RDI_WR_QOSGEN_MAINCTL */ @@ -342,6 +358,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5420, /* IFE_RDI_WR_QOSGEN_SHAPING_LOW */ @@ -349,6 +366,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5424, /* IFE_RDI_WR_QOSGEN_SHAPING_HIGH */ @@ -360,6 +378,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4c30, /* IFE_PDAF_PRIORITYLUT_LOW */ @@ -367,6 +386,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4c34, /* IFE_PDAF_PRIORITYLUT_HIGH */ @@ -374,6 +394,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4c38, /* IFE_PDAF_URGENCY_LOW */ @@ -381,6 +402,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4c40, /* IFE_PDAF_DANGERLUT_LOW */ @@ -388,6 +410,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4c48, /* IFE_PDAF_SAFELUT_LOW */ @@ -400,9 +423,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4e08, /* IFE_PDAF_QOSGEN_MAINCTL */ @@ -410,6 +435,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4e20, /* IFE_PDAF_QOSGEN_SHAPING_LOW */ @@ -417,6 +443,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4e24, /* IFE_PDAF_QOSGEN_SHAPING_HIGH */ @@ -428,6 +455,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4030, /* IFE_LINEAR_PRIORITYLUT_LOW */ @@ -435,6 +463,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4034, /* IFE_LINEAR_PRIORITYLUT_HIGH */ @@ -442,6 +471,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4038, /* IFE_LINEAR_URGENCY_LOW */ @@ -449,6 +479,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4040, /* IFE_LINEAR_DANGERLUT_LOW */ @@ -456,6 +487,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4048, /* IFE_LINEAR_SAFELUT_LOW */ @@ -468,9 +500,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4208, /* IFE_LINEAR_QOSGEN_MAINCTL */ @@ -478,6 +512,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4220, /* IFE_LINEAR_QOSGEN_SHAPING_LOW */ @@ -485,6 +520,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4224, /* IFE_LINEAR_QOSGEN_SHAPING_HIGH */ @@ -496,6 +532,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8230, /* IFE_LINEAR_1_PRIORITYLUT_LOW */ @@ -503,6 +540,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8234, /* IFE_LINEAR_1_PRIORITYLUT_HIGH */ @@ -510,6 +548,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8238, /* IFE_LINEAR_1_URGENCY_LOW */ @@ -517,6 +556,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8240, /* IFE_LINEAR_1_DANGERLUT_LOW */ @@ -524,6 +564,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8248, /* IFE_LINEAR_1_SAFELUT_LOW */ @@ -536,9 +577,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8408, /* IFE_LINEAR_1_QOSGEN_MAINCTL */ @@ -546,6 +589,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8420, /* IFE_LINEAR_1_QOSGEN_SHAPING_LOW */ @@ -553,6 +597,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x8424, /* IFE_LINEAR_1_QOSGEN_SHAPING_HIGH */ @@ -564,6 +609,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4630, /* IFE_LITE_PRIORITYLUT_LOW */ @@ -571,6 +617,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4634, /* IFE_LITE_PRIORITYLUT_HIGH */ @@ -578,6 +625,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4638, /* IFE_LITE_URGENCY_LOW */ @@ -585,6 +633,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4640, /* IFE_LITE_DANGERLUT_LOW */ @@ -592,6 +641,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4648, /* IFE_LITE_SAFELUT_LOW */ @@ -604,9 +654,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4808, /* IFE_LITE_QOSGEN_MAINCTL */ @@ -614,6 +666,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4820, /* IFE_LITE_QOSGEN_SHAPING_LOW */ @@ -621,6 +674,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x4824, /* IFE_LITE_QOSGEN_SHAPING_HIGH */ @@ -632,6 +686,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7030, /* SFE_RD_PRIORITYLUT_LOW */ @@ -639,6 +694,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7034, /* SFE_RD_PRIORITYLUT_HIGH */ @@ -646,6 +702,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7038, /* SFE_RD_URGENCY_LOW */ @@ -653,6 +710,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7040, /* SFE_RD_DANGERLUT_LOW */ @@ -660,6 +718,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7048, /* SFE_RD_SAFELUT_LOW */ @@ -672,9 +731,11 @@ static struct cam_camnoc_specific * register settings. */ .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7208, /* SFE_RD_QOSGEN_MAINCTL */ @@ -682,6 +743,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7220, /* SFE_RD_QOSGEN_SHAPING_LOW */ @@ -689,6 +751,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7224, /* SFE_RD_QOSGEN_SHAPING_HIGH */ @@ -700,6 +763,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6a30, /* IPE_WR_PRIORITYLUT_LOW */ @@ -707,6 +771,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6a34, /* IPE_WR_PRIORITYLUT_HIGH */ @@ -714,6 +779,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6a38, /* IPE_WR_URGENCY_LOW */ @@ -721,6 +787,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6a40, /* IPE_WR_DANGERLUT_LOW */ @@ -728,6 +795,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6a48, /* IPE_WR_SAFELUT_LOW */ @@ -735,9 +803,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6c08, /* IPE_WR_QOSGEN_MAINCTL */ @@ -745,6 +815,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6c20, /* IPE_WR_QOSGEN_SHAPING_LOW */ @@ -752,6 +823,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6c24, /* IPE_WR_QOSGEN_SHAPING_HIGH */ @@ -763,6 +835,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x630, /* BPS_WR_PRIORITYLUT_LOW */ @@ -770,6 +843,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x634, /* BPS_WR_PRIORITYLUT_HIGH */ @@ -777,6 +851,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x638, /* BPS_WR_URGENCY_LOW */ @@ -784,6 +859,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x640, /* BPS_WR_DANGERLUT_LOW */ @@ -791,6 +867,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x648, /* BPS_WR_SAFELUT_LOW */ @@ -798,9 +875,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x808, /* BPS_WR_QOSGEN_MAINCTL */ @@ -808,6 +887,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x820, /* BPS_WR_QOSGEN_SHAPING_LOW */ @@ -815,6 +895,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x824, /* BPS_WR_QOSGEN_SHAPING_HIGH */ @@ -826,6 +907,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x30, /* BPS_RD_PRIORITYLUT_LOW */ @@ -833,6 +915,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x34, /* BPS_RD_PRIORITYLUT_HIGH */ @@ -840,6 +923,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x38, /* BPS_RD_URGENCY_LOW */ @@ -847,6 +931,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x40, /* BPS_RD_DANGERLUT_LOW */ @@ -854,6 +939,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x48, /* BPS_RD_SAFELUT_LOW */ @@ -861,9 +947,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x208, /* BPS_RD_QOSGEN_MAINCTL */ @@ -871,6 +959,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x220, /* BPS_RD_QOSGEN_SHAPING_LOW */ @@ -878,6 +967,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x224, /* BPS_RD_QOSGEN_SHAPING_HIGH */ @@ -889,6 +979,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7c30, /* JPEG_PRIORITYLUT_LOW */ @@ -896,6 +987,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7c34, /* JPEG_PRIORITYLUT_HIGH */ @@ -903,6 +995,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7c38, /* JPEG_URGENCY_LOW */ @@ -910,6 +1003,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7c40, /* JPEG_DANGERLUT_LOW */ @@ -917,6 +1011,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7c48, /* JPEG_SAFELUT_LOW */ @@ -924,9 +1019,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7e08, /* JPEG_QOSGEN_MAINCTL */ @@ -934,6 +1031,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7e20, /* JPEG_QOSGEN_SHAPING_LOW */ @@ -941,6 +1039,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7e24, /* JPEG_QOSGEN_SHAPING_HIGH */ @@ -952,6 +1051,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5E30, /* IPE0_RD_PRIORITYLUT_LOW */ @@ -959,6 +1059,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5E34, /* IPE0_RD_PRIORITYLUT_HIGH */ @@ -966,6 +1067,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5E38, /* IPE0_RD_URGENCY_LOW */ @@ -973,6 +1075,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5E40, /* IPE0_RD_DANGERLUT_LOW */ @@ -980,6 +1083,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5E48, /* IPE0_RD_SAFELUT_LOW */ @@ -987,6 +1091,7 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x5F08, /* IPE0_RD_DECCTL_LOW */ @@ -994,6 +1099,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6008, /* IPE0_RD_QOSGEN_MAINCTL */ @@ -1001,6 +1107,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6020, /* IPE0_RD_QOSGEN_SHAPING_LOW */ @@ -1008,6 +1115,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6024, /* IPE0_RD_QOSGEN_SHAPING_HIGH */ @@ -1019,6 +1127,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6430, /* IPE1_RD_PRIORITYLUT_LOW */ @@ -1026,6 +1135,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6434, /* IPE1_RD_PRIORITYLUT_HIGH */ @@ -1033,6 +1143,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6438, /* IPE1_RD_URGENCY_LOW */ @@ -1040,6 +1151,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6440, /* IPE1_RD_DANGERLUT_LOW */ @@ -1047,6 +1159,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6448, /* IPE1_RD_SAFELUT_LOW */ @@ -1054,9 +1167,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6608, /* IPE1_RD_QOSGEN_MAINCTL */ @@ -1064,6 +1179,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6620, /* IPE1_RD_QOSGEN_SHAPING_LOW */ @@ -1071,6 +1187,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x6624, /* IPE1_RD_QOSGEN_SHAPING_HIGH */ @@ -1082,6 +1199,7 @@ static struct cam_camnoc_specific .enable = true, .priority_lut_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3830, /* CDM_PRIORITYLUT_LOW */ @@ -1089,6 +1207,7 @@ static struct cam_camnoc_specific }, .priority_lut_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3834, /* CDM_PRIORITYLUT_HIGH */ @@ -1096,6 +1215,7 @@ static struct cam_camnoc_specific }, .urgency = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3838, /* CDM_URGENCY_LOW */ @@ -1103,6 +1223,7 @@ static struct cam_camnoc_specific }, .danger_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3840, /* CDM_DANGERLUT_LOW */ @@ -1110,6 +1231,7 @@ static struct cam_camnoc_specific }, .safe_lut = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3848, /* CDM_SAFELUT_LOW */ @@ -1117,9 +1239,11 @@ static struct cam_camnoc_specific }, .ubwc_ctl = { .enable = false, + .is_fuse_based = false, }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3a08, /* CDM_QOSGEN_MAINCTL */ @@ -1127,6 +1251,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3a20, /* CDM_QOSGEN_SHAPING_LOW */ @@ -1134,6 +1259,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x3a24, /* CDM_QOSGEN_SHAPING_HIGH */ @@ -1145,6 +1271,7 @@ static struct cam_camnoc_specific .enable = true, .flag_out_set0_low = { .enable = true, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_WRITE, .masked_value = 0, .offset = 0x2288, @@ -1152,6 +1279,7 @@ static struct cam_camnoc_specific }, .qosgen_mainctl = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x7688, /* ICP_QOSGEN_MAINCTL */ @@ -1159,6 +1287,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_low = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x76A0, /* ICP_QOSGEN_SHAPING_LOW */ @@ -1166,6 +1295,7 @@ static struct cam_camnoc_specific }, .qosgen_shaping_high = { .enable = false, + .is_fuse_based = false, .access_type = CAM_REG_TYPE_READ_WRITE, .masked_value = 0, .offset = 0x76A4, /* ICP_QOSGEN_SHAPING_HIGH */ From c457fcd68afcc61486716265c2a53ab73ace1338 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Wed, 4 Aug 2021 15:16:15 +0800 Subject: [PATCH 779/790] msm: camera: reqmgr: Fix trigger count out of bound issue Since the CAM_TRIGGER_MAX_POINTS equal to CAM_TRIGGER_POINT_EOF, so we need to use CAM_TRIGGER_MAX_POINTS + 1 to define the trigger count. CRs-Fixed: 3007296 Change-Id: Ia0cefd8381417a4b7ecd8636796bf25df705101d Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 24 ++++++++++++------------ drivers/cam_req_mgr/cam_req_mgr_core.h | 3 ++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index bb8f203489db..76c1765fb3c9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -42,10 +42,10 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->last_flush_id = 0; link->initial_sync_req = -1; link->dual_trigger = false; - link->trigger_cnt[0][0] = 0; - link->trigger_cnt[0][1] = 0; - link->trigger_cnt[1][0] = 0; - link->trigger_cnt[1][1] = 0; + link->trigger_cnt[0][CAM_TRIGGER_POINT_SOF] = 0; + link->trigger_cnt[0][CAM_TRIGGER_POINT_EOF] = 0; + link->trigger_cnt[1][CAM_TRIGGER_POINT_SOF] = 0; + link->trigger_cnt[1][CAM_TRIGGER_POINT_EOF] = 0; link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; @@ -574,10 +574,10 @@ static void __cam_req_mgr_flush_req_slot( atomic_set(&link->eof_event_cnt, 0); in_q->wr_idx = 0; in_q->rd_idx = 0; - link->trigger_cnt[0][0] = 0; - link->trigger_cnt[0][1] = 0; - link->trigger_cnt[1][0] = 0; - link->trigger_cnt[1][1] = 0; + link->trigger_cnt[0][CAM_TRIGGER_POINT_SOF] = 0; + link->trigger_cnt[0][CAM_TRIGGER_POINT_EOF] = 0; + link->trigger_cnt[1][CAM_TRIGGER_POINT_SOF] = 0; + link->trigger_cnt[1][CAM_TRIGGER_POINT_EOF] = 0; } /** @@ -4084,10 +4084,10 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) goto setup_failed; } - link->trigger_cnt[0][0] = 0; - link->trigger_cnt[0][1] = 0; - link->trigger_cnt[1][0] = 0; - link->trigger_cnt[1][1] = 0; + link->trigger_cnt[0][CAM_TRIGGER_POINT_SOF] = 0; + link->trigger_cnt[0][CAM_TRIGGER_POINT_EOF] = 0; + link->trigger_cnt[1][CAM_TRIGGER_POINT_SOF] = 0; + link->trigger_cnt[1][CAM_TRIGGER_POINT_EOF] = 0; mutex_unlock(&link->lock); mutex_unlock(&g_crm_core_dev->crm_lock); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 6e6415c85fc0..8b6edaa3f9ff 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -415,7 +415,8 @@ struct cam_req_mgr_core_link { uint64_t sof_timestamp; uint64_t prev_sof_timestamp; bool dual_trigger; - uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS][CAM_TRIGGER_MAX_POINTS]; + uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS] + [CAM_TRIGGER_MAX_POINTS + 1]; atomic_t eof_event_cnt; bool skip_init_frame; uint64_t last_sof_trigger_jiffies; From d99dd2a6407a4f50717f2775778a51a3a15aabc6 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Mon, 2 Aug 2021 19:03:04 +0530 Subject: [PATCH 780/790] msm: camera: flash: Handle I2C flash request deletion Handle I2C flash request deletion in the buffer so that new request can be added. CRs-Fixed: 3002966 Change-Id: I774a49c687832ef566071ae3ec4249bf425e94c2 Signed-off-by: shiwgupt --- .../cam_flash/cam_flash_core.c | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 0dbc38b0280b..5f7a19aa2cda 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -576,6 +576,21 @@ static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl, CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", top, del_req_id); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + if ((del_req_id > + fctrl->i2c_data.per_frame[i].request_id) && ( + fctrl->i2c_data.per_frame[i].is_settings_valid + == 1)) { + fctrl->i2c_data.per_frame[i].request_id = 0; + rc = delete_request( + &(fctrl->i2c_data.per_frame[i])); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "Delete request Fail:%lld rc:%d", + del_req_id, rc); + } + } } cam_flash_i2c_flush_nrt(fctrl); @@ -675,7 +690,7 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, struct i2c_settings_list *i2c_list; struct i2c_settings_array *i2c_set = NULL; int frame_offset = 0, rc = 0; - + CAM_DBG(CAM_FLASH, "req_id=%llu", req_id); if (req_id == 0) { /* NonRealTime Init settings*/ if (fctrl->i2c_data.init_settings.is_settings_valid == true) { @@ -1185,6 +1200,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) i2c_reg_settings = &fctrl->i2c_data.per_frame[frm_offset]; if (i2c_reg_settings->is_settings_valid == true) { + CAM_DBG(CAM_FLASH, "settings already valid"); i2c_reg_settings->request_id = 0; i2c_reg_settings->is_settings_valid = false; goto update_req_mgr; @@ -1239,17 +1255,21 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) return rc; } case CAM_PKT_NOP_OPCODE: { + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { CAM_WARN(CAM_FLASH, "Rxed NOP packets without linking"); - frm_offset = csl_packet->header.request_id % - MAX_PER_FRAME_ARRAY; fctrl->i2c_data.per_frame[frm_offset].is_settings_valid = false; return 0; } - + i2c_reg_settings = + &fctrl->i2c_data.per_frame[frm_offset]; + i2c_reg_settings->is_settings_valid = true; + i2c_reg_settings->request_id = + csl_packet->header.request_id; CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u", csl_packet->header.request_id); goto update_req_mgr; From 56b34863843cd269697d5cba5a64596ca9278f78 Mon Sep 17 00:00:00 2001 From: Yash Upadhyay Date: Thu, 8 Jul 2021 14:59:28 +0530 Subject: [PATCH 781/790] msm: camera: isp: CSID Tasklet stop sequence Handle race for tasklet stop. Changed the sequence of tasklet stop call to avoid unclocked register accesses on tasklet stop/flush. CRs-Fixed: 3010894 Change-Id: Ieec9f20db127b2bebec0bb40ec437b4eb3d3d9dd Signed-off-by: Yash Upadhyay --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 3 ++- .../cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 930e1eb2687b..c25bedb07598 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1589,12 +1589,13 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_mask_addr); + cam_tasklet_stop(csid_hw->tasklet); + rc = cam_ife_csid_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed", csid_hw->hw_intf->hw_idx); - cam_tasklet_stop(csid_hw->tasklet); spin_lock_irqsave(&csid_hw->lock_state, flags); csid_hw->device_enabled = 0; spin_unlock_irqrestore(&csid_hw->lock_state, flags); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 8dd9f0f0337e..7c86db7b8912 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1165,12 +1165,13 @@ static int cam_tfe_csid_disable_hw(struct cam_tfe_csid_hw *csid_hw) cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_top_irq_mask_addr); + cam_tasklet_stop(csid_hw->tasklet); + rc = cam_tfe_csid_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed", csid_hw->hw_intf->hw_idx); - cam_tasklet_stop(csid_hw->tasklet); spin_lock_irqsave(&csid_hw->spin_lock, flags); csid_hw->device_enabled = 0; spin_unlock_irqrestore(&csid_hw->spin_lock, flags); From 6fb7609c0b8232ca018bc00f20c87fbb042ce6e3 Mon Sep 17 00:00:00 2001 From: Shadul Shaikh Date: Fri, 13 Aug 2021 16:27:04 +0530 Subject: [PATCH 782/790] msm: camera: smmu: Unmap secure buffers in secure camera use case Dettach and unmap DMA buffers obtained previously from DMA attach and mappings respectively. CRs-Fixed: 3014632 Change-Id: If8f8ebe9fc270f2ba39a9a42ab7c7bfb0f79c4eb Signed-off-by: Shadul Shaikh --- drivers/cam_smmu/cam_smmu_api.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 05b3700bddfb..0083d8674d65 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -212,6 +212,8 @@ struct cam_dma_buff_info { struct cam_sec_buff_info { struct dma_buf *buf; + struct dma_buf_attachment *attach; + struct sg_table *table; enum dma_data_direction dir; int ref_count; dma_addr_t paddr; @@ -2876,6 +2878,8 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, mapping_info->dir = dma_dir; mapping_info->ref_count = 1; mapping_info->buf = dmabuf; + mapping_info->attach = attach; + mapping_info->table = table; CAM_DBG(CAM_SMMU, "idx=%d, ion_fd=%d, dev=%pK, paddr=%pK, len=%u", idx, ion_fd, @@ -2976,11 +2980,27 @@ static int cam_smmu_secure_unmap_buf_and_remove_from_list( struct cam_sec_buff_info *mapping_info, int idx) { - if (!mapping_info) { - CAM_ERR(CAM_SMMU, "Error: List doesn't exist"); + if ((!mapping_info->buf) || (!mapping_info->table) || + (!mapping_info->attach)) { + CAM_ERR(CAM_SMMU, "Error: Invalid params dev = %pK, table = %pK", + (void *)iommu_cb_set.cb_info[idx].dev, + (void *)mapping_info->table); + CAM_ERR(CAM_SMMU, "Error:dma_buf = %pK, attach = %pK\n", + (void *)mapping_info->buf, + (void *)mapping_info->attach); return -EINVAL; } + + /* skip cache operations */ + mapping_info->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; + + /* iommu buffer clean up */ + dma_buf_unmap_attachment(mapping_info->attach, + mapping_info->table, mapping_info->dir); + dma_buf_detach(mapping_info->buf, mapping_info->attach); dma_buf_put(mapping_info->buf); + mapping_info->buf = NULL; + list_del_init(&mapping_info->list); CAM_DBG(CAM_SMMU, "unmap fd: %d, idx : %d", mapping_info->ion_fd, idx); From e3c0176a1139c92de0a5b8cd47f3e16c8604d959 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Wed, 11 Aug 2021 15:34:05 +0530 Subject: [PATCH 783/790] msm: camera: tfe: Fix dereference of pointer before NULL check This commit fixes derefering NULL pointer before accessing it. CRs-Fixed: 3011823 Change-Id: Id9ba556103310d9bb13a0b1029e942a2541a272f Signed-off-by: Shravya Samala --- drivers/cam_isp/cam_isp_context.c | 2 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index ea569d0521bc..acd4c1acad93 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -6098,7 +6098,7 @@ static int cam_isp_context_dump_requests(void *data, static int cam_isp_context_handle_message(void *context, uint32_t msg_type, uint32_t *data) { - int rc = 0; + int rc = -EINVAL; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; struct cam_context *ctx = (struct cam_context *)context; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index f947249cd129..4a3f53e39747 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -319,9 +319,10 @@ static int cam_tfe_hw_mgr_get_clock_rate( continue; hw_intf = isp_hw_res->hw_res[i]->hw_intf; - CAM_DBG(CAM_ISP, "hw type %d hw index:%d", - hw_intf->hw_type, hw_intf->hw_idx); if (hw_intf && hw_intf->hw_ops.process_cmd) { + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_GET_CLOCK_RATE, @@ -343,7 +344,7 @@ static int cam_tfe_hw_mgr_update_clock_rate( uint32_t *updated_clock_rate) { int i; - int rc = 0; + int rc = -EINVAL; struct cam_hw_intf *hw_intf; for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { @@ -351,29 +352,33 @@ static int cam_tfe_hw_mgr_update_clock_rate( continue; hw_intf = isp_hw_res->hw_res[i]->hw_intf; - CAM_DBG(CAM_ISP, "hw type %d hw index:%d", - hw_intf->hw_type, hw_intf->hw_idx); if (hw_intf && hw_intf->hw_ops.process_cmd) { + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, set_clock_rate, sizeof(uint32_t)); if (rc) { - CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + CAM_ERR(CAM_ISP, "Failed to set Clock rate"); return rc; } } if (hw_intf && hw_intf->hw_ops.process_cmd) { + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + rc = hw_intf->hw_ops.process_cmd( hw_intf->hw_priv, CAM_ISP_HW_CMD_GET_CLOCK_RATE, updated_clock_rate, sizeof(uint32_t)); if (rc) { - CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + CAM_ERR(CAM_ISP, "Failed to get updated clock rate"); return rc; } } From e41ff174c187b96feaa44622551d6c1eb1697796 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Tue, 27 Jul 2021 15:06:04 +0530 Subject: [PATCH 784/790] msm: camera: flash: Add support for flash stream off - Apply flash off register settings at the time of stream off. - Add support to send fire command in initial config command. CRs-Fixed: 2998772 Change-Id: I8897a68e637d283afd98e386b6a7b1fbaaf63c61 Signed-off-by: shiwgupt --- .../cam_flash/cam_flash_core.c | 73 ++++++++++++++++++- .../cam_flash/cam_flash_dev.c | 5 ++ .../cam_flash/cam_flash_dev.h | 5 ++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 0dbc38b0280b..0d4b3faa251c 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -459,6 +459,8 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) { + int rc = 0; + if (!flash_ctrl) { CAM_ERR(CAM_FLASH, "Flash control Null"); return -EINVAL; @@ -467,6 +469,16 @@ 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, (enum led_brightness)LED_SWITCH_OFF); + + if ((flash_ctrl->i2c_data.streamoff_settings.is_settings_valid) && + (flash_ctrl->i2c_data.streamoff_settings.request_id == 0)) { + flash_ctrl->apply_streamoff = true; + rc = cam_flash_i2c_apply_setting(flash_ctrl, 0); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "cannot apply streamoff settings"); + } + } return 0; } @@ -678,7 +690,22 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, if (req_id == 0) { /* NonRealTime Init settings*/ - if (fctrl->i2c_data.init_settings.is_settings_valid == true) { + if (fctrl->apply_streamoff == true) { + fctrl->apply_streamoff = false; + i2c_set = &fctrl->i2c_data.streamoff_settings; + list_for_each_entry(i2c_list, + &(i2c_set->list_head), + list) { + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply stream on settings: %d", rc); + return rc; + } + break; + } + } else if (fctrl->i2c_data.init_settings.is_settings_valid == true) { list_for_each_entry(i2c_list, &(fctrl->i2c_data.init_settings.list_head), list) { @@ -1201,6 +1228,16 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) "Failed in parsing i2c packets"); return rc; } + if ((fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE) || + (fctrl->flash_state == CAM_FLASH_STATE_CONFIG)) { + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; + rc = fctrl->func_tbl.apply_setting(fctrl, 1); + if (rc) { + CAM_ERR(CAM_FLASH, "cannot apply fire settings rc = %d", rc); + return rc; + } + return rc; + } break; } case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: { @@ -1254,6 +1291,29 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) csl_packet->header.request_id); goto update_req_mgr; } + case CAM_FLASH_PACKET_OPCODE_STREAM_OFF: { + if (fctrl->streamoff_count > 0) + return rc; + + CAM_DBG(CAM_FLASH, "Received Stream off Settings"); + i2c_data = &(fctrl->i2c_data); + fctrl->streamoff_count = fctrl->streamoff_count + 1; + i2c_reg_settings = &i2c_data->streamoff_settings; + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser(&fctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1, NULL); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in parsing i2c Stream off packets"); + return rc; + } + break; + } default: CAM_ERR(CAM_FLASH, "Wrong Opcode : %d", (csl_packet->header.op_code & 0xFFFFFF)); @@ -1817,6 +1877,16 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) { int rc = 0; + if (fctrl->i2c_data.streamoff_settings.is_settings_valid == true) { + fctrl->i2c_data.streamoff_settings.is_settings_valid = false; + rc = delete_request(&fctrl->i2c_data.streamoff_settings); + if (rc) { + CAM_WARN(CAM_FLASH, + "Failed to delete Stream off i2c_setting: %d", + rc); + } + } + if (fctrl->bridge_intf.device_hdl != 1) { rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl); if (rc) @@ -1827,6 +1897,7 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) fctrl->bridge_intf.link_hdl = -1; fctrl->bridge_intf.session_hdl = -1; fctrl->last_flush_req = 0; + fctrl->streamoff_count = 0; } return rc; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index a7f3370a7f8c..b2dd3265da69 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -72,6 +72,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, flash_acq_dev.device_handle; fctrl->bridge_intf.session_hdl = flash_acq_dev.session_handle; + fctrl->apply_streamoff = false; rc = copy_to_user(u64_to_user_ptr(cmd->handle), &flash_acq_dev, @@ -126,6 +127,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, CAM_WARN(CAM_FLASH, "Power Down Failed"); } + fctrl->streamoff_count = 0; fctrl->flash_state = CAM_FLASH_STATE_INIT; break; } @@ -165,6 +167,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, goto release_mutex; } + fctrl->apply_streamoff = false; fctrl->flash_state = CAM_FLASH_STATE_START; break; } @@ -493,6 +496,7 @@ static int cam_flash_component_bind(struct device *dev, INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.streamoff_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD( &(fctrl->i2c_data.per_frame[i].list_head)); @@ -641,6 +645,7 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.streamoff_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head)); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index cc1c9738d2b6..f5437c93a843 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -46,6 +46,7 @@ #define CAM_FLASH_PACKET_OPCODE_INIT 0 #define CAM_FLASH_PACKET_OPCODE_SET_OPS 1 #define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2 +#define CAM_FLASH_PACKET_OPCODE_STREAM_OFF 3 struct cam_flash_ctrl; @@ -189,6 +190,8 @@ struct cam_flash_func_tbl { * @io_master_info : Information about the communication master * @i2c_data : I2C register settings * @last_flush_req : last request to flush + * @streamoff_count : Count to hold the number of times stream off called + * @apply_streamoff : variable to store when to apply stream off */ struct cam_flash_ctrl { char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; @@ -217,6 +220,8 @@ struct cam_flash_ctrl { struct camera_io_master io_master_info; struct i2c_data_settings i2c_data; uint32_t last_flush_req; + uint32_t streamoff_count; + int32_t apply_streamoff; }; int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg); From 9d68bffd2aaf45bc8c938cb847c64709c3960f1b Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Wed, 11 Aug 2021 11:06:27 +0530 Subject: [PATCH 785/790] msm: camera: cdm: Acquire mutex lock before accessing client data There is a chance of use after release of client data in cdm internal operation calls. Hence acquire mutex lock whenever accessing client data to avoid use after release scenario. CRs-Fixed: 3010261 Change-Id: Iaf7f41d56301299a6f63a5dc1090334063019881 Signed-off-by: Shravya Samala --- drivers/cam_cdm/cam_cdm_core_common.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index d7ddcee6d9b7..fd84b8d6866b 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -180,10 +180,12 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, (struct cam_cdm_bl_cb_request_entry *)data; client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl); + mutex_lock(&cdm_hw->hw_mutex); client = core->clients[client_idx]; if ((!client) || (client->handle != node->client_hdl)) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, node->client_hdl); + mutex_unlock(&cdm_hw->hw_mutex); return; } cam_cdm_get_client_refcount(client); @@ -202,6 +204,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); + mutex_unlock(&cdm_hw->hw_mutex); return; } else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE || status == CAM_CDM_CB_STATUS_HW_FLUSH || @@ -217,7 +220,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, if ((!client) || (client->handle != node->client_hdl)) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, node->client_hdl); - return; + return; } cam_cdm_get_client_refcount(client); mutex_lock(&client->lock); @@ -239,6 +242,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) { if (core->clients[i] != NULL) { + mutex_lock(&cdm_hw->hw_mutex); client = core->clients[i]; cam_cdm_get_client_refcount(client); mutex_lock(&client->lock); @@ -261,6 +265,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); + mutex_unlock(&cdm_hw->hw_mutex); } } } @@ -320,35 +325,34 @@ int cam_cdm_stream_ops_internal(void *hw_priv, return -EINVAL; core = (struct cam_cdm *)cdm_hw->core_info; + mutex_lock(&cdm_hw->hw_mutex); client_idx = CAM_CDM_GET_CLIENT_IDX(*handle); client = core->clients[client_idx]; if (!client) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle); + mutex_unlock(&cdm_hw->hw_mutex); return -EINVAL; } cam_cdm_get_client_refcount(client); if (*handle != client->handle) { CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle); - cam_cdm_put_client_refcount(client); - return -EINVAL; + rc = -EINVAL; + goto end; } if (operation == true) { if (true == client->stream_on) { CAM_ERR(CAM_CDM, "Invalid CDM client is already streamed ON"); - cam_cdm_put_client_refcount(client); - return rc; + goto end; } } else { if (client->stream_on == false) { CAM_ERR(CAM_CDM, "Invalid CDM client is already streamed Off"); - cam_cdm_put_client_refcount(client); - return rc; + goto end; } } - mutex_lock(&cdm_hw->hw_mutex); if (operation == true) { if (!cdm_hw->open_count) { struct cam_ahb_vote ahb_vote; From 8839726f67e1c0df12b0ad24cee253f58c94ee8a Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Tue, 10 Aug 2021 06:47:52 +0000 Subject: [PATCH 786/790] msm: camera: sync: Prevent OOB access of sync name Issue: strlcpy calls strlen on src ptr. If src is not NULL terminated then OOB access will occur in below stack. strlen strlcpy cam_sync_init_row cam_sync_handle_create cam_sync_dev_ioctl Fix: Pad user-space supplied name with NULL. CRs-Fixed: 3010262 Change-Id: Ib5c2fbfe395025ec05e0bb2980f86111e95ff54c Signed-off-by: Trishansh Bhardwaj --- drivers/cam_sync/cam_sync.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index 4f447eff8c90..fca7bfc38db4 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -477,6 +477,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl) u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; + sync_create.name[SYNC_DEBUG_NAME_LEN] = '\0'; result = cam_sync_create(&sync_create.sync_obj, sync_create.name); From 1c390133114972aee7dc4b68a17a6a1a76c722dc Mon Sep 17 00:00:00 2001 From: chengxue Date: Mon, 16 Aug 2021 20:31:32 +0800 Subject: [PATCH 787/790] msm: camera: reqmgr: Delay to do slot reset for finished req For boken mode with hw sync enable, a link and its synclink streaming with sync. if a bubble condition happens on a link, and can not wait all buf done to clear the isp ctx process_bubble flag in time, there may apply fails on isp during the bubble recovery flow. current crm reset in_q slot after req's report has finished. this may lead to a synclink slot not found while do ready check. So delay to do slot reset by referring the link delay. CRs-Fixed: 2996710 Change-Id: Ice8c340a9f478a69d97e3a7c77e0d0a263be66fa Signed-off-by: chengxue --- drivers/cam_req_mgr/cam_req_mgr_core.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index bb8f203489db..8fdc5ce4a72e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -2985,6 +2985,8 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_req_queue *in_q = NULL; struct crm_task_payload *task_data = NULL; + int reset_step = 0; + int i = 0; if (!data || !priv) { CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); @@ -3013,6 +3015,22 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) in_q->last_applied_idx = -1; if (idx == in_q->rd_idx) __cam_req_mgr_dec_idx(&idx, 1, in_q->num_slots); + + reset_step = link->max_delay; + for (i = 0; i < link->num_sync_links; i++) { + if (link->sync_link[i]) { + if ((link->in_msync_mode) && + (link->sync_link[i]->max_delay > + reset_step)) + reset_step = + link->sync_link[i]->max_delay; + } + } + + __cam_req_mgr_dec_idx( + &idx, reset_step + 1, + in_q->num_slots); + __cam_req_mgr_reset_req_slot(link, idx); } } From dfa85a1638fd8fd513085a8cbbe055ce651d0f87 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 12 Aug 2021 19:01:12 +0530 Subject: [PATCH 788/790] msm: camera: ope: Fix uninitialized variable access Update ope pf dump function for uninitialized variables access. CRs-Fixed: 3020020 Change-Id: I7a996b15c8fe48297bcd160be3dbf4c7b65dc41d Signed-off-by: Alok Chauhan --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 637cdf0e1e5a..978160a6a6ac 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -4112,14 +4112,14 @@ static void cam_ope_mgr_dump_pf_data( packet = hw_cmd_args->u.pf_args.pf_data.packet; ope_request = hw_cmd_args->u.pf_args.pf_data.req; - if (ctx_data->pf_mid_found) - goto stripedump; - ope_pid_mid_args.fault_mid = hw_cmd_args->u.pf_args.mid; ope_pid_mid_args.fault_pid = hw_cmd_args->u.pf_args.pid; ctx_found = hw_cmd_args->u.pf_args.ctx_found; resource_type = hw_cmd_args->u.pf_args.resource_type; + if (ctx_data->pf_mid_found) + goto stripedump; + if (*ctx_found && *resource_type) { hw_pid_support = false; goto stripedump; @@ -4162,13 +4162,13 @@ static void cam_ope_mgr_dump_pf_data( return; } - io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + - packet->io_configs_offset / 4); - *resource_type = ope_pid_mid_args.match_res; CAM_INFO(CAM_OPE, "Fault port %d", *resource_type); stripedump: + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + if (!ope_request) goto iodump; @@ -4232,6 +4232,11 @@ iodump: io_cfg[i].mem_handle[j]); if (io_buf_found) { + if (j >= OPE_MAX_PLANES) { + CAM_ERR(CAM_OPE, "Invalid plane idx: %d", j); + break; + } + for (stripe_num = 0; stripe_num < io_buf->num_stripes[j]; stripe_num++) { CAM_INFO(CAM_OPE, From 6e6855210594d192580884e757d5205e788e4a80 Mon Sep 17 00:00:00 2001 From: Dharmender Sharma Date: Fri, 30 Jul 2021 20:19:00 +0530 Subject: [PATCH 789/790] msm: camera: isp: Support all patterns for TOP TPG It provide support for differeent TPG patterns like color bar, incrementing and user defined. CRs-Fixed: 3026095 Change-Id: If18c99fb759f9cdb5bf8950c54f719d188a5e4ae Signed-off-by: Dharmender Sharma --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 17 +++++- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 4 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw/include/cam_top_tpg_hw_intf.h | 5 +- .../isp_hw/top_tpg/cam_top_tpg101.h | 3 +- .../isp_hw/top_tpg/cam_top_tpg_core.c | 18 +++++- .../isp_hw/top_tpg/cam_top_tpg_core.h | 5 +- .../isp_hw/top_tpg/cam_top_tpg_ver1.c | 55 ++++++++++++++++++- .../isp_hw/top_tpg/cam_top_tpg_ver1.h | 3 +- 9 files changed, 101 insertions(+), 10 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index d3e2b3d24cf9..0f9c8834c828 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -3228,6 +3228,17 @@ static int cam_tfe_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) if (ctx->init_done && start_isp->start_only) goto start_only; + /* set tpg debug information for top tpg */ + for (i = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) { + if (g_tfe_hw_mgr.tpg_devices[i]) { + rc = g_tfe_hw_mgr.tpg_devices[i]->hw_ops.process_cmd( + g_tfe_hw_mgr.tpg_devices[i]->hw_priv, + CAM_ISP_HW_CMD_TPG_SET_PATTERN, + &g_tfe_hw_mgr.debug_cfg.set_tpg_pattern, + sizeof(g_tfe_hw_mgr.debug_cfg.set_tpg_pattern)); + } + } + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { if (!hw_mgr_res->hw_res[i]) @@ -5789,9 +5800,10 @@ static int cam_tfe_hw_mgr_debug_register(void) int rc = 0; struct dentry *dbgfileptr = NULL; + g_tfe_hw_mgr.debug_cfg.set_tpg_pattern = CAM_TOP_TPG_DEFAULT_PATTERN; dbgfileptr = debugfs_create_dir("camera_tfe", NULL); if (!dbgfileptr) { - CAM_ERR(CAM_ISP,"DebugFS could not create directory!"); + CAM_ERR(CAM_ISP, "DebugFS could not create directory!"); rc = -ENOENT; goto end; } @@ -5809,6 +5821,9 @@ static int cam_tfe_hw_mgr_debug_register(void) dbgfileptr = debugfs_create_u32("enable_csid_recovery", 0644, g_tfe_hw_mgr.debug_cfg.dentry, &g_tfe_hw_mgr.debug_cfg.enable_csid_recovery); + dbgfileptr = debugfs_create_u32("set_tpg_pattern", 0644, + g_tfe_hw_mgr.debug_cfg.dentry, + &g_tfe_hw_mgr.debug_cfg.set_tpg_pattern); dbgfileptr = debugfs_create_file("tfe_camif_debug", 0644, g_tfe_hw_mgr.debug_cfg.dentry, NULL, &cam_tfe_camif_debug); dbgfileptr = debugfs_create_u32("per_req_reg_dump", 0644, diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index b4b75d91103b..ea12717945e2 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_HW_MGR_H_ @@ -30,6 +30,7 @@ * @enable_recovery: enable recovery * @enable_csid_recovery: enable csid recovery * @camif_debug: enable sensor diagnosis status + * @set_tpg_pattern: tpg pattern information * @enable_reg_dump: enable reg dump on error; * @per_req_reg_dump: Enable per request reg dump * @@ -40,6 +41,7 @@ struct cam_tfe_hw_mgr_debug { uint32_t enable_recovery; uint32_t enable_csid_recovery; uint32_t camif_debug; + uint32_t set_tpg_pattern; uint32_t enable_reg_dump; uint32_t per_req_reg_dump; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 6638b9269a58..80ca8847b069 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -138,6 +138,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_GET_CLOCK_RATE, CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, CAM_ISP_HW_DUMP_HW_SRC_CLK_RATE, + CAM_ISP_HW_CMD_TPG_SET_PATTERN, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h index 1aa9d26e11c1..50191f075307 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG_HW_INTF_H_ @@ -14,7 +14,8 @@ #define CAM_TOP_TPG_HW_NUM_MAX 3 /* Max supported number of DT for TPG */ #define CAM_TOP_TPG_MAX_SUPPORTED_DT 4 - +/* TPG default pattern should be color bar */ +#define CAM_TOP_TPG_DEFAULT_PATTERN 0x8 /** * enum cam_top_tpg_id - top tpg hw instance id */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h index 0b99a3f6d1ba..937bc9886451 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg101.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG101_H_ @@ -49,6 +49,7 @@ static struct cam_top_tpg_ver1_reg_offset cam_top_tpg101_reg = { .tpg_payload_mode_color = 0x8, .tpg_split_en_shift = 5, .top_mux_reg_offset = 0x1C, + .top_unicolor_bar_shift = 2, }; struct cam_top_tpg_hw_info cam_top_tpg101_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c index 23b62f6fdb85..1d1673b9685b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #include @@ -282,6 +282,19 @@ irqreturn_t cam_top_tpg_irq(int irq_num, void *data) return IRQ_HANDLED; } +static int cam_top_tpg_set_top_tpg_pattern(struct cam_top_tpg_hw *tpg_hw, + void *cmd_args) +{ + uint32_t *top_tpg_pattern; + + top_tpg_pattern = (uint32_t *) cmd_args; + tpg_hw->tpg_pattern = *top_tpg_pattern; + CAM_DBG(CAM_ISP, "TPG:%d set tpg debug value:%d", + tpg_hw->hw_intf->hw_idx, tpg_hw->tpg_pattern); + + return 0; +} + static int cam_top_tpg_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -301,6 +314,9 @@ static int cam_top_tpg_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE: rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args); break; + case CAM_ISP_HW_CMD_TPG_SET_PATTERN: + rc = cam_top_tpg_set_top_tpg_pattern(tpg_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d", tpg_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h index d904eb949817..10a8a5bc1779 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG_CORE_H_ @@ -106,7 +106,7 @@ struct cam_top_tpg_cfg { * @hw_info: tpg hw device information * @tpg_info: tpg hw specific information * @tpg_res: tpg resource - * @tpg_cfg: tpg configuration + * @tpg_pattern: tpg pattern configuration * @clk_rate clock rate * @lock_state lock state * @tpg_complete tpg completion @@ -117,6 +117,7 @@ struct cam_top_tpg_hw { struct cam_hw_info *hw_info; struct cam_top_tpg_hw_info *tpg_info; struct cam_isp_resource_node tpg_res; + uint32_t tpg_pattern; uint64_t clk_rate; spinlock_t lock_state; struct completion tpg_complete; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c index 2f7d461383a9..821f6040a072 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include @@ -204,6 +204,7 @@ static int cam_top_tpg_ver1_start( struct cam_top_tpg_ver1_reg_offset *tpg_reg; struct cam_top_tpg_cfg *tpg_data; uint32_t i, val; + uint32_t in_format = 0; if (!hw_priv || !start_args || (arg_size != sizeof(struct cam_isp_resource_node))) { @@ -244,6 +245,7 @@ static int cam_top_tpg_ver1_start( tpg_reg->tpg_dt_0_cfg_2 + 0x10 * i); } + /* configure one DT, infinite frames */ val = (tpg_num_dt_map[tpg_data->num_active_dts-1] << tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num[0]; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0); @@ -260,6 +262,57 @@ static int cam_top_tpg_ver1_start( cam_io_w_mb(0x2581F4, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); + /* configure tpg pattern */ + in_format = tpg_data->dt_cfg[0].encode_format & 0xF; + val = in_format << tpg_reg->tpg_dt_encode_format_shift; + + switch (tpg_hw->tpg_pattern) { + case 0x0: + val = val | tpg_hw->tpg_pattern; + break; + case 0x1: + val = val | tpg_hw->tpg_pattern; + break; + case 0x2: + val = val | tpg_hw->tpg_pattern; + break; + case 0x3: + val = val | tpg_hw->tpg_pattern; + break; + case 0x4: + val = val | tpg_hw->tpg_pattern; + break; + case 0x5: + val = val | tpg_hw->tpg_pattern; + break; + case 0x6: + val = val | tpg_hw->tpg_pattern; + break; + case 0x7: + val = val | tpg_hw->tpg_pattern; + break; + case 0x8: + /* unicolor bar selection */ + val = 0x1 | (1 << tpg_reg->top_unicolor_bar_shift); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_color_bar_cfg); + val = (in_format << tpg_reg->tpg_dt_encode_format_shift) | + tpg_hw->tpg_pattern; + break; + default: + /* frame with split color bar */ + val = 1 << tpg_reg->tpg_split_en_shift; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_color_bar_cfg); + val = (in_format << tpg_reg->tpg_dt_encode_format_shift) | + CAM_TOP_TPG_DEFAULT_PATTERN; + break; + } + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_2); + + /* config pix pattern */ val = (1 << tpg_reg->tpg_split_en_shift); cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + tpg_reg->tpg_common_gen_cfg); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h index b0c5d68f04f1..9ceba49e3448 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG_VER1_H_ @@ -48,6 +48,7 @@ struct cam_top_tpg_ver1_reg_offset { uint32_t tpg_payload_mode_color; uint32_t tpg_split_en_shift; uint32_t top_mux_reg_offset; + uint32_t top_unicolor_bar_shift; }; int cam_top_tpg_ver1_init(struct cam_top_tpg_hw *tpg_hw); From 1510d5b82f938509a6bccecfe8f353e988b4bf07 Mon Sep 17 00:00:00 2001 From: Dharmender Sharma Date: Thu, 5 Aug 2021 15:05:38 +0530 Subject: [PATCH 790/790] msm: camera: jpeg: JPEG HW and Camnoc MISR Support for Camnoc MISR for JPEG DMA and Encoder. Also added support for seprate target files. CRs-Fixed: 3012752 Change-Id: I5e066d5d871f58073f669c01270d5b64ce16088e Signed-off-by: Dharmender Sharma Signed-off-by: Shravya Samala --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 86 ++++++- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 6 + .../jpeg_hw/include/cam_jpeg_hw_intf.h | 18 ++ .../cam_jpeg_dma_165_hw_info_ver_4_2_0.h | 75 ++++++ .../cam_jpeg_dma_580_hw_info_ver_4_2_0.h | 75 ++++++ .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 242 +++++++++++++++++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 37 +++ .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 10 + .../cam_jpeg_enc_165_hw_info_ver_4_2_0.h | 102 ++++++++ .../cam_jpeg_enc_580_hw_info_ver_4_2_0.h | 102 ++++++++ .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 204 +++++++++++++++ .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h | 32 +++ .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 10 + 13 files changed, 994 insertions(+), 5 deletions(-) create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_165_hw_info_ver_4_2_0.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_580_hw_info_ver_4_2_0.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_165_hw_info_ver_4_2_0.h create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_580_hw_info_ver_4_2_0.h diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 8078ee59dc20..532f6a5a0c1e 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -142,6 +142,13 @@ static int cam_jpeg_process_next_hw_update(void *priv, void *data, CAM_TRACE(CAM_JPEG, "Start JPEG ENC Req %llu", config_args->request_id); + /* configure jpeg hw and camnoc misr */ + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_CONFIG_HW_MISR, + &g_jpeg_hw_mgr.camnoc_misr_test, + sizeof(g_jpeg_hw_mgr.camnoc_misr_test)); + rc = hw_mgr->devices[dev_type][0]->hw_ops.start( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { @@ -174,6 +181,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; struct crm_workq_task *task; struct cam_jpeg_process_frame_work_data_t *wq_task_data; + struct cam_jpeg_misr_dump_args misr_args; if (!data || !priv) { CAM_ERR(CAM_JPEG, "Invalid data"); @@ -203,8 +211,19 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) } p_cfg_req->num_hw_entry_processed++; - CAM_DBG(CAM_JPEG, "hw entry processed %d", - p_cfg_req->num_hw_entry_processed); + CAM_DBG(CAM_JPEG, "hw entry processed %d Encoded size :%d", + p_cfg_req->num_hw_entry_processed, task_data->result_size); + + misr_args.req_id = p_cfg_req->req_id; + misr_args.enable_bug = g_jpeg_hw_mgr.bug_on_misr; + CAM_DBG(CAM_JPEG, "req %lld bug is enabled for MISR :%d", + misr_args.req_id, misr_args.enable_bug); + + /* dump jpeg hw and camnoc misr */ + rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd( + hw_mgr->devices[dev_type][0]->hw_priv, + CAM_JPEG_CMD_DUMP_HW_MISR_VAL, &misr_args, + sizeof(struct cam_jpeg_misr_dump_args)); if ((task_data->result_size > 0) && (p_cfg_req->num_hw_entry_processed < @@ -298,7 +317,6 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) p_params = (struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr; p_params->output_size = task_data->result_size; - CAM_DBG(CAM_JPEG, "Encoded Size %d", task_data->result_size); buf_data.num_handles = p_cfg_req->hw_cfg_args.num_out_map_entries; @@ -1791,6 +1809,64 @@ static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args) return rc; } +static int cam_jpeg_set_camnoc_misr_test(void *data, u64 val) +{ + g_jpeg_hw_mgr.camnoc_misr_test = val; + return 0; +} + +static int cam_jpeg_get_camnoc_misr_test(void *data, u64 *val) +{ + *val = g_jpeg_hw_mgr.camnoc_misr_test; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(camnoc_misr_test, cam_jpeg_get_camnoc_misr_test, + cam_jpeg_set_camnoc_misr_test, "%08llu"); + +static int cam_jpeg_set_bug_on_misr(void *data, u64 val) +{ + g_jpeg_hw_mgr.bug_on_misr = val; + return 0; +} + +static int cam_jpeg_get_bug_on_misr(void *data, u64 *val) +{ + *val = g_jpeg_hw_mgr.bug_on_misr; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(bug_on_misr_mismatch, cam_jpeg_get_bug_on_misr, + cam_jpeg_set_bug_on_misr, "%08llu"); + +static int cam_jpeg_mgr_create_debugfs_entry(void) +{ + int rc = 0; + struct dentry *dbgfileptr = NULL; + + dbgfileptr = debugfs_create_dir("camera_jpeg", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_JPEG, "DebugFS could not create directory!"); + rc = -ENOENT; + goto err; + } + /* Store parent inode for cleanup in caller */ + g_jpeg_hw_mgr.dentry = dbgfileptr; + + dbgfileptr = debugfs_create_file("camnoc_misr_test", 0644, + g_jpeg_hw_mgr.dentry, NULL, &camnoc_misr_test); + + dbgfileptr = debugfs_create_file("bug_on_misr_mismatch", 0644, + g_jpeg_hw_mgr.dentry, NULL, &bug_on_misr_mismatch); + + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_JPEG, "DebugFS not enabled in kernel!"); + else + rc = PTR_ERR(dbgfileptr); + } +err: + return rc; +} + int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, int *iommu_hdl) { @@ -1877,7 +1953,9 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, if (iommu_hdl) *iommu_hdl = g_jpeg_hw_mgr.iommu_hdl; - return rc; + rc = cam_jpeg_mgr_create_debugfs_entry(); + if (!rc) + return rc; cdm_iommu_failed: cam_smmu_destroy_handle(g_jpeg_hw_mgr.iommu_hdl); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index c4cd35307701..34d98172b8b6 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -124,6 +124,9 @@ struct cam_jpeg_hw_ctx_data { * @process_irq_cb_work_data: Work data pool for irq requests * @cdm_iommu_hdl: Iommu handle received from cdm * @cdm_iommu_hdl_secure: Secure iommu handle received from cdm + * @dentry: Debugfs entry + * @camnoc_misr_test : debugfs entry to select camnoc_misr for read or write path + * @bug_on_misr : enable/disable bug on when misr mismatch is seen * @devices: Core hw Devices of JPEG hardware manager * @cdm_info: Cdm info for each core device. * @cdm_reg_map: Regmap of each device for cdm. @@ -147,6 +150,9 @@ struct cam_jpeg_hw_mgr { struct cam_jpeg_process_irq_work_data_t *process_irq_cb_work_data; int cdm_iommu_hdl; int cdm_iommu_hdl_secure; + struct dentry *dentry; + u64 camnoc_misr_test; + u64 bug_on_misr; struct cam_hw_intf **devices[CAM_JPEG_DEV_TYPE_MAX]; struct cam_jpeg_hw_cdm_info_t cdm_info[CAM_JPEG_DEV_TYPE_MAX] diff --git a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h index 1856e6e3cc13..9bb20da715ab 100644 --- a/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h +++ b/drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h @@ -18,6 +18,11 @@ #define CAM_JPEG_HW_DUMP_TAG_MAX_LEN 32 #define CAM_JPEG_HW_DUMP_NUM_WORDS 5 #define CAM_JPEG_HW_MAX_NUM_PID 2 +#define CAM_JPEG_CAMNOC_MISR_VAL_ROW 2 +#define CAM_JPEG_CAMNOC_MISR_VAL_COL 4 +#define CAM_JPEG_ENC_MISR_VAL_NUM 3 +#define CAM_JPEG_MISR_ID_LOW_RD 0 +#define CAM_JPEG_MISR_ID_LOW_WR 1 enum cam_jpeg_hw_type { CAM_JPEG_DEV_ENC, @@ -51,12 +56,25 @@ struct cam_jpeg_match_pid_args { uint32_t match_res; }; +/** + * struct cam_jpeg_misr_dump_args + * @req_id: Request Id + * @enable_bug: This flag indicates whether BUG_ON(1) has to be called or not + * on MISR mismatch + */ +struct cam_jpeg_misr_dump_args { + uint32_t req_id; + bool enable_bug; +}; + enum cam_jpeg_cmd_type { CAM_JPEG_CMD_CDM_CFG, CAM_JPEG_CMD_SET_IRQ_CB, CAM_JPEG_CMD_HW_DUMP, CAM_JPEG_CMD_GET_NUM_PID, CAM_JPEG_CMD_MATCH_PID_MID, + CAM_JPEG_CMD_CONFIG_HW_MISR, + CAM_JPEG_CMD_DUMP_HW_MISR_VAL, CAM_JPEG_CMD_MAX, }; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_165_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_165_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..81e146938265 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_165_hw_info_ver_4_2_0.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_DMA_165_HW_INFO_VER_4_2_0_H +#define CAM_JPEG_DMA_165_HW_INFO_VER_4_2_0_H + +#define CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE (1 << 0) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RD_BUF_DONE (1 << 1) +#define CAM_JPEGDMA_HW_IRQ_STATUS_WR_BUF_DONE (1 << 5) +#define CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT (1 << 9) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE (1 << 10) + +#define CAM_JPEG_HW_MASK_SCALE_ENABLE 0x1 + +#define CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE +#define CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK \ + CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE + +static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_165_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x14, + .int_status = 0x10, + .int_mask = 0x0C, + .hw_cmd = 0x1C, + .reset_cmd = 0x08, + .encode_size = 0x180, + .core_cfg = 0x18, + .misr_cfg0 = 0x160, + .misr_cfg1 = 0x164, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x32083, + .hw_cmd_stop = 0x00000004, + .misr_cfg0 = 0x506, + }, + .int_status = { + .framedone = CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK, + .iserror = 0x0, + .stopdone = CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT, + .scale_enable = CAM_JPEG_HW_MASK_SCALE_ENABLE, + .scale_enable_shift = 0x4, + }, + .camnoc_misr_reg_offset = { + .main_ctl = 0x5908, + .id_mask_low = 0x5920, + .id_value_low = 0x5918, + .misc_ctl = 0x5910, + .sigdata0 = 0x5950, + }, + .camnoc_misr_reg_val = { + .main_ctl = 0x7, + .id_mask_low = 0xFC0, + .id_value_low_rd = 0xD00, + .id_value_low_wr = 0xD42, + .misc_ctl_start = 0x1, + .misc_ctl_stop = 0x2, + }, + .max_misr = 3, + .max_misr_rd = 4, + .max_misr_wr = 4, + .camnoc_misr_sigdata = 4, + .master_we_sel = 2, + .misr_rd_word_sel = 4, +}; + +#endif /* CAM_JPEG_DMA_165_HW_INFO_VER_4_2_0_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_580_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_580_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..b4f4ce10325d --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_580_hw_info_ver_4_2_0.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_DMA_580_HW_INFO_VER_4_2_0_H +#define CAM_JPEG_DMA_580_HW_INFO_VER_4_2_0_H + +#define CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE (1 << 0) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RD_BUF_DONE (1 << 1) +#define CAM_JPEGDMA_HW_IRQ_STATUS_WR_BUF_DONE (1 << 5) +#define CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT (1 << 9) +#define CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE (1 << 10) + +#define CAM_JPEG_HW_MASK_SCALE_ENABLE 0x1 + +#define CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE +#define CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK \ + CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE + +static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_580_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x14, + .int_status = 0x10, + .int_mask = 0x0C, + .hw_cmd = 0x1C, + .reset_cmd = 0x08, + .encode_size = 0x180, + .core_cfg = 0x18, + .misr_cfg0 = 0x160, + .misr_cfg1 = 0x164, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x32083, + .hw_cmd_stop = 0x00000004, + .misr_cfg0 = 0x506, + }, + .int_status = { + .framedone = CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK, + .iserror = 0x0, + .stopdone = CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT, + .scale_enable = CAM_JPEG_HW_MASK_SCALE_ENABLE, + .scale_enable_shift = 0x4, + }, + .camnoc_misr_reg_offset = { + .main_ctl = 0x3608, + .id_mask_low = 0x3620, + .id_value_low = 0x3618, + .misc_ctl = 0x3610, + .sigdata0 = 0x3650, + }, + .camnoc_misr_reg_val = { + .main_ctl = 0x7, + .id_mask_low = 0xFC0, + .id_value_low_rd = 0xD00, + .id_value_low_wr = 0xD42, + .misc_ctl_start = 0x1, + .misc_ctl_stop = 0x2, + }, + .max_misr = 3, + .max_misr_rd = 4, + .max_misr_wr = 4, + .camnoc_misr_sigdata = 4, + .master_we_sel = 2, + .misr_rd_word_sel = 4, +}; + +#endif /* CAM_JPEG_DMA_580_HW_INFO_VER_4_2_0_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c index bae4f3d9982d..081a52dca755 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -372,13 +372,236 @@ int cam_jpeg_dma_stop_hw(void *data, return 0; } +int cam_jpeg_dma_dump_camnoc_misr_val(struct cam_jpeg_dma_device_hw_info *hw_info, + struct cam_hw_soc_info *soc_info, void *cmd_args) +{ + void __iomem *dma_mem_base = NULL; + void __iomem *camnoc_mem_base = NULL; + struct cam_jpeg_misr_dump_args *pmisr_args; + int32_t camnoc_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL] = {{0}}; + int i, rc = 0; + int32_t val; + uint32_t index = 0; + bool mismatch = false; + + dma_mem_base = soc_info->reg_map[0].mem_base; + camnoc_mem_base = soc_info->reg_map[1].mem_base; + pmisr_args = (struct cam_jpeg_misr_dump_args *)cmd_args; + if (!pmisr_args) { + CAM_ERR(CAM_JPEG, "Invalid command argument"); + return -EINVAL; + } + val = cam_io_r_mb(dma_mem_base + hw_info->reg_offset.core_cfg); + index = (val >> hw_info->int_status.scale_enable_shift) & + hw_info->int_status.scale_enable; + CAM_DBG(CAM_JPEG, "index %d", index); + + for (i = 0; i < hw_info->camnoc_misr_sigdata; i++) { + camnoc_misr_val[index][i] = cam_io_r_mb(camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.sigdata0 + (i * 8)); + if (hw_info->prev_camnoc_misr_val[index][i] != + camnoc_misr_val[index][i]) + mismatch = true; + } + if (mismatch && (pmisr_args->req_id != 1)) { + CAM_ERR(CAM_JPEG, + "CAMNOC DMA_MISR MISMATCH [req:%d][i:%d][index:%d]\n" + "curr:0x%x %x %x %x prev:0x%x %x %x %x isbug:%d", + pmisr_args->req_id, i, index, + camnoc_misr_val[index][3], camnoc_misr_val[index][2], + camnoc_misr_val[index][1], camnoc_misr_val[index][0], + hw_info->prev_camnoc_misr_val[index][3], + hw_info->prev_camnoc_misr_val[index][2], + hw_info->prev_camnoc_misr_val[index][1], + hw_info->prev_camnoc_misr_val[index][0], + pmisr_args->enable_bug); + if (pmisr_args->enable_bug) + BUG_ON(1); + } + CAM_DBG(CAM_JPEG, + "CAMNOC DMA_MISR req:%d SigData:0x %x %x %x %x", + pmisr_args->req_id, + camnoc_misr_val[index][3], camnoc_misr_val[index][2], + camnoc_misr_val[index][1], camnoc_misr_val[index][0]); + mismatch = false; + for (i = 0; i < hw_info->camnoc_misr_sigdata; i++) + hw_info->prev_camnoc_misr_val[index][i] = + camnoc_misr_val[index][i]; + /* stop misr : cam_noc_cam_noc_0_req_link_misrprb_MiscCtl_Low */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.misc_ctl_stop, + camnoc_mem_base + hw_info->camnoc_misr_reg_offset.misc_ctl); + + return rc; +} + +int cam_jpeg_dma_dump_hw_misr_val(struct cam_jpeg_dma_device_hw_info *hw_info, + struct cam_hw_soc_info *soc_info, void *cmd_args) +{ + void __iomem *dma_mem_base = NULL; + void __iomem *camnoc_mem_base = NULL; + struct cam_jpeg_misr_dump_args *pmisr_args; + int32_t dma_wr_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL] = {{0}}; + int32_t dma_rd_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL] = {{0}}; + int offset, i, rc = 0; + int32_t val; + uint32_t index = 0; + bool mismatch = false; + + dma_mem_base = soc_info->reg_map[0].mem_base; + camnoc_mem_base = soc_info->reg_map[1].mem_base; + pmisr_args = (struct cam_jpeg_misr_dump_args *)cmd_args; + if (!pmisr_args) { + CAM_ERR(CAM_JPEG, "Invalid command argument"); + return -EINVAL; + } + val = cam_io_r_mb(dma_mem_base + hw_info->reg_offset.core_cfg); + index = (val >> hw_info->int_status.scale_enable_shift) & + hw_info->int_status.scale_enable; + CAM_DBG(CAM_JPEG, "index %d", index); + + /* After the session is complete, read back the MISR values. + * fetch engine MISR values + */ + offset = hw_info->reg_offset.misr_cfg1; + for (i = 0; i < hw_info->max_misr_rd; i++) { + val = i << hw_info->misr_rd_word_sel; + cam_io_w_mb(val, dma_mem_base + offset); + dma_rd_misr_val[index][i] = cam_io_r_mb(dma_mem_base + + offset + 0x4); + if (hw_info->prev_dma_rd_misr_val[index][i] != dma_rd_misr_val[index][i]) + mismatch = true; + } + if (mismatch && (pmisr_args->req_id != 1)) { + CAM_ERR(CAM_JPEG, + "CAMNOC DMA_RD_MISR MISMATCH [req:%d][index:%d][i:%d]\n" + "curr:0x%x %x %x %x prev:0x%x %x %x %x isbug:%d", + pmisr_args->req_id, index, i, + dma_rd_misr_val[index][3], dma_rd_misr_val[index][2], + dma_rd_misr_val[index][1], dma_rd_misr_val[index][0], + hw_info->prev_dma_rd_misr_val[index][3], + hw_info->prev_dma_rd_misr_val[index][2], + hw_info->prev_dma_rd_misr_val[index][1], + hw_info->prev_dma_rd_misr_val[index][0], + pmisr_args->enable_bug); + if (pmisr_args->enable_bug) + BUG_ON(1); + } + + CAM_DBG(CAM_JPEG, + "CORE JPEG DMA RD MISR: 0x%x %x %x %x", + dma_rd_misr_val[index][3], dma_rd_misr_val[index][2], + dma_rd_misr_val[index][1], dma_rd_misr_val[index][0]); + + mismatch = false; + for (i = 0; i < hw_info->max_misr_rd; i++) { + hw_info->prev_dma_rd_misr_val[index][i] = + dma_rd_misr_val[index][i]; + } + + /* write engine MISR values */ + for (i = 0; i < hw_info->max_misr_wr; i++) { + val = hw_info->master_we_sel | (i << hw_info->misr_rd_word_sel); + cam_io_w_mb(val, dma_mem_base + offset); + dma_wr_misr_val[index][i] = cam_io_r_mb(dma_mem_base + + offset + 0x4); + if (hw_info->prev_dma_wr_misr_val[index][i] != + dma_wr_misr_val[index][i]) + mismatch = true; + } + if (mismatch && (pmisr_args->req_id != 1)) { + CAM_ERR(CAM_JPEG, + "CAMNOC DMA_WR_MISR MISMATCH [req:%d][index:%d][i:%d]\n" + "curr:0x%x %x %x %x prev:0x%x %x %x %x isbug:%d", + pmisr_args->req_id, index, i, + dma_wr_misr_val[index][3], dma_wr_misr_val[index][2], + dma_wr_misr_val[index][1], dma_wr_misr_val[index][0], + hw_info->prev_dma_wr_misr_val[index][3], + hw_info->prev_dma_wr_misr_val[index][2], + hw_info->prev_dma_wr_misr_val[index][1], + hw_info->prev_dma_wr_misr_val[index][0], + pmisr_args->enable_bug); + if (pmisr_args->enable_bug) + BUG_ON(1); + } + CAM_DBG(CAM_JPEG, + "CORE JPEG DMA WR MISR: 0x%x %x %x %x", + dma_wr_misr_val[index][3], dma_wr_misr_val[index][2], + dma_wr_misr_val[index][1], dma_wr_misr_val[index][0]); + + mismatch = false; + for (i = 0; i < hw_info->max_misr_wr; i++) { + hw_info->prev_dma_wr_misr_val[index][i] = + dma_wr_misr_val[index][i]; + } + + return rc; +} + +int cam_jpeg_dma_config_cmanoc_hw_misr(struct cam_jpeg_dma_device_hw_info *hw_info, + struct cam_hw_soc_info *soc_info, void *cmd_args) +{ + void __iomem *dma_mem_base = NULL; + void __iomem *camnoc_mem_base = NULL; + uint32_t *camnoc_misr_test = NULL; + int val = 0; + + dma_mem_base = soc_info->reg_map[0].mem_base; + camnoc_mem_base = soc_info->reg_map[1].mem_base; + if (!camnoc_mem_base) { + CAM_ERR(CAM_JPEG, "Invalid camnoc base address"); + return -EINVAL; + } + camnoc_misr_test = (uint32_t *)cmd_args; + if (!camnoc_misr_test) { + CAM_ERR(CAM_JPEG, "Invalid command argument"); + return -EINVAL; + } + /* enable FE and WE with sample data mode */ + cam_io_w_mb(hw_info->reg_val.misr_cfg0, dma_mem_base + + hw_info->reg_offset.misr_cfg0); + + /* cam_noc_cam_noc_0_req_link_misrprb_MainCtl_Low + * enable CRC generation on both RD, WR and transaction payload + */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.main_ctl, camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.main_ctl); + /* cam_noc_cam_noc_0_req_link_misrprb_IdMask_Low */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.main_ctl, camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.id_mask_low); + /* cam_noc_cam_noc_0_req_link_misrprb_IdValue_Low */ + switch (*camnoc_misr_test) { + case CAM_JPEG_MISR_ID_LOW_RD: + val = hw_info->camnoc_misr_reg_val.id_value_low_rd; + break; + case CAM_JPEG_MISR_ID_LOW_WR: + val = hw_info->camnoc_misr_reg_val.id_value_low_wr; + break; + default: + val = hw_info->camnoc_misr_reg_val.id_value_low_rd; + break; + } + cam_io_w_mb(val, camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.id_value_low); + /* start/reset misr : cam_noc_cam_noc_0_req_link_misrprb_MiscCtl_Low */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.misc_ctl_start, + camnoc_mem_base + hw_info->camnoc_misr_reg_offset.misc_ctl); + CAM_DBG(CAM_JPEG, "DMA CAMNOC and HW MISR configured"); + + return 0; +} + int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = device_priv; struct cam_jpeg_dma_device_core_info *core_info = NULL; + struct cam_jpeg_dma_device_hw_info *hw_info = NULL; struct cam_jpeg_match_pid_args *match_pid_mid = NULL; - uint32_t *num_pid = NULL; + uint32_t *num_pid = NULL; + struct cam_hw_soc_info *soc_info = NULL; int i, rc = 0; if (!device_priv) { @@ -394,6 +617,10 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; + hw_info = core_info->jpeg_dma_hw_info; + soc_info = &jpeg_dma_dev->soc_info; + + switch (cmd_type) { case CAM_JPEG_CMD_SET_IRQ_CB: { @@ -455,6 +682,19 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, } break; + case CAM_JPEG_CMD_CONFIG_HW_MISR: + { + rc = cam_jpeg_dma_config_cmanoc_hw_misr(hw_info, soc_info, cmd_args); + break; + } + case CAM_JPEG_CMD_DUMP_HW_MISR_VAL: + { + rc = cam_jpeg_dma_dump_hw_misr_val(hw_info, soc_info, cmd_args); + if (rc) + break; + rc = cam_jpeg_dma_dump_camnoc_misr_val(hw_info, soc_info, cmd_args); + break; + } default: rc = -EINVAL; break; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h index 8f08033b04f6..c8c398072306 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -22,6 +22,9 @@ struct cam_jpeg_dma_reg_offsets { uint32_t hw_cmd; uint32_t reset_cmd; uint32_t encode_size; + uint32_t core_cfg; + uint32_t misr_cfg0; + uint32_t misr_cfg1; }; struct cam_jpeg_dma_regval { @@ -31,6 +34,7 @@ struct cam_jpeg_dma_regval { uint32_t hw_cmd_start; uint32_t reset_cmd; uint32_t hw_cmd_stop; + uint32_t misr_cfg0; }; struct cam_jpeg_dma_int_status { @@ -38,12 +42,45 @@ struct cam_jpeg_dma_int_status { uint32_t resetdone; uint32_t iserror; uint32_t stopdone; + uint32_t scale_enable; + uint32_t scale_enable_shift; +}; + +struct cam_jpeg_dma_camnoc_misr_reg_offset { + uint32_t main_ctl; + uint32_t id_mask_low; + uint32_t id_value_low; + uint32_t misc_ctl; + uint32_t sigdata0; +}; + +struct cam_jpeg_dma_camnoc_misr_reg_val { + uint32_t main_ctl; + uint32_t id_mask_low; + uint32_t id_value_low_rd; + uint32_t id_value_low_wr; + uint32_t misc_ctl_start; + uint32_t misc_ctl_stop; }; struct cam_jpeg_dma_device_hw_info { struct cam_jpeg_dma_reg_offsets reg_offset; struct cam_jpeg_dma_regval reg_val; struct cam_jpeg_dma_int_status int_status; + struct cam_jpeg_dma_camnoc_misr_reg_offset camnoc_misr_reg_offset; + struct cam_jpeg_dma_camnoc_misr_reg_val camnoc_misr_reg_val; + uint32_t max_misr; + uint32_t max_misr_rd; + uint32_t max_misr_wr; + uint32_t camnoc_misr_sigdata; + uint32_t master_we_sel; + uint32_t misr_rd_word_sel; + int32_t prev_dma_wr_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL]; + int32_t prev_dma_rd_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL]; + int32_t prev_camnoc_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL]; }; enum cam_jpeg_dma_core_state { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index c5c4b78cc1f4..512fc3225c20 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -19,6 +19,8 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" #include "cam_jpeg_dma_hw_info_ver_4_2_0.h" +#include "cam_jpeg_dma_165_hw_info_ver_4_2_0.h" +#include "cam_jpeg_dma_580_hw_info_ver_4_2_0.h" #include "camera_main.h" static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, @@ -238,6 +240,14 @@ static const struct of_device_id cam_jpeg_dma_dt_match[] = { .compatible = "qcom,cam_jpeg_dma", .data = &cam_jpeg_dma_hw_info, }, + { + .compatible = "qcom,cam_jpeg_dma_165", + .data = &cam_jpeg_dma_165_hw_info, + }, + { + .compatible = "qcom,cam_jpeg_dma_580", + .data = &cam_jpeg_dma_580_hw_info, + }, {} }; MODULE_DEVICE_TABLE(of, cam_jpeg_dma_dt_match); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_165_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_165_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..af434b2928bd --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_165_hw_info_ver_4_2_0.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_ENC_165_HW_INFO_TITAN170_H +#define CAM_JPEG_ENC_165_HW_INFO_TITAN170_H + +#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001 +#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000 + +#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000 +#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a + +#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK 0x8000000 +#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_SHIFT 0x0000001b + +#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800 +#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b + +#define CAM_JPEG_HW_MASK_SCALE_ENABLE 0x1 + +#define CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF (0x1<<19) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR (0x1<<20) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR (0x1<<21) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF (0x1<<22) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW (0x1<<23) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM (0x1<<24) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ (0x1<<25) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM (0x1<<26) +#define CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK (0x1<<29) + +#define CAM_JPEG_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK +#define CAM_JPEG_HW_MASK_COMP_RESET_ACK \ + CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK +#define CAM_JPEG_HW_MASK_COMP_ERR \ + (CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM | \ + CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK) + +static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_165_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x1c, + .int_status = 0x20, + .int_mask = 0x18, + .hw_cmd = 0x10, + .reset_cmd = 0x8, + .encode_size = 0x180, + .core_cfg = 0xc, + .misr_cfg = 0x2B4, + .misr_rd0 = 0x2B8, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x200320D3, + .hw_cmd_stop = 0x00000002, + .misr_cfg = 0x7, + }, + .int_status = { + .framedone = CAM_JPEG_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK, + .iserror = CAM_JPEG_HW_MASK_COMP_ERR, + .stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK, + .scale_enable = CAM_JPEG_HW_MASK_SCALE_ENABLE, + .scale_enable_shift = 0x7, + }, + .reg_dump = { + .start_offset = 0x0, + .end_offset = 0x33C, + }, + .camnoc_misr_reg_offset = { + .main_ctl = 0x5908, + .id_mask_low = 0x5920, + .id_value_low = 0x5918, + .misc_ctl = 0x5910, + .sigdata0 = 0x5950, + }, + .camnoc_misr_reg_val = { + .main_ctl = 0x7, + .id_mask_low = 0xFC0, + .id_value_low_rd = 0xD80, + .id_value_low_wr = 0xDC2, + .misc_ctl_start = 0x1, + .misc_ctl_stop = 0x2, + }, + .max_misr = 3, + .max_misr_rd = 4, + .camnoc_misr_sigdata = 4, +}; + +#endif /* CAM_JPEG_ENC_165_HW_INFO_TITAN170_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_580_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_580_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..647bdb514957 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_580_hw_info_ver_4_2_0.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef CAM_JPEG_ENC_580_HW_INFO_TITAN170_H +#define CAM_JPEG_ENC_580_HW_INFO_TITAN170_H + +#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001 +#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000 + +#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000 +#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a + +#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK 0x8000000 +#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_SHIFT 0x0000001b + +#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800 +#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b + +#define CAM_JPEG_HW_MASK_SCALE_ENABLE 0x1 + +#define CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF (0x1<<19) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR (0x1<<20) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR (0x1<<21) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF (0x1<<22) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW (0x1<<23) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM (0x1<<24) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ (0x1<<25) +#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM (0x1<<26) +#define CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK (0x1<<29) + +#define CAM_JPEG_HW_MASK_COMP_FRAMEDONE \ + CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK +#define CAM_JPEG_HW_MASK_COMP_RESET_ACK \ + CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK +#define CAM_JPEG_HW_MASK_COMP_ERR \ + (CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ | \ + CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM | \ + CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK) + +static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_580_hw_info = { + .reg_offset = { + .hw_version = 0x0, + .int_clr = 0x1c, + .int_status = 0x20, + .int_mask = 0x18, + .hw_cmd = 0x10, + .reset_cmd = 0x8, + .encode_size = 0x180, + .core_cfg = 0xc, + .misr_cfg = 0x2B4, + .misr_rd0 = 0x2B8, + }, + .reg_val = { + .int_clr_clearall = 0xFFFFFFFF, + .int_mask_disable_all = 0x00000000, + .int_mask_enable_all = 0xFFFFFFFF, + .hw_cmd_start = 0x00000001, + .reset_cmd = 0x200320D3, + .hw_cmd_stop = 0x00000002, + .misr_cfg = 0x7, + }, + .int_status = { + .framedone = CAM_JPEG_HW_MASK_COMP_FRAMEDONE, + .resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK, + .iserror = CAM_JPEG_HW_MASK_COMP_ERR, + .stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK, + .scale_enable = CAM_JPEG_HW_MASK_SCALE_ENABLE, + .scale_enable_shift = 0x7, + }, + .reg_dump = { + .start_offset = 0x0, + .end_offset = 0x33C, + }, + .camnoc_misr_reg_offset = { + .main_ctl = 0x3608, + .id_mask_low = 0x3620, + .id_value_low = 0x3618, + .misc_ctl = 0x3610, + .sigdata0 = 0x3650, + }, + .camnoc_misr_reg_val = { + .main_ctl = 0x7, + .id_mask_low = 0xFC0, + .id_value_low_rd = 0xD80, + .id_value_low_wr = 0xDC2, + .misc_ctl_start = 0x1, + .misc_ctl_stop = 0x2, + }, + .max_misr = 3, + .max_misr_rd = 4, + .camnoc_misr_sigdata = 4, +}; + +#endif /* CAM_JPEG_ENC_580_HW_INFO_TITAN170_H */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index 5f79260e1391..a767bb2bc75b 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -493,13 +493,201 @@ int cam_jpeg_enc_hw_dump( return 0; } +int cam_jpeg_enc_dump_camnoc_misr_val(struct cam_jpeg_enc_device_hw_info *hw_info, + struct cam_hw_soc_info *soc_info, void *cmd_args) +{ + void __iomem *enc_mem_base = NULL; + void __iomem *camnoc_mem_base = NULL; + struct cam_jpeg_misr_dump_args *pmisr_args; + int32_t val; + uint32_t index = 0; + int i; + bool mismatch = false; + int32_t camnoc_misr_val[CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL] = {{0}}; + + enc_mem_base = soc_info->reg_map[0].mem_base; + camnoc_mem_base = soc_info->reg_map[1].mem_base; + if (!camnoc_mem_base) { + CAM_ERR(CAM_JPEG, "Invalid camnoc base address"); + return -EINVAL; + } + pmisr_args = (struct cam_jpeg_misr_dump_args *)cmd_args; + if (!pmisr_args) { + CAM_ERR(CAM_JPEG, "Invalid command argument"); + return -EINVAL; + } + + val = cam_io_r_mb(enc_mem_base + hw_info->reg_offset.core_cfg); + index = (val >> hw_info->int_status.scale_enable_shift) & + hw_info->int_status.scale_enable; + CAM_DBG(CAM_JPEG, "index %d", index); + + for (i = 0; i < hw_info->camnoc_misr_sigdata; i++) { + camnoc_misr_val[index][i] = cam_io_r_mb(camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.sigdata0 + (i * 8)); + if (hw_info->prev_camnoc_misr_val[index][i] != camnoc_misr_val[index][i]) + mismatch = true; + } + if (mismatch && (pmisr_args->req_id != 1)) { + CAM_ERR(CAM_JPEG, + "CAMNOC ENC_MISR MISMATCH [req:%d][i:%d][index:%d]\n" + "curr SigData:0x%x %x %x %x prev SigData:0x%x %x %x %x isbug:%d", + pmisr_args->req_id, i, index, + camnoc_misr_val[index][3], camnoc_misr_val[index][2], + camnoc_misr_val[index][1], camnoc_misr_val[index][0], + hw_info->prev_camnoc_misr_val[index][3], + hw_info->prev_camnoc_misr_val[index][2], + hw_info->prev_camnoc_misr_val[index][1], + hw_info->prev_camnoc_misr_val[index][0], pmisr_args->enable_bug); + if (pmisr_args->enable_bug) + BUG_ON(1); + } + CAM_DBG(CAM_JPEG, + "CAMNOC ENC MISR req:%d SigData:0x%x %x %x %x", + pmisr_args->req_id, + camnoc_misr_val[index][3], camnoc_misr_val[index][2], + camnoc_misr_val[index][1], camnoc_misr_val[index][0]); + mismatch = false; + for (i = 0; i < hw_info->camnoc_misr_sigdata; i++) + hw_info->prev_camnoc_misr_val[index][i] = camnoc_misr_val[index][i]; + /* stop misr : cam_noc_cam_noc_0_req_link_misrprb_MiscCtl_Low */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.misc_ctl_stop, + camnoc_mem_base + hw_info->camnoc_misr_reg_offset.misc_ctl); + return 0; +} + +int cam_jpeg_enc_dump_hw_misr_val(struct cam_jpeg_enc_device_hw_info *hw_info, + struct cam_hw_soc_info *soc_info, void *cmd_args) +{ + void __iomem *enc_mem_base = NULL; + void __iomem *camnoc_mem_base = NULL; + struct cam_jpeg_misr_dump_args *pmisr_args; + int32_t val; + uint32_t index = 0; + int offset, i, j; + bool mismatch = false; + int32_t enc_misr_val[CAM_JPEG_ENC_MISR_VAL_NUM][CAM_JPEG_CAMNOC_MISR_VAL_ROW][ + CAM_JPEG_CAMNOC_MISR_VAL_COL] = {{{0}}}; + + enc_mem_base = soc_info->reg_map[0].mem_base; + camnoc_mem_base = soc_info->reg_map[1].mem_base; + if (!camnoc_mem_base) { + CAM_ERR(CAM_JPEG, "Invalid camnoc base address"); + return -EINVAL; + } + pmisr_args = (struct cam_jpeg_misr_dump_args *)cmd_args; + if (!pmisr_args) { + CAM_ERR(CAM_JPEG, "Invalid command argument"); + return -EINVAL; + } + + val = cam_io_r_mb(enc_mem_base + hw_info->reg_offset.core_cfg); + index = (val >> hw_info->int_status.scale_enable_shift) & + hw_info->int_status.scale_enable; + CAM_DBG(CAM_JPEG, "index %d", index); + + for (i = 0; i < hw_info->max_misr; i++) { + offset = hw_info->reg_offset.misr_rd0 + (i * 0x10); + for (j = 0; j < hw_info->max_misr_rd; j++) { + enc_misr_val[i][index][j] = cam_io_r_mb(enc_mem_base + + offset + (j * 4)); + if (hw_info->prev_enc_misr_val[i][index][j] != + enc_misr_val[i][index][j]) + mismatch = true; + } + if (mismatch && (pmisr_args->req_id != 1)) { + CAM_ERR(CAM_JPEG, + "ENC_MISR RD MISMATCH [req:%d][i:%d][index:%d][j:%d]\n" + "curr:0x%x %x %x %x prev:0x%x %x %x %x isbug:%d", + pmisr_args->req_id, i, index, j, enc_misr_val[i][index][3], + enc_misr_val[i][index][2], enc_misr_val[i][index][1], + enc_misr_val[i][index][0], hw_info->prev_enc_misr_val[i][index][3], + hw_info->prev_enc_misr_val[i][index][2], + hw_info->prev_enc_misr_val[i][index][1], + hw_info->prev_enc_misr_val[i][index][0], pmisr_args->enable_bug); + if (pmisr_args->enable_bug) + BUG_ON(1); + } + CAM_DBG(CAM_JPEG, "ENC_MISR RD [req:%d][%d]: 0x%x %x %x %x", + pmisr_args->req_id, i, + enc_misr_val[i][index][3], enc_misr_val[i][index][2], + enc_misr_val[i][index][1], enc_misr_val[i][index][0]); + mismatch = false; + + for (j = 0; j < hw_info->max_misr_rd; j++) + hw_info->prev_enc_misr_val[i][index][j] = enc_misr_val[i][index][j]; + } + + return 0; +} + +int cam_jpeg_enc_config_cmanoc_hw_misr(struct cam_jpeg_enc_device_hw_info *hw_info, + struct cam_hw_soc_info *soc_info, void *cmd_args) +{ + void __iomem *enc_mem_base = NULL; + void __iomem *camnoc_mem_base = NULL; + uint32_t *camnoc_misr_test = NULL; + int val = 0; + + enc_mem_base = soc_info->reg_map[0].mem_base; + camnoc_mem_base = soc_info->reg_map[1].mem_base; + if (!camnoc_mem_base) { + CAM_ERR(CAM_JPEG, "Invalid camnoc base address"); + return -EINVAL; + } + camnoc_misr_test = (uint32_t *)cmd_args; + if (!camnoc_misr_test) { + CAM_ERR(CAM_JPEG, "Invalid command argument"); + return -EINVAL; + } + + /* enable all MISRs */ + cam_io_w_mb(hw_info->reg_val.misr_cfg, enc_mem_base + + hw_info->reg_offset.misr_cfg); + + /* cam_noc_cam_noc_0_req_link_misrprb_MainCtl_Low + * enable CRC generation on both RD, WR and transaction payload + */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.main_ctl, camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.main_ctl); + + /* cam_noc_cam_noc_0_req_link_misrprb_IdMask_Low */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.main_ctl, camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.id_mask_low); + + /* cam_noc_cam_noc_0_req_link_misrprb_IdValue_Low */ + switch (*camnoc_misr_test) { + case CAM_JPEG_MISR_ID_LOW_RD: + val = hw_info->camnoc_misr_reg_val.id_value_low_rd; + break; + case CAM_JPEG_MISR_ID_LOW_WR: + val = hw_info->camnoc_misr_reg_val.id_value_low_wr; + break; + default: + val = hw_info->camnoc_misr_reg_val.id_value_low_rd; + break; + } + cam_io_w_mb(val, camnoc_mem_base + + hw_info->camnoc_misr_reg_offset.id_value_low); + + /* start/reset misr : cam_noc_cam_noc_0_req_link_misrprb_MiscCtl_Low */ + cam_io_w_mb(hw_info->camnoc_misr_reg_val.misc_ctl_start, + camnoc_mem_base + hw_info->camnoc_misr_reg_offset.misc_ctl); + CAM_DBG(CAM_JPEG, "ENC CAMNOC MISR configured"); + + return 0; +} + int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { struct cam_hw_info *jpeg_enc_dev = device_priv; struct cam_jpeg_enc_device_core_info *core_info = NULL; + struct cam_jpeg_enc_device_hw_info *hw_info = NULL; struct cam_jpeg_match_pid_args *match_pid_mid = NULL; uint32_t *num_pid = NULL; + struct cam_hw_soc_info *soc_info = NULL; int i, rc = 0; if (!device_priv) { @@ -515,6 +703,9 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, core_info = (struct cam_jpeg_enc_device_core_info *) jpeg_enc_dev->core_info; + hw_info = core_info->jpeg_enc_hw_info; + soc_info = &jpeg_enc_dev->soc_info; + switch (cmd_type) { case CAM_JPEG_CMD_SET_IRQ_CB: { @@ -582,6 +773,19 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type, } break; + case CAM_JPEG_CMD_CONFIG_HW_MISR: + { + rc = cam_jpeg_enc_config_cmanoc_hw_misr(hw_info, soc_info, cmd_args); + break; + } + case CAM_JPEG_CMD_DUMP_HW_MISR_VAL: + { + rc = cam_jpeg_enc_dump_hw_misr_val(hw_info, soc_info, cmd_args); + if (rc) + break; + rc = cam_jpeg_enc_dump_camnoc_misr_val(hw_info, soc_info, cmd_args); + break; + } default: rc = -EINVAL; break; diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h index 8dfc443ccd70..af52512ac43c 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h @@ -21,6 +21,9 @@ struct cam_jpeg_enc_reg_offsets { uint32_t hw_cmd; uint32_t reset_cmd; uint32_t encode_size; + uint32_t core_cfg; + uint32_t misr_cfg; + uint32_t misr_rd0; }; struct cam_jpeg_enc_regval { @@ -30,6 +33,7 @@ struct cam_jpeg_enc_regval { uint32_t hw_cmd_start; uint32_t reset_cmd; uint32_t hw_cmd_stop; + uint32_t misr_cfg; }; struct cam_jpeg_enc_int_status { @@ -37,6 +41,8 @@ struct cam_jpeg_enc_int_status { uint32_t resetdone; uint32_t iserror; uint32_t stopdone; + uint32_t scale_enable; + uint32_t scale_enable_shift; }; struct cam_jpeg_enc_reg_dump { @@ -44,11 +50,37 @@ struct cam_jpeg_enc_reg_dump { uint32_t end_offset; }; +struct cam_jpeg_enc_camnoc_misr_reg_offset { + uint32_t main_ctl; + uint32_t id_mask_low; + uint32_t id_value_low; + uint32_t misc_ctl; + uint32_t sigdata0; +}; + +struct cam_jpeg_enc_camnoc_misr_reg_val { + uint32_t main_ctl; + uint32_t id_mask_low; + uint32_t id_value_low_rd; + uint32_t id_value_low_wr; + uint32_t misc_ctl_start; + uint32_t misc_ctl_stop; +}; + struct cam_jpeg_enc_device_hw_info { struct cam_jpeg_enc_reg_offsets reg_offset; struct cam_jpeg_enc_regval reg_val; struct cam_jpeg_enc_int_status int_status; struct cam_jpeg_enc_reg_dump reg_dump; + struct cam_jpeg_enc_camnoc_misr_reg_offset camnoc_misr_reg_offset; + struct cam_jpeg_enc_camnoc_misr_reg_val camnoc_misr_reg_val; + uint32_t max_misr; + uint32_t max_misr_rd; + uint32_t camnoc_misr_sigdata; + int32_t prev_camnoc_misr_val[ + CAM_JPEG_CAMNOC_MISR_VAL_ROW][CAM_JPEG_CAMNOC_MISR_VAL_COL]; + int32_t prev_enc_misr_val[CAM_JPEG_ENC_MISR_VAL_NUM][ + CAM_JPEG_CAMNOC_MISR_VAL_ROW][CAM_JPEG_CAMNOC_MISR_VAL_COL]; }; enum cam_jpeg_enc_core_state { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index 5b6c307778a8..467d39958fe4 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -19,6 +19,8 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" #include "cam_jpeg_enc_hw_info_ver_4_2_0.h" +#include "cam_jpeg_enc_165_hw_info_ver_4_2_0.h" +#include "cam_jpeg_enc_580_hw_info_ver_4_2_0.h" #include "camera_main.h" static int cam_jpeg_enc_register_cpas(struct cam_hw_soc_info *soc_info, @@ -239,6 +241,14 @@ static const struct of_device_id cam_jpeg_enc_dt_match[] = { .compatible = "qcom,cam_jpeg_enc", .data = &cam_jpeg_enc_hw_info, }, + { + .compatible = "qcom,cam_jpeg_enc_165", + .data = &cam_jpeg_enc_165_hw_info, + }, + { + .compatible = "qcom,cam_jpeg_enc_580", + .data = &cam_jpeg_enc_580_hw_info, + }, {} }; MODULE_DEVICE_TABLE(of, cam_jpeg_enc_dt_match);